📄 ttcmap.c
字号:
/***************************************************************************//* *//* ttcmap.c *//* *//* TrueType character mapping table (cmap) support (body). *//* *//* Copyright 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 "sferrors.h" /* must come before FT_INTERNAL_VALIDATE_H */#include FT_INTERNAL_VALIDATE_H#include FT_INTERNAL_STREAM_H#include "ttload.h"#include "ttcmap.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_ttcmap#define TT_PEEK_SHORT FT_PEEK_SHORT#define TT_PEEK_USHORT FT_PEEK_USHORT#define TT_PEEK_LONG FT_PEEK_LONG#define TT_PEEK_ULONG FT_PEEK_ULONG#define TT_NEXT_SHORT FT_NEXT_SHORT#define TT_NEXT_USHORT FT_NEXT_USHORT#define TT_NEXT_LONG FT_NEXT_LONG#define TT_NEXT_ULONG FT_NEXT_ULONG FT_CALLBACK_DEF( FT_Error ) tt_cmap_init( TT_CMap cmap, FT_Byte* table ) { cmap->data = table; return SFNT_Err_Ok; } /*************************************************************************/ /*************************************************************************/ /***** *****/ /***** FORMAT 0 *****/ /***** *****/ /*************************************************************************/ /*************************************************************************/ /*************************************************************************/ /* */ /* TABLE OVERVIEW */ /* -------------- */ /* */ /* NAME OFFSET TYPE DESCRIPTION */ /* */ /* format 0 USHORT must be 0 */ /* length 2 USHORT table length in bytes */ /* language 4 USHORT Mac language code */ /* glyph_ids 6 BYTE[256] array of glyph indices */ /* 262 */ /* */#ifdef TT_CONFIG_CMAP_FORMAT_0 FT_CALLBACK_DEF( FT_Error ) tt_cmap0_validate( FT_Byte* table, FT_Validator valid ) { FT_Byte* p = table + 2; FT_UInt length = TT_NEXT_USHORT( p ); if ( table + length > valid->limit || length < 262 ) FT_INVALID_TOO_SHORT; /* check glyph indices whenever necessary */ if ( valid->level >= FT_VALIDATE_TIGHT ) { FT_UInt n, idx; p = table + 6; for ( n = 0; n < 256; n++ ) { idx = *p++; if ( idx >= TT_VALID_GLYPH_COUNT( valid ) ) FT_INVALID_GLYPH_ID; } } return SFNT_Err_Ok; } FT_CALLBACK_DEF( FT_UInt ) tt_cmap0_char_index( TT_CMap cmap, FT_UInt32 char_code ) { FT_Byte* table = cmap->data; return char_code < 256 ? table[6 + char_code] : 0; } FT_CALLBACK_DEF( FT_UInt ) tt_cmap0_char_next( TT_CMap cmap, FT_UInt32 *pchar_code ) { FT_Byte* table = cmap->data; FT_UInt32 charcode = *pchar_code; FT_UInt32 result = 0; FT_UInt gindex = 0; table += 6; /* go to glyph ids */ while ( ++charcode < 256 ) { gindex = table[charcode]; if ( gindex != 0 ) { result = charcode; break; } } *pchar_code = result; return gindex; } FT_CALLBACK_DEF( FT_Error ) tt_cmap0_get_info( TT_CMap cmap, TT_CMapInfo *cmap_info ) { FT_Byte* p = cmap->data + 4; cmap_info->language = (FT_ULong)TT_PEEK_USHORT( p ); return SFNT_Err_Ok; } FT_CALLBACK_TABLE_DEF const TT_CMap_ClassRec tt_cmap0_class_rec = { { sizeof ( TT_CMapRec ), (FT_CMap_InitFunc) tt_cmap_init, (FT_CMap_DoneFunc) NULL, (FT_CMap_CharIndexFunc)tt_cmap0_char_index, (FT_CMap_CharNextFunc) tt_cmap0_char_next }, 0, (TT_CMap_ValidateFunc) tt_cmap0_validate, (TT_CMap_Info_GetFunc) tt_cmap0_get_info };#endif /* TT_CONFIG_CMAP_FORMAT_0 */ /*************************************************************************/ /*************************************************************************/ /***** *****/ /***** FORMAT 2 *****/ /***** *****/ /***** This is used for certain CJK encodings that encode text in a *****/ /***** mixed 8/16 bits encoding along the following lines: *****/ /***** *****/ /***** * Certain byte values correspond to an 8-bit character code *****/ /***** (typically in the range 0..127 for ASCII compatibility). *****/ /***** *****/ /***** * Certain byte values signal the first byte of a 2-byte *****/ /***** character code (but these values are also valid as the *****/ /***** second byte of a 2-byte character). *****/ /***** *****/ /***** The following charmap lookup and iteration functions all *****/ /***** assume that the value "charcode" correspond to following: *****/ /***** *****/ /***** - For one byte characters, "charcode" is simply the *****/ /***** character code. *****/ /***** *****/ /***** - For two byte characters, "charcode" is the 2-byte *****/ /***** character code in big endian format. More exactly: *****/ /***** *****/ /***** (charcode >> 8) is the first byte value *****/ /***** (charcode & 0xFF) is the second byte value *****/ /***** *****/ /***** Note that not all values of "charcode" are valid according *****/ /***** to these rules, and the function moderately check the *****/ /***** arguments. *****/ /***** *****/ /*************************************************************************/ /*************************************************************************/ /*************************************************************************/ /* */ /* TABLE OVERVIEW */ /* -------------- */ /* */ /* NAME OFFSET TYPE DESCRIPTION */ /* */ /* format 0 USHORT must be 2 */ /* length 2 USHORT table length in bytes */ /* language 4 USHORT Mac language code */ /* keys 6 USHORT[256] sub-header keys */ /* subs 518 SUBHEAD[NSUBS] sub-headers array */ /* glyph_ids 518+NSUB*8 USHORT[] glyph id array */ /* */ /* The `keys' table is used to map charcode high-bytes to sub-headers. */ /* The value of `NSUBS' is the number of sub-headers defined in the */ /* table and is computed by finding the maximum of the `keys' table. */ /* */ /* Note that for any n, `keys[n]' is a byte offset within the `subs' */ /* table, i.e., it is the corresponding sub-header index multiplied */ /* by 8. */ /* */ /* Each sub-header has the following format: */ /* */ /* NAME OFFSET TYPE DESCRIPTION */ /* */ /* first 0 USHORT first valid low-byte */ /* count 2 USHORT number of valid low-bytes */ /* delta 4 SHORT see below */ /* offset 6 USHORT see below */ /* */ /* A sub-header defines, for each high-byte, the range of valid */ /* low-bytes within the charmap. Note that the range defined by `first' */ /* and `count' must be completely included in the interval [0..255] */ /* according to the specification. */ /* */ /* If a character code is contained within a given sub-header, then */ /* mapping it to a glyph index is done as follows: */ /* */ /* * The value of `offset' is read. This is a _byte_ distance from the */ /* location of the `offset' field itself into a slice of the */ /* `glyph_ids' table. Let's call it `slice' (it's a USHORT[] too). */ /* */ /* * The value `slice[char.lo - first]' is read. If it is 0, there is */ /* no glyph for the charcode. Otherwise, the value of `delta' is */ /* added to it (modulo 65536) to form a new glyph index. */ /* */ /* It is up to the validation routine to check that all offsets fall */ /* within the glyph ids table (and not within the `subs' table itself or */ /* outside of the CMap). */ /* */#ifdef TT_CONFIG_CMAP_FORMAT_2 FT_CALLBACK_DEF( FT_Error ) tt_cmap2_validate( FT_Byte* table, FT_Validator valid ) { FT_Byte* p = table + 2; /* skip format */ FT_UInt length = TT_PEEK_USHORT( p ); FT_UInt n, max_subs; FT_Byte* keys; /* keys table */ FT_Byte* subs; /* sub-headers */ FT_Byte* glyph_ids; /* glyph id array */ if ( table + length > valid->limit || length < 6 + 512 ) FT_INVALID_TOO_SHORT; keys = table + 6; /* parse keys to compute sub-headers count */ p = keys; max_subs = 0; for ( n = 0; n < 256; n++ ) { FT_UInt idx = TT_NEXT_USHORT( p ); /* value must be multiple of 8 */ if ( valid->level >= FT_VALIDATE_PARANOID && ( idx & 7 ) != 0 ) FT_INVALID_DATA; idx >>= 3; if ( idx > max_subs ) max_subs = idx; } FT_ASSERT( p == table + 518 ); subs = p; glyph_ids = subs + (max_subs + 1) * 8; if ( glyph_ids > valid->limit ) FT_INVALID_TOO_SHORT; /* parse sub-headers */ for ( n = 0; n <= max_subs; n++ ) { FT_UInt first_code, code_count, offset; FT_Int delta; FT_Byte* ids; first_code = TT_NEXT_USHORT( p ); code_count = TT_NEXT_USHORT( p ); delta = TT_NEXT_SHORT( p ); offset = TT_NEXT_USHORT( p ); /* check range within 0..255 */ if ( valid->level >= FT_VALIDATE_PARANOID ) { if ( first_code >= 256 || first_code + code_count > 256 ) FT_INVALID_DATA; } /* check offset */ if ( offset != 0 ) { ids = p - 2 + offset; if ( ids < glyph_ids || ids + code_count*2 > table + length ) FT_INVALID_OFFSET; /* check glyph ids */ if ( valid->level >= FT_VALIDATE_TIGHT ) { FT_Byte* limit = p + code_count * 2; FT_UInt idx; for ( ; p < limit; ) { idx = TT_NEXT_USHORT( p ); if ( idx != 0 ) { idx = ( idx + delta ) & 0xFFFFU; if ( idx >= TT_VALID_GLYPH_COUNT( valid ) ) FT_INVALID_GLYPH_ID; } } } } } return SFNT_Err_Ok; } /* return sub header corresponding to a given character code */ /* NULL on invalid charcode */ static FT_Byte* tt_cmap2_get_subheader( FT_Byte* table, FT_UInt32 char_code ) { FT_Byte* result = NULL; if ( char_code < 0x10000UL ) { FT_UInt char_lo = (FT_UInt)( char_code & 0xFF ); FT_UInt char_hi = (FT_UInt)( char_code >> 8 ); FT_Byte* p = table + 6; /* keys table */ FT_Byte* subs = table + 518; /* subheaders table */ FT_Byte* sub; if ( char_hi == 0 ) { /* an 8-bit character code -- we use subHeader 0 in this case */ /* to test whether the character code is in the charmap */ /* */ sub = subs; /* jump to first sub-header */ /* check that the sub-header for this byte is 0, which */ /* indicates that it's really a valid one-byte value */ /* Otherwise, return 0 */ /* */ p += char_lo * 2; if ( TT_PEEK_USHORT( p ) != 0 ) goto Exit; } else { /* a 16-bit character code */ /* jump to key entry */ p += char_hi * 2; /* jump to sub-header */ sub = subs + ( FT_PAD_FLOOR( TT_PEEK_USHORT( p ), 8 ) ); /* check that the high byte isn't a valid one-byte value */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -