Commit 38f8e894a510c13d48666134659e94aff6e76ea9

David Turner 2002-06-21T07:33:23

* src/pfr/pfrobjs.h, src/pfr/pfrobjs.c, src/pfr/pfrload.c, src/pfr/pfrtypes.h: adding Kerning support to the PFR driver

diff --git a/ChangeLog b/ChangeLog
index d60873c..a60e2e5 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2002-06-21  Sven Neuman   <sven@convergence.de>
+
+        * src/pfr/pfrobjs.h, src/pfr/pfrobjs.c, src/pfr/pfrload.c,
+        src/pfr/pfrtypes.h: adding Kerning support to the PFR driver
+
 2002-06-19  Detlef Würkner  <TetiSoft@apg.lahn.de>
 
 	* src/base/fttype1.c: Include FT_INTERNAL_TYPE42_TYPES_H.
diff --git a/README b/README
index 3407ffc..c1ba69a 100644
--- a/README
+++ b/README
@@ -10,7 +10,7 @@
   is called `libttf'.  They are *not* compatible!
 
 
-  FreeType 2.1.1
+  FreeType 2.1.2
   ==============
 
   Please   read  the  docs/CHANGES   file,  it   contains  IMPORTANT
@@ -22,9 +22,9 @@
   Note  that the  FreeType 2  documentation  is now  available as  a
   separate package from our sites.  See:
 
-    ftp://ftp.freetype.org/pub/freetype2/ftdocs-2.1.1.tar.bz2
-    ftp://ftp.freetype.org/pub/freetype2/ftdocs-2.1.1.tar.gz
-    ftp://ftp.freetype.org/pub/freetype2/ftdoc211.zip
+    ftp://ftp.freetype.org/pub/freetype2/ftdocs-2.1.2.tar.bz2
+    ftp://ftp.freetype.org/pub/freetype2/ftdocs-2.1.2.tar.gz
+    ftp://ftp.freetype.org/pub/freetype2/ftdoc212.zip
 
 
   Reports
diff --git a/docs/CHANGES b/docs/CHANGES
index 3af33e8..d7f9d9c 100644
--- a/docs/CHANGES
+++ b/docs/CHANGES
@@ -2,6 +2,36 @@ LATEST CHANGES BETWEEN 2.1.1 and 2.1.0
 
   I. IMPORTANT BUG FIXES
 
+    - Many font drivers didn't select a Unicode charmap by default when
+      a new face was opened (with the FT_CONFIG_OPTION_USE_CMAPS options
+      enabled), and this caused many application to not be able to
+      display text correctly with the 2.1.x releases
+      
+    - The PFR driver had a bug in its composite loading code that produces
+      incorrectly placed accents with many fonts
+      
+    - The Type42 driver crashed sometimes due to a nasty bug
+    
+    - The Type 1 custom encoding charmap didn't handle the case were the
+      first glyph index wasn't 0
+
+    - A serious typo in the TrueType composite loader produced incorrectly
+      placed glyphs in fonts like "Wingdings" and a few others..
+
+
+  II. MISCELLANEOUS
+
+    - The Win32 Visual C++ project file has been updated to include the
+      PFR driver as well
+
+    - "freetype.m4" is now installed by default by "make install" on Unix
+      systems.
+
+========================================================================
+LATEST CHANGES BETWEEN 2.1.1 and 2.1.0
+
+  I. IMPORTANT BUG FIXES
+
     - The `version_info' returned by `freetype-config' in 2.1.0 returned an
       invalid value. It now returns 9:1:3 (2.0.9 returned 9:0:3).
 
diff --git a/src/pfr/pfrdrivr.c b/src/pfr/pfrdrivr.c
index 9d9f3e3..64041f3 100644
--- a/src/pfr/pfrdrivr.c
+++ b/src/pfr/pfrdrivr.c
@@ -59,7 +59,7 @@
     (FT_Slot_LoadFunc)        pfr_slot_load,
     (FT_CharMap_CharIndexFunc)NULL,
 
-    (FT_Face_GetKerningFunc)  0,
+    (FT_Face_GetKerningFunc)  pfr_face_get_kerning,
     (FT_Face_AttachFunc)      0,
     (FT_Face_GetAdvancesFunc) 0,
 
diff --git a/src/pfr/pfrload.c b/src/pfr/pfrload.c
index 704b120..ec50f0a 100644
--- a/src/pfr/pfrload.c
+++ b/src/pfr/pfrload.c
@@ -68,7 +68,6 @@
       if ( item_list )
       {      
         PFR_ExtraItem  extra = item_list;
-        
 
         for ( extra = item_list; extra->parser != NULL; extra++ )
         {
@@ -501,11 +500,90 @@
   }                                 
 
 
+  /* 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 )
+  {
+    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;
+
+    /* 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;
+  }                                 
+
+
   static const PFR_ExtraItemRec  pfr_phy_font_extra_items[] =
   {
     { 1, (PFR_ExtraItem_ParseFunc) pfr_extra_item_load_bitmap_info },
     { 2, (PFR_ExtraItem_ParseFunc) pfr_extra_item_load_font_id },
     { 3, (PFR_ExtraItem_ParseFunc) pfr_extra_item_load_stem_snaps },
+    { 4, (PFR_ExtraItem_ParseFunc) pfr_extra_item_load_kerning_pairs },
     { 0, NULL }
   };
 
@@ -533,6 +611,9 @@
 
     FT_FREE( phy_font->blue_values );
     phy_font->num_blue_values = 0;
+
+    FT_FREE( phy_font->kern_pairs );
+    phy_font->num_kern_pairs = 0;
   }
   
 
diff --git a/src/pfr/pfrobjs.c b/src/pfr/pfrobjs.c
index 61e9afc..0d390e8 100644
--- a/src/pfr/pfrobjs.c
+++ b/src/pfr/pfrobjs.c
@@ -180,6 +180,10 @@
          if (root->num_charmaps)
            root->charmap = root->charmaps[0];
        }
+
+       /* check if we've loaded any kerning pairs */
+       if (phy_font->num_kern_pairs)
+         root->face_flags |= FT_FACE_FLAG_KERNING;
      }
 
   Exit:
@@ -318,4 +322,60 @@
   }
 
 
+  /*************************************************************************/
+  /*************************************************************************/
+  /*****                                                               *****/
+  /*****                      KERNING METHOD                           *****/
+  /*****                                                               *****/
+  /*************************************************************************/
+  /*************************************************************************/
+
+/* XXX: This relies on the font being spec-conformant, i.e. that the
+        kerning pairs are sorted. We might want to sort it just to make
+        sure */
+
+#undef  PFR_KERN_INDEX
+#define PFR_KERN_INDEX( g1, g2 )  ( ( (FT_ULong)g1 << 16 ) | g2 )
+
+  /* find the kerning for a given glyph pair */
+  FT_LOCAL_DEF( FT_Error )
+  pfr_face_get_kerning( PFR_Face    face,
+                        FT_UInt     glyph1,
+                        FT_UInt     glyph2,
+                        FT_Vector*  kerning )
+  {
+    PFR_PhyFont   phy_font = &face->phy_font;
+    PFR_KernPair  min, mid, max;
+    FT_ULong      idx = PFR_KERN_INDEX( glyph1, glyph2 );
+
+    /* simple binary search */
+    min = phy_font->kern_pairs;
+    max = min + phy_font->num_kern_pairs;
+
+    while ( min < max )
+    {
+      FT_ULong  midi;
+
+      mid  = min + ( max - min ) / 2;
+      midi = PFR_KERN_INDEX( mid->glyph1, mid->glyph2 );
+
+      if ( midi == idx )
+      {
+        *kerning = mid->kerning;
+        goto Exit;
+      }
+
+      if ( midi < idx )
+        min = mid + 1;
+      else
+        max = mid;
+    }
+
+    kerning->x = 0;
+    kerning->y = 0;
+
+  Exit:
+    return 0;
+  }
+
 /* END */
diff --git a/src/pfr/pfrobjs.h b/src/pfr/pfrobjs.h
index 03633a4..5b74931 100644
--- a/src/pfr/pfrobjs.h
+++ b/src/pfr/pfrobjs.h
@@ -66,6 +66,13 @@ FT_BEGIN_HEADER
 
 
   FT_LOCAL( FT_Error )
+  pfr_face_get_kerning( PFR_Face   face,
+                        FT_UInt    glyph1,
+                        FT_UInt    glyph2,
+                        FT_Vector* kerning );
+
+
+  FT_LOCAL( FT_Error )
   pfr_slot_init( PFR_Slot  slot );
 
   FT_LOCAL( void )
diff --git a/src/pfr/pfrtypes.h b/src/pfr/pfrtypes.h
index eb821d3..b3cd4df 100644
--- a/src/pfr/pfrtypes.h
+++ b/src/pfr/pfrtypes.h
@@ -189,6 +189,15 @@ FT_BEGIN_HEADER
   
   } PFR_DimensionRec, *PFR_Dimension;
 
+  /************************************************************************/
+
+  typedef struct  PFR_KernPairRec_
+  {
+    FT_UInt    glyph1;
+    FT_UInt    glyph2;
+    FT_Vector  kerning;
+
+  } PFR_KernPairRec, *PFR_KernPair;
 
   /************************************************************************/
 
@@ -221,7 +230,10 @@ FT_BEGIN_HEADER
     FT_UInt            num_chars;
     FT_UInt32          chars_offset;
     PFR_Char           chars;
-  
+
+    FT_UInt            num_kern_pairs;
+    PFR_KernPairRec   *kern_pairs;
+
   } PFR_PhyFontRec, *PFR_PhyFont;
 
 
@@ -238,6 +250,14 @@ FT_BEGIN_HEADER
   } PFR_PhyFlags;
 
 
+  typedef enum PFR_KernFlags_
+  {
+    PFR_KERN_2BYTE_ADJ   = 0x01,
+    PFR_KERN_2BYTE_CHAR  = 0x02
+  
+  } PFR_KernFlags;
+
+
   /************************************************************************/
 
   typedef enum  PFR_GlyphFlags_
diff --git a/src/type42/t42parse.c b/src/type42/t42parse.c
index 5fffde4..e28bcdb 100644
--- a/src/type42/t42parse.c
+++ b/src/type42/t42parse.c
@@ -629,7 +629,7 @@
           goto Fail;
         }
 
-        v = (FT_Byte)( 16 * t42_hexval( *cur ) + t42_hexval( *( cur + 1 ) ) );
+        v = (FT_Byte)( 16 * t42_hexval( cur[0] ) + t42_hexval( cur[1] ) );
         cur += 2;
         string_size++;
       }