shithub: freetype+ttf2subf

Download patch

ref: 7d90a4f05caa56fca8e920ed0e84c8d7f2b04e59
parent: 7543f394f77532043c7eeb7f1e028c66da0e4ae6
author: David Turner <[email protected]>
date: Tue Sep 9 16:11:56 EDT 2003

* src/base/ftpfr.c, src/pfr/pfrtypes.h, src/pfr/pfrload.c,
        src/pfr/pfrobjs.c: fixing PFR kerning support. The tables within
        the font file contain (charcode,charcode) kerning pairs, we need
        to convert them to (gindex,gindex) !

        * include/freetype/ftoption.h: commenting out the macro
        TT_CONFIG_OPTION_BYTECODE_INTERPRETER

git/fs: mount .git/fs: mount/attach disallowed
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2003-09-09  David Turner  <[email protected]>
+
+        * src/base/ftpfr.c, src/pfr/pfrtypes.h, src/pfr/pfrload.c,
+        src/pfr/pfrobjs.c: fixing PFR kerning support. The tables within
+        the font file contain (charcode,charcode) kerning pairs, we need
+        to convert them to (gindex,gindex) !
+
+        * include/freetype/ftoption.h: commenting out the macro
+        TT_CONFIG_OPTION_BYTECODE_INTERPRETER
+
 2003-08-31  Manish Singh  <[email protected]>
 
 	* src/bdf/bdflib.c (_bdf_readstream): Don't use FT_MEM_COPY but
--- a/include/freetype/config/ftoption.h
+++ b/include/freetype/config/ftoption.h
@@ -399,7 +399,7 @@
   /*   Do not #undef this macro here, since the build system might         */
   /*   define it for certain configurations only.                          */
   /*                                                                       */
-#undef  TT_CONFIG_OPTION_BYTECODE_INTERPRETER
+/* #define  TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
 
 
   /*************************************************************************/
--- a/src/base/ftpfr.c
+++ b/src/base/ftpfr.c
@@ -37,7 +37,7 @@
       if ( name[0] == 'p' &&
            name[1] == 'f' &&
            name[2] == 'r' &&
-           name[4] == 0   )
+           name[3] == 0 )
       {
         *aservice = (FT_PFR_Service) module->clazz->module_interface;
         error = 0;
--- a/src/pfr/pfrload.c
+++ b/src/pfr/pfrload.c
@@ -511,7 +511,6 @@
   }
 
 
-#if 0
 
   /* load kerning pair data */
   FT_CALLBACK_DEF( FT_Error )
@@ -519,88 +518,6 @@
                                      FT_Byte*     limit,
                                      PFR_PhyFont  phy_font )
   {
-    FT_Int        count;
-    FT_UShort     base_adj;
-    FT_UInt       flags;
-    FT_UInt       num_pairs;
-    PFR_KernPair  pairs;
-    FT_Error      error  = 0;
-    FT_Memory     memory = phy_font->memory;
-
-
-    /* allocate a new kerning item */
-    /* XXX: there may be multiple extra items for kerning */
-    if ( phy_font->kern_pairs != NULL )
-      goto Exit;
-
-    FT_TRACE2(( "pfr_extra_item_load_kerning_pairs()\n" ));
-
-    PFR_CHECK( 4 );
-
-    num_pairs = PFR_NEXT_BYTE( p );
-    base_adj  = PFR_NEXT_SHORT( p );
-    flags     = PFR_NEXT_BYTE( p );
-
-#ifndef PFR_CONFIG_NO_CHECKS
-    count = 3;
-
-    if ( flags & PFR_KERN_2BYTE_CHAR )
-      count += 2;
-
-    if ( flags & PFR_KERN_2BYTE_ADJ )
-      count += 1;
-
-    PFR_CHECK( num_pairs * count );
-#endif
-
-    if ( FT_NEW_ARRAY( pairs, num_pairs ) )
-      goto Exit;
-
-    phy_font->num_kern_pairs = num_pairs;
-    phy_font->kern_pairs     = pairs;
-
-    for (count = num_pairs ; count > 0; count--, pairs++ )
-    {
-      if ( flags & PFR_KERN_2BYTE_CHAR )
-      {
-        pairs->glyph1 = PFR_NEXT_USHORT( p );
-        pairs->glyph2 = PFR_NEXT_USHORT( p );
-      }
-      else
-      {
-        pairs->glyph1 = PFR_NEXT_BYTE( p );
-        pairs->glyph2 = PFR_NEXT_BYTE( p );
-      }
-
-      if ( flags & PFR_KERN_2BYTE_ADJ )
-        pairs->kerning.x = base_adj + PFR_NEXT_SHORT( p );
-      else
-        pairs->kerning.x = base_adj + PFR_NEXT_INT8( p );
-
-      pairs->kerning.y = 0;
-
-      FT_TRACE2(( "kerning %d <-> %d : %ld\n",
-                   pairs->glyph1, pairs->glyph2, pairs->kerning.x ));
-    }
-
-  Exit:
-    return error;
-
-  Too_Short:
-    error = PFR_Err_Invalid_Table;
-    FT_ERROR(( "pfr_extra_item_load_kerning_pairs: "
-               "invalid kerning pairs table\n" ));
-    goto Exit;
-  }
-
-#else /* 0 */
-
-  /* load kerning pair data */
-  FT_CALLBACK_DEF( FT_Error )
-  pfr_extra_item_load_kerning_pairs( FT_Byte*     p,
-                                     FT_Byte*     limit,
-                                     PFR_PhyFont  phy_font )
-  {
     PFR_KernItem  item;
     FT_Error      error  = 0;
     FT_Memory     memory = phy_font->memory;
@@ -690,9 +607,141 @@
                "invalid kerning pairs table\n" ));
     goto Exit;
   }
