ftmac.c

Go to the documentation of this file.
00001 /***************************************************************************/
00002 /*                                                                         */
00003 /*  ftmac.c                                                                */
00004 /*                                                                         */
00005 /*    Mac FOND support.  Written by just@letterror.com.                    */
00006 /*  Heavily Fixed by mpsuzuki, George Williams and Sean McBride            */
00007 /*                                                                         */
00008 /*  Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 by       */
00009 /*  Just van Rossum, David Turner, Robert Wilhelm, and Werner Lemberg.     */
00010 /*                                                                         */
00011 /*  This file is part of the FreeType project, and may only be used,       */
00012 /*  modified, and distributed under the terms of the FreeType project      */
00013 /*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
00014 /*  this file you indicate that you have read the license and              */
00015 /*  understand and accept it fully.                                        */
00016 /*                                                                         */
00017 /***************************************************************************/
00018 
00019 
00020   /*
00021     Notes
00022 
00023     Mac suitcase files can (and often do!) contain multiple fonts.  To
00024     support this I use the face_index argument of FT_(Open|New)_Face()
00025     functions, and pretend the suitcase file is a collection.
00026 
00027     Warning: fbit and NFNT bitmap resources are not supported yet.  In old
00028     sfnt fonts, bitmap glyph data for each size is stored in each `NFNT'
00029     resources instead of the `bdat' table in the sfnt resource.  Therefore,
00030     face->num_fixed_sizes is set to 0, because bitmap data in `NFNT'
00031     resource is unavailable at present.
00032 
00033     The Mac FOND support works roughly like this:
00034 
00035     - Check whether the offered stream points to a Mac suitcase file.  This
00036       is done by checking the file type: it has to be 'FFIL' or 'tfil'.  The
00037       stream that gets passed to our init_face() routine is a stdio stream,
00038       which isn't usable for us, since the FOND resources live in the
00039       resource fork.  So we just grab the stream->pathname field.
00040 
00041     - Read the FOND resource into memory, then check whether there is a
00042       TrueType font and/or(!) a Type 1 font available.
00043 
00044     - If there is a Type 1 font available (as a separate `LWFN' file), read
00045       its data into memory, massage it slightly so it becomes PFB data, wrap
00046       it into a memory stream, load the Type 1 driver and delegate the rest
00047       of the work to it by calling FT_Open_Face().  (XXX TODO: after this
00048       has been done, the kerning data from the FOND resource should be
00049       appended to the face: On the Mac there are usually no AFM files
00050       available.  However, this is tricky since we need to map Mac char
00051       codes to ps glyph names to glyph ID's...)
00052 
00053     - If there is a TrueType font (an `sfnt' resource), read it into memory,
00054       wrap it into a memory stream, load the TrueType driver and delegate
00055       the rest of the work to it, by calling FT_Open_Face().
00056 
00057     - Some suitcase fonts (notably Onyx) might point the `LWFN' file to
00058       itself, even though it doesn't contains `POST' resources.  To handle
00059       this special case without opening the file an extra time, we just
00060       ignore errors from the `LWFN' and fallback to the `sfnt' if both are
00061       available.
00062   */
00063 
00064 
00065 #include <ft2build.h>
00066 #include FT_FREETYPE_H
00067 #include FT_TRUETYPE_TAGS_H
00068 #include FT_INTERNAL_STREAM_H
00069 #include "ftbase.h"
00070 
00071 #if defined( __GNUC__ ) || defined( __IBMC__ )
00072   /* This is for Mac OS X.  Without redefinition, OS_INLINE */
00073   /* expands to `static inline' which doesn't survive the   */
00074   /* -ansi compilation flag of GCC.                         */
00075 #if !HAVE_ANSI_OS_INLINE
00076 #undef  OS_INLINE
00077 #define OS_INLINE   static __inline__
00078 #endif
00079 #include <CoreServices/CoreServices.h>
00080 #include <ApplicationServices/ApplicationServices.h>
00081 #include <sys/syslimits.h> /* PATH_MAX */
00082 #else
00083 #include <Resources.h>
00084 #include <Fonts.h>
00085 #include <Endian.h>
00086 #include <Errors.h>
00087 #include <Files.h>
00088 #include <TextUtils.h>
00089 #endif
00090 
00091 #ifndef PATH_MAX
00092 #define PATH_MAX 1024 /* same with Mac OS X's syslimits.h */
00093 #endif
00094 
00095 #if defined( __MWERKS__ ) && !TARGET_RT_MAC_MACHO
00096 #include <FSp_fopen.h>
00097 #endif
00098 
00099 #define FT_DEPRECATED_ATTRIBUTE
00100 
00101 #include FT_MAC_H
00102 
00103   /* undefine blocking-macros in ftmac.h */
00104 #undef FT_GetFile_From_Mac_Name
00105 #undef FT_GetFile_From_Mac_ATS_Name
00106 #undef FT_New_Face_From_FOND
00107 #undef FT_New_Face_From_FSSpec
00108 #undef FT_New_Face_From_FSRef
00109 
00110 
00111   /* FSSpec functions are deprecated since Mac OS X 10.4 */
00112 #ifndef HAVE_FSSPEC
00113 #if TARGET_API_MAC_OS8 || TARGET_API_MAC_CARBON
00114 #define HAVE_FSSPEC  1
00115 #else
00116 #define HAVE_FSSPEC  0
00117 #endif
00118 #endif
00119 
00120   /* most FSRef functions were introduced since Mac OS 9 */
00121 #ifndef HAVE_FSREF
00122 #if TARGET_API_MAC_OSX
00123 #define HAVE_FSREF  1
00124 #else
00125 #define HAVE_FSREF  0
00126 #endif
00127 #endif
00128 
00129   /* QuickDraw is deprecated since Mac OS X 10.4 */
00130 #ifndef HAVE_QUICKDRAW_CARBON
00131 #if TARGET_API_MAC_OS8 || TARGET_API_MAC_CARBON
00132 #define HAVE_QUICKDRAW_CARBON  1
00133 #else
00134 #define HAVE_QUICKDRAW_CARBON  0
00135 #endif
00136 #endif
00137 
00138   /* AppleTypeService is available since Mac OS X */
00139 #ifndef HAVE_ATS
00140 #if TARGET_API_MAC_OSX
00141 #define HAVE_ATS  1
00142 #ifndef kATSOptionFlagsUnRestrictedScope /* since Mac OS X 10.1 */
00143 #define kATSOptionFlagsUnRestrictedScope kATSOptionFlagsDefault
00144 #endif
00145 #else
00146 #define HAVE_ATS  0
00147 #endif
00148 #endif
00149 
00150   /* `configure' checks the availability of `ResourceIndex' strictly */
00151   /* and sets HAVE_TYPE_RESOURCE_INDEX to 1 or 0 always.  If it is   */
00152   /* not set (e.g., a build without `configure'), the availability   */
00153   /* is guessed from the SDK version.                                */
00154 #ifndef HAVE_TYPE_RESOURCE_INDEX
00155 #if !defined( MAC_OS_X_VERSION_10_5 ) || \
00156     ( MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5 )
00157 #define HAVE_TYPE_RESOURCE_INDEX 0
00158 #else
00159 #define HAVE_TYPE_RESOURCE_INDEX 1
00160 #endif
00161 #endif /* !HAVE_TYPE_RESOURCE_INDEX */
00162 
00163 #if ( HAVE_TYPE_RESOURCE_INDEX == 0 )
00164 typedef short ResourceIndex;
00165 #endif
00166 
00167   /* Set PREFER_LWFN to 1 if LWFN (Type 1) is preferred over
00168      TrueType in case *both* are available (this is not common,
00169      but it *is* possible). */
00170 #ifndef PREFER_LWFN
00171 #define PREFER_LWFN  1
00172 #endif
00173 
00174 
00175 #if !HAVE_QUICKDRAW_CARBON  /* QuickDraw is deprecated since Mac OS X 10.4 */
00176 
00177   FT_EXPORT_DEF( FT_Error )
00178   FT_GetFile_From_Mac_Name( const char*  fontName,
00179                             FSSpec*      pathSpec,
00180                             FT_Long*     face_index )
00181   {
00182     FT_UNUSED( fontName );
00183     FT_UNUSED( pathSpec );
00184     FT_UNUSED( face_index );
00185 
00186     return FT_Err_Unimplemented_Feature;
00187   }
00188 
00189 #else
00190 
00191   FT_EXPORT_DEF( FT_Error )
00192   FT_GetFile_From_Mac_Name( const char*  fontName,
00193                             FSSpec*      pathSpec,
00194                             FT_Long*     face_index )
00195   {
00196     OptionBits            options = kFMUseGlobalScopeOption;
00197 
00198     FMFontFamilyIterator  famIter;
00199     OSStatus              status = FMCreateFontFamilyIterator( NULL, NULL,
00200                                                                options,
00201                                                                &famIter );
00202     FMFont                the_font = 0;
00203     FMFontFamily          family   = 0;
00204 
00205 
00206     *face_index = 0;
00207     while ( status == 0 && !the_font )
00208     {
00209       status = FMGetNextFontFamily( &famIter, &family );
00210       if ( status == 0 )
00211       {
00212         int                           stat2;
00213         FMFontFamilyInstanceIterator  instIter;
00214         Str255                        famNameStr;
00215         char                          famName[256];
00216 
00217 
00218         /* get the family name */
00219         FMGetFontFamilyName( family, famNameStr );
00220         CopyPascalStringToC( famNameStr, famName );
00221 
00222         /* iterate through the styles */
00223         FMCreateFontFamilyInstanceIterator( family, &instIter );
00224 
00225         *face_index = 0;
00226         stat2       = 0;
00227 
00228         while ( stat2 == 0 && !the_font )
00229         {
00230           FMFontStyle  style;
00231           FMFontSize   size;
00232           FMFont       font;
00233 
00234 
00235           stat2 = FMGetNextFontFamilyInstance( &instIter, &font,
00236                                                &style, &size );
00237           if ( stat2 == 0 && size == 0 )
00238           {
00239             char  fullName[256];
00240 
00241 
00242             /* build up a complete face name */
00243             ft_strcpy( fullName, famName );
00244             if ( style & bold )
00245               ft_strcat( fullName, " Bold" );
00246             if ( style & italic )
00247               ft_strcat( fullName, " Italic" );
00248 
00249             /* compare with the name we are looking for */
00250             if ( ft_strcmp( fullName, fontName ) == 0 )
00251             {
00252               /* found it! */
00253               the_font = font;
00254             }
00255             else
00256               ++(*face_index);
00257           }
00258         }
00259 
00260         FMDisposeFontFamilyInstanceIterator( &instIter );
00261       }
00262     }
00263 
00264     FMDisposeFontFamilyIterator( &famIter );
00265 
00266     if ( the_font )
00267     {
00268       FMGetFontContainer( the_font, pathSpec );
00269       return FT_Err_Ok;
00270     }
00271     else
00272       return FT_Err_Unknown_File_Format;
00273   }
00274 
00275 #endif /* HAVE_QUICKDRAW_CARBON */
00276 
00277 
00278 #if HAVE_ATS
00279 
00280   /* Private function.                                         */
00281   /* The FSSpec type has been discouraged for a long time,     */
00282   /* unfortunately an FSRef replacement API for                */
00283   /* ATSFontGetFileSpecification() is only available in        */
00284   /* Mac OS X 10.5 and later.                                  */
00285   static OSStatus
00286   FT_ATSFontGetFileReference( ATSFontRef  ats_font_id,
00287                               FSRef*      ats_font_ref )
00288   {
00289     OSStatus  err;
00290 
00291 #if !defined( MAC_OS_X_VERSION_10_5 ) || \
00292     MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5
00293     FSSpec    spec;
00294 
00295 
00296     err = ATSFontGetFileSpecification( ats_font_id, &spec );
00297     if ( noErr == err )
00298       err = FSpMakeFSRef( &spec, ats_font_ref );
00299 #else
00300     err = ATSFontGetFileReference( ats_font_id, ats_font_ref );
00301 #endif
00302 
00303     return err;
00304   }
00305 
00306 
00307   static FT_Error
00308   FT_GetFileRef_From_Mac_ATS_Name( const char*  fontName,
00309                                    FSRef*       ats_font_ref,
00310                                    FT_Long*     face_index )
00311   {
00312     CFStringRef  cf_fontName;
00313     ATSFontRef   ats_font_id;
00314 
00315 
00316     *face_index = 0;
00317 
00318     cf_fontName = CFStringCreateWithCString( NULL, fontName,
00319                                              kCFStringEncodingMacRoman );
00320     ats_font_id = ATSFontFindFromName( cf_fontName,
00321                                        kATSOptionFlagsUnRestrictedScope );
00322     CFRelease( cf_fontName );
00323 
00324     if ( ats_font_id == 0 || ats_font_id == 0xFFFFFFFFUL )
00325       return FT_Err_Unknown_File_Format;
00326 
00327     if ( noErr != FT_ATSFontGetFileReference( ats_font_id, ats_font_ref ) )
00328       return FT_Err_Unknown_File_Format;
00329 
00330     /* face_index calculation by searching preceding fontIDs */
00331     /* with same FSRef                                       */
00332     {
00333       ATSFontRef  id2 = ats_font_id - 1;
00334       FSRef       ref2;
00335 
00336 
00337       while ( id2 > 0 )
00338       {
00339         if ( noErr != FT_ATSFontGetFileReference( id2, &ref2 ) )
00340           break;
00341         if ( noErr != FSCompareFSRefs( ats_font_ref, &ref2 ) )
00342           break;
00343 
00344         id2--;
00345       }
00346       *face_index = ats_font_id - ( id2 + 1 );
00347     }
00348 
00349     return FT_Err_Ok;
00350   }
00351 
00352 #endif
00353 
00354 #if !HAVE_ATS
00355 
00356   FT_EXPORT_DEF( FT_Error )
00357   FT_GetFilePath_From_Mac_ATS_Name( const char*  fontName,
00358                                     UInt8*       path,
00359                                     UInt32       maxPathSize,
00360                                     FT_Long*     face_index )
00361   {
00362     FT_UNUSED( fontName );
00363     FT_UNUSED( path );
00364     FT_UNUSED( maxPathSize );
00365     FT_UNUSED( face_index );
00366 
00367     return FT_Err_Unimplemented_Feature;
00368   }
00369 
00370 #else
00371 
00372   FT_EXPORT_DEF( FT_Error )
00373   FT_GetFilePath_From_Mac_ATS_Name( const char*  fontName,
00374                                     UInt8*       path,
00375                                     UInt32       maxPathSize,
00376                                     FT_Long*     face_index )
00377   {
00378     FSRef     ref;
00379     FT_Error  err;
00380 
00381 
00382     err = FT_GetFileRef_From_Mac_ATS_Name( fontName, &ref, face_index );
00383     if ( FT_Err_Ok != err )
00384       return err;
00385 
00386     if ( noErr != FSRefMakePath( &ref, path, maxPathSize ) )
00387       return FT_Err_Unknown_File_Format;
00388 
00389     return FT_Err_Ok;
00390   }
00391 
00392 #endif /* HAVE_ATS */
00393 
00394 
00395 #if !HAVE_FSSPEC || !HAVE_ATS
00396 
00397   FT_EXPORT_DEF( FT_Error )
00398   FT_GetFile_From_Mac_ATS_Name( const char*  fontName,
00399                                 FSSpec*      pathSpec,
00400                                 FT_Long*     face_index )
00401   {
00402     FT_UNUSED( fontName );
00403     FT_UNUSED( pathSpec );
00404     FT_UNUSED( face_index );
00405 
00406     return FT_Err_Unimplemented_Feature;
00407   }
00408 
00409 #else
00410 
00411   /* This function is deprecated because FSSpec is deprecated in Mac OS X. */
00412   FT_EXPORT_DEF( FT_Error )
00413   FT_GetFile_From_Mac_ATS_Name( const char*  fontName,
00414                                 FSSpec*      pathSpec,
00415                                 FT_Long*     face_index )
00416   {
00417     FSRef     ref;
00418     FT_Error  err;
00419 
00420 
00421     err = FT_GetFileRef_From_Mac_ATS_Name( fontName, &ref, face_index );
00422     if ( FT_Err_Ok != err )
00423       return err;
00424 
00425     if ( noErr != FSGetCatalogInfo( &ref, kFSCatInfoNone, NULL, NULL,
00426                                     pathSpec, NULL ) )
00427       return FT_Err_Unknown_File_Format;
00428 
00429     return FT_Err_Ok;
00430   }
00431 
00432 #endif
00433 
00434 
00435 #if defined( __MWERKS__ ) && !TARGET_RT_MAC_MACHO
00436 
00437 #define STREAM_FILE( stream )  ( (FT_FILE*)stream->descriptor.pointer )
00438 
00439 
00440   FT_CALLBACK_DEF( void )
00441   ft_FSp_stream_close( FT_Stream  stream )
00442   {
00443     ft_fclose( STREAM_FILE( stream ) );
00444 
00445     stream->descriptor.pointer = NULL;
00446     stream->size               = 0;
00447     stream->base               = 0;
00448   }
00449 
00450 
00451   FT_CALLBACK_DEF( unsigned long )
00452   ft_FSp_stream_io( FT_Stream       stream,
00453                     unsigned long   offset,
00454                     unsigned char*  buffer,
00455                     unsigned long   count )
00456   {
00457     FT_FILE*  file;
00458 
00459 
00460     file = STREAM_FILE( stream );
00461 
00462     ft_fseek( file, offset, SEEK_SET );
00463 
00464     return (unsigned long)ft_fread( buffer, 1, count, file );
00465   }
00466 
00467 #endif  /* __MWERKS__ && !TARGET_RT_MAC_MACHO */
00468 
00469 
00470 #if HAVE_FSSPEC && !HAVE_FSREF
00471 
00472   /* isDirectory is a dummy to synchronize API with FSPathMakeRef() */
00473   static OSErr
00474   FT_FSPathMakeSpec( const UInt8*  pathname,
00475                      FSSpec*       spec_p,
00476                      Boolean       isDirectory )
00477   {
00478     const char  *p, *q;
00479     short       vRefNum;
00480     long        dirID;
00481     Str255      nodeName;
00482     OSErr       err;
00483     FT_UNUSED( isDirectory );
00484 
00485 
00486     p = q = (const char *)pathname;
00487     dirID   = 0;
00488     vRefNum = 0;
00489 
00490     while ( 1 )
00491     {
00492       int  len = ft_strlen( p );
00493 
00494 
00495       if ( len > 255 )
00496         len = 255;
00497 
00498       q = p + len;
00499 
00500       if ( q == p )
00501         return 0;
00502 
00503       if ( 255 < ft_strlen( (char *)pathname ) )
00504       {
00505         while ( p < q && *q != ':' )
00506           q--;
00507       }
00508 
00509       if ( p < q )
00510         *(char *)nodeName = q - p;
00511       else if ( ft_strlen( p ) < 256 )
00512         *(char *)nodeName = ft_strlen( p );
00513       else
00514         return errFSNameTooLong;
00515 
00516       ft_strncpy( (char *)nodeName + 1, (char *)p, *(char *)nodeName );
00517       err = FSMakeFSSpec( vRefNum, dirID, nodeName, spec_p );
00518       if ( err || '\0' == *q )
00519         return err;
00520 
00521       vRefNum = spec_p->vRefNum;
00522       dirID   = spec_p->parID;
00523 
00524       p = q;
00525     }
00526   }
00527 
00528 
00529   static OSErr
00530   FT_FSpMakePath( const FSSpec*  spec_p,
00531                   UInt8*         path,
00532                   UInt32         maxPathSize )
00533   {
00534     OSErr   err;
00535     FSSpec  spec = *spec_p;
00536     short   vRefNum;
00537     long    dirID;
00538     Str255  parDir_name;
00539 
00540 
00541     FT_MEM_SET( path, 0, maxPathSize );
00542     while ( 1 )
00543     {
00544       int             child_namelen = ft_strlen( (char *)path );
00545       unsigned char   node_namelen  = spec.name[0];
00546       unsigned char*  node_name     = spec.name + 1;
00547 
00548 
00549       if ( node_namelen + child_namelen > maxPathSize )
00550         return errFSNameTooLong;
00551 
00552       FT_MEM_MOVE( path + node_namelen + 1, path, child_namelen );
00553       FT_MEM_COPY( path, node_name, node_namelen );
00554       if ( child_namelen > 0 )
00555         path[node_namelen] = ':';
00556 
00557       vRefNum        = spec.vRefNum;
00558       dirID          = spec.parID;
00559       parDir_name[0] = '\0';
00560       err = FSMakeFSSpec( vRefNum, dirID, parDir_name, &spec );
00561       if ( noErr != err || dirID == spec.parID )
00562         break;
00563     }
00564     return noErr;
00565   }
00566 
00567 #endif /* HAVE_FSSPEC && !HAVE_FSREF */
00568 
00569 
00570   static OSErr
00571   FT_FSPathMakeRes( const UInt8*    pathname,
00572                     ResFileRefNum*  res )
00573   {
00574 
00575 #if HAVE_FSREF
00576 
00577     OSErr  err;
00578     FSRef  ref;
00579 
00580 
00581     if ( noErr != FSPathMakeRef( pathname, &ref, FALSE ) )
00582       return FT_Err_Cannot_Open_Resource;
00583 
00584     /* at present, no support for dfont format */
00585     err = FSOpenResourceFile( &ref, 0, NULL, fsRdPerm, res );
00586     if ( noErr == err )
00587       return err;
00588 
00589     /* fallback to original resource-fork font */
00590     *res = FSOpenResFile( &ref, fsRdPerm );
00591     err  = ResError();
00592 
00593 #else
00594 
00595     OSErr   err;
00596     FSSpec  spec;
00597 
00598 
00599     if ( noErr != FT_FSPathMakeSpec( pathname, &spec, FALSE ) )
00600       return FT_Err_Cannot_Open_Resource;
00601 
00602     /* at present, no support for dfont format without FSRef */
00603     /* (see above), try original resource-fork font          */
00604     *res = FSpOpenResFile( &spec, fsRdPerm );
00605     err  = ResError();
00606 
00607 #endif /* HAVE_FSREF */
00608 
00609     return err;
00610   }
00611 
00612 
00613   /* Return the file type for given pathname */
00614   static OSType
00615   get_file_type_from_path( const UInt8*  pathname )
00616   {
00617 
00618 #if HAVE_FSREF
00619 
00620     FSRef          ref;
00621     FSCatalogInfo  info;
00622 
00623 
00624     if ( noErr != FSPathMakeRef( pathname, &ref, FALSE ) )
00625       return ( OSType ) 0;
00626 
00627     if ( noErr != FSGetCatalogInfo( &ref, kFSCatInfoFinderInfo, &info,
00628                                     NULL, NULL, NULL ) )
00629       return ( OSType ) 0;
00630 
00631     return ((FInfo *)(info.finderInfo))->fdType;
00632 
00633 #else
00634 
00635     FSSpec  spec;
00636     FInfo   finfo;
00637 
00638 
00639     if ( noErr != FT_FSPathMakeSpec( pathname, &spec, FALSE ) )
00640       return ( OSType ) 0;
00641 
00642     if ( noErr != FSpGetFInfo( &spec, &finfo ) )
00643       return ( OSType ) 0;
00644 
00645     return finfo.fdType;
00646 
00647 #endif /* HAVE_FSREF */
00648 
00649   }
00650 
00651 
00652   /* Given a PostScript font name, create the Macintosh LWFN file name. */
00653   static void
00654   create_lwfn_name( char*   ps_name,
00655                     Str255  lwfn_file_name )
00656   {
00657     int       max = 5, count = 0;
00658     FT_Byte*  p = lwfn_file_name;
00659     FT_Byte*  q = (FT_Byte*)ps_name;
00660 
00661 
00662     lwfn_file_name[0] = 0;
00663 
00664     while ( *q )
00665     {
00666       if ( ft_isupper( *q ) )
00667       {
00668         if ( count )
00669           max = 3;
00670         count = 0;
00671       }
00672       if ( count < max && ( ft_isalnum( *q ) || *q == '_' ) )
00673       {
00674         *++p = *q;
00675         lwfn_file_name[0]++;
00676         count++;
00677       }
00678       q++;
00679     }
00680   }
00681 
00682 
00683   static short
00684   count_faces_sfnt( char*  fond_data )
00685   {
00686     /* The count is 1 greater than the value in the FOND.  */
00687     /* Isn't that cute? :-)                                */
00688 
00689     return EndianS16_BtoN( *( (short*)( fond_data +
00690                                         sizeof ( FamRec ) ) ) ) + 1;
00691   }
00692 
00693 
00694   static short
00695   count_faces_scalable( char*  fond_data )
00696   {
00697     AsscEntry*  assoc;
00698     FamRec*     fond;
00699     short       i, face, face_all;
00700 
00701 
00702     fond     = (FamRec*)fond_data;
00703     face_all = EndianS16_BtoN( *( (short *)( fond_data +
00704                                              sizeof ( FamRec ) ) ) ) + 1;
00705     assoc    = (AsscEntry*)( fond_data + sizeof ( FamRec ) + 2 );
00706     face     = 0;
00707 
00708     for ( i = 0; i < face_all; i++ )
00709     {
00710       if ( 0 == EndianS16_BtoN( assoc[i].fontSize ) )
00711         face++;
00712     }
00713     return face;
00714   }
00715 
00716 
00717   /* Look inside the FOND data, answer whether there should be an SFNT
00718      resource, and answer the name of a possible LWFN Type 1 file.
00719 
00720      Thanks to Paul Miller (paulm@profoundeffects.com) for the fix
00721      to load a face OTHER than the first one in the FOND!
00722   */
00723 
00724   static void
00725   parse_fond( char*   fond_data,
00726               short*  have_sfnt,
00727               ResID*  sfnt_id,
00728               Str255  lwfn_file_name,
00729               short   face_index )
00730   {
00731     AsscEntry*  assoc;
00732     AsscEntry*  base_assoc;
00733     FamRec*     fond;
00734 
00735 
00736     *sfnt_id          = 0;
00737     *have_sfnt        = 0;
00738     lwfn_file_name[0] = 0;
00739 
00740     fond       = (FamRec*)fond_data;
00741     assoc      = (AsscEntry*)( fond_data + sizeof ( FamRec ) + 2 );
00742     base_assoc = assoc;
00743 
00744     /* the maximum faces in a FOND is 48, size of StyleTable.indexes[] */
00745     if ( 47 < face_index )
00746       return;
00747 
00748     /* Let's do a little range checking before we get too excited here */
00749     if ( face_index < count_faces_sfnt( fond_data ) )
00750     {
00751       assoc += face_index;        /* add on the face_index! */
00752 
00753       /* if the face at this index is not scalable,
00754          fall back to the first one (old behavior) */
00755       if ( EndianS16_BtoN( assoc->fontSize ) == 0 )
00756       {
00757         *have_sfnt = 1;
00758         *sfnt_id   = EndianS16_BtoN( assoc->fontID );
00759       }
00760       else if ( base_assoc->fontSize == 0 )
00761       {
00762         *have_sfnt = 1;
00763         *sfnt_id   = EndianS16_BtoN( base_assoc->fontID );
00764       }
00765     }
00766 
00767     if ( EndianS32_BtoN( fond->ffStylOff ) )
00768     {
00769       unsigned char*  p = (unsigned char*)fond_data;
00770       StyleTable*     style;
00771       unsigned short  string_count;
00772       char            ps_name[256];
00773       unsigned char*  names[64];
00774       int             i;
00775 
00776 
00777       p += EndianS32_BtoN( fond->ffStylOff );
00778       style = (StyleTable*)p;
00779       p += sizeof ( StyleTable );
00780       string_count = EndianS16_BtoN( *(short*)(p) );
00781       p += sizeof ( short );
00782 
00783       for ( i = 0; i < string_count && i < 64; i++ )
00784       {
00785         names[i] = p;
00786         p       += names[i][0];
00787         p++;
00788       }
00789 
00790       {
00791         size_t  ps_name_len = (size_t)names[0][0];
00792 
00793 
00794         if ( ps_name_len != 0 )
00795         {
00796           ft_memcpy(ps_name, names[0] + 1, ps_name_len);
00797           ps_name[ps_name_len] = 0;
00798         }
00799         if ( style->indexes[face_index] > 1 &&
00800              style->indexes[face_index] <= FT_MIN( string_count, 64 ) )
00801         {
00802           unsigned char*  suffixes = names[style->indexes[face_index] - 1];
00803 
00804 
00805           for ( i = 1; i <= suffixes[0]; i++ )
00806           {
00807             unsigned char*  s;
00808             size_t          j = suffixes[i] - 1;
00809 
00810 
00811             if ( j < string_count && ( s = names[j] ) != NULL )
00812             {
00813               size_t  s_len = (size_t)s[0];
00814 
00815 
00816               if ( s_len != 0 && ps_name_len + s_len < sizeof ( ps_name ) )
00817               {
00818                 ft_memcpy( ps_name + ps_name_len, s + 1, s_len );
00819                 ps_name_len += s_len;
00820                 ps_name[ps_name_len] = 0;
00821               }
00822             }
00823           }
00824         }
00825       }
00826 
00827       create_lwfn_name( ps_name, lwfn_file_name );
00828     }
00829   }
00830 
00831 
00832   static  FT_Error
00833   lookup_lwfn_by_fond( const UInt8*      path_fond,
00834                        ConstStr255Param  base_lwfn,
00835                        UInt8*            path_lwfn,
00836                        int               path_size )
00837   {
00838 
00839 #if HAVE_FSREF
00840 
00841     FSRef  ref, par_ref;
00842     int    dirname_len;
00843 
00844 
00845     /* Pathname for FSRef can be in various formats: HFS, HFS+, and POSIX. */
00846     /* We should not extract parent directory by string manipulation.      */
00847 
00848     if ( noErr != FSPathMakeRef( path_fond, &ref, FALSE ) )
00849       return FT_Err_Invalid_Argument;
00850 
00851     if ( noErr != FSGetCatalogInfo( &ref, kFSCatInfoNone,
00852                                     NULL, NULL, NULL, &par_ref ) )
00853       return FT_Err_Invalid_Argument;
00854 
00855     if ( noErr != FSRefMakePath( &par_ref, path_lwfn, path_size ) )
00856       return FT_Err_Invalid_Argument;
00857 
00858     if ( ft_strlen( (char *)path_lwfn ) + 1 + base_lwfn[0] > path_size )
00859       return FT_Err_Invalid_Argument;
00860 
00861     /* now we have absolute dirname in path_lwfn */
00862     if ( path_lwfn[0] == '/' )
00863       ft_strcat( (char *)path_lwfn, "/" );
00864     else
00865       ft_strcat( (char *)path_lwfn, ":" );
00866 
00867     dirname_len = ft_strlen( (char *)path_lwfn );
00868     ft_strcat( (char *)path_lwfn, (char *)base_lwfn + 1 );
00869     path_lwfn[dirname_len + base_lwfn[0]] = '\0';
00870 
00871     if ( noErr != FSPathMakeRef( path_lwfn, &ref, FALSE ) )
00872       return FT_Err_Cannot_Open_Resource;
00873 
00874     if ( noErr != FSGetCatalogInfo( &ref, kFSCatInfoNone,
00875                                     NULL, NULL, NULL, NULL ) )
00876       return FT_Err_Cannot_Open_Resource;
00877 
00878     return FT_Err_Ok;
00879 
00880 #else
00881 
00882     int     i;
00883     FSSpec  spec;
00884 
00885 
00886     /* pathname for FSSpec is always HFS format */
00887     if ( ft_strlen( (char *)path_fond ) > path_size )
00888       return FT_Err_Invalid_Argument;
00889 
00890     ft_strcpy( (char *)path_lwfn, (char *)path_fond );
00891 
00892     i = ft_strlen( (char *)path_lwfn ) - 1;
00893     while ( i > 0 && ':' != path_lwfn[i] )
00894       i--;
00895 
00896     if ( i + 1 + base_lwfn[0] > path_size )
00897       return FT_Err_Invalid_Argument;
00898 
00899     if ( ':' == path_lwfn[i] )
00900     {
00901       ft_strcpy( (char *)path_lwfn + i + 1, (char *)base_lwfn + 1 );
00902       path_lwfn[i + 1 + base_lwfn[0]] = '\0';
00903     }
00904     else
00905     {
00906       ft_strcpy( (char *)path_lwfn, (char *)base_lwfn + 1 );
00907       path_lwfn[base_lwfn[0]] = '\0';
00908     }
00909 
00910     if ( noErr != FT_FSPathMakeSpec( path_lwfn, &spec, FALSE ) )
00911       return FT_Err_Cannot_Open_Resource;
00912 
00913     return FT_Err_Ok;
00914 
00915 #endif /* HAVE_FSREF */
00916 
00917   }
00918 
00919 
00920   static short
00921   count_faces( Handle        fond,
00922                const UInt8*  pathname )
00923   {
00924     ResID     sfnt_id;
00925     short     have_sfnt, have_lwfn;
00926     Str255    lwfn_file_name;
00927     UInt8     buff[PATH_MAX];
00928     FT_Error  err;
00929     short     num_faces;
00930 
00931 
00932     have_sfnt = have_lwfn = 0;
00933 
00934     HLock( fond );
00935     parse_fond( *fond, &have_sfnt, &sfnt_id, lwfn_file_name, 0 );
00936 
00937     if ( lwfn_file_name[0] )
00938     {
00939       err = lookup_lwfn_by_fond( pathname, lwfn_file_name,
00940                                  buff, sizeof ( buff )  );
00941       if ( FT_Err_Ok == err )
00942         have_lwfn = 1;
00943     }
00944 
00945     if ( have_lwfn && ( !have_sfnt || PREFER_LWFN ) )
00946       num_faces = 1;
00947     else
00948       num_faces = count_faces_scalable( *fond );
00949 
00950     HUnlock( fond );
00951     return num_faces;
00952   }
00953 
00954 
00955   /* Read Type 1 data from the POST resources inside the LWFN file,
00956      return a PFB buffer.  This is somewhat convoluted because the FT2
00957      PFB parser wants the ASCII header as one chunk, and the LWFN
00958      chunks are often not organized that way, so we glue chunks
00959      of the same type together. */
00960   static FT_Error
00961   read_lwfn( FT_Memory      memory,
00962              ResFileRefNum  res,
00963              FT_Byte**      pfb_data,
00964              FT_ULong*      size )
00965   {
00966     FT_Error       error = FT_Err_Ok;
00967     ResID          res_id;
00968     unsigned char  *buffer, *p, *size_p = NULL;
00969     FT_ULong       total_size = 0;
00970     FT_ULong       old_total_size = 0;
00971     FT_ULong       post_size, pfb_chunk_size;
00972     Handle         post_data;
00973     char           code, last_code;
00974 
00975 
00976     UseResFile( res );
00977 
00978     /* First pass: load all POST resources, and determine the size of */
00979     /* the output buffer.                                             */
00980     res_id    = 501;
00981     last_code = -1;
00982 
00983     for (;;)
00984     {
00985       post_data = Get1Resource( TTAG_POST, res_id++ );
00986       if ( post_data == NULL )
00987         break;  /* we are done */
00988 
00989       code = (*post_data)[0];
00990 
00991       if ( code != last_code )
00992       {
00993         if ( code == 5 )
00994           total_size += 2; /* just the end code */
00995         else
00996           total_size += 6; /* code + 4 bytes chunk length */
00997       }
00998 
00999       total_size += GetHandleSize( post_data ) - 2;
01000       last_code = code;
01001 
01002       /* detect integer overflows */
01003       if ( total_size < old_total_size )
01004       {
01005         error = FT_Err_Array_Too_Large;
01006         goto Error;
01007       }
01008 
01009       old_total_size = total_size;
01010     }
01011 
01012     if ( FT_ALLOC( buffer, (FT_Long)total_size ) )
01013       goto Error;
01014 
01015     /* Second pass: append all POST data to the buffer, add PFB fields. */
01016     /* Glue all consecutive chunks of the same type together.           */
01017     p              = buffer;
01018     res_id         = 501;
01019     last_code      = -1;
01020     pfb_chunk_size = 0;
01021 
01022     for (;;)
01023     {
01024       post_data = Get1Resource( TTAG_POST, res_id++ );
01025       if ( post_data == NULL )
01026         break;  /* we are done */
01027 
01028       post_size = (FT_ULong)GetHandleSize( post_data ) - 2;
01029       code = (*post_data)[0];
01030 
01031       if ( code != last_code )
01032       {
01033         if ( last_code != -1 )
01034         {
01035           /* we are done adding a chunk, fill in the size field */
01036           if ( size_p != NULL )
01037           {
01038             *size_p++ = (FT_Byte)(   pfb_chunk_size         & 0xFF );
01039             *size_p++ = (FT_Byte)( ( pfb_chunk_size >> 8  ) & 0xFF );
01040             *size_p++ = (FT_Byte)( ( pfb_chunk_size >> 16 ) & 0xFF );
01041             *size_p++ = (FT_Byte)( ( pfb_chunk_size >> 24 ) & 0xFF );
01042           }
01043           pfb_chunk_size = 0;
01044         }
01045 
01046         *p++ = 0x80;
01047         if ( code == 5 )
01048           *p++ = 0x03;  /* the end */
01049         else if ( code == 2 )
01050           *p++ = 0x02;  /* binary segment */
01051         else
01052           *p++ = 0x01;  /* ASCII segment */
01053 
01054         if ( code != 5 )
01055         {
01056           size_p = p;   /* save for later */
01057           p += 4;       /* make space for size field */
01058         }
01059       }
01060 
01061       ft_memcpy( p, *post_data + 2, post_size );
01062       pfb_chunk_size += post_size;
01063       p += post_size;
01064       last_code = code;
01065     }
01066 
01067     *pfb_data = buffer;
01068     *size = total_size;
01069 
01070   Error:
01071     CloseResFile( res );
01072     return error;
01073   }
01074 
01075 
01076   /* Create a new FT_Face from a file spec to an LWFN file. */
01077   static FT_Error
01078   FT_New_Face_From_LWFN( FT_Library    library,
01079                          const UInt8*  pathname,
01080                          FT_Long       face_index,
01081                          FT_Face*      aface )
01082   {
01083     FT_Byte*       pfb_data;
01084     FT_ULong       pfb_size;
01085     FT_Error       error;
01086     ResFileRefNum  res;
01087 
01088 
01089     if ( noErr != FT_FSPathMakeRes( pathname, &res ) )
01090       return FT_Err_Cannot_Open_Resource;
01091 
01092     pfb_data = NULL;
01093     pfb_size = 0;
01094     error = read_lwfn( library->memory, res, &pfb_data, &pfb_size );
01095     CloseResFile( res ); /* PFB is already loaded, useless anymore */
01096     if ( error )
01097       return error;
01098 
01099     return open_face_from_buffer( library,
01100                                   pfb_data,
01101                                   pfb_size,
01102                                   face_index,
01103                                   "type1",
01104                                   aface );
01105   }
01106 
01107 
01108   /* Create a new FT_Face from an SFNT resource, specified by res ID. */
01109   static FT_Error
01110   FT_New_Face_From_SFNT( FT_Library  library,
01111                          ResID       sfnt_id,
01112                          FT_Long     face_index,
01113                          FT_Face*    aface )
01114   {
01115     Handle     sfnt = NULL;
01116     FT_Byte*   sfnt_data;
01117     size_t     sfnt_size;
01118     FT_Error   error  = FT_Err_Ok;
01119     FT_Memory  memory = library->memory;
01120     int        is_cff, is_sfnt_ps;
01121 
01122 
01123     sfnt = GetResource( TTAG_sfnt, sfnt_id );
01124     if ( sfnt == NULL )
01125       return FT_Err_Invalid_Handle;
01126 
01127     sfnt_size = (FT_ULong)GetHandleSize( sfnt );
01128     if ( FT_ALLOC( sfnt_data, (FT_Long)sfnt_size ) )
01129     {
01130       ReleaseResource( sfnt );
01131       return error;
01132     }
01133 
01134     HLock( sfnt );
01135     ft_memcpy( sfnt_data, *sfnt, sfnt_size );
01136     HUnlock( sfnt );
01137     ReleaseResource( sfnt );
01138 
01139     is_cff     = sfnt_size > 4 && !ft_memcmp( sfnt_data, "OTTO", 4 );
01140     is_sfnt_ps = sfnt_size > 4 && !ft_memcmp( sfnt_data, "typ1", 4 );
01141 
01142     if ( is_sfnt_ps )
01143     {
01144       FT_Stream  stream;
01145 
01146 
01147       if ( FT_NEW( stream ) )
01148         goto Try_OpenType;
01149 
01150       FT_Stream_OpenMemory( stream, sfnt_data, sfnt_size );
01151       if ( !open_face_PS_from_sfnt_stream( library,
01152                                            stream,
01153                                            face_index,
01154                                            0, NULL,
01155                                            aface ) )
01156       {
01157         FT_Stream_Close( stream );
01158         FT_FREE( stream );
01159         FT_FREE( sfnt_data );
01160         goto Exit;
01161       }
01162 
01163       FT_FREE( stream );
01164     }
01165   Try_OpenType:
01166     error = open_face_from_buffer( library,
01167                                    sfnt_data,
01168                                    sfnt_size,
01169                                    face_index,
01170                                    is_cff ? "cff" : "truetype",
01171                                    aface );
01172   Exit:
01173     return error;
01174   }
01175 
01176 
01177   /* Create a new FT_Face from a file spec to a suitcase file. */
01178   static FT_Error
01179   FT_New_Face_From_Suitcase( FT_Library    library,
01180                              const UInt8*  pathname,
01181                              FT_Long       face_index,
01182                              FT_Face*      aface )
01183   {
01184     FT_Error       error = FT_Err_Cannot_Open_Resource;
01185     ResFileRefNum  res_ref;
01186     ResourceIndex  res_index;
01187     Handle         fond;
01188     short          num_faces_in_res, num_faces_in_fond;
01189 
01190 
01191     if ( noErr != FT_FSPathMakeRes( pathname, &res_ref ) )
01192       return FT_Err_Cannot_Open_Resource;
01193 
01194     UseResFile( res_ref );
01195     if ( ResError() )
01196       return FT_Err_Cannot_Open_Resource;
01197 
01198     num_faces_in_res = 0;
01199     for ( res_index = 1; ; ++res_index )
01200     {
01201       fond = Get1IndResource( TTAG_FOND, res_index );
01202       if ( ResError() )
01203         break;
01204 
01205       num_faces_in_fond  = count_faces( fond, pathname );
01206       num_faces_in_res  += num_faces_in_fond;
01207 
01208       if ( 0 <= face_index && face_index < num_faces_in_fond && error )
01209         error = FT_New_Face_From_FOND( library, fond, face_index, aface );
01210 
01211       face_index -= num_faces_in_fond;
01212     }
01213 
01214     CloseResFile( res_ref );
01215     if ( FT_Err_Ok == error && NULL != aface )
01216       (*aface)->num_faces = num_faces_in_res;
01217     return error;
01218   }
01219 
01220 
01221   /* documentation is in ftmac.h */
01222 
01223   FT_EXPORT_DEF( FT_Error )
01224   FT_New_Face_From_FOND( FT_Library  library,
01225                          Handle      fond,
01226                          FT_Long     face_index,
01227                          FT_Face*    aface )
01228   {
01229     short     have_sfnt, have_lwfn = 0;
01230     ResID     sfnt_id, fond_id;
01231     OSType    fond_type;
01232     Str255    fond_name;
01233     Str255    lwfn_file_name;
01234     UInt8     path_lwfn[PATH_MAX];
01235     OSErr     err;
01236     FT_Error  error = FT_Err_Ok;
01237 
01238 
01239     GetResInfo( fond, &fond_id, &fond_type, fond_name );
01240     if ( ResError() != noErr || fond_type != TTAG_FOND )
01241       return FT_Err_Invalid_File_Format;
01242 
01243     HLock( fond );
01244     parse_fond( *fond, &have_sfnt, &sfnt_id, lwfn_file_name, face_index );
01245     HUnlock( fond );
01246 
01247     if ( lwfn_file_name[0] )
01248     {
01249       ResFileRefNum  res;
01250 
01251 
01252       res = HomeResFile( fond );
01253       if ( noErr != ResError() )
01254         goto found_no_lwfn_file;
01255 
01256 #if HAVE_FSREF
01257 
01258       {
01259         UInt8  path_fond[PATH_MAX];
01260         FSRef  ref;
01261 
01262 
01263         err = FSGetForkCBInfo( res, kFSInvalidVolumeRefNum,
01264                                NULL, NULL, NULL, &ref, NULL );
01265         if ( noErr != err )
01266           goto found_no_lwfn_file;
01267 
01268         err = FSRefMakePath( &ref, path_fond, sizeof ( path_fond ) );
01269         if ( noErr != err )
01270           goto found_no_lwfn_file;
01271 
01272         error = lookup_lwfn_by_fond( path_fond, lwfn_file_name,
01273                                      path_lwfn, sizeof ( path_lwfn ) );
01274         if ( FT_Err_Ok == error )
01275           have_lwfn = 1;
01276       }
01277 
01278 #elif HAVE_FSSPEC
01279 
01280       {
01281         UInt8     path_fond[PATH_MAX];
01282         FCBPBRec  pb;
01283         Str255    fond_file_name;
01284         FSSpec    spec;
01285 
01286 
01287         FT_MEM_SET( &spec, 0, sizeof ( FSSpec ) );
01288         FT_MEM_SET( &pb,   0, sizeof ( FCBPBRec ) );
01289 
01290         pb.ioNamePtr = fond_file_name;
01291         pb.ioVRefNum = 0;
01292         pb.ioRefNum  = res;
01293         pb.ioFCBIndx = 0;
01294 
01295         err = PBGetFCBInfoSync( &pb );
01296         if ( noErr != err )
01297           goto found_no_lwfn_file;
01298 
01299         err = FSMakeFSSpec( pb.ioFCBVRefNum, pb.ioFCBParID,
01300                             fond_file_name, &spec );
01301         if ( noErr != err )
01302           goto found_no_lwfn_file;
01303 
01304         err = FT_FSpMakePath( &spec, path_fond, sizeof ( path_fond ) );
01305         if ( noErr != err )
01306           goto found_no_lwfn_file;
01307 
01308         error = lookup_lwfn_by_fond( path_fond, lwfn_file_name,
01309                                      path_lwfn, sizeof ( path_lwfn ) );
01310         if ( FT_Err_Ok == error )
01311           have_lwfn = 1;
01312       }
01313 
01314 #endif /* HAVE_FSREF, HAVE_FSSPEC */
01315 
01316     }
01317 
01318     if ( have_lwfn && ( !have_sfnt || PREFER_LWFN ) )
01319       error = FT_New_Face_From_LWFN( library,
01320                                      path_lwfn,
01321                                      face_index,
01322                                      aface );
01323     else
01324       error = FT_Err_Unknown_File_Format;
01325 
01326   found_no_lwfn_file:
01327     if ( have_sfnt && FT_Err_Ok != error )
01328       error = FT_New_Face_From_SFNT( library,
01329                                      sfnt_id,
01330                                      face_index,
01331                                      aface );
01332 
01333     return error;
01334   }
01335 
01336 
01337   /* Common function to load a new FT_Face from a resource file. */
01338   static FT_Error
01339   FT_New_Face_From_Resource( FT_Library    library,
01340                              const UInt8*  pathname,
01341                              FT_Long       face_index,
01342                              FT_Face*      aface )
01343   {
01344     OSType    file_type;
01345     FT_Error  error;
01346 
01347 
01348     /* LWFN is a (very) specific file format, check for it explicitly */
01349     file_type = get_file_type_from_path( pathname );
01350     if ( file_type == TTAG_LWFN )
01351       return FT_New_Face_From_LWFN( library, pathname, face_index, aface );
01352 
01353     /* Otherwise the file type doesn't matter (there are more than  */
01354     /* `FFIL' and `tfil').  Just try opening it as a font suitcase; */
01355     /* if it works, fine.                                           */
01356 
01357     error = FT_New_Face_From_Suitcase( library, pathname, face_index, aface );
01358     if ( error == 0 )
01359       return error;
01360 
01361     /* let it fall through to normal loader (.ttf, .otf, etc.); */
01362     /* we signal this by returning no error and no FT_Face      */
01363     *aface = NULL;
01364     return 0;
01365   }
01366 
01367 
01368   /*************************************************************************/
01369   /*                                                                       */
01370   /* <Function>                                                            */
01371   /*    FT_New_Face                                                        */
01372   /*                                                                       */
01373   /* <Description>                                                         */
01374   /*    This is the Mac-specific implementation of FT_New_Face.  In        */
01375   /*    addition to the standard FT_New_Face() functionality, it also      */
01376   /*    accepts pathnames to Mac suitcase files.  For further              */
01377   /*    documentation see the original FT_New_Face() in freetype.h.        */
01378   /*                                                                       */
01379   FT_EXPORT_DEF( FT_Error )
01380   FT_New_Face( FT_Library   library,
01381                const char*  pathname,
01382                FT_Long      face_index,
01383                FT_Face*     aface )
01384   {
01385     FT_Open_Args  args;
01386     FT_Error      error;
01387 
01388 
01389     /* test for valid `library' and `aface' delayed to FT_Open_Face() */
01390     if ( !pathname )
01391       return FT_Err_Invalid_Argument;
01392 
01393     error  = FT_Err_Ok;
01394     *aface = NULL;
01395 
01396     /* try resourcefork based font: LWFN, FFIL */
01397     error = FT_New_Face_From_Resource( library, (UInt8 *)pathname,
01398                                        face_index, aface );
01399     if ( error != 0 || *aface != NULL )
01400       return error;
01401 
01402     /* let it fall through to normal loader (.ttf, .otf, etc.) */
01403     args.flags    = FT_OPEN_PATHNAME;
01404     args.pathname = (char*)pathname;
01405     return FT_Open_Face( library, &args, face_index, aface );
01406   }
01407 
01408 
01409   /*************************************************************************/
01410   /*                                                                       */
01411   /* <Function>                                                            */
01412   /*    FT_New_Face_From_FSRef                                             */
01413   /*                                                                       */
01414   /* <Description>                                                         */
01415   /*    FT_New_Face_From_FSRef is identical to FT_New_Face except it       */
01416   /*    accepts an FSRef instead of a path.                                */
01417   /*                                                                       */
01418   /* This function is deprecated because Carbon data types (FSRef)         */
01419   /* are not cross-platform, and thus not suitable for the freetype API.   */
01420   FT_EXPORT_DEF( FT_Error )
01421   FT_New_Face_From_FSRef( FT_Library    library,
01422                           const FSRef*  ref,
01423                           FT_Long       face_index,
01424                           FT_Face*      aface )
01425   {
01426 
01427 #if !HAVE_FSREF
01428 
01429     FT_UNUSED( library );
01430     FT_UNUSED( ref );
01431     FT_UNUSED( face_index );
01432     FT_UNUSED( aface );
01433 
01434     return FT_Err_Unimplemented_Feature;
01435 
01436 #else
01437 
01438     FT_Error      error;
01439     FT_Open_Args  args;
01440     OSErr   err;
01441     UInt8   pathname[PATH_MAX];
01442 
01443 
01444     if ( !ref )
01445       return FT_Err_Invalid_Argument;
01446 
01447     err = FSRefMakePath( ref, pathname, sizeof ( pathname ) );
01448     if ( err )
01449       error = FT_Err_Cannot_Open_Resource;
01450 
01451     error = FT_New_Face_From_Resource( library, pathname, face_index, aface );
01452     if ( error != 0 || *aface != NULL )
01453       return error;
01454 
01455     /* fallback to datafork font */
01456     args.flags    = FT_OPEN_PATHNAME;
01457     args.pathname = (char*)pathname;
01458     return FT_Open_Face( library, &args, face_index, aface );
01459 
01460 #endif /* HAVE_FSREF */
01461 
01462   }
01463 
01464 
01465   /*************************************************************************/
01466   /*                                                                       */
01467   /* <Function>                                                            */
01468   /*    FT_New_Face_From_FSSpec                                            */
01469   /*                                                                       */
01470   /* <Description>                                                         */
01471   /*    FT_New_Face_From_FSSpec is identical to FT_New_Face except it      */
01472   /*    accepts an FSSpec instead of a path.                               */
01473   /*                                                                       */
01474   /* This function is deprecated because Carbon data types (FSSpec)        */
01475   /* are not cross-platform, and thus not suitable for the freetype API.   */
01476   FT_EXPORT_DEF( FT_Error )
01477   FT_New_Face_From_FSSpec( FT_Library     library,
01478                            const FSSpec*  spec,
01479                            FT_Long        face_index,
01480                            FT_Face*       aface )
01481   {
01482 
01483 #if HAVE_FSREF
01484 
01485     FSRef  ref;
01486 
01487 
01488     if ( !spec || FSpMakeFSRef( spec, &ref ) != noErr )
01489       return FT_Err_Invalid_Argument;
01490     else
01491       return FT_New_Face_From_FSRef( library, &ref, face_index, aface );
01492 
01493 #elif HAVE_FSSPEC
01494 
01495     FT_Error      error;
01496     FT_Open_Args  args;
01497     OSErr         err;
01498     UInt8         pathname[PATH_MAX];
01499 
01500 
01501     if ( !spec )
01502       return FT_Err_Invalid_Argument;
01503 
01504     err = FT_FSpMakePath( spec, pathname, sizeof ( pathname ) );
01505     if ( err )
01506       error = FT_Err_Cannot_Open_Resource;
01507 
01508     error = FT_New_Face_From_Resource( library, pathname, face_index, aface );
01509     if ( error != 0 || *aface != NULL )
01510       return error;
01511 
01512     /* fallback to datafork font */
01513     args.flags    = FT_OPEN_PATHNAME;
01514     args.pathname = (char*)pathname;
01515     return FT_Open_Face( library, &args, face_index, aface );
01516 
01517 #else
01518 
01519     FT_UNUSED( library );
01520     FT_UNUSED( spec );
01521     FT_UNUSED( face_index );
01522     FT_UNUSED( aface );
01523 
01524     return FT_Err_Unimplemented_Feature;
01525 
01526 #endif /* HAVE_FSREF, HAVE_FSSPEC */
01527 
01528   }
01529 
01530 
01531 /* END */

Generated on Tue Jul 5 14:13:34 2011 for ROOT_528-00b_version by  doxygen 1.5.1