shithub: freetype+ttf2subf

Download patch

ref: 660138753b036ea5fe14c55c1ee2a57ea7615431
parent: 8db6a0702147a56a5c26fb66e6caf7de9869953e
author: David Turner <[email protected]>
date: Thu Jul 11 12:27:16 EDT 2002

updatinf the object sub-system and dynamic hash table implementations

git/fs: mount .git/fs: mount/attach disallowed
--- a/include/freetype/fttypes.h
+++ b/include/freetype/fttypes.h
@@ -21,6 +21,7 @@
 
 
 #include <ft2build.h>
+#include FT_CONFIG_CONFIG_H
 #include FT_SYSTEM_H
 #include FT_IMAGE_H
 
--- a/include/freetype/internal/fthash.h
+++ b/include/freetype/internal/fthash.h
@@ -125,7 +125,7 @@
     FT_Hash_EqualFunc    node_equal;
     FT_Memory            memory;
 
-  } FT_HashRec, *FT_Hash;
+  } FT_HashRec;
 
 
  /***********************************************************
@@ -270,7 +270,7 @@
   */
   FT_BASE_DEF( FT_HashLookup )
   ft_hash_lookup( FT_Hash      table,
-                  FT_HashNode  keynode )
+                  FT_HashNode  keynode );
 
 
  /****************************************************************
@@ -380,7 +380,7 @@
   */
   FT_BASE( FT_Error )
   ft_hash_remove( FT_Hash        table,
-                  FT_HashLookup  lookup )
+                  FT_HashLookup  lookup );
 
 
 
--- a/include/freetype/internal/ftobject.h
+++ b/include/freetype/internal/ftobject.h
@@ -288,14 +288,17 @@
   *
   * @note:
   *   if 'obj_init' is NULL, the class will use it's parent
-  *   constructor.
+  *   constructor, if any
   *
   *   if 'obj_done' is NULL, the class will use it's parent
-  *   finalizer.
+  *   finalizer, if any
   *
   *   the object sub-system allocates a new class, copies
   *   the content of its super-class into the new structure,
   *   _then_ calls 'clazz_init'.
+  *
+  *   'class_init' and 'class_done' can be NULL, in which case
+  *   the parent's class constructor and destructor wil be used
   */
   typedef struct FT_TypeRec_
   {
@@ -337,7 +340,7 @@
   * @return:
   *   1 iff the handle points to a valid object. 0 otherwise
   */
-  FT_BASE_DEF( FT_Int )
+  FT_BASE( FT_Int )
   ft_object_check( FT_Pointer  obj );
 
 
@@ -357,7 +360,7 @@
   *   1 iff the handle points to a valid 'clazz' instance. 0
   *   otherwise.
   */
-  FT_BASE_DEF( FT_Int )
+  FT_BASE( FT_Int )
   ft_object_is_a( FT_Pointer  obj,
                   FT_Class    clazz );
 
@@ -379,7 +382,7 @@
   * @return:
   *   error code. 0 means success
   */
-  FT_BASE_DEF( FT_Error )
+  FT_BASE( FT_Error )
   ft_object_create( FT_Object  *aobject,
                     FT_Class    clazz,
                     FT_Pointer  init_data );
@@ -408,7 +411,7 @@
   *   this is equivalent to calling @ft_class_from_type followed by
   *   @ft_object_create
   */
-  FT_BASE_DEF( FT_Error )
+  FT_BASE( FT_Error )
   ft_object_create_from_type( FT_Object  *aobject,
                               FT_Type     type,
                               FT_Pointer  init_data,
@@ -438,7 +441,7 @@
   *   code returned by the object constructor.
   */
 #define  FT_CREATE( _obj, _clazz, _init )  \
-             FT_MEM_SET( FT_OBJ_CREATE( _obj, _clazz, _init ) )
+             FT_SET_ERROR( FT_OBJ_CREATE( _obj, _clazz, _init ) )
 
  /**************************************************************
   *
@@ -462,7 +465,7 @@
   *   code returned by the object constructor.
   */
 #define  FT_CREATE_FROM_TYPE( _obj, _type, _init, _lib )  \
-             FT_MEM_SET( FT_OBJ_CREATE( _obj, _type, _init, _lib ) )
+             FT_SET_ERROR( FT_OBJ_CREATE_FROM_TYPE( _obj, _type, _init, _lib ) )
 
 
  /* */
@@ -486,39 +489,12 @@
   * @return:
   *   error code. 0 means success
   */
-  FT_BASE_DEF( FT_Error )
+  FT_BASE( FT_Error )
   ft_class_from_type( FT_Class   *aclass,
                       FT_Type     type,
                       FT_Library  library );
 
 
- /**************************************************************
-  *
-  * @function: ft_class_from_name
-  *
-  * @description:
-  *   retrieves the class object corresponding to a given type
-  *   name. The class is created when needed
-  *
-  * @output:
-  *   aclass  :: handle to corresponding class object. NULL
-  *              in case of error
-  *
-  * @input:
-  *   name    :: class name
-  *   library :: library handle
-  *
-  * @return:
-  *   error code. 0 means success
-  *
-  * @note:
-  *   this function is _very_ slow. You should only use it for
-  *   debugging purposes..
-  */
-  FT_BASE_DEF( FT_Error )
-  ft_class_from_name( FT_Class   *aclass,
-                      FT_CString  class_name,
-                      FT_Library  library );
  /* */
 
 #include FT_INTERNAL_HASH_H
@@ -542,12 +518,12 @@
 
 
  /* initialize meta class */
-  FT_BASE_DEF( FT_Error )
+  FT_BASE( FT_Error )
   ft_metaclass_init( FT_MetaClass  meta,
                      FT_Library    library );
 
  /* finalize meta class - destroy all registered class objects */
-  FT_BASE_DEF( void )
+  FT_BASE( void )
   ft_metaclass_done( FT_MetaClass  meta );
 
  /* */
--- a/include/freetype/internal/ftobjs.h
+++ b/include/freetype/internal/ftobjs.h
@@ -34,8 +34,8 @@
 #include FT_INTERNAL_GLYPH_LOADER_H
 #include FT_INTERNAL_DRIVER_H
 #include FT_INTERNAL_AUTOHINT_H
+#include FT_INTERNAL_OBJECT_H
 
-
 FT_BEGIN_HEADER
 
 
@@ -694,6 +694,8 @@
     FT_ULong           raster_pool_size; /* size of render pool in bytes */
 
     FT_DebugHook_Func  debug_hooks[4];
+
+    FT_MetaClassRec    meta_class;
 
   } FT_LibraryRec;
 
--- a/include/freetype/internal/internal.h
+++ b/include/freetype/internal/internal.h
@@ -35,6 +35,8 @@
 #define FT_INTERNAL_TRACE_H               <freetype/internal/fttrace.h>
 #define FT_INTERNAL_GLYPH_LOADER_H        <freetype/internal/ftgloadr.h>
 #define FT_INTERNAL_SFNT_H                <freetype/internal/sfnt.h>
+#define FT_INTERNAL_HASH_H                <freetype/internal/fthash.h>
+#define FT_INTERNAL_OBJECT_H              <freetype/internal/ftobject.h>
 
 #define FT_INTERNAL_TRUETYPE_TYPES_H      <freetype/internal/tttypes.h>
 #define FT_INTERNAL_TYPE1_TYPES_H         <freetype/internal/t1types.h>
--- a/src/base/Jamfile
+++ b/src/base/Jamfile
@@ -25,7 +25,7 @@
 #
 Library  $(FT2_LIB) : ftsystem.c ftinit.c   ftglyph.c  ftmm.c     ftbdf.c
                       ftbbox.c   ftdebug.c  ftxf86.c   fttype1.c  ftstroker.c
-                      ftsynth.c  ;
+                      ftsynth.c  ftobject.c fthash.c ;
 
 # Add Macintosh-specific file to the library when necessary.
 #
--- a/src/base/fthash.c
+++ b/src/base/fthash.c
@@ -1,4 +1,6 @@
-#include "fthash.h"
+#include <ft2build.h>
+#include FT_TYPES_H
+#include FT_INTERNAL_HASH_H
 #include FT_INTERNAL_MEMORY_H
 #include FT_INTERNAL_DEBUG_H
 
@@ -27,7 +29,7 @@
       table->mask  = 0;
       table->slack = 0;
 
-      table->compare = NULL;
+      table->node_equal = NULL;
     }
   }
 
@@ -46,17 +48,21 @@
 
 
   FT_BASE_DEF( FT_Error )
-  ft_hash_init( FT_Hash              table,
-                FT_Hash_CompareFunc  compare,
-                FT_Memory            memory )
+  ft_hash_init( FT_Hash            table,
+                FT_Hash_EqualFunc  equal,
+                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_Error  error;
 
-    FT_NEW_ARRAY( hash->buckets, FT_HASH_INITIAL_SIZE*2 );
+    table->memory     = memory;
+    table->p          = 0;
+    table->mask       = FT_HASH_INITIAL_SIZE-1;
+    table->slack      = FT_HASH_INITIAL_SIZE*FT_HASH_MAX_LOAD;
+    table->node_equal = equal;
+
+    (void)FT_NEW_ARRAY( table->buckets, FT_HASH_INITIAL_SIZE*2 );
+
+    return error;
   }
 
 
@@ -84,12 +90,13 @@
 
 
 
-  FT_BASE_DEF( FT_HashNode* )
+  FT_BASE_DEF( FT_HashLookup )
   ft_hash_lookup( FT_Hash      table,
                   FT_HashNode  keynode )
   {
-    FT_UInt    index;
-    FT_UInt23  hash = keynode->hash;
+    FT_UInt       index;
+    FT_UInt32     hash = keynode->hash;
+    FT_HashNode   node, *pnode;
 
     index = (FT_UInt)(hash & table->mask);
     if ( index < table->p )
@@ -102,7 +109,7 @@
       if ( node == NULL )
         break;
 
-      if ( node->hash == hash && table->compare( node, keynode ) )
+      if ( node->hash == hash && table->node_equal( node, keynode ) )
         break;
 
       pnode = &node->link;
@@ -114,20 +121,22 @@
 
 
 
-  FT_BASE_DEF( void )
-  ft_hash_add( FT_Hash       table,
-               FT_HashNode*  pnode,
-               FT_HashNode   new_node )
+  FT_BASE_DEF( FT_Error )
+  ft_hash_add( FT_Hash        table,
+               FT_HashLookup  lookup,
+               FT_HashNode    new_node )
   {
+    FT_Error     error = 0;
+
     /* add it to the hash table */
-    new_node->link = *pnode;
-    *pnode         = new_node;
+    new_node->link = *lookup;
+    *lookup        = new_node;
 
     if ( --table->slack < 0 )
     {
       FT_UInt       p     = table->p;
       FT_UInt       mask  = table->mask;
-      FT_HashNode   new_list;
+      FT_HashNode   new_list, node, *pnode;
 
       /* split a single bucket */
       new_list = NULL;
@@ -154,7 +163,12 @@
 
       if ( p >= mask )
       {
-        FT_RENEW_ARRAY( hash->buckets, (mask+1)*2, (mask+1)*4 );
+        FT_Memory  memory = table->memory;
+
+
+        if (FT_RENEW_ARRAY( table->buckets, (mask+1)*2, (mask+1)*4 ))
+          goto Exit;
+
         table->mask = 2*mask + 1;
         table->p    = 0;
       }
@@ -161,22 +175,25 @@
       else
         table->p = p + 1;
     }
+  Exit:
+    return error;
   }
 
 
 
-  FT_BASE_DEF( FT_Int )
-  ft_hash_remove( FT_Hash      table,
-                  FT_HashNode* pnode )
+  FT_BASE_DEF( FT_Error )
+  ft_hash_remove( FT_Hash        table,
+                  FT_HashLookup  lookup )
   {
     FT_HashNode  node;
     FT_UInt      num_buckets;
+    FT_Error     error = 0;
 
     FT_ASSERT( pnode != NULL && node != NULL );
 
-    node         = *pnode;
-    *pnode->link = node->link;
-    node->link   = NULL;
+    node       = *lookup;
+    *lookup    = node->link;
+    node->link = NULL;
 
     num_buckets = ( table->p + table->mask + 1) ;
 
@@ -189,14 +206,26 @@
       FT_HashNode*  pold;
 
       if ( old_index < FT_HASH_INITIAL_SIZE )
-        return;
+        goto Exit;
 
       if ( p == 0 )
       {
+        FT_Memory  memory = table->memory;
+
         table->mask >>= 1;
         p             = table->mask;
 
-        FT_RENEW_ARRAY( hash->buckets, (mask+1)*2, (mask+1) );
+        if ( FT_RENEW_ARRAY( table->buckets, (mask+1)*2, (mask+1) ) )
+        {
+          /* this should never happen normally, but who knows :-)   */
+          /* we need to re-inject the node in the hash table before */
+          /* returning there, since it's safer                      */
+          pnode      = table->buckets;
+          node->link = *pnode;
+          *pnode     = node;
+
+          goto Exit;
+        }
       }
       else
         p--;
@@ -212,4 +241,6 @@
       table->slack -= FT_HASH_MAX_LOAD;
       table->p      = p;
     }
+  Exit:
+    return error;
   }
--- a/src/base/ftobject.c
+++ b/src/base/ftobject.c
@@ -1,13 +1,16 @@
-#include "ftobject.h"
-#include "fthash.h"
+#include <ft2build.h>
+#include FT_INTERNAL_OBJECT_H
+#include FT_INTERNAL_OBJECTS_H
 
 #define  FT_MAGIC_DEATH   0xDEADdead
 #define  FT_MAGIC_CLASS   0x12345678
 
+#define  FT_TYPE_HASH(x)  (( (FT_UInt32)(x) >> 2 )^( (FT_UInt32)(x) >> 10 ))
+
 #define  FT_OBJECT_CHECK(o)                                  \
-           ( FT_OBJECT(o)              != NULL            && \
-             FT_OBJECT(o)->clazz       != NULL            && \
-             FT_OBJECT(o)->ref_count   >= 1               && \
+           ( FT_OBJECT(o)               != NULL           && \
+             FT_OBJECT(o)->clazz        != NULL           && \
+             FT_OBJECT(o)->ref_count    >= 1              && \
              FT_OBJECT(o)->clazz->magic == FT_MAGIC_CLASS )
 
 
@@ -21,28 +24,6 @@
  /*******************************************************************/
  /*******************************************************************/
 
- /* 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;
 
@@ -51,12 +32,12 @@
   static void
   ft_class_hnode_destroy( FT_ClassHNode  node )
   {
-    FT_Clazz   clazz  = node->clazz;
+    FT_Class   clazz  = node->clazz;
     FT_Memory  memory = clazz->memory;
     FT_Type    ctype  = clazz->type;
 
-    if ( ctype->class_done )
-      ctype->class_done( clazz );
+    if ( clazz->class_done )
+      clazz->class_done( (FT_Object) clazz );
 
     FT_FREE( clazz );
 
@@ -68,32 +49,81 @@
 
 
   static FT_Int
-  ft_class_hnode_compare( const FT_ClassHNode  node1,
-                          const FT_ClassHNode  node2 )
+  ft_type_equal( FT_Type  type1,
+                 FT_Type  type2 )
   {
-    return ( node1->type == node2->type );
+    if ( type1 == type2 )
+      goto Ok;
+
+    if ( type1 == NULL || type2 == NULL )
+      goto Fail;
+
+    /* compare parent types */
+    if ( type1->super != type2->super )
+    {
+      if ( type1->super == NULL             ||
+           type2->super == NULL             ||
+           !ft_type_compare( type1, type2 ) )
+        goto Fail;
+    }
+
+    /* compare type names */
+    if ( type1->name != type2->name )
+    {
+      if ( type1->name == NULL                        ||
+           type2->name == NULL                        ||
+           ft_strcmp( type1->name, type2->name ) != 0 )
+        goto Fail;
+    }
+
+    /* compare the other type fields */
+    if ( type1->class_size != type2->class_size ||
+         type1->class_init != type2->class_init ||
+         type1->class_done != type2->class_done ||
+         type1->obj_size   != type2->obj_size   ||
+         type1->obj_init   != type2->obj_init   ||
+         type1->obj_done   != type2->obj_done   )
+      goto Fail;
+
+  Ok:
+    return 1;
+
+  Fail:
+    return 0;
   }
 
 
-  static void
+  static FT_Int
+  ft_class_hnode_equal( const FT_ClassHNode  node1,
+                        const FT_ClassHNode  node2 )
+  {
+    FT_Type  type1 = node1->type;
+    FT_Type  type2 = node2->type;
+
+    /* comparing the pointers should work in 99% of cases */
+    return ( type1 == type2 ) ? 1 : ft_type_equal( type1, type2 );
+  }
+
+
+  FT_BASE_DEF( void )
   ft_metaclass_done( FT_MetaClass  meta )
   {
-    /* clear all objects */
+    /* clear all classes */
     ft_hash_done( &meta->type_to_class,
-                  (FT_Hash_ForeachFunc) ft_class_destroy,
+                  (FT_Hash_ForeachFunc) ft_class_hnode_destroy,
                    NULL );
 
-    meta->clazz->object.clazz    = NULL;
-    meta->clazz->object.ref_count = 0;
-    meta->clazz->magic            = FT_MAGIC_DEATH;
+    meta->clazz.object.clazz     = NULL;
+    meta->clazz.object.ref_count = 0;
+    meta->clazz.magic            = FT_MAGIC_DEATH;
   }
 
 
-  static void
+  FT_BASE_DEF( FT_Error )
   ft_metaclass_init( FT_MetaClass  meta,
                      FT_Library    library )
   {
-    FT_ClassRec*  clazz = meta->clazz;
+    FT_ClassRec*  clazz = (FT_ClassRec*) &meta->clazz;
 
     /* the meta-class is its OWN class !! */
     clazz->object.clazz     = (FT_Class) clazz;
@@ -101,20 +131,25 @@
     clazz->magic            = FT_MAGIC_CLASS;
     clazz->library          = library;
     clazz->memory           = library->memory;
-    clazz->type             = &ft_metaclass_type;
+    clazz->type             = &ft_meta_class_type;
     clazz->info             = NULL;
 
+    clazz->class_done       = (FT_Object_DoneFunc) ft_metaclass_done;
+
     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 );
+    return ft_hash_init( &meta->type_to_class,
+                        (FT_Hash_EqualFunc) ft_class_hnode_equal,
+                        library->memory );
   }
 
 
  /* find or create the class corresponding to a given type */
+ /* note that this function will retunr NULL in case of    */
+ /* memory overflow                                        */
+ /*                                                        */
   static FT_Class
   ft_metaclass_get_class( FT_MetaClass  meta,
                           FT_Type       ctype )
@@ -121,29 +156,105 @@
   {
     FT_ClassHNodeRec   keynode, *node, **pnode;
     FT_Memory          memory;
+    FT_ClassRec*       clazz;
+    FT_Class           parent;
+    FT_Error           error;
 
-    keynode.hnode.hash = (FT_UInt32)( ctype >> 2 );
-    keynode.type       = type;
+    keynode.hnode.hash = FT_TYPE_HASH( ctype );
+    keynode.type       = ctype;
 
-    pnode = (FT_ClassHNode) ft_hash_lookup( &meta->type_to_class,
-                                            &noderec );
+    pnode = (FT_ClassHNode*) ft_hash_lookup( &meta->type_to_class,
+                                             (FT_HashNode) &keynode );
     node  = *pnode;
     if ( node != NULL )
-      return node->clazz;
+    {
+      clazz = (FT_ClassRec*) node->clazz;
+      goto Exit;
+    }
 
     memory = FT_CLASS__MEMORY(meta);
-    node   = FT_MEM_SAFE_ALLOC( sizeof(*node) );
-    if ( node != NULL )
+    clazz  = NULL;
+    parent = NULL;
+    if ( ctype->super != NULL )
     {
-      FT_ClassRec*  clazz;
+      FT_ASSERT( ctype->super->class_size <= ctype->class_size );
+      FT_ASSERT( ctype->super->obj_size   <= ctype->obj_size   );
 
-      clazz = FT_MEM_SAFE_ALLOC( ctype->class_size );
-      if ( clazz == NULL )
+      parent = ft_metaclass_get_class( meta, ctype->super );
+    }
+
+    if ( !FT_NEW( node ) )
+    {
+      if ( !FT_ALLOC( clazz, ctype->class_size ) )
       {
+        if ( parent )
+          FT_MEM_COPY( (FT_ClassRec*)clazz, parent, parent->type->class_size );
+
+        clazz->object.clazz     = (FT_Class) meta;
+        clazz->object.ref_count = 1;
+
+        clazz->memory  = memory;
+        clazz->library = FT_CLASS__LIBRARY(meta);
+        clazz->super   = parent;
+        clazz->type    = ctype;
+        clazz->info    = NULL;
+        clazz->magic   = FT_MAGIC_CLASS;
+
+        clazz->class_done = ctype->class_done;
+        clazz->obj_size   = ctype->obj_size;
+        clazz->obj_init   = ctype->obj_init;
+        clazz->obj_done   = ctype->obj_done;
+
+        if ( parent )
+        {
+          if ( clazz->class_done == NULL )
+            clazz->class_done = parent->class_done;
+
+          if ( clazz->obj_init == NULL )
+            clazz->obj_init = parent->obj_init;
+
+          if ( clazz->obj_done == NULL )
+            clazz->obj_done = parent->obj_done;
+        }
+
+        /* find class initializer, if any */
+        {
+          FT_Type             ztype = ctype;
+          FT_Object_InitFunc  cinit = NULL;
+
+          do
+          {
+            cinit = ztype->class_init;
+            if ( cinit != NULL )
+              break;
+
+            ztype = ztype->super;
+          }
+          while ( ztype != NULL );
+
+          /* then call it when needed */
+          if ( cinit != NULL )
+            error = cinit( (FT_Object) clazz, NULL );
+        }
+      }
+
+      if (error)
+      {
+        if ( clazz )
+        {
+          /* we always call the class destructor when    */
+          /* an error was detected in the constructor !! */
+          if ( clazz->class_done )
+            clazz->class_done( (FT_Object) clazz );
+
+          FT_FREE( clazz );
+        }
         FT_FREE( node );
-        FT_XTHROW( FT_Err_Out_Of_Memory );
       }
     }
+
+  Exit:
+    return  (FT_Class) clazz;
   }
 
 
@@ -157,8 +268,8 @@
     (FT_Object_DoneFunc)  ft_metaclass_done,
 
     sizeof( FT_ClassRec ),
-    (FT_Object_InitFunc)  ft_class_init,
-    (FT_Object_DoneFunc)  ft_class_done
+    (FT_Object_InitFunc)  NULL,
+    (FT_Object_DoneFunc)  NULL
   };
 
 
@@ -204,90 +315,69 @@
   }
 
 
- /* the cleanup routine for all objects */
-  static void
-  ft_object_cleanup( FT_Object  object )
+  FT_BASE_DEF( FT_Error )
+  ft_object_create( FT_Object  *pobject,
+                    FT_Class    clazz,
+                    FT_Pointer  init_data )
   {
-    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_Error   error;
     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 )
+    memory = FT_CLASS__MEMORY(memory);
+    if ( !FT_ALLOC( obj, clazz->obj_size ) )
     {
-      FT_CleanupStack  stack = FT_MEMORY__CLEANUP(memory);
+      obj->clazz     = clazz;
+      obj->ref_count = 1;
 
+      if ( clazz->obj_init )
+      {
+        error = clazz->obj_init( obj, init_data );
+        if ( error )
+        {
+          /* IMPORTANT: call the destructor when an error  */
+          /*            was detected in the constructor !! */
+          if ( clazz->obj_done )
+            clazz->obj_done( obj );
 
-      ft_cleanup_push( stack, obj, (FT_CleanupFunc) ft_object_cleanup, NULL );
-
-      clazz->obj_init( obj, init_data );
-
-      ft_cleanup_pop( stack, obj, 0 );
+          FT_FREE( obj );
+        }
+      }
     }
-    return obj;
+    *pobject = obj;
+    return error;
   }
 
 
-
-  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_Library  library )
   {
-    FT_Memory  memory;
-    FT_Object  obj;
+    FT_MetaClass  meta = &library->meta_class;
 
-    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 );
+    return ft_metaclass_get_class( meta, type );
   }
 
 
-  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_BASE_DEF( FT_Error )
   ft_object_create_from_type( FT_Object  *pobject,
                               FT_Type     type,
                               FT_Pointer  init_data,
-                              FT_Memory   memory );
+                              FT_Library  library )
+  {
+    FT_Class  clazz;
+    FT_Error  error;
+
+    clazz = ft_class_find_by_type( type, library );
+    if ( clazz )
+      error = ft_object_create( pobject, clazz, init_data );
+    else
+    {
+      *pobject = NULL;
+      error    = FT_Err_Out_Of_Memory;
+    }
+
+    return error;
+  }