blob: 3be12cffc73ea180f5e14fb82729cf95de41dd87 [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. */
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +00006/* Heavily Fixed by mpsuzuki, George Williams and Sean McBride */
Just van Rossumae4bcee2000-07-28 01:10:35 +00007/* */
Werner Lemberg435046b2006-01-11 10:57:42 +00008/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006 by */
Just van Rossumae4bcee2000-07-28 01:10:35 +00009/* Just van Rossum, David Turner, Robert Wilhelm, and Werner Lemberg. */
10/* */
11/* This file is part of the FreeType project, and may only be used, */
12/* modified, and distributed under the terms of the FreeType project */
13/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
14/* this file you indicate that you have read the license and */
15/* understand and accept it fully. */
16/* */
17/***************************************************************************/
18
19
20 /*
21 Notes
22
Werner Lemberg9ca7a152002-04-30 14:26:49 +000023 Mac suitcase files can (and often do!) contain multiple fonts. To
Just van Rossumae4bcee2000-07-28 01:10:35 +000024 support this I use the face_index argument of FT_(Open|New)_Face()
25 functions, and pretend the suitcase file is a collection.
Werner Lemberg9ca7a152002-04-30 14:26:49 +000026
Werner Lemberg435046b2006-01-11 10:57:42 +000027 Warning: fbit and NFNT bitmap resources are not supported yet. In old
28 sfnt fonts, bitmap glyph data for each size is stored in each `NFNT'
29 resources instead of the `bdat' table in the sfnt resource. Therefore,
30 face->num_fixed_sizes is set to 0, because bitmap data in `NFNT'
31 resource is unavailable at present.
Just van Rossumae4bcee2000-07-28 01:10:35 +000032
Just van Rossumae4bcee2000-07-28 01:10:35 +000033 The Mac FOND support works roughly like this:
34
Werner Lemberg435046b2006-01-11 10:57:42 +000035 - Check whether the offered stream points to a Mac suitcase file. This
36 is done by checking the file type: it has to be 'FFIL' or 'tfil'. The
37 stream that gets passed to our init_face() routine is a stdio stream,
38 which isn't usable for us, since the FOND resources live in the
39 resource fork. So we just grab the stream->pathname field.
Just van Rossumae4bcee2000-07-28 01:10:35 +000040
Werner Lemberg435046b2006-01-11 10:57:42 +000041 - Read the FOND resource into memory, then check whether there is a
42 TrueType font and/or(!) a Type 1 font available.
Just van Rossumae4bcee2000-07-28 01:10:35 +000043
Werner Lemberg435046b2006-01-11 10:57:42 +000044 - If there is a Type 1 font available (as a separate `LWFN' file), read
45 its data into memory, massage it slightly so it becomes PFB data, wrap
46 it into a memory stream, load the Type 1 driver and delegate the rest
47 of the work to it by calling FT_Open_Face(). (XXX TODO: after this
48 has been done, the kerning data from the FOND resource should be
49 appended to the face: On the Mac there are usually no AFM files
50 available. However, this is tricky since we need to map Mac char
51 codes to ps glyph names to glyph ID's...)
Just van Rossumae4bcee2000-07-28 01:10:35 +000052
Werner Lemberg435046b2006-01-11 10:57:42 +000053 - If there is a TrueType font (an `sfnt' resource), read it into memory,
54 wrap it into a memory stream, load the TrueType driver and delegate
55 the rest of the work to it, by calling FT_Open_Face().
Just van Rossumae4bcee2000-07-28 01:10:35 +000056 */
57
Werner Lembergcc069be2000-12-08 16:17:16 +000058
59#include <ft2build.h>
60#include FT_FREETYPE_H
61#include FT_INTERNAL_STREAM_H
Werner Lemberg6eb116e2003-05-11 07:12:26 +000062
Werner Lembergb2c40b52004-08-28 08:02:46 +000063#if defined( __GNUC__ ) || defined( __IBMC__ )
Werner Lemberg3599a022004-04-14 08:49:11 +000064 /* This is for Mac OS X. Without redefinition, OS_INLINE */
65 /* expands to `static inline' which doesn't survive the */
66 /* -ansi compilation flag of GCC. */
Werner Lemberg435046b2006-01-11 10:57:42 +000067#define OS_INLINE static __inline__
Werner Lemberg6eb116e2003-05-11 07:12:26 +000068#include <Carbon/Carbon.h>
69#else
Just van Rossumae4bcee2000-07-28 01:10:35 +000070#include <Resources.h>
71#include <Fonts.h>
72#include <Errors.h>
Leonard Rosenthol70133732001-12-06 17:52:06 +000073#include <Files.h>
74#include <TextUtils.h>
Werner Lemberg6eb116e2003-05-11 07:12:26 +000075#endif
Just van Rossumae4bcee2000-07-28 01:10:35 +000076
Werner Lemberge2455ba2004-02-26 21:56:27 +000077#if defined( __MWERKS__ ) && !TARGET_RT_MAC_MACHO
78#include <FSp_fopen.h>
79#endif
80
David Turner19ed8af2000-12-08 02:42:29 +000081#include FT_MAC_H
Just van Rossumae4bcee2000-07-28 01:10:35 +000082
83
Werner Lemberg435046b2006-01-11 10:57:42 +000084 /* FSSpec functions are deprecated since Mac OS X 10.4 */
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +000085#ifndef HAVE_FSSPEC
86#if TARGET_API_MAC_OS8 || TARGET_API_MAC_CARBON
Werner Lemberg435046b2006-01-11 10:57:42 +000087#define HAVE_FSSPEC 1
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +000088#else
Werner Lemberg435046b2006-01-11 10:57:42 +000089#define HAVE_FSSPEC 0
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +000090#endif
91#endif
92
93 /* most FSRef functions were introduced since Mac OS 9 */
94#ifndef HAVE_FSREF
95#if TARGET_API_MAC_OSX
Werner Lemberg435046b2006-01-11 10:57:42 +000096#define HAVE_FSREF 1
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +000097#else
Werner Lemberg435046b2006-01-11 10:57:42 +000098#define HAVE_FSREF 0
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +000099#endif
100#endif
101
102#ifndef HFS_MAXPATHLEN
Werner Lemberg435046b2006-01-11 10:57:42 +0000103#define HFS_MAXPATHLEN 1024
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000104#endif
105
106
Werner Lemberg435046b2006-01-11 10:57:42 +0000107 /* QuickDraw is deprecated since Mac OS X 10.4 */
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000108#ifndef HAVE_QUICKDRAW_CARBON
109#if TARGET_API_MAC_OS8 || TARGET_API_MAC_CARBON
Werner Lemberg435046b2006-01-11 10:57:42 +0000110#define HAVE_QUICKDRAW_CARBON 1
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000111#else
Werner Lemberg435046b2006-01-11 10:57:42 +0000112#define HAVE_QUICKDRAW_CARBON 0
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000113#endif
114#endif
115
116 /* AppleTypeService is available since Mac OS X */
117#ifndef HAVE_ATS
118#if TARGET_API_MAC_OSX
Werner Lemberg435046b2006-01-11 10:57:42 +0000119#define HAVE_ATS 1
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000120#else
Werner Lemberg435046b2006-01-11 10:57:42 +0000121#define HAVE_ATS 0
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000122#endif
123#endif
124
Just van Rossumae4bcee2000-07-28 01:10:35 +0000125 /* Set PREFER_LWFN to 1 if LWFN (Type 1) is preferred over
126 TrueType in case *both* are available (this is not common,
127 but it *is* possible). */
128#ifndef PREFER_LWFN
Werner Lemberg435046b2006-01-11 10:57:42 +0000129#define PREFER_LWFN 1
Just van Rossumae4bcee2000-07-28 01:10:35 +0000130#endif
131
Werner Lemberge2455ba2004-02-26 21:56:27 +0000132
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000133#if !HAVE_QUICKDRAW_CARBON /* QuickDraw is deprecated since Mac OS X 10.4 */
Werner Lemberg435046b2006-01-11 10:57:42 +0000134
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000135 FT_EXPORT_DEF( FT_Error )
136 FT_GetFile_From_Mac_Name( const char* fontName,
137 FSSpec* pathSpec,
138 FT_Long* face_index )
139 {
140 return FT_Err_Unimplemented_Feature;
141 }
Werner Lemberg435046b2006-01-11 10:57:42 +0000142
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000143#else
Werner Lemberg435046b2006-01-11 10:57:42 +0000144
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000145 FT_EXPORT_DEF( FT_Error )
146 FT_GetFile_From_Mac_Name( const char* fontName,
147 FSSpec* pathSpec,
148 FT_Long* face_index )
149 {
150 OptionBits options = kFMUseGlobalScopeOption;
151
152 FMFontFamilyIterator famIter;
153 OSStatus status = FMCreateFontFamilyIterator( NULL, NULL,
154 options,
155 &famIter );
156 FMFont the_font = 0;
157 FMFontFamily family = 0;
158
159
160 *face_index = 0;
161 while ( status == 0 && !the_font )
162 {
163 status = FMGetNextFontFamily( &famIter, &family );
164 if ( status == 0 )
165 {
166 int stat2;
167 FMFontFamilyInstanceIterator instIter;
168 Str255 famNameStr;
169 char famName[256];
170
171
172 /* get the family name */
173 FMGetFontFamilyName( family, famNameStr );
174 CopyPascalStringToC( famNameStr, famName );
175
176 /* iterate through the styles */
177 FMCreateFontFamilyInstanceIterator( family, &instIter );
178
179 *face_index = 0;
Werner Lemberg435046b2006-01-11 10:57:42 +0000180 stat2 = 0;
181
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000182 while ( stat2 == 0 && !the_font )
183 {
184 FMFontStyle style;
185 FMFontSize size;
186 FMFont font;
187
188
189 stat2 = FMGetNextFontFamilyInstance( &instIter, &font,
190 &style, &size );
191 if ( stat2 == 0 && size == 0 )
192 {
193 char fullName[256];
194
195
196 /* build up a complete face name */
197 ft_strcpy( fullName, famName );
198 if ( style & bold )
199 strcat( fullName, " Bold" );
200 if ( style & italic )
201 strcat( fullName, " Italic" );
202
203 /* compare with the name we are looking for */
204 if ( ft_strcmp( fullName, fontName ) == 0 )
205 {
206 /* found it! */
207 the_font = font;
208 }
209 else
210 ++(*face_index);
211 }
212 }
213
214 FMDisposeFontFamilyInstanceIterator( &instIter );
215 }
216 }
217
218 FMDisposeFontFamilyIterator( &famIter );
219
220 if ( the_font )
221 {
222 FMGetFontContainer( the_font, pathSpec );
223 return FT_Err_Ok;
224 }
225 else
226 return FT_Err_Unknown_File_Format;
227 }
Werner Lemberg435046b2006-01-11 10:57:42 +0000228
229#endif /* HAVE_QUICKDRAW_CARBON */
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000230
231
232#if !HAVE_ATS
Werner Lemberg435046b2006-01-11 10:57:42 +0000233
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000234 FT_EXPORT_DEF( FT_Error )
235 FT_GetFile_From_Mac_ATS_Name( const char* fontName,
236 FSSpec* pathSpec,
237 FT_Long* face_index )
238 {
239 return FT_Err_Unimplemented_Feature;
240 }
Werner Lemberg435046b2006-01-11 10:57:42 +0000241
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000242#else
Werner Lemberg435046b2006-01-11 10:57:42 +0000243
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000244 FT_EXPORT_DEF( FT_Error )
245 FT_GetFile_From_Mac_ATS_Name( const char* fontName,
246 FSSpec* pathSpec,
247 FT_Long* face_index )
248 {
249 CFStringRef cf_fontName;
250 ATSFontRef ats_font_id;
Werner Lemberg435046b2006-01-11 10:57:42 +0000251
252
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000253 *face_index = 0;
Werner Lemberg435046b2006-01-11 10:57:42 +0000254
255 cf_fontName = CFStringCreateWithCString( NULL, fontName,
256 kCFStringEncodingMacRoman );
257 ats_font_id = ATSFontFindFromName( cf_fontName,
258 kATSOptionFlagsUnRestrictedScope );
259
260 if ( ats_font_id == 0 || ats_font_id == 0xFFFFFFFFUL )
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000261 return FT_Err_Unknown_File_Format;
Werner Lemberg435046b2006-01-11 10:57:42 +0000262
263 if ( 0 != ATSFontGetFileSpecification( ats_font_id, pathSpec ) )
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000264 return FT_Err_Unknown_File_Format;
Werner Lemberg435046b2006-01-11 10:57:42 +0000265
266 /* face_index calculation by searching preceding fontIDs */
267 /* with same FSRef */
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000268 {
269 int i;
270 FSSpec f;
Werner Lemberg435046b2006-01-11 10:57:42 +0000271
272
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000273 for ( i = 1; i < ats_font_id; i++ )
274 {
275 if ( 0 != ATSFontGetFileSpecification( ats_font_id - i,
276 &f ) ||
277 f.vRefNum != pathSpec->vRefNum ||
278 f.parID != pathSpec->parID ||
279 f.name[0] != pathSpec->name[0] ||
280 0 != ft_strncmp( (char *)f.name + 1,
281 (char *)pathSpec->name + 1,
282 f.name[0] ) )
283 break;
284 }
285 *face_index = ( i - 1 );
286 }
287 return FT_Err_Ok;
288 }
Werner Lemberg435046b2006-01-11 10:57:42 +0000289
290#endif /* HAVE_ATS */
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000291
292
Werner Lemberge2455ba2004-02-26 21:56:27 +0000293#if defined( __MWERKS__ ) && !TARGET_RT_MAC_MACHO
294
295#define STREAM_FILE( stream ) ( (FILE*)stream->descriptor.pointer )
296
297
298 FT_CALLBACK_DEF( void )
299 ft_FSp_stream_close( FT_Stream stream )
300 {
301 fclose( STREAM_FILE( stream ) );
302
303 stream->descriptor.pointer = NULL;
304 stream->size = 0;
305 stream->base = 0;
306 }
307
308
309 FT_CALLBACK_DEF( unsigned long )
310 ft_FSp_stream_io( FT_Stream stream,
311 unsigned long offset,
312 unsigned char* buffer,
313 unsigned long count )
314 {
315 FILE* file;
316
317
318 file = STREAM_FILE( stream );
319
320 fseek( file, offset, SEEK_SET );
321
322 return (unsigned long)fread( buffer, 1, count, file );
323 }
324
325#endif /* __MWERKS__ && !TARGET_RT_MAC_MACHO */
326
327
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000328#if HAVE_FSSPEC && !HAVE_FSREF
Werner Lemberg435046b2006-01-11 10:57:42 +0000329
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000330 static OSErr
Werner Lemberg435046b2006-01-11 10:57:42 +0000331 FT_FSPathMakeSpec( const UInt8* pathname,
332 FSSpec* spec_p,
333 Boolean isDirectory )
Just van Rossumae4bcee2000-07-28 01:10:35 +0000334 {
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000335 const char *p, *q;
336 short vRefNum;
337 long dirID;
338 Str255 nodeName;
339 OSErr err;
Werner Lemberg9ca7a152002-04-30 14:26:49 +0000340
341
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000342 p = q = (const char *)pathname;
343 dirID = 0;
344 vRefNum = 0;
Werner Lemberg9ca7a152002-04-30 14:26:49 +0000345
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000346 while ( 1 )
Werner Lemberg435046b2006-01-11 10:57:42 +0000347 {
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000348 q = p + FT_MIN( 255, ft_strlen( p ) );
Werner Lemberg9ca7a152002-04-30 14:26:49 +0000349
Werner Lemberg435046b2006-01-11 10:57:42 +0000350 if ( q == p )
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000351 return 0;
Werner Lemberg9ca7a152002-04-30 14:26:49 +0000352
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000353 if ( 255 < ft_strlen( (char *)pathname ) )
354 {
355 while ( p < q && *q != ':' )
356 q--;
357 }
Just van Rossumae4bcee2000-07-28 01:10:35 +0000358
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000359 if ( p < q )
360 *(char *)nodeName = q - p;
361 else if ( ft_strlen( p ) < 256 )
362 *(char *)nodeName = ft_strlen( p );
363 else
364 return errFSNameTooLong;
Just van Rossumae4bcee2000-07-28 01:10:35 +0000365
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000366 ft_strncpy( (char *)nodeName + 1, (char *)p, *(char *)nodeName );
367 err = FSMakeFSSpec( vRefNum, dirID, nodeName, spec_p );
368 if ( err || '\0' == *q )
369 return err;
Just van Rossumae4bcee2000-07-28 01:10:35 +0000370
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000371 vRefNum = spec_p->vRefNum;
372 dirID = spec_p->parID;
Werner Lemberg9ca7a152002-04-30 14:26:49 +0000373
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000374 p = q;
375 }
Just van Rossumae4bcee2000-07-28 01:10:35 +0000376 }
377
378
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000379 static OSErr
380 FT_FSpMakePath( const FSSpec* spec_p,
381 UInt8* path,
382 UInt32 maxPathSize )
Just van Rossumae4bcee2000-07-28 01:10:35 +0000383 {
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000384 OSErr err;
385 FSSpec spec = *spec_p;
386 short vRefNum;
387 long dirID;
388 Str255 parDir_name;
389
390
391 FT_MEM_SET( path, 0, maxPathSize );
392 while ( 1 )
393 {
394 int child_namelen = ft_strlen( (char *)path );
395 unsigned char node_namelen = spec.name[0];
396 unsigned char* node_name = spec.name + 1;
397
398
399 if ( node_namelen + child_namelen > maxPathSize )
400 return errFSNameTooLong;
401
402 FT_MEM_MOVE( path + node_namelen + 1, path, child_namelen );
403 FT_MEM_COPY( path, node_name, node_namelen );
404 if ( child_namelen > 0 )
Werner Lemberg435046b2006-01-11 10:57:42 +0000405 path[node_namelen] = ':';
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000406
407 vRefNum = spec.vRefNum;
408 dirID = spec.parID;
409 parDir_name[0] = '\0';
410 err = FSMakeFSSpec( vRefNum, dirID, parDir_name, &spec );
411 if ( noErr != err || dirID == spec.parID )
412 break;
413 }
414 return noErr;
415 }
Werner Lemberg435046b2006-01-11 10:57:42 +0000416
417#endif /* HAVE_FSSPEC && !HAVE_FSREF */
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000418
419
420 static OSErr
421 FT_FSPathMakeRes( const UInt8* pathname,
422 short* res )
423 {
Werner Lemberg435046b2006-01-11 10:57:42 +0000424
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000425#if HAVE_FSREF
Werner Lemberg435046b2006-01-11 10:57:42 +0000426
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000427 OSErr err;
428 FSRef ref;
429
Werner Lemberg435046b2006-01-11 10:57:42 +0000430
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000431 if ( noErr != FSPathMakeRef( pathname, &ref, FALSE ) )
432 return FT_Err_Cannot_Open_Resource;
433
Werner Lemberg435046b2006-01-11 10:57:42 +0000434 /* at present, no support for dfont format */
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000435 err = FSOpenResourceFile( &ref, 0, NULL, fsRdPerm, res );
436 if ( noErr == err )
437 return err;
438
439 /* fallback to original resource-fork font */
440 *res = FSOpenResFile( &ref, fsRdPerm );
441 err = ResError();
Werner Lemberg435046b2006-01-11 10:57:42 +0000442
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000443#else
Werner Lemberg435046b2006-01-11 10:57:42 +0000444
445 OSErr err;
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000446 FSSpec spec;
447
Werner Lemberg435046b2006-01-11 10:57:42 +0000448
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000449 if ( noErr != FT_FSPathMakeSpec( pathname, &spec, FALSE ) )
450 return FT_Err_Cannot_Open_Resource;
451
Werner Lemberg435046b2006-01-11 10:57:42 +0000452 /* at present, no support for dfont format without FSRef */
453 /* (see above), try original resource-fork font */
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000454 *res = FSpOpenResFile( &spec, fsRdPerm );
455 err = ResError();
Werner Lemberg435046b2006-01-11 10:57:42 +0000456
457#endif /* HAVE_FSREF */
458
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000459 return err;
460 }
461
462
463 /* Return the file type for given pathname */
464 static OSType
465 get_file_type_from_path( const UInt8* pathname )
466 {
Werner Lemberg435046b2006-01-11 10:57:42 +0000467
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000468#if HAVE_FSREF
Werner Lemberg435046b2006-01-11 10:57:42 +0000469
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000470 FSRef ref;
471 FSCatalogInfo info;
472
473
474 if ( noErr != FSPathMakeRef( pathname, &ref, FALSE ) )
475 return ( OSType ) 0;
476
477 if ( noErr != FSGetCatalogInfo( &ref, kFSCatInfoFinderInfo, &info,
478 NULL, NULL, NULL ) )
479 return ( OSType ) 0;
480
Werner Lemberg435046b2006-01-11 10:57:42 +0000481 return ((FInfo *)(info.finderInfo))->fdType;
482
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000483#else
Werner Lemberg435046b2006-01-11 10:57:42 +0000484
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000485 FSSpec spec;
Werner Lemberg05c21b82000-07-29 20:38:19 +0000486 FInfo finfo;
Just van Rossumae4bcee2000-07-28 01:10:35 +0000487
488
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000489 if ( noErr != FT_FSPathMakeSpec( pathname, &spec, FALSE ) )
490 return ( OSType ) 0;
491
492 if ( noErr != FSpGetFInfo( &spec, &finfo ) )
493 return ( OSType ) 0;
Werner Lemberg05c21b82000-07-29 20:38:19 +0000494
Just van Rossumae4bcee2000-07-28 01:10:35 +0000495 return finfo.fdType;
Werner Lemberg435046b2006-01-11 10:57:42 +0000496
497#endif /* HAVE_FSREF */
498
Just van Rossumae4bcee2000-07-28 01:10:35 +0000499 }
500
Werner Lemberge9e130c2001-12-07 21:56:32 +0000501
Just van Rossumae4bcee2000-07-28 01:10:35 +0000502 /* Given a PostScript font name, create the Macintosh LWFN file name. */
Werner Lembergf814d0f2001-06-27 16:18:10 +0000503 static void
504 create_lwfn_name( char* ps_name,
505 Str255 lwfn_file_name )
Just van Rossumae4bcee2000-07-28 01:10:35 +0000506 {
507 int max = 5, count = 0;
508 FT_Byte* p = lwfn_file_name;
509 FT_Byte* q = (FT_Byte*)ps_name;
510
511
512 lwfn_file_name[0] = 0;
513
514 while ( *q )
515 {
Werner Lemberg282637f2003-05-21 07:39:42 +0000516 if ( ft_isupper( *q ) )
Just van Rossumae4bcee2000-07-28 01:10:35 +0000517 {
518 if ( count )
519 max = 3;
520 count = 0;
521 }
David Turnerd15bc0d2002-04-12 09:31:48 +0000522 if ( count < max && ( ft_isalnum( *q ) || *q == '_' ) )
Just van Rossumae4bcee2000-07-28 01:10:35 +0000523 {
524 *++p = *q;
525 lwfn_file_name[0]++;
526 count++;
527 }
528 q++;
529 }
530 }
531
532
Werner Lemberge2455ba2004-02-26 21:56:27 +0000533 static short
Werner Lemberg083ba0b2005-12-23 15:10:54 +0000534 count_faces_sfnt( char* fond_data )
Werner Lemberge2455ba2004-02-26 21:56:27 +0000535 {
536 /* The count is 1 greater than the value in the FOND. */
537 /* Isn't that cute? :-) */
538
Werner Lemberg083ba0b2005-12-23 15:10:54 +0000539 return 1 + *( (short*)( fond_data + sizeof ( FamRec ) ) );
Werner Lemberge2455ba2004-02-26 21:56:27 +0000540 }
541
542
Suzuki, Toshiya (鈴木俊哉)53be6e92005-12-23 12:22:46 +0000543 static short
Werner Lemberg083ba0b2005-12-23 15:10:54 +0000544 count_faces_scalable( char* fond_data )
Suzuki, Toshiya (鈴木俊哉)53be6e92005-12-23 12:22:46 +0000545 {
546 AsscEntry* assoc;
547 FamRec* fond;
548 short i, face, face_all;
549
550
Werner Lemberg435046b2006-01-11 10:57:42 +0000551 fond = (FamRec*)fond_data;
552 face_all = *( (short *)( fond_data + sizeof ( FamRec ) ) ) + 1;
553 assoc = (AsscEntry*)( fond_data + sizeof ( FamRec ) + 2 );
554 face = 0;
Suzuki, Toshiya (鈴木俊哉)53be6e92005-12-23 12:22:46 +0000555
556 for ( i = 0; i < face_all; i++ )
557 {
558 if ( 0 == assoc[i].fontSize )
Werner Lemberg083ba0b2005-12-23 15:10:54 +0000559 face++;
Suzuki, Toshiya (鈴木俊哉)53be6e92005-12-23 12:22:46 +0000560 }
561 return face;
562 }
563
564
Just van Rossumae4bcee2000-07-28 01:10:35 +0000565 /* Look inside the FOND data, answer whether there should be an SFNT
Werner Lemberge9e130c2001-12-07 21:56:32 +0000566 resource, and answer the name of a possible LWFN Type 1 file.
567
568 Thanks to Paul Miller (paulm@profoundeffects.com) for the fix
Leonard Rosentholae340bb2001-10-26 13:24:39 +0000569 to load a face OTHER than the first one in the FOND!
570 */
Werner Lemberge2455ba2004-02-26 21:56:27 +0000571
572
Werner Lembergf814d0f2001-06-27 16:18:10 +0000573 static void
574 parse_fond( char* fond_data,
575 short* have_sfnt,
576 short* sfnt_id,
Leonard Rosentholae340bb2001-10-26 13:24:39 +0000577 Str255 lwfn_file_name,
578 short face_index )
Just van Rossumae4bcee2000-07-28 01:10:35 +0000579 {
580 AsscEntry* assoc;
Leonard Rosentholae340bb2001-10-26 13:24:39 +0000581 AsscEntry* base_assoc;
Just van Rossumae4bcee2000-07-28 01:10:35 +0000582 FamRec* fond;
583
584
585 *sfnt_id = 0;
586 *have_sfnt = 0;
587 lwfn_file_name[0] = 0;
588
Werner Lembergc3b21602001-12-05 01:22:05 +0000589 fond = (FamRec*)fond_data;
590 assoc = (AsscEntry*)( fond_data + sizeof ( FamRec ) + 2 );
Leonard Rosentholae340bb2001-10-26 13:24:39 +0000591 base_assoc = assoc;
Just van Rossumae4bcee2000-07-28 01:10:35 +0000592
Werner Lemberge2455ba2004-02-26 21:56:27 +0000593 /* Let's do a little range checking before we get too excited here */
594 if ( face_index < count_faces_sfnt( fond_data ) )
Just van Rossumae4bcee2000-07-28 01:10:35 +0000595 {
Werner Lemberge2455ba2004-02-26 21:56:27 +0000596 assoc += face_index; /* add on the face_index! */
597
598 /* if the face at this index is not scalable,
599 fall back to the first one (old behavior) */
600 if ( assoc->fontSize == 0 )
601 {
602 *have_sfnt = 1;
603 *sfnt_id = assoc->fontID;
604 }
605 else if ( base_assoc->fontSize == 0 )
606 {
607 *have_sfnt = 1;
608 *sfnt_id = base_assoc->fontID;
609 }
Leonard Rosentholae340bb2001-10-26 13:24:39 +0000610 }
Just van Rossumae4bcee2000-07-28 01:10:35 +0000611
612 if ( fond->ffStylOff )
613 {
614 unsigned char* p = (unsigned char*)fond_data;
615 StyleTable* style;
616 unsigned short string_count;
Just van Rossumae4bcee2000-07-28 01:10:35 +0000617 char ps_name[256];
618 unsigned char* names[64];
619 int i;
620
Werner Lemberg05c21b82000-07-29 20:38:19 +0000621
Just van Rossumae4bcee2000-07-28 01:10:35 +0000622 p += fond->ffStylOff;
623 style = (StyleTable*)p;
Werner Lemberg05c21b82000-07-29 20:38:19 +0000624 p += sizeof ( StyleTable );
Just van Rossumae4bcee2000-07-28 01:10:35 +0000625 string_count = *(unsigned short*)(p);
Werner Lemberg05c21b82000-07-29 20:38:19 +0000626 p += sizeof ( short );
Just van Rossumae4bcee2000-07-28 01:10:35 +0000627
Werner Lemberg435046b2006-01-11 10:57:42 +0000628 for ( i = 0; i < string_count && i < 64; i++ )
Just van Rossumae4bcee2000-07-28 01:10:35 +0000629 {
630 names[i] = p;
Werner Lemberg435046b2006-01-11 10:57:42 +0000631 p += names[i][0];
Just van Rossumae4bcee2000-07-28 01:10:35 +0000632 p++;
633 }
Just van Rossumae4bcee2000-07-28 01:10:35 +0000634
Just van Rossumae4bcee2000-07-28 01:10:35 +0000635 {
Werner Lemberg9ca7a152002-04-30 14:26:49 +0000636 size_t ps_name_len = (size_t)names[0][0];
Werner Lemberg05c21b82000-07-29 20:38:19 +0000637
638
Werner Lemberg9ca7a152002-04-30 14:26:49 +0000639 if ( ps_name_len != 0 )
640 {
Werner Lemberg282637f2003-05-21 07:39:42 +0000641 ft_memcpy(ps_name, names[0] + 1, ps_name_len);
Werner Lemberg9ca7a152002-04-30 14:26:49 +0000642 ps_name[ps_name_len] = 0;
643 }
644 if ( style->indexes[0] > 1 )
645 {
646 unsigned char* suffixes = names[style->indexes[0] - 1];
647
648
Werner Lembergfcc5c912003-04-23 18:10:19 +0000649 for ( i = 1; i <= suffixes[0]; i++ )
Werner Lemberg9ca7a152002-04-30 14:26:49 +0000650 {
651 unsigned char* s;
652 size_t j = suffixes[i] - 1;
653
654
655 if ( j < string_count && ( s = names[j] ) != NULL )
656 {
657 size_t s_len = (size_t)s[0];
658
659
660 if ( s_len != 0 && ps_name_len + s_len < sizeof ( ps_name ) )
661 {
Werner Lemberg282637f2003-05-21 07:39:42 +0000662 ft_memcpy( ps_name + ps_name_len, s + 1, s_len );
Werner Lemberg9ca7a152002-04-30 14:26:49 +0000663 ps_name_len += s_len;
664 ps_name[ps_name_len] = 0;
665 }
666 }
667 }
668 }
Just van Rossumae4bcee2000-07-28 01:10:35 +0000669 }
Werner Lemberg9ca7a152002-04-30 14:26:49 +0000670
Just van Rossumae4bcee2000-07-28 01:10:35 +0000671 create_lwfn_name( ps_name, lwfn_file_name );
672 }
673 }
674
675
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000676 static FT_Error
677 lookup_lwfn_by_fond( const UInt8* path_fond,
678 const StringPtr base_lwfn,
Werner Lemberg435046b2006-01-11 10:57:42 +0000679 UInt8* path_lwfn,
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000680 int path_size )
Werner Lemberge2455ba2004-02-26 21:56:27 +0000681 {
Werner Lemberg435046b2006-01-11 10:57:42 +0000682
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000683#if HAVE_FSREF
Werner Lemberg435046b2006-01-11 10:57:42 +0000684
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000685 FSRef ref, par_ref;
686 int dirname_len;
Werner Lemberge2455ba2004-02-26 21:56:27 +0000687
688
Werner Lemberg435046b2006-01-11 10:57:42 +0000689 /* Pathname for FSRef can be in various formats: HFS, HFS+, and POSIX. */
690 /* We should not extract parent directory by string manipulation. */
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000691
692 if ( noErr != FSPathMakeRef( path_fond, &ref, FALSE ) )
693 return FT_Err_Invalid_Argument;
694
695 if ( noErr != FSGetCatalogInfo( &ref, kFSCatInfoNone,
696 NULL, NULL, NULL, &par_ref ) )
697 return FT_Err_Invalid_Argument;
698
699 if ( noErr != FSRefMakePath( &par_ref, path_lwfn, path_size ) )
700 return FT_Err_Invalid_Argument;
701
702 if ( ft_strlen( (char *)path_lwfn ) + 1 + base_lwfn[0] > path_size )
703 return FT_Err_Invalid_Argument;
704
705 /* now we have absolute dirname in lookup_path */
706 if ( path_lwfn[0] == '/' )
707 ft_strcat( (char *)path_lwfn, "/" );
708 else
709 ft_strcat( (char *)path_lwfn, ":" );
710
711 dirname_len = ft_strlen( (char *)path_lwfn );
712 ft_strcat( (char *)path_lwfn, (char *)base_lwfn + 1 );
Werner Lemberg435046b2006-01-11 10:57:42 +0000713 path_lwfn[dirname_len + base_lwfn[0]] = '\0';
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000714
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000715 if ( noErr != FSPathMakeRef( path_lwfn, &ref, FALSE ) )
716 return FT_Err_Cannot_Open_Resource;
717
718 if ( noErr != FSGetCatalogInfo( &ref, kFSCatInfoNone,
719 NULL, NULL, NULL, NULL ) )
720 return FT_Err_Cannot_Open_Resource;
721
722 return FT_Err_Ok;
Werner Lemberg435046b2006-01-11 10:57:42 +0000723
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000724#else
Werner Lemberg435046b2006-01-11 10:57:42 +0000725
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000726 int i;
727 FSSpec spec;
728
729
730 /* pathname for FSSpec is always HFS format */
731 if ( ft_strlen( (char *)path_fond ) > path_size )
732 return FT_Err_Invalid_Argument;
733
734 ft_strcpy( (char *)path_lwfn, (char *)path_fond );
735
736 i = ft_strlen( (char *)path_lwfn ) - 1;
737 while ( i > 0 && ':' != path_lwfn[i] )
Werner Lemberg435046b2006-01-11 10:57:42 +0000738 i--;
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000739
740 if ( i + 1 + base_lwfn[0] > path_size )
741 return FT_Err_Invalid_Argument;
742
743 if ( ':' == path_lwfn[i] )
744 {
745 ft_strcpy( (char *)path_lwfn + i + 1, (char *)base_lwfn + 1 );
Werner Lemberg435046b2006-01-11 10:57:42 +0000746 path_lwfn[i + 1 + base_lwfn[0]] = '\0';
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000747 }
748 else
749 {
750 ft_strcpy( (char *)path_lwfn, (char *)base_lwfn + 1 );
Werner Lemberg435046b2006-01-11 10:57:42 +0000751 path_lwfn[base_lwfn[0]] = '\0';
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000752 }
753
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000754 if ( noErr != FT_FSPathMakeSpec( path_lwfn, &spec, FALSE ) )
755 return FT_Err_Cannot_Open_Resource;
756
757 return FT_Err_Ok;
Werner Lemberg435046b2006-01-11 10:57:42 +0000758
759#endif /* HAVE_FSREF */
760
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000761 }
762
763
764 static short
765 count_faces( Handle fond,
766 const UInt8* pathname )
767 {
768 short sfnt_id;
769 short have_sfnt, have_lwfn;
Werner Lemberg435046b2006-01-11 10:57:42 +0000770 Str255 lwfn_file_name;
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000771 UInt8 buff[HFS_MAXPATHLEN];
Werner Lemberg435046b2006-01-11 10:57:42 +0000772 FT_Error err;
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000773
774
775 have_sfnt = have_lwfn = 0;
776
Werner Lemberge2455ba2004-02-26 21:56:27 +0000777 HLock( fond );
778 parse_fond( *fond, &have_sfnt, &sfnt_id, lwfn_file_name, 0 );
779 HUnlock( fond );
780
781 if ( lwfn_file_name[0] )
782 {
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000783 err = lookup_lwfn_by_fond( pathname, lwfn_file_name,
Werner Lemberg435046b2006-01-11 10:57:42 +0000784 buff, sizeof ( buff ) );
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000785 if ( FT_Err_Ok == err )
786 have_lwfn = 1;
Werner Lemberge2455ba2004-02-26 21:56:27 +0000787 }
788
789 if ( have_lwfn && ( !have_sfnt || PREFER_LWFN ) )
790 return 1;
791 else
Suzuki, Toshiya (鈴木俊哉)53be6e92005-12-23 12:22:46 +0000792 return count_faces_scalable( *fond );
Werner Lemberge2455ba2004-02-26 21:56:27 +0000793 }
794
795
Just van Rossumae4bcee2000-07-28 01:10:35 +0000796 /* Read Type 1 data from the POST resources inside the LWFN file,
Werner Lemberg435046b2006-01-11 10:57:42 +0000797 return a PFB buffer. This is somewhat convoluted because the FT2
Just van Rossumae4bcee2000-07-28 01:10:35 +0000798 PFB parser wants the ASCII header as one chunk, and the LWFN
Werner Lemberg435046b2006-01-11 10:57:42 +0000799 chunks are often not organized that way, so we glue chunks
Just van Rossumae4bcee2000-07-28 01:10:35 +0000800 of the same type together. */
Werner Lembergf814d0f2001-06-27 16:18:10 +0000801 static FT_Error
802 read_lwfn( FT_Memory memory,
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000803 short res,
Werner Lembergf814d0f2001-06-27 16:18:10 +0000804 FT_Byte** pfb_data,
805 FT_ULong* size )
Just van Rossumae4bcee2000-07-28 01:10:35 +0000806 {
807 FT_Error error = FT_Err_Ok;
Werner Lemberge2455ba2004-02-26 21:56:27 +0000808 short res_id;
Werner Lemberg9ca7a152002-04-30 14:26:49 +0000809 unsigned char *buffer, *p, *size_p = NULL;
Just van Rossumae4bcee2000-07-28 01:10:35 +0000810 FT_ULong total_size = 0;
811 FT_ULong post_size, pfb_chunk_size;
812 Handle post_data;
813 char code, last_code;
814
815
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000816 UseResFile( res );
Just van Rossumae4bcee2000-07-28 01:10:35 +0000817
Werner Lemberge2455ba2004-02-26 21:56:27 +0000818 /* First pass: load all POST resources, and determine the size of */
819 /* the output buffer. */
Werner Lemberg9ca7a152002-04-30 14:26:49 +0000820 res_id = 501;
Just van Rossumae4bcee2000-07-28 01:10:35 +0000821 last_code = -1;
Werner Lemberg05c21b82000-07-29 20:38:19 +0000822
Just van Rossumae4bcee2000-07-28 01:10:35 +0000823 for (;;)
824 {
825 post_data = Get1Resource( 'POST', res_id++ );
826 if ( post_data == NULL )
Werner Lemberg435046b2006-01-11 10:57:42 +0000827 break; /* we are done */
Just van Rossumae4bcee2000-07-28 01:10:35 +0000828
829 code = (*post_data)[0];
830
831 if ( code != last_code )
832 {
833 if ( code == 5 )
834 total_size += 2; /* just the end code */
835 else
836 total_size += 6; /* code + 4 bytes chunk length */
837 }
838
839 total_size += GetHandleSize( post_data ) - 2;
840 last_code = code;
841 }
842
David Turnere459d742002-03-22 13:52:37 +0000843 if ( FT_ALLOC( buffer, (FT_Long)total_size ) )
Just van Rossumae4bcee2000-07-28 01:10:35 +0000844 goto Error;
845
Werner Lemberge2455ba2004-02-26 21:56:27 +0000846 /* Second pass: append all POST data to the buffer, add PFB fields. */
847 /* Glue all consecutive chunks of the same type together. */
Werner Lemberg9ca7a152002-04-30 14:26:49 +0000848 p = buffer;
849 res_id = 501;
850 last_code = -1;
Just van Rossumae4bcee2000-07-28 01:10:35 +0000851 pfb_chunk_size = 0;
852
853 for (;;)
854 {
855 post_data = Get1Resource( 'POST', res_id++ );
856 if ( post_data == NULL )
Werner Lemberg435046b2006-01-11 10:57:42 +0000857 break; /* we are done */
Just van Rossumae4bcee2000-07-28 01:10:35 +0000858
859 post_size = (FT_ULong)GetHandleSize( post_data ) - 2;
860 code = (*post_data)[0];
861
862 if ( code != last_code )
863 {
Just van Rossumae4bcee2000-07-28 01:10:35 +0000864 if ( last_code != -1 )
865 {
Werner Lemberg435046b2006-01-11 10:57:42 +0000866 /* we are done adding a chunk, fill in the size field */
Werner Lemberg9ca7a152002-04-30 14:26:49 +0000867 if ( size_p != NULL )
868 {
869 *size_p++ = (FT_Byte)( pfb_chunk_size & 0xFF );
870 *size_p++ = (FT_Byte)( ( pfb_chunk_size >> 8 ) & 0xFF );
871 *size_p++ = (FT_Byte)( ( pfb_chunk_size >> 16 ) & 0xFF );
872 *size_p++ = (FT_Byte)( ( pfb_chunk_size >> 24 ) & 0xFF );
873 }
Just van Rossumae4bcee2000-07-28 01:10:35 +0000874 pfb_chunk_size = 0;
875 }
876
877 *p++ = 0x80;
878 if ( code == 5 )
879 *p++ = 0x03; /* the end */
880 else if ( code == 2 )
881 *p++ = 0x02; /* binary segment */
882 else
883 *p++ = 0x01; /* ASCII segment */
884
885 if ( code != 5 )
886 {
887 size_p = p; /* save for later */
888 p += 4; /* make space for size field */
889 }
890 }
891
David Turnerd15bc0d2002-04-12 09:31:48 +0000892 ft_memcpy( p, *post_data + 2, post_size );
Just van Rossumae4bcee2000-07-28 01:10:35 +0000893 pfb_chunk_size += post_size;
894 p += post_size;
895 last_code = code;
896 }
897
898 *pfb_data = buffer;
899 *size = total_size;
900
Werner Lemberg05c21b82000-07-29 20:38:19 +0000901 Error:
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000902 CloseResFile( res );
Just van Rossumae4bcee2000-07-28 01:10:35 +0000903 return error;
904 }
905
906
907 /* Finalizer for a memory stream; gets called by FT_Done_Face().
908 It frees the memory it uses. */
Werner Lembergf814d0f2001-06-27 16:18:10 +0000909 static void
910 memory_stream_close( FT_Stream stream )
Just van Rossumae4bcee2000-07-28 01:10:35 +0000911 {
912 FT_Memory memory = stream->memory;
913
914
David Turnere459d742002-03-22 13:52:37 +0000915 FT_FREE( stream->base );
Werner Lemberg05c21b82000-07-29 20:38:19 +0000916
917 stream->size = 0;
918 stream->base = 0;
919 stream->close = 0;
Just van Rossumae4bcee2000-07-28 01:10:35 +0000920 }
921
922
923 /* Create a new memory stream from a buffer and a size. */
Werner Lembergf814d0f2001-06-27 16:18:10 +0000924 static FT_Error
Werner Lemberg9ca7a152002-04-30 14:26:49 +0000925 new_memory_stream( FT_Library library,
926 FT_Byte* base,
927 FT_ULong size,
928 FT_Stream_CloseFunc close,
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000929 FT_Stream* astream )
Just van Rossumae4bcee2000-07-28 01:10:35 +0000930 {
Werner Lemberg9ca7a152002-04-30 14:26:49 +0000931 FT_Error error;
932 FT_Memory memory;
933 FT_Stream stream;
Just van Rossumae4bcee2000-07-28 01:10:35 +0000934
935
Werner Lemberg9ca7a152002-04-30 14:26:49 +0000936 if ( !library )
937 return FT_Err_Invalid_Library_Handle;
Just van Rossumae4bcee2000-07-28 01:10:35 +0000938
Werner Lemberg9ca7a152002-04-30 14:26:49 +0000939 if ( !base )
940 return FT_Err_Invalid_Argument;
Just van Rossumae4bcee2000-07-28 01:10:35 +0000941
Werner Lemberg9ca7a152002-04-30 14:26:49 +0000942 *astream = 0;
943 memory = library->memory;
944 if ( FT_NEW( stream ) )
945 goto Exit;
Just van Rossumae4bcee2000-07-28 01:10:35 +0000946
Werner Lemberg9ca7a152002-04-30 14:26:49 +0000947 FT_Stream_OpenMemory( stream, base, size );
Just van Rossumae4bcee2000-07-28 01:10:35 +0000948
Werner Lemberg9ca7a152002-04-30 14:26:49 +0000949 stream->close = close;
Just van Rossumae4bcee2000-07-28 01:10:35 +0000950
Werner Lemberg9ca7a152002-04-30 14:26:49 +0000951 *astream = stream;
Just van Rossumae4bcee2000-07-28 01:10:35 +0000952
Werner Lemberg9ca7a152002-04-30 14:26:49 +0000953 Exit:
954 return error;
Just van Rossumae4bcee2000-07-28 01:10:35 +0000955 }
956
957
958 /* Create a new FT_Face given a buffer and a driver name. */
Werner Lembergf814d0f2001-06-27 16:18:10 +0000959 static FT_Error
960 open_face_from_buffer( FT_Library library,
961 FT_Byte* base,
962 FT_ULong size,
963 FT_Long face_index,
964 char* driver_name,
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +0000965 FT_Face* aface )
Just van Rossumae4bcee2000-07-28 01:10:35 +0000966 {
967 FT_Open_Args args;
968 FT_Error error;
969 FT_Stream stream;
970 FT_Memory memory = library->memory;
971
972
973 error = new_memory_stream( library,
974 base,
975 size,
976 memory_stream_close,
977 &stream );
978 if ( error )
979 {
David Turnere459d742002-03-22 13:52:37 +0000980 FT_FREE( base );
Just van Rossumae4bcee2000-07-28 01:10:35 +0000981 return error;
982 }
983
Werner Lemberg435046b2006-01-11 10:57:42 +0000984 args.flags = FT_OPEN_STREAM;
Just van Rossumae4bcee2000-07-28 01:10:35 +0000985 args.stream = stream;
986 if ( driver_name )
987 {
Werner Lemberg435046b2006-01-11 10:57:42 +0000988 args.flags = args.flags | FT_OPEN_DRIVER;
Just van Rossumae4bcee2000-07-28 01:10:35 +0000989 args.driver = FT_Get_Module( library, driver_name );
990 }
Werner Lemberg05c21b82000-07-29 20:38:19 +0000991
Werner Lemberg2630e542004-03-20 14:26:38 +0000992 /* At this point, face_index has served its purpose; */
993 /* whoever calls this function has already used it to */
994 /* locate the correct font data. We should not propagate */
995 /* this index to FT_Open_Face() (unless it is negative). */
996
997 if ( face_index > 0 )
998 face_index = 0;
999
Just van Rossumae4bcee2000-07-28 01:10:35 +00001000 error = FT_Open_Face( library, &args, face_index, aface );
Just van Rossum5fe94ff2000-07-28 02:25:23 +00001001 if ( error == FT_Err_Ok )
Just van Rossumae4bcee2000-07-28 01:10:35 +00001002 (*aface)->face_flags &= ~FT_FACE_FLAG_EXTERNAL_STREAM;
Werner Lemberg9ca7a152002-04-30 14:26:49 +00001003
Just van Rossumae4bcee2000-07-28 01:10:35 +00001004 return error;
1005 }
1006
1007
1008 /* Create a new FT_Face from a file spec to an LWFN file. */
Werner Lembergf814d0f2001-06-27 16:18:10 +00001009 static FT_Error
Werner Lemberg435046b2006-01-11 10:57:42 +00001010 FT_New_Face_From_LWFN( FT_Library library,
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +00001011 const UInt8* pathname,
Werner Lemberg435046b2006-01-11 10:57:42 +00001012 FT_Long face_index,
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +00001013 FT_Face* aface )
Just van Rossumae4bcee2000-07-28 01:10:35 +00001014 {
Werner Lemberg9ca7a152002-04-30 14:26:49 +00001015 FT_Byte* pfb_data;
1016 FT_ULong pfb_size;
1017 FT_Error error;
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +00001018 short res;
Just van Rossumae4bcee2000-07-28 01:10:35 +00001019
1020
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +00001021 if ( noErr != FT_FSPathMakeRes( pathname, &res ) )
1022 return FT_Err_Cannot_Open_Resource;
Werner Lemberge2455ba2004-02-26 21:56:27 +00001023
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +00001024 pfb_data = NULL;
1025 pfb_size = 0;
1026 error = read_lwfn( library->memory, res, &pfb_data, &pfb_size );
1027 CloseResFile( res ); /* PFB is already loaded, useless anymore */
Just van Rossumae4bcee2000-07-28 01:10:35 +00001028 if ( error )
1029 return error;
1030
Just van Rossumae4bcee2000-07-28 01:10:35 +00001031 return open_face_from_buffer( library,
1032 pfb_data,
1033 pfb_size,
1034 face_index,
1035 "type1",
1036 aface );
1037 }
1038
1039
1040 /* Create a new FT_Face from an SFNT resource, specified by res ID. */
Werner Lembergf814d0f2001-06-27 16:18:10 +00001041 static FT_Error
1042 FT_New_Face_From_SFNT( FT_Library library,
1043 short sfnt_id,
1044 FT_Long face_index,
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +00001045 FT_Face* aface )
Just van Rossumae4bcee2000-07-28 01:10:35 +00001046 {
Werner Lemberg05c21b82000-07-29 20:38:19 +00001047 Handle sfnt = NULL;
1048 FT_Byte* sfnt_data;
1049 size_t sfnt_size;
Werner Lemberg435046b2006-01-11 10:57:42 +00001050 FT_Error error = FT_Err_Ok;
Werner Lemberg05c21b82000-07-29 20:38:19 +00001051 FT_Memory memory = library->memory;
Werner Lembergc70818a2003-05-15 06:44:09 +00001052 int is_cff;
Just van Rossumae4bcee2000-07-28 01:10:35 +00001053
1054
1055 sfnt = GetResource( 'sfnt', sfnt_id );
1056 if ( ResError() )
1057 return FT_Err_Invalid_Handle;
1058
1059 sfnt_size = (FT_ULong)GetHandleSize( sfnt );
David Turnere459d742002-03-22 13:52:37 +00001060 if ( FT_ALLOC( sfnt_data, (FT_Long)sfnt_size ) )
Just van Rossumae4bcee2000-07-28 01:10:35 +00001061 {
1062 ReleaseResource( sfnt );
1063 return error;
1064 }
1065
1066 HLock( sfnt );
David Turnerd15bc0d2002-04-12 09:31:48 +00001067 ft_memcpy( sfnt_data, *sfnt, sfnt_size );
Just van Rossumae4bcee2000-07-28 01:10:35 +00001068 HUnlock( sfnt );
1069 ReleaseResource( sfnt );
1070
Werner Lemberg756655b2003-06-07 05:13:22 +00001071 is_cff = sfnt_size > 4 && sfnt_data[0] == 'O' &&
1072 sfnt_data[1] == 'T' &&
1073 sfnt_data[2] == 'T' &&
1074 sfnt_data[3] == 'O';
Werner Lembergc70818a2003-05-15 06:44:09 +00001075
Just van Rossumae4bcee2000-07-28 01:10:35 +00001076 return open_face_from_buffer( library,
1077 sfnt_data,
1078 sfnt_size,
1079 face_index,
Werner Lembergc70818a2003-05-15 06:44:09 +00001080 is_cff ? "cff" : "truetype",
Just van Rossumae4bcee2000-07-28 01:10:35 +00001081 aface );
1082 }
1083
1084
1085 /* Create a new FT_Face from a file spec to a suitcase file. */
Werner Lembergf814d0f2001-06-27 16:18:10 +00001086 static FT_Error
Werner Lemberg435046b2006-01-11 10:57:42 +00001087 FT_New_Face_From_Suitcase( FT_Library library,
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +00001088 const UInt8* pathname,
Werner Lemberg435046b2006-01-11 10:57:42 +00001089 FT_Long face_index,
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +00001090 FT_Face* aface )
Just van Rossumae4bcee2000-07-28 01:10:35 +00001091 {
Suzuki, Toshiya (鈴木俊哉)53be6e92005-12-23 12:22:46 +00001092 FT_Error error = FT_Err_Cannot_Open_Resource;
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +00001093 short res_ref, res_index;
Just van Rossumae4bcee2000-07-28 01:10:35 +00001094 Handle fond;
Suzuki, Toshiya (鈴木俊哉)53be6e92005-12-23 12:22:46 +00001095 short num_faces_in_res, num_faces_in_fond;
Just van Rossumae4bcee2000-07-28 01:10:35 +00001096
1097
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +00001098 if ( noErr != FT_FSPathMakeRes( pathname, &res_ref ) )
1099 return FT_Err_Cannot_Open_Resource;
1100
Just van Rossumae4bcee2000-07-28 01:10:35 +00001101 UseResFile( res_ref );
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +00001102 if ( ResError() )
1103 return FT_Err_Cannot_Open_Resource;
Just van Rossumae4bcee2000-07-28 01:10:35 +00001104
Suzuki, Toshiya (鈴木俊哉)53be6e92005-12-23 12:22:46 +00001105 num_faces_in_res = 0;
Werner Lemberge2455ba2004-02-26 21:56:27 +00001106 for ( res_index = 1; ; ++res_index )
Just van Rossumae4bcee2000-07-28 01:10:35 +00001107 {
Werner Lemberge2455ba2004-02-26 21:56:27 +00001108 fond = Get1IndResource( 'FOND', res_index );
1109 if ( ResError() )
Werner Lemberge2455ba2004-02-26 21:56:27 +00001110 break;
1111
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +00001112 num_faces_in_fond = count_faces( fond, pathname );
Suzuki, Toshiya (鈴木俊哉)53be6e92005-12-23 12:22:46 +00001113 num_faces_in_res += num_faces_in_fond;
Werner Lemberge2455ba2004-02-26 21:56:27 +00001114
Suzuki, Toshiya (鈴木俊哉)53be6e92005-12-23 12:22:46 +00001115 if ( 0 <= face_index && face_index < num_faces_in_fond && error )
1116 error = FT_New_Face_From_FOND( library, fond, face_index, aface );
Werner Lemberg435046b2006-01-11 10:57:42 +00001117
Suzuki, Toshiya (鈴木俊哉)53be6e92005-12-23 12:22:46 +00001118 face_index -= num_faces_in_fond;
Just van Rossumae4bcee2000-07-28 01:10:35 +00001119 }
1120
Just van Rossumae4bcee2000-07-28 01:10:35 +00001121 CloseResFile( res_ref );
Suzuki, Toshiya (鈴木俊哉)53be6e92005-12-23 12:22:46 +00001122 if ( FT_Err_Ok == error && NULL != aface )
1123 (*aface)->num_faces = num_faces_in_res;
Just van Rossumae4bcee2000-07-28 01:10:35 +00001124 return error;
1125 }
1126
Werner Lemberge9e130c2001-12-07 21:56:32 +00001127
Werner Lemberg9ca7a152002-04-30 14:26:49 +00001128 /* documentation is in ftmac.h */
Werner Lemberg90a03302000-11-07 17:21:11 +00001129
Werner Lembergf814d0f2001-06-27 16:18:10 +00001130 FT_EXPORT_DEF( FT_Error )
1131 FT_New_Face_From_FOND( FT_Library library,
1132 Handle fond,
1133 FT_Long face_index,
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +00001134 FT_Face* aface )
Just van Rossumae4bcee2000-07-28 01:10:35 +00001135 {
Werner Lemberg435046b2006-01-11 10:57:42 +00001136 short sfnt_id, have_sfnt, have_lwfn = 0;
1137 short fond_id;
1138 OSType fond_type;
1139 Str255 fond_name;
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +00001140 Str255 lwfn_file_name;
1141 UInt8 path_lwfn[HFS_MAXPATHLEN];
1142 OSErr err;
1143 FT_Error error;
Just van Rossumae4bcee2000-07-28 01:10:35 +00001144
1145
Werner Lembergc3b21602001-12-05 01:22:05 +00001146 GetResInfo( fond, &fond_id, &fond_type, fond_name );
Just van Rossumae4bcee2000-07-28 01:10:35 +00001147 if ( ResError() != noErr || fond_type != 'FOND' )
1148 return FT_Err_Invalid_File_Format;
1149
1150 HLock( fond );
Leonard Rosentholae340bb2001-10-26 13:24:39 +00001151 parse_fond( *fond, &have_sfnt, &sfnt_id, lwfn_file_name, face_index );
Just van Rossumae4bcee2000-07-28 01:10:35 +00001152 HUnlock( fond );
1153
1154 if ( lwfn_file_name[0] )
1155 {
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +00001156 short res;
1157
1158
1159 res = HomeResFile( fond );
1160 if ( noErr != ResError() )
1161 goto found_no_lwfn_file;
1162
1163#if HAVE_FSREF
Werner Lemberg435046b2006-01-11 10:57:42 +00001164
1165 {
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +00001166 UInt8 path_fond[HFS_MAXPATHLEN];
1167 FSRef ref;
1168
Werner Lemberg435046b2006-01-11 10:57:42 +00001169
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +00001170 err = FSGetForkCBInfo( res, kFSInvalidVolumeRefNum,
1171 NULL, NULL, NULL, &ref, NULL );
1172 if ( noErr != err )
1173 goto found_no_lwfn_file;
1174
Werner Lemberg435046b2006-01-11 10:57:42 +00001175 err = FSRefMakePath( &ref, path_fond, sizeof ( path_fond ) );
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +00001176 if ( noErr != err )
1177 goto found_no_lwfn_file;
1178
1179 error = lookup_lwfn_by_fond( path_fond, lwfn_file_name,
Werner Lemberg435046b2006-01-11 10:57:42 +00001180 path_lwfn, sizeof ( path_lwfn ) );
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +00001181 if ( FT_Err_Ok == error )
1182 have_lwfn = 1;
1183 }
Werner Lemberg435046b2006-01-11 10:57:42 +00001184
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +00001185#elif HAVE_FSSPEC
Werner Lemberg435046b2006-01-11 10:57:42 +00001186
1187 {
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +00001188 UInt8 path_fond[HFS_MAXPATHLEN];
1189 FCBPBRec pb;
1190 Str255 fond_file_name;
1191 FSSpec spec;
1192
1193
Werner Lemberg435046b2006-01-11 10:57:42 +00001194 FT_MEM_SET( &spec, 0, sizeof ( FSSpec ) );
1195 FT_MEM_SET( &pb, 0, sizeof ( FCBPBRec ) );
1196
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +00001197 pb.ioNamePtr = fond_file_name;
1198 pb.ioVRefNum = 0;
1199 pb.ioRefNum = res;
1200 pb.ioFCBIndx = 0;
1201
1202 err = PBGetFCBInfoSync( &pb );
1203 if ( noErr != err )
1204 goto found_no_lwfn_file;
1205
Werner Lemberg435046b2006-01-11 10:57:42 +00001206 err = FSMakeFSSpec( pb.ioFCBVRefNum, pb.ioFCBParID,
1207 fond_file_name, &spec );
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +00001208 if ( noErr != err )
1209 goto found_no_lwfn_file;
1210
Werner Lemberg435046b2006-01-11 10:57:42 +00001211 err = FT_FSpMakePath( &spec, path_fond, sizeof ( path_fond ) );
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +00001212 if ( noErr != err )
1213 goto found_no_lwfn_file;
1214
1215 error = lookup_lwfn_by_fond( path_fond, lwfn_file_name,
Werner Lemberg435046b2006-01-11 10:57:42 +00001216 path_lwfn, sizeof ( path_lwfn ) );
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +00001217 if ( FT_Err_Ok == error )
1218 have_lwfn = 1;
Werner Lemberg435046b2006-01-11 10:57:42 +00001219 }
1220
1221#endif /* HAVE_FSREF, HAVE_FSSPEC */
1222
1223 }
Just van Rossumae4bcee2000-07-28 01:10:35 +00001224
1225 if ( have_lwfn && ( !have_sfnt || PREFER_LWFN ) )
1226 return FT_New_Face_From_LWFN( library,
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +00001227 path_lwfn,
Just van Rossumae4bcee2000-07-28 01:10:35 +00001228 face_index,
1229 aface );
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +00001230
Werner Lemberg435046b2006-01-11 10:57:42 +00001231 found_no_lwfn_file:
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +00001232 if ( have_sfnt )
Just van Rossumae4bcee2000-07-28 01:10:35 +00001233 return FT_New_Face_From_SFNT( library,
1234 sfnt_id,
1235 face_index,
1236 aface );
1237
Werner Lemberg435046b2006-01-11 10:57:42 +00001238 return FT_Err_Unknown_File_Format;
Werner Lemberge9e130c2001-12-07 21:56:32 +00001239 }
1240
Werner Lembergca7ef5e2004-02-28 19:12:01 +00001241
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +00001242 /* Common function to load a new FT_Face from a resource file. */
Werner Lembergca7ef5e2004-02-28 19:12:01 +00001243 static FT_Error
Werner Lemberg435046b2006-01-11 10:57:42 +00001244 FT_New_Face_From_Resource( FT_Library library,
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +00001245 const UInt8* pathname,
Werner Lemberg435046b2006-01-11 10:57:42 +00001246 FT_Long face_index,
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +00001247 FT_Face* aface )
Werner Lembergca7ef5e2004-02-28 19:12:01 +00001248 {
1249 OSType file_type;
Werner Lembergca7ef5e2004-02-28 19:12:01 +00001250 FT_Error error;
1251
1252
Werner Lemberg435046b2006-01-11 10:57:42 +00001253 /* LWFN is a (very) specific file format, check for it explicitly */
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +00001254 file_type = get_file_type_from_path( pathname );
Werner Lemberg435046b2006-01-11 10:57:42 +00001255 if ( file_type == 'LWFN' )
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +00001256 return FT_New_Face_From_LWFN( library, pathname, face_index, aface );
Werner Lemberg435046b2006-01-11 10:57:42 +00001257
1258 /* Otherwise the file type doesn't matter (there are more than */
1259 /* `FFIL' and `tfil'). Just try opening it as a font suitcase; */
1260 /* if it works, fine. */
Werner Lembergca7ef5e2004-02-28 19:12:01 +00001261
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +00001262 error = FT_New_Face_From_Suitcase( library, pathname, face_index, aface );
Werner Lemberg435046b2006-01-11 10:57:42 +00001263 if ( error == 0 )
1264 return error;
Werner Lembergca7ef5e2004-02-28 19:12:01 +00001265
Werner Lembergca7ef5e2004-02-28 19:12:01 +00001266 /* let it fall through to normal loader (.ttf, .otf, etc.); */
1267 /* we signal this by returning no error and no FT_Face */
1268 *aface = NULL;
1269 return 0;
1270 }
1271
Just van Rossumae4bcee2000-07-28 01:10:35 +00001272
1273 /*************************************************************************/
1274 /* */
1275 /* <Function> */
1276 /* FT_New_Face */
1277 /* */
1278 /* <Description> */
1279 /* This is the Mac-specific implementation of FT_New_Face. In */
Werner Lemberg05c21b82000-07-29 20:38:19 +00001280 /* addition to the standard FT_New_Face() functionality, it also */
Just van Rossumae4bcee2000-07-28 01:10:35 +00001281 /* accepts pathnames to Mac suitcase files. For further */
Werner Lemberg90a03302000-11-07 17:21:11 +00001282 /* documentation see the original FT_New_Face() in freetype.h. */
Just van Rossumae4bcee2000-07-28 01:10:35 +00001283 /* */
Werner Lembergf814d0f2001-06-27 16:18:10 +00001284 FT_EXPORT_DEF( FT_Error )
1285 FT_New_Face( FT_Library library,
1286 const char* pathname,
1287 FT_Long face_index,
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +00001288 FT_Face* aface )
Just van Rossumae4bcee2000-07-28 01:10:35 +00001289 {
1290 FT_Open_Args args;
Werner Lembergca7ef5e2004-02-28 19:12:01 +00001291 FT_Error error;
Just van Rossumae4bcee2000-07-28 01:10:35 +00001292
1293
1294 /* test for valid `library' and `aface' delayed to FT_Open_Face() */
1295 if ( !pathname )
1296 return FT_Err_Invalid_Argument;
1297
Werner Lemberg435046b2006-01-11 10:57:42 +00001298 error = FT_Err_Ok;
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +00001299 *aface = NULL;
Just van Rossumae4bcee2000-07-28 01:10:35 +00001300
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +00001301 /* try resourcefork based font: LWFN, FFIL */
Werner Lemberg435046b2006-01-11 10:57:42 +00001302 error = FT_New_Face_From_Resource( library, (UInt8 *)pathname,
1303 face_index, aface );
Werner Lembergca7ef5e2004-02-28 19:12:01 +00001304 if ( error != 0 || *aface != NULL )
1305 return error;
Werner Lemberg9ca7a152002-04-30 14:26:49 +00001306
Werner Lemberg9ca7a152002-04-30 14:26:49 +00001307 /* let it fall through to normal loader (.ttf, .otf, etc.) */
David Turnerb08fe2d2002-08-27 20:20:29 +00001308 args.flags = FT_OPEN_PATHNAME;
Werner Lemberg9ca7a152002-04-30 14:26:49 +00001309 args.pathname = (char*)pathname;
1310 return FT_Open_Face( library, &args, face_index, aface );
Just van Rossumae4bcee2000-07-28 01:10:35 +00001311 }
1312
Werner Lemberg05c21b82000-07-29 20:38:19 +00001313
Werner Lemberge2455ba2004-02-26 21:56:27 +00001314 /*************************************************************************/
1315 /* */
1316 /* <Function> */
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +00001317 /* FT_New_Face_From_FSRef */
1318 /* */
1319 /* <Description> */
1320 /* FT_New_Face_From_FSRef is identical to FT_New_Face except it */
1321 /* accepts an FSRef instead of a path. */
1322 /* */
1323 FT_EXPORT_DEF( FT_Error )
1324 FT_New_Face_From_FSRef( FT_Library library,
1325 const FSRef* ref,
Werner Lemberg435046b2006-01-11 10:57:42 +00001326 FT_Long face_index,
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +00001327 FT_Face* aface )
1328 {
Werner Lemberg435046b2006-01-11 10:57:42 +00001329
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +00001330#if !HAVE_FSREF
Werner Lemberg435046b2006-01-11 10:57:42 +00001331
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +00001332 return FT_Err_Unimplemented_Feature;
Werner Lemberg435046b2006-01-11 10:57:42 +00001333
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +00001334#else
Werner Lemberg435046b2006-01-11 10:57:42 +00001335
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +00001336 FT_Error error;
1337 FT_Open_Args args;
1338 OSErr err;
1339 UInt8 pathname[HFS_MAXPATHLEN];
1340
1341
1342 if ( !ref )
1343 return FT_Err_Invalid_Argument;
1344
1345 err = FSRefMakePath( ref, pathname, sizeof ( pathname ) );
1346 if ( err )
1347 error = FT_Err_Cannot_Open_Resource;
1348
1349 error = FT_New_Face_From_Resource( library, pathname, face_index, aface );
1350 if ( error != 0 || *aface != NULL )
1351 return error;
1352
1353 /* fallback to datafork font */
1354 args.flags = FT_OPEN_PATHNAME;
1355 args.pathname = (char*)pathname;
1356 return FT_Open_Face( library, &args, face_index, aface );
Werner Lemberg435046b2006-01-11 10:57:42 +00001357
1358#endif /* HAVE_FSREF */
1359
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +00001360 }
1361
1362
1363 /*************************************************************************/
1364 /* */
1365 /* <Function> */
Werner Lemberge2455ba2004-02-26 21:56:27 +00001366 /* FT_New_Face_From_FSSpec */
1367 /* */
1368 /* <Description> */
1369 /* FT_New_Face_From_FSSpec is identical to FT_New_Face except it */
1370 /* accepts an FSSpec instead of a path. */
1371 /* */
1372 FT_EXPORT_DEF( FT_Error )
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +00001373 FT_New_Face_From_FSSpec( FT_Library library,
1374 const FSSpec* spec,
1375 FT_Long face_index,
1376 FT_Face* aface )
Werner Lemberg435046b2006-01-11 10:57:42 +00001377 {
1378
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +00001379#if HAVE_FSREF
Werner Lemberg435046b2006-01-11 10:57:42 +00001380
1381 FSRef ref;
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +00001382
1383
1384 if ( !spec || FSpMakeFSRef( spec, &ref ) != noErr )
1385 return FT_Err_Invalid_Argument;
1386 else
1387 return FT_New_Face_From_FSRef( library, &ref, face_index, aface );
Werner Lemberg435046b2006-01-11 10:57:42 +00001388
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +00001389#elif HAVE_FSSPEC
Werner Lemberg435046b2006-01-11 10:57:42 +00001390
Werner Lembergb2c40b52004-08-28 08:02:46 +00001391 FT_Error error;
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +00001392 FT_Open_Args args;
Werner Lemberg435046b2006-01-11 10:57:42 +00001393 OSErr err;
1394 UInt8 pathname[HFS_MAXPATHLEN];
Werner Lemberge2455ba2004-02-26 21:56:27 +00001395
1396
Werner Lemberge2455ba2004-02-26 21:56:27 +00001397 if ( !spec )
1398 return FT_Err_Invalid_Argument;
1399
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +00001400 err = FT_FSpMakePath( spec, pathname, sizeof ( pathname ) );
Werner Lemberg435046b2006-01-11 10:57:42 +00001401 if ( err )
1402 error = FT_Err_Cannot_Open_Resource;
Werner Lemberge2455ba2004-02-26 21:56:27 +00001403
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +00001404 error = FT_New_Face_From_Resource( library, pathname, face_index, aface );
1405 if ( error != 0 || *aface != NULL )
Werner Lemberg435046b2006-01-11 10:57:42 +00001406 return error;
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +00001407
1408 /* fallback to datafork font */
1409 args.flags = FT_OPEN_PATHNAME;
1410 args.pathname = (char*)pathname;
1411 return FT_Open_Face( library, &args, face_index, aface );
Werner Lemberg435046b2006-01-11 10:57:42 +00001412
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +00001413#else
Werner Lemberg435046b2006-01-11 10:57:42 +00001414
Suzuki, Toshiya (鈴木俊哉)f8d16cc2006-01-11 09:28:38 +00001415 return FT_Err_Unimplemented_Feature;
Werner Lemberg435046b2006-01-11 10:57:42 +00001416
1417#endif /* HAVE_FSREF, HAVE_FSSPEC */
1418
Werner Lemberge2455ba2004-02-26 21:56:27 +00001419 }
1420
1421
Werner Lemberg05c21b82000-07-29 20:38:19 +00001422/* END */