1*37da2899SCharles.Forsyth /***************************************************************************/ 2*37da2899SCharles.Forsyth /* */ 3*37da2899SCharles.Forsyth /* ttcmap0.c */ 4*37da2899SCharles.Forsyth /* */ 5*37da2899SCharles.Forsyth /* TrueType new character mapping table (cmap) support (body). */ 6*37da2899SCharles.Forsyth /* */ 7*37da2899SCharles.Forsyth /* Copyright 2002 by */ 8*37da2899SCharles.Forsyth /* David Turner, Robert Wilhelm, and Werner Lemberg. */ 9*37da2899SCharles.Forsyth /* */ 10*37da2899SCharles.Forsyth /* This file is part of the FreeType project, and may only be used, */ 11*37da2899SCharles.Forsyth /* modified, and distributed under the terms of the FreeType project */ 12*37da2899SCharles.Forsyth /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ 13*37da2899SCharles.Forsyth /* this file you indicate that you have read the license and */ 14*37da2899SCharles.Forsyth /* understand and accept it fully. */ 15*37da2899SCharles.Forsyth /* */ 16*37da2899SCharles.Forsyth /***************************************************************************/ 17*37da2899SCharles.Forsyth 18*37da2899SCharles.Forsyth 19*37da2899SCharles.Forsyth #include <ft2build.h> 20*37da2899SCharles.Forsyth #include FT_INTERNAL_DEBUG_H 21*37da2899SCharles.Forsyth #include FT_INTERNAL_OBJECTS_H 22*37da2899SCharles.Forsyth #include FT_INTERNAL_STREAM_H 23*37da2899SCharles.Forsyth #include "ttload.h" 24*37da2899SCharles.Forsyth #include "ttcmap0.h" 25*37da2899SCharles.Forsyth 26*37da2899SCharles.Forsyth #include "sferrors.h" 27*37da2899SCharles.Forsyth 28*37da2899SCharles.Forsyth /*************************************************************************/ 29*37da2899SCharles.Forsyth /* */ 30*37da2899SCharles.Forsyth /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ 31*37da2899SCharles.Forsyth /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ 32*37da2899SCharles.Forsyth /* messages during execution. */ 33*37da2899SCharles.Forsyth /* */ 34*37da2899SCharles.Forsyth #undef FT_COMPONENT 35*37da2899SCharles.Forsyth #define FT_COMPONENT trace_ttcmap 36*37da2899SCharles.Forsyth 37*37da2899SCharles.Forsyth 38*37da2899SCharles.Forsyth #define TT_PEEK_SHORT FT_PEEK_SHORT 39*37da2899SCharles.Forsyth #define TT_PEEK_USHORT FT_PEEK_USHORT 40*37da2899SCharles.Forsyth #define TT_PEEK_LONG FT_PEEK_LONG 41*37da2899SCharles.Forsyth #define TT_PEEK_ULONG FT_PEEK_ULONG 42*37da2899SCharles.Forsyth 43*37da2899SCharles.Forsyth #define TT_NEXT_SHORT FT_NEXT_SHORT 44*37da2899SCharles.Forsyth #define TT_NEXT_USHORT FT_NEXT_USHORT 45*37da2899SCharles.Forsyth #define TT_NEXT_LONG FT_NEXT_LONG 46*37da2899SCharles.Forsyth #define TT_NEXT_ULONG FT_NEXT_ULONG 47*37da2899SCharles.Forsyth 48*37da2899SCharles.Forsyth 49*37da2899SCharles.Forsyth FT_CALLBACK_DEF( FT_Error ) tt_cmap_init(TT_CMap cmap,FT_Byte * table)50*37da2899SCharles.Forsyth tt_cmap_init( TT_CMap cmap, 51*37da2899SCharles.Forsyth FT_Byte* table ) 52*37da2899SCharles.Forsyth { 53*37da2899SCharles.Forsyth cmap->data = table; 54*37da2899SCharles.Forsyth return 0; 55*37da2899SCharles.Forsyth } 56*37da2899SCharles.Forsyth 57*37da2899SCharles.Forsyth 58*37da2899SCharles.Forsyth /*************************************************************************/ 59*37da2899SCharles.Forsyth /*************************************************************************/ 60*37da2899SCharles.Forsyth /***** *****/ 61*37da2899SCharles.Forsyth /***** FORMAT 0 *****/ 62*37da2899SCharles.Forsyth /***** *****/ 63*37da2899SCharles.Forsyth /*************************************************************************/ 64*37da2899SCharles.Forsyth /*************************************************************************/ 65*37da2899SCharles.Forsyth 66*37da2899SCharles.Forsyth /*************************************************************************/ 67*37da2899SCharles.Forsyth /* */ 68*37da2899SCharles.Forsyth /* TABLE OVERVIEW */ 69*37da2899SCharles.Forsyth /* -------------- */ 70*37da2899SCharles.Forsyth /* */ 71*37da2899SCharles.Forsyth /* NAME OFFSET TYPE DESCRIPTION */ 72*37da2899SCharles.Forsyth /* */ 73*37da2899SCharles.Forsyth /* format 0 USHORT must be 0 */ 74*37da2899SCharles.Forsyth /* length 2 USHORT table length in bytes */ 75*37da2899SCharles.Forsyth /* language 4 USHORT Mac language code */ 76*37da2899SCharles.Forsyth /* glyph_ids 6 BYTE[256] array of glyph indices */ 77*37da2899SCharles.Forsyth /* 262 */ 78*37da2899SCharles.Forsyth /* */ 79*37da2899SCharles.Forsyth 80*37da2899SCharles.Forsyth #ifdef TT_CONFIG_CMAP_FORMAT_0 81*37da2899SCharles.Forsyth 82*37da2899SCharles.Forsyth FT_CALLBACK_DEF( void ) tt_cmap0_validate(FT_Byte * table,FT_Validator valid)83*37da2899SCharles.Forsyth tt_cmap0_validate( FT_Byte* table, 84*37da2899SCharles.Forsyth FT_Validator valid ) 85*37da2899SCharles.Forsyth { 86*37da2899SCharles.Forsyth FT_Byte* p = table + 2; 87*37da2899SCharles.Forsyth FT_UInt length = TT_NEXT_USHORT( p ); 88*37da2899SCharles.Forsyth 89*37da2899SCharles.Forsyth 90*37da2899SCharles.Forsyth if ( table + length > valid->limit || length < 262 ) 91*37da2899SCharles.Forsyth FT_INVALID_TOO_SHORT; 92*37da2899SCharles.Forsyth 93*37da2899SCharles.Forsyth /* check glyph indices whenever necessary */ 94*37da2899SCharles.Forsyth if ( valid->level >= FT_VALIDATE_TIGHT ) 95*37da2899SCharles.Forsyth { 96*37da2899SCharles.Forsyth FT_UInt n, idx; 97*37da2899SCharles.Forsyth 98*37da2899SCharles.Forsyth 99*37da2899SCharles.Forsyth p = table + 6; 100*37da2899SCharles.Forsyth for ( n = 0; n < 256; n++ ) 101*37da2899SCharles.Forsyth { 102*37da2899SCharles.Forsyth idx = *p++; 103*37da2899SCharles.Forsyth if ( idx >= TT_VALID_GLYPH_COUNT( valid ) ) 104*37da2899SCharles.Forsyth FT_INVALID_GLYPH_ID; 105*37da2899SCharles.Forsyth } 106*37da2899SCharles.Forsyth } 107*37da2899SCharles.Forsyth } 108*37da2899SCharles.Forsyth 109*37da2899SCharles.Forsyth 110*37da2899SCharles.Forsyth FT_CALLBACK_DEF( FT_UInt ) tt_cmap0_char_index(TT_CMap cmap,FT_UInt32 char_code)111*37da2899SCharles.Forsyth tt_cmap0_char_index( TT_CMap cmap, 112*37da2899SCharles.Forsyth FT_UInt32 char_code ) 113*37da2899SCharles.Forsyth { 114*37da2899SCharles.Forsyth FT_Byte* table = cmap->data; 115*37da2899SCharles.Forsyth 116*37da2899SCharles.Forsyth 117*37da2899SCharles.Forsyth return char_code < 256 ? table[6 + char_code] : 0; 118*37da2899SCharles.Forsyth } 119*37da2899SCharles.Forsyth 120*37da2899SCharles.Forsyth 121*37da2899SCharles.Forsyth FT_CALLBACK_DEF( FT_UInt ) tt_cmap0_char_next(TT_CMap cmap,FT_UInt32 * pchar_code)122*37da2899SCharles.Forsyth tt_cmap0_char_next( TT_CMap cmap, 123*37da2899SCharles.Forsyth FT_UInt32 *pchar_code ) 124*37da2899SCharles.Forsyth { 125*37da2899SCharles.Forsyth FT_Byte* table = cmap->data; 126*37da2899SCharles.Forsyth FT_UInt32 charcode = *pchar_code; 127*37da2899SCharles.Forsyth FT_UInt32 result = 0; 128*37da2899SCharles.Forsyth FT_UInt gindex = 0; 129*37da2899SCharles.Forsyth 130*37da2899SCharles.Forsyth 131*37da2899SCharles.Forsyth table += 6; /* go to glyph ids */ 132*37da2899SCharles.Forsyth while ( ++charcode < 256 ) 133*37da2899SCharles.Forsyth { 134*37da2899SCharles.Forsyth gindex = table[charcode]; 135*37da2899SCharles.Forsyth if ( gindex != 0 ) 136*37da2899SCharles.Forsyth { 137*37da2899SCharles.Forsyth result = charcode; 138*37da2899SCharles.Forsyth break; 139*37da2899SCharles.Forsyth } 140*37da2899SCharles.Forsyth } 141*37da2899SCharles.Forsyth 142*37da2899SCharles.Forsyth *pchar_code = result; 143*37da2899SCharles.Forsyth return gindex; 144*37da2899SCharles.Forsyth } 145*37da2899SCharles.Forsyth 146*37da2899SCharles.Forsyth 147*37da2899SCharles.Forsyth FT_CALLBACK_TABLE_DEF 148*37da2899SCharles.Forsyth const TT_CMap_ClassRec tt_cmap0_class_rec = 149*37da2899SCharles.Forsyth { 150*37da2899SCharles.Forsyth { 151*37da2899SCharles.Forsyth sizeof( TT_CMapRec ), 152*37da2899SCharles.Forsyth 153*37da2899SCharles.Forsyth (FT_CMap_InitFunc) tt_cmap_init, 154*37da2899SCharles.Forsyth (FT_CMap_DoneFunc) NULL, 155*37da2899SCharles.Forsyth (FT_CMap_CharIndexFunc)tt_cmap0_char_index, 156*37da2899SCharles.Forsyth (FT_CMap_CharNextFunc) tt_cmap0_char_next 157*37da2899SCharles.Forsyth }, 158*37da2899SCharles.Forsyth 0, 159*37da2899SCharles.Forsyth (TT_CMap_ValidateFunc) tt_cmap0_validate 160*37da2899SCharles.Forsyth }; 161*37da2899SCharles.Forsyth 162*37da2899SCharles.Forsyth #endif /* TT_CONFIG_CMAP_FORMAT_0 */ 163*37da2899SCharles.Forsyth 164*37da2899SCharles.Forsyth 165*37da2899SCharles.Forsyth /*************************************************************************/ 166*37da2899SCharles.Forsyth /*************************************************************************/ 167*37da2899SCharles.Forsyth /***** *****/ 168*37da2899SCharles.Forsyth /***** FORMAT 2 *****/ 169*37da2899SCharles.Forsyth /***** *****/ 170*37da2899SCharles.Forsyth /***** This is used for certain CJK encodings that encode text in a *****/ 171*37da2899SCharles.Forsyth /***** mixed 8/16 bits encoding along the following lines: *****/ 172*37da2899SCharles.Forsyth /***** *****/ 173*37da2899SCharles.Forsyth /***** * Certain byte values correspond to an 8-bit character code *****/ 174*37da2899SCharles.Forsyth /***** (typically in the range 0..127 for ASCII compatibility). *****/ 175*37da2899SCharles.Forsyth /***** *****/ 176*37da2899SCharles.Forsyth /***** * Certain byte values signal the first byte of a 2-byte *****/ 177*37da2899SCharles.Forsyth /***** character code (but these values are also valid as the *****/ 178*37da2899SCharles.Forsyth /***** second byte of a 2-byte character). *****/ 179*37da2899SCharles.Forsyth /***** *****/ 180*37da2899SCharles.Forsyth /***** The following charmap lookup and iteration functions all *****/ 181*37da2899SCharles.Forsyth /***** assume that the value "charcode" correspond to following: *****/ 182*37da2899SCharles.Forsyth /***** *****/ 183*37da2899SCharles.Forsyth /***** - For one byte characters, "charcode" is simply the *****/ 184*37da2899SCharles.Forsyth /***** character code. *****/ 185*37da2899SCharles.Forsyth /***** *****/ 186*37da2899SCharles.Forsyth /***** - For two byte characters, "charcode" is the 2-byte *****/ 187*37da2899SCharles.Forsyth /***** character code in big endian format. More exactly: *****/ 188*37da2899SCharles.Forsyth /***** *****/ 189*37da2899SCharles.Forsyth /***** (charcode >> 8) is the first byte value *****/ 190*37da2899SCharles.Forsyth /***** (charcode & 0xFF) is the second byte value *****/ 191*37da2899SCharles.Forsyth /***** *****/ 192*37da2899SCharles.Forsyth /***** Note that not all values of "charcode" are valid according *****/ 193*37da2899SCharles.Forsyth /***** to these rules, and the function moderately check the *****/ 194*37da2899SCharles.Forsyth /***** arguments. *****/ 195*37da2899SCharles.Forsyth /***** *****/ 196*37da2899SCharles.Forsyth /*************************************************************************/ 197*37da2899SCharles.Forsyth /*************************************************************************/ 198*37da2899SCharles.Forsyth 199*37da2899SCharles.Forsyth /*************************************************************************/ 200*37da2899SCharles.Forsyth /* */ 201*37da2899SCharles.Forsyth /* TABLE OVERVIEW */ 202*37da2899SCharles.Forsyth /* -------------- */ 203*37da2899SCharles.Forsyth /* */ 204*37da2899SCharles.Forsyth /* NAME OFFSET TYPE DESCRIPTION */ 205*37da2899SCharles.Forsyth /* */ 206*37da2899SCharles.Forsyth /* format 0 USHORT must be 2 */ 207*37da2899SCharles.Forsyth /* length 2 USHORT table length in bytes */ 208*37da2899SCharles.Forsyth /* language 4 USHORT Mac language code */ 209*37da2899SCharles.Forsyth /* keys 6 USHORT[256] sub-header keys */ 210*37da2899SCharles.Forsyth /* subs 518 SUBHEAD[NSUBS] sub-headers array */ 211*37da2899SCharles.Forsyth /* glyph_ids 518+NSUB*8 USHORT[] glyph id array */ 212*37da2899SCharles.Forsyth /* */ 213*37da2899SCharles.Forsyth /* The `keys' table is used to map charcode high-bytes to sub-headers. */ 214*37da2899SCharles.Forsyth /* The value of `NSUBS' is the number of sub-headers defined in the */ 215*37da2899SCharles.Forsyth /* table and is computed by finding the maximum of the `keys' table. */ 216*37da2899SCharles.Forsyth /* */ 217*37da2899SCharles.Forsyth /* Note that for any n, `keys[n]' is a byte offset within the `subs' */ 218*37da2899SCharles.Forsyth /* table, i.e., it is the corresponding sub-header index multiplied */ 219*37da2899SCharles.Forsyth /* by 8. */ 220*37da2899SCharles.Forsyth /* */ 221*37da2899SCharles.Forsyth /* Each sub-header has the following format: */ 222*37da2899SCharles.Forsyth /* */ 223*37da2899SCharles.Forsyth /* NAME OFFSET TYPE DESCRIPTION */ 224*37da2899SCharles.Forsyth /* */ 225*37da2899SCharles.Forsyth /* first 0 USHORT first valid low-byte */ 226*37da2899SCharles.Forsyth /* count 2 USHORT number of valid low-bytes */ 227*37da2899SCharles.Forsyth /* delta 4 SHORT see below */ 228*37da2899SCharles.Forsyth /* offset 6 USHORT see below */ 229*37da2899SCharles.Forsyth /* */ 230*37da2899SCharles.Forsyth /* A sub-header defines, for each high-byte, the range of valid */ 231*37da2899SCharles.Forsyth /* low-bytes within the charmap. Note that the range defined by `first' */ 232*37da2899SCharles.Forsyth /* and `count' must be completely included in the interval [0..255] */ 233*37da2899SCharles.Forsyth /* according to the specification. */ 234*37da2899SCharles.Forsyth /* */ 235*37da2899SCharles.Forsyth /* If a character code is contained within a given sub-header, then */ 236*37da2899SCharles.Forsyth /* mapping it to a glyph index is done as follows: */ 237*37da2899SCharles.Forsyth /* */ 238*37da2899SCharles.Forsyth /* * The value of `offset' is read. This is a _byte_ distance from the */ 239*37da2899SCharles.Forsyth /* location of the `offset' field itself into a slice of the */ 240*37da2899SCharles.Forsyth /* `glyph_ids' table. Let's call it `slice' (it's a USHORT[] too). */ 241*37da2899SCharles.Forsyth /* */ 242*37da2899SCharles.Forsyth /* * The value `slice[char.lo - first]' is read. If it is 0, there is */ 243*37da2899SCharles.Forsyth /* no glyph for the charcode. Otherwise, the value of `delta' is */ 244*37da2899SCharles.Forsyth /* added to it (modulo 65536) to form a new glyph index. */ 245*37da2899SCharles.Forsyth /* */ 246*37da2899SCharles.Forsyth /* It is up to the validation routine to check that all offsets fall */ 247*37da2899SCharles.Forsyth /* within the glyph ids table (and not within the `subs' table itself or */ 248*37da2899SCharles.Forsyth /* outside of the CMap). */ 249*37da2899SCharles.Forsyth /* */ 250*37da2899SCharles.Forsyth 251*37da2899SCharles.Forsyth #ifdef TT_CONFIG_CMAP_FORMAT_2 252*37da2899SCharles.Forsyth 253*37da2899SCharles.Forsyth FT_CALLBACK_DEF( void ) tt_cmap2_validate(FT_Byte * table,FT_Validator valid)254*37da2899SCharles.Forsyth tt_cmap2_validate( FT_Byte* table, 255*37da2899SCharles.Forsyth FT_Validator valid ) 256*37da2899SCharles.Forsyth { 257*37da2899SCharles.Forsyth FT_Byte* p = table + 2; /* skip format */ 258*37da2899SCharles.Forsyth FT_UInt length = TT_PEEK_USHORT( p ); 259*37da2899SCharles.Forsyth FT_UInt n, max_subs; 260*37da2899SCharles.Forsyth FT_Byte* keys; /* keys table */ 261*37da2899SCharles.Forsyth FT_Byte* subs; /* sub-headers */ 262*37da2899SCharles.Forsyth FT_Byte* glyph_ids; /* glyph id array */ 263*37da2899SCharles.Forsyth 264*37da2899SCharles.Forsyth 265*37da2899SCharles.Forsyth if ( table + length > valid->limit || length < 6 + 512 ) 266*37da2899SCharles.Forsyth FT_INVALID_TOO_SHORT; 267*37da2899SCharles.Forsyth 268*37da2899SCharles.Forsyth keys = table + 6; 269*37da2899SCharles.Forsyth 270*37da2899SCharles.Forsyth /* parse keys to compute sub-headers count */ 271*37da2899SCharles.Forsyth p = keys; 272*37da2899SCharles.Forsyth max_subs = 0; 273*37da2899SCharles.Forsyth for ( n = 0; n < 256; n++ ) 274*37da2899SCharles.Forsyth { 275*37da2899SCharles.Forsyth FT_UInt idx = TT_NEXT_USHORT( p ); 276*37da2899SCharles.Forsyth 277*37da2899SCharles.Forsyth 278*37da2899SCharles.Forsyth /* value must be multiple of 8 */ 279*37da2899SCharles.Forsyth if ( valid->level >= FT_VALIDATE_PARANOID && ( idx & 7 ) != 0 ) 280*37da2899SCharles.Forsyth FT_INVALID_DATA; 281*37da2899SCharles.Forsyth 282*37da2899SCharles.Forsyth idx >>= 3; 283*37da2899SCharles.Forsyth 284*37da2899SCharles.Forsyth if ( idx > max_subs ) 285*37da2899SCharles.Forsyth max_subs = idx; 286*37da2899SCharles.Forsyth } 287*37da2899SCharles.Forsyth 288*37da2899SCharles.Forsyth FT_ASSERT( p == table + 518 ); 289*37da2899SCharles.Forsyth 290*37da2899SCharles.Forsyth subs = p; 291*37da2899SCharles.Forsyth glyph_ids = subs + (max_subs + 1) * 8; 292*37da2899SCharles.Forsyth if ( glyph_ids > valid->limit ) 293*37da2899SCharles.Forsyth FT_INVALID_TOO_SHORT; 294*37da2899SCharles.Forsyth 295*37da2899SCharles.Forsyth /* parse sub-headers */ 296*37da2899SCharles.Forsyth for ( n = 0; n <= max_subs; n++ ) 297*37da2899SCharles.Forsyth { 298*37da2899SCharles.Forsyth FT_UInt first_code, code_count, offset; 299*37da2899SCharles.Forsyth FT_Int delta; 300*37da2899SCharles.Forsyth FT_Byte* ids; 301*37da2899SCharles.Forsyth 302*37da2899SCharles.Forsyth 303*37da2899SCharles.Forsyth first_code = TT_NEXT_USHORT( p ); 304*37da2899SCharles.Forsyth code_count = TT_NEXT_USHORT( p ); 305*37da2899SCharles.Forsyth delta = TT_NEXT_SHORT( p ); 306*37da2899SCharles.Forsyth offset = TT_NEXT_USHORT( p ); 307*37da2899SCharles.Forsyth 308*37da2899SCharles.Forsyth /* check range within 0..255 */ 309*37da2899SCharles.Forsyth if ( valid->level >= FT_VALIDATE_PARANOID ) 310*37da2899SCharles.Forsyth { 311*37da2899SCharles.Forsyth if ( first_code >= 256 || first_code + code_count > 256 ) 312*37da2899SCharles.Forsyth FT_INVALID_DATA; 313*37da2899SCharles.Forsyth } 314*37da2899SCharles.Forsyth 315*37da2899SCharles.Forsyth /* check offset */ 316*37da2899SCharles.Forsyth if ( offset != 0 ) 317*37da2899SCharles.Forsyth { 318*37da2899SCharles.Forsyth ids = p - 2 + offset; 319*37da2899SCharles.Forsyth if ( ids < glyph_ids || ids + code_count*2 > table + length ) 320*37da2899SCharles.Forsyth FT_INVALID_OFFSET; 321*37da2899SCharles.Forsyth 322*37da2899SCharles.Forsyth /* check glyph ids */ 323*37da2899SCharles.Forsyth if ( valid->level >= FT_VALIDATE_TIGHT ) 324*37da2899SCharles.Forsyth { 325*37da2899SCharles.Forsyth FT_Byte* limit = p + code_count * 2; 326*37da2899SCharles.Forsyth FT_UInt idx; 327*37da2899SCharles.Forsyth 328*37da2899SCharles.Forsyth 329*37da2899SCharles.Forsyth for ( ; p < limit; ) 330*37da2899SCharles.Forsyth { 331*37da2899SCharles.Forsyth idx = TT_NEXT_USHORT( p ); 332*37da2899SCharles.Forsyth if ( idx != 0 ) 333*37da2899SCharles.Forsyth { 334*37da2899SCharles.Forsyth idx = ( idx + delta ) & 0xFFFFU; 335*37da2899SCharles.Forsyth if ( idx >= TT_VALID_GLYPH_COUNT( valid ) ) 336*37da2899SCharles.Forsyth FT_INVALID_GLYPH_ID; 337*37da2899SCharles.Forsyth } 338*37da2899SCharles.Forsyth } 339*37da2899SCharles.Forsyth } 340*37da2899SCharles.Forsyth } 341*37da2899SCharles.Forsyth } 342*37da2899SCharles.Forsyth } 343*37da2899SCharles.Forsyth 344*37da2899SCharles.Forsyth 345*37da2899SCharles.Forsyth /* return sub header corresponding to a given character code */ 346*37da2899SCharles.Forsyth /* NULL on invalid charcode */ 347*37da2899SCharles.Forsyth static FT_Byte* tt_cmap2_get_subheader(FT_Byte * table,FT_UInt32 char_code)348*37da2899SCharles.Forsyth tt_cmap2_get_subheader( FT_Byte* table, 349*37da2899SCharles.Forsyth FT_UInt32 char_code ) 350*37da2899SCharles.Forsyth { 351*37da2899SCharles.Forsyth FT_Byte* result = NULL; 352*37da2899SCharles.Forsyth 353*37da2899SCharles.Forsyth 354*37da2899SCharles.Forsyth if ( char_code < 0x10000UL ) 355*37da2899SCharles.Forsyth { 356*37da2899SCharles.Forsyth FT_UInt char_lo = (FT_UInt)( char_code & 0xFF ); 357*37da2899SCharles.Forsyth FT_UInt char_hi = (FT_UInt)( char_code >> 8 ); 358*37da2899SCharles.Forsyth FT_Byte* p = table + 6; /* keys table */ 359*37da2899SCharles.Forsyth FT_Byte* subs = table + 518; /* subheaders table */ 360*37da2899SCharles.Forsyth FT_Byte* sub; 361*37da2899SCharles.Forsyth 362*37da2899SCharles.Forsyth 363*37da2899SCharles.Forsyth if ( char_hi == 0 ) 364*37da2899SCharles.Forsyth { 365*37da2899SCharles.Forsyth /* an 8-bit character code -- we use subHeader 0 in this case */ 366*37da2899SCharles.Forsyth /* to test whether the character code is in the charmap */ 367*37da2899SCharles.Forsyth /* */ 368*37da2899SCharles.Forsyth sub = subs; /* jump to first sub-header */ 369*37da2899SCharles.Forsyth 370*37da2899SCharles.Forsyth /* check that the sub-header for this byte is 0, which */ 371*37da2899SCharles.Forsyth /* indicates that it's really a valid one-byte value */ 372*37da2899SCharles.Forsyth /* Otherwise, return 0 */ 373*37da2899SCharles.Forsyth /* */ 374*37da2899SCharles.Forsyth p += char_lo * 2; 375*37da2899SCharles.Forsyth if ( TT_PEEK_USHORT( p ) != 0 ) 376*37da2899SCharles.Forsyth goto Exit; 377*37da2899SCharles.Forsyth } 378*37da2899SCharles.Forsyth else 379*37da2899SCharles.Forsyth { 380*37da2899SCharles.Forsyth /* a 16-bit character code */ 381*37da2899SCharles.Forsyth p += char_hi * 2; /* jump to key entry */ 382*37da2899SCharles.Forsyth sub = subs + ( TT_PEEK_USHORT( p ) & -8 ); /* jump to sub-header */ 383*37da2899SCharles.Forsyth 384*37da2899SCharles.Forsyth /* check that the hi byte isn't a valid one-byte value */ 385*37da2899SCharles.Forsyth if ( sub == subs ) 386*37da2899SCharles.Forsyth goto Exit; 387*37da2899SCharles.Forsyth } 388*37da2899SCharles.Forsyth result = sub; 389*37da2899SCharles.Forsyth } 390*37da2899SCharles.Forsyth Exit: 391*37da2899SCharles.Forsyth return result; 392*37da2899SCharles.Forsyth } 393*37da2899SCharles.Forsyth 394*37da2899SCharles.Forsyth 395*37da2899SCharles.Forsyth FT_CALLBACK_DEF( FT_UInt ) tt_cmap2_char_index(TT_CMap cmap,FT_UInt32 char_code)396*37da2899SCharles.Forsyth tt_cmap2_char_index( TT_CMap cmap, 397*37da2899SCharles.Forsyth FT_UInt32 char_code ) 398*37da2899SCharles.Forsyth { 399*37da2899SCharles.Forsyth FT_Byte* table = cmap->data; 400*37da2899SCharles.Forsyth FT_UInt result = 0; 401*37da2899SCharles.Forsyth FT_Byte* subheader; 402*37da2899SCharles.Forsyth 403*37da2899SCharles.Forsyth 404*37da2899SCharles.Forsyth subheader = tt_cmap2_get_subheader( table, char_code ); 405*37da2899SCharles.Forsyth if ( subheader ) 406*37da2899SCharles.Forsyth { 407*37da2899SCharles.Forsyth FT_Byte* p = subheader; 408*37da2899SCharles.Forsyth FT_UInt idx = (FT_UInt)(char_code & 0xFF); 409*37da2899SCharles.Forsyth FT_UInt start, count; 410*37da2899SCharles.Forsyth FT_Int delta; 411*37da2899SCharles.Forsyth FT_UInt offset; 412*37da2899SCharles.Forsyth 413*37da2899SCharles.Forsyth 414*37da2899SCharles.Forsyth start = TT_NEXT_USHORT( p ); 415*37da2899SCharles.Forsyth count = TT_NEXT_USHORT( p ); 416*37da2899SCharles.Forsyth delta = TT_NEXT_SHORT ( p ); 417*37da2899SCharles.Forsyth offset = TT_PEEK_USHORT( p ); 418*37da2899SCharles.Forsyth 419*37da2899SCharles.Forsyth idx -= start; 420*37da2899SCharles.Forsyth if ( idx < count && offset != 0 ) 421*37da2899SCharles.Forsyth { 422*37da2899SCharles.Forsyth p += offset + 2 * idx; 423*37da2899SCharles.Forsyth idx = TT_PEEK_USHORT( p ); 424*37da2899SCharles.Forsyth 425*37da2899SCharles.Forsyth if ( idx != 0 ) 426*37da2899SCharles.Forsyth result = (FT_UInt)( idx + delta ) & 0xFFFFU; 427*37da2899SCharles.Forsyth } 428*37da2899SCharles.Forsyth } 429*37da2899SCharles.Forsyth return result; 430*37da2899SCharles.Forsyth } 431*37da2899SCharles.Forsyth 432*37da2899SCharles.Forsyth 433*37da2899SCharles.Forsyth FT_CALLBACK_DEF( FT_UInt ) tt_cmap2_char_next(TT_CMap cmap,FT_UInt32 * pcharcode)434*37da2899SCharles.Forsyth tt_cmap2_char_next( TT_CMap cmap, 435*37da2899SCharles.Forsyth FT_UInt32 *pcharcode ) 436*37da2899SCharles.Forsyth { 437*37da2899SCharles.Forsyth FT_Byte* table = cmap->data; 438*37da2899SCharles.Forsyth FT_UInt gindex = 0; 439*37da2899SCharles.Forsyth FT_UInt32 result = 0; 440*37da2899SCharles.Forsyth FT_UInt32 charcode = *pcharcode + 1; 441*37da2899SCharles.Forsyth FT_Byte* subheader; 442*37da2899SCharles.Forsyth 443*37da2899SCharles.Forsyth 444*37da2899SCharles.Forsyth while ( charcode < 0x10000UL ) 445*37da2899SCharles.Forsyth { 446*37da2899SCharles.Forsyth subheader = tt_cmap2_get_subheader( table, charcode ); 447*37da2899SCharles.Forsyth if ( subheader ) 448*37da2899SCharles.Forsyth { 449*37da2899SCharles.Forsyth FT_Byte* p = subheader; 450*37da2899SCharles.Forsyth FT_UInt start = TT_NEXT_USHORT( p ); 451*37da2899SCharles.Forsyth FT_UInt count = TT_NEXT_USHORT( p ); 452*37da2899SCharles.Forsyth FT_Int delta = TT_NEXT_SHORT ( p ); 453*37da2899SCharles.Forsyth FT_UInt offset = TT_PEEK_USHORT( p ); 454*37da2899SCharles.Forsyth FT_UInt char_lo = (FT_UInt)( charcode & 0xFF ); 455*37da2899SCharles.Forsyth FT_UInt pos, idx; 456*37da2899SCharles.Forsyth 457*37da2899SCharles.Forsyth 458*37da2899SCharles.Forsyth if ( offset == 0 ) 459*37da2899SCharles.Forsyth goto Next_SubHeader; 460*37da2899SCharles.Forsyth 461*37da2899SCharles.Forsyth if ( char_lo < start ) 462*37da2899SCharles.Forsyth { 463*37da2899SCharles.Forsyth char_lo = start; 464*37da2899SCharles.Forsyth pos = 0; 465*37da2899SCharles.Forsyth } 466*37da2899SCharles.Forsyth else 467*37da2899SCharles.Forsyth pos = (FT_UInt)( char_lo - start ); 468*37da2899SCharles.Forsyth 469*37da2899SCharles.Forsyth p += offset + pos * 2; 470*37da2899SCharles.Forsyth charcode = ( charcode & -256 ) + char_lo; 471*37da2899SCharles.Forsyth 472*37da2899SCharles.Forsyth for ( ; pos < count; pos++, charcode++ ) 473*37da2899SCharles.Forsyth { 474*37da2899SCharles.Forsyth idx = TT_NEXT_USHORT( p ); 475*37da2899SCharles.Forsyth 476*37da2899SCharles.Forsyth if ( idx != 0 ) 477*37da2899SCharles.Forsyth { 478*37da2899SCharles.Forsyth gindex = ( idx + delta ) & 0xFFFFU; 479*37da2899SCharles.Forsyth if ( gindex != 0 ) 480*37da2899SCharles.Forsyth { 481*37da2899SCharles.Forsyth result = charcode; 482*37da2899SCharles.Forsyth goto Exit; 483*37da2899SCharles.Forsyth } 484*37da2899SCharles.Forsyth } 485*37da2899SCharles.Forsyth } 486*37da2899SCharles.Forsyth } 487*37da2899SCharles.Forsyth 488*37da2899SCharles.Forsyth /* jump to next sub-header, i.e. higher byte value */ 489*37da2899SCharles.Forsyth Next_SubHeader: 490*37da2899SCharles.Forsyth charcode = ( charcode & -256 ) + 256; 491*37da2899SCharles.Forsyth } 492*37da2899SCharles.Forsyth 493*37da2899SCharles.Forsyth Exit: 494*37da2899SCharles.Forsyth *pcharcode = result; 495*37da2899SCharles.Forsyth 496*37da2899SCharles.Forsyth return gindex; 497*37da2899SCharles.Forsyth } 498*37da2899SCharles.Forsyth 499*37da2899SCharles.Forsyth 500*37da2899SCharles.Forsyth FT_CALLBACK_TABLE_DEF 501*37da2899SCharles.Forsyth const TT_CMap_ClassRec tt_cmap2_class_rec = 502*37da2899SCharles.Forsyth { 503*37da2899SCharles.Forsyth { 504*37da2899SCharles.Forsyth sizeof( TT_CMapRec ), 505*37da2899SCharles.Forsyth 506*37da2899SCharles.Forsyth (FT_CMap_InitFunc) tt_cmap_init, 507*37da2899SCharles.Forsyth (FT_CMap_DoneFunc) NULL, 508*37da2899SCharles.Forsyth (FT_CMap_CharIndexFunc)tt_cmap2_char_index, 509*37da2899SCharles.Forsyth (FT_CMap_CharNextFunc) tt_cmap2_char_next 510*37da2899SCharles.Forsyth }, 511*37da2899SCharles.Forsyth 2, 512*37da2899SCharles.Forsyth (TT_CMap_ValidateFunc) tt_cmap2_validate 513*37da2899SCharles.Forsyth }; 514*37da2899SCharles.Forsyth 515*37da2899SCharles.Forsyth #endif /* TT_CONFIG_CMAP_FORMAT_2 */ 516*37da2899SCharles.Forsyth 517*37da2899SCharles.Forsyth 518*37da2899SCharles.Forsyth /*************************************************************************/ 519*37da2899SCharles.Forsyth /*************************************************************************/ 520*37da2899SCharles.Forsyth /***** *****/ 521*37da2899SCharles.Forsyth /***** FORMAT 4 *****/ 522*37da2899SCharles.Forsyth /***** *****/ 523*37da2899SCharles.Forsyth /*************************************************************************/ 524*37da2899SCharles.Forsyth /*************************************************************************/ 525*37da2899SCharles.Forsyth 526*37da2899SCharles.Forsyth /*************************************************************************/ 527*37da2899SCharles.Forsyth /* */ 528*37da2899SCharles.Forsyth /* TABLE OVERVIEW */ 529*37da2899SCharles.Forsyth /* -------------- */ 530*37da2899SCharles.Forsyth /* */ 531*37da2899SCharles.Forsyth /* NAME OFFSET TYPE DESCRIPTION */ 532*37da2899SCharles.Forsyth /* */ 533*37da2899SCharles.Forsyth /* format 0 USHORT must be 4 */ 534*37da2899SCharles.Forsyth /* length 2 USHORT table length */ 535*37da2899SCharles.Forsyth /* in bytes */ 536*37da2899SCharles.Forsyth /* language 4 USHORT Mac language code */ 537*37da2899SCharles.Forsyth /* */ 538*37da2899SCharles.Forsyth /* segCountX2 6 USHORT 2*NUM_SEGS */ 539*37da2899SCharles.Forsyth /* searchRange 8 USHORT 2*(1 << LOG_SEGS) */ 540*37da2899SCharles.Forsyth /* entrySelector 10 USHORT LOG_SEGS */ 541*37da2899SCharles.Forsyth /* rangeShift 12 USHORT segCountX2 - */ 542*37da2899SCharles.Forsyth /* searchRange */ 543*37da2899SCharles.Forsyth /* */ 544*37da2899SCharles.Forsyth /* endCount 14 USHORT[NUM_SEGS] end charcode for */ 545*37da2899SCharles.Forsyth /* each segment; last */ 546*37da2899SCharles.Forsyth /* is 0xFFFF */ 547*37da2899SCharles.Forsyth /* */ 548*37da2899SCharles.Forsyth /* pad 14+NUM_SEGS*2 USHORT padding */ 549*37da2899SCharles.Forsyth /* */ 550*37da2899SCharles.Forsyth /* startCount 16+NUM_SEGS*2 USHORT[NUM_SEGS] first charcode for */ 551*37da2899SCharles.Forsyth /* each segment */ 552*37da2899SCharles.Forsyth /* */ 553*37da2899SCharles.Forsyth /* idDelta 16+NUM_SEGS*4 SHORT[NUM_SEGS] delta for each */ 554*37da2899SCharles.Forsyth /* segment */ 555*37da2899SCharles.Forsyth /* idOffset 16+NUM_SEGS*6 SHORT[NUM_SEGS] range offset for */ 556*37da2899SCharles.Forsyth /* each segment; can be */ 557*37da2899SCharles.Forsyth /* zero */ 558*37da2899SCharles.Forsyth /* */ 559*37da2899SCharles.Forsyth /* glyphIds 16+NUM_SEGS*8 USHORT[] array of glyph id */ 560*37da2899SCharles.Forsyth /* ranges */ 561*37da2899SCharles.Forsyth /* */ 562*37da2899SCharles.Forsyth /* Character codes are modelled by a series of ordered (increasing) */ 563*37da2899SCharles.Forsyth /* intervals called segments. Each segment has start and end codes, */ 564*37da2899SCharles.Forsyth /* provided by the `startCount' and `endCount' arrays. Segments must */ 565*37da2899SCharles.Forsyth /* not be overlapping and the last segment should always contain the */ 566*37da2899SCharles.Forsyth /* `0xFFFF' endCount. */ 567*37da2899SCharles.Forsyth /* */ 568*37da2899SCharles.Forsyth /* The fields `searchRange', `entrySelector' and `rangeShift' are better */ 569*37da2899SCharles.Forsyth /* ignored (they are traces of over-engineering in the TrueType */ 570*37da2899SCharles.Forsyth /* specification). */ 571*37da2899SCharles.Forsyth /* */ 572*37da2899SCharles.Forsyth /* Each segment also has a signed `delta', as well as an optional offset */ 573*37da2899SCharles.Forsyth /* within the `glyphIds' table. */ 574*37da2899SCharles.Forsyth /* */ 575*37da2899SCharles.Forsyth /* If a segment's idOffset is 0, the glyph index corresponding to any */ 576*37da2899SCharles.Forsyth /* charcode within the segment is obtained by adding the value of */ 577*37da2899SCharles.Forsyth /* `idDelta' directly to the charcode, modulo 65536. */ 578*37da2899SCharles.Forsyth /* */ 579*37da2899SCharles.Forsyth /* Otherwise, a glyph index is taken from the glyph ids sub-array for */ 580*37da2899SCharles.Forsyth /* the segment, and the value of `idDelta' is added to it. */ 581*37da2899SCharles.Forsyth /* */ 582*37da2899SCharles.Forsyth /* */ 583*37da2899SCharles.Forsyth /* Finally, note that certain fonts contain invalid charmaps that */ 584*37da2899SCharles.Forsyth /* contain end=0xFFFF, start=0xFFFF, delta=0x0001, offset=0xFFFF at the */ 585*37da2899SCharles.Forsyth /* of their charmaps (e.g. opens___.ttf which comes with OpenOffice.org) */ 586*37da2899SCharles.Forsyth /* we need special code to deal with them correctly... */ 587*37da2899SCharles.Forsyth /* */ 588*37da2899SCharles.Forsyth 589*37da2899SCharles.Forsyth #ifdef TT_CONFIG_CMAP_FORMAT_4 590*37da2899SCharles.Forsyth 591*37da2899SCharles.Forsyth FT_CALLBACK_DEF( void ) tt_cmap4_validate(FT_Byte * table,FT_Validator valid)592*37da2899SCharles.Forsyth tt_cmap4_validate( FT_Byte* table, 593*37da2899SCharles.Forsyth FT_Validator valid ) 594*37da2899SCharles.Forsyth { 595*37da2899SCharles.Forsyth FT_Byte* p = table + 2; /* skip format */ 596*37da2899SCharles.Forsyth FT_UInt length = TT_NEXT_USHORT( p ); 597*37da2899SCharles.Forsyth FT_Byte *ends, *starts, *offsets, *deltas, *glyph_ids; 598*37da2899SCharles.Forsyth FT_UInt num_segs; 599*37da2899SCharles.Forsyth 600*37da2899SCharles.Forsyth 601*37da2899SCharles.Forsyth /* in certain fonts, the `length' field is invalid and goes */ 602*37da2899SCharles.Forsyth /* out of bound. We try to correct this here... */ 603*37da2899SCharles.Forsyth if ( length < 16 ) 604*37da2899SCharles.Forsyth FT_INVALID_TOO_SHORT; 605*37da2899SCharles.Forsyth 606*37da2899SCharles.Forsyth if ( table + length > valid->limit ) 607*37da2899SCharles.Forsyth { 608*37da2899SCharles.Forsyth if ( valid->level >= FT_VALIDATE_TIGHT ) 609*37da2899SCharles.Forsyth FT_INVALID_TOO_SHORT; 610*37da2899SCharles.Forsyth 611*37da2899SCharles.Forsyth length = (FT_UInt)( valid->limit - table ); 612*37da2899SCharles.Forsyth } 613*37da2899SCharles.Forsyth 614*37da2899SCharles.Forsyth p = table + 6; 615*37da2899SCharles.Forsyth num_segs = TT_NEXT_USHORT( p ); /* read segCountX2 */ 616*37da2899SCharles.Forsyth 617*37da2899SCharles.Forsyth if ( valid->level >= FT_VALIDATE_PARANOID ) 618*37da2899SCharles.Forsyth { 619*37da2899SCharles.Forsyth /* check that we have an even value here */ 620*37da2899SCharles.Forsyth if ( num_segs & 1 ) 621*37da2899SCharles.Forsyth FT_INVALID_DATA; 622*37da2899SCharles.Forsyth } 623*37da2899SCharles.Forsyth 624*37da2899SCharles.Forsyth num_segs /= 2; 625*37da2899SCharles.Forsyth 626*37da2899SCharles.Forsyth /* check the search parameters - even though we never use them */ 627*37da2899SCharles.Forsyth /* */ 628*37da2899SCharles.Forsyth if ( valid->level >= FT_VALIDATE_PARANOID ) 629*37da2899SCharles.Forsyth { 630*37da2899SCharles.Forsyth /* check the values of 'searchRange', 'entrySelector', 'rangeShift' */ 631*37da2899SCharles.Forsyth FT_UInt search_range = TT_NEXT_USHORT( p ); 632*37da2899SCharles.Forsyth FT_UInt entry_selector = TT_NEXT_USHORT( p ); 633*37da2899SCharles.Forsyth FT_UInt range_shift = TT_NEXT_USHORT( p ); 634*37da2899SCharles.Forsyth 635*37da2899SCharles.Forsyth 636*37da2899SCharles.Forsyth if ( ( search_range | range_shift ) & 1 ) /* must be even values */ 637*37da2899SCharles.Forsyth FT_INVALID_DATA; 638*37da2899SCharles.Forsyth 639*37da2899SCharles.Forsyth search_range /= 2; 640*37da2899SCharles.Forsyth range_shift /= 2; 641*37da2899SCharles.Forsyth 642*37da2899SCharles.Forsyth /* `search range' is the greatest power of 2 that is <= num_segs */ 643*37da2899SCharles.Forsyth 644*37da2899SCharles.Forsyth if ( search_range > num_segs || 645*37da2899SCharles.Forsyth search_range * 2 < num_segs || 646*37da2899SCharles.Forsyth search_range + range_shift != num_segs || 647*37da2899SCharles.Forsyth search_range != ( 1U << entry_selector ) ) 648*37da2899SCharles.Forsyth FT_INVALID_DATA; 649*37da2899SCharles.Forsyth } 650*37da2899SCharles.Forsyth 651*37da2899SCharles.Forsyth ends = table + 14; 652*37da2899SCharles.Forsyth starts = table + 16 + num_segs * 2; 653*37da2899SCharles.Forsyth deltas = starts + num_segs * 2; 654*37da2899SCharles.Forsyth offsets = deltas + num_segs * 2; 655*37da2899SCharles.Forsyth glyph_ids = offsets + num_segs * 2; 656*37da2899SCharles.Forsyth 657*37da2899SCharles.Forsyth if ( glyph_ids > table + length ) 658*37da2899SCharles.Forsyth FT_INVALID_TOO_SHORT; 659*37da2899SCharles.Forsyth 660*37da2899SCharles.Forsyth /* check last segment, its end count must be FFFF */ 661*37da2899SCharles.Forsyth if ( valid->level >= FT_VALIDATE_PARANOID ) 662*37da2899SCharles.Forsyth { 663*37da2899SCharles.Forsyth p = ends + ( num_segs - 1 ) * 2; 664*37da2899SCharles.Forsyth if ( TT_PEEK_USHORT( p ) != 0xFFFFU ) 665*37da2899SCharles.Forsyth FT_INVALID_DATA; 666*37da2899SCharles.Forsyth } 667*37da2899SCharles.Forsyth 668*37da2899SCharles.Forsyth /* check that segments are sorted in increasing order and do not */ 669*37da2899SCharles.Forsyth /* overlap; check also the offsets */ 670*37da2899SCharles.Forsyth { 671*37da2899SCharles.Forsyth FT_UInt start, end, last = 0, offset, n; 672*37da2899SCharles.Forsyth FT_Int delta; 673*37da2899SCharles.Forsyth 674*37da2899SCharles.Forsyth 675*37da2899SCharles.Forsyth for ( n = 0; n < num_segs; n++ ) 676*37da2899SCharles.Forsyth { 677*37da2899SCharles.Forsyth p = starts + n * 2; 678*37da2899SCharles.Forsyth start = TT_PEEK_USHORT( p ); 679*37da2899SCharles.Forsyth p = ends + n * 2; 680*37da2899SCharles.Forsyth end = TT_PEEK_USHORT( p ); 681*37da2899SCharles.Forsyth p = deltas + n * 2; 682*37da2899SCharles.Forsyth delta = TT_PEEK_SHORT( p ); 683*37da2899SCharles.Forsyth p = offsets + n * 2; 684*37da2899SCharles.Forsyth offset = TT_PEEK_USHORT( p ); 685*37da2899SCharles.Forsyth 686*37da2899SCharles.Forsyth if ( start > end ) 687*37da2899SCharles.Forsyth FT_INVALID_DATA; 688*37da2899SCharles.Forsyth 689*37da2899SCharles.Forsyth /* this test should be performed at default validation level; */ 690*37da2899SCharles.Forsyth /* unfortunately, some popular Asian fonts present overlapping */ 691*37da2899SCharles.Forsyth /* ranges in their charmaps */ 692*37da2899SCharles.Forsyth /* */ 693*37da2899SCharles.Forsyth if ( valid->level >= FT_VALIDATE_TIGHT ) 694*37da2899SCharles.Forsyth { 695*37da2899SCharles.Forsyth if ( n > 0 && start <= last ) 696*37da2899SCharles.Forsyth FT_INVALID_DATA; 697*37da2899SCharles.Forsyth } 698*37da2899SCharles.Forsyth 699*37da2899SCharles.Forsyth if ( offset && offset != 0xFFFFU ) 700*37da2899SCharles.Forsyth { 701*37da2899SCharles.Forsyth p += offset; /* start of glyph id array */ 702*37da2899SCharles.Forsyth 703*37da2899SCharles.Forsyth /* check that we point within the glyph ids table only */ 704*37da2899SCharles.Forsyth if ( p < glyph_ids || 705*37da2899SCharles.Forsyth p + ( end - start + 1 ) * 2 > table + length ) 706*37da2899SCharles.Forsyth FT_INVALID_DATA; 707*37da2899SCharles.Forsyth 708*37da2899SCharles.Forsyth /* check glyph indices within the segment range */ 709*37da2899SCharles.Forsyth if ( valid->level >= FT_VALIDATE_TIGHT ) 710*37da2899SCharles.Forsyth { 711*37da2899SCharles.Forsyth FT_UInt i, idx; 712*37da2899SCharles.Forsyth 713*37da2899SCharles.Forsyth 714*37da2899SCharles.Forsyth for ( i = start; i < end; i++ ) 715*37da2899SCharles.Forsyth { 716*37da2899SCharles.Forsyth idx = FT_NEXT_USHORT( p ); 717*37da2899SCharles.Forsyth if ( idx != 0 ) 718*37da2899SCharles.Forsyth { 719*37da2899SCharles.Forsyth idx = (FT_UInt)( idx + delta ) & 0xFFFFU; 720*37da2899SCharles.Forsyth 721*37da2899SCharles.Forsyth if ( idx >= TT_VALID_GLYPH_COUNT( valid ) ) 722*37da2899SCharles.Forsyth FT_INVALID_GLYPH_ID; 723*37da2899SCharles.Forsyth } 724*37da2899SCharles.Forsyth } 725*37da2899SCharles.Forsyth } 726*37da2899SCharles.Forsyth } 727*37da2899SCharles.Forsyth else if ( offset == 0xFFFFU ) 728*37da2899SCharles.Forsyth { 729*37da2899SCharles.Forsyth /* Some fonts (erroneously?) use a range offset of 0xFFFF */ 730*37da2899SCharles.Forsyth /* to mean missing glyph in cmap table */ 731*37da2899SCharles.Forsyth /* */ 732*37da2899SCharles.Forsyth if ( valid->level >= FT_VALIDATE_PARANOID || 733*37da2899SCharles.Forsyth n != num_segs - 1 || 734*37da2899SCharles.Forsyth !( start == 0xFFFFU && end == 0xFFFFU && delta == 0x1U ) ) 735*37da2899SCharles.Forsyth FT_INVALID_DATA; 736*37da2899SCharles.Forsyth } 737*37da2899SCharles.Forsyth 738*37da2899SCharles.Forsyth last = end; 739*37da2899SCharles.Forsyth } 740*37da2899SCharles.Forsyth } 741*37da2899SCharles.Forsyth } 742*37da2899SCharles.Forsyth 743*37da2899SCharles.Forsyth 744*37da2899SCharles.Forsyth FT_CALLBACK_DEF( FT_UInt ) tt_cmap4_char_index(TT_CMap cmap,FT_UInt32 char_code)745*37da2899SCharles.Forsyth tt_cmap4_char_index( TT_CMap cmap, 746*37da2899SCharles.Forsyth FT_UInt32 char_code ) 747*37da2899SCharles.Forsyth { 748*37da2899SCharles.Forsyth FT_Byte* table = cmap->data; 749*37da2899SCharles.Forsyth FT_UInt result = 0; 750*37da2899SCharles.Forsyth 751*37da2899SCharles.Forsyth 752*37da2899SCharles.Forsyth if ( char_code < 0x10000UL ) 753*37da2899SCharles.Forsyth { 754*37da2899SCharles.Forsyth FT_UInt idx, num_segs2; 755*37da2899SCharles.Forsyth FT_Int delta; 756*37da2899SCharles.Forsyth FT_UInt code = (FT_UInt)char_code; 757*37da2899SCharles.Forsyth FT_Byte* p; 758*37da2899SCharles.Forsyth 759*37da2899SCharles.Forsyth 760*37da2899SCharles.Forsyth p = table + 6; 761*37da2899SCharles.Forsyth num_segs2 = TT_PEEK_USHORT( p ) & -2; /* be paranoid! */ 762*37da2899SCharles.Forsyth 763*37da2899SCharles.Forsyth #if 1 764*37da2899SCharles.Forsyth /* Some fonts have more than 170 segments in their charmaps! */ 765*37da2899SCharles.Forsyth /* We changed this function to use a more efficient binary */ 766*37da2899SCharles.Forsyth /* search for improving performance */ 767*37da2899SCharles.Forsyth { 768*37da2899SCharles.Forsyth FT_UInt min = 0; 769*37da2899SCharles.Forsyth FT_UInt max = num_segs2 >> 1; 770*37da2899SCharles.Forsyth FT_UInt mid, start, end, offset; 771*37da2899SCharles.Forsyth 772*37da2899SCharles.Forsyth 773*37da2899SCharles.Forsyth while ( min < max ) 774*37da2899SCharles.Forsyth { 775*37da2899SCharles.Forsyth mid = ( min + max ) >> 1; 776*37da2899SCharles.Forsyth p = table + 14 + mid * 2; 777*37da2899SCharles.Forsyth end = TT_NEXT_USHORT( p ); 778*37da2899SCharles.Forsyth p += num_segs2; 779*37da2899SCharles.Forsyth start = TT_PEEK_USHORT( p); 780*37da2899SCharles.Forsyth 781*37da2899SCharles.Forsyth if ( code < start ) 782*37da2899SCharles.Forsyth max = mid; 783*37da2899SCharles.Forsyth 784*37da2899SCharles.Forsyth else if ( code > end ) 785*37da2899SCharles.Forsyth min = mid + 1; 786*37da2899SCharles.Forsyth 787*37da2899SCharles.Forsyth else 788*37da2899SCharles.Forsyth { 789*37da2899SCharles.Forsyth /* we found the segment */ 790*37da2899SCharles.Forsyth idx = code; 791*37da2899SCharles.Forsyth 792*37da2899SCharles.Forsyth p += num_segs2; 793*37da2899SCharles.Forsyth delta = TT_PEEK_SHORT( p ); 794*37da2899SCharles.Forsyth 795*37da2899SCharles.Forsyth p += num_segs2; 796*37da2899SCharles.Forsyth offset = TT_PEEK_USHORT( p ); 797*37da2899SCharles.Forsyth 798*37da2899SCharles.Forsyth if ( offset == 0xFFFFU ) 799*37da2899SCharles.Forsyth goto Exit; 800*37da2899SCharles.Forsyth 801*37da2899SCharles.Forsyth if ( offset != 0 ) 802*37da2899SCharles.Forsyth { 803*37da2899SCharles.Forsyth p += offset + 2 * ( idx - start ); 804*37da2899SCharles.Forsyth idx = TT_PEEK_USHORT( p ); 805*37da2899SCharles.Forsyth } 806*37da2899SCharles.Forsyth 807*37da2899SCharles.Forsyth if ( idx != 0 ) 808*37da2899SCharles.Forsyth result = (FT_UInt)( idx + delta ) & 0xFFFFU; 809*37da2899SCharles.Forsyth 810*37da2899SCharles.Forsyth goto Exit; 811*37da2899SCharles.Forsyth } 812*37da2899SCharles.Forsyth } 813*37da2899SCharles.Forsyth } 814*37da2899SCharles.Forsyth 815*37da2899SCharles.Forsyth #else /* 0 - old code */ 816*37da2899SCharles.Forsyth 817*37da2899SCharles.Forsyth { 818*37da2899SCharles.Forsyth FT_UInt n; 819*37da2899SCharles.Forsyth FT_Byte* q; 820*37da2899SCharles.Forsyth 821*37da2899SCharles.Forsyth 822*37da2899SCharles.Forsyth p = table + 14; /* ends table */ 823*37da2899SCharles.Forsyth q = table + 16 + num_segs2; /* starts table */ 824*37da2899SCharles.Forsyth 825*37da2899SCharles.Forsyth 826*37da2899SCharles.Forsyth for ( n = 0; n < num_segs2; n += 2 ) 827*37da2899SCharles.Forsyth { 828*37da2899SCharles.Forsyth FT_UInt end = TT_NEXT_USHORT( p ); 829*37da2899SCharles.Forsyth FT_UInt start = TT_NEXT_USHORT( q ); 830*37da2899SCharles.Forsyth FT_UInt offset; 831*37da2899SCharles.Forsyth 832*37da2899SCharles.Forsyth 833*37da2899SCharles.Forsyth if ( code < start ) 834*37da2899SCharles.Forsyth break; 835*37da2899SCharles.Forsyth 836*37da2899SCharles.Forsyth if ( code <= end ) 837*37da2899SCharles.Forsyth { 838*37da2899SCharles.Forsyth idx = code; 839*37da2899SCharles.Forsyth 840*37da2899SCharles.Forsyth p = q + num_segs2 - 2; 841*37da2899SCharles.Forsyth delta = TT_PEEK_SHORT( p ); 842*37da2899SCharles.Forsyth p += num_segs2; 843*37da2899SCharles.Forsyth offset = TT_PEEK_USHORT( p ); 844*37da2899SCharles.Forsyth 845*37da2899SCharles.Forsyth if ( offset == 0xFFFFU ) 846*37da2899SCharles.Forsyth goto Exit; 847*37da2899SCharles.Forsyth 848*37da2899SCharles.Forsyth if ( offset != 0 ) 849*37da2899SCharles.Forsyth { 850*37da2899SCharles.Forsyth p += offset + 2 * ( idx - start ); 851*37da2899SCharles.Forsyth idx = TT_PEEK_USHORT( p ); 852*37da2899SCharles.Forsyth } 853*37da2899SCharles.Forsyth 854*37da2899SCharles.Forsyth if ( idx != 0 ) 855*37da2899SCharles.Forsyth result = (FT_UInt)( idx + delta ) & 0xFFFFU; 856*37da2899SCharles.Forsyth } 857*37da2899SCharles.Forsyth } 858*37da2899SCharles.Forsyth } 859*37da2899SCharles.Forsyth 860*37da2899SCharles.Forsyth #endif /* 0 */ 861*37da2899SCharles.Forsyth 862*37da2899SCharles.Forsyth } 863*37da2899SCharles.Forsyth 864*37da2899SCharles.Forsyth Exit: 865*37da2899SCharles.Forsyth return result; 866*37da2899SCharles.Forsyth } 867*37da2899SCharles.Forsyth 868*37da2899SCharles.Forsyth 869*37da2899SCharles.Forsyth FT_CALLBACK_DEF( FT_UInt ) tt_cmap4_char_next(TT_CMap cmap,FT_UInt32 * pchar_code)870*37da2899SCharles.Forsyth tt_cmap4_char_next( TT_CMap cmap, 871*37da2899SCharles.Forsyth FT_UInt32 *pchar_code ) 872*37da2899SCharles.Forsyth { 873*37da2899SCharles.Forsyth FT_Byte* table = cmap->data; 874*37da2899SCharles.Forsyth FT_UInt32 result = 0; 875*37da2899SCharles.Forsyth FT_UInt32 char_code = *pchar_code + 1; 876*37da2899SCharles.Forsyth FT_UInt gindex = 0; 877*37da2899SCharles.Forsyth FT_Byte* p; 878*37da2899SCharles.Forsyth FT_Byte* q; 879*37da2899SCharles.Forsyth FT_UInt code, num_segs2; 880*37da2899SCharles.Forsyth 881*37da2899SCharles.Forsyth 882*37da2899SCharles.Forsyth if ( char_code >= 0x10000UL ) 883*37da2899SCharles.Forsyth goto Exit; 884*37da2899SCharles.Forsyth 885*37da2899SCharles.Forsyth code = (FT_UInt)char_code; 886*37da2899SCharles.Forsyth p = table + 6; 887*37da2899SCharles.Forsyth num_segs2 = TT_PEEK_USHORT(p) & -2; /* ensure even-ness */ 888*37da2899SCharles.Forsyth 889*37da2899SCharles.Forsyth for (;;) 890*37da2899SCharles.Forsyth { 891*37da2899SCharles.Forsyth FT_UInt offset, n; 892*37da2899SCharles.Forsyth FT_Int delta; 893*37da2899SCharles.Forsyth 894*37da2899SCharles.Forsyth 895*37da2899SCharles.Forsyth p = table + 14; /* ends table */ 896*37da2899SCharles.Forsyth q = table + 16 + num_segs2; /* starts table */ 897*37da2899SCharles.Forsyth 898*37da2899SCharles.Forsyth for ( n = 0; n < num_segs2; n += 2 ) 899*37da2899SCharles.Forsyth { 900*37da2899SCharles.Forsyth FT_UInt end = TT_NEXT_USHORT( p ); 901*37da2899SCharles.Forsyth FT_UInt start = TT_NEXT_USHORT( q ); 902*37da2899SCharles.Forsyth 903*37da2899SCharles.Forsyth 904*37da2899SCharles.Forsyth if ( code < start ) 905*37da2899SCharles.Forsyth code = start; 906*37da2899SCharles.Forsyth 907*37da2899SCharles.Forsyth if ( code <= end ) 908*37da2899SCharles.Forsyth { 909*37da2899SCharles.Forsyth p = q + num_segs2 - 2; 910*37da2899SCharles.Forsyth delta = TT_PEEK_SHORT( p ); 911*37da2899SCharles.Forsyth p += num_segs2; 912*37da2899SCharles.Forsyth offset = TT_PEEK_USHORT( p ); 913*37da2899SCharles.Forsyth 914*37da2899SCharles.Forsyth if ( offset != 0 && offset != 0xFFFFU ) 915*37da2899SCharles.Forsyth { 916*37da2899SCharles.Forsyth /* parse the glyph ids array for non-0 index */ 917*37da2899SCharles.Forsyth p += offset + ( code - start ) * 2; 918*37da2899SCharles.Forsyth while ( code <= end ) 919*37da2899SCharles.Forsyth { 920*37da2899SCharles.Forsyth gindex = TT_NEXT_USHORT( p ); 921*37da2899SCharles.Forsyth if ( gindex != 0 ) 922*37da2899SCharles.Forsyth { 923*37da2899SCharles.Forsyth gindex = (FT_UInt)( gindex + delta ) & 0xFFFFU; 924*37da2899SCharles.Forsyth if ( gindex != 0 ) 925*37da2899SCharles.Forsyth break; 926*37da2899SCharles.Forsyth } 927*37da2899SCharles.Forsyth code++; 928*37da2899SCharles.Forsyth } 929*37da2899SCharles.Forsyth } 930*37da2899SCharles.Forsyth else if ( offset == 0xFFFFU ) 931*37da2899SCharles.Forsyth { 932*37da2899SCharles.Forsyth /* an offset of 0xFFFF means an empty glyph in certain fonts! */ 933*37da2899SCharles.Forsyth code = end; 934*37da2899SCharles.Forsyth break; 935*37da2899SCharles.Forsyth } 936*37da2899SCharles.Forsyth else 937*37da2899SCharles.Forsyth gindex = (FT_UInt)( code + delta ) & 0xFFFFU; 938*37da2899SCharles.Forsyth 939*37da2899SCharles.Forsyth if ( gindex == 0 ) 940*37da2899SCharles.Forsyth break; 941*37da2899SCharles.Forsyth 942*37da2899SCharles.Forsyth result = code; 943*37da2899SCharles.Forsyth goto Exit; 944*37da2899SCharles.Forsyth } 945*37da2899SCharles.Forsyth } 946*37da2899SCharles.Forsyth 947*37da2899SCharles.Forsyth /* loop to next trial charcode */ 948*37da2899SCharles.Forsyth if ( code >= 0xFFFFU ) 949*37da2899SCharles.Forsyth break; 950*37da2899SCharles.Forsyth 951*37da2899SCharles.Forsyth code++; 952*37da2899SCharles.Forsyth } 953*37da2899SCharles.Forsyth return (FT_UInt)result; 954*37da2899SCharles.Forsyth 955*37da2899SCharles.Forsyth Exit: 956*37da2899SCharles.Forsyth *pchar_code = result; 957*37da2899SCharles.Forsyth return gindex; 958*37da2899SCharles.Forsyth } 959*37da2899SCharles.Forsyth 960*37da2899SCharles.Forsyth 961*37da2899SCharles.Forsyth FT_CALLBACK_TABLE_DEF 962*37da2899SCharles.Forsyth const TT_CMap_ClassRec tt_cmap4_class_rec = 963*37da2899SCharles.Forsyth { 964*37da2899SCharles.Forsyth { 965*37da2899SCharles.Forsyth sizeof ( TT_CMapRec ), 966*37da2899SCharles.Forsyth 967*37da2899SCharles.Forsyth (FT_CMap_InitFunc) tt_cmap_init, 968*37da2899SCharles.Forsyth (FT_CMap_DoneFunc) NULL, 969*37da2899SCharles.Forsyth (FT_CMap_CharIndexFunc)tt_cmap4_char_index, 970*37da2899SCharles.Forsyth (FT_CMap_CharNextFunc) tt_cmap4_char_next 971*37da2899SCharles.Forsyth }, 972*37da2899SCharles.Forsyth 4, 973*37da2899SCharles.Forsyth (TT_CMap_ValidateFunc) tt_cmap4_validate 974*37da2899SCharles.Forsyth }; 975*37da2899SCharles.Forsyth 976*37da2899SCharles.Forsyth #endif /* TT_CONFIG_CMAP_FORMAT_4 */ 977*37da2899SCharles.Forsyth 978*37da2899SCharles.Forsyth 979*37da2899SCharles.Forsyth /*************************************************************************/ 980*37da2899SCharles.Forsyth /*************************************************************************/ 981*37da2899SCharles.Forsyth /***** *****/ 982*37da2899SCharles.Forsyth /***** FORMAT 6 *****/ 983*37da2899SCharles.Forsyth /***** *****/ 984*37da2899SCharles.Forsyth /*************************************************************************/ 985*37da2899SCharles.Forsyth /*************************************************************************/ 986*37da2899SCharles.Forsyth 987*37da2899SCharles.Forsyth /*************************************************************************/ 988*37da2899SCharles.Forsyth /* */ 989*37da2899SCharles.Forsyth /* TABLE OVERVIEW */ 990*37da2899SCharles.Forsyth /* -------------- */ 991*37da2899SCharles.Forsyth /* */ 992*37da2899SCharles.Forsyth /* NAME OFFSET TYPE DESCRIPTION */ 993*37da2899SCharles.Forsyth /* */ 994*37da2899SCharles.Forsyth /* format 0 USHORT must be 4 */ 995*37da2899SCharles.Forsyth /* length 2 USHORT table length in bytes */ 996*37da2899SCharles.Forsyth /* language 4 USHORT Mac language code */ 997*37da2899SCharles.Forsyth /* */ 998*37da2899SCharles.Forsyth /* first 6 USHORT first segment code */ 999*37da2899SCharles.Forsyth /* count 8 USHORT segment size in chars */ 1000*37da2899SCharles.Forsyth /* glyphIds 10 USHORT[count] glyph ids */ 1001*37da2899SCharles.Forsyth /* */ 1002*37da2899SCharles.Forsyth /* A very simplified segment mapping. */ 1003*37da2899SCharles.Forsyth /* */ 1004*37da2899SCharles.Forsyth 1005*37da2899SCharles.Forsyth #ifdef TT_CONFIG_CMAP_FORMAT_6 1006*37da2899SCharles.Forsyth 1007*37da2899SCharles.Forsyth FT_CALLBACK_DEF( void ) tt_cmap6_validate(FT_Byte * table,FT_Validator valid)1008*37da2899SCharles.Forsyth tt_cmap6_validate( FT_Byte* table, 1009*37da2899SCharles.Forsyth FT_Validator valid ) 1010*37da2899SCharles.Forsyth { 1011*37da2899SCharles.Forsyth FT_Byte* p; 1012*37da2899SCharles.Forsyth FT_UInt length, start, count; 1013*37da2899SCharles.Forsyth 1014*37da2899SCharles.Forsyth 1015*37da2899SCharles.Forsyth if ( table + 10 > valid->limit ) 1016*37da2899SCharles.Forsyth FT_INVALID_TOO_SHORT; 1017*37da2899SCharles.Forsyth 1018*37da2899SCharles.Forsyth p = table + 2; 1019*37da2899SCharles.Forsyth length = TT_NEXT_USHORT( p ); 1020*37da2899SCharles.Forsyth 1021*37da2899SCharles.Forsyth p = table + 6; /* skip language */ 1022*37da2899SCharles.Forsyth start = TT_NEXT_USHORT( p ); 1023*37da2899SCharles.Forsyth count = TT_NEXT_USHORT( p ); 1024*37da2899SCharles.Forsyth 1025*37da2899SCharles.Forsyth if ( table + length > valid->limit || length < 10 + count * 2 ) 1026*37da2899SCharles.Forsyth FT_INVALID_TOO_SHORT; 1027*37da2899SCharles.Forsyth 1028*37da2899SCharles.Forsyth /* check glyph indices */ 1029*37da2899SCharles.Forsyth if ( valid->level >= FT_VALIDATE_TIGHT ) 1030*37da2899SCharles.Forsyth { 1031*37da2899SCharles.Forsyth FT_UInt gindex; 1032*37da2899SCharles.Forsyth 1033*37da2899SCharles.Forsyth 1034*37da2899SCharles.Forsyth for ( ; count > 0; count-- ) 1035*37da2899SCharles.Forsyth { 1036*37da2899SCharles.Forsyth gindex = TT_NEXT_USHORT( p ); 1037*37da2899SCharles.Forsyth if ( gindex >= TT_VALID_GLYPH_COUNT( valid ) ) 1038*37da2899SCharles.Forsyth FT_INVALID_GLYPH_ID; 1039*37da2899SCharles.Forsyth } 1040*37da2899SCharles.Forsyth } 1041*37da2899SCharles.Forsyth } 1042*37da2899SCharles.Forsyth 1043*37da2899SCharles.Forsyth 1044*37da2899SCharles.Forsyth FT_CALLBACK_DEF( FT_UInt ) tt_cmap6_char_index(TT_CMap cmap,FT_UInt32 char_code)1045*37da2899SCharles.Forsyth tt_cmap6_char_index( TT_CMap cmap, 1046*37da2899SCharles.Forsyth FT_UInt32 char_code ) 1047*37da2899SCharles.Forsyth { 1048*37da2899SCharles.Forsyth FT_Byte* table = cmap->data; 1049*37da2899SCharles.Forsyth FT_UInt result = 0; 1050*37da2899SCharles.Forsyth FT_Byte* p = table + 6; 1051*37da2899SCharles.Forsyth FT_UInt start = TT_NEXT_USHORT( p ); 1052*37da2899SCharles.Forsyth FT_UInt count = TT_NEXT_USHORT( p ); 1053*37da2899SCharles.Forsyth FT_UInt idx = (FT_UInt)( char_code - start ); 1054*37da2899SCharles.Forsyth 1055*37da2899SCharles.Forsyth 1056*37da2899SCharles.Forsyth if ( idx < count ) 1057*37da2899SCharles.Forsyth { 1058*37da2899SCharles.Forsyth p += 2 * idx; 1059*37da2899SCharles.Forsyth result = TT_PEEK_USHORT( p ); 1060*37da2899SCharles.Forsyth } 1061*37da2899SCharles.Forsyth return result; 1062*37da2899SCharles.Forsyth } 1063*37da2899SCharles.Forsyth 1064*37da2899SCharles.Forsyth 1065*37da2899SCharles.Forsyth FT_CALLBACK_DEF( FT_UInt ) tt_cmap6_char_next(TT_CMap cmap,FT_UInt32 * pchar_code)1066*37da2899SCharles.Forsyth tt_cmap6_char_next( TT_CMap cmap, 1067*37da2899SCharles.Forsyth FT_UInt32 *pchar_code ) 1068*37da2899SCharles.Forsyth { 1069*37da2899SCharles.Forsyth FT_Byte* table = cmap->data; 1070*37da2899SCharles.Forsyth FT_UInt32 result = 0; 1071*37da2899SCharles.Forsyth FT_UInt32 char_code = *pchar_code + 1; 1072*37da2899SCharles.Forsyth FT_UInt gindex = 0; 1073*37da2899SCharles.Forsyth 1074*37da2899SCharles.Forsyth FT_Byte* p = table + 6; 1075*37da2899SCharles.Forsyth FT_UInt start = TT_NEXT_USHORT( p ); 1076*37da2899SCharles.Forsyth FT_UInt count = TT_NEXT_USHORT( p ); 1077*37da2899SCharles.Forsyth FT_UInt idx; 1078*37da2899SCharles.Forsyth 1079*37da2899SCharles.Forsyth 1080*37da2899SCharles.Forsyth if ( char_code >= 0x10000UL ) 1081*37da2899SCharles.Forsyth goto Exit; 1082*37da2899SCharles.Forsyth 1083*37da2899SCharles.Forsyth if ( char_code < start ) 1084*37da2899SCharles.Forsyth char_code = start; 1085*37da2899SCharles.Forsyth 1086*37da2899SCharles.Forsyth idx = (FT_UInt)( char_code - start ); 1087*37da2899SCharles.Forsyth p += 2 * idx; 1088*37da2899SCharles.Forsyth 1089*37da2899SCharles.Forsyth for ( ; idx < count; idx++ ) 1090*37da2899SCharles.Forsyth { 1091*37da2899SCharles.Forsyth gindex = TT_NEXT_USHORT( p ); 1092*37da2899SCharles.Forsyth if ( gindex != 0 ) 1093*37da2899SCharles.Forsyth { 1094*37da2899SCharles.Forsyth result = char_code; 1095*37da2899SCharles.Forsyth break; 1096*37da2899SCharles.Forsyth } 1097*37da2899SCharles.Forsyth char_code++; 1098*37da2899SCharles.Forsyth } 1099*37da2899SCharles.Forsyth 1100*37da2899SCharles.Forsyth Exit: 1101*37da2899SCharles.Forsyth *pchar_code = result; 1102*37da2899SCharles.Forsyth return gindex; 1103*37da2899SCharles.Forsyth } 1104*37da2899SCharles.Forsyth 1105*37da2899SCharles.Forsyth 1106*37da2899SCharles.Forsyth FT_CALLBACK_TABLE_DEF 1107*37da2899SCharles.Forsyth const TT_CMap_ClassRec tt_cmap6_class_rec = 1108*37da2899SCharles.Forsyth { 1109*37da2899SCharles.Forsyth { 1110*37da2899SCharles.Forsyth sizeof ( TT_CMapRec ), 1111*37da2899SCharles.Forsyth 1112*37da2899SCharles.Forsyth (FT_CMap_InitFunc) tt_cmap_init, 1113*37da2899SCharles.Forsyth (FT_CMap_DoneFunc) NULL, 1114*37da2899SCharles.Forsyth (FT_CMap_CharIndexFunc)tt_cmap6_char_index, 1115*37da2899SCharles.Forsyth (FT_CMap_CharNextFunc) tt_cmap6_char_next 1116*37da2899SCharles.Forsyth }, 1117*37da2899SCharles.Forsyth 6, 1118*37da2899SCharles.Forsyth (TT_CMap_ValidateFunc) tt_cmap6_validate 1119*37da2899SCharles.Forsyth }; 1120*37da2899SCharles.Forsyth 1121*37da2899SCharles.Forsyth #endif /* TT_CONFIG_CMAP_FORMAT_6 */ 1122*37da2899SCharles.Forsyth 1123*37da2899SCharles.Forsyth 1124*37da2899SCharles.Forsyth /*************************************************************************/ 1125*37da2899SCharles.Forsyth /*************************************************************************/ 1126*37da2899SCharles.Forsyth /***** *****/ 1127*37da2899SCharles.Forsyth /***** FORMAT 8 *****/ 1128*37da2899SCharles.Forsyth /***** *****/ 1129*37da2899SCharles.Forsyth /***** It's hard to completely understand what the OpenType spec *****/ 1130*37da2899SCharles.Forsyth /***** says about this format, but here is my conclusion. *****/ 1131*37da2899SCharles.Forsyth /***** *****/ 1132*37da2899SCharles.Forsyth /***** The purpose of this format is to easily map UTF-16 text to *****/ 1133*37da2899SCharles.Forsyth /***** glyph indices. Basically, the `char_code' must be in one of *****/ 1134*37da2899SCharles.Forsyth /***** the following formats: *****/ 1135*37da2899SCharles.Forsyth /***** *****/ 1136*37da2899SCharles.Forsyth /***** - A 16-bit value that isn't part of the Unicode Surrogates *****/ 1137*37da2899SCharles.Forsyth /***** Area (i.e. U+D800-U+DFFF). *****/ 1138*37da2899SCharles.Forsyth /***** *****/ 1139*37da2899SCharles.Forsyth /***** - A 32-bit value, made of two surrogate values, i.e.. if *****/ 1140*37da2899SCharles.Forsyth /***** `char_code = (char_hi << 16) | char_lo', then both *****/ 1141*37da2899SCharles.Forsyth /***** `char_hi' and `char_lo' must be in the Surrogates Area. *****/ 1142*37da2899SCharles.Forsyth /***** Area. *****/ 1143*37da2899SCharles.Forsyth /***** *****/ 1144*37da2899SCharles.Forsyth /***** The 'is32' table embedded in the charmap indicates whether a *****/ 1145*37da2899SCharles.Forsyth /***** given 16-bit value is in the surrogates area or not. *****/ 1146*37da2899SCharles.Forsyth /***** *****/ 1147*37da2899SCharles.Forsyth /***** So, for any given `char_code', we can assert the following: *****/ 1148*37da2899SCharles.Forsyth /***** *****/ 1149*37da2899SCharles.Forsyth /***** If `char_hi == 0' then we must have `is32[char_lo] == 0'. *****/ 1150*37da2899SCharles.Forsyth /***** *****/ 1151*37da2899SCharles.Forsyth /***** If `char_hi != 0' then we must have both *****/ 1152*37da2899SCharles.Forsyth /***** `is32[char_hi] != 0' and `is32[char_lo] != 0'. *****/ 1153*37da2899SCharles.Forsyth /***** *****/ 1154*37da2899SCharles.Forsyth /*************************************************************************/ 1155*37da2899SCharles.Forsyth /*************************************************************************/ 1156*37da2899SCharles.Forsyth 1157*37da2899SCharles.Forsyth /*************************************************************************/ 1158*37da2899SCharles.Forsyth /* */ 1159*37da2899SCharles.Forsyth /* TABLE OVERVIEW */ 1160*37da2899SCharles.Forsyth /* -------------- */ 1161*37da2899SCharles.Forsyth /* */ 1162*37da2899SCharles.Forsyth /* NAME OFFSET TYPE DESCRIPTION */ 1163*37da2899SCharles.Forsyth /* */ 1164*37da2899SCharles.Forsyth /* format 0 USHORT must be 8 */ 1165*37da2899SCharles.Forsyth /* reseved 2 USHORT reserved */ 1166*37da2899SCharles.Forsyth /* length 4 ULONG length in bytes */ 1167*37da2899SCharles.Forsyth /* language 8 ULONG Mac language code */ 1168*37da2899SCharles.Forsyth /* is32 12 BYTE[8192] 32-bitness bitmap */ 1169*37da2899SCharles.Forsyth /* count 8204 ULONG number of groups */ 1170*37da2899SCharles.Forsyth /* */ 1171*37da2899SCharles.Forsyth /* This header is followed by 'count' groups of the following format: */ 1172*37da2899SCharles.Forsyth /* */ 1173*37da2899SCharles.Forsyth /* start 0 ULONG first charcode */ 1174*37da2899SCharles.Forsyth /* end 4 ULONG last charcode */ 1175*37da2899SCharles.Forsyth /* startId 8 ULONG start glyph id for the group */ 1176*37da2899SCharles.Forsyth /* */ 1177*37da2899SCharles.Forsyth 1178*37da2899SCharles.Forsyth #ifdef TT_CONFIG_CMAP_FORMAT_8 1179*37da2899SCharles.Forsyth 1180*37da2899SCharles.Forsyth FT_CALLBACK_DEF( void ) tt_cmap8_validate(FT_Byte * table,FT_Validator valid)1181*37da2899SCharles.Forsyth tt_cmap8_validate( FT_Byte* table, 1182*37da2899SCharles.Forsyth FT_Validator valid ) 1183*37da2899SCharles.Forsyth { 1184*37da2899SCharles.Forsyth FT_Byte* p = table + 4; 1185*37da2899SCharles.Forsyth FT_Byte* is32; 1186*37da2899SCharles.Forsyth FT_UInt32 length; 1187*37da2899SCharles.Forsyth FT_UInt32 num_groups; 1188*37da2899SCharles.Forsyth 1189*37da2899SCharles.Forsyth 1190*37da2899SCharles.Forsyth if ( table + 16 + 8192 > valid->limit ) 1191*37da2899SCharles.Forsyth FT_INVALID_TOO_SHORT; 1192*37da2899SCharles.Forsyth 1193*37da2899SCharles.Forsyth length = TT_NEXT_ULONG( p ); 1194*37da2899SCharles.Forsyth if ( table + length > valid->limit || length < 8208 ) 1195*37da2899SCharles.Forsyth FT_INVALID_TOO_SHORT; 1196*37da2899SCharles.Forsyth 1197*37da2899SCharles.Forsyth is32 = table + 12; 1198*37da2899SCharles.Forsyth p = is32 + 8192; /* skip `is32' array */ 1199*37da2899SCharles.Forsyth num_groups = TT_NEXT_ULONG( p ); 1200*37da2899SCharles.Forsyth 1201*37da2899SCharles.Forsyth if ( p + num_groups * 12 > valid->limit ) 1202*37da2899SCharles.Forsyth FT_INVALID_TOO_SHORT; 1203*37da2899SCharles.Forsyth 1204*37da2899SCharles.Forsyth /* check groups, they must be in increasing order */ 1205*37da2899SCharles.Forsyth { 1206*37da2899SCharles.Forsyth FT_UInt32 n, start, end, start_id, count, last = 0; 1207*37da2899SCharles.Forsyth 1208*37da2899SCharles.Forsyth 1209*37da2899SCharles.Forsyth for ( n = 0; n < num_groups; n++ ) 1210*37da2899SCharles.Forsyth { 1211*37da2899SCharles.Forsyth FT_UInt hi, lo; 1212*37da2899SCharles.Forsyth 1213*37da2899SCharles.Forsyth 1214*37da2899SCharles.Forsyth start = TT_NEXT_ULONG( p ); 1215*37da2899SCharles.Forsyth end = TT_NEXT_ULONG( p ); 1216*37da2899SCharles.Forsyth start_id = TT_NEXT_ULONG( p ); 1217*37da2899SCharles.Forsyth 1218*37da2899SCharles.Forsyth if ( start > end ) 1219*37da2899SCharles.Forsyth FT_INVALID_DATA; 1220*37da2899SCharles.Forsyth 1221*37da2899SCharles.Forsyth if ( n > 0 && start <= last ) 1222*37da2899SCharles.Forsyth FT_INVALID_DATA; 1223*37da2899SCharles.Forsyth 1224*37da2899SCharles.Forsyth if ( valid->level >= FT_VALIDATE_TIGHT ) 1225*37da2899SCharles.Forsyth { 1226*37da2899SCharles.Forsyth if ( start_id + end - start >= TT_VALID_GLYPH_COUNT( valid ) ) 1227*37da2899SCharles.Forsyth FT_INVALID_GLYPH_ID; 1228*37da2899SCharles.Forsyth 1229*37da2899SCharles.Forsyth count = (FT_UInt32)( end - start + 1 ); 1230*37da2899SCharles.Forsyth 1231*37da2899SCharles.Forsyth if ( start & ~0xFFFFU ) 1232*37da2899SCharles.Forsyth { 1233*37da2899SCharles.Forsyth /* start_hi != 0; check that is32[i] is 1 for each i in */ 1234*37da2899SCharles.Forsyth /* the `hi' and `lo' of the range [start..end] */ 1235*37da2899SCharles.Forsyth for ( ; count > 0; count--, start++ ) 1236*37da2899SCharles.Forsyth { 1237*37da2899SCharles.Forsyth hi = (FT_UInt)( start >> 16 ); 1238*37da2899SCharles.Forsyth lo = (FT_UInt)( start & 0xFFFFU ); 1239*37da2899SCharles.Forsyth 1240*37da2899SCharles.Forsyth if ( (is32[hi >> 3] & ( 0x80 >> ( hi & 7 ) ) ) == 0 ) 1241*37da2899SCharles.Forsyth FT_INVALID_DATA; 1242*37da2899SCharles.Forsyth 1243*37da2899SCharles.Forsyth if ( (is32[lo >> 3] & ( 0x80 >> ( lo & 7 ) ) ) == 0 ) 1244*37da2899SCharles.Forsyth FT_INVALID_DATA; 1245*37da2899SCharles.Forsyth } 1246*37da2899SCharles.Forsyth } 1247*37da2899SCharles.Forsyth else 1248*37da2899SCharles.Forsyth { 1249*37da2899SCharles.Forsyth /* start_hi == 0; check that is32[i] is 0 for each i in */ 1250*37da2899SCharles.Forsyth /* the range [start..end] */ 1251*37da2899SCharles.Forsyth 1252*37da2899SCharles.Forsyth /* end_hi cannot be != 0! */ 1253*37da2899SCharles.Forsyth if ( end & ~0xFFFFU ) 1254*37da2899SCharles.Forsyth FT_INVALID_DATA; 1255*37da2899SCharles.Forsyth 1256*37da2899SCharles.Forsyth for ( ; count > 0; count--, start++ ) 1257*37da2899SCharles.Forsyth { 1258*37da2899SCharles.Forsyth lo = (FT_UInt)( start & 0xFFFFU ); 1259*37da2899SCharles.Forsyth 1260*37da2899SCharles.Forsyth if ( (is32[lo >> 3] & ( 0x80 >> ( lo & 7 ) ) ) != 0 ) 1261*37da2899SCharles.Forsyth FT_INVALID_DATA; 1262*37da2899SCharles.Forsyth } 1263*37da2899SCharles.Forsyth } 1264*37da2899SCharles.Forsyth } 1265*37da2899SCharles.Forsyth 1266*37da2899SCharles.Forsyth last = end; 1267*37da2899SCharles.Forsyth } 1268*37da2899SCharles.Forsyth } 1269*37da2899SCharles.Forsyth } 1270*37da2899SCharles.Forsyth 1271*37da2899SCharles.Forsyth 1272*37da2899SCharles.Forsyth FT_CALLBACK_DEF( FT_UInt ) tt_cmap8_char_index(TT_CMap cmap,FT_UInt32 char_code)1273*37da2899SCharles.Forsyth tt_cmap8_char_index( TT_CMap cmap, 1274*37da2899SCharles.Forsyth FT_UInt32 char_code ) 1275*37da2899SCharles.Forsyth { 1276*37da2899SCharles.Forsyth FT_Byte* table = cmap->data; 1277*37da2899SCharles.Forsyth FT_UInt result = 0; 1278*37da2899SCharles.Forsyth FT_Byte* p = table + 8204; 1279*37da2899SCharles.Forsyth FT_UInt32 num_groups = TT_NEXT_ULONG( p ); 1280*37da2899SCharles.Forsyth FT_UInt32 start, end, start_id; 1281*37da2899SCharles.Forsyth 1282*37da2899SCharles.Forsyth 1283*37da2899SCharles.Forsyth for ( ; num_groups > 0; num_groups-- ) 1284*37da2899SCharles.Forsyth { 1285*37da2899SCharles.Forsyth start = TT_NEXT_ULONG( p ); 1286*37da2899SCharles.Forsyth end = TT_NEXT_ULONG( p ); 1287*37da2899SCharles.Forsyth start_id = TT_NEXT_ULONG( p ); 1288*37da2899SCharles.Forsyth 1289*37da2899SCharles.Forsyth if ( char_code < start ) 1290*37da2899SCharles.Forsyth break; 1291*37da2899SCharles.Forsyth 1292*37da2899SCharles.Forsyth if ( char_code <= end ) 1293*37da2899SCharles.Forsyth { 1294*37da2899SCharles.Forsyth result = (FT_UInt)( start_id + char_code - start ); 1295*37da2899SCharles.Forsyth break; 1296*37da2899SCharles.Forsyth } 1297*37da2899SCharles.Forsyth } 1298*37da2899SCharles.Forsyth return result; 1299*37da2899SCharles.Forsyth } 1300*37da2899SCharles.Forsyth 1301*37da2899SCharles.Forsyth 1302*37da2899SCharles.Forsyth FT_CALLBACK_DEF( FT_UInt ) tt_cmap8_char_next(TT_CMap cmap,FT_UInt32 * pchar_code)1303*37da2899SCharles.Forsyth tt_cmap8_char_next( TT_CMap cmap, 1304*37da2899SCharles.Forsyth FT_UInt32 *pchar_code ) 1305*37da2899SCharles.Forsyth { 1306*37da2899SCharles.Forsyth FT_UInt32 result = 0; 1307*37da2899SCharles.Forsyth FT_UInt32 char_code = *pchar_code + 1; 1308*37da2899SCharles.Forsyth FT_UInt gindex = 0; 1309*37da2899SCharles.Forsyth FT_Byte* table = cmap->data; 1310*37da2899SCharles.Forsyth FT_Byte* p = table + 8204; 1311*37da2899SCharles.Forsyth FT_UInt32 num_groups = TT_NEXT_ULONG( p ); 1312*37da2899SCharles.Forsyth FT_UInt32 start, end, start_id; 1313*37da2899SCharles.Forsyth 1314*37da2899SCharles.Forsyth 1315*37da2899SCharles.Forsyth p = table + 8208; 1316*37da2899SCharles.Forsyth 1317*37da2899SCharles.Forsyth for ( ; num_groups > 0; num_groups-- ) 1318*37da2899SCharles.Forsyth { 1319*37da2899SCharles.Forsyth start = TT_NEXT_ULONG( p ); 1320*37da2899SCharles.Forsyth end = TT_NEXT_ULONG( p ); 1321*37da2899SCharles.Forsyth start_id = TT_NEXT_ULONG( p ); 1322*37da2899SCharles.Forsyth 1323*37da2899SCharles.Forsyth if ( char_code < start ) 1324*37da2899SCharles.Forsyth char_code = start; 1325*37da2899SCharles.Forsyth 1326*37da2899SCharles.Forsyth if ( char_code <= end ) 1327*37da2899SCharles.Forsyth { 1328*37da2899SCharles.Forsyth gindex = (FT_UInt)( char_code - start + start_id ); 1329*37da2899SCharles.Forsyth if ( gindex != 0 ) 1330*37da2899SCharles.Forsyth { 1331*37da2899SCharles.Forsyth result = char_code; 1332*37da2899SCharles.Forsyth goto Exit; 1333*37da2899SCharles.Forsyth } 1334*37da2899SCharles.Forsyth } 1335*37da2899SCharles.Forsyth } 1336*37da2899SCharles.Forsyth 1337*37da2899SCharles.Forsyth Exit: 1338*37da2899SCharles.Forsyth *pchar_code = result; 1339*37da2899SCharles.Forsyth return gindex; 1340*37da2899SCharles.Forsyth } 1341*37da2899SCharles.Forsyth 1342*37da2899SCharles.Forsyth 1343*37da2899SCharles.Forsyth FT_CALLBACK_TABLE_DEF 1344*37da2899SCharles.Forsyth const TT_CMap_ClassRec tt_cmap8_class_rec = 1345*37da2899SCharles.Forsyth { 1346*37da2899SCharles.Forsyth { 1347*37da2899SCharles.Forsyth sizeof ( TT_CMapRec ), 1348*37da2899SCharles.Forsyth 1349*37da2899SCharles.Forsyth (FT_CMap_InitFunc) tt_cmap_init, 1350*37da2899SCharles.Forsyth (FT_CMap_DoneFunc) NULL, 1351*37da2899SCharles.Forsyth (FT_CMap_CharIndexFunc)tt_cmap8_char_index, 1352*37da2899SCharles.Forsyth (FT_CMap_CharNextFunc) tt_cmap8_char_next 1353*37da2899SCharles.Forsyth }, 1354*37da2899SCharles.Forsyth 8, 1355*37da2899SCharles.Forsyth (TT_CMap_ValidateFunc) tt_cmap8_validate 1356*37da2899SCharles.Forsyth }; 1357*37da2899SCharles.Forsyth 1358*37da2899SCharles.Forsyth #endif /* TT_CONFIG_CMAP_FORMAT_8 */ 1359*37da2899SCharles.Forsyth 1360*37da2899SCharles.Forsyth 1361*37da2899SCharles.Forsyth /*************************************************************************/ 1362*37da2899SCharles.Forsyth /*************************************************************************/ 1363*37da2899SCharles.Forsyth /***** *****/ 1364*37da2899SCharles.Forsyth /***** FORMAT 10 *****/ 1365*37da2899SCharles.Forsyth /***** *****/ 1366*37da2899SCharles.Forsyth /*************************************************************************/ 1367*37da2899SCharles.Forsyth /*************************************************************************/ 1368*37da2899SCharles.Forsyth 1369*37da2899SCharles.Forsyth /*************************************************************************/ 1370*37da2899SCharles.Forsyth /* */ 1371*37da2899SCharles.Forsyth /* TABLE OVERVIEW */ 1372*37da2899SCharles.Forsyth /* -------------- */ 1373*37da2899SCharles.Forsyth /* */ 1374*37da2899SCharles.Forsyth /* NAME OFFSET TYPE DESCRIPTION */ 1375*37da2899SCharles.Forsyth /* */ 1376*37da2899SCharles.Forsyth /* format 0 USHORT must be 10 */ 1377*37da2899SCharles.Forsyth /* reserved 2 USHORT reserved */ 1378*37da2899SCharles.Forsyth /* length 4 ULONG length in bytes */ 1379*37da2899SCharles.Forsyth /* language 8 ULONG Mac language code */ 1380*37da2899SCharles.Forsyth /* */ 1381*37da2899SCharles.Forsyth /* start 12 ULONG first char in range */ 1382*37da2899SCharles.Forsyth /* count 16 ULONG number of chars in range */ 1383*37da2899SCharles.Forsyth /* glyphIds 20 USHORT[count] glyph indices covered */ 1384*37da2899SCharles.Forsyth /* */ 1385*37da2899SCharles.Forsyth 1386*37da2899SCharles.Forsyth #ifdef TT_CONFIG_CMAP_FORMAT_10 1387*37da2899SCharles.Forsyth 1388*37da2899SCharles.Forsyth FT_CALLBACK_DEF( void ) tt_cmap10_validate(FT_Byte * table,FT_Validator valid)1389*37da2899SCharles.Forsyth tt_cmap10_validate( FT_Byte* table, 1390*37da2899SCharles.Forsyth FT_Validator valid ) 1391*37da2899SCharles.Forsyth { 1392*37da2899SCharles.Forsyth FT_Byte* p = table + 4; 1393*37da2899SCharles.Forsyth FT_ULong length, start, count; 1394*37da2899SCharles.Forsyth 1395*37da2899SCharles.Forsyth 1396*37da2899SCharles.Forsyth if ( table + 20 > valid->limit ) 1397*37da2899SCharles.Forsyth FT_INVALID_TOO_SHORT; 1398*37da2899SCharles.Forsyth 1399*37da2899SCharles.Forsyth length = TT_NEXT_ULONG( p ); 1400*37da2899SCharles.Forsyth p = table + 12; 1401*37da2899SCharles.Forsyth start = TT_NEXT_ULONG( p ); 1402*37da2899SCharles.Forsyth count = TT_NEXT_ULONG( p ); 1403*37da2899SCharles.Forsyth 1404*37da2899SCharles.Forsyth if ( table + length > valid->limit || length < 20 + count * 2 ) 1405*37da2899SCharles.Forsyth FT_INVALID_TOO_SHORT; 1406*37da2899SCharles.Forsyth 1407*37da2899SCharles.Forsyth /* check glyph indices */ 1408*37da2899SCharles.Forsyth if ( valid->level >= FT_VALIDATE_TIGHT ) 1409*37da2899SCharles.Forsyth { 1410*37da2899SCharles.Forsyth FT_UInt gindex; 1411*37da2899SCharles.Forsyth 1412*37da2899SCharles.Forsyth 1413*37da2899SCharles.Forsyth for ( ; count > 0; count-- ) 1414*37da2899SCharles.Forsyth { 1415*37da2899SCharles.Forsyth gindex = TT_NEXT_USHORT( p ); 1416*37da2899SCharles.Forsyth if ( gindex >= TT_VALID_GLYPH_COUNT( valid ) ) 1417*37da2899SCharles.Forsyth FT_INVALID_GLYPH_ID; 1418*37da2899SCharles.Forsyth } 1419*37da2899SCharles.Forsyth } 1420*37da2899SCharles.Forsyth } 1421*37da2899SCharles.Forsyth 1422*37da2899SCharles.Forsyth 1423*37da2899SCharles.Forsyth FT_CALLBACK_DEF( FT_UInt ) tt_cmap10_char_index(TT_CMap cmap,FT_UInt32 char_code)1424*37da2899SCharles.Forsyth tt_cmap10_char_index( TT_CMap cmap, 1425*37da2899SCharles.Forsyth FT_UInt32 char_code ) 1426*37da2899SCharles.Forsyth { 1427*37da2899SCharles.Forsyth FT_Byte* table = cmap->data; 1428*37da2899SCharles.Forsyth FT_UInt result = 0; 1429*37da2899SCharles.Forsyth FT_Byte* p = table + 12; 1430*37da2899SCharles.Forsyth FT_UInt32 start = TT_NEXT_ULONG( p ); 1431*37da2899SCharles.Forsyth FT_UInt32 count = TT_NEXT_ULONG( p ); 1432*37da2899SCharles.Forsyth FT_UInt32 idx = (FT_ULong)( char_code - start ); 1433*37da2899SCharles.Forsyth 1434*37da2899SCharles.Forsyth 1435*37da2899SCharles.Forsyth if ( idx < count ) 1436*37da2899SCharles.Forsyth { 1437*37da2899SCharles.Forsyth p += 2 * idx; 1438*37da2899SCharles.Forsyth result = TT_PEEK_USHORT( p ); 1439*37da2899SCharles.Forsyth } 1440*37da2899SCharles.Forsyth return result; 1441*37da2899SCharles.Forsyth } 1442*37da2899SCharles.Forsyth 1443*37da2899SCharles.Forsyth 1444*37da2899SCharles.Forsyth FT_CALLBACK_DEF( FT_UInt ) tt_cmap10_char_next(TT_CMap cmap,FT_UInt32 * pchar_code)1445*37da2899SCharles.Forsyth tt_cmap10_char_next( TT_CMap cmap, 1446*37da2899SCharles.Forsyth FT_UInt32 *pchar_code ) 1447*37da2899SCharles.Forsyth { 1448*37da2899SCharles.Forsyth FT_Byte* table = cmap->data; 1449*37da2899SCharles.Forsyth FT_UInt32 result = 0; 1450*37da2899SCharles.Forsyth FT_UInt32 char_code = *pchar_code + 1; 1451*37da2899SCharles.Forsyth FT_UInt gindex = 0; 1452*37da2899SCharles.Forsyth FT_Byte* p = table + 12; 1453*37da2899SCharles.Forsyth FT_UInt32 start = TT_NEXT_ULONG( p ); 1454*37da2899SCharles.Forsyth FT_UInt32 count = TT_NEXT_ULONG( p ); 1455*37da2899SCharles.Forsyth FT_UInt32 idx; 1456*37da2899SCharles.Forsyth 1457*37da2899SCharles.Forsyth 1458*37da2899SCharles.Forsyth if ( char_code < start ) 1459*37da2899SCharles.Forsyth char_code = start; 1460*37da2899SCharles.Forsyth 1461*37da2899SCharles.Forsyth idx = (FT_UInt32)( char_code - start ); 1462*37da2899SCharles.Forsyth p += 2 * idx; 1463*37da2899SCharles.Forsyth 1464*37da2899SCharles.Forsyth for ( ; idx < count; idx++ ) 1465*37da2899SCharles.Forsyth { 1466*37da2899SCharles.Forsyth gindex = TT_NEXT_USHORT( p ); 1467*37da2899SCharles.Forsyth if ( gindex != 0 ) 1468*37da2899SCharles.Forsyth { 1469*37da2899SCharles.Forsyth result = char_code; 1470*37da2899SCharles.Forsyth break; 1471*37da2899SCharles.Forsyth } 1472*37da2899SCharles.Forsyth char_code++; 1473*37da2899SCharles.Forsyth } 1474*37da2899SCharles.Forsyth 1475*37da2899SCharles.Forsyth *pchar_code = char_code; 1476*37da2899SCharles.Forsyth return gindex; 1477*37da2899SCharles.Forsyth } 1478*37da2899SCharles.Forsyth 1479*37da2899SCharles.Forsyth 1480*37da2899SCharles.Forsyth FT_CALLBACK_TABLE_DEF 1481*37da2899SCharles.Forsyth const TT_CMap_ClassRec tt_cmap10_class_rec = 1482*37da2899SCharles.Forsyth { 1483*37da2899SCharles.Forsyth { 1484*37da2899SCharles.Forsyth sizeof ( TT_CMapRec ), 1485*37da2899SCharles.Forsyth 1486*37da2899SCharles.Forsyth (FT_CMap_InitFunc) tt_cmap_init, 1487*37da2899SCharles.Forsyth (FT_CMap_DoneFunc) NULL, 1488*37da2899SCharles.Forsyth (FT_CMap_CharIndexFunc)tt_cmap10_char_index, 1489*37da2899SCharles.Forsyth (FT_CMap_CharNextFunc) tt_cmap10_char_next 1490*37da2899SCharles.Forsyth }, 1491*37da2899SCharles.Forsyth 10, 1492*37da2899SCharles.Forsyth (TT_CMap_ValidateFunc) tt_cmap10_validate 1493*37da2899SCharles.Forsyth }; 1494*37da2899SCharles.Forsyth 1495*37da2899SCharles.Forsyth #endif /* TT_CONFIG_CMAP_FORMAT_10 */ 1496*37da2899SCharles.Forsyth 1497*37da2899SCharles.Forsyth 1498*37da2899SCharles.Forsyth /*************************************************************************/ 1499*37da2899SCharles.Forsyth /*************************************************************************/ 1500*37da2899SCharles.Forsyth /***** *****/ 1501*37da2899SCharles.Forsyth /***** FORMAT 12 *****/ 1502*37da2899SCharles.Forsyth /***** *****/ 1503*37da2899SCharles.Forsyth /*************************************************************************/ 1504*37da2899SCharles.Forsyth /*************************************************************************/ 1505*37da2899SCharles.Forsyth 1506*37da2899SCharles.Forsyth /*************************************************************************/ 1507*37da2899SCharles.Forsyth /* */ 1508*37da2899SCharles.Forsyth /* TABLE OVERVIEW */ 1509*37da2899SCharles.Forsyth /* -------------- */ 1510*37da2899SCharles.Forsyth /* */ 1511*37da2899SCharles.Forsyth /* NAME OFFSET TYPE DESCRIPTION */ 1512*37da2899SCharles.Forsyth /* */ 1513*37da2899SCharles.Forsyth /* format 0 USHORT must be 12 */ 1514*37da2899SCharles.Forsyth /* reserved 2 USHORT reserved */ 1515*37da2899SCharles.Forsyth /* length 4 ULONG length in bytes */ 1516*37da2899SCharles.Forsyth /* language 8 ULONG Mac language code */ 1517*37da2899SCharles.Forsyth /* count 12 ULONG number of groups */ 1518*37da2899SCharles.Forsyth /* 16 */ 1519*37da2899SCharles.Forsyth /* */ 1520*37da2899SCharles.Forsyth /* This header is followed by `count' groups of the following format: */ 1521*37da2899SCharles.Forsyth /* */ 1522*37da2899SCharles.Forsyth /* start 0 ULONG first charcode */ 1523*37da2899SCharles.Forsyth /* end 4 ULONG last charcode */ 1524*37da2899SCharles.Forsyth /* startId 8 ULONG start glyph id for the group */ 1525*37da2899SCharles.Forsyth /* */ 1526*37da2899SCharles.Forsyth 1527*37da2899SCharles.Forsyth #ifdef TT_CONFIG_CMAP_FORMAT_12 1528*37da2899SCharles.Forsyth 1529*37da2899SCharles.Forsyth FT_CALLBACK_DEF( void ) tt_cmap12_validate(FT_Byte * table,FT_Validator valid)1530*37da2899SCharles.Forsyth tt_cmap12_validate( FT_Byte* table, 1531*37da2899SCharles.Forsyth FT_Validator valid ) 1532*37da2899SCharles.Forsyth { 1533*37da2899SCharles.Forsyth FT_Byte* p; 1534*37da2899SCharles.Forsyth FT_ULong length; 1535*37da2899SCharles.Forsyth FT_ULong num_groups; 1536*37da2899SCharles.Forsyth 1537*37da2899SCharles.Forsyth 1538*37da2899SCharles.Forsyth if ( table + 16 > valid->limit ) 1539*37da2899SCharles.Forsyth FT_INVALID_TOO_SHORT; 1540*37da2899SCharles.Forsyth 1541*37da2899SCharles.Forsyth p = table + 4; 1542*37da2899SCharles.Forsyth length = TT_NEXT_ULONG( p ); 1543*37da2899SCharles.Forsyth 1544*37da2899SCharles.Forsyth p = table + 12; 1545*37da2899SCharles.Forsyth num_groups = TT_NEXT_ULONG( p ); 1546*37da2899SCharles.Forsyth 1547*37da2899SCharles.Forsyth if ( table + length > valid->limit || length < 16 + 12 * num_groups ) 1548*37da2899SCharles.Forsyth FT_INVALID_TOO_SHORT; 1549*37da2899SCharles.Forsyth 1550*37da2899SCharles.Forsyth /* check groups, they must be in increasing order */ 1551*37da2899SCharles.Forsyth { 1552*37da2899SCharles.Forsyth FT_ULong n, start, end, start_id, last = 0; 1553*37da2899SCharles.Forsyth 1554*37da2899SCharles.Forsyth 1555*37da2899SCharles.Forsyth for ( n = 0; n < num_groups; n++ ) 1556*37da2899SCharles.Forsyth { 1557*37da2899SCharles.Forsyth start = TT_NEXT_ULONG( p ); 1558*37da2899SCharles.Forsyth end = TT_NEXT_ULONG( p ); 1559*37da2899SCharles.Forsyth start_id = TT_NEXT_ULONG( p ); 1560*37da2899SCharles.Forsyth 1561*37da2899SCharles.Forsyth if ( start > end ) 1562*37da2899SCharles.Forsyth FT_INVALID_DATA; 1563*37da2899SCharles.Forsyth 1564*37da2899SCharles.Forsyth if ( n > 0 && start <= last ) 1565*37da2899SCharles.Forsyth FT_INVALID_DATA; 1566*37da2899SCharles.Forsyth 1567*37da2899SCharles.Forsyth if ( valid->level >= FT_VALIDATE_TIGHT ) 1568*37da2899SCharles.Forsyth { 1569*37da2899SCharles.Forsyth if ( start_id + end - start >= TT_VALID_GLYPH_COUNT( valid ) ) 1570*37da2899SCharles.Forsyth FT_INVALID_GLYPH_ID; 1571*37da2899SCharles.Forsyth } 1572*37da2899SCharles.Forsyth 1573*37da2899SCharles.Forsyth last = end; 1574*37da2899SCharles.Forsyth } 1575*37da2899SCharles.Forsyth } 1576*37da2899SCharles.Forsyth } 1577*37da2899SCharles.Forsyth 1578*37da2899SCharles.Forsyth 1579*37da2899SCharles.Forsyth FT_CALLBACK_DEF( FT_UInt ) tt_cmap12_char_index(TT_CMap cmap,FT_UInt32 char_code)1580*37da2899SCharles.Forsyth tt_cmap12_char_index( TT_CMap cmap, 1581*37da2899SCharles.Forsyth FT_UInt32 char_code ) 1582*37da2899SCharles.Forsyth { 1583*37da2899SCharles.Forsyth FT_UInt result = 0; 1584*37da2899SCharles.Forsyth FT_Byte* table = cmap->data; 1585*37da2899SCharles.Forsyth FT_Byte* p = table + 12; 1586*37da2899SCharles.Forsyth FT_UInt32 num_groups = TT_NEXT_ULONG( p ); 1587*37da2899SCharles.Forsyth FT_UInt32 start, end, start_id; 1588*37da2899SCharles.Forsyth 1589*37da2899SCharles.Forsyth 1590*37da2899SCharles.Forsyth for ( ; num_groups > 0; num_groups-- ) 1591*37da2899SCharles.Forsyth { 1592*37da2899SCharles.Forsyth start = TT_NEXT_ULONG( p ); 1593*37da2899SCharles.Forsyth end = TT_NEXT_ULONG( p ); 1594*37da2899SCharles.Forsyth start_id = TT_NEXT_ULONG( p ); 1595*37da2899SCharles.Forsyth 1596*37da2899SCharles.Forsyth if ( char_code < start ) 1597*37da2899SCharles.Forsyth break; 1598*37da2899SCharles.Forsyth 1599*37da2899SCharles.Forsyth if ( char_code <= end ) 1600*37da2899SCharles.Forsyth { 1601*37da2899SCharles.Forsyth result = (FT_UInt)( start_id + char_code - start ); 1602*37da2899SCharles.Forsyth break; 1603*37da2899SCharles.Forsyth } 1604*37da2899SCharles.Forsyth } 1605*37da2899SCharles.Forsyth return result; 1606*37da2899SCharles.Forsyth } 1607*37da2899SCharles.Forsyth 1608*37da2899SCharles.Forsyth 1609*37da2899SCharles.Forsyth FT_CALLBACK_DEF( FT_UInt ) tt_cmap12_char_next(TT_CMap cmap,FT_UInt32 * pchar_code)1610*37da2899SCharles.Forsyth tt_cmap12_char_next( TT_CMap cmap, 1611*37da2899SCharles.Forsyth FT_UInt32 *pchar_code ) 1612*37da2899SCharles.Forsyth { 1613*37da2899SCharles.Forsyth FT_Byte* table = cmap->data; 1614*37da2899SCharles.Forsyth FT_UInt32 result = 0; 1615*37da2899SCharles.Forsyth FT_UInt32 char_code = *pchar_code + 1; 1616*37da2899SCharles.Forsyth FT_UInt gindex = 0; 1617*37da2899SCharles.Forsyth FT_Byte* p = table + 12; 1618*37da2899SCharles.Forsyth FT_UInt32 num_groups = TT_NEXT_ULONG( p ); 1619*37da2899SCharles.Forsyth FT_UInt32 start, end, start_id; 1620*37da2899SCharles.Forsyth 1621*37da2899SCharles.Forsyth 1622*37da2899SCharles.Forsyth p = table + 16; 1623*37da2899SCharles.Forsyth 1624*37da2899SCharles.Forsyth for ( ; num_groups > 0; num_groups-- ) 1625*37da2899SCharles.Forsyth { 1626*37da2899SCharles.Forsyth start = TT_NEXT_ULONG( p ); 1627*37da2899SCharles.Forsyth end = TT_NEXT_ULONG( p ); 1628*37da2899SCharles.Forsyth start_id = TT_NEXT_ULONG( p ); 1629*37da2899SCharles.Forsyth 1630*37da2899SCharles.Forsyth if ( char_code < start ) 1631*37da2899SCharles.Forsyth char_code = start; 1632*37da2899SCharles.Forsyth 1633*37da2899SCharles.Forsyth if ( char_code <= end ) 1634*37da2899SCharles.Forsyth { 1635*37da2899SCharles.Forsyth gindex = (FT_UInt)(char_code - start + start_id); 1636*37da2899SCharles.Forsyth if ( gindex != 0 ) 1637*37da2899SCharles.Forsyth { 1638*37da2899SCharles.Forsyth result = char_code; 1639*37da2899SCharles.Forsyth goto Exit; 1640*37da2899SCharles.Forsyth } 1641*37da2899SCharles.Forsyth } 1642*37da2899SCharles.Forsyth } 1643*37da2899SCharles.Forsyth 1644*37da2899SCharles.Forsyth Exit: 1645*37da2899SCharles.Forsyth *pchar_code = result; 1646*37da2899SCharles.Forsyth return gindex; 1647*37da2899SCharles.Forsyth } 1648*37da2899SCharles.Forsyth 1649*37da2899SCharles.Forsyth 1650*37da2899SCharles.Forsyth FT_CALLBACK_TABLE_DEF 1651*37da2899SCharles.Forsyth const TT_CMap_ClassRec tt_cmap12_class_rec = 1652*37da2899SCharles.Forsyth { 1653*37da2899SCharles.Forsyth { 1654*37da2899SCharles.Forsyth sizeof ( TT_CMapRec ), 1655*37da2899SCharles.Forsyth 1656*37da2899SCharles.Forsyth (FT_CMap_InitFunc) tt_cmap_init, 1657*37da2899SCharles.Forsyth (FT_CMap_DoneFunc) NULL, 1658*37da2899SCharles.Forsyth (FT_CMap_CharIndexFunc)tt_cmap12_char_index, 1659*37da2899SCharles.Forsyth (FT_CMap_CharNextFunc) tt_cmap12_char_next 1660*37da2899SCharles.Forsyth }, 1661*37da2899SCharles.Forsyth 12, 1662*37da2899SCharles.Forsyth (TT_CMap_ValidateFunc) tt_cmap12_validate 1663*37da2899SCharles.Forsyth }; 1664*37da2899SCharles.Forsyth 1665*37da2899SCharles.Forsyth 1666*37da2899SCharles.Forsyth #endif /* TT_CONFIG_CMAP_FORMAT_12 */ 1667*37da2899SCharles.Forsyth 1668*37da2899SCharles.Forsyth 1669*37da2899SCharles.Forsyth static const TT_CMap_Class tt_cmap_classes[] = 1670*37da2899SCharles.Forsyth { 1671*37da2899SCharles.Forsyth #ifdef TT_CONFIG_CMAP_FORMAT_0 1672*37da2899SCharles.Forsyth &tt_cmap0_class_rec, 1673*37da2899SCharles.Forsyth #endif 1674*37da2899SCharles.Forsyth 1675*37da2899SCharles.Forsyth #ifdef TT_CONFIG_CMAP_FORMAT_2 1676*37da2899SCharles.Forsyth &tt_cmap2_class_rec, 1677*37da2899SCharles.Forsyth #endif 1678*37da2899SCharles.Forsyth 1679*37da2899SCharles.Forsyth #ifdef TT_CONFIG_CMAP_FORMAT_4 1680*37da2899SCharles.Forsyth &tt_cmap4_class_rec, 1681*37da2899SCharles.Forsyth #endif 1682*37da2899SCharles.Forsyth 1683*37da2899SCharles.Forsyth #ifdef TT_CONFIG_CMAP_FORMAT_6 1684*37da2899SCharles.Forsyth &tt_cmap6_class_rec, 1685*37da2899SCharles.Forsyth #endif 1686*37da2899SCharles.Forsyth 1687*37da2899SCharles.Forsyth #ifdef TT_CONFIG_CMAP_FORMAT_8 1688*37da2899SCharles.Forsyth &tt_cmap8_class_rec, 1689*37da2899SCharles.Forsyth #endif 1690*37da2899SCharles.Forsyth 1691*37da2899SCharles.Forsyth #ifdef TT_CONFIG_CMAP_FORMAT_10 1692*37da2899SCharles.Forsyth &tt_cmap10_class_rec, 1693*37da2899SCharles.Forsyth #endif 1694*37da2899SCharles.Forsyth 1695*37da2899SCharles.Forsyth #ifdef TT_CONFIG_CMAP_FORMAT_12 1696*37da2899SCharles.Forsyth &tt_cmap12_class_rec, 1697*37da2899SCharles.Forsyth #endif 1698*37da2899SCharles.Forsyth 1699*37da2899SCharles.Forsyth NULL, 1700*37da2899SCharles.Forsyth }; 1701*37da2899SCharles.Forsyth 1702*37da2899SCharles.Forsyth 1703*37da2899SCharles.Forsyth /* parse the `cmap' table and build the corresponding TT_CMap objects */ 1704*37da2899SCharles.Forsyth /* in the current face */ 1705*37da2899SCharles.Forsyth /* */ 1706*37da2899SCharles.Forsyth FT_LOCAL_DEF( FT_Error ) tt_face_build_cmaps(TT_Face face)1707*37da2899SCharles.Forsyth tt_face_build_cmaps( TT_Face face ) 1708*37da2899SCharles.Forsyth { 1709*37da2899SCharles.Forsyth FT_Byte* table = face->cmap_table; 1710*37da2899SCharles.Forsyth FT_Byte* limit = table + face->cmap_size; 1711*37da2899SCharles.Forsyth FT_UInt volatile num_cmaps; 1712*37da2899SCharles.Forsyth FT_Byte* volatile p = table; 1713*37da2899SCharles.Forsyth 1714*37da2899SCharles.Forsyth 1715*37da2899SCharles.Forsyth if ( p + 4 > limit ) 1716*37da2899SCharles.Forsyth return FT_Err_Invalid_Table; 1717*37da2899SCharles.Forsyth 1718*37da2899SCharles.Forsyth /* only recognize format 0 */ 1719*37da2899SCharles.Forsyth if ( TT_NEXT_USHORT( p ) != 0 ) 1720*37da2899SCharles.Forsyth { 1721*37da2899SCharles.Forsyth p -= 2; 1722*37da2899SCharles.Forsyth FT_ERROR(( "tt_face_build_cmaps: unsupported `cmap' table format = %d\n", 1723*37da2899SCharles.Forsyth TT_PEEK_USHORT( p ) )); 1724*37da2899SCharles.Forsyth return FT_Err_Invalid_Table; 1725*37da2899SCharles.Forsyth } 1726*37da2899SCharles.Forsyth 1727*37da2899SCharles.Forsyth num_cmaps = TT_NEXT_USHORT( p ); 1728*37da2899SCharles.Forsyth 1729*37da2899SCharles.Forsyth for ( ; num_cmaps > 0 && p + 8 <= limit; num_cmaps-- ) 1730*37da2899SCharles.Forsyth { 1731*37da2899SCharles.Forsyth FT_CharMapRec charmap; 1732*37da2899SCharles.Forsyth FT_UInt32 offset; 1733*37da2899SCharles.Forsyth 1734*37da2899SCharles.Forsyth 1735*37da2899SCharles.Forsyth charmap.platform_id = TT_NEXT_USHORT( p ); 1736*37da2899SCharles.Forsyth charmap.encoding_id = TT_NEXT_USHORT( p ); 1737*37da2899SCharles.Forsyth charmap.face = FT_FACE( face ); 1738*37da2899SCharles.Forsyth charmap.encoding = FT_ENCODING_NONE; /* will be filled later */ 1739*37da2899SCharles.Forsyth offset = TT_NEXT_ULONG( p ); 1740*37da2899SCharles.Forsyth 1741*37da2899SCharles.Forsyth if ( offset && table + offset + 2 < limit ) 1742*37da2899SCharles.Forsyth { 1743*37da2899SCharles.Forsyth FT_Byte* cmap = table + offset; 1744*37da2899SCharles.Forsyth FT_UInt format = TT_PEEK_USHORT( cmap ); 1745*37da2899SCharles.Forsyth const TT_CMap_Class* volatile pclazz = tt_cmap_classes; 1746*37da2899SCharles.Forsyth TT_CMap_Class clazz; 1747*37da2899SCharles.Forsyth 1748*37da2899SCharles.Forsyth 1749*37da2899SCharles.Forsyth for ( ; *pclazz; pclazz++ ) 1750*37da2899SCharles.Forsyth { 1751*37da2899SCharles.Forsyth clazz = *pclazz; 1752*37da2899SCharles.Forsyth if ( clazz->format == format ) 1753*37da2899SCharles.Forsyth { 1754*37da2899SCharles.Forsyth volatile TT_ValidatorRec valid; 1755*37da2899SCharles.Forsyth 1756*37da2899SCharles.Forsyth 1757*37da2899SCharles.Forsyth ft_validator_init( FT_VALIDATOR( &valid ), cmap, limit, 1758*37da2899SCharles.Forsyth FT_VALIDATE_DEFAULT ); 1759*37da2899SCharles.Forsyth 1760*37da2899SCharles.Forsyth valid.num_glyphs = (FT_UInt)face->root.num_glyphs; 1761*37da2899SCharles.Forsyth 1762*37da2899SCharles.Forsyth if ( ft_setjmp( FT_VALIDATOR( &valid )->jump_buffer ) == 0 ) 1763*37da2899SCharles.Forsyth { 1764*37da2899SCharles.Forsyth /* validate this cmap sub-table */ 1765*37da2899SCharles.Forsyth clazz->validate( cmap, FT_VALIDATOR( &valid ) ); 1766*37da2899SCharles.Forsyth } 1767*37da2899SCharles.Forsyth 1768*37da2899SCharles.Forsyth if ( valid.validator.error == 0 ) 1769*37da2899SCharles.Forsyth (void)FT_CMap_New( (FT_CMap_Class)clazz, cmap, &charmap, NULL ); 1770*37da2899SCharles.Forsyth else 1771*37da2899SCharles.Forsyth { 1772*37da2899SCharles.Forsyth FT_ERROR(( "tt_face_build_cmaps:" )); 1773*37da2899SCharles.Forsyth FT_ERROR(( " broken cmap sub-table ignored!\n" )); 1774*37da2899SCharles.Forsyth } 1775*37da2899SCharles.Forsyth } 1776*37da2899SCharles.Forsyth } 1777*37da2899SCharles.Forsyth } 1778*37da2899SCharles.Forsyth } 1779*37da2899SCharles.Forsyth 1780*37da2899SCharles.Forsyth return 0; 1781*37da2899SCharles.Forsyth } 1782*37da2899SCharles.Forsyth 1783*37da2899SCharles.Forsyth 1784*37da2899SCharles.Forsyth /* END */ 1785