Commit e70d553111963cb0031869f708038f52c9f57fe9

David Turner 2005-02-22T16:53:06

* include/freetype/config/ftoption.h, include/freetype/internal/ttypes.h, src/truetype/ttpload.c, src/truetype/ttpload.h, src/truetype/ttgload.c: added the temporary configuration FT_OPTIMIZE_MEMORY to control various optimizations used to reduce the heap footprint of memory-mapped TrueType files. * src/truetype/ttpload.c (tt_face_load_loca, tt_face_get_location, tt_face_done_loca): when FT_OPTIMIZE_MEMORY is set, the locations table is read directly from memory-mapped streams, instead of being decoded into the heap. * src/truetype/ttpload.c: only load the CVT and fpgm tables when the bytecode interpreter is compiled in.

diff --git a/ChangeLog b/ChangeLog
index fb56e4f..cde05d7 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -18,6 +18,20 @@
 	* include/freetype/internal/ftmemory.h: adding FT_ARRAY_ZERO, as a
 	convenience macro.
 
+    * include/freetype/config/ftoption.h, include/freetype/internal/ttypes.h,
+    src/truetype/ttpload.c, src/truetype/ttpload.h, src/truetype/ttgload.c:
+    added the temporary configuration FT_OPTIMIZE_MEMORY to control various
+    optimizations used to reduce the heap footprint of memory-mapped TrueType
+    files.
+
+    * src/truetype/ttpload.c (tt_face_load_loca, tt_face_get_location,
+    tt_face_done_loca): when FT_OPTIMIZE_MEMORY is set, the locations table
+    is read directly from memory-mapped streams, instead of being decoded
+    into the heap.
+
+    * src/truetype/ttpload.c: only load the CVT and fpgm tables when the
+    bytecode interpreter is compiled in.
+
 
 2005-02-20  Werner Lemberg  <wl@gnu.org>
 
diff --git a/include/freetype/config/ftoption.h b/include/freetype/config/ftoption.h
index 1d9efe4..c3d06c4 100644
--- a/include/freetype/config/ftoption.h
+++ b/include/freetype/config/ftoption.h
@@ -568,6 +568,8 @@ FT_BEGIN_HEADER
 
 #endif /* FT_CONFIG_OPTION_CHESTER_HINTS */
 
+#define FT_OPTIMIZE_MEMORY
+
 FT_END_HEADER
 
 
diff --git a/include/freetype/internal/tttypes.h b/include/freetype/internal/tttypes.h
index 4a3aab1..183beb8 100644
--- a/include/freetype/internal/tttypes.h
+++ b/include/freetype/internal/tttypes.h
@@ -361,6 +361,7 @@ FT_BEGIN_HEADER
   } TT_HdmxRec, *TT_Hdmx;
 
 
+
   /*************************************************************************/
   /*                                                                       */
   /* <Struct>                                                              */
@@ -1263,9 +1264,14 @@ FT_BEGIN_HEADER
     /*                                                                     */
     /***********************************************************************/
 
+#ifdef FT_OPTIMIZE_MEMORY
+    FT_UInt               num_locations;
+    FT_Byte*              glyph_locations;
+#else
     /* the glyph locations */
     FT_UShort             num_locations;
     FT_Long*              glyph_locations;
+#endif
 
     /* the font program, if any */
     FT_ULong              font_program_size;
@@ -1297,7 +1303,7 @@ FT_BEGIN_HEADER
     FT_Bool               doblend;
     GX_Blend              blend;
 #endif
-    
+
     /***********************************************************************/
     /*                                                                     */
     /* Other tables or fields. This is used by derivative formats like     */
diff --git a/src/autohint/ahglyph.c b/src/autohint/ahglyph.c
index 5bf1988..7db7bb9 100644
--- a/src/autohint/ahglyph.c
+++ b/src/autohint/ahglyph.c
@@ -304,12 +304,15 @@
 
 
       if ( FT_RENEW_ARRAY( outline->points,        max,     news     ) ||
-           FT_RENEW_ARRAY( outline->horz_edges,    max * 2, news * 2 ) ||
-           FT_RENEW_ARRAY( outline->horz_segments, max * 2, news * 2 ) )
+           FT_RENEW_ARRAY( outline->horz_edges,    max * 2, news * 2 ) )
         goto Exit;
 
-      /* readjust some pointers */
       outline->vert_edges    = outline->horz_edges    + news;
