blob: 1347d7dbb30a5d7c6af77024c14b816cd9bde401 [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 {
108 return FT_Err_Unimplemented_Feature;
109 }
Werner Lemberg435046b2006-01-11 10:57:42 +0000110
Werner Lemberg435046b2006-01-11 10:57:42 +0000111
Suzuki, Toshiya (鈴木俊哉)4827e9b2007-02-05 03:28:29 +0000112 /* Private function. */
113 /* The FSSpec type has been discouraged for a long time, */
114 /* but for some reason, there is no FSRef version of */
115 /* ATSFontGetFileSpecification(), so we made our own. */
116 /* Apple will provide one eventually. */
117 static OSStatus
118 FT_ATSFontGetFileReference( ATSFontRef ats_font_id,
119 FSRef* ats_font_ref )
120 {
Werner Lembergdcbb7082007-02-08 08:54:09 +0000121 OSStatus err;
122 FSSpec spec;
123
Suzuki, Toshiya (鈴木俊哉)4827e9b2007-02-05 03:28:29 +0000124
125 err = ATSFontGetFileSpecification( ats_font_id, &spec );
126 if ( noErr == err )
Suzuki, Toshiya (鈴木俊哉)4827e9b2007-02-05 03:28:29 +0000127 err = FSpMakeFSRef( &spec, ats_font_ref );
Suzuki, Toshiya (鈴木俊哉)4827e9b2007-02-05 03:28:29 +0000128
129 return err;
130 }
131
132
133 static FT_Error
134 FT_GetFileRef_From_Mac_ATS_Name( const char* fontName,
135 FSRef* ats_font_ref,
136 FT_Long* face_index )
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000137 {
138 CFStringRef cf_fontName;
139 ATSFontRef ats_font_id;
Werner Lemberg435046b2006-01-11 10:57:42 +0000140
141
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000142 *face_index = 0;
Werner Lemberg435046b2006-01-11 10:57:42 +0000143
144 cf_fontName = CFStringCreateWithCString( NULL, fontName,
145 kCFStringEncodingMacRoman );
146 ats_font_id = ATSFontFindFromName( cf_fontName,
147 kATSOptionFlagsUnRestrictedScope );
148
149 if ( ats_font_id == 0 || ats_font_id == 0xFFFFFFFFUL )
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000150 return FT_Err_Unknown_File_Format;
Werner Lemberg435046b2006-01-11 10:57:42 +0000151
Suzuki, Toshiya (鈴木俊哉)4827e9b2007-02-05 03:28:29 +0000152 if ( noErr != FT_ATSFontGetFileReference( ats_font_id, ats_font_ref ) )
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000153 return FT_Err_Unknown_File_Format;
Werner Lemberg435046b2006-01-11 10:57:42 +0000154
155 /* face_index calculation by searching preceding fontIDs */
156 /* with same FSRef */
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000157 {
Suzuki, Toshiya (鈴木俊哉)4827e9b2007-02-05 03:28:29 +0000158 ATSFontRef id2 = ats_font_id - 1;
159 FSRef ref2;
Werner Lemberg435046b2006-01-11 10:57:42 +0000160
161
Suzuki, Toshiya (鈴木俊哉)4827e9b2007-02-05 03:28:29 +0000162 while ( id2 > 0 )
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000163 {
Suzuki, Toshiya (鈴木俊哉)4827e9b2007-02-05 03:28:29 +0000164 if ( noErr != FT_ATSFontGetFileReference( id2, &ref2 ) )
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000165 break;
Suzuki, Toshiya (鈴木俊哉)4827e9b2007-02-05 03:28:29 +0000166 if ( noErr != FSCompareFSRefs( ats_font_ref, &ref2 ) )
167 break;
168
169 id2 --;
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000170 }
Suzuki, Toshiya (鈴木俊哉)4827e9b2007-02-05 03:28:29 +0000171 *face_index = ats_font_id - ( id2 + 1 );
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000172 }
Suzuki, Toshiya (鈴木俊哉)4827e9b2007-02-05 03:28:29 +0000173
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000174 return FT_Err_Ok;
175 }
Werner Lemberg435046b2006-01-11 10:57:42 +0000176
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000177
Suzuki, Toshiya (鈴木俊哉)4827e9b2007-02-05 03:28:29 +0000178 FT_EXPORT_DEF( FT_Error )
179 FT_GetFilePath_From_Mac_ATS_Name( const char* fontName,
180 UInt8* path,
181 UInt32 maxPathSize,
182 FT_Long* face_index )
183 {
184 FSRef ref;
185 FT_Error err;
186
187
188 err = FT_GetFileRef_From_Mac_ATS_Name( fontName, &ref, face_index );
189 if ( FT_Err_Ok != err )
190 return err;
191
192 if ( noErr != FSRefMakePath( &ref, path, maxPathSize ) )
193 return FT_Err_Unknown_File_Format;
194
195 return FT_Err_Ok;
196 }
197
198
199 /* This function is deprecated because FSSpec is deprecated in Mac OS X */
200 FT_EXPORT_DEF( FT_Error )
201 FT_GetFile_From_Mac_ATS_Name( const char* fontName,
202 FSSpec* pathSpec,
203 FT_Long* face_index )
204 {
205#if __LP64__
Werner Lembergdcbb7082007-02-08 08:54:09 +0000206
Suzuki, Toshiya (鈴木俊哉)4827e9b2007-02-05 03:28:29 +0000207 return FT_Err_Unimplemented_Feature;
Werner Lembergdcbb7082007-02-08 08:54:09 +0000208
Suzuki, Toshiya (鈴木俊哉)4827e9b2007-02-05 03:28:29 +0000209#else
Werner Lembergdcbb7082007-02-08 08:54:09 +0000210
Suzuki, Toshiya (鈴木俊哉)4827e9b2007-02-05 03:28:29 +0000211 FSRef ref;
212 FT_Error err;
213
Werner Lembergdcbb7082007-02-08 08:54:09 +0000214
Suzuki, Toshiya (鈴木俊哉)4827e9b2007-02-05 03:28:29 +0000215 err = FT_GetFileRef_From_Mac_ATS_Name( fontName, &ref, face_index );
216 if ( FT_Err_Ok != err )
217 return err;
218
219 if ( noErr != FSGetCatalogInfo( &ref, kFSCatInfoNone, NULL, NULL,
220 pathSpec, NULL ) )
221 return FT_Err_Unknown_File_Format;
222
223 return FT_Err_Ok;
Werner Lembergdcbb7082007-02-08 08:54:09 +0000224
Suzuki, Toshiya (鈴木俊哉)4827e9b2007-02-05 03:28:29 +0000225#endif
226 }
227
228
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000229 static OSErr
230 FT_FSPathMakeRes( const UInt8* pathname,
231 short* res )
232 {
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000233 OSErr err;
234 FSRef ref;
235
Werner Lemberg435046b2006-01-11 10:57:42 +0000236
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000237 if ( noErr != FSPathMakeRef( pathname, &ref, FALSE ) )
238 return FT_Err_Cannot_Open_Resource;
239
Werner Lemberg435046b2006-01-11 10:57:42 +0000240 /* at present, no support for dfont format */
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000241 err = FSOpenResourceFile( &ref, 0, NULL, fsRdPerm, res );
242 if ( noErr == err )
243 return err;
244
245 /* fallback to original resource-fork font */
246 *res = FSOpenResFile( &ref, fsRdPerm );
247 err = ResError();
Werner Lemberg435046b2006-01-11 10:57:42 +0000248
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000249 return err;
250 }
251
252
253 /* Return the file type for given pathname */
254 static OSType
255 get_file_type_from_path( const UInt8* pathname )
256 {
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000257 FSRef ref;
258 FSCatalogInfo info;
259
260
261 if ( noErr != FSPathMakeRef( pathname, &ref, FALSE ) )
262 return ( OSType ) 0;
263
264 if ( noErr != FSGetCatalogInfo( &ref, kFSCatInfoFinderInfo, &info,
265 NULL, NULL, NULL ) )
266 return ( OSType ) 0;
267
Werner Lemberg435046b2006-01-11 10:57:42 +0000268 return ((FInfo *)(info.finderInfo))->fdType;
Just van Rossumae4bcee2000-07-28 01:10:35 +0000269 }
270
Werner Lemberge9e130c2001-12-07 21:56:32 +0000271
Just van Rossumae4bcee2000-07-28 01:10:35 +0000272 /* Given a PostScript font name, create the Macintosh LWFN file name. */
Werner Lembergf814d0f2001-06-27 16:18:10 +0000273 static void
274 create_lwfn_name( char* ps_name,
275 Str255 lwfn_file_name )
Just van Rossumae4bcee2000-07-28 01:10:35 +0000276 {
277 int max = 5, count = 0;
278 FT_Byte* p = lwfn_file_name;
279 FT_Byte* q = (FT_Byte*)ps_name;
280
281
282 lwfn_file_name[0] = 0;
283
284 while ( *q )
285 {
Werner Lemberg282637f2003-05-21 07:39:42 +0000286 if ( ft_isupper( *q ) )
Just van Rossumae4bcee2000-07-28 01:10:35 +0000287 {
288 if ( count )
289 max = 3;
290 count = 0;
291 }
David Turnerd15bc0d2002-04-12 09:31:48 +0000292 if ( count < max && ( ft_isalnum( *q ) || *q == '_' ) )
Just van Rossumae4bcee2000-07-28 01:10:35 +0000293 {
294 *++p = *q;
295 lwfn_file_name[0]++;
296 count++;
297 }
298 q++;
299 }
300 }
301
302
Werner Lemberge2455ba2004-02-26 21:56:27 +0000303 static short
Werner Lemberg083ba0b2005-12-23 15:10:54 +0000304 count_faces_sfnt( char* fond_data )
Werner Lemberge2455ba2004-02-26 21:56:27 +0000305 {
306 /* The count is 1 greater than the value in the FOND. */
307 /* Isn't that cute? :-) */
308
Werner Lembergef3d2c22006-06-25 06:07:14 +0000309 return EndianS16_BtoN( *( (short*)( fond_data +
310 sizeof ( FamRec ) ) ) ) + 1;
Werner Lemberge2455ba2004-02-26 21:56:27 +0000311 }
312
313
Suzuki, Toshiya (鈴木俊哉)53be6e92005-12-23 12:22:46 +0000314 static short
Werner Lemberg083ba0b2005-12-23 15:10:54 +0000315 count_faces_scalable( char* fond_data )
Suzuki, Toshiya (鈴木俊哉)53be6e92005-12-23 12:22:46 +0000316 {
317 AsscEntry* assoc;
318 FamRec* fond;
319 short i, face, face_all;
320
321
Werner Lemberg435046b2006-01-11 10:57:42 +0000322 fond = (FamRec*)fond_data;
Werner Lembergef3d2c22006-06-25 06:07:14 +0000323 face_all = EndianS16_BtoN( *( (short *)( fond_data +
324 sizeof ( FamRec ) ) ) ) + 1;
Werner Lemberg435046b2006-01-11 10:57:42 +0000325 assoc = (AsscEntry*)( fond_data + sizeof ( FamRec ) + 2 );
326 face = 0;
Suzuki, Toshiya (鈴木俊哉)53be6e92005-12-23 12:22:46 +0000327
328 for ( i = 0; i < face_all; i++ )
329 {
Suzuki, Toshiya (鈴木俊哉)52311972006-06-22 02:34:27 +0000330 if ( 0 == EndianS16_BtoN( assoc[i].fontSize ) )
Werner Lemberg083ba0b2005-12-23 15:10:54 +0000331 face++;
Suzuki, Toshiya (鈴木俊哉)53be6e92005-12-23 12:22:46 +0000332 }
333 return face;
334 }
335
336
Just van Rossumae4bcee2000-07-28 01:10:35 +0000337 /* Look inside the FOND data, answer whether there should be an SFNT
Werner Lemberge9e130c2001-12-07 21:56:32 +0000338 resource, and answer the name of a possible LWFN Type 1 file.
339
340 Thanks to Paul Miller (paulm@profoundeffects.com) for the fix
Leonard Rosentholae340bb2001-10-26 13:24:39 +0000341 to load a face OTHER than the first one in the FOND!
342 */
Werner Lemberge2455ba2004-02-26 21:56:27 +0000343
344
Werner Lembergf814d0f2001-06-27 16:18:10 +0000345 static void
346 parse_fond( char* fond_data,
347 short* have_sfnt,
348 short* sfnt_id,
Leonard Rosentholae340bb2001-10-26 13:24:39 +0000349 Str255 lwfn_file_name,
350 short face_index )
Just van Rossumae4bcee2000-07-28 01:10:35 +0000351 {
352 AsscEntry* assoc;
Leonard Rosentholae340bb2001-10-26 13:24:39 +0000353 AsscEntry* base_assoc;
Just van Rossumae4bcee2000-07-28 01:10:35 +0000354 FamRec* fond;
355
356
357 *sfnt_id = 0;
358 *have_sfnt = 0;
359 lwfn_file_name[0] = 0;
360
Werner Lembergc3b21602001-12-05 01:22:05 +0000361 fond = (FamRec*)fond_data;
362 assoc = (AsscEntry*)( fond_data + sizeof ( FamRec ) + 2 );
Leonard Rosentholae340bb2001-10-26 13:24:39 +0000363 base_assoc = assoc;
Just van Rossumae4bcee2000-07-28 01:10:35 +0000364
Werner Lemberge2455ba2004-02-26 21:56:27 +0000365 /* Let's do a little range checking before we get too excited here */
366 if ( face_index < count_faces_sfnt( fond_data ) )
Just van Rossumae4bcee2000-07-28 01:10:35 +0000367 {
Werner Lemberge2455ba2004-02-26 21:56:27 +0000368 assoc += face_index; /* add on the face_index! */
369
370 /* if the face at this index is not scalable,
371 fall back to the first one (old behavior) */
Suzuki, Toshiya (鈴木俊哉)52311972006-06-22 02:34:27 +0000372 if ( EndianS16_BtoN( assoc->fontSize ) == 0 )
Werner Lemberge2455ba2004-02-26 21:56:27 +0000373 {
374 *have_sfnt = 1;
Suzuki, Toshiya (鈴木俊哉)52311972006-06-22 02:34:27 +0000375 *sfnt_id = EndianS16_BtoN( assoc->fontID );
Werner Lemberge2455ba2004-02-26 21:56:27 +0000376 }
377 else if ( base_assoc->fontSize == 0 )
378 {
379 *have_sfnt = 1;
Suzuki, Toshiya (鈴木俊哉)52311972006-06-22 02:34:27 +0000380 *sfnt_id = EndianS16_BtoN( base_assoc->fontID );
Werner Lemberge2455ba2004-02-26 21:56:27 +0000381 }
Leonard Rosentholae340bb2001-10-26 13:24:39 +0000382 }
Just van Rossumae4bcee2000-07-28 01:10:35 +0000383
Suzuki, Toshiya (鈴木俊哉)52311972006-06-22 02:34:27 +0000384 if ( EndianS32_BtoN( fond->ffStylOff ) )
Just van Rossumae4bcee2000-07-28 01:10:35 +0000385 {
386 unsigned char* p = (unsigned char*)fond_data;
387 StyleTable* style;
388 unsigned short string_count;
Just van Rossumae4bcee2000-07-28 01:10:35 +0000389 char ps_name[256];
390 unsigned char* names[64];
391 int i;
392
Werner Lemberg05c21b82000-07-29 20:38:19 +0000393
Suzuki, Toshiya (鈴木俊哉)52311972006-06-22 02:34:27 +0000394 p += EndianS32_BtoN( fond->ffStylOff );
Just van Rossumae4bcee2000-07-28 01:10:35 +0000395 style = (StyleTable*)p;
Werner Lemberg05c21b82000-07-29 20:38:19 +0000396 p += sizeof ( StyleTable );
Suzuki, Toshiya (鈴木俊哉)52311972006-06-22 02:34:27 +0000397 string_count = EndianS16_BtoN( *(short*)(p) );
Werner Lemberg05c21b82000-07-29 20:38:19 +0000398 p += sizeof ( short );
Just van Rossumae4bcee2000-07-28 01:10:35 +0000399
Werner Lemberg435046b2006-01-11 10:57:42 +0000400 for ( i = 0; i < string_count && i < 64; i++ )
Just van Rossumae4bcee2000-07-28 01:10:35 +0000401 {
402 names[i] = p;
Werner Lemberg435046b2006-01-11 10:57:42 +0000403 p += names[i][0];
Just van Rossumae4bcee2000-07-28 01:10:35 +0000404 p++;
405 }
Just van Rossumae4bcee2000-07-28 01:10:35 +0000406
Just van Rossumae4bcee2000-07-28 01:10:35 +0000407 {
Werner Lemberg9ca7a152002-04-30 14:26:49 +0000408 size_t ps_name_len = (size_t)names[0][0];
Werner Lemberg05c21b82000-07-29 20:38:19 +0000409
410
Werner Lemberg9ca7a152002-04-30 14:26:49 +0000411 if ( ps_name_len != 0 )
412 {
Werner Lemberg282637f2003-05-21 07:39:42 +0000413 ft_memcpy(ps_name, names[0] + 1, ps_name_len);
Werner Lemberg9ca7a152002-04-30 14:26:49 +0000414 ps_name[ps_name_len] = 0;
415 }
416 if ( style->indexes[0] > 1 )
417 {
418 unsigned char* suffixes = names[style->indexes[0] - 1];
419
420
Werner Lembergfcc5c912003-04-23 18:10:19 +0000421 for ( i = 1; i <= suffixes[0]; i++ )
Werner Lemberg9ca7a152002-04-30 14:26:49 +0000422 {
423 unsigned char* s;
424 size_t j = suffixes[i] - 1;
425
426
427 if ( j < string_count && ( s = names[j] ) != NULL )
428 {
429 size_t s_len = (size_t)s[0];
430
431
432 if ( s_len != 0 && ps_name_len + s_len < sizeof ( ps_name ) )
433 {
Werner Lemberg282637f2003-05-21 07:39:42 +0000434 ft_memcpy( ps_name + ps_name_len, s + 1, s_len );
Werner Lemberg9ca7a152002-04-30 14:26:49 +0000435 ps_name_len += s_len;
436 ps_name[ps_name_len] = 0;
437 }
438 }
439 }
440 }
Just van Rossumae4bcee2000-07-28 01:10:35 +0000441 }
Werner Lemberg9ca7a152002-04-30 14:26:49 +0000442
Just van Rossumae4bcee2000-07-28 01:10:35 +0000443 create_lwfn_name( ps_name, lwfn_file_name );
444 }
445 }
446
447
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000448 static FT_Error
449 lookup_lwfn_by_fond( const UInt8* path_fond,
450 const StringPtr base_lwfn,
Werner Lemberg435046b2006-01-11 10:57:42 +0000451 UInt8* path_lwfn,
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000452 int path_size )
Werner Lemberge2455ba2004-02-26 21:56:27 +0000453 {
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000454 FSRef ref, par_ref;
455 int dirname_len;
Werner Lemberge2455ba2004-02-26 21:56:27 +0000456
457
Werner Lemberg435046b2006-01-11 10:57:42 +0000458 /* Pathname for FSRef can be in various formats: HFS, HFS+, and POSIX. */
459 /* We should not extract parent directory by string manipulation. */
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000460
461 if ( noErr != FSPathMakeRef( path_fond, &ref, FALSE ) )
462 return FT_Err_Invalid_Argument;
463
464 if ( noErr != FSGetCatalogInfo( &ref, kFSCatInfoNone,
465 NULL, NULL, NULL, &par_ref ) )
466 return FT_Err_Invalid_Argument;
467
468 if ( noErr != FSRefMakePath( &par_ref, path_lwfn, path_size ) )
469 return FT_Err_Invalid_Argument;
470
471 if ( ft_strlen( (char *)path_lwfn ) + 1 + base_lwfn[0] > path_size )
472 return FT_Err_Invalid_Argument;
473
474 /* now we have absolute dirname in lookup_path */
475 if ( path_lwfn[0] == '/' )
476 ft_strcat( (char *)path_lwfn, "/" );
477 else
478 ft_strcat( (char *)path_lwfn, ":" );
479
480 dirname_len = ft_strlen( (char *)path_lwfn );
481 ft_strcat( (char *)path_lwfn, (char *)base_lwfn + 1 );
Werner Lemberg435046b2006-01-11 10:57:42 +0000482 path_lwfn[dirname_len + base_lwfn[0]] = '\0';
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000483
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000484 if ( noErr != FSPathMakeRef( path_lwfn, &ref, FALSE ) )
485 return FT_Err_Cannot_Open_Resource;
486
487 if ( noErr != FSGetCatalogInfo( &ref, kFSCatInfoNone,
488 NULL, NULL, NULL, NULL ) )
489 return FT_Err_Cannot_Open_Resource;
490
491 return FT_Err_Ok;
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000492 }
493
494
495 static short
496 count_faces( Handle fond,
497 const UInt8* pathname )
498 {
499 short sfnt_id;
500 short have_sfnt, have_lwfn;
Werner Lemberg435046b2006-01-11 10:57:42 +0000501 Str255 lwfn_file_name;
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000502 UInt8 buff[HFS_MAXPATHLEN];
Werner Lemberg435046b2006-01-11 10:57:42 +0000503 FT_Error err;
Suzuki, Toshiya (鈴木俊哉)52311972006-06-22 02:34:27 +0000504 short num_faces;
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000505
506
507 have_sfnt = have_lwfn = 0;
508
Werner Lemberge2455ba2004-02-26 21:56:27 +0000509 HLock( fond );
510 parse_fond( *fond, &have_sfnt, &sfnt_id, lwfn_file_name, 0 );
Werner Lemberge2455ba2004-02-26 21:56:27 +0000511
512 if ( lwfn_file_name[0] )
513 {
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000514 err = lookup_lwfn_by_fond( pathname, lwfn_file_name,
Werner Lemberg435046b2006-01-11 10:57:42 +0000515 buff, sizeof ( buff ) );
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000516 if ( FT_Err_Ok == err )
517 have_lwfn = 1;
Werner Lemberge2455ba2004-02-26 21:56:27 +0000518 }
519
520 if ( have_lwfn && ( !have_sfnt || PREFER_LWFN ) )
Suzuki, Toshiya (鈴木俊哉)52311972006-06-22 02:34:27 +0000521 num_faces = 1;
Werner Lemberge2455ba2004-02-26 21:56:27 +0000522 else
Suzuki, Toshiya (鈴木俊哉)52311972006-06-22 02:34:27 +0000523 num_faces = count_faces_scalable( *fond );
524
525 HUnlock( fond );
526 return num_faces;
Werner Lemberge2455ba2004-02-26 21:56:27 +0000527 }
528
529
Just van Rossumae4bcee2000-07-28 01:10:35 +0000530 /* Read Type 1 data from the POST resources inside the LWFN file,
Werner Lemberg435046b2006-01-11 10:57:42 +0000531 return a PFB buffer. This is somewhat convoluted because the FT2
Just van Rossumae4bcee2000-07-28 01:10:35 +0000532 PFB parser wants the ASCII header as one chunk, and the LWFN
Werner Lemberg435046b2006-01-11 10:57:42 +0000533 chunks are often not organized that way, so we glue chunks
Just van Rossumae4bcee2000-07-28 01:10:35 +0000534 of the same type together. */
Werner Lembergf814d0f2001-06-27 16:18:10 +0000535 static FT_Error
536 read_lwfn( FT_Memory memory,
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000537 short res,
Werner Lembergf814d0f2001-06-27 16:18:10 +0000538 FT_Byte** pfb_data,
539 FT_ULong* size )
Just van Rossumae4bcee2000-07-28 01:10:35 +0000540 {
541 FT_Error error = FT_Err_Ok;
Werner Lemberge2455ba2004-02-26 21:56:27 +0000542 short res_id;
Werner Lemberg9ca7a152002-04-30 14:26:49 +0000543 unsigned char *buffer, *p, *size_p = NULL;
Just van Rossumae4bcee2000-07-28 01:10:35 +0000544 FT_ULong total_size = 0;
David Turner9ca78252006-05-02 09:00:29 +0000545 FT_ULong old_total_size = 0;
Just van Rossumae4bcee2000-07-28 01:10:35 +0000546 FT_ULong post_size, pfb_chunk_size;
547 Handle post_data;
548 char code, last_code;
549
550
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000551 UseResFile( res );
Just van Rossumae4bcee2000-07-28 01:10:35 +0000552
Werner Lemberge2455ba2004-02-26 21:56:27 +0000553 /* First pass: load all POST resources, and determine the size of */
554 /* the output buffer. */
Werner Lemberg9ca7a152002-04-30 14:26:49 +0000555 res_id = 501;
Just van Rossumae4bcee2000-07-28 01:10:35 +0000556 last_code = -1;
Werner Lemberg05c21b82000-07-29 20:38:19 +0000557
Just van Rossumae4bcee2000-07-28 01:10:35 +0000558 for (;;)
559 {
560 post_data = Get1Resource( 'POST', res_id++ );
561 if ( post_data == NULL )
Werner Lemberg435046b2006-01-11 10:57:42 +0000562 break; /* we are done */
Just van Rossumae4bcee2000-07-28 01:10:35 +0000563
564 code = (*post_data)[0];
565
566 if ( code != last_code )
567 {
568 if ( code == 5 )
569 total_size += 2; /* just the end code */
570 else
571 total_size += 6; /* code + 4 bytes chunk length */
572 }
573
574 total_size += GetHandleSize( post_data ) - 2;
575 last_code = code;
David Turner9ca78252006-05-02 09:00:29 +0000576
577 /* detect integer overflows */
578 if ( total_size < old_total_size )
579 {
580 error = FT_Err_Array_Too_Large;
581 goto Error;
582 }
583
584 old_total_size = total_size;
Just van Rossumae4bcee2000-07-28 01:10:35 +0000585 }
586
David Turnere459d742002-03-22 13:52:37 +0000587 if ( FT_ALLOC( buffer, (FT_Long)total_size ) )
Just van Rossumae4bcee2000-07-28 01:10:35 +0000588 goto Error;
589
Werner Lemberge2455ba2004-02-26 21:56:27 +0000590 /* Second pass: append all POST data to the buffer, add PFB fields. */
591 /* Glue all consecutive chunks of the same type together. */
Werner Lemberg9ca7a152002-04-30 14:26:49 +0000592 p = buffer;
593 res_id = 501;
594 last_code = -1;
Just van Rossumae4bcee2000-07-28 01:10:35 +0000595 pfb_chunk_size = 0;
596
597 for (;;)
598 {
599 post_data = Get1Resource( 'POST', res_id++ );
600 if ( post_data == NULL )
Werner Lemberg435046b2006-01-11 10:57:42 +0000601 break; /* we are done */
Just van Rossumae4bcee2000-07-28 01:10:35 +0000602
603 post_size = (FT_ULong)GetHandleSize( post_data ) - 2;
604 code = (*post_data)[0];
605
606 if ( code != last_code )
607 {
Just van Rossumae4bcee2000-07-28 01:10:35 +0000608 if ( last_code != -1 )
609 {
Werner Lemberg435046b2006-01-11 10:57:42 +0000610 /* we are done adding a chunk, fill in the size field */
Werner Lemberg9ca7a152002-04-30 14:26:49 +0000611 if ( size_p != NULL )
612 {
613 *size_p++ = (FT_Byte)( pfb_chunk_size & 0xFF );
614 *size_p++ = (FT_Byte)( ( pfb_chunk_size >> 8 ) & 0xFF );
615 *size_p++ = (FT_Byte)( ( pfb_chunk_size >> 16 ) & 0xFF );
616 *size_p++ = (FT_Byte)( ( pfb_chunk_size >> 24 ) & 0xFF );
617 }
Just van Rossumae4bcee2000-07-28 01:10:35 +0000618 pfb_chunk_size = 0;
619 }
620
621 *p++ = 0x80;
622 if ( code == 5 )
623 *p++ = 0x03; /* the end */
624 else if ( code == 2 )
625 *p++ = 0x02; /* binary segment */
626 else
627 *p++ = 0x01; /* ASCII segment */
628
629 if ( code != 5 )
630 {
631 size_p = p; /* save for later */
632 p += 4; /* make space for size field */
633 }
634 }
635
David Turnerd15bc0d2002-04-12 09:31:48 +0000636 ft_memcpy( p, *post_data + 2, post_size );
Just van Rossumae4bcee2000-07-28 01:10:35 +0000637 pfb_chunk_size += post_size;
638 p += post_size;
639 last_code = code;
640 }
641
642 *pfb_data = buffer;
643 *size = total_size;
644
Werner Lemberg05c21b82000-07-29 20:38:19 +0000645 Error:
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000646 CloseResFile( res );
Just van Rossumae4bcee2000-07-28 01:10:35 +0000647 return error;
648 }
649
650
651 /* Finalizer for a memory stream; gets called by FT_Done_Face().
652 It frees the memory it uses. */
Werner Lembergf814d0f2001-06-27 16:18:10 +0000653 static void
654 memory_stream_close( FT_Stream stream )
Just van Rossumae4bcee2000-07-28 01:10:35 +0000655 {
656 FT_Memory memory = stream->memory;
657
658
David Turnere459d742002-03-22 13:52:37 +0000659 FT_FREE( stream->base );
Werner Lemberg05c21b82000-07-29 20:38:19 +0000660
661 stream->size = 0;
662 stream->base = 0;
663 stream->close = 0;
Just van Rossumae4bcee2000-07-28 01:10:35 +0000664 }
665
666
667 /* Create a new memory stream from a buffer and a size. */
Werner Lembergf814d0f2001-06-27 16:18:10 +0000668 static FT_Error
Werner Lemberg9ca7a152002-04-30 14:26:49 +0000669 new_memory_stream( FT_Library library,
670 FT_Byte* base,
671 FT_ULong size,
672 FT_Stream_CloseFunc close,
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000673 FT_Stream* astream )
Just van Rossumae4bcee2000-07-28 01:10:35 +0000674 {
Werner Lemberg9ca7a152002-04-30 14:26:49 +0000675 FT_Error error;
676 FT_Memory memory;
677 FT_Stream stream;
Just van Rossumae4bcee2000-07-28 01:10:35 +0000678
679
Werner Lemberg9ca7a152002-04-30 14:26:49 +0000680 if ( !library )
681 return FT_Err_Invalid_Library_Handle;
Just van Rossumae4bcee2000-07-28 01:10:35 +0000682
Werner Lemberg9ca7a152002-04-30 14:26:49 +0000683 if ( !base )
684 return FT_Err_Invalid_Argument;
Just van Rossumae4bcee2000-07-28 01:10:35 +0000685
Werner Lemberg9ca7a152002-04-30 14:26:49 +0000686 *astream = 0;
687 memory = library->memory;
688 if ( FT_NEW( stream ) )
689 goto Exit;
Just van Rossumae4bcee2000-07-28 01:10:35 +0000690
Werner Lemberg9ca7a152002-04-30 14:26:49 +0000691 FT_Stream_OpenMemory( stream, base, size );
Just van Rossumae4bcee2000-07-28 01:10:35 +0000692
Werner Lemberg9ca7a152002-04-30 14:26:49 +0000693 stream->close = close;
Just van Rossumae4bcee2000-07-28 01:10:35 +0000694
Werner Lemberg9ca7a152002-04-30 14:26:49 +0000695 *astream = stream;
Just van Rossumae4bcee2000-07-28 01:10:35 +0000696
Werner Lemberg9ca7a152002-04-30 14:26:49 +0000697 Exit:
698 return error;
Just van Rossumae4bcee2000-07-28 01:10:35 +0000699 }
700
701
702 /* Create a new FT_Face given a buffer and a driver name. */
Werner Lembergf814d0f2001-06-27 16:18:10 +0000703 static FT_Error
704 open_face_from_buffer( FT_Library library,
705 FT_Byte* base,
706 FT_ULong size,
707 FT_Long face_index,
708 char* driver_name,
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000709 FT_Face* aface )
Just van Rossumae4bcee2000-07-28 01:10:35 +0000710 {
711 FT_Open_Args args;
712 FT_Error error;
713 FT_Stream stream;
714 FT_Memory memory = library->memory;
715
716
717 error = new_memory_stream( library,
718 base,
719 size,
720 memory_stream_close,
721 &stream );
722 if ( error )
723 {
David Turnere459d742002-03-22 13:52:37 +0000724 FT_FREE( base );
Just van Rossumae4bcee2000-07-28 01:10:35 +0000725 return error;
726 }
727
Werner Lemberg435046b2006-01-11 10:57:42 +0000728 args.flags = FT_OPEN_STREAM;
Just van Rossumae4bcee2000-07-28 01:10:35 +0000729 args.stream = stream;
730 if ( driver_name )
731 {
Werner Lemberg435046b2006-01-11 10:57:42 +0000732 args.flags = args.flags | FT_OPEN_DRIVER;
Just van Rossumae4bcee2000-07-28 01:10:35 +0000733 args.driver = FT_Get_Module( library, driver_name );
734 }
Werner Lemberg05c21b82000-07-29 20:38:19 +0000735
Werner Lemberg2630e542004-03-20 14:26:38 +0000736 /* At this point, face_index has served its purpose; */
737 /* whoever calls this function has already used it to */
738 /* locate the correct font data. We should not propagate */
739 /* this index to FT_Open_Face() (unless it is negative). */
740
741 if ( face_index > 0 )
742 face_index = 0;
743
Just van Rossumae4bcee2000-07-28 01:10:35 +0000744 error = FT_Open_Face( library, &args, face_index, aface );
Just van Rossum5fe94ff2000-07-28 02:25:23 +0000745 if ( error == FT_Err_Ok )
Just van Rossumae4bcee2000-07-28 01:10:35 +0000746 (*aface)->face_flags &= ~FT_FACE_FLAG_EXTERNAL_STREAM;
Suzuki, Toshiya (鈴木俊哉)47200602006-05-19 10:48:42 +0000747 else
748 FT_Stream_Free( stream, 0 );
Werner Lemberg9ca7a152002-04-30 14:26:49 +0000749
Just van Rossumae4bcee2000-07-28 01:10:35 +0000750 return error;
751 }
752
753
754 /* Create a new FT_Face from a file spec to an LWFN file. */
Werner Lembergf814d0f2001-06-27 16:18:10 +0000755 static FT_Error
Werner Lemberg435046b2006-01-11 10:57:42 +0000756 FT_New_Face_From_LWFN( FT_Library library,
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000757 const UInt8* pathname,
Werner Lemberg435046b2006-01-11 10:57:42 +0000758 FT_Long face_index,
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000759 FT_Face* aface )
Just van Rossumae4bcee2000-07-28 01:10:35 +0000760 {
Werner Lemberg9ca7a152002-04-30 14:26:49 +0000761 FT_Byte* pfb_data;
762 FT_ULong pfb_size;
763 FT_Error error;
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000764 short res;
Just van Rossumae4bcee2000-07-28 01:10:35 +0000765
766
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000767 if ( noErr != FT_FSPathMakeRes( pathname, &res ) )
768 return FT_Err_Cannot_Open_Resource;
Werner Lemberge2455ba2004-02-26 21:56:27 +0000769
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000770 pfb_data = NULL;
771 pfb_size = 0;
772 error = read_lwfn( library->memory, res, &pfb_data, &pfb_size );
773 CloseResFile( res ); /* PFB is already loaded, useless anymore */
Just van Rossumae4bcee2000-07-28 01:10:35 +0000774 if ( error )
775 return error;
776
Just van Rossumae4bcee2000-07-28 01:10:35 +0000777 return open_face_from_buffer( library,
778 pfb_data,
779 pfb_size,
780 face_index,
781 "type1",
782 aface );
783 }
784
785
786 /* Create a new FT_Face from an SFNT resource, specified by res ID. */
Werner Lembergf814d0f2001-06-27 16:18:10 +0000787 static FT_Error
788 FT_New_Face_From_SFNT( FT_Library library,
789 short sfnt_id,
790 FT_Long face_index,
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000791 FT_Face* aface )
Just van Rossumae4bcee2000-07-28 01:10:35 +0000792 {
Werner Lemberg05c21b82000-07-29 20:38:19 +0000793 Handle sfnt = NULL;
794 FT_Byte* sfnt_data;
795 size_t sfnt_size;
Werner Lemberg435046b2006-01-11 10:57:42 +0000796 FT_Error error = FT_Err_Ok;
Werner Lemberg05c21b82000-07-29 20:38:19 +0000797 FT_Memory memory = library->memory;
Werner Lembergc70818a2003-05-15 06:44:09 +0000798 int is_cff;
Just van Rossumae4bcee2000-07-28 01:10:35 +0000799
800
801 sfnt = GetResource( 'sfnt', sfnt_id );
802 if ( ResError() )
803 return FT_Err_Invalid_Handle;
804
805 sfnt_size = (FT_ULong)GetHandleSize( sfnt );
David Turnere459d742002-03-22 13:52:37 +0000806 if ( FT_ALLOC( sfnt_data, (FT_Long)sfnt_size ) )
Just van Rossumae4bcee2000-07-28 01:10:35 +0000807 {
808 ReleaseResource( sfnt );
809 return error;
810 }
811
812 HLock( sfnt );
David Turnerd15bc0d2002-04-12 09:31:48 +0000813 ft_memcpy( sfnt_data, *sfnt, sfnt_size );
Just van Rossumae4bcee2000-07-28 01:10:35 +0000814 HUnlock( sfnt );
815 ReleaseResource( sfnt );
816
Werner Lemberg756655b2003-06-07 05:13:22 +0000817 is_cff = sfnt_size > 4 && sfnt_data[0] == 'O' &&
818 sfnt_data[1] == 'T' &&
819 sfnt_data[2] == 'T' &&
820 sfnt_data[3] == 'O';
Werner Lembergc70818a2003-05-15 06:44:09 +0000821
Just van Rossumae4bcee2000-07-28 01:10:35 +0000822 return open_face_from_buffer( library,
823 sfnt_data,
824 sfnt_size,
825 face_index,
Werner Lembergc70818a2003-05-15 06:44:09 +0000826 is_cff ? "cff" : "truetype",
Just van Rossumae4bcee2000-07-28 01:10:35 +0000827 aface );
828 }
829
830
831 /* Create a new FT_Face from a file spec to a suitcase file. */
Werner Lembergf814d0f2001-06-27 16:18:10 +0000832 static FT_Error
Werner Lemberg435046b2006-01-11 10:57:42 +0000833 FT_New_Face_From_Suitcase( FT_Library library,
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000834 const UInt8* pathname,
Werner Lemberg435046b2006-01-11 10:57:42 +0000835 FT_Long face_index,
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000836 FT_Face* aface )
Just van Rossumae4bcee2000-07-28 01:10:35 +0000837 {
Suzuki, Toshiya (鈴木俊哉)53be6e92005-12-23 12:22:46 +0000838 FT_Error error = FT_Err_Cannot_Open_Resource;
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000839 short res_ref, res_index;
Just van Rossumae4bcee2000-07-28 01:10:35 +0000840 Handle fond;
Suzuki, Toshiya (鈴木俊哉)53be6e92005-12-23 12:22:46 +0000841 short num_faces_in_res, num_faces_in_fond;
Just van Rossumae4bcee2000-07-28 01:10:35 +0000842
843
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000844 if ( noErr != FT_FSPathMakeRes( pathname, &res_ref ) )
845 return FT_Err_Cannot_Open_Resource;
846
Just van Rossumae4bcee2000-07-28 01:10:35 +0000847 UseResFile( res_ref );
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000848 if ( ResError() )
849 return FT_Err_Cannot_Open_Resource;
Just van Rossumae4bcee2000-07-28 01:10:35 +0000850
Suzuki, Toshiya (鈴木俊哉)53be6e92005-12-23 12:22:46 +0000851 num_faces_in_res = 0;
Werner Lemberge2455ba2004-02-26 21:56:27 +0000852 for ( res_index = 1; ; ++res_index )
Just van Rossumae4bcee2000-07-28 01:10:35 +0000853 {
Werner Lemberge2455ba2004-02-26 21:56:27 +0000854 fond = Get1IndResource( 'FOND', res_index );
855 if ( ResError() )
Werner Lemberge2455ba2004-02-26 21:56:27 +0000856 break;
857
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000858 num_faces_in_fond = count_faces( fond, pathname );
Suzuki, Toshiya (鈴木俊哉)53be6e92005-12-23 12:22:46 +0000859 num_faces_in_res += num_faces_in_fond;
Werner Lemberge2455ba2004-02-26 21:56:27 +0000860
Suzuki, Toshiya (鈴木俊哉)53be6e92005-12-23 12:22:46 +0000861 if ( 0 <= face_index && face_index < num_faces_in_fond && error )
862 error = FT_New_Face_From_FOND( library, fond, face_index, aface );
Werner Lemberg435046b2006-01-11 10:57:42 +0000863
Suzuki, Toshiya (鈴木俊哉)53be6e92005-12-23 12:22:46 +0000864 face_index -= num_faces_in_fond;
Just van Rossumae4bcee2000-07-28 01:10:35 +0000865 }
866
Just van Rossumae4bcee2000-07-28 01:10:35 +0000867 CloseResFile( res_ref );
Suzuki, Toshiya (鈴木俊哉)53be6e92005-12-23 12:22:46 +0000868 if ( FT_Err_Ok == error && NULL != aface )
869 (*aface)->num_faces = num_faces_in_res;
Just van Rossumae4bcee2000-07-28 01:10:35 +0000870 return error;
871 }
872
Werner Lemberge9e130c2001-12-07 21:56:32 +0000873
Werner Lemberg9ca7a152002-04-30 14:26:49 +0000874 /* documentation is in ftmac.h */
Werner Lemberg90a03302000-11-07 17:21:11 +0000875
Werner Lembergf814d0f2001-06-27 16:18:10 +0000876 FT_EXPORT_DEF( FT_Error )
877 FT_New_Face_From_FOND( FT_Library library,
878 Handle fond,
879 FT_Long face_index,
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000880 FT_Face* aface )
Just van Rossumae4bcee2000-07-28 01:10:35 +0000881 {
Werner Lemberg435046b2006-01-11 10:57:42 +0000882 short sfnt_id, have_sfnt, have_lwfn = 0;
883 short fond_id;
884 OSType fond_type;
885 Str255 fond_name;
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000886 Str255 lwfn_file_name;
887 UInt8 path_lwfn[HFS_MAXPATHLEN];
888 OSErr err;
Suzuki, Toshiya (鈴木俊哉)07088262006-10-15 07:15:28 +0000889 FT_Error error = FT_Err_Ok;
Just van Rossumae4bcee2000-07-28 01:10:35 +0000890
891
Werner Lembergc3b21602001-12-05 01:22:05 +0000892 GetResInfo( fond, &fond_id, &fond_type, fond_name );
Just van Rossumae4bcee2000-07-28 01:10:35 +0000893 if ( ResError() != noErr || fond_type != 'FOND' )
894 return FT_Err_Invalid_File_Format;
895
896 HLock( fond );
Leonard Rosentholae340bb2001-10-26 13:24:39 +0000897 parse_fond( *fond, &have_sfnt, &sfnt_id, lwfn_file_name, face_index );
Just van Rossumae4bcee2000-07-28 01:10:35 +0000898 HUnlock( fond );
899
900 if ( lwfn_file_name[0] )
901 {
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000902 short res;
903
904
905 res = HomeResFile( fond );
906 if ( noErr != ResError() )
907 goto found_no_lwfn_file;
908
Werner Lemberg435046b2006-01-11 10:57:42 +0000909 {
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000910 UInt8 path_fond[HFS_MAXPATHLEN];
911 FSRef ref;
912
Werner Lemberg435046b2006-01-11 10:57:42 +0000913
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000914 err = FSGetForkCBInfo( res, kFSInvalidVolumeRefNum,
915 NULL, NULL, NULL, &ref, NULL );
916 if ( noErr != err )
917 goto found_no_lwfn_file;
918
Werner Lemberg435046b2006-01-11 10:57:42 +0000919 err = FSRefMakePath( &ref, path_fond, sizeof ( path_fond ) );
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000920 if ( noErr != err )
921 goto found_no_lwfn_file;
922
923 error = lookup_lwfn_by_fond( path_fond, lwfn_file_name,
Werner Lemberg435046b2006-01-11 10:57:42 +0000924 path_lwfn, sizeof ( path_lwfn ) );
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000925 if ( FT_Err_Ok == error )
926 have_lwfn = 1;
927 }
Werner Lemberg435046b2006-01-11 10:57:42 +0000928 }
Just van Rossumae4bcee2000-07-28 01:10:35 +0000929
930 if ( have_lwfn && ( !have_sfnt || PREFER_LWFN ) )
Werner Lemberg745ff2c2006-09-19 05:48:02 +0000931 error = FT_New_Face_From_LWFN( library,
932 path_lwfn,
933 face_index,
934 aface );
935 else
936 error = FT_Err_Unknown_File_Format;
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000937
Werner Lemberg435046b2006-01-11 10:57:42 +0000938 found_no_lwfn_file:
Werner Lemberg745ff2c2006-09-19 05:48:02 +0000939 if ( have_sfnt && FT_Err_Ok != error )
940 error = FT_New_Face_From_SFNT( library,
941 sfnt_id,
942 face_index,
943 aface );
Just van Rossumae4bcee2000-07-28 01:10:35 +0000944
Werner Lemberg745ff2c2006-09-19 05:48:02 +0000945 return error;
Werner Lemberge9e130c2001-12-07 21:56:32 +0000946 }
947
Werner Lembergca7ef5e2004-02-28 19:12:01 +0000948
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000949 /* Common function to load a new FT_Face from a resource file. */
Werner Lembergca7ef5e2004-02-28 19:12:01 +0000950 static FT_Error
Werner Lemberg435046b2006-01-11 10:57:42 +0000951 FT_New_Face_From_Resource( FT_Library library,
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000952 const UInt8* pathname,
Werner Lemberg435046b2006-01-11 10:57:42 +0000953 FT_Long face_index,
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000954 FT_Face* aface )
Werner Lembergca7ef5e2004-02-28 19:12:01 +0000955 {
956 OSType file_type;
Werner Lembergca7ef5e2004-02-28 19:12:01 +0000957 FT_Error error;
958
959
Werner Lemberg435046b2006-01-11 10:57:42 +0000960 /* LWFN is a (very) specific file format, check for it explicitly */
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000961 file_type = get_file_type_from_path( pathname );
Werner Lemberg435046b2006-01-11 10:57:42 +0000962 if ( file_type == 'LWFN' )
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000963 return FT_New_Face_From_LWFN( library, pathname, face_index, aface );
Werner Lemberg435046b2006-01-11 10:57:42 +0000964
965 /* Otherwise the file type doesn't matter (there are more than */
966 /* `FFIL' and `tfil'). Just try opening it as a font suitcase; */
967 /* if it works, fine. */
Werner Lembergca7ef5e2004-02-28 19:12:01 +0000968
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000969 error = FT_New_Face_From_Suitcase( library, pathname, face_index, aface );
Werner Lemberg435046b2006-01-11 10:57:42 +0000970 if ( error == 0 )
971 return error;
Werner Lembergca7ef5e2004-02-28 19:12:01 +0000972
Werner Lembergca7ef5e2004-02-28 19:12:01 +0000973 /* let it fall through to normal loader (.ttf, .otf, etc.); */
974 /* we signal this by returning no error and no FT_Face */
975 *aface = NULL;
976 return 0;
977 }
978
Just van Rossumae4bcee2000-07-28 01:10:35 +0000979
980 /*************************************************************************/
981 /* */
982 /* <Function> */
983 /* FT_New_Face */
984 /* */
985 /* <Description> */
986 /* This is the Mac-specific implementation of FT_New_Face. In */
Werner Lemberg05c21b82000-07-29 20:38:19 +0000987 /* addition to the standard FT_New_Face() functionality, it also */
Just van Rossumae4bcee2000-07-28 01:10:35 +0000988 /* accepts pathnames to Mac suitcase files. For further */
Werner Lemberg90a03302000-11-07 17:21:11 +0000989 /* documentation see the original FT_New_Face() in freetype.h. */
Just van Rossumae4bcee2000-07-28 01:10:35 +0000990 /* */
Werner Lembergf814d0f2001-06-27 16:18:10 +0000991 FT_EXPORT_DEF( FT_Error )
992 FT_New_Face( FT_Library library,
993 const char* pathname,
994 FT_Long face_index,
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000995 FT_Face* aface )
Just van Rossumae4bcee2000-07-28 01:10:35 +0000996 {
997 FT_Open_Args args;
Werner Lembergca7ef5e2004-02-28 19:12:01 +0000998 FT_Error error;
Just van Rossumae4bcee2000-07-28 01:10:35 +0000999
1000
1001 /* test for valid `library' and `aface' delayed to FT_Open_Face() */
1002 if ( !pathname )
1003 return FT_Err_Invalid_Argument;
1004
Werner Lemberg435046b2006-01-11 10:57:42 +00001005 error = FT_Err_Ok;
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +00001006 *aface = NULL;
Just van Rossumae4bcee2000-07-28 01:10:35 +00001007
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +00001008 /* try resourcefork based font: LWFN, FFIL */
Werner Lemberg435046b2006-01-11 10:57:42 +00001009 error = FT_New_Face_From_Resource( library, (UInt8 *)pathname,
1010 face_index, aface );
Werner Lembergca7ef5e2004-02-28 19:12:01 +00001011 if ( error != 0 || *aface != NULL )
1012 return error;
Werner Lemberg9ca7a152002-04-30 14:26:49 +00001013
Werner Lemberg9ca7a152002-04-30 14:26:49 +00001014 /* let it fall through to normal loader (.ttf, .otf, etc.) */
David Turnerb08fe2d2002-08-27 20:20:29 +00001015 args.flags = FT_OPEN_PATHNAME;
Werner Lemberg9ca7a152002-04-30 14:26:49 +00001016 args.pathname = (char*)pathname;
1017 return FT_Open_Face( library, &args, face_index, aface );
Just van Rossumae4bcee2000-07-28 01:10:35 +00001018 }
1019
Werner Lemberg05c21b82000-07-29 20:38:19 +00001020
Werner Lemberge2455ba2004-02-26 21:56:27 +00001021 /*************************************************************************/
1022 /* */
1023 /* <Function> */
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +00001024 /* FT_New_Face_From_FSRef */
1025 /* */
1026 /* <Description> */
1027 /* FT_New_Face_From_FSRef is identical to FT_New_Face except it */
1028 /* accepts an FSRef instead of a path. */
1029 /* */
1030 FT_EXPORT_DEF( FT_Error )
1031 FT_New_Face_From_FSRef( FT_Library library,
1032 const FSRef* ref,
Werner Lemberg435046b2006-01-11 10:57:42 +00001033 FT_Long face_index,
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +00001034 FT_Face* aface )
1035 {
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +00001036 FT_Error error;
1037 FT_Open_Args args;
1038 OSErr err;
1039 UInt8 pathname[HFS_MAXPATHLEN];
1040
1041
1042 if ( !ref )
1043 return FT_Err_Invalid_Argument;
1044
1045 err = FSRefMakePath( ref, pathname, sizeof ( pathname ) );
1046 if ( err )
1047 error = FT_Err_Cannot_Open_Resource;
1048
1049 error = FT_New_Face_From_Resource( library, pathname, face_index, aface );
1050 if ( error != 0 || *aface != NULL )
1051 return error;
1052
1053 /* fallback to datafork font */
1054 args.flags = FT_OPEN_PATHNAME;
1055 args.pathname = (char*)pathname;
1056 return FT_Open_Face( library, &args, face_index, aface );
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +00001057 }
1058
1059
1060 /*************************************************************************/
1061 /* */
1062 /* <Function> */
Werner Lemberge2455ba2004-02-26 21:56:27 +00001063 /* FT_New_Face_From_FSSpec */
1064 /* */
1065 /* <Description> */
1066 /* FT_New_Face_From_FSSpec is identical to FT_New_Face except it */
1067 /* accepts an FSSpec instead of a path. */
1068 /* */
1069 FT_EXPORT_DEF( FT_Error )
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +00001070 FT_New_Face_From_FSSpec( FT_Library library,
1071 const FSSpec* spec,
1072 FT_Long face_index,
1073 FT_Face* aface )
Werner Lemberg435046b2006-01-11 10:57:42 +00001074 {
Werner Lemberg435046b2006-01-11 10:57:42 +00001075 FSRef ref;
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +00001076
1077
1078 if ( !spec || FSpMakeFSRef( spec, &ref ) != noErr )
1079 return FT_Err_Invalid_Argument;
1080 else
1081 return FT_New_Face_From_FSRef( library, &ref, face_index, aface );
Werner Lemberge2455ba2004-02-26 21:56:27 +00001082 }
1083
1084
Werner Lemberg05c21b82000-07-29 20:38:19 +00001085/* END */