?? ftmac.c
字號(hào):
return ( OSType ) 0; return ((FInfo *)(info.finderInfo))->fdType;#else FSSpec spec; FInfo finfo; if ( noErr != FT_FSPathMakeSpec( pathname, &spec, FALSE ) ) return ( OSType ) 0; if ( noErr != FSpGetFInfo( &spec, &finfo ) ) return ( OSType ) 0; return finfo.fdType;#endif /* HAVE_FSREF */ } /* Given a PostScript font name, create the Macintosh LWFN file name. */ static void create_lwfn_name( char* ps_name, Str255 lwfn_file_name ) { int max = 5, count = 0; FT_Byte* p = lwfn_file_name; FT_Byte* q = (FT_Byte*)ps_name; lwfn_file_name[0] = 0; while ( *q ) { if ( ft_isupper( *q ) ) { if ( count ) max = 3; count = 0; } if ( count < max && ( ft_isalnum( *q ) || *q == '_' ) ) { *++p = *q; lwfn_file_name[0]++; count++; } q++; } } static short count_faces_sfnt( char* fond_data ) { /* The count is 1 greater than the value in the FOND. */ /* Isn't that cute? :-) */ return 1 + *( (short*)( fond_data + sizeof ( FamRec ) ) ); } static short count_faces_scalable( char* fond_data ) { AsscEntry* assoc; FamRec* fond; short i, face, face_all; fond = (FamRec*)fond_data; face_all = *( (short *)( fond_data + sizeof ( FamRec ) ) ) + 1; assoc = (AsscEntry*)( fond_data + sizeof ( FamRec ) + 2 ); face = 0; for ( i = 0; i < face_all; i++ ) { if ( 0 == assoc[i].fontSize ) face++; } return face; } /* Look inside the FOND data, answer whether there should be an SFNT resource, and answer the name of a possible LWFN Type 1 file. Thanks to Paul Miller (paulm@profoundeffects.com) for the fix to load a face OTHER than the first one in the FOND! */ static void parse_fond( char* fond_data, short* have_sfnt, short* sfnt_id, Str255 lwfn_file_name, short face_index ) { AsscEntry* assoc; AsscEntry* base_assoc; FamRec* fond; *sfnt_id = 0; *have_sfnt = 0; lwfn_file_name[0] = 0; fond = (FamRec*)fond_data; assoc = (AsscEntry*)( fond_data + sizeof ( FamRec ) + 2 ); base_assoc = assoc; /* Let's do a little range checking before we get too excited here */ if ( face_index < count_faces_sfnt( fond_data ) ) { assoc += face_index; /* add on the face_index! */ /* if the face at this index is not scalable, fall back to the first one (old behavior) */ if ( assoc->fontSize == 0 ) { *have_sfnt = 1; *sfnt_id = assoc->fontID; } else if ( base_assoc->fontSize == 0 ) { *have_sfnt = 1; *sfnt_id = base_assoc->fontID; } } if ( fond->ffStylOff ) { unsigned char* p = (unsigned char*)fond_data; StyleTable* style; unsigned short string_count; char ps_name[256]; unsigned char* names[64]; int i; p += fond->ffStylOff; style = (StyleTable*)p; p += sizeof ( StyleTable ); string_count = *(unsigned short*)(p); p += sizeof ( short ); for ( i = 0; i < string_count && i < 64; i++ ) { names[i] = p; p += names[i][0]; p++; } { size_t ps_name_len = (size_t)names[0][0]; if ( ps_name_len != 0 ) { ft_memcpy(ps_name, names[0] + 1, ps_name_len); ps_name[ps_name_len] = 0; } if ( style->indexes[0] > 1 ) { unsigned char* suffixes = names[style->indexes[0] - 1]; for ( i = 1; i <= suffixes[0]; i++ ) { unsigned char* s; size_t j = suffixes[i] - 1; if ( j < string_count && ( s = names[j] ) != NULL ) { size_t s_len = (size_t)s[0]; if ( s_len != 0 && ps_name_len + s_len < sizeof ( ps_name ) ) { ft_memcpy( ps_name + ps_name_len, s + 1, s_len ); ps_name_len += s_len; ps_name[ps_name_len] = 0; } } } } } create_lwfn_name( ps_name, lwfn_file_name ); } } static FT_Error lookup_lwfn_by_fond( const UInt8* path_fond, const StringPtr base_lwfn, UInt8* path_lwfn, int path_size ) {#if HAVE_FSREF FSRef ref, par_ref; int dirname_len; /* Pathname for FSRef can be in various formats: HFS, HFS+, and POSIX. */ /* We should not extract parent directory by string manipulation. */ if ( noErr != FSPathMakeRef( path_fond, &ref, FALSE ) ) return FT_Err_Invalid_Argument; if ( noErr != FSGetCatalogInfo( &ref, kFSCatInfoNone, NULL, NULL, NULL, &par_ref ) ) return FT_Err_Invalid_Argument; if ( noErr != FSRefMakePath( &par_ref, path_lwfn, path_size ) ) return FT_Err_Invalid_Argument; if ( ft_strlen( (char *)path_lwfn ) + 1 + base_lwfn[0] > path_size ) return FT_Err_Invalid_Argument; /* now we have absolute dirname in lookup_path */ if ( path_lwfn[0] == '/' ) ft_strcat( (char *)path_lwfn, "/" ); else ft_strcat( (char *)path_lwfn, ":" ); dirname_len = ft_strlen( (char *)path_lwfn ); ft_strcat( (char *)path_lwfn, (char *)base_lwfn + 1 ); path_lwfn[dirname_len + base_lwfn[0]] = '\0'; if ( noErr != FSPathMakeRef( path_lwfn, &ref, FALSE ) ) return FT_Err_Cannot_Open_Resource; if ( noErr != FSGetCatalogInfo( &ref, kFSCatInfoNone, NULL, NULL, NULL, NULL ) ) return FT_Err_Cannot_Open_Resource; return FT_Err_Ok;#else int i; FSSpec spec; /* pathname for FSSpec is always HFS format */ if ( ft_strlen( (char *)path_fond ) > path_size ) return FT_Err_Invalid_Argument; ft_strcpy( (char *)path_lwfn, (char *)path_fond ); i = ft_strlen( (char *)path_lwfn ) - 1; while ( i > 0 && ':' != path_lwfn[i] ) i--; if ( i + 1 + base_lwfn[0] > path_size ) return FT_Err_Invalid_Argument; if ( ':' == path_lwfn[i] ) { ft_strcpy( (char *)path_lwfn + i + 1, (char *)base_lwfn + 1 ); path_lwfn[i + 1 + base_lwfn[0]] = '\0'; } else { ft_strcpy( (char *)path_lwfn, (char *)base_lwfn + 1 ); path_lwfn[base_lwfn[0]] = '\0'; } if ( noErr != FT_FSPathMakeSpec( path_lwfn, &spec, FALSE ) ) return FT_Err_Cannot_Open_Resource; return FT_Err_Ok;#endif /* HAVE_FSREF */ } static short count_faces( Handle fond, const UInt8* pathname ) { short sfnt_id; short have_sfnt, have_lwfn; Str255 lwfn_file_name; UInt8 buff[HFS_MAXPATHLEN]; FT_Error err; have_sfnt = have_lwfn = 0; HLock( fond ); parse_fond( *fond, &have_sfnt, &sfnt_id, lwfn_file_name, 0 ); HUnlock( fond ); if ( lwfn_file_name[0] ) { err = lookup_lwfn_by_fond( pathname, lwfn_file_name, buff, sizeof ( buff ) ); if ( FT_Err_Ok == err ) have_lwfn = 1; } if ( have_lwfn && ( !have_sfnt || PREFER_LWFN ) ) return 1; else return count_faces_scalable( *fond ); } /* Read Type 1 data from the POST resources inside the LWFN file, return a PFB buffer. This is somewhat convoluted because the FT2 PFB parser wants the ASCII header as one chunk, and the LWFN chunks are often not organized that way, so we glue chunks of the same type together. */ static FT_Error read_lwfn( FT_Memory memory, short res, FT_Byte** pfb_data, FT_ULong* size ) { FT_Error error = FT_Err_Ok; short res_id; unsigned char *buffer, *p, *size_p = NULL; FT_ULong total_size = 0; FT_ULong old_total_size = 0; FT_ULong post_size, pfb_chunk_size; Handle post_data; char code, last_code; UseResFile( res ); /* First pass: load all POST resources, and determine the size of */ /* the output buffer. */ res_id = 501; last_code = -1; for (;;) { post_data = Get1Resource( 'POST', res_id++ ); if ( post_data == NULL ) break; /* we are done */ code = (*post_data)[0]; if ( code != last_code ) { if ( code == 5 ) total_size += 2; /* just the end code */ else total_size += 6; /* code + 4 bytes chunk length */ } total_size += GetHandleSize( post_data ) - 2; last_code = code; /* detect integer overflows */ if ( total_size < old_total_size ) { error = FT_Err_Array_Too_Large; goto Error; } old_total_size = total_size; } if ( FT_ALLOC( buffer, (FT_Long)total_size ) ) goto Error; /* Second pass: append all POST data to the buffer, add PFB fields. */ /* Glue all consecutive chunks of the same type together. */ p = buffer; res_id = 501; last_code = -1; pfb_chunk_size = 0; for (;;) { post_data = Get1Resource( 'POST', res_id++ ); if ( post_data == NULL ) break; /* we are done */ post_size = (FT_ULong)GetHandleSize( post_data ) - 2; code = (*post_data)[0]; if ( code != last_code ) { if ( last_code != -1 ) { /* we are done adding a chunk, fill in the size field */ if ( size_p != NULL ) { *size_p++ = (FT_Byte)( pfb_chunk_size & 0xFF ); *size_p++ = (FT_Byte)( ( pfb_chunk_size >> 8 ) & 0xFF ); *size_p++ = (FT_Byte)( ( pfb_chunk_size >> 16 ) & 0xFF ); *size_p++ = (FT_Byte)( ( pfb_chunk_size >> 24 ) & 0xFF ); } pfb_chunk_size = 0; } *p++ = 0x80; if ( code == 5 ) *p++ = 0x03; /* the end */ else if ( code == 2 ) *p++ = 0x02; /* binary segment */ else *p++ = 0x01; /* ASCII segment */ if ( code != 5 ) { size_p = p; /* save for later */ p += 4; /* make space for size field */ } } ft_memcpy( p, *post_data + 2, post_size ); pfb_chunk_size += post_size; p += post_size; last_code = code; } *pfb_data = buffer; *size = total_size; Error: CloseResFile( res ); return error; } /* Finalizer for a memory stream; gets called by FT_Done_Face(). It frees the memory it uses. */ static void memory_stream_close( FT_Stream stream ) { FT_Memory memory = stream->memory; FT_FREE( stream->base ); stream->size = 0; stream->base = 0; stream->close = 0; } /* Create a new memory stream from a buffer and a size. */ static FT_Error new_memory_stream( FT_Library library, FT_Byte* base, FT_ULong size, FT_Stream_CloseFunc close, FT_Stream* astream ) { FT_Error error; FT_Memory memory; FT_Stream stream; if ( !library ) return FT_Err_Invalid_Library_Handle; if ( !base ) return FT_Err_Invalid_Argument; *astream = 0; memory = library->memory; if ( FT_NEW( stream ) ) goto Exit;
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -