text/shape: reduce garbage a bit

The sfnt.Buffer embedded in the opentype type caused instances of
it to escape. Move the buffer to Family to avoid that.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
This commit is contained in:
Elias Naur
2019-10-05 22:53:37 +02:00
parent e8ca986a63
commit 1b44594411
2 changed files with 24 additions and 25 deletions
+10 -9
View File
@@ -29,6 +29,7 @@ type Family struct {
layoutCache layoutCache layoutCache layoutCache
pathCache pathCache pathCache pathCache
buf sfnt.Buffer
} }
// for returns a font for the given face. // for returns a font for the given face.
@@ -58,7 +59,7 @@ func (f *Family) Layout(face text.Face, size float32, str string, opts text.Layo
if l, ok := f.layoutCache.Get(lk); ok { if l, ok := f.layoutCache.Get(lk); ok {
return l return l
} }
l := layoutText(ppem, str, &opentype{Font: fnt, Hinting: font.HintingFull}, opts) l := layoutText(&f.buf, ppem, str, &opentype{Font: fnt, Hinting: font.HintingFull}, opts)
f.layoutCache.Put(lk, l) f.layoutCache.Put(lk, l)
return l return l
} }
@@ -74,19 +75,19 @@ func (f *Family) Shape(face text.Face, size float32, str text.String) op.MacroOp
if p, ok := f.pathCache.Get(pk); ok { if p, ok := f.pathCache.Get(pk); ok {
return p return p
} }
p := textPath(ppem, &opentype{Font: fnt, Hinting: font.HintingFull}, str) p := textPath(&f.buf, ppem, &opentype{Font: fnt, Hinting: font.HintingFull}, str)
f.pathCache.Put(pk, p) f.pathCache.Put(pk, p)
return p return p
} }
func layoutText(ppem fixed.Int26_6, str string, f *opentype, opts text.LayoutOptions) *text.Layout { func layoutText(buf *sfnt.Buffer, ppem fixed.Int26_6, str string, f *opentype, opts text.LayoutOptions) *text.Layout {
m := f.Metrics(ppem) m := f.Metrics(buf, ppem)
lineTmpl := text.Line{ lineTmpl := text.Line{
Ascent: m.Ascent, Ascent: m.Ascent,
// m.Height is equal to m.Ascent + m.Descent + linegap. // m.Height is equal to m.Ascent + m.Descent + linegap.
// Compute the descent including the linegap. // Compute the descent including the linegap.
Descent: m.Height - m.Ascent, Descent: m.Height - m.Ascent,
Bounds: f.Bounds(ppem), Bounds: f.Bounds(buf, ppem),
} }
var lines []text.Line var lines []text.Line
maxDotX := fixed.Int26_6(math.MaxInt32) maxDotX := fixed.Int26_6(math.MaxInt32)
@@ -119,7 +120,7 @@ func layoutText(ppem fixed.Int26_6, str string, f *opentype, opts text.LayoutOpt
c = ' ' c = ' '
s = 1 s = 1
} }
a, ok := f.GlyphAdvance(ppem, c) a, ok := f.GlyphAdvance(buf, ppem, c)
if !ok { if !ok {
prev.idx += s prev.idx += s
continue continue
@@ -142,7 +143,7 @@ func layoutText(ppem fixed.Int26_6, str string, f *opentype, opts text.LayoutOpt
next.adv = a next.adv = a
var k fixed.Int26_6 var k fixed.Int26_6
if prev.valid { if prev.valid {
k = f.Kern(ppem, prev.r, next.r) k = f.Kern(buf, ppem, prev.r, next.r)
} }
// Break the line if we're out of space. // Break the line if we're out of space.
if prev.idx > 0 && next.x+next.adv+k >= maxDotX { if prev.idx > 0 && next.x+next.adv+k >= maxDotX {
@@ -168,7 +169,7 @@ func layoutText(ppem fixed.Int26_6, str string, f *opentype, opts text.LayoutOpt
return &text.Layout{Lines: lines} return &text.Layout{Lines: lines}
} }
func textPath(ppem fixed.Int26_6, f *opentype, str text.String) op.MacroOp { func textPath(buf *sfnt.Buffer, ppem fixed.Int26_6, f *opentype, str text.String) op.MacroOp {
var lastPos f32.Point var lastPos f32.Point
var builder paint.Path var builder paint.Path
ops := new(op.Ops) ops := new(op.Ops)
@@ -179,7 +180,7 @@ func textPath(ppem fixed.Int26_6, f *opentype, str text.String) op.MacroOp {
builder.Begin(ops) builder.Begin(ops)
for _, r := range str.String { for _, r := range str.String {
if !unicode.IsSpace(r) { if !unicode.IsSpace(r) {
segs, ok := f.LoadGlyph(ppem, r) segs, ok := f.LoadGlyph(buf, ppem, r)
if !ok { if !ok {
continue continue
} }
+14 -16
View File
@@ -11,51 +11,49 @@ import (
type opentype struct { type opentype struct {
Font *sfnt.Font Font *sfnt.Font
Hinting font.Hinting Hinting font.Hinting
buf sfnt.Buffer
} }
func (f *opentype) GlyphAdvance(ppem fixed.Int26_6, r rune) (advance fixed.Int26_6, ok bool) { func (f *opentype) GlyphAdvance(buf *sfnt.Buffer, ppem fixed.Int26_6, r rune) (advance fixed.Int26_6, ok bool) {
g, err := f.Font.GlyphIndex(&f.buf, r) g, err := f.Font.GlyphIndex(buf, r)
if err != nil { if err != nil {
return 0, false return 0, false
} }
adv, err := f.Font.GlyphAdvance(&f.buf, g, ppem, f.Hinting) adv, err := f.Font.GlyphAdvance(buf, g, ppem, f.Hinting)
return adv, err == nil return adv, err == nil
} }
func (f *opentype) Kern(ppem fixed.Int26_6, r0, r1 rune) fixed.Int26_6 { func (f *opentype) Kern(buf *sfnt.Buffer, ppem fixed.Int26_6, r0, r1 rune) fixed.Int26_6 {
g0, err := f.Font.GlyphIndex(&f.buf, r0) g0, err := f.Font.GlyphIndex(buf, r0)
if err != nil { if err != nil {
return 0 return 0
} }
g1, err := f.Font.GlyphIndex(&f.buf, r1) g1, err := f.Font.GlyphIndex(buf, r1)
if err != nil { if err != nil {
return 0 return 0
} }
adv, err := f.Font.Kern(&f.buf, g0, g1, ppem, f.Hinting) adv, err := f.Font.Kern(buf, g0, g1, ppem, f.Hinting)
if err != nil { if err != nil {
return 0 return 0
} }
return adv return adv
} }
func (f *opentype) Metrics(ppem fixed.Int26_6) font.Metrics { func (f *opentype) Metrics(buf *sfnt.Buffer, ppem fixed.Int26_6) font.Metrics {
m, _ := f.Font.Metrics(&f.buf, ppem, f.Hinting) m, _ := f.Font.Metrics(buf, ppem, f.Hinting)
return m return m
} }
func (f *opentype) Bounds(ppem fixed.Int26_6) fixed.Rectangle26_6 { func (f *opentype) Bounds(buf *sfnt.Buffer, ppem fixed.Int26_6) fixed.Rectangle26_6 {
r, _ := f.Font.Bounds(&f.buf, ppem, f.Hinting) r, _ := f.Font.Bounds(buf, ppem, f.Hinting)
return r return r
} }
func (f *opentype) LoadGlyph(ppem fixed.Int26_6, r rune) ([]sfnt.Segment, bool) { func (f *opentype) LoadGlyph(buf *sfnt.Buffer, ppem fixed.Int26_6, r rune) ([]sfnt.Segment, bool) {
g, err := f.Font.GlyphIndex(&f.buf, r) g, err := f.Font.GlyphIndex(buf, r)
if err != nil { if err != nil {
return nil, false return nil, false
} }
segs, err := f.Font.LoadGlyph(&f.buf, g, ppem, nil) segs, err := f.Font.LoadGlyph(buf, g, ppem, nil)
if err != nil { if err != nil {
return nil, false return nil, false
} }