shithub: freetype+ttf2subf

Download patch

ref: 4e4a43631c91cceeae2f90e190ca2cef67910374
parent: 9b8f5c4ce1ac3f75c2b8960fc31cafe868fa8731
author: David Turner <[email protected]>
date: Sat Oct 28 09:17:11 EDT 2000

- completed the abstract chunk cache class
- started implementin a "small-bitmaps" cache derived from it
- (soon a "metrics" cache will be written too)

git/fs: mount .git/fs: mount/attach disallowed
--- /dev/null
+++ b/include/freetype/cache/ftcchunk.h
@@ -1,0 +1,208 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftcchunk.h                                                             */
+/*                                                                         */
+/*    FreeType chunk cache (specification).                                */
+/*                                                                         */
+/*  Copyright 2000 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.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Important: The functions defined in this file are only used to        */
+  /*            implement an abstract chunk cache class.  You need to      */
+  /*            provide additional logic to implement a complete cache.    */
+  /*            For example, see `ftcmetrx.h' and `ftcmetrx.c' which       */
+  /*            implement a glyph metrics cache based on this code.        */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*********                                                       *********/
+  /*********        WARNING, THIS IS ALPHA CODE, THIS API          *********/
+  /*********    IS DUE TO CHANGE UNTIL STRICTLY NOTIFIED BY THE    *********/
+  /*********            FREETYPE DEVELOPMENT TEAM                  *********/
+  /*********                                                       *********/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+#ifndef FTCCHUNK_H
+#define FTCCHUNK_H
+
+#include <freetype/cache/ftcmanag.h>
+
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/* maximum number of chunk sets in a given chunk cache */
+#define  FTC_MAX_CHUNK_SETS  16
+
+
+  typedef struct FTC_ChunkRec_*        FTC_Chunk;
+  typedef struct FTC_ChunkSetRec_*     FTC_ChunkSet;
+  typedef struct FTC_Chunk_CacheRec_*  FTC_Chunk_Cache;
+
+  typedef struct FTC_ChunkRec_
+  {
+    FTC_CacheNodeRec    root;
+    FTC_ChunkSet        cset;
+    FT_UShort           cset_index;
+    FT_UShort           num_elements;
+    FT_Byte*            elements;
+  
+  } FTC_ChunkRec;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*  chunk set methods                                                    */
+  /*                                                                       */
+
+  typedef FT_Error  (*FTC_ChunkSet_InitFunc)  ( FTC_ChunkSet   cset,
+                                                FT_Pointer     type );
+
+
+  typedef void      (*FTC_ChunkSet_DoneFunc)   ( FTC_ChunkSet  cset );
+
+  typedef FT_Bool   (*FTC_ChunkSet_CompareFunc)( FTC_ChunkSet  cset,
+                                                 FT_Pointer    type );
+
+
+
+  typedef FT_Error  (*FTC_ChunkSet_NewNodeFunc)( FTC_ChunkSet     cset,
+                                                 FT_UInt          index,
+                                                 FTC_ChunkNode*   anode );
+
+  typedef void      (*FTC_ChunkSet_DestroyNodeFunc)( FTC_ChunkNode  node );
+
+  typedef FT_ULong  (*FTC_ChunkSet_SizeNodeFunc)   ( FTC_ChunkNode  node );
+
+
+  typedef struct  FTC_ChunkSet_Class_
+  {
+    FT_UInt                       cset_size;
+
+    FTC_ChunkSet_InitFunc         init;
+    FTC_ChunkSet_DoneFunc         done;
+    FTC_ChunkSet_CompareFunc      compare;
+
+    FTC_ChunkSet_NewNodeFunc      new_node;
+    FTC_ChunkSet_SizeNodeFunc     size_node;
+    FTC_ChunkSet_DestroyNodeFunc  destroy_node;
+
+  } FTC_ChunkSet_Class;
+
+
+  typedef struct  FTC_ChunkSetRec_
+  {
+    FTC_Chunk_Cache      cache;
+    FTC_Manager          manager;
+    FT_Memory            memory;
+    FTC_ChunkSet_Class*  clazz;
+    FT_UInt              cset_index;  /* index in parent cache    */
+
+    FT_UInt              element_max;    /* maximum number of elements   */
+    FT_UInt              element_size;   /* element size in bytes        */
+    FT_UInt              element_count;  /* number of elements per chunk */
+    FT_UInt              num_chunks;
+    FTC_ChunkNode*       chunks;
+
+  } FTC_ChunkSetRec;
+
+
+  /* the abstract chunk cache class */
+  typedef struct  FTC_Chunk_Cache_Class_
+  {
+    FTC_Cache_Class      root;
+    FTC_ChunkSet_Class*  cset_class;
+
+  } FTC_Chunk_Cache_Class;
+
+
+  /* the abstract chunk cache object */
+  typedef struct  FTC_Chunk_CacheRec_
+  {
+    FTC_CacheRec     root;
+    FT_Lru           csets_lru;  /* static chunk set lru list */
+    FTC_ChunkSet     last_cset;  /* small cache :-)           */
+
+  } FTC_Chunk_CacheRec;
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* These functions are exported so that they can be called from          */
+  /* user-provided cache classes; otherwise, they are really parts of the  */
+  /* cache sub-system internals.                                           */
+  /*                                                                       */
+
+  FT_EXPORT_FUNC( NV_Error )
+  FTC_ChunkNode_Init( FTC_ChunkNode  node,
+                      FTC_ChunkSet   cset,
+                      FT_UInt        index,
+                      FT_Bool        alloc );
+
+#define FTC_ChunkNode_Ref( n ) \
+          FTC_CACHENODE_TO_DATA_P( &(n)->root )->ref_count++
+
+#define FTC_ChunkNode_Unref( n ) \
+          FTC_CACHENODE_TO_DATA_P( &(n)->root )->ref_count--
+
+
+  FT_EXPORT_DEF( void )
+  FTC_ChunkNode_Destroy( FTC_ChunkNode    node );
+
+
+
+  FT_EXPORT_DEF( FT_Error )
+  FTC_Chunk_Cache_Init( FTC_Chunk_Cache  cache );
+
+
+  FT_EXPORT_DEF( void )
+  FTC_Chunk_Cache_Done( FTC_Chunk_Cache  cache );
+
+
+
+
+  FT_EXPORT_DEF( FT_Error )
+  FTC_ChunkSet_New( FTC_Chunk_Cache   cache,
+                    FT_Pointer        type,
+                    FT_UInt           num_elements,
+                    FT_UInt           element_size,
+                    FT_UInt           chunk_size,
+                    FTC_ChunkSet     *aset )
+
+
+  FT_EXPORT_DEF( FT_Error )
+  FTC_ChunkSet_Lookup_Node( FTC_ChunkSet     cset,
+                            FT_UInt          glyph_index,
+                            FTC_ChunkNode   *anode,
+                            FT_UInt         *aindex );
+
+#ifdef __cplusplus
+  }
+#endif
+
+
+#endif /* FTCCHUNK_H */
+
+/* END */
--- a/include/freetype/cache/ftcglyph.h
+++ b/include/freetype/cache/ftcglyph.h
@@ -57,21 +57,20 @@
 #endif
 
 
-  /* maximum number of queues per glyph cache; must be < 256 */
-#define FTC_MAX_GLYPH_QUEUES  16
+  /* maximum number of glyph sets per glyph cache; must be < 256 */
+#define FTC_MAX_GLYPH_SETS          16
+#define FTC_GSET_HASH_SIZE_DEFAULT  64
 
-#define FTC_QUEUE_HASH_SIZE_DEFAULT  64
-
-  typedef struct FTC_Glyph_QueueRec_*  FTC_Glyph_Queue;
+  typedef struct FTC_GlyphSetRec_*     FTC_GlyphSet;
   typedef struct FTC_GlyphNodeRec_*    FTC_GlyphNode;
   typedef struct FTC_Glyph_CacheRec_*  FTC_Glyph_Cache;
 
-  typedef struct  FTC_GlyphNodeRec_
+  typedef struct FTC_GlyphNodeRec_
   {
     FTC_CacheNodeRec  root;
-    FTC_GlyphNode     queue_next;   /* next in queue's bucket list */
+    FTC_GlyphNode     gset_next;   /* next in glyph set's bucket list */
     FT_UShort         glyph_index;
-    FT_UShort         queue_index;
+    FT_UShort         gset_index;
 
   } FTC_GlyphNodeRec;
 
@@ -83,62 +82,62 @@
 
   /*************************************************************************/
   /*                                                                       */
-  /* Glyph queue methods.                                                  */
+  /* Glyph set methods.                                                    */
   /*                                                                       */
 
-  typedef FT_Error  (*FTC_Glyph_Queue_InitFunc)( FTC_Glyph_Queue  queue,
-                                                 FT_Pointer       type );
+  typedef FT_Error  (*FTC_GlyphSet_InitFunc)   ( FTC_GlyphSet  gset,
+                                                 FT_Pointer    type );
 
-  typedef void  (*FTC_Glyph_Queue_DoneFunc)( FTC_Glyph_Queue  queue );
+  typedef void      (*FTC_GlyphSet_DoneFunc)   ( FTC_GlyphSet  gset );
 
-  typedef FT_Bool  (*FTC_Glyph_Queue_CompareFunc)( FTC_Glyph_Queue  queue,
-                                                   FT_Pointer       type );
+  typedef FT_Bool   (*FTC_GlyphSet_CompareFunc)( FTC_GlyphSet  gset,
+                                                 FT_Pointer    type );
 
-  typedef FT_Error  (*FTC_Glyph_Queue_NewNodeFunc)( FTC_Glyph_Queue  queue,
-                                                    FT_UInt          gindex,
-                                                    FTC_GlyphNode*   anode );
 
-  typedef void  (*FTC_Glyph_Queue_DestroyNodeFunc)( FTC_GlyphNode    node,
-                                                    FTC_Glyph_Queue  queue );
+  typedef FT_Error  (*FTC_GlyphSet_NewNodeFunc)( FTC_GlyphSet    gset,
+                                                 FT_UInt         gindex,
+                                                 FTC_GlyphNode  *anode );
 
-  typedef FT_ULong (*FTC_Glyph_Queue_SizeNodeFunc)( FTC_GlyphNode    node,
-                                                    FTC_Glyph_Queue  queue );
+  typedef void  (*FTC_GlyphSet_DestroyNodeFunc)( FTC_GlyphNode   node,
+                                                 FTC_GlyphSet    gset );
 
+  typedef FT_ULong (*FTC_GlyphSet_SizeNodeFunc)( FTC_GlyphNode   node,
+                                                 FTC_GlyphSet    gset );
 
-  typedef struct  FTC_Glyph_Queue_Class_
+
+  typedef struct  FTC_GlyphSet_Class_
   {
-    FT_UInt                          queue_byte_size;
+    FT_UInt                       gset_byte_size;
 
-    FTC_Glyph_Queue_InitFunc         init;
-    FTC_Glyph_Queue_DoneFunc         done;
-    FTC_Glyph_Queue_CompareFunc      compare;
+    FTC_GlyphSet_InitFunc         init;
+    FTC_GlyphSet_DoneFunc         done;
+    FTC_GlyphSet_CompareFunc      compare;
 
-    FTC_Glyph_Queue_NewNodeFunc      new_node;
-    FTC_Glyph_Queue_SizeNodeFunc     size_node;
-    FTC_Glyph_Queue_DestroyNodeFunc  destroy_node;
+    FTC_GlyphSet_NewNodeFunc      new_node;
+    FTC_GlyphSet_SizeNodeFunc     size_node;
+    FTC_GlyphSet_DestroyNodeFunc  destroy_node;
 
-  } FTC_Glyph_Queue_Class;
+  } FTC_GlyphSet_Class;
 
 
-  typedef struct  FTC_Glyph_QueueRec_
+  typedef struct  FTC_GlyphSetRec_
   {
-    FTC_Glyph_Cache         cache;
-    FTC_Manager             manager;
-    FT_Memory               memory;
-    FTC_Glyph_Queue_Class*  clazz;
-    FTC_Image_Desc          descriptor;
-    FT_UInt                 hash_size;
-    FTC_GlyphNode*          buckets;
-    FT_UInt                 queue_index;  /* index in parent cache    */
+    FTC_Glyph_Cache      cache;
+    FTC_Manager          manager;
+    FT_Memory            memory;
+    FTC_GlyphSet_Class*  clazz;
+    FT_UInt              hash_size;
+    FTC_GlyphNode*       buckets;
+    FT_UInt              gset_index;  /* index in parent cache    */
 
-  } FTC_Glyph_QueueRec;
+  } FTC_GlyphSetRec;
 
 
   /* the abstract glyph cache class */
   typedef struct  FTC_Glyph_Cache_Class_
   {
-    FTC_Cache_Class         root;
-    FTC_Glyph_Queue_Class*  queue_class;
+    FTC_Cache_Class      root;
+    FTC_GlyphSet_Class*  gset_class;
 
   } FTC_Glyph_Cache_Class;
 
@@ -146,9 +145,9 @@
   /* the abstract glyph cache object */
   typedef struct  FTC_Glyph_CacheRec_
   {
-    FTC_CacheRec     root;
-    FT_Lru           queues_lru;  /* static queues lru list */
-    FTC_Glyph_Queue  last_queue;  /* small cache :-)        */
+    FTC_CacheRec  root;
+    FT_Lru        gsets_lru;  /* static sets lru list */
+    FTC_GlyphSet  last_gset;  /* small cache :-)        */
 
   } FTC_Glyph_CacheRec;
 
@@ -161,9 +160,9 @@
   /*                                                                       */
 
   FT_EXPORT_FUNC( void )
-  FTC_GlyphNode_Init( FTC_GlyphNode    node,
-                      FTC_Glyph_Queue  queue,
-                      FT_UInt          gindex );
+  FTC_GlyphNode_Init( FTC_GlyphNode  node,
+                      FTC_GlyphSet   gset,
+                      FT_UInt        gindex );
 
 #define FTC_GlyphNode_Ref( n ) \
           FTC_CACHENODE_TO_DATA_P( &(n)->root )->ref_count++
@@ -173,8 +172,8 @@
 
 
   FT_EXPORT_DEF( void )
-  FTC_Destroy_Glyph_Node( FTC_GlyphNode    node,
-                          FTC_Glyph_Cache  cache );
+  FTC_GlyphNode_Destroy( FTC_GlyphNode    node,
+                         FTC_Glyph_Cache  cache );
 
 
 
@@ -189,15 +188,15 @@
 
 
   FT_EXPORT_DEF( FT_Error )
-  FTC_Glyph_Queue_New( FTC_Glyph_Cache   cache,
-                       FT_Pointer        type,
-                       FTC_Glyph_Queue*  aqueue );
+  FTC_GlyphSet_New( FTC_Glyph_Cache   cache,
+                    FT_Pointer        type,
+                    FTC_GlyphSet     *aset );
 
 
   FT_EXPORT_DEF( FT_Error )
-  FTC_Glyph_Queue_Lookup_Node( FTC_Glyph_Queue  queue,
-                               FT_UInt          glyph_index,
-                               FTC_GlyphNode*   anode );
+  FTC_GlyphSet_Lookup_Node( FTC_GlyphSet     gset,
+                            FT_UInt          glyph_index,
+                            FTC_GlyphNode   *anode );
 
 
 #ifdef __cplusplus
@@ -205,6 +204,6 @@
 #endif
 
 
-#endif /* FTCIMAGE_H */
+#endif /* FTCGLYPH_H */
 
 /* END */
--- a/include/freetype/ftcache.h
+++ b/include/freetype/ftcache.h
@@ -450,7 +450,7 @@
   /*              failure.                                                 */
   /*                                                                       */
   /* <Return>                                                              */
-  /*    FreType error code.  0 means success.                              */
+  /*    error code, 0 means success                                        */
   /*                                                                       */
   /* <Note>                                                                */
   /*    the returned glyph is owned and manager by the glyph image cache.  */
@@ -461,11 +461,11 @@
   /*    taken by the glyphs it holds, the returned glyph might disappear   */
   /*    on a later invocation of this function!  It's a cache after all... */
   /*                                                                       */
-  FT_EXPORT_DEF( FT_Error )  FTC_Image_Cache_Lookup(
-                               FTC_Image_Cache  cache,
-                               FTC_Image_Desc*  desc,
-                               FT_UInt          gindex,
-                               FT_Glyph*        aglyph );
+  FT_EXPORT_DEF( FT_Error )
+  FTC_Image_Cache_Lookup( FTC_Image_Cache  cache,
+                          FTC_Image_Desc*  desc,
+                          FT_UInt          gindex,
+                          FT_Glyph*        aglyph );
 
 
 #ifdef __cplusplus
