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