diff -bur freetype2.orig/include/freetype/ftmac.h freetype2/include/freetype/ftmac.h --- freetype2.orig/include/freetype/ftmac.h 2001-12-07 13:56:32.000000000 -0800 +++ freetype2/include/freetype/ftmac.h 2004-01-08 01:04:59.000000000 -0800 @@ -116,6 +116,12 @@ FSSpec* pathSpec, FT_Long* face_index ); + FT_EXPORT_DEF( FT_Error ) + FT_New_Face_From_FSSpec( FT_Library library, + const FSSpec *spec, + FT_Long face_index, + FT_Face *aface ); + /* */ diff -bur freetype2.orig/src/base/ftmac.c freetype2/src/base/ftmac.c --- freetype2.orig/src/base/ftmac.c 2003-06-06 22:13:21.000000000 -0700 +++ freetype2/src/base/ftmac.c 2004-01-08 01:11:27.000000000 -0800 @@ -77,6 +77,10 @@ #include #endif +#if defined(__MWERKS__) && !TARGET_RT_MAC_MACHO +#include +#endif + #include FT_MAC_H @@ -128,7 +132,7 @@ /* Return the file type of the file specified by spec. */ static OSType - get_file_type( FSSpec* spec ) + get_file_type( const FSSpec* spec ) { FInfo finfo; @@ -144,7 +148,7 @@ /* is this a Mac OS X .dfont file */ static Boolean - is_dfont( FSSpec* spec ) + is_dfont( const FSSpec* spec ) { int nameLen = spec->name[0]; @@ -280,6 +284,7 @@ *sfnt_id = base_assoc->fontID; } + /* Not all fonts have style mapping tables... */ if ( fond->ffStylOff ) { unsigned char* p = (unsigned char*)fond_data; @@ -351,7 +356,7 @@ of the same type together. */ static FT_Error read_lwfn( FT_Memory memory, - FSSpec* lwfn_spec, + const FSSpec* lwfn_spec, FT_Byte** pfb_data, FT_ULong* size ) { @@ -554,7 +559,7 @@ /* Create a new FT_Face from a file spec to an LWFN file. */ static FT_Error FT_New_Face_From_LWFN( FT_Library library, - FSSpec* spec, + const FSSpec* spec, FT_Long face_index, FT_Face *aface ) { @@ -590,9 +595,8 @@ FT_Memory memory = library->memory; int is_cff; - sfnt = GetResource( 'sfnt', sfnt_id ); - if ( ResError() ) + if ( ResError() || (NULL==sfnt) ) return FT_Err_Invalid_Handle; sfnt_size = (FT_ULong)GetHandleSize( sfnt ); @@ -624,31 +628,21 @@ /* Create a new FT_Face from a file spec to a suitcase file. */ static FT_Error FT_New_Face_From_Suitcase( FT_Library library, - FSSpec* spec, + const FSSpec* spec, FT_Long face_index, FT_Face *aface ) { FT_Error error = FT_Err_Ok; - short res_ref, res_index; + short res_ref; Handle fond; - res_ref = FSpOpenResFile( spec, fsRdPerm ); if ( ResError() ) return FT_Err_Cannot_Open_Resource; UseResFile( res_ref ); - /* face_index may be -1, in which case we - just need to do a sanity check */ - if ( face_index < 0 ) - res_index = 1; - else - { - res_index = (short)( face_index + 1 ); - face_index = 0; - } - fond = Get1IndResource( 'FOND', res_index ); - if ( ResError() ) + fond = Get1IndResource( 'FOND', 1 ); + if ( ResError() || fond == NULL ) { error = FT_Err_Cannot_Open_Resource; goto Error; @@ -662,55 +656,134 @@ } -#ifdef TARGET_API_MAC_CARBON - /* Create a new FT_Face from a file spec to a suitcase file. */ static FT_Error FT_New_Face_From_dfont( FT_Library library, - FSSpec* spec, + const FSSpec* spec, FT_Long face_index, FT_Face* aface ) { FT_Error error = FT_Err_Ok; - short res_ref, res_index; - Handle fond; + short res_ref; + Handle fond_data = NULL; FSRef hostContainerRef; + short nFONDCount; + short nFONDIndex; + short nNumFontsInFOND; + short nFontAssocIndex; + AsscEntry* assoc; + AsscEntry* base_assoc; + short nTotalFacesReferenced = 0; + short nFONDBaseAssoc; + short bGotFace = 0; + short sfnt_id, have_sfnt, have_lwfn; + Str255 lwfn_file_name; + FSSpec lwfn_spec; - + /* Make and FSRef that points to the font file */ error = FSpMakeFSRef( spec, &hostContainerRef ); if ( error == noErr ) - error = FSOpenResourceFile( &hostContainerRef, - 0, NULL, fsRdPerm, &res_ref ); + { + /* First attempt to open the file's resource fork. */ + res_ref = FSpOpenResFile( spec, fsRdPerm ); + if ( -1 == res_ref ) + { +#ifdef TARGET_API_MAC_CARBON + /* File had no resource fork, so attempt to grab resources from data fork */ + error = FSOpenResourceFile( &hostContainerRef, 0, NULL, fsRdPerm, &res_ref ); +#else + error = ResError(); +#endif + } + } if ( error != noErr ) return FT_Err_Cannot_Open_Resource; UseResFile( res_ref ); - /* face_index may be -1, in which case we - just need to do a sanity check */ - if ( face_index < 0 ) - res_index = 1; + /* Loop through all FONDs and find out how many 'sfnt' resources + * each one refers to. + */ + nFONDCount = Count1Resources( 'FOND' ); + if ( nFONDCount > 0 ) + { + /* Loop through all FONDs and tally up their font associations. We must + * do this for _all_ FONDs even when we are past the FOND that contains the + * face_index we want, because we have to fill an accurate # into + * aface->num_faces for the face we are returning. + */ + for( nFONDIndex = 1; nFONDIndex <= nFONDCount; nFONDIndex++ ) + { + fond_data = Get1IndResource( 'FOND', nFONDIndex ); + if ( fond_data && !ResError() ) + { + HLock( fond_data ); + /* Grab # of Font Association entries in this FOND. Keep in mind + * that the FOND holds # assocation entries - 1. + */ + nNumFontsInFOND = ((FontAssoc *)((*fond_data)+sizeof(FamRec)))->numAssoc + 1; + + /* We have to step through each association entry in the FOND to weed out + * NFNT references. We can only use scalable TrueType 'sfnt' references, + * which have a AsscEntry->fontSize of 0, so only count them. + * We also need to check for a LWFN file here. + */ + assoc = (AsscEntry *)( (*fond_data) + sizeof(FamRec) + sizeof(FontAssoc) ); + nFONDBaseAssoc = nTotalFacesReferenced; + have_lwfn = 0; + parse_fond( *fond_data, &have_sfnt, &sfnt_id, lwfn_file_name, 0 ); + if ( lwfn_file_name[0] ) + { + if ( make_lwfn_spec( fond_data, lwfn_file_name, &lwfn_spec ) == FT_Err_Ok ) + have_lwfn = 1; /* yeah, we got one! */ else + have_lwfn = 0; /* no LWFN file found */ + } + if ( have_lwfn && PREFER_LWFN ) + nTotalFacesReferenced++; + else for( nFontAssocIndex = 0; nFontAssocIndex < nNumFontsInFOND; nFontAssocIndex++ ) + { + /* Grab each association record from the FOND's Association Table + * and count only if its an 'sfnt'. + */ + if ( assoc->fontSize == 0 ) { - res_index = (short)( face_index + 1 ); - face_index = 0; + if ( have_lwfn ) + have_lwfn = 0; /* we already added 1 */ + else + nTotalFacesReferenced++; } - fond = Get1IndResource( 'FOND', res_index ); - if ( ResError() ) + assoc++; + } + + /* If the face_index we wanted to pull was contained in this FOND, get the FT face. + * Remember that nTotalFacesReferenced is 1-up numbering, while face_index is 0-up. + */ + if ( (nTotalFacesReferenced >= face_index + 1) && !bGotFace ) { - error = FT_Err_Cannot_Open_Resource; - goto Error; + /* We also need to localize face_index to this FOND, not to all FONDs. */ + error = FT_New_Face_From_FOND( library, fond_data, (face_index - nFONDBaseAssoc), aface ); + bGotFace = 1; + } + HUnlock( fond_data ); + } + if ( fond_data ) + ReleaseResource( fond_data ); } - error = FT_New_Face_From_FOND( library, fond, face_index, aface ); + /* Fill in the accurate count of the # faces in this Mac font file */ + if ( *aface ) + (*aface)->num_faces = nTotalFacesReferenced - 1; + } - Error: CloseResFile( res_ref ); - return error; - } -#endif + if ( error == noErr && !bGotFace ) + error = FT_Err_Invalid_Argument; + + return( error ); + } /* documentation is in ftmac.h */ @@ -847,7 +920,7 @@ static long - ResourceForkSize(FSSpec* spec) + ResourceForkSize(const FSSpec* spec) { long len; short refNum; @@ -897,29 +970,123 @@ /* Regardless of type, don't try to use the resource fork if it is */ /* empty. Some TTF fonts have type `FFIL', for example, but they */ /* only have data forks. */ - - if ( ResourceForkSize( &spec ) != 0 ) - { file_type = get_file_type( &spec ); - if ( file_type == 'FFIL' || file_type == 'tfil' ) - return FT_New_Face_From_Suitcase( library, &spec, face_index, aface ); + if ( (file_type == 'FFIL') || (file_type == 'tfil') || is_dfont(&spec) ) + return FT_New_Face_From_dfont( library, &spec, face_index, aface ); - if ( file_type == 'LWFN' ) + if ( (file_type=='LWFN') && (ResourceForkSize(&spec)!=0) ) return FT_New_Face_From_LWFN( library, &spec, face_index, aface ); + + /* let it fall through to normal loader (.ttf, .otf, etc.) */ + args.flags = FT_OPEN_PATHNAME; + args.pathname = (char*)pathname; + return FT_Open_Face( library, &args, face_index, aface ); } -#ifdef TARGET_API_MAC_CARBON +#define STREAM_FILE( stream ) ( (FILE*)stream->descriptor.pointer ) - if ( is_dfont( &spec ) ) - return FT_New_Face_From_dfont( library, &spec, face_index, aface ); + FT_CALLBACK_DEF( void ) + ft_FSp_stream_close( FT_Stream stream ) + { + fclose( STREAM_FILE( stream ) ); -#endif + stream->descriptor.pointer = NULL; + stream->size = 0; + stream->base = 0; + } + + FT_CALLBACK_DEF( unsigned long ) + ft_FSp_stream_io( FT_Stream stream, + unsigned long offset, + unsigned char* buffer, + unsigned long count ) + { + FILE* file; + + + file = STREAM_FILE( stream ); + + fseek( file, offset, SEEK_SET ); + + return (unsigned long)fread( buffer, 1, count, file ); + } + + FT_EXPORT_DEF( FT_Error ) + FT_New_Face_From_FSSpec( FT_Library library, + const FSSpec *spec, + FT_Long face_index, + FT_Face *aface ) + { + FT_Open_Args args; + OSType file_type; + FT_Error error; + FT_Stream stream; + FILE* file; + FT_Memory memory; + + /* test for valid `library' and `aface' delayed to FT_Open_Face() */ + if ( !spec ) + return FT_Err_Invalid_Argument; + + /* Regardless of type, don't try to use the resource fork if it is */ + /* empty. Some TTF fonts have type `FFIL', for example, but they */ + /* only have data forks. */ + + file_type = get_file_type( spec ); + if ( (file_type == 'FFIL') || (file_type == 'tfil') || is_dfont(spec) ) + return FT_New_Face_From_dfont( library, spec, face_index, aface ); + + if ( (file_type=='LWFN') && (ResourceForkSize(spec)!=0) ) + return FT_New_Face_From_LWFN( library, spec, face_index, aface ); /* let it fall through to normal loader (.ttf, .otf, etc.) */ - args.flags = FT_OPEN_PATHNAME; - args.pathname = (char*)pathname; - return FT_Open_Face( library, &args, face_index, aface ); +#if defined(__MWERKS__) && !TARGET_RT_MAC_MACHO + /* Codewarrior's C library can open a FILE from a FSSpec */ + #include + memory = library->memory; + if ( FT_NEW( stream ) ) + return error; + stream->memory = memory; + + file = FSp_fopen( spec, "rb" ); + if ( !file ) + { + return FT_Err_Cannot_Open_Resource; } + fseek( file, 0, SEEK_END ); + stream->size = ftell( file ); + fseek( file, 0, SEEK_SET ); + + stream->descriptor.pointer = file; + stream->pathname.pointer = NULL; + stream->pos = 0; + + stream->read = ft_FSp_stream_io; + stream->close = ft_FSp_stream_close; + + args.flags = FT_OPEN_STREAM; + args.stream = stream; + error = FT_Open_Face( library, &args, face_index, aface ); + if ( error == FT_Err_Ok ) + (*aface)->face_flags &= ~FT_FACE_FLAG_EXTERNAL_STREAM; +#else + { + FSRef ref; + UInt8 path[256]; + OSErr err; + err = FSpMakeFSRef(spec, &ref); + if (!err) { + err = FSRefMakePath(&ref, path, sizeof(path)); + if (!err) { + error = FT_New_Face(library, (const char*)path, face_index, aface); + } + } + if (err) + error = FT_Err_Cannot_Open_Resource; + } +#endif + return error; + } /* END */