1 /****************************************************************************
2  *
3  * ftcglyph.h
4  *
5  *   FreeType abstract glyph cache (specification).
6  *
7  * Copyright (C) 2000-2020 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 #ifdef FTC_INLINE
183 
184   /* returns TRUE iff the query's glyph index correspond to the node;  */
185   /* this assumes that the `family' and `hash' fields of the query are */
186   /* already correctly set                                             */
187   FT_LOCAL( FT_Bool )
188   FTC_GNode_Compare( FTC_GNode   gnode,
189                      FTC_GQuery  gquery,
190                      FTC_Cache   cache,
191                      FT_Bool*    list_changed );
192 
193 #endif
194 
195   /* call this function to clear a node's family -- this is necessary */
196   /* to implement the `node_remove_faceid' cache method correctly     */
197   FT_LOCAL( void )
198   FTC_GNode_UnselectFamily( FTC_GNode  gnode,
199                             FTC_Cache  cache );
200 
201   /* must be called by derived FTC_Node_DoneFunc routines */
202   FT_LOCAL( void )
203   FTC_GNode_Done( FTC_GNode  node,
204                   FTC_Cache  cache );
205 
206 
207   FT_LOCAL( void )
208   FTC_Family_Init( FTC_Family  family,
209                    FTC_Cache   cache );
210 
211   typedef struct FTC_GCacheRec_
212   {
213     FTC_CacheRec    cache;
214     FTC_MruListRec  families;
215 
216   } FTC_GCacheRec, *FTC_GCache;
217 
218 #define FTC_GCACHE( x )  ((FTC_GCache)(x))
219 
220 
221 #if 0
222   /* can be used as @FTC_Cache_InitFunc */
223   FT_LOCAL( FT_Error )
224   FTC_GCache_Init( FTC_GCache  cache );
225 #endif
226 
227 
228 #if 0
229   /* can be used as @FTC_Cache_DoneFunc */
230   FT_LOCAL( void )
231   FTC_GCache_Done( FTC_GCache  cache );
232 #endif
233 
234 
235   /* the glyph cache class adds fields for the family implementation */
236   typedef struct  FTC_GCacheClassRec_
237   {
238     FTC_CacheClassRec  clazz;
239     FTC_MruListClass   family_class;
240 
241   } FTC_GCacheClassRec;
242 
243   typedef const FTC_GCacheClassRec*   FTC_GCacheClass;
244 
245 #define FTC_GCACHE_CLASS( x )  ((FTC_GCacheClass)(x))
246 
247 #define FTC_CACHE_GCACHE_CLASS( x ) \
248           FTC_GCACHE_CLASS( FTC_CACHE(x)->org_class )
249 #define FTC_CACHE_FAMILY_CLASS( x ) \
250           ( (FTC_MruListClass)FTC_CACHE_GCACHE_CLASS( x )->family_class )
251 
252 
253   /* convenience function; use it instead of FTC_Manager_Register_Cache */
254   FT_LOCAL( FT_Error )
255   FTC_GCache_New( FTC_Manager       manager,
256                   FTC_GCacheClass   clazz,
257                   FTC_GCache       *acache );
258 
259 #ifndef FTC_INLINE
260   FT_LOCAL( FT_Error )
261   FTC_GCache_Lookup( FTC_GCache   cache,
262                      FT_Offset    hash,
263                      FT_UInt      gindex,
264                      FTC_GQuery   query,
265                      FTC_Node    *anode );
266 #endif
267 
268 
269   /* */
270 
271 
272 #define FTC_FAMILY_FREE( family, cache )                      \
273           FTC_MruList_Remove( &FTC_GCACHE((cache))->families, \
274                               (FTC_MruNode)(family) )
275 
276 
277 #ifdef FTC_INLINE
278 
279 #define FTC_GCACHE_LOOKUP_CMP( cache, famcmp, nodecmp, hash,                \
280                                gindex, query, node, error )                 \
281   FT_BEGIN_STMNT                                                            \
282     FTC_GCache               _gcache   = FTC_GCACHE( cache );               \
283     FTC_GQuery               _gquery   = (FTC_GQuery)( query );             \
284     FTC_MruNode_CompareFunc  _fcompare = (FTC_MruNode_CompareFunc)(famcmp); \
285     FTC_MruNode              _mrunode;                                      \
286                                                                             \
287                                                                             \
288     _gquery->gindex = (gindex);                                             \
289                                                                             \
290     FTC_MRULIST_LOOKUP_CMP( &_gcache->families, _gquery, _fcompare,         \
291                             _mrunode, error );                              \
292     _gquery->family = FTC_FAMILY( _mrunode );                               \
293     if ( !error )                                                           \
294     {                                                                       \
295       FTC_Family  _gqfamily = _gquery->family;                              \
296                                                                             \
297                                                                             \
298       _gqfamily->num_nodes++;                                               \
299                                                                             \
300       FTC_CACHE_LOOKUP_CMP( cache, nodecmp, hash, query, node, error );     \
301                                                                             \
302       if ( --_gqfamily->num_nodes == 0 )                                    \
303         FTC_FAMILY_FREE( _gqfamily, _gcache );                              \
304     }                                                                       \
305   FT_END_STMNT
306   /* */
307 
308 #else /* !FTC_INLINE */
309 
310 #define FTC_GCACHE_LOOKUP_CMP( cache, famcmp, nodecmp, hash,          \
311                                gindex, query, node, error )           \
312    FT_BEGIN_STMNT                                                     \
313                                                                       \
314      error = FTC_GCache_Lookup( FTC_GCACHE( cache ), hash, gindex,    \
315                                 FTC_GQUERY( query ), &node );         \
316                                                                       \
317    FT_END_STMNT
318 
319 #endif /* !FTC_INLINE */
320 
321 
322 FT_END_HEADER
323 
324 
325 #endif /* FTCGLYPH_H_ */
326 
327 
328 /* END */
329