[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [ft-devel] FT_Get_Advance() docs
Re: [ft-devel] FT_Get_Advance() docs
Fri, 09 Dec 2011 11:39:42 +0100
Mozilla/5.0 (Windows; U; Windows NT 6.1; fr; rv:184.108.40.206) Gecko/20100228 Thunderbird/220.127.116.11 Mnenhy/0.7.6.0
Werner LEMBERG wrote:
> While looking at the whole issue more closely, I've identified at
> least four bugs :-( One is extremely serious, making
> `FT_Get_Advance' return wrongly scaled values if fast advance
> loading isn't available (now fixed in git).
Yesterday I was away from my mail, but I also found this bug, and used
about the same fix as you committed. The only difference is a minor nit,
in the case FT_LOAD_NO_SCALE is used and the quick way failed with
ErrNotImplem, <<10 scaling might not be done.
Also, see below at the end for another point.
> The next two are more subtle and not directly related to
> `FT_Get_Advance' (I get wrong metrics from some fonts), and I need
> more investigation to fix them.
Details please. I did found something myself, most likely a double
rounding issue (more below), but I cannot figure where is the problem
exactly because I do not know the internals enough :-(.
>> Another thing we need to document is that the ->glyph instance
>> inside the face object might be erased after a call through
> Yes. Can you provide a patch?
Will do. I noticed there are some places (about GlyphSlotRec) where it
is mentioned the API functions which modify them, I should update that.
>> Well, there is also the "problem" that they used the FT_Get_Advance
>> API specifying light rendering, just to found out later that the
>> lightly hinted advance was actually different...
> One important issue has been missed completely by me: Advance widths
> don't change during the light hinting process, however, they get
> rounded to integer values, similar to TrueType.
Yeah, and I understand this was the problem Chromium guys did encounter
in the first place.
> After some thinking I now believe that it is a bug that
> `FT_Get_Advance' returns unrounded advance widths for the light
> hinting mode.
Okay, but then we have to mimic exactly the rounding process used by the
Load_Glyph logic*s*... More below.
>>>> [...] in TrueType there is a way to get the hinted advances
>>>> quicker than executing the full bytecode program, even if it is
>>>> not alluded above: when the requested ppem has an associated
>>>> hdmx/VDMX table within the font.
>>> Do you volunteer to implement support for those two tables?
>> Yes, I will do that (but not today.)
I looked at it, but it does not appear to be very easy to do,
particularly because the current (*...clazz->get_advances)() functions
returns _unscaled_ values (which are to be scaled within FT_Get_Advance
while "hdmx" values are pixels, hence are already scaled.
A possible way to deal with that could be for (*clazz->get_advances)()
to return FT_PseudoErr_InternalAlreadyScaled (it's internal after all),
and dealing with that case at FT_Get_Advance.
How do you feel it?
>> I wonder also about a new demo program to check whether
>> FT_Get_Advance() gives, or not, the same results as FT_Load_Glyph().
> This might be useful, yes.
Attached. -f and -i options behaves the same as with ftbench: so -f
10000 forces the use of the light hinting mode; -i is useful when you
got many failures, to skip up to "interesting" glyphs. The -a option
checks the value of glyph->advance.x; without -a, it checks the value of
glyph->linearHoriAdvance (which are supposedly the base; more below.)
I added the -r option after discovering as you did the issue with
grid-fitting: so -r rounds the 16.16 values before doing the comparison.
The problem I detected then was the behaviour of invocations like
C>ftchkadv -f 10000 -a -r 147 \Windows\Fonts\times.ttf
\Windows\Fonts\times.ttf: glyph 376: Load_Glyph->->advance: 92.0000 !=
glyph 377: Load_Glyph->->advance: 92.0000 != Get_Advance: 91.7e20
glyph 378: Load_Glyph->->advance: 92.0000 != Get_Advance: 91.7e20
glyph 379: Load_Glyph->->advance: 92.0000 != Get_Advance: 91.7e20
glyph 1620: Load_Glyph->->advance: 1d.0000 != Get_Advance: 1c.7ee0
glyph 1962: Load_Glyph->->advance: 2b.0000 != Get_Advance: 2a.7e00
glyph 2974: Load_Glyph->->advance: 2c.0000 != Get_Advance: 2b.7f40
glyph 3065: Load_Glyph->->advance: 2b.0000 != Get_Advance: 2a.7e00
Changing ppem only changes the problematic glyphs :-/.
Notice that every problem are always with Get_Advance being slightly
below the xx.8000 mark. I know the path for Get_Advance: grabs the raw
font units in 26.6 then MulDiv(,x_scale,64), and the result is in 16.16;
my current guess is that within the Load_Glyph codepath for ->advance,
there is two rounding steps... but I do not where/how; also the fact I
was not able to spot a similar problem with Type1 fonts suggests there
is something specific to TrueType happening.
But these experimentations with the two values (with -a or without)
reminds me with the first point, about the computation of FT_Get_Advance
in the fall-back case, and the use of the computed advance.x<<10 values
as references: would it make more sense to use linearHoriAdvance<<0 there?
I tried my test program with that change to ftadvanc.c, and detected
another variation, this time with FT_LOAD_NO_HINTING
C>ftchkadv -f 2 -a 147 \Windows\Fonts\times.ttf
\Windows\Fonts\times.ttf: glyph 0: Load_Glyph->->advance: 72.5800 !=
glyph 4: Load_Glyph->->advance: 30.f400 != Get_Advance: 30.f3c0
glyph 5: Load_Glyph->->advance: 3c.0000 != Get_Advance: 3c.0180
glyph 8: Load_Glyph->->advance: 7a.7400 != Get_Advance: 7a.73c0
glyph 9: Load_Glyph->->advance: 72.5800 != Get_Advance: 72.5760
glyph 10: Load_Glyph->->advance: 1a.7c00 != Get_Advance: 1a.7c60
glyph 11: Load_Glyph->->advance: 30.f400 != Get_Advance: 30.f3c0
glyph 12: Load_Glyph->->advance: 30.f400 != Get_Advance: 30.f3c0
glyph 14: Load_Glyph->->advance: 52.e800 != Get_Advance: 52.e720
glyph 16: Load_Glyph->->advance: 30.f400 != Get_Advance: 30.f3c0
Clearly, the problem now is with the precision: FT_Get_Advance gives
16.16 values, same as the precision of linearHoriAdvance; but advance.x
is a 26.6 value, so there is a loss of precision which the test program
detects here. I believe these results are to be expected, and they all
concur to the point that FT_Get_Advance is a quick way to find out the
"linearHoriAdvance" value, _not_ advance.x.
Description: Text document