shithub: freetype+ttf2subf

Download patch

ref: 5dbdb6c3c4f681186716234c3738cd3a0d2412a1
parent: 82dba7620e74d2245e576e61ef83f54c7c8f43dd
author: David Turner <[email protected]>
date: Fri Jan 5 08:14:08 EST 2007

* src/cff/cffload.c, src/cff/cffload.h, src/cff/cffgload.c,
	src/cff/cfftypes.h: formatting + do not load the CFF index
	offsets into memory, since this wastes a *lot* of heap memory
	with large Asian CFF fonts. There is no significant performance
	loss

git/fs: mount .git/fs: mount/attach disallowed
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,10 @@
 2007-01-04  David Turner  <[email protected]>
 
-	* src/cff/cffload.c: formatting
+	* src/cff/cffload.c, src/cff/cffload.h, src/cff/cffgload.c,
+	src/cff/cfftypes.h: formatting + do not load the CFF index
+	offsets into memory, since this wastes a *lot* of heap memory
+	with large Asian CFF fonts. There is no significant performance
+	loss
 
 2007-01-04  David Turner  <[email protected]>
 
--- a/src/cff/cffgload.c
+++ b/src/cff/cffgload.c
@@ -2291,9 +2291,8 @@
     if ( cff->top_font.font_dict.cid_registry != 0xFFFFU &&
          cff->charset.cids )
     {
-      if ( glyph_index < cff->charset.max_cid )
-        glyph_index = cff->charset.cids[glyph_index];
-      else
+      glyph_index = cff_charset_cid_to_gindex( &cff->charset, glyph_index );
+      if ( glyph_index == 0 )
         return CFF_Err_Invalid_Argument;
     }
     else if ( glyph_index >= cff->num_glyphs )
@@ -2423,13 +2422,13 @@
         /* See how charstring loads at cff_index_access_element() in      */
         /* cffload.c.                                                     */
         {
-          CFF_IndexRec csindex = cff->charstrings_index;
+          CFF_Index csindex = &cff->charstrings_index;
 
-
-          glyph->root.control_data =
-            csindex.bytes + csindex.offsets[glyph_index] - 1;
-          glyph->root.control_len =
-            charstring_len;
+          if (csindex->offsets)
+          {
+            glyph->root.control_data = csindex->bytes + csindex->offsets[glyph_index] - 1;
+            glyph->root.control_len  = charstring_len;
+          }
         }
       }
 
--- a/src/cff/cffload.c
+++ b/src/cff/cffload.c
@@ -193,11 +193,33 @@
 #undef  FT_COMPONENT
 #define FT_COMPONENT  trace_cffload
 
+  /* read an offset from the index's stream current position */
+  static FT_ULong
+  cff_index_read_offset( CFF_Index  idx,
+                         FT_Error  *perror )
+  {
+    FT_Error   error;
+    FT_Stream  stream = idx->stream;
+    FT_Byte    tmp[4];
+    FT_ULong   result = 0;
 
+    if ( !FT_STREAM_READ( tmp, idx->off_size ) )
+    {
+      FT_Int  nn;
+
+      for ( nn = 0; nn < idx->off_size; nn++ )
+        result = (result << 8) | tmp[nn];
+    }
+
+    *perror = error;
+    return result;
+  }
+
+
   static FT_Error
-  cff_new_index( CFF_Index  idx,
-                 FT_Stream  stream,
-                 FT_Bool    load )
+  cff_index_init( CFF_Index  idx,
+                  FT_Stream  stream,
+                  FT_Bool    load )
   {
     FT_Error   error;
     FT_Memory  memory = stream->memory;
@@ -207,14 +229,12 @@
     FT_MEM_ZERO( idx, sizeof ( *idx ) );
 
     idx->stream = stream;
+    idx->start  = FT_STREAM_POS();
     if ( !FT_READ_USHORT( count ) &&
          count > 0                )
     {
-      FT_Byte*   p;
       FT_Byte    offsize;
-      FT_ULong   data_size;
-      FT_ULong*  poff;
-      FT_Byte*   p_end;
+      FT_ULong   size, last_offset;
 
 
       /* there is at least one element; read the offset size,           */
@@ -228,56 +248,37 @@
         goto Exit;
       }
 
-      idx->stream   = stream;
       idx->count    = count;
       idx->off_size = offsize;
-      data_size     = (FT_ULong)( count + 1 ) * offsize;
+      size          = (FT_ULong)( count + 1 ) * offsize;
 
-      if ( FT_NEW_ARRAY( idx->offsets, count + 1 ) ||
-           FT_FRAME_ENTER( data_size )             )
+      idx->data_offset = idx->start + 3 + size;
+
+      if ( FT_STREAM_SKIP( size - offsize ) )
         goto Exit;
 
-      poff   = idx->offsets;
-      p      = (FT_Byte*)stream->cursor;
-      p_end  = p + data_size;
+      size = cff_index_read_offset( idx, &error );
+      if (error)
+        goto Exit;
 
-      switch ( offsize )
+      if ( size == 0 )
       {
-      case 1:
-        for ( ; p < p_end; p++, poff++ )
-          poff[0] = p[0];
-        break;
-
-      case 2:
-        for ( ; p < p_end; p += 2, poff++ )
-          poff[0] = FT_PEEK_USHORT( p );
-        break;
-
-      case 3:
-        for ( ; p < p_end; p += 3, poff++ )
-          poff[0] = FT_PEEK_OFF3( p );
-        break;
-
-      default:
-        for ( ; p < p_end; p += 4, poff++ )
-          poff[0] = FT_PEEK_ULONG( p );
+        error = CFF_Err_Invalid_Table;
+        goto Exit;
       }
 
-      FT_FRAME_EXIT();
+      idx->data_size = --size;
 
-      idx->data_offset = FT_STREAM_POS();
-      data_size        = poff[-1] - 1;
-
       if ( load )
       {
         /* load the data */
-        if ( FT_FRAME_EXTRACT( data_size, idx->bytes ) )
+        if ( FT_FRAME_EXTRACT( size, idx->bytes ) )
           goto Exit;
       }
       else
       {
         /* skip the data */
-        if ( FT_STREAM_SKIP( data_size ) )
+        if ( FT_STREAM_SKIP( size ) )
           goto Exit;
       }
     }
@@ -291,7 +292,7 @@
 
 
   static void
