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