Commit 683973b47cb634dd80ac4863a556633ef1a16c03

David Turner 2005-03-03T14:00:23

* include/freetype/internal/ftobjs.h, src/base/ftutil.c (ft_highpow2), src/pfr/pfrload.c, src/pfr/pfrobjs.c, src/pfr/pfrtypes.h: implement FT_OPTIMIZE_MEMORY, the kerning table is not loaded into the heap anymore.

diff --git a/include/freetype/internal/ftobjs.h b/include/freetype/internal/ftobjs.h
index 805c3ae..1a6130c 100644
--- a/include/freetype/internal/ftobjs.h
+++ b/include/freetype/internal/ftobjs.h
@@ -80,6 +80,12 @@ FT_BEGIN_HEADER
 #define FT_PIX_CEIL( x )      FT_PIX_FLOOR( (x) + 63 )
 
 
+ /* returns the highest power of 2 that is <= value, this correspond to
+  * the highest bit in a given 32-bit value
+  */
+  FT_BASE( FT_UInt32 )
+  ft_highpow2( FT_UInt32  value );
+
   /*************************************************************************/
   /*************************************************************************/
   /*************************************************************************/
diff --git a/src/base/ftutil.c b/src/base/ftutil.c
index ac3760f..317cd95 100644
--- a/src/base/ftutil.c
+++ b/src/base/ftutil.c
@@ -398,4 +398,24 @@
   }
 
 
+  FT_BASE( FT_UInt32 )
+  ft_highpow2( FT_UInt32  value )
+  {
+    FT_UInt32  value2;
+
+   /* we simply clear the lowest bit in each iteration. when
+    * we reach 0, we now that the previous value was our result
+    */
+    for ( ;; )
+    {
+      value2 = value & (value-1);  /* clear lowest bit */
+      if ( value2 == 0 )
+        break;
+
+      value = value2;
+    }
+    return value;
+  }
+
+
 /* END */
diff --git a/src/pfr/pfrload.c b/src/pfr/pfrload.c
index 1435336..38a10c1 100644
--- a/src/pfr/pfrload.c
+++ b/src/pfr/pfrload.c
@@ -609,6 +609,7 @@
   }
 
 
+#ifndef FT_OPTIMIZE_MEMORY
  /*
   *  The kerning data embedded in a PFR font are (charcode,charcode)
   *  pairs; we need to translate them to (gindex,gindex) and sort
@@ -747,7 +748,7 @@
 
     return error;
   }
-
+#endif /* !FT_OPTIMIZE_MEMORY */
 
   static const PFR_ExtraItemRec  pfr_phy_font_extra_items[] =
   {
@@ -826,7 +827,10 @@
     FT_FREE( phy_font->blue_values );
     phy_font->num_blue_values = 0;
 
+#ifndef FT_OPTIMIZE_MEMORY
     FT_FREE( phy_font->kern_pairs );
+#endif
+
     {
       PFR_KernItem  item, next;
 
@@ -1065,8 +1069,10 @@
     phy_font->bct_offset = FT_STREAM_POS();
     phy_font->cursor     = NULL;
 
+#ifndef FT_OPTIMIZE_MEMORY
     /* now sort kerning pairs */
     error = pfr_sort_kerning_pairs( stream, phy_font );
+#endif
 
   Exit:
     return error;
diff --git a/src/pfr/pfrobjs.c b/src/pfr/pfrobjs.c
index 8b318e9..68e1bd9 100644
--- a/src/pfr/pfrobjs.c
+++ b/src/pfr/pfrobjs.c
@@ -48,7 +48,7 @@
     /* we don't want dangling pointers */
     pfrface->family_name = NULL;
     pfrface->style_name  = NULL;
-    
+
     /* finalize the physical font record */
     pfr_phy_font_done( &face->phy_font, FT_FACE_MEMORY( face ) );
 
@@ -174,11 +174,11 @@
         FT_Bitmap_Size*  size;
         PFR_Strike       strike;
         FT_Memory        memory = pfrface->stream->memory;
-         
-         
+
+
         if ( FT_NEW_ARRAY( pfrface->available_sizes, count ) )
           goto Exit;
-         
+
         size   = pfrface->available_sizes;
         strike = phy_font->strikes;
         for ( n = 0; n < count; n++, size++, strike++ )
@@ -361,6 +361,8 @@
       metrics->vertBearingX = 0;
       metrics->vertBearingY = 0;
 
+#if 0 /* some fonts seem to be broken here !! */
+
       /* Apply the font matrix, if any.                 */
       /* TODO: Test existing fonts with unusual matrix  */
       /* whether we have to adjust Units per EM.        */
@@ -375,6 +377,7 @@
 
         FT_Outline_Transform( outline, &font_matrix );
       }
+#endif
 
       /* scale when needed */
       if ( scaling )
@@ -419,6 +422,123 @@
   /*************************************************************************/
   /*************************************************************************/
 
+#ifdef FT_OPTIMIZE_MEMORY
+  FT_LOCAL_DEF( FT_Error )
+  pfr_face_get_kerning( FT_Face     pfrface,        /* PFR_Face */
+                        FT_UInt     glyph1,
+                        FT_UInt     glyph2,
+                        FT_Vector*  kerning )
+  {
+    PFR_Face      face     = (PFR_Face)pfrface;
+    FT_Error      error    = PFR_Err_Ok;
+    PFR_PhyFont   phy_font = &face->phy_font;
+    FT_UInt32     code1, code2, pair;
+
+    kerning->x = 0;
+    kerning->y = 0;
+
+    if ( glyph1 > 0 )
+      glyph1--;
+
+    if ( glyph2 > 0 )
+      glyph2--;
+
+    /* convert glyph indices to character codes */
+    if ( glyph1 > phy_font->num_chars ||
+         glyph2 > phy_font->num_chars )
+      goto Exit;
+
+    code1 = phy_font->chars[glyph1].char_code;
+    code2 = phy_font->chars[glyph2].char_code;
+    pair  = PFR_KERN_INDEX(code1,code2);
+
+    /* now search the list of kerning items */
+    {
+      PFR_KernItem  item   = phy_font->kern_items;
+      FT_Stream     stream = pfrface->stream;
+
+      for ( ; item; item = item->next )
+      {
+        if ( pair >= item->pair1 && pair <= item->pair2 )
+          goto FoundPair;
+      }
+      goto Exit;
+
+    FoundPair: /* we found an item, now parse it and find the value if any */
+      if ( FT_STREAM_SEEK( item->offset )                     ||
+           FT_FRAME_ENTER( item->pair_count*item->pair_size ) )
+        goto Exit;
+
+      {
+        FT_UInt   count    = item->pair_count;
+        FT_UInt   size     = item->pair_size;
+        FT_UInt   power    = (FT_UInt)ft_highpow2( (FT_UInt32)count );
+        FT_UInt   probe    = power*size;
+        FT_UInt   extra    = count - power;
+        FT_Byte*  base     = stream->cursor;
+        FT_Bool   twobytes = item->flags & 1;
+        FT_Byte*  p;
+        FT_UInt32 cpair;
+
+        if ( extra > 0 )
+        {
+          p    = base + extra*size;
+          if ( twobytes )
+            cpair = FT_NEXT_ULONG(p);
+          else
+            cpair = PFR_NEXT_KPAIR(p);
+
+          if ( cpair == pair )
+            goto Found;
+
+          if ( cpair < pair )
+            base = p;
+        }
+
+        while ( probe > size )
+        {
+          probe >>= 1;
+          p       = base + probe;
+          if ( twobytes )
+            cpair = FT_NEXT_ULONG(p);
+          else
+            cpair = PFR_NEXT_KPAIR(p);
+
+          if ( cpair == pair )
+            goto Found;
+
+          if ( cpair < pair )
+            base += probe;
+        }
+
+        p = base;
+        if ( twobytes )
+          cpair = FT_NEXT_ULONG(p);
+        else
+          cpair = PFR_NEXT_KPAIR(p);
+
+        if ( cpair == pair )
+        {
+          FT_Int  value;
+
+        Found:
+          if ( item->flags & 2 )
+            value = FT_PEEK_SHORT(p);
+          else
+            value = p[0];
+
+          kerning->x = item->base_adj + value;
+        }
+      }
+
+      FT_FRAME_EXIT();
+    }
+
+  Exit:
+    return error;
+  }
+
+#else /* !FT_OPTIMIZE_MEMORY */
   FT_LOCAL_DEF( FT_Error )
   pfr_face_get_kerning( FT_Face     pfrface,        /* PFR_Face */
                         FT_UInt     glyph1,
@@ -438,20 +558,20 @@
 
     min = 0;
     max = phy_font->num_kern_pairs;
-    
+
     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 )
       {
         kerning->x = pair->kerning;
         break;
       }
-      
+
       if ( pidx < idx )
         min = mid + 1;
       else
@@ -460,6 +580,6 @@
 
     return error;
   }
-
+#endif /* !FT_OPTIMIZE_MEMORY */
 
 /* END */
diff --git a/src/pfr/pfrtypes.h b/src/pfr/pfrtypes.h
index a10a2b2..db593f0 100644
--- a/src/pfr/pfrtypes.h
+++ b/src/pfr/pfrtypes.h
@@ -196,10 +196,10 @@ FT_BEGIN_HEADER
   typedef struct  PFR_KernItemRec_
   {
     PFR_KernItem  next;
-    FT_UInt       pair_count;
+    FT_Byte       pair_count;
+    FT_Byte       flags;
+    FT_Short      base_adj;
     FT_UInt       pair_size;
-    FT_Int        base_adj;
-    FT_UInt       flags;
     FT_UInt32     offset;
     FT_UInt32     pair1;
     FT_UInt32     pair2;
@@ -212,6 +212,8 @@ FT_BEGIN_HEADER
 #define PFR_KERN_PAIR_INDEX( pair )  \
           PFR_KERN_INDEX( (pair)->glyph1, (pair)->glyph2 )
 
+#define PFR_NEXT_KPAIR(p)  ( p+=2, ((FT_UInt32)p[-2] << 16) | p[-1] )
+
   typedef struct  PFR_KernPairRec_
   {
     FT_UInt    glyph1;
@@ -261,7 +263,9 @@ FT_BEGIN_HEADER
     FT_UInt            num_kern_pairs;
     PFR_KernItem       kern_items;
     PFR_KernItem*      kern_items_tail;
+#ifndef FT_OPTIMIZE_MEMORY
     PFR_KernPair       kern_pairs;
+#endif
 
     /* not part of the spec, but used during load */
     FT_UInt32          bct_offset;