Home | History | Annotate | Download | only in cache
      1 /***************************************************************************/
      2 /*                                                                         */
      3 /*  ftcglyph.h                                                             */
      4 /*                                                                         */
      5 /*    FreeType abstract glyph cache (specification).                       */
      6 /*                                                                         */
      7 /*  Copyright 2000-2018 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   /*
     20    *
     21    *  FTC_GCache is an _abstract_ cache object optimized to store glyph
     22    *  data.  It works as follows:
     23    *
     24    *   - It manages FTC_GNode objects. Each one of them can hold one or more
     25    *     glyph `items'.  Item types are not specified in the FTC_GCache but
     26    *     in classes that extend it.
     27    *
     28    *   - Glyph attributes, like face ID, character size, render mode, etc.,
     29    *     can be grouped into abstract `glyph families'.  This avoids storing
     30    *     the attributes within the FTC_GCache, since it is likely that many
     31    *     FTC_GNodes will belong to the same family in typical uses.
     32    *
     33    *   - Each FTC_GNode is thus an FTC_Node with two additional fields:
     34    *
     35    *       * gindex: A glyph index, or the first index in a glyph range.
     36    *       * family: A pointer to a glyph `family'.
     37    *
     38    *   - Family types are not fully specific in the FTC_Family type, but
     39    *     by classes that extend it.
     40    *
     41    *  Note that both FTC_ImageCache and FTC_SBitCache extend FTC_GCache.
     42    *  They share an FTC_Family sub-class called FTC_BasicFamily which is
     43    *  used to store the following data: face ID, pixel/point sizes, load
     44    *  flags.  For more details see the file `src/cache/ftcbasic.c'.
     45    *
     46    *  Client applications can extend FTC_GNode with their own FTC_GNode
     47    *  and FTC_Family sub-classes to implement more complex caches (e.g.,
     48    *  handling automatic synthesis, like obliquing & emboldening, colored
     49    *  glyphs, etc.).
     50    *
     51    *  See also the FTC_ICache & FTC_SCache classes in `ftcimage.h' and
     52    *  `ftcsbits.h', which both extend FTC_GCache with additional
     53    *  optimizations.
     54    *
     55    *  A typical FTC_GCache implementation must provide at least the
     56    *  following:
     57    *
     58    *  - FTC_GNode sub-class, e.g. MyNode, with relevant methods:
     59    *        my_node_new            (must call FTC_GNode_Init)
     60    *        my_node_free           (must call FTC_GNode_Done)
     61    *        my_node_compare        (must call FTC_GNode_Compare)
     62    *        my_node_remove_faceid  (must call ftc_gnode_unselect in case
     63    *                                of match)
     64    *
     65    *  - FTC_Family sub-class, e.g. MyFamily, with relevant methods:
     66    *        my_family_compare
     67    *        my_family_init
     68    *        my_family_reset (optional)
     69    *        my_family_done
     70    *
     71    *  - FTC_GQuery sub-class, e.g. MyQuery, to hold cache-specific query
     72    *    data.
     73    *
     74    *  - Constant structures for a FTC_GNodeClass.
     75    *
     76    *  - MyCacheNew() can be implemented easily as a call to the convenience
     77    *    function FTC_GCache_New.
     78    *
     79    *  - MyCacheLookup with a call to FTC_GCache_Lookup.  This function will
     80    *    automatically:
     81    *
     82    *    - Search for the corresponding family in the cache, or create
     83    *      a new one if necessary.  Put it in FTC_GQUERY(myquery).family
     84    *
     85    *    - Call FTC_Cache_Lookup.
     86    *
     87    *    If it returns NULL, you should create a new node, then call
     88    *    ftc_cache_add as usual.
     89    */
     90 
     91 
     92   /*************************************************************************/
     93   /*                                                                       */
     94   /* Important: The functions defined in this file are only used to        */
     95   /*            implement an abstract glyph cache class.  You need to      */
     96   /*            provide additional logic to implement a complete cache.    */
     97   /*                                                                       */
     98   /*************************************************************************/
     99 
    100 
    101   /*************************************************************************/
    102   /*************************************************************************/
    103   /*************************************************************************/
    104   /*************************************************************************/
    105   /*************************************************************************/
    106   /*********                                                       *********/
    107   /*********             WARNING, THIS IS BETA CODE.               *********/
    108   /*********                                                       *********/
    109   /*************************************************************************/
    110   /*************************************************************************/
    111   /*************************************************************************/
    112   /*************************************************************************/
    113   /*************************************************************************/
    114 
    115 
    116 #ifndef FTCGLYPH_H_
    117 #define FTCGLYPH_H_
    118 
    119 
    120 #include <ft2build.h>
    121 #include "ftcmanag.h"
    122 
    123 
    124 FT_BEGIN_HEADER
    125 
    126 
    127  /*
    128   *  We can group glyphs into `families'.  Each family correspond to a
    129   *  given face ID, character size, transform, etc.
    130   *
    131   *  Families are implemented as MRU list nodes.  They are
    132   *  reference-counted.
    133   */
    134 
    135   typedef struct  FTC_FamilyRec_
    136   {
    137     FTC_MruNodeRec    mrunode;
    138     FT_UInt           num_nodes; /* current number of nodes in this family */
    139     FTC_Cache         cache;
    140     FTC_MruListClass  clazz;
    141 
    142   } FTC_FamilyRec, *FTC_Family;
    143 
    144 #define  FTC_FAMILY(x)    ( (FTC_Family)(x) )
    145 #define  FTC_FAMILY_P(x)  ( (FTC_Family*)(x) )
    146 
    147 
    148   typedef struct  FTC_GNodeRec_
    149   {
    150     FTC_NodeRec      node;
    151     FTC_Family       family;
    152     FT_UInt          gindex;
    153 
    154   } FTC_GNodeRec, *FTC_GNode;
    155 
    156 #define FTC_GNODE( x )    ( (FTC_GNode)(x) )
    157 #define FTC_GNODE_P( x )  ( (FTC_GNode*)(x) )
    158 
    159 
    160   typedef struct  FTC_GQueryRec_
    161   {
    162     FT_UInt      gindex;
    163     FTC_Family   family;
    164 
    165   } FTC_GQueryRec, *FTC_GQuery;
    166 
    167 #define FTC_GQUERY( x )  ( (FTC_GQuery)(x) )
    168 
    169 
    170   /*************************************************************************/
    171   /*                                                                       */
    172   /* These functions are exported so that they can be called from          */
    173   /* user-provided cache classes; otherwise, they are really part of the   */
    174   /* cache sub-system internals.                                           */
    175   /*                                                                       */
    176 
    177   /* must be called by derived FTC_Node_InitFunc routines */
    178   FT_LOCAL( void )
    179   FTC_GNode_Init( FTC_GNode   node,
    180                   FT_UInt     gindex,  /* glyph index for node */
    181                   FTC_Family  family );
    182 
    183 #ifdef FTC_INLINE
    184 
    185   /* returns TRUE iff the query's glyph index correspond to the node;  */
    186   /* this assumes that the `family' and `hash' fields of the query are */
    187   /* already correctly set                                             */
    188   FT_LOCAL( FT_Bool )
    189   FTC_GNode_Compare( FTC_GNode   gnode,
    190                      FTC_GQuery  gquery,
    191                      FTC_Cache   cache,
    192                      FT_Bool*    list_changed );
    193 
    194 #endif
    195 
    196   /* call this function to clear a node's family -- this is necessary */
    197   /* to implement the `node_remove_faceid' cache method correctly     */
    198   FT_LOCAL( void )
    199   FTC_GNode_UnselectFamily( FTC_GNode  gnode,
    200                             FTC_Cache  cache );
    201 
    202   /* must be called by derived FTC_Node_DoneFunc routines */
    203   FT_LOCAL( void )
    204   FTC_GNode_Done( FTC_GNode  node,
    205                   FTC_Cache  cache );
    206 
    207 
    208   FT_LOCAL( void )
    209   FTC_Family_Init( FTC_Family  family,
    210                    FTC_Cache   cache );
    211 
    212   typedef struct FTC_GCacheRec_
    213   {
    214     FTC_CacheRec    cache;
    215     FTC_MruListRec  families;
    216 
    217   } FTC_GCacheRec, *FTC_GCache;
    218 
    219 #define FTC_GCACHE( x )  ((FTC_GCache)(x))
    220 
    221 
    222 #if 0
    223   /* can be used as @FTC_Cache_InitFunc */
    224   FT_LOCAL( FT_Error )
    225   FTC_GCache_Init( FTC_GCache  cache );
    226 #endif
    227 
    228 
    229 #if 0
    230   /* can be used as @FTC_Cache_DoneFunc */
    231   FT_LOCAL( void )
    232   FTC_GCache_Done( FTC_GCache  cache );
    233 #endif
    234 
    235 
    236   /* the glyph cache class adds fields for the family implementation */
    237   typedef struct  FTC_GCacheClassRec_
    238   {
    239     FTC_CacheClassRec  clazz;
    240     FTC_MruListClass   family_class;
    241 
    242   } FTC_GCacheClassRec;
    243 
    244   typedef const FTC_GCacheClassRec*   FTC_GCacheClass;
    245 
    246 #define FTC_GCACHE_CLASS( x )  ((FTC_GCacheClass)(x))
    247 
    248 #define FTC_CACHE_GCACHE_CLASS( x ) \
    249           FTC_GCACHE_CLASS( FTC_CACHE(x)->org_class )
    250 #define FTC_CACHE_FAMILY_CLASS( x ) \
    251           ( (FTC_MruListClass)FTC_CACHE_GCACHE_CLASS( x )->family_class )
    252 
    253 
    254   /* convenience function; use it instead of FTC_Manager_Register_Cache */
    255   FT_LOCAL( FT_Error )
    256   FTC_GCache_New( FTC_Manager       manager,
    257                   FTC_GCacheClass   clazz,
    258                   FTC_GCache       *acache );
    259 
    260 #ifndef FTC_INLINE
    261   FT_LOCAL( FT_Error )
    262   FTC_GCache_Lookup( FTC_GCache   cache,
    263                      FT_Offset    hash,
    264                      FT_UInt      gindex,
    265                      FTC_GQuery   query,
    266                      FTC_Node    *anode );
    267 #endif
    268 
    269 
    270   /* */
    271 
    272 
    273 #define FTC_FAMILY_FREE( family, cache )                      \
    274           FTC_MruList_Remove( &FTC_GCACHE((cache))->families, \
    275                               (FTC_MruNode)(family) )
    276 
    277 
    278 #ifdef FTC_INLINE
    279 
    280 #define FTC_GCACHE_LOOKUP_CMP( cache, famcmp, nodecmp, hash,                \
    281                                gindex, query, node, error )                 \
    282   FT_BEGIN_STMNT                                                            \
    283     FTC_GCache               _gcache   = FTC_GCACHE( cache );               \
    284     FTC_GQuery               _gquery   = (FTC_GQuery)( query );             \
    285     FTC_MruNode_CompareFunc  _fcompare = (FTC_MruNode_CompareFunc)(famcmp); \
    286     FTC_MruNode              _mrunode;                                      \
    287                                                                             \
    288                                                                             \
    289     _gquery->gindex = (gindex);                                             \
    290                                                                             \
    291     FTC_MRULIST_LOOKUP_CMP( &_gcache->families, _gquery, _fcompare,         \
    292                             _mrunode, error );                              \
    293     _gquery->family = FTC_FAMILY( _mrunode );                               \
    294     if ( !error )                                                           \
    295     {                                                                       \
    296       FTC_Family  _gqfamily = _gquery->family;                              \
    297                                                                             \
    298                                                                             \
    299       _gqfamily->num_nodes++;                                               \
    300                                                                             \
    301       FTC_CACHE_LOOKUP_CMP( cache, nodecmp, hash, query, node, error );     \
    302                                                                             \
    303       if ( --_gqfamily->num_nodes == 0 )                                    \
    304         FTC_FAMILY_FREE( _gqfamily, _gcache );                              \
    305     }                                                                       \
    306   FT_END_STMNT
    307   /* */
    308 
    309 #else /* !FTC_INLINE */
    310 
    311 #define FTC_GCACHE_LOOKUP_CMP( cache, famcmp, nodecmp, hash,          \
    312                                gindex, query, node, error )           \
    313    FT_BEGIN_STMNT                                                     \
    314                                                                       \
    315      error = FTC_GCache_Lookup( FTC_GCACHE( cache ), hash, gindex,    \
    316                                 FTC_GQUERY( query ), &node );         \
    317                                                                       \
    318    FT_END_STMNT
    319 
    320 #endif /* !FTC_INLINE */
    321 
    322 
    323 FT_END_HEADER
    324 
    325 
    326 #endif /* FTCGLYPH_H_ */
    327 
    328 
    329 /* END */
    330