diff --git a/include/freetype/cache/ftccache.h b/include/freetype/cache/ftccache.h index 60191bc00..0f78c34ff 100644 --- a/include/freetype/cache/ftccache.h +++ b/include/freetype/cache/ftccache.h @@ -19,7 +19,7 @@ #ifndef __FTCCACHE_H__ #define __FTCCACHE_H__ - +#include FT_CACHE_INTERNAL_MRU_H FT_BEGIN_HEADER @@ -52,12 +52,11 @@ FT_BEGIN_HEADER /* 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 @@ FT_BEGIN_HEADER #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 ) /*************************************************************************/ /* */ diff --git a/include/freetype/cache/ftcglyph.h b/include/freetype/cache/ftcglyph.h index 3b7510d06..2b42bda04 100644 --- 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 @@ FT_BEGIN_HEADER * * 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,15 +167,6 @@ FT_BEGIN_HEADER - /* 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 ) /*************************************************************************/ /* */ @@ -209,6 +201,10 @@ FT_BEGIN_HEADER 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 @@ FT_BEGIN_HEADER #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 @@ FT_BEGIN_HEADER FTC_Node *anode ); /* */ - + FT_END_HEADER diff --git a/include/freetype/cache/ftcmanag.h b/include/freetype/cache/ftcmanag.h index 34f3857e4..21ca51e1a 100644 --- 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_BEGIN_HEADER 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_BEGIN_HEADER FT_Int pixel; FT_UInt x_res; FT_UInt y_res; - + } FTC_ScalerRec, *FTC_Scaler; @@ -167,14 +168,14 @@ FT_BEGIN_HEADER (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 ) diff --git a/include/freetype/cache/ftcmru.h b/include/freetype/cache/ftcmru.h index e0232fbff..e3bb2a39a 100644 --- 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 @@ FT_BEGIN_HEADER } FTC_MruListClassRec; + typedef struct FTC_MruListRec_ { FT_UInt num_nodes; @@ -119,14 +135,22 @@ FT_BEGIN_HEADER 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, diff --git a/src/cache/descrip.mms b/src/cache/descrip.mms index ea12f2e37..f6129fdab 100644 --- a/src/cache/descrip.mms +++ b/src/cache/descrip.mms @@ -20,7 +20,7 @@ OBJS=ftcache.obj 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 diff --git a/src/cache/ftcbasic.c b/src/cache/ftcbasic.c index 7696cbe5a..78fd1c026 100644 --- a/src/cache/ftcbasic.c +++ b/src/cache/ftcbasic.c @@ -57,15 +57,7 @@ FTC_BasicQuery query, FTC_Cache cache ) { - ftc_family_init( FTC_FAMILY( family ), cache ); - family->attrs = query->attrs; - return 0; - } - - static FT_Error - ftc_basic_family_reset( FTC_BasicFamily family, - FTC_BasicQuery query ) - { + FTC_Family_Init( FTC_FAMILY( family ), cache ); family->attrs = query->attrs; return 0; } @@ -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, diff --git a/src/cache/ftccache.c b/src/cache/ftccache.c index d5d2e410b..4db4757a1 100644 --- 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 */ @@ -624,4 +566,5 @@ ftc_cache_resize( cache ); } + /* END */ diff --git a/src/cache/ftccache.i b/src/cache/ftccache.i deleted file mode 100644 index bb6e631a2..000000000 --- a/src/cache/ftccache.i +++ /dev/null @@ -1,157 +0,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 */ diff --git a/src/cache/ftcglyph.c b/src/cache/ftcglyph.c index f877e9b0b..bca87f3bb 100644 --- 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,13 +81,14 @@ /*************************************************************************/ 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); 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; } diff --git a/src/cache/ftcmanag.c b/src/cache/ftcmanag.c index 388df2587..b6bb4e914 100644 --- 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,11 +586,10 @@ 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; diff --git a/src/cache/ftcmru.c b/src/cache/ftcmru.c index bfc7bc55d..003c153a4 100644 --- a/src/cache/ftcmru.c +++ b/src/cache/ftcmru.c @@ -6,6 +6,94 @@ #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, @@ -22,30 +110,33 @@ } - static void - ftc_mrulist_free_nodes( FTC_MruList list, - FTC_MruNode *plist ) - { - FT_Memory memory = list->memory; - - while ( *plist ) - { - FTC_MruNode node = *plist; - - *plist = node->next; - - if ( list->clazz.node_done ) - list->clazz.node_done( node, list->data ); - - FT_FREE( node ); - } - } FT_EXPORT( void ) FTC_MruList_Reset( FTC_MruList list ) { - ftc_mrulist_free_nodes( list, &list->nodes ); + FT_Memory memory = list->memory; + FTC_MruNode first = list->nodes; + + if ( first ) + { + FTC_MruNode node = first; + FTC_MruNode next; + + do + { + next = node->next; + + if ( list->clazz.node_done ) + list->clazz.node_done( node, list->data ); + + FT_FREE( node ); + + node = next; + } + while ( node != first ); + } + list->nodes = NULL; list->num_nodes = 0; } @@ -57,75 +148,91 @@ } - FT_EXPORT( FT_Error ) - FTC_MruList_Lookup( FTC_MruList list, - FT_Pointer key, - FTC_MruNode *anode ) + FT_EXPORT_DEF( void ) + FTC_MruList_Up( FTC_MruList list, + FTC_MruNode node ) + { + FTC_MruNode_Up( &list->nodes, node ); + } + + + 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; - } - goto Exit; + node = node->next; + + } while ( node != first ); + + node = NULL; + } + Exit: + return node; + } + + + + 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; - NewNode: 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; - } - - list->clazz.node_done( node, list->data ); + error = list->clazz.node_reset( node, key, list->data ); + if ( !error ) + goto Exit; } - } - else if ( FT_ALLOC( node, list->clazz.node_size ) ) - goto Exit; - error = list->clazz.node_init( node, key, list->data ); - if ( error ) - { + FTC_MruNode_Remove( &list->nodes, node ); + list->num_nodes--; + if ( list->clazz.node_done ) list->clazz.node_done( node, list->data ); - - FT_FREE( node ); + } + else + { + if ( FT_ALLOC( node, list->clazz.node_size ) ) + goto Exit; + } + error = list->clazz.node_init( node, key, list->data ); + if ( !error ) + { + 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; @@ -133,39 +240,42 @@ } + + FT_EXPORT_DEF( FT_Error ) + FTC_MruList_Get( FTC_MruList list, + FT_Pointer key, + FTC_MruNode *anode ) + { + FT_Error error = 0; + FTC_MruNode node; + + node = FTC_MruList_Lookup( list, key ); + if ( node == NULL ) + { + error = FTC_MruList_New( list, key, &node ); + if ( error ) + node = NULL; + } + *anode = node; + return error; + } + + FT_EXPORT_DEF( void ) FTC_MruList_Remove( FTC_MruList list, FTC_MruNode node ) { - FTC_MruNode *pnode = &list->nodes; + FT_Memory memory = list->memory; - for ( ;; ) - { - if ( *pnode == NULL ) /* should not happen !! */ - { - FT_ERROR(( "%s: trying to remove unknown node !!\n", - "FTC_MruList_Remove" )); - return; - } + FT_ASSERT( list->nodes != NULL && list->num_nodes > 0 ); - if ( *pnode == node ) - break; - - pnode = &node->next; - } - - *pnode = node->next; - node->next = NULL; + 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; - - if ( node == NULL ) - break; - - if ( select( node, key ) ) - { - *pnode = node->next; - node->next = free; - free = node; - } - else - pnode = &node->next; - } + FTC_MruList_Remove( list, first ); + first = list->nodes; } - ftc_mrulist_free_nodes( list, &free ); + if ( first ) + { + FTC_MruNode node = first->next; + FTC_MruNode next; + + while ( node != first ) + { + next = node->next; + + if ( select( node, key ) ) + FTC_MruList_Remove( list, node ); + + node = next; + } + } } /* END */ diff --git a/src/cache/ftcsbits.c b/src/cache/ftcsbits.c index d708d3398..353099330 100644 --- 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 */