Skip to content

Fix font height computation#13

Merged
ktye merged 1 commit intoktye:masterfrom
fhs:font-height
Mar 8, 2019
Merged

Fix font height computation#13
ktye merged 1 commit intoktye:masterfrom
fhs:font-height

Conversation

@fhs
Copy link
Contributor

@fhs fhs commented Mar 8, 2019

The height that was being returned is the "recommended" amount of
vertical space, but it seems to be only slightly bigger than the Ascent.
It's small enough such that characters that take up space below the
baseline (e.g. 'g', 'y', 'j', 'p') gets cut off at the bottom.
(For reference, see
https://developer.apple.com/library/archive/documentation/TextFonts/Conceptual/CocoaTextArchitecture/Art/glyph_metrics_2x.png)

Plan9port's fontsrv also similarly sums up ascent and descent to compute
the height:
https://github.com/9fans/plan9port/blob/047fd921744f39a82a86d9370e03f7af511e6e84/src/cmd/fontsrv/x11.c#L80

@ktye
Copy link
Owner

ktye commented Mar 8, 2019

If I understand the image correctly: LineHeight = Ascent + Descent + LineGap.
All values should be positive and LineHeight > Ascent + Descent.
font.Metrics().Height should correspond to LineHeight.

Do you say, that this is not the case?
I think I believe so too, because I just recently converted from Height to Ascent+Descent in
https://github.com/ktye/plot/blob/master/vg/vg.go#L142

Is the issue a misinterpretation on my side, or a bug in the go freetype implementation of Metrics?

@ktye
Copy link
Owner

ktye commented Mar 8, 2019

For the record. This example:

package duitdraw

import (
        "fmt"
        "testing"

        "github.com/golang/freetype/truetype"
        "golang.org/x/image/font/gofont/goregular"
)

func TestFont(t *testing.T) {
        testCases := []struct {
                size float64
                dpi  float64
        }{
                {18, 72},
        }

        f, err := truetype.Parse(goregular.TTF)
        if err != nil {
                t.Fatal(err)
        }

        for _, tc := range testCases {
                opt := truetype.Options{
                        Size: tc.size,
                        DPI:  tc.dpi,
                }
                face := truetype.NewFace(f, &opt)
                m := face.Metrics()
                fmt.Printf("metrics: %+v\n", m)
                fmt.Printf("asc+dsc: %v\n", m.Ascent+m.Descent)
        }
}

prints:
metrics: {Height:18:00 Ascent:17:01 Descent:3:51 XHeight:0:00 CapHeight:0:00 CaretSlope:(0,0)}
asc+dsc: 20:52

While golang.org/x/image/font/basicfont is defined as:

var Face7x13 = &Face{
	Advance: 7,
	Width:   6,
	Height:  13,
	Ascent:  11,
	Descent: 2,
	Mask:    mask7x13,
	Ranges: []Range{
		{'\u0020', '\u007f', 0},
		{'\ufffd', '\ufffe', 95},
	},
}

Here Height > Ascent + Descent.

@fhs
Copy link
Contributor Author

fhs commented Mar 8, 2019

Yep, it does look like a freetype bug. I found the relevant issue: golang/freetype#34

It's unfortunate freetype is currently unmaintained. There are multiple PRs (golang/freetype#32, golang/freetype#62) with a fix waiting to be merged.

@ktye
Copy link
Owner

ktye commented Mar 8, 2019

I can commit your change. But this sets the Height to Ascent+Descent without any additional gap. The plan9 reference you linked scales with 1.35.
Do you want to add it, or should I commit as is?

The height seems to be only slightly bigger than the Ascent.
It's small enough such that characters that take up space below the
baseline (e.g. 'g', 'y', 'j', 'p') gets cut off at the bottom.
(For reference, see
https://developer.apple.com/library/archive/documentation/TextFonts/Conceptual/CocoaTextArchitecture/Art/glyph_metrics_2x.png)

This is a freetype bug: golang/freetype#34
There are multiple PRs with a fix that haven't been merged:
golang/freetype#32
golang/freetype#62

Plan9port's fontsrv also similarly sums up ascent and descent to compute
the height:
https://github.com/9fans/plan9port/blob/047fd921744f39a82a86d9370e03f7af511e6e84/src/cmd/fontsrv/x11.c#L80
@fhs
Copy link
Contributor Author

fhs commented Mar 8, 2019

The 1.35 scale seems to be experimentally determined, and it's part of a longer computation where the height is computed as:

(ascent + descent) * 1.35 * font_size/units_per_EM

Anyway, without the 1.35, I've checked that Edwood looks the same with fontsrv and duitdraw for the Go-Font and DejaVuSans. If I add 1.35, it adds too much space. I'm guessing the fonts I'm testing with have 0 line gap. To do this correctly, we'd probably have to fork the freetype package.

@ktye ktye merged commit 6f732b9 into ktye:master Mar 8, 2019
@ktye
Copy link
Owner

ktye commented Mar 8, 2019

Before forking freetype, I would prefer to make golang.org/x/image/font/sfnt usable.
As far as I know, it cannot be used to draw text using a font.Drawer yet.
The only way is to use the method in the example:
https://github.com/golang/image/blob/master/font/sfnt/example_test.go

@fhs fhs deleted the font-height branch March 8, 2019 20:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants