1 /***************************************************************************/
2 /* */
3 /* ftextend.c */
4 /* */
5 /* FreeType extensions implementation (body). */
6 /* */
7 /* Copyright 1996-2001 by */
8 /* David Turner, Robert Wilhelm, and Werner Lemberg. */
9 /* */
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. */
15 /* */
16 /***************************************************************************/
18 /*************************************************************************/
19 /* */
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 */
23 /* API. */
24 /* */
25 /*************************************************************************/
28 #include <ft2build.h>
29 #include FT_INTERNAL_EXTEND_H
30 #include FT_INTERNAL_DEBUG_H
33 /*************************************************************************/
34 /* */
35 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
36 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
37 /* messages during execution. */
38 /* */
39 #undef FT_COMPONENT
40 #define FT_COMPONENT trace_extend
43 typedef struct FT_Extension_Registry_
44 {
45 FT_Int num_extensions;
46 FT_Long cur_offset;
47 FT_Extension_Class classes[FT_MAX_EXTENSIONS];
49 } FT_Extension_Registry;
52 /*************************************************************************/
53 /* */
54 /* <Function> */
55 /* FT_Init_Extensions */
56 /* */
57 /* <Description> */
58 /* Initializes the extension component. */
59 /* */
60 /* <InOut> */
61 /* driver :: A handle to the driver object. */
62 /* */
63 /* <Return> */
64 /* FreeType error code. 0 means success. */
65 /* */
66 FT_LOCAL_DEF FT_Error
67 FT_Init_Extensions( FT_Driver driver )
68 {
69 FT_Error error;
70 FT_Memory memory;
71 FT_Extension_Registry* registry;
74 memory = driver->root.library->memory;
75 if ( ALLOC( registry, sizeof ( *registry ) ) )
76 return error;
78 registry->num_extensions = 0;
79 registry->cur_offset = 0;
80 driver->extensions = registry;
82 FT_TRACE2(( "FT_Init_Extensions: success\n" ));
84 return FT_Err_Ok;
85 }
88 /*************************************************************************/
89 /* */
90 /* <Function> */
91 /* FT_Done_Extensions */
92 /* */
93 /* <Description> */
94 /* Finalizes the extension component. */
95 /* */
96 /* <InOut> */
97 /* driver :: A handle to the driver object. */
98 /* */
99 /* <Return> */
100 /* FreeType error code. 0 means success. */
101 /* */
102 FT_LOCAL_DEF FT_Error
103 FT_Done_Extensions( FT_Driver driver )
104 {
105 FT_Memory memory = driver->root.memory;
108 FREE( driver->extensions );
109 return FT_Err_Ok;
110 }
113 /* documentation is in ftextend.h */
115 FT_EXPORT_DEF( FT_Error )
116 FT_Register_Extension( FT_Driver driver,
117 FT_Extension_Class* clazz )
118 {
119 FT_Extension_Registry* registry;
122 if ( !driver )
123 return FT_Err_Invalid_Driver_Handle;
125 if ( !clazz )
126 return FT_Err_Invalid_Argument;
128 registry = (FT_Extension_Registry*)driver->extensions;
129 if ( registry )
130 {
131 FT_Int n = registry->num_extensions;
132 FT_Extension_Class* cur = registry->classes + n;
135 if ( n >= FT_MAX_EXTENSIONS )
136 return FT_Err_Too_Many_Extensions;
138 *cur = *clazz;
140 cur->offset = registry->cur_offset;
142 registry->num_extensions++;
143 registry->cur_offset +=
144 ( cur->size + FT_ALIGNMENT - 1 ) & -FT_ALIGNMENT;
146 FT_TRACE1(( "FT_Register_Extension: `%s' successfully registered\n",
147 cur->id ));
148 }
150 return FT_Err_Ok;
151 }
154 /* documentation is in ftextend.h */
156 FT_EXPORT_DEF( void* )
157 FT_Get_Extension( FT_Face face,
158 const char* extension_id,
159 void** extension_interface )
160 {
161 FT_Extension_Registry* registry;
164 if ( !face || !extension_id || !extension_interface )
165 return 0;
167 registry = (FT_Extension_Registry*)face->driver->extensions;
168 if ( registry && face->extensions )
169 {
170 FT_Extension_Class* cur = registry->classes;
171 FT_Extension_Class* limit = cur + registry->num_extensions;
174 for ( ; cur < limit; cur++ )
175 if ( strcmp( cur->id, extension_id ) == 0 )
176 {
177 *extension_interface = cur->interface;
179 FT_TRACE1(( "FT_Get_Extension: got `%s'\n", extension_id ));
181 return (void*)((char*)face->extensions + cur->offset);
182 }
183 }
185 /* could not find the extension id */
187 FT_ERROR(( "FT_Get_Extension: couldn't find `%s'\n", extension_id ));
189 *extension_interface = 0;
191 return 0;
192 }
195 /*************************************************************************/
196 /* */
197 /* <Function> */
198 /* FT_Destroy_Extensions */
199 /* */
200 /* <Description> */
201 /* Destroys all extensions within a face object. */
202 /* */
203 /* <InOut> */
204 /* face :: A handle to the face object. */
205 /* */
206 /* <Return> */
207 /* FreeType error code. 0 means success. */
208 /* */
209 /* <Note> */
210 /* Called by the face object destructor. */
211 /* */
212 FT_LOCAL_DEF FT_Error
213 FT_Destroy_Extensions( FT_Face face )
214 {
215 FT_Extension_Registry* registry;
216 FT_Memory memory;
219 registry = (FT_Extension_Registry*)face->driver->extensions;
220 if ( registry && face->extensions )
221 {
222 FT_Extension_Class* cur = registry->classes;
223 FT_Extension_Class* limit = cur + registry->num_extensions;
226 for ( ; cur < limit; cur++ )
227 {
228 char* ext = (char*)face->extensions + cur->offset;
230 if ( cur->finalize )
231 cur->finalize( ext, face );
232 }
234 memory = face->driver->root.memory;
235 FREE( face->extensions );
236 }
238 return FT_Err_Ok;
239 }
242 /*************************************************************************/
243 /* */
244 /* <Function> */
245 /* FT_Create_Extensions */
246 /* */
247 /* <Description> */
248 /* Creates an extension object within a face object for all */
249 /* registered extensions. */
250 /* */
251 /* <InOut> */
252 /* face :: A handle to the face object. */
253 /* */
254 /* <Return> */
255 /* FreeType error code. 0 means success. */
256 /* */
257 /* <Note> */
258 /* Called by the face object constructor. */
259 /* */
260 FT_LOCAL_DEF FT_Error
261 FT_Create_Extensions( FT_Face face )
262 {
263 FT_Extension_Registry* registry;
264 FT_Memory memory;
265 FT_Error error;
268 face->extensions = 0;
270 /* load extensions registry; exit successfully if none is there */
272 registry = (FT_Extension_Registry*)face->driver->extensions;
273 if ( !registry )
274 return FT_Err_Ok;
276 memory = face->driver->root.memory;
277 if ( ALLOC( face->extensions, registry->cur_offset ) )
278 return error;
280 {
281 FT_Extension_Class* cur = registry->classes;
282 FT_Extension_Class* limit = cur + registry->num_extensions;
285 for ( ; cur < limit; cur++ )
286 {
287 char* ext = (char*)face->extensions + cur->offset;
289 if ( cur->init )
290 {
291 error = cur->init( ext, face );
292 if ( error )
293 break;
294 }
295 }
296 }
298 return error;
299 }
302 /* END */