diff --git a/ChangeLog b/ChangeLog index 3f5877fb7..12a54606c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,22 @@ +2006-02-13 Chia-I Wu + + Clean up the SFNT_Interface. In this pass, we want to treat the font + directory (offset table and table directory) as a normal table like + the others. This also means that TTC is no longer recognized there, + but in `init_face'. + + * include/freetype/internal/sfnt.h (SFNT_Interface), + src/sfnt/sfdriver.c: `load_sfnt_header' and `load_directory' are + combined and renamed to `load_font_dir'. + + * src/sfnt/ttload.h, src/sfnt/ttload.c: + s/sfnt_dir_check/check_table_dir/. + `sfnt_init' is moved to sfobjs.c and renamed to `sfnt_open_font'. + `tt_face_load_sfnt_header' and `tt_face_load_directory' are combined + and renamed to `tt_face_load_font_dir'. + + * src/sfnt/sfobjs.c (sfnt_init_face): Recognize TTC here. + 2006-02-13 Chia-I Wu Clean up the SFNT_Interface. Table loading functions are now named diff --git a/include/freetype/internal/sfnt.h b/include/freetype/internal/sfnt.h index 5753a0620..4d54fb35d 100644 --- a/include/freetype/internal/sfnt.h +++ b/include/freetype/internal/sfnt.h @@ -125,73 +125,6 @@ FT_BEGIN_HEADER (*TT_Done_Face_Func)( TT_Face face ); - /*************************************************************************/ - /* */ - /* */ - /* TT_Load_SFNT_HeaderRec_Func */ - /* */ - /* */ - /* Load the header of a SFNT font file. Supports collections. */ - /* */ - /* */ - /* face :: A handle to the target face object. */ - /* */ - /* stream :: The input stream. */ - /* */ - /* face_index :: The index of the TrueType font, if we are opening a */ - /* collection. */ - /* */ - /* */ - /* sfnt :: The SFNT header. */ - /* */ - /* */ - /* FreeType error code. 0 means success. */ - /* */ - /* */ - /* The stream cursor must be at the font file's origin. */ - /* */ - /* This function recognizes fonts embedded in a `TrueType */ - /* collection'. */ - /* */ - /* This function checks that the header is valid by looking at the */ - /* values of `search_range', `entry_selector', and `range_shift'. */ - /* */ - typedef FT_Error - (*TT_Load_SFNT_HeaderRec_Func)( TT_Face face, - FT_Stream stream, - FT_Long face_index, - SFNT_Header sfnt ); - - - /*************************************************************************/ - /* */ - /* */ - /* TT_Load_Directory_Func */ - /* */ - /* */ - /* Load the table directory into a face object. */ - /* */ - /* */ - /* face :: A handle to the target face object. */ - /* */ - /* stream :: The input stream. */ - /* */ - /* sfnt :: The SFNT header. */ - /* */ - /* */ - /* FreeType error code. 0 means success. */ - /* */ - /* */ - /* The stream cursor must be on the first byte after the 4-byte font */ - /* format tag. This is the case just after a call to */ - /* TT_Load_Format_Tag(). */ - /* */ - typedef FT_Error - (*TT_Load_Directory_Func)( TT_Face face, - FT_Stream stream, - SFNT_Header sfnt ); - - /*************************************************************************/ /* */ /* */ @@ -505,7 +438,7 @@ FT_BEGIN_HEADER /* */ /* */ /* The function will use `face->goto_table' to seek the stream to */ - /* the start of the table. */ + /* the start of the table, except in loading font directory. */ /* */ typedef FT_Error (*TT_Load_Table_Func)( TT_Face face, @@ -570,8 +503,10 @@ FT_BEGIN_HEADER FT_Module_Requester get_interface; TT_Load_Any_Func load_any; - TT_Load_SFNT_HeaderRec_Func load_sfnt_header; - TT_Load_Directory_Func load_directory; + + /* load the font directory, i.e. the offset table and */ + /* the table directory */ + TT_Load_Table_Func load_font_dir; /* these functions are called by `load_face' but they can also */ /* be called from external modules, if there is a need to do so */ diff --git a/src/sfnt/sfdriver.c b/src/sfnt/sfdriver.c index a43ac01ed..f45195072 100644 --- a/src/sfnt/sfdriver.c +++ b/src/sfnt/sfdriver.c @@ -386,8 +386,7 @@ sfnt_get_interface, tt_face_load_any, - tt_face_load_sfnt_header, - tt_face_load_directory, + tt_face_load_font_dir, tt_face_load_head, tt_face_load_hhea, diff --git a/src/sfnt/sfobjs.c b/src/sfnt/sfobjs.c index da466ae9c..e16cc9440 100644 --- a/src/sfnt/sfobjs.c +++ b/src/sfnt/sfobjs.c @@ -345,6 +345,85 @@ } + /* Fill in face->ttc_header. If the font is not a TTC, it is */ + /* synthesized into a TTC with one offset table. */ + static FT_Error + sfnt_open_font( FT_Stream stream, + TT_Face face ) + { + FT_Memory memory = stream->memory; + FT_Error error; + FT_ULong tag, offset; + + static const FT_Frame_Field ttc_header_fields[] = + { +#undef FT_STRUCTURE +#define FT_STRUCTURE TTC_HeaderRec + + FT_FRAME_START( 8 ), + FT_FRAME_LONG( version ), + FT_FRAME_LONG( count ), + FT_FRAME_END + }; + + + face->ttc_header.tag = 0; + face->ttc_header.version = 0; + face->ttc_header.count = 0; + + offset = FT_STREAM_POS(); + + if ( FT_READ_ULONG( tag ) ) + return error; + + if ( tag != 0x00010000UL && + tag != TTAG_ttcf && + tag != FT_MAKE_TAG( 'O', 'T', 'T', 'O' ) && + tag != TTAG_true && + tag != 0x00020000UL ) + return SFNT_Err_Unknown_File_Format; + + face->ttc_header.tag = TTAG_ttcf; + + if ( tag == TTAG_ttcf ) + { + FT_Int n; + + + FT_TRACE3(( "sfnt_open_font: file is a collection\n" )); + + if ( FT_STREAM_READ_FIELDS( ttc_header_fields, &face->ttc_header ) ) + return error; + + /* now read the offsets of each font in the file */ + if ( FT_NEW_ARRAY( face->ttc_header.offsets, face->ttc_header.count ) ) + return error; + + if ( FT_FRAME_ENTER( face->ttc_header.count * 4L ) ) + return error; + + for ( n = 0; n < face->ttc_header.count; n++ ) + face->ttc_header.offsets[n] = FT_GET_ULONG(); + + FT_FRAME_EXIT(); + } + else + { + FT_TRACE3(( "sfnt_open_font: synthesize TTC\n" )); + + face->ttc_header.version = 1 << 16; + face->ttc_header.count = 1; + + if ( FT_NEW( face->ttc_header.offsets) ) + return error; + + face->ttc_header.offsets[0] = offset; + } + + return error; + } + + FT_LOCAL_DEF( FT_Error ) sfnt_init_face( FT_Stream stream, TT_Face face, @@ -355,7 +434,7 @@ FT_Error error; FT_Library library = face->root.driver->root.library; SFNT_Service sfnt; - SFNT_HeaderRec sfnt_header; + /* for now, parameters are unused */ FT_UNUSED( num_params ); @@ -367,10 +446,7 @@ { sfnt = (SFNT_Service)FT_Get_Module_Interface( library, "sfnt" ); if ( !sfnt ) - { - error = SFNT_Err_Invalid_File_Format; - goto Exit; - } + return SFNT_Err_Invalid_File_Format; face->sfnt = sfnt; face->goto_table = sfnt->goto_table; @@ -378,24 +454,28 @@ FT_FACE_FIND_GLOBAL_SERVICE( face, face->psnames, POSTSCRIPT_CMAPS ); + error = sfnt_open_font( stream, face ); + if ( error ) + return error; + + FT_TRACE2(( "sfnt_init_face: %08p, %ld\n", face, face_index )); + + if ( face_index < 0 ) + face_index = 0; + + if ( face_index >= face->ttc_header.count ) + return SFNT_Err_Bad_Argument; + + if ( FT_STREAM_SEEK( face->ttc_header.offsets[face_index] ) ) + return error; + /* check that we have a valid TrueType file */ - error = sfnt->load_sfnt_header( face, stream, face_index, &sfnt_header ); + error = sfnt->load_font_dir( face, stream ); if ( error ) - goto Exit; - - face->format_tag = sfnt_header.format_tag; - face->num_tables = sfnt_header.num_tables; - - /* Load font directory */ - error = sfnt->load_directory( face, stream, &sfnt_header ); - if ( error ) - goto Exit; + return error; face->root.num_faces = face->ttc_header.count; - if ( face->root.num_faces < 1 ) - face->root.num_faces = 1; - Exit: return error; } diff --git a/src/sfnt/ttload.c b/src/sfnt/ttload.c index 9877b9e1a..adfb0b924 100644 --- a/src/sfnt/ttload.c +++ b/src/sfnt/ttload.c @@ -145,8 +145,8 @@ /* Type 42 fonts, and which are generally invalid. */ /* */ static FT_Error - sfnt_dir_check( SFNT_Header sfnt, - FT_Stream stream ) + check_table_dir( SFNT_Header sfnt, + FT_Stream stream ) { FT_Error error; FT_UInt nn; @@ -156,7 +156,7 @@ const FT_ULong glyx_tag = FT_MAKE_TAG( 'g', 'l', 'y', 'x' ); const FT_ULong locx_tag = FT_MAKE_TAG( 'l', 'o', 'c', 'x' ); - static const FT_Frame_Field sfnt_dir_entry_fields[] = + static const FT_Frame_Field table_dir_entry_fields[] = { #undef FT_STRUCTURE #define FT_STRUCTURE TT_TableRec @@ -182,7 +182,7 @@ TT_TableRec table; - if ( FT_STREAM_READ_FIELDS( sfnt_dir_entry_fields, &table ) ) + if ( FT_STREAM_READ_FIELDS( table_dir_entry_fields, &table ) ) return error; if ( table.Offset + table.Length > stream->size && @@ -194,6 +194,7 @@ { FT_UInt32 magic; + #ifndef TT_CONFIG_OPTION_EMBEDDED_BITMAPS if ( table.Tag == TTAG_head ) #endif @@ -235,101 +236,19 @@ } - /* Fill in face->ttc_header. If the font is not a TTC, it is */ - /* synthesized into a TTC with one offset table. */ - static FT_Error - sfnt_init( FT_Stream stream, - TT_Face face ) - { - FT_Memory memory = stream->memory; - FT_Error error; - FT_ULong tag, offset; - - static const FT_Frame_Field ttc_header_fields[] = - { -#undef FT_STRUCTURE -#define FT_STRUCTURE TTC_HeaderRec - - FT_FRAME_START( 8 ), - FT_FRAME_LONG( version ), - FT_FRAME_LONG( count ), - FT_FRAME_END - }; - - - face->ttc_header.tag = 0; - face->ttc_header.version = 0; - face->ttc_header.count = 0; - - offset = FT_STREAM_POS(); - - if ( FT_READ_ULONG( tag ) ) - return error; - - if ( tag != 0x00010000UL && - tag != TTAG_ttcf && - tag != FT_MAKE_TAG( 'O', 'T', 'T', 'O' ) && - tag != TTAG_true && - tag != 0x00020000UL ) - return SFNT_Err_Unknown_File_Format; - - face->ttc_header.tag = TTAG_ttcf; - - if ( tag == TTAG_ttcf ) - { - FT_Int n; - - - FT_TRACE3(( "sfnt_init: file is a collection\n" )); - - if ( FT_STREAM_READ_FIELDS( ttc_header_fields, &face->ttc_header ) ) - return error; - - /* now read the offsets of each font in the file */ - if ( FT_NEW_ARRAY( face->ttc_header.offsets, face->ttc_header.count ) ) - return error; - - if ( FT_FRAME_ENTER( face->ttc_header.count * 4L ) ) - return error; - - for ( n = 0; n < face->ttc_header.count; n++ ) - face->ttc_header.offsets[n] = FT_GET_ULONG(); - - FT_FRAME_EXIT(); - } - else - { - FT_TRACE3(( "sfnt_init: synthesize TTC\n" )); - - face->ttc_header.version = 1 << 16; - face->ttc_header.count = 1; - - if ( FT_NEW( face->ttc_header.offsets) ) - return error; - - face->ttc_header.offsets[0] = offset; - } - - return error; - } - - /*************************************************************************/ /* */ /* */ - /* tt_face_load_sfnt_header */ + /* tt_face_load_font_dir */ /* */ /* */ - /* Loads the header of a SFNT font file. Supports collections. */ + /* Loads the header of a SFNT font file. */ /* */ /* */ /* face :: A handle to the target face object. */ /* */ /* stream :: The input stream. */ /* */ - /* face_index :: If the font is a collection, the number of the font */ - /* in the collection. Must be zero otherwise. */ - /* */ /* */ /* sfnt :: The SFNT header. */ /* */ @@ -337,22 +256,19 @@ /* FreeType error code. 0 means success. */ /* */ /* */ - /* The stream cursor must be at the font file's origin. */ - /* */ - /* This function recognizes fonts embedded in a `TrueType collection' */ - /* */ - /* The header will be checked whether it is valid by looking at the */ - /* values of `search_range', `entry_selector', and `range_shift'. */ + /* The stream cursor must be at the beginning of the font directory. */ /* */ FT_LOCAL_DEF( FT_Error ) - tt_face_load_sfnt_header( TT_Face face, - FT_Stream stream, - FT_Long face_index, - SFNT_Header sfnt ) + tt_face_load_font_dir( TT_Face face, + FT_Stream stream ) { - FT_Error error; + SFNT_HeaderRec sfnt; + FT_Error error; + FT_Memory memory = stream->memory; + TT_TableRec* entry; + TT_TableRec* limit; - static const FT_Frame_Field sfnt_header_fields[] = + static const FT_Frame_Field offset_table_fields[] = { #undef FT_STRUCTURE #define FT_STRUCTURE SFNT_HeaderRec @@ -366,101 +282,52 @@ }; - FT_TRACE2(( "tt_face_load_sfnt_header: %08p, %ld\n", - face, face_index )); + FT_TRACE2(( "tt_face_load_font_dir: %08p\n", face )); - error = sfnt_init( stream, face ); - if ( error ) - return error; + /* read the offset table */ - if ( face_index < 0 ) - face_index = 0; + sfnt.offset = FT_STREAM_POS(); - if ( face_index >= face->ttc_header.count ) - return SFNT_Err_Bad_Argument; - - sfnt->offset = face->ttc_header.offsets[face_index]; - - if ( FT_STREAM_SEEK( sfnt->offset ) ) - return error; - - /* read offset table */ - if ( FT_READ_ULONG( sfnt->format_tag ) || - FT_STREAM_READ_FIELDS( sfnt_header_fields, sfnt ) ) + if ( FT_READ_ULONG( sfnt.format_tag ) || + FT_STREAM_READ_FIELDS( offset_table_fields, &sfnt ) ) return error; /* many fonts don't have these fields set correctly */ #if 0 - if ( sfnt->search_range != 1 << ( sfnt->entry_selector + 4 ) || - sfnt->search_range + sfnt->range_shift != sfnt->num_tables << 4 ) + if ( sfnt.search_range != 1 << ( sfnt.entry_selector + 4 ) || + sfnt.search_range + sfnt.range_shift != sfnt.num_tables << 4 ) return SFNT_Err_Unknown_File_Format; #endif - return error; - } + /* load the table directory */ - - /*************************************************************************/ - /* */ - /* */ - /* tt_face_load_directory */ - /* */ - /* */ - /* Loads the table directory into a face object. */ - /* */ - /* */ - /* face :: A handle to the target face object. */ - /* */ - /* */ - /* stream :: The input stream. */ - /* */ - /* sfnt :: The SFNT directory header. */ - /* */ - /* */ - /* FreeType error code. 0 means success. */ - /* */ - /* */ - /* The stream cursor must be at the font file's origin. */ - /* */ - FT_LOCAL_DEF( FT_Error ) - tt_face_load_directory( TT_Face face, - FT_Stream stream, - SFNT_Header sfnt ) - { - FT_Error error; - FT_Memory memory = stream->memory; - - TT_TableRec *entry, *limit; - - - FT_TRACE2(( "tt_face_load_directory: %08p\n", face )); - - FT_TRACE2(( "-- Tables count: %12u\n", sfnt->num_tables )); - FT_TRACE2(( "-- Format version: %08lx\n", sfnt->format_tag )); + FT_TRACE2(( "-- Tables count: %12u\n", sfnt.num_tables )); + FT_TRACE2(( "-- Format version: %08lx\n", sfnt.format_tag )); /* check first */ - error = sfnt_dir_check( sfnt, stream ); + error = check_table_dir( &sfnt, stream ); if ( error ) { - FT_TRACE2(( "tt_face_load_directory: directory checking failed!\n" )); + FT_TRACE2(( "tt_face_load_font_dir: invalid table directory!\n" )); return error; } - face->num_tables = sfnt->num_tables; + face->num_tables = sfnt.num_tables; + face->format_tag = sfnt.format_tag; if ( FT_QNEW_ARRAY( face->dir_tables, face->num_tables ) ) - goto Exit; + return error; - if ( FT_STREAM_SEEK( sfnt->offset + 12 ) || + if ( FT_STREAM_SEEK( sfnt.offset + 12 ) || FT_FRAME_ENTER( face->num_tables * 16L ) ) - goto Exit; + return error; entry = face->dir_tables; limit = entry + face->num_tables; for ( ; entry < limit; entry++ ) - { /* loop through the tables and get all entries */ + { entry->Tag = FT_GET_TAG4(); entry->CheckSum = FT_GET_ULONG(); entry->Offset = FT_GET_LONG(); @@ -477,9 +344,8 @@ FT_FRAME_EXIT(); - FT_TRACE2(( "Directory loaded\n\n" )); + FT_TRACE2(( "table directory loaded\n\n" )); - Exit: return error; } diff --git a/src/sfnt/ttload.h b/src/sfnt/ttload.h index 68b50ea27..b665711ee 100644 --- a/src/sfnt/ttload.h +++ b/src/sfnt/ttload.h @@ -41,15 +41,9 @@ FT_BEGIN_HEADER FT_LOCAL( FT_Error ) - tt_face_load_sfnt_header( TT_Face face, - FT_Stream stream, - FT_Long face_index, - SFNT_Header sfnt ); + tt_face_load_font_dir( TT_Face face, + FT_Stream stream ); - FT_LOCAL( FT_Error ) - tt_face_load_directory( TT_Face face, - FT_Stream stream, - SFNT_Header sfnt ); FT_LOCAL( FT_Error ) tt_face_load_any( TT_Face face,