xref: /inferno-os/libfreetype/ftccmap.c (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
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