blob: 55ba30afb03f33bdd5f3ec04340c9852cc8d7ba1 [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
David Turner19ed8af2000-12-08 02:42:29 +000059#include <ft2build.h>
60#include FT_FREETYPE_H
61#include FT_INTERNAL_STREAM_H
62#include FT_SOURCE_FILE(truetype/ttobjs.h)
63#include FT_SOURCE_FILE(type1/t1objs.h)
Just van Rossumae4bcee2000-07-28 01:10:35 +000064
65#include <Resources.h>
66#include <Fonts.h>
67#include <Errors.h>
68
69#include <ctype.h> /* for isupper() and isalnum() */
70
David Turner19ed8af2000-12-08 02:42:29 +000071#include FT_MAC_H
Just van Rossumae4bcee2000-07-28 01:10:35 +000072
73
74
75 /* Set PREFER_LWFN to 1 if LWFN (Type 1) is preferred over
76 TrueType in case *both* are available (this is not common,
77 but it *is* possible). */
78#ifndef PREFER_LWFN
79#define PREFER_LWFN 1
80#endif
81
82
83
Werner Lemberg05c21b82000-07-29 20:38:19 +000084 /* Quick'n'dirty Pascal string to C string converter.
Just van Rossumae4bcee2000-07-28 01:10:35 +000085 Warning: this call is not thread safe! Use with caution. */
86 static
Werner Lemberg05c21b82000-07-29 20:38:19 +000087 char* p2c_str( unsigned char* pstr )
Just van Rossumae4bcee2000-07-28 01:10:35 +000088 {
Werner Lemberg05c21b82000-07-29 20:38:19 +000089 static char cstr[256];
Just van Rossumae4bcee2000-07-28 01:10:35 +000090
91
Werner Lemberg05c21b82000-07-29 20:38:19 +000092 strncpy( cstr, (char*)pstr + 1, pstr[0] );
Just van Rossumae4bcee2000-07-28 01:10:35 +000093 cstr[pstr[0]] = '\0';
94 return cstr;
95 }
96
97
98 /* Given a pathname, fill in a file spec. */
99 static
Werner Lemberg05c21b82000-07-29 20:38:19 +0000100 int file_spec_from_path( const char* pathname,
101 FSSpec* spec )
Just van Rossumae4bcee2000-07-28 01:10:35 +0000102 {
103 Str255 p_path;
104 FT_ULong path_len;
105
106
107 /* convert path to a pascal string */
108 path_len = strlen( pathname );
109 if ( path_len > 255 )
110 return -1;
111 p_path[0] = (unsigned char)path_len;
Werner Lemberg05c21b82000-07-29 20:38:19 +0000112 strncpy( (char*)p_path + 1, pathname, path_len );
Just van Rossumae4bcee2000-07-28 01:10:35 +0000113
114 if ( FSMakeFSSpec( 0, 0, p_path, spec ) != noErr )
115 return -1;
116 else
117 return 0;
118 }
119
120
121 /* Return the file type of the file specified by spec. */
122 static
Werner Lemberg05c21b82000-07-29 20:38:19 +0000123 OSType get_file_type( FSSpec* spec )
Just van Rossumae4bcee2000-07-28 01:10:35 +0000124 {
Werner Lemberg05c21b82000-07-29 20:38:19 +0000125 FInfo finfo;
Just van Rossumae4bcee2000-07-28 01:10:35 +0000126
127
128 if ( FSpGetFInfo( spec, &finfo ) != noErr )
129 return 0; /* file might not exist */
Werner Lemberg05c21b82000-07-29 20:38:19 +0000130
Just van Rossumae4bcee2000-07-28 01:10:35 +0000131 return finfo.fdType;
132 }
133
134
135 /* Given a PostScript font name, create the Macintosh LWFN file name. */
136 static
Werner Lemberg05c21b82000-07-29 20:38:19 +0000137 void create_lwfn_name( char* ps_name,
138 Str255 lwfn_file_name )
Just van Rossumae4bcee2000-07-28 01:10:35 +0000139 {
140 int max = 5, count = 0;
141 FT_Byte* p = lwfn_file_name;
142 FT_Byte* q = (FT_Byte*)ps_name;
143
144
145 lwfn_file_name[0] = 0;
146
147 while ( *q )
148 {
Werner Lemberg05c21b82000-07-29 20:38:19 +0000149 if ( isupper( *q ) )
Just van Rossumae4bcee2000-07-28 01:10:35 +0000150 {
151 if ( count )
152 max = 3;
153 count = 0;
154 }
Werner Lemberg05c21b82000-07-29 20:38:19 +0000155 if ( count < max && ( isalnum( *q ) || *q == '_' ) )
Just van Rossumae4bcee2000-07-28 01:10:35 +0000156 {
157 *++p = *q;
158 lwfn_file_name[0]++;
159 count++;
160 }
161 q++;
162 }
163 }
164
165
166 /* Given a file reference, answer its location as a vRefNum
167 and a dirID. */
168 static
Werner Lemberg05c21b82000-07-29 20:38:19 +0000169 FT_Error get_file_location( short ref_num,
170 short* v_ref_num,
171 long* dir_id,
172 unsigned char* file_name )
Just van Rossumae4bcee2000-07-28 01:10:35 +0000173 {
174 FCBPBRec pb;
175 OSErr error;
176
Just van Rossumae4bcee2000-07-28 01:10:35 +0000177 pb.ioNamePtr = file_name;
178 pb.ioVRefNum = 0;
179 pb.ioRefNum = ref_num;
180 pb.ioFCBIndx = 0;
181
Werner Lemberg05c21b82000-07-29 20:38:19 +0000182
Just van Rossumae4bcee2000-07-28 01:10:35 +0000183 error = PBGetFCBInfoSync( &pb );
184 if ( error == noErr )
185 {
186 *v_ref_num = pb.ioFCBVRefNum;
Werner Lemberg05c21b82000-07-29 20:38:19 +0000187 *dir_id = pb.ioFCBParID;
Just van Rossumae4bcee2000-07-28 01:10:35 +0000188 }
189 return error;
190 }
191
192
193 /* Make a file spec for an LWFN file from a FOND resource and
194 a file name. */
195 static
196 FT_Error make_lwfn_spec( Handle fond,
197 unsigned char* file_name,
198 FSSpec* spec )
199 {
200 FT_Error error;
201 short ref_num, v_ref_num;
202 long dir_id;
203 Str255 fond_file_name;
204
205
206 ref_num = HomeResFile( fond );
Werner Lemberg05c21b82000-07-29 20:38:19 +0000207
Just van Rossumae4bcee2000-07-28 01:10:35 +0000208 error = ResError();
209 if ( !error )
Werner Lemberg05c21b82000-07-29 20:38:19 +0000210 error = get_file_location( ref_num, &v_ref_num,
211 &dir_id, fond_file_name );
Just van Rossumae4bcee2000-07-28 01:10:35 +0000212 if ( !error )
213 error = FSMakeFSSpec( v_ref_num, dir_id, file_name, spec );
214
215 return error;
216 }
217
218
219 /* Look inside the FOND data, answer whether there should be an SFNT
220 resource, and answer the name of a possible LWFN Type 1 file. */
221 static
222 void parse_fond( char* fond_data,
Werner Lemberg05c21b82000-07-29 20:38:19 +0000223 short* have_sfnt,
224 short* sfnt_id,
Just van Rossumae4bcee2000-07-28 01:10:35 +0000225 Str255 lwfn_file_name )
226 {
227 AsscEntry* assoc;
228 FamRec* fond;
229
230
231 *sfnt_id = 0;
232 *have_sfnt = 0;
233 lwfn_file_name[0] = 0;
234
235 fond = (FamRec*)fond_data;
Werner Lemberg05c21b82000-07-29 20:38:19 +0000236 assoc = (AsscEntry*)( fond_data + sizeof ( FamRec ) + 2 );
Just van Rossumae4bcee2000-07-28 01:10:35 +0000237
238 if ( assoc->fontSize == 0 )
239 {
240 *have_sfnt = 1;
241 *sfnt_id = assoc->fontID;
242 }
243
244 if ( fond->ffStylOff )
245 {
246 unsigned char* p = (unsigned char*)fond_data;
247 StyleTable* style;
248 unsigned short string_count;
249 unsigned char* name_table = 0;
250 char ps_name[256];
251 unsigned char* names[64];
252 int i;
253
Werner Lemberg05c21b82000-07-29 20:38:19 +0000254
Just van Rossumae4bcee2000-07-28 01:10:35 +0000255 p += fond->ffStylOff;
256 style = (StyleTable*)p;
Werner Lemberg05c21b82000-07-29 20:38:19 +0000257 p += sizeof ( StyleTable );
Just van Rossumae4bcee2000-07-28 01:10:35 +0000258 string_count = *(unsigned short*)(p);
Werner Lemberg05c21b82000-07-29 20:38:19 +0000259 p += sizeof ( short );
Just van Rossumae4bcee2000-07-28 01:10:35 +0000260
261 for ( i = 0 ; i < string_count && i < 64; i++ )
262 {
263 names[i] = p;
264 p += names[i][0];
265 p++;
266 }
Werner Lemberg05c21b82000-07-29 20:38:19 +0000267 strcpy( ps_name, p2c_str( names[0] ) ); /* Family name */
Just van Rossumae4bcee2000-07-28 01:10:35 +0000268
269 if ( style->indexes[0] > 1 )
270 {
Werner Lemberg05c21b82000-07-29 20:38:19 +0000271 unsigned char* suffixes = names[style->indexes[0] - 1];
272
273
Just van Rossumae4bcee2000-07-28 01:10:35 +0000274 for ( i=1; i<=suffixes[0]; i++ )
Werner Lemberg05c21b82000-07-29 20:38:19 +0000275 strcat( ps_name, p2c_str( names[suffixes[i] - 1 ] ) );
Just van Rossumae4bcee2000-07-28 01:10:35 +0000276 }
277 create_lwfn_name( ps_name, lwfn_file_name );
278 }
279 }
280
281
282 /* Read Type 1 data from the POST resources inside the LWFN file,
283 return a PFB buffer. This is somewhat convoluted because the FT2
284 PFB parser wants the ASCII header as one chunk, and the LWFN
285 chunks are often not organized that way, so we'll glue chunks
286 of the same type together. */
287 static
288 FT_Error read_lwfn( FT_Memory memory,
289 FSSpec* lwfn_spec,
290 FT_Byte** pfb_data,
291 FT_ULong* size )
292 {
293 FT_Error error = FT_Err_Ok;
294 short res_ref, res_id;
295 unsigned char *buffer, *p, *size_p;
296 FT_ULong total_size = 0;
297 FT_ULong post_size, pfb_chunk_size;
298 Handle post_data;
299 char code, last_code;
300
301
302 res_ref = FSpOpenResFile( lwfn_spec, fsRdPerm );
303 if ( ResError() )
304 return FT_Err_Out_Of_Memory;
305 UseResFile( res_ref );
306
307 /* First pass: load all POST resources, and determine the size of
308 the output buffer. */
309 res_id = 501;
310 last_code = -1;
Werner Lemberg05c21b82000-07-29 20:38:19 +0000311
Just van Rossumae4bcee2000-07-28 01:10:35 +0000312 for (;;)
313 {
314 post_data = Get1Resource( 'POST', res_id++ );
315 if ( post_data == NULL )
316 break; /* we're done */
317
318 code = (*post_data)[0];
319
320 if ( code != last_code )
321 {
322 if ( code == 5 )
323 total_size += 2; /* just the end code */
324 else
325 total_size += 6; /* code + 4 bytes chunk length */
326 }
327
328 total_size += GetHandleSize( post_data ) - 2;
329 last_code = code;
330 }
331
332 if ( ALLOC( buffer, (FT_Long)total_size ) )
333 goto Error;
334
335 /* Second pass: append all POST data to the buffer, add PFB fields.
Werner Lemberg05c21b82000-07-29 20:38:19 +0000336 Glue all consecutive chunks of the same type together. */
Just van Rossumae4bcee2000-07-28 01:10:35 +0000337 p = buffer;
338 res_id = 501;
339 last_code = -1;
340 pfb_chunk_size = 0;
341
342 for (;;)
343 {
344 post_data = Get1Resource( 'POST', res_id++ );
345 if ( post_data == NULL )
346 break; /* we're done */
347
348 post_size = (FT_ULong)GetHandleSize( post_data ) - 2;
349 code = (*post_data)[0];
350
351 if ( code != last_code )
352 {
353
354 if ( last_code != -1 )
355 {
356 /* we're done adding a chunk, fill in the size field */
Werner Lemberg05c21b82000-07-29 20:38:19 +0000357 *size_p++ = (FT_Byte)( pfb_chunk_size & 0xFF );
358 *size_p++ = (FT_Byte)( ( pfb_chunk_size >> 8 ) & 0xFF );
359 *size_p++ = (FT_Byte)( ( pfb_chunk_size >> 16 ) & 0xFF );
360 *size_p++ = (FT_Byte)( ( pfb_chunk_size >> 24 ) & 0xFF );
Just van Rossumae4bcee2000-07-28 01:10:35 +0000361 pfb_chunk_size = 0;
362 }
363
364 *p++ = 0x80;
365 if ( code == 5 )
366 *p++ = 0x03; /* the end */
367 else if ( code == 2 )
368 *p++ = 0x02; /* binary segment */
369 else
370 *p++ = 0x01; /* ASCII segment */
371
372 if ( code != 5 )
373 {
374 size_p = p; /* save for later */
375 p += 4; /* make space for size field */
376 }
377 }
378
379 memcpy( p, *post_data + 2, post_size );
380 pfb_chunk_size += post_size;
381 p += post_size;
382 last_code = code;
383 }
384
385 *pfb_data = buffer;
386 *size = total_size;
387
Werner Lemberg05c21b82000-07-29 20:38:19 +0000388 Error:
Just van Rossumae4bcee2000-07-28 01:10:35 +0000389 CloseResFile( res_ref );
390 return error;
391 }
392
393
394 /* Finalizer for a memory stream; gets called by FT_Done_Face().
395 It frees the memory it uses. */
396 static
Werner Lemberg05c21b82000-07-29 20:38:19 +0000397 void memory_stream_close( FT_Stream stream )
Just van Rossumae4bcee2000-07-28 01:10:35 +0000398 {
399 FT_Memory memory = stream->memory;
400
401
402 FREE( stream->base );
Werner Lemberg05c21b82000-07-29 20:38:19 +0000403
404 stream->size = 0;
405 stream->base = 0;
406 stream->close = 0;
Just van Rossumae4bcee2000-07-28 01:10:35 +0000407 }
408
409
410 /* Create a new memory stream from a buffer and a size. */
411 static
412 FT_Error new_memory_stream( FT_Library library,
413 FT_Byte* base,
414 FT_ULong size,
415 FT_Stream_Close close,
416 FT_Stream* astream )
417 {
418 FT_Error error;
419 FT_Memory memory;
420 FT_Stream stream;
421
422
423 if ( !library )
424 return FT_Err_Invalid_Library_Handle;
425
426 if ( !base )
427 return FT_Err_Invalid_Argument;
428
429 *astream = 0;
430 memory = library->memory;
Werner Lemberg05c21b82000-07-29 20:38:19 +0000431 if ( ALLOC( stream, sizeof ( *stream ) ) )
Just van Rossumae4bcee2000-07-28 01:10:35 +0000432 goto Exit;
433
434 FT_New_Memory_Stream( library,
435 base,
436 size,
437 stream );
438
439 stream->close = close;
440
441 *astream = stream;
442
443 Exit:
444 return error;
445 }
446
447
448 /* Create a new FT_Face given a buffer and a driver name. */
449 static
450 FT_Error open_face_from_buffer( FT_Library library,
451 FT_Byte* base,
452 FT_ULong size,
453 FT_Long face_index,
454 char* driver_name,
455 FT_Face* aface )
456 {
457 FT_Open_Args args;
458 FT_Error error;
459 FT_Stream stream;
460 FT_Memory memory = library->memory;
461
462
463 error = new_memory_stream( library,
464 base,
465 size,
466 memory_stream_close,
467 &stream );
468 if ( error )
469 {
470 FREE( base );
471 return error;
472 }
473
474 args.flags = ft_open_stream;
475 args.stream = stream;
476 if ( driver_name )
477 {
478 args.flags = args.flags | ft_open_driver;
479 args.driver = FT_Get_Module( library, driver_name );
480 }
Werner Lemberg05c21b82000-07-29 20:38:19 +0000481
Just van Rossumae4bcee2000-07-28 01:10:35 +0000482 error = FT_Open_Face( library, &args, face_index, aface );
Just van Rossum5fe94ff2000-07-28 02:25:23 +0000483 if ( error == FT_Err_Ok )
Just van Rossumae4bcee2000-07-28 01:10:35 +0000484 (*aface)->face_flags &= ~FT_FACE_FLAG_EXTERNAL_STREAM;
Just van Rossum5fe94ff2000-07-28 02:25:23 +0000485 else
486 {
487 FT_Done_Stream( stream );
488 FREE( stream );
489 }
Just van Rossumae4bcee2000-07-28 01:10:35 +0000490 return error;
491 }
492
493
494 /* Create a new FT_Face from a file spec to an LWFN file. */
495 static
Werner Lemberg05c21b82000-07-29 20:38:19 +0000496 FT_Error FT_New_Face_From_LWFN( FT_Library library,
497 FSSpec* spec,
498 FT_Long face_index,
499 FT_Face* aface )
Just van Rossumae4bcee2000-07-28 01:10:35 +0000500 {
Werner Lemberg05c21b82000-07-29 20:38:19 +0000501 FT_Byte* pfb_data;
502 FT_ULong pfb_size;
503 FT_Error error;
504 FT_Memory memory = library->memory;
Just van Rossumae4bcee2000-07-28 01:10:35 +0000505
506
507 error = read_lwfn( library->memory, spec, &pfb_data, &pfb_size );
508 if ( error )
509 return error;
510
511#if 0
512 {
Werner Lemberg05c21b82000-07-29 20:38:19 +0000513 FILE* f;
514 char* path;
515
Just van Rossumae4bcee2000-07-28 01:10:35 +0000516
517 path = p2c_str( spec->name );
518 strcat( path, ".PFB" );
Werner Lemberg05c21b82000-07-29 20:38:19 +0000519 f = fopen( path, "wb" );
Just van Rossumae4bcee2000-07-28 01:10:35 +0000520 if ( f )
521 {
522 fwrite( pfb_data, 1, pfb_size, f );
523 fclose( f );
524 }
525 }
526#endif
527
528 return open_face_from_buffer( library,
529 pfb_data,
530 pfb_size,
531 face_index,
532 "type1",
533 aface );
534 }
535
536
537 /* Create a new FT_Face from an SFNT resource, specified by res ID. */
538 static
Werner Lemberg05c21b82000-07-29 20:38:19 +0000539 FT_Error FT_New_Face_From_SFNT( FT_Library library,
540 short sfnt_id,
541 FT_Long face_index,
542 FT_Face* aface )
Just van Rossumae4bcee2000-07-28 01:10:35 +0000543 {
Werner Lemberg05c21b82000-07-29 20:38:19 +0000544 Handle sfnt = NULL;
545 FT_Byte* sfnt_data;
546 size_t sfnt_size;
547 FT_Stream stream = NULL;
548 FT_Error error = 0;
549 FT_Memory memory = library->memory;
Just van Rossumae4bcee2000-07-28 01:10:35 +0000550
551
552 sfnt = GetResource( 'sfnt', sfnt_id );
553 if ( ResError() )
554 return FT_Err_Invalid_Handle;
555
556 sfnt_size = (FT_ULong)GetHandleSize( sfnt );
557 if ( ALLOC( sfnt_data, (FT_Long)sfnt_size ) )
558 {
559 ReleaseResource( sfnt );
560 return error;
561 }
562
563 HLock( sfnt );
Werner Lemberg05c21b82000-07-29 20:38:19 +0000564 memcpy( sfnt_data, *sfnt, sfnt_size );
Just van Rossumae4bcee2000-07-28 01:10:35 +0000565 HUnlock( sfnt );
566 ReleaseResource( sfnt );
567
568 return open_face_from_buffer( library,
569 sfnt_data,
570 sfnt_size,
571 face_index,
572 "truetype",
573 aface );
574 }
575
576
577 /* Create a new FT_Face from a file spec to a suitcase file. */
578 static
Werner Lemberg05c21b82000-07-29 20:38:19 +0000579 FT_Error FT_New_Face_From_Suitcase( FT_Library library,
580 FSSpec* spec,
581 FT_Long face_index,
582 FT_Face* aface )
Just van Rossumae4bcee2000-07-28 01:10:35 +0000583 {
584 FT_Error error = FT_Err_Ok;
585 short res_ref, res_index;
586 Handle fond;
587
588
589 res_ref = FSpOpenResFile( spec, fsRdPerm );
590 if ( ResError() )
591 return FT_Err_Cannot_Open_Resource;
592 UseResFile( res_ref );
593
594 /* face_index may be -1, in which case we
595 just need to do a sanity check */
Werner Lemberg05c21b82000-07-29 20:38:19 +0000596 if ( face_index < 0 )
Just van Rossumae4bcee2000-07-28 01:10:35 +0000597 res_index = 1;
598 else
599 {
Werner Lemberg05c21b82000-07-29 20:38:19 +0000600 res_index = (short)( face_index + 1 );
Just van Rossumae4bcee2000-07-28 01:10:35 +0000601 face_index = 0;
602 }
603 fond = Get1IndResource( 'FOND', res_index );
604 if ( ResError() )
605 {
606 error = FT_Err_Cannot_Open_Resource;
607 goto Error;
608 }
609
610 error = FT_New_Face_From_FOND( library, fond, face_index, aface );
611
Werner Lemberg05c21b82000-07-29 20:38:19 +0000612 Error:
Just van Rossumae4bcee2000-07-28 01:10:35 +0000613 CloseResFile( res_ref );
614 return error;
615 }
616
617
Werner Lemberg90a03302000-11-07 17:21:11 +0000618 /* documentation in ftmac.h */
619
David Turner76a5f622000-11-04 01:55:49 +0000620 FT_EXPORT_DEF( FT_Error ) FT_New_Face_From_FOND( FT_Library library,
621 Handle fond,
622 FT_Long face_index,
Werner Lemberg4b680072000-11-07 06:30:29 +0000623 FT_Face *aface )
Just van Rossumae4bcee2000-07-28 01:10:35 +0000624 {
625 short sfnt_id, have_sfnt, have_lwfn = 0;
626 Str255 lwfn_file_name;
627 short fond_id;
628 OSType fond_type;
629 Str255 fond_name;
630 FSSpec lwfn_spec;
631 FT_Error error = FT_Err_Unknown_File_Format;
632
633
634 GetResInfo(fond, &fond_id, &fond_type, fond_name);
635 if ( ResError() != noErr || fond_type != 'FOND' )
636 return FT_Err_Invalid_File_Format;
637
638 HLock( fond );
639 parse_fond( *fond, &have_sfnt, &sfnt_id, lwfn_file_name );
640 HUnlock( fond );
641
642 if ( lwfn_file_name[0] )
643 {
644 if ( make_lwfn_spec( fond, lwfn_file_name, &lwfn_spec ) == FT_Err_Ok )
645 have_lwfn = 1; /* yeah, we got one! */
646 else
647 have_lwfn = 0; /* no LWFN file found */
648 }
649
650 if ( have_lwfn && ( !have_sfnt || PREFER_LWFN ) )
651 return FT_New_Face_From_LWFN( library,
652 &lwfn_spec,
653 face_index,
654 aface );
655 else if ( have_sfnt )
656 return FT_New_Face_From_SFNT( library,
657 sfnt_id,
658 face_index,
659 aface );
660
661 return FT_Err_Unknown_File_Format;
662 }
663
664
665 /*************************************************************************/
666 /* */
667 /* <Function> */
668 /* FT_New_Face */
669 /* */
670 /* <Description> */
671 /* This is the Mac-specific implementation of FT_New_Face. In */
Werner Lemberg05c21b82000-07-29 20:38:19 +0000672 /* addition to the standard FT_New_Face() functionality, it also */
Just van Rossumae4bcee2000-07-28 01:10:35 +0000673 /* accepts pathnames to Mac suitcase files. For further */
Werner Lemberg90a03302000-11-07 17:21:11 +0000674 /* documentation see the original FT_New_Face() in freetype.h. */
Just van Rossumae4bcee2000-07-28 01:10:35 +0000675 /* */
David Turner76a5f622000-11-04 01:55:49 +0000676 FT_EXPORT_DEF( FT_Error ) FT_New_Face( FT_Library library,
677 const char* pathname,
678 FT_Long face_index,
Werner Lemberg4b680072000-11-07 06:30:29 +0000679 FT_Face *aface )
Just van Rossumae4bcee2000-07-28 01:10:35 +0000680 {
681 FT_Open_Args args;
682 FSSpec spec;
683 OSType file_type;
684
685
686 /* test for valid `library' and `aface' delayed to FT_Open_Face() */
687 if ( !pathname )
688 return FT_Err_Invalid_Argument;
689
690 if ( file_spec_from_path( pathname, &spec ) )
691 return FT_Err_Invalid_Argument;
692
693 file_type = get_file_type( &spec );
694 if ( file_type == 'FFIL' || file_type == 'tfil' )
695 return FT_New_Face_From_Suitcase( library, &spec, face_index, aface );
696 else if ( file_type == 'LWFN' )
697 return FT_New_Face_From_LWFN( library, &spec, face_index, aface );
698 else
699 {
700 args.flags = ft_open_pathname;
701 args.pathname = (char*)pathname;
702
703 return FT_Open_Face( library, &args, face_index, aface );
704 }
705 }
706
Werner Lemberg05c21b82000-07-29 20:38:19 +0000707
708/* END */