ReactOS  0.4.15-dev-3442-gc05a45e
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-2018 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 
75 #ifdef FT_MACINTOSH
76 
77  /* This is for Mac OS X. Without redefinition, OS_INLINE */
78  /* expands to `static inline' which doesn't survive the */
79  /* -ansi compilation flag of GCC. */
80 #if !HAVE_ANSI_OS_INLINE
81 #undef OS_INLINE
82 #define OS_INLINE static __inline__
83 #endif
84 
85  /* `configure' checks the availability of `ResourceIndex' strictly */
86  /* and sets HAVE_TYPE_RESOURCE_INDEX 1 or 0 always. If it is */
87  /* not set (e.g., a build without `configure'), the availability */
88  /* is guessed from the SDK version. */
89 #ifndef HAVE_TYPE_RESOURCE_INDEX
90 #if !defined( MAC_OS_X_VERSION_10_5 ) || \
91  ( MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5 )
92 #define HAVE_TYPE_RESOURCE_INDEX 0
93 #else
94 #define HAVE_TYPE_RESOURCE_INDEX 1
95 #endif
96 #endif /* !HAVE_TYPE_RESOURCE_INDEX */
97 
98 #if ( HAVE_TYPE_RESOURCE_INDEX == 0 )
99  typedef short ResourceIndex;
100 #endif
101 
102 #include <CoreServices/CoreServices.h>
103 #include <ApplicationServices/ApplicationServices.h>
104 #include <sys/syslimits.h> /* PATH_MAX */
105 
106  /* Don't want warnings about our own use of deprecated functions. */
107 #define FT_DEPRECATED_ATTRIBUTE
108 
109 #include FT_MAC_H
110 
111 #ifndef kATSOptionFlagsUnRestrictedScope /* since Mac OS X 10.1 */
112 #define kATSOptionFlagsUnRestrictedScope kATSOptionFlagsDefault
113 #endif
114 
115 
116  /* Set PREFER_LWFN to 1 if LWFN (Type 1) is preferred over
117  TrueType in case *both* are available (this is not common,
118  but it *is* possible). */
119 #ifndef PREFER_LWFN
120 #define PREFER_LWFN 1
121 #endif
122 
123 
124  /* This function is deprecated because FSSpec is deprecated in Mac OS X */
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_THROW( 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_THROW( Unknown_File_Format );
194 
195  if ( noErr != FT_ATSFontGetFileReference( ats_font_id, ats_font_ref ) )
196  return FT_THROW( 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 
223  UInt8* path,
224  UInt32 maxPathSize,
225  FT_Long* face_index )
226  {
227  FSRef ref;
228  FT_Error err;
229 
230 
231  if ( !fontName || !face_index )
232  return FT_THROW( Invalid_Argument);
233 
234  err = FT_GetFileRef_From_Mac_ATS_Name( fontName, &ref, face_index );
235  if ( err )
236  return err;
237 
238  if ( noErr != FSRefMakePath( &ref, path, maxPathSize ) )
239  return FT_THROW( Unknown_File_Format );
240 
241  return FT_Err_Ok;
242  }
243 
244 
245  /* This function is deprecated because FSSpec is deprecated in Mac OS X */
248  FSSpec* pathSpec,
249  FT_Long* face_index )
250  {
251 #if ( __LP64__ ) || ( defined( MAC_OS_X_VERSION_10_5 ) && \
252  ( MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 ) )
253  FT_UNUSED( fontName );
254  FT_UNUSED( pathSpec );
255  FT_UNUSED( face_index );
256 
257  return FT_THROW( Unimplemented_Feature );
258 #else
259  FSRef ref;
260  FT_Error err;
261 
262 
263  if ( !fontName || !face_index )
264  return FT_THROW( Invalid_Argument );
265 
266  err = FT_GetFileRef_From_Mac_ATS_Name( fontName, &ref, face_index );
267  if ( err )
268  return err;
269 
270  if ( noErr != FSGetCatalogInfo( &ref, kFSCatInfoNone, NULL, NULL,
271  pathSpec, NULL ) )
272  return FT_THROW( Unknown_File_Format );
273 
274  return FT_Err_Ok;
275 #endif
276  }
277 
278 
279  static OSErr
280  FT_FSPathMakeRes( const UInt8* pathname,
281  ResFileRefNum* res )
282  {
283  OSErr err;
284  FSRef ref;
285 
286 
287  if ( noErr != FSPathMakeRef( pathname, &ref, FALSE ) )
288  return FT_THROW( Cannot_Open_Resource );
289 
290  /* at present, no support for dfont format */
291  err = FSOpenResourceFile( &ref, 0, NULL, fsRdPerm, res );
292  if ( noErr == err )
293  return err;
294 
295  /* fallback to original resource-fork font */
296  *res = FSOpenResFile( &ref, fsRdPerm );
297  err = ResError();
298 
299  return err;
300  }
301 
302 
303  /* Return the file type for given pathname */
304  static OSType
305  get_file_type_from_path( const UInt8* pathname )
306  {
307  FSRef ref;
308  FSCatalogInfo info;
309 
310 
311  if ( noErr != FSPathMakeRef( pathname, &ref, FALSE ) )
312  return ( OSType ) 0;
313 
314  if ( noErr != FSGetCatalogInfo( &ref, kFSCatInfoFinderInfo, &info,
315  NULL, NULL, NULL ) )
316  return ( OSType ) 0;
317 
318  return ((FInfo *)(info.finderInfo))->fdType;
319  }
320 
321 
322  /* Given a PostScript font name, create the Macintosh LWFN file name. */
323  static void
324  create_lwfn_name( char* ps_name,
325  Str255 lwfn_file_name )
326  {
327  int max = 5, count = 0;
328  FT_Byte* p = lwfn_file_name;
329  FT_Byte* q = (FT_Byte*)ps_name;
330 
331 
332  lwfn_file_name[0] = 0;
333 
334  while ( *q )
335  {
336  if ( ft_isupper( *q ) )
337  {
338  if ( count )
339  max = 3;
340  count = 0;
341  }
342  if ( count < max && ( ft_isalnum( *q ) || *q == '_' ) )
343  {
344  *++p = *q;
345  lwfn_file_name[0]++;
346  count++;
347  }
348  q++;
349  }
350  }
351 
352 
353  static short
354  count_faces_sfnt( char* fond_data )
355  {
356  /* The count is 1 greater than the value in the FOND. */
357  /* Isn't that cute? :-) */
358 
359  return EndianS16_BtoN( *( (short*)( fond_data +
360  sizeof ( FamRec ) ) ) ) + 1;
361  }
362 
363 
364  static short
365  count_faces_scalable( char* fond_data )
366  {
367  AsscEntry* assoc;
368  short i, face, face_all;
369 
370 
371  face_all = EndianS16_BtoN( *( (short *)( fond_data +
372  sizeof ( FamRec ) ) ) ) + 1;
373  assoc = (AsscEntry*)( fond_data + sizeof ( FamRec ) + 2 );
374  face = 0;
375 
376  for ( i = 0; i < face_all; i++ )
377  {
378  if ( 0 == EndianS16_BtoN( assoc[i].fontSize ) )
379  face++;
380  }
381  return face;
382  }
383 
384 
385  /* Look inside the FOND data, answer whether there should be an SFNT
386  resource, and answer the name of a possible LWFN Type 1 file.
387 
388  Thanks to Paul Miller (paulm@profoundeffects.com) for the fix
389  to load a face OTHER than the first one in the FOND!
390  */
391 
392 
393  static void
394  parse_fond( char* fond_data,
395  short* have_sfnt,
396  ResID* sfnt_id,
397  Str255 lwfn_file_name,
398  short face_index )
399  {
400  AsscEntry* assoc;
401  AsscEntry* base_assoc;
402  FamRec* fond;
403 
404 
405  *sfnt_id = 0;
406  *have_sfnt = 0;
407  lwfn_file_name[0] = 0;
408 
409  fond = (FamRec*)fond_data;
410  assoc = (AsscEntry*)( fond_data + sizeof ( FamRec ) + 2 );
411  base_assoc = assoc;
412 
413  /* the maximum faces in a FOND is 48, size of StyleTable.indexes[] */
414  if ( 47 < face_index )
415  return;
416 
417  /* Let's do a little range checking before we get too excited here */
418  if ( face_index < count_faces_sfnt( fond_data ) )
419  {
420  assoc += face_index; /* add on the face_index! */
421 
422  /* if the face at this index is not scalable,
423  fall back to the first one (old behavior) */
424  if ( EndianS16_BtoN( assoc->fontSize ) == 0 )
425  {
426  *have_sfnt = 1;
427  *sfnt_id = EndianS16_BtoN( assoc->fontID );
428  }
429  else if ( base_assoc->fontSize == 0 )
430  {
431  *have_sfnt = 1;
432  *sfnt_id = EndianS16_BtoN( base_assoc->fontID );
433  }
434  }
435 
436  if ( EndianS32_BtoN( fond->ffStylOff ) )
437  {
438  unsigned char* p = (unsigned char*)fond_data;
439  StyleTable* style;
440  unsigned short string_count;
441  char ps_name[256];
442  unsigned char* names[64];
443  int i;
444 
445 
446  p += EndianS32_BtoN( fond->ffStylOff );
447  style = (StyleTable*)p;
448  p += sizeof ( StyleTable );
449  string_count = EndianS16_BtoN( *(short*)(p) );
450  string_count = FT_MIN( 64, string_count );
451  p += sizeof ( short );
452 
453  for ( i = 0; i < string_count; i++ )
454  {
455  names[i] = p;
456  p += names[i][0];
457  p++;
458  }
459 
460  {
461  size_t ps_name_len = (size_t)names[0][0];
462 
463 
464  if ( ps_name_len != 0 )
465  {
466  ft_memcpy(ps_name, names[0] + 1, ps_name_len);
467  ps_name[ps_name_len] = 0;
468  }
469  if ( style->indexes[face_index] > 1 &&
470  style->indexes[face_index] <= string_count )
471  {
472  unsigned char* suffixes = names[style->indexes[face_index] - 1];
473 
474 
475  for ( i = 1; i <= suffixes[0]; i++ )
476  {
477  unsigned char* s;
478  size_t j = suffixes[i] - 1;
479 
480 
481  if ( j < string_count && ( s = names[j] ) != NULL )
482  {
483  size_t s_len = (size_t)s[0];
484 
485 
486  if ( s_len != 0 && ps_name_len + s_len < sizeof ( ps_name ) )
487  {
488  ft_memcpy( ps_name + ps_name_len, s + 1, s_len );
489  ps_name_len += s_len;
490  ps_name[ps_name_len] = 0;
491  }
492  }
493  }
494  }
495  }
496 
497  create_lwfn_name( ps_name, lwfn_file_name );
498  }
499  }
500 
501 
502  static FT_Error
503  lookup_lwfn_by_fond( const UInt8* path_fond,
504  ConstStr255Param base_lwfn,
505  UInt8* path_lwfn,
506  size_t path_size )
507  {
508  FSRef ref, par_ref;
509  size_t dirname_len;
510 
511 
512  /* Pathname for FSRef can be in various formats: HFS, HFS+, and POSIX. */
513  /* We should not extract parent directory by string manipulation. */
514 
515  if ( noErr != FSPathMakeRef( path_fond, &ref, FALSE ) )
516  return FT_THROW( Invalid_Argument );
517 
518  if ( noErr != FSGetCatalogInfo( &ref, kFSCatInfoNone,
519  NULL, NULL, NULL, &par_ref ) )
520  return FT_THROW( Invalid_Argument );
521 
522  if ( noErr != FSRefMakePath( &par_ref, path_lwfn, path_size ) )
523  return FT_THROW( Invalid_Argument );
524 
525  if ( ft_strlen( (char *)path_lwfn ) + 1 + base_lwfn[0] > path_size )
526  return FT_THROW( Invalid_Argument );
527 
528  /* now we have absolute dirname in path_lwfn */
529  ft_strcat( (char *)path_lwfn, "/" );
530  dirname_len = ft_strlen( (char *)path_lwfn );
531  ft_strcat( (char *)path_lwfn, (char *)base_lwfn + 1 );
532  path_lwfn[dirname_len + base_lwfn[0]] = '\0';
533 
534  if ( noErr != FSPathMakeRef( path_lwfn, &ref, FALSE ) )
535  return FT_THROW( Cannot_Open_Resource );
536 
537  if ( noErr != FSGetCatalogInfo( &ref, kFSCatInfoNone,
538  NULL, NULL, NULL, NULL ) )
539  return FT_THROW( Cannot_Open_Resource );
540 
541  return FT_Err_Ok;
542  }
543 
544 
545  static short
546  count_faces( Handle fond,
547  const UInt8* pathname )
548  {
549  ResID sfnt_id;
550  short have_sfnt, have_lwfn;
551  Str255 lwfn_file_name;
553  FT_Error err;
554  short num_faces;
555 
556 
557  have_sfnt = have_lwfn = 0;
558 
559  parse_fond( *fond, &have_sfnt, &sfnt_id, lwfn_file_name, 0 );
560 
561  if ( lwfn_file_name[0] )
562  {
563  err = lookup_lwfn_by_fond( pathname, lwfn_file_name,
564  buff, sizeof ( buff ) );
565  if ( !err )
566  have_lwfn = 1;
567  }
568 
569  if ( have_lwfn && ( !have_sfnt || PREFER_LWFN ) )
570  num_faces = 1;
571  else
572  num_faces = count_faces_scalable( *fond );
573 
574  return num_faces;
575  }
576 
577 
578  /* Read Type 1 data from the POST resources inside the LWFN file,
579  return a PFB buffer. This is somewhat convoluted because the FT2
580  PFB parser wants the ASCII header as one chunk, and the LWFN
581  chunks are often not organized that way, so we glue chunks
582  of the same type together. */
583  static FT_Error
584  read_lwfn( FT_Memory memory,
585  ResFileRefNum res,
586  FT_Byte** pfb_data,
587  FT_ULong* size )
588  {
590  ResID res_id;
591  unsigned char *buffer, *p, *size_p = NULL;
592  FT_ULong total_size = 0;
593  FT_ULong old_total_size = 0;
594  FT_ULong post_size, pfb_chunk_size;
596  char code, last_code;
597 
598 
599  UseResFile( res );
600 
601  /* First pass: load all POST resources, and determine the size of */
602  /* the output buffer. */
603  res_id = 501;
604  last_code = -1;
605 
606  for (;;)
607  {
608  post_data = Get1Resource( TTAG_POST, res_id++ );
609  if ( !post_data )
610  break; /* we are done */
611 
612  code = (*post_data)[0];
613 
614  if ( code != last_code )
615  {
616  if ( code == 5 )
617  total_size += 2; /* just the end code */
618  else
619  total_size += 6; /* code + 4 bytes chunk length */
620  }
621 
622  total_size += (FT_ULong)GetHandleSize( post_data ) - 2;
623  last_code = code;
624 
625  /* detect resource fork overflow */
626  if ( FT_MAC_RFORK_MAX_LEN < total_size )
627  {
628  error = FT_THROW( Array_Too_Large );
629  goto Error;
630  }
631 
632  old_total_size = total_size;
633  }
634 
635  if ( FT_ALLOC( buffer, (FT_Long)total_size ) )
636  goto Error;
637 
638  /* Second pass: append all POST data to the buffer, add PFB fields. */
639  /* Glue all consecutive chunks of the same type together. */
640  p = buffer;
641  res_id = 501;
642  last_code = -1;
643  pfb_chunk_size = 0;
644 
645  for (;;)
646  {
647  post_data = Get1Resource( TTAG_POST, res_id++ );
648  if ( !post_data )
649  break; /* we are done */
650 
651  post_size = (FT_ULong)GetHandleSize( post_data ) - 2;
652  code = (*post_data)[0];
653 
654  if ( code != last_code )
655  {
656  if ( last_code != -1 )
657  {
658  /* we are done adding a chunk, fill in the size field */
659  if ( size_p )
660  {
661  *size_p++ = (FT_Byte)( pfb_chunk_size & 0xFF );
662  *size_p++ = (FT_Byte)( ( pfb_chunk_size >> 8 ) & 0xFF );
663  *size_p++ = (FT_Byte)( ( pfb_chunk_size >> 16 ) & 0xFF );
664  *size_p++ = (FT_Byte)( ( pfb_chunk_size >> 24 ) & 0xFF );
665  }
666  pfb_chunk_size = 0;
667  }
668 
669  *p++ = 0x80;
670  if ( code == 5 )
671  *p++ = 0x03; /* the end */
672  else if ( code == 2 )
673  *p++ = 0x02; /* binary segment */
674  else
675  *p++ = 0x01; /* ASCII segment */
676 
677  if ( code != 5 )
678  {
679  size_p = p; /* save for later */
680  p += 4; /* make space for size field */
681  }
682  }
683 
684  ft_memcpy( p, *post_data + 2, post_size );
685  pfb_chunk_size += post_size;
686  p += post_size;
687  last_code = code;
688  }
689 
690  *pfb_data = buffer;
691  *size = total_size;
692 
693  Error:
694  CloseResFile( res );
695  return error;
696  }
697 
698 
699  /* Create a new FT_Face from a file path to an LWFN file. */
700  static FT_Error
701  FT_New_Face_From_LWFN( FT_Library library,
702  const UInt8* pathname,
703  FT_Long face_index,
704  FT_Face* aface )
705  {
706  FT_Byte* pfb_data;
707  FT_ULong pfb_size;
708  FT_Error error;
709  ResFileRefNum res;
710 
711 
712  if ( noErr != FT_FSPathMakeRes( pathname, &res ) )
713  return FT_THROW( Cannot_Open_Resource );
714 
715  pfb_data = NULL;
716  pfb_size = 0;
717  error = read_lwfn( library->memory, res, &pfb_data, &pfb_size );
718  CloseResFile( res ); /* PFB is already loaded, useless anymore */
719  if ( error )
720  return error;
721 
722  return open_face_from_buffer( library,
723  pfb_data,
724  pfb_size,
725  face_index,
726  "type1",
727  aface );
728  }
729 
730 
731  /* Create a new FT_Face from an SFNT resource, specified by res ID. */
732  static FT_Error
733  FT_New_Face_From_SFNT( FT_Library library,
734  ResID sfnt_id,
735  FT_Long face_index,
736  FT_Face* aface )
737  {
738  Handle sfnt = NULL;
739  FT_Byte* sfnt_data;
740  size_t sfnt_size;
743  int is_cff, is_sfnt_ps;
744 
745 
746  sfnt = GetResource( TTAG_sfnt, sfnt_id );
747  if ( !sfnt )
748  return FT_THROW( Invalid_Handle );
749 
750  sfnt_size = (FT_ULong)GetHandleSize( sfnt );
751 
752  /* detect resource fork overflow */
753  if ( FT_MAC_RFORK_MAX_LEN < sfnt_size )
754  return FT_THROW( Array_Too_Large );
755 
756  if ( FT_ALLOC( sfnt_data, (FT_Long)sfnt_size ) )
757  {
758  ReleaseResource( sfnt );
759  return error;
760  }
761 
762  ft_memcpy( sfnt_data, *sfnt, sfnt_size );
763  ReleaseResource( sfnt );
764 
765  is_cff = sfnt_size > 4 && !ft_memcmp( sfnt_data, "OTTO", 4 );
766  is_sfnt_ps = sfnt_size > 4 && !ft_memcmp( sfnt_data, "typ1", 4 );
767 
768  if ( is_sfnt_ps )
769  {
771 
772 
773  if ( FT_NEW( stream ) )
774  goto Try_OpenType;
775 
776  FT_Stream_OpenMemory( stream, sfnt_data, sfnt_size );
777  if ( !open_face_PS_from_sfnt_stream( library,
778  stream,
779  face_index,
780  0, NULL,
781  aface ) )
782  {
784  FT_FREE( stream );
785  FT_FREE( sfnt_data );
786  goto Exit;
787  }
788 
789  FT_FREE( stream );
790  }
791  Try_OpenType:
792  error = open_face_from_buffer( library,
793  sfnt_data,
794  sfnt_size,
795  face_index,
796  is_cff ? "cff" : "truetype",
797  aface );
798  Exit:
799  return error;
800  }
801 
802 
803  /* Create a new FT_Face from a file path to a suitcase file. */
804  static FT_Error
805  FT_New_Face_From_Suitcase( FT_Library library,
806  const UInt8* pathname,
807  FT_Long face_index,
808  FT_Face* aface )
809  {
810  FT_Error error = FT_ERR( Cannot_Open_Resource );
811  ResFileRefNum res_ref;
812  ResourceIndex res_index;
813  Handle fond;
814  short num_faces_in_res;
815 
816 
817  if ( noErr != FT_FSPathMakeRes( pathname, &res_ref ) )
818  return FT_THROW( Cannot_Open_Resource );
819 
820  UseResFile( res_ref );
821  if ( ResError() )
822  return FT_THROW( Cannot_Open_Resource );
823 
824  num_faces_in_res = 0;
825  for ( res_index = 1; ; res_index++ )
826  {
827  short num_faces_in_fond;
828 
829 
830  fond = Get1IndResource( TTAG_FOND, res_index );
831  if ( ResError() )
832  break;
833 
834  num_faces_in_fond = count_faces( fond, pathname );
835  num_faces_in_res += num_faces_in_fond;
836 
837  if ( 0 <= face_index && face_index < num_faces_in_fond && error )
838  error = FT_New_Face_From_FOND( library, fond, face_index, aface );
839 
840  face_index -= num_faces_in_fond;
841  }
842 
843  CloseResFile( res_ref );
844  if ( !error && aface && *aface )
845  (*aface)->num_faces = num_faces_in_res;
846  return error;
847  }
848 
849 
850  /* documentation is in ftmac.h */
851 
854  Handle fond,
855  FT_Long face_index,
856  FT_Face* aface )
857  {
858  short have_sfnt, have_lwfn = 0;
859  ResID sfnt_id, fond_id;
860  OSType fond_type;
861  Str255 fond_name;
862  Str255 lwfn_file_name;
863  UInt8 path_lwfn[PATH_MAX];
864  OSErr err;
866 
867 
868  /* check of `library' and `aface' delayed to `FT_New_Face_From_XXX' */
869 
870  GetResInfo( fond, &fond_id, &fond_type, fond_name );
871  if ( ResError() != noErr || fond_type != TTAG_FOND )
872  return FT_THROW( Invalid_File_Format );
873 
874  parse_fond( *fond, &have_sfnt, &sfnt_id, lwfn_file_name, face_index );
875 
876  if ( lwfn_file_name[0] )
877  {
878  ResFileRefNum res;
879 
880 
881  res = HomeResFile( fond );
882  if ( noErr != ResError() )
883  goto found_no_lwfn_file;
884 
885  {
886  UInt8 path_fond[PATH_MAX];
887  FSRef ref;
888 
889 
890  err = FSGetForkCBInfo( res, kFSInvalidVolumeRefNum,
891  NULL, NULL, NULL, &ref, NULL );
892  if ( noErr != err )
893  goto found_no_lwfn_file;
894 
895  err = FSRefMakePath( &ref, path_fond, sizeof ( path_fond ) );
896  if ( noErr != err )
897  goto found_no_lwfn_file;
898 
899  error = lookup_lwfn_by_fond( path_fond, lwfn_file_name,
900  path_lwfn, sizeof ( path_lwfn ) );
901  if ( !error )
902  have_lwfn = 1;
903  }
904  }
905 
906  if ( have_lwfn && ( !have_sfnt || PREFER_LWFN ) )
907  error = FT_New_Face_From_LWFN( library,
908  path_lwfn,
909  face_index,
910  aface );
911  else
912  error = FT_THROW( Unknown_File_Format );
913 
914  found_no_lwfn_file:
915  if ( have_sfnt && error )
916  error = FT_New_Face_From_SFNT( library,
917  sfnt_id,
918  face_index,
919  aface );
920 
921  return error;
922  }
923 
924 
925  /* Common function to load a new FT_Face from a resource file. */
926  static FT_Error
927  FT_New_Face_From_Resource( FT_Library library,
928  const UInt8* pathname,
929  FT_Long face_index,
930  FT_Face* aface )
931  {
932  OSType file_type;
933  FT_Error error;
934 
935 
936  /* LWFN is a (very) specific file format, check for it explicitly */
937  file_type = get_file_type_from_path( pathname );
938  if ( file_type == TTAG_LWFN )
939  return FT_New_Face_From_LWFN( library, pathname, face_index, aface );
940 
941  /* Otherwise the file type doesn't matter (there are more than */
942  /* `FFIL' and `tfil'). Just try opening it as a font suitcase; */
943  /* if it works, fine. */
944 
945  error = FT_New_Face_From_Suitcase( library, pathname, face_index, aface );
946  if ( error )
947  {
948  /* let it fall through to normal loader (.ttf, .otf, etc.); */
949  /* we signal this by returning no error and no FT_Face */
950  *aface = NULL;
951  }
952 
953  return FT_Err_Ok;
954  }
955 
956 
957  /*************************************************************************/
958  /* */
959  /* <Function> */
960  /* FT_New_Face */
961  /* */
962  /* <Description> */
963  /* This is the Mac-specific implementation of FT_New_Face. In */
964  /* addition to the standard FT_New_Face() functionality, it also */
965  /* accepts pathnames to Mac suitcase files. For further */
966  /* documentation see the original FT_New_Face() in freetype.h. */
967  /* */
970  const char* pathname,
971  FT_Long face_index,
972  FT_Face* aface )
973  {
975  FT_Error error;
976 
977 
978  /* test for valid `library' and `aface' delayed to FT_Open_Face() */
979  if ( !pathname )
980  return FT_THROW( Invalid_Argument );
981 
982  *aface = NULL;
983 
984  /* try resourcefork based font: LWFN, FFIL */
985  error = FT_New_Face_From_Resource( library, (UInt8 *)pathname,
986  face_index, aface );
987  if ( error || *aface )
988  return error;
989 
990  /* let it fall through to normal loader (.ttf, .otf, etc.) */
991  args.flags = FT_OPEN_PATHNAME;
992  args.pathname = (char*)pathname;
993 
994  return FT_Open_Face( library, &args, face_index, aface );
995  }
996 
997 
998  /*************************************************************************/
999  /* */
1000  /* <Function> */
1001  /* FT_New_Face_From_FSRef */
1002  /* */
1003  /* <Description> */
1004  /* FT_New_Face_From_FSRef is identical to FT_New_Face except it */
1005  /* accepts an FSRef instead of a path. */
1006  /* */
1007  /* This function is deprecated because Carbon data types (FSRef) */
1008  /* are not cross-platform, and thus not suitable for the FreeType API. */
1011  const FSRef* ref,
1012  FT_Long face_index,
1013  FT_Face* aface )
1014  {
1015  FT_Error error;
1017 
1018  OSErr err;
1020 
1021 
1022  /* check of `library' and `aface' delayed to */
1023  /* `FT_New_Face_From_Resource' */
1024 
1025  if ( !ref )
1026  return FT_THROW( Invalid_Argument );
1027 
1028  err = FSRefMakePath( ref, pathname, sizeof ( pathname ) );
1029  if ( err )
1030  error = FT_THROW( Cannot_Open_Resource );
1031 
1032  error = FT_New_Face_From_Resource( library, pathname, face_index, aface );
1033  if ( error || *aface )
1034  return error;
1035 
1036  /* fallback to datafork font */
1037  args.flags = FT_OPEN_PATHNAME;
1038  args.pathname = (char*)pathname;
1039  return FT_Open_Face( library, &args, face_index, aface );
1040  }
1041 
1042 
1043  /*************************************************************************/
1044  /* */
1045  /* <Function> */
1046  /* FT_New_Face_From_FSSpec */
1047  /* */
1048  /* <Description> */
1049  /* FT_New_Face_From_FSSpec is identical to FT_New_Face except it */
1050  /* accepts an FSSpec instead of a path. */
1051  /* */
1052  /* This function is deprecated because FSSpec is deprecated in Mac OS X */
1055  const FSSpec* spec,
1056  FT_Long face_index,
1057  FT_Face* aface )
1058  {
1059 #if ( __LP64__ ) || ( defined( MAC_OS_X_VERSION_10_5 ) && \
1060  ( MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 ) )
1061  FT_UNUSED( library );
1062  FT_UNUSED( spec );
1063  FT_UNUSED( face_index );
1064  FT_UNUSED( aface );
1065 
1066  return FT_THROW( Unimplemented_Feature );
1067 #else
1068  FSRef ref;
1069 
1070 
1071  /* check of `library' and `aface' delayed to `FT_New_Face_From_FSRef' */
1072 
1073  if ( !spec || FSpMakeFSRef( spec, &ref ) != noErr )
1074  return FT_THROW( Invalid_Argument );
1075  else
1076  return FT_New_Face_From_FSRef( library, &ref, face_index, aface );
1077 #endif
1078  }
1079 
1080 #else /* !FT_MACINTOSH */
1081 
1082  /* ANSI C doesn't like empty source files */
1083  typedef int _ft_mac_dummy;
1084 
1085 #endif /* !FT_MACINTOSH */
1086 
1087 
1088 /* END */
#define FT_ALLOC(ptr, size)
Definition: ftmemory.h:303
int FT_Error
Definition: fttypes.h:300
FT_New_Face_From_FSRef(FT_Library library, const FSRef *ref, FT_Long face_index, FT_Face *aface) FT_DEPRECATED_ATTRIBUTE
#define max(a, b)
Definition: svc.c:63
signed long FT_Long
Definition: fttypes.h:242
unsigned long FT_ULong
Definition: fttypes.h:253
#define FT_OPEN_PATHNAME
Definition: freetype.h:2036
#define args
Definition: format.c:66
FT_Memory memory
Definition: ftobjs.h:918
#define error(str)
Definition: mkdosfs.c:1605
DWORD UInt32
Definition: chm_lib.c:104
FT_GetFilePath_From_Mac_ATS_Name(const char *fontName, UInt8 *path, UInt32 maxPathSize, FT_Long *face_index) FT_DEPRECATED_ATTRIBUTE
SFNT_Service sfnt
Definition: ttdriver.c:206
GLuint GLuint GLsizei count
Definition: gl.h:1545
char pathname[512]
Definition: util.h:13
#define UInt8
Definition: interfaces.hpp:75
#define FT_MIN(a, b)
Definition: ftobjs.h:71
GLuint buffer
Definition: glext.h:5915
#define ft_strcat
Definition: ftstdlib.h:85
FT_Library library
Definition: cffdrivr.c:654
return FT_Err_Ok
Definition: ftbbox.c:511
Definition: match.c:390
static char memory[1024 *256]
Definition: process.c:116
FT_Stream_Close(FT_Stream stream)
Definition: ftstream.c:49
Definition: send.c:48
GLenum const GLvoid * fontName
Definition: glext.h:11715
GLuint GLuint * names
Definition: glext.h:11545
unsigned short(__cdecl typeof(TIFFCurrentDirectory))(struct tiff *)
Definition: typeof.h:94
#define ft_isupper(x)
Definition: ftobjs.h:125
#define FALSE
Definition: types.h:117
unsigned char FT_Byte
Definition: fttypes.h:154
#define FT_THROW(e)
Definition: ftdebug.h:213
GLenum GLint ref
Definition: glext.h:6028
#define TTAG_LWFN
Definition: tttags.h:76
#define FT_FREE(ptr)
Definition: ftmemory.h:329
#define TTAG_POST
Definition: tttags.h:90
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
#define FT_ERR(e)
Definition: fttypes.h:586
__kernel_size_t size_t
Definition: linux.h:237
unsigned long size_p
Definition: compat.h:140
GLsizeiptr size
Definition: glext.h:5919
FT_GetFile_From_Mac_Name(const char *fontName, FSSpec *pathSpec, FT_Long *face_index) FT_DEPRECATED_ATTRIBUTE
static void Exit(void)
Definition: sock.c:1331
WORD face[3]
Definition: mesh.c:4747
#define PATH_MAX
Definition: types.h:280
BOOL Error
Definition: chkdsk.c:66
GLdouble GLdouble GLdouble GLdouble q
Definition: gl.h:2063
FT_GetFile_From_Mac_ATS_Name(const char *fontName, FSSpec *pathSpec, FT_Long *face_index) FT_DEPRECATED_ATTRIBUTE
FD_TYPE file_type(FDSC **curr, char *fixed)
Definition: file.c:221
struct _test_info info[]
Definition: SetCursorPos.c:19
static const CHAR post_data[]
Definition: protocol.c:217
Definition: parse.h:22
GLuint GLuint stream
Definition: glext.h:7522
static LPVOID GetResource(LPCWSTR FontName, LPDWORD Size)
#define TTAG_sfnt
Definition: tttags.h:95
typedefFT_BEGIN_HEADER struct FT_MemoryRec_ * FT_Memory
Definition: ftsystem.h:66
int _ft_mac_dummy
Definition: ftmac.c:1083
GLdouble s
Definition: gl.h:2039
#define err(...)
Definition: inflate.c:139
int code
Definition: main.c:75
#define TTAG_FOND
Definition: tttags.h:56
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:81
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define FT_EXPORT_DEF(x)
Definition: ftconfig.h:483
FT_Open_Face(FT_Library library, const FT_Open_Args *args, FT_Long face_index, FT_Face *aface)
Definition: ftobjs.c:2317
#define NULL
Definition: types.h:112
FT_New_Face(FT_Library library, const char *filepathname, FT_Long face_index, FT_Face *aface)
Definition: ftobjs.c:1406
FT_Stream_OpenMemory(FT_Stream stream, const FT_Byte *base, FT_ULong size)
Definition: ftstream.c:35
_In_ HANDLE Handle
Definition: extypes.h:390
GLuint res
Definition: glext.h:9613
#define ft_isalnum(x)
Definition: ftobjs.h:129
#define FT_NEW(ptr)
Definition: ftmemory.h:331
GLfloat GLfloat p
Definition: glext.h:8902
Arabic default style
Definition: afstyles.h:93
#define ft_memcpy
Definition: ftstdlib.h:82
#define FT_UNUSED(arg)
Definition: ftconfig.h:101
static unsigned char buff[32768]
Definition: fatten.c:17
#define ft_strlen
Definition: ftstdlib.h:88
FT_New_Face_From_FOND(FT_Library library, Handle fond, FT_Long face_index, FT_Face *aface) FT_DEPRECATED_ATTRIBUTE
GLenum GLuint GLint GLenum face
Definition: glext.h:7025