--- /dev/null
+++ b/src/cache/ftcchunk.c
@@ -1,0 +1,373 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftcchunk.c                                                             */
+/*                                                                         */
+/*    FreeType chunk cache cache (body).                                   */
+/*                                                                         */
+/*  Copyright 2000 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 <freetype/cache/ftcglyph.h>
+#include <freetype/fterrors.h>
+#include <freetype/internal/ftobjs.h>
+#include <freetype/internal/ftlist.h>
+#include <freetype/fterrors.h>
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*****                                                               *****/
+  /*****                      GLYPH NODES                              *****/
+  /*****                                                               *****/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+
+  /* create a new chunk node, setting its cache index and ref count */
+  FT_EXPORT_FUNC( NV_Error )
+  FTC_ChunkNode_Init( FTC_ChunkNode  node,
+                      FTC_ChunkSet   cset,
+                      FT_UInt        index,
+                      FT_Bool        alloc )
+  {
+    FTC_Chunk_Cache      cache = cset->cache;
+    FTC_CacheNode_Data*  data  = FTC_CACHENODE_TO_DATA_P( &node->root );
+    NV_Error             error = 0;
+
+
+    data->cache_index = (FT_UShort) cache->root.cache_index;
+    data->ref_count   = (FT_Short)  0;
+    node->cset_index  = (FT_UShort) index;
+
+    node->num_elements = (index+1 < cset->chunk_count)
+                       ? cset->chunk_size
+                       : cset->element_max - cset->chunk_count*index;
+    if (alloc)
+    {
+      /* allocate elements array */
+      memory = cache->root.memory;
+      error  = MEM_ALLOC( cache->elements, cset->element_size *
+                                           cset->element_count );
+    }
+    return error;
+  }
+
+
+  FT_EXPORT_FUNC( void )  FTC_ChunkNode_Destroy( FTC_ChunkNode    node )
+  {
+    FTC_ChunkSet  cset     = node->cset;
+
+    /* remove from parent set table */
+    cset->chunks[ node->cset_index ] = 0;
+        
+    /* destroy the node */
+    cset->clazz->destroy_node( node );
+  }
+
+
+  FT_EXPORT_FUNC( FT_ULong )  FTC_ChunkNode_Size( FTC_ChunkNode    node )
+  {
+    FTC_ChunkSet  cset     = node->cset;
+
+
+    return cset->clazz->size_node( node, cset );
+  }
+
+
+  FT_CPLUSPLUS( const FTC_CacheNode_Class )  ftc_chunk_cache_node_class =
+  {
+    (FTC_CacheNode_SizeFunc)    FTC_ChunkNode_Size,
+    (FTC_CacheNode_DestroyFunc) FTC_ChunkNode_Destroy
+  };
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*****                                                               *****/
+  /*****                      CHUNK SETS                               *****/
+  /*****                                                               *****/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  FT_EXPORT_FUNC( FT_Error )
+  FTC_ChunkSet_New( FTC_Chunk_Cache   cache,
+                    FT_Pointer        type,
+                    FT_UInt           num_elements,
+                    FT_UInt           element_size,
+                    FT_UInt           chunk_size,
+                    FTC_ChunkSet     *aset )
+  {
+    FT_Error      error;
+    FT_Memory     memory  = cache->root.memory;
+    FTC_Manager   manager = cache->root.manager;
+    FTC_ChunkSet  cset    = 0;
+
+    FTC_Chunk_Cache_Class*  ccache_class;
+    FTC_ChunkSet_Class*     clazz;
+
+
+    ccache_class = (FTC_Chunk_Cache_Class*)cache->root.clazz;
+    clazz        = ccache_class->cset_class;
+
+    *aset = 0;
+
+    if ( ALLOC( set, clazz->cset_byte_size ) )
+      goto Exit;
+
+    cset->cache         = cache;
+    cset->manager       = manager;
+    cset->memory        = memory;
+    cset->element_max   = num_elements;
+    cset->element_size  = element_size;
+    cset->element_count = chunk_size;
+    cset->clazz         = clazz;
+
+    /* compute maximum number of nodes */
+    cset->num_chunks = (num_elements + (chunk_size-1))/chunk_size;
+
+    /* allocate chunk pointers table */
+    if ( ALLOC_ARRAY( cset->chunks, cset->num_chunks, FTC_ChunkNode ) )
+      goto Exit;
+
+    /* initialize set by type if needed */
+    if ( clazz->init )
+    {
+      error = clazz->init( cset, type );
+      if ( error )
+        goto Exit;
+    }
+
+    *aset = cset;
+
+  Exit:
+    if ( error && cset )
+    {
+      FREE( cset->chunks );
+      FREE( cset );
+    }
+
+    return error;
+  }
+
+
+  FT_EXPORT_FUNC( void )  FTC_ChunkSet_Destroy( FTC_ChunkSet  cset )
+  {
+    FTC_Chunk_Cache         cache        = cset->cache;
+    FTC_Manager             manager      = cache->root.manager;
+    FT_List                 glyphs_lru   = &manager->global_lru;
+    FTC_ChunkNode*          bucket       = cset->chunk;
+    FTC_ChunkNode*          bucket_limit = bucket + cset->num_chunks;
+    FT_Memory               memory       = cache->root.memory;
+
+    FTC_ChunkSet_Class*     clazz = cset->clazz;
+
+
+    /* for each bucket, free the list of glyph nodes */
+    for ( ; bucket < bucket_limit; bucket++ )
+    {
+      FTC_ChunkNode   node = bucket[0];
+      FT_ListNode     lrunode;
+
+      lrunode = FTC_CHUNKNODE_TO_LRUNODE( node );
+
+      manager->num_bytes -= clazz->size_node( node );
+
+      FT_List_Remove( glyphs_lru, lrunode );
+
+      clazz->destroy_node( node );
+
+      bucket[0] = 0;
+   }
+
+   if ( clazz->done )
+     clazz->done( cset );
+
+    FREE( cset->chunks );
+    FREE( cset );
+  }
+
+
+  FT_EXPORT_FUNC( FT_Error )
+  FTC_ChunkSet_Lookup_Node( FTC_ChunkSet    cset,
+                            FT_UInt         glyph_index,
+                            FTC_ChunkNode  *anode,
+                            FTC_UInt       *index )
+  {
+    FTC_Glyph_Cache  cache   = cset->cache;
+    FTC_Manager      manager = cache->root.manager;
+    FT_Error         error   = 0;
+
+    FTC_GlyphSet_Class*  clazz = cset->clazz;
+
+
+    *anode = 0;
+    if (glyph_index >= cset->elements_max)
+      error = FT_Err_Invalid_Argument;
+    else
+    {
+      FT_UInt         chunk_size  = cset->chunk_size;
+      FT_UInt         chunk_index = glyph_index/chunk_size;
+      FTC_ChunkNode*  pnode       = cset->chunks + chunk_index;
+      FTC_ChunkNode   node        = *pnode;
+      
+      if (!node)
+      {
+        /* we didn't found the glyph image, we will now create a new one */
+        error = clazz->new_node( cset, glyph_index, &node );
+        if ( error )
+          goto Exit;
+
+        /* store the new chunk in the cset's table */
+        *pnode = node;
+
+        /* insert the node at the start the global LRU glyph list */
+        FT_List_Insert( &manager->global_lru, FTC_CHUNKNODE_TO_LRUNODE( node ) );
+
+        manager->num_bytes += clazz->size_node( node, gset );
+
+        if (manager->num_bytes > manager->max_bytes)
+        {
+          FTC_ChunkNode_Ref   ( node );
+          FTC_Manager_Compress( manager );
+          FTC_ChunkNode_Unref ( node );
+        }
+      }
+
+      *anode  = node;
+      *aindex = glyph_index - chunk_index*chunk_size;
+    }
+
+  Exit:
+    return error;
+  }
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*****                                                               *****/
+  /*****                   CHUNK SETS LRU CALLBACKS                    *****/
+  /*****                                                               *****/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+#define FTC_CSET_LRU_GET_CACHE( lru )   \
+          ( (FTC_Chunk_Cache)(lru)->user_data )
+
+#define FTC_CSET_LRU_GET_MANAGER( lru ) \
+          FTC_CSET_LRU_GET_CACHE( lru )->manager
+
+#define FTC_LRUNODE_CSET( node )        \
+          ( (FTC_ChunkSet)(node)->root.data )
+
+
+  LOCAL_FUNC_X
+  FT_Error  ftc_chunk_set_lru_init( FT_Lru      lru,
+                                    FT_LruNode  node )
+  {
+    FTC_Chunk_Cache  cache = FTC_CSET_LRU_GET_CACHE( lru );
+    FT_Error         error;
+    FTC_ChunkSet     cset;
+
+
+    error = FTC_ChunkSet_New( cache,
+                              (FT_Pointer)node->key,
+                              &cset );
+    if ( !error )
+    {
+      /* good, now set the set index within the set object */
+      cset->cset_index = node - lru->nodes;
+      node->root.data  = set;
+    }
+
+    return error;
+  }
+
+
+  LOCAL_FUNC_X
+  void  ftc_chunk_set_lru_done( FT_Lru      lru,
+                                FT_LruNode  node )
+  {
+    FTC_ChunkSet  cset = FTC_LRUNODE_CSET( node );
+
+    FT_UNUSED( lru );
+
+
+    FTC_ChunkSet_Destroy( cset );
+  }
+
+
+  LOCAL_FUNC_X
+  FT_Bool  ftc_chunk_set_lru_compare( FT_LruNode  node,
+                                      FT_LruKey   key )
+  {
+    FTC_ChunkSet  cset = FTC_LRUNODE_CSET( node );
+
+
+    return cset->clazz->compare( cset, (FT_Pointer)key );
+  }
+
+
+  FT_CPLUSPLUS( const FT_Lru_Class )  ftc_chunk_set_lru_class =
+  {
+    sizeof( FT_LruRec ),
+    ftc_chunk_set_lru_init,
+    ftc_chunk_set_lru_done,
+    0,  /* no flush */
+    ftc_chunk_set_lru_compare
+  };
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*****                                                               *****/
+  /*****                   CHUNK CACHE OBJECTS                         *****/
+  /*****                                                               *****/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  FT_EXPORT_FUNC( FT_Error )  FTC_Chunk_Cache_Init( FTC_Chunk_Cache  cache )
+  {
+    FT_Memory  memory = cache->root.memory;
+    FT_Error   error;
+
+
+    /* set up root node_class to be used by manager */
+    cache->root.node_clazz =
+      (FTC_CacheNode_Class*)&ftc_chunk_cache_node_class;
+
+    /* The following is extremely important for ftc_destroy_glyph_image() */
+    /* to work properly, as the second parameter that is sent to it       */
+    /* through the cache manager is `user_data' and must be set to        */
+    /* `cache' here.                                                      */
+    /*                                                                    */
+    cache->root.cache_user = cache;
+
+    error = FT_Lru_New( &ftc_chunk_set_lru_class,
+                        FTC_MAX_GLYPH_CSETS,
+                        cache,
+                        memory,
+                        1, /* pre_alloc == TRUE */
+                        &cache->csets_lru );
+    return error;
+  }
+
+
+  FT_EXPORT_FUNC( void )  FTC_Chunk_Cache_Done( FTC_Chunk_Cache  cache )
+  {
+    /* discard glyph sets */
+    FT_Lru_Done( cache->csets_lru );
+  }
+
+
--- a/src/cache/ftcglyph.c
+++ b/src/cache/ftcglyph.c
@@ -16,16 +16,6 @@
 /***************************************************************************/
 
 
-  /*************************************************************************/
-  /*                                                                       */
-  /*  Note: The implementation of glyph queues is rather generic in this   */
-  /*        code.  This will allow other glyph node/cache types to be      */
-  /*        easily included in the future.  For now, we only cache glyph   */
-  /*        images.                                                        */
-  /*                                                                       */
-  /*************************************************************************/
-
-
 #include <freetype/cache/ftcglyph.h>
 #include <freetype/fterrors.h>
 #include <freetype/internal/ftobjs.h>
@@ -42,22 +32,18 @@
   /*************************************************************************/
 
 
-  /* In the future, we might provide a better scheme for managing glyph  */
-  /* node elements.  For the moment, we simply use FT_Alloc()/FT_Free(). */
-
-
   /* create a new glyph node, setting its cache index and ref count */
-  FT_EXPORT_FUNC( void )  FTC_GlyphNode_Init( FTC_GlyphNode    node,
-                                              FTC_Glyph_Queue  queue,
-                                              FT_UInt          gindex )
+  FT_EXPORT_FUNC( void )  FTC_GlyphNode_Init( FTC_GlyphNode  node,
+                                              FTC_GlyphSet   gset,
+                                              FT_UInt        gindex )
   {
-    FTC_Glyph_Cache      cache = queue->cache;
+    FTC_Glyph_Cache      cache = gset->cache;
     FTC_CacheNode_Data*  data  = FTC_CACHENODE_TO_DATA_P( &node->root );
 
 
     data->cache_index = (FT_UShort)cache->root.cache_index;
     data->ref_count   = (FT_Short) 0;
-    node->queue_index = (FT_UShort)queue->queue_index;
+    node->gset_index  = (FT_UShort)gset->gset_index;
     node->glyph_index = (FT_UShort)gindex;
   }
 
@@ -72,13 +58,13 @@
   FT_EXPORT_FUNC( void )  FTC_GlyphNode_Destroy( FTC_GlyphNode    node,
                                                  FTC_Glyph_Cache  cache )
   {
-    FT_LruNode       queue_lru = cache->queues_lru->nodes + node->queue_index;
-    FTC_Glyph_Queue  queue     = (FTC_Glyph_Queue)queue_lru->root.data;
-    FT_UInt          hash      = node->glyph_index % queue->hash_size;
+    FT_LruNode    gset_lru = cache->gsets_lru->nodes + node->gset_index;
+    FTC_GlyphSet  gset     = (FTC_GlyphSet)gset_lru->root.data;
+    FT_UInt       hash     = node->glyph_index % gset->hash_size;
     
-    /* remove the node from its queue's bucket list */
+    /* remove the node from its gset's bucket list */
     {
-      FTC_GlyphNode*  pnode = queue->buckets + hash;
+      FTC_GlyphNode*  pnode = gset->buckets + hash;
       FTC_GlyphNode   cur;
       
       for (;;)
@@ -94,15 +80,15 @@
           
         if (cur == node)
         {
-          *pnode = cur->queue_next;
+          *pnode = cur->gset_next;
           break;
         }
-        pnode = &cur->queue_next;
+        pnode = &cur->gset_next;
       }
     }
 
     /* destroy the node */
-    queue->clazz->destroy_node( node, queue );
+    gset->clazz->destroy_node( node, gset );
   }
 
 
@@ -116,18 +102,18 @@
   FT_EXPORT_FUNC( FT_ULong )  FTC_GlyphNode_Size( FTC_GlyphNode    node,
                                                   FTC_Glyph_Cache  cache )
   {
-    FT_LruNode       queue_lru = cache->queues_lru->nodes + node->queue_index;
-    FTC_Glyph_Queue  queue     = (FTC_Glyph_Queue)queue_lru->root.data;
+    FT_LruNode    gset_lru = cache->gsets_lru->nodes + node->gset_index;
+    FTC_GlyphSet  gset     = (FTC_GlyphSet)gset_lru->root.data;
 
 
-    return queue->clazz->size_node( node, queue );
+    return gset->clazz->size_node( node, gset );
   }
 
 
   FT_CPLUSPLUS( const FTC_CacheNode_Class )  ftc_glyph_cache_node_class =
   {
-    (FTC_CacheNode_SizeFunc)   FTC_GlyphNode_Size,
-    (FTC_CacheNode_DestroyFunc)FTC_GlyphNode_Destroy
+    (FTC_CacheNode_SizeFunc)    FTC_GlyphNode_Size,
+    (FTC_CacheNode_DestroyFunc) FTC_GlyphNode_Destroy
   };
 
 
@@ -140,52 +126,52 @@
   /*************************************************************************/
 
 
