1ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/***************************************************************************/ 2ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* */ 3ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* ttcmap.c */ 4ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* */ 5ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* TrueType character mapping table (cmap) support (body). */ 6ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* */ 7ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* Copyright 2002-2010, 2012, 2013 by */ 8ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* David Turner, Robert Wilhelm, and Werner Lemberg. */ 9ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* */ 10ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* This file is part of the FreeType project, and may only be used, */ 11ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* modified, and distributed under the terms of the FreeType project */ 12ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ 13ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* this file you indicate that you have read the license and */ 14ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* understand and accept it fully. */ 15ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* */ 16ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/***************************************************************************/ 17ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 18ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 19ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "../../include/ft2build.h" 20ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "../../include/freetype/internal/ftdebug.h" 21ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 22ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "sferrors.h" /* must come before FT_INTERNAL_VALIDATE_H */ 23ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 24ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "../../include/freetype/internal/ftvalid.h" 25ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "../../include/freetype/internal/ftstream.h" 26ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "ttload.h" 27ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "ttcmap.h" 28ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "sfntpic.h" 29ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 30ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 31ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 32ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 33ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ 34ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ 35ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* messages during execution. */ 36ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 37ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#undef FT_COMPONENT 38ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define FT_COMPONENT trace_ttcmap 39ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 40ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 41ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define TT_PEEK_SHORT FT_PEEK_SHORT 42ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define TT_PEEK_USHORT FT_PEEK_USHORT 43ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define TT_PEEK_UINT24 FT_PEEK_UOFF3 44ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define TT_PEEK_LONG FT_PEEK_LONG 45ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define TT_PEEK_ULONG FT_PEEK_ULONG 46ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 47ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define TT_NEXT_SHORT FT_NEXT_SHORT 48ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define TT_NEXT_USHORT FT_NEXT_USHORT 49ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define TT_NEXT_UINT24 FT_NEXT_UOFF3 50ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define TT_NEXT_LONG FT_NEXT_LONG 51ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define TT_NEXT_ULONG FT_NEXT_ULONG 52ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 53ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 54ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_CALLBACK_DEF( FT_Error ) 55ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tt_cmap_init( TT_CMap cmap, 56ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte* table ) 57ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 58ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmap->data = table; 59ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FT_Err_Ok; 60ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 61ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 62ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 63ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 64ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 65ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /***** *****/ 66ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /***** FORMAT 0 *****/ 67ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /***** *****/ 68ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 69ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 70ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 71ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 72ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 73ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* TABLE OVERVIEW */ 74ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* -------------- */ 75ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 76ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* NAME OFFSET TYPE DESCRIPTION */ 77ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 78ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* format 0 USHORT must be 0 */ 79ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* length 2 USHORT table length in bytes */ 80ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* language 4 USHORT Mac language code */ 81ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* glyph_ids 6 BYTE[256] array of glyph indices */ 82ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* 262 */ 83ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 84ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 85ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#ifdef TT_CONFIG_CMAP_FORMAT_0 86ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 87ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_CALLBACK_DEF( FT_Error ) 88ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tt_cmap0_validate( FT_Byte* table, 89ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Validator valid ) 90ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 91ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte* p = table + 2; 92ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt length = TT_NEXT_USHORT( p ); 93ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 94ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 95ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( table + length > valid->limit || length < 262 ) 96ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_INVALID_TOO_SHORT; 97ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 98ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* check glyph indices whenever necessary */ 99ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( valid->level >= FT_VALIDATE_TIGHT ) 100ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 101ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt n, idx; 102ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 103ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 104ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p = table + 6; 105ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( n = 0; n < 256; n++ ) 106ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 107ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov idx = *p++; 108ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( idx >= TT_VALID_GLYPH_COUNT( valid ) ) 109ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_INVALID_GLYPH_ID; 110ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 111ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 112ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 113ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FT_Err_Ok; 114ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 115ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 116ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 117ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_CALLBACK_DEF( FT_UInt ) 118ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tt_cmap0_char_index( TT_CMap cmap, 119ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt32 char_code ) 120ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 121ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte* table = cmap->data; 122ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 123ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 124ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return char_code < 256 ? table[6 + char_code] : 0; 125ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 126ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 127ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 128ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_CALLBACK_DEF( FT_UInt32 ) 129ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tt_cmap0_char_next( TT_CMap cmap, 130ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt32 *pchar_code ) 131ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 132ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte* table = cmap->data; 133ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt32 charcode = *pchar_code; 134ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt32 result = 0; 135ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt gindex = 0; 136ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 137ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 138ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov table += 6; /* go to glyph IDs */ 139ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov while ( ++charcode < 256 ) 140ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 141ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gindex = table[charcode]; 142ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( gindex != 0 ) 143ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 144ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov result = charcode; 145ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 146ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 147ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 148ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 149ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov *pchar_code = result; 150ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return gindex; 151ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 152ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 153ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 154ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_CALLBACK_DEF( FT_Error ) 155ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tt_cmap0_get_info( TT_CMap cmap, 156ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TT_CMapInfo *cmap_info ) 157ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 158ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte* p = cmap->data + 4; 159ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 160ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 161ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmap_info->format = 0; 162ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmap_info->language = (FT_ULong)TT_PEEK_USHORT( p ); 163ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 164ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FT_Err_Ok; 165ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 166ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 167ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 168ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_DEFINE_TT_CMAP( 169ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tt_cmap0_class_rec, 170ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov sizeof ( TT_CMapRec ), 171ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 172ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (FT_CMap_InitFunc) tt_cmap_init, 173ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (FT_CMap_DoneFunc) NULL, 174ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (FT_CMap_CharIndexFunc)tt_cmap0_char_index, 175ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (FT_CMap_CharNextFunc) tt_cmap0_char_next, 176ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 177ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov NULL, 178ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov NULL, 179ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov NULL, 180ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov NULL, 181ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov NULL, 182ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 183ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 0, 184ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (TT_CMap_ValidateFunc)tt_cmap0_validate, 185ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (TT_CMap_Info_GetFunc)tt_cmap0_get_info ) 186ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 187ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif /* TT_CONFIG_CMAP_FORMAT_0 */ 188ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 189ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 190ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 191ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 192ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /***** *****/ 193ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /***** FORMAT 2 *****/ 194ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /***** *****/ 195ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /***** This is used for certain CJK encodings that encode text in a *****/ 196ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /***** mixed 8/16 bits encoding along the following lines: *****/ 197ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /***** *****/ 198ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /***** * Certain byte values correspond to an 8-bit character code *****/ 199ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /***** (typically in the range 0..127 for ASCII compatibility). *****/ 200ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /***** *****/ 201ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /***** * Certain byte values signal the first byte of a 2-byte *****/ 202ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /***** character code (but these values are also valid as the *****/ 203ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /***** second byte of a 2-byte character). *****/ 204ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /***** *****/ 205ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /***** The following charmap lookup and iteration functions all *****/ 206ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /***** assume that the value "charcode" correspond to following: *****/ 207ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /***** *****/ 208ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /***** - For one byte characters, "charcode" is simply the *****/ 209ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /***** character code. *****/ 210ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /***** *****/ 211ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /***** - For two byte characters, "charcode" is the 2-byte *****/ 212ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /***** character code in big endian format. More exactly: *****/ 213ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /***** *****/ 214ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /***** (charcode >> 8) is the first byte value *****/ 215ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /***** (charcode & 0xFF) is the second byte value *****/ 216ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /***** *****/ 217ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /***** Note that not all values of "charcode" are valid according *****/ 218ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /***** to these rules, and the function moderately check the *****/ 219ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /***** arguments. *****/ 220ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /***** *****/ 221ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 222ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 223ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 224ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 225ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 226ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* TABLE OVERVIEW */ 227ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* -------------- */ 228ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 229ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* NAME OFFSET TYPE DESCRIPTION */ 230ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 231ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* format 0 USHORT must be 2 */ 232ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* length 2 USHORT table length in bytes */ 233ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* language 4 USHORT Mac language code */ 234ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* keys 6 USHORT[256] sub-header keys */ 235ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* subs 518 SUBHEAD[NSUBS] sub-headers array */ 236ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* glyph_ids 518+NSUB*8 USHORT[] glyph ID array */ 237ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 238ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* The `keys' table is used to map charcode high-bytes to sub-headers. */ 239ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* The value of `NSUBS' is the number of sub-headers defined in the */ 240ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* table and is computed by finding the maximum of the `keys' table. */ 241ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 242ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* Note that for any n, `keys[n]' is a byte offset within the `subs' */ 243ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* table, i.e., it is the corresponding sub-header index multiplied */ 244ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* by 8. */ 245ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 246ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* Each sub-header has the following format: */ 247ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 248ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* NAME OFFSET TYPE DESCRIPTION */ 249ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 250ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* first 0 USHORT first valid low-byte */ 251ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* count 2 USHORT number of valid low-bytes */ 252ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* delta 4 SHORT see below */ 253ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* offset 6 USHORT see below */ 254ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 255ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* A sub-header defines, for each high-byte, the range of valid */ 256ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* low-bytes within the charmap. Note that the range defined by `first' */ 257ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* and `count' must be completely included in the interval [0..255] */ 258ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* according to the specification. */ 259ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 260ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* If a character code is contained within a given sub-header, then */ 261ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* mapping it to a glyph index is done as follows: */ 262ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 263ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* * The value of `offset' is read. This is a _byte_ distance from the */ 264ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* location of the `offset' field itself into a slice of the */ 265ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* `glyph_ids' table. Let's call it `slice' (it is a USHORT[] too). */ 266ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 267ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* * The value `slice[char.lo - first]' is read. If it is 0, there is */ 268ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* no glyph for the charcode. Otherwise, the value of `delta' is */ 269ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* added to it (modulo 65536) to form a new glyph index. */ 270ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 271ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* It is up to the validation routine to check that all offsets fall */ 272ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* within the glyph IDs table (and not within the `subs' table itself or */ 273ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* outside of the CMap). */ 274ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 275ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 276ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#ifdef TT_CONFIG_CMAP_FORMAT_2 277ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 278ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_CALLBACK_DEF( FT_Error ) 279ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tt_cmap2_validate( FT_Byte* table, 280ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Validator valid ) 281ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 282ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte* p = table + 2; /* skip format */ 283ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt length = TT_PEEK_USHORT( p ); 284ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt n, max_subs; 285ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte* keys; /* keys table */ 286ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte* subs; /* sub-headers */ 287ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte* glyph_ids; /* glyph ID array */ 288ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 289ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 290ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( table + length > valid->limit || length < 6 + 512 ) 291ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_INVALID_TOO_SHORT; 292ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 293ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov keys = table + 6; 294ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 295ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* parse keys to compute sub-headers count */ 296ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p = keys; 297ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov max_subs = 0; 298ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( n = 0; n < 256; n++ ) 299ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 300ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt idx = TT_NEXT_USHORT( p ); 301ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 302ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 303ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* value must be multiple of 8 */ 304ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( valid->level >= FT_VALIDATE_PARANOID && ( idx & 7 ) != 0 ) 305ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_INVALID_DATA; 306ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 307ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov idx >>= 3; 308ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 309ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( idx > max_subs ) 310ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov max_subs = idx; 311ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 312ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 313ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_ASSERT( p == table + 518 ); 314ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 315ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov subs = p; 316ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov glyph_ids = subs + (max_subs + 1) * 8; 317ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( glyph_ids > valid->limit ) 318ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_INVALID_TOO_SHORT; 319ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 320ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* parse sub-headers */ 321ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( n = 0; n <= max_subs; n++ ) 322ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 323ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt first_code, code_count, offset; 324ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Int delta; 325ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte* ids; 326ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 327ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 328ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov first_code = TT_NEXT_USHORT( p ); 329ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov code_count = TT_NEXT_USHORT( p ); 330ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov delta = TT_NEXT_SHORT( p ); 331ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov offset = TT_NEXT_USHORT( p ); 332ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 333ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* many Dynalab fonts have empty sub-headers */ 334ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( code_count == 0 ) 335ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov continue; 336ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 337ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* check range within 0..255 */ 338ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( valid->level >= FT_VALIDATE_PARANOID ) 339ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 340ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( first_code >= 256 || first_code + code_count > 256 ) 341ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_INVALID_DATA; 342ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 343ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 344ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* check offset */ 345ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( offset != 0 ) 346ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 347ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ids = p - 2 + offset; 348ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( ids < glyph_ids || ids + code_count*2 > table + length ) 349ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_INVALID_OFFSET; 350ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 351ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* check glyph IDs */ 352ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( valid->level >= FT_VALIDATE_TIGHT ) 353ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 354ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte* limit = p + code_count * 2; 355ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt idx; 356ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 357ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 358ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( ; p < limit; ) 359ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 360ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov idx = TT_NEXT_USHORT( p ); 361ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( idx != 0 ) 362ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 363ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov idx = ( idx + delta ) & 0xFFFFU; 364ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( idx >= TT_VALID_GLYPH_COUNT( valid ) ) 365ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_INVALID_GLYPH_ID; 366ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 367ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 368ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 369ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 370ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 371ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 372ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FT_Err_Ok; 373ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 374ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 375ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 376ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* return sub header corresponding to a given character code */ 377ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* NULL on invalid charcode */ 378ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov static FT_Byte* 379ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tt_cmap2_get_subheader( FT_Byte* table, 380ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt32 char_code ) 381ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 382ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte* result = NULL; 383ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 384ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 385ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( char_code < 0x10000UL ) 386ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 387ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt char_lo = (FT_UInt)( char_code & 0xFF ); 388ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt char_hi = (FT_UInt)( char_code >> 8 ); 389ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte* p = table + 6; /* keys table */ 390ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte* subs = table + 518; /* subheaders table */ 391ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte* sub; 392ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 393ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 394ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( char_hi == 0 ) 395ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 396ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* an 8-bit character code -- we use subHeader 0 in this case */ 397ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* to test whether the character code is in the charmap */ 398ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 399ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov sub = subs; /* jump to first sub-header */ 400ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 401ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* check that the sub-header for this byte is 0, which */ 402ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* indicates that it is really a valid one-byte value */ 403ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* Otherwise, return 0 */ 404ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 405ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p += char_lo * 2; 406ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( TT_PEEK_USHORT( p ) != 0 ) 407ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Exit; 408ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 409ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else 410ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 411ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* a 16-bit character code */ 412ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 413ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* jump to key entry */ 414ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p += char_hi * 2; 415ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* jump to sub-header */ 416ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov sub = subs + ( FT_PAD_FLOOR( TT_PEEK_USHORT( p ), 8 ) ); 417ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 418ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* check that the high byte isn't a valid one-byte value */ 419ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( sub == subs ) 420ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Exit; 421ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 422ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov result = sub; 423ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 424ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Exit: 425ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return result; 426ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 427ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 428ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 429ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_CALLBACK_DEF( FT_UInt ) 430ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tt_cmap2_char_index( TT_CMap cmap, 431ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt32 char_code ) 432ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 433ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte* table = cmap->data; 434ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt result = 0; 435ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte* subheader; 436ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 437ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 438ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov subheader = tt_cmap2_get_subheader( table, char_code ); 439ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( subheader ) 440ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 441ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte* p = subheader; 442ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt idx = (FT_UInt)(char_code & 0xFF); 443ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt start, count; 444ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Int delta; 445ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt offset; 446ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 447ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 448ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov start = TT_NEXT_USHORT( p ); 449ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov count = TT_NEXT_USHORT( p ); 450ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov delta = TT_NEXT_SHORT ( p ); 451ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov offset = TT_PEEK_USHORT( p ); 452ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 453ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov idx -= start; 454ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( idx < count && offset != 0 ) 455ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 456ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p += offset + 2 * idx; 457ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov idx = TT_PEEK_USHORT( p ); 458ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 459ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( idx != 0 ) 460ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov result = (FT_UInt)( idx + delta ) & 0xFFFFU; 461ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 462ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 463ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return result; 464ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 465ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 466ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 467ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_CALLBACK_DEF( FT_UInt32 ) 468ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tt_cmap2_char_next( TT_CMap cmap, 469ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt32 *pcharcode ) 470ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 471ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte* table = cmap->data; 472ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt gindex = 0; 473ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt32 result = 0; 474ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt32 charcode = *pcharcode + 1; 475ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte* subheader; 476ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 477ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 478ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov while ( charcode < 0x10000UL ) 479ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 480ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov subheader = tt_cmap2_get_subheader( table, charcode ); 481ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( subheader ) 482ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 483ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte* p = subheader; 484ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt start = TT_NEXT_USHORT( p ); 485ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt count = TT_NEXT_USHORT( p ); 486ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Int delta = TT_NEXT_SHORT ( p ); 487ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt offset = TT_PEEK_USHORT( p ); 488ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt char_lo = (FT_UInt)( charcode & 0xFF ); 489ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt pos, idx; 490ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 491ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 492ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( offset == 0 ) 493ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Next_SubHeader; 494ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 495ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( char_lo < start ) 496ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 497ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov char_lo = start; 498ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov pos = 0; 499ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 500ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else 501ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov pos = (FT_UInt)( char_lo - start ); 502ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 503ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p += offset + pos * 2; 504ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov charcode = FT_PAD_FLOOR( charcode, 256 ) + char_lo; 505ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 506ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( ; pos < count; pos++, charcode++ ) 507ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 508ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov idx = TT_NEXT_USHORT( p ); 509ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 510ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( idx != 0 ) 511ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 512ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gindex = ( idx + delta ) & 0xFFFFU; 513ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( gindex != 0 ) 514ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 515ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov result = charcode; 516ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Exit; 517ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 518ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 519ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 520ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 521ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 522ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* jump to next sub-header, i.e. higher byte value */ 523ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Next_SubHeader: 524ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov charcode = FT_PAD_FLOOR( charcode, 256 ) + 256; 525ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 526ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 527ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Exit: 528ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov *pcharcode = result; 529ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 530ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return gindex; 531ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 532ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 533ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 534ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_CALLBACK_DEF( FT_Error ) 535ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tt_cmap2_get_info( TT_CMap cmap, 536ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TT_CMapInfo *cmap_info ) 537ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 538ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte* p = cmap->data + 4; 539ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 540ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 541ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmap_info->format = 2; 542ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmap_info->language = (FT_ULong)TT_PEEK_USHORT( p ); 543ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 544ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FT_Err_Ok; 545ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 546ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 547ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 548ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_DEFINE_TT_CMAP( 549ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tt_cmap2_class_rec, 550ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov sizeof ( TT_CMapRec ), 551ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 552ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (FT_CMap_InitFunc) tt_cmap_init, 553ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (FT_CMap_DoneFunc) NULL, 554ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (FT_CMap_CharIndexFunc)tt_cmap2_char_index, 555ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (FT_CMap_CharNextFunc) tt_cmap2_char_next, 556ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 557ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov NULL, 558ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov NULL, 559ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov NULL, 560ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov NULL, 561ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov NULL, 562ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 563ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2, 564ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (TT_CMap_ValidateFunc)tt_cmap2_validate, 565ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (TT_CMap_Info_GetFunc)tt_cmap2_get_info ) 566ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 567ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif /* TT_CONFIG_CMAP_FORMAT_2 */ 568ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 569ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 570ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 571ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 572ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /***** *****/ 573ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /***** FORMAT 4 *****/ 574ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /***** *****/ 575ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 576ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 577ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 578ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 579ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 580ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* TABLE OVERVIEW */ 581ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* -------------- */ 582ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 583ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* NAME OFFSET TYPE DESCRIPTION */ 584ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 585ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* format 0 USHORT must be 4 */ 586ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* length 2 USHORT table length */ 587ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* in bytes */ 588ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* language 4 USHORT Mac language code */ 589ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 590ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* segCountX2 6 USHORT 2*NUM_SEGS */ 591ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* searchRange 8 USHORT 2*(1 << LOG_SEGS) */ 592ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* entrySelector 10 USHORT LOG_SEGS */ 593ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* rangeShift 12 USHORT segCountX2 - */ 594ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* searchRange */ 595ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 596ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* endCount 14 USHORT[NUM_SEGS] end charcode for */ 597ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* each segment; last */ 598ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* is 0xFFFF */ 599ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 600ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* pad 14+NUM_SEGS*2 USHORT padding */ 601ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 602ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* startCount 16+NUM_SEGS*2 USHORT[NUM_SEGS] first charcode for */ 603ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* each segment */ 604ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 605ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* idDelta 16+NUM_SEGS*4 SHORT[NUM_SEGS] delta for each */ 606ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* segment */ 607ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* idOffset 16+NUM_SEGS*6 SHORT[NUM_SEGS] range offset for */ 608ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* each segment; can be */ 609ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* zero */ 610ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 611ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* glyphIds 16+NUM_SEGS*8 USHORT[] array of glyph ID */ 612ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* ranges */ 613ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 614ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* Character codes are modelled by a series of ordered (increasing) */ 615ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* intervals called segments. Each segment has start and end codes, */ 616ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* provided by the `startCount' and `endCount' arrays. Segments must */ 617ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* not overlap, and the last segment should always contain the value */ 618ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* 0xFFFF for `endCount'. */ 619ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 620ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* The fields `searchRange', `entrySelector' and `rangeShift' are better */ 621ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* ignored (they are traces of over-engineering in the TrueType */ 622ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* specification). */ 623ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 624ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* Each segment also has a signed `delta', as well as an optional offset */ 625ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* within the `glyphIds' table. */ 626ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 627ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* If a segment's idOffset is 0, the glyph index corresponding to any */ 628ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* charcode within the segment is obtained by adding the value of */ 629ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* `idDelta' directly to the charcode, modulo 65536. */ 630ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 631ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* Otherwise, a glyph index is taken from the glyph IDs sub-array for */ 632ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* the segment, and the value of `idDelta' is added to it. */ 633ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 634ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 635ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* Finally, note that a lot of fonts contain an invalid last segment, */ 636ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* where `start' and `end' are correctly set to 0xFFFF but both `delta' */ 637ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* and `offset' are incorrect (e.g., `opens___.ttf' which comes with */ 638ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* OpenOffice.org). We need special code to deal with them correctly. */ 639ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 640ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 641ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#ifdef TT_CONFIG_CMAP_FORMAT_4 642ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 643ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov typedef struct TT_CMap4Rec_ 644ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 645ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TT_CMapRec cmap; 646ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt32 cur_charcode; /* current charcode */ 647ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt cur_gindex; /* current glyph index */ 648ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 649ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt num_ranges; 650ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt cur_range; 651ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt cur_start; 652ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt cur_end; 653ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Int cur_delta; 654ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte* cur_values; 655ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 656ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } TT_CMap4Rec, *TT_CMap4; 657ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 658ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 659ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_CALLBACK_DEF( FT_Error ) 660ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tt_cmap4_init( TT_CMap4 cmap, 661ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte* table ) 662ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 663ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte* p; 664ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 665ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 666ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmap->cmap.data = table; 667ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 668ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p = table + 6; 669ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmap->num_ranges = FT_PEEK_USHORT( p ) >> 1; 670ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmap->cur_charcode = (FT_UInt32)0xFFFFFFFFUL; 671ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmap->cur_gindex = 0; 672ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 673ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FT_Err_Ok; 674ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 675ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 676ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 677ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov static FT_Int 678ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tt_cmap4_set_range( TT_CMap4 cmap, 679ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt range_index ) 680ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 681ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte* table = cmap->cmap.data; 682ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte* p; 683ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt num_ranges = cmap->num_ranges; 684ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 685ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 686ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov while ( range_index < num_ranges ) 687ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 688ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt offset; 689ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 690ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 691ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p = table + 14 + range_index * 2; 692ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmap->cur_end = FT_PEEK_USHORT( p ); 693ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 694ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p += 2 + num_ranges * 2; 695ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmap->cur_start = FT_PEEK_USHORT( p ); 696ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 697ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p += num_ranges * 2; 698ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmap->cur_delta = FT_PEEK_SHORT( p ); 699ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 700ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p += num_ranges * 2; 701ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov offset = FT_PEEK_USHORT( p ); 702ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 703ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* some fonts have an incorrect last segment; */ 704ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* we have to catch it */ 705ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( range_index >= num_ranges - 1 && 706ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmap->cur_start == 0xFFFFU && 707ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmap->cur_end == 0xFFFFU ) 708ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 709ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TT_Face face = (TT_Face)cmap->cmap.cmap.charmap.face; 710ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte* limit = face->cmap_table + face->cmap_size; 711ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 712ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 713ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( offset && p + offset + 2 > limit ) 714ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 715ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmap->cur_delta = 1; 716ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov offset = 0; 717ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 718ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 719ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 720ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( offset != 0xFFFFU ) 721ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 722ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmap->cur_values = offset ? p + offset : NULL; 723ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmap->cur_range = range_index; 724ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return 0; 725ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 726ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 727ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* we skip empty segments */ 728ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov range_index++; 729ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 730ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 731ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return -1; 732ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 733ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 734ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 735ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* search the index of the charcode next to cmap->cur_charcode; */ 736ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* caller should call tt_cmap4_set_range with proper range */ 737ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* before calling this function */ 738ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 739ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov static void 740ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tt_cmap4_next( TT_CMap4 cmap ) 741ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 742ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt charcode; 743ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 744ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 745ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( cmap->cur_charcode >= 0xFFFFUL ) 746ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Fail; 747ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 748ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov charcode = (FT_UInt)cmap->cur_charcode + 1; 749ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 750ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( charcode < cmap->cur_start ) 751ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov charcode = cmap->cur_start; 752ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 753ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( ;; ) 754ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 755ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte* values = cmap->cur_values; 756ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt end = cmap->cur_end; 757ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Int delta = cmap->cur_delta; 758ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 759ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 760ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( charcode <= end ) 761ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 762ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( values ) 763ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 764ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte* p = values + 2 * ( charcode - cmap->cur_start ); 765ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 766ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 767ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov do 768ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 769ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt gindex = FT_NEXT_USHORT( p ); 770ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 771ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 772ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( gindex != 0 ) 773ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 774ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gindex = (FT_UInt)( ( gindex + delta ) & 0xFFFFU ); 775ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( gindex != 0 ) 776ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 777ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmap->cur_charcode = charcode; 778ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmap->cur_gindex = gindex; 779ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return; 780ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 781ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 782ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } while ( ++charcode <= end ); 783ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 784ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else 785ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 786ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov do 787ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 788ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt gindex = (FT_UInt)( ( charcode + delta ) & 0xFFFFU ); 789ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 790ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 791ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( gindex != 0 ) 792ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 793ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmap->cur_charcode = charcode; 794ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmap->cur_gindex = gindex; 795ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return; 796ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 797ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } while ( ++charcode <= end ); 798ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 799ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 800ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 801ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* we need to find another range */ 802ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( tt_cmap4_set_range( cmap, cmap->cur_range + 1 ) < 0 ) 803ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 804ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 805ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( charcode < cmap->cur_start ) 806ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov charcode = cmap->cur_start; 807ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 808ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 809ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Fail: 810ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmap->cur_charcode = (FT_UInt32)0xFFFFFFFFUL; 811ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmap->cur_gindex = 0; 812ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 813ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 814ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 815ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_CALLBACK_DEF( FT_Error ) 816ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tt_cmap4_validate( FT_Byte* table, 817ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Validator valid ) 818ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 819ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte* p = table + 2; /* skip format */ 820ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt length = TT_NEXT_USHORT( p ); 821ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte *ends, *starts, *offsets, *deltas, *glyph_ids; 822ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt num_segs; 823ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Error error = FT_Err_Ok; 824ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 825ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 826ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( length < 16 ) 827ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_INVALID_TOO_SHORT; 828ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 829ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* in certain fonts, the `length' field is invalid and goes */ 830ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* out of bound. We try to correct this here... */ 831ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( table + length > valid->limit ) 832ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 833ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( valid->level >= FT_VALIDATE_TIGHT ) 834ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_INVALID_TOO_SHORT; 835ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 836ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov length = (FT_UInt)( valid->limit - table ); 837ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 838ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 839ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p = table + 6; 840ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov num_segs = TT_NEXT_USHORT( p ); /* read segCountX2 */ 841ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 842ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( valid->level >= FT_VALIDATE_PARANOID ) 843ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 844ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* check that we have an even value here */ 845ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( num_segs & 1 ) 846ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_INVALID_DATA; 847ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 848ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 849ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov num_segs /= 2; 850ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 851ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( length < 16 + num_segs * 2 * 4 ) 852ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_INVALID_TOO_SHORT; 853ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 854ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* check the search parameters - even though we never use them */ 855ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 856ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( valid->level >= FT_VALIDATE_PARANOID ) 857ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 858ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* check the values of `searchRange', `entrySelector', `rangeShift' */ 859ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt search_range = TT_NEXT_USHORT( p ); 860ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt entry_selector = TT_NEXT_USHORT( p ); 861ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt range_shift = TT_NEXT_USHORT( p ); 862ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 863ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 864ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( ( search_range | range_shift ) & 1 ) /* must be even values */ 865ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_INVALID_DATA; 866ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 867ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov search_range /= 2; 868ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov range_shift /= 2; 869ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 870ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* `search range' is the greatest power of 2 that is <= num_segs */ 871ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 872ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( search_range > num_segs || 873ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov search_range * 2 < num_segs || 874ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov search_range + range_shift != num_segs || 875ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov search_range != ( 1U << entry_selector ) ) 876ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_INVALID_DATA; 877ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 878ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 879ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ends = table + 14; 880ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov starts = table + 16 + num_segs * 2; 881ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov deltas = starts + num_segs * 2; 882ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov offsets = deltas + num_segs * 2; 883ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov glyph_ids = offsets + num_segs * 2; 884ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 885ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* check last segment; its end count value must be 0xFFFF */ 886ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( valid->level >= FT_VALIDATE_PARANOID ) 887ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 888ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p = ends + ( num_segs - 1 ) * 2; 889ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( TT_PEEK_USHORT( p ) != 0xFFFFU ) 890ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_INVALID_DATA; 891ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 892ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 893ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 894ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt start, end, offset, n; 895ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt last_start = 0, last_end = 0; 896ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Int delta; 897ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte* p_start = starts; 898ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte* p_end = ends; 899ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte* p_delta = deltas; 900ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte* p_offset = offsets; 901ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 902ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 903ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( n = 0; n < num_segs; n++ ) 904ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 905ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p = p_offset; 906ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov start = TT_NEXT_USHORT( p_start ); 907ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov end = TT_NEXT_USHORT( p_end ); 908ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov delta = TT_NEXT_SHORT( p_delta ); 909ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov offset = TT_NEXT_USHORT( p_offset ); 910ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 911ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( start > end ) 912ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_INVALID_DATA; 913ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 914ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* this test should be performed at default validation level; */ 915ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* unfortunately, some popular Asian fonts have overlapping */ 916ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* ranges in their charmaps */ 917ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 918ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( start <= last_end && n > 0 ) 919ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 920ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( valid->level >= FT_VALIDATE_TIGHT ) 921ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_INVALID_DATA; 922ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else 923ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 924ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* allow overlapping segments, provided their start points */ 925ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* and end points, respectively, are in ascending order */ 926ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 927ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( last_start > start || last_end > end ) 928ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov error |= TT_CMAP_FLAG_UNSORTED; 929ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else 930ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov error |= TT_CMAP_FLAG_OVERLAPPING; 931ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 932ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 933ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 934ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( offset && offset != 0xFFFFU ) 935ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 936ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p += offset; /* start of glyph ID array */ 937ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 938ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* check that we point within the glyph IDs table only */ 939ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( valid->level >= FT_VALIDATE_TIGHT ) 940ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 941ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( p < glyph_ids || 942ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p + ( end - start + 1 ) * 2 > table + length ) 943ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_INVALID_DATA; 944ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 945ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* Some fonts handle the last segment incorrectly. In */ 946ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* theory, 0xFFFF might point to an ordinary glyph -- */ 947ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* a cmap 4 is versatile and could be used for any */ 948ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* encoding, not only Unicode. However, reality shows */ 949ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* that far too many fonts are sloppy and incorrectly */ 950ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* set all fields but `start' and `end' for the last */ 951ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* segment if it contains only a single character. */ 952ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 953ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* We thus omit the test here, delaying it to the */ 954ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* routines which actually access the cmap. */ 955ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else if ( n != num_segs - 1 || 956ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov !( start == 0xFFFFU && end == 0xFFFFU ) ) 957ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 958ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( p < glyph_ids || 959ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p + ( end - start + 1 ) * 2 > valid->limit ) 960ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_INVALID_DATA; 961ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 962ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 963ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* check glyph indices within the segment range */ 964ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( valid->level >= FT_VALIDATE_TIGHT ) 965ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 966ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt i, idx; 967ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 968ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 969ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( i = start; i < end; i++ ) 970ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 971ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov idx = FT_NEXT_USHORT( p ); 972ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( idx != 0 ) 973ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 974ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov idx = (FT_UInt)( idx + delta ) & 0xFFFFU; 975ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 976ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( idx >= TT_VALID_GLYPH_COUNT( valid ) ) 977ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_INVALID_GLYPH_ID; 978ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 979ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 980ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 981ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 982ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else if ( offset == 0xFFFFU ) 983ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 984ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* some fonts (erroneously?) use a range offset of 0xFFFF */ 985ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* to mean missing glyph in cmap table */ 986ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 987ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( valid->level >= FT_VALIDATE_PARANOID || 988ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov n != num_segs - 1 || 989ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov !( start == 0xFFFFU && end == 0xFFFFU ) ) 990ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_INVALID_DATA; 991ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 992ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 993ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov last_start = start; 994ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov last_end = end; 995ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 996ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 997ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 998ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return error; 999ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1000ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1001ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1002ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov static FT_UInt 1003ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tt_cmap4_char_map_linear( TT_CMap cmap, 1004ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt32* pcharcode, 1005ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Bool next ) 1006ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1007ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt num_segs2, start, end, offset; 1008ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Int delta; 1009ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt i, num_segs; 1010ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt32 charcode = *pcharcode; 1011ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt gindex = 0; 1012ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte* p; 1013ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1014ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1015ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p = cmap->data + 6; 1016ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov num_segs2 = FT_PAD_FLOOR( TT_PEEK_USHORT( p ), 2 ); 1017ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1018ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov num_segs = num_segs2 >> 1; 1019ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1020ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( !num_segs ) 1021ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return 0; 1022ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1023ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( next ) 1024ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov charcode++; 1025ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1026ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* linear search */ 1027ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( ; charcode <= 0xFFFFU; charcode++ ) 1028ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1029ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte* q; 1030ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1031ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1032ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p = cmap->data + 14; /* ends table */ 1033ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov q = cmap->data + 16 + num_segs2; /* starts table */ 1034ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1035ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( i = 0; i < num_segs; i++ ) 1036ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1037ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov end = TT_NEXT_USHORT( p ); 1038ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov start = TT_NEXT_USHORT( q ); 1039ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1040ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( charcode >= start && charcode <= end ) 1041ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1042ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p = q - 2 + num_segs2; 1043ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov delta = TT_PEEK_SHORT( p ); 1044ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p += num_segs2; 1045ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov offset = TT_PEEK_USHORT( p ); 1046ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1047ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* some fonts have an incorrect last segment; */ 1048ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* we have to catch it */ 1049ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( i >= num_segs - 1 && 1050ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov start == 0xFFFFU && end == 0xFFFFU ) 1051ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1052ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TT_Face face = (TT_Face)cmap->cmap.charmap.face; 1053ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte* limit = face->cmap_table + face->cmap_size; 1054ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1055ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1056ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( offset && p + offset + 2 > limit ) 1057ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1058ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov delta = 1; 1059ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov offset = 0; 1060ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1061ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1062ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1063ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( offset == 0xFFFFU ) 1064ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov continue; 1065ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1066ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( offset ) 1067ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1068ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p += offset + ( charcode - start ) * 2; 1069ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gindex = TT_PEEK_USHORT( p ); 1070ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( gindex != 0 ) 1071ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gindex = (FT_UInt)( gindex + delta ) & 0xFFFFU; 1072ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1073ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else 1074ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gindex = (FT_UInt)( charcode + delta ) & 0xFFFFU; 1075ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1076ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 1077ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1078ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1079ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1080ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( !next || gindex ) 1081ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 1082ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1083ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1084ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( next && gindex ) 1085ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov *pcharcode = charcode; 1086ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1087ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return gindex; 1088ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1089ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1090ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1091ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov static FT_UInt 1092ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tt_cmap4_char_map_binary( TT_CMap cmap, 1093ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt32* pcharcode, 1094ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Bool next ) 1095ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1096ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt num_segs2, start, end, offset; 1097ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Int delta; 1098ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt max, min, mid, num_segs; 1099ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt charcode = (FT_UInt)*pcharcode; 1100ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt gindex = 0; 1101ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte* p; 1102ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1103ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1104ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p = cmap->data + 6; 1105ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov num_segs2 = FT_PAD_FLOOR( TT_PEEK_USHORT( p ), 2 ); 1106ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1107ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( !num_segs2 ) 1108ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return 0; 1109ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1110ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov num_segs = num_segs2 >> 1; 1111ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1112ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* make compiler happy */ 1113ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov mid = num_segs; 1114ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov end = 0xFFFFU; 1115ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1116ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( next ) 1117ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov charcode++; 1118ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1119ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov min = 0; 1120ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov max = num_segs; 1121ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1122ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* binary search */ 1123ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov while ( min < max ) 1124ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1125ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov mid = ( min + max ) >> 1; 1126ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p = cmap->data + 14 + mid * 2; 1127ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov end = TT_PEEK_USHORT( p ); 1128ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p += 2 + num_segs2; 1129ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov start = TT_PEEK_USHORT( p ); 1130ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1131ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( charcode < start ) 1132ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov max = mid; 1133ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else if ( charcode > end ) 1134ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov min = mid + 1; 1135ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else 1136ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1137ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p += num_segs2; 1138ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov delta = TT_PEEK_SHORT( p ); 1139ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p += num_segs2; 1140ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov offset = TT_PEEK_USHORT( p ); 1141ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1142ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* some fonts have an incorrect last segment; */ 1143ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* we have to catch it */ 1144ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( mid >= num_segs - 1 && 1145ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov start == 0xFFFFU && end == 0xFFFFU ) 1146ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1147ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TT_Face face = (TT_Face)cmap->cmap.charmap.face; 1148ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte* limit = face->cmap_table + face->cmap_size; 1149ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1150ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1151ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( offset && p + offset + 2 > limit ) 1152ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1153ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov delta = 1; 1154ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov offset = 0; 1155ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1156ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1157ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1158ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* search the first segment containing `charcode' */ 1159ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( cmap->flags & TT_CMAP_FLAG_OVERLAPPING ) 1160ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1161ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt i; 1162ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1163ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1164ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* call the current segment `max' */ 1165ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov max = mid; 1166ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1167ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( offset == 0xFFFFU ) 1168ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov mid = max + 1; 1169ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1170ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* search in segments before the current segment */ 1171ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( i = max ; i > 0; i-- ) 1172ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1173ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt prev_end; 1174ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte* old_p; 1175ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1176ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1177ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov old_p = p; 1178ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p = cmap->data + 14 + ( i - 1 ) * 2; 1179ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov prev_end = TT_PEEK_USHORT( p ); 1180ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1181ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( charcode > prev_end ) 1182ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1183ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p = old_p; 1184ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 1185ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1186ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1187ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov end = prev_end; 1188ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p += 2 + num_segs2; 1189ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov start = TT_PEEK_USHORT( p ); 1190ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p += num_segs2; 1191ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov delta = TT_PEEK_SHORT( p ); 1192ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p += num_segs2; 1193ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov offset = TT_PEEK_USHORT( p ); 1194ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1195ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( offset != 0xFFFFU ) 1196ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov mid = i - 1; 1197ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1198ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1199ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* no luck */ 1200ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( mid == max + 1 ) 1201ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1202ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( i != max ) 1203ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1204ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p = cmap->data + 14 + max * 2; 1205ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov end = TT_PEEK_USHORT( p ); 1206ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p += 2 + num_segs2; 1207ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov start = TT_PEEK_USHORT( p ); 1208ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p += num_segs2; 1209ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov delta = TT_PEEK_SHORT( p ); 1210ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p += num_segs2; 1211ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov offset = TT_PEEK_USHORT( p ); 1212ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1213ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1214ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov mid = max; 1215ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1216ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* search in segments after the current segment */ 1217ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( i = max + 1; i < num_segs; i++ ) 1218ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1219ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt next_end, next_start; 1220ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1221ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1222ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p = cmap->data + 14 + i * 2; 1223ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov next_end = TT_PEEK_USHORT( p ); 1224ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p += 2 + num_segs2; 1225ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov next_start = TT_PEEK_USHORT( p ); 1226ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1227ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( charcode < next_start ) 1228ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 1229ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1230ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov end = next_end; 1231ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov start = next_start; 1232ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p += num_segs2; 1233ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov delta = TT_PEEK_SHORT( p ); 1234ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p += num_segs2; 1235ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov offset = TT_PEEK_USHORT( p ); 1236ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1237ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( offset != 0xFFFFU ) 1238ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov mid = i; 1239ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1240ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov i--; 1241ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1242ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* still no luck */ 1243ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( mid == max ) 1244ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1245ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov mid = i; 1246ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1247ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 1248ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1249ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1250ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1251ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* end, start, delta, and offset are for the i'th segment */ 1252ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( mid != i ) 1253ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1254ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p = cmap->data + 14 + mid * 2; 1255ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov end = TT_PEEK_USHORT( p ); 1256ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p += 2 + num_segs2; 1257ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov start = TT_PEEK_USHORT( p ); 1258ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p += num_segs2; 1259ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov delta = TT_PEEK_SHORT( p ); 1260ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p += num_segs2; 1261ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov offset = TT_PEEK_USHORT( p ); 1262ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1263ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1264ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else 1265ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1266ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( offset == 0xFFFFU ) 1267ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 1268ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1269ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1270ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( offset ) 1271ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1272ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p += offset + ( charcode - start ) * 2; 1273ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gindex = TT_PEEK_USHORT( p ); 1274ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( gindex != 0 ) 1275ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gindex = (FT_UInt)( gindex + delta ) & 0xFFFFU; 1276ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1277ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else 1278ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gindex = (FT_UInt)( charcode + delta ) & 0xFFFFU; 1279ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1280ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 1281ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1282ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1283ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1284ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( next ) 1285ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1286ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TT_CMap4 cmap4 = (TT_CMap4)cmap; 1287ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1288ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1289ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* if `charcode' is not in any segment, then `mid' is */ 1290ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* the segment nearest to `charcode' */ 1291ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 1292ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1293ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( charcode > end ) 1294ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1295ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov mid++; 1296ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( mid == num_segs ) 1297ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return 0; 1298ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1299ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1300ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( tt_cmap4_set_range( cmap4, mid ) ) 1301ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1302ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( gindex ) 1303ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov *pcharcode = charcode; 1304ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1305ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else 1306ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1307ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmap4->cur_charcode = charcode; 1308ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1309ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( gindex ) 1310ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmap4->cur_gindex = gindex; 1311ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else 1312ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1313ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmap4->cur_charcode = charcode; 1314ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tt_cmap4_next( cmap4 ); 1315ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gindex = cmap4->cur_gindex; 1316ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1317ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1318ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( gindex ) 1319ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov *pcharcode = cmap4->cur_charcode; 1320ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1321ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1322ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1323ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return gindex; 1324ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1325ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1326ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1327ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_CALLBACK_DEF( FT_UInt ) 1328ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tt_cmap4_char_index( TT_CMap cmap, 1329ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt32 char_code ) 1330ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1331ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( char_code >= 0x10000UL ) 1332ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return 0; 1333ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1334ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( cmap->flags & TT_CMAP_FLAG_UNSORTED ) 1335ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return tt_cmap4_char_map_linear( cmap, &char_code, 0 ); 1336ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else 1337ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return tt_cmap4_char_map_binary( cmap, &char_code, 0 ); 1338ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1339ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1340ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1341ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_CALLBACK_DEF( FT_UInt32 ) 1342ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tt_cmap4_char_next( TT_CMap cmap, 1343ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt32 *pchar_code ) 1344ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1345ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt gindex; 1346ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1347ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1348ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( *pchar_code >= 0xFFFFU ) 1349ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return 0; 1350ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1351ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( cmap->flags & TT_CMAP_FLAG_UNSORTED ) 1352ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gindex = tt_cmap4_char_map_linear( cmap, pchar_code, 1 ); 1353ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else 1354ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1355ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TT_CMap4 cmap4 = (TT_CMap4)cmap; 1356ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1357ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1358ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* no need to search */ 1359ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( *pchar_code == cmap4->cur_charcode ) 1360ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1361ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tt_cmap4_next( cmap4 ); 1362ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gindex = cmap4->cur_gindex; 1363ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( gindex ) 1364ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov *pchar_code = cmap4->cur_charcode; 1365ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1366ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else 1367ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gindex = tt_cmap4_char_map_binary( cmap, pchar_code, 1 ); 1368ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1369ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1370ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return gindex; 1371ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1372ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1373ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1374ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_CALLBACK_DEF( FT_Error ) 1375ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tt_cmap4_get_info( TT_CMap cmap, 1376ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TT_CMapInfo *cmap_info ) 1377ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1378ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte* p = cmap->data + 4; 1379ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1380ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1381ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmap_info->format = 4; 1382ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmap_info->language = (FT_ULong)TT_PEEK_USHORT( p ); 1383ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1384ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FT_Err_Ok; 1385ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1386ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1387ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1388ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_DEFINE_TT_CMAP( 1389ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tt_cmap4_class_rec, 1390ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov sizeof ( TT_CMap4Rec ), 1391ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (FT_CMap_InitFunc) tt_cmap4_init, 1392ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (FT_CMap_DoneFunc) NULL, 1393ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (FT_CMap_CharIndexFunc)tt_cmap4_char_index, 1394ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (FT_CMap_CharNextFunc) tt_cmap4_char_next, 1395ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1396ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov NULL, 1397ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov NULL, 1398ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov NULL, 1399ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov NULL, 1400ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov NULL, 1401ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1402ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 4, 1403ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (TT_CMap_ValidateFunc)tt_cmap4_validate, 1404ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (TT_CMap_Info_GetFunc)tt_cmap4_get_info ) 1405ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1406ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif /* TT_CONFIG_CMAP_FORMAT_4 */ 1407ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1408ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1409ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 1410ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 1411ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /***** *****/ 1412ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /***** FORMAT 6 *****/ 1413ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /***** *****/ 1414ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 1415ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 1416ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1417ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 1418ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 1419ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* TABLE OVERVIEW */ 1420ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* -------------- */ 1421ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 1422ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* NAME OFFSET TYPE DESCRIPTION */ 1423ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 1424ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* format 0 USHORT must be 4 */ 1425ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* length 2 USHORT table length in bytes */ 1426ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* language 4 USHORT Mac language code */ 1427ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 1428ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* first 6 USHORT first segment code */ 1429ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* count 8 USHORT segment size in chars */ 1430ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* glyphIds 10 USHORT[count] glyph IDs */ 1431ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 1432ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* A very simplified segment mapping. */ 1433ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 1434ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1435ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#ifdef TT_CONFIG_CMAP_FORMAT_6 1436ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1437ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_CALLBACK_DEF( FT_Error ) 1438ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tt_cmap6_validate( FT_Byte* table, 1439ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Validator valid ) 1440ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1441ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte* p; 1442ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt length, count; 1443ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1444ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1445ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( table + 10 > valid->limit ) 1446ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_INVALID_TOO_SHORT; 1447ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1448ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p = table + 2; 1449ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov length = TT_NEXT_USHORT( p ); 1450ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1451ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p = table + 8; /* skip language and start index */ 1452ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov count = TT_NEXT_USHORT( p ); 1453ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1454ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( table + length > valid->limit || length < 10 + count/* * 2 */) // Zhangxuefeng 2013.12.23. remove count multiply 2. 1455ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_INVALID_TOO_SHORT; 1456ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1457ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* check glyph indices */ 1458ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( valid->level >= FT_VALIDATE_TIGHT ) 1459ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1460ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt gindex; 1461ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1462ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1463ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( ; count > 0; count-- ) 1464ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1465ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gindex = TT_NEXT_USHORT( p ); 1466ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( gindex >= TT_VALID_GLYPH_COUNT( valid ) ) 1467ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_INVALID_GLYPH_ID; 1468ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1469ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1470ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1471ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FT_Err_Ok; 1472ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1473ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1474ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1475ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_CALLBACK_DEF( FT_UInt ) 1476ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tt_cmap6_char_index( TT_CMap cmap, 1477ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt32 char_code ) 1478ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1479ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte* table = cmap->data; 1480ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt result = 0; 1481ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte* p = table + 6; 1482ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt start = TT_NEXT_USHORT( p ); 1483ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt count = TT_NEXT_USHORT( p ); 1484ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt idx = (FT_UInt)( char_code - start ); 1485ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1486ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1487ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( idx < count ) 1488ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1489ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p += 2 * idx; 1490ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov result = TT_PEEK_USHORT( p ); 1491ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1492ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return result; 1493ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1494ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1495ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1496ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_CALLBACK_DEF( FT_UInt32 ) 1497ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tt_cmap6_char_next( TT_CMap cmap, 1498ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt32 *pchar_code ) 1499ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1500ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte* table = cmap->data; 1501ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt32 result = 0; 1502ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt32 char_code = *pchar_code + 1; 1503ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt gindex = 0; 1504ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1505ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte* p = table + 6; 1506ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt start = TT_NEXT_USHORT( p ); 1507ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt count = TT_NEXT_USHORT( p ); 1508ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt idx; 1509ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1510ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1511ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( char_code >= 0x10000UL ) 1512ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Exit; 1513ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1514ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( char_code < start ) 1515ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov char_code = start; 1516ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1517ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov idx = (FT_UInt)( char_code - start ); 1518ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p += 2 * idx; 1519ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1520ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( ; idx < count; idx++ ) 1521ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1522ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gindex = TT_NEXT_USHORT( p ); 1523ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( gindex != 0 ) 1524ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1525ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov result = char_code; 1526ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 1527ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1528ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov char_code++; 1529ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1530ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1531ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Exit: 1532ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov *pchar_code = result; 1533ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return gindex; 1534ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1535ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1536ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1537ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_CALLBACK_DEF( FT_Error ) 1538ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tt_cmap6_get_info( TT_CMap cmap, 1539ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TT_CMapInfo *cmap_info ) 1540ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1541ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte* p = cmap->data + 4; 1542ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1543ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1544ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmap_info->format = 6; 1545ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmap_info->language = (FT_ULong)TT_PEEK_USHORT( p ); 1546ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1547ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FT_Err_Ok; 1548ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1549ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1550ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1551ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_DEFINE_TT_CMAP( 1552ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tt_cmap6_class_rec, 1553ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov sizeof ( TT_CMapRec ), 1554ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1555ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (FT_CMap_InitFunc) tt_cmap_init, 1556ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (FT_CMap_DoneFunc) NULL, 1557ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (FT_CMap_CharIndexFunc)tt_cmap6_char_index, 1558ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (FT_CMap_CharNextFunc) tt_cmap6_char_next, 1559ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1560ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov NULL, 1561ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov NULL, 1562ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov NULL, 1563ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov NULL, 1564ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov NULL, 1565ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1566ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 6, 1567ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (TT_CMap_ValidateFunc)tt_cmap6_validate, 1568ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (TT_CMap_Info_GetFunc)tt_cmap6_get_info ) 1569ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1570ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif /* TT_CONFIG_CMAP_FORMAT_6 */ 1571ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1572ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1573ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 1574ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 1575ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /***** *****/ 1576ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /***** FORMAT 8 *****/ 1577ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /***** *****/ 1578ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /***** It is hard to completely understand what the OpenType spec *****/ 1579ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /***** says about this format, but here is my conclusion. *****/ 1580ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /***** *****/ 1581ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /***** The purpose of this format is to easily map UTF-16 text to *****/ 1582ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /***** glyph indices. Basically, the `char_code' must be in one of *****/ 1583ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /***** the following formats: *****/ 1584ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /***** *****/ 1585ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /***** - A 16-bit value that isn't part of the Unicode Surrogates *****/ 1586ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /***** Area (i.e. U+D800-U+DFFF). *****/ 1587ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /***** *****/ 1588ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /***** - A 32-bit value, made of two surrogate values, i.e.. if *****/ 1589ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /***** `char_code = (char_hi << 16) | char_lo', then both *****/ 1590ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /***** `char_hi' and `char_lo' must be in the Surrogates Area. *****/ 1591ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /***** Area. *****/ 1592ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /***** *****/ 1593ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /***** The `is32' table embedded in the charmap indicates whether a *****/ 1594ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /***** given 16-bit value is in the surrogates area or not. *****/ 1595ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /***** *****/ 1596ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /***** So, for any given `char_code', we can assert the following: *****/ 1597ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /***** *****/ 1598ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /***** If `char_hi == 0' then we must have `is32[char_lo] == 0'. *****/ 1599ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /***** *****/ 1600ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /***** If `char_hi != 0' then we must have both *****/ 1601ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /***** `is32[char_hi] != 0' and `is32[char_lo] != 0'. *****/ 1602ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /***** *****/ 1603ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 1604ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 1605ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1606ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 1607ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 1608ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* TABLE OVERVIEW */ 1609ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* -------------- */ 1610ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 1611ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* NAME OFFSET TYPE DESCRIPTION */ 1612ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 1613ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* format 0 USHORT must be 8 */ 1614ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* reserved 2 USHORT reserved */ 1615ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* length 4 ULONG length in bytes */ 1616ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* language 8 ULONG Mac language code */ 1617ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* is32 12 BYTE[8192] 32-bitness bitmap */ 1618ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* count 8204 ULONG number of groups */ 1619ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 1620ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* This header is followed by `count' groups of the following format: */ 1621ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 1622ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* start 0 ULONG first charcode */ 1623ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* end 4 ULONG last charcode */ 1624ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* startId 8 ULONG start glyph ID for the group */ 1625ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 1626ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1627ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#ifdef TT_CONFIG_CMAP_FORMAT_8 1628ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1629ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_CALLBACK_DEF( FT_Error ) 1630ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tt_cmap8_validate( FT_Byte* table, 1631ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Validator valid ) 1632ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1633ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte* p = table + 4; 1634ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte* is32; 1635ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt32 length; 1636ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt32 num_groups; 1637ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1638ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1639ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( table + 16 + 8192 > valid->limit ) 1640ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_INVALID_TOO_SHORT; 1641ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1642ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov length = TT_NEXT_ULONG( p ); 1643ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( length > (FT_UInt32)( valid->limit - table ) || length < 8192 + 16 ) 1644ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_INVALID_TOO_SHORT; 1645ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1646ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov is32 = table + 12; 1647ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p = is32 + 8192; /* skip `is32' array */ 1648ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov num_groups = TT_NEXT_ULONG( p ); 1649ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1650ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( p + num_groups * 12 > valid->limit ) 1651ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_INVALID_TOO_SHORT; 1652ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1653ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* check groups, they must be in increasing order */ 1654ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1655ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt32 n, start, end, start_id, count, last = 0; 1656ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1657ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1658ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( n = 0; n < num_groups; n++ ) 1659ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1660ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt hi, lo; 1661ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1662ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1663ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov start = TT_NEXT_ULONG( p ); 1664ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov end = TT_NEXT_ULONG( p ); 1665ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov start_id = TT_NEXT_ULONG( p ); 1666ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1667ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( start > end ) 1668ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_INVALID_DATA; 1669ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1670ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( n > 0 && start <= last ) 1671ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_INVALID_DATA; 1672ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1673ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( valid->level >= FT_VALIDATE_TIGHT ) 1674ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1675ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( start_id + end - start >= TT_VALID_GLYPH_COUNT( valid ) ) 1676ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_INVALID_GLYPH_ID; 1677ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1678ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov count = (FT_UInt32)( end - start + 1 ); 1679ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1680ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( start & ~0xFFFFU ) 1681ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1682ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* start_hi != 0; check that is32[i] is 1 for each i in */ 1683ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* the `hi' and `lo' of the range [start..end] */ 1684ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( ; count > 0; count--, start++ ) 1685ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1686ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov hi = (FT_UInt)( start >> 16 ); 1687ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov lo = (FT_UInt)( start & 0xFFFFU ); 1688ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1689ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( (is32[hi >> 3] & ( 0x80 >> ( hi & 7 ) ) ) == 0 ) 1690ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_INVALID_DATA; 1691ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1692ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( (is32[lo >> 3] & ( 0x80 >> ( lo & 7 ) ) ) == 0 ) 1693ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_INVALID_DATA; 1694ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1695ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1696ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else 1697ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1698ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* start_hi == 0; check that is32[i] is 0 for each i in */ 1699ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* the range [start..end] */ 1700ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1701ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* end_hi cannot be != 0! */ 1702ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( end & ~0xFFFFU ) 1703ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_INVALID_DATA; 1704ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1705ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( ; count > 0; count--, start++ ) 1706ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1707ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov lo = (FT_UInt)( start & 0xFFFFU ); 1708ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1709ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( (is32[lo >> 3] & ( 0x80 >> ( lo & 7 ) ) ) != 0 ) 1710ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_INVALID_DATA; 1711ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1712ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1713ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1714ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1715ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov last = end; 1716ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1717ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1718ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1719ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FT_Err_Ok; 1720ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1721ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1722ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1723ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_CALLBACK_DEF( FT_UInt ) 1724ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tt_cmap8_char_index( TT_CMap cmap, 1725ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt32 char_code ) 1726ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1727ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte* table = cmap->data; 1728ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt result = 0; 1729ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte* p = table + 8204; 1730ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt32 num_groups = TT_NEXT_ULONG( p ); 1731ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt32 start, end, start_id; 1732ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1733ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1734ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( ; num_groups > 0; num_groups-- ) 1735ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1736ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov start = TT_NEXT_ULONG( p ); 1737ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov end = TT_NEXT_ULONG( p ); 1738ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov start_id = TT_NEXT_ULONG( p ); 1739ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1740ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( char_code < start ) 1741ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 1742ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1743ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( char_code <= end ) 1744ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1745ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov result = (FT_UInt)( start_id + char_code - start ); 1746ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 1747ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1748ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1749ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return result; 1750ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1751ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1752ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1753ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_CALLBACK_DEF( FT_UInt32 ) 1754ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tt_cmap8_char_next( TT_CMap cmap, 1755ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt32 *pchar_code ) 1756ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1757ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt32 result = 0; 1758ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt32 char_code = *pchar_code + 1; 1759ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt gindex = 0; 1760ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte* table = cmap->data; 1761ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte* p = table + 8204; 1762ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt32 num_groups = TT_NEXT_ULONG( p ); 1763ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt32 start, end, start_id; 1764ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1765ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1766ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p = table + 8208; 1767ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1768ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( ; num_groups > 0; num_groups-- ) 1769ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1770ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov start = TT_NEXT_ULONG( p ); 1771ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov end = TT_NEXT_ULONG( p ); 1772ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov start_id = TT_NEXT_ULONG( p ); 1773ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1774ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( char_code < start ) 1775ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov char_code = start; 1776ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1777ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( char_code <= end ) 1778ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1779ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gindex = (FT_UInt)( char_code - start + start_id ); 1780ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( gindex != 0 ) 1781ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1782ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov result = char_code; 1783ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Exit; 1784ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1785ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1786ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1787ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1788ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Exit: 1789ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov *pchar_code = result; 1790ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return gindex; 1791ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1792ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1793ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1794ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_CALLBACK_DEF( FT_Error ) 1795ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tt_cmap8_get_info( TT_CMap cmap, 1796ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TT_CMapInfo *cmap_info ) 1797ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1798ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte* p = cmap->data + 8; 1799ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1800ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1801ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmap_info->format = 8; 1802ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmap_info->language = (FT_ULong)TT_PEEK_ULONG( p ); 1803ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1804ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FT_Err_Ok; 1805ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1806ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1807ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1808ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_DEFINE_TT_CMAP( 1809ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tt_cmap8_class_rec, 1810ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov sizeof ( TT_CMapRec ), 1811ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1812ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (FT_CMap_InitFunc) tt_cmap_init, 1813ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (FT_CMap_DoneFunc) NULL, 1814ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (FT_CMap_CharIndexFunc)tt_cmap8_char_index, 1815ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (FT_CMap_CharNextFunc) tt_cmap8_char_next, 1816ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1817ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov NULL, 1818ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov NULL, 1819ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov NULL, 1820ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov NULL, 1821ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov NULL, 1822ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1823ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 8, 1824ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (TT_CMap_ValidateFunc)tt_cmap8_validate, 1825ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (TT_CMap_Info_GetFunc)tt_cmap8_get_info ) 1826ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1827ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif /* TT_CONFIG_CMAP_FORMAT_8 */ 1828ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1829ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1830ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 1831ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 1832ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /***** *****/ 1833ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /***** FORMAT 10 *****/ 1834ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /***** *****/ 1835ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 1836ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 1837ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1838ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 1839ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 1840ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* TABLE OVERVIEW */ 1841ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* -------------- */ 1842ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 1843ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* NAME OFFSET TYPE DESCRIPTION */ 1844ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 1845ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* format 0 USHORT must be 10 */ 1846ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* reserved 2 USHORT reserved */ 1847ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* length 4 ULONG length in bytes */ 1848ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* language 8 ULONG Mac language code */ 1849ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 1850ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* start 12 ULONG first char in range */ 1851ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* count 16 ULONG number of chars in range */ 1852ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* glyphIds 20 USHORT[count] glyph indices covered */ 1853ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 1854ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1855ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#ifdef TT_CONFIG_CMAP_FORMAT_10 1856ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1857ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_CALLBACK_DEF( FT_Error ) 1858ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tt_cmap10_validate( FT_Byte* table, 1859ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Validator valid ) 1860ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1861ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte* p = table + 4; 1862ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_ULong length, count; 1863ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1864ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1865ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( table + 20 > valid->limit ) 1866ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_INVALID_TOO_SHORT; 1867ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1868ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov length = TT_NEXT_ULONG( p ); 1869ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p = table + 16; 1870ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov count = TT_NEXT_ULONG( p ); 1871ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1872ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( length > (FT_ULong)( valid->limit - table ) || 1873ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov length < 20 + count * 2 ) 1874ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_INVALID_TOO_SHORT; 1875ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1876ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* check glyph indices */ 1877ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( valid->level >= FT_VALIDATE_TIGHT ) 1878ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1879ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt gindex; 1880ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1881ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1882ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( ; count > 0; count-- ) 1883ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1884ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gindex = TT_NEXT_USHORT( p ); 1885ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( gindex >= TT_VALID_GLYPH_COUNT( valid ) ) 1886ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_INVALID_GLYPH_ID; 1887ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1888ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1889ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1890ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FT_Err_Ok; 1891ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1892ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1893ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1894ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_CALLBACK_DEF( FT_UInt ) 1895ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tt_cmap10_char_index( TT_CMap cmap, 1896ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt32 char_code ) 1897ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1898ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte* table = cmap->data; 1899ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt result = 0; 1900ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte* p = table + 12; 1901ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt32 start = TT_NEXT_ULONG( p ); 1902ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt32 count = TT_NEXT_ULONG( p ); 1903ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt32 idx = (FT_ULong)( char_code - start ); 1904ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1905ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1906ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( idx < count ) 1907ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1908ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p += 2 * idx; 1909ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov result = TT_PEEK_USHORT( p ); 1910ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1911ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return result; 1912ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1913ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1914ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1915ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_CALLBACK_DEF( FT_UInt32 ) 1916ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tt_cmap10_char_next( TT_CMap cmap, 1917ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt32 *pchar_code ) 1918ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1919ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte* table = cmap->data; 1920ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt32 char_code = *pchar_code + 1; 1921ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt gindex = 0; 1922ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte* p = table + 12; 1923ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt32 start = TT_NEXT_ULONG( p ); 1924ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt32 count = TT_NEXT_ULONG( p ); 1925ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt32 idx; 1926ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1927ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1928ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( char_code < start ) 1929ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov char_code = start; 1930ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1931ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov idx = (FT_UInt32)( char_code - start ); 1932ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p += 2 * idx; 1933ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1934ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( ; idx < count; idx++ ) 1935ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1936ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gindex = TT_NEXT_USHORT( p ); 1937ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( gindex != 0 ) 1938ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 1939ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov char_code++; 1940ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1941ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1942ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov *pchar_code = char_code; 1943ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return gindex; 1944ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1945ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1946ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1947ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_CALLBACK_DEF( FT_Error ) 1948ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tt_cmap10_get_info( TT_CMap cmap, 1949ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TT_CMapInfo *cmap_info ) 1950ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1951ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte* p = cmap->data + 8; 1952ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1953ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1954ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmap_info->format = 10; 1955ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmap_info->language = (FT_ULong)TT_PEEK_ULONG( p ); 1956ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1957ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FT_Err_Ok; 1958ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1959ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1960ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1961ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_DEFINE_TT_CMAP( 1962ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tt_cmap10_class_rec, 1963ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov sizeof ( TT_CMapRec ), 1964ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1965ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (FT_CMap_InitFunc) tt_cmap_init, 1966ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (FT_CMap_DoneFunc) NULL, 1967ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (FT_CMap_CharIndexFunc)tt_cmap10_char_index, 1968ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (FT_CMap_CharNextFunc) tt_cmap10_char_next, 1969ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1970ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov NULL, 1971ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov NULL, 1972ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov NULL, 1973ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov NULL, 1974ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov NULL, 1975ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1976ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 10, 1977ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (TT_CMap_ValidateFunc)tt_cmap10_validate, 1978ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (TT_CMap_Info_GetFunc)tt_cmap10_get_info ) 1979ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1980ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif /* TT_CONFIG_CMAP_FORMAT_10 */ 1981ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1982ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1983ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 1984ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 1985ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /***** *****/ 1986ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /***** FORMAT 12 *****/ 1987ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /***** *****/ 1988ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 1989ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 1990ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1991ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 1992ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 1993ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* TABLE OVERVIEW */ 1994ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* -------------- */ 1995ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 1996ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* NAME OFFSET TYPE DESCRIPTION */ 1997ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 1998ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* format 0 USHORT must be 12 */ 1999ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* reserved 2 USHORT reserved */ 2000ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* length 4 ULONG length in bytes */ 2001ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* language 8 ULONG Mac language code */ 2002ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* count 12 ULONG number of groups */ 2003ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* 16 */ 2004ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 2005ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* This header is followed by `count' groups of the following format: */ 2006ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 2007ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* start 0 ULONG first charcode */ 2008ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* end 4 ULONG last charcode */ 2009ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* startId 8 ULONG start glyph ID for the group */ 2010ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 2011ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2012ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#ifdef TT_CONFIG_CMAP_FORMAT_12 2013ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2014ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov typedef struct TT_CMap12Rec_ 2015ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2016ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TT_CMapRec cmap; 2017ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Bool valid; 2018ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_ULong cur_charcode; 2019ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt cur_gindex; 2020ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_ULong cur_group; 2021ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_ULong num_groups; 2022ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2023ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } TT_CMap12Rec, *TT_CMap12; 2024ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2025ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2026ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_CALLBACK_DEF( FT_Error ) 2027ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tt_cmap12_init( TT_CMap12 cmap, 2028ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte* table ) 2029ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2030ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmap->cmap.data = table; 2031ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2032ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov table += 12; 2033ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmap->num_groups = FT_PEEK_ULONG( table ); 2034ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2035ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmap->valid = 0; 2036ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2037ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FT_Err_Ok; 2038ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2039ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2040ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2041ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_CALLBACK_DEF( FT_Error ) 2042ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tt_cmap12_validate( FT_Byte* table, 2043ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Validator valid ) 2044ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2045ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte* p; 2046ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_ULong length; 2047ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_ULong num_groups; 2048ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2049ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2050ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( table + 16 > valid->limit ) 2051ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_INVALID_TOO_SHORT; 2052ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2053ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p = table + 4; 2054ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov length = TT_NEXT_ULONG( p ); 2055ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2056ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p = table + 12; 2057ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov num_groups = TT_NEXT_ULONG( p ); 2058ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2059ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( length > (FT_ULong)( valid->limit - table ) || 2060ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov length < 16 + 12 * num_groups ) 2061ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_INVALID_TOO_SHORT; 2062ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2063ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* check groups, they must be in increasing order */ 2064ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2065ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_ULong n, start, end, start_id, last = 0; 2066ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2067ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2068ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( n = 0; n < num_groups; n++ ) 2069ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2070ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov start = TT_NEXT_ULONG( p ); 2071ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov end = TT_NEXT_ULONG( p ); 2072ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov start_id = TT_NEXT_ULONG( p ); 2073ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2074ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( start > end ) 2075ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_INVALID_DATA; 2076ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2077ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( n > 0 && start <= last ) 2078ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_INVALID_DATA; 2079ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2080ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( valid->level >= FT_VALIDATE_TIGHT ) 2081ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2082ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( start_id + end - start >= TT_VALID_GLYPH_COUNT( valid ) ) 2083ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_INVALID_GLYPH_ID; 2084ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2085ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2086ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov last = end; 2087ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2088ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2089ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2090ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FT_Err_Ok; 2091ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2092ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2093ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2094ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* search the index of the charcode next to cmap->cur_charcode */ 2095ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* cmap->cur_group should be set up properly by caller */ 2096ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 2097ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov static void 2098ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tt_cmap12_next( TT_CMap12 cmap ) 2099ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2100ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte* p; 2101ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_ULong start, end, start_id, char_code; 2102ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_ULong n; 2103ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt gindex; 2104ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2105ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2106ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( cmap->cur_charcode >= 0xFFFFFFFFUL ) 2107ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Fail; 2108ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2109ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov char_code = cmap->cur_charcode + 1; 2110ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2111ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov n = cmap->cur_group; 2112ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2113ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( n = cmap->cur_group; n < cmap->num_groups; n++ ) 2114ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2115ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p = cmap->cmap.data + 16 + 12 * n; 2116ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov start = TT_NEXT_ULONG( p ); 2117ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov end = TT_NEXT_ULONG( p ); 2118ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov start_id = TT_PEEK_ULONG( p ); 2119ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2120ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( char_code < start ) 2121ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov char_code = start; 2122ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2123ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( ; char_code <= end; char_code++ ) 2124ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2125ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gindex = (FT_UInt)( start_id + char_code - start ); 2126ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2127ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( gindex ) 2128ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2129ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmap->cur_charcode = char_code;; 2130ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmap->cur_gindex = gindex; 2131ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmap->cur_group = n; 2132ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2133ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return; 2134ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2135ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2136ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2137ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2138ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Fail: 2139ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmap->valid = 0; 2140ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2141ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2142ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2143ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov static FT_UInt 2144ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tt_cmap12_char_map_binary( TT_CMap cmap, 2145ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt32* pchar_code, 2146ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Bool next ) 2147ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2148ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt gindex = 0; 2149ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte* p = cmap->data + 12; 2150ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt32 num_groups = TT_PEEK_ULONG( p ); 2151ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt32 char_code = *pchar_code; 2152ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt32 start, end, start_id; 2153ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt32 max, min, mid; 2154ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2155ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2156ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( !num_groups ) 2157ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return 0; 2158ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2159ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* make compiler happy */ 2160ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov mid = num_groups; 2161ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov end = 0xFFFFFFFFUL; 2162ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2163ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( next ) 2164ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov char_code++; 2165ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2166ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov min = 0; 2167ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov max = num_groups; 2168ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2169ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* binary search */ 2170ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov while ( min < max ) 2171ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2172ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov mid = ( min + max ) >> 1; 2173ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p = cmap->data + 16 + 12 * mid; 2174ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2175ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov start = TT_NEXT_ULONG( p ); 2176ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov end = TT_NEXT_ULONG( p ); 2177ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2178ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( char_code < start ) 2179ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov max = mid; 2180ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else if ( char_code > end ) 2181ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov min = mid + 1; 2182ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else 2183ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2184ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov start_id = TT_PEEK_ULONG( p ); 2185ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gindex = (FT_UInt)( start_id + char_code - start ); 2186ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2187ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 2188ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2189ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2190ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2191ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( next ) 2192ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2193ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TT_CMap12 cmap12 = (TT_CMap12)cmap; 2194ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2195ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2196ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* if `char_code' is not in any group, then `mid' is */ 2197ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* the group nearest to `char_code' */ 2198ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 2199ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2200ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( char_code > end ) 2201ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2202ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov mid++; 2203ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( mid == num_groups ) 2204ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return 0; 2205ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2206ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2207ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmap12->valid = 1; 2208ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmap12->cur_charcode = char_code; 2209ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmap12->cur_group = mid; 2210ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2211ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( !gindex ) 2212ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2213ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tt_cmap12_next( cmap12 ); 2214ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2215ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( cmap12->valid ) 2216ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gindex = cmap12->cur_gindex; 2217ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2218ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else 2219ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmap12->cur_gindex = gindex; 2220ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2221ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( gindex ) 2222ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov *pchar_code = cmap12->cur_charcode; 2223ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2224ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2225ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return gindex; 2226ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2227ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2228ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2229ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_CALLBACK_DEF( FT_UInt ) 2230ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tt_cmap12_char_index( TT_CMap cmap, 2231ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt32 char_code ) 2232ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2233ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return tt_cmap12_char_map_binary( cmap, &char_code, 0 ); 2234ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2235ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2236ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2237ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_CALLBACK_DEF( FT_UInt32 ) 2238ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tt_cmap12_char_next( TT_CMap cmap, 2239ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt32 *pchar_code ) 2240ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2241ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TT_CMap12 cmap12 = (TT_CMap12)cmap; 2242ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_ULong gindex; 2243ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2244ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2245ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( cmap12->cur_charcode >= 0xFFFFFFFFUL ) 2246ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return 0; 2247ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2248ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* no need to search */ 2249ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( cmap12->valid && cmap12->cur_charcode == *pchar_code ) 2250ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2251ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tt_cmap12_next( cmap12 ); 2252ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( cmap12->valid ) 2253ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2254ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gindex = cmap12->cur_gindex; 2255ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2256ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* XXX: check cur_charcode overflow is expected */ 2257ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( gindex ) 2258ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov *pchar_code = (FT_UInt32)cmap12->cur_charcode; 2259ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2260ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else 2261ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gindex = 0; 2262ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2263ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else 2264ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gindex = tt_cmap12_char_map_binary( cmap, pchar_code, 1 ); 2265ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2266ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* XXX: check gindex overflow is expected */ 2267ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return (FT_UInt32)gindex; 2268ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2269ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2270ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2271ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_CALLBACK_DEF( FT_Error ) 2272ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tt_cmap12_get_info( TT_CMap cmap, 2273ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TT_CMapInfo *cmap_info ) 2274ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2275ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte* p = cmap->data + 8; 2276ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2277ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2278ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmap_info->format = 12; 2279ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmap_info->language = (FT_ULong)TT_PEEK_ULONG( p ); 2280ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2281ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FT_Err_Ok; 2282ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2283ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2284ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2285ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_DEFINE_TT_CMAP( 2286ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tt_cmap12_class_rec, 2287ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov sizeof ( TT_CMap12Rec ), 2288ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2289ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (FT_CMap_InitFunc) tt_cmap12_init, 2290ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (FT_CMap_DoneFunc) NULL, 2291ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (FT_CMap_CharIndexFunc)tt_cmap12_char_index, 2292ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (FT_CMap_CharNextFunc) tt_cmap12_char_next, 2293ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2294ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov NULL, 2295ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov NULL, 2296ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov NULL, 2297ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov NULL, 2298ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov NULL, 2299ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2300ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 12, 2301ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (TT_CMap_ValidateFunc)tt_cmap12_validate, 2302ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (TT_CMap_Info_GetFunc)tt_cmap12_get_info ) 2303ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2304ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif /* TT_CONFIG_CMAP_FORMAT_12 */ 2305ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2306ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2307ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 2308ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 2309ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /***** *****/ 2310ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /***** FORMAT 13 *****/ 2311ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /***** *****/ 2312ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 2313ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 2314ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2315ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 2316ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 2317ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* TABLE OVERVIEW */ 2318ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* -------------- */ 2319ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 2320ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* NAME OFFSET TYPE DESCRIPTION */ 2321ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 2322ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* format 0 USHORT must be 13 */ 2323ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* reserved 2 USHORT reserved */ 2324ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* length 4 ULONG length in bytes */ 2325ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* language 8 ULONG Mac language code */ 2326ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* count 12 ULONG number of groups */ 2327ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* 16 */ 2328ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 2329ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* This header is followed by `count' groups of the following format: */ 2330ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 2331ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* start 0 ULONG first charcode */ 2332ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* end 4 ULONG last charcode */ 2333ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* glyphId 8 ULONG glyph ID for the whole group */ 2334ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 2335ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2336ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#ifdef TT_CONFIG_CMAP_FORMAT_13 2337ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2338ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov typedef struct TT_CMap13Rec_ 2339ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2340ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TT_CMapRec cmap; 2341ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Bool valid; 2342ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_ULong cur_charcode; 2343ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt cur_gindex; 2344ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_ULong cur_group; 2345ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_ULong num_groups; 2346ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2347ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } TT_CMap13Rec, *TT_CMap13; 2348ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2349ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2350ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_CALLBACK_DEF( FT_Error ) 2351ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tt_cmap13_init( TT_CMap13 cmap, 2352ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte* table ) 2353ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2354ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmap->cmap.data = table; 2355ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2356ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov table += 12; 2357ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmap->num_groups = FT_PEEK_ULONG( table ); 2358ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2359ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmap->valid = 0; 2360ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2361ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FT_Err_Ok; 2362ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2363ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2364ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2365ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_CALLBACK_DEF( FT_Error ) 2366ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tt_cmap13_validate( FT_Byte* table, 2367ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Validator valid ) 2368ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2369ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte* p; 2370ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_ULong length; 2371ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_ULong num_groups; 2372ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2373ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2374ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( table + 16 > valid->limit ) 2375ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_INVALID_TOO_SHORT; 2376ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2377ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p = table + 4; 2378ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov length = TT_NEXT_ULONG( p ); 2379ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2380ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p = table + 12; 2381ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov num_groups = TT_NEXT_ULONG( p ); 2382ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2383ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( length > (FT_ULong)( valid->limit - table ) || 2384ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov length < 16 + 12 * num_groups ) 2385ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_INVALID_TOO_SHORT; 2386ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2387ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* check groups, they must be in increasing order */ 2388ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2389ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_ULong n, start, end, glyph_id, last = 0; 2390ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2391ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2392ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( n = 0; n < num_groups; n++ ) 2393ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2394ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov start = TT_NEXT_ULONG( p ); 2395ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov end = TT_NEXT_ULONG( p ); 2396ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov glyph_id = TT_NEXT_ULONG( p ); 2397ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2398ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( start > end ) 2399ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_INVALID_DATA; 2400ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2401ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( n > 0 && start <= last ) 2402ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_INVALID_DATA; 2403ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2404ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( valid->level >= FT_VALIDATE_TIGHT ) 2405ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2406ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( glyph_id >= TT_VALID_GLYPH_COUNT( valid ) ) 2407ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_INVALID_GLYPH_ID; 2408ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2409ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2410ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov last = end; 2411ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2412ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2413ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2414ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FT_Err_Ok; 2415ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2416ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2417ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2418ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* search the index of the charcode next to cmap->cur_charcode */ 2419ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* cmap->cur_group should be set up properly by caller */ 2420ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 2421ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov static void 2422ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tt_cmap13_next( TT_CMap13 cmap ) 2423ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2424ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte* p; 2425ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_ULong start, end, glyph_id, char_code; 2426ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_ULong n; 2427ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt gindex; 2428ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2429ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2430ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( cmap->cur_charcode >= 0xFFFFFFFFUL ) 2431ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Fail; 2432ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2433ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov char_code = cmap->cur_charcode + 1; 2434ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2435ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov n = cmap->cur_group; 2436ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2437ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( n = cmap->cur_group; n < cmap->num_groups; n++ ) 2438ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2439ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p = cmap->cmap.data + 16 + 12 * n; 2440ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov start = TT_NEXT_ULONG( p ); 2441ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov end = TT_NEXT_ULONG( p ); 2442ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov glyph_id = TT_PEEK_ULONG( p ); 2443ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2444ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( char_code < start ) 2445ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov char_code = start; 2446ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2447ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( char_code <= end ) 2448ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2449ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gindex = (FT_UInt)glyph_id; 2450ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2451ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( gindex ) 2452ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2453ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmap->cur_charcode = char_code;; 2454ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmap->cur_gindex = gindex; 2455ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmap->cur_group = n; 2456ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2457ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return; 2458ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2459ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2460ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2461ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2462ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Fail: 2463ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmap->valid = 0; 2464ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2465ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2466ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2467ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov static FT_UInt 2468ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tt_cmap13_char_map_binary( TT_CMap cmap, 2469ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt32* pchar_code, 2470ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Bool next ) 2471ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2472ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt gindex = 0; 2473ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte* p = cmap->data + 12; 2474ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt32 num_groups = TT_PEEK_ULONG( p ); 2475ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt32 char_code = *pchar_code; 2476ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt32 start, end; 2477ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt32 max, min, mid; 2478ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2479ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2480ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( !num_groups ) 2481ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return 0; 2482ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2483ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* make compiler happy */ 2484ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov mid = num_groups; 2485ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov end = 0xFFFFFFFFUL; 2486ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2487ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( next ) 2488ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov char_code++; 2489ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2490ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov min = 0; 2491ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov max = num_groups; 2492ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2493ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* binary search */ 2494ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov while ( min < max ) 2495ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2496ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov mid = ( min + max ) >> 1; 2497ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p = cmap->data + 16 + 12 * mid; 2498ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2499ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov start = TT_NEXT_ULONG( p ); 2500ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov end = TT_NEXT_ULONG( p ); 2501ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2502ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( char_code < start ) 2503ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov max = mid; 2504ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else if ( char_code > end ) 2505ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov min = mid + 1; 2506ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else 2507ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2508ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gindex = (FT_UInt)TT_PEEK_ULONG( p ); 2509ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2510ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 2511ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2512ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2513ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2514ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( next ) 2515ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2516ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TT_CMap13 cmap13 = (TT_CMap13)cmap; 2517ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2518ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2519ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* if `char_code' is not in any group, then `mid' is */ 2520ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* the group nearest to `char_code' */ 2521ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2522ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( char_code > end ) 2523ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2524ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov mid++; 2525ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( mid == num_groups ) 2526ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return 0; 2527ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2528ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2529ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmap13->valid = 1; 2530ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmap13->cur_charcode = char_code; 2531ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmap13->cur_group = mid; 2532ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2533ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( !gindex ) 2534ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2535ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tt_cmap13_next( cmap13 ); 2536ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2537ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( cmap13->valid ) 2538ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gindex = cmap13->cur_gindex; 2539ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2540ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else 2541ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmap13->cur_gindex = gindex; 2542ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2543ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( gindex ) 2544ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov *pchar_code = cmap13->cur_charcode; 2545ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2546ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2547ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return gindex; 2548ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2549ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2550ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2551ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_CALLBACK_DEF( FT_UInt ) 2552ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tt_cmap13_char_index( TT_CMap cmap, 2553ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt32 char_code ) 2554ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2555ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return tt_cmap13_char_map_binary( cmap, &char_code, 0 ); 2556ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2557ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2558ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2559ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_CALLBACK_DEF( FT_UInt32 ) 2560ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tt_cmap13_char_next( TT_CMap cmap, 2561ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt32 *pchar_code ) 2562ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2563ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TT_CMap13 cmap13 = (TT_CMap13)cmap; 2564ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt gindex; 2565ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2566ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2567ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( cmap13->cur_charcode >= 0xFFFFFFFFUL ) 2568ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return 0; 2569ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2570ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* no need to search */ 2571ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( cmap13->valid && cmap13->cur_charcode == *pchar_code ) 2572ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2573ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tt_cmap13_next( cmap13 ); 2574ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( cmap13->valid ) 2575ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2576ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gindex = cmap13->cur_gindex; 2577ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( gindex ) 2578ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov *pchar_code = cmap13->cur_charcode; 2579ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2580ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else 2581ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gindex = 0; 2582ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2583ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else 2584ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gindex = tt_cmap13_char_map_binary( cmap, pchar_code, 1 ); 2585ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2586ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return gindex; 2587ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2588ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2589ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2590ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_CALLBACK_DEF( FT_Error ) 2591ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tt_cmap13_get_info( TT_CMap cmap, 2592ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TT_CMapInfo *cmap_info ) 2593ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2594ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte* p = cmap->data + 8; 2595ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2596ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2597ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmap_info->format = 13; 2598ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmap_info->language = (FT_ULong)TT_PEEK_ULONG( p ); 2599ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2600ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FT_Err_Ok; 2601ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2602ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2603ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2604ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_DEFINE_TT_CMAP( 2605ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tt_cmap13_class_rec, 2606ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov sizeof ( TT_CMap13Rec ), 2607ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2608ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (FT_CMap_InitFunc) tt_cmap13_init, 2609ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (FT_CMap_DoneFunc) NULL, 2610ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (FT_CMap_CharIndexFunc)tt_cmap13_char_index, 2611ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (FT_CMap_CharNextFunc) tt_cmap13_char_next, 2612ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2613ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov NULL, 2614ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov NULL, 2615ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov NULL, 2616ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov NULL, 2617ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov NULL, 2618ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2619ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 13, 2620ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (TT_CMap_ValidateFunc)tt_cmap13_validate, 2621ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (TT_CMap_Info_GetFunc)tt_cmap13_get_info ) 2622ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2623ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif /* TT_CONFIG_CMAP_FORMAT_13 */ 2624ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2625ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2626ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 2627ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 2628ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /***** *****/ 2629ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /***** FORMAT 14 *****/ 2630ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /***** *****/ 2631ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 2632ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 2633ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2634ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 2635ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 2636ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* TABLE OVERVIEW */ 2637ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* -------------- */ 2638ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 2639ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* NAME OFFSET TYPE DESCRIPTION */ 2640ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 2641ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* format 0 USHORT must be 14 */ 2642ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* length 2 ULONG table length in bytes */ 2643ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* numSelector 6 ULONG number of variation sel. records */ 2644ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 2645ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* Followed by numSelector records, each of which looks like */ 2646ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 2647ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* varSelector 0 UINT24 Unicode codepoint of sel. */ 2648ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* defaultOff 3 ULONG offset to a default UVS table */ 2649ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* describing any variants to be found in */ 2650ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* the normal Unicode subtable. */ 2651ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* nonDefOff 7 ULONG offset to a non-default UVS table */ 2652ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* describing any variants not in the */ 2653ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* standard cmap, with GIDs here */ 2654ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* (either offset may be 0 NULL) */ 2655ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 2656ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* Selectors are sorted by code point. */ 2657ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 2658ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* A default Unicode Variation Selector (UVS) subtable is just a list of */ 2659ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* ranges of code points which are to be found in the standard cmap. No */ 2660ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* glyph IDs (GIDs) here. */ 2661ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 2662ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* numRanges 0 ULONG number of ranges following */ 2663ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 2664ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* A range looks like */ 2665ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 2666ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* uniStart 0 UINT24 code point of the first character in */ 2667ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* this range */ 2668ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* additionalCnt 3 UBYTE count of additional characters in this */ 2669ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* range (zero means a range of a single */ 2670ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* character) */ 2671ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 2672ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* Ranges are sorted by `uniStart'. */ 2673ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 2674ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* A non-default Unicode Variation Selector (UVS) subtable is a list of */ 2675ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* mappings from codepoint to GID. */ 2676ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 2677ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* numMappings 0 ULONG number of mappings */ 2678ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 2679ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* A range looks like */ 2680ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 2681ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* uniStart 0 UINT24 code point of the first character in */ 2682ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* this range */ 2683ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* GID 3 USHORT and its GID */ 2684ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 2685ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* Ranges are sorted by `uniStart'. */ 2686ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2687ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#ifdef TT_CONFIG_CMAP_FORMAT_14 2688ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2689ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov typedef struct TT_CMap14Rec_ 2690ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2691ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TT_CMapRec cmap; 2692ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_ULong num_selectors; 2693ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2694ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* This array is used to store the results of various 2695ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov * cmap 14 query functions. The data is overwritten 2696ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov * on each call to these functions. 2697ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov */ 2698ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt32 max_results; 2699ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt32* results; 2700ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Memory memory; 2701ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2702ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } TT_CMap14Rec, *TT_CMap14; 2703ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2704ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2705ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_CALLBACK_DEF( void ) 2706ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tt_cmap14_done( TT_CMap14 cmap ) 2707ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2708ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Memory memory = cmap->memory; 2709ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2710ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2711ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmap->max_results = 0; 2712ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( memory != NULL && cmap->results != NULL ) 2713ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_FREE( cmap->results ); 2714ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2715ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2716ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2717ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov static FT_Error 2718ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tt_cmap14_ensure( TT_CMap14 cmap, 2719ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt32 num_results, 2720ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Memory memory ) 2721ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2722ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt32 old_max = cmap->max_results; 2723ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Error error = FT_Err_Ok; 2724ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2725ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2726ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( num_results > cmap->max_results ) 2727ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2728ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmap->memory = memory; 2729ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2730ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( FT_QRENEW_ARRAY( cmap->results, old_max, num_results ) ) 2731ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return error; 2732ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2733ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmap->max_results = num_results; 2734ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2735ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2736ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return error; 2737ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2738ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2739ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2740ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_CALLBACK_DEF( FT_Error ) 2741ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tt_cmap14_init( TT_CMap14 cmap, 2742ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte* table ) 2743ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2744ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmap->cmap.data = table; 2745ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2746ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov table += 6; 2747ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmap->num_selectors = FT_PEEK_ULONG( table ); 2748ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmap->max_results = 0; 2749ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmap->results = NULL; 2750ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2751ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FT_Err_Ok; 2752ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2753ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2754ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2755ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_CALLBACK_DEF( FT_Error ) 2756ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tt_cmap14_validate( FT_Byte* table, 2757ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Validator valid ) 2758ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2759ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte* p = table + 2; 2760ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_ULong length = TT_NEXT_ULONG( p ); 2761ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_ULong num_selectors = TT_NEXT_ULONG( p ); 2762ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2763ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2764ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( length > (FT_ULong)( valid->limit - table ) || 2765ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov length < 10 + 11 * num_selectors ) 2766ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_INVALID_TOO_SHORT; 2767ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2768ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* check selectors, they must be in increasing order */ 2769ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2770ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* we start lastVarSel at 1 because a variant selector value of 0 2771ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov * isn't valid. 2772ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov */ 2773ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_ULong n, lastVarSel = 1; 2774ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2775ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2776ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( n = 0; n < num_selectors; n++ ) 2777ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2778ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_ULong varSel = TT_NEXT_UINT24( p ); 2779ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_ULong defOff = TT_NEXT_ULONG( p ); 2780ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_ULong nondefOff = TT_NEXT_ULONG( p ); 2781ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2782ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2783ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( defOff >= length || nondefOff >= length ) 2784ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_INVALID_TOO_SHORT; 2785ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2786ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( varSel < lastVarSel ) 2787ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_INVALID_DATA; 2788ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2789ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov lastVarSel = varSel + 1; 2790ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2791ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* check the default table (these glyphs should be reached */ 2792ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* through the normal Unicode cmap, no GIDs, just check order) */ 2793ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( defOff != 0 ) 2794ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2795ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte* defp = table + defOff; 2796ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_ULong numRanges = TT_NEXT_ULONG( defp ); 2797ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_ULong i; 2798ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_ULong lastBase = 0; 2799ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2800ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2801ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( defp + numRanges * 4 > valid->limit ) 2802ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_INVALID_TOO_SHORT; 2803ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2804ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( i = 0; i < numRanges; ++i ) 2805ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2806ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_ULong base = TT_NEXT_UINT24( defp ); 2807ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_ULong cnt = FT_NEXT_BYTE( defp ); 2808ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2809ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2810ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( base + cnt >= 0x110000UL ) /* end of Unicode */ 2811ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_INVALID_DATA; 2812ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2813ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( base < lastBase ) 2814ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_INVALID_DATA; 2815ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2816ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov lastBase = base + cnt + 1U; 2817ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2818ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2819ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2820ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* and the non-default table (these glyphs are specified here) */ 2821ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( nondefOff != 0 ) 2822ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2823ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte* ndp = table + nondefOff; 2824ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_ULong numMappings = TT_NEXT_ULONG( ndp ); 2825ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_ULong i, lastUni = 0; 2826ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2827ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2828ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( numMappings * 4 > (FT_ULong)( valid->limit - ndp ) ) 2829ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_INVALID_TOO_SHORT; 2830ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2831ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( i = 0; i < numMappings; ++i ) 2832ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2833ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_ULong uni = TT_NEXT_UINT24( ndp ); 2834ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_ULong gid = TT_NEXT_USHORT( ndp ); 2835ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2836ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2837ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( uni >= 0x110000UL ) /* end of Unicode */ 2838ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_INVALID_DATA; 2839ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2840ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( uni < lastUni ) 2841ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_INVALID_DATA; 2842ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2843ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov lastUni = uni + 1U; 2844ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2845ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( valid->level >= FT_VALIDATE_TIGHT && 2846ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gid >= TT_VALID_GLYPH_COUNT( valid ) ) 2847ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_INVALID_GLYPH_ID; 2848ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2849ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2850ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2851ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2852ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2853ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FT_Err_Ok; 2854ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2855ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2856ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2857ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_CALLBACK_DEF( FT_UInt ) 2858ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tt_cmap14_char_index( TT_CMap cmap, 2859ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt32 char_code ) 2860ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2861ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UNUSED( cmap ); 2862ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UNUSED( char_code ); 2863ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2864ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* This can't happen */ 2865ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return 0; 2866ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2867ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2868ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2869ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_CALLBACK_DEF( FT_UInt32 ) 2870ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tt_cmap14_char_next( TT_CMap cmap, 2871ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt32 *pchar_code ) 2872ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2873ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UNUSED( cmap ); 2874ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2875ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* This can't happen */ 2876ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov *pchar_code = 0; 2877ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return 0; 2878ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2879ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2880ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2881ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_CALLBACK_DEF( FT_Error ) 2882ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tt_cmap14_get_info( TT_CMap cmap, 2883ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TT_CMapInfo *cmap_info ) 2884ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2885ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UNUSED( cmap ); 2886ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2887ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmap_info->format = 14; 2888ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* subtable 14 does not define a language field */ 2889ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmap_info->language = 0xFFFFFFFFUL; 2890ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2891ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FT_Err_Ok; 2892ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2893ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2894ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2895ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov static FT_UInt 2896ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tt_cmap14_char_map_def_binary( FT_Byte *base, 2897ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt32 char_code ) 2898ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2899ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt32 numRanges = TT_PEEK_ULONG( base ); 2900ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt32 max, min; 2901ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2902ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2903ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov min = 0; 2904ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov max = numRanges; 2905ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2906ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov base += 4; 2907ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2908ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* binary search */ 2909ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov while ( min < max ) 2910ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2911ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt32 mid = ( min + max ) >> 1; 2912ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte* p = base + 4 * mid; 2913ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_ULong start = TT_NEXT_UINT24( p ); 2914ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt cnt = FT_NEXT_BYTE( p ); 2915ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2916ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2917ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( char_code < start ) 2918ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov max = mid; 2919ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else if ( char_code > start+cnt ) 2920ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov min = mid + 1; 2921ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else 2922ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return TRUE; 2923ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2924ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2925ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FALSE; 2926ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2927ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2928ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2929ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov static FT_UInt 2930ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tt_cmap14_char_map_nondef_binary( FT_Byte *base, 2931ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt32 char_code ) 2932ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2933ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt32 numMappings = TT_PEEK_ULONG( base ); 2934ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt32 max, min; 2935ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2936ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2937ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov min = 0; 2938ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov max = numMappings; 2939ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2940ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov base += 4; 2941ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2942ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* binary search */ 2943ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov while ( min < max ) 2944ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2945ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt32 mid = ( min + max ) >> 1; 2946ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte* p = base + 5 * mid; 2947ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt32 uni = (FT_UInt32)TT_NEXT_UINT24( p ); 2948ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2949ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2950ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( char_code < uni ) 2951ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov max = mid; 2952ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else if ( char_code > uni ) 2953ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov min = mid + 1; 2954ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else 2955ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return TT_PEEK_USHORT( p ); 2956ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2957ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2958ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return 0; 2959ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2960ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2961ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2962ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov static FT_Byte* 2963ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tt_cmap14_find_variant( FT_Byte *base, 2964ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt32 variantCode ) 2965ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2966ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt32 numVar = TT_PEEK_ULONG( base ); 2967ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt32 max, min; 2968ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2969ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2970ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov min = 0; 2971ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov max = numVar; 2972ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2973ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov base += 4; 2974ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2975ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* binary search */ 2976ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov while ( min < max ) 2977ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2978ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt32 mid = ( min + max ) >> 1; 2979ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte* p = base + 11 * mid; 2980ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_ULong varSel = TT_NEXT_UINT24( p ); 2981ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2982ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2983ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( variantCode < varSel ) 2984ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov max = mid; 2985ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else if ( variantCode > varSel ) 2986ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov min = mid + 1; 2987ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else 2988ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return p; 2989ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2990ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2991ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return NULL; 2992ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2993ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2994ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2995ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_CALLBACK_DEF( FT_UInt ) 2996ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tt_cmap14_char_var_index( TT_CMap cmap, 2997ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TT_CMap ucmap, 2998ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt32 charcode, 2999ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt32 variantSelector ) 3000ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 3001ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte* p = tt_cmap14_find_variant( cmap->data + 6, variantSelector ); 3002ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_ULong defOff; 3003ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_ULong nondefOff; 3004ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3005ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3006ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( !p ) 3007ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return 0; 3008ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3009ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov defOff = TT_NEXT_ULONG( p ); 3010ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov nondefOff = TT_PEEK_ULONG( p ); 3011ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3012ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( defOff != 0 && 3013ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tt_cmap14_char_map_def_binary( cmap->data + defOff, charcode ) ) 3014ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 3015ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* This is the default variant of this charcode. GID not stored */ 3016ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* here; stored in the normal Unicode charmap instead. */ 3017ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return ucmap->cmap.clazz->char_index( &ucmap->cmap, charcode ); 3018ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 3019ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3020ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( nondefOff != 0 ) 3021ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return tt_cmap14_char_map_nondef_binary( cmap->data + nondefOff, 3022ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov charcode ); 3023ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3024ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return 0; 3025ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 3026ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3027ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3028ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_CALLBACK_DEF( FT_Int ) 3029ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tt_cmap14_char_var_isdefault( TT_CMap cmap, 3030ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt32 charcode, 3031ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt32 variantSelector ) 3032ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 3033ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte* p = tt_cmap14_find_variant( cmap->data + 6, variantSelector ); 3034ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_ULong defOff; 3035ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_ULong nondefOff; 3036ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3037ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3038ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( !p ) 3039ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return -1; 3040ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3041ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov defOff = TT_NEXT_ULONG( p ); 3042ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov nondefOff = TT_NEXT_ULONG( p ); 3043ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3044ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( defOff != 0 && 3045ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tt_cmap14_char_map_def_binary( cmap->data + defOff, charcode ) ) 3046ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return 1; 3047ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3048ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( nondefOff != 0 && 3049ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tt_cmap14_char_map_nondef_binary( cmap->data + nondefOff, 3050ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov charcode ) != 0 ) 3051ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return 0; 3052ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3053ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return -1; 3054ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 3055ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3056ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3057ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_CALLBACK_DEF( FT_UInt32* ) 3058ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tt_cmap14_variants( TT_CMap cmap, 3059ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Memory memory ) 3060ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 3061ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TT_CMap14 cmap14 = (TT_CMap14)cmap; 3062ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt32 count = cmap14->num_selectors; 3063ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte* p = cmap->data + 10; 3064ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt32* result; 3065ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt32 i; 3066ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3067ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3068ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( tt_cmap14_ensure( cmap14, ( count + 1 ), memory ) ) 3069ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return NULL; 3070ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3071ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov result = cmap14->results; 3072ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( i = 0; i < count; ++i ) 3073ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 3074ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov result[i] = (FT_UInt32)TT_NEXT_UINT24( p ); 3075ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p += 8; 3076ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 3077ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov result[i] = 0; 3078ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3079ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return result; 3080ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 3081ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3082ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3083ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_CALLBACK_DEF( FT_UInt32 * ) 3084ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tt_cmap14_char_variants( TT_CMap cmap, 3085ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Memory memory, 3086ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt32 charCode ) 3087ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 3088ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TT_CMap14 cmap14 = (TT_CMap14) cmap; 3089ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt32 count = cmap14->num_selectors; 3090ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte* p = cmap->data + 10; 3091ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt32* q; 3092ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3093ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3094ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( tt_cmap14_ensure( cmap14, ( count + 1 ), memory ) ) 3095ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return NULL; 3096ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3097ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( q = cmap14->results; count > 0; --count ) 3098ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 3099ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt32 varSel = TT_NEXT_UINT24( p ); 3100ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_ULong defOff = TT_NEXT_ULONG( p ); 3101ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_ULong nondefOff = TT_NEXT_ULONG( p ); 3102ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3103ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3104ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( ( defOff != 0 && 3105ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tt_cmap14_char_map_def_binary( cmap->data + defOff, 3106ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov charCode ) ) || 3107ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ( nondefOff != 0 && 3108ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tt_cmap14_char_map_nondef_binary( cmap->data + nondefOff, 3109ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov charCode ) != 0 ) ) 3110ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 3111ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov q[0] = varSel; 3112ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov q++; 3113ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 3114ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 3115ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov q[0] = 0; 3116ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3117ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return cmap14->results; 3118ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 3119ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3120ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3121ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov static FT_UInt 3122ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tt_cmap14_def_char_count( FT_Byte *p ) 3123ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 3124ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt32 numRanges = (FT_UInt32)TT_NEXT_ULONG( p ); 3125ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt tot = 0; 3126ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3127ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3128ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p += 3; /* point to the first `cnt' field */ 3129ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( ; numRanges > 0; numRanges-- ) 3130ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 3131ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tot += 1 + p[0]; 3132ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p += 4; 3133ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 3134ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3135ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return tot; 3136ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 3137ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3138ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3139ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov static FT_UInt32* 3140ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tt_cmap14_get_def_chars( TT_CMap cmap, 3141ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte* p, 3142ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Memory memory ) 3143ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 3144ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TT_CMap14 cmap14 = (TT_CMap14) cmap; 3145ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt32 numRanges; 3146ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt cnt; 3147ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt32* q; 3148ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3149ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3150ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cnt = tt_cmap14_def_char_count( p ); 3151ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov numRanges = (FT_UInt32)TT_NEXT_ULONG( p ); 3152ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3153ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( tt_cmap14_ensure( cmap14, ( cnt + 1 ), memory ) ) 3154ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return NULL; 3155ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3156ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( q = cmap14->results; numRanges > 0; --numRanges ) 3157ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 3158ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt32 uni = (FT_UInt32)TT_NEXT_UINT24( p ); 3159ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3160ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3161ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cnt = FT_NEXT_BYTE( p ) + 1; 3162ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov do 3163ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 3164ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov q[0] = uni; 3165ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov uni += 1; 3166ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov q += 1; 3167ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3168ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } while ( --cnt != 0 ); 3169ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 3170ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov q[0] = 0; 3171ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3172ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return cmap14->results; 3173ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 3174ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3175ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3176ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov static FT_UInt32* 3177ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tt_cmap14_get_nondef_chars( TT_CMap cmap, 3178ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte *p, 3179ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Memory memory ) 3180ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 3181ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TT_CMap14 cmap14 = (TT_CMap14) cmap; 3182ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt32 numMappings; 3183ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt i; 3184ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt32 *ret; 3185ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3186ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3187ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov numMappings = (FT_UInt32)TT_NEXT_ULONG( p ); 3188ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3189ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( tt_cmap14_ensure( cmap14, ( numMappings + 1 ), memory ) ) 3190ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return NULL; 3191ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3192ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ret = cmap14->results; 3193ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( i = 0; i < numMappings; ++i ) 3194ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 3195ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ret[i] = (FT_UInt32)TT_NEXT_UINT24( p ); 3196ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p += 2; 3197ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 3198ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ret[i] = 0; 3199ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3200ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return ret; 3201ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 3202ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3203ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3204ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_CALLBACK_DEF( FT_UInt32 * ) 3205ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tt_cmap14_variant_chars( TT_CMap cmap, 3206ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Memory memory, 3207ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt32 variantSelector ) 3208ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 3209ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte *p = tt_cmap14_find_variant( cmap->data + 6, 3210ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov variantSelector ); 3211ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt32 *ret; 3212ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Int i; 3213ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_ULong defOff; 3214ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_ULong nondefOff; 3215ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3216ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3217ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( !p ) 3218ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return NULL; 3219ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3220ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov defOff = TT_NEXT_ULONG( p ); 3221ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov nondefOff = TT_NEXT_ULONG( p ); 3222ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3223ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( defOff == 0 && nondefOff == 0 ) 3224ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return NULL; 3225ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3226ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( defOff == 0 ) 3227ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return tt_cmap14_get_nondef_chars( cmap, cmap->data + nondefOff, 3228ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov memory ); 3229ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else if ( nondefOff == 0 ) 3230ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return tt_cmap14_get_def_chars( cmap, cmap->data + defOff, 3231ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov memory ); 3232ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else 3233ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 3234ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* Both a default and a non-default glyph set? That's probably not */ 3235ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* good font design, but the spec allows for it... */ 3236ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TT_CMap14 cmap14 = (TT_CMap14) cmap; 3237ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt32 numRanges; 3238ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt32 numMappings; 3239ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt32 duni; 3240ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt32 dcnt; 3241ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt32 nuni; 3242ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte* dp; 3243ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt di, ni, k; 3244ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3245ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3246ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p = cmap->data + nondefOff; 3247ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov dp = cmap->data + defOff; 3248ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3249ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov numMappings = (FT_UInt32)TT_NEXT_ULONG( p ); 3250ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov dcnt = tt_cmap14_def_char_count( dp ); 3251ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov numRanges = (FT_UInt32)TT_NEXT_ULONG( dp ); 3252ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3253ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( numMappings == 0 ) 3254ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return tt_cmap14_get_def_chars( cmap, cmap->data + defOff, 3255ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov memory ); 3256ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( dcnt == 0 ) 3257ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return tt_cmap14_get_nondef_chars( cmap, cmap->data + nondefOff, 3258ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov memory ); 3259ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3260ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( tt_cmap14_ensure( cmap14, ( dcnt + numMappings + 1 ), memory ) ) 3261ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return NULL; 3262ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3263ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ret = cmap14->results; 3264ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov duni = (FT_UInt32)TT_NEXT_UINT24( dp ); 3265ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov dcnt = FT_NEXT_BYTE( dp ); 3266ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov di = 1; 3267ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov nuni = (FT_UInt32)TT_NEXT_UINT24( p ); 3268ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p += 2; 3269ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ni = 1; 3270ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov i = 0; 3271ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3272ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( ;; ) 3273ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 3274ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( nuni > duni + dcnt ) 3275ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 3276ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( k = 0; k <= dcnt; ++k ) 3277ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ret[i++] = duni + k; 3278ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3279ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ++di; 3280ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3281ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( di > numRanges ) 3282ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 3283ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3284ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov duni = (FT_UInt32)TT_NEXT_UINT24( dp ); 3285ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov dcnt = FT_NEXT_BYTE( dp ); 3286ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 3287ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else 3288ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 3289ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( nuni < duni ) 3290ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ret[i++] = nuni; 3291ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* If it is within the default range then ignore it -- */ 3292ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* that should not have happened */ 3293ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ++ni; 3294ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( ni > numMappings ) 3295ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 3296ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3297ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov nuni = (FT_UInt32)TT_NEXT_UINT24( p ); 3298ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p += 2; 3299ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 3300ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 3301ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3302ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( ni <= numMappings ) 3303ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 3304ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* If we get here then we have run out of all default ranges. */ 3305ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* We have read one non-default mapping which we haven't stored */ 3306ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* and there may be others that need to be read. */ 3307ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ret[i++] = nuni; 3308ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov while ( ni < numMappings ) 3309ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 3310ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ret[i++] = (FT_UInt32)TT_NEXT_UINT24( p ); 3311ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p += 2; 3312ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ++ni; 3313ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 3314ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 3315ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else if ( di <= numRanges ) 3316ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 3317ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* If we get here then we have run out of all non-default */ 3318ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* mappings. We have read one default range which we haven't */ 3319ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* stored and there may be others that need to be read. */ 3320ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( k = 0; k <= dcnt; ++k ) 3321ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ret[i++] = duni + k; 3322ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3323ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov while ( di < numRanges ) 3324ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 3325ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov duni = (FT_UInt32)TT_NEXT_UINT24( dp ); 3326ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov dcnt = FT_NEXT_BYTE( dp ); 3327ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3328ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( k = 0; k <= dcnt; ++k ) 3329ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ret[i++] = duni + k; 3330ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ++di; 3331ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 3332ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 3333ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3334ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ret[i] = 0; 3335ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3336ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return ret; 3337ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 3338ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 3339ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3340ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3341ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_DEFINE_TT_CMAP( 3342ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tt_cmap14_class_rec, 3343ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov sizeof ( TT_CMap14Rec ), 3344ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3345ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (FT_CMap_InitFunc) tt_cmap14_init, 3346ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (FT_CMap_DoneFunc) tt_cmap14_done, 3347ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (FT_CMap_CharIndexFunc)tt_cmap14_char_index, 3348ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (FT_CMap_CharNextFunc) tt_cmap14_char_next, 3349ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3350ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* Format 14 extension functions */ 3351ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (FT_CMap_CharVarIndexFunc) tt_cmap14_char_var_index, 3352ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (FT_CMap_CharVarIsDefaultFunc)tt_cmap14_char_var_isdefault, 3353ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (FT_CMap_VariantListFunc) tt_cmap14_variants, 3354ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (FT_CMap_CharVariantListFunc) tt_cmap14_char_variants, 3355ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (FT_CMap_VariantCharListFunc) tt_cmap14_variant_chars, 3356ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3357ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 14, 3358ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (TT_CMap_ValidateFunc)tt_cmap14_validate, 3359ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (TT_CMap_Info_GetFunc)tt_cmap14_get_info ) 3360ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3361ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif /* TT_CONFIG_CMAP_FORMAT_14 */ 3362ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3363ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3364ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#ifndef FT_CONFIG_OPTION_PIC 3365ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3366ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov static const TT_CMap_Class tt_cmap_classes[] = 3367ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 3368ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define TTCMAPCITEM( a ) &a, 3369ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "ttcmapc.h" 3370ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov NULL, 3371ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov }; 3372ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3373ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#else /*FT_CONFIG_OPTION_PIC*/ 3374ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3375ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov void 3376ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Destroy_Class_tt_cmap_classes( FT_Library library, 3377ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TT_CMap_Class* clazz ) 3378ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 3379ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Memory memory = library->memory; 3380ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3381ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3382ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( clazz ) 3383ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_FREE( clazz ); 3384ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 3385ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3386ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3387ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Error 3388ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Create_Class_tt_cmap_classes( FT_Library library, 3389ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TT_CMap_Class** output_class ) 3390ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 3391ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TT_CMap_Class* clazz = NULL; 3392ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TT_CMap_ClassRec* recs; 3393ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Error error; 3394ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Memory memory = library->memory; 3395ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3396ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int i = 0; 3397ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3398ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3399ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define TTCMAPCITEM( a ) i++; 3400ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "ttcmapc.h" 3401ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3402ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* allocate enough space for both the pointers */ 3403ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* plus terminator and the class instances */ 3404ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( FT_ALLOC( clazz, sizeof ( *clazz ) * ( i + 1 ) + 3405ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov sizeof ( TT_CMap_ClassRec ) * i ) ) 3406ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return error; 3407ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3408ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* the location of the class instances follows the array of pointers */ 3409ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov recs = (TT_CMap_ClassRec*)( (char*)clazz + 3410ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov sizeof ( *clazz ) * ( i + 1 ) ); 3411ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov i = 0; 3412ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3413ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#undef TTCMAPCITEM 3414ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define TTCMAPCITEM( a ) \ 3415ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Init_Class_ ## a( &recs[i] ); \ 3416ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov clazz[i] = &recs[i]; \ 3417ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov i++; 3418ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "ttcmapc.h" 3419ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3420ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov clazz[i] = NULL; 3421ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3422ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov *output_class = clazz; 3423ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FT_Err_Ok; 3424ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 3425ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3426ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif /*FT_CONFIG_OPTION_PIC*/ 3427ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3428ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3429ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* parse the `cmap' table and build the corresponding TT_CMap objects */ 3430ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* in the current face */ 3431ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 3432ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_LOCAL_DEF( FT_Error ) 3433ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tt_face_build_cmaps( TT_Face face ) 3434ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 3435ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte* table = face->cmap_table; 3436ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte* limit = table + face->cmap_size; 3437ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt volatile num_cmaps; 3438ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte* volatile p = table; 3439ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Library library = FT_FACE_LIBRARY( face ); 3440ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3441ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UNUSED( library ); 3442ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3443ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3444ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( !p || p + 4 > limit ) 3445ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FT_THROW( Invalid_Table ); 3446ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3447ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* only recognize format 0 */ 3448ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( TT_NEXT_USHORT( p ) != 0 ) 3449ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 3450ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p -= 2; 3451ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_ERROR(( "tt_face_build_cmaps:" 3452ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov " unsupported `cmap' table format = %d\n", 3453ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TT_PEEK_USHORT( p ) )); 3454ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FT_THROW( Invalid_Table ); 3455ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 3456ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3457ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov num_cmaps = TT_NEXT_USHORT( p ); 3458ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3459ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#ifdef FT_MAX_CHARMAP_CACHEABLE 3460ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( num_cmaps > FT_MAX_CHARMAP_CACHEABLE ) 3461ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_ERROR(( "tt_face_build_cmaps: too many cmap subtables (%d)\n" 3462ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov " subtable #%d and higher are loaded" 3463ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov " but cannot be searched\n", 3464ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov num_cmaps, FT_MAX_CHARMAP_CACHEABLE + 1 )); 3465ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif 3466ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3467ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( ; num_cmaps > 0 && p + 8 <= limit; num_cmaps-- ) 3468ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 3469ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_CharMapRec charmap; 3470ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt32 offset; 3471ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3472ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3473ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov charmap.platform_id = TT_NEXT_USHORT( p ); 3474ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov charmap.encoding_id = TT_NEXT_USHORT( p ); 3475ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov charmap.face = FT_FACE( face ); 3476ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov charmap.encoding = FT_ENCODING_NONE; /* will be filled later */ 3477ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov offset = TT_NEXT_ULONG( p ); 3478ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3479ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( offset && offset <= face->cmap_size - 2 ) 3480ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 3481ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte* volatile cmap = table + offset; 3482ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov volatile FT_UInt format = TT_PEEK_USHORT( cmap ); 3483ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov const TT_CMap_Class* volatile pclazz = TT_CMAP_CLASSES_GET; 3484ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TT_CMap_Class volatile clazz; 3485ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3486ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3487ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( ; *pclazz; pclazz++ ) 3488ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 3489ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov clazz = *pclazz; 3490ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( clazz->format == format ) 3491ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 3492ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov volatile TT_ValidatorRec valid; 3493ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov volatile FT_Error error = FT_Err_Ok; 3494ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3495ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3496ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ft_validator_init( FT_VALIDATOR( &valid ), cmap, limit, 3497ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_VALIDATE_DEFAULT ); 3498ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3499ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov valid.num_glyphs = (FT_UInt)face->max_profile.numGlyphs; 3500ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#ifndef _FX_MANAGED_CODE_ 3501ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( ft_setjmp( FT_VALIDATOR( &valid )->jump_buffer) == 0 ) 3502ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 3503ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif 3504ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* validate this cmap sub-table */ 3505ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov error = clazz->validate( cmap, FT_VALIDATOR( &valid ) ); 3506ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#ifndef _FX_MANAGED_CODE_ 3507ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 3508ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif 3509ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3510ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( valid.validator.error == 0 ) 3511ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 3512ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_CMap ttcmap; 3513ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3514ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3515ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* It might make sense to store the single variation */ 3516ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* selector cmap somewhere special. But it would have to be */ 3517ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* in the public FT_FaceRec, and we can't change that. */ 3518ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3519ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( !FT_CMap_New( (FT_CMap_Class)clazz, 3520ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmap, &charmap, &ttcmap ) ) 3521ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 3522ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* it is simpler to directly set `flags' than adding */ 3523ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* a parameter to FT_CMap_New */ 3524ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ((TT_CMap)ttcmap)->flags = (FT_Int)error; 3525ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 3526ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 3527ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else 3528ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 3529ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_TRACE0(( "tt_face_build_cmaps:" 3530ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov " broken cmap sub-table ignored\n" )); 3531ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 3532ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 3533ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 3534ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 3535ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3536ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( *pclazz == NULL ) 3537ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 3538ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_TRACE0(( "tt_face_build_cmaps:" 3539ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov " unsupported cmap sub-table ignored\n" )); 3540ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 3541ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 3542ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 3543ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3544ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FT_Err_Ok; 3545ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 3546ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3547ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3548ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_LOCAL( FT_Error ) 3549ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tt_get_cmap_info( FT_CharMap charmap, 3550ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TT_CMapInfo *cmap_info ) 3551ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 3552ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_CMap cmap = (FT_CMap)charmap; 3553ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TT_CMap_Class clazz = (TT_CMap_Class)cmap->clazz; 3554ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3555ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3556ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return clazz->get_cmap_info( charmap, cmap_info ); 3557ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 3558ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3559ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3560ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* END */ 3561