mirror of
https://git.sr.ht/~eliasnaur/gio
synced 2026-07-06 09:55:40 +00:00
font/opentype: make reusing font.Face efficient and safe
This commit updates the internal representation of a font to separate the threadsafe and non-threadsafe operations in a way that enures font.Faces can be shared by all text shapers in an application. This should ensure that applications only need to parse fonts a single time, saving a great deal of memory for applications that open many windows (which each need a different text shaper). Signed-off-by: Chris Waldon <christopher.waldon.dev@gmail.com>
This commit is contained in:
@@ -22,9 +22,11 @@ import (
|
|||||||
"github.com/go-text/typesetting/opentype/loader"
|
"github.com/go-text/typesetting/opentype/loader"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Face is a shapeable representation of a font.
|
// Face is a thread-safe representation of a loaded font. For efficiency, applications
|
||||||
|
// should construct a face for any given font file once, reusing it across different
|
||||||
|
// text shapers.
|
||||||
type Face struct {
|
type Face struct {
|
||||||
face font.Face
|
face font.Font
|
||||||
aspect metadata.Aspect
|
aspect metadata.Aspect
|
||||||
family string
|
family string
|
||||||
variant string
|
variant string
|
||||||
@@ -36,12 +38,12 @@ func Parse(src []byte) (Face, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return Face{}, err
|
return Face{}, err
|
||||||
}
|
}
|
||||||
face, aspect, family, variant, err := parseLoader(ld)
|
font, aspect, family, variant, err := parseLoader(ld)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return Face{}, fmt.Errorf("failed parsing truetype font: %w", err)
|
return Face{}, fmt.Errorf("failed parsing truetype font: %w", err)
|
||||||
}
|
}
|
||||||
return Face{
|
return Face{
|
||||||
face: face,
|
face: font,
|
||||||
aspect: aspect,
|
aspect: aspect,
|
||||||
family: family,
|
family: family,
|
||||||
variant: variant,
|
variant: variant,
|
||||||
@@ -81,7 +83,7 @@ func ParseCollection(src []byte) ([]giofont.FontFace, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// parseLoader parses the contents of the loader into a face and its metadata.
|
// parseLoader parses the contents of the loader into a face and its metadata.
|
||||||
func parseLoader(ld *loader.Loader) (_ font.Face, _ metadata.Aspect, family, variant string, _ error) {
|
func parseLoader(ld *loader.Loader) (_ font.Font, _ metadata.Aspect, family, variant string, _ error) {
|
||||||
ft, err := fontapi.NewFont(ld)
|
ft, err := fontapi.NewFont(ld)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, metadata.Aspect{}, "", "", err
|
return nil, metadata.Aspect{}, "", "", err
|
||||||
@@ -90,11 +92,14 @@ func parseLoader(ld *loader.Loader) (_ font.Face, _ metadata.Aspect, family, var
|
|||||||
if data.IsMonospace {
|
if data.IsMonospace {
|
||||||
variant = "Mono"
|
variant = "Mono"
|
||||||
}
|
}
|
||||||
return &fontapi.Face{Font: ft}, data.Aspect, data.Family, variant, nil
|
return ft, data.Aspect, data.Family, variant, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Face returns a thread-unsafe wrapper for this Face suitable for use by a single shaper.
|
||||||
|
// Face many be invoked any number of times and is safe so long as each return value is
|
||||||
|
// only used by one goroutine.
|
||||||
func (f Face) Face() font.Face {
|
func (f Face) Face() font.Face {
|
||||||
return f.face
|
return &fontapi.Face{Font: f.face}
|
||||||
}
|
}
|
||||||
|
|
||||||
// FontFace returns a text.Font with populated font metadata for the
|
// FontFace returns a text.Font with populated font metadata for the
|
||||||
|
|||||||
Reference in New Issue
Block a user