PageRenderTime 121ms CodeModel.GetById 36ms app.highlight 76ms RepoModel.GetById 1ms app.codeStats 0ms

/modules/freetype2/builds/mac/ftmac.c

http://github.com/zpao/v8monkey
C | 1531 lines | 1012 code | 347 blank | 172 comment | 240 complexity | 93e3c0c7b14585a8092b86ee3f2d1588 MD5 | raw file
   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 )
 164typedef 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 */