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-2009, 2013, 2014 by */
12 /* Just van Rossum, David Turner, Robert Wilhelm, and Werner Lemberg. */
14 /* This file is part of the FreeType project, and may only be used, */
15 /* modified, and distributed under the terms of the FreeType project */
16 /* license, LICENSE.TXT. By continuing to use, modify, or distribute */
17 /* this file you indicate that you have read the license and */
18 /* understand and accept it fully. */
20 /***************************************************************************/
26 Mac suitcase files can (and often do!) contain multiple fonts. To
27 support this I use the face_index argument of FT_(Open|New)_Face()
28 functions, and pretend the suitcase file is a collection.
30 Warning: fbit and NFNT bitmap resources are not supported yet. In old
31 sfnt fonts, bitmap glyph data for each size is stored in each `NFNT'
32 resources instead of the `bdat' table in the sfnt resource. Therefore,
33 face->num_fixed_sizes is set to 0, because bitmap data in `NFNT'
34 resource is unavailable at present.
36 The Mac FOND support works roughly like this:
38 - Check whether the offered stream points to a Mac suitcase file. This
39 is done by checking the file type: it has to be 'FFIL' or 'tfil'. The
40 stream that gets passed to our init_face() routine is a stdio stream,
41 which isn't usable for us, since the FOND resources live in the
42 resource fork. So we just grab the stream->pathname field.
44 - Read the FOND resource into memory, then check whether there is a
45 TrueType font and/or(!) a Type 1 font available.
47 - If there is a Type 1 font available (as a separate `LWFN' file), read
48 its data into memory, massage it slightly so it becomes PFB data, wrap
49 it into a memory stream, load the Type 1 driver and delegate the rest
50 of the work to it by calling FT_Open_Face(). (XXX TODO: after this
51 has been done, the kerning data from the FOND resource should be
52 appended to the face: On the Mac there are usually no AFM files
53 available. However, this is tricky since we need to map Mac char
54 codes to ps glyph names to glyph ID's...)
56 - If there is a TrueType font (an `sfnt' resource), read it into memory,
57 wrap it into a memory stream, load the TrueType driver and delegate
58 the rest of the work to it, by calling FT_Open_Face().
60 - Some suitcase fonts (notably Onyx) might point the `LWFN' file to
61 itself, even though it doesn't contains `POST' resources. To handle
62 this special case without opening the file an extra time, we just
63 ignore errors from the `LWFN' and fallback to the `sfnt' if both are
69 #include FT_FREETYPE_H
70 #include FT_TRUETYPE_TAGS_H
71 #include FT_INTERNAL_STREAM_H
74 /* This is for Mac OS X. Without redefinition, OS_INLINE */
75 /* expands to `static inline' which doesn't survive the */
76 /* -ansi compilation flag of GCC. */
77 #if !HAVE_ANSI_OS_INLINE
79 #define OS_INLINE static __inline__
82 /* `configure' checks the availability of `ResourceIndex' strictly */
83 /* and sets HAVE_TYPE_RESOURCE_INDEX 1 or 0 always. If it is */
84 /* not set (e.g., a build without `configure'), the availability */
85 /* is guessed from the SDK version. */
86 #ifndef HAVE_TYPE_RESOURCE_INDEX
87 #if !defined( MAC_OS_X_VERSION_10_5 ) || \
88 ( MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5 )
89 #define HAVE_TYPE_RESOURCE_INDEX 0
91 #define HAVE_TYPE_RESOURCE_INDEX 1
93 #endif /* !HAVE_TYPE_RESOURCE_INDEX */
95 #if ( HAVE_TYPE_RESOURCE_INDEX == 0 )
96 typedef short ResourceIndex;
99 #include <CoreServices/CoreServices.h>
100 #include <ApplicationServices/ApplicationServices.h>
101 #include <sys/syslimits.h> /* PATH_MAX */
103 /* Don't want warnings about our own use of deprecated functions. */
104 #define FT_DEPRECATED_ATTRIBUTE
108 #ifndef kATSOptionFlagsUnRestrictedScope /* since Mac OS X 10.1 */
109 #define kATSOptionFlagsUnRestrictedScope kATSOptionFlagsDefault
113 /* Set PREFER_LWFN to 1 if LWFN (Type 1) is preferred over
114 TrueType in case *both* are available (this is not common,
115 but it *is* possible). */
117 #define PREFER_LWFN 1
123 /* This function is deprecated because FSSpec is deprecated in Mac OS X */
124 FT_EXPORT_DEF( FT_Error )
125 FT_GetFile_From_Mac_Name( const char* fontName,
127 FT_Long* face_index )
129 FT_UNUSED( fontName );
130 FT_UNUSED( pathSpec );
131 FT_UNUSED( face_index );
133 return FT_THROW( Unimplemented_Feature );
137 /* Private function. */
138 /* The FSSpec type has been discouraged for a long time, */
139 /* unfortunately an FSRef replacement API for */
140 /* ATSFontGetFileSpecification() is only available in */
141 /* Mac OS X 10.5 and later. */
143 FT_ATSFontGetFileReference( ATSFontRef ats_font_id,
144 FSRef* ats_font_ref )
146 #if defined( MAC_OS_X_VERSION_10_5 ) && \
147 ( MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 )
151 err = ATSFontGetFileReference( ats_font_id, ats_font_ref );
154 #elif __LP64__ /* No 64bit Carbon API on legacy platforms */
155 FT_UNUSED( ats_font_id );
156 FT_UNUSED( ats_font_ref );
160 #else /* 32bit Carbon API on legacy platforms */
165 err = ATSFontGetFileSpecification( ats_font_id, &spec );
167 err = FSpMakeFSRef( &spec, ats_font_ref );
175 FT_GetFileRef_From_Mac_ATS_Name( const char* fontName,
177 FT_Long* face_index )
179 CFStringRef cf_fontName;
180 ATSFontRef ats_font_id;
185 cf_fontName = CFStringCreateWithCString( NULL, fontName,
186 kCFStringEncodingMacRoman );
187 ats_font_id = ATSFontFindFromName( cf_fontName,
188 kATSOptionFlagsUnRestrictedScope );
189 CFRelease( cf_fontName );
191 if ( ats_font_id == 0 || ats_font_id == 0xFFFFFFFFUL )
192 return FT_THROW( Unknown_File_Format );
194 if ( noErr != FT_ATSFontGetFileReference( ats_font_id, ats_font_ref ) )
195 return FT_THROW( Unknown_File_Format );
197 /* face_index calculation by searching preceding fontIDs */
198 /* with same FSRef */
200 ATSFontRef id2 = ats_font_id - 1;
206 if ( noErr != FT_ATSFontGetFileReference( id2, &ref2 ) )
208 if ( noErr != FSCompareFSRefs( ats_font_ref, &ref2 ) )
213 *face_index = ats_font_id - ( id2 + 1 );
220 FT_EXPORT_DEF( FT_Error )
221 FT_GetFilePath_From_Mac_ATS_Name( const char* fontName,
224 FT_Long* face_index )
230 if ( !fontName || !face_index )
231 return FT_THROW( Invalid_Argument) ;
233 err = FT_GetFileRef_From_Mac_ATS_Name( fontName, &ref, face_index );
237 if ( noErr != FSRefMakePath( &ref, path, maxPathSize ) )
238 return FT_THROW( Unknown_File_Format );
244 /* This function is deprecated because FSSpec is deprecated in Mac OS X */
245 FT_EXPORT_DEF( FT_Error )
246 FT_GetFile_From_Mac_ATS_Name( const char* fontName,
248 FT_Long* face_index )
250 #if ( __LP64__ ) || ( defined( MAC_OS_X_VERSION_10_5 ) && \
251 ( MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 ) )
252 FT_UNUSED( fontName );
253 FT_UNUSED( pathSpec );
254 FT_UNUSED( face_index );
256 return FT_THROW( Unimplemented_Feature );
262 if ( !fontName || !face_index )
263 return FT_THROW( Invalid_Argument );
265 err = FT_GetFileRef_From_Mac_ATS_Name( fontName, &ref, face_index );
269 if ( noErr != FSGetCatalogInfo( &ref, kFSCatInfoNone, NULL, NULL,
271 return FT_THROW( Unknown_File_Format );
279 FT_FSPathMakeRes( const UInt8* pathname,
286 if ( noErr != FSPathMakeRef( pathname, &ref, FALSE ) )
287 return FT_THROW( Cannot_Open_Resource );
289 /* at present, no support for dfont format */
290 err = FSOpenResourceFile( &ref, 0, NULL, fsRdPerm, res );
294 /* fallback to original resource-fork font */
295 *res = FSOpenResFile( &ref, fsRdPerm );
302 /* Return the file type for given pathname */
304 get_file_type_from_path( const UInt8* pathname )
310 if ( noErr != FSPathMakeRef( pathname, &ref, FALSE ) )
313 if ( noErr != FSGetCatalogInfo( &ref, kFSCatInfoFinderInfo, &info,
317 return ((FInfo *)(info.finderInfo))->fdType;
321 /* Given a PostScript font name, create the Macintosh LWFN file name. */
323 create_lwfn_name( char* ps_name,
324 Str255 lwfn_file_name )
326 int max = 5, count = 0;
327 FT_Byte* p = lwfn_file_name;
328 FT_Byte* q = (FT_Byte*)ps_name;
331 lwfn_file_name[0] = 0;
335 if ( ft_isupper( *q ) )
341 if ( count < max && ( ft_isalnum( *q ) || *q == '_' ) )
353 count_faces_sfnt( char* fond_data )
355 /* The count is 1 greater than the value in the FOND. */
356 /* Isn't that cute? :-) */
358 return EndianS16_BtoN( *( (short*)( fond_data +
359 sizeof ( FamRec ) ) ) ) + 1;
364 count_faces_scalable( char* fond_data )
367 short i, face, face_all;
370 face_all = EndianS16_BtoN( *( (short *)( fond_data +
371 sizeof ( FamRec ) ) ) ) + 1;
372 assoc = (AsscEntry*)( fond_data + sizeof ( FamRec ) + 2 );
375 for ( i = 0; i < face_all; i++ )
377 if ( 0 == EndianS16_BtoN( assoc[i].fontSize ) )
384 /* Look inside the FOND data, answer whether there should be an SFNT
385 resource, and answer the name of a possible LWFN Type 1 file.
387 Thanks to Paul Miller (paulm@profoundeffects.com) for the fix
388 to load a face OTHER than the first one in the FOND!
393 parse_fond( char* fond_data,
396 Str255 lwfn_file_name,
400 AsscEntry* base_assoc;
406 lwfn_file_name[0] = 0;
408 fond = (FamRec*)fond_data;
409 assoc = (AsscEntry*)( fond_data + sizeof ( FamRec ) + 2 );
412 /* the maximum faces in a FOND is 48, size of StyleTable.indexes[] */
413 if ( 47 < face_index )
416 /* Let's do a little range checking before we get too excited here */
417 if ( face_index < count_faces_sfnt( fond_data ) )
419 assoc += face_index; /* add on the face_index! */
421 /* if the face at this index is not scalable,
422 fall back to the first one (old behavior) */
423 if ( EndianS16_BtoN( assoc->fontSize ) == 0 )
426 *sfnt_id = EndianS16_BtoN( assoc->fontID );
428 else if ( base_assoc->fontSize == 0 )
431 *sfnt_id = EndianS16_BtoN( base_assoc->fontID );
435 if ( EndianS32_BtoN( fond->ffStylOff ) )
437 unsigned char* p = (unsigned char*)fond_data;
439 unsigned short string_count;
441 unsigned char* names[64];
445 p += EndianS32_BtoN( fond->ffStylOff );
446 style = (StyleTable*)p;
447 p += sizeof ( StyleTable );
448 string_count = EndianS16_BtoN( *(short*)(p) );
449 string_count = FT_MIN( 64, string_count );
450 p += sizeof ( short );
452 for ( i = 0; i < string_count; i++ )
460 size_t ps_name_len = (size_t)names[0][0];
463 if ( ps_name_len != 0 )
465 ft_memcpy(ps_name, names[0] + 1, ps_name_len);
466 ps_name[ps_name_len] = 0;
468 if ( style->indexes[face_index] > 1 &&
469 style->indexes[face_index] <= string_count )
471 unsigned char* suffixes = names[style->indexes[face_index] - 1];
474 for ( i = 1; i <= suffixes[0]; i++ )
477 size_t j = suffixes[i] - 1;
480 if ( j < string_count && ( s = names[j] ) != NULL )
482 size_t s_len = (size_t)s[0];
485 if ( s_len != 0 && ps_name_len + s_len < sizeof ( ps_name ) )
487 ft_memcpy( ps_name + ps_name_len, s + 1, s_len );
488 ps_name_len += s_len;
489 ps_name[ps_name_len] = 0;
496 create_lwfn_name( ps_name, lwfn_file_name );
502 lookup_lwfn_by_fond( const UInt8* path_fond,
503 ConstStr255Param base_lwfn,
511 /* Pathname for FSRef can be in various formats: HFS, HFS+, and POSIX. */
512 /* We should not extract parent directory by string manipulation. */
514 if ( noErr != FSPathMakeRef( path_fond, &ref, FALSE ) )
515 return FT_THROW( Invalid_Argument );
517 if ( noErr != FSGetCatalogInfo( &ref, kFSCatInfoNone,
518 NULL, NULL, NULL, &par_ref ) )
519 return FT_THROW( Invalid_Argument );
521 if ( noErr != FSRefMakePath( &par_ref, path_lwfn, path_size ) )
522 return FT_THROW( Invalid_Argument );
524 if ( ft_strlen( (char *)path_lwfn ) + 1 + base_lwfn[0] > path_size )
525 return FT_THROW( Invalid_Argument );
527 /* now we have absolute dirname in path_lwfn */
528 ft_strcat( (char *)path_lwfn, "/" );
529 dirname_len = ft_strlen( (char *)path_lwfn );
530 ft_strcat( (char *)path_lwfn, (char *)base_lwfn + 1 );
531 path_lwfn[dirname_len + base_lwfn[0]] = '\0';
533 if ( noErr != FSPathMakeRef( path_lwfn, &ref, FALSE ) )
534 return FT_THROW( Cannot_Open_Resource );
536 if ( noErr != FSGetCatalogInfo( &ref, kFSCatInfoNone,
537 NULL, NULL, NULL, NULL ) )
538 return FT_THROW( Cannot_Open_Resource );
545 count_faces( Handle fond,
546 const UInt8* pathname )
549 short have_sfnt, have_lwfn;
550 Str255 lwfn_file_name;
551 UInt8 buff[PATH_MAX];
556 have_sfnt = have_lwfn = 0;
558 parse_fond( *fond, &have_sfnt, &sfnt_id, lwfn_file_name, 0 );
560 if ( lwfn_file_name[0] )
562 err = lookup_lwfn_by_fond( pathname, lwfn_file_name,
563 buff, sizeof ( buff ) );
568 if ( have_lwfn && ( !have_sfnt || PREFER_LWFN ) )
571 num_faces = count_faces_scalable( *fond );
577 /* Read Type 1 data from the POST resources inside the LWFN file,
578 return a PFB buffer. This is somewhat convoluted because the FT2
579 PFB parser wants the ASCII header as one chunk, and the LWFN
580 chunks are often not organized that way, so we glue chunks
581 of the same type together. */
583 read_lwfn( FT_Memory memory,
588 FT_Error error = FT_Err_Ok;
590 unsigned char *buffer, *p, *size_p = NULL;
591 FT_ULong total_size = 0;
592 FT_ULong old_total_size = 0;
593 FT_ULong post_size, pfb_chunk_size;
595 char code, last_code;
600 /* First pass: load all POST resources, and determine the size of */
601 /* the output buffer. */
607 post_data = Get1Resource( TTAG_POST, res_id++ );
608 if ( post_data == NULL )
609 break; /* we are done */
611 code = (*post_data)[0];
613 if ( code != last_code )
616 total_size += 2; /* just the end code */
618 total_size += 6; /* code + 4 bytes chunk length */
621 total_size += GetHandleSize( post_data ) - 2;
624 /* detect integer overflows */
625 if ( total_size < old_total_size )
627 error = FT_THROW( Array_Too_Large );
631 old_total_size = total_size;
634 if ( FT_ALLOC( buffer, (FT_Long)total_size ) )
637 /* Second pass: append all POST data to the buffer, add PFB fields. */
638 /* Glue all consecutive chunks of the same type together. */
646 post_data = Get1Resource( TTAG_POST, res_id++ );
647 if ( post_data == NULL )
648 break; /* we are done */
650 post_size = (FT_ULong)GetHandleSize( post_data ) - 2;
651 code = (*post_data)[0];
653 if ( code != last_code )
655 if ( last_code != -1 )
657 /* we are done adding a chunk, fill in the size field */
658 if ( size_p != NULL )
660 *size_p++ = (FT_Byte)( pfb_chunk_size & 0xFF );
661 *size_p++ = (FT_Byte)( ( pfb_chunk_size >> 8 ) & 0xFF );
662 *size_p++ = (FT_Byte)( ( pfb_chunk_size >> 16 ) & 0xFF );
663 *size_p++ = (FT_Byte)( ( pfb_chunk_size >> 24 ) & 0xFF );
670 *p++ = 0x03; /* the end */
671 else if ( code == 2 )
672 *p++ = 0x02; /* binary segment */
674 *p++ = 0x01; /* ASCII segment */
678 size_p = p; /* save for later */
679 p += 4; /* make space for size field */
683 ft_memcpy( p, *post_data + 2, post_size );
684 pfb_chunk_size += post_size;
698 /* Create a new FT_Face from a file path to an LWFN file. */
700 FT_New_Face_From_LWFN( FT_Library library,
701 const UInt8* pathname,
711 if ( noErr != FT_FSPathMakeRes( pathname, &res ) )
712 return FT_THROW( Cannot_Open_Resource );
716 error = read_lwfn( library->memory, res, &pfb_data, &pfb_size );
717 CloseResFile( res ); /* PFB is already loaded, useless anymore */
721 return open_face_from_buffer( library,
730 /* Create a new FT_Face from an SFNT resource, specified by res ID. */
732 FT_New_Face_From_SFNT( FT_Library library,
740 FT_Error error = FT_Err_Ok;
741 FT_Memory memory = library->memory;
742 int is_cff, is_sfnt_ps;
745 sfnt = GetResource( TTAG_sfnt, sfnt_id );
747 return FT_THROW( Invalid_Handle );
749 sfnt_size = (FT_ULong)GetHandleSize( sfnt );
750 if ( FT_ALLOC( sfnt_data, (FT_Long)sfnt_size ) )
752 ReleaseResource( sfnt );
756 ft_memcpy( sfnt_data, *sfnt, sfnt_size );
757 ReleaseResource( sfnt );
759 is_cff = sfnt_size > 4 && !ft_memcmp( sfnt_data, "OTTO", 4 );
760 is_sfnt_ps = sfnt_size > 4 && !ft_memcmp( sfnt_data, "typ1", 4 );
767 if ( FT_NEW( stream ) )
770 FT_Stream_OpenMemory( stream, sfnt_data, sfnt_size );
771 if ( !open_face_PS_from_sfnt_stream( library,
777 FT_Stream_Close( stream );
779 FT_FREE( sfnt_data );
786 error = open_face_from_buffer( library,
790 is_cff ? "cff" : "truetype",
797 /* Create a new FT_Face from a file path to a suitcase file. */
799 FT_New_Face_From_Suitcase( FT_Library library,
800 const UInt8* pathname,
804 FT_Error error = FT_ERR( Cannot_Open_Resource );
805 ResFileRefNum res_ref;
806 ResourceIndex res_index;
808 short num_faces_in_res;
811 if ( noErr != FT_FSPathMakeRes( pathname, &res_ref ) )
812 return FT_THROW( Cannot_Open_Resource );
814 UseResFile( res_ref );
816 return FT_THROW( Cannot_Open_Resource );
818 num_faces_in_res = 0;
819 for ( res_index = 1; ; ++res_index )
821 short num_faces_in_fond;
824 fond = Get1IndResource( TTAG_FOND, res_index );
828 num_faces_in_fond = count_faces( fond, pathname );
829 num_faces_in_res += num_faces_in_fond;
831 if ( 0 <= face_index && face_index < num_faces_in_fond && error )
832 error = FT_New_Face_From_FOND( library, fond, face_index, aface );
834 face_index -= num_faces_in_fond;
837 CloseResFile( res_ref );
838 if ( !error && aface && *aface )
839 (*aface)->num_faces = num_faces_in_res;
844 /* documentation is in ftmac.h */
846 FT_EXPORT_DEF( FT_Error )
847 FT_New_Face_From_FOND( FT_Library library,
852 short have_sfnt, have_lwfn = 0;
853 ResID sfnt_id, fond_id;
856 Str255 lwfn_file_name;
857 UInt8 path_lwfn[PATH_MAX];
859 FT_Error error = FT_Err_Ok;
862 /* check of `library' and `aface' delayed to `FT_New_Face_From_XXX' */
864 GetResInfo( fond, &fond_id, &fond_type, fond_name );
865 if ( ResError() != noErr || fond_type != TTAG_FOND )
866 return FT_THROW( Invalid_File_Format );
868 parse_fond( *fond, &have_sfnt, &sfnt_id, lwfn_file_name, face_index );
870 if ( lwfn_file_name[0] )
875 res = HomeResFile( fond );
876 if ( noErr != ResError() )
877 goto found_no_lwfn_file;
880 UInt8 path_fond[PATH_MAX];
884 err = FSGetForkCBInfo( res, kFSInvalidVolumeRefNum,
885 NULL, NULL, NULL, &ref, NULL );
887 goto found_no_lwfn_file;
889 err = FSRefMakePath( &ref, path_fond, sizeof ( path_fond ) );
891 goto found_no_lwfn_file;
893 error = lookup_lwfn_by_fond( path_fond, lwfn_file_name,
894 path_lwfn, sizeof ( path_lwfn ) );
900 if ( have_lwfn && ( !have_sfnt || PREFER_LWFN ) )
901 error = FT_New_Face_From_LWFN( library,
906 error = FT_THROW( Unknown_File_Format );
909 if ( have_sfnt && error )
910 error = FT_New_Face_From_SFNT( library,
919 /* Common function to load a new FT_Face from a resource file. */
921 FT_New_Face_From_Resource( FT_Library library,
922 const UInt8* pathname,
930 /* LWFN is a (very) specific file format, check for it explicitly */
931 file_type = get_file_type_from_path( pathname );
932 if ( file_type == TTAG_LWFN )
933 return FT_New_Face_From_LWFN( library, pathname, face_index, aface );
935 /* Otherwise the file type doesn't matter (there are more than */
936 /* `FFIL' and `tfil'). Just try opening it as a font suitcase; */
937 /* if it works, fine. */
939 error = FT_New_Face_From_Suitcase( library, pathname, face_index, aface );
943 /* let it fall through to normal loader (.ttf, .otf, etc.); */
944 /* we signal this by returning no error and no FT_Face */
950 /*************************************************************************/
956 /* This is the Mac-specific implementation of FT_New_Face. In */
957 /* addition to the standard FT_New_Face() functionality, it also */
958 /* accepts pathnames to Mac suitcase files. For further */
959 /* documentation see the original FT_New_Face() in freetype.h. */
961 FT_EXPORT_DEF( FT_Error )
962 FT_New_Face( FT_Library library,
963 const char* pathname,
971 /* test for valid `library' and `aface' delayed to FT_Open_Face() */
973 return FT_THROW( Invalid_Argument );
977 /* try resourcefork based font: LWFN, FFIL */
978 error = FT_New_Face_From_Resource( library, (UInt8 *)pathname,
980 if ( error != 0 || *aface != NULL )
983 /* let it fall through to normal loader (.ttf, .otf, etc.) */
984 args.flags = FT_OPEN_PATHNAME;
985 args.pathname = (char*)pathname;
986 return FT_Open_Face( library, &args, face_index, aface );
990 /*************************************************************************/
993 /* FT_New_Face_From_FSRef */
996 /* FT_New_Face_From_FSRef is identical to FT_New_Face except it */
997 /* accepts an FSRef instead of a path. */
999 /* This function is deprecated because Carbon data types (FSRef) */
1000 /* are not cross-platform, and thus not suitable for the freetype API. */
1001 FT_EXPORT_DEF( FT_Error )
1002 FT_New_Face_From_FSRef( FT_Library library,
1011 UInt8 pathname[PATH_MAX];
1014 /* check of `library' and `aface' delayed to */
1015 /* `FT_New_Face_From_Resource' */
1018 return FT_THROW( Invalid_Argument );
1020 err = FSRefMakePath( ref, pathname, sizeof ( pathname ) );
1022 error = FT_THROW( Cannot_Open_Resource );
1024 error = FT_New_Face_From_Resource( library, pathname, face_index, aface );
1025 if ( error != 0 || *aface != NULL )
1028 /* fallback to datafork font */
1029 args.flags = FT_OPEN_PATHNAME;
1030 args.pathname = (char*)pathname;
1031 return FT_Open_Face( library, &args, face_index, aface );
1035 /*************************************************************************/
1038 /* FT_New_Face_From_FSSpec */
1041 /* FT_New_Face_From_FSSpec is identical to FT_New_Face except it */
1042 /* accepts an FSSpec instead of a path. */
1044 /* This function is deprecated because FSSpec is deprecated in Mac OS X */
1045 FT_EXPORT_DEF( FT_Error )
1046 FT_New_Face_From_FSSpec( FT_Library library,
1051 #if ( __LP64__ ) || ( defined( MAC_OS_X_VERSION_10_5 ) && \
1052 ( MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 ) )
1053 FT_UNUSED( library );
1055 FT_UNUSED( face_index );
1058 return FT_THROW( Unimplemented_Feature );
1063 /* check of `library' and `aface' delayed to `FT_New_Face_From_FSRef' */
1065 if ( !spec || FSpMakeFSRef( spec, &ref ) != noErr )
1066 return FT_THROW( Invalid_Argument );
1068 return FT_New_Face_From_FSRef( library, &ref, face_index, aface );
1072 #endif /* FT_MACINTOSH */