diff --git a/ChangeLog b/ChangeLog index 96856a0dc..f8ce13527 100644 --- a/ChangeLog +++ b/ChangeLog @@ -11,6 +11,16 @@ caused the CID driver to return Postscript font names with a leading slash ("/") as in "/MOEKai-Regular" + * src/sfnt/ttload.c (TT_Load_Names), src/sfnt/sfobjs.c (Get_Name), + src/sfnt/sfdriver.c (get_sfnt_postscript_name): Fixed the loader so + that it accepts broken fonts like "foxjump.ttf", which made FreeType + crash when trying to load them. + + Also improved the name table parser to be able to load + Windows-encoded entries before Macintosh or Unicode ones, since it + seems some fonts don't have reliable values here anyway. + + 2002-03-05 Werner Lemberg * builds/unix/aclocal.m4, builds/unix/ltmain.sh: Update to libtool diff --git a/src/sfnt/sfdriver.c b/src/sfnt/sfdriver.c index e023c0b16..af92ed206 100644 --- a/src/sfnt/sfdriver.c +++ b/src/sfnt/sfdriver.c @@ -114,7 +114,7 @@ static const char* get_sfnt_postscript_name( TT_Face face ) { - FT_Int n; + FT_Int n, found_win, found_apple; /* shouldn't happen, but just in case to avoid memory leaks */ @@ -123,41 +123,66 @@ /* scan the name table to see whether we have a Postscript name here, */ /* either in Macintosh or Windows platform encodings */ + found_win = -1; + found_apple = -1; + for ( n = 0; n < face->num_names; n++ ) { TT_NameRec* name = face->name_table.names + n; - if ( name->nameID == 6 ) + if ( name->nameID == 6 && name->string != NULL ) { - if ( ( name->platformID == 3 && - name->encodingID == 1 && - name->languageID == 0x409 ) || - - ( name->platformID == 1 && - name->encodingID == 0 && - name->languageID == 0 ) ) - { - FT_UInt len = name->stringLength; - FT_Error error; - FT_Memory memory = face->root.memory; - FT_String* result; - - - if ( !ALLOC( result, len + 1 ) ) - { - memcpy( result, name->string, len ); - result[len] = '\0'; - - face->root.internal->postscript_name = result; - } - - FT_UNUSED( error ); - - return result; - } + if ( name->platformID == 3 && + name->encodingID == 1 && + name->languageID == 0x409 ) + found_win = n; + + if ( name->platformID == 1 && + name->encodingID == 0 && + name->languageID == 0 ) + found_apple = n; } } + + if ( found_win ) + { + FT_Memory memory = face->root.memory; + TT_NameRec* name = face->name_table.names + found_win; + FT_UInt len = name->stringLength/2; + FT_Error error; + FT_String* result; + + if ( !ALLOC( result, len+1 ) ) + { + FT_String* r = result; + FT_Byte* p = (FT_Byte*) name->string; + + for ( ; len > 0; len--, p += 2 ) + { + if ( p[0] == 0 && p[1] >= 32 && p[1] < 128 ) + *r++ = p[1]; + } + *r = '\0'; + } + return result; + } + + if ( found_apple ) + { + FT_Memory memory = face->root.memory; + TT_NameRec* name = face->name_table.names + found_win; + FT_UInt len = name->stringLength; + FT_Error error; + FT_String* result; + + if ( !ALLOC( result, len+1 ) ) + { + MEM_Copy( result, name->string, len ); + result[len] = '\0'; + } + return result; + } return NULL; } diff --git a/src/sfnt/sfobjs.c b/src/sfnt/sfobjs.c index 967c93c10..03db1820a 100644 --- a/src/sfnt/sfobjs.c +++ b/src/sfnt/sfobjs.c @@ -60,70 +60,96 @@ FT_Memory memory = face->root.memory; FT_UShort n; TT_NameRec* rec; - FT_Bool wide_chars = 1; + FT_Bool wide_chars = 1; + FT_Int found_apple = -1; + FT_Int found_win = -1; + FT_Int found_unicode = -1; + FT_Int found; rec = face->name_table.names; for ( n = 0; n < face->name_table.numNameRecords; n++, rec++ ) { - if ( rec->nameID == nameid ) + if ( rec->nameID == nameid && rec->string ) { - /* found the name -- now create an ASCII string from it */ - FT_Bool found = 0; - - - /* test for Microsoft English language */ - if ( rec->platformID == TT_PLATFORM_MICROSOFT && - rec->encodingID <= TT_MS_ID_UNICODE_CS && - ( rec->languageID & 0x3FF ) == 0x009 ) - found = 1; - - /* test for Apple Unicode encoding */ - else if ( rec->platformID == TT_PLATFORM_APPLE_UNICODE ) - found = 1; - - /* test for Apple Roman */ - else if ( rec->platformID == TT_PLATFORM_MACINTOSH && - rec->languageID == TT_MAC_ID_ROMAN ) + switch ( rec->platformID ) { - found = 1; - wide_chars = 0; - } - - /* found a Unicode name */ - if ( found ) - { - FT_String* string; - FT_UInt len; - - - if ( wide_chars ) - { - FT_UInt m; - - - len = (FT_UInt)rec->stringLength / 2; - if ( 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 ( MEM_Alloc( string, len + 1 ) ) - return NULL; - - MEM_Copy( string, rec->string, len ); - } - - string[len] = '\0'; - return string; + case TT_PLATFORM_APPLE_UNICODE: + { + found_unicode = n; + break; + } + + case TT_PLATFORM_MACINTOSH: + { + if ( rec->languageID == TT_MAC_ID_ROMAN ) + found_apple = n; + + break; + } + + case TT_PLATFORM_MICROSOFT: + { + if ( rec->encodingID <= TT_MS_ID_UNICODE_CS && + (rec->languageID & 0x3FF) == 0x009 ) + { + found_win = n; + } + break; + } + + default: + ; } } } + /* some fonts contain invalid Unicode or Macintosh formatted entries */ + /* we will thus favor name encoded in Windows formats when they're */ + /* available.. */ + /* */ + found = found_win; + if ( found < 0 ) + { + found = found_apple; + if ( found_apple < 0 ) + found = found_unicode; + else + wide_chars = 0; + } + + /* found a Unicode name */ + if ( found >= 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 ( 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 ( MEM_Alloc( string, len + 1 ) ) + return NULL; + + MEM_Copy( string, rec->string, len ); + } + + string[len] = '\0'; + return string; + } + return NULL; } diff --git a/src/sfnt/ttload.c b/src/sfnt/ttload.c index 4127bbd1d..84ae9bcfd 100644 --- a/src/sfnt/ttload.c +++ b/src/sfnt/ttload.c @@ -1003,15 +1003,18 @@ for ( ; cur < limit; cur ++ ) { - FT_ULong upper; - - if ( READ_Fields( name_record_fields, cur ) ) break; /* invalid name entries will have "cur->string" set to NULL !! */ if ( (FT_ULong)(cur->stringOffset + cur->stringLength) < storageSize ) cur->string = storage + cur->stringOffset; + else + { + /* that's an invalid entry */ + cur->stringOffset = 0; + cur->string = NULL; + } } } @@ -1020,6 +1023,12 @@ if (error) goto Exit; + storageOffset -= 6 + 12*names->numNameRecords; + if ( FILE_Skip( storageOffset ) || + FILE_Read( storage, storageSize ) ) + goto Exit; + + #ifdef FT_DEBUG_LEVEL_TRACE /* Print Name Record Table in case of debugging */