ref: 9f051a7fa46417f59b56691ef21a372ba2847997
parent: 4ff243d90af16b25993be5cf3924170a53249a0c
author: Werner Lemberg <[email protected]>
date: Tue Nov 25 13:15:56 EST 2003
* 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.
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+2003-11-23 Werner Lemberg <[email protected]>
+
+ * 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 <[email protected]>
* src/truetype/ttinterp.c (CUR_Func_move_orig): New macro.
--- 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 )
@@ -57,6 +58,35 @@
/* FT_MulDiv() and FT_MulFix() are declared in freetype.h. */
/* */
/*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_MulDiv_No_Round */
+ /* */
+ /* <Description> */
+ /* 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. */
+ /* */
+ /* <Input> */
+ /* a :: The first multiplier. */
+ /* b :: The second multiplier. */
+ /* c :: The divisor. */
+ /* */
+ /* <Return> */
+ /* 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 )
--- 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;
@@ -316,6 +338,39 @@
temp2.hi = 0;
temp2.lo = (FT_UInt32)(c >> 1);
FT_Add64( &temp, &temp2, &temp );
+ a = ft_div64by32( temp.hi, temp.lo, c );
+ }
+ else
+ a = 0x7FFFFFFFL;
+
+ return ( s < 0 ? -a : a );
+ }
+
+
+ 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/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 )
--- a/src/truetype/ttinterp.c
+++ b/src/truetype/ttinterp.c
@@ -30,10 +30,11 @@
#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
+
/*************************************************************************/
/* */
/* The macro FT_COMPONENT is used in trace mode. It is an implicit */
@@ -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 \