diff --git a/app/ime_test.go b/app/ime_test.go index 20c14cd8..61399c48 100644 --- a/app/ime_test.go +++ b/app/ime_test.go @@ -9,6 +9,7 @@ import ( "testing" "unicode/utf8" + "gioui.org/font" "gioui.org/font/gofont" "gioui.org/io/key" "gioui.org/io/router" @@ -35,7 +36,7 @@ func FuzzIME(f *testing.F) { var r router.Router gtx := layout.Context{Ops: new(op.Ops), Queue: &r} // Layout once to register focus. - e.Layout(gtx, cache, text.Font{}, unit.Sp(10), op.CallOp{}, op.CallOp{}) + e.Layout(gtx, cache, font.Font{}, unit.Sp(10), op.CallOp{}, op.CallOp{}) r.Frame(gtx.Ops) var state editorState @@ -103,7 +104,7 @@ func FuzzIME(f *testing.F) { } } cmds = cmds[cmdLen:] - e.Layout(gtx, cache, text.Font{}, unit.Sp(10), op.CallOp{}, op.CallOp{}) + e.Layout(gtx, cache, font.Font{}, unit.Sp(10), op.CallOp{}, op.CallOp{}) r.Frame(gtx.Ops) newState := r.EditorState() // We don't track caret position. diff --git a/app/window.go b/app/window.go index dfbba118..69704083 100644 --- a/app/window.go +++ b/app/window.go @@ -14,6 +14,7 @@ import ( "unicode/utf8" "gioui.org/f32" + "gioui.org/font" "gioui.org/font/opentype" "gioui.org/gpu" "gioui.org/internal/ops" @@ -25,7 +26,6 @@ import ( "gioui.org/io/system" "gioui.org/layout" "gioui.org/op" - "gioui.org/text" "gioui.org/unit" "gioui.org/widget" "gioui.org/widget/material" @@ -143,7 +143,7 @@ func NewWindow(options ...Option) *Window { // Measure decoration height. deco := new(widget.Decorations) face, _ := opentype.Parse(goregular.TTF) - theme := material.NewTheme([]text.FontFace{{Font: text.Font{Typeface: "Go"}, Face: face}}) + theme := material.NewTheme([]font.FontFace{{Font: font.Font{Typeface: "Go"}, Face: face}}) decoStyle := material.Decorations(theme, deco, 0, "") gtx := layout.Context{ Ops: new(op.Ops), diff --git a/font/font.go b/font/font.go new file mode 100644 index 00000000..9d00f35b --- /dev/null +++ b/font/font.go @@ -0,0 +1,94 @@ +/* +Package font provides type describing font faces attributes. +*/ +package font + +import "github.com/go-text/typesetting/font" + +// A FontFace is a Font and a matching Face. +type FontFace struct { + Font Font + Face Face +} + +// Style is the font style. +type Style int + +// Weight is a font weight, in CSS units subtracted 400 so the zero value +// is normal text weight. +type Weight int + +// Font specify a particular typeface variant, style and weight. +type Font struct { + Typeface Typeface + Variant Variant + Style Style + // Weight is the text weight. If zero, Normal is used instead. + Weight Weight +} + +// Face is an opaque handle to a typeface. The concrete implementation depends +// upon the kind of font and shaper in use. +type Face interface { + Face() font.Face +} + +// Typeface identifies a particular typeface design. The empty +// string denotes the default typeface. +type Typeface string + +// Variant denotes a typeface variant such as "Mono" or "Smallcaps". +type Variant string + +const ( + Regular Style = iota + Italic +) + +const ( + Thin Weight = -300 + ExtraLight Weight = -200 + Light Weight = -100 + Normal Weight = 0 + Medium Weight = 100 + SemiBold Weight = 200 + Bold Weight = 300 + ExtraBold Weight = 400 + Black Weight = 500 +) + +func (s Style) String() string { + switch s { + case Regular: + return "Regular" + case Italic: + return "Italic" + default: + panic("invalid Style") + } +} + +func (w Weight) String() string { + switch w { + case Thin: + return "Thin" + case ExtraLight: + return "ExtraLight" + case Light: + return "Light" + case Normal: + return "Normal" + case Medium: + return "Medium" + case SemiBold: + return "SemiBold" + case Bold: + return "Bold" + case ExtraBold: + return "ExtraBold" + case Black: + return "Black" + default: + panic("invalid Weight") + } +} diff --git a/font/gofont/gofont.go b/font/gofont/gofont.go index a06efeb8..1139399a 100644 --- a/font/gofont/gofont.go +++ b/font/gofont/gofont.go @@ -24,29 +24,29 @@ import ( "golang.org/x/image/font/gofont/gosmallcaps" "golang.org/x/image/font/gofont/gosmallcapsitalic" + "gioui.org/font" "gioui.org/font/opentype" - "gioui.org/text" ) var ( once sync.Once - collection []text.FontFace + collection []font.FontFace ) -func Collection() []text.FontFace { +func Collection() []font.FontFace { once.Do(func() { - register(text.Font{}, goregular.TTF) - register(text.Font{Style: text.Italic}, goitalic.TTF) - register(text.Font{Weight: text.Bold}, gobold.TTF) - register(text.Font{Style: text.Italic, Weight: text.Bold}, gobolditalic.TTF) - register(text.Font{Weight: text.Medium}, gomedium.TTF) - register(text.Font{Weight: text.Medium, Style: text.Italic}, gomediumitalic.TTF) - register(text.Font{Variant: "Mono"}, gomono.TTF) - register(text.Font{Variant: "Mono", Weight: text.Bold}, gomonobold.TTF) - register(text.Font{Variant: "Mono", Weight: text.Bold, Style: text.Italic}, gomonobolditalic.TTF) - register(text.Font{Variant: "Mono", Style: text.Italic}, gomonoitalic.TTF) - register(text.Font{Variant: "Smallcaps"}, gosmallcaps.TTF) - register(text.Font{Variant: "Smallcaps", Style: text.Italic}, gosmallcapsitalic.TTF) + register(font.Font{}, goregular.TTF) + register(font.Font{Style: font.Italic}, goitalic.TTF) + register(font.Font{Weight: font.Bold}, gobold.TTF) + register(font.Font{Style: font.Italic, Weight: font.Bold}, gobolditalic.TTF) + register(font.Font{Weight: font.Medium}, gomedium.TTF) + register(font.Font{Weight: font.Medium, Style: font.Italic}, gomediumitalic.TTF) + register(font.Font{Variant: "Mono"}, gomono.TTF) + register(font.Font{Variant: "Mono", Weight: font.Bold}, gomonobold.TTF) + register(font.Font{Variant: "Mono", Weight: font.Bold, Style: font.Italic}, gomonobolditalic.TTF) + register(font.Font{Variant: "Mono", Style: font.Italic}, gomonoitalic.TTF) + register(font.Font{Variant: "Smallcaps"}, gosmallcaps.TTF) + register(font.Font{Variant: "Smallcaps", Style: font.Italic}, gosmallcapsitalic.TTF) // Ensure that any outside appends will not reuse the backing store. n := len(collection) collection = collection[:n:n] @@ -54,11 +54,11 @@ func Collection() []text.FontFace { return collection } -func register(fnt text.Font, ttf []byte) { +func register(fnt font.Font, ttf []byte) { face, err := opentype.Parse(ttf) if err != nil { panic(fmt.Errorf("failed to parse font: %v", err)) } fnt.Typeface = "Go" - collection = append(collection, text.FontFace{Font: fnt, Face: face}) + collection = append(collection, font.FontFace{Font: fnt, Face: face}) } diff --git a/font/opentype/opentype.go b/font/opentype/opentype.go index 6287d026..43c8335a 100644 --- a/font/opentype/opentype.go +++ b/font/opentype/opentype.go @@ -15,23 +15,133 @@ import ( "fmt" _ "image/png" + giofont "gioui.org/font" "github.com/go-text/typesetting/font" + fontapi "github.com/go-text/typesetting/opentype/api/font" + "github.com/go-text/typesetting/opentype/api/metadata" + "github.com/go-text/typesetting/opentype/loader" ) // Face is a shapeable representation of a font. type Face struct { - face font.Face + face font.Face + aspect metadata.Aspect + family string + variant string } // Parse constructs a Face from source bytes. func Parse(src []byte) (Face, error) { - face, err := font.ParseTTF(bytes.NewReader(src)) + ld, err := loader.NewLoader(bytes.NewReader(src)) + if err != nil { + return Face{}, err + } + face, aspect, family, variant, err := parseLoader(ld) if err != nil { return Face{}, fmt.Errorf("failed parsing truetype font: %w", err) } - return Face{face: face}, nil + return Face{ + face: face, + aspect: aspect, + family: family, + variant: variant, + }, nil +} + +// ParseCollection parse an Opentype font file, with support for collections. +// Single font files are supported, returning a slice with length 1. +// The returned fonts are automatically wrapped in a text.FontFace with +// inferred font metadata. +// BUG(whereswaldon): the only Variant that can be detected automatically is +// "Mono". +func ParseCollection(src []byte) ([]giofont.FontFace, error) { + lds, err := loader.NewLoaders(bytes.NewReader(src)) + if err != nil { + return nil, err + } + out := make([]giofont.FontFace, len(lds)) + for i, ld := range lds { + face, aspect, family, variant, err := parseLoader(ld) + if err != nil { + return nil, fmt.Errorf("reading font %d of collection: %s", i, err) + } + ff := Face{ + face: face, + aspect: aspect, + family: family, + variant: variant, + } + out[i] = giofont.FontFace{ + Face: ff, + Font: ff.Font(), + } + } + + return out, nil +} + +// 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) { + ft, err := fontapi.NewFont(ld) + if err != nil { + return nil, metadata.Aspect{}, "", "", err + } + data := metadata.Metadata(ld) + if data.IsMonospace { + variant = "Mono" + } + return &fontapi.Face{Font: ft}, data.Aspect, data.Family, variant, nil } func (f Face) Face() font.Face { return f.face } + +// FontFace returns a text.Font with populated font metadata for the +// font. +// BUG(whereswaldon): the only Variant that can be detected automatically is +// "Mono". +func (f Face) Font() giofont.Font { + return giofont.Font{ + Typeface: giofont.Typeface(f.family), + Style: f.style(), + Weight: f.weight(), + Variant: giofont.Variant(f.variant), + } +} + +func (f Face) style() giofont.Style { + switch f.aspect.Style { + case metadata.StyleItalic: + return giofont.Italic + case metadata.StyleNormal: + fallthrough + default: + return giofont.Regular + } +} + +func (f Face) weight() giofont.Weight { + switch f.aspect.Weight { + case metadata.WeightThin: + return giofont.Thin + case metadata.WeightExtraLight: + return giofont.ExtraLight + case metadata.WeightLight: + return giofont.Light + case metadata.WeightNormal: + return giofont.Normal + case metadata.WeightMedium: + return giofont.Medium + case metadata.WeightSemibold: + return giofont.SemiBold + case metadata.WeightBold: + return giofont.Bold + case metadata.WeightExtraBold: + return giofont.ExtraBold + case metadata.WeightBlack: + return giofont.Black + default: + return giofont.Normal + } +} diff --git a/go.mod b/go.mod index 95bc680e..16a1fc30 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( eliasnaur.com/font v0.0.0-20230308162249-dd43949cb42d gioui.org/cpu v0.0.0-20210817075930-8d6a761490d2 gioui.org/shader v1.0.6 - github.com/go-text/typesetting v0.0.0-20230405155246-bf9c697c6e16 + github.com/go-text/typesetting v0.0.0-20230413204129-b4f0492bf7ae golang.org/x/exp v0.0.0-20221012211006-4de253d81b95 golang.org/x/exp/shiny v0.0.0-20220827204233-334a2380cb91 golang.org/x/image v0.5.0 diff --git a/go.sum b/go.sum index b5847017..dcc58bea 100644 --- a/go.sum +++ b/go.sum @@ -5,9 +5,9 @@ gioui.org/cpu v0.0.0-20210817075930-8d6a761490d2 h1:AGDDxsJE1RpcXTAxPG2B4jrwVUJG gioui.org/cpu v0.0.0-20210817075930-8d6a761490d2/go.mod h1:A8M0Cn5o+vY5LTMlnRoK3O5kG+rH0kWfJjeKd9QpBmQ= gioui.org/shader v1.0.6 h1:cvZmU+eODFR2545X+/8XucgZdTtEjR3QWW6W65b0q5Y= gioui.org/shader v1.0.6/go.mod h1:mWdiME581d/kV7/iEhLmUgUK5iZ09XR5XpduXzbePVM= -github.com/go-text/typesetting v0.0.0-20230405155246-bf9c697c6e16 h1:DvHeDNqK8cxdZ7C6y88pt3uE7euZH7/LluzyfnUfH/Q= -github.com/go-text/typesetting v0.0.0-20230405155246-bf9c697c6e16/go.mod h1:zvWM81wAVW6QfVDI6yxfbCuoLnobSYTuMsrXU/u11y8= -github.com/go-text/typesetting-utils v0.0.0-20230326210548-458646692de6 h1:zAAA1U4ykFwqPbcj6YDxvq3F2g0wc/ngPfLJjkR/8zs= +github.com/go-text/typesetting v0.0.0-20230413204129-b4f0492bf7ae h1:LCcaQgYrnS+sx9Tc3oGUvbRBRt+5oFnKWakaxeAvNVI= +github.com/go-text/typesetting v0.0.0-20230413204129-b4f0492bf7ae/go.mod h1:KmrpWuSMFcO2yjmyhGpnBGQHSKAoEgMTSSzvLDzCuEA= +github.com/go-text/typesetting-utils v0.0.0-20230412163830-89e4bcfa3ecc h1:9Kf84pnrmmjdRzZIkomfjowmGUhHs20jkrWYw/I6CYc= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= diff --git a/text/gotext.go b/text/gotext.go index c78ce664..4baed57b 100644 --- a/text/gotext.go +++ b/text/gotext.go @@ -18,6 +18,7 @@ import ( "golang.org/x/text/unicode/bidi" "gioui.org/f32" + giofont "gioui.org/font" "gioui.org/io/system" "gioui.org/op" "gioui.org/op/clip" @@ -150,24 +151,24 @@ type runLayout struct { // faceOrderer chooses the order in which faces should be applied to text. type faceOrderer struct { - def Font + def giofont.Font faceScratch []font.Face - fontDefaultOrder map[Font]int - defaultOrderedFonts []Font - faces map[Font]font.Face + fontDefaultOrder map[giofont.Font]int + defaultOrderedFonts []giofont.Font + faces map[giofont.Font]font.Face faceToIndex map[font.Face]int - fonts []Font + fonts []giofont.Font } -func (f *faceOrderer) insert(fnt Font, face font.Face) { +func (f *faceOrderer) insert(fnt giofont.Font, face font.Face) { if len(f.fonts) == 0 { f.def = fnt } if f.fontDefaultOrder == nil { - f.fontDefaultOrder = make(map[Font]int) + f.fontDefaultOrder = make(map[giofont.Font]int) } if f.faces == nil { - f.faces = make(map[Font]font.Face) + f.faces = make(map[giofont.Font]font.Face) f.faceToIndex = make(map[font.Face]int) } f.fontDefaultOrder[fnt] = len(f.faceScratch) @@ -198,7 +199,7 @@ func (c *faceOrderer) faceFor(idx int) font.Face { // TODO(whereswaldon): this function could sort all faces by appropriateness for the // given font characteristics. This would ensure that (if possible) text using a // fallback font would select similar weights and emphases to the primary font. -func (c *faceOrderer) sortedFacesForStyle(font Font) []font.Face { +func (c *faceOrderer) sortedFacesForStyle(font giofont.Font) []font.Face { c.resetFontOrder() primary, ok := c.fontForStyle(font) if !ok { @@ -213,11 +214,11 @@ func (c *faceOrderer) sortedFacesForStyle(font Font) []font.Face { // fontForStyle returns the closest existing font to the requested font within the // same typeface. -func (c *faceOrderer) fontForStyle(font Font) (Font, bool) { +func (c *faceOrderer) fontForStyle(font giofont.Font) (giofont.Font, bool) { if closest, ok := closestFont(font, c.fonts); ok { return closest, true } - font.Style = Regular + font.Style = giofont.Regular if closest, ok := closestFont(font, c.fonts); ok { return closest, true } @@ -226,7 +227,7 @@ func (c *faceOrderer) fontForStyle(font Font) (Font, bool) { // faces returns a slice of faces with primary as the first element and // the remaining faces ordered by insertion order. -func (f *faceOrderer) sorted(primary Font) []font.Face { +func (f *faceOrderer) sorted(primary giofont.Font) []font.Face { // If we find primary, put it first, and omit it from the below sort. lowest := 0 for i := range f.fonts { @@ -875,9 +876,9 @@ func computeVisualOrder(l *line) { // closestFont returns the closest Font in available by weight. // In case of equality the lighter weight will be returned. -func closestFont(lookup Font, available []Font) (Font, bool) { +func closestFont(lookup giofont.Font, available []giofont.Font) (giofont.Font, bool) { found := false - var match Font + var match giofont.Font for _, cf := range available { if cf == lookup { return lookup, true @@ -902,7 +903,7 @@ func closestFont(lookup Font, available []Font) (Font, bool) { } // weightDistance returns the distance value between two font weights. -func weightDistance(wa Weight, wb Weight) int { +func weightDistance(wa giofont.Weight, wb giofont.Weight) int { // Avoid dealing with negative Weight values. a := int(wa) + 400 b := int(wb) + 400 diff --git a/text/gotext_test.go b/text/gotext_test.go index 98fd8d80..5b633361 100644 --- a/text/gotext_test.go +++ b/text/gotext_test.go @@ -10,6 +10,7 @@ import ( "golang.org/x/image/font/gofont/goregular" "golang.org/x/image/math/fixed" + giofont "gioui.org/font" "gioui.org/font/opentype" "gioui.org/io/system" ) @@ -24,7 +25,7 @@ var arabic = system.Locale{ Direction: system.RTL, } -func testShaper(faces ...Face) *shaperImpl { +func testShaper(faces ...giofont.Face) *shaperImpl { shaper := shaperImpl{} for _, face := range faces { shaper.Load(FontFace{Face: face}) @@ -268,12 +269,12 @@ func makeTestText(shaper *shaperImpl, primaryDir system.TextDirection, fontSize, rtlSource = string(complexRunes[:runeLimit]) } } - simpleText, _ := shaper.shapeAndWrapText(shaper.orderer.sortedFacesForStyle(Font{}), Parameters{ + simpleText, _ := shaper.shapeAndWrapText(shaper.orderer.sortedFacesForStyle(giofont.Font{}), Parameters{ PxPerEm: fixed.I(fontSize), MaxWidth: lineWidth, Locale: locale, }, []rune(simpleSource)) - complexText, _ := shaper.shapeAndWrapText(shaper.orderer.sortedFacesForStyle(Font{}), Parameters{ + complexText, _ := shaper.shapeAndWrapText(shaper.orderer.sortedFacesForStyle(giofont.Font{}), Parameters{ PxPerEm: fixed.I(fontSize), MaxWidth: lineWidth, Locale: locale, @@ -642,33 +643,33 @@ func TestTextAppend(t *testing.T) { func TestClosestFontByWeight(t *testing.T) { const ( - testTF1 Typeface = "MockFace" - testTF2 Typeface = "TestFace" - testTF3 Typeface = "AnotherFace" + testTF1 giofont.Typeface = "MockFace" + testTF2 giofont.Typeface = "TestFace" + testTF3 giofont.Typeface = "AnotherFace" ) - fonts := []Font{ - {Typeface: testTF1, Style: Regular, Weight: Normal}, - {Typeface: testTF1, Style: Regular, Weight: Light}, - {Typeface: testTF1, Style: Regular, Weight: Bold}, - {Typeface: testTF1, Style: Italic, Weight: Thin}, + fonts := []giofont.Font{ + {Typeface: testTF1, Style: giofont.Regular, Weight: giofont.Normal}, + {Typeface: testTF1, Style: giofont.Regular, Weight: giofont.Light}, + {Typeface: testTF1, Style: giofont.Regular, Weight: giofont.Bold}, + {Typeface: testTF1, Style: giofont.Italic, Weight: giofont.Thin}, } weightOnlyTests := []struct { - Lookup Weight - Expected Weight + Lookup giofont.Weight + Expected giofont.Weight }{ // Test for existing weights. - {Lookup: Normal, Expected: Normal}, - {Lookup: Light, Expected: Light}, - {Lookup: Bold, Expected: Bold}, + {Lookup: giofont.Normal, Expected: giofont.Normal}, + {Lookup: giofont.Light, Expected: giofont.Light}, + {Lookup: giofont.Bold, Expected: giofont.Bold}, // Test for missing weights. - {Lookup: Thin, Expected: Light}, - {Lookup: ExtraLight, Expected: Light}, - {Lookup: Medium, Expected: Normal}, - {Lookup: SemiBold, Expected: Bold}, - {Lookup: ExtraBlack, Expected: Bold}, + {Lookup: giofont.Thin, Expected: giofont.Light}, + {Lookup: giofont.ExtraLight, Expected: giofont.Light}, + {Lookup: giofont.Medium, Expected: giofont.Normal}, + {Lookup: giofont.SemiBold, Expected: giofont.Bold}, + {Lookup: giofont.ExtraBold, Expected: giofont.Bold}, } for _, test := range weightOnlyTests { - got, ok := closestFont(Font{Typeface: testTF1, Weight: test.Lookup}, fonts) + got, ok := closestFont(giofont.Font{Typeface: testTF1, Weight: test.Lookup}, fonts) if !ok { t.Errorf("expected closest font for %v to exist", test.Lookup) } @@ -676,49 +677,49 @@ func TestClosestFontByWeight(t *testing.T) { t.Errorf("got weight %v, expected %v", got.Weight, test.Expected) } } - fonts = []Font{ - {Typeface: testTF1, Style: Regular, Weight: Light}, - {Typeface: testTF1, Style: Regular, Weight: Bold}, - {Typeface: testTF1, Style: Italic, Weight: Normal}, - {Typeface: testTF3, Style: Italic, Weight: Bold}, + fonts = []giofont.Font{ + {Typeface: testTF1, Style: giofont.Regular, Weight: giofont.Light}, + {Typeface: testTF1, Style: giofont.Regular, Weight: giofont.Bold}, + {Typeface: testTF1, Style: giofont.Italic, Weight: giofont.Normal}, + {Typeface: testTF3, Style: giofont.Italic, Weight: giofont.Bold}, } otherTests := []struct { - Lookup Font - Expected Font + Lookup giofont.Font + Expected giofont.Font ExpectedToFail bool }{ // Test for existing fonts. { - Lookup: Font{Typeface: testTF1, Weight: Light}, - Expected: Font{Typeface: testTF1, Style: Regular, Weight: Light}, + Lookup: giofont.Font{Typeface: testTF1, Weight: giofont.Light}, + Expected: giofont.Font{Typeface: testTF1, Style: giofont.Regular, Weight: giofont.Light}, }, { - Lookup: Font{Typeface: testTF1, Style: Italic, Weight: Normal}, - Expected: Font{Typeface: testTF1, Style: Italic, Weight: Normal}, + Lookup: giofont.Font{Typeface: testTF1, Style: giofont.Italic, Weight: giofont.Normal}, + Expected: giofont.Font{Typeface: testTF1, Style: giofont.Italic, Weight: giofont.Normal}, }, // Test for missing fonts. { - Lookup: Font{Typeface: testTF1, Weight: Normal}, - Expected: Font{Typeface: testTF1, Style: Regular, Weight: Light}, + Lookup: giofont.Font{Typeface: testTF1, Weight: giofont.Normal}, + Expected: giofont.Font{Typeface: testTF1, Style: giofont.Regular, Weight: giofont.Light}, }, { - Lookup: Font{Typeface: testTF3, Style: Italic, Weight: Normal}, - Expected: Font{Typeface: testTF3, Style: Italic, Weight: Bold}, + Lookup: giofont.Font{Typeface: testTF3, Style: giofont.Italic, Weight: giofont.Normal}, + Expected: giofont.Font{Typeface: testTF3, Style: giofont.Italic, Weight: giofont.Bold}, }, { - Lookup: Font{Typeface: testTF1, Style: Italic, Weight: Thin}, - Expected: Font{Typeface: testTF1, Style: Italic, Weight: Normal}, + Lookup: giofont.Font{Typeface: testTF1, Style: giofont.Italic, Weight: giofont.Thin}, + Expected: giofont.Font{Typeface: testTF1, Style: giofont.Italic, Weight: giofont.Normal}, }, { - Lookup: Font{Typeface: testTF1, Style: Italic, Weight: Bold}, - Expected: Font{Typeface: testTF1, Style: Italic, Weight: Normal}, + Lookup: giofont.Font{Typeface: testTF1, Style: giofont.Italic, Weight: giofont.Bold}, + Expected: giofont.Font{Typeface: testTF1, Style: giofont.Italic, Weight: giofont.Normal}, }, { - Lookup: Font{Typeface: testTF2, Weight: Normal}, + Lookup: giofont.Font{Typeface: testTF2, Weight: giofont.Normal}, ExpectedToFail: true, }, { - Lookup: Font{Typeface: testTF2, Style: Italic, Weight: Normal}, + Lookup: giofont.Font{Typeface: testTF2, Style: giofont.Italic, Weight: giofont.Normal}, ExpectedToFail: true, }, } diff --git a/text/lru.go b/text/lru.go index f8b7caf1..78200eac 100644 --- a/text/lru.go +++ b/text/lru.go @@ -7,6 +7,7 @@ import ( "hash/maphash" "image" + giofont "gioui.org/font" "gioui.org/io/system" "gioui.org/op" "gioui.org/op/clip" @@ -156,7 +157,7 @@ type layoutKey struct { str string truncator string locale system.Locale - font Font + font giofont.Font forceTruncate bool } diff --git a/text/shaper.go b/text/shaper.go index f82973e9..446e2250 100644 --- a/text/shaper.go +++ b/text/shaper.go @@ -9,6 +9,7 @@ import ( "strings" "unicode/utf8" + giofont "gioui.org/font" "gioui.org/io/system" "gioui.org/op" "gioui.org/op/clip" @@ -19,7 +20,7 @@ import ( // Parameters are static text shaping attributes applied to the entire shaped text. type Parameters struct { // Font describes the preferred typeface. - Font Font + Font giofont.Font // Alignment characterizes the positioning of text within the line. It does not directly // impact shaping, but is provided in order to allow efficient offset computation. Alignment Alignment @@ -44,11 +45,7 @@ type Parameters struct { forceTruncate bool } -// A FontFace is a Font and a matching Face. -type FontFace struct { - Font Font - Face Face -} +type FontFace = giofont.FontFace // Glyph describes a shaped font glyph. Many fields are distances relative // to the "dot", which is a point on the baseline (the line upon which glyphs diff --git a/text/text.go b/text/text.go index b6d7cac0..98e94667 100644 --- a/text/text.go +++ b/text/text.go @@ -6,39 +6,9 @@ import ( "fmt" "gioui.org/io/system" - "github.com/go-text/typesetting/font" "golang.org/x/image/math/fixed" ) -// Style is the font style. -type Style int - -// Weight is a font weight, in CSS units subtracted 400 so the zero value -// is normal text weight. -type Weight int - -// Font specify a particular typeface variant, style and weight. -type Font struct { - Typeface Typeface - Variant Variant - Style Style - // Weight is the text weight. If zero, Normal is used instead. - Weight Weight -} - -// Face is an opaque handle to a typeface. The concrete implementation depends -// upon the kind of font and shaper in use. -type Face interface { - Face() font.Face -} - -// Typeface identifies a particular typeface design. The empty -// string denotes the default typeface. -type Typeface string - -// Variant denotes a typeface variant such as "Mono" or "Smallcaps". -type Variant string - type Alignment uint8 const ( @@ -47,31 +17,6 @@ const ( Middle ) -const ( - Regular Style = iota - Italic -) - -const ( - Thin Weight = -300 - ExtraLight Weight = -200 - Light Weight = -100 - Normal Weight = 0 - Medium Weight = 100 - SemiBold Weight = 200 - Bold Weight = 300 - ExtraBold Weight = 400 - Black Weight = 500 - - Hairline = Thin - UltraLight = ExtraLight - DemiBold = SemiBold - UltraBold = ExtraBold - Heavy = Black - ExtraBlack = Black + 50 - UltraBlack = ExtraBlack -) - func (a Alignment) String() string { switch a { case Start: @@ -109,41 +54,3 @@ func (a Alignment) Align(dir system.TextDirection, width fixed.Int26_6, maxWidth panic(fmt.Errorf("unknown alignment %v", a)) } } - -func (s Style) String() string { - switch s { - case Regular: - return "Regular" - case Italic: - return "Italic" - default: - panic("invalid Style") - } -} - -func (w Weight) String() string { - switch w { - case Thin: - return "Thin" - case ExtraLight: - return "ExtraLight" - case Light: - return "Light" - case Normal: - return "Normal" - case Medium: - return "Medium" - case SemiBold: - return "SemiBold" - case Bold: - return "Bold" - case ExtraBold: - return "ExtraBold" - case Black: - return "Black" - case ExtraBlack: - return "ExtraBlack" - default: - panic("invalid Weight") - } -} diff --git a/widget/editor.go b/widget/editor.go index 89fd9af7..1211a04a 100644 --- a/widget/editor.go +++ b/widget/editor.go @@ -13,6 +13,7 @@ import ( "unicode/utf8" "gioui.org/f32" + "gioui.org/font" "gioui.org/gesture" "gioui.org/io/clipboard" "gioui.org/io/event" @@ -508,7 +509,7 @@ func (e *Editor) initBuffer() { // Layout lays out the editor using the provided textMaterial as the paint material // for the text glyphs+caret and the selectMaterial as the paint material for the // selection rectangle. -func (e *Editor) Layout(gtx layout.Context, lt *text.Shaper, font text.Font, size unit.Sp, textMaterial, selectMaterial op.CallOp) layout.Dimensions { +func (e *Editor) Layout(gtx layout.Context, lt *text.Shaper, font font.Font, size unit.Sp, textMaterial, selectMaterial op.CallOp) layout.Dimensions { e.initBuffer() e.text.Update(gtx, lt, font, size, e.processEvents) diff --git a/widget/editor_test.go b/widget/editor_test.go index a896c7c4..016e410d 100644 --- a/widget/editor_test.go +++ b/widget/editor_test.go @@ -17,6 +17,7 @@ import ( nsareg "eliasnaur.com/font/noto/sans/arabic/regular" "eliasnaur.com/font/roboto/robotoregular" "gioui.org/f32" + "gioui.org/font" "gioui.org/font/gofont" "gioui.org/font/opentype" "gioui.org/io/event" @@ -109,7 +110,7 @@ func TestEditorReadOnly(t *testing.T) { } cache := text.NewShaper(gofont.Collection()) fontSize := unit.Sp(10) - font := text.Font{} + font := font.Font{} e := new(Editor) e.ReadOnly = true e.SetText("The quick brown fox jumps over the lazy dog. We just need a few lines of text in the editor so that it can adequately test a few different modes of selection. The quick brown fox jumps over the lazy dog. We just need a few lines of text in the editor so that it can adequately test a few different modes of selection.") @@ -188,7 +189,7 @@ func TestEditorConfigurations(t *testing.T) { } cache := text.NewShaper(gofont.Collection()) fontSize := unit.Sp(10) - font := text.Font{} + font := font.Font{} sentence := "\n\n\n\n\n\n\n\n\n\n\n\nthe quick brown fox jumps over the lazy dog" runes := len([]rune(sentence)) @@ -242,7 +243,7 @@ func TestEditor(t *testing.T) { } cache := text.NewShaper(gofont.Collection()) fontSize := unit.Sp(10) - font := text.Font{} + font := font.Font{} // Regression test for bad in-cluster rune offset math. e.SetText("æbc") @@ -336,9 +337,9 @@ var arabic = system.Locale{ Direction: system.RTL, } -var arabicCollection = func() []text.FontFace { +var arabicCollection = func() []font.FontFace { parsed, _ := opentype.Parse(nsareg.TTF) - return []text.FontFace{{Font: text.Font{}, Face: parsed}} + return []font.FontFace{{Font: font.Font{}, Face: parsed}} }() func TestEditorRTL(t *testing.T) { @@ -350,7 +351,7 @@ func TestEditorRTL(t *testing.T) { } cache := text.NewShaper(arabicCollection) fontSize := unit.Sp(10) - font := text.Font{} + font := font.Font{} e.SetCaret(0, 0) // shouldn't panic assertCaret(t, e, 0, 0, 0) @@ -417,16 +418,16 @@ func TestEditorLigature(t *testing.T) { if err != nil { t.Skipf("failed parsing test font: %v", err) } - cache := text.NewShaper([]text.FontFace{ + cache := text.NewShaper([]font.FontFace{ { - Font: text.Font{ + Font: font.Font{ Typeface: "Roboto", }, Face: face, }, }) fontSize := unit.Sp(10) - font := text.Font{} + font := font.Font{} /* In this font, the following rune sequences form ligatures: @@ -540,7 +541,7 @@ func TestEditorDimensions(t *testing.T) { } cache := text.NewShaper(gofont.Collection()) fontSize := unit.Sp(10) - font := text.Font{} + font := font.Font{} dims := e.Layout(gtx, cache, font, fontSize, op.CallOp{}, op.CallOp{}) if dims.Size.X == 0 { t.Errorf("EditEvent was not reflected in Editor width") @@ -587,7 +588,7 @@ func TestEditorCaretConsistency(t *testing.T) { } cache := text.NewShaper(gofont.Collection()) fontSize := unit.Sp(10) - font := text.Font{} + font := font.Font{} for _, a := range []text.Alignment{text.Start, text.Middle, text.End} { e := &Editor{} e.Alignment = a @@ -679,7 +680,7 @@ func TestEditorMoveWord(t *testing.T) { } cache := text.NewShaper(gofont.Collection()) fontSize := unit.Sp(10) - font := text.Font{} + font := font.Font{} e.SetText(t) e.Layout(gtx, cache, font, fontSize, op.CallOp{}, op.CallOp{}) return e @@ -784,7 +785,7 @@ func TestEditorInsert(t *testing.T) { } cache := text.NewShaper(gofont.Collection()) fontSize := unit.Sp(10) - font := text.Font{} + font := font.Font{} e.SetText(t) e.Layout(gtx, cache, font, fontSize, op.CallOp{}, op.CallOp{}) return e @@ -874,7 +875,7 @@ func TestEditorDeleteWord(t *testing.T) { } cache := text.NewShaper(gofont.Collection()) fontSize := unit.Sp(10) - font := text.Font{} + font := font.Font{} e.SetText(t) e.Layout(gtx, cache, font, fontSize, op.CallOp{}, op.CallOp{}) return e @@ -927,7 +928,7 @@ g 2 4 6 8 g Locale: english, } cache := text.NewShaper(gofont.Collection()) - font := text.Font{} + font := font.Font{} fontSize := unit.Sp(10) var tim time.Duration @@ -1025,7 +1026,7 @@ func TestSelectMove(t *testing.T) { Locale: english, } cache := text.NewShaper(gofont.Collection()) - font := text.Font{} + font := font.Font{} fontSize := unit.Sp(10) // Layout once to populate e.lines and get focus. @@ -1114,7 +1115,7 @@ func TestEditor_MaxLen(t *testing.T) { } cache := text.NewShaper(gofont.Collection()) fontSize := unit.Sp(10) - font := text.Font{} + font := font.Font{} e.Layout(gtx, cache, font, fontSize, op.CallOp{}, op.CallOp{}) if got, want := e.Text(), "12345678"; got != want { @@ -1145,7 +1146,7 @@ func TestEditor_Filter(t *testing.T) { } cache := text.NewShaper(gofont.Collection()) fontSize := unit.Sp(10) - font := text.Font{} + font := font.Font{} e.Layout(gtx, cache, font, fontSize, op.CallOp{}, op.CallOp{}) if got, want := e.Text(), "12345678"; got != want { @@ -1169,7 +1170,7 @@ func TestEditor_Submit(t *testing.T) { } cache := text.NewShaper(gofont.Collection()) fontSize := unit.Sp(10) - font := text.Font{} + font := font.Font{} e.Layout(gtx, cache, font, fontSize, op.CallOp{}, op.CallOp{}) if got, want := e.Text(), "ab1"; got != want { diff --git a/widget/index_test.go b/widget/index_test.go index 532c6338..3d767652 100644 --- a/widget/index_test.go +++ b/widget/index_test.go @@ -6,6 +6,7 @@ import ( "testing" nsareg "eliasnaur.com/font/noto/sans/arabic/regular" + "gioui.org/font" "gioui.org/font/opentype" "gioui.org/text" "golang.org/x/image/font/gofont/goregular" @@ -19,13 +20,13 @@ func makePosTestText(fontSize, lineWidth int, alignOpposite bool) (source string ltrFace, _ := opentype.Parse(goregular.TTF) rtlFace, _ := opentype.Parse(nsareg.TTF) - shaper := text.NewShaper([]text.FontFace{ + shaper := text.NewShaper([]font.FontFace{ { - Font: text.Font{Typeface: "LTR"}, + Font: font.Font{Typeface: "LTR"}, Face: ltrFace, }, { - Font: text.Font{Typeface: "RTL"}, + Font: font.Font{Typeface: "RTL"}, Face: rtlFace, }, }) @@ -33,7 +34,7 @@ func makePosTestText(fontSize, lineWidth int, alignOpposite bool) (source string // changing scripts within the RTL). bidiSource := "The quick سماء שלום لا fox تمط שלום غير the lazy dog." ltrParams := text.Parameters{ - Font: text.Font{Typeface: "LTR"}, + Font: font.Font{Typeface: "LTR"}, PxPerEm: fixed.I(fontSize), MaxWidth: lineWidth, MinWidth: lineWidth, @@ -41,7 +42,7 @@ func makePosTestText(fontSize, lineWidth int, alignOpposite bool) (source string } rtlParams := text.Parameters{ Alignment: text.End, - Font: text.Font{Typeface: "RTL"}, + Font: font.Font{Typeface: "RTL"}, PxPerEm: fixed.I(fontSize), MaxWidth: lineWidth, MinWidth: lineWidth, @@ -68,12 +69,12 @@ func makeAccountingTestText(str string, fontSize, lineWidth int) (txt []text.Gly ltrFace, _ := opentype.Parse(goregular.TTF) rtlFace, _ := opentype.Parse(nsareg.TTF) - shaper := text.NewShaper([]text.FontFace{{ - Font: text.Font{Typeface: "LTR"}, + shaper := text.NewShaper([]font.FontFace{{ + Font: font.Font{Typeface: "LTR"}, Face: ltrFace, }, { - Font: text.Font{Typeface: "RTL"}, + Font: font.Font{Typeface: "RTL"}, Face: rtlFace, }, }) @@ -94,12 +95,12 @@ func getGlyphs(fontSize, minWidth, lineWidth int, align text.Alignment, str stri ltrFace, _ := opentype.Parse(goregular.TTF) rtlFace, _ := opentype.Parse(nsareg.TTF) - shaper := text.NewShaper([]text.FontFace{{ - Font: text.Font{Typeface: "LTR"}, + shaper := text.NewShaper([]font.FontFace{{ + Font: font.Font{Typeface: "LTR"}, Face: ltrFace, }, { - Font: text.Font{Typeface: "RTL"}, + Font: font.Font{Typeface: "RTL"}, Face: rtlFace, }, }) diff --git a/widget/label.go b/widget/label.go index 10af00bc..5d7eae85 100644 --- a/widget/label.go +++ b/widget/label.go @@ -6,6 +6,7 @@ import ( "image" "gioui.org/f32" + "gioui.org/font" "gioui.org/io/semantic" "gioui.org/layout" "gioui.org/op" @@ -30,7 +31,7 @@ type Label struct { } // Layout the label with the given shaper, font, size, text, and material. -func (l Label) Layout(gtx layout.Context, lt *text.Shaper, font text.Font, size unit.Sp, txt string, textMaterial op.CallOp) layout.Dimensions { +func (l Label) Layout(gtx layout.Context, lt *text.Shaper, font font.Font, size unit.Sp, txt string, textMaterial op.CallOp) layout.Dimensions { cs := gtx.Constraints textSize := fixed.I(gtx.Sp(size)) lt.LayoutString(text.Parameters{ diff --git a/widget/material/button.go b/widget/material/button.go index 8ef552ea..ecb15258 100644 --- a/widget/material/button.go +++ b/widget/material/button.go @@ -7,6 +7,7 @@ import ( "image/color" "math" + "gioui.org/font" "gioui.org/internal/f32color" "gioui.org/io/semantic" "gioui.org/layout" @@ -22,7 +23,7 @@ type ButtonStyle struct { Text string // Color is the text color. Color color.NRGBA - Font text.Font + Font font.Font TextSize unit.Sp Background color.NRGBA CornerRadius unit.Dp diff --git a/widget/material/checkable.go b/widget/material/checkable.go index 93fb0934..35115fa4 100644 --- a/widget/material/checkable.go +++ b/widget/material/checkable.go @@ -6,6 +6,7 @@ import ( "image" "image/color" + "gioui.org/font" "gioui.org/internal/f32color" "gioui.org/layout" "gioui.org/op" @@ -19,7 +20,7 @@ import ( type checkable struct { Label string Color color.NRGBA - Font text.Font + Font font.Font TextSize unit.Sp IconColor color.NRGBA Size unit.Dp diff --git a/widget/material/editor.go b/widget/material/editor.go index 3d75a0b0..57ca54c1 100644 --- a/widget/material/editor.go +++ b/widget/material/editor.go @@ -5,6 +5,7 @@ package material import ( "image/color" + "gioui.org/font" "gioui.org/internal/f32color" "gioui.org/layout" "gioui.org/op" @@ -15,7 +16,7 @@ import ( ) type EditorStyle struct { - Font text.Font + Font font.Font TextSize unit.Sp // Color is the text color. Color color.NRGBA diff --git a/widget/material/label.go b/widget/material/label.go index 434a2218..c606fe86 100644 --- a/widget/material/label.go +++ b/widget/material/label.go @@ -5,6 +5,7 @@ package material import ( "image/color" + "gioui.org/font" "gioui.org/internal/f32color" "gioui.org/layout" "gioui.org/op" @@ -19,7 +20,7 @@ import ( // the label will be non-interactive. type LabelStyle struct { // Face defines the text style. - Font text.Font + Font font.Font // Color is the text color. Color color.NRGBA // SelectionColor is the color of the background for selected text. @@ -47,13 +48,13 @@ type LabelStyle struct { func H1(th *Theme, txt string) LabelStyle { label := Label(th, th.TextSize*96.0/16.0, txt) - label.Font.Weight = text.Light + label.Font.Weight = font.Light return label } func H2(th *Theme, txt string) LabelStyle { label := Label(th, th.TextSize*60.0/16.0, txt) - label.Font.Weight = text.Light + label.Font.Weight = font.Light return label } @@ -71,7 +72,7 @@ func H5(th *Theme, txt string) LabelStyle { func H6(th *Theme, txt string) LabelStyle { label := Label(th, th.TextSize*20.0/16.0, txt) - label.Font.Weight = text.Medium + label.Font.Weight = font.Medium return label } @@ -81,7 +82,7 @@ func Subtitle1(th *Theme, txt string) LabelStyle { func Subtitle2(th *Theme, txt string) LabelStyle { label := Label(th, th.TextSize*14.0/16.0, txt) - label.Font.Weight = text.Medium + label.Font.Weight = font.Medium return label } diff --git a/widget/material/theme.go b/widget/material/theme.go index 350d995d..3e641c61 100644 --- a/widget/material/theme.go +++ b/widget/material/theme.go @@ -7,6 +7,7 @@ import ( "golang.org/x/exp/shiny/materialdesign/icons" + "gioui.org/font" "gioui.org/text" "gioui.org/unit" "gioui.org/widget" @@ -46,7 +47,7 @@ type Theme struct { FingerSize unit.Dp } -func NewTheme(fontCollection []text.FontFace) *Theme { +func NewTheme(fontCollection []font.FontFace) *Theme { t := &Theme{ Shaper: text.NewShaper(fontCollection), } diff --git a/widget/selectable.go b/widget/selectable.go index 438cc097..40a58eb6 100644 --- a/widget/selectable.go +++ b/widget/selectable.go @@ -5,6 +5,7 @@ import ( "math" "strings" + "gioui.org/font" "gioui.org/gesture" "gioui.org/io/clipboard" "gioui.org/io/event" @@ -176,7 +177,7 @@ func (l *Selectable) Truncated() bool { // Layout clips to the dimensions of the selectable, updates the shaped text, configures input handling, and paints // the text and selection rectangles. The provided textMaterial and selectionMaterial ops are used to set the // paint material for the text and selection rectangles, respectively. -func (l *Selectable) Layout(gtx layout.Context, lt *text.Shaper, font text.Font, size unit.Sp, textMaterial, selectionMaterial op.CallOp) layout.Dimensions { +func (l *Selectable) Layout(gtx layout.Context, lt *text.Shaper, font font.Font, size unit.Sp, textMaterial, selectionMaterial op.CallOp) layout.Dimensions { l.initialize() l.text.Alignment = l.Alignment l.text.MaxLines = l.MaxLines diff --git a/widget/selectable_test.go b/widget/selectable_test.go index 0307ff33..45978a6f 100644 --- a/widget/selectable_test.go +++ b/widget/selectable_test.go @@ -5,6 +5,7 @@ import ( "image" "testing" + "gioui.org/font" "gioui.org/font/gofont" "gioui.org/io/key" "gioui.org/layout" @@ -37,7 +38,7 @@ func TestSelectableMove(t *testing.T) { Locale: english, } cache := text.NewShaper(gofont.Collection()) - font := text.Font{} + fnt := font.Font{} fontSize := unit.Sp(10) str := `0123456789` @@ -47,7 +48,7 @@ func TestSelectableMove(t *testing.T) { s := new(Selectable) s.SetText(str) - s.Layout(gtx, cache, text.Font{}, fontSize, op.CallOp{}, op.CallOp{}) + s.Layout(gtx, cache, font.Font{}, fontSize, op.CallOp{}, op.CallOp{}) testKey := func(keyName string) { // Select 345 @@ -62,7 +63,7 @@ func TestSelectableMove(t *testing.T) { // Press the key gtx.Queue = newQueue(key.Event{State: key.Press, Name: keyName}) s.SetText(str) - s.Layout(gtx, cache, font, fontSize, op.CallOp{}, op.CallOp{}) + s.Layout(gtx, cache, fnt, fontSize, op.CallOp{}, op.CallOp{}) if expected, got := "", s.SelectedText(); expected != got { t.Errorf("KeyName %s, expected %q, got %q", keyName, expected, got) @@ -83,7 +84,7 @@ func TestSelectableConfigurations(t *testing.T) { } cache := text.NewShaper(gofont.Collection()) fontSize := unit.Sp(10) - font := text.Font{} + font := font.Font{} sentence := "\n\n\n\n\n\n\n\n\n\n\n\nthe quick brown fox jumps over the lazy dog" for _, alignment := range []text.Alignment{text.Start, text.Middle, text.End} { diff --git a/widget/text.go b/widget/text.go index e6054203..335f5d89 100644 --- a/widget/text.go +++ b/widget/text.go @@ -10,6 +10,7 @@ import ( "unicode/utf8" "gioui.org/f32" + "gioui.org/font" "gioui.org/layout" "gioui.org/op" "gioui.org/op/clip" @@ -222,7 +223,7 @@ func (e *textView) calculateViewSize(gtx layout.Context) image.Point { // Update the text, reshaping it as necessary. If not nil, eventHandling will be invoked after reshaping the text to // allow parent widgets to adapt to any changes in text content or positioning. If eventHandling modifies the contents // of the textView, it is guaranteed to be reshaped (and ready for painting) before Update returns. -func (e *textView) Update(gtx layout.Context, lt *text.Shaper, font text.Font, size unit.Sp, eventHandling func(gtx layout.Context)) { +func (e *textView) Update(gtx layout.Context, lt *text.Shaper, font font.Font, size unit.Sp, eventHandling func(gtx layout.Context)) { if e.params.Locale != gtx.Locale { e.params.Locale = gtx.Locale e.invalidate() diff --git a/widget/text_bench_test.go b/widget/text_bench_test.go index 2fe11d7c..17a0ed82 100644 --- a/widget/text_bench_test.go +++ b/widget/text_bench_test.go @@ -10,6 +10,7 @@ import ( "time" colEmoji "eliasnaur.com/font/noto/emoji/color" + "gioui.org/font" "gioui.org/font/gofont" "gioui.org/font/opentype" "gioui.org/gpu/headless" @@ -34,11 +35,11 @@ var ( }() sizes = []int{10, 100, 1000} locales = []system.Locale{arabic, english} - benchFonts = func() []text.FontFace { + benchFonts = func() []font.FontFace { collection := gofont.Collection() collection = append(collection, arabicCollection...) - collection = append(collection, text.FontFace{ - Font: text.Font{ + collection = append(collection, font.FontFace{ + Font: font.Font{ Typeface: "Noto Color Emoji", }, Face: emojiFace, @@ -91,7 +92,7 @@ func BenchmarkLabelStatic(b *testing.B) { defer win.Release() } fontSize := unit.Sp(10) - font := text.Font{} + font := font.Font{} runes := []rune(txt)[:runeCount] runesStr := string(runes) l := Label{} @@ -123,7 +124,7 @@ func BenchmarkLabelDynamic(b *testing.B) { defer win.Release() } fontSize := unit.Sp(10) - font := text.Font{} + font := font.Font{} runes := []rune(txt)[:runeCount] l := Label{} b.ResetTimer() @@ -158,7 +159,7 @@ func BenchmarkEditorStatic(b *testing.B) { defer win.Release() } fontSize := unit.Sp(10) - font := text.Font{} + font := font.Font{} runes := []rune(txt)[:runeCount] runesStr := string(runes) e := Editor{} @@ -191,7 +192,7 @@ func BenchmarkEditorDynamic(b *testing.B) { defer win.Release() } fontSize := unit.Sp(10) - font := text.Font{} + font := font.Font{} runes := []rune(txt)[:runeCount] e := Editor{} e.SetText(string(runes)) @@ -225,7 +226,7 @@ func FuzzEditorEditing(f *testing.F) { } cache := text.NewShaper(benchFonts) fontSize := unit.Sp(10) - font := text.Font{} + font := font.Font{} e := Editor{} f.Fuzz(func(t *testing.T, txt string, replaceFrom, replaceTo int16) { e.SetText(txt)