📄 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 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_TRACE3(( "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_TRACE3(( "found table.\n" ));
return entry;
}
}
FT_TRACE3(( "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;
}
/* In theory, we should check the values of `search_range', */
/* `entry_selector', and `range_shift' to detect non-SFNT based files */
/* whose header might also start with 0x100000L (yes, these exist). */
/* */
/* Very unfortunately, many TrueType fonts don't have these fields */
/* set correctly and we must ignore them to support them. An */
/* alternative way to check the font file is thus to: */
/* */
/* - check that `num_tables' is valid */
/* - look for a "head" table, check its size, and parse it to */
/* see if 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 will generally be invalid. */
/* */
static FT_Error
sfnt_dir_check( FT_Stream stream,
FT_ULong offset,
FT_UInt num_tables )
{
FT_Error error;
FT_UInt nn, has_head = 0;
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 sfnt_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 'num_tables' is 0, read the table count from the file */
if ( num_tables == 0 )
{
if ( FT_STREAM_SEEK( offset ) ||
FT_STREAM_SKIP( 4 ) ||
FT_READ_USHORT( num_tables ) ||
FT_STREAM_SKIP( 6 ) )
goto Bad_Format;
if ( offset + 12 + num_tables*16 > stream->size )
goto Bad_Format;
}
else if ( FT_STREAM_SEEK( offset + 12 ) )
goto Bad_Format;
for ( nn = 0; nn < num_tables; nn++ )
{
TT_TableRec table;
if ( FT_STREAM_READ_FIELDS( sfnt_dir_entry_fields, &table ) )
goto Bad_Format;
if ( table.Offset + table.Length > stream->size &&
table.Tag != glyx_tag && table.Tag != locx_tag )
goto Bad_Format;
if ( table.Tag == TTAG_head )
{
FT_UInt32 magic;
#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
head_retry:
#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
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 ||
FT_STREAM_SEEK( table.Offset + 12 ) ||
FT_READ_ULONG( magic ) ||
magic != 0x5F0F3CF5UL )
goto Bad_Format;
if ( FT_STREAM_SEEK( offset + 28 + 16*nn ) )
goto Bad_Format;
}
#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
else if ( table.Tag == TTAG_bhed )
goto head_retry;
#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
}
if ( has_head == 0 )
goto Bad_Format;
Exit:
return error;
Bad_Format:
error = SFNT_Err_Unknown_File_Format;
goto Exit;
}
/*************************************************************************/
/* */
/* <Function> */
/* tt_face_load_sfnt_header */
/* */
/* <Description> */
/* Loads the header of a SFNT font file. Supports collections. */
/* */
/* <Input> */
/* face :: A handle to the target face object. */
/* */
/* stream :: The input stream. */
/* */
/* face_index :: If the font is a collection, the number of the font */
/* in the collection. Must be zero otherwise. */
/* */
/* <Output> */
/* sfnt :: The SFNT header. */
/* */
/* <Return> */
/* FreeType error code. 0 means success. */
/* */
/* <Note> */
/* The stream cursor must be at the font file's origin. */
/* */
/* This function recognizes fonts embedded in a `TrueType collection' */
/* */
/* The header will be checked whether it is valid by looking at the */
/* values of `search_range', `entry_selector', and `range_shift'. */
/* */
FT_LOCAL_DEF( FT_Error )
tt_face_load_sfnt_header( TT_Face face,
FT_Stream stream,
FT_Long face_index,
SFNT_Header sfnt )
{
FT_Error error;
FT_ULong font_format_tag, format_tag, offset;
FT_Memory memory = stream->memory;
static const FT_Frame_Field sfnt_header_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
};
static const FT_Frame_Field ttc_header_fields[] =
{
#undef FT_STRUCTURE
#define FT_STRUCTURE TTC_HeaderRec
FT_FRAME_START( 8 ),
FT_FRAME_LONG( version ),
FT_FRAME_LONG( count ),
FT_FRAME_END
};
FT_TRACE2(( "tt_face_load_sfnt_header: %08p, %ld\n",
face, face_index ));
face->ttc_header.tag = 0;
face->ttc_header.version = 0;
face->ttc_header.count = 0;
face->num_tables = 0;
/* First of all, read the first 4 bytes. If it is `ttcf', then the */
/* file is a TrueType collection, otherwise it is a single-face font. */
/* */
offset = FT_STREAM_POS();
if ( FT_READ_ULONG( font_format_tag ) )
goto Exit;
format_tag = font_format_tag;
if ( font_format_tag == TTAG_ttcf )
{
FT_Int n;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -