blob: 1a10f2a81151b417df28d4e567d93c6c0c09bea7 [file] [log] [blame]
David Turnerd2b1f351999-12-16 23:11:37 +00001/***************************************************************************/
2/* */
3/* ftobjs.c */
4/* */
Werner Lemberg5aa646c2000-07-14 06:16:47 +00005/* The FreeType private base classes (body). */
David Turnerd2b1f351999-12-16 23:11:37 +00006/* */
Werner Lemberg415235d2001-06-28 17:49:10 +00007/* Copyright 1996-2001 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 Lembergcc069be2000-12-08 16:17:16 +000018
19#include <ft2build.h>
20#include FT_LIST_H
21#include FT_INTERNAL_OBJECTS_H
22#include FT_INTERNAL_DEBUG_H
23#include FT_INTERNAL_STREAM_H
24#include FT_TRUETYPE_TABLES_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
Werner Lemberg8ec9dfd2000-11-07 23:56:02 +000051 /* documentation is in ftmemory.h */
52
Werner Lembergf814d0f2001-06-27 16:18:10 +000053 FT_BASE_DEF( FT_Error )
54 FT_Alloc( FT_Memory memory,
55 FT_Long size,
56 void* *P )
David Turnerd2b1f351999-12-16 23:11:37 +000057 {
58 FT_Assert( P != 0 );
59
Werner Lemberg7880dd62000-01-10 17:19:45 +000060 if ( size > 0 )
David Turnerd2b1f351999-12-16 23:11:37 +000061 {
62 *P = memory->alloc( memory, size );
Werner Lemberg7880dd62000-01-10 17:19:45 +000063 if ( !*P )
David Turnerd2b1f351999-12-16 23:11:37 +000064 {
Werner Lemberga3b6c6c2000-05-31 06:55:12 +000065 FT_ERROR(( "FT_Alloc:" ));
Werner Lemberg7880dd62000-01-10 17:19:45 +000066 FT_ERROR(( " Out of memory? (%ld requested)\n",
David Turnerd2b1f351999-12-16 23:11:37 +000067 size ));
68
69 return FT_Err_Out_Of_Memory;
70 }
71 MEM_Set( *P, 0, size );
72 }
73 else
74 *P = NULL;
75
Werner Lemberg56177262000-06-03 21:59:44 +000076 FT_TRACE7(( "FT_Alloc:" ));
77 FT_TRACE7(( " size = %ld, block = 0x%08p, ref = 0x%08p\n",
David Turner51179f02000-05-18 16:18:05 +000078 size, *P, P ));
David Turnerd2b1f351999-12-16 23:11:37 +000079
80 return FT_Err_Ok;
81 }
82
83
Werner Lemberg8ec9dfd2000-11-07 23:56:02 +000084 /* documentation is in ftmemory.h */
85
Werner Lembergf814d0f2001-06-27 16:18:10 +000086 FT_BASE_DEF( FT_Error )
87 FT_Realloc( FT_Memory memory,
88 FT_Long current,
89 FT_Long size,
90 void** P )
David Turnerd2b1f351999-12-16 23:11:37 +000091 {
92 void* Q;
93
Werner Lemberg7880dd62000-01-10 17:19:45 +000094
David Turnerd2b1f351999-12-16 23:11:37 +000095 FT_Assert( P != 0 );
96
97 /* if the original pointer is NULL, call FT_Alloc() */
98 if ( !*P )
99 return FT_Alloc( memory, size, P );
100
101 /* if the new block if zero-sized, clear the current one */
102 if ( size <= 0 )
103 {
104 FT_Free( memory, P );
105 return FT_Err_Ok;
106 }
107
108 Q = memory->realloc( memory, current, size, *P );
Werner Lemberg7880dd62000-01-10 17:19:45 +0000109 if ( !Q )
110 goto Fail;
David Turnerd2b1f351999-12-16 23:11:37 +0000111
David Turnera1471032001-10-18 11:23:51 +0000112 if ( size > current )
113 memset( (char*)Q + current, 0, size - current );
114
David Turnerd2b1f351999-12-16 23:11:37 +0000115 *P = Q;
116 return FT_Err_Ok;
117
118 Fail:
Werner Lemberga3b6c6c2000-05-31 06:55:12 +0000119 FT_ERROR(( "FT_Realloc:" ));
Werner Lemberg7880dd62000-01-10 17:19:45 +0000120 FT_ERROR(( " Failed (current %ld, requested %ld)\n",
David Turnerd2b1f351999-12-16 23:11:37 +0000121 current, size ));
122 return FT_Err_Out_Of_Memory;
123 }
124
125
Werner Lemberg8ec9dfd2000-11-07 23:56:02 +0000126 /* documentation is in ftmemory.h */
127
Werner Lembergf814d0f2001-06-27 16:18:10 +0000128 FT_BASE_DEF( void )
129 FT_Free( FT_Memory memory,
130 void** P )
David Turnerd2b1f351999-12-16 23:11:37 +0000131 {
Werner Lemberg56177262000-06-03 21:59:44 +0000132 FT_TRACE7(( "FT_Free:" ));
133 FT_TRACE7(( " Freeing block 0x%08p, ref 0x%08p\n",
Werner Lemberga3b6c6c2000-05-31 06:55:12 +0000134 P, P ? *P : (void*)0 ));
David Turnerd2b1f351999-12-16 23:11:37 +0000135
Werner Lemberge35cac62000-06-11 03:46:57 +0000136 if ( P && *P )
David Turnerd2b1f351999-12-16 23:11:37 +0000137 {
138 memory->free( memory, *P );
139 *P = 0;
140 }
141 }
142
Werner Lembergdeb4e982000-06-29 03:14:25 +0000143
David Turnerf0df85b2000-06-22 00:17:42 +0000144 /*************************************************************************/
145 /*************************************************************************/
146 /*************************************************************************/
147 /**** ****/
148 /**** ****/
149 /**** S T R E A M ****/
150 /**** ****/
151 /**** ****/
152 /*************************************************************************/
153 /*************************************************************************/
154 /*************************************************************************/
155
Werner Lemberg7880dd62000-01-10 17:19:45 +0000156
Werner Lemberg547a2522000-02-16 08:23:58 +0000157 /*************************************************************************/
158 /* */
159 /* <Function> */
160 /* ft_new_input_stream */
161 /* */
162 /* <Description> */
163 /* Creates a new input stream object from an FT_Open_Args structure. */
164 /* */
Werner Lemberg2fbf7e42000-06-02 00:01:14 +0000165 /* <Note> */
166 /* The function expects a valid `astream' parameter. */
Werner Lembergdeb4e982000-06-29 03:14:25 +0000167 /* */
Werner Lembergf814d0f2001-06-27 16:18:10 +0000168 static FT_Error
169 ft_new_input_stream( FT_Library library,
170 FT_Open_Args* args,
171 FT_Stream* astream )
David Turner7663f222000-02-13 13:37:38 +0000172 {
Werner Lemberg547a2522000-02-16 08:23:58 +0000173 FT_Error error;
174 FT_Memory memory;
175 FT_Stream stream;
176
Werner Lemberga3b6c6c2000-05-31 06:55:12 +0000177
Werner Lemberg2fbf7e42000-06-02 00:01:14 +0000178 if ( !library )
179 return FT_Err_Invalid_Library_Handle;
180
181 if ( !args )
182 return FT_Err_Invalid_Argument;
183
David Turner37379e22000-03-28 11:22:31 +0000184 *astream = 0;
185 memory = library->memory;
Werner Lemberg547a2522000-02-16 08:23:58 +0000186 if ( ALLOC( stream, sizeof ( *stream ) ) )
David Turner37379e22000-03-28 11:22:31 +0000187 goto Exit;
David Turnere49ab252000-05-16 23:44:38 +0000188
David Turner7663f222000-02-13 13:37:38 +0000189 stream->memory = memory;
David Turnere49ab252000-05-16 23:44:38 +0000190
David Turner4f2c5542000-05-12 10:19:41 +0000191 /* now, look at the stream flags */
192 if ( args->flags & ft_open_memory )
Just van Rossumd35aea72000-03-02 01:07:50 +0000193 {
David Turner4f2c5542000-05-12 10:19:41 +0000194 error = 0;
195 FT_New_Memory_Stream( library,
David Turner8edbcab2001-06-19 08:28:24 +0000196 (FT_Byte*)args->memory_base,
David Turner4f2c5542000-05-12 10:19:41 +0000197 args->memory_size,
198 stream );
199 }
Werner Lemberga3b6c6c2000-05-31 06:55:12 +0000200 else if ( args->flags & ft_open_pathname )
David Turner4f2c5542000-05-12 10:19:41 +0000201 {
202 error = FT_New_Stream( args->pathname, stream );
203 stream->pathname.pointer = args->pathname;
204 }
Werner Lemberg58b17f92000-07-27 23:29:08 +0000205 else if ( ( args->flags & ft_open_stream ) && args->stream )
David Turner4f2c5542000-05-12 10:19:41 +0000206 {
Werner Lemberg58b17f92000-07-27 23:29:08 +0000207 /* in this case, we do not need to allocate a new stream object */
208 /* since the caller is responsible for closing it himself */
209 FREE( stream );
David Turnerc5cdf8b2000-07-27 21:40:22 +0000210 stream = args->stream;
David Turner4f2c5542000-05-12 10:19:41 +0000211 }
212 else
David Turner4f2c5542000-05-12 10:19:41 +0000213 error = FT_Err_Invalid_Argument;
David Turnere49ab252000-05-16 23:44:38 +0000214
Werner Lemberg547a2522000-02-16 08:23:58 +0000215 if ( error )
216 FREE( stream );
David Turnere49ab252000-05-16 23:44:38 +0000217
David Turner7663f222000-02-13 13:37:38 +0000218 *astream = stream;
Werner Lemberga3b6c6c2000-05-31 06:55:12 +0000219
David Turner37379e22000-03-28 11:22:31 +0000220 Exit:
David Turner7663f222000-02-13 13:37:38 +0000221 return error;
222 }
223
224
Werner Lemberg90a03302000-11-07 17:21:11 +0000225 /* documentation is in ftobjs.h */
226
Werner Lembergf814d0f2001-06-27 16:18:10 +0000227 FT_EXPORT_DEF( void )
228 FT_Done_Stream( FT_Stream stream )
David Turnera8bcdf82000-05-02 10:51:41 +0000229 {
Werner Lemberg2fbf7e42000-06-02 00:01:14 +0000230 if ( stream && stream->close )
Just van Rossume97cb912000-07-28 03:13:31 +0000231 {
David Turnera8bcdf82000-05-02 10:51:41 +0000232 stream->close( stream );
Just van Rossume97cb912000-07-28 03:13:31 +0000233 stream->close = 0;
234 }
David Turnera8bcdf82000-05-02 10:51:41 +0000235 }
236
237
Werner Lembergf814d0f2001-06-27 16:18:10 +0000238 static void
239 ft_done_stream( FT_Stream* astream,
240 FT_Int external )
David Turner7663f222000-02-13 13:37:38 +0000241 {
242 FT_Stream stream = *astream;
Werner Lemberg547a2522000-02-16 08:23:58 +0000243
Werner Lemberga3b6c6c2000-05-31 06:55:12 +0000244
Werner Lemberg547a2522000-02-16 08:23:58 +0000245 if ( stream->close )
David Turner7663f222000-02-13 13:37:38 +0000246 stream->close( stream );
Just van Rossum7eef5362000-03-05 16:07:58 +0000247
Werner Lemberg58b17f92000-07-27 23:29:08 +0000248 if ( !external )
David Turnerc5cdf8b2000-07-27 21:40:22 +0000249 {
250 FT_Memory memory = stream->memory;
Werner Lemberg58b17f92000-07-27 23:29:08 +0000251
252
David Turnerc5cdf8b2000-07-27 21:40:22 +0000253 FREE( stream );
254 }
David Turner7663f222000-02-13 13:37:38 +0000255 *astream = 0;
256 }
257
Werner Lemberga3b6c6c2000-05-31 06:55:12 +0000258
Werner Lembergeb81e372000-06-03 06:03:11 +0000259#undef FT_COMPONENT
260#define FT_COMPONENT trace_objs
261
Werner Lembergdeb4e982000-06-29 03:14:25 +0000262
David Turnerf0df85b2000-06-22 00:17:42 +0000263 /*************************************************************************/
264 /*************************************************************************/
265 /*************************************************************************/
266 /**** ****/
267 /**** ****/
268 /**** G L Y P H L O A D E R ****/
269 /**** ****/
270 /**** ****/
271 /*************************************************************************/
272 /*************************************************************************/
273 /*************************************************************************/
274
David Turnerf0df85b2000-06-22 00:17:42 +0000275
Werner Lemberga929ba92000-06-25 06:47:11 +0000276 /*************************************************************************/
277 /* */
278 /* The glyph loader is a simple object which is used to load a set of */
279 /* glyphs easily. It is critical for the correct loading of composites. */
280 /* */
281 /* Ideally, one can see it as a stack of abstract `glyph' objects. */
282 /* */
283 /* loader.base Is really the bottom of the stack. It describes a */
284 /* single glyph image made of the juxtaposition of */
285 /* several glyphs (those `in the stack'). */
286 /* */
287 /* loader.current Describes the top of the stack, on which a new */
288 /* glyph can be loaded. */
289 /* */
290 /* Rewind Clears the stack. */
291 /* Prepare Set up `loader.current' for addition of a new glyph */
292 /* image. */
293 /* Add Add the `current' glyph image to the `base' one, */
294 /* and prepare for another one. */
295 /* */
296 /* The glyph loader is now a base object. Each driver used to */
297 /* re-implement it in one way or the other, which wasted code and */
298 /* energy. */
299 /* */
300 /*************************************************************************/
301
302
303 /* create a new glyph loader */
Werner Lembergf814d0f2001-06-27 16:18:10 +0000304 FT_BASE_DEF( FT_Error )
305 FT_GlyphLoader_New( FT_Memory memory,
306 FT_GlyphLoader* *aloader )
David Turnerf0df85b2000-06-22 00:17:42 +0000307 {
308 FT_GlyphLoader* loader;
309 FT_Error error;
310
Werner Lemberga929ba92000-06-25 06:47:11 +0000311
312 if ( !ALLOC( loader, sizeof ( *loader ) ) )
David Turnerf0df85b2000-06-22 00:17:42 +0000313 {
314 loader->memory = memory;
315 *aloader = loader;
316 }
317 return error;
318 }
319
320
Werner Lemberga929ba92000-06-25 06:47:11 +0000321 /* rewind the glyph loader - reset counters to 0 */
Werner Lembergf814d0f2001-06-27 16:18:10 +0000322 FT_BASE_DEF( void )
323 FT_GlyphLoader_Rewind( FT_GlyphLoader* loader )
David Turnerf0df85b2000-06-22 00:17:42 +0000324 {
325 FT_GlyphLoad* base = &loader->base;
326 FT_GlyphLoad* current = &loader->current;
327
Werner Lemberga929ba92000-06-25 06:47:11 +0000328
David Turnerf0df85b2000-06-22 00:17:42 +0000329 base->outline.n_points = 0;
330 base->outline.n_contours = 0;
331 base->num_subglyphs = 0;
332
333 *current = *base;
334 }
335
336
Werner Lemberga929ba92000-06-25 06:47:11 +0000337 /* reset the glyph loader, frees all allocated tables */
338 /* and starts from zero */
Werner Lembergf814d0f2001-06-27 16:18:10 +0000339 FT_BASE_DEF( void )
340 FT_GlyphLoader_Reset( FT_GlyphLoader* loader )
David Turnerf0df85b2000-06-22 00:17:42 +0000341 {
342 FT_Memory memory = loader->memory;
343
Werner Lemberga929ba92000-06-25 06:47:11 +0000344
David Turnerf0df85b2000-06-22 00:17:42 +0000345 FREE( loader->base.outline.points );
346 FREE( loader->base.outline.tags );
347 FREE( loader->base.outline.contours );
348 FREE( loader->base.extra_points );
349 FREE( loader->base.subglyphs );
350
351 loader->max_points = 0;
352 loader->max_contours = 0;
353 loader->max_subglyphs = 0;
354
355 FT_GlyphLoader_Rewind( loader );
356 }
357
358
Werner Lemberga929ba92000-06-25 06:47:11 +0000359 /* delete a glyph loader */
Werner Lembergf814d0f2001-06-27 16:18:10 +0000360 FT_BASE_DEF( void )
361 FT_GlyphLoader_Done( FT_GlyphLoader* loader )
David Turnerf0df85b2000-06-22 00:17:42 +0000362 {
Werner Lemberga929ba92000-06-25 06:47:11 +0000363 if ( loader )
David Turnerf0df85b2000-06-22 00:17:42 +0000364 {
365 FT_Memory memory = loader->memory;
366
Werner Lemberga929ba92000-06-25 06:47:11 +0000367
Werner Lembergdeb4e982000-06-29 03:14:25 +0000368 FT_GlyphLoader_Reset( loader );
David Turnerf0df85b2000-06-22 00:17:42 +0000369 FREE( loader );
370 }
371 }
372
373
Werner Lemberga929ba92000-06-25 06:47:11 +0000374 /* re-adjust the `current' outline fields */
Werner Lembergf814d0f2001-06-27 16:18:10 +0000375 static void
376 FT_GlyphLoader_Adjust_Points( FT_GlyphLoader* loader )
David Turnerf0df85b2000-06-22 00:17:42 +0000377 {
378 FT_Outline* base = &loader->base.outline;
379 FT_Outline* current = &loader->current.outline;
380
Werner Lemberga929ba92000-06-25 06:47:11 +0000381
David Turnerf0df85b2000-06-22 00:17:42 +0000382 current->points = base->points + base->n_points;
383 current->tags = base->tags + base->n_points;
384 current->contours = base->contours + base->n_contours;
Werner Lembergdeb4e982000-06-29 03:14:25 +0000385
David Turnerf0df85b2000-06-22 00:17:42 +0000386 /* handle extra points table - if any */
Werner Lemberga929ba92000-06-25 06:47:11 +0000387 if ( loader->use_extra )
388 loader->current.extra_points =
389 loader->base.extra_points + base->n_points;
David Turnerf0df85b2000-06-22 00:17:42 +0000390 }
391
392
Werner Lembergf814d0f2001-06-27 16:18:10 +0000393 FT_BASE_DEF( FT_Error )
394 FT_GlyphLoader_Create_Extra( FT_GlyphLoader* loader )
David Turnerf0df85b2000-06-22 00:17:42 +0000395 {
396 FT_Error error;
397 FT_Memory memory = loader->memory;
Werner Lemberga929ba92000-06-25 06:47:11 +0000398
Werner Lembergdeb4e982000-06-29 03:14:25 +0000399
David Turnerf0df85b2000-06-22 00:17:42 +0000400 if ( !ALLOC_ARRAY( loader->base.extra_points,
401 loader->max_points, FT_Vector ) )
402 {
403 loader->use_extra = 1;
Werner Lemberga929ba92000-06-25 06:47:11 +0000404 FT_GlyphLoader_Adjust_Points( loader );
David Turnerf0df85b2000-06-22 00:17:42 +0000405 }
406 return error;
407 }
408
409
Werner Lemberga929ba92000-06-25 06:47:11 +0000410 /* re-adjust the `current' subglyphs field */
Werner Lembergf814d0f2001-06-27 16:18:10 +0000411 static void
412 FT_GlyphLoader_Adjust_Subglyphs( FT_GlyphLoader* loader )
David Turnerf0df85b2000-06-22 00:17:42 +0000413 {
414 FT_GlyphLoad* base = &loader->base;
415 FT_GlyphLoad* current = &loader->current;
416
Werner Lemberga929ba92000-06-25 06:47:11 +0000417
David Turnerf0df85b2000-06-22 00:17:42 +0000418 current->subglyphs = base->subglyphs + base->num_subglyphs;
419 }
420
421
Werner Lemberga929ba92000-06-25 06:47:11 +0000422 /* Ensure that we can add `n_points' and `n_contours' to our glyph. this */
423 /* function reallocates its outline tables if necessary. Note that it */
424 /* DOESN'T change the number of points within the loader! */
Werner Lembergdeb4e982000-06-29 03:14:25 +0000425 /* */
Werner Lembergf814d0f2001-06-27 16:18:10 +0000426 FT_BASE_DEF( FT_Error )
427 FT_GlyphLoader_Check_Points( FT_GlyphLoader* loader,
428 FT_UInt n_points,
429 FT_UInt n_contours )
David Turnerf0df85b2000-06-22 00:17:42 +0000430 {
431 FT_Memory memory = loader->memory;
432 FT_Error error = FT_Err_Ok;
433 FT_Outline* base = &loader->base.outline;
434 FT_Outline* current = &loader->current.outline;
435 FT_Bool adjust = 1;
436
David Turner61d6b2b2001-05-16 17:49:07 +0000437 FT_UInt new_max, old_max;
David Turnerf0df85b2000-06-22 00:17:42 +0000438
Werner Lemberga929ba92000-06-25 06:47:11 +0000439
David Turnerf0df85b2000-06-22 00:17:42 +0000440 /* check points & tags */
441 new_max = base->n_points + current->n_points + n_points;
David Turner61d6b2b2001-05-16 17:49:07 +0000442 old_max = loader->max_points;
443
444 if ( new_max > old_max )
David Turnerf0df85b2000-06-22 00:17:42 +0000445 {
Werner Lemberga929ba92000-06-25 06:47:11 +0000446 new_max = ( new_max + 7 ) & -8;
David Turner61d6b2b2001-05-16 17:49:07 +0000447
Werner Lemberg55798122001-05-17 06:27:17 +0000448 if ( REALLOC_ARRAY( base->points, old_max, new_max, FT_Vector ) ||
449 REALLOC_ARRAY( base->tags, old_max, new_max, FT_Byte ) )
David Turnerf0df85b2000-06-22 00:17:42 +0000450 goto Exit;
451
452 if ( loader->use_extra &&
David Turner61d6b2b2001-05-16 17:49:07 +0000453 REALLOC_ARRAY( loader->base.extra_points, old_max,
Werner Lemberga929ba92000-06-25 06:47:11 +0000454 new_max, FT_Vector ) )
David Turnerf0df85b2000-06-22 00:17:42 +0000455 goto Exit;
456
457 adjust = 1;
458 loader->max_points = new_max;
459 }
460
461 /* check contours */
David Turner61d6b2b2001-05-16 17:49:07 +0000462 old_max = loader->max_contours;
David Turnerf0df85b2000-06-22 00:17:42 +0000463 new_max = base->n_contours + current->n_contours +
464 n_contours;
David Turner61d6b2b2001-05-16 17:49:07 +0000465 if ( new_max > old_max )
David Turnerf0df85b2000-06-22 00:17:42 +0000466 {
Werner Lemberga929ba92000-06-25 06:47:11 +0000467 new_max = ( new_max + 3 ) & -4;
David Turner61d6b2b2001-05-16 17:49:07 +0000468 if ( REALLOC_ARRAY( base->contours, old_max, new_max, FT_Short ) )
David Turnerf0df85b2000-06-22 00:17:42 +0000469 goto Exit;
470
471 adjust = 1;
472 loader->max_contours = new_max;
473 }
474
Werner Lemberga929ba92000-06-25 06:47:11 +0000475 if ( adjust )
David Turnerf0df85b2000-06-22 00:17:42 +0000476 FT_GlyphLoader_Adjust_Points( loader );
477
478 Exit:
479 return error;
480 }
481
482
Werner Lemberga929ba92000-06-25 06:47:11 +0000483 /* Ensure that we can add `n_subglyphs' to our glyph. this function */
484 /* reallocates its subglyphs table if necessary. Note that it DOES */
485 /* NOT change the number of subglyphs within the loader! */
Werner Lembergdeb4e982000-06-29 03:14:25 +0000486 /* */
Werner Lembergf814d0f2001-06-27 16:18:10 +0000487 FT_BASE_DEF( FT_Error )
488 FT_GlyphLoader_Check_Subglyphs( FT_GlyphLoader* loader,
489 FT_UInt n_subs )
David Turnerf0df85b2000-06-22 00:17:42 +0000490 {
491 FT_Memory memory = loader->memory;
492 FT_Error error = FT_Err_Ok;
David Turner61d6b2b2001-05-16 17:49:07 +0000493 FT_UInt new_max, old_max;
David Turnerf0df85b2000-06-22 00:17:42 +0000494
495 FT_GlyphLoad* base = &loader->base;
496 FT_GlyphLoad* current = &loader->current;
497
Werner Lemberga929ba92000-06-25 06:47:11 +0000498
David Turnerf0df85b2000-06-22 00:17:42 +0000499 new_max = base->num_subglyphs + current->num_subglyphs + n_subs;
David Turner61d6b2b2001-05-16 17:49:07 +0000500 old_max = loader->max_subglyphs;
501 if ( new_max > old_max )
David Turnerf0df85b2000-06-22 00:17:42 +0000502 {
Werner Lemberga929ba92000-06-25 06:47:11 +0000503 new_max = ( new_max + 1 ) & -2;
David Turner61d6b2b2001-05-16 17:49:07 +0000504 if ( REALLOC_ARRAY( base->subglyphs, old_max, new_max, FT_SubGlyph ) )
David Turnerf0df85b2000-06-22 00:17:42 +0000505 goto Exit;
506
507 loader->max_subglyphs = new_max;
508
509 FT_GlyphLoader_Adjust_Subglyphs( loader );
510 }
511
512 Exit:
513 return error;
514 }
515
516
Werner Lemberga929ba92000-06-25 06:47:11 +0000517 /* prepare loader for the addition of a new glyph on top of the base one */
Werner Lembergf814d0f2001-06-27 16:18:10 +0000518 FT_BASE_DEF( void )
519 FT_GlyphLoader_Prepare( FT_GlyphLoader* loader )
David Turnerf0df85b2000-06-22 00:17:42 +0000520 {
521 FT_GlyphLoad* current = &loader->current;
522
Werner Lemberga929ba92000-06-25 06:47:11 +0000523
David Turnerf0df85b2000-06-22 00:17:42 +0000524 current->outline.n_points = 0;
525 current->outline.n_contours = 0;
526 current->num_subglyphs = 0;
527
528 FT_GlyphLoader_Adjust_Points ( loader );
529 FT_GlyphLoader_Adjust_Subglyphs( loader );
530 }
531
532
Werner Lemberga929ba92000-06-25 06:47:11 +0000533 /* add current glyph to the base image - and prepare for another */
Werner Lembergf814d0f2001-06-27 16:18:10 +0000534 FT_BASE_DEF( void )
535 FT_GlyphLoader_Add( FT_GlyphLoader* loader )
David Turnerf0df85b2000-06-22 00:17:42 +0000536 {
537 FT_GlyphLoad* base = &loader->base;
538 FT_GlyphLoad* current = &loader->current;
539
540 FT_UInt n_curr_contours = current->outline.n_contours;
541 FT_UInt n_base_points = base->outline.n_points;
542 FT_UInt n;
543
Werner Lemberga929ba92000-06-25 06:47:11 +0000544
Werner Lemberg8eb03532001-06-19 23:03:41 +0000545 base->outline.n_points =
546 (short)( base->outline.n_points + current->outline.n_points );
547 base->outline.n_contours =
548 (short)( base->outline.n_contours + current->outline.n_contours );
549
550 base->num_subglyphs += current->num_subglyphs;
David Turnerf0df85b2000-06-22 00:17:42 +0000551
552 /* adjust contours count in newest outline */
553 for ( n = 0; n < n_curr_contours; n++ )
Werner Lemberg8eb03532001-06-19 23:03:41 +0000554 current->outline.contours[n] =
555 (short)( current->outline.contours[n] + n_base_points );
David Turnerf0df85b2000-06-22 00:17:42 +0000556
557 /* prepare for another new glyph image */
558 FT_GlyphLoader_Prepare( loader );
559 }
560
561
Werner Lembergf814d0f2001-06-27 16:18:10 +0000562 FT_BASE_DEF( FT_Error )
563 FT_GlyphLoader_Copy_Points( FT_GlyphLoader* target,
564 FT_GlyphLoader* source )
David Turnerf0df85b2000-06-22 00:17:42 +0000565 {
566 FT_Error error;
567 FT_UInt num_points = source->base.outline.n_points;
568 FT_UInt num_contours = source->base.outline.n_contours;
Werner Lemberga929ba92000-06-25 06:47:11 +0000569
Werner Lembergdeb4e982000-06-29 03:14:25 +0000570
David Turnerf0df85b2000-06-22 00:17:42 +0000571 error = FT_GlyphLoader_Check_Points( target, num_points, num_contours );
Werner Lemberga929ba92000-06-25 06:47:11 +0000572 if ( !error )
David Turnerf0df85b2000-06-22 00:17:42 +0000573 {
574 FT_Outline* out = &target->base.outline;
575 FT_Outline* in = &source->base.outline;
Werner Lemberga929ba92000-06-25 06:47:11 +0000576
Werner Lembergdeb4e982000-06-29 03:14:25 +0000577
Werner Lemberga929ba92000-06-25 06:47:11 +0000578 MEM_Copy( out->points, in->points,
579 num_points * sizeof ( FT_Vector ) );
580 MEM_Copy( out->tags, in->tags,
581 num_points * sizeof ( char ) );
582 MEM_Copy( out->contours, in->contours,
583 num_contours * sizeof ( short ) );
Werner Lembergdeb4e982000-06-29 03:14:25 +0000584
Werner Lemberga929ba92000-06-25 06:47:11 +0000585 /* do we need to copy the extra points? */
586 if ( target->use_extra && source->use_extra )
David Turnerf0df85b2000-06-22 00:17:42 +0000587 MEM_Copy( target->base.extra_points, source->base.extra_points,
Werner Lemberga929ba92000-06-25 06:47:11 +0000588 num_points * sizeof ( FT_Vector ) );
Werner Lembergdeb4e982000-06-29 03:14:25 +0000589
David Turner8edbcab2001-06-19 08:28:24 +0000590 out->n_points = (short)num_points;
591 out->n_contours = (short)num_contours;
Werner Lembergdeb4e982000-06-29 03:14:25 +0000592
David Turnerf0df85b2000-06-22 00:17:42 +0000593 FT_GlyphLoader_Adjust_Points( target );
594 }
Werner Lemberga929ba92000-06-25 06:47:11 +0000595
Werner Lembergdeb4e982000-06-29 03:14:25 +0000596 return error;
597 }
David Turnerf0df85b2000-06-22 00:17:42 +0000598
599
David Turnerf0df85b2000-06-22 00:17:42 +0000600 /*************************************************************************/
601 /*************************************************************************/
602 /*************************************************************************/
603 /**** ****/
604 /**** ****/
605 /**** FACE, SIZE & GLYPH SLOT OBJECTS ****/
606 /**** ****/
607 /**** ****/
608 /*************************************************************************/
609 /*************************************************************************/
610 /*************************************************************************/
611
Werner Lembergdeb4e982000-06-29 03:14:25 +0000612
Werner Lembergf814d0f2001-06-27 16:18:10 +0000613 static FT_Error
614 ft_glyphslot_init( FT_GlyphSlot slot )
David Turnerf0df85b2000-06-22 00:17:42 +0000615 {
616 FT_Driver driver = slot->face->driver;
617 FT_Driver_Class* clazz = driver->clazz;
618 FT_Memory memory = driver->root.memory;
619 FT_Error error = FT_Err_Ok;
David Turner54e75742000-11-04 02:52:02 +0000620 FT_Slot_Internal internal;
David Turnerf0df85b2000-06-22 00:17:42 +0000621
Werner Lemberga8bbc262000-07-01 14:06:46 +0000622
David Turnerf9ca2bb2000-06-30 23:12:55 +0000623 slot->library = driver->root.library;
Werner Lembergfbeb41d2000-07-02 00:27:53 +0000624
Werner Lembergdc72aff2000-11-04 08:33:38 +0000625 if ( ALLOC( internal, sizeof ( *internal ) ) )
David Turner54e75742000-11-04 02:52:02 +0000626 goto Exit;
627
628 slot->internal = internal;
629
Werner Lemberga929ba92000-06-25 06:47:11 +0000630 if ( FT_DRIVER_USES_OUTLINES( driver ) )
David Turner54e75742000-11-04 02:52:02 +0000631 error = FT_GlyphLoader_New( memory, &internal->loader );
David Turnerf0df85b2000-06-22 00:17:42 +0000632
Werner Lemberga929ba92000-06-25 06:47:11 +0000633 if ( !error && clazz->init_slot )
David Turnerf0df85b2000-06-22 00:17:42 +0000634 error = clazz->init_slot( slot );
635
David Turner54e75742000-11-04 02:52:02 +0000636 Exit:
David Turnerf0df85b2000-06-22 00:17:42 +0000637 return error;
638 }
639
640
Werner Lembergf814d0f2001-06-27 16:18:10 +0000641 static void
642 ft_glyphslot_clear( FT_GlyphSlot slot )
David Turnerf0df85b2000-06-22 00:17:42 +0000643 {
David Turner5ae831c2000-06-30 01:31:22 +0000644 /* free bitmap if needed */
645 if ( slot->flags & ft_glyph_own_bitmap )
646 {
647 FT_Memory memory = FT_FACE_MEMORY( slot->face );
Werner Lembergcc9fc492000-06-30 06:21:26 +0000648
649
David Turner5ae831c2000-06-30 01:31:22 +0000650 FREE( slot->bitmap.buffer );
651 slot->flags &= ~ft_glyph_own_bitmap;
652 }
Werner Lembergfbeb41d2000-07-02 00:27:53 +0000653
David Turnerf0df85b2000-06-22 00:17:42 +0000654 /* clear all public fields in the glyph slot */
Werner Lemberga929ba92000-06-25 06:47:11 +0000655 MEM_Set( &slot->metrics, 0, sizeof ( slot->metrics ) );
656 MEM_Set( &slot->outline, 0, sizeof ( slot->outline ) );
657 MEM_Set( &slot->bitmap, 0, sizeof ( slot->bitmap ) );
David Turnerf0df85b2000-06-22 00:17:42 +0000658
659 slot->bitmap_left = 0;
660 slot->bitmap_top = 0;
661 slot->num_subglyphs = 0;
662 slot->subglyphs = 0;
663 slot->control_data = 0;
664 slot->control_len = 0;
665 slot->other = 0;
Werner Lembergbd5ae402000-07-05 04:32:02 +0000666 slot->format = ft_glyph_format_none;
David Turnerf0df85b2000-06-22 00:17:42 +0000667
668 slot->linearHoriAdvance = 0;
669 slot->linearVertAdvance = 0;
670 }
671
672
Werner Lembergf814d0f2001-06-27 16:18:10 +0000673 static void
674 ft_glyphslot_done( FT_GlyphSlot slot )
David Turnerf0df85b2000-06-22 00:17:42 +0000675 {
676 FT_Driver driver = slot->face->driver;
677 FT_Driver_Class* clazz = driver->clazz;
678 FT_Memory memory = driver->root.memory;
679
Werner Lemberga929ba92000-06-25 06:47:11 +0000680
David Turner54e75742000-11-04 02:52:02 +0000681 if ( clazz->done_slot )
682 clazz->done_slot( slot );
683
David Turnerf0df85b2000-06-22 00:17:42 +0000684 /* free bitmap buffer if needed */
685 if ( slot->flags & ft_glyph_own_bitmap )
686 FREE( slot->bitmap.buffer );
687
688 /* free glyph loader */
Werner Lemberga929ba92000-06-25 06:47:11 +0000689 if ( FT_DRIVER_USES_OUTLINES( driver ) )
David Turnerf0df85b2000-06-22 00:17:42 +0000690 {
David Turner54e75742000-11-04 02:52:02 +0000691 FT_GlyphLoader_Done( slot->internal->loader );
692 slot->internal->loader = 0;
David Turnerf0df85b2000-06-22 00:17:42 +0000693 }
694
David Turner54e75742000-11-04 02:52:02 +0000695 FREE( slot->internal );
David Turnerf0df85b2000-06-22 00:17:42 +0000696 }
697
698
Werner Lemberg8ec9dfd2000-11-07 23:56:02 +0000699 /* documentation is in ftobjs.h */
700
Werner Lembergf814d0f2001-06-27 16:18:10 +0000701 FT_BASE_DEF( FT_Error )
702 FT_New_GlyphSlot( FT_Face face,
703 FT_GlyphSlot *aslot )
David Turnerf0df85b2000-06-22 00:17:42 +0000704 {
Werner Lemberga929ba92000-06-25 06:47:11 +0000705 FT_Error error;
706 FT_Driver driver;
707 FT_Driver_Class* clazz;
708 FT_Memory memory;
709 FT_GlyphSlot slot;
710
David Turnerf0df85b2000-06-22 00:17:42 +0000711
David Turnerf0df85b2000-06-22 00:17:42 +0000712 if ( !face || !aslot || !face->driver )
713 return FT_Err_Invalid_Argument;
714
Werner Lembergdeb4e982000-06-29 03:14:25 +0000715 *aslot = 0;
716
David Turnerf0df85b2000-06-22 00:17:42 +0000717 driver = face->driver;
718 clazz = driver->clazz;
719 memory = driver->root.memory;
720
721 FT_TRACE4(( "FT_New_GlyphSlot: Creating new slot object\n" ));
722 if ( !ALLOC( slot, clazz->slot_object_size ) )
723 {
724 slot->face = face;
725
726 error = ft_glyphslot_init( slot );
Werner Lemberga929ba92000-06-25 06:47:11 +0000727 if ( error )
David Turnerf0df85b2000-06-22 00:17:42 +0000728 {
729 ft_glyphslot_done( slot );
730 FREE( slot );
731 goto Exit;
732 }
733
734 *aslot = slot;
735 }
736
737 Exit:
738 FT_TRACE4(( "FT_New_GlyphSlot: Return %d\n", error ));
739 return error;
740 }
741
742
Werner Lemberg8ec9dfd2000-11-07 23:56:02 +0000743 /* documentation is in ftobjs.h */
744
Werner Lembergf814d0f2001-06-27 16:18:10 +0000745 FT_BASE_DEF( void )
746 FT_Done_GlyphSlot( FT_GlyphSlot slot )
David Turnerf0df85b2000-06-22 00:17:42 +0000747 {
748 if ( slot )
749 {
750 FT_Driver driver = slot->face->driver;
751 FT_Memory memory = driver->root.memory;
752 FT_GlyphSlot* parent;
753 FT_GlyphSlot cur;
754
Werner Lemberga929ba92000-06-25 06:47:11 +0000755
David Turnerf0df85b2000-06-22 00:17:42 +0000756 /* Remove slot from its parent face's list */
757 parent = &slot->face->glyph;
758 cur = *parent;
Werner Lemberga929ba92000-06-25 06:47:11 +0000759
David Turnerf0df85b2000-06-22 00:17:42 +0000760 while ( cur )
761 {
762 if ( cur == slot )
763 {
764 *parent = cur->next;
Werner Lemberga929ba92000-06-25 06:47:11 +0000765 ft_glyphslot_done( slot );
David Turnerf0df85b2000-06-22 00:17:42 +0000766 FREE( slot );
767 break;
768 }
769 cur = cur->next;
770 }
771 }
772 }
773
774
Werner Lemberg90a03302000-11-07 17:21:11 +0000775 /* documentation is in freetype.h */
776
Werner Lembergf814d0f2001-06-27 16:18:10 +0000777 FT_EXPORT_DEF( void )
778 FT_Set_Transform( FT_Face face,
779 FT_Matrix* matrix,
780 FT_Vector* delta )
David Turnerf0df85b2000-06-22 00:17:42 +0000781 {
David Turner54e75742000-11-04 02:52:02 +0000782 FT_Face_Internal internal;
David Turner61d6b2b2001-05-16 17:49:07 +0000783
David Turner54e75742000-11-04 02:52:02 +0000784
David Turnerf0df85b2000-06-22 00:17:42 +0000785 if ( !face )
786 return;
787
David Turner54e75742000-11-04 02:52:02 +0000788 internal = face->internal;
789
790 internal->transform_flags = 0;
David Turnerf0df85b2000-06-22 00:17:42 +0000791
792 if ( !matrix )
793 {
David Turner54e75742000-11-04 02:52:02 +0000794 internal->transform_matrix.xx = 0x10000L;
795 internal->transform_matrix.xy = 0;
796 internal->transform_matrix.yx = 0;
797 internal->transform_matrix.yy = 0x10000L;
798 matrix = &internal->transform_matrix;
David Turnerf0df85b2000-06-22 00:17:42 +0000799 }
800 else
David Turner54e75742000-11-04 02:52:02 +0000801 internal->transform_matrix = *matrix;
David Turnerf0df85b2000-06-22 00:17:42 +0000802
803 /* set transform_flags bit flag 0 if `matrix' isn't the identity */
804 if ( ( matrix->xy | matrix->yx ) ||
805 matrix->xx != 0x10000L ||
806 matrix->yy != 0x10000L )
David Turner54e75742000-11-04 02:52:02 +0000807 internal->transform_flags |= 1;
David Turnerf0df85b2000-06-22 00:17:42 +0000808
809 if ( !delta )
810 {
David Turner54e75742000-11-04 02:52:02 +0000811 internal->transform_delta.x = 0;
812 internal->transform_delta.y = 0;
813 delta = &internal->transform_delta;
David Turnerf0df85b2000-06-22 00:17:42 +0000814 }
815 else
David Turner54e75742000-11-04 02:52:02 +0000816 internal->transform_delta = *delta;
David Turnerf0df85b2000-06-22 00:17:42 +0000817
818 /* set transform_flags bit flag 1 if `delta' isn't the null vector */
819 if ( delta->x | delta->y )
David Turner54e75742000-11-04 02:52:02 +0000820 internal->transform_flags |= 2;
David Turnerf0df85b2000-06-22 00:17:42 +0000821 }
822
823
Werner Lembergf814d0f2001-06-27 16:18:10 +0000824 static FT_Renderer
825 ft_lookup_glyph_renderer( FT_GlyphSlot slot );
Werner Lembergdeb4e982000-06-29 03:14:25 +0000826
827
Werner Lemberg90a03302000-11-07 17:21:11 +0000828 /* documentation is in freetype.h */
829
Werner Lembergf814d0f2001-06-27 16:18:10 +0000830 FT_EXPORT_DEF( FT_Error )
831 FT_Load_Glyph( FT_Face face,
832 FT_UInt glyph_index,
833 FT_Int load_flags )
David Turnerf0df85b2000-06-22 00:17:42 +0000834 {
835 FT_Error error;
836 FT_Driver driver;
837 FT_GlyphSlot slot;
David Turner5ae831c2000-06-30 01:31:22 +0000838 FT_Library library;
839 FT_Bool autohint;
840 FT_Module hinter;
David Turnerf0df85b2000-06-22 00:17:42 +0000841
Werner Lemberga929ba92000-06-25 06:47:11 +0000842
David Turnerf0df85b2000-06-22 00:17:42 +0000843 if ( !face || !face->size || !face->glyph )
844 return FT_Err_Invalid_Face_Handle;
845
David Turner74abee82000-06-27 23:31:53 +0000846 if ( glyph_index >= (FT_UInt)face->num_glyphs )
David Turnerf0df85b2000-06-22 00:17:42 +0000847 return FT_Err_Invalid_Argument;
848
849 slot = face->glyph;
850 ft_glyphslot_clear( slot );
851
852 driver = face->driver;
853
854 /* when the flag NO_RECURSE is set, we disable hinting and scaling */
855 if ( load_flags & FT_LOAD_NO_RECURSE )
David Turnerc9ce9e42000-09-15 17:16:49 +0000856 {
Werner Lembergeddd9902000-10-12 05:05:40 +0000857 /* disable scaling, hinting, and transformation */
858 load_flags |= FT_LOAD_NO_SCALE |
859 FT_LOAD_NO_HINTING |
David Turnerc9ce9e42000-09-15 17:16:49 +0000860 FT_LOAD_IGNORE_TRANSFORM;
Werner Lembergeddd9902000-10-12 05:05:40 +0000861
David Turnerc9ce9e42000-09-15 17:16:49 +0000862 /* disable bitmap rendering */
Werner Lembergeddd9902000-10-12 05:05:40 +0000863 load_flags &= ~FT_LOAD_RENDER;
David Turnerc9ce9e42000-09-15 17:16:49 +0000864 }
David Turnerf0df85b2000-06-22 00:17:42 +0000865
Werner Lembergcc9fc492000-06-30 06:21:26 +0000866 /* do we need to load the glyph through the auto-hinter? */
David Turner5ae831c2000-06-30 01:31:22 +0000867 library = driver->root.library;
868 hinter = library->auto_hinter;
Werner Lemberg8eb03532001-06-19 23:03:41 +0000869 autohint =
870 FT_BOOL( hinter &&
David Turner710354b2000-08-16 17:04:22 +0000871 !( load_flags & ( FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING ) ) &&
Werner Lemberg8eb03532001-06-19 23:03:41 +0000872 FT_DRIVER_IS_SCALABLE( driver ) &&
873 FT_DRIVER_USES_OUTLINES( driver ) );
Werner Lembergcc9fc492000-06-30 06:21:26 +0000874 if ( autohint )
David Turner5ae831c2000-06-30 01:31:22 +0000875 {
876 if ( FT_DRIVER_HAS_HINTER( driver ) &&
Werner Lembergcc9fc492000-06-30 06:21:26 +0000877 !( load_flags & FT_LOAD_FORCE_AUTOHINT ) )
878 autohint = 0;
879 }
Werner Lembergfbeb41d2000-07-02 00:27:53 +0000880
Werner Lembergcc9fc492000-06-30 06:21:26 +0000881 if ( autohint )
David Turner5ae831c2000-06-30 01:31:22 +0000882 {
883 FT_AutoHinter_Interface* hinting;
Werner Lembergfbeb41d2000-07-02 00:27:53 +0000884
Werner Lembergcc9fc492000-06-30 06:21:26 +0000885
David Turner5ae831c2000-06-30 01:31:22 +0000886 hinting = (FT_AutoHinter_Interface*)hinter->clazz->module_interface;
David Turner76a5f622000-11-04 01:55:49 +0000887
888 error = hinting->load_glyph( (FT_AutoHinter)hinter,
889 slot, face->size,
890 glyph_index, load_flags );
David Turner5ae831c2000-06-30 01:31:22 +0000891 }
892 else
893 error = driver->clazz->load_glyph( slot,
894 face->size,
Werner Lembergcc9fc492000-06-30 06:21:26 +0000895 glyph_index,
896 load_flags );
Werner Lemberga929ba92000-06-25 06:47:11 +0000897 if ( error )
898 goto Exit;
David Turnerf0df85b2000-06-22 00:17:42 +0000899
900 /* compute the advance */
Werner Lemberga929ba92000-06-25 06:47:11 +0000901 if ( load_flags & FT_LOAD_VERTICAL_LAYOUT )
David Turnerf0df85b2000-06-22 00:17:42 +0000902 {
903 slot->advance.x = 0;
904 slot->advance.y = slot->metrics.vertAdvance;
905 }
906 else
907 {
908 slot->advance.x = slot->metrics.horiAdvance;
909 slot->advance.y = 0;
910 }
911
David Turnerc9ce9e42000-09-15 17:16:49 +0000912 /* compute the linear advance in 16.16 pixels */
913 if ( ( load_flags & FT_LOAD_LINEAR_DESIGN ) == 0 )
914 {
915 FT_UInt EM = face->units_per_EM;
916 FT_Size_Metrics* metrics = &face->size->metrics;
Werner Lembergeddd9902000-10-12 05:05:40 +0000917
David Turnerc9ce9e42000-09-15 17:16:49 +0000918 slot->linearHoriAdvance = FT_MulDiv( slot->linearHoriAdvance,
919 (FT_Long)metrics->x_ppem << 16, EM );
920
921 slot->linearVertAdvance = FT_MulDiv( slot->linearVertAdvance,
922 (FT_Long)metrics->y_ppem << 16, EM );
923 }
924
925 if ( ( load_flags & FT_LOAD_IGNORE_TRANSFORM ) == 0 )
David Turnerf0df85b2000-06-22 00:17:42 +0000926 {
David Turner54e75742000-11-04 02:52:02 +0000927 FT_Face_Internal internal = face->internal;
David Turner61d6b2b2001-05-16 17:49:07 +0000928
929
Werner Lembergd1b74752000-08-24 16:29:15 +0000930 /* now, transform the glyph image if needed */
David Turner54e75742000-11-04 02:52:02 +0000931 if ( internal->transform_flags )
David Turner35db7322000-08-24 12:39:40 +0000932 {
933 /* get renderer */
934 FT_Renderer renderer = ft_lookup_glyph_renderer( slot );
Werner Lembergdeb4e982000-06-29 03:14:25 +0000935
Werner Lemberga929ba92000-06-25 06:47:11 +0000936
David Turner35db7322000-08-24 12:39:40 +0000937 if ( renderer )
Werner Lembergdc72aff2000-11-04 08:33:38 +0000938 error = renderer->clazz->transform_glyph(
939 renderer, slot,
940 &internal->transform_matrix,
941 &internal->transform_delta );
David Turner35db7322000-08-24 12:39:40 +0000942 /* transform advance */
David Turner54e75742000-11-04 02:52:02 +0000943 FT_Vector_Transform( &slot->advance, &internal->transform_matrix );
David Turner35db7322000-08-24 12:39:40 +0000944 }
David Turnerc9ce9e42000-09-15 17:16:49 +0000945 }
David Turnerf0df85b2000-06-22 00:17:42 +0000946
David Turnerc9ce9e42000-09-15 17:16:49 +0000947 /* do we need to render the image now? */
948 if ( !error &&
949 slot->format != ft_glyph_format_bitmap &&
950 slot->format != ft_glyph_format_composite &&
951 load_flags & FT_LOAD_RENDER )
952 {
953 error = FT_Render_Glyph( slot,
954 ( load_flags & FT_LOAD_MONOCHROME )
955 ? ft_render_mode_mono
956 : ft_render_mode_normal );
Werner Lembergd060a752000-07-20 06:57:41 +0000957 }
David Turner5ae831c2000-06-30 01:31:22 +0000958
Werner Lembergdeb4e982000-06-29 03:14:25 +0000959 Exit:
David Turnerf0df85b2000-06-22 00:17:42 +0000960 return error;
961 }
962
963
Werner Lemberg90a03302000-11-07 17:21:11 +0000964 /* documentation is in freetype.h */
965
Werner Lembergf814d0f2001-06-27 16:18:10 +0000966 FT_EXPORT_DEF( FT_Error )
967 FT_Load_Char( FT_Face face,
968 FT_ULong char_code,
969 FT_Int load_flags )
David Turnerf0df85b2000-06-22 00:17:42 +0000970 {
Werner Lembergdeb4e982000-06-29 03:14:25 +0000971 FT_UInt glyph_index;
David Turnerf0df85b2000-06-22 00:17:42 +0000972
Werner Lemberga929ba92000-06-25 06:47:11 +0000973
David Turnerf0df85b2000-06-22 00:17:42 +0000974 if ( !face )
975 return FT_Err_Invalid_Face_Handle;
976
977 glyph_index = (FT_UInt)char_code;
Werner Lemberga929ba92000-06-25 06:47:11 +0000978 if ( face->charmap )
David Turnerf0df85b2000-06-22 00:17:42 +0000979 glyph_index = FT_Get_Char_Index( face, char_code );
980
David Turner5ae831c2000-06-30 01:31:22 +0000981 return FT_Load_Glyph( face, glyph_index, load_flags );
David Turnerf0df85b2000-06-22 00:17:42 +0000982 }
983
984
Werner Lemberg7880dd62000-01-10 17:19:45 +0000985 /* destructor for sizes list */
Werner Lembergf814d0f2001-06-27 16:18:10 +0000986 static void
987 destroy_size( FT_Memory memory,
988 FT_Size size,
989 FT_Driver driver )
Werner Lemberg7880dd62000-01-10 17:19:45 +0000990 {
David Turnerf0df85b2000-06-22 00:17:42 +0000991 /* finalize client-specific data */
Werner Lemberga929ba92000-06-25 06:47:11 +0000992 if ( size->generic.finalizer )
David Turnerf0df85b2000-06-22 00:17:42 +0000993 size->generic.finalizer( size );
994
Werner Lemberg7880dd62000-01-10 17:19:45 +0000995 /* finalize format-specific stuff */
Werner Lemberga929ba92000-06-25 06:47:11 +0000996 if ( driver->clazz->done_size )
David Turnerf0df85b2000-06-22 00:17:42 +0000997 driver->clazz->done_size( size );
998
David Turner54e75742000-11-04 02:52:02 +0000999 FREE( size->internal );
Werner Lemberg7880dd62000-01-10 17:19:45 +00001000 FREE( size );
1001 }
David Turnerd2b1f351999-12-16 23:11:37 +00001002
1003
Werner Lemberg7880dd62000-01-10 17:19:45 +00001004 /* destructor for faces list */
Werner Lembergf814d0f2001-06-27 16:18:10 +00001005 static void
1006 destroy_face( FT_Memory memory,
1007 FT_Face face,
1008 FT_Driver driver )
Werner Lemberg7880dd62000-01-10 17:19:45 +00001009 {
David Turnerf0df85b2000-06-22 00:17:42 +00001010 FT_Driver_Class* clazz = driver->clazz;
1011
Werner Lembergd060a752000-07-20 06:57:41 +00001012
David Turnerc49f69c2000-07-20 03:44:50 +00001013 /* discard auto-hinting data */
1014 if ( face->autohint.finalizer )
1015 face->autohint.finalizer( face->autohint.data );
Werner Lembergeddd9902000-10-12 05:05:40 +00001016
David Turner23bcde12001-10-17 13:48:10 +00001017 /* Discard glyph slots for this face */
1018 /* Beware! FT_Done_GlyphSlot() changes the field `face->glyph' */
Werner Lemberg7880dd62000-01-10 17:19:45 +00001019 while ( face->glyph )
1020 FT_Done_GlyphSlot( face->glyph );
1021
1022 /* Discard all sizes for this face */
1023 FT_List_Finalize( &face->sizes_list,
1024 (FT_List_Destructor)destroy_size,
1025 memory,
1026 driver );
1027 face->size = 0;
1028
Werner Lemberg7880dd62000-01-10 17:19:45 +00001029 /* Now discard client data */
1030 if ( face->generic.finalizer )
1031 face->generic.finalizer( face );
1032
David Turnerf0df85b2000-06-22 00:17:42 +00001033 /* finalize format-specific stuff */
Werner Lemberga929ba92000-06-25 06:47:11 +00001034 if ( clazz->done_face )
1035 clazz->done_face( face );
David Turnerf0df85b2000-06-22 00:17:42 +00001036
1037 /* close the stream for this face if needed */
Werner Lemberg58b17f92000-07-27 23:29:08 +00001038 ft_done_stream(
1039 &face->stream,
1040 ( face->face_flags & FT_FACE_FLAG_EXTERNAL_STREAM ) != 0 );
David Turner7663f222000-02-13 13:37:38 +00001041
Werner Lemberg7880dd62000-01-10 17:19:45 +00001042 /* get rid of it */
David Turner23bcde12001-10-17 13:48:10 +00001043 if ( face->internal )
1044 {
1045 FREE( face->internal->postscript_name );
1046 FREE( face->internal );
1047 }
Werner Lemberg7880dd62000-01-10 17:19:45 +00001048 FREE( face );
1049 }
David Turnerd2b1f351999-12-16 23:11:37 +00001050
1051
Werner Lembergf814d0f2001-06-27 16:18:10 +00001052 static void
1053 Destroy_Driver( FT_Driver driver )
David Turnerd2b1f351999-12-16 23:11:37 +00001054 {
David Turnerd2b1f351999-12-16 23:11:37 +00001055 FT_List_Finalize( &driver->faces_list,
1056 (FT_List_Destructor)destroy_face,
David Turnerf0df85b2000-06-22 00:17:42 +00001057 driver->root.memory,
David Turnerd2b1f351999-12-16 23:11:37 +00001058 driver );
1059
Werner Lembergdeb4e982000-06-29 03:14:25 +00001060 /* check whether we need to drop the driver's glyph loader */
Werner Lemberga929ba92000-06-25 06:47:11 +00001061 if ( FT_DRIVER_USES_OUTLINES( driver ) )
David Turnerf0df85b2000-06-22 00:17:42 +00001062 FT_GlyphLoader_Done( driver->glyph_loader );
David Turnerd2b1f351999-12-16 23:11:37 +00001063 }
1064
1065
Werner Lemberg547a2522000-02-16 08:23:58 +00001066 /*************************************************************************/
1067 /* */
1068 /* <Function> */
1069 /* open_face */
1070 /* */
1071 /* <Description> */
1072 /* This function does some work for FT_Open_Face(). */
1073 /* */
Werner Lembergf814d0f2001-06-27 16:18:10 +00001074 static FT_Error
1075 open_face( FT_Driver driver,
1076 FT_Stream stream,
1077 FT_Long face_index,
1078 FT_Int num_params,
1079 FT_Parameter* params,
1080 FT_Face* aface )
David Turnerd2b1f351999-12-16 23:11:37 +00001081 {
David Turnerf0df85b2000-06-22 00:17:42 +00001082 FT_Memory memory;
1083 FT_Driver_Class* clazz;
1084 FT_Face face = 0;
1085 FT_Error error;
David Turner54e75742000-11-04 02:52:02 +00001086 FT_Face_Internal internal;
David Turnerd2b1f351999-12-16 23:11:37 +00001087
Werner Lemberga929ba92000-06-25 06:47:11 +00001088
David Turnerf0df85b2000-06-22 00:17:42 +00001089 clazz = driver->clazz;
1090 memory = driver->root.memory;
David Turnerd2b1f351999-12-16 23:11:37 +00001091
Werner Lembergdeb4e982000-06-29 03:14:25 +00001092 /* allocate the face object and perform basic initialization */
David Turnerf0df85b2000-06-22 00:17:42 +00001093 if ( ALLOC( face, clazz->face_object_size ) )
David Turnerd2b1f351999-12-16 23:11:37 +00001094 goto Fail;
1095
Werner Lembergdc72aff2000-11-04 08:33:38 +00001096 if ( ALLOC( internal, sizeof ( *internal ) ) )
David Turner54e75742000-11-04 02:52:02 +00001097 goto Fail;
David Turner61d6b2b2001-05-16 17:49:07 +00001098
David Turner54e75742000-11-04 02:52:02 +00001099 face->internal = internal;
1100
1101 face->driver = driver;
1102 face->memory = memory;
1103 face->stream = stream;
David Turnerd2b1f351999-12-16 23:11:37 +00001104
David Turnerf0df85b2000-06-22 00:17:42 +00001105 error = clazz->init_face( stream,
1106 face,
1107 face_index,
1108 num_params,
1109 params );
David Turnerd2b1f351999-12-16 23:11:37 +00001110 if ( error )
1111 goto Fail;
1112
1113 *aface = face;
1114
1115 Fail:
1116 if ( error )
1117 {
David Turnerf0df85b2000-06-22 00:17:42 +00001118 clazz->done_face( face );
David Turner54e75742000-11-04 02:52:02 +00001119 FREE( face->internal );
David Turnerd2b1f351999-12-16 23:11:37 +00001120 FREE( face );
1121 *aface = 0;
1122 }
1123
1124 return error;
1125 }
1126
1127
Werner Lemberg05c21b82000-07-29 20:38:19 +00001128 /* there's a Mac-specific extended implementation of FT_New_Face() */
1129 /* in src/mac/ftmac.c */
1130
Just van Rossum9e830c52000-07-28 01:12:34 +00001131#ifndef macintosh
1132
Werner Lemberg90a03302000-11-07 17:21:11 +00001133 /* documentation is in freetype.h */
1134
Werner Lembergf814d0f2001-06-27 16:18:10 +00001135 FT_EXPORT_DEF( FT_Error )
1136 FT_New_Face( FT_Library library,
1137 const char* pathname,
1138 FT_Long face_index,
1139 FT_Face *aface )
David Turnerd2b1f351999-12-16 23:11:37 +00001140 {
David Turner37379e22000-03-28 11:22:31 +00001141 FT_Open_Args args;
Werner Lemberg547a2522000-02-16 08:23:58 +00001142
Werner Lemberga929ba92000-06-25 06:47:11 +00001143
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001144 /* test for valid `library' and `aface' delayed to FT_Open_Face() */
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001145 if ( !pathname )
1146 return FT_Err_Invalid_Argument;
1147
David Turner4f2c5542000-05-12 10:19:41 +00001148 args.flags = ft_open_pathname;
1149 args.pathname = (char*)pathname;
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001150
David Turnercda32b72000-02-10 16:14:35 +00001151 return FT_Open_Face( library, &args, face_index, aface );
David Turnerd2b1f351999-12-16 23:11:37 +00001152 }
1153
Just van Rossum9e830c52000-07-28 01:12:34 +00001154#endif /* !macintosh */
1155
Werner Lemberg7880dd62000-01-10 17:19:45 +00001156
Werner Lemberg90a03302000-11-07 17:21:11 +00001157 /* documentation is in freetype.h */
1158
Werner Lembergf814d0f2001-06-27 16:18:10 +00001159 FT_EXPORT_DEF( FT_Error )
1160 FT_New_Memory_Face( FT_Library library,
1161 const FT_Byte* file_base,
1162 FT_Long file_size,
1163 FT_Long face_index,
1164 FT_Face *aface )
David Turnerd2b1f351999-12-16 23:11:37 +00001165 {
David Turner37379e22000-03-28 11:22:31 +00001166 FT_Open_Args args;
Werner Lemberg7880dd62000-01-10 17:19:45 +00001167
Werner Lemberga929ba92000-06-25 06:47:11 +00001168
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001169 /* test for valid `library' and `face' delayed to FT_Open_Face() */
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001170 if ( !file_base )
1171 return FT_Err_Invalid_Argument;
1172
David Turner4f2c5542000-05-12 10:19:41 +00001173 args.flags = ft_open_memory;
David Turnercda32b72000-02-10 16:14:35 +00001174 args.memory_base = file_base;
1175 args.memory_size = file_size;
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001176
Werner Lemberg4b680072000-11-07 06:30:29 +00001177 return FT_Open_Face( library, &args, face_index, aface );
David Turnerd2b1f351999-12-16 23:11:37 +00001178 }
1179
Werner Lemberg7880dd62000-01-10 17:19:45 +00001180
Werner Lemberg90a03302000-11-07 17:21:11 +00001181 /* documentation is in freetype.h */
1182
Werner Lembergf814d0f2001-06-27 16:18:10 +00001183 FT_EXPORT_DEF( FT_Error )
1184 FT_Open_Face( FT_Library library,
1185 FT_Open_Args* args,
1186 FT_Long face_index,
1187 FT_Face *aface )
David Turnerd2b1f351999-12-16 23:11:37 +00001188 {
1189 FT_Error error;
1190 FT_Driver driver;
1191 FT_Memory memory;
David Turnercda32b72000-02-10 16:14:35 +00001192 FT_Stream stream;
David Turnerd2b1f351999-12-16 23:11:37 +00001193 FT_Face face = 0;
1194 FT_ListNode node = 0;
David Turnerc5cdf8b2000-07-27 21:40:22 +00001195 FT_Bool external_stream;
Werner Lemberg547a2522000-02-16 08:23:58 +00001196
Werner Lemberg58b17f92000-07-27 23:29:08 +00001197
Werner Lembergf9b03752000-09-11 22:50:13 +00001198 /* test for valid `library' delayed to */
1199 /* ft_new_input_stream() */
David Turnerd2b1f351999-12-16 23:11:37 +00001200
Werner Lembergf9b03752000-09-11 22:50:13 +00001201 if ( !aface || !args )
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001202 return FT_Err_Invalid_Argument;
1203
1204 *aface = 0;
David Turnerd2b1f351999-12-16 23:11:37 +00001205
Werner Lemberg8eb03532001-06-19 23:03:41 +00001206 external_stream = FT_BOOL( ( args->flags & ft_open_stream ) &&
1207 args->stream );
David Turnerc5cdf8b2000-07-27 21:40:22 +00001208
David Turnercda32b72000-02-10 16:14:35 +00001209 /* create input stream */
1210 error = ft_new_input_stream( library, args, &stream );
Werner Lembergdeb4e982000-06-29 03:14:25 +00001211 if ( error )
1212 goto Exit;
David Turnercda32b72000-02-10 16:14:35 +00001213
David Turnerd2b1f351999-12-16 23:11:37 +00001214 memory = library->memory;
1215
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001216 /* If the font driver is specified in the `args' structure, use */
Werner Lembergdeb4e982000-06-29 03:14:25 +00001217 /* it. Otherwise, we scan the list of registered drivers. */
Werner Lembergf9b03752000-09-11 22:50:13 +00001218 if ( ( args->flags & ft_open_driver ) && args->driver )
David Turner7663f222000-02-13 13:37:38 +00001219 {
Werner Lemberga929ba92000-06-25 06:47:11 +00001220 driver = FT_DRIVER( args->driver );
David Turnerf0df85b2000-06-22 00:17:42 +00001221
1222 /* not all modules are drivers, so check... */
Werner Lemberga929ba92000-06-25 06:47:11 +00001223 if ( FT_MODULE_IS_DRIVER( driver ) )
David Turner7663f222000-02-13 13:37:38 +00001224 {
David Turner4f2c5542000-05-12 10:19:41 +00001225 FT_Int num_params = 0;
1226 FT_Parameter* params = 0;
David Turnere49ab252000-05-16 23:44:38 +00001227
Werner Lemberga929ba92000-06-25 06:47:11 +00001228
David Turner4f2c5542000-05-12 10:19:41 +00001229 if ( args->flags & ft_open_params )
1230 {
1231 num_params = args->num_params;
1232 params = args->params;
1233 }
David Turnere49ab252000-05-16 23:44:38 +00001234
David Turner4f2c5542000-05-12 10:19:41 +00001235 error = open_face( driver, stream, face_index,
1236 num_params, params, &face );
Werner Lemberg547a2522000-02-16 08:23:58 +00001237 if ( !error )
1238 goto Success;
David Turner7663f222000-02-13 13:37:38 +00001239 }
1240 else
1241 error = FT_Err_Invalid_Handle;
1242
David Turnerc5cdf8b2000-07-27 21:40:22 +00001243 ft_done_stream( &stream, external_stream );
David Turner7663f222000-02-13 13:37:38 +00001244 goto Fail;
1245 }
Just van Rossum1e5754f2000-03-02 10:52:57 +00001246 else
David Turnerd2b1f351999-12-16 23:11:37 +00001247 {
1248 /* check each font driver for an appropriate format */
David Turnerf0df85b2000-06-22 00:17:42 +00001249 FT_Module* cur = library->modules;
1250 FT_Module* limit = cur + library->num_modules;
David Turnerd2b1f351999-12-16 23:11:37 +00001251
Werner Lemberga929ba92000-06-25 06:47:11 +00001252
David Turnerd2b1f351999-12-16 23:11:37 +00001253 for ( ; cur < limit; cur++ )
1254 {
David Turnerf0df85b2000-06-22 00:17:42 +00001255 /* not all modules are font drivers, so check... */
Werner Lemberga929ba92000-06-25 06:47:11 +00001256 if ( FT_MODULE_IS_DRIVER( cur[0] ) )
David Turnerd2b1f351999-12-16 23:11:37 +00001257 {
David Turner4f2c5542000-05-12 10:19:41 +00001258 FT_Int num_params = 0;
1259 FT_Parameter* params = 0;
David Turnere49ab252000-05-16 23:44:38 +00001260
Werner Lembergdeb4e982000-06-29 03:14:25 +00001261
Werner Lemberga929ba92000-06-25 06:47:11 +00001262 driver = FT_DRIVER( cur[0] );
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001263
David Turner4f2c5542000-05-12 10:19:41 +00001264 if ( args->flags & ft_open_params )
1265 {
1266 num_params = args->num_params;
1267 params = args->params;
1268 }
David Turnere49ab252000-05-16 23:44:38 +00001269
David Turner4f2c5542000-05-12 10:19:41 +00001270 error = open_face( driver, stream, face_index,
1271 num_params, params, &face );
David Turnerd2b1f351999-12-16 23:11:37 +00001272 if ( !error )
1273 goto Success;
1274
Werner Lemberg79860702001-06-08 21:17:29 +00001275 if ( FT_ERROR_BASE( error ) != FT_Err_Unknown_File_Format )
David Turnerebe85f52001-05-11 14:25:57 +00001276 goto Fail2;
David Turnerd2b1f351999-12-16 23:11:37 +00001277 }
1278 }
1279
1280 /* no driver is able to handle this format */
1281 error = FT_Err_Unknown_File_Format;
David Turnerebe85f52001-05-11 14:25:57 +00001282
1283 Fail2:
1284 ft_done_stream( &stream, external_stream );
David Turnercda32b72000-02-10 16:14:35 +00001285 goto Fail;
David Turnerd2b1f351999-12-16 23:11:37 +00001286 }
1287
1288 Success:
Werner Lembergf9b03752000-09-11 22:50:13 +00001289 FT_TRACE4(( "FT_Open_Face: New face object, adding to list\n" ));
David Turnerd2b1f351999-12-16 23:11:37 +00001290
Werner Lembergdeb4e982000-06-29 03:14:25 +00001291 /* set the FT_FACE_FLAG_EXTERNAL_STREAM bit for FT_Done_Face */
David Turnerc5cdf8b2000-07-27 21:40:22 +00001292 if ( external_stream )
David Turnerf0df85b2000-06-22 00:17:42 +00001293 face->face_flags |= FT_FACE_FLAG_EXTERNAL_STREAM;
1294
Werner Lemberg547a2522000-02-16 08:23:58 +00001295 /* add the face object to its driver's list */
David Turnerd2b1f351999-12-16 23:11:37 +00001296 if ( ALLOC( node, sizeof ( *node ) ) )
1297 goto Fail;
1298
1299 node->data = face;
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001300 /* don't assume driver is the same as face->driver, so use */
1301 /* face->driver instead. */
Just van Rossum7eef5362000-03-05 16:07:58 +00001302 FT_List_Add( &face->driver->faces_list, node );
David Turnerd2b1f351999-12-16 23:11:37 +00001303
Werner Lemberg547a2522000-02-16 08:23:58 +00001304 /* now allocate a glyph slot object for the face */
David Turnerd2b1f351999-12-16 23:11:37 +00001305 {
1306 FT_GlyphSlot slot;
1307
Werner Lemberg547a2522000-02-16 08:23:58 +00001308
David Turnerd2b1f351999-12-16 23:11:37 +00001309 FT_TRACE4(( "FT_Open_Face: Creating glyph slot\n" ));
Werner Lembergdeb4e982000-06-29 03:14:25 +00001310
David Turnerd2b1f351999-12-16 23:11:37 +00001311 error = FT_New_GlyphSlot( face, &slot );
Werner Lembergdeb4e982000-06-29 03:14:25 +00001312 if ( error )
1313 goto Fail;
1314
David Turnerf0df85b2000-06-22 00:17:42 +00001315 face->glyph = slot;
David Turnerd2b1f351999-12-16 23:11:37 +00001316 }
Werner Lemberg7880dd62000-01-10 17:19:45 +00001317
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001318 /* finally, allocate a size object for the face */
David Turnerd2b1f351999-12-16 23:11:37 +00001319 {
1320 FT_Size size;
1321
Werner Lemberg547a2522000-02-16 08:23:58 +00001322
David Turnerd2b1f351999-12-16 23:11:37 +00001323 FT_TRACE4(( "FT_Open_Face: Creating size object\n" ));
Werner Lembergdeb4e982000-06-29 03:14:25 +00001324
David Turnerd2b1f351999-12-16 23:11:37 +00001325 error = FT_New_Size( face, &size );
Werner Lembergdeb4e982000-06-29 03:14:25 +00001326 if ( error )
1327 goto Fail;
1328
David Turnerf0df85b2000-06-22 00:17:42 +00001329 face->size = size;
David Turnerd2b1f351999-12-16 23:11:37 +00001330 }
Werner Lemberg7880dd62000-01-10 17:19:45 +00001331
David Turner54e75742000-11-04 02:52:02 +00001332 /* initialize internal face data */
1333 {
1334 FT_Face_Internal internal = face->internal;
David Turner61d6b2b2001-05-16 17:49:07 +00001335
David Turner37379e22000-03-28 11:22:31 +00001336
David Turner54e75742000-11-04 02:52:02 +00001337 internal->transform_matrix.xx = 0x10000L;
1338 internal->transform_matrix.xy = 0;
1339 internal->transform_matrix.yx = 0;
1340 internal->transform_matrix.yy = 0x10000L;
David Turner61d6b2b2001-05-16 17:49:07 +00001341
David Turner54e75742000-11-04 02:52:02 +00001342 internal->transform_delta.x = 0;
1343 internal->transform_delta.y = 0;
1344 }
David Turner37379e22000-03-28 11:22:31 +00001345
David Turnerd2b1f351999-12-16 23:11:37 +00001346 *aface = face;
1347 goto Exit;
1348
1349 Fail:
1350 FT_Done_Face( face );
1351
David Turnerd2b1f351999-12-16 23:11:37 +00001352 Exit:
1353 FT_TRACE4(( "FT_Open_Face: Return %d\n", error ));
Werner Lembergdeb4e982000-06-29 03:14:25 +00001354
David Turnerd2b1f351999-12-16 23:11:37 +00001355 return error;
1356 }
1357
1358
Werner Lemberg90a03302000-11-07 17:21:11 +00001359 /* documentation is in freetype.h */
1360
Werner Lembergf814d0f2001-06-27 16:18:10 +00001361 FT_EXPORT_DEF( FT_Error )
1362 FT_Attach_File( FT_Face face,
1363 const char* filepathname )
David Turner7663f222000-02-13 13:37:38 +00001364 {
David Turner37379e22000-03-28 11:22:31 +00001365 FT_Open_Args open;
David Turner7663f222000-02-13 13:37:38 +00001366
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001367
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001368 /* test for valid `face' delayed to FT_Attach_Stream() */
1369
1370 if ( !filepathname )
1371 return FT_Err_Invalid_Argument;
1372
David Turner4f2c5542000-05-12 10:19:41 +00001373 open.flags = ft_open_pathname;
1374 open.pathname = (char*)filepathname;
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001375
David Turner7663f222000-02-13 13:37:38 +00001376 return FT_Attach_Stream( face, &open );
1377 }
Werner Lemberg547a2522000-02-16 08:23:58 +00001378
David Turnere49ab252000-05-16 23:44:38 +00001379
Werner Lemberg90a03302000-11-07 17:21:11 +00001380 /* documentation is in freetype.h */
1381
Werner Lembergf814d0f2001-06-27 16:18:10 +00001382 FT_EXPORT_DEF( FT_Error )
1383 FT_Attach_Stream( FT_Face face,
1384 FT_Open_Args* parameters )
David Turner7663f222000-02-13 13:37:38 +00001385 {
1386 FT_Stream stream;
1387 FT_Error error;
1388 FT_Driver driver;
David Turnere49ab252000-05-16 23:44:38 +00001389
David Turnerf0df85b2000-06-22 00:17:42 +00001390 FT_Driver_Class* clazz;
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001391
Werner Lemberga929ba92000-06-25 06:47:11 +00001392
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001393 /* test for valid `parameters' delayed to ft_new_input_stream() */
1394
1395 if ( !face )
1396 return FT_Err_Invalid_Face_Handle;
David Turnere49ab252000-05-16 23:44:38 +00001397
David Turner7663f222000-02-13 13:37:38 +00001398 driver = face->driver;
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001399 if ( !driver )
1400 return FT_Err_Invalid_Driver_Handle;
1401
David Turnerf0df85b2000-06-22 00:17:42 +00001402 error = ft_new_input_stream( driver->root.library, parameters, &stream );
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001403 if ( error )
1404 goto Exit;
David Turnere49ab252000-05-16 23:44:38 +00001405
David Turner7663f222000-02-13 13:37:38 +00001406 /* we implement FT_Attach_Stream in each driver through the */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001407 /* `attach_file' interface */
1408
David Turner7663f222000-02-13 13:37:38 +00001409 error = FT_Err_Unimplemented_Feature;
David Turnerf0df85b2000-06-22 00:17:42 +00001410 clazz = driver->clazz;
Werner Lemberga929ba92000-06-25 06:47:11 +00001411 if ( clazz->attach_file )
David Turnerf0df85b2000-06-22 00:17:42 +00001412 error = clazz->attach_file( face, stream );
David Turnere49ab252000-05-16 23:44:38 +00001413
David Turner7663f222000-02-13 13:37:38 +00001414 /* close the attached stream */
David Turnerc5cdf8b2000-07-27 21:40:22 +00001415 ft_done_stream( &stream,
Werner Lemberg58b17f92000-07-27 23:29:08 +00001416 (FT_Bool)( parameters->stream &&
1417 ( parameters->flags & ft_open_stream ) ) );
David Turnere49ab252000-05-16 23:44:38 +00001418
David Turner7663f222000-02-13 13:37:38 +00001419 Exit:
1420 return error;
1421 }
1422
1423
Werner Lemberg90a03302000-11-07 17:21:11 +00001424 /* documentation is in freetype.h */
1425
Werner Lembergf814d0f2001-06-27 16:18:10 +00001426 FT_EXPORT_DEF( FT_Error )
1427 FT_Done_Face( FT_Face face )
David Turnerd2b1f351999-12-16 23:11:37 +00001428 {
Werner Lemberga929ba92000-06-25 06:47:11 +00001429 FT_Error error;
1430 FT_Driver driver;
1431 FT_Memory memory;
1432 FT_ListNode node;
1433
David Turnerd2b1f351999-12-16 23:11:37 +00001434
David Turnerf0df85b2000-06-22 00:17:42 +00001435 error = FT_Err_Invalid_Face_Handle;
1436 if ( face && face->driver )
David Turnerd2b1f351999-12-16 23:11:37 +00001437 {
David Turnerf0df85b2000-06-22 00:17:42 +00001438 driver = face->driver;
1439 memory = driver->root.memory;
Werner Lembergdeb4e982000-06-29 03:14:25 +00001440
David Turnerf0df85b2000-06-22 00:17:42 +00001441 /* find face in driver's list */
1442 node = FT_List_Find( &driver->faces_list, face );
1443 if ( node )
1444 {
1445 /* remove face object from the driver's list */
1446 FT_List_Remove( &driver->faces_list, node );
1447 FREE( node );
Werner Lembergdeb4e982000-06-29 03:14:25 +00001448
David Turnerf0df85b2000-06-22 00:17:42 +00001449 /* now destroy the object proper */
1450 destroy_face( memory, face, driver );
1451 error = FT_Err_Ok;
1452 }
David Turnerd2b1f351999-12-16 23:11:37 +00001453 }
David Turnerd2b1f351999-12-16 23:11:37 +00001454 return error;
1455 }
1456
1457
Werner Lemberg90a03302000-11-07 17:21:11 +00001458 /* documentation is in ftobjs.h */
1459
Werner Lembergf814d0f2001-06-27 16:18:10 +00001460 FT_EXPORT_DEF( FT_Error )
1461 FT_New_Size( FT_Face face,
1462 FT_Size *asize )
David Turnerd2b1f351999-12-16 23:11:37 +00001463 {
David Turnerf0df85b2000-06-22 00:17:42 +00001464 FT_Error error;
1465 FT_Memory memory;
1466 FT_Driver driver;
1467 FT_Driver_Class* clazz;
David Turnerd2b1f351999-12-16 23:11:37 +00001468
David Turnerf0df85b2000-06-22 00:17:42 +00001469 FT_Size size = 0;
1470 FT_ListNode node = 0;
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001471
Werner Lemberga929ba92000-06-25 06:47:11 +00001472
Werner Lembergb48a6092000-07-09 19:15:30 +00001473 if ( !face )
1474 return FT_Err_Invalid_Face_Handle;
1475
1476 if ( !asize )
1477 return FT_Err_Invalid_Size_Handle;
1478
1479 if ( !face->driver )
1480 return FT_Err_Invalid_Driver_Handle;
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001481
Werner Lembergdeb4e982000-06-29 03:14:25 +00001482 *asize = 0;
1483
David Turnerf0df85b2000-06-22 00:17:42 +00001484 driver = face->driver;
1485 clazz = driver->clazz;
1486 memory = face->memory;
David Turnerd2b1f351999-12-16 23:11:37 +00001487
1488 /* Allocate new size object and perform basic initialisation */
David Turnerf0df85b2000-06-22 00:17:42 +00001489 if ( ALLOC( size, clazz->size_object_size ) ||
1490 ALLOC( node, sizeof ( FT_ListNodeRec ) ) )
David Turnerd2b1f351999-12-16 23:11:37 +00001491 goto Exit;
1492
1493 size->face = face;
David Turner61d6b2b2001-05-16 17:49:07 +00001494
David Turner54e75742000-11-04 02:52:02 +00001495 /* for now, do not use any internal fields in size objects */
1496 size->internal = 0;
David Turnerd2b1f351999-12-16 23:11:37 +00001497
Werner Lemberga929ba92000-06-25 06:47:11 +00001498 if ( clazz->init_size )
David Turnerf0df85b2000-06-22 00:17:42 +00001499 error = clazz->init_size( size );
David Turnerd2b1f351999-12-16 23:11:37 +00001500
1501 /* in case of success, add to the face's list */
1502 if ( !error )
1503 {
1504 *asize = size;
1505 node->data = size;
1506 FT_List_Add( &face->sizes_list, node );
David Turnerd2b1f351999-12-16 23:11:37 +00001507 }
1508
1509 Exit:
1510 if ( error )
1511 {
1512 FREE( node );
1513 FREE( size );
1514 }
1515
1516 return error;
1517 }
1518
1519
Werner Lemberg90a03302000-11-07 17:21:11 +00001520 /* documentation is in ftobjs.h */
1521
Werner Lembergf814d0f2001-06-27 16:18:10 +00001522 FT_EXPORT_DEF( FT_Error )
1523 FT_Done_Size( FT_Size size )
David Turnerd2b1f351999-12-16 23:11:37 +00001524 {
1525 FT_Error error;
1526 FT_Driver driver;
1527 FT_Memory memory;
1528 FT_Face face;
1529 FT_ListNode node;
1530
1531
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001532 if ( !size )
David Turnerd2b1f351999-12-16 23:11:37 +00001533 return FT_Err_Invalid_Size_Handle;
1534
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001535 face = size->face;
1536 if ( !face )
1537 return FT_Err_Invalid_Face_Handle;
1538
1539 driver = face->driver;
David Turnerd2b1f351999-12-16 23:11:37 +00001540 if ( !driver )
1541 return FT_Err_Invalid_Driver_Handle;
1542
David Turnerf0df85b2000-06-22 00:17:42 +00001543 memory = driver->root.memory;
David Turnerd2b1f351999-12-16 23:11:37 +00001544
1545 error = FT_Err_Ok;
David Turnerd2b1f351999-12-16 23:11:37 +00001546 node = FT_List_Find( &face->sizes_list, size );
1547 if ( node )
1548 {
1549 FT_List_Remove( &face->sizes_list, node );
1550 FREE( node );
1551
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001552 if ( face->size == size )
David Turnerd2b1f351999-12-16 23:11:37 +00001553 {
1554 face->size = 0;
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001555 if ( face->sizes_list.head )
David Turnerd2b1f351999-12-16 23:11:37 +00001556 face->size = (FT_Size)(face->sizes_list.head->data);
1557 }
1558
1559 destroy_size( memory, size, driver );
1560 }
1561 else
1562 error = FT_Err_Invalid_Size_Handle;
1563
Werner Lembergcf24d512001-06-18 14:23:45 +00001564 return error;
David Turnerd2b1f351999-12-16 23:11:37 +00001565 }
1566
1567
Werner Lembergf814d0f2001-06-27 16:18:10 +00001568 static void
1569 ft_recompute_scaled_metrics( FT_Face face,
1570 FT_Size_Metrics* metrics )
Werner Lembergdeb4e982000-06-29 03:14:25 +00001571 {
Werner Lemberga929ba92000-06-25 06:47:11 +00001572 /* Compute root ascender, descender, test height, and max_advance */
Werner Lembergdeb4e982000-06-29 03:14:25 +00001573
Werner Lemberga929ba92000-06-25 06:47:11 +00001574 metrics->ascender = ( FT_MulFix( face->ascender,
1575 metrics->y_scale ) + 32 ) & -64;
1576
1577 metrics->descender = ( FT_MulFix( face->descender,
1578 metrics->y_scale ) + 32 ) & -64;
1579
1580 metrics->height = ( FT_MulFix( face->height,
1581 metrics->y_scale ) + 32 ) & -64;
1582
1583 metrics->max_advance = ( FT_MulFix( face->max_advance_width,
1584 metrics->x_scale ) + 32 ) & -64;
1585 }
1586
1587
Werner Lemberg90a03302000-11-07 17:21:11 +00001588 /* documentation is in freetype.h */
1589
Werner Lembergf814d0f2001-06-27 16:18:10 +00001590 FT_EXPORT_DEF( FT_Error )
1591 FT_Set_Char_Size( FT_Face face,
1592 FT_F26Dot6 char_width,
1593 FT_F26Dot6 char_height,
1594 FT_UInt horz_resolution,
1595 FT_UInt vert_resolution )
David Turnerd2b1f351999-12-16 23:11:37 +00001596 {
David Turnerf0df85b2000-06-22 00:17:42 +00001597 FT_Error error = FT_Err_Ok;
1598 FT_Driver driver;
David Turnerf0df85b2000-06-22 00:17:42 +00001599 FT_Driver_Class* clazz;
1600 FT_Size_Metrics* metrics;
1601 FT_Long dim_x, dim_y;
David Turnerd2b1f351999-12-16 23:11:37 +00001602
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001603
David Turnerf0df85b2000-06-22 00:17:42 +00001604 if ( !face || !face->size || !face->driver )
David Turnerd2b1f351999-12-16 23:11:37 +00001605 return FT_Err_Invalid_Face_Handle;
1606
David Turnerf0df85b2000-06-22 00:17:42 +00001607 driver = face->driver;
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001608 metrics = &face->size->metrics;
1609
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001610 if ( !char_width )
David Turnerd2b1f351999-12-16 23:11:37 +00001611 char_width = char_height;
Werner Lembergdeb4e982000-06-29 03:14:25 +00001612
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001613 else if ( !char_height )
David Turnerd2b1f351999-12-16 23:11:37 +00001614 char_height = char_width;
Werner Lemberg7880dd62000-01-10 17:19:45 +00001615
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001616 if ( !horz_resolution )
David Turnerd2b1f351999-12-16 23:11:37 +00001617 horz_resolution = 72;
Werner Lembergdeb4e982000-06-29 03:14:25 +00001618
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001619 if ( !vert_resolution )
David Turnerd2b1f351999-12-16 23:11:37 +00001620 vert_resolution = 72;
1621
David Turnerf0df85b2000-06-22 00:17:42 +00001622 driver = face->driver;
1623 clazz = driver->clazz;
David Turnerd2b1f351999-12-16 23:11:37 +00001624
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001625 /* default processing -- this can be overridden by the driver */
Werner Lembergdeb4e982000-06-29 03:14:25 +00001626 if ( char_width < 1 * 64 )
1627 char_width = 1 * 64;
1628 if ( char_height < 1 * 64 )
1629 char_height = 1 * 64;
David Turnerd42c68e2000-01-27 13:56:02 +00001630
1631 /* Compute pixel sizes in 26.6 units */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001632 dim_x = ( ( ( char_width * horz_resolution ) / 72 ) + 32 ) & -64;
1633 dim_y = ( ( ( char_height * vert_resolution ) / 72 ) + 32 ) & -64;
David Turnerd42c68e2000-01-27 13:56:02 +00001634
Werner Lembergdeb4e982000-06-29 03:14:25 +00001635 metrics->x_ppem = (FT_UShort)( dim_x >> 6 );
1636 metrics->y_ppem = (FT_UShort)( dim_y >> 6 );
David Turnerd42c68e2000-01-27 13:56:02 +00001637
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001638 metrics->x_scale = 0x10000L;
1639 metrics->y_scale = 0x10000L;
1640
1641 if ( face->face_flags & FT_FACE_FLAG_SCALABLE )
David Turnerd42c68e2000-01-27 13:56:02 +00001642 {
1643 metrics->x_scale = FT_DivFix( dim_x, face->units_per_EM );
1644 metrics->y_scale = FT_DivFix( dim_y, face->units_per_EM );
David Turnerd42c68e2000-01-27 13:56:02 +00001645
David Turner9b3d1c72000-07-07 19:47:34 +00001646 ft_recompute_scaled_metrics( face, metrics );
1647 }
David Turnerf0df85b2000-06-22 00:17:42 +00001648
Werner Lemberga929ba92000-06-25 06:47:11 +00001649 if ( clazz->set_char_sizes )
David Turnerf0df85b2000-06-22 00:17:42 +00001650 error = clazz->set_char_sizes( face->size,
1651 char_width,
1652 char_height,
1653 horz_resolution,
1654 vert_resolution );
David Turnerd2b1f351999-12-16 23:11:37 +00001655 return error;
1656 }
1657
1658
Werner Lemberg90a03302000-11-07 17:21:11 +00001659 /* documentation is in freetype.h */
1660
Werner Lembergf814d0f2001-06-27 16:18:10 +00001661 FT_EXPORT_DEF( FT_Error )
1662 FT_Set_Pixel_Sizes( FT_Face face,
1663 FT_UInt pixel_width,
1664 FT_UInt pixel_height )
David Turnerd2b1f351999-12-16 23:11:37 +00001665 {
David Turnerf0df85b2000-06-22 00:17:42 +00001666 FT_Error error = FT_Err_Ok;
1667 FT_Driver driver;
David Turnerf0df85b2000-06-22 00:17:42 +00001668 FT_Driver_Class* clazz;
1669 FT_Size_Metrics* metrics = &face->size->metrics;
David Turnerd2b1f351999-12-16 23:11:37 +00001670
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001671
David Turnerf0df85b2000-06-22 00:17:42 +00001672 if ( !face || !face->size || !face->driver )
David Turnerd2b1f351999-12-16 23:11:37 +00001673 return FT_Err_Invalid_Face_Handle;
1674
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001675 driver = face->driver;
David Turnerf0df85b2000-06-22 00:17:42 +00001676 clazz = driver->clazz;
David Turnerd2b1f351999-12-16 23:11:37 +00001677
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001678 /* default processing -- this can be overridden by the driver */
1679 if ( pixel_width == 0 )
David Turner11187202000-05-26 17:13:23 +00001680 pixel_width = pixel_height;
David Turnerf0df85b2000-06-22 00:17:42 +00001681
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001682 else if ( pixel_height == 0 )
David Turner11187202000-05-26 17:13:23 +00001683 pixel_height = pixel_width;
Werner Lembergeb81e372000-06-03 06:03:11 +00001684
Werner Lembergdeb4e982000-06-29 03:14:25 +00001685 if ( pixel_width < 1 )
1686 pixel_width = 1;
1687 if ( pixel_height < 1 )
1688 pixel_height = 1;
David Turnerd2b1f351999-12-16 23:11:37 +00001689
David Turner8edbcab2001-06-19 08:28:24 +00001690 metrics->x_ppem = (FT_UShort)pixel_width;
1691 metrics->y_ppem = (FT_UShort)pixel_height;
David Turnerd42c68e2000-01-27 13:56:02 +00001692
1693 if ( face->face_flags & FT_FACE_FLAG_SCALABLE )
1694 {
1695 metrics->x_scale = FT_DivFix( metrics->x_ppem << 6,
1696 face->units_per_EM );
1697
1698 metrics->y_scale = FT_DivFix( metrics->y_ppem << 6,
1699 face->units_per_EM );
Werner Lemberg7fa51b52000-07-08 19:51:42 +00001700
David Turner9b3d1c72000-07-07 19:47:34 +00001701 ft_recompute_scaled_metrics( face, metrics );
David Turnerd42c68e2000-01-27 13:56:02 +00001702 }
1703
Werner Lemberga929ba92000-06-25 06:47:11 +00001704 if ( clazz->set_pixel_sizes )
David Turnerf0df85b2000-06-22 00:17:42 +00001705 error = clazz->set_pixel_sizes( face->size,
1706 pixel_width,
1707 pixel_height );
David Turnerd2b1f351999-12-16 23:11:37 +00001708 return error;
1709 }
1710
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001711
Werner Lemberg90a03302000-11-07 17:21:11 +00001712 /* documentation is in freetype.h */
1713
Werner Lembergf814d0f2001-06-27 16:18:10 +00001714 FT_EXPORT_DEF( FT_Error )
1715 FT_Get_Kerning( FT_Face face,
1716 FT_UInt left_glyph,
1717 FT_UInt right_glyph,
1718 FT_UInt kern_mode,
1719 FT_Vector *akerning )
David Turnerd2b1f351999-12-16 23:11:37 +00001720 {
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001721 FT_Error error = FT_Err_Ok;
David Turnerd2b1f351999-12-16 23:11:37 +00001722 FT_Driver driver;
David Turnerd2b1f351999-12-16 23:11:37 +00001723
Werner Lemberga8bbc262000-07-01 14:06:46 +00001724
David Turnerd2b1f351999-12-16 23:11:37 +00001725 if ( !face )
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001726 return FT_Err_Invalid_Face_Handle;
1727
Werner Lemberg4b680072000-11-07 06:30:29 +00001728 if ( !akerning )
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001729 return FT_Err_Invalid_Argument;
David Turnerd2b1f351999-12-16 23:11:37 +00001730
1731 driver = face->driver;
David Turnerd2b1f351999-12-16 23:11:37 +00001732
Werner Lemberg4b680072000-11-07 06:30:29 +00001733 akerning->x = 0;
1734 akerning->y = 0;
Werner Lemberg5aa646c2000-07-14 06:16:47 +00001735
David Turnerf0df85b2000-06-22 00:17:42 +00001736 if ( driver->clazz->get_kerning )
David Turnerd2b1f351999-12-16 23:11:37 +00001737 {
David Turnerf0df85b2000-06-22 00:17:42 +00001738 error = driver->clazz->get_kerning( face,
Werner Lemberga929ba92000-06-25 06:47:11 +00001739 left_glyph,
1740 right_glyph,
Werner Lemberg4b680072000-11-07 06:30:29 +00001741 akerning );
Werner Lemberg5aa646c2000-07-14 06:16:47 +00001742 if ( !error )
David Turnerf9ca2bb2000-06-30 23:12:55 +00001743 {
Werner Lemberg5aa646c2000-07-14 06:16:47 +00001744 if ( kern_mode != ft_kerning_unscaled )
David Turnerf9ca2bb2000-06-30 23:12:55 +00001745 {
Werner Lemberg4b680072000-11-07 06:30:29 +00001746 akerning->x = FT_MulFix( akerning->x, face->size->metrics.x_scale );
1747 akerning->y = FT_MulFix( akerning->y, face->size->metrics.y_scale );
Werner Lemberg5aa646c2000-07-14 06:16:47 +00001748
1749 if ( kern_mode != ft_kerning_unfitted )
1750 {
Werner Lemberg4b680072000-11-07 06:30:29 +00001751 akerning->x = ( akerning->x + 32 ) & -64;
1752 akerning->y = ( akerning->y + 32 ) & -64;
Werner Lemberg5aa646c2000-07-14 06:16:47 +00001753 }
David Turnerf9ca2bb2000-06-30 23:12:55 +00001754 }
1755 }
1756 }
David Turnerd2b1f351999-12-16 23:11:37 +00001757
David Turnerd2b1f351999-12-16 23:11:37 +00001758 return error;
1759 }
1760
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001761
Werner Lemberg90a03302000-11-07 17:21:11 +00001762 /* documentation is in freetype.h */
1763
Werner Lembergf814d0f2001-06-27 16:18:10 +00001764 FT_EXPORT_DEF( FT_Error )
1765 FT_Select_Charmap( FT_Face face,
1766 FT_Encoding encoding )
David Turner0a29c692000-05-12 17:09:38 +00001767 {
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001768 FT_CharMap* cur;
1769 FT_CharMap* limit;
David Turnere49ab252000-05-16 23:44:38 +00001770
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001771
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001772 if ( !face )
1773 return FT_Err_Invalid_Face_Handle;
1774
1775 cur = face->charmaps;
1776 if ( !cur )
1777 return FT_Err_Invalid_CharMap_Handle;
1778
1779 limit = cur + face->num_charmaps;
1780
David Turner0a29c692000-05-12 17:09:38 +00001781 for ( ; cur < limit; cur++ )
1782 {
1783 if ( cur[0]->encoding == encoding )
1784 {
1785 face->charmap = cur[0];
1786 return 0;
1787 }
1788 }
Werner Lembergdeb4e982000-06-29 03:14:25 +00001789
David Turner0a29c692000-05-12 17:09:38 +00001790 return FT_Err_Invalid_Argument;
1791 }
1792
1793
Werner Lemberg90a03302000-11-07 17:21:11 +00001794 /* documentation is in freetype.h */
1795
Werner Lembergf814d0f2001-06-27 16:18:10 +00001796 FT_EXPORT_DEF( FT_Error )
1797 FT_Set_Charmap( FT_Face face,
1798 FT_CharMap charmap )
David Turner0a29c692000-05-12 17:09:38 +00001799 {
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001800 FT_CharMap* cur;
1801 FT_CharMap* limit;
David Turnere49ab252000-05-16 23:44:38 +00001802
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001803
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001804 if ( !face )
1805 return FT_Err_Invalid_Face_Handle;
1806
1807 cur = face->charmaps;
1808 if ( !cur )
1809 return FT_Err_Invalid_CharMap_Handle;
1810
1811 limit = cur + face->num_charmaps;
1812
David Turner0a29c692000-05-12 17:09:38 +00001813 for ( ; cur < limit; cur++ )
1814 {
1815 if ( cur[0] == charmap )
1816 {
1817 face->charmap = cur[0];
1818 return 0;
1819 }
1820 }
1821 return FT_Err_Invalid_Argument;
1822 }
David Turnerd2b1f351999-12-16 23:11:37 +00001823
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001824
Werner Lemberg90a03302000-11-07 17:21:11 +00001825 /* documentation is in freetype.h */
1826
Werner Lembergf814d0f2001-06-27 16:18:10 +00001827 FT_EXPORT_DEF( FT_UInt )
1828 FT_Get_Char_Index( FT_Face face,
1829 FT_ULong charcode )
David Turnerd2b1f351999-12-16 23:11:37 +00001830 {
1831 FT_UInt result;
1832 FT_Driver driver;
1833
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001834
David Turnerd2b1f351999-12-16 23:11:37 +00001835 result = 0;
1836 if ( face && face->charmap )
1837 {
1838 driver = face->driver;
David Turnerf0df85b2000-06-22 00:17:42 +00001839 result = driver->clazz->get_char_index( face->charmap, charcode );
David Turnerd2b1f351999-12-16 23:11:37 +00001840 }
1841 return result;
1842 }
1843
David Turnerd2b1f351999-12-16 23:11:37 +00001844
Werner Lemberg90a03302000-11-07 17:21:11 +00001845 /* documentation is in freetype.h */
1846
Tom Kacvinskyff2714f2001-08-08 10:58:08 +00001847 FT_EXPORT_DEF( FT_UInt )
1848 FT_Get_Name_Index( FT_Face face,
1849 FT_String* glyph_name )
1850 {
1851 FT_UInt result = 0;
1852
1853
1854 if ( face && FT_HAS_GLYPH_NAMES( face ) )
1855 {
1856 /* now, lookup for glyph name */
Werner Lemberg5dea4442001-08-13 11:44:29 +00001857 FT_Driver driver = face->driver;
1858 FT_Module_Class* clazz = FT_MODULE_CLASS( driver );
Tom Kacvinskyff2714f2001-08-08 10:58:08 +00001859
1860
1861 if ( clazz->get_interface )
1862 {
1863 FT_Name_Index_Requester requester;
1864
1865
1866 requester = (FT_Name_Index_Requester)clazz->get_interface(
1867 FT_MODULE( driver ), "name_index" );
1868 if ( requester )
1869 result = requester( face, glyph_name );
1870 }
1871 }
1872
1873 return result;
1874 }
1875
Werner Lembergaef3fc82001-12-17 16:21:22 +00001876
Tom Kacvinskyff2714f2001-08-08 10:58:08 +00001877 /* documentation is in freetype.h */
1878
Werner Lembergf814d0f2001-06-27 16:18:10 +00001879 FT_EXPORT_DEF( FT_Error )
1880 FT_Get_Glyph_Name( FT_Face face,
1881 FT_UInt glyph_index,
1882 FT_Pointer buffer,
1883 FT_UInt buffer_max )
David Turner6930b452000-07-19 17:13:03 +00001884 {
1885 FT_Error error = FT_Err_Invalid_Argument;
Werner Lembergeddd9902000-10-12 05:05:40 +00001886
Werner Lembergd060a752000-07-20 06:57:41 +00001887
David Turner6930b452000-07-19 17:13:03 +00001888 /* clean up buffer */
Werner Lembergd060a752000-07-20 06:57:41 +00001889 if ( buffer && buffer_max > 0 )
David Turner6930b452000-07-19 17:13:03 +00001890 ((FT_Byte*)buffer)[0] = 0;
Werner Lembergeddd9902000-10-12 05:05:40 +00001891
Werner Lembergd060a752000-07-20 06:57:41 +00001892 if ( face &&
1893 glyph_index < (FT_UInt)face->num_glyphs &&
1894 FT_HAS_GLYPH_NAMES( face ) )
David Turner6930b452000-07-19 17:13:03 +00001895 {
1896 /* now, lookup for glyph name */
1897 FT_Driver driver = face->driver;
Werner Lembergd060a752000-07-20 06:57:41 +00001898 FT_Module_Class* clazz = FT_MODULE_CLASS( driver );
David Turner6930b452000-07-19 17:13:03 +00001899
Werner Lembergd060a752000-07-20 06:57:41 +00001900
1901 if ( clazz->get_interface )
David Turner6930b452000-07-19 17:13:03 +00001902 {
1903 FT_Glyph_Name_Requester requester;
Werner Lembergeddd9902000-10-12 05:05:40 +00001904
Werner Lembergd060a752000-07-20 06:57:41 +00001905
1906 requester = (FT_Glyph_Name_Requester)clazz->get_interface(
1907 FT_MODULE( driver ), "glyph_name" );
1908 if ( requester )
David Turner6930b452000-07-19 17:13:03 +00001909 error = requester( face, glyph_index, buffer, buffer_max );
1910 }
1911 }
Werner Lembergd060a752000-07-20 06:57:41 +00001912
David Turner6930b452000-07-19 17:13:03 +00001913 return error;
Werner Lembergeddd9902000-10-12 05:05:40 +00001914 }
David Turner6930b452000-07-19 17:13:03 +00001915
1916
David Turner23bcde12001-10-17 13:48:10 +00001917 /* documentation is in freetype.h */
1918
1919 FT_EXPORT_DEF( const char* )
1920 FT_Get_Postscript_Name( FT_Face face )
1921 {
1922 const char* result = NULL;
1923
Werner Lembergc3b21602001-12-05 01:22:05 +00001924
David Turner23bcde12001-10-17 13:48:10 +00001925 if ( !face )
1926 goto Exit;
1927
1928 result = face->internal->postscript_name;
1929 if ( !result )
1930 {
1931 /* now, lookup for glyph name */
Werner Lembergc3b21602001-12-05 01:22:05 +00001932 FT_Driver driver = face->driver;
1933 FT_Module_Class* clazz = FT_MODULE_CLASS( driver );
1934
David Turner23bcde12001-10-17 13:48:10 +00001935
1936 if ( clazz->get_interface )
1937 {
1938 FT_PSName_Requester requester;
1939
Werner Lembergc3b21602001-12-05 01:22:05 +00001940
David Turner23bcde12001-10-17 13:48:10 +00001941 requester = (FT_PSName_Requester)clazz->get_interface(
1942 FT_MODULE( driver ), "postscript_name" );
1943 if ( requester )
1944 result = requester( face );
1945 }
1946 }
1947 Exit:
1948 return result;
1949 }
1950
1951
Werner Lemberg90a03302000-11-07 17:21:11 +00001952 /* documentation is in tttables.h */
1953
Werner Lembergf814d0f2001-06-27 16:18:10 +00001954 FT_EXPORT_DEF( void* )
1955 FT_Get_Sfnt_Table( FT_Face face,
1956 FT_Sfnt_Tag tag )
David Turner99a4d932000-04-25 16:10:50 +00001957 {
1958 void* table = 0;
1959 FT_Get_Sfnt_Table_Func func;
1960 FT_Driver driver;
David Turnere49ab252000-05-16 23:44:38 +00001961
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001962
1963 if ( !face || !FT_IS_SFNT( face ) )
David Turner99a4d932000-04-25 16:10:50 +00001964 goto Exit;
David Turnere49ab252000-05-16 23:44:38 +00001965
David Turner99a4d932000-04-25 16:10:50 +00001966 driver = face->driver;
David Turnerf0df85b2000-06-22 00:17:42 +00001967 func = (FT_Get_Sfnt_Table_Func)driver->root.clazz->get_interface(
Werner Lemberga929ba92000-06-25 06:47:11 +00001968 FT_MODULE( driver ), "get_sfnt" );
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001969 if ( func )
1970 table = func( face, tag );
David Turnere49ab252000-05-16 23:44:38 +00001971
David Turner99a4d932000-04-25 16:10:50 +00001972 Exit:
1973 return table;
David Turnere49ab252000-05-16 23:44:38 +00001974 }
David Turner99a4d932000-04-25 16:10:50 +00001975
1976
David Turnerb3ba40d2001-10-07 13:30:26 +00001977 FT_EXPORT_DEF( FT_Error )
Werner Lemberg80b8d772001-10-10 19:56:42 +00001978 FT_Activate_Size( FT_Size size )
David Turnerb3ba40d2001-10-07 13:30:26 +00001979 {
1980 FT_Face face;
1981
Werner Lemberg80b8d772001-10-10 19:56:42 +00001982
David Turnerb3ba40d2001-10-07 13:30:26 +00001983 if ( size == NULL )
1984 return FT_Err_Bad_Argument;
1985
1986 face = size->face;
1987 if ( face == NULL || face->driver == NULL )
1988 return FT_Err_Bad_Argument;
1989
Werner Lemberg80b8d772001-10-10 19:56:42 +00001990 /* we don't need anything more complex than that; all size objects */
1991 /* are already listed by the face */
David Turnerb3ba40d2001-10-07 13:30:26 +00001992 face->size = size;
1993
1994 return FT_Err_Ok;
1995 }
1996
1997
David Turnerd2b1f351999-12-16 23:11:37 +00001998 /*************************************************************************/
David Turnerf0df85b2000-06-22 00:17:42 +00001999 /*************************************************************************/
2000 /*************************************************************************/
2001 /**** ****/
2002 /**** ****/
2003 /**** R E N D E R E R S ****/
2004 /**** ****/
2005 /**** ****/
2006 /*************************************************************************/
2007 /*************************************************************************/
2008 /*************************************************************************/
2009
Werner Lembergdeb4e982000-06-29 03:14:25 +00002010 /* lookup a renderer by glyph format in the library's list */
Werner Lembergf814d0f2001-06-27 16:18:10 +00002011 FT_BASE_DEF( FT_Renderer )
2012 FT_Lookup_Renderer( FT_Library library,
2013 FT_Glyph_Format format,
2014 FT_ListNode* node )
David Turnerf0df85b2000-06-22 00:17:42 +00002015 {
Werner Lembergdeb4e982000-06-29 03:14:25 +00002016 FT_ListNode cur;
David Turnerf0df85b2000-06-22 00:17:42 +00002017 FT_Renderer result = 0;
Werner Lemberga929ba92000-06-25 06:47:11 +00002018
Werner Lembergdeb4e982000-06-29 03:14:25 +00002019
2020 if ( !library )
2021 goto Exit;
2022
2023 cur = library->renderers.head;
2024
2025 if ( node )
David Turner74abee82000-06-27 23:31:53 +00002026 {
Werner Lembergdeb4e982000-06-29 03:14:25 +00002027 if ( *node )
David Turner74abee82000-06-27 23:31:53 +00002028 cur = (*node)->next;
David Turnerf0df85b2000-06-22 00:17:42 +00002029 *node = 0;
David Turner74abee82000-06-27 23:31:53 +00002030 }
Werner Lembergdeb4e982000-06-29 03:14:25 +00002031
Werner Lemberga929ba92000-06-25 06:47:11 +00002032 while ( cur )
David Turnerf0df85b2000-06-22 00:17:42 +00002033 {
Werner Lemberga929ba92000-06-25 06:47:11 +00002034 FT_Renderer renderer = FT_RENDERER( cur->data );
Werner Lembergdeb4e982000-06-29 03:14:25 +00002035
Werner Lemberga929ba92000-06-25 06:47:11 +00002036
2037 if ( renderer->glyph_format == format )
David Turnerf0df85b2000-06-22 00:17:42 +00002038 {
Werner Lemberga929ba92000-06-25 06:47:11 +00002039 if ( node )
David Turnerf0df85b2000-06-22 00:17:42 +00002040 *node = cur;
Werner Lembergdeb4e982000-06-29 03:14:25 +00002041
David Turnerf0df85b2000-06-22 00:17:42 +00002042 result = renderer;
2043 break;
2044 }
David Turner74abee82000-06-27 23:31:53 +00002045 cur = cur->next;
David Turnerf0df85b2000-06-22 00:17:42 +00002046 }
Werner Lemberga929ba92000-06-25 06:47:11 +00002047
Werner Lembergdeb4e982000-06-29 03:14:25 +00002048 Exit:
David Turnerf0df85b2000-06-22 00:17:42 +00002049 return result;
2050 }
2051
Werner Lemberga929ba92000-06-25 06:47:11 +00002052
Werner Lembergf814d0f2001-06-27 16:18:10 +00002053 static FT_Renderer
2054 ft_lookup_glyph_renderer( FT_GlyphSlot slot )
Werner Lembergdeb4e982000-06-29 03:14:25 +00002055 {
2056 FT_Face face = slot->face;
2057 FT_Library library = FT_FACE_LIBRARY( face );
2058 FT_Renderer result = library->cur_renderer;
2059
2060
Werner Lemberga929ba92000-06-25 06:47:11 +00002061 if ( !result || result->glyph_format != slot->format )
David Turner81bb4ad2000-06-28 04:19:49 +00002062 result = FT_Lookup_Renderer( library, slot->format, 0 );
Werner Lembergfbeb41d2000-07-02 00:27:53 +00002063
David Turnerf0df85b2000-06-22 00:17:42 +00002064 return result;
2065 }
2066
Werner Lembergdeb4e982000-06-29 03:14:25 +00002067
Werner Lembergf814d0f2001-06-27 16:18:10 +00002068 static void
2069 ft_set_current_renderer( FT_Library library )
David Turnerf0df85b2000-06-22 00:17:42 +00002070 {
2071 FT_Renderer renderer;
2072
Werner Lembergdeb4e982000-06-29 03:14:25 +00002073
David Turner74abee82000-06-27 23:31:53 +00002074 renderer = FT_Lookup_Renderer( library, ft_glyph_format_outline, 0 );
David Turnerf0df85b2000-06-22 00:17:42 +00002075 library->cur_renderer = renderer;
2076 }
2077
2078
Werner Lembergf814d0f2001-06-27 16:18:10 +00002079 static FT_Error
2080 ft_add_renderer( FT_Module module )
David Turnerf0df85b2000-06-22 00:17:42 +00002081 {
2082 FT_Library library = module->library;
2083 FT_Memory memory = library->memory;
2084 FT_Error error;
2085 FT_ListNode node;
Werner Lembergdeb4e982000-06-29 03:14:25 +00002086
2087
Werner Lemberga929ba92000-06-25 06:47:11 +00002088 if ( ALLOC( node, sizeof ( *node ) ) )
David Turnerf0df85b2000-06-22 00:17:42 +00002089 goto Exit;
Werner Lembergdeb4e982000-06-29 03:14:25 +00002090
David Turnerf0df85b2000-06-22 00:17:42 +00002091 {
Werner Lemberga929ba92000-06-25 06:47:11 +00002092 FT_Renderer render = FT_RENDERER( module );
David Turnerf0df85b2000-06-22 00:17:42 +00002093 FT_Renderer_Class* clazz = (FT_Renderer_Class*)module->clazz;
2094
Werner Lemberga929ba92000-06-25 06:47:11 +00002095
David Turnerf0df85b2000-06-22 00:17:42 +00002096 render->clazz = clazz;
2097 render->glyph_format = clazz->glyph_format;
Werner Lembergdeb4e982000-06-29 03:14:25 +00002098
David Turnerf0df85b2000-06-22 00:17:42 +00002099 /* allocate raster object if needed */
2100 if ( clazz->glyph_format == ft_glyph_format_outline &&
2101 clazz->raster_class->raster_new )
2102 {
2103 error = clazz->raster_class->raster_new( memory, &render->raster );
Werner Lemberga929ba92000-06-25 06:47:11 +00002104 if ( error )
2105 goto Fail;
Werner Lembergdeb4e982000-06-29 03:14:25 +00002106
David Turnerf0df85b2000-06-22 00:17:42 +00002107 render->raster_render = clazz->raster_class->raster_render;
2108 render->render = clazz->render_glyph;
Werner Lembergdeb4e982000-06-29 03:14:25 +00002109 }
2110
David Turnerf0df85b2000-06-22 00:17:42 +00002111 /* add to list */
2112 node->data = module;
2113 FT_List_Add( &library->renderers, node );
2114
2115 ft_set_current_renderer( library );
2116 }
2117
2118 Fail:
Werner Lemberga929ba92000-06-25 06:47:11 +00002119 if ( error )
2120 FREE( node );
David Turnerf0df85b2000-06-22 00:17:42 +00002121
2122 Exit:
2123 return error;
Werner Lembergdeb4e982000-06-29 03:14:25 +00002124 }
David Turnerf0df85b2000-06-22 00:17:42 +00002125
2126
Werner Lembergf814d0f2001-06-27 16:18:10 +00002127 static void
2128 ft_remove_renderer( FT_Module module )
David Turnerf0df85b2000-06-22 00:17:42 +00002129 {
2130 FT_Library library = module->library;
2131 FT_Memory memory = library->memory;
2132 FT_ListNode node;
2133
Werner Lemberga929ba92000-06-25 06:47:11 +00002134
David Turnerf0df85b2000-06-22 00:17:42 +00002135 node = FT_List_Find( &library->renderers, module );
Werner Lemberga929ba92000-06-25 06:47:11 +00002136 if ( node )
David Turnerf0df85b2000-06-22 00:17:42 +00002137 {
Werner Lemberga929ba92000-06-25 06:47:11 +00002138 FT_Renderer render = FT_RENDERER( module );
Werner Lembergdeb4e982000-06-29 03:14:25 +00002139
Werner Lemberga929ba92000-06-25 06:47:11 +00002140
David Turnerf0df85b2000-06-22 00:17:42 +00002141 /* release raster object, if any */
Werner Lemberga929ba92000-06-25 06:47:11 +00002142 if ( render->raster )
David Turnerf0df85b2000-06-22 00:17:42 +00002143 render->clazz->raster_class->raster_done( render->raster );
Werner Lembergdeb4e982000-06-29 03:14:25 +00002144
David Turnerf0df85b2000-06-22 00:17:42 +00002145 /* remove from list */
2146 FT_List_Remove( &library->renderers, node );
2147 FREE( node );
Werner Lembergdeb4e982000-06-29 03:14:25 +00002148
David Turnerf0df85b2000-06-22 00:17:42 +00002149 ft_set_current_renderer( library );
2150 }
2151 }
2152
2153
Werner Lemberg90a03302000-11-07 17:21:11 +00002154 /* documentation is in ftrender.h */
2155
Werner Lembergf814d0f2001-06-27 16:18:10 +00002156 FT_EXPORT_DEF( FT_Renderer )
2157 FT_Get_Renderer( FT_Library library,
2158 FT_Glyph_Format format )
David Turnerf0df85b2000-06-22 00:17:42 +00002159 {
Werner Lembergdeb4e982000-06-29 03:14:25 +00002160 /* test for valid `library' delayed to FT_Lookup_Renderer() */
2161
David Turner74abee82000-06-27 23:31:53 +00002162 return FT_Lookup_Renderer( library, format, 0 );
Werner Lembergdeb4e982000-06-29 03:14:25 +00002163 }
David Turnerf0df85b2000-06-22 00:17:42 +00002164
2165
Werner Lemberg90a03302000-11-07 17:21:11 +00002166 /* documentation is in ftrender.h */
2167
Werner Lembergf814d0f2001-06-27 16:18:10 +00002168 FT_EXPORT_DEF( FT_Error )
2169 FT_Set_Renderer( FT_Library library,
2170 FT_Renderer renderer,
2171 FT_UInt num_params,
2172 FT_Parameter* parameters )
David Turnerf0df85b2000-06-22 00:17:42 +00002173 {
2174 FT_ListNode node;
2175 FT_Error error = FT_Err_Ok;
Werner Lembergdeb4e982000-06-29 03:14:25 +00002176
2177
2178 if ( !library )
2179 return FT_Err_Invalid_Library_Handle;
2180
2181 if ( !renderer )
2182 return FT_Err_Invalid_Argument;
Werner Lemberga929ba92000-06-25 06:47:11 +00002183
David Turnerf0df85b2000-06-22 00:17:42 +00002184 node = FT_List_Find( &library->renderers, renderer );
Werner Lemberga929ba92000-06-25 06:47:11 +00002185 if ( !node )
David Turnerf0df85b2000-06-22 00:17:42 +00002186 {
2187 error = FT_Err_Invalid_Argument;
2188 goto Exit;
2189 }
David Turner74abee82000-06-27 23:31:53 +00002190
David Turnerf0df85b2000-06-22 00:17:42 +00002191 FT_List_Up( &library->renderers, node );
Werner Lembergdeb4e982000-06-29 03:14:25 +00002192
Werner Lemberga929ba92000-06-25 06:47:11 +00002193 if ( renderer->glyph_format == ft_glyph_format_outline )
David Turnerf0df85b2000-06-22 00:17:42 +00002194 library->cur_renderer = renderer;
Werner Lembergdeb4e982000-06-29 03:14:25 +00002195
Werner Lemberga929ba92000-06-25 06:47:11 +00002196 if ( num_params > 0 )
David Turnerf0df85b2000-06-22 00:17:42 +00002197 {
2198 FTRenderer_setMode set_mode = renderer->clazz->set_mode;
Werner Lembergdeb4e982000-06-29 03:14:25 +00002199
Werner Lemberga929ba92000-06-25 06:47:11 +00002200
David Turnerf0df85b2000-06-22 00:17:42 +00002201 for ( ; num_params > 0; num_params-- )
2202 {
2203 error = set_mode( renderer, parameters->tag, parameters->data );
Werner Lemberga929ba92000-06-25 06:47:11 +00002204 if ( error )
David Turnerf0df85b2000-06-22 00:17:42 +00002205 break;
2206 }
2207 }
Werner Lembergdeb4e982000-06-29 03:14:25 +00002208
David Turnerf0df85b2000-06-22 00:17:42 +00002209 Exit:
2210 return error;
Werner Lembergdeb4e982000-06-29 03:14:25 +00002211 }
David Turnerf0df85b2000-06-22 00:17:42 +00002212
2213
Werner Lembergf814d0f2001-06-27 16:18:10 +00002214 FT_EXPORT_DEF( FT_Error )
2215 FT_Render_Glyph_Internal( FT_Library library,
2216 FT_GlyphSlot slot,
2217 FT_UInt render_mode )
David Turnerf0df85b2000-06-22 00:17:42 +00002218 {
2219 FT_Error error = FT_Err_Ok;
2220 FT_Renderer renderer;
Werner Lemberga929ba92000-06-25 06:47:11 +00002221
Werner Lembergdeb4e982000-06-29 03:14:25 +00002222
2223 /* if it is already a bitmap, no need to do anything */
2224 switch ( slot->format )
David Turnerf0df85b2000-06-22 00:17:42 +00002225 {
Werner Lembergdeb4e982000-06-29 03:14:25 +00002226 case ft_glyph_format_bitmap: /* already a bitmap, don't do anything */
2227 break;
2228
2229 default:
David Turner74abee82000-06-27 23:31:53 +00002230 {
2231 FT_ListNode node = 0;
2232 FT_Bool update = 0;
Werner Lembergdeb4e982000-06-29 03:14:25 +00002233
2234
Werner Lemberga929ba92000-06-25 06:47:11 +00002235 /* small shortcut for the very common case */
Werner Lembergdeb4e982000-06-29 03:14:25 +00002236 if ( slot->format == ft_glyph_format_outline )
David Turner74abee82000-06-27 23:31:53 +00002237 {
Werner Lemberga929ba92000-06-25 06:47:11 +00002238 renderer = library->cur_renderer;
David Turner74abee82000-06-27 23:31:53 +00002239 node = library->renderers.head;
2240 }
Werner Lemberga929ba92000-06-25 06:47:11 +00002241 else
David Turner74abee82000-06-27 23:31:53 +00002242 renderer = FT_Lookup_Renderer( library, slot->format, &node );
2243
Werner Lemberga929ba92000-06-25 06:47:11 +00002244 error = FT_Err_Unimplemented_Feature;
Werner Lembergdeb4e982000-06-29 03:14:25 +00002245 while ( renderer )
David Turner74abee82000-06-27 23:31:53 +00002246 {
David Turnerc8ad30a2001-12-05 17:24:34 +00002247 error = renderer->render( renderer, slot, render_mode, NULL );
Werner Lemberg79860702001-06-08 21:17:29 +00002248 if ( !error ||
2249 FT_ERROR_BASE( error ) != FT_Err_Cannot_Render_Glyph )
Werner Lembergdeb4e982000-06-29 03:14:25 +00002250 break;
David Turner74abee82000-06-27 23:31:53 +00002251
Werner Lembergdeb4e982000-06-29 03:14:25 +00002252 /* FT_Err_Cannot_Render_Glyph is returned if the render mode */
David Turner74abee82000-06-27 23:31:53 +00002253 /* is unsupported by the current renderer for this glyph image */
Werner Lembergdeb4e982000-06-29 03:14:25 +00002254 /* format. */
2255
2256 /* now, look for another renderer that supports the same */
2257 /* format. */
David Turner74abee82000-06-27 23:31:53 +00002258 renderer = FT_Lookup_Renderer( library, slot->format, &node );
2259 update = 1;
2260 }
2261
2262 /* if we changed the current renderer for the glyph image format */
Werner Lembergdeb4e982000-06-29 03:14:25 +00002263 /* we need to select it as the next current one */
2264 if ( !error && update && renderer )
David Turner74abee82000-06-27 23:31:53 +00002265 FT_Set_Renderer( library, renderer, 0, 0 );
David Turnerf0df85b2000-06-22 00:17:42 +00002266 }
2267 }
Werner Lembergdeb4e982000-06-29 03:14:25 +00002268
David Turnerf0df85b2000-06-22 00:17:42 +00002269 return error;
2270 }
Werner Lemberga929ba92000-06-25 06:47:11 +00002271
David Turner74abee82000-06-27 23:31:53 +00002272
Werner Lemberg90a03302000-11-07 17:21:11 +00002273 /* documentation is in freetype.h */
2274
Werner Lembergf814d0f2001-06-27 16:18:10 +00002275 FT_EXPORT_DEF( FT_Error )
2276 FT_Render_Glyph( FT_GlyphSlot slot,
2277 FT_UInt render_mode )
David Turner74abee82000-06-27 23:31:53 +00002278 {
2279 FT_Library library;
Werner Lembergdeb4e982000-06-29 03:14:25 +00002280
2281
2282 if ( !slot )
David Turner74abee82000-06-27 23:31:53 +00002283 return FT_Err_Invalid_Argument;
Werner Lembergdeb4e982000-06-29 03:14:25 +00002284
2285 library = FT_FACE_LIBRARY( slot->face );
2286
David Turner74abee82000-06-27 23:31:53 +00002287 return FT_Render_Glyph_Internal( library, slot, render_mode );
2288 }
2289
Werner Lembergdeb4e982000-06-29 03:14:25 +00002290
David Turnerf0df85b2000-06-22 00:17:42 +00002291 /*************************************************************************/
2292 /*************************************************************************/
2293 /*************************************************************************/
2294 /**** ****/
2295 /**** ****/
2296 /**** M O D U L E S ****/
2297 /**** ****/
2298 /**** ****/
2299 /*************************************************************************/
2300 /*************************************************************************/
2301 /*************************************************************************/
2302
Werner Lemberga929ba92000-06-25 06:47:11 +00002303
David Turnerf0df85b2000-06-22 00:17:42 +00002304 /*************************************************************************/
2305 /* */
2306 /* <Function> */
2307 /* Destroy_Module */
2308 /* */
2309 /* <Description> */
2310 /* Destroys a given module object. For drivers, this also destroys */
Werner Lemberga929ba92000-06-25 06:47:11 +00002311 /* all child faces. */
David Turnerf0df85b2000-06-22 00:17:42 +00002312 /* */
2313 /* <InOut> */
2314 /* module :: A handle to the target driver object. */
2315 /* */
2316 /* <Note> */
2317 /* The driver _must_ be LOCKED! */
2318 /* */
Werner Lembergf814d0f2001-06-27 16:18:10 +00002319 static void
2320 Destroy_Module( FT_Module module )
David Turnerf0df85b2000-06-22 00:17:42 +00002321 {
David Turner5ae831c2000-06-30 01:31:22 +00002322 FT_Memory memory = module->memory;
2323 FT_Module_Class* clazz = module->clazz;
2324 FT_Library library = module->library;
David Turnerf0df85b2000-06-22 00:17:42 +00002325
Werner Lemberga929ba92000-06-25 06:47:11 +00002326
David Turnerf0df85b2000-06-22 00:17:42 +00002327 /* finalize client-data - before anything else */
2328 if ( module->generic.finalizer )
2329 module->generic.finalizer( module );
2330
David Turner5ae831c2000-06-30 01:31:22 +00002331 if ( library && library->auto_hinter == module )
2332 library->auto_hinter = 0;
2333
David Turnerf0df85b2000-06-22 00:17:42 +00002334 /* if the module is a renderer */
Werner Lemberga929ba92000-06-25 06:47:11 +00002335 if ( FT_MODULE_IS_RENDERER( module ) )
2336 ft_remove_renderer( module );
David Turnerf0df85b2000-06-22 00:17:42 +00002337
2338 /* if the module is a font driver, add some steps */
Werner Lemberga929ba92000-06-25 06:47:11 +00002339 if ( FT_MODULE_IS_DRIVER( module ) )
2340 Destroy_Driver( FT_DRIVER( module ) );
David Turnerf0df85b2000-06-22 00:17:42 +00002341
2342 /* finalize the module object */
Werner Lemberga929ba92000-06-25 06:47:11 +00002343 if ( clazz->module_done )
2344 clazz->module_done( module );
David Turnerf0df85b2000-06-22 00:17:42 +00002345
2346 /* discard it */
2347 FREE( module );
2348 }
2349
David Turnerf0df85b2000-06-22 00:17:42 +00002350
Werner Lemberg90a03302000-11-07 17:21:11 +00002351 /* documentation is in ftmodule.h */
2352
Werner Lembergf814d0f2001-06-27 16:18:10 +00002353 FT_EXPORT_DEF( FT_Error )
2354 FT_Add_Module( FT_Library library,
2355 const FT_Module_Class* clazz )
David Turnerf0df85b2000-06-22 00:17:42 +00002356 {
2357 FT_Error error;
2358 FT_Memory memory;
2359 FT_Module module;
2360 FT_UInt nn;
2361
David Turnerf0df85b2000-06-22 00:17:42 +00002362
Werner Lembergdeb4e982000-06-29 03:14:25 +00002363#define FREETYPE_VER_FIXED ( ( (FT_Long)FREETYPE_MAJOR << 16 ) | \
2364 FREETYPE_MINOR )
Werner Lemberga929ba92000-06-25 06:47:11 +00002365
Werner Lembergdeb4e982000-06-29 03:14:25 +00002366 if ( !library )
2367 return FT_Err_Invalid_Library_Handle;
2368
2369 if ( !clazz )
David Turnerf0df85b2000-06-22 00:17:42 +00002370 return FT_Err_Invalid_Argument;
2371
2372 /* check freetype version */
2373 if ( clazz->module_requires > FREETYPE_VER_FIXED )
2374 return FT_Err_Invalid_Version;
2375
2376 /* look for a module with the same name in the library's table */
2377 for ( nn = 0; nn < library->num_modules; nn++ )
2378 {
2379 module = library->modules[nn];
2380 if ( strcmp( module->clazz->module_name, clazz->module_name ) == 0 )
2381 {
2382 /* this installed module has the same name, compare their versions */
2383 if ( clazz->module_version <= module->clazz->module_version )
2384 return FT_Err_Lower_Module_Version;
2385
2386 /* remove the module from our list, then exit the loop to replace */
2387 /* it by our new version.. */
2388 FT_Remove_Module( library, module );
2389 break;
2390 }
2391 }
2392
2393 memory = library->memory;
2394 error = FT_Err_Ok;
2395
2396 if ( library->num_modules >= FT_MAX_MODULES )
2397 {
2398 error = FT_Err_Too_Many_Drivers;
2399 goto Exit;
2400 }
2401
2402 /* allocate module object */
Werner Lemberga929ba92000-06-25 06:47:11 +00002403 if ( ALLOC( module,clazz->module_size ) )
David Turnerf0df85b2000-06-22 00:17:42 +00002404 goto Exit;
2405
Werner Lembergdeb4e982000-06-29 03:14:25 +00002406 /* base initialization */
David Turnerf0df85b2000-06-22 00:17:42 +00002407 module->library = library;
2408 module->memory = memory;
2409 module->clazz = (FT_Module_Class*)clazz;
2410
Werner Lembergdeb4e982000-06-29 03:14:25 +00002411 /* check whether the module is a renderer - this must be performed */
2412 /* before the normal module initialization */
Werner Lemberga929ba92000-06-25 06:47:11 +00002413 if ( FT_MODULE_IS_RENDERER( module ) )
David Turnerf0df85b2000-06-22 00:17:42 +00002414 {
2415 /* add to the renderers list */
Werner Lemberga929ba92000-06-25 06:47:11 +00002416 error = ft_add_renderer( module );
2417 if ( error )
2418 goto Fail;
David Turnerf0df85b2000-06-22 00:17:42 +00002419 }
2420
Werner Lembergcc9fc492000-06-30 06:21:26 +00002421 /* is the module a auto-hinter? */
2422 if ( FT_MODULE_IS_HINTER( module ) )
David Turner5ae831c2000-06-30 01:31:22 +00002423 library->auto_hinter = module;
Werner Lembergfbeb41d2000-07-02 00:27:53 +00002424
David Turnerf0df85b2000-06-22 00:17:42 +00002425 /* if the module is a font driver */
Werner Lemberga929ba92000-06-25 06:47:11 +00002426 if ( FT_MODULE_IS_DRIVER( module ) )
David Turnerf0df85b2000-06-22 00:17:42 +00002427 {
2428 /* allocate glyph loader if needed */
Werner Lemberga929ba92000-06-25 06:47:11 +00002429 FT_Driver driver = FT_DRIVER( module );
2430
Werner Lembergdeb4e982000-06-29 03:14:25 +00002431
David Turnerf0df85b2000-06-22 00:17:42 +00002432 driver->clazz = (FT_Driver_Class*)module->clazz;
Werner Lemberga929ba92000-06-25 06:47:11 +00002433 if ( FT_DRIVER_USES_OUTLINES( driver ) )
David Turnerf0df85b2000-06-22 00:17:42 +00002434 {
2435 error = FT_GlyphLoader_New( memory, &driver->glyph_loader );
Werner Lemberga929ba92000-06-25 06:47:11 +00002436 if ( error )
2437 goto Fail;
David Turnerf0df85b2000-06-22 00:17:42 +00002438 }
2439 }
2440
Werner Lemberga929ba92000-06-25 06:47:11 +00002441 if ( clazz->module_init )
David Turnerf0df85b2000-06-22 00:17:42 +00002442 {
Werner Lemberga929ba92000-06-25 06:47:11 +00002443 error = clazz->module_init( module );
2444 if ( error )
2445 goto Fail;
David Turnerf0df85b2000-06-22 00:17:42 +00002446 }
2447
2448 /* add module to the library's table */
Werner Lemberga929ba92000-06-25 06:47:11 +00002449 library->modules[library->num_modules++] = module;
Werner Lembergdeb4e982000-06-29 03:14:25 +00002450
David Turnerf0df85b2000-06-22 00:17:42 +00002451 Exit:
2452 return error;
Werner Lembergdeb4e982000-06-29 03:14:25 +00002453
David Turnerf0df85b2000-06-22 00:17:42 +00002454 Fail:
Werner Lemberga929ba92000-06-25 06:47:11 +00002455 if ( FT_MODULE_IS_DRIVER( module ) )
David Turnerf0df85b2000-06-22 00:17:42 +00002456 {
Werner Lemberga929ba92000-06-25 06:47:11 +00002457 FT_Driver driver = FT_DRIVER( module );
Werner Lembergdeb4e982000-06-29 03:14:25 +00002458
Werner Lemberga929ba92000-06-25 06:47:11 +00002459
2460 if ( FT_DRIVER_USES_OUTLINES( driver ) )
David Turnerf0df85b2000-06-22 00:17:42 +00002461 FT_GlyphLoader_Done( driver->glyph_loader );
2462 }
Werner Lembergdeb4e982000-06-29 03:14:25 +00002463
Werner Lemberga929ba92000-06-25 06:47:11 +00002464 if ( FT_MODULE_IS_RENDERER( module ) )
David Turnerf0df85b2000-06-22 00:17:42 +00002465 {
Werner Lemberga929ba92000-06-25 06:47:11 +00002466 FT_Renderer renderer = FT_RENDERER( module );
2467
2468
2469 if ( renderer->raster )
David Turnerf0df85b2000-06-22 00:17:42 +00002470 renderer->clazz->raster_class->raster_done( renderer->raster );
2471 }
Werner Lemberga929ba92000-06-25 06:47:11 +00002472
2473 FREE( module );
David Turnerf0df85b2000-06-22 00:17:42 +00002474 goto Exit;
2475 }
2476
David Turnerf0df85b2000-06-22 00:17:42 +00002477
Werner Lemberg90a03302000-11-07 17:21:11 +00002478 /* documentation is in ftmodule.h */
2479
Werner Lembergf814d0f2001-06-27 16:18:10 +00002480 FT_EXPORT_DEF( FT_Module )
2481 FT_Get_Module( FT_Library library,
2482 const char* module_name )
David Turnerf0df85b2000-06-22 00:17:42 +00002483 {
Werner Lembergdeb4e982000-06-29 03:14:25 +00002484 FT_Module result = 0;
2485 FT_Module* cur;
2486 FT_Module* limit;
David Turnerf0df85b2000-06-22 00:17:42 +00002487
Werner Lemberga929ba92000-06-25 06:47:11 +00002488
Werner Lembergdeb4e982000-06-29 03:14:25 +00002489 if ( !library || !module_name )
2490 return result;
2491
2492 cur = library->modules;
2493 limit = cur + library->num_modules;
2494
David Turnerf0df85b2000-06-22 00:17:42 +00002495 for ( ; cur < limit; cur++ )
2496 if ( strcmp( cur[0]->clazz->module_name, module_name ) == 0 )
2497 {
2498 result = cur[0];
2499 break;
2500 }
2501
2502 return result;
2503 }
2504
Werner Lemberga929ba92000-06-25 06:47:11 +00002505
Werner Lemberg8ec9dfd2000-11-07 23:56:02 +00002506 /* documentation is in ftobjs.h */
2507
Werner Lembergf814d0f2001-06-27 16:18:10 +00002508 FT_BASE_DEF( const void* )
2509 FT_Get_Module_Interface( FT_Library library,
2510 const char* mod_name )
David Turnerf0df85b2000-06-22 00:17:42 +00002511 {
2512 FT_Module module;
Werner Lembergdeb4e982000-06-29 03:14:25 +00002513
2514
2515 /* test for valid `library' delayed to FT_Get_Module() */
Werner Lemberga929ba92000-06-25 06:47:11 +00002516
David Turnerf0df85b2000-06-22 00:17:42 +00002517 module = FT_Get_Module( library, mod_name );
Werner Lemberga929ba92000-06-25 06:47:11 +00002518
David Turnerf0df85b2000-06-22 00:17:42 +00002519 return module ? module->clazz->module_interface : 0;
Werner Lembergdeb4e982000-06-29 03:14:25 +00002520 }
David Turnerf0df85b2000-06-22 00:17:42 +00002521
2522
Werner Lemberg90a03302000-11-07 17:21:11 +00002523 /* documentation is in ftmodule.h */
2524
Werner Lembergf814d0f2001-06-27 16:18:10 +00002525 FT_EXPORT_DEF( FT_Error )
2526 FT_Remove_Module( FT_Library library,
2527 FT_Module module )
David Turnerf0df85b2000-06-22 00:17:42 +00002528 {
2529 /* try to find the module from the table, then remove it from there */
Werner Lembergdeb4e982000-06-29 03:14:25 +00002530
2531 if ( !library )
2532 return FT_Err_Invalid_Library_Handle;
2533
2534 if ( module )
David Turnerf0df85b2000-06-22 00:17:42 +00002535 {
2536 FT_Module* cur = library->modules;
2537 FT_Module* limit = cur + library->num_modules;
2538
Werner Lemberga929ba92000-06-25 06:47:11 +00002539
David Turnerf0df85b2000-06-22 00:17:42 +00002540 for ( ; cur < limit; cur++ )
2541 {
Werner Lembergdeb4e982000-06-29 03:14:25 +00002542 if ( cur[0] == module )
David Turnerf0df85b2000-06-22 00:17:42 +00002543 {
2544 /* remove it from the table */
2545 library->num_modules--;
2546 limit--;
Werner Lemberga929ba92000-06-25 06:47:11 +00002547 while ( cur < limit )
David Turnerf0df85b2000-06-22 00:17:42 +00002548 {
2549 cur[0] = cur[1];
2550 cur++;
2551 }
2552 limit[0] = 0;
2553
2554 /* destroy the module */
Werner Lemberga929ba92000-06-25 06:47:11 +00002555 Destroy_Module( module );
David Turnerf0df85b2000-06-22 00:17:42 +00002556
2557 return FT_Err_Ok;
2558 }
2559 }
2560 }
Werner Lembergb48a6092000-07-09 19:15:30 +00002561 return FT_Err_Invalid_Driver_Handle;
David Turnerf0df85b2000-06-22 00:17:42 +00002562 }
2563
2564
David Turnerf0df85b2000-06-22 00:17:42 +00002565 /*************************************************************************/
2566 /*************************************************************************/
2567 /*************************************************************************/
2568 /**** ****/
2569 /**** ****/
2570 /**** L I B R A R Y ****/
2571 /**** ****/
2572 /**** ****/
2573 /*************************************************************************/
2574 /*************************************************************************/
2575 /*************************************************************************/
2576
Werner Lemberga929ba92000-06-25 06:47:11 +00002577
Werner Lemberg90a03302000-11-07 17:21:11 +00002578 /* documentation is in ftmodule.h */
2579
Werner Lembergf814d0f2001-06-27 16:18:10 +00002580 FT_EXPORT_DEF( FT_Error )
2581 FT_New_Library( FT_Memory memory,
2582 FT_Library *alibrary )
David Turnerf0df85b2000-06-22 00:17:42 +00002583 {
2584 FT_Library library = 0;
2585 FT_Error error;
2586
2587
2588 if ( !memory )
2589 return FT_Err_Invalid_Argument;
2590
2591 /* first of all, allocate the library object */
2592 if ( ALLOC( library, sizeof ( *library ) ) )
2593 return error;
2594
2595 library->memory = memory;
2596
2597 /* allocate the render pool */
2598 library->raster_pool_size = FT_RENDER_POOL_SIZE;
2599 if ( ALLOC( library->raster_pool, FT_RENDER_POOL_SIZE ) )
2600 goto Fail;
2601
2602 /* That's ok now */
2603 *alibrary = library;
2604
2605 return FT_Err_Ok;
2606
2607 Fail:
2608 FREE( library );
2609 return error;
2610 }
2611
2612
Werner Lemberg90a03302000-11-07 17:21:11 +00002613 /* documentation is in ftmodule.h */
2614
Werner Lembergf814d0f2001-06-27 16:18:10 +00002615 FT_EXPORT_DEF( FT_Error )
2616 FT_Done_Library( FT_Library library )
David Turnerf0df85b2000-06-22 00:17:42 +00002617 {
2618 FT_Memory memory;
David Turner74abee82000-06-27 23:31:53 +00002619 FT_UInt n;
David Turnerf0df85b2000-06-22 00:17:42 +00002620
2621
2622 if ( !library )
2623 return FT_Err_Invalid_Library_Handle;
2624
2625 memory = library->memory;
2626
2627 /* Discard client-data */
2628 if ( library->generic.finalizer )
2629 library->generic.finalizer( library );
2630
2631 /* Close all modules in the library */
2632 for ( n = 0; n < library->num_modules; n++ )
2633 {
2634 FT_Module module = library->modules[n];
2635
Werner Lemberga929ba92000-06-25 06:47:11 +00002636
David Turnerf0df85b2000-06-22 00:17:42 +00002637 if ( module )
2638 {
2639 Destroy_Module( module );
2640 library->modules[n] = 0;
2641 }
2642 }
2643
2644 /* Destroy raster objects */
2645 FREE( library->raster_pool );
2646 library->raster_pool_size = 0;
2647
2648 FREE( library );
2649 return FT_Err_Ok;
2650 }
2651
2652
Werner Lemberg90a03302000-11-07 17:21:11 +00002653 /* documentation is in ftmodule.h */
2654
Werner Lembergf814d0f2001-06-27 16:18:10 +00002655 FT_EXPORT_DEF( void )
2656 FT_Set_Debug_Hook( FT_Library library,
2657 FT_UInt hook_index,
2658 FT_DebugHook_Func debug_hook )
David Turnerf0df85b2000-06-22 00:17:42 +00002659 {
2660 if ( library && debug_hook &&
2661 hook_index <
2662 ( sizeof ( library->debug_hooks ) / sizeof ( void* ) ) )
2663 library->debug_hooks[hook_index] = debug_hook;
2664 }
2665
2666
David Turnerd2b1f351999-12-16 23:11:37 +00002667/* END */