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