📄 ftobjs.c
字号:
flag_offset = offsets[face_index]; error = FT_Stream_Seek( stream, flag_offset ); if ( error ) goto Exit; if ( FT_READ_LONG( rlen ) ) goto Exit; if ( rlen == -1 ) return FT_Err_Cannot_Open_Resource; if ( FT_ALLOC( sfnt_data, (FT_Long)rlen ) ) return error; error = FT_Stream_Read( stream, (FT_Byte *)sfnt_data, rlen ); if ( error ) goto Exit; is_cff = rlen > 4 && sfnt_data[0] == 'O' && sfnt_data[1] == 'T' && sfnt_data[2] == 'T' && sfnt_data[3] == 'O'; error = open_face_from_buffer( library, sfnt_data, rlen, face_index_in_resource, is_cff ? "cff" : "truetype", aface ); Exit: return error; } /* Check for a valid resource fork header, or a valid dfont */ /* header. In a resource fork the first 16 bytes are repeated */ /* at the location specified by bytes 4-7. In a dfont bytes */ /* 4-7 point to 16 bytes of zeroes instead. */ /* */ static FT_Error IsMacResource( FT_Library library, FT_Stream stream, FT_Long resource_offset, FT_Long face_index, FT_Face *aface ) { FT_Memory memory = library->memory; FT_Error error; FT_Long map_offset, rdara_pos; FT_Long *data_offsets; FT_Long count; error = FT_Raccess_Get_HeaderInfo( library, stream, resource_offset, &map_offset, &rdara_pos ); if ( error ) return error; error = FT_Raccess_Get_DataOffsets( library, stream, map_offset, rdara_pos, FT_MAKE_TAG( 'P', 'O', 'S', 'T' ), &data_offsets, &count ); if ( !error ) { error = Mac_Read_POST_Resource( library, stream, data_offsets, count, face_index, aface ); FT_FREE( data_offsets ); /* POST exists in an LWFN providing a single face */ if ( !error ) (*aface)->num_faces = 1; return error; } error = FT_Raccess_Get_DataOffsets( library, stream, map_offset, rdara_pos, FT_MAKE_TAG( 's', 'f', 'n', 't' ), &data_offsets, &count ); if ( !error ) { FT_Long face_index_internal = face_index % count; error = Mac_Read_sfnt_Resource( library, stream, data_offsets, count, face_index_internal, aface ); FT_FREE( data_offsets ); if ( !error ) (*aface)->num_faces = count; } return error; } /* Check for a valid macbinary header, and if we find one */ /* check that the (flattened) resource fork in it is valid. */ /* */ static FT_Error IsMacBinary( FT_Library library, FT_Stream stream, FT_Long face_index, FT_Face *aface ) { unsigned char header[128]; FT_Error error; FT_Long dlen, offset; error = FT_Stream_Seek( stream, 0 ); if ( error ) goto Exit; error = FT_Stream_Read( stream, (FT_Byte*)header, 128 ); if ( error ) goto Exit; if ( header[ 0] != 0 || header[74] != 0 || header[82] != 0 || header[ 1] == 0 || header[ 1] > 33 || header[63] != 0 || header[2 + header[1]] != 0 ) return FT_Err_Unknown_File_Format; dlen = ( header[0x53] << 24 ) | ( header[0x54] << 16 ) | ( header[0x55] << 8 ) | header[0x56];#if 0 rlen = ( header[0x57] << 24 ) | ( header[0x58] << 16 ) | ( header[0x59] << 8 ) | header[0x5a];#endif /* 0 */ offset = 128 + ( ( dlen + 127 ) & ~127 ); return IsMacResource( library, stream, offset, face_index, aface ); Exit: return error; } static FT_Error load_face_in_embedded_rfork( FT_Library library, FT_Stream stream, FT_Long face_index, FT_Face *aface, const FT_Open_Args *args ) {#undef FT_COMPONENT#define FT_COMPONENT trace_raccess FT_Memory memory = library->memory; FT_Error error = FT_Err_Unknown_File_Format; int i; char * file_names[FT_RACCESS_N_RULES]; FT_Long offsets[FT_RACCESS_N_RULES]; FT_Error errors[FT_RACCESS_N_RULES]; FT_Open_Args args2; FT_Stream stream2; FT_Raccess_Guess( library, stream, args->pathname, file_names, offsets, errors ); for ( i = 0; i < FT_RACCESS_N_RULES; i++ ) { if ( errors[i] ) { FT_TRACE3(( "Error[%d] has occurred in rule %d\n", errors[i], i )); continue; } args2.flags = FT_OPEN_PATHNAME; args2.pathname = file_names[i] ? file_names[i] : args->pathname; FT_TRACE3(( "Try rule %d: %s (offset=%d) ...", i, args2.pathname, offsets[i] )); error = FT_Stream_New( library, &args2, &stream2 ); if ( error ) { FT_TRACE3(( "failed\n" )); continue; } error = IsMacResource( library, stream2, offsets[i], face_index, aface ); FT_Stream_Free( stream2, 0 ); FT_TRACE3(( "%s\n", error ? "failed": "successful" )); if ( !error ) break; } for (i = 0; i < FT_RACCESS_N_RULES; i++) { if ( file_names[i] ) FT_FREE( file_names[i] ); } /* Caller (load_mac_face) requires FT_Err_Unknown_File_Format. */ if ( error ) error = FT_Err_Unknown_File_Format; return error;#undef FT_COMPONENT#define FT_COMPONENT trace_objs } /* Check for some macintosh formats. */ /* Is this a macbinary file? If so look at the resource fork. */ /* Is this a mac dfont file? */ /* Is this an old style resource fork? (in data) */ /* Else call load_face_in_embedded_rfork to try extra rules */ /* (defined in `ftrfork.c'). */ /* */ static FT_Error load_mac_face( FT_Library library, FT_Stream stream, FT_Long face_index, FT_Face *aface, const FT_Open_Args *args ) { FT_Error error; FT_UNUSED( args ); error = IsMacBinary( library, stream, face_index, aface ); if ( FT_ERROR_BASE( error ) == FT_Err_Unknown_File_Format ) {#undef FT_COMPONENT#define FT_COMPONENT trace_raccess FT_TRACE3(( "Try as dfont: %s ...", args->pathname )); error = IsMacResource( library, stream, 0, face_index, aface ); FT_TRACE3(( "%s\n", error ? "failed" : "successful" ));#undef FT_COMPONENT#define FT_COMPONENT trace_objs } if ( ( FT_ERROR_BASE( error ) == FT_Err_Unknown_File_Format || FT_ERROR_BASE( error ) == FT_Err_Invalid_Stream_Operation ) && ( args->flags & FT_OPEN_PATHNAME ) ) error = load_face_in_embedded_rfork( library, stream, face_index, aface, args ); return error; }#endif /* !FT_MACINTOSH && FT_CONFIG_OPTION_MAC_FONTS */ /* documentation is in freetype.h */ FT_EXPORT_DEF( FT_Error ) FT_Open_Face( FT_Library library, const FT_Open_Args* args, FT_Long face_index, FT_Face *aface ) { FT_Error error; FT_Driver driver; FT_Memory memory; FT_Stream stream; FT_Face face = 0; FT_ListNode node = 0; FT_Bool external_stream; /* test for valid `library' delayed to */ /* FT_Stream_New() */ if ( ( !aface && face_index >= 0 ) || !args ) return FT_Err_Invalid_Argument; external_stream = FT_BOOL( ( args->flags & FT_OPEN_STREAM ) && args->stream ); /* create input stream */ error = FT_Stream_New( library, args, &stream ); if ( error ) goto Exit; memory = library->memory; /* If the font driver is specified in the `args' structure, use */ /* it. Otherwise, we scan the list of registered drivers. */ if ( ( args->flags & FT_OPEN_DRIVER ) && args->driver ) { driver = FT_DRIVER( args->driver ); /* not all modules are drivers, so check... */ if ( FT_MODULE_IS_DRIVER( driver ) ) { FT_Int num_params = 0; FT_Parameter* params = 0; if ( args->flags & FT_OPEN_PARAMS ) { num_params = args->num_params; params = args->params; } error = open_face( driver, stream, face_index, num_params, params, &face ); if ( !error ) goto Success; } else error = FT_Err_Invalid_Handle; FT_Stream_Free( stream, external_stream ); goto Fail; } else { /* check each font driver for an appropriate format */ FT_Module* cur = library->modules; FT_Module* limit = cur + library->num_modules; for ( ; cur < limit; cur++ ) { /* not all modules are font drivers, so check... */ if ( FT_MODULE_IS_DRIVER( cur[0] ) ) { FT_Int num_params = 0; FT_Parameter* params = 0; driver = FT_DRIVER( cur[0] ); if ( args->flags & FT_OPEN_PARAMS ) { num_params = args->num_params; params = args->params; } error = open_face( driver, stream, face_index, num_params, params, &face ); if ( !error ) goto Success; if ( FT_ERROR_BASE( error ) != FT_Err_Unknown_File_Format ) goto Fail3; } } Fail3: /* If we are on the mac, and we get an FT_Err_Invalid_Stream_Operation */ /* it may be because we have an empty data fork, so we need to check */ /* the resource fork. */ if ( FT_ERROR_BASE( error ) != FT_Err_Unknown_File_Format && FT_ERROR_BASE( error ) != FT_Err_Invalid_Stream_Operation ) goto Fail2;#if !defined( FT_MACINTOSH ) && defined( FT_CONFIG_OPTION_MAC_FONTS ) error = load_mac_face( library, stream, face_index, aface, args ); if ( !error ) { /* We don't want to go to Success here. We've already done that. */ /* On the other hand, if we succeeded we still need to close this */ /* stream (we opened a different stream which extracted the */ /* interesting information out of this stream here. That stream */ /* will still be open and the face will point to it). */ FT_Stream_Free( stream, external_stream ); return error; } if ( FT_ERROR_BASE( error ) != FT_Err_Unknown_File_Format ) goto Fail2;#endif /* !FT_MACINTOSH && FT_CONFIG_OPTION_MAC_FONTS */ /* no driver is able to handle this format */ error = FT_Err_Unknown_File_Format; Fail2: FT_Stream_Free( stream, external_stream ); goto Fail; } Success: FT_TRACE4(( "FT_Open_Face: New face object, adding to list\n" )); /* set the FT_FACE_FLAG_EXTERNAL_STREAM bit for FT_Done_Face */ if ( external_stream ) face->face_flags |= FT_FACE_FLAG_EXTERNAL_STREAM; /* add the face object to its driver's list */ if ( FT_NEW( node ) ) goto Fail; node->data = face; /* don't assume driver is the same as face->driver, so use */ /* face->driver instead. */ FT_List_Add( &face->driver->faces_list, node ); /* now allocate a glyph slot object for the face */ FT_TRACE4(( "FT_Open_Face: Creating glyph slot\n" )); if ( face_index >= 0 ) { error = FT_New_GlyphSlot( face, NULL ); if ( error ) goto Fail; /* finally, allocate a size object for the face */ { FT_Size size; FT_TRACE4(( "FT_Open_Face: Creating size object\n" )); error = FT_New_Size( face, &size ); if ( error ) goto Fail; face->size = size; } } /* some checks */ if ( FT_IS_SCALABLE( face ) ) { if ( face->height < 0 ) face->height = (FT_Short)-face->height; if ( !FT_HAS_VERTICAL( face ) ) face->max_advance_height = (FT_Short)face->height; } if ( FT_HAS_FIXED_SIZES( face ) ) { FT_Int i; for ( i = 0; i < face->num_fixed_sizes; i++ ) { FT_Bitmap_Size* bsize = face->available_sizes + i; if ( bsize->height < 0 ) bsize->height = (FT_Short)-bsize->height; if ( bsize->x_ppem < 0 ) bsize->x_ppem = (FT_Short)-bsize->x_ppem;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -