| /***************************************************************************/ |
| /* */ |
| /* ftextend.h */ |
| /* */ |
| /* FreeType extensions implementation (body). */ |
| /* */ |
| /* Copyright 1996-2000 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 <freetype/internal/ftextend.h> |
| |
| |
| /*************************************************************************/ |
| /* */ |
| /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ |
| /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ |
| /* messages during execution. */ |
| /* */ |
| #undef FT_COMPONENT |
| #define FT_COMPONENT trace_extend |
| |
| |
| typedef struct FT_Extension_Registry_ |
| { |
| FT_Int num_extensions; |
| FT_Long cur_offset; |
| FT_Extension_Class classes[FT_MAX_EXTENSIONS]; |
| |
| } FT_Extension_Registry; |
| |
| |
| /*************************************************************************/ |
| /* */ |
| /* <Function> */ |
| /* FT_Init_Extensions */ |
| /* */ |
| /* <Description> */ |
| /* Initializes the extension component. */ |
| /* */ |
| /* <InOut> */ |
| /* driver :: A handle to the driver object. */ |
| /* */ |
| /* <Return> */ |
| /* FreeType error code. 0 means success. */ |
| /* */ |
| LOCAL_FUNC |
| FT_Error FT_Init_Extensions( FT_Driver driver ) |
| { |
| FT_Error error; |
| FT_Memory memory; |
| FT_Extension_Registry* registry; |
| |
| |
| memory = driver->library->memory; |
| if ( ALLOC( registry, sizeof ( *registry ) ) ) |
| return error; |
| |
| registry->num_extensions = 0; |
| registry->cur_offset = 0; |
| driver->extensions = registry; |
| |
| FT_TRACE2(( "FT_Init_Extensions: success" )); |
| |
| return FT_Err_Ok; |
| } |
| |
| |
| /*************************************************************************/ |
| /* */ |
| /* <Function> */ |
| /* FT_Done_Extensions */ |
| /* */ |
| /* <Description> */ |
| /* Finalizes the extension component. */ |
| /* */ |
| /* <InOut> */ |
| /* driver :: A handle to the driver object. */ |
| /* */ |
| /* <Return> */ |
| /* FreeType error code. 0 means success. */ |
| /* */ |
| LOCAL_FUNC |
| FT_Error FT_Done_Extensions( FT_Driver driver ) |
| { |
| FT_Memory memory = driver->memory; |
| |
| |
| FREE( driver->extensions ); |
| return FT_Err_Ok; |
| } |
| |
| |
| /*************************************************************************/ |
| /* */ |
| /* <Function> */ |
| /* FT_Register_Extension */ |
| /* */ |
| /* <Description> */ |
| /* Registers a new extension. */ |
| /* */ |
| /* <InOut> */ |
| /* driver :: A handle to the driver object. */ |
| /* class :: A pointer to a class describing the extension. */ |
| /* */ |
| /* <Return> */ |
| /* FreeType error code. 0 means success. */ |
| /* */ |
| FT_EXPORT_FUNC( FT_Error ) FT_Register_Extension( |
| FT_Driver driver, |
| FT_Extension_Class* class ) |
| { |
| FT_Extension_Registry* registry; |
| |
| |
| if ( !driver ) |
| return FT_Err_Invalid_Driver_Handle; |
| |
| if ( !class ) |
| return FT_Err_Invalid_Argument; |
| |
| registry = (FT_Extension_Registry*)driver->extensions; |
| if ( registry ) |
| { |
| FT_Int n = registry->num_extensions; |
| FT_Extension_Class* cur = registry->classes + n; |
| |
| |
| if ( n >= FT_MAX_EXTENSIONS ) |
| return FT_Err_Too_Many_Extensions; |
| |
| *cur = *class; |
| |
| cur->offset = registry->cur_offset; |
| |
| registry->num_extensions++; |
| registry->cur_offset += ( cur->size + FT_ALIGNMENT-1 ) & -FT_ALIGNMENT; |
| |
| FT_TRACE1(( "FT_Register_Extension: `%s' successfully registered", |
| cur->id )); |
| } |
| |
| return FT_Err_Ok; |
| } |
| |
| |
| /*************************************************************************/ |
| /* */ |
| /* <Function> */ |
| /* FT_Get_Extension */ |
| /* */ |
| /* <Description> */ |
| /* Queries an extension block by an extension ID string. */ |
| /* */ |
| /* <Input> */ |
| /* face :: A handle to the face object. */ |
| /* extension_id :: An ID string identifying the extension. */ |
| /* */ |
| /* <Output> */ |
| /* extension_interface :: A generic pointer, usually pointing to a */ |
| /* table of functions implementing the */ |
| /* extension interface. */ |
| /* */ |
| /* <Return> */ |
| /* A pointer to the extension block. */ |
| /* */ |
| FT_EXPORT_FUNC( void* ) FT_Get_Extension( |
| FT_Face face, |
| const char* extension_id, |
| void* *extension_interface ) |
| { |
| FT_Extension_Registry* registry; |
| |
| |
| if ( !face || !extension_id || !extension_interface ) |
| return 0; |
| |
| registry = (FT_Extension_Registry*)face->driver->extensions; |
| if ( registry && face->extensions ) |
| { |
| FT_Extension_Class* cur = registry->classes; |
| FT_Extension_Class* limit = cur + registry->num_extensions; |
| |
| |
| for ( ; cur < limit; cur++ ) |
| if ( strcmp( cur->id, extension_id ) == 0 ) |
| { |
| *extension_interface = cur->interface; |
| |
| FT_TRACE1(( "FT_Get_Extension: got `%s'", extension_id )); |
| |
| return (void*)((char*)face->extensions + cur->offset); |
| } |
| } |
| |
| /* could not find the extension id */ |
| |
| FT_ERROR(( "FT_Get_Extension: couldn't find `%s'", extension_id )); |
| |
| *extension_interface = 0; |
| |
| return 0; |
| } |
| |
| |
| /*************************************************************************/ |
| /* */ |
| /* <Function> */ |
| /* FT_Destroy_Extensions */ |
| /* */ |
| /* <Description> */ |
| /* Destroys all extensions within a face object. */ |
| /* */ |
| /* <InOut> */ |
| /* face :: A handle to the face object. */ |
| /* */ |
| /* <Return> */ |
| /* FreeType error code. 0 means success. */ |
| /* */ |
| /* <Note> */ |
| /* Called by the face object destructor. */ |
| /* */ |
| LOCAL_FUNC |
| FT_Error FT_Destroy_Extensions( FT_Face face ) |
| { |
| FT_Extension_Registry* registry; |
| FT_Memory memory; |
| |
| |
| registry = (FT_Extension_Registry*)face->driver->extensions; |
| if ( registry && face->extensions ) |
| { |
| FT_Extension_Class* cur = registry->classes; |
| FT_Extension_Class* limit = cur + registry->num_extensions; |
| |
| |
| for ( ; cur < limit; cur++ ) |
| { |
| char* ext = (char*)face->extensions + cur->offset; |
| |
| if ( cur->finalize ) |
| cur->finalize( ext, face ); |
| } |
| |
| memory = face->driver->memory; |
| FREE( face->extensions ); |
| } |
| |
| return FT_Err_Ok; |
| } |
| |
| |
| /*************************************************************************/ |
| /* */ |
| /* <Function> */ |
| /* FT_Create_Extensions */ |
| /* */ |
| /* <Description> */ |
| /* Creates an extension object within a face object for all */ |
| /* registered extensions. */ |
| /* */ |
| /* <InOut> */ |
| /* face :: A handle to the face object. */ |
| /* */ |
| /* <Return> */ |
| /* FreeType error code. 0 means success. */ |
| /* */ |
| /* <Note> */ |
| /* Called by the face object constructor. */ |
| /* */ |
| LOCAL_FUNC |
| FT_Error FT_Create_Extensions( FT_Face face ) |
| { |
| FT_Extension_Registry* registry; |
| FT_Memory memory; |
| FT_Error error; |
| |
| |
| face->extensions = 0; |
| |
| /* load extensions registry, exit successfully if none is there */ |
| |
| registry = (FT_Extension_Registry*)face->driver->extensions; |
| if ( !registry ) |
| return FT_Err_Ok; |
| |
| memory = face->driver->memory; |
| if ( ALLOC( face->extensions, registry->cur_offset ) ) |
| return error; |
| |
| { |
| FT_Extension_Class* cur = registry->classes; |
| FT_Extension_Class* limit = cur + registry->num_extensions; |
| |
| |
| for ( ; cur < limit; cur++ ) |
| { |
| char* ext = (char*)face->extensions + cur->offset; |
| |
| if ( cur->init ) |
| { |
| error = cur->init( ext, face ); |
| if ( error ) |
| break; |
| } |
| } |
| } |
| |
| return error; |
| } |
| |
| |
| /* END */ |