Files
gio/text/shaper.go
T
Elias Naur 481cca5781 text: use the first registered font as the default in Shaper
Before this change, the default font was the one registered with an empty
Typeface.

We're about to use the correct names for fonts, so change Shaper to
fallback to the first registered typeface instead.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2019-10-13 18:23:30 +02:00

112 lines
2.2 KiB
Go

// SPDX-License-Identifier: Unlicense OR MIT
package text
import (
"gioui.org/op/paint"
"gioui.org/unit"
"golang.org/x/image/math/fixed"
)
// Shaper implements layout and shaping of text and a cache of
// computed results.
//
// Specify the default and fallback font by calling Register with the
// empty Font.
type Shaper struct {
def Typeface
faces map[Font]*face
}
type face struct {
face Face
layoutCache layoutCache
pathCache pathCache
}
func (s *Shaper) Register(font Font, tf Face) {
if s.faces == nil {
s.def = font.Typeface
s.faces = make(map[Font]*face)
}
// Treat all font sizes equally.
font.Size = unit.Value{}
if font.Weight == 0 {
font.Weight = Normal
}
s.faces[font] = &face{
face: tf,
}
}
func (s *Shaper) Layout(c unit.Converter, font Font, str string, opts LayoutOptions) *Layout {
tf := s.faceForFont(font)
return tf.layout(fixed.I(c.Px(font.Size)), str, opts)
}
func (s *Shaper) Shape(c unit.Converter, font Font, str String) paint.ClipOp {
tf := s.faceForFont(font)
return tf.shape(fixed.I(c.Px(font.Size)), str)
}
func (s *Shaper) faceForStyle(font Font) *face {
tf := s.faces[font]
if tf == nil {
font := font
font.Weight = Normal
tf = s.faces[font]
}
if tf == nil {
font := font
font.Style = Regular
tf = s.faces[font]
}
if tf == nil {
font := font
font.Style = Regular
font.Weight = Normal
tf = s.faces[font]
}
return tf
}
func (s *Shaper) faceForFont(font Font) *face {
font.Size = unit.Value{}
tf := s.faceForStyle(font)
if tf == nil {
font.Typeface = s.def
tf = s.faceForStyle(font)
}
if tf == nil {
panic("no default typeface defined")
}
return tf
}
func (t *face) layout(ppem fixed.Int26_6, str string, opts LayoutOptions) *Layout {
lk := layoutKey{
ppem: ppem,
str: str,
opts: opts,
}
if l, ok := t.layoutCache.Get(lk); ok {
return l
}
l := t.face.Layout(ppem, str, opts)
t.layoutCache.Put(lk, l)
return l
}
func (t *face) shape(ppem fixed.Int26_6, str String) paint.ClipOp {
pk := pathKey{
ppem: ppem,
str: str.String,
}
if clip, ok := t.pathCache.Get(pk); ok {
return clip
}
clip := t.face.Shape(ppem, str)
t.pathCache.Put(pk, clip)
return clip
}