#include "ttextend.h"
#include "ttengine.h"
#include "ttmemory.h"
#undef TT_COMPONENT
#define TT_COMPONENT trace_extend
struct TExtension_Registry_
{
Int num_extensions;
Long cur_offset;
TExtension_Class classes[TT_MAX_EXTENSIONS];
};
typedef struct TExtension_Registry_ TExtension_Registry;
typedef TExtension_Registry* PExtension_Registry;
LOCAL_FUNC
TT_Error TTExtend_Init( PEngine_Instance engine )
{
TT_Error error;
PExtension_Registry exts;
if ( ALLOC( exts, sizeof ( TExtension_Registry ) ) )
return error;
exts->num_extensions = 0;
exts->cur_offset = 0;
engine->extension_component = (void*)exts;
return TT_Err_Ok;
}
LOCAL_FUNC
TT_Error TTExtend_Done( PEngine_Instance engine )
{
FREE( engine->extension_component );
return TT_Err_Ok;
}
EXPORT_FUNC
TT_Error TT_Register_Extension( PEngine_Instance engine,
Long id,
Long size,
PExt_Constructor create,
PExt_Destructor destroy )
{
PExtension_Registry exts;
PExtension_Class clazz;
Int p;
exts = (PExtension_Registry)engine->extension_component;
if ( !exts )
return TT_Err_Ok;
p = exts->num_extensions;
if ( p >= TT_MAX_EXTENSIONS )
return TT_Err_Too_Many_Extensions;
clazz = exts->classes + p;
clazz->id = id;
clazz->size = size;
clazz->build = create;
clazz->destroy = destroy;
clazz->offset = exts->cur_offset;
exts->num_extensions++;
exts->cur_offset += ( size + ALIGNMENT-1 ) & -ALIGNMENT;
return TT_Err_Ok;
}
EXPORT_FUNC
TT_Error TT_Extension_Get( PFace face,
Long extension_id,
void** extension_block )
{
PExtension_Registry registry;
PExtension_Class clazz;
Int n;
if ( !face->extension )
return TT_Err_Extensions_Unsupported;
registry = (PExtension_Registry)face->engine->extension_component;
for ( n = 0; n < face->n_extensions; n++ )
{
clazz = registry->classes + n;
if ( clazz->id == extension_id )
{
*extension_block = (PByte)face->extension + clazz->offset;
return TT_Err_Ok;
}
}
return TT_Err_Invalid_Extension_Id;
}
LOCAL_FUNC
TT_Error Extension_Destroy( PFace face )
{
PEngine_Instance engine = face->engine;
PExtension_Registry registry;
PExtension_Class clazz;
Int n;
PByte ext;
registry = (PExtension_Registry)engine->extension_component;
for ( n = 0; n < face->n_extensions; n++ )
{
clazz = registry->classes + n;
ext = (PByte)face->extension + clazz->offset;
if ( clazz->destroy )
clazz->destroy( (void*)ext, face );
}
FREE( face->extension );
face->n_extensions = 0;
return TT_Err_Ok;
}
LOCAL_FUNC
TT_Error Extension_Create( PFace face )
{
PEngine_Instance engine = face->engine;
PExtension_Registry registry;
PExtension_Class clazz;
TT_Error error;
Int n;
PByte ext;
registry = (PExtension_Registry)engine->extension_component;
face->n_extensions = registry->num_extensions;
if ( ALLOC( face->extension, registry->cur_offset ) )
return error;
for ( n = 0; n < face->n_extensions; n++ )
{
clazz = registry->classes + n;
ext = (PByte)face->extension + clazz->offset;
error = clazz->build( (void*)ext, face );
if ( error )
goto Fail;
}
return TT_Err_Ok;
Fail:
Extension_Destroy( face );
return error;
}