blob: aa129938a89b348c93191cae3a0413d7d4d7f22a [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
David Turnerf0df85b2000-06-22 00:17:42 +0000204 /*************************************************************************/
205 /*************************************************************************/
206 /*************************************************************************/
207 /**** ****/
208 /**** ****/
209 /**** S T R E A M ****/
210 /**** ****/
211 /**** ****/
212 /*************************************************************************/
213 /*************************************************************************/
214 /*************************************************************************/
215
Werner Lemberg7880dd62000-01-10 17:19:45 +0000216
Werner Lemberg547a2522000-02-16 08:23:58 +0000217 /*************************************************************************/
218 /* */
219 /* <Function> */
220 /* ft_new_input_stream */
221 /* */
222 /* <Description> */
223 /* Creates a new input stream object from an FT_Open_Args structure. */
224 /* */
Werner Lemberg2fbf7e42000-06-02 00:01:14 +0000225 /* <Note> */
226 /* The function expects a valid `astream' parameter. */
David Turner7663f222000-02-13 13:37:38 +0000227 static
Werner Lemberg547a2522000-02-16 08:23:58 +0000228 FT_Error ft_new_input_stream( FT_Library library,
229 FT_Open_Args* args,
Werner Lemberga3b6c6c2000-05-31 06:55:12 +0000230 FT_Stream* astream )
David Turner7663f222000-02-13 13:37:38 +0000231 {
Werner Lemberg547a2522000-02-16 08:23:58 +0000232 FT_Error error;
233 FT_Memory memory;
234 FT_Stream stream;
235
Werner Lemberga3b6c6c2000-05-31 06:55:12 +0000236
Werner Lemberg2fbf7e42000-06-02 00:01:14 +0000237 if ( !library )
238 return FT_Err_Invalid_Library_Handle;
239
240 if ( !args )
241 return FT_Err_Invalid_Argument;
242
David Turner37379e22000-03-28 11:22:31 +0000243 *astream = 0;
244 memory = library->memory;
Werner Lemberg547a2522000-02-16 08:23:58 +0000245 if ( ALLOC( stream, sizeof ( *stream ) ) )
David Turner37379e22000-03-28 11:22:31 +0000246 goto Exit;
David Turnere49ab252000-05-16 23:44:38 +0000247
David Turner7663f222000-02-13 13:37:38 +0000248 stream->memory = memory;
David Turnere49ab252000-05-16 23:44:38 +0000249
David Turner4f2c5542000-05-12 10:19:41 +0000250 /* now, look at the stream flags */
251 if ( args->flags & ft_open_memory )
Just van Rossumd35aea72000-03-02 01:07:50 +0000252 {
David Turner4f2c5542000-05-12 10:19:41 +0000253 error = 0;
254 FT_New_Memory_Stream( library,
255 args->memory_base,
256 args->memory_size,
257 stream );
258 }
Werner Lemberga3b6c6c2000-05-31 06:55:12 +0000259 else if ( args->flags & ft_open_pathname )
David Turner4f2c5542000-05-12 10:19:41 +0000260 {
261 error = FT_New_Stream( args->pathname, stream );
262 stream->pathname.pointer = args->pathname;
263 }
Werner Lemberga3b6c6c2000-05-31 06:55:12 +0000264 else if ( args->flags & ft_open_stream && args->stream )
David Turner4f2c5542000-05-12 10:19:41 +0000265 {
266 *stream = *(args->stream);
267 stream->memory = memory;
268 }
269 else
David Turner4f2c5542000-05-12 10:19:41 +0000270 error = FT_Err_Invalid_Argument;
David Turnere49ab252000-05-16 23:44:38 +0000271
Werner Lemberg547a2522000-02-16 08:23:58 +0000272 if ( error )
273 FREE( stream );
David Turnere49ab252000-05-16 23:44:38 +0000274
David Turner7663f222000-02-13 13:37:38 +0000275 *astream = stream;
Werner Lemberga3b6c6c2000-05-31 06:55:12 +0000276
David Turner37379e22000-03-28 11:22:31 +0000277 Exit:
David Turner7663f222000-02-13 13:37:38 +0000278 return error;
279 }
280
281
Werner Lemberg547a2522000-02-16 08:23:58 +0000282 /*************************************************************************/
283 /* */
284 /* <Function> */
David Turnera8bcdf82000-05-02 10:51:41 +0000285 /* FT_Done_Stream */
Werner Lemberg547a2522000-02-16 08:23:58 +0000286 /* */
287 /* <Description> */
288 /* Closes and destroys a stream object. */
289 /* */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +0000290 /* <Input> */
291 /* stream :: The stream to be closed and destroyed. */
292 /* */
293 FT_EXPORT_FUNC( void ) FT_Done_Stream( FT_Stream stream )
David Turnera8bcdf82000-05-02 10:51:41 +0000294 {
Werner Lemberg2fbf7e42000-06-02 00:01:14 +0000295 if ( stream && stream->close )
David Turnera8bcdf82000-05-02 10:51:41 +0000296 stream->close( stream );
297 }
298
299
David Turner7663f222000-02-13 13:37:38 +0000300 static
Werner Lemberg547a2522000-02-16 08:23:58 +0000301 void ft_done_stream( FT_Stream* astream )
David Turner7663f222000-02-13 13:37:38 +0000302 {
303 FT_Stream stream = *astream;
304 FT_Memory memory = stream->memory;
Werner Lemberg547a2522000-02-16 08:23:58 +0000305
Werner Lemberga3b6c6c2000-05-31 06:55:12 +0000306
Werner Lemberg547a2522000-02-16 08:23:58 +0000307 if ( stream->close )
David Turner7663f222000-02-13 13:37:38 +0000308 stream->close( stream );
Just van Rossum7eef5362000-03-05 16:07:58 +0000309
David Turner7663f222000-02-13 13:37:38 +0000310 FREE( stream );
311 *astream = 0;
312 }
313
Werner Lemberga3b6c6c2000-05-31 06:55:12 +0000314
Werner Lembergeb81e372000-06-03 06:03:11 +0000315#undef FT_COMPONENT
316#define FT_COMPONENT trace_objs
317
David Turnerf0df85b2000-06-22 00:17:42 +0000318 /*************************************************************************/
319 /*************************************************************************/
320 /*************************************************************************/
321 /**** ****/
322 /**** ****/
323 /**** G L Y P H L O A D E R ****/
324 /**** ****/
325 /**** ****/
326 /*************************************************************************/
327 /*************************************************************************/
328 /*************************************************************************/
329
David Turnerf0df85b2000-06-22 00:17:42 +0000330
Werner Lemberga929ba92000-06-25 06:47:11 +0000331 /*************************************************************************/
332 /* */
333 /* The glyph loader is a simple object which is used to load a set of */
334 /* glyphs easily. It is critical for the correct loading of composites. */
335 /* */
336 /* Ideally, one can see it as a stack of abstract `glyph' objects. */
337 /* */
338 /* loader.base Is really the bottom of the stack. It describes a */
339 /* single glyph image made of the juxtaposition of */
340 /* several glyphs (those `in the stack'). */
341 /* */
342 /* loader.current Describes the top of the stack, on which a new */
343 /* glyph can be loaded. */
344 /* */
345 /* Rewind Clears the stack. */
346 /* Prepare Set up `loader.current' for addition of a new glyph */
347 /* image. */
348 /* Add Add the `current' glyph image to the `base' one, */
349 /* and prepare for another one. */
350 /* */
351 /* The glyph loader is now a base object. Each driver used to */
352 /* re-implement it in one way or the other, which wasted code and */
353 /* energy. */
354 /* */
355 /*************************************************************************/
356
357
358 /* create a new glyph loader */
359 BASE_FUNC( FT_Error ) FT_GlyphLoader_New( FT_Memory memory,
360 FT_GlyphLoader** aloader )
David Turnerf0df85b2000-06-22 00:17:42 +0000361 {
362 FT_GlyphLoader* loader;
363 FT_Error error;
364
Werner Lemberga929ba92000-06-25 06:47:11 +0000365
366 if ( !ALLOC( loader, sizeof ( *loader ) ) )
David Turnerf0df85b2000-06-22 00:17:42 +0000367 {
368 loader->memory = memory;
369 *aloader = loader;
370 }
371 return error;
372 }
373
374
Werner Lemberga929ba92000-06-25 06:47:11 +0000375 /* rewind the glyph loader - reset counters to 0 */
376 BASE_FUNC( void ) FT_GlyphLoader_Rewind( FT_GlyphLoader* loader )
David Turnerf0df85b2000-06-22 00:17:42 +0000377 {
378 FT_GlyphLoad* base = &loader->base;
379 FT_GlyphLoad* current = &loader->current;
380
Werner Lemberga929ba92000-06-25 06:47:11 +0000381
David Turnerf0df85b2000-06-22 00:17:42 +0000382 base->outline.n_points = 0;
383 base->outline.n_contours = 0;
384 base->num_subglyphs = 0;
385
386 *current = *base;
387 }
388
389
Werner Lemberga929ba92000-06-25 06:47:11 +0000390 /* reset the glyph loader, frees all allocated tables */
391 /* and starts from zero */
392 BASE_FUNC( void ) FT_GlyphLoader_Reset( FT_GlyphLoader* loader )
David Turnerf0df85b2000-06-22 00:17:42 +0000393 {
394 FT_Memory memory = loader->memory;
395
Werner Lemberga929ba92000-06-25 06:47:11 +0000396
David Turnerf0df85b2000-06-22 00:17:42 +0000397 FREE( loader->base.outline.points );
398 FREE( loader->base.outline.tags );
399 FREE( loader->base.outline.contours );
400 FREE( loader->base.extra_points );
401 FREE( loader->base.subglyphs );
402
403 loader->max_points = 0;
404 loader->max_contours = 0;
405 loader->max_subglyphs = 0;
406
407 FT_GlyphLoader_Rewind( loader );
408 }
409
410
Werner Lemberga929ba92000-06-25 06:47:11 +0000411 /* delete a glyph loader */
412 BASE_FUNC( void ) FT_GlyphLoader_Done( FT_GlyphLoader* loader )
David Turnerf0df85b2000-06-22 00:17:42 +0000413 {
Werner Lemberga929ba92000-06-25 06:47:11 +0000414 if ( loader )
David Turnerf0df85b2000-06-22 00:17:42 +0000415 {
416 FT_Memory memory = loader->memory;
417
Werner Lemberga929ba92000-06-25 06:47:11 +0000418
David Turnerf0df85b2000-06-22 00:17:42 +0000419 FT_GlyphLoader_Reset(loader);
420 FREE( loader );
421 }
422 }
423
424
Werner Lemberga929ba92000-06-25 06:47:11 +0000425 /* re-adjust the `current' outline fields */
426 static void FT_GlyphLoader_Adjust_Points( FT_GlyphLoader* loader )
David Turnerf0df85b2000-06-22 00:17:42 +0000427 {
428 FT_Outline* base = &loader->base.outline;
429 FT_Outline* current = &loader->current.outline;
430
Werner Lemberga929ba92000-06-25 06:47:11 +0000431
David Turnerf0df85b2000-06-22 00:17:42 +0000432 current->points = base->points + base->n_points;
433 current->tags = base->tags + base->n_points;
434 current->contours = base->contours + base->n_contours;
435
436 /* handle extra points table - if any */
Werner Lemberga929ba92000-06-25 06:47:11 +0000437 if ( loader->use_extra )
438 loader->current.extra_points =
439 loader->base.extra_points + base->n_points;
David Turnerf0df85b2000-06-22 00:17:42 +0000440 }
441
442
David Turner74abee82000-06-27 23:31:53 +0000443
444 BASE_FUNC(FT_Error) FT_GlyphLoader_Create_Extra( FT_GlyphLoader* loader )
David Turnerf0df85b2000-06-22 00:17:42 +0000445 {
446 FT_Error error;
447 FT_Memory memory = loader->memory;
Werner Lemberga929ba92000-06-25 06:47:11 +0000448
David Turnerf0df85b2000-06-22 00:17:42 +0000449
450 if ( !ALLOC_ARRAY( loader->base.extra_points,
451 loader->max_points, FT_Vector ) )
452 {
453 loader->use_extra = 1;
Werner Lemberga929ba92000-06-25 06:47:11 +0000454 FT_GlyphLoader_Adjust_Points( loader );
David Turnerf0df85b2000-06-22 00:17:42 +0000455 }
456 return error;
457 }
458
459
Werner Lemberga929ba92000-06-25 06:47:11 +0000460 /* re-adjust the `current' subglyphs field */
461 static void FT_GlyphLoader_Adjust_Subglyphs( FT_GlyphLoader* loader )
David Turnerf0df85b2000-06-22 00:17:42 +0000462 {
463 FT_GlyphLoad* base = &loader->base;
464 FT_GlyphLoad* current = &loader->current;
465
Werner Lemberga929ba92000-06-25 06:47:11 +0000466
David Turnerf0df85b2000-06-22 00:17:42 +0000467 current->subglyphs = base->subglyphs + base->num_subglyphs;
468 }
469
470
Werner Lemberga929ba92000-06-25 06:47:11 +0000471 /* Ensure that we can add `n_points' and `n_contours' to our glyph. this */
472 /* function reallocates its outline tables if necessary. Note that it */
473 /* DOESN'T change the number of points within the loader! */
474 BASE_FUNC( FT_Error ) FT_GlyphLoader_Check_Points(
475 FT_GlyphLoader* loader,
476 FT_UInt n_points,
477 FT_UInt n_contours )
David Turnerf0df85b2000-06-22 00:17:42 +0000478 {
479 FT_Memory memory = loader->memory;
480 FT_Error error = FT_Err_Ok;
481 FT_Outline* base = &loader->base.outline;
482 FT_Outline* current = &loader->current.outline;
483 FT_Bool adjust = 1;
484
485 FT_UInt new_max;
486
Werner Lemberga929ba92000-06-25 06:47:11 +0000487
David Turnerf0df85b2000-06-22 00:17:42 +0000488 /* check points & tags */
489 new_max = base->n_points + current->n_points + n_points;
Werner Lemberga929ba92000-06-25 06:47:11 +0000490 if ( new_max > loader->max_points )
David Turnerf0df85b2000-06-22 00:17:42 +0000491 {
Werner Lemberga929ba92000-06-25 06:47:11 +0000492 new_max = ( new_max + 7 ) & -8;
493 if ( REALLOC_ARRAY( base->points, base->n_points,
494 new_max, FT_Vector ) ||
495 REALLOC_ARRAY( base->tags, base->n_points,
496 new_max, FT_Byte ) )
David Turnerf0df85b2000-06-22 00:17:42 +0000497 goto Exit;
498
499 if ( loader->use_extra &&
Werner Lemberga929ba92000-06-25 06:47:11 +0000500 REALLOC_ARRAY( loader->base.extra_points, base->n_points,
501 new_max, FT_Vector ) )
David Turnerf0df85b2000-06-22 00:17:42 +0000502 goto Exit;
503
504 adjust = 1;
505 loader->max_points = new_max;
506 }
507
508 /* check contours */
509 new_max = base->n_contours + current->n_contours +
510 n_contours;
Werner Lemberga929ba92000-06-25 06:47:11 +0000511 if ( new_max > loader->max_contours )
David Turnerf0df85b2000-06-22 00:17:42 +0000512 {
Werner Lemberga929ba92000-06-25 06:47:11 +0000513 new_max = ( new_max + 3 ) & -4;
514 if ( REALLOC_ARRAY( base->contours, base->n_contours,
515 new_max, FT_Short ) )
David Turnerf0df85b2000-06-22 00:17:42 +0000516 goto Exit;
517
518 adjust = 1;
519 loader->max_contours = new_max;
520 }
521
Werner Lemberga929ba92000-06-25 06:47:11 +0000522 if ( adjust )
David Turnerf0df85b2000-06-22 00:17:42 +0000523 FT_GlyphLoader_Adjust_Points( loader );
524
525 Exit:
526 return error;
527 }
528
529
Werner Lemberga929ba92000-06-25 06:47:11 +0000530 /* Ensure that we can add `n_subglyphs' to our glyph. this function */
531 /* reallocates its subglyphs table if necessary. Note that it DOES */
532 /* NOT change the number of subglyphs within the loader! */
533 BASE_FUNC( FT_Error ) FT_GlyphLoader_Check_Subglyphs(
534 FT_GlyphLoader* loader,
535 FT_UInt n_subs )
David Turnerf0df85b2000-06-22 00:17:42 +0000536 {
537 FT_Memory memory = loader->memory;
538 FT_Error error = FT_Err_Ok;
539 FT_UInt new_max;
540
541 FT_GlyphLoad* base = &loader->base;
542 FT_GlyphLoad* current = &loader->current;
543
Werner Lemberga929ba92000-06-25 06:47:11 +0000544
David Turnerf0df85b2000-06-22 00:17:42 +0000545 new_max = base->num_subglyphs + current->num_subglyphs + n_subs;
Werner Lemberga929ba92000-06-25 06:47:11 +0000546 if ( new_max > loader->max_subglyphs )
David Turnerf0df85b2000-06-22 00:17:42 +0000547 {
Werner Lemberga929ba92000-06-25 06:47:11 +0000548 new_max = ( new_max + 1 ) & -2;
549 if ( REALLOC_ARRAY( base->subglyphs, base->num_subglyphs,
550 new_max, FT_SubGlyph ) )
David Turnerf0df85b2000-06-22 00:17:42 +0000551 goto Exit;
552
553 loader->max_subglyphs = new_max;
554
555 FT_GlyphLoader_Adjust_Subglyphs( loader );
556 }
557
558 Exit:
559 return error;
560 }
561
562
Werner Lemberga929ba92000-06-25 06:47:11 +0000563 /* prepare loader for the addition of a new glyph on top of the base one */
564 BASE_FUNC( void ) FT_GlyphLoader_Prepare( FT_GlyphLoader* loader )
David Turnerf0df85b2000-06-22 00:17:42 +0000565 {
566 FT_GlyphLoad* current = &loader->current;
567
Werner Lemberga929ba92000-06-25 06:47:11 +0000568
David Turnerf0df85b2000-06-22 00:17:42 +0000569 current->outline.n_points = 0;
570 current->outline.n_contours = 0;
571 current->num_subglyphs = 0;
572
573 FT_GlyphLoader_Adjust_Points ( loader );
574 FT_GlyphLoader_Adjust_Subglyphs( loader );
575 }
576
577
Werner Lemberga929ba92000-06-25 06:47:11 +0000578 /* add current glyph to the base image - and prepare for another */
579 BASE_FUNC( void ) FT_GlyphLoader_Add( FT_GlyphLoader* loader )
David Turnerf0df85b2000-06-22 00:17:42 +0000580 {
581 FT_GlyphLoad* base = &loader->base;
582 FT_GlyphLoad* current = &loader->current;
583
584 FT_UInt n_curr_contours = current->outline.n_contours;
585 FT_UInt n_base_points = base->outline.n_points;
586 FT_UInt n;
587
Werner Lemberga929ba92000-06-25 06:47:11 +0000588
David Turnerf0df85b2000-06-22 00:17:42 +0000589 base->outline.n_points += current->outline.n_points;
590 base->outline.n_contours += current->outline.n_contours;
591 base->num_subglyphs += current->num_subglyphs;
592
593 /* adjust contours count in newest outline */
594 for ( n = 0; n < n_curr_contours; n++ )
595 current->outline.contours[n] += n_base_points;
596
597 /* prepare for another new glyph image */
598 FT_GlyphLoader_Prepare( loader );
599 }
600
601
Werner Lemberga929ba92000-06-25 06:47:11 +0000602 BASE_FUNC( FT_Error ) FT_GlyphLoader_Copy_Points(
603 FT_GlyphLoader* target,
604 FT_GlyphLoader* source )
David Turnerf0df85b2000-06-22 00:17:42 +0000605 {
606 FT_Error error;
607 FT_UInt num_points = source->base.outline.n_points;
608 FT_UInt num_contours = source->base.outline.n_contours;
Werner Lemberga929ba92000-06-25 06:47:11 +0000609
David Turnerf0df85b2000-06-22 00:17:42 +0000610
611 error = FT_GlyphLoader_Check_Points( target, num_points, num_contours );
Werner Lemberga929ba92000-06-25 06:47:11 +0000612 if ( !error )
David Turnerf0df85b2000-06-22 00:17:42 +0000613 {
614 FT_Outline* out = &target->base.outline;
615 FT_Outline* in = &source->base.outline;
Werner Lemberga929ba92000-06-25 06:47:11 +0000616
David Turnerf0df85b2000-06-22 00:17:42 +0000617
Werner Lemberga929ba92000-06-25 06:47:11 +0000618 MEM_Copy( out->points, in->points,
619 num_points * sizeof ( FT_Vector ) );
620 MEM_Copy( out->tags, in->tags,
621 num_points * sizeof ( char ) );
622 MEM_Copy( out->contours, in->contours,
623 num_contours * sizeof ( short ) );
David Turnerf0df85b2000-06-22 00:17:42 +0000624
Werner Lemberga929ba92000-06-25 06:47:11 +0000625 /* do we need to copy the extra points? */
626 if ( target->use_extra && source->use_extra )
David Turnerf0df85b2000-06-22 00:17:42 +0000627 MEM_Copy( target->base.extra_points, source->base.extra_points,
Werner Lemberga929ba92000-06-25 06:47:11 +0000628 num_points * sizeof ( FT_Vector ) );
David Turnerf0df85b2000-06-22 00:17:42 +0000629
630 out->n_points = num_points;
631 out->n_contours = num_contours;
632
633 FT_GlyphLoader_Adjust_Points( target );
634 }
Werner Lemberga929ba92000-06-25 06:47:11 +0000635
David Turnerf0df85b2000-06-22 00:17:42 +0000636 return error;
637 }
638
639
David Turnerf0df85b2000-06-22 00:17:42 +0000640 /*************************************************************************/
641 /*************************************************************************/
642 /*************************************************************************/
643 /**** ****/
644 /**** ****/
645 /**** FACE, SIZE & GLYPH SLOT OBJECTS ****/
646 /**** ****/
647 /**** ****/
648 /*************************************************************************/
649 /*************************************************************************/
650 /*************************************************************************/
651
652 static FT_Error ft_glyphslot_init( FT_GlyphSlot slot )
653 {
654 FT_Driver driver = slot->face->driver;
655 FT_Driver_Class* clazz = driver->clazz;
656 FT_Memory memory = driver->root.memory;
657 FT_Error error = FT_Err_Ok;
658
Werner Lemberga929ba92000-06-25 06:47:11 +0000659
660 if ( FT_DRIVER_USES_OUTLINES( driver ) )
David Turnerf0df85b2000-06-22 00:17:42 +0000661 error = FT_GlyphLoader_New( memory, &slot->loader );
662
Werner Lemberga929ba92000-06-25 06:47:11 +0000663 if ( !error && clazz->init_slot )
David Turnerf0df85b2000-06-22 00:17:42 +0000664 error = clazz->init_slot( slot );
665
666 return error;
667 }
668
669
Werner Lemberga929ba92000-06-25 06:47:11 +0000670 static void ft_glyphslot_clear( FT_GlyphSlot slot )
David Turnerf0df85b2000-06-22 00:17:42 +0000671 {
672 /* clear all public fields in the glyph slot */
Werner Lemberga929ba92000-06-25 06:47:11 +0000673 MEM_Set( &slot->metrics, 0, sizeof ( slot->metrics ) );
674 MEM_Set( &slot->outline, 0, sizeof ( slot->outline ) );
675 MEM_Set( &slot->bitmap, 0, sizeof ( slot->bitmap ) );
David Turnerf0df85b2000-06-22 00:17:42 +0000676
677 slot->bitmap_left = 0;
678 slot->bitmap_top = 0;
679 slot->num_subglyphs = 0;
680 slot->subglyphs = 0;
681 slot->control_data = 0;
682 slot->control_len = 0;
683 slot->other = 0;
684 slot->format = 0;
685
686 slot->linearHoriAdvance = 0;
687 slot->linearVertAdvance = 0;
688 }
689
690
Werner Lemberga929ba92000-06-25 06:47:11 +0000691 static void ft_glyphslot_done( FT_GlyphSlot slot )
David Turnerf0df85b2000-06-22 00:17:42 +0000692 {
693 FT_Driver driver = slot->face->driver;
694 FT_Driver_Class* clazz = driver->clazz;
695 FT_Memory memory = driver->root.memory;
696
Werner Lemberga929ba92000-06-25 06:47:11 +0000697
David Turnerf0df85b2000-06-22 00:17:42 +0000698 /* free bitmap buffer if needed */
699 if ( slot->flags & ft_glyph_own_bitmap )
700 FREE( slot->bitmap.buffer );
701
702 /* free glyph loader */
Werner Lemberga929ba92000-06-25 06:47:11 +0000703 if ( FT_DRIVER_USES_OUTLINES( driver ) )
David Turnerf0df85b2000-06-22 00:17:42 +0000704 {
705 FT_GlyphLoader_Done( slot->loader );
706 slot->loader = 0;
707 }
708
Werner Lemberga929ba92000-06-25 06:47:11 +0000709 if ( clazz->done_slot )
David Turnerf0df85b2000-06-22 00:17:42 +0000710 clazz->done_slot( slot );
711 }
712
713
David Turnerf0df85b2000-06-22 00:17:42 +0000714 /*************************************************************************/
715 /* */
716 /* <Function> */
717 /* FT_New_GlyphSlot */
718 /* */
719 /* <Description> */
720 /* It is sometimes useful to have more than one glyph slot for a */
721 /* given face object. This function is used to create additional */
722 /* slots. All of them are automatically discarded when the face is */
723 /* destroyed. */
724 /* */
725 /* <Input> */
726 /* face :: A handle to a parent face object. */
727 /* */
728 /* <Output> */
729 /* aslot :: A handle to a new glyph slot object. */
730 /* */
731 /* <Return> */
732 /* FreeType error code. 0 means success. */
733 /* */
David Turnerf0df85b2000-06-22 00:17:42 +0000734 FT_EXPORT_FUNC( FT_Error ) FT_New_GlyphSlot( FT_Face face,
735 FT_GlyphSlot* aslot )
736 {
Werner Lemberga929ba92000-06-25 06:47:11 +0000737 FT_Error error;
738 FT_Driver driver;
739 FT_Driver_Class* clazz;
740 FT_Memory memory;
741 FT_GlyphSlot slot;
742
David Turnerf0df85b2000-06-22 00:17:42 +0000743
744 *aslot = 0;
745
746 if ( !face || !aslot || !face->driver )
747 return FT_Err_Invalid_Argument;
748
749 driver = face->driver;
750 clazz = driver->clazz;
751 memory = driver->root.memory;
752
753 FT_TRACE4(( "FT_New_GlyphSlot: Creating new slot object\n" ));
754 if ( !ALLOC( slot, clazz->slot_object_size ) )
755 {
756 slot->face = face;
757
758 error = ft_glyphslot_init( slot );
Werner Lemberga929ba92000-06-25 06:47:11 +0000759 if ( error )
David Turnerf0df85b2000-06-22 00:17:42 +0000760 {
761 ft_glyphslot_done( slot );
762 FREE( slot );
763 goto Exit;
764 }
765
766 *aslot = slot;
767 }
768
769 Exit:
770 FT_TRACE4(( "FT_New_GlyphSlot: Return %d\n", error ));
771 return error;
772 }
773
774
775 /*************************************************************************/
776 /* */
777 /* <Function> */
778 /* FT_Done_GlyphSlot */
779 /* */
780 /* <Description> */
781 /* Destroys a given glyph slot. Remember however that all slots are */
782 /* automatically destroyed with its parent. Using this function is */
783 /* not always mandatory. */
784 /* */
785 /* <Input> */
786 /* slot :: A handle to a target glyph slot. */
787 /* */
788 FT_EXPORT_FUNC( void ) FT_Done_GlyphSlot( FT_GlyphSlot slot )
789 {
790 if ( slot )
791 {
792 FT_Driver driver = slot->face->driver;
793 FT_Memory memory = driver->root.memory;
794 FT_GlyphSlot* parent;
795 FT_GlyphSlot cur;
796
Werner Lemberga929ba92000-06-25 06:47:11 +0000797
David Turnerf0df85b2000-06-22 00:17:42 +0000798 /* Remove slot from its parent face's list */
799 parent = &slot->face->glyph;
800 cur = *parent;
Werner Lemberga929ba92000-06-25 06:47:11 +0000801
David Turnerf0df85b2000-06-22 00:17:42 +0000802 while ( cur )
803 {
804 if ( cur == slot )
805 {
806 *parent = cur->next;
Werner Lemberga929ba92000-06-25 06:47:11 +0000807 ft_glyphslot_done( slot );
David Turnerf0df85b2000-06-22 00:17:42 +0000808 FREE( slot );
809 break;
810 }
811 cur = cur->next;
812 }
813 }
814 }
815
816
Werner Lemberga929ba92000-06-25 06:47:11 +0000817 /* forward declaration */
818 static FT_Renderer ft_lookup_glyph_renderer( FT_GlyphSlot slot );
David Turnerf0df85b2000-06-22 00:17:42 +0000819
820
821 /*************************************************************************/
822 /* */
823 /* <Function> */
824 /* FT_Set_Transform */
825 /* */
826 /* <Description> */
827 /* A function used to set the transformation that is applied to glyph */
Werner Lemberga929ba92000-06-25 06:47:11 +0000828 /* images just before they are converted to bitmaps in a glyph slot */
829 /* when FT_Render_Glyph() is called. */
David Turnerf0df85b2000-06-22 00:17:42 +0000830 /* */
831 /* <InOut> */
832 /* face :: A handle to the source face object. */
833 /* */
834 /* <Input> */
835 /* matrix :: A pointer to the transformation's 2x2 matrix. Use 0 for */
836 /* the identity matrix. */
837 /* delta :: A pointer to the translation vector. Use 0 for the null */
838 /* vector. */
839 /* */
840 /* <Note> */
841 /* The transformation is only applied to scalable image formats. */
842 /* */
843 FT_EXPORT_FUNC( void ) FT_Set_Transform( FT_Face face,
844 FT_Matrix* matrix,
845 FT_Vector* delta )
846 {
847 if ( !face )
848 return;
849
850 face->transform_flags = 0;
851
852 if ( !matrix )
853 {
854 face->transform_matrix.xx = 0x10000L;
855 face->transform_matrix.xy = 0L;
856 face->transform_matrix.yx = 0L;
857 face->transform_matrix.yy = 0x10000L;
858 matrix = &face->transform_matrix;
859 }
860 else
861 face->transform_matrix = *matrix;
862
863 /* set transform_flags bit flag 0 if `matrix' isn't the identity */
864 if ( ( matrix->xy | matrix->yx ) ||
865 matrix->xx != 0x10000L ||
866 matrix->yy != 0x10000L )
867 face->transform_flags |= 1;
868
869 if ( !delta )
870 {
871 face->transform_delta.x = 0;
872 face->transform_delta.y = 0;
873 delta = &face->transform_delta;
874 }
875 else
876 face->transform_delta = *delta;
877
878 /* set transform_flags bit flag 1 if `delta' isn't the null vector */
879 if ( delta->x | delta->y )
880 face->transform_flags |= 2;
881 }
882
883
David Turner74abee82000-06-27 23:31:53 +0000884 static FT_Renderer ft_lookup_glyph_renderer( FT_GlyphSlot slot );
885
David Turnerf0df85b2000-06-22 00:17:42 +0000886 /*************************************************************************/
887 /* */
888 /* <Function> */
889 /* FT_Load_Glyph */
890 /* */
891 /* <Description> */
892 /* A function used to load a single glyph within a given glyph slot, */
893 /* for a given size. */
894 /* */
895 /* <Input> */
896 /* face :: A handle to the target face object where the glyph */
897 /* will be loaded. */
898 /* */
899 /* glyph_index :: The index of the glyph in the font file. */
900 /* */
901 /* load_flags :: A flag indicating what to load for this glyph. The */
902 /* FT_LOAD_XXX constants can be used to control the */
903 /* glyph loading process (e.g., whether the outline */
904 /* should be scaled, whether to load bitmaps or not, */
905 /* whether to hint the outline, etc). */
906 /* */
907 /* <Return> */
908 /* FreeType error code. 0 means success. */
909 /* */
910 /* <Note> */
911 /* If the glyph image is not a bitmap, and if the bit flag */
912 /* FT_LOAD_IGNORE_TRANSFORM is unset, the glyph image will be */
913 /* transformed with the information passed to a previous call to */
914 /* FT_Set_Transform. */
915 /* */
Werner Lemberga929ba92000-06-25 06:47:11 +0000916 /* Note that this also transforms the `face.glyph.advance' field, but */
917 /* *not* the values in `face.glyph.metrics'. */
David Turnerf0df85b2000-06-22 00:17:42 +0000918 /* */
David Turnerf0df85b2000-06-22 00:17:42 +0000919 FT_EXPORT_FUNC( FT_Error ) FT_Load_Glyph( FT_Face face,
920 FT_UInt glyph_index,
921 FT_Int load_flags )
922 {
923 FT_Error error;
924 FT_Driver driver;
925 FT_GlyphSlot slot;
926
Werner Lemberga929ba92000-06-25 06:47:11 +0000927
David Turnerf0df85b2000-06-22 00:17:42 +0000928 if ( !face || !face->size || !face->glyph )
929 return FT_Err_Invalid_Face_Handle;
930
David Turner74abee82000-06-27 23:31:53 +0000931 if ( glyph_index >= (FT_UInt)face->num_glyphs )
David Turnerf0df85b2000-06-22 00:17:42 +0000932 return FT_Err_Invalid_Argument;
933
934 slot = face->glyph;
935 ft_glyphslot_clear( slot );
936
937 driver = face->driver;
938
939 /* when the flag NO_RECURSE is set, we disable hinting and scaling */
940 if ( load_flags & FT_LOAD_NO_RECURSE )
941 load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING;
942
943 error = driver->clazz->load_glyph( slot,
944 face->size,
945 glyph_index,
946 load_flags );
Werner Lemberga929ba92000-06-25 06:47:11 +0000947 if ( error )
948 goto Exit;
David Turnerf0df85b2000-06-22 00:17:42 +0000949
950 /* compute the advance */
Werner Lemberga929ba92000-06-25 06:47:11 +0000951 if ( load_flags & FT_LOAD_VERTICAL_LAYOUT )
David Turnerf0df85b2000-06-22 00:17:42 +0000952 {
953 slot->advance.x = 0;
954 slot->advance.y = slot->metrics.vertAdvance;
955 }
956 else
957 {
958 slot->advance.x = slot->metrics.horiAdvance;
959 slot->advance.y = 0;
960 }
961
962 /* now, transform the glyph image when needed */
Werner Lemberga929ba92000-06-25 06:47:11 +0000963 if ( face->transform_flags )
David Turnerf0df85b2000-06-22 00:17:42 +0000964 {
965 /* get renderer */
966 FT_Renderer renderer = ft_lookup_glyph_renderer( slot );
967
Werner Lemberga929ba92000-06-25 06:47:11 +0000968
969 if ( renderer )
David Turnerf0df85b2000-06-22 00:17:42 +0000970 error = renderer->clazz->transform_glyph( renderer, slot,
971 &face->transform_matrix,
972 &face->transform_delta );
973 /* transform advance */
974 FT_Vector_Transform( &slot->advance, &face->transform_matrix );
975 }
976
977 Exit:
978 return error;
979 }
980
981
982 /*************************************************************************/
983 /* */
984 /* <Function> */
985 /* FT_Load_Char */
986 /* */
987 /* <Description> */
988 /* A function used to load a single glyph within a given glyph slot, */
Werner Lemberga929ba92000-06-25 06:47:11 +0000989 /* for a given size, according to its character code. */
David Turnerf0df85b2000-06-22 00:17:42 +0000990 /* */
991 /* <Input> */
992 /* face :: A handle to a target face object where the glyph */
993 /* will be loaded. */
994 /* */
995 /* char_code :: The glyph's character code, according to the */
996 /* current charmap used in the face. */
997 /* */
998 /* load_flags :: A flag indicating what to load for this glyph. The */
999 /* FT_LOAD_XXX constants can be used to control the */
1000 /* glyph loading process (e.g., whether the outline */
1001 /* should be scaled, whether to load bitmaps or not, */
1002 /* whether to hint the outline, etc). */
Werner Lemberga929ba92000-06-25 06:47:11 +00001003 /* */
David Turnerf0df85b2000-06-22 00:17:42 +00001004 /* <Return> */
1005 /* FreeType error code. 0 means success. */
1006 /* */
1007 /* <Note> */
1008 /* If the face has no current charmap, or if the character code */
1009 /* is not defined in the charmap, this function will return an */
Werner Lemberga929ba92000-06-25 06:47:11 +00001010 /* error. */
David Turnerf0df85b2000-06-22 00:17:42 +00001011 /* */
1012 /* If the glyph image is not a bitmap, and if the bit flag */
1013 /* FT_LOAD_IGNORE_TRANSFORM is unset, the glyph image will be */
1014 /* transformed with the information passed to a previous call to */
Werner Lemberga929ba92000-06-25 06:47:11 +00001015 /* FT_Set_Transform(). */
David Turnerf0df85b2000-06-22 00:17:42 +00001016 /* */
Werner Lemberga929ba92000-06-25 06:47:11 +00001017 /* Note that this also transforms the `face.glyph.advance' field, but */
1018 /* *not* the values in `face.glyph.metrics'. */
David Turnerf0df85b2000-06-22 00:17:42 +00001019 /* */
1020 FT_EXPORT_FUNC( FT_Error ) FT_Load_Char( FT_Face face,
1021 FT_ULong char_code,
1022 FT_Int load_flags )
1023 {
1024 FT_UInt glyph_index;
1025
Werner Lemberga929ba92000-06-25 06:47:11 +00001026
David Turnerf0df85b2000-06-22 00:17:42 +00001027 if ( !face )
1028 return FT_Err_Invalid_Face_Handle;
1029
1030 glyph_index = (FT_UInt)char_code;
Werner Lemberga929ba92000-06-25 06:47:11 +00001031 if ( face->charmap )
David Turnerf0df85b2000-06-22 00:17:42 +00001032 glyph_index = FT_Get_Char_Index( face, char_code );
1033
1034 return glyph_index ? FT_Load_Glyph( face, glyph_index, load_flags )
1035 : FT_Err_Invalid_Character_Code;
1036 }
1037
1038
Werner Lemberg7880dd62000-01-10 17:19:45 +00001039 /* destructor for sizes list */
1040 static
1041 void destroy_size( FT_Memory memory,
1042 FT_Size size,
1043 FT_Driver driver )
1044 {
David Turnerf0df85b2000-06-22 00:17:42 +00001045 /* finalize client-specific data */
Werner Lemberga929ba92000-06-25 06:47:11 +00001046 if ( size->generic.finalizer )
David Turnerf0df85b2000-06-22 00:17:42 +00001047 size->generic.finalizer( size );
1048
Werner Lemberg7880dd62000-01-10 17:19:45 +00001049 /* finalize format-specific stuff */
Werner Lemberga929ba92000-06-25 06:47:11 +00001050 if ( driver->clazz->done_size )
David Turnerf0df85b2000-06-22 00:17:42 +00001051 driver->clazz->done_size( size );
1052
Werner Lemberg7880dd62000-01-10 17:19:45 +00001053 FREE( size );
1054 }
David Turnerd2b1f351999-12-16 23:11:37 +00001055
1056
Werner Lemberg7880dd62000-01-10 17:19:45 +00001057 /* destructor for faces list */
1058 static
1059 void destroy_face( FT_Memory memory,
1060 FT_Face face,
1061 FT_Driver driver )
1062 {
David Turnerf0df85b2000-06-22 00:17:42 +00001063 FT_Driver_Class* clazz = driver->clazz;
1064
Werner Lemberga929ba92000-06-25 06:47:11 +00001065
David Turnerf0df85b2000-06-22 00:17:42 +00001066 /* Discard glyph slots for this face */
1067 /* Beware! FT_Done_GlyphSlot() changes the field `face->slot' */
Werner Lemberg7880dd62000-01-10 17:19:45 +00001068 while ( face->glyph )
1069 FT_Done_GlyphSlot( face->glyph );
1070
1071 /* Discard all sizes for this face */
1072 FT_List_Finalize( &face->sizes_list,
1073 (FT_List_Destructor)destroy_size,
1074 memory,
1075 driver );
1076 face->size = 0;
1077
Werner Lemberg7880dd62000-01-10 17:19:45 +00001078 /* Now discard client data */
1079 if ( face->generic.finalizer )
1080 face->generic.finalizer( face );
1081
David Turnerf0df85b2000-06-22 00:17:42 +00001082 /* finalize format-specific stuff */
Werner Lemberga929ba92000-06-25 06:47:11 +00001083 if ( clazz->done_face )
1084 clazz->done_face( face );
David Turnerf0df85b2000-06-22 00:17:42 +00001085
1086 /* close the stream for this face if needed */
Werner Lemberga929ba92000-06-25 06:47:11 +00001087 if ( ( face->face_flags & FT_FACE_FLAG_EXTERNAL_STREAM ) == 0 )
David Turnerf0df85b2000-06-22 00:17:42 +00001088 ft_done_stream( &face->stream );
David Turner7663f222000-02-13 13:37:38 +00001089
Werner Lemberg7880dd62000-01-10 17:19:45 +00001090 /* get rid of it */
1091 FREE( face );
1092 }
David Turnerd2b1f351999-12-16 23:11:37 +00001093
1094
David Turnerf0df85b2000-06-22 00:17:42 +00001095 static void Destroy_Driver( FT_Driver driver )
David Turnerd2b1f351999-12-16 23:11:37 +00001096 {
David Turnerd2b1f351999-12-16 23:11:37 +00001097 FT_List_Finalize( &driver->faces_list,
1098 (FT_List_Destructor)destroy_face,
David Turnerf0df85b2000-06-22 00:17:42 +00001099 driver->root.memory,
David Turnerd2b1f351999-12-16 23:11:37 +00001100 driver );
1101
David Turnerf0df85b2000-06-22 00:17:42 +00001102 /* see if we need to drop the driver's glyph loader */
Werner Lemberga929ba92000-06-25 06:47:11 +00001103 if ( FT_DRIVER_USES_OUTLINES( driver ) )
David Turnerf0df85b2000-06-22 00:17:42 +00001104 FT_GlyphLoader_Done( driver->glyph_loader );
David Turnerd2b1f351999-12-16 23:11:37 +00001105 }
1106
1107
Werner Lemberg547a2522000-02-16 08:23:58 +00001108 /*************************************************************************/
1109 /* */
1110 /* <Function> */
1111 /* open_face */
1112 /* */
1113 /* <Description> */
1114 /* This function does some work for FT_Open_Face(). */
1115 /* */
David Turnerd2b1f351999-12-16 23:11:37 +00001116 static
David Turner4f2c5542000-05-12 10:19:41 +00001117 FT_Error open_face( FT_Driver driver,
1118 FT_Stream stream,
1119 FT_Long face_index,
1120 FT_Int num_params,
1121 FT_Parameter* params,
1122 FT_Face* aface )
David Turnerd2b1f351999-12-16 23:11:37 +00001123 {
David Turnerf0df85b2000-06-22 00:17:42 +00001124 FT_Memory memory;
1125 FT_Driver_Class* clazz;
1126 FT_Face face = 0;
1127 FT_Error error;
David Turnerd2b1f351999-12-16 23:11:37 +00001128
Werner Lemberga929ba92000-06-25 06:47:11 +00001129
David Turnerf0df85b2000-06-22 00:17:42 +00001130 clazz = driver->clazz;
1131 memory = driver->root.memory;
David Turnerd2b1f351999-12-16 23:11:37 +00001132
Werner Lemberg547a2522000-02-16 08:23:58 +00001133 /* allocate the face object, and perform basic initialization */
David Turnerf0df85b2000-06-22 00:17:42 +00001134 if ( ALLOC( face, clazz->face_object_size ) )
David Turnerd2b1f351999-12-16 23:11:37 +00001135 goto Fail;
1136
1137 face->driver = driver;
1138 face->memory = memory;
1139 face->stream = stream;
1140
David Turnerf0df85b2000-06-22 00:17:42 +00001141 error = clazz->init_face( stream,
1142 face,
1143 face_index,
1144 num_params,
1145 params );
David Turnerd2b1f351999-12-16 23:11:37 +00001146 if ( error )
1147 goto Fail;
1148
1149 *aface = face;
1150
1151 Fail:
1152 if ( error )
1153 {
David Turnerf0df85b2000-06-22 00:17:42 +00001154 clazz->done_face( face );
David Turnerd2b1f351999-12-16 23:11:37 +00001155 FREE( face );
1156 *aface = 0;
1157 }
1158
1159 return error;
1160 }
1161
1162
1163 /*************************************************************************/
1164 /* */
1165 /* <Function> */
1166 /* FT_New_Face */
1167 /* */
1168 /* <Description> */
Werner Lemberg547a2522000-02-16 08:23:58 +00001169 /* Creates a new face object from a given resource and typeface index */
1170 /* using a pathname to the font file. */
1171 /* */
1172 /* <InOut> */
1173 /* library :: A handle to the library resource. */
David Turnerd2b1f351999-12-16 23:11:37 +00001174 /* */
1175 /* <Input> */
Werner Lemberg547a2522000-02-16 08:23:58 +00001176 /* pathname :: A path to the font file. */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001177 /* */
David Turnerd2b1f351999-12-16 23:11:37 +00001178 /* face_index :: The index of the face within the resource. The */
1179 /* first face has index 0. */
1180 /* <Output> */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001181 /* aface :: A handle to a new face object. */
David Turnerd2b1f351999-12-16 23:11:37 +00001182 /* */
1183 /* <Return> */
Werner Lemberg7880dd62000-01-10 17:19:45 +00001184 /* FreeType error code. 0 means success. */
David Turnerd2b1f351999-12-16 23:11:37 +00001185 /* */
1186 /* <Note> */
Werner Lemberg547a2522000-02-16 08:23:58 +00001187 /* Unlike FreeType 1.x, this function automatically creates a glyph */
David Turnerd2b1f351999-12-16 23:11:37 +00001188 /* slot for the face object which can be accessed directly through */
1189 /* `face->glyph'. */
1190 /* */
Werner Lemberg547a2522000-02-16 08:23:58 +00001191 /* Note that additional slots can be added to each face with the */
David Turnerd2b1f351999-12-16 23:11:37 +00001192 /* FT_New_GlyphSlot() API function. Slots are linked in a single */
1193 /* list through their `next' field. */
1194 /* */
1195 /* FT_New_Face() can be used to determine and/or check the font */
1196 /* format of a given font resource. If the `face_index' field is */
1197 /* negative, the function will _not_ return any face handle in */
1198 /* `*face'. Its return value should be 0 if the resource is */
1199 /* recognized, or non-zero if not. */
1200 /* */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001201 FT_EXPORT_FUNC( FT_Error ) FT_New_Face( FT_Library library,
1202 const char* pathname,
1203 FT_Long face_index,
1204 FT_Face* aface )
David Turnerd2b1f351999-12-16 23:11:37 +00001205 {
David Turner37379e22000-03-28 11:22:31 +00001206 FT_Open_Args args;
Werner Lemberg547a2522000-02-16 08:23:58 +00001207
Werner Lemberga929ba92000-06-25 06:47:11 +00001208
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001209 /* test for valid `library' and `aface' delayed to FT_Open_Face() */
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001210 if ( !pathname )
1211 return FT_Err_Invalid_Argument;
1212
David Turner4f2c5542000-05-12 10:19:41 +00001213 args.flags = ft_open_pathname;
1214 args.pathname = (char*)pathname;
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001215
David Turnercda32b72000-02-10 16:14:35 +00001216 return FT_Open_Face( library, &args, face_index, aface );
David Turnerd2b1f351999-12-16 23:11:37 +00001217 }
1218
Werner Lemberg7880dd62000-01-10 17:19:45 +00001219
Werner Lemberg547a2522000-02-16 08:23:58 +00001220 /*************************************************************************/
1221 /* */
1222 /* <Function> */
1223 /* FT_New_Memory_Face */
1224 /* */
1225 /* <Description> */
1226 /* Creates a new face object from a given resource and typeface index */
1227 /* using a font file already loaded into memory. */
1228 /* */
1229 /* <InOut> */
1230 /* library :: A handle to the library resource. */
1231 /* */
1232 /* <Input> */
1233 /* file_base :: A pointer to the beginning of the font data. */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001234 /* */
Werner Lemberg547a2522000-02-16 08:23:58 +00001235 /* file_size :: The size of the memory chunk used by the font data. */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001236 /* */
Werner Lemberg547a2522000-02-16 08:23:58 +00001237 /* face_index :: The index of the face within the resource. The */
1238 /* first face has index 0. */
1239 /* <Output> */
1240 /* face :: A handle to a new face object. */
1241 /* */
1242 /* <Return> */
1243 /* FreeType error code. 0 means success. */
1244 /* */
1245 /* <Note> */
1246 /* Unlike FreeType 1.x, this function automatically creates a glyph */
1247 /* slot for the face object which can be accessed directly through */
1248 /* `face->glyph'. */
1249 /* */
1250 /* Note that additional slots can be added to each face with the */
1251 /* FT_New_GlyphSlot() API function. Slots are linked in a single */
1252 /* list through their `next' field. */
1253 /* */
1254 /* FT_New_Memory_Face() can be used to determine and/or check the */
1255 /* font format of a given font resource. If the `face_index' field */
1256 /* is negative, the function will _not_ return any face handle in */
1257 /* `*face'. Its return value should be 0 if the resource is */
1258 /* recognized, or non-zero if not. */
1259 /* */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001260 FT_EXPORT_FUNC( FT_Error ) FT_New_Memory_Face( FT_Library library,
1261 void* file_base,
1262 FT_Long file_size,
1263 FT_Long face_index,
1264 FT_Face* face )
David Turnerd2b1f351999-12-16 23:11:37 +00001265 {
David Turner37379e22000-03-28 11:22:31 +00001266 FT_Open_Args args;
Werner Lemberg7880dd62000-01-10 17:19:45 +00001267
Werner Lemberga929ba92000-06-25 06:47:11 +00001268
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001269 /* test for valid `library' and `face' delayed to FT_Open_Face() */
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001270 if ( !file_base )
1271 return FT_Err_Invalid_Argument;
1272
David Turner4f2c5542000-05-12 10:19:41 +00001273 args.flags = ft_open_memory;
David Turnercda32b72000-02-10 16:14:35 +00001274 args.memory_base = file_base;
1275 args.memory_size = file_size;
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001276
David Turnercda32b72000-02-10 16:14:35 +00001277 return FT_Open_Face( library, &args, face_index, face );
David Turnerd2b1f351999-12-16 23:11:37 +00001278 }
1279
Werner Lemberg7880dd62000-01-10 17:19:45 +00001280
Werner Lemberg547a2522000-02-16 08:23:58 +00001281 /*************************************************************************/
1282 /* */
1283 /* <Function> */
1284 /* FT_Open_Face */
1285 /* */
1286 /* <Description> */
1287 /* Opens a face object from a given resource and typeface index using */
1288 /* an `FT_Open_Args' structure. If the face object doesn't exist, it */
1289 /* will be created. */
1290 /* */
1291 /* <InOut> */
1292 /* library :: A handle to the library resource. */
1293 /* */
1294 /* <Input> */
1295 /* args :: A pointer to an `FT_Open_Args' structure which must */
1296 /* be filled by the caller. */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001297 /* */
Werner Lemberg547a2522000-02-16 08:23:58 +00001298 /* face_index :: The index of the face within the resource. The */
1299 /* first face has index 0. */
1300 /* <Output> */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001301 /* aface :: A handle to a new face object. */
Werner Lemberg547a2522000-02-16 08:23:58 +00001302 /* */
1303 /* <Return> */
1304 /* FreeType error code. 0 means success. */
1305 /* */
1306 /* <Note> */
1307 /* Unlike FreeType 1.x, this function automatically creates a glyph */
1308 /* slot for the face object which can be accessed directly through */
1309 /* `face->glyph'. */
1310 /* */
1311 /* Note that additional slots can be added to each face with the */
1312 /* FT_New_GlyphSlot() API function. Slots are linked in a single */
1313 /* list through their `next' field. */
1314 /* */
1315 /* FT_Open_Face() can be used to determine and/or check the font */
1316 /* format of a given font resource. If the `face_index' field is */
1317 /* negative, the function will _not_ return any face handle in */
1318 /* `*face'. Its return value should be 0 if the resource is */
1319 /* recognized, or non-zero if not. */
1320 /* */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001321 FT_EXPORT_FUNC( FT_Error ) FT_Open_Face( FT_Library library,
1322 FT_Open_Args* args,
1323 FT_Long face_index,
1324 FT_Face* aface )
David Turnerd2b1f351999-12-16 23:11:37 +00001325 {
1326 FT_Error error;
1327 FT_Driver driver;
1328 FT_Memory memory;
David Turnercda32b72000-02-10 16:14:35 +00001329 FT_Stream stream;
David Turnerd2b1f351999-12-16 23:11:37 +00001330 FT_Face face = 0;
1331 FT_ListNode node = 0;
1332
Werner Lemberg547a2522000-02-16 08:23:58 +00001333
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001334 /* test for valid `library' and `args' delayed to */
1335 /* ft_new_input_stream() */
David Turnerd2b1f351999-12-16 23:11:37 +00001336
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001337 if ( !aface )
1338 return FT_Err_Invalid_Argument;
1339
1340 *aface = 0;
David Turnerd2b1f351999-12-16 23:11:37 +00001341
David Turnercda32b72000-02-10 16:14:35 +00001342 /* create input stream */
1343 error = ft_new_input_stream( library, args, &stream );
David Turnerf0df85b2000-06-22 00:17:42 +00001344 if ( error ) goto Exit;
David Turnercda32b72000-02-10 16:14:35 +00001345
David Turnerd2b1f351999-12-16 23:11:37 +00001346 memory = library->memory;
1347
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001348 /* If the font driver is specified in the `args' structure, use */
Werner Lemberg547a2522000-02-16 08:23:58 +00001349 /* it. Otherwise, we'll scan the list of registered drivers. */
David Turner4f2c5542000-05-12 10:19:41 +00001350 if ( args->flags & ft_open_driver && args->driver )
David Turner7663f222000-02-13 13:37:38 +00001351 {
Werner Lemberga929ba92000-06-25 06:47:11 +00001352 driver = FT_DRIVER( args->driver );
David Turnerf0df85b2000-06-22 00:17:42 +00001353
1354 /* not all modules are drivers, so check... */
Werner Lemberga929ba92000-06-25 06:47:11 +00001355 if ( FT_MODULE_IS_DRIVER( driver ) )
David Turner7663f222000-02-13 13:37:38 +00001356 {
David Turner4f2c5542000-05-12 10:19:41 +00001357 FT_Int num_params = 0;
1358 FT_Parameter* params = 0;
David Turnere49ab252000-05-16 23:44:38 +00001359
Werner Lemberga929ba92000-06-25 06:47:11 +00001360
David Turner4f2c5542000-05-12 10:19:41 +00001361 if ( args->flags & ft_open_params )
1362 {
1363 num_params = args->num_params;
1364 params = args->params;
1365 }
David Turnere49ab252000-05-16 23:44:38 +00001366
David Turner4f2c5542000-05-12 10:19:41 +00001367 error = open_face( driver, stream, face_index,
1368 num_params, params, &face );
Werner Lemberg547a2522000-02-16 08:23:58 +00001369 if ( !error )
1370 goto Success;
David Turner7663f222000-02-13 13:37:38 +00001371 }
1372 else
1373 error = FT_Err_Invalid_Handle;
1374
David Turner2a98b3c2000-06-23 13:47:55 +00001375 ft_done_stream( &stream );
David Turner7663f222000-02-13 13:37:38 +00001376 goto Fail;
1377 }
Just van Rossum1e5754f2000-03-02 10:52:57 +00001378 else
David Turnerd2b1f351999-12-16 23:11:37 +00001379 {
1380 /* check each font driver for an appropriate format */
David Turnerf0df85b2000-06-22 00:17:42 +00001381 FT_Module* cur = library->modules;
1382 FT_Module* limit = cur + library->num_modules;
David Turnerd2b1f351999-12-16 23:11:37 +00001383
Werner Lemberga929ba92000-06-25 06:47:11 +00001384
David Turnerd2b1f351999-12-16 23:11:37 +00001385 for ( ; cur < limit; cur++ )
1386 {
David Turnerf0df85b2000-06-22 00:17:42 +00001387 /* not all modules are font drivers, so check... */
Werner Lemberga929ba92000-06-25 06:47:11 +00001388 if ( FT_MODULE_IS_DRIVER( cur[0] ) )
David Turnerd2b1f351999-12-16 23:11:37 +00001389 {
David Turner4f2c5542000-05-12 10:19:41 +00001390 FT_Int num_params = 0;
1391 FT_Parameter* params = 0;
David Turnere49ab252000-05-16 23:44:38 +00001392
Werner Lemberga929ba92000-06-25 06:47:11 +00001393 driver = FT_DRIVER( cur[0] );
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001394
David Turner4f2c5542000-05-12 10:19:41 +00001395 if ( args->flags & ft_open_params )
1396 {
1397 num_params = args->num_params;
1398 params = args->params;
1399 }
David Turnere49ab252000-05-16 23:44:38 +00001400
David Turner4f2c5542000-05-12 10:19:41 +00001401 error = open_face( driver, stream, face_index,
1402 num_params, params, &face );
David Turnerd2b1f351999-12-16 23:11:37 +00001403 if ( !error )
1404 goto Success;
1405
1406 if ( error != FT_Err_Unknown_File_Format )
David Turnercda32b72000-02-10 16:14:35 +00001407 goto Fail;
David Turnerd2b1f351999-12-16 23:11:37 +00001408 }
1409 }
1410
David Turner2a98b3c2000-06-23 13:47:55 +00001411 ft_done_stream( &stream );
1412
David Turnerd2b1f351999-12-16 23:11:37 +00001413 /* no driver is able to handle this format */
1414 error = FT_Err_Unknown_File_Format;
David Turnercda32b72000-02-10 16:14:35 +00001415 goto Fail;
David Turnerd2b1f351999-12-16 23:11:37 +00001416 }
1417
1418 Success:
David Turnerd2b1f351999-12-16 23:11:37 +00001419 FT_TRACE4(( "FT_New_Face: New face object, adding to list\n" ));
1420
David Turnerf0df85b2000-06-22 00:17:42 +00001421 /* set the EXTERNAL_STREAM bit for FT_Done_Face */
1422 if ( args->flags & ft_open_stream && args->stream )
1423 face->face_flags |= FT_FACE_FLAG_EXTERNAL_STREAM;
1424
Werner Lemberg547a2522000-02-16 08:23:58 +00001425 /* add the face object to its driver's list */
David Turnerd2b1f351999-12-16 23:11:37 +00001426 if ( ALLOC( node, sizeof ( *node ) ) )
1427 goto Fail;
1428
1429 node->data = face;
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001430 /* don't assume driver is the same as face->driver, so use */
1431 /* face->driver instead. */
Just van Rossum7eef5362000-03-05 16:07:58 +00001432 FT_List_Add( &face->driver->faces_list, node );
David Turnerd2b1f351999-12-16 23:11:37 +00001433
Werner Lemberg547a2522000-02-16 08:23:58 +00001434 /* now allocate a glyph slot object for the face */
David Turnerd2b1f351999-12-16 23:11:37 +00001435 {
1436 FT_GlyphSlot slot;
1437
Werner Lemberg547a2522000-02-16 08:23:58 +00001438
David Turnerd2b1f351999-12-16 23:11:37 +00001439 FT_TRACE4(( "FT_Open_Face: Creating glyph slot\n" ));
1440 error = FT_New_GlyphSlot( face, &slot );
David Turnerf0df85b2000-06-22 00:17:42 +00001441 if ( error ) goto Fail;
1442
1443 face->glyph = slot;
David Turnerd2b1f351999-12-16 23:11:37 +00001444 }
Werner Lemberg7880dd62000-01-10 17:19:45 +00001445
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001446 /* finally, allocate a size object for the face */
David Turnerd2b1f351999-12-16 23:11:37 +00001447 {
1448 FT_Size size;
1449
Werner Lemberg547a2522000-02-16 08:23:58 +00001450
David Turnerd2b1f351999-12-16 23:11:37 +00001451 FT_TRACE4(( "FT_Open_Face: Creating size object\n" ));
1452 error = FT_New_Size( face, &size );
David Turnerf0df85b2000-06-22 00:17:42 +00001453 if ( error ) goto Fail;
1454
1455 face->size = size;
David Turnerd2b1f351999-12-16 23:11:37 +00001456 }
Werner Lemberg7880dd62000-01-10 17:19:45 +00001457
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001458 /* initialize transformation for convenience functions */
David Turner37379e22000-03-28 11:22:31 +00001459 face->transform_matrix.xx = 0x10000L;
1460 face->transform_matrix.xy = 0;
1461 face->transform_matrix.yx = 0;
1462 face->transform_matrix.yy = 0x10000L;
1463
1464 face->transform_delta.x = 0;
1465 face->transform_delta.y = 0;
1466
David Turnerd2b1f351999-12-16 23:11:37 +00001467 *aface = face;
1468 goto Exit;
1469
1470 Fail:
1471 FT_Done_Face( face );
1472
David Turnerd2b1f351999-12-16 23:11:37 +00001473 Exit:
1474 FT_TRACE4(( "FT_Open_Face: Return %d\n", error ));
1475 return error;
1476 }
1477
1478
1479 /*************************************************************************/
1480 /* */
1481 /* <Function> */
David Turner7663f222000-02-13 13:37:38 +00001482 /* FT_Attach_File */
1483 /* */
1484 /* <Description> */
Werner Lemberg547a2522000-02-16 08:23:58 +00001485 /* `Attaches' a given font file to an existing face. This is usually */
1486 /* to read additional information for a single face object. For */
David Turner7663f222000-02-13 13:37:38 +00001487 /* example, it is used to read the AFM files that come with Type 1 */
Werner Lemberg547a2522000-02-16 08:23:58 +00001488 /* fonts in order to add kerning data and other metrics. */
1489 /* */
1490 /* <InOut> */
1491 /* face :: The target face object. */
David Turner7663f222000-02-13 13:37:38 +00001492 /* */
1493 /* <Input> */
Werner Lemberg547a2522000-02-16 08:23:58 +00001494 /* filepathname :: An 8-bit pathname naming the `metrics' file. */
David Turner7663f222000-02-13 13:37:38 +00001495 /* */
1496 /* <Return> */
Werner Lemberg547a2522000-02-16 08:23:58 +00001497 /* FreeType error code. 0 means success. */
David Turner7663f222000-02-13 13:37:38 +00001498 /* */
1499 /* <Note> */
1500 /* If your font file is in memory, or if you want to provide your */
Werner Lemberg547a2522000-02-16 08:23:58 +00001501 /* own input stream object, use FT_Attach_Stream(). */
David Turner7663f222000-02-13 13:37:38 +00001502 /* */
Werner Lemberg547a2522000-02-16 08:23:58 +00001503 /* The meaning of the `attach' action (i.e., what really happens when */
1504 /* the new file is read) is not fixed by FreeType itself. It really */
David Turner7663f222000-02-13 13:37:38 +00001505 /* depends on the font format (and thus the font driver). */
1506 /* */
Werner Lemberg547a2522000-02-16 08:23:58 +00001507 /* Client applications are expected to know what they are doing */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001508 /* when invoking this function. Most drivers simply do not implement */
Werner Lemberg547a2522000-02-16 08:23:58 +00001509 /* file attachments. */
David Turner7663f222000-02-13 13:37:38 +00001510 /* */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001511 FT_EXPORT_FUNC( FT_Error ) FT_Attach_File( FT_Face face,
1512 const char* filepathname )
David Turner7663f222000-02-13 13:37:38 +00001513 {
David Turner37379e22000-03-28 11:22:31 +00001514 FT_Open_Args open;
David Turner7663f222000-02-13 13:37:38 +00001515
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001516
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001517 /* test for valid `face' delayed to FT_Attach_Stream() */
1518
1519 if ( !filepathname )
1520 return FT_Err_Invalid_Argument;
1521
David Turner4f2c5542000-05-12 10:19:41 +00001522 open.flags = ft_open_pathname;
1523 open.pathname = (char*)filepathname;
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001524
David Turner7663f222000-02-13 13:37:38 +00001525 return FT_Attach_Stream( face, &open );
1526 }
Werner Lemberg547a2522000-02-16 08:23:58 +00001527
David Turnere49ab252000-05-16 23:44:38 +00001528
David Turner7663f222000-02-13 13:37:38 +00001529 /*************************************************************************/
1530 /* */
1531 /* <Function> */
1532 /* FT_Attach_Stream */
1533 /* */
1534 /* <Description> */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001535 /* This function is similar to FT_Attach_File() with the exception */
David Turner7663f222000-02-13 13:37:38 +00001536 /* that it reads the attachment from an arbitrary stream. */
1537 /* */
1538 /* <Input> */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001539 /* face :: The target face object. */
David Turner7663f222000-02-13 13:37:38 +00001540 /* */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001541 /* parameters :: A pointer to an FT_Open_Args structure used to */
1542 /* describe the input stream to FreeType. */
David Turner7663f222000-02-13 13:37:38 +00001543 /* <Return> */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001544 /* FreeType error code. 0 means success. */
David Turner7663f222000-02-13 13:37:38 +00001545 /* */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001546 /* <Note> */
1547 /* The meaning of the `attach' (i.e. what really happens when the */
1548 /* new file is read) is not fixed by FreeType itself. It really */
David Turner7663f222000-02-13 13:37:38 +00001549 /* depends on the font format (and thus the font driver). */
1550 /* */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001551 /* Client applications are expected to know what they are doing */
1552 /* when invoking this function. Most drivers simply do not implement */
1553 /* file attachments. */
David Turner7663f222000-02-13 13:37:38 +00001554 /* */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001555 FT_EXPORT_FUNC( FT_Error ) FT_Attach_Stream( FT_Face face,
1556 FT_Open_Args* parameters )
David Turner7663f222000-02-13 13:37:38 +00001557 {
1558 FT_Stream stream;
1559 FT_Error error;
1560 FT_Driver driver;
David Turnere49ab252000-05-16 23:44:38 +00001561
David Turnerf0df85b2000-06-22 00:17:42 +00001562 FT_Driver_Class* clazz;
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001563
Werner Lemberga929ba92000-06-25 06:47:11 +00001564
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001565 /* test for valid `parameters' delayed to ft_new_input_stream() */
1566
1567 if ( !face )
1568 return FT_Err_Invalid_Face_Handle;
David Turnere49ab252000-05-16 23:44:38 +00001569
David Turner7663f222000-02-13 13:37:38 +00001570 driver = face->driver;
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001571 if ( !driver )
1572 return FT_Err_Invalid_Driver_Handle;
1573
David Turnerf0df85b2000-06-22 00:17:42 +00001574 error = ft_new_input_stream( driver->root.library, parameters, &stream );
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001575 if ( error )
1576 goto Exit;
David Turnere49ab252000-05-16 23:44:38 +00001577
David Turner7663f222000-02-13 13:37:38 +00001578 /* we implement FT_Attach_Stream in each driver through the */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001579 /* `attach_file' interface */
1580
David Turner7663f222000-02-13 13:37:38 +00001581 error = FT_Err_Unimplemented_Feature;
David Turnerf0df85b2000-06-22 00:17:42 +00001582 clazz = driver->clazz;
Werner Lemberga929ba92000-06-25 06:47:11 +00001583 if ( clazz->attach_file )
David Turnerf0df85b2000-06-22 00:17:42 +00001584 error = clazz->attach_file( face, stream );
David Turnere49ab252000-05-16 23:44:38 +00001585
David Turner7663f222000-02-13 13:37:38 +00001586 /* close the attached stream */
Werner Lemberga929ba92000-06-25 06:47:11 +00001587 if ( !parameters->stream || ( parameters->flags & ft_open_stream ) )
David Turnerf0df85b2000-06-22 00:17:42 +00001588 ft_done_stream( &stream );
David Turnere49ab252000-05-16 23:44:38 +00001589
David Turner7663f222000-02-13 13:37:38 +00001590 Exit:
1591 return error;
1592 }
1593
1594
David Turner7663f222000-02-13 13:37:38 +00001595 /*************************************************************************/
1596 /* */
1597 /* <Function> */
David Turnerd2b1f351999-12-16 23:11:37 +00001598 /* FT_Done_Face */
1599 /* */
1600 /* <Description> */
1601 /* Discards a given face object, as well as all of its child slots */
1602 /* and sizes. */
1603 /* */
1604 /* <Input> */
1605 /* face :: A handle to a target face object. */
1606 /* */
1607 /* <Return> */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001608 /* FreeType error code. 0 means success. */
David Turnerd2b1f351999-12-16 23:11:37 +00001609 /* */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001610 FT_EXPORT_FUNC( FT_Error ) FT_Done_Face( FT_Face face )
David Turnerd2b1f351999-12-16 23:11:37 +00001611 {
Werner Lemberga929ba92000-06-25 06:47:11 +00001612 FT_Error error;
1613 FT_Driver driver;
1614 FT_Memory memory;
1615 FT_ListNode node;
1616
David Turnerd2b1f351999-12-16 23:11:37 +00001617
David Turnerf0df85b2000-06-22 00:17:42 +00001618 error = FT_Err_Invalid_Face_Handle;
1619 if ( face && face->driver )
David Turnerd2b1f351999-12-16 23:11:37 +00001620 {
David Turnerf0df85b2000-06-22 00:17:42 +00001621 driver = face->driver;
1622 memory = driver->root.memory;
1623
1624 /* find face in driver's list */
1625 node = FT_List_Find( &driver->faces_list, face );
1626 if ( node )
1627 {
1628 /* remove face object from the driver's list */
1629 FT_List_Remove( &driver->faces_list, node );
1630 FREE( node );
1631
1632 /* now destroy the object proper */
1633 destroy_face( memory, face, driver );
1634 error = FT_Err_Ok;
1635 }
David Turnerd2b1f351999-12-16 23:11:37 +00001636 }
David Turnerd2b1f351999-12-16 23:11:37 +00001637 return error;
1638 }
1639
1640
1641 /*************************************************************************/
1642 /* */
1643 /* <Function> */
1644 /* FT_New_Size */
1645 /* */
1646 /* <Description> */
1647 /* Creates a new size object from a given face object. */
1648 /* */
1649 /* <Input> */
1650 /* face :: A handle to a parent face object. */
1651 /* */
1652 /* <Output> */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001653 /* asize :: A handle to a new size object. */
David Turnerd2b1f351999-12-16 23:11:37 +00001654 /* */
1655 /* <Return> */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001656 /* FreeType error code. 0 means success. */
David Turnerd2b1f351999-12-16 23:11:37 +00001657 /* */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001658 FT_EXPORT_FUNC( FT_Error ) FT_New_Size( FT_Face face,
1659 FT_Size* asize )
David Turnerd2b1f351999-12-16 23:11:37 +00001660 {
David Turnerf0df85b2000-06-22 00:17:42 +00001661 FT_Error error;
1662 FT_Memory memory;
1663 FT_Driver driver;
1664 FT_Driver_Class* clazz;
David Turnerd2b1f351999-12-16 23:11:37 +00001665
David Turnerf0df85b2000-06-22 00:17:42 +00001666 FT_Size size = 0;
1667 FT_ListNode node = 0;
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001668
Werner Lemberga929ba92000-06-25 06:47:11 +00001669
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001670 *asize = 0;
1671
David Turnerf0df85b2000-06-22 00:17:42 +00001672 if ( !face || !asize || !face->driver )
1673 return FT_Err_Invalid_Handle;
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001674
David Turnerf0df85b2000-06-22 00:17:42 +00001675 driver = face->driver;
1676 clazz = driver->clazz;
1677 memory = face->memory;
David Turnerd2b1f351999-12-16 23:11:37 +00001678
1679 /* Allocate new size object and perform basic initialisation */
David Turnerf0df85b2000-06-22 00:17:42 +00001680 if ( ALLOC( size, clazz->size_object_size ) ||
1681 ALLOC( node, sizeof ( FT_ListNodeRec ) ) )
David Turnerd2b1f351999-12-16 23:11:37 +00001682 goto Exit;
1683
1684 size->face = face;
1685
Werner Lemberga929ba92000-06-25 06:47:11 +00001686 if ( clazz->init_size )
David Turnerf0df85b2000-06-22 00:17:42 +00001687 error = clazz->init_size( size );
David Turnerd2b1f351999-12-16 23:11:37 +00001688
1689 /* in case of success, add to the face's list */
1690 if ( !error )
1691 {
1692 *asize = size;
1693 node->data = size;
1694 FT_List_Add( &face->sizes_list, node );
David Turnerd2b1f351999-12-16 23:11:37 +00001695 }
1696
1697 Exit:
1698 if ( error )
1699 {
1700 FREE( node );
1701 FREE( size );
1702 }
1703
1704 return error;
1705 }
1706
1707
1708 /*************************************************************************/
1709 /* */
1710 /* <Function> */
1711 /* FT_Done_Size */
1712 /* */
1713 /* <Description> */
1714 /* Discards a given size object. */
1715 /* */
1716 /* <Input> */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001717 /* size :: A handle to a target size object. */
David Turnerd2b1f351999-12-16 23:11:37 +00001718 /* */
1719 /* <Return> */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001720 /* FreeType error code. 0 means success. */
David Turnerd2b1f351999-12-16 23:11:37 +00001721 /* */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001722 FT_EXPORT_FUNC( FT_Error ) FT_Done_Size( FT_Size size )
David Turnerd2b1f351999-12-16 23:11:37 +00001723 {
1724 FT_Error error;
1725 FT_Driver driver;
1726 FT_Memory memory;
1727 FT_Face face;
1728 FT_ListNode node;
1729
1730
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001731 if ( !size )
David Turnerd2b1f351999-12-16 23:11:37 +00001732 return FT_Err_Invalid_Size_Handle;
1733
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001734 face = size->face;
1735 if ( !face )
1736 return FT_Err_Invalid_Face_Handle;
1737
1738 driver = face->driver;
David Turnerd2b1f351999-12-16 23:11:37 +00001739 if ( !driver )
1740 return FT_Err_Invalid_Driver_Handle;
1741
David Turnerf0df85b2000-06-22 00:17:42 +00001742 memory = driver->root.memory;
David Turnerd2b1f351999-12-16 23:11:37 +00001743
1744 error = FT_Err_Ok;
David Turnerd2b1f351999-12-16 23:11:37 +00001745 node = FT_List_Find( &face->sizes_list, size );
1746 if ( node )
1747 {
1748 FT_List_Remove( &face->sizes_list, node );
1749 FREE( node );
1750
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001751 if ( face->size == size )
David Turnerd2b1f351999-12-16 23:11:37 +00001752 {
1753 face->size = 0;
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001754 if ( face->sizes_list.head )
David Turnerd2b1f351999-12-16 23:11:37 +00001755 face->size = (FT_Size)(face->sizes_list.head->data);
1756 }
1757
1758 destroy_size( memory, size, driver );
1759 }
1760 else
1761 error = FT_Err_Invalid_Size_Handle;
1762
1763 return FT_Err_Ok;
1764 }
1765
1766
Werner Lemberga929ba92000-06-25 06:47:11 +00001767 static void ft_recompute_scaled_metrics( FT_Face face,
1768 FT_Size_Metrics* metrics )
1769 {
1770 /* Compute root ascender, descender, test height, and max_advance */
1771 metrics->ascender = ( FT_MulFix( face->ascender,
1772 metrics->y_scale ) + 32 ) & -64;
1773
1774 metrics->descender = ( FT_MulFix( face->descender,
1775 metrics->y_scale ) + 32 ) & -64;
1776
1777 metrics->height = ( FT_MulFix( face->height,
1778 metrics->y_scale ) + 32 ) & -64;
1779
1780 metrics->max_advance = ( FT_MulFix( face->max_advance_width,
1781 metrics->x_scale ) + 32 ) & -64;
1782 }
1783
1784
David Turnerd2b1f351999-12-16 23:11:37 +00001785 /*************************************************************************/
1786 /* */
1787 /* <Function> */
1788 /* FT_Set_Char_Size */
1789 /* */
1790 /* <Description> */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001791 /* Sets the character dimensions of a given face object. The */
1792 /* `char_width' and `char_height' values are used for the width and */
1793 /* height, respectively, expressed in 26.6 fractional points. */
1794 /* */
1795 /* If the horizontal or vertical resolution values are zero, a */
1796 /* default value of 72dpi is used. Similarly, if one of the */
1797 /* character dimensions is zero, its value is set equal to the other. */
1798 /* */
1799 /* <InOut> */
1800 /* size :: A handle to a target size object. */
David Turnerd2b1f351999-12-16 23:11:37 +00001801 /* */
1802 /* <Input> */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001803 /* char_width :: The character width, in 26.6 fractional points. */
1804 /* */
1805 /* char_height :: The character height, in 26.6 fractional */
1806 /* points. */
1807 /* */
1808 /* horz_resolution :: The horizontal resolution. */
1809 /* */
1810 /* vert_resolution :: The vertical resolution. */
David Turnerd2b1f351999-12-16 23:11:37 +00001811 /* */
1812 /* <Return> */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001813 /* FreeType error code. 0 means success. */
David Turnerd2b1f351999-12-16 23:11:37 +00001814 /* */
1815 /* <Note> */
1816 /* When dealing with fixed-size faces (i.e., non-scalable formats), */
1817 /* use the function FT_Set_Pixel_Sizes(). */
1818 /* */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001819 FT_EXPORT_FUNC( FT_Error ) FT_Set_Char_Size( FT_Face face,
1820 FT_F26Dot6 char_width,
1821 FT_F26Dot6 char_height,
1822 FT_UInt horz_resolution,
1823 FT_UInt vert_resolution )
David Turnerd2b1f351999-12-16 23:11:37 +00001824 {
David Turnerf0df85b2000-06-22 00:17:42 +00001825 FT_Error error = FT_Err_Ok;
1826 FT_Driver driver;
1827 FT_Memory memory;
1828 FT_Driver_Class* clazz;
1829 FT_Size_Metrics* metrics;
1830 FT_Long dim_x, dim_y;
David Turnerd2b1f351999-12-16 23:11:37 +00001831
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001832
David Turnerf0df85b2000-06-22 00:17:42 +00001833 if ( !face || !face->size || !face->driver )
David Turnerd2b1f351999-12-16 23:11:37 +00001834 return FT_Err_Invalid_Face_Handle;
1835
David Turnerf0df85b2000-06-22 00:17:42 +00001836 driver = face->driver;
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001837 metrics = &face->size->metrics;
1838
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001839 if ( !char_width )
David Turnerd2b1f351999-12-16 23:11:37 +00001840 char_width = char_height;
David Turnerf0df85b2000-06-22 00:17:42 +00001841
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001842 else if ( !char_height )
David Turnerd2b1f351999-12-16 23:11:37 +00001843 char_height = char_width;
Werner Lemberg7880dd62000-01-10 17:19:45 +00001844
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001845 if ( !horz_resolution )
David Turnerd2b1f351999-12-16 23:11:37 +00001846 horz_resolution = 72;
David Turnerf0df85b2000-06-22 00:17:42 +00001847
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001848 if ( !vert_resolution )
David Turnerd2b1f351999-12-16 23:11:37 +00001849 vert_resolution = 72;
1850
David Turnerf0df85b2000-06-22 00:17:42 +00001851 driver = face->driver;
1852 clazz = driver->clazz;
1853 memory = driver->root.memory;
David Turnerd2b1f351999-12-16 23:11:37 +00001854
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001855 /* default processing -- this can be overridden by the driver */
1856 if ( char_width < 1 * 64 ) char_width = 1 * 64;
1857 if ( char_height < 1 * 64 ) char_height = 1 * 64;
David Turnerd42c68e2000-01-27 13:56:02 +00001858
1859 /* Compute pixel sizes in 26.6 units */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001860 dim_x = ( ( ( char_width * horz_resolution ) / 72 ) + 32 ) & -64;
1861 dim_y = ( ( ( char_height * vert_resolution ) / 72 ) + 32 ) & -64;
David Turnerd42c68e2000-01-27 13:56:02 +00001862
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001863 metrics->x_ppem = (FT_UShort)(dim_x >> 6);
1864 metrics->y_ppem = (FT_UShort)(dim_y >> 6);
David Turnerd42c68e2000-01-27 13:56:02 +00001865
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001866 metrics->x_scale = 0x10000L;
1867 metrics->y_scale = 0x10000L;
1868
1869 if ( face->face_flags & FT_FACE_FLAG_SCALABLE )
David Turnerd42c68e2000-01-27 13:56:02 +00001870 {
1871 metrics->x_scale = FT_DivFix( dim_x, face->units_per_EM );
1872 metrics->y_scale = FT_DivFix( dim_y, face->units_per_EM );
1873 }
1874
David Turnerf0df85b2000-06-22 00:17:42 +00001875 ft_recompute_scaled_metrics( face, metrics );
1876
Werner Lemberga929ba92000-06-25 06:47:11 +00001877 if ( clazz->set_char_sizes )
David Turnerf0df85b2000-06-22 00:17:42 +00001878 error = clazz->set_char_sizes( face->size,
1879 char_width,
1880 char_height,
1881 horz_resolution,
1882 vert_resolution );
David Turnerd2b1f351999-12-16 23:11:37 +00001883 return error;
1884 }
1885
1886
1887 /*************************************************************************/
1888 /* */
1889 /* <Function> */
1890 /* FT_Set_Pixel_Sizes */
1891 /* */
1892 /* <Description> */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001893 /* Sets the character dimensions of a given face object. The width */
David Turnerd2b1f351999-12-16 23:11:37 +00001894 /* and height are expressed in integer pixels. */
1895 /* */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001896 /* If one of the character dimensions is zero, its value is set equal */
1897 /* to the other. */
1898 /* */
1899 /* <InOut> */
1900 /* face :: A handle to the target face object. */
1901 /* */
David Turnerd2b1f351999-12-16 23:11:37 +00001902 /* <Input> */
David Turnerd2b1f351999-12-16 23:11:37 +00001903 /* pixel_width :: The character width, in integer pixels. */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001904 /* */
David Turnerd2b1f351999-12-16 23:11:37 +00001905 /* pixel_height :: The character height, in integer pixels. */
1906 /* */
1907 /* <Return> */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001908 /* FreeType error code. 0 means success. */
David Turnerd2b1f351999-12-16 23:11:37 +00001909 /* */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001910 FT_EXPORT_FUNC( FT_Error ) FT_Set_Pixel_Sizes( FT_Face face,
1911 FT_UInt pixel_width,
1912 FT_UInt pixel_height )
David Turnerd2b1f351999-12-16 23:11:37 +00001913 {
David Turnerf0df85b2000-06-22 00:17:42 +00001914 FT_Error error = FT_Err_Ok;
1915 FT_Driver driver;
1916 FT_Memory memory;
1917 FT_Driver_Class* clazz;
1918 FT_Size_Metrics* metrics = &face->size->metrics;
David Turnerd2b1f351999-12-16 23:11:37 +00001919
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001920
David Turnerf0df85b2000-06-22 00:17:42 +00001921 if ( !face || !face->size || !face->driver )
David Turnerd2b1f351999-12-16 23:11:37 +00001922 return FT_Err_Invalid_Face_Handle;
1923
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001924 driver = face->driver;
David Turnerf0df85b2000-06-22 00:17:42 +00001925 clazz = driver->clazz;
1926 memory = driver->root.memory;
David Turnerd2b1f351999-12-16 23:11:37 +00001927
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001928 /* default processing -- this can be overridden by the driver */
1929 if ( pixel_width == 0 )
David Turner11187202000-05-26 17:13:23 +00001930 pixel_width = pixel_height;
David Turnerf0df85b2000-06-22 00:17:42 +00001931
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001932 else if ( pixel_height == 0 )
David Turner11187202000-05-26 17:13:23 +00001933 pixel_height = pixel_width;
Werner Lembergeb81e372000-06-03 06:03:11 +00001934
David Turnerd42c68e2000-01-27 13:56:02 +00001935 if ( pixel_width < 1 ) pixel_width = 1;
1936 if ( pixel_height < 1 ) pixel_height = 1;
David Turnerd2b1f351999-12-16 23:11:37 +00001937
David Turnerd42c68e2000-01-27 13:56:02 +00001938 metrics->x_ppem = pixel_width;
1939 metrics->y_ppem = pixel_height;
1940
1941 if ( face->face_flags & FT_FACE_FLAG_SCALABLE )
1942 {
1943 metrics->x_scale = FT_DivFix( metrics->x_ppem << 6,
1944 face->units_per_EM );
1945
1946 metrics->y_scale = FT_DivFix( metrics->y_ppem << 6,
1947 face->units_per_EM );
1948 }
1949
David Turnerf0df85b2000-06-22 00:17:42 +00001950 ft_recompute_scaled_metrics( face, metrics );
David Turnerd2b1f351999-12-16 23:11:37 +00001951
Werner Lemberga929ba92000-06-25 06:47:11 +00001952 if ( clazz->set_pixel_sizes )
David Turnerf0df85b2000-06-22 00:17:42 +00001953 error = clazz->set_pixel_sizes( face->size,
1954 pixel_width,
1955 pixel_height );
David Turnerd2b1f351999-12-16 23:11:37 +00001956 return error;
1957 }
1958
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001959
David Turnerd2b1f351999-12-16 23:11:37 +00001960 /*************************************************************************/
1961 /* */
1962 /* <Function> */
1963 /* FT_Get_Kerning */
1964 /* */
1965 /* <Description> */
1966 /* Returns the kerning vector between two glyphs of a same face. */
1967 /* */
1968 /* <Input> */
1969 /* face :: A handle to a source face object. */
1970 /* */
1971 /* left_glyph :: The index of the left glyph in the kern pair. */
1972 /* */
1973 /* right_glyph :: The index of the right glyph in the kern pair. */
1974 /* */
1975 /* <Output> */
1976 /* kerning :: The kerning vector. This is in font units for */
1977 /* scalable formats, and in pixels for fixed-sizes */
1978 /* formats. */
1979 /* */
1980 /* <Return> */
1981 /* FreeType error code. 0 means success. */
1982 /* */
1983 /* <Note> */
1984 /* Only horizontal layouts (left-to-right & right-to-left) are */
1985 /* supported by this method. Other layouts, or more sophisticated */
1986 /* kernings, are out of the scope of this API function -- they can be */
1987 /* implemented through format-specific interfaces. */
1988 /* */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001989 FT_EXPORT_FUNC( FT_Error ) FT_Get_Kerning( FT_Face face,
1990 FT_UInt left_glyph,
1991 FT_UInt right_glyph,
1992 FT_Vector* kerning )
David Turnerd2b1f351999-12-16 23:11:37 +00001993 {
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001994 FT_Error error = FT_Err_Ok;
David Turnerd2b1f351999-12-16 23:11:37 +00001995 FT_Driver driver;
1996 FT_Memory memory;
1997
1998
1999 if ( !face )
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00002000 return FT_Err_Invalid_Face_Handle;
2001
2002 if ( !kerning )
2003 return FT_Err_Invalid_Argument;
David Turnerd2b1f351999-12-16 23:11:37 +00002004
2005 driver = face->driver;
David Turnerf0df85b2000-06-22 00:17:42 +00002006 memory = driver->root.memory;
David Turnerd2b1f351999-12-16 23:11:37 +00002007
David Turnerf0df85b2000-06-22 00:17:42 +00002008 if ( driver->clazz->get_kerning )
David Turnerd2b1f351999-12-16 23:11:37 +00002009 {
David Turnerf0df85b2000-06-22 00:17:42 +00002010 error = driver->clazz->get_kerning( face,
Werner Lemberga929ba92000-06-25 06:47:11 +00002011 left_glyph,
2012 right_glyph,
2013 kerning );
David Turnerd2b1f351999-12-16 23:11:37 +00002014 }
2015 else
2016 {
2017 kerning->x = 0;
2018 kerning->y = 0;
David Turnerd2b1f351999-12-16 23:11:37 +00002019 }
2020
David Turnerd2b1f351999-12-16 23:11:37 +00002021 return error;
2022 }
2023
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00002024
David Turner0a29c692000-05-12 17:09:38 +00002025 /*************************************************************************/
2026 /* */
2027 /* <Function> */
2028 /* FT_Select_Charmap */
2029 /* */
2030 /* <Description> */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00002031 /* Selects a given charmap by its encoding tag (as listed in */
2032 /* `freetype.h'). */
David Turner0a29c692000-05-12 17:09:38 +00002033 /* */
2034 /* <Input> */
2035 /* face :: A handle to the source face object. */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00002036 /* */
2037 /* encoding :: A handle to the selected charmap. */
David Turner0a29c692000-05-12 17:09:38 +00002038 /* */
2039 /* <Return> */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00002040 /* FreeType error code. 0 means success. */
David Turner0a29c692000-05-12 17:09:38 +00002041 /* */
2042 /* <Note> */
2043 /* This function will return an error if no charmap in the face */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00002044 /* corresponds to the encoding queried here. */
David Turner0a29c692000-05-12 17:09:38 +00002045 /* */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00002046 FT_EXPORT_FUNC( FT_Error ) FT_Select_Charmap( FT_Face face,
2047 FT_Encoding encoding )
David Turner0a29c692000-05-12 17:09:38 +00002048 {
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00002049 FT_CharMap* cur;
2050 FT_CharMap* limit;
David Turnere49ab252000-05-16 23:44:38 +00002051
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00002052
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00002053 if ( !face )
2054 return FT_Err_Invalid_Face_Handle;
2055
2056 cur = face->charmaps;
2057 if ( !cur )
2058 return FT_Err_Invalid_CharMap_Handle;
2059
2060 limit = cur + face->num_charmaps;
2061
David Turner0a29c692000-05-12 17:09:38 +00002062 for ( ; cur < limit; cur++ )
2063 {
2064 if ( cur[0]->encoding == encoding )
2065 {
2066 face->charmap = cur[0];
2067 return 0;
2068 }
2069 }
2070 return FT_Err_Invalid_Argument;
2071 }
2072
2073
2074 /*************************************************************************/
2075 /* */
2076 /* <Function> */
2077 /* FT_Set_Charmap */
2078 /* */
2079 /* <Description> */
2080 /* Selects a given charmap for character code to glyph index */
2081 /* decoding. */
2082 /* */
2083 /* <Input> */
2084 /* face :: A handle to the source face object. */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00002085 /* charmap :: A handle to the selected charmap. */
David Turner0a29c692000-05-12 17:09:38 +00002086 /* */
2087 /* <Return> */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00002088 /* FreeType error code. 0 means success. */
David Turner0a29c692000-05-12 17:09:38 +00002089 /* */
2090 /* <Note> */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00002091 /* This function will return an error when the charmap is not part */
2092 /* of the face (i.e., if it is not listed in the face->charmaps[] */
David Turner0a29c692000-05-12 17:09:38 +00002093 /* table). */
2094 /* */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00002095 FT_EXPORT_FUNC( FT_Error ) FT_Set_Charmap( FT_Face face,
2096 FT_CharMap charmap )
David Turner0a29c692000-05-12 17:09:38 +00002097 {
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00002098 FT_CharMap* cur;
2099 FT_CharMap* limit;
David Turnere49ab252000-05-16 23:44:38 +00002100
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00002101
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00002102 if ( !face )
2103 return FT_Err_Invalid_Face_Handle;
2104
2105 cur = face->charmaps;
2106 if ( !cur )
2107 return FT_Err_Invalid_CharMap_Handle;
2108
2109 limit = cur + face->num_charmaps;
2110
David Turner0a29c692000-05-12 17:09:38 +00002111 for ( ; cur < limit; cur++ )
2112 {
2113 if ( cur[0] == charmap )
2114 {
2115 face->charmap = cur[0];
2116 return 0;
2117 }
2118 }
2119 return FT_Err_Invalid_Argument;
2120 }
David Turnerd2b1f351999-12-16 23:11:37 +00002121
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00002122
David Turnerd2b1f351999-12-16 23:11:37 +00002123 /*************************************************************************/
2124 /* */
2125 /* <Function> */
2126 /* FT_Get_Char_Index */
2127 /* */
2128 /* <Description> */
2129 /* Returns the glyph index of a given character code. This function */
2130 /* uses a charmap object to do the translation. */
2131 /* */
2132 /* <Input> */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00002133 /* face :: A handle to the source face object. */
David Turnerd2b1f351999-12-16 23:11:37 +00002134 /* charcode :: The character code. */
2135 /* */
2136 /* <Return> */
2137 /* The glyph index. 0 means `undefined character code'. */
2138 /* */
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00002139 FT_EXPORT_FUNC( FT_UInt ) FT_Get_Char_Index( FT_Face face,
2140 FT_ULong charcode )
David Turnerd2b1f351999-12-16 23:11:37 +00002141 {
2142 FT_UInt result;
2143 FT_Driver driver;
2144
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00002145
David Turnerd2b1f351999-12-16 23:11:37 +00002146 result = 0;
2147 if ( face && face->charmap )
2148 {
2149 driver = face->driver;
David Turnerf0df85b2000-06-22 00:17:42 +00002150 result = driver->clazz->get_char_index( face->charmap, charcode );
David Turnerd2b1f351999-12-16 23:11:37 +00002151 }
2152 return result;
2153 }
2154
David Turnerd2b1f351999-12-16 23:11:37 +00002155
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00002156 /*************************************************************************/
2157 /* */
2158 /* <Function> */
2159 /* FT_Get_Sfnt_Table */
2160 /* */
2161 /* <Description> */
2162 /* Returns a pointer to a given SFNT table within a face. */
2163 /* */
2164 /* <Input> */
2165 /* face :: A handle to the source face object. */
2166 /* tag :: An index of an SFNT table. */
2167 /* */
2168 /* <Return> */
2169 /* A type-less pointer to the table. This will be 0 in case of */
2170 /* error, or if the corresponding table was not found *OR* loaded */
2171 /* from the file. */
2172 /* */
2173 /* <Note> */
2174 /* The table is owned by the face object, and disappears with it. */
2175 /* */
2176 /* This function is only useful to access SFNT tables that are loaded */
2177 /* by the sfnt/truetype/opentype drivers. See the FT_Sfnt_Tag */
2178 /* enumeration in `tttables.h' for a list. */
2179 /* */
2180 /* You can load any table with a different function.. XXX */
2181 /* */
2182 FT_EXPORT_FUNC( void* ) FT_Get_Sfnt_Table( FT_Face face,
2183 FT_Sfnt_Tag tag )
David Turner99a4d932000-04-25 16:10:50 +00002184 {
2185 void* table = 0;
2186 FT_Get_Sfnt_Table_Func func;
2187 FT_Driver driver;
David Turnere49ab252000-05-16 23:44:38 +00002188
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00002189
2190 if ( !face || !FT_IS_SFNT( face ) )
David Turner99a4d932000-04-25 16:10:50 +00002191 goto Exit;
David Turnere49ab252000-05-16 23:44:38 +00002192
David Turner99a4d932000-04-25 16:10:50 +00002193 driver = face->driver;
David Turnerf0df85b2000-06-22 00:17:42 +00002194 func = (FT_Get_Sfnt_Table_Func)driver->root.clazz->get_interface(
Werner Lemberga929ba92000-06-25 06:47:11 +00002195 FT_MODULE( driver ), "get_sfnt" );
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00002196 if ( func )
2197 table = func( face, tag );
David Turnere49ab252000-05-16 23:44:38 +00002198
David Turner99a4d932000-04-25 16:10:50 +00002199 Exit:
2200 return table;
David Turnere49ab252000-05-16 23:44:38 +00002201 }
David Turner99a4d932000-04-25 16:10:50 +00002202
2203
David Turnerd2b1f351999-12-16 23:11:37 +00002204 /*************************************************************************/
David Turnerf0df85b2000-06-22 00:17:42 +00002205 /*************************************************************************/
2206 /*************************************************************************/
2207 /**** ****/
2208 /**** ****/
2209 /**** R E N D E R E R S ****/
2210 /**** ****/
2211 /**** ****/
2212 /*************************************************************************/
2213 /*************************************************************************/
2214 /*************************************************************************/
2215
2216 /* lookup a renderer by glyph format in the library's list */
David Turner74abee82000-06-27 23:31:53 +00002217 BASE_FUNC(FT_Renderer) FT_Lookup_Renderer( FT_Library library,
2218 FT_Glyph_Format format,
2219 FT_ListNode *node )
David Turnerf0df85b2000-06-22 00:17:42 +00002220 {
2221 FT_ListNode cur = library->renderers.head;
2222 FT_Renderer result = 0;
Werner Lemberga929ba92000-06-25 06:47:11 +00002223
David Turnerf0df85b2000-06-22 00:17:42 +00002224
David Turner74abee82000-06-27 23:31:53 +00002225 if (node)
2226 {
2227 if (*node)
2228 cur = (*node)->next;
David Turnerf0df85b2000-06-22 00:17:42 +00002229 *node = 0;
David Turner74abee82000-06-27 23:31:53 +00002230 }
David Turnerf0df85b2000-06-22 00:17:42 +00002231
Werner Lemberga929ba92000-06-25 06:47:11 +00002232 while ( cur )
David Turnerf0df85b2000-06-22 00:17:42 +00002233 {
Werner Lemberga929ba92000-06-25 06:47:11 +00002234 FT_Renderer renderer = FT_RENDERER( cur->data );
David Turnerf0df85b2000-06-22 00:17:42 +00002235
Werner Lemberga929ba92000-06-25 06:47:11 +00002236
2237 if ( renderer->glyph_format == format )
David Turnerf0df85b2000-06-22 00:17:42 +00002238 {
Werner Lemberga929ba92000-06-25 06:47:11 +00002239 if ( node )
David Turnerf0df85b2000-06-22 00:17:42 +00002240 *node = cur;
2241
2242 result = renderer;
2243 break;
2244 }
David Turner74abee82000-06-27 23:31:53 +00002245 cur = cur->next;
David Turnerf0df85b2000-06-22 00:17:42 +00002246 }
Werner Lemberga929ba92000-06-25 06:47:11 +00002247
David Turnerf0df85b2000-06-22 00:17:42 +00002248 return result;
2249 }
2250
2251
David Turner74abee82000-06-27 23:31:53 +00002252 static FT_Renderer ft_lookup_glyph_renderer( FT_GlyphSlot slot )
David Turnerf0df85b2000-06-22 00:17:42 +00002253 {
2254 FT_Face face = slot->face;
Werner Lemberga929ba92000-06-25 06:47:11 +00002255 FT_Library library = FT_FACE_LIBRARY( face );
David Turnerf0df85b2000-06-22 00:17:42 +00002256 FT_Renderer result = library->cur_renderer;
Werner Lemberga929ba92000-06-25 06:47:11 +00002257
David Turnerf0df85b2000-06-22 00:17:42 +00002258
Werner Lemberga929ba92000-06-25 06:47:11 +00002259 if ( !result || result->glyph_format != slot->format )
David Turner81bb4ad2000-06-28 04:19:49 +00002260 result = FT_Lookup_Renderer( library, slot->format, 0 );
David Turnerf0df85b2000-06-22 00:17:42 +00002261
2262 return result;
2263 }
2264
2265
2266 static void ft_set_current_renderer( FT_Library library )
2267 {
2268 FT_Renderer renderer;
2269
David Turner74abee82000-06-27 23:31:53 +00002270 renderer = FT_Lookup_Renderer( library, ft_glyph_format_outline, 0 );
David Turnerf0df85b2000-06-22 00:17:42 +00002271 library->cur_renderer = renderer;
2272 }
2273
2274
2275 static FT_Error ft_add_renderer( FT_Module module )
2276 {
2277 FT_Library library = module->library;
2278 FT_Memory memory = library->memory;
2279 FT_Error error;
2280 FT_ListNode node;
2281
Werner Lemberga929ba92000-06-25 06:47:11 +00002282 if ( ALLOC( node, sizeof ( *node ) ) )
David Turnerf0df85b2000-06-22 00:17:42 +00002283 goto Exit;
2284
2285 {
Werner Lemberga929ba92000-06-25 06:47:11 +00002286 FT_Renderer render = FT_RENDERER( module );
David Turnerf0df85b2000-06-22 00:17:42 +00002287 FT_Renderer_Class* clazz = (FT_Renderer_Class*)module->clazz;
2288
Werner Lemberga929ba92000-06-25 06:47:11 +00002289
David Turnerf0df85b2000-06-22 00:17:42 +00002290 render->clazz = clazz;
2291 render->glyph_format = clazz->glyph_format;
2292
2293 /* allocate raster object if needed */
2294 if ( clazz->glyph_format == ft_glyph_format_outline &&
2295 clazz->raster_class->raster_new )
2296 {
2297 error = clazz->raster_class->raster_new( memory, &render->raster );
Werner Lemberga929ba92000-06-25 06:47:11 +00002298 if ( error )
2299 goto Fail;
David Turnerf0df85b2000-06-22 00:17:42 +00002300
2301 render->raster_render = clazz->raster_class->raster_render;
2302 render->render = clazz->render_glyph;
2303 }
2304
2305 /* add to list */
2306 node->data = module;
2307 FT_List_Add( &library->renderers, node );
2308
2309 ft_set_current_renderer( library );
2310 }
2311
2312 Fail:
Werner Lemberga929ba92000-06-25 06:47:11 +00002313 if ( error )
2314 FREE( node );
David Turnerf0df85b2000-06-22 00:17:42 +00002315
2316 Exit:
2317 return error;
2318 }
2319
2320
2321 static void ft_remove_renderer( FT_Module module )
2322 {
2323 FT_Library library = module->library;
2324 FT_Memory memory = library->memory;
2325 FT_ListNode node;
2326
Werner Lemberga929ba92000-06-25 06:47:11 +00002327
David Turnerf0df85b2000-06-22 00:17:42 +00002328 node = FT_List_Find( &library->renderers, module );
Werner Lemberga929ba92000-06-25 06:47:11 +00002329 if ( node )
David Turnerf0df85b2000-06-22 00:17:42 +00002330 {
Werner Lemberga929ba92000-06-25 06:47:11 +00002331 FT_Renderer render = FT_RENDERER( module );
David Turnerf0df85b2000-06-22 00:17:42 +00002332
Werner Lemberga929ba92000-06-25 06:47:11 +00002333
David Turnerf0df85b2000-06-22 00:17:42 +00002334 /* release raster object, if any */
Werner Lemberga929ba92000-06-25 06:47:11 +00002335 if ( render->raster )
David Turnerf0df85b2000-06-22 00:17:42 +00002336 render->clazz->raster_class->raster_done( render->raster );
2337
2338 /* remove from list */
2339 FT_List_Remove( &library->renderers, node );
2340 FREE( node );
2341
2342 ft_set_current_renderer( library );
2343 }
2344 }
2345
2346
Werner Lemberga929ba92000-06-25 06:47:11 +00002347 /*************************************************************************/
2348 /* */
2349 /* <Function> */
2350 /* FT_Get_Renderer */
2351 /* */
2352 /* <Description> */
2353 /* Retrieves the current renderer for a given glyph format. */
2354 /* */
2355 /* <Input> */
2356 /* library :: A handle to the library object. */
2357 /* */
2358 /* format :: The glyph format. */
2359 /* */
2360 /* <Return> */
2361 /* A renderer handle. 0 if none found. */
2362 /* */
2363 /* <Note> */
2364 /* An error will be returned if a module already exists by that name, */
2365 /* or if the module requires a version of FreeType that is too great. */
2366 /* */
2367 /* To add a new renderer, simply use FT_Add_Module(). To retrieve a */
2368 /* renderer by its name, use FT_Get_Module(). */
Werner Lembergdcd2e142000-06-25 07:43:15 +00002369 /* */
Werner Lemberga929ba92000-06-25 06:47:11 +00002370 FT_EXPORT_FUNC( FT_Renderer ) FT_Get_Renderer( FT_Library library,
2371 FT_Glyph_Format format )
David Turnerf0df85b2000-06-22 00:17:42 +00002372 {
David Turner74abee82000-06-27 23:31:53 +00002373 return FT_Lookup_Renderer( library, format, 0 );
David Turnerf0df85b2000-06-22 00:17:42 +00002374 }
2375
2376
Werner Lemberga929ba92000-06-25 06:47:11 +00002377 /*************************************************************************/
2378 /* */
2379 /* <Function> */
2380 /* FT_Set_Renderer */
2381 /* */
2382 /* <Description> */
2383 /* Sets the current renderer to use, and set additional mode. */
2384 /* */
2385 /* <Input> */
2386 /* library :: A handle to the library object. */
2387 /* */
2388 /* renderer :: A handle to the renderer object. */
2389 /* */
2390 /* num_params :: The number of additional parameters. */
2391 /* */
2392 /* params :: Additional parameters. */
2393 /* */
2394 /* <Return> */
2395 /* FreeType error code. 0 means success. */
2396 /* */
2397 /* <Note> */
2398 /* In case of success, the renderer will be used to convert glyph */
2399 /* images in the renderer's known format into bitmaps. */
2400 /* */
2401 /* This doesn't change the current renderer for other formats. */
2402 /* */
2403 FT_EXPORT_DEF( FT_Error ) FT_Set_Renderer( FT_Library library,
2404 FT_Renderer renderer,
2405 FT_UInt num_params,
2406 FT_Parameter* parameters )
David Turnerf0df85b2000-06-22 00:17:42 +00002407 {
2408 FT_ListNode node;
2409 FT_Error error = FT_Err_Ok;
2410
Werner Lemberga929ba92000-06-25 06:47:11 +00002411
David Turnerf0df85b2000-06-22 00:17:42 +00002412 node = FT_List_Find( &library->renderers, renderer );
Werner Lemberga929ba92000-06-25 06:47:11 +00002413 if ( !node )
David Turnerf0df85b2000-06-22 00:17:42 +00002414 {
2415 error = FT_Err_Invalid_Argument;
2416 goto Exit;
2417 }
David Turner74abee82000-06-27 23:31:53 +00002418
David Turnerf0df85b2000-06-22 00:17:42 +00002419 FT_List_Up( &library->renderers, node );
2420
Werner Lemberga929ba92000-06-25 06:47:11 +00002421 if ( renderer->glyph_format == ft_glyph_format_outline )
David Turnerf0df85b2000-06-22 00:17:42 +00002422 library->cur_renderer = renderer;
2423
Werner Lemberga929ba92000-06-25 06:47:11 +00002424 if ( num_params > 0 )
David Turnerf0df85b2000-06-22 00:17:42 +00002425 {
2426 FTRenderer_setMode set_mode = renderer->clazz->set_mode;
2427
Werner Lemberga929ba92000-06-25 06:47:11 +00002428
David Turnerf0df85b2000-06-22 00:17:42 +00002429 for ( ; num_params > 0; num_params-- )
2430 {
2431 error = set_mode( renderer, parameters->tag, parameters->data );
Werner Lemberga929ba92000-06-25 06:47:11 +00002432 if ( error )
David Turnerf0df85b2000-06-22 00:17:42 +00002433 break;
2434 }
2435 }
2436
2437 Exit:
2438 return error;
2439 }
2440
2441
David Turner74abee82000-06-27 23:31:53 +00002442 /*************************************************************************
2443 *
2444 * <Function>
2445 * FT_Render_Glyph
2446 *
2447 * <Description>
2448 * Converts a given glyph image to a bitmap. It does so by inspecting
2449 * the glyph image format, find the relevant renderer, and invoke it
2450 *
2451 * <Input>
2452 * slot :: handle to the glyph slot containing the image to
2453 * convert
2454 *
2455 * render_mode :: a set of bit flags indicating which kind of bitmap
2456 * to render. For now, only 'ft_render_mode_anti_alias'
2457 * is supported by the available renderers, but others
2458 * could appear later (e.g. LCD or TV optimised)
2459 *
2460 * <Return>
2461 * Error code. 0 means success.
2462 *
2463 * <Note>
2464 * in case of success, the renderer will be used to convert glyph
2465 * images in the renderer's known format into bitmaps.
2466 *
2467 * This doesn't change the current renderer for other formats..
2468 *
2469 * The slot's native image should be considered lost after the
2470 * conversion..
2471 *
2472 *************************************************************************/
2473
2474 LOCAL_FUNC
2475 FT_Error FT_Render_Glyph_Internal( FT_Library library,
2476 FT_GlyphSlot slot,
2477 FT_UInt render_mode )
David Turnerf0df85b2000-06-22 00:17:42 +00002478 {
2479 FT_Error error = FT_Err_Ok;
2480 FT_Renderer renderer;
Werner Lemberga929ba92000-06-25 06:47:11 +00002481
David Turnerf0df85b2000-06-22 00:17:42 +00002482
David Turner74abee82000-06-27 23:31:53 +00002483 /* if it's already a bitmap, no need to do anything */
2484 switch (slot->format)
David Turnerf0df85b2000-06-22 00:17:42 +00002485 {
David Turner74abee82000-06-27 23:31:53 +00002486 case ft_glyph_format_bitmap: /* already a bitmap, don't do anything */
Werner Lemberga929ba92000-06-25 06:47:11 +00002487 break;
David Turner74abee82000-06-27 23:31:53 +00002488
Werner Lemberga929ba92000-06-25 06:47:11 +00002489 default:
David Turner74abee82000-06-27 23:31:53 +00002490 {
2491 FT_ListNode node = 0;
2492 FT_Bool update = 0;
2493
Werner Lemberga929ba92000-06-25 06:47:11 +00002494 /* small shortcut for the very common case */
David Turner74abee82000-06-27 23:31:53 +00002495 if (slot->format == ft_glyph_format_outline)
2496 {
Werner Lemberga929ba92000-06-25 06:47:11 +00002497 renderer = library->cur_renderer;
David Turner74abee82000-06-27 23:31:53 +00002498 node = library->renderers.head;
2499 }
Werner Lemberga929ba92000-06-25 06:47:11 +00002500 else
David Turner74abee82000-06-27 23:31:53 +00002501 renderer = FT_Lookup_Renderer( library, slot->format, &node );
2502
Werner Lemberga929ba92000-06-25 06:47:11 +00002503 error = FT_Err_Unimplemented_Feature;
David Turner74abee82000-06-27 23:31:53 +00002504 while (renderer)
2505 {
2506 error = renderer->render( renderer, slot, render_mode, 0 );
2507 if (!error || error != FT_Err_Cannot_Render_Glyph) break;
2508
2509 /* FT_Err_Cannot_Render_Glyph is returned when the render mode */
2510 /* is unsupported by the current renderer for this glyph image */
2511 /* format.. */
2512
2513 /* now, look for another renderer that supports the same */
2514 /* format.. */
2515 renderer = FT_Lookup_Renderer( library, slot->format, &node );
2516 update = 1;
2517 }
2518
2519 /* if we changed the current renderer for the glyph image format */
2520 /* we need to select it as the next current one.. */
2521 if (!error && update && renderer)
2522 FT_Set_Renderer( library, renderer, 0, 0 );
David Turnerf0df85b2000-06-22 00:17:42 +00002523 }
2524 }
David Turnerf0df85b2000-06-22 00:17:42 +00002525
2526 return error;
2527 }
Werner Lemberga929ba92000-06-25 06:47:11 +00002528
David Turner74abee82000-06-27 23:31:53 +00002529
2530
2531 FT_EXPORT_FUNC(FT_Error) FT_Render_Glyph( FT_GlyphSlot slot,
2532 FT_UInt render_mode )
2533 {
2534 FT_Library library;
2535
2536 if (!slot)
2537 return FT_Err_Invalid_Argument;
2538
2539 library = FT_FACE_LIBRARY(slot->face);
2540 return FT_Render_Glyph_Internal( library, slot, render_mode );
2541 }
2542
David Turnerf0df85b2000-06-22 00:17:42 +00002543
2544 /*************************************************************************/
2545 /*************************************************************************/
2546 /*************************************************************************/
2547 /**** ****/
2548 /**** ****/
2549 /**** M O D U L E S ****/
2550 /**** ****/
2551 /**** ****/
2552 /*************************************************************************/
2553 /*************************************************************************/
2554 /*************************************************************************/
2555
Werner Lemberga929ba92000-06-25 06:47:11 +00002556
David Turnerf0df85b2000-06-22 00:17:42 +00002557 /*************************************************************************/
2558 /* */
2559 /* <Function> */
2560 /* Destroy_Module */
2561 /* */
2562 /* <Description> */
2563 /* Destroys a given module object. For drivers, this also destroys */
Werner Lemberga929ba92000-06-25 06:47:11 +00002564 /* all child faces. */
David Turnerf0df85b2000-06-22 00:17:42 +00002565 /* */
2566 /* <InOut> */
2567 /* module :: A handle to the target driver object. */
2568 /* */
2569 /* <Note> */
2570 /* The driver _must_ be LOCKED! */
2571 /* */
2572 static
2573 void Destroy_Module( FT_Module module )
2574 {
2575 FT_Memory memory = module->memory;
2576 FT_Module_Class* clazz = module->clazz;
2577
Werner Lemberga929ba92000-06-25 06:47:11 +00002578
David Turnerf0df85b2000-06-22 00:17:42 +00002579 /* finalize client-data - before anything else */
2580 if ( module->generic.finalizer )
2581 module->generic.finalizer( module );
2582
2583 /* if the module is a renderer */
Werner Lemberga929ba92000-06-25 06:47:11 +00002584 if ( FT_MODULE_IS_RENDERER( module ) )
2585 ft_remove_renderer( module );
David Turnerf0df85b2000-06-22 00:17:42 +00002586
2587 /* if the module is a font driver, add some steps */
Werner Lemberga929ba92000-06-25 06:47:11 +00002588 if ( FT_MODULE_IS_DRIVER( module ) )
2589 Destroy_Driver( FT_DRIVER( module ) );
David Turnerf0df85b2000-06-22 00:17:42 +00002590
2591 /* finalize the module object */
Werner Lemberga929ba92000-06-25 06:47:11 +00002592 if ( clazz->module_done )
2593 clazz->module_done( module );
David Turnerf0df85b2000-06-22 00:17:42 +00002594
2595 /* discard it */
2596 FREE( module );
2597 }
2598
David Turnerf0df85b2000-06-22 00:17:42 +00002599
Werner Lemberga929ba92000-06-25 06:47:11 +00002600 /*************************************************************************/
2601 /* */
2602 /* <Function> */
2603 /* FT_Add_Module */
2604 /* */
2605 /* <Description> */
2606 /* Adds a new module to a given library instance. */
2607 /* */
2608 /* <Input> */
2609 /* library :: A handle to the library object. */
2610 /* clazz :: A pointer to class descriptor for the module. */
2611 /* */
2612 /* <Return> */
2613 /* FreeType error code. 0 means success. */
2614 /* */
2615 /* <Note> */
2616 /* An error will be returned if a module already exists by that name, */
2617 /* or if the module requires a version of FreeType that is too great. */
2618 /* */
2619 FT_EXPORT_FUNC( FT_Error ) FT_Add_Module( FT_Library library,
2620 const FT_Module_Class* clazz )
David Turnerf0df85b2000-06-22 00:17:42 +00002621 {
2622 FT_Error error;
2623 FT_Memory memory;
2624 FT_Module module;
2625 FT_UInt nn;
2626
David Turnerf0df85b2000-06-22 00:17:42 +00002627
Werner Lembergdcd2e142000-06-25 07:43:15 +00002628#define FREETYPE_VER_FIXED ( ( (FT_Long)FREETYPE_MAJOR << 16 ) | \
Werner Lemberga929ba92000-06-25 06:47:11 +00002629 FREETYPE_MINOR )
2630
2631 if ( !library || !clazz )
David Turnerf0df85b2000-06-22 00:17:42 +00002632 return FT_Err_Invalid_Argument;
2633
2634 /* check freetype version */
2635 if ( clazz->module_requires > FREETYPE_VER_FIXED )
2636 return FT_Err_Invalid_Version;
2637
2638 /* look for a module with the same name in the library's table */
2639 for ( nn = 0; nn < library->num_modules; nn++ )
2640 {
2641 module = library->modules[nn];
2642 if ( strcmp( module->clazz->module_name, clazz->module_name ) == 0 )
2643 {
2644 /* this installed module has the same name, compare their versions */
2645 if ( clazz->module_version <= module->clazz->module_version )
2646 return FT_Err_Lower_Module_Version;
2647
2648 /* remove the module from our list, then exit the loop to replace */
2649 /* it by our new version.. */
2650 FT_Remove_Module( library, module );
2651 break;
2652 }
2653 }
2654
2655 memory = library->memory;
2656 error = FT_Err_Ok;
2657
2658 if ( library->num_modules >= FT_MAX_MODULES )
2659 {
2660 error = FT_Err_Too_Many_Drivers;
2661 goto Exit;
2662 }
2663
2664 /* allocate module object */
Werner Lemberga929ba92000-06-25 06:47:11 +00002665 if ( ALLOC( module,clazz->module_size ) )
David Turnerf0df85b2000-06-22 00:17:42 +00002666 goto Exit;
2667
2668 /* base initialisation */
2669 module->library = library;
2670 module->memory = memory;
2671 module->clazz = (FT_Module_Class*)clazz;
2672
2673 /* if the module is a renderer - this must be performed before */
Werner Lemberga929ba92000-06-25 06:47:11 +00002674 /* the normal module initialization. */
2675 if ( FT_MODULE_IS_RENDERER( module ) )
David Turnerf0df85b2000-06-22 00:17:42 +00002676 {
2677 /* add to the renderers list */
Werner Lemberga929ba92000-06-25 06:47:11 +00002678 error = ft_add_renderer( module );
2679 if ( error )
2680 goto Fail;
David Turnerf0df85b2000-06-22 00:17:42 +00002681 }
2682
2683 /* if the module is a font driver */
Werner Lemberga929ba92000-06-25 06:47:11 +00002684 if ( FT_MODULE_IS_DRIVER( module ) )
David Turnerf0df85b2000-06-22 00:17:42 +00002685 {
2686 /* allocate glyph loader if needed */
Werner Lemberga929ba92000-06-25 06:47:11 +00002687 FT_Driver driver = FT_DRIVER( module );
2688
David Turnerf0df85b2000-06-22 00:17:42 +00002689
2690 driver->clazz = (FT_Driver_Class*)module->clazz;
Werner Lemberga929ba92000-06-25 06:47:11 +00002691 if ( FT_DRIVER_USES_OUTLINES( driver ) )
David Turnerf0df85b2000-06-22 00:17:42 +00002692 {
2693 error = FT_GlyphLoader_New( memory, &driver->glyph_loader );
Werner Lemberga929ba92000-06-25 06:47:11 +00002694 if ( error )
2695 goto Fail;
David Turnerf0df85b2000-06-22 00:17:42 +00002696 }
2697 }
2698
Werner Lemberga929ba92000-06-25 06:47:11 +00002699 if ( clazz->module_init )
David Turnerf0df85b2000-06-22 00:17:42 +00002700 {
Werner Lemberga929ba92000-06-25 06:47:11 +00002701 error = clazz->module_init( module );
2702 if ( error )
2703 goto Fail;
David Turnerf0df85b2000-06-22 00:17:42 +00002704 }
2705
2706 /* add module to the library's table */
Werner Lemberga929ba92000-06-25 06:47:11 +00002707 library->modules[library->num_modules++] = module;
David Turnerf0df85b2000-06-22 00:17:42 +00002708
David Turnerf0df85b2000-06-22 00:17:42 +00002709 Exit:
2710 return error;
2711
2712 Fail:
Werner Lemberga929ba92000-06-25 06:47:11 +00002713 if ( FT_MODULE_IS_DRIVER( module ) )
David Turnerf0df85b2000-06-22 00:17:42 +00002714 {
Werner Lemberga929ba92000-06-25 06:47:11 +00002715 FT_Driver driver = FT_DRIVER( module );
David Turnerf0df85b2000-06-22 00:17:42 +00002716
Werner Lemberga929ba92000-06-25 06:47:11 +00002717
2718 if ( FT_DRIVER_USES_OUTLINES( driver ) )
David Turnerf0df85b2000-06-22 00:17:42 +00002719 FT_GlyphLoader_Done( driver->glyph_loader );
2720 }
2721
Werner Lemberga929ba92000-06-25 06:47:11 +00002722 if ( FT_MODULE_IS_RENDERER( module ) )
David Turnerf0df85b2000-06-22 00:17:42 +00002723 {
Werner Lemberga929ba92000-06-25 06:47:11 +00002724 FT_Renderer renderer = FT_RENDERER( module );
2725
2726
2727 if ( renderer->raster )
David Turnerf0df85b2000-06-22 00:17:42 +00002728 renderer->clazz->raster_class->raster_done( renderer->raster );
2729 }
Werner Lemberga929ba92000-06-25 06:47:11 +00002730
2731 FREE( module );
David Turnerf0df85b2000-06-22 00:17:42 +00002732 goto Exit;
2733 }
2734
David Turnerf0df85b2000-06-22 00:17:42 +00002735
Werner Lemberga929ba92000-06-25 06:47:11 +00002736 /*************************************************************************/
2737 /* */
2738 /* <Function> */
2739 /* FT_Get_Module */
2740 /* */
2741 /* <Description> */
2742 /* Finds a module by its name. */
2743 /* */
2744 /* <Input> */
2745 /* library :: A handle to the library object. */
2746 /* */
2747 /* module_name :: The module's name (as an ASCII string). */
2748 /* */
2749 /* <Return> */
2750 /* A module handle. 0 if none was found. */
2751 /* */
2752 /* <Note> */
2753 /* You should better be familiar with FreeType internals to know */
2754 /* which module to look for :-) */
2755 /* */
2756 FT_EXPORT_FUNC( FT_Module ) FT_Get_Module( FT_Library library,
2757 const char* module_name )
David Turnerf0df85b2000-06-22 00:17:42 +00002758 {
2759 FT_Module result = 0;
2760 FT_Module* cur = library->modules;
2761 FT_Module* limit = cur + library->num_modules;
2762
Werner Lemberga929ba92000-06-25 06:47:11 +00002763
David Turnerf0df85b2000-06-22 00:17:42 +00002764 for ( ; cur < limit; cur++ )
2765 if ( strcmp( cur[0]->clazz->module_name, module_name ) == 0 )
2766 {
2767 result = cur[0];
2768 break;
2769 }
2770
2771 return result;
2772 }
2773
Werner Lemberga929ba92000-06-25 06:47:11 +00002774
2775 /*************************************************************************/
2776 /* */
2777 /* <Function> */
2778 /* FT_Get_Module_Interface */
2779 /* */
2780 /* <Description> */
2781 /* Finds a module and returns its specific interface as a typeless */
2782 /* pointer. */
2783 /* */
2784 /* <Input> */
2785 /* library :: A handle to the library object. */
2786 /* */
2787 /* module_name :: The module's name (as an ASCII string). */
2788 /* */
2789 /* <Return> */
2790 /* A module-specific interface if available, 0 otherwise. */
2791 /* */
2792 /* <Note> */
2793 /* You should better be familiar with FreeType internals to know */
2794 /* which module to look for, and what its interface is :-) */
2795 /* */
2796 FT_EXPORT_FUNC(const void*) FT_Get_Module_Interface(
2797 FT_Library library,
2798 const char* mod_name )
David Turnerf0df85b2000-06-22 00:17:42 +00002799 {
2800 FT_Module module;
2801
Werner Lemberga929ba92000-06-25 06:47:11 +00002802
David Turnerf0df85b2000-06-22 00:17:42 +00002803 module = FT_Get_Module( library, mod_name );
Werner Lemberga929ba92000-06-25 06:47:11 +00002804
David Turnerf0df85b2000-06-22 00:17:42 +00002805 return module ? module->clazz->module_interface : 0;
2806 }
2807
2808
Werner Lemberga929ba92000-06-25 06:47:11 +00002809 /*************************************************************************/
2810 /* */
2811 /* <Function> */
2812 /* FT_Remove_Module */
2813 /* */
2814 /* <Description> */
2815 /* Removes a given module from a library instance. */
2816 /* */
2817 /* <Input> */
2818 /* library :: A handle to a library object. */
2819 /* */
2820 /* module :: A handle to a module object. */
2821 /* */
2822 /* <Return> */
2823 /* FreeType error code. 0 means success. */
2824 /* */
2825 /* <Note> */
2826 /* The module object is destroyed by the function in case of success. */
Werner Lembergdcd2e142000-06-25 07:43:15 +00002827 /* */
Werner Lemberga929ba92000-06-25 06:47:11 +00002828 FT_EXPORT_FUNC( FT_Error ) FT_Remove_Module( FT_Library library,
2829 FT_Module module )
David Turnerf0df85b2000-06-22 00:17:42 +00002830 {
2831 /* try to find the module from the table, then remove it from there */
Werner Lemberga929ba92000-06-25 06:47:11 +00002832 if ( library && module )
David Turnerf0df85b2000-06-22 00:17:42 +00002833 {
2834 FT_Module* cur = library->modules;
2835 FT_Module* limit = cur + library->num_modules;
2836
Werner Lemberga929ba92000-06-25 06:47:11 +00002837
David Turnerf0df85b2000-06-22 00:17:42 +00002838 for ( ; cur < limit; cur++ )
2839 {
2840 if (cur[0] == module)
2841 {
2842 /* remove it from the table */
2843 library->num_modules--;
2844 limit--;
Werner Lemberga929ba92000-06-25 06:47:11 +00002845 while ( cur < limit )
David Turnerf0df85b2000-06-22 00:17:42 +00002846 {
2847 cur[0] = cur[1];
2848 cur++;
2849 }
2850 limit[0] = 0;
2851
2852 /* destroy the module */
Werner Lemberga929ba92000-06-25 06:47:11 +00002853 Destroy_Module( module );
David Turnerf0df85b2000-06-22 00:17:42 +00002854
2855 return FT_Err_Ok;
2856 }
2857 }
2858 }
2859 return FT_Err_Invalid_Handle;
2860 }
2861
2862
David Turnerf0df85b2000-06-22 00:17:42 +00002863 /*************************************************************************/
2864 /*************************************************************************/
2865 /*************************************************************************/
2866 /**** ****/
2867 /**** ****/
2868 /**** L I B R A R Y ****/
2869 /**** ****/
2870 /**** ****/
2871 /*************************************************************************/
2872 /*************************************************************************/
2873 /*************************************************************************/
2874
Werner Lemberga929ba92000-06-25 06:47:11 +00002875
David Turnerf0df85b2000-06-22 00:17:42 +00002876 /*************************************************************************/
2877 /* */
2878 /* <Function> */
2879 /* FT_New_Library */
2880 /* */
2881 /* <Description> */
2882 /* This function is used to create a new FreeType library instance */
2883 /* from a given memory object. It is thus possible to use libraries */
2884 /* with distinct memory allocators within the same program. */
2885 /* */
2886 /* <Input> */
2887 /* memory :: A handle to the original memory object. */
2888 /* */
2889 /* <Output> */
2890 /* alibrary :: A pointer to handle of a new library object. */
2891 /* */
2892 /* <Return> */
2893 /* FreeType error code. 0 means success. */
2894 /* */
2895 FT_EXPORT_FUNC( FT_Error ) FT_New_Library( FT_Memory memory,
2896 FT_Library* alibrary )
2897 {
2898 FT_Library library = 0;
2899 FT_Error error;
2900
2901
2902 if ( !memory )
2903 return FT_Err_Invalid_Argument;
2904
2905 /* first of all, allocate the library object */
2906 if ( ALLOC( library, sizeof ( *library ) ) )
2907 return error;
2908
2909 library->memory = memory;
2910
2911 /* allocate the render pool */
2912 library->raster_pool_size = FT_RENDER_POOL_SIZE;
2913 if ( ALLOC( library->raster_pool, FT_RENDER_POOL_SIZE ) )
2914 goto Fail;
2915
2916 /* That's ok now */
2917 *alibrary = library;
2918
2919 return FT_Err_Ok;
2920
2921 Fail:
2922 FREE( library );
2923 return error;
2924 }
2925
2926
2927 /*************************************************************************/
2928 /* */
2929 /* <Function> */
2930 /* FT_Done_Library */
2931 /* */
2932 /* <Description> */
2933 /* Discards a given library object. This closes all drivers and */
2934 /* discards all resource objects. */
2935 /* */
2936 /* <Input> */
2937 /* library :: A handle to the target library. */
2938 /* */
2939 /* <Return> */
2940 /* FreeType error code. 0 means success. */
2941 /* */
2942 FT_EXPORT_FUNC( FT_Error ) FT_Done_Library( FT_Library library )
2943 {
2944 FT_Memory memory;
David Turner74abee82000-06-27 23:31:53 +00002945 FT_UInt n;
David Turnerf0df85b2000-06-22 00:17:42 +00002946
2947
2948 if ( !library )
2949 return FT_Err_Invalid_Library_Handle;
2950
2951 memory = library->memory;
2952
2953 /* Discard client-data */
2954 if ( library->generic.finalizer )
2955 library->generic.finalizer( library );
2956
2957 /* Close all modules in the library */
2958 for ( n = 0; n < library->num_modules; n++ )
2959 {
2960 FT_Module module = library->modules[n];
2961
Werner Lemberga929ba92000-06-25 06:47:11 +00002962
David Turnerf0df85b2000-06-22 00:17:42 +00002963 if ( module )
2964 {
2965 Destroy_Module( module );
2966 library->modules[n] = 0;
2967 }
2968 }
2969
2970 /* Destroy raster objects */
2971 FREE( library->raster_pool );
2972 library->raster_pool_size = 0;
2973
2974 FREE( library );
2975 return FT_Err_Ok;
2976 }
2977
2978
2979 /*************************************************************************/
2980 /* */
2981 /* <Function> */
2982 /* FT_Set_Debug_Hook */
2983 /* */
2984 /* <Description> */
Werner Lemberga929ba92000-06-25 06:47:11 +00002985 /* Sets a debug hook function for debugging the interpreter of a font */
2986 /* format. */
David Turnerf0df85b2000-06-22 00:17:42 +00002987 /* */
2988 /* <Input> */
2989 /* library :: A handle to the library object. */
2990 /* */
2991 /* hook_index :: The index of the debug hook. You should use the */
2992 /* values defined in ftobjs.h, e.g. */
2993 /* FT_DEBUG_HOOK_TRUETYPE */
2994 /* */
2995 /* debug_hook :: The function used to debug the interpreter. */
2996 /* */
2997 /* <Note> */
2998 /* Currently, four debug hook slots are available, but only two (for */
2999 /* the TrueType and the Type 1 interpreter) are defined. */
3000 /* */
3001 FT_EXPORT_FUNC( void ) FT_Set_Debug_Hook( FT_Library library,
3002 FT_UInt hook_index,
3003 FT_DebugHook_Func debug_hook )
3004 {
3005 if ( library && debug_hook &&
3006 hook_index <
3007 ( sizeof ( library->debug_hooks ) / sizeof ( void* ) ) )
3008 library->debug_hooks[hook_index] = debug_hook;
3009 }
3010
3011
David Turnerf0df85b2000-06-22 00:17:42 +00003012 /*************************************************************************/
David Turnerd2b1f351999-12-16 23:11:37 +00003013 /* */
3014 /* <Function> */
3015 /* FT_Done_FreeType */
3016 /* */
3017 /* <Description> */
3018 /* Destroys a given FreeType library object and all of its childs, */
3019 /* including resources, drivers, faces, sizes, etc. */
3020 /* */
3021 /* <Input> */
3022 /* library :: A handle to the target library object. */
3023 /* */
3024 /* <Return> */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00003025 /* FreeType error code. 0 means success. */
David Turnerd2b1f351999-12-16 23:11:37 +00003026 /* */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00003027 FT_EXPORT_FUNC( FT_Error ) FT_Done_FreeType( FT_Library library )
David Turnerd2b1f351999-12-16 23:11:37 +00003028 {
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00003029 /* test for valid `library' delayed to FT_Done_Library() */
3030
David Turnerd2b1f351999-12-16 23:11:37 +00003031 /* Discard the library object */
3032 FT_Done_Library( library );
3033
3034 return FT_Err_Ok;
3035 }
3036
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00003037
David Turnerd2b1f351999-12-16 23:11:37 +00003038/* END */