00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024   
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 
00034 
00035 
00036 
00037 
00038 
00039 
00040 
00041 
00042 
00043 
00044 
00045 
00046 
00047 
00048 
00049 
00050 
00051 
00052 
00053 
00054 
00055 
00056 
00057 
00058 
00059 
00060 
00061 
00062 
00063 
00064 
00065 
00066 
00067 
00068 
00069 #include <ft2build.h>
00070 #include FT_FREETYPE_H
00071 #include FT_TRUETYPE_TAGS_H
00072 #include FT_INTERNAL_STREAM_H
00073 #include "ftbase.h"
00074 
00075   
00076   
00077   
00078 #if !HAVE_ANSI_OS_INLINE
00079 #undef  OS_INLINE
00080 #define OS_INLINE  static __inline__
00081 #endif
00082 
00083   
00084   
00085   
00086   
00087 #ifndef HAVE_TYPE_RESOURCE_INDEX
00088 #if !defined( MAC_OS_X_VERSION_10_5 ) || \
00089     ( MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5 )
00090 #define HAVE_TYPE_RESOURCE_INDEX 0
00091 #else
00092 #define HAVE_TYPE_RESOURCE_INDEX 1
00093 #endif
00094 #endif 
00095 
00096 #if ( HAVE_TYPE_RESOURCE_INDEX == 0 )
00097   typedef short  ResourceIndex;
00098 #endif
00099 
00100 #include <CoreServices/CoreServices.h>
00101 #include <ApplicationServices/ApplicationServices.h>
00102 #include <sys/syslimits.h> 
00103 
00104   
00105 #define FT_DEPRECATED_ATTRIBUTE
00106 
00107 #include FT_MAC_H
00108 
00109 #ifndef kATSOptionFlagsUnRestrictedScope 
00110 #define kATSOptionFlagsUnRestrictedScope kATSOptionFlagsDefault
00111 #endif
00112 
00113 
00114   
00115 
00116 
00117 #ifndef PREFER_LWFN
00118 #define PREFER_LWFN  1
00119 #endif
00120 
00121 
00122   
00123   FT_EXPORT_DEF( FT_Error )
00124   FT_GetFile_From_Mac_Name( const char*  fontName,
00125                             FSSpec*      pathSpec,
00126                             FT_Long*     face_index )
00127   {
00128     FT_UNUSED( fontName );
00129     FT_UNUSED( pathSpec );
00130     FT_UNUSED( face_index );
00131 
00132     return FT_Err_Unimplemented_Feature;
00133   }
00134 
00135 
00136   
00137   
00138   
00139   
00140   
00141   static OSStatus
00142   FT_ATSFontGetFileReference( ATSFontRef  ats_font_id,
00143                               FSRef*      ats_font_ref )
00144   {
00145 #if defined( MAC_OS_X_VERSION_10_5 ) && \
00146     ( MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 )
00147  
00148     OSStatus  err;
00149 
00150     err = ATSFontGetFileReference( ats_font_id, ats_font_ref );
00151 
00152     return err;
00153 #elif __LP64__ 
00154     FT_UNUSED( ats_font_id );
00155     FT_UNUSED( ats_font_ref );
00156 
00157 
00158     return fnfErr;
00159 #else 
00160     OSStatus  err;
00161     FSSpec    spec;
00162 
00163 
00164     err = ATSFontGetFileSpecification( ats_font_id, &spec );
00165     if ( noErr == err )
00166       err = FSpMakeFSRef( &spec, ats_font_ref );
00167 
00168     return err;
00169 #endif
00170   }
00171 
00172 
00173   static FT_Error
00174   FT_GetFileRef_From_Mac_ATS_Name( const char*  fontName,
00175                                    FSRef*       ats_font_ref,
00176                                    FT_Long*     face_index )
00177   {
00178     CFStringRef  cf_fontName;
00179     ATSFontRef   ats_font_id;
00180 
00181 
00182     *face_index = 0;
00183 
00184     cf_fontName = CFStringCreateWithCString( NULL, fontName,
00185                                              kCFStringEncodingMacRoman );
00186     ats_font_id = ATSFontFindFromName( cf_fontName,
00187                                        kATSOptionFlagsUnRestrictedScope );
00188     CFRelease( cf_fontName );
00189 
00190     if ( ats_font_id == 0 || ats_font_id == 0xFFFFFFFFUL )
00191       return FT_Err_Unknown_File_Format;
00192 
00193     if ( noErr != FT_ATSFontGetFileReference( ats_font_id, ats_font_ref ) )
00194       return FT_Err_Unknown_File_Format;
00195 
00196     
00197     
00198     {
00199       ATSFontRef  id2 = ats_font_id - 1;
00200       FSRef       ref2;
00201 
00202 
00203       while ( id2 > 0 )
00204       {
00205         if ( noErr != FT_ATSFontGetFileReference( id2, &ref2 ) )
00206           break;
00207         if ( noErr != FSCompareFSRefs( ats_font_ref, &ref2 ) )
00208           break;
00209 
00210         id2 --;
00211       }
00212       *face_index = ats_font_id - ( id2 + 1 );
00213     }
00214 
00215     return FT_Err_Ok;
00216   }
00217 
00218 
00219   FT_EXPORT_DEF( FT_Error )
00220   FT_GetFilePath_From_Mac_ATS_Name( const char*  fontName,
00221                                     UInt8*       path,
00222                                     UInt32       maxPathSize,
00223                                     FT_Long*     face_index )
00224   {
00225     FSRef     ref;
00226     FT_Error  err;
00227 
00228 
00229     err = FT_GetFileRef_From_Mac_ATS_Name( fontName, &ref, face_index );
00230     if ( FT_Err_Ok != err )
00231       return err;
00232 
00233     if ( noErr != FSRefMakePath( &ref, path, maxPathSize ) )
00234       return FT_Err_Unknown_File_Format;
00235 
00236     return FT_Err_Ok;
00237   }
00238 
00239 
00240   
00241   FT_EXPORT_DEF( FT_Error )
00242   FT_GetFile_From_Mac_ATS_Name( const char*  fontName,
00243                                 FSSpec*      pathSpec,
00244                                 FT_Long*     face_index )
00245   {
00246 #if ( __LP64__ ) || ( defined( MAC_OS_X_VERSION_10_5 ) && \
00247       ( MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 ) )
00248     FT_UNUSED( fontName );
00249     FT_UNUSED( pathSpec );
00250     FT_UNUSED( face_index );
00251 
00252     return FT_Err_Unimplemented_Feature;
00253 #else
00254     FSRef     ref;
00255     FT_Error  err;
00256 
00257 
00258     err = FT_GetFileRef_From_Mac_ATS_Name( fontName, &ref, face_index );
00259     if ( FT_Err_Ok != err )
00260       return err;
00261 
00262     if ( noErr != FSGetCatalogInfo( &ref, kFSCatInfoNone, NULL, NULL,
00263                                     pathSpec, NULL ) )
00264       return FT_Err_Unknown_File_Format;
00265 
00266     return FT_Err_Ok;
00267 #endif
00268   }
00269 
00270 
00271   static OSErr
00272   FT_FSPathMakeRes( const UInt8*    pathname,
00273                     ResFileRefNum*  res )
00274   {
00275     OSErr  err;
00276     FSRef  ref;
00277 
00278 
00279     if ( noErr != FSPathMakeRef( pathname, &ref, FALSE ) )
00280       return FT_Err_Cannot_Open_Resource;
00281 
00282     
00283     err = FSOpenResourceFile( &ref, 0, NULL, fsRdPerm, res );
00284     if ( noErr == err )
00285       return err;
00286 
00287     
00288     *res = FSOpenResFile( &ref, fsRdPerm );
00289     err  = ResError();
00290 
00291     return err;
00292   }
00293 
00294 
00295   
00296   static OSType
00297   get_file_type_from_path( const UInt8*  pathname )
00298   {
00299     FSRef          ref;
00300     FSCatalogInfo  info;
00301 
00302 
00303     if ( noErr != FSPathMakeRef( pathname, &ref, FALSE ) )
00304       return ( OSType ) 0;
00305 
00306     if ( noErr != FSGetCatalogInfo( &ref, kFSCatInfoFinderInfo, &info,
00307                                     NULL, NULL, NULL ) )
00308       return ( OSType ) 0;
00309 
00310     return ((FInfo *)(info.finderInfo))->fdType;
00311   }
00312 
00313 
00314   
00315   static void
00316   create_lwfn_name( char*   ps_name,
00317                     Str255  lwfn_file_name )
00318   {
00319     int       max = 5, count = 0;
00320     FT_Byte*  p = lwfn_file_name;
00321     FT_Byte*  q = (FT_Byte*)ps_name;
00322 
00323 
00324     lwfn_file_name[0] = 0;
00325 
00326     while ( *q )
00327     {
00328       if ( ft_isupper( *q ) )
00329       {
00330         if ( count )
00331           max = 3;
00332         count = 0;
00333       }
00334       if ( count < max && ( ft_isalnum( *q ) || *q == '_' ) )
00335       {
00336         *++p = *q;
00337         lwfn_file_name[0]++;
00338         count++;
00339       }
00340       q++;
00341     }
00342   }
00343 
00344 
00345   static short
00346   count_faces_sfnt( char*  fond_data )
00347   {
00348     
00349     
00350 
00351     return EndianS16_BtoN( *( (short*)( fond_data +
00352                                         sizeof ( FamRec ) ) ) ) + 1;
00353   }
00354 
00355 
00356   static short
00357   count_faces_scalable( char*  fond_data )
00358   {
00359     AsscEntry*  assoc;
00360     FamRec*     fond;
00361     short       i, face, face_all;
00362 
00363 
00364     fond     = (FamRec*)fond_data;
00365     face_all = EndianS16_BtoN( *( (short *)( fond_data +
00366                                              sizeof ( FamRec ) ) ) ) + 1;
00367     assoc    = (AsscEntry*)( fond_data + sizeof ( FamRec ) + 2 );
00368     face     = 0;
00369 
00370     for ( i = 0; i < face_all; i++ )
00371     {
00372       if ( 0 == EndianS16_BtoN( assoc[i].fontSize ) )
00373         face++;
00374     }
00375     return face;
00376   }
00377 
00378 
00379   
00380 
00381 
00382 
00383 
00384 
00385 
00386 
00387   static void
00388   parse_fond( char*   fond_data,
00389               short*  have_sfnt,
00390               ResID*  sfnt_id,
00391               Str255  lwfn_file_name,
00392               short   face_index )
00393   {
00394     AsscEntry*  assoc;
00395     AsscEntry*  base_assoc;
00396     FamRec*     fond;
00397 
00398 
00399     *sfnt_id          = 0;
00400     *have_sfnt        = 0;
00401     lwfn_file_name[0] = 0;
00402 
00403     fond       = (FamRec*)fond_data;
00404     assoc      = (AsscEntry*)( fond_data + sizeof ( FamRec ) + 2 );
00405     base_assoc = assoc;
00406 
00407     
00408     if ( 47 < face_index )
00409       return;
00410 
00411     
00412     if ( face_index < count_faces_sfnt( fond_data ) )
00413     {
00414       assoc += face_index;        
00415 
00416       
00417 
00418       if ( EndianS16_BtoN( assoc->fontSize ) == 0 )
00419       {
00420         *have_sfnt = 1;
00421         *sfnt_id   = EndianS16_BtoN( assoc->fontID );
00422       }
00423       else if ( base_assoc->fontSize == 0 )
00424       {
00425         *have_sfnt = 1;
00426         *sfnt_id   = EndianS16_BtoN( base_assoc->fontID );
00427       }
00428     }
00429 
00430     if ( EndianS32_BtoN( fond->ffStylOff ) )
00431     {
00432       unsigned char*  p = (unsigned char*)fond_data;
00433       StyleTable*     style;
00434       unsigned short  string_count;
00435       char            ps_name[256];
00436       unsigned char*  names[64];
00437       int             i;
00438 
00439 
00440       p += EndianS32_BtoN( fond->ffStylOff );
00441       style = (StyleTable*)p;
00442       p += sizeof ( StyleTable );
00443       string_count = EndianS16_BtoN( *(short*)(p) );
00444       p += sizeof ( short );
00445 
00446       for ( i = 0; i < string_count && i < 64; i++ )
00447       {
00448         names[i] = p;
00449         p       += names[i][0];
00450         p++;
00451       }
00452 
00453       {
00454         size_t  ps_name_len = (size_t)names[0][0];
00455 
00456 
00457         if ( ps_name_len != 0 )
00458         {
00459           ft_memcpy(ps_name, names[0] + 1, ps_name_len);
00460           ps_name[ps_name_len] = 0;
00461         }
00462         if ( style->indexes[face_index] > 1 &&
00463              style->indexes[face_index] <= FT_MIN( string_count, 64 ) )
00464         {
00465           unsigned char*  suffixes = names[style->indexes[face_index] - 1];
00466 
00467 
00468           for ( i = 1; i <= suffixes[0]; i++ )
00469           {
00470             unsigned char*  s;
00471             size_t          j = suffixes[i] - 1;
00472 
00473 
00474             if ( j < string_count && ( s = names[j] ) != NULL )
00475             {
00476               size_t  s_len = (size_t)s[0];
00477 
00478 
00479               if ( s_len != 0 && ps_name_len + s_len < sizeof ( ps_name ) )
00480               {
00481                 ft_memcpy( ps_name + ps_name_len, s + 1, s_len );
00482                 ps_name_len += s_len;
00483                 ps_name[ps_name_len] = 0;
00484               }
00485             }
00486           }
00487         }
00488       }
00489 
00490       create_lwfn_name( ps_name, lwfn_file_name );
00491     }
00492   }
00493 
00494 
00495   static  FT_Error
00496   lookup_lwfn_by_fond( const UInt8*      path_fond,
00497                        ConstStr255Param  base_lwfn,
00498                        UInt8*            path_lwfn,
00499                        size_t            path_size )
00500   {
00501     FSRef   ref, par_ref;
00502     size_t  dirname_len;
00503 
00504 
00505     
00506     
00507 
00508     if ( noErr != FSPathMakeRef( path_fond, &ref, FALSE ) )
00509       return FT_Err_Invalid_Argument;
00510 
00511     if ( noErr != FSGetCatalogInfo( &ref, kFSCatInfoNone,
00512                                     NULL, NULL, NULL, &par_ref ) )
00513       return FT_Err_Invalid_Argument;
00514 
00515     if ( noErr != FSRefMakePath( &par_ref, path_lwfn, path_size ) )
00516       return FT_Err_Invalid_Argument;
00517 
00518     if ( ft_strlen( (char *)path_lwfn ) + 1 + base_lwfn[0] > path_size )
00519       return FT_Err_Invalid_Argument;
00520 
00521     
00522     ft_strcat( (char *)path_lwfn, "/" );
00523     dirname_len = ft_strlen( (char *)path_lwfn );
00524     ft_strcat( (char *)path_lwfn, (char *)base_lwfn + 1 );
00525     path_lwfn[dirname_len + base_lwfn[0]] = '\0';
00526 
00527     if ( noErr != FSPathMakeRef( path_lwfn, &ref, FALSE ) )
00528       return FT_Err_Cannot_Open_Resource;
00529 
00530     if ( noErr != FSGetCatalogInfo( &ref, kFSCatInfoNone,
00531                                     NULL, NULL, NULL, NULL ) )
00532       return FT_Err_Cannot_Open_Resource;
00533 
00534     return FT_Err_Ok;
00535   }
00536 
00537 
00538   static short
00539   count_faces( Handle        fond,
00540                const UInt8*  pathname )
00541   {
00542     ResID     sfnt_id;
00543     short     have_sfnt, have_lwfn;
00544     Str255    lwfn_file_name;
00545     UInt8     buff[PATH_MAX];
00546     FT_Error  err;
00547     short     num_faces;
00548 
00549 
00550     have_sfnt = have_lwfn = 0;
00551 
00552     parse_fond( *fond, &have_sfnt, &sfnt_id, lwfn_file_name, 0 );
00553 
00554     if ( lwfn_file_name[0] )
00555     {
00556       err = lookup_lwfn_by_fond( pathname, lwfn_file_name,
00557                                  buff, sizeof ( buff )  );
00558       if ( FT_Err_Ok == err )
00559         have_lwfn = 1;
00560     }
00561 
00562     if ( have_lwfn && ( !have_sfnt || PREFER_LWFN ) )
00563       num_faces = 1;
00564     else
00565       num_faces = count_faces_scalable( *fond );
00566 
00567     return num_faces;
00568   }
00569 
00570 
00571   
00572 
00573 
00574 
00575 
00576   static FT_Error
00577   read_lwfn( FT_Memory      memory,
00578              ResFileRefNum  res,
00579              FT_Byte**      pfb_data,
00580              FT_ULong*      size )
00581   {
00582     FT_Error       error = FT_Err_Ok;
00583     ResID          res_id;
00584     unsigned char  *buffer, *p, *size_p = NULL;
00585     FT_ULong       total_size = 0;
00586     FT_ULong       old_total_size = 0;
00587     FT_ULong       post_size, pfb_chunk_size;
00588     Handle         post_data;
00589     char           code, last_code;
00590 
00591 
00592     UseResFile( res );
00593 
00594     
00595     
00596     res_id    = 501;
00597     last_code = -1;
00598 
00599     for (;;)
00600     {
00601       post_data = Get1Resource( TTAG_POST, res_id++ );
00602       if ( post_data == NULL )
00603         break;  
00604 
00605       code = (*post_data)[0];
00606 
00607       if ( code != last_code )
00608       {
00609         if ( code == 5 )
00610           total_size += 2; 
00611         else
00612           total_size += 6; 
00613       }
00614 
00615       total_size += GetHandleSize( post_data ) - 2;
00616       last_code = code;
00617 
00618       
00619       if ( total_size < old_total_size )
00620       {
00621         error = FT_Err_Array_Too_Large;
00622         goto Error;
00623       }
00624 
00625       old_total_size = total_size;
00626     }
00627 
00628     if ( FT_ALLOC( buffer, (FT_Long)total_size ) )
00629       goto Error;
00630 
00631     
00632     
00633     p              = buffer;
00634     res_id         = 501;
00635     last_code      = -1;
00636     pfb_chunk_size = 0;
00637 
00638     for (;;)
00639     {
00640       post_data = Get1Resource( TTAG_POST, res_id++ );
00641       if ( post_data == NULL )
00642         break;  
00643 
00644       post_size = (FT_ULong)GetHandleSize( post_data ) - 2;
00645       code = (*post_data)[0];
00646 
00647       if ( code != last_code )
00648       {
00649         if ( last_code != -1 )
00650         {
00651           
00652           if ( size_p != NULL )
00653           {
00654             *size_p++ = (FT_Byte)(   pfb_chunk_size         & 0xFF );
00655             *size_p++ = (FT_Byte)( ( pfb_chunk_size >> 8  ) & 0xFF );
00656             *size_p++ = (FT_Byte)( ( pfb_chunk_size >> 16 ) & 0xFF );
00657             *size_p++ = (FT_Byte)( ( pfb_chunk_size >> 24 ) & 0xFF );
00658           }
00659           pfb_chunk_size = 0;
00660         }
00661 
00662         *p++ = 0x80;
00663         if ( code == 5 )
00664           *p++ = 0x03;  
00665         else if ( code == 2 )
00666           *p++ = 0x02;  
00667         else
00668           *p++ = 0x01;  
00669 
00670         if ( code != 5 )
00671         {
00672           size_p = p;   
00673           p += 4;       
00674         }
00675       }
00676 
00677       ft_memcpy( p, *post_data + 2, post_size );
00678       pfb_chunk_size += post_size;
00679       p += post_size;
00680       last_code = code;
00681     }
00682 
00683     *pfb_data = buffer;
00684     *size = total_size;
00685 
00686   Error:
00687     CloseResFile( res );
00688     return error;
00689   }
00690 
00691 
00692   
00693   static FT_Error
00694   FT_New_Face_From_LWFN( FT_Library    library,
00695                          const UInt8*  pathname,
00696                          FT_Long       face_index,
00697                          FT_Face*      aface )
00698   {
00699     FT_Byte*       pfb_data;
00700     FT_ULong       pfb_size;
00701     FT_Error       error;
00702     ResFileRefNum  res;
00703 
00704 
00705     if ( noErr != FT_FSPathMakeRes( pathname, &res ) )
00706       return FT_Err_Cannot_Open_Resource;
00707 
00708     pfb_data = NULL;
00709     pfb_size = 0;
00710     error = read_lwfn( library->memory, res, &pfb_data, &pfb_size );
00711     CloseResFile( res ); 
00712     if ( error )
00713       return error;
00714 
00715     return open_face_from_buffer( library,
00716                                   pfb_data,
00717                                   pfb_size,
00718                                   face_index,
00719                                   "type1",
00720                                   aface );
00721   }
00722 
00723 
00724   
00725   static FT_Error
00726   FT_New_Face_From_SFNT( FT_Library  library,
00727                          ResID       sfnt_id,
00728                          FT_Long     face_index,
00729                          FT_Face*    aface )
00730   {
00731     Handle     sfnt = NULL;
00732     FT_Byte*   sfnt_data;
00733     size_t     sfnt_size;
00734     FT_Error   error  = FT_Err_Ok;
00735     FT_Memory  memory = library->memory;
00736     int        is_cff, is_sfnt_ps;
00737 
00738 
00739     sfnt = GetResource( TTAG_sfnt, sfnt_id );
00740     if ( sfnt == NULL )
00741       return FT_Err_Invalid_Handle;
00742 
00743     sfnt_size = (FT_ULong)GetHandleSize( sfnt );
00744     if ( FT_ALLOC( sfnt_data, (FT_Long)sfnt_size ) )
00745     {
00746       ReleaseResource( sfnt );
00747       return error;
00748     }
00749 
00750     ft_memcpy( sfnt_data, *sfnt, sfnt_size );
00751     ReleaseResource( sfnt );
00752 
00753     is_cff     = sfnt_size > 4 && !ft_memcmp( sfnt_data, "OTTO", 4 );
00754     is_sfnt_ps = sfnt_size > 4 && !ft_memcmp( sfnt_data, "typ1", 4 );
00755 
00756     if ( is_sfnt_ps )
00757     {
00758       FT_Stream  stream;
00759 
00760 
00761       if ( FT_NEW( stream ) )
00762         goto Try_OpenType;
00763 
00764       FT_Stream_OpenMemory( stream, sfnt_data, sfnt_size );
00765       if ( !open_face_PS_from_sfnt_stream( library,
00766                                            stream,
00767                                            face_index,
00768                                            0, NULL,
00769                                            aface ) )
00770       {
00771         FT_Stream_Close( stream );
00772         FT_FREE( stream );
00773         FT_FREE( sfnt_data );
00774         goto Exit;
00775       }
00776 
00777       FT_FREE( stream );
00778     }
00779   Try_OpenType:
00780     error = open_face_from_buffer( library,
00781                                    sfnt_data,
00782                                    sfnt_size,
00783                                    face_index,
00784                                    is_cff ? "cff" : "truetype",
00785                                    aface );
00786   Exit:
00787     return error;
00788   }
00789 
00790 
00791   
00792   static FT_Error
00793   FT_New_Face_From_Suitcase( FT_Library    library,
00794                              const UInt8*  pathname,
00795                              FT_Long       face_index,
00796                              FT_Face*      aface )
00797   {
00798     FT_Error       error = FT_Err_Cannot_Open_Resource;
00799     ResFileRefNum  res_ref;
00800     ResourceIndex  res_index;
00801     Handle         fond;
00802     short          num_faces_in_res, num_faces_in_fond;
00803 
00804 
00805     if ( noErr != FT_FSPathMakeRes( pathname, &res_ref ) )
00806       return FT_Err_Cannot_Open_Resource;
00807 
00808     UseResFile( res_ref );
00809     if ( ResError() )
00810       return FT_Err_Cannot_Open_Resource;
00811 
00812     num_faces_in_res = 0;
00813     for ( res_index = 1; ; ++res_index )
00814     {
00815       fond = Get1IndResource( TTAG_FOND, res_index );
00816       if ( ResError() )
00817         break;
00818 
00819       num_faces_in_fond  = count_faces( fond, pathname );
00820       num_faces_in_res  += num_faces_in_fond;
00821 
00822       if ( 0 <= face_index && face_index < num_faces_in_fond && error )
00823         error = FT_New_Face_From_FOND( library, fond, face_index, aface );
00824 
00825       face_index -= num_faces_in_fond;
00826     }
00827 
00828     CloseResFile( res_ref );
00829     if ( FT_Err_Ok == error && NULL != aface && NULL != *aface )
00830       (*aface)->num_faces = num_faces_in_res;
00831     return error;
00832   }
00833 
00834 
00835   
00836 
00837   FT_EXPORT_DEF( FT_Error )
00838   FT_New_Face_From_FOND( FT_Library  library,
00839                          Handle      fond,
00840                          FT_Long     face_index,
00841                          FT_Face*    aface )
00842   {
00843     short     have_sfnt, have_lwfn = 0;
00844     ResID     sfnt_id, fond_id;
00845     OSType    fond_type;
00846     Str255    fond_name;
00847     Str255    lwfn_file_name;
00848     UInt8     path_lwfn[PATH_MAX];
00849     OSErr     err;
00850     FT_Error  error = FT_Err_Ok;
00851 
00852 
00853     GetResInfo( fond, &fond_id, &fond_type, fond_name );
00854     if ( ResError() != noErr || fond_type != TTAG_FOND )
00855       return FT_Err_Invalid_File_Format;
00856 
00857     parse_fond( *fond, &have_sfnt, &sfnt_id, lwfn_file_name, face_index );
00858 
00859     if ( lwfn_file_name[0] )
00860     {
00861       ResFileRefNum  res;
00862 
00863 
00864       res = HomeResFile( fond );
00865       if ( noErr != ResError() )
00866         goto found_no_lwfn_file;
00867 
00868       {
00869         UInt8  path_fond[PATH_MAX];
00870         FSRef  ref;
00871 
00872 
00873         err = FSGetForkCBInfo( res, kFSInvalidVolumeRefNum,
00874                                NULL, NULL, NULL, &ref, NULL );
00875         if ( noErr != err )
00876           goto found_no_lwfn_file;
00877 
00878         err = FSRefMakePath( &ref, path_fond, sizeof ( path_fond ) );
00879         if ( noErr != err )
00880           goto found_no_lwfn_file;
00881 
00882         error = lookup_lwfn_by_fond( path_fond, lwfn_file_name,
00883                                      path_lwfn, sizeof ( path_lwfn ) );
00884         if ( FT_Err_Ok == error )
00885           have_lwfn = 1;
00886       }
00887     }
00888 
00889     if ( have_lwfn && ( !have_sfnt || PREFER_LWFN ) )
00890       error = FT_New_Face_From_LWFN( library,
00891                                      path_lwfn,
00892                                      face_index,
00893                                      aface );
00894     else
00895       error = FT_Err_Unknown_File_Format;
00896 
00897   found_no_lwfn_file:
00898     if ( have_sfnt && FT_Err_Ok != error )
00899       error = FT_New_Face_From_SFNT( library,
00900                                      sfnt_id,
00901                                      face_index,
00902                                      aface );
00903 
00904     return error;
00905   }
00906 
00907 
00908   
00909   static FT_Error
00910   FT_New_Face_From_Resource( FT_Library    library,
00911                              const UInt8*  pathname,
00912                              FT_Long       face_index,
00913                              FT_Face*      aface )
00914   {
00915     OSType    file_type;
00916     FT_Error  error;
00917 
00918 
00919     
00920     file_type = get_file_type_from_path( pathname );
00921     if ( file_type == TTAG_LWFN )
00922       return FT_New_Face_From_LWFN( library, pathname, face_index, aface );
00923 
00924     
00925     
00926     
00927 
00928     error = FT_New_Face_From_Suitcase( library, pathname, face_index, aface );
00929     if ( error == 0 )
00930       return error;
00931 
00932     
00933     
00934     *aface = NULL;
00935     return 0;
00936   }
00937 
00938 
00939   
00940   
00941   
00942   
00943   
00944   
00945   
00946   
00947   
00948   
00949   
00950   FT_EXPORT_DEF( FT_Error )
00951   FT_New_Face( FT_Library   library,
00952                const char*  pathname,
00953                FT_Long      face_index,
00954                FT_Face*     aface )
00955   {
00956     FT_Open_Args  args;
00957     FT_Error      error;
00958 
00959 
00960     
00961     if ( !pathname )
00962       return FT_Err_Invalid_Argument;
00963 
00964     error  = FT_Err_Ok;
00965     *aface = NULL;
00966 
00967     
00968     error = FT_New_Face_From_Resource( library, (UInt8 *)pathname,
00969                                        face_index, aface );
00970     if ( error != 0 || *aface != NULL )
00971       return error;
00972 
00973     
00974     args.flags    = FT_OPEN_PATHNAME;
00975     args.pathname = (char*)pathname;
00976     return FT_Open_Face( library, &args, face_index, aface );
00977   }
00978 
00979 
00980   
00981   
00982   
00983   
00984   
00985   
00986   
00987   
00988   
00989   
00990   
00991   FT_EXPORT_DEF( FT_Error )
00992   FT_New_Face_From_FSRef( FT_Library    library,
00993                           const FSRef*  ref,
00994                           FT_Long       face_index,
00995                           FT_Face*      aface )
00996   {
00997     FT_Error      error;
00998     FT_Open_Args  args;
00999     OSErr   err;
01000     UInt8   pathname[PATH_MAX];
01001 
01002 
01003     if ( !ref )
01004       return FT_Err_Invalid_Argument;
01005 
01006     err = FSRefMakePath( ref, pathname, sizeof ( pathname ) );
01007     if ( err )
01008       error = FT_Err_Cannot_Open_Resource;
01009 
01010     error = FT_New_Face_From_Resource( library, pathname, face_index, aface );
01011     if ( error != 0 || *aface != NULL )
01012       return error;
01013 
01014     
01015     args.flags    = FT_OPEN_PATHNAME;
01016     args.pathname = (char*)pathname;
01017     return FT_Open_Face( library, &args, face_index, aface );
01018   }
01019 
01020 
01021   
01022   
01023   
01024   
01025   
01026   
01027   
01028   
01029   
01030   
01031   FT_EXPORT_DEF( FT_Error )
01032   FT_New_Face_From_FSSpec( FT_Library     library,
01033                            const FSSpec*  spec,
01034                            FT_Long        face_index,
01035                            FT_Face*       aface )
01036   {
01037 #if ( __LP64__ ) || ( defined( MAC_OS_X_VERSION_10_5 ) && \
01038       ( MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 ) )
01039     FT_UNUSED( library );
01040     FT_UNUSED( spec );
01041     FT_UNUSED( face_index );
01042     FT_UNUSED( aface );
01043 
01044     return FT_Err_Unimplemented_Feature;
01045 #else
01046     FSRef  ref;
01047 
01048 
01049     if ( !spec || FSpMakeFSRef( spec, &ref ) != noErr )
01050       return FT_Err_Invalid_Argument;
01051     else
01052       return FT_New_Face_From_FSRef( library, &ref, face_index, aface );
01053 #endif
01054   }
01055 
01056 
01057