ref: 57ecae22a7b837d486bb03eda944736780ce0868
parent: 9e185f32ce3e99c31d66c24e75d5033a3a3ac244
author: David Turner <[email protected]>
date: Fri Dec 19 16:23:58 EST 2003
new version of the cache sub-system - still under debugging
--- a/include/freetype/cache/ftccache.h
+++ b/include/freetype/cache/ftccache.h
@@ -20,10 +20,7 @@
#define __FTCCACHE_H__
-/* define to allow cache lookup inlining */
-#define FTC_CACHE_USE_INLINE
-
FT_BEGIN_HEADER
/* handle to cache object */
@@ -30,15 +27,8 @@
typedef struct FTC_CacheRec_* FTC_Cache;
/* handle to cache class */
- typedef const struct FTC_Cache_ClassRec_* FTC_Cache_Class;
+ typedef const struct FTC_CacheClassRec_* FTC_CacheClass;
- /* handle to cache node family */
- typedef struct FTC_FamilyRec_* FTC_Family;
-
- /* handle to cache root query */
- typedef struct FTC_QueryRec_* FTC_Query;
-
-
/*************************************************************************/
/*************************************************************************/
/***** *****/
@@ -66,7 +56,7 @@
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,11 +73,6 @@
/* 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,
@@ -94,98 +79,67 @@
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 *****/
+ /***** CACHE DEFINITIONS *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
- typedef struct FTC_FamilyRec_
- {
- FT_LruNodeRec lru;
- FTC_Cache cache;
- FT_UInt num_nodes;
- FT_UInt fam_index;
+ /* initialize a new cache node */
+ typedef FT_Error (*FTC_Node_NewFunc)( FTC_Node *pnode,
+ FT_Pointer query,
+ FTC_Cache cache );
- } FTC_FamilyRec;
+ 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 );
-#define FTC_FAMILY( x ) ( (FTC_Family)(x) )
-#define FTC_FAMILY_P( x ) ( (FTC_Family*)(x) )
+ typedef void (*FTC_Node_FreeFunc)( FTC_Node node,
+ FTC_Cache cache );
- /*************************************************************************/
- /* */
- /* 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. */
- /* */
+ typedef FT_Error (*FTC_Cache_InitFunc)( FTC_Cache cache );
- /* 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 );
+ typedef void (*FTC_Cache_DoneFunc)( 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 );
+ 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;
- /*************************************************************************/
- /*************************************************************************/
- /***** *****/
- /***** CACHE DEFINITIONS *****/
- /***** *****/
- /*************************************************************************/
- /*************************************************************************/
+ } 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 @@
#define FTC_CACHE_P( x ) ( (FTC_Cache*)(x) )
- /* initialize a given cache */
- typedef FT_Error
- (*FTC_Cache_InitFunc)( FTC_Cache cache );
+ /* default cache initialize */
+ FT_EXPORT( FT_Error )
+ FTC_Cache_Init( 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 */
+ /* default cache finalizer */
FT_EXPORT( void )
- ftc_cache_done( FTC_Cache cache );
+ 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 */
+ /* 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_init( FTC_Cache cache );
+ FTC_Cache_Lookup( FTC_Cache cache,
+ FT_UInt32 hash,
+ FT_Pointer query,
+ FTC_Node *anode );
- /* can be called when the key's hash value has been computed */
- FT_EXPORT( FT_Error )
- ftc_cache_lookup( FTC_Cache cache,
- FTC_Query 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 );
/* */
--- a/include/freetype/cache/ftcglyph.h
+++ b/include/freetype/cache/ftcglyph.h
@@ -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,99 +118,64 @@
#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 )
+#define FTC_FAMILY_START( gfam, gindex ) \
+ ( FTC_FAMILY_CHUNK( gfam, gindex ) * \
+ FTC_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 ) )
-
-
/*************************************************************************/
/* */
/* These functions are exported so that they can be called from */
@@ -149,36 +185,78 @@
/* 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 );
/* */
--- a/include/freetype/cache/ftcimage.h
+++ b/include/freetype/cache/ftcimage.h
@@ -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,283 +38,63 @@
#include <ft2build.h>
#include FT_CACHE_H
+#include FT_CACHE_INTERNAL_GLYPH_H
-
FT_BEGIN_HEADER
- /*************************************************************************/
- /* */
- /* <Section> */
- /* cache_subsystem */
- /* */
- /*************************************************************************/
-
-
- /*************************************************************************/
- /*************************************************************************/
- /*************************************************************************/
- /***** *****/
- /***** IMAGE CACHE OBJECT *****/
- /***** *****/
- /*************************************************************************/
- /*************************************************************************/
- /*************************************************************************/
-
-
- /**************************************************************************
- *
- * @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_ImageTypeRec_
+ /* the FT_Glyph image node type - we store only 1 glyph per node */
+ typedef struct FTC_INodeRec_
{
- FTC_FontRec font;
- FT_Int32 flags;
+ FTC_GNodeRec gnode;
+ FT_Glyph glyph;
- } FTC_ImageTypeRec;
+ } FTC_INodeRec, *FTC_INode;
- typedef struct FTC_ImageTypeRec_* FTC_ImageType;
+#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 );
-#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 );
-
-
- /*************************************************************************/
- /* */
- /* <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_
+ typedef struct FTC_IFamilyClassRec_
{
- FTC_FontRec font;
- FT_UInt image_type;
+ FTC_MruListClassRec clazz;
+ FTC_IFamily_LoadGlyphFunc family_load_glyph;
- } FTC_Image_Desc;
+ } FTC_IFamilyClassRec;
+ typedef const FTC_IFamilyClassRec* FTC_IFamilyClass;
- /*************************************************************************/
- /* */
- /* <Type> */
- /* FTC_Image_Cache */
- /* */
- /* <Description> */
- /* THIS TYPE IS DEPRECATED. Use @FTC_ImageCache instead. */
- /* */
- typedef FTC_ImageCache FTC_Image_Cache;
+#define FTC_IFAMILY_CLASS(x) ((FTC_IFamilyClass)(x))
+#define FTC_CACHE__IFAMILY_CLASS(x) \
+ FTC_IFAMILY_CLASS( FTC_CACHE__GCACHE_CLASS(x)->family_class )
- /*************************************************************************/
- /* */
- /* <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 );
+ /* can be used as a @FTC_Node_FreeFunc */
+ FT_EXPORT( void )
+ FTC_INode_Free( FTC_INode inode,
+ FTC_Cache cache );
-
- /*************************************************************************/
- /* */
- /* <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. */
- /* */
+ /* 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
+ */
FT_EXPORT( FT_Error )
- FTC_Image_Cache_Lookup( FTC_Image_Cache cache,
- FTC_Image_Desc* desc,
- FT_UInt gindex,
- FT_Glyph *aglyph );
+ FTC_INode_New( FTC_INode *pinode,
+ FTC_GQuery gquery,
+ FTC_Cache cache );
+ /* can be used as @FTC_Node_WeightFunc */
+ FT_EXPORT( FT_ULong )
+ FTC_INode_Weight( FTC_INode inode );
+
/* */
FT_END_HEADER
-
#endif /* __FTCIMAGE_H__ */
--- a/include/freetype/cache/ftcmanag.h
+++ b/include/freetype/cache/ftcmanag.h
@@ -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 @@
/*************************************************************************/
-#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,42 +134,57 @@
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 );
+ /* */
- /* can be called to increment a node's reference count */
- FT_EXPORT( void )
- FTC_Node_Ref( FTC_Node node,
- FTC_Manager manager );
+ 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;
- /*************************************************************************/
- /* */
- /* <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 );
+#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 )
+
+
+ FT_EXPORT( FT_Error )
+ FTC_Manager_LookupSize( FTC_Manager manager,
+ FTC_Scaler scaler,
+ FT_Size *asize );
+
/* */
FT_END_HEADER
-
#endif /* __FTCMANAG_H__ */
--- /dev/null
+++ b/include/freetype/cache/ftcmru.h
@@ -1,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 */
--- a/include/freetype/cache/ftcsbits.h
+++ b/include/freetype/cache/ftcsbits.h
@@ -22,250 +22,68 @@
#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 */
- /* */
- /*************************************************************************/
+ typedef struct FTC_SNodeRec_
+ {
+ FTC_GNodeRec gnode;
+ FT_UInt count;
+ FTC_SBitRec sbits[ FTC_SBIT_ITEMS_PER_NODE ];
+ } FTC_SNodeRec, *FTC_SNode;
- /*************************************************************************/
- /* */
- /* <Type> */
- /* FTC_SBit */
- /* */
- /* <Description> */
- /* A handle to a small bitmap descriptor. See the @FTC_SBitRec */
- /* structure for details. */
- /* */
- typedef struct FTC_SBitRec_* FTC_SBit;
+#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
- /*************************************************************************/
- /* */
- /* <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;
+ typedef FT_UInt (*FTC_SFamily_GetCountFunc)( FTC_Family family,
+ FTC_Manager manager );
- FT_Byte format;
- FT_Byte max_grays;
- FT_Short pitch;
- FT_Char xadvance;
- FT_Char yadvance;
+ typedef FT_Error (*FTC_SFamily_LoadGlyphFunc)( FTC_Family family,
+ FT_UInt gindex,
+ FTC_Manager manager,
+ FT_Face *aface );
- FT_Byte* buffer;
+ typedef struct FTC_SFamilyClassRec_
+ {
+ FTC_MruListClassRec clazz;
+ FTC_SFamily_GetCountFunc family_get_count;
+ FTC_SFamily_LoadGlyphFunc family_load_glyph;
- } FTC_SBitRec;
+ } FTC_SFamilyClassRec;
+ typedef const FTC_SFamilyClassRec* FTC_SFamilyClass;
- /*************************************************************************/
- /* */
- /* <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_SFAMILY_CLASS(x) ((FTC_SFamilyClass)(x))
+#define FTC_CACHE__SFAMILY_CLASS(x) \
+ FTC_SFAMILY_CLASS( FTC_CACHE__GCACHE_CLASS(x)->family_class )
- /*************************************************************************/
- /* */
- /* <Type> */
- /* FTC_SBit_Cache */
- /* */
- /* <Description> */
- /* DEPRECATED. Use @FTC_SBitCache instead. */
- /* */
- typedef FTC_SBitCache FTC_SBit_Cache;
+ 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
--- a/include/freetype/cache/ftlru.h
+++ /dev/null
@@ -1,208 +1,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 */
--- a/include/freetype/config/ftheader.h
+++ b/include/freetype/config/ftheader.h
@@ -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>
--- a/include/freetype/config/ftoption.h
+++ b/include/freetype/config/ftoption.h
@@ -277,8 +277,8 @@
/* 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 @@
/* 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
/*************************************************************************/
--- a/include/freetype/ftcache.h
+++ b/include/freetype/ftcache.h
@@ -63,7 +63,7 @@
/* FTC_Face_Requester */
/* */
/* FTC_Manager_New */
- /* FTC_Manager_Lookup_Face */
+ /* FTC_Manager_LookupFace */
/* FTC_Manager_Lookup_Size */
/* */
/* FTC_Node */
@@ -257,29 +257,17 @@
/* 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'). */
+ /* req_data :: A generic pointer that is passed to the requester */
+ /* each time it is called (see @FTC_Face_Requester). */
/* */
- /* 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). */
- /* */
/* <Output> */
/* amanager :: A handle to a new manager object. 0 in case of */
/* failure. */
@@ -331,7 +319,7 @@
/*************************************************************************/
/* */
/* <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 @@
/* 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 @@
/*************************************************************************/
/* */
/* <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! */
+ /* 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! */
/* */
- /* 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. */
+ FT_EXPORT( FT_Error )
+ 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_Manager_Lookup_Size( FTC_Manager manager,
- FTC_Font font,
- FT_Face *aface,
- FT_Size *asize );
+ 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
--- a/include/freetype/ftstroke.h
+++ b/include/freetype/ftstroke.h
@@ -95,12 +95,113 @@
} 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_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_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
--- a/src/autofit/afhints.c
+++ b/src/autofit/afhints.c
@@ -399,6 +399,8 @@
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 )
@@ -405,8 +407,6 @@
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;
--- a/src/autofit/afhints.h
+++ b/src/autofit/afhints.h
@@ -163,7 +163,11 @@
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;
--- a/src/autofit/aflatin.c
+++ b/src/autofit/aflatin.c
@@ -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;
--- a/src/autofit/aftypes.h
+++ b/src/autofit/aftypes.h
@@ -40,14 +40,14 @@
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 @@
/***** *****/
/**************************************************************************/
/**************************************************************************/
-
+
/*
* 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_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 @@
* auto-hinted glyph image
*
*/
-
+
typedef enum
{
AF_SCALER_FLAG_NO_HORIZONTAL = 1, /* disable horizontal hinting */
@@ -152,7 +152,7 @@
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 @@
* 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 @@
{
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 @@
/* 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_UInt32 first;
FT_UInt32 last;
-
+
} AF_Script_UniRangeRec, *AF_Script_UniRange;
-
+
typedef struct AF_ScriptClassRec_
{
--- a/src/base/ftstroke.c
+++ b/src/base/ftstroke.c
@@ -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] );
}
@@ -1424,6 +1449,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,
FT_UInt *anum_contours )
@@ -1446,8 +1499,6 @@
num_points = count1 + count3;
num_contours = count2 + count4;
- stroker->valid = 1;
-
Exit:
*anum_points = num_points;
*anum_contours = num_contours;
@@ -1456,15 +1507,30 @@
FT_EXPORT_DEF( void )
- FT_Stroker_Export( FT_Stroker stroker,
+ FT_Stroker_ExportBorder( FT_Stroker stroker,
+ FT_StrokerBorder border,
FT_Outline* outline )
{
- if ( stroker->valid )
+ if ( border == FT_STROKER_BORDER_LEFT ||
+ border == FT_STROKER_BORDER_RIGHT )
{
- ft_stroke_border_export( stroker->borders + 0, outline );
- ft_stroke_border_export( stroker->borders + 1, outline );
+ 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 )
+ {
+ FT_Stroker_ExportBorder( stroker, FT_STROKER_BORDER_LEFT, outline );
+ FT_Stroker_ExportBorder( stroker, FT_STROKER_BORDER_RIGHT, outline );
+ }
+
+
/*
--- a/src/cache/Jamfile
+++ b/src/cache/Jamfile
@@ -14,7 +14,15 @@
if $(FT2_MULTI)
{
- _sources = ftlru ftcmanag ftccache ftcglyph ftcsbits ftcimage ftccmap ;
+ _sources = ftmru
+ ftcmanag
+ ftccache
+ ftcglyph
+ ftcsbits
+ ftcimage
+ ftcbasic
+ ftccmap
+ ;
}
else
{
--- a/src/cache/ftcache.c
+++ b/src/cache/ftcache.c
@@ -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 */
--- /dev/null
+++ b/src/cache/ftcbasic.c
@@ -1,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;
+ }
+
--- a/src/cache/ftccache.c
+++ b/src/cache/ftccache.c
@@ -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,159 +135,171 @@
}
- /* remove a node from its cache's hash table */
- static FT_Error
- ftc_node_hash_unlink( FTC_Node node,
- FTC_Cache cache )
+ /* 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 )
{
- FT_Error error = 0;
- FTC_Node *pnode;
- FT_UInt idx, num_buckets;
-
-
- idx = (FT_UInt)( node->hash & cache->mask );
- if ( idx < cache->p )
- idx = (FT_UInt)( node->hash & ( 2 * cache->mask + 1 ) );
-
- pnode = cache->buckets + idx;
-
for (;;)
{
- if ( *pnode == NULL )
- {
- FT_ERROR(( "ftc_node_hash_unlink: unknown node!\n" ));
- return FTC_Err_Ok;
- }
+ FTC_Node node, *pnode;
+ FT_UInt p = cache->p;
+ FT_UInt mask = cache->mask;
+ FT_UInt count = mask + p + 1; /* number of buckets */
- if ( *pnode == node )
+ /* do we need to shrink the buckets array ?
+ */
+ if ( cache->slack < 0 )
{
- *pnode = node->link;
- node->link = NULL;
- break;
- }
+ FTC_Node new_list = NULL;
- pnode = &(*pnode)->link;
- }
+ /* try to expand the buckets array _before_ splitting
+ * the bucket lists
+ */
+ if ( p >= mask )
+ {
+ FT_Memory memory = cache->memory;
- num_buckets = ( cache->p + cache->mask + 1 );
+ /* if we can't expand the array, leave immediately */
+ if ( FT_MEM_RENEW_ARRAY( cache->buckets, (mask+1)*2, (mask+1)*4 ) )
+ break;
+ }
- 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;
+ /* split a single bucket */
+ pnode = cache->buckets + p;
+ for (;;)
+ {
+ node = *pnode;
+ if ( node == NULL )
+ break;
- if ( old_index + 1 <= FTC_HASH_INITIAL_SIZE )
- goto Exit;
+ if ( node->hash & ( mask + 1 ) )
+ {
+ *pnode = node->link;
+ node->link = new_list;
+ new_list = node;
+ }
+ else
+ pnode = &node->link;
+ }
- if ( p == 0 )
- {
- FT_Memory memory = cache->memory;
+ cache->buckets[p + mask + 1] = new_list;
+ cache->slack += FTC_HASH_MAX_LOAD;
- cache->mask >>= 1;
- p = cache->mask;
-
- if ( FT_RENEW_ARRAY( cache->buckets, ( mask + 1 ) * 2, (mask+1) ) )
+ if ( p >= mask )
{
- FT_ERROR(( "ftc_node_hash_unlink: couldn't shunk buckets!\n" ));
- goto Exit;
+ cache->mask = 2 * mask + 1;
+ cache->p = 0;
}
+ else
+ cache->p = p + 1;
}
- else
- p--;
+ /* 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;
- pnode = cache->buckets + p;
- while ( *pnode )
- pnode = &(*pnode)->link;
+ if ( old_index + 1 <= FTC_HASH_INITIAL_SIZE )
+ break;
- pold = cache->buckets + old_index;
- *pnode = *pold;
- *pold = NULL;
+ if ( p == 0 )
+ {
+ FT_Memory memory = cache->memory;
- cache->slack -= FTC_HASH_MAX_LOAD;
- cache->p = p;
- }
+ /* if we can't shrink the array, leave immediately */
+ if ( FT_MEM_RENEW_ARRAY( cache->buckets, ( mask + 1 ) * 2, (mask+1) ) )
+ break;
- Exit:
- return error;
+ 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;
+ }
}
- /* add a node to the "top" of its cache's hash table */
- static FT_Error
- ftc_node_hash_link( FTC_Node node,
- FTC_Cache cache )
+ /* remove a node from its cache's hash table */
+ static void
+ ftc_node_hash_unlink( FTC_Node node0,
+ FTC_Cache cache )
{
FTC_Node *pnode;
FT_UInt idx;
- FT_Error error = 0;
- 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;
- node->link = *pnode;
- *pnode = node;
-
- if ( --cache->slack < 0 )
+ for (;;)
{
- FT_UInt p = cache->p;
- FT_UInt mask = cache->mask;
- FTC_Node new_list;
+ FTC_Node node = *pnode;
+ if ( node == NULL )
+ {
+ FT_ERROR(( "ftc_node_hash_unlink: unknown node!\n" ));
+ return;
+ }
- /* split a single bucket */
- new_list = NULL;
- pnode = cache->buckets + p;
+ if ( node == node0 )
+ break;
- for (;;)
- {
- node = *pnode;
- if ( node == NULL )
- break;
+ pnode = &(*pnode)->link;
+ }
- if ( node->hash & ( mask + 1 ) )
- {
- *pnode = node->link;
- node->link = new_list;
- new_list = node;
- }
- else
- pnode = &node->link;
- }
+ *pnode = node0->link;
+ node0->link = NULL;
- cache->buckets[p + mask + 1] = new_list;
+ cache->slack++;
+ ftc_cache_resize( cache );
+ }
- cache->slack += FTC_HASH_MAX_LOAD;
- if ( p >= mask )
- {
- FT_Memory memory = cache->memory;
+ /* add a node to the "top" of its cache's hash table */
+ static void
+ ftc_node_hash_link( FTC_Node node,
+ FTC_Cache cache )
+ {
+ FTC_Node *pnode;
+ FT_UInt idx;
- 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;
- }
+ idx = (FT_UInt)( node->hash & cache->mask );
+ if ( idx < cache->p )
+ idx = (FT_UInt)( node->hash & (2 * cache->mask + 1 ) );
- Exit:
- return error;
+ pnode = cache->buckets + idx;
+
+ node->link = *pnode;
+ *pnode = node;
+
+ cache->slack--;
+ ftc_cache_resize( cache );
}
@@ -315,15 +310,12 @@
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;
@@ -330,8 +322,7 @@
}
#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,10 +332,8 @@
}
#endif
- clazz = cache->clazz;
+ manager->cur_weight -= cache->clazz.node_weight( node, cache );
- manager->cur_weight -= clazz->node_weight( node, cache );
-
/* remove node from mru list */
ftc_node_mru_unlink( node, manager );
@@ -352,11 +341,8 @@
ftc_node_hash_unlink( node, cache );
/* now finalize it */
- if ( clazz->node_done )
- clazz->node_done( node, cache );
+ cache->clazz.node_free( node, cache );
- FT_FREE( node );
-
#if 0
/* check, just in case of general corruption :-) */
if ( manager->num_nodes == 0 )
@@ -369,58 +355,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 );
- }
- }
-
-
- /*************************************************************************/
- /*************************************************************************/
- /***** *****/
/***** ABSTRACT CACHE CLASS *****/
/***** *****/
/*************************************************************************/
@@ -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 )
- {
- FT_LruList_Destroy( cache->families );
- cache->families = NULL;
- }
+ cache->memory = NULL;
}
}
- /* 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,
- FTC_Node *anode )
+
+ static void
+ ftc_cache_add( FTC_Cache cache,
+ FT_UInt32 hash,
+ FTC_Node node )
{
- FT_Error error = FTC_Err_Ok;
- FTC_Manager manager;
- FT_LruNode lru;
- FT_UInt free_count = 0;
+ node->hash = hash;
+ ftc_node_hash_link( node, cache );
+ ftc_node_mru_link( node, cache->manager );
- if ( !cache || !query || !anode )
- return FTC_Err_Invalid_Argument;
+ {
+ FTC_Manager manager = cache->manager;
- *anode = NULL;
+ manager->cur_weight += cache->clazz.node_weight( node, cache );
- 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.
- */
-
- for (;;)
- {
+ if ( manager->cur_weight >= manager->max_weight )
{
- /* first of all, find the relevant family */
- FT_LruList list = cache->families;
- FT_LruNode fam, *pfam;
- FT_LruNode_CompareFunc compare = list->clazz->node_compare;
+ node->ref_count++;
+ FTC_Manager_Compress( manager );
+ node->ref_count--;
+ }
+ }
+ }
- pfam = &list->nodes;
- for (;;)
- {
- fam = *pfam;
- if ( fam == NULL )
- {
- error = FT_LruList_Lookup( list, query, &lru );
- if ( error )
- goto Fail;
- goto Skip;
- }
+ FT_EXPORT( FT_Error )
+ FTC_Cache_Lookup( FTC_Cache cache,
+ FT_UInt32 hash,
+ FT_Pointer query,
+ FTC_Node *anode )
+ {
+ FT_UFast idx;
+ FTC_Node* bucket;
+ FTC_Node* pnode;
+ FTC_Node node;
+ FT_Error error = 0;
- if ( compare( fam, query, list->data ) )
- break;
+ FTC_Node_CompareFunc compare = cache->clazz.node_compare;
- pfam = &fam->next;
- }
- FT_ASSERT( fam != NULL );
+ if ( cache == NULL || anode == NULL )
+ return FT_Err_Invalid_Argument;
- /* move to top of list when needed */
- if ( fam != list->nodes )
- {
- *pfam = fam->next;
- fam->next = list->nodes;
- list->nodes = fam;
- }
+ idx = hash & cache->mask;
+ if ( idx < cache->p )
+ idx = hash & ( cache->mask * 2 + 1 );
- lru = fam;
+ bucket = cache->buckets + idx;
+ pnode = bucket;
+ for (;;)
+ {
+ node = *pnode;
+ if ( node == NULL )
+ goto NewNode;
- Skip:
- ;
- }
+ if ( node->hash == hash && compare( node, query, cache ) )
+ break;
- {
- FTC_Family family = (FTC_Family) lru;
- FT_UFast hash = query->hash;
- FTC_Node* bucket;
- FT_UInt idx;
+ pnode = &node->link;
+ }
+ if ( node != *bucket )
+ {
+ *pnode = node->link;
+ node->link = *bucket;
+ *bucket = node;
+ }
- idx = hash & cache->mask;
- if ( idx < cache->p )
- idx = hash & ( cache->mask * 2 + 1 );
+ /* move to head of MRU list */
+ {
+ FTC_Manager manager = cache->manager;
- bucket = cache->buckets + idx;
+ if ( node != manager->nodes_list )
+ ftc_node_mru_up( node, manager );
+ }
+ goto Exit;
+ NewNode:
- 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;
- }
+ /*
+ * 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;
- if ( *bucket )
- {
- FTC_Node* pnode = bucket;
- FTC_Node_CompareFunc compare = cache->clazz->node_compare;
+ node = NULL;
+ if ( error != FT_Err_Out_Of_Memory )
+ goto Exit;
+ {
+ FTC_Manager manager = cache->manager;
+ FT_UInt count, tries = 1;
- for ( ;; )
- {
- FTC_Node node;
+ for (;;)
+ {
+ error = cache->clazz.node_new( &node, query, cache );
+ if ( !error )
+ break;
+ node = NULL;
+ if ( error != FT_Err_Out_Of_Memory )
+ goto Exit;
- node = *pnode;
- if ( node == NULL )
- break;
+ count = FTC_Manager_FlushN( manager, tries );
+ if ( count == 0 )
+ goto Exit;
- 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;
- }
+ if ( count == tries )
+ {
+ count = tries*2;
+ if ( count < tries || count > manager->num_nodes )
+ count = manager->num_nodes;
}
+ tries = count;
+ }
+ }
- /* didn't find a node, create a new one */
- {
- FTC_Cache_Class clazz = cache->clazz;
- FT_Memory memory = cache->memory;
- FTC_Node node;
+ 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;
+ }
- 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;
- }
+ 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;
- ftc_node_mru_link( node, cache->manager );
+ count = cache->p + cache->mask;
+ for ( i = 0; i < count; i++ )
+ {
+ FTC_Node* bucket = cache->buckets + i;
+ FTC_Node* pnode = bucket;
- cache->manager->cur_weight += clazz->node_weight( node, cache );
+ for ( ;; )
+ {
+ FTC_Node node = *pnode;
- /* 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--;
- }
+ if ( node == NULL )
+ break;
- *anode = node;
+ if ( cache->clazz.node_remove_faceid( node, face_id, cache ) )
+ {
+ *pnode = node->link;
+ node->link = free;
+ free = node;
}
-
- /* all is well, exit now
- */
- goto Exit;
+ else
+ pnode = &node->link;
}
+ }
- Fail:
- if ( error != FTC_Err_Out_Of_Memory )
- goto Exit;
+ /* remove all nodes in the free list
+ */
+ while ( free )
+ {
+ FTC_Node node;
- /* 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;
+ node = free;
+ free = node->link;
+ manager->cur_weight -= cache->clazz.node_weight( node, cache );
+ ftc_node_mru_unlink( node, manager );
- new_count = 1 + free_count * 2;
+ cache->clazz.node_free( node, cache );
- /* check overflow and bounds */
- if ( new_count < free_count || free_count > manager->num_nodes )
- goto Exit;
-
- free_count = new_count;
-
- /* try to remove "new_count" nodes from the list */
- {
- 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;
- }
- }
- }
+ cache->slack ++;
}
- Exit:
- return error;
+ ftc_cache_resize( cache );
}
-
/* END */
--- a/src/cache/ftccmap.c
+++ b/src/cache/ftccmap.c
@@ -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 ) )
+#define FTC_CMAP_NODE_HASH(x) FTC_CMAP_HASH( (x)->face_id, (x)->cmap_index, (x)->first )
-
- /* 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 ) )
-
/* 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;
- cnode->first = first;
- for ( n = 0; n < FTC_CMAP_INDICES_MAX; n++ )
- cnode->indices[n] = FTC_CMAP_UNKNOWN;
+ /* 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;
- return 0;
+ 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;
+
+ 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,26 +172,19 @@
FT_CALLBACK_TABLE_DEF
- const FTC_Cache_ClassRec ftc_cmap_cache_class =
+ const FTC_CacheClassRec ftc_cmap_cache_class =
{
- sizeof ( FTC_CacheRec ),
- (FTC_Cache_InitFunc) ftc_cache_init,
- (FTC_Cache_ClearFunc)ftc_cache_clear,
- (FTC_Cache_DoneFunc) ftc_cache_done,
+ (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_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
+ sizeof ( FTC_CacheRec ),
+ (FTC_Cache_InitFunc) FTC_Cache_Init,
+ (FTC_Cache_DoneFunc) FTC_Cache_Done,
};
-
/* documentation is in ftccmap.h */
FT_EXPORT_DEF( FT_Error )
@@ -360,101 +191,76 @@
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 )
- {
- FT_UInt offset = (FT_UInt)( char_code - node->first );
+ 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( offset < FTC_CMAP_INDICES_MAX );
+ FT_ASSERT( (FT_UInt)( char_code - node->first ) < FTC_CMAP_INDICES_MAX );
- gindex = node->indices[offset];
- if ( gindex == FTC_CMAP_UNKNOWN )
- {
- FT_Face face;
+ gindex = node->indices[ char_code - node->first ];
+ if ( gindex == FTC_CMAP_UNKNOWN )
+ {
+ FT_Face face;
+ gindex = 0;
- /* we need to use FT_Get_Char_Index */
- gindex = 0;
+ error = FTC_Manager_LookupFace( cache->manager, node->face_id, &face );
+ if ( error )
+ goto Exit;
- error = FTC_Manager_Lookup_Face( FTC_CACHE(cache)->manager,
- desc->face_id,
- &face );
- if ( !error )
- {
- FT_CharMap old, cmap = NULL;
- FT_UInt cmap_index;
+ if ( (FT_UInt)cmap_index < (FT_UInt)face->num_charmaps )
+ {
+ FT_CharMap old, cmap = NULL;
+ old = face->charmap;
+ cmap = face->charmaps[ 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 */
--- a/src/cache/ftcglyph.c
+++ b/src/cache/ftcglyph.c
@@ -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->family = family;
+ gnode->gindex = gindex;
+ family->num_nodes++;
+ }
- gnode->item_start = (FT_UShort)start;
+ FT_EXPORT_DEF( void )
+ FTC_GNode_UnselectFamily( FTC_GNode gnode,
+ FTC_Cache cache )
+ {
+ FTC_Family family = gnode->family;
- 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 = NULL;
+ if ( family && --family->num_nodes <= 0 )
+ FTC_MruList_Remove( & FTC_GCACHE(cache)->families, (FTC_MruNode)family );
}
FT_EXPORT_DEF( void )
- ftc_glyph_node_done( FTC_GlyphNode gnode,
- FTC_Cache cache )
+ 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;
}
--- a/src/cache/ftcimage.c
+++ b/src/cache/ftcimage.c
@@ -18,65 +18,19 @@
#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 );
@@ -83,68 +37,41 @@
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;
@@ -182,217 +109,6 @@
size += sizeof ( *inode );
return size;
- }
-
-
- /*************************************************************************/
- /*************************************************************************/
- /***** *****/
- /***** 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 );
}
--- a/src/cache/ftcmanag.c
+++ b/src/cache/ftcmanag.c
@@ -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,124 +32,135 @@
#define FTC_LRU_GET_MANAGER( lru ) ( (FTC_Manager)(lru)->user_data )
- /*************************************************************************/
- /*************************************************************************/
- /***** *****/
- /***** FACE LRU IMPLEMENTATION *****/
- /***** *****/
- /*************************************************************************/
- /*************************************************************************/
+ 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;
- typedef struct FTC_FaceNodeRec_* FTC_FaceNode;
- typedef struct FTC_SizeNodeRec_* FTC_SizeNode;
+ error = FTC_Manager_LookupFace( manager, scaler->face_id, &face );
+ if ( error ) goto Exit;
+ error = FT_New_Size( face, &size );
+ if ( error ) goto Exit;
- typedef struct FTC_FaceNodeRec_
- {
- FT_LruNodeRec lru;
- FT_Face face;
+ FT_Activate_Size( size );
- } FTC_FaceNodeRec;
+ 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_
+
+ typedef struct FTC_SizeNodeRec_
{
- FT_LruNodeRec lru;
- FT_Size size;
+ FTC_MruNodeRec node;
+ FT_Size size;
+ FTC_ScalerRec scaler;
- } FTC_SizeNodeRec;
+ } FTC_SizeNodeRec, *FTC_SizeNode;
- FT_CALLBACK_DEF( FT_Error )
- ftc_face_node_init( FTC_FaceNode node,
- FTC_FaceID face_id,
- FTC_Manager manager )
+ FT_CALLBACK_DEF( void )
+ ftc_size_node_done( FTC_SizeNode node )
{
- FT_Error error;
+ FT_Size size = node->size;
-
- error = manager->request_face( face_id,
- manager->library,
- manager->request_data,
- &node->face );
- if ( !error )
- {
- /* destroy initial size object; it will be re-created later */
- if ( node->face->size )
- FT_Done_Size( node->face->size );
- }
-
- return error;
+ if ( size )
+ FT_Done_Size( size );
}
- /* helper function for ftc_face_node_done() */
FT_CALLBACK_DEF( FT_Bool )
- ftc_size_node_select( FTC_SizeNode node,
- FT_Face face )
+ ftc_size_node_compare( FTC_SizeNode node,
+ FTC_Scaler scaler )
{
- return FT_BOOL( node->size->face == face );
+ FTC_Scaler scaler0 = &node->scaler;
+
+ return FTC_SCALER_COMPARE( scaler0, scaler );
}
- FT_CALLBACK_DEF( void )
- ftc_face_node_done( FTC_FaceNode node,
- FTC_Manager manager )
+
+ FT_CALLBACK_DEF( FT_Error )
+ ftc_size_node_init( FTC_SizeNode node,
+ FTC_Scaler scaler,
+ FTC_Manager manager )
{
- FT_Face face = node->face;
+ node->scaler = scaler[0];
+ return ftc_scaler_lookup_size( manager, scaler, &node->size );
+ }
- /* 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 );
- /* all right, we can discard the face now */
- FT_Done_Face( face );
- node->face = NULL;
+ 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 );
}
- FT_CALLBACK_TABLE_DEF
- const FT_LruList_ClassRec ftc_face_list_class =
+ static const FTC_MruListClassRec ftc_size_list_class =
{
- sizeof ( FT_LruListRec ),
- (FT_LruList_InitFunc)0,
- (FT_LruList_DoneFunc)0,
-
- 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 */
+ 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
};
- /* documentation is in ftcache.h */
+ /* 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_Lookup_Face( FTC_Manager manager,
- FTC_FaceID face_id,
- FT_Face *aface )
+ FTC_Manager_LookupSize( FTC_Manager manager,
+ FTC_Scaler scaler,
+ FT_Size *asize )
{
FT_Error error;
- FTC_FaceNode node;
+ FTC_SizeNode node;
- if ( aface == NULL )
+ if ( asize == NULL )
return FTC_Err_Bad_Argument;
- *aface = NULL;
+ *asize = NULL;
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->sizes,
+ scaler,
+ (FTC_MruNode*) &node );
if ( !error )
- *aface = node->face;
+ *asize = node->size;
return error;
}
@@ -159,42 +169,39 @@
/*************************************************************************/
/*************************************************************************/
/***** *****/
- /***** SIZES LRU IMPLEMENTATION *****/
+ /***** FACE MRU IMPLEMENTATION *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
-
- typedef struct FTC_SizeQueryRec_
+ typedef struct FTC_FaceNodeRec_
{
- FT_Face face;
- FT_UInt width;
- FT_UInt height;
+ FTC_MruNodeRec node;
+ FTC_FaceID face_id;
+ FT_Face face;
- } FTC_SizeQueryRec, *FTC_SizeQuery;
+ } FTC_FaceNodeRec, *FTC_FaceNode;
+
FT_CALLBACK_DEF( FT_Error )
- ftc_size_node_init( FTC_SizeNode node,
- FTC_SizeQuery query )
+ ftc_face_node_init( FTC_FaceNode node,
+ FTC_FaceID face_id,
+ FTC_Manager manager )
{
- FT_Face face = query->face;
- FT_Size size;
- FT_Error error;
+ FT_Error error;
+ node->face_id = face_id;
- node->size = NULL;
- error = FT_New_Size( face, &size );
+ error = manager->request_face( face_id,
+ manager->library,
+ manager->request_data,
+ &node->face );
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;
+ /* destroy initial size object; it will be re-created later */
+ if ( node->face->size )
+ FT_Done_Size( node->face->size );
}
return error;
}
@@ -201,238 +208,79 @@
FT_CALLBACK_DEF( void )
- ftc_size_node_done( FTC_SizeNode node )
+ ftc_face_node_done( FTC_FaceNode node,
+ FTC_Manager manager )
{
- if ( node->size )
- {
- FT_Done_Size( node->size );
- node->size = NULL;
- }
- }
+ FT_Memory memory = manager->memory;
- FT_CALLBACK_DEF( FT_Error )
- ftc_size_node_flush( FTC_SizeNode node,
- FTC_SizeQuery query )
- {
- FT_Size size = node->size;
- FT_Error error;
+ /* 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( node->face );
+ node->face = NULL;
+ node->face_id = NULL;
- 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_FREE( node );
}
FT_CALLBACK_DEF( FT_Bool )
- ftc_size_node_compare( FTC_SizeNode node,
- FTC_SizeQuery query )
+ ftc_face_node_compare( FTC_FaceNode node,
+ FTC_FaceID face_id )
{
- 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 );
+ return FT_BOOL( node->face_id == face_id );
}
- FT_CALLBACK_TABLE_DEF
- const FT_LruList_ClassRec ftc_size_list_class =
+ static const FTC_MruListClassRec ftc_face_list_class =
{
- sizeof ( FT_LruListRec ),
- (FT_LruList_InitFunc)0,
- (FT_LruList_DoneFunc)0,
+ sizeof( FTC_FaceNodeRec),
- 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
+ (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_Size( FTC_Manager manager,
- FTC_Font font,
- FT_Face *aface,
- FT_Size *asize )
+ FTC_Manager_LookupFace( FTC_Manager manager,
+ FTC_FaceID face_id,
+ FT_Face *aface )
{
- FT_Error error;
+ FT_Error error;
+ FTC_FaceNode node;
- /* check for valid `manager' delayed to FTC_Manager_Lookup_Face() */
- if ( aface )
- *aface = 0;
+ if ( aface == NULL )
+ return FTC_Err_Bad_Argument;
- if ( asize )
- *asize = 0;
+ *aface = NULL;
- error = FTC_Manager_Lookup_Face( manager, font->face_id, aface );
+ if ( !manager )
+ return FTC_Err_Invalid_Cache_Handle;
+
+ error = FTC_MruList_Lookup( &manager->faces,
+ face_id,
+ (FTC_MruNode*) &node );
if ( !error )
- {
- FTC_SizeQueryRec query;
- FTC_SizeNode node;
+ *aface = node->face;
-
- 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;
}
}
+ manager->num_caches = 0;
- /* discard families table */
- ftc_family_table_done( &manager->families, memory );
-
/* 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,8 +408,8 @@
FTC_Manager_Check( FTC_Manager manager )
{
FTC_Node node, first;
-
+
first = manager->nodes_list;
/* check node weights */
@@ -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->num_caches >= FTC_MAX_CACHES )
{
- if ( manager->caches[idx] == 0 )
- break;
- }
-
- /* return an error if there are too many registered caches */
- if ( idx >= 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,6 +563,57 @@
}
+ 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 )
@@ -754,11 +620,8 @@
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--;
- }
}
--- /dev/null
+++ b/src/cache/ftcmru.c
@@ -1,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 */
+
--- a/src/cache/ftcsbits.c
+++ b/src/cache/ftcsbits.c
@@ -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,48 +26,7 @@
#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,12 +58,12 @@
}
- 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;
@@ -112,116 +70,105 @@
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 = FTC_Manager_Lookup_Size( manager, &sfam->type.font,
- &face, &size );
- if ( !error )
+ error = clazz->family_load_glyph( family, gindex, manager, &face );
+ if ( error )
+ goto BadGlyph;
+
{
- /* 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;
@@ -228,38 +175,64 @@
}
- 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 */
@@ -266,7 +239,7 @@
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 */
--- a/src/cache/ftlru.c
+++ /dev/null
@@ -1,390 +1,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 */
--- a/src/cache/rules.mk
+++ b/src/cache/rules.mk
@@ -25,8 +25,9 @@
# 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 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