1
/***************************************************************************/
5
/* FreeType CharMap cache (body) */
7
/* Copyright 2000-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 by */
8
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
10
/* This file is part of the FreeType project, and may only be used, */
11
/* modified, and distributed under the terms of the FreeType project */
12
/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
13
/* this file you indicate that you have read the license and */
14
/* understand and accept it fully. */
16
/***************************************************************************/
20
#include FT_FREETYPE_H
23
#include FT_INTERNAL_MEMORY_H
24
#include FT_INTERNAL_DEBUG_H
25
#include FT_TRUETYPE_IDS_H
31
#define FT_COMPONENT trace_cache
34
#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
36
typedef enum FTC_OldCMapType_
38
FTC_OLD_CMAP_BY_INDEX = 0,
39
FTC_OLD_CMAP_BY_ENCODING = 1,
40
FTC_OLD_CMAP_BY_ID = 2
45
typedef struct FTC_OldCMapIdRec_
50
} FTC_OldCMapIdRec, *FTC_OldCMapId;
53
typedef struct FTC_OldCMapDescRec_
66
} FTC_OldCMapDescRec, *FTC_OldCMapDesc;
68
#endif /* FT_CONFIG_OLD_INTERNALS */
71
/*************************************************************************/
73
/* Each FTC_CMapNode contains a simple array to map a range of character */
74
/* codes to equivalent glyph indices. */
76
/* For now, the implementation is very basic: Each node maps a range of */
77
/* 128 consecutive character codes to their corresponding glyph indices. */
79
/* We could do more complex things, but I don't think it is really very */
82
/*************************************************************************/
85
/* number of glyph indices / character code per node */
86
#define FTC_CMAP_INDICES_MAX 128
88
/* compute a query/node hash */
89
#define FTC_CMAP_HASH( faceid, index, charcode ) \
90
( FTC_FACE_ID_HASH( faceid ) + 211 * ( index ) + \
91
( (char_code) / FTC_CMAP_INDICES_MAX ) )
93
/* the charmap query */
94
typedef struct FTC_CMapQueryRec_
100
} FTC_CMapQueryRec, *FTC_CMapQuery;
102
#define FTC_CMAP_QUERY( x ) ((FTC_CMapQuery)(x))
103
#define FTC_CMAP_QUERY_HASH( x ) \
104
FTC_CMAP_HASH( (x)->face_id, (x)->cmap_index, (x)->char_code )
106
/* the cmap cache node */
107
typedef struct FTC_CMapNodeRec_
112
FT_UInt32 first; /* first character in node */
113
FT_UInt16 indices[FTC_CMAP_INDICES_MAX]; /* array of glyph indices */
115
} FTC_CMapNodeRec, *FTC_CMapNode;
117
#define FTC_CMAP_NODE( x ) ( (FTC_CMapNode)( x ) )
118
#define FTC_CMAP_NODE_HASH( x ) \
119
FTC_CMAP_HASH( (x)->face_id, (x)->cmap_index, (x)->first )
121
/* if (indices[n] == FTC_CMAP_UNKNOWN), we assume that the corresponding */
122
/* glyph indices haven't been queried through FT_Get_Glyph_Index() yet */
123
#define FTC_CMAP_UNKNOWN ( (FT_UInt16)-1 )
126
/*************************************************************************/
127
/*************************************************************************/
129
/***** CHARMAP NODES *****/
131
/*************************************************************************/
132
/*************************************************************************/
135
FT_CALLBACK_DEF( void )
136
ftc_cmap_node_free( FTC_Node ftcnode,
139
FTC_CMapNode node = (FTC_CMapNode)ftcnode;
140
FT_Memory memory = cache->memory;
147
/* initialize a new cmap node */
148
FT_CALLBACK_DEF( FT_Error )
149
ftc_cmap_node_new( FTC_Node *ftcanode,
153
FTC_CMapNode *anode = (FTC_CMapNode*)ftcanode;
154
FTC_CMapQuery query = (FTC_CMapQuery)ftcquery;
156
FT_Memory memory = cache->memory;
161
if ( !FT_NEW( node ) )
163
node->face_id = query->face_id;
164
node->cmap_index = query->cmap_index;
165
node->first = (query->char_code / FTC_CMAP_INDICES_MAX) *
166
FTC_CMAP_INDICES_MAX;
168
for ( nn = 0; nn < FTC_CMAP_INDICES_MAX; nn++ )
169
node->indices[nn] = FTC_CMAP_UNKNOWN;
177
/* compute the weight of a given cmap node */
178
FT_CALLBACK_DEF( FT_ULong )
179
ftc_cmap_node_weight( FTC_Node cnode,
185
return sizeof ( *cnode );
189
/* compare a cmap node to a given query */
190
FT_CALLBACK_DEF( FT_Bool )
191
ftc_cmap_node_compare( FTC_Node ftcnode,
195
FTC_CMapNode node = (FTC_CMapNode)ftcnode;
196
FTC_CMapQuery query = (FTC_CMapQuery)ftcquery;
200
if ( node->face_id == query->face_id &&
201
node->cmap_index == query->cmap_index )
203
FT_UInt32 offset = (FT_UInt32)( query->char_code - node->first );
206
return FT_BOOL( offset < FTC_CMAP_INDICES_MAX );
213
FT_CALLBACK_DEF( FT_Bool )
214
ftc_cmap_node_remove_faceid( FTC_Node ftcnode,
215
FT_Pointer ftcface_id,
218
FTC_CMapNode node = (FTC_CMapNode)ftcnode;
219
FTC_FaceID face_id = (FTC_FaceID)ftcface_id;
222
return FT_BOOL( node->face_id == face_id );
226
/*************************************************************************/
227
/*************************************************************************/
229
/***** GLYPH IMAGE CACHE *****/
231
/*************************************************************************/
232
/*************************************************************************/
235
FT_CALLBACK_TABLE_DEF
236
const FTC_CacheClassRec ftc_cmap_cache_class =
239
ftc_cmap_node_weight,
240
ftc_cmap_node_compare,
241
ftc_cmap_node_remove_faceid,
244
sizeof ( FTC_CacheRec ),
250
/* documentation is in ftcache.h */
252
FT_EXPORT_DEF( FT_Error )
253
FTC_CMapCache_New( FTC_Manager manager,
254
FTC_CMapCache *acache )
256
return FTC_Manager_RegisterCache( manager,
257
&ftc_cmap_cache_class,
258
FTC_CACHE_P( acache ) );
262
#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
265
* Unfortunately, it is not possible to support binary backwards
266
* compatibility in the cmap cache. The FTC_CMapCache_Lookup signature
267
* changes were too deep, and there is no clever hackish way to detect
268
* what kind of structure we are being passed.
270
* On the other hand it seems that no production code is using this
271
* function on Unix distributions.
277
/* documentation is in ftcache.h */
279
FT_EXPORT_DEF( FT_UInt )
280
FTC_CMapCache_Lookup( FTC_CMapCache cmap_cache,
283
FT_UInt32 char_code )
285
FTC_Cache cache = FTC_CACHE( cmap_cache );
286
FTC_CMapQueryRec query;
291
FT_Int no_cmap_change = 0;
294
if ( cmap_index < 0 )
296
/* Treat a negative cmap index as a special value, meaning that you */
297
/* don't want to change the FT_Face's character map through this */
298
/* call. This can be useful if the face requester callback already */
299
/* sets the face's charmap to the appropriate value. */
307
FT_ERROR(( "FTC_CMapCache_Lookup: bad arguments, returning 0!\n" ));
311
#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
314
* Detect a call from a rogue client that thinks it is linking
315
* to FreeType 2.1.7. This is possible because the third parameter
316
* is then a character code, and we have never seen any font with
317
* more than a few charmaps, so if the index is very large...
319
* It is also very unlikely that a rogue client is interested
320
* in Unicode values 0 to 15.
322
* NOTE: The original threshold was 4, but we found a font from the
323
* Adobe Acrobat Reader Pack, named `KozMinProVI-Regular.otf',
324
* which contains more than 5 charmaps.
326
if ( cmap_index >= 16 && !no_cmap_change )
328
FTC_OldCMapDesc desc = (FTC_OldCMapDesc) face_id;
331
char_code = (FT_UInt32)cmap_index;
332
query.face_id = desc->face_id;
335
switch ( desc->type )
337
case FTC_OLD_CMAP_BY_INDEX:
338
query.cmap_index = desc->u.index;
339
query.char_code = (FT_UInt32)cmap_index;
342
case FTC_OLD_CMAP_BY_ENCODING:
347
error = FTC_Manager_LookupFace( cache->manager, desc->face_id,
352
FT_Select_Charmap( face, desc->u.encoding );
354
return FT_Get_Char_Index( face, char_code );
363
#endif /* FT_CONFIG_OPTION_OLD_INTERNALS */
366
query.face_id = face_id;
367
query.cmap_index = (FT_UInt)cmap_index;
368
query.char_code = char_code;
371
hash = FTC_CMAP_HASH( face_id, cmap_index, char_code );
374
FTC_CACHE_LOOKUP_CMP( cache, ftc_cmap_node_compare, hash, &query,
377
error = FTC_Cache_Lookup( cache, hash, &query, (FTC_Node*) &node );
382
FT_ASSERT( (FT_UInt)( char_code - node->first ) < FTC_CMAP_INDICES_MAX );
384
/* something rotten can happen with rogue clients */
385
if ( (FT_UInt)( char_code - node->first >= FTC_CMAP_INDICES_MAX ) )
388
gindex = node->indices[char_code - node->first];
389
if ( gindex == FTC_CMAP_UNKNOWN )
396
error = FTC_Manager_LookupFace( cache->manager, node->face_id, &face );
400
if ( (FT_UInt)cmap_index < (FT_UInt)face->num_charmaps )
402
FT_CharMap old, cmap = NULL;
406
cmap = face->charmaps[cmap_index];
408
if ( old != cmap && !no_cmap_change )
409
FT_Set_Charmap( face, cmap );
411
gindex = FT_Get_Char_Index( face, char_code );
413
if ( old != cmap && !no_cmap_change )
414
FT_Set_Charmap( face, old );
417
node->indices[char_code - node->first] = (FT_UShort)gindex;