-
Notifications
You must be signed in to change notification settings - Fork 185
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
discrepancy in scale factor conversion between freetype and truetype packages #85
Comments
With this change, the computation of the scale factor becomes identical across the freetype and truetype packages, removing deviations in the font metrics that are derived from scale. The rounding computation is newer; it was introduced when the truetype.Face type was added in commit 6deea24. Fixes #85.
It's been a while since I remembered how this all works. Do you know what the C FreeType library does re round-down versus round-to-nearest? Does C FreeType even have a similar concept?? C FreeType and Go FreeType don't necessarily have identical APIs (even after accounting for C vs Go idioms)... If you don't know, that's fine, I can dig into it. It's just that, if you already know, it'd save me some work. FWIW, golang.org/x/image/font/opentype also rounds to nearest. https://github.com/golang/image/blob/a66eb6448b8d7557efb0c974c8d4d72085371c58/font/opentype/opentype.go#L111 says
so changing Go's |
Thanks for taking a look. I haven’t looked at the C FreeType code, so I don’t know which it uses offhand. I wouldn’t mind trying to look later on if it can help. |
I took a look. Specifically, I was looking over the C FreeType API and trying to see if there's something that accepts a font size in floating point and converts to fixed point. From what I was able to find, the C FreeType API doesn't have that: it largely accepts integers for DPI and fixed point for points, or integers for pixels. This means I wasn't able to find direct precedent for the Go API to follow in this particular situation. I did find a few places that in spirit seem to support the general idea of rounding to a nearest value rather than truncating, including: There are also mentions of a couple exceptions due to historical reasons, such ascender being rounded up to an integer value, and descender rounded down to an integer value. But those were the only two exceptions in terms of unusual rounding that I spotted. |
Copy-pasting a pull-request comment #86 (comment) here: I just noticed there's a return fixed.Int26_6(x * float64(c.dpi) * (64.0 / 72.0)) We should not change one without also changing the other, as that would fix #85 but introduce another inconsistency within this package. Hmm. |
To update this issue with the latest PR status: the comment above is resolved in #86 (comment). |
I noticed there's sometimes a tiny discrepancy in font metrics as computed by
freetype.Context
andtruetype.NewFace
.As a reproducible example, using the Go Mono font of size 86.4 exactly, at 72.0 DPI, the advance width for the glyph 'H' differs by 1/64 (the smallest value a
fixed.Int26_6
can represent).See the complete program on the Go Playground. Its output:
I've tracked it down and found the root cause. When computing the scale factor, the float64 → fixed 26.6 conversion is done differently between those two packages. In
truetype
, it rounds to the nearest 26.6 fixed point value:But in
freetype
, it uses the floor:Between those two, it seems taking the nearest value is the better behavior, so I'll send a PR that adjusts
freetype
to fix this discrepancy. CC @nigeltao.The text was updated successfully, but these errors were encountered: