/***************************************************************************/ /* */ /* ftcglyph.h */ /* */ /* FreeType abstract glyph cache (specification). */ /* */ /* Copyright 2000-2015 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 #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_Offset 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 */