Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenftmac.cGo 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 Thu Feb 9 04:59:38 2012 for ReactOS by
1.6.3
|