1
/***************************************************************************/
5
/* FreeType CharMap cache (body) */
7
/* Copyright 2000-2001, 2002, 2003, 2004 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
22
#include FT_CACHE_INTERNAL_MANAGER_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
/*************************************************************************/
36
/* Each FTC_CMapNode contains a simple array to map a range of character */
37
/* codes to equivalent glyph indices. */
39
/* For now, the implementation is very basic: Each node maps a range of */
40
/* 128 consecutive character codes to their corresponding glyph indices. */
42
/* We could do more complex things, but I don't think it is really very */
45
/*************************************************************************/
48
/* number of glyph indices / character code per node */
49
#define FTC_CMAP_INDICES_MAX 128
51
/* compute a query/node hash */
52
#define FTC_CMAP_HASH( faceid, index, charcode ) \
53
( FTC_FACE_ID_HASH( faceid ) + 211 * ( index ) + \
54
( (char_code) / FTC_CMAP_INDICES_MAX ) )
56
/* the charmap query */
57
typedef struct FTC_CMapQueryRec_
63
} FTC_CMapQueryRec, *FTC_CMapQuery;
65
#define FTC_CMAP_QUERY( x ) ((FTC_CMapQuery)(x))
66
#define FTC_CMAP_QUERY_HASH( x ) \
67
FTC_CMAP_HASH( (x)->face_id, (x)->cmap_index, (x)->char_code )
69
/* the cmap cache node */
70
typedef struct FTC_CMapNodeRec_
75
FT_UInt32 first; /* first character in node */
76
FT_UInt16 indices[FTC_CMAP_INDICES_MAX]; /* array of glyph indices */
78
} FTC_CMapNodeRec, *FTC_CMapNode;
80
#define FTC_CMAP_NODE( x ) ( (FTC_CMapNode)( x ) )
81
#define FTC_CMAP_NODE_HASH( x ) \
82
FTC_CMAP_HASH( (x)->face_id, (x)->cmap_index, (x)->first )
84
/* if (indices[n] == FTC_CMAP_UNKNOWN), we assume that the corresponding */
85
/* glyph indices haven't been queried through FT_Get_Glyph_Index() yet */
86
#define FTC_CMAP_UNKNOWN ( (FT_UInt16)-1 )
89
/*************************************************************************/
90
/*************************************************************************/
92
/***** CHARMAP NODES *****/
94
/*************************************************************************/
95
/*************************************************************************/
98
/* no need for specific finalizer; we use `ftc_node_done' directly */
100
FT_CALLBACK_DEF( void )
101
ftc_cmap_node_free( FTC_Node ftcnode,
104
FTC_CMapNode node = (FTC_CMapNode)ftcnode;
105
FT_Memory memory = cache->memory;
112
/* initialize a new cmap node */
113
FT_CALLBACK_DEF( FT_Error )
114
ftc_cmap_node_new( FTC_Node *ftcanode,
118
FTC_CMapNode *anode = (FTC_CMapNode*)ftcanode;
119
FTC_CMapQuery query = (FTC_CMapQuery)ftcquery;
121
FT_Memory memory = cache->memory;
126
if ( !FT_NEW( node ) )
128
node->face_id = query->face_id;
129
node->cmap_index = query->cmap_index;
130
node->first = (query->char_code / FTC_CMAP_INDICES_MAX) *
131
FTC_CMAP_INDICES_MAX;
133
for ( nn = 0; nn < FTC_CMAP_INDICES_MAX; nn++ )
134
node->indices[nn] = FTC_CMAP_UNKNOWN;
142
/* compute the weight of a given cmap node */
143
FT_CALLBACK_DEF( FT_ULong )
144
ftc_cmap_node_weight( FTC_Node cnode,
150
return sizeof ( *cnode );
154
/* compare a cmap node to a given query */
155
FT_CALLBACK_DEF( FT_Bool )
156
ftc_cmap_node_compare( FTC_Node ftcnode,
160
FTC_CMapNode node = (FTC_CMapNode)ftcnode;
161
FTC_CMapQuery query = (FTC_CMapQuery)ftcquery;
165
if ( node->face_id == query->face_id &&
166
node->cmap_index == query->cmap_index )
168
FT_UInt32 offset = (FT_UInt32)( query->char_code - node->first );
171
return FT_BOOL( offset < FTC_CMAP_INDICES_MAX );
178
FT_CALLBACK_DEF( FT_Bool )
179
ftc_cmap_node_remove_faceid( FTC_Node ftcnode,
180
FT_Pointer ftcface_id,
183
FTC_CMapNode node = (FTC_CMapNode)ftcnode;
184
FTC_FaceID face_id = (FTC_FaceID)ftcface_id;
187
return FT_BOOL( node->face_id == face_id );
191
/*************************************************************************/
192
/*************************************************************************/
194
/***** GLYPH IMAGE CACHE *****/
196
/*************************************************************************/
197
/*************************************************************************/
200
FT_CALLBACK_TABLE_DEF
201
const FTC_CacheClassRec ftc_cmap_cache_class =
204
ftc_cmap_node_weight,
205
ftc_cmap_node_compare,
206
ftc_cmap_node_remove_faceid,
209
sizeof ( FTC_CacheRec ),
215
/* documentation is in ftcache.h */
217
FT_EXPORT_DEF( FT_Error )
218
FTC_CMapCache_New( FTC_Manager manager,
219
FTC_CMapCache *acache )
221
return FTC_Manager_RegisterCache( manager,
222
&ftc_cmap_cache_class,
223
FTC_CACHE_P( acache ) );
227
/* documentation is in ftcache.h */
229
FT_EXPORT_DEF( FT_UInt )
230
FTC_CMapCache_Lookup( FTC_CMapCache cmap_cache,
233
FT_UInt32 char_code )
235
FTC_Cache cache = FTC_CACHE( cmap_cache );
236
FTC_CMapQueryRec query;
245
FT_ERROR(( "FTC_CMapCache_Lookup: bad arguments, returning 0!\n" ));
249
query.face_id = face_id;
250
query.cmap_index = (FT_UInt)cmap_index;
251
query.char_code = char_code;
253
hash = FTC_CMAP_HASH( face_id, cmap_index, char_code );
256
FTC_CACHE_LOOKUP_CMP( cache, ftc_cmap_node_compare, hash, &query,
259
error = FTC_Cache_Lookup( cache, hash, &query, (FTC_Node*) &node );
264
FT_ASSERT( (FT_UInt)( char_code - node->first ) < FTC_CMAP_INDICES_MAX );
266
gindex = node->indices[char_code - node->first];
267
if ( gindex == FTC_CMAP_UNKNOWN )
274
error = FTC_Manager_LookupFace( cache->manager, node->face_id, &face );
278
if ( (FT_UInt)cmap_index < (FT_UInt)face->num_charmaps )
280
FT_CharMap old, cmap = NULL;
284
cmap = face->charmaps[cmap_index];
287
FT_Set_Charmap( face, cmap );
289
gindex = FT_Get_Char_Index( face, char_code );
292
FT_Set_Charmap( face, old );
295
node->indices[char_code - node->first] = gindex;