5c0d3a4dca
src/bdf/bdfdrivr.c: removed compiler warnings
397 lines
9.8 KiB
C
397 lines
9.8 KiB
C
#include <ft2build.h>
|
|
#include FT_INTERNAL_OBJECT_H
|
|
#include FT_INTERNAL_DEBUG_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)->clazz->magic == FT_MAGIC_CLASS )
|
|
|
|
#define FT_CLASS_CHECK(c) \
|
|
( FT_CLASS(c) != NULL && FT_CLASS(c)->magic == FT_MAGIC_CLASS )
|
|
|
|
#define FT_ASSERT_IS_CLASS(c) FT_ASSERT( FT_CLASS_CHECK(c) )
|
|
|
|
/*******************************************************************/
|
|
/*******************************************************************/
|
|
/***** *****/
|
|
/***** *****/
|
|
/***** M E T A - C L A S S *****/
|
|
/***** *****/
|
|
/***** *****/
|
|
/*******************************************************************/
|
|
/*******************************************************************/
|
|
|
|
/* forward declaration */
|
|
FT_BASE_DEF( FT_Error )
|
|
ft_metaclass_init( FT_MetaClass meta,
|
|
FT_Library library );
|
|
|
|
/* forward declaration */
|
|
FT_BASE_DEF( void )
|
|
ft_metaclass_done( FT_MetaClass meta );
|
|
|
|
|
|
/* class type for the meta-class itself */
|
|
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) NULL,
|
|
(FT_Object_DoneFunc) NULL
|
|
};
|
|
|
|
|
|
|
|
|
|
/* destroy a given class */
|
|
static void
|
|
ft_class_hnode_destroy( FT_ClassHNode node )
|
|
{
|
|
FT_Class clazz = node->clazz;
|
|
FT_Memory memory = clazz->memory;
|
|
|
|
if ( clazz->class_done )
|
|
clazz->class_done( (FT_Object) clazz );
|
|
|
|
FT_FREE( clazz );
|
|
|
|
node->clazz = NULL;
|
|
node->type = NULL;
|
|
|
|
FT_FREE( node );
|
|
}
|
|
|
|
|
|
static FT_Int
|
|
ft_type_equal( FT_Type type1,
|
|
FT_Type type2 )
|
|
{
|
|
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_equal( 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 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 classes */
|
|
ft_hash_done( &meta->type_to_class,
|
|
(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;
|
|
}
|
|
|
|
|
|
FT_BASE_DEF( FT_Error )
|
|
ft_metaclass_init( FT_MetaClass meta,
|
|
FT_Library library )
|
|
{
|
|
FT_ClassRec* clazz = (FT_ClassRec*) &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_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;
|
|
|
|
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 )
|
|
{
|
|
FT_ClassHNodeRec keynode, *node, **pnode;
|
|
FT_Memory memory;
|
|
FT_ClassRec* clazz;
|
|
FT_Class parent;
|
|
FT_Error error;
|
|
|
|
keynode.hnode.hash = FT_TYPE_HASH( ctype );
|
|
keynode.type = ctype;
|
|
|
|
pnode = (FT_ClassHNode*) ft_hash_lookup( &meta->type_to_class,
|
|
(FT_HashNode) &keynode );
|
|
node = *pnode;
|
|
if ( node != NULL )
|
|
{
|
|
clazz = (FT_ClassRec*) node->clazz;
|
|
goto Exit;
|
|
}
|
|
|
|
memory = FT_CLASS__MEMORY(meta);
|
|
clazz = NULL;
|
|
parent = NULL;
|
|
if ( ctype->super != NULL )
|
|
{
|
|
FT_ASSERT( ctype->super->class_size <= ctype->class_size );
|
|
FT_ASSERT( ctype->super->obj_size <= ctype->obj_size );
|
|
|
|
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 );
|
|
}
|
|
}
|
|
|
|
Exit:
|
|
return (FT_Class) clazz;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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_Class c = FT_OBJECT__CLASS(obj);
|
|
|
|
do
|
|
{
|
|
if ( c == clazz )
|
|
return 1;
|
|
|
|
c = c->super;
|
|
}
|
|
while ( c == NULL );
|
|
|
|
return (clazz == NULL);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
FT_BASE_DEF( FT_Error )
|
|
ft_object_create( FT_Object *pobject,
|
|
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);
|
|
if ( !FT_ALLOC( obj, clazz->obj_size ) )
|
|
{
|
|
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_FREE( obj );
|
|
}
|
|
}
|
|
}
|
|
*pobject = obj;
|
|
return error;
|
|
}
|
|
|
|
|
|
FT_BASE_DEF( FT_Class )
|
|
ft_class_find_by_type( FT_Type type,
|
|
FT_Library library )
|
|
{
|
|
FT_MetaClass meta = &library->meta_class;
|
|
|
|
return ft_metaclass_get_class( meta, type );
|
|
}
|
|
|
|
|
|
FT_BASE_DEF( FT_Error )
|
|
ft_object_create_from_type( FT_Object *pobject,
|
|
FT_Type type,
|
|
FT_Pointer init_data,
|
|
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;
|
|
}
|