1 /***************************************************************************/
5 /* FreeType internal cache interface (specification). */
7 /* Copyright 2000-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2009, 2010 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 #define _FTC_FACE_ID_HASH( i ) \
28 ((FT_PtrDist)(( (FT_PtrDist)(i) >> 3 ) ^ ( (FT_PtrDist)(i) << 7 )))
30 /* handle to cache object */
31 typedef struct FTC_CacheRec_
* FTC_Cache
;
33 /* handle to cache class */
34 typedef const struct FTC_CacheClassRec_
* FTC_CacheClass
;
37 /*************************************************************************/
38 /*************************************************************************/
40 /***** CACHE NODE DEFINITIONS *****/
42 /*************************************************************************/
43 /*************************************************************************/
45 /*************************************************************************/
47 /* Each cache controls one or more cache nodes. Each node is part of */
48 /* the global_lru list of the manager. Its `data' field however is used */
49 /* as a reference count for now. */
51 /* A node can be anything, depending on the type of information held by */
52 /* the cache. It can be an individual glyph image, a set of bitmaps */
53 /* glyphs for a given size, some metrics, etc. */
55 /*************************************************************************/
57 /* structure size should be 20 bytes on 32-bits machines */
58 typedef struct FTC_NodeRec_
60 FTC_MruNodeRec mru
; /* circular mru list pointer */
61 FTC_Node link
; /* used for hashing */
62 FT_PtrDist hash
; /* used for hashing too */
63 FT_UShort cache_index
; /* index of cache the node belongs to */
64 FT_Short ref_count
; /* reference count for this node */
69 #define FTC_NODE( x ) ( (FTC_Node)(x) )
70 #define FTC_NODE_P( x ) ( (FTC_Node*)(x) )
72 #define FTC_NODE__NEXT( x ) FTC_NODE( (x)->mru.next )
73 #define FTC_NODE__PREV( x ) FTC_NODE( (x)->mru.prev )
76 #ifdef FT_CONFIG_OPTION_OLD_INTERNALS
78 ftc_node_destroy( FTC_Node node
,
79 FTC_Manager manager
);
83 /*************************************************************************/
84 /*************************************************************************/
86 /***** CACHE DEFINITIONS *****/
88 /*************************************************************************/
89 /*************************************************************************/
91 /* initialize a new cache node */
93 (*FTC_Node_NewFunc
)( FTC_Node
*pnode
,
98 (*FTC_Node_WeightFunc
)( FTC_Node node
,
101 /* compare a node to a given key pair */
103 (*FTC_Node_CompareFunc
)( FTC_Node node
,
109 (*FTC_Node_FreeFunc
)( FTC_Node node
,
113 (*FTC_Cache_InitFunc
)( FTC_Cache cache
);
116 (*FTC_Cache_DoneFunc
)( FTC_Cache cache
);
119 typedef struct FTC_CacheClassRec_
121 FTC_Node_NewFunc node_new
;
122 FTC_Node_WeightFunc node_weight
;
123 FTC_Node_CompareFunc node_compare
;
124 FTC_Node_CompareFunc node_remove_faceid
;
125 FTC_Node_FreeFunc node_free
;
127 FT_Offset cache_size
;
128 FTC_Cache_InitFunc cache_init
;
129 FTC_Cache_DoneFunc cache_done
;
134 /* each cache really implements a dynamic hash table to manage its nodes */
135 typedef struct FTC_CacheRec_
142 FTC_CacheClassRec clazz
; /* local copy, for speed */
146 FT_UInt index
; /* in manager's table */
148 FTC_CacheClass org_class
; /* original class pointer */
153 #define FTC_CACHE( x ) ( (FTC_Cache)(x) )
154 #define FTC_CACHE_P( x ) ( (FTC_Cache*)(x) )
157 /* default cache initialize */
159 FTC_Cache_Init( FTC_Cache cache
);
161 /* default cache finalizer */
163 FTC_Cache_Done( FTC_Cache cache
);
165 /* Call this function to lookup the cache. If no corresponding
166 * node is found, a new one is automatically created. This function
167 * is capable of flushing the cache adequately to make room for the
173 FTC_Cache_Lookup( FTC_Cache cache
,
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_PtrDist _hash = (FT_PtrDist)(hash); \
207 FTC_Node_CompareFunc _nodcomp = (FTC_Node_CompareFunc)(nodecmp); \
211 error = FTC_Err_Ok; \
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; \
239 void* _nl = &_manager->nodes_list; \
242 if ( _node != _manager->nodes_list ) \
243 FTC_MruNode_Up( (FTC_MruNode*)_nl, \
244 (FTC_MruNode)_node ); \
249 error = FTC_Cache_NewNode( _cache, _hash, query, &_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 != FTC_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__ */