Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /***************************************************************************/
  2. /*                                                                         */
  3. /*  ftccache.h                                                             */
  4. /*                                                                         */
  5. /*    FreeType internal cache interface (specification).                   */
  6. /*                                                                         */
  7. /*  Copyright 2000-2007, 2009-2011, 2013 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 "ftcmru.h"
  24.  
  25. FT_BEGIN_HEADER
  26.  
  27. #define _FTC_FACE_ID_HASH( i )                                                \
  28.           ((FT_PtrDist)(( (FT_PtrDist)(i) >> 3 ) ^ ( (FT_PtrDist)(i) << 7 )))
  29.  
  30.   /* handle to cache object */
  31.   typedef struct FTC_CacheRec_*  FTC_Cache;
  32.  
  33.   /* handle to cache class */
  34.   typedef const struct FTC_CacheClassRec_*  FTC_CacheClass;
  35.  
  36.  
  37.   /*************************************************************************/
  38.   /*************************************************************************/
  39.   /*****                                                               *****/
  40.   /*****                   CACHE NODE DEFINITIONS                      *****/
  41.   /*****                                                               *****/
  42.   /*************************************************************************/
  43.   /*************************************************************************/
  44.  
  45.   /*************************************************************************/
  46.   /*                                                                       */
  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.                                         */
  50.   /*                                                                       */
  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.                           */
  54.   /*                                                                       */
  55.   /*************************************************************************/
  56.  
  57.   /* structure size should be 20 bytes on 32-bits machines */
  58.   typedef struct  FTC_NodeRec_
  59.   {
  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       */
  65.  
  66.   } FTC_NodeRec;
  67.  
  68.  
  69. #define FTC_NODE( x )    ( (FTC_Node)(x) )
  70. #define FTC_NODE_P( x )  ( (FTC_Node*)(x) )
  71.  
  72. #define FTC_NODE__NEXT( x )  FTC_NODE( (x)->mru.next )
  73. #define FTC_NODE__PREV( x )  FTC_NODE( (x)->mru.prev )
  74.  
  75. #ifdef FTC_INLINE
  76. #define FTC_NODE__TOP_FOR_HASH( cache, hash )                     \
  77.         ( ( cache )->buckets +                                    \
  78.             ( ( ( ( hash ) &   ( cache )->mask ) < ( cache )->p ) \
  79.               ? ( ( hash ) & ( ( cache )->mask * 2 + 1 ) )        \
  80.               : ( ( hash ) &   ( cache )->mask ) ) )
  81. #else
  82.   FT_LOCAL( FTC_Node* )
  83.   ftc_get_top_node_for_hash( FTC_Cache   cache,
  84.                              FT_PtrDist  hash );
  85. #define FTC_NODE__TOP_FOR_HASH( cache, hash )            \
  86.         ftc_get_top_node_for_hash( ( cache ), ( hash ) )
  87. #endif
  88.  
  89.  
  90.   /*************************************************************************/
  91.   /*************************************************************************/
  92.   /*****                                                               *****/
  93.   /*****                       CACHE DEFINITIONS                       *****/
  94.   /*****                                                               *****/
  95.   /*************************************************************************/
  96.   /*************************************************************************/
  97.  
  98.   /* initialize a new cache node */
  99.   typedef FT_Error
  100.   (*FTC_Node_NewFunc)( FTC_Node    *pnode,
  101.                        FT_Pointer   query,
  102.                        FTC_Cache    cache );
  103.  
  104.   typedef FT_Offset
  105.   (*FTC_Node_WeightFunc)( FTC_Node   node,
  106.                           FTC_Cache  cache );
  107.  
  108.   /* compare a node to a given key pair */
  109.   typedef FT_Bool
  110.   (*FTC_Node_CompareFunc)( FTC_Node    node,
  111.                            FT_Pointer  key,
  112.                            FTC_Cache   cache,
  113.                            FT_Bool*    list_changed );
  114.  
  115.  
  116.   typedef void
  117.   (*FTC_Node_FreeFunc)( FTC_Node   node,
  118.                         FTC_Cache  cache );
  119.  
  120.   typedef FT_Error
  121.   (*FTC_Cache_InitFunc)( FTC_Cache  cache );
  122.  
  123.   typedef void
  124.   (*FTC_Cache_DoneFunc)( FTC_Cache  cache );
  125.  
  126.  
  127.   typedef struct  FTC_CacheClassRec_
  128.   {
  129.     FTC_Node_NewFunc      node_new;
  130.     FTC_Node_WeightFunc   node_weight;
  131.     FTC_Node_CompareFunc  node_compare;
  132.     FTC_Node_CompareFunc  node_remove_faceid;
  133.     FTC_Node_FreeFunc     node_free;
  134.  
  135.     FT_Offset             cache_size;
  136.     FTC_Cache_InitFunc    cache_init;
  137.     FTC_Cache_DoneFunc    cache_done;
  138.  
  139.   } FTC_CacheClassRec;
  140.  
  141.  
  142.   /* each cache really implements a dynamic hash table to manage its nodes */
  143.   typedef struct  FTC_CacheRec_
  144.   {
  145.     FT_UFast           p;
  146.     FT_UFast           mask;
  147.     FT_Long            slack;
  148.     FTC_Node*          buckets;
  149.  
  150.     FTC_CacheClassRec  clazz;       /* local copy, for speed  */
  151.  
  152.     FTC_Manager        manager;
  153.     FT_Memory          memory;
  154.     FT_UInt            index;       /* in manager's table     */
  155.  
  156.     FTC_CacheClass     org_class;   /* original class pointer */
  157.  
  158.   } FTC_CacheRec;
  159.  
  160.  
  161. #define FTC_CACHE( x )    ( (FTC_Cache)(x) )
  162. #define FTC_CACHE_P( x )  ( (FTC_Cache*)(x) )
  163.  
  164.  
  165.   /* default cache initialize */
  166.   FT_LOCAL( FT_Error )
  167.   FTC_Cache_Init( FTC_Cache  cache );
  168.  
  169.   /* default cache finalizer */
  170.   FT_LOCAL( void )
  171.   FTC_Cache_Done( FTC_Cache  cache );
  172.  
  173.   /* Call this function to look up the cache.  If no corresponding
  174.    * node is found, a new one is automatically created.  This function
  175.    * is capable of flushing the cache adequately to make room for the
  176.    * new cache object.
  177.    */
  178.  
  179. #ifndef FTC_INLINE
  180.   FT_LOCAL( FT_Error )
  181.   FTC_Cache_Lookup( FTC_Cache   cache,
  182.                     FT_PtrDist  hash,
  183.                     FT_Pointer  query,
  184.                     FTC_Node   *anode );
  185. #endif
  186.  
  187.   FT_LOCAL( FT_Error )
  188.   FTC_Cache_NewNode( FTC_Cache   cache,
  189.                      FT_PtrDist  hash,
  190.                      FT_Pointer  query,
  191.                      FTC_Node   *anode );
  192.  
  193.   /* Remove all nodes that relate to a given face_id.  This is useful
  194.    * when un-installing fonts.  Note that if a cache node relates to
  195.    * the face_id but is locked (i.e., has `ref_count > 0'), the node
  196.    * will _not_ be destroyed, but its internal face_id reference will
  197.    * be modified.
  198.    *
  199.    * The final result will be that the node will never come back
  200.    * in further lookup requests, and will be flushed on demand from
  201.    * the cache normally when its reference count reaches 0.
  202.    */
  203.   FT_LOCAL( void )
  204.   FTC_Cache_RemoveFaceID( FTC_Cache   cache,
  205.                           FTC_FaceID  face_id );
  206.  
  207.  
  208. #ifdef FTC_INLINE
  209.  
  210. #define FTC_CACHE_LOOKUP_CMP( cache, nodecmp, hash, query, node, error ) \
  211.   FT_BEGIN_STMNT                                                         \
  212.     FTC_Node             *_bucket, *_pnode, _node;                       \
  213.     FTC_Cache             _cache   = FTC_CACHE(cache);                   \
  214.     FT_PtrDist            _hash    = (FT_PtrDist)(hash);                 \
  215.     FTC_Node_CompareFunc  _nodcomp = (FTC_Node_CompareFunc)(nodecmp);    \
  216.     FT_Bool               _list_changed = FALSE;                         \
  217.                                                                          \
  218.                                                                          \
  219.     error = FT_Err_Ok;                                                   \
  220.     node  = NULL;                                                        \
  221.                                                                          \
  222.     /* Go to the `top' node of the list sharing same masked hash */      \
  223.     _bucket = _pnode = FTC_NODE__TOP_FOR_HASH( _cache, _hash );          \
  224.                                                                          \
  225.     /* Look up a node with identical hash and queried properties.    */  \
  226.     /* NOTE: _nodcomp() may change the linked list to reduce memory. */  \
  227.     for (;;)                                                             \
  228.     {                                                                    \
  229.       _node = *_pnode;                                                   \
  230.       if ( _node == NULL )                                               \
  231.         goto _NewNode;                                                   \
  232.                                                                          \
  233.       if ( _node->hash == _hash                             &&           \
  234.            _nodcomp( _node, query, _cache, &_list_changed ) )            \
  235.         break;                                                           \
  236.                                                                          \
  237.       _pnode = &_node->link;                                             \
  238.     }                                                                    \
  239.                                                                          \
  240.     if ( _list_changed )                                                 \
  241.     {                                                                    \
  242.       /* Update _bucket by possibly modified linked list */              \
  243.       _bucket = _pnode = FTC_NODE__TOP_FOR_HASH( _cache, _hash );        \
  244.                                                                          \
  245.       /* Update _pnode by possibly modified linked list */               \
  246.       while ( *_pnode != _node )                                         \
  247.       {                                                                  \
  248.         if ( *_pnode == NULL )                                           \
  249.         {                                                                \
  250.           FT_ERROR(( "FTC_CACHE_LOOKUP_CMP: oops!!! node missing\n" ));  \
  251.           goto _NewNode;                                                 \
  252.         }                                                                \
  253.         else                                                             \
  254.           _pnode = &((*_pnode)->link);                                   \
  255.       }                                                                  \
  256.     }                                                                    \
  257.                                                                          \
  258.     /* Reorder the list to move the found node to the `top' */           \
  259.     if ( _node != *_bucket )                                             \
  260.     {                                                                    \
  261.       *_pnode     = _node->link;                                         \
  262.       _node->link = *_bucket;                                            \
  263.       *_bucket    = _node;                                               \
  264.     }                                                                    \
  265.                                                                          \
  266.     /* Update MRU list */                                                \
  267.     {                                                                    \
  268.       FTC_Manager  _manager = _cache->manager;                           \
  269.       void*        _nl      = &_manager->nodes_list;                     \
  270.                                                                          \
  271.                                                                          \
  272.       if ( _node != _manager->nodes_list )                               \
  273.         FTC_MruNode_Up( (FTC_MruNode*)_nl,                               \
  274.                         (FTC_MruNode)_node );                            \
  275.     }                                                                    \
  276.     goto _Ok;                                                            \
  277.                                                                          \
  278.   _NewNode:                                                              \
  279.     error = FTC_Cache_NewNode( _cache, _hash, query, &_node );           \
  280.                                                                          \
  281.   _Ok:                                                                   \
  282.     node = _node;                                                        \
  283.   FT_END_STMNT
  284.  
  285. #else /* !FTC_INLINE */
  286.  
  287. #define FTC_CACHE_LOOKUP_CMP( cache, nodecmp, hash, query, node, error ) \
  288.   FT_BEGIN_STMNT                                                         \
  289.     error = FTC_Cache_Lookup( FTC_CACHE( cache ), hash, query,           \
  290.                               (FTC_Node*)&(node) );                      \
  291.   FT_END_STMNT
  292.  
  293. #endif /* !FTC_INLINE */
  294.  
  295.  
  296.   /*
  297.    * This macro, together with FTC_CACHE_TRYLOOP_END, defines a retry
  298.    * loop to flush the cache repeatedly in case of memory overflows.
  299.    *
  300.    * It is used when creating a new cache node, or within a lookup
  301.    * that needs to allocate data (e.g. the sbit cache lookup).
  302.    *
  303.    * Example:
  304.    *
  305.    *   {
  306.    *     FTC_CACHE_TRYLOOP( cache )
  307.    *       error = load_data( ... );
  308.    *     FTC_CACHE_TRYLOOP_END()
  309.    *   }
  310.    *
  311.    */
  312. #define FTC_CACHE_TRYLOOP( cache )                           \
  313.   {                                                          \
  314.     FTC_Manager  _try_manager = FTC_CACHE( cache )->manager; \
  315.     FT_UInt      _try_count   = 4;                           \
  316.                                                              \
  317.                                                              \
  318.     for (;;)                                                 \
  319.     {                                                        \
  320.       FT_UInt  _try_done;
  321.  
  322.  
  323. #define FTC_CACHE_TRYLOOP_END( list_changed )                     \
  324.       if ( !error || FT_ERR_NEQ( error, Out_Of_Memory ) )         \
  325.         break;                                                    \
  326.                                                                   \
  327.       _try_done = FTC_Manager_FlushN( _try_manager, _try_count ); \
  328.       if ( _try_done > 0 && ( list_changed ) )                    \
  329.         *(FT_Bool*)( list_changed ) = TRUE;                       \
  330.                                                                   \
  331.       if ( _try_done == 0 )                                       \
  332.         break;                                                    \
  333.                                                                   \
  334.       if ( _try_done == _try_count )                              \
  335.       {                                                           \
  336.         _try_count *= 2;                                          \
  337.         if ( _try_count < _try_done              ||               \
  338.             _try_count > _try_manager->num_nodes )                \
  339.           _try_count = _try_manager->num_nodes;                   \
  340.       }                                                           \
  341.     }                                                             \
  342.   }
  343.  
  344.  /* */
  345.  
  346. FT_END_HEADER
  347.  
  348.  
  349. #endif /* __FTCCACHE_H__ */
  350.  
  351.  
  352. /* END */
  353.