-  FT_EXPORT_FUNC( FT_Error )  FTC_Glyph_Queue_New( FTC_Glyph_Cache   cache,
-                                                   FT_Pointer        type,
-                                                   FTC_Glyph_Queue*  aqueue )
+  FT_EXPORT_FUNC( FT_Error )  FTC_GlyphSet_New( FTC_Glyph_Cache  cache,
+                                                FT_Pointer       type,
+                                                FTC_GlyphSet    *aset )
   {
-    FT_Error         error;
-    FT_Memory        memory  = cache->root.memory;
-    FTC_Manager      manager = cache->root.manager;
-    FTC_Glyph_Queue  queue   = 0;
+    FT_Error        error;
+    FT_Memory       memory  = cache->root.memory;
+    FTC_Manager     manager = cache->root.manager;
+    FTC_GlyphSet    gset   = 0;
 
     FTC_Glyph_Cache_Class*  gcache_class;
-    FTC_Glyph_Queue_Class*  clazz;
+    FTC_GlyphSet_Class*     clazz;
 
 
     gcache_class = (FTC_Glyph_Cache_Class*)cache->root.clazz;
-    clazz        = gcache_class->queue_class;
+    clazz        = gcache_class->gset_class;
 
-    *aqueue = 0;
+    *aset = 0;
 
-    if ( ALLOC( queue, clazz->queue_byte_size ) )
+    if ( ALLOC( gset, clazz->gset_byte_size ) )
       goto Exit;
 
-    queue->cache     = cache;
-    queue->manager   = manager;
-    queue->memory    = memory;
-    queue->hash_size = FTC_QUEUE_HASH_SIZE_DEFAULT;
-    queue->clazz     = clazz;
+    gset->cache     = cache;
+    gset->manager   = manager;
+    gset->memory    = memory;
+    gset->hash_size = FTC_GSET_HASH_SIZE_DEFAULT;
+    gset->clazz     = clazz;
 
     /* allocate buckets table */
-    if ( ALLOC_ARRAY( queue->buckets, queue->hash_size, FTC_GlyphNode ) )
+    if ( ALLOC_ARRAY( gset->buckets, gset->hash_size, FTC_GlyphNode ) )
       goto Exit;
 
-    /* initialize queue by type if needed */
+    /* initialize gset by type if needed */
     if ( clazz->init )
     {
-      error = clazz->init( queue, type );
+      error = clazz->init( gset, type );
       if ( error )
         goto Exit;
     }
 
-    *aqueue = queue;
+    *aset = gset;
 
   Exit:
-    if ( error && queue )
+    if ( error && gset )
     {
-      FREE( queue->buckets );
-      FREE( queue );
+      FREE( gset->buckets );
+      FREE( gset );
     }
 
     return error;
@@ -192,16 +178,16 @@
   }
 
 
-  FT_EXPORT_FUNC( void )  FTC_Glyph_Queue_Done( FTC_Glyph_Queue  queue )
+  FT_EXPORT_FUNC( void )  FTC_GlyphSet_Destroy( FTC_GlyphSet  gset )
   {
-    FTC_Glyph_Cache         cache        = queue->cache;
+    FTC_Glyph_Cache         cache        = gset->cache;
     FTC_Manager             manager      = cache->root.manager;
     FT_List                 glyphs_lru   = &manager->global_lru;
-    FTC_GlyphNode*          bucket       = queue->buckets;
-    FTC_GlyphNode*          bucket_limit = bucket + queue->hash_size;
+    FTC_GlyphNode*          bucket       = gset->buckets;
+    FTC_GlyphNode*          bucket_limit = bucket + gset->hash_size;
     FT_Memory               memory       = cache->root.memory;
 
-    FTC_Glyph_Queue_Class*  clazz = queue->clazz;
+    FTC_GlyphSet_Class*  clazz = gset->clazz;
 
 
     /* for each bucket, free the list of glyph nodes */
@@ -214,14 +200,14 @@
 
       for ( ; node; node = next )
       {
-        next    = node->queue_next;
+        next    = node->gset_next;
         lrunode = FTC_GLYPHNODE_TO_LRUNODE( node );
 
-        manager->num_bytes -= clazz->size_node( node, queue );
+        manager->num_bytes -= clazz->size_node( node, gset );
 
         FT_List_Remove( glyphs_lru, lrunode );
 
-        clazz->destroy_node( node, queue );
+        clazz->destroy_node( node, gset );
       }
 
       bucket[0] = 0;
@@ -228,27 +214,27 @@
     }
 
     if ( clazz->done )
-      clazz->done( queue );
+      clazz->done( gset );
 
-    FREE( queue->buckets );
-    FREE( queue );
+    FREE( gset->buckets );
+    FREE( gset );
   }
 
 
   FT_EXPORT_FUNC( FT_Error )
-  FTC_Glyph_Queue_Lookup_Node( FTC_Glyph_Queue  queue,
-                               FT_UInt          glyph_index,
-                               FTC_GlyphNode*   anode )
+  FTC_GlyphSet_Lookup_Node( FTC_GlyphSet    gset,
+                            FT_UInt         glyph_index,
+                            FTC_GlyphNode  *anode )
   {
-    FTC_Glyph_Cache         cache      = queue->cache;
+    FTC_Glyph_Cache         cache      = gset->cache;
     FTC_Manager             manager    = cache->root.manager;
-    FT_UInt                 hash_index = glyph_index % queue->hash_size;
-    FTC_GlyphNode*          bucket     = queue->buckets + hash_index;
+    FT_UInt                 hash_index = glyph_index % gset->hash_size;
+    FTC_GlyphNode*          bucket     = gset->buckets + hash_index;
     FTC_GlyphNode*          pnode      = bucket;
     FTC_GlyphNode           node;
     FT_Error                error;
 
-    FTC_Glyph_Queue_Class*  clazz = queue->clazz;
+    FTC_GlyphSet_Class*  clazz = gset->clazz;
 
 
     *anode = 0;
@@ -262,9 +248,9 @@
       if ( node->glyph_index == glyph_index )
       {
         /* we found it! -- move glyph to start of the lists */
-        *pnode           = node->queue_next;
-        node->queue_next = bucket[0];
-        bucket[0]        = node;
+        *pnode          = node->gset_next;
+        node->gset_next = bucket[0];
+        bucket[0]       = node;
         
         FT_List_Up( &manager->global_lru, FTC_GLYPHNODE_TO_LRUNODE( node ) );
         *anode = node;
@@ -271,25 +257,29 @@
         return 0;
       }
       /* go to next node in bucket */
-      pnode = &node->queue_next;
+      pnode = &node->gset_next;
     }
 
     /* we didn't found the glyph image, we will now create a new one */
-    error = clazz->new_node( queue, glyph_index, &node );
+    error = clazz->new_node( gset, glyph_index, &node );
     if ( error )
       goto Exit;
 
     /* insert the node at the start of our bucket list */
-    node->queue_next = bucket[0];
-    bucket[0]        = node;
+    node->gset_next = bucket[0];
+    bucket[0]       = node;
 
     /* insert the node at the start the global LRU glyph list */
     FT_List_Insert( &manager->global_lru, FTC_GLYPHNODE_TO_LRUNODE( node ) );
 
-    manager->num_bytes += clazz->size_node( node, queue );
+    manager->num_bytes += clazz->size_node( node, gset );
 
     if (manager->num_bytes > manager->max_bytes)
+    {
+      FTC_GlyphNode_Ref   ( node );
       FTC_Manager_Compress( manager );
+      FTC_GlyphNode_Unref ( node );
+    }
 
     *anode = node;
 
@@ -301,39 +291,37 @@
   /*************************************************************************/
   /*************************************************************************/
   /*****                                                               *****/
-  /*****                   GLYPH QUEUES LRU CALLBACKS                  *****/
+  /*****                   GLYPH SETS LRU CALLBACKS                    *****/
   /*****                                                               *****/
   /*************************************************************************/
   /*************************************************************************/
 
 
-#define FTC_QUEUE_LRU_GET_CACHE( lru )   \
+#define FTC_GSET_LRU_GET_CACHE( lru )   \
           ( (FTC_Glyph_Cache)(lru)->user_data )
 
-#define FTC_QUEUE_LRU_GET_MANAGER( lru ) \
-          FTC_QUEUE_LRU_GET_CACHE( lru )->manager
+#define FTC_GSET_LRU_GET_MANAGER( lru ) \
+          FTC_GSET_LRU_GET_CACHE( lru )->manager
 
-#define FTC_LRUNODE_QUEUE( node )        \
-          ( (FTC_Glyph_Queue)(node)->root.data )
+#define FTC_LRUNODE_GSET( node )        \
+          ( (FTC_GlyphSet)(node)->root.data )
 
 
   LOCAL_FUNC_X
