diff --git a/ChangeLog b/ChangeLog index ce649fb71..c6c78c478 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +2003-11-23 Werner Lemberg + + * src/base/ftcalc.c (FT_MulDiv_No_Round): New function (32 and + 64 bit version). + * include/freetype/internal/ftcalc.h: Updated. + + * src/truetype/ttinterp.c (TT_MULDIV_NO_ROUND): New macro. + (TT_INT64): Removed. + (DO_DIV): Use TT_MULDIV_NO_ROUND. + + * src/pfr/pfrdrivr.c (pfr_get_metrics): Directly use + metrics->x_scale and metrics->y_scale. + 2003-11-22 Rogier van Dalen * src/truetype/ttinterp.c (CUR_Func_move_orig): New macro. diff --git a/include/freetype/internal/ftcalc.h b/include/freetype/internal/ftcalc.h index af1f64072..73fc5551e 100644 --- a/include/freetype/internal/ftcalc.h +++ b/include/freetype/internal/ftcalc.h @@ -4,7 +4,7 @@ /* */ /* Arithmetic computations (specification). */ /* */ -/* Copyright 1996-2001, 2002 by */ +/* Copyright 1996-2001, 2002, 2003 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -27,7 +27,8 @@ FT_BEGIN_HEADER - FT_EXPORT( FT_Int32 ) FT_SqrtFixed( FT_Int32 x ); + FT_EXPORT( FT_Int32 ) + FT_SqrtFixed( FT_Int32 x ); #define SQRT_32( x ) FT_Sqrt32( x ) @@ -59,6 +60,35 @@ FT_BEGIN_HEADER /*************************************************************************/ + /*************************************************************************/ + /* */ + /* */ + /* FT_MulDiv_No_Round */ + /* */ + /* */ + /* A very simple function used to perform the computation `(a*b)/c' */ + /* (without rounding) with maximal accuracy (it uses a 64-bit */ + /* intermediate integer whenever necessary). */ + /* */ + /* This function isn't necessarily as fast as some processor specific */ + /* operations, but is at least completely portable. */ + /* */ + /* */ + /* a :: The first multiplier. */ + /* b :: The second multiplier. */ + /* c :: The divisor. */ + /* */ + /* */ + /* The result of `(a*b)/c'. This function never traps when trying to */ + /* divide by zero; it simply returns `MaxInt' or `MinInt' depending */ + /* on the signs of `a' and `b'. */ + /* */ + FT_BASE( FT_Long ) + FT_MulDiv_No_Round( FT_Long a, + FT_Long b, + FT_Long c ); + + #define INT_TO_F26DOT6( x ) ( (FT_Long)(x) << 6 ) #define INT_TO_F2DOT14( x ) ( (FT_Long)(x) << 14 ) #define INT_TO_FIXED( x ) ( (FT_Long)(x) << 16 ) diff --git a/src/base/ftcalc.c b/src/base/ftcalc.c index 29a3a59fc..82cbcaae3 100644 --- a/src/base/ftcalc.c +++ b/src/base/ftcalc.c @@ -155,6 +155,29 @@ } + /* documentation is in ftcalc.h */ + + FT_BASE_DEF( FT_Long ) + FT_MulDiv_No_Round( FT_Long a, + FT_Long b, + FT_Long c ) + { + FT_Int s; + FT_Long d; + + + s = 1; + if ( a < 0 ) { a = -a; s = -1; } + if ( b < 0 ) { b = -b; s = -s; } + if ( c < 0 ) { c = -c; s = -s; } + + d = (FT_Long)( c > 0 ? (FT_Int64)a * b / c + : 0x7FFFFFFFL ); + + return ( s > 0 ) ? d : -d; + } + + /* documentation is in freetype.h */ FT_EXPORT_DEF( FT_Long ) @@ -303,9 +326,8 @@ s ^= c; c = ABS( c ); if ( a <= 46340L && b <= 46340L && c <= 176095L && c > 0 ) - { a = ( a * b + ( c >> 1 ) ) / c; - } + else if ( c > 0 ) { FT_Int64 temp, temp2; @@ -325,6 +347,39 @@ } + FT_BASE_DEF( FT_Long ) + FT_MulDiv_No_Round( FT_Long a, + FT_Long b, + FT_Long c ) + { + long s; + + + if ( a == 0 || b == c ) + return a; + + s = a; a = ABS( a ); + s ^= b; b = ABS( b ); + s ^= c; c = ABS( c ); + + if ( a <= 46340L && b <= 46340L && c > 0 ) + a = a * b / c; + + else if ( c > 0 ) + { + FT_Int64 temp; + + + ft_multo64( a, b, &temp ); + a = ft_div64by32( temp.hi, temp.lo, c ); + } + else + a = 0x7FFFFFFFL; + + return ( s < 0 ? -a : a ); + } + + /* documentation is in freetype.h */ FT_EXPORT_DEF( FT_Long ) diff --git a/src/pfr/pfrdrivr.c b/src/pfr/pfrdrivr.c index 6a72d09bb..c5f553017 100644 --- a/src/pfr/pfrdrivr.c +++ b/src/pfr/pfrdrivr.c @@ -62,12 +62,12 @@ static FT_Error pfr_get_advance( PFR_Face face, FT_UInt gindex, - FT_Pos *aadvance ) + FT_Pos *anadvance ) { FT_Error error = PFR_Err_Bad_Argument; - *aadvance = 0; + *anadvance = 0; if ( face ) { PFR_PhyFont phys = &face->phy_font; @@ -75,7 +75,7 @@ if ( gindex < phys->num_chars ) { - *aadvance = phys->chars[gindex].advance; + *anadvance = phys->chars[gindex].advance; error = 0; } } @@ -86,7 +86,7 @@ static FT_Error pfr_get_metrics( PFR_Face face, - FT_UInt *aoutline_resolution, + FT_UInt *anoutline_resolution, FT_UInt *ametrics_resolution, FT_Fixed *ametrics_x_scale, FT_Fixed *ametrics_y_scale ) @@ -96,8 +96,8 @@ FT_Size size = face->root.size; - if ( aoutline_resolution ) - *aoutline_resolution = phys->outline_resolution; + if ( anoutline_resolution ) + *anoutline_resolution = phys->outline_resolution; if ( ametrics_resolution ) *ametrics_resolution = phys->metrics_resolution; @@ -107,11 +107,8 @@ if ( size ) { - x_scale = FT_DivFix( size->metrics.x_ppem << 6, - phys->metrics_resolution ); - - y_scale = FT_DivFix( size->metrics.y_ppem << 6, - phys->metrics_resolution ); + x_scale = size->metrics.x_scale; + y_scale = size->metrics.y_scale; } if ( ametrics_x_scale ) diff --git a/src/truetype/ttinterp.c b/src/truetype/ttinterp.c index d996a5dd8..1aaecee7b 100644 --- a/src/truetype/ttinterp.c +++ b/src/truetype/ttinterp.c @@ -30,9 +30,10 @@ #ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER -#define TT_MULFIX FT_MulFix -#define TT_MULDIV FT_MulDiv -#define TT_INT64 FT_Int64 +#define TT_MULFIX FT_MulFix +#define TT_MULDIV FT_MulDiv +#define TT_MULDIV_NO_ROUND FT_MulDiv_No_Round + /*************************************************************************/ /* */ @@ -2973,12 +2974,11 @@ args[0] -= args[1]; -#define DO_DIV \ - if ( args[1] == 0 ) \ - CUR.error = TT_Err_Divide_By_Zero; \ - else \ -/* Should args[0] be cast to FT_Int64 first? */ \ - args[0] = ( args[0] * 64L ) / args[1]; +#define DO_DIV \ + if ( args[1] == 0 ) \ + CUR.error = TT_Err_Divide_By_Zero; \ + else \ + args[0] = TT_MULDIV_NO_ROUND( args[0], 64L, args[1] ); #define DO_MUL \