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 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_INTERNAL_STREAM_H
72 /* This is for Mac OS X. Without redefinition, OS_INLINE */
73 /* expands to `static inline' which doesn't survive the */
74 /* -ansi compilation flag of GCC. */
75 #if !HAVE_ANSI_OS_INLINE
77 #define OS_INLINE static __inline__
80 /* The ResourceIndex type was available SDKs on 10.5 */
81 #ifndef HAVE_TYPE_RESOURCE_INDEX
82 typedef short ResourceIndex
;
85 #include <CoreServices/CoreServices.h>
86 #include <ApplicationServices/ApplicationServices.h>
87 #include <sys/syslimits.h> /* PATH_MAX */
89 #define FT_DEPRECATED_ATTRIBUTE
93 /* undefine blocking-macros in ftmac.h */
94 #undef FT_GetFile_From_Mac_Name( a, b, c )
95 #undef FT_GetFile_From_Mac_ATS_Name( a, b, c )
96 #undef FT_New_Face_From_FOND( a, b, c, d )
97 #undef FT_New_Face_From_FSSpec( a, b, c, d )
98 #undef FT_New_Face_From_FSRef( a, b, c, d )
100 #ifndef kATSOptionFlagsUnRestrictedScope /* since Mac OS X 10.1 */
101 #define kATSOptionFlagsUnRestrictedScope kATSOptionFlagsDefault
105 /* Set PREFER_LWFN to 1 if LWFN (Type 1) is preferred over
106 TrueType in case *both* are available (this is not common,
107 but it *is* possible). */
109 #define PREFER_LWFN 1
113 /* This function is deprecated because FSSpec is deprecated in Mac OS X */
114 FT_EXPORT_DEF( FT_Error
)
115 FT_GetFile_From_Mac_Name( const char* fontName
,
117 FT_Long
* face_index
)
119 FT_UNUSED( fontName
);
120 FT_UNUSED( pathSpec
);
121 FT_UNUSED( face_index
);
123 return FT_Err_Unimplemented_Feature
;
127 /* Private function. */
128 /* The FSSpec type has been discouraged for a long time, */
129 /* unfortunately an FSRef replacement API for */
130 /* ATSFontGetFileSpecification() is only available in */
131 /* Mac OS X 10.5 and later. */
133 FT_ATSFontGetFileReference( ATSFontRef ats_font_id
,
134 FSRef
* ats_font_ref
)
136 #if defined( MAC_OS_X_VERSION_10_5 ) && \
137 ( MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 )
141 err
= ATSFontGetFileReference( ats_font_id
, ats_font_ref
);
144 #elif __LP64__ /* No 64bit Carbon API on legacy platforms */
145 FT_UNUSED( ats_font_id
);
146 FT_UNUSED( ats_font_ref
);
150 #else /* 32bit Carbon API on legacy platforms */
155 err
= ATSFontGetFileSpecification( ats_font_id
, &spec
);
157 err
= FSpMakeFSRef( &spec
, ats_font_ref
);
165 FT_GetFileRef_From_Mac_ATS_Name( const char* fontName
,
167 FT_Long
* face_index
)
169 CFStringRef cf_fontName
;
170 ATSFontRef ats_font_id
;
175 cf_fontName
= CFStringCreateWithCString( NULL
, fontName
,
176 kCFStringEncodingMacRoman
);
177 ats_font_id
= ATSFontFindFromName( cf_fontName
,
178 kATSOptionFlagsUnRestrictedScope
);
179 CFRelease( cf_fontName
);
181 if ( ats_font_id
== 0 || ats_font_id
== 0xFFFFFFFFUL
)
182 return FT_Err_Unknown_File_Format
;
184 if ( noErr
!= FT_ATSFontGetFileReference( ats_font_id
, ats_font_ref
) )
185 return FT_Err_Unknown_File_Format
;
187 /* face_index calculation by searching preceding fontIDs */
188 /* with same FSRef */
190 ATSFontRef id2
= ats_font_id
- 1;
196 if ( noErr
!= FT_ATSFontGetFileReference( id2
, &ref2
) )
198 if ( noErr
!= FSCompareFSRefs( ats_font_ref
, &ref2
) )
203 *face_index
= ats_font_id
- ( id2
+ 1 );
210 FT_EXPORT_DEF( FT_Error
)
211 FT_GetFilePath_From_Mac_ATS_Name( const char* fontName
,
214 FT_Long
* face_index
)
220 err
= FT_GetFileRef_From_Mac_ATS_Name( fontName
, &ref
, face_index
);
221 if ( FT_Err_Ok
!= err
)
224 if ( noErr
!= FSRefMakePath( &ref
, path
, maxPathSize
) )
225 return FT_Err_Unknown_File_Format
;
231 /* This function is deprecated because FSSpec is deprecated in Mac OS X */
232 FT_EXPORT_DEF( FT_Error
)
233 FT_GetFile_From_Mac_ATS_Name( const char* fontName
,
235 FT_Long
* face_index
)
237 #if ( __LP64__ ) || ( defined( MAC_OS_X_VERSION_10_5 ) && \
238 ( MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 ) )
239 FT_UNUSED( fontName
);
240 FT_UNUSED( pathSpec
);
241 FT_UNUSED( face_index
);
243 return FT_Err_Unimplemented_Feature
;
249 err
= FT_GetFileRef_From_Mac_ATS_Name( fontName
, &ref
, face_index
);
250 if ( FT_Err_Ok
!= err
)
253 if ( noErr
!= FSGetCatalogInfo( &ref
, kFSCatInfoNone
, NULL
, NULL
,
255 return FT_Err_Unknown_File_Format
;
263 FT_FSPathMakeRes( const UInt8
* pathname
,
270 if ( noErr
!= FSPathMakeRef( pathname
, &ref
, FALSE
) )
271 return FT_Err_Cannot_Open_Resource
;
273 /* at present, no support for dfont format */
274 err
= FSOpenResourceFile( &ref
, 0, NULL
, fsRdPerm
, res
);
278 /* fallback to original resource-fork font */
279 *res
= FSOpenResFile( &ref
, fsRdPerm
);
286 /* Return the file type for given pathname */
288 get_file_type_from_path( const UInt8
* pathname
)
294 if ( noErr
!= FSPathMakeRef( pathname
, &ref
, FALSE
) )
297 if ( noErr
!= FSGetCatalogInfo( &ref
, kFSCatInfoFinderInfo
, &info
,
301 return ((FInfo
*)(info
.finderInfo
))->fdType
;
305 /* Given a PostScript font name, create the Macintosh LWFN file name. */
307 create_lwfn_name( char* ps_name
,
308 Str255 lwfn_file_name
)
310 int max
= 5, count
= 0;
311 FT_Byte
* p
= lwfn_file_name
;
312 FT_Byte
* q
= (FT_Byte
*)ps_name
;
315 lwfn_file_name
[0] = 0;
319 if ( ft_isupper( *q
) )
325 if ( count
< max
&& ( ft_isalnum( *q
) || *q
== '_' ) )
337 count_faces_sfnt( char* fond_data
)
339 /* The count is 1 greater than the value in the FOND. */
340 /* Isn't that cute? :-) */
342 return EndianS16_BtoN( *( (short*)( fond_data
+
343 sizeof ( FamRec
) ) ) ) + 1;
348 count_faces_scalable( char* fond_data
)
352 short i
, face
, face_all
;
355 fond
= (FamRec
*)fond_data
;
356 face_all
= EndianS16_BtoN( *( (short *)( fond_data
+
357 sizeof ( FamRec
) ) ) ) + 1;
358 assoc
= (AsscEntry
*)( fond_data
+ sizeof ( FamRec
) + 2 );
361 for ( i
= 0; i
< face_all
; i
++ )
363 if ( 0 == EndianS16_BtoN( assoc
[i
].fontSize
) )
370 /* Look inside the FOND data, answer whether there should be an SFNT
371 resource, and answer the name of a possible LWFN Type 1 file.
373 Thanks to Paul Miller (paulm@profoundeffects.com) for the fix
374 to load a face OTHER than the first one in the FOND!
379 parse_fond( char* fond_data
,
382 Str255 lwfn_file_name
,
386 AsscEntry
* base_assoc
;
392 lwfn_file_name
[0] = 0;
394 fond
= (FamRec
*)fond_data
;
395 assoc
= (AsscEntry
*)( fond_data
+ sizeof ( FamRec
) + 2 );
398 /* the maximum faces in a FOND is 48, size of StyleTable.indexes[] */
399 if ( 47 < face_index
)
402 /* Let's do a little range checking before we get too excited here */
403 if ( face_index
< count_faces_sfnt( fond_data
) )
405 assoc
+= face_index
; /* add on the face_index! */
407 /* if the face at this index is not scalable,
408 fall back to the first one (old behavior) */
409 if ( EndianS16_BtoN( assoc
->fontSize
) == 0 )
412 *sfnt_id
= EndianS16_BtoN( assoc
->fontID
);
414 else if ( base_assoc
->fontSize
== 0 )
417 *sfnt_id
= EndianS16_BtoN( base_assoc
->fontID
);
421 if ( EndianS32_BtoN( fond
->ffStylOff
) )
423 unsigned char* p
= (unsigned char*)fond_data
;
425 unsigned short string_count
;
427 unsigned char* names
[64];
431 p
+= EndianS32_BtoN( fond
->ffStylOff
);
432 style
= (StyleTable
*)p
;
433 p
+= sizeof ( StyleTable
);
434 string_count
= EndianS16_BtoN( *(short*)(p
) );
435 p
+= sizeof ( short );
437 for ( i
= 0; i
< string_count
&& i
< 64; i
++ )
445 size_t ps_name_len
= (size_t)names
[0][0];
448 if ( ps_name_len
!= 0 )
450 ft_memcpy(ps_name
, names
[0] + 1, ps_name_len
);
451 ps_name
[ps_name_len
] = 0;
453 if ( style
->indexes
[face_index
] > 1 &&
454 style
->indexes
[face_index
] <= FT_MIN( string_count
, 64 ) )
456 unsigned char* suffixes
= names
[style
->indexes
[face_index
] - 1];
459 for ( i
= 1; i
<= suffixes
[0]; i
++ )
462 size_t j
= suffixes
[i
] - 1;
465 if ( j
< string_count
&& ( s
= names
[j
] ) != NULL
)
467 size_t s_len
= (size_t)s
[0];
470 if ( s_len
!= 0 && ps_name_len
+ s_len
< sizeof ( ps_name
) )
472 ft_memcpy( ps_name
+ ps_name_len
, s
+ 1, s_len
);
473 ps_name_len
+= s_len
;
474 ps_name
[ps_name_len
] = 0;
481 create_lwfn_name( ps_name
, lwfn_file_name
);
487 lookup_lwfn_by_fond( const UInt8
* path_fond
,
488 ConstStr255Param base_lwfn
,
496 /* Pathname for FSRef can be in various formats: HFS, HFS+, and POSIX. */
497 /* We should not extract parent directory by string manipulation. */
499 if ( noErr
!= FSPathMakeRef( path_fond
, &ref
, FALSE
) )
500 return FT_Err_Invalid_Argument
;
502 if ( noErr
!= FSGetCatalogInfo( &ref
, kFSCatInfoNone
,
503 NULL
, NULL
, NULL
, &par_ref
) )
504 return FT_Err_Invalid_Argument
;
506 if ( noErr
!= FSRefMakePath( &par_ref
, path_lwfn
, path_size
) )
507 return FT_Err_Invalid_Argument
;
509 if ( ft_strlen( (char *)path_lwfn
) + 1 + base_lwfn
[0] > path_size
)
510 return FT_Err_Invalid_Argument
;
512 /* now we have absolute dirname in path_lwfn */
513 ft_strcat( (char *)path_lwfn
, "/" );
514 dirname_len
= ft_strlen( (char *)path_lwfn
);
515 ft_strcat( (char *)path_lwfn
, (char *)base_lwfn
+ 1 );
516 path_lwfn
[dirname_len
+ base_lwfn
[0]] = '\0';
518 if ( noErr
!= FSPathMakeRef( path_lwfn
, &ref
, FALSE
) )
519 return FT_Err_Cannot_Open_Resource
;
521 if ( noErr
!= FSGetCatalogInfo( &ref
, kFSCatInfoNone
,
522 NULL
, NULL
, NULL
, NULL
) )
523 return FT_Err_Cannot_Open_Resource
;
530 count_faces( Handle fond
,
531 const UInt8
* pathname
)
534 short have_sfnt
, have_lwfn
;
535 Str255 lwfn_file_name
;
536 UInt8 buff
[PATH_MAX
];
541 have_sfnt
= have_lwfn
= 0;
543 parse_fond( *fond
, &have_sfnt
, &sfnt_id
, lwfn_file_name
, 0 );
545 if ( lwfn_file_name
[0] )
547 err
= lookup_lwfn_by_fond( pathname
, lwfn_file_name
,
548 buff
, sizeof ( buff
) );
549 if ( FT_Err_Ok
== err
)
553 if ( have_lwfn
&& ( !have_sfnt
|| PREFER_LWFN
) )
556 num_faces
= count_faces_scalable( *fond
);
562 /* Read Type 1 data from the POST resources inside the LWFN file,
563 return a PFB buffer. This is somewhat convoluted because the FT2
564 PFB parser wants the ASCII header as one chunk, and the LWFN
565 chunks are often not organized that way, so we glue chunks
566 of the same type together. */
568 read_lwfn( FT_Memory memory
,
573 FT_Error error
= FT_Err_Ok
;
575 unsigned char *buffer
, *p
, *size_p
= NULL
;
576 FT_ULong total_size
= 0;
577 FT_ULong old_total_size
= 0;
578 FT_ULong post_size
, pfb_chunk_size
;
580 char code
, last_code
;
585 /* First pass: load all POST resources, and determine the size of */
586 /* the output buffer. */
592 post_data
= Get1Resource( FT_MAKE_TAG( 'P', 'O', 'S', 'T' ),
594 if ( post_data
== NULL
)
595 break; /* we are done */
597 code
= (*post_data
)[0];
599 if ( code
!= last_code
)
602 total_size
+= 2; /* just the end code */
604 total_size
+= 6; /* code + 4 bytes chunk length */
607 total_size
+= GetHandleSize( post_data
) - 2;
610 /* detect integer overflows */
611 if ( total_size
< old_total_size
)
613 error
= FT_Err_Array_Too_Large
;
617 old_total_size
= total_size
;
620 if ( FT_ALLOC( buffer
, (FT_Long
)total_size
) )
623 /* Second pass: append all POST data to the buffer, add PFB fields. */
624 /* Glue all consecutive chunks of the same type together. */
632 post_data
= Get1Resource( FT_MAKE_TAG( 'P', 'O', 'S', 'T' ),
634 if ( post_data
== NULL
)
635 break; /* we are done */
637 post_size
= (FT_ULong
)GetHandleSize( post_data
) - 2;
638 code
= (*post_data
)[0];
640 if ( code
!= last_code
)
642 if ( last_code
!= -1 )
644 /* we are done adding a chunk, fill in the size field */
645 if ( size_p
!= NULL
)
647 *size_p
++ = (FT_Byte
)( pfb_chunk_size
& 0xFF );
648 *size_p
++ = (FT_Byte
)( ( pfb_chunk_size
>> 8 ) & 0xFF );
649 *size_p
++ = (FT_Byte
)( ( pfb_chunk_size
>> 16 ) & 0xFF );
650 *size_p
++ = (FT_Byte
)( ( pfb_chunk_size
>> 24 ) & 0xFF );
657 *p
++ = 0x03; /* the end */
658 else if ( code
== 2 )
659 *p
++ = 0x02; /* binary segment */
661 *p
++ = 0x01; /* ASCII segment */
665 size_p
= p
; /* save for later */
666 p
+= 4; /* make space for size field */
670 ft_memcpy( p
, *post_data
+ 2, post_size
);
671 pfb_chunk_size
+= post_size
;
685 /* Finalizer for a memory stream; gets called by FT_Done_Face().
686 It frees the memory it uses. */
688 memory_stream_close( FT_Stream stream
)
690 FT_Memory memory
= stream
->memory
;
693 FT_FREE( stream
->base
);
701 /* Create a new memory stream from a buffer and a size. */
703 new_memory_stream( FT_Library library
,
706 FT_Stream_CloseFunc close
,
715 return FT_Err_Invalid_Library_Handle
;
718 return FT_Err_Invalid_Argument
;
721 memory
= library
->memory
;
722 if ( FT_NEW( stream
) )
725 FT_Stream_OpenMemory( stream
, base
, size
);
727 stream
->close
= close
;
736 /* Create a new FT_Face given a buffer and a driver name. */
738 open_face_from_buffer( FT_Library library
,
742 const char* driver_name
,
748 FT_Memory memory
= library
->memory
;
751 error
= new_memory_stream( library
,
762 args
.flags
= FT_OPEN_STREAM
;
763 args
.stream
= stream
;
766 args
.flags
= args
.flags
| FT_OPEN_DRIVER
;
767 args
.driver
= FT_Get_Module( library
, driver_name
);
770 /* At this point, face_index has served its purpose; */
771 /* whoever calls this function has already used it to */
772 /* locate the correct font data. We should not propagate */
773 /* this index to FT_Open_Face() (unless it is negative). */
775 if ( face_index
> 0 )
778 error
= FT_Open_Face( library
, &args
, face_index
, aface
);
779 if ( error
== FT_Err_Ok
)
780 (*aface
)->face_flags
&= ~FT_FACE_FLAG_EXTERNAL_STREAM
;
782 FT_Stream_Free( stream
, 0 );
788 /* Create a new FT_Face from a file spec to an LWFN file. */
790 FT_New_Face_From_LWFN( FT_Library library
,
791 const UInt8
* pathname
,
801 if ( noErr
!= FT_FSPathMakeRes( pathname
, &res
) )
802 return FT_Err_Cannot_Open_Resource
;
806 error
= read_lwfn( library
->memory
, res
, &pfb_data
, &pfb_size
);
807 CloseResFile( res
); /* PFB is already loaded, useless anymore */
811 return open_face_from_buffer( library
,
820 /* Create a new FT_Face from an SFNT resource, specified by res ID. */
822 FT_New_Face_From_SFNT( FT_Library library
,
830 FT_Error error
= FT_Err_Ok
;
831 FT_Memory memory
= library
->memory
;
835 sfnt
= GetResource( FT_MAKE_TAG( 's', 'f', 'n', 't' ), sfnt_id
);
837 return FT_Err_Invalid_Handle
;
839 sfnt_size
= (FT_ULong
)GetHandleSize( sfnt
);
840 if ( FT_ALLOC( sfnt_data
, (FT_Long
)sfnt_size
) )
842 ReleaseResource( sfnt
);
846 ft_memcpy( sfnt_data
, *sfnt
, sfnt_size
);
847 ReleaseResource( sfnt
);
849 is_cff
= sfnt_size
> 4 && sfnt_data
[0] == 'O' &&
850 sfnt_data
[1] == 'T' &&
851 sfnt_data
[2] == 'T' &&
854 return open_face_from_buffer( library
,
858 is_cff
? "cff" : "truetype",
863 /* Create a new FT_Face from a file spec to a suitcase file. */
865 FT_New_Face_From_Suitcase( FT_Library library
,
866 const UInt8
* pathname
,
870 FT_Error error
= FT_Err_Cannot_Open_Resource
;
871 ResFileRefNum res_ref
;
872 ResourceIndex res_index
;
874 short num_faces_in_res
, num_faces_in_fond
;
877 if ( noErr
!= FT_FSPathMakeRes( pathname
, &res_ref
) )
878 return FT_Err_Cannot_Open_Resource
;
880 UseResFile( res_ref
);
882 return FT_Err_Cannot_Open_Resource
;
884 num_faces_in_res
= 0;
885 for ( res_index
= 1; ; ++res_index
)
887 fond
= Get1IndResource( FT_MAKE_TAG( 'F', 'O', 'N', 'D' ),
892 num_faces_in_fond
= count_faces( fond
, pathname
);
893 num_faces_in_res
+= num_faces_in_fond
;
895 if ( 0 <= face_index
&& face_index
< num_faces_in_fond
&& error
)
896 error
= FT_New_Face_From_FOND( library
, fond
, face_index
, aface
);
898 face_index
-= num_faces_in_fond
;
901 CloseResFile( res_ref
);
902 if ( FT_Err_Ok
== error
&& NULL
!= aface
&& NULL
!= *aface
)
903 (*aface
)->num_faces
= num_faces_in_res
;
908 /* documentation is in ftmac.h */
910 FT_EXPORT_DEF( FT_Error
)
911 FT_New_Face_From_FOND( FT_Library library
,
916 short have_sfnt
, have_lwfn
= 0;
917 ResID sfnt_id
, fond_id
;
920 Str255 lwfn_file_name
;
921 UInt8 path_lwfn
[PATH_MAX
];
923 FT_Error error
= FT_Err_Ok
;
926 GetResInfo( fond
, &fond_id
, &fond_type
, fond_name
);
927 if ( ResError() != noErr
|| fond_type
!= FT_MAKE_TAG( 'F', 'O', 'N', 'D' ) )
928 return FT_Err_Invalid_File_Format
;
930 parse_fond( *fond
, &have_sfnt
, &sfnt_id
, lwfn_file_name
, face_index
);
932 if ( lwfn_file_name
[0] )
937 res
= HomeResFile( fond
);
938 if ( noErr
!= ResError() )
939 goto found_no_lwfn_file
;
942 UInt8 path_fond
[PATH_MAX
];
946 err
= FSGetForkCBInfo( res
, kFSInvalidVolumeRefNum
,
947 NULL
, NULL
, NULL
, &ref
, NULL
);
949 goto found_no_lwfn_file
;
951 err
= FSRefMakePath( &ref
, path_fond
, sizeof ( path_fond
) );
953 goto found_no_lwfn_file
;
955 error
= lookup_lwfn_by_fond( path_fond
, lwfn_file_name
,
956 path_lwfn
, sizeof ( path_lwfn
) );
957 if ( FT_Err_Ok
== error
)
962 if ( have_lwfn
&& ( !have_sfnt
|| PREFER_LWFN
) )
963 error
= FT_New_Face_From_LWFN( library
,
968 error
= FT_Err_Unknown_File_Format
;
971 if ( have_sfnt
&& FT_Err_Ok
!= error
)
972 error
= FT_New_Face_From_SFNT( library
,
981 /* Common function to load a new FT_Face from a resource file. */
983 FT_New_Face_From_Resource( FT_Library library
,
984 const UInt8
* pathname
,
992 /* LWFN is a (very) specific file format, check for it explicitly */
993 file_type
= get_file_type_from_path( pathname
);
994 if ( file_type
== FT_MAKE_TAG( 'L', 'W', 'F', 'N' ) )
995 return FT_New_Face_From_LWFN( library
, pathname
, face_index
, aface
);
997 /* Otherwise the file type doesn't matter (there are more than */
998 /* `FFIL' and `tfil'). Just try opening it as a font suitcase; */
999 /* if it works, fine. */
1001 error
= FT_New_Face_From_Suitcase( library
, pathname
, face_index
, aface
);
1005 /* let it fall through to normal loader (.ttf, .otf, etc.); */
1006 /* we signal this by returning no error and no FT_Face */
1012 /*************************************************************************/
1018 /* This is the Mac-specific implementation of FT_New_Face. In */
1019 /* addition to the standard FT_New_Face() functionality, it also */
1020 /* accepts pathnames to Mac suitcase files. For further */
1021 /* documentation see the original FT_New_Face() in freetype.h. */
1023 FT_EXPORT_DEF( FT_Error
)
1024 FT_New_Face( FT_Library library
,
1025 const char* pathname
,
1033 /* test for valid `library' and `aface' delayed to FT_Open_Face() */
1035 return FT_Err_Invalid_Argument
;
1040 /* try resourcefork based font: LWFN, FFIL */
1041 error
= FT_New_Face_From_Resource( library
, (UInt8
*)pathname
,
1042 face_index
, aface
);
1043 if ( error
!= 0 || *aface
!= NULL
)
1046 /* let it fall through to normal loader (.ttf, .otf, etc.) */
1047 args
.flags
= FT_OPEN_PATHNAME
;
1048 args
.pathname
= (char*)pathname
;
1049 return FT_Open_Face( library
, &args
, face_index
, aface
);
1053 /*************************************************************************/
1056 /* FT_New_Face_From_FSRef */
1059 /* FT_New_Face_From_FSRef is identical to FT_New_Face except it */
1060 /* accepts an FSRef instead of a path. */
1062 /* This function is deprecated because Carbon data types (FSRef) */
1063 /* are not cross-platform, and thus not suitable for the freetype API. */
1064 FT_EXPORT_DEF( FT_Error
)
1065 FT_New_Face_From_FSRef( FT_Library library
,
1073 UInt8 pathname
[PATH_MAX
];
1077 return FT_Err_Invalid_Argument
;
1079 err
= FSRefMakePath( ref
, pathname
, sizeof ( pathname
) );
1081 error
= FT_Err_Cannot_Open_Resource
;
1083 error
= FT_New_Face_From_Resource( library
, pathname
, face_index
, aface
);
1084 if ( error
!= 0 || *aface
!= NULL
)
1087 /* fallback to datafork font */
1088 args
.flags
= FT_OPEN_PATHNAME
;
1089 args
.pathname
= (char*)pathname
;
1090 return FT_Open_Face( library
, &args
, face_index
, aface
);
1094 /*************************************************************************/
1097 /* FT_New_Face_From_FSSpec */
1100 /* FT_New_Face_From_FSSpec is identical to FT_New_Face except it */
1101 /* accepts an FSSpec instead of a path. */
1103 /* This function is deprecated because FSSpec is deprecated in Mac OS X */
1104 FT_EXPORT_DEF( FT_Error
)
1105 FT_New_Face_From_FSSpec( FT_Library library
,
1110 #if ( __LP64__ ) || ( defined( MAC_OS_X_VERSION_10_5 ) && \
1111 ( MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 ) )
1112 FT_UNUSED( library
);
1114 FT_UNUSED( face_index
);
1117 return FT_Err_Unimplemented_Feature
;
1122 if ( !spec
|| FSpMakeFSRef( spec
, &ref
) != noErr
)
1123 return FT_Err_Invalid_Argument
;
1125 return FT_New_Face_From_FSRef( library
, &ref
, face_index
, aface
);