Commit 658f530ef54d973b0741df73b0939d906f0f68a1

Werner Lemberg 2016-02-15T14:28:28

[cff] Correctly trace SIDs that contain NULL bytes. We need this to properly trace Multiple Master CFFs, which contain two SIDs that are charstrings. This commit makes FreeType also show the last SID, omitted previously due to a bug. * src/cff/cfftypes.h (CFF_FontRec): Add `string_pool_size' field. * src/cff/cffload.c (cff_index_get_pointers): Add argument to return the pool size. Update all callers. * src/cff/cffobjs.c (cff_face_init) [FT_DEBUG_LEVEL_TRACE]: Directly access `cff->strings' to display the non-default strings.

diff --git a/ChangeLog b/ChangeLog
index 648cb3d..b884755 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,22 @@
+2016-02-15  Werner Lemberg  <wl@gnu.org>
+
+	[cff] Correctly trace SIDs that contain NULL bytes.
+
+	We need this to properly trace Multiple Master CFFs, which contain
+	two SIDs that are charstrings.
+
+	This commit makes FreeType also show the last SID, omitted
+	previously due to a bug.
+
+	* src/cff/cfftypes.h (CFF_FontRec): Add `string_pool_size' field.
+
+	* src/cff/cffload.c (cff_index_get_pointers): Add argument to return
+	the pool size.
+	Update all callers.
+
+	* src/cff/cffobjs.c (cff_face_init) [FT_DEBUG_LEVEL_TRACE]: Directly
+	access `cff->strings' to display the non-default strings.
+
 2016-02-14  Werner Lemberg  <wl@gnu.org>
 
 	* src/base/fthash.c: Include FT_INTERNAL_MEMORY_H.
diff --git a/src/cff/cffload.c b/src/cff/cffload.c
index 2ea4e37..920f10b 100644
--- a/src/cff/cffload.c
+++ b/src/cff/cffload.c
@@ -382,13 +382,15 @@
   static FT_Error
   cff_index_get_pointers( CFF_Index   idx,
                           FT_Byte***  table,
-                          FT_Byte**   pool )
+                          FT_Byte**   pool,
+                          FT_ULong*   pool_size )
   {
     FT_Error   error     = FT_Err_Ok;
     FT_Memory  memory    = idx->stream->memory;
 
     FT_Byte**  t         = NULL;
     FT_Byte*   new_bytes = NULL;
+    FT_ULong   new_size;
 
 
     *table = NULL;
@@ -400,10 +402,11 @@
         goto Exit;
     }
 
-    if ( idx->count > 0                                        &&
-         !FT_NEW_ARRAY( t, idx->count + 1 )                    &&
-         ( !pool || !FT_ALLOC( new_bytes,
-                               idx->data_size + idx->count ) ) )
+    new_size = idx->data_size + idx->count;
+
+    if ( idx->count > 0                                &&
+         !FT_NEW_ARRAY( t, idx->count + 1 )            &&
+         ( !pool || !FT_ALLOC( new_bytes, new_size ) ) )
     {
       FT_ULong  n, cur_offset;
       FT_ULong  extra = 0;
@@ -459,6 +462,8 @@
 
       if ( pool )
         *pool = new_bytes;
+      if ( pool_size )
+        *pool_size = new_size;
     }
 
   Exit:
@@ -1408,7 +1413,7 @@
         goto Exit;
 
       error = cff_index_get_pointers( &font->local_subrs_index,
-                                      &font->local_subrs, NULL );
+                                      &font->local_subrs, NULL, NULL );
       if ( error )
         goto Exit;
     }
@@ -1486,16 +1491,17 @@
 
     /* read the name, top dict, string and global subrs index */
     if ( FT_SET_ERROR( cff_index_init( &font->name_index,
-                                       stream, 0 ) )                  ||
+                                       stream, 0 ) )                       ||
          FT_SET_ERROR( cff_index_init( &font->font_dict_index,
-                                       stream, 0 ) )                  ||
+                                       stream, 0 ) )                       ||
          FT_SET_ERROR( cff_index_init( &string_index,
-                                       stream, 1 ) )                  ||
+                                       stream, 1 ) )                       ||
          FT_SET_ERROR( cff_index_init( &font->global_subrs_index,
-                                       stream, 1 ) )                  ||
+                                       stream, 1 ) )                       ||
          FT_SET_ERROR( cff_index_get_pointers( &string_index,
                                                &font->strings,
-                                               &font->string_pool ) ) )
+                                               &font->string_pool,
+                                               &font->string_pool_size ) ) )
       goto Exit;
 
     font->num_strings = string_index.count;
@@ -1622,7 +1628,7 @@
     font->num_glyphs = font->charstrings_index.count;
 
     error = cff_index_get_pointers( &font->global_subrs_index,
-                                    &font->global_subrs, NULL );
+                                    &font->global_subrs, NULL, NULL );
 
     if ( error )
       goto Exit;
diff --git a/src/cff/cffobjs.c b/src/cff/cffobjs.c
index e22ae82..52fd0ec 100644
--- a/src/cff/cffobjs.c
+++ b/src/cff/cffobjs.c
@@ -625,11 +625,44 @@
         FT_TRACE4(( "SIDs\n" ));
 
         /* dump string index, including default strings for convenience */
-        for ( idx = 0; idx < cff->num_strings + 390; idx++ )
+        for ( idx = 0; idx <= 390; idx++ )
         {
           s = cff_index_get_sid_string( cff, idx );
           if ( s )
-            FT_TRACE4(("  %5d %s\n", idx, s ));
+            FT_TRACE4(( "  %5d %s\n", idx, s ));
+        }
+
+        /* In Multiple Master CFFs, two SIDs hold the Normalize Design  */
+        /* Vector (NDV) and Convert Design Vector (CDV) charstrings,    */
+        /* which may contain NULL bytes in the middle of the data, too. */
+        /* We thus access `cff->strings' directly.                      */
+        for ( idx = 1; idx < cff->num_strings; idx++ )
+        {
+          FT_Byte*  s1    = cff->strings[idx - 1];
+          FT_Byte*  s2    = cff->strings[idx];
+          size_t    s1len = s2 - s1 - 1; /* without the final NULL byte */
+          size_t    l;
+
+
+          FT_TRACE4(( "  %5d ", idx + 390, s ));
+          for ( l = 0; l < s1len; l++ )
+            FT_TRACE4(( "%c", s1[l] ));
+          FT_TRACE4(( "\n" ));
+        }
+
+        /* print last element */
+        if ( cff->num_strings )
+        {
+          FT_Byte*  s1    = cff->strings[cff->num_strings - 1];
+          FT_Byte*  s2    = cff->string_pool + cff->string_pool_size;
+          size_t    s1len = s2 - s1 - 1;
+          size_t    l;
+
+
+          FT_TRACE4(( "  %5d ", cff->num_strings + 390, s ));
+          for ( l = 0; l < s1len; l++ )
+            FT_TRACE4(( "%c", s1[l] ));
+          FT_TRACE4(( "\n" ));
         }
       }
 #endif /* FT_DEBUG_LEVEL_TRACE */
diff --git a/src/cff/cfftypes.h b/src/cff/cfftypes.h
index 10fe937..b2320fd 100644
--- a/src/cff/cfftypes.h
+++ b/src/cff/cfftypes.h
@@ -255,6 +255,7 @@ FT_BEGIN_HEADER
     FT_UInt          num_strings;
     FT_Byte**        strings;
     FT_Byte*         string_pool;
+    FT_ULong         string_pool_size;
 
     CFF_SubFontRec   top_font;
     FT_UInt          num_subfonts;