blob: 1df4ec7a10bb5cd3618cc66d2dfb56e1ae3dd92b [file] [log] [blame]
David Turnerd2b1f351999-12-16 23:11:37 +00001/***************************************************************************/
2/* */
3/* ftobjs.c */
4/* */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00005/* The FreeType private base classes (base). */
David Turnerd2b1f351999-12-16 23:11:37 +00006/* */
Werner Lemberg7880dd62000-01-10 17:19:45 +00007/* Copyright 1996-2000 by */
Werner Lemberg4e6dd852000-06-05 05:26:15 +00008/* David Turner, Robert Wilhelm, and Werner Lemberg. */
David Turnerd2b1f351999-12-16 23:11:37 +00009/* */
Werner Lemberg4e6dd852000-06-05 05:26:15 +000010/* This file is part of the FreeType project, and may only be used, */
11/* modified, and distributed under the terms of the FreeType project */
David Turnerd2b1f351999-12-16 23:11:37 +000012/* 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
Werner Lemberga3b6c6c2000-05-31 06:55:12 +000018
David Turnerefce08d2000-05-11 18:23:52 +000019#include <freetype/internal/ftobjs.h>
20#include <freetype/internal/ftlist.h>
21#include <freetype/internal/ftdebug.h>
22#include <freetype/internal/ftstream.h>
David Turnerd2b1f351999-12-16 23:11:37 +000023
David Turnerefce08d2000-05-11 18:23:52 +000024#include <freetype/tttables.h>
Werner Lemberg7880dd62000-01-10 17:19:45 +000025
Werner Lemberga929ba92000-06-25 06:47:11 +000026#include <string.h> /* for strcmp() */
27
Werner Lemberga3b6c6c2000-05-31 06:55:12 +000028
David Turnerd2b1f351999-12-16 23:11:37 +000029 /*************************************************************************/
30 /*************************************************************************/
31 /*************************************************************************/
32 /**** ****/
33 /**** ****/
34 /**** M E M O R Y ****/
35 /**** ****/
36 /**** ****/
37 /*************************************************************************/
38 /*************************************************************************/
39 /*************************************************************************/
40
41 /*************************************************************************/
42 /* */
43 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
Werner Lemberg7880dd62000-01-10 17:19:45 +000044 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
David Turnerd2b1f351999-12-16 23:11:37 +000045 /* messages during execution. */
46 /* */
47#undef FT_COMPONENT
48#define FT_COMPONENT trace_memory
49
50
51 /*************************************************************************/
52 /* */
53 /* <Function> */
54 /* FT_Alloc */
55 /* */
56 /* <Description> */
57 /* Allocates a new block of memory. The returned area is always */
Werner Lemberg547a2522000-02-16 08:23:58 +000058 /* zero-filled; this is a strong convention in many FreeType parts. */
David Turnerd2b1f351999-12-16 23:11:37 +000059 /* */
60 /* <Input> */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +000061 /* memory :: A handle to a given `memory object' which handles */
62 /* allocation. */
David Turnerd2b1f351999-12-16 23:11:37 +000063 /* */
64 /* size :: The size in bytes of the block to allocate. */
65 /* */
66 /* <Output> */
67 /* P :: A pointer to the fresh new block. It should be set to */
68 /* NULL if `size' is 0, or in case of error. */
69 /* */
70 /* <Return> */
71 /* FreeType error code. 0 means success. */
72 /* */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +000073 BASE_FUNC( FT_Error ) FT_Alloc( FT_Memory memory,
74 FT_Long size,
75 void** P )
David Turnerd2b1f351999-12-16 23:11:37 +000076 {
77 FT_Assert( P != 0 );
78
Werner Lemberg7880dd62000-01-10 17:19:45 +000079 if ( size > 0 )
David Turnerd2b1f351999-12-16 23:11:37 +000080 {
81 *P = memory->alloc( memory, size );
Werner Lemberg7880dd62000-01-10 17:19:45 +000082 if ( !*P )
David Turnerd2b1f351999-12-16 23:11:37 +000083 {
Werner Lemberga3b6c6c2000-05-31 06:55:12 +000084 FT_ERROR(( "FT_Alloc:" ));
Werner Lemberg7880dd62000-01-10 17:19:45 +000085 FT_ERROR(( " Out of memory? (%ld requested)\n",
David Turnerd2b1f351999-12-16 23:11:37 +000086 size ));
87
88 return FT_Err_Out_Of_Memory;
89 }
90 MEM_Set( *P, 0, size );
91 }
92 else
93 *P = NULL;
94
Werner Lemberg56177262000-06-03 21:59:44 +000095 FT_TRACE7(( "FT_Alloc:" ));
96 FT_TRACE7(( " size = %ld, block = 0x%08p, ref = 0x%08p\n",
David Turner51179f02000-05-18 16:18:05 +000097 size, *P, P ));
David Turnerd2b1f351999-12-16 23:11:37 +000098
99 return FT_Err_Ok;
100 }
101
102
103 /*************************************************************************/
104 /* */
105 /* <Function> */
106 /* FT_Realloc */
107 /* */
108 /* <Description> */
109 /* Reallocates a block of memory pointed to by `*P' to `Size' bytes */
110 /* from the heap, possibly changing `*P'. */
111 /* */
112 /* <Input> */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +0000113 /* memory :: A handle to a given `memory object' which handles */
114 /* reallocation. */
David Turnerd2b1f351999-12-16 23:11:37 +0000115 /* */
Werner Lemberg547a2522000-02-16 08:23:58 +0000116 /* current :: The current block size in bytes. */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +0000117 /* */
Werner Lemberg547a2522000-02-16 08:23:58 +0000118 /* size :: The new block size in bytes. */
David Turnerd2b1f351999-12-16 23:11:37 +0000119 /* */
120 /* <InOut> */
Werner Lemberg547a2522000-02-16 08:23:58 +0000121 /* P :: A pointer to the fresh new block. It should be set to */
122 /* NULL if `size' is 0, or in case of error. */
David Turnerd2b1f351999-12-16 23:11:37 +0000123 /* */
124 /* <Return> */
125 /* FreeType error code. 0 means success. */
126 /* */
127 /* <Note> */
Werner Lemberg547a2522000-02-16 08:23:58 +0000128 /* All callers of FT_Realloc() _must_ provide the current block size */
David Turnerd2b1f351999-12-16 23:11:37 +0000129 /* as well as the new one. */
130 /* */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +0000131 BASE_FUNC( FT_Error ) FT_Realloc( FT_Memory memory,
132 FT_Long current,
133 FT_Long size,
134 void** P )
David Turnerd2b1f351999-12-16 23:11:37 +0000135 {
136 void* Q;
137
Werner Lemberg7880dd62000-01-10 17:19:45 +0000138
David Turnerd2b1f351999-12-16 23:11:37 +0000139 FT_Assert( P != 0 );
140
141 /* if the original pointer is NULL, call FT_Alloc() */
142 if ( !*P )
143 return FT_Alloc( memory, size, P );
144
145 /* if the new block if zero-sized, clear the current one */
146 if ( size <= 0 )
147 {
148 FT_Free( memory, P );
149 return FT_Err_Ok;
150 }
151
152 Q = memory->realloc( memory, current, size, *P );
Werner Lemberg7880dd62000-01-10 17:19:45 +0000153 if ( !Q )
154 goto Fail;
David Turnerd2b1f351999-12-16 23:11:37 +0000155
156 *P = Q;
157 return FT_Err_Ok;
158
159 Fail:
Werner Lemberga3b6c6c2000-05-31 06:55:12 +0000160 FT_ERROR(( "FT_Realloc:" ));
Werner Lemberg7880dd62000-01-10 17:19:45 +0000161 FT_ERROR(( " Failed (current %ld, requested %ld)\n",
David Turnerd2b1f351999-12-16 23:11:37 +0000162 current, size ));
163 return FT_Err_Out_Of_Memory;
164 }
165
166
167 /*************************************************************************/
168 /* */
169 /* <Function> */
170 /* FT_Free */
171 /* */
172 /* <Description> */
173 /* Releases a given block of memory allocated through FT_Alloc(). */
174 /* */
175 /* <Input> */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +0000176 /* memory :: A handle to a given `memory object' which handles */
177 /* memory deallocation */
David Turnerd2b1f351999-12-16 23:11:37 +0000178 /* */
179 /* P :: This is the _address_ of a _pointer_ which points to the */
180 /* allocated block. It is always set to NULL on exit. */
181 /* */
182 /* <Return> */
183 /* FreeType error code. 0 means success. */
184 /* */
185 /* <Note> */
186 /* If P or *P are NULL, this function should return successfully. */
187 /* This is a strong convention within all of FreeType and its */
188 /* drivers. */
189 /* */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +0000190 BASE_FUNC( void ) FT_Free( FT_Memory memory,
191 void** P )
David Turnerd2b1f351999-12-16 23:11:37 +0000192 {
Werner Lemberg56177262000-06-03 21:59:44 +0000193 FT_TRACE7(( "FT_Free:" ));
194 FT_TRACE7(( " Freeing block 0x%08p, ref 0x%08p\n",
Werner Lemberga3b6c6c2000-05-31 06:55:12 +0000195 P, P ? *P : (void*)0 ));
David Turnerd2b1f351999-12-16 23:11:37 +0000196
Werner Lemberge35cac62000-06-11 03:46:57 +0000197 if ( P && *P )
David Turnerd2b1f351999-12-16 23:11:37 +0000198 {
199 memory->free( memory, *P );
200 *P = 0;
201 }
202 }
203
Werner Lembergdeb4e982000-06-29 03:14:25 +0000204
David Turnerf0df85b2000-06-22 00:17:42 +0000205 /*************************************************************************/
206 /*************************************************************************/
207 /*************************************************************************/
208 /**** ****/
209 /**** ****/
210 /**** S T R E A M ****/
211 /**** ****/
212 /**** ****/
213 /*************************************************************************/
214 /*************************************************************************/
215 /*************************************************************************/
216
Werner Lemberg7880dd62000-01-10 17:19:45 +0000217
Werner Lemberg547a2522000-02-16 08:23:58 +0000218 /*************************************************************************/
219 /* */
220 /* <Function> */
221 /* ft_new_input_stream */
222 /* */
223 /* <Description> */
224 /* Creates a new input stream object from an FT_Open_Args structure. */
225 /* */
Werner Lemberg2fbf7e42000-06-02 00:01:14 +0000226 /* <Note> */
227 /* The function expects a valid `astream' parameter. */
Werner Lembergdeb4e982000-06-29 03:14:25 +0000228 /* */
David Turner7663f222000-02-13 13:37:38 +0000229 static
Werner Lemberg547a2522000-02-16 08:23:58 +0000230 FT_Error ft_new_input_stream( FT_Library library,
231 FT_Open_Args* args,
Werner Lemberga3b6c6c2000-05-31 06:55:12 +0000232 FT_Stream* astream )
David Turner7663f222000-02-13 13:37:38 +0000233 {
Werner Lemberg547a2522000-02-16 08:23:58 +0000234 FT_Error error;
235 FT_Memory memory;
236 FT_Stream stream;
237
Werner Lemberga3b6c6c2000-05-31 06:55:12 +0000238
Werner Lemberg2fbf7e42000-06-02 00:01:14 +0000239 if ( !library )
240 return FT_Err_Invalid_Library_Handle;
241
242 if ( !args )
243 return FT_Err_Invalid_Argument;
244
David Turner37379e22000-03-28 11:22:31 +0000245 *astream = 0;
246 memory = library->memory;
Werner Lemberg547a2522000-02-16 08:23:58 +0000247 if ( ALLOC( stream, sizeof ( *stream ) ) )
David Turner37379e22000-03-28 11:22:31 +0000248 goto Exit;
David Turnere49ab252000-05-16 23:44:38 +0000249
David Turner7663f222000-02-13 13:37:38 +0000250 stream->memory = memory;
David Turnere49ab252000-05-16 23:44:38 +0000251
David Turner4f2c5542000-05-12 10:19:41 +0000252 /* now, look at the stream flags */
253 if ( args->flags & ft_open_memory )
Just van Rossumd35aea72000-03-02 01:07:50 +0000254 {
David Turner4f2c5542000-05-12 10:19:41 +0000255 error = 0;
256 FT_New_Memory_Stream( library,
257 args->memory_base,
258 args->memory_size,
259 stream );
260 }
Werner Lemberga3b6c6c2000-05-31 06:55:12 +0000261 else if ( args->flags & ft_open_pathname )
David Turner4f2c5542000-05-12 10:19:41 +0000262 {
263 error = FT_New_Stream( args->pathname, stream );
264 stream->pathname.pointer = args->pathname;
265 }
Werner Lemberga3b6c6c2000-05-31 06:55:12 +0000266 else if ( args->flags & ft_open_stream && args->stream )
David Turner4f2c5542000-05-12 10:19:41 +0000267 {
268 *stream = *(args->stream);
269 stream->memory = memory;
270 }
271 else
David Turner4f2c5542000-05-12 10:19:41 +0000272 error = FT_Err_Invalid_Argument;
David Turnere49ab252000-05-16 23:44:38 +0000273
Werner Lemberg547a2522000-02-16 08:23:58 +0000274 if ( error )
275 FREE( stream );
David Turnere49ab252000-05-16 23:44:38 +0000276
David Turner7663f222000-02-13 13:37:38 +0000277 *astream = stream;
Werner Lemberga3b6c6c2000-05-31 06:55:12 +0000278
David Turner37379e22000-03-28 11:22:31 +0000279 Exit:
David Turner7663f222000-02-13 13:37:38 +0000280 return error;
281 }
282
283
Werner Lemberg547a2522000-02-16 08:23:58 +0000284 /*************************************************************************/
285 /* */
286 /* <Function> */
David Turnera8bcdf82000-05-02 10:51:41 +0000287 /* FT_Done_Stream */
Werner Lemberg547a2522000-02-16 08:23:58 +0000288 /* */
289 /* <Description> */
290 /* Closes and destroys a stream object. */
291 /* */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +0000292 /* <Input> */
293 /* stream :: The stream to be closed and destroyed. */
294 /* */
295 FT_EXPORT_FUNC( void ) FT_Done_Stream( FT_Stream stream )
David Turnera8bcdf82000-05-02 10:51:41 +0000296 {
Werner Lemberg2fbf7e42000-06-02 00:01:14 +0000297 if ( stream && stream->close )
David Turnera8bcdf82000-05-02 10:51:41 +0000298 stream->close( stream );
299 }
300
301
David Turner7663f222000-02-13 13:37:38 +0000302 static
Werner Lemberg547a2522000-02-16 08:23:58 +0000303 void ft_done_stream( FT_Stream* astream )
David Turner7663f222000-02-13 13:37:38 +0000304 {
305 FT_Stream stream = *astream;
306 FT_Memory memory = stream->memory;
Werner Lemberg547a2522000-02-16 08:23:58 +0000307
Werner Lemberga3b6c6c2000-05-31 06:55:12 +0000308
Werner Lemberg547a2522000-02-16 08:23:58 +0000309 if ( stream->close )
David Turner7663f222000-02-13 13:37:38 +0000310 stream->close( stream );
Just van Rossum7eef5362000-03-05 16:07:58 +0000311
David Turner7663f222000-02-13 13:37:38 +0000312 FREE( stream );
313 *astream = 0;
314 }
315
Werner Lemberga3b6c6c2000-05-31 06:55:12 +0000316
Werner Lembergeb81e372000-06-03 06:03:11 +0000317#undef FT_COMPONENT
318#define FT_COMPONENT trace_objs
319
Werner Lembergdeb4e982000-06-29 03:14:25 +0000320
David Turnerf0df85b2000-06-22 00:17:42 +0000321 /*************************************************************************/
322 /*************************************************************************/
323 /*************************************************************************/
324 /**** ****/
325 /**** ****/
326 /**** G L Y P H L O A D E R ****/
327 /**** ****/
328 /**** ****/
329 /*************************************************************************/
330 /*************************************************************************/
331 /*************************************************************************/
332
David Turnerf0df85b2000-06-22 00:17:42 +0000333
Werner Lemberga929ba92000-06-25 06:47:11 +0000334 /*************************************************************************/
335 /* */
336 /* The glyph loader is a simple object which is used to load a set of */
337 /* glyphs easily. It is critical for the correct loading of composites. */
338 /* */
339 /* Ideally, one can see it as a stack of abstract `glyph' objects. */
340 /* */
341 /* loader.base Is really the bottom of the stack. It describes a */
342 /* single glyph image made of the juxtaposition of */
343 /* several glyphs (those `in the stack'). */
344 /* */
345 /* loader.current Describes the top of the stack, on which a new */
346 /* glyph can be loaded. */
347 /* */
348 /* Rewind Clears the stack. */
349 /* Prepare Set up `loader.current' for addition of a new glyph */
350 /* image. */
351 /* Add Add the `current' glyph image to the `base' one, */
352 /* and prepare for another one. */
353 /* */
354 /* The glyph loader is now a base object. Each driver used to */
355 /* re-implement it in one way or the other, which wasted code and */
356 /* energy. */
357 /* */
358 /*************************************************************************/
359
360
361 /* create a new glyph loader */
362 BASE_FUNC( FT_Error ) FT_GlyphLoader_New( FT_Memory memory,
363 FT_GlyphLoader** aloader )
David Turnerf0df85b2000-06-22 00:17:42 +0000364 {
365 FT_GlyphLoader* loader;
366 FT_Error error;
367
Werner Lemberga929ba92000-06-25 06:47:11 +0000368
369 if ( !ALLOC( loader, sizeof ( *loader ) ) )
David Turnerf0df85b2000-06-22 00:17:42 +0000370 {
371 loader->memory = memory;
372 *aloader = loader;
373 }
374 return error;
375 }
376
377
Werner Lemberga929ba92000-06-25 06:47:11 +0000378 /* rewind the glyph loader - reset counters to 0 */
379 BASE_FUNC( void ) FT_GlyphLoader_Rewind( FT_GlyphLoader* loader )
David Turnerf0df85b2000-06-22 00:17:42 +0000380 {
381 FT_GlyphLoad* base = &loader->base;
382 FT_GlyphLoad* current = &loader->current;
383
Werner Lemberga929ba92000-06-25 06:47:11 +0000384
David Turnerf0df85b2000-06-22 00:17:42 +0000385 base->outline.n_points = 0;
386 base->outline.n_contours = 0;
387 base->num_subglyphs = 0;
388
389 *current = *base;
390 }
391
392
Werner Lemberga929ba92000-06-25 06:47:11 +0000393 /* reset the glyph loader, frees all allocated tables */
394 /* and starts from zero */
395 BASE_FUNC( void ) FT_GlyphLoader_Reset( FT_GlyphLoader* loader )
David Turnerf0df85b2000-06-22 00:17:42 +0000396 {
397 FT_Memory memory = loader->memory;
398
Werner Lemberga929ba92000-06-25 06:47:11 +0000399
David Turnerf0df85b2000-06-22 00:17:42 +0000400 FREE( loader->base.outline.points );
401 FREE( loader->base.outline.tags );
402 FREE( loader->base.outline.contours );
403 FREE( loader->base.extra_points );
404 FREE( loader->base.subglyphs );
405
406 loader->max_points = 0;
407 loader->max_contours = 0;
408 loader->max_subglyphs = 0;
409
410 FT_GlyphLoader_Rewind( loader );
411 }
412
413
Werner Lemberga929ba92000-06-25 06:47:11 +0000414 /* delete a glyph loader */
415 BASE_FUNC( void ) FT_GlyphLoader_Done( FT_GlyphLoader* loader )
David Turnerf0df85b2000-06-22 00:17:42 +0000416 {
Werner Lemberga929ba92000-06-25 06:47:11 +0000417 if ( loader )
David Turnerf0df85b2000-06-22 00:17:42 +0000418 {
419 FT_Memory memory = loader->memory;
420
Werner Lemberga929ba92000-06-25 06:47:11 +0000421
Werner Lembergdeb4e982000-06-29 03:14:25 +0000422 FT_GlyphLoader_Reset( loader );
David Turnerf0df85b2000-06-22 00:17:42 +0000423 FREE( loader );
424 }
425 }
426
427
Werner Lemberga929ba92000-06-25 06:47:11 +0000428 /* re-adjust the `current' outline fields */
Werner Lembergdeb4e982000-06-29 03:14:25 +0000429 static
430 void FT_GlyphLoader_Adjust_Points( FT_GlyphLoader* loader )
David Turnerf0df85b2000-06-22 00:17:42 +0000431 {
432 FT_Outline* base = &loader->base.outline;
433 FT_Outline* current = &loader->current.outline;
434
Werner Lemberga929ba92000-06-25 06:47:11 +0000435
David Turnerf0df85b2000-06-22 00:17:42 +0000436 current->points = base->points + base->n_points;
437 current->tags = base->tags + base->n_points;
438 current->contours = base->contours + base->n_contours;
Werner Lembergdeb4e982000-06-29 03:14:25 +0000439
David Turnerf0df85b2000-06-22 00:17:42 +0000440 /* handle extra points table - if any */
Werner Lemberga929ba92000-06-25 06:47:11 +0000441 if ( loader->use_extra )
442 loader->current.extra_points =
443 loader->base.extra_points + base->n_points;
David Turnerf0df85b2000-06-22 00:17:42 +0000444 }
445
446
Werner Lembergdeb4e982000-06-29 03:14:25 +0000447 BASE_FUNC( FT_Error ) FT_GlyphLoader_Create_Extra(
448 FT_GlyphLoader* loader )
David Turnerf0df85b2000-06-22 00:17:42 +0000449 {
450 FT_Error error;
451 FT_Memory memory = loader->memory;
Werner Lemberga929ba92000-06-25 06:47:11 +0000452
Werner Lembergdeb4e982000-06-29 03:14:25 +0000453
David Turnerf0df85b2000-06-22 00:17:42 +0000454 if ( !ALLOC_ARRAY( loader->base.extra_points,
455 loader->max_points, FT_Vector ) )
456 {
457 loader->use_extra = 1;
Werner Lemberga929ba92000-06-25 06:47:11 +0000458 FT_GlyphLoader_Adjust_Points( loader );
David Turnerf0df85b2000-06-22 00:17:42 +0000459 }
460 return error;
461 }
462
463
Werner Lemberga929ba92000-06-25 06:47:11 +0000464 /* re-adjust the `current' subglyphs field */
Werner Lembergdeb4e982000-06-29 03:14:25 +0000465 static
466 void FT_GlyphLoader_Adjust_Subglyphs( FT_GlyphLoader* loader )
David Turnerf0df85b2000-06-22 00:17:42 +0000467 {
468 FT_GlyphLoad* base = &loader->base;
469 FT_GlyphLoad* current = &loader->current;
470
Werner Lemberga929ba92000-06-25 06:47:11 +0000471
David Turnerf0df85b2000-06-22 00:17:42 +0000472 current->subglyphs = base->subglyphs + base->num_subglyphs;
473 }
474
475
Werner Lemberga929ba92000-06-25 06:47:11 +0000476 /* Ensure that we can add `n_points' and `n_contours' to our glyph. this */
477 /* function reallocates its outline tables if necessary. Note that it */
478 /* DOESN'T change the number of points within the loader! */
Werner Lembergdeb4e982000-06-29 03:14:25 +0000479 /* */
Werner Lemberga929ba92000-06-25 06:47:11 +0000480 BASE_FUNC( FT_Error ) FT_GlyphLoader_Check_Points(
481 FT_GlyphLoader* loader,
482 FT_UInt n_points,
483 FT_UInt n_contours )
David Turnerf0df85b2000-06-22 00:17:42 +0000484 {
485 FT_Memory memory = loader->memory;
486 FT_Error error = FT_Err_Ok;
487 FT_Outline* base = &loader->base.outline;
488 FT_Outline* current = &loader->current.outline;
489 FT_Bool adjust = 1;
490
Werner Lembergdeb4e982000-06-29 03:14:25 +0000491 FT_UInt new_max;
David Turnerf0df85b2000-06-22 00:17:42 +0000492
Werner Lemberga929ba92000-06-25 06:47:11 +0000493
David Turnerf0df85b2000-06-22 00:17:42 +0000494 /* check points & tags */
495 new_max = base->n_points + current->n_points + n_points;
Werner Lemberga929ba92000-06-25 06:47:11 +0000496 if ( new_max > loader->max_points )
David Turnerf0df85b2000-06-22 00:17:42 +0000497 {
Werner Lemberga929ba92000-06-25 06:47:11 +0000498 new_max = ( new_max + 7 ) & -8;
499 if ( REALLOC_ARRAY( base->points, base->n_points,
500 new_max, FT_Vector ) ||
501 REALLOC_ARRAY( base->tags, base->n_points,
502 new_max, FT_Byte ) )
David Turnerf0df85b2000-06-22 00:17:42 +0000503 goto Exit;
504
505 if ( loader->use_extra &&
Werner Lemberga929ba92000-06-25 06:47:11 +0000506 REALLOC_ARRAY( loader->base.extra_points, base->n_points,
507 new_max, FT_Vector ) )
David Turnerf0df85b2000-06-22 00:17:42 +0000508 goto Exit;
509
510 adjust = 1;
511 loader->max_points = new_max;
512 }
513
514 /* check contours */
515 new_max = base->n_contours + current->n_contours +
516 n_contours;
Werner Lemberga929ba92000-06-25 06:47:11 +0000517 if ( new_max > loader->max_contours )
David Turnerf0df85b2000-06-22 00:17:42 +0000518 {
Werner Lemberga929ba92000-06-25 06:47:11 +0000519 new_max = ( new_max + 3 ) & -4;
520 if ( REALLOC_ARRAY( base->contours, base->n_contours,
521 new_max, FT_Short ) )
David Turnerf0df85b2000-06-22 00:17:42 +0000522 goto Exit;
523
524 adjust = 1;
525 loader->max_contours = new_max;
526 }
527
Werner Lemberga929ba92000-06-25 06:47:11 +0000528 if ( adjust )
David Turnerf0df85b2000-06-22 00:17:42 +0000529 FT_GlyphLoader_Adjust_Points( loader );
530
531 Exit:
532 return error;
533 }
534
535
Werner Lemberga929ba92000-06-25 06:47:11 +0000536 /* Ensure that we can add `n_subglyphs' to our glyph. this function */
537 /* reallocates its subglyphs table if necessary. Note that it DOES */
538 /* NOT change the number of subglyphs within the loader! */
Werner Lembergdeb4e982000-06-29 03:14:25 +0000539 /* */
Werner Lemberga929ba92000-06-25 06:47:11 +0000540 BASE_FUNC( FT_Error ) FT_GlyphLoader_Check_Subglyphs(
541 FT_GlyphLoader* loader,
542 FT_UInt n_subs )
David Turnerf0df85b2000-06-22 00:17:42 +0000543 {
544 FT_Memory memory = loader->memory;
545 FT_Error error = FT_Err_Ok;
546 FT_UInt new_max;
547
548 FT_GlyphLoad* base = &loader->base;
549 FT_GlyphLoad* current = &loader->current;
550
Werner Lemberga929ba92000-06-25 06:47:11 +0000551
David Turnerf0df85b2000-06-22 00:17:42 +0000552 new_max = base->num_subglyphs + current->num_subglyphs + n_subs;
Werner Lemberga929ba92000-06-25 06:47:11 +0000553 if ( new_max > loader->max_subglyphs )
David Turnerf0df85b2000-06-22 00:17:42 +0000554 {
Werner Lemberga929ba92000-06-25 06:47:11 +0000555 new_max = ( new_max + 1 ) & -2;
556 if ( REALLOC_ARRAY( base->subglyphs, base->num_subglyphs,
557 new_max, FT_SubGlyph ) )
David Turnerf0df85b2000-06-22 00:17:42 +0000558 goto Exit;
559
560 loader->max_subglyphs = new_max;
561
562 FT_GlyphLoader_Adjust_Subglyphs( loader );
563 }
564
565 Exit:
566 return error;
567 }
568
569
Werner Lemberga929ba92000-06-25 06:47:11 +0000570 /* prepare loader for the addition of a new glyph on top of the base one */
571 BASE_FUNC( void ) FT_GlyphLoader_Prepare( FT_GlyphLoader* loader )
David Turnerf0df85b2000-06-22 00:17:42 +0000572 {
573 FT_GlyphLoad* current = &loader->current;
574
Werner Lemberga929ba92000-06-25 06:47:11 +0000575
David Turnerf0df85b2000-06-22 00:17:42 +0000576 current->outline.n_points = 0;
577 current->outline.n_contours = 0;
578 current->num_subglyphs = 0;
579
580 FT_GlyphLoader_Adjust_Points ( loader );
581 FT_GlyphLoader_Adjust_Subglyphs( loader );
582 }
583
584
Werner Lemberga929ba92000-06-25 06:47:11 +0000585 /* add current glyph to the base image - and prepare for another */
586 BASE_FUNC( void ) FT_GlyphLoader_Add( FT_GlyphLoader* loader )
David Turnerf0df85b2000-06-22 00:17:42 +0000587 {
588 FT_GlyphLoad* base = &loader->base;
589 FT_GlyphLoad* current = &loader->current;
590
591 FT_UInt n_curr_contours = current->outline.n_contours;
592 FT_UInt n_base_points = base->outline.n_points;
593 FT_UInt n;
594
Werner Lemberga929ba92000-06-25 06:47:11 +0000595
David Turnerf0df85b2000-06-22 00:17:42 +0000596 base->outline.n_points += current->outline.n_points;
597 base->outline.n_contours += current->outline.n_contours;
598 base->num_subglyphs += current->num_subglyphs;
599
600 /* adjust contours count in newest outline */
601 for ( n = 0; n < n_curr_contours; n++ )
602 current->outline.contours[n] += n_base_points;
603
604 /* prepare for another new glyph image */
605 FT_GlyphLoader_Prepare( loader );
606 }
607
608
Werner Lembergdeb4e982000-06-29 03:14:25 +0000609 BASE_FUNC( FT_Error ) FT_GlyphLoader_Copy_Points( FT_GlyphLoader* target,
610 FT_GlyphLoader* source )
David Turnerf0df85b2000-06-22 00:17:42 +0000611 {
612 FT_Error error;
613 FT_UInt num_points = source->base.outline.n_points;
614 FT_UInt num_contours = source->base.outline.n_contours;
Werner Lemberga929ba92000-06-25 06:47:11 +0000615
Werner Lembergdeb4e982000-06-29 03:14:25 +0000616
David Turnerf0df85b2000-06-22 00:17:42 +0000617 error = FT_GlyphLoader_Check_Points( target, num_points, num_contours );
Werner Lemberga929ba92000-06-25 06:47:11 +0000618 if ( !error )
David Turnerf0df85b2000-06-22 00:17:42 +0000619 {
620 FT_Outline* out = &target->base.outline;
621 FT_Outline* in = &source->base.outline;
Werner Lemberga929ba92000-06-25 06:47:11 +0000622
Werner Lembergdeb4e982000-06-29 03:14:25 +0000623
Werner Lemberga929ba92000-06-25 06:47:11 +0000624 MEM_Copy( out->points, in->points,
625 num_points * sizeof ( FT_Vector ) );
626 MEM_Copy( out->tags, in->tags,
627 num_points * sizeof ( char ) );
628 MEM_Copy( out->contours, in->contours,
629 num_contours * sizeof ( short ) );
Werner Lembergdeb4e982000-06-29 03:14:25 +0000630
Werner Lemberga929ba92000-06-25 06:47:11 +0000631 /* do we need to copy the extra points? */
632 if ( target->use_extra && source->use_extra )
David Turnerf0df85b2000-06-22 00:17:42 +0000633 MEM_Copy( target->base.extra_points, source->base.extra_points,
Werner Lemberga929ba92000-06-25 06:47:11 +0000634 num_points * sizeof ( FT_Vector ) );
Werner Lembergdeb4e982000-06-29 03:14:25 +0000635
David Turnerf0df85b2000-06-22 00:17:42 +0000636 out->n_points = num_points;
637 out->n_contours = num_contours;
Werner Lembergdeb4e982000-06-29 03:14:25 +0000638
David Turnerf0df85b2000-06-22 00:17:42 +0000639 FT_GlyphLoader_Adjust_Points( target );
640 }
Werner Lemberga929ba92000-06-25 06:47:11 +0000641
Werner Lembergdeb4e982000-06-29 03:14:25 +0000642 return error;
643 }
David Turnerf0df85b2000-06-22 00:17:42 +0000644
645
David Turnerf0df85b2000-06-22 00:17:42 +0000646 /*************************************************************************/
647 /*************************************************************************/
648 /*************************************************************************/
649 /**** ****/
650 /**** ****/
651 /**** FACE, SIZE & GLYPH SLOT OBJECTS ****/
652 /**** ****/
653 /**** ****/
654 /*************************************************************************/
655 /*************************************************************************/
656 /*************************************************************************/
657
Werner Lembergdeb4e982000-06-29 03:14:25 +0000658
659 static
660 FT_Error ft_glyphslot_init( FT_GlyphSlot slot )
David Turnerf0df85b2000-06-22 00:17:42 +0000661 {
662 FT_Driver driver = slot->face->driver;
663 FT_Driver_Class* clazz = driver->clazz;
664 FT_Memory memory = driver->root.memory;
665 FT_Error error = FT_Err_Ok;
666
Werner Lemberga929ba92000-06-25 06:47:11 +0000667
668 if ( FT_DRIVER_USES_OUTLINES( driver ) )
David Turnerf0df85b2000-06-22 00:17:42 +0000669 error = FT_GlyphLoader_New( memory, &slot->loader );
670
Werner Lemberga929ba92000-06-25 06:47:11 +0000671 if ( !error && clazz->init_slot )
David Turnerf0df85b2000-06-22 00:17:42 +0000672 error = clazz->init_slot( slot );
673
674 return error;
675 }
676
677
Werner Lembergdeb4e982000-06-29 03:14:25 +0000678 static
679 void ft_glyphslot_clear( FT_GlyphSlot slot )
David Turnerf0df85b2000-06-22 00:17:42 +0000680 {
David Turner5ae831c2000-06-30 01:31:22 +0000681 /* free bitmap if needed */
682 if ( slot->flags & ft_glyph_own_bitmap )
683 {
684 FT_Memory memory = FT_FACE_MEMORY( slot->face );
685 FREE( slot->bitmap.buffer );
686 slot->flags &= ~ft_glyph_own_bitmap;
687 }
688
David Turnerf0df85b2000-06-22 00:17:42 +0000689 /* clear all public fields in the glyph slot */
Werner Lemberga929ba92000-06-25 06:47:11 +0000690 MEM_Set( &slot->metrics, 0, sizeof ( slot->metrics ) );
691 MEM_Set( &slot->outline, 0, sizeof ( slot->outline ) );
692 MEM_Set( &slot->bitmap, 0, sizeof ( slot->bitmap ) );
David Turnerf0df85b2000-06-22 00:17:42 +0000693
694 slot->bitmap_left = 0;
695 slot->bitmap_top = 0;
696 slot->num_subglyphs = 0;
697 slot->subglyphs = 0;
698 slot->control_data = 0;
699 slot->control_len = 0;
700 slot->other = 0;
701 slot->format = 0;
702
703 slot->linearHoriAdvance = 0;
704 slot->linearVertAdvance = 0;
705 }
706
707
Werner Lembergdeb4e982000-06-29 03:14:25 +0000708 static
709 void ft_glyphslot_done( FT_GlyphSlot slot )
David Turnerf0df85b2000-06-22 00:17:42 +0000710 {
711 FT_Driver driver = slot->face->driver;
712 FT_Driver_Class* clazz = driver->clazz;
713 FT_Memory memory = driver->root.memory;
714
Werner Lemberga929ba92000-06-25 06:47:11 +0000715
David Turnerf0df85b2000-06-22 00:17:42 +0000716 /* free bitmap buffer if needed */
717 if ( slot->flags & ft_glyph_own_bitmap )
718 FREE( slot->bitmap.buffer );
719
720 /* free glyph loader */
Werner Lemberga929ba92000-06-25 06:47:11 +0000721 if ( FT_DRIVER_USES_OUTLINES( driver ) )
David Turnerf0df85b2000-06-22 00:17:42 +0000722 {
723 FT_GlyphLoader_Done( slot->loader );
724 slot->loader = 0;
725 }
726
Werner Lemberga929ba92000-06-25 06:47:11 +0000727 if ( clazz->done_slot )
David Turnerf0df85b2000-06-22 00:17:42 +0000728 clazz->done_slot( slot );
729 }
730
731
David Turnerf0df85b2000-06-22 00:17:42 +0000732 /*************************************************************************/
733 /* */
734 /* <Function> */
735 /* FT_New_GlyphSlot */
736 /* */
737 /* <Description> */
738 /* It is sometimes useful to have more than one glyph slot for a */
739 /* given face object. This function is used to create additional */
740 /* slots. All of them are automatically discarded when the face is */
741 /* destroyed. */
742 /* */
743 /* <Input> */
744 /* face :: A handle to a parent face object. */
745 /* */
746 /* <Output> */
747 /* aslot :: A handle to a new glyph slot object. */
748 /* */
749 /* <Return> */
750 /* FreeType error code. 0 means success. */
751 /* */
David Turnerf0df85b2000-06-22 00:17:42 +0000752 FT_EXPORT_FUNC( FT_Error ) FT_New_GlyphSlot( FT_Face face,
753 FT_GlyphSlot* aslot )
754 {
Werner Lemberga929ba92000-06-25 06:47:11 +0000755 FT_Error error;
756 FT_Driver driver;
757 FT_Driver_Class* clazz;
758 FT_Memory memory;
759 FT_GlyphSlot slot;
760
David Turnerf0df85b2000-06-22 00:17:42 +0000761
David Turnerf0df85b2000-06-22 00:17:42 +0000762 if ( !face || !aslot || !face->driver )
763 return FT_Err_Invalid_Argument;
764
Werner Lembergdeb4e982000-06-29 03:14:25 +0000765 *aslot = 0;
766
David Turnerf0df85b2000-06-22 00:17:42 +0000767 driver = face->driver;
768 clazz = driver->clazz;
769 memory = driver->root.memory;
770
771 FT_TRACE4(( "FT_New_GlyphSlot: Creating new slot object\n" ));
772 if ( !ALLOC( slot, clazz->slot_object_size ) )
773 {
774 slot->face = face;
775
776 error = ft_glyphslot_init( slot );
Werner Lemberga929ba92000-06-25 06:47:11 +0000777 if ( error )
David Turnerf0df85b2000-06-22 00:17:42 +0000778 {
779 ft_glyphslot_done( slot );
780 FREE( slot );
781 goto Exit;
782 }
783
784 *aslot = slot;
785 }
786
787 Exit:
788 FT_TRACE4(( "FT_New_GlyphSlot: Return %d\n", error ));
789 return error;
790 }
791
792
793 /*************************************************************************/
794 /* */
795 /* <Function> */
796 /* FT_Done_GlyphSlot */
797 /* */
798 /* <Description> */
799 /* Destroys a given glyph slot. Remember however that all slots are */
800 /* automatically destroyed with its parent. Using this function is */
801 /* not always mandatory. */
802 /* */
803 /* <Input> */
804 /* slot :: A handle to a target glyph slot. */
805 /* */
806 FT_EXPORT_FUNC( void ) FT_Done_GlyphSlot( FT_GlyphSlot slot )
807 {
808 if ( slot )
809 {
810 FT_Driver driver = slot->face->driver;
811 FT_Memory memory = driver->root.memory;
812 FT_GlyphSlot* parent;
813 FT_GlyphSlot cur;
814
Werner Lemberga929ba92000-06-25 06:47:11 +0000815
David Turnerf0df85b2000-06-22 00:17:42 +0000816 /* Remove slot from its parent face's list */
817 parent = &slot->face->glyph;
818 cur = *parent;
Werner Lemberga929ba92000-06-25 06:47:11 +0000819
David Turnerf0df85b2000-06-22 00:17:42 +0000820 while ( cur )
821 {
822 if ( cur == slot )
823 {
824 *parent = cur->next;
Werner Lemberga929ba92000-06-25 06:47:11 +0000825 ft_glyphslot_done( slot );
David Turnerf0df85b2000-06-22 00:17:42 +0000826 FREE( slot );
827 break;
828 }
829 cur = cur->next;
830 }
831 }
832 }
833
834
David Turnerf0df85b2000-06-22 00:17:42 +0000835 /*************************************************************************/
836 /* */
837 /* <Function> */
838 /* FT_Set_Transform */
839 /* */
840 /* <Description> */
841 /* A function used to set the transformation that is applied to glyph */
Werner Lemberga929ba92000-06-25 06:47:11 +0000842 /* images just before they are converted to bitmaps in a glyph slot */
843 /* when FT_Render_Glyph() is called. */
David Turnerf0df85b2000-06-22 00:17:42 +0000844 /* */
845 /* <InOut> */
846 /* face :: A handle to the source face object. */
847 /* */
848 /* <Input> */
849 /* matrix :: A pointer to the transformation's 2x2 matrix. Use 0 for */
850 /* the identity matrix. */
851 /* delta :: A pointer to the translation vector. Use 0 for the null */
852 /* vector. */
853 /* */
854 /* <Note> */
855 /* The transformation is only applied to scalable image formats. */
856 /* */
857 FT_EXPORT_FUNC( void ) FT_Set_Transform( FT_Face face,
858 FT_Matrix* matrix,
859 FT_Vector* delta )
860 {
861 if ( !face )
862 return;
863
864 face->transform_flags = 0;
865
866 if ( !matrix )
867 {
868 face->transform_matrix.xx = 0x10000L;
Werner Lembergdeb4e982000-06-29 03:14:25 +0000869 face->transform_matrix.xy = 0;
870 face->transform_matrix.yx = 0;
David Turnerf0df85b2000-06-22 00:17:42 +0000871 face->transform_matrix.yy = 0x10000L;
872 matrix = &face->transform_matrix;
873 }
874 else
875 face->transform_matrix = *matrix;
876
877 /* set transform_flags bit flag 0 if `matrix' isn't the identity */
878 if ( ( matrix->xy | matrix->yx ) ||
879 matrix->xx != 0x10000L ||
880 matrix->yy != 0x10000L )
881 face->transform_flags |= 1;
882
883 if ( !delta )
884 {
885 face->transform_delta.x = 0;
886 face->transform_delta.y = 0;
887 delta = &face->transform_delta;
888 }
889 else
890 face->transform_delta = *delta;
891
892 /* set transform_flags bit flag 1 if `delta' isn't the null vector */
893 if ( delta->x | delta->y )
894 face->transform_flags |= 2;
895 }
896
897
Werner Lembergdeb4e982000-06-29 03:14:25 +0000898 static FT_Renderer ft_lookup_glyph_renderer( FT_GlyphSlot slot );
899
900
David Turnerf0df85b2000-06-22 00:17:42 +0000901 /*************************************************************************/
902 /* */
903 /* <Function> */
904 /* FT_Load_Glyph */
905 /* */
906 /* <Description> */
907 /* A function used to load a single glyph within a given glyph slot, */
908 /* for a given size. */
909 /* */
910 /* <Input> */
911 /* face :: A handle to the target face object where the glyph */
912 /* will be loaded. */
913 /* */
914 /* glyph_index :: The index of the glyph in the font file. */
915 /* */
916 /* load_flags :: A flag indicating what to load for this glyph. The */
917 /* FT_LOAD_XXX constants can be used to control the */
918 /* glyph loading process (e.g., whether the outline */
919 /* should be scaled, whether to load bitmaps or not, */
920 /* whether to hint the outline, etc). */
921 /* */
922 /* <Return> */
923 /* FreeType error code. 0 means success. */
924 /* */
925 /* <Note> */
926 /* If the glyph image is not a bitmap, and if the bit flag */
927 /* FT_LOAD_IGNORE_TRANSFORM is unset, the glyph image will be */
928 /* transformed with the information passed to a previous call to */
929 /* FT_Set_Transform. */
930 /* */
Werner Lemberga929ba92000-06-25 06:47:11 +0000931 /* Note that this also transforms the `face.glyph.advance' field, but */
932 /* *not* the values in `face.glyph.metrics'. */
David Turnerf0df85b2000-06-22 00:17:42 +0000933 /* */
David Turnerf0df85b2000-06-22 00:17:42 +0000934 FT_EXPORT_FUNC( FT_Error ) FT_Load_Glyph( FT_Face face,
935 FT_UInt glyph_index,
936 FT_Int load_flags )
937 {
938 FT_Error error;
939 FT_Driver driver;
940 FT_GlyphSlot slot;
David Turner5ae831c2000-06-30 01:31:22 +0000941 FT_Library library;
942 FT_Bool autohint;
943 FT_Module hinter;
David Turnerf0df85b2000-06-22 00:17:42 +0000944
Werner Lemberga929ba92000-06-25 06:47:11 +0000945
David Turnerf0df85b2000-06-22 00:17:42 +0000946 if ( !face || !face->size || !face->glyph )
947 return FT_Err_Invalid_Face_Handle;
948
David Turner74abee82000-06-27 23:31:53 +0000949 if ( glyph_index >= (FT_UInt)face->num_glyphs )
David Turnerf0df85b2000-06-22 00:17:42 +0000950 return FT_Err_Invalid_Argument;
951
952 slot = face->glyph;
953 ft_glyphslot_clear( slot );
954
955 driver = face->driver;
956
957 /* when the flag NO_RECURSE is set, we disable hinting and scaling */
958 if ( load_flags & FT_LOAD_NO_RECURSE )
959 load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING;
960
David Turner5ae831c2000-06-30 01:31:22 +0000961 /* do we need to load the glyph through the auto-hinter ?? */
962 library = driver->root.library;
963 hinter = library->auto_hinter;
964 autohint = hinter &&
965 !(load_flags & (FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING));
966 if (autohint)
967 {
968 if ( FT_DRIVER_HAS_HINTER( driver ) &&
969 !(load_flags & FT_LOAD_FORCE_AUTOHINT) )
970 autohint = 0;
971 }
972
973 if (autohint)
974 {
975 FT_AutoHinter_Interface* hinting;
976
977 hinting = (FT_AutoHinter_Interface*)hinter->clazz->module_interface;
978 error = hinting->load_glyph( (FT_AutoHinter)hinter, slot, face->size,
979 glyph_index, load_flags );
980 }
981 else
982 error = driver->clazz->load_glyph( slot,
983 face->size,
984 glyph_index,
985 load_flags );
Werner Lemberga929ba92000-06-25 06:47:11 +0000986 if ( error )
987 goto Exit;
David Turnerf0df85b2000-06-22 00:17:42 +0000988
989 /* compute the advance */
Werner Lemberga929ba92000-06-25 06:47:11 +0000990 if ( load_flags & FT_LOAD_VERTICAL_LAYOUT )
David Turnerf0df85b2000-06-22 00:17:42 +0000991 {
992 slot->advance.x = 0;
993 slot->advance.y = slot->metrics.vertAdvance;
994 }
995 else
996 {
997 slot->advance.x = slot->metrics.horiAdvance;
998 slot->advance.y = 0;
999 }
1000
1001 /* now, transform the glyph image when needed */
Werner Lemberga929ba92000-06-25 06:47:11 +00001002 if ( face->transform_flags )
David Turnerf0df85b2000-06-22 00:17:42 +00001003 {
1004 /* get renderer */
1005 FT_Renderer renderer = ft_lookup_glyph_renderer( slot );
Werner Lembergdeb4e982000-06-29 03:14:25 +00001006
Werner Lemberga929ba92000-06-25 06:47:11 +00001007
1008 if ( renderer )
David Turnerf0df85b2000-06-22 00:17:42 +00001009 error = renderer->clazz->transform_glyph( renderer, slot,
1010 &face->transform_matrix,
1011 &face->transform_delta );
Werner Lembergdeb4e982000-06-29 03:14:25 +00001012 /* transform advance */
1013 FT_Vector_Transform( &slot->advance, &face->transform_matrix );
David Turnerf0df85b2000-06-22 00:17:42 +00001014 }
1015
David Turner5ae831c2000-06-30 01:31:22 +00001016 /* do we need to render the image now ? */
1017 if ( !error &&
1018 slot->format != ft_glyph_format_bitmap &&
1019 slot->format != ft_glyph_format_composite &&
1020 load_flags & FT_LOAD_RENDER )
1021 {
1022 error = FT_Render_Glyph( slot, (load_flags & FT_LOAD_ANTI_ALIAS) ?
1023 ft_render_mode_antialias : 0 );
1024 }
1025
Werner Lembergdeb4e982000-06-29 03:14:25 +00001026 Exit:
David Turnerf0df85b2000-06-22 00:17:42 +00001027 return error;
1028 }
1029
1030
1031 /*************************************************************************/
1032 /* */
1033 /* <Function> */
1034 /* FT_Load_Char */
1035 /* */
1036 /* <Description> */
1037 /* A function used to load a single glyph within a given glyph slot, */
Werner Lemberga929ba92000-06-25 06:47:11 +00001038 /* for a given size, according to its character code. */
David Turnerf0df85b2000-06-22 00:17:42 +00001039 /* */
1040 /* <Input> */
1041 /* face :: A handle to a target face object where the glyph */
1042 /* will be loaded. */
1043 /* */
1044 /* char_code :: The glyph's character code, according to the */
1045 /* current charmap used in the face. */
1046 /* */
1047 /* load_flags :: A flag indicating what to load for this glyph. The */
1048 /* FT_LOAD_XXX constants can be used to control the */
1049 /* glyph loading process (e.g., whether the outline */
1050 /* should be scaled, whether to load bitmaps or not, */
1051 /* whether to hint the outline, etc). */
Werner Lemberga929ba92000-06-25 06:47:11 +00001052 /* */
David Turnerf0df85b2000-06-22 00:17:42 +00001053 /* <Return> */
1054 /* FreeType error code. 0 means success. */
1055 /* */
1056 /* <Note> */
1057 /* If the face has no current charmap, or if the character code */
1058 /* is not defined in the charmap, this function will return an */
Werner Lemberga929ba92000-06-25 06:47:11 +00001059 /* error. */
David Turnerf0df85b2000-06-22 00:17:42 +00001060 /* */
1061 /* If the glyph image is not a bitmap, and if the bit flag */
1062 /* FT_LOAD_IGNORE_TRANSFORM is unset, the glyph image will be */
1063 /* transformed with the information passed to a previous call to */
Werner Lemberga929ba92000-06-25 06:47:11 +00001064 /* FT_Set_Transform(). */
David Turnerf0df85b2000-06-22 00:17:42 +00001065 /* */
Werner Lemberga929ba92000-06-25 06:47:11 +00001066 /* Note that this also transforms the `face.glyph.advance' field, but */
1067 /* *not* the values in `face.glyph.metrics'. */
David Turnerf0df85b2000-06-22 00:17:42 +00001068 /* */
1069 FT_EXPORT_FUNC( FT_Error ) FT_Load_Char( FT_Face face,
1070 FT_ULong char_code,
1071 FT_Int load_flags )
1072 {
Werner Lembergdeb4e982000-06-29 03:14:25 +00001073 FT_UInt glyph_index;
David Turnerf0df85b2000-06-22 00:17:42 +00001074
Werner Lemberga929ba92000-06-25 06:47:11 +00001075
David Turnerf0df85b2000-06-22 00:17:42 +00001076 if ( !face )
1077 return FT_Err_Invalid_Face_Handle;
1078
1079 glyph_index = (FT_UInt)char_code;
Werner Lemberga929ba92000-06-25 06:47:11 +00001080 if ( face->charmap )
David Turnerf0df85b2000-06-22 00:17:42 +00001081 glyph_index = FT_Get_Char_Index( face, char_code );
1082
David Turner5ae831c2000-06-30 01:31:22 +00001083 return FT_Load_Glyph( face, glyph_index, load_flags );
David Turnerf0df85b2000-06-22 00:17:42 +00001084 }
1085
1086
Werner Lemberg7880dd62000-01-10 17:19:45 +00001087 /* destructor for sizes list */
1088 static
1089 void destroy_size( FT_Memory memory,
1090 FT_Size size,
1091 FT_Driver driver )
1092 {
David Turnerf0df85b2000-06-22 00:17:42 +00001093 /* finalize client-specific data */
Werner Lemberga929ba92000-06-25 06:47:11 +00001094 if ( size->generic.finalizer )
David Turnerf0df85b2000-06-22 00:17:42 +00001095 size->generic.finalizer( size );
1096
Werner Lemberg7880dd62000-01-10 17:19:45 +00001097 /* finalize format-specific stuff */
Werner Lemberga929ba92000-06-25 06:47:11 +00001098 if ( driver->clazz->done_size )
David Turnerf0df85b2000-06-22 00:17:42 +00001099 driver->clazz->done_size( size );
1100
Werner Lemberg7880dd62000-01-10 17:19:45 +00001101 FREE( size );
1102 }
David Turnerd2b1f351999-12-16 23:11:37 +00001103
1104
Werner Lemberg7880dd62000-01-10 17:19:45 +00001105 /* destructor for faces list */
1106 static
1107 void destroy_face( FT_Memory memory,
1108 FT_Face face,
1109 FT_Driver driver )
1110 {
David Turnerf0df85b2000-06-22 00:17:42 +00001111 FT_Driver_Class* clazz = driver->clazz;
1112
Werner Lemberga929ba92000-06-25 06:47:11 +00001113
David Turnerf0df85b2000-06-22 00:17:42 +00001114 /* Discard glyph slots for this face */
1115 /* Beware! FT_Done_GlyphSlot() changes the field `face->slot' */
Werner Lemberg7880dd62000-01-10 17:19:45 +00001116 while ( face->glyph )
1117 FT_Done_GlyphSlot( face->glyph );
1118
1119 /* Discard all sizes for this face */
1120 FT_List_Finalize( &face->sizes_list,
1121 (FT_List_Destructor)destroy_size,
1122 memory,
1123 driver );
1124 face->size = 0;
1125
Werner Lemberg7880dd62000-01-10 17:19:45 +00001126 /* Now discard client data */
1127 if ( face->generic.finalizer )
1128 face->generic.finalizer( face );
1129
David Turnerf0df85b2000-06-22 00:17:42 +00001130 /* finalize format-specific stuff */
Werner Lemberga929ba92000-06-25 06:47:11 +00001131 if ( clazz->done_face )
1132 clazz->done_face( face );
David Turnerf0df85b2000-06-22 00:17:42 +00001133
1134 /* close the stream for this face if needed */
Werner Lemberga929ba92000-06-25 06:47:11 +00001135 if ( ( face->face_flags & FT_FACE_FLAG_EXTERNAL_STREAM ) == 0 )
David Turnerf0df85b2000-06-22 00:17:42 +00001136 ft_done_stream( &face->stream );
David Turner7663f222000-02-13 13:37:38 +00001137
Werner Lemberg7880dd62000-01-10 17:19:45 +00001138 /* get rid of it */
1139 FREE( face );
1140 }
David Turnerd2b1f351999-12-16 23:11:37 +00001141
1142
Werner Lembergdeb4e982000-06-29 03:14:25 +00001143 static
1144 void Destroy_Driver( FT_Driver driver )
David Turnerd2b1f351999-12-16 23:11:37 +00001145 {
David Turnerd2b1f351999-12-16 23:11:37 +00001146 FT_List_Finalize( &driver->faces_list,
1147 (FT_List_Destructor)destroy_face,
David Turnerf0df85b2000-06-22 00:17:42 +00001148 driver->root.memory,
David Turnerd2b1f351999-12-16 23:11:37 +00001149 driver );
1150
Werner Lembergdeb4e982000-06-29 03:14:25 +00001151 /* check whether we need to drop the driver's glyph loader */
Werner Lemberga929ba92000-06-25 06:47:11 +00001152 if ( FT_DRIVER_USES_OUTLINES( driver ) )
David Turnerf0df85b2000-06-22 00:17:42 +00001153 FT_GlyphLoader_Done( driver->glyph_loader );
David Turnerd2b1f351999-12-16 23:11:37 +00001154 }
1155
1156
Werner Lemberg547a2522000-02-16 08:23:58 +00001157 /*************************************************************************/
1158 /* */
1159 /* <Function> */
1160 /* open_face */
1161 /* */
1162 /* <Description> */
1163 /* This function does some work for FT_Open_Face(). */
1164 /* */
David Turnerd2b1f351999-12-16 23:11:37 +00001165 static
David Turner4f2c5542000-05-12 10:19:41 +00001166 FT_Error open_face( FT_Driver driver,
1167 FT_Stream stream,
1168 FT_Long face_index,
1169 FT_Int num_params,
1170 FT_Parameter* params,
1171 FT_Face* aface )
David Turnerd2b1f351999-12-16 23:11:37 +00001172 {
David Turnerf0df85b2000-06-22 00:17:42 +00001173 FT_Memory memory;
1174 FT_Driver_Class* clazz;
1175 FT_Face face = 0;
1176 FT_Error error;
David Turnerd2b1f351999-12-16 23:11:37 +00001177
Werner Lemberga929ba92000-06-25 06:47:11 +00001178
David Turnerf0df85b2000-06-22 00:17:42 +00001179 clazz = driver->clazz;
1180 memory = driver->root.memory;
David Turnerd2b1f351999-12-16 23:11:37 +00001181
Werner Lembergdeb4e982000-06-29 03:14:25 +00001182 /* allocate the face object and perform basic initialization */
David Turnerf0df85b2000-06-22 00:17:42 +00001183 if ( ALLOC( face, clazz->face_object_size ) )
David Turnerd2b1f351999-12-16 23:11:37 +00001184 goto Fail;
1185
1186 face->driver = driver;
1187 face->memory = memory;
1188 face->stream = stream;
1189
David Turnerf0df85b2000-06-22 00:17:42 +00001190 error = clazz->init_face( stream,
1191 face,
1192 face_index,
1193 num_params,
1194 params );
David Turnerd2b1f351999-12-16 23:11:37 +00001195 if ( error )
1196 goto Fail;
1197
1198 *aface = face;
1199
1200 Fail:
1201 if ( error )
1202 {
David Turnerf0df85b2000-06-22 00:17:42 +00001203 clazz->done_face( face );
David Turnerd2b1f351999-12-16 23:11:37 +00001204 FREE( face );
1205 *aface = 0;
1206 }
1207
1208 return error;
1209 }
1210
1211
1212 /*************************************************************************/
1213 /* */
1214 /* <Function> */
1215 /* FT_New_Face */
1216 /* */
1217 /* <Description> */
Werner Lemberg547a2522000-02-16 08:23:58 +00001218 /* Creates a new face object from a given resource and typeface index */
1219 /* using a pathname to the font file. */
1220 /* */
1221 /* <InOut> */
1222 /* library :: A handle to the library resource. */
David Turnerd2b1f351999-12-16 23:11:37 +00001223 /* */
1224 /* <Input> */
Werner Lemberg547a2522000-02-16 08:23:58 +00001225 /* pathname :: A path to the font file. */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001226 /* */
David Turnerd2b1f351999-12-16 23:11:37 +00001227 /* face_index :: The index of the face within the resource. The */
1228 /* first face has index 0. */
1229 /* <Output> */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001230 /* aface :: A handle to a new face object. */
David Turnerd2b1f351999-12-16 23:11:37 +00001231 /* */
1232 /* <Return> */
Werner Lemberg7880dd62000-01-10 17:19:45 +00001233 /* FreeType error code. 0 means success. */
David Turnerd2b1f351999-12-16 23:11:37 +00001234 /* */
1235 /* <Note> */
Werner Lemberg547a2522000-02-16 08:23:58 +00001236 /* Unlike FreeType 1.x, this function automatically creates a glyph */
David Turnerd2b1f351999-12-16 23:11:37 +00001237 /* slot for the face object which can be accessed directly through */
1238 /* `face->glyph'. */
1239 /* */
Werner Lemberg547a2522000-02-16 08:23:58 +00001240 /* Note that additional slots can be added to each face with the */
David Turnerd2b1f351999-12-16 23:11:37 +00001241 /* FT_New_GlyphSlot() API function. Slots are linked in a single */
1242 /* list through their `next' field. */
1243 /* */
1244 /* FT_New_Face() can be used to determine and/or check the font */
1245 /* format of a given font resource. If the `face_index' field is */
1246 /* negative, the function will _not_ return any face handle in */
1247 /* `*face'. Its return value should be 0 if the resource is */
1248 /* recognized, or non-zero if not. */
1249 /* */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001250 FT_EXPORT_FUNC( FT_Error ) FT_New_Face( FT_Library library,
1251 const char* pathname,
1252 FT_Long face_index,
1253 FT_Face* aface )
David Turnerd2b1f351999-12-16 23:11:37 +00001254 {
David Turner37379e22000-03-28 11:22:31 +00001255 FT_Open_Args args;
Werner Lemberg547a2522000-02-16 08:23:58 +00001256
Werner Lemberga929ba92000-06-25 06:47:11 +00001257
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001258 /* test for valid `library' and `aface' delayed to FT_Open_Face() */
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001259 if ( !pathname )
1260 return FT_Err_Invalid_Argument;
1261
David Turner4f2c5542000-05-12 10:19:41 +00001262 args.flags = ft_open_pathname;
1263 args.pathname = (char*)pathname;
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001264
David Turnercda32b72000-02-10 16:14:35 +00001265 return FT_Open_Face( library, &args, face_index, aface );
David Turnerd2b1f351999-12-16 23:11:37 +00001266 }
1267
Werner Lemberg7880dd62000-01-10 17:19:45 +00001268
Werner Lemberg547a2522000-02-16 08:23:58 +00001269 /*************************************************************************/
1270 /* */
1271 /* <Function> */
1272 /* FT_New_Memory_Face */
1273 /* */
1274 /* <Description> */
1275 /* Creates a new face object from a given resource and typeface index */
1276 /* using a font file already loaded into memory. */
1277 /* */
1278 /* <InOut> */
1279 /* library :: A handle to the library resource. */
1280 /* */
1281 /* <Input> */
1282 /* file_base :: A pointer to the beginning of the font data. */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001283 /* */
Werner Lemberg547a2522000-02-16 08:23:58 +00001284 /* file_size :: The size of the memory chunk used by the font data. */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001285 /* */
Werner Lemberg547a2522000-02-16 08:23:58 +00001286 /* face_index :: The index of the face within the resource. The */
1287 /* first face has index 0. */
1288 /* <Output> */
1289 /* face :: A handle to a new face object. */
1290 /* */
1291 /* <Return> */
1292 /* FreeType error code. 0 means success. */
1293 /* */
1294 /* <Note> */
1295 /* Unlike FreeType 1.x, this function automatically creates a glyph */
1296 /* slot for the face object which can be accessed directly through */
1297 /* `face->glyph'. */
1298 /* */
1299 /* Note that additional slots can be added to each face with the */
1300 /* FT_New_GlyphSlot() API function. Slots are linked in a single */
1301 /* list through their `next' field. */
1302 /* */
1303 /* FT_New_Memory_Face() can be used to determine and/or check the */
1304 /* font format of a given font resource. If the `face_index' field */
1305 /* is negative, the function will _not_ return any face handle in */
1306 /* `*face'. Its return value should be 0 if the resource is */
1307 /* recognized, or non-zero if not. */
1308 /* */
Werner Lembergdeb4e982000-06-29 03:14:25 +00001309 FT_EXPORT_FUNC( FT_Error ) FT_New_Memory_Face( FT_Library library,
1310 void* file_base,
1311 FT_Long file_size,
1312 FT_Long face_index,
1313 FT_Face* face )
David Turnerd2b1f351999-12-16 23:11:37 +00001314 {
David Turner37379e22000-03-28 11:22:31 +00001315 FT_Open_Args args;
Werner Lemberg7880dd62000-01-10 17:19:45 +00001316
Werner Lemberga929ba92000-06-25 06:47:11 +00001317
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001318 /* test for valid `library' and `face' delayed to FT_Open_Face() */
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001319 if ( !file_base )
1320 return FT_Err_Invalid_Argument;
1321
David Turner4f2c5542000-05-12 10:19:41 +00001322 args.flags = ft_open_memory;
David Turnercda32b72000-02-10 16:14:35 +00001323 args.memory_base = file_base;
1324 args.memory_size = file_size;
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001325
David Turnercda32b72000-02-10 16:14:35 +00001326 return FT_Open_Face( library, &args, face_index, face );
David Turnerd2b1f351999-12-16 23:11:37 +00001327 }
1328
Werner Lemberg7880dd62000-01-10 17:19:45 +00001329
Werner Lemberg547a2522000-02-16 08:23:58 +00001330 /*************************************************************************/
1331 /* */
1332 /* <Function> */
1333 /* FT_Open_Face */
1334 /* */
1335 /* <Description> */
1336 /* Opens a face object from a given resource and typeface index using */
1337 /* an `FT_Open_Args' structure. If the face object doesn't exist, it */
1338 /* will be created. */
1339 /* */
1340 /* <InOut> */
1341 /* library :: A handle to the library resource. */
1342 /* */
1343 /* <Input> */
1344 /* args :: A pointer to an `FT_Open_Args' structure which must */
1345 /* be filled by the caller. */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001346 /* */
Werner Lemberg547a2522000-02-16 08:23:58 +00001347 /* face_index :: The index of the face within the resource. The */
1348 /* first face has index 0. */
1349 /* <Output> */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001350 /* aface :: A handle to a new face object. */
Werner Lemberg547a2522000-02-16 08:23:58 +00001351 /* */
1352 /* <Return> */
1353 /* FreeType error code. 0 means success. */
1354 /* */
1355 /* <Note> */
1356 /* Unlike FreeType 1.x, this function automatically creates a glyph */
1357 /* slot for the face object which can be accessed directly through */
1358 /* `face->glyph'. */
1359 /* */
1360 /* Note that additional slots can be added to each face with the */
1361 /* FT_New_GlyphSlot() API function. Slots are linked in a single */
1362 /* list through their `next' field. */
1363 /* */
1364 /* FT_Open_Face() can be used to determine and/or check the font */
1365 /* format of a given font resource. If the `face_index' field is */
1366 /* negative, the function will _not_ return any face handle in */
1367 /* `*face'. Its return value should be 0 if the resource is */
1368 /* recognized, or non-zero if not. */
1369 /* */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001370 FT_EXPORT_FUNC( FT_Error ) FT_Open_Face( FT_Library library,
1371 FT_Open_Args* args,
1372 FT_Long face_index,
1373 FT_Face* aface )
David Turnerd2b1f351999-12-16 23:11:37 +00001374 {
1375 FT_Error error;
1376 FT_Driver driver;
1377 FT_Memory memory;
David Turnercda32b72000-02-10 16:14:35 +00001378 FT_Stream stream;
David Turnerd2b1f351999-12-16 23:11:37 +00001379 FT_Face face = 0;
1380 FT_ListNode node = 0;
1381
Werner Lemberg547a2522000-02-16 08:23:58 +00001382
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001383 /* test for valid `library' and `args' delayed to */
1384 /* ft_new_input_stream() */
David Turnerd2b1f351999-12-16 23:11:37 +00001385
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001386 if ( !aface )
1387 return FT_Err_Invalid_Argument;
1388
1389 *aface = 0;
David Turnerd2b1f351999-12-16 23:11:37 +00001390
David Turnercda32b72000-02-10 16:14:35 +00001391 /* create input stream */
1392 error = ft_new_input_stream( library, args, &stream );
Werner Lembergdeb4e982000-06-29 03:14:25 +00001393 if ( error )
1394 goto Exit;
David Turnercda32b72000-02-10 16:14:35 +00001395
David Turnerd2b1f351999-12-16 23:11:37 +00001396 memory = library->memory;
1397
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001398 /* If the font driver is specified in the `args' structure, use */
Werner Lembergdeb4e982000-06-29 03:14:25 +00001399 /* it. Otherwise, we scan the list of registered drivers. */
David Turner4f2c5542000-05-12 10:19:41 +00001400 if ( args->flags & ft_open_driver && args->driver )
David Turner7663f222000-02-13 13:37:38 +00001401 {
Werner Lemberga929ba92000-06-25 06:47:11 +00001402 driver = FT_DRIVER( args->driver );
David Turnerf0df85b2000-06-22 00:17:42 +00001403
1404 /* not all modules are drivers, so check... */
Werner Lemberga929ba92000-06-25 06:47:11 +00001405 if ( FT_MODULE_IS_DRIVER( driver ) )
David Turner7663f222000-02-13 13:37:38 +00001406 {
David Turner4f2c5542000-05-12 10:19:41 +00001407 FT_Int num_params = 0;
1408 FT_Parameter* params = 0;
David Turnere49ab252000-05-16 23:44:38 +00001409
Werner Lemberga929ba92000-06-25 06:47:11 +00001410
David Turner4f2c5542000-05-12 10:19:41 +00001411 if ( args->flags & ft_open_params )
1412 {
1413 num_params = args->num_params;
1414 params = args->params;
1415 }
David Turnere49ab252000-05-16 23:44:38 +00001416
David Turner4f2c5542000-05-12 10:19:41 +00001417 error = open_face( driver, stream, face_index,
1418 num_params, params, &face );
Werner Lemberg547a2522000-02-16 08:23:58 +00001419 if ( !error )
1420 goto Success;
David Turner7663f222000-02-13 13:37:38 +00001421 }
1422 else
1423 error = FT_Err_Invalid_Handle;
1424
David Turner2a98b3c2000-06-23 13:47:55 +00001425 ft_done_stream( &stream );
David Turner7663f222000-02-13 13:37:38 +00001426 goto Fail;
1427 }
Just van Rossum1e5754f2000-03-02 10:52:57 +00001428 else
David Turnerd2b1f351999-12-16 23:11:37 +00001429 {
1430 /* check each font driver for an appropriate format */
David Turnerf0df85b2000-06-22 00:17:42 +00001431 FT_Module* cur = library->modules;
1432 FT_Module* limit = cur + library->num_modules;
David Turnerd2b1f351999-12-16 23:11:37 +00001433
Werner Lemberga929ba92000-06-25 06:47:11 +00001434
David Turnerd2b1f351999-12-16 23:11:37 +00001435 for ( ; cur < limit; cur++ )
1436 {
David Turnerf0df85b2000-06-22 00:17:42 +00001437 /* not all modules are font drivers, so check... */
Werner Lemberga929ba92000-06-25 06:47:11 +00001438 if ( FT_MODULE_IS_DRIVER( cur[0] ) )
David Turnerd2b1f351999-12-16 23:11:37 +00001439 {
David Turner4f2c5542000-05-12 10:19:41 +00001440 FT_Int num_params = 0;
1441 FT_Parameter* params = 0;
David Turnere49ab252000-05-16 23:44:38 +00001442
Werner Lembergdeb4e982000-06-29 03:14:25 +00001443
Werner Lemberga929ba92000-06-25 06:47:11 +00001444 driver = FT_DRIVER( cur[0] );
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001445
David Turner4f2c5542000-05-12 10:19:41 +00001446 if ( args->flags & ft_open_params )
1447 {
1448 num_params = args->num_params;
1449 params = args->params;
1450 }
David Turnere49ab252000-05-16 23:44:38 +00001451
David Turner4f2c5542000-05-12 10:19:41 +00001452 error = open_face( driver, stream, face_index,
1453 num_params, params, &face );
David Turnerd2b1f351999-12-16 23:11:37 +00001454 if ( !error )
1455 goto Success;
1456
1457 if ( error != FT_Err_Unknown_File_Format )
David Turnercda32b72000-02-10 16:14:35 +00001458 goto Fail;
David Turnerd2b1f351999-12-16 23:11:37 +00001459 }
1460 }
1461
David Turner2a98b3c2000-06-23 13:47:55 +00001462 ft_done_stream( &stream );
1463
David Turnerd2b1f351999-12-16 23:11:37 +00001464 /* no driver is able to handle this format */
1465 error = FT_Err_Unknown_File_Format;
David Turnercda32b72000-02-10 16:14:35 +00001466 goto Fail;
David Turnerd2b1f351999-12-16 23:11:37 +00001467 }
1468
1469 Success:
David Turnerd2b1f351999-12-16 23:11:37 +00001470 FT_TRACE4(( "FT_New_Face: New face object, adding to list\n" ));
1471
Werner Lembergdeb4e982000-06-29 03:14:25 +00001472 /* set the FT_FACE_FLAG_EXTERNAL_STREAM bit for FT_Done_Face */
David Turnerf0df85b2000-06-22 00:17:42 +00001473 if ( args->flags & ft_open_stream && args->stream )
1474 face->face_flags |= FT_FACE_FLAG_EXTERNAL_STREAM;
1475
Werner Lemberg547a2522000-02-16 08:23:58 +00001476 /* add the face object to its driver's list */
David Turnerd2b1f351999-12-16 23:11:37 +00001477 if ( ALLOC( node, sizeof ( *node ) ) )
1478 goto Fail;
1479
1480 node->data = face;
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001481 /* don't assume driver is the same as face->driver, so use */
1482 /* face->driver instead. */
Just van Rossum7eef5362000-03-05 16:07:58 +00001483 FT_List_Add( &face->driver->faces_list, node );
David Turnerd2b1f351999-12-16 23:11:37 +00001484
Werner Lemberg547a2522000-02-16 08:23:58 +00001485 /* now allocate a glyph slot object for the face */
David Turnerd2b1f351999-12-16 23:11:37 +00001486 {
1487 FT_GlyphSlot slot;
1488
Werner Lemberg547a2522000-02-16 08:23:58 +00001489
David Turnerd2b1f351999-12-16 23:11:37 +00001490 FT_TRACE4(( "FT_Open_Face: Creating glyph slot\n" ));
Werner Lembergdeb4e982000-06-29 03:14:25 +00001491
David Turnerd2b1f351999-12-16 23:11:37 +00001492 error = FT_New_GlyphSlot( face, &slot );
Werner Lembergdeb4e982000-06-29 03:14:25 +00001493 if ( error )
1494 goto Fail;
1495
David Turnerf0df85b2000-06-22 00:17:42 +00001496 face->glyph = slot;
David Turnerd2b1f351999-12-16 23:11:37 +00001497 }
Werner Lemberg7880dd62000-01-10 17:19:45 +00001498
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001499 /* finally, allocate a size object for the face */
David Turnerd2b1f351999-12-16 23:11:37 +00001500 {
1501 FT_Size size;
1502
Werner Lemberg547a2522000-02-16 08:23:58 +00001503
David Turnerd2b1f351999-12-16 23:11:37 +00001504 FT_TRACE4(( "FT_Open_Face: Creating size object\n" ));
Werner Lembergdeb4e982000-06-29 03:14:25 +00001505
David Turnerd2b1f351999-12-16 23:11:37 +00001506 error = FT_New_Size( face, &size );
Werner Lembergdeb4e982000-06-29 03:14:25 +00001507 if ( error )
1508 goto Fail;
1509
David Turnerf0df85b2000-06-22 00:17:42 +00001510 face->size = size;
David Turnerd2b1f351999-12-16 23:11:37 +00001511 }
Werner Lemberg7880dd62000-01-10 17:19:45 +00001512
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001513 /* initialize transformation for convenience functions */
David Turner37379e22000-03-28 11:22:31 +00001514 face->transform_matrix.xx = 0x10000L;
1515 face->transform_matrix.xy = 0;
1516 face->transform_matrix.yx = 0;
1517 face->transform_matrix.yy = 0x10000L;
1518
1519 face->transform_delta.x = 0;
1520 face->transform_delta.y = 0;
1521
David Turnerd2b1f351999-12-16 23:11:37 +00001522 *aface = face;
1523 goto Exit;
1524
1525 Fail:
1526 FT_Done_Face( face );
1527
David Turnerd2b1f351999-12-16 23:11:37 +00001528 Exit:
1529 FT_TRACE4(( "FT_Open_Face: Return %d\n", error ));
Werner Lembergdeb4e982000-06-29 03:14:25 +00001530
David Turnerd2b1f351999-12-16 23:11:37 +00001531 return error;
1532 }
1533
1534
1535 /*************************************************************************/
1536 /* */
1537 /* <Function> */
David Turner7663f222000-02-13 13:37:38 +00001538 /* FT_Attach_File */
1539 /* */
1540 /* <Description> */
Werner Lemberg547a2522000-02-16 08:23:58 +00001541 /* `Attaches' a given font file to an existing face. This is usually */
1542 /* to read additional information for a single face object. For */
David Turner7663f222000-02-13 13:37:38 +00001543 /* example, it is used to read the AFM files that come with Type 1 */
Werner Lemberg547a2522000-02-16 08:23:58 +00001544 /* fonts in order to add kerning data and other metrics. */
1545 /* */
1546 /* <InOut> */
1547 /* face :: The target face object. */
David Turner7663f222000-02-13 13:37:38 +00001548 /* */
1549 /* <Input> */
Werner Lemberg547a2522000-02-16 08:23:58 +00001550 /* filepathname :: An 8-bit pathname naming the `metrics' file. */
David Turner7663f222000-02-13 13:37:38 +00001551 /* */
1552 /* <Return> */
Werner Lemberg547a2522000-02-16 08:23:58 +00001553 /* FreeType error code. 0 means success. */
David Turner7663f222000-02-13 13:37:38 +00001554 /* */
1555 /* <Note> */
1556 /* If your font file is in memory, or if you want to provide your */
Werner Lemberg547a2522000-02-16 08:23:58 +00001557 /* own input stream object, use FT_Attach_Stream(). */
David Turner7663f222000-02-13 13:37:38 +00001558 /* */
Werner Lemberg547a2522000-02-16 08:23:58 +00001559 /* The meaning of the `attach' action (i.e., what really happens when */
1560 /* the new file is read) is not fixed by FreeType itself. It really */
David Turner7663f222000-02-13 13:37:38 +00001561 /* depends on the font format (and thus the font driver). */
1562 /* */
Werner Lemberg547a2522000-02-16 08:23:58 +00001563 /* Client applications are expected to know what they are doing */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001564 /* when invoking this function. Most drivers simply do not implement */
Werner Lemberg547a2522000-02-16 08:23:58 +00001565 /* file attachments. */
David Turner7663f222000-02-13 13:37:38 +00001566 /* */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001567 FT_EXPORT_FUNC( FT_Error ) FT_Attach_File( FT_Face face,
1568 const char* filepathname )
David Turner7663f222000-02-13 13:37:38 +00001569 {
David Turner37379e22000-03-28 11:22:31 +00001570 FT_Open_Args open;
David Turner7663f222000-02-13 13:37:38 +00001571
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001572
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001573 /* test for valid `face' delayed to FT_Attach_Stream() */
1574
1575 if ( !filepathname )
1576 return FT_Err_Invalid_Argument;
1577
David Turner4f2c5542000-05-12 10:19:41 +00001578 open.flags = ft_open_pathname;
1579 open.pathname = (char*)filepathname;
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001580
David Turner7663f222000-02-13 13:37:38 +00001581 return FT_Attach_Stream( face, &open );
1582 }
Werner Lemberg547a2522000-02-16 08:23:58 +00001583
David Turnere49ab252000-05-16 23:44:38 +00001584
David Turner7663f222000-02-13 13:37:38 +00001585 /*************************************************************************/
1586 /* */
1587 /* <Function> */
1588 /* FT_Attach_Stream */
1589 /* */
1590 /* <Description> */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001591 /* This function is similar to FT_Attach_File() with the exception */
David Turner7663f222000-02-13 13:37:38 +00001592 /* that it reads the attachment from an arbitrary stream. */
1593 /* */
1594 /* <Input> */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001595 /* face :: The target face object. */
David Turner7663f222000-02-13 13:37:38 +00001596 /* */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001597 /* parameters :: A pointer to an FT_Open_Args structure used to */
1598 /* describe the input stream to FreeType. */
David Turner7663f222000-02-13 13:37:38 +00001599 /* <Return> */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001600 /* FreeType error code. 0 means success. */
David Turner7663f222000-02-13 13:37:38 +00001601 /* */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001602 /* <Note> */
1603 /* The meaning of the `attach' (i.e. what really happens when the */
1604 /* new file is read) is not fixed by FreeType itself. It really */
David Turner7663f222000-02-13 13:37:38 +00001605 /* depends on the font format (and thus the font driver). */
1606 /* */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001607 /* Client applications are expected to know what they are doing */
1608 /* when invoking this function. Most drivers simply do not implement */
1609 /* file attachments. */
David Turner7663f222000-02-13 13:37:38 +00001610 /* */
Werner Lembergdeb4e982000-06-29 03:14:25 +00001611 FT_EXPORT_FUNC( FT_Error ) FT_Attach_Stream( FT_Face face,
1612 FT_Open_Args* parameters )
David Turner7663f222000-02-13 13:37:38 +00001613 {
1614 FT_Stream stream;
1615 FT_Error error;
1616 FT_Driver driver;
David Turnere49ab252000-05-16 23:44:38 +00001617
David Turnerf0df85b2000-06-22 00:17:42 +00001618 FT_Driver_Class* clazz;
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001619
Werner Lemberga929ba92000-06-25 06:47:11 +00001620
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001621 /* test for valid `parameters' delayed to ft_new_input_stream() */
1622
1623 if ( !face )
1624 return FT_Err_Invalid_Face_Handle;
David Turnere49ab252000-05-16 23:44:38 +00001625
David Turner7663f222000-02-13 13:37:38 +00001626 driver = face->driver;
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001627 if ( !driver )
1628 return FT_Err_Invalid_Driver_Handle;
1629
David Turnerf0df85b2000-06-22 00:17:42 +00001630 error = ft_new_input_stream( driver->root.library, parameters, &stream );
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001631 if ( error )
1632 goto Exit;
David Turnere49ab252000-05-16 23:44:38 +00001633
David Turner7663f222000-02-13 13:37:38 +00001634 /* we implement FT_Attach_Stream in each driver through the */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001635 /* `attach_file' interface */
1636
David Turner7663f222000-02-13 13:37:38 +00001637 error = FT_Err_Unimplemented_Feature;
David Turnerf0df85b2000-06-22 00:17:42 +00001638 clazz = driver->clazz;
Werner Lemberga929ba92000-06-25 06:47:11 +00001639 if ( clazz->attach_file )
David Turnerf0df85b2000-06-22 00:17:42 +00001640 error = clazz->attach_file( face, stream );
David Turnere49ab252000-05-16 23:44:38 +00001641
David Turner7663f222000-02-13 13:37:38 +00001642 /* close the attached stream */
Werner Lemberga929ba92000-06-25 06:47:11 +00001643 if ( !parameters->stream || ( parameters->flags & ft_open_stream ) )
David Turnerf0df85b2000-06-22 00:17:42 +00001644 ft_done_stream( &stream );
David Turnere49ab252000-05-16 23:44:38 +00001645
David Turner7663f222000-02-13 13:37:38 +00001646 Exit:
1647 return error;
1648 }
1649
1650
David Turner7663f222000-02-13 13:37:38 +00001651 /*************************************************************************/
1652 /* */
1653 /* <Function> */
David Turnerd2b1f351999-12-16 23:11:37 +00001654 /* FT_Done_Face */
1655 /* */
1656 /* <Description> */
1657 /* Discards a given face object, as well as all of its child slots */
1658 /* and sizes. */
1659 /* */
1660 /* <Input> */
1661 /* face :: A handle to a target face object. */
1662 /* */
1663 /* <Return> */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001664 /* FreeType error code. 0 means success. */
David Turnerd2b1f351999-12-16 23:11:37 +00001665 /* */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001666 FT_EXPORT_FUNC( FT_Error ) FT_Done_Face( FT_Face face )
David Turnerd2b1f351999-12-16 23:11:37 +00001667 {
Werner Lemberga929ba92000-06-25 06:47:11 +00001668 FT_Error error;
1669 FT_Driver driver;
1670 FT_Memory memory;
1671 FT_ListNode node;
1672
David Turnerd2b1f351999-12-16 23:11:37 +00001673
David Turnerf0df85b2000-06-22 00:17:42 +00001674 error = FT_Err_Invalid_Face_Handle;
1675 if ( face && face->driver )
David Turnerd2b1f351999-12-16 23:11:37 +00001676 {
David Turnerf0df85b2000-06-22 00:17:42 +00001677 driver = face->driver;
1678 memory = driver->root.memory;
Werner Lembergdeb4e982000-06-29 03:14:25 +00001679
David Turnerf0df85b2000-06-22 00:17:42 +00001680 /* find face in driver's list */
1681 node = FT_List_Find( &driver->faces_list, face );
1682 if ( node )
1683 {
1684 /* remove face object from the driver's list */
1685 FT_List_Remove( &driver->faces_list, node );
1686 FREE( node );
Werner Lembergdeb4e982000-06-29 03:14:25 +00001687
David Turnerf0df85b2000-06-22 00:17:42 +00001688 /* now destroy the object proper */
1689 destroy_face( memory, face, driver );
1690 error = FT_Err_Ok;
1691 }
David Turnerd2b1f351999-12-16 23:11:37 +00001692 }
David Turnerd2b1f351999-12-16 23:11:37 +00001693 return error;
1694 }
1695
1696
1697 /*************************************************************************/
1698 /* */
1699 /* <Function> */
1700 /* FT_New_Size */
1701 /* */
1702 /* <Description> */
1703 /* Creates a new size object from a given face object. */
1704 /* */
1705 /* <Input> */
1706 /* face :: A handle to a parent face object. */
1707 /* */
1708 /* <Output> */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001709 /* asize :: A handle to a new size object. */
David Turnerd2b1f351999-12-16 23:11:37 +00001710 /* */
1711 /* <Return> */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001712 /* FreeType error code. 0 means success. */
David Turnerd2b1f351999-12-16 23:11:37 +00001713 /* */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001714 FT_EXPORT_FUNC( FT_Error ) FT_New_Size( FT_Face face,
1715 FT_Size* asize )
David Turnerd2b1f351999-12-16 23:11:37 +00001716 {
David Turnerf0df85b2000-06-22 00:17:42 +00001717 FT_Error error;
1718 FT_Memory memory;
1719 FT_Driver driver;
1720 FT_Driver_Class* clazz;
David Turnerd2b1f351999-12-16 23:11:37 +00001721
David Turnerf0df85b2000-06-22 00:17:42 +00001722 FT_Size size = 0;
1723 FT_ListNode node = 0;
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001724
Werner Lemberga929ba92000-06-25 06:47:11 +00001725
David Turnerf0df85b2000-06-22 00:17:42 +00001726 if ( !face || !asize || !face->driver )
1727 return FT_Err_Invalid_Handle;
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001728
Werner Lembergdeb4e982000-06-29 03:14:25 +00001729 *asize = 0;
1730
David Turnerf0df85b2000-06-22 00:17:42 +00001731 driver = face->driver;
1732 clazz = driver->clazz;
1733 memory = face->memory;
David Turnerd2b1f351999-12-16 23:11:37 +00001734
1735 /* Allocate new size object and perform basic initialisation */
David Turnerf0df85b2000-06-22 00:17:42 +00001736 if ( ALLOC( size, clazz->size_object_size ) ||
1737 ALLOC( node, sizeof ( FT_ListNodeRec ) ) )
David Turnerd2b1f351999-12-16 23:11:37 +00001738 goto Exit;
1739
1740 size->face = face;
1741
Werner Lemberga929ba92000-06-25 06:47:11 +00001742 if ( clazz->init_size )
David Turnerf0df85b2000-06-22 00:17:42 +00001743 error = clazz->init_size( size );
David Turnerd2b1f351999-12-16 23:11:37 +00001744
1745 /* in case of success, add to the face's list */
1746 if ( !error )
1747 {
1748 *asize = size;
1749 node->data = size;
1750 FT_List_Add( &face->sizes_list, node );
David Turnerd2b1f351999-12-16 23:11:37 +00001751 }
1752
1753 Exit:
1754 if ( error )
1755 {
1756 FREE( node );
1757 FREE( size );
1758 }
1759
1760 return error;
1761 }
1762
1763
1764 /*************************************************************************/
1765 /* */
1766 /* <Function> */
1767 /* FT_Done_Size */
1768 /* */
1769 /* <Description> */
1770 /* Discards a given size object. */
1771 /* */
1772 /* <Input> */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001773 /* size :: A handle to a target size object. */
David Turnerd2b1f351999-12-16 23:11:37 +00001774 /* */
1775 /* <Return> */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001776 /* FreeType error code. 0 means success. */
David Turnerd2b1f351999-12-16 23:11:37 +00001777 /* */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001778 FT_EXPORT_FUNC( FT_Error ) FT_Done_Size( FT_Size size )
David Turnerd2b1f351999-12-16 23:11:37 +00001779 {
1780 FT_Error error;
1781 FT_Driver driver;
1782 FT_Memory memory;
1783 FT_Face face;
1784 FT_ListNode node;
1785
1786
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001787 if ( !size )
David Turnerd2b1f351999-12-16 23:11:37 +00001788 return FT_Err_Invalid_Size_Handle;
1789
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001790 face = size->face;
1791 if ( !face )
1792 return FT_Err_Invalid_Face_Handle;
1793
1794 driver = face->driver;
David Turnerd2b1f351999-12-16 23:11:37 +00001795 if ( !driver )
1796 return FT_Err_Invalid_Driver_Handle;
1797
David Turnerf0df85b2000-06-22 00:17:42 +00001798 memory = driver->root.memory;
David Turnerd2b1f351999-12-16 23:11:37 +00001799
1800 error = FT_Err_Ok;
David Turnerd2b1f351999-12-16 23:11:37 +00001801 node = FT_List_Find( &face->sizes_list, size );
1802 if ( node )
1803 {
1804 FT_List_Remove( &face->sizes_list, node );
1805 FREE( node );
1806
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001807 if ( face->size == size )
David Turnerd2b1f351999-12-16 23:11:37 +00001808 {
1809 face->size = 0;
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001810 if ( face->sizes_list.head )
David Turnerd2b1f351999-12-16 23:11:37 +00001811 face->size = (FT_Size)(face->sizes_list.head->data);
1812 }
1813
1814 destroy_size( memory, size, driver );
1815 }
1816 else
1817 error = FT_Err_Invalid_Size_Handle;
1818
1819 return FT_Err_Ok;
1820 }
1821
1822
Werner Lembergdeb4e982000-06-29 03:14:25 +00001823 static
1824 void ft_recompute_scaled_metrics( FT_Face face,
1825 FT_Size_Metrics* metrics )
1826 {
Werner Lemberga929ba92000-06-25 06:47:11 +00001827 /* Compute root ascender, descender, test height, and max_advance */
Werner Lembergdeb4e982000-06-29 03:14:25 +00001828
Werner Lemberga929ba92000-06-25 06:47:11 +00001829 metrics->ascender = ( FT_MulFix( face->ascender,
1830 metrics->y_scale ) + 32 ) & -64;
1831
1832 metrics->descender = ( FT_MulFix( face->descender,
1833 metrics->y_scale ) + 32 ) & -64;
1834
1835 metrics->height = ( FT_MulFix( face->height,
1836 metrics->y_scale ) + 32 ) & -64;
1837
1838 metrics->max_advance = ( FT_MulFix( face->max_advance_width,
1839 metrics->x_scale ) + 32 ) & -64;
1840 }
1841
1842
David Turnerd2b1f351999-12-16 23:11:37 +00001843 /*************************************************************************/
1844 /* */
1845 /* <Function> */
1846 /* FT_Set_Char_Size */
1847 /* */
1848 /* <Description> */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001849 /* Sets the character dimensions of a given face object. The */
1850 /* `char_width' and `char_height' values are used for the width and */
1851 /* height, respectively, expressed in 26.6 fractional points. */
1852 /* */
1853 /* If the horizontal or vertical resolution values are zero, a */
1854 /* default value of 72dpi is used. Similarly, if one of the */
1855 /* character dimensions is zero, its value is set equal to the other. */
1856 /* */
1857 /* <InOut> */
1858 /* size :: A handle to a target size object. */
David Turnerd2b1f351999-12-16 23:11:37 +00001859 /* */
1860 /* <Input> */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001861 /* char_width :: The character width, in 26.6 fractional points. */
1862 /* */
1863 /* char_height :: The character height, in 26.6 fractional */
1864 /* points. */
1865 /* */
1866 /* horz_resolution :: The horizontal resolution. */
1867 /* */
1868 /* vert_resolution :: The vertical resolution. */
David Turnerd2b1f351999-12-16 23:11:37 +00001869 /* */
1870 /* <Return> */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001871 /* FreeType error code. 0 means success. */
David Turnerd2b1f351999-12-16 23:11:37 +00001872 /* */
1873 /* <Note> */
1874 /* When dealing with fixed-size faces (i.e., non-scalable formats), */
1875 /* use the function FT_Set_Pixel_Sizes(). */
1876 /* */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001877 FT_EXPORT_FUNC( FT_Error ) FT_Set_Char_Size( FT_Face face,
1878 FT_F26Dot6 char_width,
1879 FT_F26Dot6 char_height,
1880 FT_UInt horz_resolution,
1881 FT_UInt vert_resolution )
David Turnerd2b1f351999-12-16 23:11:37 +00001882 {
David Turnerf0df85b2000-06-22 00:17:42 +00001883 FT_Error error = FT_Err_Ok;
1884 FT_Driver driver;
1885 FT_Memory memory;
1886 FT_Driver_Class* clazz;
1887 FT_Size_Metrics* metrics;
1888 FT_Long dim_x, dim_y;
David Turnerd2b1f351999-12-16 23:11:37 +00001889
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001890
David Turnerf0df85b2000-06-22 00:17:42 +00001891 if ( !face || !face->size || !face->driver )
David Turnerd2b1f351999-12-16 23:11:37 +00001892 return FT_Err_Invalid_Face_Handle;
1893
David Turnerf0df85b2000-06-22 00:17:42 +00001894 driver = face->driver;
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001895 metrics = &face->size->metrics;
1896
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001897 if ( !char_width )
David Turnerd2b1f351999-12-16 23:11:37 +00001898 char_width = char_height;
Werner Lembergdeb4e982000-06-29 03:14:25 +00001899
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001900 else if ( !char_height )
David Turnerd2b1f351999-12-16 23:11:37 +00001901 char_height = char_width;
Werner Lemberg7880dd62000-01-10 17:19:45 +00001902
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001903 if ( !horz_resolution )
David Turnerd2b1f351999-12-16 23:11:37 +00001904 horz_resolution = 72;
Werner Lembergdeb4e982000-06-29 03:14:25 +00001905
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001906 if ( !vert_resolution )
David Turnerd2b1f351999-12-16 23:11:37 +00001907 vert_resolution = 72;
1908
David Turnerf0df85b2000-06-22 00:17:42 +00001909 driver = face->driver;
1910 clazz = driver->clazz;
1911 memory = driver->root.memory;
David Turnerd2b1f351999-12-16 23:11:37 +00001912
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001913 /* default processing -- this can be overridden by the driver */
Werner Lembergdeb4e982000-06-29 03:14:25 +00001914 if ( char_width < 1 * 64 )
1915 char_width = 1 * 64;
1916 if ( char_height < 1 * 64 )
1917 char_height = 1 * 64;
David Turnerd42c68e2000-01-27 13:56:02 +00001918
1919 /* Compute pixel sizes in 26.6 units */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001920 dim_x = ( ( ( char_width * horz_resolution ) / 72 ) + 32 ) & -64;
1921 dim_y = ( ( ( char_height * vert_resolution ) / 72 ) + 32 ) & -64;
David Turnerd42c68e2000-01-27 13:56:02 +00001922
Werner Lembergdeb4e982000-06-29 03:14:25 +00001923 metrics->x_ppem = (FT_UShort)( dim_x >> 6 );
1924 metrics->y_ppem = (FT_UShort)( dim_y >> 6 );
David Turnerd42c68e2000-01-27 13:56:02 +00001925
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001926 metrics->x_scale = 0x10000L;
1927 metrics->y_scale = 0x10000L;
1928
1929 if ( face->face_flags & FT_FACE_FLAG_SCALABLE )
David Turnerd42c68e2000-01-27 13:56:02 +00001930 {
1931 metrics->x_scale = FT_DivFix( dim_x, face->units_per_EM );
1932 metrics->y_scale = FT_DivFix( dim_y, face->units_per_EM );
1933 }
1934
David Turnerf0df85b2000-06-22 00:17:42 +00001935 ft_recompute_scaled_metrics( face, metrics );
1936
Werner Lemberga929ba92000-06-25 06:47:11 +00001937 if ( clazz->set_char_sizes )
David Turnerf0df85b2000-06-22 00:17:42 +00001938 error = clazz->set_char_sizes( face->size,
1939 char_width,
1940 char_height,
1941 horz_resolution,
1942 vert_resolution );
David Turnerd2b1f351999-12-16 23:11:37 +00001943 return error;
1944 }
1945
1946
1947 /*************************************************************************/
1948 /* */
1949 /* <Function> */
1950 /* FT_Set_Pixel_Sizes */
1951 /* */
1952 /* <Description> */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001953 /* Sets the character dimensions of a given face object. The width */
David Turnerd2b1f351999-12-16 23:11:37 +00001954 /* and height are expressed in integer pixels. */
1955 /* */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001956 /* If one of the character dimensions is zero, its value is set equal */
1957 /* to the other. */
1958 /* */
1959 /* <InOut> */
1960 /* face :: A handle to the target face object. */
1961 /* */
David Turnerd2b1f351999-12-16 23:11:37 +00001962 /* <Input> */
David Turnerd2b1f351999-12-16 23:11:37 +00001963 /* pixel_width :: The character width, in integer pixels. */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001964 /* */
David Turnerd2b1f351999-12-16 23:11:37 +00001965 /* pixel_height :: The character height, in integer pixels. */
1966 /* */
1967 /* <Return> */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001968 /* FreeType error code. 0 means success. */
David Turnerd2b1f351999-12-16 23:11:37 +00001969 /* */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001970 FT_EXPORT_FUNC( FT_Error ) FT_Set_Pixel_Sizes( FT_Face face,
1971 FT_UInt pixel_width,
1972 FT_UInt pixel_height )
David Turnerd2b1f351999-12-16 23:11:37 +00001973 {
David Turnerf0df85b2000-06-22 00:17:42 +00001974 FT_Error error = FT_Err_Ok;
1975 FT_Driver driver;
1976 FT_Memory memory;
1977 FT_Driver_Class* clazz;
1978 FT_Size_Metrics* metrics = &face->size->metrics;
David Turnerd2b1f351999-12-16 23:11:37 +00001979
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001980
David Turnerf0df85b2000-06-22 00:17:42 +00001981 if ( !face || !face->size || !face->driver )
David Turnerd2b1f351999-12-16 23:11:37 +00001982 return FT_Err_Invalid_Face_Handle;
1983
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001984 driver = face->driver;
David Turnerf0df85b2000-06-22 00:17:42 +00001985 clazz = driver->clazz;
1986 memory = driver->root.memory;
David Turnerd2b1f351999-12-16 23:11:37 +00001987
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001988 /* default processing -- this can be overridden by the driver */
1989 if ( pixel_width == 0 )
David Turner11187202000-05-26 17:13:23 +00001990 pixel_width = pixel_height;
David Turnerf0df85b2000-06-22 00:17:42 +00001991
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001992 else if ( pixel_height == 0 )
David Turner11187202000-05-26 17:13:23 +00001993 pixel_height = pixel_width;
Werner Lembergeb81e372000-06-03 06:03:11 +00001994
Werner Lembergdeb4e982000-06-29 03:14:25 +00001995 if ( pixel_width < 1 )
1996 pixel_width = 1;
1997 if ( pixel_height < 1 )
1998 pixel_height = 1;
David Turnerd2b1f351999-12-16 23:11:37 +00001999
David Turnerd42c68e2000-01-27 13:56:02 +00002000 metrics->x_ppem = pixel_width;
2001 metrics->y_ppem = pixel_height;
2002
2003 if ( face->face_flags & FT_FACE_FLAG_SCALABLE )
2004 {
2005 metrics->x_scale = FT_DivFix( metrics->x_ppem << 6,
2006 face->units_per_EM );
2007
2008 metrics->y_scale = FT_DivFix( metrics->y_ppem << 6,
2009 face->units_per_EM );
2010 }
2011
David Turnerf0df85b2000-06-22 00:17:42 +00002012 ft_recompute_scaled_metrics( face, metrics );
David Turnerd2b1f351999-12-16 23:11:37 +00002013
Werner Lemberga929ba92000-06-25 06:47:11 +00002014 if ( clazz->set_pixel_sizes )
David Turnerf0df85b2000-06-22 00:17:42 +00002015 error = clazz->set_pixel_sizes( face->size,
2016 pixel_width,
2017 pixel_height );
David Turnerd2b1f351999-12-16 23:11:37 +00002018 return error;
2019 }
2020
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00002021
David Turnerd2b1f351999-12-16 23:11:37 +00002022 /*************************************************************************/
2023 /* */
2024 /* <Function> */
2025 /* FT_Get_Kerning */
2026 /* */
2027 /* <Description> */
2028 /* Returns the kerning vector between two glyphs of a same face. */
2029 /* */
2030 /* <Input> */
2031 /* face :: A handle to a source face object. */
2032 /* */
2033 /* left_glyph :: The index of the left glyph in the kern pair. */
2034 /* */
2035 /* right_glyph :: The index of the right glyph in the kern pair. */
2036 /* */
2037 /* <Output> */
2038 /* kerning :: The kerning vector. This is in font units for */
2039 /* scalable formats, and in pixels for fixed-sizes */
2040 /* formats. */
2041 /* */
2042 /* <Return> */
2043 /* FreeType error code. 0 means success. */
2044 /* */
2045 /* <Note> */
2046 /* Only horizontal layouts (left-to-right & right-to-left) are */
2047 /* supported by this method. Other layouts, or more sophisticated */
2048 /* kernings, are out of the scope of this API function -- they can be */
2049 /* implemented through format-specific interfaces. */
2050 /* */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00002051 FT_EXPORT_FUNC( FT_Error ) FT_Get_Kerning( FT_Face face,
2052 FT_UInt left_glyph,
2053 FT_UInt right_glyph,
2054 FT_Vector* kerning )
David Turnerd2b1f351999-12-16 23:11:37 +00002055 {
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00002056 FT_Error error = FT_Err_Ok;
David Turnerd2b1f351999-12-16 23:11:37 +00002057 FT_Driver driver;
2058 FT_Memory memory;
2059
2060
2061 if ( !face )
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00002062 return FT_Err_Invalid_Face_Handle;
2063
2064 if ( !kerning )
2065 return FT_Err_Invalid_Argument;
David Turnerd2b1f351999-12-16 23:11:37 +00002066
2067 driver = face->driver;
David Turnerf0df85b2000-06-22 00:17:42 +00002068 memory = driver->root.memory;
David Turnerd2b1f351999-12-16 23:11:37 +00002069
David Turnerf0df85b2000-06-22 00:17:42 +00002070 if ( driver->clazz->get_kerning )
David Turnerd2b1f351999-12-16 23:11:37 +00002071 {
David Turnerf0df85b2000-06-22 00:17:42 +00002072 error = driver->clazz->get_kerning( face,
Werner Lemberga929ba92000-06-25 06:47:11 +00002073 left_glyph,
2074 right_glyph,
2075 kerning );
David Turnerd2b1f351999-12-16 23:11:37 +00002076 }
2077 else
2078 {
2079 kerning->x = 0;
2080 kerning->y = 0;
David Turnerd2b1f351999-12-16 23:11:37 +00002081 }
2082
David Turnerd2b1f351999-12-16 23:11:37 +00002083 return error;
2084 }
2085
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00002086
David Turner0a29c692000-05-12 17:09:38 +00002087 /*************************************************************************/
2088 /* */
2089 /* <Function> */
2090 /* FT_Select_Charmap */
2091 /* */
2092 /* <Description> */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00002093 /* Selects a given charmap by its encoding tag (as listed in */
2094 /* `freetype.h'). */
David Turner0a29c692000-05-12 17:09:38 +00002095 /* */
2096 /* <Input> */
2097 /* face :: A handle to the source face object. */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00002098 /* */
2099 /* encoding :: A handle to the selected charmap. */
David Turner0a29c692000-05-12 17:09:38 +00002100 /* */
2101 /* <Return> */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00002102 /* FreeType error code. 0 means success. */
David Turner0a29c692000-05-12 17:09:38 +00002103 /* */
2104 /* <Note> */
2105 /* This function will return an error if no charmap in the face */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00002106 /* corresponds to the encoding queried here. */
David Turner0a29c692000-05-12 17:09:38 +00002107 /* */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00002108 FT_EXPORT_FUNC( FT_Error ) FT_Select_Charmap( FT_Face face,
2109 FT_Encoding encoding )
David Turner0a29c692000-05-12 17:09:38 +00002110 {
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00002111 FT_CharMap* cur;
2112 FT_CharMap* limit;
David Turnere49ab252000-05-16 23:44:38 +00002113
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00002114
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00002115 if ( !face )
2116 return FT_Err_Invalid_Face_Handle;
2117
2118 cur = face->charmaps;
2119 if ( !cur )
2120 return FT_Err_Invalid_CharMap_Handle;
2121
2122 limit = cur + face->num_charmaps;
2123
David Turner0a29c692000-05-12 17:09:38 +00002124 for ( ; cur < limit; cur++ )
2125 {
2126 if ( cur[0]->encoding == encoding )
2127 {
2128 face->charmap = cur[0];
2129 return 0;
2130 }
2131 }
Werner Lembergdeb4e982000-06-29 03:14:25 +00002132
David Turner0a29c692000-05-12 17:09:38 +00002133 return FT_Err_Invalid_Argument;
2134 }
2135
2136
2137 /*************************************************************************/
2138 /* */
2139 /* <Function> */
2140 /* FT_Set_Charmap */
2141 /* */
2142 /* <Description> */
2143 /* Selects a given charmap for character code to glyph index */
2144 /* decoding. */
2145 /* */
2146 /* <Input> */
2147 /* face :: A handle to the source face object. */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00002148 /* charmap :: A handle to the selected charmap. */
David Turner0a29c692000-05-12 17:09:38 +00002149 /* */
2150 /* <Return> */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00002151 /* FreeType error code. 0 means success. */
David Turner0a29c692000-05-12 17:09:38 +00002152 /* */
2153 /* <Note> */
Werner Lembergdeb4e982000-06-29 03:14:25 +00002154 /* This function will return an error if the charmap is not part of */
2155 /* the face (i.e., if it is not listed in the face->charmaps[] */
David Turner0a29c692000-05-12 17:09:38 +00002156 /* table). */
2157 /* */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00002158 FT_EXPORT_FUNC( FT_Error ) FT_Set_Charmap( FT_Face face,
2159 FT_CharMap charmap )
David Turner0a29c692000-05-12 17:09:38 +00002160 {
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00002161 FT_CharMap* cur;
2162 FT_CharMap* limit;
David Turnere49ab252000-05-16 23:44:38 +00002163
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00002164
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00002165 if ( !face )
2166 return FT_Err_Invalid_Face_Handle;
2167
2168 cur = face->charmaps;
2169 if ( !cur )
2170 return FT_Err_Invalid_CharMap_Handle;
2171
2172 limit = cur + face->num_charmaps;
2173
David Turner0a29c692000-05-12 17:09:38 +00002174 for ( ; cur < limit; cur++ )
2175 {
2176 if ( cur[0] == charmap )
2177 {
2178 face->charmap = cur[0];
2179 return 0;
2180 }
2181 }
2182 return FT_Err_Invalid_Argument;
2183 }
David Turnerd2b1f351999-12-16 23:11:37 +00002184
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00002185
David Turnerd2b1f351999-12-16 23:11:37 +00002186 /*************************************************************************/
2187 /* */
2188 /* <Function> */
2189 /* FT_Get_Char_Index */
2190 /* */
2191 /* <Description> */
2192 /* Returns the glyph index of a given character code. This function */
2193 /* uses a charmap object to do the translation. */
2194 /* */
2195 /* <Input> */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00002196 /* face :: A handle to the source face object. */
David Turnerd2b1f351999-12-16 23:11:37 +00002197 /* charcode :: The character code. */
2198 /* */
2199 /* <Return> */
2200 /* The glyph index. 0 means `undefined character code'. */
2201 /* */
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00002202 FT_EXPORT_FUNC( FT_UInt ) FT_Get_Char_Index( FT_Face face,
2203 FT_ULong charcode )
David Turnerd2b1f351999-12-16 23:11:37 +00002204 {
2205 FT_UInt result;
2206 FT_Driver driver;
2207
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00002208
David Turnerd2b1f351999-12-16 23:11:37 +00002209 result = 0;
2210 if ( face && face->charmap )
2211 {
2212 driver = face->driver;
David Turnerf0df85b2000-06-22 00:17:42 +00002213 result = driver->clazz->get_char_index( face->charmap, charcode );
David Turnerd2b1f351999-12-16 23:11:37 +00002214 }
2215 return result;
2216 }
2217
David Turnerd2b1f351999-12-16 23:11:37 +00002218
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00002219 /*************************************************************************/
2220 /* */
2221 /* <Function> */
2222 /* FT_Get_Sfnt_Table */
2223 /* */
2224 /* <Description> */
2225 /* Returns a pointer to a given SFNT table within a face. */
2226 /* */
2227 /* <Input> */
2228 /* face :: A handle to the source face object. */
2229 /* tag :: An index of an SFNT table. */
2230 /* */
2231 /* <Return> */
2232 /* A type-less pointer to the table. This will be 0 in case of */
2233 /* error, or if the corresponding table was not found *OR* loaded */
2234 /* from the file. */
2235 /* */
2236 /* <Note> */
2237 /* The table is owned by the face object, and disappears with it. */
2238 /* */
2239 /* This function is only useful to access SFNT tables that are loaded */
2240 /* by the sfnt/truetype/opentype drivers. See the FT_Sfnt_Tag */
2241 /* enumeration in `tttables.h' for a list. */
2242 /* */
2243 /* You can load any table with a different function.. XXX */
2244 /* */
2245 FT_EXPORT_FUNC( void* ) FT_Get_Sfnt_Table( FT_Face face,
2246 FT_Sfnt_Tag tag )
David Turner99a4d932000-04-25 16:10:50 +00002247 {
2248 void* table = 0;
2249 FT_Get_Sfnt_Table_Func func;
2250 FT_Driver driver;
David Turnere49ab252000-05-16 23:44:38 +00002251
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00002252
2253 if ( !face || !FT_IS_SFNT( face ) )
David Turner99a4d932000-04-25 16:10:50 +00002254 goto Exit;
David Turnere49ab252000-05-16 23:44:38 +00002255
David Turner99a4d932000-04-25 16:10:50 +00002256 driver = face->driver;
David Turnerf0df85b2000-06-22 00:17:42 +00002257 func = (FT_Get_Sfnt_Table_Func)driver->root.clazz->get_interface(
Werner Lemberga929ba92000-06-25 06:47:11 +00002258 FT_MODULE( driver ), "get_sfnt" );
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00002259 if ( func )
2260 table = func( face, tag );
David Turnere49ab252000-05-16 23:44:38 +00002261
David Turner99a4d932000-04-25 16:10:50 +00002262 Exit:
2263 return table;
David Turnere49ab252000-05-16 23:44:38 +00002264 }
David Turner99a4d932000-04-25 16:10:50 +00002265
2266
David Turnerd2b1f351999-12-16 23:11:37 +00002267 /*************************************************************************/
David Turnerf0df85b2000-06-22 00:17:42 +00002268 /*************************************************************************/
2269 /*************************************************************************/
2270 /**** ****/
2271 /**** ****/
2272 /**** R E N D E R E R S ****/
2273 /**** ****/
2274 /**** ****/
2275 /*************************************************************************/
2276 /*************************************************************************/
2277 /*************************************************************************/
2278
Werner Lembergdeb4e982000-06-29 03:14:25 +00002279 /* lookup a renderer by glyph format in the library's list */
2280 BASE_FUNC( FT_Renderer ) FT_Lookup_Renderer( FT_Library library,
2281 FT_Glyph_Format format,
2282 FT_ListNode* node )
David Turnerf0df85b2000-06-22 00:17:42 +00002283 {
Werner Lembergdeb4e982000-06-29 03:14:25 +00002284 FT_ListNode cur;
David Turnerf0df85b2000-06-22 00:17:42 +00002285 FT_Renderer result = 0;
Werner Lemberga929ba92000-06-25 06:47:11 +00002286
Werner Lembergdeb4e982000-06-29 03:14:25 +00002287
2288 if ( !library )
2289 goto Exit;
2290
2291 cur = library->renderers.head;
2292
2293 if ( node )
David Turner74abee82000-06-27 23:31:53 +00002294 {
Werner Lembergdeb4e982000-06-29 03:14:25 +00002295 if ( *node )
David Turner74abee82000-06-27 23:31:53 +00002296 cur = (*node)->next;
David Turnerf0df85b2000-06-22 00:17:42 +00002297 *node = 0;
David Turner74abee82000-06-27 23:31:53 +00002298 }
Werner Lembergdeb4e982000-06-29 03:14:25 +00002299
Werner Lemberga929ba92000-06-25 06:47:11 +00002300 while ( cur )
David Turnerf0df85b2000-06-22 00:17:42 +00002301 {
Werner Lemberga929ba92000-06-25 06:47:11 +00002302 FT_Renderer renderer = FT_RENDERER( cur->data );
Werner Lembergdeb4e982000-06-29 03:14:25 +00002303
Werner Lemberga929ba92000-06-25 06:47:11 +00002304
2305 if ( renderer->glyph_format == format )
David Turnerf0df85b2000-06-22 00:17:42 +00002306 {
Werner Lemberga929ba92000-06-25 06:47:11 +00002307 if ( node )
David Turnerf0df85b2000-06-22 00:17:42 +00002308 *node = cur;
Werner Lembergdeb4e982000-06-29 03:14:25 +00002309
David Turnerf0df85b2000-06-22 00:17:42 +00002310 result = renderer;
2311 break;
2312 }
David Turner74abee82000-06-27 23:31:53 +00002313 cur = cur->next;
David Turnerf0df85b2000-06-22 00:17:42 +00002314 }
Werner Lemberga929ba92000-06-25 06:47:11 +00002315
Werner Lembergdeb4e982000-06-29 03:14:25 +00002316 Exit:
David Turnerf0df85b2000-06-22 00:17:42 +00002317 return result;
2318 }
2319
Werner Lemberga929ba92000-06-25 06:47:11 +00002320
Werner Lembergdeb4e982000-06-29 03:14:25 +00002321 static
2322 FT_Renderer ft_lookup_glyph_renderer( FT_GlyphSlot slot )
2323 {
2324 FT_Face face = slot->face;
2325 FT_Library library = FT_FACE_LIBRARY( face );
2326 FT_Renderer result = library->cur_renderer;
2327
2328
Werner Lemberga929ba92000-06-25 06:47:11 +00002329 if ( !result || result->glyph_format != slot->format )
David Turner81bb4ad2000-06-28 04:19:49 +00002330 result = FT_Lookup_Renderer( library, slot->format, 0 );
David Turnerf0df85b2000-06-22 00:17:42 +00002331
2332 return result;
2333 }
2334
Werner Lembergdeb4e982000-06-29 03:14:25 +00002335
2336 static
2337 void ft_set_current_renderer( FT_Library library )
David Turnerf0df85b2000-06-22 00:17:42 +00002338 {
2339 FT_Renderer renderer;
2340
Werner Lembergdeb4e982000-06-29 03:14:25 +00002341
David Turner74abee82000-06-27 23:31:53 +00002342 renderer = FT_Lookup_Renderer( library, ft_glyph_format_outline, 0 );
David Turnerf0df85b2000-06-22 00:17:42 +00002343 library->cur_renderer = renderer;
2344 }
2345
2346
Werner Lembergdeb4e982000-06-29 03:14:25 +00002347 static
2348 FT_Error ft_add_renderer( FT_Module module )
David Turnerf0df85b2000-06-22 00:17:42 +00002349 {
2350 FT_Library library = module->library;
2351 FT_Memory memory = library->memory;
2352 FT_Error error;
2353 FT_ListNode node;
Werner Lembergdeb4e982000-06-29 03:14:25 +00002354
2355
Werner Lemberga929ba92000-06-25 06:47:11 +00002356 if ( ALLOC( node, sizeof ( *node ) ) )
David Turnerf0df85b2000-06-22 00:17:42 +00002357 goto Exit;
Werner Lembergdeb4e982000-06-29 03:14:25 +00002358
David Turnerf0df85b2000-06-22 00:17:42 +00002359 {
Werner Lemberga929ba92000-06-25 06:47:11 +00002360 FT_Renderer render = FT_RENDERER( module );
David Turnerf0df85b2000-06-22 00:17:42 +00002361 FT_Renderer_Class* clazz = (FT_Renderer_Class*)module->clazz;
2362
Werner Lemberga929ba92000-06-25 06:47:11 +00002363
David Turnerf0df85b2000-06-22 00:17:42 +00002364 render->clazz = clazz;
2365 render->glyph_format = clazz->glyph_format;
Werner Lembergdeb4e982000-06-29 03:14:25 +00002366
David Turnerf0df85b2000-06-22 00:17:42 +00002367 /* allocate raster object if needed */
2368 if ( clazz->glyph_format == ft_glyph_format_outline &&
2369 clazz->raster_class->raster_new )
2370 {
2371 error = clazz->raster_class->raster_new( memory, &render->raster );
Werner Lemberga929ba92000-06-25 06:47:11 +00002372 if ( error )
2373 goto Fail;
Werner Lembergdeb4e982000-06-29 03:14:25 +00002374
David Turnerf0df85b2000-06-22 00:17:42 +00002375 render->raster_render = clazz->raster_class->raster_render;
2376 render->render = clazz->render_glyph;
Werner Lembergdeb4e982000-06-29 03:14:25 +00002377 }
2378
David Turnerf0df85b2000-06-22 00:17:42 +00002379 /* add to list */
2380 node->data = module;
2381 FT_List_Add( &library->renderers, node );
2382
2383 ft_set_current_renderer( library );
2384 }
2385
2386 Fail:
Werner Lemberga929ba92000-06-25 06:47:11 +00002387 if ( error )
2388 FREE( node );
David Turnerf0df85b2000-06-22 00:17:42 +00002389
2390 Exit:
2391 return error;
Werner Lembergdeb4e982000-06-29 03:14:25 +00002392 }
David Turnerf0df85b2000-06-22 00:17:42 +00002393
2394
Werner Lembergdeb4e982000-06-29 03:14:25 +00002395 static
2396 void ft_remove_renderer( FT_Module module )
David Turnerf0df85b2000-06-22 00:17:42 +00002397 {
2398 FT_Library library = module->library;
2399 FT_Memory memory = library->memory;
2400 FT_ListNode node;
2401
Werner Lemberga929ba92000-06-25 06:47:11 +00002402
David Turnerf0df85b2000-06-22 00:17:42 +00002403 node = FT_List_Find( &library->renderers, module );
Werner Lemberga929ba92000-06-25 06:47:11 +00002404 if ( node )
David Turnerf0df85b2000-06-22 00:17:42 +00002405 {
Werner Lemberga929ba92000-06-25 06:47:11 +00002406 FT_Renderer render = FT_RENDERER( module );
Werner Lembergdeb4e982000-06-29 03:14:25 +00002407
Werner Lemberga929ba92000-06-25 06:47:11 +00002408
David Turnerf0df85b2000-06-22 00:17:42 +00002409 /* release raster object, if any */
Werner Lemberga929ba92000-06-25 06:47:11 +00002410 if ( render->raster )
David Turnerf0df85b2000-06-22 00:17:42 +00002411 render->clazz->raster_class->raster_done( render->raster );
Werner Lembergdeb4e982000-06-29 03:14:25 +00002412
David Turnerf0df85b2000-06-22 00:17:42 +00002413 /* remove from list */
2414 FT_List_Remove( &library->renderers, node );
2415 FREE( node );
Werner Lembergdeb4e982000-06-29 03:14:25 +00002416
David Turnerf0df85b2000-06-22 00:17:42 +00002417 ft_set_current_renderer( library );
2418 }
2419 }
2420
2421
Werner Lemberga929ba92000-06-25 06:47:11 +00002422 /*************************************************************************/
2423 /* */
2424 /* <Function> */
2425 /* FT_Get_Renderer */
2426 /* */
2427 /* <Description> */
2428 /* Retrieves the current renderer for a given glyph format. */
2429 /* */
2430 /* <Input> */
2431 /* library :: A handle to the library object. */
2432 /* */
2433 /* format :: The glyph format. */
2434 /* */
2435 /* <Return> */
2436 /* A renderer handle. 0 if none found. */
2437 /* */
2438 /* <Note> */
2439 /* An error will be returned if a module already exists by that name, */
2440 /* or if the module requires a version of FreeType that is too great. */
2441 /* */
2442 /* To add a new renderer, simply use FT_Add_Module(). To retrieve a */
2443 /* renderer by its name, use FT_Get_Module(). */
Werner Lembergdcd2e142000-06-25 07:43:15 +00002444 /* */
Werner Lemberga929ba92000-06-25 06:47:11 +00002445 FT_EXPORT_FUNC( FT_Renderer ) FT_Get_Renderer( FT_Library library,
2446 FT_Glyph_Format format )
David Turnerf0df85b2000-06-22 00:17:42 +00002447 {
Werner Lembergdeb4e982000-06-29 03:14:25 +00002448 /* test for valid `library' delayed to FT_Lookup_Renderer() */
2449
David Turner74abee82000-06-27 23:31:53 +00002450 return FT_Lookup_Renderer( library, format, 0 );
Werner Lembergdeb4e982000-06-29 03:14:25 +00002451 }
David Turnerf0df85b2000-06-22 00:17:42 +00002452
2453
Werner Lemberga929ba92000-06-25 06:47:11 +00002454 /*************************************************************************/
2455 /* */
2456 /* <Function> */
2457 /* FT_Set_Renderer */
2458 /* */
2459 /* <Description> */
2460 /* Sets the current renderer to use, and set additional mode. */
2461 /* */
2462 /* <Input> */
2463 /* library :: A handle to the library object. */
2464 /* */
2465 /* renderer :: A handle to the renderer object. */
2466 /* */
2467 /* num_params :: The number of additional parameters. */
2468 /* */
2469 /* params :: Additional parameters. */
2470 /* */
2471 /* <Return> */
2472 /* FreeType error code. 0 means success. */
2473 /* */
2474 /* <Note> */
2475 /* In case of success, the renderer will be used to convert glyph */
2476 /* images in the renderer's known format into bitmaps. */
2477 /* */
2478 /* This doesn't change the current renderer for other formats. */
2479 /* */
Werner Lembergdeb4e982000-06-29 03:14:25 +00002480 FT_EXPORT_DEF( FT_Error ) FT_Set_Renderer( FT_Library library,
2481 FT_Renderer renderer,
2482 FT_UInt num_params,
2483 FT_Parameter* parameters )
David Turnerf0df85b2000-06-22 00:17:42 +00002484 {
2485 FT_ListNode node;
2486 FT_Error error = FT_Err_Ok;
Werner Lembergdeb4e982000-06-29 03:14:25 +00002487
2488
2489 if ( !library )
2490 return FT_Err_Invalid_Library_Handle;
2491
2492 if ( !renderer )
2493 return FT_Err_Invalid_Argument;
Werner Lemberga929ba92000-06-25 06:47:11 +00002494
David Turnerf0df85b2000-06-22 00:17:42 +00002495 node = FT_List_Find( &library->renderers, renderer );
Werner Lemberga929ba92000-06-25 06:47:11 +00002496 if ( !node )
David Turnerf0df85b2000-06-22 00:17:42 +00002497 {
2498 error = FT_Err_Invalid_Argument;
2499 goto Exit;
2500 }
David Turner74abee82000-06-27 23:31:53 +00002501
David Turnerf0df85b2000-06-22 00:17:42 +00002502 FT_List_Up( &library->renderers, node );
Werner Lembergdeb4e982000-06-29 03:14:25 +00002503
Werner Lemberga929ba92000-06-25 06:47:11 +00002504 if ( renderer->glyph_format == ft_glyph_format_outline )
David Turnerf0df85b2000-06-22 00:17:42 +00002505 library->cur_renderer = renderer;
Werner Lembergdeb4e982000-06-29 03:14:25 +00002506
Werner Lemberga929ba92000-06-25 06:47:11 +00002507 if ( num_params > 0 )
David Turnerf0df85b2000-06-22 00:17:42 +00002508 {
2509 FTRenderer_setMode set_mode = renderer->clazz->set_mode;
Werner Lembergdeb4e982000-06-29 03:14:25 +00002510
Werner Lemberga929ba92000-06-25 06:47:11 +00002511
David Turnerf0df85b2000-06-22 00:17:42 +00002512 for ( ; num_params > 0; num_params-- )
2513 {
2514 error = set_mode( renderer, parameters->tag, parameters->data );
Werner Lemberga929ba92000-06-25 06:47:11 +00002515 if ( error )
David Turnerf0df85b2000-06-22 00:17:42 +00002516 break;
2517 }
2518 }
Werner Lembergdeb4e982000-06-29 03:14:25 +00002519
David Turnerf0df85b2000-06-22 00:17:42 +00002520 Exit:
2521 return error;
Werner Lembergdeb4e982000-06-29 03:14:25 +00002522 }
David Turnerf0df85b2000-06-22 00:17:42 +00002523
2524
David Turner74abee82000-06-27 23:31:53 +00002525 LOCAL_FUNC
Werner Lembergdeb4e982000-06-29 03:14:25 +00002526 FT_Error FT_Render_Glyph_Internal( FT_Library library,
2527 FT_GlyphSlot slot,
2528 FT_UInt render_mode )
David Turnerf0df85b2000-06-22 00:17:42 +00002529 {
2530 FT_Error error = FT_Err_Ok;
2531 FT_Renderer renderer;
Werner Lemberga929ba92000-06-25 06:47:11 +00002532
Werner Lembergdeb4e982000-06-29 03:14:25 +00002533
2534 /* if it is already a bitmap, no need to do anything */
2535 switch ( slot->format )
David Turnerf0df85b2000-06-22 00:17:42 +00002536 {
Werner Lembergdeb4e982000-06-29 03:14:25 +00002537 case ft_glyph_format_bitmap: /* already a bitmap, don't do anything */
2538 break;
2539
2540 default:
David Turner74abee82000-06-27 23:31:53 +00002541 {
2542 FT_ListNode node = 0;
2543 FT_Bool update = 0;
Werner Lembergdeb4e982000-06-29 03:14:25 +00002544
2545
Werner Lemberga929ba92000-06-25 06:47:11 +00002546 /* small shortcut for the very common case */
Werner Lembergdeb4e982000-06-29 03:14:25 +00002547 if ( slot->format == ft_glyph_format_outline )
David Turner74abee82000-06-27 23:31:53 +00002548 {
Werner Lemberga929ba92000-06-25 06:47:11 +00002549 renderer = library->cur_renderer;
David Turner74abee82000-06-27 23:31:53 +00002550 node = library->renderers.head;
2551 }
Werner Lemberga929ba92000-06-25 06:47:11 +00002552 else
David Turner74abee82000-06-27 23:31:53 +00002553 renderer = FT_Lookup_Renderer( library, slot->format, &node );
2554
Werner Lemberga929ba92000-06-25 06:47:11 +00002555 error = FT_Err_Unimplemented_Feature;
Werner Lembergdeb4e982000-06-29 03:14:25 +00002556 while ( renderer )
David Turner74abee82000-06-27 23:31:53 +00002557 {
2558 error = renderer->render( renderer, slot, render_mode, 0 );
Werner Lembergdeb4e982000-06-29 03:14:25 +00002559 if ( !error || error != FT_Err_Cannot_Render_Glyph )
2560 break;
David Turner74abee82000-06-27 23:31:53 +00002561
Werner Lembergdeb4e982000-06-29 03:14:25 +00002562 /* FT_Err_Cannot_Render_Glyph is returned if the render mode */
David Turner74abee82000-06-27 23:31:53 +00002563 /* is unsupported by the current renderer for this glyph image */
Werner Lembergdeb4e982000-06-29 03:14:25 +00002564 /* format. */
2565
2566 /* now, look for another renderer that supports the same */
2567 /* format. */
David Turner74abee82000-06-27 23:31:53 +00002568 renderer = FT_Lookup_Renderer( library, slot->format, &node );
2569 update = 1;
2570 }
2571
2572 /* if we changed the current renderer for the glyph image format */
Werner Lembergdeb4e982000-06-29 03:14:25 +00002573 /* we need to select it as the next current one */
2574 if ( !error && update && renderer )
David Turner74abee82000-06-27 23:31:53 +00002575 FT_Set_Renderer( library, renderer, 0, 0 );
David Turnerf0df85b2000-06-22 00:17:42 +00002576 }
2577 }
Werner Lembergdeb4e982000-06-29 03:14:25 +00002578
David Turnerf0df85b2000-06-22 00:17:42 +00002579 return error;
2580 }
Werner Lemberga929ba92000-06-25 06:47:11 +00002581
David Turner74abee82000-06-27 23:31:53 +00002582
Werner Lembergdeb4e982000-06-29 03:14:25 +00002583 /*************************************************************************/
2584 /* */
2585 /* <Function> */
2586 /* FT_Render_Glyph */
2587 /* */
2588 /* <Description> */
2589 /* Converts a given glyph image to a bitmap. It does so by */
2590 /* inspecting the glyph image format, find the relevant renderer, and */
2591 /* invoke it. */
2592 /* */
2593 /* <Input> */
2594 /* slot :: A handle to the glyph slot containing the image to */
2595 /* convert. */
2596 /* */
2597 /* render_mode :: A set of bit flags indicating which kind of bitmap */
2598 /* to render. For now, only */
2599 /* `ft_render_mode_anti_alias' is supported by the */
2600 /* available renderers, but others could appear later */
2601 /* (e.g. optimized for TV or LCD). */
2602 /* */
2603 /* <Return> */
2604 /* FreeType error code. 0 means success. */
2605 /* */
2606 /* <Note> */
2607 /* In case of success, the renderer will be used to convert glyph */
2608 /* images in the renderer's known format into bitmaps. */
2609 /* */
2610 /* This doesn't change the current renderer for other formats. */
2611 /* */
2612 /* The slot's native image should be considered lost after the */
2613 /* conversion. */
2614 /* */
2615 FT_EXPORT_FUNC( FT_Error ) FT_Render_Glyph( FT_GlyphSlot slot,
2616 FT_UInt render_mode )
David Turner74abee82000-06-27 23:31:53 +00002617 {
2618 FT_Library library;
Werner Lembergdeb4e982000-06-29 03:14:25 +00002619
2620
2621 if ( !slot )
David Turner74abee82000-06-27 23:31:53 +00002622 return FT_Err_Invalid_Argument;
Werner Lembergdeb4e982000-06-29 03:14:25 +00002623
2624 library = FT_FACE_LIBRARY( slot->face );
2625
David Turner74abee82000-06-27 23:31:53 +00002626 return FT_Render_Glyph_Internal( library, slot, render_mode );
2627 }
2628
Werner Lembergdeb4e982000-06-29 03:14:25 +00002629
David Turnerf0df85b2000-06-22 00:17:42 +00002630 /*************************************************************************/
2631 /*************************************************************************/
2632 /*************************************************************************/
2633 /**** ****/
2634 /**** ****/
2635 /**** M O D U L E S ****/
2636 /**** ****/
2637 /**** ****/
2638 /*************************************************************************/
2639 /*************************************************************************/
2640 /*************************************************************************/
2641
Werner Lemberga929ba92000-06-25 06:47:11 +00002642
David Turnerf0df85b2000-06-22 00:17:42 +00002643 /*************************************************************************/
2644 /* */
2645 /* <Function> */
2646 /* Destroy_Module */
2647 /* */
2648 /* <Description> */
2649 /* Destroys a given module object. For drivers, this also destroys */
Werner Lemberga929ba92000-06-25 06:47:11 +00002650 /* all child faces. */
David Turnerf0df85b2000-06-22 00:17:42 +00002651 /* */
2652 /* <InOut> */
2653 /* module :: A handle to the target driver object. */
2654 /* */
2655 /* <Note> */
2656 /* The driver _must_ be LOCKED! */
2657 /* */
2658 static
2659 void Destroy_Module( FT_Module module )
2660 {
David Turner5ae831c2000-06-30 01:31:22 +00002661 FT_Memory memory = module->memory;
2662 FT_Module_Class* clazz = module->clazz;
2663 FT_Library library = module->library;
David Turnerf0df85b2000-06-22 00:17:42 +00002664
Werner Lemberga929ba92000-06-25 06:47:11 +00002665
David Turnerf0df85b2000-06-22 00:17:42 +00002666 /* finalize client-data - before anything else */
2667 if ( module->generic.finalizer )
2668 module->generic.finalizer( module );
2669
David Turner5ae831c2000-06-30 01:31:22 +00002670 if ( library && library->auto_hinter == module )
2671 library->auto_hinter = 0;
2672
David Turnerf0df85b2000-06-22 00:17:42 +00002673 /* if the module is a renderer */
Werner Lemberga929ba92000-06-25 06:47:11 +00002674 if ( FT_MODULE_IS_RENDERER( module ) )
2675 ft_remove_renderer( module );
David Turnerf0df85b2000-06-22 00:17:42 +00002676
2677 /* if the module is a font driver, add some steps */
Werner Lemberga929ba92000-06-25 06:47:11 +00002678 if ( FT_MODULE_IS_DRIVER( module ) )
2679 Destroy_Driver( FT_DRIVER( module ) );
David Turnerf0df85b2000-06-22 00:17:42 +00002680
2681 /* finalize the module object */
Werner Lemberga929ba92000-06-25 06:47:11 +00002682 if ( clazz->module_done )
2683 clazz->module_done( module );
David Turnerf0df85b2000-06-22 00:17:42 +00002684
2685 /* discard it */
2686 FREE( module );
2687 }
2688
David Turnerf0df85b2000-06-22 00:17:42 +00002689
Werner Lemberga929ba92000-06-25 06:47:11 +00002690 /*************************************************************************/
2691 /* */
2692 /* <Function> */
2693 /* FT_Add_Module */
2694 /* */
2695 /* <Description> */
2696 /* Adds a new module to a given library instance. */
2697 /* */
2698 /* <Input> */
2699 /* library :: A handle to the library object. */
2700 /* clazz :: A pointer to class descriptor for the module. */
2701 /* */
2702 /* <Return> */
2703 /* FreeType error code. 0 means success. */
2704 /* */
2705 /* <Note> */
2706 /* An error will be returned if a module already exists by that name, */
2707 /* or if the module requires a version of FreeType that is too great. */
2708 /* */
2709 FT_EXPORT_FUNC( FT_Error ) FT_Add_Module( FT_Library library,
2710 const FT_Module_Class* clazz )
David Turnerf0df85b2000-06-22 00:17:42 +00002711 {
2712 FT_Error error;
2713 FT_Memory memory;
2714 FT_Module module;
2715 FT_UInt nn;
2716
David Turnerf0df85b2000-06-22 00:17:42 +00002717
Werner Lembergdeb4e982000-06-29 03:14:25 +00002718#define FREETYPE_VER_FIXED ( ( (FT_Long)FREETYPE_MAJOR << 16 ) | \
2719 FREETYPE_MINOR )
Werner Lemberga929ba92000-06-25 06:47:11 +00002720
Werner Lembergdeb4e982000-06-29 03:14:25 +00002721 if ( !library )
2722 return FT_Err_Invalid_Library_Handle;
2723
2724 if ( !clazz )
David Turnerf0df85b2000-06-22 00:17:42 +00002725 return FT_Err_Invalid_Argument;
2726
2727 /* check freetype version */
2728 if ( clazz->module_requires > FREETYPE_VER_FIXED )
2729 return FT_Err_Invalid_Version;
2730
2731 /* look for a module with the same name in the library's table */
2732 for ( nn = 0; nn < library->num_modules; nn++ )
2733 {
2734 module = library->modules[nn];
2735 if ( strcmp( module->clazz->module_name, clazz->module_name ) == 0 )
2736 {
2737 /* this installed module has the same name, compare their versions */
2738 if ( clazz->module_version <= module->clazz->module_version )
2739 return FT_Err_Lower_Module_Version;
2740
2741 /* remove the module from our list, then exit the loop to replace */
2742 /* it by our new version.. */
2743 FT_Remove_Module( library, module );
2744 break;
2745 }
2746 }
2747
2748 memory = library->memory;
2749 error = FT_Err_Ok;
2750
2751 if ( library->num_modules >= FT_MAX_MODULES )
2752 {
2753 error = FT_Err_Too_Many_Drivers;
2754 goto Exit;
2755 }
2756
2757 /* allocate module object */
Werner Lemberga929ba92000-06-25 06:47:11 +00002758 if ( ALLOC( module,clazz->module_size ) )
David Turnerf0df85b2000-06-22 00:17:42 +00002759 goto Exit;
2760
Werner Lembergdeb4e982000-06-29 03:14:25 +00002761 /* base initialization */
David Turnerf0df85b2000-06-22 00:17:42 +00002762 module->library = library;
2763 module->memory = memory;
2764 module->clazz = (FT_Module_Class*)clazz;
2765
Werner Lembergdeb4e982000-06-29 03:14:25 +00002766 /* check whether the module is a renderer - this must be performed */
2767 /* before the normal module initialization */
Werner Lemberga929ba92000-06-25 06:47:11 +00002768 if ( FT_MODULE_IS_RENDERER( module ) )
David Turnerf0df85b2000-06-22 00:17:42 +00002769 {
2770 /* add to the renderers list */
Werner Lemberga929ba92000-06-25 06:47:11 +00002771 error = ft_add_renderer( module );
2772 if ( error )
2773 goto Fail;
David Turnerf0df85b2000-06-22 00:17:42 +00002774 }
2775
David Turner5ae831c2000-06-30 01:31:22 +00002776 /* is the module a auto-hinter ? */
2777 if ( FT_MODULE_IS_HINTER(module) )
2778 library->auto_hinter = module;
2779
David Turnerf0df85b2000-06-22 00:17:42 +00002780 /* if the module is a font driver */
Werner Lemberga929ba92000-06-25 06:47:11 +00002781 if ( FT_MODULE_IS_DRIVER( module ) )
David Turnerf0df85b2000-06-22 00:17:42 +00002782 {
2783 /* allocate glyph loader if needed */
Werner Lemberga929ba92000-06-25 06:47:11 +00002784 FT_Driver driver = FT_DRIVER( module );
2785
Werner Lembergdeb4e982000-06-29 03:14:25 +00002786
David Turnerf0df85b2000-06-22 00:17:42 +00002787 driver->clazz = (FT_Driver_Class*)module->clazz;
Werner Lemberga929ba92000-06-25 06:47:11 +00002788 if ( FT_DRIVER_USES_OUTLINES( driver ) )
David Turnerf0df85b2000-06-22 00:17:42 +00002789 {
2790 error = FT_GlyphLoader_New( memory, &driver->glyph_loader );
Werner Lemberga929ba92000-06-25 06:47:11 +00002791 if ( error )
2792 goto Fail;
David Turnerf0df85b2000-06-22 00:17:42 +00002793 }
2794 }
2795
Werner Lemberga929ba92000-06-25 06:47:11 +00002796 if ( clazz->module_init )
David Turnerf0df85b2000-06-22 00:17:42 +00002797 {
Werner Lemberga929ba92000-06-25 06:47:11 +00002798 error = clazz->module_init( module );
2799 if ( error )
2800 goto Fail;
David Turnerf0df85b2000-06-22 00:17:42 +00002801 }
2802
2803 /* add module to the library's table */
Werner Lemberga929ba92000-06-25 06:47:11 +00002804 library->modules[library->num_modules++] = module;
Werner Lembergdeb4e982000-06-29 03:14:25 +00002805
David Turnerf0df85b2000-06-22 00:17:42 +00002806 Exit:
2807 return error;
Werner Lembergdeb4e982000-06-29 03:14:25 +00002808
David Turnerf0df85b2000-06-22 00:17:42 +00002809 Fail:
Werner Lemberga929ba92000-06-25 06:47:11 +00002810 if ( FT_MODULE_IS_DRIVER( module ) )
David Turnerf0df85b2000-06-22 00:17:42 +00002811 {
Werner Lemberga929ba92000-06-25 06:47:11 +00002812 FT_Driver driver = FT_DRIVER( module );
Werner Lembergdeb4e982000-06-29 03:14:25 +00002813
Werner Lemberga929ba92000-06-25 06:47:11 +00002814
2815 if ( FT_DRIVER_USES_OUTLINES( driver ) )
David Turnerf0df85b2000-06-22 00:17:42 +00002816 FT_GlyphLoader_Done( driver->glyph_loader );
2817 }
Werner Lembergdeb4e982000-06-29 03:14:25 +00002818
Werner Lemberga929ba92000-06-25 06:47:11 +00002819 if ( FT_MODULE_IS_RENDERER( module ) )
David Turnerf0df85b2000-06-22 00:17:42 +00002820 {
Werner Lemberga929ba92000-06-25 06:47:11 +00002821 FT_Renderer renderer = FT_RENDERER( module );
2822
2823
2824 if ( renderer->raster )
David Turnerf0df85b2000-06-22 00:17:42 +00002825 renderer->clazz->raster_class->raster_done( renderer->raster );
2826 }
Werner Lemberga929ba92000-06-25 06:47:11 +00002827
2828 FREE( module );
David Turnerf0df85b2000-06-22 00:17:42 +00002829 goto Exit;
2830 }
2831
David Turnerf0df85b2000-06-22 00:17:42 +00002832
Werner Lemberga929ba92000-06-25 06:47:11 +00002833 /*************************************************************************/
2834 /* */
2835 /* <Function> */
2836 /* FT_Get_Module */
2837 /* */
2838 /* <Description> */
2839 /* Finds a module by its name. */
2840 /* */
2841 /* <Input> */
2842 /* library :: A handle to the library object. */
2843 /* */
2844 /* module_name :: The module's name (as an ASCII string). */
2845 /* */
2846 /* <Return> */
2847 /* A module handle. 0 if none was found. */
2848 /* */
2849 /* <Note> */
2850 /* You should better be familiar with FreeType internals to know */
2851 /* which module to look for :-) */
2852 /* */
2853 FT_EXPORT_FUNC( FT_Module ) FT_Get_Module( FT_Library library,
2854 const char* module_name )
David Turnerf0df85b2000-06-22 00:17:42 +00002855 {
Werner Lembergdeb4e982000-06-29 03:14:25 +00002856 FT_Module result = 0;
2857 FT_Module* cur;
2858 FT_Module* limit;
David Turnerf0df85b2000-06-22 00:17:42 +00002859
Werner Lemberga929ba92000-06-25 06:47:11 +00002860
Werner Lembergdeb4e982000-06-29 03:14:25 +00002861 if ( !library || !module_name )
2862 return result;
2863
2864 cur = library->modules;
2865 limit = cur + library->num_modules;
2866
David Turnerf0df85b2000-06-22 00:17:42 +00002867 for ( ; cur < limit; cur++ )
2868 if ( strcmp( cur[0]->clazz->module_name, module_name ) == 0 )
2869 {
2870 result = cur[0];
2871 break;
2872 }
2873
2874 return result;
2875 }
2876
Werner Lemberga929ba92000-06-25 06:47:11 +00002877
2878 /*************************************************************************/
2879 /* */
2880 /* <Function> */
2881 /* FT_Get_Module_Interface */
2882 /* */
2883 /* <Description> */
2884 /* Finds a module and returns its specific interface as a typeless */
2885 /* pointer. */
2886 /* */
2887 /* <Input> */
2888 /* library :: A handle to the library object. */
2889 /* */
2890 /* module_name :: The module's name (as an ASCII string). */
2891 /* */
2892 /* <Return> */
2893 /* A module-specific interface if available, 0 otherwise. */
2894 /* */
2895 /* <Note> */
2896 /* You should better be familiar with FreeType internals to know */
2897 /* which module to look for, and what its interface is :-) */
2898 /* */
Werner Lembergdeb4e982000-06-29 03:14:25 +00002899 FT_EXPORT_FUNC( const void* ) FT_Get_Module_Interface(
2900 FT_Library library,
2901 const char* mod_name )
David Turnerf0df85b2000-06-22 00:17:42 +00002902 {
2903 FT_Module module;
Werner Lembergdeb4e982000-06-29 03:14:25 +00002904
2905
2906 /* test for valid `library' delayed to FT_Get_Module() */
Werner Lemberga929ba92000-06-25 06:47:11 +00002907
David Turnerf0df85b2000-06-22 00:17:42 +00002908 module = FT_Get_Module( library, mod_name );
Werner Lemberga929ba92000-06-25 06:47:11 +00002909
David Turnerf0df85b2000-06-22 00:17:42 +00002910 return module ? module->clazz->module_interface : 0;
Werner Lembergdeb4e982000-06-29 03:14:25 +00002911 }
David Turnerf0df85b2000-06-22 00:17:42 +00002912
2913
Werner Lemberga929ba92000-06-25 06:47:11 +00002914 /*************************************************************************/
2915 /* */
2916 /* <Function> */
2917 /* FT_Remove_Module */
2918 /* */
2919 /* <Description> */
2920 /* Removes a given module from a library instance. */
2921 /* */
2922 /* <Input> */
Werner Lembergdeb4e982000-06-29 03:14:25 +00002923 /* library :: A handle to a library object. */
Werner Lemberga929ba92000-06-25 06:47:11 +00002924 /* */
Werner Lembergdeb4e982000-06-29 03:14:25 +00002925 /* module :: A handle to a module object. */
Werner Lemberga929ba92000-06-25 06:47:11 +00002926 /* */
2927 /* <Return> */
2928 /* FreeType error code. 0 means success. */
2929 /* */
2930 /* <Note> */
2931 /* The module object is destroyed by the function in case of success. */
Werner Lembergdcd2e142000-06-25 07:43:15 +00002932 /* */
Werner Lemberga929ba92000-06-25 06:47:11 +00002933 FT_EXPORT_FUNC( FT_Error ) FT_Remove_Module( FT_Library library,
2934 FT_Module module )
David Turnerf0df85b2000-06-22 00:17:42 +00002935 {
2936 /* try to find the module from the table, then remove it from there */
Werner Lembergdeb4e982000-06-29 03:14:25 +00002937
2938 if ( !library )
2939 return FT_Err_Invalid_Library_Handle;
2940
2941 if ( module )
David Turnerf0df85b2000-06-22 00:17:42 +00002942 {
2943 FT_Module* cur = library->modules;
2944 FT_Module* limit = cur + library->num_modules;
2945
Werner Lemberga929ba92000-06-25 06:47:11 +00002946
David Turnerf0df85b2000-06-22 00:17:42 +00002947 for ( ; cur < limit; cur++ )
2948 {
Werner Lembergdeb4e982000-06-29 03:14:25 +00002949 if ( cur[0] == module )
David Turnerf0df85b2000-06-22 00:17:42 +00002950 {
2951 /* remove it from the table */
2952 library->num_modules--;
2953 limit--;
Werner Lemberga929ba92000-06-25 06:47:11 +00002954 while ( cur < limit )
David Turnerf0df85b2000-06-22 00:17:42 +00002955 {
2956 cur[0] = cur[1];
2957 cur++;
2958 }
2959 limit[0] = 0;
2960
2961 /* destroy the module */
Werner Lemberga929ba92000-06-25 06:47:11 +00002962 Destroy_Module( module );
David Turnerf0df85b2000-06-22 00:17:42 +00002963
2964 return FT_Err_Ok;
2965 }
2966 }
2967 }
2968 return FT_Err_Invalid_Handle;
2969 }
2970
2971
David Turnerf0df85b2000-06-22 00:17:42 +00002972 /*************************************************************************/
2973 /*************************************************************************/
2974 /*************************************************************************/
2975 /**** ****/
2976 /**** ****/
2977 /**** L I B R A R Y ****/
2978 /**** ****/
2979 /**** ****/
2980 /*************************************************************************/
2981 /*************************************************************************/
2982 /*************************************************************************/
2983
Werner Lemberga929ba92000-06-25 06:47:11 +00002984
David Turnerf0df85b2000-06-22 00:17:42 +00002985 /*************************************************************************/
2986 /* */
2987 /* <Function> */
2988 /* FT_New_Library */
2989 /* */
2990 /* <Description> */
2991 /* This function is used to create a new FreeType library instance */
2992 /* from a given memory object. It is thus possible to use libraries */
2993 /* with distinct memory allocators within the same program. */
2994 /* */
2995 /* <Input> */
2996 /* memory :: A handle to the original memory object. */
2997 /* */
2998 /* <Output> */
2999 /* alibrary :: A pointer to handle of a new library object. */
3000 /* */
3001 /* <Return> */
3002 /* FreeType error code. 0 means success. */
3003 /* */
3004 FT_EXPORT_FUNC( FT_Error ) FT_New_Library( FT_Memory memory,
3005 FT_Library* alibrary )
3006 {
3007 FT_Library library = 0;
3008 FT_Error error;
3009
3010
3011 if ( !memory )
3012 return FT_Err_Invalid_Argument;
3013
3014 /* first of all, allocate the library object */
3015 if ( ALLOC( library, sizeof ( *library ) ) )
3016 return error;
3017
3018 library->memory = memory;
3019
3020 /* allocate the render pool */
3021 library->raster_pool_size = FT_RENDER_POOL_SIZE;
3022 if ( ALLOC( library->raster_pool, FT_RENDER_POOL_SIZE ) )
3023 goto Fail;
3024
3025 /* That's ok now */
3026 *alibrary = library;
3027
3028 return FT_Err_Ok;
3029
3030 Fail:
3031 FREE( library );
3032 return error;
3033 }
3034
3035
3036 /*************************************************************************/
3037 /* */
3038 /* <Function> */
3039 /* FT_Done_Library */
3040 /* */
3041 /* <Description> */
3042 /* Discards a given library object. This closes all drivers and */
3043 /* discards all resource objects. */
3044 /* */
3045 /* <Input> */
3046 /* library :: A handle to the target library. */
3047 /* */
3048 /* <Return> */
3049 /* FreeType error code. 0 means success. */
3050 /* */
3051 FT_EXPORT_FUNC( FT_Error ) FT_Done_Library( FT_Library library )
3052 {
3053 FT_Memory memory;
David Turner74abee82000-06-27 23:31:53 +00003054 FT_UInt n;
David Turnerf0df85b2000-06-22 00:17:42 +00003055
3056
3057 if ( !library )
3058 return FT_Err_Invalid_Library_Handle;
3059
3060 memory = library->memory;
3061
3062 /* Discard client-data */
3063 if ( library->generic.finalizer )
3064 library->generic.finalizer( library );
3065
3066 /* Close all modules in the library */
3067 for ( n = 0; n < library->num_modules; n++ )
3068 {
3069 FT_Module module = library->modules[n];
3070
Werner Lemberga929ba92000-06-25 06:47:11 +00003071
David Turnerf0df85b2000-06-22 00:17:42 +00003072 if ( module )
3073 {
3074 Destroy_Module( module );
3075 library->modules[n] = 0;
3076 }
3077 }
3078
3079 /* Destroy raster objects */
3080 FREE( library->raster_pool );
3081 library->raster_pool_size = 0;
3082
3083 FREE( library );
3084 return FT_Err_Ok;
3085 }
3086
3087
3088 /*************************************************************************/
3089 /* */
3090 /* <Function> */
3091 /* FT_Set_Debug_Hook */
3092 /* */
3093 /* <Description> */
Werner Lemberga929ba92000-06-25 06:47:11 +00003094 /* Sets a debug hook function for debugging the interpreter of a font */
3095 /* format. */
David Turnerf0df85b2000-06-22 00:17:42 +00003096 /* */
3097 /* <Input> */
3098 /* library :: A handle to the library object. */
3099 /* */
3100 /* hook_index :: The index of the debug hook. You should use the */
3101 /* values defined in ftobjs.h, e.g. */
3102 /* FT_DEBUG_HOOK_TRUETYPE */
3103 /* */
3104 /* debug_hook :: The function used to debug the interpreter. */
3105 /* */
3106 /* <Note> */
3107 /* Currently, four debug hook slots are available, but only two (for */
3108 /* the TrueType and the Type 1 interpreter) are defined. */
3109 /* */
3110 FT_EXPORT_FUNC( void ) FT_Set_Debug_Hook( FT_Library library,
3111 FT_UInt hook_index,
3112 FT_DebugHook_Func debug_hook )
3113 {
3114 if ( library && debug_hook &&
3115 hook_index <
3116 ( sizeof ( library->debug_hooks ) / sizeof ( void* ) ) )
3117 library->debug_hooks[hook_index] = debug_hook;
3118 }
3119
3120
David Turnerf0df85b2000-06-22 00:17:42 +00003121 /*************************************************************************/
David Turnerd2b1f351999-12-16 23:11:37 +00003122 /* */
3123 /* <Function> */
3124 /* FT_Done_FreeType */
3125 /* */
3126 /* <Description> */
3127 /* Destroys a given FreeType library object and all of its childs, */
3128 /* including resources, drivers, faces, sizes, etc. */
3129 /* */
3130 /* <Input> */
3131 /* library :: A handle to the target library object. */
3132 /* */
3133 /* <Return> */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00003134 /* FreeType error code. 0 means success. */
David Turnerd2b1f351999-12-16 23:11:37 +00003135 /* */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00003136 FT_EXPORT_FUNC( FT_Error ) FT_Done_FreeType( FT_Library library )
David Turnerd2b1f351999-12-16 23:11:37 +00003137 {
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00003138 /* test for valid `library' delayed to FT_Done_Library() */
3139
David Turnerd2b1f351999-12-16 23:11:37 +00003140 /* Discard the library object */
3141 FT_Done_Library( library );
3142
3143 return FT_Err_Ok;
3144 }
3145
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00003146
David Turnerd2b1f351999-12-16 23:11:37 +00003147/* END */