Blame src/base/ftmac.c

Packit Service d360f7
/***************************************************************************/
Packit Service d360f7
/*                                                                         */
Packit Service d360f7
/*  ftmac.c                                                                */
Packit Service d360f7
/*                                                                         */
Packit Service d360f7
/*    Mac FOND support.  Written by just@letterror.com.                    */
Packit Service d360f7
/*  Heavily modified by mpsuzuki, George Williams, and Sean McBride.       */
Packit Service d360f7
/*                                                                         */
Packit Service d360f7
/*  This file is for Mac OS X only; see builds/mac/ftoldmac.c for          */
Packit Service d360f7
/*  classic platforms built by MPW.                                        */
Packit Service d360f7
/*                                                                         */
Packit Service d360f7
/*  Copyright 1996-2017 by                                                 */
Packit Service d360f7
/*  Just van Rossum, David Turner, Robert Wilhelm, and Werner Lemberg.     */
Packit Service d360f7
/*                                                                         */
Packit Service d360f7
/*  This file is part of the FreeType project, and may only be used,       */
Packit Service d360f7
/*  modified, and distributed under the terms of the FreeType project      */
Packit Service d360f7
/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
Packit Service d360f7
/*  this file you indicate that you have read the license and              */
Packit Service d360f7
/*  understand and accept it fully.                                        */
Packit Service d360f7
/*                                                                         */
Packit Service d360f7
/***************************************************************************/
Packit Service d360f7
Packit Service d360f7
Packit Service d360f7
  /*
Packit Service d360f7
    Notes
Packit Service d360f7
Packit Service d360f7
    Mac suitcase files can (and often do!) contain multiple fonts.  To
Packit Service d360f7
    support this I use the face_index argument of FT_(Open|New)_Face()
Packit Service d360f7
    functions, and pretend the suitcase file is a collection.
Packit Service d360f7
Packit Service d360f7
    Warning: fbit and NFNT bitmap resources are not supported yet.  In old
Packit Service d360f7
    sfnt fonts, bitmap glyph data for each size is stored in each `NFNT'
Packit Service d360f7
    resources instead of the `bdat' table in the sfnt resource.  Therefore,
Packit Service d360f7
    face->num_fixed_sizes is set to 0, because bitmap data in `NFNT'
Packit Service d360f7
    resource is unavailable at present.
Packit Service d360f7
Packit Service d360f7
    The Mac FOND support works roughly like this:
Packit Service d360f7
Packit Service d360f7
    - Check whether the offered stream points to a Mac suitcase file.  This
Packit Service d360f7
      is done by checking the file type: it has to be 'FFIL' or 'tfil'.  The
Packit Service d360f7
      stream that gets passed to our init_face() routine is a stdio stream,
Packit Service d360f7
      which isn't usable for us, since the FOND resources live in the
Packit Service d360f7
      resource fork.  So we just grab the stream->pathname field.
Packit Service d360f7
Packit Service d360f7
    - Read the FOND resource into memory, then check whether there is a
Packit Service d360f7
      TrueType font and/or(!) a Type 1 font available.
Packit Service d360f7
Packit Service d360f7
    - If there is a Type 1 font available (as a separate `LWFN' file), read
Packit Service d360f7
      its data into memory, massage it slightly so it becomes PFB data, wrap
Packit Service d360f7
      it into a memory stream, load the Type 1 driver and delegate the rest
Packit Service d360f7
      of the work to it by calling FT_Open_Face().  (XXX TODO: after this
Packit Service d360f7
      has been done, the kerning data from the FOND resource should be
Packit Service d360f7
      appended to the face: On the Mac there are usually no AFM files
Packit Service d360f7
      available.  However, this is tricky since we need to map Mac char
Packit Service d360f7
      codes to ps glyph names to glyph ID's...)
Packit Service d360f7
Packit Service d360f7
    - If there is a TrueType font (an `sfnt' resource), read it into memory,
Packit Service d360f7
      wrap it into a memory stream, load the TrueType driver and delegate
Packit Service d360f7
      the rest of the work to it, by calling FT_Open_Face().
Packit Service d360f7
Packit Service d360f7
    - Some suitcase fonts (notably Onyx) might point the `LWFN' file to
Packit Service d360f7
      itself, even though it doesn't contains `POST' resources.  To handle
Packit Service d360f7
      this special case without opening the file an extra time, we just
Packit Service d360f7
      ignore errors from the `LWFN' and fallback to the `sfnt' if both are
Packit Service d360f7
      available.
Packit Service d360f7
  */
Packit Service d360f7
Packit Service d360f7
Packit Service d360f7
#include <ft2build.h>
Packit Service d360f7
#include FT_FREETYPE_H
Packit Service d360f7
#include FT_TRUETYPE_TAGS_H
Packit Service d360f7
#include FT_INTERNAL_STREAM_H
Packit Service d360f7
#include "ftbase.h"
Packit Service d360f7
Packit Service d360f7
Packit Service d360f7
#ifdef FT_MACINTOSH
Packit Service d360f7
Packit Service d360f7
  /* This is for Mac OS X.  Without redefinition, OS_INLINE */
Packit Service d360f7
  /* expands to `static inline' which doesn't survive the   */
Packit Service d360f7
  /* -ansi compilation flag of GCC.                         */
Packit Service d360f7
#if !HAVE_ANSI_OS_INLINE
Packit Service d360f7
#undef  OS_INLINE
Packit Service d360f7
#define OS_INLINE  static __inline__
Packit Service d360f7
#endif
Packit Service d360f7
Packit Service d360f7
  /* `configure' checks the availability of `ResourceIndex' strictly */
Packit Service d360f7
  /* and sets HAVE_TYPE_RESOURCE_INDEX 1 or 0 always.  If it is      */
Packit Service d360f7
  /* not set (e.g., a build without `configure'), the availability   */
Packit Service d360f7
  /* is guessed from the SDK version.                                */
Packit Service d360f7
#ifndef HAVE_TYPE_RESOURCE_INDEX
Packit Service d360f7
#if !defined( MAC_OS_X_VERSION_10_5 ) || \
Packit Service d360f7
    ( MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5 )
Packit Service d360f7
#define HAVE_TYPE_RESOURCE_INDEX 0
Packit Service d360f7
#else
Packit Service d360f7
#define HAVE_TYPE_RESOURCE_INDEX 1
Packit Service d360f7
#endif
Packit Service d360f7
#endif /* !HAVE_TYPE_RESOURCE_INDEX */
Packit Service d360f7
Packit Service d360f7
#if ( HAVE_TYPE_RESOURCE_INDEX == 0 )
Packit Service d360f7
  typedef short  ResourceIndex;
Packit Service d360f7
#endif
Packit Service d360f7
Packit Service d360f7
#include <CoreServices/CoreServices.h>
Packit Service d360f7
#include <ApplicationServices/ApplicationServices.h>
Packit Service d360f7
#include <sys/syslimits.h> /* PATH_MAX */
Packit Service d360f7
Packit Service d360f7
  /* Don't want warnings about our own use of deprecated functions. */
Packit Service d360f7
#define FT_DEPRECATED_ATTRIBUTE
Packit Service d360f7
Packit Service d360f7
#include FT_MAC_H
Packit Service d360f7
Packit Service d360f7
#ifndef kATSOptionFlagsUnRestrictedScope /* since Mac OS X 10.1 */
Packit Service d360f7
#define kATSOptionFlagsUnRestrictedScope kATSOptionFlagsDefault
Packit Service d360f7
#endif
Packit Service d360f7
Packit Service d360f7
Packit Service d360f7
  /* Set PREFER_LWFN to 1 if LWFN (Type 1) is preferred over
Packit Service d360f7
     TrueType in case *both* are available (this is not common,
Packit Service d360f7
     but it *is* possible). */
Packit Service d360f7
#ifndef PREFER_LWFN
Packit Service d360f7
#define PREFER_LWFN  1
Packit Service d360f7
#endif
Packit Service d360f7
Packit Service d360f7
Packit Service d360f7
  /* This function is deprecated because FSSpec is deprecated in Mac OS X  */
Packit Service d360f7
  FT_EXPORT_DEF( FT_Error )
Packit Service d360f7
  FT_GetFile_From_Mac_Name( const char*  fontName,
Packit Service d360f7
                            FSSpec*      pathSpec,
Packit Service d360f7
                            FT_Long*     face_index )
Packit Service d360f7
  {
Packit Service d360f7
    FT_UNUSED( fontName );
Packit Service d360f7
    FT_UNUSED( pathSpec );
Packit Service d360f7
    FT_UNUSED( face_index );
Packit Service d360f7
Packit Service d360f7
    return FT_THROW( Unimplemented_Feature );
Packit Service d360f7
  }
Packit Service d360f7
Packit Service d360f7
Packit Service d360f7
  /* Private function.                                         */
Packit Service d360f7
  /* The FSSpec type has been discouraged for a long time,     */
Packit Service d360f7
  /* unfortunately an FSRef replacement API for                */
Packit Service d360f7
  /* ATSFontGetFileSpecification() is only available in        */
Packit Service d360f7
  /* Mac OS X 10.5 and later.                                  */
Packit Service d360f7
  static OSStatus
Packit Service d360f7
  FT_ATSFontGetFileReference( ATSFontRef  ats_font_id,
Packit Service d360f7
                              FSRef*      ats_font_ref )
Packit Service d360f7
  {
Packit Service d360f7
#if defined( MAC_OS_X_VERSION_10_5 ) && \
Packit Service d360f7
    ( MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 )
Packit Service d360f7
Packit Service d360f7
    OSStatus  err;
Packit Service d360f7
Packit Service d360f7
    err = ATSFontGetFileReference( ats_font_id, ats_font_ref );
Packit Service d360f7
Packit Service d360f7
    return err;
Packit Service d360f7
#elif __LP64__ /* No 64bit Carbon API on legacy platforms */
Packit Service d360f7
    FT_UNUSED( ats_font_id );
Packit Service d360f7
    FT_UNUSED( ats_font_ref );
Packit Service d360f7
Packit Service d360f7
Packit Service d360f7
    return fnfErr;
Packit Service d360f7
#else /* 32bit Carbon API on legacy platforms */
Packit Service d360f7
    OSStatus  err;
Packit Service d360f7
    FSSpec    spec;
Packit Service d360f7
Packit Service d360f7
Packit Service d360f7
    err = ATSFontGetFileSpecification( ats_font_id, &spec );
Packit Service d360f7
    if ( noErr == err )
Packit Service d360f7
      err = FSpMakeFSRef( &spec, ats_font_ref );
Packit Service d360f7
Packit Service d360f7
    return err;
Packit Service d360f7
#endif
Packit Service d360f7
  }
Packit Service d360f7
Packit Service d360f7
Packit Service d360f7
  static FT_Error
Packit Service d360f7
  FT_GetFileRef_From_Mac_ATS_Name( const char*  fontName,
Packit Service d360f7
                                   FSRef*       ats_font_ref,
Packit Service d360f7
                                   FT_Long*     face_index )
Packit Service d360f7
  {
Packit Service d360f7
    CFStringRef  cf_fontName;
Packit Service d360f7
    ATSFontRef   ats_font_id;
Packit Service d360f7
Packit Service d360f7
Packit Service d360f7
    *face_index = 0;
Packit Service d360f7
Packit Service d360f7
    cf_fontName = CFStringCreateWithCString( NULL, fontName,
Packit Service d360f7
                                             kCFStringEncodingMacRoman );
Packit Service d360f7
    ats_font_id = ATSFontFindFromName( cf_fontName,
Packit Service d360f7
                                       kATSOptionFlagsUnRestrictedScope );
Packit Service d360f7
    CFRelease( cf_fontName );
Packit Service d360f7
Packit Service d360f7
    if ( ats_font_id == 0 || ats_font_id == 0xFFFFFFFFUL )
Packit Service d360f7
      return FT_THROW( Unknown_File_Format );
Packit Service d360f7
Packit Service d360f7
    if ( noErr != FT_ATSFontGetFileReference( ats_font_id, ats_font_ref ) )
Packit Service d360f7
      return FT_THROW( Unknown_File_Format );
Packit Service d360f7
Packit Service d360f7
    /* face_index calculation by searching preceding fontIDs */
Packit Service d360f7
    /* with same FSRef                                       */
Packit Service d360f7
    {
Packit Service d360f7
      ATSFontRef  id2 = ats_font_id - 1;
Packit Service d360f7
      FSRef       ref2;
Packit Service d360f7
Packit Service d360f7
Packit Service d360f7
      while ( id2 > 0 )
Packit Service d360f7
      {
Packit Service d360f7
        if ( noErr != FT_ATSFontGetFileReference( id2, &ref2 ) )
Packit Service d360f7
          break;
Packit Service d360f7
        if ( noErr != FSCompareFSRefs( ats_font_ref, &ref2 ) )
Packit Service d360f7
          break;
Packit Service d360f7
Packit Service d360f7
        id2 --;
Packit Service d360f7
      }
Packit Service d360f7
      *face_index = ats_font_id - ( id2 + 1 );
Packit Service d360f7
    }
Packit Service d360f7
Packit Service d360f7
    return FT_Err_Ok;
Packit Service d360f7
  }
Packit Service d360f7
Packit Service d360f7
Packit Service d360f7
  FT_EXPORT_DEF( FT_Error )
Packit Service d360f7
  FT_GetFilePath_From_Mac_ATS_Name( const char*  fontName,
Packit Service d360f7
                                    UInt8*       path,
Packit Service d360f7
                                    UInt32       maxPathSize,
Packit Service d360f7
                                    FT_Long*     face_index )
Packit Service d360f7
  {
Packit Service d360f7
    FSRef     ref;
Packit Service d360f7
    FT_Error  err;
Packit Service d360f7
Packit Service d360f7
Packit Service d360f7
    if ( !fontName || !face_index )
Packit Service d360f7
      return FT_THROW( Invalid_Argument);
Packit Service d360f7
Packit Service d360f7
    err = FT_GetFileRef_From_Mac_ATS_Name( fontName, &ref, face_index );
Packit Service d360f7
    if ( err )
Packit Service d360f7
      return err;
Packit Service d360f7
Packit Service d360f7
    if ( noErr != FSRefMakePath( &ref, path, maxPathSize ) )
Packit Service d360f7
      return FT_THROW( Unknown_File_Format );
Packit Service d360f7
Packit Service d360f7
    return FT_Err_Ok;
Packit Service d360f7
  }
Packit Service d360f7
Packit Service d360f7
Packit Service d360f7
  /* This function is deprecated because FSSpec is deprecated in Mac OS X  */
Packit Service d360f7
  FT_EXPORT_DEF( FT_Error )
Packit Service d360f7
  FT_GetFile_From_Mac_ATS_Name( const char*  fontName,
Packit Service d360f7
                                FSSpec*      pathSpec,
Packit Service d360f7
                                FT_Long*     face_index )
Packit Service d360f7
  {
Packit Service d360f7
#if ( __LP64__ ) || ( defined( MAC_OS_X_VERSION_10_5 ) && \
Packit Service d360f7
      ( MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 ) )
Packit Service d360f7
    FT_UNUSED( fontName );
Packit Service d360f7
    FT_UNUSED( pathSpec );
Packit Service d360f7
    FT_UNUSED( face_index );
Packit Service d360f7
Packit Service d360f7
    return FT_THROW( Unimplemented_Feature );
Packit Service d360f7
#else
Packit Service d360f7
    FSRef     ref;
Packit Service d360f7
    FT_Error  err;
Packit Service d360f7
Packit Service d360f7
Packit Service d360f7
    if ( !fontName || !face_index )
Packit Service d360f7
      return FT_THROW( Invalid_Argument );
Packit Service d360f7
Packit Service d360f7
    err = FT_GetFileRef_From_Mac_ATS_Name( fontName, &ref, face_index );
Packit Service d360f7
    if ( err )
Packit Service d360f7
      return err;
Packit Service d360f7
Packit Service d360f7
    if ( noErr != FSGetCatalogInfo( &ref, kFSCatInfoNone, NULL, NULL,
Packit Service d360f7
                                    pathSpec, NULL ) )
Packit Service d360f7
      return FT_THROW( Unknown_File_Format );
Packit Service d360f7
Packit Service d360f7
    return FT_Err_Ok;
Packit Service d360f7
#endif
Packit Service d360f7
  }
Packit Service d360f7
Packit Service d360f7
Packit Service d360f7
  static OSErr
Packit Service d360f7
  FT_FSPathMakeRes( const UInt8*    pathname,
Packit Service d360f7
                    ResFileRefNum*  res )
Packit Service d360f7
  {
Packit Service d360f7
    OSErr  err;
Packit Service d360f7
    FSRef  ref;
Packit Service d360f7
Packit Service d360f7
Packit Service d360f7
    if ( noErr != FSPathMakeRef( pathname, &ref, FALSE ) )
Packit Service d360f7
      return FT_THROW( Cannot_Open_Resource );
Packit Service d360f7
Packit Service d360f7
    /* at present, no support for dfont format */
Packit Service d360f7
    err = FSOpenResourceFile( &ref, 0, NULL, fsRdPerm, res );
Packit Service d360f7
    if ( noErr == err )
Packit Service d360f7
      return err;
Packit Service d360f7
Packit Service d360f7
    /* fallback to original resource-fork font */
Packit Service d360f7
    *res = FSOpenResFile( &ref, fsRdPerm );
Packit Service d360f7
    err  = ResError();
Packit Service d360f7
Packit Service d360f7
    return err;
Packit Service d360f7
  }
Packit Service d360f7
Packit Service d360f7
Packit Service d360f7
  /* Return the file type for given pathname */
Packit Service d360f7
  static OSType
Packit Service d360f7
  get_file_type_from_path( const UInt8*  pathname )
Packit Service d360f7
  {
Packit Service d360f7
    FSRef          ref;
Packit Service d360f7
    FSCatalogInfo  info;
Packit Service d360f7
Packit Service d360f7
Packit Service d360f7
    if ( noErr != FSPathMakeRef( pathname, &ref, FALSE ) )
Packit Service d360f7
      return ( OSType ) 0;
Packit Service d360f7
Packit Service d360f7
    if ( noErr != FSGetCatalogInfo( &ref, kFSCatInfoFinderInfo, &info,
Packit Service d360f7
                                    NULL, NULL, NULL ) )
Packit Service d360f7
      return ( OSType ) 0;
Packit Service d360f7
Packit Service d360f7
    return ((FInfo *)(info.finderInfo))->fdType;
Packit Service d360f7
  }
Packit Service d360f7
Packit Service d360f7
Packit Service d360f7
  /* Given a PostScript font name, create the Macintosh LWFN file name. */
Packit Service d360f7
  static void
Packit Service d360f7
  create_lwfn_name( char*   ps_name,
Packit Service d360f7
                    Str255  lwfn_file_name )
Packit Service d360f7
  {
Packit Service d360f7
    int       max = 5, count = 0;
Packit Service d360f7
    FT_Byte*  p = lwfn_file_name;
Packit Service d360f7
    FT_Byte*  q = (FT_Byte*)ps_name;
Packit Service d360f7
Packit Service d360f7
Packit Service d360f7
    lwfn_file_name[0] = 0;
Packit Service d360f7
Packit Service d360f7
    while ( *q )
Packit Service d360f7
    {
Packit Service d360f7
      if ( ft_isupper( *q ) )
Packit Service d360f7
      {
Packit Service d360f7
        if ( count )
Packit Service d360f7
          max = 3;
Packit Service d360f7
        count = 0;
Packit Service d360f7
      }
Packit Service d360f7
      if ( count < max && ( ft_isalnum( *q ) || *q == '_' ) )
Packit Service d360f7
      {
Packit Service d360f7
        *++p = *q;
Packit Service d360f7
        lwfn_file_name[0]++;
Packit Service d360f7
        count++;
Packit Service d360f7
      }
Packit Service d360f7
      q++;
Packit Service d360f7
    }
Packit Service d360f7
  }
Packit Service d360f7
Packit Service d360f7
Packit Service d360f7
  static short
Packit Service d360f7
  count_faces_sfnt( char*  fond_data )
Packit Service d360f7
  {
Packit Service d360f7
    /* The count is 1 greater than the value in the FOND.  */
Packit Service d360f7
    /* Isn't that cute? :-)                                */
Packit Service d360f7
Packit Service d360f7
    return EndianS16_BtoN( *( (short*)( fond_data +
Packit Service d360f7
                                        sizeof ( FamRec ) ) ) ) + 1;
Packit Service d360f7
  }
Packit Service d360f7
Packit Service d360f7
Packit Service d360f7
  static short
Packit Service d360f7
  count_faces_scalable( char*  fond_data )
Packit Service d360f7
  {
Packit Service d360f7
    AsscEntry*  assoc;
Packit Service d360f7
    short       i, face, face_all;
Packit Service d360f7
Packit Service d360f7
Packit Service d360f7
    face_all = EndianS16_BtoN( *( (short *)( fond_data +
Packit Service d360f7
                                             sizeof ( FamRec ) ) ) ) + 1;
Packit Service d360f7
    assoc    = (AsscEntry*)( fond_data + sizeof ( FamRec ) + 2 );
Packit Service d360f7
    face     = 0;
Packit Service d360f7
Packit Service d360f7
    for ( i = 0; i < face_all; i++ )
Packit Service d360f7
    {
Packit Service d360f7
      if ( 0 == EndianS16_BtoN( assoc[i].fontSize ) )
Packit Service d360f7
        face++;
Packit Service d360f7
    }
Packit Service d360f7
    return face;
Packit Service d360f7
  }
Packit Service d360f7
Packit Service d360f7
Packit Service d360f7
  /* Look inside the FOND data, answer whether there should be an SFNT
Packit Service d360f7
     resource, and answer the name of a possible LWFN Type 1 file.
Packit Service d360f7
Packit Service d360f7
     Thanks to Paul Miller (paulm@profoundeffects.com) for the fix
Packit Service d360f7
     to load a face OTHER than the first one in the FOND!
Packit Service d360f7
  */
Packit Service d360f7
Packit Service d360f7
Packit Service d360f7
  static void
Packit Service d360f7
  parse_fond( char*   fond_data,
Packit Service d360f7
              short*  have_sfnt,
Packit Service d360f7
              ResID*  sfnt_id,
Packit Service d360f7
              Str255  lwfn_file_name,
Packit Service d360f7
              short   face_index )
Packit Service d360f7
  {
Packit Service d360f7
    AsscEntry*  assoc;
Packit Service d360f7
    AsscEntry*  base_assoc;
Packit Service d360f7
    FamRec*     fond;
Packit Service d360f7
Packit Service d360f7
Packit Service d360f7
    *sfnt_id          = 0;
Packit Service d360f7
    *have_sfnt        = 0;
Packit Service d360f7
    lwfn_file_name[0] = 0;
Packit Service d360f7
Packit Service d360f7
    fond       = (FamRec*)fond_data;
Packit Service d360f7
    assoc      = (AsscEntry*)( fond_data + sizeof ( FamRec ) + 2 );
Packit Service d360f7
    base_assoc = assoc;
Packit Service d360f7
Packit Service d360f7
    /* the maximum faces in a FOND is 48, size of StyleTable.indexes[] */
Packit Service d360f7
    if ( 47 < face_index )
Packit Service d360f7
      return;
Packit Service d360f7
Packit Service d360f7
    /* Let's do a little range checking before we get too excited here */
Packit Service d360f7
    if ( face_index < count_faces_sfnt( fond_data ) )
Packit Service d360f7
    {
Packit Service d360f7
      assoc += face_index;        /* add on the face_index! */
Packit Service d360f7
Packit Service d360f7
      /* if the face at this index is not scalable,
Packit Service d360f7
         fall back to the first one (old behavior) */
Packit Service d360f7
      if ( EndianS16_BtoN( assoc->fontSize ) == 0 )
Packit Service d360f7
      {
Packit Service d360f7
        *have_sfnt = 1;
Packit Service d360f7
        *sfnt_id   = EndianS16_BtoN( assoc->fontID );
Packit Service d360f7
      }
Packit Service d360f7
      else if ( base_assoc->fontSize == 0 )
Packit Service d360f7
      {
Packit Service d360f7
        *have_sfnt = 1;
Packit Service d360f7
        *sfnt_id   = EndianS16_BtoN( base_assoc->fontID );
Packit Service d360f7
      }
Packit Service d360f7
    }
Packit Service d360f7
Packit Service d360f7
    if ( EndianS32_BtoN( fond->ffStylOff ) )
Packit Service d360f7
    {
Packit Service d360f7
      unsigned char*  p = (unsigned char*)fond_data;
Packit Service d360f7
      StyleTable*     style;
Packit Service d360f7
      unsigned short  string_count;
Packit Service d360f7
      char            ps_name[256];
Packit Service d360f7
      unsigned char*  names[64];
Packit Service d360f7
      int             i;
Packit Service d360f7
Packit Service d360f7
Packit Service d360f7
      p += EndianS32_BtoN( fond->ffStylOff );
Packit Service d360f7
      style = (StyleTable*)p;
Packit Service d360f7
      p += sizeof ( StyleTable );
Packit Service d360f7
      string_count = EndianS16_BtoN( *(short*)(p) );
Packit Service d360f7
      string_count = FT_MIN( 64, string_count );
Packit Service d360f7
      p += sizeof ( short );
Packit Service d360f7
Packit Service d360f7
      for ( i = 0; i < string_count; i++ )
Packit Service d360f7
      {
Packit Service d360f7
        names[i] = p;
Packit Service d360f7
        p       += names[i][0];
Packit Service d360f7
        p++;
Packit Service d360f7
      }
Packit Service d360f7
Packit Service d360f7
      {
Packit Service d360f7
        size_t  ps_name_len = (size_t)names[0][0];
Packit Service d360f7
Packit Service d360f7
Packit Service d360f7
        if ( ps_name_len != 0 )
Packit Service d360f7
        {
Packit Service d360f7
          ft_memcpy(ps_name, names[0] + 1, ps_name_len);
Packit Service d360f7
          ps_name[ps_name_len] = 0;
Packit Service d360f7
        }
Packit Service d360f7
        if ( style->indexes[face_index] > 1 &&
Packit Service d360f7
             style->indexes[face_index] <= string_count )
Packit Service d360f7
        {
Packit Service d360f7
          unsigned char*  suffixes = names[style->indexes[face_index] - 1];
Packit Service d360f7
Packit Service d360f7
Packit Service d360f7
          for ( i = 1; i <= suffixes[0]; i++ )
Packit Service d360f7
          {
Packit Service d360f7
            unsigned char*  s;
Packit Service d360f7
            size_t          j = suffixes[i] - 1;
Packit Service d360f7
Packit Service d360f7
Packit Service d360f7
            if ( j < string_count && ( s = names[j] ) != NULL )
Packit Service d360f7
            {
Packit Service d360f7
              size_t  s_len = (size_t)s[0];
Packit Service d360f7
Packit Service d360f7
Packit Service d360f7
              if ( s_len != 0 && ps_name_len + s_len < sizeof ( ps_name ) )
Packit Service d360f7
              {
Packit Service d360f7
                ft_memcpy( ps_name + ps_name_len, s + 1, s_len );
Packit Service d360f7
                ps_name_len += s_len;
Packit Service d360f7
                ps_name[ps_name_len] = 0;
Packit Service d360f7
              }
Packit Service d360f7
            }
Packit Service d360f7
          }
Packit Service d360f7
        }
Packit Service d360f7
      }
Packit Service d360f7
Packit Service d360f7
      create_lwfn_name( ps_name, lwfn_file_name );
Packit Service d360f7
    }
Packit Service d360f7
  }
Packit Service d360f7
Packit Service d360f7
Packit Service d360f7
  static  FT_Error
Packit Service d360f7
  lookup_lwfn_by_fond( const UInt8*      path_fond,
Packit Service d360f7
                       ConstStr255Param  base_lwfn,
Packit Service d360f7
                       UInt8*            path_lwfn,
Packit Service d360f7
                       size_t            path_size )
Packit Service d360f7
  {
Packit Service d360f7
    FSRef   ref, par_ref;
Packit Service d360f7
    size_t  dirname_len;
Packit Service d360f7
Packit Service d360f7
Packit Service d360f7
    /* Pathname for FSRef can be in various formats: HFS, HFS+, and POSIX. */
Packit Service d360f7
    /* We should not extract parent directory by string manipulation.      */
Packit Service d360f7
Packit Service d360f7
    if ( noErr != FSPathMakeRef( path_fond, &ref, FALSE ) )
Packit Service d360f7
      return FT_THROW( Invalid_Argument );
Packit Service d360f7
Packit Service d360f7
    if ( noErr != FSGetCatalogInfo( &ref, kFSCatInfoNone,
Packit Service d360f7
                                    NULL, NULL, NULL, &par_ref ) )
Packit Service d360f7
      return FT_THROW( Invalid_Argument );
Packit Service d360f7
Packit Service d360f7
    if ( noErr != FSRefMakePath( &par_ref, path_lwfn, path_size ) )
Packit Service d360f7
      return FT_THROW( Invalid_Argument );
Packit Service d360f7
Packit Service d360f7
    if ( ft_strlen( (char *)path_lwfn ) + 1 + base_lwfn[0] > path_size )
Packit Service d360f7
      return FT_THROW( Invalid_Argument );
Packit Service d360f7
Packit Service d360f7
    /* now we have absolute dirname in path_lwfn */
Packit Service d360f7
    ft_strcat( (char *)path_lwfn, "/" );
Packit Service d360f7
    dirname_len = ft_strlen( (char *)path_lwfn );
Packit Service d360f7
    ft_strcat( (char *)path_lwfn, (char *)base_lwfn + 1 );
Packit Service d360f7
    path_lwfn[dirname_len + base_lwfn[0]] = '\0';
Packit Service d360f7
Packit Service d360f7
    if ( noErr != FSPathMakeRef( path_lwfn, &ref, FALSE ) )
Packit Service d360f7
      return FT_THROW( Cannot_Open_Resource );
Packit Service d360f7
Packit Service d360f7
    if ( noErr != FSGetCatalogInfo( &ref, kFSCatInfoNone,
Packit Service d360f7
                                    NULL, NULL, NULL, NULL ) )
Packit Service d360f7
      return FT_THROW( Cannot_Open_Resource );
Packit Service d360f7
Packit Service d360f7
    return FT_Err_Ok;
Packit Service d360f7
  }
Packit Service d360f7
Packit Service d360f7
Packit Service d360f7
  static short
Packit Service d360f7
  count_faces( Handle        fond,
Packit Service d360f7
               const UInt8*  pathname )
Packit Service d360f7
  {
Packit Service d360f7
    ResID     sfnt_id;
Packit Service d360f7
    short     have_sfnt, have_lwfn;
Packit Service d360f7
    Str255    lwfn_file_name;
Packit Service d360f7
    UInt8     buff[PATH_MAX];
Packit Service d360f7
    FT_Error  err;
Packit Service d360f7
    short     num_faces;
Packit Service d360f7
Packit Service d360f7
Packit Service d360f7
    have_sfnt = have_lwfn = 0;
Packit Service d360f7
Packit Service d360f7
    parse_fond( *fond, &have_sfnt, &sfnt_id, lwfn_file_name, 0 );
Packit Service d360f7
Packit Service d360f7
    if ( lwfn_file_name[0] )
Packit Service d360f7
    {
Packit Service d360f7
      err = lookup_lwfn_by_fond( pathname, lwfn_file_name,
Packit Service d360f7
                                 buff, sizeof ( buff )  );
Packit Service d360f7
      if ( !err )
Packit Service d360f7
        have_lwfn = 1;
Packit Service d360f7
    }
Packit Service d360f7
Packit Service d360f7
    if ( have_lwfn && ( !have_sfnt || PREFER_LWFN ) )
Packit Service d360f7
      num_faces = 1;
Packit Service d360f7
    else
Packit Service d360f7
      num_faces = count_faces_scalable( *fond );
Packit Service d360f7
Packit Service d360f7
    return num_faces;
Packit Service d360f7
  }
Packit Service d360f7
Packit Service d360f7
Packit Service d360f7
  /* Read Type 1 data from the POST resources inside the LWFN file,
Packit Service d360f7
     return a PFB buffer.  This is somewhat convoluted because the FT2
Packit Service d360f7
     PFB parser wants the ASCII header as one chunk, and the LWFN
Packit Service d360f7
     chunks are often not organized that way, so we glue chunks
Packit Service d360f7
     of the same type together. */
Packit Service d360f7
  static FT_Error
Packit Service d360f7
  read_lwfn( FT_Memory      memory,
Packit Service d360f7
             ResFileRefNum  res,
Packit Service d360f7
             FT_Byte**      pfb_data,
Packit Service d360f7
             FT_ULong*      size )
Packit Service d360f7
  {
Packit Service d360f7
    FT_Error       error = FT_Err_Ok;
Packit Service d360f7
    ResID          res_id;
Packit Service d360f7
    unsigned char  *buffer, *p, *size_p = NULL;
Packit Service d360f7
    FT_ULong       total_size = 0;
Packit Service d360f7
    FT_ULong       old_total_size = 0;
Packit Service d360f7
    FT_ULong       post_size, pfb_chunk_size;
Packit Service d360f7
    Handle         post_data;
Packit Service d360f7
    char           code, last_code;
Packit Service d360f7
Packit Service d360f7
Packit Service d360f7
    UseResFile( res );
Packit Service d360f7
Packit Service d360f7
    /* First pass: load all POST resources, and determine the size of */
Packit Service d360f7
    /* the output buffer.                                             */
Packit Service d360f7
    res_id    = 501;
Packit Service d360f7
    last_code = -1;
Packit Service d360f7
Packit Service d360f7
    for (;;)
Packit Service d360f7
    {
Packit Service d360f7
      post_data = Get1Resource( TTAG_POST, res_id++ );
Packit Service d360f7
      if ( !post_data )
Packit Service d360f7
        break;  /* we are done */
Packit Service d360f7
Packit Service d360f7
      code = (*post_data)[0];
Packit Service d360f7
Packit Service d360f7
      if ( code != last_code )
Packit Service d360f7
      {
Packit Service d360f7
        if ( code == 5 )
Packit Service d360f7
          total_size += 2; /* just the end code */
Packit Service d360f7
        else
Packit Service d360f7
          total_size += 6; /* code + 4 bytes chunk length */
Packit Service d360f7
      }
Packit Service d360f7
Packit Service d360f7
      total_size += (FT_ULong)GetHandleSize( post_data ) - 2;
Packit Service d360f7
      last_code = code;
Packit Service d360f7
Packit Service d360f7
      /* detect resource fork overflow */
Packit Service d360f7
      if ( FT_MAC_RFORK_MAX_LEN < total_size )
Packit Service d360f7
      {
Packit Service d360f7
        error = FT_THROW( Array_Too_Large );
Packit Service d360f7
        goto Error;
Packit Service d360f7
      }
Packit Service d360f7
Packit Service d360f7
      old_total_size = total_size;
Packit Service d360f7
    }
Packit Service d360f7
Packit Service d360f7
    if ( FT_ALLOC( buffer, (FT_Long)total_size ) )
Packit Service d360f7
      goto Error;
Packit Service d360f7
Packit Service d360f7
    /* Second pass: append all POST data to the buffer, add PFB fields. */
Packit Service d360f7
    /* Glue all consecutive chunks of the same type together.           */
Packit Service d360f7
    p              = buffer;
Packit Service d360f7
    res_id         = 501;
Packit Service d360f7
    last_code      = -1;
Packit Service d360f7
    pfb_chunk_size = 0;
Packit Service d360f7
Packit Service d360f7
    for (;;)
Packit Service d360f7
    {
Packit Service d360f7
      post_data = Get1Resource( TTAG_POST, res_id++ );
Packit Service d360f7
      if ( !post_data )
Packit Service d360f7
        break;  /* we are done */
Packit Service d360f7
Packit Service d360f7
      post_size = (FT_ULong)GetHandleSize( post_data ) - 2;
Packit Service d360f7
      code = (*post_data)[0];
Packit Service d360f7
Packit Service d360f7
      if ( code != last_code )
Packit Service d360f7
      {
Packit Service d360f7
        if ( last_code != -1 )
Packit Service d360f7
        {
Packit Service d360f7
          /* we are done adding a chunk, fill in the size field */
Packit Service d360f7
          if ( size_p )
Packit Service d360f7
          {
Packit Service d360f7
            *size_p++ = (FT_Byte)(   pfb_chunk_size         & 0xFF );
Packit Service d360f7
            *size_p++ = (FT_Byte)( ( pfb_chunk_size >> 8  ) & 0xFF );
Packit Service d360f7
            *size_p++ = (FT_Byte)( ( pfb_chunk_size >> 16 ) & 0xFF );
Packit Service d360f7
            *size_p++ = (FT_Byte)( ( pfb_chunk_size >> 24 ) & 0xFF );
Packit Service d360f7
          }
Packit Service d360f7
          pfb_chunk_size = 0;
Packit Service d360f7
        }
Packit Service d360f7
Packit Service d360f7
        *p++ = 0x80;
Packit Service d360f7
        if ( code == 5 )
Packit Service d360f7
          *p++ = 0x03;  /* the end */
Packit Service d360f7
        else if ( code == 2 )
Packit Service d360f7
          *p++ = 0x02;  /* binary segment */
Packit Service d360f7
        else
Packit Service d360f7
          *p++ = 0x01;  /* ASCII segment */
Packit Service d360f7
Packit Service d360f7
        if ( code != 5 )
Packit Service d360f7
        {
Packit Service d360f7
          size_p = p;   /* save for later */
Packit Service d360f7
          p += 4;       /* make space for size field */
Packit Service d360f7
        }
Packit Service d360f7
      }
Packit Service d360f7
Packit Service d360f7
      ft_memcpy( p, *post_data + 2, post_size );
Packit Service d360f7
      pfb_chunk_size += post_size;
Packit Service d360f7
      p += post_size;
Packit Service d360f7
      last_code = code;
Packit Service d360f7
    }
Packit Service d360f7
Packit Service d360f7
    *pfb_data = buffer;
Packit Service d360f7
    *size = total_size;
Packit Service d360f7
Packit Service d360f7
  Error:
Packit Service d360f7
    CloseResFile( res );
Packit Service d360f7
    return error;
Packit Service d360f7
  }
Packit Service d360f7
Packit Service d360f7
Packit Service d360f7
  /* Create a new FT_Face from a file path to an LWFN file. */
Packit Service d360f7
  static FT_Error
Packit Service d360f7
  FT_New_Face_From_LWFN( FT_Library    library,
Packit Service d360f7
                         const UInt8*  pathname,
Packit Service d360f7
                         FT_Long       face_index,
Packit Service d360f7
                         FT_Face*      aface )
Packit Service d360f7
  {
Packit Service d360f7
    FT_Byte*       pfb_data;
Packit Service d360f7
    FT_ULong       pfb_size;
Packit Service d360f7
    FT_Error       error;
Packit Service d360f7
    ResFileRefNum  res;
Packit Service d360f7
Packit Service d360f7
Packit Service d360f7
    if ( noErr != FT_FSPathMakeRes( pathname, &res ) )
Packit Service d360f7
      return FT_THROW( Cannot_Open_Resource );
Packit Service d360f7
Packit Service d360f7
    pfb_data = NULL;
Packit Service d360f7
    pfb_size = 0;
Packit Service d360f7
    error = read_lwfn( library->memory, res, &pfb_data, &pfb_size );
Packit Service d360f7
    CloseResFile( res ); /* PFB is already loaded, useless anymore */
Packit Service d360f7
    if ( error )
Packit Service d360f7
      return error;
Packit Service d360f7
Packit Service d360f7
    return open_face_from_buffer( library,
Packit Service d360f7
                                  pfb_data,
Packit Service d360f7
                                  pfb_size,
Packit Service d360f7
                                  face_index,
Packit Service d360f7
                                  "type1",
Packit Service d360f7
                                  aface );
Packit Service d360f7
  }
Packit Service d360f7
Packit Service d360f7
Packit Service d360f7
  /* Create a new FT_Face from an SFNT resource, specified by res ID. */
Packit Service d360f7
  static FT_Error
Packit Service d360f7
  FT_New_Face_From_SFNT( FT_Library  library,
Packit Service d360f7
                         ResID       sfnt_id,
Packit Service d360f7
                         FT_Long     face_index,
Packit Service d360f7
                         FT_Face*    aface )
Packit Service d360f7
  {
Packit Service d360f7
    Handle     sfnt = NULL;
Packit Service d360f7
    FT_Byte*   sfnt_data;
Packit Service d360f7
    size_t     sfnt_size;
Packit Service d360f7
    FT_Error   error  = FT_Err_Ok;
Packit Service d360f7
    FT_Memory  memory = library->memory;
Packit Service d360f7
    int        is_cff, is_sfnt_ps;
Packit Service d360f7
Packit Service d360f7
Packit Service d360f7
    sfnt = GetResource( TTAG_sfnt, sfnt_id );
Packit Service d360f7
    if ( !sfnt )
Packit Service d360f7
      return FT_THROW( Invalid_Handle );
Packit Service d360f7
Packit Service d360f7
    sfnt_size = (FT_ULong)GetHandleSize( sfnt );
Packit Service d360f7
Packit Service d360f7
    /* detect resource fork overflow */
Packit Service d360f7
    if ( FT_MAC_RFORK_MAX_LEN < sfnt_size )
Packit Service d360f7
      return FT_THROW( Array_Too_Large );
Packit Service d360f7
Packit Service d360f7
    if ( FT_ALLOC( sfnt_data, (FT_Long)sfnt_size ) )
Packit Service d360f7
    {
Packit Service d360f7
      ReleaseResource( sfnt );
Packit Service d360f7
      return error;
Packit Service d360f7
    }
Packit Service d360f7
Packit Service d360f7
    ft_memcpy( sfnt_data, *sfnt, sfnt_size );
Packit Service d360f7
    ReleaseResource( sfnt );
Packit Service d360f7
Packit Service d360f7
    is_cff     = sfnt_size > 4 && !ft_memcmp( sfnt_data, "OTTO", 4 );
Packit Service d360f7
    is_sfnt_ps = sfnt_size > 4 && !ft_memcmp( sfnt_data, "typ1", 4 );
Packit Service d360f7
Packit Service d360f7
    if ( is_sfnt_ps )
Packit Service d360f7
    {
Packit Service d360f7
      FT_Stream  stream;
Packit Service d360f7
Packit Service d360f7
Packit Service d360f7
      if ( FT_NEW( stream ) )
Packit Service d360f7
        goto Try_OpenType;
Packit Service d360f7
Packit Service d360f7
      FT_Stream_OpenMemory( stream, sfnt_data, sfnt_size );
Packit Service d360f7
      if ( !open_face_PS_from_sfnt_stream( library,
Packit Service d360f7
                                           stream,
Packit Service d360f7
                                           face_index,
Packit Service d360f7
                                           0, NULL,
Packit Service d360f7
                                           aface ) )
Packit Service d360f7
      {
Packit Service d360f7
        FT_Stream_Close( stream );
Packit Service d360f7
        FT_FREE( stream );
Packit Service d360f7
        FT_FREE( sfnt_data );
Packit Service d360f7
        goto Exit;
Packit Service d360f7
      }
Packit Service d360f7
Packit Service d360f7
      FT_FREE( stream );
Packit Service d360f7
    }
Packit Service d360f7
  Try_OpenType:
Packit Service d360f7
    error = open_face_from_buffer( library,
Packit Service d360f7
                                   sfnt_data,
Packit Service d360f7
                                   sfnt_size,
Packit Service d360f7
                                   face_index,
Packit Service d360f7
                                   is_cff ? "cff" : "truetype",
Packit Service d360f7
                                   aface );
Packit Service d360f7
  Exit:
Packit Service d360f7
    return error;
Packit Service d360f7
  }
Packit Service d360f7
Packit Service d360f7
Packit Service d360f7
  /* Create a new FT_Face from a file path to a suitcase file. */
Packit Service d360f7
  static FT_Error
Packit Service d360f7
  FT_New_Face_From_Suitcase( FT_Library    library,
Packit Service d360f7
                             const UInt8*  pathname,
Packit Service d360f7
                             FT_Long       face_index,
Packit Service d360f7
                             FT_Face*      aface )
Packit Service d360f7
  {
Packit Service d360f7
    FT_Error       error = FT_ERR( Cannot_Open_Resource );
Packit Service d360f7
    ResFileRefNum  res_ref;
Packit Service d360f7
    ResourceIndex  res_index;
Packit Service d360f7
    Handle         fond;
Packit Service d360f7
    short          num_faces_in_res;
Packit Service d360f7
Packit Service d360f7
Packit Service d360f7
    if ( noErr != FT_FSPathMakeRes( pathname, &res_ref ) )
Packit Service d360f7
      return FT_THROW( Cannot_Open_Resource );
Packit Service d360f7
Packit Service d360f7
    UseResFile( res_ref );
Packit Service d360f7
    if ( ResError() )
Packit Service d360f7
      return FT_THROW( Cannot_Open_Resource );
Packit Service d360f7
Packit Service d360f7
    num_faces_in_res = 0;
Packit Service d360f7
    for ( res_index = 1; ; res_index++ )
Packit Service d360f7
    {
Packit Service d360f7
      short  num_faces_in_fond;
Packit Service d360f7
Packit Service d360f7
Packit Service d360f7
      fond = Get1IndResource( TTAG_FOND, res_index );
Packit Service d360f7
      if ( ResError() )
Packit Service d360f7
        break;
Packit Service d360f7
Packit Service d360f7
      num_faces_in_fond  = count_faces( fond, pathname );
Packit Service d360f7
      num_faces_in_res  += num_faces_in_fond;
Packit Service d360f7
Packit Service d360f7
      if ( 0 <= face_index && face_index < num_faces_in_fond && error )
Packit Service d360f7
        error = FT_New_Face_From_FOND( library, fond, face_index, aface );
Packit Service d360f7
Packit Service d360f7
      face_index -= num_faces_in_fond;
Packit Service d360f7
    }
Packit Service d360f7
Packit Service d360f7
    CloseResFile( res_ref );
Packit Service d360f7
    if ( !error && aface && *aface )
Packit Service d360f7
      (*aface)->num_faces = num_faces_in_res;
Packit Service d360f7
    return error;
Packit Service d360f7
  }
Packit Service d360f7
Packit Service d360f7
Packit Service d360f7
  /* documentation is in ftmac.h */
Packit Service d360f7
Packit Service d360f7
  FT_EXPORT_DEF( FT_Error )
Packit Service d360f7
  FT_New_Face_From_FOND( FT_Library  library,
Packit Service d360f7
                         Handle      fond,
Packit Service d360f7
                         FT_Long     face_index,
Packit Service d360f7
                         FT_Face*    aface )
Packit Service d360f7
  {
Packit Service d360f7
    short     have_sfnt, have_lwfn = 0;
Packit Service d360f7
    ResID     sfnt_id, fond_id;
Packit Service d360f7
    OSType    fond_type;
Packit Service d360f7
    Str255    fond_name;
Packit Service d360f7
    Str255    lwfn_file_name;
Packit Service d360f7
    UInt8     path_lwfn[PATH_MAX];
Packit Service d360f7
    OSErr     err;
Packit Service d360f7
    FT_Error  error = FT_Err_Ok;
Packit Service d360f7
Packit Service d360f7
Packit Service d360f7
    /* check of `library' and `aface' delayed to `FT_New_Face_From_XXX' */
Packit Service d360f7
Packit Service d360f7
    GetResInfo( fond, &fond_id, &fond_type, fond_name );
Packit Service d360f7
    if ( ResError() != noErr || fond_type != TTAG_FOND )
Packit Service d360f7
      return FT_THROW( Invalid_File_Format );
Packit Service d360f7
Packit Service d360f7
    parse_fond( *fond, &have_sfnt, &sfnt_id, lwfn_file_name, face_index );
Packit Service d360f7
Packit Service d360f7
    if ( lwfn_file_name[0] )
Packit Service d360f7
    {
Packit Service d360f7
      ResFileRefNum  res;
Packit Service d360f7
Packit Service d360f7
Packit Service d360f7
      res = HomeResFile( fond );
Packit Service d360f7
      if ( noErr != ResError() )
Packit Service d360f7
        goto found_no_lwfn_file;
Packit Service d360f7
Packit Service d360f7
      {
Packit Service d360f7
        UInt8  path_fond[PATH_MAX];
Packit Service d360f7
        FSRef  ref;
Packit Service d360f7
Packit Service d360f7
Packit Service d360f7
        err = FSGetForkCBInfo( res, kFSInvalidVolumeRefNum,
Packit Service d360f7
                               NULL, NULL, NULL, &ref, NULL );
Packit Service d360f7
        if ( noErr != err )
Packit Service d360f7
          goto found_no_lwfn_file;
Packit Service d360f7
Packit Service d360f7
        err = FSRefMakePath( &ref, path_fond, sizeof ( path_fond ) );
Packit Service d360f7
        if ( noErr != err )
Packit Service d360f7
          goto found_no_lwfn_file;
Packit Service d360f7
Packit Service d360f7
        error = lookup_lwfn_by_fond( path_fond, lwfn_file_name,
Packit Service d360f7
                                     path_lwfn, sizeof ( path_lwfn ) );
Packit Service d360f7
        if ( !error )
Packit Service d360f7
          have_lwfn = 1;
Packit Service d360f7
      }
Packit Service d360f7
    }
Packit Service d360f7
Packit Service d360f7
    if ( have_lwfn && ( !have_sfnt || PREFER_LWFN ) )
Packit Service d360f7
      error = FT_New_Face_From_LWFN( library,
Packit Service d360f7
                                     path_lwfn,
Packit Service d360f7
                                     face_index,
Packit Service d360f7
                                     aface );
Packit Service d360f7
    else
Packit Service d360f7
      error = FT_THROW( Unknown_File_Format );
Packit Service d360f7
Packit Service d360f7
  found_no_lwfn_file:
Packit Service d360f7
    if ( have_sfnt && error )
Packit Service d360f7
      error = FT_New_Face_From_SFNT( library,
Packit Service d360f7
                                     sfnt_id,
Packit Service d360f7
                                     face_index,
Packit Service d360f7
                                     aface );
Packit Service d360f7
Packit Service d360f7
    return error;
Packit Service d360f7
  }
Packit Service d360f7
Packit Service d360f7
Packit Service d360f7
  /* Common function to load a new FT_Face from a resource file. */
Packit Service d360f7
  static FT_Error
Packit Service d360f7
  FT_New_Face_From_Resource( FT_Library    library,
Packit Service d360f7
                             const UInt8*  pathname,
Packit Service d360f7
                             FT_Long       face_index,
Packit Service d360f7
                             FT_Face*      aface )
Packit Service d360f7
  {
Packit Service d360f7
    OSType    file_type;
Packit Service d360f7
    FT_Error  error;
Packit Service d360f7
Packit Service d360f7
Packit Service d360f7
    /* LWFN is a (very) specific file format, check for it explicitly */
Packit Service d360f7
    file_type = get_file_type_from_path( pathname );
Packit Service d360f7
    if ( file_type == TTAG_LWFN )
Packit Service d360f7
      return FT_New_Face_From_LWFN( library, pathname, face_index, aface );
Packit Service d360f7
Packit Service d360f7
    /* Otherwise the file type doesn't matter (there are more than  */
Packit Service d360f7
    /* `FFIL' and `tfil').  Just try opening it as a font suitcase; */
Packit Service d360f7
    /* if it works, fine.                                           */
Packit Service d360f7
Packit Service d360f7
    error = FT_New_Face_From_Suitcase( library, pathname, face_index, aface );
Packit Service d360f7
    if ( error )
Packit Service d360f7
    {
Packit Service d360f7
      /* let it fall through to normal loader (.ttf, .otf, etc.); */
Packit Service d360f7
      /* we signal this by returning no error and no FT_Face      */
Packit Service d360f7
      *aface = NULL;
Packit Service d360f7
    }
Packit Service d360f7
Packit Service d360f7
    return FT_Err_Ok;
Packit Service d360f7
  }
Packit Service d360f7
Packit Service d360f7
Packit Service d360f7
  /*************************************************************************/
