1 /***************************************************************************/
5 /* FreeType internal cache interface (specification). */
7 /* Copyright 2000-2001, 2002, 2003, 2004, 2005 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__
23 #include FT_CACHE_INTERNAL_MRU_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 /*************************************************************************/
75 /* These functions are exported so that they can be called from */
76 /* user-provided cache classes; otherwise, they are really part of the */
77 /* cache sub-system internals. */
80 /* reserved for manager's use */
82 ftc_node_destroy( FTC_Node node,
83 FTC_Manager manager );
86 /*************************************************************************/
87 /*************************************************************************/
89 /***** CACHE DEFINITIONS *****/
91 /*************************************************************************/
92 /*************************************************************************/
94 /* initialize a new cache node */
96 (*FTC_Node_NewFunc)( FTC_Node *pnode,
101 (*FTC_Node_WeightFunc)( FTC_Node node,
104 /* compare a node to a given key pair */
106 (*FTC_Node_CompareFunc)( FTC_Node node,
112 (*FTC_Node_FreeFunc)( FTC_Node node,
116 (*FTC_Cache_InitFunc)( FTC_Cache cache );
119 (*FTC_Cache_DoneFunc)( FTC_Cache cache );
122 typedef struct FTC_CacheClassRec_
124 FTC_Node_NewFunc node_new;
125 FTC_Node_WeightFunc node_weight;
126 FTC_Node_CompareFunc node_compare;
127 FTC_Node_CompareFunc node_remove_faceid;
128 FTC_Node_FreeFunc node_free;
131 FTC_Cache_InitFunc cache_init;
132 FTC_Cache_DoneFunc cache_done;
137 /* each cache really implements a dynamic hash table to manage its nodes */
138 typedef struct FTC_CacheRec_
145 FTC_CacheClassRec clazz; /* local copy, for speed */
149 FT_UInt index; /* in manager's table */
151 FTC_CacheClass org_class; /* original class pointer */
156 #define FTC_CACHE( x ) ( (FTC_Cache)(x) )
157 #define FTC_CACHE_P( x ) ( (FTC_Cache*)(x) )
160 /* default cache initialize */
161 FT_EXPORT( FT_Error )
162 FTC_Cache_Init( FTC_Cache cache );
164 /* default cache finalizer */
166 FTC_Cache_Done( FTC_Cache cache );
168 /* Call this function to lookup the cache. If no corresponding
169 * node is found, a new one is automatically created. This function
170 * is capable of flushing the cache adequately to make room for the
173 FT_EXPORT( FT_Error )
174 FTC_Cache_Lookup( FTC_Cache cache,
179 FT_EXPORT( FT_Error )
180 FTC_Cache_NewNode( FTC_Cache cache,
185 /* Remove all nodes that relate to a given face_id. This is useful
186 * when un-installing fonts. Note that if a cache node relates to
187 * the face_id, but is locked (i.e., has 'ref_count > 0'), the node
188 * will _not_ be destroyed, but its internal face_id reference will
191 * The final result will be that the node will never come back
192 * in further lookup requests, and will be flushed on demand from
193 * the cache normally when its reference count reaches 0.
196 FTC_Cache_RemoveFaceID( FTC_Cache cache,
197 FTC_FaceID face_id );
202 #define FTC_CACHE_LOOKUP_CMP( cache, nodecmp, hash, query, node, error ) \
204 FTC_Node *_bucket, *_pnode, _node; \
205 FTC_Cache _cache = FTC_CACHE(cache); \
206 FT_UInt32 _hash = (FT_UInt32)(hash); \
207 FTC_Node_CompareFunc _nodcomp = (FTC_Node_CompareFunc)(nodecmp); \
213 _idx = _hash & _cache->mask; \
214 if ( _idx < _cache->p ) \
215 _idx = _hash & ( _cache->mask*2 + 1 ); \
217 _bucket = _pnode = _cache->buckets + _idx; \
221 if ( _node == NULL ) \
224 if ( _node->hash == _hash && _nodcomp( _node, query, _cache ) ) \
227 _pnode = &_node->link; \
230 if ( _node != *_bucket ) \
232 *_pnode = _node->link; \
233 _node->link = *_bucket; \
238 FTC_Manager _manager = _cache->manager; \
241 if ( _node != _manager->nodes_list ) \
242 FTC_MruNode_Up( (FTC_MruNode*)&_manager->nodes_list, \
243 (FTC_MruNode)_node ); \
248 error = FTC_Cache_NewNode( _cache, _hash, query, &_node ); \
251 _pnode = (FTC_Node*)(void*)&(node); \
255 #else /* !FTC_INLINE */
257 #define FTC_CACHE_LOOKUP_CMP( cache, nodecmp, hash, query, node, error ) \
259 error = FTC_Cache_Lookup( FTC_CACHE( cache ), hash, query, \
260 (FTC_Node*)&(node) ); \
263 #endif /* !FTC_INLINE */
267 * This macro, together with FTC_CACHE_TRYLOOP_END, defines a retry
268 * loop to flush the cache repeatedly in case of memory overflows.
270 * It is used when creating a new cache node, or within a lookup
271 * that needs to allocate data (e.g., the sbit cache lookup).
276 * FTC_CACHE_TRYLOOP( cache )
277 * error = load_data( ... );
278 * FTC_CACHE_TRYLOOP_END()
282 #define FTC_CACHE_TRYLOOP( cache ) \
284 FTC_Manager _try_manager = FTC_CACHE( cache )->manager; \
285 FT_UInt _try_count = 4; \
293 #define FTC_CACHE_TRYLOOP_END() \
294 if ( !error || error != FT_Err_Out_Of_Memory ) \
297 _try_done = FTC_Manager_FlushN( _try_manager, _try_count ); \
298 if ( _try_done == 0 ) \
301 if ( _try_done == _try_count ) \
304 if ( _try_count < _try_done || \
305 _try_count > _try_manager->num_nodes ) \
306 _try_count = _try_manager->num_nodes; \
316 #endif /* __FTCCACHE_H__ */