mirror of
https://git.sr.ht/~eliasnaur/gio
synced 2026-07-01 07:35:40 +00:00
481cca5781
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>
112 lines
2.2 KiB
Go
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
|
|
}
|