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 #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
00073
00074
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>
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
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
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
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
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
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
00139 #ifndef HAVE_ATS
00140 #if TARGET_API_MAC_OSX
00141 #define HAVE_ATS 1
00142 #ifndef kATSOptionFlagsUnRestrictedScope
00143 #define kATSOptionFlagsUnRestrictedScope kATSOptionFlagsDefault
00144 #endif
00145 #else
00146 #define HAVE_ATS 0
00147 #endif
00148 #endif
00149
00150
00151
00152
00153
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
00162
00163 #if ( HAVE_TYPE_RESOURCE_INDEX == 0 )
00164 typedef short ResourceIndex;
00165 #endif
00166
00167
00168
00169
00170 #ifndef PREFER_LWFN
00171 #define PREFER_LWFN 1
00172 #endif
00173
00174
00175 #if !HAVE_QUICKDRAW_CARBON
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
00219 FMGetFontFamilyName( family, famNameStr );
00220 CopyPascalStringToC( famNameStr, famName );
00221
00222
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
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
00250 if ( ft_strcmp( fullName, fontName ) == 0 )
00251 {
00252
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
00276
00277
00278 #if HAVE_ATS
00279
00280
00281
00282
00283
00284
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
00331
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
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
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
00468
00469
00470 #if HAVE_FSSPEC && !HAVE_FSREF
00471
00472
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
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
00585 err = FSOpenResourceFile( &ref, 0, NULL, fsRdPerm, res );
00586 if ( noErr == err )
00587 return err;
00588
00589
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
00603
00604 *res = FSpOpenResFile( &spec, fsRdPerm );
00605 err = ResError();
00606
00607 #endif
00608
00609 return err;
00610 }
00611
00612
00613
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
00648
00649 }
00650
00651
00652
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
00687
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
00718
00719
00720
00721
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
00745 if ( 47 < face_index )
00746 return;
00747
00748
00749 if ( face_index < count_faces_sfnt( fond_data ) )
00750 {
00751 assoc += face_index;
00752
00753
00754
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
00846
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
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
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
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
00956
00957
00958
00959
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
00979
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;
00988
00989 code = (*post_data)[0];
00990
00991 if ( code != last_code )
00992 {
00993 if ( code == 5 )
00994 total_size += 2;
00995 else
00996 total_size += 6;
00997 }
00998
00999 total_size += GetHandleSize( post_data ) - 2;
01000 last_code = code;
01001
01002
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
01016
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;
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
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;
01049 else if ( code == 2 )
01050 *p++ = 0x02;
01051 else
01052 *p++ = 0x01;
01053
01054 if ( code != 5 )
01055 {
01056 size_p = p;
01057 p += 4;
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
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 );
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
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
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
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
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
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
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
01354
01355
01356
01357 error = FT_New_Face_From_Suitcase( library, pathname, face_index, aface );
01358 if ( error == 0 )
01359 return error;
01360
01361
01362
01363 *aface = NULL;
01364 return 0;
01365 }
01366
01367
01368
01369
01370
01371
01372
01373
01374
01375
01376
01377
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
01390 if ( !pathname )
01391 return FT_Err_Invalid_Argument;
01392
01393 error = FT_Err_Ok;
01394 *aface = NULL;
01395
01396
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
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
01412
01413
01414
01415
01416
01417
01418
01419
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
01456 args.flags = FT_OPEN_PATHNAME;
01457 args.pathname = (char*)pathname;
01458 return FT_Open_Face( library, &args, face_index, aface );
01459
01460 #endif
01461
01462 }
01463
01464
01465
01466
01467
01468
01469
01470
01471
01472
01473
01474
01475
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
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
01527
01528 }
01529
01530
01531