~ubuntu-branches/ubuntu/utopic/hedgewars/utopic

« back to all changes in this revision

Viewing changes to misc/libfreetype/builds/mac/ftmac.c

  • Committer: Package Import Robot
  • Author(s): Gianfranco Costamagna
  • Date: 2014-01-02 12:37:23 UTC
  • mfrom: (19.1.5 sid)
  • Revision ID: package-import@ubuntu.com-20140102123723-6pdhmyj8tb5y8xbg
Tags: 0.9.20.3-1
New upstream minor release, suitable for unstable

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 Fixed by mpsuzuki, George Williams and Sean McBride            */
7
 
/*                                                                         */
8
 
/*  Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 by       */
9
 
/*  Just van Rossum, David Turner, Robert Wilhelm, and Werner Lemberg.     */
10
 
/*                                                                         */
11
 
/*  This file is part of the FreeType project, and may only be used,       */
12
 
/*  modified, and distributed under the terms of the FreeType project      */
13
 
/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
14
 
/*  this file you indicate that you have read the license and              */
15
 
/*  understand and accept it fully.                                        */
16
 
/*                                                                         */
17
 
/***************************************************************************/
18
 
 
19
 
 
20
 
  /*
21
 
    Notes
22
 
 
23
 
    Mac suitcase files can (and often do!) contain multiple fonts.  To
24
 
    support this I use the face_index argument of FT_(Open|New)_Face()
25
 
    functions, and pretend the suitcase file is a collection.
26
 
 
27
 
    Warning: fbit and NFNT bitmap resources are not supported yet.  In old
28
 
    sfnt fonts, bitmap glyph data for each size is stored in each `NFNT'
29
 
    resources instead of the `bdat' table in the sfnt resource.  Therefore,
30
 
    face->num_fixed_sizes is set to 0, because bitmap data in `NFNT'
31
 
    resource is unavailable at present.
32
 
 
33
 
    The Mac FOND support works roughly like this:
34
 
 
35
 
    - Check whether the offered stream points to a Mac suitcase file.  This
36
 
      is done by checking the file type: it has to be 'FFIL' or 'tfil'.  The
37
 
      stream that gets passed to our init_face() routine is a stdio stream,
38
 
      which isn't usable for us, since the FOND resources live in the
39
 
      resource fork.  So we just grab the stream->pathname field.
40
 
 
41
 
    - Read the FOND resource into memory, then check whether there is a
42
 
      TrueType font and/or(!) a Type 1 font available.
43
 
 
44
 
    - If there is a Type 1 font available (as a separate `LWFN' file), read
45
 
      its data into memory, massage it slightly so it becomes PFB data, wrap
46
 
      it into a memory stream, load the Type 1 driver and delegate the rest
47
 
      of the work to it by calling FT_Open_Face().  (XXX TODO: after this
48
 
      has been done, the kerning data from the FOND resource should be
49
 
      appended to the face: On the Mac there are usually no AFM files
50
 
      available.  However, this is tricky since we need to map Mac char
51
 
      codes to ps glyph names to glyph ID's...)
52
 
 
53
 
    - If there is a TrueType font (an `sfnt' resource), read it into memory,
54
 
      wrap it into a memory stream, load the TrueType driver and delegate
55
 
      the rest of the work to it, by calling FT_Open_Face().
56
 
 
57
 
    - Some suitcase fonts (notably Onyx) might point the `LWFN' file to
58
 
      itself, even though it doesn't contains `POST' resources.  To handle
59
 
      this special case without opening the file an extra time, we just
60
 
      ignore errors from the `LWFN' and fallback to the `sfnt' if both are
61
 
      available.
62
 
  */
63
 
 
64
 
 
65
 
#include <ft2build.h>
66
 
#include FT_FREETYPE_H
67
 
#include FT_TRUETYPE_TAGS_H
68
 
#include FT_INTERNAL_STREAM_H
69
 
#include "ftbase.h"
70
 
 
71
 
#if defined( __GNUC__ ) || defined( __IBMC__ )
72
 
  /* This is for Mac OS X.  Without redefinition, OS_INLINE */
73
 
  /* expands to `static inline' which doesn't survive the   */
74
 
  /* -ansi compilation flag of GCC.                         */
75
 
#if !HAVE_ANSI_OS_INLINE
76
 
#undef  OS_INLINE
77
 
#define OS_INLINE   static __inline__
78
 
#endif
79
 
#include <CoreServices/CoreServices.h>
80
 
#include <ApplicationServices/ApplicationServices.h>
81
 
#include <sys/syslimits.h> /* PATH_MAX */
82
 
#else
83
 
#include <Resources.h>
84
 
#include <Fonts.h>
85
 
#include <Endian.h>
86
 
#include <Errors.h>
87
 
#include <Files.h>
88
 
#include <TextUtils.h>
89
 
#endif
90
 
 
91
 
#ifndef PATH_MAX
92
 
#define PATH_MAX 1024 /* same with Mac OS X's syslimits.h */
93
 
#endif
94
 
 
95
 
#if defined( __MWERKS__ ) && !TARGET_RT_MAC_MACHO
96
 
#include <FSp_fopen.h>
97
 
#endif
98
 
 
99
 
#define FT_DEPRECATED_ATTRIBUTE
100
 
 
101
 
#include FT_MAC_H
102
 
 
103
 
  /* undefine blocking-macros in ftmac.h */
104
 
#undef FT_GetFile_From_Mac_Name
105
 
#undef FT_GetFile_From_Mac_ATS_Name
106
 
#undef FT_New_Face_From_FOND
107
 
#undef FT_New_Face_From_FSSpec
108
 
#undef FT_New_Face_From_FSRef
109
 
 
110
 
 
111
 
  /* FSSpec functions are deprecated since Mac OS X 10.4 */
112
 
#ifndef HAVE_FSSPEC
113
 
#if TARGET_API_MAC_OS8 || TARGET_API_MAC_CARBON
114
 
#define HAVE_FSSPEC  1
115
 
#else
116
 
#define HAVE_FSSPEC  0
117
 
#endif
118
 
#endif
119
 
 
120
 
  /* most FSRef functions were introduced since Mac OS 9 */
121
 
#ifndef HAVE_FSREF
122
 
#if TARGET_API_MAC_OSX
123
 
#define HAVE_FSREF  1
124
 
#else
125
 
#define HAVE_FSREF  0
126
 
#endif
127
 
#endif
128
 
 
129
 
  /* QuickDraw is deprecated since Mac OS X 10.4 */
130
 
#ifndef HAVE_QUICKDRAW_CARBON
131
 
#if TARGET_API_MAC_OS8 || TARGET_API_MAC_CARBON
132
 
#define HAVE_QUICKDRAW_CARBON  1
133
 
#else
134
 
#define HAVE_QUICKDRAW_CARBON  0
135
 
#endif
136
 
#endif
137
 
 
138
 
  /* AppleTypeService is available since Mac OS X */
139
 
#ifndef HAVE_ATS
140
 
#if TARGET_API_MAC_OSX
141
 
#define HAVE_ATS  1
142
 
#ifndef kATSOptionFlagsUnRestrictedScope /* since Mac OS X 10.1 */
143
 
#define kATSOptionFlagsUnRestrictedScope kATSOptionFlagsDefault
144
 
#endif
145
 
#else
146
 
#define HAVE_ATS  0
147
 
#endif
148
 
#endif
149
 
 
150
 
  /* `configure' checks the availability of `ResourceIndex' strictly */
151
 
  /* and sets HAVE_TYPE_RESOURCE_INDEX to 1 or 0 always.  If it is   */
152
 
  /* not set (e.g., a build without `configure'), the availability   */
153
 
  /* is guessed from the SDK version.                                */
154
 
#ifndef HAVE_TYPE_RESOURCE_INDEX
155
 
#if !defined( MAC_OS_X_VERSION_10_5 ) || \
156
 
    ( MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5 )
157
 
#define HAVE_TYPE_RESOURCE_INDEX 0
158
 
#else
159
 
#define HAVE_TYPE_RESOURCE_INDEX 1
160
 
#endif
161
 
#endif /* !HAVE_TYPE_RESOURCE_INDEX */
162
 
 
163
 
#if ( HAVE_TYPE_RESOURCE_INDEX == 0 )
164
 
typedef short ResourceIndex;
165
 
#endif
166
 
 
167
 
  /* Set PREFER_LWFN to 1 if LWFN (Type 1) is preferred over
168
 
     TrueType in case *both* are available (this is not common,
169
 
     but it *is* possible). */
170
 
#ifndef PREFER_LWFN
171
 
#define PREFER_LWFN  1
172
 
#endif
173
 
 
174
 
 
175
 
#if !HAVE_QUICKDRAW_CARBON  /* QuickDraw is deprecated since Mac OS X 10.4 */
176
 
 
177
 
  FT_EXPORT_DEF( FT_Error )
178
 
  FT_GetFile_From_Mac_Name( const char*  fontName,
179
 
                            FSSpec*      pathSpec,
180
 
                            FT_Long*     face_index )
181
 
  {
182
 
    FT_UNUSED( fontName );
183
 
    FT_UNUSED( pathSpec );
184
 
    FT_UNUSED( face_index );
185
 
 
186
 
    return FT_Err_Unimplemented_Feature;
187
 
  }
188
 
 
189
 
#else
190
 
 
191
 
  FT_EXPORT_DEF( FT_Error )
192
 
  FT_GetFile_From_Mac_Name( const char*  fontName,
193
 
                            FSSpec*      pathSpec,
194
 
                            FT_Long*     face_index )
195
 
  {
196
 
    OptionBits            options = kFMUseGlobalScopeOption;
197
 
 
198
 
    FMFontFamilyIterator  famIter;
199
 
    OSStatus              status = FMCreateFontFamilyIterator( NULL, NULL,
200
 
                                                               options,
201
 
                                                               &famIter );
202
 
    FMFont                the_font = 0;
203
 
    FMFontFamily          family   = 0;
204
 
 
205
 
 
206
 
    *face_index = 0;
207
 
    while ( status == 0 && !the_font )
208
 
    {
209
 
      status = FMGetNextFontFamily( &famIter, &family );
210
 
      if ( status == 0 )
211
 
      {
212
 
        int                           stat2;
213
 
        FMFontFamilyInstanceIterator  instIter;
214
 
        Str255                        famNameStr;
215
 
        char                          famName[256];
216
 
 
217
 
 
218
 
        /* get the family name */
219
 
        FMGetFontFamilyName( family, famNameStr );
220
 
        CopyPascalStringToC( famNameStr, famName );
221
 
 
222
 
        /* iterate through the styles */
223
 
        FMCreateFontFamilyInstanceIterator( family, &instIter );
224
 
 
225
 
        *face_index = 0;
226
 
        stat2       = 0;
227
 
 
228
 
        while ( stat2 == 0 && !the_font )
229
 
        {
230
 
          FMFontStyle  style;
231
 
          FMFontSize   size;
232
 
          FMFont       font;
233
 
 
234
 
 
235
 
          stat2 = FMGetNextFontFamilyInstance( &instIter, &font,
236
 
                                               &style, &size );
237
 
          if ( stat2 == 0 && size == 0 )
238
 
          {
239
 
            char  fullName[256];
240
 
 
241
 
 
242
 
            /* build up a complete face name */
243
 
            ft_strcpy( fullName, famName );
244
 
            if ( style & bold )
245
 
              ft_strcat( fullName, " Bold" );
246
 
            if ( style & italic )
247
 
              ft_strcat( fullName, " Italic" );
248
 
 
249
 
            /* compare with the name we are looking for */
250
 
            if ( ft_strcmp( fullName, fontName ) == 0 )
251
 
            {
252
 
              /* found it! */
253
 
              the_font = font;
254
 
            }
255
 
            else
256
 
              ++(*face_index);
257
 
          }
258
 
        }
259
 
 
260
 
        FMDisposeFontFamilyInstanceIterator( &instIter );
261
 
      }
262
 
    }
263
 
 
264
 
    FMDisposeFontFamilyIterator( &famIter );
265
 
 
266
 
    if ( the_font )
267
 
    {
268
 
      FMGetFontContainer( the_font, pathSpec );
269
 
      return FT_Err_Ok;
270
 
    }
271
 
    else
272
 
      return FT_Err_Unknown_File_Format;
273
 
  }
274
 
 
275
 
#endif /* HAVE_QUICKDRAW_CARBON */
276
 
 
277
 
 
278
 
#if HAVE_ATS
279
 
 
280
 
  /* Private function.                                         */
281
 
  /* The FSSpec type has been discouraged for a long time,     */
282
 
  /* unfortunately an FSRef replacement API for                */
283
 
  /* ATSFontGetFileSpecification() is only available in        */
284
 
  /* Mac OS X 10.5 and later.                                  */
285
 
  static OSStatus
286
 
  FT_ATSFontGetFileReference( ATSFontRef  ats_font_id,
287
 
                              FSRef*      ats_font_ref )
288
 
  {
289
 
    OSStatus  err;
290
 
 
291
 
#if !defined( MAC_OS_X_VERSION_10_5 ) || \
292
 
    MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5
293
 
    FSSpec    spec;
294
 
 
295
 
 
296
 
    err = ATSFontGetFileSpecification( ats_font_id, &spec );
297
 
    if ( noErr == err )
298
 
      err = FSpMakeFSRef( &spec, ats_font_ref );
299
 
#else
300
 
    err = ATSFontGetFileReference( ats_font_id, ats_font_ref );
301
 
#endif
302
 
 
303
 
    return err;
304
 
  }
305
 
 
306
 
 
307
 
  static FT_Error
308
 
  FT_GetFileRef_From_Mac_ATS_Name( const char*  fontName,
309
 
                                   FSRef*       ats_font_ref,
310
 
                                   FT_Long*     face_index )
311
 
  {
312
 
    CFStringRef  cf_fontName;
313
 
    ATSFontRef   ats_font_id;
314
 
 
315
 
 
316
 
    *face_index = 0;
317
 
 
318
 
    cf_fontName = CFStringCreateWithCString( NULL, fontName,
319
 
                                             kCFStringEncodingMacRoman );
320
 
    ats_font_id = ATSFontFindFromName( cf_fontName,
321
 
                                       kATSOptionFlagsUnRestrictedScope );
322
 
    CFRelease( cf_fontName );
323
 
 
324
 
    if ( ats_font_id == 0 || ats_font_id == 0xFFFFFFFFUL )
325
 
      return FT_Err_Unknown_File_Format;
326
 
 
327
 
    if ( noErr != FT_ATSFontGetFileReference( ats_font_id, ats_font_ref ) )
328
 
      return FT_Err_Unknown_File_Format;
329
 
 
330
 
    /* face_index calculation by searching preceding fontIDs */
331
 
    /* with same FSRef                                       */
332
 
    {
333
 
      ATSFontRef  id2 = ats_font_id - 1;
334
 
      FSRef       ref2;
335
 
 
336
 
 
337
 
      while ( id2 > 0 )
338
 
      {
339
 
        if ( noErr != FT_ATSFontGetFileReference( id2, &ref2 ) )
340
 
          break;
341
 
        if ( noErr != FSCompareFSRefs( ats_font_ref, &ref2 ) )
342
 
          break;
343
 
 
344
 
        id2--;
345
 
      }
346
 
      *face_index = ats_font_id - ( id2 + 1 );
347
 
    }
348
 
 
349
 
    return FT_Err_Ok;
350
 
  }
351
 
 
352
 
#endif
353
 
 
354
 
#if !HAVE_ATS
355
 
 
356
 
  FT_EXPORT_DEF( FT_Error )
357
 
  FT_GetFilePath_From_Mac_ATS_Name( const char*  fontName,
358
 
                                    UInt8*       path,
359
 
                                    UInt32       maxPathSize,
360
 
                                    FT_Long*     face_index )
361
 
  {
362
 
    FT_UNUSED( fontName );
363
 
    FT_UNUSED( path );
364
 
    FT_UNUSED( maxPathSize );
365
 
    FT_UNUSED( face_index );
366
 
 
367
 
    return FT_Err_Unimplemented_Feature;
368
 
  }
369
 
 
370
 
#else
371
 
 
372
 
  FT_EXPORT_DEF( FT_Error )
373
 
  FT_GetFilePath_From_Mac_ATS_Name( const char*  fontName,
374
 
                                    UInt8*       path,
375
 
                                    UInt32       maxPathSize,
376
 
                                    FT_Long*     face_index )
377
 
  {
378
 
    FSRef     ref;
379
 
    FT_Error  err;
380
 
 
381
 
 
382
 
    err = FT_GetFileRef_From_Mac_ATS_Name( fontName, &ref, face_index );
383
 
    if ( FT_Err_Ok != err )
384
 
      return err;
385
 
 
386
 
    if ( noErr != FSRefMakePath( &ref, path, maxPathSize ) )
387
 
      return FT_Err_Unknown_File_Format;
388
 
 
389
 
    return FT_Err_Ok;
390
 
  }
391
 
 
392
 
#endif /* HAVE_ATS */
393
 
 
394
 
 
395
 
#if !HAVE_FSSPEC || !HAVE_ATS
396
 
 
397
 
  FT_EXPORT_DEF( FT_Error )
398
 
  FT_GetFile_From_Mac_ATS_Name( const char*  fontName,
399
 
                                FSSpec*      pathSpec,
400
 
                                FT_Long*     face_index )
401
 
  {
402
 
    FT_UNUSED( fontName );
403
 
    FT_UNUSED( pathSpec );
404
 
    FT_UNUSED( face_index );
405
 
 
406
 
    return FT_Err_Unimplemented_Feature;
407
 
  }
408
 
 
409
 
#else
410
 
 
411
 
  /* This function is deprecated because FSSpec is deprecated in Mac OS X. */
412
 
  FT_EXPORT_DEF( FT_Error )
413
 
  FT_GetFile_From_Mac_ATS_Name( const char*  fontName,
414
 
                                FSSpec*      pathSpec,
415
 
                                FT_Long*     face_index )
416
 
  {
417
 
    FSRef     ref;
418
 
    FT_Error  err;
419
 
 
420
 
 
421
 
    err = FT_GetFileRef_From_Mac_ATS_Name( fontName, &ref, face_index );
422
 
    if ( FT_Err_Ok != err )
423
 
      return err;
424
 
 
425
 
    if ( noErr != FSGetCatalogInfo( &ref, kFSCatInfoNone, NULL, NULL,
426
 
                                    pathSpec, NULL ) )
427
 
      return FT_Err_Unknown_File_Format;
428
 
 
429
 
    return FT_Err_Ok;
430
 
  }
431
 
 
432
 
#endif
433
 
 
434
 
 
435
 
#if defined( __MWERKS__ ) && !TARGET_RT_MAC_MACHO
436
 
 
437
 
#define STREAM_FILE( stream )  ( (FT_FILE*)stream->descriptor.pointer )
438
 
 
439
 
 
440
 
  FT_CALLBACK_DEF( void )
441
 
  ft_FSp_stream_close( FT_Stream  stream )
442
 
  {
443
 
    ft_fclose( STREAM_FILE( stream ) );
444
 
 
445
 
    stream->descriptor.pointer = NULL;
446
 
    stream->size               = 0;
447
 
    stream->base               = 0;
448
 
  }
449
 
 
450
 
 
451
 
  FT_CALLBACK_DEF( unsigned long )
452
 
  ft_FSp_stream_io( FT_Stream       stream,
453
 
                    unsigned long   offset,
454
 
                    unsigned char*  buffer,
455
 
                    unsigned long   count )
456
 
  {
457
 
    FT_FILE*  file;
458
 
 
459
 
 
460
 
    file = STREAM_FILE( stream );
461
 
 
462
 
    ft_fseek( file, offset, SEEK_SET );
463
 
 
464
 
    return (unsigned long)ft_fread( buffer, 1, count, file );
465
 
  }
466
 
 
467
 
#endif  /* __MWERKS__ && !TARGET_RT_MAC_MACHO */
468
 
 
469
 
 
470
 
#if HAVE_FSSPEC && !HAVE_FSREF
471
 
 
472
 
  /* isDirectory is a dummy to synchronize API with FSPathMakeRef() */
473
 
  static OSErr
474
 
  FT_FSPathMakeSpec( const UInt8*  pathname,
475
 
                     FSSpec*       spec_p,
476
 
                     Boolean       isDirectory )
477
 
  {
478
 
    const char  *p, *q;
479
 
    short       vRefNum;
480
 
    long        dirID;
481
 
    Str255      nodeName;
482
 
    OSErr       err;
483
 
    FT_UNUSED( isDirectory );
484
 
 
485
 
 
486
 
    p = q = (const char *)pathname;
487
 
    dirID   = 0;
488
 
    vRefNum = 0;
489
 
 
490
 
    while ( 1 )
491
 
    {
492
 
      int  len = ft_strlen( p );
493
 
 
494
 
 
495
 
      if ( len > 255 )
496
 
        len = 255;
497
 
 
498
 
      q = p + len;
499
 
 
500
 
      if ( q == p )
501
 
        return 0;
502
 
 
503
 
      if ( 255 < ft_strlen( (char *)pathname ) )
504
 
      {
505
 
        while ( p < q && *q != ':' )
506
 
          q--;
507
 
      }
508
 
 
509
 
      if ( p < q )
510
 
        *(char *)nodeName = q - p;
511
 
      else if ( ft_strlen( p ) < 256 )
512
 
        *(char *)nodeName = ft_strlen( p );
513
 
      else
514
 
        return errFSNameTooLong;
515
 
 
516
 
      ft_strncpy( (char *)nodeName + 1, (char *)p, *(char *)nodeName );
517
 
      err = FSMakeFSSpec( vRefNum, dirID, nodeName, spec_p );
518
 
      if ( err || '\0' == *q )
519
 
        return err;
520
 
 
521
 
      vRefNum = spec_p->vRefNum;
522
 
      dirID   = spec_p->parID;
523
 
 
524
 
      p = q;
525
 
    }
526
 
  }
527
 
 
528
 
 
529
 
  static OSErr
530
 
  FT_FSpMakePath( const FSSpec*  spec_p,
531
 
                  UInt8*         path,
532
 
                  UInt32         maxPathSize )
533
 
  {
534
 
    OSErr   err;
535
 
    FSSpec  spec = *spec_p;
536
 
    short   vRefNum;
537
 
    long    dirID;
538
 
    Str255  parDir_name;
539
 
 
540
 
 
541
 
    FT_MEM_SET( path, 0, maxPathSize );
542
 
    while ( 1 )
543
 
    {
544
 
      int             child_namelen = ft_strlen( (char *)path );
545
 
      unsigned char   node_namelen  = spec.name[0];
546
 
      unsigned char*  node_name     = spec.name + 1;
547
 
 
548
 
 
549
 
      if ( node_namelen + child_namelen > maxPathSize )
550
 
        return errFSNameTooLong;
551
 
 
552
 
      FT_MEM_MOVE( path + node_namelen + 1, path, child_namelen );
553
 
      FT_MEM_COPY( path, node_name, node_namelen );
554
 
      if ( child_namelen > 0 )
555
 
        path[node_namelen] = ':';
556
 
 
557
 
      vRefNum        = spec.vRefNum;
558
 
      dirID          = spec.parID;
559
 
      parDir_name[0] = '\0';
560
 
      err = FSMakeFSSpec( vRefNum, dirID, parDir_name, &spec );
561
 
      if ( noErr != err || dirID == spec.parID )
562
 
        break;
563
 
    }
564
 
    return noErr;
565
 
  }
566
 
 
567
 
#endif /* HAVE_FSSPEC && !HAVE_FSREF */
568
 
 
569
 
 
570
 
  static OSErr
571
 
  FT_FSPathMakeRes( const UInt8*    pathname,
572
 
                    ResFileRefNum*  res )
573
 
  {
574
 
 
575
 
#if HAVE_FSREF
576
 
 
577
 
    OSErr  err;
578
 
    FSRef  ref;
579
 
 
580
 
 
581
 
    if ( noErr != FSPathMakeRef( pathname, &ref, FALSE ) )
582
 
      return FT_Err_Cannot_Open_Resource;
583
 
 
584
 
    /* at present, no support for dfont format */
585
 
    err = FSOpenResourceFile( &ref, 0, NULL, fsRdPerm, res );
586
 
    if ( noErr == err )
587
 
      return err;
588
 
 
589
 
    /* fallback to original resource-fork font */
590
 
    *res = FSOpenResFile( &ref, fsRdPerm );
591
 
    err  = ResError();
592
 
 
593
 
#else
594
 
 
595
 
    OSErr   err;
596
 
    FSSpec  spec;
597
 
 
598
 
 
599
 
    if ( noErr != FT_FSPathMakeSpec( pathname, &spec, FALSE ) )
600
 
      return FT_Err_Cannot_Open_Resource;
601
 
 
602
 
    /* at present, no support for dfont format without FSRef */
603
 
    /* (see above), try original resource-fork font          */
604
 
    *res = FSpOpenResFile( &spec, fsRdPerm );
605
 
    err  = ResError();
606
 
 
607
 
#endif /* HAVE_FSREF */
608
 
 
609
 
    return err;
610
 
  }
611
 
 
612
 
 
613
 
  /* Return the file type for given pathname */
614
 
  static OSType
615
 
  get_file_type_from_path( const UInt8*  pathname )
616
 
  {
617
 
 
618
 
#if HAVE_FSREF
619
 
 
620
 
    FSRef          ref;
621
 
    FSCatalogInfo  info;
622
 
 
623
 
 
624
 
    if ( noErr != FSPathMakeRef( pathname, &ref, FALSE ) )
625
 
      return ( OSType ) 0;
626
 
 
627
 
    if ( noErr != FSGetCatalogInfo( &ref, kFSCatInfoFinderInfo, &info,
628
 
                                    NULL, NULL, NULL ) )
629
 
      return ( OSType ) 0;
630
 
 
631
 
    return ((FInfo *)(info.finderInfo))->fdType;
632
 
 
633
 
#else
634
 
 
635
 
    FSSpec  spec;
636
 
    FInfo   finfo;
637
 
 
638
 
 
639
 
    if ( noErr != FT_FSPathMakeSpec( pathname, &spec, FALSE ) )
640
 
      return ( OSType ) 0;
641
 
 
642
 
    if ( noErr != FSpGetFInfo( &spec, &finfo ) )
643
 
      return ( OSType ) 0;
644
 
 
645
 
    return finfo.fdType;
646
 
 
647
 
#endif /* HAVE_FSREF */
648
 
 
649
 
  }
650
 
 
651
 
 
652
 
  /* Given a PostScript font name, create the Macintosh LWFN file name. */
653
 
  static void
654
 
  create_lwfn_name( char*   ps_name,
655
 
                    Str255  lwfn_file_name )
656
 
  {
657
 
    int       max = 5, count = 0;
658
 
    FT_Byte*  p = lwfn_file_name;
659
 
    FT_Byte*  q = (FT_Byte*)ps_name;
660
 
 
661
 
 
662
 
    lwfn_file_name[0] = 0;
663
 
 
664
 
    while ( *q )
665
 
    {
666
 
      if ( ft_isupper( *q ) )
667
 
      {
668
 
        if ( count )
669
 
          max = 3;
670
 
        count = 0;
671
 
      }
672
 
      if ( count < max && ( ft_isalnum( *q ) || *q == '_' ) )
673
 
      {
674
 
        *++p = *q;
675
 
        lwfn_file_name[0]++;
676
 
        count++;
677
 
      }
678
 
      q++;
679
 
    }
680
 
  }
681
 
 
682
 
 
683
 
  static short
684
 
  count_faces_sfnt( char*  fond_data )
685
 
  {
686
 
    /* The count is 1 greater than the value in the FOND.  */
687
 
    /* Isn't that cute? :-)                                */
688
 
 
689
 
    return EndianS16_BtoN( *( (short*)( fond_data +
690
 
                                        sizeof ( FamRec ) ) ) ) + 1;
691
 
  }
692
 
 
693
 
 
694
 
  static short
695
 
  count_faces_scalable( char*  fond_data )
696
 
  {
697
 
    AsscEntry*  assoc;
698
 
    FamRec*     fond;
699
 
    short       i, face, face_all;
700
 
 
701
 
 
702
 
    fond     = (FamRec*)fond_data;
703
 
    face_all = EndianS16_BtoN( *( (short *)( fond_data +
704
 
                                             sizeof ( FamRec ) ) ) ) + 1;
705
 
    assoc    = (AsscEntry*)( fond_data + sizeof ( FamRec ) + 2 );
706
 
    face     = 0;
707
 
 
708
 
    for ( i = 0; i < face_all; i++ )
709
 
    {
710
 
      if ( 0 == EndianS16_BtoN( assoc[i].fontSize ) )
711
 
        face++;
712
 
    }
713
 
    return face;
714
 
  }
715
 
 
716
 
 
717
 
  /* Look inside the FOND data, answer whether there should be an SFNT
718
 
     resource, and answer the name of a possible LWFN Type 1 file.
719
 
 
720
 
     Thanks to Paul Miller (paulm@profoundeffects.com) for the fix
721
 
     to load a face OTHER than the first one in the FOND!
722
 
  */
723
 
 
724
 
  static void
725
 
  parse_fond( char*   fond_data,
726
 
              short*  have_sfnt,
727
 
              ResID*  sfnt_id,
728
 
              Str255  lwfn_file_name,
729
 
              short   face_index )
730
 
  {
731
 
    AsscEntry*  assoc;
732
 
    AsscEntry*  base_assoc;
733
 
    FamRec*     fond;
734
 
 
735
 
 
736
 
    *sfnt_id          = 0;
737
 
    *have_sfnt        = 0;
738
 
    lwfn_file_name[0] = 0;
739
 
 
740
 
    fond       = (FamRec*)fond_data;
741
 
    assoc      = (AsscEntry*)( fond_data + sizeof ( FamRec ) + 2 );
742
 
    base_assoc = assoc;
743
 
 
744
 
    /* the maximum faces in a FOND is 48, size of StyleTable.indexes[] */
745
 
    if ( 47 < face_index )
746
 
      return;
747
 
 
748
 
    /* Let's do a little range checking before we get too excited here */
749
 
    if ( face_index < count_faces_sfnt( fond_data ) )
750
 
    {
751
 
      assoc += face_index;        /* add on the face_index! */
752
 
 
753
 
      /* if the face at this index is not scalable,
754
 
         fall back to the first one (old behavior) */
755
 
      if ( EndianS16_BtoN( assoc->fontSize ) == 0 )
756
 
      {
757
 
        *have_sfnt = 1;
758
 
        *sfnt_id   = EndianS16_BtoN( assoc->fontID );
759
 
      }
760
 
      else if ( base_assoc->fontSize == 0 )
761
 
      {
762
 
        *have_sfnt = 1;
763
 
        *sfnt_id   = EndianS16_BtoN( base_assoc->fontID );
764
 
      }
765
 
    }
766
 
 
767
 
    if ( EndianS32_BtoN( fond->ffStylOff ) )
768
 
    {
769
 
      unsigned char*  p = (unsigned char*)fond_data;
770
 
      StyleTable*     style;
771
 
      unsigned short  string_count;
772
 
      char            ps_name[256];
773
 
      unsigned char*  names[64];
774
 
      int             i;
775
 
 
776
 
 
777
 
      p += EndianS32_BtoN( fond->ffStylOff );
778
 
      style = (StyleTable*)p;
779
 
      p += sizeof ( StyleTable );
780
 
      string_count = EndianS16_BtoN( *(short*)(p) );
781
 
      p += sizeof ( short );
782
 
 
783
 
      for ( i = 0; i < string_count && i < 64; i++ )
784
 
      {
785
 
        names[i] = p;
786
 
        p       += names[i][0];
787
 
        p++;
788
 
      }
789
 
 
790
 
      {
791
 
        size_t  ps_name_len = (size_t)names[0][0];
792
 
 
793
 
 
794
 
        if ( ps_name_len != 0 )
795
 
        {
796
 
          ft_memcpy(ps_name, names[0] + 1, ps_name_len);
797
 
          ps_name[ps_name_len] = 0;
798
 
        }
799
 
        if ( style->indexes[face_index] > 1 &&
800
 
             style->indexes[face_index] <= FT_MIN( string_count, 64 ) )
801
 
        {
802
 
          unsigned char*  suffixes = names[style->indexes[face_index] - 1];
803
 
 
804
 
 
805
 
          for ( i = 1; i <= suffixes[0]; i++ )
806
 
          {
807
 
            unsigned char*  s;
808
 
            size_t          j = suffixes[i] - 1;
809
 
 
810
 
 
811
 
            if ( j < string_count && ( s = names[j] ) != NULL )
812
 
            {
813
 
              size_t  s_len = (size_t)s[0];
814
 
 
815
 
 
816
 
              if ( s_len != 0 && ps_name_len + s_len < sizeof ( ps_name ) )
817
 
              {
818
 
                ft_memcpy( ps_name + ps_name_len, s + 1, s_len );
819
 
                ps_name_len += s_len;
820
 
                ps_name[ps_name_len] = 0;
821
 
              }
822
 
            }
823
 
          }
824
 
        }
825
 
      }
826
 
 
827
 
      create_lwfn_name( ps_name, lwfn_file_name );
828
 
    }
829
 
  }
830
 
 
831
 
 
832
 
  static  FT_Error
833
 
  lookup_lwfn_by_fond( const UInt8*      path_fond,
834
 
                       ConstStr255Param  base_lwfn,
835
 
                       UInt8*            path_lwfn,
836
 
                       int               path_size )
837
 
  {
838
 
 
839
 
#if HAVE_FSREF
840
 
 
841
 
    FSRef  ref, par_ref;
842
 
    int    dirname_len;
843
 
 
844
 
 
845
 
    /* Pathname for FSRef can be in various formats: HFS, HFS+, and POSIX. */
846
 
    /* We should not extract parent directory by string manipulation.      */
847
 
 
848
 
    if ( noErr != FSPathMakeRef( path_fond, &ref, FALSE ) )
849
 
      return FT_Err_Invalid_Argument;
850
 
 
851
 
    if ( noErr != FSGetCatalogInfo( &ref, kFSCatInfoNone,
852
 
                                    NULL, NULL, NULL, &par_ref ) )
853
 
      return FT_Err_Invalid_Argument;
854
 
 
855
 
    if ( noErr != FSRefMakePath( &par_ref, path_lwfn, path_size ) )
856
 
      return FT_Err_Invalid_Argument;
857
 
 
858
 
    if ( ft_strlen( (char *)path_lwfn ) + 1 + base_lwfn[0] > path_size )
859
 
      return FT_Err_Invalid_Argument;
860
 
 
861
 
    /* now we have absolute dirname in path_lwfn */
862
 
    if ( path_lwfn[0] == '/' )
863
 
      ft_strcat( (char *)path_lwfn, "/" );
864
 
    else
865
 
      ft_strcat( (char *)path_lwfn, ":" );
866
 
 
867
 
    dirname_len = ft_strlen( (char *)path_lwfn );
868
 
    ft_strcat( (char *)path_lwfn, (char *)base_lwfn + 1 );
869
 
    path_lwfn[dirname_len + base_lwfn[0]] = '\0';
870
 
 
871
 
    if ( noErr != FSPathMakeRef( path_lwfn, &ref, FALSE ) )
872
 
      return FT_Err_Cannot_Open_Resource;
873
 
 
874
 
    if ( noErr != FSGetCatalogInfo( &ref, kFSCatInfoNone,
875
 
                                    NULL, NULL, NULL, NULL ) )
876
 
      return FT_Err_Cannot_Open_Resource;
877
 
 
878
 
    return FT_Err_Ok;
879
 
 
880
 
#else
881
 
 
882
 
    int     i;
883
 
    FSSpec  spec;
884
 
 
885
 
 
886
 
    /* pathname for FSSpec is always HFS format */
887
 
    if ( ft_strlen( (char *)path_fond ) > path_size )
888
 
      return FT_Err_Invalid_Argument;
889
 
 
890
 
    ft_strcpy( (char *)path_lwfn, (char *)path_fond );
891
 
 
892
 
    i = ft_strlen( (char *)path_lwfn ) - 1;
893
 
    while ( i > 0 && ':' != path_lwfn[i] )
894
 
      i--;
895
 
 
896
 
    if ( i + 1 + base_lwfn[0] > path_size )
897
 
      return FT_Err_Invalid_Argument;
898
 
 
899
 
    if ( ':' == path_lwfn[i] )
900
 
    {
901
 
      ft_strcpy( (char *)path_lwfn + i + 1, (char *)base_lwfn + 1 );
902
 
      path_lwfn[i + 1 + base_lwfn[0]] = '\0';
903
 
    }
904
 
    else
905
 
    {
906
 
      ft_strcpy( (char *)path_lwfn, (char *)base_lwfn + 1 );
907
 
      path_lwfn[base_lwfn[0]] = '\0';
908
 
    }
909
 
 
910
 
    if ( noErr != FT_FSPathMakeSpec( path_lwfn, &spec, FALSE ) )
911
 
      return FT_Err_Cannot_Open_Resource;
912
 
 
913
 
    return FT_Err_Ok;
914
 
 
915
 
#endif /* HAVE_FSREF */
916
 
 
917
 
  }
918
 
 
919
 
 
920
 
  static short
921
 
  count_faces( Handle        fond,
922
 
               const UInt8*  pathname )
923
 
  {
924
 
    ResID     sfnt_id;
925
 
    short     have_sfnt, have_lwfn;
926
 
    Str255    lwfn_file_name;
927
 
    UInt8     buff[PATH_MAX];
928
 
    FT_Error  err;
929
 
    short     num_faces;
930
 
 
931
 
 
932
 
    have_sfnt = have_lwfn = 0;
933
 
 
934
 
    HLock( fond );
935
 
    parse_fond( *fond, &have_sfnt, &sfnt_id, lwfn_file_name, 0 );
936
 
 
937
 
    if ( lwfn_file_name[0] )
938
 
    {
939
 
      err = lookup_lwfn_by_fond( pathname, lwfn_file_name,
940
 
                                 buff, sizeof ( buff )  );
941
 
      if ( FT_Err_Ok == err )
942
 
        have_lwfn = 1;
943
 
    }
944
 
 
945
 
    if ( have_lwfn && ( !have_sfnt || PREFER_LWFN ) )
946
 
      num_faces = 1;
947
 
    else
948
 
      num_faces = count_faces_scalable( *fond );
949
 
 
950
 
    HUnlock( fond );
951
 
    return num_faces;
952
 
  }
953
 
 
954
 
 
955
 
  /* Read Type 1 data from the POST resources inside the LWFN file,
956
 
     return a PFB buffer.  This is somewhat convoluted because the FT2
957
 
     PFB parser wants the ASCII header as one chunk, and the LWFN
958
 
     chunks are often not organized that way, so we glue chunks
959
 
     of the same type together. */
960
 
  static FT_Error
961
 
  read_lwfn( FT_Memory      memory,
962
 
             ResFileRefNum  res,
963
 
             FT_Byte**      pfb_data,
964
 
             FT_ULong*      size )
965
 
  {
966
 
    FT_Error       error = FT_Err_Ok;
967
 
    ResID          res_id;
968
 
    unsigned char  *buffer, *p, *size_p = NULL;
969
 
    FT_ULong       total_size = 0;
970
 
    FT_ULong       old_total_size = 0;
971
 
    FT_ULong       post_size, pfb_chunk_size;
972
 
    Handle         post_data;
973
 
    char           code, last_code;
974
 
 
975
 
 
976
 
    UseResFile( res );
977
 
 
978
 
    /* First pass: load all POST resources, and determine the size of */
979
 
    /* the output buffer.                                             */
980
 
    res_id    = 501;
981
 
    last_code = -1;
982
 
 
983
 
    for (;;)
984
 
    {
985
 
      post_data = Get1Resource( TTAG_POST, res_id++ );
986
 
      if ( post_data == NULL )
987
 
        break;  /* we are done */
988
 
 
989
 
      code = (*post_data)[0];
990
 
 
991
 
      if ( code != last_code )
992
 
      {
993
 
        if ( code == 5 )
994
 
          total_size += 2; /* just the end code */
995
 
        else
996
 
          total_size += 6; /* code + 4 bytes chunk length */
997
 
      }
998
 
 
999
 
      total_size += GetHandleSize( post_data ) - 2;
1000
 
      last_code = code;
1001
 
 
1002
 
      /* detect integer overflows */
1003
 
      if ( total_size < old_total_size )
1004
 
      {
1005
 
        error = FT_Err_Array_Too_Large;
1006
 
        goto Error;
1007
 
      }
1008
 
 
1009
 
      old_total_size = total_size;
1010
 
    }
1011
 
 
1012
 
    if ( FT_ALLOC( buffer, (FT_Long)total_size ) )
1013
 
      goto Error;
1014
 
 
1015
 
    /* Second pass: append all POST data to the buffer, add PFB fields. */
1016
 
    /* Glue all consecutive chunks of the same type together.           */
1017
 
    p              = buffer;
1018
 
    res_id         = 501;
1019
 
    last_code      = -1;
1020
 
    pfb_chunk_size = 0;
1021
 
 
1022
 
    for (;;)
1023
 
    {
1024
 
      post_data = Get1Resource( TTAG_POST, res_id++ );
1025
 
      if ( post_data == NULL )
1026
 
        break;  /* we are done */
1027
 
 
1028
 
      post_size = (FT_ULong)GetHandleSize( post_data ) - 2;
1029
 
      code = (*post_data)[0];
1030
 
 
1031
 
      if ( code != last_code )
1032
 
      {
1033
 
        if ( last_code != -1 )
1034
 
        {
1035
 
          /* we are done adding a chunk, fill in the size field */
1036
 
          if ( size_p != NULL )
1037
 
          {
1038
 
            *size_p++ = (FT_Byte)(   pfb_chunk_size         & 0xFF );
1039
 
            *size_p++ = (FT_Byte)( ( pfb_chunk_size >> 8  ) & 0xFF );
1040
 
            *size_p++ = (FT_Byte)( ( pfb_chunk_size >> 16 ) & 0xFF );
1041
 
            *size_p++ = (FT_Byte)( ( pfb_chunk_size >> 24 ) & 0xFF );
1042
 
          }
1043
 
          pfb_chunk_size = 0;
1044
 
        }
1045
 
 
1046
 
        *p++ = 0x80;
1047
 
        if ( code == 5 )
1048
 
          *p++ = 0x03;  /* the end */
1049
 
        else if ( code == 2 )
1050
 
          *p++ = 0x02;  /* binary segment */
1051
 
        else
1052
 
          *p++ = 0x01;  /* ASCII segment */
1053
 
 
1054
 
        if ( code != 5 )
1055
 
        {
1056
 
          size_p = p;   /* save for later */
1057
 
          p += 4;       /* make space for size field */
1058
 
        }
1059
 
      }
1060
 
 
1061
 
      ft_memcpy( p, *post_data + 2, post_size );
1062
 
      pfb_chunk_size += post_size;
1063
 
      p += post_size;
1064
 
      last_code = code;
1065
 
    }
1066
 
 
1067
 
    *pfb_data = buffer;
1068
 
    *size = total_size;
1069
 
 
1070
 
  Error:
1071
 
    CloseResFile( res );
1072
 
    return error;
1073
 
  }
1074
 
 
1075
 
 
1076
 
  /* Create a new FT_Face from a file spec to an LWFN file. */
1077
 
  static FT_Error
1078
 
  FT_New_Face_From_LWFN( FT_Library    library,
1079
 
                         const UInt8*  pathname,
1080
 
                         FT_Long       face_index,
1081
 
                         FT_Face*      aface )
1082
 
  {
1083
 
    FT_Byte*       pfb_data;
1084
 
    FT_ULong       pfb_size;
1085
 
    FT_Error       error;
1086
 
    ResFileRefNum  res;
1087
 
 
1088
 
 
1089
 
    if ( noErr != FT_FSPathMakeRes( pathname, &res ) )
1090
 
      return FT_Err_Cannot_Open_Resource;
1091
 
 
1092
 
    pfb_data = NULL;
1093
 
    pfb_size = 0;
1094
 
    error = read_lwfn( library->memory, res, &pfb_data, &pfb_size );
1095
 
    CloseResFile( res ); /* PFB is already loaded, useless anymore */
1096
 
    if ( error )
1097
 
      return error;
1098
 
 
1099
 
    return open_face_from_buffer( library,
1100
 
                                  pfb_data,
1101
 
                                  pfb_size,
1102
 
                                  face_index,
1103
 
                                  "type1",
1104
 
                                  aface );
1105
 
  }
1106
 
 
1107
 
 
1108
 
  /* Create a new FT_Face from an SFNT resource, specified by res ID. */
1109
 
  static FT_Error
1110
 
  FT_New_Face_From_SFNT( FT_Library  library,
1111
 
                         ResID       sfnt_id,
1112
 
                         FT_Long     face_index,
1113
 
                         FT_Face*    aface )
1114
 
  {
1115
 
    Handle     sfnt = NULL;
1116
 
    FT_Byte*   sfnt_data;
1117
 
    size_t     sfnt_size;
1118
 
    FT_Error   error  = FT_Err_Ok;
1119
 
    FT_Memory  memory = library->memory;
1120
 
    int        is_cff, is_sfnt_ps;
1121
 
 
1122
 
 
1123
 
    sfnt = GetResource( TTAG_sfnt, sfnt_id );
1124
 
    if ( sfnt == NULL )
1125
 
      return FT_Err_Invalid_Handle;
1126
 
 
1127
 
    sfnt_size = (FT_ULong)GetHandleSize( sfnt );
1128
 
    if ( FT_ALLOC( sfnt_data, (FT_Long)sfnt_size ) )
1129
 
    {
1130
 
      ReleaseResource( sfnt );
1131
 
      return error;
1132
 
    }
1133
 
 
1134
 
    HLock( sfnt );
1135
 
    ft_memcpy( sfnt_data, *sfnt, sfnt_size );
1136
 
    HUnlock( sfnt );
1137
 
    ReleaseResource( sfnt );
1138
 
 
1139
 
    is_cff     = sfnt_size > 4 && !ft_memcmp( sfnt_data, "OTTO", 4 );
1140
 
    is_sfnt_ps = sfnt_size > 4 && !ft_memcmp( sfnt_data, "typ1", 4 );
1141
 
 
1142
 
    if ( is_sfnt_ps )
1143
 
    {
1144
 
      FT_Stream  stream;
1145
 
 
1146
 
 
1147
 
      if ( FT_NEW( stream ) )
1148
 
        goto Try_OpenType;
1149
 
 
1150
 
      FT_Stream_OpenMemory( stream, sfnt_data, sfnt_size );
1151
 
      if ( !open_face_PS_from_sfnt_stream( library,
1152
 
                                           stream,
1153
 
                                           face_index,
1154
 
                                           0, NULL,
1155
 
                                           aface ) )
1156
 
      {
1157
 
        FT_Stream_Close( stream );
1158
 
        FT_FREE( stream );
1159
 
        FT_FREE( sfnt_data );
1160
 
        goto Exit;
1161
 
      }
1162
 
 
1163
 
      FT_FREE( stream );
1164
 
    }
1165
 
  Try_OpenType:
1166
 
    error = open_face_from_buffer( library,
1167
 
                                   sfnt_data,
1168
 
                                   sfnt_size,
1169
 
                                   face_index,
1170
 
                                   is_cff ? "cff" : "truetype",
1171
 
                                   aface );
1172
 
  Exit:
1173
 
    return error;
1174
 
  }
1175
 
 
1176
 
 
1177
 
  /* Create a new FT_Face from a file spec to a suitcase file. */
1178
 
  static FT_Error
1179
 
  FT_New_Face_From_Suitcase( FT_Library    library,
1180
 
                             const UInt8*  pathname,
1181
 
                             FT_Long       face_index,
1182
 
                             FT_Face*      aface )
1183
 
  {
1184
 
    FT_Error       error = FT_Err_Cannot_Open_Resource;
1185
 
    ResFileRefNum  res_ref;
1186
 
    ResourceIndex  res_index;
1187
 
    Handle         fond;
1188
 
    short          num_faces_in_res, num_faces_in_fond;
1189
 
 
1190
 
 
1191
 
    if ( noErr != FT_FSPathMakeRes( pathname, &res_ref ) )
1192
 
      return FT_Err_Cannot_Open_Resource;
1193
 
 
1194
 
    UseResFile( res_ref );
1195
 
    if ( ResError() )
1196
 
      return FT_Err_Cannot_Open_Resource;
1197
 
 
1198
 
    num_faces_in_res = 0;
1199
 
    for ( res_index = 1; ; ++res_index )
1200
 
    {
1201
 
      fond = Get1IndResource( TTAG_FOND, res_index );
1202
 
      if ( ResError() )
1203
 
        break;
1204
 
 
1205
 
      num_faces_in_fond  = count_faces( fond, pathname );
1206
 
      num_faces_in_res  += num_faces_in_fond;
1207
 
 
1208
 
      if ( 0 <= face_index && face_index < num_faces_in_fond && error )
1209
 
        error = FT_New_Face_From_FOND( library, fond, face_index, aface );
1210
 
 
1211
 
      face_index -= num_faces_in_fond;
1212
 
    }
1213
 
 
1214
 
    CloseResFile( res_ref );
1215
 
    if ( FT_Err_Ok == error && NULL != aface )
1216
 
      (*aface)->num_faces = num_faces_in_res;
1217
 
    return error;
1218
 
  }
1219
 
 
1220
 
 
1221
 
  /* documentation is in ftmac.h */
1222
 
 
1223
 
  FT_EXPORT_DEF( FT_Error )
1224
 
  FT_New_Face_From_FOND( FT_Library  library,
1225
 
                         Handle      fond,
1226
 
                         FT_Long     face_index,
1227
 
                         FT_Face*    aface )
1228
 
  {
1229
 
    short     have_sfnt, have_lwfn = 0;
1230
 
    ResID     sfnt_id, fond_id;
1231
 
    OSType    fond_type;
1232
 
    Str255    fond_name;
1233
 
    Str255    lwfn_file_name;
1234
 
    UInt8     path_lwfn[PATH_MAX];
1235
 
    OSErr     err;
1236
 
    FT_Error  error = FT_Err_Ok;
1237
 
 
1238
 
 
1239
 
    GetResInfo( fond, &fond_id, &fond_type, fond_name );
1240
 
    if ( ResError() != noErr || fond_type != TTAG_FOND )
1241
 
      return FT_Err_Invalid_File_Format;
1242
 
 
1243
 
    HLock( fond );
1244
 
    parse_fond( *fond, &have_sfnt, &sfnt_id, lwfn_file_name, face_index );
1245
 
    HUnlock( fond );
1246
 
 
1247
 
    if ( lwfn_file_name[0] )
1248
 
    {
1249
 
      ResFileRefNum  res;
1250
 
 
1251
 
 
1252
 
      res = HomeResFile( fond );
1253
 
      if ( noErr != ResError() )
1254
 
        goto found_no_lwfn_file;
1255
 
 
1256
 
#if HAVE_FSREF
1257
 
 
1258
 
      {
1259
 
        UInt8  path_fond[PATH_MAX];
1260
 
        FSRef  ref;
1261
 
 
1262
 
 
1263
 
        err = FSGetForkCBInfo( res, kFSInvalidVolumeRefNum,
1264
 
                               NULL, NULL, NULL, &ref, NULL );
1265
 
        if ( noErr != err )
1266
 
          goto found_no_lwfn_file;
1267
 
 
1268
 
        err = FSRefMakePath( &ref, path_fond, sizeof ( path_fond ) );
1269
 
        if ( noErr != err )
1270
 
          goto found_no_lwfn_file;
1271
 
 
1272
 
        error = lookup_lwfn_by_fond( path_fond, lwfn_file_name,
1273
 
                                     path_lwfn, sizeof ( path_lwfn ) );
1274
 
        if ( FT_Err_Ok == error )
1275
 
          have_lwfn = 1;
1276
 
      }
1277
 
 
1278
 
#elif HAVE_FSSPEC
1279
 
 
1280
 
      {
1281
 
        UInt8     path_fond[PATH_MAX];
1282
 
        FCBPBRec  pb;
1283
 
        Str255    fond_file_name;
1284
 
        FSSpec    spec;
1285
 
 
1286
 
 
1287
 
        FT_MEM_SET( &spec, 0, sizeof ( FSSpec ) );
1288
 
        FT_MEM_SET( &pb,   0, sizeof ( FCBPBRec ) );
1289
 
 
1290
 
        pb.ioNamePtr = fond_file_name;
1291
 
        pb.ioVRefNum = 0;
1292
 
        pb.ioRefNum  = res;
1293
 
        pb.ioFCBIndx = 0;
1294
 
 
1295
 
        err = PBGetFCBInfoSync( &pb );
1296
 
        if ( noErr != err )
1297
 
          goto found_no_lwfn_file;
1298
 
 
1299
 
        err = FSMakeFSSpec( pb.ioFCBVRefNum, pb.ioFCBParID,
1300
 
                            fond_file_name, &spec );
1301
 
        if ( noErr != err )
1302
 
          goto found_no_lwfn_file;
1303
 
 
1304
 
        err = FT_FSpMakePath( &spec, path_fond, sizeof ( path_fond ) );
1305
 
        if ( noErr != err )
1306
 
          goto found_no_lwfn_file;
1307
 
 
1308
 
        error = lookup_lwfn_by_fond( path_fond, lwfn_file_name,
1309
 
                                     path_lwfn, sizeof ( path_lwfn ) );
1310
 
        if ( FT_Err_Ok == error )
1311
 
          have_lwfn = 1;
1312
 
      }
1313
 
 
1314
 
#endif /* HAVE_FSREF, HAVE_FSSPEC */
1315
 
 
1316
 
    }
1317
 
 
1318
 
    if ( have_lwfn && ( !have_sfnt || PREFER_LWFN ) )
1319
 
      error = FT_New_Face_From_LWFN( library,
1320
 
                                     path_lwfn,
1321
 
                                     face_index,
1322
 
                                     aface );
1323
 
    else
1324
 
      error = FT_Err_Unknown_File_Format;
1325
 
 
1326
 
  found_no_lwfn_file:
1327
 
    if ( have_sfnt && FT_Err_Ok != error )
1328
 
      error = FT_New_Face_From_SFNT( library,
1329
 
                                     sfnt_id,
1330
 
                                     face_index,
1331
 
                                     aface );
1332
 
 
1333
 
    return error;
1334
 
  }
1335
 
 
1336
 
 
1337
 
  /* Common function to load a new FT_Face from a resource file. */
1338
 
  static FT_Error
1339
 
  FT_New_Face_From_Resource( FT_Library    library,
1340
 
                             const UInt8*  pathname,
1341
 
                             FT_Long       face_index,
1342
 
                             FT_Face*      aface )
1343
 
  {
1344
 
    OSType    file_type;
1345
 
    FT_Error  error;
1346
 
 
1347
 
 
1348
 
    /* LWFN is a (very) specific file format, check for it explicitly */
1349
 
    file_type = get_file_type_from_path( pathname );
1350
 
    if ( file_type == TTAG_LWFN )
1351
 
      return FT_New_Face_From_LWFN( library, pathname, face_index, aface );
1352
 
 
1353
 
    /* Otherwise the file type doesn't matter (there are more than  */
1354
 
    /* `FFIL' and `tfil').  Just try opening it as a font suitcase; */
1355
 
    /* if it works, fine.                                           */
1356
 
 
1357
 
    error = FT_New_Face_From_Suitcase( library, pathname, face_index, aface );
1358
 
    if ( error == 0 )
1359
 
      return error;
1360
 
 
1361
 
    /* let it fall through to normal loader (.ttf, .otf, etc.); */
1362
 
    /* we signal this by returning no error and no FT_Face      */
1363
 
    *aface = NULL;
1364
 
    return 0;
1365
 
  }
1366
 
 
1367
 
 
1368
 
  /*************************************************************************/
1369
 
  /*                                                                       */
1370
 
  /* <Function>                                                            */
1371
 
  /*    FT_New_Face                                                        */
1372
 
  /*                                                                       */
1373
 
  /* <Description>                                                         */
1374
 
  /*    This is the Mac-specific implementation of FT_New_Face.  In        */
1375
 
  /*    addition to the standard FT_New_Face() functionality, it also      */
1376
 
  /*    accepts pathnames to Mac suitcase files.  For further              */
1377
 
  /*    documentation see the original FT_New_Face() in freetype.h.        */
1378
 
  /*                                                                       */
1379
 
  FT_EXPORT_DEF( FT_Error )
1380
 
  FT_New_Face( FT_Library   library,
1381
 
               const char*  pathname,
1382
 
               FT_Long      face_index,
1383
 
               FT_Face*     aface )
1384
 
  {
1385
 
    FT_Open_Args  args;
1386
 
    FT_Error      error;
1387
 
 
1388
 
 
1389
 
    /* test for valid `library' and `aface' delayed to FT_Open_Face() */
1390
 
    if ( !pathname )
1391
 
      return FT_Err_Invalid_Argument;
1392
 
 
1393
 
    error  = FT_Err_Ok;
1394
 
    *aface = NULL;
1395
 
 
1396
 
    /* try resourcefork based font: LWFN, FFIL */
1397
 
    error = FT_New_Face_From_Resource( library, (UInt8 *)pathname,
1398
 
                                       face_index, aface );
1399
 
    if ( error != 0 || *aface != NULL )
1400
 
      return error;
1401
 
 
1402
 
    /* let it fall through to normal loader (.ttf, .otf, etc.) */
1403
 
    args.flags    = FT_OPEN_PATHNAME;
1404
 
    args.pathname = (char*)pathname;
1405
 
    return FT_Open_Face( library, &args, face_index, aface );
1406
 
  }
1407
 
 
1408
 
 
1409
 
  /*************************************************************************/
1410
 
  /*                                                                       */
1411
 
  /* <Function>                                                            */
1412
 
  /*    FT_New_Face_From_FSRef                                             */
1413
 
  /*                                                                       */
1414
 
  /* <Description>                                                         */
1415
 
  /*    FT_New_Face_From_FSRef is identical to FT_New_Face except it       */
1416
 
  /*    accepts an FSRef instead of a path.                                */
1417
 
  /*                                                                       */
1418
 
  /* This function is deprecated because Carbon data types (FSRef)         */
1419
 
  /* are not cross-platform, and thus not suitable for the freetype API.   */
1420
 
  FT_EXPORT_DEF( FT_Error )
1421
 
  FT_New_Face_From_FSRef( FT_Library    library,
1422
 
                          const FSRef*  ref,
1423
 
                          FT_Long       face_index,
1424
 
                          FT_Face*      aface )
1425
 
  {
1426
 
 
1427
 
#if !HAVE_FSREF
1428
 
 
1429
 
    FT_UNUSED( library );
1430
 
    FT_UNUSED( ref );
1431
 
    FT_UNUSED( face_index );
1432
 
    FT_UNUSED( aface );
1433
 
 
1434
 
    return FT_Err_Unimplemented_Feature;
1435
 
 
1436
 
#else
1437
 
 
1438
 
    FT_Error      error;
1439
 
    FT_Open_Args  args;
1440
 
    OSErr   err;
1441
 
    UInt8   pathname[PATH_MAX];
1442
 
 
1443
 
 
1444
 
    if ( !ref )
1445
 
      return FT_Err_Invalid_Argument;
1446
 
 
1447
 
    err = FSRefMakePath( ref, pathname, sizeof ( pathname ) );
1448
 
    if ( err )
1449
 
      error = FT_Err_Cannot_Open_Resource;
1450
 
 
1451
 
    error = FT_New_Face_From_Resource( library, pathname, face_index, aface );
1452
 
    if ( error != 0 || *aface != NULL )
1453
 
      return error;
1454
 
 
1455
 
    /* fallback to datafork font */
1456
 
    args.flags    = FT_OPEN_PATHNAME;
1457
 
    args.pathname = (char*)pathname;
1458
 
    return FT_Open_Face( library, &args, face_index, aface );
1459
 
 
1460
 
#endif /* HAVE_FSREF */
1461
 
 
1462
 
  }
1463
 
 
1464
 
 
1465
 
  /*************************************************************************/
1466
 
  /*                                                                       */
1467
 
  /* <Function>                                                            */
1468
 
  /*    FT_New_Face_From_FSSpec                                            */
1469
 
  /*                                                                       */
1470
 
  /* <Description>                                                         */
1471
 
  /*    FT_New_Face_From_FSSpec is identical to FT_New_Face except it      */
1472
 
  /*    accepts an FSSpec instead of a path.                               */
1473
 
  /*                                                                       */
1474
 
  /* This function is deprecated because Carbon data types (FSSpec)        */
1475
 
  /* are not cross-platform, and thus not suitable for the freetype API.   */
1476
 
  FT_EXPORT_DEF( FT_Error )
1477
 
  FT_New_Face_From_FSSpec( FT_Library     library,
1478
 
                           const FSSpec*  spec,
1479
 
                           FT_Long        face_index,
1480
 
                           FT_Face*       aface )
1481
 
  {
1482
 
 
1483
 
#if HAVE_FSREF
1484
 
 
1485
 
    FSRef  ref;
1486
 
 
1487
 
 
1488
 
    if ( !spec || FSpMakeFSRef( spec, &ref ) != noErr )
1489
 
      return FT_Err_Invalid_Argument;
1490
 
    else
1491
 
      return FT_New_Face_From_FSRef( library, &ref, face_index, aface );
1492
 
 
1493
 
#elif HAVE_FSSPEC
1494
 
 
1495
 
    FT_Error      error;
1496
 
    FT_Open_Args  args;
1497
 
    OSErr         err;
1498
 
    UInt8         pathname[PATH_MAX];
1499
 
 
1500
 
 
1501
 
    if ( !spec )
1502
 
      return FT_Err_Invalid_Argument;
1503
 
 
1504
 
    err = FT_FSpMakePath( spec, pathname, sizeof ( pathname ) );
1505
 
    if ( err )
1506
 
      error = FT_Err_Cannot_Open_Resource;
1507
 
 
1508
 
    error = FT_New_Face_From_Resource( library, pathname, face_index, aface );
1509
 
    if ( error != 0 || *aface != NULL )
1510
 
      return error;
1511
 
 
1512
 
    /* fallback to datafork font */
1513
 
    args.flags    = FT_OPEN_PATHNAME;
1514
 
    args.pathname = (char*)pathname;
1515
 
    return FT_Open_Face( library, &args, face_index, aface );
1516
 
 
1517
 
#else
1518
 
 
1519
 
    FT_UNUSED( library );
1520
 
    FT_UNUSED( spec );
1521
 
    FT_UNUSED( face_index );
1522
 
    FT_UNUSED( aface );
1523
 
 
1524
 
    return FT_Err_Unimplemented_Feature;
1525
 
 
1526
 
#endif /* HAVE_FSREF, HAVE_FSSPEC */
1527
 
 
1528
 
  }
1529
 
 
1530
 
 
1531
 
/* END */