From 7946394216f347739cfd0e45357bafc3a15bafbf Mon Sep 17 00:00:00 2001 From: "Randall C. O'Reilly" Date: Thu, 16 Aug 2018 23:41:02 -0600 Subject: [PATCH] add advanceCache map[rune] -- easy and major speedup; add reading of lineGap; fix Height computation to use ascent - descent + lineGap --- truetype/face.go | 14 +++++++++++++- truetype/truetype.go | 6 +++++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/truetype/face.go b/truetype/face.go index 20611fa..f8697d1 100644 --- a/truetype/face.go +++ b/truetype/face.go @@ -229,6 +229,7 @@ type face struct { maxh int glyphBuf GlyphBuf indexCache [indexCacheLen]indexCacheEntry + advanceCache map[rune]fixed.Int26_6 // TODO: clip rectangle? } @@ -255,9 +256,12 @@ func (a *face) Metrics() font.Metrics { scale := float64(a.scale) fupe := float64(a.f.FUnitsPerEm()) return font.Metrics{ - Height: a.scale, + Height: fixed.Int26_6(math.Ceil(scale * float64(a.f.ascent-a.f.descent+a.f.lineGap) / fupe)), Ascent: fixed.Int26_6(math.Ceil(scale * float64(+a.f.ascent) / fupe)), Descent: fixed.Int26_6(math.Ceil(scale * float64(-a.f.descent) / fupe)), + // TODO: Metrics should include LineGap as a separate measure + // TODO: Would also be great to include Ex as in the height of an "x" -- + // used widely for layout } } @@ -342,9 +346,17 @@ func (a *face) GlyphBounds(r rune) (bounds fixed.Rectangle26_6, advance fixed.In } func (a *face) GlyphAdvance(r rune) (advance fixed.Int26_6, ok bool) { + if a.advanceCache == nil { + a.advanceCache = make(map[rune]fixed.Int26_6, 1024) + } + advance, ok = a.advanceCache[r] + if ok { + return + } if err := a.glyphBuf.Load(a.f, a.scale, a.index(r), a.hinting); err != nil { return 0, false } + a.advanceCache[r] = a.glyphBuf.AdvanceWidth return a.glyphBuf.AdvanceWidth, true } diff --git a/truetype/truetype.go b/truetype/truetype.go index 703fee8..2ae677a 100644 --- a/truetype/truetype.go +++ b/truetype/truetype.go @@ -187,6 +187,7 @@ type Font struct { fUnitsPerEm int32 ascent int32 // In FUnits. descent int32 // In FUnits; typically negative. + lineGap int32 // In FUnits. bounds fixed.Rectangle26_6 // In FUnits. // Values from the maxp section. maxTwilightPoints, maxStorage, maxFunctionDefs, maxStackElements uint16 @@ -294,6 +295,7 @@ func (f *Font) parseHhea() error { } f.ascent = int32(int16(u16(f.hhea, 4))) f.descent = int32(int16(u16(f.hhea, 6))) + f.lineGap = int32(int16(u16(f.hhea, 8))) f.nHMetric = int(u16(f.hhea, 34)) if 4*f.nHMetric+2*(f.nGlyph-f.nHMetric) != len(f.hmtx) { return FormatError(fmt.Sprintf("bad hmtx length: %d", len(f.hmtx))) @@ -323,7 +325,9 @@ func (f *Font) parseKern() error { } version, offset := u16(f.kern, 0), 2 if version != 0 { - return UnsupportedError(fmt.Sprintf("kern version: %d", version)) + f.nKern = 0 + return nil + // return UnsupportedError(fmt.Sprintf("kern version: %d", version)) } n, offset := u16(f.kern, offset), offset+2