summaryrefslogtreecommitdiffstats
path: root/src/cache/ftcglyph.h
blob: 5fed19cb8fa20049ddc6260f1f265f96b437a20b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
/***************************************************************************/
/*                                                                         */
/*  ftcglyph.h                                                             */
/*                                                                         */
/*    FreeType abstract glyph cache (specification).                       */
/*                                                                         */
/*  Copyright 2000-2001, 2003, 2004, 2006, 2007, 2011 by                   */
/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
/*                                                                         */
/*  This file is part of the FreeType project, and may only be used,       */
/*  modified, and distributed under the terms of the FreeType project      */
/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
/*  this file you indicate that you have read the license and              */
/*  understand and accept it fully.                                        */
/*                                                                         */
/***************************************************************************/


  /*
   *
   *  FTC_GCache is an _abstract_ cache object optimized to store glyph
   *  data.  It works as follows:
   *
   *   - It manages FTC_GNode objects. Each one of them can hold one or more
   *     glyph `items'.  Item types are not specified in the FTC_GCache but
   *     in classes that extend it.
   *
   *   - Glyph attributes, like face ID, character size, render mode, etc.,
   *     can be grouped into abstract `glyph families'.  This avoids storing
   *     the attributes within the FTC_GCache, since it is likely that many
   *     FTC_GNodes will belong to the same family in typical uses.
   *
   *   - Each FTC_GNode is thus an FTC_Node with two additional fields:
   *
   *       * gindex: A glyph index, or the first index in a glyph range.
   *       * family: A pointer to a glyph `family'.
   *
   *   - Family types are not fully specific in the FTC_Family type, but
   *     by classes that extend it.
   *
   *  Note that both FTC_ImageCache and FTC_SBitCache extend FTC_GCache.
   *  They share an FTC_Family sub-class called FTC_BasicFamily which is
   *  used to store the following data: face ID, pixel/point sizes, load
   *  flags.  For more details see the file `src/cache/ftcbasic.c'.
   *
   *  Client applications can extend FTC_GNode with their own FTC_GNode
   *  and FTC_Family sub-classes to implement more complex caches (e.g.,
   *  handling automatic synthesis, like obliquing & emboldening, colored
   *  glyphs, etc.).
   *
   *  See also the FTC_ICache & FTC_SCache classes in `ftcimage.h' and
   *  `ftcsbits.h', which both extend FTC_GCache with additional
   *  optimizations.
   *
   *  A typical FTC_GCache implementation must provide at least the
   *  following:
   *
   *  - FTC_GNode sub-class, e.g. MyNode, with relevant methods:
   *        my_node_new            (must call FTC_GNode_Init)
   *        my_node_free           (must call FTC_GNode_Done)
   *        my_node_compare        (must call FTC_GNode_Compare)
   *        my_node_remove_faceid  (must call ftc_gnode_unselect in case
   *                                of match)
   *
   *  - FTC_Family sub-class, e.g. MyFamily, with relevant methods:
   *        my_family_compare
   *        my_family_init
   *        my_family_reset (optional)
   *        my_family_done
   *
   *  - FTC_GQuery sub-class, e.g. MyQuery, to hold cache-specific query
   *    data.
   *
   *  - Constant structures for a FTC_GNodeClass.
   *
   *  - MyCacheNew() can be implemented easily as a call to the convenience
   *    function FTC_GCache_New.
   *
   *  - MyCacheLookup with a call to FTC_GCache_Lookup.  This function will
   *    automatically:
   *
   *    - Search for the corresponding family in the cache, or create
   *      a new one if necessary.  Put it in FTC_GQUERY(myquery).family
   *
   *    - Call FTC_Cache_Lookup.
   *
   *    If it returns NULL, you should create a new node, then call
   *    ftc_cache_add as usual.
   */


  /*************************************************************************/
  /*                                                                       */
  /* Important: The functions defined in this file are only used to        */
  /*            implement an abstract glyph cache class.  You need to      */
  /*            provide additional logic to implement a complete cache.    */
  /*                                                                       */
  /*************************************************************************/


  /*************************************************************************/
  /*************************************************************************/
  /*************************************************************************/
  /*************************************************************************/
  /*************************************************************************/
  /*********                                                       *********/
  /*********             WARNING, THIS IS BETA CODE.               *********/
  /*********                                                       *********/
  /*************************************************************************/
  /*************************************************************************/
  /*************************************************************************/
  /*************************************************************************/
  /*************************************************************************/


#ifndef __FTCGLYPH_H__
#define __FTCGLYPH_H__


#include <ft2build.h>
#include "ftcmanag.h"


FT_BEGIN_HEADER


 /*
  *  We can group glyphs into `families'.  Each family correspond to a
  *  given face ID, character size, transform, etc.
  *
  *  Families are implemented as MRU list nodes.  They are
  *  reference-counted.
  */

  typedef struct  FTC_FamilyRec_
  {
    FTC_MruNodeRec    mrunode;
    FT_UInt           num_nodes; /* current number of nodes in this family */
    FTC_Cache         cache;
    FTC_MruListClass  clazz;

  } FTC_FamilyRec, *FTC_Family;

#define  FTC_FAMILY(x)    ( (FTC_Family)(x) )
#define  FTC_FAMILY_P(x)  ( (FTC_Family*)(x) )


  typedef struct  FTC_GNodeRec_
  {
    FTC_NodeRec      node;
    FTC_Family       family;
    FT_UInt          gindex;

  } FTC_GNodeRec, *FTC_GNode;

#define FTC_GNODE( x )    ( (FTC_GNode)(x) )
#define FTC_GNODE_P( x )  ( (FTC_GNode*)(x) )


  typedef struct  FTC_GQueryRec_
  {
    FT_UInt      gindex;
    FTC_Family   family;

  } FTC_GQueryRec, *FTC_GQuery;

#define FTC_GQUERY( x )  ( (FTC_GQuery)(x) )


  /*************************************************************************/
  /*                                                                       */
  /* These functions are exported so that they can be called from          */
  /* user-provided cache classes; otherwise, they are really part of the   */
  /* cache sub-system internals.                                           */
  /*                                                                       */

  /* must be called by derived FTC_Node_InitFunc routines */
  FT_LOCAL( void )
  FTC_GNode_Init( FTC_GNode   node,
                  FT_UInt     gindex,  /* glyph index for node */
                  FTC_Family  family );

#ifdef FTC_INLINE

  /* returns TRUE iff the query's glyph index correspond to the node;  */
  /* this assumes that the `family' and `hash' fields of the query are */
  /* already correctly set                                             */
  FT_LOCAL( FT_Bool )
  FTC_GNode_Compare( FTC_GNode   gnode,
                     FTC_GQuery  gquery,
                     FTC_Cache   cache,
                     FT_Bool*    list_changed );

#endif

  /* call this function to clear a node's family -- this is necessary */
  /* to implement the `node_remove_faceid' cache method correctly     */
  FT_LOCAL( void )
  FTC_GNode_UnselectFamily( FTC_GNode  gnode,
                            FTC_Cache  cache );

  /* must be called by derived FTC_Node_DoneFunc routines */
  FT_LOCAL( void )
  FTC_GNode_Done( FTC_GNode  node,
                  FTC_Cache  cache );


  FT_LOCAL( void )
  FTC_Family_Init( FTC_Family  family,
                   FTC_Cache   cache );

  typedef struct FTC_GCacheRec_
  {
    FTC_CacheRec    cache;
    FTC_MruListRec  families;

  } FTC_GCacheRec, *FTC_GCache;

#define FTC_GCACHE( x )  ((FTC_GCache)(x))


#if 0
  /* can be used as @FTC_Cache_InitFunc */
  FT_LOCAL( FT_Error )
  FTC_GCache_Init( FTC_GCache  cache );
#endif


#if 0
  /* can be used as @FTC_Cache_DoneFunc */
  FT_LOCAL( void )
  FTC_GCache_Done( FTC_GCache  cache );
#endif


  /* the glyph cache class adds fields for the family implementation */
  typedef struct  FTC_GCacheClassRec_
  {
    FTC_CacheClassRec  clazz;
    FTC_MruListClass   family_class;

  } FTC_GCacheClassRec;

  typedef const FTC_GCacheClassRec*   FTC_GCacheClass;

#define FTC_GCACHE_CLASS( x )  ((FTC_GCacheClass)(x))

#define FTC_CACHE__GCACHE_CLASS( x ) \
          FTC_GCACHE_CLASS( FTC_CACHE(x)->org_class )
#define FTC_CACHE__FAMILY_CLASS( x ) \
          ( (FTC_MruListClass)FTC_CACHE__GCACHE_CLASS( x )->family_class )


  /* convenience function; use it instead of FTC_Manager_Register_Cache */
  FT_LOCAL( FT_Error )
  FTC_GCache_New( FTC_Manager       manager,
                  FTC_GCacheClass   clazz,
                  FTC_GCache       *acache );

#ifndef FTC_INLINE
  FT_LOCAL( FT_Error )
  FTC_GCache_Lookup( FTC_GCache   cache,
                     FT_PtrDist   hash,
                     FT_UInt      gindex,
                     FTC_GQuery   query,
                     FTC_Node    *anode );
#endif


  /* */


#define FTC_FAMILY_FREE( family, cache )                      \
          FTC_MruList_Remove( &FTC_GCACHE((cache))->families, \
                              (FTC_MruNode)(family) )


#ifdef FTC_INLINE

#define FTC_GCACHE_LOOKUP_CMP( cache, famcmp, nodecmp, hash,                \
                               gindex, query, node, error )                 \
  FT_BEGIN_STMNT                                                            \
    FTC_GCache               _gcache   = FTC_GCACHE( cache );               \
    FTC_GQuery               _gquery   = (FTC_GQuery)( query );             \
    FTC_MruNode_CompareFunc  _fcompare = (FTC_MruNode_CompareFunc)(famcmp); \
    FTC_MruNode              _mrunode;                                      \
                                                                            \
                                                                            \
    _gquery->gindex = (gindex);                                             \
                                                                            \
    FTC_MRULIST_LOOKUP_CMP( &_gcache->families, _gquery, _fcompare,         \
                            _mrunode, error );                              \
    _gquery->family = FTC_FAMILY( _mrunode );                               \
    if ( !error )                                                           \
    {                                                                       \
      FTC_Family  _gqfamily = _gquery->family;                              \
                                                                            \
                                                                            \
      _gqfamily->num_nodes++;                                               \
                                                                            \
      FTC_CACHE_LOOKUP_CMP( cache, nodecmp, hash, query, node, error );     \
                                                                            \
      if ( --_gqfamily->num_nodes == 0 )                                    \
        FTC_FAMILY_FREE( _gqfamily, _gcache );                              \
    }                                                                       \
  FT_END_STMNT
  /* */

#else /* !FTC_INLINE */

#define FTC_GCACHE_LOOKUP_CMP( cache, famcmp, nodecmp, hash,          \
                               gindex, query, node, error )           \
   FT_BEGIN_STMNT                                                     \
                                                                      \
     error = FTC_GCache_Lookup( FTC_GCACHE( cache ), hash, gindex,    \
                                FTC_GQUERY( query ), &node );         \
                                                                      \
   FT_END_STMNT

#endif /* !FTC_INLINE */


FT_END_HEADER


#endif /* __FTCGLYPH_H__ */


/* END */