golang/freetype

truetype: font metrics ascent and descent values appear incorrect

dskinner opened this issue · 2 comments

I believe this is related to #32 where eaburns pointed out a potential issue with the scale factor. I don't know a great deal about fonts, but presuming a zero line gap and that height == ascent+descent, I'm seeing issues with Droid Sans and Source Code Pro fonts using font.Drawer, no hinting, 72dpi, 240pt.

For example:

bin, err := ioutil.ReadFile("DroidSans.ttf")
if err != nil {
    log.Fatal(err)
}
f, err := truetype.Parse(bin)
if err != nil {
    log.Fatal(err)
}

fc := truetype.NewFace(f, &truetype.Options{
    Size:    240,
    DPI:     72,
    Hinting: font.HintingNone,
})

fmt.Printf("metrics %+v\n", fc.Metrics())
// Output: metrics {Height:240:00 Ascent:222:50 Descent:56:39}
fmt.Printf("ascent+descent %v\n", fc.Metrics().Ascent+fc.Metrics().Descent)
// Output: ascent+descent 279:25

I'm packing glyphs in a texture and exporting the metrics for use in opengl. The above was causing my baseline calculation to be lower than expected. For now I've worked around this by scaling the ascent and descent by size/(ascent+descent) which produced the semi-correct result I'd expect.

Your assumption that height == ascent + descent is a reasonable guess, but is incorrect. (I made the same mistake!) In FreeType, descent is a negative value, so height == ascent - descent.

From the FreeType docs:

Descent
The distance from the baseline to the lowest grid coordinate used to place an outline point. In FreeType, this is a negative value, due to the grid's orientation. Note that in some font formats this is a positive value.

(https://www.freetype.org/freetype2/docs/glyphs/glyphs-3.html)

Descent being negative might be true for the C FreeType library, but it's not true for the Go FreeType library. The Go flavor implements the golang.org/x/image/font interfaces, which allow non-FreeType implementations, and the docs for the Descent field at http://godoc.org/golang.org/x/image/font#Metrics says:

// Descent is the distance from the bottom of a line to its baseline. The
// value is typically positive, even though a descender goes below the
// baseline.