freetype-devel
[Top][All Lists]
Advanced

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

Re: [Devel] Getting accurate advances


From: David Bevan
Subject: Re: [Devel] Getting accurate advances
Date: Mon, 17 Nov 2003 09:23:50 +0000
User-agent: Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.0.2) Gecko/20030208 Netscape/7.02


Werner LEMBERG wrote:
So I tried linearHoriAdvance which was better but, despite what the
tutorial says, still not accurate enough - because it is calculated
using x_ppem (ftobjs.c line 554) which has been rounded to the
nearest pixel (x_scale is similarly rounded). The cumulative error
can be several mm with a text string of 15cm or so.


This is definitely a bug.


Perhaps the tutorial could be changed so that it doesn't claim that
linearHoriAdvance is accurate to 1/65536th of a pixel - or, better,
linearHoriAdvance could be calculated accurately (I can't see how to
do this without storing an additional unrounded value in a new
field).


The necessary data is already available in metrics->x_scale, with
sufficient accuracy I think.  We have to say

  slot->linearHoriAdvance =
    FT_MulDiv( slot->linearHoriAdvance, metrics->x_scale, 64 );

instead of

  slot->linearHoriAdvance =
    FT_MulDiv( slot->linearHoriAdvance,
               (FT_Long)metrics->x_ppem << 16, EM );

in function FT_Load_Glyph.

Please test.  If this works as expected I'll apply the change to the
CVS.

As I mentioned in my first paragraph, metrics->x_scale is also rounded - in fact it's simply 2048 * metrics->x_ppem with font I'm using, so the rsults are the same as using metrics->x_ppem.

The relevant code is from line 2019 in ftobjs.c:

  dim_x = ( ( char_width * horz_resolution + (36+32*72) ) / 72 ) & -64;

  metrics->x_ppem  = (FT_UShort)( dim_x >> 6 );

  metrics->x_scale = FT_DivFix( dim_x, face->units_per_EM );

Note that the rounding occurs in the calculation for dim_x. Changing this to:

  dim_x = ( char_width * horz_resolution + 36 ) / 72;

  metrics->x_ppem  = (FT_UShort)( ( dim_x + 32 ) >> 6 );

  metrics->x_scale = FT_DivFix( dim_x, face->units_per_EM );

produces the correct advances when used with your suggested change - *but* this changes the x_scale value used throughout all resizing, rendering, hinting, etc. Is this change correct or dangerous? Has the x_scale value always been wrong or does it need to be rounded for some reason? Since I don't know the answer to these questions, I am very reluctant to recommend the above change. (A parallel change would also be necessary for y_scale and linearVertAdvance).

Thanks.

David %^>

--
 ________________________________________________________
 David Bevan, Emtex Ltd.
 Emtex House, Station Road, Kings Langley, Herts. WD4 8LH England
 Tel:    +44 (0)1923 270882
 E-mail: address@hidden
 Web:    www.emtex.com




reply via email to

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