-  cff_done_index( CFF_Index  idx )
+  cff_index_done( CFF_Index  idx )
   {
     if ( idx->stream )
     {
@@ -308,6 +309,67 @@
   }
 
 
+  static FT_Error
+  cff_index_load_offsets( CFF_Index  idx )
+  {
+    FT_Error   error  = 0;
+    FT_Stream  stream = idx->stream;
+    FT_Memory  memory = stream->memory;
+
+    if ( idx->count > 0 && idx->offsets == NULL ) 
+    {
+      FT_Byte    offsize = idx->off_size;
+      FT_ULong   data_size;
+      FT_Byte*   p;
+      FT_Byte*   p_end;
+      FT_ULong*  poff;
+
+      data_size     = (FT_ULong)( idx->count + 1 ) * offsize;
+
+      if ( FT_NEW_ARRAY( idx->offsets, idx->count + 1 ) ||
+           FT_STREAM_SEEK( idx->start + 3 )        ||
+           FT_FRAME_ENTER( data_size )             )
+        goto Exit;
+
+      poff   = idx->offsets;
+      p      = (FT_Byte*)stream->cursor;
+      p_end  = p + data_size;
+
+      switch ( offsize )
+      {
+      case 1:
+        for ( ; p < p_end; p++, poff++ )
+          poff[0] = p[0];
+        break;
+
+      case 2:
+        for ( ; p < p_end; p += 2, poff++ )
+          poff[0] = FT_PEEK_USHORT( p );
+        break;
+
+      case 3:
+        for ( ; p < p_end; p += 3, poff++ )
+          poff[0] = FT_PEEK_OFF3( p );
+        break;
+
+      default:
+        for ( ; p < p_end; p += 4, poff++ )
+          poff[0] = FT_PEEK_ULONG( p );
+      }
+
+      FT_FRAME_EXIT();
+    }
+
+  Exit:
+    if (error)
+      FT_FREE( idx->offsets );
+
+    return error;
+  }
+
+
+
+
   /* allocate a table containing pointers to an index's elements */
   static FT_Error
   cff_index_get_pointers( CFF_Index   idx,
@@ -321,6 +383,13 @@
 
     *table = 0;
 
+    if ( idx->offsets == NULL )
+    {
+      error = cff_index_load_offsets( idx );
+      if ( error )
+        goto Exit;
+    }
+
     if ( idx->count > 0 && !FT_NEW_ARRAY( t, idx->count + 1 ) )
     {
       old_offset = 1;
@@ -330,6 +399,10 @@
         if ( !offset )
           offset = old_offset;
 
+        /* sanity check for invalid offset tables */
+        else if ( offset < old_offset || offset-1 >= idx->data_size )
+          offset = old_offset;
+
         t[n] = idx->bytes + offset - 1;
 
         old_offset = offset;
@@ -337,6 +410,7 @@
       *table = t;
     }
 
+  Exit:
     return error;
   }
 
@@ -353,23 +427,45 @@
     if ( idx && idx->count > element )
     {
       /* compute start and end offsets */
-      FT_ULong  off1, off2 = 0;
+      FT_Stream  stream = idx->stream;
+      FT_ULong   off1, off2 = 0;
 
 
-      off1 = idx->offsets[element];
-      if ( off1 )
+      /* load offsets from file or the offset table */
+      if ( !idx->offsets )
       {
-        do
-        {
-          element++;
-          off2 = idx->offsets[element];
+        FT_ULong  pos = element*idx->off_size;
 
-        } while ( off2 == 0 && element < idx->count );
+        if ( FT_STREAM_SEEK( idx->start + 3 + pos ) )
+          goto Exit;
 
-        if ( !off2 )
-          off1 = 0;
+        off1 = cff_index_read_offset( idx, &error );
+        if (error) goto Exit;
+
+        if ( off1 != 0 )
+        {
+          do
+          {
+            element++;
+            off2 = cff_index_read_offset( idx, &error );
+          }
+          while ( off2 == 0 && element < idx->count );
+        }
       }
+      else   /* use offsets table */
+      {
+        off1 = idx->offsets[element];
+        if ( off1 )
+        {
+          do
+          {
+            element++;
+            off2 = idx->offsets[element];
 
+          } while ( off2 == 0 && element < idx->count );
+        }
+      }
+
       /* access element */
       if ( off1 && off2 > off1 )
       {
@@ -383,9 +479,6 @@
         else
         {
           /* this index is still on disk/file, access it through a frame */
-          FT_Stream  stream = idx->stream;
-
-
           if ( FT_STREAM_SEEK( idx->data_offset + off1 - 1 ) ||
                FT_FRAME_EXTRACT( off2 - off1, *pbytes )      )
             goto Exit;
@@ -660,6 +753,18 @@
   }
 
 
+  FT_LOCAL_DEF( FT_UInt )
+  cff_charset_cid_to_gindex( CFF_Charset  charset,
+                             FT_UInt      cid )
+  {
+    FT_UInt  result = 0;
+
+    if ( cid < charset->max_cid )
+      result = charset->cids[cid];
+
+    return result;
+  }
+
   static void
   cff_charset_free_cids( CFF_Charset  charset,
                          FT_Memory    memory )
@@ -1209,7 +1314,7 @@
                            priv->local_subrs_offset ) )
         goto Exit;
 
-      error = cff_new_index( &font->local_subrs_index, stream, 1 );
+      error = cff_index_init( &font->local_subrs_index, stream, 1 );
       if ( error )
         goto Exit;
 
@@ -1231,7 +1336,7 @@
   {
     if ( subfont )
     {
-      cff_done_index( &subfont->local_subrs_index );
+      cff_index_done( &subfont->local_subrs_index );
       FT_FREE( subfont->local_subrs );
     }
   }
@@ -1287,10 +1392,10 @@
       goto Exit;
 
     /* read the name, top dict, string and global subrs index */
-    if ( FT_SET_ERROR( cff_new_index( &font->name_index,         stream, 0 )) ||
-         FT_SET_ERROR( cff_new_index( &font->font_dict_index,    stream, 0 )) ||
-         FT_SET_ERROR( cff_new_index( &font->string_index,       stream, 0 )) ||
-         FT_SET_ERROR( cff_new_index( &font->global_subrs_index, stream, 1 )) )
+    if ( FT_SET_ERROR( cff_index_init( &font->name_index,         stream, 0 )) ||
+         FT_SET_ERROR( cff_index_init( &font->font_dict_index,    stream, 0 )) ||
+         FT_SET_ERROR( cff_index_init( &font->string_index,       stream, 0 )) ||
+         FT_SET_ERROR( cff_index_init( &font->global_subrs_index, stream, 1 )) )
       goto Exit;
 
     /* well, we don't really forget the `disabled' fonts... */
@@ -1318,7 +1423,7 @@
     if ( FT_STREAM_SEEK( base_offset + dict->charstrings_offset ) )
       goto Exit;
 
-    error = cff_new_index( &font->charstrings_index, stream, 0 );
+    error = cff_index_init( &font->charstrings_index, stream, 0 );
     if ( error )
       goto Exit;
 
@@ -1335,7 +1440,7 @@
       if ( FT_STREAM_SEEK( base_offset + dict->cid_fd_array_offset ) )
         goto Exit;
 
-      error = cff_new_index( &fd_index, stream, 0 );
+      error = cff_index_init( &fd_index, stream, 0 );
       if ( error )
         goto Exit;
 
@@ -1371,7 +1476,7 @@
                                   base_offset + dict->cid_fd_select_offset );
 
     Fail_CID:
