📄 ttgload.c
字号:
/***************************************************************************//* *//* ttgload.c *//* *//* TrueType Glyph Loader (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_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/* Maximum recursion depth we allow for composite glyphs. * The TrueType spec doesn't say anything about recursion, * so it isn't clear that recursion is allowed at all. But * we'll be generous. */#define TT_MAX_COMPOSITE_RECURSE 5 /*************************************************************************/ /* */ /* <Function> */ /* tt_face_get_metrics */ /* */ /* <Description> */ /* Returns the horizontal or vertical metrics in font units for a */ /* given glyph. The metrics are the left side bearing (resp. top */ /* side bearing) and advance width (resp. advance height). */ /* */ /* <Input> */ /* header :: A pointer to either the horizontal or vertical metrics */ /* structure. */ /* */ /* idx :: The glyph index. */ /* */ /* <Output> */ /* bearing :: The bearing, either left side or top side. */ /* */ /* advance :: The advance width resp. advance height. */ /* */ /* <Note> */ /* This function will much probably move to another component in the */ /* near future, but I haven't decided which yet. */ /* */#ifdef FT_OPTIMIZE_MEMORY static void tt_face_get_metrics( TT_Face face, FT_Bool vertical, FT_UInt idx, FT_Short *abearing, FT_UShort *aadvance ) { TT_HoriHeader* header; FT_Byte* p; FT_Byte* limit; FT_UShort k; if ( vertical ) { header = (TT_HoriHeader*)&face->vertical; p = face->vert_metrics; limit = p + face->vert_metrics_size; } else { header = &face->horizontal; p = face->horz_metrics; limit = p + face->horz_metrics_size; } k = header->number_Of_HMetrics; if ( k > 0 ) { if ( idx < (FT_UInt)k ) { p += 4 * idx; if ( p + 4 > limit ) goto NoData; *aadvance = FT_NEXT_USHORT( p ); *abearing = FT_NEXT_SHORT( p ); } else { p += 4 * ( k - 1 ); if ( p + 4 > limit ) goto NoData; *aadvance = FT_NEXT_USHORT( p ); p += 2 + 2 * ( idx - k ); if ( p + 2 > limit ) *abearing = 0; else *abearing = FT_PEEK_SHORT( p ); } } else { NoData: *abearing = 0; *aadvance = 0; } }#else /* !FT_OPTIMIZE_MEMORY */ static void tt_face_get_metrics( TT_Face face, FT_Bool vertical, FT_UInt idx, FT_Short *abearing, FT_UShort *aadvance ) { TT_HoriHeader* header = vertical ? (TT_HoriHeader*)&face->vertical : &face->horizontal; TT_LongMetrics longs_m; FT_UShort k = header->number_Of_HMetrics; if ( k == 0 ) { *abearing = *aadvance = 0; return; } if ( idx < (FT_UInt)k ) { longs_m = (TT_LongMetrics)header->long_metrics + idx; *abearing = longs_m->bearing; *aadvance = longs_m->advance; } else { *abearing = ((TT_ShortMetrics*)header->short_metrics)[idx - k]; *aadvance = ((TT_LongMetrics)header->long_metrics)[k - 1].advance; } }#endif /* !FT_OPTIMIZE_MEMORY */ /*************************************************************************/ /* */ /* 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 ) { tt_face_get_metrics( face, 0, idx, lsb, aw ); if ( check && face->postscript.isFixedPitch ) *aw = face->horizontal.advance_Width_Max; } /*************************************************************************/ /* */ /* Returns the advance width table for a given pixel size if it is found */ /* in the font's `hdmx' table (if any). */ /* */ static FT_Byte* Get_Advance_WidthPtr( TT_Face face, FT_Int ppem, FT_UInt gindex ) {#ifdef FT_OPTIMIZE_MEMORY FT_UInt nn; FT_Byte* result = NULL; FT_ULong record_size = face->hdmx_record_size; FT_Byte* record = face->hdmx_table + 8; for ( nn = 0; nn < face->hdmx_record_count; nn++ ) if ( face->hdmx_record_sizes[nn] == ppem ) { gindex += 2; if ( gindex < record_size ) result = record + gindex; break; } return result;#else FT_UShort n; for ( n = 0; n < face->hdmx.num_records; n++ ) if ( face->hdmx.records[n].ppem == ppem ) return &face->hdmx.records[n].widths[gindex]; return NULL;#endif } /*************************************************************************/ /* */ /* 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 ) tt_face_get_metrics( face, 1, idx, tsb, ah );#if 1 /* Emperically 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 }#define cur_to_org( n, zone ) \ FT_ARRAY_COPY( (zone)->org, (zone)->cur, (n) )#define org_to_cur( n, zone ) \ FT_ARRAY_COPY( (zone)->cur, (zone)->org, (n) ) /*************************************************************************/ /* */ /* 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; } static void tt_prepare_zone( TT_GlyphZone zone, FT_GlyphLoad load, FT_UInt start_point, FT_UInt start_contour ) { zone->n_points = (FT_UShort)( load->outline.n_points - start_point ); zone->n_contours = (FT_Short) ( load->outline.n_contours - start_contour ); zone->org = load->extra_points + start_point; zone->cur = load->outline.points + start_point; zone->tags = (FT_Byte*)load->outline.tags + start_point; zone->contours = (FT_UShort*)load->outline.contours + start_contour; }#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; return TT_Err_Ok; } FT_CALLBACK_DEF( void ) TT_Forget_Glyph_Frame( TT_Loader loader ) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -