(root)/
freetype-2.13.2/
src/
cache/
ftcglyph.h
       1  /****************************************************************************
       2   *
       3   * ftcglyph.h
       4   *
       5   *   FreeType abstract glyph cache (specification).
       6   *
       7   * Copyright (C) 2000-2023 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 "ftcmanag.h"
     121  
     122  
     123  FT_BEGIN_HEADER
     124  
     125  
     126   /*
     127    * We can group glyphs into `families'.  Each family correspond to a
     128    * given face ID, character size, transform, etc.
     129    *
     130    * Families are implemented as MRU list nodes.  They are
     131    * reference-counted.
     132    */
     133  
     134    typedef struct  FTC_FamilyRec_
     135    {
     136      FTC_MruNodeRec    mrunode;
     137      FT_UInt           num_nodes; /* current number of nodes in this family */
     138      FTC_Cache         cache;
     139      FTC_MruListClass  clazz;
     140  
     141    } FTC_FamilyRec, *FTC_Family;
     142  
     143  #define  FTC_FAMILY( x )    ( (FTC_Family)(x) )
     144  #define  FTC_FAMILY_P( x )  ( (FTC_Family*)(x) )
     145  
     146  
     147    typedef struct  FTC_GNodeRec_
     148    {
     149      FTC_NodeRec      node;
     150      FTC_Family       family;
     151      FT_UInt          gindex;
     152  
     153    } FTC_GNodeRec, *FTC_GNode;
     154  
     155  #define FTC_GNODE( x )    ( (FTC_GNode)(x) )
     156  #define FTC_GNODE_P( x )  ( (FTC_GNode*)(x) )
     157  
     158  
     159    typedef struct  FTC_GQueryRec_
     160    {
     161      FT_UInt      gindex;
     162      FTC_Family   family;
     163  
     164    } FTC_GQueryRec, *FTC_GQuery;
     165  
     166  #define FTC_GQUERY( x )  ( (FTC_GQuery)(x) )
     167  
     168  
     169    /**************************************************************************
     170     *
     171     * These functions are exported so that they can be called from
     172     * user-provided cache classes; otherwise, they are really part of the
     173     * cache sub-system internals.
     174     */
     175  
     176    /* must be called by derived FTC_Node_InitFunc routines */
     177    FT_LOCAL( void )
     178    FTC_GNode_Init( FTC_GNode   node,
     179                    FT_UInt     gindex,  /* glyph index for node */
     180                    FTC_Family  family );
     181  
     182    /* call this function to clear a node's family -- this is necessary */
     183    /* to implement the `node_remove_faceid' cache method correctly     */
     184    FT_LOCAL( void )
     185    FTC_GNode_UnselectFamily( FTC_GNode  gnode,
     186                              FTC_Cache  cache );
     187  
     188    /* must be called by derived FTC_Node_DoneFunc routines */
     189    FT_LOCAL( void )
     190    FTC_GNode_Done( FTC_GNode  node,
     191                    FTC_Cache  cache );
     192  
     193  
     194    FT_LOCAL( void )
     195    FTC_Family_Init( FTC_Family  family,
     196                     FTC_Cache   cache );
     197  
     198    typedef struct FTC_GCacheRec_
     199    {
     200      FTC_CacheRec    cache;
     201      FTC_MruListRec  families;
     202  
     203    } FTC_GCacheRec, *FTC_GCache;
     204  
     205  #define FTC_GCACHE( x )  ((FTC_GCache)(x))
     206  
     207  
     208  #if 0
     209    /* can be used as @FTC_Cache_InitFunc */
     210    FT_LOCAL( FT_Error )
     211    FTC_GCache_Init( FTC_GCache  cache );
     212  #endif
     213  
     214  
     215  #if 0
     216    /* can be used as @FTC_Cache_DoneFunc */
     217    FT_LOCAL( void )
     218    FTC_GCache_Done( FTC_GCache  cache );
     219  #endif
     220  
     221  
     222    /* the glyph cache class adds fields for the family implementation */
     223    typedef struct  FTC_GCacheClassRec_
     224    {
     225      FTC_CacheClassRec  clazz;
     226      FTC_MruListClass   family_class;
     227  
     228    } FTC_GCacheClassRec;
     229  
     230    typedef const FTC_GCacheClassRec*   FTC_GCacheClass;
     231  
     232  #define FTC_GCACHE_CLASS( x )  ((FTC_GCacheClass)(x))
     233  
     234  #define FTC_CACHE_GCACHE_CLASS( x ) \
     235            FTC_GCACHE_CLASS( FTC_CACHE( x )->org_class )
     236  #define FTC_CACHE_FAMILY_CLASS( x ) \
     237            ( (FTC_MruListClass)FTC_CACHE_GCACHE_CLASS( x )->family_class )
     238  
     239  
     240    /* convenience function; use it instead of FTC_Manager_Register_Cache */
     241    FT_LOCAL( FT_Error )
     242    FTC_GCache_New( FTC_Manager       manager,
     243                    FTC_GCacheClass   clazz,
     244                    FTC_GCache       *acache );
     245  
     246  #ifndef FTC_INLINE
     247    FT_LOCAL( FT_Error )
     248    FTC_GCache_Lookup( FTC_GCache   cache,
     249                       FT_Offset    hash,
     250                       FT_UInt      gindex,
     251                       FTC_GQuery   query,
     252                       FTC_Node    *anode );
     253  #endif
     254  
     255  
     256    /* */
     257  
     258  
     259  #define FTC_FAMILY_FREE( family, cache )                      \
     260            FTC_MruList_Remove( &FTC_GCACHE((cache))->families, \
     261                                (FTC_MruNode)(family) )
     262  
     263  
     264  #ifdef FTC_INLINE
     265  
     266  #define FTC_GCACHE_LOOKUP_CMP( cache, famcmp, nodecmp, hash,                \
     267                                 gindex, query, node, error )                 \
     268    FT_BEGIN_STMNT                                                            \
     269      FTC_GCache               _gcache   = FTC_GCACHE( cache );               \
     270      FTC_GQuery               _gquery   = (FTC_GQuery)( query );             \
     271      FTC_MruNode_CompareFunc  _fcompare = (FTC_MruNode_CompareFunc)(famcmp); \
     272      FTC_MruNode              _mrunode;                                      \
     273                                                                              \
     274                                                                              \
     275      _gquery->gindex = (gindex);                                             \
     276                                                                              \
     277      FTC_MRULIST_LOOKUP_CMP( &_gcache->families, _gquery, _fcompare,         \
     278                              _mrunode, error );                              \
     279      _gquery->family = FTC_FAMILY( _mrunode );                               \
     280      if ( !error )                                                           \
     281      {                                                                       \
     282        FTC_Family  _gqfamily = _gquery->family;                              \
     283                                                                              \
     284                                                                              \
     285        _gqfamily->num_nodes++;                                               \
     286                                                                              \
     287        FTC_CACHE_LOOKUP_CMP( cache, nodecmp, hash, query, node, error );     \
     288                                                                              \
     289        if ( --_gqfamily->num_nodes == 0 )                                    \
     290          FTC_FAMILY_FREE( _gqfamily, _gcache );                              \
     291      }                                                                       \
     292    FT_END_STMNT
     293    /* */
     294  
     295  #else /* !FTC_INLINE */
     296  
     297  #define FTC_GCACHE_LOOKUP_CMP( cache, famcmp, nodecmp, hash,          \
     298                                 gindex, query, node, error )           \
     299     FT_BEGIN_STMNT                                                     \
     300                                                                        \
     301       error = FTC_GCache_Lookup( FTC_GCACHE( cache ), hash, gindex,    \
     302                                  FTC_GQUERY( query ), &node );         \
     303                                                                        \
     304     FT_END_STMNT
     305  
     306  #endif /* !FTC_INLINE */
     307  
     308  
     309  FT_END_HEADER
     310  
     311  
     312  #endif /* FTCGLYPH_H_ */
     313  
     314  
     315  /* END */