Commit 9a554eb2d619e3340558b5b8b54dbd20b9b37a7e

David Turner 2001-06-27T12:40:46

the SFNT Kerning table loader now ensures that the table is correctly sorted.

diff --git a/ChangeLog b/ChangeLog
index 59949c9..145a8af 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,9 @@
 2001-06-27  David Turner <david@freetype.org>
 
+	* src/sfnt/ttload.c (TT_Load_Kern): the kern table loader now ensures
+	that the kerning table is correctly sorted (some problem fonts don't
+	have a correct kern table !!)
+
 	* builds/unix/ftconfig.in: changed the definition of the
 	FT_CALLBACK_DEF macro
 
diff --git a/src/sfnt/ttload.c b/src/sfnt/ttload.c
index 8f4e366..e81e475 100644
--- a/src/sfnt/ttload.c
+++ b/src/sfnt/ttload.c
@@ -26,6 +26,7 @@
 
 #include "sferrors.h"
 
+#include <stdlib.h>  /* for qsort */
 
   /*************************************************************************/
   /*                                                                       */
@@ -1537,6 +1538,10 @@
   /* <Return>                                                              */
   /*    FreeType error code.  0 means success.                             */
   /*                                                                       */
+
+  FT_CALLBACK_DEF(int)
+  tt_kern_pair_compare( const void* a, const void* b );
+
   FT_LOCAL_DEF
   FT_Error  TT_Load_Kern( TT_Face    face,
                           FT_Stream  stream )
@@ -1610,6 +1615,26 @@
 
         face->num_kern_pairs   = num_pairs;
         face->kern_table_index = n;
+        
+        /* ensure that the kerning pair table is sorted (yes, some */
+        /* fonts have unsorted tables !!)                          */
+        {
+          FT_UInt          i;
+          TT_Kern_0_Pair*  pair;
+          
+          pair = face->kern_pairs;
+
+          for ( i=1; i < num_pairs; i++, pair++ )
+          {
+            if ( tt_kern_pair_compare( pair, pair+1 ) != -1 )
+            {
+              qsort( (void*)face->kern_pairs, (int)num_pairs,
+                     sizeof(TT_Kern_0_Pair), tt_kern_pair_compare );
+              break;
+            }
+          }
+        }
+        
         goto Exit;
       }
 
@@ -1626,6 +1651,23 @@
     return error;
   }
 
+#undef  TT_KERN_INDEX
+#define TT_KERN_INDEX(g1,g2)   (((FT_ULong)g1 << 16) | g2)
+
+  FT_CALLBACK_DEF(int)
+  tt_kern_pair_compare( const void* a, const void* b )
+  {
+    TT_Kern_0_Pair*  pair1 = (TT_Kern_0_Pair*)a;
+    TT_Kern_0_Pair*  pair2 = (TT_Kern_0_Pair*)b;
+
+    FT_ULong  index1 = TT_KERN_INDEX( pair1->left, pair1->right );
+    FT_ULong  index2 = TT_KERN_INDEX( pair2->left, pair2->right );
+
+    return ( index1 < index2 ? -1 :
+           ( index1 > index2 ?  1 : 0 ));
+  }
+
+#undef TT_KERN_INDEX
 
   /*************************************************************************/
   /*                                                                       */