diff --git a/ChangeLog b/ChangeLog index 19c96b2d7..9b4146ae5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,7 @@ 2002-03-30 David Turner + * src/sfnt/sfobjs.c (tt_face_get_name): bug-fix + * include/freetype/internal/tttypes.h: adding comments to some of the TT_FaceRec fields. diff --git a/src/sfnt/sfobjs.c b/src/sfnt/sfobjs.c index 5d866ee43..21d4d71b0 100644 --- a/src/sfnt/sfobjs.c +++ b/src/sfnt/sfobjs.c @@ -38,6 +38,94 @@ #define FT_COMPONENT trace_sfobjs + + /* convert a UTF-16 name entry to ASCII */ + static FT_String* + tt_name_entry_ascii_from_utf16( TT_NameEntry entry, + FT_Memory memory ) + { + FT_String* string; + FT_UInt len, code, n; + FT_Byte* read = (FT_Byte*) entry->string; + + len = (FT_UInt) entry->stringLength/2; + + if ( FT_MEM_NEW_ARRAY( string, len+1 ) ) + return NULL; + + for ( n = 0; n < len; n++ ) + { + code = FT_NEXT_USHORT(read); + if ( code < 32 || code > 127 ) + code = '?'; + + string[n] = (char)code; + } + + string[len] = 0; + + return string; + } + + + /* convert a UCS-4 name entry to ASCII */ + static FT_String* + tt_name_entry_ascii_from_ucs4( TT_NameEntry entry, + FT_Memory memory ) + { + FT_String* string; + FT_UInt len, code, n; + FT_Byte* read = (FT_Byte*) entry->string; + + len = (FT_UInt) entry->stringLength/4; + + if ( FT_MEM_NEW_ARRAY( string, len+1 ) ) + return NULL; + + for ( n = 0; n < len; n++ ) + { + code = FT_NEXT_ULONG(read); + if ( code < 32 || code > 127 ) + code = '?'; + + string[n] = (char)code; + } + + string[len] = 0; + + return string; + } + + + /* convert an Apple Roman or symbol name entry to ASCII */ + static FT_String* + tt_name_entry_ascii_from_other( TT_NameEntry entry, + FT_Memory memory ) + { + FT_String* string; + FT_UInt len, code, n; + FT_Byte* read = (FT_Byte*) entry->string; + + len = (FT_UInt) entry->stringLength; + + if ( FT_MEM_NEW_ARRAY( string, len+1 ) ) + return NULL; + + for ( n = 0; n < len; n++ ) + { + code = *read++; + if ( code < 32 || code > 127 ) + code = '?'; + + string[n] = (char)code; + } + + string[len] = 0; + + return string; + } + + /*************************************************************************/ /* */ /* */ @@ -56,34 +144,48 @@ /* */ static FT_String* tt_face_get_name( TT_Face face, - FT_UShort nameid ) + FT_UShort nameid ) { - FT_Memory memory = face->root.memory; - FT_UShort n; + FT_Memory memory = face->root.memory; + FT_String* result = NULL; + FT_UShort n; TT_NameEntryRec* rec; - FT_Bool wide_chars = 1; - FT_Int found_apple = -1; - FT_Int found_win = -1; - FT_Int found_unicode = -1; - FT_Int found; + FT_Int found_apple = -1; + FT_Int found_win = -1; + FT_Int found_unicode = -1; rec = face->name_table.names; for ( n = 0; n < face->name_table.numNameRecords; n++, rec++ ) { + /* according to the OpenType 1.3 specification, only Microsoft of */ + /* Apple platform ids might be used in the 'name' table. The */ + /* 'Unicode' platform is reserved for the 'cmap' table, and */ + /* the 'Iso' one is deprecated */ + + /* however the Apple TrueType specification doesn't says the same */ + /* thing and goes to suggest that all Unicode 'name' table entries */ + /* should be coded in UTF-16 (in big-endian format I suppose) */ + /* */ if ( rec->nameID == nameid && rec->string ) { switch ( rec->platformID ) { + case TT_PLATFORM_APPLE_UNICODE: + case TT_PLATFORM_ISO: { + /* there is 'languageID' to check there. We should use this */ + /* field only as a last solution when nothing else is */ + /* available.. */ + /* */ found_unicode = n; break; } - + case TT_PLATFORM_MACINTOSH: { - if ( rec->languageID == TT_MAC_ID_ROMAN ) + if ( rec->languageID == TT_MAC_LANGID_ENGLISH ) found_apple = n; break; @@ -91,10 +193,22 @@ case TT_PLATFORM_MICROSOFT: { - if ( rec->encodingID <= TT_MS_ID_UNICODE_CS && - (rec->languageID & 0x3FF) == 0x009 ) + /* we only take a non-English name when there is nothing */ + /* else available in the font.. */ + /* */ + if ( found_win == -1 || (rec->languageID & 0x3FF) == 0x009 ) { - found_win = n; + switch ( rec->encodingID ) + { + case TT_MS_ID_SYMBOL_CS: + case TT_MS_ID_UNICODE_CS: + case TT_MS_ID_UCS_4: + found_win = n; + break; + + default: + ; + } } break; } @@ -109,49 +223,40 @@ /* we will thus favor name encoded in Windows formats when they're */ /* available.. */ /* */ - found = found_win; - if ( found < 0 ) + if ( found_win >= 0 ) { - found = found_apple; - if ( found_apple < 0 ) - found = found_unicode; - else - wide_chars = 0; + rec = face->name_table.names + found_win; + switch ( rec->encodingID ) + { + case TT_MS_ID_UNICODE_CS: + case TT_MS_ID_SYMBOL_CS: + { + result = tt_name_entry_ascii_from_utf16( rec, memory ); + break; + } + + case TT_MS_ID_UCS_4: + { + result = tt_name_entry_ascii_from_ucs4( rec, memory ); + break; + } + + default: + ; + } } - - /* found a Unicode name */ - if ( found >= 0 ) + else if ( found_apple >= 0 ) { - FT_String* string; - FT_UInt len; - - rec = face->name_table.names + found; - if ( wide_chars ) - { - FT_UInt m; - - - len = (FT_UInt)rec->stringLength / 2; - if ( FT_MEM_ALLOC( string, len + 1 ) ) - return NULL; - - for ( m = 0; m < len; m ++ ) - string[m] = rec->string[2 * m + 1]; - } - else - { - len = rec->stringLength; - if ( FT_MEM_ALLOC( string, len + 1 ) ) - return NULL; - - FT_MEM_COPY( string, rec->string, len ); - } - - string[len] = '\0'; - return string; + rec = face->name_table.names + found_apple; + result = tt_name_entry_ascii_from_other( rec, memory ); } - - return NULL; + else if ( found_unicode >= 0 ) + { + rec = face->name_table.names + found_unicode; + result = tt_name_entry_ascii_from_utf16( rec, memory ); + } + + return result; }