Visualization Library 2.0.0-b5

A lightweight C++ OpenGL middleware for 2D/3D graphics

VL     Star     Watch     Fork     Issue

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