Packit Service d360f7
  /*                                                                       */
Packit Service d360f7
  /* <Function>                                                            */
Packit Service d360f7
  /*    FT_New_Face                                                        */
Packit Service d360f7
  /*                                                                       */
Packit Service d360f7
  /* <Description>                                                         */
Packit Service d360f7
  /*    This is the Mac-specific implementation of FT_New_Face.  In        */
Packit Service d360f7
  /*    addition to the standard FT_New_Face() functionality, it also      */
Packit Service d360f7
  /*    accepts pathnames to Mac suitcase files.  For further              */
Packit Service d360f7
  /*    documentation see the original FT_New_Face() in freetype.h.        */
Packit Service d360f7
  /*                                                                       */
Packit Service d360f7
  FT_EXPORT_DEF( FT_Error )
Packit Service d360f7
  FT_New_Face( FT_Library   library,
Packit Service d360f7
               const char*  pathname,
Packit Service d360f7
               FT_Long      face_index,
Packit Service d360f7
               FT_Face*     aface )
Packit Service d360f7
  {
Packit Service d360f7
    FT_Open_Args  args;
Packit Service d360f7
    FT_Error      error;
Packit Service d360f7
Packit Service d360f7
Packit Service d360f7
    /* test for valid `library' and `aface' delayed to FT_Open_Face() */
Packit Service d360f7
    if ( !pathname )
Packit Service d360f7
      return FT_THROW( Invalid_Argument );
Packit Service d360f7
Packit Service d360f7
    *aface = NULL;
Packit Service d360f7
Packit Service d360f7
    /* try resourcefork based font: LWFN, FFIL */
Packit Service d360f7
    error = FT_New_Face_From_Resource( library, (UInt8 *)pathname,
Packit Service d360f7
                                       face_index, aface );
Packit Service d360f7
    if ( error || *aface )
Packit Service d360f7
      return error;
Packit Service d360f7
Packit Service d360f7
    /* let it fall through to normal loader (.ttf, .otf, etc.) */
Packit Service d360f7
    args.flags    = FT_OPEN_PATHNAME;
Packit Service d360f7
    args.pathname = (char*)pathname;
Packit Service d360f7
Packit Service d360f7
    return FT_Open_Face( library, &args, face_index, aface );
Packit Service d360f7
  }
Packit Service d360f7
Packit Service d360f7
Packit Service d360f7
  /*************************************************************************/
Packit Service d360f7
  /*                                                                       */
Packit Service d360f7
  /* <Function>                                                            */
Packit Service d360f7
  /*    FT_New_Face_From_FSRef                                             */
Packit Service d360f7
  /*                                                                       */
Packit Service d360f7
  /* <Description>                                                         */
Packit Service d360f7
  /*    FT_New_Face_From_FSRef is identical to FT_New_Face except it       */
Packit Service d360f7
  /*    accepts an FSRef instead of a path.                                */
Packit Service d360f7
  /*                                                                       */
Packit Service d360f7
  /* This function is deprecated because Carbon data types (FSRef)         */
Packit Service d360f7
  /* are not cross-platform, and thus not suitable for the freetype API.   */
Packit Service d360f7
  FT_EXPORT_DEF( FT_Error )
Packit Service d360f7
  FT_New_Face_From_FSRef( FT_Library    library,
Packit Service d360f7
                          const FSRef*  ref,
Packit Service d360f7
                          FT_Long       face_index,
Packit Service d360f7
                          FT_Face*      aface )
Packit Service d360f7
  {
Packit Service d360f7
    FT_Error      error;
Packit Service d360f7
    FT_Open_Args  args;
Packit Service d360f7
Packit Service d360f7
    OSErr  err;
Packit Service d360f7
    UInt8  pathname[PATH_MAX];
Packit Service d360f7
Packit Service d360f7
Packit Service d360f7
    /* check of `library' and `aface' delayed to */
Packit Service d360f7
    /* `FT_New_Face_From_Resource'               */
Packit Service d360f7
Packit Service d360f7
    if ( !ref )
Packit Service d360f7
      return FT_THROW( Invalid_Argument );
Packit Service d360f7
Packit Service d360f7
    err = FSRefMakePath( ref, pathname, sizeof ( pathname ) );
Packit Service d360f7
    if ( err )
Packit Service d360f7
      error = FT_THROW( Cannot_Open_Resource );
Packit Service d360f7
Packit Service d360f7
    error = FT_New_Face_From_Resource( library, pathname, face_index, aface );
Packit Service d360f7
    if ( error || *aface )
Packit Service d360f7
      return error;
Packit Service d360f7
Packit Service d360f7
    /* fallback to datafork font */
Packit Service d360f7
    args.flags    = FT_OPEN_PATHNAME;
Packit Service d360f7
    args.pathname = (char*)pathname;
Packit Service d360f7
    return FT_Open_Face( library, &args, face_index, aface );
Packit Service d360f7
  }
Packit Service d360f7
Packit Service d360f7
Packit Service d360f7
  /*************************************************************************/
Packit Service d360f7
  /*                                                                       */
Packit Service d360f7
  /* <Function>                                                            */
Packit Service d360f7
  /*    FT_New_Face_From_FSSpec                                            */
Packit Service d360f7
  /*                                                                       */
Packit Service d360f7
  /* <Description>                                                         */
Packit Service d360f7
  /*    FT_New_Face_From_FSSpec is identical to FT_New_Face except it      */
Packit Service d360f7
  /*    accepts an FSSpec instead of a path.                               */
Packit Service d360f7
  /*                                                                       */
Packit Service d360f7
  /* This function is deprecated because FSSpec is deprecated in Mac OS X  */
Packit Service d360f7
  FT_EXPORT_DEF( FT_Error )
Packit Service d360f7
  FT_New_Face_From_FSSpec( FT_Library     library,
Packit Service d360f7
                           const FSSpec*  spec,
Packit Service d360f7
                           FT_Long        face_index,
Packit Service d360f7
                           FT_Face*       aface )
Packit Service d360f7
  {
Packit Service d360f7
#if ( __LP64__ ) || ( defined( MAC_OS_X_VERSION_10_5 ) && \
Packit Service d360f7
      ( MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 ) )
Packit Service d360f7
    FT_UNUSED( library );
Packit Service d360f7
    FT_UNUSED( spec );
Packit Service d360f7
    FT_UNUSED( face_index );
Packit Service d360f7
    FT_UNUSED( aface );
Packit Service d360f7
Packit Service d360f7
    return FT_THROW( Unimplemented_Feature );
Packit Service d360f7
#else
Packit Service d360f7
    FSRef  ref;
Packit Service d360f7
Packit Service d360f7
Packit Service d360f7
    /* check of `library' and `aface' delayed to `FT_New_Face_From_FSRef' */
Packit Service d360f7
Packit Service d360f7
    if ( !spec || FSpMakeFSRef( spec, &ref ) != noErr )
Packit Service d360f7
      return FT_THROW( Invalid_Argument );
Packit Service d360f7
    else
Packit Service d360f7
      return FT_New_Face_From_FSRef( library, &ref, face_index, aface );
Packit Service d360f7
#endif
Packit Service d360f7
  }
Packit Service d360f7
Packit Service d360f7
#else /* !FT_MACINTOSH */
Packit Service d360f7
Packit Service d360f7
  /* ANSI C doesn't like empty source files */
Packit Service d360f7
  typedef int  _ft_mac_dummy;
Packit Service d360f7
Packit Service d360f7
#endif /* !FT_MACINTOSH */
Packit Service d360f7
Packit Service d360f7
Packit Service d360f7
/* END */