new version of the cache sub-system - still under debugging
This commit is contained in:
parent
9e185f32ce
commit
57ecae22a7
261
include/freetype/cache/ftccache.h
vendored
261
include/freetype/cache/ftccache.h
vendored
@ -20,9 +20,6 @@
|
||||
#define __FTCCACHE_H__
|
||||
|
||||
|
||||
/* define to allow cache lookup inlining */
|
||||
#define FTC_CACHE_USE_INLINE
|
||||
|
||||
|
||||
FT_BEGIN_HEADER
|
||||
|
||||
@ -30,14 +27,7 @@ FT_BEGIN_HEADER
|
||||
typedef struct FTC_CacheRec_* FTC_Cache;
|
||||
|
||||
/* handle to cache class */
|
||||
typedef const struct FTC_Cache_ClassRec_* FTC_Cache_Class;
|
||||
|
||||
/* handle to cache node family */
|
||||
typedef struct FTC_FamilyRec_* FTC_Family;
|
||||
|
||||
/* handle to cache root query */
|
||||
typedef struct FTC_QueryRec_* FTC_Query;
|
||||
|
||||
typedef const struct FTC_CacheClassRec_* FTC_CacheClass;
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
@ -66,7 +56,7 @@ FT_BEGIN_HEADER
|
||||
FTC_Node mru_prev; /* circular mru list pointer */
|
||||
FTC_Node link; /* used for hashing */
|
||||
FT_UInt32 hash; /* used for hashing too */
|
||||
FT_UShort fam_index; /* index of family the node belongs to */
|
||||
FT_UShort cache_index; /* index of cache the node belongs to */
|
||||
FT_Short ref_count; /* reference count for this node */
|
||||
|
||||
} FTC_NodeRec;
|
||||
@ -83,82 +73,12 @@ FT_BEGIN_HEADER
|
||||
/* cache sub-system internals. */
|
||||
/* */
|
||||
|
||||
/* can be used as a FTC_Node_DoneFunc */
|
||||
FT_EXPORT( void )
|
||||
ftc_node_done( FTC_Node node,
|
||||
FTC_Cache cache );
|
||||
|
||||
/* reserved for manager's use */
|
||||
FT_EXPORT( void )
|
||||
ftc_node_destroy( FTC_Node node,
|
||||
FTC_Manager manager );
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/***** *****/
|
||||
/***** CACHE QUERY DEFINITIONS *****/
|
||||
/***** *****/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
/* A structure modelling a cache node query. The following fields must */
|
||||
/* all be set by the @FTC_Family_CompareFunc method of a cache's family */
|
||||
/* list. */
|
||||
/* */
|
||||
typedef struct FTC_QueryRec_
|
||||
{
|
||||
FTC_Family family;
|
||||
FT_UFast hash;
|
||||
|
||||
} FTC_QueryRec;
|
||||
|
||||
|
||||
#define FTC_QUERY( x ) ( (FTC_Query)(x) )
|
||||
#define FTC_QUERY_P( x ) ( (FTC_Query*)(x) )
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/***** *****/
|
||||
/***** CACHE FAMILY DEFINITIONS *****/
|
||||
/***** *****/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
typedef struct FTC_FamilyRec_
|
||||
{
|
||||
FT_LruNodeRec lru;
|
||||
FTC_Cache cache;
|
||||
FT_UInt num_nodes;
|
||||
FT_UInt fam_index;
|
||||
|
||||
} FTC_FamilyRec;
|
||||
|
||||
|
||||
#define FTC_FAMILY( x ) ( (FTC_Family)(x) )
|
||||
#define FTC_FAMILY_P( x ) ( (FTC_Family*)(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 any FTC_Node_InitFunc routine */
|
||||
FT_EXPORT( FT_Error )
|
||||
ftc_family_init( FTC_Family family,
|
||||
FTC_Query query,
|
||||
FTC_Cache cache );
|
||||
|
||||
|
||||
/* can be used as a FTC_Family_DoneFunc; otherwise, must be called */
|
||||
/* by any family finalizer function */
|
||||
FT_EXPORT( void )
|
||||
ftc_family_done( FTC_Family family );
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
@ -168,23 +88,57 @@ FT_BEGIN_HEADER
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
/* initialize a new cache node */
|
||||
typedef FT_Error (*FTC_Node_NewFunc)( FTC_Node *pnode,
|
||||
FT_Pointer query,
|
||||
FTC_Cache cache );
|
||||
|
||||
typedef FT_ULong (*FTC_Node_WeightFunc)( FTC_Node node,
|
||||
FTC_Cache cache );
|
||||
|
||||
/* compare a node to a given key pair */
|
||||
typedef FT_Bool (*FTC_Node_CompareFunc)( FTC_Node node,
|
||||
FT_Pointer key,
|
||||
FTC_Cache cache );
|
||||
|
||||
|
||||
typedef void (*FTC_Node_FreeFunc)( FTC_Node node,
|
||||
FTC_Cache cache );
|
||||
|
||||
typedef FT_Error (*FTC_Cache_InitFunc)( FTC_Cache cache );
|
||||
|
||||
typedef void (*FTC_Cache_DoneFunc)( FTC_Cache cache );
|
||||
|
||||
|
||||
typedef struct FTC_CacheClassRec_
|
||||
{
|
||||
FTC_Node_NewFunc node_new;
|
||||
FTC_Node_WeightFunc node_weight;
|
||||
FTC_Node_CompareFunc node_compare;
|
||||
FTC_Node_CompareFunc node_remove_faceid;
|
||||
FTC_Node_FreeFunc node_free;
|
||||
|
||||
FT_UInt cache_size;
|
||||
FTC_Cache_InitFunc cache_init;
|
||||
FTC_Cache_DoneFunc cache_done;
|
||||
|
||||
} FTC_CacheClassRec;
|
||||
|
||||
/* each cache really implements a dynamic hash table to manage its nodes */
|
||||
typedef struct FTC_CacheRec_
|
||||
{
|
||||
FTC_Manager manager;
|
||||
FT_Memory memory;
|
||||
FTC_Cache_Class clazz;
|
||||
|
||||
FT_UInt cache_index; /* in manager's table */
|
||||
FT_Pointer cache_data; /* used by cache node methods */
|
||||
|
||||
FT_UFast p;
|
||||
FT_UFast mask;
|
||||
FT_Long slack;
|
||||
FTC_Node* buckets;
|
||||
|
||||
FT_LruList_ClassRec family_class;
|
||||
FT_LruList families;
|
||||
FTC_CacheClassRec clazz; /* local copy, for speed */
|
||||
|
||||
FTC_Manager manager;
|
||||
FT_Memory memory;
|
||||
FT_UInt index; /* in manager's table */
|
||||
|
||||
FTC_CacheClass org_class; /* original class pointer */
|
||||
|
||||
} FTC_CacheRec;
|
||||
|
||||
@ -193,105 +147,38 @@ FT_BEGIN_HEADER
|
||||
#define FTC_CACHE_P( x ) ( (FTC_Cache*)(x) )
|
||||
|
||||
|
||||
/* initialize a given cache */
|
||||
typedef FT_Error
|
||||
(*FTC_Cache_InitFunc)( FTC_Cache cache );
|
||||
|
||||
/* clear a cache */
|
||||
typedef void
|
||||
(*FTC_Cache_ClearFunc)( FTC_Cache cache );
|
||||
|
||||
/* finalize a given cache */
|
||||
typedef void
|
||||
(*FTC_Cache_DoneFunc)( FTC_Cache cache );
|
||||
|
||||
|
||||
typedef FT_Error
|
||||
(*FTC_Family_InitFunc)( FTC_Family family,
|
||||
FTC_Query query,
|
||||
FTC_Cache cache );
|
||||
|
||||
typedef FT_Int
|
||||
(*FTC_Family_CompareFunc)( FTC_Family family,
|
||||
FTC_Query query );
|
||||
|
||||
typedef void
|
||||
(*FTC_Family_DoneFunc)( FTC_Family family,
|
||||
FTC_Cache cache );
|
||||
|
||||
/* initialize a new cache node */
|
||||
typedef FT_Error
|
||||
(*FTC_Node_InitFunc)( FTC_Node node,
|
||||
FT_Pointer type,
|
||||
FTC_Cache cache );
|
||||
|
||||
/* compute the weight of a given cache node */
|
||||
typedef FT_ULong
|
||||
(*FTC_Node_WeightFunc)( FTC_Node node,
|
||||
FTC_Cache cache );
|
||||
|
||||
/* compare a node to a given key pair */
|
||||
typedef FT_Bool
|
||||
(*FTC_Node_CompareFunc)( FTC_Node node,
|
||||
FT_Pointer key,
|
||||
FTC_Cache cache );
|
||||
|
||||
/* finalize a given cache node */
|
||||
typedef void
|
||||
(*FTC_Node_DoneFunc)( FTC_Node node,
|
||||
FTC_Cache cache );
|
||||
|
||||
|
||||
typedef struct FTC_Cache_ClassRec_
|
||||
{
|
||||
FT_UInt cache_size;
|
||||
FTC_Cache_InitFunc cache_init;
|
||||
FTC_Cache_ClearFunc cache_clear;
|
||||
FTC_Cache_DoneFunc cache_done;
|
||||
|
||||
FT_UInt family_size;
|
||||
FTC_Family_InitFunc family_init;
|
||||
FTC_Family_CompareFunc family_compare;
|
||||
FTC_Family_DoneFunc family_done;
|
||||
|
||||
FT_UInt node_size;
|
||||
FTC_Node_InitFunc node_init;
|
||||
FTC_Node_WeightFunc node_weight;
|
||||
FTC_Node_CompareFunc node_compare;
|
||||
FTC_Node_DoneFunc node_done;
|
||||
|
||||
} FTC_Cache_ClassRec;
|
||||
|
||||
|
||||
/* */
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/* */
|
||||
/* 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. */
|
||||
/* */
|
||||
|
||||
/* can be used directly as FTC_Cache_DoneFunc(), or called by custom */
|
||||
/* cache finalizers */
|
||||
FT_EXPORT( void )
|
||||
ftc_cache_done( FTC_Cache cache );
|
||||
|
||||
/* can be used directly as FTC_Cache_ClearFunc(), or called by custom */
|
||||
/* cache clear routines */
|
||||
FT_EXPORT( void )
|
||||
ftc_cache_clear( FTC_Cache cache );
|
||||
|
||||
/* initalize the hash table within the cache */
|
||||
/* default cache initialize */
|
||||
FT_EXPORT( FT_Error )
|
||||
ftc_cache_init( FTC_Cache cache );
|
||||
FTC_Cache_Init( FTC_Cache cache );
|
||||
|
||||
/* can be called when the key's hash value has been computed */
|
||||
/* default cache finalizer */
|
||||
FT_EXPORT( void )
|
||||
FTC_Cache_Done( FTC_Cache cache );
|
||||
|
||||
/* call this function to lookup the cache. if no corresponding
|
||||
* node is found, a new one is automatically created. This function
|
||||
* is capable of flushing the cache adequately to make room for the
|
||||
* new cache object.
|
||||
*/
|
||||
FT_EXPORT( FT_Error )
|
||||
ftc_cache_lookup( FTC_Cache cache,
|
||||
FTC_Query query,
|
||||
FTC_Node *anode );
|
||||
FTC_Cache_Lookup( FTC_Cache cache,
|
||||
FT_UInt32 hash,
|
||||
FT_Pointer query,
|
||||
FTC_Node *anode );
|
||||
|
||||
/* remove all nodes that relate to a given face_id. This is useful
|
||||
* when un-installing fonts. Note that if a cache node relates to
|
||||
* the face_id, but is locked (i.e. has 'ref_count > 0'), the node
|
||||
* will _not_ be destroyed, but its internal face_id reference will
|
||||
* be modified.
|
||||
*
|
||||
* the end result will be that the node will never come back
|
||||
* in further lookup requests, and will be flushed on demand from
|
||||
* the cache normally when its reference count reaches 0
|
||||
*/
|
||||
FT_EXPORT( void )
|
||||
FTC_Cache_RemoveFaceID( FTC_Cache cache,
|
||||
FTC_FaceID face_id );
|
||||
|
||||
/* */
|
||||
|
||||
|
252
include/freetype/cache/ftcglyph.h
vendored
252
include/freetype/cache/ftcglyph.h
vendored
@ -16,13 +16,84 @@
|
||||
/***************************************************************************/
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* 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 in 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 a FTC_Node with two additionnal 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 synthetis, 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 additionnal
|
||||
* optimizations.
|
||||
*
|
||||
*
|
||||
* a typical FTC_GCache implementation must provide at least the following:
|
||||
*
|
||||
* - FTC_GNode sub-class, e.g. MyNode, with relevant methods, i.e:
|
||||
* 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, e.g.:
|
||||
* 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.
|
||||
*
|
||||
* - provide constant structures for a FTC_GNodeClass
|
||||
*
|
||||
* - MyCacheNew() can be implemented easily as a call to the convenience
|
||||
* function FTC_GCache_New
|
||||
*
|
||||
* - implement 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. */
|
||||
/* For example, see `ftcimage.h' and `ftcimage.c' which */
|
||||
/* implement a FT_Glyph cache based on this code. */
|
||||
/* */
|
||||
/*************************************************************************/
|
||||
|
||||
@ -47,98 +118,63 @@
|
||||
|
||||
|
||||
#include <ft2build.h>
|
||||
#include FT_CACHE_H
|
||||
#include FT_CACHE_MANAGER_H
|
||||
#include FT_CACHE_INTERNAL_MANAGER_H
|
||||
|
||||
|
||||
FT_BEGIN_HEADER
|
||||
|
||||
|
||||
/* each glyph set is characterized by a "glyph set type" which must be */
|
||||
/* defined by sub-classes */
|
||||
typedef struct FTC_GlyphFamilyRec_* FTC_GlyphFamily;
|
||||
|
||||
/* handle to a glyph cache node */
|
||||
typedef struct FTC_GlyphNodeRec_* FTC_GlyphNode;
|
||||
|
||||
|
||||
/* size should be 24 + chunk size on 32-bit machines; */
|
||||
/* note that the node's hash is ((gfam->hash << 16) | glyph_index) -- */
|
||||
/* this _must_ be set properly by the glyph node initializer */
|
||||
/* */
|
||||
typedef struct FTC_GlyphNodeRec_
|
||||
/*
|
||||
* we can group glyph in "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_NodeRec node;
|
||||
FT_UShort item_count;
|
||||
FT_UShort item_start;
|
||||
FTC_MruNode mrunode;
|
||||
FT_UInt num_nodes; /* current number of nodes in this family */
|
||||
FTC_MruListClass clazz;
|
||||
|
||||
} FTC_FamilyRec, *FTC_Family;
|
||||
|
||||
} FTC_GlyphNodeRec;
|
||||
#define FTC_FAMILY(x) ( (FTC_Family)(x) )
|
||||
#define FTC_FAMILY_P(x) ( (FTC_Family*)(x) )
|
||||
|
||||
|
||||
#define FTC_GLYPH_NODE( x ) ( (FTC_GlyphNode)(x) )
|
||||
#define FTC_GLYPH_NODE_P( x ) ( (FTC_GlyphNode*)(x) )
|
||||
|
||||
|
||||
typedef struct FTC_GlyphQueryRec_
|
||||
typedef struct FTC_GNodeRec_
|
||||
{
|
||||
FTC_QueryRec query;
|
||||
FT_UInt gindex;
|
||||
FTC_NodeRec node;
|
||||
FTC_Family family;
|
||||
FT_UInt gindex;
|
||||
|
||||
} FTC_GlyphQueryRec, *FTC_GlyphQuery;
|
||||
} FTC_GNodeRec, *FTC_GNode;
|
||||
|
||||
#define FTC_GNODE( x ) ( (FTC_GNode)(x) )
|
||||
#define FTC_GNODE_P( x ) ( (FTC_GNode*)(x) )
|
||||
|
||||
|
||||
#define FTC_GLYPH_QUERY( x ) ( (FTC_GlyphQuery)(x) )
|
||||
|
||||
|
||||
/* a glyph set is used to categorize glyphs of a given type */
|
||||
typedef struct FTC_GlyphFamilyRec_
|
||||
typedef struct FTC_GQueryRec_
|
||||
{
|
||||
FTC_FamilyRec family;
|
||||
FT_UInt32 hash;
|
||||
FT_UInt item_total; /* total number of glyphs in family */
|
||||
FT_UInt item_count; /* number of glyph items per node */
|
||||
FT_UInt gindex;
|
||||
FTC_Family family;
|
||||
|
||||
} FTC_GlyphFamilyRec;
|
||||
} FTC_GQueryRec, *FTC_GQuery;
|
||||
|
||||
#define FTC_GQUERY( x ) ( (FTC_GQuery)(x) )
|
||||
|
||||
#define FTC_GLYPH_FAMILY( x ) ( (FTC_GlyphFamily)(x) )
|
||||
#define FTC_GLYPH_FAMILY_P( x ) ( (FTC_GlyphFamily*)(x) )
|
||||
|
||||
#define FTC_GLYPH_FAMILY_MEMORY( x ) FTC_FAMILY(x)->cache->memory
|
||||
|
||||
|
||||
/* each glyph node contains a 'chunk' of glyph items; */
|
||||
/* translate a glyph index into a chunk index */
|
||||
#define FTC_GLYPH_FAMILY_CHUNK( gfam, gindex ) \
|
||||
( ( gindex ) / FTC_GLYPH_FAMILY( gfam )->item_count )
|
||||
#define FTC_FAMILY_CHUNK( gfam, gindex ) \
|
||||
( ( gindex ) / FTC_FAMILY( gfam )->item_count )
|
||||
|
||||
/* find a glyph index's chunk, and return its start index */
|
||||
#define FTC_GLYPH_FAMILY_START( gfam, gindex ) \
|
||||
( FTC_GLYPH_FAMILY_CHUNK( gfam, gindex ) * \
|
||||
FTC_GLYPH_FAMILY( gfam )->item_count )
|
||||
|
||||
/* compute a glyph request's hash value */
|
||||
#define FTC_GLYPH_FAMILY_HASH( gfam, gindex ) \
|
||||
( (FT_UFast)( \
|
||||
( FTC_GLYPH_FAMILY( gfam )->hash << 16 ) | \
|
||||
( FTC_GLYPH_FAMILY_CHUNK( gfam, gindex ) & 0xFFFFU ) ) )
|
||||
|
||||
/* must be called in an FTC_Family_CompareFunc to update the query */
|
||||
/* whenever a glyph set is matched in the lookup, or when it */
|
||||
/* is created */
|
||||
#define FTC_GLYPH_FAMILY_FOUND( gfam, gquery ) \
|
||||
do \
|
||||
{ \
|
||||
FTC_QUERY( gquery )->family = FTC_FAMILY( gfam ); \
|
||||
FTC_QUERY( gquery )->hash = \
|
||||
FTC_GLYPH_FAMILY_HASH( gfam, \
|
||||
FTC_GLYPH_QUERY( gquery )->gindex ); \
|
||||
} while ( 0 )
|
||||
|
||||
/* retrieve glyph index of glyph node */
|
||||
#define FTC_GLYPH_NODE_GINDEX( x ) \
|
||||
( (FT_UInt)( FTC_GLYPH_NODE( x )->node.hash & 0xFFFFU ) )
|
||||
|
||||
#define FTC_FAMILY_START( gfam, gindex ) \
|
||||
( FTC_FAMILY_CHUNK( gfam, gindex ) * \
|
||||
FTC_FAMILY( gfam )->item_count )
|
||||
|
||||
/*************************************************************************/
|
||||
/* */
|
||||
@ -149,37 +185,79 @@ FT_BEGIN_HEADER
|
||||
|
||||
/* must be called by derived FTC_Node_InitFunc routines */
|
||||
FT_EXPORT( void )
|
||||
ftc_glyph_node_init( FTC_GlyphNode node,
|
||||
FT_UInt gindex, /* glyph index for node */
|
||||
FTC_GlyphFamily gfam );
|
||||
FTC_GNode_Init( FTC_GNode node,
|
||||
FT_UInt gindex, /* glyph index for node */
|
||||
FTC_Family family );
|
||||
|
||||
/* 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_EXPORT( FT_Bool )
|
||||
ftc_glyph_node_compare( FTC_GlyphNode gnode,
|
||||
FTC_GlyphQuery gquery );
|
||||
FTC_GNode_Compare( FTC_GNode gnode,
|
||||
FTC_GQuery gquery );
|
||||
|
||||
/* call this function to clear a node's family. this is necessary
|
||||
* to implement the "node_remove_faceid" cache method correctly
|
||||
*/
|
||||
FT_EXPORT( void )
|
||||
FTC_GNode_UnselectFamily( FTC_GNode gnode,
|
||||
FTC_Cache cache );
|
||||
|
||||
/* must be called by derived FTC_Node_DoneFunc routines */
|
||||
FT_EXPORT( void )
|
||||
ftc_glyph_node_done( FTC_GlyphNode node,
|
||||
FTC_Cache cache );
|
||||
FTC_GNode_Done( FTC_GNode node,
|
||||
FTC_Cache cache );
|
||||
|
||||
|
||||
/* must be called by derived FTC_Family_InitFunc; */
|
||||
/* calls "ftc_family_init" */
|
||||
typedef struct FTC_GCacheRec_
|
||||
{
|
||||
FTC_CacheRec cache;
|
||||
FTC_MruListRec families;
|
||||
|
||||
} FTC_GCacheRec, *FTC_GCache;
|
||||
|
||||
|
||||
#define FTC_GCACHE(x) ((FTC_GCache)(x))
|
||||
|
||||
|
||||
/* can be used as @FTC_Cache_InitFunc */
|
||||
FT_EXPORT( FT_Error )
|
||||
ftc_glyph_family_init( FTC_GlyphFamily gfam,
|
||||
FT_UInt32 hash,
|
||||
FT_UInt item_count,
|
||||
FT_UInt item_total,
|
||||
FTC_GlyphQuery gquery,
|
||||
FTC_Cache cache );
|
||||
FTC_GCache_Init( FTC_GCache cache );
|
||||
|
||||
|
||||
/* can be used as @FTC_Cache_DoneFunc */
|
||||
FT_EXPORT( void )
|
||||
ftc_glyph_family_done( FTC_GlyphFamily gfam );
|
||||
FTC_GCache_Done( FTC_GCache cache );
|
||||
|
||||
|
||||
/* 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 )
|
||||
|
||||
|
||||
/* convenience function. use instead of FTC_Manager_Register_Cache */
|
||||
FT_EXPORT( FT_Error )
|
||||
FTC_GCache_New( FTC_Manager manager,
|
||||
FTC_GCacheClass clazz,
|
||||
FTC_GCache *acache );
|
||||
|
||||
FT_EXPORT( FT_Error )
|
||||
FTC_GCache_Lookup( FTC_GCache cache,
|
||||
FT_UInt32 hash,
|
||||
FT_UInt gindex,
|
||||
FTC_GQuery query,
|
||||
FTC_Node *anode );
|
||||
|
||||
/* */
|
||||
|
||||
FT_END_HEADER
|
||||
|
315
include/freetype/cache/ftcimage.h
vendored
315
include/freetype/cache/ftcimage.h
vendored
@ -2,7 +2,7 @@
|
||||
/* */
|
||||
/* ftcimage.h */
|
||||
/* */
|
||||
/* FreeType Image cache (specification). */
|
||||
/* FreeType Generic Image cache (specification) */
|
||||
/* */
|
||||
/* Copyright 2000-2001, 2002, 2003 by */
|
||||
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
|
||||
@ -16,6 +16,15 @@
|
||||
/***************************************************************************/
|
||||
|
||||
|
||||
/*
|
||||
* FTC_ICache is an _abstract_ cache used to store a single FT_Glyph
|
||||
* image per cache node.
|
||||
*
|
||||
* FTC_ICache extends FTC_GCache. For an implementation example,
|
||||
* see FTC_ImageCache in "src/cache/ftbasic.c"
|
||||
*
|
||||
*/
|
||||
|
||||
/*************************************************************************/
|
||||
/* */
|
||||
/* Each image cache really manages FT_Glyph objects. */
|
||||
@ -29,284 +38,64 @@
|
||||
|
||||
#include <ft2build.h>
|
||||
#include FT_CACHE_H
|
||||
|
||||
#include FT_CACHE_INTERNAL_GLYPH_H
|
||||
|
||||
FT_BEGIN_HEADER
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/* */
|
||||
/* <Section> */
|
||||
/* cache_subsystem */
|
||||
/* */
|
||||
/*************************************************************************/
|
||||
/* the FT_Glyph image node type - we store only 1 glyph per node */
|
||||
typedef struct FTC_INodeRec_
|
||||
{
|
||||
FTC_GNodeRec gnode;
|
||||
FT_Glyph glyph;
|
||||
|
||||
} FTC_INodeRec, *FTC_INode;
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/***** *****/
|
||||
/***** IMAGE CACHE OBJECT *****/
|
||||
/***** *****/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
#define FTC_INODE( x ) ( (FTC_INode)( x ) )
|
||||
#define FTC_INODE_GINDEX( x ) FTC_GNODE(x)->gindex
|
||||
#define FTC_INODE_FAMILY( x ) FTC_GNODE(x)->family
|
||||
|
||||
typedef FT_Error (*FTC_IFamily_LoadGlyphFunc)( FTC_Family family,
|
||||
FT_UInt gindex,
|
||||
FTC_Cache cache,
|
||||
FT_Glyph *aglyph );
|
||||
|
||||
/**************************************************************************
|
||||
*
|
||||
* @struct:
|
||||
* FTC_ImageTypeRec
|
||||
*
|
||||
* @description:
|
||||
* A simple structure used to describe the type of glyph image to be
|
||||
* loaded into the cache.
|
||||
*
|
||||
* @fields:
|
||||
* font :: An @FTC_FontRec used to describe the glyph's face and size.
|
||||
*
|
||||
* flags :: The load flags to be applied when loading the glyph; see
|
||||
* the @FT_LOAD_XXX constants for details.
|
||||
*
|
||||
* @note:
|
||||
* This type completely replaces the @FTC_Image_Desc structure which is
|
||||
* now obsolete.
|
||||
typedef struct FTC_IFamilyClassRec_
|
||||
{
|
||||
FTC_MruListClassRec clazz;
|
||||
FTC_IFamily_LoadGlyphFunc family_load_glyph;
|
||||
|
||||
} FTC_IFamilyClassRec;
|
||||
|
||||
typedef const FTC_IFamilyClassRec* FTC_IFamilyClass;
|
||||
|
||||
#define FTC_IFAMILY_CLASS(x) ((FTC_IFamilyClass)(x))
|
||||
|
||||
#define FTC_CACHE__IFAMILY_CLASS(x) \
|
||||
FTC_IFAMILY_CLASS( FTC_CACHE__GCACHE_CLASS(x)->family_class )
|
||||
|
||||
/* can be used as a @FTC_Node_FreeFunc */
|
||||
FT_EXPORT( void )
|
||||
FTC_INode_Free( FTC_INode inode,
|
||||
FTC_Cache cache );
|
||||
|
||||
/* can be used as @FTC_Node_NewFunc. "gquery.index" & "gquery.family" must
|
||||
* be set correctly. this function will call the 'family_load_glyph' method
|
||||
* to load the FT_Glyph into the cache node
|
||||
*/
|
||||
typedef struct FTC_ImageTypeRec_
|
||||
{
|
||||
FTC_FontRec font;
|
||||
FT_Int32 flags;
|
||||
|
||||
} FTC_ImageTypeRec;
|
||||
|
||||
typedef struct FTC_ImageTypeRec_* FTC_ImageType;
|
||||
|
||||
/* */
|
||||
|
||||
#define FTC_IMAGE_TYPE_COMPARE( d1, d2 ) \
|
||||
( FTC_FONT_COMPARE( &(d1)->font, &(d2)->font ) && \
|
||||
(d1)->flags == (d2)->flags )
|
||||
|
||||
#define FTC_IMAGE_TYPE_HASH( d ) \
|
||||
(FT_UFast)( FTC_FONT_HASH( &(d)->font ) ^ \
|
||||
( (d)->flags << 4 ) )
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/* */
|
||||
/* <Type> */
|
||||
/* FTC_ImageCache */
|
||||
/* */
|
||||
/* <Description> */
|
||||
/* A handle to an glyph image cache object. They are designed to */
|
||||
/* hold many distinct glyph images while not exceeding a certain */
|
||||
/* memory threshold. */
|
||||
/* */
|
||||
typedef struct FTC_ImageCacheRec_* FTC_ImageCache;
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/* */
|
||||
/* <Function> */
|
||||
/* FTC_ImageCache_New */
|
||||
/* */
|
||||
/* <Description> */
|
||||
/* Creates a new glyph image cache. */
|
||||
/* */
|
||||
/* <Input> */
|
||||
/* manager :: The parent manager for the image cache. */
|
||||
/* */
|
||||
/* <Output> */
|
||||
/* acache :: A handle to the new glyph image cache object. */
|
||||
/* */
|
||||
/* <Return> */
|
||||
/* FreeType error code. 0 means success. */
|
||||
/* */
|
||||
FT_EXPORT( FT_Error )
|
||||
FTC_ImageCache_New( FTC_Manager manager,
|
||||
FTC_ImageCache *acache );
|
||||
FTC_INode_New( FTC_INode *pinode,
|
||||
FTC_GQuery gquery,
|
||||
FTC_Cache cache );
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/* */
|
||||
/* <Function> */
|
||||
/* FTC_ImageCache_Lookup */
|
||||
/* */
|
||||
/* <Description> */
|
||||
/* Retrieves a given glyph image from a glyph image cache. */
|
||||
/* */
|
||||
/* <Input> */
|
||||
/* cache :: A handle to the source glyph image cache. */
|
||||
/* */
|
||||
/* type :: A pointer to a glyph image type descriptor. */
|
||||
/* */
|
||||
/* gindex :: The glyph index to retrieve. */
|
||||
/* */
|
||||
/* <Output> */
|
||||
/* aglyph :: The corresponding @FT_Glyph object. 0 in case of */
|
||||
/* failure. */
|
||||
/* */
|
||||
/* anode :: Used to return the address of of the corresponding cache */
|
||||
/* node after incrementing its reference count (see note */
|
||||
/* below). */
|
||||
/* */
|
||||
/* <Return> */
|
||||
/* FreeType error code. 0 means success. */
|
||||
/* */
|
||||
/* <Note> */
|
||||
/* The returned glyph is owned and managed by the glyph image cache. */
|
||||
/* Never try to transform or discard it manually! You can however */
|
||||
/* create a copy with @FT_Glyph_Copy and modify the new one. */
|
||||
/* */
|
||||
/* If "anode" is _not_ NULL, it receives the address of the cache */
|
||||
/* node containing the glyph image, after increasing its reference */
|
||||
/* count. This ensures that the node (as well as the FT_Glyph) will */
|
||||
/* always be kept in the cache until you call @FTC_Node_Unref to */
|
||||
/* "release" it. */
|
||||
/* */
|
||||
/* If "anode" is NULL, the cache node is left unchanged, which means */
|
||||
/* that the FT_Glyph could be flushed out of the cache on the next */
|
||||
/* call to one of the caching sub-system APIs. Don't assume that it */
|
||||
/* is persistent! */
|
||||
/* */
|
||||
FT_EXPORT( FT_Error )
|
||||
FTC_ImageCache_Lookup( FTC_ImageCache cache,
|
||||
FTC_ImageType type,
|
||||
FT_UInt gindex,
|
||||
FT_Glyph *aglyph,
|
||||
FTC_Node *anode );
|
||||
|
||||
/* */
|
||||
|
||||
#define ftc_image_format( x ) ( (x) & 7 )
|
||||
|
||||
|
||||
#define ftc_image_format_bitmap 0x0000
|
||||
#define ftc_image_format_outline 0x0001
|
||||
|
||||
#define ftc_image_format_mask 0x000F
|
||||
|
||||
#define ftc_image_flag_monochrome 0x0010
|
||||
#define ftc_image_flag_unhinted 0x0020
|
||||
#define ftc_image_flag_autohinted 0x0040
|
||||
#define ftc_image_flag_unscaled 0x0080
|
||||
#define ftc_image_flag_no_sbits 0x0100
|
||||
|
||||
/* monochrome bitmap */
|
||||
#define ftc_image_mono ftc_image_format_bitmap | \
|
||||
ftc_image_flag_monochrome
|
||||
|
||||
/* anti-aliased bitmap */
|
||||
#define ftc_image_grays ftc_image_format_bitmap
|
||||
|
||||
/* scaled outline */
|
||||
#define ftc_image_outline ftc_image_format_outline
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/* */
|
||||
/* <Struct> */
|
||||
/* FTC_Image_Desc */
|
||||
/* */
|
||||
/* <Description> */
|
||||
/* THIS TYPE IS DEPRECATED. Use @FTC_ImageTypeRec instead. */
|
||||
/* */
|
||||
/* A simple structure used to describe a given glyph image category. */
|
||||
/* */
|
||||
/* <Fields> */
|
||||
/* font :: An @FTC_FontRec used to describe the glyph's face */
|
||||
/* and size. */
|
||||
/* */
|
||||
/* image_type :: The glyph image's type. */
|
||||
/* */
|
||||
typedef struct FTC_Image_Desc_
|
||||
{
|
||||
FTC_FontRec font;
|
||||
FT_UInt image_type;
|
||||
|
||||
} FTC_Image_Desc;
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/* */
|
||||
/* <Type> */
|
||||
/* FTC_Image_Cache */
|
||||
/* */
|
||||
/* <Description> */
|
||||
/* THIS TYPE IS DEPRECATED. Use @FTC_ImageCache instead. */
|
||||
/* */
|
||||
typedef FTC_ImageCache FTC_Image_Cache;
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/* */
|
||||
/* <Function> */
|
||||
/* FTC_Image_Cache_New */
|
||||
/* */
|
||||
/* <Description> */
|
||||
/* THIS FUNCTION IS DEPRECATED. Use @FTC_ImageCache_New instead. */
|
||||
/* */
|
||||
/* Creates a new glyph image cache. */
|
||||
/* */
|
||||
/* <Input> */
|
||||
/* manager :: The parent manager for the image cache. */
|
||||
/* */
|
||||
/* <Output> */
|
||||
/* acache :: A handle to the new glyph image cache object. */
|
||||
/* */
|
||||
/* <Return> */
|
||||
/* FreeType error code. 0 means success. */
|
||||
/* */
|
||||
FT_EXPORT( FT_Error )
|
||||
FTC_Image_Cache_New( FTC_Manager manager,
|
||||
FTC_Image_Cache *acache );
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/* */
|
||||
/* <Function> */
|
||||
/* FTC_Image_Cache_Lookup */
|
||||
/* */
|
||||
/* <Description> */
|
||||
/* THIS FUNCTION IS DEPRECATED. Use @FTC_ImageCache_Lookup instead. */
|
||||
/* */
|
||||
/* <Input> */
|
||||
/* cache :: A handle to the source glyph image cache. */
|
||||
/* */
|
||||
/* desc :: A pointer to a glyph image descriptor. */
|
||||
/* */
|
||||
/* gindex :: The glyph index to retrieve. */
|
||||
/* */
|
||||
/* <Output> */
|
||||
/* aglyph :: The corresponding @FT_Glyph object. 0 in case of */
|
||||
/* failure. */
|
||||
/* */
|
||||
/* <Return> */
|
||||
/* FreeType error code. 0 means success. */
|
||||
/* */
|
||||
/* <Note> */
|
||||
/* The returned glyph is owned and managed by the glyph image cache. */
|
||||
/* Never try to transform or discard it manually! You can however */
|
||||
/* create a copy with @FT_Glyph_Copy and modify the new one. */
|
||||
/* */
|
||||
/* Because the glyph image cache limits the total amount of memory */
|
||||
/* taken by the glyphs it holds, the returned glyph might disappear */
|
||||
/* on a later invocation of this function! It is a cache after */
|
||||
/* all... */
|
||||
/* */
|
||||
/* Use this function to "lock" the glyph as long as it is needed. */
|
||||
/* */
|
||||
FT_EXPORT( FT_Error )
|
||||
FTC_Image_Cache_Lookup( FTC_Image_Cache cache,
|
||||
FTC_Image_Desc* desc,
|
||||
FT_UInt gindex,
|
||||
FT_Glyph *aglyph );
|
||||
/* can be used as @FTC_Node_WeightFunc */
|
||||
FT_EXPORT( FT_ULong )
|
||||
FTC_INode_Weight( FTC_INode inode );
|
||||
|
||||
/* */
|
||||
|
||||
FT_END_HEADER
|
||||
|
||||
|
||||
#endif /* __FTCIMAGE_H__ */
|
||||
|
||||
|
||||
|
156
include/freetype/cache/ftcmanag.h
vendored
156
include/freetype/cache/ftcmanag.h
vendored
@ -65,7 +65,7 @@
|
||||
|
||||
#include <ft2build.h>
|
||||
#include FT_CACHE_H
|
||||
#include FT_CACHE_INTERNAL_LRU_H
|
||||
#include FT_CACHE_INTERNAL_MRU_H
|
||||
#include FT_CACHE_INTERNAL_CACHE_H
|
||||
|
||||
|
||||
@ -80,99 +80,32 @@ FT_BEGIN_HEADER
|
||||
/*************************************************************************/
|
||||
|
||||
|
||||
#define FTC_MAX_FACES_DEFAULT 2
|
||||
#define FTC_MAX_SIZES_DEFAULT 4
|
||||
#define FTC_MAX_BYTES_DEFAULT 200000L /* ~200kByte by default */
|
||||
#define FTC_MAX_FACES_DEFAULT 2
|
||||
#define FTC_MAX_SIZES_DEFAULT 4
|
||||
#define FTC_MAX_BYTES_DEFAULT 200000L /* ~200kByte by default */
|
||||
|
||||
/* maximum number of caches registered in a single manager */
|
||||
#define FTC_MAX_CACHES 16
|
||||
|
||||
|
||||
typedef struct FTC_FamilyEntryRec_
|
||||
{
|
||||
FTC_Family family;
|
||||
FTC_Cache cache;
|
||||
FT_UInt index;
|
||||
FT_UInt link;
|
||||
|
||||
} FTC_FamilyEntryRec, *FTC_FamilyEntry;
|
||||
|
||||
|
||||
#define FTC_FAMILY_ENTRY_NONE ( (FT_UInt)-1 )
|
||||
|
||||
|
||||
typedef struct FTC_FamilyTableRec_
|
||||
{
|
||||
FT_UInt count;
|
||||
FT_UInt size;
|
||||
FTC_FamilyEntry entries;
|
||||
FT_UInt free;
|
||||
|
||||
} FTC_FamilyTableRec, *FTC_FamilyTable;
|
||||
|
||||
|
||||
FT_EXPORT( FT_Error )
|
||||
ftc_family_table_alloc( FTC_FamilyTable table,
|
||||
FT_Memory memory,
|
||||
FTC_FamilyEntry *aentry );
|
||||
|
||||
FT_EXPORT( void )
|
||||
ftc_family_table_free( FTC_FamilyTable table,
|
||||
FT_UInt idx );
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/* */
|
||||
/* <Struct> */
|
||||
/* FTC_ManagerRec */
|
||||
/* */
|
||||
/* <Description> */
|
||||
/* The cache manager structure. */
|
||||
/* */
|
||||
/* <Fields> */
|
||||
/* library :: A handle to a FreeType library instance. */
|
||||
/* */
|
||||
/* faces_list :: The lru list of @FT_Face objects in the cache. */
|
||||
/* */
|
||||
/* sizes_list :: The lru list of @FT_Size objects in the cache. */
|
||||
/* */
|
||||
/* max_weight :: The maximum cache pool weight. */
|
||||
/* */
|
||||
/* cur_weight :: The current cache pool weight. */
|
||||
/* */
|
||||
/* num_nodes :: The current number of nodes in the manager. */
|
||||
/* */
|
||||
/* nodes_list :: The global lru list of all cache nodes. */
|
||||
/* */
|
||||
/* caches :: A table of installed/registered cache objects. */
|
||||
/* */
|
||||
/* request_data :: User-provided data passed to the requester. */
|
||||
/* */
|
||||
/* request_face :: User-provided function used to implement a mapping */
|
||||
/* between abstract @FTC_FaceID values and real */
|
||||
/* @FT_Face objects. */
|
||||
/* */
|
||||
/* families :: Global table of families. */
|
||||
/* */
|
||||
typedef struct FTC_ManagerRec_
|
||||
{
|
||||
FT_Library library;
|
||||
FT_LruList faces_list;
|
||||
FT_LruList sizes_list;
|
||||
FT_Memory memory;
|
||||
|
||||
FTC_Node nodes_list;
|
||||
FT_ULong max_weight;
|
||||
FT_ULong cur_weight;
|
||||
|
||||
FT_UInt num_nodes;
|
||||
FTC_Node nodes_list;
|
||||
|
||||
FTC_Cache caches[FTC_MAX_CACHES];
|
||||
FTC_Cache caches[ FTC_MAX_CACHES ];
|
||||
FT_UInt num_caches;
|
||||
|
||||
FTC_MruListRec faces;
|
||||
FTC_MruListRec sizes;
|
||||
|
||||
FT_Pointer request_data;
|
||||
FTC_Face_Requester request_face;
|
||||
|
||||
FTC_FamilyTableRec families;
|
||||
|
||||
} FTC_ManagerRec;
|
||||
|
||||
|
||||
@ -201,43 +134,58 @@ FT_BEGIN_HEADER
|
||||
FTC_Manager_Compress( FTC_Manager manager );
|
||||
|
||||
|
||||
/* try to flush "count" old nodes from the cache. return the number
|
||||
* of really flushed nodes
|
||||
*/
|
||||
FT_EXPORT( FT_UInt )
|
||||
FTC_Manager_FlushN( FTC_Manager manager,
|
||||
FT_UInt count );
|
||||
|
||||
|
||||
/* this must be used internally for the moment */
|
||||
FT_EXPORT( FT_Error )
|
||||
FTC_Manager_Register_Cache( FTC_Manager manager,
|
||||
FTC_Cache_Class clazz,
|
||||
FTC_Cache *acache );
|
||||
FTC_Manager_RegisterCache( FTC_Manager manager,
|
||||
FTC_CacheClass clazz,
|
||||
FTC_Cache *acache );
|
||||
|
||||
/* */
|
||||
|
||||
typedef struct FTC_ScalerRec_
|
||||
{
|
||||
FTC_FaceID face_id;
|
||||
FT_UInt width;
|
||||
FT_UInt height;
|
||||
FT_Int pixel;
|
||||
FT_UInt x_res;
|
||||
FT_UInt y_res;
|
||||
|
||||
} FTC_ScalerRec, *FTC_Scaler;
|
||||
|
||||
|
||||
/* can be called to increment a node's reference count */
|
||||
FT_EXPORT( void )
|
||||
FTC_Node_Ref( FTC_Node node,
|
||||
FTC_Manager manager );
|
||||
#define FTC_SCALER_COMPARE(a,b) \
|
||||
( (a)->face_id == (b)->face_id && \
|
||||
(a)->width == (b)->width && \
|
||||
(a)->height == (b)->height && \
|
||||
((a)->pixel != 0) == ((b)->pixel != 0) && \
|
||||
( (a)->pixel || \
|
||||
( (a)->x_res == (b)->x_res && \
|
||||
(a)->y_res == (b)->y_res ) ) )
|
||||
|
||||
#define FTC_SCALER_HASH(q) \
|
||||
( FTC_FACE_ID_HASH((q)->face_id) + \
|
||||
(q)->width + (q)->height*7 + \
|
||||
(q)->pixel ? ( (q)->x_res*33 ^ (q)->y_res*61 ) : 0 )
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/* */
|
||||
/* <Function> */
|
||||
/* FTC_Node_Unref */
|
||||
/* */
|
||||
/* <Description> */
|
||||
/* Decrement a cache node's internal reference count. When the count */
|
||||
/* reaches 0, it is not destroyed but becomes eligible for subsequent */
|
||||
/* cache flushes. */
|
||||
/* */
|
||||
/* <Input> */
|
||||
/* node :: The cache node handle. */
|
||||
/* */
|
||||
/* manager :: The cache manager handle. */
|
||||
/* */
|
||||
FT_EXPORT( void )
|
||||
FTC_Node_Unref( FTC_Node node,
|
||||
FTC_Manager manager );
|
||||
FT_EXPORT( FT_Error )
|
||||
FTC_Manager_LookupSize( FTC_Manager manager,
|
||||
FTC_Scaler scaler,
|
||||
FT_Size *asize );
|
||||
|
||||
/* */
|
||||
|
||||
FT_END_HEADER
|
||||
|
||||
|
||||
#endif /* __FTCMANAG_H__ */
|
||||
|
||||
|
||||
|
143
include/freetype/cache/ftcmru.h
vendored
Normal file
143
include/freetype/cache/ftcmru.h
vendored
Normal file
@ -0,0 +1,143 @@
|
||||
/***************************************************************************/
|
||||
/* */
|
||||
/* ftcmru.h */
|
||||
/* */
|
||||
/* Simple MRU list-cache (specification). */
|
||||
/* */
|
||||
/* Copyright 2000-2001, 2003 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. */
|
||||
/* */
|
||||
/***************************************************************************/
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/* */
|
||||
/* An MRU is a list that cannot hold more than a certain number of */
|
||||
/* elements (`max_elements'). All elements in the list are sorted in */
|
||||
/* least-recently-used order, i.e., the `oldest' element is at the tail */
|
||||
/* of the list. */
|
||||
/* */
|
||||
/* When doing a lookup (either through `Lookup()' or `Lookup_Node()'), */
|
||||
/* the list is searched for an element with the corresponding key. If */
|
||||
/* it is found, the element is moved to the head of the list and is */
|
||||
/* returned. */
|
||||
/* */
|
||||
/* If no corresponding element is found, the lookup routine will try to */
|
||||
/* obtain a new element with the relevant key. If the list is already */
|
||||
/* full, the oldest element from the list is discarded and replaced by a */
|
||||
/* new one; a new element is added to the list otherwise. */
|
||||
/* */
|
||||
/* Note that it is possible to pre-allocate the element list nodes. */
|
||||
/* This is handy if `max_elements' is sufficiently small, as it saves */
|
||||
/* allocations/releases during the lookup process. */
|
||||
/* */
|
||||
/*************************************************************************/
|
||||
|
||||
|
||||
#ifndef __FTCMRU_H__
|
||||
#define __FTCMRU_H__
|
||||
|
||||
|
||||
#include <ft2build.h>
|
||||
#include FT_FREETYPE_H
|
||||
|
||||
#ifdef FREETYPE_H
|
||||
#error "freetype.h of FreeType 1 has been loaded!"
|
||||
#error "Please fix the directory search order for header files"
|
||||
#error "so that freetype.h of FreeType 2 is found first."
|
||||
#endif
|
||||
|
||||
|
||||
FT_BEGIN_HEADER
|
||||
|
||||
typedef struct FTC_MruListRec_* FTC_MruList;
|
||||
|
||||
typedef struct FTC_MruNodeRec_* FTC_MruNode;
|
||||
|
||||
typedef struct FTC_MruListClassRec_ const * FTC_MruListClass;
|
||||
|
||||
typedef struct FTC_MruNodeRec_
|
||||
{
|
||||
FTC_MruNode next;
|
||||
|
||||
} FTC_MruNodeRec;
|
||||
|
||||
typedef FT_Int (*FTC_MruNode_CompareFunc)( FTC_MruNode node,
|
||||
FT_Pointer key );
|
||||
|
||||
typedef FT_Error (*FTC_MruNode_InitFunc)( FTC_MruNode node,
|
||||
FT_Pointer key,
|
||||
FT_Pointer data );
|
||||
|
||||
typedef FT_Error (*FTC_MruNode_ResetFunc)( FTC_MruNode node,
|
||||
FT_Pointer key,
|
||||
FT_Pointer data );
|
||||
|
||||
typedef void (*FTC_MruNode_DoneFunc)( FTC_MruNode node,
|
||||
FT_Pointer data );
|
||||
|
||||
typedef struct FTC_MruListClassRec_
|
||||
{
|
||||
FT_UInt node_size;
|
||||
FTC_MruNode_CompareFunc node_compare;
|
||||
FTC_MruNode_InitFunc node_init;
|
||||
FTC_MruNode_ResetFunc node_reset;
|
||||
FTC_MruNode_DoneFunc node_done;
|
||||
|
||||
} FTC_MruListClassRec;
|
||||
|
||||
typedef struct FTC_MruListRec_
|
||||
{
|
||||
FT_UInt num_nodes;
|
||||
FT_UInt max_nodes;
|
||||
FTC_MruNode nodes;
|
||||
FT_Pointer data;
|
||||
FTC_MruListClassRec clazz;
|
||||
FT_Memory memory;
|
||||
|
||||
} FTC_MruListRec;
|
||||
|
||||
|
||||
FT_EXPORT( void )
|
||||
FTC_MruList_Init( FTC_MruList list,
|
||||
FTC_MruListClass clazz,
|
||||
FT_UInt max_nodes,
|
||||
FT_Pointer data,
|
||||
FT_Memory memory );
|
||||
|
||||
FT_EXPORT( void )
|
||||
FTC_MruList_Reset( FTC_MruList list );
|
||||
|
||||
|
||||
FT_EXPORT( void )
|
||||
FTC_MruList_Done( FTC_MruList list );
|
||||
|
||||
|
||||
FT_EXPORT( FT_Error )
|
||||
FTC_MruList_Lookup( FTC_MruList list,
|
||||
FT_Pointer key,
|
||||
FTC_MruNode *pnode );
|
||||
|
||||
FT_EXPORT( void )
|
||||
FTC_MruList_Remove( FTC_MruList list,
|
||||
FTC_MruNode node );
|
||||
|
||||
FT_EXPORT( void )
|
||||
FTC_MruList_RemoveSelection( FTC_MruList list,
|
||||
FTC_MruNode_CompareFunc select,
|
||||
FT_Pointer key );
|
||||
/* */
|
||||
|
||||
FT_END_HEADER
|
||||
|
||||
|
||||
#endif /* __FTCMRU_H__ */
|
||||
|
||||
|
||||
/* END */
|
270
include/freetype/cache/ftcsbits.h
vendored
270
include/freetype/cache/ftcsbits.h
vendored
@ -22,251 +22,69 @@
|
||||
|
||||
#include <ft2build.h>
|
||||
#include FT_CACHE_H
|
||||
#include FT_CACHE_IMAGE_H
|
||||
#include FT_CACHE_INTERNAL_GLYPH_H
|
||||
|
||||
|
||||
FT_BEGIN_HEADER
|
||||
|
||||
#define FTC_SBIT_ITEMS_PER_NODE 16
|
||||
|
||||
/*************************************************************************/
|
||||
/* */
|
||||
/* <Section> */
|
||||
/* cache_subsystem */
|
||||
/* */
|
||||
/*************************************************************************/
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/* */
|
||||
/* <Type> */
|
||||
/* FTC_SBit */
|
||||
/* */
|
||||
/* <Description> */
|
||||
/* A handle to a small bitmap descriptor. See the @FTC_SBitRec */
|
||||
/* structure for details. */
|
||||
/* */
|
||||
typedef struct FTC_SBitRec_* FTC_SBit;
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/* */
|
||||
/* <Struct> */
|
||||
/* FTC_SBitRec */
|
||||
/* */
|
||||
/* <Description> */
|
||||
/* A very compact structure used to describe a small glyph bitmap. */
|
||||
/* */
|
||||
/* <Fields> */
|
||||
/* width :: The bitmap width in pixels. */
|
||||
/* */
|
||||
/* height :: The bitmap height in pixels. */
|
||||
/* */
|
||||
/* left :: The horizontal distance from the pen position to the */
|
||||
/* left bitmap border (a.k.a. `left side bearing', or */
|
||||
/* `lsb'). */
|
||||
/* */
|
||||
/* top :: The vertical distance from the pen position (on the */
|
||||
/* baseline) to the upper bitmap border (a.k.a. `top */
|
||||
/* side bearing'). The distance is positive for upwards */
|
||||
/* Y coordinates. */
|
||||
/* */
|
||||
/* format :: The format of the glyph bitmap (monochrome or gray). */
|
||||
/* */
|
||||
/* max_grays :: Maximum gray level value (in the range 1 to 255). */
|
||||
/* */
|
||||
/* pitch :: The number of bytes per bitmap line. May be positive */
|
||||
/* or negative. */
|
||||
/* */
|
||||
/* xadvance :: The horizontal advance width in pixels. */
|
||||
/* */
|
||||
/* yadvance :: The vertical advance height in pixels. */
|
||||
/* */
|
||||
/* buffer :: A pointer to the bitmap pixels. */
|
||||
/* */
|
||||
typedef struct FTC_SBitRec_
|
||||
typedef struct FTC_SNodeRec_
|
||||
{
|
||||
FT_Byte width;
|
||||
FT_Byte height;
|
||||
FT_Char left;
|
||||
FT_Char top;
|
||||
FTC_GNodeRec gnode;
|
||||
FT_UInt count;
|
||||
FTC_SBitRec sbits[ FTC_SBIT_ITEMS_PER_NODE ];
|
||||
|
||||
FT_Byte format;
|
||||
FT_Byte max_grays;
|
||||
FT_Short pitch;
|
||||
FT_Char xadvance;
|
||||
FT_Char yadvance;
|
||||
|
||||
FT_Byte* buffer;
|
||||
|
||||
} FTC_SBitRec;
|
||||
} FTC_SNodeRec, *FTC_SNode;
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/* */
|
||||
/* <Type> */
|
||||
/* FTC_SBitCache */
|
||||
/* */
|
||||
/* <Description> */
|
||||
/* A handle to a small bitmap cache. These are special cache objects */
|
||||
/* used to store small glyph bitmaps (and anti-aliased pixmaps) in a */
|
||||
/* much more efficient way than the traditional glyph image cache */
|
||||
/* implemented by @FTC_ImageCache. */
|
||||
/* */
|
||||
typedef struct FTC_SBitCacheRec_* FTC_SBitCache;
|
||||
#define FTC_SNODE( x ) ( (FTC_SNode)( x ) )
|
||||
#define FTC_SNODE_GINDEX( x ) FTC_GNODE(x)->gindex
|
||||
#define FTC_SNODE_FAMILY( x ) FTC_GNODE(x)->family
|
||||
|
||||
typedef FT_UInt (*FTC_SFamily_GetCountFunc)( FTC_Family family,
|
||||
FTC_Manager manager );
|
||||
|
||||
/*************************************************************************/
|
||||
/* */
|
||||
/* <Type> */
|
||||
/* FTC_SBit_Cache */
|
||||
/* */
|
||||
/* <Description> */
|
||||
/* DEPRECATED. Use @FTC_SBitCache instead. */
|
||||
/* */
|
||||
typedef FTC_SBitCache FTC_SBit_Cache;
|
||||
typedef FT_Error (*FTC_SFamily_LoadGlyphFunc)( FTC_Family family,
|
||||
FT_UInt gindex,
|
||||
FTC_Manager manager,
|
||||
FT_Face *aface );
|
||||
|
||||
typedef struct FTC_SFamilyClassRec_
|
||||
{
|
||||
FTC_MruListClassRec clazz;
|
||||
FTC_SFamily_GetCountFunc family_get_count;
|
||||
FTC_SFamily_LoadGlyphFunc family_load_glyph;
|
||||
|
||||
} FTC_SFamilyClassRec;
|
||||
|
||||
typedef const FTC_SFamilyClassRec* FTC_SFamilyClass;
|
||||
|
||||
#define FTC_SFAMILY_CLASS(x) ((FTC_SFamilyClass)(x))
|
||||
|
||||
#define FTC_CACHE__SFAMILY_CLASS(x) \
|
||||
FTC_SFAMILY_CLASS( FTC_CACHE__GCACHE_CLASS(x)->family_class )
|
||||
|
||||
FT_EXPORT( void )
|
||||
FTC_SNode_Free( FTC_SNode snode,
|
||||
FTC_Cache cache );
|
||||
|
||||
/*************************************************************************/
|
||||
/* */
|
||||
/* <Function> */
|
||||
/* FTC_SBitCache_New */
|
||||
/* */
|
||||
/* <Description> */
|
||||
/* Creates a new cache to store small glyph bitmaps. */
|
||||
/* */
|
||||
/* <Input> */
|
||||
/* manager :: A handle to the source cache manager. */
|
||||
/* */
|
||||
/* <Output> */
|
||||
/* acache :: A handle to the new sbit cache. NULL in case of error. */
|
||||
/* */
|
||||
/* <Return> */
|
||||
/* FreeType error code. 0 means success. */
|
||||
/* */
|
||||
FT_EXPORT( FT_Error )
|
||||
FTC_SBitCache_New( FTC_Manager manager,
|
||||
FTC_SBitCache *acache );
|
||||
FTC_SNode_New( FTC_SNode *psnode,
|
||||
FTC_GQuery gquery,
|
||||
FTC_Cache cache );
|
||||
|
||||
FT_EXPORT( FT_ULong )
|
||||
FTC_SNode_Weight( FTC_SNode inode );
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/* */
|
||||
/* <Function> */
|
||||
/* FTC_SBitCache_Lookup */
|
||||
/* */
|
||||
/* <Description> */
|
||||
/* Looks up a given small glyph bitmap in a given sbit cache and */
|
||||
/* "lock" it to prevent its flushing from the cache until needed */
|
||||
/* */
|
||||
/* <Input> */
|
||||
/* cache :: A handle to the source sbit cache. */
|
||||
/* */
|
||||
/* type :: A pointer to the glyph image type descriptor. */
|
||||
/* */
|
||||
/* gindex :: The glyph index. */
|
||||
/* */
|
||||
/* <Output> */
|
||||
/* sbit :: A handle to a small bitmap descriptor. */
|
||||
/* */
|
||||
/* anode :: Used to return the address of of the corresponding cache */
|
||||
/* node after incrementing its reference count (see note */
|
||||
/* below). */
|
||||
/* */
|
||||
/* <Return> */
|
||||
/* FreeType error code. 0 means success. */
|
||||
/* */
|
||||
/* <Note> */
|
||||
/* The small bitmap descriptor and its bit buffer are owned by the */
|
||||
/* cache and should never be freed by the application. They might */
|
||||
/* as well disappear from memory on the next cache lookup, so don't */
|
||||
/* treat them as persistent data. */
|
||||
/* */
|
||||
/* The descriptor's `buffer' field is set to 0 to indicate a missing */
|
||||
/* glyph bitmap. */
|
||||
/* */
|
||||
/* If "anode" is _not_ NULL, it receives the address of the cache */
|
||||
/* node containing the bitmap, after increasing its reference count. */
|
||||
/* This ensures that the node (as well as the image) will always be */
|
||||
/* kept in the cache until you call @FTC_Node_Unref to "release" it. */
|
||||
/* */
|
||||
/* If "anode" is NULL, the cache node is left unchanged, which means */
|
||||
/* that the bitmap could be flushed out of the cache on the next */
|
||||
/* call to one of the caching sub-system APIs. Don't assume that it */
|
||||
/* is persistent! */
|
||||
/* */
|
||||
FT_EXPORT( FT_Error )
|
||||
FTC_SBitCache_Lookup( FTC_SBitCache cache,
|
||||
FTC_ImageType type,
|
||||
FT_UInt gindex,
|
||||
FTC_SBit *sbit,
|
||||
FTC_Node *anode );
|
||||
|
||||
FT_EXPORT( FT_Bool )
|
||||
FTC_SNode_Compare( FTC_SNode snode,
|
||||
FTC_GQuery gquery,
|
||||
FTC_Cache cache );
|
||||
|
||||
/* */
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/* */
|
||||
/* <Function> */
|
||||
/* FTC_SBit_Cache_New */
|
||||
/* */
|
||||
/* <Description> */
|
||||
/* DEPRECATED. Use @FTC_SBitCache_New instead. */
|
||||
/* */
|
||||
/* Creates a new cache to store small glyph bitmaps. */
|
||||
/* */
|
||||
/* <Input> */
|
||||
/* manager :: A handle to the source cache manager. */
|
||||
/* */
|
||||
/* <Output> */
|
||||
/* acache :: A handle to the new sbit cache. NULL in case of error. */
|
||||
/* */
|
||||
/* <Return> */
|
||||
/* FreeType error code. 0 means success. */
|
||||
/* */
|
||||
FT_EXPORT( FT_Error )
|
||||
FTC_SBit_Cache_New( FTC_Manager manager,
|
||||
FTC_SBit_Cache *acache );
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/* */
|
||||
/* <Function> */
|
||||
/* FTC_SBit_Cache_Lookup */
|
||||
/* */
|
||||
/* <Description> */
|
||||
/* DEPRECATED. Use @FTC_SBitCache_Lookup instead. */
|
||||
/* */
|
||||
/* Looks up a given small glyph bitmap in a given sbit cache. */
|
||||
/* */
|
||||
/* <Input> */
|
||||
/* cache :: A handle to the source sbit cache. */
|
||||
/* */
|
||||
/* desc :: A pointer to the glyph image descriptor. */
|
||||
/* */
|
||||
/* gindex :: The glyph index. */
|
||||
/* */
|
||||
/* <Output> */
|
||||
/* sbit :: A handle to a small bitmap descriptor. */
|
||||
/* */
|
||||
/* <Return> */
|
||||
/* FreeType error code. 0 means success. */
|
||||
/* */
|
||||
/* <Note> */
|
||||
/* The small bitmap descriptor and its bit buffer are owned by the */
|
||||
/* cache and should never be freed by the application. They might */
|
||||
/* as well disappear from memory on the next cache lookup, so don't */
|
||||
/* treat them as persistent data. */
|
||||
/* */
|
||||
/* The descriptor's `buffer' field is set to 0 to indicate a missing */
|
||||
/* glyph bitmap. */
|
||||
/* */
|
||||
FT_EXPORT( FT_Error )
|
||||
FTC_SBit_Cache_Lookup( FTC_SBit_Cache cache,
|
||||
FTC_Image_Desc* desc,
|
||||
FT_UInt gindex,
|
||||
FTC_SBit *sbit );
|
||||
|
||||
|
||||
FT_END_HEADER
|
||||
|
||||
#endif /* __FTCSBITS_H__ */
|
||||
|
208
include/freetype/cache/ftlru.h
vendored
208
include/freetype/cache/ftlru.h
vendored
@ -1,208 +0,0 @@
|
||||
/***************************************************************************/
|
||||
/* */
|
||||
/* ftlru.h */
|
||||
/* */
|
||||
/* Simple LRU list-cache (specification). */
|
||||
/* */
|
||||
/* Copyright 2000-2001, 2003 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. */
|
||||
/* */
|
||||
/***************************************************************************/
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/* */
|
||||
/* An LRU is a list that cannot hold more than a certain number of */
|
||||
/* elements (`max_elements'). All elements in the list are sorted in */
|
||||
/* least-recently-used order, i.e., the `oldest' element is at the tail */
|
||||
/* of the list. */
|
||||
/* */
|
||||
/* When doing a lookup (either through `Lookup()' or `Lookup_Node()'), */
|
||||
/* the list is searched for an element with the corresponding key. If */
|
||||
/* it is found, the element is moved to the head of the list and is */
|
||||
/* returned. */
|
||||
/* */
|
||||
/* If no corresponding element is found, the lookup routine will try to */
|
||||
/* obtain a new element with the relevant key. If the list is already */
|
||||
/* full, the oldest element from the list is discarded and replaced by a */
|
||||
/* new one; a new element is added to the list otherwise. */
|
||||
/* */
|
||||
/* Note that it is possible to pre-allocate the element list nodes. */
|
||||
/* This is handy if `max_elements' is sufficiently small, as it saves */
|
||||
/* allocations/releases during the lookup process. */
|
||||
/* */
|
||||
/*************************************************************************/
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/********* *********/
|
||||
/********* WARNING, THIS IS BETA CODE. *********/
|
||||
/********* *********/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
|
||||
#ifndef __FTLRU_H__
|
||||
#define __FTLRU_H__
|
||||
|
||||
|
||||
#include <ft2build.h>
|
||||
#include FT_FREETYPE_H
|
||||
|
||||
#ifdef FREETYPE_H
|
||||
#error "freetype.h of FreeType 1 has been loaded!"
|
||||
#error "Please fix the directory search order for header files"
|
||||
#error "so that freetype.h of FreeType 2 is found first."
|
||||
#endif
|
||||
|
||||
|
||||
FT_BEGIN_HEADER
|
||||
|
||||
|
||||
/* generic list key type */
|
||||
typedef FT_Pointer FT_LruKey;
|
||||
|
||||
/* a list list handle */
|
||||
typedef struct FT_LruListRec_* FT_LruList;
|
||||
|
||||
/* a list class handle */
|
||||
typedef const struct FT_LruList_ClassRec_* FT_LruList_Class;
|
||||
|
||||
/* a list node handle */
|
||||
typedef struct FT_LruNodeRec_* FT_LruNode;
|
||||
|
||||
/* the list node structure */
|
||||
typedef struct FT_LruNodeRec_
|
||||
{
|
||||
FT_LruNode next;
|
||||
FT_LruKey key;
|
||||
|
||||
} FT_LruNodeRec;
|
||||
|
||||
|
||||
/* the list structure */
|
||||
typedef struct FT_LruListRec_
|
||||
{
|
||||
FT_Memory memory;
|
||||
FT_LruList_Class clazz;
|
||||
FT_LruNode nodes;
|
||||
FT_UInt max_nodes;
|
||||
FT_UInt num_nodes;
|
||||
FT_Pointer data;
|
||||
|
||||
} FT_LruListRec;
|
||||
|
||||
|
||||
/* initialize a list list */
|
||||
typedef FT_Error
|
||||
(*FT_LruList_InitFunc)( FT_LruList list );
|
||||
|
||||
/* finalize a list list */
|
||||
typedef void
|
||||
(*FT_LruList_DoneFunc)( FT_LruList list );
|
||||
|
||||
/* this method is used to initialize a new list element node */
|
||||
typedef FT_Error
|
||||
(*FT_LruNode_InitFunc)( FT_LruNode node,
|
||||
FT_LruKey key,
|
||||
FT_Pointer data );
|
||||
|
||||
/* this method is used to finalize a given list element node */
|
||||
typedef void
|
||||
(*FT_LruNode_DoneFunc)( FT_LruNode node,
|
||||
FT_Pointer data );
|
||||
|
||||
/* If defined, this method is called when the list if full */
|
||||
/* during the lookup process -- it is used to change the contents */
|
||||
/* of a list element node instead of calling `done_element()', */
|
||||
/* then `init_element()'. Set it to 0 for default behaviour. */
|
||||
typedef FT_Error
|
||||
(*FT_LruNode_FlushFunc)( FT_LruNode node,
|
||||
FT_LruKey new_key,
|
||||
FT_Pointer data );
|
||||
|
||||
/* If defined, this method is used to compare a list element node */
|
||||
/* with a given key during a lookup. If set to 0, the `key' */
|
||||
/* fields will be directly compared instead. */
|
||||
typedef FT_Bool
|
||||
(*FT_LruNode_CompareFunc)( FT_LruNode node,
|
||||
FT_LruKey key,
|
||||
FT_Pointer data );
|
||||
|
||||
/* A selector is used to indicate whether a given list element node */
|
||||
/* is part of a selection for FT_LruList_Remove_Selection(). The */
|
||||
/* functrion must return true (i.e., non-null) to indicate that the */
|
||||
/* node is part of it. */
|
||||
typedef FT_Bool
|
||||
(*FT_LruNode_SelectFunc)( FT_LruNode node,
|
||||
FT_Pointer data,
|
||||
FT_Pointer list_data );
|
||||
|
||||
/* LRU class */
|
||||
typedef struct FT_LruList_ClassRec_
|
||||
{
|
||||
FT_UInt list_size;
|
||||
FT_LruList_InitFunc list_init; /* optional */
|
||||
FT_LruList_DoneFunc list_done; /* optional */
|
||||
|
||||
FT_UInt node_size;
|
||||
FT_LruNode_InitFunc node_init; /* MANDATORY */
|
||||
FT_LruNode_DoneFunc node_done; /* optional */
|
||||
FT_LruNode_FlushFunc node_flush; /* optional */
|
||||
FT_LruNode_CompareFunc node_compare; /* optional */
|
||||
|
||||
} FT_LruList_ClassRec;
|
||||
|
||||
|
||||
/* The following functions must be exported in the case where */
|
||||
/* applications would want to write their own cache classes. */
|
||||
|
||||
FT_EXPORT( FT_Error )
|
||||
FT_LruList_New( FT_LruList_Class clazz,
|
||||
FT_UInt max_elements,
|
||||
FT_Pointer user_data,
|
||||
FT_Memory memory,
|
||||
FT_LruList *alist );
|
||||
|
||||
FT_EXPORT( void )
|
||||
FT_LruList_Reset( FT_LruList list );
|
||||
|
||||
FT_EXPORT( void )
|
||||
FT_LruList_Destroy ( FT_LruList list );
|
||||
|
||||
FT_EXPORT( FT_Error )
|
||||
FT_LruList_Lookup( FT_LruList list,
|
||||
FT_LruKey key,
|
||||
FT_LruNode *anode );
|
||||
|
||||
FT_EXPORT( void )
|
||||
FT_LruList_Remove( FT_LruList list,
|
||||
FT_LruNode node );
|
||||
|
||||
FT_EXPORT( void )
|
||||
FT_LruList_Remove_Selection( FT_LruList list,
|
||||
FT_LruNode_SelectFunc select_func,
|
||||
FT_Pointer select_data );
|
||||
|
||||
/* */
|
||||
|
||||
FT_END_HEADER
|
||||
|
||||
|
||||
#endif /* __FTLRU_H__ */
|
||||
|
||||
|
||||
/* END */
|
@ -433,7 +433,10 @@
|
||||
/* see the API defined in @FT_CACHE_SMALL_BITMAPS_H if you only need */
|
||||
/* to store small glyph bitmaps, as it will use less memory. */
|
||||
/* */
|
||||
#define FT_CACHE_IMAGE_H <freetype/cache/ftcimage.h>
|
||||
/* this macro is *DEPRECATED*, simply include @FT_CACHE_H and you'll */
|
||||
/* have all glyph image-related cache declarations */
|
||||
/* */
|
||||
#define FT_CACHE_IMAGE_H FT_CACHE_H
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
@ -450,7 +453,10 @@
|
||||
/* in @FT_CACHE_IMAGE_H if you want to cache arbitrary glyph images, */
|
||||
/* including scalable outlines. */
|
||||
/* */
|
||||
#define FT_CACHE_SMALL_BITMAPS_H <freetype/cache/ftcsbits.h>
|
||||
/* this macro is *DEPRECATED*, simply include @FT_CACHE_H and you'll */
|
||||
/* have all small bitmaps-related cache declarations */
|
||||
/* */
|
||||
#define FT_CACHE_SMALL_BITMAPS_H FT_CACHE_H
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
@ -462,7 +468,10 @@
|
||||
/* A macro used in #include statements to name the file containing */
|
||||
/* the `charmap' API of the FreeType 2 cache sub-system. */
|
||||
/* */
|
||||
#define FT_CACHE_CHARMAP_H <freetype/cache/ftccmap.h>
|
||||
/* this macro is *DEPRECATED*, simply include @FT_CACHE_H and you'll */
|
||||
/* have all charmap-based cache declarations */
|
||||
/* */
|
||||
#define FT_CACHE_CHARMAP_H FT_CACHE_H
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
@ -515,9 +524,13 @@
|
||||
|
||||
#define FT_CACHE_MANAGER_H <freetype/cache/ftcmanag.h>
|
||||
|
||||
#define FT_CACHE_INTERNAL_LRU_H <freetype/cache/ftlru.h>
|
||||
#define FT_CACHE_INTERNAL_GLYPH_H <freetype/cache/ftcglyph.h>
|
||||
#define FT_CACHE_INTERNAL_MRU_H <freetype/cache/ftcmru.h>
|
||||
#define FT_CACHE_INTERNAL_MANAGER_H <freetype/cache/ftcmanag.h>
|
||||
#define FT_CACHE_INTERNAL_CACHE_H <freetype/cache/ftccache.h>
|
||||
#define FT_CACHE_INTERNAL_GLYPH_H <freetype/cache/ftcglyph.h>
|
||||
#define FT_CACHE_INTERNAL_IMAGE_H <freetype/cache/ftcimage.h>
|
||||
#define FT_CACHE_INTERNAL_SBITS_H <freetype/cache/ftcsbits.h>
|
||||
|
||||
|
||||
#define FT_XFREE86_H <freetype/ftxf86.h>
|
||||
|
||||
|
@ -277,8 +277,8 @@ FT_BEGIN_HEADER
|
||||
/* Do not #undef these macros here since the build system might define */
|
||||
/* them for certain configurations only. */
|
||||
/* */
|
||||
/* #define FT_DEBUG_LEVEL_ERROR */
|
||||
/* #define FT_DEBUG_LEVEL_TRACE */
|
||||
#define FT_DEBUG_LEVEL_ERROR
|
||||
#define FT_DEBUG_LEVEL_TRACE
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
@ -296,7 +296,7 @@ FT_BEGIN_HEADER
|
||||
/* Do not #undef this macro here since the build system might define */
|
||||
/* it for certain configurations only. */
|
||||
/* */
|
||||
/* #define FT_DEBUG_MEMORY */
|
||||
#define FT_DEBUG_MEMORY
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
|
@ -63,7 +63,7 @@ FT_BEGIN_HEADER
|
||||
/* FTC_Face_Requester */
|
||||
/* */
|
||||
/* FTC_Manager_New */
|
||||
/* FTC_Manager_Lookup_Face */
|
||||
/* FTC_Manager_LookupFace */
|
||||
/* FTC_Manager_Lookup_Size */
|
||||
/* */
|
||||
/* FTC_Node */
|
||||
@ -257,28 +257,16 @@ FT_BEGIN_HEADER
|
||||
/* Creates a new cache manager. */
|
||||
/* */
|
||||
/* <Input> */
|
||||
/* library :: The parent FreeType library handle to use. */
|
||||
/* library :: The parent FreeType library handle to use. */
|
||||
/* */
|
||||
/* max_faces :: Maximum number of faces to keep alive in manager. */
|
||||
/* Use 0 for defaults (currently 2; see the value of */
|
||||
/* FTC_MAX_FACES_DEFAULT in */
|
||||
/* `include/freetype/cache/ftcmanag.h'). */
|
||||
/* max_bytes :: Maximum number of bytes to use for cached data. */
|
||||
/* Use 0 for defaults. */
|
||||
/* */
|
||||
/* max_sizes :: Maximum number of sizes to keep alive in manager. */
|
||||
/* Use 0 for defaults (currently 4; see the value of */
|
||||
/* FTC_MAX_SIZES_DEFAULT in */
|
||||
/* `include/freetype/cache/ftcmanag.h'). */
|
||||
/* requester :: An application-provided callback used to translate */
|
||||
/* face IDs into real @FT_Face objects. */
|
||||
/* */
|
||||
/* max_bytes :: Maximum number of bytes to use for cached data. */
|
||||
/* Use 0 for defaults (currently 200000; see the value */
|
||||
/* of FTC_MAX_BYTES_DEFAULT in */
|
||||
/* `include/freetype/cache/ftcmanag.h'). */
|
||||
/* */
|
||||
/* requester :: An application-provided callback used to translate */
|
||||
/* face IDs into real @FT_Face objects. */
|
||||
/* */
|
||||
/* req_data :: A generic pointer that is passed to the requester */
|
||||
/* each time it is called (see @FTC_Face_Requester). */
|
||||
/* req_data :: A generic pointer that is passed to the requester */
|
||||
/* each time it is called (see @FTC_Face_Requester). */
|
||||
/* */
|
||||
/* <Output> */
|
||||
/* amanager :: A handle to a new manager object. 0 in case of */
|
||||
@ -331,7 +319,7 @@ FT_BEGIN_HEADER
|
||||
/*************************************************************************/
|
||||
/* */
|
||||
/* <Function> */
|
||||
/* FTC_Manager_Lookup_Face */
|
||||
/* FTC_Manager_LookupFace */
|
||||
/* */
|
||||
/* <Description> */
|
||||
/* Retrieves the @FT_Face object that corresponds to a given face ID */
|
||||
@ -361,7 +349,7 @@ FT_BEGIN_HEADER
|
||||
/* to transform glyphs, do it yourself after glyph loading. */
|
||||
/* */
|
||||
FT_EXPORT( FT_Error )
|
||||
FTC_Manager_Lookup_Face( FTC_Manager manager,
|
||||
FTC_Manager_LookupFace( FTC_Manager manager,
|
||||
FTC_FaceID face_id,
|
||||
FT_Face *aface );
|
||||
|
||||
@ -369,48 +357,411 @@ FT_BEGIN_HEADER
|
||||
/*************************************************************************/
|
||||
/* */
|
||||
/* <Function> */
|
||||
/* FTC_Manager_Lookup_Size */
|
||||
/* FTC_Node_Unref */
|
||||
/* */
|
||||
/* <Description> */
|
||||
/* Retrieves the @FT_Face and @FT_Size objects that correspond to a */
|
||||
/* given font. */
|
||||
/* Decrement a cache node's internal reference count. When the count */
|
||||
/* reaches 0, it is not destroyed but becomes eligible for subsequent */
|
||||
/* cache flushes. */
|
||||
/* */
|
||||
/* <Input> */
|
||||
/* node :: The cache node handle. */
|
||||
/* */
|
||||
/* manager :: The cache manager handle. */
|
||||
/* */
|
||||
FT_EXPORT( void )
|
||||
FTC_Node_Unref( FTC_Node node,
|
||||
FTC_Manager manager );
|
||||
|
||||
|
||||
/* remove all nodes belonging to a given face_id */
|
||||
FT_EXPORT( void )
|
||||
FTC_Manager_RemoveFaceID( FTC_Manager manager,
|
||||
FTC_FaceID face_id );
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/* */
|
||||
/* <Section> */
|
||||
/* cache_subsystem */
|
||||
/* */
|
||||
/*************************************************************************/
|
||||
|
||||
/************************************************************************
|
||||
*
|
||||
* @type:
|
||||
* FTC_CMapCache
|
||||
*
|
||||
* @description:
|
||||
* An opaque handle used to manager a charmap cache. This cache is
|
||||
* to hold character codes -> glyph indices mappings.
|
||||
*/
|
||||
typedef struct FTC_CMapCacheRec_* FTC_CMapCache;
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/* */
|
||||
/* @type: */
|
||||
/* FTC_CMapDesc */
|
||||
/* */
|
||||
/* @description: */
|
||||
/* A handle to an @FTC_CMapDescRec structure used to describe a given */
|
||||
/* charmap in a charmap cache. */
|
||||
/* */
|
||||
/* Each @FTC_CMapDesc describes which charmap (of which @FTC_FaceID) */
|
||||
/* we want to use in @FTC_CMapCache_Lookup. */
|
||||
/* */
|
||||
typedef struct FTC_CMapDescRec_* FTC_CMapDesc;
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/* */
|
||||
/* @function: */
|
||||
/* FTC_CMapCache_New */
|
||||
/* */
|
||||
/* @description: */
|
||||
/* Creates a new charmap cache. */
|
||||
/* */
|
||||
/* @input: */
|
||||
/* manager :: A handle to the cache manager. */
|
||||
/* */
|
||||
/* font :: The font to use. */
|
||||
/* @output: */
|
||||
/* acache :: A new cache handle. NULL in case of error. */
|
||||
/* */
|
||||
/* @return: */
|
||||
/* FreeType error code. 0 means success. */
|
||||
/* */
|
||||
/* @note: */
|
||||
/* Like all other caches, this one will be destroyed with the cache */
|
||||
/* manager. */
|
||||
/* */
|
||||
FT_EXPORT( FT_Error )
|
||||
FTC_CMapCache_New( FTC_Manager manager,
|
||||
FTC_CMapCache *acache );
|
||||
|
||||
|
||||
/* retrieve the index of a given charmap
|
||||
*/
|
||||
FT_EXPORT( FT_UInt )
|
||||
FT_Get_CharMap_Index( FT_CharMap charmap );
|
||||
|
||||
/*************************************************************************/
|
||||
/* */
|
||||
/* @function: */
|
||||
/* FTC_CMapCache_Lookup */
|
||||
/* */
|
||||
/* @description: */
|
||||
/* Translates a character code into a glyph index, using the charmap */
|
||||
/* cache. */
|
||||
/* */
|
||||
/* @input: */
|
||||
/* cache :: A charmap cache handle. */
|
||||
/* */
|
||||
/* cmap_desc :: A charmap descriptor handle. */
|
||||
/* */
|
||||
/* char_code :: The character code (in the corresponding charmap). */
|
||||
/* */
|
||||
/* @return: */
|
||||
/* Glyph index. 0 means "no glyph". */
|
||||
/* */
|
||||
/* @note: */
|
||||
/* This function doesn't return @FTC_Node handles, since there is no */
|
||||
/* real use for them with typical uses of charmaps. */
|
||||
/* */
|
||||
FT_EXPORT( FT_UInt )
|
||||
FTC_CMapCache_Lookup( FTC_CMapCache cache,
|
||||
FTC_FaceID face_id,
|
||||
FT_UInt cmap_index,
|
||||
FT_UInt32 char_code );
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/* */
|
||||
/* <Section> */
|
||||
/* cache_subsystem */
|
||||
/* */
|
||||
/*************************************************************************/
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/***** *****/
|
||||
/***** IMAGE CACHE OBJECT *****/
|
||||
/***** *****/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
typedef struct FTC_ImageTypeRec_
|
||||
{
|
||||
FTC_FaceID face_id;
|
||||
FT_Int width;
|
||||
FT_Int height;
|
||||
FT_Int32 flags;
|
||||
|
||||
} FTC_ImageTypeRec;
|
||||
|
||||
typedef struct FTC_ImageTypeRec_* FTC_ImageType;
|
||||
|
||||
/* */
|
||||
|
||||
#define FTC_IMAGE_TYPE_COMPARE( d1, d2 ) \
|
||||
( FTC_FONT_COMPARE( &(d1)->font, &(d2)->font ) && \
|
||||
(d1)->flags == (d2)->flags )
|
||||
|
||||
#define FTC_IMAGE_TYPE_HASH( d ) \
|
||||
(FT_UFast)( FTC_FONT_HASH( &(d)->font ) ^ \
|
||||
( (d)->flags << 4 ) )
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/* */
|
||||
/* <Type> */
|
||||
/* FTC_ImageCache */
|
||||
/* */
|
||||
/* <Description> */
|
||||
/* A handle to an glyph image cache object. They are designed to */
|
||||
/* hold many distinct glyph images while not exceeding a certain */
|
||||
/* memory threshold. */
|
||||
/* */
|
||||
typedef struct FTC_ImageCacheRec_* FTC_ImageCache;
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/* */
|
||||
/* <Function> */
|
||||
/* FTC_ImageCache_New */
|
||||
/* */
|
||||
/* <Description> */
|
||||
/* Creates a new glyph image cache. */
|
||||
/* */
|
||||
/* <Input> */
|
||||
/* manager :: The parent manager for the image cache. */
|
||||
/* */
|
||||
/* <Output> */
|
||||
/* aface :: A pointer to the handle of the face object. Set it to */
|
||||
/* zero if you don't need it. */
|
||||
/* acache :: A handle to the new glyph image cache object. */
|
||||
/* */
|
||||
/* asize :: A pointer to the handle of the size object. Set it to */
|
||||
/* zero if you don't need it. */
|
||||
/* <Return> */
|
||||
/* FreeType error code. 0 means success. */
|
||||
/* */
|
||||
FT_EXPORT( FT_Error )
|
||||
FTC_ImageCache_New( FTC_Manager manager,
|
||||
FTC_ImageCache *acache );
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/* */
|
||||
/* <Function> */
|
||||
/* FTC_ImageCache_Lookup */
|
||||
/* */
|
||||
/* <Description> */
|
||||
/* Retrieves a given glyph image from a glyph image cache. */
|
||||
/* */
|
||||
/* <Input> */
|
||||
/* cache :: A handle to the source glyph image cache. */
|
||||
/* */
|
||||
/* type :: A pointer to a glyph image type descriptor. */
|
||||
/* */
|
||||
/* gindex :: The glyph index to retrieve. */
|
||||
/* */
|
||||
/* <Output> */
|
||||
/* aglyph :: The corresponding @FT_Glyph object. 0 in case of */
|
||||
/* failure. */
|
||||
/* */
|
||||
/* anode :: Used to return the address of of the corresponding cache */
|
||||
/* node after incrementing its reference count (see note */
|
||||
/* below). */
|
||||
/* */
|
||||
/* <Return> */
|
||||
/* FreeType error code. 0 means success. */
|
||||
/* */
|
||||
/* <Note> */
|
||||
/* The returned @FT_Face object is always owned by the manager. You */
|
||||
/* should never try to discard it yourself. */
|
||||
/* The returned glyph is owned and managed by the glyph image cache. */
|
||||
/* Never try to transform or discard it manually! You can however */
|
||||
/* create a copy with @FT_Glyph_Copy and modify the new one. */
|
||||
/* */
|
||||
/* Never change the face's transformation matrix (i.e., never call */
|
||||
/* the @FT_Set_Transform function) on a returned face! If you need */
|
||||
/* to transform glyphs, do it yourself after glyph loading. */
|
||||
/* If "anode" is _not_ NULL, it receives the address of the cache */
|
||||
/* node containing the glyph image, after increasing its reference */
|
||||
/* count. This ensures that the node (as well as the FT_Glyph) will */
|
||||
/* always be kept in the cache until you call @FTC_Node_Unref to */
|
||||
/* "release" it. */
|
||||
/* */
|
||||
/* Similarly, the returned @FT_Size object is always owned by the */
|
||||
/* manager. You should never try to discard it, and never change its */
|
||||
/* settings with @FT_Set_Pixel_Sizes or @FT_Set_Char_Size! */
|
||||
/* */
|
||||
/* The returned size object is the face's current size, which means */
|
||||
/* that you can call @FT_Load_Glyph with the face if you need to. */
|
||||
/* If "anode" is NULL, the cache node is left unchanged, which means */
|
||||
/* that the FT_Glyph could be flushed out of the cache on the next */
|
||||
/* call to one of the caching sub-system APIs. Don't assume that it */
|
||||
/* is persistent! */
|
||||
/* */
|
||||
FT_EXPORT( FT_Error )
|
||||
FTC_Manager_Lookup_Size( FTC_Manager manager,
|
||||
FTC_Font font,
|
||||
FT_Face *aface,
|
||||
FT_Size *asize );
|
||||
FTC_ImageCache_Lookup( FTC_ImageCache cache,
|
||||
FTC_ImageType type,
|
||||
FT_UInt gindex,
|
||||
FT_Glyph *aglyph,
|
||||
FTC_Node *anode );
|
||||
|
||||
/*************************************************************************/
|
||||
/* */
|
||||
/* <Section> */
|
||||
/* cache_subsystem */
|
||||
/* */
|
||||
/*************************************************************************/
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/* */
|
||||
/* <Type> */
|
||||
/* FTC_SBit */
|
||||
/* */
|
||||
/* <Description> */
|
||||
/* A handle to a small bitmap descriptor. See the @FTC_SBitRec */
|
||||
/* structure for details. */
|
||||
/* */
|
||||
typedef struct FTC_SBitRec_* FTC_SBit;
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/* */
|
||||
/* <Struct> */
|
||||
/* FTC_SBitRec */
|
||||
/* */
|
||||
/* <Description> */
|
||||
/* A very compact structure used to describe a small glyph bitmap. */
|
||||
/* */
|
||||
/* <Fields> */
|
||||
/* width :: The bitmap width in pixels. */
|
||||
/* */
|
||||
/* height :: The bitmap height in pixels. */
|
||||
/* */
|
||||
/* left :: The horizontal distance from the pen position to the */
|
||||
/* left bitmap border (a.k.a. `left side bearing', or */
|
||||
/* `lsb'). */
|
||||
/* */
|
||||
/* top :: The vertical distance from the pen position (on the */
|
||||
/* baseline) to the upper bitmap border (a.k.a. `top */
|
||||
/* side bearing'). The distance is positive for upwards */
|
||||
/* Y coordinates. */
|
||||
/* */
|
||||
/* format :: The format of the glyph bitmap (monochrome or gray). */
|
||||
/* */
|
||||
/* max_grays :: Maximum gray level value (in the range 1 to 255). */
|
||||
/* */
|
||||
/* pitch :: The number of bytes per bitmap line. May be positive */
|
||||
/* or negative. */
|
||||
/* */
|
||||
/* xadvance :: The horizontal advance width in pixels. */
|
||||
/* */
|
||||
/* yadvance :: The vertical advance height in pixels. */
|
||||
/* */
|
||||
/* buffer :: A pointer to the bitmap pixels. */
|
||||
/* */
|
||||
typedef struct FTC_SBitRec_
|
||||
{
|
||||
FT_Byte width;
|
||||
FT_Byte height;
|
||||
FT_Char left;
|
||||
FT_Char top;
|
||||
|
||||
FT_Byte format;
|
||||
FT_Byte max_grays;
|
||||
FT_Short pitch;
|
||||
FT_Char xadvance;
|
||||
FT_Char yadvance;
|
||||
|
||||
FT_Byte* buffer;
|
||||
|
||||
} FTC_SBitRec;
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/* */
|
||||
/* <Type> */
|
||||
/* FTC_SBitCache */
|
||||
/* */
|
||||
/* <Description> */
|
||||
/* A handle to a small bitmap cache. These are special cache objects */
|
||||
/* used to store small glyph bitmaps (and anti-aliased pixmaps) in a */
|
||||
/* much more efficient way than the traditional glyph image cache */
|
||||
/* implemented by @FTC_ImageCache. */
|
||||
/* */
|
||||
typedef struct FTC_SBitCacheRec_* FTC_SBitCache;
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/* */
|
||||
/* <Function> */
|
||||
/* FTC_SBitCache_New */
|
||||
/* */
|
||||
/* <Description> */
|
||||
/* Creates a new cache to store small glyph bitmaps. */
|
||||
/* */
|
||||
/* <Input> */
|
||||
/* manager :: A handle to the source cache manager. */
|
||||
/* */
|
||||
/* <Output> */
|
||||
/* acache :: A handle to the new sbit cache. NULL in case of error. */
|
||||
/* */
|
||||
/* <Return> */
|
||||
/* FreeType error code. 0 means success. */
|
||||
/* */
|
||||
FT_EXPORT( FT_Error )
|
||||
FTC_SBitCache_New( FTC_Manager manager,
|
||||
FTC_SBitCache *acache );
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/* */
|
||||
/* <Function> */
|
||||
/* FTC_SBitCache_Lookup */
|
||||
/* */
|
||||
/* <Description> */
|
||||
/* Looks up a given small glyph bitmap in a given sbit cache and */
|
||||
/* "lock" it to prevent its flushing from the cache until needed */
|
||||
/* */
|
||||
/* <Input> */
|
||||
/* cache :: A handle to the source sbit cache. */
|
||||
/* */
|
||||
/* type :: A pointer to the glyph image type descriptor. */
|
||||
/* */
|
||||
/* gindex :: The glyph index. */
|
||||
/* */
|
||||
/* <Output> */
|
||||
/* sbit :: A handle to a small bitmap descriptor. */
|
||||
/* */
|
||||
/* anode :: Used to return the address of of the corresponding cache */
|
||||
/* node after incrementing its reference count (see note */
|
||||
/* below). */
|
||||
/* */
|
||||
/* <Return> */
|
||||
/* FreeType error code. 0 means success. */
|
||||
/* */
|
||||
/* <Note> */
|
||||
/* The small bitmap descriptor and its bit buffer are owned by the */
|
||||
/* cache and should never be freed by the application. They might */
|
||||
/* as well disappear from memory on the next cache lookup, so don't */
|
||||
/* treat them as persistent data. */
|
||||
/* */
|
||||
/* The descriptor's `buffer' field is set to 0 to indicate a missing */
|
||||
/* glyph bitmap. */
|
||||
/* */
|
||||
/* If "anode" is _not_ NULL, it receives the address of the cache */
|
||||
/* node containing the bitmap, after increasing its reference count. */
|
||||
/* This ensures that the node (as well as the image) will always be */
|
||||
/* kept in the cache until you call @FTC_Node_Unref to "release" it. */
|
||||
/* */
|
||||
/* If "anode" is NULL, the cache node is left unchanged, which means */
|
||||
/* that the bitmap could be flushed out of the cache on the next */
|
||||
/* call to one of the caching sub-system APIs. Don't assume that it */
|
||||
/* is persistent! */
|
||||
/* */
|
||||
FT_EXPORT( FT_Error )
|
||||
FTC_SBitCache_Lookup( FTC_SBitCache cache,
|
||||
FTC_ImageType type,
|
||||
FT_UInt gindex,
|
||||
FTC_SBit *sbit,
|
||||
FTC_Node *anode );
|
||||
|
||||
|
||||
/* */
|
||||
|
||||
FT_END_HEADER
|
||||
|
||||
|
@ -95,12 +95,113 @@ FT_BEGIN_HEADER
|
||||
|
||||
} FT_Stroker_LineCap;
|
||||
|
||||
/* */
|
||||
|
||||
/**************************************************************
|
||||
*
|
||||
* @enum: FT_StrokerBorder
|
||||
*
|
||||
* @description:
|
||||
* theses values are used to select a given stroke border
|
||||
* in @FT_Stroker_GetBorderCounts and @FT_Stroker_ExportBorder
|
||||
*
|
||||
* @values:
|
||||
* FT_STROKER_BORDER_LEFT ::
|
||||
* select the left border, relative to the drawing direction
|
||||
*
|
||||
* FT_STROKER_BORDER_RIGHT ::
|
||||
* select the right border, relative to the drawing direction
|
||||
*
|
||||
* @note:
|
||||
* applications are generally interested in the "inside" and "outside"
|
||||
* borders. However, there is no direct mapping between these and
|
||||
* the "left" / "right" ones, since this really depends on the glyph's
|
||||
* drawing orientation, which varies between font formats
|
||||
*
|
||||
* you can however use @FT_Outline_GetInsideBorder and
|
||||
* @FT_Outline_GetOutsideBorder to get these.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
FT_STROKER_BORDER_LEFT = 0,
|
||||
FT_STROKER_BORDER_RIGHT
|
||||
|
||||
} FT_StrokerBorder;
|
||||
|
||||
|
||||
/**************************************************************
|
||||
*
|
||||
* @function: FT_Outline_GetInsideBorder
|
||||
*
|
||||
* @description:
|
||||
* retrieve the @FT_StrokerBorder value corresponding to the
|
||||
* "inside" borders of a given outline
|
||||
*
|
||||
* @input:
|
||||
* outline :: source outline handle
|
||||
*
|
||||
* @return:
|
||||
* border index. @FT_STROKER_BORDER_LEFT for empty or invalid outlines
|
||||
*/
|
||||
FT_EXPORT( FT_StrokerBorder )
|
||||
FT_Outline_GetInsideBorder( FT_Outline* outline );
|
||||
|
||||
|
||||
/**************************************************************
|
||||
*
|
||||
* @function: FT_Outline_GetOutsideBorder
|
||||
*
|
||||
* @description:
|
||||
* retrieve the @FT_StrokerBorder value corresponding to the
|
||||
* "outside" borders of a given outline
|
||||
*
|
||||
* @input:
|
||||
* outline :: source outline handle
|
||||
*
|
||||
* @return:
|
||||
* border index. @FT_STROKER_BORDER_LEFT for empty or invalid outlines
|
||||
*/
|
||||
FT_EXPORT( FT_StrokerBorder )
|
||||
FT_Outline_GetOutsideBorder( FT_Outline* outline );
|
||||
|
||||
|
||||
/**************************************************************
|
||||
*
|
||||
* @function: FT_Stroker_New
|
||||
*
|
||||
* @description:
|
||||
* create a new stroker object
|
||||
*
|
||||
* @input:
|
||||
* memory :: memory manager handle
|
||||
*
|
||||
* @output:
|
||||
* new stroker object handle, NULL in case of error
|
||||
*
|
||||
* @return:
|
||||
* error code. 0 means success
|
||||
*/
|
||||
FT_EXPORT( FT_Error )
|
||||
FT_Stroker_New( FT_Memory memory,
|
||||
FT_Stroker *astroker );
|
||||
|
||||
|
||||
/**************************************************************
|
||||
*
|
||||
* @function: FT_Stroker_Set
|
||||
*
|
||||
* @description:
|
||||
* reset a stroker object's attributes
|
||||
*
|
||||
* @input:
|
||||
* stroker :: target stroker handle
|
||||
* radius :: border radius
|
||||
* line_cap :: line cap style
|
||||
* line_join :: line join style
|
||||
* miter_limit :: miter limit for the FT_STROKER_LINEJOIN_MITER style,
|
||||
* expressed as 16.16 fixed point value.
|
||||
* @note:
|
||||
* the radius is expressed in the same units that the outline coordinates.
|
||||
*/
|
||||
FT_EXPORT( void )
|
||||
FT_Stroker_Set( FT_Stroker stroker,
|
||||
FT_Fixed radius,
|
||||
@ -109,29 +210,152 @@ FT_BEGIN_HEADER
|
||||
FT_Fixed miter_limit );
|
||||
|
||||
|
||||
/**************************************************************
|
||||
*
|
||||
* @function: FT_Stroker_ParseOutline
|
||||
*
|
||||
* @description:
|
||||
* a convenient function used to parse a whole outline with
|
||||
* the stroker. The resulting outline(s) can be retrieved
|
||||
* later by functions like @FT_Stroker_GetCounts and @FT_Stroker_Export
|
||||
*
|
||||
* @input:
|
||||
* stroker :: target stroker handle
|
||||
* outline :: source outline
|
||||
* opened :: boolean. if TRUE, the outline is treated as an open path,
|
||||
* instead of a closed one
|
||||
*
|
||||
* @return:*
|
||||
* error code. 0 means success
|
||||
*
|
||||
* @note:
|
||||
* if 'opened' is 0 (the default), the outline is treated as a closed path,
|
||||
* and the stroker will generate two distinct "border" outlines
|
||||
*
|
||||
* if 'opened' is 1, the outline is processed as an open path, and the
|
||||
* stroker will generate a single "stroke" outline
|
||||
*/
|
||||
FT_EXPORT( FT_Error )
|
||||
FT_Stroker_ParseOutline( FT_Stroker stroker,
|
||||
FT_Outline* outline,
|
||||
FT_Bool opened );
|
||||
|
||||
/**************************************************************
|
||||
*
|
||||
* @function: FT_Stroker_BeginSubPath
|
||||
*
|
||||
* @description:
|
||||
* start a new sub-path in the stroker
|
||||
*
|
||||
* @input:
|
||||
* stroker :: target stroker handle
|
||||
* to :: pointer to start vector
|
||||
* open :: boolean. if TRUE, the sub-path is treated as an open
|
||||
* one
|
||||
*
|
||||
* @return:*
|
||||
* error code. 0 means success
|
||||
*
|
||||
* @note:
|
||||
* this function is useful when you need to stroke a path that is
|
||||
* not stored as a @FT_Outline object
|
||||
*/
|
||||
FT_EXPORT( FT_Error )
|
||||
FT_Stroker_BeginSubPath( FT_Stroker stroker,
|
||||
FT_Vector* to,
|
||||
FT_Bool open );
|
||||
|
||||
/**************************************************************
|
||||
*
|
||||
* @function: FT_Stroker_EndSubPath
|
||||
*
|
||||
* @description:
|
||||
* close the current sub-path in the stroker
|
||||
*
|
||||
* @input:
|
||||
* stroker :: target stroker handle
|
||||
*
|
||||
* @return:
|
||||
* error code. 0 means success
|
||||
*
|
||||
* @note:
|
||||
* you should call this function after @FT_Stroker_BeginSubPath.
|
||||
* if the subpath was not "opened", this function will "draw" a
|
||||
* single line segment to the start position when needed.
|
||||
*/
|
||||
FT_EXPORT( FT_Error )
|
||||
FT_Stroker_EndSubPath( FT_Stroker stroker );
|
||||
|
||||
|
||||
/**************************************************************
|
||||
*
|
||||
* @function: FT_Stroker_LineTo
|
||||
*
|
||||
* @description:
|
||||
* "draw" a single line segment in the stroker's current sub-path,
|
||||
* from the last position
|
||||
*
|
||||
* @input:
|
||||
* stroker :: target stroker handle
|
||||
* to :: pointer to destination point
|
||||
*
|
||||
* @return:
|
||||
* error code. 0 means success
|
||||
*
|
||||
* @note:
|
||||
* you should call this function between @FT_Stroker_BeginSubPath and
|
||||
* @FT_Stroker_EndSubPath
|
||||
*/
|
||||
FT_EXPORT( FT_Error )
|
||||
FT_Stroker_LineTo( FT_Stroker stroker,
|
||||
FT_Vector* to );
|
||||
|
||||
/**************************************************************
|
||||
*
|
||||
* @function: FT_Stroker_ConicTo
|
||||
*
|
||||
* @description:
|
||||
* "draw" a single quadratic bezier in the stroker's current sub-path,
|
||||
* from the last position
|
||||
*
|
||||
* @input:
|
||||
* stroker :: target stroker handle
|
||||
* control :: pointer to bezier control point
|
||||
* to :: pointer to destination point
|
||||
*
|
||||
* @return:
|
||||
* error code. 0 means success
|
||||
*
|
||||
* @note:
|
||||
* you should call this function between @FT_Stroker_BeginSubPath and
|
||||
* @FT_Stroker_EndSubPath
|
||||
*/
|
||||
FT_EXPORT( FT_Error )
|
||||
FT_Stroker_ConicTo( FT_Stroker stroker,
|
||||
FT_Vector* control,
|
||||
FT_Vector* to );
|
||||
|
||||
/**************************************************************
|
||||
*
|
||||
* @function: FT_Stroker_CubicTo
|
||||
*
|
||||
* @description:
|
||||
* "draw" a single cubic bezier in the stroker's current sub-path,
|
||||
* from the last position
|
||||
*
|
||||
* @input:
|
||||
* stroker :: target stroker handle
|
||||
* control1 :: pointer to first bezier control point
|
||||
* control2 :: pointer to second bezier control point
|
||||
* to :: pointer to destination point
|
||||
*
|
||||
* @return:
|
||||
* error code. 0 means success
|
||||
*
|
||||
* @note:
|
||||
* you should call this function between @FT_Stroker_BeginSubPath and
|
||||
* @FT_Stroker_EndSubPath
|
||||
*/
|
||||
FT_EXPORT( FT_Error )
|
||||
FT_Stroker_CubicTo( FT_Stroker stroker,
|
||||
FT_Vector* control1,
|
||||
@ -139,18 +363,166 @@ FT_BEGIN_HEADER
|
||||
FT_Vector* to );
|
||||
|
||||
|
||||
/**************************************************************
|
||||
*
|
||||
* @function: FT_Stroker_GetBorderCounts
|
||||
*
|
||||
* @description:
|
||||
* call this function once you finished parsing your paths
|
||||
* with the stroker. It will return the number of points and
|
||||
* contours necessary to export one of the "border" or "stroke"
|
||||
* outlines generated by the stroker.
|
||||
*
|
||||
* @input:
|
||||
* stroker :: target stroker handle
|
||||
* border :: border index
|
||||
*
|
||||
* @output:
|
||||
* anum_points :: number of points
|
||||
* anum_contours :: number of contours
|
||||
*
|
||||
* @return:
|
||||
* error code. 0 means success
|
||||
*
|
||||
* @note:
|
||||
* when an outline, or a sub-path, is "closed", the stroker generates
|
||||
* two independent 'border' outlines, named 'left' and 'right'
|
||||
*
|
||||
* when the outline, or a sub-path, is "opened", the stroker merges
|
||||
* the 'border' outlines with caps. The 'left' border receives all
|
||||
* points, while the 'right' border becomes empty.
|
||||
*
|
||||
* use the function @FT_Stroker_GetCounts instead if you want to
|
||||
* retrieve the counts associated to both borders.
|
||||
*/
|
||||
FT_EXPORT( FT_Error )
|
||||
FT_Stroker_GetBorderCounts( FT_Stroker stroker,
|
||||
FT_StrokerBorder border,
|
||||
FT_UInt *anum_points,
|
||||
FT_UInt *anum_contours );
|
||||
|
||||
/**************************************************************
|
||||
*
|
||||
* @function: FT_Stroker_ExportBorder
|
||||
*
|
||||
* @description:
|
||||
* call this function after @FT_Stroker_GetBorderCounts to
|
||||
* export the corresponding border to your own @FT_Outline
|
||||
* structure.
|
||||
*
|
||||
* note that this function will append the border points and
|
||||
* contours to your outline, but will not try to resize its
|
||||
* arrays.
|
||||
*
|
||||
* @input:
|
||||
* stroker :: target stroker handle
|
||||
* border :: border index
|
||||
* outline :: target outline handle
|
||||
*
|
||||
* @return:
|
||||
* error code. 0 means success
|
||||
*
|
||||
* @note:
|
||||
* always call this function after @FT_Stroker_GetBorderCounts to
|
||||
* get sure that there is enough room in your @FT_Outline object to
|
||||
* receive all new data.
|
||||
*
|
||||
* when an outline, or a sub-path, is "closed", the stroker generates
|
||||
* two independent 'border' outlines, named 'left' and 'right'
|
||||
*
|
||||
* when the outline, or a sub-path, is "opened", the stroker merges
|
||||
* the 'border' outlines with caps. The 'left' border receives all
|
||||
* points, while the 'right' border becomes empty.
|
||||
*
|
||||
* use the function @FT_Stroker_Export instead if you want to
|
||||
* retrieve all borders at once
|
||||
*/
|
||||
FT_EXPORT( void )
|
||||
FT_Stroker_ExportBorder( FT_Stroker stroker,
|
||||
FT_StrokerBorder border,
|
||||
FT_Outline* outline );
|
||||
|
||||
/**************************************************************
|
||||
*
|
||||
* @function: FT_Stroker_GetCounts
|
||||
*
|
||||
* @description:
|
||||
* call this function once you finished parsing your paths
|
||||
* with the stroker. It will return the number of points and
|
||||
* contours necessary to export all points/borders from the stroked
|
||||
* outline/path.
|
||||
*
|
||||
* @input:
|
||||
* stroker :: target stroker handle
|
||||
*
|
||||
* @output:
|
||||
* anum_points :: number of points
|
||||
* anum_contours :: number of contours
|
||||
*
|
||||
* @return:
|
||||
* error code. 0 means success
|
||||
*
|
||||
* @note:
|
||||
*/
|
||||
FT_EXPORT( FT_Error )
|
||||
FT_Stroker_GetCounts( FT_Stroker stroker,
|
||||
FT_UInt *anum_points,
|
||||
FT_UInt *anum_contours );
|
||||
|
||||
/**************************************************************
|
||||
*
|
||||
* @function: FT_Stroker_ExportBorder
|
||||
*
|
||||
* @description:
|
||||
* call this function after @FT_Stroker_GetBorderCounts to
|
||||
* export the corresponding border to your own @FT_Outline
|
||||
* structure.
|
||||
*
|
||||
* note that this function will append the border points and
|
||||
* contours to your outline, but will not try to resize its
|
||||
* arrays.
|
||||
*
|
||||
* @input:
|
||||
* stroker :: target stroker handle
|
||||
* border :: border index
|
||||
* outline :: target outline handle
|
||||
*
|
||||
* @return:
|
||||
* error code. 0 means success
|
||||
*
|
||||
* @note:
|
||||
* always call this function after @FT_Stroker_GetBorderCounts to
|
||||
* get sure that there is enough room in your @FT_Outline object to
|
||||
* receive all new data.
|
||||
*
|
||||
* when an outline, or a sub-path, is "closed", the stroker generates
|
||||
* two independent 'border' outlines, named 'left' and 'right'
|
||||
*
|
||||
* when the outline, or a sub-path, is "opened", the stroker merges
|
||||
* the 'border' outlines with caps. The 'left' border receives all
|
||||
* points, while the 'right' border becomes empty.
|
||||
*
|
||||
* use the function @FT_Stroker_Export instead if you want to
|
||||
* retrieve all borders at once
|
||||
*/
|
||||
FT_EXPORT( void )
|
||||
FT_Stroker_Export( FT_Stroker stroker,
|
||||
FT_Outline* outline );
|
||||
|
||||
/**************************************************************
|
||||
*
|
||||
* @function: FT_Stroker_Done
|
||||
*
|
||||
* @description:
|
||||
* destroy a stroker object
|
||||
*
|
||||
* @input:
|
||||
* stroker :: stroker handle. can be NULL
|
||||
*/
|
||||
FT_EXPORT( void )
|
||||
FT_Stroker_Done( FT_Stroker stroker );
|
||||
|
||||
/* */
|
||||
|
||||
FT_END_HEADER
|
||||
|
||||
|
@ -399,14 +399,14 @@
|
||||
|
||||
hints->x_scale = x_scale;
|
||||
hints->y_scale = y_scale;
|
||||
hints->x_delta = x_delta;
|
||||
hints->y_delta = y_delta;
|
||||
|
||||
points = hints->points;
|
||||
if ( hints->num_points == 0 )
|
||||
goto Exit;
|
||||
|
||||
{
|
||||
/* do one thing at a time -- it is easier to understand, and */
|
||||
/* the code is clearer */
|
||||
AF_Point point;
|
||||
AF_Point point_limit = points + hints->num_points;
|
||||
|
||||
|
@ -163,7 +163,11 @@ FT_BEGIN_HEADER
|
||||
FT_Memory memory;
|
||||
|
||||
FT_Fixed x_scale;
|
||||
FT_Pos x_delta;
|
||||
|
||||
FT_Fixed y_scale;
|
||||
FT_Pos y_delta;
|
||||
|
||||
FT_Pos edge_distance_threshold;
|
||||
|
||||
FT_Int max_points;
|
||||
|
@ -20,10 +20,7 @@
|
||||
metrics->axis[ AF_DIMENSION_HORZ ].width_count = 0;
|
||||
metrics->axis[ AF_DIMENSION_VERT ].width_count = 0;
|
||||
|
||||
/* For now, compute the standard width and height from the `o' */
|
||||
/* character. I started computing the stem width of the `i' and the */
|
||||
/* stem height of the "-", but it wasn't too good. Moreover, we now */
|
||||
/* have a single character that gives us standard width and height. */
|
||||
/* For now, compute the standard width and height from the `o' */
|
||||
{
|
||||
FT_UInt glyph_index;
|
||||
AF_Dimension dim;
|
||||
|
@ -40,14 +40,14 @@ FT_BEGIN_HEADER
|
||||
FT_Pos org; /* original position/width in font units */
|
||||
FT_Pos cur; /* current/scaled position/width in device sub-pixels */
|
||||
FT_Pos fit; /* current/fitted position/width in device sub-pixels */
|
||||
|
||||
|
||||
} AF_WidthRec, *AF_Width;
|
||||
|
||||
|
||||
|
||||
AF_LOCAL( void )
|
||||
af_sort_pos( FT_UInt count,
|
||||
FT_Pos* table );
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/***** *****/
|
||||
@ -55,11 +55,11 @@ FT_BEGIN_HEADER
|
||||
/***** *****/
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/*
|
||||
* Angle type. The auto-fitter doesn't need a very high angular accuracy,
|
||||
* and this allows us to speed up some computations considerably with a
|
||||
* light Cordic algorithm (see afangle.c)
|
||||
* light Cordic algorithm (see afangles.c)
|
||||
*
|
||||
*/
|
||||
|
||||
@ -111,10 +111,10 @@ FT_BEGIN_HEADER
|
||||
FT_Face face;
|
||||
FT_OutlineRec outline;
|
||||
FT_UInt outline_resolution;
|
||||
|
||||
|
||||
FT_Int advance;
|
||||
FT_UInt metrics_resolution;
|
||||
|
||||
|
||||
AF_GlyphHints hints;
|
||||
|
||||
} AF_OutlineRec;
|
||||
@ -133,7 +133,7 @@ FT_BEGIN_HEADER
|
||||
* auto-hinted glyph image
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
typedef enum
|
||||
{
|
||||
AF_SCALER_FLAG_NO_HORIZONTAL = 1, /* disable horizontal hinting */
|
||||
@ -152,7 +152,7 @@ FT_BEGIN_HEADER
|
||||
FT_Pos y_delta; /* in 1/64th device pixels */
|
||||
FT_Render_Mode render_mode; /* monochrome, anti-aliased, LCD, etc.. */
|
||||
FT_UInt32 flags; /* additionnal control flags, see above */
|
||||
|
||||
|
||||
} AF_ScalerRec, *AF_Scaler;
|
||||
|
||||
|
||||
@ -169,7 +169,7 @@ FT_BEGIN_HEADER
|
||||
* the list of know scripts. Each different script correspond to the
|
||||
* following information:
|
||||
*
|
||||
* - a set of Unicode ranges to test wether the face supports the
|
||||
* - a set of Unicode ranges to test weither the face supports the
|
||||
* script
|
||||
*
|
||||
* - a specific global analyzer that will compute global metrics
|
||||
@ -189,9 +189,9 @@ FT_BEGIN_HEADER
|
||||
{
|
||||
AF_SCRIPT_LATIN = 0,
|
||||
/* add new scripts here. don't forget to update the list in "afglobal.c" */
|
||||
|
||||
|
||||
AF_SCRIPT_MAX /* do not remove */
|
||||
|
||||
|
||||
} AF_Script;
|
||||
|
||||
|
||||
@ -207,7 +207,7 @@ FT_BEGIN_HEADER
|
||||
|
||||
/* this function parses a FT_Face to compute global metrics for
|
||||
* a specific script
|
||||
*/
|
||||
*/
|
||||
typedef FT_Error (*AF_Script_InitMetricsFunc)( AF_ScriptMetrics metrics,
|
||||
FT_Face face );
|
||||
|
||||
@ -230,9 +230,9 @@ FT_BEGIN_HEADER
|
||||
{
|
||||
FT_UInt32 first;
|
||||
FT_UInt32 last;
|
||||
|
||||
|
||||
} AF_Script_UniRangeRec, *AF_Script_UniRange;
|
||||
|
||||
|
||||
|
||||
typedef struct AF_ScriptClassRec_
|
||||
{
|
||||
|
@ -19,10 +19,31 @@
|
||||
#include <ft2build.h>
|
||||
#include FT_STROKER_H
|
||||
#include FT_TRIGONOMETRY_H
|
||||
#include FT_OUTLINE_H
|
||||
#include FT_INTERNAL_MEMORY_H
|
||||
#include FT_INTERNAL_DEBUG_H
|
||||
|
||||
|
||||
FT_EXPORT_DEF( FT_StrokerBorder )
|
||||
FT_Outline_GetInsideBorder( FT_Outline* outline )
|
||||
{
|
||||
FT_Orientation or = FT_Outline_Get_Orientation( outline );
|
||||
|
||||
return ( or == FT_ORIENTATION_TRUETYPE ) ? FT_STROKER_BORDER_RIGHT
|
||||
: FT_STROKER_BORDER_LEFT ;
|
||||
}
|
||||
|
||||
|
||||
FT_EXPORT_DEF( FT_StrokerBorder )
|
||||
FT_Outline_GetOutsideBorder( FT_Outline* outline )
|
||||
{
|
||||
FT_Orientation or = FT_Outline_Get_Orientation( outline );
|
||||
|
||||
return ( or == FT_ORIENTATION_TRUETYPE ) ? FT_STROKER_BORDER_RIGHT
|
||||
: FT_STROKER_BORDER_LEFT ;
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************/
|
||||
/***************************************************************************/
|
||||
/***** *****/
|
||||
@ -221,6 +242,7 @@
|
||||
FT_Bool movable;
|
||||
FT_Int start; /* index of current sub-path start point */
|
||||
FT_Memory memory;
|
||||
FT_Bool valid;
|
||||
|
||||
} FT_StrokeBorderRec, *FT_StrokeBorder;
|
||||
|
||||
@ -468,6 +490,7 @@
|
||||
border->num_points = 0;
|
||||
border->max_points = 0;
|
||||
border->start = -1;
|
||||
border->valid = 0;
|
||||
}
|
||||
|
||||
|
||||
@ -476,6 +499,7 @@
|
||||
{
|
||||
border->num_points = 0;
|
||||
border->start = -1;
|
||||
border->valid = 0;
|
||||
}
|
||||
|
||||
|
||||
@ -491,6 +515,7 @@
|
||||
border->num_points = 0;
|
||||
border->max_points = 0;
|
||||
border->start = -1;
|
||||
border->valid = 0;
|
||||
}
|
||||
|
||||
|
||||
@ -520,7 +545,7 @@
|
||||
}
|
||||
else if ( in_contour == 0 )
|
||||
goto Fail;
|
||||
|
||||
|
||||
if ( tags[0] & FT_STROKE_TAG_END )
|
||||
{
|
||||
if ( in_contour == 0 )
|
||||
@ -534,6 +559,8 @@
|
||||
if ( in_contour != 0 )
|
||||
goto Fail;
|
||||
|
||||
border->valid = 1;
|
||||
|
||||
Exit:
|
||||
*anum_points = num_points;
|
||||
*anum_contours = num_contours;
|
||||
@ -661,8 +688,6 @@
|
||||
stroker->line_join = line_join;
|
||||
stroker->miter_limit = miter_limit;
|
||||
|
||||
stroker->valid = 0;
|
||||
|
||||
ft_stroke_border_reset( &stroker->borders[0] );
|
||||
ft_stroke_border_reset( &stroker->borders[1] );
|
||||
}
|
||||
@ -1423,6 +1448,34 @@
|
||||
}
|
||||
|
||||
|
||||
FT_EXPORT_DEF( FT_Error )
|
||||
FT_Stroker_GetBorderCounts( FT_Stroker stroker,
|
||||
FT_StrokerBorder border,
|
||||
FT_UInt *anum_points,
|
||||
FT_UInt *anum_contours )
|
||||
{
|
||||
FT_UInt num_points = 0, num_contours = 0;
|
||||
FT_Error error;
|
||||
|
||||
if ( !stroker || border > 1 )
|
||||
{
|
||||
error = FT_Err_Invalid_Argument;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
error = ft_stroke_border_get_counts( stroker->borders + border,
|
||||
&num_points, &num_contours );
|
||||
Exit:
|
||||
if ( anum_points )
|
||||
*anum_points = num_points;
|
||||
|
||||
if ( anum_contours )
|
||||
*anum_contours = num_contours;
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
FT_EXPORT_DEF( FT_Error )
|
||||
FT_Stroker_GetCounts( FT_Stroker stroker,
|
||||
FT_UInt *anum_points,
|
||||
@ -1446,8 +1499,6 @@
|
||||
num_points = count1 + count3;
|
||||
num_contours = count2 + count4;
|
||||
|
||||
stroker->valid = 1;
|
||||
|
||||
Exit:
|
||||
*anum_points = num_points;
|
||||
*anum_contours = num_contours;
|
||||
@ -1455,18 +1506,33 @@
|
||||
}
|
||||
|
||||
|
||||
FT_EXPORT_DEF( void )
|
||||
FT_Stroker_ExportBorder( FT_Stroker stroker,
|
||||
FT_StrokerBorder border,
|
||||
FT_Outline* outline )
|
||||
{
|
||||
if ( border == FT_STROKER_BORDER_LEFT ||
|
||||
border == FT_STROKER_BORDER_RIGHT )
|
||||
{
|
||||
FT_StrokeBorder sborder = & stroker->borders[border];
|
||||
|
||||
if ( sborder->valid )
|
||||
ft_stroke_border_export( sborder, outline );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
FT_EXPORT_DEF( void )
|
||||
FT_Stroker_Export( FT_Stroker stroker,
|
||||
FT_Outline* outline )
|
||||
{
|
||||
if ( stroker->valid )
|
||||
{
|
||||
ft_stroke_border_export( stroker->borders + 0, outline );
|
||||
ft_stroke_border_export( stroker->borders + 1, outline );
|
||||
}
|
||||
FT_Stroker_ExportBorder( stroker, FT_STROKER_BORDER_LEFT, outline );
|
||||
FT_Stroker_ExportBorder( stroker, FT_STROKER_BORDER_RIGHT, outline );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* The following is very similar to FT_Outline_Decompose, except
|
||||
* that we do support opened paths, and do not scale the outline.
|
||||
|
10
src/cache/Jamfile
vendored
10
src/cache/Jamfile
vendored
@ -14,7 +14,15 @@ HDRMACRO [ FT2_SubDir include ftcache.h ] ;
|
||||
|
||||
if $(FT2_MULTI)
|
||||
{
|
||||
_sources = ftlru ftcmanag ftccache ftcglyph ftcsbits ftcimage ftccmap ;
|
||||
_sources = ftmru
|
||||
ftcmanag
|
||||
ftccache
|
||||
ftcglyph
|
||||
ftcsbits
|
||||
ftcimage
|
||||
ftcbasic
|
||||
ftccmap
|
||||
;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
6
src/cache/ftcache.c
vendored
6
src/cache/ftcache.c
vendored
@ -19,13 +19,13 @@
|
||||
#define FT_MAKE_OPTION_SINGLE_OBJECT
|
||||
|
||||
#include <ft2build.h>
|
||||
#include "ftlru.c"
|
||||
#include "ftcmru.c"
|
||||
#include "ftcmanag.c"
|
||||
#include "ftccache.c"
|
||||
#include "ftccmap.c"
|
||||
#include "ftcglyph.c"
|
||||
#include "ftcimage.c"
|
||||
#include "ftcsbits.c"
|
||||
#include "ftccmap.c"
|
||||
|
||||
#include "ftcbasic.c"
|
||||
|
||||
/* END */
|
||||
|
380
src/cache/ftcbasic.c
vendored
Normal file
380
src/cache/ftcbasic.c
vendored
Normal file
@ -0,0 +1,380 @@
|
||||
#include <ft2build.h>
|
||||
#include FT_CACHE_H
|
||||
#include FT_CACHE_INTERNAL_GLYPH_H
|
||||
#include FT_CACHE_INTERNAL_IMAGE_H
|
||||
#include FT_CACHE_INTERNAL_SBITS_H
|
||||
#include FT_INTERNAL_MEMORY_H
|
||||
|
||||
#include "ftcerror.h"
|
||||
|
||||
|
||||
/*
|
||||
* Basic Families
|
||||
*
|
||||
*
|
||||
*/
|
||||
typedef struct FTC_BasicAttrRec_
|
||||
{
|
||||
FTC_ScalerRec scaler;
|
||||
FT_UInt load_flags;
|
||||
|
||||
} FTC_BasicAttrRec, *FTC_BasicAttrs;
|
||||
|
||||
#define FTC_BASIC_ATTR_COMPARE(a,b) \
|
||||
( FTC_SCALER_COMPARE( &(a)->scaler, &(b)->scaler ) && \
|
||||
(a)->load_flags == (b)->load_flags )
|
||||
|
||||
#define FTC_BASIC_ATTR_HASH(a) \
|
||||
( FTC_SCALER_HASH(&(a)->scaler) + 31*(a)->load_flags )
|
||||
|
||||
|
||||
typedef struct FTC_BasicQueryRec_
|
||||
{
|
||||
FTC_GQueryRec gquery;
|
||||
FTC_BasicAttrRec attrs;
|
||||
|
||||
} FTC_BasicQueryRec, *FTC_BasicQuery;
|
||||
|
||||
|
||||
|
||||
typedef struct FTC_BasicFamilyRec_
|
||||
{
|
||||
FTC_FamilyRec family;
|
||||
FTC_BasicAttrRec attrs;
|
||||
|
||||
} FTC_BasicFamilyRec, *FTC_BasicFamily;
|
||||
|
||||
|
||||
static FT_Bool
|
||||
ftc_basic_family_compare( FTC_BasicFamily family,
|
||||
FTC_BasicQuery query )
|
||||
{
|
||||
return FT_BOOL( FTC_BASIC_ATTR_COMPARE( &family->attrs, &query->attrs ) );
|
||||
}
|
||||
|
||||
static FT_Error
|
||||
ftc_basic_family_init( FTC_BasicFamily family,
|
||||
FTC_BasicQuery query,
|
||||
FTC_Cache cache )
|
||||
{
|
||||
ftc_family_init( FTC_FAMILY( family ), cache );
|
||||
family->attrs = query->attrs;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static FT_Error
|
||||
ftc_basic_family_reset( FTC_BasicFamily family,
|
||||
FTC_BasicQuery query )
|
||||
{
|
||||
family->attrs = query->attrs;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static FT_Bool
|
||||
ftc_basic_gnode_compare_faceid( FTC_GNode gnode,
|
||||
FTC_FaceID face_id,
|
||||
FTC_Cache cache )
|
||||
{
|
||||
FTC_BasicFamily family = (FTC_BasicFamily) gnode->family;
|
||||
FT_Bool result;
|
||||
|
||||
result = FT_BOOL( family->attrs.scaler.face_id == face_id );
|
||||
if ( result )
|
||||
{
|
||||
/* we must call this function to avoid this node from appearing
|
||||
* in later lookups with the same face_id !!
|
||||
*/
|
||||
FTC_GNode_UnselectFamily( gnode, cache );
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
static FT_UInt
|
||||
ftc_basic_family_get_count( FTC_BasicFamily family,
|
||||
FTC_Manager manager )
|
||||
{
|
||||
FT_Error error;
|
||||
FT_Face face;
|
||||
FT_UInt result = 0;
|
||||
|
||||
error = FTC_Manager_LookupFace( manager, &family->attrs.scaler.face_id,
|
||||
&face );
|
||||
if ( !error )
|
||||
result = face->num_glyphs;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
static FT_Error
|
||||
ftc_basic_family_load_bitmap( FTC_BasicFamily family,
|
||||
FT_UInt gindex,
|
||||
FTC_Manager manager,
|
||||
FT_Face *aface )
|
||||
{
|
||||
FT_Error error;
|
||||
FT_Size size;
|
||||
|
||||
error = FTC_Manager_LookupSize( manager, &family->attrs.scaler, &size );
|
||||
if ( !error )
|
||||
{
|
||||
FT_Face face = size->face;
|
||||
|
||||
error = FT_Load_Glyph( face, gindex, family->attrs.load_flags |
|
||||
FT_LOAD_RENDER );
|
||||
if ( !error )
|
||||
*aface = face;
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
static FT_Error
|
||||
ftc_basic_family_load_glyph( FTC_BasicFamily family,
|
||||
FT_UInt gindex,
|
||||
FTC_Cache cache,
|
||||
FT_Glyph *aglyph )
|
||||
{
|
||||
FT_Error error;
|
||||
FTC_Scaler scaler = &family->attrs.scaler;
|
||||
FT_Face face;
|
||||
FT_Size size;
|
||||
|
||||
/* we will now load the glyph image */
|
||||
error = FTC_Manager_LookupSize( cache->manager,
|
||||
scaler,
|
||||
&size );
|
||||
if ( !error )
|
||||
{
|
||||
face = size->face;
|
||||
|
||||
error = FT_Load_Glyph( face, gindex, family->attrs.load_flags );
|
||||
if ( !error )
|
||||
{
|
||||
if ( face->glyph->format == FT_GLYPH_FORMAT_BITMAP ||
|
||||
face->glyph->format == FT_GLYPH_FORMAT_OUTLINE )
|
||||
{
|
||||
/* ok, copy it */
|
||||
FT_Glyph glyph;
|
||||
|
||||
|
||||
error = FT_Get_Glyph( face->glyph, &glyph );
|
||||
if ( !error )
|
||||
{
|
||||
*aglyph = glyph;
|
||||
goto Exit;
|
||||
}
|
||||
}
|
||||
else
|
||||
error = FTC_Err_Invalid_Argument;
|
||||
}
|
||||
}
|
||||
Exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* basic image cache
|
||||
*
|
||||
*/
|
||||
|
||||
static const FTC_IFamilyClassRec ftc_basic_image_family_class =
|
||||
{
|
||||
{
|
||||
sizeof( FTC_BasicFamilyRec ),
|
||||
(FTC_MruNode_CompareFunc) ftc_basic_family_compare,
|
||||
(FTC_MruNode_InitFunc) ftc_basic_family_init,
|
||||
(FTC_MruNode_ResetFunc) ftc_basic_family_reset,
|
||||
(FTC_MruNode_DoneFunc) NULL
|
||||
},
|
||||
(FTC_IFamily_LoadGlyphFunc) ftc_basic_family_load_glyph
|
||||
};
|
||||
|
||||
|
||||
|
||||
static const FTC_GCacheClassRec ftc_basic_image_cache_class =
|
||||
{
|
||||
{
|
||||
(FTC_Node_NewFunc) FTC_INode_New,
|
||||
(FTC_Node_WeightFunc) FTC_INode_Weight,
|
||||
(FTC_Node_CompareFunc) FTC_GNode_Compare,
|
||||
(FTC_Node_CompareFunc) ftc_basic_gnode_compare_faceid,
|
||||
(FTC_Node_FreeFunc) FTC_INode_Free,
|
||||
|
||||
sizeof( FTC_GCacheRec ),
|
||||
(FTC_Cache_InitFunc) FTC_GCache_Init,
|
||||
(FTC_Cache_DoneFunc) FTC_GCache_Done
|
||||
},
|
||||
(FTC_MruListClass) & ftc_basic_image_family_class
|
||||
};
|
||||
|
||||
|
||||
FT_EXPORT_DEF( FT_Error )
|
||||
FTC_ImageCache_New( FTC_Manager manager,
|
||||
FTC_ImageCache *acache )
|
||||
{
|
||||
return FTC_GCache_New( manager, & ftc_basic_image_cache_class,
|
||||
(FTC_GCache*) acache );
|
||||
}
|
||||
|
||||
|
||||
/* documentation is in ftcimage.h */
|
||||
|
||||
FT_EXPORT_DEF( FT_Error )
|
||||
FTC_ImageCache_Lookup( FTC_ImageCache cache,
|
||||
FTC_ImageType type,
|
||||
FT_UInt gindex,
|
||||
FT_Glyph *aglyph,
|
||||
FTC_Node *anode )
|
||||
{
|
||||
FTC_BasicQueryRec query;
|
||||
FTC_INode node;
|
||||
FT_Error error;
|
||||
FT_UInt32 hash;
|
||||
|
||||
|
||||
/* some argument checks are delayed to FTC_Cache_Lookup */
|
||||
if ( !aglyph )
|
||||
{
|
||||
error = FTC_Err_Invalid_Argument;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
*aglyph = NULL;
|
||||
if ( anode )
|
||||
*anode = NULL;
|
||||
|
||||
query.attrs.scaler.face_id = type->face_id;
|
||||
query.attrs.scaler.width = type->width;
|
||||
query.attrs.scaler.height = type->height;
|
||||
query.attrs.scaler.pixel = 1;
|
||||
query.attrs.load_flags = type->flags;
|
||||
|
||||
hash = FTC_BASIC_ATTR_HASH( &query.attrs ) ^ (gindex << 8);
|
||||
|
||||
error = FTC_GCache_Lookup( FTC_GCACHE( cache ),
|
||||
hash, gindex,
|
||||
FTC_GQUERY( &query ),
|
||||
(FTC_Node*) &node );
|
||||
if ( !error )
|
||||
{
|
||||
*aglyph = FTC_INODE(node)->glyph;
|
||||
|
||||
if ( anode )
|
||||
{
|
||||
*anode = FTC_NODE(node);
|
||||
FTC_NODE(node)->ref_count++;
|
||||
}
|
||||
}
|
||||
|
||||
Exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* basic small bitmap cache
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
static const FTC_SFamilyClassRec ftc_basic_sbit_family_class =
|
||||
{
|
||||
{
|
||||
sizeof( FTC_BasicFamilyRec ),
|
||||
(FTC_MruNode_CompareFunc) ftc_basic_family_compare,
|
||||
(FTC_MruNode_InitFunc) ftc_basic_family_init,
|
||||
(FTC_MruNode_ResetFunc) ftc_basic_family_reset,
|
||||
(FTC_MruNode_DoneFunc) NULL
|
||||
},
|
||||
(FTC_SFamily_GetCountFunc) ftc_basic_family_get_count,
|
||||
(FTC_SFamily_LoadGlyphFunc) ftc_basic_family_load_bitmap
|
||||
};
|
||||
|
||||
|
||||
static const FTC_GCacheClassRec ftc_basic_sbit_cache_class =
|
||||
{
|
||||
{
|
||||
(FTC_Node_NewFunc) FTC_SNode_New,
|
||||
(FTC_Node_WeightFunc) FTC_SNode_Weight,
|
||||
(FTC_Node_CompareFunc) FTC_SNode_Compare,
|
||||
(FTC_Node_CompareFunc) ftc_basic_gnode_compare_faceid,
|
||||
(FTC_Node_FreeFunc) FTC_SNode_Free,
|
||||
|
||||
sizeof( FTC_GCacheRec ),
|
||||
(FTC_Cache_InitFunc) FTC_GCache_Init,
|
||||
(FTC_Cache_DoneFunc) FTC_GCache_Done
|
||||
},
|
||||
(FTC_MruListClass) & ftc_basic_sbit_family_class
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
FT_EXPORT_DEF( FT_Error )
|
||||
FTC_SBitCache_New( FTC_Manager manager,
|
||||
FTC_SBitCache *acache )
|
||||
{
|
||||
return FTC_GCache_New( manager, & ftc_basic_sbit_cache_class,
|
||||
(FTC_GCache*) acache );
|
||||
}
|
||||
|
||||
|
||||
FT_EXPORT_DEF( FT_Error )
|
||||
FTC_SBitCache_Lookup( FTC_SBitCache cache,
|
||||
FTC_ImageType type,
|
||||
FT_UInt gindex,
|
||||
FTC_SBit *ansbit,
|
||||
FTC_Node *anode )
|
||||
{
|
||||
FT_Error error;
|
||||
FTC_BasicQueryRec query;
|
||||
FTC_SNode node;
|
||||
FT_UInt32 hash;
|
||||
|
||||
if ( anode )
|
||||
*anode = NULL;
|
||||
|
||||
/* other argument checks delayed to FTC_Cache_Lookup */
|
||||
if ( !ansbit )
|
||||
return FTC_Err_Invalid_Argument;
|
||||
|
||||
*ansbit = NULL;
|
||||
|
||||
query.attrs.scaler.face_id = type->face_id;
|
||||
query.attrs.scaler.width = type->width;
|
||||
query.attrs.scaler.height = type->height;
|
||||
query.attrs.scaler.pixel = 1;
|
||||
query.attrs.load_flags = type->flags;
|
||||
|
||||
/* beware, the hash must be the same for all glyph ranges !!
|
||||
*/
|
||||
hash = FTC_BASIC_ATTR_HASH( &query.attrs ) ^
|
||||
(gindex/FTC_SBIT_ITEMS_PER_NODE);
|
||||
|
||||
error = FTC_GCache_Lookup( FTC_GCACHE( cache ),
|
||||
hash,
|
||||
gindex,
|
||||
FTC_GQUERY( &query ),
|
||||
(FTC_Node*) &node );
|
||||
if ( error )
|
||||
goto Exit;
|
||||
|
||||
*ansbit = node->sbits + ( gindex - FTC_GNODE(node)->gindex );
|
||||
|
||||
if ( anode )
|
||||
{
|
||||
*anode = FTC_NODE( node );
|
||||
FTC_NODE( node )->ref_count++;
|
||||
}
|
||||
|
||||
Exit:
|
||||
return error;
|
||||
}
|
||||
|
816
src/cache/ftccache.c
vendored
816
src/cache/ftccache.c
vendored
@ -17,7 +17,7 @@
|
||||
|
||||
|
||||
#include <ft2build.h>
|
||||
#include FT_CACHE_MANAGER_H
|
||||
#include FT_CACHE_INTERNAL_MANAGER_H
|
||||
#include FT_INTERNAL_OBJECTS_H
|
||||
#include FT_INTERNAL_DEBUG_H
|
||||
|
||||
@ -40,23 +40,6 @@
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
FT_EXPORT_DEF( void )
|
||||
ftc_node_done( FTC_Node node,
|
||||
FTC_Cache cache )
|
||||
{
|
||||
FTC_Family family;
|
||||
FTC_FamilyEntry entry;
|
||||
|
||||
|
||||
entry = cache->manager->families.entries + node->fam_index;
|
||||
family = entry->family;
|
||||
|
||||
/* remove from parent set table - eventually destroy the set */
|
||||
if ( --family->num_nodes == 0 )
|
||||
FT_LruList_Remove( cache->families, (FT_LruNode) family );
|
||||
}
|
||||
|
||||
|
||||
/* add a new node to the head of the manager's circular MRU list */
|
||||
static void
|
||||
ftc_node_mru_link( FTC_Node node,
|
||||
@ -152,96 +135,158 @@
|
||||
}
|
||||
|
||||
|
||||
/* note that this function cannot fail. If we cannot re-size the
|
||||
* buckets array appropriately, we simply degrade the hash table's
|
||||
* performance !!
|
||||
*/
|
||||
static void
|
||||
ftc_cache_resize( FTC_Cache cache )
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
FTC_Node node, *pnode;
|
||||
FT_UInt p = cache->p;
|
||||
FT_UInt mask = cache->mask;
|
||||
FT_UInt count = mask + p + 1; /* number of buckets */
|
||||
|
||||
/* do we need to shrink the buckets array ?
|
||||
*/
|
||||
if ( cache->slack < 0 )
|
||||
{
|
||||
FTC_Node new_list = NULL;
|
||||
|
||||
/* try to expand the buckets array _before_ splitting
|
||||
* the bucket lists
|
||||
*/
|
||||
if ( p >= mask )
|
||||
{
|
||||
FT_Memory memory = cache->memory;
|
||||
|
||||
/* if we can't expand the array, leave immediately */
|
||||
if ( FT_MEM_RENEW_ARRAY( cache->buckets, (mask+1)*2, (mask+1)*4 ) )
|
||||
break;
|
||||
}
|
||||
|
||||
/* split a single bucket */
|
||||
pnode = cache->buckets + p;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
node = *pnode;
|
||||
if ( node == NULL )
|
||||
break;
|
||||
|
||||
if ( node->hash & ( mask + 1 ) )
|
||||
{
|
||||
*pnode = node->link;
|
||||
node->link = new_list;
|
||||
new_list = node;
|
||||
}
|
||||
else
|
||||
pnode = &node->link;
|
||||
}
|
||||
|
||||
cache->buckets[p + mask + 1] = new_list;
|
||||
|
||||
cache->slack += FTC_HASH_MAX_LOAD;
|
||||
|
||||
if ( p >= mask )
|
||||
{
|
||||
cache->mask = 2 * mask + 1;
|
||||
cache->p = 0;
|
||||
}
|
||||
else
|
||||
cache->p = p + 1;
|
||||
}
|
||||
/* do we need to expand the buckets array ?
|
||||
*/
|
||||
else if ( cache->slack > (FT_Long)count * FTC_HASH_SUB_LOAD )
|
||||
{
|
||||
FT_UInt old_index = p + mask;
|
||||
FTC_Node* pold;
|
||||
|
||||
if ( old_index + 1 <= FTC_HASH_INITIAL_SIZE )
|
||||
break;
|
||||
|
||||
if ( p == 0 )
|
||||
{
|
||||
FT_Memory memory = cache->memory;
|
||||
|
||||
/* if we can't shrink the array, leave immediately */
|
||||
if ( FT_MEM_RENEW_ARRAY( cache->buckets, ( mask + 1 ) * 2, (mask+1) ) )
|
||||
break;
|
||||
|
||||
cache->mask >>= 1;
|
||||
p = cache->mask;
|
||||
}
|
||||
else
|
||||
p--;
|
||||
|
||||
pnode = cache->buckets + p;
|
||||
while ( *pnode )
|
||||
pnode = &(*pnode)->link;
|
||||
|
||||
pold = cache->buckets + old_index;
|
||||
*pnode = *pold;
|
||||
*pold = NULL;
|
||||
|
||||
cache->slack -= FTC_HASH_MAX_LOAD;
|
||||
cache->p = p;
|
||||
}
|
||||
else /* the hash table is balanced */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* remove a node from its cache's hash table */
|
||||
static FT_Error
|
||||
ftc_node_hash_unlink( FTC_Node node,
|
||||
static void
|
||||
ftc_node_hash_unlink( FTC_Node node0,
|
||||
FTC_Cache cache )
|
||||
{
|
||||
FT_Error error = 0;
|
||||
FTC_Node *pnode;
|
||||
FT_UInt idx, num_buckets;
|
||||
FT_UInt idx;
|
||||
|
||||
|
||||
idx = (FT_UInt)( node->hash & cache->mask );
|
||||
idx = (FT_UInt)( node0->hash & cache->mask );
|
||||
if ( idx < cache->p )
|
||||
idx = (FT_UInt)( node->hash & ( 2 * cache->mask + 1 ) );
|
||||
idx = (FT_UInt)( node0->hash & ( 2 * cache->mask + 1 ) );
|
||||
|
||||
pnode = cache->buckets + idx;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if ( *pnode == NULL )
|
||||
FTC_Node node = *pnode;
|
||||
|
||||
if ( node == NULL )
|
||||
{
|
||||
FT_ERROR(( "ftc_node_hash_unlink: unknown node!\n" ));
|
||||
return FTC_Err_Ok;
|
||||
return;
|
||||
}
|
||||
|
||||
if ( *pnode == node )
|
||||
{
|
||||
*pnode = node->link;
|
||||
node->link = NULL;
|
||||
if ( node == node0 )
|
||||
break;
|
||||
}
|
||||
|
||||
pnode = &(*pnode)->link;
|
||||
}
|
||||
|
||||
num_buckets = ( cache->p + cache->mask + 1 );
|
||||
*pnode = node0->link;
|
||||
node0->link = NULL;
|
||||
|
||||
if ( ++cache->slack > (FT_Long)num_buckets * FTC_HASH_SUB_LOAD )
|
||||
{
|
||||
FT_UInt p = cache->p;
|
||||
FT_UInt mask = cache->mask;
|
||||
FT_UInt old_index = p + mask;
|
||||
FTC_Node* pold;
|
||||
|
||||
|
||||
if ( old_index + 1 <= FTC_HASH_INITIAL_SIZE )
|
||||
goto Exit;
|
||||
|
||||
if ( p == 0 )
|
||||
{
|
||||
FT_Memory memory = cache->memory;
|
||||
|
||||
|
||||
cache->mask >>= 1;
|
||||
p = cache->mask;
|
||||
|
||||
if ( FT_RENEW_ARRAY( cache->buckets, ( mask + 1 ) * 2, (mask+1) ) )
|
||||
{
|
||||
FT_ERROR(( "ftc_node_hash_unlink: couldn't shunk buckets!\n" ));
|
||||
goto Exit;
|
||||
}
|
||||
}
|
||||
else
|
||||
p--;
|
||||
|
||||
pnode = cache->buckets + p;
|
||||
while ( *pnode )
|
||||
pnode = &(*pnode)->link;
|
||||
|
||||
pold = cache->buckets + old_index;
|
||||
*pnode = *pold;
|
||||
*pold = NULL;
|
||||
|
||||
cache->slack -= FTC_HASH_MAX_LOAD;
|
||||
cache->p = p;
|
||||
}
|
||||
|
||||
Exit:
|
||||
return error;
|
||||
cache->slack++;
|
||||
ftc_cache_resize( cache );
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* add a node to the "top" of its cache's hash table */
|
||||
static FT_Error
|
||||
static void
|
||||
ftc_node_hash_link( FTC_Node node,
|
||||
FTC_Cache cache )
|
||||
{
|
||||
FTC_Node *pnode;
|
||||
FT_UInt idx;
|
||||
FT_Error error = 0;
|
||||
|
||||
|
||||
idx = (FT_UInt)( node->hash & cache->mask );
|
||||
@ -253,58 +298,8 @@
|
||||
node->link = *pnode;
|
||||
*pnode = node;
|
||||
|
||||
if ( --cache->slack < 0 )
|
||||
{
|
||||
FT_UInt p = cache->p;
|
||||
FT_UInt mask = cache->mask;
|
||||
FTC_Node new_list;
|
||||
|
||||
|
||||
/* split a single bucket */
|
||||
new_list = NULL;
|
||||
pnode = cache->buckets + p;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
node = *pnode;
|
||||
if ( node == NULL )
|
||||
break;
|
||||
|
||||
if ( node->hash & ( mask + 1 ) )
|
||||
{
|
||||
*pnode = node->link;
|
||||
node->link = new_list;
|
||||
new_list = node;
|
||||
}
|
||||
else
|
||||
pnode = &node->link;
|
||||
}
|
||||
|
||||
cache->buckets[p + mask + 1] = new_list;
|
||||
|
||||
cache->slack += FTC_HASH_MAX_LOAD;
|
||||
|
||||
if ( p >= mask )
|
||||
{
|
||||
FT_Memory memory = cache->memory;
|
||||
|
||||
|
||||
if ( FT_RENEW_ARRAY( cache->buckets,
|
||||
( mask + 1 ) * 2, ( mask + 1 ) * 4 ) )
|
||||
{
|
||||
FT_ERROR(( "ftc_node_hash_link: couldn't expand buckets!\n" ));
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
cache->mask = 2 * mask + 1;
|
||||
cache->p = 0;
|
||||
}
|
||||
else
|
||||
cache->p = p + 1;
|
||||
}
|
||||
|
||||
Exit:
|
||||
return error;
|
||||
cache->slack--;
|
||||
ftc_cache_resize( cache );
|
||||
}
|
||||
|
||||
|
||||
@ -315,23 +310,19 @@
|
||||
ftc_node_destroy( FTC_Node node,
|
||||
FTC_Manager manager )
|
||||
{
|
||||
FT_Memory memory = manager->library->memory;
|
||||
FTC_Cache cache;
|
||||
FTC_FamilyEntry entry;
|
||||
FTC_Cache_Class clazz;
|
||||
FTC_Cache cache;
|
||||
|
||||
|
||||
#ifdef FT_DEBUG_ERROR
|
||||
/* find node's cache */
|
||||
if ( node->fam_index >= manager->families.count )
|
||||
if ( node->cache_index >= manager->num_caches )
|
||||
{
|
||||
FT_ERROR(( "ftc_node_destroy: invalid node handle\n" ));
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
entry = manager->families.entries + node->fam_index;
|
||||
cache = entry->cache;
|
||||
cache = manager->caches[ node->cache_index ];
|
||||
|
||||
#ifdef FT_DEBUG_ERROR
|
||||
if ( cache == NULL )
|
||||
@ -341,9 +332,7 @@
|
||||
}
|
||||
#endif
|
||||
|
||||
clazz = cache->clazz;
|
||||
|
||||
manager->cur_weight -= clazz->node_weight( node, cache );
|
||||
manager->cur_weight -= cache->clazz.node_weight( node, cache );
|
||||
|
||||
/* remove node from mru list */
|
||||
ftc_node_mru_unlink( node, manager );
|
||||
@ -352,10 +341,7 @@
|
||||
ftc_node_hash_unlink( node, cache );
|
||||
|
||||
/* now finalize it */
|
||||
if ( clazz->node_done )
|
||||
clazz->node_done( node, cache );
|
||||
|
||||
FT_FREE( node );
|
||||
cache->clazz.node_free( node, cache );
|
||||
|
||||
#if 0
|
||||
/* check, just in case of general corruption :-) */
|
||||
@ -366,58 +352,6 @@
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/***** *****/
|
||||
/***** CACHE FAMILY DEFINITIONS *****/
|
||||
/***** *****/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
|
||||
FT_EXPORT_DEF( FT_Error )
|
||||
ftc_family_init( FTC_Family family,
|
||||
FTC_Query query,
|
||||
FTC_Cache cache )
|
||||
{
|
||||
FT_Error error;
|
||||
FTC_Manager manager = cache->manager;
|
||||
FT_Memory memory = manager->library->memory;
|
||||
FTC_FamilyEntry entry;
|
||||
|
||||
|
||||
family->cache = cache;
|
||||
family->num_nodes = 0;
|
||||
|
||||
/* now add to manager's family table */
|
||||
error = ftc_family_table_alloc( &manager->families, memory, &entry );
|
||||
if ( !error )
|
||||
{
|
||||
entry->cache = cache;
|
||||
entry->family = family;
|
||||
family->fam_index = entry->index;
|
||||
|
||||
query->family = family; /* save family in query */
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
FT_EXPORT_DEF( void )
|
||||
ftc_family_done( FTC_Family family )
|
||||
{
|
||||
if ( family && family->cache )
|
||||
{
|
||||
FTC_Manager manager = family->cache->manager;
|
||||
|
||||
|
||||
/* remove from manager's family table */
|
||||
ftc_family_table_free( &manager->families, family->fam_index );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/***** *****/
|
||||
@ -427,62 +361,28 @@
|
||||
/*************************************************************************/
|
||||
|
||||
|
||||
|
||||
FT_EXPORT_DEF( FT_Error )
|
||||
ftc_cache_init( FTC_Cache cache )
|
||||
FT_EXPORT( FT_Error )
|
||||
FTC_Cache_Init( FTC_Cache cache )
|
||||
{
|
||||
FT_Memory memory = cache->memory;
|
||||
FTC_Cache_Class clazz = cache->clazz;
|
||||
FT_Error error;
|
||||
FT_Memory memory = cache->memory;
|
||||
|
||||
cache->p = 0;
|
||||
cache->mask = FTC_HASH_INITIAL_SIZE - 1;
|
||||
cache->slack = FTC_HASH_INITIAL_SIZE * FTC_HASH_MAX_LOAD;
|
||||
|
||||
cache->p = 0;
|
||||
cache->mask = FTC_HASH_INITIAL_SIZE - 1;
|
||||
cache->slack = FTC_HASH_INITIAL_SIZE * FTC_HASH_MAX_LOAD;
|
||||
|
||||
if ( FT_NEW_ARRAY( cache->buckets, FTC_HASH_INITIAL_SIZE * 2 ) )
|
||||
goto Exit;
|
||||
|
||||
/* now, initialize the lru list of families for this cache */
|
||||
if ( clazz->family_size > 0 )
|
||||
{
|
||||
FT_LruList_ClassRec* lru_class = &cache->family_class;
|
||||
|
||||
|
||||
lru_class->list_size = sizeof( FT_LruListRec );
|
||||
lru_class->list_init = NULL;
|
||||
lru_class->list_done = NULL;
|
||||
|
||||
lru_class->node_size = clazz->family_size;
|
||||
lru_class->node_init = (FT_LruNode_InitFunc) clazz->family_init;
|
||||
lru_class->node_done = (FT_LruNode_DoneFunc) clazz->family_done;
|
||||
lru_class->node_flush = (FT_LruNode_FlushFunc) NULL;
|
||||
lru_class->node_compare = (FT_LruNode_CompareFunc)clazz->family_compare;
|
||||
|
||||
error = FT_LruList_New( (FT_LruList_Class) lru_class,
|
||||
0, /* max items == 0 => unbounded list */
|
||||
cache,
|
||||
memory,
|
||||
&cache->families );
|
||||
if ( error )
|
||||
FT_FREE( cache->buckets );
|
||||
}
|
||||
|
||||
Exit:
|
||||
return error;
|
||||
return ( FT_MEM_NEW_ARRAY( cache->buckets, FTC_HASH_INITIAL_SIZE * 2 ) );
|
||||
}
|
||||
|
||||
|
||||
|
||||
FT_EXPORT_DEF( void )
|
||||
ftc_cache_clear( FTC_Cache cache )
|
||||
FTC_Cache_Clear( FTC_Cache cache )
|
||||
{
|
||||
if ( cache )
|
||||
{
|
||||
FT_Memory memory = cache->memory;
|
||||
FTC_Cache_Class clazz = cache->clazz;
|
||||
FTC_Manager manager = cache->manager;
|
||||
FT_UFast i;
|
||||
FT_UInt count;
|
||||
FTC_Manager manager = cache->manager;
|
||||
FT_UFast i;
|
||||
FT_UInt count;
|
||||
|
||||
count = cache->p + cache->mask + 1;
|
||||
|
||||
@ -500,310 +400,228 @@
|
||||
ftc_node_mru_unlink( node, manager );
|
||||
|
||||
/* now finalize it */
|
||||
manager->cur_weight -= clazz->node_weight( node, cache );
|
||||
manager->cur_weight -= cache->clazz.node_weight( node, cache );
|
||||
|
||||
if ( clazz->node_done )
|
||||
clazz->node_done( node, cache );
|
||||
|
||||
FT_FREE( node );
|
||||
cache->clazz.node_free( node, cache );
|
||||
node = next;
|
||||
}
|
||||
cache->buckets[i] = NULL;
|
||||
}
|
||||
|
||||
cache->p = 0;
|
||||
|
||||
/* destroy the families */
|
||||
if ( cache->families )
|
||||
FT_LruList_Reset( cache->families );
|
||||
ftc_cache_resize( cache );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
FT_EXPORT_DEF( void )
|
||||
ftc_cache_done( FTC_Cache cache )
|
||||
FT_EXPORT( void )
|
||||
FTC_Cache_Done( FTC_Cache cache )
|
||||
{
|
||||
if ( cache )
|
||||
if ( cache->memory )
|
||||
{
|
||||
FT_Memory memory = cache->memory;
|
||||
|
||||
|
||||
ftc_cache_clear( cache );
|
||||
FTC_Cache_Clear( cache );
|
||||
|
||||
FT_FREE( cache->buckets );
|
||||
cache->mask = 0;
|
||||
cache->p = 0;
|
||||
cache->slack = 0;
|
||||
|
||||
if ( cache->families )
|
||||
cache->memory = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
ftc_cache_add( FTC_Cache cache,
|
||||
FT_UInt32 hash,
|
||||
FTC_Node node )
|
||||
{
|
||||
node->hash = hash;
|
||||
|
||||
ftc_node_hash_link( node, cache );
|
||||
ftc_node_mru_link( node, cache->manager );
|
||||
|
||||
{
|
||||
FTC_Manager manager = cache->manager;
|
||||
|
||||
manager->cur_weight += cache->clazz.node_weight( node, cache );
|
||||
|
||||
if ( manager->cur_weight >= manager->max_weight )
|
||||
{
|
||||
FT_LruList_Destroy( cache->families );
|
||||
cache->families = NULL;
|
||||
node->ref_count++;
|
||||
FTC_Manager_Compress( manager );
|
||||
node->ref_count--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Look up a node in "top" of its cache's hash table. */
|
||||
/* If not found, create a new node. */
|
||||
/* */
|
||||
FT_EXPORT_DEF( FT_Error )
|
||||
ftc_cache_lookup( FTC_Cache cache,
|
||||
FTC_Query query,
|
||||
FT_EXPORT( FT_Error )
|
||||
FTC_Cache_Lookup( FTC_Cache cache,
|
||||
FT_UInt32 hash,
|
||||
FT_Pointer query,
|
||||
FTC_Node *anode )
|
||||
{
|
||||
FT_Error error = FTC_Err_Ok;
|
||||
FTC_Manager manager;
|
||||
FT_LruNode lru;
|
||||
FT_UInt free_count = 0;
|
||||
FT_UFast idx;
|
||||
FTC_Node* bucket;
|
||||
FTC_Node* pnode;
|
||||
FTC_Node node;
|
||||
FT_Error error = 0;
|
||||
|
||||
FTC_Node_CompareFunc compare = cache->clazz.node_compare;
|
||||
|
||||
|
||||
if ( !cache || !query || !anode )
|
||||
return FTC_Err_Invalid_Argument;
|
||||
if ( cache == NULL || anode == NULL )
|
||||
return FT_Err_Invalid_Argument;
|
||||
|
||||
*anode = NULL;
|
||||
|
||||
query->hash = 0;
|
||||
query->family = NULL;
|
||||
|
||||
manager = cache->manager;
|
||||
|
||||
/* here's a small note explaining what's happening in the code below.
|
||||
*
|
||||
* We need to deal intelligently with out-of-memory (OOM) conditions
|
||||
* when trying to create a new family or cache node during the lookup.
|
||||
*
|
||||
* When an OOM is detected, we try to free one or more "old" nodes
|
||||
* from the cache, then try again. It may be necessary to do that
|
||||
* several times, so a loop is needed.
|
||||
*
|
||||
* The local variable "free_count" holds the number of "old" nodes to
|
||||
* discard on each attempt. It starts at 1 and doubles on each
|
||||
* iteration. The loop stops when:
|
||||
*
|
||||
* - a non-OOM error is detected
|
||||
* - a succesful lookup is performed
|
||||
* - there are no more unused nodes in the cache
|
||||
*
|
||||
* For the record, remember that all used nodes appear _before_
|
||||
* unused ones in the manager's MRU node list.
|
||||
*/
|
||||
idx = hash & cache->mask;
|
||||
if ( idx < cache->p )
|
||||
idx = hash & ( cache->mask * 2 + 1 );
|
||||
|
||||
bucket = cache->buckets + idx;
|
||||
pnode = bucket;
|
||||
for (;;)
|
||||
{
|
||||
node = *pnode;
|
||||
if ( node == NULL )
|
||||
goto NewNode;
|
||||
|
||||
if ( node->hash == hash && compare( node, query, cache ) )
|
||||
break;
|
||||
|
||||
pnode = &node->link;
|
||||
}
|
||||
|
||||
if ( node != *bucket )
|
||||
{
|
||||
*pnode = node->link;
|
||||
node->link = *bucket;
|
||||
*bucket = node;
|
||||
}
|
||||
|
||||
/* move to head of MRU list */
|
||||
{
|
||||
FTC_Manager manager = cache->manager;
|
||||
|
||||
if ( node != manager->nodes_list )
|
||||
ftc_node_mru_up( node, manager );
|
||||
}
|
||||
goto Exit;
|
||||
|
||||
NewNode:
|
||||
|
||||
/*
|
||||
* try to allocate a new cache node. Note that in case of
|
||||
* out-of-memory error (OOM), we'll flush the cache a bit,
|
||||
* then try again.
|
||||
*
|
||||
* on each try, the "tries" variable gives the number
|
||||
* of old nodes we want to flush from the manager's global list
|
||||
* before the next allocation attempt. it barely doubles on
|
||||
* each iteration
|
||||
*
|
||||
*/
|
||||
error = cache->clazz.node_new( &node, query, cache );
|
||||
if ( !error )
|
||||
goto AddNode;
|
||||
|
||||
node = NULL;
|
||||
if ( error != FT_Err_Out_Of_Memory )
|
||||
goto Exit;
|
||||
|
||||
{
|
||||
FTC_Manager manager = cache->manager;
|
||||
FT_UInt count, tries = 1;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
/* first of all, find the relevant family */
|
||||
FT_LruList list = cache->families;
|
||||
FT_LruNode fam, *pfam;
|
||||
FT_LruNode_CompareFunc compare = list->clazz->node_compare;
|
||||
error = cache->clazz.node_new( &node, query, cache );
|
||||
if ( !error )
|
||||
break;
|
||||
|
||||
pfam = &list->nodes;
|
||||
for (;;)
|
||||
{
|
||||
fam = *pfam;
|
||||
if ( fam == NULL )
|
||||
{
|
||||
error = FT_LruList_Lookup( list, query, &lru );
|
||||
if ( error )
|
||||
goto Fail;
|
||||
|
||||
goto Skip;
|
||||
}
|
||||
|
||||
if ( compare( fam, query, list->data ) )
|
||||
break;
|
||||
|
||||
pfam = &fam->next;
|
||||
}
|
||||
|
||||
FT_ASSERT( fam != NULL );
|
||||
|
||||
/* move to top of list when needed */
|
||||
if ( fam != list->nodes )
|
||||
{
|
||||
*pfam = fam->next;
|
||||
fam->next = list->nodes;
|
||||
list->nodes = fam;
|
||||
}
|
||||
|
||||
lru = fam;
|
||||
|
||||
Skip:
|
||||
;
|
||||
}
|
||||
|
||||
{
|
||||
FTC_Family family = (FTC_Family) lru;
|
||||
FT_UFast hash = query->hash;
|
||||
FTC_Node* bucket;
|
||||
FT_UInt idx;
|
||||
|
||||
|
||||
idx = hash & cache->mask;
|
||||
if ( idx < cache->p )
|
||||
idx = hash & ( cache->mask * 2 + 1 );
|
||||
|
||||
bucket = cache->buckets + idx;
|
||||
|
||||
|
||||
if ( query->family != family ||
|
||||
family->fam_index >= manager->families.size )
|
||||
{
|
||||
FT_ERROR((
|
||||
"ftc_cache_lookup: invalid query (bad 'family' field)\n" ));
|
||||
error = FTC_Err_Invalid_Argument;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
if ( *bucket )
|
||||
{
|
||||
FTC_Node* pnode = bucket;
|
||||
FTC_Node_CompareFunc compare = cache->clazz->node_compare;
|
||||
|
||||
|
||||
for ( ;; )
|
||||
{
|
||||
FTC_Node node;
|
||||
|
||||
|
||||
node = *pnode;
|
||||
if ( node == NULL )
|
||||
break;
|
||||
|
||||
if ( node->hash == hash &&
|
||||
(FT_UInt)node->fam_index == family->fam_index &&
|
||||
compare( node, query, cache ) )
|
||||
{
|
||||
/* move to head of bucket list */
|
||||
if ( pnode != bucket )
|
||||
{
|
||||
*pnode = node->link;
|
||||
node->link = *bucket;
|
||||
*bucket = node;
|
||||
}
|
||||
|
||||
/* move to head of MRU list */
|
||||
if ( node != manager->nodes_list )
|
||||
ftc_node_mru_up( node, manager );
|
||||
|
||||
*anode = node;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
pnode = &node->link;
|
||||
}
|
||||
}
|
||||
|
||||
/* didn't find a node, create a new one */
|
||||
{
|
||||
FTC_Cache_Class clazz = cache->clazz;
|
||||
FT_Memory memory = cache->memory;
|
||||
FTC_Node node;
|
||||
|
||||
|
||||
if ( FT_ALLOC( node, clazz->node_size ) )
|
||||
goto Fail;
|
||||
|
||||
node->fam_index = (FT_UShort) family->fam_index;
|
||||
node->hash = query->hash;
|
||||
node->ref_count = 0;
|
||||
|
||||
error = clazz->node_init( node, query, cache );
|
||||
if ( error )
|
||||
{
|
||||
FT_FREE( node );
|
||||
goto Fail;
|
||||
}
|
||||
|
||||
error = ftc_node_hash_link( node, cache );
|
||||
if ( error )
|
||||
{
|
||||
clazz->node_done( node, cache );
|
||||
FT_FREE( node );
|
||||
goto Fail;
|
||||
}
|
||||
|
||||
ftc_node_mru_link( node, cache->manager );
|
||||
|
||||
cache->manager->cur_weight += clazz->node_weight( node, cache );
|
||||
|
||||
/* now try to compress the node pool when necessary */
|
||||
if ( manager->cur_weight >= manager->max_weight )
|
||||
{
|
||||
node->ref_count++;
|
||||
FTC_Manager_Compress( manager );
|
||||
node->ref_count--;
|
||||
}
|
||||
|
||||
*anode = node;
|
||||
}
|
||||
|
||||
/* all is well, exit now
|
||||
*/
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
Fail:
|
||||
if ( error != FTC_Err_Out_Of_Memory )
|
||||
goto Exit;
|
||||
|
||||
/* There is not enough memory; try to release some unused nodes
|
||||
* from the cache to make room for a new one.
|
||||
*/
|
||||
{
|
||||
FT_UInt new_count;
|
||||
|
||||
|
||||
new_count = 1 + free_count * 2;
|
||||
|
||||
/* check overflow and bounds */
|
||||
if ( new_count < free_count || free_count > manager->num_nodes )
|
||||
node = NULL;
|
||||
if ( error != FT_Err_Out_Of_Memory )
|
||||
goto Exit;
|
||||
|
||||
free_count = new_count;
|
||||
count = FTC_Manager_FlushN( manager, tries );
|
||||
if ( count == 0 )
|
||||
goto Exit;
|
||||
|
||||
/* try to remove "new_count" nodes from the list */
|
||||
if ( count == tries )
|
||||
{
|
||||
FTC_Node first = manager->nodes_list;
|
||||
FTC_Node node;
|
||||
|
||||
|
||||
if ( first == NULL ) /* empty list! */
|
||||
goto Exit;
|
||||
|
||||
/* go to last node - it's a circular list */
|
||||
node = first->mru_prev;
|
||||
for ( ; node && new_count > 0; new_count-- )
|
||||
{
|
||||
FTC_Node prev = node->mru_prev;
|
||||
|
||||
|
||||
/* Used nodes always appear before unused one in the MRU
|
||||
* list. If we find one here, we'd better stop right now
|
||||
* our iteration.
|
||||
*/
|
||||
if ( node->ref_count > 0 )
|
||||
{
|
||||
/* if there are no unused nodes in the list, we'd better exit */
|
||||
if ( new_count == free_count )
|
||||
goto Exit;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
ftc_node_destroy( node, manager );
|
||||
|
||||
if ( node == first )
|
||||
break;
|
||||
|
||||
node = prev;
|
||||
}
|
||||
count = tries*2;
|
||||
if ( count < tries || count > manager->num_nodes )
|
||||
count = manager->num_nodes;
|
||||
}
|
||||
tries = count;
|
||||
}
|
||||
}
|
||||
|
||||
AddNode:
|
||||
/* don't assume that the cache has the same number of buckets, since
|
||||
* our allocation request might have triggered global cache flushing
|
||||
*/
|
||||
ftc_cache_add( cache, hash, node );
|
||||
|
||||
Exit:
|
||||
*anode = node;
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
FT_EXPORT( void )
|
||||
FTC_Cache_RemoveFaceID( FTC_Cache cache,
|
||||
FTC_FaceID face_id )
|
||||
{
|
||||
FT_UFast i, count;
|
||||
FTC_Manager manager = cache->manager;
|
||||
FTC_Node free = NULL;
|
||||
|
||||
count = cache->p + cache->mask;
|
||||
for ( i = 0; i < count; i++ )
|
||||
{
|
||||
FTC_Node* bucket = cache->buckets + i;
|
||||
FTC_Node* pnode = bucket;
|
||||
|
||||
for ( ;; )
|
||||
{
|
||||
FTC_Node node = *pnode;
|
||||
|
||||
if ( node == NULL )
|
||||
break;
|
||||
|
||||
if ( cache->clazz.node_remove_faceid( node, face_id, cache ) )
|
||||
{
|
||||
*pnode = node->link;
|
||||
node->link = free;
|
||||
free = node;
|
||||
}
|
||||
else
|
||||
pnode = &node->link;
|
||||
}
|
||||
}
|
||||
|
||||
/* remove all nodes in the free list
|
||||
*/
|
||||
while ( free )
|
||||
{
|
||||
FTC_Node node;
|
||||
|
||||
node = free;
|
||||
free = node->link;
|
||||
|
||||
manager->cur_weight -= cache->clazz.node_weight( node, cache );
|
||||
ftc_node_mru_unlink( node, manager );
|
||||
|
||||
cache->clazz.node_free( node, cache );
|
||||
|
||||
cache->slack ++;
|
||||
}
|
||||
|
||||
ftc_cache_resize( cache );
|
||||
}
|
||||
|
||||
/* END */
|
||||
|
404
src/cache/ftccmap.c
vendored
404
src/cache/ftccmap.c
vendored
@ -19,8 +19,7 @@
|
||||
#include <ft2build.h>
|
||||
#include FT_FREETYPE_H
|
||||
#include FT_CACHE_H
|
||||
#include FT_CACHE_CHARMAP_H
|
||||
#include FT_CACHE_MANAGER_H
|
||||
#include FT_CACHE_INTERNAL_MANAGER_H
|
||||
#include FT_INTERNAL_MEMORY_H
|
||||
#include FT_INTERNAL_DEBUG_H
|
||||
#include FT_TRUETYPE_IDS_H
|
||||
@ -47,56 +46,41 @@
|
||||
/* number of glyph indices / character code per node */
|
||||
#define FTC_CMAP_INDICES_MAX 128
|
||||
|
||||
/* compute a query/node hash */
|
||||
#define FTC_CMAP_HASH( faceid, index, charcode ) \
|
||||
( FTC_FACE_ID_HASH( faceid ) + 211*( index ) + ((char_code) / FTC_CMAP_INDICES_MAX) )
|
||||
|
||||
/* the charmap query */
|
||||
typedef struct FTC_CMapQueryRec_
|
||||
{
|
||||
FTC_FaceID face_id;
|
||||
FT_UInt cmap_index;
|
||||
FT_UInt32 char_code;
|
||||
|
||||
} FTC_CMapQueryRec, *FTC_CMapQuery;
|
||||
|
||||
#define FTC_CMAP_QUERY(x) ((FTC_CMapQuery)(x))
|
||||
#define FTC_CMAP_QUERY_HASH(x) FTC_CMAP_HASH( (x)->face_id, (x)->cmap_index, (x)->char_code )
|
||||
|
||||
/* the cmap cache node */
|
||||
typedef struct FTC_CMapNodeRec_
|
||||
{
|
||||
FTC_NodeRec node;
|
||||
FTC_FaceID face_id;
|
||||
FT_UInt cmap_index;
|
||||
FT_UInt32 first; /* first character in node */
|
||||
FT_UInt16 indices[FTC_CMAP_INDICES_MAX]; /* array of glyph indices */
|
||||
|
||||
} FTC_CMapNodeRec, *FTC_CMapNode;
|
||||
|
||||
|
||||
#define FTC_CMAP_NODE( x ) ( (FTC_CMapNode)( x ) )
|
||||
|
||||
|
||||
/* compute node hash value from cmap family and "requested" glyph index */
|
||||
#define FTC_CMAP_HASH( cfam, cquery ) \
|
||||
( (cfam)->hash + ( (cquery)->char_code / FTC_CMAP_INDICES_MAX ) )
|
||||
#define FTC_CMAP_NODE_HASH(x) FTC_CMAP_HASH( (x)->face_id, (x)->cmap_index, (x)->first )
|
||||
|
||||
/* if (indices[n] == FTC_CMAP_UNKNOWN), we assume that the corresponding */
|
||||
/* glyph indices haven't been queried through FT_Get_Glyph_Index() yet */
|
||||
#define FTC_CMAP_UNKNOWN ( (FT_UInt16)-1 )
|
||||
|
||||
|
||||
/* the charmap query */
|
||||
typedef struct FTC_CMapQueryRec_
|
||||
{
|
||||
FTC_QueryRec query;
|
||||
FTC_CMapDesc desc;
|
||||
FT_UInt32 char_code;
|
||||
|
||||
} FTC_CMapQueryRec, *FTC_CMapQuery;
|
||||
|
||||
|
||||
#define FTC_CMAP_QUERY( x ) ( (FTC_CMapQuery)( x ) )
|
||||
|
||||
|
||||
/* the charmap family */
|
||||
typedef struct FTC_CMapFamilyRec_
|
||||
{
|
||||
FTC_FamilyRec family;
|
||||
FT_UInt32 hash;
|
||||
FTC_CMapDescRec desc;
|
||||
FT_UInt index;
|
||||
|
||||
} FTC_CMapFamilyRec, *FTC_CMapFamily;
|
||||
|
||||
|
||||
#define FTC_CMAP_FAMILY( x ) ( (FTC_CMapFamily)( x ) )
|
||||
#define FTC_CMAP_FAMILY_MEMORY( x ) FTC_FAMILY( x )->memory
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/***** *****/
|
||||
@ -108,25 +92,40 @@
|
||||
|
||||
/* no need for specific finalizer; we use "ftc_node_done" directly */
|
||||
|
||||
/* initialize a new cmap node */
|
||||
FT_CALLBACK_DEF( FT_Error )
|
||||
ftc_cmap_node_init( FTC_CMapNode cnode,
|
||||
FTC_CMapQuery cquery,
|
||||
FT_CALLBACK_DEF( void )
|
||||
ftc_cmap_node_free( FTC_CMapNode node,
|
||||
FTC_Cache cache )
|
||||
{
|
||||
FT_UInt32 first;
|
||||
FT_UInt n;
|
||||
FT_UNUSED( cache );
|
||||
FT_Memory memory = cache->memory;
|
||||
|
||||
FT_FREE( node );
|
||||
}
|
||||
|
||||
|
||||
first = ( cquery->char_code / FTC_CMAP_INDICES_MAX ) *
|
||||
FTC_CMAP_INDICES_MAX;
|
||||
/* initialize a new cmap node */
|
||||
FT_CALLBACK_DEF( FT_Error )
|
||||
ftc_cmap_node_new( FTC_CMapNode *anode,
|
||||
FTC_CMapQuery query,
|
||||
FTC_Cache cache )
|
||||
{
|
||||
FT_Error error;
|
||||
FT_Memory memory = cache->memory;
|
||||
FTC_CMapNode node;
|
||||
FT_UInt nn;
|
||||
|
||||
cnode->first = first;
|
||||
for ( n = 0; n < FTC_CMAP_INDICES_MAX; n++ )
|
||||
cnode->indices[n] = FTC_CMAP_UNKNOWN;
|
||||
if ( !FT_NEW( node ) )
|
||||
{
|
||||
node->face_id = query->face_id;
|
||||
node->cmap_index = query->cmap_index;
|
||||
node->first = (query->char_code / FTC_CMAP_INDICES_MAX) *
|
||||
FTC_CMAP_INDICES_MAX;
|
||||
|
||||
return 0;
|
||||
for ( nn = 0; nn < FTC_CMAP_INDICES_MAX; nn++ )
|
||||
node->indices[nn] = FTC_CMAP_UNKNOWN;
|
||||
}
|
||||
|
||||
*anode = node;
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
@ -142,188 +141,27 @@
|
||||
|
||||
/* compare a cmap node to a given query */
|
||||
FT_CALLBACK_DEF( FT_Bool )
|
||||
ftc_cmap_node_compare( FTC_CMapNode cnode,
|
||||
FTC_CMapQuery cquery )
|
||||
ftc_cmap_node_compare( FTC_CMapNode node,
|
||||
FTC_CMapQuery query )
|
||||
{
|
||||
FT_UInt32 offset = (FT_UInt32)( cquery->char_code - cnode->first );
|
||||
|
||||
|
||||
return FT_BOOL( offset < FTC_CMAP_INDICES_MAX );
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/***** *****/
|
||||
/***** CHARMAP FAMILY *****/
|
||||
/***** *****/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
|
||||
FT_CALLBACK_DEF( FT_Error )
|
||||
ftc_cmap_family_init( FTC_CMapFamily cfam,
|
||||
FTC_CMapQuery cquery,
|
||||
FTC_Cache cache )
|
||||
{
|
||||
FTC_Manager manager = cache->manager;
|
||||
FTC_CMapDesc desc = cquery->desc;
|
||||
FT_UInt32 hash = 0;
|
||||
FT_Error error;
|
||||
FT_Face face;
|
||||
|
||||
|
||||
/* setup charmap descriptor */
|
||||
cfam->desc = *desc;
|
||||
|
||||
/* let's see whether the rest is correct too */
|
||||
error = FTC_Manager_Lookup_Face( manager, desc->face_id, &face );
|
||||
if ( !error )
|
||||
if ( node->face_id == query->face_id &&
|
||||
node->cmap_index == query->cmap_index )
|
||||
{
|
||||
FT_UInt count = face->num_charmaps;
|
||||
FT_UInt idx = count;
|
||||
FT_CharMap* cur = face->charmaps;
|
||||
FT_UInt32 offset = (FT_UInt32)( query->char_code - node->first );
|
||||
|
||||
|
||||
switch ( desc->type )
|
||||
{
|
||||
case FTC_CMAP_BY_INDEX:
|
||||
idx = desc->u.index;
|
||||
hash = idx * 33;
|
||||
break;
|
||||
|
||||
case FTC_CMAP_BY_ENCODING:
|
||||
if ( desc->u.encoding == FT_ENCODING_UNICODE )
|
||||
{
|
||||
/* Since the `interesting' table, pid/eid (3,10), is normally the
|
||||
* last one, we loop backwards. This looses with type1 fonts with
|
||||
* non-BMP characters (<.0001%), this wins with .ttf with non-BMP
|
||||
* chars (.01% ?), and this is the same about 99.99% of the time!
|
||||
*/
|
||||
|
||||
FT_UInt unicmap_idx = count; /* some UCS-2 map, if we found it */
|
||||
|
||||
|
||||
cur += count - 1;
|
||||
|
||||
for ( idx = 0; idx < count; idx++, cur-- )
|
||||
{
|
||||
if ( cur[0]->encoding == FT_ENCODING_UNICODE )
|
||||
{
|
||||
unicmap_idx = idx; /* record we found a Unicode charmap */
|
||||
|
||||
/* XXX If some new encodings to represent UCS-4 are added,
|
||||
* they should be added here.
|
||||
*/
|
||||
if ( ( cur[0]->platform_id == TT_PLATFORM_MICROSOFT &&
|
||||
cur[0]->encoding_id == TT_MS_ID_UCS_4 ) ||
|
||||
( cur[0]->platform_id == TT_PLATFORM_APPLE_UNICODE &&
|
||||
cur[0]->encoding_id == TT_APPLE_ID_UNICODE_32 ) )
|
||||
|
||||
/* Hurray! We found a UCS-4 charmap. We can stop the scan! */
|
||||
{
|
||||
idx = count - 1 - idx;
|
||||
goto Found_idx_for_FTC_CMAP_BY_ENCODING;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* We do not have any UCS-4 charmap. Sigh.
|
||||
* Let's see if we have some other kind of Unicode charmap, though.
|
||||
*/
|
||||
if ( unicmap_idx < count )
|
||||
idx = count - 1 - unicmap_idx;
|
||||
}
|
||||
else
|
||||
{
|
||||
for ( idx = 0; idx < count; idx++, cur++ )
|
||||
if ( cur[0]->encoding == desc->u.encoding )
|
||||
break;
|
||||
}
|
||||
|
||||
Found_idx_for_FTC_CMAP_BY_ENCODING:
|
||||
hash = idx * 67;
|
||||
break;
|
||||
|
||||
case FTC_CMAP_BY_ID:
|
||||
for ( idx = 0; idx < count; idx++, cur++ )
|
||||
{
|
||||
if ( (FT_UInt)cur[0]->platform_id == desc->u.id.platform &&
|
||||
(FT_UInt)cur[0]->encoding_id == desc->u.id.encoding )
|
||||
{
|
||||
hash = ( ( desc->u.id.platform << 8 ) | desc->u.id.encoding ) * 7;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
;
|
||||
}
|
||||
|
||||
if ( idx >= count )
|
||||
goto Bad_Descriptor;
|
||||
|
||||
/* compute hash value, both in family and query */
|
||||
cfam->index = idx;
|
||||
cfam->hash = hash ^ FTC_FACE_ID_HASH( desc->face_id );
|
||||
FTC_QUERY( cquery )->hash = FTC_CMAP_HASH( cfam, cquery );
|
||||
|
||||
error = ftc_family_init( FTC_FAMILY( cfam ),
|
||||
FTC_QUERY( cquery ), cache );
|
||||
return FT_BOOL( offset < FTC_CMAP_INDICES_MAX );
|
||||
}
|
||||
|
||||
return error;
|
||||
|
||||
Bad_Descriptor:
|
||||
FT_TRACE1(( "ftp_cmap_family_init: invalid charmap descriptor\n" ));
|
||||
return FTC_Err_Invalid_Argument;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
FT_CALLBACK_DEF( FT_Bool )
|
||||
ftc_cmap_family_compare( FTC_CMapFamily cfam,
|
||||
FTC_CMapQuery cquery )
|
||||
ftc_cmap_node_remove_faceid( FTC_CMapNode node,
|
||||
FTC_FaceID face_id )
|
||||
{
|
||||
FT_Int result = 0;
|
||||
|
||||
|
||||
/* first, compare face id and type */
|
||||
if ( cfam->desc.face_id != cquery->desc->face_id ||
|
||||
cfam->desc.type != cquery->desc->type )
|
||||
goto Exit;
|
||||
|
||||
switch ( cfam->desc.type )
|
||||
{
|
||||
case FTC_CMAP_BY_INDEX:
|
||||
result = ( cfam->desc.u.index == cquery->desc->u.index );
|
||||
break;
|
||||
|
||||
case FTC_CMAP_BY_ENCODING:
|
||||
result = ( cfam->desc.u.encoding == cquery->desc->u.encoding );
|
||||
break;
|
||||
|
||||
case FTC_CMAP_BY_ID:
|
||||
result = ( cfam->desc.u.id.platform == cquery->desc->u.id.platform &&
|
||||
cfam->desc.u.id.encoding == cquery->desc->u.id.encoding );
|
||||
break;
|
||||
|
||||
default:
|
||||
;
|
||||
}
|
||||
|
||||
if ( result )
|
||||
{
|
||||
/* when found, update the 'family' and 'hash' field of the query */
|
||||
FTC_QUERY( cquery )->family = FTC_FAMILY( cfam );
|
||||
FTC_QUERY( cquery )->hash = FTC_CMAP_HASH( cfam, cquery );
|
||||
}
|
||||
|
||||
Exit:
|
||||
return FT_BOOL( result );
|
||||
return FT_BOOL( node->face_id == face_id );
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/***** *****/
|
||||
@ -334,127 +172,95 @@
|
||||
|
||||
|
||||
FT_CALLBACK_TABLE_DEF
|
||||
const FTC_Cache_ClassRec ftc_cmap_cache_class =
|
||||
const FTC_CacheClassRec ftc_cmap_cache_class =
|
||||
{
|
||||
(FTC_Node_NewFunc) ftc_cmap_node_new,
|
||||
(FTC_Node_WeightFunc) ftc_cmap_node_weight,
|
||||
(FTC_Node_CompareFunc) ftc_cmap_node_compare,
|
||||
(FTC_Node_CompareFunc) ftc_cmap_node_remove_faceid,
|
||||
(FTC_Node_FreeFunc) ftc_cmap_node_free,
|
||||
|
||||
sizeof ( FTC_CacheRec ),
|
||||
(FTC_Cache_InitFunc) ftc_cache_init,
|
||||
(FTC_Cache_ClearFunc)ftc_cache_clear,
|
||||
(FTC_Cache_DoneFunc) ftc_cache_done,
|
||||
|
||||
sizeof ( FTC_CMapFamilyRec ),
|
||||
(FTC_Family_InitFunc) ftc_cmap_family_init,
|
||||
(FTC_Family_CompareFunc)ftc_cmap_family_compare,
|
||||
(FTC_Family_DoneFunc) ftc_family_done,
|
||||
|
||||
sizeof ( FTC_CMapNodeRec ),
|
||||
(FTC_Node_InitFunc) ftc_cmap_node_init,
|
||||
(FTC_Node_WeightFunc) ftc_cmap_node_weight,
|
||||
(FTC_Node_CompareFunc)ftc_cmap_node_compare,
|
||||
(FTC_Node_DoneFunc) ftc_node_done
|
||||
(FTC_Cache_InitFunc) FTC_Cache_Init,
|
||||
(FTC_Cache_DoneFunc) FTC_Cache_Done,
|
||||
};
|
||||
|
||||
|
||||
/* documentation is in ftccmap.h */
|
||||
|
||||
FT_EXPORT_DEF( FT_Error )
|
||||
FTC_CMapCache_New( FTC_Manager manager,
|
||||
FTC_CMapCache *acache )
|
||||
{
|
||||
return FTC_Manager_Register_Cache(
|
||||
manager,
|
||||
(FTC_Cache_Class)&ftc_cmap_cache_class,
|
||||
FTC_CACHE_P( acache ) );
|
||||
return FTC_Manager_RegisterCache( manager,
|
||||
& ftc_cmap_cache_class,
|
||||
FTC_CACHE_P( acache ) );
|
||||
}
|
||||
|
||||
|
||||
#ifdef FTC_CACHE_USE_INLINE
|
||||
|
||||
#define GEN_CACHE_FAMILY_COMPARE( f, q, c ) \
|
||||
ftc_cmap_family_compare( (FTC_CMapFamily)(f), (FTC_CMapQuery)(q) )
|
||||
|
||||
#define GEN_CACHE_NODE_COMPARE( n, q, c ) \
|
||||
ftc_cmap_node_compare( (FTC_CMapNode)(n), (FTC_CMapQuery)(q) )
|
||||
|
||||
#define GEN_CACHE_LOOKUP ftc_cmap_cache_lookup
|
||||
|
||||
#include "ftccache.i"
|
||||
|
||||
#else /* !FTC_CACHE_USE_INLINE */
|
||||
|
||||
#define ftc_cmap_cache_lookup ftc_cache_lookup
|
||||
|
||||
#endif /* !FTC_CACHE_USE_INLINE */
|
||||
|
||||
|
||||
/* documentation is in ftccmap.h */
|
||||
|
||||
FT_EXPORT_DEF( FT_UInt )
|
||||
FTC_CMapCache_Lookup( FTC_CMapCache cache,
|
||||
FTC_CMapDesc desc,
|
||||
FTC_CMapCache_Lookup( FTC_CMapCache cmap_cache,
|
||||
FTC_FaceID face_id,
|
||||
FT_UInt cmap_index,
|
||||
FT_UInt32 char_code )
|
||||
{
|
||||
FTC_CMapQueryRec cquery;
|
||||
FTC_Cache cache = FTC_CACHE( cmap_cache );
|
||||
FTC_CMapQueryRec query;
|
||||
FTC_CMapNode node;
|
||||
FT_Error error;
|
||||
FT_UInt gindex = 0;
|
||||
FT_UInt32 hash;
|
||||
|
||||
|
||||
if ( !cache || !desc )
|
||||
if ( !cache )
|
||||
{
|
||||
FT_ERROR(( "FTC_CMapCache_Lookup: bad arguments, returning 0!\n" ));
|
||||
return 0;
|
||||
}
|
||||
|
||||
cquery.desc = desc;
|
||||
cquery.char_code = char_code;
|
||||
query.face_id = face_id;
|
||||
query.cmap_index = cmap_index;
|
||||
query.char_code = char_code;
|
||||
|
||||
error = ftc_cmap_cache_lookup( FTC_CACHE( cache ),
|
||||
FTC_QUERY( &cquery ),
|
||||
(FTC_Node*)&node );
|
||||
if ( !error )
|
||||
hash = FTC_CMAP_HASH( face_id, cmap_index, char_code );
|
||||
|
||||
error = FTC_Cache_Lookup( cache, hash, &query, (FTC_Node*) &node );
|
||||
if ( error )
|
||||
goto Exit;
|
||||
|
||||
FT_ASSERT( (FT_UInt)( char_code - node->first ) < FTC_CMAP_INDICES_MAX );
|
||||
|
||||
gindex = node->indices[ char_code - node->first ];
|
||||
if ( gindex == FTC_CMAP_UNKNOWN )
|
||||
{
|
||||
FT_UInt offset = (FT_UInt)( char_code - node->first );
|
||||
FT_Face face;
|
||||
|
||||
gindex = 0;
|
||||
|
||||
FT_ASSERT( offset < FTC_CMAP_INDICES_MAX );
|
||||
error = FTC_Manager_LookupFace( cache->manager, node->face_id, &face );
|
||||
if ( error )
|
||||
goto Exit;
|
||||
|
||||
gindex = node->indices[offset];
|
||||
if ( gindex == FTC_CMAP_UNKNOWN )
|
||||
if ( (FT_UInt)cmap_index < (FT_UInt)face->num_charmaps )
|
||||
{
|
||||
FT_Face face;
|
||||
FT_CharMap old, cmap = NULL;
|
||||
|
||||
old = face->charmap;
|
||||
cmap = face->charmaps[ cmap_index ];
|
||||
|
||||
/* we need to use FT_Get_Char_Index */
|
||||
gindex = 0;
|
||||
|
||||
error = FTC_Manager_Lookup_Face( FTC_CACHE(cache)->manager,
|
||||
desc->face_id,
|
||||
&face );
|
||||
if ( !error )
|
||||
{
|
||||
FT_CharMap old, cmap = NULL;
|
||||
FT_UInt cmap_index;
|
||||
|
||||
|
||||
/* save old charmap, select new one */
|
||||
old = face->charmap;
|
||||
cmap_index = FTC_CMAP_FAMILY( FTC_QUERY( &cquery )->family )->index;
|
||||
cmap = face->charmaps[cmap_index];
|
||||
|
||||
if (old != cmap)
|
||||
FT_Set_Charmap( face, cmap );
|
||||
|
||||
/* perform lookup */
|
||||
gindex = FT_Get_Char_Index( face, char_code );
|
||||
node->indices[offset] = (FT_UInt16)gindex;
|
||||
gindex = FT_Get_Char_Index( face, char_code );
|
||||
|
||||
/* restore old charmap */
|
||||
if (old != cmap)
|
||||
FT_Set_Charmap( face, old );
|
||||
}
|
||||
}
|
||||
|
||||
node->indices[ char_code - node->first ] = gindex;
|
||||
}
|
||||
|
||||
Exit:
|
||||
return gindex;
|
||||
}
|
||||
|
||||
|
||||
/* END */
|
||||
|
123
src/cache/ftcglyph.c
vendored
123
src/cache/ftcglyph.c
vendored
@ -20,7 +20,6 @@
|
||||
#include FT_CACHE_H
|
||||
#include FT_CACHE_INTERNAL_GLYPH_H
|
||||
#include FT_ERRORS_H
|
||||
#include FT_LIST_H
|
||||
#include FT_INTERNAL_OBJECTS_H
|
||||
#include FT_INTERNAL_DEBUG_H
|
||||
|
||||
@ -29,45 +28,45 @@
|
||||
|
||||
/* create a new chunk node, setting its cache index and ref count */
|
||||
FT_EXPORT_DEF( void )
|
||||
ftc_glyph_node_init( FTC_GlyphNode gnode,
|
||||
FT_UInt gindex,
|
||||
FTC_GlyphFamily gfam )
|
||||
FTC_GNode_Init( FTC_GNode gnode,
|
||||
FT_UInt gindex,
|
||||
FTC_Family family )
|
||||
{
|
||||
FT_UInt len;
|
||||
FT_UInt start = FTC_GLYPH_FAMILY_START( gfam, gindex );
|
||||
|
||||
|
||||
gnode->item_start = (FT_UShort)start;
|
||||
|
||||
len = gfam->item_total - start;
|
||||
if ( len > gfam->item_count )
|
||||
len = gfam->item_count;
|
||||
|
||||
gnode->item_count = (FT_UShort)len;
|
||||
gfam->family.num_nodes++;
|
||||
gnode->family = family;
|
||||
gnode->gindex = gindex;
|
||||
family->num_nodes++;
|
||||
}
|
||||
|
||||
|
||||
FT_EXPORT_DEF( void )
|
||||
ftc_glyph_node_done( FTC_GlyphNode gnode,
|
||||
FTC_Cache cache )
|
||||
FTC_GNode_UnselectFamily( FTC_GNode gnode,
|
||||
FTC_Cache cache )
|
||||
{
|
||||
FTC_Family family = gnode->family;
|
||||
|
||||
gnode->family = NULL;
|
||||
if ( family && --family->num_nodes <= 0 )
|
||||
FTC_MruList_Remove( & FTC_GCACHE(cache)->families, (FTC_MruNode)family );
|
||||
}
|
||||
|
||||
|
||||
FT_EXPORT_DEF( void )
|
||||
FTC_GNode_Done( FTC_GNode gnode,
|
||||
FTC_Cache cache )
|
||||
{
|
||||
/* finalize the node */
|
||||
gnode->item_count = 0;
|
||||
gnode->item_start = 0;
|
||||
gnode->gindex = 0;
|
||||
|
||||
ftc_node_done( FTC_NODE( gnode ), cache );
|
||||
FTC_GNode_UnselectFamily( gnode, cache );
|
||||
}
|
||||
|
||||
|
||||
FT_EXPORT_DEF( FT_Bool )
|
||||
ftc_glyph_node_compare( FTC_GlyphNode gnode,
|
||||
FTC_GlyphQuery gquery )
|
||||
FTC_GNode_Compare( FTC_GNode gnode,
|
||||
FTC_GQuery gquery )
|
||||
{
|
||||
FT_UInt start = (FT_UInt)gnode->item_start;
|
||||
FT_UInt count = (FT_UInt)gnode->item_count;
|
||||
|
||||
return FT_BOOL( (FT_UInt)( gquery->gindex - start ) < count );
|
||||
return FT_BOOL( gnode->family == gquery->family &&
|
||||
gnode->gindex == gquery->gindex );
|
||||
}
|
||||
|
||||
|
||||
@ -79,36 +78,72 @@
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
FT_EXPORT_DEF( void )
|
||||
ftc_family_init( FTC_Family family,
|
||||
FTC_Cache cache )
|
||||
{
|
||||
FTC_GCacheClass clazz = FTC_CACHE__GCACHE_CLASS(cache);
|
||||
|
||||
family->clazz = clazz->family_class;
|
||||
family->num_nodes = 0;
|
||||
}
|
||||
|
||||
|
||||
FT_EXPORT_DEF( FT_Error )
|
||||
ftc_glyph_family_init( FTC_GlyphFamily gfam,
|
||||
FT_UInt32 hash,
|
||||
FT_UInt item_count,
|
||||
FT_UInt item_total,
|
||||
FTC_GlyphQuery gquery,
|
||||
FTC_Cache cache )
|
||||
FTC_GCache_Init( FTC_GCache cache )
|
||||
{
|
||||
FT_Error error;
|
||||
FT_Error error;
|
||||
|
||||
|
||||
error = ftc_family_init( FTC_FAMILY( gfam ), FTC_QUERY( gquery ), cache );
|
||||
error = FTC_Cache_Init( FTC_CACHE(cache) );
|
||||
if ( !error )
|
||||
{
|
||||
gfam->hash = hash;
|
||||
gfam->item_total = item_total;
|
||||
gfam->item_count = item_count;
|
||||
|
||||
FTC_GLYPH_FAMILY_FOUND( gfam, gquery );
|
||||
}
|
||||
FTC_GCacheClass clazz = (FTC_GCacheClass) FTC_CACHE(cache)->org_class;
|
||||
|
||||
FTC_MruList_Init( &cache->families,
|
||||
clazz->family_class,
|
||||
0, /* no maximum here !! */
|
||||
cache,
|
||||
FTC_CACHE(cache)->memory );
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
FT_EXPORT_DEF( void )
|
||||
ftc_glyph_family_done( FTC_GlyphFamily gfam )
|
||||
FTC_GCache_Done( FTC_GCache cache )
|
||||
{
|
||||
ftc_family_done( FTC_FAMILY( gfam ) );
|
||||
FTC_Cache_Done( (FTC_Cache)cache );
|
||||
FTC_MruList_Done( &cache->families );
|
||||
}
|
||||
|
||||
|
||||
FT_EXPORT_DEF( FT_Error )
|
||||
FTC_GCache_New( FTC_Manager manager,
|
||||
FTC_GCacheClass clazz,
|
||||
FTC_GCache *acache )
|
||||
{
|
||||
return FTC_Manager_RegisterCache( manager, (FTC_CacheClass) clazz,
|
||||
(FTC_Cache*) acache );
|
||||
}
|
||||
|
||||
|
||||
FT_EXPORT_DEF( FT_Error )
|
||||
FTC_GCache_Lookup( FTC_GCache cache,
|
||||
FT_UInt32 hash,
|
||||
FT_UInt gindex,
|
||||
FTC_GQuery query,
|
||||
FTC_Node *anode )
|
||||
{
|
||||
FT_Error error;
|
||||
|
||||
query->gindex = gindex;
|
||||
|
||||
error = FTC_MruList_Lookup( &cache->families, query,
|
||||
(FTC_MruNode*) &query->family );
|
||||
if ( !error )
|
||||
error = FTC_Cache_Lookup( FTC_CACHE(cache), hash, query, anode );
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
|
338
src/cache/ftcimage.c
vendored
338
src/cache/ftcimage.c
vendored
@ -18,133 +18,60 @@
|
||||
|
||||
#include <ft2build.h>
|
||||
#include FT_CACHE_H
|
||||
#include FT_CACHE_IMAGE_H
|
||||
#include FT_CACHE_INTERNAL_GLYPH_H
|
||||
#include FT_CACHE_INTERNAL_IMAGE_H
|
||||
#include FT_INTERNAL_MEMORY_H
|
||||
|
||||
#include "ftcerror.h"
|
||||
|
||||
|
||||
/* the FT_Glyph image node type */
|
||||
typedef struct FTC_ImageNodeRec_
|
||||
{
|
||||
FTC_GlyphNodeRec gnode;
|
||||
FT_Glyph glyph;
|
||||
|
||||
} FTC_ImageNodeRec, *FTC_ImageNode;
|
||||
|
||||
|
||||
#define FTC_IMAGE_NODE( x ) ( (FTC_ImageNode)( x ) )
|
||||
#define FTC_IMAGE_NODE_GINDEX( x ) FTC_GLYPH_NODE_GINDEX( x )
|
||||
|
||||
|
||||
/* the glyph image query */
|
||||
typedef struct FTC_ImageQueryRec_
|
||||
{
|
||||
FTC_GlyphQueryRec gquery;
|
||||
FTC_ImageTypeRec type;
|
||||
|
||||
} FTC_ImageQueryRec, *FTC_ImageQuery;
|
||||
|
||||
|
||||
#define FTC_IMAGE_QUERY( x ) ( (FTC_ImageQuery)( x ) )
|
||||
|
||||
|
||||
/* the glyph image set type */
|
||||
typedef struct FTC_ImageFamilyRec_
|
||||
{
|
||||
FTC_GlyphFamilyRec gfam;
|
||||
FTC_ImageTypeRec type;
|
||||
|
||||
} FTC_ImageFamilyRec, *FTC_ImageFamily;
|
||||
|
||||
|
||||
#define FTC_IMAGE_FAMILY( x ) ( (FTC_ImageFamily)( x ) )
|
||||
#define FTC_IMAGE_FAMILY_MEMORY( x ) FTC_GLYPH_FAMILY_MEMORY( &(x)->gfam )
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/***** *****/
|
||||
/***** GLYPH IMAGE NODES *****/
|
||||
/***** *****/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
|
||||
/* finalize a given glyph image node */
|
||||
FT_CALLBACK_DEF( void )
|
||||
ftc_image_node_done( FTC_ImageNode inode,
|
||||
FTC_Cache cache )
|
||||
FT_EXPORT_DEF( void )
|
||||
FTC_INode_Free( FTC_INode inode,
|
||||
FTC_Cache cache )
|
||||
{
|
||||
FT_Memory memory = cache->memory;
|
||||
|
||||
if ( inode->glyph )
|
||||
{
|
||||
FT_Done_Glyph( inode->glyph );
|
||||
inode->glyph = NULL;
|
||||
}
|
||||
|
||||
ftc_glyph_node_done( FTC_GLYPH_NODE( inode ), cache );
|
||||
FTC_GNode_Done( FTC_GNODE( inode ), cache );
|
||||
FT_FREE( inode );
|
||||
}
|
||||
|
||||
|
||||
/* initialize a new glyph image node */
|
||||
FT_CALLBACK_DEF( FT_Error )
|
||||
ftc_image_node_init( FTC_ImageNode inode,
|
||||
FTC_GlyphQuery gquery,
|
||||
FTC_Cache cache )
|
||||
FT_EXPORT_DEF( FT_Error )
|
||||
FTC_INode_New( FTC_INode *pinode,
|
||||
FTC_GQuery gquery,
|
||||
FTC_Cache cache )
|
||||
{
|
||||
FTC_ImageFamily ifam = FTC_IMAGE_FAMILY( gquery->query.family );
|
||||
FT_Error error;
|
||||
FT_Face face;
|
||||
FT_Size size;
|
||||
FT_Memory memory = cache->memory;
|
||||
FT_Error error;
|
||||
FTC_INode inode;
|
||||
|
||||
|
||||
/* initialize its inner fields */
|
||||
ftc_glyph_node_init( FTC_GLYPH_NODE( inode ),
|
||||
gquery->gindex,
|
||||
FTC_GLYPH_FAMILY( ifam ) );
|
||||
|
||||
/* we will now load the glyph image */
|
||||
error = FTC_Manager_Lookup_Size( FTC_FAMILY( ifam )->cache->manager,
|
||||
&ifam->type.font,
|
||||
&face, &size );
|
||||
if ( !error )
|
||||
if ( !FT_NEW( inode ) )
|
||||
{
|
||||
FT_UInt gindex = FTC_GLYPH_NODE_GINDEX( inode );
|
||||
FTC_GNode gnode = FTC_GNODE( inode );
|
||||
FTC_Family family = gquery->family;
|
||||
FT_UInt gindex = gquery->gindex;
|
||||
FTC_IFamilyClass clazz = FTC_CACHE__IFAMILY_CLASS( cache );
|
||||
|
||||
/* initialize its inner fields */
|
||||
FTC_GNode_Init( gnode, gindex, family );
|
||||
|
||||
error = FT_Load_Glyph( face, gindex, ifam->type.flags );
|
||||
if ( !error )
|
||||
{
|
||||
if ( face->glyph->format == FT_GLYPH_FORMAT_BITMAP ||
|
||||
face->glyph->format == FT_GLYPH_FORMAT_OUTLINE )
|
||||
{
|
||||
/* ok, copy it */
|
||||
FT_Glyph glyph;
|
||||
|
||||
|
||||
error = FT_Get_Glyph( face->glyph, &glyph );
|
||||
if ( !error )
|
||||
{
|
||||
inode->glyph = glyph;
|
||||
goto Exit;
|
||||
}
|
||||
}
|
||||
else
|
||||
error = FTC_Err_Invalid_Argument;
|
||||
}
|
||||
/* we will now load the glyph image */
|
||||
error = clazz->family_load_glyph( family, gindex, cache, &inode->glyph );
|
||||
}
|
||||
|
||||
/* in case of error */
|
||||
ftc_glyph_node_done( FTC_GLYPH_NODE(inode), cache );
|
||||
|
||||
Exit:
|
||||
*pinode = inode;
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
FT_CALLBACK_DEF( FT_ULong )
|
||||
ftc_image_node_weight( FTC_ImageNode inode )
|
||||
FT_EXPORT_DEF( FT_ULong )
|
||||
FTC_INode_Weight( FTC_INode inode )
|
||||
{
|
||||
FT_ULong size = 0;
|
||||
FT_Glyph glyph = inode->glyph;
|
||||
@ -185,215 +112,4 @@
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/***** *****/
|
||||
/***** GLYPH IMAGE SETS *****/
|
||||
/***** *****/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
|
||||
FT_CALLBACK_DEF( FT_Error )
|
||||
ftc_image_family_init( FTC_ImageFamily ifam,
|
||||
FTC_ImageQuery iquery,
|
||||
FTC_Cache cache )
|
||||
{
|
||||
FTC_Manager manager = cache->manager;
|
||||
FT_Error error;
|
||||
FT_Face face;
|
||||
|
||||
|
||||
ifam->type = iquery->type;
|
||||
|
||||
/* we need to compute "iquery.item_total" now */
|
||||
error = FTC_Manager_Lookup_Face( manager,
|
||||
iquery->type.font.face_id,
|
||||
&face );
|
||||
if ( !error )
|
||||
{
|
||||
error = ftc_glyph_family_init( FTC_GLYPH_FAMILY( ifam ),
|
||||
FTC_IMAGE_TYPE_HASH( &ifam->type ),
|
||||
1,
|
||||
face->num_glyphs,
|
||||
FTC_GLYPH_QUERY( iquery ),
|
||||
cache );
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
FT_CALLBACK_DEF( FT_Bool )
|
||||
ftc_image_family_compare( FTC_ImageFamily ifam,
|
||||
FTC_ImageQuery iquery )
|
||||
{
|
||||
FT_Bool result;
|
||||
|
||||
|
||||
result = FT_BOOL( FTC_IMAGE_TYPE_COMPARE( &ifam->type, &iquery->type ) );
|
||||
if ( result )
|
||||
FTC_GLYPH_FAMILY_FOUND( ifam, iquery );
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/***** *****/
|
||||
/***** GLYPH IMAGE CACHE *****/
|
||||
/***** *****/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
|
||||
|
||||
FT_CALLBACK_TABLE_DEF
|
||||
const FTC_Cache_ClassRec ftc_image_cache_class =
|
||||
{
|
||||
sizeof ( FTC_CacheRec ),
|
||||
(FTC_Cache_InitFunc) ftc_cache_init,
|
||||
(FTC_Cache_ClearFunc)ftc_cache_clear,
|
||||
(FTC_Cache_DoneFunc) ftc_cache_done,
|
||||
|
||||
sizeof ( FTC_ImageFamilyRec ),
|
||||
(FTC_Family_InitFunc) ftc_image_family_init,
|
||||
(FTC_Family_CompareFunc)ftc_image_family_compare,
|
||||
(FTC_Family_DoneFunc) ftc_glyph_family_done,
|
||||
|
||||
sizeof ( FTC_ImageNodeRec ),
|
||||
(FTC_Node_InitFunc) ftc_image_node_init,
|
||||
(FTC_Node_WeightFunc) ftc_image_node_weight,
|
||||
(FTC_Node_CompareFunc)ftc_glyph_node_compare,
|
||||
(FTC_Node_DoneFunc) ftc_image_node_done
|
||||
};
|
||||
|
||||
|
||||
/* documentation is in ftcimage.h */
|
||||
|
||||
FT_EXPORT_DEF( FT_Error )
|
||||
FTC_ImageCache_New( FTC_Manager manager,
|
||||
FTC_ImageCache *acache )
|
||||
{
|
||||
return FTC_Manager_Register_Cache(
|
||||
manager,
|
||||
(FTC_Cache_Class)&ftc_image_cache_class,
|
||||
FTC_CACHE_P( acache ) );
|
||||
}
|
||||
|
||||
|
||||
/* documentation is in ftcimage.h */
|
||||
|
||||
FT_EXPORT_DEF( FT_Error )
|
||||
FTC_ImageCache_Lookup( FTC_ImageCache cache,
|
||||
FTC_ImageType type,
|
||||
FT_UInt gindex,
|
||||
FT_Glyph *aglyph,
|
||||
FTC_Node *anode )
|
||||
{
|
||||
FTC_ImageQueryRec iquery;
|
||||
FTC_ImageNode node;
|
||||
FT_Error error;
|
||||
|
||||
|
||||
/* some argument checks are delayed to ftc_cache_lookup */
|
||||
if ( !aglyph )
|
||||
return FTC_Err_Invalid_Argument;
|
||||
|
||||
if ( anode )
|
||||
*anode = NULL;
|
||||
|
||||
iquery.gquery.gindex = gindex;
|
||||
iquery.type = *type;
|
||||
|
||||
error = ftc_cache_lookup( FTC_CACHE( cache ),
|
||||
FTC_QUERY( &iquery ),
|
||||
(FTC_Node*)&node );
|
||||
if ( !error )
|
||||
{
|
||||
*aglyph = node->glyph;
|
||||
|
||||
if ( anode )
|
||||
{
|
||||
*anode = (FTC_Node)node;
|
||||
FTC_NODE( node )->ref_count++;
|
||||
}
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
/* backwards-compatibility functions */
|
||||
|
||||
FT_EXPORT_DEF( FT_Error )
|
||||
FTC_Image_Cache_New( FTC_Manager manager,
|
||||
FTC_Image_Cache *acache )
|
||||
{
|
||||
return FTC_ImageCache_New( manager, (FTC_ImageCache*)acache );
|
||||
}
|
||||
|
||||
|
||||
FT_EXPORT_DEF( FT_Error )
|
||||
FTC_Image_Cache_Lookup( FTC_Image_Cache icache,
|
||||
FTC_Image_Desc* desc,
|
||||
FT_UInt gindex,
|
||||
FT_Glyph *aglyph )
|
||||
{
|
||||
FTC_ImageTypeRec type0;
|
||||
|
||||
|
||||
if ( !desc )
|
||||
return FTC_Err_Invalid_Argument;
|
||||
|
||||
type0.font = desc->font;
|
||||
|
||||
/* convert image type flags to load flags */
|
||||
{
|
||||
FT_UInt load_flags = FT_LOAD_DEFAULT;
|
||||
FT_UInt type = desc->image_type;
|
||||
|
||||
|
||||
/* determine load flags, depending on the font description's */
|
||||
/* image type */
|
||||
|
||||
if ( ftc_image_format( type ) == ftc_image_format_bitmap )
|
||||
{
|
||||
if ( type & ftc_image_flag_monochrome )
|
||||
load_flags |= FT_LOAD_MONOCHROME;
|
||||
|
||||
/* disable embedded bitmaps loading if necessary */
|
||||
if ( type & ftc_image_flag_no_sbits )
|
||||
load_flags |= FT_LOAD_NO_BITMAP;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* we want an outline, don't load embedded bitmaps */
|
||||
load_flags |= FT_LOAD_NO_BITMAP;
|
||||
|
||||
if ( type & ftc_image_flag_unscaled )
|
||||
load_flags |= FT_LOAD_NO_SCALE;
|
||||
}
|
||||
|
||||
/* always render glyphs to bitmaps */
|
||||
load_flags |= FT_LOAD_RENDER;
|
||||
|
||||
if ( type & ftc_image_flag_unhinted )
|
||||
load_flags |= FT_LOAD_NO_HINTING;
|
||||
|
||||
if ( type & ftc_image_flag_autohinted )
|
||||
load_flags |= FT_LOAD_FORCE_AUTOHINT;
|
||||
|
||||
type0.flags = load_flags;
|
||||
}
|
||||
|
||||
return FTC_ImageCache_Lookup( (FTC_ImageCache)icache,
|
||||
&type0,
|
||||
gindex,
|
||||
aglyph,
|
||||
NULL );
|
||||
}
|
||||
|
||||
|
||||
/* END */
|
||||
|
685
src/cache/ftcmanag.c
vendored
685
src/cache/ftcmanag.c
vendored
@ -18,8 +18,7 @@
|
||||
|
||||
#include <ft2build.h>
|
||||
#include FT_CACHE_H
|
||||
#include FT_CACHE_MANAGER_H
|
||||
#include FT_CACHE_INTERNAL_LRU_H
|
||||
#include FT_CACHE_INTERNAL_MANAGER_H
|
||||
#include FT_INTERNAL_OBJECTS_H
|
||||
#include FT_INTERNAL_DEBUG_H
|
||||
#include FT_SIZES_H
|
||||
@ -33,41 +32,166 @@
|
||||
#define FTC_LRU_GET_MANAGER( lru ) ( (FTC_Manager)(lru)->user_data )
|
||||
|
||||
|
||||
static FT_Error
|
||||
ftc_scaler_lookup_size( FTC_Manager manager,
|
||||
FTC_Scaler scaler,
|
||||
FT_Size *asize )
|
||||
{
|
||||
FT_Face face;
|
||||
FT_Size size = NULL;
|
||||
FT_Error error;
|
||||
|
||||
error = FTC_Manager_LookupFace( manager, scaler->face_id, &face );
|
||||
if ( error ) goto Exit;
|
||||
|
||||
error = FT_New_Size( face, &size );
|
||||
if ( error ) goto Exit;
|
||||
|
||||
FT_Activate_Size( size );
|
||||
|
||||
if ( scaler->pixel )
|
||||
error = FT_Set_Pixel_Sizes( face, scaler->width, scaler->height );
|
||||
else
|
||||
error = FT_Set_Char_Size( face, scaler->width, scaler->height,
|
||||
scaler->x_res, scaler->y_res );
|
||||
if ( error )
|
||||
{
|
||||
FT_Done_Size( size );
|
||||
size = NULL;
|
||||
}
|
||||
|
||||
Exit:
|
||||
*asize = size;
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
typedef struct FTC_SizeNodeRec_
|
||||
{
|
||||
FTC_MruNodeRec node;
|
||||
FT_Size size;
|
||||
FTC_ScalerRec scaler;
|
||||
|
||||
} FTC_SizeNodeRec, *FTC_SizeNode;
|
||||
|
||||
|
||||
FT_CALLBACK_DEF( void )
|
||||
ftc_size_node_done( FTC_SizeNode node )
|
||||
{
|
||||
FT_Size size = node->size;
|
||||
|
||||
if ( size )
|
||||
FT_Done_Size( size );
|
||||
}
|
||||
|
||||
|
||||
FT_CALLBACK_DEF( FT_Bool )
|
||||
ftc_size_node_compare( FTC_SizeNode node,
|
||||
FTC_Scaler scaler )
|
||||
{
|
||||
FTC_Scaler scaler0 = &node->scaler;
|
||||
|
||||
return FTC_SCALER_COMPARE( scaler0, scaler );
|
||||
}
|
||||
|
||||
|
||||
|
||||
FT_CALLBACK_DEF( FT_Error )
|
||||
ftc_size_node_init( FTC_SizeNode node,
|
||||
FTC_Scaler scaler,
|
||||
FTC_Manager manager )
|
||||
{
|
||||
node->scaler = scaler[0];
|
||||
|
||||
return ftc_scaler_lookup_size( manager, scaler, &node->size );
|
||||
}
|
||||
|
||||
|
||||
FT_CALLBACK_DEF( FT_Error )
|
||||
ftc_size_node_reset( FTC_SizeNode node,
|
||||
FTC_Scaler scaler,
|
||||
FTC_Manager manager )
|
||||
{
|
||||
FT_Done_Size( node->size );
|
||||
|
||||
node->scaler = scaler[0];
|
||||
|
||||
return ftc_scaler_lookup_size( manager, scaler, &node->size );
|
||||
}
|
||||
|
||||
|
||||
static const FTC_MruListClassRec ftc_size_list_class =
|
||||
{
|
||||
sizeof( FTC_SizeNodeRec ),
|
||||
(FTC_MruNode_CompareFunc) ftc_size_node_compare,
|
||||
(FTC_MruNode_InitFunc) ftc_size_node_init,
|
||||
(FTC_MruNode_ResetFunc) ftc_size_node_reset,
|
||||
(FTC_MruNode_DoneFunc) ftc_size_node_done
|
||||
};
|
||||
|
||||
|
||||
/* helper function used by ftc_face_node_done */
|
||||
static FT_Bool
|
||||
ftc_size_node_compare_faceid( FTC_SizeNode node,
|
||||
FTC_FaceID face_id )
|
||||
{
|
||||
return FT_BOOL( node->scaler.face_id == face_id );
|
||||
}
|
||||
|
||||
|
||||
FT_EXPORT_DEF( FT_Error )
|
||||
FTC_Manager_LookupSize( FTC_Manager manager,
|
||||
FTC_Scaler scaler,
|
||||
FT_Size *asize )
|
||||
{
|
||||
FT_Error error;
|
||||
FTC_SizeNode node;
|
||||
|
||||
|
||||
if ( asize == NULL )
|
||||
return FTC_Err_Bad_Argument;
|
||||
|
||||
*asize = NULL;
|
||||
|
||||
if ( !manager )
|
||||
return FTC_Err_Invalid_Cache_Handle;
|
||||
|
||||
error = FTC_MruList_Lookup( &manager->sizes,
|
||||
scaler,
|
||||
(FTC_MruNode*) &node );
|
||||
if ( !error )
|
||||
*asize = node->size;
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/***** *****/
|
||||
/***** FACE LRU IMPLEMENTATION *****/
|
||||
/***** FACE MRU IMPLEMENTATION *****/
|
||||
/***** *****/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
typedef struct FTC_FaceNodeRec_* FTC_FaceNode;
|
||||
typedef struct FTC_SizeNodeRec_* FTC_SizeNode;
|
||||
|
||||
|
||||
typedef struct FTC_FaceNodeRec_
|
||||
{
|
||||
FT_LruNodeRec lru;
|
||||
FT_Face face;
|
||||
FTC_MruNodeRec node;
|
||||
FTC_FaceID face_id;
|
||||
FT_Face face;
|
||||
|
||||
} FTC_FaceNodeRec;
|
||||
} FTC_FaceNodeRec, *FTC_FaceNode;
|
||||
|
||||
|
||||
typedef struct FTC_SizeNodeRec_
|
||||
{
|
||||
FT_LruNodeRec lru;
|
||||
FT_Size size;
|
||||
|
||||
} FTC_SizeNodeRec;
|
||||
|
||||
|
||||
FT_CALLBACK_DEF( FT_Error )
|
||||
ftc_face_node_init( FTC_FaceNode node,
|
||||
FTC_FaceID face_id,
|
||||
FTC_Manager manager )
|
||||
{
|
||||
FT_Error error;
|
||||
FT_Error error;
|
||||
|
||||
node->face_id = face_id;
|
||||
|
||||
error = manager->request_face( face_id,
|
||||
manager->library,
|
||||
@ -79,60 +203,59 @@
|
||||
if ( node->face->size )
|
||||
FT_Done_Size( node->face->size );
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
/* helper function for ftc_face_node_done() */
|
||||
FT_CALLBACK_DEF( FT_Bool )
|
||||
ftc_size_node_select( FTC_SizeNode node,
|
||||
FT_Face face )
|
||||
{
|
||||
return FT_BOOL( node->size->face == face );
|
||||
}
|
||||
|
||||
|
||||
FT_CALLBACK_DEF( void )
|
||||
ftc_face_node_done( FTC_FaceNode node,
|
||||
FTC_Manager manager )
|
||||
{
|
||||
FT_Face face = node->face;
|
||||
FT_Memory memory = manager->memory;
|
||||
|
||||
|
||||
/* we must begin by removing all sizes for the target face */
|
||||
/* from the manager's list */
|
||||
FT_LruList_Remove_Selection( manager->sizes_list,
|
||||
(FT_LruNode_SelectFunc)ftc_size_node_select,
|
||||
face );
|
||||
/* we must begin by removing all scalers for the target face */
|
||||
/* from the manager's list */
|
||||
FTC_MruList_RemoveSelection(
|
||||
& manager->sizes,
|
||||
(FTC_MruNode_CompareFunc) ftc_size_node_compare_faceid,
|
||||
node->face_id );
|
||||
|
||||
/* all right, we can discard the face now */
|
||||
FT_Done_Face( face );
|
||||
node->face = NULL;
|
||||
FT_Done_Face( node->face );
|
||||
node->face = NULL;
|
||||
node->face_id = NULL;
|
||||
|
||||
FT_FREE( node );
|
||||
}
|
||||
|
||||
|
||||
FT_CALLBACK_TABLE_DEF
|
||||
const FT_LruList_ClassRec ftc_face_list_class =
|
||||
FT_CALLBACK_DEF( FT_Bool )
|
||||
ftc_face_node_compare( FTC_FaceNode node,
|
||||
FTC_FaceID face_id )
|
||||
{
|
||||
sizeof ( FT_LruListRec ),
|
||||
(FT_LruList_InitFunc)0,
|
||||
(FT_LruList_DoneFunc)0,
|
||||
return FT_BOOL( node->face_id == face_id );
|
||||
}
|
||||
|
||||
sizeof ( FTC_FaceNodeRec ),
|
||||
(FT_LruNode_InitFunc) ftc_face_node_init,
|
||||
(FT_LruNode_DoneFunc) ftc_face_node_done,
|
||||
(FT_LruNode_FlushFunc) 0, /* no flushing needed */
|
||||
(FT_LruNode_CompareFunc)0, /* direct comparison of FTC_FaceID handles */
|
||||
|
||||
static const FTC_MruListClassRec ftc_face_list_class =
|
||||
{
|
||||
sizeof( FTC_FaceNodeRec),
|
||||
|
||||
(FTC_MruNode_CompareFunc) ftc_face_node_compare,
|
||||
(FTC_MruNode_InitFunc) ftc_face_node_init,
|
||||
(FTC_MruNode_ResetFunc) NULL,
|
||||
(FTC_MruNode_DoneFunc) ftc_face_node_done
|
||||
};
|
||||
|
||||
|
||||
|
||||
/* documentation is in ftcache.h */
|
||||
|
||||
FT_EXPORT_DEF( FT_Error )
|
||||
FTC_Manager_Lookup_Face( FTC_Manager manager,
|
||||
FTC_FaceID face_id,
|
||||
FT_Face *aface )
|
||||
FTC_Manager_LookupFace( FTC_Manager manager,
|
||||
FTC_FaceID face_id,
|
||||
FT_Face *aface )
|
||||
{
|
||||
FT_Error error;
|
||||
FTC_FaceNode node;
|
||||
@ -146,9 +269,9 @@
|
||||
if ( !manager )
|
||||
return FTC_Err_Invalid_Cache_Handle;
|
||||
|
||||
error = FT_LruList_Lookup( manager->faces_list,
|
||||
(FT_LruKey)face_id,
|
||||
(FT_LruNode*)&node );
|
||||
error = FTC_MruList_Lookup( &manager->faces,
|
||||
face_id,
|
||||
(FTC_MruNode*) &node );
|
||||
if ( !error )
|
||||
*aface = node->face;
|
||||
|
||||
@ -156,281 +279,6 @@
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/***** *****/
|
||||
/***** SIZES LRU IMPLEMENTATION *****/
|
||||
/***** *****/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
|
||||
typedef struct FTC_SizeQueryRec_
|
||||
{
|
||||
FT_Face face;
|
||||
FT_UInt width;
|
||||
FT_UInt height;
|
||||
|
||||
} FTC_SizeQueryRec, *FTC_SizeQuery;
|
||||
|
||||
|
||||
FT_CALLBACK_DEF( FT_Error )
|
||||
ftc_size_node_init( FTC_SizeNode node,
|
||||
FTC_SizeQuery query )
|
||||
{
|
||||
FT_Face face = query->face;
|
||||
FT_Size size;
|
||||
FT_Error error;
|
||||
|
||||
|
||||
node->size = NULL;
|
||||
error = FT_New_Size( face, &size );
|
||||
if ( !error )
|
||||
{
|
||||
FT_Activate_Size( size );
|
||||
error = FT_Set_Pixel_Sizes( query->face,
|
||||
query->width,
|
||||
query->height );
|
||||
if ( error )
|
||||
FT_Done_Size( size );
|
||||
else
|
||||
node->size = size;
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
FT_CALLBACK_DEF( void )
|
||||
ftc_size_node_done( FTC_SizeNode node )
|
||||
{
|
||||
if ( node->size )
|
||||
{
|
||||
FT_Done_Size( node->size );
|
||||
node->size = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
FT_CALLBACK_DEF( FT_Error )
|
||||
ftc_size_node_flush( FTC_SizeNode node,
|
||||
FTC_SizeQuery query )
|
||||
{
|
||||
FT_Size size = node->size;
|
||||
FT_Error error;
|
||||
|
||||
|
||||
if ( size->face == query->face )
|
||||
{
|
||||
FT_Activate_Size( size );
|
||||
error = FT_Set_Pixel_Sizes( query->face, query->width, query->height );
|
||||
if ( error )
|
||||
{
|
||||
FT_Done_Size( size );
|
||||
node->size = NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
FT_Done_Size( size );
|
||||
node->size = NULL;
|
||||
|
||||
error = ftc_size_node_init( node, query );
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
FT_CALLBACK_DEF( FT_Bool )
|
||||
ftc_size_node_compare( FTC_SizeNode node,
|
||||
FTC_SizeQuery query )
|
||||
{
|
||||
FT_Size size = node->size;
|
||||
|
||||
|
||||
return FT_BOOL( size->face == query->face &&
|
||||
(FT_UInt)size->metrics.x_ppem == query->width &&
|
||||
(FT_UInt)size->metrics.y_ppem == query->height );
|
||||
}
|
||||
|
||||
|
||||
FT_CALLBACK_TABLE_DEF
|
||||
const FT_LruList_ClassRec ftc_size_list_class =
|
||||
{
|
||||
sizeof ( FT_LruListRec ),
|
||||
(FT_LruList_InitFunc)0,
|
||||
(FT_LruList_DoneFunc)0,
|
||||
|
||||
sizeof ( FTC_SizeNodeRec ),
|
||||
(FT_LruNode_InitFunc) ftc_size_node_init,
|
||||
(FT_LruNode_DoneFunc) ftc_size_node_done,
|
||||
(FT_LruNode_FlushFunc) ftc_size_node_flush,
|
||||
(FT_LruNode_CompareFunc)ftc_size_node_compare
|
||||
};
|
||||
|
||||
|
||||
/* documentation is in ftcache.h */
|
||||
|
||||
FT_EXPORT_DEF( FT_Error )
|
||||
FTC_Manager_Lookup_Size( FTC_Manager manager,
|
||||
FTC_Font font,
|
||||
FT_Face *aface,
|
||||
FT_Size *asize )
|
||||
{
|
||||
FT_Error error;
|
||||
|
||||
|
||||
/* check for valid `manager' delayed to FTC_Manager_Lookup_Face() */
|
||||
if ( aface )
|
||||
*aface = 0;
|
||||
|
||||
if ( asize )
|
||||
*asize = 0;
|
||||
|
||||
error = FTC_Manager_Lookup_Face( manager, font->face_id, aface );
|
||||
if ( !error )
|
||||
{
|
||||
FTC_SizeQueryRec query;
|
||||
FTC_SizeNode node;
|
||||
|
||||
|
||||
query.face = *aface;
|
||||
query.width = font->pix_width;
|
||||
query.height = font->pix_height;
|
||||
|
||||
error = FT_LruList_Lookup( manager->sizes_list,
|
||||
(FT_LruKey)&query,
|
||||
(FT_LruNode*)&node );
|
||||
if ( !error )
|
||||
{
|
||||
/* select the size as the current one for this face */
|
||||
FT_Activate_Size( node->size );
|
||||
|
||||
if ( asize )
|
||||
*asize = node->size;
|
||||
}
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/***** *****/
|
||||
/***** SET TABLE MANAGEMENT *****/
|
||||
/***** *****/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
static void
|
||||
ftc_family_table_init( FTC_FamilyTable table )
|
||||
{
|
||||
table->count = 0;
|
||||
table->size = 0;
|
||||
table->entries = NULL;
|
||||
table->free = FTC_FAMILY_ENTRY_NONE;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
ftc_family_table_done( FTC_FamilyTable table,
|
||||
FT_Memory memory )
|
||||
{
|
||||
FT_FREE( table->entries );
|
||||
table->free = 0;
|
||||
table->count = 0;
|
||||
table->size = 0;
|
||||
}
|
||||
|
||||
|
||||
FT_EXPORT_DEF( FT_Error )
|
||||
ftc_family_table_alloc( FTC_FamilyTable table,
|
||||
FT_Memory memory,
|
||||
FTC_FamilyEntry *aentry )
|
||||
{
|
||||
FTC_FamilyEntry entry;
|
||||
FT_Error error = 0;
|
||||
|
||||
|
||||
/* re-allocate table size when needed */
|
||||
if ( table->free == FTC_FAMILY_ENTRY_NONE && table->count >= table->size )
|
||||
{
|
||||
FT_UInt old_size = table->size;
|
||||
FT_UInt new_size, idx;
|
||||
|
||||
|
||||
if ( old_size == 0 )
|
||||
new_size = 8;
|
||||
else
|
||||
{
|
||||
new_size = old_size * 2;
|
||||
|
||||
/* check for (unlikely) overflow */
|
||||
if ( new_size < old_size )
|
||||
new_size = 65534;
|
||||
}
|
||||
|
||||
if ( FT_RENEW_ARRAY( table->entries, old_size, new_size ) )
|
||||
return error;
|
||||
|
||||
table->size = new_size;
|
||||
|
||||
entry = table->entries + old_size;
|
||||
table->free = old_size;
|
||||
|
||||
for ( idx = old_size; idx + 1 < new_size; idx++, entry++ )
|
||||
{
|
||||
entry->link = idx + 1;
|
||||
entry->index = idx;
|
||||
}
|
||||
|
||||
entry->link = FTC_FAMILY_ENTRY_NONE;
|
||||
entry->index = idx;
|
||||
}
|
||||
|
||||
if ( table->free != FTC_FAMILY_ENTRY_NONE )
|
||||
{
|
||||
entry = table->entries + table->free;
|
||||
table->free = entry->link;
|
||||
}
|
||||
else if ( table->count < table->size )
|
||||
{
|
||||
entry = table->entries + table->count++;
|
||||
}
|
||||
else
|
||||
{
|
||||
FT_ERROR(( "ftc_family_table_alloc: internal bug!" ));
|
||||
return FTC_Err_Invalid_Argument;
|
||||
}
|
||||
|
||||
entry->link = FTC_FAMILY_ENTRY_NONE;
|
||||
table->count++;
|
||||
|
||||
*aentry = entry;
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
FT_EXPORT_DEF( void )
|
||||
ftc_family_table_free( FTC_FamilyTable table,
|
||||
FT_UInt idx )
|
||||
{
|
||||
/* simply add it to the linked list of free entries */
|
||||
if ( idx < table->count )
|
||||
{
|
||||
FTC_FamilyEntry entry = table->entries + idx;
|
||||
|
||||
|
||||
if ( entry->link != FTC_FAMILY_ENTRY_NONE )
|
||||
FT_ERROR(( "ftc_family_table_free: internal bug!\n" ));
|
||||
else
|
||||
{
|
||||
entry->link = table->free;
|
||||
table->free = entry->index;
|
||||
table->count--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
@ -475,41 +323,28 @@
|
||||
if ( max_bytes == 0 )
|
||||
max_bytes = FTC_MAX_BYTES_DEFAULT;
|
||||
|
||||
error = FT_LruList_New( &ftc_face_list_class,
|
||||
max_faces,
|
||||
manager,
|
||||
memory,
|
||||
&manager->faces_list );
|
||||
if ( error )
|
||||
goto Exit;
|
||||
|
||||
error = FT_LruList_New( &ftc_size_list_class,
|
||||
max_sizes,
|
||||
manager,
|
||||
memory,
|
||||
&manager->sizes_list );
|
||||
if ( error )
|
||||
goto Exit;
|
||||
|
||||
manager->library = library;
|
||||
manager->memory = memory;
|
||||
manager->max_weight = max_bytes;
|
||||
manager->cur_weight = 0;
|
||||
|
||||
manager->request_face = requester;
|
||||
manager->request_data = req_data;
|
||||
|
||||
ftc_family_table_init( &manager->families );
|
||||
FTC_MruList_Init( &manager->faces,
|
||||
&ftc_face_list_class,
|
||||
max_faces,
|
||||
manager,
|
||||
memory );
|
||||
|
||||
FTC_MruList_Init( &manager->sizes,
|
||||
&ftc_size_list_class,
|
||||
max_sizes,
|
||||
manager,
|
||||
memory );
|
||||
|
||||
*amanager = manager;
|
||||
|
||||
Exit:
|
||||
if ( error && manager )
|
||||
{
|
||||
FT_LruList_Destroy( manager->faces_list );
|
||||
FT_LruList_Destroy( manager->sizes_list );
|
||||
FT_FREE( manager );
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -526,31 +361,28 @@
|
||||
if ( !manager || !manager->library )
|
||||
return;
|
||||
|
||||
memory = manager->library->memory;
|
||||
memory = manager->memory;
|
||||
|
||||
/* now discard all caches */
|
||||
for (idx = 0; idx < FTC_MAX_CACHES; idx++ )
|
||||
for (idx = manager->num_caches; idx-- > 0; )
|
||||
{
|
||||
FTC_Cache cache = manager->caches[idx];
|
||||
|
||||
|
||||
if ( cache )
|
||||
{
|
||||
cache->clazz->cache_done( cache );
|
||||
cache->clazz.cache_done( cache );
|
||||
FT_FREE( cache );
|
||||
manager->caches[idx] = 0;
|
||||
manager->caches[idx] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* discard families table */
|
||||
ftc_family_table_done( &manager->families, memory );
|
||||
manager->num_caches = 0;
|
||||
|
||||
/* discard faces and sizes */
|
||||
FT_LruList_Destroy( manager->faces_list );
|
||||
manager->faces_list = 0;
|
||||
FTC_MruList_Done( &manager->sizes );
|
||||
FTC_MruList_Done( &manager->faces );
|
||||
|
||||
FT_LruList_Destroy( manager->sizes_list );
|
||||
manager->sizes_list = 0;
|
||||
manager->library = NULL;
|
||||
manager->memory = NULL;
|
||||
|
||||
FT_FREE( manager );
|
||||
}
|
||||
@ -563,8 +395,8 @@
|
||||
{
|
||||
if ( manager )
|
||||
{
|
||||
FT_LruList_Reset( manager->sizes_list );
|
||||
FT_LruList_Reset( manager->faces_list );
|
||||
FTC_MruList_Reset( &manager->sizes );
|
||||
FTC_MruList_Reset( &manager->faces );
|
||||
}
|
||||
/* XXX: FIXME: flush the caches? */
|
||||
}
|
||||
@ -576,7 +408,7 @@
|
||||
FTC_Manager_Check( FTC_Manager manager )
|
||||
{
|
||||
FTC_Node node, first;
|
||||
|
||||
|
||||
|
||||
first = manager->nodes_list;
|
||||
|
||||
@ -584,23 +416,20 @@
|
||||
if ( first )
|
||||
{
|
||||
FT_ULong weight = 0;
|
||||
|
||||
|
||||
|
||||
node = first;
|
||||
|
||||
do
|
||||
{
|
||||
FTC_FamilyEntry entry = manager->families.entries + node->fam_index;
|
||||
FTC_Cache cache;
|
||||
FTC_Cache cache = manager->caches + node->cache_index;
|
||||
|
||||
if ( (FT_UInt)node->fam_index >= manager->families.count ||
|
||||
entry->link != FTC_FAMILY_ENTRY_NONE )
|
||||
FT_ERROR(( "FTC_Manager_Check: invalid node (family index = %ld\n",
|
||||
node->fam_index ));
|
||||
if ( (FT_UInt)node->cache_index >= manager->num_caches )
|
||||
FT_ERROR(( "FTC_Manager_Check: invalid node (cache index = %ld\n",
|
||||
node->cache_index ));
|
||||
else
|
||||
{
|
||||
cache = entry->cache;
|
||||
weight += cache->clazz->node_weight( node, cache );
|
||||
weight += cache->clazz.node_weight( node, cache );
|
||||
}
|
||||
|
||||
node = node->mru_next;
|
||||
@ -685,8 +514,8 @@
|
||||
/* documentation is in ftcmanag.h */
|
||||
|
||||
FT_EXPORT_DEF( FT_Error )
|
||||
FTC_Manager_Register_Cache( FTC_Manager manager,
|
||||
FTC_Cache_Class clazz,
|
||||
FTC_Manager_RegisterCache( FTC_Manager manager,
|
||||
FTC_CacheClass clazz,
|
||||
FTC_Cache *acache )
|
||||
{
|
||||
FT_Error error = FTC_Err_Invalid_Argument;
|
||||
@ -695,50 +524,36 @@
|
||||
|
||||
if ( manager && clazz && acache )
|
||||
{
|
||||
FT_Memory memory = manager->library->memory;
|
||||
FT_UInt idx = 0;
|
||||
FT_Memory memory = manager->memory;
|
||||
|
||||
|
||||
/* check for an empty cache slot in the manager's table */
|
||||
for ( idx = 0; idx < FTC_MAX_CACHES; idx++ )
|
||||
{
|
||||
if ( manager->caches[idx] == 0 )
|
||||
break;
|
||||
}
|
||||
|
||||
/* return an error if there are too many registered caches */
|
||||
if ( idx >= FTC_MAX_CACHES )
|
||||
if ( manager->num_caches >= FTC_MAX_CACHES )
|
||||
{
|
||||
error = FTC_Err_Too_Many_Caches;
|
||||
FT_ERROR(( "FTC_Manager_Register_Cache:" ));
|
||||
FT_ERROR(( " too many registered caches\n" ));
|
||||
FT_ERROR(( "%s: too many registered caches\n",
|
||||
"FTC_Manager_Register_Cache" ));
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
if ( !FT_ALLOC( cache, clazz->cache_size ) )
|
||||
{
|
||||
cache->manager = manager;
|
||||
cache->memory = memory;
|
||||
cache->clazz = clazz;
|
||||
cache->manager = manager;
|
||||
cache->memory = memory;
|
||||
cache->clazz = clazz[0];
|
||||
cache->org_class = clazz;
|
||||
|
||||
/* THIS IS VERY IMPORTANT! IT WILL WRETCH THE MANAGER */
|
||||
/* IF IT IS NOT SET CORRECTLY */
|
||||
cache->cache_index = idx;
|
||||
cache->index = manager->num_caches;
|
||||
|
||||
if ( clazz->cache_init )
|
||||
error = clazz->cache_init( cache );
|
||||
if ( error )
|
||||
{
|
||||
error = clazz->cache_init( cache );
|
||||
if ( error )
|
||||
{
|
||||
if ( clazz->cache_done )
|
||||
clazz->cache_done( cache );
|
||||
|
||||
FT_FREE( cache );
|
||||
goto Exit;
|
||||
}
|
||||
clazz->cache_done( cache );
|
||||
FT_FREE( cache );
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
manager->caches[idx] = cache;
|
||||
manager->caches[ manager->num_caches++ ] = cache;
|
||||
}
|
||||
}
|
||||
|
||||
@ -748,17 +563,65 @@
|
||||
}
|
||||
|
||||
|
||||
FT_EXPORT_DEF( FT_UInt )
|
||||
FTC_Manager_FlushN( FTC_Manager manager,
|
||||
FT_UInt count )
|
||||
{
|
||||
FTC_Node first = manager->nodes_list;
|
||||
FTC_Node node;
|
||||
FT_UInt result;
|
||||
|
||||
/* try to remove "count" nodes from the list */
|
||||
if ( first == NULL ) /* empty list! */
|
||||
return 0;
|
||||
|
||||
/* go to last node - it's a circular list */
|
||||
node = first->mru_prev;
|
||||
for ( result = 0; result < count; )
|
||||
{
|
||||
FTC_Node prev = node->mru_prev;
|
||||
|
||||
|
||||
/* don't touch locked nodes */
|
||||
if ( node->ref_count <= 0 )
|
||||
{
|
||||
ftc_node_destroy( node, manager );
|
||||
result++;
|
||||
}
|
||||
|
||||
if ( prev == manager->nodes_list )
|
||||
break;
|
||||
|
||||
node = prev;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
FT_EXPORT_DEF( void )
|
||||
FTC_Manager_RemoveFaceID( FTC_Manager manager,
|
||||
FTC_FaceID face_id )
|
||||
{
|
||||
FT_UInt nn;
|
||||
|
||||
/* this will remove all FTC_SizeNode that correspond to
|
||||
* the face_id as well
|
||||
*/
|
||||
FTC_MruList_RemoveSelection( &manager->faces, NULL, face_id );
|
||||
|
||||
for ( nn = 0; nn < manager->num_caches; nn++ )
|
||||
FTC_Cache_RemoveFaceID( manager->caches[nn], face_id );
|
||||
}
|
||||
|
||||
|
||||
/* documentation is in ftcmanag.h */
|
||||
|
||||
FT_EXPORT_DEF( void )
|
||||
FTC_Node_Unref( FTC_Node node,
|
||||
FTC_Manager manager )
|
||||
{
|
||||
if ( node && (FT_UInt)node->fam_index < manager->families.count &&
|
||||
manager->families.entries[node->fam_index].cache )
|
||||
{
|
||||
if ( node && (FT_UInt)node->cache_index < manager->num_caches )
|
||||
node->ref_count--;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
204
src/cache/ftcmru.c
vendored
Normal file
204
src/cache/ftcmru.c
vendored
Normal file
@ -0,0 +1,204 @@
|
||||
#include <ft2build.h>
|
||||
#include FT_CACHE_H
|
||||
#include FT_CACHE_INTERNAL_MRU_H
|
||||
#include FT_INTERNAL_OBJECTS_H
|
||||
#include FT_INTERNAL_DEBUG_H
|
||||
|
||||
#include "ftcerror.h"
|
||||
|
||||
FT_EXPORT_DEF( void )
|
||||
FTC_MruList_Init( FTC_MruList list,
|
||||
FTC_MruListClass clazz,
|
||||
FT_UInt max_nodes,
|
||||
FT_Pointer data,
|
||||
FT_Memory memory )
|
||||
{
|
||||
list->num_nodes = 0;
|
||||
list->max_nodes = max_nodes;
|
||||
list->nodes = NULL;
|
||||
list->clazz = *clazz;
|
||||
list->data = data;
|
||||
list->memory = memory;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
ftc_mrulist_free_nodes( FTC_MruList list,
|
||||
FTC_MruNode *plist )
|
||||
{
|
||||
FT_Memory memory = list->memory;
|
||||
|
||||
while ( *plist )
|
||||
{
|
||||
FTC_MruNode node = *plist;
|
||||
|
||||
*plist = node->next;
|
||||
|
||||
if ( list->clazz.node_done )
|
||||
list->clazz.node_done( node, list->data );
|
||||
|
||||
FT_FREE( node );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
FT_EXPORT( void )
|
||||
FTC_MruList_Reset( FTC_MruList list )
|
||||
{
|
||||
ftc_mrulist_free_nodes( list, &list->nodes );
|
||||
list->num_nodes = 0;
|
||||
}
|
||||
|
||||
|
||||
FT_EXPORT( void )
|
||||
FTC_MruList_Done( FTC_MruList list )
|
||||
{
|
||||
FTC_MruList_Reset( list );
|
||||
}
|
||||
|
||||
|
||||
FT_EXPORT( FT_Error )
|
||||
FTC_MruList_Lookup( FTC_MruList list,
|
||||
FT_Pointer key,
|
||||
FTC_MruNode *anode )
|
||||
{
|
||||
FT_Memory memory = list->memory;
|
||||
FTC_MruNode_CompareFunc compare = list->clazz.node_compare;
|
||||
FTC_MruNode *plast, *pnode, *pfirst;
|
||||
FTC_MruNode node;
|
||||
FT_Error error = 0;
|
||||
|
||||
pfirst = &list->nodes;
|
||||
plast = pnode = pfirst;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
node = *pnode;
|
||||
if ( node == NULL )
|
||||
goto NewNode;
|
||||
if ( compare( node, key ) )
|
||||
break;
|
||||
plast = pnode;
|
||||
pnode = &node->next;
|
||||
}
|
||||
|
||||
if ( node != *pfirst )
|
||||
{
|
||||
*pnode = node->next;
|
||||
node->next = *pfirst;
|
||||
*pfirst = node;
|
||||
}
|
||||
goto Exit;
|
||||
|
||||
NewNode:
|
||||
if ( list->max_nodes > 0 && list->num_nodes >= list->max_nodes )
|
||||
{
|
||||
node = *plast;
|
||||
|
||||
if ( node )
|
||||
{
|
||||
*plast = NULL;
|
||||
list->num_nodes--;
|
||||
|
||||
if ( list->clazz.node_reset )
|
||||
{
|
||||
error = list->clazz.node_reset( node, key, list->data );
|
||||
if ( !error ) goto AddNode;
|
||||
}
|
||||
|
||||
list->clazz.node_done( node, list->data );
|
||||
}
|
||||
}
|
||||
else if ( FT_ALLOC( node, list->clazz.node_size ) )
|
||||
goto Exit;
|
||||
|
||||
error = list->clazz.node_init( node, key, list->data );
|
||||
if ( error )
|
||||
{
|
||||
if ( list->clazz.node_done )
|
||||
list->clazz.node_done( node, list->data );
|
||||
|
||||
FT_FREE( node );
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
AddNode:
|
||||
node->next = list->nodes;
|
||||
list->nodes = node;
|
||||
list->num_nodes++;
|
||||
|
||||
Exit:
|
||||
*anode = node;
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
FT_EXPORT_DEF( void )
|
||||
FTC_MruList_Remove( FTC_MruList list,
|
||||
FTC_MruNode node )
|
||||
{
|
||||
FTC_MruNode *pnode = &list->nodes;
|
||||
|
||||
for ( ;; )
|
||||
{
|
||||
if ( *pnode == NULL ) /* should not happen !! */
|
||||
{
|
||||
FT_ERROR(( "%s: trying to remove unknown node !!\n",
|
||||
"FTC_MruList_Remove" ));
|
||||
return;
|
||||
}
|
||||
|
||||
if ( *pnode == node )
|
||||
break;
|
||||
|
||||
pnode = &node->next;
|
||||
}
|
||||
|
||||
*pnode = node->next;
|
||||
node->next = NULL;
|
||||
list->num_nodes--;
|
||||
|
||||
{
|
||||
FT_Memory memory = list->memory;
|
||||
|
||||
if ( list->clazz.node_done )
|
||||
list->clazz.node_done( node, list->data );
|
||||
|
||||
FT_FREE( node );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
FT_EXPORT_DEF( void )
|
||||
FTC_MruList_RemoveSelection( FTC_MruList list,
|
||||
FTC_MruNode_CompareFunc select,
|
||||
FT_Pointer key )
|
||||
{
|
||||
FTC_MruNode *pnode = &list->nodes;
|
||||
FTC_MruNode node, free = NULL;;
|
||||
|
||||
if ( select )
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
FTC_MruNode node = *pnode;
|
||||
|
||||
if ( node == NULL )
|
||||
break;
|
||||
|
||||
if ( select( node, key ) )
|
||||
{
|
||||
*pnode = node->next;
|
||||
node->next = free;
|
||||
free = node;
|
||||
}
|
||||
else
|
||||
pnode = &node->next;
|
||||
}
|
||||
}
|
||||
|
||||
ftc_mrulist_free_nodes( list, &free );
|
||||
}
|
||||
|
||||
/* END */
|
||||
|
539
src/cache/ftcsbits.c
vendored
539
src/cache/ftcsbits.c
vendored
@ -18,8 +18,7 @@
|
||||
|
||||
#include <ft2build.h>
|
||||
#include FT_CACHE_H
|
||||
#include FT_CACHE_SMALL_BITMAPS_H
|
||||
#include FT_CACHE_INTERNAL_GLYPH_H
|
||||
#include FT_CACHE_INTERNAL_SBITS_H
|
||||
#include FT_INTERNAL_OBJECTS_H
|
||||
#include FT_INTERNAL_DEBUG_H
|
||||
#include FT_ERRORS_H
|
||||
@ -27,47 +26,6 @@
|
||||
#include "ftcerror.h"
|
||||
|
||||
|
||||
#define FTC_SBIT_ITEMS_PER_NODE 16
|
||||
|
||||
|
||||
typedef struct FTC_SBitNodeRec_* FTC_SBitNode;
|
||||
|
||||
typedef struct FTC_SBitNodeRec_
|
||||
{
|
||||
FTC_GlyphNodeRec gnode;
|
||||
FTC_SBitRec sbits[FTC_SBIT_ITEMS_PER_NODE];
|
||||
|
||||
} FTC_SBitNodeRec;
|
||||
|
||||
|
||||
#define FTC_SBIT_NODE( x ) ( (FTC_SBitNode)( x ) )
|
||||
|
||||
|
||||
typedef struct FTC_SBitQueryRec_
|
||||
{
|
||||
FTC_GlyphQueryRec gquery;
|
||||
FTC_ImageTypeRec type;
|
||||
|
||||
} FTC_SBitQueryRec, *FTC_SBitQuery;
|
||||
|
||||
|
||||
#define FTC_SBIT_QUERY( x ) ( (FTC_SBitQuery)( x ) )
|
||||
|
||||
|
||||
typedef struct FTC_SBitFamilyRec_* FTC_SBitFamily;
|
||||
|
||||
/* sbit family structure */
|
||||
typedef struct FTC_SBitFamilyRec_
|
||||
{
|
||||
FTC_GlyphFamilyRec gfam;
|
||||
FTC_ImageTypeRec type;
|
||||
|
||||
} FTC_SBitFamilyRec;
|
||||
|
||||
|
||||
#define FTC_SBIT_FAMILY( x ) ( (FTC_SBitFamily)( x ) )
|
||||
#define FTC_SBIT_FAMILY_MEMORY( x ) FTC_GLYPH_FAMILY_MEMORY( &( x )->cset )
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
@ -100,173 +58,188 @@
|
||||
}
|
||||
|
||||
|
||||
FT_CALLBACK_DEF( void )
|
||||
ftc_sbit_node_done( FTC_SBitNode snode,
|
||||
FTC_Cache cache )
|
||||
FT_EXPORT_DEF( void )
|
||||
FTC_SNode_Free( FTC_SNode snode,
|
||||
FTC_Cache cache )
|
||||
{
|
||||
FTC_SBit sbit = snode->sbits;
|
||||
FT_UInt count = FTC_GLYPH_NODE( snode )->item_count;
|
||||
FT_UInt count = snode->count;
|
||||
FT_Memory memory = cache->memory;
|
||||
|
||||
|
||||
for ( ; count > 0; sbit++, count-- )
|
||||
FT_FREE( sbit->buffer );
|
||||
|
||||
ftc_glyph_node_done( FTC_GLYPH_NODE( snode ), cache );
|
||||
FTC_GNode_Done( FTC_GNODE( snode ), cache );
|
||||
|
||||
FT_FREE( snode );
|
||||
}
|
||||
|
||||
|
||||
static FT_Error
|
||||
ftc_sbit_node_load( FTC_SBitNode snode,
|
||||
FTC_Manager manager,
|
||||
FTC_SBitFamily sfam,
|
||||
FT_UInt gindex,
|
||||
FT_ULong *asize )
|
||||
ftc_snode_load( FTC_SNode snode,
|
||||
FTC_Manager manager,
|
||||
FT_UInt gindex,
|
||||
FT_ULong *asize )
|
||||
{
|
||||
FT_Error error;
|
||||
FTC_GlyphNode gnode = FTC_GLYPH_NODE( snode );
|
||||
FT_Memory memory;
|
||||
FT_Face face;
|
||||
FT_Size size;
|
||||
FTC_SBit sbit;
|
||||
FT_Error error;
|
||||
FTC_GNode gnode = FTC_GNODE( snode );
|
||||
FTC_Family family = gnode->family;
|
||||
FT_Memory memory = manager->memory;
|
||||
FT_Face face;
|
||||
FTC_SBit sbit;
|
||||
FTC_SFamilyClass clazz;
|
||||
|
||||
|
||||
if ( gindex < (FT_UInt)gnode->item_start ||
|
||||
gindex >= (FT_UInt)gnode->item_start + gnode->item_count )
|
||||
if ( (FT_UInt)gindex >= gnode->gindex + snode->count )
|
||||
{
|
||||
FT_ERROR(( "ftc_sbit_node_load: invalid glyph index" ));
|
||||
FT_ERROR(( "ftc_snode_load: invalid glyph index" ));
|
||||
return FTC_Err_Invalid_Argument;
|
||||
}
|
||||
|
||||
memory = manager->library->memory;
|
||||
sbit = snode->sbits + ( gindex - gnode->gindex );
|
||||
clazz = (FTC_SFamilyClass) family->clazz;
|
||||
|
||||
sbit = snode->sbits + ( gindex - gnode->item_start );
|
||||
sbit->buffer = 0;
|
||||
|
||||
error = clazz->family_load_glyph( family, gindex, manager, &face );
|
||||
if ( error )
|
||||
goto BadGlyph;
|
||||
|
||||
error = FTC_Manager_Lookup_Size( manager, &sfam->type.font,
|
||||
&face, &size );
|
||||
if ( !error )
|
||||
{
|
||||
/* by default, indicates a `missing' glyph */
|
||||
sbit->buffer = 0;
|
||||
FT_Int temp;
|
||||
FT_GlyphSlot slot = face->glyph;
|
||||
FT_Bitmap* bitmap = &slot->bitmap;
|
||||
FT_Int xadvance, yadvance;
|
||||
|
||||
error = FT_Load_Glyph( face, gindex, sfam->type.flags | FT_LOAD_RENDER );
|
||||
if ( !error )
|
||||
if ( slot->format != FT_GLYPH_FORMAT_BITMAP )
|
||||
{
|
||||
FT_Int temp;
|
||||
FT_GlyphSlot slot = face->glyph;
|
||||
FT_Bitmap* bitmap = &slot->bitmap;
|
||||
FT_Int xadvance, yadvance;
|
||||
FT_ERROR(( "%s: glyph loaded didn't returned a bitmap !!\n",
|
||||
"ftc_snode_load" ));
|
||||
goto BadGlyph;
|
||||
}
|
||||
|
||||
|
||||
/* check that our values fit into 8-bit containers! */
|
||||
/* If this is not the case, our bitmap is too large */
|
||||
/* and we will leave it as `missing' with sbit.buffer = 0 */
|
||||
/* check that our values fit into 8-bit containers! */
|
||||
/* If this is not the case, our bitmap is too large */
|
||||
/* and we will leave it as `missing' with sbit.buffer = 0 */
|
||||
|
||||
#define CHECK_CHAR( d ) ( temp = (FT_Char)d, temp == d )
|
||||
#define CHECK_BYTE( d ) ( temp = (FT_Byte)d, temp == d )
|
||||
|
||||
/* XXX: FIXME: add support for vertical layouts maybe */
|
||||
/* horizontal advance in pixels */
|
||||
xadvance = ( slot->metrics.horiAdvance + 32 ) >> 6;
|
||||
yadvance = ( slot->metrics.vertAdvance + 32 ) >> 6;
|
||||
|
||||
/* horizontal advance in pixels */
|
||||
xadvance = ( slot->metrics.horiAdvance + 32 ) >> 6;
|
||||
yadvance = ( slot->metrics.vertAdvance + 32 ) >> 6;
|
||||
if ( !CHECK_BYTE( bitmap->rows ) ||
|
||||
!CHECK_BYTE( bitmap->width ) ||
|
||||
!CHECK_CHAR( bitmap->pitch ) ||
|
||||
!CHECK_CHAR( slot->bitmap_left ) ||
|
||||
!CHECK_CHAR( slot->bitmap_top ) ||
|
||||
!CHECK_CHAR( xadvance ) ||
|
||||
!CHECK_CHAR( yadvance ) )
|
||||
goto BadGlyph;
|
||||
|
||||
if ( CHECK_BYTE( bitmap->rows ) &&
|
||||
CHECK_BYTE( bitmap->width ) &&
|
||||
CHECK_CHAR( bitmap->pitch ) &&
|
||||
CHECK_CHAR( slot->bitmap_left ) &&
|
||||
CHECK_CHAR( slot->bitmap_top ) &&
|
||||
CHECK_CHAR( xadvance ) &&
|
||||
CHECK_CHAR( yadvance ) )
|
||||
{
|
||||
sbit->width = (FT_Byte)bitmap->width;
|
||||
sbit->height = (FT_Byte)bitmap->rows;
|
||||
sbit->pitch = (FT_Char)bitmap->pitch;
|
||||
sbit->left = (FT_Char)slot->bitmap_left;
|
||||
sbit->top = (FT_Char)slot->bitmap_top;
|
||||
sbit->xadvance = (FT_Char)xadvance;
|
||||
sbit->yadvance = (FT_Char)yadvance;
|
||||
sbit->format = (FT_Byte)bitmap->pixel_mode;
|
||||
sbit->max_grays = (FT_Byte)(bitmap->num_grays - 1);
|
||||
sbit->width = (FT_Byte)bitmap->width;
|
||||
sbit->height = (FT_Byte)bitmap->rows;
|
||||
sbit->pitch = (FT_Char)bitmap->pitch;
|
||||
sbit->left = (FT_Char)slot->bitmap_left;
|
||||
sbit->top = (FT_Char)slot->bitmap_top;
|
||||
sbit->xadvance = (FT_Char)xadvance;
|
||||
sbit->yadvance = (FT_Char)yadvance;
|
||||
sbit->format = (FT_Byte)bitmap->pixel_mode;
|
||||
sbit->max_grays = (FT_Byte)(bitmap->num_grays - 1);
|
||||
|
||||
#if 0 /* this doesn't work well with embedded bitmaps */
|
||||
/* copy the bitmap into a new buffer -- ignore error */
|
||||
error = ftc_sbit_copy_bitmap( sbit, bitmap, memory );
|
||||
|
||||
/* grab the bitmap when possible - this is a hack! */
|
||||
if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP )
|
||||
{
|
||||
slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP;
|
||||
sbit->buffer = bitmap->buffer;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
/* copy the bitmap into a new buffer -- ignore error */
|
||||
error = ftc_sbit_copy_bitmap( sbit, bitmap, memory );
|
||||
}
|
||||
/* now, compute size */
|
||||
if ( asize )
|
||||
*asize = ABS( sbit->pitch ) * sbit->height;
|
||||
|
||||
/* now, compute size */
|
||||
if ( asize )
|
||||
*asize = ABS( sbit->pitch ) * sbit->height;
|
||||
} /* glyph loading successful */
|
||||
|
||||
} /* glyph dimensions ok */
|
||||
|
||||
} /* glyph loading successful */
|
||||
|
||||
/* ignore the errors that might have occurred -- */
|
||||
/* we mark unloaded glyphs with `sbit.buffer == 0' */
|
||||
/* and 'width == 255', 'height == 0' */
|
||||
/* */
|
||||
if ( error && error != FTC_Err_Out_Of_Memory )
|
||||
{
|
||||
sbit->width = 255;
|
||||
error = 0;
|
||||
/* sbit->buffer == NULL too! */
|
||||
}
|
||||
/* ignore the errors that might have occurred -- */
|
||||
/* we mark unloaded glyphs with `sbit.buffer == 0' */
|
||||
/* and 'width == 255', 'height == 0' */
|
||||
/* */
|
||||
if ( error && error != FTC_Err_Out_Of_Memory )
|
||||
{
|
||||
BadGlyph:
|
||||
sbit->width = 255;
|
||||
sbit->height = 0;
|
||||
sbit->buffer = NULL;
|
||||
error = 0;
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
FT_CALLBACK_DEF( FT_Error )
|
||||
ftc_sbit_node_init( FTC_SBitNode snode,
|
||||
FTC_GlyphQuery gquery,
|
||||
FTC_Cache cache )
|
||||
FT_EXPORT_DEF( FT_Error )
|
||||
FTC_SNode_New( FTC_SNode *psnode,
|
||||
FTC_GQuery gquery,
|
||||
FTC_Cache cache )
|
||||
{
|
||||
FT_Error error;
|
||||
FT_Memory memory = cache->memory;
|
||||
FT_Error error;
|
||||
FTC_SNode snode = NULL;
|
||||
FT_UInt gindex = gquery->gindex;
|
||||
FTC_Family family = gquery->family;
|
||||
|
||||
FTC_SFamilyClass clazz = FTC_CACHE__SFAMILY_CLASS( cache );
|
||||
FT_UInt total;
|
||||
|
||||
ftc_glyph_node_init( FTC_GLYPH_NODE( snode ),
|
||||
gquery->gindex,
|
||||
FTC_GLYPH_FAMILY( gquery->query.family ) );
|
||||
total = clazz->family_get_count( family, cache->manager );
|
||||
if ( total == 0 || gindex >= total )
|
||||
{
|
||||
error = FT_Err_Invalid_Argument;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
error = ftc_sbit_node_load( snode,
|
||||
cache->manager,
|
||||
FTC_SBIT_FAMILY( FTC_QUERY( gquery )->family ),
|
||||
gquery->gindex,
|
||||
NULL );
|
||||
if ( error )
|
||||
ftc_glyph_node_done( FTC_GLYPH_NODE( snode ), cache );
|
||||
if ( !FT_NEW( snode ) )
|
||||
{
|
||||
FT_UInt count, start;
|
||||
|
||||
start = gindex - (gindex % FTC_SBIT_ITEMS_PER_NODE);
|
||||
count = total - start;
|
||||
if ( count > FTC_SBIT_ITEMS_PER_NODE )
|
||||
count = FTC_SBIT_ITEMS_PER_NODE;
|
||||
|
||||
FTC_GNode_Init( FTC_GNODE( snode ), start, family );
|
||||
|
||||
snode->count = count;
|
||||
|
||||
error = ftc_snode_load( snode,
|
||||
cache->manager,
|
||||
gindex,
|
||||
NULL );
|
||||
if ( error )
|
||||
{
|
||||
FTC_SNode_Free( snode, cache );
|
||||
snode = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
Exit:
|
||||
*psnode = snode;
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
FT_CALLBACK_DEF( FT_ULong )
|
||||
ftc_sbit_node_weight( FTC_SBitNode snode )
|
||||
FT_EXPORT_DEF( FT_ULong )
|
||||
FTC_SNode_Weight( FTC_SNode snode )
|
||||
{
|
||||
FTC_GlyphNode gnode = FTC_GLYPH_NODE( snode );
|
||||
FT_UInt count = gnode->item_count;
|
||||
FTC_SBit sbit = snode->sbits;
|
||||
FT_Int pitch;
|
||||
FT_ULong size;
|
||||
FT_UInt count = snode->count;
|
||||
FTC_SBit sbit = snode->sbits;
|
||||
FT_Int pitch;
|
||||
FT_ULong size;
|
||||
|
||||
|
||||
/* the node itself */
|
||||
size = sizeof ( *snode );
|
||||
|
||||
/* the sbit records */
|
||||
size += FTC_GLYPH_NODE( snode )->item_count * sizeof ( FTC_SBitRec );
|
||||
size += count * sizeof( FTC_SBitRec );
|
||||
|
||||
for ( ; count > 0; count--, sbit++ )
|
||||
{
|
||||
@ -285,22 +258,20 @@
|
||||
}
|
||||
|
||||
|
||||
FT_CALLBACK_DEF( FT_Bool )
|
||||
ftc_sbit_node_compare( FTC_SBitNode snode,
|
||||
FTC_SBitQuery squery,
|
||||
FTC_Cache cache )
|
||||
FT_EXPORT_DEF( FT_Bool )
|
||||
FTC_SNode_Compare( FTC_SNode snode,
|
||||
FTC_GQuery gquery,
|
||||
FTC_Cache cache )
|
||||
{
|
||||
FTC_GlyphQuery gquery = FTC_GLYPH_QUERY( squery );
|
||||
FTC_GlyphNode gnode = FTC_GLYPH_NODE( snode );
|
||||
FT_Bool result;
|
||||
FTC_GNode gnode = FTC_GNODE( snode );
|
||||
FT_UInt gindex = gquery->gindex;
|
||||
FT_Bool result;
|
||||
|
||||
|
||||
result = ftc_glyph_node_compare( gnode, gquery );
|
||||
result = FT_BOOL( (FT_UInt)(gindex - gnode->gindex) < snode->count );
|
||||
if ( result )
|
||||
{
|
||||
/* check if we need to load the glyph bitmap now */
|
||||
FT_UInt gindex = gquery->gindex;
|
||||
FTC_SBit sbit = snode->sbits + ( gindex - gnode->item_start );
|
||||
FTC_SBit sbit = snode->sbits + ( gindex - gnode->gindex );
|
||||
|
||||
|
||||
if ( sbit->buffer == NULL && sbit->width != 255 )
|
||||
@ -308,247 +279,15 @@
|
||||
FT_ULong size;
|
||||
|
||||
|
||||
if ( !ftc_sbit_node_load(
|
||||
snode, cache->manager,
|
||||
FTC_SBIT_FAMILY( FTC_QUERY( squery )->family ),
|
||||
gindex, &size ) )
|
||||
if ( !ftc_snode_load( snode, cache->manager,
|
||||
gindex, &size ) )
|
||||
{
|
||||
cache->manager->cur_weight += size;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/***** *****/
|
||||
/***** SBITS FAMILIES *****/
|
||||
/***** *****/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
|
||||
FT_CALLBACK_DEF( FT_Error )
|
||||
ftc_sbit_family_init( FTC_SBitFamily sfam,
|
||||
FTC_SBitQuery squery,
|
||||
FTC_Cache cache )
|
||||
{
|
||||
FTC_Manager manager = cache->manager;
|
||||
FT_Error error;
|
||||
FT_Face face;
|
||||
|
||||
|
||||
sfam->type = squery->type;
|
||||
|
||||
/* we need to compute "cquery.item_total" now */
|
||||
error = FTC_Manager_Lookup_Face( manager,
|
||||
squery->type.font.face_id,
|
||||
&face );
|
||||
if ( !error )
|
||||
{
|
||||
error = ftc_glyph_family_init( FTC_GLYPH_FAMILY( sfam ),
|
||||
FTC_IMAGE_TYPE_HASH( &sfam->type ),
|
||||
FTC_SBIT_ITEMS_PER_NODE,
|
||||
face->num_glyphs,
|
||||
FTC_GLYPH_QUERY( squery ),
|
||||
cache );
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
FT_CALLBACK_DEF( FT_Bool )
|
||||
ftc_sbit_family_compare( FTC_SBitFamily sfam,
|
||||
FTC_SBitQuery squery )
|
||||
{
|
||||
FT_Bool result;
|
||||
|
||||
|
||||
/* we need to set the "cquery.cset" field or our query for */
|
||||
/* faster glyph comparisons in ftc_sbit_node_compare */
|
||||
/* */
|
||||
result = FT_BOOL( FTC_IMAGE_TYPE_COMPARE( &sfam->type, &squery->type ) );
|
||||
if ( result )
|
||||
FTC_GLYPH_FAMILY_FOUND( sfam, squery );
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/***** *****/
|
||||
/***** SBITS CACHE *****/
|
||||
/***** *****/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
|
||||
FT_CALLBACK_TABLE_DEF
|
||||
const FTC_Cache_ClassRec ftc_sbit_cache_class =
|
||||
{
|
||||
sizeof ( FTC_CacheRec ),
|
||||
(FTC_Cache_InitFunc) ftc_cache_init,
|
||||
(FTC_Cache_ClearFunc)ftc_cache_clear,
|
||||
(FTC_Cache_DoneFunc) ftc_cache_done,
|
||||
|
||||
sizeof ( FTC_SBitFamilyRec ),
|
||||
(FTC_Family_InitFunc) ftc_sbit_family_init,
|
||||
(FTC_Family_CompareFunc)ftc_sbit_family_compare,
|
||||
(FTC_Family_DoneFunc) ftc_glyph_family_done,
|
||||
|
||||
sizeof ( FTC_SBitNodeRec ),
|
||||
(FTC_Node_InitFunc) ftc_sbit_node_init,
|
||||
(FTC_Node_WeightFunc) ftc_sbit_node_weight,
|
||||
(FTC_Node_CompareFunc)ftc_sbit_node_compare,
|
||||
(FTC_Node_DoneFunc) ftc_sbit_node_done
|
||||
};
|
||||
|
||||
|
||||
/* documentation is in ftcsbits.h */
|
||||
|
||||
FT_EXPORT_DEF( FT_Error )
|
||||
FTC_SBitCache_New( FTC_Manager manager,
|
||||
FTC_SBitCache *acache )
|
||||
{
|
||||
return FTC_Manager_Register_Cache( manager,
|
||||
&ftc_sbit_cache_class,
|
||||
(FTC_Cache*)acache );
|
||||
}
|
||||
|
||||
|
||||
/* documentation is in ftcsbits.h */
|
||||
|
||||
#ifdef FTC_CACHE_USE_INLINE
|
||||
|
||||
#define GEN_CACHE_FAMILY_COMPARE( f, q, c ) \
|
||||
ftc_sbit_family_compare( (FTC_SBitFamily)(f), (FTC_SBitQuery)(q) )
|
||||
|
||||
#define GEN_CACHE_NODE_COMPARE( n, q, c ) \
|
||||
ftc_sbit_node_compare( (FTC_SBitNode)(n), (FTC_SBitQuery)(q), c )
|
||||
|
||||
#define GEN_CACHE_LOOKUP ftc_sbit_cache_lookup
|
||||
#include "ftccache.i"
|
||||
|
||||
#else /* !FTC_CACHE_USE_INLINE */
|
||||
|
||||
#define ftc_sbit_cache_lookup ftc_cache_lookup
|
||||
|
||||
#endif /* !FTC_CACHE_USE_INLINE */
|
||||
|
||||
FT_EXPORT_DEF( FT_Error )
|
||||
FTC_SBitCache_Lookup( FTC_SBitCache cache,
|
||||
FTC_ImageType type,
|
||||
FT_UInt gindex,
|
||||
FTC_SBit *ansbit,
|
||||
FTC_Node *anode )
|
||||
{
|
||||
FT_Error error;
|
||||
FTC_SBitQueryRec squery;
|
||||
FTC_SBitNode node;
|
||||
|
||||
|
||||
/* other argument checks delayed to ftc_cache_lookup */
|
||||
if ( !ansbit )
|
||||
return FTC_Err_Invalid_Argument;
|
||||
|
||||
*ansbit = NULL;
|
||||
|
||||
if ( anode )
|
||||
*anode = NULL;
|
||||
|
||||
squery.gquery.gindex = gindex;
|
||||
squery.type = *type;
|
||||
|
||||
error = ftc_sbit_cache_lookup( FTC_CACHE( cache ),
|
||||
FTC_QUERY( &squery ),
|
||||
(FTC_Node*)&node );
|
||||
if ( !error )
|
||||
{
|
||||
*ansbit = node->sbits + ( gindex - FTC_GLYPH_NODE( node )->item_start );
|
||||
|
||||
if ( anode )
|
||||
{
|
||||
*anode = FTC_NODE( node );
|
||||
FTC_NODE( node )->ref_count++;
|
||||
}
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
/* backwards-compatibility functions */
|
||||
|
||||
FT_EXPORT_DEF( FT_Error )
|
||||
FTC_SBit_Cache_New( FTC_Manager manager,
|
||||
FTC_SBit_Cache *acache )
|
||||
{
|
||||
return FTC_SBitCache_New( manager, (FTC_SBitCache*)acache );
|
||||
}
|
||||
|
||||
|
||||
FT_EXPORT_DEF( FT_Error )
|
||||
FTC_SBit_Cache_Lookup( FTC_SBit_Cache cache,
|
||||
FTC_Image_Desc* desc,
|
||||
FT_UInt gindex,
|
||||
FTC_SBit *ansbit )
|
||||
{
|
||||
FTC_ImageTypeRec type0;
|
||||
|
||||
|
||||
if ( !desc )
|
||||
return FTC_Err_Invalid_Argument;
|
||||
|
||||
type0.font = desc->font;
|
||||
type0.flags = 0;
|
||||
|
||||
/* convert image type flags to load flags */
|
||||
{
|
||||
FT_UInt load_flags = FT_LOAD_DEFAULT;
|
||||
FT_UInt type = desc->image_type;
|
||||
|
||||
|
||||
/* determine load flags, depending on the font description's */
|
||||
/* image type */
|
||||
|
||||
if ( ftc_image_format( type ) == ftc_image_format_bitmap )
|
||||
{
|
||||
if ( type & ftc_image_flag_monochrome )
|
||||
load_flags |= FT_LOAD_MONOCHROME;
|
||||
|
||||
/* disable embedded bitmaps loading if necessary */
|
||||
if ( type & ftc_image_flag_no_sbits )
|
||||
load_flags |= FT_LOAD_NO_BITMAP;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* we want an outline, don't load embedded bitmaps */
|
||||
load_flags |= FT_LOAD_NO_BITMAP;
|
||||
|
||||
if ( type & ftc_image_flag_unscaled )
|
||||
load_flags |= FT_LOAD_NO_SCALE;
|
||||
}
|
||||
|
||||
/* always render glyphs to bitmaps */
|
||||
load_flags |= FT_LOAD_RENDER;
|
||||
|
||||
if ( type & ftc_image_flag_unhinted )
|
||||
load_flags |= FT_LOAD_NO_HINTING;
|
||||
|
||||
if ( type & ftc_image_flag_autohinted )
|
||||
load_flags |= FT_LOAD_FORCE_AUTOHINT;
|
||||
|
||||
type0.flags = load_flags;
|
||||
}
|
||||
|
||||
return FTC_SBitCache_Lookup( (FTC_SBitCache)cache,
|
||||
&type0,
|
||||
gindex,
|
||||
ansbit,
|
||||
NULL );
|
||||
}
|
||||
|
||||
|
||||
/* END */
|
||||
|
390
src/cache/ftlru.c
vendored
390
src/cache/ftlru.c
vendored
@ -1,390 +0,0 @@
|
||||
/***************************************************************************/
|
||||
/* */
|
||||
/* ftlru.c */
|
||||
/* */
|
||||
/* Simple LRU list-cache (body). */
|
||||
/* */
|
||||
/* Copyright 2000-2001, 2002, 2003 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. */
|
||||
/* */
|
||||
/***************************************************************************/
|
||||
|
||||
|
||||
#include <ft2build.h>
|
||||
#include FT_CACHE_H
|
||||
#include FT_CACHE_INTERNAL_LRU_H
|
||||
#include FT_LIST_H
|
||||
#include FT_INTERNAL_OBJECTS_H
|
||||
#include FT_INTERNAL_DEBUG_H
|
||||
|
||||
#include "ftcerror.h"
|
||||
|
||||
|
||||
FT_EXPORT_DEF( FT_Error )
|
||||
FT_LruList_New( FT_LruList_Class clazz,
|
||||
FT_UInt max_nodes,
|
||||
FT_Pointer user_data,
|
||||
FT_Memory memory,
|
||||
FT_LruList *alist )
|
||||
{
|
||||
FT_Error error;
|
||||
FT_LruList list;
|
||||
|
||||
|
||||
if ( !alist || !clazz )
|
||||
return FTC_Err_Invalid_Argument;
|
||||
|
||||
*alist = NULL;
|
||||
if ( !FT_ALLOC( list, clazz->list_size ) )
|
||||
{
|
||||
/* initialize common fields */
|
||||
list->clazz = clazz;
|
||||
list->memory = memory;
|
||||
list->max_nodes = max_nodes;
|
||||
list->data = user_data;
|
||||
|
||||
if ( clazz->list_init )
|
||||
{
|
||||
error = clazz->list_init( list );
|
||||
if ( error )
|
||||
{
|
||||
if ( clazz->list_done )
|
||||
clazz->list_done( list );
|
||||
|
||||
FT_FREE( list );
|
||||
}
|
||||
}
|
||||
|
||||
*alist = list;
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
FT_EXPORT_DEF( void )
|
||||
FT_LruList_Destroy( FT_LruList list )
|
||||
{
|
||||
FT_Memory memory;
|
||||
FT_LruList_Class clazz;
|
||||
|
||||
|
||||
if ( !list )
|
||||
return;
|
||||
|
||||
memory = list->memory;
|
||||
clazz = list->clazz;
|
||||
|
||||
FT_LruList_Reset( list );
|
||||
|
||||
if ( clazz->list_done )
|
||||
clazz->list_done( list );
|
||||
|
||||
FT_FREE( list );
|
||||
}
|
||||
|
||||
|
||||
FT_EXPORT_DEF( void )
|
||||
FT_LruList_Reset( FT_LruList list )
|
||||
{
|
||||
FT_LruNode node;
|
||||
FT_LruList_Class clazz;
|
||||
FT_Memory memory;
|
||||
|
||||
|
||||
if ( !list )
|
||||
return;
|
||||
|
||||
node = list->nodes;
|
||||
clazz = list->clazz;
|
||||
memory = list->memory;
|
||||
|
||||
while ( node )
|
||||
{
|
||||
FT_LruNode next = node->next;
|
||||
|
||||
|
||||
if ( clazz->node_done )
|
||||
clazz->node_done( node, list->data );
|
||||
|
||||
FT_FREE( node );
|
||||
node = next;
|
||||
}
|
||||
|
||||
list->nodes = NULL;
|
||||
list->num_nodes = 0;
|
||||
}
|
||||
|
||||
|
||||
FT_EXPORT_DEF( FT_Error )
|
||||
FT_LruList_Lookup( FT_LruList list,
|
||||
FT_LruKey key,
|
||||
FT_LruNode *anode )
|
||||
{
|
||||
FT_Error error = 0;
|
||||
FT_LruNode node, *pnode;
|
||||
FT_LruList_Class clazz;
|
||||
FT_LruNode result = NULL;
|
||||
FT_Memory memory;
|
||||
|
||||
|
||||
if ( !list || !key || !anode )
|
||||
return FTC_Err_Invalid_Argument;
|
||||
|
||||
pnode = &list->nodes;
|
||||
node = NULL;
|
||||
clazz = list->clazz;
|
||||
memory = list->memory;
|
||||
|
||||
if ( clazz->node_compare )
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
node = *pnode;
|
||||
if ( node == NULL )
|
||||
break;
|
||||
|
||||
if ( clazz->node_compare( node, key, list->data ) )
|
||||
break;
|
||||
|
||||
pnode = &(*pnode)->next;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
node = *pnode;
|
||||
if ( node == NULL )
|
||||
break;
|
||||
|
||||
if ( node->key == key )
|
||||
break;
|
||||
|
||||
pnode = &(*pnode)->next;
|
||||
}
|
||||
}
|
||||
|
||||
if ( node )
|
||||
{
|
||||
/* move element to top of list */
|
||||
if ( list->nodes != node )
|
||||
{
|
||||
*pnode = node->next;
|
||||
node->next = list->nodes;
|
||||
list->nodes = node;
|
||||
}
|
||||
result = node;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
/* Since we haven't found the relevant element in our LRU list,
|
||||
* we're going to "create" a new one.
|
||||
*
|
||||
* The following code is a bit special, because it tries to handle
|
||||
* out-of-memory conditions (OOM) in an intelligent way.
|
||||
*
|
||||
* More precisely, if not enough memory is available to create a
|
||||
* new node or "flush" an old one, we need to remove the oldest
|
||||
* elements from our list, and try again. Since several tries may
|
||||
* be necessary, a loop is needed.
|
||||
*
|
||||
* This loop will only exit when:
|
||||
*
|
||||
* - a new node was successfully created, or an old node flushed
|
||||
* - an error other than FTC_Err_Out_Of_Memory is detected
|
||||
* - the list of nodes is empty, and it isn't possible to create
|
||||
* new nodes
|
||||
*
|
||||
* On each unsuccessful attempt, one node will be removed from the list.
|
||||
*
|
||||
*/
|
||||
|
||||
{
|
||||
FT_Int drop_last = ( list->max_nodes > 0 &&
|
||||
list->num_nodes >= list->max_nodes );
|
||||
|
||||
for (;;)
|
||||
{
|
||||
node = NULL;
|
||||
|
||||
/* If "drop_last" is true, we should free the last node in
|
||||
* the list to make room for a new one. Note that we reuse
|
||||
* its memory block to save allocation calls.
|
||||
*/
|
||||
if ( drop_last )
|
||||
{
|
||||
/* find the last node in the list
|
||||
*/
|
||||
pnode = &list->nodes;
|
||||
node = *pnode;
|
||||
|
||||
if ( node == NULL )
|
||||
{
|
||||
FT_ASSERT( list->num_nodes == 0 );
|
||||
error = FTC_Err_Out_Of_Memory;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
FT_ASSERT( list->num_nodes > 0 );
|
||||
|
||||
while ( node->next )
|
||||
{
|
||||
pnode = &node->next;
|
||||
node = *pnode;
|
||||
}
|
||||
|
||||
/* Remove it from the list, and try to "flush" it. Doing this will
|
||||
* save a significant number of dynamic allocations compared to
|
||||
* a classic destroy/create cycle.
|
||||
*/
|
||||
*pnode = NULL;
|
||||
list->num_nodes--;
|
||||
|
||||
if ( clazz->node_flush )
|
||||
{
|
||||
error = clazz->node_flush( node, key, list->data );
|
||||
if ( !error )
|
||||
goto Success;
|
||||
|
||||
/* Note that if an error occured during the flush, we need to
|
||||
* finalize it since it is potentially in incomplete state.
|
||||
*/
|
||||
}
|
||||
|
||||
/* We finalize, but do not destroy the last node, we
|
||||
* simply reuse its memory block!
|
||||
*/
|
||||
if ( clazz->node_done )
|
||||
clazz->node_done( node, list->data );
|
||||
|
||||
FT_MEM_ZERO( node, clazz->node_size );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Try to allocate a new node when "drop_last" is not TRUE.
|
||||
* This usually happens on the first pass, when the LRU list
|
||||
* is not already full.
|
||||
*/
|
||||
if ( FT_ALLOC( node, clazz->node_size ) )
|
||||
goto Fail;
|
||||
}
|
||||
|
||||
FT_ASSERT( node != NULL );
|
||||
|
||||
node->key = key;
|
||||
error = clazz->node_init( node, key, list->data );
|
||||
if ( error )
|
||||
{
|
||||
if ( clazz->node_done )
|
||||
clazz->node_done( node, list->data );
|
||||
|
||||
FT_FREE( node );
|
||||
goto Fail;
|
||||
}
|
||||
|
||||
Success:
|
||||
result = node;
|
||||
|
||||
node->next = list->nodes;
|
||||
list->nodes = node;
|
||||
list->num_nodes++;
|
||||
goto Exit;
|
||||
|
||||
Fail:
|
||||
if ( error != FTC_Err_Out_Of_Memory )
|
||||
goto Exit;
|
||||
|
||||
drop_last = 1;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
Exit:
|
||||
*anode = result;
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
FT_EXPORT_DEF( void )
|
||||
FT_LruList_Remove( FT_LruList list,
|
||||
FT_LruNode node )
|
||||
{
|
||||
FT_LruNode *pnode;
|
||||
|
||||
|
||||
if ( !list || !node )
|
||||
return;
|
||||
|
||||
pnode = &list->nodes;
|
||||
for (;;)
|
||||
{
|
||||
if ( *pnode == node )
|
||||
{
|
||||
FT_Memory memory = list->memory;
|
||||
FT_LruList_Class clazz = list->clazz;
|
||||
|
||||
|
||||
*pnode = node->next;
|
||||
node->next = NULL;
|
||||
|
||||
if ( clazz->node_done )
|
||||
clazz->node_done( node, list->data );
|
||||
|
||||
FT_FREE( node );
|
||||
list->num_nodes--;
|
||||
break;
|
||||
}
|
||||
|
||||
pnode = &(*pnode)->next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
FT_EXPORT_DEF( void )
|
||||
FT_LruList_Remove_Selection( FT_LruList list,
|
||||
FT_LruNode_SelectFunc select_func,
|
||||
FT_Pointer select_data )
|
||||
{
|
||||
FT_LruNode *pnode, node;
|
||||
FT_LruList_Class clazz;
|
||||
FT_Memory memory;
|
||||
|
||||
|
||||
if ( !list || !select_func )
|
||||
return;
|
||||
|
||||
memory = list->memory;
|
||||
clazz = list->clazz;
|
||||
pnode = &list->nodes;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
node = *pnode;
|
||||
if ( node == NULL )
|
||||
break;
|
||||
|
||||
if ( select_func( node, select_data, list->data ) )
|
||||
{
|
||||
*pnode = node->next;
|
||||
node->next = NULL;
|
||||
|
||||
if ( clazz->node_done )
|
||||
clazz->node_done( node, list );
|
||||
|
||||
FT_FREE( node );
|
||||
list->num_nodes--;
|
||||
}
|
||||
else
|
||||
pnode = &(*pnode)->next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* END */
|
6
src/cache/rules.mk
vendored
6
src/cache/rules.mk
vendored
@ -25,8 +25,9 @@ CACHE_COMPILE := $(FT_COMPILE) $I$(subst /,$(COMPILER_SEP),$(CACHE_DIR))
|
||||
|
||||
# Cache driver sources (i.e., C files)
|
||||
#
|
||||
CACHE_DRV_SRC := $(CACHE_DIR)/ftlru.c \
|
||||
CACHE_DRV_SRC := $(CACHE_DIR)/ftcmru.c \
|
||||
$(CACHE_DIR)/ftcmanag.c \
|
||||
$(CACHE_DIR)/ftcbasic.c \
|
||||
$(CACHE_DIR)/ftccache.c \
|
||||
$(CACHE_DIR)/ftcglyph.c \
|
||||
$(CACHE_DIR)/ftcsbits.c \
|
||||
@ -35,10 +36,11 @@ CACHE_DRV_SRC := $(CACHE_DIR)/ftlru.c \
|
||||
|
||||
# Cache driver headers
|
||||
#
|
||||
CACHE_DRV_H := $(CACHE_H_DIR)/ftlru.h \
|
||||
CACHE_DRV_H := $(CACHE_H_DIR)/ftcmru.h \
|
||||
$(CACHE_H_DIR)/ftcmanag.h \
|
||||
$(CACHE_H_DIR)/ftcglyph.h \
|
||||
$(CACHE_H_DIR)/ftcimage.h \
|
||||
$(CACHE_H_DIR)/ftccmap.h \
|
||||
$(CACHE_DIR)/ftcerror.h
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user