]> git.sesse.net Git - casparcg/blob - SFML-1.6/extlibs/headers/freetype/cache/ftccache.h
(no commit message)
[casparcg] / SFML-1.6 / extlibs / headers / freetype / cache / ftccache.h
1 /***************************************************************************/
2 /*                                                                         */
3 /*  ftccache.h                                                             */
4 /*                                                                         */
5 /*    FreeType internal cache interface (specification).                   */
6 /*                                                                         */
7 /*  Copyright 2000-2001, 2002, 2003, 2004, 2005 by                         */
8 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
9 /*                                                                         */
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.                                        */
15 /*                                                                         */
16 /***************************************************************************/
17
18
19 #ifndef __FTCCACHE_H__
20 #define __FTCCACHE_H__
21
22
23 #include FT_CACHE_INTERNAL_MRU_H
24
25 FT_BEGIN_HEADER
26
27   /* handle to cache object */
28   typedef struct FTC_CacheRec_*  FTC_Cache;
29
30   /* handle to cache class */
31   typedef const struct FTC_CacheClassRec_*  FTC_CacheClass;
32
33
34   /*************************************************************************/
35   /*************************************************************************/
36   /*****                                                               *****/
37   /*****                   CACHE NODE DEFINITIONS                      *****/
38   /*****                                                               *****/
39   /*************************************************************************/
40   /*************************************************************************/
41
42   /*************************************************************************/
43   /*                                                                       */
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.                                         */
47   /*                                                                       */
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.                           */
51   /*                                                                       */
52   /*************************************************************************/
53
54   /* structure size should be 20 bytes on 32-bits machines */
55   typedef struct  FTC_NodeRec_
56   {
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       */
62
63   } FTC_NodeRec;
64
65
66 #define FTC_NODE( x )    ( (FTC_Node)(x) )
67 #define FTC_NODE_P( x )  ( (FTC_Node*)(x) )
68
69 #define FTC_NODE__NEXT(x)  FTC_NODE( (x)->mru.next )
70 #define FTC_NODE__PREV(x)  FTC_NODE( (x)->mru.prev )
71
72
73   /*************************************************************************/
74   /*                                                                       */
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.                                           */
78   /*                                                                       */
79
80   /* reserved for manager's use */
81   FT_EXPORT( void )
82   ftc_node_destroy( FTC_Node     node,
83                     FTC_Manager  manager );
84
85
86   /*************************************************************************/
87   /*************************************************************************/
88   /*****                                                               *****/
89   /*****                       CACHE DEFINITIONS                       *****/
90   /*****                                                               *****/
91   /*************************************************************************/
92   /*************************************************************************/
93
94   /* initialize a new cache node */
95   typedef FT_Error
96   (*FTC_Node_NewFunc)( FTC_Node    *pnode,
97                        FT_Pointer   query,
98                        FTC_Cache    cache );
99
100   typedef FT_ULong
101   (*FTC_Node_WeightFunc)( FTC_Node   node,
102                           FTC_Cache  cache );
103
104   /* compare a node to a given key pair */
105   typedef FT_Bool
106   (*FTC_Node_CompareFunc)( FTC_Node    node,
107                            FT_Pointer  key,
108                            FTC_Cache   cache );
109
110
111   typedef void
112   (*FTC_Node_FreeFunc)( FTC_Node   node,
113                         FTC_Cache  cache );
114
115   typedef FT_Error
116   (*FTC_Cache_InitFunc)( FTC_Cache  cache );
117
118   typedef void
119   (*FTC_Cache_DoneFunc)( FTC_Cache  cache );
120
121
122   typedef struct  FTC_CacheClassRec_
123   {
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;
129
130     FT_UInt               cache_size;
131     FTC_Cache_InitFunc    cache_init;
132     FTC_Cache_DoneFunc    cache_done;
133
134   } FTC_CacheClassRec;
135
136
137   /* each cache really implements a dynamic hash table to manage its nodes */
138   typedef struct  FTC_CacheRec_
139   {
140     FT_UFast           p;
141     FT_UFast           mask;
142     FT_Long            slack;
143     FTC_Node*          buckets;
144
145     FTC_CacheClassRec  clazz;       /* local copy, for speed  */
146
147     FTC_Manager        manager;
148     FT_Memory          memory;
149     FT_UInt            index;       /* in manager's table     */
150
151     FTC_CacheClass     org_class;   /* original class pointer */
152
153   } FTC_CacheRec;
154
155
156 #define FTC_CACHE( x )    ( (FTC_Cache)(x) )
157 #define FTC_CACHE_P( x )  ( (FTC_Cache*)(x) )
158
159
160   /* default cache initialize */
161   FT_EXPORT( FT_Error )
162   FTC_Cache_Init( FTC_Cache  cache );
163
164   /* default cache finalizer */
165   FT_EXPORT( void )
166   FTC_Cache_Done( FTC_Cache  cache );
167
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
171    * new cache object.
172    */
173   FT_EXPORT( FT_Error )
174   FTC_Cache_Lookup( FTC_Cache   cache,
175                     FT_UInt32   hash,
176                     FT_Pointer  query,
177                     FTC_Node   *anode );
178
179   FT_EXPORT( FT_Error )
180   FTC_Cache_NewNode( FTC_Cache   cache,
181                      FT_UInt32   hash,
182                      FT_Pointer  query,
183                      FTC_Node   *anode );
184
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
189    * be modified.
190    *
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.
194    */
195   FT_EXPORT( void )
196   FTC_Cache_RemoveFaceID( FTC_Cache   cache,
197                           FTC_FaceID  face_id );
198
199
200 #ifdef FTC_INLINE
201
202 #define FTC_CACHE_LOOKUP_CMP( cache, nodecmp, hash, query, node, error ) \
203   FT_BEGIN_STMNT                                                         \
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);    \
208     FT_UInt               _idx;                                          \
209                                                                          \
210                                                                          \
211     error = 0;                                                           \
212     node  = NULL;                                                        \
213     _idx  = _hash & _cache->mask;                                        \
214     if ( _idx < _cache->p )                                              \
215       _idx = _hash & ( _cache->mask*2 + 1 );                             \
216                                                                          \
217     _bucket = _pnode = _cache->buckets + _idx;                           \
218     for (;;)                                                             \
219     {                                                                    \
220       _node = *_pnode;                                                   \
221       if ( _node == NULL )                                               \
222         goto _NewNode;                                                   \
223                                                                          \
224       if ( _node->hash == _hash && _nodcomp( _node, query, _cache ) )    \
225         break;                                                           \
226                                                                          \
227       _pnode = &_node->link;                                             \
228     }                                                                    \
229                                                                          \
230     if ( _node != *_bucket )                                             \
231     {                                                                    \
232       *_pnode     = _node->link;                                         \
233       _node->link = *_bucket;                                            \
234       *_bucket    = _node;                                               \
235     }                                                                    \
236                                                                          \
237     {                                                                    \
238       FTC_Manager  _manager = _cache->manager;                           \
239                                                                          \
240                                                                          \
241       if ( _node != _manager->nodes_list )                               \
242         FTC_MruNode_Up( (FTC_MruNode*)&_manager->nodes_list,             \
243                         (FTC_MruNode)_node );                            \
244     }                                                                    \
245     goto _Ok;                                                            \
246                                                                          \
247   _NewNode:                                                              \
248     error = FTC_Cache_NewNode( _cache, _hash, query, &_node );           \
249                                                                          \
250   _Ok:                                                                   \
251     _pnode = (FTC_Node*)(void*)&(node);                                  \
252     *_pnode = _node;                                                     \
253   FT_END_STMNT
254
255 #else /* !FTC_INLINE */
256
257 #define FTC_CACHE_LOOKUP_CMP( cache, nodecmp, hash, query, node, error ) \
258   FT_BEGIN_STMNT                                                         \
259     error = FTC_Cache_Lookup( FTC_CACHE( cache ), hash, query,           \
260                               (FTC_Node*)&(node) );                      \
261   FT_END_STMNT
262
263 #endif /* !FTC_INLINE */
264
265
266   /*
267    * This macro, together with FTC_CACHE_TRYLOOP_END, defines a retry
268    * loop to flush the cache repeatedly in case of memory overflows.
269    *
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).
272    * 
273    * Example:
274    *
275    *   {
276    *     FTC_CACHE_TRYLOOP( cache )
277    *       error = load_data( ... );
278    *     FTC_CACHE_TRYLOOP_END()
279    *   }
280    *
281    */
282 #define FTC_CACHE_TRYLOOP( cache )                           \
283   {                                                          \
284     FTC_Manager  _try_manager = FTC_CACHE( cache )->manager; \
285     FT_UInt      _try_count   = 4;                           \
286                                                              \
287                                                              \
288     for (;;)                                                 \
289     {                                                        \
290       FT_UInt  _try_done;
291
292
293 #define FTC_CACHE_TRYLOOP_END()                                   \
294       if ( !error || error != FT_Err_Out_Of_Memory )              \
295         break;                                                    \
296                                                                   \
297       _try_done = FTC_Manager_FlushN( _try_manager, _try_count ); \
298       if ( _try_done == 0 )                                       \
299         break;                                                    \
300                                                                   \
301       if ( _try_done == _try_count )                              \
302       {                                                           \
303         _try_count *= 2;                                          \
304         if ( _try_count < _try_done              ||               \
305             _try_count > _try_manager->num_nodes )                \
306           _try_count = _try_manager->num_nodes;                   \
307       }                                                           \
308     }                                                             \
309   }
310
311  /* */
312
313 FT_END_HEADER
314
315
316 #endif /* __FTCCACHE_H__ */
317
318
319 /* END */