shithub: freetype+ttf2subf

Download patch

ref: 10937304475b6b2737d3aa0571a23ead083da7cb
parent: ad6eaed6765180842f424c4eb73ed731cc6b5c5f
author: David Turner <[email protected]>
date: Wed May 1 04:46:56 EDT 2002

* include/freetype/internal/fthash.h, src/base/fthash.c:
          adding a generic implementation of dynamic hash tables using
          linear algorithm (to get rid of 'stalls' during resizes). This
          will be used in the future in at least three parts of the
          library: the cache sub-system, the object sub-system and
          the memory debugger.

        * include/freetype/internal/ftcore.h: added this header file to
          group all new definitions related to exception handling and
          memory management. It's very likely that this file will disappear
          or be renamed in the future..

        * include/freetype/internal/ftobject.h, include/freetype/ftsysmem.h:
          adding comments to better explain the object sub-system as well
          as the new memory manager interface.

git/fs: mount .git/fs: mount/attach disallowed
--- a/ChangeLog
+++ b/ChangeLog
@@ -7,6 +7,35 @@
         * src/sfnt/ttload.c (TT_Load_Names): applied a small work-around to
           manage fonts containing a broken name table (e.g. "hya6gb.ttf")
 
+        * src/sfnt/ttcmap0.c (tt_cmap4_validate):
+          fixed over-restrictive validation test. the charmap validator
+          now accepts overlapping ranges in format 4 charmaps.
+
+        * src/sfnt/ttcmap0.c (tt_cmap4_char_index):
+          switched to a binary search algorithm. Certain fonts contain
+          more than 170 distinct segments !!
+
+        * include/freetype/config/ftstdlib.h: adding an alias for the
+          'exit' function. This will be used in the near future to panic
+          in case of un-expected exception (which shouldn't happen in
+          theory, but as everyone knows, shit happens :-) )
+
+        * include/freetype/internal/fthash.h, src/base/fthash.c:
+          adding a generic implementation of dynamic hash tables using
+          linear algorithm (to get rid of 'stalls' during resizes). This
+          will be used in the future in at least three parts of the
+          library: the cache sub-system, the object sub-system and
+          the memory debugger.
+
+        * include/freetype/internal/ftcore.h: added this header file to
+          group all new definitions related to exception handling and
+          memory management. It's very likely that this file will disappear
+          or be renamed in the future..
+
+        * include/freetype/internal/ftobject.h, include/freetype/ftsysmem.h:
+          adding comments to better explain the object sub-system as well
+          as the new memory manager interface.
+
 2002-04-30  Wenlin Institute (Tom Bishop) <[email protected]>
 
 	* src/base/ftmac.c (p2c_str): Removed.
--- a/include/freetype/ftsysio.h
+++ b/include/freetype/ftsysio.h
@@ -1,42 +1,146 @@
 #ifndef __FT_SYSTEM_IO_H__
 #define __FT_SYSTEM_IO_H__
 
+ /********************************************************************
+  *
+  *  designing custom streams is a bit different now
+  *
+  *
+  *
+  *
+  *
+  *
+  *
+  *
+  *
+  *
+  *
+  *
+  *
+  *
+  *
+  *
+  *
+  *
+  *
+  *
+  *
+  *
+  *
+  *
+  */
+
 #include <ft2build.h>
 #include FT_INTERNAL_OBJECT_H
 
 FT_BEGIN_HEADER
 
- /* handle to a FT_Stream object */
+ /********************************************************************
+  *
+  * @type: FT_Stream
+  *
+  * @description:
+  *   handle to an input stream object. These are also @FT_Object handles
+  */
   typedef struct FT_StreamRec_*    FT_Stream;
 
- /* handle to the FT_Stream class */
+
+ /********************************************************************
+  *
+  * @type: FT_Stream_Class
+  *
+  * @description:
+  *   opaque handle to a @FT_Stream_ClassRec class structure describing
+  *   the methods of input streams
+  */
   typedef const struct FT_Stream_ClassRec_*   FT_Stream_Class;
 
- /* a method used to read data from a stream into a buffer */
+
+ /********************************************************************
+  *
+  * @functype: FT_Stream_ReadFunc
+  *
+  * @description:
+  *   a method used to read bytes from an input stream into memory
+  *
+  * @input:
+  *   stream  :: target stream handle
+  *   buffer  :: target buffer address
+  *   size    :: number of bytes to read
+  *
+  * @return:
+  *   number of bytes effectively read. Must be <= 'size'.
+  */
   typedef FT_ULong  (*FT_Stream_ReadFunc)( FT_Stream   stream,
                                            FT_Byte*    buffer,
                                            FT_ULong    size );
 
- /* a method used to seek to a new position within a stream */
- /* position is always relative to the start                */
+
+ /********************************************************************
+  *
+  * @functype: FT_Stream_SeekFunc
+  *
+  * @description:
+  *   a method used to seek to a new position within a stream
+  *
+  * @input:
+  *   stream  :: target stream handle
+  *   pos     :: new read position, from start of stream
+  *
+  * @return:
+  *   error code. 0 means success
+  */
   typedef FT_Error  (*FT_Stream_SeekFunc)( FT_Stream   stream,
                                            FT_ULong    pos );
 
- /* the stream class structure + some useful macros */
+ /********************************************************************
+  *
+  * @struct: FT_Stream_ClassRec
+  *
+  * @description:
+  *   a structure used to describe an input stream class
+  *
+  * @input:
+  *   clazz       :: root @FT_ClassRec fields
+  *   stream_read :: stream byte read method
+  *   stream_seek :: stream seek method
+  */
   typedef struct FT_Stream_ClassRec_
   {
     FT_ClassRec          clazz;
     FT_Stream_ReadFunc   stream_read;
     FT_Stream_SeekFunc   stream_seek;
-    
+
   } FT_Stream_ClassRec;
 
-#define  FT_STREAM_CLASS(x)        ((FT_Stream_Class)(x))
+ /* */
 
+#define  FT_STREAM_CLASS(x)        ((FT_Stream_Class)(x))
 #define  FT_STREAM_CLASS__READ(x)  FT_STREAM_CLASS(x)->stream_read
 #define  FT_STREAM_CLASS__SEEK(x)  FT_STREAM_CLASS(x)->stream_seek;
 
- /* the base FT_Stream object structure */
+ /********************************************************************
+  *
+  * @struct: FT_StreamRec
+  *
+  * @description:
+  *   the input stream object structure. See @FT_Stream_ClassRec for
+  *   its class descriptor
+  *
+  * @fields:
+  *   object      :: root @FT_ObjectRec fields
+  *   size        :: size of stream in bytes (0 if unknown)
+  *   pos         :: current position within stream
+  *   base        :: for memory-based streams, the address of the stream's
+  *                  first data byte in memory. NULL otherwise
+  *
+  *   cursor      :: the current cursor position within an input stream
+  *                  frame. Only valid within a FT_FRAME_ENTER .. FT_FRAME_EXIT
+  *                  block; NULL otherwise
+  *
+  *   limit       :: the current frame limit within a FT_FRAME_ENTER ..
+  *                  FT_FRAME_EXIT block. NULL otherwise
+  */
   typedef struct FT_StreamRec_
   {
     FT_ObjectRec        object;
@@ -57,12 +161,23 @@
 
 #define  FT_STREAM_IS_BASED(x)  ( FT_STREAM(x)->base != NULL )
 
+ /* */
 
+ /* create new memory-based stream */
+  FT_BASE( FT_Error )   ft_stream_new_memory( const FT_Byte*  stream_base,
+                                              FT_ULong        stream_size,
+                                              FT_Memory       memory,
+                                              FT_Stream      *astream );
 
-#if 0
-#endif
+  FT_BASE( FT_Error )   ft_stream_new_iso( const char*  pathanme,
+                                           FT_Memory    memory,
+                                           FT_Stream   *astream );
 
- /* */
+
+ /* handle to default stream class implementation for a given build */
+ /* this is used by "FT_New_Face"                                   */
+ /*                                                                 */
+  FT_APIVAR( FT_Type )   ft_stream_default_type;
 
 FT_END_HEADER
 
--- a/include/freetype/ftsysmem.h
+++ b/include/freetype/ftsysmem.h
@@ -5,35 +5,131 @@
 
 FT_BEGIN_HEADER
 
- /* handle to memory structure */
+ /***********************************************************************
+  *
+  * @type: FT_Memory
+  *
+  * @description:
+  *   opaque handle to a memory manager handle. Note that since FreeType
+  *   2.2, the memory manager structure FT_MemoryRec is hidden to client
+  *   applications.
+  *
+  *   however, you can still define custom allocators easily using the
+  *   @ft_memory_new API
+  */
   typedef struct FT_MemoryRec_*   FT_Memory;
 
- /* a function used to allocate a new block of memory from a heap */
+
+ /***********************************************************************
+  *
+  * @functype: FT_Memory_AllocFunc
+  *
+  * @description:
+  *   a function used to allocate a block of memory.
+  *
+  * @input:
+  *   size     :: size of blocks in bytes. Always > 0 !!
+  *   mem_data :: memory-manager specific optional argument
+  *               (see @ft_memory_new)
+  *
+  * @return:
+  *   address of new block. NULL in case of memory exhaustion
+  */
   typedef FT_Pointer  (*FT_Memory_AllocFunc)( FT_ULong   size,
-                                              FT_Memory  memory );
-  
- /* a function used to free a block of memory */
+                                              FT_Pointer mem_data );
+
+
+ /***********************************************************************
+  *
+  * @functype: FT_Memory_FreeFunc
+  *
+  * @description:
+  *   a function used to release a block of memory created through
+  *   @FT_Memory_AllocFunc or @FT_Memory_ReallocFunc
+  *
+  * @input:
+  *   block    :: address of target memory block. cannot be NULL !!
+  *   mem_data :: memory-manager specific optional argument
+  *               (see @ft_memory_new)
+  */
   typedef void        (*FT_Memory_FreeFunc) ( FT_Pointer  block,
-                                              FT_Memory   memory );
-  
- /* a function used to reallocate a given memory block to a new size */
+                                              FT_Pointer  mem_data );
+
+
+ /***********************************************************************
+  *
+  * @functype: FT_Memory_ReallocFunc
+  *
+  * @description:
+  *   a function used to reallocate a memory block.
+  *
+  * @input:
+  *   block    :: address of target memory block. cannot be NULL !!
+  *   new_size :: new requested size in bytes
+  *   cur_size :: current block size in bytes
+  *   mem_data :: memory-manager specific optional argument
+  *               (see @ft_memory_new)
+  */
   typedef FT_Pointer  (*FT_Memory_ReallocFunc)( FT_Pointer   block,
                                                 FT_ULong     new_size,
                                                 FT_ULong     cur_size,
-                                                FT_Memory    memory );
+                                                FT_Pointer   mem_data );
 
