ftccache.h

Go to the documentation of this file.
00001 /***************************************************************************/
00002 /*                                                                         */
00003 /*  ftccache.h                                                             */
00004 /*                                                                         */
00005 /*    FreeType internal cache interface (specification).                   */
00006 /*                                                                         */
00007 /*  Copyright 2000-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2009 by       */
00008 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
00009 /*                                                                         */
00010 /*  This file is part of the FreeType project, and may only be used,       */
00011 /*  modified, and distributed under the terms of the FreeType project      */
00012 /*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
00013 /*  this file you indicate that you have read the license and              */
00014 /*  understand and accept it fully.                                        */
00015 /*                                                                         */
00016 /***************************************************************************/
00017 
00018 
00019 #ifndef __FTCCACHE_H__
00020 #define __FTCCACHE_H__
00021 
00022 
00023 #include "ftcmru.h"
00024 
00025 FT_BEGIN_HEADER
00026 
00027   /* handle to cache object */
00028   typedef struct FTC_CacheRec_*  FTC_Cache;
00029 
00030   /* handle to cache class */
00031   typedef const struct FTC_CacheClassRec_*  FTC_CacheClass;
00032 
00033 
00034   /*************************************************************************/
00035   /*************************************************************************/
00036   /*****                                                               *****/
00037   /*****                   CACHE NODE DEFINITIONS                      *****/
00038   /*****                                                               *****/
00039   /*************************************************************************/
00040   /*************************************************************************/
00041 
00042   /*************************************************************************/
00043   /*                                                                       */
00044   /* Each cache controls one or more cache nodes.  Each node is part of    */
00045   /* the global_lru list of the manager.  Its `data' field however is used */
00046   /* as a reference count for now.                                         */
00047   /*                                                                       */
00048   /* A node can be anything, depending on the type of information held by  */
00049   /* the cache.  It can be an individual glyph image, a set of bitmaps     */
00050   /* glyphs for a given size, some metrics, etc.                           */
00051   /*                                                                       */
00052   /*************************************************************************/
00053 
00054   /* structure size should be 20 bytes on 32-bits machines */
00055   typedef struct  FTC_NodeRec_
00056   {
00057     FTC_MruNodeRec  mru;          /* circular mru list pointer           */
00058     FTC_Node        link;         /* used for hashing                    */
00059     FT_UInt32       hash;         /* used for hashing too                */
00060     FT_UShort       cache_index;  /* index of cache the node belongs to  */
00061     FT_Short        ref_count;    /* reference count for this node       */
00062 
00063   } FTC_NodeRec;
00064 
00065 
00066 #define FTC_NODE( x )    ( (FTC_Node)(x) )
00067 #define FTC_NODE_P( x )  ( (FTC_Node*)(x) )
00068 
00069 #define FTC_NODE__NEXT( x )  FTC_NODE( (x)->mru.next )
00070 #define FTC_NODE__PREV( x )  FTC_NODE( (x)->mru.prev )
00071 
00072 
00073 #ifdef FT_CONFIG_OPTION_OLD_INTERNALS
00074   FT_BASE( void )
00075   ftc_node_destroy( FTC_Node     node,
00076                     FTC_Manager  manager );
00077 #endif
00078 
00079 
00080   /*************************************************************************/
00081   /*************************************************************************/
00082   /*****                                                               *****/
00083   /*****                       CACHE DEFINITIONS                       *****/
00084   /*****                                                               *****/
00085   /*************************************************************************/
00086   /*************************************************************************/
00087 
00088   /* initialize a new cache node */
00089   typedef FT_Error
00090   (*FTC_Node_NewFunc)( FTC_Node    *pnode,
00091                        FT_Pointer   query,
00092                        FTC_Cache    cache );
00093 
00094   typedef FT_Offset
00095   (*FTC_Node_WeightFunc)( FTC_Node   node,
00096                           FTC_Cache  cache );
00097 
00098   /* compare a node to a given key pair */
00099   typedef FT_Bool
00100   (*FTC_Node_CompareFunc)( FTC_Node    node,
00101                            FT_Pointer  key,
00102                            FTC_Cache   cache );
00103 
00104 
00105   typedef void
00106   (*FTC_Node_FreeFunc)( FTC_Node   node,
00107                         FTC_Cache  cache );
00108 
00109   typedef FT_Error
00110   (*FTC_Cache_InitFunc)( FTC_Cache  cache );
00111 
00112   typedef void
00113   (*FTC_Cache_DoneFunc)( FTC_Cache  cache );
00114 
00115 
00116   typedef struct  FTC_CacheClassRec_
00117   {
00118     FTC_Node_NewFunc      node_new;
00119     FTC_Node_WeightFunc   node_weight;
00120     FTC_Node_CompareFunc  node_compare;
00121     FTC_Node_CompareFunc  node_remove_faceid;
00122     FTC_Node_FreeFunc     node_free;
00123 
00124     FT_Offset             cache_size;
00125     FTC_Cache_InitFunc    cache_init;
00126     FTC_Cache_DoneFunc    cache_done;
00127 
00128   } FTC_CacheClassRec;
00129 
00130 
00131   /* each cache really implements a dynamic hash table to manage its nodes */
00132   typedef struct  FTC_CacheRec_
00133   {
00134     FT_UFast           p;
00135     FT_UFast           mask;
00136     FT_Long            slack;
00137     FTC_Node*          buckets;
00138 
00139     FTC_CacheClassRec  clazz;       /* local copy, for speed  */
00140 
00141     FTC_Manager        manager;
00142     FT_Memory          memory;
00143     FT_UInt            index;       /* in manager's table     */
00144 
00145     FTC_CacheClass     org_class;   /* original class pointer */
00146 
00147   } FTC_CacheRec;
00148 
00149 
00150 #define FTC_CACHE( x )    ( (FTC_Cache)(x) )
00151 #define FTC_CACHE_P( x )  ( (FTC_Cache*)(x) )
00152 
00153 
00154   /* default cache initialize */
00155   FT_LOCAL( FT_Error )
00156   FTC_Cache_Init( FTC_Cache  cache );
00157 
00158   /* default cache finalizer */
00159   FT_LOCAL( void )
00160   FTC_Cache_Done( FTC_Cache  cache );
00161 
00162   /* Call this function to lookup the cache.  If no corresponding
00163    * node is found, a new one is automatically created.  This function
00164    * is capable of flushing the cache adequately to make room for the
00165    * new cache object.
00166    */
00167 
00168 #ifndef FTC_INLINE
00169   FT_LOCAL( FT_Error )
00170   FTC_Cache_Lookup( FTC_Cache   cache,
00171                     FT_UInt32   hash,
00172                     FT_Pointer  query,
00173                     FTC_Node   *anode );
00174 #endif
00175 
00176   FT_LOCAL( FT_Error )
00177   FTC_Cache_NewNode( FTC_Cache   cache,
00178                      FT_UInt32   hash,
00179                      FT_Pointer  query,
00180                      FTC_Node   *anode );
00181 
00182   /* Remove all nodes that relate to a given face_id.  This is useful
00183    * when un-installing fonts.  Note that if a cache node relates to
00184    * the face_id, but is locked (i.e., has `ref_count > 0'), the node
00185    * will _not_ be destroyed, but its internal face_id reference will
00186    * be modified.
00187    *
00188    * The final result will be that the node will never come back
00189    * in further lookup requests, and will be flushed on demand from
00190    * the cache normally when its reference count reaches 0.
00191    */
00192   FT_LOCAL( void )
00193   FTC_Cache_RemoveFaceID( FTC_Cache   cache,
00194                           FTC_FaceID  face_id );
00195 
00196 
00197 #ifdef FTC_INLINE
00198 
00199 #define FTC_CACHE_LOOKUP_CMP( cache, nodecmp, hash, query, node, error ) \
00200   FT_BEGIN_STMNT                                                         \
00201     FTC_Node             *_bucket, *_pnode, _node;                       \
00202     FTC_Cache             _cache   = FTC_CACHE(cache);                   \
00203     FT_UInt32             _hash    = (FT_UInt32)(hash);                  \
00204     FTC_Node_CompareFunc  _nodcomp = (FTC_Node_CompareFunc)(nodecmp);    \
00205     FT_UFast              _idx;                                          \
00206                                                                          \
00207                                                                          \
00208     error = 0;                                                           \
00209     node  = NULL;                                                        \
00210     _idx  = _hash & _cache->mask;                                        \
00211     if ( _idx < _cache->p )                                              \
00212       _idx = _hash & ( _cache->mask*2 + 1 );                             \
00213                                                                          \
00214     _bucket = _pnode = _cache->buckets + _idx;                           \
00215     for (;;)                                                             \
00216     {                                                                    \
00217       _node = *_pnode;                                                   \
00218       if ( _node == NULL )                                               \
00219         goto _NewNode;                                                   \
00220                                                                          \
00221       if ( _node->hash == _hash && _nodcomp( _node, query, _cache ) )    \
00222         break;                                                           \
00223                                                                          \
00224       _pnode = &_node->link;                                             \
00225     }                                                                    \
00226                                                                          \
00227     if ( _node != *_bucket )                                             \
00228     {                                                                    \
00229       *_pnode     = _node->link;                                         \
00230       _node->link = *_bucket;                                            \
00231       *_bucket    = _node;                                               \
00232     }                                                                    \
00233                                                                          \
00234     {                                                                    \
00235       FTC_Manager  _manager = _cache->manager;                           \
00236       void*        _nl      = &_manager->nodes_list;                     \
00237                                                                          \
00238                                                                          \
00239       if ( _node != _manager->nodes_list )                               \
00240         FTC_MruNode_Up( (FTC_MruNode*)_nl,                               \
00241                         (FTC_MruNode)_node );                            \
00242     }                                                                    \
00243     goto _Ok;                                                            \
00244                                                                          \
00245   _NewNode:                                                              \
00246     error = FTC_Cache_NewNode( _cache, _hash, query, &_node );           \
00247                                                                          \
00248   _Ok:                                                                   \
00249     node = _node;                                                        \
00250   FT_END_STMNT
00251 
00252 #else /* !FTC_INLINE */
00253 
00254 #define FTC_CACHE_LOOKUP_CMP( cache, nodecmp, hash, query, node, error ) \
00255   FT_BEGIN_STMNT                                                         \
00256     error = FTC_Cache_Lookup( FTC_CACHE( cache ), hash, query,           \
00257                               (FTC_Node*)&(node) );                      \
00258   FT_END_STMNT
00259 
00260 #endif /* !FTC_INLINE */
00261 
00262 
00263   /*
00264    * This macro, together with FTC_CACHE_TRYLOOP_END, defines a retry
00265    * loop to flush the cache repeatedly in case of memory overflows.
00266    *
00267    * It is used when creating a new cache node, or within a lookup
00268    * that needs to allocate data (e.g., the sbit cache lookup).
00269    *
00270    * Example:
00271    *
00272    *   {
00273    *     FTC_CACHE_TRYLOOP( cache )
00274    *       error = load_data( ... );
00275    *     FTC_CACHE_TRYLOOP_END()
00276    *   }
00277    *
00278    */
00279 #define FTC_CACHE_TRYLOOP( cache )                           \
00280   {                                                          \
00281     FTC_Manager  _try_manager = FTC_CACHE( cache )->manager; \
00282     FT_UInt      _try_count   = 4;                           \
00283                                                              \
00284                                                              \
00285     for (;;)                                                 \
00286     {                                                        \
00287       FT_UInt  _try_done;
00288 
00289 
00290 #define FTC_CACHE_TRYLOOP_END()                                   \
00291       if ( !error || error != FT_Err_Out_Of_Memory )              \
00292         break;                                                    \
00293                                                                   \
00294       _try_done = FTC_Manager_FlushN( _try_manager, _try_count ); \
00295       if ( _try_done == 0 )                                       \
00296         break;                                                    \
00297                                                                   \
00298       if ( _try_done == _try_count )                              \
00299       {                                                           \
00300         _try_count *= 2;                                          \
00301         if ( _try_count < _try_done              ||               \
00302             _try_count > _try_manager->num_nodes )                \
00303           _try_count = _try_manager->num_nodes;                   \
00304       }                                                           \
00305     }                                                             \
00306   }
00307 
00308  /* */
00309 
00310 FT_END_HEADER
00311 
00312 
00313 #endif /* __FTCCACHE_H__ */
00314 
00315 
00316 /* END */

Generated on Tue Jul 5 14:13:45 2011 for ROOT_528-00b_version by  doxygen 1.5.1