1*37da2899SCharles.Forsyth /***************************************************************************/ 2*37da2899SCharles.Forsyth /* */ 3*37da2899SCharles.Forsyth /* ttcmap.c */ 4*37da2899SCharles.Forsyth /* */ 5*37da2899SCharles.Forsyth /* TrueType character mapping table (cmap) support (body). */ 6*37da2899SCharles.Forsyth /* */ 7*37da2899SCharles.Forsyth /* Copyright 1996-2001, 2002 by */ 8*37da2899SCharles.Forsyth /* David Turner, Robert Wilhelm, and Werner Lemberg. */ 9*37da2899SCharles.Forsyth /* */ 10*37da2899SCharles.Forsyth /* This file is part of the FreeType project, and may only be used, */ 11*37da2899SCharles.Forsyth /* modified, and distributed under the terms of the FreeType project */ 12*37da2899SCharles.Forsyth /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ 13*37da2899SCharles.Forsyth /* this file you indicate that you have read the license and */ 14*37da2899SCharles.Forsyth /* understand and accept it fully. */ 15*37da2899SCharles.Forsyth /* */ 16*37da2899SCharles.Forsyth /***************************************************************************/ 17*37da2899SCharles.Forsyth 18*37da2899SCharles.Forsyth 19*37da2899SCharles.Forsyth #include <ft2build.h> 20*37da2899SCharles.Forsyth #include FT_INTERNAL_DEBUG_H 21*37da2899SCharles.Forsyth #include "ttload.h" 22*37da2899SCharles.Forsyth #include "ttcmap.h" 23*37da2899SCharles.Forsyth 24*37da2899SCharles.Forsyth #include "sferrors.h" 25*37da2899SCharles.Forsyth 26*37da2899SCharles.Forsyth 27*37da2899SCharles.Forsyth /*************************************************************************/ 28*37da2899SCharles.Forsyth /* */ 29*37da2899SCharles.Forsyth /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ 30*37da2899SCharles.Forsyth /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ 31*37da2899SCharles.Forsyth /* messages during execution. */ 32*37da2899SCharles.Forsyth /* */ 33*37da2899SCharles.Forsyth #undef FT_COMPONENT 34*37da2899SCharles.Forsyth #define FT_COMPONENT trace_ttcmap 35*37da2899SCharles.Forsyth 36*37da2899SCharles.Forsyth 37*37da2899SCharles.Forsyth FT_CALLBACK_DEF( FT_UInt ) 38*37da2899SCharles.Forsyth code_to_index0( TT_CMapTable charmap, 39*37da2899SCharles.Forsyth FT_ULong char_code ); 40*37da2899SCharles.Forsyth 41*37da2899SCharles.Forsyth FT_CALLBACK_DEF( FT_ULong ) 42*37da2899SCharles.Forsyth code_to_next0( TT_CMapTable charmap, 43*37da2899SCharles.Forsyth FT_ULong char_code ); 44*37da2899SCharles.Forsyth 45*37da2899SCharles.Forsyth FT_CALLBACK_DEF( FT_UInt ) 46*37da2899SCharles.Forsyth code_to_index2( TT_CMapTable charmap, 47*37da2899SCharles.Forsyth FT_ULong char_code ); 48*37da2899SCharles.Forsyth 49*37da2899SCharles.Forsyth FT_CALLBACK_DEF( FT_ULong ) 50*37da2899SCharles.Forsyth code_to_next2( TT_CMapTable charmap, 51*37da2899SCharles.Forsyth FT_ULong char_code ); 52*37da2899SCharles.Forsyth 53*37da2899SCharles.Forsyth FT_CALLBACK_DEF( FT_UInt ) 54*37da2899SCharles.Forsyth code_to_index4( TT_CMapTable charmap, 55*37da2899SCharles.Forsyth FT_ULong char_code ); 56*37da2899SCharles.Forsyth 57*37da2899SCharles.Forsyth FT_CALLBACK_DEF( FT_ULong ) 58*37da2899SCharles.Forsyth code_to_next4( TT_CMapTable charmap, 59*37da2899SCharles.Forsyth FT_ULong char_code ); 60*37da2899SCharles.Forsyth 61*37da2899SCharles.Forsyth FT_CALLBACK_DEF( FT_UInt ) 62*37da2899SCharles.Forsyth code_to_index6( TT_CMapTable charmap, 63*37da2899SCharles.Forsyth FT_ULong char_code ); 64*37da2899SCharles.Forsyth 65*37da2899SCharles.Forsyth FT_CALLBACK_DEF( FT_ULong ) 66*37da2899SCharles.Forsyth code_to_next6( TT_CMapTable charmap, 67*37da2899SCharles.Forsyth FT_ULong char_code ); 68*37da2899SCharles.Forsyth 69*37da2899SCharles.Forsyth FT_CALLBACK_DEF( FT_UInt ) 70*37da2899SCharles.Forsyth code_to_index8_12( TT_CMapTable charmap, 71*37da2899SCharles.Forsyth FT_ULong char_code ); 72*37da2899SCharles.Forsyth 73*37da2899SCharles.Forsyth FT_CALLBACK_DEF( FT_ULong ) 74*37da2899SCharles.Forsyth code_to_next8_12( TT_CMapTable charmap, 75*37da2899SCharles.Forsyth FT_ULong char_code ); 76*37da2899SCharles.Forsyth 77*37da2899SCharles.Forsyth FT_CALLBACK_DEF( FT_UInt ) 78*37da2899SCharles.Forsyth code_to_index10( TT_CMapTable charmap, 79*37da2899SCharles.Forsyth FT_ULong char_code ); 80*37da2899SCharles.Forsyth 81*37da2899SCharles.Forsyth FT_CALLBACK_DEF( FT_ULong ) 82*37da2899SCharles.Forsyth code_to_next10( TT_CMapTable charmap, 83*37da2899SCharles.Forsyth FT_ULong char_code ); 84*37da2899SCharles.Forsyth 85*37da2899SCharles.Forsyth 86*37da2899SCharles.Forsyth /*************************************************************************/ 87*37da2899SCharles.Forsyth /* */ 88*37da2899SCharles.Forsyth /* <Function> */ 89*37da2899SCharles.Forsyth /* tt_face_load_charmap */ 90*37da2899SCharles.Forsyth /* */ 91*37da2899SCharles.Forsyth /* <Description> */ 92*37da2899SCharles.Forsyth /* Loads a given TrueType character map into memory. */ 93*37da2899SCharles.Forsyth /* */ 94*37da2899SCharles.Forsyth /* <Input> */ 95*37da2899SCharles.Forsyth /* face :: A handle to the parent face object. */ 96*37da2899SCharles.Forsyth /* */ 97*37da2899SCharles.Forsyth /* stream :: A handle to the current stream object. */ 98*37da2899SCharles.Forsyth /* */ 99*37da2899SCharles.Forsyth /* <InOut> */ 100*37da2899SCharles.Forsyth /* table :: A pointer to a cmap object. */ 101*37da2899SCharles.Forsyth /* */ 102*37da2899SCharles.Forsyth /* <Return> */ 103*37da2899SCharles.Forsyth /* FreeType error code. 0 means success. */ 104*37da2899SCharles.Forsyth /* */ 105*37da2899SCharles.Forsyth /* <Note> */ 106*37da2899SCharles.Forsyth /* The function assumes that the stream is already in use (i.e., */ 107*37da2899SCharles.Forsyth /* opened). In case of error, all partially allocated tables are */ 108*37da2899SCharles.Forsyth /* released. */ 109*37da2899SCharles.Forsyth /* */ 110*37da2899SCharles.Forsyth FT_LOCAL_DEF( FT_Error ) tt_face_load_charmap(TT_Face face,TT_CMapTable cmap,FT_Stream stream)111*37da2899SCharles.Forsyth tt_face_load_charmap( TT_Face face, 112*37da2899SCharles.Forsyth TT_CMapTable cmap, 113*37da2899SCharles.Forsyth FT_Stream stream ) 114*37da2899SCharles.Forsyth { 115*37da2899SCharles.Forsyth FT_Error error; 116*37da2899SCharles.Forsyth FT_Memory memory; 117*37da2899SCharles.Forsyth FT_UShort num_SH, num_Seg, i; 118*37da2899SCharles.Forsyth FT_ULong j, n; 119*37da2899SCharles.Forsyth 120*37da2899SCharles.Forsyth FT_UShort u, l; 121*37da2899SCharles.Forsyth 122*37da2899SCharles.Forsyth TT_CMap0 cmap0; 123*37da2899SCharles.Forsyth TT_CMap2 cmap2; 124*37da2899SCharles.Forsyth TT_CMap4 cmap4; 125*37da2899SCharles.Forsyth TT_CMap6 cmap6; 126*37da2899SCharles.Forsyth TT_CMap8_12 cmap8_12; 127*37da2899SCharles.Forsyth TT_CMap10 cmap10; 128*37da2899SCharles.Forsyth 129*37da2899SCharles.Forsyth TT_CMap2SubHeader cmap2sub; 130*37da2899SCharles.Forsyth TT_CMap4Segment segments; 131*37da2899SCharles.Forsyth TT_CMapGroup groups; 132*37da2899SCharles.Forsyth 133*37da2899SCharles.Forsyth 134*37da2899SCharles.Forsyth if ( cmap->loaded ) 135*37da2899SCharles.Forsyth return SFNT_Err_Ok; 136*37da2899SCharles.Forsyth 137*37da2899SCharles.Forsyth memory = stream->memory; 138*37da2899SCharles.Forsyth 139*37da2899SCharles.Forsyth if ( FT_STREAM_SEEK( cmap->offset ) ) 140*37da2899SCharles.Forsyth return error; 141*37da2899SCharles.Forsyth 142*37da2899SCharles.Forsyth switch ( cmap->format ) 143*37da2899SCharles.Forsyth { 144*37da2899SCharles.Forsyth case 0: 145*37da2899SCharles.Forsyth cmap0 = &cmap->c.cmap0; 146*37da2899SCharles.Forsyth 147*37da2899SCharles.Forsyth if ( FT_READ_USHORT( cmap0->language ) || 148*37da2899SCharles.Forsyth FT_ALLOC( cmap0->glyphIdArray, 256L ) || 149*37da2899SCharles.Forsyth FT_STREAM_READ( cmap0->glyphIdArray, 256L ) ) 150*37da2899SCharles.Forsyth goto Fail; 151*37da2899SCharles.Forsyth 152*37da2899SCharles.Forsyth cmap->get_index = code_to_index0; 153*37da2899SCharles.Forsyth cmap->get_next_char = code_to_next0; 154*37da2899SCharles.Forsyth break; 155*37da2899SCharles.Forsyth 156*37da2899SCharles.Forsyth case 2: 157*37da2899SCharles.Forsyth num_SH = 0; 158*37da2899SCharles.Forsyth cmap2 = &cmap->c.cmap2; 159*37da2899SCharles.Forsyth 160*37da2899SCharles.Forsyth /* allocate subheader keys */ 161*37da2899SCharles.Forsyth 162*37da2899SCharles.Forsyth if ( FT_NEW_ARRAY( cmap2->subHeaderKeys, 256 ) || 163*37da2899SCharles.Forsyth FT_FRAME_ENTER( 2L + 512L ) ) 164*37da2899SCharles.Forsyth goto Fail; 165*37da2899SCharles.Forsyth 166*37da2899SCharles.Forsyth cmap2->language = FT_GET_USHORT(); 167*37da2899SCharles.Forsyth 168*37da2899SCharles.Forsyth for ( i = 0; i < 256; i++ ) 169*37da2899SCharles.Forsyth { 170*37da2899SCharles.Forsyth u = (FT_UShort)( FT_GET_USHORT() / 8 ); 171*37da2899SCharles.Forsyth cmap2->subHeaderKeys[i] = u; 172*37da2899SCharles.Forsyth 173*37da2899SCharles.Forsyth if ( num_SH < u ) 174*37da2899SCharles.Forsyth num_SH = u; 175*37da2899SCharles.Forsyth } 176*37da2899SCharles.Forsyth 177*37da2899SCharles.Forsyth FT_FRAME_EXIT(); 178*37da2899SCharles.Forsyth 179*37da2899SCharles.Forsyth /* load subheaders */ 180*37da2899SCharles.Forsyth 181*37da2899SCharles.Forsyth cmap2->numGlyphId = l = (FT_UShort)( 182*37da2899SCharles.Forsyth ( ( cmap->length - 2L * ( 256 + 3 ) - num_SH * 8L ) & 0xFFFFU ) / 2 ); 183*37da2899SCharles.Forsyth 184*37da2899SCharles.Forsyth if ( FT_NEW_ARRAY( cmap2->subHeaders, num_SH + 1 ) || 185*37da2899SCharles.Forsyth FT_FRAME_ENTER( ( num_SH + 1 ) * 8L ) ) 186*37da2899SCharles.Forsyth { 187*37da2899SCharles.Forsyth FT_FREE( cmap2->subHeaderKeys ); 188*37da2899SCharles.Forsyth goto Fail; 189*37da2899SCharles.Forsyth } 190*37da2899SCharles.Forsyth 191*37da2899SCharles.Forsyth cmap2sub = cmap2->subHeaders; 192*37da2899SCharles.Forsyth 193*37da2899SCharles.Forsyth for ( i = 0; i <= num_SH; i++ ) 194*37da2899SCharles.Forsyth { 195*37da2899SCharles.Forsyth cmap2sub->firstCode = FT_GET_USHORT(); 196*37da2899SCharles.Forsyth cmap2sub->entryCount = FT_GET_USHORT(); 197*37da2899SCharles.Forsyth cmap2sub->idDelta = FT_GET_SHORT(); 198*37da2899SCharles.Forsyth /* we apply the location offset immediately */ 199*37da2899SCharles.Forsyth cmap2sub->idRangeOffset = (FT_UShort)( 200*37da2899SCharles.Forsyth FT_GET_USHORT() - ( num_SH - i ) * 8 - 2 ); 201*37da2899SCharles.Forsyth 202*37da2899SCharles.Forsyth cmap2sub++; 203*37da2899SCharles.Forsyth } 204*37da2899SCharles.Forsyth 205*37da2899SCharles.Forsyth FT_FRAME_EXIT(); 206*37da2899SCharles.Forsyth 207*37da2899SCharles.Forsyth /* load glyph IDs */ 208*37da2899SCharles.Forsyth 209*37da2899SCharles.Forsyth if ( FT_NEW_ARRAY( cmap2->glyphIdArray, l ) || 210*37da2899SCharles.Forsyth FT_FRAME_ENTER( l * 2L ) ) 211*37da2899SCharles.Forsyth { 212*37da2899SCharles.Forsyth FT_FREE( cmap2->subHeaders ); 213*37da2899SCharles.Forsyth FT_FREE( cmap2->subHeaderKeys ); 214*37da2899SCharles.Forsyth goto Fail; 215*37da2899SCharles.Forsyth } 216*37da2899SCharles.Forsyth 217*37da2899SCharles.Forsyth for ( i = 0; i < l; i++ ) 218*37da2899SCharles.Forsyth cmap2->glyphIdArray[i] = FT_GET_USHORT(); 219*37da2899SCharles.Forsyth 220*37da2899SCharles.Forsyth FT_FRAME_EXIT(); 221*37da2899SCharles.Forsyth 222*37da2899SCharles.Forsyth cmap->get_index = code_to_index2; 223*37da2899SCharles.Forsyth cmap->get_next_char = code_to_next2; 224*37da2899SCharles.Forsyth break; 225*37da2899SCharles.Forsyth 226*37da2899SCharles.Forsyth case 4: 227*37da2899SCharles.Forsyth cmap4 = &cmap->c.cmap4; 228*37da2899SCharles.Forsyth 229*37da2899SCharles.Forsyth /* load header */ 230*37da2899SCharles.Forsyth 231*37da2899SCharles.Forsyth if ( FT_FRAME_ENTER( 10L ) ) 232*37da2899SCharles.Forsyth goto Fail; 233*37da2899SCharles.Forsyth 234*37da2899SCharles.Forsyth cmap4->language = FT_GET_USHORT(); 235*37da2899SCharles.Forsyth cmap4->segCountX2 = FT_GET_USHORT(); 236*37da2899SCharles.Forsyth cmap4->searchRange = FT_GET_USHORT(); 237*37da2899SCharles.Forsyth cmap4->entrySelector = FT_GET_USHORT(); 238*37da2899SCharles.Forsyth cmap4->rangeShift = FT_GET_USHORT(); 239*37da2899SCharles.Forsyth 240*37da2899SCharles.Forsyth num_Seg = (FT_UShort)( cmap4->segCountX2 / 2 ); 241*37da2899SCharles.Forsyth 242*37da2899SCharles.Forsyth FT_FRAME_EXIT(); 243*37da2899SCharles.Forsyth 244*37da2899SCharles.Forsyth /* load segments */ 245*37da2899SCharles.Forsyth 246*37da2899SCharles.Forsyth if ( FT_NEW_ARRAY( cmap4->segments, num_Seg ) || 247*37da2899SCharles.Forsyth FT_FRAME_ENTER( ( num_Seg * 4 + 1 ) * 2L ) ) 248*37da2899SCharles.Forsyth goto Fail; 249*37da2899SCharles.Forsyth 250*37da2899SCharles.Forsyth segments = cmap4->segments; 251*37da2899SCharles.Forsyth 252*37da2899SCharles.Forsyth for ( i = 0; i < num_Seg; i++ ) 253*37da2899SCharles.Forsyth segments[i].endCount = FT_GET_USHORT(); 254*37da2899SCharles.Forsyth 255*37da2899SCharles.Forsyth (void)FT_GET_USHORT(); 256*37da2899SCharles.Forsyth 257*37da2899SCharles.Forsyth for ( i = 0; i < num_Seg; i++ ) 258*37da2899SCharles.Forsyth segments[i].startCount = FT_GET_USHORT(); 259*37da2899SCharles.Forsyth 260*37da2899SCharles.Forsyth for ( i = 0; i < num_Seg; i++ ) 261*37da2899SCharles.Forsyth segments[i].idDelta = FT_GET_SHORT(); 262*37da2899SCharles.Forsyth 263*37da2899SCharles.Forsyth for ( i = 0; i < num_Seg; i++ ) 264*37da2899SCharles.Forsyth segments[i].idRangeOffset = FT_GET_USHORT(); 265*37da2899SCharles.Forsyth 266*37da2899SCharles.Forsyth FT_FRAME_EXIT(); 267*37da2899SCharles.Forsyth 268*37da2899SCharles.Forsyth cmap4->numGlyphId = l = (FT_UShort)( 269*37da2899SCharles.Forsyth ( ( cmap->length - ( 16L + 8L * num_Seg ) ) & 0xFFFFU ) / 2 ); 270*37da2899SCharles.Forsyth 271*37da2899SCharles.Forsyth /* load IDs */ 272*37da2899SCharles.Forsyth 273*37da2899SCharles.Forsyth if ( FT_NEW_ARRAY( cmap4->glyphIdArray, l ) || 274*37da2899SCharles.Forsyth FT_FRAME_ENTER( l * 2L ) ) 275*37da2899SCharles.Forsyth { 276*37da2899SCharles.Forsyth FT_FREE( cmap4->segments ); 277*37da2899SCharles.Forsyth goto Fail; 278*37da2899SCharles.Forsyth } 279*37da2899SCharles.Forsyth 280*37da2899SCharles.Forsyth for ( i = 0; i < l; i++ ) 281*37da2899SCharles.Forsyth cmap4->glyphIdArray[i] = FT_GET_USHORT(); 282*37da2899SCharles.Forsyth 283*37da2899SCharles.Forsyth FT_FRAME_EXIT(); 284*37da2899SCharles.Forsyth 285*37da2899SCharles.Forsyth cmap4->last_segment = cmap4->segments; 286*37da2899SCharles.Forsyth 287*37da2899SCharles.Forsyth cmap->get_index = code_to_index4; 288*37da2899SCharles.Forsyth cmap->get_next_char = code_to_next4; 289*37da2899SCharles.Forsyth break; 290*37da2899SCharles.Forsyth 291*37da2899SCharles.Forsyth case 6: 292*37da2899SCharles.Forsyth cmap6 = &cmap->c.cmap6; 293*37da2899SCharles.Forsyth 294*37da2899SCharles.Forsyth if ( FT_FRAME_ENTER( 6L ) ) 295*37da2899SCharles.Forsyth goto Fail; 296*37da2899SCharles.Forsyth 297*37da2899SCharles.Forsyth cmap6->language = FT_GET_USHORT(); 298*37da2899SCharles.Forsyth cmap6->firstCode = FT_GET_USHORT(); 299*37da2899SCharles.Forsyth cmap6->entryCount = FT_GET_USHORT(); 300*37da2899SCharles.Forsyth 301*37da2899SCharles.Forsyth FT_FRAME_EXIT(); 302*37da2899SCharles.Forsyth 303*37da2899SCharles.Forsyth l = cmap6->entryCount; 304*37da2899SCharles.Forsyth 305*37da2899SCharles.Forsyth if ( FT_NEW_ARRAY( cmap6->glyphIdArray, l ) || 306*37da2899SCharles.Forsyth FT_FRAME_ENTER( l * 2L ) ) 307*37da2899SCharles.Forsyth goto Fail; 308*37da2899SCharles.Forsyth 309*37da2899SCharles.Forsyth for ( i = 0; i < l; i++ ) 310*37da2899SCharles.Forsyth cmap6->glyphIdArray[i] = FT_GET_USHORT(); 311*37da2899SCharles.Forsyth 312*37da2899SCharles.Forsyth FT_FRAME_EXIT(); 313*37da2899SCharles.Forsyth cmap->get_index = code_to_index6; 314*37da2899SCharles.Forsyth cmap->get_next_char = code_to_next6; 315*37da2899SCharles.Forsyth break; 316*37da2899SCharles.Forsyth 317*37da2899SCharles.Forsyth case 8: 318*37da2899SCharles.Forsyth case 12: 319*37da2899SCharles.Forsyth cmap8_12 = &cmap->c.cmap8_12; 320*37da2899SCharles.Forsyth 321*37da2899SCharles.Forsyth if ( FT_FRAME_ENTER( 8L ) ) 322*37da2899SCharles.Forsyth goto Fail; 323*37da2899SCharles.Forsyth 324*37da2899SCharles.Forsyth cmap->length = FT_GET_ULONG(); 325*37da2899SCharles.Forsyth cmap8_12->language = FT_GET_ULONG(); 326*37da2899SCharles.Forsyth 327*37da2899SCharles.Forsyth FT_FRAME_EXIT(); 328*37da2899SCharles.Forsyth 329*37da2899SCharles.Forsyth if ( cmap->format == 8 ) 330*37da2899SCharles.Forsyth if ( FT_STREAM_SKIP( 8192L ) ) 331*37da2899SCharles.Forsyth goto Fail; 332*37da2899SCharles.Forsyth 333*37da2899SCharles.Forsyth if ( FT_READ_ULONG( cmap8_12->nGroups ) ) 334*37da2899SCharles.Forsyth goto Fail; 335*37da2899SCharles.Forsyth 336*37da2899SCharles.Forsyth n = cmap8_12->nGroups; 337*37da2899SCharles.Forsyth 338*37da2899SCharles.Forsyth if ( FT_NEW_ARRAY( cmap8_12->groups, n ) || 339*37da2899SCharles.Forsyth FT_FRAME_ENTER( n * 3 * 4L ) ) 340*37da2899SCharles.Forsyth goto Fail; 341*37da2899SCharles.Forsyth 342*37da2899SCharles.Forsyth groups = cmap8_12->groups; 343*37da2899SCharles.Forsyth 344*37da2899SCharles.Forsyth for ( j = 0; j < n; j++ ) 345*37da2899SCharles.Forsyth { 346*37da2899SCharles.Forsyth groups[j].startCharCode = FT_GET_ULONG(); 347*37da2899SCharles.Forsyth groups[j].endCharCode = FT_GET_ULONG(); 348*37da2899SCharles.Forsyth groups[j].startGlyphID = FT_GET_ULONG(); 349*37da2899SCharles.Forsyth } 350*37da2899SCharles.Forsyth 351*37da2899SCharles.Forsyth FT_FRAME_EXIT(); 352*37da2899SCharles.Forsyth 353*37da2899SCharles.Forsyth cmap8_12->last_group = cmap8_12->groups; 354*37da2899SCharles.Forsyth 355*37da2899SCharles.Forsyth cmap->get_index = code_to_index8_12; 356*37da2899SCharles.Forsyth cmap->get_next_char = code_to_next8_12; 357*37da2899SCharles.Forsyth break; 358*37da2899SCharles.Forsyth 359*37da2899SCharles.Forsyth case 10: 360*37da2899SCharles.Forsyth cmap10 = &cmap->c.cmap10; 361*37da2899SCharles.Forsyth 362*37da2899SCharles.Forsyth if ( FT_FRAME_ENTER( 16L ) ) 363*37da2899SCharles.Forsyth goto Fail; 364*37da2899SCharles.Forsyth 365*37da2899SCharles.Forsyth cmap->length = FT_GET_ULONG(); 366*37da2899SCharles.Forsyth cmap10->language = FT_GET_ULONG(); 367*37da2899SCharles.Forsyth cmap10->startCharCode = FT_GET_ULONG(); 368*37da2899SCharles.Forsyth cmap10->numChars = FT_GET_ULONG(); 369*37da2899SCharles.Forsyth 370*37da2899SCharles.Forsyth FT_FRAME_EXIT(); 371*37da2899SCharles.Forsyth 372*37da2899SCharles.Forsyth n = cmap10->numChars; 373*37da2899SCharles.Forsyth 374*37da2899SCharles.Forsyth if ( FT_NEW_ARRAY( cmap10->glyphs, n ) || 375*37da2899SCharles.Forsyth FT_FRAME_ENTER( n * 2L ) ) 376*37da2899SCharles.Forsyth goto Fail; 377*37da2899SCharles.Forsyth 378*37da2899SCharles.Forsyth for ( j = 0; j < n; j++ ) 379*37da2899SCharles.Forsyth cmap10->glyphs[j] = FT_GET_USHORT(); 380*37da2899SCharles.Forsyth 381*37da2899SCharles.Forsyth FT_FRAME_EXIT(); 382*37da2899SCharles.Forsyth cmap->get_index = code_to_index10; 383*37da2899SCharles.Forsyth cmap->get_next_char = code_to_next10; 384*37da2899SCharles.Forsyth break; 385*37da2899SCharles.Forsyth 386*37da2899SCharles.Forsyth default: /* corrupt character mapping table */ 387*37da2899SCharles.Forsyth return SFNT_Err_Invalid_CharMap_Format; 388*37da2899SCharles.Forsyth 389*37da2899SCharles.Forsyth } 390*37da2899SCharles.Forsyth 391*37da2899SCharles.Forsyth return SFNT_Err_Ok; 392*37da2899SCharles.Forsyth 393*37da2899SCharles.Forsyth Fail: 394*37da2899SCharles.Forsyth tt_face_free_charmap( face, cmap ); 395*37da2899SCharles.Forsyth return error; 396*37da2899SCharles.Forsyth } 397*37da2899SCharles.Forsyth 398*37da2899SCharles.Forsyth 399*37da2899SCharles.Forsyth /*************************************************************************/ 400*37da2899SCharles.Forsyth /* */ 401*37da2899SCharles.Forsyth /* <Function> */ 402*37da2899SCharles.Forsyth /* tt_face_free_charmap */ 403*37da2899SCharles.Forsyth /* */ 404*37da2899SCharles.Forsyth /* <Description> */ 405*37da2899SCharles.Forsyth /* Destroys a character mapping table. */ 406*37da2899SCharles.Forsyth /* */ 407*37da2899SCharles.Forsyth /* <Input> */ 408*37da2899SCharles.Forsyth /* face :: A handle to the parent face object. */ 409*37da2899SCharles.Forsyth /* */ 410*37da2899SCharles.Forsyth /* cmap :: A handle to a cmap object. */ 411*37da2899SCharles.Forsyth /* */ 412*37da2899SCharles.Forsyth /* <Return> */ 413*37da2899SCharles.Forsyth /* FreeType error code. 0 means success. */ 414*37da2899SCharles.Forsyth /* */ 415*37da2899SCharles.Forsyth FT_LOCAL_DEF( FT_Error ) tt_face_free_charmap(TT_Face face,TT_CMapTable cmap)416*37da2899SCharles.Forsyth tt_face_free_charmap( TT_Face face, 417*37da2899SCharles.Forsyth TT_CMapTable cmap ) 418*37da2899SCharles.Forsyth { 419*37da2899SCharles.Forsyth FT_Memory memory; 420*37da2899SCharles.Forsyth 421*37da2899SCharles.Forsyth 422*37da2899SCharles.Forsyth if ( !cmap ) 423*37da2899SCharles.Forsyth return SFNT_Err_Ok; 424*37da2899SCharles.Forsyth 425*37da2899SCharles.Forsyth memory = face->root.driver->root.memory; 426*37da2899SCharles.Forsyth 427*37da2899SCharles.Forsyth switch ( cmap->format ) 428*37da2899SCharles.Forsyth { 429*37da2899SCharles.Forsyth case 0: 430*37da2899SCharles.Forsyth FT_FREE( cmap->c.cmap0.glyphIdArray ); 431*37da2899SCharles.Forsyth break; 432*37da2899SCharles.Forsyth 433*37da2899SCharles.Forsyth case 2: 434*37da2899SCharles.Forsyth FT_FREE( cmap->c.cmap2.subHeaderKeys ); 435*37da2899SCharles.Forsyth FT_FREE( cmap->c.cmap2.subHeaders ); 436*37da2899SCharles.Forsyth FT_FREE( cmap->c.cmap2.glyphIdArray ); 437*37da2899SCharles.Forsyth break; 438*37da2899SCharles.Forsyth 439*37da2899SCharles.Forsyth case 4: 440*37da2899SCharles.Forsyth FT_FREE( cmap->c.cmap4.segments ); 441*37da2899SCharles.Forsyth FT_FREE( cmap->c.cmap4.glyphIdArray ); 442*37da2899SCharles.Forsyth cmap->c.cmap4.segCountX2 = 0; 443*37da2899SCharles.Forsyth break; 444*37da2899SCharles.Forsyth 445*37da2899SCharles.Forsyth case 6: 446*37da2899SCharles.Forsyth FT_FREE( cmap->c.cmap6.glyphIdArray ); 447*37da2899SCharles.Forsyth cmap->c.cmap6.entryCount = 0; 448*37da2899SCharles.Forsyth break; 449*37da2899SCharles.Forsyth 450*37da2899SCharles.Forsyth case 8: 451*37da2899SCharles.Forsyth case 12: 452*37da2899SCharles.Forsyth FT_FREE( cmap->c.cmap8_12.groups ); 453*37da2899SCharles.Forsyth cmap->c.cmap8_12.nGroups = 0; 454*37da2899SCharles.Forsyth break; 455*37da2899SCharles.Forsyth 456*37da2899SCharles.Forsyth case 10: 457*37da2899SCharles.Forsyth FT_FREE( cmap->c.cmap10.glyphs ); 458*37da2899SCharles.Forsyth cmap->c.cmap10.numChars = 0; 459*37da2899SCharles.Forsyth break; 460*37da2899SCharles.Forsyth 461*37da2899SCharles.Forsyth default: 462*37da2899SCharles.Forsyth /* invalid table format, do nothing */ 463*37da2899SCharles.Forsyth ; 464*37da2899SCharles.Forsyth } 465*37da2899SCharles.Forsyth 466*37da2899SCharles.Forsyth cmap->loaded = FALSE; 467*37da2899SCharles.Forsyth return SFNT_Err_Ok; 468*37da2899SCharles.Forsyth } 469*37da2899SCharles.Forsyth 470*37da2899SCharles.Forsyth 471*37da2899SCharles.Forsyth /*************************************************************************/ 472*37da2899SCharles.Forsyth /* */ 473*37da2899SCharles.Forsyth /* <Function> */ 474*37da2899SCharles.Forsyth /* code_to_index0 */ 475*37da2899SCharles.Forsyth /* */ 476*37da2899SCharles.Forsyth /* <Description> */ 477*37da2899SCharles.Forsyth /* Converts the character code into a glyph index. Uses format 0. */ 478*37da2899SCharles.Forsyth /* `charCode' must be in the range 0x00-0xFF (otherwise 0 is */ 479*37da2899SCharles.Forsyth /* returned). */ 480*37da2899SCharles.Forsyth /* */ 481*37da2899SCharles.Forsyth /* <Input> */ 482*37da2899SCharles.Forsyth /* charCode :: The wanted character code. */ 483*37da2899SCharles.Forsyth /* */ 484*37da2899SCharles.Forsyth /* cmap0 :: A pointer to a cmap table in format 0. */ 485*37da2899SCharles.Forsyth /* */ 486*37da2899SCharles.Forsyth /* <Return> */ 487*37da2899SCharles.Forsyth /* Glyph index into the glyphs array. 0 if the glyph does not exist. */ 488*37da2899SCharles.Forsyth /* */ 489*37da2899SCharles.Forsyth FT_CALLBACK_DEF( FT_UInt ) code_to_index0(TT_CMapTable cmap,FT_ULong charCode)490*37da2899SCharles.Forsyth code_to_index0( TT_CMapTable cmap, 491*37da2899SCharles.Forsyth FT_ULong charCode ) 492*37da2899SCharles.Forsyth { 493*37da2899SCharles.Forsyth TT_CMap0 cmap0 = &cmap->c.cmap0; 494*37da2899SCharles.Forsyth 495*37da2899SCharles.Forsyth 496*37da2899SCharles.Forsyth return ( charCode <= 0xFF ? cmap0->glyphIdArray[charCode] : 0 ); 497*37da2899SCharles.Forsyth } 498*37da2899SCharles.Forsyth 499*37da2899SCharles.Forsyth 500*37da2899SCharles.Forsyth /*************************************************************************/ 501*37da2899SCharles.Forsyth /* */ 502*37da2899SCharles.Forsyth /* <Function> */ 503*37da2899SCharles.Forsyth /* code_to_next0 */ 504*37da2899SCharles.Forsyth /* */ 505*37da2899SCharles.Forsyth /* <Description> */ 506*37da2899SCharles.Forsyth /* Finds the next encoded character after the given one. Uses */ 507*37da2899SCharles.Forsyth /* format 0. `charCode' must be in the range 0x00-0xFF (otherwise 0 */ 508*37da2899SCharles.Forsyth /* is returned). */ 509*37da2899SCharles.Forsyth /* */ 510*37da2899SCharles.Forsyth /* <Input> */ 511*37da2899SCharles.Forsyth /* charCode :: The wanted character code. */ 512*37da2899SCharles.Forsyth /* */ 513*37da2899SCharles.Forsyth /* cmap0 :: A pointer to a cmap table in format 0. */ 514*37da2899SCharles.Forsyth /* */ 515*37da2899SCharles.Forsyth /* <Return> */ 516*37da2899SCharles.Forsyth /* Next char code. 0 if no higher one is encoded. */ 517*37da2899SCharles.Forsyth /* */ 518*37da2899SCharles.Forsyth FT_CALLBACK_DEF( FT_ULong ) code_to_next0(TT_CMapTable cmap,FT_ULong charCode)519*37da2899SCharles.Forsyth code_to_next0( TT_CMapTable cmap, 520*37da2899SCharles.Forsyth FT_ULong charCode ) 521*37da2899SCharles.Forsyth { 522*37da2899SCharles.Forsyth TT_CMap0 cmap0 = &cmap->c.cmap0; 523*37da2899SCharles.Forsyth 524*37da2899SCharles.Forsyth 525*37da2899SCharles.Forsyth while ( ++charCode <= 0xFF ) 526*37da2899SCharles.Forsyth if ( cmap0->glyphIdArray[charCode] ) 527*37da2899SCharles.Forsyth return ( charCode ); 528*37da2899SCharles.Forsyth return ( 0 ); 529*37da2899SCharles.Forsyth } 530*37da2899SCharles.Forsyth 531*37da2899SCharles.Forsyth 532*37da2899SCharles.Forsyth /*************************************************************************/ 533*37da2899SCharles.Forsyth /* */ 534*37da2899SCharles.Forsyth /* <Function> */ 535*37da2899SCharles.Forsyth /* code_to_index2 */ 536*37da2899SCharles.Forsyth /* */ 537*37da2899SCharles.Forsyth /* <Description> */ 538*37da2899SCharles.Forsyth /* Converts the character code into a glyph index. Uses format 2. */ 539*37da2899SCharles.Forsyth /* */ 540*37da2899SCharles.Forsyth /* <Input> */ 541*37da2899SCharles.Forsyth /* charCode :: The wanted character code. */ 542*37da2899SCharles.Forsyth /* */ 543*37da2899SCharles.Forsyth /* cmap2 :: A pointer to a cmap table in format 2. */ 544*37da2899SCharles.Forsyth /* */ 545*37da2899SCharles.Forsyth /* <Return> */ 546*37da2899SCharles.Forsyth /* Glyph index into the glyphs array. 0 if the glyph does not exist. */ 547*37da2899SCharles.Forsyth /* */ 548*37da2899SCharles.Forsyth FT_CALLBACK_DEF( FT_UInt ) code_to_index2(TT_CMapTable cmap,FT_ULong charCode)549*37da2899SCharles.Forsyth code_to_index2( TT_CMapTable cmap, 550*37da2899SCharles.Forsyth FT_ULong charCode ) 551*37da2899SCharles.Forsyth { 552*37da2899SCharles.Forsyth FT_UInt result, index1, offset; 553*37da2899SCharles.Forsyth FT_UInt char_lo; 554*37da2899SCharles.Forsyth FT_ULong char_hi; 555*37da2899SCharles.Forsyth TT_CMap2SubHeader sh2; 556*37da2899SCharles.Forsyth TT_CMap2 cmap2; 557*37da2899SCharles.Forsyth 558*37da2899SCharles.Forsyth 559*37da2899SCharles.Forsyth cmap2 = &cmap->c.cmap2; 560*37da2899SCharles.Forsyth result = 0; 561*37da2899SCharles.Forsyth char_lo = (FT_UInt)( charCode & 0xFF ); 562*37da2899SCharles.Forsyth char_hi = charCode >> 8; 563*37da2899SCharles.Forsyth 564*37da2899SCharles.Forsyth if ( char_hi == 0 ) 565*37da2899SCharles.Forsyth { 566*37da2899SCharles.Forsyth /* an 8-bit character code -- we use the subHeader 0 in this case */ 567*37da2899SCharles.Forsyth /* to test whether the character code is in the charmap */ 568*37da2899SCharles.Forsyth index1 = cmap2->subHeaderKeys[char_lo]; 569*37da2899SCharles.Forsyth if ( index1 != 0 ) 570*37da2899SCharles.Forsyth return 0; 571*37da2899SCharles.Forsyth } 572*37da2899SCharles.Forsyth else 573*37da2899SCharles.Forsyth { 574*37da2899SCharles.Forsyth /* a 16-bit character code */ 575*37da2899SCharles.Forsyth index1 = cmap2->subHeaderKeys[char_hi & 0xFF]; 576*37da2899SCharles.Forsyth if ( index1 == 0 ) 577*37da2899SCharles.Forsyth return 0; 578*37da2899SCharles.Forsyth } 579*37da2899SCharles.Forsyth 580*37da2899SCharles.Forsyth sh2 = cmap2->subHeaders + index1; 581*37da2899SCharles.Forsyth char_lo -= sh2->firstCode; 582*37da2899SCharles.Forsyth 583*37da2899SCharles.Forsyth if ( char_lo < (FT_UInt)sh2->entryCount ) 584*37da2899SCharles.Forsyth { 585*37da2899SCharles.Forsyth offset = sh2->idRangeOffset / 2 + char_lo; 586*37da2899SCharles.Forsyth if ( offset < (FT_UInt)cmap2->numGlyphId ) 587*37da2899SCharles.Forsyth { 588*37da2899SCharles.Forsyth result = cmap2->glyphIdArray[offset]; 589*37da2899SCharles.Forsyth if ( result ) 590*37da2899SCharles.Forsyth result = ( result + sh2->idDelta ) & 0xFFFFU; 591*37da2899SCharles.Forsyth } 592*37da2899SCharles.Forsyth } 593*37da2899SCharles.Forsyth 594*37da2899SCharles.Forsyth return result; 595*37da2899SCharles.Forsyth } 596*37da2899SCharles.Forsyth 597*37da2899SCharles.Forsyth 598*37da2899SCharles.Forsyth /*************************************************************************/ 599*37da2899SCharles.Forsyth /* */ 600*37da2899SCharles.Forsyth /* <Function> */ 601*37da2899SCharles.Forsyth /* code_to_next2 */ 602*37da2899SCharles.Forsyth /* */ 603*37da2899SCharles.Forsyth /* <Description> */ 604*37da2899SCharles.Forsyth /* Find the next encoded character. Uses format 2. */ 605*37da2899SCharles.Forsyth /* */ 606*37da2899SCharles.Forsyth /* <Input> */ 607*37da2899SCharles.Forsyth /* charCode :: The wanted character code. */ 608*37da2899SCharles.Forsyth /* */ 609*37da2899SCharles.Forsyth /* cmap2 :: A pointer to a cmap table in format 2. */ 610*37da2899SCharles.Forsyth /* */ 611*37da2899SCharles.Forsyth /* <Return> */ 612*37da2899SCharles.Forsyth /* Next encoded character. 0 if none exists. */ 613*37da2899SCharles.Forsyth /* */ 614*37da2899SCharles.Forsyth FT_CALLBACK_DEF( FT_ULong ) code_to_next2(TT_CMapTable cmap,FT_ULong charCode)615*37da2899SCharles.Forsyth code_to_next2( TT_CMapTable cmap, 616*37da2899SCharles.Forsyth FT_ULong charCode ) 617*37da2899SCharles.Forsyth { 618*37da2899SCharles.Forsyth FT_UInt index1, offset; 619*37da2899SCharles.Forsyth FT_UInt char_lo; 620*37da2899SCharles.Forsyth FT_ULong char_hi; 621*37da2899SCharles.Forsyth TT_CMap2SubHeader sh2; 622*37da2899SCharles.Forsyth TT_CMap2 cmap2; 623*37da2899SCharles.Forsyth 624*37da2899SCharles.Forsyth 625*37da2899SCharles.Forsyth cmap2 = &cmap->c.cmap2; 626*37da2899SCharles.Forsyth charCode++; 627*37da2899SCharles.Forsyth 628*37da2899SCharles.Forsyth /* 629*37da2899SCharles.Forsyth * This is relatively simplistic -- look for a subHeader containing 630*37da2899SCharles.Forsyth * glyphs and then walk to the first glyph in that subHeader. 631*37da2899SCharles.Forsyth */ 632*37da2899SCharles.Forsyth while ( charCode < 0x10000L ) 633*37da2899SCharles.Forsyth { 634*37da2899SCharles.Forsyth char_lo = (FT_UInt)( charCode & 0xFF ); 635*37da2899SCharles.Forsyth char_hi = charCode >> 8; 636*37da2899SCharles.Forsyth 637*37da2899SCharles.Forsyth if ( char_hi == 0 ) 638*37da2899SCharles.Forsyth { 639*37da2899SCharles.Forsyth /* an 8-bit character code -- we use the subHeader 0 in this case */ 640*37da2899SCharles.Forsyth /* to test whether the character code is in the charmap */ 641*37da2899SCharles.Forsyth index1 = cmap2->subHeaderKeys[char_lo]; 642*37da2899SCharles.Forsyth if ( index1 != 0 ) 643*37da2899SCharles.Forsyth { 644*37da2899SCharles.Forsyth charCode++; 645*37da2899SCharles.Forsyth continue; 646*37da2899SCharles.Forsyth } 647*37da2899SCharles.Forsyth } 648*37da2899SCharles.Forsyth else 649*37da2899SCharles.Forsyth { 650*37da2899SCharles.Forsyth /* a 16-bit character code */ 651*37da2899SCharles.Forsyth index1 = cmap2->subHeaderKeys[char_hi & 0xFF]; 652*37da2899SCharles.Forsyth if ( index1 == 0 ) 653*37da2899SCharles.Forsyth { 654*37da2899SCharles.Forsyth charCode = ( char_hi + 1 ) << 8; 655*37da2899SCharles.Forsyth continue; 656*37da2899SCharles.Forsyth } 657*37da2899SCharles.Forsyth } 658*37da2899SCharles.Forsyth 659*37da2899SCharles.Forsyth sh2 = cmap2->subHeaders + index1; 660*37da2899SCharles.Forsyth char_lo -= sh2->firstCode; 661*37da2899SCharles.Forsyth 662*37da2899SCharles.Forsyth if ( char_lo > (FT_UInt)sh2->entryCount ) 663*37da2899SCharles.Forsyth { 664*37da2899SCharles.Forsyth charCode = ( char_hi + 1 ) << 8; 665*37da2899SCharles.Forsyth continue; 666*37da2899SCharles.Forsyth } 667*37da2899SCharles.Forsyth 668*37da2899SCharles.Forsyth offset = sh2->idRangeOffset / 2 + char_lo; 669*37da2899SCharles.Forsyth if ( offset >= (FT_UInt)cmap2->numGlyphId || 670*37da2899SCharles.Forsyth cmap2->glyphIdArray[offset] == 0 ) 671*37da2899SCharles.Forsyth { 672*37da2899SCharles.Forsyth charCode++; 673*37da2899SCharles.Forsyth continue; 674*37da2899SCharles.Forsyth } 675*37da2899SCharles.Forsyth 676*37da2899SCharles.Forsyth return charCode; 677*37da2899SCharles.Forsyth } 678*37da2899SCharles.Forsyth return 0; 679*37da2899SCharles.Forsyth } 680*37da2899SCharles.Forsyth 681*37da2899SCharles.Forsyth 682*37da2899SCharles.Forsyth /*************************************************************************/ 683*37da2899SCharles.Forsyth /* */ 684*37da2899SCharles.Forsyth /* <Function> */ 685*37da2899SCharles.Forsyth /* code_to_index4 */ 686*37da2899SCharles.Forsyth /* */ 687*37da2899SCharles.Forsyth /* <Description> */ 688*37da2899SCharles.Forsyth /* Converts the character code into a glyph index. Uses format 4. */ 689*37da2899SCharles.Forsyth /* */ 690*37da2899SCharles.Forsyth /* <Input> */ 691*37da2899SCharles.Forsyth /* charCode :: The wanted character code. */ 692*37da2899SCharles.Forsyth /* */ 693*37da2899SCharles.Forsyth /* cmap4 :: A pointer to a cmap table in format 4. */ 694*37da2899SCharles.Forsyth /* */ 695*37da2899SCharles.Forsyth /* <Return> */ 696*37da2899SCharles.Forsyth /* Glyph index into the glyphs array. 0 if the glyph does not exist. */ 697*37da2899SCharles.Forsyth /* */ 698*37da2899SCharles.Forsyth FT_CALLBACK_DEF( FT_UInt ) code_to_index4(TT_CMapTable cmap,FT_ULong charCode)699*37da2899SCharles.Forsyth code_to_index4( TT_CMapTable cmap, 700*37da2899SCharles.Forsyth FT_ULong charCode ) 701*37da2899SCharles.Forsyth { 702*37da2899SCharles.Forsyth FT_UInt result, index1, segCount; 703*37da2899SCharles.Forsyth TT_CMap4 cmap4; 704*37da2899SCharles.Forsyth TT_CMap4SegmentRec *seg4, *limit; 705*37da2899SCharles.Forsyth 706*37da2899SCharles.Forsyth 707*37da2899SCharles.Forsyth cmap4 = &cmap->c.cmap4; 708*37da2899SCharles.Forsyth result = 0; 709*37da2899SCharles.Forsyth segCount = cmap4->segCountX2 / 2; 710*37da2899SCharles.Forsyth limit = cmap4->segments + segCount; 711*37da2899SCharles.Forsyth 712*37da2899SCharles.Forsyth /* first, check against the last used segment */ 713*37da2899SCharles.Forsyth 714*37da2899SCharles.Forsyth seg4 = cmap4->last_segment; 715*37da2899SCharles.Forsyth 716*37da2899SCharles.Forsyth /* the following is equivalent to performing two tests, as in */ 717*37da2899SCharles.Forsyth /* */ 718*37da2899SCharles.Forsyth /* if ( charCode >= seg4->startCount && charCode <= seg4->endCount ) */ 719*37da2899SCharles.Forsyth /* */ 720*37da2899SCharles.Forsyth /* This is a bit strange, but it is faster, and the idea behind the */ 721*37da2899SCharles.Forsyth /* cache is to significantly speed up charcode to glyph index */ 722*37da2899SCharles.Forsyth /* conversion. */ 723*37da2899SCharles.Forsyth 724*37da2899SCharles.Forsyth if ( (FT_ULong)( charCode - seg4->startCount ) < 725*37da2899SCharles.Forsyth (FT_ULong)( seg4->endCount - seg4->startCount ) ) 726*37da2899SCharles.Forsyth goto Found1; 727*37da2899SCharles.Forsyth 728*37da2899SCharles.Forsyth for ( seg4 = cmap4->segments; seg4 < limit; seg4++ ) 729*37da2899SCharles.Forsyth { 730*37da2899SCharles.Forsyth /* the ranges are sorted in increasing order. If we are out of */ 731*37da2899SCharles.Forsyth /* the range here, the char code isn't in the charmap, so exit. */ 732*37da2899SCharles.Forsyth 733*37da2899SCharles.Forsyth if ( charCode > (FT_UInt)seg4->endCount ) 734*37da2899SCharles.Forsyth continue; 735*37da2899SCharles.Forsyth 736*37da2899SCharles.Forsyth if ( charCode >= (FT_UInt)seg4->startCount ) 737*37da2899SCharles.Forsyth goto Found; 738*37da2899SCharles.Forsyth } 739*37da2899SCharles.Forsyth return 0; 740*37da2899SCharles.Forsyth 741*37da2899SCharles.Forsyth Found: 742*37da2899SCharles.Forsyth cmap4->last_segment = seg4; 743*37da2899SCharles.Forsyth 744*37da2899SCharles.Forsyth Found1: 745*37da2899SCharles.Forsyth /* if the idRangeOffset is 0, we can compute the glyph index */ 746*37da2899SCharles.Forsyth /* directly */ 747*37da2899SCharles.Forsyth 748*37da2899SCharles.Forsyth if ( seg4->idRangeOffset == 0 ) 749*37da2899SCharles.Forsyth result = (FT_UInt)( charCode + seg4->idDelta ) & 0xFFFFU; 750*37da2899SCharles.Forsyth else 751*37da2899SCharles.Forsyth { 752*37da2899SCharles.Forsyth /* otherwise, we must use the glyphIdArray to do it */ 753*37da2899SCharles.Forsyth index1 = (FT_UInt)( seg4->idRangeOffset / 2 754*37da2899SCharles.Forsyth + ( charCode - seg4->startCount ) 755*37da2899SCharles.Forsyth + ( seg4 - cmap4->segments ) 756*37da2899SCharles.Forsyth - segCount ); 757*37da2899SCharles.Forsyth 758*37da2899SCharles.Forsyth if ( index1 < (FT_UInt)cmap4->numGlyphId && 759*37da2899SCharles.Forsyth cmap4->glyphIdArray[index1] != 0 ) 760*37da2899SCharles.Forsyth result = ( cmap4->glyphIdArray[index1] + seg4->idDelta ) & 0xFFFFU; 761*37da2899SCharles.Forsyth } 762*37da2899SCharles.Forsyth 763*37da2899SCharles.Forsyth return result; 764*37da2899SCharles.Forsyth } 765*37da2899SCharles.Forsyth 766*37da2899SCharles.Forsyth 767*37da2899SCharles.Forsyth /*************************************************************************/ 768*37da2899SCharles.Forsyth /* */ 769*37da2899SCharles.Forsyth /* <Function> */ 770*37da2899SCharles.Forsyth /* code_to_next4 */ 771*37da2899SCharles.Forsyth /* */ 772*37da2899SCharles.Forsyth /* <Description> */ 773*37da2899SCharles.Forsyth /* Find the next encoded character. Uses format 4. */ 774*37da2899SCharles.Forsyth /* */ 775*37da2899SCharles.Forsyth /* <Input> */ 776*37da2899SCharles.Forsyth /* charCode :: The wanted character code. */ 777*37da2899SCharles.Forsyth /* */ 778*37da2899SCharles.Forsyth /* cmap :: A pointer to a cmap table in format 4. */ 779*37da2899SCharles.Forsyth /* */ 780*37da2899SCharles.Forsyth /* <Return> */ 781*37da2899SCharles.Forsyth /* Next encoded character. 0 if none exists. */ 782*37da2899SCharles.Forsyth /* */ 783*37da2899SCharles.Forsyth FT_CALLBACK_DEF( FT_ULong ) code_to_next4(TT_CMapTable cmap,FT_ULong charCode)784*37da2899SCharles.Forsyth code_to_next4( TT_CMapTable cmap, 785*37da2899SCharles.Forsyth FT_ULong charCode ) 786*37da2899SCharles.Forsyth { 787*37da2899SCharles.Forsyth FT_UInt index1, segCount; 788*37da2899SCharles.Forsyth TT_CMap4 cmap4; 789*37da2899SCharles.Forsyth TT_CMap4SegmentRec *seg4, *limit; 790*37da2899SCharles.Forsyth 791*37da2899SCharles.Forsyth 792*37da2899SCharles.Forsyth cmap4 = &cmap->c.cmap4; 793*37da2899SCharles.Forsyth segCount = cmap4->segCountX2 / 2; 794*37da2899SCharles.Forsyth limit = cmap4->segments + segCount; 795*37da2899SCharles.Forsyth 796*37da2899SCharles.Forsyth charCode++; 797*37da2899SCharles.Forsyth 798*37da2899SCharles.Forsyth for ( seg4 = cmap4->segments; seg4 < limit; seg4++ ) 799*37da2899SCharles.Forsyth { 800*37da2899SCharles.Forsyth /* The ranges are sorted in increasing order. If we are out of */ 801*37da2899SCharles.Forsyth /* the range here, the char code isn't in the charmap, so exit. */ 802*37da2899SCharles.Forsyth 803*37da2899SCharles.Forsyth if ( charCode <= (FT_UInt)seg4->endCount ) 804*37da2899SCharles.Forsyth goto Found; 805*37da2899SCharles.Forsyth } 806*37da2899SCharles.Forsyth return 0; 807*37da2899SCharles.Forsyth 808*37da2899SCharles.Forsyth Found: 809*37da2899SCharles.Forsyth if ( charCode < (FT_ULong) seg4->startCount ) 810*37da2899SCharles.Forsyth charCode = seg4->startCount; 811*37da2899SCharles.Forsyth 812*37da2899SCharles.Forsyth /* if the idRangeOffset is 0, all chars in the map exist */ 813*37da2899SCharles.Forsyth 814*37da2899SCharles.Forsyth if ( seg4->idRangeOffset == 0 ) 815*37da2899SCharles.Forsyth return ( charCode ); 816*37da2899SCharles.Forsyth 817*37da2899SCharles.Forsyth while ( charCode <= (FT_UInt) seg4->endCount ) 818*37da2899SCharles.Forsyth { 819*37da2899SCharles.Forsyth /* otherwise, we must use the glyphIdArray to do it */ 820*37da2899SCharles.Forsyth index1 = (FT_UInt)( seg4->idRangeOffset / 2 821*37da2899SCharles.Forsyth + ( charCode - seg4->startCount ) 822*37da2899SCharles.Forsyth + ( seg4 - cmap4->segments ) 823*37da2899SCharles.Forsyth - segCount ); 824*37da2899SCharles.Forsyth 825*37da2899SCharles.Forsyth if ( index1 < (FT_UInt)cmap4->numGlyphId && 826*37da2899SCharles.Forsyth cmap4->glyphIdArray[index1] != 0 ) 827*37da2899SCharles.Forsyth return ( charCode ); 828*37da2899SCharles.Forsyth charCode++; 829*37da2899SCharles.Forsyth } 830*37da2899SCharles.Forsyth 831*37da2899SCharles.Forsyth return 0; 832*37da2899SCharles.Forsyth } 833*37da2899SCharles.Forsyth 834*37da2899SCharles.Forsyth 835*37da2899SCharles.Forsyth /*************************************************************************/ 836*37da2899SCharles.Forsyth /* */ 837*37da2899SCharles.Forsyth /* <Function> */ 838*37da2899SCharles.Forsyth /* code_to_index6 */ 839*37da2899SCharles.Forsyth /* */ 840*37da2899SCharles.Forsyth /* <Description> */ 841*37da2899SCharles.Forsyth /* Converts the character code into a glyph index. Uses format 6. */ 842*37da2899SCharles.Forsyth /* */ 843*37da2899SCharles.Forsyth /* <Input> */ 844*37da2899SCharles.Forsyth /* charCode :: The wanted character code. */ 845*37da2899SCharles.Forsyth /* */ 846*37da2899SCharles.Forsyth /* cmap6 :: A pointer to a cmap table in format 6. */ 847*37da2899SCharles.Forsyth /* */ 848*37da2899SCharles.Forsyth /* <Return> */ 849*37da2899SCharles.Forsyth /* Glyph index into the glyphs array. 0 if the glyph does not exist. */ 850*37da2899SCharles.Forsyth /* */ 851*37da2899SCharles.Forsyth FT_CALLBACK_DEF( FT_UInt ) code_to_index6(TT_CMapTable cmap,FT_ULong charCode)852*37da2899SCharles.Forsyth code_to_index6( TT_CMapTable cmap, 853*37da2899SCharles.Forsyth FT_ULong charCode ) 854*37da2899SCharles.Forsyth { 855*37da2899SCharles.Forsyth TT_CMap6 cmap6; 856*37da2899SCharles.Forsyth FT_UInt result = 0; 857*37da2899SCharles.Forsyth 858*37da2899SCharles.Forsyth 859*37da2899SCharles.Forsyth cmap6 = &cmap->c.cmap6; 860*37da2899SCharles.Forsyth charCode -= cmap6->firstCode; 861*37da2899SCharles.Forsyth 862*37da2899SCharles.Forsyth if ( charCode < (FT_UInt)cmap6->entryCount ) 863*37da2899SCharles.Forsyth result = cmap6->glyphIdArray[charCode]; 864*37da2899SCharles.Forsyth 865*37da2899SCharles.Forsyth return result; 866*37da2899SCharles.Forsyth } 867*37da2899SCharles.Forsyth 868*37da2899SCharles.Forsyth 869*37da2899SCharles.Forsyth /*************************************************************************/ 870*37da2899SCharles.Forsyth /* */ 871*37da2899SCharles.Forsyth /* <Function> */ 872*37da2899SCharles.Forsyth /* code_to_next6 */ 873*37da2899SCharles.Forsyth /* */ 874*37da2899SCharles.Forsyth /* <Description> */ 875*37da2899SCharles.Forsyth /* Find the next encoded character. Uses format 6. */ 876*37da2899SCharles.Forsyth /* */ 877*37da2899SCharles.Forsyth /* <Input> */ 878*37da2899SCharles.Forsyth /* charCode :: The wanted character code. */ 879*37da2899SCharles.Forsyth /* */ 880*37da2899SCharles.Forsyth /* cmap :: A pointer to a cmap table in format 6. */ 881*37da2899SCharles.Forsyth /* */ 882*37da2899SCharles.Forsyth /* <Return> */ 883*37da2899SCharles.Forsyth /* Next encoded character. 0 if none exists. */ 884*37da2899SCharles.Forsyth /* */ 885*37da2899SCharles.Forsyth FT_CALLBACK_DEF( FT_ULong ) code_to_next6(TT_CMapTable cmap,FT_ULong charCode)886*37da2899SCharles.Forsyth code_to_next6( TT_CMapTable cmap, 887*37da2899SCharles.Forsyth FT_ULong charCode ) 888*37da2899SCharles.Forsyth { 889*37da2899SCharles.Forsyth TT_CMap6 cmap6; 890*37da2899SCharles.Forsyth 891*37da2899SCharles.Forsyth 892*37da2899SCharles.Forsyth charCode++; 893*37da2899SCharles.Forsyth 894*37da2899SCharles.Forsyth cmap6 = &cmap->c.cmap6; 895*37da2899SCharles.Forsyth 896*37da2899SCharles.Forsyth if ( charCode < (FT_ULong) cmap6->firstCode ) 897*37da2899SCharles.Forsyth charCode = cmap6->firstCode; 898*37da2899SCharles.Forsyth 899*37da2899SCharles.Forsyth charCode -= cmap6->firstCode; 900*37da2899SCharles.Forsyth 901*37da2899SCharles.Forsyth while ( charCode < (FT_UInt)cmap6->entryCount ) 902*37da2899SCharles.Forsyth { 903*37da2899SCharles.Forsyth if ( cmap6->glyphIdArray[charCode] != 0 ) 904*37da2899SCharles.Forsyth return charCode + cmap6->firstCode; 905*37da2899SCharles.Forsyth charCode++; 906*37da2899SCharles.Forsyth } 907*37da2899SCharles.Forsyth 908*37da2899SCharles.Forsyth return 0; 909*37da2899SCharles.Forsyth } 910*37da2899SCharles.Forsyth 911*37da2899SCharles.Forsyth 912*37da2899SCharles.Forsyth /*************************************************************************/ 913*37da2899SCharles.Forsyth /* */ 914*37da2899SCharles.Forsyth /* <Function> */ 915*37da2899SCharles.Forsyth /* code_to_index8_12 */ 916*37da2899SCharles.Forsyth /* */ 917*37da2899SCharles.Forsyth /* <Description> */ 918*37da2899SCharles.Forsyth /* Converts the (possibly 32bit) character code into a glyph index. */ 919*37da2899SCharles.Forsyth /* Uses format 8 or 12. */ 920*37da2899SCharles.Forsyth /* */ 921*37da2899SCharles.Forsyth /* <Input> */ 922*37da2899SCharles.Forsyth /* charCode :: The wanted character code. */ 923*37da2899SCharles.Forsyth /* */ 924*37da2899SCharles.Forsyth /* cmap8_12 :: A pointer to a cmap table in format 8 or 12. */ 925*37da2899SCharles.Forsyth /* */ 926*37da2899SCharles.Forsyth /* <Return> */ 927*37da2899SCharles.Forsyth /* Glyph index into the glyphs array. 0 if the glyph does not exist. */ 928*37da2899SCharles.Forsyth /* */ 929*37da2899SCharles.Forsyth FT_CALLBACK_DEF( FT_UInt ) code_to_index8_12(TT_CMapTable cmap,FT_ULong charCode)930*37da2899SCharles.Forsyth code_to_index8_12( TT_CMapTable cmap, 931*37da2899SCharles.Forsyth FT_ULong charCode ) 932*37da2899SCharles.Forsyth { 933*37da2899SCharles.Forsyth TT_CMap8_12 cmap8_12; 934*37da2899SCharles.Forsyth TT_CMapGroupRec *group, *limit; 935*37da2899SCharles.Forsyth 936*37da2899SCharles.Forsyth 937*37da2899SCharles.Forsyth cmap8_12 = &cmap->c.cmap8_12; 938*37da2899SCharles.Forsyth limit = cmap8_12->groups + cmap8_12->nGroups; 939*37da2899SCharles.Forsyth 940*37da2899SCharles.Forsyth /* first, check against the last used group */ 941*37da2899SCharles.Forsyth 942*37da2899SCharles.Forsyth group = cmap8_12->last_group; 943*37da2899SCharles.Forsyth 944*37da2899SCharles.Forsyth /* the following is equivalent to performing two tests, as in */ 945*37da2899SCharles.Forsyth /* */ 946*37da2899SCharles.Forsyth /* if ( charCode >= group->startCharCode && */ 947*37da2899SCharles.Forsyth /* charCode <= group->endCharCode ) */ 948*37da2899SCharles.Forsyth /* */ 949*37da2899SCharles.Forsyth /* This is a bit strange, but it is faster, and the idea behind the */ 950*37da2899SCharles.Forsyth /* cache is to significantly speed up charcode to glyph index */ 951*37da2899SCharles.Forsyth /* conversion. */ 952*37da2899SCharles.Forsyth 953*37da2899SCharles.Forsyth if ( (FT_ULong)( charCode - group->startCharCode ) < 954*37da2899SCharles.Forsyth (FT_ULong)( group->endCharCode - group->startCharCode ) ) 955*37da2899SCharles.Forsyth goto Found1; 956*37da2899SCharles.Forsyth 957*37da2899SCharles.Forsyth for ( group = cmap8_12->groups; group < limit; group++ ) 958*37da2899SCharles.Forsyth { 959*37da2899SCharles.Forsyth /* the ranges are sorted in increasing order. If we are out of */ 960*37da2899SCharles.Forsyth /* the range here, the char code isn't in the charmap, so exit. */ 961*37da2899SCharles.Forsyth 962*37da2899SCharles.Forsyth if ( charCode > group->endCharCode ) 963*37da2899SCharles.Forsyth continue; 964*37da2899SCharles.Forsyth 965*37da2899SCharles.Forsyth if ( charCode >= group->startCharCode ) 966*37da2899SCharles.Forsyth goto Found; 967*37da2899SCharles.Forsyth } 968*37da2899SCharles.Forsyth return 0; 969*37da2899SCharles.Forsyth 970*37da2899SCharles.Forsyth Found: 971*37da2899SCharles.Forsyth cmap8_12->last_group = group; 972*37da2899SCharles.Forsyth 973*37da2899SCharles.Forsyth Found1: 974*37da2899SCharles.Forsyth return (FT_UInt)( group->startGlyphID + 975*37da2899SCharles.Forsyth ( charCode - group->startCharCode ) ); 976*37da2899SCharles.Forsyth } 977*37da2899SCharles.Forsyth 978*37da2899SCharles.Forsyth 979*37da2899SCharles.Forsyth /*************************************************************************/ 980*37da2899SCharles.Forsyth /* */ 981*37da2899SCharles.Forsyth /* <Function> */ 982*37da2899SCharles.Forsyth /* code_to_next8_12 */ 983*37da2899SCharles.Forsyth /* */ 984*37da2899SCharles.Forsyth /* <Description> */ 985*37da2899SCharles.Forsyth /* Find the next encoded character. Uses format 8 or 12. */ 986*37da2899SCharles.Forsyth /* */ 987*37da2899SCharles.Forsyth /* <Input> */ 988*37da2899SCharles.Forsyth /* charCode :: The wanted character code. */ 989*37da2899SCharles.Forsyth /* */ 990*37da2899SCharles.Forsyth /* cmap :: A pointer to a cmap table in format 8 or 12. */ 991*37da2899SCharles.Forsyth /* */ 992*37da2899SCharles.Forsyth /* <Return> */ 993*37da2899SCharles.Forsyth /* Next encoded character. 0 if none exists. */ 994*37da2899SCharles.Forsyth /* */ 995*37da2899SCharles.Forsyth FT_CALLBACK_DEF( FT_ULong ) code_to_next8_12(TT_CMapTable cmap,FT_ULong charCode)996*37da2899SCharles.Forsyth code_to_next8_12( TT_CMapTable cmap, 997*37da2899SCharles.Forsyth FT_ULong charCode ) 998*37da2899SCharles.Forsyth { 999*37da2899SCharles.Forsyth TT_CMap8_12 cmap8_12; 1000*37da2899SCharles.Forsyth TT_CMapGroupRec *group, *limit; 1001*37da2899SCharles.Forsyth 1002*37da2899SCharles.Forsyth 1003*37da2899SCharles.Forsyth charCode++; 1004*37da2899SCharles.Forsyth cmap8_12 = &cmap->c.cmap8_12; 1005*37da2899SCharles.Forsyth limit = cmap8_12->groups + cmap8_12->nGroups; 1006*37da2899SCharles.Forsyth 1007*37da2899SCharles.Forsyth for ( group = cmap8_12->groups; group < limit; group++ ) 1008*37da2899SCharles.Forsyth { 1009*37da2899SCharles.Forsyth /* the ranges are sorted in increasing order. If we are out of */ 1010*37da2899SCharles.Forsyth /* the range here, the char code isn't in the charmap, so exit. */ 1011*37da2899SCharles.Forsyth 1012*37da2899SCharles.Forsyth if ( charCode <= group->endCharCode ) 1013*37da2899SCharles.Forsyth goto Found; 1014*37da2899SCharles.Forsyth } 1015*37da2899SCharles.Forsyth return 0; 1016*37da2899SCharles.Forsyth 1017*37da2899SCharles.Forsyth Found: 1018*37da2899SCharles.Forsyth if ( charCode < group->startCharCode ) 1019*37da2899SCharles.Forsyth charCode = group->startCharCode; 1020*37da2899SCharles.Forsyth 1021*37da2899SCharles.Forsyth return charCode; 1022*37da2899SCharles.Forsyth } 1023*37da2899SCharles.Forsyth 1024*37da2899SCharles.Forsyth 1025*37da2899SCharles.Forsyth /*************************************************************************/ 1026*37da2899SCharles.Forsyth /* */ 1027*37da2899SCharles.Forsyth /* <Function> */ 1028*37da2899SCharles.Forsyth /* code_to_index10 */ 1029*37da2899SCharles.Forsyth /* */ 1030*37da2899SCharles.Forsyth /* <Description> */ 1031*37da2899SCharles.Forsyth /* Converts the (possibly 32bit) character code into a glyph index. */ 1032*37da2899SCharles.Forsyth /* Uses format 10. */ 1033*37da2899SCharles.Forsyth /* */ 1034*37da2899SCharles.Forsyth /* <Input> */ 1035*37da2899SCharles.Forsyth /* charCode :: The wanted character code. */ 1036*37da2899SCharles.Forsyth /* */ 1037*37da2899SCharles.Forsyth /* cmap10 :: A pointer to a cmap table in format 10. */ 1038*37da2899SCharles.Forsyth /* */ 1039*37da2899SCharles.Forsyth /* <Return> */ 1040*37da2899SCharles.Forsyth /* Glyph index into the glyphs array. 0 if the glyph does not exist. */ 1041*37da2899SCharles.Forsyth /* */ 1042*37da2899SCharles.Forsyth FT_CALLBACK_DEF( FT_UInt ) code_to_index10(TT_CMapTable cmap,FT_ULong charCode)1043*37da2899SCharles.Forsyth code_to_index10( TT_CMapTable cmap, 1044*37da2899SCharles.Forsyth FT_ULong charCode ) 1045*37da2899SCharles.Forsyth { 1046*37da2899SCharles.Forsyth TT_CMap10 cmap10; 1047*37da2899SCharles.Forsyth FT_UInt result = 0; 1048*37da2899SCharles.Forsyth 1049*37da2899SCharles.Forsyth 1050*37da2899SCharles.Forsyth cmap10 = &cmap->c.cmap10; 1051*37da2899SCharles.Forsyth charCode -= cmap10->startCharCode; 1052*37da2899SCharles.Forsyth 1053*37da2899SCharles.Forsyth /* the overflow trick for comparison works here also since the number */ 1054*37da2899SCharles.Forsyth /* of glyphs (even if numChars is specified as ULong in the specs) in */ 1055*37da2899SCharles.Forsyth /* an OpenType font is limited to 64k */ 1056*37da2899SCharles.Forsyth 1057*37da2899SCharles.Forsyth if ( charCode < cmap10->numChars ) 1058*37da2899SCharles.Forsyth result = cmap10->glyphs[charCode]; 1059*37da2899SCharles.Forsyth 1060*37da2899SCharles.Forsyth return result; 1061*37da2899SCharles.Forsyth } 1062*37da2899SCharles.Forsyth 1063*37da2899SCharles.Forsyth 1064*37da2899SCharles.Forsyth /*************************************************************************/ 1065*37da2899SCharles.Forsyth /* */ 1066*37da2899SCharles.Forsyth /* <Function> */ 1067*37da2899SCharles.Forsyth /* code_to_next10 */ 1068*37da2899SCharles.Forsyth /* */ 1069*37da2899SCharles.Forsyth /* <Description> */ 1070*37da2899SCharles.Forsyth /* Find the next encoded character. Uses format 10. */ 1071*37da2899SCharles.Forsyth /* */ 1072*37da2899SCharles.Forsyth /* <Input> */ 1073*37da2899SCharles.Forsyth /* charCode :: The wanted character code. */ 1074*37da2899SCharles.Forsyth /* */ 1075*37da2899SCharles.Forsyth /* cmap :: A pointer to a cmap table in format 10. */ 1076*37da2899SCharles.Forsyth /* */ 1077*37da2899SCharles.Forsyth /* <Return> */ 1078*37da2899SCharles.Forsyth /* Next encoded character. 0 if none exists. */ 1079*37da2899SCharles.Forsyth /* */ 1080*37da2899SCharles.Forsyth FT_CALLBACK_DEF( FT_ULong ) code_to_next10(TT_CMapTable cmap,FT_ULong charCode)1081*37da2899SCharles.Forsyth code_to_next10( TT_CMapTable cmap, 1082*37da2899SCharles.Forsyth FT_ULong charCode ) 1083*37da2899SCharles.Forsyth { 1084*37da2899SCharles.Forsyth TT_CMap10 cmap10; 1085*37da2899SCharles.Forsyth 1086*37da2899SCharles.Forsyth 1087*37da2899SCharles.Forsyth charCode++; 1088*37da2899SCharles.Forsyth cmap10 = &cmap->c.cmap10; 1089*37da2899SCharles.Forsyth 1090*37da2899SCharles.Forsyth if ( charCode < cmap10->startCharCode ) 1091*37da2899SCharles.Forsyth charCode = cmap10->startCharCode; 1092*37da2899SCharles.Forsyth 1093*37da2899SCharles.Forsyth charCode -= cmap10->startCharCode; 1094*37da2899SCharles.Forsyth 1095*37da2899SCharles.Forsyth /* the overflow trick for comparison works here also since the number */ 1096*37da2899SCharles.Forsyth /* of glyphs (even if numChars is specified as ULong in the specs) in */ 1097*37da2899SCharles.Forsyth /* an OpenType font is limited to 64k */ 1098*37da2899SCharles.Forsyth 1099*37da2899SCharles.Forsyth while ( charCode < cmap10->numChars ) 1100*37da2899SCharles.Forsyth { 1101*37da2899SCharles.Forsyth if ( cmap10->glyphs[charCode] ) 1102*37da2899SCharles.Forsyth return ( charCode + cmap10->startCharCode ); 1103*37da2899SCharles.Forsyth charCode++; 1104*37da2899SCharles.Forsyth } 1105*37da2899SCharles.Forsyth 1106*37da2899SCharles.Forsyth return 0; 1107*37da2899SCharles.Forsyth } 1108*37da2899SCharles.Forsyth 1109*37da2899SCharles.Forsyth 1110*37da2899SCharles.Forsyth /* END */ 1111