blob: fff02f401a79a8c382e8a4695aae9dce9f00ab2c [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
Werner Lembergcc069be2000-12-08 16:17:16 +000059
60#include <ft2build.h>
61#include FT_FREETYPE_H
62#include FT_INTERNAL_STREAM_H
David Turner8d3a4012001-03-20 11:14:24 +000063#include "truetype/ttobjs.h"
64#include "type1/t1objs.h"
Just van Rossumae4bcee2000-07-28 01:10:35 +000065
66#include <Resources.h>
67#include <Fonts.h>
68#include <Errors.h>
69
70#include <ctype.h> /* for isupper() and isalnum() */
71
David Turner19ed8af2000-12-08 02:42:29 +000072#include FT_MAC_H
Just van Rossumae4bcee2000-07-28 01:10:35 +000073
74
75
76 /* Set PREFER_LWFN to 1 if LWFN (Type 1) is preferred over
77 TrueType in case *both* are available (this is not common,
78 but it *is* possible). */
79#ifndef PREFER_LWFN
80#define PREFER_LWFN 1
81#endif
82
83
84
Werner Lemberg05c21b82000-07-29 20:38:19 +000085 /* Quick'n'dirty Pascal string to C string converter.
Just van Rossumae4bcee2000-07-28 01:10:35 +000086 Warning: this call is not thread safe! Use with caution. */
87 static
Werner Lemberg05c21b82000-07-29 20:38:19 +000088 char* p2c_str( unsigned char* pstr )
Just van Rossumae4bcee2000-07-28 01:10:35 +000089 {
Werner Lemberg05c21b82000-07-29 20:38:19 +000090 static char cstr[256];
Just van Rossumae4bcee2000-07-28 01:10:35 +000091
92
Werner Lemberg05c21b82000-07-29 20:38:19 +000093 strncpy( cstr, (char*)pstr + 1, pstr[0] );
Just van Rossumae4bcee2000-07-28 01:10:35 +000094 cstr[pstr[0]] = '\0';
95 return cstr;
96 }
97
98
99 /* Given a pathname, fill in a file spec. */
100 static
Werner Lemberg05c21b82000-07-29 20:38:19 +0000101 int file_spec_from_path( const char* pathname,
102 FSSpec* spec )
Just van Rossumae4bcee2000-07-28 01:10:35 +0000103 {
104 Str255 p_path;
105 FT_ULong path_len;
106
107
108 /* convert path to a pascal string */
109 path_len = strlen( pathname );
110 if ( path_len > 255 )
111 return -1;
112 p_path[0] = (unsigned char)path_len;
Werner Lemberg05c21b82000-07-29 20:38:19 +0000113 strncpy( (char*)p_path + 1, pathname, path_len );
Just van Rossumae4bcee2000-07-28 01:10:35 +0000114
115 if ( FSMakeFSSpec( 0, 0, p_path, spec ) != noErr )
116 return -1;
117 else
118 return 0;
119 }
120
121
122 /* Return the file type of the file specified by spec. */
123 static
Werner Lemberg05c21b82000-07-29 20:38:19 +0000124 OSType get_file_type( FSSpec* spec )
Just van Rossumae4bcee2000-07-28 01:10:35 +0000125 {
Werner Lemberg05c21b82000-07-29 20:38:19 +0000126 FInfo finfo;
Just van Rossumae4bcee2000-07-28 01:10:35 +0000127
128
129 if ( FSpGetFInfo( spec, &finfo ) != noErr )
130 return 0; /* file might not exist */
Werner Lemberg05c21b82000-07-29 20:38:19 +0000131
Just van Rossumae4bcee2000-07-28 01:10:35 +0000132 return finfo.fdType;
133 }
134
135
136 /* Given a PostScript font name, create the Macintosh LWFN file name. */
137 static
Werner Lemberg05c21b82000-07-29 20:38:19 +0000138 void create_lwfn_name( char* ps_name,
139 Str255 lwfn_file_name )
Just van Rossumae4bcee2000-07-28 01:10:35 +0000140 {
141 int max = 5, count = 0;
142 FT_Byte* p = lwfn_file_name;
143 FT_Byte* q = (FT_Byte*)ps_name;
144
145
146 lwfn_file_name[0] = 0;
147
148 while ( *q )
149 {
Werner Lemberg05c21b82000-07-29 20:38:19 +0000150 if ( isupper( *q ) )
Just van Rossumae4bcee2000-07-28 01:10:35 +0000151 {
152 if ( count )
153 max = 3;
154 count = 0;
155 }
Werner Lemberg05c21b82000-07-29 20:38:19 +0000156 if ( count < max && ( isalnum( *q ) || *q == '_' ) )
Just van Rossumae4bcee2000-07-28 01:10:35 +0000157 {
158 *++p = *q;
159 lwfn_file_name[0]++;
160 count++;
161 }
162 q++;
163 }
164 }
165
166
167 /* Given a file reference, answer its location as a vRefNum
168 and a dirID. */
169 static
Werner Lemberg05c21b82000-07-29 20:38:19 +0000170 FT_Error get_file_location( short ref_num,
171 short* v_ref_num,
172 long* dir_id,
173 unsigned char* file_name )
Just van Rossumae4bcee2000-07-28 01:10:35 +0000174 {
175 FCBPBRec pb;
176 OSErr error;
177
Just van Rossumae4bcee2000-07-28 01:10:35 +0000178 pb.ioNamePtr = file_name;
179 pb.ioVRefNum = 0;
180 pb.ioRefNum = ref_num;
181 pb.ioFCBIndx = 0;
182
Werner Lemberg05c21b82000-07-29 20:38:19 +0000183
Just van Rossumae4bcee2000-07-28 01:10:35 +0000184 error = PBGetFCBInfoSync( &pb );
185 if ( error == noErr )
186 {
187 *v_ref_num = pb.ioFCBVRefNum;
Werner Lemberg05c21b82000-07-29 20:38:19 +0000188 *dir_id = pb.ioFCBParID;
Just van Rossumae4bcee2000-07-28 01:10:35 +0000189 }
190 return error;
191 }
192
193
194 /* Make a file spec for an LWFN file from a FOND resource and
195 a file name. */
196 static
197 FT_Error make_lwfn_spec( Handle fond,
198 unsigned char* file_name,
199 FSSpec* spec )
200 {
201 FT_Error error;
202 short ref_num, v_ref_num;
203 long dir_id;
204 Str255 fond_file_name;
205
206
207 ref_num = HomeResFile( fond );
Werner Lemberg05c21b82000-07-29 20:38:19 +0000208
Just van Rossumae4bcee2000-07-28 01:10:35 +0000209 error = ResError();
210 if ( !error )
Werner Lemberg05c21b82000-07-29 20:38:19 +0000211 error = get_file_location( ref_num, &v_ref_num,
212 &dir_id, fond_file_name );
Just van Rossumae4bcee2000-07-28 01:10:35 +0000213 if ( !error )
214 error = FSMakeFSSpec( v_ref_num, dir_id, file_name, spec );
215
216 return error;
217 }
218
219
220 /* Look inside the FOND data, answer whether there should be an SFNT
221 resource, and answer the name of a possible LWFN Type 1 file. */
222 static
223 void parse_fond( char* fond_data,
Werner Lemberg05c21b82000-07-29 20:38:19 +0000224 short* have_sfnt,
225 short* sfnt_id,
Just van Rossumae4bcee2000-07-28 01:10:35 +0000226 Str255 lwfn_file_name )
227 {
228 AsscEntry* assoc;
229 FamRec* fond;
230
231
232 *sfnt_id = 0;
233 *have_sfnt = 0;
234 lwfn_file_name[0] = 0;
235
236 fond = (FamRec*)fond_data;
Werner Lemberg05c21b82000-07-29 20:38:19 +0000237 assoc = (AsscEntry*)( fond_data + sizeof ( FamRec ) + 2 );
Just van Rossumae4bcee2000-07-28 01:10:35 +0000238
239 if ( assoc->fontSize == 0 )
240 {
241 *have_sfnt = 1;
242 *sfnt_id = assoc->fontID;
243 }
244
245 if ( fond->ffStylOff )
246 {
247 unsigned char* p = (unsigned char*)fond_data;
248 StyleTable* style;
249 unsigned short string_count;
250 unsigned char* name_table = 0;
251 char ps_name[256];
252 unsigned char* names[64];
253 int i;
254
Werner Lemberg05c21b82000-07-29 20:38:19 +0000255
Just van Rossumae4bcee2000-07-28 01:10:35 +0000256 p += fond->ffStylOff;
257 style = (StyleTable*)p;
Werner Lemberg05c21b82000-07-29 20:38:19 +0000258 p += sizeof ( StyleTable );
Just van Rossumae4bcee2000-07-28 01:10:35 +0000259 string_count = *(unsigned short*)(p);
Werner Lemberg05c21b82000-07-29 20:38:19 +0000260 p += sizeof ( short );
Just van Rossumae4bcee2000-07-28 01:10:35 +0000261
262 for ( i = 0 ; i < string_count && i < 64; i++ )
263 {
264 names[i] = p;
265 p += names[i][0];
266 p++;
267 }
Werner Lemberg05c21b82000-07-29 20:38:19 +0000268 strcpy( ps_name, p2c_str( names[0] ) ); /* Family name */
Just van Rossumae4bcee2000-07-28 01:10:35 +0000269
270 if ( style->indexes[0] > 1 )
271 {
Werner Lemberg05c21b82000-07-29 20:38:19 +0000272 unsigned char* suffixes = names[style->indexes[0] - 1];
273
274
Just van Rossumae4bcee2000-07-28 01:10:35 +0000275 for ( i=1; i<=suffixes[0]; i++ )
Werner Lemberg05c21b82000-07-29 20:38:19 +0000276 strcat( ps_name, p2c_str( names[suffixes[i] - 1 ] ) );
Just van Rossumae4bcee2000-07-28 01:10:35 +0000277 }
278 create_lwfn_name( ps_name, lwfn_file_name );
279 }
280 }
281
282
283 /* Read Type 1 data from the POST resources inside the LWFN file,
284 return a PFB buffer. This is somewhat convoluted because the FT2
285 PFB parser wants the ASCII header as one chunk, and the LWFN
286 chunks are often not organized that way, so we'll glue chunks
287 of the same type together. */
288 static
289 FT_Error read_lwfn( FT_Memory memory,
290 FSSpec* lwfn_spec,
291 FT_Byte** pfb_data,
292 FT_ULong* size )
293 {
294 FT_Error error = FT_Err_Ok;
295 short res_ref, res_id;
296 unsigned char *buffer, *p, *size_p;
297 FT_ULong total_size = 0;
298 FT_ULong post_size, pfb_chunk_size;
299 Handle post_data;
300 char code, last_code;
301
302
303 res_ref = FSpOpenResFile( lwfn_spec, fsRdPerm );
304 if ( ResError() )
305 return FT_Err_Out_Of_Memory;
306 UseResFile( res_ref );
307
308 /* First pass: load all POST resources, and determine the size of
309 the output buffer. */
310 res_id = 501;
311 last_code = -1;
Werner Lemberg05c21b82000-07-29 20:38:19 +0000312
Just van Rossumae4bcee2000-07-28 01:10:35 +0000313 for (;;)
314 {
315 post_data = Get1Resource( 'POST', res_id++ );
316 if ( post_data == NULL )
317 break; /* we're done */
318
319 code = (*post_data)[0];
320
321 if ( code != last_code )
322 {
323 if ( code == 5 )
324 total_size += 2; /* just the end code */
325 else
326 total_size += 6; /* code + 4 bytes chunk length */
327 }
328
329 total_size += GetHandleSize( post_data ) - 2;
330 last_code = code;
331 }
332
333 if ( ALLOC( buffer, (FT_Long)total_size ) )
334 goto Error;
335
336 /* Second pass: append all POST data to the buffer, add PFB fields.
Werner Lemberg05c21b82000-07-29 20:38:19 +0000337 Glue all consecutive chunks of the same type together. */
Just van Rossumae4bcee2000-07-28 01:10:35 +0000338 p = buffer;
339 res_id = 501;
340 last_code = -1;
341 pfb_chunk_size = 0;
342
343 for (;;)
344 {
345 post_data = Get1Resource( 'POST', res_id++ );
346 if ( post_data == NULL )
347 break; /* we're done */
348
349 post_size = (FT_ULong)GetHandleSize( post_data ) - 2;
350 code = (*post_data)[0];
351
352 if ( code != last_code )
353 {
354
355 if ( last_code != -1 )
356 {
357 /* we're done adding a chunk, fill in the size field */
Werner Lemberg05c21b82000-07-29 20:38:19 +0000358 *size_p++ = (FT_Byte)( pfb_chunk_size & 0xFF );
359 *size_p++ = (FT_Byte)( ( pfb_chunk_size >> 8 ) & 0xFF );
360 *size_p++ = (FT_Byte)( ( pfb_chunk_size >> 16 ) & 0xFF );
361 *size_p++ = (FT_Byte)( ( pfb_chunk_size >> 24 ) & 0xFF );
Just van Rossumae4bcee2000-07-28 01:10:35 +0000362 pfb_chunk_size = 0;
363 }
364
365 *p++ = 0x80;
366 if ( code == 5 )
367 *p++ = 0x03; /* the end */
368 else if ( code == 2 )
369 *p++ = 0x02; /* binary segment */
370 else
371 *p++ = 0x01; /* ASCII segment */
372
373 if ( code != 5 )
374 {
375 size_p = p; /* save for later */
376 p += 4; /* make space for size field */
377 }
378 }
379
380 memcpy( p, *post_data + 2, post_size );
381 pfb_chunk_size += post_size;
382 p += post_size;
383 last_code = code;
384 }
385
386 *pfb_data = buffer;
387 *size = total_size;
388
Werner Lemberg05c21b82000-07-29 20:38:19 +0000389 Error:
Just van Rossumae4bcee2000-07-28 01:10:35 +0000390 CloseResFile( res_ref );
391 return error;
392 }
393
394
395 /* Finalizer for a memory stream; gets called by FT_Done_Face().
396 It frees the memory it uses. */
397 static
Werner Lemberg05c21b82000-07-29 20:38:19 +0000398 void memory_stream_close( FT_Stream stream )
Just van Rossumae4bcee2000-07-28 01:10:35 +0000399 {
400 FT_Memory memory = stream->memory;
401
402
403 FREE( stream->base );
Werner Lemberg05c21b82000-07-29 20:38:19 +0000404
405 stream->size = 0;
406 stream->base = 0;
407 stream->close = 0;
Just van Rossumae4bcee2000-07-28 01:10:35 +0000408 }
409
410
411 /* Create a new memory stream from a buffer and a size. */
412 static
413 FT_Error new_memory_stream( FT_Library library,
414 FT_Byte* base,
415 FT_ULong size,
416 FT_Stream_Close close,
417 FT_Stream* astream )
418 {
419 FT_Error error;
420 FT_Memory memory;
421 FT_Stream stream;
422
423
424 if ( !library )
425 return FT_Err_Invalid_Library_Handle;
426
427 if ( !base )
428 return FT_Err_Invalid_Argument;
429
430 *astream = 0;
431 memory = library->memory;
Werner Lemberg05c21b82000-07-29 20:38:19 +0000432 if ( ALLOC( stream, sizeof ( *stream ) ) )
Just van Rossumae4bcee2000-07-28 01:10:35 +0000433 goto Exit;
434
435 FT_New_Memory_Stream( library,
436 base,
437 size,
438 stream );
439
440 stream->close = close;
441
442 *astream = stream;
443
444 Exit:
445 return error;
446 }
447
448
449 /* Create a new FT_Face given a buffer and a driver name. */
450 static
451 FT_Error open_face_from_buffer( FT_Library library,
452 FT_Byte* base,
453 FT_ULong size,
454 FT_Long face_index,
455 char* driver_name,
456 FT_Face* aface )
457 {
458 FT_Open_Args args;
459 FT_Error error;
460 FT_Stream stream;
461 FT_Memory memory = library->memory;
462
463
464 error = new_memory_stream( library,
465 base,
466 size,
467 memory_stream_close,
468 &stream );
469 if ( error )
470 {
471 FREE( base );
472 return error;
473 }
474
475 args.flags = ft_open_stream;
476 args.stream = stream;
477 if ( driver_name )
478 {
479 args.flags = args.flags | ft_open_driver;
480 args.driver = FT_Get_Module( library, driver_name );
481 }
Werner Lemberg05c21b82000-07-29 20:38:19 +0000482
Just van Rossumae4bcee2000-07-28 01:10:35 +0000483 error = FT_Open_Face( library, &args, face_index, aface );
Just van Rossum5fe94ff2000-07-28 02:25:23 +0000484 if ( error == FT_Err_Ok )
Just van Rossumae4bcee2000-07-28 01:10:35 +0000485 (*aface)->face_flags &= ~FT_FACE_FLAG_EXTERNAL_STREAM;
Just van Rossum5fe94ff2000-07-28 02:25:23 +0000486 else
487 {
488 FT_Done_Stream( stream );
489 FREE( stream );
490 }
Just van Rossumae4bcee2000-07-28 01:10:35 +0000491 return error;
492 }
493
494
495 /* Create a new FT_Face from a file spec to an LWFN file. */
496 static
Werner Lemberg05c21b82000-07-29 20:38:19 +0000497 FT_Error FT_New_Face_From_LWFN( FT_Library library,
498 FSSpec* spec,
499 FT_Long face_index,
500 FT_Face* aface )
Just van Rossumae4bcee2000-07-28 01:10:35 +0000501 {
Werner Lemberg05c21b82000-07-29 20:38:19 +0000502 FT_Byte* pfb_data;
503 FT_ULong pfb_size;
504 FT_Error error;
505 FT_Memory memory = library->memory;
Just van Rossumae4bcee2000-07-28 01:10:35 +0000506
507
508 error = read_lwfn( library->memory, spec, &pfb_data, &pfb_size );
509 if ( error )
510 return error;
511
512#if 0
513 {
Werner Lemberg05c21b82000-07-29 20:38:19 +0000514 FILE* f;
515 char* path;
516
Just van Rossumae4bcee2000-07-28 01:10:35 +0000517
518 path = p2c_str( spec->name );
519 strcat( path, ".PFB" );
Werner Lemberg05c21b82000-07-29 20:38:19 +0000520 f = fopen( path, "wb" );
Just van Rossumae4bcee2000-07-28 01:10:35 +0000521 if ( f )
522 {
523 fwrite( pfb_data, 1, pfb_size, f );
524 fclose( f );
525 }
526 }
527#endif
528
529 return open_face_from_buffer( library,
530 pfb_data,
531 pfb_size,
532 face_index,
533 "type1",
534 aface );
535 }
536
537
538 /* Create a new FT_Face from an SFNT resource, specified by res ID. */
539 static
Werner Lemberg05c21b82000-07-29 20:38:19 +0000540 FT_Error FT_New_Face_From_SFNT( FT_Library library,
541 short sfnt_id,
542 FT_Long face_index,
543 FT_Face* aface )
Just van Rossumae4bcee2000-07-28 01:10:35 +0000544 {
Werner Lemberg05c21b82000-07-29 20:38:19 +0000545 Handle sfnt = NULL;
546 FT_Byte* sfnt_data;
547 size_t sfnt_size;
548 FT_Stream stream = NULL;
549 FT_Error error = 0;
550 FT_Memory memory = library->memory;
Just van Rossumae4bcee2000-07-28 01:10:35 +0000551
552
553 sfnt = GetResource( 'sfnt', sfnt_id );
554 if ( ResError() )
555 return FT_Err_Invalid_Handle;
556
557 sfnt_size = (FT_ULong)GetHandleSize( sfnt );
558 if ( ALLOC( sfnt_data, (FT_Long)sfnt_size ) )
559 {
560 ReleaseResource( sfnt );
561 return error;
562 }
563
564 HLock( sfnt );
Werner Lemberg05c21b82000-07-29 20:38:19 +0000565 memcpy( sfnt_data, *sfnt, sfnt_size );
Just van Rossumae4bcee2000-07-28 01:10:35 +0000566 HUnlock( sfnt );
567 ReleaseResource( sfnt );
568
569 return open_face_from_buffer( library,
570 sfnt_data,
571 sfnt_size,
572 face_index,
573 "truetype",
574 aface );
575 }
576
577
578 /* Create a new FT_Face from a file spec to a suitcase file. */
579 static
Werner Lemberg05c21b82000-07-29 20:38:19 +0000580 FT_Error FT_New_Face_From_Suitcase( FT_Library library,
581 FSSpec* spec,
582 FT_Long face_index,
583 FT_Face* aface )
Just van Rossumae4bcee2000-07-28 01:10:35 +0000584 {
585 FT_Error error = FT_Err_Ok;
586 short res_ref, res_index;
587 Handle fond;
588
589
590 res_ref = FSpOpenResFile( spec, fsRdPerm );
591 if ( ResError() )
592 return FT_Err_Cannot_Open_Resource;
593 UseResFile( res_ref );
594
595 /* face_index may be -1, in which case we
596 just need to do a sanity check */
Werner Lemberg05c21b82000-07-29 20:38:19 +0000597 if ( face_index < 0 )
Just van Rossumae4bcee2000-07-28 01:10:35 +0000598 res_index = 1;
599 else
600 {
Werner Lemberg05c21b82000-07-29 20:38:19 +0000601 res_index = (short)( face_index + 1 );
Just van Rossumae4bcee2000-07-28 01:10:35 +0000602 face_index = 0;
603 }
604 fond = Get1IndResource( 'FOND', res_index );
605 if ( ResError() )
606 {
607 error = FT_Err_Cannot_Open_Resource;
608 goto Error;
609 }
610
611 error = FT_New_Face_From_FOND( library, fond, face_index, aface );
612
Werner Lemberg05c21b82000-07-29 20:38:19 +0000613 Error:
Just van Rossumae4bcee2000-07-28 01:10:35 +0000614 CloseResFile( res_ref );
615 return error;
616 }
617
618
Werner Lemberg90a03302000-11-07 17:21:11 +0000619 /* documentation in ftmac.h */
620
David Turner76a5f622000-11-04 01:55:49 +0000621 FT_EXPORT_DEF( FT_Error ) FT_New_Face_From_FOND( FT_Library library,
622 Handle fond,
623 FT_Long face_index,
Werner Lemberg4b680072000-11-07 06:30:29 +0000624 FT_Face *aface )
Just van Rossumae4bcee2000-07-28 01:10:35 +0000625 {
626 short sfnt_id, have_sfnt, have_lwfn = 0;
627 Str255 lwfn_file_name;
628 short fond_id;
629 OSType fond_type;
630 Str255 fond_name;
631 FSSpec lwfn_spec;
632 FT_Error error = FT_Err_Unknown_File_Format;
633
634
635 GetResInfo(fond, &fond_id, &fond_type, fond_name);
636 if ( ResError() != noErr || fond_type != 'FOND' )
637 return FT_Err_Invalid_File_Format;
638
639 HLock( fond );
640 parse_fond( *fond, &have_sfnt, &sfnt_id, lwfn_file_name );
641 HUnlock( fond );
642
643 if ( lwfn_file_name[0] )
644 {
645 if ( make_lwfn_spec( fond, lwfn_file_name, &lwfn_spec ) == FT_Err_Ok )
646 have_lwfn = 1; /* yeah, we got one! */
647 else
648 have_lwfn = 0; /* no LWFN file found */
649 }
650
651 if ( have_lwfn && ( !have_sfnt || PREFER_LWFN ) )
652 return FT_New_Face_From_LWFN( library,
653 &lwfn_spec,
654 face_index,
655 aface );
656 else if ( have_sfnt )
657 return FT_New_Face_From_SFNT( library,
658 sfnt_id,
659 face_index,
660 aface );
661
662 return FT_Err_Unknown_File_Format;
663 }
664
665
666 /*************************************************************************/
667 /* */
668 /* <Function> */
669 /* FT_New_Face */
670 /* */
671 /* <Description> */
672 /* This is the Mac-specific implementation of FT_New_Face. In */
Werner Lemberg05c21b82000-07-29 20:38:19 +0000673 /* addition to the standard FT_New_Face() functionality, it also */
Just van Rossumae4bcee2000-07-28 01:10:35 +0000674 /* accepts pathnames to Mac suitcase files. For further */
Werner Lemberg90a03302000-11-07 17:21:11 +0000675 /* documentation see the original FT_New_Face() in freetype.h. */
Just van Rossumae4bcee2000-07-28 01:10:35 +0000676 /* */
David Turner76a5f622000-11-04 01:55:49 +0000677 FT_EXPORT_DEF( FT_Error ) FT_New_Face( FT_Library library,
678 const char* pathname,
679 FT_Long face_index,
Werner Lemberg4b680072000-11-07 06:30:29 +0000680 FT_Face *aface )
Just van Rossumae4bcee2000-07-28 01:10:35 +0000681 {
682 FT_Open_Args args;
683 FSSpec spec;
684 OSType file_type;
685
686
687 /* test for valid `library' and `aface' delayed to FT_Open_Face() */
688 if ( !pathname )
689 return FT_Err_Invalid_Argument;
690
691 if ( file_spec_from_path( pathname, &spec ) )
692 return FT_Err_Invalid_Argument;
693
694 file_type = get_file_type( &spec );
695 if ( file_type == 'FFIL' || file_type == 'tfil' )
696 return FT_New_Face_From_Suitcase( library, &spec, face_index, aface );
697 else if ( file_type == 'LWFN' )
698 return FT_New_Face_From_LWFN( library, &spec, face_index, aface );
699 else
700 {
701 args.flags = ft_open_pathname;
702 args.pathname = (char*)pathname;
703
704 return FT_Open_Face( library, &args, face_index, aface );
705 }
706 }
707
Werner Lemberg05c21b82000-07-29 20:38:19 +0000708
709/* END */