-#endif /* 0 */
 
 
+ /* the kerning data embedded in a PFR font are (charcode,charcode)
+  * pairs, we need to translate them to (gindex,gindex) and sort
+  * the resulting array
+  */
+  static FT_UInt
+  pfr_get_gindex( PFR_Char     chars,
+                  FT_UInt      count,
+                  FT_UInt      charcode )
+  {
+    FT_UInt    min    = 0;
+    FT_UInt    max    = count;
+
+    while ( min < max )
+    {
+      FT_UInt   mid = (min+max) >> 1;
+      PFR_Char  c   = chars + mid;
+
+      if ( c->char_code == charcode )
+        return mid + 1;
+
+      if ( c->char_code < charcode )
+        min = mid + 1;
+      else
+        max = mid;
+    }
+    return 0;
+  }
+
+
+  FT_CALLBACK_DEF( int )
+  pfr_compare_kern_pairs( const void*   pair1,
+                          const void*   pair2 )
+  {
+    FT_UInt32  p1 = PFR_KERN_PAIR_INDEX( (PFR_KernPair)pair1 );
+    FT_UInt32  p2 = PFR_KERN_PAIR_INDEX( (PFR_KernPair)pair2 );
+
+    if ( p1 < p2 )
+      return -1;
+    if ( p1 > p2 )
+      return 1;
+    return 0;
+  }
+
+
+  static FT_Error
+  pfr_sort_kerning_pairs( FT_Stream     stream,
+                          PFR_PhyFont   phy_font )
+  {
+    FT_Error      error;
+    FT_Memory     memory = stream->memory;
+    PFR_KernPair  pairs;
+    PFR_KernItem  item;
+    PFR_Char      chars     = phy_font->chars;
+    FT_UInt       num_chars = phy_font->num_chars;
+    FT_UInt       count;
+
+   /* create kerning pairs array
+    */
+    if ( FT_NEW_ARRAY( phy_font->kern_pairs, phy_font->num_kern_pairs ) )
+      goto Exit;
+
+   /* load all kerning items into the array,
+    * converting character codes into glyph indices
+    */
+    pairs = phy_font->kern_pairs;
+    item  = phy_font->kern_items;
+    count = 0;
+
+    for ( ; item; item = item->next )
+    {
+      FT_UInt   limit = count + item->pair_count;
+      FT_Byte*  p;
+
+      if ( limit > phy_font->num_kern_pairs )
+      {
+        error = PFR_Err_Invalid_Table;
+        goto Exit;
+      }
+
+      if ( FT_STREAM_SEEK( item->offset )                       ||
+           FT_FRAME_ENTER( item->pair_count * item->pair_size ) )
+        goto Exit;
+
+      p = stream->cursor;
+
+      for ( ; count < limit; count++ )
+      {
+        PFR_KernPair  pair = pairs + count;
+        FT_UInt       char1, char2;
+        FT_Int        kerning;
+
+        if ( item->flags & PFR_KERN_2BYTE_CHAR )
+        {
+          char1 = FT_NEXT_USHORT( p );
+          char2 = FT_NEXT_USHORT( p );
+        }
+        else
+        {
+          char1 = FT_NEXT_BYTE( p );
+          char2 = FT_NEXT_BYTE( p );
+        }
+
+        if ( item->flags & PFR_KERN_2BYTE_ADJ )
+          kerning = item->base_adj + FT_NEXT_SHORT( p );
+        else
+          kerning = item->base_adj + FT_NEXT_CHAR( p );
+
+        pair->glyph1  = pfr_get_gindex( chars, num_chars, char1 );
+        pair->glyph2  = pfr_get_gindex( chars, num_chars, char2 );
+        pair->kerning = kerning;
+      }
+
+      FT_FRAME_EXIT();
+    }
+
+   /* sort the resulting array
+    */
+    ft_qsort( pairs, count,
+              sizeof ( PFR_KernPairRec ),
+              pfr_compare_kern_pairs );
+
+  Exit:
+    if ( error )
+    {
+     /* disable kerning data in case of error
+      */
+      phy_font->num_kern_pairs = 0;
+    }
+
+    return error;
+  }
+
+
   static const PFR_ExtraItemRec  pfr_phy_font_extra_items[] =
   {
     { 1, (PFR_ExtraItem_ParseFunc) pfr_extra_item_load_bitmap_info },
@@ -770,6 +819,7 @@
     FT_FREE( phy_font->blue_values );
     phy_font->num_blue_values = 0;
 
+    FT_FREE( phy_font->kern_pairs );
     {
       PFR_KernItem  item, next;
 
@@ -1007,6 +1057,9 @@
     /* save position of bitmap info */
     phy_font->bct_offset = FT_STREAM_POS();
     phy_font->cursor     = NULL;
+
+    /* now sort kerning pairs */
+    error = pfr_sort_kerning_pairs( stream, phy_font );
 
   Exit:
     return error;
--- a/src/pfr/pfrobjs.c
+++ b/src/pfr/pfrobjs.c
@@ -419,77 +419,34 @@
   {
     FT_Error      error    = PFR_Err_Ok;
     PFR_PhyFont   phy_font = &face->phy_font;
-    PFR_KernItem  item     = phy_font->kern_items;
+    PFR_KernPair  pairs    = phy_font->kern_pairs;
     FT_UInt32     idx      = PFR_KERN_INDEX( glyph1, glyph2 );
+    FT_UInt       min, max;
 
     FT_UNUSED( error ); /* just needed as syntactical sugar */
 
-
     kerning->x = 0;
     kerning->y = 0;
 
-    /* find the kerning item containing our pair */
-    while ( item )
+    min = 0;
+    max = phy_font->num_kern_pairs;
+    
+    while ( min < max )
     {
-      if ( item->pair1 <= idx && idx <= item->pair2 )
-        goto Found_Item;
-
-      item = item->next;
-    }
-
-    /* not found */
-    return;
-
-  Found_Item:
-    {
-      /* perform simply binary search within the item */
-      FT_UInt    min, mid, max;
-      FT_Stream  stream = face->root.stream;
-      FT_Byte*   p;
-
-
-      if ( FT_STREAM_SEEK( item->offset )                       ||
-           FT_FRAME_ENTER( item->pair_count * item->pair_size ) )
-        return;
-
-      min = 0;
-      max = item->pair_count;
-      while ( min < max )
+      FT_UInt       mid  = (min+max) >> 1;
+      PFR_KernPair  pair = pairs + mid;
+      FT_UInt32     pidx = PFR_KERN_PAIR_INDEX( pair );
+      
+      if ( pidx == idx )
       {
-        FT_UInt  char1, char2, charcode;
-
-
-        mid = ( min + max ) >> 1;
-        p   = stream->cursor + mid*item->pair_size;
-
-        if ( item->flags & PFR_KERN_2BYTE_CHAR )
-        {
-          char1 = FT_NEXT_USHORT( p );
-          char2 = FT_NEXT_USHORT( p );
-        }
-        else
-        {
-          char1 = FT_NEXT_USHORT( p );
-          char2 = FT_NEXT_USHORT( p );
-        }
-        charcode = PFR_KERN_INDEX( char1, char2 );
-
-        if ( idx == charcode )
-        {
-          if ( item->flags & PFR_KERN_2BYTE_ADJ )
-            kerning->x = item->base_adj + FT_NEXT_SHORT( p );
-          else
-            kerning->x = item->base_adj + FT_NEXT_CHAR( p );
-
-          break;
-        }
-        if ( idx > charcode )
-          min = mid + 1;
-        else
-          max = mid;
+        kerning->x = pair->kerning;
+        break;
       }
-
-      FT_FRAME_EXIT();
+      
+      if ( pidx < idx )
+        min = mid+1;
+      else
+        max = mid;
     }
   }
 
--- a/src/pfr/pfrtypes.h
+++ b/src/pfr/pfrtypes.h
@@ -209,11 +209,14 @@
 #define PFR_KERN_INDEX( g1, g2 ) \
   ( ( (FT_UInt32)(g1) << 16 ) | (FT_UInt16)(g2) )
 
+#define PFR_KERN_PAIR_INDEX( pair )  \
+          PFR_KERN_INDEX( (pair)->glyph1, (pair)->glyph2 )
+
   typedef struct  PFR_KernPairRec_
   {
     FT_UInt    glyph1;
     FT_UInt    glyph2;
-    FT_Vector  kerning;
+    FT_Int     kerning;
 
   } PFR_KernPairRec, *PFR_KernPair;
 
@@ -230,7 +233,7 @@
     FT_BBox            bbox;
     FT_UInt            flags;
     FT_UInt            standard_advance;
-    
+
     FT_Int             ascent;   /* optional, bbox.yMax if not present */
     FT_Int             descent;  /* optional, bbox.yMin if not present */
     FT_Int             leading;  /* optional, 0 if not present         */
@@ -258,6 +261,7 @@
     FT_UInt            num_kern_pairs;
     PFR_KernItem       kern_items;
     PFR_KernItem*      kern_items_tail;
+    PFR_KernPair       kern_pairs;
 
     /* not part of the spec, but used during load */
     FT_UInt32          bct_offset;
@@ -281,8 +285,8 @@
 
   typedef enum PFR_KernFlags_
   {
-    PFR_KERN_2BYTE_ADJ   = 0x01,
-    PFR_KERN_2BYTE_CHAR  = 0x02
+    PFR_KERN_2BYTE_CHAR  = 0x01,
+    PFR_KERN_2BYTE_ADJ   = 0x02
 
   } PFR_KernFlags;