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
122
/* This function is deprecated because FSSpec is deprecated in Mac OS X */
123
FT_EXPORT_DEF( FT_Error )
124
FT_GetFile_From_Mac_Name( const char* fontName,
126
FT_Long* face_index )
128
FT_UNUSED( fontName );
129
FT_UNUSED( pathSpec );
130
FT_UNUSED( face_index );
132
return FT_Err_Unimplemented_Feature;
136
/* Private function. */
137
/* The FSSpec type has been discouraged for a long time, */
138
/* unfortunately an FSRef replacement API for */
139
/* ATSFontGetFileSpecification() is only available in */
140
/* Mac OS X 10.5 and later. */
142
FT_ATSFontGetFileReference( ATSFontRef ats_font_id,
143
FSRef* ats_font_ref )
145
#if defined( MAC_OS_X_VERSION_10_5 ) && \
146
( MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 )
150
err = ATSFontGetFileReference( ats_font_id, ats_font_ref );
153
#elif __LP64__ /* No 64bit Carbon API on legacy platforms */
154
FT_UNUSED( ats_font_id );
155
FT_UNUSED( ats_font_ref );
159
#else /* 32bit Carbon API on legacy platforms */
164
err = ATSFontGetFileSpecification( ats_font_id, &spec );
166
err = FSpMakeFSRef( &spec, ats_font_ref );
174
FT_GetFileRef_From_Mac_ATS_Name( const char* fontName,
176
FT_Long* face_index )
178
CFStringRef cf_fontName;
179
ATSFontRef ats_font_id;
184
cf_fontName = CFStringCreateWithCString( NULL, fontName,
185
kCFStringEncodingMacRoman );
186
ats_font_id = ATSFontFindFromName( cf_fontName,
187
kATSOptionFlagsUnRestrictedScope );
188
CFRelease( cf_fontName );
190
if ( ats_font_id == 0 || ats_font_id == 0xFFFFFFFFUL )
191
return FT_Err_Unknown_File_Format;
193
if ( noErr != FT_ATSFontGetFileReference( ats_font_id, ats_font_ref ) )
194
return FT_Err_Unknown_File_Format;
196
/* face_index calculation by searching preceding fontIDs */
197
/* with same FSRef */
199
ATSFontRef id2 = ats_font_id - 1;
205
if ( noErr != FT_ATSFontGetFileReference( id2, &ref2 ) )
207
if ( noErr != FSCompareFSRefs( ats_font_ref, &ref2 ) )
212
*face_index = ats_font_id - ( id2 + 1 );
219
FT_EXPORT_DEF( FT_Error )
220
FT_GetFilePath_From_Mac_ATS_Name( const char* fontName,
223
FT_Long* face_index )
229
err = FT_GetFileRef_From_Mac_ATS_Name( fontName, &ref, face_index );
230
if ( FT_Err_Ok != err )
233
if ( noErr != FSRefMakePath( &ref, path, maxPathSize ) )
234
return FT_Err_Unknown_File_Format;
240
/* This function is deprecated because FSSpec is deprecated in Mac OS X */
241
FT_EXPORT_DEF( FT_Error )
242
FT_GetFile_From_Mac_ATS_Name( const char* fontName,
244
FT_Long* face_index )
246
#if ( __LP64__ ) || ( defined( MAC_OS_X_VERSION_10_5 ) && \
247
( MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 ) )
248
FT_UNUSED( fontName );
249
FT_UNUSED( pathSpec );
250
FT_UNUSED( face_index );
252
return FT_Err_Unimplemented_Feature;
258
err = FT_GetFileRef_From_Mac_ATS_Name( fontName, &ref, face_index );
259
if ( FT_Err_Ok != err )
262
if ( noErr != FSGetCatalogInfo( &ref, kFSCatInfoNone, NULL, NULL,
264
return FT_Err_Unknown_File_Format;
272
FT_FSPathMakeRes( const UInt8* pathname,
279
if ( noErr != FSPathMakeRef( pathname, &ref, FALSE ) )
280
return FT_Err_Cannot_Open_Resource;
282
/* at present, no support for dfont format */
283
err = FSOpenResourceFile( &ref, 0, NULL, fsRdPerm, res );
287
/* fallback to original resource-fork font */
288
*res = FSOpenResFile( &ref, fsRdPerm );
295
/* Return the file type for given pathname */
297
get_file_type_from_path( const UInt8* pathname )
303
if ( noErr != FSPathMakeRef( pathname, &ref, FALSE ) )
306
if ( noErr != FSGetCatalogInfo( &ref, kFSCatInfoFinderInfo, &info,
310
return ((FInfo *)(info.finderInfo))->fdType;
314
/* Given a PostScript font name, create the Macintosh LWFN file name. */
316
create_lwfn_name( char* ps_name,
317
Str255 lwfn_file_name )
319
int max = 5, count = 0;
320
FT_Byte* p = lwfn_file_name;
321
FT_Byte* q = (FT_Byte*)ps_name;
324
lwfn_file_name[0] = 0;
328
if ( ft_isupper( *q ) )
334
if ( count < max && ( ft_isalnum( *q ) || *q == '_' ) )
346
count_faces_sfnt( char* fond_data )
348
/* The count is 1 greater than the value in the FOND. */
349
/* Isn't that cute? :-) */
351
return EndianS16_BtoN( *( (short*)( fond_data +
352
sizeof ( FamRec ) ) ) ) + 1;
357
count_faces_scalable( char* fond_data )
361
short i, face, face_all;
364
fond = (FamRec*)fond_data;
365
face_all = EndianS16_BtoN( *( (short *)( fond_data +
366
sizeof ( FamRec ) ) ) ) + 1;
367
assoc = (AsscEntry*)( fond_data + sizeof ( FamRec ) + 2 );
370
for ( i = 0; i < face_all; i++ )
372
if ( 0 == EndianS16_BtoN( assoc[i].fontSize ) )
379
/* Look inside the FOND data, answer whether there should be an SFNT
380
resource, and answer the name of a possible LWFN Type 1 file.
382
Thanks to Paul Miller (paulm@profoundeffects.com) for the fix
383
to load a face OTHER than the first one in the FOND!
388
parse_fond( char* fond_data,
391
Str255 lwfn_file_name,
395
AsscEntry* base_assoc;
401
lwfn_file_name[0] = 0;
403
fond = (FamRec*)fond_data;
404
assoc = (AsscEntry*)( fond_data + sizeof ( FamRec ) + 2 );
407
/* the maximum faces in a FOND is 48, size of StyleTable.indexes[] */
408
if ( 47 < face_index )
411
/* Let's do a little range checking before we get too excited here */
412
if ( face_index < count_faces_sfnt( fond_data ) )
414
assoc += face_index; /* add on the face_index! */
416
/* if the face at this index is not scalable,
417
fall back to the first one (old behavior) */
418
if ( EndianS16_BtoN( assoc->fontSize ) == 0 )
421
*sfnt_id = EndianS16_BtoN( assoc->fontID );
423
else if ( base_assoc->fontSize == 0 )
426
*sfnt_id = EndianS16_BtoN( base_assoc->fontID );
430
if ( EndianS32_BtoN( fond->ffStylOff ) )
432
unsigned char* p = (unsigned char*)fond_data;
434
unsigned short string_count;
436
unsigned char* names[64];
440
p += EndianS32_BtoN( fond->ffStylOff );
441
style = (StyleTable*)p;
442
p += sizeof ( StyleTable );
443
string_count = EndianS16_BtoN( *(short*)(p) );
444
p += sizeof ( short );
446
for ( i = 0; i < string_count && i < 64; i++ )
454
size_t ps_name_len = (size_t)names[0][0];
457
if ( ps_name_len != 0 )
459
ft_memcpy(ps_name, names[0] + 1, ps_name_len);
460
ps_name[ps_name_len] = 0;
462
if ( style->indexes[face_index] > 1 &&
463
style->indexes[face_index] <= FT_MIN( string_count, 64 ) )
465
unsigned char* suffixes = names[style->indexes[face_index] - 1];
468
for ( i = 1; i <= suffixes[0]; i++ )
471
size_t j = suffixes[i] - 1;
474
if ( j < string_count && ( s = names[j] ) != NULL )
476
size_t s_len = (size_t)s[0];
479
if ( s_len != 0 && ps_name_len + s_len < sizeof ( ps_name ) )
481
ft_memcpy( ps_name + ps_name_len, s + 1, s_len );
482
ps_name_len += s_len;
483
ps_name[ps_name_len] = 0;
490
create_lwfn_name( ps_name, lwfn_file_name );
496
lookup_lwfn_by_fond( const UInt8* path_fond,
497
ConstStr255Param base_lwfn,
505
/* Pathname for FSRef can be in various formats: HFS, HFS+, and POSIX. */
506
/* We should not extract parent directory by string manipulation. */
508
if ( noErr != FSPathMakeRef( path_fond, &ref, FALSE ) )
509
return FT_Err_Invalid_Argument;
511
if ( noErr != FSGetCatalogInfo( &ref, kFSCatInfoNone,
512
NULL, NULL, NULL, &par_ref ) )
513
return FT_Err_Invalid_Argument;
515
if ( noErr != FSRefMakePath( &par_ref, path_lwfn, path_size ) )
516
return FT_Err_Invalid_Argument;
518
if ( ft_strlen( (char *)path_lwfn ) + 1 + base_lwfn[0] > path_size )
519
return FT_Err_Invalid_Argument;
521
/* now we have absolute dirname in path_lwfn */
522
ft_strcat( (char *)path_lwfn, "/" );
523
dirname_len = ft_strlen( (char *)path_lwfn );
524
ft_strcat( (char *)path_lwfn, (char *)base_lwfn + 1 );
525
path_lwfn[dirname_len + base_lwfn[0]] = '\0';
527
if ( noErr != FSPathMakeRef( path_lwfn, &ref, FALSE ) )
528
return FT_Err_Cannot_Open_Resource;
530
if ( noErr != FSGetCatalogInfo( &ref, kFSCatInfoNone,
531
NULL, NULL, NULL, NULL ) )
532
return FT_Err_Cannot_Open_Resource;
539
count_faces( Handle fond,
540
const UInt8* pathname )
543
short have_sfnt, have_lwfn;
544
Str255 lwfn_file_name;
545
UInt8 buff[PATH_MAX];
550
have_sfnt = have_lwfn = 0;
552
parse_fond( *fond, &have_sfnt, &sfnt_id, lwfn_file_name, 0 );
554
if ( lwfn_file_name[0] )
556
err = lookup_lwfn_by_fond( pathname, lwfn_file_name,
557
buff, sizeof ( buff ) );
558
if ( FT_Err_Ok == err )
562
if ( have_lwfn && ( !have_sfnt || PREFER_LWFN ) )
565
num_faces = count_faces_scalable( *fond );
571
/* Read Type 1 data from the POST resources inside the LWFN file,
572
return a PFB buffer. This is somewhat convoluted because the FT2
573
PFB parser wants the ASCII header as one chunk, and the LWFN
574
chunks are often not organized that way, so we glue chunks
575
of the same type together. */
577
read_lwfn( FT_Memory memory,
582
FT_Error error = FT_Err_Ok;
584
unsigned char *buffer, *p, *size_p = NULL;
585
FT_ULong total_size = 0;
586
FT_ULong old_total_size = 0;
587
FT_ULong post_size, pfb_chunk_size;
589
char code, last_code;
594
/* First pass: load all POST resources, and determine the size of */
595
/* the output buffer. */
601
post_data = Get1Resource( TTAG_POST, res_id++ );
602
if ( post_data == NULL )
603
break; /* we are done */
605
code = (*post_data)[0];
607
if ( code != last_code )
610
total_size += 2; /* just the end code */
612
total_size += 6; /* code + 4 bytes chunk length */
615
total_size += GetHandleSize( post_data ) - 2;
618
/* detect integer overflows */
619
if ( total_size < old_total_size )
621
error = FT_Err_Array_Too_Large;
625
old_total_size = total_size;
628
if ( FT_ALLOC( buffer, (FT_Long)total_size ) )
631
/* Second pass: append all POST data to the buffer, add PFB fields. */
632
/* Glue all consecutive chunks of the same type together. */
640
post_data = Get1Resource( TTAG_POST, res_id++ );
641
if ( post_data == NULL )
642
break; /* we are done */
644
post_size = (FT_ULong)GetHandleSize( post_data ) - 2;
645
code = (*post_data)[0];
647
if ( code != last_code )
649
if ( last_code != -1 )
651
/* we are done adding a chunk, fill in the size field */
652
if ( size_p != NULL )
654
*size_p++ = (FT_Byte)( pfb_chunk_size & 0xFF );
655
*size_p++ = (FT_Byte)( ( pfb_chunk_size >> 8 ) & 0xFF );
656
*size_p++ = (FT_Byte)( ( pfb_chunk_size >> 16 ) & 0xFF );
657
*size_p++ = (FT_Byte)( ( pfb_chunk_size >> 24 ) & 0xFF );
664
*p++ = 0x03; /* the end */
665
else if ( code == 2 )
666
*p++ = 0x02; /* binary segment */
668
*p++ = 0x01; /* ASCII segment */
672
size_p = p; /* save for later */
673
p += 4; /* make space for size field */
677
ft_memcpy( p, *post_data + 2, post_size );
678
pfb_chunk_size += post_size;
692
/* Create a new FT_Face from a file path to an LWFN file. */
694
FT_New_Face_From_LWFN( FT_Library library,
695
const UInt8* pathname,
705
if ( noErr != FT_FSPathMakeRes( pathname, &res ) )
706
return FT_Err_Cannot_Open_Resource;
710
error = read_lwfn( library->memory, res, &pfb_data, &pfb_size );
711
CloseResFile( res ); /* PFB is already loaded, useless anymore */
715
return open_face_from_buffer( library,
724
/* Create a new FT_Face from an SFNT resource, specified by res ID. */
726
FT_New_Face_From_SFNT( FT_Library library,
734
FT_Error error = FT_Err_Ok;
735
FT_Memory memory = library->memory;
736
int is_cff, is_sfnt_ps;
739
sfnt = GetResource( TTAG_sfnt, sfnt_id );
741
return FT_Err_Invalid_Handle;
743
sfnt_size = (FT_ULong)GetHandleSize( sfnt );
744
if ( FT_ALLOC( sfnt_data, (FT_Long)sfnt_size ) )
746
ReleaseResource( sfnt );
750
ft_memcpy( sfnt_data, *sfnt, sfnt_size );
751
ReleaseResource( sfnt );
753
is_cff = sfnt_size > 4 && !ft_memcmp( sfnt_data, "OTTO", 4 );
754
is_sfnt_ps = sfnt_size > 4 && !ft_memcmp( sfnt_data, "typ1", 4 );
761
if ( FT_NEW( stream ) )
764
FT_Stream_OpenMemory( stream, sfnt_data, sfnt_size );
765
if ( !open_face_PS_from_sfnt_stream( library,
771
FT_Stream_Close( stream );
773
FT_FREE( sfnt_data );
780
error = open_face_from_buffer( library,
784
is_cff ? "cff" : "truetype",
791
/* Create a new FT_Face from a file path to a suitcase file. */
793
FT_New_Face_From_Suitcase( FT_Library library,
794
const UInt8* pathname,
798
FT_Error error = FT_Err_Cannot_Open_Resource;
799
ResFileRefNum res_ref;
800
ResourceIndex res_index;
802
short num_faces_in_res, num_faces_in_fond;
805
if ( noErr != FT_FSPathMakeRes( pathname, &res_ref ) )
806
return FT_Err_Cannot_Open_Resource;
808
UseResFile( res_ref );
810
return FT_Err_Cannot_Open_Resource;
812
num_faces_in_res = 0;
813
for ( res_index = 1; ; ++res_index )
815
fond = Get1IndResource( TTAG_FOND, res_index );
819
num_faces_in_fond = count_faces( fond, pathname );
820
num_faces_in_res += num_faces_in_fond;
822
if ( 0 <= face_index && face_index < num_faces_in_fond && error )
823
error = FT_New_Face_From_FOND( library, fond, face_index, aface );
825
face_index -= num_faces_in_fond;
828
CloseResFile( res_ref );
829
if ( FT_Err_Ok == error && NULL != aface && NULL != *aface )
830
(*aface)->num_faces = num_faces_in_res;
835
/* documentation is in ftmac.h */
837
FT_EXPORT_DEF( FT_Error )
838
FT_New_Face_From_FOND( FT_Library library,
843
short have_sfnt, have_lwfn = 0;
844
ResID sfnt_id, fond_id;
847
Str255 lwfn_file_name;
848
UInt8 path_lwfn[PATH_MAX];
850
FT_Error error = FT_Err_Ok;
853
GetResInfo( fond, &fond_id, &fond_type, fond_name );
854
if ( ResError() != noErr || fond_type != TTAG_FOND )
855
return FT_Err_Invalid_File_Format;
857
parse_fond( *fond, &have_sfnt, &sfnt_id, lwfn_file_name, face_index );
859
if ( lwfn_file_name[0] )
864
res = HomeResFile( fond );
865
if ( noErr != ResError() )
866
goto found_no_lwfn_file;
869
UInt8 path_fond[PATH_MAX];
873
err = FSGetForkCBInfo( res, kFSInvalidVolumeRefNum,
874
NULL, NULL, NULL, &ref, NULL );
876
goto found_no_lwfn_file;
878
err = FSRefMakePath( &ref, path_fond, sizeof ( path_fond ) );
880
goto found_no_lwfn_file;
882
error = lookup_lwfn_by_fond( path_fond, lwfn_file_name,
883
path_lwfn, sizeof ( path_lwfn ) );
884
if ( FT_Err_Ok == error )
889
if ( have_lwfn && ( !have_sfnt || PREFER_LWFN ) )
890
error = FT_New_Face_From_LWFN( library,
895
error = FT_Err_Unknown_File_Format;
898
if ( have_sfnt && FT_Err_Ok != error )
899
error = FT_New_Face_From_SFNT( library,
908
/* Common function to load a new FT_Face from a resource file. */
910
FT_New_Face_From_Resource( FT_Library library,
911
const UInt8* pathname,
919
/* LWFN is a (very) specific file format, check for it explicitly */
920
file_type = get_file_type_from_path( pathname );
921
if ( file_type == TTAG_LWFN )
922
return FT_New_Face_From_LWFN( library, pathname, face_index, aface );
924
/* Otherwise the file type doesn't matter (there are more than */
925
/* `FFIL' and `tfil'). Just try opening it as a font suitcase; */
926
/* if it works, fine. */
928
error = FT_New_Face_From_Suitcase( library, pathname, face_index, aface );
932
/* let it fall through to normal loader (.ttf, .otf, etc.); */
933
/* we signal this by returning no error and no FT_Face */
939
/*************************************************************************/
945
/* This is the Mac-specific implementation of FT_New_Face. In */
946
/* addition to the standard FT_New_Face() functionality, it also */
947
/* accepts pathnames to Mac suitcase files. For further */
948
/* documentation see the original FT_New_Face() in freetype.h. */
950
FT_EXPORT_DEF( FT_Error )
951
FT_New_Face( FT_Library library,
952
const char* pathname,
960
/* test for valid `library' and `aface' delayed to FT_Open_Face() */
962
return FT_Err_Invalid_Argument;
967
/* try resourcefork based font: LWFN, FFIL */
968
error = FT_New_Face_From_Resource( library, (UInt8 *)pathname,
970
if ( error != 0 || *aface != NULL )
973
/* let it fall through to normal loader (.ttf, .otf, etc.) */
974
args.flags = FT_OPEN_PATHNAME;
975
args.pathname = (char*)pathname;
976
return FT_Open_Face( library, &args, face_index, aface );
980
/*************************************************************************/
983
/* FT_New_Face_From_FSRef */
986
/* FT_New_Face_From_FSRef is identical to FT_New_Face except it */
987
/* accepts an FSRef instead of a path. */
989
/* This function is deprecated because Carbon data types (FSRef) */
990
/* are not cross-platform, and thus not suitable for the freetype API. */
991
FT_EXPORT_DEF( FT_Error )
992
FT_New_Face_From_FSRef( FT_Library library,
1000
UInt8 pathname[PATH_MAX];
1004
return FT_Err_Invalid_Argument;
1006
err = FSRefMakePath( ref, pathname, sizeof ( pathname ) );
1008
error = FT_Err_Cannot_Open_Resource;
1010
error = FT_New_Face_From_Resource( library, pathname, face_index, aface );
1011
if ( error != 0 || *aface != NULL )
1014
/* fallback to datafork font */
1015
args.flags = FT_OPEN_PATHNAME;
1016
args.pathname = (char*)pathname;
1017
return FT_Open_Face( library, &args, face_index, aface );
1021
/*************************************************************************/
1024
/* FT_New_Face_From_FSSpec */
1027
/* FT_New_Face_From_FSSpec is identical to FT_New_Face except it */
1028
/* accepts an FSSpec instead of a path. */
1030
/* This function is deprecated because FSSpec is deprecated in Mac OS X */
1031
FT_EXPORT_DEF( FT_Error )
1032
FT_New_Face_From_FSSpec( FT_Library library,
1037
#if ( __LP64__ ) || ( defined( MAC_OS_X_VERSION_10_5 ) && \
1038
( MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 ) )
1039
FT_UNUSED( library );
1041
FT_UNUSED( face_index );
1044
return FT_Err_Unimplemented_Feature;
1049
if ( !spec || FSpMakeFSRef( spec, &ref ) != noErr )
1050
return FT_Err_Invalid_Argument;
1052
return FT_New_Face_From_FSRef( library, &ref, face_index, aface );