-  FT_Error  ftc_glyph_queue_lru_init( FT_Lru      lru,
-                                      FT_LruNode  node )
+  FT_Error  ftc_glyph_set_lru_init( FT_Lru      lru,
+                                    FT_LruNode  node )
   {
-    FTC_Glyph_Cache  cache = FTC_QUEUE_LRU_GET_CACHE( lru );
+    FTC_Glyph_Cache  cache = FTC_GSET_LRU_GET_CACHE( lru );
     FT_Error         error;
-    FTC_Glyph_Queue  queue;
+    FTC_GlyphSet     gset;
 
 
-    error = FTC_Glyph_Queue_New( cache,
-                                 (FT_Pointer)node->key,
-                                 &queue );
+    error = FTC_GlyphSet_New( cache, (FT_Pointer)node->key, &gset );
     if ( !error )
     {
-      /* good, now set the queue index within the queue object */
-      queue->queue_index = node - lru->nodes;
-      node->root.data    = queue;
+      /* good, now set the gset index within the gset object */
+      gset->gset_index = node - lru->nodes;
+      node->root.data  = gset;
     }
 
     return error;
@@ -341,36 +329,36 @@
 
 
   LOCAL_FUNC_X
-  void  ftc_glyph_queue_lru_done( FT_Lru      lru,
-                                  FT_LruNode  node )
+  void  ftc_glyph_set_lru_done( FT_Lru      lru,
+                                FT_LruNode  node )
   {
-    FTC_Glyph_Queue  queue = FTC_LRUNODE_QUEUE( node );
+    FTC_GlyphSet  gset = FTC_LRUNODE_GSET( node );
 
     FT_UNUSED( lru );
 
 
-    FTC_Glyph_Queue_Done( queue );
+    FTC_GlyphSet_Destroy( gset );
   }
 
 
   LOCAL_FUNC_X
-  FT_Bool  ftc_glyph_queue_lru_compare( FT_LruNode  node,
-                                        FT_LruKey   key )
+  FT_Bool  ftc_glyph_set_lru_compare( FT_LruNode  node,
+                                      FT_LruKey   key )
   {
-    FTC_Glyph_Queue  queue = FTC_LRUNODE_QUEUE( node );
+    FTC_GlyphSet  gset = FTC_LRUNODE_GSET( node );
 
 
-    return queue->clazz->compare( queue, (FT_Pointer)key );
+    return gset->clazz->compare( gset, (FT_Pointer)key );
   }
 
 
-  FT_CPLUSPLUS( const FT_Lru_Class )  ftc_glyph_queue_lru_class =
+  FT_CPLUSPLUS( const FT_Lru_Class )  ftc_glyph_set_lru_class =
   {
     sizeof( FT_LruRec ),
-    ftc_glyph_queue_lru_init,
-    ftc_glyph_queue_lru_done,
+    ftc_glyph_set_lru_init,
+    ftc_glyph_set_lru_done,
     0,  /* no flush */
-    ftc_glyph_queue_lru_compare
+    ftc_glyph_set_lru_compare
   };
 
 
@@ -400,12 +388,12 @@
     /*                                                                    */
     cache->root.cache_user = cache;
 
-    error = FT_Lru_New( &ftc_glyph_queue_lru_class,
-                        FTC_MAX_GLYPH_QUEUES,
+    error = FT_Lru_New( &ftc_glyph_set_lru_class,
+                        FTC_MAX_GLYPH_SETS,
                         cache,
                         memory,
                         1, /* pre_alloc == TRUE */
-                        &cache->queues_lru );
+                        &cache->gsets_lru );
     return error;
   }
 
@@ -412,8 +400,8 @@
 
   FT_EXPORT_FUNC( void )  FTC_Glyph_Cache_Done( FTC_Glyph_Cache  cache )
   {
-    /* discard glyph queues */
-    FT_Lru_Done( cache->queues_lru );
+    /* discard glyph sets */
+    FT_Lru_Done( cache->gsets_lru );
   }
 
 
--- a/src/cache/ftcimage.c
+++ b/src/cache/ftcimage.c
@@ -36,13 +36,11 @@
   /*************************************************************************/
 
 
-  /* this is a simple glyph image destructor, which is called exclusively */
-  /* from the CacheQueue object                                           */
   LOCAL_FUNC_X
-  void  ftc_glyph_image_node_destroy( FTC_GlyphImage   node,
-                                      FTC_Glyph_Queue  queue )
+  void  ftc_glyph_image_node_destroy( FTC_GlyphImage  node,
+                                      FTC_GlyphSet    gset )
   {
-    FT_Memory  memory = queue->memory;
+    FT_Memory  memory = gset->memory;
 
 
     FT_Done_Glyph( node->ft_glyph );
@@ -51,12 +49,12 @@
 
 
   LOCAL_FUNC_X
-  FT_Error  ftc_glyph_image_node_new( FTC_Glyph_Queue  queue,
-                                      FT_UInt          glyph_index,
-                                      FTC_GlyphImage  *anode )
+  FT_Error  ftc_glyph_image_node_new( FTC_GlyphSet    gset,
+                                      FT_UInt         glyph_index,
+                                      FTC_GlyphImage *anode )
   {
-    FT_Memory        memory   = queue->memory;
-    FTC_Image_Queue  imageq = (FTC_Image_Queue)queue;
+    FT_Memory        memory   = gset->memory;
+    FTC_ImageSet     imageset = (FTC_ImageSet)gset;
     FT_Error         error;
     FTC_GlyphImage   node = 0;
     FT_Face          face;
@@ -68,17 +66,17 @@
       goto Exit;
 
     /* init its inner fields */
-    FTC_GlyphNode_Init( FTC_GLYPHNODE(node), queue, glyph_index );
+    FTC_GlyphNode_Init( FTC_GLYPHNODE(node), gset, glyph_index );
 
     /* we will now load the glyph image */
-    error = FTC_Manager_Lookup_Size( queue->manager,
-                                     &imageq->description.font,
+    error = FTC_Manager_Lookup_Size( gset->manager,
+                                     &imageset->description.font,
                                      &face, &size );
     if ( !error )
     {
       FT_UInt  glyph_index = node->root.glyph_index;
       FT_UInt  load_flags  = FT_LOAD_DEFAULT;
-      FT_UInt  image_type  = imageq->description.image_type;
+      FT_UInt  image_type  = imageset->description.image_type;
 
 
       if ( FTC_IMAGE_FORMAT( image_type ) == ftc_image_format_bitmap )
@@ -135,7 +133,7 @@
 
 
   /* this function is important because it is both part of */
-  /* a FTC_Glyph_Queue_Class and a FTC_CacheNode_Class     */
+  /* a FTC_GlyphSet_Class and a FTC_CacheNode_Class     */
   /*                                                       */
   LOCAL_FUNC_X
   FT_ULong  ftc_glyph_image_node_size( FTC_GlyphImage  node )
@@ -189,33 +187,33 @@
 
 
   LOCAL_FUNC_X
-  FT_Error  ftc_image_queue_init( FTC_Image_Queue  queue,
-                                  FTC_Image_Desc*  type )
+  FT_Error  ftc_image_set_init( FTC_ImageSet     iset,
+                                FTC_Image_Desc*  type )
   {
-    queue->description = *type;
+    iset->description = *type;
     return 0;
   }
 
 
   LOCAL_FUNC_X
-  FT_Bool  ftc_image_queue_compare( FTC_Image_Queue  queue,
-                                    FTC_Image_Desc*  type )
+  FT_Bool  ftc_image_set_compare( FTC_ImageSet     iset,
+                                  FTC_Image_Desc*  type )
   {
-    return !memcmp( &queue->description, type, sizeof ( *type ) );
+    return !memcmp( &iset->description, type, sizeof ( *type ) );
   }
 
 
-  FT_CPLUSPLUS( const FTC_Glyph_Queue_Class )  ftc_glyph_image_queue_class =
+  FT_CPLUSPLUS( const FTC_GlyphSet_Class )  ftc_glyph_image_set_class =
   {
-    sizeof( FTC_Image_QueueRec ),
+    sizeof( FTC_ImageSetRec ),
 
-    (FTC_Glyph_Queue_InitFunc)       ftc_image_queue_init,
-    (FTC_Glyph_Queue_DoneFunc)       0,
-    (FTC_Glyph_Queue_CompareFunc)    ftc_image_queue_compare,
+    (FTC_GlyphSet_InitFunc)       ftc_image_set_init,
+    (FTC_GlyphSet_DoneFunc)       0,
+    (FTC_GlyphSet_CompareFunc)    ftc_image_set_compare,
 
-    (FTC_Glyph_Queue_NewNodeFunc)    ftc_glyph_image_node_new,
-    (FTC_Glyph_Queue_SizeNodeFunc)   ftc_glyph_image_node_size,
-    (FTC_Glyph_Queue_DestroyNodeFunc)ftc_glyph_image_node_destroy
+    (FTC_GlyphSet_NewNodeFunc)    ftc_glyph_image_node_new,
+    (FTC_GlyphSet_SizeNodeFunc)   ftc_glyph_image_node_size,
+    (FTC_GlyphSet_DestroyNodeFunc)ftc_glyph_image_node_destroy
   };
 
 
@@ -231,11 +229,11 @@
   FT_CPLUSPLUS( const FTC_Glyph_Cache_Class )  ftc_glyph_image_cache_class =
   {
     {
-      sizeof( FTC_Glyph_CacheRec ),
-      (FTC_Cache_InitFunc)FTC_Glyph_Cache_Init,
-      (FTC_Cache_DoneFunc)FTC_Glyph_Cache_Done
+      sizeof( FTC_Image_CacheRec ),
+      (FTC_Cache_InitFunc) FTC_Glyph_Cache_Init,
+      (FTC_Cache_DoneFunc) FTC_Glyph_Cache_Done
     },
-    (FTC_Glyph_Queue_Class*)&ftc_glyph_image_queue_class
+    (FTC_GlyphSet_Class*) &ftc_glyph_image_set_class
   };
 
 
@@ -255,12 +253,12 @@
                           FT_UInt          gindex,
                           FT_Glyph*        aglyph )
   {
-    FT_Error         error;
-    FTC_Glyph_Queue  queue;
-    FTC_GlyphNode    node;
-    FTC_Manager      manager;
+    FT_Error       error;
+    FTC_GlyphSet   gset;
+    FTC_GlyphNode  node;
+    FTC_Manager    manager;
 
-    FTC_Image_Queue  img_queue;
+    FTC_ImageSet   img_set;
 
 
     /* check for valid `desc' delayed to FT_Lru_Lookup() */
@@ -268,20 +266,20 @@
     if ( !cache || !aglyph )
       return FT_Err_Invalid_Argument;
 
-    *aglyph   = 0;
-    queue     = cache->root.last_queue;
-    img_queue = (FTC_Image_Queue)queue;
-    if ( !queue || memcmp( &img_queue->description, desc, sizeof ( *desc ) ) )
+    *aglyph  = 0;
+    gset     = cache->root.last_gset;
+    img_set  = (FTC_ImageSet)gset;
+    if ( !gset || memcmp( &img_set->description, desc, sizeof ( *desc ) ) )
     {
-      error = FT_Lru_Lookup( cache->root.queues_lru,
+      error = FT_Lru_Lookup( cache->root.gsets_lru,
                              (FT_LruKey)desc,
-                             (FT_Pointer*)&queue );
-      cache->root.last_queue = queue;
+                             (FT_Pointer*)&gset );
+      cache->root.last_gset = gset;
       if ( error )
         goto Exit;
     }
 
-    error = FTC_Glyph_Queue_Lookup_Node( queue, gindex, &node );
+    error = FTC_GlyphSet_Lookup_Node( gset, gindex, &node );
     if ( error )
       goto Exit;
 
--- a/src/cache/ftcimage.h
+++ b/src/cache/ftcimage.h
@@ -38,12 +38,12 @@
 
 
   /* the glyph image queue type */
-  typedef struct  FTC_Image_QueueRec_
+  typedef struct  FTC_ImageSetRec_
   {
-    FTC_Glyph_QueueRec  root;
-    FTC_Image_Desc      description;
+    FTC_GlyphSetRec  root;
+    FTC_Image_Desc   description;
   
-  } FTC_Image_QueueRec, *FTC_Image_Queue;
+  } FTC_ImageSetRec, *FTC_ImageSet;
 
 
   typedef struct  FTC_Image_CacheRec_
--- /dev/null
+++ b/src/cache/ftcsbits.c
@@ -1,0 +1,346 @@
+#include <cache/ftcsbits.h>
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*****                                                               *****/
+  /*****                    GLYPH IMAGE NODES                          *****/
+  /*****                                                               *****/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  LOCAL_FUNC_X
+  void  ftc_sbit_chunk_node_destroy( FTC_ChunkNode  node )
+  {
+    FTC_ChunkSet   cset   = node->cset;
+    FT_Memory      memory = cset->memory;
+    FT_UInt        count  = node->num_elements;
+    FTC_SBit       sbit   = (FTC_SBit)node->elements;
+    
+    for ( ; count > 0; sbit++, count-- )
+      FREE( sbit->buffer );
+
+    FREE( node );
+  }
+
+
+  static
+  FT_Error  ftc_bitmap_copy( FT_Memory   memory,
+                             FT_Bitmap*  source,
+                             FTC_SBit    target )
+  {
+    FT_Error  error;
+    FT_Int    pitch = source->pitch;
+    FT_ULong  size;
+
+    if ( pitch < 0 )
+      pitch = -pitch;
+
+    size = (FT_ULong)( pitch * source->rows );
+
+    if ( !ALLOC( target->buffer, size ) )
+      MEM_Copy( target->buffer, source->buffer, size );
+
+    return error;
+  }
+
+
+  LOCAL_FUNC_X
+  FT_Error  ftc_sbit_chunk_node_new( FTC_ChunkSet   cset,
+                                     FT_UInt        index,
+                                     FTC_SBitChunk *anode )
+  {
+    FT_Error         error;
+    FT_Memory        memory  = cset->memory;
+    FTC_SBitSet      sbitset = (FTC_SBitSet)cset;
+    FTC_SBitChunk    node    = 0;
+    FT_Face          face;
+    FT_Size          size;
+
+
+    /* allocate node */
+    if ( ALLOC( node, sizeof ( *node ) ) )
+      goto Exit;
+
+    /* init its inner fields */
+    error = FTC_ChunkNode_Init( FTC_CHUNKNODE(node), cset, index, 1 );
+    if (error)
+      goto Exit;
+
+    /* we will now load all glyph images */
+    error = FTC_Manager_Lookup_Size( cset->manager,
+                                     &sbitset->description.font,
+                                     &face, &size );
+    if ( !error )
+    {
+      FT_UInt  glyph_index = index * cset->chunk_size;
+      FT_UInt  load_flags  = FT_LOAD_DEFAULT;
+      FT_UInt  image_type  = sbitset->description.image_type;
+      FT_UInt  count       = node->num_elements;
+      FTC_SBit sbit        = (FTC_SBit)node->elements;
+
+
+      if ( FTC_IMAGE_FORMAT( image_type ) == ftc_image_format_bitmap )
+      {
+        if ( image_type & ftc_image_flag_monochrome )
+          load_flags |= FT_LOAD_MONOCHROME;
+
+        /* disable embedded bitmaps loading if necessary */
+        if ( image_type & ftc_image_flag_no_sbits )
+          load_flags |= FT_LOAD_NO_BITMAP;
+      }
+      else if ( FTC_IMAGE_FORMAT( image_type ) == ftc_image_format_outline )
+      {
+        /* disable embedded bitmaps loading */
+        load_flags |= FT_LOAD_NO_BITMAP;
+
+        if ( image_type & ftc_image_flag_unscaled )
+        {
+          FT_ERROR(( "FTC_SBit_Cache: cannot load vector outlines in a"
+                     " sbit cache, please check your arguments !!\n" ));
+          error = FT_Err_Bad_Argument;
+          goto Exit;
+        }
+      }
+
+      /* always render glyphs to bitmaps */
+      load_flags |= FT_LOAD_RENDER;
+        
+      if ( image_type & ftc_image_flag_unhinted )
+        load_flags |= FT_LOAD_NO_HINTING;
+
+      if ( image_type & ftc_image_flag_autohinted )
+        load_flags |= FT_LOAD_FORCE_AUTOHINT;
+
+
+      /* load a chunk of small bitmaps in a row */
+      for ( ; count > 0; count--, glyph_index++ )
+      {
+        error = FT_Load_Glyph( face, glyph_index, load_flags );
+        if (!error)
+        {
+          FT_Int        temp;
+          FT_GlyphSlot  slot   = face->glyph;
+          FT_Bitmap*    bitmap = &slot->bitmap;
+          FT_Int        advance;
+
+          /* check that our values fit in 8-bit containers !! */
+#define  CHECK_SCHAR(d)  ( temp = (FT_SChar)d, temp == d )
+#define  CHECK_BYTE(d)   ( temp = (FT_Byte) d, temp == d )
+
+          advance = (slot->metrics.horiAdvance+32) >> 6;
+          
+          if ( CHECK_BYTE ( bitmap->rows  )     &&
+               CHECK_BYTE ( bitmap->width )     &&
+               CHECK_SCHAR( bitmap->pitch )     &&
+               CHECK_SCHAR( slot->bitmap_left ) &&
+               CHECK_SCHAR( slot->bitmap_top  ) &&
+               CHECK_SCHAR( advance )           )
+          {
+            sbit->width   = (FT_Byte) bitmap->width;
+            sbit->height  = (FT_Byte) bitmap->height;
+            sbit->pitch   = (FT_SChar)bitmap->pitch;
+            sbit->left    = (FT_SChar)slot->bitmap_left;
+            sbit->top     = (FT_SChar)slot->bitmap_top;
+            sbit->advance = (FT_SChar)advance;
+
+            /* grab the bitmap when possible */
+            if ( slot->flags & ft_glyph_own_bitmap )
+            {
+              slot->flags &= ~ft_glyph_own_bitmap;
+              sbit->buffer = bitmap->buffer;
+            }
+            else
+            {
+              /* copy the bitmap into a new buffer - ignore error */
+              ftc_bitmap_copy( memory, bitmap, sbit );
+            }
+          }
+        }
+        else
+          sbit->buffer = 0;
+      }
+
+      /* ignore the errors that might have occured there      */
+      /* we recognize unloaded glyphs with "sbit.buffer == 0" */
+      error = 0;
+    }
+
+  Exit:
+    if ( error && node )
+    {
+      FREE( node->elements );
+      FREE( node );
+    }
+
+    *anode = node;
+    return error;
+  }
+
+
+  /* this function is important because it is both part of */
+  /* a FTC_ChunkSet_Class and a FTC_CacheNode_Class     */
+  /*                                                       */
+  LOCAL_FUNC_X
+  FT_ULong  ftc_sbit_chunk_node_size( FTC_SBitChunk  node )
+  {
+    FT_ULong  size  = 0;
+    FT_Glyph  glyph = node->ft_glyph;
+
+
+    switch ( glyph->format )
+    {
+    case ft_glyph_format_bitmap:
+      {
+        FT_BitmapGlyph  bitg;
+
+
+        bitg = (FT_BitmapGlyph)glyph;
+        size = bitg->bitmap.rows * labs( bitg->bitmap.pitch ) +
+               sizeof ( *bitg );
+      }
+      break;
+
+    case ft_glyph_format_outline:
+      {
+        FT_OutlineGlyph  outg;
+
+
+        outg = (FT_OutlineGlyph)glyph;
+        size = outg->outline.n_points *
+                 ( sizeof( FT_Vector ) + sizeof ( FT_Byte ) ) +
+               outg->outline.n_contours * sizeof ( FT_Short ) +
+               sizeof ( *outg );
+      }
+      break;
+
+    default:
+      ;
+    }
+
+    size += sizeof ( *node );
+    return size;
+  }
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*****                                                               *****/
+  /*****                    GLYPH IMAGE QUEUES                         *****/
+  /*****                                                               *****/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  LOCAL_FUNC_X
+  FT_Error  ftc_image_set_init( FTC_ImageSet     iset,
+                                FTC_Image_Desc*  type )
+  {
+    iset->description = *type;
+    return 0;
+  }
+
+
+  LOCAL_FUNC_X
+  FT_Bool  ftc_image_set_compare( FTC_ImageSet     iset,
+                                  FTC_Image_Desc*  type )
+  {
+    return !memcmp( &iset->description, type, sizeof ( *type ) );
+  }
+
+
+  FT_CPLUSPLUS( const FTC_ChunkSet_Class )  ftc_sbit_chunk_set_class =
+  {
+    sizeof( FTC_ImageSetRec ),
+
+    (FTC_ChunkSet_InitFunc)       ftc_image_set_init,
+    (FTC_ChunkSet_DoneFunc)       0,
+    (FTC_ChunkSet_CompareFunc)    ftc_image_set_compare,
+
+    (FTC_ChunkSet_NewNodeFunc)    ftc_sbit_chunk_node_new,
+    (FTC_ChunkSet_SizeNodeFunc)   ftc_sbit_chunk_node_size,
+    (FTC_ChunkSet_DestroyNodeFunc)ftc_sbit_chunk_node_destroy
+  };
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*****                                                               *****/
+  /*****                    GLYPH IMAGE CACHE                          *****/
+  /*****                                                               *****/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  FT_CPLUSPLUS( const FTC_Glyph_Cache_Class )  ftc_sbit_chunk_cache_class =
+  {
+    {
+      sizeof( FTC_Image_CacheRec ),
+      (FTC_Cache_InitFunc) FTC_Glyph_Cache_Init,
+      (FTC_Cache_DoneFunc) FTC_Glyph_Cache_Done
+    },
+    (FTC_ChunkSet_Class*) &ftc_sbit_chunk_set_class
+  };
+
+
+  FT_EXPORT_FUNC( FT_Error )  FTC_Image_Cache_New( FTC_Manager       manager,
+                                                   FTC_Image_Cache*  acache )
+  {
+    return FTC_Manager_Register_Cache(
+              manager,
+              (FTC_Cache_Class*)&ftc_sbit_chunk_cache_class,
+              (FTC_Cache*)acache );
+  }
+
+
+  FT_EXPORT_DEF( FT_Error )
+  FTC_Image_Cache_Lookup( FTC_Image_Cache  cache,
+                          FTC_Image_Desc*  desc,
+                          FT_UInt          gindex,
+                          FT_Glyph*        aglyph )
+  {
+    FT_Error       error;
+    FTC_ChunkSet   gset;
+    FTC_GlyphNode  node;
+    FTC_Manager    manager;
+
+    FTC_ImageSet   img_set;
+
+
+    /* check for valid `desc' delayed to FT_Lru_Lookup() */
+
+    if ( !cache || !aglyph )
+      return FT_Err_Invalid_Argument;
+
+    *aglyph  = 0;
+    gset     = cache->root.last_gset;
+    img_set  = (FTC_ImageSet)gset;
+    if ( !gset || memcmp( &img_set->description, desc, sizeof ( *desc ) ) )
+    {
+      error = FT_Lru_Lookup( cache->root.gsets_lru,
+                             (FT_LruKey)desc,
+                             (FT_Pointer*)&gset );
+      cache->root.last_gset = gset;
+      if ( error )
+        goto Exit;
+    }
+
+    error = FTC_ChunkSet_Lookup_Node( gset, gindex, &node );
+    if ( error )
+      goto Exit;
+
+    /* now compress the manager's cache pool if needed */
+    manager = cache->root.root.manager;
+    if ( manager->num_bytes > manager->max_bytes )
+    {
+      FTC_GlyphNode_Ref   ( node );
+      FTC_Manager_Compress( manager );
+      FTC_GlyphNode_Unref ( node );
+    }
+
+    *aglyph = ((FTC_SBitChunk)node)->ft_glyph;
+
+  Exit:
+    return error;
+  }
+
--- /dev/null
+++ b/src/cache/ftcsbits.h
@@ -1,0 +1,97 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftcsbits.h                                                             */
+/*                                                                         */
+/*    a small-bitmaps cache (specification).                               */
+/*                                                                         */
+/*  Copyright 2000 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 FTCSBITS_H
+#define FTCSBITS_H
+
+#include <freetype/cache/ftcchunk.h> 
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+ /* handle to small bitmap */
+  typedef struct FTC_SBitRec_*   FTC_SBit;
+
+
+ /* handle to small bitmap cache */
+  typedef struct FTC_SBit_CacheRec_*   FTC_SBit_Cache;
+
+
+ /* format of small bitmaps */  
+  typedef enum FTC_SBit_Format_
+  {
+    ftc_sbit_format_mono  = 0,
+    ftc_sbit_format_aa256 = 1,
+
+  } FTC_SBit_Format;
+
+
+ /* a compact structure used to hold a single small bitmap */  
+  typedef struct FTC_SBitRec_
+  {
+    FT_Byte   width;
+    FT_Byte   height;
+    FT_SChar  left;
+    FT_SChar  top;
+
+    FT_Byte   format;
+    FT_SChar  pitch;
+    FT_SChar  xadvance;
+    FT_SChar  yadvance;
+
+    FT_Byte*  buffer;
+  
+  } FTC_SBitRec;
+
+
+  typedef struct FTC_SBitSetRec_
+  {
+    FTC_ChunkSetRec   root;
+    FTC_Image_Desc    desc;
+
+  } FTC_SBitSet;
+
+
+  typedef struct FTC_SBit_CacheRec_
+  {
+    FTC_Chunk_CacheRec    root;
+    
+  } FTC_SBit_CacheRec;
+
+
+
+  FT_EXPORT_DEF( FT_Error )
+  FTC_SBit_Cache_New( FTC_Manager      manager,
+                      FTC_SBit_Cache  *acache );
+
+
+  FT_EXPORT_DEF( FT_Error )
+  FTC_SBit_Cache_Lookup( FTC_SBit_Cache   cache,
+                         FTC_Image_Desc*  desc,
+                         FTC_SBit        *sbit );
+
+
+#ifdef __cplusplus
+  }
+#endif
+
+
+#endif /* FTCSBITS_H */
+
+/* END */
+