Commit 9f051a7fa46417f59b56691ef21a372ba2847997

Werner Lemberg 2003-11-25T18:15:56

* 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.

diff --git a/ChangeLog b/ChangeLog
index ce649fb..c6c78c4 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+2003-11-23  Werner Lemberg  <wl@gnu.org>
+
+	* 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  <R.C.van.Dalen@umail.leidenuniv.nl>
 
 	* 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 af1f640..73fc555 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
   /*************************************************************************/
 
 
+  /*************************************************************************/
+  /*                                                                       */
+  /* <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  )
 #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 29a3a59..82cbcaa 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 6a72d09..c5f5530 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 d996a5d..1aaecee 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                                    \