[Top][All Lists]
[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/