Skip to content

Commit

Permalink
[font] add cap-height and x-height fallback for older fonts (closes #169
Browse files Browse the repository at this point in the history
)
  • Loading branch information
benoitkugler authored and whereswaldon committed Sep 25, 2024
1 parent 46915d6 commit bceaf9b
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 0 deletions.
11 changes: 11 additions & 0 deletions font/font_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,3 +123,14 @@ func TestLoadCFF2(t *testing.T) {
tu.Assert(t, font.cff2 != nil)
tu.Assert(t, font.cff2.VarStore.AxisCount() == 1)
}

func TestCapHeight(t *testing.T) {
ld := readFontFile(t, "common/mplus-1p-regular.ttf")
font, err := NewFont(ld)
tu.AssertNoErr(t, err)
face := NewFace(font)

// reference values from Harfbuzz
tu.Assert(t, face.LineMetric(CapHeight) == 730)
tu.Assert(t, face.LineMetric(XHeight) == 520)
}
23 changes: 23 additions & 0 deletions font/metrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,19 @@ var (
tagCapHeight = ot.MustNewTag("cpht")
)

// return the height from baseline (in font units)
func (f *Face) runeHeight(r rune) float32 {
gid, ok := f.Font.NominalGlyph(r)
if !ok {
return 0
}
extents, ok := f.GlyphExtents(gid)
if !ok {
return 0
}
return extents.YBearing
}

// LineMetric returns the metric identified by `metric` (in fonts units).
func (f *Face) LineMetric(metric LineMetric) float32 {
switch metric {
Expand All @@ -152,8 +165,18 @@ func (f *Face) LineMetric(metric LineMetric) float32 {
case SubscriptEmXOffset:
return float32(f.os2.ySubscriptXOffset) + f.mvar.getVar(tagSubscriptXOffset, f.coords)
case CapHeight:
if f.os2.version < 2 {
// sCapHeight may be set equal to the top of the unscaled and unhinted glyph
// bounding box of the glyph encoded at U+0048 (LATIN CAPITAL LETTER H).
return f.runeHeight('H')
}
return float32(f.os2.sCapHeight) + f.mvar.getVar(tagCapHeight, f.coords)
case XHeight:
if f.os2.version < 2 {
// sxHeight equal to the top of the unscaled and unhinted glyph bounding box
// of the glyph encoded at U+0078 (LATIN SMALL LETTER X).
return f.runeHeight('x')
}
return float32(f.os2.sxHeigh) + f.mvar.getVar(tagXHeight, f.coords)
default:
return 0
Expand Down

0 comments on commit bceaf9b

Please sign in to comment.