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-2015 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
+= (FT_ULong
)GetHandleSize( post_data
) - 2;
624 /* detect resource fork overflow */
625 if ( FT_MAC_RFORK_MAX_LEN
< 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
);
751 /* detect resource fork overflow */
752 if ( FT_MAC_RFORK_MAX_LEN
< sfnt_size
)
753 return FT_THROW( Array_Too_Large
);
755 if ( FT_ALLOC( sfnt_data
, (FT_Long
)sfnt_size
) )
757 ReleaseResource( sfnt
);
761 ft_memcpy( sfnt_data
, *sfnt
, sfnt_size
);
762 ReleaseResource( sfnt
);
764 is_cff
= sfnt_size
> 4 && !ft_memcmp( sfnt_data
, "OTTO", 4 );
765 is_sfnt_ps
= sfnt_size
> 4 && !ft_memcmp( sfnt_data
, "typ1", 4 );
772 if ( FT_NEW( stream
) )
775 FT_Stream_OpenMemory( stream
, sfnt_data
, sfnt_size
);
776 if ( !open_face_PS_from_sfnt_stream( library
,
782 FT_Stream_Close( stream
);
784 FT_FREE( sfnt_data
);
791 error
= open_face_from_buffer( library
,
795 is_cff
? "cff" : "truetype",
802 /* Create a new FT_Face from a file path to a suitcase file. */
804 FT_New_Face_From_Suitcase( FT_Library library
,
805 const UInt8
* pathname
,
809 FT_Error error
= FT_ERR( Cannot_Open_Resource
);
810 ResFileRefNum res_ref
;
811 ResourceIndex res_index
;
813 short num_faces_in_res
;
816 if ( noErr
!= FT_FSPathMakeRes( pathname
, &res_ref
) )
817 return FT_THROW( Cannot_Open_Resource
);
819 UseResFile( res_ref
);
821 return FT_THROW( Cannot_Open_Resource
);
823 num_faces_in_res
= 0;
824 for ( res_index
= 1; ; ++res_index
)
826 short num_faces_in_fond
;
829 fond
= Get1IndResource( TTAG_FOND
, res_index
);
833 num_faces_in_fond
= count_faces( fond
, pathname
);
834 num_faces_in_res
+= num_faces_in_fond
;
836 if ( 0 <= face_index
&& face_index
< num_faces_in_fond
&& error
)
837 error
= FT_New_Face_From_FOND( library
, fond
, face_index
, aface
);
839 face_index
-= num_faces_in_fond
;
842 CloseResFile( res_ref
);
843 if ( !error
&& aface
&& *aface
)
844 (*aface
)->num_faces
= num_faces_in_res
;
849 /* documentation is in ftmac.h */
851 FT_EXPORT_DEF( FT_Error
)
852 FT_New_Face_From_FOND( FT_Library library
,
857 short have_sfnt
, have_lwfn
= 0;
858 ResID sfnt_id
, fond_id
;
861 Str255 lwfn_file_name
;
862 UInt8 path_lwfn
[PATH_MAX
];
864 FT_Error error
= FT_Err_Ok
;
867 /* check of `library' and `aface' delayed to `FT_New_Face_From_XXX' */
869 GetResInfo( fond
, &fond_id
, &fond_type
, fond_name
);
870 if ( ResError() != noErr
|| fond_type
!= TTAG_FOND
)
871 return FT_THROW( Invalid_File_Format
);
873 parse_fond( *fond
, &have_sfnt
, &sfnt_id
, lwfn_file_name
, face_index
);
875 if ( lwfn_file_name
[0] )
880 res
= HomeResFile( fond
);
881 if ( noErr
!= ResError() )
882 goto found_no_lwfn_file
;
885 UInt8 path_fond
[PATH_MAX
];
889 err
= FSGetForkCBInfo( res
, kFSInvalidVolumeRefNum
,
890 NULL
, NULL
, NULL
, &ref
, NULL
);
892 goto found_no_lwfn_file
;
894 err
= FSRefMakePath( &ref
, path_fond
, sizeof ( path_fond
) );
896 goto found_no_lwfn_file
;
898 error
= lookup_lwfn_by_fond( path_fond
, lwfn_file_name
,
899 path_lwfn
, sizeof ( path_lwfn
) );
905 if ( have_lwfn
&& ( !have_sfnt
|| PREFER_LWFN
) )
906 error
= FT_New_Face_From_LWFN( library
,
911 error
= FT_THROW( Unknown_File_Format
);
914 if ( have_sfnt
&& error
)
915 error
= FT_New_Face_From_SFNT( library
,
924 /* Common function to load a new FT_Face from a resource file. */
926 FT_New_Face_From_Resource( FT_Library library
,
927 const UInt8
* pathname
,
935 /* LWFN is a (very) specific file format, check for it explicitly */
936 file_type
= get_file_type_from_path( pathname
);
937 if ( file_type
== TTAG_LWFN
)
938 return FT_New_Face_From_LWFN( library
, pathname
, face_index
, aface
);
940 /* Otherwise the file type doesn't matter (there are more than */
941 /* `FFIL' and `tfil'). Just try opening it as a font suitcase; */
942 /* if it works, fine. */
944 error
= FT_New_Face_From_Suitcase( library
, pathname
, face_index
, aface
);
948 /* let it fall through to normal loader (.ttf, .otf, etc.); */
949 /* we signal this by returning no error and no FT_Face */
955 /*************************************************************************/
961 /* This is the Mac-specific implementation of FT_New_Face. In */
962 /* addition to the standard FT_New_Face() functionality, it also */
963 /* accepts pathnames to Mac suitcase files. For further */
964 /* documentation see the original FT_New_Face() in freetype.h. */
966 FT_EXPORT_DEF( FT_Error
)
967 FT_New_Face( FT_Library library
,
968 const char* pathname
,
976 /* test for valid `library' and `aface' delayed to FT_Open_Face() */
978 return FT_THROW( Invalid_Argument
);
982 /* try resourcefork based font: LWFN, FFIL */
983 error
= FT_New_Face_From_Resource( library
, (UInt8
*)pathname
,
985 if ( error
!= 0 || *aface
!= NULL
)
988 /* let it fall through to normal loader (.ttf, .otf, etc.) */
989 args
.flags
= FT_OPEN_PATHNAME
;
990 args
.pathname
= (char*)pathname
;
991 return FT_Open_Face( library
, &args
, face_index
, aface
);
995 /*************************************************************************/
998 /* FT_New_Face_From_FSRef */
1001 /* FT_New_Face_From_FSRef is identical to FT_New_Face except it */
1002 /* accepts an FSRef instead of a path. */
1004 /* This function is deprecated because Carbon data types (FSRef) */
1005 /* are not cross-platform, and thus not suitable for the freetype API. */
1006 FT_EXPORT_DEF( FT_Error
)
1007 FT_New_Face_From_FSRef( FT_Library library
,
1016 UInt8 pathname
[PATH_MAX
];
1019 /* check of `library' and `aface' delayed to */
1020 /* `FT_New_Face_From_Resource' */
1023 return FT_THROW( Invalid_Argument
);
1025 err
= FSRefMakePath( ref
, pathname
, sizeof ( pathname
) );
1027 error
= FT_THROW( Cannot_Open_Resource
);
1029 error
= FT_New_Face_From_Resource( library
, pathname
, face_index
, aface
);
1030 if ( error
!= 0 || *aface
!= NULL
)
1033 /* fallback to datafork font */
1034 args
.flags
= FT_OPEN_PATHNAME
;
1035 args
.pathname
= (char*)pathname
;
1036 return FT_Open_Face( library
, &args
, face_index
, aface
);
1040 /*************************************************************************/
1043 /* FT_New_Face_From_FSSpec */
1046 /* FT_New_Face_From_FSSpec is identical to FT_New_Face except it */
1047 /* accepts an FSSpec instead of a path. */
1049 /* This function is deprecated because FSSpec is deprecated in Mac OS X */
1050 FT_EXPORT_DEF( FT_Error
)
1051 FT_New_Face_From_FSSpec( FT_Library library
,
1056 #if ( __LP64__ ) || ( defined( MAC_OS_X_VERSION_10_5 ) && \
1057 ( MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 ) )
1058 FT_UNUSED( library
);
1060 FT_UNUSED( face_index
);
1063 return FT_THROW( Unimplemented_Feature
);
1068 /* check of `library' and `aface' delayed to `FT_New_Face_From_FSRef' */
1070 if ( !spec
|| FSpMakeFSRef( spec
, &ref
) != noErr
)
1071 return FT_THROW( Invalid_Argument
);
1073 return FT_New_Face_From_FSRef( library
, &ref
, face_index
, aface
);
1077 #endif /* FT_MACINTOSH */