zenilib: zenilib/jni/external/freetype2/src/base/ftmac.c Source File

zenilib 0.5.3.0

- Main Page
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
ftmac.c
Go to the documentation of this file.
1 /***************************************************************************/
2 /* */
3 /* ftmac.c */
4 /* */
5 /* Mac FOND support. Written by just@letterror.com. */
6 /* Heavily modified by mpsuzuki, George Williams, and Sean McBride. */
7 /* */
8 /* This file is for Mac OS X only; see builds/mac/ftoldmac.c for */
9 /* classic platforms built by MPW. */
10 /* */
11 /* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, */
12 /* 2009 by */
13 /* Just van Rossum, David Turner, Robert Wilhelm, and Werner Lemberg. */
14 /* */
15 /* This file is part of the FreeType project, and may only be used, */
16 /* modified, and distributed under the terms of the FreeType project */
17 /* license, LICENSE.TXT. By continuing to use, modify, or distribute */
18 /* this file you indicate that you have read the license and */
19 /* understand and accept it fully. */
20 /* */
21 /***************************************************************************/
22
23
24 /*
25 Notes
26
27 Mac suitcase files can (and often do!) contain multiple fonts. To
28 support this I use the face_index argument of FT_(Open|New)_Face()
29 functions, and pretend the suitcase file is a collection.
30
31 Warning: fbit and NFNT bitmap resources are not supported yet. In old
32 sfnt fonts, bitmap glyph data for each size is stored in each `NFNT'
33 resources instead of the `bdat' table in the sfnt resource. Therefore,
34 face->num_fixed_sizes is set to 0, because bitmap data in `NFNT'
35 resource is unavailable at present.
36
37 The Mac FOND support works roughly like this:
38
39 - Check whether the offered stream points to a Mac suitcase file. This
40 is done by checking the file type: it has to be 'FFIL' or 'tfil'. The
41 stream that gets passed to our init_face() routine is a stdio stream,
42 which isn't usable for us, since the FOND resources live in the
43 resource fork. So we just grab the stream->pathname field.
44
45 - Read the FOND resource into memory, then check whether there is a
46 TrueType font and/or(!) a Type 1 font available.
47
48 - If there is a Type 1 font available (as a separate `LWFN' file), read
49 its data into memory, massage it slightly so it becomes PFB data, wrap
50 it into a memory stream, load the Type 1 driver and delegate the rest
51 of the work to it by calling FT_Open_Face(). (XXX TODO: after this
52 has been done, the kerning data from the FOND resource should be
53 appended to the face: On the Mac there are usually no AFM files
54 available. However, this is tricky since we need to map Mac char
55 codes to ps glyph names to glyph ID's...)
56
57 - If there is a TrueType font (an `sfnt' resource), read it into memory,
58 wrap it into a memory stream, load the TrueType driver and delegate
59 the rest of the work to it, by calling FT_Open_Face().
60
61 - Some suitcase fonts (notably Onyx) might point the `LWFN' file to
62 itself, even though it doesn't contains `POST' resources. To handle
63 this special case without opening the file an extra time, we just
64 ignore errors from the `LWFN' and fallback to the `sfnt' if both are
65 available.
66 */
67
68
69 #include <ft2build.h>
70 #include FT_FREETYPE_H
71 #include FT_TRUETYPE_TAGS_H
72 #include FT_INTERNAL_STREAM_H
73 #include "ftbase.h"
74
75 /* This is for Mac OS X. Without redefinition, OS_INLINE */
76 /* expands to `static inline' which doesn't survive the */
77 /* -ansi compilation flag of GCC. */
78 #if !HAVE_ANSI_OS_INLINE
79 #undef OS_INLINE
80 #define OS_INLINE static __inline__
81 #endif
82
83 /* `configure' checks the availability of `ResourceIndex' strictly */
84 /* and sets HAVE_TYPE_RESOURCE_INDEX 1 or 0 always. If it is */
85 /* not set (e.g., a build without `configure'), the availability */
86 /* is guessed from the SDK version. */
87 #ifndef HAVE_TYPE_RESOURCE_INDEX
88 #if !defined( MAC_OS_X_VERSION_10_5 ) || \
89 ( MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5 )
90 #define HAVE_TYPE_RESOURCE_INDEX 0
91 #else
92 #define HAVE_TYPE_RESOURCE_INDEX 1
93 #endif
94 #endif /* !HAVE_TYPE_RESOURCE_INDEX */
95
96 #if ( HAVE_TYPE_RESOURCE_INDEX == 0 )
97 typedef short ResourceIndex;
98 #endif
99
100 #include <CoreServices/CoreServices.h>
101 #include <ApplicationServices/ApplicationServices.h>
102 #include <sys/syslimits.h> /* PATH_MAX */
103
104 /* Don't want warnings about our own use of deprecated functions. */
105 #define FT_DEPRECATED_ATTRIBUTE
106
107 #include FT_MAC_H
108
109 #ifndef kATSOptionFlagsUnRestrictedScope /* since Mac OS X 10.1 */
110 #define kATSOptionFlagsUnRestrictedScope kATSOptionFlagsDefault
111 #endif
112
113
114 /* Set PREFER_LWFN to 1 if LWFN (Type 1) is preferred over
115 TrueType in case *both* are available (this is not common,
116 but it *is* possible). */
117 #ifndef PREFER_LWFN
118 #define PREFER_LWFN 1
119 #endif
120
121
122 #ifdef FT_MACINTOSH
123
124 /* This function is deprecated because FSSpec is deprecated in Mac OS X */
125 FT_EXPORT_DEF( FT_Error )
126 FT_GetFile_From_Mac_Name( const char* fontName,
127 FSSpec* pathSpec,
128 FT_Long* face_index )
129 {
130 FT_UNUSED( fontName );
131 FT_UNUSED( pathSpec );
132 FT_UNUSED( face_index );
133
134 return FT_Err_Unimplemented_Feature;
135 }
136
137
138 /* Private function. */
139 /* The FSSpec type has been discouraged for a long time, */
140 /* unfortunately an FSRef replacement API for */
141 /* ATSFontGetFileSpecification() is only available in */
142 /* Mac OS X 10.5 and later. */
143 static OSStatus
144 FT_ATSFontGetFileReference( ATSFontRef ats_font_id,
145 FSRef* ats_font_ref )
146 {
147 #if defined( MAC_OS_X_VERSION_10_5 ) && \
148 ( MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 )
149
150 OSStatus err;
151
152 err = ATSFontGetFileReference( ats_font_id, ats_font_ref );
153
154 return err;
155 #elif __LP64__ /* No 64bit Carbon API on legacy platforms */
156 FT_UNUSED( ats_font_id );
157 FT_UNUSED( ats_font_ref );
158
159
160 return fnfErr;
161 #else /* 32bit Carbon API on legacy platforms */
162 OSStatus err;
163 FSSpec spec;
164
165
166 err = ATSFontGetFileSpecification( ats_font_id, &spec );
167 if ( noErr == err )
168 err = FSpMakeFSRef( &spec, ats_font_ref );
169
170 return err;
171 #endif
172 }
173
174
175 static FT_Error
176 FT_GetFileRef_From_Mac_ATS_Name( const char* fontName,
177 FSRef* ats_font_ref,
178 FT_Long* face_index )
179 {
180 CFStringRef cf_fontName;
181 ATSFontRef ats_font_id;
182
183
184 *face_index = 0;
185
186 cf_fontName = CFStringCreateWithCString( NULL, fontName,
187 kCFStringEncodingMacRoman );
188 ats_font_id = ATSFontFindFromName( cf_fontName,
189 kATSOptionFlagsUnRestrictedScope );
190 CFRelease( cf_fontName );
191
192 if ( ats_font_id == 0 || ats_font_id == 0xFFFFFFFFUL )
193 return FT_Err_Unknown_File_Format;
194
195 if ( noErr != FT_ATSFontGetFileReference( ats_font_id, ats_font_ref ) )
196 return FT_Err_Unknown_File_Format;
197
198 /* face_index calculation by searching preceding fontIDs */
199 /* with same FSRef */
200 {
201 ATSFontRef id2 = ats_font_id - 1;
202 FSRef ref2;
203
204
205 while ( id2 > 0 )
206 {
207 if ( noErr != FT_ATSFontGetFileReference( id2, &ref2 ) )
208 break;
209 if ( noErr != FSCompareFSRefs( ats_font_ref, &ref2 ) )
210 break;
211
212 id2 --;
213 }
214 *face_index = ats_font_id - ( id2 + 1 );
215 }
216
217 return FT_Err_Ok;
218 }
219
220
221 FT_EXPORT_DEF( FT_Error )
222 FT_GetFilePath_From_Mac_ATS_Name( const char* fontName,
223 UInt8* path,
224 UInt32 maxPathSize,
225 FT_Long* face_index )
226 {
227 FSRef ref;
228 FT_Error err;
229
230
231 err = FT_GetFileRef_From_Mac_ATS_Name( fontName, &ref, face_index );
232 if ( FT_Err_Ok != err )
233 return err;
234
235 if ( noErr != FSRefMakePath( &ref, path, maxPathSize ) )
236 return FT_Err_Unknown_File_Format;
237
238 return FT_Err_Ok;
239 }
240
241
242 /* This function is deprecated because FSSpec is deprecated in Mac OS X */
243 FT_EXPORT_DEF( FT_Error )
244 FT_GetFile_From_Mac_ATS_Name( const char* fontName,
245 FSSpec* pathSpec,
246 FT_Long* face_index )
247 {
248 #if ( __LP64__ ) || ( defined( MAC_OS_X_VERSION_10_5 ) && \
249 ( MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 ) )
250 FT_UNUSED( fontName );
251 FT_UNUSED( pathSpec );
252 FT_UNUSED( face_index );
253
254 return FT_Err_Unimplemented_Feature;
255 #else
256 FSRef ref;
257 FT_Error err;
258
259
260 err = FT_GetFileRef_From_Mac_ATS_Name( fontName, &ref, face_index );
261 if ( FT_Err_Ok != err )
262 return err;
263
264 if ( noErr != FSGetCatalogInfo( &ref, kFSCatInfoNone, NULL, NULL,
265 pathSpec, NULL ) )
266 return FT_Err_Unknown_File_Format;
267
268 return FT_Err_Ok;
269 #endif
270 }
271
272
273 static OSErr
274 FT_FSPathMakeRes( const UInt8* pathname,
275 ResFileRefNum* res )
276 {
277 OSErr err;
278 FSRef ref;
279
280
281 if ( noErr != FSPathMakeRef( pathname, &ref, FALSE ) )
282 return FT_Err_Cannot_Open_Resource;
283
284 /* at present, no support for dfont format */
285 err = FSOpenResourceFile( &ref, 0, NULL, fsRdPerm, res );
286 if ( noErr == err )
287 return err;
288
289 /* fallback to original resource-fork font */
290 *res = FSOpenResFile( &ref, fsRdPerm );
291 err = ResError();
292
293 return err;
294 }
295
296
297 /* Return the file type for given pathname */
298 static OSType
299 get_file_type_from_path( const UInt8* pathname )
300 {
301 FSRef ref;
302 FSCatalogInfo info;
303
304
305 if ( noErr != FSPathMakeRef( pathname, &ref, FALSE ) )
306 return ( OSType ) 0;
307
308 if ( noErr != FSGetCatalogInfo( &ref, kFSCatInfoFinderInfo, &info,
309 NULL, NULL, NULL ) )
310 return ( OSType ) 0;
311
312 return ((FInfo *)(info.finderInfo))->fdType;
313 }
314
315
316 /* Given a PostScript font name, create the Macintosh LWFN file name. */
317 static void
318 create_lwfn_name( char* ps_name,
319 Str255 lwfn_file_name )
320 {
321 int max = 5, count = 0;
322 FT_Byte* p = lwfn_file_name;
323 FT_Byte* q = (FT_Byte*)ps_name;
324
325
326 lwfn_file_name[0] = 0;
327
328 while ( *q )
329 {
330 if ( ft_isupper( *q ) )
331 {
332 if ( count )
333 max = 3;
334 count = 0;
335 }
336 if ( count < max && ( ft_isalnum( *q ) || *q == '_' ) )
337 {
338 *++p = *q;
339 lwfn_file_name[0]++;
340 count++;
341 }
342 q++;
343 }
344 }
345
346
347 static short
348 count_faces_sfnt( char* fond_data )
349 {
350 /* The count is 1 greater than the value in the FOND. */
351 /* Isn't that cute? :-) */
352
353 return EndianS16_BtoN( *( (short*)( fond_data +
354 sizeof ( FamRec ) ) ) ) + 1;
355 }
356
357
358 static short
359 count_faces_scalable( char* fond_data )
360 {
361 AsscEntry* assoc;
362 FamRec* fond;
363 short i, face, face_all;
364
365
366 fond = (FamRec*)fond_data;
367 face_all = EndianS16_BtoN( *( (short *)( fond_data +
368 sizeof ( FamRec ) ) ) ) + 1;
369 assoc = (AsscEntry*)( fond_data + sizeof ( FamRec ) + 2 );
370 face = 0;
371
372 for ( i = 0; i < face_all; i++ )
373 {
374 if ( 0 == EndianS16_BtoN( assoc[i].fontSize ) )
375 face++;
376 }
377 return face;
378 }
379
380
381 /* Look inside the FOND data, answer whether there should be an SFNT
382 resource, and answer the name of a possible LWFN Type 1 file.
383
384 Thanks to Paul Miller (paulm@profoundeffects.com) for the fix
385 to load a face OTHER than the first one in the FOND!
386 */
387
388
389 static void
390 parse_fond( char* fond_data,
391 short* have_sfnt,
392 ResID* sfnt_id,
393 Str255 lwfn_file_name,
394 short face_index )
395 {
396 AsscEntry* assoc;
397 AsscEntry* base_assoc;
398 FamRec* fond;
399
400
401 *sfnt_id = 0;
402 *have_sfnt = 0;
403 lwfn_file_name[0] = 0;
404
405 fond = (FamRec*)fond_data;
406 assoc = (AsscEntry*)( fond_data + sizeof ( FamRec ) + 2 );
407 base_assoc = assoc;
408
409 /* the maximum faces in a FOND is 48, size of StyleTable.indexes[] */
410 if ( 47 < face_index )
411 return;
412
413 /* Let's do a little range checking before we get too excited here */
414 if ( face_index < count_faces_sfnt( fond_data ) )
415 {
416 assoc += face_index; /* add on the face_index! */
417
418 /* if the face at this index is not scalable,
419 fall back to the first one (old behavior) */
420 if ( EndianS16_BtoN( assoc->fontSize ) == 0 )
421 {
422 *have_sfnt = 1;
423 *sfnt_id = EndianS16_BtoN( assoc->fontID );
424 }
425 else if ( base_assoc->fontSize == 0 )
426 {
427 *have_sfnt = 1;
428 *sfnt_id = EndianS16_BtoN( base_assoc->fontID );
429 }
430 }
431
432 if ( EndianS32_BtoN( fond->ffStylOff ) )
433 {
434 unsigned char* p = (unsigned char*)fond_data;
435 StyleTable* style;
436 unsigned short string_count;
437 char ps_name[256];
438 unsigned char* names[64];
439 int i;
440
441
442 p += EndianS32_BtoN( fond->ffStylOff );
443 style = (StyleTable*)p;
444 p += sizeof ( StyleTable );
445 string_count = EndianS16_BtoN( *(short*)(p) );
446 p += sizeof ( short );
447
448 for ( i = 0; i < string_count && i < 64; i++ )
449 {
450 names[i] = p;
451 p += names[i][0];
452 p++;
453 }
454
455 {
456 size_t ps_name_len = (size_t)names[0][0];
457
458
459 if ( ps_name_len != 0 )
460 {
461 ft_memcpy(ps_name, names[0] + 1, ps_name_len);
462 ps_name[ps_name_len] = 0;
463 }
464 if ( style->indexes[face_index] > 1 &&
465 style->indexes[face_index] <= FT_MIN( string_count, 64 ) )
466 {
467 unsigned char* suffixes = names[style->indexes[face_index] - 1];
468
469
470 for ( i = 1; i <= suffixes[0]; i++ )
471 {
472 unsigned char* s;
473 size_t j = suffixes[i] - 1;
474
475
476 if ( j < string_count && ( s = names[j] ) != NULL )
477 {
478 size_t s_len = (size_t)s[0];
479
480
481 if ( s_len != 0 && ps_name_len + s_len < sizeof ( ps_name ) )
482 {
483 ft_memcpy( ps_name + ps_name_len, s + 1, s_len );
484 ps_name_len += s_len;
485 ps_name[ps_name_len] = 0;
486 }
487 }
488 }
489 }
490 }
491
492 create_lwfn_name( ps_name, lwfn_file_name );
493 }
494 }
495
496
497 static FT_Error
498 lookup_lwfn_by_fond( const UInt8* path_fond,
499 ConstStr255Param base_lwfn,
500 UInt8* path_lwfn,
501 size_t path_size )
502 {
503 FSRef ref, par_ref;
504 size_t dirname_len;
505
506
507 /* Pathname for FSRef can be in various formats: HFS, HFS+, and POSIX. */
508 /* We should not extract parent directory by string manipulation. */
509
510 if ( noErr != FSPathMakeRef( path_fond, &ref, FALSE ) )
511 return FT_Err_Invalid_Argument;
512
513 if ( noErr != FSGetCatalogInfo( &ref, kFSCatInfoNone,
514 NULL, NULL, NULL, &par_ref ) )
515 return FT_Err_Invalid_Argument;
516
517 if ( noErr != FSRefMakePath( &par_ref, path_lwfn, path_size ) )
518 return FT_Err_Invalid_Argument;
519
520 if ( ft_strlen( (char *)path_lwfn ) + 1 + base_lwfn[0] > path_size )
521 return FT_Err_Invalid_Argument;
522
523 /* now we have absolute dirname in path_lwfn */
524 ft_strcat( (char *)path_lwfn, "/" );
525 dirname_len = ft_strlen( (char *)path_lwfn );
526 ft_strcat( (char *)path_lwfn, (char *)base_lwfn + 1 );
527 path_lwfn[dirname_len + base_lwfn[0]] = '\0';
528
529 if ( noErr != FSPathMakeRef( path_lwfn, &ref, FALSE ) )
530 return FT_Err_Cannot_Open_Resource;
531
532 if ( noErr != FSGetCatalogInfo( &ref, kFSCatInfoNone,
533 NULL, NULL, NULL, NULL ) )
534 return FT_Err_Cannot_Open_Resource;
535
536 return FT_Err_Ok;
537 }
538
539
540 static short
541 count_faces( Handle fond,
542 const UInt8* pathname )
543 {
544 ResID sfnt_id;
545 short have_sfnt, have_lwfn;
546 Str255 lwfn_file_name;
547 UInt8 buff[PATH_MAX];
548 FT_Error err;
549 short num_faces;
550
551
552 have_sfnt = have_lwfn = 0;
553
554 parse_fond( *fond, &have_sfnt, &sfnt_id, lwfn_file_name, 0 );
555
556 if ( lwfn_file_name[0] )
557 {
558 err = lookup_lwfn_by_fond( pathname, lwfn_file_name,
559 buff, sizeof ( buff ) );
560 if ( FT_Err_Ok == err )
561 have_lwfn = 1;
562 }
563
564 if ( have_lwfn && ( !have_sfnt || PREFER_LWFN ) )
565 num_faces = 1;
566 else
567 num_faces = count_faces_scalable( *fond );
568
569 return num_faces;
570 }
571
572
573 /* Read Type 1 data from the POST resources inside the LWFN file,
574 return a PFB buffer. This is somewhat convoluted because the FT2
575 PFB parser wants the ASCII header as one chunk, and the LWFN
576 chunks are often not organized that way, so we glue chunks
577 of the same type together. */
578 static FT_Error
579 read_lwfn( FT_Memory memory,
580 ResFileRefNum res,
581 FT_Byte** pfb_data,
582 FT_ULong* size )
583 {
584 FT_Error error = FT_Err_Ok;
585 ResID res_id;
586 unsigned char *buffer, *p, *size_p = NULL;
587 FT_ULong total_size = 0;
588 FT_ULong old_total_size = 0;
589 FT_ULong post_size, pfb_chunk_size;
590 Handle post_data;
591 char code, last_code;
592
593
594 UseResFile( res );
595
596 /* First pass: load all POST resources, and determine the size of */
597 /* the output buffer. */
598 res_id = 501;
599 last_code = -1;
600
601 for (;;)
602 {
603 post_data = Get1Resource( TTAG_POST, res_id++ );
604 if ( post_data == NULL )
605 break; /* we are done */
606
607 code = (*post_data)[0];
608
609 if ( code != last_code )
610 {
611 if ( code == 5 )
612 total_size += 2; /* just the end code */
613 else
614 total_size += 6; /* code + 4 bytes chunk length */
615 }
616
617 total_size += GetHandleSize( post_data ) - 2;
618 last_code = code;
619
620 /* detect integer overflows */
621 if ( total_size < old_total_size )
622 {
623 error = FT_Err_Array_Too_Large;
624 goto Error;
625 }
626
627 old_total_size = total_size;
628 }
629
630 if ( FT_ALLOC( buffer, (FT_Long)total_size ) )
631 goto Error;
632
633 /* Second pass: append all POST data to the buffer, add PFB fields. */
634 /* Glue all consecutive chunks of the same type together. */
635 p = buffer;
636 res_id = 501;
637 last_code = -1;
638 pfb_chunk_size = 0;
639
640 for (;;)
641 {
642 post_data = Get1Resource( TTAG_POST, res_id++ );
643 if ( post_data == NULL )
644 break; /* we are done */
645
646 post_size = (FT_ULong)GetHandleSize( post_data ) - 2;
647 code = (*post_data)[0];
648
649 if ( code != last_code )
650 {
651 if ( last_code != -1 )
652 {
653 /* we are done adding a chunk, fill in the size field */
654 if ( size_p != NULL )
655 {
656 *size_p++ = (FT_Byte)( pfb_chunk_size & 0xFF );
657 *size_p++ = (FT_Byte)( ( pfb_chunk_size >> 8 ) & 0xFF );
658 *size_p++ = (FT_Byte)( ( pfb_chunk_size >> 16 ) & 0xFF );
659 *size_p++ = (FT_Byte)( ( pfb_chunk_size >> 24 ) & 0xFF );
660 }
661 pfb_chunk_size = 0;
662 }
663
664 *p++ = 0x80;
665 if ( code == 5 )
666 *p++ = 0x03; /* the end */
667 else if ( code == 2 )
668 *p++ = 0x02; /* binary segment */
669 else
670 *p++ = 0x01; /* ASCII segment */
671
672 if ( code != 5 )
673 {
674 size_p = p; /* save for later */
675 p += 4; /* make space for size field */
676 }
677 }
678
679 ft_memcpy( p, *post_data + 2, post_size );
680 pfb_chunk_size += post_size;
681 p += post_size;
682 last_code = code;
683 }
684
685 *pfb_data = buffer;
686 *size = total_size;
687
688 Error:
689 CloseResFile( res );
690 return error;
691 }
692
693
694 /* Create a new FT_Face from a file path to an LWFN file. */
695 static FT_Error
696 FT_New_Face_From_LWFN( FT_Library library,
697 const UInt8* pathname,
698 FT_Long face_index,
699 FT_Face* aface )
700 {
701 FT_Byte* pfb_data;
702 FT_ULong pfb_size;
703 FT_Error error;
704 ResFileRefNum res;
705
706
707 if ( noErr != FT_FSPathMakeRes( pathname, &res ) )
708 return FT_Err_Cannot_Open_Resource;
709
710 pfb_data = NULL;
711 pfb_size = 0;
712 error = read_lwfn( library->memory, res, &pfb_data, &pfb_size );
713 CloseResFile( res ); /* PFB is already loaded, useless anymore */
714 if ( error )
715 return error;
716
717 return open_face_from_buffer( library,
718 pfb_data,
719 pfb_size,
720 face_index,
721 "type1",
722 aface );
723 }
724
725
726 /* Create a new FT_Face from an SFNT resource, specified by res ID. */
727 static FT_Error
728 FT_New_Face_From_SFNT( FT_Library library,
729 ResID sfnt_id,
730 FT_Long face_index,
731 FT_Face* aface )
732 {
733 Handle sfnt = NULL;
734 FT_Byte* sfnt_data;
735 size_t sfnt_size;
736 FT_Error error = FT_Err_Ok;
737 FT_Memory memory = library->memory;
738 int is_cff, is_sfnt_ps;
739
740
741 sfnt = GetResource( TTAG_sfnt, sfnt_id );
742 if ( sfnt == NULL )
743 return FT_Err_Invalid_Handle;
744
745 sfnt_size = (FT_ULong)GetHandleSize( sfnt );
746 if ( FT_ALLOC( sfnt_data, (FT_Long)sfnt_size ) )
747 {
748 ReleaseResource( sfnt );
749 return error;
750 }
751
752 ft_memcpy( sfnt_data, *sfnt, sfnt_size );
753 ReleaseResource( sfnt );
754
755 is_cff = sfnt_size > 4 && !ft_memcmp( sfnt_data, "OTTO", 4 );
756 is_sfnt_ps = sfnt_size > 4 && !ft_memcmp( sfnt_data, "typ1", 4 );
757
758 if ( is_sfnt_ps )
759 {
760 FT_Stream stream;
761
762
763 if ( FT_NEW( stream ) )
764 goto Try_OpenType;
765
766 FT_Stream_OpenMemory( stream, sfnt_data, sfnt_size );
767 if ( !open_face_PS_from_sfnt_stream( library,
768 stream,
769 face_index,
770 0, NULL,
771 aface ) )
772 {
773 FT_Stream_Close( stream );
774 FT_FREE( stream );
775 FT_FREE( sfnt_data );
776 goto Exit;
777 }
778
779 FT_FREE( stream );
780 }
781 Try_OpenType:
782 error = open_face_from_buffer( library,
783 sfnt_data,
784 sfnt_size,
785 face_index,
786 is_cff ? "cff" : "truetype",
787 aface );
788 Exit:
789 return error;
790 }
791
792
793 /* Create a new FT_Face from a file path to a suitcase file. */
794 static FT_Error
795 FT_New_Face_From_Suitcase( FT_Library library,
796 const UInt8* pathname,
797 FT_Long face_index,
798 FT_Face* aface )
799 {
800 FT_Error error = FT_Err_Cannot_Open_Resource;
801 ResFileRefNum res_ref;
802 ResourceIndex res_index;
803 Handle fond;
804 short num_faces_in_res, num_faces_in_fond;
805
806
807 if ( noErr != FT_FSPathMakeRes( pathname, &res_ref ) )
808 return FT_Err_Cannot_Open_Resource;
809
810 UseResFile( res_ref );
811 if ( ResError() )
812 return FT_Err_Cannot_Open_Resource;
813
814 num_faces_in_res = 0;
815 for ( res_index = 1; ; ++res_index )
816 {
817 fond = Get1IndResource( TTAG_FOND, res_index );
818 if ( ResError() )
819 break;
820
821 num_faces_in_fond = count_faces( fond, pathname );
822 num_faces_in_res += num_faces_in_fond;
823
824 if ( 0 <= face_index && face_index < num_faces_in_fond && error )
825 error = FT_New_Face_From_FOND( library, fond, face_index, aface );
826
827 face_index -= num_faces_in_fond;
828 }
829
830 CloseResFile( res_ref );
831 if ( FT_Err_Ok == error && NULL != aface && NULL != *aface )
832 (*aface)->num_faces = num_faces_in_res;
833 return error;
834 }
835
836
837 /* documentation is in ftmac.h */
838
839 FT_EXPORT_DEF( FT_Error )
840 FT_New_Face_From_FOND( FT_Library library,
841 Handle fond,
842 FT_Long face_index,
843 FT_Face* aface )
844 {
845 short have_sfnt, have_lwfn = 0;
846 ResID sfnt_id, fond_id;
847 OSType fond_type;
848 Str255 fond_name;
849 Str255 lwfn_file_name;
850 UInt8 path_lwfn[PATH_MAX];
851 OSErr err;
852 FT_Error error = FT_Err_Ok;
853
854
855 GetResInfo( fond, &fond_id, &fond_type, fond_name );
856 if ( ResError() != noErr || fond_type != TTAG_FOND )
857 return FT_Err_Invalid_File_Format;
858
859 parse_fond( *fond, &have_sfnt, &sfnt_id, lwfn_file_name, face_index );
860
861 if ( lwfn_file_name[0] )
862 {
863 ResFileRefNum res;
864
865
866 res = HomeResFile( fond );
867 if ( noErr != ResError() )
868 goto found_no_lwfn_file;
869
870 {
871 UInt8 path_fond[PATH_MAX];
872 FSRef ref;
873
874
875 err = FSGetForkCBInfo( res, kFSInvalidVolumeRefNum,
876 NULL, NULL, NULL, &ref, NULL );
877 if ( noErr != err )
878 goto found_no_lwfn_file;
879
880 err = FSRefMakePath( &ref, path_fond, sizeof ( path_fond ) );
881 if ( noErr != err )
882 goto found_no_lwfn_file;
883
884 error = lookup_lwfn_by_fond( path_fond, lwfn_file_name,
885 path_lwfn, sizeof ( path_lwfn ) );
886 if ( FT_Err_Ok == error )
887 have_lwfn = 1;
888 }
889 }
890
891 if ( have_lwfn && ( !have_sfnt || PREFER_LWFN ) )
892 error = FT_New_Face_From_LWFN( library,
893 path_lwfn,
894 face_index,
895 aface );
896 else
897 error = FT_Err_Unknown_File_Format;
898
899 found_no_lwfn_file:
900 if ( have_sfnt && FT_Err_Ok != error )
901 error = FT_New_Face_From_SFNT( library,
902 sfnt_id,
903 face_index,
904 aface );
905
906 return error;
907 }
908
909
910 /* Common function to load a new FT_Face from a resource file. */
911 static FT_Error
912 FT_New_Face_From_Resource( FT_Library library,
913 const UInt8* pathname,
914 FT_Long face_index,
915 FT_Face* aface )
916 {
917 OSType file_type;
918 FT_Error error;
919
920
921 /* LWFN is a (very) specific file format, check for it explicitly */
922 file_type = get_file_type_from_path( pathname );
923 if ( file_type == TTAG_LWFN )
924 return FT_New_Face_From_LWFN( library, pathname, face_index, aface );
925
926 /* Otherwise the file type doesn't matter (there are more than */
927 /* `FFIL' and `tfil'). Just try opening it as a font suitcase; */
928 /* if it works, fine. */
929
930 error = FT_New_Face_From_Suitcase( library, pathname, face_index, aface );
931 if ( error == 0 )
932 return error;
933
934 /* let it fall through to normal loader (.ttf, .otf, etc.); */
935 /* we signal this by returning no error and no FT_Face */
936 *aface = NULL;
937 return 0;
938 }
939
940
941 /*************************************************************************/
942 /* */
943 /* <Function> */
944 /* FT_New_Face */
945 /* */
946 /* <Description> */
947 /* This is the Mac-specific implementation of FT_New_Face. In */
948 /* addition to the standard FT_New_Face() functionality, it also */
949 /* accepts pathnames to Mac suitcase files. For further */
950 /* documentation see the original FT_New_Face() in freetype.h. */
951 /* */
952 FT_EXPORT_DEF( FT_Error )
953 FT_New_Face( FT_Library library,
954 const char* pathname,
955 FT_Long face_index,
956 FT_Face* aface )
957 {
958 FT_Open_Args args;
959 FT_Error error;
960
961
962 /* test for valid `library' and `aface' delayed to FT_Open_Face() */
963 if ( !pathname )
964 return FT_Err_Invalid_Argument;
965
966 error = FT_Err_Ok;
967 *aface = NULL;
968
969 /* try resourcefork based font: LWFN, FFIL */
970 error = FT_New_Face_From_Resource( library, (UInt8 *)pathname,
971 face_index, aface );
972 if ( error != 0 || *aface != NULL )
973 return error;
974
975 /* let it fall through to normal loader (.ttf, .otf, etc.) */
976 args.flags = FT_OPEN_PATHNAME;
977 args.pathname = (char*)pathname;
978 return FT_Open_Face( library, &args, face_index, aface );
979 }
980
981
982 /*************************************************************************/
983 /* */
984 /* <Function> */
985 /* FT_New_Face_From_FSRef */
986 /* */
987 /* <Description> */
988 /* FT_New_Face_From_FSRef is identical to FT_New_Face except it */
989 /* accepts an FSRef instead of a path. */
990 /* */
991 /* This function is deprecated because Carbon data types (FSRef) */
992 /* are not cross-platform, and thus not suitable for the freetype API. */
993 FT_EXPORT_DEF( FT_Error )
994 FT_New_Face_From_FSRef( FT_Library library,
995 const FSRef* ref,
996 FT_Long face_index,
997 FT_Face* aface )
998 {
999 FT_Error error;
1000 FT_Open_Args args;
1001 OSErr err;
1002 UInt8 pathname[PATH_MAX];
1003
1004
1005 if ( !ref )
1006 return FT_Err_Invalid_Argument;
1007
1008 err = FSRefMakePath( ref, pathname, sizeof ( pathname ) );
1009 if ( err )
1010 error = FT_Err_Cannot_Open_Resource;
1011
1012 error = FT_New_Face_From_Resource( library, pathname, face_index, aface );
1013 if ( error != 0 || *aface != NULL )
1014 return error;
1015
1016 /* fallback to datafork font */
1017 args.flags = FT_OPEN_PATHNAME;
1018 args.pathname = (char*)pathname;
1019 return FT_Open_Face( library, &args, face_index, aface );
1020 }
1021
1022
1023 /*************************************************************************/
1024 /* */
1025 /* <Function> */
1026 /* FT_New_Face_From_FSSpec */
1027 /* */
1028 /* <Description> */
1029 /* FT_New_Face_From_FSSpec is identical to FT_New_Face except it */
1030 /* accepts an FSSpec instead of a path. */
1031 /* */
1032 /* This function is deprecated because FSSpec is deprecated in Mac OS X */
1033 FT_EXPORT_DEF( FT_Error )
1034 FT_New_Face_From_FSSpec( FT_Library library,
1035 const FSSpec* spec,
1036 FT_Long face_index,
1037 FT_Face* aface )
1038 {
1039 #if ( __LP64__ ) || ( defined( MAC_OS_X_VERSION_10_5 ) && \
1040 ( MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 ) )
1041 FT_UNUSED( library );
1042 FT_UNUSED( spec );
1043 FT_UNUSED( face_index );
1044 FT_UNUSED( aface );
1045
1046 return FT_Err_Unimplemented_Feature;
1047 #else
1048 FSRef ref;
1049
1050
1051 if ( !spec || FSpMakeFSRef( spec, &ref ) != noErr )
1052 return FT_Err_Invalid_Argument;
1053 else
1054 return FT_New_Face_From_FSRef( library, &ref, face_index, aface );
1055 #endif
1056 }
1057
1058 #endif /* FT_MACINTOSH */
1059
1060
1061 /* END */
FT_ALLOC
#define FT_ALLOC(ptr, size)
Definition: ftmemory.h:260
FT_Error
int FT_Error
Definition: fttypes.h:296
FT_New_Face_From_FSRef
FT_New_Face_From_FSRef(FT_Library library, const FSRef *ref, FT_Long face_index, FT_Face *aface) FT_DEPRECATED_ATTRIBUTE
FT_Long
signed long FT_Long
Definition: fttypes.h:238
s
GLdouble s
Definition: glew.h:1376
FT_ULong
unsigned long FT_ULong
Definition: fttypes.h:249
FT_OPEN_PATHNAME
#define FT_OPEN_PATHNAME
Definition: freetype.h:1734
FT_Open_Args_::flags
FT_UInt flags
Definition: freetype.h:1831
NULL
#define NULL
Definition: ftobjs.h:61
FT_GetFilePath_From_Mac_ATS_Name
FT_GetFilePath_From_Mac_ATS_Name(const char *fontName, UInt8 *path, UInt32 maxPathSize, FT_Long *face_index) FT_DEPRECATED_ATTRIBUTE
FT_Open_Args_::pathname
FT_String * pathname
Definition: freetype.h:1834
FT_Err_Invalid_Argument
return FT_Err_Invalid_Argument
Definition: ftbbox.c:584
names
GLuint const GLuint * names
Definition: glew.h:2631
stream
GLuint GLuint stream
Definition: glew.h:6573
FT_MIN
#define FT_MIN(a, b)
Definition: ftobjs.h:70
ft_strcat
#define ft_strcat
Definition: ftstdlib.h:84
j
int32_t j
Definition: e_log.c:102
library
FT_Library library
Definition: cffdrivr.c:409
FT_Err_Ok
return FT_Err_Ok
Definition: ftbbox.c:658
FT_Stream_Close
FT_Stream_Close(FT_Stream stream)
Definition: ftstream.c:49
open_face_PS_from_sfnt_stream
FT_BEGIN_HEADER open_face_PS_from_sfnt_stream(FT_Library library, FT_Stream stream, FT_Long face_index, FT_Int num_params, FT_Parameter *params, FT_Face *aface)
ResourceIndex
short ResourceIndex
Definition: ftmac.c:97
path
GLsizei const GLchar *const * path
Definition: glew.h:5828
open_face_from_buffer
open_face_from_buffer(FT_Library library, FT_Byte *base, FT_ULong size, FT_Long face_index, const char *driver_name, FT_Face *aface)
ft_isupper
#define ft_isupper(x)
Definition: ftobjs.h:105
FT_Byte
unsigned char FT_Byte
Definition: fttypes.h:150
fontName
GLenum const void * fontName
Definition: glew.h:12411
buffer
EGLContext EGLenum EGLClientBuffer buffer
Definition: eglext.h:87
FT_LibraryRec_::memory
FT_Memory memory
Definition: ftobjs.h:826
FT_Open_Args_
Definition: freetype.h:1829
TTAG_LWFN
#define TTAG_LWFN
Definition: tttags.h:72
FT_FREE
#define FT_FREE(ptr)
Definition: ftmemory.h:286
TTAG_POST
#define TTAG_POST
Definition: tttags.h:85
FT_FaceRec_
Definition: freetype.h:912
error
FT_Error error
Definition: cffdrivr.c:407
count
GLint GLsizei count
Definition: gl2ext.h:1011
face
GLenum face
Definition: gl2ext.h:1490
FT_GetFile_From_Mac_Name
FT_GetFile_From_Mac_Name(const char *fontName, FSSpec *pathSpec, FT_Long *face_index) FT_DEPRECATED_ATTRIBUTE
p
GLfloat GLfloat p
Definition: glew.h:14938
FT_GetFile_From_Mac_ATS_Name
FT_GetFile_From_Mac_ATS_Name(const char *fontName, FSSpec *pathSpec, FT_Long *face_index) FT_DEPRECATED_ATTRIBUTE
FALSE
#define FALSE
Definition: ftobjs.h:57
kATSOptionFlagsUnRestrictedScope
#define kATSOptionFlagsUnRestrictedScope
Definition: ftmac.c:110
FT_LibraryRec_
Definition: ftobjs.h:824
TTAG_sfnt
#define TTAG_sfnt
Definition: tttags.h:89
FT_Memory
typedefFT_BEGIN_HEADER struct FT_MemoryRec_ * FT_Memory
Definition: ftsystem.h:66
code
Definition: inftrees.h:24
PATH_MAX
#define PATH_MAX
Definition: hrtf.c:34
TTAG_FOND
#define TTAG_FOND
Definition: tttags.h:53
ftbase.h
const
#define const
Definition: zconf.h:91
ft2build.h
FT_New_Face_From_FSSpec
FT_New_Face_From_FSSpec(FT_Library library, const FSSpec *spec, FT_Long face_index, FT_Face *aface) FT_DEPRECATED_ATTRIBUTE
ft_memcmp
#define ft_memcmp
Definition: ftstdlib.h:80
FT_EXPORT_DEF
#define FT_EXPORT_DEF(x)
Definition: ftconfig.h:511
q
GLdouble GLdouble GLdouble GLdouble q
Definition: glew.h:1400
FT_Open_Face
FT_Open_Face(FT_Library library, const FT_Open_Args *args, FT_Long face_index, FT_Face *aface)
Definition: ftobjs.c:1994
FT_New_Face
FT_New_Face(FT_Library library, const char *filepathname, FT_Long face_index, FT_Face *aface)
Definition: ftobjs.c:1199
ref
GLclampf ref
Definition: gl2ext.h:1455
FT_Stream_OpenMemory
FT_Stream_OpenMemory(FT_Stream stream, const FT_Byte *base, FT_ULong size)
Definition: ftstream.c:35
ft_isalnum
#define ft_isalnum(x)
Definition: ftobjs.h:109
FT_NEW
#define FT_NEW(ptr)
Definition: ftmemory.h:288
i
int i
Definition: pngrutil.c:1377
max
#define max(x, y)
Definition: os.h:79
PREFER_LWFN
#define PREFER_LWFN
Definition: ftmac.c:118
FT_StreamRec_
Definition: ftsystem.h:321
ft_memcpy
#define ft_memcpy
Definition: ftstdlib.h:81
FT_UNUSED
#define FT_UNUSED(arg)
Definition: ftconfig.h:101
ft_strlen
#define ft_strlen
Definition: ftstdlib.h:87
FT_New_Face_From_FOND
FT_New_Face_From_FOND(FT_Library library, Handle fond, FT_Long face_index, FT_Face *aface) FT_DEPRECATED_ATTRIBUTE
res
GLuint res
Definition: glew.h:10669
size_t
unsigned int size_t
Definition: SDL_config_windows.h:67
size
GLsizei size
Definition: gl2ext.h:1467