1 /***************************************************************************/
5 /* FreeType CharMap cache (body) */
7 /* Copyright 2000-2001, 2002, 2003, 2004, 2005, 2006, 2007 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
;
295 FT_ERROR(( "FTC_CMapCache_Lookup: bad arguments, returning 0!\n" ));
299 #ifdef FT_CONFIG_OPTION_OLD_INTERNALS
302 * Detect a call from a rogue client that thinks it is linking
303 * to FreeType 2.1.7. This is possible because the third parameter
304 * is then a character code, and we have never seen any font with
305 * more than a few charmaps, so if the index is very large...
307 * It is also very unlikely that a rogue client is interested
308 * in Unicode values 0 to 15.
310 * NOTE: The original threshold was 4, but we found a font from the
311 * Adobe Acrobat Reader Pack, named `KozMinProVI-Regular.otf',
312 * which contains more than 5 charmaps.
314 if ( cmap_index
>= 16 )
316 FTC_OldCMapDesc desc
= (FTC_OldCMapDesc
) face_id
;
319 char_code
= (FT_UInt32
)cmap_index
;
320 query
.face_id
= desc
->face_id
;
323 switch ( desc
->type
)
325 case FTC_OLD_CMAP_BY_INDEX
:
326 query
.cmap_index
= desc
->u
.index
;
327 query
.char_code
= (FT_UInt32
)cmap_index
;
330 case FTC_OLD_CMAP_BY_ENCODING
:
335 error
= FTC_Manager_LookupFace( cache
->manager
, desc
->face_id
,
340 FT_Select_Charmap( face
, desc
->u
.encoding
);
342 return FT_Get_Char_Index( face
, char_code
);
351 #endif /* FT_CONFIG_OPTION_OLD_INTERNALS */
354 query
.face_id
= face_id
;
355 query
.cmap_index
= (FT_UInt
)cmap_index
;
356 query
.char_code
= char_code
;
359 hash
= FTC_CMAP_HASH( face_id
, cmap_index
, char_code
);
362 FTC_CACHE_LOOKUP_CMP( cache
, ftc_cmap_node_compare
, hash
, &query
,
365 error
= FTC_Cache_Lookup( cache
, hash
, &query
, (FTC_Node
*) &node
);
370 FT_ASSERT( (FT_UInt
)( char_code
- node
->first
) < FTC_CMAP_INDICES_MAX
);
372 /* something rotten can happen with rogue clients */
373 if ( (FT_UInt
)( char_code
- node
->first
>= FTC_CMAP_INDICES_MAX
) )
376 gindex
= node
->indices
[char_code
- node
->first
];
377 if ( gindex
== FTC_CMAP_UNKNOWN
)
384 error
= FTC_Manager_LookupFace( cache
->manager
, node
->face_id
, &face
);
388 if ( (FT_UInt
)cmap_index
< (FT_UInt
)face
->num_charmaps
)
390 FT_CharMap old
, cmap
= NULL
;
394 cmap
= face
->charmaps
[cmap_index
];
397 FT_Set_Charmap( face
, cmap
);
399 gindex
= FT_Get_Char_Index( face
, char_code
);
402 FT_Set_Charmap( face
, old
);
405 node
->indices
[char_code
- node
->first
] = (FT_UShort
)gindex
;