freetype
[Top][All Lists]
Advanced

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

Re: [ft] FT_Outline_Render makes different bitmaps in 32-bit and 64-bit


From: Tom Bishop, Wenlin Institute
Subject: Re: [ft] FT_Outline_Render makes different bitmaps in 32-bit and 64-bit programs?
Date: Tue, 26 Oct 2010 16:20:49 -0700

The bug appears to be here in ftraster.c:

  /* FMulDiv means `Fast MulDiv'; it is used in case where `b' is       */
  /* typically a small value and the result of a*b is known to fit into */
  /* 32 bits.                                                           */
#define FMulDiv( a, b, c )  ( (a) * (b) / (c) )

Evidently "...known to fit into 32 bits" is overly confident, especially when 
precision_bits = 12 (rather than 10 or 6).

Changing to

#define FMulDiv FT_MulDiv

(same as SMulDiv) solves the bug. For more information, you can make it a 
function:

static long FMulDiv(long a, long b, long c)
{
        long fast = ( (a) * (b) / (c) );
        long slow = FT_MulDiv(a, b, c);
        if (fast != slow) {
                printf("Problem in FMulDiv (%ld, %ld)\n", fast, slow);
        }
        return slow;
}

For the test program, there are many reports where fast and slow differ only 
slightly:

Problem in FMulDiv (162, 163)
Problem in FMulDiv (461, 462)
Problem in FMulDiv (49, 50)
...

But also some reports where the difference is huge:

Problem in FMulDiv (-308386, 934370)
Problem in FMulDiv (15151, -107087)
...

Maybe the solution could be optimized for speed by determining which calls to 
FMulDiv() are failing badly, and changing them to SMulDiv(), while retaining 
the old FMulDiv() where appropriate; but how one can assume such a limitation 
on the size of path coordinates? And is FT_MulDiv() really slow enough to make 
a big difference?

By the way, I noticed a few other things in ftraster.c:

(1) ras.precision_mask is never used. The macros like FLOOR() use 
"-ras.precision"; maybe they were supposed to use ras.precision_mask.

(2) ULong is never used.

(3) Changing Int, Short, Long, and *PLong all to int32_t, and changing UInt, 
UShort, and *PUShort all to uint32_t seems to make no difference to the 
behavior when running as 32-bit, but when running as 64-bit, it crashed with 
EXC_BAD_ACCESS at this line in Draw_Sweep():

   P->countL = (UShort)( P->start - min_Y );

-- because P wasn't a valid pointer; P->link had become corrupted. This line in 
Finalize_Profile_Table() is suspicious:

   p->link = (PProfile)( p->offset + p->height );

Note p->offset is type PLong, so the assumption seems to be made that 
sizeof(PProfile) == sizeof(Long), i.e., sizeof(struct TProfile_ *) == 
sizeof(Long), or in general, sizeof(void *) == sizeof(Long). Here's one example 
where Freetype does need 64-bit items, to store pointers when running in a 
64-bit program; but it seems problematic to assume a pointer is the same size 
as any type of integer. If p->offset is used for storage of PProfile, shouldn't 
its type be PProfile rather than PLong?

Yours,

Tom

文林 Wenlin Institute, Inc.        Software for Learning Chinese
E-mail: address@hidden     Web: http://www.wenlin.com
Telephone: 1-877-4-WENLIN (1-877-493-6546)
☯








reply via email to

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