Files
freetype/lib/ttextend.c
2023-08-27 18:03:45 +02:00

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 */