Commit 495bd3cc4f54f5f4604709391a716fcd0c033277

Werner Lemberg 2012-06-06T13:24:04

[ftraster] Fix rounding issue causing visual artifacts. Problem reported by jola <hans-jochen.lau@lhsystems.com>; see http://lists.gnu.org/archive/html/freetype-devel/2012-05/msg00036.html * src/raster/ftraster.c (SMulDiv_No_Round): New macro. (Line_Up): Use it. * src/raster/ftmisc.h (FT_MulDiv_No_Round): Copied from `ftcalc.c'.

diff --git a/ChangeLog b/ChangeLog
index d2f6465..cbf9679 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+2012-06-06  Werner Lemberg  <wl@gnu.org>
+
+	[ftraster] Fix rounding issue causing visual artifacts.
+
+	Problem reported by jola <hans-jochen.lau@lhsystems.com>; see
+
+	  http://lists.gnu.org/archive/html/freetype-devel/2012-05/msg00036.html
+
+	* src/raster/ftraster.c (SMulDiv_No_Round): New macro.
+	(Line_Up): Use it.
+	* src/raster/ftmisc.h (FT_MulDiv_No_Round): Copied from `ftcalc.c'.
+
 2012-05-28  Alexei Podtelezhnikov  <apodtele@gmail.com>
 
 	* src/base/ftoutln.c (FT_Outline_Get_Orientation): Simplify.
diff --git a/src/raster/ftmisc.h b/src/raster/ftmisc.h
index 7773924..703155a 100644
--- a/src/raster/ftmisc.h
+++ b/src/raster/ftmisc.h
@@ -115,6 +115,27 @@
     return ( s > 0 ) ? d : -d;
   }
 
+
+  static 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;
+  }
+
 #endif /* __FTMISC_H__ */
 
 
diff --git a/src/raster/ftraster.c b/src/raster/ftraster.c
index f85845e..7d5bcae 100644
--- a/src/raster/ftraster.c
+++ b/src/raster/ftraster.c
@@ -60,7 +60,7 @@
 
 #include <ft2build.h>
 #include "ftraster.h"
-#include FT_INTERNAL_CALC_H   /* for FT_MulDiv only */
+#include FT_INTERNAL_CALC_H   /* for FT_MulDiv and FT_MulDiv_No_Round */
 
 #include "rastpic.h"
 
@@ -255,7 +255,8 @@
   /* On the other hand, SMulDiv means `Slow MulDiv', and is used typically */
   /* for clipping computations.  It simply uses the FT_MulDiv() function   */
   /* defined in `ftcalc.h'.                                                */
-#define SMulDiv  FT_MulDiv
+#define SMulDiv           FT_MulDiv
+#define SMulDiv_No_Round  FT_MulDiv_No_Round
 
   /* The rasterizer is a very general purpose component; please leave */
   /* the following redefinitions there (you never know your target    */
@@ -1150,14 +1151,14 @@
 
     if ( Dx > 0 )
     {
-      Ix = SMulDiv( ras.precision, Dx, Dy);
+      Ix = SMulDiv_No_Round( ras.precision, Dx, Dy );
       Rx = ( ras.precision * Dx ) % Dy;
       Dx = 1;
     }
     else
     {
-      Ix = SMulDiv( ras.precision, -Dx, Dy) * -1;
-      Rx =    ( ras.precision * -Dx ) % Dy;
+      Ix = -SMulDiv_No_Round( ras.precision, -Dx, Dy );
+      Rx = ( ras.precision * -Dx ) % Dy;
       Dx = -1;
     }