1 /***************************************************************************/
5 /* FreeType internal cache interface (specification). */
7 /* Copyright 2000-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2009 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 /***************************************************************************/
19 #ifndef __FTCCACHE_H__
20 #define __FTCCACHE_H__
27 /* handle to cache object */
28 typedef struct FTC_CacheRec_
* FTC_Cache
;
30 /* handle to cache class */
31 typedef const struct FTC_CacheClassRec_
* FTC_CacheClass
;
34 /*************************************************************************/
35 /*************************************************************************/
37 /***** CACHE NODE DEFINITIONS *****/
39 /*************************************************************************/
40 /*************************************************************************/
42 /*************************************************************************/
44 /* Each cache controls one or more cache nodes. Each node is part of */
45 /* the global_lru list of the manager. Its `data' field however is used */
46 /* as a reference count for now. */
48 /* A node can be anything, depending on the type of information held by */
49 /* the cache. It can be an individual glyph image, a set of bitmaps */
50 /* glyphs for a given size, some metrics, etc. */
52 /*************************************************************************/
54 /* structure size should be 20 bytes on 32-bits machines */
55 typedef struct FTC_NodeRec_
57 FTC_MruNodeRec mru
; /* circular mru list pointer */
58 FTC_Node link
; /* used for hashing */
59 FT_UInt32 hash
; /* used for hashing too */
60 FT_UShort cache_index
; /* index of cache the node belongs to */
61 FT_Short ref_count
; /* reference count for this node */
66 #define FTC_NODE( x ) ( (FTC_Node)(x) )
67 #define FTC_NODE_P( x ) ( (FTC_Node*)(x) )
69 #define FTC_NODE__NEXT( x ) FTC_NODE( (x)->mru.next )
70 #define FTC_NODE__PREV( x ) FTC_NODE( (x)->mru.prev )
73 #ifdef FT_CONFIG_OPTION_OLD_INTERNALS
75 ftc_node_destroy( FTC_Node node
,
76 FTC_Manager manager
);
80 /*************************************************************************/
81 /*************************************************************************/
83 /***** CACHE DEFINITIONS *****/
85 /*************************************************************************/
86 /*************************************************************************/
88 /* initialize a new cache node */
90 (*FTC_Node_NewFunc
)( FTC_Node
*pnode
,
95 (*FTC_Node_WeightFunc
)( FTC_Node node
,
98 /* compare a node to a given key pair */
100 (*FTC_Node_CompareFunc
)( FTC_Node node
,
106 (*FTC_Node_FreeFunc
)( FTC_Node node
,
110 (*FTC_Cache_InitFunc
)( FTC_Cache cache
);
113 (*FTC_Cache_DoneFunc
)( FTC_Cache cache
);
116 typedef struct FTC_CacheClassRec_
118 FTC_Node_NewFunc node_new
;
119 FTC_Node_WeightFunc node_weight
;
120 FTC_Node_CompareFunc node_compare
;
121 FTC_Node_CompareFunc node_remove_faceid
;
122 FTC_Node_FreeFunc node_free
;
124 FT_Offset cache_size
;
125 FTC_Cache_InitFunc cache_init
;
126 FTC_Cache_DoneFunc cache_done
;
131 /* each cache really implements a dynamic hash table to manage its nodes */
132 typedef struct FTC_CacheRec_
139 FTC_CacheClassRec clazz
; /* local copy, for speed */
143 FT_UInt index
; /* in manager's table */
145 FTC_CacheClass org_class
; /* original class pointer */
150 #define FTC_CACHE( x ) ( (FTC_Cache)(x) )
151 #define FTC_CACHE_P( x ) ( (FTC_Cache*)(x) )
154 /* default cache initialize */
156 FTC_Cache_Init( FTC_Cache cache
);
158 /* default cache finalizer */
160 FTC_Cache_Done( FTC_Cache cache
);
162 /* Call this function to lookup the cache. If no corresponding
163 * node is found, a new one is automatically created. This function
164 * is capable of flushing the cache adequately to make room for the
170 FTC_Cache_Lookup( FTC_Cache cache
,
177 FTC_Cache_NewNode( FTC_Cache cache
,
182 /* Remove all nodes that relate to a given face_id. This is useful
183 * when un-installing fonts. Note that if a cache node relates to
184 * the face_id, but is locked (i.e., has `ref_count > 0'), the node
185 * will _not_ be destroyed, but its internal face_id reference will
188 * The final result will be that the node will never come back
189 * in further lookup requests, and will be flushed on demand from
190 * the cache normally when its reference count reaches 0.
193 FTC_Cache_RemoveFaceID( FTC_Cache cache
,
194 FTC_FaceID face_id
);
199 #define FTC_CACHE_LOOKUP_CMP( cache, nodecmp, hash, query, node, error ) \
201 FTC_Node *_bucket, *_pnode, _node; \
202 FTC_Cache _cache = FTC_CACHE(cache); \
203 FT_UInt32 _hash = (FT_UInt32)(hash); \
204 FTC_Node_CompareFunc _nodcomp = (FTC_Node_CompareFunc)(nodecmp); \
210 _idx = _hash & _cache->mask; \
211 if ( _idx < _cache->p ) \
212 _idx = _hash & ( _cache->mask*2 + 1 ); \
214 _bucket = _pnode = _cache->buckets + _idx; \
218 if ( _node == NULL ) \
221 if ( _node->hash == _hash && _nodcomp( _node, query, _cache ) ) \
224 _pnode = &_node->link; \
227 if ( _node != *_bucket ) \
229 *_pnode = _node->link; \
230 _node->link = *_bucket; \
235 FTC_Manager _manager = _cache->manager; \
236 void* _nl = &_manager->nodes_list; \
239 if ( _node != _manager->nodes_list ) \
240 FTC_MruNode_Up( (FTC_MruNode*)_nl, \
241 (FTC_MruNode)_node ); \
246 error = FTC_Cache_NewNode( _cache, _hash, query, &_node ); \
252 #else /* !FTC_INLINE */
254 #define FTC_CACHE_LOOKUP_CMP( cache, nodecmp, hash, query, node, error ) \
256 error = FTC_Cache_Lookup( FTC_CACHE( cache ), hash, query, \
257 (FTC_Node*)&(node) ); \
260 #endif /* !FTC_INLINE */
264 * This macro, together with FTC_CACHE_TRYLOOP_END, defines a retry
265 * loop to flush the cache repeatedly in case of memory overflows.
267 * It is used when creating a new cache node, or within a lookup
268 * that needs to allocate data (e.g., the sbit cache lookup).
273 * FTC_CACHE_TRYLOOP( cache )
274 * error = load_data( ... );
275 * FTC_CACHE_TRYLOOP_END()
279 #define FTC_CACHE_TRYLOOP( cache ) \
281 FTC_Manager _try_manager = FTC_CACHE( cache )->manager; \
282 FT_UInt _try_count = 4; \
290 #define FTC_CACHE_TRYLOOP_END() \
291 if ( !error || error != FT_Err_Out_Of_Memory ) \
294 _try_done = FTC_Manager_FlushN( _try_manager, _try_count ); \
295 if ( _try_done == 0 ) \
298 if ( _try_done == _try_count ) \
301 if ( _try_count < _try_done || \
302 _try_count > _try_manager->num_nodes ) \
303 _try_count = _try_manager->num_nodes; \
313 #endif /* __FTCCACHE_H__ */