• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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