📄 ttload.c
字号:
/***************************************************************************//* *//* ttload.c *//* *//* Load the basic TrueType tables, i.e., tables that can be either in *//* TTF or OTF fonts (body). *//* *//* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007 by *//* David Turner, Robert Wilhelm, and Werner Lemberg. *//* *//* This file is part of the FreeType project, and may only be used, *//* modified, and distributed under the terms of the FreeType project *//* license, LICENSE.TXT. By continuing to use, modify, or distribute *//* this file you indicate that you have read the license and *//* understand and accept it fully. *//* *//***************************************************************************/#include <ft2build.h>#include FT_INTERNAL_DEBUG_H#include FT_INTERNAL_STREAM_H#include FT_TRUETYPE_TAGS_H#include "ttload.h"#include "sferrors.h" /*************************************************************************/ /* */ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ /* messages during execution. */ /* */#undef FT_COMPONENT#define FT_COMPONENT trace_ttload /*************************************************************************/ /* */ /* <Function> */ /* tt_face_lookup_table */ /* */ /* <Description> */ /* Looks for a TrueType table by name. */ /* */ /* <Input> */ /* face :: A face object handle. */ /* */ /* tag :: The searched tag. */ /* */ /* <Return> */ /* A pointer to the table directory entry. 0 if not found. */ /* */ FT_LOCAL_DEF( TT_Table ) tt_face_lookup_table( TT_Face face, FT_ULong tag ) { TT_Table entry; TT_Table limit; FT_TRACE4(( "tt_face_lookup_table: %08p, `%c%c%c%c' -- ", face, (FT_Char)( tag >> 24 ), (FT_Char)( tag >> 16 ), (FT_Char)( tag >> 8 ), (FT_Char)( tag ) )); entry = face->dir_tables; limit = entry + face->num_tables; for ( ; entry < limit; entry++ ) { /* For compatibility with Windows, we consider 0-length */ /* tables the same as missing tables. */ if ( entry->Tag == tag && entry->Length != 0 ) { FT_TRACE4(( "found table.\n" )); return entry; } } FT_TRACE4(( "could not find table!\n" )); return 0; } /*************************************************************************/ /* */ /* <Function> */ /* tt_face_goto_table */ /* */ /* <Description> */ /* Looks for a TrueType table by name, then seek a stream to it. */ /* */ /* <Input> */ /* face :: A face object handle. */ /* */ /* tag :: The searched tag. */ /* */ /* stream :: The stream to seek when the table is found. */ /* */ /* <Output> */ /* length :: The length of the table if found, undefined otherwise. */ /* */ /* <Return> */ /* FreeType error code. 0 means success. */ /* */ FT_LOCAL_DEF( FT_Error ) tt_face_goto_table( TT_Face face, FT_ULong tag, FT_Stream stream, FT_ULong* length ) { TT_Table table; FT_Error error; table = tt_face_lookup_table( face, tag ); if ( table ) { if ( length ) *length = table->Length; if ( FT_STREAM_SEEK( table->Offset ) ) goto Exit; } else error = SFNT_Err_Table_Missing; Exit: return error; } /* Here, we */ /* */ /* - check that `num_tables' is valid */ /* - look for a `head' table, check its size, and parse it to check */ /* whether its `magic' field is correctly set */ /* */ /* When checking directory entries, ignore the tables `glyx' and `locx' */ /* which are hacked-out versions of `glyf' and `loca' in some PostScript */ /* Type 42 fonts, and which are generally invalid. */ /* */ static FT_Error check_table_dir( SFNT_Header sfnt, FT_Stream stream ) { FT_Error error; FT_UInt nn; FT_UInt has_head = 0, has_sing = 0, has_meta = 0; FT_ULong offset = sfnt->offset + 12; const FT_ULong glyx_tag = FT_MAKE_TAG( 'g', 'l', 'y', 'x' ); const FT_ULong locx_tag = FT_MAKE_TAG( 'l', 'o', 'c', 'x' ); static const FT_Frame_Field table_dir_entry_fields[] = {#undef FT_STRUCTURE#define FT_STRUCTURE TT_TableRec FT_FRAME_START( 16 ), FT_FRAME_ULONG( Tag ), FT_FRAME_ULONG( CheckSum ), FT_FRAME_ULONG( Offset ), FT_FRAME_ULONG( Length ), FT_FRAME_END }; if ( sfnt->num_tables == 0 || offset + sfnt->num_tables * 16 > stream->size ) return SFNT_Err_Unknown_File_Format; if ( FT_STREAM_SEEK( offset ) ) return error; for ( nn = 0; nn < sfnt->num_tables; nn++ ) { TT_TableRec table; if ( FT_STREAM_READ_FIELDS( table_dir_entry_fields, &table ) ) return error; if ( table.Offset + table.Length > stream->size && table.Tag != glyx_tag && table.Tag != locx_tag ) return SFNT_Err_Unknown_File_Format; if ( table.Tag == TTAG_head || table.Tag == TTAG_bhed ) { FT_UInt32 magic;#ifndef TT_CONFIG_OPTION_EMBEDDED_BITMAPS if ( table.Tag == TTAG_head )#endif has_head = 1; /* * The table length should be 0x36, but certain font tools make it * 0x38, so we will just check that it is greater. * * Note that according to the specification, the table must be * padded to 32-bit lengths, but this doesn't apply to the value of * its `Length' field! * */ if ( table.Length < 0x36 ) return SFNT_Err_Unknown_File_Format; if ( FT_STREAM_SEEK( table.Offset + 12 ) || FT_READ_ULONG( magic ) ) return error; if ( magic != 0x5F0F3CF5UL ) return SFNT_Err_Unknown_File_Format; if ( FT_STREAM_SEEK( offset + ( nn + 1 ) * 16 ) ) return error; } else if ( table.Tag == TTAG_SING ) has_sing = 1; else if ( table.Tag == TTAG_META ) has_meta = 1; } /* if `sing' and `meta' tables are present, there is no `head' table */ if ( has_head || ( has_sing && has_meta ) ) return SFNT_Err_Ok; else return SFNT_Err_Unknown_File_Format; } /*************************************************************************/ /* */ /* <Function> */ /* tt_face_load_font_dir */ /* */ /* <Description> */ /* Loads the header of a SFNT font file. */ /* */ /* <Input> */ /* face :: A handle to the target face object. */ /* */ /* stream :: The input stream. */ /* */ /* <Output> */ /* sfnt :: The SFNT header. */ /* */ /* <Return> */ /* FreeType error code. 0 means success. */ /* */ /* <Note> */ /* The stream cursor must be at the beginning of the font directory. */ /* */ FT_LOCAL_DEF( FT_Error ) tt_face_load_font_dir( TT_Face face, FT_Stream stream ) { SFNT_HeaderRec sfnt; FT_Error error; FT_Memory memory = stream->memory; TT_TableRec* entry; TT_TableRec* limit; static const FT_Frame_Field offset_table_fields[] = {#undef FT_STRUCTURE#define FT_STRUCTURE SFNT_HeaderRec FT_FRAME_START( 8 ), FT_FRAME_USHORT( num_tables ), FT_FRAME_USHORT( search_range ), FT_FRAME_USHORT( entry_selector ), FT_FRAME_USHORT( range_shift ), FT_FRAME_END }; FT_TRACE2(( "tt_face_load_font_dir: %08p\n", face )); /* read the offset table */ sfnt.offset = FT_STREAM_POS(); if ( FT_READ_ULONG( sfnt.format_tag ) || FT_STREAM_READ_FIELDS( offset_table_fields, &sfnt ) ) return error; /* many fonts don't have these fields set correctly */#if 0 if ( sfnt.search_range != 1 << ( sfnt.entry_selector + 4 ) || sfnt.search_range + sfnt.range_shift != sfnt.num_tables << 4 ) return SFNT_Err_Unknown_File_Format;#endif /* load the table directory */ FT_TRACE2(( "-- Tables count: %12u\n", sfnt.num_tables )); FT_TRACE2(( "-- Format version: %08lx\n", sfnt.format_tag )); /* check first */ error = check_table_dir( &sfnt, stream ); if ( error ) { FT_TRACE2(( "tt_face_load_font_dir: invalid table directory!\n" )); return error; } face->num_tables = sfnt.num_tables; face->format_tag = sfnt.format_tag; if ( FT_QNEW_ARRAY( face->dir_tables, face->num_tables ) ) return error; if ( FT_STREAM_SEEK( sfnt.offset + 12 ) || FT_FRAME_ENTER( face->num_tables * 16L ) ) return error; entry = face->dir_tables; limit = entry + face->num_tables; for ( ; entry < limit; entry++ ) { entry->Tag = FT_GET_TAG4(); entry->CheckSum = FT_GET_ULONG(); entry->Offset = FT_GET_LONG(); entry->Length = FT_GET_LONG(); FT_TRACE2(( " %c%c%c%c - %08lx - %08lx\n", (FT_Char)( entry->Tag >> 24 ), (FT_Char)( entry->Tag >> 16 ), (FT_Char)( entry->Tag >> 8 ), (FT_Char)( entry->Tag ), entry->Offset, entry->Length )); } FT_FRAME_EXIT(); FT_TRACE2(( "table directory loaded\n\n" )); return error; } /*************************************************************************/ /* */ /* <Function> */ /* tt_face_load_any */ /* */ /* <Description> */ /* Loads any font table into client memory. */ /* */ /* <Input> */ /* face :: The face object to look for. */ /* */ /* tag :: The tag of table to load. Use the value 0 if you want */ /* to access the whole font file, else set this parameter */ /* to a valid TrueType table tag that you can forge with */ /* the MAKE_TT_TAG macro. */ /* */ /* offset :: The starting offset in the table (or the file if */ /* tag == 0). */ /* */ /* length :: The address of the decision variable: */ /* */ /* If length == NULL: */ /* Loads the whole table. Returns an error if */ /* `offset' == 0! */ /* */ /* If *length == 0: */ /* Exits immediately; returning the length of the given */ /* table or of the font file, depending on the value of */ /* `tag'. */ /* */ /* If *length != 0: */ /* Loads the next `length' bytes of table or font, */ /* starting at offset `offset' (in table or font too). */ /* */ /* <Output> */ /* buffer :: The address of target buffer. */ /* */ /* <Return> */ /* FreeType error code. 0 means success. */ /* */ FT_LOCAL_DEF( FT_Error )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -