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
);