* include/freetype/cache/ftccache.h,
include/freetype/cache/ftcmru.h, include/freetype/cache/ftcglyph.h, src/cache/ftcbasic.c, src/cache/ftccache.c, src/cache/ftccmap.c, src/cache/ftcmanag.c: additional speed optimization to the cache sub-system. It is now up to 70% faster than the one in the previous table release (i.e. 2.1.7). Note that the API did slightly change though.
This commit is contained in:
parent
48b6ddb8a8
commit
023612221e
|
@ -1,193 +1,251 @@
|
|||
/***************************************************************************/
|
||||
/* */
|
||||
/* ftccache.h */
|
||||
/* */
|
||||
/* FreeType internal cache interface (specification). */
|
||||
/* */
|
||||
/* Copyright 2000-2001, 2002 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. */
|
||||
/* */
|
||||
/***************************************************************************/
|
||||
|
||||
|
||||
#ifndef __FTCCACHE_H__
|
||||
#define __FTCCACHE_H__
|
||||
|
||||
|
||||
#include FT_CACHE_INTERNAL_MRU_H
|
||||
|
||||
FT_BEGIN_HEADER
|
||||
|
||||
/* handle to cache object */
|
||||
typedef struct FTC_CacheRec_* FTC_Cache;
|
||||
|
||||
/* handle to cache class */
|
||||
typedef const struct FTC_CacheClassRec_* FTC_CacheClass;
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/***** *****/
|
||||
/***** CACHE NODE DEFINITIONS *****/
|
||||
/***** *****/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
/*************************************************************************/
|
||||
/* */
|
||||
/* Each cache controls one or more cache nodes. Each node is part of */
|
||||
/* the global_lru list of the manager. Its `data' field however is used */
|
||||
/* as a reference count for now. */
|
||||
/* */
|
||||
/* A node can be anything, depending on the type of information held by */
|
||||
/* the cache. It can be an individual glyph image, a set of bitmaps */
|
||||
/* glyphs for a given size, some metrics, etc. */
|
||||
/* */
|
||||
/*************************************************************************/
|
||||
|
||||
/* structure size should be 20 bytes on 32-bits machines */
|
||||
typedef struct FTC_NodeRec_
|
||||
{
|
||||
FTC_MruNodeRec mru; /* circular mru list pointer */
|
||||
FTC_Node link; /* used for hashing */
|
||||
FT_UInt32 hash; /* used for hashing too */
|
||||
FT_UShort cache_index; /* index of cache the node belongs to */
|
||||
FT_Short ref_count; /* reference count for this node */
|
||||
|
||||
} FTC_NodeRec;
|
||||
|
||||
|
||||
#define FTC_NODE( x ) ( (FTC_Node)(x) )
|
||||
#define FTC_NODE_P( x ) ( (FTC_Node*)(x) )
|
||||
|
||||
#define FTC_NODE__NEXT(x) FTC_NODE( (x)->mru.next )
|
||||
#define FTC_NODE__PREV(x) FTC_NODE( (x)->mru.prev )
|
||||
|
||||
/*************************************************************************/
|
||||
/* */
|
||||
/* 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. */
|
||||
/* */
|
||||
|
||||
/* reserved for manager's use */
|
||||
FT_EXPORT( void )
|
||||
ftc_node_destroy( FTC_Node node,
|
||||
FTC_Manager manager );
|
||||
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/***** *****/
|
||||
/***** CACHE DEFINITIONS *****/
|
||||
/***** *****/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
/* initialize a new cache node */
|
||||
typedef FT_Error (*FTC_Node_NewFunc)( FTC_Node *pnode,
|
||||
FT_Pointer query,
|
||||
FTC_Cache cache );
|
||||
|
||||
typedef FT_ULong (*FTC_Node_WeightFunc)( FTC_Node node,
|
||||
FTC_Cache cache );
|
||||
|
||||
/* compare a node to a given key pair */
|
||||
typedef FT_Bool (*FTC_Node_CompareFunc)( FTC_Node node,
|
||||
FT_Pointer key,
|
||||
FTC_Cache cache );
|
||||
|
||||
|
||||
typedef void (*FTC_Node_FreeFunc)( FTC_Node node,
|
||||
FTC_Cache cache );
|
||||
|
||||
typedef FT_Error (*FTC_Cache_InitFunc)( FTC_Cache cache );
|
||||
|
||||
typedef void (*FTC_Cache_DoneFunc)( FTC_Cache cache );
|
||||
|
||||
|
||||
typedef struct FTC_CacheClassRec_
|
||||
{
|
||||
FTC_Node_NewFunc node_new;
|
||||
FTC_Node_WeightFunc node_weight;
|
||||
FTC_Node_CompareFunc node_compare;
|
||||
FTC_Node_CompareFunc node_remove_faceid;
|
||||
FTC_Node_FreeFunc node_free;
|
||||
|
||||
FT_UInt cache_size;
|
||||
FTC_Cache_InitFunc cache_init;
|
||||
FTC_Cache_DoneFunc cache_done;
|
||||
|
||||
} FTC_CacheClassRec;
|
||||
|
||||
/* each cache really implements a dynamic hash table to manage its nodes */
|
||||
typedef struct FTC_CacheRec_
|
||||
{
|
||||
FT_UFast p;
|
||||
FT_UFast mask;
|
||||
FT_Long slack;
|
||||
FTC_Node* buckets;
|
||||
|
||||
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;
|
||||
|
||||
|
||||
#define FTC_CACHE( x ) ( (FTC_Cache)(x) )
|
||||
#define FTC_CACHE_P( x ) ( (FTC_Cache*)(x) )
|
||||
|
||||
|
||||
/* default cache initialize */
|
||||
FT_EXPORT( FT_Error )
|
||||
FTC_Cache_Init( FTC_Cache cache );
|
||||
|
||||
/* default cache finalizer */
|
||||
FT_EXPORT( void )
|
||||
FTC_Cache_Done( FTC_Cache cache );
|
||||
|
||||
/* call this function to lookup the cache. if no corresponding
|
||||
* node is found, a new one is automatically created. This function
|
||||
* is capable of flushing the cache adequately to make room for the
|
||||
* new cache object.
|
||||
*/
|
||||
FT_EXPORT( FT_Error )
|
||||
FTC_Cache_Lookup( FTC_Cache cache,
|
||||
FT_UInt32 hash,
|
||||
FT_Pointer query,
|
||||
FTC_Node *anode );
|
||||
|
||||
/* remove all nodes that relate to a given face_id. This is useful
|
||||
* when un-installing fonts. Note that if a cache node relates to
|
||||
* the face_id, but is locked (i.e. has 'ref_count > 0'), the node
|
||||
* will _not_ be destroyed, but its internal face_id reference will
|
||||
* be modified.
|
||||
*
|
||||
* the end result will be that the node will never come back
|
||||
* in further lookup requests, and will be flushed on demand from
|
||||
* the cache normally when its reference count reaches 0
|
||||
*/
|
||||
FT_EXPORT( void )
|
||||
FTC_Cache_RemoveFaceID( FTC_Cache cache,
|
||||
FTC_FaceID face_id );
|
||||
|
||||
/* */
|
||||
|
||||
FT_END_HEADER
|
||||
|
||||
|
||||
#endif /* __FTCCACHE_H__ */
|
||||
|
||||
|
||||
/* END */
|
||||
/***************************************************************************/
|
||||
/* */
|
||||
/* ftccache.h */
|
||||
/* */
|
||||
/* FreeType internal cache interface (specification). */
|
||||
/* */
|
||||
/* Copyright 2000-2001, 2002 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. */
|
||||
/* */
|
||||
/***************************************************************************/
|
||||
|
||||
|
||||
#ifndef __FTCCACHE_H__
|
||||
#define __FTCCACHE_H__
|
||||
|
||||
|
||||
#include FT_CACHE_INTERNAL_MRU_H
|
||||
|
||||
FT_BEGIN_HEADER
|
||||
|
||||
/* handle to cache object */
|
||||
typedef struct FTC_CacheRec_* FTC_Cache;
|
||||
|
||||
/* handle to cache class */
|
||||
typedef const struct FTC_CacheClassRec_* FTC_CacheClass;
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/***** *****/
|
||||
/***** CACHE NODE DEFINITIONS *****/
|
||||
/***** *****/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
/*************************************************************************/
|
||||
/* */
|
||||
/* Each cache controls one or more cache nodes. Each node is part of */
|
||||
/* the global_lru list of the manager. Its `data' field however is used */
|
||||
/* as a reference count for now. */
|
||||
/* */
|
||||
/* A node can be anything, depending on the type of information held by */
|
||||
/* the cache. It can be an individual glyph image, a set of bitmaps */
|
||||
/* glyphs for a given size, some metrics, etc. */
|
||||
/* */
|
||||
/*************************************************************************/
|
||||
|
||||
/* structure size should be 20 bytes on 32-bits machines */
|
||||
typedef struct FTC_NodeRec_
|
||||
{
|
||||
FTC_MruNodeRec mru; /* circular mru list pointer */
|
||||
FTC_Node link; /* used for hashing */
|
||||
FT_UInt32 hash; /* used for hashing too */
|
||||
FT_UShort cache_index; /* index of cache the node belongs to */
|
||||
FT_Short ref_count; /* reference count for this node */
|
||||
|
||||
} FTC_NodeRec;
|
||||
|
||||
|
||||
#define FTC_NODE( x ) ( (FTC_Node)(x) )
|
||||
#define FTC_NODE_P( x ) ( (FTC_Node*)(x) )
|
||||
|
||||
#define FTC_NODE__NEXT(x) FTC_NODE( (x)->mru.next )
|
||||
#define FTC_NODE__PREV(x) FTC_NODE( (x)->mru.prev )
|
||||
|
||||
/*************************************************************************/
|
||||
/* */
|
||||
/* 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. */
|
||||
/* */
|
||||
|
||||
/* reserved for manager's use */
|
||||
FT_EXPORT( void )
|
||||
ftc_node_destroy( FTC_Node node,
|
||||
FTC_Manager manager );
|
||||
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/***** *****/
|
||||
/***** CACHE DEFINITIONS *****/
|
||||
/***** *****/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
/* initialize a new cache node */
|
||||
typedef FT_Error (*FTC_Node_NewFunc)( FTC_Node *pnode,
|
||||
FT_Pointer query,
|
||||
FTC_Cache cache );
|
||||
|
||||
typedef FT_ULong (*FTC_Node_WeightFunc)( FTC_Node node,
|
||||
FTC_Cache cache );
|
||||
|
||||
/* compare a node to a given key pair */
|
||||
typedef FT_Bool (*FTC_Node_CompareFunc)( FTC_Node node,
|
||||
FT_Pointer key,
|
||||
FTC_Cache cache );
|
||||
|
||||
|
||||
typedef void (*FTC_Node_FreeFunc)( FTC_Node node,
|
||||
FTC_Cache cache );
|
||||
|
||||
typedef FT_Error (*FTC_Cache_InitFunc)( FTC_Cache cache );
|
||||
|
||||
typedef void (*FTC_Cache_DoneFunc)( FTC_Cache cache );
|
||||
|
||||
|
||||
typedef struct FTC_CacheClassRec_
|
||||
{
|
||||
FTC_Node_NewFunc node_new;
|
||||
FTC_Node_WeightFunc node_weight;
|
||||
FTC_Node_CompareFunc node_compare;
|
||||
FTC_Node_CompareFunc node_remove_faceid;
|
||||
FTC_Node_FreeFunc node_free;
|
||||
|
||||
FT_UInt cache_size;
|
||||
FTC_Cache_InitFunc cache_init;
|
||||
FTC_Cache_DoneFunc cache_done;
|
||||
|
||||
} FTC_CacheClassRec;
|
||||
|
||||
/* each cache really implements a dynamic hash table to manage its nodes */
|
||||
typedef struct FTC_CacheRec_
|
||||
{
|
||||
FT_UFast p;
|
||||
FT_UFast mask;
|
||||
FT_Long slack;
|
||||
FTC_Node* buckets;
|
||||
|
||||
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;
|
||||
|
||||
|
||||
#define FTC_CACHE( x ) ( (FTC_Cache)(x) )
|
||||
#define FTC_CACHE_P( x ) ( (FTC_Cache*)(x) )
|
||||
|
||||
|
||||
/* default cache initialize */
|
||||
FT_EXPORT( FT_Error )
|
||||
FTC_Cache_Init( FTC_Cache cache );
|
||||
|
||||
/* default cache finalizer */
|
||||
FT_EXPORT( void )
|
||||
FTC_Cache_Done( FTC_Cache cache );
|
||||
|
||||
/* call this function to lookup the cache. if no corresponding
|
||||
* node is found, a new one is automatically created. This function
|
||||
* is capable of flushing the cache adequately to make room for the
|
||||
* new cache object.
|
||||
*/
|
||||
FT_EXPORT( FT_Error )
|
||||
FTC_Cache_Lookup( FTC_Cache cache,
|
||||
FT_UInt32 hash,
|
||||
FT_Pointer query,
|
||||
FTC_Node *anode );
|
||||
|
||||
FT_EXPORT( FT_Error )
|
||||
FTC_Cache_NewNode( FTC_Cache cache,
|
||||
FT_UInt32 hash,
|
||||
FT_Pointer query,
|
||||
FTC_Node *anode );
|
||||
|
||||
/* remove all nodes that relate to a given face_id. This is useful
|
||||
* when un-installing fonts. Note that if a cache node relates to
|
||||
* the face_id, but is locked (i.e. has 'ref_count > 0'), the node
|
||||
* will _not_ be destroyed, but its internal face_id reference will
|
||||
* be modified.
|
||||
*
|
||||
* the end result will be that the node will never come back
|
||||
* in further lookup requests, and will be flushed on demand from
|
||||
* the cache normally when its reference count reaches 0
|
||||
*/
|
||||
FT_EXPORT( void )
|
||||
FTC_Cache_RemoveFaceID( FTC_Cache cache,
|
||||
FTC_FaceID face_id );
|
||||
|
||||
|
||||
|
||||
#define FTC_CACHE_LOOKUP_CMP( cache, nodecmp, hash, query, node, error ) \
|
||||
FT_BEGIN_STMNT \
|
||||
FTC_Node *_bucket, *_pnode, _node; \
|
||||
FTC_Cache _cache = FTC_CACHE(cache); \
|
||||
FT_UInt32 _hash = (FT_UInt32)(hash); \
|
||||
FTC_Node_CompareFunc _nodcomp = (FTC_Node_CompareFunc)(nodecmp); \
|
||||
FT_UInt _idx; \
|
||||
\
|
||||
error = 0; \
|
||||
_idx = _hash & _cache->mask; \
|
||||
if ( _idx < _cache->p ) \
|
||||
_idx = _hash & (_cache->mask*2 + 1); \
|
||||
\
|
||||
_bucket = _pnode = _cache->buckets + _idx; \
|
||||
for (;;) \
|
||||
{ \
|
||||
_node = *_pnode; \
|
||||
if ( _node == NULL ) \
|
||||
goto _NewNode; \
|
||||
\
|
||||
if ( _node->hash == _hash && _nodcomp( _node, query, _cache ) ) \
|
||||
break; \
|
||||
\
|
||||
_pnode = &_node->link; \
|
||||
} \
|
||||
\
|
||||
if ( _node != *_bucket ) \
|
||||
{ \
|
||||
*_pnode = _node->link; \
|
||||
_node->link = *_bucket; \
|
||||
*_bucket = _node; \
|
||||
} \
|
||||
\
|
||||
{ \
|
||||
FTC_Manager _manager = _cache->manager; \
|
||||
\
|
||||
if ( _node != _manager->nodes_list ) \
|
||||
FTC_MruNode_Up( (FTC_MruNode*)&_manager->nodes_list, \
|
||||
(FTC_MruNode)_node ); \
|
||||
} \
|
||||
goto _Ok; \
|
||||
\
|
||||
_NewNode: \
|
||||
error = FTC_Cache_NewNode( _cache, _hash, query, &_node ); \
|
||||
\
|
||||
_Ok: \
|
||||
*(FTC_Node*)&(node) = _node; \
|
||||
FT_END_STMNT
|
||||
|
||||
|
||||
/* */
|
||||
|
||||
FT_END_HEADER
|
||||
|
||||
|
||||
#endif /* __FTCCACHE_H__ */
|
||||
|
||||
|
||||
/* END */
|
||||
|
|
|
@ -1,266 +1,295 @@
|
|||
/***************************************************************************/
|
||||
/* */
|
||||
/* ftcglyph.h */
|
||||
/* */
|
||||
/* FreeType abstract glyph 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. */
|
||||
/* */
|
||||
/***************************************************************************/
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* 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. */
|
||||
/* */
|
||||
/*************************************************************************/
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/********* *********/
|
||||
/********* WARNING, THIS IS BETA CODE. *********/
|
||||
/********* *********/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
|
||||
#ifndef __FTCGLYPH_H__
|
||||
#define __FTCGLYPH_H__
|
||||
|
||||
|
||||
#include <ft2build.h>
|
||||
#include FT_CACHE_INTERNAL_MANAGER_H
|
||||
|
||||
|
||||
FT_BEGIN_HEADER
|
||||
|
||||
|
||||
/*
|
||||
* 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_MruNodeRec mrunode;
|
||||
FT_UInt num_nodes; /* current number of nodes in this family */
|
||||
FTC_Cache cache;
|
||||
FTC_MruListClass clazz;
|
||||
|
||||
} FTC_FamilyRec, *FTC_Family;
|
||||
|
||||
#define FTC_FAMILY(x) ( (FTC_Family)(x) )
|
||||
#define FTC_FAMILY_P(x) ( (FTC_Family*)(x) )
|
||||
|
||||
|
||||
typedef struct FTC_GNodeRec_
|
||||
{
|
||||
FTC_NodeRec node;
|
||||
FTC_Family family;
|
||||
FT_UInt gindex;
|
||||
|
||||
} FTC_GNodeRec, *FTC_GNode;
|
||||
|
||||
#define FTC_GNODE( x ) ( (FTC_GNode)(x) )
|
||||
#define FTC_GNODE_P( x ) ( (FTC_GNode*)(x) )
|
||||
|
||||
|
||||
typedef struct FTC_GQueryRec_
|
||||
{
|
||||
FT_UInt gindex;
|
||||
FTC_Family family;
|
||||
|
||||
} FTC_GQueryRec, *FTC_GQuery;
|
||||
|
||||
#define FTC_GQUERY( x ) ( (FTC_GQuery)(x) )
|
||||
|
||||
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/* */
|
||||
/* These functions are exported so that they can be called from */
|
||||
/* user-provided cache classes; otherwise, they are really part of the */
|
||||
/* cache sub-system internals. */
|
||||
/* */
|
||||
|
||||
/* must be called by derived FTC_Node_InitFunc routines */
|
||||
FT_EXPORT( void )
|
||||
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_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_GNode_Done( FTC_GNode node,
|
||||
FTC_Cache cache );
|
||||
|
||||
|
||||
FT_EXPORT( void )
|
||||
FTC_Family_Init( FTC_Family family,
|
||||
FTC_Cache cache );
|
||||
|
||||
typedef struct FTC_GCacheRec_
|
||||
{
|
||||
FTC_CacheRec cache;
|
||||
FTC_MruListRec families;
|
||||
|
||||
} FTC_GCacheRec, *FTC_GCache;
|
||||
|
||||
|
||||
#define FTC_GCACHE(x) ((FTC_GCache)(x))
|
||||
|
||||
|
||||
/* can be used as @FTC_Cache_InitFunc */
|
||||
FT_EXPORT( FT_Error )
|
||||
FTC_GCache_Init( FTC_GCache cache );
|
||||
|
||||
|
||||
/* can be used as @FTC_Cache_DoneFunc */
|
||||
FT_EXPORT( void )
|
||||
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 )
|
||||
#define FTC_CACHE__FAMILY_CLASS(x) ((FTC_MruListClass) FTC_CACHE__GCACHE_CLASS(x)->family_class)
|
||||
|
||||
|
||||
/* convenience function. use instead of FTC_Manager_Register_Cache */
|
||||
FT_EXPORT( FT_Error )
|
||||
FTC_GCache_New( FTC_Manager manager,
|
||||
FTC_GCacheClass clazz,
|
||||
FTC_GCache *acache );
|
||||
|
||||
FT_EXPORT( FT_Error )
|
||||
FTC_GCache_Lookup( FTC_GCache cache,
|
||||
FT_UInt32 hash,
|
||||
FT_UInt gindex,
|
||||
FTC_GQuery query,
|
||||
FTC_Node *anode );
|
||||
|
||||
/* */
|
||||
|
||||
FT_END_HEADER
|
||||
|
||||
|
||||
#endif /* __FTCGLYPH_H__ */
|
||||
|
||||
|
||||
/* END */
|
||||
/***************************************************************************/
|
||||
/* */
|
||||
/* ftcglyph.h */
|
||||
/* */
|
||||
/* FreeType abstract glyph 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. */
|
||||
/* */
|
||||
/***************************************************************************/
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* 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. */
|
||||
/* */
|
||||
/*************************************************************************/
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/********* *********/
|
||||
/********* WARNING, THIS IS BETA CODE. *********/
|
||||
/********* *********/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
|
||||
#ifndef __FTCGLYPH_H__
|
||||
#define __FTCGLYPH_H__
|
||||
|
||||
|
||||
#include <ft2build.h>
|
||||
#include FT_CACHE_INTERNAL_MANAGER_H
|
||||
|
||||
|
||||
FT_BEGIN_HEADER
|
||||
|
||||
|
||||
/*
|
||||
* 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_MruNodeRec mrunode;
|
||||
FT_UInt num_nodes; /* current number of nodes in this family */
|
||||
FTC_Cache cache;
|
||||
FTC_MruListClass clazz;
|
||||
|
||||
} FTC_FamilyRec, *FTC_Family;
|
||||
|
||||
#define FTC_FAMILY(x) ( (FTC_Family)(x) )
|
||||
#define FTC_FAMILY_P(x) ( (FTC_Family*)(x) )
|
||||
|
||||
|
||||
typedef struct FTC_GNodeRec_
|
||||
{
|
||||
FTC_NodeRec node;
|
||||
FTC_Family family;
|
||||
FT_UInt gindex;
|
||||
|
||||
} FTC_GNodeRec, *FTC_GNode;
|
||||
|
||||
#define FTC_GNODE( x ) ( (FTC_GNode)(x) )
|
||||
#define FTC_GNODE_P( x ) ( (FTC_GNode*)(x) )
|
||||
|
||||
|
||||
typedef struct FTC_GQueryRec_
|
||||
{
|
||||
FT_UInt gindex;
|
||||
FTC_Family family;
|
||||
|
||||
} FTC_GQueryRec, *FTC_GQuery;
|
||||
|
||||
#define FTC_GQUERY( x ) ( (FTC_GQuery)(x) )
|
||||
|
||||
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/* */
|
||||
/* These functions are exported so that they can be called from */
|
||||
/* user-provided cache classes; otherwise, they are really part of the */
|
||||
/* cache sub-system internals. */
|
||||
/* */
|
||||
|
||||
/* must be called by derived FTC_Node_InitFunc routines */
|
||||
FT_EXPORT( void )
|
||||
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_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_GNode_Done( FTC_GNode node,
|
||||
FTC_Cache cache );
|
||||
|
||||
|
||||
FT_EXPORT( void )
|
||||
FTC_Family_Init( FTC_Family family,
|
||||
FTC_Cache cache );
|
||||
|
||||
typedef struct FTC_GCacheRec_
|
||||
{
|
||||
FTC_CacheRec cache;
|
||||
FTC_MruListRec families;
|
||||
|
||||
} FTC_GCacheRec, *FTC_GCache;
|
||||
|
||||
|
||||
#define FTC_GCACHE(x) ((FTC_GCache)(x))
|
||||
|
||||
|
||||
/* can be used as @FTC_Cache_InitFunc */
|
||||
FT_EXPORT( FT_Error )
|
||||
FTC_GCache_Init( FTC_GCache cache );
|
||||
|
||||
|
||||
/* can be used as @FTC_Cache_DoneFunc */
|
||||
FT_EXPORT( void )
|
||||
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 )
|
||||
#define FTC_CACHE__FAMILY_CLASS(x) ((FTC_MruListClass) FTC_CACHE__GCACHE_CLASS(x)->family_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 );
|
||||
|
||||
|
||||
#define FTC_GCACHE_LOOKUP_CMP( cache, famcmp, nodecmp, hash, gindex, query, node, error ) \
|
||||
FT_BEGIN_STMNT \
|
||||
FTC_GCache _gcache = FTC_GCACHE( cache ); \
|
||||
FTC_Family _family; \
|
||||
FTC_GQuery _gquery = (FTC_GQuery)( query ); \
|
||||
FTC_MruNode_CompareFunc _fcompare = (FTC_MruNode_CompareFunc)(famcmp); \
|
||||
\
|
||||
_gquery->gindex = (gindex); \
|
||||
\
|
||||
FTC_MRULIST_LOOP( &_gcache->families, _family ) \
|
||||
{ \
|
||||
if ( _fcompare( (FTC_MruNode)_family, _gquery ) ) \
|
||||
{ \
|
||||
_gquery->family = _family; \
|
||||
goto _FamilyFound; \
|
||||
} \
|
||||
} \
|
||||
FTC_MRULIST_LOOP_END(); \
|
||||
\
|
||||
error = FTC_MruList_New( &_gcache->families, \
|
||||
_gquery, \
|
||||
(FTC_MruNode*)&_gquery->family ); \
|
||||
if ( !error ) \
|
||||
{ \
|
||||
_FamilyFound: \
|
||||
FTC_CACHE_LOOKUP_CMP( cache, nodecmp, hash, query, node, error ); \
|
||||
} \
|
||||
FT_END_STMNT
|
||||
/* */
|
||||
|
||||
FT_END_HEADER
|
||||
|
||||
|
||||
#endif /* __FTCGLYPH_H__ */
|
||||
|
||||
|
||||
/* END */
|
||||
|
|
|
@ -1,165 +1,227 @@
|
|||
/***************************************************************************/
|
||||
/* */
|
||||
/* 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
|
||||
|
||||
#define xxFT_DEBUG_ERROR
|
||||
|
||||
FT_BEGIN_HEADER
|
||||
|
||||
typedef struct FTC_MruNodeRec_* FTC_MruNode;
|
||||
|
||||
typedef struct FTC_MruNodeRec_
|
||||
{
|
||||
FTC_MruNode next;
|
||||
FTC_MruNode prev;
|
||||
|
||||
} FTC_MruNodeRec;
|
||||
|
||||
FT_EXPORT( void )
|
||||
FTC_MruNode_Prepend( FTC_MruNode *plist,
|
||||
FTC_MruNode node );
|
||||
|
||||
FT_EXPORT( void )
|
||||
FTC_MruNode_Up( FTC_MruNode *plist,
|
||||
FTC_MruNode node );
|
||||
|
||||
FT_EXPORT( void )
|
||||
FTC_MruNode_Remove( FTC_MruNode *plist,
|
||||
FTC_MruNode node );
|
||||
|
||||
typedef struct FTC_MruListRec_* FTC_MruList;
|
||||
|
||||
typedef struct FTC_MruListClassRec_ const * FTC_MruListClass;
|
||||
|
||||
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( FTC_MruNode )
|
||||
FTC_MruList_Find( FTC_MruList list,
|
||||
FT_Pointer key );
|
||||
|
||||
FT_EXPORT( FT_Error )
|
||||
FTC_MruList_New( FTC_MruList list,
|
||||
FT_Pointer key,
|
||||
FTC_MruNode *anode );
|
||||
|
||||
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 */
|
||||
/***************************************************************************/
|
||||
/* */
|
||||
/* 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
|
||||
|
||||
#define xxFT_DEBUG_ERROR
|
||||
#define FTC_INLINE
|
||||
|
||||
FT_BEGIN_HEADER
|
||||
|
||||
typedef struct FTC_MruNodeRec_* FTC_MruNode;
|
||||
|
||||
typedef struct FTC_MruNodeRec_
|
||||
{
|
||||
FTC_MruNode next;
|
||||
FTC_MruNode prev;
|
||||
|
||||
} FTC_MruNodeRec;
|
||||
|
||||
FT_EXPORT( void )
|
||||
FTC_MruNode_Prepend( FTC_MruNode *plist,
|
||||
FTC_MruNode node );
|
||||
|
||||
FT_EXPORT( void )
|
||||
FTC_MruNode_Up( FTC_MruNode *plist,
|
||||
FTC_MruNode node );
|
||||
|
||||
FT_EXPORT( void )
|
||||
FTC_MruNode_Remove( FTC_MruNode *plist,
|
||||
FTC_MruNode node );
|
||||
|
||||
typedef struct FTC_MruListRec_* FTC_MruList;
|
||||
|
||||
typedef struct FTC_MruListClassRec_ const * FTC_MruListClass;
|
||||
|
||||
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( FTC_MruNode )
|
||||
FTC_MruList_Find( FTC_MruList list,
|
||||
FT_Pointer key );
|
||||
|
||||
FT_EXPORT( FT_Error )
|
||||
FTC_MruList_New( FTC_MruList list,
|
||||
FT_Pointer key,
|
||||
FTC_MruNode *anode );
|
||||
|
||||
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 );
|
||||
|
||||
|
||||
#ifdef FTC_INLINE
|
||||
|
||||
#define FTC_MRULIST_LOOKUP( list, key, node, error ) \
|
||||
FT_BEGIN_STMNT \
|
||||
FTC_MruNode_CompareFunc _compare = (list)->clazz.node_compare; \
|
||||
FTC_MruNode _first, _node; \
|
||||
\
|
||||
error = 0; \
|
||||
_first = (list)->nodes; \
|
||||
_node = NULL; \
|
||||
\
|
||||
if ( _first ) \
|
||||
{ \
|
||||
_node = _first; \
|
||||
do \
|
||||
{ \
|
||||
if ( _compare( _node, (key) ) ) \
|
||||
{ \
|
||||
*(FTC_MruNode*)&(node) = _node; \
|
||||
goto _Ok; \
|
||||
} \
|
||||
_node = _node->next; \
|
||||
} \
|
||||
while ( _node != _first) ; \
|
||||
} \
|
||||
\
|
||||
error = FTC_MruList_New( (list), (key), (FTC_MruNode*)&(node) ); \
|
||||
_Ok: \
|
||||
; \
|
||||
FT_END_STMNT
|
||||
|
||||
#else /* !FTC_INLINE */
|
||||
|
||||
#define FTC_MRULIST_LOOKUP_CMP( list, key, node, error ) \
|
||||
error = FTC_MruList_Lookup( (list), (key), (FTC_MruNode*)&(node) )
|
||||
|
||||
#endif /* !FTC_INLINE */
|
||||
|
||||
|
||||
#define FTC_MRULIST_LOOP( list, node ) \
|
||||
FT_BEGIN_STMNT \
|
||||
FTC_MruNode _first = (list)->nodes; \
|
||||
\
|
||||
if ( _first ) \
|
||||
{ \
|
||||
FTC_MruNode _node = _first; \
|
||||
do \
|
||||
{ \
|
||||
*(FTC_MruNode*)&(node) = _node;
|
||||
|
||||
|
||||
#define FTC_MRULIST_LOOP_END() \
|
||||
_node = _node->next; \
|
||||
} \
|
||||
while ( _node != _first ); \
|
||||
} \
|
||||
FT_END_STMNT
|
||||
|
||||
/* */
|
||||
|
||||
FT_END_HEADER
|
||||
|
||||
|
||||
#endif /* __FTCMRU_H__ */
|
||||
|
||||
|
||||
/* END */
|
||||
|
|
|
@ -1,373 +1,393 @@
|
|||
#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_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;
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* 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) NULL,
|
||||
(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;
|
||||
|
||||
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) NULL,
|
||||
(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;
|
||||
}
|
||||
|
||||
#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_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;
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* 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) NULL,
|
||||
(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;
|
||||
|
||||
#if 1 /* inlining is about 50% faster !! */
|
||||
FTC_GCACHE_LOOKUP_CMP( cache,
|
||||
ftc_basic_family_compare,
|
||||
FTC_GNode_Compare,
|
||||
hash, gindex,
|
||||
&query,
|
||||
node,
|
||||
error );
|
||||
#else
|
||||
error = FTC_GCache_Lookup( FTC_GCACHE( cache ),
|
||||
hash, gindex,
|
||||
FTC_GQUERY( &query ),
|
||||
(FTC_Node*) &node );
|
||||
#endif
|
||||
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) NULL,
|
||||
(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);
|
||||
|
||||
#if 1 /* inlining is about 50% faster !! */
|
||||
FTC_GCACHE_LOOKUP_CMP( cache,
|
||||
ftc_basic_family_compare,
|
||||
FTC_SNode_Compare,
|
||||
hash, gindex,
|
||||
&query,
|
||||
node,
|
||||
error );
|
||||
#else
|
||||
error = FTC_GCache_Lookup( FTC_GCACHE( cache ),
|
||||
hash,
|
||||
gindex,
|
||||
FTC_GQUERY( &query ),
|
||||
(FTC_Node*) &node );
|
||||
#endif
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,266 +1,271 @@
|
|||
/***************************************************************************/
|
||||
/* */
|
||||
/* ftccmap.c */
|
||||
/* */
|
||||
/* FreeType CharMap 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_FREETYPE_H
|
||||
#include FT_CACHE_H
|
||||
#include FT_CACHE_INTERNAL_MANAGER_H
|
||||
#include FT_INTERNAL_MEMORY_H
|
||||
#include FT_INTERNAL_DEBUG_H
|
||||
#include FT_TRUETYPE_IDS_H
|
||||
|
||||
#include "ftcerror.h"
|
||||
|
||||
#undef FT_COMPONENT
|
||||
#define FT_COMPONENT trace_cache
|
||||
|
||||
/*************************************************************************/
|
||||
/* */
|
||||
/* Each FTC_CMapNode contains a simple array to map a range of character */
|
||||
/* codes to equivalent glyph indices. */
|
||||
/* */
|
||||
/* For now, the implementation is very basic: Each node maps a range of */
|
||||
/* 128 consecutive character codes to their corresponding glyph indices. */
|
||||
/* */
|
||||
/* We could do more complex things, but I don't think it is really very */
|
||||
/* useful. */
|
||||
/* */
|
||||
/*************************************************************************/
|
||||
|
||||
|
||||
/* 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 )
|
||||
|
||||
/* 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 )
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/***** *****/
|
||||
/***** CHARMAP NODES *****/
|
||||
/***** *****/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
|
||||
/* no need for specific finalizer; we use "ftc_node_done" directly */
|
||||
|
||||
FT_CALLBACK_DEF( void )
|
||||
ftc_cmap_node_free( FTC_CMapNode node,
|
||||
FTC_Cache cache )
|
||||
{
|
||||
FT_Memory memory = cache->memory;
|
||||
|
||||
FT_FREE( node );
|
||||
}
|
||||
|
||||
|
||||
/* 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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
/* compute the weight of a given cmap node */
|
||||
FT_CALLBACK_DEF( FT_ULong )
|
||||
ftc_cmap_node_weight( FTC_CMapNode cnode )
|
||||
{
|
||||
FT_UNUSED( cnode );
|
||||
|
||||
return sizeof ( *cnode );
|
||||
}
|
||||
|
||||
|
||||
/* compare a cmap node to a given query */
|
||||
FT_CALLBACK_DEF( FT_Bool )
|
||||
ftc_cmap_node_compare( FTC_CMapNode node,
|
||||
FTC_CMapQuery query )
|
||||
{
|
||||
if ( node->face_id == query->face_id &&
|
||||
node->cmap_index == query->cmap_index )
|
||||
{
|
||||
FT_UInt32 offset = (FT_UInt32)( query->char_code - node->first );
|
||||
|
||||
return FT_BOOL( offset < FTC_CMAP_INDICES_MAX );
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
FT_CALLBACK_DEF( FT_Bool )
|
||||
ftc_cmap_node_remove_faceid( FTC_CMapNode node,
|
||||
FTC_FaceID face_id )
|
||||
{
|
||||
return FT_BOOL( node->face_id == face_id );
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/***** *****/
|
||||
/***** GLYPH IMAGE CACHE *****/
|
||||
/***** *****/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
|
||||
FT_CALLBACK_TABLE_DEF
|
||||
const FTC_CacheClassRec ftc_cmap_cache_class =
|
||||
{
|
||||
(FTC_Node_NewFunc) ftc_cmap_node_new,
|
||||
(FTC_Node_WeightFunc) ftc_cmap_node_weight,
|
||||
(FTC_Node_CompareFunc) ftc_cmap_node_compare,
|
||||
(FTC_Node_CompareFunc) ftc_cmap_node_remove_faceid,
|
||||
(FTC_Node_FreeFunc) ftc_cmap_node_free,
|
||||
|
||||
sizeof ( FTC_CacheRec ),
|
||||
(FTC_Cache_InitFunc) FTC_Cache_Init,
|
||||
(FTC_Cache_DoneFunc) FTC_Cache_Done,
|
||||
};
|
||||
|
||||
/* documentation is in ftccmap.h */
|
||||
|
||||
FT_EXPORT_DEF( FT_Error )
|
||||
FTC_CMapCache_New( FTC_Manager manager,
|
||||
FTC_CMapCache *acache )
|
||||
{
|
||||
return FTC_Manager_RegisterCache( manager,
|
||||
& ftc_cmap_cache_class,
|
||||
FTC_CACHE_P( acache ) );
|
||||
}
|
||||
/* documentation is in ftccmap.h */
|
||||
|
||||
FT_EXPORT_DEF( FT_UInt )
|
||||
FTC_CMapCache_Lookup( FTC_CMapCache cmap_cache,
|
||||
FTC_FaceID face_id,
|
||||
FT_Int cmap_index,
|
||||
FT_UInt32 char_code )
|
||||
{
|
||||
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 )
|
||||
{
|
||||
FT_ERROR(( "FTC_CMapCache_Lookup: bad arguments, returning 0!\n" ));
|
||||
return 0;
|
||||
}
|
||||
|
||||
query.face_id = face_id;
|
||||
query.cmap_index = (FT_UInt)cmap_index;
|
||||
query.char_code = char_code;
|
||||
|
||||
hash = FTC_CMAP_HASH( face_id, cmap_index, char_code );
|
||||
|
||||
error = FTC_Cache_Lookup( cache, hash, &query, (FTC_Node*) &node );
|
||||
if ( error )
|
||||
goto Exit;
|
||||
|
||||
FT_ASSERT( (FT_UInt)( char_code - node->first ) < FTC_CMAP_INDICES_MAX );
|
||||
|
||||
gindex = node->indices[ char_code - node->first ];
|
||||
if ( gindex == FTC_CMAP_UNKNOWN )
|
||||
{
|
||||
FT_Face face;
|
||||
|
||||
gindex = 0;
|
||||
|
||||
error = FTC_Manager_LookupFace( cache->manager, node->face_id, &face );
|
||||
if ( error )
|
||||
goto Exit;
|
||||
|
||||
if ( (FT_UInt)cmap_index < (FT_UInt)face->num_charmaps )
|
||||
{
|
||||
FT_CharMap old, cmap = NULL;
|
||||
|
||||
old = face->charmap;
|
||||
cmap = face->charmaps[ cmap_index ];
|
||||
|
||||
if (old != cmap)
|
||||
FT_Set_Charmap( face, cmap );
|
||||
|
||||
gindex = FT_Get_Char_Index( face, char_code );
|
||||
|
||||
if (old != cmap)
|
||||
FT_Set_Charmap( face, old );
|
||||
}
|
||||
|
||||
node->indices[ char_code - node->first ] = gindex;
|
||||
}
|
||||
|
||||
Exit:
|
||||
return gindex;
|
||||
}
|
||||
|
||||
/* END */
|
||||
/***************************************************************************/
|
||||
/* */
|
||||
/* ftccmap.c */
|
||||
/* */
|
||||
/* FreeType CharMap 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_FREETYPE_H
|
||||
#include FT_CACHE_H
|
||||
#include FT_CACHE_INTERNAL_MANAGER_H
|
||||
#include FT_INTERNAL_MEMORY_H
|
||||
#include FT_INTERNAL_DEBUG_H
|
||||
#include FT_TRUETYPE_IDS_H
|
||||
|
||||
#include "ftcerror.h"
|
||||
|
||||
#undef FT_COMPONENT
|
||||
#define FT_COMPONENT trace_cache
|
||||
|
||||
/*************************************************************************/
|
||||
/* */
|
||||
/* Each FTC_CMapNode contains a simple array to map a range of character */
|
||||
/* codes to equivalent glyph indices. */
|
||||
/* */
|
||||
/* For now, the implementation is very basic: Each node maps a range of */
|
||||
/* 128 consecutive character codes to their corresponding glyph indices. */
|
||||
/* */
|
||||
/* We could do more complex things, but I don't think it is really very */
|
||||
/* useful. */
|
||||
/* */
|
||||
/*************************************************************************/
|
||||
|
||||
|
||||
/* 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 )
|
||||
|
||||
/* 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 )
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/***** *****/
|
||||
/***** CHARMAP NODES *****/
|
||||
/***** *****/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
|
||||
/* no need for specific finalizer; we use "ftc_node_done" directly */
|
||||
|
||||
FT_CALLBACK_DEF( void )
|
||||
ftc_cmap_node_free( FTC_CMapNode node,
|
||||
FTC_Cache cache )
|
||||
{
|
||||
FT_Memory memory = cache->memory;
|
||||
|
||||
FT_FREE( node );
|
||||
}
|
||||
|
||||
|
||||
/* 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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
/* compute the weight of a given cmap node */
|
||||
FT_CALLBACK_DEF( FT_ULong )
|
||||
ftc_cmap_node_weight( FTC_CMapNode cnode )
|
||||
{
|
||||
FT_UNUSED( cnode );
|
||||
|
||||
return sizeof ( *cnode );
|
||||
}
|
||||
|
||||
|
||||
/* compare a cmap node to a given query */
|
||||
FT_CALLBACK_DEF( FT_Bool )
|
||||
ftc_cmap_node_compare( FTC_CMapNode node,
|
||||
FTC_CMapQuery query )
|
||||
{
|
||||
if ( node->face_id == query->face_id &&
|
||||
node->cmap_index == query->cmap_index )
|
||||
{
|
||||
FT_UInt32 offset = (FT_UInt32)( query->char_code - node->first );
|
||||
|
||||
return FT_BOOL( offset < FTC_CMAP_INDICES_MAX );
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
FT_CALLBACK_DEF( FT_Bool )
|
||||
ftc_cmap_node_remove_faceid( FTC_CMapNode node,
|
||||
FTC_FaceID face_id )
|
||||
{
|
||||
return FT_BOOL( node->face_id == face_id );
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/***** *****/
|
||||
/***** GLYPH IMAGE CACHE *****/
|
||||
/***** *****/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
|
||||
FT_CALLBACK_TABLE_DEF
|
||||
const FTC_CacheClassRec ftc_cmap_cache_class =
|
||||
{
|
||||
(FTC_Node_NewFunc) ftc_cmap_node_new,
|
||||
(FTC_Node_WeightFunc) ftc_cmap_node_weight,
|
||||
(FTC_Node_CompareFunc) ftc_cmap_node_compare,
|
||||
(FTC_Node_CompareFunc) ftc_cmap_node_remove_faceid,
|
||||
(FTC_Node_FreeFunc) ftc_cmap_node_free,
|
||||
|
||||
sizeof ( FTC_CacheRec ),
|
||||
(FTC_Cache_InitFunc) FTC_Cache_Init,
|
||||
(FTC_Cache_DoneFunc) FTC_Cache_Done,
|
||||
};
|
||||
|
||||
/* documentation is in ftccmap.h */
|
||||
|
||||
FT_EXPORT_DEF( FT_Error )
|
||||
FTC_CMapCache_New( FTC_Manager manager,
|
||||
FTC_CMapCache *acache )
|
||||
{
|
||||
return FTC_Manager_RegisterCache( manager,
|
||||
& ftc_cmap_cache_class,
|
||||
FTC_CACHE_P( acache ) );
|
||||
}
|
||||
/* documentation is in ftccmap.h */
|
||||
|
||||
FT_EXPORT_DEF( FT_UInt )
|
||||
FTC_CMapCache_Lookup( FTC_CMapCache cmap_cache,
|
||||
FTC_FaceID face_id,
|
||||
FT_Int cmap_index,
|
||||
FT_UInt32 char_code )
|
||||
{
|
||||
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 )
|
||||
{
|
||||
FT_ERROR(( "FTC_CMapCache_Lookup: bad arguments, returning 0!\n" ));
|
||||
return 0;
|
||||
}
|
||||
|
||||
query.face_id = face_id;
|
||||
query.cmap_index = (FT_UInt)cmap_index;
|
||||
query.char_code = char_code;
|
||||
|
||||
hash = FTC_CMAP_HASH( face_id, cmap_index, char_code );
|
||||
|
||||
#if 1
|
||||
FTC_CACHE_LOOKUP_CMP( cache, ftc_cmap_node_compare, hash, &query,
|
||||
node, error );
|
||||
#else
|
||||
error = FTC_Cache_Lookup( cache, hash, &query, (FTC_Node*) &node );
|
||||
#endif
|
||||
if ( error )
|
||||
goto Exit;
|
||||
|
||||
FT_ASSERT( (FT_UInt)( char_code - node->first ) < FTC_CMAP_INDICES_MAX );
|
||||
|
||||
gindex = node->indices[ char_code - node->first ];
|
||||
if ( gindex == FTC_CMAP_UNKNOWN )
|
||||
{
|
||||
FT_Face face;
|
||||
|
||||
gindex = 0;
|
||||
|
||||
error = FTC_Manager_LookupFace( cache->manager, node->face_id, &face );
|
||||
if ( error )
|
||||
goto Exit;
|
||||
|
||||
if ( (FT_UInt)cmap_index < (FT_UInt)face->num_charmaps )
|
||||
{
|
||||
FT_CharMap old, cmap = NULL;
|
||||
|
||||
old = face->charmap;
|
||||
cmap = face->charmaps[ cmap_index ];
|
||||
|
||||
if (old != cmap)
|
||||
FT_Set_Charmap( face, cmap );
|
||||
|
||||
gindex = FT_Get_Char_Index( face, char_code );
|
||||
|
||||
if (old != cmap)
|
||||
FT_Set_Charmap( face, old );
|
||||
}
|
||||
|
||||
node->indices[ char_code - node->first ] = gindex;
|
||||
}
|
||||
|
||||
Exit:
|
||||
return gindex;
|
||||
}
|
||||
|
||||
/* END */
|
||||
|
|
|
@ -1,153 +1,152 @@
|
|||
/***************************************************************************/
|
||||
/* */
|
||||
/* ftcglyph.c */
|
||||
/* */
|
||||
/* FreeType Glyph Image (FT_Glyph) cache (body). */
|
||||
/* */
|
||||
/* Copyright 2000-2001 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_GLYPH_H
|
||||
#include FT_ERRORS_H
|
||||
#include FT_INTERNAL_OBJECTS_H
|
||||
#include FT_INTERNAL_DEBUG_H
|
||||
|
||||
#include "ftcerror.h"
|
||||
|
||||
|
||||
/* create a new chunk node, setting its cache index and ref count */
|
||||
FT_EXPORT_DEF( void )
|
||||
FTC_GNode_Init( FTC_GNode gnode,
|
||||
FT_UInt gindex,
|
||||
FTC_Family family )
|
||||
{
|
||||
gnode->family = family;
|
||||
gnode->gindex = gindex;
|
||||
family->num_nodes++;
|
||||
}
|
||||
|
||||
|
||||
FT_EXPORT_DEF( void )
|
||||
FTC_GNode_UnselectFamily( FTC_GNode gnode,
|
||||
FTC_Cache cache )
|
||||
{
|
||||
FTC_Family family = gnode->family;
|
||||
|
||||
gnode->family = NULL;
|
||||
if ( family && --family->num_nodes <= 0 )
|
||||
{
|
||||
FTC_MruList_Remove( & FTC_GCACHE(cache)->families, (FTC_MruNode)family );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
FT_EXPORT_DEF( void )
|
||||
FTC_GNode_Done( FTC_GNode gnode,
|
||||
FTC_Cache cache )
|
||||
{
|
||||
/* finalize the node */
|
||||
gnode->gindex = 0;
|
||||
|
||||
FTC_GNode_UnselectFamily( gnode, cache );
|
||||
}
|
||||
|
||||
|
||||
FT_EXPORT_DEF( FT_Bool )
|
||||
FTC_GNode_Compare( FTC_GNode gnode,
|
||||
FTC_GQuery gquery )
|
||||
{
|
||||
return FT_BOOL( gnode->family == gquery->family &&
|
||||
gnode->gindex == gquery->gindex );
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/***** *****/
|
||||
/***** CHUNK SETS *****/
|
||||
/***** *****/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
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;
|
||||
family->cache = cache;
|
||||
}
|
||||
|
||||
|
||||
FT_EXPORT_DEF( FT_Error )
|
||||
FTC_GCache_Init( FTC_GCache cache )
|
||||
{
|
||||
FT_Error error;
|
||||
|
||||
error = FTC_Cache_Init( FTC_CACHE(cache) );
|
||||
if ( !error )
|
||||
{
|
||||
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_GCache_Done( FTC_GCache cache )
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
/* END */
|
||||
/***************************************************************************/
|
||||
/* */
|
||||
/* ftcglyph.c */
|
||||
/* */
|
||||
/* FreeType Glyph Image (FT_Glyph) cache (body). */
|
||||
/* */
|
||||
/* Copyright 2000-2001 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_GLYPH_H
|
||||
#include FT_ERRORS_H
|
||||
#include FT_INTERNAL_OBJECTS_H
|
||||
#include FT_INTERNAL_DEBUG_H
|
||||
|
||||
#include "ftcerror.h"
|
||||
|
||||
|
||||
/* create a new chunk node, setting its cache index and ref count */
|
||||
FT_EXPORT_DEF( void )
|
||||
FTC_GNode_Init( FTC_GNode gnode,
|
||||
FT_UInt gindex,
|
||||
FTC_Family family )
|
||||
{
|
||||
gnode->family = family;
|
||||
gnode->gindex = gindex;
|
||||
family->num_nodes++;
|
||||
}
|
||||
|
||||
|
||||
FT_EXPORT_DEF( void )
|
||||
FTC_GNode_UnselectFamily( FTC_GNode gnode,
|
||||
FTC_Cache cache )
|
||||
{
|
||||
FTC_Family family = gnode->family;
|
||||
|
||||
gnode->family = NULL;
|
||||
if ( family && --family->num_nodes <= 0 )
|
||||
{
|
||||
FTC_MruList_Remove( & FTC_GCACHE(cache)->families, (FTC_MruNode)family );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
FT_EXPORT_DEF( void )
|
||||
FTC_GNode_Done( FTC_GNode gnode,
|
||||
FTC_Cache cache )
|
||||
{
|
||||
/* finalize the node */
|
||||
gnode->gindex = 0;
|
||||
|
||||
FTC_GNode_UnselectFamily( gnode, cache );
|
||||
}
|
||||
|
||||
|
||||
FT_EXPORT_DEF( FT_Bool )
|
||||
FTC_GNode_Compare( FTC_GNode gnode,
|
||||
FTC_GQuery gquery )
|
||||
{
|
||||
return FT_BOOL( gnode->family == gquery->family &&
|
||||
gnode->gindex == gquery->gindex );
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/***** *****/
|
||||
/***** CHUNK SETS *****/
|
||||
/***** *****/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
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;
|
||||
family->cache = cache;
|
||||
}
|
||||
|
||||
|
||||
FT_EXPORT_DEF( FT_Error )
|
||||
FTC_GCache_Init( FTC_GCache cache )
|
||||
{
|
||||
FT_Error error;
|
||||
|
||||
error = FTC_Cache_Init( FTC_CACHE(cache) );
|
||||
if ( !error )
|
||||
{
|
||||
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_GCache_Done( FTC_GCache cache )
|
||||
{
|
||||
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;
|
||||
|
||||
FTC_MRULIST_LOOKUP( &cache->families, query, query->family, error );
|
||||
if ( !error )
|
||||
error = FTC_Cache_Lookup( FTC_CACHE(cache), hash, query, anode );
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
/* END */
|
||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue