Commit 9a2b3b6d55f0266550770f95626de677c00e7282

Wu, Chia-I (吳佳一) 2006-02-14T08:37:03

* src/sfnt/ttmtx.c (tt_face_load_hhea, tt_face_load_hmtx): Simply return error if table is missing. Check table length in non-FT_OPTIMIZE_MEMORY'ed `tt_face_load_hmtx'. * src/sfnt/sfobjs.c (sfnt_load_face): Take care of missing metrics tables. The last change makes Mac bitmap-only font not load and this fixes it. * src/truetype/ttgload.c (load_truetype_glyph): Fix compilation error when FT_CONFIG_OPTION_INCREMENTAL is defined.

diff --git a/ChangeLog b/ChangeLog
index bcd15cf..096928e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+2006-02-14  Chia-I Wu  <b90201047@ntu.edu.tw>
+
+	* src/sfnt/ttmtx.c (tt_face_load_hhea, tt_face_load_hmtx): Simply
+	return error if table is missing.
+	Check table length in non-FT_OPTIMIZE_MEMORY'ed `tt_face_load_hmtx'.
+
+	* src/sfnt/sfobjs.c (sfnt_load_face): Take care of missing metrics
+	tables.  The last change makes Mac bitmap-only font not load and this
+	fixes it.
+
+	* src/truetype/ttgload.c (load_truetype_glyph): Fix compilation error
+	when FT_CONFIG_OPTION_INCREMENTAL is defined.
+
 2006-02-13  Chia-I Wu  <b90201047@ntu.edu.tw>
 
 	Clean up the SFNT_Interface.  In this final pass, `load_hmtx' is
diff --git a/src/sfnt/sfobjs.c b/src/sfnt/sfobjs.c
index 169fba2..53a09dd 100644
--- a/src/sfnt/sfobjs.c
+++ b/src/sfnt/sfobjs.c
@@ -560,16 +560,54 @@
     /* sbit font file                                                 */
     if ( !is_apple_sbit )
     {
-      /* load the `hhea' and `hmtx' tables at once */
-      error = sfnt->load_hhea( face, stream, 0 ) ||
-              sfnt->load_hmtx( face, stream, 0 );
+      /* load the `hhea' and `hmtx' tables */
+      error = sfnt->load_hhea( face, stream, 0 );
+      if ( !error )
+      {
+        error = sfnt->load_hmtx( face, stream, 0 );
+
+        if ( error == SFNT_Err_Table_Missing )
+        {
+          error = SFNT_Err_Hmtx_Table_Missing;
+
+#ifdef FT_CONFIG_OPTION_INCREMENTAL
+          /* If this is an incrementally loaded font and there are */
+          /* overriding metrics, tolerate a missing `hmtx' table.  */
+          if ( face->root.internal->incremental_interface          &&
+               face->root.internal->incremental_interface->funcs->
+                 get_glyph_metrics                                 )
+          {
+            face->horizontal.number_Of_HMetrics = 0;
+            error = SFNT_Err_Ok;
+          }
+#endif
+        }
+      }
+      else if ( error == SFNT_Err_Table_Missing )
+      {
+        /* No `hhea' table necessary for SFNT Mac fonts. */
+        if ( face->format_tag == TTAG_true )
+        {
+          FT_TRACE2(( "This is an SFNT Mac font.\n"));
+          error = SFNT_Err_Ok;
+        }
+        else
+          error = SFNT_Err_Horiz_Header_Missing;
+      }
+
       if ( error )
         goto Exit;
 
-      /* try to load the `vhea' and `vmtx' tables at once */
-      error = sfnt->load_hhea( face, stream, 1 ) ||
-              sfnt->load_hmtx( face, stream, 1 );
-      if ( error )
+      /* try to load the `vhea' and `vmtx' tables */
+      error = sfnt->load_hhea( face, stream, 1 );
+      if ( !error )
+      {
+        error = sfnt->load_hmtx( face, stream, 1 );
+        if ( !error )
+          face->vertical_info = 1;
+      }
+
+      if ( error && error != SFNT_Err_Table_Missing )
         goto Exit;
 
       if ( LOAD_( os2 ) )
diff --git a/src/sfnt/ttmtx.c b/src/sfnt/ttmtx.c
index 43a1953..5d326c7 100644
--- a/src/sfnt/ttmtx.c
+++ b/src/sfnt/ttmtx.c
@@ -66,65 +66,40 @@
     FT_ULong*  ptable_size;
     
     
-    FT_TRACE2(( "TT_Load_%s_Metrics: %08p\n", vertical ? "Vertical"
-                                                       : "Horizontal",
-                                              face ));
+    FT_TRACE2(( "%cmtx ", vertical ? 'v' : 'h' ));
 
     if ( vertical )
     {
-      ptable      = &face->vert_metrics;
-      ptable_size = &face->vert_metrics_size;
-      
-      /* The table is optional, quit silently if it wasn't found.      */
-      /*                                                               */
-      /* XXX: Some fonts have a valid vertical header with a non-null  */
-      /*      `number_of_VMetrics' fields, but no corresponding `vmtx' */
-      /*      table to get the metrics from (e.g. mingliu).            */
-      /*                                                               */
-      /*      For safety, we set the field to 0!                       */
-      /*                                                               */
       error = face->goto_table( face, TTAG_vmtx, stream, &table_size );
       if ( error )
-      {
-        /* Set number_Of_VMetrics to 0! */
-        FT_TRACE2(( "  no vertical header in file.\n" ));
-        error = SFNT_Err_Ok;
-        goto Exit;
-      }
+        goto Fail;
+
+      ptable      = &face->vert_metrics;
+      ptable_size = &face->vert_metrics_size;
     }
     else
     {
-      ptable      = &face->horz_metrics;
-      ptable_size = &face->horz_metrics_size;
-
       error = face->goto_table( face, TTAG_hmtx, stream, &table_size );
       if ( error )
-      {
-#ifdef FT_CONFIG_OPTION_INCREMENTAL
-        /* If this is an incrementally loaded font and there are */
-        /* overriding metrics, tolerate a missing `hmtx' table.  */
-        if ( face->root.internal->incremental_interface          &&
-             face->root.internal->incremental_interface->funcs->
-               get_glyph_metrics                                 )
-        {
-          face->horizontal.number_Of_HMetrics = 0;
-          error = SFNT_Err_Ok;
-          goto Exit;
-        }
-#endif
+        goto Fail;
 
-        FT_ERROR(( " no horizontal metrics in file!\n" ));
-        error = SFNT_Err_Hmtx_Table_Missing;
-        goto Exit;
-      }
+      ptable      = &face->horz_metrics;
+      ptable_size = &face->horz_metrics_size;
     }
     
     if ( FT_FRAME_EXTRACT( table_size, *ptable ) )
-      goto Exit;
+      goto Fail;
       
     *ptable_size = table_size;
+
+    return SFNT_Err_Ok;
     
-  Exit:
+  Fail:
+    if ( error == SFNT_Err_Table_Missing )
+      FT_TRACE2(( "missing\n" ));
+    else
+      FT_TRACE2(( "failed\n" ));
+
     return error;
   }
 
@@ -145,31 +120,26 @@
     TT_ShortMetrics**  shorts;
 
 
-    FT_TRACE2(( "TT_Load_%s_Metrics: %08p\n", vertical ? "Vertical"
-                                                       : "Horizontal",
-                                              face ));
+    FT_TRACE2(( "%cmtx ", vertical ? 'v' : 'h' ));
 
     if ( vertical )
     {
-      /* The table is optional, quit silently if it wasn't found.      */
-      /*                                                               */
-      /* XXX: Some fonts have a valid vertical header with a non-null  */
-      /*      `number_of_VMetrics' fields, but no corresponding `vmtx' */
-      /*      table to get the metrics from (e.g. mingliu).            */
-      /*                                                               */
-      /*      For safety, we set the field to 0!                       */
-      /*                                                               */
       error = face->goto_table( face, TTAG_vmtx, stream, &table_len );
       if ( error )
       {
         /* Set number_Of_VMetrics to 0! */
-        FT_TRACE2(( "  no vertical header in file.\n" ));
         face->vertical.number_Of_VMetrics = 0;
-        error = SFNT_Err_Ok;
-        goto Exit;
+
+        goto Fail;
       }
 
       num_longs = face->vertical.number_Of_VMetrics;
+      if ( num_longs > table_len / 4 )
+      {
+        num_longs = table_len / 4;
+        face->vertical.number_Of_VMetrics = num_longs;
+      }
+
       longs     = (TT_LongMetrics *)&face->vertical.long_metrics;
       shorts    = (TT_ShortMetrics**)&face->vertical.short_metrics;
     }
@@ -178,26 +148,18 @@
       error = face->goto_table( face, TTAG_hmtx, stream, &table_len );
       if ( error )
       {
+        face->horizontal.number_Of_HMetrics = 0;
 
-#ifdef FT_CONFIG_OPTION_INCREMENTAL
-        /* If this is an incrementally loaded font and there are */
-        /* overriding metrics, tolerate a missing `hmtx' table.  */
-        if ( face->root.internal->incremental_interface          &&
-             face->root.internal->incremental_interface->funcs->
-               get_glyph_metrics                                 )
-        {
-          face->horizontal.number_Of_HMetrics = 0;
-          error = SFNT_Err_Ok;
-          goto Exit;
-        }
-#endif
-
-        FT_ERROR(( " no horizontal metrics in file!\n" ));
-        error = SFNT_Err_Hmtx_Table_Missing;
-        goto Exit;
+        goto Fail;
       }
 
       num_longs = face->horizontal.number_Of_HMetrics;
+      if ( num_longs > table_len / 4 )
+      {
+        num_longs = table_len / 4;
+        face->horizontal.number_Of_HMetrics = num_longs;
+      }
+
       longs     = (TT_LongMetrics *)&face->horizontal.long_metrics;
       shorts    = (TT_ShortMetrics**)&face->horizontal.short_metrics;
     }
@@ -209,9 +171,8 @@
 
     if ( num_shorts < 0 )
     {
-      FT_ERROR(( "TT_Load_%s_Metrics: more metrics than glyphs!\n",
-                 vertical ? "Vertical"
-                          : "Horizontal" ));
+      FT_ERROR(( "%cmtx: more metrics than glyphs!\n",
+                 vertical ? 'v' : 'h' ));
 
       /* Adobe simply ignores this problem.  So we shall do the same. */
 #if 0
@@ -225,10 +186,10 @@
 
     if ( FT_QNEW_ARRAY( *longs,  num_longs  ) ||
          FT_QNEW_ARRAY( *shorts, num_shorts ) )
-      goto Exit;
+      goto Fail;
 
     if ( FT_FRAME_ENTER( table_len ) )
-      goto Exit;
+      goto Fail;
 
     {
       TT_LongMetrics  cur   = *longs;
@@ -270,7 +231,14 @@
 
     FT_TRACE2(( "loaded\n" ));
 
-  Exit:
+    return SFNT_Err_Ok;
+
+  Fail:
+    if ( error == SFNT_Err_Table_Missing )
+      FT_TRACE2(( "missing\n" ));
+    else
+      FT_TRACE2(( "failed\n" ));
+
     return error;
   }
 
@@ -330,48 +298,27 @@
     };
 
 
-    FT_TRACE2(( vertical ? "Vertical header " : "Horizontal header " ));
+    FT_TRACE2(( "%chea ", vertical ? 'v' : 'h' ));
 
     if ( vertical )
     {
-      face->vertical_info = 0;
-
-      /* The vertical header table is optional, so return quietly if */
-      /* we don't find it.                                           */
       error = face->goto_table( face, TTAG_vhea, stream, 0 );
       if ( error )
-      {
-        error = SFNT_Err_Ok;
-        goto Exit;
-      }
+        goto Fail;
 
-      face->vertical_info = 1;
       header = (TT_HoriHeader*)&face->vertical;
     }
     else
     {
-      /* The horizontal header is mandatory for most fonts; return */
-      /* an error if we don't find it.                             */
       error = face->goto_table( face, TTAG_hhea, stream, 0 );
       if ( error )
-      {
-        error = SFNT_Err_Horiz_Header_Missing;
-
-        /* No `hhea' table necessary for SFNT Mac fonts. */
-        if ( face->format_tag == TTAG_true )
-        {
-          FT_TRACE2(( "missing.  This is an SFNT Mac font.\n"));
-          error = SFNT_Err_Ok;
-        }
-
-        goto Exit;
-      }
+        goto Fail;
 
       header = &face->horizontal;
     }
 
     if ( FT_STREAM_READ_FIELDS( metrics_header_fields, header ) )
-      goto Exit;
+      goto Fail;
 
     header->long_metrics  = NULL;
     header->short_metrics = NULL;
@@ -380,7 +327,12 @@
 
     return SFNT_Err_Ok;
 
-  Exit:
+  Fail:
+    if ( error == SFNT_Err_Table_Missing )
+      FT_TRACE2(( "missing\n" ));
+    else
+      FT_TRACE2(( "failed\n" ));
+
     return error;
   }
 
@@ -388,7 +340,7 @@
   /*************************************************************************/
   /*                                                                       */
   /* <Function>                                                            */
-  /*    tt_face_get_metrics                                                */
+  /*    tt_face_get_metrics                                                */ 
   /*                                                                       */
   /* <Description>                                                         */
   /*    Returns the horizontal or vertical metrics in font units for a     */
@@ -490,7 +442,7 @@
     FT_UShort       k      = header->number_Of_HMetrics;
 
 
-    if ( k == 0 )
+    if ( k == 0 || k >= (FT_UInt)face->max_profile.numGlyphs )
     {
       *abearing = *aadvance = 0;
       return SFNT_Err_Ok;
diff --git a/src/truetype/ttgload.c b/src/truetype/ttgload.c
index deca965..1581113 100644
--- a/src/truetype/ttgload.c
+++ b/src/truetype/ttgload.c
@@ -1158,7 +1158,7 @@
 
       glyph_data_loaded = 1;
       offset            = 0;
-      byte_len          = glyph_data.length;
+      loader->byte_len  = glyph_data.length;
 
       FT_MEM_ZERO( &inc_stream, sizeof ( inc_stream ) );
       FT_Stream_OpenMemory( &inc_stream,