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