shithub: freetype+ttf2subf

Download patch

ref: 540b954574569bc56e4ea61eec67159e88ca4dff
parent: d156cabcaed41beeed2fb92cff2a72302b726435
author: Suzuki, Toshiya (鈴木俊哉) <[email protected]>
date: Fri Dec 21 01:03:59 EST 2007

Improvement of POSIX resource-fork accessor to load Mac OS X HelveLTMM

git/fs: mount .git/fs: mount/attach disallowed
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,21 @@
+2007-12-21  suzuki toshiya  <[email protected]>
+
+	Improvement of POSIX resource-fork accessor to load unsorted
+	references in a resource. In HelveLTMM (resource-fork
+	PostScript Type1 font bundled to Mac OS X since 10.3.x),
+	the appearance order of PFB chunks is not sorted.
+	Sorting the chunks by reference IDs is required.
+
+	* include/freetype/internal/ftrfork.h (FT_RFork_Ref):
+	New structure type to store a pair of reference ID and offset
+	to the chunk.
+
+	* src/base/ftrfork.c (ft_raccess_sort_ref_by_id):
+	New function to sort FT_RFork_Ref by their reference ID.
+
+	(FT_Raccess_Get_DataOffsets): Returns an array of offsets
+	that is sorted by reference ID.
+
 2007-12-14  Werner Lemberg  <[email protected]>
 
 	* src/cff/cffparse.c (cff_parse_real): Don't apply `power_ten'
--- a/include/freetype/internal/ftrfork.h
+++ b/include/freetype/internal/ftrfork.h
@@ -36,6 +36,13 @@
   /* Don't forget to increment the number if you add a new guessing rule. */
 #define FT_RACCESS_N_RULES  9
 
+  /* Structure to describe a reference in resource, by its resource id    */
+  /* and internal offset. `POST' resource expects to be concatenated by   */
+  /* the order of resource id, instead of its appearance in the file.     */
+  typedef struct FT_RFork_Ref_ {
+      FT_UShort  res_id;
+      FT_ULong   offset;
+  } FT_RFork_Ref;
 
   /*************************************************************************/
   /*                                                                       */
--- a/src/base/ftrfork.c
+++ b/src/base/ftrfork.c
@@ -132,6 +132,19 @@
   }
 
 
+  static int
+  ft_raccess_sort_ref_by_id( FT_RFork_Ref*  a,
+                             FT_RFork_Ref*  b )
+  {
+    if ( a->res_id < b->res_id )
+      return ( -1 );
+    else if ( a->res_id > b->res_id )
+      return ( 1 );
+    else
+      return ( 0 );
+  }
+
+
   FT_BASE_DEF( FT_Error )
   FT_Raccess_Get_DataOffsets( FT_Library  library,
                               FT_Stream   stream,
@@ -147,6 +160,7 @@
     FT_Memory  memory = library->memory;
     FT_Long    temp;
     FT_Long    *offsets_internal;
+    FT_RFork_Ref  *ref;
 
 
     error = FT_Stream_Seek( stream, map_offset );
@@ -179,28 +193,42 @@
         if ( error )
           return error;
 
-        if ( FT_NEW_ARRAY( offsets_internal, *count ) )
+        if ( FT_NEW_ARRAY( ref, *count ) )
           return error;
 
         for ( j = 0; j < *count; ++j )
         {
-          (void)FT_STREAM_SKIP( 2 ); /* resource id */
-          (void)FT_STREAM_SKIP( 2 ); /* rsource name */
-
+          if ( FT_READ_USHORT( ref[j].res_id ) )
+            goto Exit;
+          if ( FT_STREAM_SKIP( 2 ) ) /* resource name */
+            goto Exit;
           if ( FT_READ_LONG( temp ) )
-          {
-            FT_FREE( offsets_internal );
-            return error;
-          }
+            goto Exit;
+          if ( FT_STREAM_SKIP( 4 ) ) /* mbz */
+            goto Exit;
 
-          offsets_internal[j] = rdata_pos + ( temp & 0xFFFFFFL );
-
-          (void)FT_STREAM_SKIP( 4 ); /* mbz */
+          ref[j].offset = temp & 0xFFFFFFL;
         }
 
-        *offsets = offsets_internal;
+	ft_qsort( ref, *count, sizeof( FT_RFork_Ref ),
+                  ( int(*)(const void*, const void*) )
+                  ft_raccess_sort_ref_by_id );
 
-        return FT_Err_Ok;
+        if ( FT_NEW_ARRAY( offsets_internal, *count ) )
+          goto Exit;
+
+        /* XXX: duplicated reference ID,
+         *      gap between reference IDs are acceptable?
+         *      further investigation on Apple implementation is needed.
+         */
+        for ( j = 0; j < *count; ++j )
+          offsets_internal[j] = rdata_pos + ref[j].offset;
+
+        *offsets = offsets_internal;
+        error = FT_Err_Ok;
+Exit:
+        FT_FREE( ref );
+        return error;
       }
     }