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 modified by mpsuzuki, George Williams, and Sean McBride.       */
00007 /*                                                                         */
00008 /*  This file is for Mac OS X only; see builds/mac/ftoldmac.c for          */
00009 /*  classic platforms built by MPW.                                        */
00010 /*                                                                         */
00011 /*  Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,         */
00012 /*            2009 by                                                      */
00013 /*  Just van Rossum, David Turner, Robert Wilhelm, and Werner Lemberg.     */
00014 /*                                                                         */
00015 /*  This file is part of the FreeType project, and may only be used,       */
00016 /*  modified, and distributed under the terms of the FreeType project      */
00017 /*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
00018 /*  this file you indicate that you have read the license and              */
00019 /*  understand and accept it fully.                                        */
00020 /*                                                                         */
00021 /***************************************************************************/
00022 
00023 
00024   /*
00025     Notes
00026 
00027     Mac suitcase files can (and often do!) contain multiple fonts.  To
00028     support this I use the face_index argument of FT_(Open|New)_Face()
00029     functions, and pretend the suitcase file is a collection.
00030 
00031     Warning: fbit and NFNT bitmap resources are not supported yet.  In old
00032     sfnt fonts, bitmap glyph data for each size is stored in each `NFNT'
00033     resources instead of the `bdat' table in the sfnt resource.  Therefore,
00034     face->num_fixed_sizes is set to 0, because bitmap data in `NFNT'
00035     resource is unavailable at present.
00036 
00037     The Mac FOND support works roughly like this:
00038 
00039     - Check whether the offered stream points to a Mac suitcase file.  This
00040       is done by checking the file type: it has to be 'FFIL' or 'tfil'.  The
00041       stream that gets passed to our init_face() routine is a stdio stream,
00042       which isn't usable for us, since the FOND resources live in the
00043       resource fork.  So we just grab the stream->pathname field.
00044 
00045     - Read the FOND resource into memory, then check whether there is a
00046       TrueType font and/or(!) a Type 1 font available.
00047 
00048     - If there is a Type 1 font available (as a separate `LWFN' file), read
00049       its data into memory, massage it slightly so it becomes PFB data, wrap
00050       it into a memory stream, load the Type 1 driver and delegate the rest
00051       of the work to it by calling FT_Open_Face().  (XXX TODO: after this
00052       has been done, the kerning data from the FOND resource should be
00053       appended to the face: On the Mac there are usually no AFM files
00054       available.  However, this is tricky since we need to map Mac char
00055       codes to ps glyph names to glyph ID's...)
00056 
00057     - If there is a TrueType font (an `sfnt' resource), read it into memory,
00058       wrap it into a memory stream, load the TrueType driver and delegate
00059       the rest of the work to it, by calling FT_Open_Face().
00060 
00061     - Some suitcase fonts (notably Onyx) might point the `LWFN' file to
00062       itself, even though it doesn't contains `POST' resources.  To handle
00063       this special case without opening the file an extra time, we just
00064       ignore errors from the `LWFN' and fallback to the `sfnt' if both are
00065       available.
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   /* This is for Mac OS X.  Without redefinition, OS_INLINE */
00076   /* expands to `static inline' which doesn't survive the   */
00077   /* -ansi compilation flag of GCC.                         */
00078 #if !HAVE_ANSI_OS_INLINE
00079 #undef  OS_INLINE
00080 #define OS_INLINE  static __inline__
00081 #endif
00082 
00083   /* `configure' checks the availability of `ResourceIndex' strictly */
00084   /* and sets HAVE_TYPE_RESOURCE_INDEX 1 or 0 always.  If it is      */
00085   /* not set (e.g., a build without `configure'), the availability   */
00086   /* is guessed from the SDK version.                                */
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 /* !HAVE_TYPE_RESOURCE_INDEX */
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> /* PATH_MAX */
00103 
00104   /* Don't want warnings about our own use of deprecated functions. */
00105 #define FT_DEPRECATED_ATTRIBUTE
00106 
00107 #include FT_MAC_H
00108 
00109 #ifndef kATSOptionFlagsUnRestrictedScope /* since Mac OS X 10.1 */
00110 #define kATSOptionFlagsUnRestrictedScope kATSOptionFlagsDefault
00111 #endif
00112 
00113 
00114   /* Set PREFER_LWFN to 1 if LWFN (Type 1) is preferred over
00115      TrueType in case *both* are available (this is not common,
00116      but it *is* possible). */
00117 #ifndef PREFER_LWFN
00118 #define PREFER_LWFN  1
00119 #endif
00120 
00121 
00122   /* This function is deprecated because FSSpec is deprecated in Mac OS X  */
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   /* Private function.                                         */
00137   /* The FSSpec type has been discouraged for a long time,     */
00138   /* unfortunately an FSRef replacement API for                */
00139   /* ATSFontGetFileSpecification() is only available in        */
00140   /* Mac OS X 10.5 and later.                                  */
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__ /* No 64bit Carbon API on legacy platforms */
00154     FT_UNUSED( ats_font_id );
00155     FT_UNUSED( ats_font_ref );
00156 
00157 
00158     return fnfErr;
00159 #else /* 32bit Carbon API on legacy platforms */
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     /* face_index calculation by searching preceding fontIDs */
00197     /* with same FSRef                                       */
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   /* This function is deprecated because FSSpec is deprecated in Mac OS X  */
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     /* at present, no support for dfont format */
00283     err = FSOpenResourceFile( &ref, 0, NULL, fsRdPerm, res );
00284     if ( noErr == err )
00285       return err;
00286 
00287     /* fallback to original resource-fork font */
00288     *res = FSOpenResFile( &ref, fsRdPerm );
00289     err  = ResError();
00290 
00291     return err;
00292   }
00293 
00294 
00295   /* Return the file type for given pathname */
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   /* Given a PostScript font name, create the Macintosh LWFN file name. */
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     /* The count is 1 greater than the value in the FOND.  */
00349     /* Isn't that cute? :-)                                */
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   /* Look inside the FOND data, answer whether there should be an SFNT
00380      resource, and answer the name of a possible LWFN Type 1 file.
00381 
00382      Thanks to Paul Miller (paulm@profoundeffects.com) for the fix
00383      to load a face OTHER than the first one in the FOND!
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     /* the maximum faces in a FOND is 48, size of StyleTable.indexes[] */
00408     if ( 47 < face_index )
00409       return;
00410 
00411     /* Let's do a little range checking before we get too excited here */
00412     if ( face_index < count_faces_sfnt( fond_data ) )
00413     {
00414       assoc += face_index;        /* add on the face_index! */
00415 
00416       /* if the face at this index is not scalable,
00417          fall back to the first one (old behavior) */
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     /* Pathname for FSRef can be in various formats: HFS, HFS+, and POSIX. */
00506     /* We should not extract parent directory by string manipulation.      */
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     /* now we have absolute dirname in path_lwfn */
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   /* Read Type 1 data from the POST resources inside the LWFN file,
00572      return a PFB buffer.  This is somewhat convoluted because the FT2
00573      PFB parser wants the ASCII header as one chunk, and the LWFN
00574      chunks are often not organized that way, so we glue chunks
00575      of the same type together. */
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     /* First pass: load all POST resources, and determine the size of */
00595     /* the output buffer.                                             */
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;  /* we are done */
00604 
00605       code = (*post_data)[0];
00606 
00607       if ( code != last_code )
00608       {
00609         if ( code == 5 )
00610           total_size += 2; /* just the end code */
00611         else
00612           total_size += 6; /* code + 4 bytes chunk length */
00613       }
00614 
00615       total_size += GetHandleSize( post_data ) - 2;
00616       last_code = code;
00617 
00618       /* detect integer overflows */
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     /* Second pass: append all POST data to the buffer, add PFB fields. */
00632     /* Glue all consecutive chunks of the same type together.           */
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;  /* we are done */
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           /* we are done adding a chunk, fill in the size field */
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;  /* the end */
00665         else if ( code == 2 )
00666           *p++ = 0x02;  /* binary segment */
00667         else
00668           *p++ = 0x01;  /* ASCII segment */
00669 
00670         if ( code != 5 )
00671         {
00672           size_p = p;   /* save for later */
00673           p += 4;       /* make space for size field */
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   /* Create a new FT_Face from a file path to an LWFN file. */
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 ); /* PFB is already loaded, useless anymore */
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   /* Create a new FT_Face from an SFNT resource, specified by res ID. */
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   /* Create a new FT_Face from a file path to a suitcase file. */
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   /* documentation is in ftmac.h */
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   /* Common function to load a new FT_Face from a resource file. */
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     /* LWFN is a (very) specific file format, check for it explicitly */
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     /* Otherwise the file type doesn't matter (there are more than  */
00925     /* `FFIL' and `tfil').  Just try opening it as a font suitcase; */
00926     /* if it works, fine.                                           */
00927 
00928     error = FT_New_Face_From_Suitcase( library, pathname, face_index, aface );
00929     if ( error == 0 )
00930       return error;
00931 
00932     /* let it fall through to normal loader (.ttf, .otf, etc.); */
00933     /* we signal this by returning no error and no FT_Face      */
00934     *aface = NULL;
00935     return 0;
00936   }
00937 
00938 
00939   /*************************************************************************/
00940   /*                                                                       */
00941   /* <Function>                                                            */
00942   /*    FT_New_Face                                                        */
00943   /*                                                                       */
00944   /* <Description>                                                         */
00945   /*    This is the Mac-specific implementation of FT_New_Face.  In        */
00946   /*    addition to the standard FT_New_Face() functionality, it also      */
00947   /*    accepts pathnames to Mac suitcase files.  For further              */
00948   /*    documentation see the original FT_New_Face() in freetype.h.        */
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     /* test for valid `library' and `aface' delayed to FT_Open_Face() */
00961     if ( !pathname )
00962       return FT_Err_Invalid_Argument;
00963 
00964     error  = FT_Err_Ok;
00965     *aface = NULL;
00966 
00967     /* try resourcefork based font: LWFN, FFIL */
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     /* let it fall through to normal loader (.ttf, .otf, etc.) */
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   /* <Function>                                                            */
00983   /*    FT_New_Face_From_FSRef                                             */
00984   /*                                                                       */
00985   /* <Description>                                                         */
00986   /*    FT_New_Face_From_FSRef is identical to FT_New_Face except it       */
00987   /*    accepts an FSRef instead of a path.                                */
00988   /*                                                                       */
00989   /* This function is deprecated because Carbon data types (FSRef)         */
00990   /* are not cross-platform, and thus not suitable for the freetype API.   */
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     /* fallback to datafork font */
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   /* <Function>                                                            */
01024   /*    FT_New_Face_From_FSSpec                                            */
01025   /*                                                                       */
01026   /* <Description>                                                         */
01027   /*    FT_New_Face_From_FSSpec is identical to FT_New_Face except it      */
01028   /*    accepts an FSSpec instead of a path.                               */
01029   /*                                                                       */
01030   /* This function is deprecated because FSSpec is deprecated in Mac OS X  */
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 /* END */

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