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 */ |
316 | |