1 /***************************************************************************/
5 /* Mac FOND support. Written by just@letterror.com. */
6 /* Heavily modified by mpsuzuki, George Williams, and Sean McBride. */
8 /* This file is for Mac OS X only; see builds/mac/ftoldmac.c for */
9 /* classic platforms built by MPW. */
11 /* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, */
13 /* Just van Rossum, David Turner, Robert Wilhelm, and Werner Lemberg. */
15 /* This file is part of the FreeType project, and may only be used, */
16 /* modified, and distributed under the terms of the FreeType project */
17 /* license, LICENSE.TXT. By continuing to use, modify, or distribute */
18 /* this file you indicate that you have read the license and */
19 /* understand and accept it fully. */
21 /***************************************************************************/
27 Mac suitcase files can (and often do!) contain multiple fonts. To
28 support this I use the face_index argument of FT_(Open|New)_Face()
29 functions, and pretend the suitcase file is a collection.
31 Warning: fbit and NFNT bitmap resources are not supported yet. In old
32 sfnt fonts, bitmap glyph data for each size is stored in each `NFNT'
33 resources instead of the `bdat' table in the sfnt resource. Therefore,
34 face->num_fixed_sizes is set to 0, because bitmap data in `NFNT'
35 resource is unavailable at present.
37 The Mac FOND support works roughly like this:
39 - Check whether the offered stream points to a Mac suitcase file. This
40 is done by checking the file type: it has to be 'FFIL' or 'tfil'. The
41 stream that gets passed to our init_face() routine is a stdio stream,
42 which isn't usable for us, since the FOND resources live in the
43 resource fork. So we just grab the stream->pathname field.
45 - Read the FOND resource into memory, then check whether there is a
46 TrueType font and/or(!) a Type 1 font available.
48 - If there is a Type 1 font available (as a separate `LWFN' file), read
49 its data into memory, massage it slightly so it becomes PFB data, wrap
50 it into a memory stream, load the Type 1 driver and delegate the rest
51 of the work to it by calling FT_Open_Face(). (XXX TODO: after this
52 has been done, the kerning data from the FOND resource should be
53 appended to the face: On the Mac there are usually no AFM files
54 available. However, this is tricky since we need to map Mac char
55 codes to ps glyph names to glyph ID's...)
57 - If there is a TrueType font (an `sfnt' resource), read it into memory,
58 wrap it into a memory stream, load the TrueType driver and delegate
59 the rest of the work to it, by calling FT_Open_Face().
61 - Some suitcase fonts (notably Onyx) might point the `LWFN' file to
62 itself, even though it doesn't contains `POST' resources. To handle
63 this special case without opening the file an extra time, we just
64 ignore errors from the `LWFN' and fallback to the `sfnt' if both are
70 #include FT_FREETYPE_H
71 #include FT_TRUETYPE_TAGS_H
72 #include FT_INTERNAL_STREAM_H
75 /* This is for Mac OS X. Without redefinition, OS_INLINE */
76 /* expands to `static inline' which doesn't survive the */
77 /* -ansi compilation flag of GCC. */
78 #if !HAVE_ANSI_OS_INLINE
80 #define OS_INLINE static __inline__
83 /* `configure' checks the availability of `ResourceIndex' strictly */
84 /* and sets HAVE_TYPE_RESOURCE_INDEX 1 or 0 always. If it is */
85 /* not set (e.g., a build without `configure'), the availability */
86 /* is guessed from the SDK version. */
87 #ifndef HAVE_TYPE_RESOURCE_INDEX
88 #if !defined( MAC_OS_X_VERSION_10_5 ) || \
89 ( MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5 )
90 #define HAVE_TYPE_RESOURCE_INDEX 0
92 #define HAVE_TYPE_RESOURCE_INDEX 1
94 #endif /* !HAVE_TYPE_RESOURCE_INDEX */
96 #if ( HAVE_TYPE_RESOURCE_INDEX == 0 )
97 typedef short ResourceIndex;
100 #include <CoreServices/CoreServices.h>
101 #include <ApplicationServices/ApplicationServices.h>
102 #include <sys/syslimits.h> /* PATH_MAX */
104 /* Don't want warnings about our own use of deprecated functions. */
105 #define FT_DEPRECATED_ATTRIBUTE
109 #ifndef kATSOptionFlagsUnRestrictedScope /* since Mac OS X 10.1 */
110 #define kATSOptionFlagsUnRestrictedScope kATSOptionFlagsDefault
114 /* Set PREFER_LWFN to 1 if LWFN (Type 1) is preferred over
115 TrueType in case *both* are available (this is not common,
116 but it *is* possible). */
118 #define PREFER_LWFN 1
124 /* This function is deprecated because FSSpec is deprecated in Mac OS X */
125 FT_EXPORT_DEF( FT_Error )
126 FT_GetFile_From_Mac_Name( const char* fontName,
128 FT_Long* face_index )
130 FT_UNUSED( fontName );
131 FT_UNUSED( pathSpec );
132 FT_UNUSED( face_index );
134 return FT_Err_Unimplemented_Feature;
138 /* Private function. */
139 /* The FSSpec type has been discouraged for a long time, */
140 /* unfortunately an FSRef replacement API for */
141 /* ATSFontGetFileSpecification() is only available in */
142 /* Mac OS X 10.5 and later. */
144 FT_ATSFontGetFileReference( ATSFontRef ats_font_id,
145 FSRef* ats_font_ref )
147 #if defined( MAC_OS_X_VERSION_10_5 ) && \
148 ( MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 )
152 err = ATSFontGetFileReference( ats_font_id, ats_font_ref );
155 #elif __LP64__ /* No 64bit Carbon API on legacy platforms */
156 FT_UNUSED( ats_font_id );
157 FT_UNUSED( ats_font_ref );
161 #else /* 32bit Carbon API on legacy platforms */
166 err = ATSFontGetFileSpecification( ats_font_id, &spec );
168 err = FSpMakeFSRef( &spec, ats_font_ref );
176 FT_GetFileRef_From_Mac_ATS_Name( const char* fontName,
178 FT_Long* face_index )
180 CFStringRef cf_fontName;
181 ATSFontRef ats_font_id;
186 cf_fontName = CFStringCreateWithCString( NULL, fontName,
187 kCFStringEncodingMacRoman );
188 ats_font_id = ATSFontFindFromName( cf_fontName,
189 kATSOptionFlagsUnRestrictedScope );
190 CFRelease( cf_fontName );
192 if ( ats_font_id == 0 || ats_font_id == 0xFFFFFFFFUL )
193 return FT_Err_Unknown_File_Format;
195 if ( noErr != FT_ATSFontGetFileReference( ats_font_id, ats_font_ref ) )
196 return FT_Err_Unknown_File_Format;
198 /* face_index calculation by searching preceding fontIDs */
199 /* with same FSRef */
201 ATSFontRef id2 = ats_font_id - 1;
207 if ( noErr != FT_ATSFontGetFileReference( id2, &ref2 ) )
209 if ( noErr != FSCompareFSRefs( ats_font_ref, &ref2 ) )
214 *face_index = ats_font_id - ( id2 + 1 );
221 FT_EXPORT_DEF( FT_Error )
222 FT_GetFilePath_From_Mac_ATS_Name( const char* fontName,
225 FT_Long* face_index )
231 err = FT_GetFileRef_From_Mac_ATS_Name( fontName, &ref, face_index );
232 if ( FT_Err_Ok != err )
235 if ( noErr != FSRefMakePath( &ref, path, maxPathSize ) )
236 return FT_Err_Unknown_File_Format;
242 /* This function is deprecated because FSSpec is deprecated in Mac OS X */
243 FT_EXPORT_DEF( FT_Error )
244 FT_GetFile_From_Mac_ATS_Name( const char* fontName,
246 FT_Long* face_index )
248 #if ( __LP64__ ) || ( defined( MAC_OS_X_VERSION_10_5 ) && \
249 ( MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 ) )
250 FT_UNUSED( fontName );
251 FT_UNUSED( pathSpec );
252 FT_UNUSED( face_index );
254 return FT_Err_Unimplemented_Feature;
260 err = FT_GetFileRef_From_Mac_ATS_Name( fontName, &ref, face_index );
261 if ( FT_Err_Ok != err )
264 if ( noErr != FSGetCatalogInfo( &ref, kFSCatInfoNone, NULL, NULL,
266 return FT_Err_Unknown_File_Format;
274 FT_FSPathMakeRes( const UInt8* pathname,
281 if ( noErr != FSPathMakeRef( pathname, &ref, FALSE ) )
282 return FT_Err_Cannot_Open_Resource;
284 /* at present, no support for dfont format */
285 err = FSOpenResourceFile( &ref, 0, NULL, fsRdPerm, res );
289 /* fallback to original resource-fork font */
290 *res = FSOpenResFile( &ref, fsRdPerm );
297 /* Return the file type for given pathname */
299 get_file_type_from_path( const UInt8* pathname )
305 if ( noErr != FSPathMakeRef( pathname, &ref, FALSE ) )
308 if ( noErr != FSGetCatalogInfo( &ref, kFSCatInfoFinderInfo, &info,
312 return ((FInfo *)(info.finderInfo))->fdType;
316 /* Given a PostScript font name, create the Macintosh LWFN file name. */
318 create_lwfn_name( char* ps_name,
319 Str255 lwfn_file_name )
321 int max = 5, count = 0;
322 FT_Byte* p = lwfn_file_name;
323 FT_Byte* q = (FT_Byte*)ps_name;
326 lwfn_file_name[0] = 0;
330 if ( ft_isupper( *q ) )
336 if ( count < max && ( ft_isalnum( *q ) || *q == '_' ) )
348 count_faces_sfnt( char* fond_data )
350 /* The count is 1 greater than the value in the FOND. */
351 /* Isn't that cute? :-) */
353 return EndianS16_BtoN( *( (short*)( fond_data +
354 sizeof ( FamRec ) ) ) ) + 1;
359 count_faces_scalable( char* fond_data )
363 short i, face, face_all;
366 fond = (FamRec*)fond_data;
367 face_all = EndianS16_BtoN( *( (short *)( fond_data +
368 sizeof ( FamRec ) ) ) ) + 1;
369 assoc = (AsscEntry*)( fond_data + sizeof ( FamRec ) + 2 );
372 for ( i = 0; i < face_all; i++ )
374 if ( 0 == EndianS16_BtoN( assoc[i].fontSize ) )
381 /* Look inside the FOND data, answer whether there should be an SFNT
382 resource, and answer the name of a possible LWFN Type 1 file.
384 Thanks to Paul Miller (paulm@profoundeffects.com) for the fix
385 to load a face OTHER than the first one in the FOND!
390 parse_fond( char* fond_data,
393 Str255 lwfn_file_name,
397 AsscEntry* base_assoc;
403 lwfn_file_name[0] = 0;
405 fond = (FamRec*)fond_data;
406 assoc = (AsscEntry*)( fond_data + sizeof ( FamRec ) + 2 );
409 /* the maximum faces in a FOND is 48, size of StyleTable.indexes[] */
410 if ( 47 < face_index )
413 /* Let's do a little range checking before we get too excited here */
414 if ( face_index < count_faces_sfnt( fond_data ) )
416 assoc += face_index; /* add on the face_index! */
418 /* if the face at this index is not scalable,
419 fall back to the first one (old behavior) */
420 if ( EndianS16_BtoN( assoc->fontSize ) == 0 )
423 *sfnt_id = EndianS16_BtoN( assoc->fontID );
425 else if ( base_assoc->fontSize == 0 )
428 *sfnt_id = EndianS16_BtoN( base_assoc->fontID );
432 if ( EndianS32_BtoN( fond->ffStylOff ) )
434 unsigned char* p = (unsigned char*)fond_data;
436 unsigned short string_count;
438 unsigned char* names[64];
442 p += EndianS32_BtoN( fond->ffStylOff );
443 style = (StyleTable*)p;
444 p += sizeof ( StyleTable );
445 string_count = EndianS16_BtoN( *(short*)(p) );
446 p += sizeof ( short );
448 for ( i = 0; i < string_count && i < 64; i++ )
456 size_t ps_name_len = (size_t)names[0][0];
459 if ( ps_name_len != 0 )
461 ft_memcpy(ps_name, names[0] + 1, ps_name_len);
462 ps_name[ps_name_len] = 0;
464 if ( style->indexes[face_index] > 1 &&
465 style->indexes[face_index] <= FT_MIN( string_count, 64 ) )
467 unsigned char* suffixes = names[style->indexes[face_index] - 1];
470 for ( i = 1; i <= suffixes[0]; i++ )
473 size_t j = suffixes[i] - 1;
476 if ( j < string_count && ( s = names[j] ) != NULL )
478 size_t s_len = (size_t)s[0];
481 if ( s_len != 0 && ps_name_len + s_len < sizeof ( ps_name ) )
483 ft_memcpy( ps_name + ps_name_len, s + 1, s_len );
484 ps_name_len += s_len;
485 ps_name[ps_name_len] = 0;
492 create_lwfn_name( ps_name, lwfn_file_name );
498 lookup_lwfn_by_fond( const UInt8* path_fond,
499 ConstStr255Param base_lwfn,
507 /* Pathname for FSRef can be in various formats: HFS, HFS+, and POSIX. */
508 /* We should not extract parent directory by string manipulation. */
510 if ( noErr != FSPathMakeRef( path_fond, &ref, FALSE ) )
511 return FT_Err_Invalid_Argument;
513 if ( noErr != FSGetCatalogInfo( &ref, kFSCatInfoNone,
514 NULL, NULL, NULL, &par_ref ) )
515 return FT_Err_Invalid_Argument;
517 if ( noErr != FSRefMakePath( &par_ref, path_lwfn, path_size ) )
518 return FT_Err_Invalid_Argument;
520 if ( ft_strlen( (char *)path_lwfn ) + 1 + base_lwfn[0] > path_size )
521 return FT_Err_Invalid_Argument;
523 /* now we have absolute dirname in path_lwfn */
524 ft_strcat( (char *)path_lwfn, "/" );
525 dirname_len = ft_strlen( (char *)path_lwfn );
526 ft_strcat( (char *)path_lwfn, (char *)base_lwfn + 1 );
527 path_lwfn[dirname_len + base_lwfn[0]] = '\0';
529 if ( noErr != FSPathMakeRef( path_lwfn, &ref, FALSE ) )
530 return FT_Err_Cannot_Open_Resource;
532 if ( noErr != FSGetCatalogInfo( &ref, kFSCatInfoNone,
533 NULL, NULL, NULL, NULL ) )
534 return FT_Err_Cannot_Open_Resource;
541 count_faces( Handle fond,
542 const UInt8* pathname )
545 short have_sfnt, have_lwfn;
546 Str255 lwfn_file_name;
547 UInt8 buff[PATH_MAX];
552 have_sfnt = have_lwfn = 0;
554 parse_fond( *fond, &have_sfnt, &sfnt_id, lwfn_file_name, 0 );
556 if ( lwfn_file_name[0] )
558 err = lookup_lwfn_by_fond( pathname, lwfn_file_name,
559 buff, sizeof ( buff ) );
560 if ( FT_Err_Ok == err )
564 if ( have_lwfn && ( !have_sfnt || PREFER_LWFN ) )
567 num_faces = count_faces_scalable( *fond );
573 /* Read Type 1 data from the POST resources inside the LWFN file,
574 return a PFB buffer. This is somewhat convoluted because the FT2
575 PFB parser wants the ASCII header as one chunk, and the LWFN
576 chunks are often not organized that way, so we glue chunks
577 of the same type together. */
579 read_lwfn( FT_Memory memory,
584 FT_Error error = FT_Err_Ok;
586 unsigned char *buffer, *p, *size_p = NULL;
587 FT_ULong total_size = 0;
588 FT_ULong old_total_size = 0;
589 FT_ULong post_size, pfb_chunk_size;
591 char code, last_code;
596 /* First pass: load all POST resources, and determine the size of */
597 /* the output buffer. */
603 post_data = Get1Resource( TTAG_POST, res_id++ );
604 if ( post_data == NULL )
605 break; /* we are done */
607 code = (*post_data)[0];
609 if ( code != last_code )
612 total_size += 2; /* just the end code */
614 total_size += 6; /* code + 4 bytes chunk length */
617 total_size += GetHandleSize( post_data ) - 2;
620 /* detect integer overflows */
621 if ( total_size < old_total_size )
623 error = FT_Err_Array_Too_Large;
627 old_total_size = total_size;
630 if ( FT_ALLOC( buffer, (FT_Long)total_size ) )
633 /* Second pass: append all POST data to the buffer, add PFB fields. */
634 /* Glue all consecutive chunks of the same type together. */
642 post_data = Get1Resource( TTAG_POST, res_id++ );
643 if ( post_data == NULL )
644 break; /* we are done */
646 post_size = (FT_ULong)GetHandleSize( post_data ) - 2;
647 code = (*post_data)[0];
649 if ( code != last_code )
651 if ( last_code != -1 )
653 /* we are done adding a chunk, fill in the size field */
654 if ( size_p != NULL )
656 *size_p++ = (FT_Byte)( pfb_chunk_size & 0xFF );
657 *size_p++ = (FT_Byte)( ( pfb_chunk_size >> 8 ) & 0xFF );
658 *size_p++ = (FT_Byte)( ( pfb_chunk_size >> 16 ) & 0xFF );
659 *size_p++ = (FT_Byte)( ( pfb_chunk_size >> 24 ) & 0xFF );
666 *p++ = 0x03; /* the end */
667 else if ( code == 2 )
668 *p++ = 0x02; /* binary segment */
670 *p++ = 0x01; /* ASCII segment */
674 size_p = p; /* save for later */
675 p += 4; /* make space for size field */
679 ft_memcpy( p, *post_data + 2, post_size );
680 pfb_chunk_size += post_size;
694 /* Create a new FT_Face from a file path to an LWFN file. */
696 FT_New_Face_From_LWFN( FT_Library library,
697 const UInt8* pathname,
707 if ( noErr != FT_FSPathMakeRes( pathname, &res ) )
708 return FT_Err_Cannot_Open_Resource;
712 error = read_lwfn( library->memory, res, &pfb_data, &pfb_size );
713 CloseResFile( res ); /* PFB is already loaded, useless anymore */
717 return open_face_from_buffer( library,
726 /* Create a new FT_Face from an SFNT resource, specified by res ID. */
728 FT_New_Face_From_SFNT( FT_Library library,
736 FT_Error error = FT_Err_Ok;
737 FT_Memory memory = library->memory;
738 int is_cff, is_sfnt_ps;
741 sfnt = GetResource( TTAG_sfnt, sfnt_id );
743 return FT_Err_Invalid_Handle;
745 sfnt_size = (FT_ULong)GetHandleSize( sfnt );
746 if ( FT_ALLOC( sfnt_data, (FT_Long)sfnt_size ) )
748 ReleaseResource( sfnt );
752 ft_memcpy( sfnt_data, *sfnt, sfnt_size );
753 ReleaseResource( sfnt );
755 is_cff = sfnt_size > 4 && !ft_memcmp( sfnt_data, "OTTO", 4 );
756 is_sfnt_ps = sfnt_size > 4 && !ft_memcmp( sfnt_data, "typ1", 4 );
763 if ( FT_NEW( stream ) )
766 FT_Stream_OpenMemory( stream, sfnt_data, sfnt_size );
767 if ( !open_face_PS_from_sfnt_stream( library,
773 FT_Stream_Close( stream );
775 FT_FREE( sfnt_data );
782 error = open_face_from_buffer( library,
786 is_cff ? "cff" : "truetype",
793 /* Create a new FT_Face from a file path to a suitcase file. */
795 FT_New_Face_From_Suitcase( FT_Library library,
796 const UInt8* pathname,
800 FT_Error error = FT_Err_Cannot_Open_Resource;
801 ResFileRefNum res_ref;
802 ResourceIndex res_index;
804 short num_faces_in_res, num_faces_in_fond;
807 if ( noErr != FT_FSPathMakeRes( pathname, &res_ref ) )
808 return FT_Err_Cannot_Open_Resource;
810 UseResFile( res_ref );
812 return FT_Err_Cannot_Open_Resource;
814 num_faces_in_res = 0;
815 for ( res_index = 1; ; ++res_index )
817 fond = Get1IndResource( TTAG_FOND, res_index );
821 num_faces_in_fond = count_faces( fond, pathname );
822 num_faces_in_res += num_faces_in_fond;
824 if ( 0 <= face_index && face_index < num_faces_in_fond && error )
825 error = FT_New_Face_From_FOND( library, fond, face_index, aface );
827 face_index -= num_faces_in_fond;
830 CloseResFile( res_ref );
831 if ( FT_Err_Ok == error && NULL != aface && NULL != *aface )
832 (*aface)->num_faces = num_faces_in_res;
837 /* documentation is in ftmac.h */
839 FT_EXPORT_DEF( FT_Error )
840 FT_New_Face_From_FOND( FT_Library library,
845 short have_sfnt, have_lwfn = 0;
846 ResID sfnt_id, fond_id;
849 Str255 lwfn_file_name;
850 UInt8 path_lwfn[PATH_MAX];
852 FT_Error error = FT_Err_Ok;
855 GetResInfo( fond, &fond_id, &fond_type, fond_name );
856 if ( ResError() != noErr || fond_type != TTAG_FOND )
857 return FT_Err_Invalid_File_Format;
859 parse_fond( *fond, &have_sfnt, &sfnt_id, lwfn_file_name, face_index );
861 if ( lwfn_file_name[0] )
866 res = HomeResFile( fond );
867 if ( noErr != ResError() )
868 goto found_no_lwfn_file;
871 UInt8 path_fond[PATH_MAX];
875 err = FSGetForkCBInfo( res, kFSInvalidVolumeRefNum,
876 NULL, NULL, NULL, &ref, NULL );
878 goto found_no_lwfn_file;
880 err = FSRefMakePath( &ref, path_fond, sizeof ( path_fond ) );
882 goto found_no_lwfn_file;
884 error = lookup_lwfn_by_fond( path_fond, lwfn_file_name,
885 path_lwfn, sizeof ( path_lwfn ) );
886 if ( FT_Err_Ok == error )
891 if ( have_lwfn && ( !have_sfnt || PREFER_LWFN ) )
892 error = FT_New_Face_From_LWFN( library,
897 error = FT_Err_Unknown_File_Format;
900 if ( have_sfnt && FT_Err_Ok != error )
901 error = FT_New_Face_From_SFNT( library,
910 /* Common function to load a new FT_Face from a resource file. */
912 FT_New_Face_From_Resource( FT_Library library,
913 const UInt8* pathname,
921 /* LWFN is a (very) specific file format, check for it explicitly */
922 file_type = get_file_type_from_path( pathname );
923 if ( file_type == TTAG_LWFN )
924 return FT_New_Face_From_LWFN( library, pathname, face_index, aface );
926 /* Otherwise the file type doesn't matter (there are more than */
927 /* `FFIL' and `tfil'). Just try opening it as a font suitcase; */
928 /* if it works, fine. */
930 error = FT_New_Face_From_Suitcase( library, pathname, face_index, aface );
934 /* let it fall through to normal loader (.ttf, .otf, etc.); */
935 /* we signal this by returning no error and no FT_Face */
941 /*************************************************************************/
947 /* This is the Mac-specific implementation of FT_New_Face. In */
948 /* addition to the standard FT_New_Face() functionality, it also */
949 /* accepts pathnames to Mac suitcase files. For further */
950 /* documentation see the original FT_New_Face() in freetype.h. */
952 FT_EXPORT_DEF( FT_Error )
953 FT_New_Face( FT_Library library,
954 const char* pathname,
962 /* test for valid `library' and `aface' delayed to FT_Open_Face() */
964 return FT_Err_Invalid_Argument;
969 /* try resourcefork based font: LWFN, FFIL */
970 error = FT_New_Face_From_Resource( library, (UInt8 *)pathname,
972 if ( error != 0 || *aface != NULL )
975 /* let it fall through to normal loader (.ttf, .otf, etc.) */
976 args.flags = FT_OPEN_PATHNAME;
977 args.pathname = (char*)pathname;
978 return FT_Open_Face( library, &args, face_index, aface );
982 /*************************************************************************/
985 /* FT_New_Face_From_FSRef */
988 /* FT_New_Face_From_FSRef is identical to FT_New_Face except it */
989 /* accepts an FSRef instead of a path. */
991 /* This function is deprecated because Carbon data types (FSRef) */
992 /* are not cross-platform, and thus not suitable for the freetype API. */
993 FT_EXPORT_DEF( FT_Error )
994 FT_New_Face_From_FSRef( FT_Library library,
1002 UInt8 pathname[PATH_MAX];
1006 return FT_Err_Invalid_Argument;
1008 err = FSRefMakePath( ref, pathname, sizeof ( pathname ) );
1010 error = FT_Err_Cannot_Open_Resource;
1012 error = FT_New_Face_From_Resource( library, pathname, face_index, aface );
1013 if ( error != 0 || *aface != NULL )
1016 /* fallback to datafork font */
1017 args.flags = FT_OPEN_PATHNAME;
1018 args.pathname = (char*)pathname;
1019 return FT_Open_Face( library, &args, face_index, aface );
1023 /*************************************************************************/
1026 /* FT_New_Face_From_FSSpec */
1029 /* FT_New_Face_From_FSSpec is identical to FT_New_Face except it */
1030 /* accepts an FSSpec instead of a path. */
1032 /* This function is deprecated because FSSpec is deprecated in Mac OS X */
1033 FT_EXPORT_DEF( FT_Error )
1034 FT_New_Face_From_FSSpec( FT_Library library,
1039 #if ( __LP64__ ) || ( defined( MAC_OS_X_VERSION_10_5 ) && \
1040 ( MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 ) )
1041 FT_UNUSED( library );
1043 FT_UNUSED( face_index );
1046 return FT_Err_Unimplemented_Feature;
1051 if ( !spec || FSpMakeFSRef( spec, &ref ) != noErr )
1052 return FT_Err_Invalid_Argument;
1054 return FT_New_Face_From_FSRef( library, &ref, face_index, aface );
1058 #endif /* FT_MACINTOSH */