freetype-devel
[Top][All Lists]
Advanced

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

Re: [Devel] Character positioning issue still exists: more rounding erro


From: Anthony Fok
Subject: Re: [Devel] Character positioning issue still exists: more rounding error(s)?
Date: Mon, 24 Mar 2003 23:51:59 +0800
User-agent: Mutt/1.5.4i

On Fri, Mar 21, 2003 at 10:38:05AM +0100, David Turner wrote:
> Hi Anthony,
> 
> Anthony Fok wrote:
> >Sorry, I spoke too soon.  I receive more screenshots from a Debian users
> >after my upload of the latest 2003-03-15 CVS.  To my untrained eyes, it
> >seems that letters like "i", "l" got shifted (so that the letters look 
> >stuck together), and "A" looks horizontally compressed.  (If I am not
> >mistaken, Filipe's screenshots are rendered with Xft using the Tahoma font.)
> >I wonder if it is yet more rounding errors?
> >
> Could you confirm me that this bug is still present in the current
> implementation (i.e. this morning's CVS ?)

Yes, unfortunately, a rounding error with bytecode-interpreter hinted fonts
(not using autohinting) seems to be present still.

Note again that it seems to be related to the "#ifdef
FT_CONFIG_CHESTER_BLUE_SCALE" section in FT_Set_Char_Size() in ftobjs.c:

#ifdef FT_CONFIG_CHESTER_BLUE_SCALE
    /* No rounding; needed for autohinting??? */

    dim_x = ( char_width  * horz_resolution ) / 72;
    dim_y = ( char_height * vert_resolution ) / 72;

    metrics->x_ppem = (FT_UShort)( (dim_x+32) >> 6 );
    metrics->y_ppem = (FT_UShort)( (dim_y+32) >> 6 );
#else
    /* With rounding; needed for bytecode interpreted hints */

    dim_x = ( ( ( char_width  * horz_resolution ) / 72 ) + 32 ) & -64;
    dim_y = ( ( ( char_height * vert_resolution ) / 72 ) + 32 ) & -64;

    metrics->x_ppem  = (FT_UShort)( dim_x >> 6 );
    metrics->y_ppem  = (FT_UShort)( dim_y >> 6 );
#endif


When I took out the #ifdef and kept only the second half with "& -64"
rounding, the bytecode-interpreter-hinted fonts look good again.  A problem
is that the non-rounded code is never compiled.  So, I was convinced that a
runtime "if...else..." is needed, and, modelling after FT_Load_Glyph()
and combining the fine-tuning by Artur Zaprzala, tried the following patch:

============================================================================
--- freetype2~/src/base/ftobjs.c        2003-03-21 19:27:54.000000000 +0800
+++ freetype2/src/base/ftobjs.c 2003-03-23 01:11:55.000000000 +0800
@@ -1394,6 +1394,11 @@
     FT_Error          error = FT_Err_Ok;
     FT_Driver         driver;
     FT_Driver_Class   clazz;
+#ifdef FT_CONFIG_CHESTER_BLUE_SCALE
+    FT_Library        library;
+    FT_Bool           autohint;
+    FT_Module         hinter;
+#endif
     FT_Size_Metrics*  metrics;
     FT_Long           dim_x, dim_y;
 
@@ -1427,17 +1432,45 @@
 
     /* Compute pixel sizes in 26.6 units */
 #ifdef FT_CONFIG_CHESTER_BLUE_SCALE
-    dim_x = ( char_width  * horz_resolution ) / 72;
-    dim_y = ( char_height * vert_resolution ) / 72;
+    library = driver->root.library;
+    hinter  - library->auto_hinter;
+    autohint =
+      FT_BOOL( hinter                                      &&
+               !( load_flags & ( FT_LOAD_NO_SCALE    |
+                                 FT_LOAD_NO_RECURSE  |
+                                 FT_LOAD_NO_HINTING  |
+                                 FT_LOAD_NO_AUTOHINT ) )   &&
+               FT_DRIVER_IS_SCALABLE( driver )             &&
+               FT_DRIVER_USES_OUTLINES( driver )           );
+    if ( autohint )
+    {
+      if ( FT_DRIVER_HAS_HINTER( driver ) &&
+           !( load_flags & FT_LOAD_FORCE_AUTOHINT ) )
+        autohint = 0;
+    }
+
+    if ( autohint )
+    {
+      dim_x = ( char_width  * horz_resolution + 36 ) / 72; /* round div */
+      dim_y = ( char_height * vert_resolution + 36 ) / 72; /* round div */
+
+      metrics->x_ppem = (FT_UShort)( (dim_x+32) >> 6 ); /* round div */
+      metrics->y_ppem = (FT_UShort)( (dim_y+32) >> 6 ); /* round div */
+    }
+    else
+    {
+      dim_x = ( ( char_width  * horz_resolution + (36+32*72) ) / 72 ) & -64; 
/* round div */
+      dim_y = ( ( char_height * vert_resolution + (36+32*72) ) / 72 ) & -64; 
/* round div */
 
-    metrics->x_ppem = (FT_UShort)( (dim_x+32) >> 6 );
-    metrics->y_ppem = (FT_UShort)( (dim_y+32) >> 6 );
+      metrics->x_ppem  = (FT_UShort)( dim_x >> 6 ); /* floor div, already 
rounded */
+      metrics->y_ppem  = (FT_UShort)( dim_y >> 6 ); /* floor div, already 
rounded */
+    }
 #else
-    dim_x = ( ( ( char_width  * horz_resolution ) / 72 ) + 32 ) & -64;
-    dim_y = ( ( ( char_height * vert_resolution ) / 72 ) + 32 ) & -64;
+    dim_x = ( ( char_width  * horz_resolution + (36+32*72) ) / 72 ) & -64; /* 
round div */
+    dim_y = ( ( char_height * vert_resolution + (36+32*72) ) / 72 ) & -64; /* 
round div */
 
-    metrics->x_ppem  = (FT_UShort)( dim_x >> 6 );
-    metrics->y_ppem  = (FT_UShort)( dim_y >> 6 );
+    metrics->x_ppem  = (FT_UShort)( dim_x >> 6 ); /* floor div, already 
rounded */
+    metrics->y_ppem  = (FT_UShort)( dim_y >> 6 ); /* floor div, already 
rounded */
 #endif
 
     metrics->x_scale = 0x10000L;
==============================================================================

which did not work because load_flags is never passed to
FT_Set_Char_Size().  Silly me.  :-)

I see similar rounding in ttdriver.c added on 2003-03-15.  Perhaps that
is the right place.  Perhaps not.  I really don't know.  If the
rounding is not done at FT_Set_Char_Size(), could it be done at any
other place and achieve the same result?

But of course, all I have written above is based on my very very
limited knowledge of the FreeType source code.  I am very much like a
blind man touching the legs of an elephant and thinks that an elephant
is like a column.  :-)

Cheers,

Anthony

-- 
Anthony Fok Tung-Ling
ThizLinux Laboratory   <address@hidden> http://www.thizlinux.com/
Debian Chinese Project <address@hidden>       http://www.debian.org/intl/zh/
Come visit Our Lady of Victory Camp!           http://www.olvc.ab.ca/



reply via email to

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