1 /***************************************************************************/
5 /* FreeType extensions implementation (body). */
7 /* Copyright 1996-2000 by */
8 /* David Turner, Robert Wilhelm, and Werner Lemberg. */
10 /* This file is part of the FreeType project, and may only be used, */
11 /* modified, and distributed under the terms of the FreeType project */
12 /* license, LICENSE.TXT. By continuing to use, modify, or distribute */
13 /* this file you indicate that you have read the license and */
14 /* understand and accept it fully. */
16 /***************************************************************************/
18 /*************************************************************************/
20 /* This is an updated version of the extension component, now located */
21 /* in the main library's source directory. It allows the dynamic */
22 /* registration/use of various face object extensions through a simple */
25 /*************************************************************************/
28 #include <freetype/internal/ftextend.h>
29 #include <freetype/internal/ftdebug.h>
32 /*************************************************************************/
34 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
35 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
36 /* messages during execution. */
39 #define FT_COMPONENT trace_extend
42 typedef struct FT_Extension_Registry_
44 FT_Int num_extensions;
46 FT_Extension_Class classes[FT_MAX_EXTENSIONS];
48 } FT_Extension_Registry;
51 /*************************************************************************/
54 /* FT_Init_Extensions */
57 /* Initializes the extension component. */
60 /* driver :: A handle to the driver object. */
63 /* FreeType error code. 0 means success. */
66 FT_Error FT_Init_Extensions( FT_Driver driver )
70 FT_Extension_Registry* registry;
73 memory = driver->root.library->memory;
74 if ( ALLOC( registry, sizeof ( *registry ) ) )
77 registry->num_extensions = 0;
78 registry->cur_offset = 0;
79 driver->extensions = registry;
81 FT_TRACE2(( "FT_Init_Extensions: success\n" ));
87 /*************************************************************************/
90 /* FT_Done_Extensions */
93 /* Finalizes the extension component. */
96 /* driver :: A handle to the driver object. */
99 /* FreeType error code. 0 means success. */
102 FT_Error FT_Done_Extensions( FT_Driver driver )
104 FT_Memory memory = driver->root.memory;
107 FREE( driver->extensions );
112 /*************************************************************************/
115 /* FT_Register_Extension */
118 /* Registers a new extension. */
121 /* driver :: A handle to the driver object. */
122 /* class :: A pointer to a class describing the extension. */
125 /* FreeType error code. 0 means success. */
127 FT_EXPORT_FUNC( FT_Error ) FT_Register_Extension(
129 FT_Extension_Class* clazz )
131 FT_Extension_Registry* registry;
135 return FT_Err_Invalid_Driver_Handle;
138 return FT_Err_Invalid_Argument;
140 registry = (FT_Extension_Registry*)driver->extensions;
143 FT_Int n = registry->num_extensions;
144 FT_Extension_Class* cur = registry->classes + n;
147 if ( n >= FT_MAX_EXTENSIONS )
148 return FT_Err_Too_Many_Extensions;
152 cur->offset = registry->cur_offset;
154 registry->num_extensions++;
155 registry->cur_offset +=
156 ( cur->size + FT_ALIGNMENT - 1 ) & -FT_ALIGNMENT;
158 FT_TRACE1(( "FT_Register_Extension: `%s' successfully registered\n",
166 /*************************************************************************/
169 /* FT_Get_Extension */
172 /* Queries an extension block by an extension ID string. */
175 /* face :: A handle to the face object. */
176 /* extension_id :: An ID string identifying the extension. */
179 /* extension_interface :: A generic pointer, usually pointing to a */
180 /* table of functions implementing the */
181 /* extension interface. */
184 /* A generic pointer to the extension block. */
186 FT_EXPORT_FUNC( void* ) FT_Get_Extension(
188 const char* extension_id,
189 void** extension_interface )
191 FT_Extension_Registry* registry;
194 if ( !face || !extension_id || !extension_interface )
197 registry = (FT_Extension_Registry*)face->driver->extensions;
198 if ( registry && face->extensions )
200 FT_Extension_Class* cur = registry->classes;
201 FT_Extension_Class* limit = cur + registry->num_extensions;
204 for ( ; cur < limit; cur++ )
205 if ( strcmp( cur->id, extension_id ) == 0 )
207 *extension_interface = cur->interface;
209 FT_TRACE1(( "FT_Get_Extension: got `%s'\n", extension_id ));
211 return (void*)((char*)face->extensions + cur->offset);
215 /* could not find the extension id */
217 FT_ERROR(( "FT_Get_Extension: couldn't find `%s'\n", extension_id ));
219 *extension_interface = 0;
225 /*************************************************************************/
228 /* FT_Destroy_Extensions */
231 /* Destroys all extensions within a face object. */
234 /* face :: A handle to the face object. */
237 /* FreeType error code. 0 means success. */
240 /* Called by the face object destructor. */
243 FT_Error FT_Destroy_Extensions( FT_Face face )
245 FT_Extension_Registry* registry;
249 registry = (FT_Extension_Registry*)face->driver->extensions;
250 if ( registry && face->extensions )
252 FT_Extension_Class* cur = registry->classes;
253 FT_Extension_Class* limit = cur + registry->num_extensions;
256 for ( ; cur < limit; cur++ )
258 char* ext = (char*)face->extensions + cur->offset;
261 cur->finalize( ext, face );
264 memory = face->driver->root.memory;
265 FREE( face->extensions );
272 /*************************************************************************/
275 /* FT_Create_Extensions */
278 /* Creates an extension object within a face object for all */
279 /* registered extensions. */
282 /* face :: A handle to the face object. */
285 /* FreeType error code. 0 means success. */
288 /* Called by the face object constructor. */
291 FT_Error FT_Create_Extensions( FT_Face face )
293 FT_Extension_Registry* registry;
298 face->extensions = 0;
300 /* load extensions registry; exit successfully if none is there */
302 registry = (FT_Extension_Registry*)face->driver->extensions;
306 memory = face->driver->root.memory;
307 if ( ALLOC( face->extensions, registry->cur_offset ) )
311 FT_Extension_Class* cur = registry->classes;
312 FT_Extension_Class* limit = cur + registry->num_extensions;
315 for ( ; cur < limit; cur++ )
317 char* ext = (char*)face->extensions + cur->offset;
321 error = cur->init( ext, face );