zenilib  0.5.3.0
 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 */
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,
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 
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 */
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 ) )
512 
513  if ( noErr != FSGetCatalogInfo( &ref, kFSCatInfoNone,
514  NULL, NULL, NULL, &par_ref ) )
516 
517  if ( noErr != FSRefMakePath( &par_ref, path_lwfn, path_size ) )
519 
520  if ( ft_strlen( (char *)path_lwfn ) + 1 + base_lwfn[0] > path_size )
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  {
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  {
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 
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  /* */
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 )
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. */
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 */
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 */
#define FT_ALLOC(ptr, size)
Definition: ftmemory.h:260
int FT_Error
Definition: fttypes.h:296
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
GLdouble s
Definition: glew.h:1376
unsigned long FT_ULong
Definition: fttypes.h:249
#define FT_OPEN_PATHNAME
Definition: freetype.h:1734
FT_UInt flags
Definition: freetype.h:1831
#define NULL
Definition: ftobjs.h:61
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:1834
return FT_Err_Invalid_Argument
Definition: ftbbox.c:584
GLuint const GLuint * names
Definition: glew.h:2631
GLuint GLuint stream
Definition: glew.h:6573
#define FT_MIN(a, b)
Definition: ftobjs.h:70
#define ft_strcat
Definition: ftstdlib.h:84
int32_t j
Definition: e_log.c:102
FT_Library library
Definition: cffdrivr.c:409
return FT_Err_Ok
Definition: ftbbox.c:658
FT_Stream_Close(FT_Stream stream)
Definition: ftstream.c:49
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)
short ResourceIndex
Definition: ftmac.c:97
GLsizei const GLchar *const * path
Definition: glew.h:5828
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
unsigned char FT_Byte
Definition: fttypes.h:150
GLenum const void * fontName
Definition: glew.h:12411
EGLContext EGLenum EGLClientBuffer buffer
Definition: eglext.h:87
FT_Memory memory
Definition: ftobjs.h:826
#define TTAG_LWFN
Definition: tttags.h:72
#define FT_FREE(ptr)
Definition: ftmemory.h:286
#define TTAG_POST
Definition: tttags.h:85
FT_Error error
Definition: cffdrivr.c:407
GLint GLsizei count
Definition: gl2ext.h:1011
GLenum face
Definition: gl2ext.h:1490
FT_GetFile_From_Mac_Name(const char *fontName, FSSpec *pathSpec, FT_Long *face_index) FT_DEPRECATED_ATTRIBUTE
GLfloat GLfloat p
Definition: glew.h:14938
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 kATSOptionFlagsUnRestrictedScope
Definition: ftmac.c:110
#define TTAG_sfnt
Definition: tttags.h:89
typedefFT_BEGIN_HEADER struct FT_MemoryRec_ * FT_Memory
Definition: ftsystem.h:66
Definition: inftrees.h:24
#define PATH_MAX
Definition: hrtf.c:34
#define TTAG_FOND
Definition: tttags.h:53
#define const
Definition: zconf.h:91
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
#define FT_EXPORT_DEF(x)
Definition: ftconfig.h:511
GLdouble GLdouble GLdouble GLdouble q
Definition: glew.h:1400
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_Library library, const char *filepathname, FT_Long face_index, FT_Face *aface)
Definition: ftobjs.c:1199
GLclampf ref
Definition: gl2ext.h:1455
FT_Stream_OpenMemory(FT_Stream stream, const FT_Byte *base, FT_ULong size)
Definition: ftstream.c:35
#define ft_isalnum(x)
Definition: ftobjs.h:109
#define FT_NEW(ptr)
Definition: ftmemory.h:288
int i
Definition: pngrutil.c:1377
#define max(x, y)
Definition: os.h:79
#define PREFER_LWFN
Definition: ftmac.c:118
#define ft_memcpy
Definition: ftstdlib.h:81
#define FT_UNUSED(arg)
Definition: ftconfig.h:101
#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
GLuint res
Definition: glew.h:10669
unsigned int size_t
GLsizei size
Definition: gl2ext.h:1467