blob: fd6201adb5a5cfa9d2bec1a56bb1a4deb78fa470 [file] [log] [blame]
Just van Rossumae4bcee2000-07-28 01:10:35 +00001/***************************************************************************/
2/* */
3/* ftmac.c */
4/* */
Werner Lemberg05c21b82000-07-29 20:38:19 +00005/* Mac FOND support. Written by just@letterror.com. */
Werner Lemberg0fd08bd2006-12-16 02:57:46 +00006/* Heavily modified by mpsuzuki, George Williams, and Sean McBride. */
7/* */
8/* This file is for Mac OS X only; see builds/mac/ftoldmac.c for */
Werner Lemberg9b774e22007-01-16 06:11:27 +00009/* classic platforms built by MPW. */
Just van Rossumae4bcee2000-07-28 01:10:35 +000010/* */
Werner Lembergdcbb7082007-02-08 08:54:09 +000011/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007 by */
Just van Rossumae4bcee2000-07-28 01:10:35 +000012/* Just van Rossum, David Turner, Robert Wilhelm, and Werner Lemberg. */
13/* */
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. */
19/* */
20/***************************************************************************/
21
22
23 /*
24 Notes
25
Werner Lemberg9ca7a152002-04-30 14:26:49 +000026 Mac suitcase files can (and often do!) contain multiple fonts. To
Just van Rossumae4bcee2000-07-28 01:10:35 +000027 support this I use the face_index argument of FT_(Open|New)_Face()
28 functions, and pretend the suitcase file is a collection.
Werner Lemberg9ca7a152002-04-30 14:26:49 +000029
Werner Lemberg435046b2006-01-11 10:57:42 +000030 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.
Just van Rossumae4bcee2000-07-28 01:10:35 +000035
Just van Rossumae4bcee2000-07-28 01:10:35 +000036 The Mac FOND support works roughly like this:
37
Werner Lemberg435046b2006-01-11 10:57:42 +000038 - 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.
Just van Rossumae4bcee2000-07-28 01:10:35 +000043
Werner Lemberg435046b2006-01-11 10:57:42 +000044 - Read the FOND resource into memory, then check whether there is a
45 TrueType font and/or(!) a Type 1 font available.
Just van Rossumae4bcee2000-07-28 01:10:35 +000046
Werner Lemberg435046b2006-01-11 10:57:42 +000047 - 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...)
Just van Rossumae4bcee2000-07-28 01:10:35 +000055
Werner Lemberg435046b2006-01-11 10:57:42 +000056 - 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().
Werner Lemberg745ff2c2006-09-19 05:48:02 +000059
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
64 available.
Just van Rossumae4bcee2000-07-28 01:10:35 +000065 */
66
Werner Lembergcc069be2000-12-08 16:17:16 +000067
68#include <ft2build.h>
69#include FT_FREETYPE_H
70#include FT_INTERNAL_STREAM_H
Werner Lemberg6eb116e2003-05-11 07:12:26 +000071
Werner Lemberg3599a022004-04-14 08:49:11 +000072 /* 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. */
Suzuki, Toshiya (鈴木俊哉)027357f2007-02-05 02:50:45 +000075#if !HAVE_ANSI_OS_INLINE
Suzuki, Toshiya (鈴木俊哉)52311972006-06-22 02:34:27 +000076#undef OS_INLINE
Werner Lembergdcbb7082007-02-08 08:54:09 +000077#define OS_INLINE static __inline__
Suzuki, Toshiya (鈴木俊哉)027357f2007-02-05 02:50:45 +000078#endif
Werner Lemberg6eb116e2003-05-11 07:12:26 +000079#include <Carbon/Carbon.h>
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +000080
81#ifndef HFS_MAXPATHLEN
Werner Lemberg435046b2006-01-11 10:57:42 +000082#define HFS_MAXPATHLEN 1024
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +000083#endif
84
Suzuki, Toshiya (鈴木俊哉)f223df62007-02-05 04:07:46 +000085#define FT_DEPRECATED_ATTRIBUTE
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +000086
Suzuki, Toshiya (鈴木俊哉)7e3d6012006-12-15 15:23:21 +000087#include FT_MAC_H
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +000088
Suzuki, Toshiya (鈴木俊哉)7e3d6012006-12-15 15:23:21 +000089 /* undefine blocking-macros in ftmac.h */
90#undef FT_GetFile_From_Mac_Name( a, b, c )
91#undef FT_GetFile_From_Mac_ATS_Name( a, b, c )
92#undef FT_New_Face_From_FSSpec( a, b, c, d )
93
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +000094
Just van Rossumae4bcee2000-07-28 01:10:35 +000095 /* Set PREFER_LWFN to 1 if LWFN (Type 1) is preferred over
96 TrueType in case *both* are available (this is not common,
97 but it *is* possible). */
98#ifndef PREFER_LWFN
Werner Lemberg435046b2006-01-11 10:57:42 +000099#define PREFER_LWFN 1
Just van Rossumae4bcee2000-07-28 01:10:35 +0000100#endif
101
Werner Lemberge2455ba2004-02-26 21:56:27 +0000102
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000103 FT_EXPORT_DEF( FT_Error )
104 FT_GetFile_From_Mac_Name( const char* fontName,
105 FSSpec* pathSpec,
106 FT_Long* face_index )
107 {
Suzuki, Toshiya (鈴木俊哉)78935012007-06-19 03:27:05 +0000108 FT_UNUSED( fontName );
109 FT_UNUSED( pathSpec );
110 FT_UNUSED( face_index );
111
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000112 return FT_Err_Unimplemented_Feature;
113 }
Werner Lemberg435046b2006-01-11 10:57:42 +0000114
Werner Lemberg435046b2006-01-11 10:57:42 +0000115
Suzuki, Toshiya (鈴木俊哉)4827e9b2007-02-05 03:28:29 +0000116 /* Private function. */
117 /* The FSSpec type has been discouraged for a long time, */
118 /* but for some reason, there is no FSRef version of */
119 /* ATSFontGetFileSpecification(), so we made our own. */
120 /* Apple will provide one eventually. */
121 static OSStatus
122 FT_ATSFontGetFileReference( ATSFontRef ats_font_id,
123 FSRef* ats_font_ref )
124 {
Suzuki, Toshiya (鈴木俊哉)78935012007-06-19 03:27:05 +0000125#if __LP64__
126 FT_UNUSED( ats_font_id );
127 FT_UNUSED( ats_font_ref );
128
129 return fnfErr;
130#else
Werner Lembergdcbb7082007-02-08 08:54:09 +0000131 OSStatus err;
132 FSSpec spec;
133
Suzuki, Toshiya (鈴木俊哉)4827e9b2007-02-05 03:28:29 +0000134
135 err = ATSFontGetFileSpecification( ats_font_id, &spec );
136 if ( noErr == err )
Suzuki, Toshiya (鈴木俊哉)4827e9b2007-02-05 03:28:29 +0000137 err = FSpMakeFSRef( &spec, ats_font_ref );
Suzuki, Toshiya (鈴木俊哉)4827e9b2007-02-05 03:28:29 +0000138
139 return err;
Suzuki, Toshiya (鈴木俊哉)78935012007-06-19 03:27:05 +0000140#endif
Suzuki, Toshiya (鈴木俊哉)4827e9b2007-02-05 03:28:29 +0000141 }
142
143
144 static FT_Error
145 FT_GetFileRef_From_Mac_ATS_Name( const char* fontName,
146 FSRef* ats_font_ref,
147 FT_Long* face_index )
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000148 {
149 CFStringRef cf_fontName;
150 ATSFontRef ats_font_id;
Werner Lemberg435046b2006-01-11 10:57:42 +0000151
152
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000153 *face_index = 0;
Werner Lemberg435046b2006-01-11 10:57:42 +0000154
155 cf_fontName = CFStringCreateWithCString( NULL, fontName,
156 kCFStringEncodingMacRoman );
157 ats_font_id = ATSFontFindFromName( cf_fontName,
158 kATSOptionFlagsUnRestrictedScope );
Suzuki, Toshiya (鈴木俊哉)b68e0252007-02-20 02:37:36 +0000159 CFRelease( cf_fontName );
Werner Lemberg435046b2006-01-11 10:57:42 +0000160
161 if ( ats_font_id == 0 || ats_font_id == 0xFFFFFFFFUL )
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000162 return FT_Err_Unknown_File_Format;
Werner Lemberg435046b2006-01-11 10:57:42 +0000163
Suzuki, Toshiya (鈴木俊哉)4827e9b2007-02-05 03:28:29 +0000164 if ( noErr != FT_ATSFontGetFileReference( ats_font_id, ats_font_ref ) )
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000165 return FT_Err_Unknown_File_Format;
Werner Lemberg435046b2006-01-11 10:57:42 +0000166
167 /* face_index calculation by searching preceding fontIDs */
168 /* with same FSRef */
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000169 {
Suzuki, Toshiya (鈴木俊哉)4827e9b2007-02-05 03:28:29 +0000170 ATSFontRef id2 = ats_font_id - 1;
171 FSRef ref2;
Werner Lemberg435046b2006-01-11 10:57:42 +0000172
173
Suzuki, Toshiya (鈴木俊哉)4827e9b2007-02-05 03:28:29 +0000174 while ( id2 > 0 )
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000175 {
Suzuki, Toshiya (鈴木俊哉)4827e9b2007-02-05 03:28:29 +0000176 if ( noErr != FT_ATSFontGetFileReference( id2, &ref2 ) )
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000177 break;
Suzuki, Toshiya (鈴木俊哉)4827e9b2007-02-05 03:28:29 +0000178 if ( noErr != FSCompareFSRefs( ats_font_ref, &ref2 ) )
179 break;
180
181 id2 --;
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000182 }
Suzuki, Toshiya (鈴木俊哉)4827e9b2007-02-05 03:28:29 +0000183 *face_index = ats_font_id - ( id2 + 1 );
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000184 }
Suzuki, Toshiya (鈴木俊哉)4827e9b2007-02-05 03:28:29 +0000185
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000186 return FT_Err_Ok;
187 }
Werner Lemberg435046b2006-01-11 10:57:42 +0000188
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000189
Suzuki, Toshiya (鈴木俊哉)4827e9b2007-02-05 03:28:29 +0000190 FT_EXPORT_DEF( FT_Error )
191 FT_GetFilePath_From_Mac_ATS_Name( const char* fontName,
192 UInt8* path,
193 UInt32 maxPathSize,
194 FT_Long* face_index )
195 {
196 FSRef ref;
197 FT_Error err;
198
199
200 err = FT_GetFileRef_From_Mac_ATS_Name( fontName, &ref, face_index );
201 if ( FT_Err_Ok != err )
202 return err;
203
204 if ( noErr != FSRefMakePath( &ref, path, maxPathSize ) )
205 return FT_Err_Unknown_File_Format;
206
207 return FT_Err_Ok;
208 }
209
210
211 /* This function is deprecated because FSSpec is deprecated in Mac OS X */
212 FT_EXPORT_DEF( FT_Error )
213 FT_GetFile_From_Mac_ATS_Name( const char* fontName,
214 FSSpec* pathSpec,
215 FT_Long* face_index )
216 {
217#if __LP64__
Suzuki, Toshiya (鈴木俊哉)78935012007-06-19 03:27:05 +0000218 FT_UNUSED( fontName );
219 FT_UNUSED( pathSpec );
220 FT_UNUSED( face_index );
Werner Lembergdcbb7082007-02-08 08:54:09 +0000221
Suzuki, Toshiya (鈴木俊哉)4827e9b2007-02-05 03:28:29 +0000222 return FT_Err_Unimplemented_Feature;
223#else
224 FSRef ref;
225 FT_Error err;
226
Werner Lembergdcbb7082007-02-08 08:54:09 +0000227
Suzuki, Toshiya (鈴木俊哉)4827e9b2007-02-05 03:28:29 +0000228 err = FT_GetFileRef_From_Mac_ATS_Name( fontName, &ref, face_index );
229 if ( FT_Err_Ok != err )
230 return err;
231
232 if ( noErr != FSGetCatalogInfo( &ref, kFSCatInfoNone, NULL, NULL,
233 pathSpec, NULL ) )
234 return FT_Err_Unknown_File_Format;
235
236 return FT_Err_Ok;
237#endif
238 }
239
240
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000241 static OSErr
242 FT_FSPathMakeRes( const UInt8* pathname,
243 short* res )
244 {
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000245 OSErr err;
246 FSRef ref;
247
Werner Lemberg435046b2006-01-11 10:57:42 +0000248
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000249 if ( noErr != FSPathMakeRef( pathname, &ref, FALSE ) )
250 return FT_Err_Cannot_Open_Resource;
251
Werner Lemberg435046b2006-01-11 10:57:42 +0000252 /* at present, no support for dfont format */
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000253 err = FSOpenResourceFile( &ref, 0, NULL, fsRdPerm, res );
254 if ( noErr == err )
255 return err;
256
257 /* fallback to original resource-fork font */
258 *res = FSOpenResFile( &ref, fsRdPerm );
259 err = ResError();
Werner Lemberg435046b2006-01-11 10:57:42 +0000260
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000261 return err;
262 }
263
264
265 /* Return the file type for given pathname */
266 static OSType
267 get_file_type_from_path( const UInt8* pathname )
268 {
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000269 FSRef ref;
270 FSCatalogInfo info;
271
272
273 if ( noErr != FSPathMakeRef( pathname, &ref, FALSE ) )
274 return ( OSType ) 0;
275
276 if ( noErr != FSGetCatalogInfo( &ref, kFSCatInfoFinderInfo, &info,
277 NULL, NULL, NULL ) )
278 return ( OSType ) 0;
279
Werner Lemberg435046b2006-01-11 10:57:42 +0000280 return ((FInfo *)(info.finderInfo))->fdType;
Just van Rossumae4bcee2000-07-28 01:10:35 +0000281 }
282
Werner Lemberge9e130c2001-12-07 21:56:32 +0000283
Just van Rossumae4bcee2000-07-28 01:10:35 +0000284 /* Given a PostScript font name, create the Macintosh LWFN file name. */
Werner Lembergf814d0f2001-06-27 16:18:10 +0000285 static void
286 create_lwfn_name( char* ps_name,
287 Str255 lwfn_file_name )
Just van Rossumae4bcee2000-07-28 01:10:35 +0000288 {
289 int max = 5, count = 0;
290 FT_Byte* p = lwfn_file_name;
291 FT_Byte* q = (FT_Byte*)ps_name;
292
293
294 lwfn_file_name[0] = 0;
295
296 while ( *q )
297 {
Werner Lemberg282637f2003-05-21 07:39:42 +0000298 if ( ft_isupper( *q ) )
Just van Rossumae4bcee2000-07-28 01:10:35 +0000299 {
300 if ( count )
301 max = 3;
302 count = 0;
303 }
David Turnerd15bc0d2002-04-12 09:31:48 +0000304 if ( count < max && ( ft_isalnum( *q ) || *q == '_' ) )
Just van Rossumae4bcee2000-07-28 01:10:35 +0000305 {
306 *++p = *q;
307 lwfn_file_name[0]++;
308 count++;
309 }
310 q++;
311 }
312 }
313
314
Werner Lemberge2455ba2004-02-26 21:56:27 +0000315 static short
Werner Lemberg083ba0b2005-12-23 15:10:54 +0000316 count_faces_sfnt( char* fond_data )
Werner Lemberge2455ba2004-02-26 21:56:27 +0000317 {
318 /* The count is 1 greater than the value in the FOND. */
319 /* Isn't that cute? :-) */
320
Werner Lembergef3d2c22006-06-25 06:07:14 +0000321 return EndianS16_BtoN( *( (short*)( fond_data +
322 sizeof ( FamRec ) ) ) ) + 1;
Werner Lemberge2455ba2004-02-26 21:56:27 +0000323 }
324
325
Suzuki, Toshiya (鈴木俊哉)53be6e92005-12-23 12:22:46 +0000326 static short
Werner Lemberg083ba0b2005-12-23 15:10:54 +0000327 count_faces_scalable( char* fond_data )
Suzuki, Toshiya (鈴木俊哉)53be6e92005-12-23 12:22:46 +0000328 {
329 AsscEntry* assoc;
330 FamRec* fond;
331 short i, face, face_all;
332
333
Werner Lemberg435046b2006-01-11 10:57:42 +0000334 fond = (FamRec*)fond_data;
Werner Lembergef3d2c22006-06-25 06:07:14 +0000335 face_all = EndianS16_BtoN( *( (short *)( fond_data +
336 sizeof ( FamRec ) ) ) ) + 1;
Werner Lemberg435046b2006-01-11 10:57:42 +0000337 assoc = (AsscEntry*)( fond_data + sizeof ( FamRec ) + 2 );
338 face = 0;
Suzuki, Toshiya (鈴木俊哉)53be6e92005-12-23 12:22:46 +0000339
340 for ( i = 0; i < face_all; i++ )
341 {
Suzuki, Toshiya (鈴木俊哉)52311972006-06-22 02:34:27 +0000342 if ( 0 == EndianS16_BtoN( assoc[i].fontSize ) )
Werner Lemberg083ba0b2005-12-23 15:10:54 +0000343 face++;
Suzuki, Toshiya (鈴木俊哉)53be6e92005-12-23 12:22:46 +0000344 }
345 return face;
346 }
347
348
Just van Rossumae4bcee2000-07-28 01:10:35 +0000349 /* Look inside the FOND data, answer whether there should be an SFNT
Werner Lemberge9e130c2001-12-07 21:56:32 +0000350 resource, and answer the name of a possible LWFN Type 1 file.
351
352 Thanks to Paul Miller (paulm@profoundeffects.com) for the fix
Leonard Rosentholae340bb2001-10-26 13:24:39 +0000353 to load a face OTHER than the first one in the FOND!
354 */
Werner Lemberge2455ba2004-02-26 21:56:27 +0000355
356
Werner Lembergf814d0f2001-06-27 16:18:10 +0000357 static void
358 parse_fond( char* fond_data,
359 short* have_sfnt,
360 short* sfnt_id,
Leonard Rosentholae340bb2001-10-26 13:24:39 +0000361 Str255 lwfn_file_name,
362 short face_index )
Just van Rossumae4bcee2000-07-28 01:10:35 +0000363 {
364 AsscEntry* assoc;
Leonard Rosentholae340bb2001-10-26 13:24:39 +0000365 AsscEntry* base_assoc;
Just van Rossumae4bcee2000-07-28 01:10:35 +0000366 FamRec* fond;
367
368
369 *sfnt_id = 0;
370 *have_sfnt = 0;
371 lwfn_file_name[0] = 0;
372
Werner Lembergc3b21602001-12-05 01:22:05 +0000373 fond = (FamRec*)fond_data;
374 assoc = (AsscEntry*)( fond_data + sizeof ( FamRec ) + 2 );
Leonard Rosentholae340bb2001-10-26 13:24:39 +0000375 base_assoc = assoc;
Just van Rossumae4bcee2000-07-28 01:10:35 +0000376
Werner Lemberge2455ba2004-02-26 21:56:27 +0000377 /* Let's do a little range checking before we get too excited here */
378 if ( face_index < count_faces_sfnt( fond_data ) )
Just van Rossumae4bcee2000-07-28 01:10:35 +0000379 {
Werner Lemberge2455ba2004-02-26 21:56:27 +0000380 assoc += face_index; /* add on the face_index! */
381
382 /* if the face at this index is not scalable,
383 fall back to the first one (old behavior) */
Suzuki, Toshiya (鈴木俊哉)52311972006-06-22 02:34:27 +0000384 if ( EndianS16_BtoN( assoc->fontSize ) == 0 )
Werner Lemberge2455ba2004-02-26 21:56:27 +0000385 {
386 *have_sfnt = 1;
Suzuki, Toshiya (鈴木俊哉)52311972006-06-22 02:34:27 +0000387 *sfnt_id = EndianS16_BtoN( assoc->fontID );
Werner Lemberge2455ba2004-02-26 21:56:27 +0000388 }
389 else if ( base_assoc->fontSize == 0 )
390 {
391 *have_sfnt = 1;
Suzuki, Toshiya (鈴木俊哉)52311972006-06-22 02:34:27 +0000392 *sfnt_id = EndianS16_BtoN( base_assoc->fontID );
Werner Lemberge2455ba2004-02-26 21:56:27 +0000393 }
Leonard Rosentholae340bb2001-10-26 13:24:39 +0000394 }
Just van Rossumae4bcee2000-07-28 01:10:35 +0000395
Suzuki, Toshiya (鈴木俊哉)52311972006-06-22 02:34:27 +0000396 if ( EndianS32_BtoN( fond->ffStylOff ) )
Just van Rossumae4bcee2000-07-28 01:10:35 +0000397 {
398 unsigned char* p = (unsigned char*)fond_data;
399 StyleTable* style;
400 unsigned short string_count;
Just van Rossumae4bcee2000-07-28 01:10:35 +0000401 char ps_name[256];
402 unsigned char* names[64];
403 int i;
404
Werner Lemberg05c21b82000-07-29 20:38:19 +0000405
Suzuki, Toshiya (鈴木俊哉)52311972006-06-22 02:34:27 +0000406 p += EndianS32_BtoN( fond->ffStylOff );
Just van Rossumae4bcee2000-07-28 01:10:35 +0000407 style = (StyleTable*)p;
Werner Lemberg05c21b82000-07-29 20:38:19 +0000408 p += sizeof ( StyleTable );
Suzuki, Toshiya (鈴木俊哉)52311972006-06-22 02:34:27 +0000409 string_count = EndianS16_BtoN( *(short*)(p) );
Werner Lemberg05c21b82000-07-29 20:38:19 +0000410 p += sizeof ( short );
Just van Rossumae4bcee2000-07-28 01:10:35 +0000411
Werner Lemberg435046b2006-01-11 10:57:42 +0000412 for ( i = 0; i < string_count && i < 64; i++ )
Just van Rossumae4bcee2000-07-28 01:10:35 +0000413 {
414 names[i] = p;
Werner Lemberg435046b2006-01-11 10:57:42 +0000415 p += names[i][0];
Just van Rossumae4bcee2000-07-28 01:10:35 +0000416 p++;
417 }
Just van Rossumae4bcee2000-07-28 01:10:35 +0000418
Just van Rossumae4bcee2000-07-28 01:10:35 +0000419 {
Werner Lemberg9ca7a152002-04-30 14:26:49 +0000420 size_t ps_name_len = (size_t)names[0][0];
Werner Lemberg05c21b82000-07-29 20:38:19 +0000421
422
Werner Lemberg9ca7a152002-04-30 14:26:49 +0000423 if ( ps_name_len != 0 )
424 {
Werner Lemberg282637f2003-05-21 07:39:42 +0000425 ft_memcpy(ps_name, names[0] + 1, ps_name_len);
Werner Lemberg9ca7a152002-04-30 14:26:49 +0000426 ps_name[ps_name_len] = 0;
427 }
428 if ( style->indexes[0] > 1 )
429 {
430 unsigned char* suffixes = names[style->indexes[0] - 1];
431
432
Werner Lembergfcc5c912003-04-23 18:10:19 +0000433 for ( i = 1; i <= suffixes[0]; i++ )
Werner Lemberg9ca7a152002-04-30 14:26:49 +0000434 {
435 unsigned char* s;
436 size_t j = suffixes[i] - 1;
437
438
439 if ( j < string_count && ( s = names[j] ) != NULL )
440 {
441 size_t s_len = (size_t)s[0];
442
443
444 if ( s_len != 0 && ps_name_len + s_len < sizeof ( ps_name ) )
445 {
Werner Lemberg282637f2003-05-21 07:39:42 +0000446 ft_memcpy( ps_name + ps_name_len, s + 1, s_len );
Werner Lemberg9ca7a152002-04-30 14:26:49 +0000447 ps_name_len += s_len;
448 ps_name[ps_name_len] = 0;
449 }
450 }
451 }
452 }
Just van Rossumae4bcee2000-07-28 01:10:35 +0000453 }
Werner Lemberg9ca7a152002-04-30 14:26:49 +0000454
Just van Rossumae4bcee2000-07-28 01:10:35 +0000455 create_lwfn_name( ps_name, lwfn_file_name );
456 }
457 }
458
459
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000460 static FT_Error
Suzuki, Toshiya (鈴木俊哉)78935012007-06-19 03:27:05 +0000461 lookup_lwfn_by_fond( const UInt8* path_fond,
462 ConstStr255Param base_lwfn,
463 UInt8* path_lwfn,
464 size_t path_size )
Werner Lemberge2455ba2004-02-26 21:56:27 +0000465 {
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000466 FSRef ref, par_ref;
467 int dirname_len;
Werner Lemberge2455ba2004-02-26 21:56:27 +0000468
469
Werner Lemberg435046b2006-01-11 10:57:42 +0000470 /* Pathname for FSRef can be in various formats: HFS, HFS+, and POSIX. */
471 /* We should not extract parent directory by string manipulation. */
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000472
473 if ( noErr != FSPathMakeRef( path_fond, &ref, FALSE ) )
474 return FT_Err_Invalid_Argument;
475
476 if ( noErr != FSGetCatalogInfo( &ref, kFSCatInfoNone,
477 NULL, NULL, NULL, &par_ref ) )
478 return FT_Err_Invalid_Argument;
479
480 if ( noErr != FSRefMakePath( &par_ref, path_lwfn, path_size ) )
481 return FT_Err_Invalid_Argument;
482
483 if ( ft_strlen( (char *)path_lwfn ) + 1 + base_lwfn[0] > path_size )
484 return FT_Err_Invalid_Argument;
485
Suzuki, Toshiya (鈴木俊哉)78935012007-06-19 03:27:05 +0000486 /* now we have absolute dirname in path_lwfn */
487 ft_strcat( (char *)path_lwfn, "/" );
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000488 dirname_len = ft_strlen( (char *)path_lwfn );
489 ft_strcat( (char *)path_lwfn, (char *)base_lwfn + 1 );
Werner Lemberg435046b2006-01-11 10:57:42 +0000490 path_lwfn[dirname_len + base_lwfn[0]] = '\0';
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000491
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000492 if ( noErr != FSPathMakeRef( path_lwfn, &ref, FALSE ) )
493 return FT_Err_Cannot_Open_Resource;
494
495 if ( noErr != FSGetCatalogInfo( &ref, kFSCatInfoNone,
496 NULL, NULL, NULL, NULL ) )
497 return FT_Err_Cannot_Open_Resource;
498
499 return FT_Err_Ok;
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000500 }
501
502
503 static short
504 count_faces( Handle fond,
505 const UInt8* pathname )
506 {
507 short sfnt_id;
508 short have_sfnt, have_lwfn;
Werner Lemberg435046b2006-01-11 10:57:42 +0000509 Str255 lwfn_file_name;
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000510 UInt8 buff[HFS_MAXPATHLEN];
Werner Lemberg435046b2006-01-11 10:57:42 +0000511 FT_Error err;
Suzuki, Toshiya (鈴木俊哉)52311972006-06-22 02:34:27 +0000512 short num_faces;
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000513
514
515 have_sfnt = have_lwfn = 0;
516
Werner Lemberge2455ba2004-02-26 21:56:27 +0000517 parse_fond( *fond, &have_sfnt, &sfnt_id, lwfn_file_name, 0 );
Werner Lemberge2455ba2004-02-26 21:56:27 +0000518
519 if ( lwfn_file_name[0] )
520 {
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000521 err = lookup_lwfn_by_fond( pathname, lwfn_file_name,
Werner Lemberg435046b2006-01-11 10:57:42 +0000522 buff, sizeof ( buff ) );
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000523 if ( FT_Err_Ok == err )
524 have_lwfn = 1;
Werner Lemberge2455ba2004-02-26 21:56:27 +0000525 }
526
527 if ( have_lwfn && ( !have_sfnt || PREFER_LWFN ) )
Suzuki, Toshiya (鈴木俊哉)52311972006-06-22 02:34:27 +0000528 num_faces = 1;
Werner Lemberge2455ba2004-02-26 21:56:27 +0000529 else
Suzuki, Toshiya (鈴木俊哉)52311972006-06-22 02:34:27 +0000530 num_faces = count_faces_scalable( *fond );
531
Suzuki, Toshiya (鈴木俊哉)52311972006-06-22 02:34:27 +0000532 return num_faces;
Werner Lemberge2455ba2004-02-26 21:56:27 +0000533 }
534
535
Just van Rossumae4bcee2000-07-28 01:10:35 +0000536 /* Read Type 1 data from the POST resources inside the LWFN file,
Werner Lemberg435046b2006-01-11 10:57:42 +0000537 return a PFB buffer. This is somewhat convoluted because the FT2
Just van Rossumae4bcee2000-07-28 01:10:35 +0000538 PFB parser wants the ASCII header as one chunk, and the LWFN
Werner Lemberg435046b2006-01-11 10:57:42 +0000539 chunks are often not organized that way, so we glue chunks
Just van Rossumae4bcee2000-07-28 01:10:35 +0000540 of the same type together. */
Werner Lembergf814d0f2001-06-27 16:18:10 +0000541 static FT_Error
542 read_lwfn( FT_Memory memory,
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000543 short res,
Werner Lembergf814d0f2001-06-27 16:18:10 +0000544 FT_Byte** pfb_data,
545 FT_ULong* size )
Just van Rossumae4bcee2000-07-28 01:10:35 +0000546 {
547 FT_Error error = FT_Err_Ok;
Werner Lemberge2455ba2004-02-26 21:56:27 +0000548 short res_id;
Werner Lemberg9ca7a152002-04-30 14:26:49 +0000549 unsigned char *buffer, *p, *size_p = NULL;
Just van Rossumae4bcee2000-07-28 01:10:35 +0000550 FT_ULong total_size = 0;
David Turner9ca78252006-05-02 09:00:29 +0000551 FT_ULong old_total_size = 0;
Just van Rossumae4bcee2000-07-28 01:10:35 +0000552 FT_ULong post_size, pfb_chunk_size;
553 Handle post_data;
554 char code, last_code;
555
556
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000557 UseResFile( res );
Just van Rossumae4bcee2000-07-28 01:10:35 +0000558
Werner Lemberge2455ba2004-02-26 21:56:27 +0000559 /* First pass: load all POST resources, and determine the size of */
560 /* the output buffer. */
Werner Lemberg9ca7a152002-04-30 14:26:49 +0000561 res_id = 501;
Just van Rossumae4bcee2000-07-28 01:10:35 +0000562 last_code = -1;
Werner Lemberg05c21b82000-07-29 20:38:19 +0000563
Just van Rossumae4bcee2000-07-28 01:10:35 +0000564 for (;;)
565 {
566 post_data = Get1Resource( 'POST', res_id++ );
567 if ( post_data == NULL )
Werner Lemberg435046b2006-01-11 10:57:42 +0000568 break; /* we are done */
Just van Rossumae4bcee2000-07-28 01:10:35 +0000569
570 code = (*post_data)[0];
571
572 if ( code != last_code )
573 {
574 if ( code == 5 )
575 total_size += 2; /* just the end code */
576 else
577 total_size += 6; /* code + 4 bytes chunk length */
578 }
579
580 total_size += GetHandleSize( post_data ) - 2;
581 last_code = code;
David Turner9ca78252006-05-02 09:00:29 +0000582
583 /* detect integer overflows */
584 if ( total_size < old_total_size )
585 {
586 error = FT_Err_Array_Too_Large;
587 goto Error;
588 }
589
590 old_total_size = total_size;
Just van Rossumae4bcee2000-07-28 01:10:35 +0000591 }
592
David Turnere459d742002-03-22 13:52:37 +0000593 if ( FT_ALLOC( buffer, (FT_Long)total_size ) )
Just van Rossumae4bcee2000-07-28 01:10:35 +0000594 goto Error;
595
Werner Lemberge2455ba2004-02-26 21:56:27 +0000596 /* Second pass: append all POST data to the buffer, add PFB fields. */
597 /* Glue all consecutive chunks of the same type together. */
Werner Lemberg9ca7a152002-04-30 14:26:49 +0000598 p = buffer;
599 res_id = 501;
600 last_code = -1;
Just van Rossumae4bcee2000-07-28 01:10:35 +0000601 pfb_chunk_size = 0;
602
603 for (;;)
604 {
605 post_data = Get1Resource( 'POST', res_id++ );
606 if ( post_data == NULL )
Werner Lemberg435046b2006-01-11 10:57:42 +0000607 break; /* we are done */
Just van Rossumae4bcee2000-07-28 01:10:35 +0000608
609 post_size = (FT_ULong)GetHandleSize( post_data ) - 2;
610 code = (*post_data)[0];
611
612 if ( code != last_code )
613 {
Just van Rossumae4bcee2000-07-28 01:10:35 +0000614 if ( last_code != -1 )
615 {
Werner Lemberg435046b2006-01-11 10:57:42 +0000616 /* we are done adding a chunk, fill in the size field */
Werner Lemberg9ca7a152002-04-30 14:26:49 +0000617 if ( size_p != NULL )
618 {
619 *size_p++ = (FT_Byte)( pfb_chunk_size & 0xFF );
620 *size_p++ = (FT_Byte)( ( pfb_chunk_size >> 8 ) & 0xFF );
621 *size_p++ = (FT_Byte)( ( pfb_chunk_size >> 16 ) & 0xFF );
622 *size_p++ = (FT_Byte)( ( pfb_chunk_size >> 24 ) & 0xFF );
623 }
Just van Rossumae4bcee2000-07-28 01:10:35 +0000624 pfb_chunk_size = 0;
625 }
626
627 *p++ = 0x80;
628 if ( code == 5 )
629 *p++ = 0x03; /* the end */
630 else if ( code == 2 )
631 *p++ = 0x02; /* binary segment */
632 else
633 *p++ = 0x01; /* ASCII segment */
634
635 if ( code != 5 )
636 {
637 size_p = p; /* save for later */
638 p += 4; /* make space for size field */
639 }
640 }
641
David Turnerd15bc0d2002-04-12 09:31:48 +0000642 ft_memcpy( p, *post_data + 2, post_size );
Just van Rossumae4bcee2000-07-28 01:10:35 +0000643 pfb_chunk_size += post_size;
644 p += post_size;
645 last_code = code;
646 }
647
648 *pfb_data = buffer;
649 *size = total_size;
650
Werner Lemberg05c21b82000-07-29 20:38:19 +0000651 Error:
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000652 CloseResFile( res );
Just van Rossumae4bcee2000-07-28 01:10:35 +0000653 return error;
654 }
655
656
657 /* Finalizer for a memory stream; gets called by FT_Done_Face().
658 It frees the memory it uses. */
Werner Lembergf814d0f2001-06-27 16:18:10 +0000659 static void
660 memory_stream_close( FT_Stream stream )
Just van Rossumae4bcee2000-07-28 01:10:35 +0000661 {
662 FT_Memory memory = stream->memory;
663
664
David Turnere459d742002-03-22 13:52:37 +0000665 FT_FREE( stream->base );
Werner Lemberg05c21b82000-07-29 20:38:19 +0000666
667 stream->size = 0;
668 stream->base = 0;
669 stream->close = 0;
Just van Rossumae4bcee2000-07-28 01:10:35 +0000670 }
671
672
673 /* Create a new memory stream from a buffer and a size. */
Werner Lembergf814d0f2001-06-27 16:18:10 +0000674 static FT_Error
Werner Lemberg9ca7a152002-04-30 14:26:49 +0000675 new_memory_stream( FT_Library library,
676 FT_Byte* base,
677 FT_ULong size,
678 FT_Stream_CloseFunc close,
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000679 FT_Stream* astream )
Just van Rossumae4bcee2000-07-28 01:10:35 +0000680 {
Werner Lemberg9ca7a152002-04-30 14:26:49 +0000681 FT_Error error;
682 FT_Memory memory;
683 FT_Stream stream;
Just van Rossumae4bcee2000-07-28 01:10:35 +0000684
685
Werner Lemberg9ca7a152002-04-30 14:26:49 +0000686 if ( !library )
687 return FT_Err_Invalid_Library_Handle;
Just van Rossumae4bcee2000-07-28 01:10:35 +0000688
Werner Lemberg9ca7a152002-04-30 14:26:49 +0000689 if ( !base )
690 return FT_Err_Invalid_Argument;
Just van Rossumae4bcee2000-07-28 01:10:35 +0000691
Werner Lemberg9ca7a152002-04-30 14:26:49 +0000692 *astream = 0;
693 memory = library->memory;
694 if ( FT_NEW( stream ) )
695 goto Exit;
Just van Rossumae4bcee2000-07-28 01:10:35 +0000696
Werner Lemberg9ca7a152002-04-30 14:26:49 +0000697 FT_Stream_OpenMemory( stream, base, size );
Just van Rossumae4bcee2000-07-28 01:10:35 +0000698
Werner Lemberg9ca7a152002-04-30 14:26:49 +0000699 stream->close = close;
Just van Rossumae4bcee2000-07-28 01:10:35 +0000700
Werner Lemberg9ca7a152002-04-30 14:26:49 +0000701 *astream = stream;
Just van Rossumae4bcee2000-07-28 01:10:35 +0000702
Werner Lemberg9ca7a152002-04-30 14:26:49 +0000703 Exit:
704 return error;
Just van Rossumae4bcee2000-07-28 01:10:35 +0000705 }
706
707
708 /* Create a new FT_Face given a buffer and a driver name. */
Werner Lembergf814d0f2001-06-27 16:18:10 +0000709 static FT_Error
710 open_face_from_buffer( FT_Library library,
711 FT_Byte* base,
712 FT_ULong size,
713 FT_Long face_index,
714 char* driver_name,
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000715 FT_Face* aface )
Just van Rossumae4bcee2000-07-28 01:10:35 +0000716 {
717 FT_Open_Args args;
718 FT_Error error;
719 FT_Stream stream;
720 FT_Memory memory = library->memory;
721
722
723 error = new_memory_stream( library,
724 base,
725 size,
726 memory_stream_close,
727 &stream );
728 if ( error )
729 {
David Turnere459d742002-03-22 13:52:37 +0000730 FT_FREE( base );
Just van Rossumae4bcee2000-07-28 01:10:35 +0000731 return error;
732 }
733
Werner Lemberg435046b2006-01-11 10:57:42 +0000734 args.flags = FT_OPEN_STREAM;
Just van Rossumae4bcee2000-07-28 01:10:35 +0000735 args.stream = stream;
736 if ( driver_name )
737 {
Werner Lemberg435046b2006-01-11 10:57:42 +0000738 args.flags = args.flags | FT_OPEN_DRIVER;
Just van Rossumae4bcee2000-07-28 01:10:35 +0000739 args.driver = FT_Get_Module( library, driver_name );
740 }
Werner Lemberg05c21b82000-07-29 20:38:19 +0000741
Werner Lemberg2630e542004-03-20 14:26:38 +0000742 /* At this point, face_index has served its purpose; */
743 /* whoever calls this function has already used it to */
744 /* locate the correct font data. We should not propagate */
745 /* this index to FT_Open_Face() (unless it is negative). */
746
747 if ( face_index > 0 )
748 face_index = 0;
749
Just van Rossumae4bcee2000-07-28 01:10:35 +0000750 error = FT_Open_Face( library, &args, face_index, aface );
Just van Rossum5fe94ff2000-07-28 02:25:23 +0000751 if ( error == FT_Err_Ok )
Just van Rossumae4bcee2000-07-28 01:10:35 +0000752 (*aface)->face_flags &= ~FT_FACE_FLAG_EXTERNAL_STREAM;
Suzuki, Toshiya (鈴木俊哉)47200602006-05-19 10:48:42 +0000753 else
754 FT_Stream_Free( stream, 0 );
Werner Lemberg9ca7a152002-04-30 14:26:49 +0000755
Just van Rossumae4bcee2000-07-28 01:10:35 +0000756 return error;
757 }
758
759
760 /* Create a new FT_Face from a file spec to an LWFN file. */
Werner Lembergf814d0f2001-06-27 16:18:10 +0000761 static FT_Error
Werner Lemberg435046b2006-01-11 10:57:42 +0000762 FT_New_Face_From_LWFN( FT_Library library,
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000763 const UInt8* pathname,
Werner Lemberg435046b2006-01-11 10:57:42 +0000764 FT_Long face_index,
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000765 FT_Face* aface )
Just van Rossumae4bcee2000-07-28 01:10:35 +0000766 {
Werner Lemberg9ca7a152002-04-30 14:26:49 +0000767 FT_Byte* pfb_data;
768 FT_ULong pfb_size;
769 FT_Error error;
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000770 short res;
Just van Rossumae4bcee2000-07-28 01:10:35 +0000771
772
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000773 if ( noErr != FT_FSPathMakeRes( pathname, &res ) )
774 return FT_Err_Cannot_Open_Resource;
Werner Lemberge2455ba2004-02-26 21:56:27 +0000775
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000776 pfb_data = NULL;
777 pfb_size = 0;
778 error = read_lwfn( library->memory, res, &pfb_data, &pfb_size );
779 CloseResFile( res ); /* PFB is already loaded, useless anymore */
Just van Rossumae4bcee2000-07-28 01:10:35 +0000780 if ( error )
781 return error;
782
Just van Rossumae4bcee2000-07-28 01:10:35 +0000783 return open_face_from_buffer( library,
784 pfb_data,
785 pfb_size,
786 face_index,
787 "type1",
788 aface );
789 }
790
791
792 /* Create a new FT_Face from an SFNT resource, specified by res ID. */
Werner Lembergf814d0f2001-06-27 16:18:10 +0000793 static FT_Error
794 FT_New_Face_From_SFNT( FT_Library library,
795 short sfnt_id,
796 FT_Long face_index,
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000797 FT_Face* aface )
Just van Rossumae4bcee2000-07-28 01:10:35 +0000798 {
Werner Lemberg05c21b82000-07-29 20:38:19 +0000799 Handle sfnt = NULL;
800 FT_Byte* sfnt_data;
801 size_t sfnt_size;
Werner Lemberg435046b2006-01-11 10:57:42 +0000802 FT_Error error = FT_Err_Ok;
Werner Lemberg05c21b82000-07-29 20:38:19 +0000803 FT_Memory memory = library->memory;
Werner Lembergc70818a2003-05-15 06:44:09 +0000804 int is_cff;
Just van Rossumae4bcee2000-07-28 01:10:35 +0000805
806
807 sfnt = GetResource( 'sfnt', sfnt_id );
808 if ( ResError() )
809 return FT_Err_Invalid_Handle;
810
811 sfnt_size = (FT_ULong)GetHandleSize( sfnt );
David Turnere459d742002-03-22 13:52:37 +0000812 if ( FT_ALLOC( sfnt_data, (FT_Long)sfnt_size ) )
Just van Rossumae4bcee2000-07-28 01:10:35 +0000813 {
814 ReleaseResource( sfnt );
815 return error;
816 }
817
David Turnerd15bc0d2002-04-12 09:31:48 +0000818 ft_memcpy( sfnt_data, *sfnt, sfnt_size );
Just van Rossumae4bcee2000-07-28 01:10:35 +0000819 ReleaseResource( sfnt );
820
Werner Lemberg756655b2003-06-07 05:13:22 +0000821 is_cff = sfnt_size > 4 && sfnt_data[0] == 'O' &&
822 sfnt_data[1] == 'T' &&
823 sfnt_data[2] == 'T' &&
824 sfnt_data[3] == 'O';
Werner Lembergc70818a2003-05-15 06:44:09 +0000825
Just van Rossumae4bcee2000-07-28 01:10:35 +0000826 return open_face_from_buffer( library,
827 sfnt_data,
828 sfnt_size,
829 face_index,
Werner Lembergc70818a2003-05-15 06:44:09 +0000830 is_cff ? "cff" : "truetype",
Just van Rossumae4bcee2000-07-28 01:10:35 +0000831 aface );
832 }
833
834
835 /* Create a new FT_Face from a file spec to a suitcase file. */
Werner Lembergf814d0f2001-06-27 16:18:10 +0000836 static FT_Error
Werner Lemberg435046b2006-01-11 10:57:42 +0000837 FT_New_Face_From_Suitcase( FT_Library library,
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000838 const UInt8* pathname,
Werner Lemberg435046b2006-01-11 10:57:42 +0000839 FT_Long face_index,
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000840 FT_Face* aface )
Just van Rossumae4bcee2000-07-28 01:10:35 +0000841 {
Suzuki, Toshiya (鈴木俊哉)53be6e92005-12-23 12:22:46 +0000842 FT_Error error = FT_Err_Cannot_Open_Resource;
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000843 short res_ref, res_index;
Just van Rossumae4bcee2000-07-28 01:10:35 +0000844 Handle fond;
Suzuki, Toshiya (鈴木俊哉)53be6e92005-12-23 12:22:46 +0000845 short num_faces_in_res, num_faces_in_fond;
Just van Rossumae4bcee2000-07-28 01:10:35 +0000846
847
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000848 if ( noErr != FT_FSPathMakeRes( pathname, &res_ref ) )
849 return FT_Err_Cannot_Open_Resource;
850
Just van Rossumae4bcee2000-07-28 01:10:35 +0000851 UseResFile( res_ref );
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000852 if ( ResError() )
853 return FT_Err_Cannot_Open_Resource;
Just van Rossumae4bcee2000-07-28 01:10:35 +0000854
Suzuki, Toshiya (鈴木俊哉)53be6e92005-12-23 12:22:46 +0000855 num_faces_in_res = 0;
Werner Lemberge2455ba2004-02-26 21:56:27 +0000856 for ( res_index = 1; ; ++res_index )
Just van Rossumae4bcee2000-07-28 01:10:35 +0000857 {
Werner Lemberge2455ba2004-02-26 21:56:27 +0000858 fond = Get1IndResource( 'FOND', res_index );
859 if ( ResError() )
Werner Lemberge2455ba2004-02-26 21:56:27 +0000860 break;
861
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000862 num_faces_in_fond = count_faces( fond, pathname );
Suzuki, Toshiya (鈴木俊哉)53be6e92005-12-23 12:22:46 +0000863 num_faces_in_res += num_faces_in_fond;
Werner Lemberge2455ba2004-02-26 21:56:27 +0000864
Suzuki, Toshiya (鈴木俊哉)53be6e92005-12-23 12:22:46 +0000865 if ( 0 <= face_index && face_index < num_faces_in_fond && error )
866 error = FT_New_Face_From_FOND( library, fond, face_index, aface );
Werner Lemberg435046b2006-01-11 10:57:42 +0000867
Suzuki, Toshiya (鈴木俊哉)53be6e92005-12-23 12:22:46 +0000868 face_index -= num_faces_in_fond;
Just van Rossumae4bcee2000-07-28 01:10:35 +0000869 }
870
Just van Rossumae4bcee2000-07-28 01:10:35 +0000871 CloseResFile( res_ref );
Suzuki, Toshiya (鈴木俊哉)53be6e92005-12-23 12:22:46 +0000872 if ( FT_Err_Ok == error && NULL != aface )
873 (*aface)->num_faces = num_faces_in_res;
Just van Rossumae4bcee2000-07-28 01:10:35 +0000874 return error;
875 }
876
Werner Lemberge9e130c2001-12-07 21:56:32 +0000877
Werner Lemberg9ca7a152002-04-30 14:26:49 +0000878 /* documentation is in ftmac.h */
Werner Lemberg90a03302000-11-07 17:21:11 +0000879
Werner Lembergf814d0f2001-06-27 16:18:10 +0000880 FT_EXPORT_DEF( FT_Error )
881 FT_New_Face_From_FOND( FT_Library library,
882 Handle fond,
883 FT_Long face_index,
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000884 FT_Face* aface )
Just van Rossumae4bcee2000-07-28 01:10:35 +0000885 {
Werner Lemberg435046b2006-01-11 10:57:42 +0000886 short sfnt_id, have_sfnt, have_lwfn = 0;
887 short fond_id;
888 OSType fond_type;
889 Str255 fond_name;
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000890 Str255 lwfn_file_name;
891 UInt8 path_lwfn[HFS_MAXPATHLEN];
892 OSErr err;
Suzuki, Toshiya (鈴木俊哉)07088262006-10-15 07:15:28 +0000893 FT_Error error = FT_Err_Ok;
Just van Rossumae4bcee2000-07-28 01:10:35 +0000894
895
Werner Lembergc3b21602001-12-05 01:22:05 +0000896 GetResInfo( fond, &fond_id, &fond_type, fond_name );
Just van Rossumae4bcee2000-07-28 01:10:35 +0000897 if ( ResError() != noErr || fond_type != 'FOND' )
898 return FT_Err_Invalid_File_Format;
899
Leonard Rosentholae340bb2001-10-26 13:24:39 +0000900 parse_fond( *fond, &have_sfnt, &sfnt_id, lwfn_file_name, face_index );
Just van Rossumae4bcee2000-07-28 01:10:35 +0000901
902 if ( lwfn_file_name[0] )
903 {
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000904 short res;
905
906
907 res = HomeResFile( fond );
908 if ( noErr != ResError() )
909 goto found_no_lwfn_file;
910
Werner Lemberg435046b2006-01-11 10:57:42 +0000911 {
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000912 UInt8 path_fond[HFS_MAXPATHLEN];
913 FSRef ref;
914
Werner Lemberg435046b2006-01-11 10:57:42 +0000915
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000916 err = FSGetForkCBInfo( res, kFSInvalidVolumeRefNum,
917 NULL, NULL, NULL, &ref, NULL );
918 if ( noErr != err )
919 goto found_no_lwfn_file;
920
Werner Lemberg435046b2006-01-11 10:57:42 +0000921 err = FSRefMakePath( &ref, path_fond, sizeof ( path_fond ) );
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000922 if ( noErr != err )
923 goto found_no_lwfn_file;
924
925 error = lookup_lwfn_by_fond( path_fond, lwfn_file_name,
Werner Lemberg435046b2006-01-11 10:57:42 +0000926 path_lwfn, sizeof ( path_lwfn ) );
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000927 if ( FT_Err_Ok == error )
928 have_lwfn = 1;
929 }
Werner Lemberg435046b2006-01-11 10:57:42 +0000930 }
Just van Rossumae4bcee2000-07-28 01:10:35 +0000931
932 if ( have_lwfn && ( !have_sfnt || PREFER_LWFN ) )
Werner Lemberg745ff2c2006-09-19 05:48:02 +0000933 error = FT_New_Face_From_LWFN( library,
934 path_lwfn,
935 face_index,
936 aface );
937 else
938 error = FT_Err_Unknown_File_Format;
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000939
Werner Lemberg435046b2006-01-11 10:57:42 +0000940 found_no_lwfn_file:
Werner Lemberg745ff2c2006-09-19 05:48:02 +0000941 if ( have_sfnt && FT_Err_Ok != error )
942 error = FT_New_Face_From_SFNT( library,
943 sfnt_id,
944 face_index,
945 aface );
Just van Rossumae4bcee2000-07-28 01:10:35 +0000946
Werner Lemberg745ff2c2006-09-19 05:48:02 +0000947 return error;
Werner Lemberge9e130c2001-12-07 21:56:32 +0000948 }
949
Werner Lembergca7ef5e2004-02-28 19:12:01 +0000950
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000951 /* Common function to load a new FT_Face from a resource file. */
Werner Lembergca7ef5e2004-02-28 19:12:01 +0000952 static FT_Error
Werner Lemberg435046b2006-01-11 10:57:42 +0000953 FT_New_Face_From_Resource( FT_Library library,
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000954 const UInt8* pathname,
Werner Lemberg435046b2006-01-11 10:57:42 +0000955 FT_Long face_index,
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000956 FT_Face* aface )
Werner Lembergca7ef5e2004-02-28 19:12:01 +0000957 {
958 OSType file_type;
Werner Lembergca7ef5e2004-02-28 19:12:01 +0000959 FT_Error error;
960
961
Werner Lemberg435046b2006-01-11 10:57:42 +0000962 /* LWFN is a (very) specific file format, check for it explicitly */
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000963 file_type = get_file_type_from_path( pathname );
Werner Lemberg435046b2006-01-11 10:57:42 +0000964 if ( file_type == 'LWFN' )
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000965 return FT_New_Face_From_LWFN( library, pathname, face_index, aface );
Werner Lemberg435046b2006-01-11 10:57:42 +0000966
967 /* Otherwise the file type doesn't matter (there are more than */
968 /* `FFIL' and `tfil'). Just try opening it as a font suitcase; */
969 /* if it works, fine. */
Werner Lembergca7ef5e2004-02-28 19:12:01 +0000970
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000971 error = FT_New_Face_From_Suitcase( library, pathname, face_index, aface );
Werner Lemberg435046b2006-01-11 10:57:42 +0000972 if ( error == 0 )
973 return error;
Werner Lembergca7ef5e2004-02-28 19:12:01 +0000974
Werner Lembergca7ef5e2004-02-28 19:12:01 +0000975 /* let it fall through to normal loader (.ttf, .otf, etc.); */
976 /* we signal this by returning no error and no FT_Face */
977 *aface = NULL;
978 return 0;
979 }
980
Just van Rossumae4bcee2000-07-28 01:10:35 +0000981
982 /*************************************************************************/
983 /* */
984 /* <Function> */
985 /* FT_New_Face */
986 /* */
987 /* <Description> */
988 /* This is the Mac-specific implementation of FT_New_Face. In */
Werner Lemberg05c21b82000-07-29 20:38:19 +0000989 /* addition to the standard FT_New_Face() functionality, it also */
Just van Rossumae4bcee2000-07-28 01:10:35 +0000990 /* accepts pathnames to Mac suitcase files. For further */
Werner Lemberg90a03302000-11-07 17:21:11 +0000991 /* documentation see the original FT_New_Face() in freetype.h. */
Just van Rossumae4bcee2000-07-28 01:10:35 +0000992 /* */
Werner Lembergf814d0f2001-06-27 16:18:10 +0000993 FT_EXPORT_DEF( FT_Error )
994 FT_New_Face( FT_Library library,
995 const char* pathname,
996 FT_Long face_index,
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000997 FT_Face* aface )
Just van Rossumae4bcee2000-07-28 01:10:35 +0000998 {
999 FT_Open_Args args;
Werner Lembergca7ef5e2004-02-28 19:12:01 +00001000 FT_Error error;
Just van Rossumae4bcee2000-07-28 01:10:35 +00001001
1002
1003 /* test for valid `library' and `aface' delayed to FT_Open_Face() */
1004 if ( !pathname )
1005 return FT_Err_Invalid_Argument;
1006
Werner Lemberg435046b2006-01-11 10:57:42 +00001007 error = FT_Err_Ok;
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +00001008 *aface = NULL;
Just van Rossumae4bcee2000-07-28 01:10:35 +00001009
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +00001010 /* try resourcefork based font: LWFN, FFIL */
Werner Lemberg435046b2006-01-11 10:57:42 +00001011 error = FT_New_Face_From_Resource( library, (UInt8 *)pathname,
1012 face_index, aface );
Werner Lembergca7ef5e2004-02-28 19:12:01 +00001013 if ( error != 0 || *aface != NULL )
1014 return error;
Werner Lemberg9ca7a152002-04-30 14:26:49 +00001015
Werner Lemberg9ca7a152002-04-30 14:26:49 +00001016 /* let it fall through to normal loader (.ttf, .otf, etc.) */
David Turnerb08fe2d2002-08-27 20:20:29 +00001017 args.flags = FT_OPEN_PATHNAME;
Werner Lemberg9ca7a152002-04-30 14:26:49 +00001018 args.pathname = (char*)pathname;
1019 return FT_Open_Face( library, &args, face_index, aface );
Just van Rossumae4bcee2000-07-28 01:10:35 +00001020 }
1021
Werner Lemberg05c21b82000-07-29 20:38:19 +00001022
Werner Lemberge2455ba2004-02-26 21:56:27 +00001023 /*************************************************************************/
1024 /* */
1025 /* <Function> */
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +00001026 /* FT_New_Face_From_FSRef */
1027 /* */
1028 /* <Description> */
1029 /* FT_New_Face_From_FSRef is identical to FT_New_Face except it */
1030 /* accepts an FSRef instead of a path. */
1031 /* */
1032 FT_EXPORT_DEF( FT_Error )
1033 FT_New_Face_From_FSRef( FT_Library library,
1034 const FSRef* ref,
Werner Lemberg435046b2006-01-11 10:57:42 +00001035 FT_Long face_index,
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +00001036 FT_Face* aface )
1037 {
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +00001038 FT_Error error;
1039 FT_Open_Args args;
1040 OSErr err;
1041 UInt8 pathname[HFS_MAXPATHLEN];
1042
1043
1044 if ( !ref )
1045 return FT_Err_Invalid_Argument;
1046
1047 err = FSRefMakePath( ref, pathname, sizeof ( pathname ) );
1048 if ( err )
1049 error = FT_Err_Cannot_Open_Resource;
1050
1051 error = FT_New_Face_From_Resource( library, pathname, face_index, aface );
1052 if ( error != 0 || *aface != NULL )
1053 return error;
1054
1055 /* fallback to datafork font */
1056 args.flags = FT_OPEN_PATHNAME;
1057 args.pathname = (char*)pathname;
1058 return FT_Open_Face( library, &args, face_index, aface );
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +00001059 }
1060
1061
1062 /*************************************************************************/
1063 /* */
1064 /* <Function> */
Werner Lemberge2455ba2004-02-26 21:56:27 +00001065 /* FT_New_Face_From_FSSpec */
1066 /* */
1067 /* <Description> */
1068 /* FT_New_Face_From_FSSpec is identical to FT_New_Face except it */
1069 /* accepts an FSSpec instead of a path. */
1070 /* */
1071 FT_EXPORT_DEF( FT_Error )
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +00001072 FT_New_Face_From_FSSpec( FT_Library library,
1073 const FSSpec* spec,
1074 FT_Long face_index,
1075 FT_Face* aface )
Werner Lemberg435046b2006-01-11 10:57:42 +00001076 {
Suzuki, Toshiya (鈴木俊哉)78935012007-06-19 03:27:05 +00001077#if __LP64__
1078 FT_UNUSED( library );
1079 FT_UNUSED( spec );
1080 FT_UNUSED( face_index );
1081 FT_UNUSED( aface );
1082
1083 return FT_Err_Unimplemented_Feature;
1084#else
Werner Lemberg435046b2006-01-11 10:57:42 +00001085 FSRef ref;
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +00001086
1087
1088 if ( !spec || FSpMakeFSRef( spec, &ref ) != noErr )
1089 return FT_Err_Invalid_Argument;
1090 else
1091 return FT_New_Face_From_FSRef( library, &ref, face_index, aface );
Suzuki, Toshiya (鈴木俊哉)78935012007-06-19 03:27:05 +00001092#endif
Werner Lemberge2455ba2004-02-26 21:56:27 +00001093 }
1094
1095
Werner Lemberg05c21b82000-07-29 20:38:19 +00001096/* END */