ref: 3afbee82fef0333f44e0d29d5ef48ecde535069d
parent: dec8e7b97dd10e72890f785c98c9cd8fae8185b6
author: Suzuki, Toshiya (鈴木俊哉) <[email protected]>
date: Fri Sep 19 13:46:01 EDT 2008
* ftmac.c: Import sfnt-wrapped Type1/CID font support
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,11 @@
2008-09-19 suzuki toshiya <[email protected]>
+ * 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 <[email protected]>
+
* 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
--- a/builds/mac/ftmac.c
+++ b/builds/mac/ftmac.c
@@ -1208,6 +1208,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,
@@ -1220,7 +1273,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 );
@@ -1239,17 +1292,49 @@
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;
}
--- 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;
}