/src/freetype/src/cache/ftccache.h

https://bitbucket.org/cabalistic/ogredeps/ · C++ Header · 359 lines · 214 code · 62 blank · 83 comment · 28 complexity · 065f3b10a5a11df6fa37e4c0f06cea5e MD5 · raw file

  1. /***************************************************************************/
  2. /* */
  3. /* ftccache.h */
  4. /* */
  5. /* FreeType internal cache interface (specification). */
  6. /* */
  7. /* Copyright 2000-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2009, 2010, */
  8. /* 2011 by */
  9. /* David Turner, Robert Wilhelm, and Werner Lemberg. */
  10. /* */
  11. /* This file is part of the FreeType project, and may only be used, */
  12. /* modified, and distributed under the terms of the FreeType project */
  13. /* license, LICENSE.TXT. By continuing to use, modify, or distribute */
  14. /* this file you indicate that you have read the license and */
  15. /* understand and accept it fully. */
  16. /* */
  17. /***************************************************************************/
  18. #ifndef __FTCCACHE_H__
  19. #define __FTCCACHE_H__
  20. #include "ftcmru.h"
  21. FT_BEGIN_HEADER
  22. #define _FTC_FACE_ID_HASH( i ) \
  23. ((FT_PtrDist)(( (FT_PtrDist)(i) >> 3 ) ^ ( (FT_PtrDist)(i) << 7 )))
  24. /* handle to cache object */
  25. typedef struct FTC_CacheRec_* FTC_Cache;
  26. /* handle to cache class */
  27. typedef const struct FTC_CacheClassRec_* FTC_CacheClass;
  28. /*************************************************************************/
  29. /*************************************************************************/
  30. /***** *****/
  31. /***** CACHE NODE DEFINITIONS *****/
  32. /***** *****/
  33. /*************************************************************************/
  34. /*************************************************************************/
  35. /*************************************************************************/
  36. /* */
  37. /* Each cache controls one or more cache nodes. Each node is part of */
  38. /* the global_lru list of the manager. Its `data' field however is used */
  39. /* as a reference count for now. */
  40. /* */
  41. /* A node can be anything, depending on the type of information held by */
  42. /* the cache. It can be an individual glyph image, a set of bitmaps */
  43. /* glyphs for a given size, some metrics, etc. */
  44. /* */
  45. /*************************************************************************/
  46. /* structure size should be 20 bytes on 32-bits machines */
  47. typedef struct FTC_NodeRec_
  48. {
  49. FTC_MruNodeRec mru; /* circular mru list pointer */
  50. FTC_Node link; /* used for hashing */
  51. FT_PtrDist hash; /* used for hashing too */
  52. FT_UShort cache_index; /* index of cache the node belongs to */
  53. FT_Short ref_count; /* reference count for this node */
  54. } FTC_NodeRec;
  55. #define FTC_NODE( x ) ( (FTC_Node)(x) )
  56. #define FTC_NODE_P( x ) ( (FTC_Node*)(x) )
  57. #define FTC_NODE__NEXT( x ) FTC_NODE( (x)->mru.next )
  58. #define FTC_NODE__PREV( x ) FTC_NODE( (x)->mru.prev )
  59. #ifdef FTC_INLINE
  60. #define FTC_NODE__TOP_FOR_HASH( cache, hash ) \
  61. ( ( cache )->buckets + \
  62. ( ( ( ( hash ) & ( cache )->mask ) < ( cache )->p ) \
  63. ? ( ( hash ) & ( ( cache )->mask * 2 + 1 ) ) \
  64. : ( ( hash ) & ( cache )->mask ) ) )
  65. #else
  66. FT_LOCAL( FTC_Node* )
  67. ftc_get_top_node_for_hash( FTC_Cache cache,
  68. FT_PtrDist hash );
  69. #define FTC_NODE__TOP_FOR_HASH( cache, hash ) \
  70. ftc_get_top_node_for_hash( ( cache ), ( hash ) )
  71. #endif
  72. #ifdef FT_CONFIG_OPTION_OLD_INTERNALS
  73. FT_BASE( void )
  74. ftc_node_destroy( FTC_Node node,
  75. FTC_Manager manager );
  76. #endif
  77. /*************************************************************************/
  78. /*************************************************************************/
  79. /***** *****/
  80. /***** CACHE DEFINITIONS *****/
  81. /***** *****/
  82. /*************************************************************************/
  83. /*************************************************************************/
  84. /* initialize a new cache node */
  85. typedef FT_Error
  86. (*FTC_Node_NewFunc)( FTC_Node *pnode,
  87. FT_Pointer query,
  88. FTC_Cache cache );
  89. typedef FT_Offset
  90. (*FTC_Node_WeightFunc)( FTC_Node node,
  91. FTC_Cache cache );
  92. /* compare a node to a given key pair */
  93. typedef FT_Bool
  94. (*FTC_Node_CompareFunc)( FTC_Node node,
  95. FT_Pointer key,
  96. FTC_Cache cache,
  97. FT_Bool* list_changed );
  98. typedef void
  99. (*FTC_Node_FreeFunc)( FTC_Node node,
  100. FTC_Cache cache );
  101. typedef FT_Error
  102. (*FTC_Cache_InitFunc)( FTC_Cache cache );
  103. typedef void
  104. (*FTC_Cache_DoneFunc)( FTC_Cache cache );
  105. typedef struct FTC_CacheClassRec_
  106. {
  107. FTC_Node_NewFunc node_new;
  108. FTC_Node_WeightFunc node_weight;
  109. FTC_Node_CompareFunc node_compare;
  110. FTC_Node_CompareFunc node_remove_faceid;
  111. FTC_Node_FreeFunc node_free;
  112. FT_Offset cache_size;
  113. FTC_Cache_InitFunc cache_init;
  114. FTC_Cache_DoneFunc cache_done;
  115. } FTC_CacheClassRec;
  116. /* each cache really implements a dynamic hash table to manage its nodes */
  117. typedef struct FTC_CacheRec_
  118. {
  119. FT_UFast p;
  120. FT_UFast mask;
  121. FT_Long slack;
  122. FTC_Node* buckets;
  123. FTC_CacheClassRec clazz; /* local copy, for speed */
  124. FTC_Manager manager;
  125. FT_Memory memory;
  126. FT_UInt index; /* in manager's table */
  127. FTC_CacheClass org_class; /* original class pointer */
  128. } FTC_CacheRec;
  129. #define FTC_CACHE( x ) ( (FTC_Cache)(x) )
  130. #define FTC_CACHE_P( x ) ( (FTC_Cache*)(x) )
  131. /* default cache initialize */
  132. FT_LOCAL( FT_Error )
  133. FTC_Cache_Init( FTC_Cache cache );
  134. /* default cache finalizer */
  135. FT_LOCAL( void )
  136. FTC_Cache_Done( FTC_Cache cache );
  137. /* Call this function to look up the cache. If no corresponding
  138. * node is found, a new one is automatically created. This function
  139. * is capable of flushing the cache adequately to make room for the
  140. * new cache object.
  141. */
  142. #ifndef FTC_INLINE
  143. FT_LOCAL( FT_Error )
  144. FTC_Cache_Lookup( FTC_Cache cache,
  145. FT_PtrDist hash,
  146. FT_Pointer query,
  147. FTC_Node *anode );
  148. #endif
  149. FT_LOCAL( FT_Error )
  150. FTC_Cache_NewNode( FTC_Cache cache,
  151. FT_PtrDist hash,
  152. FT_Pointer query,
  153. FTC_Node *anode );
  154. /* Remove all nodes that relate to a given face_id. This is useful
  155. * when un-installing fonts. Note that if a cache node relates to
  156. * the face_id but is locked (i.e., has `ref_count > 0'), the node
  157. * will _not_ be destroyed, but its internal face_id reference will
  158. * be modified.
  159. *
  160. * The final result will be that the node will never come back
  161. * in further lookup requests, and will be flushed on demand from
  162. * the cache normally when its reference count reaches 0.
  163. */
  164. FT_LOCAL( void )
  165. FTC_Cache_RemoveFaceID( FTC_Cache cache,
  166. FTC_FaceID face_id );
  167. #ifdef FTC_INLINE
  168. #define FTC_CACHE_LOOKUP_CMP( cache, nodecmp, hash, query, node, error ) \
  169. FT_BEGIN_STMNT \
  170. FTC_Node *_bucket, *_pnode, _node; \
  171. FTC_Cache _cache = FTC_CACHE(cache); \
  172. FT_PtrDist _hash = (FT_PtrDist)(hash); \
  173. FTC_Node_CompareFunc _nodcomp = (FTC_Node_CompareFunc)(nodecmp); \
  174. FT_Bool _list_changed = FALSE; \
  175. \
  176. \
  177. error = FTC_Err_Ok; \
  178. node = NULL; \
  179. \
  180. /* Go to the `top' node of the list sharing same masked hash */ \
  181. _bucket = _pnode = FTC_NODE__TOP_FOR_HASH( _cache, _hash ); \
  182. \
  183. /* Look up a node with identical hash and queried properties. */ \
  184. /* NOTE: _nodcomp() may change the linked list to reduce memory. */ \
  185. for (;;) \
  186. { \
  187. _node = *_pnode; \
  188. if ( _node == NULL ) \
  189. goto _NewNode; \
  190. \
  191. if ( _node->hash == _hash && \
  192. _nodcomp( _node, query, _cache, &_list_changed ) ) \
  193. break; \
  194. \
  195. _pnode = &_node->link; \
  196. } \
  197. \
  198. if ( _list_changed ) \
  199. { \
  200. /* Update _bucket by possibly modified linked list */ \
  201. _bucket = _pnode = FTC_NODE__TOP_FOR_HASH( _cache, _hash ); \
  202. \
  203. /* Update _pnode by possibly modified linked list */ \
  204. while ( *_pnode != _node ) \
  205. { \
  206. if ( *_pnode == NULL ) \
  207. { \
  208. FT_ERROR(( "FTC_CACHE_LOOKUP_CMP: oops!!! node missing\n" )); \
  209. goto _NewNode; \
  210. } \
  211. else \
  212. _pnode = &((*_pnode)->link); \
  213. } \
  214. } \
  215. \
  216. /* Reorder the list to move the found node to the `top' */ \
  217. if ( _node != *_bucket ) \
  218. { \
  219. *_pnode = _node->link; \
  220. _node->link = *_bucket; \
  221. *_bucket = _node; \
  222. } \
  223. \
  224. /* Update MRU list */ \
  225. { \
  226. FTC_Manager _manager = _cache->manager; \
  227. void* _nl = &_manager->nodes_list; \
  228. \
  229. \
  230. if ( _node != _manager->nodes_list ) \
  231. FTC_MruNode_Up( (FTC_MruNode*)_nl, \
  232. (FTC_MruNode)_node ); \
  233. } \
  234. goto _Ok; \
  235. \
  236. _NewNode: \
  237. error = FTC_Cache_NewNode( _cache, _hash, query, &_node ); \
  238. \
  239. _Ok: \
  240. node = _node; \
  241. FT_END_STMNT
  242. #else /* !FTC_INLINE */
  243. #define FTC_CACHE_LOOKUP_CMP( cache, nodecmp, hash, query, node, error ) \
  244. FT_BEGIN_STMNT \
  245. error = FTC_Cache_Lookup( FTC_CACHE( cache ), hash, query, \
  246. (FTC_Node*)&(node) ); \
  247. FT_END_STMNT
  248. #endif /* !FTC_INLINE */
  249. /*
  250. * This macro, together with FTC_CACHE_TRYLOOP_END, defines a retry
  251. * loop to flush the cache repeatedly in case of memory overflows.
  252. *
  253. * It is used when creating a new cache node, or within a lookup
  254. * that needs to allocate data (e.g. the sbit cache lookup).
  255. *
  256. * Example:
  257. *
  258. * {
  259. * FTC_CACHE_TRYLOOP( cache )
  260. * error = load_data( ... );
  261. * FTC_CACHE_TRYLOOP_END()
  262. * }
  263. *
  264. */
  265. #define FTC_CACHE_TRYLOOP( cache ) \
  266. { \
  267. FTC_Manager _try_manager = FTC_CACHE( cache )->manager; \
  268. FT_UInt _try_count = 4; \
  269. \
  270. \
  271. for (;;) \
  272. { \
  273. FT_UInt _try_done;
  274. #define FTC_CACHE_TRYLOOP_END( list_changed ) \
  275. if ( !error || error != FTC_Err_Out_Of_Memory ) \
  276. break; \
  277. \
  278. _try_done = FTC_Manager_FlushN( _try_manager, _try_count ); \
  279. if ( _try_done > 0 && ( list_changed ) ) \
  280. *(FT_Bool*)( list_changed ) = TRUE; \
  281. \
  282. if ( _try_done == 0 ) \
  283. break; \
  284. \
  285. if ( _try_done == _try_count ) \
  286. { \
  287. _try_count *= 2; \
  288. if ( _try_count < _try_done || \
  289. _try_count > _try_manager->num_nodes ) \
  290. _try_count = _try_manager->num_nodes; \
  291. } \
  292. } \
  293. }
  294. /* */
  295. FT_END_HEADER
  296. #endif /* __FTCCACHE_H__ */
  297. /* END */