+
+      if ( FT_RENEW_ARRAY( outline->horz_segments, max * 2, news * 2 ) )
+        goto Exit;
+
+      /* readjust some pointers */
       outline->vert_segments = outline->horz_segments + news;
       outline->max_points    = news;
     }
diff --git a/src/truetype/ttgload.c b/src/truetype/ttgload.c
index 145ac98..036a7d2 100644
--- a/src/truetype/ttgload.c
+++ b/src/truetype/ttgload.c
@@ -1019,13 +1019,7 @@
 
 #endif /* FT_CONFIG_OPTION_INCREMENTAL */
 
-    {
-      offset = face->glyph_locations[glyph_index];
-      count  = 0;
-
-      if ( glyph_index < (FT_UInt)face->num_locations - 1 )
-        count = (FT_UInt)( face->glyph_locations[glyph_index + 1] - offset );
-    }
+    offset = tt_face_get_location( face, glyph_index, &count );
 
     if ( count == 0 )
     {
diff --git a/src/truetype/ttobjs.c b/src/truetype/ttobjs.c
index b606ace..095292d 100644
--- a/src/truetype/ttobjs.c
+++ b/src/truetype/ttobjs.c
@@ -218,8 +218,11 @@
       if ( !face->root.internal->incremental_interface )
         error = tt_face_load_loca( face, stream );
       if ( !error )
-        error = tt_face_load_cvt( face, stream ) ||
-                tt_face_load_fpgm( face, stream );
+      {
+        error = tt_face_load_cvt( face, stream );
+        if ( !error )
+          error = tt_face_load_fpgm( face, stream );
+      }
 
 #else
 
@@ -290,8 +293,7 @@
       sfnt->done_face( face );
 
     /* freeing the locations table */
-    FT_FREE( face->glyph_locations );
-    face->num_locations = 0;
+    tt_face_done_loca( face );
 
     /* freeing the CVT */
     FT_FREE( face->cvt );
diff --git a/src/truetype/ttpload.c b/src/truetype/ttpload.c
index 9cae477..cc2eb61 100644
--- a/src/truetype/ttpload.c
+++ b/src/truetype/ttpload.c
@@ -58,6 +58,118 @@
   /* <Return>                                                              */
   /*    FreeType error code.  0 means success.                             */
   /*                                                                       */
+#ifdef FT_OPTIMIZE_MEMORY
+
+  FT_LOCAL_DEF( FT_Error )
+  tt_face_load_loca( TT_Face    face,
+                     FT_Stream  stream )
+  {
+    FT_Error   error;
+    FT_Memory  memory = stream->memory;
+    FT_ULong   table_len;
+
+
+    FT_TRACE2(( "Locations " ));
+    error = face->goto_table( face, TTAG_loca, stream, &table_len );
+    if ( error )
+    {
+      error = TT_Err_Locations_Missing;
+      goto Exit;
+    }
+
+    if ( face->header.Index_To_Loc_Format != 0 )
+    {
+      if ( table_len >= 040000 )
+      {
+        FT_TRACE2(( "table too large !!\n" ));
+        error = TT_Err_Invalid_Table;
+        goto Exit;
+      }
+      face->num_locations = (FT_UInt)(table_len >> 2);
+    }
+    else
+    {
+      if ( table_len >= 0x20000 )
+      {
+        FT_TRACE2(( "table too large !!\n" ));
+        error = TT_Err_Invalid_Table;
+        goto Exit;
+      }
+      face->num_locations = (FT_UInt)(table_len >> 1);
+    }
+
+
+   /* extract the frame. We don't need to decompress it since
+    * we'll be able to parse it directly
+    */
+    if ( FT_FRAME_EXTRACT( table_len, face->glyph_locations ) )
+      goto Exit;
+
+    FT_TRACE2(( "loaded\n" ));
+
+  Exit:
+    return error;
+  }
+
+
+  FT_LOCAL_DEF( FT_ULong )
+  tt_face_get_location( TT_Face    face,
+                        FT_UInt    gindex,
+                        FT_UInt   *asize )
+  {
+    FT_ULong  pos1, pos2;
+    FT_Byte*  p;
+    FT_Byte*  p_limit;
+
+    pos1 = pos2 = 0;
+    if ( gindex < face->num_locations )
+    {
+      if ( face->header.Index_To_Loc_Format != 0 )
+      {
+        p       = face->glyph_locations + gindex*4;
+        p_limit = face->glyph_locations + face->num_locations*4;
+
+        pos1 = FT_NEXT_ULONG(p);
+        pos2 = pos1;
+
+        if ( p+4 <= p_limit )
+          pos2 = FT_NEXT_ULONG(p);
+      }
+      else
+      {
+        p       = face->glyph_locations + gindex*2;
+        p_limit = face->glyph_locations + face->num_locations*2;
+
+        pos1 = FT_NEXT_USHORT(p);
+        pos2 = pos1;
+
+        if ( p+2 <= p_limit )
+          pos2 = FT_NEXT_USHORT(p);
+
+        pos1 <<= 1;
+        pos2 <<= 1;
+      }
+    }
+
+    *asize = (FT_UInt)(pos2 - pos1);
+
+    return pos1;
+  }
+
+
+  FT_LOCAL_DEF( void )
+  tt_face_done_loca( TT_Face  face )
+  {
+    FT_Stream     stream = face->root.stream;
+
+    FT_FRAME_RELEASE( face->glyph_locations );
+    face->num_locations = 0;
+  }
+
+
+
+#else /* !FT_OPTIMIZE_MEMORY */
+
   FT_LOCAL_DEF( FT_Error )
   tt_face_load_loca( TT_Face    face,
                      FT_Stream  stream )
@@ -130,6 +242,39 @@
   }
 
 
