Commit 0e0fdc5dc89e5079898c5da67b56f994c439fee1

Alexei Podtelezhnikov 2013-01-12T23:05:55

[truetype] Improve accuracy of normalization of short vectors. Unit vector components are stored as 2.14 fixed-point numbers. In order to calculate all 14 bits accurately, a short vector to be normalized has to be upscaled to at least 14 bits before its length is calculated. This has been safe since accurate CORDIC algorithms were adopted. * src/truetype/ttinterp.c (Normalize): Scale short vectors by 0x4000.

diff --git a/ChangeLog b/ChangeLog
index 4b35164..07931d1 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,17 @@
 2013-01-12  Alexei Podtelezhnikov  <apodtele@gmail.com>
 
+	[truetype] Improve accuracy of normalization of short vectors.
+
+	Unit vector components are stored as 2.14 fixed-point numbers. In
+	order to calculate all 14 bits accurately, a short vector to be
+	normalized has to be upscaled to at least 14 bits before its length
+	is calculated. This has been safe since accurate CORDIC algorithms
+	were adopted.
+
+	* src/truetype/ttinterp.c (Normalize): Scale short vectors by 0x4000.
+
+2013-01-12  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
 	[truetype] Kill very old vector normalization hacks.
 
 	Back in the days, vector length calculations were not very accurate
diff --git a/src/truetype/ttinterp.c b/src/truetype/ttinterp.c
index f862320..1cbb351 100644
--- a/src/truetype/ttinterp.c
+++ b/src/truetype/ttinterp.c
@@ -2635,8 +2635,6 @@
   /*    In case Vx and Vy are both zero, Normalize() returns SUCCESS, and  */
   /*    R is undefined.                                                    */
   /*                                                                       */
-
-
   static FT_Bool
   Normalize( EXEC_OP_ FT_F26Dot6      Vx,
                       FT_F26Dot6      Vy,
@@ -2647,17 +2645,17 @@
     FT_UNUSED_EXEC;
 
 
-    if ( FT_ABS( Vx ) < 0x10000L && FT_ABS( Vy ) < 0x10000L )
+    if ( FT_ABS( Vx ) < 0x4000L && FT_ABS( Vy ) < 0x4000L )
     {
-      Vx *= 0x100;
-      Vy *= 0x100;
-
       if ( Vx == 0 && Vy == 0 )
       {
         /* XXX: UNDOCUMENTED! It seems that it is possible to try   */
         /*      to normalize the vector (0,0).  Return immediately. */
         return SUCCESS;
       }
+
+      Vx *= 0x4000;
+      Vy *= 0x4000;
     }
 
     W = TT_VecLen( Vx, Vy );