📄 ttgload.c
字号:
/***************************************************************************//* *//* ttgload.c *//* *//* TrueType Glyph Loader (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_CALC_H#include FT_INTERNAL_STREAM_H#include FT_INTERNAL_SFNT_H#include FT_TRUETYPE_TAGS_H#include FT_OUTLINE_H#include "ttgload.h"#include "ttpload.h"#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT#include "ttgxvar.h"#endif#include "tterrors.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_ttgload /*************************************************************************/ /* */ /* Composite font flags. */ /* */#define ARGS_ARE_WORDS 0x0001#define ARGS_ARE_XY_VALUES 0x0002#define ROUND_XY_TO_GRID 0x0004#define WE_HAVE_A_SCALE 0x0008/* reserved 0x0010 */#define MORE_COMPONENTS 0x0020#define WE_HAVE_AN_XY_SCALE 0x0040#define WE_HAVE_A_2X2 0x0080#define WE_HAVE_INSTR 0x0100#define USE_MY_METRICS 0x0200#define OVERLAP_COMPOUND 0x0400#define SCALED_COMPONENT_OFFSET 0x0800#define UNSCALED_COMPONENT_OFFSET 0x1000 /*************************************************************************/ /* */ /* Returns the horizontal metrics in font units for a given glyph. If */ /* `check' is true, take care of monospaced fonts by returning the */ /* advance width maximum. */ /* */ static void Get_HMetrics( TT_Face face, FT_UInt idx, FT_Bool check, FT_Short* lsb, FT_UShort* aw ) { ( (SFNT_Service)face->sfnt )->get_metrics( face, 0, idx, lsb, aw ); if ( check && face->postscript.isFixedPitch ) *aw = face->horizontal.advance_Width_Max; } /*************************************************************************/ /* */ /* Returns the vertical metrics in font units for a given glyph. */ /* Greg Hitchcock from Microsoft told us that if there were no `vmtx' */ /* table, typoAscender/Descender from the `OS/2' table would be used */ /* instead, and if there were no `OS/2' table, use ascender/descender */ /* from the `hhea' table. But that is not what Microsoft's rasterizer */ /* apparently does: It uses the ppem value as the advance height, and */ /* sets the top side bearing to be zero. */ /* */ /* The monospace `check' is probably not meaningful here, but we leave */ /* it in for a consistent interface. */ /* */ static void Get_VMetrics( TT_Face face, FT_UInt idx, FT_Bool check, FT_Short* tsb, FT_UShort* ah ) { FT_UNUSED( check ); if ( face->vertical_info ) ( (SFNT_Service)face->sfnt )->get_metrics( face, 1, idx, tsb, ah );#if 1 /* Empirically determined, at variance with what MS said */ else { *tsb = 0; *ah = face->root.units_per_EM; }#else /* This is what MS said to do. It isn't what they do, however. */ else if ( face->os2.version != 0xFFFFU ) { *tsb = face->os2.sTypoAscender; *ah = face->os2.sTypoAscender - face->os2.sTypoDescender; } else { *tsb = face->horizontal.Ascender; *ah = face->horizontal.Ascender - face->horizontal.Descender; }#endif } /*************************************************************************/ /* */ /* Translates an array of coordinates. */ /* */ static void translate_array( FT_UInt n, FT_Vector* coords, FT_Pos delta_x, FT_Pos delta_y ) { FT_UInt k; if ( delta_x ) for ( k = 0; k < n; k++ ) coords[k].x += delta_x; if ( delta_y ) for ( k = 0; k < n; k++ ) coords[k].y += delta_y; }#undef IS_HINTED#define IS_HINTED( flags ) ( ( flags & FT_LOAD_NO_HINTING ) == 0 ) /*************************************************************************/ /* */ /* The following functions are used by default with TrueType fonts. */ /* However, they can be replaced by alternatives if we need to support */ /* TrueType-compressed formats (like MicroType) in the future. */ /* */ /*************************************************************************/ FT_CALLBACK_DEF( FT_Error ) TT_Access_Glyph_Frame( TT_Loader loader, FT_UInt glyph_index, FT_ULong offset, FT_UInt byte_count ) { FT_Error error; FT_Stream stream = loader->stream; /* for non-debug mode */ FT_UNUSED( glyph_index ); FT_TRACE5(( "Glyph %ld\n", glyph_index )); /* the following line sets the `error' variable through macros! */ if ( FT_STREAM_SEEK( offset ) || FT_FRAME_ENTER( byte_count ) ) return error; loader->cursor = stream->cursor; loader->limit = stream->limit; return TT_Err_Ok; } FT_CALLBACK_DEF( void ) TT_Forget_Glyph_Frame( TT_Loader loader ) { FT_Stream stream = loader->stream; FT_FRAME_EXIT(); } FT_CALLBACK_DEF( FT_Error ) TT_Load_Glyph_Header( TT_Loader loader ) { FT_Byte* p = loader->cursor; FT_Byte* limit = loader->limit; if ( p + 10 > limit ) return TT_Err_Invalid_Outline; loader->n_contours = FT_NEXT_SHORT( p ); loader->bbox.xMin = FT_NEXT_SHORT( p ); loader->bbox.yMin = FT_NEXT_SHORT( p ); loader->bbox.xMax = FT_NEXT_SHORT( p ); loader->bbox.yMax = FT_NEXT_SHORT( p ); FT_TRACE5(( " # of contours: %d\n", loader->n_contours )); FT_TRACE5(( " xMin: %4d xMax: %4d\n", loader->bbox.xMin, loader->bbox.xMax )); FT_TRACE5(( " yMin: %4d yMax: %4d\n", loader->bbox.yMin, loader->bbox.yMax )); loader->cursor = p; return TT_Err_Ok; } FT_CALLBACK_DEF( FT_Error ) TT_Load_Simple_Glyph( TT_Loader load ) { FT_Error error; FT_Byte* p = load->cursor; FT_Byte* limit = load->limit; FT_GlyphLoader gloader = load->gloader; FT_Int n_contours = load->n_contours; FT_Outline* outline; TT_Face face = (TT_Face)load->face; FT_UShort n_ins; FT_Int n, n_points; FT_Byte *flag, *flag_limit; FT_Byte c, count; FT_Vector *vec, *vec_limit; FT_Pos x; FT_Short *cont, *cont_limit; /* check that we can add the contours to the glyph */ error = FT_GLYPHLOADER_CHECK_POINTS( gloader, 0, n_contours ); if ( error ) goto Fail; /* reading the contours' endpoints & number of points */ cont = gloader->current.outline.contours; cont_limit = cont + n_contours; /* check space for contours array + instructions count */ if ( n_contours >= 0xFFF || p + (n_contours + 1) * 2 > limit ) goto Invalid_Outline; for ( ; cont < cont_limit; cont++ ) cont[0] = FT_NEXT_USHORT( p ); n_points = 0; if ( n_contours > 0 ) { n_points = cont[-1] + 1; if ( n_points < 0 ) goto Invalid_Outline; } /* note that we will add four phantom points later */ error = FT_GLYPHLOADER_CHECK_POINTS( gloader, n_points + 4, 0 ); if ( error ) goto Fail; /* we'd better check the contours table right now */ outline = &gloader->current.outline; for ( cont = outline->contours + 1; cont < cont_limit; cont++ ) if ( cont[-1] >= cont[0] ) goto Invalid_Outline; /* reading the bytecode instructions */ load->glyph->control_len = 0; load->glyph->control_data = 0; if ( p + 2 > limit ) goto Invalid_Outline; n_ins = FT_NEXT_USHORT( p ); FT_TRACE5(( " Instructions size: %u\n", n_ins )); if ( n_ins > face->max_profile.maxSizeOfInstructions ) { FT_TRACE0(( "TT_Load_Simple_Glyph: Too many instructions!\n" )); error = TT_Err_Too_Many_Hints; goto Fail; } if ( ( limit - p ) < n_ins ) { FT_TRACE0(( "TT_Load_Simple_Glyph: Instruction count mismatch!\n" )); error = TT_Err_Too_Many_Hints; goto Fail; }#ifdef TT_USE_BYTECODE_INTERPRETER if ( IS_HINTED( load->load_flags ) ) { load->glyph->control_len = n_ins; load->glyph->control_data = load->exec->glyphIns; FT_MEM_COPY( load->exec->glyphIns, p, (FT_Long)n_ins ); }#endif /* TT_USE_BYTECODE_INTERPRETER */ p += n_ins; /* reading the point tags */ flag = (FT_Byte*)outline->tags; flag_limit = flag + n_points; FT_ASSERT( flag != NULL ); while ( flag < flag_limit ) { if ( p + 1 > limit ) goto Invalid_Outline; *flag++ = c = FT_NEXT_BYTE( p ); if ( c & 8 ) { if ( p + 1 > limit ) goto Invalid_Outline; count = FT_NEXT_BYTE( p ); if ( flag + (FT_Int)count > flag_limit ) goto Invalid_Outline; for ( ; count > 0; count-- ) *flag++ = c; } } /* reading the X coordinates */ vec = outline->points; vec_limit = vec + n_points; flag = (FT_Byte*)outline->tags; x = 0; for ( ; vec < vec_limit; vec++, flag++ ) { FT_Pos y = 0; if ( *flag & 2 ) { if ( p + 1 > limit ) goto Invalid_Outline; y = (FT_Pos)FT_NEXT_BYTE( p ); if ( ( *flag & 16 ) == 0 ) y = -y; } else if ( ( *flag & 16 ) == 0 ) { if ( p + 2 > limit ) goto Invalid_Outline; y = (FT_Pos)FT_NEXT_SHORT( p ); } x += y; vec->x = x;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -