Commit 1137d04f85079ff3b96b148ebcfed39690fdb09e

Suzuki, Toshiya (鈴木俊哉) 2008-10-04T07:11:58

* New function `open_face_PS_from_sfnt_stream' to check and open a Type1 PS or CID-keyed font in an sfnt stream.

diff --git a/ChangeLog b/ChangeLog
index d784856..ff89f68 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,19 @@
+2008-10-04  suzuki toshiya  <mpsuzuki@hiroshima-u.ac.jp>
+
+	* src/base/ftobjs.c (ft_lookup_PS_in_sfnt): Replaced by...
+	(ft_lookup_PS_in_sfnt_stream): This.
+	(open_face_PS_from_sfnt_stream): New function. It checks
+	whether the stream is sfnt-wrapped Type1 PS font or sfnt-
+	wrapped CID-keyed font, then try to open a face for given
+	face_index.
+	(Mac_Read_sfnt_Resource): Replace the combination of
+	`ft_lookup_PS_in_sfnt' and `open_face_from_buffer' by
+	`open_face_PS_from_sfnt_stream'.
+	* src/base/ftmac.c (FT_New_Face_From_SFNT): Ditto.
+	* builds/mac/ftmac.c (FT_New_Face_From_SFNT): Ditto.
+	* src/base/ftbase.h: Remove `ft_lookup_PS_in_sfnt' and add
+	`open_face_PS_from_sfnt_stream'.
+
 2008-10-03  suzuki toshiya  <mpsuzuki@hiroshima-u.ac.jp>
 
 	* src/base/ftobjs.c (ft_lookup_PS_in_sfnt): Set *is_sfnt_cid
diff --git a/builds/mac/ftmac.c b/builds/mac/ftmac.c
index 77f025e..b2d56b8 100644
--- a/builds/mac/ftmac.c
+++ b/builds/mac/ftmac.c
@@ -1142,34 +1142,26 @@ typedef short ResourceIndex;
 
     if ( is_sfnt_ps )
     {
-      FT_ULong  offset, length;
-      FT_Bool   is_sfnt_cid;
-      FT_Byte*  sfnt_ps;
+      FT_Stream  stream;
 
 
-      error = ft_lookup_PS_in_sfnt( sfnt_data,
-                                    &offset,
-                                    &length,
-                                    &is_sfnt_cid );
-      if ( error )
+      if ( FT_NEW( stream ) )
         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_Stream_OpenMemory( stream, sfnt_data, sfnt_size );
+      if ( !open_face_PS_from_sfnt_stream( library,
+                                           stream,
+                                           face_index,
+                                           0, NULL,
+                                           aface ) )
       {
+        FT_Stream_Close( stream );
+        FT_FREE( stream );
         FT_FREE( sfnt_data );
         goto Exit;
       }
+
+      FT_FREE( stream );
     }
   Try_OpenType:
     error = open_face_from_buffer( library,
diff --git a/src/base/ftbase.h b/src/base/ftbase.h
index a201583..d8c18ab 100644
--- a/src/base/ftbase.h
+++ b/src/base/ftbase.h
@@ -27,14 +27,16 @@
 FT_BEGIN_HEADER
 
 
-  /* Check whether the sfnt image in the buffer is sfnt-wrapped PS Type1 */
-  /* or sfnt-wrapped CID-keyed font.                                     */
+  /* Assume the stream is sfnt-wrapped PS Type1 or sfnt-wrapped CID-keyed */
+  /* font, and try to load a face specified by the face_index.            */
   FT_LOCAL_DEF( FT_Error )
-  ft_lookup_PS_in_sfnt( FT_Byte*   sfnt,
-                        FT_ULong*  offset,
-                        FT_ULong*  length,
-                        FT_Bool*   is_sfnt_cid );
- 
+  open_face_PS_from_sfnt_stream( FT_Library    library,
+                                 FT_Stream     stream,
+                                 FT_Long       face_index,
+                                 FT_Int        num_params,
+                                 FT_Parameter  *params,
+                                 FT_Face       *aface );
+
 
   /* Create a new FT_Face given a buffer and a driver name. */
   /* From ftmac.c.                                          */
diff --git a/src/base/ftmac.c b/src/base/ftmac.c
index 4c47138..b9d11ae 100644
--- a/src/base/ftmac.c
+++ b/src/base/ftmac.c
@@ -761,36 +761,27 @@
 
     if ( is_sfnt_ps )
     {
-      FT_ULong  offset, length;
-      FT_Bool   is_sfnt_cid;
-      FT_Byte*  sfnt_ps;
+      FT_Stream  stream;
 
 
-      error = ft_lookup_PS_in_sfnt( sfnt_data,
-                                    &offset,
-                                    &length,
-                                    &is_sfnt_cid );
-      if ( error )
+      if ( FT_NEW( stream ) )
         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_Stream_OpenMemory( stream, sfnt_data, sfnt_size );
+      if ( !open_face_PS_from_sfnt_stream( library,
+                                           stream,
+                                           face_index,
+                                           0, NULL,
+                                           aface ) )
       {
+        FT_Stream_Close( stream );
+        FT_FREE( stream );
         FT_FREE( sfnt_data );
         goto Exit;
       }
-    }
 
+      FT_FREE( stream );
+    }
   Try_OpenType:
     error = open_face_from_buffer( library,
                                    sfnt_data,
diff --git a/src/base/ftobjs.c b/src/base/ftobjs.c
index b799a31..a8fe744 100644
--- a/src/base/ftobjs.c
+++ b/src/base/ftobjs.c
@@ -1323,50 +1323,117 @@
   /* ourselves.  We are only interested in the name of the table and */
   /* the offset.                                                     */
 
-  FT_LOCAL_DEF( FT_Error )
-  ft_lookup_PS_in_sfnt( FT_Byte*   sfnt,
-                        FT_ULong*  offset,
-                        FT_ULong*  length,
-                        FT_Bool*   is_sfnt_cid )
+  static FT_Error
+  ft_lookup_PS_in_sfnt_stream( FT_Stream  stream,
+                               FT_Long    face_index,
+                               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 );
+    FT_Error   error;
+    FT_UShort  numTables;
+    FT_Long    pstable_index;
+    FT_ULong   tag;
+    int        i;
 
 
-    p += 2 * 3;              /* skip binary search header */
+    *offset = 0;
+    *length = 0;
+    *is_sfnt_cid = TRUE;
+    /* TODO: support for sfnt-wrapped PS/CID in TTC format */
+    *is_sfnt_cid = FALSE;
 
-    for ( ; numTables > 0 ; numTables -- )
-    {
-      FT_ULong  tag = FT_NEXT_ULONG( p );
+    /* version check for 'typ1' (should be ignored?) */
+    if ( FT_READ_ULONG( tag ) )
+      return error;
+    if ( tag != FT_MAKE_TAG( 't', 'y', 'p', '1' ) )
+      return FT_Err_Unknown_File_Format;
+
+
+    if ( FT_READ_USHORT( numTables ) )
+      return error;
+    if ( FT_STREAM_SKIP( 2 * 3 ) ) /* skip binary search header */
+      return error;
 
 
-      p += 4; /* skip checkSum */
-      *offset = FT_NEXT_ULONG( p );
-      *length = FT_NEXT_ULONG( p );
+    pstable_index = -1;
+    *is_sfnt_cid = FALSE;
+    for ( i = 0; i < numTables; i ++ )
+    {
+      if ( FT_READ_ULONG( tag )     || FT_STREAM_SKIP( 4 )     ||
+           FT_READ_ULONG( *offset ) || FT_READ_ULONG( *length ) )
+        return error;
 
-      /* see Adobe TN# 5180 for binary header in CID table */
       if ( tag == FT_MAKE_TAG( 'C', 'I', 'D', ' ' ) )
       {
+        pstable_index ++;
         *offset += 22;
         *length -= 22;
         *is_sfnt_cid = TRUE;
-        return FT_Err_Ok;
+        if ( face_index < 0 )
+          return FT_Err_Ok;
       }
-
-      /* see Apple's `The Type 1 GX Font Format' */
-      if ( tag == FT_MAKE_TAG( 'T', 'Y', 'P', '1' ) )
+      else if ( tag == FT_MAKE_TAG( 'T', 'Y', 'P', '1' ) )
       {
+        pstable_index ++;
         *offset += 24;
         *length -= 24;
         *is_sfnt_cid = FALSE;
-        return FT_Err_Ok;
+        if ( face_index < 0 )
+          return FT_Err_Ok;
       }
+      if ( face_index >= 0 && pstable_index == face_index )
+        return FT_Err_Ok;
     }
+    return FT_Err_Table_Missing;
+  }
 
-    *offset = 0;
-    *length = 0;
-    *is_sfnt_cid = FALSE;
-    return FT_Err_Invalid_Table;
+
+  FT_LOCAL_DEF( FT_Error )
+  open_face_PS_from_sfnt_stream( FT_Library    library,
+                                 FT_Stream     stream,
+                                 FT_Long       face_index,
+                                 FT_Int        num_params,
+                                 FT_Parameter  *params,
+                                 FT_Face       *aface )
+  {
+    FT_Error   error;
+    FT_Memory  memory = library->memory;
+    FT_ULong   offset, length;
+    FT_Long    pos;
+    FT_Bool    is_sfnt_cid;
+    FT_Byte*   sfnt_ps;
+
+
+    pos = FT_Stream_Pos( stream );
+
+    error = ft_lookup_PS_in_sfnt_stream( stream,
+                                         face_index,
+                                         &offset,
+                                         &length,
+                                         &is_sfnt_cid );
+    if ( error )
+      return error;
+
+    if ( FT_Stream_Seek( stream, pos + offset ) )
+      goto Exit;
+
+    if ( FT_ALLOC( sfnt_ps, (FT_Long)length ) )
+      goto Exit;
+
+    error = FT_Stream_Read( stream, (FT_Byte *)sfnt_ps, length );
+    if ( error )
+      goto Exit;
+
+    error = open_face_from_buffer( library,
+                                   sfnt_ps,
+                                   length,
+                                   face_index < 0 ? face_index : 0,
+                                   is_sfnt_cid ? "cid" : "type1",
+                                   aface );
+  Exit:
+    FT_Stream_Seek( stream, pos );
+    return error;
   }
 
 
@@ -1508,7 +1575,6 @@
     FT_Long    flag_offset;
     FT_Long    rlen;
     int        is_cff;
-    int        is_sfnt_ps;
     FT_Long    face_index_in_resource = 0;
 
 
@@ -1527,48 +1593,21 @@
     if ( rlen == -1 )
       return FT_Err_Cannot_Open_Resource;
 
+    error = open_face_PS_from_sfnt_stream( library,
+                                           stream,
+                                           face_index,
+                                           0, NULL,
+                                           aface );
+    if ( !error )
+      goto Exit;
+
     if ( FT_ALLOC( sfnt_data, (FT_Long)rlen ) )
       return error;
     error = FT_Stream_Read( stream, (FT_Byte *)sfnt_data, rlen );
     if ( error )
       goto Exit;
 
-    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;
-      }
-    }
-
-  Try_OpenType:
+    is_cff = rlen > 4 && !ft_memcmp( sfnt_data, "OTTO", 4 );
     error = open_face_from_buffer( library,
                                    sfnt_data,
                                    rlen,