- /* a function called to allocate a new structure of 'size' bytes that */
- /* will be used for a new FT_Memory object..                          */
- /*                                                                    */
+
+ /***********************************************************************
+  *
+  * @functype: FT_Memory_CreateFunc
+  *
+  * @description:
+  *   a function used to create a @FT_Memory object to model a
+  *   memory manager
+  *
+  * @input:
+  *   size      :: size of memory manager structure in bytes
+  *   init_data :: optional initialisation argument
+  *
+  * @output:
+  *   amem_data :: memory-manager specific argument to block management
+  *                routines.
+  *
+  * @return:
+  *   handle to new memory manager object. NULL in case of failure
+  */
   typedef FT_Pointer  (*FT_Memory_CreateFunc)( FT_UInt     size,
-                                               FT_Pointer  init_data );
+                                               FT_Pointer  init_data,
+                                               FT_Pointer *amem_data );
 
- /* a function used to destroy a FT_Memory object */  
-  typedef void        (*FT_Memory_DestroyFunc)( FT_Memory  memory );
 
- /* a structure holding the functions used to describe a given FT_Memory */
- /* implementation..                                                     */
- /*                                                                      */
+ /***********************************************************************
+  *
+  * @functype: FT_Memory_DestroyFunc
+  *
+  * @description:
+  *   a function used to destroy a given @FT_Memory manager
+  *
+  * @input:
+  *   memory   :: target memory manager handle
+  *   mem_data :: option manager-specific argument
+  */
+  typedef void        (*FT_Memory_DestroyFunc)( FT_Memory  memory,
+                                                FT_Pointer mem_data );
+
+
+ /***********************************************************************
+  *
+  * @struct: FT_Memory_FuncsRec
+  *
+  * @description:
+  *   a function used to hold all methods of a given memory manager
+  *   implementation.
+  *
+  * @fields:
+  *   mem_alloc   :: block allocation routine
+  *   mem_free    :: block release routine
+  *   mem_realloc :: block re-allocation routine
+  *   mem_create  :: manager creation routine
+  *   mem_destroy :: manager destruction routine
+  */
   typedef struct FT_Memory_FuncsRec_
   {
     FT_Memory_AllocFunc     mem_alloc;
@@ -41,24 +137,53 @@
     FT_Memory_ReallocFunc   mem_realloc;
     FT_Memory_CreateFunc    mem_create;
     FT_Memory_DestroyFunc   mem_destroy;
-  
+
   } FT_Memory_FuncsRec, *FT_Memory_Funcs;
 
 
- /* a function used to create a new custom FT_Memory object */
- /*                                                         */
-  FT_BASE_DEF( FT_Memory )
+ /***********************************************************************
+  *
+  * @type: FT_Memory_Funcs
+  *
+  * @description:
+  *   a pointer to a constant @FT_Memory_FuncsRec structure used to
+  *   describe a given memory manager implementation.
+  */
+  typedef const FT_Memory_FuncsRec*  FT_Memory_Funcs;
+
+
+ /***********************************************************************
+  *
+  * @function: ft_memory_new
+  *
+  * @description:
+  *   create a new memory manager, given a set of memory methods
+  *
+  * @input:
+  *   mem_funcs     :: handle to memory manager implementation descriptor
+  *   mem_init_data :: optional initialisation argument, passed to
+  *                    @FT_Memory_CreateFunc
+  *
+  * @return:
+  *   new memory manager handle. NULL in case of failure
+  */
+  FT_BASE( FT_Memory )
   ft_memory_new( FT_Memory_Funcs  mem_funcs,
                  FT_Pointer       mem_init_data );
 
- /* a function used to destroy a custom FT_Memory object */
-  FT_BASE_DEF( void )
-  ft_memory_destroy( FT_Memory  memory );
 
- /* a pointer to the default memory functions used by FreeType in a */
- /* given build. By default, uses the ISO C malloc/free/realloc     */
- /*                                                                 */
-  FT_APIVAR( const FT_MemoryFuncs )    ft_memory_funcs_default;
+ /***********************************************************************
+  *
+  * @function: ft_memory_destroy
+  *
+  * @description:
+  *   destroy a given memory manager
+  *
+  * @input:
+  *   memory :: handle to target memory manager
+  */
+  FT_BASE( void )
+  ft_memory_destroy( FT_Memory  memory );
 
 /* */
 
--- /dev/null
+++ b/include/freetype/internal/ftcore.h
@@ -1,0 +1,185 @@
+#ifndef __FT_CORE_H__
+#define __FT_CORE_H__
+
+#include <ft2build.h>
+#include FT_TYPES_H
+#include FT_SYSTEM_MEMORY_H
+
+FT_BEGIN_HEADER
+
+ /**************************************************************************/
+ /**************************************************************************/
+ /*****                                                                *****/
+ /*****                  C L E A N U P   S T A C K                     *****/
+ /*****                                                                *****/
+ /**************************************************************************/
+ /**************************************************************************/
+
+
+ /************************************************************************
+  *
+  * @functype: FT_CleanupFunc
+  *
+  * @description:
+  *   a function used to cleanup a given item on the cleanup stack
+  *
+  * @input:
+  *   item      :: target item pointer
+  *   item_data :: optional argument to cleanup routine
+  */
+  typedef void  (*FT_CleanupFunc)( FT_Pointer  item,
+                                   FT_Pointer  item_data );
+
+
+
+ /************************************************************************
+  *
+  * @type: FT_XHandler
+  *
+  * @description:
+  *   handle to an exception-handler structure for the FreeType
+  *   exception sub-system
+  *
+  * @note:
+  *   exception handlers are allocated on the stack within a
+  *   @FT_XTRY macro. Do not try to access them directly.
+  */
+  typedef struct FT_XHandlerRec_*  FT_XHandler;
+
+
+/* the size of a cleanup chunk in bytes is FT_CLEANUP_CHUNK_SIZE*12 + 4 */
+/* this must be a small power of 2 whenever possible..                  */
+/*                                                                      */
+/* with a value of 5, we have a byte size of 64 bytes per chunk..       */
+/*                                                                      */
+#define  FT_CLEANUP_CHUNK_SIZE   5
+
+
+
+  typedef struct FT_CleanupItemRec_
+  {
+    FT_Pointer      item;
+    FT_CleanupFunc  item_func;
+    FT_Pointer      item_data;
+
+  } FT_CleanupItemRec;
+
+
+  typedef struct FT_CleanupChunkRec_*   FT_CleanupChunk;
+
+  typedef struct FT_CleanupChunkRec_
+  {
+    FT_CleanupChunk    link;
+    FT_CleanupItemRec  items[ FT_CLEANUP_CHUNK_SIZE ];
+
+  } FT_CleanupChunkRec;
+
+
+  typedef struct FT_CleanupStackRec_
+  {
+    FT_CleanupItem     top;
+    FT_CleanupItem     limit;
+    FT_CleanupChunk    chunk;
+    FT_CleanupChunkRec chunk_0;  /* avoids stupid dynamic allocation */
+    FT_Memory          memory;
+
+  } FT_CleanupStackRec, *FT_CleanupStack;
+
+
+  FT_BASE( void )
+  ft_cleanup_stack_push( FT_CleanupStack  stack,
+                         FT_Pointer       item,
+                         FT_CleanupFunc   item_func,
+                         FT_Pointer       item_data );
+
+  FT_BASE( void )
+  ft_cleanup_stack_pop( FT_CleanupStack   stack,
+                        FT_Int            destroy );
+
+  FT_BASE( FT_CleanupItem )
+  ft_cleanup_stack_peek( FT_CleanupStack  stack );
+
+  FT_BASE( void )
+  ft_cleanup_throw( FT_CleanupStack  stack,
+                    FT_Error         error );
+
+
+
+ /**************************************************************************/
+ /**************************************************************************/
+ /*****                                                                *****/
+ /*****                 M E M O R Y   M A N A G E R                    *****/
+ /*****                                                                *****/
+ /**************************************************************************/
+ /**************************************************************************/
+
+  typedef struct FT_MemoryRec_
+  {
+    FT_Memory_AllocFunc     mem_alloc;   /* shortcut to funcs->mem_alloc */
+    FT_Memory_FreeFunc      mem_free;    /* shortcut to funcs->mem_free  */
+    FT_Pointer              mem_data;
+    const FT_Memory_Funcs   mem_funcs;
+
+    FT_CleanupStackRec      cleanup_stack;
+    FT_Pointer              meta_class;
+
+  } FT_MemoryRec;
+
+
+#define  FT_MEMORY(x)  ((FT_Memory)(x))
+#define  FT_MEMORY__ALLOC(x)       FT_MEMORY(x)->mem_alloc
+#define  FT_MEMORY__FREE(x)        FT_MEMORY(x)->mem_free
+#define  FT_MEMORY__REALLOC(x)     FT_MEMORY(x)->mem_funcs->mem_realloc
+#define  FT_MEMORY__CLEANUP(x)     (&FT_MEMORY(x)->cleanup_stack)
+#define  FT_MEMORY__META_CLASS(x)  ((FT_MetaClass)(FT_MEMORY(x)->meta_class))
+
+
+ /**************************************************************************/
+ /**************************************************************************/
+ /*****                                                                *****/
+ /*****             E X C E P T I O N   H A N D L I N G                *****/
+ /*****                                                                *****/
+ /**************************************************************************/
+ /**************************************************************************/
+
+
+ /************************************************************************
+  *
+  * @struct: FT_XHandlerRec
+  *
+  * @description:
+  *   exception handler structure
+  *
+  * @fields:
+  *   previous   :: previous handler in chain.
+  *   jum_buffer :: processor state used by setjmp/longjmp to implement
+  *                 exception control transfer
+  *   error      :: exception error code
+  *   mark       :: top of cleanup stack when @FT_XTRY is used
+  */
+  typedef struct FT_XHandlerRec_
+  {
+    FT_XHandler        previous;
+    ft_jmp_buf         jump_buffer;
+    volatile FT_Error  error;
+    FT_Pointer         mark;
+
+  } FT_XHandlerRec;
+
+  FT_BASE( void )
+  ft_xhandler_enter( FT_XHandler  xhandler,
+                     FT_Memory    memory );
+
+  FT_BASE( void )
+  ft_xhandler_exit( FT_XHandler  xhandler );
+
+
+
+
+
+
+
+
+FT_END_HEADER
+
+#endif /* __FT_CORE_H__ */
--- a/include/freetype/internal/ftexcept.h
+++ b/include/freetype/internal/ftexcept.h
@@ -6,21 +6,12 @@
 
 FT_BEGIN_HEADER
 
-  typedef struct FT_XHandlerRec_*  FT_XHandler;
-  
-  typedef struct FT_XHandlerRec_
-  {
-    FT_XHandler        previous;
-    ft_jmp_buf         jump_buffer;
-    volatile FT_Error  error;
-    FT_Pointer         cleanup;
-  
-  } FT_XHandlerRec;
 
 
-  typedef void  (*FT_CleanupFunc)( FT_Pointer  item,
-                                   FT_Pointer  item_data );
+ /* I can't find a better place for this for now */
 
+<<<<<<< ftexcept.h
+=======
 
 /* the size of a cleanup chunk in bytes is FT_CLEANUP_CHUNK_SIZE*12 + 4 */
 /* this must be a small power of 2 whenever possible..                  */
@@ -85,6 +76,7 @@
   ft_cleanup_throw( FT_CleanupStack  stack,
                     FT_Error         error );
 
+>>>>>>> 1.2
 FT_END_HEADER
 
 #endif /* __FT_EXCEPT_H__ */
--- /dev/null
+++ b/include/freetype/internal/fthash.h
@@ -1,0 +1,484 @@
+/******************************************************************
+ *
+ *  fthash.h  - fast dynamic hash tables
+ *
+ *  Copyright 2002 by
+ *  David Turner, Robert Wilhelm, and Werner Lemberg
+ *
+ *  This file is part of the FreeType project, and may only be used,
+ *  modified, and distributed under the terms of the FreeType project
+ *  license, LICENSE.TXT.  By continuing to use, modify, or distribute
+ *  this file you indicate that you have read the license and
+ *  understand and accept it fully.
+ *
+ *
+ *  This header is used to define dynamic hash tables as described
+ *  by the article "Main-Memory Linear Hashing - Some Enhancements
+ *  of Larson's Algorithm" by Mikael Petterson.
+ *
+ *  Basically, linear hashing prevents big "stalls" during
+ *  resizes of the buckets array by only splitting one bucket
+ *  at a time. This ensures excellent response time even when
+ *  the table is frequently resized..
+ *
+ *
+ *  Note that the use of the FT_Hash type is rather unusual in order
+ *  to be as generic and efficient as possible. See the comments in the
+ *  following definitions for more details.
+ */
+
+#ifndef __FT_HASH_H__
+#define __FT_HASH_H__
+
+#include <ft2build.h>
+#include FT_TYPES_H
+
+FT_BEGIN_HEADER
+
+ /***********************************************************
+  *
+  * @type: FT_Hash
+  *
+  * @description:
+  *   handle to a @FT_HashRec structure used to model a
+  *   dynamic hash table
+  */
+  typedef struct FT_HashRec_*      FT_Hash;
+
+
+ /***********************************************************
+  *
+  * @type: FT_HashNode
+  *
+  * @description:
+  *   handle to a @FT_HashNodeRec structure used to model a
+  *   single node of a hash table
+  */
+  typedef struct FT_HashNodeRec_*  FT_HashNode;
+
+
+ /***********************************************************
+  *
+  * @type: FT_Hash_CompareFunc
+  *
+  * @description:
+  *   a function used to compare two nodes of the hash table
+  *
+  * @input:
+  *   node1 :: handle to first node
+  *   node2 :: handle to second node
+  *
+  * @return:
+  *   1 iff the 'keys' in 'node1' and 'node2' are identical.
+  *   0 otherwise.
+  */
+  typedef FT_Int  (*FT_Hash_CompareFunc)( const FT_HashNode  node1,
+                                          const FT_HashNode  node2 );
+
+
+ /***********************************************************
+  *
+  * @struct: FT_HashRec
+  *
+  * @description:
+  *   a structure used to model a dynamic hash table.
+  *
+  * @fields:
+  *   memory       :: memory manager used to allocate
+  *                   the buckets array and the hash nodes
+  *
+  *   buckets      :: array of hash buckets
+  *
+  *   node_size    :: size of node in bytes
+  *   node_compare :: a function used to compare two nodes
+  *   node_hash    :: a function used to compute the hash
+  *                   value of a given node
+  *   p            ::
+  *   mask         ::
+  *   slack        ::
+  *
+  * @note:
+  *   'p', 'mask' and 'slack' are control values managed by
+  *   the hash table. Do not try to interpret them directly.
+  *
+  *   You can grab the hash table size by calling
+  *   '@ft_hash_get_size'.
+  */
+  typedef struct FT_HashRec_
+  {
+    FT_Memory            memory;
+    FT_HashNode*         buckets;
+    FT_UInt              p;
+    FT_UInt              mask;  /* really maxp-1 */
+    FT_UInt              slack;
+
+
+    FT_UInt              node_size;
+    FT_Hash_CompareFunc  node_compare;
+    FT_Hash_ComputeFunc  node_hash;
+
+  } FT_HashRec, *FT_Hash;
+
+
+ /***********************************************************
+  *
+  * @struct: FT_HashNodeRec
+  *
+  * @description:
+  *   a structure used to model the root fields of a dynamic
+  *   hash table node.
+  *
+  *   it's up to client applications to "sub-class" this
+  *   structure to add relevant (key,value) definitions
+  *
+  * @fields:
+  *   link :: pointer to next node in bucket's collision list
+  *   hash :: 32-bit hash value for this node
+  *
+  * @note:
+  *   it's up to client applications to "sub-class" this structure
+  *   to add relevant (key,value) type definitions. For example,
+  *   if we want to build a "string -> int" mapping, we could use
+  *   something like:
+  *
+  *   {
+  *     typedef struct MyNodeRec_
+  *     {
+  *       FT_HashNodeRec  hnode;
+  *       const char*     key;
+  *       int             value;
+  *
+  *     } MyNodeRec, *MyNode;
+  *   }
+  *
+  */
+  typedef struct FT_HashNodeRec_
+  {
+    FT_HashNode  link;
+    FT_UInt32    hash;
+
+  } FT_HashNodeRec;
+
+
+ /****************************************************************
+  *
+  * @function: ft_hash_init
+  *
+  * @description:
+  *   initialize a dynamic hash table
+  *
+  * @input:
+  *   table   :: handle to target hash table structure
+  *   compare :: node comparison function
+  *   memory  :: memory manager handle used to allocate the
+  *              buckets array within the hash table
+  *
+  * @note:
+  *   the node comparison function should only compare node _keys_
+  *   and ignore values !! with good hashing computation (which the
+  *   user must perform itself), the comparison function should be
+  *   pretty selfom called.
+  *
+  *   here is a simple example:
+  *
+  *   {
+  *     static int my_compare( const MyNode  node1,
+  *                            const MyNode  node2 )
+  *     {
+  *       // compare keys of 'node1' and 'node2'
+  *       return strcmp( node1->key, node2->key );
+  *     }
+  *
+  *     ....
+  *
+  *     ft_hash_init( &hash, (FT_Hash_CompareFunc) my_compare, memory );
+  *     ....
+  *   }
+  */
+  FT_BASE( void )
+  ft_hash_init( FT_Hash              table,
+                FT_Hash_CompareFunc  compare,
+                FT_Memory            memory );
+
+
+ /****************************************************************
+  *
+  * @function: ft_hash_lookup
+  *
+  * @description:
+  *   search a hash table to find a node corresponding to a given
+  *   key.
+  *
+  * @input:
+  *   table   :: handle to target hash table structure
+  *   keynode :: handle to a reference hash node that will be
+  *              only used for key comparisons with the table's
+  *              elements
+  *
+  * @return:
+  *   a pointer-to-hash-node value, which must be used as followed:
+  *
+  *   - if '*result' is NULL, the key wasn't found in the hash
+  *     table. The value of 'result' can be used to add new elements
+  *     through @ft_hash_add however..
+  *
+  *   - if '*result' is not NULL, it's a handle to the first table
+  *     node that corresponds to the search key. The value of 'result'
+  *     can be used to remove this element through @ft_hash_remove
+  *
+  * @note:
+  *   here is an example:
+  *
+  *   {
+  *     // maps a string to an integer with a hash table
+  *     // returns -1 in case of failure
+  *     //
+  *     int  my_lookup( FT_Hash      table,
+  *                     const char*  key )
+  *     {
+  *       MyNode*    pnode;
+  *       MyNodeRec  noderec;
+  *
+  *       // set-up key node. It's 'hash' and 'key' fields must
+  *       // be set correctly.. we ignore 'link' and 'value'
+  *       //
+  *       noderec.hnode.hash = strhash( key );
+  *       noderec.key        = key;
+  *
+  *       // perform search - return value
+  *       //
+  *       pnode = (MyNode) ft_hash_lookup( table, &noderec );
+  *       if ( *pnode )
+  *       {
+  *         // we found it
+  *         return (*pnode)->value;
+  *       }
+  *       return -1;
+  *     }
+  *   }
+  */
+  FT_BASE_DEF( FT_HashNode* )
+  ft_hash_lookup( FT_Hash      table,
+                  FT_HashNode  keynode )
+
+
+ /****************************************************************
+  *
+  * @function: ft_hash_add
+  *
+  * @description:
+  *   add a new node to a dynamic hash table. the user must
+  *   call @ft_hash_lookup and allocate a new node before calling
+  *   this function.
+  *
+  * @input:
+  *   table    :: hash table handle
+  *   pnode    :: pointer-to-hash-node value returned by @ft_hash_lookup
+  *   new_node :: handle to new hash node. All its fields must be correctly
+  *               set, including 'hash'.
+  *
+  * @note:
+  *   this function should always be used _after_ a call to @ft_hash_lookup
+  *   that returns a pointer to a NULL  handle. Here's an example:
+  *
+  *   {
+  *     // sets the value corresponding to a given string key
+  *     //
+  *     void  my_set( FT_Hash      table,
+  *                   const char*  key,
+  *                   int          value )
+  *     {
+  *       MyNode*    pnode;
+  *       MyNodeRec  noderec;
+  *       MyNode     node;
+  *
+  *       // set-up key node. It's 'hash' and 'key' fields must
+  *       // be set correctly..
+  *       noderec.hnode.hash = strhash( key );
+  *       noderec.key        = key;
+  *
+  *       // perform search - return value
+  *       pnode = (MyNode) ft_hash_lookup( table, &noderec );
+  *       if ( *pnode )
+  *       {
+  *         // we found it, simply replace the value in the node
+  *         (*pnode)->value = value;
+  *         return;
+  *       }
+  *
+  *       // allocate a new node - and set it up
+  *       node = (MyNode) malloc( sizeof(*node) );
+  *       node->hnode.hash = noderec.hnode.hash;
+  *       node->key        = key;
+  *       node->value      = value;
+  *
+  *       // add it to the hash table
+  *       ft_hash_add( table, pnode, node );
+  *     }
+  */
+  FT_BASE( void )
+  ft_hash_add( FT_Hash       table,
+               FT_HashNode*  pnode,
+               FT_HashNode   new_node );
+
+
+ /****************************************************************
+  *
+  * @function: ft_hash_remove
+  *
+  * @description:
+  *   try to remove the node corresponding to a given key from
+  *   a hash table. This must be called after @ft_hash_lookup
+  *
+  * @input:
+  *   table   :: hash table handle
+  *   pnode   :: pointer-to-hash-node value returned by @ft_hash_lookup
+  *
+  * @note:
+  *   this function doesn't free the node itself !! Here's an example:
+  *
+  *   {
+  *     // sets the value corresponding to a given string key
+  *     //
+  *     void  my_remove( FT_Hash      table,
+  *                      const char*  key )
+  *     {
+  *       MyNodeRec  noderec;
+  *       MyNode     node;
+  *
+  *       noderec.hnode.hash = strhash(key);
+  *       noderec.key        = key;
+  *       node               = &noderec;
+  *
+  *       pnode = ft_hash_lookup( table, &noderec );
+  *       node  = *pnode;
+  *       if ( node != NULL )
+  *       {
+  *         ft_hash_remove( table, pnode );
+  *         free( node );
+  *       }
+  *     }
+  *   }
+  */
+  FT_BASE( void )
+  ft_hash_remove( FT_Hash       table,
+                  FT_HashNode*  pnode );
+
+
+
+ /****************************************************************
+  *
+  * @function: ft_hash_get_size
+  *
+  * @description:
+  *   return the number of elements in a given hash table
+  *
+  * @input:
+  *   table   :: handle to target hash table structure
+  *
+  * @return:
+  *   number of elements. 0 if empty
+  */
+  FT_BASE( FT_UInt )
+  ft_hash_get_size( FT_Hash  table );
+
+
+
+ /****************************************************************
+  *
+  * @functype: FT_Hash_ForeachFunc
+  *
+  * @description:
+  *   a function used to iterate over all elements of a given
+  *   hash table
+  *
+  * @input:
+  *   node :: handle to target @FT_HashNodeRec node structure
+  *   data :: optional argument to iteration routine
+  *
+  * @also:  @ft_hash_foreach
+  */
+  typedef void  (*FT_Hash_ForeachFunc)( const FT_HashNode  node,
+                                        const FT_Pointer   data );
+
+
+ /****************************************************************
+  *
+  * @function: ft_hash_foreach
+  *
+  * @description:
+  *   parse over all elements in a hash table
+  *
+  * @input:
+  *   table        :: handle to target hash table structure
+  *   foreach_func :: iteration routine called for each element
+  *   foreach_data :: optional argument to the iteration routine
+  *
+  * @note:
+  *   this function is often used to release all elements from a
+  *   hash table. See the example given for @ft_hash_done
+  */
+  FT_BASE( void )
+  ft_hash_foreach( FT_Hash              table,
+                   FT_Hash_ForeachFunc  foreach_func,
+                   const FT_Pointer     foreach_data );
+
+
+
+ /****************************************************************
+  *
+  * @function: ft_hash_done
+  *
+  * @description:
+  *   finalize a given hash table
+  *
+  * @input:
+  *   table     :: handle to target hash table structure
+  *   node_func :: optional iteration function pointer. this
+  *                can be used to destroy all nodes explicitely
+  *   node_data :: optional argument to the node iterator
+  *
+  * @note:
+  *   this function simply frees the hash table's buckets.
+  *   you probably will need to call @ft_hash_foreach to
+  *   destroy all its elements before @ft_hash_done, as in
+  *   the following example:
+  *
+  *   {
+  *     static void  my_node_clear( const MyNode  node )
+  *     {
+  *       free( node );
+  *     }
+  *
+  *     static void  my_done( FT_Hash  table )
+  *     {
+  *       ft_hash_done( table, (FT_Hash_ForeachFunc) my_node_clear, NULL );
+  *     }
+  *   }
+  */
+  FT_BASE( void )
+  ft_hash_done( FT_Hash              table,
+                FT_Hash_ForeachFunc  item_func,
+                const FT_Pointer     item_data );
+
+ /* */
+
+ /* compute bucket index from hash value in a dynamic hash table */
+ /* this is only used to break encapsulation to speed lookups in */
+ /* the FreeType cache manager !!                                */
+ /*                                                              */
+
+#define  FT_HASH_COMPUTE_INDEX(_table,_hash,_index)                  \
+             {                                                       \
+               FT_UInt  _mask  = (_table)->mask;                     \
+               FT_UInt  _hash0 = (_hash);                            \
+                                                                     \
+               (_index) = (FT_UInt)( (_hash0) & _mask ) );           \
+               if ( (_index) < (_table)->p )                         \
+                 (_index) = (FT_uInt)( (_hash0) & ( 2*_mask+1 ) );   \
+             }
+
+
+FT_END_HEADER
+
+#endif /* __FT_HASH_H__ */
--- a/include/freetype/internal/ftobject.h
+++ b/include/freetype/internal/ftobject.h
@@ -6,35 +6,189 @@
 
 FT_BEGIN_HEADER
 
+ /**************************************************************
+  *
+  * @type: FT_Object
+  *
+  * @description:
+  *   handle to a FreeType Object. See @FT_ObjectRec
+  */
   typedef struct FT_ObjectRec_*        FT_Object;
-  
+
+
+ /**************************************************************
+  *
+  * @type: FT_Class
+  *
+  * @description:
+  *   handle to a constant class handle to a FreeType Object.
+  *
+  *   Note that a class is itself a @FT_Object and are dynamically
+  *   allocated on the heap.
+  *
+  * @also:
+  *  @FT_ClassRec, @FT_Object, @FT_ObjectRec, @FT_Type, @FT_TypeRec
+  */
   typedef const struct FT_ClassRec_*   FT_Class;
-  
+
+
+ /**************************************************************
+  *
+  * @type: FT_Type
+  *
+  * @description:
+  *   handle to a constant structure (of type @FT_TypeRec) used
+  *   to describe a given @FT_Class type to the FreeType object
+  *   sub-system.
+  */
   typedef const struct FT_TypeRec_*    FT_Type;
 
+
+
+ /**************************************************************
+  *
+  * @struct: FT_ObjectRec
+  *
+  * @description:
+  *   a structure describing the root fields of all @FT_Object
+  *   class instances in FreeType
+  *
+  * @fields:
+  *   clazz     :: handle to the object's class
+  *   ref_count :: object's reference count. Starts at 1
+  */
   typedef struct FT_ObjectRec_
   {
     FT_Class  clazz;
     FT_Int    ref_count;
-    
+
   } FT_ObjectRec;
 
+
+ /**************************************************************
+  *
+  * @macro: FT_OBJECT (x)
+  *
+  * @description:
+  *   a useful macro to type-cast anything to a @FT_Object
+  *   handle. No check performed..
+  */
 #define  FT_OBJECT(x)    ((FT_Object)(x))
+
+
+ /**************************************************************
+  *
+  * @macro: FT_OBJECT_P (x)
+  *
+  * @description:
+  *   a useful macro to type-cast anything to a pointer to
+  *   @FT_Object handle.
+  */
 #define  FT_OBJECT_P(x)  ((FT_Object*)(x))
 
+
+ /**************************************************************
+  *
+  * @macro: FT_OBJECT__CLASS (obj)
+  *
+  * @description:
+  *   a useful macro to return the class of any object
+  */
 #define  FT_OBJECT__CLASS(x)      FT_OBJECT(x)->clazz
+
+
+ /**************************************************************
+  *
+  * @macro: FT_OBJECT__REF_COUNT (obj)
+  *
+  * @description:
+  *   a useful macro to return the reference count of any object
+  */
 #define  FT_OBJECT__REF_COUNT(x)  FT_OBJECT(x)->ref_count
+
+
+ /**************************************************************
+  *
+  * @macro: FT_OBJECT__MEMORY (obj)
+  *
+  * @description:
+  *   a useful macro to return a handle to the memory manager
+  *   used to allocate a given object
+  */
 #define  FT_OBJECT__MEMORY(x)     FT_CLASS__MEMORY(FT_OBJECT(x)->clazz)
+
+
+ /**************************************************************
+  *
+  * @macro: FT_OBJECT__LIBRARY (obj)
+  *
+  * @description:
+  *   a useful macro to return a handle to the library handle
+  *   that owns the object
+  */
 #define  FT_OBJECT__LIBRARY(x)    FT_CLASS__LIBRARY(FT_OBJECT(x)->clazz)
 
+
+ /**************************************************************
+  *
+  * @functype: FT_Object_InitFunc
+  *
+  * @description:
+  *   a function used to initialize a new object
+  *
+  * @input:
+  *   object    :: target object handle
+  *   init_data :: optional pointer to initialization data
+  *
+  * @throws: any
+  *
+  *   the object is _assumed_ to be reachable from the cleanup
+  *   stack when the constructor is called. This means that
+  *   any exception can be thrown safely in it.
+  */
   typedef void  (*FT_Object_InitFunc)( FT_Object   object,
                                        FT_Pointer  init_data );
 
+ /**************************************************************
+  *
+  * @functype: FT_Object_DoneFunc
+  *
+  * @description:
+  *   a function used to finalize a given object
+  *
+  * @input:
+  *   object    :: handle to target object
+  *
+  * @throws: *never* !!
+  */
   typedef void  (*FT_Object_DoneFunc)( FT_Object   object );
 
-  typedef void  (*FT_Object_CopyFunc)( FT_Object   target,
-                                       FT_Object   source );
 
+ /**************************************************************
+  *
+  * @struct: FT_ClassRec
+  *
+  * @description:
+  *   a structure used to describe a given object class within
+  *   FreeType
+  *
+  * @fields:
+  *   object   :: root @FT_ObjectRec fields, since each class is
+  *               itself an object. (it's an instance of the
+  *               "metaclass", a special object of the FreeType
+  *               object sub-system.)
+  *
+  *   magic    :: a 32-bit magic number used for decoding
+  *   type     :: the @FT_Type descriptor of this class
+  *   memory   :: the current memory manager handle
+  *   library  :: the current library handle
+  *   info     :: an opaque pointer to class-specific information
+  *               managed by the FreeType object sub-system
+  *
+  *   obj_size :: size of class instances in bytes
+  *   obj_init :: class instance constructor
+  *   obj_done :: class instance destructor
+  */
   typedef struct FT_ClassRec_
   {
     FT_ObjectRec        object;
@@ -43,58 +197,245 @@
     FT_Memory           memory;
     FT_Library          library;
     FT_Pointer          info;
-    FT_Pointer          data;    
 
     FT_UInt             obj_size;
     FT_Object_InitFunc  obj_init;
     FT_Object_DoneFunc  obj_done;
-    FT_Object_CopyFunc  obj_copy;
-  
+
   } FT_ClassRec;
 
+
+ /**************************************************************
+  *
+  * @macro: FT_CLASS (x)
+  *
+  * @description:
+  *   a useful macro to convert anything to a class handle
+  *   without checks
+  */
 #define  FT_CLASS(x)    ((FT_Class)(x))
+
+
+ /**************************************************************
+  *
+  * @macro: FT_CLASS_P (x)
+  *
+  * @description:
+  *   a useful macro to convert anything to a pointer to a class
+  *   handle without checks
+  */
 #define  FT_CLASS_P(x)  ((FT_Class*)(x))
 
+
+ /**************************************************************
+  *
+  * @macro: FT_CLASS__MEMORY (clazz)
+  *
+  * @description:
+  *   a useful macro to return the memory manager handle of a
+  *   given class
+  */
 #define  FT_CLASS__MEMORY(x)   FT_CLASS(x)->memory
+
+
+ /**************************************************************
+  *
+  * @macro: FT_CLASS__LIBRARY (clazz)
+  *
+  * @description:
+  *   a useful macro to return the library handle of a
+  *   given class
+  */
 #define  FT_CLASS__LIBRARY(x)  FT_CLASS(x)->library
-#define  FT_CLASS__MAGIC(x)    FT_CLASS(x)->magic
+
+
+
+ /**************************************************************
+  *
+  * @macro: FT_CLASS__TYPE (clazz)
+  *
+  * @description:
+  *   a useful macro to return the type of a given class
+  *   given class
+  */
 #define  FT_CLASS__TYPE(x)     FT_CLASS(x)->type
-#define  FT_CLASS__DATA(x)     FT_CLASS(x)->data
+
+ /* */
 #define  FT_CLASS__INFO(x)     FT_CLASS(x)->info
+#define  FT_CLASS__MAGIC(x)    FT_CLASS(x)->magic
 
+
+ /**************************************************************
+  *
+  * @struct: FT_TypeRec
+  *
+  * @description:
+  *   a structure used to describe a given class to the FreeType
+  *   object sub-system.
+  *
+  * @fields:
+  *   name       :: class name. only used for debugging
+  *   super      :: type of super-class. NULL if none
+  *
+  *   class_size :: size of class structure in bytes
+  *   class_init :: class constructor
+  *   class_done :: class finalizer
+  *
+  *   obj_size   :: instance size in bytes
+  *   obj_init   :: instance constructor. can be NULL
+  *   obj_done   :: instance destructor. can be NULL
+  *
+  * @note:
+  *   if 'obj_init' is NULL, the class will use it's parent
+  *   constructor.
+  *
+  *   if 'obj_done' is NULL, the class will use it's parent
+  *   finalizer.
+  *
+  *   the object sub-system allocates a new class, copies
+  *   the content of its super-class into the new structure,
+  *   _then_ calls 'clazz_init'.
+  */
   typedef struct FT_TypeRec_
   {
     const char*         name;
     FT_Type             super;
-    
+
     FT_UInt             class_size;
     FT_Object_InitFunc  class_init;
     FT_Object_DoneFunc  class_done;
-    
+
     FT_UInt             obj_size;
     FT_Object_InitFunc  obj_init;
     FT_Object_DoneFunc  obj_done;
-    FT_Object_CopyFunc  obj_copy;
-  
+
   } FT_TypeRec;
 
+
+ /**************************************************************
+  *
+  * @macro: FT_TYPE (x)
+  *
+  * @description:
+  *   a useful macro to convert anything to a class type handle
+  *   without checks
+  */
 #define  FT_TYPE(x)  ((FT_Type)(x))
 
 
- /* check that a handle points to a valid object */
+ /**************************************************************
+  *
+  * @function: ft_object_check
+  *
+  * @description:
+  *   checks that a handle points to a valid @FT_Object
+  *
+  * @input:
+  *   obj :: handle/pointer
+  *
+  * @return:
+  *   1 iff the handle points to a valid object. 0 otherwise
+  */
   FT_BASE_DEF( FT_Int )
   ft_object_check( FT_Pointer  obj );
 
 
- /* check that an object is of a given class */
+ /**************************************************************
+  *
+  * @function: ft_object_is_a
+  *
+  * @description:
+  *   checks that a handle points to a valid @FT_Object that
+  *   is an instance of a given class (or of any of its sub-classes)
+  *
+  * @input:
+  *   obj   :: handle/pointer
+  *   clazz :: class handle to check
+  *
+  * @return:
+  *   1 iff the handle points to a valid 'clazz' instance. 0
+  *   otherwise.
+  */
   FT_BASE_DEF( FT_Int )
   ft_object_is_a( FT_Pointer  obj,
                   FT_Class    clazz );
 
 
+ /**************************************************************
+  *
+  * @function: ft_object_new
+  *
+  * @description:
+  *   create a new object (class instance)
+  *
+  * @input:
+  *   clazz     :: object's class pointer
+  *   init_data :: optional pointer to initialization data
+  *
+  * @return:
+  *   handle to new object. Cannot be NULL !
+  */
   FT_BASE_DEF( FT_Object )
   ft_object_new( FT_Class    clazz,
                  FT_Pointer  init_data );
+
+
+ /**************************************************************
+  *
+  * @function: ft_object_create
+  *
+  * @description:
+  *   a variation of @ft_object_new that should be used when
+  *   creating a new object that is owned by another object
+  *   which is reachable from the cleanup stack.
+  *
+  *   this function is a bit more akward to use but completely
+  *   avoids push/pop pairs during object construction and is
+  *   therefore faster.
+  *
+  * @output:
+  *   pobject   :: new object handle
+  *
+  * @input:
+  *   clazz     :: object's class pointer
+  *   init_data :: optional pointer to initialization data
+  *   push      :: boolean. If true, the new object is pushed
+  *                on top of the cleanup stack.
+  */
+  FT_BASE_DEF( void )
+  ft_object_create( FT_Object  *pobject,
+                    FT_Class    clazz,
+                    FT_Pointer  init_data );
+
+ /* */
+
+  FT_BASE_DEF( FT_Class )
+  ft_class_find_by_type( FT_Type    type,
+                         FT_Memory  memory );
+
+  FT_BASE_DEF( FT_Class )
+  ft_class_find_by_name( FT_CString  class_name,
+                         FT_Memory   memory );
+
+  FT_BASE_DEF( FT_Object )
+  ft_object_new_from_type( FT_Type     type,
+                           FT_Pointer  data,
+                           FT_Memory   memory );
+
+  FT_BASE_DEF( void )
+  ft_object_create_from_type( FT_Object  *pobject,
+                              FT_Type     type,
+                              FT_Pointer  init_data,
+                              FT_Memory   memory );
+
+  FT_BASE_DEF( void )
+  ft_object_push( FT_Object  object );
+
+  FT_BASE_DEF( void )
+  ft_object_pop( FT_Object  object );
+
+  FT_BASE_DEF( void )
+  ft_object_pop_destroy( FT_Object  object );
 
 
 FT_END_HEADER
--- a/src/base/ftexcept.c
+++ b/src/base/ftexcept.c
@@ -10,9 +10,9 @@
     stack->top   = stack->chunk->items;
     stack->limit = stack->top + FT_CLEANUP_CHUNK_SIZE;
     stack->chunk_0.link = NULL;
-    
+
     stack->memory = memory;
-  }                         
+  }
 
 
 
@@ -21,7 +21,7 @@
   {
     FT_Memory        memory = stack->memory;
     FT_CleanupChunk  chunk, next;
-    
+
     for (;;)
     {
       chunk = stack->chunk;
@@ -29,10 +29,10 @@
         break;
 
       stack->chunk = chunk->link;
-      
-      FT_FREE( chunk );
+
+      FT_Free( chunk, memory );
     }
-    
+
     stack->memory = NULL;
   }
 
@@ -49,23 +49,21 @@
 
     FT_ASSERT( stack && stack->chunk && stack->top );
     FT_ASSERT( item  && item_func );
-    
+
     top = stack->top;
-    
+
     top->item      = item;
     top->item_func = item_func;
     top->item_data = item_data;
-    
+
     top ++;
-    
+
     if ( top == stack->limit )
     {
       FT_CleanupChunk  chunk;
-      FT_Error         error;
-      
-      if ( FT_ALLOC( chunk, stack->memory ) )
-        ft_cleanup_stack_throw( stack, error );
 
+      chunk = FT_QAlloc( sizeof(*chunk), stack->memory );
+
       chunk->link  = stack->chunk;
       stack->chunk = chunk;
       stack->limit = chunk->items + FT_CLEANUP_CHUNK_SIZE;
@@ -73,7 +71,7 @@
     }
 
     stack->top = top;
-  }                         
+  }
 
 
 
@@ -82,17 +80,17 @@
                         FT_Int            destroy )
   {
     FT_CleanupItem  top;
-    
-    
+
+
     FT_ASSERT( stack && stack->chunk && stack->top );
     top = stack->top;
-    
+
     if ( top == stack->chunk->items )
     {
       FT_CleanupChunk  chunk;
-      
+
       chunk = stack->chunk;
-      
+
       if ( chunk == &stack->chunk_0 )
       {
         FT_ERROR(( "cleanup.pop: empty cleanup stack !!\n" ));
@@ -101,21 +99,21 @@
 
       chunk = chunk->link;
       FT_QFree( stack->chunk, stack->memory );
-      
+
       stack->chunk = chunk;
       stack->limit = chunk->items + FT_CLEANUP_CHUNK_SIZE;
       top          = stack->limit;
     }
-    
+
     top --;
-    
+
     if ( destroy )
       top->item_func( top->item, top->item_data );
-    
+
     top->item      = NULL;
     top->item_func = NULL;
     top->item_data = NULL;
-    
+
     stack->top = top;
   }
 
@@ -129,10 +127,10 @@
 
 
     FT_ASSERT( stack && stack->chunk && stack->top );
-    
+
     top   = stack->top;
     chunk = stack->chunk;
-    
+
     if ( top > chunk->items )
       top--;
     else
@@ -146,17 +144,17 @@
   }
 
 
-  FT_BASE_DEF( void )
-  ft_cleanup_stack_throw( FT_CleanupStack  stack, FT_Error  error )
-  {
-  }
 
-
   FT_BASE_DEF( void )
   ft_xhandler_enter( FT_XHandler  xhandler,
                      FT_Memory    memory )
   {
-    
+    FT_CleanupStack  stack = FT_MEMORY__CLEANUP(memory);
+
+    xhandler->previous = stack->xhandler;
+    xhandler->cleanup  = stack->top;
+    xhandler->error    = 0;
+    stack->xhandler    = xhandler;
   }
 
 
@@ -164,5 +162,36 @@
   FT_BASE_DEF( void )
   ft_xhandler_exit( FT_XHandler  xhandler )
   {
+    FT_CleanupStack  stack = FT_MEMORY__CLEANUP(memory);
+
+    stack->xhandler    = xhandler->previous;
+    xhandler->previous = NULL;
+    xhandler->error    = error;
+    xhandler->cleanup  = NULL;
   }
 
+
+
+  FT_BASE_DEF( void )
+  ft_cleanup_throw( FT_CleanupStack  stack,
+                    FT_Error         error )
+  {
+    FT_XHandler  xhandler = stack->xhandler;
+
+    if ( xhandler == NULL )
+    {
+      /* no exception handler was registered. this  */
+      /* means that we have an un-handled exception */
+      /* the only thing we can do is _PANIC_ and    */
+      /* halt the current program..                 */
+      /*                                            */
+      FT_ERROR(( "FREETYPE PANIC: An un-handled exception occured. Program aborted" ));
+      ft_exit(1);
+    }
+
+    /* cleanup the stack until we reach the handler's */
+    /* starting stack location..                      */
+
+    xhandler->error = error;
+    longmp( xhandler->jump_buffer, 1 );
+  }                    
\ No newline at end of file
--- /dev/null
+++ b/src/base/fthash.c
@@ -1,0 +1,215 @@
+#include "fthash.h"
+#include FT_INTERNAL_MEMORY_H
+#include FT_INTERNAL_DEBUG_H
+
+#define  FT_HASH_MAX_LOAD  2
+#define  FT_HASH_MIN_LOAD  1
+#define  FT_HASH_SUB_LOAD  (FT_HASH_MAX_LOAD-FT_HASH_MIN_LOAD)
+
+/* this one _must_ be a power of 2 !! */
+#define  FT_HASH_INITIAL_SIZE  8
+
+
+  FT_BASE_DEF( void )
+  ft_hash_done( FT_Hash              table,
+                FT_Hash_ForeachFunc  node_func,
+                const FT_Pointer     node_data )
+  {
+    if ( table )
+    {
+      FT_Memory  memory = table->memory;
+
+      if ( node_func )
+        ft_hash_foreach( table, node_func, node_data );
+
+      FT_FREE( table->buckets );
+      table->p     = 0;
+      table->mask  = 0;
+      table->slack = 0;
+
+      table->compare = NULL;
+    }
+  }
+
+
+  FT_BASE_DEF( FT_UInt )
+  ft_hash_get_size( FT_Hash  table )
+  {
+    FT_UInt  result = 0;
+
+    if ( table )
+      result = (table->p + table->mask + 1)*FT_HASH_MAX_LOAD - table->slack;
+
+    return result;
+  }
+
+
+
+  FT_BASE_DEF( void )
+  ft_hash_init( FT_Hash              table,
+                FT_Hash_CompareFunc  compare,
+                FT_Memory            memory )
+  {
+    hash->memory  = memory;
+    hash->compare = node_compare;
+    hash->p       = 0;
+    hash->mask    = FT_HASH_INITIAL_SIZE-1;
+    hash->slack   = FT_HASH_INITIAL_SIZE*FT_HASH_MAX_LOAD;
+
+    FT_NEW_ARRAY( hash->buckets, FT_HASH_INITIAL_SIZE*2 );
+  }
+
+
+
+  FT_BASE_DEF( void )
+  ft_hash_foreach( FT_Hash              table,
+                   FT_Hash_ForeachFunc  foreach_func,
+                   const FT_Pointer     foreach_data )
+  {
+    FT_UInt       count = table->p + table->mask + 1;
+    FT_HashNode*  pnode = table->buckets;
+    FT_HashNode   node, next;
+
+    for ( ; count > 0; count--, pnode++ )
+    {
+      node = *pnode;
+      while ( node )
+      {
+        next = node->link;
+        foreach_func( node, foreach_data );
+        node = next;
+      }
+    }
+  }
+
+
+
+  FT_BASE_DEF( FT_HashNode* )
+  ft_hash_lookup( FT_Hash      table,
+                  FT_HashNode  keynode )
+  {
+    FT_UInt    index;
+    FT_UInt23  hash = keynode->hash;
+
+    index = (FT_UInt)(hash & table->mask);
+    if ( index < table->p )
+      index = (FT_UInt)(hash & (2*table->mask+1));
+
+    pnode = &table->buckets[index];
+    for (;;)
+    {
+      node = *pnode;
+      if ( node == NULL )
+        break;
+
+      if ( node->hash == hash && table->compare( node, keynode ) )
+        break;
+
+      pnode = &node->link;
+    }
+
+    return pnode;
+  }
+
+
+
+
+  FT_BASE_DEF( void )
+  ft_hash_add( FT_Hash       table,
+               FT_HashNode*  pnode,
+               FT_HashNode   new_node )
+  {
+    /* add it to the hash table */
+    new_node->link = *pnode;
+    *pnode         = new_node;
+
+    if ( --table->slack < 0 )
+    {
+      FT_UInt       p     = table->p;
+      FT_UInt       mask  = table->mask;
+      FT_HashNode   new_list;
+
+      /* split a single bucket */
+      new_list = NULL;
+      pnode    = table->buckets + p;
+      for (;;)
+      {
+        node = *pnode;
+        if ( node == NULL )
+          break;
+
+        if ( node->hash & mask )
+        {
+          *pnode     = node->link;
+          node->link = new_list;
+          new_list   = node;
+        }
+        else
+          pnode = &node->link;
+      }
+
+      table->buckets[ p + mask + 1 ] = new_list;
+
+      table->slack += FT_HASH_MAX_LOAD;
+
+      if ( p >= mask )
+      {
+        FT_RENEW_ARRAY( hash->buckets, (mask+1)*2, (mask+1)*4 );
+        table->mask = 2*mask + 1;
+        table->p    = 0;
+      }
+      else
+        table->p = p + 1;
+    }
+  }
+
+
+
+  FT_BASE_DEF( FT_Int )
+  ft_hash_remove( FT_Hash      table,
+                  FT_HashNode* pnode )
+  {
+    FT_HashNode  node;
+    FT_UInt      num_buckets;
+
+    FT_ASSERT( pnode != NULL && node != NULL );
+
+    node         = *pnode;
+    *pnode->link = node->link;
+    node->link   = NULL;
+
+    num_buckets = ( table->p + table->mask + 1) ;
+
+    if ( ++ table->slack > num_buckets*FT_HASH_SUB_LOAD )
+    {
+      FT_UInt       p         = table->p;
+      FT_UInt       mask      = table->mask;
+      FT_UInt       old_index = p + mask;
+      FT_HashNode*  pnode;
+      FT_HashNode*  pold;
+
+      if ( old_index < FT_HASH_INITIAL_SIZE )
+        return;
+
+      if ( p == 0 )
+      {
+        table->mask >>= 1;
+        p             = table->mask;
+
+        FT_RENEW_ARRAY( hash->buckets, (mask+1)*2, (mask) );
+      }
+      else
+        p--;
+
+      pnode = table->buckets + p;
+      while ( *pnode )
+        pnode = &(*pnode)->link;
+
+      pold   = table->buckets + old_index;
+      *pnode = *pold;
+      *pold  = NULL;
+
+      table->slack -= FT_HASH_MAX_LOAD;
+      table->p      = p;
+    }
+  }
--- /dev/null
+++ b/src/base/ftobject.c
@@ -1,0 +1,302 @@
+#include "ftobject.c"
+
+#define  FT_MAGIC_DEATH   0xDEADdead
+#define  FT_MAGIC_CLASS   0x12345678
+
+#define  FT_OBJECT_CHECK(o)                                  \
+           ( FT_OBJECT(o)              != NULL            && \
+             FT_OBJECT(o)->clazz       != NULL            && \
+             FT_OBJECT(o)->ref_count   >= 1               && \
+             FT_OBJECT(o)->clazz->magic == FT_MAGIC_CLASS )
+
+
+ /*******************************************************************/
+ /*******************************************************************/
+ /*****                                                         *****/
+ /*****                                                         *****/
+ /*****                  M E T A - C L A S S                    *****/
+ /*****                                                         *****/
+ /*****                                                         *****/
+ /*******************************************************************/
+ /*******************************************************************/
+
+ /* we use a dynamic hash table to map types to classes */
+ /* this structure defines the layout of each node of   */
+ /* this table                                          */
+  typedef struct FT_ClassHNodeRec_
+  {
+    FT_HashNodeRec  hnode;
+    FT_Type         ctype;
+    FT_Class        clazz;
+
+  } FT_ClassHNodeRec, *FT_ClassHNode;
+
+
+ /* the meta class contains a type -> class mapping */
+ /* and owns all class objects..                    */
+ /*                                                 */
+  typedef struct FT_MetaClassRec_
+  {
+    FT_ClassRec  clazz;
+    FT_HashRec   type_to_class;
+
+  } FT_MetaClassRec, *FT_MetaClass;
+
+ /* forward declaration */
+  static const FT_TypeRec  ft_meta_class_type;
+
+
+ /* destroy a given class */
+  static void
+  ft_class_hnode_destroy( FT_ClassHNode  node )
+  {
+    FT_Clazz   clazz  = node->clazz;
+    FT_Memory  memory = clazz->memory;
+    FT_Type    ctype  = clazz->type;
+
+    if ( ctype->class_done )
+      ctype->class_done( clazz );
+
+    FT_FREE( clazz );
+
+    node->clazz = NULL;
+    node->type  = NULL;
+
+    FT_FREE( node );
+  }
+
+
+  static FT_Int
+  ft_class_hnode_compare( const FT_ClassHNode  node1,
+                          const FT_ClassHNode  node2 )
+  {
+    return ( node1->type == node2->type );
+  }
+
+
+  static void
+  ft_metaclass_done( FT_MetaClass  meta )
+  {
+    /* clear all objects */
+    ft_hash_done( &meta->type_to_class,
+                  (FT_Hash_ForeachFunc) ft_class_destroy,
+                   NULL );
+
+    meta->clazz->object.clazz    = NULL;
+    meta->clazz->object.ref_count = 0;
+    meta->clazz->magic            = FT_MAGIC_DEATH;
+  }
+
+
+  static void
+  ft_metaclass_init( FT_MetaClass  meta,
+                     FT_Library    library )
+  {
+    FT_ClassRec*  clazz = meta->clazz;
+
+    /* the meta-class is its OWN class !! */
+    clazz->object.clazz     = (FT_Class) clazz;
+    clazz->object.ref_count = 1;
+    clazz->magic            = FT_MAGIC_CLASS;
+    clazz->library          = library;
+    clazz->memory           = library->memory;
+    clazz->type             = &ft_metaclass_type;
+    clazz->info             = NULL;
+
+    clazz->obj_size         = sizeof( FT_ClassRec );
+    clazz->obj_init         = NULL;
+    clazz->obj_done         = NULL;
+
+    ft_hash_init( &meta->type_to_class,
+                  (FT_Hash_CompareFunc) ft_class_hnode_compare,
+                  library->memory );
+  }
+
+
+ /* find or create the class corresponding to a given type */
+  static FT_Class
+  ft_metaclass_get_class( FT_MetaClass  meta,
+                          FT_Type       ctype )
+  {
+    FT_ClassHNodeRec   keynode, *node, **pnode;
+    FT_Memory          memory;
+
+    keynode.hnode.hash = (FT_UInt32)( ctype >> 2 );
+    keynode.type       = type;
+
+    pnode = (FT_ClassHNode) ft_hash_lookup( &meta->type_to_class,
+                                            &noderec );
+    node  = *pnode;
+    if ( node != NULL )
+      return node->clazz;
+
+    memory = FT_CLASS__MEMORY(meta);
+    node   = FT_MEM_SAFE_ALLOC( sizeof(*node) );
+    if ( node != NULL )
+    {
+      FT_ClassRec*  clazz;
+
+      clazz = FT_MEM_SAFE_ALLOC( ctype->class_size );
+      if ( clazz == NULL )
+      {
+        FT_FREE( node );
+        FT_XTHROW( FT_Err_Out_Of_Memory );
+      }
+    }
+  }
+
+
+  static const FT_TypeRec  ft_meta_class_type =
+  {
+    "FT2.MetaClass",
+    NULL,
+
+    sizeof( FT_MetaClassRec ),
+    (FT_Object_InitFunc)  ft_metaclass_init,
+    (FT_Object_DoneFunc)  ft_metaclass_done,
+
+    sizeof( FT_ClassRec ),
+    (FT_Object_InitFunc)  ft_class_init,
+    (FT_Object_DoneFunc)  ft_class_done
+  };
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+  FT_BASE_DEF( FT_Int )
+  ft_object_check( FT_Pointer  obj )
+  {
+    return FT_OBJECT_CHECK(obj);
+  }
+
+
+  FT_BASE_DEF( FT_Int )
+  ft_object_is_a( FT_Pointer  obj,
+                  FT_Class    clazz )
+  {
+    if ( FT_OBJECT_CHECK(obj) )
+    {
+      FT_Object  o = FT_OBJECT(obj);
+      FT_Class   c = FT_OBJECT__CLASS(obj);
+
+      do
+      {
+        if ( c == clazz )
+          return 1;
+
+        c = c->super;
+      }
+      while ( c == NULL );
+
+      return (clazz == NULL);
+    }
+  }
+
+
+ /* the cleanup routine for all objects */
+  static void
+  ft_object_cleanup( FT_Object  object )
+  {
+    FT_Memory  memory = FT_OBJECT__MEMORY(object);
+    FT_Class   clazz  = FT_OBJECT__CLASS(object);
+
+    if ( clazz->obj_done )
+      clazz->obj_done( object );
+
+    FT_FREE( object );
+  }
+
+
+  FT_BASE_DEF( FT_Object )
+  ft_object_new( FT_Class    clazz,
+                 FT_Pointer  init_data )
+  {
+    FT_Memory  memory;
+    FT_Object  obj;
+
+
+    FT_ASSERT_IS_CLASS(clazz);
+
+    memory         = FT_CLASS__MEMORY(clazz);
+    obj            = ft_mem_alloc( clazz->obj_size, memory );
+    obj->clazz     = clazz;
+    obj->ref_count = 1;
+
+    if ( clazz->obj_init )
+    {
+      FT_CleanupStack  stack = FT_MEMORY__CLEANUP(memory);
+
+
+      ft_cleanup_push( stack, obj, (FT_CleanupFunc) ft_object_cleanup, NULL );
+
+      clazz->obj_init( obj, init_data );
+
+      ft_cleanup_pop( stack, obj, 0 );
+    }
+    return obj;
+  }
+
+
+
+  FT_BASE_DEF( void )
+  ft_object_create( FT_Object  *pobject,
+                    FT_Class    clazz,
+                    FT_Pointer  init_data )
+  {
+    FT_Memory  memory;
+    FT_Object  obj;
+
+    FT_ASSERT_IS_CLASS(clazz);
+
+    memory         = FT_CLASS__MEMORY(memory);
+    obj            = ft_mem_alloc( clazz->obj_size, memory );
+    obj->clazz     = clazz;
+    obj->ref_count = 1;
+    *pobject       = obj;
+
+    if ( clazz->obj_init )
+      clazz->obj_init( obj, init_data );
+  }
+
+
+  FT_BASE_DEF( FT_Class )
+  ft_class_find_by_type( FT_Type    type,
+                         FT_Memory  memory )
+  {
+  }
+
+
+  FT_BASE_DEF( FT_Class )
+  ft_class_find_by_name( FT_CString  class_name,
+                         FT_Memory   memory );
+
+  FT_BASE_DEF( FT_Object )
+  ft_object_new_from_type( FT_Type     type,
+                           FT_Pointer  data,
+                           FT_Memory   memory );
+
+  FT_BASE_DEF( void )
+  ft_object_create_from_type( FT_Object  *pobject,
+                              FT_Type     type,
+                              FT_Pointer  init_data,
+                              FT_Memory   memory );
+
+  FT_BASE_DEF( void )
+  ft_object_push( FT_Object  object );
+
+  FT_BASE_DEF( void )
+  ft_object_pop( FT_Object  object );
+
+  FT_BASE_DEF( void )
+  ft_object_pop_destroy( FT_Object  object );
+