]> git.saurik.com Git - wxWidgets.git/blob - src/freetype/base/ftextend.c
applied SourceForge patch #419884 from Marc Newsam
[wxWidgets.git] / src / freetype / base / ftextend.c
1 /***************************************************************************/
2 /* */
3 /* ftextend.h */
4 /* */
5 /* FreeType extensions implementation (body). */
6 /* */
7 /* Copyright 1996-2000 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 /***************************************************************************/
17
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 /*************************************************************************/
26
27
28 #include <freetype/internal/ftextend.h>
29 #include <freetype/internal/ftdebug.h>
30
31
32 /*************************************************************************/
33 /* */
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. */
37 /* */
38 #undef FT_COMPONENT
39 #define FT_COMPONENT trace_extend
40
41
42 typedef struct FT_Extension_Registry_
43 {
44 FT_Int num_extensions;
45 FT_Long cur_offset;
46 FT_Extension_Class classes[FT_MAX_EXTENSIONS];
47
48 } FT_Extension_Registry;
49
50
51 /*************************************************************************/
52 /* */
53 /* <Function> */
54 /* FT_Init_Extensions */
55 /* */
56 /* <Description> */
57 /* Initializes the extension component. */
58 /* */
59 /* <InOut> */
60 /* driver :: A handle to the driver object. */
61 /* */
62 /* <Return> */
63 /* FreeType error code. 0 means success. */
64 /* */
65 LOCAL_FUNC
66 FT_Error FT_Init_Extensions( FT_Driver driver )
67 {
68 FT_Error error;
69 FT_Memory memory;
70 FT_Extension_Registry* registry;
71
72
73 memory = driver->root.library->memory;
74 if ( ALLOC( registry, sizeof ( *registry ) ) )
75 return error;
76
77 registry->num_extensions = 0;
78 registry->cur_offset = 0;
79 driver->extensions = registry;
80
81 FT_TRACE2(( "FT_Init_Extensions: success\n" ));
82
83 return FT_Err_Ok;
84 }
85
86
87 /*************************************************************************/
88 /* */
89 /* <Function> */
90 /* FT_Done_Extensions */
91 /* */
92 /* <Description> */
93 /* Finalizes the extension component. */
94 /* */
95 /* <InOut> */
96 /* driver :: A handle to the driver object. */
97 /* */
98 /* <Return> */
99 /* FreeType error code. 0 means success. */
100 /* */
101 LOCAL_FUNC
102 FT_Error FT_Done_Extensions( FT_Driver driver )
103 {
104 FT_Memory memory = driver->root.memory;
105
106
107 FREE( driver->extensions );
108 return FT_Err_Ok;
109 }
110
111
112 /*************************************************************************/
113 /* */
114 /* <Function> */
115 /* FT_Register_Extension */
116 /* */
117 /* <Description> */
118 /* Registers a new extension. */
119 /* */
120 /* <InOut> */
121 /* driver :: A handle to the driver object. */
122 /* class :: A pointer to a class describing the extension. */
123 /* */
124 /* <Return> */
125 /* FreeType error code. 0 means success. */
126 /* */
127 FT_EXPORT_FUNC( FT_Error ) FT_Register_Extension(
128 FT_Driver driver,
129 FT_Extension_Class* clazz )
130 {
131 FT_Extension_Registry* registry;
132
133
134 if ( !driver )
135 return FT_Err_Invalid_Driver_Handle;
136
137 if ( !clazz )
138 return FT_Err_Invalid_Argument;
139
140 registry = (FT_Extension_Registry*)driver->extensions;
141 if ( registry )
142 {
143 FT_Int n = registry->num_extensions;
144 FT_Extension_Class* cur = registry->classes + n;
145
146
147 if ( n >= FT_MAX_EXTENSIONS )
148 return FT_Err_Too_Many_Extensions;
149
150 *cur = *clazz;
151
152 cur->offset = registry->cur_offset;
153
154 registry->num_extensions++;
155 registry->cur_offset +=
156 ( cur->size + FT_ALIGNMENT - 1 ) & -FT_ALIGNMENT;
157
158 FT_TRACE1(( "FT_Register_Extension: `%s' successfully registered\n",
159 cur->id ));
160 }
161
162 return FT_Err_Ok;
163 }
164
165
166 /*************************************************************************/
167 /* */
168 /* <Function> */
169 /* FT_Get_Extension */
170 /* */
171 /* <Description> */
172 /* Queries an extension block by an extension ID string. */
173 /* */
174 /* <Input> */
175 /* face :: A handle to the face object. */
176 /* extension_id :: An ID string identifying the extension. */
177 /* */
178 /* <Output> */
179 /* extension_interface :: A generic pointer, usually pointing to a */
180 /* table of functions implementing the */
181 /* extension interface. */
182 /* */
183 /* <Return> */
184 /* A generic pointer to the extension block. */
185 /* */
186 FT_EXPORT_FUNC( void* ) FT_Get_Extension(
187 FT_Face face,
188 const char* extension_id,
189 void** extension_interface )
190 {
191 FT_Extension_Registry* registry;
192
193
194 if ( !face || !extension_id || !extension_interface )
195 return 0;
196
197 registry = (FT_Extension_Registry*)face->driver->extensions;
198 if ( registry && face->extensions )
199 {
200 FT_Extension_Class* cur = registry->classes;
201 FT_Extension_Class* limit = cur + registry->num_extensions;
202
203
204 for ( ; cur < limit; cur++ )
205 if ( strcmp( cur->id, extension_id ) == 0 )
206 {
207 *extension_interface = cur->interface;
208
209 FT_TRACE1(( "FT_Get_Extension: got `%s'\n", extension_id ));
210
211 return (void*)((char*)face->extensions + cur->offset);
212 }
213 }
214
215 /* could not find the extension id */
216
217 FT_ERROR(( "FT_Get_Extension: couldn't find `%s'\n", extension_id ));
218
219 *extension_interface = 0;
220
221 return 0;
222 }
223
224
225 /*************************************************************************/
226 /* */
227 /* <Function> */
228 /* FT_Destroy_Extensions */
229 /* */
230 /* <Description> */
231 /* Destroys all extensions within a face object. */
232 /* */
233 /* <InOut> */
234 /* face :: A handle to the face object. */
235 /* */
236 /* <Return> */
237 /* FreeType error code. 0 means success. */
238 /* */
239 /* <Note> */
240 /* Called by the face object destructor. */
241 /* */
242 LOCAL_FUNC
243 FT_Error FT_Destroy_Extensions( FT_Face face )
244 {
245 FT_Extension_Registry* registry;
246 FT_Memory memory;
247
248
249 registry = (FT_Extension_Registry*)face->driver->extensions;
250 if ( registry && face->extensions )
251 {
252 FT_Extension_Class* cur = registry->classes;
253 FT_Extension_Class* limit = cur + registry->num_extensions;
254
255
256 for ( ; cur < limit; cur++ )
257 {
258 char* ext = (char*)face->extensions + cur->offset;
259
260 if ( cur->finalize )
261 cur->finalize( ext, face );
262 }
263
264 memory = face->driver->root.memory;
265 FREE( face->extensions );
266 }
267
268 return FT_Err_Ok;
269 }
270
271
272 /*************************************************************************/
273 /* */
274 /* <Function> */
275 /* FT_Create_Extensions */
276 /* */
277 /* <Description> */
278 /* Creates an extension object within a face object for all */
279 /* registered extensions. */
280 /* */
281 /* <InOut> */
282 /* face :: A handle to the face object. */
283 /* */
284 /* <Return> */
285 /* FreeType error code. 0 means success. */
286 /* */
287 /* <Note> */
288 /* Called by the face object constructor. */
289 /* */
290 LOCAL_FUNC
291 FT_Error FT_Create_Extensions( FT_Face face )
292 {
293 FT_Extension_Registry* registry;
294 FT_Memory memory;
295 FT_Error error;
296
297
298 face->extensions = 0;
299
300 /* load extensions registry; exit successfully if none is there */
301
302 registry = (FT_Extension_Registry*)face->driver->extensions;
303 if ( !registry )
304 return FT_Err_Ok;
305
306 memory = face->driver->root.memory;
307 if ( ALLOC( face->extensions, registry->cur_offset ) )
308 return error;
309
310 {
311 FT_Extension_Class* cur = registry->classes;
312 FT_Extension_Class* limit = cur + registry->num_extensions;
313
314
315 for ( ; cur < limit; cur++ )
316 {
317 char* ext = (char*)face->extensions + cur->offset;
318
319 if ( cur->init )
320 {
321 error = cur->init( ext, face );
322 if ( error )
323 break;
324 }
325 }
326 }
327
328 return error;
329 }
330
331
332 /* END */