freetype-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [ft-devel] FT_Get_Advance() docs


From: Antoine Leca
Subject: Re: [ft-devel] FT_Get_Advance() docs
Date: Fri, 09 Dec 2011 11:39:42 +0100
User-agent: Mozilla/5.0 (Windows; U; Windows NT 6.1; fr; rv:1.8.1.24) Gecko/20100228 Thunderbird/2.0.0.24 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
>> FT_Get_Advance().
> 
> 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 !=
Get_Advance: 91.7e20
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
8 fails.

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 !=
Get_Advance: 72.5760
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
2549 fails.

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.


Antoine

Attachment: ftchkadv.c
Description: Text document


reply via email to

[Prev in Thread] Current Thread [Next in Thread]