Commit 3afbee82fef0333f44e0d29d5ef48ecde535069d

Suzuki, Toshiya (鈴木俊哉) 2008-09-19T17:46:01

* ftmac.c: Import sfnt-wrapped Type1/CID font support

diff --git a/ChangeLog b/ChangeLog
index 303b640..16e464e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,11 @@
 2008-09-19  suzuki toshiya  <mpsuzuki@hiroshima-u.ac.jp>
 
+	* src/base/ftmac.c: Import sfnt-wrapped Type1 and sfnt-wrapped
+	CID-keyed font support.
+	* builds/mac/ftmac.c: Ditto.
+
+2008-09-19  suzuki toshiya  <mpsuzuki@hiroshima-u.ac.jp>
+
 	* src/base/ftobjs.c (Mac_Read_sfnt_Resource): Fix double free bug
 	in sfnt-wrapped Type1 and sfnt-wrapped CID-keyed font support code.
 	open_face_from_buffer() frees the passed buffer when it cannot
diff --git a/builds/mac/ftmac.c b/builds/mac/ftmac.c
index ef45dca..2484434 100644
--- a/builds/mac/ftmac.c
+++ b/builds/mac/ftmac.c
@@ -1208,6 +1208,59 @@ typedef short ResourceIndex;
   }
 
 
+  /* Look up `TYP1' or `CID ' table from sfnt table directory. */
+  /* offset & length must exclude the binary header in tables. */
+
+  /* For proper support, PS Type1 and CID-keyed font drivers  */
+  /* should recognize sfnt-wrapped format. Here, yet TrueType */
+  /* font driver is not loaded, we must parse by ourselves.   */
+  /* We only care the name of table and offset. */
+
+  static FT_Error
+  ft_lookup_PS_in_sfnt( FT_Byte*   sfnt,
+                        FT_ULong*  offset,
+                        FT_ULong*  length,
+                        FT_Bool*   is_sfnt_cid )
+  {
+    FT_Byte*   p = sfnt + 4; /* skip version `typ1' */
+    FT_UShort  numTables = FT_NEXT_USHORT( p );
+
+
+    p += ( 2 * 3 ); /* skip binary search header */
+    for ( ; numTables > 0 ; numTables -- )
+    {
+      FT_ULong  tag = FT_NEXT_ULONG( p );
+
+
+      p += 4; /* skip checkSum */
+      *offset = FT_NEXT_ULONG( p );
+      *length = FT_NEXT_ULONG( p );
+
+      /* see Adobe TN# 5180 for binary header in CID table */
+      if ( tag == FT_MAKE_TAG( 'C', 'I', 'D', ' ' ) )
+      {
+        *offset += 22;
+        *length -= 22;
+        *is_sfnt_cid = TRUE;
+        return FT_Err_Ok;
+      }
+
+      /* see Apple "The Type 1 GX Font Format" */
+      if ( tag == FT_MAKE_TAG( 'T', 'Y', 'P', '1' ) )
+      {
+        *offset += 24;
+        *length -= 24;
+        *is_sfnt_cid = FALSE;
+        return FT_Err_Ok;
+      }
+    }
+
+    *offset = 0;
+    *length = 0;
+    return FT_Err_Invalid_Table;
+  }
+
+
   /* Create a new FT_Face from an SFNT resource, specified by res ID. */
   static FT_Error
   FT_New_Face_From_SFNT( FT_Library  library,
@@ -1220,7 +1273,7 @@ typedef short ResourceIndex;
     size_t     sfnt_size;
     FT_Error   error  = FT_Err_Ok;
     FT_Memory  memory = library->memory;
-    int        is_cff;
+    int        is_cff, is_sfnt_ps;
 
 
     sfnt = GetResource( FT_MAKE_TAG( 's', 'f', 'n', 't' ), sfnt_id );
@@ -1239,17 +1292,49 @@ typedef short ResourceIndex;
     HUnlock( sfnt );
     ReleaseResource( sfnt );
 
-    is_cff = sfnt_size > 4 && sfnt_data[0] == 'O' &&
-                              sfnt_data[1] == 'T' &&
-                              sfnt_data[2] == 'T' &&
-                              sfnt_data[3] == 'O';
+    is_cff     = sfnt_size > 4 && !ft_memcmp( sfnt_data, "OTTO", 4 );
+    is_sfnt_ps = sfnt_size > 4 && !ft_memcmp( sfnt_data, "typ1", 4 );
 
-    return open_face_from_buffer( library,
-                                  sfnt_data,
-                                  sfnt_size,
-                                  face_index,
-                                  is_cff ? "cff" : "truetype",
-                                  aface );
+    if ( is_sfnt_ps )
+    {
+      FT_ULong  offset, length;
+      FT_Bool   is_sfnt_cid;
+      FT_Byte*  sfnt_ps;
+
+
+      error = ft_lookup_PS_in_sfnt( sfnt_data,
+                                    &offset,
+                                    &length,
+                                    &is_sfnt_cid );
+      if ( error )
+        goto Try_OpenType;
+
+
+      if ( FT_ALLOC( sfnt_ps, (FT_Long)length ) )
+        return error;
+      ft_memcpy( sfnt_ps, sfnt_data + offset, length );
+
+      error = open_face_from_buffer( library,
+                                     sfnt_ps,
+                                     length,
+                                     face_index,
+                                     is_sfnt_cid ? "cid" : "type1",
+                                     aface );
+      if ( !error )
+      {
+        FT_FREE( sfnt_data );
+        goto Exit;
+      }
+    }
+  Try_OpenType:
+    error = open_face_from_buffer( library,
+                                   sfnt_data,
+                                   sfnt_size,
+                                   face_index,
+                                   is_cff ? "cff" : "truetype",
+                                   aface );
+  Exit:
+    return error;
   }
 
 
diff --git a/src/base/ftmac.c b/src/base/ftmac.c
index a799817..4a52d76 100644
--- a/src/base/ftmac.c
+++ b/src/base/ftmac.c
@@ -829,6 +829,59 @@
   }
 
 
+  /* Look up `TYP1' or `CID ' table from sfnt table directory. */
+  /* offset & length must exclude the binary header in tables. */
+
+  /* For proper support, PS Type1 and CID-keyed font drivers  */
+  /* should recognize sfnt-wrapped format. Here, yet TrueType */
+  /* font driver is not loaded, we must parse by ourselves.   */
+  /* We only care the name of table and offset. */
+
+  static FT_Error
+  ft_lookup_PS_in_sfnt( FT_Byte*   sfnt,
+                        FT_ULong*  offset,
+                        FT_ULong*  length,
+                        FT_Bool*   is_sfnt_cid )
+  {
+    FT_Byte*   p = sfnt + 4; /* skip version `typ1' */
+    FT_UShort  numTables = FT_NEXT_USHORT( p );
+
+
+    p += ( 2 * 3 ); /* skip binary search header */
+    for ( ; numTables > 0 ; numTables -- )
+    {
+      FT_ULong  tag = FT_NEXT_ULONG( p );
+
+
+      p += 4; /* skip checkSum */
+      *offset = FT_NEXT_ULONG( p );
+      *length = FT_NEXT_ULONG( p );
+
+      /* see Adobe TN# 5180 for binary header in CID table */
+      if ( tag == FT_MAKE_TAG( 'C', 'I', 'D', ' ' ) )
+      {
+        *offset += 22;
+        *length -= 22;
+        *is_sfnt_cid = TRUE;
+        return FT_Err_Ok;
+      }
+
+      /* see Apple "The Type 1 GX Font Format" */
+      if ( tag == FT_MAKE_TAG( 'T', 'Y', 'P', '1' ) )
+      {
+        *offset += 24;
+        *length -= 24;
+        *is_sfnt_cid = FALSE;
+        return FT_Err_Ok;
+      }
+    }
+
+    *offset = 0;
+    *length = 0;
+    return FT_Err_Invalid_Table;
+  }
+
+
   /* Create a new FT_Face from an SFNT resource, specified by res ID. */
   static FT_Error
   FT_New_Face_From_SFNT( FT_Library  library,
@@ -841,7 +894,7 @@
     size_t     sfnt_size;
     FT_Error   error  = FT_Err_Ok;
     FT_Memory  memory = library->memory;
-    int        is_cff;
+    int        is_cff, is_sfnt_ps;
 
 
     sfnt = GetResource( FT_MAKE_TAG( 's', 'f', 'n', 't' ), sfnt_id );
@@ -858,17 +911,49 @@
     ft_memcpy( sfnt_data, *sfnt, sfnt_size );
     ReleaseResource( sfnt );
 
-    is_cff = sfnt_size > 4 && sfnt_data[0] == 'O' &&
-                              sfnt_data[1] == 'T' &&
-                              sfnt_data[2] == 'T' &&
-                              sfnt_data[3] == 'O';
+    is_cff     = sfnt_size > 4 && !ft_memcmp( sfnt_data, "OTTO", 4 );
+    is_sfnt_ps = sfnt_size > 4 && !ft_memcmp( sfnt_data, "typ1", 4 );
 
-    return open_face_from_buffer( library,
-                                  sfnt_data,
-                                  sfnt_size,
-                                  face_index,
-                                  is_cff ? "cff" : "truetype",
-                                  aface );
+    if ( is_sfnt_ps )
+    {
+      FT_ULong  offset, length;
+      FT_Bool   is_sfnt_cid;
+      FT_Byte*  sfnt_ps;
+
+
+      error = ft_lookup_PS_in_sfnt( sfnt_data,
+                                    &offset,
+                                    &length,
+                                    &is_sfnt_cid );
+      if ( error )
+        goto Try_OpenType;
+
+
+      if ( FT_ALLOC( sfnt_ps, (FT_Long)length ) )
+        return error;
+      ft_memcpy( sfnt_ps, sfnt_data + offset, length );
+
+      error = open_face_from_buffer( library,
+                                     sfnt_ps,
+                                     length,
+                                     face_index,
+                                     is_sfnt_cid ? "cid" : "type1",
+                                     aface );
+      if ( !error )
+      {
+        FT_FREE( sfnt_data );
+        goto Exit;
+      }
+    }
+  Try_OpenType:
+    error = open_face_from_buffer( library,
+                                   sfnt_data,
+                                   sfnt_size,
+                                   face_index,
+                                   is_cff ? "cff" : "truetype",
+                                   aface );
+  Exit:
+    return error;
   }