ref: 89f331b7130c22fd93bb1b15381eae9c6da2a8a5
parent: 32174ffba29883763853c45b74fd75ef59508c70
author: David Turner <[email protected]>
date: Sat Dec 20 20:41:32 EST 2003
important bug fixes for new cache code
--- a/include/freetype/cache/ftccache.h
+++ b/include/freetype/cache/ftccache.h
@@ -19,8 +19,8 @@
#ifndef __FTCCACHE_H__
#define __FTCCACHE_H__
+#include FT_CACHE_INTERNAL_MRU_H
-
FT_BEGIN_HEADER
/* handle to cache object */
@@ -52,12 +52,11 @@
/* structure size should be 20 bytes on 32-bits machines */
typedef struct FTC_NodeRec_
{
- FTC_Node mru_next; /* circular mru list pointer */
- FTC_Node mru_prev; /* 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_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;
@@ -65,6 +64,8 @@
#define FTC_NODE( x ) ( (FTC_Node)(x) )
#define FTC_NODE_P( x ) ( (FTC_Node*)(x) )
+#define FTC_NODE__MRU_NEXT(x) FTC_NODE( (x)->mru.next )
+#define FTC_NODE__MRU_PREV(x) FTC_NODE( (x)->mru.prev )
/*************************************************************************/
/* */
--- a/include/freetype/cache/ftcglyph.h
+++ b/include/freetype/cache/ftcglyph.h
@@ -54,12 +54,12 @@
*
*
* 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
+ * my_node_remove_faceid ( must call ftc_gnode_unselect in case
* of match )
*
*
@@ -130,13 +130,14 @@
*
* families are implemented as MRU list nodes. They are reference-counted
*/
-
+
typedef struct FTC_FamilyRec_
{
- FTC_MruNode mrunode;
+ 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) )
@@ -166,16 +167,7 @@
- /* each glyph node contains a 'chunk' of glyph items; */
- /* translate a glyph index into a chunk index */
-#define FTC_FAMILY_CHUNK( gfam, gindex ) \
- ( ( gindex ) / FTC_FAMILY( gfam )->item_count )
- /* find a glyph index's chunk, and return its start index */
-#define FTC_FAMILY_START( gfam, gindex ) \
- ( FTC_FAMILY_CHUNK( gfam, gindex ) * \
- FTC_FAMILY( gfam )->item_count )
-
/*************************************************************************/
/* */
/* These functions are exported so that they can be called from */
@@ -209,6 +201,10 @@
FTC_Cache cache );
+ FT_EXPORT( void )
+ FTC_Family_Init( FTC_Family family,
+ FTC_Cache cache );
+
typedef struct FTC_GCacheRec_
{
FTC_CacheRec cache;
@@ -243,6 +239,7 @@
#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 */
@@ -259,7 +256,7 @@
FTC_Node *anode );
/* */
-
+
FT_END_HEADER
--- a/include/freetype/cache/ftcmanag.h
+++ b/include/freetype/cache/ftcmanag.h
@@ -71,6 +71,7 @@
FT_BEGIN_HEADER
+#define FT_DEBUG_ERROR
/*************************************************************************/
/* */
@@ -96,7 +97,7 @@
FT_ULong max_weight;
FT_ULong cur_weight;
FT_UInt num_nodes;
-
+
FTC_Cache caches[ FTC_MAX_CACHES ];
FT_UInt num_caches;
@@ -158,7 +159,7 @@
FT_Int pixel;
FT_UInt x_res;
FT_UInt y_res;
-
+
} FTC_ScalerRec, *FTC_Scaler;
@@ -167,14 +168,14 @@
(a)->width == (b)->width && \
(a)->height == (b)->height && \
((a)->pixel != 0) == ((b)->pixel != 0) && \
- ( (a)->pixel || \
- ( (a)->x_res == (b)->x_res && \
+ ( (a)->pixel || \
+ ( (a)->x_res == (b)->x_res && \
(a)->y_res == (b)->y_res ) ) )
#define FTC_SCALER_HASH(q) \
( FTC_FACE_ID_HASH((q)->face_id) + \
(q)->width + (q)->height*7 + \
- (q)->pixel ? ( (q)->x_res*33 ^ (q)->y_res*61 ) : 0 )
+ ( (q)->pixel ? 0 : ( (q)->x_res*33 ^ (q)->y_res*61 ) ) )
FT_EXPORT( FT_Error )
--- a/include/freetype/cache/ftcmru.h
+++ b/include/freetype/cache/ftcmru.h
@@ -56,18 +56,33 @@
FT_BEGIN_HEADER
- typedef struct FTC_MruListRec_* FTC_MruList;
-
typedef struct FTC_MruNodeRec_* FTC_MruNode;
- typedef struct FTC_MruListClassRec_ const * FTC_MruListClass;
-
typedef struct FTC_MruNodeRec_
{
FTC_MruNode next;
+ FTC_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 );
@@ -92,6 +107,7 @@
} FTC_MruListClassRec;
+
typedef struct FTC_MruListRec_
{
FT_UInt num_nodes;
@@ -119,14 +135,22 @@
FTC_MruList_Done( FTC_MruList list );
- FT_EXPORT( FT_Error )
+ FT_EXPORT( FTC_MruNode )
FTC_MruList_Lookup( FTC_MruList list,
- FT_Pointer key,
- FTC_MruNode *pnode );
+ FT_Pointer key );
FT_EXPORT( void )
- FTC_MruList_Remove( FTC_MruList list,
- FTC_MruNode node );
+ FTC_MruList_Up( FTC_MruList list,
+ FTC_MruNode node );
+
+ FT_EXPORT( FT_Error )
+ FTC_MruList_New( FTC_MruList list,
+ FT_Pointer key,
+ FTC_MruNode *anode );
+
+ FT_EXPORT( void )
+ FTC_MruList_Remove( FTC_MruList list,
+ FTC_MruNode node );
FT_EXPORT( void )
FTC_MruList_RemoveSelection( FTC_MruList list,
--- a/src/cache/descrip.mms
+++ b/src/cache/descrip.mms
@@ -20,7 +20,7 @@
all : $(OBJS)
library [--.lib]freetype.olb $(OBJS)
-ftcache.obj : ftcache.c ftlru.c ftcmanag.c ftccache.c ftcglyph.c ftcimage.c \
- ftcsbits.c ftccmap.c
+ftcache.obj : ftcache.c ftcmru.c ftcmanag.c ftccache.c ftcglyph.c ftcimage.c \
+ ftcsbits.c ftccmap.c ftcbasic.c
# EOF
--- a/src/cache/ftcbasic.c
+++ b/src/cache/ftcbasic.c
@@ -57,20 +57,12 @@
FTC_BasicQuery query,
FTC_Cache cache )
{
- ftc_family_init( FTC_FAMILY( family ), cache );
+ FTC_Family_Init( FTC_FAMILY( family ), cache );
family->attrs = query->attrs;
return 0;
}
- static FT_Error
- ftc_basic_family_reset( FTC_BasicFamily family,
- FTC_BasicQuery query )
- {
- family->attrs = query->attrs;
- return 0;
- }
-
static FT_Bool
ftc_basic_gnode_compare_faceid( FTC_GNode gnode,
FTC_FaceID face_id,
@@ -188,7 +180,7 @@
sizeof( FTC_BasicFamilyRec ),
(FTC_MruNode_CompareFunc) ftc_basic_family_compare,
(FTC_MruNode_InitFunc) ftc_basic_family_init,
- (FTC_MruNode_ResetFunc) ftc_basic_family_reset,
+ (FTC_MruNode_ResetFunc) NULL,
(FTC_MruNode_DoneFunc) NULL
},
(FTC_IFamily_LoadGlyphFunc) ftc_basic_family_load_glyph
@@ -290,7 +282,7 @@
sizeof( FTC_BasicFamilyRec ),
(FTC_MruNode_CompareFunc) ftc_basic_family_compare,
(FTC_MruNode_InitFunc) ftc_basic_family_init,
- (FTC_MruNode_ResetFunc) ftc_basic_family_reset,
+ (FTC_MruNode_ResetFunc) NULL,
(FTC_MruNode_DoneFunc) NULL
},
(FTC_SFamily_GetCountFunc) ftc_basic_family_get_count,
--- a/src/cache/ftccache.c
+++ b/src/cache/ftccache.c
@@ -29,7 +29,7 @@
#define FTC_HASH_SUB_LOAD ( FTC_HASH_MAX_LOAD - FTC_HASH_MIN_LOAD )
/* this one _must_ be a power of 2! */
-#define FTC_HASH_INITIAL_SIZE 8
+#define FTC_HASH_INITIAL_SIZE 512
/*************************************************************************/
@@ -45,31 +45,7 @@
ftc_node_mru_link( FTC_Node node,
FTC_Manager manager )
{
- FTC_Node first = manager->nodes_list;
-
-
- if ( first )
- {
- FTC_Node last = first->mru_prev;
-
-
- FT_ASSERT( last->mru_next == first );
-
- node->mru_prev = last;
- node->mru_next = first;
-
- last->mru_next = node;
- first->mru_prev = node;
- }
- else
- {
- FT_ASSERT( manager->num_nodes == 0 );
-
- node->mru_next = node;
- node->mru_prev = node;
- }
-
- manager->nodes_list = node;
+ FTC_MruNode_Prepend( (FTC_MruNode*)&manager->nodes_list, (FTC_MruNode)node );
manager->num_nodes++;
}
@@ -79,29 +55,7 @@
ftc_node_mru_unlink( FTC_Node node,
FTC_Manager manager )
{
- FTC_Node first = manager->nodes_list;
- FTC_Node prev = node->mru_prev;
- FTC_Node next = node->mru_next;
-
-
- FT_ASSERT( first != NULL && manager->num_nodes > 0 );
- FT_ASSERT( next->mru_prev == node );
- FT_ASSERT( prev->mru_next == node );
-
- next->mru_prev = prev;
- prev->mru_next = next;
-
- if ( node == first )
- {
- /* this is the last node in the list; update its head pointer */
- if ( node == next )
- manager->nodes_list = NULL;
- else
- manager->nodes_list = next;
- }
-
- node->mru_next = NULL;
- node->mru_prev = NULL;
+ FTC_MruNode_Remove( (FTC_MruNode*)&manager->nodes_list, (FTC_MruNode)node );
manager->num_nodes--;
}
@@ -111,27 +65,7 @@
ftc_node_mru_up( FTC_Node node,
FTC_Manager manager )
{
- FTC_Node first = manager->nodes_list;
-
-
- if ( node != first )
- {
- FTC_Node prev = node->mru_prev;
- FTC_Node next = node->mru_next;
- FTC_Node last;
-
-
- prev->mru_next = next;
- next->mru_prev = prev;
-
- last = first->mru_prev;
- node->mru_next = first;
- node->mru_prev = last;
- first->mru_prev = node;
- last->mru_next = node;
-
- manager->nodes_list = node;
- }
+ FTC_MruNode_Up( (FTC_MruNode*)&manager->nodes_list, (FTC_MruNode)node );
}
@@ -142,6 +76,9 @@
static void
ftc_cache_resize( FTC_Cache cache )
{
+#if 1
+ FT_UNUSED(cache);
+#else
for (;;)
{
FTC_Node node, *pnode;
@@ -236,6 +173,7 @@
else /* the hash table is balanced */
break;
}
+#endif
}
@@ -559,6 +497,10 @@
}
AddNode:
+ node->ref_count = 0;
+ node->cache_index = (FT_UInt16) cache->index;
+ node->hash = hash;
+
/* don't assume that the cache has the same number of buckets, since
* our allocation request might have triggered global cache flushing
*/
@@ -623,5 +565,6 @@
ftc_cache_resize( cache );
}
+
/* END */
--- a/src/cache/ftccache.i
+++ /dev/null
@@ -1,157 +1,0 @@
-/***************************************************************************/
-/* */
-/* ftccache.i */
-/* */
-/* FreeType template for generic cache. */
-/* */
-/* Copyright 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 GEN_CACHE_FAMILY_COMPARE
-#error "GEN_CACHE_FAMILY_COMPARE not defined in template instantiation"
-#endif
-
-#ifndef GEN_CACHE_NODE_COMPARE
-#error "GEN_CACHE_NODE_COMPARE not defined in template instantiation"
-#endif
-
-
- static FT_Error
- GEN_CACHE_LOOKUP( FTC_Cache cache,
- FTC_Query query,
- FTC_Node *anode )
- {
- FT_LruNode lru;
- FTC_Family family;
- FT_UFast hash;
-
-
- query->hash = 0;
- query->family = NULL;
-
- /* XXX: we break encapsulation for the sake of speed! */
- {
- /* first of all, find the relevant family */
- FT_LruList list = cache->families;
- FT_LruNode fam, *pfam;
-
-
- pfam = &list->nodes;
- for (;;)
- {
- fam = *pfam;
- if ( fam == NULL )
- goto Normal;
-
- if ( GEN_CACHE_FAMILY_COMPARE( fam, query, list->data ) )
- break;
-
- pfam = &fam->next;
- }
-
- FT_ASSERT( fam != NULL );
-
- /* move to top of list when needed */
- if ( fam != list->nodes )
- {
- *pfam = fam->next;
- fam->next = list->nodes;
- list->nodes = fam;
- }
-
- lru = fam;
- }
-
- {
- FTC_Node node, *pnode, *bucket;
-
-
- family = (FTC_Family)lru;
- hash = query->hash;
-
- {
- FT_UInt idx;
-
-
- idx = hash & cache->mask;
- if ( idx < cache->p )
- idx = hash & ( cache->mask * 2 + 1 );
-
- bucket = cache->buckets + idx;
- }
-
- pnode = bucket;
-
- for ( ;; )
- {
- node = *pnode;
- if ( node == NULL )
- goto Normal;
-
- if ( node->hash == hash &&
- (FT_UInt)node->fam_index == family->fam_index &&
- GEN_CACHE_NODE_COMPARE( node, query, cache ) )
- {
- /* we place the following out of the loop to make it */
- /* as small as possible... */
- goto Found;
- }
-
- pnode = &node->link;
- }
-
- Normal:
- return ftc_cache_lookup( cache, query, anode );
-
- Found:
- /* move to head of bucket list */
- if ( pnode != bucket )
- {
- *pnode = node->link;
- node->link = *bucket;
- *bucket = node;
- }
-
- /* move to head of MRU list */
- if ( node != cache->manager->nodes_list )
- {
- /* XXX: again, this is an inlined version of ftc_node_mru_up */
- FTC_Manager manager = cache->manager;
- FTC_Node first = manager->nodes_list;
- FTC_Node prev = node->mru_prev;
- FTC_Node next = node->mru_next;
- FTC_Node last;
-
-
- prev->mru_next = next;
- next->mru_prev = prev;
-
- last = first->mru_prev;
- node->mru_next = first;
- node->mru_prev = last;
- first->mru_prev = node;
- last->mru_next = node;
-
- manager->nodes_list = node;
- }
-
- *anode = node;
- return 0;
- }
- }
-
-#undef GEN_CACHE_NODE_COMPARE
-#undef GEN_CACHE_FAMILY_COMPARE
-#undef GEN_CACHE_LOOKUP
-
-
-/* END */
--- a/src/cache/ftcglyph.c
+++ b/src/cache/ftcglyph.c
@@ -26,6 +26,7 @@
#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,
@@ -34,6 +35,7 @@
{
gnode->family = family;
gnode->gindex = gindex;
+
family->num_nodes++;
}
@@ -79,7 +81,7 @@
/*************************************************************************/
FT_EXPORT_DEF( void )
- ftc_family_init( FTC_Family family,
+ FTC_Family_Init( FTC_Family family,
FTC_Cache cache )
{
FTC_GCacheClass clazz = FTC_CACHE__GCACHE_CLASS(cache);
@@ -86,6 +88,7 @@
family->clazz = clazz->family_class;
family->num_nodes = 0;
+ family->cache = cache;
}
@@ -134,15 +137,27 @@
FTC_GQuery query,
FTC_Node *anode )
{
- FT_Error error;
+ FT_Error error;
+ FTC_Family family;
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 );
+ family = (FTC_Family) FTC_MruList_Lookup( &cache->families, query );
+ if ( family == NULL )
+ {
+ error = FTC_MruList_New( &cache->families, query, (FTC_MruNode*) &family );
+ if ( error )
+ {
+ *anode = NULL;
+ goto Exit;
+ }
+ }
+ query->family = family;
+
+ error = FTC_Cache_Lookup( FTC_CACHE(cache), hash, query, anode );
+
+ Exit:
return error;
}
--- a/src/cache/ftcmanag.c
+++ b/src/cache/ftcmanag.c
@@ -144,7 +144,7 @@
FTC_Scaler scaler,
FT_Size *asize )
{
- FT_Error error;
+ FT_Error error = 0;
FTC_SizeNode node;
@@ -156,16 +156,20 @@
if ( !manager )
return FTC_Err_Invalid_Cache_Handle;
- error = FTC_MruList_Lookup( &manager->sizes,
- scaler,
- (FTC_MruNode*) &node );
+ error = FTC_MruList_Get( &manager->sizes, scaler, (FTC_MruNode*) &node );
if ( !error )
+ {
*asize = node->size;
+ FT_Activate_Size( node->size );
+ }
+ Exit:
return error;
}
+
+
/*************************************************************************/
/*************************************************************************/
/***** *****/
@@ -211,9 +215,6 @@
ftc_face_node_done( FTC_FaceNode node,
FTC_Manager manager )
{
- FT_Memory memory = manager->memory;
-
-
/* we must begin by removing all scalers for the target face */
/* from the manager's list */
FTC_MruList_RemoveSelection(
@@ -222,11 +223,12 @@
node->face_id );
/* all right, we can discard the face now */
- FT_Done_Face( node->face );
- node->face = NULL;
+ if ( node->face )
+ {
+ FT_Done_Face( node->face );
+ node->face = NULL;
+ }
node->face_id = NULL;
-
- FT_FREE( node );
}
@@ -257,7 +259,7 @@
FTC_FaceID face_id,
FT_Face *aface )
{
- FT_Error error;
+ FT_Error error = 0;
FTC_FaceNode node;
@@ -269,12 +271,17 @@
if ( !manager )
return FTC_Err_Invalid_Cache_Handle;
- error = FTC_MruList_Lookup( &manager->faces,
- face_id,
- (FTC_MruNode*) &node );
- if ( !error )
- *aface = node->face;
+ node = (FTC_FaceNode) FTC_MruList_Lookup( &manager->faces, face_id );
+ if ( node == NULL )
+ {
+ error = FTC_MruList_New( &manager->faces, face_id, (FTC_MruNode*) &node );
+ if (error)
+ goto Exit;
+ }
+ *aface = node->face;
+
+ Exit:
return error;
}
@@ -422,7 +429,7 @@
do
{
- FTC_Cache cache = manager->caches + node->cache_index;
+ FTC_Cache cache = manager->caches[node->cache_index];
if ( (FT_UInt)node->cache_index >= manager->num_caches )
FT_ERROR(( "FTC_Manager_Check: invalid node (cache index = %ld\n",
@@ -432,7 +439,7 @@
weight += cache->clazz.node_weight( node, cache );
}
- node = node->mru_next;
+ node = FTC_NODE__MRU_NEXT(node);
} while ( node != first );
@@ -451,7 +458,7 @@
do
{
count++;
- node = node->mru_next;
+ node = FTC_NODE__MRU_NEXT(node);
} while ( node != first );
@@ -494,20 +501,23 @@
return;
/* go to last node - it's a circular list */
- node = first->mru_prev;
+ node = FTC_NODE__MRU_PREV(first);
do
{
- FTC_Node prev = node->mru_prev;
+ FTC_Node prev = FTC_NODE__MRU_PREV(node);
- prev = ( node == first ) ? NULL : node->mru_prev;
+ prev = FTC_NODE__MRU_PREV(node);
if ( node->ref_count <= 0 )
ftc_node_destroy( node, manager );
+ if ( node == first )
+ break;
+
node = prev;
- } while ( node && manager->cur_weight > manager->max_weight );
+ } while ( manager->cur_weight > manager->max_weight );
}
@@ -576,12 +586,11 @@
return 0;
/* go to last node - it's a circular list */
- node = first->mru_prev;
+ node = FTC_NODE__MRU_PREV( first );
for ( result = 0; result < count; )
{
- FTC_Node prev = node->mru_prev;
+ FTC_Node prev = FTC_NODE__MRU_PREV(node);
-
/* don't touch locked nodes */
if ( node->ref_count <= 0 )
{
@@ -589,7 +598,7 @@
result++;
}
- if ( prev == manager->nodes_list )
+ if ( node == first )
break;
node = prev;
--- a/src/cache/ftcmru.c
+++ b/src/cache/ftcmru.c
@@ -6,7 +6,95 @@
#include "ftcerror.h"
+
FT_EXPORT_DEF( void )
+ FTC_MruNode_Prepend( FTC_MruNode *plist,
+ FTC_MruNode node )
+ {
+ FTC_MruNode first = *plist;
+
+ if ( first )
+ {
+ FTC_MruNode last = first->prev;
+
+ last->next = node;
+ first->prev = node;
+ node->prev = last;
+ node->next = first;
+ }
+ else
+ {
+ node->next = node;
+ node->prev = node;
+ }
+ *plist = node;
+ }
+
+
+ FT_EXPORT_DEF( void )
+ FTC_MruNode_Up( FTC_MruNode *plist,
+ FTC_MruNode node )
+ {
+ FTC_MruNode first = *plist;
+
+ FT_ASSERT( first != NULL );
+
+ if ( node != first )
+ {
+ FTC_MruNode prev = node->prev;
+ FTC_MruNode next = node->next;
+ FTC_MruNode last;
+
+ prev->next = next;
+ next->prev = prev;
+
+ last = first->prev;
+
+ first->prev = node;
+ last->next = node;
+
+ node->prev = last;
+ node->next = first;
+
+ *plist = node;
+ }
+ }
+
+
+ FT_EXPORT( void )
+ FTC_MruNode_Remove( FTC_MruNode *plist,
+ FTC_MruNode node )
+ {
+ FTC_MruNode first = *plist;
+ FTC_MruNode prev, next;
+
+ FT_ASSERT( first != NULL );
+
+ next = node->next;
+ prev = node->prev;
+
+ if ( node == next )
+ {
+ FT_ASSERT( node == prev );
+ FT_ASSERT( node == first );
+
+ *plist = NULL;
+ }
+ else
+ {
+ prev->next = next;
+ next->prev = prev;
+
+ if ( node == first )
+ *plist = next;
+ }
+ node->prev = NULL;
+ node->next = NULL;
+ }
+
+
+
+ FT_EXPORT_DEF( void )
FTC_MruList_Init( FTC_MruList list,
FTC_MruListClass clazz,
FT_UInt max_nodes,
@@ -22,111 +110,130 @@
}
- static void
- ftc_mrulist_free_nodes( FTC_MruList list,
- FTC_MruNode *plist )
+
+
+ FT_EXPORT( void )
+ FTC_MruList_Reset( FTC_MruList list )
{
- FT_Memory memory = list->memory;
+ FT_Memory memory = list->memory;
+ FTC_MruNode first = list->nodes;
- while ( *plist )
+ if ( first )
{
- FTC_MruNode node = *plist;
+ FTC_MruNode node = first;
+ FTC_MruNode next;
- *plist = node->next;
+ do
+ {
+ next = node->next;
- if ( list->clazz.node_done )
- list->clazz.node_done( node, list->data );
+ if ( list->clazz.node_done )
+ list->clazz.node_done( node, list->data );
- FT_FREE( node );
+ FT_FREE( node );
+
+ node = next;
+ }
+ while ( node != first );
}
+ list->nodes = NULL;
+ list->num_nodes = 0;
}
FT_EXPORT( void )
- FTC_MruList_Reset( FTC_MruList list )
+ FTC_MruList_Done( FTC_MruList list )
{
- ftc_mrulist_free_nodes( list, &list->nodes );
- list->num_nodes = 0;
+ FTC_MruList_Reset( list );
}
- FT_EXPORT( void )
- FTC_MruList_Done( FTC_MruList list )
+ FT_EXPORT_DEF( void )
+ FTC_MruList_Up( FTC_MruList list,
+ FTC_MruNode node )
{
- FTC_MruList_Reset( list );
+ FTC_MruNode_Up( &list->nodes, node );
}
- FT_EXPORT( FT_Error )
- FTC_MruList_Lookup( FTC_MruList list,
- FT_Pointer key,
- FTC_MruNode *anode )
+ FT_EXPORT_DEF( FTC_MruNode )
+ FTC_MruList_Lookup( FTC_MruList list,
+ FT_Pointer key )
{
- FT_Memory memory = list->memory;
FTC_MruNode_CompareFunc compare = list->clazz.node_compare;
- FTC_MruNode *plast, *pnode, *pfirst;
- FTC_MruNode node;
- FT_Error error = 0;
+ FTC_MruNode node, first;
- pfirst = &list->nodes;
- plast = pnode = pfirst;
+ first = list->nodes;
+ node = NULL;
- for (;;)
+ if ( first )
{
- node = *pnode;
- if ( node == NULL )
- goto NewNode;
- if ( compare( node, key ) )
- break;
- plast = pnode;
- pnode = &node->next;
- }
+ node = first;
+ do
+ {
+ if ( compare( node, key ) )
+ goto Exit;
- if ( node != *pfirst )
- {
- *pnode = node->next;
- node->next = *pfirst;
- *pfirst = node;
+ node = node->next;
+
+ } while ( node != first );
+
+ node = NULL;
}
- goto Exit;
+ Exit:
+ return node;
+ }
- NewNode:
+
+
+ FT_EXPORT_DEF( FT_Error )
+ FTC_MruList_New( FTC_MruList list,
+ FT_Pointer key,
+ FTC_MruNode *anode )
+ {
+ FT_Memory memory = list->memory;
+ FT_Error error;
+ FTC_MruNode node;
+
if ( list->max_nodes > 0 && list->num_nodes >= list->max_nodes )
{
- node = *plast;
+ FT_ASSERT( list->nodes != NULL );
- if ( node )
+ node = list->nodes->prev; /* last node */
+
+ if ( list->clazz.node_reset )
{
- *plast = NULL;
- list->num_nodes--;
+ FTC_MruNode_Up( &list->nodes, node );
- if ( list->clazz.node_reset )
- {
- error = list->clazz.node_reset( node, key, list->data );
- if ( !error ) goto AddNode;
- }
+ error = list->clazz.node_reset( node, key, list->data );
+ if ( !error )
+ goto Exit;
+ }
+ FTC_MruNode_Remove( &list->nodes, node );
+ list->num_nodes--;
+
+ if ( list->clazz.node_done )
list->clazz.node_done( node, list->data );
- }
}
- else if ( FT_ALLOC( node, list->clazz.node_size ) )
- goto Exit;
-
+ else
+ {
+ if ( FT_ALLOC( node, list->clazz.node_size ) )
+ goto Exit;
+ }
error = list->clazz.node_init( node, key, list->data );
- if ( error )
+ if ( !error )
{
- if ( list->clazz.node_done )
- list->clazz.node_done( node, list->data );
-
- FT_FREE( node );
+ FTC_MruNode_Prepend( &list->nodes, node );
+ list->num_nodes++;
goto Exit;
}
- AddNode:
- node->next = list->nodes;
- list->nodes = node;
- list->num_nodes++;
+ if ( list->clazz.node_done )
+ list->clazz.node_done( node, list->data );
+ FT_FREE( node );
+
Exit:
*anode = node;
return error;
@@ -133,39 +240,42 @@
}
- FT_EXPORT_DEF( void )
- FTC_MruList_Remove( FTC_MruList list,
- FTC_MruNode node )
+
+ FT_EXPORT_DEF( FT_Error )
+ FTC_MruList_Get( FTC_MruList list,
+ FT_Pointer key,
+ FTC_MruNode *anode )
{
- FTC_MruNode *pnode = &list->nodes;
+ FT_Error error = 0;
+ FTC_MruNode node;
- for ( ;; )
+ node = FTC_MruList_Lookup( list, key );
+ if ( node == NULL )
{
- if ( *pnode == NULL ) /* should not happen !! */
- {
- FT_ERROR(( "%s: trying to remove unknown node !!\n",
- "FTC_MruList_Remove" ));
- return;
- }
+ error = FTC_MruList_New( list, key, &node );
+ if ( error )
+ node = NULL;
+ }
+ *anode = node;
+ return error;
+ }
- if ( *pnode == node )
- break;
- pnode = &node->next;
- }
+ FT_EXPORT_DEF( void )
+ FTC_MruList_Remove( FTC_MruList list,
+ FTC_MruNode node )
+ {
+ FT_Memory memory = list->memory;
- *pnode = node->next;
- node->next = NULL;
+ FT_ASSERT( list->nodes != NULL && list->num_nodes > 0 );
+
+ FTC_MruNode_Remove( &list->nodes, node );
list->num_nodes--;
- {
- FT_Memory memory = list->memory;
+ if ( list->clazz.node_done )
+ list->clazz.node_done( node, list->data );
- if ( list->clazz.node_done )
- list->clazz.node_done( node, list->data );
-
- FT_FREE( node );
- }
+ FT_FREE( node );
}
@@ -174,30 +284,29 @@
FTC_MruNode_CompareFunc select,
FT_Pointer key )
{
- FTC_MruNode *pnode = &list->nodes;
- FTC_MruNode node, free = NULL;;
+ FTC_MruNode first = list->nodes;
- if ( select )
+ while ( first && select( first, key ) )
{
- for (;;)
- {
- FTC_MruNode node = *pnode;
+ FTC_MruList_Remove( list, first );
+ first = list->nodes;
+ }
- if ( node == NULL )
- break;
+ if ( first )
+ {
+ FTC_MruNode node = first->next;
+ FTC_MruNode next;
+ while ( node != first )
+ {
+ next = node->next;
+
if ( select( node, key ) )
- {
- *pnode = node->next;
- node->next = free;
- free = node;
- }
- else
- pnode = &node->next;
+ FTC_MruList_Remove( list, node );
+
+ node = next;
}
}
-
- ftc_mrulist_free_nodes( list, &free );
}
/* END */
--- a/src/cache/ftcsbits.c
+++ b/src/cache/ftcsbits.c
@@ -91,7 +91,7 @@
FTC_SFamilyClass clazz;
- if ( (FT_UInt)gindex >= gnode->gindex + snode->count )
+ if ( (FT_UInt)(gindex - gnode->gindex) >= snode->count )
{
FT_ERROR(( "ftc_snode_load: invalid glyph index" ));
return FTC_Err_Invalid_Argument;
@@ -267,7 +267,8 @@
FT_UInt gindex = gquery->gindex;
FT_Bool result;
- result = FT_BOOL( (FT_UInt)(gindex - gnode->gindex) < snode->count );
+ result = FT_BOOL( gnode->family == gquery->family &&
+ (FT_UInt)(gindex - gnode->gindex) < snode->count );
if ( result )
{
/* check if we need to load the glyph bitmap now */