1*37da2899SCharles.Forsyth /***************************************************************************/ 2*37da2899SCharles.Forsyth /* */ 3*37da2899SCharles.Forsyth /* ftccmap.c */ 4*37da2899SCharles.Forsyth /* */ 5*37da2899SCharles.Forsyth /* FreeType CharMap cache (body) */ 6*37da2899SCharles.Forsyth /* */ 7*37da2899SCharles.Forsyth /* Copyright 2000-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_FREETYPE_H 21*37da2899SCharles.Forsyth #include FT_CACHE_H 22*37da2899SCharles.Forsyth #include FT_CACHE_CHARMAP_H 23*37da2899SCharles.Forsyth #include FT_CACHE_MANAGER_H 24*37da2899SCharles.Forsyth #include FT_INTERNAL_MEMORY_H 25*37da2899SCharles.Forsyth #include FT_INTERNAL_DEBUG_H 26*37da2899SCharles.Forsyth 27*37da2899SCharles.Forsyth #include "ftcerror.h" 28*37da2899SCharles.Forsyth 29*37da2899SCharles.Forsyth /*************************************************************************/ 30*37da2899SCharles.Forsyth /* */ 31*37da2899SCharles.Forsyth /* Each FTC_CMapNode contains a simple array to map a range of character */ 32*37da2899SCharles.Forsyth /* codes to equivalent glyph indices. */ 33*37da2899SCharles.Forsyth /* */ 34*37da2899SCharles.Forsyth /* For now, the implementation is very basic: Each node maps a range of */ 35*37da2899SCharles.Forsyth /* 128 consecutive character codes to their corresponding glyph indices. */ 36*37da2899SCharles.Forsyth /* */ 37*37da2899SCharles.Forsyth /* We could do more complex things, but I don't think it is really very */ 38*37da2899SCharles.Forsyth /* useful. */ 39*37da2899SCharles.Forsyth /* */ 40*37da2899SCharles.Forsyth /*************************************************************************/ 41*37da2899SCharles.Forsyth 42*37da2899SCharles.Forsyth 43*37da2899SCharles.Forsyth /* number of glyph indices / character code per node */ 44*37da2899SCharles.Forsyth #define FTC_CMAP_INDICES_MAX 128 45*37da2899SCharles.Forsyth 46*37da2899SCharles.Forsyth 47*37da2899SCharles.Forsyth typedef struct FTC_CMapNodeRec_ 48*37da2899SCharles.Forsyth { 49*37da2899SCharles.Forsyth FTC_NodeRec node; 50*37da2899SCharles.Forsyth FT_UInt32 first; /* first character in node */ 51*37da2899SCharles.Forsyth FT_UInt16 indices[FTC_CMAP_INDICES_MAX]; /* array of glyph indices */ 52*37da2899SCharles.Forsyth 53*37da2899SCharles.Forsyth } FTC_CMapNodeRec, *FTC_CMapNode; 54*37da2899SCharles.Forsyth 55*37da2899SCharles.Forsyth 56*37da2899SCharles.Forsyth #define FTC_CMAP_NODE( x ) ( (FTC_CMapNode)( x ) ) 57*37da2899SCharles.Forsyth 58*37da2899SCharles.Forsyth 59*37da2899SCharles.Forsyth /* compute node hash value from cmap family and "requested" glyph index */ 60*37da2899SCharles.Forsyth #define FTC_CMAP_HASH( cfam, cquery ) \ 61*37da2899SCharles.Forsyth ( (cfam)->hash + ( (cquery)->char_code / FTC_CMAP_INDICES_MAX ) ) 62*37da2899SCharles.Forsyth 63*37da2899SCharles.Forsyth /* if (indices[n] == FTC_CMAP_UNKNOWN), we assume that the corresponding */ 64*37da2899SCharles.Forsyth /* glyph indices haven't been queried through FT_Get_Glyph_Index() yet */ 65*37da2899SCharles.Forsyth #define FTC_CMAP_UNKNOWN ( (FT_UInt16)-1 ) 66*37da2899SCharles.Forsyth 67*37da2899SCharles.Forsyth 68*37da2899SCharles.Forsyth /* the charmap query */ 69*37da2899SCharles.Forsyth typedef struct FTC_CMapQueryRec_ 70*37da2899SCharles.Forsyth { 71*37da2899SCharles.Forsyth FTC_QueryRec query; 72*37da2899SCharles.Forsyth FTC_CMapDesc desc; 73*37da2899SCharles.Forsyth FT_UInt32 char_code; 74*37da2899SCharles.Forsyth 75*37da2899SCharles.Forsyth } FTC_CMapQueryRec, *FTC_CMapQuery; 76*37da2899SCharles.Forsyth 77*37da2899SCharles.Forsyth 78*37da2899SCharles.Forsyth #define FTC_CMAP_QUERY( x ) ( (FTC_CMapQuery)( x ) ) 79*37da2899SCharles.Forsyth 80*37da2899SCharles.Forsyth 81*37da2899SCharles.Forsyth /* the charmap family */ 82*37da2899SCharles.Forsyth typedef struct FTC_CMapFamilyRec_ 83*37da2899SCharles.Forsyth { 84*37da2899SCharles.Forsyth FTC_FamilyRec family; 85*37da2899SCharles.Forsyth FT_UInt32 hash; 86*37da2899SCharles.Forsyth FTC_CMapDescRec desc; 87*37da2899SCharles.Forsyth FT_UInt index; 88*37da2899SCharles.Forsyth 89*37da2899SCharles.Forsyth } FTC_CMapFamilyRec, *FTC_CMapFamily; 90*37da2899SCharles.Forsyth 91*37da2899SCharles.Forsyth 92*37da2899SCharles.Forsyth #define FTC_CMAP_FAMILY( x ) ( (FTC_CMapFamily)( x ) ) 93*37da2899SCharles.Forsyth #define FTC_CMAP_FAMILY_MEMORY( x ) FTC_FAMILY( x )->memory 94*37da2899SCharles.Forsyth 95*37da2899SCharles.Forsyth 96*37da2899SCharles.Forsyth /*************************************************************************/ 97*37da2899SCharles.Forsyth /*************************************************************************/ 98*37da2899SCharles.Forsyth /***** *****/ 99*37da2899SCharles.Forsyth /***** CHARMAP NODES *****/ 100*37da2899SCharles.Forsyth /***** *****/ 101*37da2899SCharles.Forsyth /*************************************************************************/ 102*37da2899SCharles.Forsyth /*************************************************************************/ 103*37da2899SCharles.Forsyth 104*37da2899SCharles.Forsyth 105*37da2899SCharles.Forsyth /* no need for specific finalizer; we use "ftc_node_done" directly */ 106*37da2899SCharles.Forsyth 107*37da2899SCharles.Forsyth /* initialize a new cmap node */ 108*37da2899SCharles.Forsyth FT_CALLBACK_DEF( FT_Error ) ftc_cmap_node_init(FTC_CMapNode cnode,FTC_CMapQuery cquery,FTC_Cache cache)109*37da2899SCharles.Forsyth ftc_cmap_node_init( FTC_CMapNode cnode, 110*37da2899SCharles.Forsyth FTC_CMapQuery cquery, 111*37da2899SCharles.Forsyth FTC_Cache cache ) 112*37da2899SCharles.Forsyth { 113*37da2899SCharles.Forsyth FT_UInt32 first; 114*37da2899SCharles.Forsyth FT_UInt n; 115*37da2899SCharles.Forsyth FT_UNUSED( cache ); 116*37da2899SCharles.Forsyth 117*37da2899SCharles.Forsyth 118*37da2899SCharles.Forsyth first = ( cquery->char_code / FTC_CMAP_INDICES_MAX ) * 119*37da2899SCharles.Forsyth FTC_CMAP_INDICES_MAX; 120*37da2899SCharles.Forsyth 121*37da2899SCharles.Forsyth cnode->first = first; 122*37da2899SCharles.Forsyth for ( n = 0; n < FTC_CMAP_INDICES_MAX; n++ ) 123*37da2899SCharles.Forsyth cnode->indices[n] = FTC_CMAP_UNKNOWN; 124*37da2899SCharles.Forsyth 125*37da2899SCharles.Forsyth return 0; 126*37da2899SCharles.Forsyth } 127*37da2899SCharles.Forsyth 128*37da2899SCharles.Forsyth 129*37da2899SCharles.Forsyth /* compute the weight of a given cmap node */ 130*37da2899SCharles.Forsyth FT_CALLBACK_DEF( FT_ULong ) ftc_cmap_node_weight(FTC_CMapNode cnode)131*37da2899SCharles.Forsyth ftc_cmap_node_weight( FTC_CMapNode cnode ) 132*37da2899SCharles.Forsyth { 133*37da2899SCharles.Forsyth FT_UNUSED( cnode ); 134*37da2899SCharles.Forsyth 135*37da2899SCharles.Forsyth return sizeof ( *cnode ); 136*37da2899SCharles.Forsyth } 137*37da2899SCharles.Forsyth 138*37da2899SCharles.Forsyth 139*37da2899SCharles.Forsyth /* compare a cmap node to a given query */ 140*37da2899SCharles.Forsyth FT_CALLBACK_DEF( FT_Bool ) ftc_cmap_node_compare(FTC_CMapNode cnode,FTC_CMapQuery cquery)141*37da2899SCharles.Forsyth ftc_cmap_node_compare( FTC_CMapNode cnode, 142*37da2899SCharles.Forsyth FTC_CMapQuery cquery ) 143*37da2899SCharles.Forsyth { 144*37da2899SCharles.Forsyth FT_UInt32 offset = (FT_UInt32)( cquery->char_code - cnode->first ); 145*37da2899SCharles.Forsyth 146*37da2899SCharles.Forsyth 147*37da2899SCharles.Forsyth return FT_BOOL( offset < FTC_CMAP_INDICES_MAX ); 148*37da2899SCharles.Forsyth } 149*37da2899SCharles.Forsyth 150*37da2899SCharles.Forsyth 151*37da2899SCharles.Forsyth /*************************************************************************/ 152*37da2899SCharles.Forsyth /*************************************************************************/ 153*37da2899SCharles.Forsyth /***** *****/ 154*37da2899SCharles.Forsyth /***** CHARMAP FAMILY *****/ 155*37da2899SCharles.Forsyth /***** *****/ 156*37da2899SCharles.Forsyth /*************************************************************************/ 157*37da2899SCharles.Forsyth /*************************************************************************/ 158*37da2899SCharles.Forsyth 159*37da2899SCharles.Forsyth 160*37da2899SCharles.Forsyth FT_CALLBACK_DEF( FT_Error ) ftc_cmap_family_init(FTC_CMapFamily cfam,FTC_CMapQuery cquery,FTC_Cache cache)161*37da2899SCharles.Forsyth ftc_cmap_family_init( FTC_CMapFamily cfam, 162*37da2899SCharles.Forsyth FTC_CMapQuery cquery, 163*37da2899SCharles.Forsyth FTC_Cache cache ) 164*37da2899SCharles.Forsyth { 165*37da2899SCharles.Forsyth FTC_Manager manager = cache->manager; 166*37da2899SCharles.Forsyth FTC_CMapDesc desc = cquery->desc; 167*37da2899SCharles.Forsyth FT_UInt32 hash = 0; 168*37da2899SCharles.Forsyth FT_Error error; 169*37da2899SCharles.Forsyth FT_Face face; 170*37da2899SCharles.Forsyth 171*37da2899SCharles.Forsyth 172*37da2899SCharles.Forsyth /* setup charmap descriptor */ 173*37da2899SCharles.Forsyth cfam->desc = *desc; 174*37da2899SCharles.Forsyth 175*37da2899SCharles.Forsyth /* let's see whether the rest is correct too */ 176*37da2899SCharles.Forsyth error = FTC_Manager_Lookup_Face( manager, desc->face_id, &face ); 177*37da2899SCharles.Forsyth if ( !error ) 178*37da2899SCharles.Forsyth { 179*37da2899SCharles.Forsyth FT_UInt count = face->num_charmaps; 180*37da2899SCharles.Forsyth FT_UInt idx = count; 181*37da2899SCharles.Forsyth FT_CharMap* cur = face->charmaps; 182*37da2899SCharles.Forsyth 183*37da2899SCharles.Forsyth 184*37da2899SCharles.Forsyth switch ( desc->type ) 185*37da2899SCharles.Forsyth { 186*37da2899SCharles.Forsyth case FTC_CMAP_BY_INDEX: 187*37da2899SCharles.Forsyth idx = desc->u.index; 188*37da2899SCharles.Forsyth hash = idx * 33; 189*37da2899SCharles.Forsyth break; 190*37da2899SCharles.Forsyth 191*37da2899SCharles.Forsyth case FTC_CMAP_BY_ENCODING: 192*37da2899SCharles.Forsyth for ( idx = 0; idx < count; idx++, cur++ ) 193*37da2899SCharles.Forsyth if ( cur[0]->encoding == desc->u.encoding ) 194*37da2899SCharles.Forsyth break; 195*37da2899SCharles.Forsyth 196*37da2899SCharles.Forsyth hash = idx * 67; 197*37da2899SCharles.Forsyth break; 198*37da2899SCharles.Forsyth 199*37da2899SCharles.Forsyth case FTC_CMAP_BY_ID: 200*37da2899SCharles.Forsyth for ( idx = 0; idx < count; idx++, cur++ ) 201*37da2899SCharles.Forsyth { 202*37da2899SCharles.Forsyth if ( (FT_UInt)cur[0]->platform_id == desc->u.id.platform && 203*37da2899SCharles.Forsyth (FT_UInt)cur[0]->encoding_id == desc->u.id.encoding ) 204*37da2899SCharles.Forsyth { 205*37da2899SCharles.Forsyth hash = ( ( desc->u.id.platform << 8 ) | desc->u.id.encoding ) * 7; 206*37da2899SCharles.Forsyth break; 207*37da2899SCharles.Forsyth } 208*37da2899SCharles.Forsyth } 209*37da2899SCharles.Forsyth break; 210*37da2899SCharles.Forsyth 211*37da2899SCharles.Forsyth default: 212*37da2899SCharles.Forsyth ; 213*37da2899SCharles.Forsyth } 214*37da2899SCharles.Forsyth 215*37da2899SCharles.Forsyth if ( idx >= count ) 216*37da2899SCharles.Forsyth goto Bad_Descriptor; 217*37da2899SCharles.Forsyth 218*37da2899SCharles.Forsyth /* compute hash value, both in family and query */ 219*37da2899SCharles.Forsyth cfam->index = idx; 220*37da2899SCharles.Forsyth cfam->hash = hash ^ FTC_FACE_ID_HASH( desc->face_id ); 221*37da2899SCharles.Forsyth FTC_QUERY( cquery )->hash = FTC_CMAP_HASH( cfam, cquery ); 222*37da2899SCharles.Forsyth 223*37da2899SCharles.Forsyth error = ftc_family_init( FTC_FAMILY( cfam ), 224*37da2899SCharles.Forsyth FTC_QUERY( cquery ), cache ); 225*37da2899SCharles.Forsyth } 226*37da2899SCharles.Forsyth 227*37da2899SCharles.Forsyth return error; 228*37da2899SCharles.Forsyth 229*37da2899SCharles.Forsyth Bad_Descriptor: 230*37da2899SCharles.Forsyth FT_ERROR(( "ftp_cmap_family_init: invalid charmap descriptor\n" )); 231*37da2899SCharles.Forsyth return FTC_Err_Invalid_Argument; 232*37da2899SCharles.Forsyth } 233*37da2899SCharles.Forsyth 234*37da2899SCharles.Forsyth 235*37da2899SCharles.Forsyth FT_CALLBACK_DEF( FT_Bool ) ftc_cmap_family_compare(FTC_CMapFamily cfam,FTC_CMapQuery cquery)236*37da2899SCharles.Forsyth ftc_cmap_family_compare( FTC_CMapFamily cfam, 237*37da2899SCharles.Forsyth FTC_CMapQuery cquery ) 238*37da2899SCharles.Forsyth { 239*37da2899SCharles.Forsyth FT_Int result = 0; 240*37da2899SCharles.Forsyth 241*37da2899SCharles.Forsyth 242*37da2899SCharles.Forsyth /* first, compare face id and type */ 243*37da2899SCharles.Forsyth if ( cfam->desc.face_id != cquery->desc->face_id || 244*37da2899SCharles.Forsyth cfam->desc.type != cquery->desc->type ) 245*37da2899SCharles.Forsyth goto Exit; 246*37da2899SCharles.Forsyth 247*37da2899SCharles.Forsyth switch ( cfam->desc.type ) 248*37da2899SCharles.Forsyth { 249*37da2899SCharles.Forsyth case FTC_CMAP_BY_INDEX: 250*37da2899SCharles.Forsyth result = ( cfam->desc.u.index == cquery->desc->u.index ); 251*37da2899SCharles.Forsyth break; 252*37da2899SCharles.Forsyth 253*37da2899SCharles.Forsyth case FTC_CMAP_BY_ENCODING: 254*37da2899SCharles.Forsyth result = ( cfam->desc.u.encoding == cquery->desc->u.encoding ); 255*37da2899SCharles.Forsyth break; 256*37da2899SCharles.Forsyth 257*37da2899SCharles.Forsyth case FTC_CMAP_BY_ID: 258*37da2899SCharles.Forsyth result = ( cfam->desc.u.id.platform == cquery->desc->u.id.platform && 259*37da2899SCharles.Forsyth cfam->desc.u.id.encoding == cquery->desc->u.id.encoding ); 260*37da2899SCharles.Forsyth break; 261*37da2899SCharles.Forsyth 262*37da2899SCharles.Forsyth default: 263*37da2899SCharles.Forsyth ; 264*37da2899SCharles.Forsyth } 265*37da2899SCharles.Forsyth 266*37da2899SCharles.Forsyth if ( result ) 267*37da2899SCharles.Forsyth { 268*37da2899SCharles.Forsyth /* when found, update the 'family' and 'hash' field of the query */ 269*37da2899SCharles.Forsyth FTC_QUERY( cquery )->family = FTC_FAMILY( cfam ); 270*37da2899SCharles.Forsyth FTC_QUERY( cquery )->hash = FTC_CMAP_HASH( cfam, cquery ); 271*37da2899SCharles.Forsyth } 272*37da2899SCharles.Forsyth 273*37da2899SCharles.Forsyth Exit: 274*37da2899SCharles.Forsyth return FT_BOOL( result ); 275*37da2899SCharles.Forsyth } 276*37da2899SCharles.Forsyth 277*37da2899SCharles.Forsyth 278*37da2899SCharles.Forsyth /*************************************************************************/ 279*37da2899SCharles.Forsyth /*************************************************************************/ 280*37da2899SCharles.Forsyth /***** *****/ 281*37da2899SCharles.Forsyth /***** GLYPH IMAGE CACHE *****/ 282*37da2899SCharles.Forsyth /***** *****/ 283*37da2899SCharles.Forsyth /*************************************************************************/ 284*37da2899SCharles.Forsyth /*************************************************************************/ 285*37da2899SCharles.Forsyth 286*37da2899SCharles.Forsyth 287*37da2899SCharles.Forsyth FT_CALLBACK_TABLE_DEF 288*37da2899SCharles.Forsyth const FTC_Cache_ClassRec ftc_cmap_cache_class = 289*37da2899SCharles.Forsyth { 290*37da2899SCharles.Forsyth sizeof ( FTC_CacheRec ), 291*37da2899SCharles.Forsyth (FTC_Cache_InitFunc) ftc_cache_init, 292*37da2899SCharles.Forsyth (FTC_Cache_ClearFunc)ftc_cache_clear, 293*37da2899SCharles.Forsyth (FTC_Cache_DoneFunc) ftc_cache_done, 294*37da2899SCharles.Forsyth 295*37da2899SCharles.Forsyth sizeof ( FTC_CMapFamilyRec ), 296*37da2899SCharles.Forsyth (FTC_Family_InitFunc) ftc_cmap_family_init, 297*37da2899SCharles.Forsyth (FTC_Family_CompareFunc)ftc_cmap_family_compare, 298*37da2899SCharles.Forsyth (FTC_Family_DoneFunc) ftc_family_done, 299*37da2899SCharles.Forsyth 300*37da2899SCharles.Forsyth sizeof ( FTC_CMapNodeRec ), 301*37da2899SCharles.Forsyth (FTC_Node_InitFunc) ftc_cmap_node_init, 302*37da2899SCharles.Forsyth (FTC_Node_WeightFunc) ftc_cmap_node_weight, 303*37da2899SCharles.Forsyth (FTC_Node_CompareFunc)ftc_cmap_node_compare, 304*37da2899SCharles.Forsyth (FTC_Node_DoneFunc) ftc_node_done 305*37da2899SCharles.Forsyth }; 306*37da2899SCharles.Forsyth 307*37da2899SCharles.Forsyth 308*37da2899SCharles.Forsyth /* documentation is in ftccmap.h */ 309*37da2899SCharles.Forsyth 310*37da2899SCharles.Forsyth FT_EXPORT_DEF( FT_Error ) FTC_CMapCache_New(FTC_Manager manager,FTC_CMapCache * acache)311*37da2899SCharles.Forsyth FTC_CMapCache_New( FTC_Manager manager, 312*37da2899SCharles.Forsyth FTC_CMapCache *acache ) 313*37da2899SCharles.Forsyth { 314*37da2899SCharles.Forsyth return FTC_Manager_Register_Cache( 315*37da2899SCharles.Forsyth manager, 316*37da2899SCharles.Forsyth (FTC_Cache_Class)&ftc_cmap_cache_class, 317*37da2899SCharles.Forsyth FTC_CACHE_P( acache ) ); 318*37da2899SCharles.Forsyth } 319*37da2899SCharles.Forsyth 320*37da2899SCharles.Forsyth 321*37da2899SCharles.Forsyth #ifdef FTC_CACHE_USE_INLINE 322*37da2899SCharles.Forsyth 323*37da2899SCharles.Forsyth #define GEN_CACHE_FAMILY_COMPARE( f, q, c ) \ 324*37da2899SCharles.Forsyth ftc_cmap_family_compare( (FTC_CMapFamily)(f), (FTC_CMapQuery)(q) ) 325*37da2899SCharles.Forsyth 326*37da2899SCharles.Forsyth #define GEN_CACHE_NODE_COMPARE( n, q, c ) \ 327*37da2899SCharles.Forsyth ftc_cmap_node_compare( (FTC_CMapNode)(n), (FTC_CMapQuery)(q) ) 328*37da2899SCharles.Forsyth 329*37da2899SCharles.Forsyth #define GEN_CACHE_LOOKUP ftc_cmap_cache_lookup 330*37da2899SCharles.Forsyth 331*37da2899SCharles.Forsyth #include "ftccache.i" 332*37da2899SCharles.Forsyth 333*37da2899SCharles.Forsyth #else /* !FTC_CACHE_USE_INLINE */ 334*37da2899SCharles.Forsyth 335*37da2899SCharles.Forsyth #define ftc_cmap_cache_lookup ftc_cache_lookup 336*37da2899SCharles.Forsyth 337*37da2899SCharles.Forsyth #endif /* !FTC_CACHE_USE_INLINE */ 338*37da2899SCharles.Forsyth 339*37da2899SCharles.Forsyth 340*37da2899SCharles.Forsyth /* documentation is in ftccmap.h */ 341*37da2899SCharles.Forsyth 342*37da2899SCharles.Forsyth FT_EXPORT_DEF( FT_UInt ) FTC_CMapCache_Lookup(FTC_CMapCache cache,FTC_CMapDesc desc,FT_UInt32 char_code)343*37da2899SCharles.Forsyth FTC_CMapCache_Lookup( FTC_CMapCache cache, 344*37da2899SCharles.Forsyth FTC_CMapDesc desc, 345*37da2899SCharles.Forsyth FT_UInt32 char_code ) 346*37da2899SCharles.Forsyth { 347*37da2899SCharles.Forsyth FTC_CMapQueryRec cquery; 348*37da2899SCharles.Forsyth FTC_CMapNode node; 349*37da2899SCharles.Forsyth FT_Error error; 350*37da2899SCharles.Forsyth FT_UInt gindex = 0; 351*37da2899SCharles.Forsyth 352*37da2899SCharles.Forsyth 353*37da2899SCharles.Forsyth if ( !cache || !desc ) 354*37da2899SCharles.Forsyth { 355*37da2899SCharles.Forsyth FT_ERROR(( "FTC_CMapCache_Lookup: bad arguments, returning 0!\n" )); 356*37da2899SCharles.Forsyth return 0; 357*37da2899SCharles.Forsyth } 358*37da2899SCharles.Forsyth 359*37da2899SCharles.Forsyth cquery.desc = desc; 360*37da2899SCharles.Forsyth cquery.char_code = char_code; 361*37da2899SCharles.Forsyth 362*37da2899SCharles.Forsyth error = ftc_cmap_cache_lookup( FTC_CACHE( cache ), 363*37da2899SCharles.Forsyth FTC_QUERY( &cquery ), 364*37da2899SCharles.Forsyth (FTC_Node*)&node ); 365*37da2899SCharles.Forsyth if ( !error ) 366*37da2899SCharles.Forsyth { 367*37da2899SCharles.Forsyth FT_UInt offset = (FT_UInt)( char_code - node->first ); 368*37da2899SCharles.Forsyth 369*37da2899SCharles.Forsyth 370*37da2899SCharles.Forsyth FT_ASSERT( offset < FTC_CMAP_INDICES_MAX ); 371*37da2899SCharles.Forsyth 372*37da2899SCharles.Forsyth gindex = node->indices[offset]; 373*37da2899SCharles.Forsyth if ( gindex == FTC_CMAP_UNKNOWN ) 374*37da2899SCharles.Forsyth { 375*37da2899SCharles.Forsyth FT_Face face; 376*37da2899SCharles.Forsyth 377*37da2899SCharles.Forsyth 378*37da2899SCharles.Forsyth /* we need to use FT_Get_Char_Index */ 379*37da2899SCharles.Forsyth gindex = 0; 380*37da2899SCharles.Forsyth 381*37da2899SCharles.Forsyth error = FTC_Manager_Lookup_Face( FTC_CACHE(cache)->manager, 382*37da2899SCharles.Forsyth desc->face_id, 383*37da2899SCharles.Forsyth &face ); 384*37da2899SCharles.Forsyth if ( !error ) 385*37da2899SCharles.Forsyth { 386*37da2899SCharles.Forsyth FT_CharMap old, cmap = NULL; 387*37da2899SCharles.Forsyth FT_UInt cmap_index; 388*37da2899SCharles.Forsyth 389*37da2899SCharles.Forsyth 390*37da2899SCharles.Forsyth /* save old charmap, select new one */ 391*37da2899SCharles.Forsyth old = face->charmap; 392*37da2899SCharles.Forsyth cmap_index = FTC_CMAP_FAMILY( FTC_QUERY( &cquery )->family )->index; 393*37da2899SCharles.Forsyth cmap = face->charmaps[cmap_index]; 394*37da2899SCharles.Forsyth 395*37da2899SCharles.Forsyth FT_Set_Charmap( face, cmap ); 396*37da2899SCharles.Forsyth 397*37da2899SCharles.Forsyth /* perform lookup */ 398*37da2899SCharles.Forsyth gindex = FT_Get_Char_Index( face, char_code ); 399*37da2899SCharles.Forsyth node->indices[offset] = (FT_UInt16)gindex; 400*37da2899SCharles.Forsyth 401*37da2899SCharles.Forsyth /* restore old charmap */ 402*37da2899SCharles.Forsyth FT_Set_Charmap( face, old ); 403*37da2899SCharles.Forsyth } 404*37da2899SCharles.Forsyth } 405*37da2899SCharles.Forsyth } 406*37da2899SCharles.Forsyth 407*37da2899SCharles.Forsyth return gindex; 408*37da2899SCharles.Forsyth } 409*37da2899SCharles.Forsyth 410*37da2899SCharles.Forsyth 411*37da2899SCharles.Forsyth /* END */ 412