shithub: freetype+ttf2subf

Download patch

ref: 80171e06dd1ee8790c0a37874e671eeeb1395a91
parent: 4c09ae8002bcd35509f365c871776f9acbe35ab0
author: David Turner <[email protected]>
date: Sat Oct 5 10:57:03 EDT 2002

* src/pfr/pfrsbit.h, src/pfr/pfrsbit.c, src/pfr/pfrload.c,
        src/pfr/pfrgload.c, src/pfr/pfrobjs.c, src/pfr/pfrtypes.h,
        Jamfile, src/base/ftobjs.c: adding support for embedded bitmaps to
        the PFR driver, and rewriting its kerning loader / handler to use all
        kerning pairs in a physical font (and not just the first item).

        * src/tools/docmaker/content.py, src/tools/docmaker/sources.py,
        src/tools/docmaker/tohtml.py: fixing a few nasty bugs

        * src/sfnt/ttcmap0.c: the validator for format 4 sub-tables is
        now capable of dealing with invalid "length" fields at the start
        of the sub-table. This allows fonts like "mg______.ttf" (i.e.
        Marriage) to return accurate charmaps.

git/fs: mount .git/fs: mount/attach disallowed
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,19 @@
+2002-10-05  David Turner  <[email protected]>
+
+        * src/pfr/pfrsbit.h, src/pfr/pfrsbit.c, src/pfr/pfrload.c,
+        src/pfr/pfrgload.c, src/pfr/pfrobjs.c, src/pfr/pfrtypes.h,
+        Jamfile, src/base/ftobjs.c: adding support for embedded bitmaps to
+        the PFR driver, and rewriting its kerning loader / handler to use all
+        kerning pairs in a physical font (and not just the first item).
+
+        * src/tools/docmaker/content.py, src/tools/docmaker/sources.py,
+        src/tools/docmaker/tohtml.py: fixing a few nasty bugs
+
+        * src/sfnt/ttcmap0.c: the validator for format 4 sub-tables is
+        now capable of dealing with invalid "length" fields at the start
+        of the sub-table. This allows fonts like "mg______.ttf" (i.e.
+        Marriage) to return accurate charmaps.
+
 2002-10-05  Werner Lemberg  <[email protected]>
 
 	* src/smooth/ftgrays.c (SUBPIXELS): Add cast to `TPos'.
--- a/src/base/ftobjs.c
+++ b/src/base/ftobjs.c
@@ -433,6 +433,7 @@
       /* disable scaling, hinting, and transformation */
       load_flags |= FT_LOAD_NO_SCALE         |
                     FT_LOAD_NO_HINTING       |
+                    FT_LOAD_NO_BITMAP        |
                     FT_LOAD_IGNORE_TRANSFORM;
 
       /* disable bitmap rendering */
@@ -466,7 +467,8 @@
       /* XXX: This is really a temporary hack that should disappear */
       /*      promptly with FreeType 2.1!                           */
       /*                                                            */
-      if ( FT_HAS_FIXED_SIZES( face ) )
+      if ( FT_HAS_FIXED_SIZES( face ) &&
+          ( load_flags & FT_LOAD_NO_BITMAP ) == 0 )
       {
         error = driver->clazz->load_glyph( slot, face->size,
                                            glyph_index,
--- a/src/pfr/Jamfile
+++ b/src/pfr/Jamfile
@@ -10,7 +10,7 @@
 
   if $(FT2_MULTI)
   {
-    _sources = pfrdrivr  pfrgload  pfrload  pfrobjs pfrcmap ;
+    _sources = pfrdrivr  pfrgload  pfrload  pfrobjs pfrcmap pfrsbit ;
   }
   else
   {
--- a/src/pfr/pfr.c
+++ b/src/pfr/pfr.c
@@ -24,5 +24,6 @@
 #include "pfrcmap.c"
 #include "pfrobjs.c"
 #include "pfrdrivr.c"
+#include "pfrsbit.c"
 
 /* END */
--- a/src/pfr/pfrgload.c
+++ b/src/pfr/pfrgload.c
@@ -17,6 +17,7 @@
 
 
 #include "pfrgload.h"
+#include "pfrsbit.h"
 #include "pfrload.h"            /* for macro definitions */
 #include FT_INTERNAL_DEBUG_H
 
@@ -676,6 +677,9 @@
   }
 
 
+
+
+
   static FT_Error
   pfr_glyph_load_rec( PFR_Glyph  glyph,
                       FT_Stream  stream,
@@ -774,6 +778,9 @@
   Exit:
     return error;
   }
+
+
+
 
 
   FT_LOCAL_DEF( FT_Error )
--- a/src/pfr/pfrload.c
+++ b/src/pfr/pfrload.c
@@ -52,8 +52,8 @@
     FT_Error  error = 0;
     FT_Byte*  p     = *pp;
     FT_UInt   num_items, item_type, item_size;
-    
 
+
     PFR_CHECK( 1 );
     num_items = PFR_NEXT_BYTE( p );
 
@@ -62,11 +62,11 @@
       PFR_CHECK( 2 );
       item_size = PFR_NEXT_BYTE( p );
       item_type = PFR_NEXT_BYTE( p );
-      
+
       PFR_CHECK( item_size );
 
       if ( item_list )
-      {      
+      {
         PFR_ExtraItem  extra = item_list;
 
 
@@ -76,12 +76,12 @@
           {
             error = extra->parser( p, p + item_size, item_data );
             if ( error ) goto Exit;
-            
+
             break;
           }
         }
       }
-      
+
       p += item_size;
     }
 
@@ -88,7 +88,7 @@
   Exit:
     *pp = p;
     return error;
-    
+
   Too_Short:
     FT_ERROR(( "pfr_extra_items_parse: invalid extra items table\n" ));
     error = PFR_Err_Invalid_Table;
@@ -204,17 +204,17 @@
     FT_Error   error;
     FT_UInt    count;
     FT_UInt    result = 0;
-    
 
+
     if ( FT_STREAM_SEEK( section_offset ) || FT_READ_USHORT( count ) )
       goto Exit;
-    
+
     result = count;
-    
+
   Exit:
     *acount = result;
     return error;
-  }                      
+  }
 
 
   FT_LOCAL_DEF( FT_Error )
@@ -252,23 +252,23 @@
       FT_Byte*  p;
       FT_Byte*  limit;
       FT_UInt   local;
-      
 
+
       if ( FT_STREAM_SEEK( offset ) || FT_FRAME_ENTER( size ) )
         goto Exit;
 
       p     = stream->cursor;
       limit = p + size;
-      
+
       PFR_CHECK(13);
-      
+
       log_font->matrix[0] = PFR_NEXT_LONG( p );
       log_font->matrix[1] = PFR_NEXT_LONG( p );
       log_font->matrix[2] = PFR_NEXT_LONG( p );
       log_font->matrix[3] = PFR_NEXT_LONG( p );
-      
+
       flags = PFR_NEXT_BYTE( p );
-      
+
       local = 0;
       if ( flags & PFR_LOG_STROKE )
       {
@@ -275,7 +275,7 @@
         local++;
         if ( flags & PFR_LOG_2BYTE_STROKE )
           local++;
-          
+
         if ( (flags & PFR_LINE_JOIN_MASK) == PFR_LINE_JOIN_MITER )
           local += 3;
       }
@@ -293,11 +293,11 @@
         log_font->stroke_thickness = ( flags & PFR_LOG_2BYTE_STROKE )
                                      ? PFR_NEXT_SHORT( p )
                                      : PFR_NEXT_BYTE( p );
-  
+
         if ( ( flags & PFR_LINE_JOIN_MASK ) == PFR_LINE_JOIN_MITER )
           log_font->miter_limit = PFR_NEXT_LONG( p );
       }
-  
+
       if ( flags & PFR_LOG_BOLD )
       {
         log_font->bold_thickness = ( flags & PFR_LOG_2BYTE_BOLD )
@@ -304,7 +304,7 @@
                                    ? PFR_NEXT_SHORT( p )
                                    : PFR_NEXT_BYTE( p );
       }
-  
+
       if ( flags & PFR_LOG_EXTRA_ITEMS )
       {
         error = pfr_extra_items_skip( &p, limit );
@@ -326,7 +326,7 @@
 
   Exit:
     return error;
-  
+
   Too_Short:
     FT_ERROR(( "pfr_log_font_load: invalid logical font table\n" ));
     error = PFR_Err_Invalid_Table;
@@ -355,7 +355,7 @@
     FT_UInt     n, count, size1;
     FT_Error    error = 0;
 
- 
+
     PFR_CHECK( 5 );
 
     p += 3;  /* skip bctSize */
@@ -366,12 +366,12 @@
     if ( phy_font->num_strikes + count > phy_font->max_strikes )
     {
       FT_UInt  new_max = (phy_font->num_strikes + count + 3) & -4;
-      
+
       if ( FT_RENEW_ARRAY( phy_font->strikes,
                            phy_font->num_strikes,
                            new_max ) )
         goto Exit;
-        
+
       phy_font->max_strikes = new_max;
     }
 
@@ -421,15 +421,15 @@
     }
 
     phy_font->num_strikes += count;
-    
+
   Exit:
     return error;
-    
+
   Too_Short:
     error = PFR_Err_Invalid_Table;
     FT_ERROR(( "pfr_extra_item_load_bitmap_info: invalid bitmap info table\n" ));
     goto Exit;
-  }                                  
+  }
 
 
   /* load font ID, i.e. name */
@@ -441,11 +441,11 @@
     FT_Error   error  = 0;
     FT_Memory  memory = phy_font->memory;
     FT_UInt    len    = (FT_UInt)( limit - p );
-    
 
+
     if ( phy_font->font_id != NULL )
       goto Exit;
-    
+
     if ( FT_ALLOC( phy_font->font_id, len+1 ) )
       goto Exit;
 
@@ -452,7 +452,7 @@
     /* copy font ID name, and terminate it for safety */
     FT_MEM_COPY( phy_font->font_id, p, len );
     phy_font->font_id[len] = 0;
-    
+
   Exit:
     return error;
   }
@@ -472,35 +472,37 @@
 
     if ( phy_font->vertical.stem_snaps != NULL )
       goto Exit;
-    
+
     PFR_CHECK( 1 );
     count = PFR_NEXT_BYTE( p );
-    
+
     num_vert = count & 15;
     num_horz = count >> 4;
     count    = num_vert + num_horz;
-    
+
     PFR_CHECK( count * 2 );
-    
+
     if ( FT_NEW_ARRAY( snaps, count ) )
       goto Exit;
-    
+
     phy_font->vertical.stem_snaps = snaps;
     phy_font->horizontal.stem_snaps = snaps + num_vert;
-    
+
     for ( ; count > 0; count--, snaps++ )
       *snaps = FT_NEXT_SHORT( p );
-    
+
   Exit:
     return error;
-  
+
   Too_Short:
     error = PFR_Err_Invalid_Table;
     FT_ERROR(( "pfr_exta_item_load_stem_snaps: invalid stem snaps table\n" ));
     goto Exit;
-  }                                 
+  }
 
 
+
+#if 0
   /* load kerning pair data */
   FT_CALLBACK_DEF( FT_Error )
   pfr_extra_item_load_kerning_pairs( FT_Byte*     p,
@@ -516,24 +518,25 @@
     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;
 
@@ -542,10 +545,10 @@
 
     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 )
@@ -558,7 +561,7 @@
         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
@@ -569,18 +572,112 @@
       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
+  /* 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;
 
+    FT_TRACE2(( "pfr_extra_item_load_kerning_pairs()\n" ));
 
+    if ( FT_NEW( item ) )
+      goto Exit;
+
+    PFR_CHECK( 4 );
+
+    item->pair_count = PFR_NEXT_BYTE( p );
+    item->base_adj   = PFR_NEXT_SHORT( p );
+    item->flags      = PFR_NEXT_BYTE( p );
+    item->offset     = phy_font->offset + ( p - phy_font->cursor );
+
+#ifndef PFR_CONFIG_NO_CHECKS
+    item->pair_size = 3;
+
+    if ( item->flags & PFR_KERN_2BYTE_CHAR )
+      item->pair_size += 2;
+
+    if ( item->flags & PFR_KERN_2BYTE_ADJ )
+      item->pair_size += 1;
+
+    PFR_CHECK( item->pair_count * item->pair_size );
+#endif
+
+    /* load first and last pairs into the item to speed up */
+    /* lookup later...                                     */
+    if ( item->pair_count > 0 )
+    {
+      FT_UInt   char1, char2;
+      FT_Byte*  q;
+
+      if ( item->flags & PFR_KERN_2BYTE_CHAR )
+      {
+        q     = p;
+        char1 = PFR_NEXT_USHORT(q);
+        char2 = PFR_NEXT_USHORT(q);
+
+        item->pair1 = PFR_KERN_INDEX(char1,char2);
+
+        q = p + item->pair_size*(item->pair_count-1);
+        char1 = PFR_NEXT_USHORT(q);
+        char2 = PFR_NEXT_USHORT(q);
+
+        item->pair2 = PFR_KERN_INDEX(char1,char2);
+      }
+      else
+      {
+        q     = p;
+        char1 = PFR_NEXT_BYTE(q);
+        char2 = PFR_NEXT_BYTE(q);
+
+        item->pair1 = PFR_KERN_INDEX(char1,char2);
+
+        q = p + item->pair_size*(item->pair_count-1);
+        char1 = PFR_NEXT_BYTE(q);
+        char2 = PFR_NEXT_BYTE(q);
+
+        item->pair2 = PFR_KERN_INDEX(char1,char2);
+      }
+
+      /* add new item to the current list */
+      item->next                 = NULL;
+      *phy_font->kern_items_tail = item;
+      phy_font->kern_items_tail  = &item->next;
+      phy_font->num_kern_pairs  += item->pair_count;
+    }
+    else
+    {
+      /* empty item !! */
+      FT_FREE( item );
+    }
+
+  Exit:
+    return error;
+
+  Too_Short:
+    FT_FREE( item );
+
+    error = PFR_Err_Invalid_Table;
+    FT_ERROR(( "pfr_extra_item_load_kerning_pairs: "
+               "invalid kerning pairs table\n" ));
+    goto Exit;
+  }
+#endif
+
   static const PFR_ExtraItemRec  pfr_phy_font_extra_items[] =
   {
     { 1, (PFR_ExtraItem_ParseFunc) pfr_extra_item_load_bitmap_info },
@@ -607,7 +704,7 @@
     FT_FREE( phy_font->strikes );
     phy_font->num_strikes = 0;
     phy_font->max_strikes = 0;
-  
+
     FT_FREE( phy_font->chars );
     phy_font->num_chars    = 0;
     phy_font->chars_offset = 0;
@@ -615,11 +712,23 @@
     FT_FREE( phy_font->blue_values );
     phy_font->num_blue_values = 0;
 
-    FT_FREE( phy_font->kern_pairs );
+    {
+      PFR_KernItem  item, next;
+
+      item = phy_font->kern_items;
+      while (item)
+      {
+        next = item->next;
+        FT_FREE( item );
+        item = next;
+      }
+      phy_font->kern_items      = NULL;
+      phy_font->kern_items_tail = NULL;
+    }
     phy_font->num_kern_pairs = 0;
   }
-  
 
+
   FT_LOCAL_DEF( FT_Error )
   pfr_phy_font_load( PFR_PhyFont  phy_font,
                      FT_Stream    stream,
@@ -636,9 +745,14 @@
     phy_font->memory = memory;
     phy_font->offset = offset;
 
+    phy_font->kern_items      = NULL;
+    phy_font->kern_items_tail = &phy_font->kern_items;
+
     if ( FT_STREAM_SEEK( offset ) || FT_FRAME_ENTER( size ) )
       goto Exit;
 
+    phy_font->cursor = stream->cursor;
+
     p     = stream->cursor;
     limit = p + size;
 
@@ -664,15 +778,15 @@
     {
       error =  pfr_extra_items_parse( &p, limit,
                                       pfr_phy_font_extra_items, phy_font );
-        
+
       if ( error )
         goto Fail;
     }
-    
+
     /* skip the aux bytes */
     PFR_CHECK( 3 );
     num_aux = PFR_NEXT_ULONG( p );
-    
+
     PFR_CHECK( num_aux );
     p += num_aux;
 
@@ -684,7 +798,7 @@
       phy_font->num_blue_values = count = PFR_NEXT_BYTE( p );
 
       PFR_CHECK( count * 2 );
-      
+
       if ( FT_NEW_ARRAY( phy_font->blue_values, count ) )
         goto Fail;
 
@@ -713,19 +827,19 @@
       Size = 1 + 1 + 2;
       if ( flags & PFR_PHY_2BYTE_CHARCODE )
         Size += 1;
-      
+
       if ( flags & PFR_PHY_PROPORTIONAL )
         Size += 2;
-      
+
       if ( flags & PFR_PHY_ASCII_CODE )
         Size += 1;
-        
+
       if ( flags & PFR_PHY_2BYTE_GPS_SIZE )
         Size += 1;
-        
+
       if ( flags & PFR_PHY_3BYTE_GPS_OFFSET )
         Size += 1;
-      
+
       PFR_CHECK( count * Size );
 
       for ( n = 0; n < count; n++ )
@@ -763,9 +877,13 @@
   Fail:
     FT_FRAME_EXIT();
 
+    /* save position of bitmap info */
+    phy_font->bct_offset = FT_STREAM_POS();
+    phy_font->cursor     = NULL;
+
   Exit:
     return error;
-  
+
   Too_Short:
     error = PFR_Err_Invalid_Table;
     FT_ERROR(( "pfr_phy_font_load: invalid physical font table\n" ));
--- a/src/pfr/pfrobjs.c
+++ b/src/pfr/pfrobjs.c
@@ -20,6 +20,7 @@
 #include "pfrload.h"
 #include "pfrgload.h"
 #include "pfrcmap.h"
+#include "pfrsbit.h"
 #include FT_OUTLINE_H
 #include FT_INTERNAL_DEBUG_H
 
@@ -129,8 +130,12 @@
        else
          root->face_flags |= FT_FACE_FLAG_HORIZONTAL;
 
-       /* XXX: kerning and embedded bitmap support isn't there yet */
+       if ( phy_font->num_strikes > 0 )
+         root->face_flags |= FT_FACE_FLAG_FIXED_SIZES;
 
+       if ( phy_font->num_kern_pairs > 0 )
+         root->face_flags |= FT_FACE_FLAG_KERNING;
+
        root->family_name = phy_font->font_id;
        root->style_name  = NULL;  /* no style name in font file */
 
@@ -242,6 +247,14 @@
     /* check that the glyph index is correct */
     FT_ASSERT( gindex < face->phy_font.num_chars );
 
+    /* try to load an embedded bitmap */
+    if ( (load_flags & (FT_LOAD_NO_SCALE | FT_LOAD_NO_BITMAP)) == 0 )
+    {
+      error = pfr_slot_load_bitmap( slot, size, gindex );
+      if ( error == 0 )
+        goto Exit;
+    }
+
     gchar               = face->phy_font.chars + gindex;
     slot->root.format   = FT_GLYPH_FORMAT_OUTLINE;
     outline->n_points   = 0;
@@ -325,6 +338,7 @@
       metrics->horiBearingY = cbox.yMax - metrics->height;
     }
 
+  Exit:
     return error;
   }
 
@@ -341,9 +355,7 @@
           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 )
-
+#if 0
   /* find the kerning for a given glyph pair */
   FT_LOCAL_DEF( FT_Error )
   pfr_face_get_kerning( PFR_Face    face,
@@ -386,5 +398,87 @@
   Exit:
     return 0;
   }
+#else
+  /* 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 )
+  {
+    FT_Error      error;
+    PFR_PhyFont   phy_font = &face->phy_font;
+    PFR_KernItem  item     = phy_font->kern_items;
+    FT_UInt32     idx      = PFR_KERN_INDEX( glyph1, glyph2 );
+
+    kerning->x = 0;
+    kerning->y = 0;
+
+    /* find the kerning item containing our pair */
+    while ( item )
+    {
+      if ( item->pair1 <= idx && idx <= item->pair2 )
+        goto Found_Item;
+
+      item = item->next;
+    }
+
+    /* not found */
+    goto Exit;
+
+  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 ) )
+        goto Exit;
+
+      min = 0;
+      max = item->pair_count;
+      while ( min < max )
+      {
+        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;
+      }
+
+      FT_FRAME_EXIT();
+    }
+
+  Exit:
+    return 0;
+  }
+#endif
 
 /* END */
--- /dev/null
+++ b/src/pfr/pfrsbit.c
@@ -1,0 +1,629 @@
+#include "pfrsbit.h"
+#include "pfrload.h"
+#include FT_INTERNAL_DEBUG_H
+#include FT_INTERNAL_STREAM_H
+
+#include "pfrerror.h"
+
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_pfr
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*****                                                               *****/
+  /*****                      PFR BIT WRITER                           *****/
+  /*****                                                               *****/
+  /*************************************************************************/
+  /*************************************************************************/
+
+  typedef  struct PFR_BitWriter_
+  {
+    FT_Byte*  line;      /* current line start                    */
+    FT_Int    pitch;     /* line size in bytes                    */
+    FT_Int    width;     /* width in pixels/bits                  */
+    FT_Int    rows;      /* number of remaining rows to scan      */
+    FT_Int    total;     /* total number of bits to draw          */
+
+  } PFR_BitWriterRec, *PFR_BitWriter;
+
+
+  static void
+  pfr_bitwriter_init( PFR_BitWriter  writer,
+                      FT_Bitmap*     target,
+                      FT_Bool        decreasing )
+  {
+    writer->line   = target->buffer;
+    writer->pitch  = target->pitch;
+    writer->width  = target->width;
+    writer->rows   = target->rows;
+    writer->total  = writer->width * writer->rows;
+
+    if ( !decreasing )
+    {
+      writer->line += writer->pitch * ( target->rows-1 );
+      writer->pitch = -writer->pitch;
+    }
+  }
+
+
+  static void
+  pfr_bitwriter_decode_bytes( PFR_BitWriter  writer,
+                              FT_Byte*       p,
+                              FT_Byte*       limit )
+  {
+    FT_Int    n, reload;
+    FT_Int    left = writer->width;
+    FT_Byte*  cur  = writer->line;
+    FT_UInt   mask = 0x80;
+    FT_UInt   val  = 0;
+    FT_UInt   c    = 0;
+
+    n = (FT_Int)(limit - p)*8;
+    if ( n > writer->total )
+      n = writer->total;
+
+    reload = n & 7;
+
+    for ( ; n > 0; n-- )
+    {
+      if ( (n & 7) == reload )
+        val = *p++;
+
+      if ( val & 0x80 )
+        c |= mask;
+
+      val  <<= 1;
+      mask >>= 1;
+
+      if ( --left <= 0 )
+      {
+        cur[0] = (FT_Byte) c;
+        left   = writer->width;
+        mask   = 0x80;
+
+        writer->line += writer->pitch;
+        cur           = writer->line;
+        c             = 0;
+      }
+      else if ( mask == 0 )
+      {
+        cur[0] = c;
+        mask   = 0x80;
+        c      = 0;
+        cur ++;
+      }
+    }
+
+    if ( mask != 0x80 )
+      cur[0] = c;
+  }
+
+
+  static void
+  pfr_bitwriter_decode_rle1( PFR_BitWriter  writer,
+                             FT_Byte*       p,
+                             FT_Byte*       limit )
+  {
+    FT_Int    n, phase, count, counts[2], reload;
+    FT_Int    left = writer->width;
+    FT_Byte*  cur  = writer->line;
+    FT_UInt   mask = 0x80;
+    FT_UInt   c    = 0;
+
+    n = writer->total;
+
+    phase     = 1;
+    counts[0] = 0;
+    counts[1] = 0;
+    count     = 0;
+    reload    = 1;
+
+    for ( ; n > 0; n-- )
+    {
+      if ( reload )
+      {
+        do
+        {
+          if ( phase )
+          {
+            FT_Int  v;
+
+            if ( p >= limit )
+              break;
+
+            v         = *p++;
+            counts[0] = (v >> 4);
+            counts[1] = (v & 15);
+            phase     = 0;
+            count     = counts[0];
+          }
+          else
+          {
+            phase = 1;
+            count = counts[1];
+          }
+        }
+        while ( count == 0 );
+      }
+
+      if ( phase )
+        c |= mask;
+
+      mask >>= 1;
+
+      if ( --left <= 0 )
+      {
+        cur[0] = (FT_Byte) c;
+        left   = writer->width;
+        mask   = 0x80;
+
+        writer->line += writer->pitch;
+        cur           = writer->line;
+        c             = 0;
+      }
+      else if ( mask == 0 )
+      {
+        cur[0] = c;
+        mask   = 0x80;
+        c      = 0;
+        cur ++;
+      }
+
+      reload = ( --count <= 0 );
+    }
+
+    if ( mask != 0x80 )
+      cur[0] = (FT_Byte) c;
+  }
+
+
+  static void
+  pfr_bitwriter_decode_rle2( PFR_BitWriter  writer,
+                             FT_Byte*       p,
+                             FT_Byte*       limit )
+  {
+    FT_Int    n, phase, count, reload;
+    FT_Int    left = writer->width;
+    FT_Byte*  cur  = writer->line;
+    FT_UInt   mask = 0x80;
+    FT_UInt   c    = 0;
+
+    n = writer->total;
+
+    phase     = 1;
+    count     = 0;
+    reload    = 1;
+
+    for ( ; n > 0; n-- )
+    {
+      if ( reload )
+      {
+        do
+        {
+          if ( p >= limit )
+            break;
+
+          count = *p++;
+          phase = phase ^ 1;
+        }
+        while ( count == 0 );
+      }
+
+      if ( phase )
+        c |= mask;
+
+      mask >>= 1;
+
+      if ( --left <= 0 )
+      {
+        cur[0] = (FT_Byte) c;
+        c      = 0;
+        mask   = 0x80;
+        left   = writer->width;
+
+        writer->line += writer->pitch;
+        cur           = writer->line;
+      }
+      else if ( mask == 0 )
+      {
+        cur[0] = c;
+        c      = 0;
+        mask   = 0x80;
+        cur ++;
+      }
+
+      reload = ( --count <= 0 );
+    }
+
+    if ( mask != 0x80 )
+      cur[0] = (FT_Byte) c;
+  }
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*****                                                               *****/
+  /*****                  BITMAP DATA DECODING                         *****/
+  /*****                                                               *****/
+  /*************************************************************************/
+  /*************************************************************************/
+
+  static void
+  pfr_lookup_bitmap_data( FT_Byte*    base,
+                          FT_Byte*    limit,
+                          FT_Int      count,
+                          FT_Byte     flags,
+                          FT_UInt     char_code,
+                          FT_ULong*   found_offset,
+                          FT_ULong*   found_size )
+  {
+    FT_UInt    left, right, char_len;
+    FT_Bool    two = (flags & 1);
+    FT_Byte*   buff;
+
+    char_len = 4;
+    if ( two )      char_len += 1;
+    if ( flags & 2) char_len += 1;
+    if ( flags & 4) char_len += 1;
+
+    left      = 0;
+    right     = count;
+
+    while ( left < right )
+    {
+      FT_UInt  middle, code;
+
+      middle = (left + right) >> 1;
+      buff   = base + middle*char_len;
+
+      /* check that we're not outside of the table */
+      /* this is possible with broken fonts...     */
+      if ( buff + char_len > limit )
+        goto Fail;
+
+      if (two) code = PFR_NEXT_USHORT(buff);
+         else  code = PFR_NEXT_BYTE(buff);
+
+      if ( code == char_code )
+        goto Found_It;
+
+      if ( code < char_code )
+        left = middle;
+      else
+        right = middle;
+    }
+
+  Fail:
+    /* Not found */
+    *found_size   = 0;
+    *found_offset = 0;
+    return;
+
+  Found_It:
+    if (flags & 2) *found_size = PFR_NEXT_USHORT(buff);
+              else *found_size = PFR_NEXT_BYTE(buff);
+
+    if (flags & 4) *found_offset = PFR_NEXT_ULONG(buff);
+              else *found_offset = PFR_NEXT_USHORT(buff);
+  }
+
+
+ /* load bitmap metrics. "*padvance" must be set to the default value */
+ /* before calling this function...                                   */
+ /*                                                                   */
+  static FT_Error
+  pfr_load_bitmap_metrics( FT_Byte** pdata,
+                           FT_Byte*  limit,
+                           FT_Long   scaled_advance,
+                           FT_Long  *axpos,
+                           FT_Long  *aypos,
+                           FT_UInt  *axsize,
+                           FT_UInt  *aysize,
+                           FT_Long  *aadvance,
+                           FT_UInt  *aformat )
+  {
+    FT_Error  error = 0;
+    FT_Byte    flags;
+    FT_Char    b;
+    FT_Byte*   p = *pdata;
+    FT_Long    xpos, ypos, advance;
+    FT_UInt    xsize, ysize;
+
+    PFR_CHECK(1);
+    flags = PFR_NEXT_BYTE(p);
+
+    xpos    = 0;
+    ypos    = 0;
+    xsize   = 0;
+    ysize   = 0;
+    advance = 0;
+
+    switch (flags & 3)
+    {
+      case 0:
+        PFR_CHECK(1);
+        b    = PFR_NEXT_INT8(p);
+        xpos = b >> 4;
+        ypos = ((FT_Char)(b << 4)) >> 4;
+        break;
+
+      case 1:
+        PFR_CHECK(2);
+        xpos = PFR_NEXT_INT8(p);
+        ypos = PFR_NEXT_INT8(p);
+        break;
+
+      case 2:
+        PFR_CHECK(4);
+        xpos = PFR_NEXT_SHORT(p);
+        ypos = PFR_NEXT_SHORT(p);
+        break;
+
+      case 3:
+        PFR_CHECK(6);
+        xpos = PFR_NEXT_LONG(p);
+        ypos = PFR_NEXT_LONG(p);
+        break;
+
+      default:
+        ;
+    }
+
+    flags >>= 2;
+    switch (flags & 3)
+    {
+      case 0:
+        /* blank image */
+        xsize = 0;
+        ysize = 0;
+        break;
+
+      case 1:
+        PFR_CHECK(1);
+        b     = PFR_NEXT_BYTE(p);
+        xsize = (b >> 4) & 0xF;
+        ysize =  b & 0xF;
+        break;
+
+      case 2:
+        PFR_CHECK(2);
+        xsize = PFR_NEXT_BYTE(p);
+        ysize = PFR_NEXT_BYTE(p);
+        break;
+
+      case 3:
+        PFR_CHECK(4);
+        xsize = PFR_NEXT_USHORT(p);
+        ysize = PFR_NEXT_USHORT(p);
+        break;
+
+      default:
+        ;
+    }
+
+    flags >>= 2;
+    switch (flags & 3)
+    {
+      case 0:
+       advance = scaled_advance;
+       break;
+
+      case 1:
+        PFR_CHECK(1);
+        advance = PFR_NEXT_INT8(p) << 8;
+        break;
+
+      case 2:
+        PFR_CHECK(2);
+        advance = PFR_NEXT_SHORT(p);
+        break;
+
+      case 3:
+        PFR_CHECK(3);
+        advance = PFR_NEXT_LONG(p);
+        break;
+
+      default:
+        ;
+    }
+
+    *axpos    = xpos;
+    *aypos    = ypos;
+    *axsize   = xsize;
+    *aysize   = ysize;
+    *aadvance = advance;
+    *aformat  = flags >> 2;
+    *pdata    = p;
+
+  Exit:
+    return error;
+
+  Too_Short:
+    error = PFR_Err_Invalid_Table;
+    FT_ERROR(( "pfr_load_bitmap_metrics: invalid glyph data\n" ));
+    goto Exit;
+  }
+
+
+  static FT_Error
+  pfr_load_bitmap_bits( FT_Byte*        p,
+                        FT_Byte*        limit,
+                        FT_UInt         format,
+                        FT_UInt         decreasing,
+                        FT_Bitmap*      target )
+  {
+    FT_Error          error = 0;
+    PFR_BitWriterRec  writer;
+
+    if ( target->rows > 0 && target->width > 0 )
+    {
+      pfr_bitwriter_init( &writer, target, decreasing );
+
+      switch (format)
+      {
+        case 0: /* packed bits */
+          pfr_bitwriter_decode_bytes( &writer, p, limit );
+          break;
+
+        case 1: /* RLE1 */
+          pfr_bitwriter_decode_rle1( &writer, p, limit );
+          break;
+
+        case 2: /* RLE2 */
+          pfr_bitwriter_decode_rle2( &writer, p, limit );
+          break;
+
+        default:
+          FT_ERROR(( "pfr_read_bitmap_data: invalid image type\n" ));
+          error = FT_Err_Invalid_File_Format;
+      }
+    }
+
+    return error;
+  }
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*****                                                               *****/
+  /*****                     BITMAP LOADING                            *****/
+  /*****                                                               *****/
+  /*************************************************************************/
+  /*************************************************************************/
+
+  FT_LOCAL( FT_Error )
+  pfr_slot_load_bitmap( PFR_Slot  glyph,
+                        PFR_Size  size,
+                        FT_UInt   glyph_index )
+  {
+    FT_Error     error;
+    PFR_Face     face   = (PFR_Face) glyph->root.face;
+    FT_Stream    stream = face->root.stream;
+    PFR_PhyFont  phys   = &face->phy_font;
+    FT_ULong     gps_offset;
+    FT_ULong     gps_size;
+    PFR_Char     character;
+    PFR_Strike   strike;
+
+    character = &phys->chars[glyph_index];
+
+    /* Look-up a bitmap strike corresponding to the current */
+    /* character dimensions                                 */
+
+    {
+      FT_UInt     n;
+
+      strike = phys->strikes;
+      for ( n = 0; n < phys->num_strikes; n++ )
+      {
+        if ( strike->x_ppm == (FT_UInt) size->root.metrics.x_ppem &&
+             strike->y_ppm == (FT_UInt) size->root.metrics.y_ppem )
+        {
+          goto Found_Strike;
+        }
+        strike++;
+      }
+
+      /* couldn't find it */
+      return FT_Err_Invalid_Argument;
+    }
+
+  Found_Strike:
+
+    /* Now lookup the glyph's position within the file */
+    {
+      FT_UInt   char_len;
+
+      char_len = 4;
+      if ( strike->flags & 1 ) char_len += 1;
+      if ( strike->flags & 2 ) char_len += 1;
+      if ( strike->flags & 4 ) char_len += 1;
+
+      /* Access data directly in the frame to speed lookups */
+      if ( FT_STREAM_SEEK( phys->bct_offset + strike->bct_offset ) ||
+           FT_FRAME_ENTER( char_len * strike->num_bitmaps )       )
+        goto Exit;
+
+      pfr_lookup_bitmap_data( stream->cursor,
+                              stream->limit,
+                              strike->num_bitmaps,
+                              strike->flags,
+                              character->char_code,
+                              &gps_offset,
+                              &gps_size );
+
+      FT_FRAME_EXIT();
+
+      if (gps_size == 0)
+      {
+        /* Could not find a bitmap program string for this glyph */
+        error = FT_Err_Invalid_Argument;
+        goto Exit;
+      }
+    }
+
+    /* get the bitmap metrics */
+    {
+      FT_Long   xpos, ypos, advance;
+      FT_UInt   xsize, ysize, format;
+      FT_Byte*  p;
+
+      advance = FT_MulDiv( size->root.metrics.x_ppem << 8,
+                           character->advance,
+                           phys->metrics_resolution );
+
+      /* XXX: handle linearHoriAdvance correctly !! */
+
+      if ( FT_STREAM_SEEK( face->header.gps_section_offset + gps_offset ) ||
+           FT_FRAME_ENTER( gps_size )                             )
+        goto Exit;
+
+      p     = stream->cursor;
+      error = pfr_load_bitmap_metrics( &p, stream->limit,
+                                       advance,
+                                       &xpos, &ypos,
+                                       &xsize, &ysize,
+                                       &advance, &format );
+      if ( !error )
+      {
+        glyph->root.format = FT_GLYPH_FORMAT_BITMAP;
+      
+        /* Set up glyph bitmap and metrics */
+        glyph->root.bitmap.width      = (FT_Int) xsize;
+        glyph->root.bitmap.rows       = (FT_Int) ysize;
+        glyph->root.bitmap.pitch      = (FT_Long)(xsize+7) >> 3;
+        glyph->root.bitmap.pixel_mode = FT_PIXEL_MODE_MONO;
+
+        glyph->root.metrics.width        = (FT_Long)xsize << 6;
+        glyph->root.metrics.height       = (FT_Long)ysize << 6;
+        glyph->root.metrics.horiBearingX = xpos << 6;
+        glyph->root.metrics.horiBearingY = ypos << 6;
+        glyph->root.metrics.horiAdvance  = ((advance >> 2) + 32) & -64;
+        glyph->root.metrics.vertBearingX = - glyph->root.metrics.width >> 1;
+        glyph->root.metrics.vertBearingY = 0;
+        glyph->root.metrics.vertAdvance  = size->root.metrics.height;
+
+        glyph->root.bitmap_left = xpos;
+        glyph->root.bitmap_top  = ypos + ysize;
+
+        /* Allocate and read bitmap data */
+        {
+          FT_Memory  memory = face->root.memory;
+          FT_Long    len    = glyph->root.bitmap.pitch*ysize;
+
+          if ( !FT_ALLOC( glyph->root.bitmap.buffer, len ) )
+          {
+            error = pfr_load_bitmap_bits( p,
+                                          stream->limit,
+                                          format,
+                                          (face->header.color_flags & 2),
+                                          &glyph->root.bitmap );
+          }
+        }
+      }
+      FT_FRAME_EXIT();
+    }
+
+  Exit:
+    return error;
+  }
--- /dev/null
+++ b/src/pfr/pfrsbit.h
@@ -1,0 +1,32 @@
+/***************************************************************************/
+/*                                                                         */
+/*  pfrsbit.c                                                              */
+/*                                                                         */
+/*    FreeType PFR bitmap loader                                           */
+/*                                                                         */
+/*  Copyright 2002 by                                                      */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+#ifndef __PFRSBIT_H__
+#define __PFRSBIT_H__
+
+#include "pfrobjs.h"
+
+FT_BEGIN_HEADER
+
+  FT_LOCAL( FT_Error )
+  pfr_slot_load_bitmap( PFR_Slot  glyph,
+                        PFR_Size  size,
+                        FT_UInt   glyph_index );
+
+FT_END_HEADER
+
+#endif /* __PFR_SBIT_H__ */
--- a/src/pfr/pfrtypes.h
+++ b/src/pfr/pfrtypes.h
@@ -52,19 +52,19 @@
     FT_UInt    max_blue_values;
     FT_UInt    max_x_orus;
     FT_UInt    max_y_orus;
-    
+
     FT_UInt    phy_font_max_size_high;
     FT_UInt    color_flags;
-    
+
     FT_UInt32  bct_max_size;
-    FT_UInt32  bct_set_max_size;        
+    FT_UInt32  bct_set_max_size;
     FT_UInt32  phy_bct_set_max_size;
-    
+
     FT_UInt    num_phy_fonts;
     FT_UInt    max_vert_stem_snap;
     FT_UInt    max_horz_stem_snap;
     FT_UInt    max_chars;
-  
+
   } PFR_HeaderRec, *PFR_Header;
 
 
@@ -73,7 +73,7 @@
   {
     PFR_FLAG_BLACK_PIXEL   = 1,
     PFR_FLAG_INVERT_BITMAP = 2
-  
+
   } PFR_HeaderFlags;
 
 
@@ -83,16 +83,16 @@
   {
     FT_UInt32  size;
     FT_UInt32  offset;
-    
+
     FT_Int32   matrix[4];
     FT_UInt    stroke_flags;
     FT_Int     stroke_thickness;
     FT_Int     bold_thickness;
     FT_Int32   miter_limit;
-    
+
     FT_UInt32  phys_size;
     FT_UInt32  phys_offset;
-  
+
   } PFR_LogFontRec, *PFR_LogFont;
 
 
@@ -104,7 +104,7 @@
     PFR_LOG_2BYTE_STROKE = 8,
     PFR_LOG_STROKE       = 4,
     PFR_LINE_JOIN_MASK   = 3
-    
+
   } PFR_LogFlags;
 
 
@@ -113,7 +113,7 @@
     PFR_LINE_JOIN_MITER = 0,
     PFR_LINE_JOIN_ROUND = 1,
     PFR_LINE_JOIN_BEVEL = 2
-    
+
   } PFR_LineJoinFlags;
 
 
@@ -124,7 +124,7 @@
     PFR_BITMAP_3BYTE_OFFSET   = 4,
     PFR_BITMAP_2BYTE_SIZE     = 2,
     PFR_BITMAP_2BYTE_CHARCODE = 1
-  
+
   } PFR_BitmapFlags;
 
 
@@ -133,7 +133,7 @@
     FT_UInt    char_code;
     FT_UInt    gps_size;
     FT_UInt32  gps_offset;
-  
+
   } PFR_BitmapCharRec, *PFR_BitmapChar;
 
 
@@ -153,17 +153,17 @@
     FT_UInt         x_ppm;
     FT_UInt         y_ppm;
     FT_UInt         flags;
-    
+
     FT_UInt32       gps_size;
     FT_UInt32       gps_offset;
-    
+
     FT_UInt32       bct_size;
     FT_UInt32       bct_offset;
-    
+
     /* optional */
     FT_UInt         num_bitmaps;
     PFR_BitmapChar  bitmaps;
-    
+
   } PFR_StrikeRec, *PFR_Strike;
 
 
@@ -175,7 +175,7 @@
     FT_Int     advance;
     FT_UInt    gps_size;
     FT_UInt32  gps_offset;
-  
+
   } PFR_CharRec, *PFR_Char;
 
 
@@ -186,11 +186,27 @@
     FT_UInt  standard;
     FT_UInt  num_stem_snaps;
     FT_Int*  stem_snaps;
-  
+
   } PFR_DimensionRec, *PFR_Dimension;
 
   /************************************************************************/
 
+  typedef struct PFR_KernItemRec_*  PFR_KernItem;
+  typedef struct PFR_KernItemRec_
+  {
+    PFR_KernItem  next;
+    FT_UInt       pair_count;
+    FT_UInt       pair_size;
+    FT_Int        base_adj;
+    FT_UInt       flags;
+    FT_UInt32     offset;
+    FT_UInt32     pair1;
+    FT_UInt32     pair2;
+
+  } PFR_KernItemRec;
+
+#define PFR_KERN_INDEX( g1, g2 )  ( ( (FT_UInt32)(g1) << 16 ) | (FT_UInt16)(g2) )
+
   typedef struct  PFR_KernPairRec_
   {
     FT_UInt    glyph1;
@@ -212,7 +228,7 @@
     FT_BBox            bbox;
     FT_UInt            flags;
     FT_UInt            standard_advance;
-    
+
     PFR_DimensionRec   horizontal;
     PFR_DimensionRec   vertical;
 
@@ -221,19 +237,24 @@
     FT_UInt            num_strikes;
     FT_UInt            max_strikes;
     PFR_StrikeRec*     strikes;
-    
+
     FT_UInt            num_blue_values;
     FT_Int            *blue_values;
     FT_UInt            blue_fuzz;
     FT_UInt            blue_scale;
-    
+
     FT_UInt            num_chars;
     FT_UInt32          chars_offset;
     PFR_Char           chars;
 
     FT_UInt            num_kern_pairs;
-    PFR_KernPairRec   *kern_pairs;
+    PFR_KernItem       kern_items;
+    PFR_KernItem*      kern_items_tail;
 
+    /* not part of the spec, but used during load */
+    FT_UInt32          bct_offset;
+    FT_Byte*           cursor;
+
   } PFR_PhyFontRec, *PFR_PhyFont;
 
 
@@ -254,7 +275,7 @@
   {
     PFR_KERN_2BYTE_ADJ   = 0x01,
     PFR_KERN_2BYTE_CHAR  = 0x02
-  
+
   } PFR_KernFlags;
 
 
@@ -267,7 +288,7 @@
     PFR_GLYPH_1BYTE_XYCOUNT = 0x04,
     PFR_GLYPH_XCOUNT        = 0x02,
     PFR_GLYPH_YCOUNT        = 0x01
-    
+
   } PFR_GlyphFlags;
 
 
@@ -276,7 +297,7 @@
   {
     FT_UInt  org;
     FT_UInt  cur;
-  
+
   } PFR_CoordRec, *PFR_Coord;
 
 
@@ -288,7 +309,7 @@
     FT_Int     y_delta;
     FT_UInt32  gps_offset;
     FT_UInt    gps_size;
-  
+
   } PFR_SubGlyphRec, *PFR_SubGlyph;
 
 
@@ -298,7 +319,7 @@
     PFR_SUBGLYPH_2BYTE_SIZE   = 0x40,
     PFR_SUBGLYPH_YSCALE       = 0x20,
     PFR_SUBGLYPH_XSCALE       = 0x10
-    
+
   } PFR_SubGlyphFlags;
 
 
@@ -305,7 +326,7 @@
   typedef struct  PFR_GlyphRec_
   {
     FT_Byte           format;
-    
+
     FT_UInt           num_x_control;
     FT_UInt           num_y_control;
     FT_UInt           max_xy_control;
@@ -316,10 +337,10 @@
     FT_UInt           num_subs;
     FT_UInt           max_subs;
     PFR_SubGlyphRec*  subs;
-    
+
     FT_GlyphLoader    loader;
     FT_Bool           path_begun;
-    
+
   } PFR_GlyphRec, *PFR_Glyph;
 
 
--- a/src/sfnt/ttcmap0.c
+++ b/src/sfnt/ttcmap0.c
@@ -597,9 +597,18 @@
     FT_Byte   *ends, *starts, *offsets, *deltas, *glyph_ids;
     FT_UInt   num_segs;
 
-
-    if ( table + length > valid->limit || length < 16 )
+    /* in certain fonts, the 'length' field is invalid and goes */
+    /* out of bound. We try to correct this here...             */
+    if ( length < 16 )
       FT_INVALID_TOO_SHORT;
+
+    if ( table + length > valid->limit )
+    {
+      if ( valid->level >= FT_VALIDATE_TIGHT )
+        FT_INVALID_TOO_SHORT;
+
+      length = (FT_UInt)( valid->limit - table );
+    }
 
     p        = table + 6;
     num_segs = TT_NEXT_USHORT( p );   /* read segCountX2 */
--- a/src/tools/docmaker/content.py
+++ b/src/tools/docmaker/content.py
@@ -132,7 +132,7 @@
                 m = re_code_end.match( l )
                 if m and len(m.group(1)) <= margin:
                     # that's it, we finised the code sequence
-                    code = DocCode( margin, cur_lines )
+                    code = DocCode( 0, cur_lines )
                     self.items.append( code )
                     margin    = -1
                     cur_lines = []
@@ -289,9 +289,9 @@
                 self.description = block.get_markup_items( "description" )
                 self.order       = block.get_markup_words( "order" )
                 return
-                
+
     def reorder( self ):
-        
+
         self.block_names = sort_order_list( self.block_names, self.order )
 
 
@@ -300,7 +300,7 @@
     def __init__( self ):
         """initialize a block content processor"""
         self.reset()
-        
+
         self.sections = {}    # dictionary of documentation sections
         self.section  = None  # current documentation section
 
@@ -379,7 +379,7 @@
         blocks = source_processor.blocks
         count  = len(blocks)
         for n in range(count):
-            
+
             source = blocks[n]
             if source.content:
                 # this is a documentation comment, we need to catch
@@ -392,8 +392,8 @@
                     m = m+1
 
                 doc_block = DocBlock( source, follow, self )
-    
-    
+
+
     def  finish( self ):
 
         # process all sections to extract their abstract, description
@@ -430,13 +430,13 @@
             chap = DocChapter( None )
             chap.sections = others
             self.chapters.append( chap )
-            
 
 
+
 class DocBlock:
 
     def __init__( self, source, follow, processor ):
-        
+
         processor.reset()
 
         self.source    = source
@@ -451,8 +451,8 @@
             self.type = self.markups[0].tag
         except:
             pass
-        
-            
+
+
         # compute block name from first markup paragraph
         try:
             markup = self.markups[0]
@@ -492,7 +492,7 @@
         # now strip the leading and trailing empty lines from the sources
         start = 0
         end   = len( source )-1
-        
+
         while start < end and not string.strip( source[start] ):
             start = start + 1
 
--- a/src/tools/docmaker/sources.py
+++ b/src/tools/docmaker/sources.py
@@ -10,7 +10,7 @@
 #     "<Function>", "<Type>", etc..
 #
 # the routines used to process the content of documentation blocks
-# are not contained here, but in "doccontent.py"
+# are not contained here, but in "content.py"
 #
 # the classes and methods found here only deal with text parsing
 # and basic documentation block extraction
@@ -76,11 +76,11 @@
 #
 # format 2 documentation comment blocks look like the following:
 #
-#    /************************************
+#    /************************************ (at least 2 asterisks)
 #     *
-#     *                                                                    
-#     *                                                                    
-#     *                                                                    
+#     *
+#     *
+#     *
 #     **/       (1 or more asterisks at the end)
 #
 # we define a few regular expressions here to detect them
@@ -94,12 +94,12 @@
 column = r'''
   \s*         # any number of whitespace
   \*{1}       # followed by precisely one asterisk
-  (.*)        # followed by anything (group1)
+  (.*)        # then anything (group1)
 '''
 
 end = r'''
   \s*     # any number of whitespace
-  \*+/    # followed by at least on asterisk, then '/'
+  \*+/    # followed by at least one asterisk, then '/'
 '''
 
 re_source_block_format2 = SourceBlockFormat( 2, start, column, end )
@@ -151,7 +151,7 @@
 #
 # a list of reserved source keywords
 #
-re_source_keywords = re.compile( '''( typedef | 
+re_source_keywords = re.compile( '''( typedef |
                                        struct |
                                        enum   |
                                        union  |
@@ -232,7 +232,7 @@
 
     # debugging only - not used in normal operations
     def dump( self ):
-        
+
         if self.content:
             print "{{{content start---"
             for l in self.content:
@@ -239,11 +239,11 @@
                 print l
             print "---content end}}}"
             return
-            
+
         fmt = ""
         if self.format:
             fmt = repr(self.format.id) + " "
-        
+
         for line in self.lines:
             print line
 
@@ -281,11 +281,11 @@
 
     def  parse_file( self, filename ):
         """parse a C source file, and adds its blocks to the processor's list"""
-        
+
         self.reset()
-        
+
         self.filename = filename
-        
+
         fileinput.close()
         self.format    = None
         self.lineno    = 0
@@ -292,11 +292,11 @@
         self.lines     = []
 
         for line in fileinput.input( filename ):
-            
+
             # strip trailing newlines, important on Windows machines !!
             if  line[-1] == '\012':
                 line = line[0:-1]
-    
+
             if self.format == None:
                 self.process_normal_line( line )
 
@@ -304,26 +304,26 @@
                 if self.format.end.match( line ):
                     # that's a normal block end, add it to lines and
                     # create a new block
-                    self.lines.append( line )
+                    # self.lines.append( line )
                     self.add_block_lines()
-                    
+
                 elif self.format.column.match( line ):
                     # that's a normal column line, add it to 'lines'
                     self.lines.append( line )
-                        
+
                 else:
                     # humm.. this is an unexcepted block end,
                     # create a new block, but don't process the line
                     self.add_block_lines()
-                    
+
                     # we need to process the line again
                     self.process_normal_line( line )
-                                
+
         # record the last lines
         self.add_block_lines()
 
-        
 
+
     def process_normal_line( self, line ):
         """process a normal line and check if it's the start of a new block"""
         for f in re_source_block_formats:
@@ -334,18 +334,18 @@
 
         self.lines.append( line )
 
-    
 
+
     def add_block_lines( self ):
         """add the current accumulated lines, and create a new block"""
         if self.lines != []:
             block = SourceBlock( self, self.filename, self.lineno, self.lines )
-            
+
             self.blocks.append( block )
             self.format = None
             self.lines  = []
 
-    
+
     # debugging only, not used in normal operations
     def dump( self ):
         """print all blocks in a processor"""
--- a/src/tools/docmaker/tohtml.py
+++ b/src/tools/docmaker/tohtml.py
@@ -273,29 +273,10 @@
 
     def print_html_field_list( self, fields ):
         print "<table valign=top cellpadding=3>"
-
-        # compute the maximum length of each field name
-        # if it is
-        #
-        max = 0
         for field in fields:
-            l = len( field.name )
-            if l > max:
-              max = l
-
-        head  = "<tr valign=top><td><b>"
-        inter = "</b></td><td>"
-        foot  = "</td></tr>"
-        if max > 18:
-            head  = "<tr><td colspan=2><b>"
-            inter = "</b></td></tr><tr><td width=5%></td><td>"
-            foot  = "<p></td></tr>"
-
-        for field in fields:
-            print head + field.name + inter
+            print "<tr valign=top><td><b>" + field.name + "</b></td><td>"
             self.print_html_items( field.items )
-            print foot
-
+            print "</td></tr>"
         print "</table>"
 
 
@@ -338,7 +319,7 @@
         count = len( self.block_index )
         rows  = (count + self.columns - 1)/self.columns
 
-        print "<center><table border=0 cellpadding=0 cellspacing=2>"
+        print "<center><table border=0 cellpadding=0 cellspacing=0>"
         for r in range(rows):
             line = "<tr>"
             for c in range(self.columns):
@@ -416,9 +397,9 @@
 
         # print section synopsys
         print section_synopsis_header
-        print "<center><table cellspacing=5 cellpadding=2 border=0>"
+        print "<center><table cellspacing=5 cellpadding=0 border=0>"
 
-        maxwidth = 1
+        maxwidth = 0
         for b in section.blocks.values():
             if len(b.name) > maxwidth:
                 maxwidth = len(b.name)