freetype-devel
[Top][All Lists]
Advanced

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

Re: [Devel] off-by-one-digit bug in ttinterp.c?


From: David Turner
Subject: Re: [Devel] off-by-one-digit bug in ttinterp.c?
Date: Sun, 18 Jul 2004 09:26:34 +0200
User-agent: Mozilla Thunderbird 0.5 (Windows/20040207)

david mosberger wrote:

[I sent this mail from my home machine already but it was incorrectly rejected:

  <address@hidden>: host mail.freetype.org[212.43.237.66] said: 554 Service
    unavailable; [66.127.195.58] blocked using dul.dnsbl.sorbs.net, reason:
    Dynamic IP Address See:
    http://www.dnsbl.sorbs.net/cgi-bin/lookup?IP=66.127.195.58 (in reply to
    RCPT TO command)

 The black-list is wrong: IP address 66.127.195.58 is a FIXED IP address and the
 mail shouldn't have been rejected...]

I believe you should send a notice to the SORBS admins, there is little thing
we can do at the FreeType site unless we want to play "security russian 
roulette" :-)

Hi,

I have been experiencing long stalls on certain web-pages (such as
slashdot.org) when using mozilla on a Debian/ia64 box running
"testing".  During the stalls, the CPU was 100% busy in a loop inside
the TrueType's ttinterp.c:Normalize() routine.  If I understand that
code correctly, it's trying to normalize the vector length to 1.0
(scaled by 16384).  However, there appears to be an off-by-one-digit
error in the error-correction code that follows the main scaling.  In
particular, the code there says:

    /* Now, we want that Sqrt( W ) = 0x4000 */
    /* Or 0x1000000 <= W < 0x1004000        */

However, 0x4000 * 0x4000 = 0x10000000, so I think the condition should
be:

    /* Or 0x10000000 <= W < 0x10004000        */

Indeed, if I apply the attached patch, the hangs in mozilla do disappear.


My, oh my, I really wonder why I didn't spot this before. This code has
been in the interpreter for so long. It's really a miracle that it doesn't
seem to affect rendering quality in any way.

Thanks a lot for spotting this problem. This is now fixed in the CVS



PS: Is there a particular reason not to use IEEE extended precision
    (80-bit) arithmetic on platforms that have this available?
    Particularly on ia64, that would be a lot faster than using
    fixed-point arithmetic, since (general) 64-bit multiplication has
    to be done in the floating-point unit anyhow.

There are particular reasons not to use floating points:

- the whole TrueType virtual machine is built around 26.6
  fixed point arithmetic. And it is _extremely_ sensitive
  to rounding bugs, i.e. I had to experiment a lot to
  determine how to perform most computations to mimic the
  original Apple/Microsoft code that most TrueType bytecode
  depends on.

- a very common operation in the hinters (TrueType bytecode,
  Type 1, or autohint), is to fit a value to the pixel grid,
  i.e., something like:

       x = (x+32) & ~63;
       y = y & ~63;
       z = (z+63) & ~63;

  these operations are typically very slow with floating
  points


- performance in lots of embedded systems would suck

If you want to experiment with floating points, try to
re-implement the functions FT_MulFix and FT_MulDiv with
them, since that's where most of the CPU spends it time
during glyph loading. This may make a big difference
on certain architectures.

Best Regards,

- David Turner
- The FreeType Project  (www.freetype.org)




------------------------------------------------------------------------

--- freetype2/src/truetype/ttinterp.c-orig      2004-07-15 23:57:01.763595339 
-0700
+++ freetype2/src/truetype/ttinterp.c   2004-07-15 23:57:27.806845483 -0700
@@ -2474,7 +2474,7 @@
     W = Vx * Vx + Vy * Vy;
/* Now, we want that Sqrt( W ) = 0x4000 */
-    /* Or 0x1000000 <= W < 0x1004000        */
+    /* Or 0x10000000 <= W < 0x10004000        */
if ( Vx < 0 )
     {
@@ -2492,7 +2492,7 @@
     else
       S2 = FALSE;
- while ( W < 0x1000000L )
+    while ( W < 0x10000000L )
     {
       /* We need to increase W by a minimal amount */
       if ( Vx < Vy )
@@ -2503,7 +2503,7 @@
       W = Vx * Vx + Vy * Vy;
     }
- while ( W >= 0x1004000L )
+    while ( W >= 0x10004000L )
     {
       /* We need to decrease W by a minimal amount */
       if ( Vx < Vy )




reply via email to

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