blob: 6feaa31e684e250cc896da8b7ee5ba6991c2513b [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. */
Just van Rossumae4bcee2000-07-28 01:10:35 +00006/* */
7/* Copyright 1996-2000 by */
8/* Just van Rossum, David Turner, Robert Wilhelm, and Werner Lemberg. */
9/* */
10/* This file is part of the FreeType project, and may only be used, */
11/* modified, and distributed under the terms of the FreeType project */
12/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
13/* this file you indicate that you have read the license and */
14/* understand and accept it fully. */
15/* */
16/***************************************************************************/
17
18
19 /*
20 Notes
21
22 Mac suitcase files can (and often do!) contain multiple fonts. To
23 support this I use the face_index argument of FT_(Open|New)_Face()
24 functions, and pretend the suitcase file is a collection.
25 Warning: although the FOND driver sets face->num_faces field to the
26 number of available fonts, but the Type 1 driver sets it to 1 anyway.
27 So this field is currently not reliable, and I don't see a clean way
28 to resolve that. The face_index argument translates to
29 Get1IndResource( 'FOND', face_index + 1 );
30 so clients should figure out the resource index of the FOND.
31 (I'll try to provide some example code for this at some point.)
32
33
34 The Mac FOND support works roughly like this:
35
36 - Check whether the offered stream points to a Mac suitcase file.
37 This is done by checking the file type: it has to be 'FFIL' or 'tfil'.
38 The stream that gets passed to our init_face() routine is a stdio
39 stream, which isn't usable for us, since the FOND resources live
40 in the resource fork. So we just grab the stream->pathname field.
41
42 - Read the FOND resource into memory, then check whether there is
43 a TrueType font and/or (!) a Type 1 font available.
44
45 - If there is a Type 1 font available (as a separate 'LWFN' file),
46 read its data into memory, massage it slightly so it becomes
47 PFB data, wrap it into a memory stream, load the Type 1 driver
48 and delegate the rest of the work to it by calling FT_Open_Face().
49 (XXX TODO: after this has been done, the kerning data from the FOND
50 resource should be appended to the face: on the Mac there are usually
51 no AFM files available. However, this is tricky since we need to map
52 Mac char codes to ps glyph names to glyph ID's...)
53
54 - If there is a TrueType font (an 'sfnt' resource), read it into
55 memory, wrap it into a memory stream, load the TrueType driver
56 and delegate the rest of the work to it, by calling FT_Open_Face().
57 */
58
59#include <freetype/freetype.h>
60#include <freetype/internal/ftstream.h>
61#include <truetype/ttobjs.h>
Werner Lembergb5084e12000-10-28 17:10:06 +000062#include <type1/t1objs.h>
Just van Rossumae4bcee2000-07-28 01:10:35 +000063
64#include <Resources.h>
65#include <Fonts.h>
66#include <Errors.h>
67
68#include <ctype.h> /* for isupper() and isalnum() */
69
70#include <ftmac.h>
71
72
73
74 /* Set PREFER_LWFN to 1 if LWFN (Type 1) is preferred over
75 TrueType in case *both* are available (this is not common,
76 but it *is* possible). */
77#ifndef PREFER_LWFN
78#define PREFER_LWFN 1
79#endif
80
81
82
Werner Lemberg05c21b82000-07-29 20:38:19 +000083 /* Quick'n'dirty Pascal string to C string converter.
Just van Rossumae4bcee2000-07-28 01:10:35 +000084 Warning: this call is not thread safe! Use with caution. */
85 static
Werner Lemberg05c21b82000-07-29 20:38:19 +000086 char* p2c_str( unsigned char* pstr )
Just van Rossumae4bcee2000-07-28 01:10:35 +000087 {
Werner Lemberg05c21b82000-07-29 20:38:19 +000088 static char cstr[256];
Just van Rossumae4bcee2000-07-28 01:10:35 +000089
90
Werner Lemberg05c21b82000-07-29 20:38:19 +000091 strncpy( cstr, (char*)pstr + 1, pstr[0] );
Just van Rossumae4bcee2000-07-28 01:10:35 +000092 cstr[pstr[0]] = '\0';
93 return cstr;
94 }
95
96
97 /* Given a pathname, fill in a file spec. */
98 static
Werner Lemberg05c21b82000-07-29 20:38:19 +000099 int file_spec_from_path( const char* pathname,
100 FSSpec* spec )
Just van Rossumae4bcee2000-07-28 01:10:35 +0000101 {
102 Str255 p_path;
103 FT_ULong path_len;
104
105
106 /* convert path to a pascal string */
107 path_len = strlen( pathname );
108 if ( path_len > 255 )
109 return -1;
110 p_path[0] = (unsigned char)path_len;
Werner Lemberg05c21b82000-07-29 20:38:19 +0000111 strncpy( (char*)p_path + 1, pathname, path_len );
Just van Rossumae4bcee2000-07-28 01:10:35 +0000112
113 if ( FSMakeFSSpec( 0, 0, p_path, spec ) != noErr )
114 return -1;
115 else
116 return 0;
117 }
118
119
120 /* Return the file type of the file specified by spec. */
121 static
Werner Lemberg05c21b82000-07-29 20:38:19 +0000122 OSType get_file_type( FSSpec* spec )
Just van Rossumae4bcee2000-07-28 01:10:35 +0000123 {
Werner Lemberg05c21b82000-07-29 20:38:19 +0000124 FInfo finfo;
Just van Rossumae4bcee2000-07-28 01:10:35 +0000125
126
127 if ( FSpGetFInfo( spec, &finfo ) != noErr )
128 return 0; /* file might not exist */
Werner Lemberg05c21b82000-07-29 20:38:19 +0000129
Just van Rossumae4bcee2000-07-28 01:10:35 +0000130 return finfo.fdType;
131 }
132
133
134 /* Given a PostScript font name, create the Macintosh LWFN file name. */
135 static
Werner Lemberg05c21b82000-07-29 20:38:19 +0000136 void create_lwfn_name( char* ps_name,
137 Str255 lwfn_file_name )
Just van Rossumae4bcee2000-07-28 01:10:35 +0000138 {
139 int max = 5, count = 0;
140 FT_Byte* p = lwfn_file_name;
141 FT_Byte* q = (FT_Byte*)ps_name;
142
143
144 lwfn_file_name[0] = 0;
145
146 while ( *q )
147 {
Werner Lemberg05c21b82000-07-29 20:38:19 +0000148 if ( isupper( *q ) )
Just van Rossumae4bcee2000-07-28 01:10:35 +0000149 {
150 if ( count )
151 max = 3;
152 count = 0;
153 }
Werner Lemberg05c21b82000-07-29 20:38:19 +0000154 if ( count < max && ( isalnum( *q ) || *q == '_' ) )
Just van Rossumae4bcee2000-07-28 01:10:35 +0000155 {
156 *++p = *q;
157 lwfn_file_name[0]++;
158 count++;
159 }
160 q++;
161 }
162 }
163
164
165 /* Given a file reference, answer its location as a vRefNum
166 and a dirID. */
167 static
Werner Lemberg05c21b82000-07-29 20:38:19 +0000168 FT_Error get_file_location( short ref_num,
169 short* v_ref_num,
170 long* dir_id,
171 unsigned char* file_name )
Just van Rossumae4bcee2000-07-28 01:10:35 +0000172 {
173 FCBPBRec pb;
174 OSErr error;
175
Just van Rossumae4bcee2000-07-28 01:10:35 +0000176 pb.ioNamePtr = file_name;
177 pb.ioVRefNum = 0;
178 pb.ioRefNum = ref_num;
179 pb.ioFCBIndx = 0;
180
Werner Lemberg05c21b82000-07-29 20:38:19 +0000181
Just van Rossumae4bcee2000-07-28 01:10:35 +0000182 error = PBGetFCBInfoSync( &pb );
183 if ( error == noErr )
184 {
185 *v_ref_num = pb.ioFCBVRefNum;
Werner Lemberg05c21b82000-07-29 20:38:19 +0000186 *dir_id = pb.ioFCBParID;
Just van Rossumae4bcee2000-07-28 01:10:35 +0000187 }
188 return error;
189 }
190
191
192 /* Make a file spec for an LWFN file from a FOND resource and
193 a file name. */
194 static
195 FT_Error make_lwfn_spec( Handle fond,
196 unsigned char* file_name,
197 FSSpec* spec )
198 {
199 FT_Error error;
200 short ref_num, v_ref_num;
201 long dir_id;
202 Str255 fond_file_name;
203
204
205 ref_num = HomeResFile( fond );
Werner Lemberg05c21b82000-07-29 20:38:19 +0000206
Just van Rossumae4bcee2000-07-28 01:10:35 +0000207 error = ResError();
208 if ( !error )
Werner Lemberg05c21b82000-07-29 20:38:19 +0000209 error = get_file_location( ref_num, &v_ref_num,
210 &dir_id, fond_file_name );
Just van Rossumae4bcee2000-07-28 01:10:35 +0000211 if ( !error )
212 error = FSMakeFSSpec( v_ref_num, dir_id, file_name, spec );
213
214 return error;
215 }
216
217
218 /* Look inside the FOND data, answer whether there should be an SFNT
219 resource, and answer the name of a possible LWFN Type 1 file. */
220 static
221 void parse_fond( char* fond_data,
Werner Lemberg05c21b82000-07-29 20:38:19 +0000222 short* have_sfnt,
223 short* sfnt_id,
Just van Rossumae4bcee2000-07-28 01:10:35 +0000224 Str255 lwfn_file_name )
225 {
226 AsscEntry* assoc;
227 FamRec* fond;
228
229
230 *sfnt_id = 0;
231 *have_sfnt = 0;
232 lwfn_file_name[0] = 0;
233
234 fond = (FamRec*)fond_data;
Werner Lemberg05c21b82000-07-29 20:38:19 +0000235 assoc = (AsscEntry*)( fond_data + sizeof ( FamRec ) + 2 );
Just van Rossumae4bcee2000-07-28 01:10:35 +0000236
237 if ( assoc->fontSize == 0 )
238 {
239 *have_sfnt = 1;
240 *sfnt_id = assoc->fontID;
241 }
242
243 if ( fond->ffStylOff )
244 {
245 unsigned char* p = (unsigned char*)fond_data;
246 StyleTable* style;
247 unsigned short string_count;
248 unsigned char* name_table = 0;
249 char ps_name[256];
250 unsigned char* names[64];
251 int i;
252
Werner Lemberg05c21b82000-07-29 20:38:19 +0000253
Just van Rossumae4bcee2000-07-28 01:10:35 +0000254 p += fond->ffStylOff;
255 style = (StyleTable*)p;
Werner Lemberg05c21b82000-07-29 20:38:19 +0000256 p += sizeof ( StyleTable );
Just van Rossumae4bcee2000-07-28 01:10:35 +0000257 string_count = *(unsigned short*)(p);
Werner Lemberg05c21b82000-07-29 20:38:19 +0000258 p += sizeof ( short );
Just van Rossumae4bcee2000-07-28 01:10:35 +0000259
260 for ( i = 0 ; i < string_count && i < 64; i++ )
261 {
262 names[i] = p;
263 p += names[i][0];
264 p++;
265 }
Werner Lemberg05c21b82000-07-29 20:38:19 +0000266 strcpy( ps_name, p2c_str( names[0] ) ); /* Family name */
Just van Rossumae4bcee2000-07-28 01:10:35 +0000267
268 if ( style->indexes[0] > 1 )
269 {
Werner Lemberg05c21b82000-07-29 20:38:19 +0000270 unsigned char* suffixes = names[style->indexes[0] - 1];
271
272
Just van Rossumae4bcee2000-07-28 01:10:35 +0000273 for ( i=1; i<=suffixes[0]; i++ )
Werner Lemberg05c21b82000-07-29 20:38:19 +0000274 strcat( ps_name, p2c_str( names[suffixes[i] - 1 ] ) );
Just van Rossumae4bcee2000-07-28 01:10:35 +0000275 }
276 create_lwfn_name( ps_name, lwfn_file_name );
277 }
278 }
279
280
281 /* Read Type 1 data from the POST resources inside the LWFN file,
282 return a PFB buffer. This is somewhat convoluted because the FT2
283 PFB parser wants the ASCII header as one chunk, and the LWFN
284 chunks are often not organized that way, so we'll glue chunks
285 of the same type together. */
286 static
287 FT_Error read_lwfn( FT_Memory memory,
288 FSSpec* lwfn_spec,
289 FT_Byte** pfb_data,
290 FT_ULong* size )
291 {
292 FT_Error error = FT_Err_Ok;
293 short res_ref, res_id;
294 unsigned char *buffer, *p, *size_p;
295 FT_ULong total_size = 0;
296 FT_ULong post_size, pfb_chunk_size;
297 Handle post_data;
298 char code, last_code;
299
300
301 res_ref = FSpOpenResFile( lwfn_spec, fsRdPerm );
302 if ( ResError() )
303 return FT_Err_Out_Of_Memory;
304 UseResFile( res_ref );
305
306 /* First pass: load all POST resources, and determine the size of
307 the output buffer. */
308 res_id = 501;
309 last_code = -1;
Werner Lemberg05c21b82000-07-29 20:38:19 +0000310
Just van Rossumae4bcee2000-07-28 01:10:35 +0000311 for (;;)
312 {
313 post_data = Get1Resource( 'POST', res_id++ );
314 if ( post_data == NULL )
315 break; /* we're done */
316
317 code = (*post_data)[0];
318
319 if ( code != last_code )
320 {
321 if ( code == 5 )
322 total_size += 2; /* just the end code */
323 else
324 total_size += 6; /* code + 4 bytes chunk length */
325 }
326
327 total_size += GetHandleSize( post_data ) - 2;
328 last_code = code;
329 }
330
331 if ( ALLOC( buffer, (FT_Long)total_size ) )
332 goto Error;
333
334 /* Second pass: append all POST data to the buffer, add PFB fields.
Werner Lemberg05c21b82000-07-29 20:38:19 +0000335 Glue all consecutive chunks of the same type together. */
Just van Rossumae4bcee2000-07-28 01:10:35 +0000336 p = buffer;
337 res_id = 501;
338 last_code = -1;
339 pfb_chunk_size = 0;
340
341 for (;;)
342 {
343 post_data = Get1Resource( 'POST', res_id++ );
344 if ( post_data == NULL )
345 break; /* we're done */
346
347 post_size = (FT_ULong)GetHandleSize( post_data ) - 2;
348 code = (*post_data)[0];
349
350 if ( code != last_code )
351 {
352
353 if ( last_code != -1 )
354 {
355 /* we're done adding a chunk, fill in the size field */
Werner Lemberg05c21b82000-07-29 20:38:19 +0000356 *size_p++ = (FT_Byte)( pfb_chunk_size & 0xFF );
357 *size_p++ = (FT_Byte)( ( pfb_chunk_size >> 8 ) & 0xFF );
358 *size_p++ = (FT_Byte)( ( pfb_chunk_size >> 16 ) & 0xFF );
359 *size_p++ = (FT_Byte)( ( pfb_chunk_size >> 24 ) & 0xFF );
Just van Rossumae4bcee2000-07-28 01:10:35 +0000360 pfb_chunk_size = 0;
361 }
362
363 *p++ = 0x80;
364 if ( code == 5 )
365 *p++ = 0x03; /* the end */
366 else if ( code == 2 )
367 *p++ = 0x02; /* binary segment */
368 else
369 *p++ = 0x01; /* ASCII segment */
370
371 if ( code != 5 )
372 {
373 size_p = p; /* save for later */
374 p += 4; /* make space for size field */
375 }
376 }
377
378 memcpy( p, *post_data + 2, post_size );
379 pfb_chunk_size += post_size;
380 p += post_size;
381 last_code = code;
382 }
383
384 *pfb_data = buffer;
385 *size = total_size;
386
Werner Lemberg05c21b82000-07-29 20:38:19 +0000387 Error:
Just van Rossumae4bcee2000-07-28 01:10:35 +0000388 CloseResFile( res_ref );
389 return error;
390 }
391
392
393 /* Finalizer for a memory stream; gets called by FT_Done_Face().
394 It frees the memory it uses. */
395 static
Werner Lemberg05c21b82000-07-29 20:38:19 +0000396 void memory_stream_close( FT_Stream stream )
Just van Rossumae4bcee2000-07-28 01:10:35 +0000397 {
398 FT_Memory memory = stream->memory;
399
400
401 FREE( stream->base );
Werner Lemberg05c21b82000-07-29 20:38:19 +0000402
403 stream->size = 0;
404 stream->base = 0;
405 stream->close = 0;
Just van Rossumae4bcee2000-07-28 01:10:35 +0000406 }
407
408
409 /* Create a new memory stream from a buffer and a size. */
410 static
411 FT_Error new_memory_stream( FT_Library library,
412 FT_Byte* base,
413 FT_ULong size,
414 FT_Stream_Close close,
415 FT_Stream* astream )
416 {
417 FT_Error error;
418 FT_Memory memory;
419 FT_Stream stream;
420
421
422 if ( !library )
423 return FT_Err_Invalid_Library_Handle;
424
425 if ( !base )
426 return FT_Err_Invalid_Argument;
427
428 *astream = 0;
429 memory = library->memory;
Werner Lemberg05c21b82000-07-29 20:38:19 +0000430 if ( ALLOC( stream, sizeof ( *stream ) ) )
Just van Rossumae4bcee2000-07-28 01:10:35 +0000431 goto Exit;
432
433 FT_New_Memory_Stream( library,
434 base,
435 size,
436 stream );
437
438 stream->close = close;
439
440 *astream = stream;
441
442 Exit:
443 return error;
444 }
445
446
447 /* Create a new FT_Face given a buffer and a driver name. */
448 static
449 FT_Error open_face_from_buffer( FT_Library library,
450 FT_Byte* base,
451 FT_ULong size,
452 FT_Long face_index,
453 char* driver_name,
454 FT_Face* aface )
455 {
456 FT_Open_Args args;
457 FT_Error error;
458 FT_Stream stream;
459 FT_Memory memory = library->memory;
460
461
462 error = new_memory_stream( library,
463 base,
464 size,
465 memory_stream_close,
466 &stream );
467 if ( error )
468 {
469 FREE( base );
470 return error;
471 }
472
473 args.flags = ft_open_stream;
474 args.stream = stream;
475 if ( driver_name )
476 {
477 args.flags = args.flags | ft_open_driver;
478 args.driver = FT_Get_Module( library, driver_name );
479 }
Werner Lemberg05c21b82000-07-29 20:38:19 +0000480
Just van Rossumae4bcee2000-07-28 01:10:35 +0000481 error = FT_Open_Face( library, &args, face_index, aface );
Just van Rossum5fe94ff2000-07-28 02:25:23 +0000482 if ( error == FT_Err_Ok )
Just van Rossumae4bcee2000-07-28 01:10:35 +0000483 (*aface)->face_flags &= ~FT_FACE_FLAG_EXTERNAL_STREAM;
Just van Rossum5fe94ff2000-07-28 02:25:23 +0000484 else
485 {
486 FT_Done_Stream( stream );
487 FREE( stream );
488 }
Just van Rossumae4bcee2000-07-28 01:10:35 +0000489 return error;
490 }
491
492
493 /* Create a new FT_Face from a file spec to an LWFN file. */
494 static
Werner Lemberg05c21b82000-07-29 20:38:19 +0000495 FT_Error FT_New_Face_From_LWFN( FT_Library library,
496 FSSpec* spec,
497 FT_Long face_index,
498 FT_Face* aface )
Just van Rossumae4bcee2000-07-28 01:10:35 +0000499 {
Werner Lemberg05c21b82000-07-29 20:38:19 +0000500 FT_Byte* pfb_data;
501 FT_ULong pfb_size;
502 FT_Error error;
503 FT_Memory memory = library->memory;
Just van Rossumae4bcee2000-07-28 01:10:35 +0000504
505
506 error = read_lwfn( library->memory, spec, &pfb_data, &pfb_size );
507 if ( error )
508 return error;
509
510#if 0
511 {
Werner Lemberg05c21b82000-07-29 20:38:19 +0000512 FILE* f;
513 char* path;
514
Just van Rossumae4bcee2000-07-28 01:10:35 +0000515
516 path = p2c_str( spec->name );
517 strcat( path, ".PFB" );
Werner Lemberg05c21b82000-07-29 20:38:19 +0000518 f = fopen( path, "wb" );
Just van Rossumae4bcee2000-07-28 01:10:35 +0000519 if ( f )
520 {
521 fwrite( pfb_data, 1, pfb_size, f );
522 fclose( f );
523 }
524 }
525#endif
526
527 return open_face_from_buffer( library,
528 pfb_data,
529 pfb_size,
530 face_index,
531 "type1",
532 aface );
533 }
534
535
536 /* Create a new FT_Face from an SFNT resource, specified by res ID. */
537 static
Werner Lemberg05c21b82000-07-29 20:38:19 +0000538 FT_Error FT_New_Face_From_SFNT( FT_Library library,
539 short sfnt_id,
540 FT_Long face_index,
541 FT_Face* aface )
Just van Rossumae4bcee2000-07-28 01:10:35 +0000542 {
Werner Lemberg05c21b82000-07-29 20:38:19 +0000543 Handle sfnt = NULL;
544 FT_Byte* sfnt_data;
545 size_t sfnt_size;
546 FT_Stream stream = NULL;
547 FT_Error error = 0;
548 FT_Memory memory = library->memory;
Just van Rossumae4bcee2000-07-28 01:10:35 +0000549
550
551 sfnt = GetResource( 'sfnt', sfnt_id );
552 if ( ResError() )
553 return FT_Err_Invalid_Handle;
554
555 sfnt_size = (FT_ULong)GetHandleSize( sfnt );
556 if ( ALLOC( sfnt_data, (FT_Long)sfnt_size ) )
557 {
558 ReleaseResource( sfnt );
559 return error;
560 }
561
562 HLock( sfnt );
Werner Lemberg05c21b82000-07-29 20:38:19 +0000563 memcpy( sfnt_data, *sfnt, sfnt_size );
Just van Rossumae4bcee2000-07-28 01:10:35 +0000564 HUnlock( sfnt );
565 ReleaseResource( sfnt );
566
567 return open_face_from_buffer( library,
568 sfnt_data,
569 sfnt_size,
570 face_index,
571 "truetype",
572 aface );
573 }
574
575
576 /* Create a new FT_Face from a file spec to a suitcase file. */
577 static
Werner Lemberg05c21b82000-07-29 20:38:19 +0000578 FT_Error FT_New_Face_From_Suitcase( FT_Library library,
579 FSSpec* spec,
580 FT_Long face_index,
581 FT_Face* aface )
Just van Rossumae4bcee2000-07-28 01:10:35 +0000582 {
583 FT_Error error = FT_Err_Ok;
584 short res_ref, res_index;
585 Handle fond;
586
587
588 res_ref = FSpOpenResFile( spec, fsRdPerm );
589 if ( ResError() )
590 return FT_Err_Cannot_Open_Resource;
591 UseResFile( res_ref );
592
593 /* face_index may be -1, in which case we
594 just need to do a sanity check */
Werner Lemberg05c21b82000-07-29 20:38:19 +0000595 if ( face_index < 0 )
Just van Rossumae4bcee2000-07-28 01:10:35 +0000596 res_index = 1;
597 else
598 {
Werner Lemberg05c21b82000-07-29 20:38:19 +0000599 res_index = (short)( face_index + 1 );
Just van Rossumae4bcee2000-07-28 01:10:35 +0000600 face_index = 0;
601 }
602 fond = Get1IndResource( 'FOND', res_index );
603 if ( ResError() )
604 {
605 error = FT_Err_Cannot_Open_Resource;
606 goto Error;
607 }
608
609 error = FT_New_Face_From_FOND( library, fond, face_index, aface );
610
Werner Lemberg05c21b82000-07-29 20:38:19 +0000611 Error:
Just van Rossumae4bcee2000-07-28 01:10:35 +0000612 CloseResFile( res_ref );
613 return error;
614 }
615
616
Werner Lemberg90a03302000-11-07 17:21:11 +0000617 /* documentation in ftmac.h */
618
David Turner76a5f622000-11-04 01:55:49 +0000619 FT_EXPORT_DEF( FT_Error ) FT_New_Face_From_FOND( FT_Library library,
620 Handle fond,
621 FT_Long face_index,
Werner Lemberg4b680072000-11-07 06:30:29 +0000622 FT_Face *aface )
Just van Rossumae4bcee2000-07-28 01:10:35 +0000623 {
624 short sfnt_id, have_sfnt, have_lwfn = 0;
625 Str255 lwfn_file_name;
626 short fond_id;
627 OSType fond_type;
628 Str255 fond_name;
629 FSSpec lwfn_spec;
630 FT_Error error = FT_Err_Unknown_File_Format;
631
632
633 GetResInfo(fond, &fond_id, &fond_type, fond_name);
634 if ( ResError() != noErr || fond_type != 'FOND' )
635 return FT_Err_Invalid_File_Format;
636
637 HLock( fond );
638 parse_fond( *fond, &have_sfnt, &sfnt_id, lwfn_file_name );
639 HUnlock( fond );
640
641 if ( lwfn_file_name[0] )
642 {
643 if ( make_lwfn_spec( fond, lwfn_file_name, &lwfn_spec ) == FT_Err_Ok )
644 have_lwfn = 1; /* yeah, we got one! */
645 else
646 have_lwfn = 0; /* no LWFN file found */
647 }
648
649 if ( have_lwfn && ( !have_sfnt || PREFER_LWFN ) )
650 return FT_New_Face_From_LWFN( library,
651 &lwfn_spec,
652 face_index,
653 aface );
654 else if ( have_sfnt )
655 return FT_New_Face_From_SFNT( library,
656 sfnt_id,
657 face_index,
658 aface );
659
660 return FT_Err_Unknown_File_Format;
661 }
662
663
664 /*************************************************************************/
665 /* */
666 /* <Function> */
667 /* FT_New_Face */
668 /* */
669 /* <Description> */
670 /* This is the Mac-specific implementation of FT_New_Face. In */
Werner Lemberg05c21b82000-07-29 20:38:19 +0000671 /* addition to the standard FT_New_Face() functionality, it also */
Just van Rossumae4bcee2000-07-28 01:10:35 +0000672 /* accepts pathnames to Mac suitcase files. For further */
Werner Lemberg90a03302000-11-07 17:21:11 +0000673 /* documentation see the original FT_New_Face() in freetype.h. */
Just van Rossumae4bcee2000-07-28 01:10:35 +0000674 /* */
David Turner76a5f622000-11-04 01:55:49 +0000675 FT_EXPORT_DEF( FT_Error ) FT_New_Face( FT_Library library,
676 const char* pathname,
677 FT_Long face_index,
Werner Lemberg4b680072000-11-07 06:30:29 +0000678 FT_Face *aface )
Just van Rossumae4bcee2000-07-28 01:10:35 +0000679 {
680 FT_Open_Args args;
681 FSSpec spec;
682 OSType file_type;
683
684
685 /* test for valid `library' and `aface' delayed to FT_Open_Face() */
686 if ( !pathname )
687 return FT_Err_Invalid_Argument;
688
689 if ( file_spec_from_path( pathname, &spec ) )
690 return FT_Err_Invalid_Argument;
691
692 file_type = get_file_type( &spec );
693 if ( file_type == 'FFIL' || file_type == 'tfil' )
694 return FT_New_Face_From_Suitcase( library, &spec, face_index, aface );
695 else if ( file_type == 'LWFN' )
696 return FT_New_Face_From_LWFN( library, &spec, face_index, aface );
697 else
698 {
699 args.flags = ft_open_pathname;
700 args.pathname = (char*)pathname;
701
702 return FT_Open_Face( library, &args, face_index, aface );
703 }
704 }
705
Werner Lemberg05c21b82000-07-29 20:38:19 +0000706
707/* END */