📄 ftmac.c
字号:
/***************************************************************************//* *//* ftmac.c *//* *//* Mac FOND support. Written by just@letterror.com. *//* Heavily modified by mpsuzuki, George Williams, and Sean McBride. *//* *//* This file is for Mac OS X only; see builds/mac/ftoldmac.c for *//* classic platforms built by MPW. *//* *//* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007 by *//* Just van Rossum, David Turner, Robert Wilhelm, and Werner Lemberg. *//* *//* This file is part of the FreeType project, and may only be used, *//* modified, and distributed under the terms of the FreeType project *//* license, LICENSE.TXT. By continuing to use, modify, or distribute *//* this file you indicate that you have read the license and *//* understand and accept it fully. *//* *//***************************************************************************/ /* Notes Mac suitcase files can (and often do!) contain multiple fonts. To support this I use the face_index argument of FT_(Open|New)_Face() functions, and pretend the suitcase file is a collection. Warning: fbit and NFNT bitmap resources are not supported yet. In old sfnt fonts, bitmap glyph data for each size is stored in each `NFNT' resources instead of the `bdat' table in the sfnt resource. Therefore, face->num_fixed_sizes is set to 0, because bitmap data in `NFNT' resource is unavailable at present. The Mac FOND support works roughly like this: - Check whether the offered stream points to a Mac suitcase file. This is done by checking the file type: it has to be 'FFIL' or 'tfil'. The stream that gets passed to our init_face() routine is a stdio stream, which isn't usable for us, since the FOND resources live in the resource fork. So we just grab the stream->pathname field. - Read the FOND resource into memory, then check whether there is a TrueType font and/or(!) a Type 1 font available. - If there is a Type 1 font available (as a separate `LWFN' file), read its data into memory, massage it slightly so it becomes PFB data, wrap it into a memory stream, load the Type 1 driver and delegate the rest of the work to it by calling FT_Open_Face(). (XXX TODO: after this has been done, the kerning data from the FOND resource should be appended to the face: On the Mac there are usually no AFM files available. However, this is tricky since we need to map Mac char codes to ps glyph names to glyph ID's...) - If there is a TrueType font (an `sfnt' resource), read it into memory, wrap it into a memory stream, load the TrueType driver and delegate the rest of the work to it, by calling FT_Open_Face(). - Some suitcase fonts (notably Onyx) might point the `LWFN' file to itself, even though it doesn't contains `POST' resources. To handle this special case without opening the file an extra time, we just ignore errors from the `LWFN' and fallback to the `sfnt' if both are available. */#include <ft2build.h>#include FT_FREETYPE_H#include FT_INTERNAL_STREAM_H /* This is for Mac OS X. Without redefinition, OS_INLINE */ /* expands to `static inline' which doesn't survive the */ /* -ansi compilation flag of GCC. */#if !HAVE_ANSI_OS_INLINE#undef OS_INLINE#define OS_INLINE static __inline__#endif#include <Carbon/Carbon.h>#ifndef HFS_MAXPATHLEN#define HFS_MAXPATHLEN 1024#endif#define FT_DEPRECATED_ATTRIBUTE#include FT_MAC_H /* undefine blocking-macros in ftmac.h */#undef FT_GetFile_From_Mac_Name( a, b, c )#undef FT_GetFile_From_Mac_ATS_Name( a, b, c )#undef FT_New_Face_From_FSSpec( a, b, c, d ) /* Set PREFER_LWFN to 1 if LWFN (Type 1) is preferred over TrueType in case *both* are available (this is not common, but it *is* possible). */#ifndef PREFER_LWFN#define PREFER_LWFN 1#endif FT_EXPORT_DEF( FT_Error ) FT_GetFile_From_Mac_Name( const char* fontName, FSSpec* pathSpec, FT_Long* face_index ) { return FT_Err_Unimplemented_Feature; } /* Private function. */ /* The FSSpec type has been discouraged for a long time, */ /* but for some reason, there is no FSRef version of */ /* ATSFontGetFileSpecification(), so we made our own. */ /* Apple will provide one eventually. */ static OSStatus FT_ATSFontGetFileReference( ATSFontRef ats_font_id, FSRef* ats_font_ref ) { OSStatus err; FSSpec spec; err = ATSFontGetFileSpecification( ats_font_id, &spec ); if ( noErr == err ) err = FSpMakeFSRef( &spec, ats_font_ref ); return err; } static FT_Error FT_GetFileRef_From_Mac_ATS_Name( const char* fontName, FSRef* ats_font_ref, FT_Long* face_index ) { CFStringRef cf_fontName; ATSFontRef ats_font_id; *face_index = 0; cf_fontName = CFStringCreateWithCString( NULL, fontName, kCFStringEncodingMacRoman ); ats_font_id = ATSFontFindFromName( cf_fontName, kATSOptionFlagsUnRestrictedScope ); CFRelease( cf_fontName ); if ( ats_font_id == 0 || ats_font_id == 0xFFFFFFFFUL ) return FT_Err_Unknown_File_Format; if ( noErr != FT_ATSFontGetFileReference( ats_font_id, ats_font_ref ) ) return FT_Err_Unknown_File_Format; /* face_index calculation by searching preceding fontIDs */ /* with same FSRef */ { ATSFontRef id2 = ats_font_id - 1; FSRef ref2; while ( id2 > 0 ) { if ( noErr != FT_ATSFontGetFileReference( id2, &ref2 ) ) break; if ( noErr != FSCompareFSRefs( ats_font_ref, &ref2 ) ) break; id2 --; } *face_index = ats_font_id - ( id2 + 1 ); } return FT_Err_Ok; } FT_EXPORT_DEF( FT_Error ) FT_GetFilePath_From_Mac_ATS_Name( const char* fontName, UInt8* path, UInt32 maxPathSize, FT_Long* face_index ) { FSRef ref; FT_Error err; err = FT_GetFileRef_From_Mac_ATS_Name( fontName, &ref, face_index ); if ( FT_Err_Ok != err ) return err; if ( noErr != FSRefMakePath( &ref, path, maxPathSize ) ) return FT_Err_Unknown_File_Format; return FT_Err_Ok; } /* This function is deprecated because FSSpec is deprecated in Mac OS X */ FT_EXPORT_DEF( FT_Error ) FT_GetFile_From_Mac_ATS_Name( const char* fontName, FSSpec* pathSpec, FT_Long* face_index ) {#if __LP64__ return FT_Err_Unimplemented_Feature;#else FSRef ref; FT_Error err; err = FT_GetFileRef_From_Mac_ATS_Name( fontName, &ref, face_index ); if ( FT_Err_Ok != err ) return err; if ( noErr != FSGetCatalogInfo( &ref, kFSCatInfoNone, NULL, NULL, pathSpec, NULL ) ) return FT_Err_Unknown_File_Format; return FT_Err_Ok;#endif } static OSErr FT_FSPathMakeRes( const UInt8* pathname, short* res ) { OSErr err; FSRef ref; if ( noErr != FSPathMakeRef( pathname, &ref, FALSE ) ) return FT_Err_Cannot_Open_Resource; /* at present, no support for dfont format */ err = FSOpenResourceFile( &ref, 0, NULL, fsRdPerm, res ); if ( noErr == err ) return err; /* fallback to original resource-fork font */ *res = FSOpenResFile( &ref, fsRdPerm ); err = ResError(); return err; } /* Return the file type for given pathname */ static OSType get_file_type_from_path( const UInt8* pathname ) { FSRef ref; FSCatalogInfo info; if ( noErr != FSPathMakeRef( pathname, &ref, FALSE ) ) return ( OSType ) 0; if ( noErr != FSGetCatalogInfo( &ref, kFSCatInfoFinderInfo, &info, NULL, NULL, NULL ) ) return ( OSType ) 0; return ((FInfo *)(info.finderInfo))->fdType; } /* Given a PostScript font name, create the Macintosh LWFN file name. */ static void create_lwfn_name( char* ps_name, Str255 lwfn_file_name ) { int max = 5, count = 0; FT_Byte* p = lwfn_file_name; FT_Byte* q = (FT_Byte*)ps_name; lwfn_file_name[0] = 0; while ( *q ) { if ( ft_isupper( *q ) ) { if ( count ) max = 3; count = 0; } if ( count < max && ( ft_isalnum( *q ) || *q == '_' ) ) { *++p = *q; lwfn_file_name[0]++; count++; } q++; } } static short count_faces_sfnt( char* fond_data ) { /* The count is 1 greater than the value in the FOND. */ /* Isn't that cute? :-) */ return EndianS16_BtoN( *( (short*)( fond_data + sizeof ( FamRec ) ) ) ) + 1; } static short count_faces_scalable( char* fond_data ) { AsscEntry* assoc; FamRec* fond; short i, face, face_all; fond = (FamRec*)fond_data; face_all = EndianS16_BtoN( *( (short *)( fond_data + sizeof ( FamRec ) ) ) ) + 1; assoc = (AsscEntry*)( fond_data + sizeof ( FamRec ) + 2 ); face = 0; for ( i = 0; i < face_all; i++ ) { if ( 0 == EndianS16_BtoN( assoc[i].fontSize ) ) face++; } return face; } /* Look inside the FOND data, answer whether there should be an SFNT resource, and answer the name of a possible LWFN Type 1 file. Thanks to Paul Miller (paulm@profoundeffects.com) for the fix to load a face OTHER than the first one in the FOND! */ static void parse_fond( char* fond_data, short* have_sfnt, short* sfnt_id, Str255 lwfn_file_name, short face_index ) { AsscEntry* assoc; AsscEntry* base_assoc; FamRec* fond; *sfnt_id = 0; *have_sfnt = 0; lwfn_file_name[0] = 0; fond = (FamRec*)fond_data; assoc = (AsscEntry*)( fond_data + sizeof ( FamRec ) + 2 );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -