~ubuntu-branches/ubuntu/wily/hedgewars/wily

« back to all changes in this revision

Viewing changes to misc/libfreetype/src/base/ftmac.c

  • Committer: Package Import Robot
  • Author(s): Dmitry E. Oboukhov
  • Date: 2011-09-23 10:16:55 UTC
  • mfrom: (1.2.11 upstream)
  • Revision ID: package-import@ubuntu.com-20110923101655-3977th2gc5n0a3pv
Tags: 0.9.16-1
* New upstream version.
 + Downloadable content! Simply click to install any content.
   New voices, hats, maps, themes, translations, music, scripts...
   Hedgewars is now more customisable than ever before! As time goes
   by we will be soliciting community content to feature on this page,
   so remember to check it from time to time. If you decide you want
   to go back to standard Hedgewars, just remove the Data directory
   from your Hedgewars config directory.
 + 3-D rendering! Diorama-like rendering of the game in a variety
   of 3D modes. Let us know which ones work best for you, we didn't
   really have the equipment to test them all.
 + Resizable game window.
 + New utilities! The Time Box will remove one of your hedgehogs
   from the game for a while, protecting from attack until it returns,
   somewhere else on the map. Land spray will allow you to build bridges,
   seal up holes, or just make life unpleasant for your enemies.
 + New single player: Bamboo Thicket, That Sinking Feeling, Newton and
   the Tree and multi-player: The Specialists, Space Invaders,
   Racer - scripts! And a ton more script hooks for scripters
 + New twists on old weapons. Drill strike, seduction and fire have
   been adjusted. Defective mines have been added, rope can attach to
   hogs/crates/barrels again, grenades now have variable bounce (use
   precise key + 1-5). Portal gun is now more usable in flight and
   all game actions are a lot faster.
 + New theme - Golf, dozens of new community hats and a new
   localised Default voice, Ukranian.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
  /* This function is deprecated because FSSpec is deprecated in Mac OS X  */
 
123
  FT_EXPORT_DEF( FT_Error )
 
124
  FT_GetFile_From_Mac_Name( const char*  fontName,
 
125
                            FSSpec*      pathSpec,
 
126
                            FT_Long*     face_index )
 
127
  {
 
128
    FT_UNUSED( fontName );
 
129
    FT_UNUSED( pathSpec );
 
130
    FT_UNUSED( face_index );
 
131
 
 
132
    return FT_Err_Unimplemented_Feature;
 
133
  }
 
134
 
 
135
 
 
136
  /* Private function.                                         */
 
137
  /* The FSSpec type has been discouraged for a long time,     */
 
138
  /* unfortunately an FSRef replacement API for                */
 
139
  /* ATSFontGetFileSpecification() is only available in        */
 
140
  /* Mac OS X 10.5 and later.                                  */
 
141
  static OSStatus
 
142
  FT_ATSFontGetFileReference( ATSFontRef  ats_font_id,
 
143
                              FSRef*      ats_font_ref )
 
144
  {
 
145
#if defined( MAC_OS_X_VERSION_10_5 ) && \
 
146
    ( MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 )
 
147
 
 
148
    OSStatus  err;
 
149
 
 
150
    err = ATSFontGetFileReference( ats_font_id, ats_font_ref );
 
151
 
 
152
    return err;
 
153
#elif __LP64__ /* No 64bit Carbon API on legacy platforms */
 
154
    FT_UNUSED( ats_font_id );
 
155
    FT_UNUSED( ats_font_ref );
 
156
 
 
157
 
 
158
    return fnfErr;
 
159
#else /* 32bit Carbon API on legacy platforms */
 
160
    OSStatus  err;
 
161
    FSSpec    spec;
 
162
 
 
163
 
 
164
    err = ATSFontGetFileSpecification( ats_font_id, &spec );
 
165
    if ( noErr == err )
 
166
      err = FSpMakeFSRef( &spec, ats_font_ref );
 
167
 
 
168
    return err;
 
169
#endif
 
170
  }
 
171
 
 
172
 
 
173
  static FT_Error
 
174
  FT_GetFileRef_From_Mac_ATS_Name( const char*  fontName,
 
175
                                   FSRef*       ats_font_ref,
 
176
                                   FT_Long*     face_index )
 
177
  {
 
178
    CFStringRef  cf_fontName;
 
179
    ATSFontRef   ats_font_id;
 
180
 
 
181
 
 
182
    *face_index = 0;
 
183
 
 
184
    cf_fontName = CFStringCreateWithCString( NULL, fontName,
 
185
                                             kCFStringEncodingMacRoman );
 
186
    ats_font_id = ATSFontFindFromName( cf_fontName,
 
187
                                       kATSOptionFlagsUnRestrictedScope );
 
188
    CFRelease( cf_fontName );
 
189
 
 
190
    if ( ats_font_id == 0 || ats_font_id == 0xFFFFFFFFUL )
 
191
      return FT_Err_Unknown_File_Format;
 
192
 
 
193
    if ( noErr != FT_ATSFontGetFileReference( ats_font_id, ats_font_ref ) )
 
194
      return FT_Err_Unknown_File_Format;
 
195
 
 
196
    /* face_index calculation by searching preceding fontIDs */
 
197
    /* with same FSRef                                       */
 
198
    {
 
199
      ATSFontRef  id2 = ats_font_id - 1;
 
200
      FSRef       ref2;
 
201
 
 
202
 
 
203
      while ( id2 > 0 )
 
204
      {
 
205
        if ( noErr != FT_ATSFontGetFileReference( id2, &ref2 ) )
 
206
          break;
 
207
        if ( noErr != FSCompareFSRefs( ats_font_ref, &ref2 ) )
 
208
          break;
 
209
 
 
210
        id2 --;
 
211
      }
 
212
      *face_index = ats_font_id - ( id2 + 1 );
 
213
    }
 
214
 
 
215
    return FT_Err_Ok;
 
216
  }
 
217
 
 
218
 
 
219
  FT_EXPORT_DEF( FT_Error )
 
220
  FT_GetFilePath_From_Mac_ATS_Name( const char*  fontName,
 
221
                                    UInt8*       path,
 
222
                                    UInt32       maxPathSize,
 
223
                                    FT_Long*     face_index )
 
224
  {
 
225
    FSRef     ref;
 
226
    FT_Error  err;
 
227
 
 
228
 
 
229
    err = FT_GetFileRef_From_Mac_ATS_Name( fontName, &ref, face_index );
 
230
    if ( FT_Err_Ok != err )
 
231
      return err;
 
232
 
 
233
    if ( noErr != FSRefMakePath( &ref, path, maxPathSize ) )
 
234
      return FT_Err_Unknown_File_Format;
 
235
 
 
236
    return FT_Err_Ok;
 
237
  }
 
238
 
 
239
 
 
240
  /* This function is deprecated because FSSpec is deprecated in Mac OS X  */
 
241
  FT_EXPORT_DEF( FT_Error )
 
242
  FT_GetFile_From_Mac_ATS_Name( const char*  fontName,
 
243
                                FSSpec*      pathSpec,
 
244
                                FT_Long*     face_index )
 
245
  {
 
246
#if ( __LP64__ ) || ( defined( MAC_OS_X_VERSION_10_5 ) && \
 
247
      ( MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 ) )
 
248
    FT_UNUSED( fontName );
 
249
    FT_UNUSED( pathSpec );
 
250
    FT_UNUSED( face_index );
 
251
 
 
252
    return FT_Err_Unimplemented_Feature;
 
253
#else
 
254
    FSRef     ref;
 
255
    FT_Error  err;
 
256
 
 
257
 
 
258
    err = FT_GetFileRef_From_Mac_ATS_Name( fontName, &ref, face_index );
 
259
    if ( FT_Err_Ok != err )
 
260
      return err;
 
261
 
 
262
    if ( noErr != FSGetCatalogInfo( &ref, kFSCatInfoNone, NULL, NULL,
 
263
                                    pathSpec, NULL ) )
 
264
      return FT_Err_Unknown_File_Format;
 
265
 
 
266
    return FT_Err_Ok;
 
267
#endif
 
268
  }
 
269
 
 
270
 
 
271
  static OSErr
 
272
  FT_FSPathMakeRes( const UInt8*    pathname,
 
273
                    ResFileRefNum*  res )
 
274
  {
 
275
    OSErr  err;
 
276
    FSRef  ref;
 
277
 
 
278
 
 
279
    if ( noErr != FSPathMakeRef( pathname, &ref, FALSE ) )
 
280
      return FT_Err_Cannot_Open_Resource;
 
281
 
 
282
    /* at present, no support for dfont format */
 
283
    err = FSOpenResourceFile( &ref, 0, NULL, fsRdPerm, res );
 
284
    if ( noErr == err )
 
285
      return err;
 
286
 
 
287
    /* fallback to original resource-fork font */
 
288
    *res = FSOpenResFile( &ref, fsRdPerm );
 
289
    err  = ResError();
 
290
 
 
291
    return err;
 
292
  }
 
293
 
 
294
 
 
295
  /* Return the file type for given pathname */
 
296
  static OSType
 
297
  get_file_type_from_path( const UInt8*  pathname )
 
298
  {
 
299
    FSRef          ref;
 
300
    FSCatalogInfo  info;
 
301
 
 
302
 
 
303
    if ( noErr != FSPathMakeRef( pathname, &ref, FALSE ) )
 
304
      return ( OSType ) 0;
 
305
 
 
306
    if ( noErr != FSGetCatalogInfo( &ref, kFSCatInfoFinderInfo, &info,
 
307
                                    NULL, NULL, NULL ) )
 
308
      return ( OSType ) 0;
 
309
 
 
310
    return ((FInfo *)(info.finderInfo))->fdType;
 
311
  }
 
312
 
 
313
 
 
314
  /* Given a PostScript font name, create the Macintosh LWFN file name. */
 
315
  static void
 
316
  create_lwfn_name( char*   ps_name,
 
317
                    Str255  lwfn_file_name )
 
318
  {
 
319
    int       max = 5, count = 0;
 
320
    FT_Byte*  p = lwfn_file_name;
 
321
    FT_Byte*  q = (FT_Byte*)ps_name;
 
322
 
 
323
 
 
324
    lwfn_file_name[0] = 0;
 
325
 
 
326
    while ( *q )
 
327
    {
 
328
      if ( ft_isupper( *q ) )
 
329
      {
 
330
        if ( count )
 
331
          max = 3;
 
332
        count = 0;
 
333
      }
 
334
      if ( count < max && ( ft_isalnum( *q ) || *q == '_' ) )
 
335
      {
 
336
        *++p = *q;
 
337
        lwfn_file_name[0]++;
 
338
        count++;
 
339
      }
 
340
      q++;
 
341
    }
 
342
  }
 
343
 
 
344
 
 
345
  static short
 
346
  count_faces_sfnt( char*  fond_data )
 
347
  {
 
348
    /* The count is 1 greater than the value in the FOND.  */
 
349
    /* Isn't that cute? :-)                                */
 
350
 
 
351
    return EndianS16_BtoN( *( (short*)( fond_data +
 
352
                                        sizeof ( FamRec ) ) ) ) + 1;
 
353
  }
 
354
 
 
355
 
 
356
  static short
 
357
  count_faces_scalable( char*  fond_data )
 
358
  {
 
359
    AsscEntry*  assoc;
 
360
    FamRec*     fond;
 
361
    short       i, face, face_all;
 
362
 
 
363
 
 
364
    fond     = (FamRec*)fond_data;
 
365
    face_all = EndianS16_BtoN( *( (short *)( fond_data +
 
366
                                             sizeof ( FamRec ) ) ) ) + 1;
 
367
    assoc    = (AsscEntry*)( fond_data + sizeof ( FamRec ) + 2 );
 
368
    face     = 0;
 
369
 
 
370
    for ( i = 0; i < face_all; i++ )
 
371
    {
 
372
      if ( 0 == EndianS16_BtoN( assoc[i].fontSize ) )
 
373
        face++;
 
374
    }
 
375
    return face;
 
376
  }
 
377
 
 
378
 
 
379
  /* Look inside the FOND data, answer whether there should be an SFNT
 
380
     resource, and answer the name of a possible LWFN Type 1 file.
 
381
 
 
382
     Thanks to Paul Miller (paulm@profoundeffects.com) for the fix
 
383
     to load a face OTHER than the first one in the FOND!
 
384
  */
 
385
 
 
386
 
 
387
  static void
 
388
  parse_fond( char*   fond_data,
 
389
              short*  have_sfnt,
 
390
              ResID*  sfnt_id,
 
391
              Str255  lwfn_file_name,
 
392
              short   face_index )
 
393
  {
 
394
    AsscEntry*  assoc;
 
395
    AsscEntry*  base_assoc;
 
396
    FamRec*     fond;
 
397
 
 
398
 
 
399
    *sfnt_id          = 0;
 
400
    *have_sfnt        = 0;
 
401
    lwfn_file_name[0] = 0;
 
402
 
 
403
    fond       = (FamRec*)fond_data;
 
404
    assoc      = (AsscEntry*)( fond_data + sizeof ( FamRec ) + 2 );
 
405
    base_assoc = assoc;
 
406
 
 
407
    /* the maximum faces in a FOND is 48, size of StyleTable.indexes[] */
 
408
    if ( 47 < face_index )
 
409
      return;
 
410
 
 
411
    /* Let's do a little range checking before we get too excited here */
 
412
    if ( face_index < count_faces_sfnt( fond_data ) )
 
413
    {
 
414
      assoc += face_index;        /* add on the face_index! */
 
415
 
 
416
      /* if the face at this index is not scalable,
 
417
         fall back to the first one (old behavior) */
 
418
      if ( EndianS16_BtoN( assoc->fontSize ) == 0 )
 
419
      {
 
420
        *have_sfnt = 1;
 
421
        *sfnt_id   = EndianS16_BtoN( assoc->fontID );
 
422
      }
 
423
      else if ( base_assoc->fontSize == 0 )
 
424
      {
 
425
        *have_sfnt = 1;
 
426
        *sfnt_id   = EndianS16_BtoN( base_assoc->fontID );
 
427
      }
 
428
    }
 
429
 
 
430
    if ( EndianS32_BtoN( fond->ffStylOff ) )
 
431
    {
 
432
      unsigned char*  p = (unsigned char*)fond_data;
 
433
      StyleTable*     style;
 
434
      unsigned short  string_count;
 
435
      char            ps_name[256];
 
436
      unsigned char*  names[64];
 
437
      int             i;
 
438
 
 
439
 
 
440
      p += EndianS32_BtoN( fond->ffStylOff );
 
441
      style = (StyleTable*)p;
 
442
      p += sizeof ( StyleTable );
 
443
      string_count = EndianS16_BtoN( *(short*)(p) );
 
444
      p += sizeof ( short );
 
445
 
 
446
      for ( i = 0; i < string_count && i < 64; i++ )
 
447
      {
 
448
        names[i] = p;
 
449
        p       += names[i][0];
 
450
        p++;
 
451
      }
 
452
 
 
453
      {
 
454
        size_t  ps_name_len = (size_t)names[0][0];
 
455
 
 
456
 
 
457
        if ( ps_name_len != 0 )
 
458
        {
 
459
          ft_memcpy(ps_name, names[0] + 1, ps_name_len);
 
460
          ps_name[ps_name_len] = 0;
 
461
        }
 
462
        if ( style->indexes[face_index] > 1 &&
 
463
             style->indexes[face_index] <= FT_MIN( string_count, 64 ) )
 
464
        {
 
465
          unsigned char*  suffixes = names[style->indexes[face_index] - 1];
 
466
 
 
467
 
 
468
          for ( i = 1; i <= suffixes[0]; i++ )
 
469
          {
 
470
            unsigned char*  s;
 
471
            size_t          j = suffixes[i] - 1;
 
472
 
 
473
 
 
474
            if ( j < string_count && ( s = names[j] ) != NULL )
 
475
            {
 
476
              size_t  s_len = (size_t)s[0];
 
477
 
 
478
 
 
479
              if ( s_len != 0 && ps_name_len + s_len < sizeof ( ps_name ) )
 
480
              {
 
481
                ft_memcpy( ps_name + ps_name_len, s + 1, s_len );
 
482
                ps_name_len += s_len;
 
483
                ps_name[ps_name_len] = 0;
 
484
              }
 
485
            }
 
486
          }
 
487
        }
 
488
      }
 
489
 
 
490
      create_lwfn_name( ps_name, lwfn_file_name );
 
491
    }
 
492
  }
 
493
 
 
494
 
 
495
  static  FT_Error
 
496
  lookup_lwfn_by_fond( const UInt8*      path_fond,
 
497
                       ConstStr255Param  base_lwfn,
 
498
                       UInt8*            path_lwfn,
 
499
                       size_t            path_size )
 
500
  {
 
501
    FSRef   ref, par_ref;
 
502
    size_t  dirname_len;
 
503
 
 
504
 
 
505
    /* Pathname for FSRef can be in various formats: HFS, HFS+, and POSIX. */
 
506
    /* We should not extract parent directory by string manipulation.      */
 
507
 
 
508
    if ( noErr != FSPathMakeRef( path_fond, &ref, FALSE ) )
 
509
      return FT_Err_Invalid_Argument;
 
510
 
 
511
    if ( noErr != FSGetCatalogInfo( &ref, kFSCatInfoNone,
 
512
                                    NULL, NULL, NULL, &par_ref ) )
 
513
      return FT_Err_Invalid_Argument;
 
514
 
 
515
    if ( noErr != FSRefMakePath( &par_ref, path_lwfn, path_size ) )
 
516
      return FT_Err_Invalid_Argument;
 
517
 
 
518
    if ( ft_strlen( (char *)path_lwfn ) + 1 + base_lwfn[0] > path_size )
 
519
      return FT_Err_Invalid_Argument;
 
520
 
 
521
    /* now we have absolute dirname in path_lwfn */
 
522
    ft_strcat( (char *)path_lwfn, "/" );
 
523
    dirname_len = ft_strlen( (char *)path_lwfn );
 
524
    ft_strcat( (char *)path_lwfn, (char *)base_lwfn + 1 );
 
525
    path_lwfn[dirname_len + base_lwfn[0]] = '\0';
 
526
 
 
527
    if ( noErr != FSPathMakeRef( path_lwfn, &ref, FALSE ) )
 
528
      return FT_Err_Cannot_Open_Resource;
 
529
 
 
530
    if ( noErr != FSGetCatalogInfo( &ref, kFSCatInfoNone,
 
531
                                    NULL, NULL, NULL, NULL ) )
 
532
      return FT_Err_Cannot_Open_Resource;
 
533
 
 
534
    return FT_Err_Ok;
 
535
  }
 
536
 
 
537
 
 
538
  static short
 
539
  count_faces( Handle        fond,
 
540
               const UInt8*  pathname )
 
541
  {
 
542
    ResID     sfnt_id;
 
543
    short     have_sfnt, have_lwfn;
 
544
    Str255    lwfn_file_name;
 
545
    UInt8     buff[PATH_MAX];
 
546
    FT_Error  err;
 
547
    short     num_faces;
 
548
 
 
549
 
 
550
    have_sfnt = have_lwfn = 0;
 
551
 
 
552
    parse_fond( *fond, &have_sfnt, &sfnt_id, lwfn_file_name, 0 );
 
553
 
 
554
    if ( lwfn_file_name[0] )
 
555
    {
 
556
      err = lookup_lwfn_by_fond( pathname, lwfn_file_name,
 
557
                                 buff, sizeof ( buff )  );
 
558
      if ( FT_Err_Ok == err )
 
559
        have_lwfn = 1;
 
560
    }
 
561
 
 
562
    if ( have_lwfn && ( !have_sfnt || PREFER_LWFN ) )
 
563
      num_faces = 1;
 
564
    else
 
565
      num_faces = count_faces_scalable( *fond );
 
566
 
 
567
    return num_faces;
 
568
  }
 
569
 
 
570
 
 
571
  /* Read Type 1 data from the POST resources inside the LWFN file,
 
572
     return a PFB buffer.  This is somewhat convoluted because the FT2
 
573
     PFB parser wants the ASCII header as one chunk, and the LWFN
 
574
     chunks are often not organized that way, so we glue chunks
 
575
     of the same type together. */
 
576
  static FT_Error
 
577
  read_lwfn( FT_Memory      memory,
 
578
             ResFileRefNum  res,
 
579
             FT_Byte**      pfb_data,
 
580
             FT_ULong*      size )
 
581
  {
 
582
    FT_Error       error = FT_Err_Ok;
 
583
    ResID          res_id;
 
584
    unsigned char  *buffer, *p, *size_p = NULL;
 
585
    FT_ULong       total_size = 0;
 
586
    FT_ULong       old_total_size = 0;
 
587
    FT_ULong       post_size, pfb_chunk_size;
 
588
    Handle         post_data;
 
589
    char           code, last_code;
 
590
 
 
591
 
 
592
    UseResFile( res );
 
593
 
 
594
    /* First pass: load all POST resources, and determine the size of */
 
595
    /* the output buffer.                                             */
 
596
    res_id    = 501;
 
597
    last_code = -1;
 
598
 
 
599
    for (;;)
 
600
    {
 
601
      post_data = Get1Resource( TTAG_POST, res_id++ );
 
602
      if ( post_data == NULL )
 
603
        break;  /* we are done */
 
604
 
 
605
      code = (*post_data)[0];
 
606
 
 
607
      if ( code != last_code )
 
608
      {
 
609
        if ( code == 5 )
 
610
          total_size += 2; /* just the end code */
 
611
        else
 
612
          total_size += 6; /* code + 4 bytes chunk length */
 
613
      }
 
614
 
 
615
      total_size += GetHandleSize( post_data ) - 2;
 
616
      last_code = code;
 
617
 
 
618
      /* detect integer overflows */
 
619
      if ( total_size < old_total_size )
 
620
      {
 
621
        error = FT_Err_Array_Too_Large;
 
622
        goto Error;
 
623
      }
 
624
 
 
625
      old_total_size = total_size;
 
626
    }
 
627
 
 
628
    if ( FT_ALLOC( buffer, (FT_Long)total_size ) )
 
629
      goto Error;
 
630
 
 
631
    /* Second pass: append all POST data to the buffer, add PFB fields. */
 
632
    /* Glue all consecutive chunks of the same type together.           */
 
633
    p              = buffer;
 
634
    res_id         = 501;
 
635
    last_code      = -1;
 
636
    pfb_chunk_size = 0;
 
637
 
 
638
    for (;;)
 
639
    {
 
640
      post_data = Get1Resource( TTAG_POST, res_id++ );
 
641
      if ( post_data == NULL )
 
642
        break;  /* we are done */
 
643
 
 
644
      post_size = (FT_ULong)GetHandleSize( post_data ) - 2;
 
645
      code = (*post_data)[0];
 
646
 
 
647
      if ( code != last_code )
 
648
      {
 
649
        if ( last_code != -1 )
 
650
        {
 
651
          /* we are done adding a chunk, fill in the size field */
 
652
          if ( size_p != NULL )
 
653
          {
 
654
            *size_p++ = (FT_Byte)(   pfb_chunk_size         & 0xFF );
 
655
            *size_p++ = (FT_Byte)( ( pfb_chunk_size >> 8  ) & 0xFF );
 
656
            *size_p++ = (FT_Byte)( ( pfb_chunk_size >> 16 ) & 0xFF );
 
657
            *size_p++ = (FT_Byte)( ( pfb_chunk_size >> 24 ) & 0xFF );
 
658
          }
 
659
          pfb_chunk_size = 0;
 
660
        }
 
661
 
 
662
        *p++ = 0x80;
 
663
        if ( code == 5 )
 
664
          *p++ = 0x03;  /* the end */
 
665
        else if ( code == 2 )
 
666
          *p++ = 0x02;  /* binary segment */
 
667
        else
 
668
          *p++ = 0x01;  /* ASCII segment */
 
669
 
 
670
        if ( code != 5 )
 
671
        {
 
672
          size_p = p;   /* save for later */
 
673
          p += 4;       /* make space for size field */
 
674
        }
 
675
      }
 
676
 
 
677
      ft_memcpy( p, *post_data + 2, post_size );
 
678
      pfb_chunk_size += post_size;
 
679
      p += post_size;
 
680
      last_code = code;
 
681
    }
 
682
 
 
683
    *pfb_data = buffer;
 
684
    *size = total_size;
 
685
 
 
686
  Error:
 
687
    CloseResFile( res );
 
688
    return error;
 
689
  }
 
690
 
 
691
 
 
692
  /* Create a new FT_Face from a file path to an LWFN file. */
 
693
  static FT_Error
 
694
  FT_New_Face_From_LWFN( FT_Library    library,
 
695
                         const UInt8*  pathname,
 
696
                         FT_Long       face_index,
 
697
                         FT_Face*      aface )
 
698
  {
 
699
    FT_Byte*       pfb_data;
 
700
    FT_ULong       pfb_size;
 
701
    FT_Error       error;
 
702
    ResFileRefNum  res;
 
703
 
 
704
 
 
705
    if ( noErr != FT_FSPathMakeRes( pathname, &res ) )
 
706
      return FT_Err_Cannot_Open_Resource;
 
707
 
 
708
    pfb_data = NULL;
 
709
    pfb_size = 0;
 
710
    error = read_lwfn( library->memory, res, &pfb_data, &pfb_size );
 
711
    CloseResFile( res ); /* PFB is already loaded, useless anymore */
 
712
    if ( error )
 
713
      return error;
 
714
 
 
715
    return open_face_from_buffer( library,
 
716
                                  pfb_data,
 
717
                                  pfb_size,
 
718
                                  face_index,
 
719
                                  "type1",
 
720
                                  aface );
 
721
  }
 
722
 
 
723
 
 
724
  /* Create a new FT_Face from an SFNT resource, specified by res ID. */
 
725
  static FT_Error
 
726
  FT_New_Face_From_SFNT( FT_Library  library,
 
727
                         ResID       sfnt_id,
 
728
                         FT_Long     face_index,
 
729
                         FT_Face*    aface )
 
730
  {
 
731
    Handle     sfnt = NULL;
 
732
    FT_Byte*   sfnt_data;
 
733
    size_t     sfnt_size;
 
734
    FT_Error   error  = FT_Err_Ok;
 
735
    FT_Memory  memory = library->memory;
 
736
    int        is_cff, is_sfnt_ps;
 
737
 
 
738
 
 
739
    sfnt = GetResource( TTAG_sfnt, sfnt_id );
 
740
    if ( sfnt == NULL )
 
741
      return FT_Err_Invalid_Handle;
 
742
 
 
743
    sfnt_size = (FT_ULong)GetHandleSize( sfnt );
 
744
    if ( FT_ALLOC( sfnt_data, (FT_Long)sfnt_size ) )
 
745
    {
 
746
      ReleaseResource( sfnt );
 
747
      return error;
 
748
    }
 
749
 
 
750
    ft_memcpy( sfnt_data, *sfnt, sfnt_size );
 
751
    ReleaseResource( sfnt );
 
752
 
 
753
    is_cff     = sfnt_size > 4 && !ft_memcmp( sfnt_data, "OTTO", 4 );
 
754
    is_sfnt_ps = sfnt_size > 4 && !ft_memcmp( sfnt_data, "typ1", 4 );
 
755
 
 
756
    if ( is_sfnt_ps )
 
757
    {
 
758
      FT_Stream  stream;
 
759
 
 
760
 
 
761
      if ( FT_NEW( stream ) )
 
762
        goto Try_OpenType;
 
763
 
 
764
      FT_Stream_OpenMemory( stream, sfnt_data, sfnt_size );
 
765
      if ( !open_face_PS_from_sfnt_stream( library,
 
766
                                           stream,
 
767
                                           face_index,
 
768
                                           0, NULL,
 
769
                                           aface ) )
 
770
      {
 
771
        FT_Stream_Close( stream );
 
772
        FT_FREE( stream );
 
773
        FT_FREE( sfnt_data );
 
774
        goto Exit;
 
775
      }
 
776
 
 
777
      FT_FREE( stream );
 
778
    }
 
779
  Try_OpenType:
 
780
    error = open_face_from_buffer( library,
 
781
                                   sfnt_data,
 
782
                                   sfnt_size,
 
783
                                   face_index,
 
784
                                   is_cff ? "cff" : "truetype",
 
785
                                   aface );
 
786
  Exit:
 
787
    return error;
 
788
  }
 
789
 
 
790
 
 
791
  /* Create a new FT_Face from a file path to a suitcase file. */
 
792
  static FT_Error
 
793
  FT_New_Face_From_Suitcase( FT_Library    library,
 
794
                             const UInt8*  pathname,
 
795
                             FT_Long       face_index,
 
796
                             FT_Face*      aface )
 
797
  {
 
798
    FT_Error       error = FT_Err_Cannot_Open_Resource;
 
799
    ResFileRefNum  res_ref;
 
800
    ResourceIndex  res_index;
 
801
    Handle         fond;
 
802
    short          num_faces_in_res, num_faces_in_fond;
 
803
 
 
804
 
 
805
    if ( noErr != FT_FSPathMakeRes( pathname, &res_ref ) )
 
806
      return FT_Err_Cannot_Open_Resource;
 
807
 
 
808
    UseResFile( res_ref );
 
809
    if ( ResError() )
 
810
      return FT_Err_Cannot_Open_Resource;
 
811
 
 
812
    num_faces_in_res = 0;
 
813
    for ( res_index = 1; ; ++res_index )
 
814
    {
 
815
      fond = Get1IndResource( TTAG_FOND, res_index );
 
816
      if ( ResError() )
 
817
        break;
 
818
 
 
819
      num_faces_in_fond  = count_faces( fond, pathname );
 
820
      num_faces_in_res  += num_faces_in_fond;
 
821
 
 
822
      if ( 0 <= face_index && face_index < num_faces_in_fond && error )
 
823
        error = FT_New_Face_From_FOND( library, fond, face_index, aface );
 
824
 
 
825
      face_index -= num_faces_in_fond;
 
826
    }
 
827
 
 
828
    CloseResFile( res_ref );
 
829
    if ( FT_Err_Ok == error && NULL != aface && NULL != *aface )
 
830
      (*aface)->num_faces = num_faces_in_res;
 
831
    return error;
 
832
  }
 
833
 
 
834
 
 
835
  /* documentation is in ftmac.h */
 
836
 
 
837
  FT_EXPORT_DEF( FT_Error )
 
838
  FT_New_Face_From_FOND( FT_Library  library,
 
839
                         Handle      fond,
 
840
                         FT_Long     face_index,
 
841
                         FT_Face*    aface )
 
842
  {
 
843
    short     have_sfnt, have_lwfn = 0;
 
844
    ResID     sfnt_id, fond_id;
 
845
    OSType    fond_type;
 
846
    Str255    fond_name;
 
847
    Str255    lwfn_file_name;
 
848
    UInt8     path_lwfn[PATH_MAX];
 
849
    OSErr     err;
 
850
    FT_Error  error = FT_Err_Ok;
 
851
 
 
852
 
 
853
    GetResInfo( fond, &fond_id, &fond_type, fond_name );
 
854
    if ( ResError() != noErr || fond_type != TTAG_FOND )
 
855
      return FT_Err_Invalid_File_Format;
 
856
 
 
857
    parse_fond( *fond, &have_sfnt, &sfnt_id, lwfn_file_name, face_index );
 
858
 
 
859
    if ( lwfn_file_name[0] )
 
860
    {
 
861
      ResFileRefNum  res;
 
862
 
 
863
 
 
864
      res = HomeResFile( fond );
 
865
      if ( noErr != ResError() )
 
866
        goto found_no_lwfn_file;
 
867
 
 
868
      {
 
869
        UInt8  path_fond[PATH_MAX];
 
870
        FSRef  ref;
 
871
 
 
872
 
 
873
        err = FSGetForkCBInfo( res, kFSInvalidVolumeRefNum,
 
874
                               NULL, NULL, NULL, &ref, NULL );
 
875
        if ( noErr != err )
 
876
          goto found_no_lwfn_file;
 
877
 
 
878
        err = FSRefMakePath( &ref, path_fond, sizeof ( path_fond ) );
 
879
        if ( noErr != err )
 
880
          goto found_no_lwfn_file;
 
881
 
 
882
        error = lookup_lwfn_by_fond( path_fond, lwfn_file_name,
 
883
                                     path_lwfn, sizeof ( path_lwfn ) );
 
884
        if ( FT_Err_Ok == error )
 
885
          have_lwfn = 1;
 
886
      }
 
887
    }
 
888
 
 
889
    if ( have_lwfn && ( !have_sfnt || PREFER_LWFN ) )
 
890
      error = FT_New_Face_From_LWFN( library,
 
891
                                     path_lwfn,
 
892
                                     face_index,
 
893
                                     aface );
 
894
    else
 
895
      error = FT_Err_Unknown_File_Format;
 
896
 
 
897
  found_no_lwfn_file:
 
898
    if ( have_sfnt && FT_Err_Ok != error )
 
899
      error = FT_New_Face_From_SFNT( library,
 
900
                                     sfnt_id,
 
901
                                     face_index,
 
902
                                     aface );
 
903
 
 
904
    return error;
 
905
  }
 
906
 
 
907
 
 
908
  /* Common function to load a new FT_Face from a resource file. */
 
909
  static FT_Error
 
910
  FT_New_Face_From_Resource( FT_Library    library,
 
911
                             const UInt8*  pathname,
 
912
                             FT_Long       face_index,
 
913
                             FT_Face*      aface )
 
914
  {
 
915
    OSType    file_type;
 
916
    FT_Error  error;
 
917
 
 
918
 
 
919
    /* LWFN is a (very) specific file format, check for it explicitly */
 
920
    file_type = get_file_type_from_path( pathname );
 
921
    if ( file_type == TTAG_LWFN )
 
922
      return FT_New_Face_From_LWFN( library, pathname, face_index, aface );
 
923
 
 
924
    /* Otherwise the file type doesn't matter (there are more than  */
 
925
    /* `FFIL' and `tfil').  Just try opening it as a font suitcase; */
 
926
    /* if it works, fine.                                           */
 
927
 
 
928
    error = FT_New_Face_From_Suitcase( library, pathname, face_index, aface );
 
929
    if ( error == 0 )
 
930
      return error;
 
931
 
 
932
    /* let it fall through to normal loader (.ttf, .otf, etc.); */
 
933
    /* we signal this by returning no error and no FT_Face      */
 
934
    *aface = NULL;
 
935
    return 0;
 
936
  }
 
937
 
 
938
 
 
939
  /*************************************************************************/
 
940
  /*                                                                       */
 
941
  /* <Function>                                                            */
 
942
  /*    FT_New_Face                                                        */
 
943
  /*                                                                       */
 
944
  /* <Description>                                                         */
 
945
  /*    This is the Mac-specific implementation of FT_New_Face.  In        */
 
946
  /*    addition to the standard FT_New_Face() functionality, it also      */
 
947
  /*    accepts pathnames to Mac suitcase files.  For further              */
 
948
  /*    documentation see the original FT_New_Face() in freetype.h.        */
 
949
  /*                                                                       */
 
950
  FT_EXPORT_DEF( FT_Error )
 
951
  FT_New_Face( FT_Library   library,
 
952
               const char*  pathname,
 
953
               FT_Long      face_index,
 
954
               FT_Face*     aface )
 
955
  {
 
956
    FT_Open_Args  args;
 
957
    FT_Error      error;
 
958
 
 
959
 
 
960
    /* test for valid `library' and `aface' delayed to FT_Open_Face() */
 
961
    if ( !pathname )
 
962
      return FT_Err_Invalid_Argument;
 
963
 
 
964
    error  = FT_Err_Ok;
 
965
    *aface = NULL;
 
966
 
 
967
    /* try resourcefork based font: LWFN, FFIL */
 
968
    error = FT_New_Face_From_Resource( library, (UInt8 *)pathname,
 
969
                                       face_index, aface );
 
970
    if ( error != 0 || *aface != NULL )
 
971
      return error;
 
972
 
 
973
    /* let it fall through to normal loader (.ttf, .otf, etc.) */
 
974
    args.flags    = FT_OPEN_PATHNAME;
 
975
    args.pathname = (char*)pathname;
 
976
    return FT_Open_Face( library, &args, face_index, aface );
 
977
  }
 
978
 
 
979
 
 
980
  /*************************************************************************/
 
981
  /*                                                                       */
 
982
  /* <Function>                                                            */
 
983
  /*    FT_New_Face_From_FSRef                                             */
 
984
  /*                                                                       */
 
985
  /* <Description>                                                         */
 
986
  /*    FT_New_Face_From_FSRef is identical to FT_New_Face except it       */
 
987
  /*    accepts an FSRef instead of a path.                                */
 
988
  /*                                                                       */
 
989
  /* This function is deprecated because Carbon data types (FSRef)         */
 
990
  /* are not cross-platform, and thus not suitable for the freetype API.   */
 
991
  FT_EXPORT_DEF( FT_Error )
 
992
  FT_New_Face_From_FSRef( FT_Library    library,
 
993
                          const FSRef*  ref,
 
994
                          FT_Long       face_index,
 
995
                          FT_Face*      aface )
 
996
  {
 
997
    FT_Error      error;
 
998
    FT_Open_Args  args;
 
999
    OSErr   err;
 
1000
    UInt8   pathname[PATH_MAX];
 
1001
 
 
1002
 
 
1003
    if ( !ref )
 
1004
      return FT_Err_Invalid_Argument;
 
1005
 
 
1006
    err = FSRefMakePath( ref, pathname, sizeof ( pathname ) );
 
1007
    if ( err )
 
1008
      error = FT_Err_Cannot_Open_Resource;
 
1009
 
 
1010
    error = FT_New_Face_From_Resource( library, pathname, face_index, aface );
 
1011
    if ( error != 0 || *aface != NULL )
 
1012
      return error;
 
1013
 
 
1014
    /* fallback to datafork font */
 
1015
    args.flags    = FT_OPEN_PATHNAME;
 
1016
    args.pathname = (char*)pathname;
 
1017
    return FT_Open_Face( library, &args, face_index, aface );
 
1018
  }
 
1019
 
 
1020
 
 
1021
  /*************************************************************************/
 
1022
  /*                                                                       */
 
1023
  /* <Function>                                                            */
 
1024
  /*    FT_New_Face_From_FSSpec                                            */
 
1025
  /*                                                                       */
 
1026
  /* <Description>                                                         */
 
1027
  /*    FT_New_Face_From_FSSpec is identical to FT_New_Face except it      */
 
1028
  /*    accepts an FSSpec instead of a path.                               */
 
1029
  /*                                                                       */
 
1030
  /* This function is deprecated because FSSpec is deprecated in Mac OS X  */
 
1031
  FT_EXPORT_DEF( FT_Error )
 
1032
  FT_New_Face_From_FSSpec( FT_Library     library,
 
1033
                           const FSSpec*  spec,
 
1034
                           FT_Long        face_index,
 
1035
                           FT_Face*       aface )
 
1036
  {
 
1037
#if ( __LP64__ ) || ( defined( MAC_OS_X_VERSION_10_5 ) && \
 
1038
      ( MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 ) )
 
1039
    FT_UNUSED( library );
 
1040
    FT_UNUSED( spec );
 
1041
    FT_UNUSED( face_index );
 
1042
    FT_UNUSED( aface );
 
1043
 
 
1044
    return FT_Err_Unimplemented_Feature;
 
1045
#else
 
1046
    FSRef  ref;
 
1047
 
 
1048
 
 
1049
    if ( !spec || FSpMakeFSRef( spec, &ref ) != noErr )
 
1050
      return FT_Err_Invalid_Argument;
 
1051
    else
 
1052
      return FT_New_Face_From_FSRef( library, &ref, face_index, aface );
 
1053
#endif
 
1054
  }
 
1055
 
 
1056
 
 
1057
/* END */