-      cff_done_index( &fd_index );
+      cff_index_done( &fd_index );
 
       if ( error )
         goto Exit;
@@ -1441,11 +1546,11 @@
     FT_UInt    idx;
 
 
-    cff_done_index( &font->global_subrs_index );
-    cff_done_index( &font->string_index );
-    cff_done_index( &font->font_dict_index );
-    cff_done_index( &font->name_index );
-    cff_done_index( &font->charstrings_index );
+    cff_index_done( &font->global_subrs_index );
+    cff_index_done( &font->string_index );
+    cff_index_done( &font->font_dict_index );
+    cff_index_done( &font->name_index );
+    cff_index_done( &font->charstrings_index );
 
     /* release font dictionaries, but only if working with */
     /* a CID keyed CFF font                                */
--- a/src/cff/cffload.h
+++ b/src/cff/cffload.h
@@ -52,6 +52,10 @@
                             FT_Byte**  pbytes );
 
 
+  FT_LOCAL( FT_UInt )
+  cff_charset_cid_to_gindex( CFF_Charset  charset,
+                             FT_UInt      cid );
+
   FT_LOCAL( FT_Error )
   cff_font_load( FT_Stream  stream,
                  FT_Int     face_index,
--- a/src/cff/cfftypes.h
+++ b/src/cff/cfftypes.h
@@ -39,6 +39,9 @@
   /* <Fields>                                                              */
   /*    stream      :: The source input stream.                            */
   /*                                                                       */
+  /*    start       :: The position of the first index byte in the         */
+  /*                   input stream                                        */
+  /*                                                                       */
   /*    count       :: The number of elements in the index.                */
   /*                                                                       */
   /*    off_size    :: The size in bytes of object offsets in index.       */
@@ -46,16 +49,21 @@
   /*    data_offset :: The position of first data byte in the index's      */
   /*                   bytes.                                              */
   /*                                                                       */
-  /*    offsets     :: A table of element offsets in the index.            */
+  /*    data_size   :: size of data table in this index                    */
   /*                                                                       */
+  /*    offsets     :: A table of element offsets in the index. must be    */
+  /*                   loaded explicitely                                  */
+  /*                                                                       */
   /*    bytes       :: If the index is loaded in memory, its bytes.        */
   /*                                                                       */
   typedef struct  CFF_IndexRec_
   {
     FT_Stream  stream;
+    FT_ULong   start;
     FT_UInt    count;
     FT_Byte    off_size;
     FT_ULong   data_offset;
+    FT_ULong   data_size;
 
     FT_ULong*  offsets;
     FT_Byte*   bytes;
@@ -85,6 +93,8 @@
     FT_UShort*  cids;       /* the inverse mapping of `sids'; only needed */
                             /* for CID-keyed fonts                        */
     FT_UInt     max_cid;
+    FT_UInt     num_glyphs;
+
   } CFF_CharsetRec, *CFF_Charset;