Commit 9ae5eaf862ee6c3464a98ef5f6e2fbfc929ef37a

Suzuki, Toshiya (鈴木俊哉) 2008-09-19T06:48:35

* src/base/ftobjs.c: Add initial support for sfnt-wrapped CID-keyed fonts

diff --git a/ChangeLog b/ChangeLog
index 86aaf34..5b75144 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2008-09-19  suzuki toshiya  <mpsuzuki@hiroshima-u.ac.jp>
+
+	* src/base/ftobjs.c (Mac_Read_sfnt_Resource): Add initial support
+	for sfnt-wrapped Type1 and sfnt-wrapped CID-keyed font.
+	(ft_lookup_PS_in_sfnt): New function to look up `TYP1' or `CID '
+	table in sfnt table directory. It is used before loading TrueType
+	font driver.
+
 2008-09-18  Werner Lemberg  <wl@gnu.org>
 
 	* src/base/ftsystem.c (FT_Done_Memory): Use ft_sfree directly for
diff --git a/docs/CHANGES b/docs/CHANGES
index c99d3ba..0966816 100644
--- a/docs/CHANGES
+++ b/docs/CHANGES
@@ -2,7 +2,10 @@ CHANGES BETWEEN 2.3.8 and 2.3.7
 
   I. IMPORTANT BUG FIXES
 
-    - CID-keyed fonts in an SFNT wrapper were not handled correctly.
+    - PS Type1 and CID-keyed fonts in an SFNT wrapper were not loaded.
+      In version 2.3.8, the core tables `TYP1' or `CID ' are passed to
+      PS Type1 or CID-keyed font drivers, other tables (`ALMX', `BBOX'
+      etc) are not supported yet.
 
 
 ======================================================================
diff --git a/src/base/ftobjs.c b/src/base/ftobjs.c
index 76ebfe4..dc4905f 100644
--- a/src/base/ftobjs.c
+++ b/src/base/ftobjs.c
@@ -1409,6 +1409,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;
+  }
+
+
   /* The resource header says we've got resource_cnt `sfnt'      */
   /* (TrueType/OpenType) resources in this file.  Look through   */
   /* them for the one indicated by face_index, load it into mem, */
@@ -1428,6 +1481,7 @@
     FT_Long    flag_offset;
     FT_Long    rlen;
     int        is_cff;
+    int        is_sfnt_ps;
     FT_Long    face_index_in_resource = 0;
 
 
@@ -1452,11 +1506,43 @@
     if ( error )
       goto Exit;
 
-    is_cff = rlen > 4 && sfnt_data[0] == 'O' &&
-                         sfnt_data[1] == 'T' &&
-                         sfnt_data[2] == 'T' &&
-                         sfnt_data[3] == 'O';
+    is_cff     = rlen > 4 && !ft_memcmp( sfnt_data, "OTTO", 4 );
+    is_sfnt_ps = rlen > 4 && !ft_memcmp( sfnt_data, "typ1", 4 );
+
+    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_in_resource,
+                                     is_sfnt_cid ? "cid" : "type1",
+                                     aface );
+      if ( !error )
+      {
+        FT_FREE( sfnt_data );
+        goto Exit;
+      }
+
+      FT_FREE( sfnt_ps );
+    }
+  Try_OpenType:
     error = open_face_from_buffer( library,
                                    sfnt_data,
                                    rlen,