+  FT_LOCAL_DEF( FT_ULong )
+  tt_face_get_location( TT_Face    face,
+                        FT_UInt    gindex,
+                        FT_UInt   *asize )
+  {
+    FT_ULong  offset;
+    FT_UInt   count;
+
+    offset = face->glyph_locations[gindex];
+    count  = 0;
+
+    if ( gindex < (FT_UInt)face->num_locations - 1 )
+      count = (FT_UInt)( face->glyph_locations[gindex + 1] - offset );
+
+    *asize = count;
+    return offset;
+  }
+
+
+  FT_LOCAL_DEF( void )
+  tt_face_done_loca( TT_Face  face )
+  {
+    FT_Memory     memory = face->root.memory;
+
+    FT_FREE( face->glyph_locations );
+    face->num_locations = 0;
+  }
+
+
+
+#endif /* !FT_OPTIMIZE_MEMORY */
+
+
   /*************************************************************************/
   /*                                                                       */
   /* <Function>                                                            */
@@ -151,6 +296,8 @@
   tt_face_load_cvt( TT_Face    face,
                     FT_Stream  stream )
   {
+#ifdef FT_CONFIG_OPTION_BYTECODE_INTERPRETER
+
     FT_Error   error;
     FT_Memory  memory = stream->memory;
     FT_ULong   table_len;
@@ -197,6 +344,12 @@
 
   Exit:
     return error;
+
+#else /* !BYTECODE_INTERPRETER */
+    FT_UNUSED(face);
+    FT_UNUSED(stream);
+    return 0;
+#endif
   }
 
 
@@ -221,6 +374,8 @@
   tt_face_load_fpgm( TT_Face    face,
                      FT_Stream  stream )
   {
+#ifdef FT_CONFIG_OPTION_BYTECODE_INTERPRETER
+
     FT_Error   error;
     FT_ULong   table_len;
 
@@ -267,6 +422,12 @@
 
   Exit:
     return error;
+
+#else /* !BYTECODE_INTERPRETER */
+    FT_UNUSED(face);
+    FT_UNUSED(stream);
+    return 0;
+#endif
   }
 
 
diff --git a/src/truetype/ttpload.h b/src/truetype/ttpload.h
index 3f8cd64..1d14aec 100644
--- a/src/truetype/ttpload.h
+++ b/src/truetype/ttpload.h
@@ -31,6 +31,14 @@ FT_BEGIN_HEADER
   tt_face_load_loca( TT_Face    face,
                      FT_Stream  stream );
 
+  FT_LOCAL( FT_ULong )
+  tt_face_get_location( TT_Face    face,
+                        FT_UInt    gindex,
+                        FT_UInt   *asize );
+
+  FT_LOCAL( void )
+  tt_face_done_loca( TT_Face  face );
+
   FT_LOCAL( FT_Error )
   tt_face_load_cvt( TT_Face    face,
                     FT_Stream  stream );