shithub: freetype+ttf2subf

Download patch

ref: 581ec91c2719f1a6594cfb1a3e46f94bf5feab03
parent: 63abb4bc63b06e537d0827cda7912259798083f2
author: David Turner <[email protected]>
date: Mon Dec 22 16:53:37 EST 2003

* include/freetype/ftcache.h,
        include/freetype/cache/ftcmanag.h,
        include/freetype/cache/ftccache.h,
        include/freetype/cache/ftcmanag.h,
        include/freetype/cache/ftcmru.h (added),
        include/freetype/cache/ftlru.h (removed),
        include/freetype/cache/ftcsbits.h,
        include/freetype/cache/ftcimage.h,
        include/freetype/cache/ftcglyph.h,
        src/cache/ftcmru.c,
        src/cache/ftcmanag.c,
        src/cache/ftccache.c,
        src/cache/ftcglyph.c,
        src/cache/ftcimage.c,
        src/cache/ftcsbits.c,
        src/cache/ftccmap.c,
        src/cache/ftcbasic.c (added),
        src/cache/ftclru.c (removed):

          *Complete* rewrite of the cache sub-system to "solve" the
          following points:

            - all public APIs have been moved to FT_CACHE_H, everything
              under "include/freetype/cache" is only needed by client
              applications that want to implement their own caches

            - a new function named FTC_Manager_RemoveFaceID to deal
              with the uninstallation of FaceIDs

            - the image and sbit cache are now abstract classes, that
              can be extended much more easily by client applications

            - better performance in certain areas. Further optimizations
              to come shortly anyway...

            - the FTC_CMapCache_Lookup function has changed its signature,
              charmaps can now only be retrieved by index

            - FTC_Manager_Lookup_Face => FTC_Manager_LookupFace
              FTC_Manager_Lookup_Size => FTC_Manager_LookupSize (still in
              private header for the moment)

git/fs: mount .git/fs: mount/attach disallowed
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,48 @@
+2003-12-22  David Turner  <[email protected]>
+
+        * include/freetype/ftcache.h,
+        include/freetype/cache/ftcmanag.h,
+        include/freetype/cache/ftccache.h,
+        include/freetype/cache/ftcmanag.h,
+        include/freetype/cache/ftcmru.h (added),
+        include/freetype/cache/ftlru.h (removed),
+        include/freetype/cache/ftcsbits.h,
+        include/freetype/cache/ftcimage.h,
+        include/freetype/cache/ftcglyph.h,
+        src/cache/ftcmru.c,
+        src/cache/ftcmanag.c,
+        src/cache/ftccache.c,
+        src/cache/ftcglyph.c,
+        src/cache/ftcimage.c,
+        src/cache/ftcsbits.c,
+        src/cache/ftccmap.c,
+        src/cache/ftcbasic.c (added),
+        src/cache/ftclru.c (removed):
+
+          *Complete* rewrite of the cache sub-system to "solve" the
+          following points:
+
+            - all public APIs have been moved to FT_CACHE_H, everything
+              under "include/freetype/cache" is only needed by client
+              applications that want to implement their own caches
+
+            - a new function named FTC_Manager_RemoveFaceID to deal
+              with the uninstallation of FaceIDs
+
+            - the image and sbit cache are now abstract classes, that
+              can be extended much more easily by client applications
+
+            - better performance in certain areas. Further optimizations
+              to come shortly anyway...
+
+            - the FTC_CMapCache_Lookup function has changed its signature,
+              charmaps can now only be retrieved by index
+
+            - FTC_Manager_Lookup_Face => FTC_Manager_LookupFace
+              FTC_Manager_Lookup_Size => FTC_Manager_LookupSize (still in
+              private header for the moment)
+
+
 2003-12-21  Werner Lemberg  <[email protected]>
 
 	* src/type1/t1load.c (parse_dict): Stop parsing if `eexec' keyword
--- a/include/freetype/cache/ftccache.h
+++ b/include/freetype/cache/ftccache.h
@@ -19,6 +19,7 @@
 #ifndef __FTCCACHE_H__
 #define __FTCCACHE_H__
 
+
 #include FT_CACHE_INTERNAL_MRU_H
 
 FT_BEGIN_HEADER
@@ -64,8 +65,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 )
+#define FTC_NODE__NEXT(x)  FTC_NODE( (x)->mru.next )
+#define FTC_NODE__PREV(x)  FTC_NODE( (x)->mru.prev )
 
   /*************************************************************************/
   /*                                                                       */
--- a/include/freetype/cache/ftcmanag.h
+++ b/include/freetype/cache/ftcmanag.h
@@ -71,7 +71,6 @@
 
 FT_BEGIN_HEADER
 
-#define FT_DEBUG_ERROR
 
   /*************************************************************************/
   /*                                                                       */
--- a/include/freetype/cache/ftcmru.h
+++ b/include/freetype/cache/ftcmru.h
@@ -53,6 +53,7 @@
 #error "so that freetype.h of FreeType 2 is found first."
 #endif
 
+#define xxFT_DEBUG_ERROR
 
 FT_BEGIN_HEADER
 
@@ -65,7 +66,6 @@
 
   } FTC_MruNodeRec;
 
-
   FT_EXPORT( void )
   FTC_MruNode_Prepend( FTC_MruNode  *plist,
                        FTC_MruNode   node );
@@ -78,7 +78,6 @@
   FTC_MruNode_Remove( FTC_MruNode  *plist,
                       FTC_MruNode   node );
 
-
   typedef struct FTC_MruListRec_*              FTC_MruList;
 
   typedef struct FTC_MruListClassRec_ const *  FTC_MruListClass;
@@ -107,7 +106,6 @@
 
   } FTC_MruListClassRec;
 
-
   typedef struct FTC_MruListRec_
   {
     FT_UInt                  num_nodes;
@@ -134,19 +132,19 @@
   FT_EXPORT( void )
   FTC_MruList_Done( FTC_MruList  list );
 
-
   FT_EXPORT( FTC_MruNode )
-  FTC_MruList_Lookup( FTC_MruList   list,
-                      FT_Pointer    key );
+  FTC_MruList_Find( FTC_MruList  list,
+                    FT_Pointer    key );
 
-  FT_EXPORT( void )
-  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( FT_Error )
+  FTC_MruList_Lookup( FTC_MruList   list,
+                      FT_Pointer    key,
+                      FTC_MruNode  *pnode );
 
   FT_EXPORT( void )
   FTC_MruList_Remove( FTC_MruList  list,
--- a/include/freetype/ftcache.h
+++ b/include/freetype/ftcache.h
@@ -108,10 +108,10 @@
   /*    FTC_FaceID                                                         */
   /*                                                                       */
   /* <Description>                                                         */
-  /*    A generic pointer type that is used to identity face objects.  The */
+  /*    An opaque pointer type that is used to identity face objects.  The */
   /*    contents of such objects is application-dependent.                 */
   /*                                                                       */
-  typedef FT_Pointer  FTC_FaceID;
+  typedef struct FTC_FaceIDRec_*    FTC_FaceID;
 
 
   /*************************************************************************/
@@ -401,21 +401,6 @@
 
   /*************************************************************************/
   /*                                                                       */
-  /* @type:                                                                */
-  /*    FTC_CMapDesc                                                       */
-  /*                                                                       */
-  /* @description:                                                         */
-  /*    A handle to an @FTC_CMapDescRec structure used to describe a given */
-  /*    charmap in a charmap cache.                                        */
-  /*                                                                       */
-  /*    Each @FTC_CMapDesc describes which charmap (of which @FTC_FaceID)  */
-  /*    we want to use in @FTC_CMapCache_Lookup.                           */
-  /*                                                                       */
-  typedef struct FTC_CMapDescRec_*  FTC_CMapDesc;
-
-
-  /*************************************************************************/
-  /*                                                                       */
   /* @function:                                                            */
   /*    FTC_CMapCache_New                                                  */
   /*                                                                       */
@@ -442,7 +427,7 @@
 
  /* retrieve the index of a given charmap
   */
-  FT_EXPORT( FT_UInt )
+  FT_EXPORT( FT_Int )
   FT_Get_CharMap_Index( FT_CharMap  charmap );
 
   /*************************************************************************/
@@ -457,21 +442,19 @@
   /* @input:                                                               */
   /*    cache     :: A charmap cache handle.                               */
   /*                                                                       */
-  /*    cmap_desc :: A charmap descriptor handle.                          */
+  /*    face_id    :: source face id                                       */
   /*                                                                       */
+  /*    cmap_index :: index of charmap in source face                      */
+  /*                                                                       */
   /*    char_code :: The character code (in the corresponding charmap).    */
   /*                                                                       */
   /* @return:                                                              */
   /*    Glyph index.  0 means "no glyph".                                  */
   /*                                                                       */
-  /* @note:                                                                */
-  /*    This function doesn't return @FTC_Node handles, since there is no  */
-  /*    real use for them with typical uses of charmaps.                   */
-  /*                                                                       */
   FT_EXPORT( FT_UInt )
   FTC_CMapCache_Lookup( FTC_CMapCache  cache,
                         FTC_FaceID     face_id,
-                        FT_UInt        cmap_index,
+                        FT_Int         cmap_index,
                         FT_UInt32      char_code );
 
 
@@ -480,7 +463,7 @@
   /* <Section>                                                             */
   /*    cache_subsystem                                                    */
   /*                                                                       */
-  /*************************************************************************/
+  /**********************************************************************/
 
 
   /*************************************************************************/
--- a/src/cache/ftcbasic.c
+++ b/src/cache/ftcbasic.c
@@ -63,26 +63,6 @@
   }
 
 
-  static FT_Bool
-  ftc_basic_gnode_compare_faceid( FTC_GNode   gnode,
-                                  FTC_FaceID  face_id,
-                                  FTC_Cache   cache )
-  {
-    FTC_BasicFamily  family = (FTC_BasicFamily) gnode->family;
-    FT_Bool          result;
-
-    result = FT_BOOL( family->attrs.scaler.face_id == face_id );
-    if ( result )
-    {
-     /* we must call this function to avoid this node from appearing
-      * in later lookups with the same face_id !!
-      */
-      FTC_GNode_UnselectFamily( gnode, cache );
-    }
-    return result;
-  }
-
-
   static FT_UInt
   ftc_basic_family_get_count( FTC_BasicFamily  family,
                               FTC_Manager      manager )
@@ -91,7 +71,7 @@
     FT_Face   face;
     FT_UInt   result = 0;
 
-    error = FTC_Manager_LookupFace( manager, &family->attrs.scaler.face_id,
+    error = FTC_Manager_LookupFace( manager, family->attrs.scaler.face_id,
                                     &face );
     if ( !error )
       result = face->num_glyphs;
@@ -168,6 +148,27 @@
   }
 
 
+  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
@@ -246,7 +247,7 @@
     query.attrs.scaler.pixel   = 1;
     query.attrs.load_flags     = type->flags;
 
-    hash = FTC_BASIC_ATTR_HASH( &query.attrs ) ^ (gindex << 8);
+    hash = FTC_BASIC_ATTR_HASH( &query.attrs ) + gindex;
 
     error = FTC_GCache_Lookup( FTC_GCACHE( cache ),
                                hash, gindex,
@@ -347,7 +348,7 @@
 
    /* beware, the hash must be the same for all glyph ranges !!
     */
-    hash = FTC_BASIC_ATTR_HASH( &query.attrs ) ^
+    hash = FTC_BASIC_ATTR_HASH( &query.attrs ) +
            (gindex/FTC_SBIT_ITEMS_PER_NODE);
 
     error = FTC_GCache_Lookup( FTC_GCACHE( cache ),
--- 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  512
+#define FTC_HASH_INITIAL_SIZE  8
 
 
   /*************************************************************************/
@@ -76,9 +76,6 @@
   static void
   ftc_cache_resize( FTC_Cache  cache )
   {
-#if 1
-    FT_UNUSED(cache);
-#else
     for (;;)
     {
       FTC_Node   node, *pnode;
@@ -173,7 +170,6 @@
       else /* the hash table is balanced */
         break;
     }
-#endif
   }
 
 
@@ -376,6 +372,8 @@
                  FTC_Node     node )
   {
     node->hash = hash;
+    node->cache_index = (FT_UInt16) cache->index;
+    node->ref_count   = 0;
 
     ftc_node_hash_link( node, cache );
     ftc_node_mru_link( node, cache->manager );
@@ -461,9 +459,20 @@
     *
     */
     error = cache->clazz.node_new( &node, query, cache );
-    if ( !error )
-      goto AddNode;
+    if ( error )
+      goto FlushCache;
 
+  AddNode:
+   /* don't assume that the cache has the same number of buckets, since
+    * our allocation request might have triggered global cache flushing
+    */
+    ftc_cache_add( cache, hash, node );
+
+  Exit:
+    *anode = node;
+    return error;
+
+  FlushCache:
     node = NULL;
     if ( error != FT_Err_Out_Of_Memory )
       goto Exit;
@@ -495,20 +504,7 @@
         tries = count;
       }
     }
-
-  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
-    */
-    ftc_cache_add( cache, hash, node );
-
-  Exit:
-    *anode = node;
-    return error;
+    goto AddNode;
   }
 
 
@@ -565,6 +561,5 @@
 
     ftc_cache_resize( cache );
   }
-
 
 /* END */
--- a/src/cache/ftccmap.c
+++ b/src/cache/ftccmap.c
@@ -200,7 +200,7 @@
   FT_EXPORT_DEF( FT_UInt )
   FTC_CMapCache_Lookup( FTC_CMapCache  cmap_cache,
                         FTC_FaceID     face_id,
-                        FT_UInt        cmap_index,
+                        FT_Int         cmap_index,
                         FT_UInt32      char_code )
   {
     FTC_Cache         cache = FTC_CACHE( cmap_cache );
@@ -218,7 +218,7 @@
     }
 
     query.face_id    = face_id;
-    query.cmap_index = cmap_index;
+    query.cmap_index = (FT_UInt)cmap_index;
     query.char_code  = char_code;
 
     hash = FTC_CMAP_HASH( face_id, cmap_index, char_code );
--- a/src/cache/ftcglyph.c
+++ b/src/cache/ftcglyph.c
@@ -26,7 +26,6 @@
 #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,
@@ -35,7 +34,6 @@
   {
     gnode->family = family;
     gnode->gindex = gindex;
-
     family->num_nodes++;
   }
 
@@ -48,8 +46,10 @@
 
     gnode->family = NULL;
     if ( family && --family->num_nodes <= 0 )
+    {
       FTC_MruList_Remove( & FTC_GCACHE(cache)->families, (FTC_MruNode)family );
   }
+  }
 
 
   FT_EXPORT_DEF( void )
@@ -138,26 +138,14 @@
                      FTC_Node    *anode )
   {
     FT_Error    error;
-    FTC_Family  family;
 
     query->gindex = gindex;
 
-    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_MruList_Lookup( &cache->families, query,
+                                (FTC_MruNode*) &query->family );
+    if ( !error )
     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 = 0;
+    FT_Error      error;
     FTC_SizeNode  node;
 
 
@@ -156,20 +156,16 @@
     if ( !manager )
       return FTC_Err_Invalid_Cache_Handle;
 
-    error = FTC_MruList_Get( &manager->sizes, scaler, (FTC_MruNode*) &node );
+    error = FTC_MruList_Lookup( &manager->sizes,
+                                scaler,
+                                (FTC_MruNode*) &node );
     if ( !error )
-    {
       *asize = node->size;
-      FT_Activate_Size( node->size );
-    }
 
-  Exit:
     return error;
   }
 
 
-
-
   /*************************************************************************/
   /*************************************************************************/
   /*****                                                               *****/
@@ -223,11 +219,8 @@
           node->face_id );
 
     /* all right, we can discard the face now */
-    if ( node->face )
-    {
-      FT_Done_Face( node->face );
-      node->face    = NULL;
-    }
+    FT_Done_Face( node->face );
+    node->face    = NULL;
     node->face_id = NULL;
   }
 
@@ -259,7 +252,7 @@
                           FTC_FaceID   face_id,
                           FT_Face     *aface )
   {
-    FT_Error      error = 0;
+    FT_Error      error;
     FTC_FaceNode  node;
 
 
@@ -271,17 +264,12 @@
     if ( !manager )
       return FTC_Err_Invalid_Cache_Handle;
 
-    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;
-    }
-
+    error = FTC_MruList_Lookup( &manager->faces,
+                                face_id,
+                                (FTC_MruNode*) &node );
+    if ( !error )
     *aface = node->face;
 
-  Exit:
     return error;
   }
 
@@ -429,7 +417,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",
@@ -439,7 +427,7 @@
           weight += cache->clazz.node_weight( node, cache );
         }
 
-        node = FTC_NODE__MRU_NEXT(node);
+        node = FTC_NODE__NEXT(node);
 
       } while ( node != first );
 
@@ -458,7 +446,7 @@
       do
       {
         count++;
-        node = FTC_NODE__MRU_NEXT(node);
+        node = FTC_NODE__NEXT(node);
 
       } while ( node != first );
 
@@ -501,23 +489,20 @@
       return;
 
     /* go to last node - it's a circular list */
-    node = FTC_NODE__MRU_PREV(first);
+    node = FTC_NODE__PREV(first);
     do
     {
-      FTC_Node  prev = FTC_NODE__MRU_PREV(node);
+      FTC_Node  prev;
 
 
-      prev = FTC_NODE__MRU_PREV(node);
+      prev = ( node == first ) ? NULL : FTC_NODE__PREV(node);
 
       if ( node->ref_count <= 0 )
         ftc_node_destroy( node, manager );
 
-      if ( node == first )
-        break;
-
       node = prev;
 
-    } while ( manager->cur_weight > manager->max_weight );
+    } while ( node && manager->cur_weight > manager->max_weight );
   }
 
 
@@ -586,11 +571,12 @@
       return 0;
 
     /* go to last node - it's a circular list */
-    node = FTC_NODE__MRU_PREV( first );
+    node = FTC_NODE__PREV(first);
     for ( result = 0; result < count; )
     {
-      FTC_Node  prev = FTC_NODE__MRU_PREV(node);
+      FTC_Node  prev = FTC_NODE__PREV(node);
 
+
      /* don't touch locked nodes */
       if ( node->ref_count <= 0 )
       {
@@ -598,7 +584,7 @@
         result++;
       }
 
-      if ( node == first )
+      if ( prev == manager->nodes_list )
         break;
 
       node = prev;
--- a/src/cache/ftcmru.c
+++ b/src/cache/ftcmru.c
@@ -6,7 +6,6 @@
 
 #include "ftcerror.h"
 
-
   FT_EXPORT_DEF( void )
   FTC_MruNode_Prepend( FTC_MruNode  *plist,
                        FTC_MruNode   node )
@@ -17,10 +16,26 @@
     {
       FTC_MruNode  last = first->prev;
 
-      last->next  = node;
+#ifdef FT_DEBUG_ERROR
+      {
+        FTC_MruNode  cnode = first;
+        do
+        {
+          if ( cnode == node )
+          {
+            fprintf( stderr, "FTC_MruNode_Prepend: invalid action !!\n" );
+            exit(2);
+          }
+          cnode = cnode->next;
+        }
+        while ( cnode != first );
+      }
+#endif
+
       first->prev = node;
-      node->prev  = last;
+      last->next  = node;
       node->next  = first;
+      node->prev  = last;
     }
     else
     {
@@ -39,22 +54,39 @@
 
     FT_ASSERT( first != NULL );
 
-    if ( node != first )
+    if ( first != node )
     {
-      FTC_MruNode  prev = node->prev;
-      FTC_MruNode  next = node->next;
-      FTC_MruNode  last;
+      FTC_MruNode  prev, next, last;
 
+#ifdef FT_DEBUG_ERROR
+      {
+        FTC_MruNode  cnode = first;
+        do
+        {
+          if ( cnode == node )
+            goto Ok;
+          cnode = cnode->next;
+        }
+        while ( cnode != first );
+
+        fprintf( stderr, "FTC_MruNode_Up: invalid action !!\n" );
+        exit(2);
+      Ok:
+      }
+#endif
+      prev = node->prev;
+      next = node->next;
+
       prev->next = next;
       next->prev = prev;
 
       last = first->prev;
 
-      first->prev = node;
       last->next  = node;
+      first->prev = node;
 
-      node->prev  = last;
       node->next  = first;
+      node->prev = last;
 
       *plist = node;
     }
@@ -61,7 +93,7 @@
   }
 
 
-  FT_EXPORT( void )
+  FT_EXPORT_DEF( void )
   FTC_MruNode_Remove( FTC_MruNode  *plist,
                       FTC_MruNode   node )
   {
@@ -70,27 +102,39 @@
 
     FT_ASSERT( first != NULL );
 
-    next = node->next;
+#ifdef FT_DEBUG_ERROR
+      {
+        FTC_MruNode  cnode = first;
+        do
+        {
+          if ( cnode == node )
+            goto Ok;
+          cnode = cnode->next;
+        }
+        while ( cnode != first );
+
+        fprintf( stderr, "FTC_MruNode_Remove: invalid action !!\n" );
+        exit(2);
+      Ok:
+      }
+#endif
+
     prev = node->prev;
+    next = node->next;
 
+    prev->next = next;
+    next->prev = prev;
+
     if ( node == next )
     {
-      FT_ASSERT( node == prev );
-      FT_ASSERT( node == first );
+      FT_ASSERT( first == node );
+      FT_ASSERT( prev  == node );
 
       *plist = NULL;
     }
-    else
-    {
-      prev->next = next;
-      next->prev = prev;
-
-      if ( node == first )
+    else if ( node == first )
         *plist = next;
     }
-    node->prev = NULL;
-    node->next = NULL;
-  }
 
 
 
@@ -110,34 +154,13 @@
   }
 
 
-
-
   FT_EXPORT( void )
   FTC_MruList_Reset( FTC_MruList  list )
   {
-    FT_Memory    memory = list->memory;
-    FTC_MruNode  first  = list->nodes;
+    while ( list->nodes )
+      FTC_MruList_Remove( list, 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;
+    FT_ASSERT( list->num_nodes == 0 );
   }
 
 
@@ -148,20 +171,13 @@
   }
 
 
-  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,
+  FTC_MruList_Find( FTC_MruList  list,
                       FT_Pointer   key )
   {
     FTC_MruNode_CompareFunc  compare = list->clazz.node_compare;
-    FTC_MruNode              node, first;
+    FTC_MruNode              first, node;
 
     first = list->nodes;
     node  = NULL;
@@ -172,16 +188,13 @@
       do
       {
         if ( compare( node, key ) )
-          goto Exit;
+          return node;
 
         node = node->next;
-
-      } while ( node != first );
-
-      node = NULL;
     }
-  Exit:
-    return node;
+      while ( node != first) ;
+    }
+    return NULL;
   }
 
 
@@ -191,15 +204,15 @@
                    FT_Pointer     key,
                    FTC_MruNode   *anode )
   {
-    FT_Memory    memory = list->memory;
     FT_Error     error;
     FTC_MruNode  node;
+    FT_Memory    memory = list->memory;
 
-    if ( list->max_nodes > 0 && list->num_nodes >= list->max_nodes )
+    if ( list->num_nodes >= list->max_nodes && list->max_nodes > 0 )
     {
-      FT_ASSERT( list->nodes != NULL );
+      node = list->nodes->prev;
 
-      node = list->nodes->prev;  /* last node */
+      FT_ASSERT( node );
 
       if ( list->clazz.node_reset )
       {
@@ -216,48 +229,43 @@
       if ( list->clazz.node_done )
         list->clazz.node_done( node, list->data );
     }
-    else
-    {
-      if ( FT_ALLOC( node, list->clazz.node_size ) )
+    else if ( FT_ALLOC( node, list->clazz.node_size ) )
         goto Exit;
-    }
+
     error = list->clazz.node_init( node, key, list->data );
-    if ( !error )
-    {
+    if ( error )
+      goto Fail;
+
       FTC_MruNode_Prepend( &list->nodes, node );
       list->num_nodes++;
-      goto Exit;
-    }
 
+  Exit:
+    *anode = node;
+    return error;
+
+  Fail:
     if ( list->clazz.node_done )
       list->clazz.node_done( node, list->data );
 
     FT_FREE( node );
-
-  Exit:
-    *anode = node;
-    return error;
+    goto Exit;
   }
 
 
-
-  FT_EXPORT_DEF( FT_Error )
-  FTC_MruList_Get( FTC_MruList   list,
+  FT_EXPORT( FT_Error )
+  FTC_MruList_Lookup( FTC_MruList   list,
                    FT_Pointer    key,
                    FTC_MruNode  *anode )
   {
-    FT_Error     error = 0;
     FTC_MruNode  node;
+    FT_Error     error = 0;
 
-    node = FTC_MruList_Lookup( list, key );
+    node = FTC_MruList_Find( list, key );
     if ( node == NULL )
-    {
-      error = FTC_MruList_New( list, key, &node );
-      if ( error )
-        node = NULL;
-    }
+      return FTC_MruList_New( list, key, anode );
+
     *anode = node;
-    return error;
+    return 0;
   }
 
 
@@ -265,18 +273,18 @@
   FTC_MruList_Remove( FTC_MruList   list,
                       FTC_MruNode   node )
   {
-    FT_Memory    memory = list->memory;
-
-    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 );
 
     FT_FREE( node );
   }
+  }
 
 
   FT_EXPORT_DEF( void )
@@ -284,8 +292,9 @@
                                FTC_MruNode_CompareFunc  select,
                                FT_Pointer               key )
   {
-    FTC_MruNode   first = list->nodes;
+    FTC_MruNode  first, node, next;
 
+    first = list->nodes;
     while ( first && select( first, key ) )
     {
       FTC_MruList_Remove( list, first );
@@ -294,9 +303,7 @@
 
     if ( first )
     {
-      FTC_MruNode  node = first->next;
-      FTC_MruNode  next;
-
+      node = first->next;
       while ( node != first )
       {
         next = node->next;
--- a/src/cache/ftcsbits.c
+++ b/src/cache/ftcsbits.c
@@ -235,11 +235,10 @@
     FT_ULong   size;
 
 
+    FT_ASSERT( snode->count <= FTC_SBITS_ITEM_PER_NODE );
+
     /* the node itself */
     size = sizeof ( *snode );
-
-    /* the sbit records */
-    size += count * sizeof( FTC_SBitRec );
 
     for ( ; count > 0; count--, sbit++ )
     {