213 lines
5.3 KiB
C
213 lines
5.3 KiB
C
/*******************************************************************
|
|
*
|
|
* ttextend.h 2.0
|
|
*
|
|
* Extensions Interface
|
|
*
|
|
* Copyright 1996-1999 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 is an updated version of the extension component, now
|
|
* located in the main library's source directory. It allows
|
|
* the dynamic registration/use of various face object extensions
|
|
* through a simple API.
|
|
*
|
|
******************************************************************/
|
|
|
|
#include "ttextend.h"
|
|
#include "ttengine.h"
|
|
#include "ttmemory.h"
|
|
|
|
/* required by the tracing mode */
|
|
#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;
|
|
|
|
|
|
|
|
/* Initialize the extension component */
|
|
|
|
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;
|
|
}
|
|
|
|
|
|
/* Finalize the extension component */
|
|
|
|
LOCAL_FUNC
|
|
TT_Error TTExtend_Done( PEngine_Instance engine )
|
|
{
|
|
FREE( engine->extension_component );
|
|
return TT_Err_Ok;
|
|
}
|
|
|
|
|
|
/* Register a new extension */
|
|
|
|
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;
|
|
}
|
|
|
|
|
|
/* Query an extension block by extension_ID */
|
|
|
|
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;
|
|
}
|
|
|
|
|
|
/* Destroy all extensions within a face object. Called by the */
|
|
/* face object destructor. */
|
|
|
|
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;
|
|
|
|
/* the destructor is optional */
|
|
if ( clazz->destroy )
|
|
clazz->destroy( (void*)ext, face );
|
|
}
|
|
|
|
/* destroy the face's extension block too */
|
|
FREE( face->extension );
|
|
face->n_extensions = 0;
|
|
|
|
return TT_Err_Ok;
|
|
}
|
|
|
|
|
|
/* Create an extension within a face object. Called by the */
|
|
/* face object constructor. */
|
|
|
|
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;
|
|
}
|
|
|
|
|
|
/* END */
|