blob: 08708d12a272fb5a13ae569faaf01d5b45abf292 [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 Lembergc8c6bf52003-04-23 05:38:13 +00007/* Copyright 1996-2001, 2002, 2003 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
David Turner7fe38a52002-01-04 09:47:30 +000021#include FT_OUTLINE_H
Werner Lembergcc069be2000-12-08 16:17:16 +000022#include FT_INTERNAL_OBJECTS_H
23#include FT_INTERNAL_DEBUG_H
24#include FT_INTERNAL_STREAM_H
David Turner621e4882002-12-16 21:51:24 +000025#include FT_INTERNAL_SFNT_H /* for SFNT_Load_Table_Func */
Werner Lembergcc069be2000-12-08 16:17:16 +000026#include FT_TRUETYPE_TABLES_H
Antoine Lecac96f69d2002-12-03 00:39:16 +000027#include FT_TRUETYPE_IDS_H
David Turnerf86709a2002-01-07 10:04:09 +000028#include FT_OUTLINE_H
Werner Lemberg7880dd62000-01-10 17:19:45 +000029
Werner Lemberg3c403e42002-08-06 21:47:40 +000030
David Turnered54f282002-03-22 17:09:52 +000031 FT_BASE_DEF( void )
32 ft_validator_init( FT_Validator valid,
33 const FT_Byte* base,
34 const FT_Byte* limit,
35 FT_ValidationLevel level )
36 {
37 valid->base = base;
38 valid->limit = limit;
39 valid->level = level;
40 valid->error = 0;
41 }
David Turner25a6e3a2002-06-10 23:03:35 +000042
David Turnered54f282002-03-22 17:09:52 +000043
44 FT_BASE_DEF( FT_Int )
45 ft_validator_run( FT_Validator valid )
46 {
47 int result;
Werner Lembergf8ba2002002-03-30 13:16:35 +000048
David Turner25a6e3a2002-06-10 23:03:35 +000049
50 result = ft_setjmp( valid->jump_buffer );
David Turnered54f282002-03-22 17:09:52 +000051 return result;
52 }
53
Werner Lembergf8ba2002002-03-30 13:16:35 +000054
David Turnered54f282002-03-22 17:09:52 +000055 FT_BASE_DEF( void )
56 ft_validator_error( FT_Validator valid,
57 FT_Error error )
58 {
59 valid->error = error;
David Turner25a6e3a2002-06-10 23:03:35 +000060 ft_longjmp( valid->jump_buffer, 1 );
61 }
Werner Lemberga929ba92000-06-25 06:47:11 +000062
Werner Lemberga3b6c6c2000-05-31 06:55:12 +000063
David Turnerd2b1f351999-12-16 23:11:37 +000064 /*************************************************************************/
65 /*************************************************************************/
66 /*************************************************************************/
67 /**** ****/
68 /**** ****/
David Turnerf0df85b2000-06-22 00:17:42 +000069 /**** S T R E A M ****/
70 /**** ****/
71 /**** ****/
72 /*************************************************************************/
73 /*************************************************************************/
74 /*************************************************************************/
75
Werner Lemberg7880dd62000-01-10 17:19:45 +000076
Werner Lembergf8ba2002002-03-30 13:16:35 +000077 /* create a new input stream from a FT_Open_Args structure */
78 /* */
Werner Lembergf814d0f2001-06-27 16:18:10 +000079 static FT_Error
Werner Lembergc4c373c2002-10-07 09:15:20 +000080 ft_input_stream_new( FT_Library library,
81 const FT_Open_Args* args,
82 FT_Stream* astream )
David Turner7663f222000-02-13 13:37:38 +000083 {
Werner Lemberg547a2522000-02-16 08:23:58 +000084 FT_Error error;
85 FT_Memory memory;
86 FT_Stream stream;
87
Werner Lemberga3b6c6c2000-05-31 06:55:12 +000088
Werner Lemberg2fbf7e42000-06-02 00:01:14 +000089 if ( !library )
90 return FT_Err_Invalid_Library_Handle;
91
92 if ( !args )
93 return FT_Err_Invalid_Argument;
94
David Turner37379e22000-03-28 11:22:31 +000095 *astream = 0;
96 memory = library->memory;
Werner Lembergf8ba2002002-03-30 13:16:35 +000097
David Turnere459d742002-03-22 13:52:37 +000098 if ( FT_NEW( stream ) )
David Turner37379e22000-03-28 11:22:31 +000099 goto Exit;
David Turnere49ab252000-05-16 23:44:38 +0000100
David Turner7663f222000-02-13 13:37:38 +0000101 stream->memory = memory;
David Turnere49ab252000-05-16 23:44:38 +0000102
David Turnerb08fe2d2002-08-27 20:20:29 +0000103 if ( args->flags & FT_OPEN_MEMORY )
Just van Rossumd35aea72000-03-02 01:07:50 +0000104 {
David Turner53b3fa12002-02-24 05:26:57 +0000105 /* create a memory-based stream */
David Turner7d3a2642002-03-20 10:49:31 +0000106 FT_Stream_OpenMemory( stream,
Werner Lembergf8ba2002002-03-30 13:16:35 +0000107 (const FT_Byte*)args->memory_base,
108 args->memory_size );
David Turner4f2c5542000-05-12 10:19:41 +0000109 }
David Turnerb08fe2d2002-08-27 20:20:29 +0000110 else if ( args->flags & FT_OPEN_PATHNAME )
David Turner4f2c5542000-05-12 10:19:41 +0000111 {
David Turner53b3fa12002-02-24 05:26:57 +0000112 /* create a normal system stream */
113 error = FT_Stream_Open( stream, args->pathname );
David Turner4f2c5542000-05-12 10:19:41 +0000114 stream->pathname.pointer = args->pathname;
115 }
David Turnerb08fe2d2002-08-27 20:20:29 +0000116 else if ( ( args->flags & FT_OPEN_STREAM ) && args->stream )
David Turner4f2c5542000-05-12 10:19:41 +0000117 {
David Turner53b3fa12002-02-24 05:26:57 +0000118 /* use an existing, user-provided stream */
119
Werner Lemberg58b17f92000-07-27 23:29:08 +0000120 /* in this case, we do not need to allocate a new stream object */
121 /* since the caller is responsible for closing it himself */
David Turnere459d742002-03-22 13:52:37 +0000122 FT_FREE( stream );
David Turnerc5cdf8b2000-07-27 21:40:22 +0000123 stream = args->stream;
David Turner4f2c5542000-05-12 10:19:41 +0000124 }
125 else
David Turner4f2c5542000-05-12 10:19:41 +0000126 error = FT_Err_Invalid_Argument;
David Turnere49ab252000-05-16 23:44:38 +0000127
Werner Lemberg547a2522000-02-16 08:23:58 +0000128 if ( error )
David Turnere459d742002-03-22 13:52:37 +0000129 FT_FREE( stream );
David Turner53b3fa12002-02-24 05:26:57 +0000130 else
131 stream->memory = memory; /* just to be certain */
David Turnere49ab252000-05-16 23:44:38 +0000132
David Turner7663f222000-02-13 13:37:38 +0000133 *astream = stream;
Werner Lemberga3b6c6c2000-05-31 06:55:12 +0000134
David Turner37379e22000-03-28 11:22:31 +0000135 Exit:
David Turner7663f222000-02-13 13:37:38 +0000136 return error;
137 }
138
139
Werner Lembergf814d0f2001-06-27 16:18:10 +0000140 static void
David Turner53b3fa12002-02-24 05:26:57 +0000141 ft_input_stream_free( FT_Stream stream,
142 FT_Int external )
David Turner7663f222000-02-13 13:37:38 +0000143 {
David Turner53b3fa12002-02-24 05:26:57 +0000144 if ( stream )
David Turnerc5cdf8b2000-07-27 21:40:22 +0000145 {
146 FT_Memory memory = stream->memory;
Werner Lemberg58b17f92000-07-27 23:29:08 +0000147
Werner Lembergf8ba2002002-03-30 13:16:35 +0000148
David Turner53b3fa12002-02-24 05:26:57 +0000149 FT_Stream_Close( stream );
Werner Lemberg58b17f92000-07-27 23:29:08 +0000150
David Turner53b3fa12002-02-24 05:26:57 +0000151 if ( !external )
David Turnere459d742002-03-22 13:52:37 +0000152 FT_FREE( stream );
David Turnerc5cdf8b2000-07-27 21:40:22 +0000153 }
David Turner7663f222000-02-13 13:37:38 +0000154 }
155
Werner Lemberga3b6c6c2000-05-31 06:55:12 +0000156
Werner Lembergeb81e372000-06-03 06:03:11 +0000157#undef FT_COMPONENT
158#define FT_COMPONENT trace_objs
159
Werner Lembergdeb4e982000-06-29 03:14:25 +0000160
David Turnerf0df85b2000-06-22 00:17:42 +0000161 /*************************************************************************/
162 /*************************************************************************/
163 /*************************************************************************/
164 /**** ****/
165 /**** ****/
166 /**** FACE, SIZE & GLYPH SLOT OBJECTS ****/
167 /**** ****/
168 /**** ****/
169 /*************************************************************************/
170 /*************************************************************************/
171 /*************************************************************************/
172
Werner Lembergdeb4e982000-06-29 03:14:25 +0000173
Werner Lembergf814d0f2001-06-27 16:18:10 +0000174 static FT_Error
175 ft_glyphslot_init( FT_GlyphSlot slot )
David Turnerf0df85b2000-06-22 00:17:42 +0000176 {
177 FT_Driver driver = slot->face->driver;
Werner Lembergf8ba2002002-03-30 13:16:35 +0000178 FT_Driver_Class clazz = driver->clazz;
David Turnerf0df85b2000-06-22 00:17:42 +0000179 FT_Memory memory = driver->root.memory;
180 FT_Error error = FT_Err_Ok;
David Turner54e75742000-11-04 02:52:02 +0000181 FT_Slot_Internal internal;
David Turnerf0df85b2000-06-22 00:17:42 +0000182
Werner Lemberga8bbc262000-07-01 14:06:46 +0000183
David Turnerf9ca2bb2000-06-30 23:12:55 +0000184 slot->library = driver->root.library;
Werner Lembergfbeb41d2000-07-02 00:27:53 +0000185
David Turnere459d742002-03-22 13:52:37 +0000186 if ( FT_NEW( internal ) )
David Turner54e75742000-11-04 02:52:02 +0000187 goto Exit;
188
189 slot->internal = internal;
190
Werner Lemberga929ba92000-06-25 06:47:11 +0000191 if ( FT_DRIVER_USES_OUTLINES( driver ) )
David Turner54e75742000-11-04 02:52:02 +0000192 error = FT_GlyphLoader_New( memory, &internal->loader );
David Turnerf0df85b2000-06-22 00:17:42 +0000193
Werner Lemberga929ba92000-06-25 06:47:11 +0000194 if ( !error && clazz->init_slot )
David Turnerf0df85b2000-06-22 00:17:42 +0000195 error = clazz->init_slot( slot );
196
David Turner54e75742000-11-04 02:52:02 +0000197 Exit:
David Turnerf0df85b2000-06-22 00:17:42 +0000198 return error;
199 }
200
David Turner66cbc202003-03-20 07:04:40 +0000201 FT_BASE_DEF( void )
202 ft_glyphslot_free_bitmap( FT_GlyphSlot slot )
203 {
204 if ( slot->flags & FT_GLYPH_OWN_BITMAP )
205 {
206 FT_Memory memory = FT_FACE_MEMORY( slot->face );
207
208
209 FT_FREE( slot->bitmap.buffer );
210 slot->flags &= ~FT_GLYPH_OWN_BITMAP;
211 }
212 else
213 {
214 /* assume that the bitmap buffer was stolen or not */
215 /* allocated from the heap */
216 slot->bitmap.buffer = NULL;
217 }
218 }
219
220
221 FT_BASE_DEF( void )
222 ft_glyphslot_set_bitmap( FT_GlyphSlot slot,
223 FT_Pointer buffer )
224 {
225 ft_glyphslot_free_bitmap( slot );
226
227 slot->bitmap.buffer = buffer;
228
229 FT_ASSERT( (slot->flags & FT_GLYPH_OWN_BITMAP) == 0 );
230 }
231
232
233 FT_BASE_DEF( FT_Error )
234 ft_glyphslot_alloc_bitmap( FT_GlyphSlot slot,
235 FT_ULong size )
236 {
237 FT_Memory memory = FT_FACE_MEMORY( slot->face );
238
239
240 if ( slot->flags & FT_GLYPH_OWN_BITMAP )
241 FT_FREE( slot->bitmap.buffer );
242 else
243 slot->flags |= FT_GLYPH_OWN_BITMAP;
244
245 return FT_MEM_ALLOC( slot->bitmap.buffer, size );
246 }
247
David Turnerf0df85b2000-06-22 00:17:42 +0000248
Werner Lembergf814d0f2001-06-27 16:18:10 +0000249 static void
250 ft_glyphslot_clear( FT_GlyphSlot slot )
David Turnerf0df85b2000-06-22 00:17:42 +0000251 {
David Turner5ae831c2000-06-30 01:31:22 +0000252 /* free bitmap if needed */
David Turner66cbc202003-03-20 07:04:40 +0000253 ft_glyphslot_free_bitmap( slot );
Werner Lembergfbeb41d2000-07-02 00:27:53 +0000254
David Turnerf0df85b2000-06-22 00:17:42 +0000255 /* clear all public fields in the glyph slot */
David Turner3249c622002-10-31 08:30:19 +0000256 FT_ZERO( &slot->metrics );
257 FT_ZERO( &slot->outline );
258
259 slot->bitmap.width = 0;
260 slot->bitmap.rows = 0;
261 slot->bitmap.pitch = 0;
262 slot->bitmap.pixel_mode = 0;
Werner Lembergc8c6bf52003-04-23 05:38:13 +0000263 /* don't touch 'slot->bitmap.buffer'! */
David Turnerf0df85b2000-06-22 00:17:42 +0000264
265 slot->bitmap_left = 0;
266 slot->bitmap_top = 0;
267 slot->num_subglyphs = 0;
268 slot->subglyphs = 0;
269 slot->control_data = 0;
270 slot->control_len = 0;
271 slot->other = 0;
David Turnerb08fe2d2002-08-27 20:20:29 +0000272 slot->format = FT_GLYPH_FORMAT_NONE;
David Turnerf0df85b2000-06-22 00:17:42 +0000273
274 slot->linearHoriAdvance = 0;
275 slot->linearVertAdvance = 0;
276 }
277
278
Werner Lembergf814d0f2001-06-27 16:18:10 +0000279 static void
280 ft_glyphslot_done( FT_GlyphSlot slot )
David Turnerf0df85b2000-06-22 00:17:42 +0000281 {
282 FT_Driver driver = slot->face->driver;
Werner Lembergf8ba2002002-03-30 13:16:35 +0000283 FT_Driver_Class clazz = driver->clazz;
David Turnerf0df85b2000-06-22 00:17:42 +0000284 FT_Memory memory = driver->root.memory;
285
Werner Lemberga929ba92000-06-25 06:47:11 +0000286
David Turner54e75742000-11-04 02:52:02 +0000287 if ( clazz->done_slot )
288 clazz->done_slot( slot );
289
David Turnerf0df85b2000-06-22 00:17:42 +0000290 /* free bitmap buffer if needed */
David Turner66cbc202003-03-20 07:04:40 +0000291 ft_glyphslot_free_bitmap( slot );
David Turnerf0df85b2000-06-22 00:17:42 +0000292
293 /* free glyph loader */
Werner Lemberga929ba92000-06-25 06:47:11 +0000294 if ( FT_DRIVER_USES_OUTLINES( driver ) )
David Turnerf0df85b2000-06-22 00:17:42 +0000295 {
David Turner54e75742000-11-04 02:52:02 +0000296 FT_GlyphLoader_Done( slot->internal->loader );
297 slot->internal->loader = 0;
David Turnerf0df85b2000-06-22 00:17:42 +0000298 }
299
David Turnere459d742002-03-22 13:52:37 +0000300 FT_FREE( slot->internal );
David Turnerf0df85b2000-06-22 00:17:42 +0000301 }
302
303
Werner Lemberg8ec9dfd2000-11-07 23:56:02 +0000304 /* documentation is in ftobjs.h */
305
Werner Lembergf814d0f2001-06-27 16:18:10 +0000306 FT_BASE_DEF( FT_Error )
307 FT_New_GlyphSlot( FT_Face face,
308 FT_GlyphSlot *aslot )
David Turnerf0df85b2000-06-22 00:17:42 +0000309 {
Werner Lemberga929ba92000-06-25 06:47:11 +0000310 FT_Error error;
311 FT_Driver driver;
Werner Lembergf8ba2002002-03-30 13:16:35 +0000312 FT_Driver_Class clazz;
Werner Lemberga929ba92000-06-25 06:47:11 +0000313 FT_Memory memory;
314 FT_GlyphSlot slot;
315
David Turnerf0df85b2000-06-22 00:17:42 +0000316
David Turnerf0df85b2000-06-22 00:17:42 +0000317 if ( !face || !aslot || !face->driver )
318 return FT_Err_Invalid_Argument;
319
Werner Lembergdeb4e982000-06-29 03:14:25 +0000320 *aslot = 0;
321
David Turnerf0df85b2000-06-22 00:17:42 +0000322 driver = face->driver;
323 clazz = driver->clazz;
324 memory = driver->root.memory;
325
326 FT_TRACE4(( "FT_New_GlyphSlot: Creating new slot object\n" ));
David Turnere459d742002-03-22 13:52:37 +0000327 if ( !FT_ALLOC( slot, clazz->slot_object_size ) )
David Turnerf0df85b2000-06-22 00:17:42 +0000328 {
329 slot->face = face;
330
331 error = ft_glyphslot_init( slot );
Werner Lemberga929ba92000-06-25 06:47:11 +0000332 if ( error )
David Turnerf0df85b2000-06-22 00:17:42 +0000333 {
334 ft_glyphslot_done( slot );
David Turnere459d742002-03-22 13:52:37 +0000335 FT_FREE( slot );
David Turnerf0df85b2000-06-22 00:17:42 +0000336 goto Exit;
337 }
338
339 *aslot = slot;
340 }
341
342 Exit:
343 FT_TRACE4(( "FT_New_GlyphSlot: Return %d\n", error ));
344 return error;
345 }
346
347
Werner Lemberg8ec9dfd2000-11-07 23:56:02 +0000348 /* documentation is in ftobjs.h */
349
Werner Lembergf814d0f2001-06-27 16:18:10 +0000350 FT_BASE_DEF( void )
351 FT_Done_GlyphSlot( FT_GlyphSlot slot )
David Turnerf0df85b2000-06-22 00:17:42 +0000352 {
353 if ( slot )
354 {
Werner Lembergf8ba2002002-03-30 13:16:35 +0000355 FT_Driver driver = slot->face->driver;
356 FT_Memory memory = driver->root.memory;
357 FT_GlyphSlot* parent;
358 FT_GlyphSlot cur;
David Turnerf0df85b2000-06-22 00:17:42 +0000359
Werner Lemberga929ba92000-06-25 06:47:11 +0000360
David Turnerf0df85b2000-06-22 00:17:42 +0000361 /* Remove slot from its parent face's list */
362 parent = &slot->face->glyph;
363 cur = *parent;
Werner Lemberga929ba92000-06-25 06:47:11 +0000364
David Turnerf0df85b2000-06-22 00:17:42 +0000365 while ( cur )
366 {
367 if ( cur == slot )
368 {
369 *parent = cur->next;
Werner Lemberga929ba92000-06-25 06:47:11 +0000370 ft_glyphslot_done( slot );
David Turnere459d742002-03-22 13:52:37 +0000371 FT_FREE( slot );
David Turnerf0df85b2000-06-22 00:17:42 +0000372 break;
373 }
374 cur = cur->next;
375 }
376 }
377 }
378
379
Werner Lemberg90a03302000-11-07 17:21:11 +0000380 /* documentation is in freetype.h */
381
Werner Lembergf814d0f2001-06-27 16:18:10 +0000382 FT_EXPORT_DEF( void )
383 FT_Set_Transform( FT_Face face,
384 FT_Matrix* matrix,
385 FT_Vector* delta )
David Turnerf0df85b2000-06-22 00:17:42 +0000386 {
David Turner54e75742000-11-04 02:52:02 +0000387 FT_Face_Internal internal;
David Turner61d6b2b2001-05-16 17:49:07 +0000388
David Turner54e75742000-11-04 02:52:02 +0000389
David Turnerf0df85b2000-06-22 00:17:42 +0000390 if ( !face )
391 return;
392
David Turner54e75742000-11-04 02:52:02 +0000393 internal = face->internal;
394
395 internal->transform_flags = 0;
David Turnerf0df85b2000-06-22 00:17:42 +0000396
397 if ( !matrix )
398 {
David Turner54e75742000-11-04 02:52:02 +0000399 internal->transform_matrix.xx = 0x10000L;
400 internal->transform_matrix.xy = 0;
401 internal->transform_matrix.yx = 0;
402 internal->transform_matrix.yy = 0x10000L;
403 matrix = &internal->transform_matrix;
David Turnerf0df85b2000-06-22 00:17:42 +0000404 }
405 else
David Turner54e75742000-11-04 02:52:02 +0000406 internal->transform_matrix = *matrix;
David Turnerf0df85b2000-06-22 00:17:42 +0000407
408 /* set transform_flags bit flag 0 if `matrix' isn't the identity */
409 if ( ( matrix->xy | matrix->yx ) ||
410 matrix->xx != 0x10000L ||
411 matrix->yy != 0x10000L )
David Turner54e75742000-11-04 02:52:02 +0000412 internal->transform_flags |= 1;
David Turnerf0df85b2000-06-22 00:17:42 +0000413
414 if ( !delta )
415 {
David Turner54e75742000-11-04 02:52:02 +0000416 internal->transform_delta.x = 0;
417 internal->transform_delta.y = 0;
418 delta = &internal->transform_delta;
David Turnerf0df85b2000-06-22 00:17:42 +0000419 }
420 else
David Turner54e75742000-11-04 02:52:02 +0000421 internal->transform_delta = *delta;
David Turnerf0df85b2000-06-22 00:17:42 +0000422
423 /* set transform_flags bit flag 1 if `delta' isn't the null vector */
424 if ( delta->x | delta->y )
David Turner54e75742000-11-04 02:52:02 +0000425 internal->transform_flags |= 2;
David Turnerf0df85b2000-06-22 00:17:42 +0000426 }
427
428
David Turner27c322e2002-07-08 22:26:11 +0000429 /* documentation is in freetype.h */
430
431 FT_EXPORT_DEF( void )
432 FT_Set_Hint_Flags( FT_Face face,
433 FT_ULong flags )
434 {
435 FT_Face_Internal internal;
436
437 if ( !face )
438 return;
439
440 internal = face->internal;
441
442 internal->hint_flags = (FT_UInt)flags;
443 }
444
445
Werner Lembergf814d0f2001-06-27 16:18:10 +0000446 static FT_Renderer
447 ft_lookup_glyph_renderer( FT_GlyphSlot slot );
Werner Lembergdeb4e982000-06-29 03:14:25 +0000448
449
Werner Lemberg90a03302000-11-07 17:21:11 +0000450 /* documentation is in freetype.h */
451
Werner Lembergf814d0f2001-06-27 16:18:10 +0000452 FT_EXPORT_DEF( FT_Error )
Werner Lemberg6b5c6692002-09-05 15:10:54 +0000453 FT_Load_Glyph( FT_Face face,
454 FT_UInt glyph_index,
455 FT_Int32 load_flags )
David Turnerf0df85b2000-06-22 00:17:42 +0000456 {
457 FT_Error error;
458 FT_Driver driver;
459 FT_GlyphSlot slot;
David Turner5ae831c2000-06-30 01:31:22 +0000460 FT_Library library;
461 FT_Bool autohint;
462 FT_Module hinter;
David Turnerf0df85b2000-06-22 00:17:42 +0000463
Werner Lemberga929ba92000-06-25 06:47:11 +0000464
David Turnerf0df85b2000-06-22 00:17:42 +0000465 if ( !face || !face->size || !face->glyph )
466 return FT_Err_Invalid_Face_Handle;
467
Werner Lembergfd97d132002-06-16 01:14:16 +0000468 if ( glyph_index > (FT_UInt)face->num_glyphs )
David Turnerf0df85b2000-06-22 00:17:42 +0000469 return FT_Err_Invalid_Argument;
470
471 slot = face->glyph;
472 ft_glyphslot_clear( slot );
473
474 driver = face->driver;
475
Werner Lemberg0d535112001-12-19 22:26:12 +0000476 /* if the flag NO_RECURSE is set, we disable hinting and scaling */
David Turnerf0df85b2000-06-22 00:17:42 +0000477 if ( load_flags & FT_LOAD_NO_RECURSE )
David Turnerc9ce9e42000-09-15 17:16:49 +0000478 {
Werner Lembergeddd9902000-10-12 05:05:40 +0000479 /* disable scaling, hinting, and transformation */
480 load_flags |= FT_LOAD_NO_SCALE |
481 FT_LOAD_NO_HINTING |
David Turner80171e02002-10-05 14:57:03 +0000482 FT_LOAD_NO_BITMAP |
David Turnerc9ce9e42000-09-15 17:16:49 +0000483 FT_LOAD_IGNORE_TRANSFORM;
Werner Lembergeddd9902000-10-12 05:05:40 +0000484
David Turnerc9ce9e42000-09-15 17:16:49 +0000485 /* disable bitmap rendering */
Werner Lembergeddd9902000-10-12 05:05:40 +0000486 load_flags &= ~FT_LOAD_RENDER;
David Turnerc9ce9e42000-09-15 17:16:49 +0000487 }
David Turnerf0df85b2000-06-22 00:17:42 +0000488
Werner Lembergcc9fc492000-06-30 06:21:26 +0000489 /* do we need to load the glyph through the auto-hinter? */
David Turner5ae831c2000-06-30 01:31:22 +0000490 library = driver->root.library;
491 hinter = library->auto_hinter;
Werner Lemberg8eb03532001-06-19 23:03:41 +0000492 autohint =
David Turner21f433c2002-08-21 22:06:41 +0000493 FT_BOOL( hinter &&
David Turner00d9f402002-09-08 21:29:11 +0000494 !( load_flags & ( FT_LOAD_NO_SCALE |
495 FT_LOAD_NO_HINTING |
David Turner21f433c2002-08-21 22:06:41 +0000496 FT_LOAD_NO_AUTOHINT ) ) &&
497 FT_DRIVER_IS_SCALABLE( driver ) &&
498 FT_DRIVER_USES_OUTLINES( driver ) );
Werner Lembergcc9fc492000-06-30 06:21:26 +0000499 if ( autohint )
David Turner5ae831c2000-06-30 01:31:22 +0000500 {
501 if ( FT_DRIVER_HAS_HINTER( driver ) &&
Werner Lembergcc9fc492000-06-30 06:21:26 +0000502 !( load_flags & FT_LOAD_FORCE_AUTOHINT ) )
503 autohint = 0;
504 }
Werner Lembergfbeb41d2000-07-02 00:27:53 +0000505
Werner Lembergcc9fc492000-06-30 06:21:26 +0000506 if ( autohint )
David Turner5ae831c2000-06-30 01:31:22 +0000507 {
David Turner9657ef02002-03-14 08:49:59 +0000508 FT_AutoHinter_Service hinting;
Werner Lembergfbeb41d2000-07-02 00:27:53 +0000509
Werner Lembergcc9fc492000-06-30 06:21:26 +0000510
Werner Lemberg0d535112001-12-19 22:26:12 +0000511 /* try to load embedded bitmaps first if available */
512 /* */
513 /* XXX: This is really a temporary hack that should disappear */
514 /* promptly with FreeType 2.1! */
David Turner4937a3e2001-12-19 21:09:16 +0000515 /* */
Werner Lembergeacb9302002-10-07 10:12:43 +0000516 if ( FT_HAS_FIXED_SIZES( face ) &&
David Turner80171e02002-10-05 14:57:03 +0000517 ( load_flags & FT_LOAD_NO_BITMAP ) == 0 )
David Turner4937a3e2001-12-19 21:09:16 +0000518 {
519 error = driver->clazz->load_glyph( slot, face->size,
520 glyph_index,
521 load_flags | FT_LOAD_SBITS_ONLY );
522
David Turnerb08fe2d2002-08-27 20:20:29 +0000523 if ( !error && slot->format == FT_GLYPH_FORMAT_BITMAP )
David Turner4937a3e2001-12-19 21:09:16 +0000524 goto Load_Ok;
525 }
526
527 /* load auto-hinted outline */
David Turner9657ef02002-03-14 08:49:59 +0000528 hinting = (FT_AutoHinter_Service)hinter->clazz->module_interface;
David Turner76a5f622000-11-04 01:55:49 +0000529
530 error = hinting->load_glyph( (FT_AutoHinter)hinter,
531 slot, face->size,
532 glyph_index, load_flags );
David Turner5ae831c2000-06-30 01:31:22 +0000533 }
534 else
David Turner662b3442002-01-03 16:56:59 +0000535 {
David Turner5ae831c2000-06-30 01:31:22 +0000536 error = driver->clazz->load_glyph( slot,
537 face->size,
Werner Lembergcc9fc492000-06-30 06:21:26 +0000538 glyph_index,
539 load_flags );
David Turner662b3442002-01-03 16:56:59 +0000540 if ( error )
541 goto Exit;
542
Werner Lemberg1a0a9792002-01-03 22:06:13 +0000543 /* check that the loaded outline is correct */
David Turner662b3442002-01-03 16:56:59 +0000544 error = FT_Outline_Check( &slot->outline );
545 if ( error )
546 goto Exit;
547 }
David Turnerf0df85b2000-06-22 00:17:42 +0000548
David Turner4937a3e2001-12-19 21:09:16 +0000549 Load_Ok:
David Turnerf0df85b2000-06-22 00:17:42 +0000550 /* compute the advance */
Werner Lemberga929ba92000-06-25 06:47:11 +0000551 if ( load_flags & FT_LOAD_VERTICAL_LAYOUT )
David Turnerf0df85b2000-06-22 00:17:42 +0000552 {
553 slot->advance.x = 0;
554 slot->advance.y = slot->metrics.vertAdvance;
555 }
556 else
557 {
558 slot->advance.x = slot->metrics.horiAdvance;
559 slot->advance.y = 0;
560 }
561
David Turnerc9ce9e42000-09-15 17:16:49 +0000562 /* compute the linear advance in 16.16 pixels */
563 if ( ( load_flags & FT_LOAD_LINEAR_DESIGN ) == 0 )
564 {
565 FT_UInt EM = face->units_per_EM;
566 FT_Size_Metrics* metrics = &face->size->metrics;
Werner Lembergeddd9902000-10-12 05:05:40 +0000567
Werner Lembergf8ba2002002-03-30 13:16:35 +0000568
David Turnerc9ce9e42000-09-15 17:16:49 +0000569 slot->linearHoriAdvance = FT_MulDiv( slot->linearHoriAdvance,
570 (FT_Long)metrics->x_ppem << 16, EM );
571
572 slot->linearVertAdvance = FT_MulDiv( slot->linearVertAdvance,
573 (FT_Long)metrics->y_ppem << 16, EM );
574 }
575
576 if ( ( load_flags & FT_LOAD_IGNORE_TRANSFORM ) == 0 )
David Turnerf0df85b2000-06-22 00:17:42 +0000577 {
David Turner54e75742000-11-04 02:52:02 +0000578 FT_Face_Internal internal = face->internal;
David Turner61d6b2b2001-05-16 17:49:07 +0000579
580
Werner Lembergd1b74752000-08-24 16:29:15 +0000581 /* now, transform the glyph image if needed */
David Turner54e75742000-11-04 02:52:02 +0000582 if ( internal->transform_flags )
David Turner35db7322000-08-24 12:39:40 +0000583 {
584 /* get renderer */
585 FT_Renderer renderer = ft_lookup_glyph_renderer( slot );
Werner Lembergdeb4e982000-06-29 03:14:25 +0000586
Werner Lemberga929ba92000-06-25 06:47:11 +0000587
David Turner35db7322000-08-24 12:39:40 +0000588 if ( renderer )
Werner Lembergdc72aff2000-11-04 08:33:38 +0000589 error = renderer->clazz->transform_glyph(
590 renderer, slot,
591 &internal->transform_matrix,
592 &internal->transform_delta );
David Turner35db7322000-08-24 12:39:40 +0000593 /* transform advance */
David Turner54e75742000-11-04 02:52:02 +0000594 FT_Vector_Transform( &slot->advance, &internal->transform_matrix );
David Turner35db7322000-08-24 12:39:40 +0000595 }
David Turnerc9ce9e42000-09-15 17:16:49 +0000596 }
David Turnerf0df85b2000-06-22 00:17:42 +0000597
David Turnerc9ce9e42000-09-15 17:16:49 +0000598 /* do we need to render the image now? */
599 if ( !error &&
David Turnerb08fe2d2002-08-27 20:20:29 +0000600 slot->format != FT_GLYPH_FORMAT_BITMAP &&
601 slot->format != FT_GLYPH_FORMAT_COMPOSITE &&
David Turnerc9ce9e42000-09-15 17:16:49 +0000602 load_flags & FT_LOAD_RENDER )
603 {
David Turner00d9f402002-09-08 21:29:11 +0000604 FT_Render_Mode mode = FT_LOAD_TARGET_MODE( load_flags );
605
Werner Lemberg68e9f922002-09-27 11:09:23 +0000606
David Turner00d9f402002-09-08 21:29:11 +0000607 if ( mode == FT_RENDER_MODE_NORMAL &&
608 (load_flags & FT_LOAD_MONOCHROME ) )
609 mode = FT_RENDER_MODE_MONO;
610
611 error = FT_Render_Glyph( slot, mode );
Werner Lembergd060a752000-07-20 06:57:41 +0000612 }
David Turner5ae831c2000-06-30 01:31:22 +0000613
Werner Lembergdeb4e982000-06-29 03:14:25 +0000614 Exit:
David Turnerf0df85b2000-06-22 00:17:42 +0000615 return error;
616 }
617
618
Werner Lemberg90a03302000-11-07 17:21:11 +0000619 /* documentation is in freetype.h */
620
Werner Lembergf814d0f2001-06-27 16:18:10 +0000621 FT_EXPORT_DEF( FT_Error )
622 FT_Load_Char( FT_Face face,
623 FT_ULong char_code,
David Turnerf467e6a2002-08-21 21:39:28 +0000624 FT_Int32 load_flags )
David Turnerf0df85b2000-06-22 00:17:42 +0000625 {
Werner Lembergdeb4e982000-06-29 03:14:25 +0000626 FT_UInt glyph_index;
David Turnerf0df85b2000-06-22 00:17:42 +0000627
Werner Lemberga929ba92000-06-25 06:47:11 +0000628
David Turnerf0df85b2000-06-22 00:17:42 +0000629 if ( !face )
630 return FT_Err_Invalid_Face_Handle;
631
632 glyph_index = (FT_UInt)char_code;
Werner Lemberga929ba92000-06-25 06:47:11 +0000633 if ( face->charmap )
David Turnerf0df85b2000-06-22 00:17:42 +0000634 glyph_index = FT_Get_Char_Index( face, char_code );
635
David Turner5ae831c2000-06-30 01:31:22 +0000636 return FT_Load_Glyph( face, glyph_index, load_flags );
David Turnerf0df85b2000-06-22 00:17:42 +0000637 }
638
639
Werner Lemberg7880dd62000-01-10 17:19:45 +0000640 /* destructor for sizes list */
Werner Lembergf814d0f2001-06-27 16:18:10 +0000641 static void
642 destroy_size( FT_Memory memory,
643 FT_Size size,
644 FT_Driver driver )
Werner Lemberg7880dd62000-01-10 17:19:45 +0000645 {
David Turnerf0df85b2000-06-22 00:17:42 +0000646 /* finalize client-specific data */
Werner Lemberga929ba92000-06-25 06:47:11 +0000647 if ( size->generic.finalizer )
David Turnerf0df85b2000-06-22 00:17:42 +0000648 size->generic.finalizer( size );
649
Werner Lemberg7880dd62000-01-10 17:19:45 +0000650 /* finalize format-specific stuff */
Werner Lemberga929ba92000-06-25 06:47:11 +0000651 if ( driver->clazz->done_size )
David Turnerf0df85b2000-06-22 00:17:42 +0000652 driver->clazz->done_size( size );
653
David Turnere459d742002-03-22 13:52:37 +0000654 FT_FREE( size->internal );
655 FT_FREE( size );
Werner Lemberg7880dd62000-01-10 17:19:45 +0000656 }
David Turnerd2b1f351999-12-16 23:11:37 +0000657
658
Werner Lemberg7880dd62000-01-10 17:19:45 +0000659 /* destructor for faces list */
Werner Lembergf814d0f2001-06-27 16:18:10 +0000660 static void
661 destroy_face( FT_Memory memory,
662 FT_Face face,
663 FT_Driver driver )
Werner Lemberg7880dd62000-01-10 17:19:45 +0000664 {
David Turneref3c1262002-03-14 09:22:48 +0000665 FT_Driver_Class clazz = driver->clazz;
David Turnerf0df85b2000-06-22 00:17:42 +0000666
Werner Lembergd060a752000-07-20 06:57:41 +0000667
David Turnerc49f69c2000-07-20 03:44:50 +0000668 /* discard auto-hinting data */
669 if ( face->autohint.finalizer )
670 face->autohint.finalizer( face->autohint.data );
Werner Lembergeddd9902000-10-12 05:05:40 +0000671
Werner Lembergf8ba2002002-03-30 13:16:35 +0000672 /* Discard glyph slots for this face. */
David Turner23bcde12001-10-17 13:48:10 +0000673 /* Beware! FT_Done_GlyphSlot() changes the field `face->glyph' */
Werner Lemberg7880dd62000-01-10 17:19:45 +0000674 while ( face->glyph )
675 FT_Done_GlyphSlot( face->glyph );
676
Werner Lembergf8ba2002002-03-30 13:16:35 +0000677 /* discard all sizes for this face */
Werner Lemberg7880dd62000-01-10 17:19:45 +0000678 FT_List_Finalize( &face->sizes_list,
679 (FT_List_Destructor)destroy_size,
680 memory,
681 driver );
682 face->size = 0;
683
Werner Lembergf8ba2002002-03-30 13:16:35 +0000684 /* now discard client data */
Werner Lemberg7880dd62000-01-10 17:19:45 +0000685 if ( face->generic.finalizer )
686 face->generic.finalizer( face );
687
David Turner2ded2c12002-03-22 22:37:40 +0000688 /* discard charmaps */
689 {
690 FT_Int n;
David Turner25a6e3a2002-06-10 23:03:35 +0000691
Werner Lembergf8ba2002002-03-30 13:16:35 +0000692
David Turner2ded2c12002-03-22 22:37:40 +0000693 for ( n = 0; n < face->num_charmaps; n++ )
694 {
695 FT_CMap cmap = FT_CMAP( face->charmaps[n] );
David Turner25a6e3a2002-06-10 23:03:35 +0000696
Werner Lembergf8ba2002002-03-30 13:16:35 +0000697
David Turner2ded2c12002-03-22 22:37:40 +0000698 FT_CMap_Done( cmap );
David Turner25a6e3a2002-06-10 23:03:35 +0000699
David Turner2ded2c12002-03-22 22:37:40 +0000700 face->charmaps[n] = NULL;
701 }
David Turner25a6e3a2002-06-10 23:03:35 +0000702
David Turner2ded2c12002-03-22 22:37:40 +0000703 FT_FREE( face->charmaps );
704 face->num_charmaps = 0;
705 }
706
David Turner2ded2c12002-03-22 22:37:40 +0000707
David Turnerf0df85b2000-06-22 00:17:42 +0000708 /* finalize format-specific stuff */
Werner Lemberga929ba92000-06-25 06:47:11 +0000709 if ( clazz->done_face )
710 clazz->done_face( face );
David Turnerf0df85b2000-06-22 00:17:42 +0000711
712 /* close the stream for this face if needed */
Werner Lembergf8ba2002002-03-30 13:16:35 +0000713 ft_input_stream_free(
714 face->stream,
Werner Lemberg58b17f92000-07-27 23:29:08 +0000715 ( face->face_flags & FT_FACE_FLAG_EXTERNAL_STREAM ) != 0 );
David Turner7663f222000-02-13 13:37:38 +0000716
David Turner53b3fa12002-02-24 05:26:57 +0000717 face->stream = 0;
718
Werner Lemberg7880dd62000-01-10 17:19:45 +0000719 /* get rid of it */
David Turner23bcde12001-10-17 13:48:10 +0000720 if ( face->internal )
721 {
David Turnere459d742002-03-22 13:52:37 +0000722 FT_FREE( face->internal->postscript_name );
723 FT_FREE( face->internal );
David Turner23bcde12001-10-17 13:48:10 +0000724 }
David Turnere459d742002-03-22 13:52:37 +0000725 FT_FREE( face );
Werner Lemberg7880dd62000-01-10 17:19:45 +0000726 }
David Turnerd2b1f351999-12-16 23:11:37 +0000727
728
Werner Lembergf814d0f2001-06-27 16:18:10 +0000729 static void
730 Destroy_Driver( FT_Driver driver )
David Turnerd2b1f351999-12-16 23:11:37 +0000731 {
David Turnerd2b1f351999-12-16 23:11:37 +0000732 FT_List_Finalize( &driver->faces_list,
733 (FT_List_Destructor)destroy_face,
David Turnerf0df85b2000-06-22 00:17:42 +0000734 driver->root.memory,
David Turnerd2b1f351999-12-16 23:11:37 +0000735 driver );
736
Werner Lembergdeb4e982000-06-29 03:14:25 +0000737 /* check whether we need to drop the driver's glyph loader */
Werner Lemberga929ba92000-06-25 06:47:11 +0000738 if ( FT_DRIVER_USES_OUTLINES( driver ) )
David Turnerf0df85b2000-06-22 00:17:42 +0000739 FT_GlyphLoader_Done( driver->glyph_loader );
David Turnerd2b1f351999-12-16 23:11:37 +0000740 }
741
742
Werner Lemberg547a2522000-02-16 08:23:58 +0000743 /*************************************************************************/
744 /* */
745 /* <Function> */
Antoine Lecac96f69d2002-12-03 00:39:16 +0000746 /* find_unicode_charmap */
747 /* */
748 /* <Description> */
749 /* This function finds a Unicode charmap, if there is one. */
750 /* And if there is more than one, it tries to favour the more */
Werner Lembergc8c6bf52003-04-23 05:38:13 +0000751 /* extensive one, i.e., one that supports UCS-4 against those which */
Antoine Lecac96f69d2002-12-03 00:39:16 +0000752 /* are limited to the BMP (said UCS-2 encoding.) */
753 /* */
754 /* This function is called from open_face() (just below), and also */
Werner Lembergc8c6bf52003-04-23 05:38:13 +0000755 /* from FT_Select_Charmap( ..., FT_ENCODING_UNICODE). */
Antoine Lecac96f69d2002-12-03 00:39:16 +0000756 /* */
757 static FT_Error
758 find_unicode_charmap( FT_Face face )
759 {
760 FT_CharMap* first;
761 FT_CharMap* cur;
762 FT_CharMap* unicmap = NULL; /* some UCS-2 map, if we found it */
763
764
765 /* caller should have already checked that `face' is valid */
766 FT_ASSERT ( face );
767
768 first = face->charmaps;
769
770 if ( !first )
771 return FT_Err_Invalid_CharMap_Handle;
772
David Turnerc528f6f2002-12-18 22:43:07 +0000773 /*
Werner Lembergc8c6bf52003-04-23 05:38:13 +0000774 * The original TrueType specification(s) only specified charmap
David Turnerc528f6f2002-12-18 22:43:07 +0000775 * formats that are capable of mapping 8 or 16 bit character codes to
776 * glyph indices.
777 *
Werner Lembergc8c6bf52003-04-23 05:38:13 +0000778 * However, recent updates to the Apple and OpenType specifications
David Turnerc528f6f2002-12-18 22:43:07 +0000779 * introduced new formats that are capable of mapping 32-bit character
Werner Lembergc8c6bf52003-04-23 05:38:13 +0000780 * codes as well. And these are already used on some fonts, mainly to
David Turnerae26c682003-02-25 20:37:50 +0000781 * map non-BMP Asian ideographs as defined in Unicode.
David Turnerc528f6f2002-12-18 22:43:07 +0000782 *
Werner Lembergc8c6bf52003-04-23 05:38:13 +0000783 * For compatibility purposes, these fonts generally come with
David Turnerc528f6f2002-12-18 22:43:07 +0000784 * *several* Unicode charmaps:
785 *
Werner Lembergc8c6bf52003-04-23 05:38:13 +0000786 * - One of them in the "old" 16-bit format, that cannot access
787 * all glyphs in the font.
David Turnerc528f6f2002-12-18 22:43:07 +0000788 *
Werner Lembergc8c6bf52003-04-23 05:38:13 +0000789 * - Another one in the "new" 32-bit format, that can access all
David Turnerc528f6f2002-12-18 22:43:07 +0000790 * the glyphs.
791 *
Werner Lembergc8c6bf52003-04-23 05:38:13 +0000792 * This function has been written to always favor a 32-bit charmap
793 * when found. Otherwise, a 16-bit one is returned when found.
David Turnerc528f6f2002-12-18 22:43:07 +0000794 */
795
Antoine Lecac96f69d2002-12-03 00:39:16 +0000796 /* since the `interesting' table, with id's 3,10, is normally the */
797 /* last one, we loop backwards. This looses with type1 fonts with */
798 /* non-BMP characters (<.0001%), this wins with .ttf with non-BMP */
799 /* chars (.01% ?), and this is the same about 99.99% of the time! */
800
801 cur = first + face->num_charmaps; /* points after the last one */
802
803 for ( ; --cur >= first; )
804 {
805 if ( cur[0]->encoding == FT_ENCODING_UNICODE )
806 {
807 unicmap = cur; /* record we found a Unicode charmap */
808
809 /* XXX If some new encodings to represent UCS-4 are added, */
810 /* they should be added here. */
David Turnerc528f6f2002-12-18 22:43:07 +0000811 if ( ( cur[0]->platform_id == TT_PLATFORM_MICROSOFT &&
812 cur[0]->encoding_id == TT_MS_ID_UCS_4 ) ||
813 ( cur[0]->platform_id == TT_PLATFORM_APPLE_UNICODE &&
814 cur[0]->encoding_id == TT_APPLE_ID_UNICODE_32 ) )
815
Antoine Lecac96f69d2002-12-03 00:39:16 +0000816 /* Hurray! We found a UCS-4 charmap. We can stop the scan! */
817 {
818 face->charmap = cur[0];
819 return 0;
820 }
821 }
822 }
823
824 /* We do not have any UCS-4 charmap. Sigh. */
825 /* Let's see if we have some other kind of Unicode charmap, though. */
826 if ( unicmap != NULL )
827 {
828 face->charmap = unicmap[0];
829 return 0;
830 }
831
832 /* Chou blanc! */
David Turner6453a812003-01-08 09:28:34 +0000833 return FT_Err_Invalid_CharMap_Handle;
Antoine Lecac96f69d2002-12-03 00:39:16 +0000834 }
835
836
837 /*************************************************************************/
838 /* */
839 /* <Function> */
Werner Lemberg547a2522000-02-16 08:23:58 +0000840 /* open_face */
841 /* */
842 /* <Description> */
843 /* This function does some work for FT_Open_Face(). */
844 /* */
Werner Lembergf814d0f2001-06-27 16:18:10 +0000845 static FT_Error
846 open_face( FT_Driver driver,
847 FT_Stream stream,
848 FT_Long face_index,
849 FT_Int num_params,
850 FT_Parameter* params,
851 FT_Face* aface )
David Turnerd2b1f351999-12-16 23:11:37 +0000852 {
David Turnerf0df85b2000-06-22 00:17:42 +0000853 FT_Memory memory;
David Turneref3c1262002-03-14 09:22:48 +0000854 FT_Driver_Class clazz;
David Turnerf0df85b2000-06-22 00:17:42 +0000855 FT_Face face = 0;
Antoine Lecac96f69d2002-12-03 00:39:16 +0000856 FT_Error error, error2;
David Turner54e75742000-11-04 02:52:02 +0000857 FT_Face_Internal internal;
David Turnerd2b1f351999-12-16 23:11:37 +0000858
Werner Lemberg3c403e42002-08-06 21:47:40 +0000859
David Turnerf0df85b2000-06-22 00:17:42 +0000860 clazz = driver->clazz;
861 memory = driver->root.memory;
David Turnerd2b1f351999-12-16 23:11:37 +0000862
Werner Lembergdeb4e982000-06-29 03:14:25 +0000863 /* allocate the face object and perform basic initialization */
David Turnere459d742002-03-22 13:52:37 +0000864 if ( FT_ALLOC( face, clazz->face_object_size ) )
David Turnerd2b1f351999-12-16 23:11:37 +0000865 goto Fail;
866
David Turnere459d742002-03-22 13:52:37 +0000867 if ( FT_NEW( internal ) )
David Turner54e75742000-11-04 02:52:02 +0000868 goto Fail;
David Turner61d6b2b2001-05-16 17:49:07 +0000869
David Turner54e75742000-11-04 02:52:02 +0000870 face->internal = internal;
871
872 face->driver = driver;
873 face->memory = memory;
874 face->stream = stream;
Graham Asherce121822002-08-01 15:29:17 +0000875
Graham Asherd53cf1d2002-07-18 15:04:29 +0000876#ifdef FT_CONFIG_OPTION_INCREMENTAL
Werner Lemberg3c403e42002-08-06 21:47:40 +0000877 {
878 int i;
879
880
881 face->internal->incremental_interface = 0;
882 for ( i = 0; i < num_params && !face->internal->incremental_interface;
883 i++ )
884 if ( params[i].tag == FT_PARAM_TAG_INCREMENTAL )
885 face->internal->incremental_interface = params[i].data;
Antoine Lecac96f69d2002-12-03 00:39:16 +0000886 }
Graham Asherd53cf1d2002-07-18 15:04:29 +0000887#endif
David Turnerd2b1f351999-12-16 23:11:37 +0000888
David Turnerf0df85b2000-06-22 00:17:42 +0000889 error = clazz->init_face( stream,
890 face,
Werner Lemberg68e9f922002-09-27 11:09:23 +0000891 (FT_Int)face_index,
David Turnerf0df85b2000-06-22 00:17:42 +0000892 num_params,
893 params );
David Turnerd2b1f351999-12-16 23:11:37 +0000894 if ( error )
895 goto Fail;
896
David Turnerfed59b72002-07-17 22:51:06 +0000897 /* select Unicode charmap by default */
Antoine Lecac96f69d2002-12-03 00:39:16 +0000898 error2 = find_unicode_charmap( face );
David Turnerc528f6f2002-12-18 22:43:07 +0000899
900 /* if no Unicode charmap can be found, FT_Err_Invalid_CharMap_Handle is
901 * returned.
902 */
Antoine Lecac96f69d2002-12-03 00:39:16 +0000903
904 /* no error should happen, but we want to play safe. */
David Turnerc528f6f2002-12-18 22:43:07 +0000905 if ( error2 && error2 != FT_Err_Invalid_CharMap_Handle )
David Turnerfed59b72002-07-17 22:51:06 +0000906 {
Antoine Lecac96f69d2002-12-03 00:39:16 +0000907 error = error2;
908 goto Fail;
David Turnerfed59b72002-07-17 22:51:06 +0000909 }
910
David Turnerd2b1f351999-12-16 23:11:37 +0000911 *aface = face;
912
913 Fail:
914 if ( error )
915 {
David Turnerf0df85b2000-06-22 00:17:42 +0000916 clazz->done_face( face );
David Turnere459d742002-03-22 13:52:37 +0000917 FT_FREE( face->internal );
918 FT_FREE( face );
David Turnerd2b1f351999-12-16 23:11:37 +0000919 *aface = 0;
920 }
921
922 return error;
923 }
924
925
Werner Lemberg05c21b82000-07-29 20:38:19 +0000926 /* there's a Mac-specific extended implementation of FT_New_Face() */
Werner Lemberg4d631e42002-05-27 13:02:37 +0000927 /* in src/base/ftmac.c */
Werner Lemberg05c21b82000-07-29 20:38:19 +0000928
Werner Lemberg9ca7a152002-04-30 14:26:49 +0000929#ifndef FT_MACINTOSH
Just van Rossum9e830c52000-07-28 01:12:34 +0000930
Werner Lemberg90a03302000-11-07 17:21:11 +0000931 /* documentation is in freetype.h */
932
Werner Lembergf814d0f2001-06-27 16:18:10 +0000933 FT_EXPORT_DEF( FT_Error )
934 FT_New_Face( FT_Library library,
935 const char* pathname,
936 FT_Long face_index,
937 FT_Face *aface )
David Turnerd2b1f351999-12-16 23:11:37 +0000938 {
David Turner37379e22000-03-28 11:22:31 +0000939 FT_Open_Args args;
Werner Lemberg547a2522000-02-16 08:23:58 +0000940
Werner Lemberga929ba92000-06-25 06:47:11 +0000941
Werner Lemberg2fbf7e42000-06-02 00:01:14 +0000942 /* test for valid `library' and `aface' delayed to FT_Open_Face() */
Werner Lemberg2fbf7e42000-06-02 00:01:14 +0000943 if ( !pathname )
944 return FT_Err_Invalid_Argument;
945
David Turnerb08fe2d2002-08-27 20:20:29 +0000946 args.flags = FT_OPEN_PATHNAME;
David Turner4f2c5542000-05-12 10:19:41 +0000947 args.pathname = (char*)pathname;
Werner Lemberga3b6c6c2000-05-31 06:55:12 +0000948
David Turnercda32b72000-02-10 16:14:35 +0000949 return FT_Open_Face( library, &args, face_index, aface );
David Turnerd2b1f351999-12-16 23:11:37 +0000950 }
951
Werner Lemberg9ca7a152002-04-30 14:26:49 +0000952#endif /* !FT_MACINTOSH */
Just van Rossum9e830c52000-07-28 01:12:34 +0000953
Werner Lemberg7880dd62000-01-10 17:19:45 +0000954
Werner Lemberg90a03302000-11-07 17:21:11 +0000955 /* documentation is in freetype.h */
956
Werner Lembergf814d0f2001-06-27 16:18:10 +0000957 FT_EXPORT_DEF( FT_Error )
958 FT_New_Memory_Face( FT_Library library,
959 const FT_Byte* file_base,
960 FT_Long file_size,
961 FT_Long face_index,
962 FT_Face *aface )
David Turnerd2b1f351999-12-16 23:11:37 +0000963 {
David Turner37379e22000-03-28 11:22:31 +0000964 FT_Open_Args args;
Werner Lemberg7880dd62000-01-10 17:19:45 +0000965
Werner Lemberga929ba92000-06-25 06:47:11 +0000966
Werner Lemberg2fbf7e42000-06-02 00:01:14 +0000967 /* test for valid `library' and `face' delayed to FT_Open_Face() */
Werner Lemberg2fbf7e42000-06-02 00:01:14 +0000968 if ( !file_base )
969 return FT_Err_Invalid_Argument;
970
David Turnerb08fe2d2002-08-27 20:20:29 +0000971 args.flags = FT_OPEN_MEMORY;
David Turnercda32b72000-02-10 16:14:35 +0000972 args.memory_base = file_base;
973 args.memory_size = file_size;
Werner Lemberga3b6c6c2000-05-31 06:55:12 +0000974
Werner Lemberg4b680072000-11-07 06:30:29 +0000975 return FT_Open_Face( library, &args, face_index, aface );
David Turnerd2b1f351999-12-16 23:11:37 +0000976 }
977
Werner Lemberg7880dd62000-01-10 17:19:45 +0000978
Werner Lemberg90a03302000-11-07 17:21:11 +0000979 /* documentation is in freetype.h */
980
Werner Lembergf814d0f2001-06-27 16:18:10 +0000981 FT_EXPORT_DEF( FT_Error )
Werner Lembergc4c373c2002-10-07 09:15:20 +0000982 FT_Open_Face( FT_Library library,
983 const FT_Open_Args* args,
984 FT_Long face_index,
985 FT_Face *aface )
David Turnerd2b1f351999-12-16 23:11:37 +0000986 {
987 FT_Error error;
988 FT_Driver driver;
989 FT_Memory memory;
David Turnercda32b72000-02-10 16:14:35 +0000990 FT_Stream stream;
David Turnerd2b1f351999-12-16 23:11:37 +0000991 FT_Face face = 0;
992 FT_ListNode node = 0;
David Turnerc5cdf8b2000-07-27 21:40:22 +0000993 FT_Bool external_stream;
Werner Lemberg547a2522000-02-16 08:23:58 +0000994
Werner Lemberg58b17f92000-07-27 23:29:08 +0000995
Werner Lembergf9b03752000-09-11 22:50:13 +0000996 /* test for valid `library' delayed to */
David Turner53b3fa12002-02-24 05:26:57 +0000997 /* ft_input_stream_new() */
David Turnerd2b1f351999-12-16 23:11:37 +0000998
Werner Lembergf9b03752000-09-11 22:50:13 +0000999 if ( !aface || !args )
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001000 return FT_Err_Invalid_Argument;
1001
1002 *aface = 0;
David Turnerd2b1f351999-12-16 23:11:37 +00001003
David Turnerb08fe2d2002-08-27 20:20:29 +00001004 external_stream = FT_BOOL( ( args->flags & FT_OPEN_STREAM ) &&
Werner Lemberg8eb03532001-06-19 23:03:41 +00001005 args->stream );
David Turnerc5cdf8b2000-07-27 21:40:22 +00001006
David Turnercda32b72000-02-10 16:14:35 +00001007 /* create input stream */
David Turner53b3fa12002-02-24 05:26:57 +00001008 error = ft_input_stream_new( library, args, &stream );
Werner Lembergdeb4e982000-06-29 03:14:25 +00001009 if ( error )
1010 goto Exit;
David Turnercda32b72000-02-10 16:14:35 +00001011
David Turnerd2b1f351999-12-16 23:11:37 +00001012 memory = library->memory;
1013
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001014 /* If the font driver is specified in the `args' structure, use */
Werner Lembergdeb4e982000-06-29 03:14:25 +00001015 /* it. Otherwise, we scan the list of registered drivers. */
David Turnerb08fe2d2002-08-27 20:20:29 +00001016 if ( ( args->flags & FT_OPEN_DRIVER ) && args->driver )
David Turner7663f222000-02-13 13:37:38 +00001017 {
Werner Lemberga929ba92000-06-25 06:47:11 +00001018 driver = FT_DRIVER( args->driver );
David Turnerf0df85b2000-06-22 00:17:42 +00001019
1020 /* not all modules are drivers, so check... */
Werner Lemberga929ba92000-06-25 06:47:11 +00001021 if ( FT_MODULE_IS_DRIVER( driver ) )
David Turner7663f222000-02-13 13:37:38 +00001022 {
Werner Lemberg3c403e42002-08-06 21:47:40 +00001023 FT_Int num_params = 0;
1024 FT_Parameter* params = 0;
1025
Werner Lemberga929ba92000-06-25 06:47:11 +00001026
David Turnerb08fe2d2002-08-27 20:20:29 +00001027 if ( args->flags & FT_OPEN_PARAMS )
David Turner4f2c5542000-05-12 10:19:41 +00001028 {
1029 num_params = args->num_params;
1030 params = args->params;
1031 }
David Turnere49ab252000-05-16 23:44:38 +00001032
David Turner4f2c5542000-05-12 10:19:41 +00001033 error = open_face( driver, stream, face_index,
1034 num_params, params, &face );
Werner Lemberg547a2522000-02-16 08:23:58 +00001035 if ( !error )
1036 goto Success;
David Turner7663f222000-02-13 13:37:38 +00001037 }
1038 else
1039 error = FT_Err_Invalid_Handle;
1040
David Turner53b3fa12002-02-24 05:26:57 +00001041 ft_input_stream_free( stream, external_stream );
David Turner7663f222000-02-13 13:37:38 +00001042 goto Fail;
1043 }
Just van Rossum1e5754f2000-03-02 10:52:57 +00001044 else
David Turnerd2b1f351999-12-16 23:11:37 +00001045 {
1046 /* check each font driver for an appropriate format */
David Turnerf0df85b2000-06-22 00:17:42 +00001047 FT_Module* cur = library->modules;
1048 FT_Module* limit = cur + library->num_modules;
David Turnerd2b1f351999-12-16 23:11:37 +00001049
Werner Lemberga929ba92000-06-25 06:47:11 +00001050
David Turnerd2b1f351999-12-16 23:11:37 +00001051 for ( ; cur < limit; cur++ )
1052 {
David Turnerf0df85b2000-06-22 00:17:42 +00001053 /* not all modules are font drivers, so check... */
Werner Lemberga929ba92000-06-25 06:47:11 +00001054 if ( FT_MODULE_IS_DRIVER( cur[0] ) )
David Turnerd2b1f351999-12-16 23:11:37 +00001055 {
David Turner4f2c5542000-05-12 10:19:41 +00001056 FT_Int num_params = 0;
1057 FT_Parameter* params = 0;
David Turnere49ab252000-05-16 23:44:38 +00001058
Werner Lemberg3c403e42002-08-06 21:47:40 +00001059
Werner Lemberga929ba92000-06-25 06:47:11 +00001060 driver = FT_DRIVER( cur[0] );
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001061
David Turnerb08fe2d2002-08-27 20:20:29 +00001062 if ( args->flags & FT_OPEN_PARAMS )
David Turner4f2c5542000-05-12 10:19:41 +00001063 {
1064 num_params = args->num_params;
1065 params = args->params;
1066 }
David Turnere49ab252000-05-16 23:44:38 +00001067
Graham Asherd53cf1d2002-07-18 15:04:29 +00001068 error = open_face( driver, stream, face_index,
1069 num_params, params, &face );
David Turnerd2b1f351999-12-16 23:11:37 +00001070 if ( !error )
1071 goto Success;
1072
Werner Lemberg79860702001-06-08 21:17:29 +00001073 if ( FT_ERROR_BASE( error ) != FT_Err_Unknown_File_Format )
David Turnerebe85f52001-05-11 14:25:57 +00001074 goto Fail2;
David Turnerd2b1f351999-12-16 23:11:37 +00001075 }
1076 }
1077
1078 /* no driver is able to handle this format */
1079 error = FT_Err_Unknown_File_Format;
David Turnerebe85f52001-05-11 14:25:57 +00001080
1081 Fail2:
David Turner53b3fa12002-02-24 05:26:57 +00001082 ft_input_stream_free( stream, external_stream );
David Turnercda32b72000-02-10 16:14:35 +00001083 goto Fail;
David Turnerd2b1f351999-12-16 23:11:37 +00001084 }
1085
1086 Success:
Werner Lembergf9b03752000-09-11 22:50:13 +00001087 FT_TRACE4(( "FT_Open_Face: New face object, adding to list\n" ));
David Turnerd2b1f351999-12-16 23:11:37 +00001088
Werner Lembergdeb4e982000-06-29 03:14:25 +00001089 /* set the FT_FACE_FLAG_EXTERNAL_STREAM bit for FT_Done_Face */
David Turnerc5cdf8b2000-07-27 21:40:22 +00001090 if ( external_stream )
David Turnerf0df85b2000-06-22 00:17:42 +00001091 face->face_flags |= FT_FACE_FLAG_EXTERNAL_STREAM;
1092
Werner Lemberg547a2522000-02-16 08:23:58 +00001093 /* add the face object to its driver's list */
David Turnere459d742002-03-22 13:52:37 +00001094 if ( FT_NEW( node ) )
David Turnerd2b1f351999-12-16 23:11:37 +00001095 goto Fail;
1096
1097 node->data = face;
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001098 /* don't assume driver is the same as face->driver, so use */
1099 /* face->driver instead. */
Just van Rossum7eef5362000-03-05 16:07:58 +00001100 FT_List_Add( &face->driver->faces_list, node );
David Turnerd2b1f351999-12-16 23:11:37 +00001101
Werner Lemberg547a2522000-02-16 08:23:58 +00001102 /* now allocate a glyph slot object for the face */
David Turnerd2b1f351999-12-16 23:11:37 +00001103 {
1104 FT_GlyphSlot slot;
1105
Werner Lemberg547a2522000-02-16 08:23:58 +00001106
David Turnerd2b1f351999-12-16 23:11:37 +00001107 FT_TRACE4(( "FT_Open_Face: Creating glyph slot\n" ));
Werner Lembergdeb4e982000-06-29 03:14:25 +00001108
David Turnerd2b1f351999-12-16 23:11:37 +00001109 error = FT_New_GlyphSlot( face, &slot );
Werner Lembergdeb4e982000-06-29 03:14:25 +00001110 if ( error )
1111 goto Fail;
1112
David Turnerf0df85b2000-06-22 00:17:42 +00001113 face->glyph = slot;
David Turnerd2b1f351999-12-16 23:11:37 +00001114 }
Werner Lemberg7880dd62000-01-10 17:19:45 +00001115
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001116 /* finally, allocate a size object for the face */
David Turnerd2b1f351999-12-16 23:11:37 +00001117 {
1118 FT_Size size;
1119
Werner Lemberg547a2522000-02-16 08:23:58 +00001120
David Turnerd2b1f351999-12-16 23:11:37 +00001121 FT_TRACE4(( "FT_Open_Face: Creating size object\n" ));
Werner Lembergdeb4e982000-06-29 03:14:25 +00001122
David Turnerd2b1f351999-12-16 23:11:37 +00001123 error = FT_New_Size( face, &size );
Werner Lembergdeb4e982000-06-29 03:14:25 +00001124 if ( error )
1125 goto Fail;
1126
David Turnerf0df85b2000-06-22 00:17:42 +00001127 face->size = size;
David Turnerd2b1f351999-12-16 23:11:37 +00001128 }
Werner Lemberg7880dd62000-01-10 17:19:45 +00001129
David Turner54e75742000-11-04 02:52:02 +00001130 /* initialize internal face data */
1131 {
1132 FT_Face_Internal internal = face->internal;
David Turner61d6b2b2001-05-16 17:49:07 +00001133
David Turner37379e22000-03-28 11:22:31 +00001134
David Turner54e75742000-11-04 02:52:02 +00001135 internal->transform_matrix.xx = 0x10000L;
1136 internal->transform_matrix.xy = 0;
1137 internal->transform_matrix.yx = 0;
1138 internal->transform_matrix.yy = 0x10000L;
David Turner61d6b2b2001-05-16 17:49:07 +00001139
David Turner54e75742000-11-04 02:52:02 +00001140 internal->transform_delta.x = 0;
1141 internal->transform_delta.y = 0;
1142 }
David Turner37379e22000-03-28 11:22:31 +00001143
David Turnerd2b1f351999-12-16 23:11:37 +00001144 *aface = face;
1145 goto Exit;
1146
1147 Fail:
1148 FT_Done_Face( face );
1149
David Turnerd2b1f351999-12-16 23:11:37 +00001150 Exit:
1151 FT_TRACE4(( "FT_Open_Face: Return %d\n", error ));
Werner Lembergdeb4e982000-06-29 03:14:25 +00001152
David Turnerd2b1f351999-12-16 23:11:37 +00001153 return error;
1154 }
1155
1156
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_Attach_File( FT_Face face,
1161 const char* filepathname )
David Turner7663f222000-02-13 13:37:38 +00001162 {
David Turner37379e22000-03-28 11:22:31 +00001163 FT_Open_Args open;
David Turner7663f222000-02-13 13:37:38 +00001164
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001165
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001166 /* test for valid `face' delayed to FT_Attach_Stream() */
1167
1168 if ( !filepathname )
1169 return FT_Err_Invalid_Argument;
1170
David Turnerb08fe2d2002-08-27 20:20:29 +00001171 open.flags = FT_OPEN_PATHNAME;
David Turner4f2c5542000-05-12 10:19:41 +00001172 open.pathname = (char*)filepathname;
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001173
David Turner7663f222000-02-13 13:37:38 +00001174 return FT_Attach_Stream( face, &open );
1175 }
Werner Lemberg547a2522000-02-16 08:23:58 +00001176
David Turnere49ab252000-05-16 23:44:38 +00001177
Werner Lemberg90a03302000-11-07 17:21:11 +00001178 /* documentation is in freetype.h */
1179
Werner Lembergf814d0f2001-06-27 16:18:10 +00001180 FT_EXPORT_DEF( FT_Error )
1181 FT_Attach_Stream( FT_Face face,
1182 FT_Open_Args* parameters )
David Turner7663f222000-02-13 13:37:38 +00001183 {
1184 FT_Stream stream;
1185 FT_Error error;
1186 FT_Driver driver;
David Turnere49ab252000-05-16 23:44:38 +00001187
David Turneref3c1262002-03-14 09:22:48 +00001188 FT_Driver_Class clazz;
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001189
Werner Lemberga929ba92000-06-25 06:47:11 +00001190
David Turner53b3fa12002-02-24 05:26:57 +00001191 /* test for valid `parameters' delayed to ft_input_stream_new() */
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001192
1193 if ( !face )
1194 return FT_Err_Invalid_Face_Handle;
David Turnere49ab252000-05-16 23:44:38 +00001195
David Turner7663f222000-02-13 13:37:38 +00001196 driver = face->driver;
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001197 if ( !driver )
1198 return FT_Err_Invalid_Driver_Handle;
1199
David Turner53b3fa12002-02-24 05:26:57 +00001200 error = ft_input_stream_new( driver->root.library, parameters, &stream );
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001201 if ( error )
1202 goto Exit;
David Turnere49ab252000-05-16 23:44:38 +00001203
David Turner7663f222000-02-13 13:37:38 +00001204 /* we implement FT_Attach_Stream in each driver through the */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001205 /* `attach_file' interface */
1206
David Turner7663f222000-02-13 13:37:38 +00001207 error = FT_Err_Unimplemented_Feature;
David Turnerf0df85b2000-06-22 00:17:42 +00001208 clazz = driver->clazz;
Werner Lemberga929ba92000-06-25 06:47:11 +00001209 if ( clazz->attach_file )
David Turnerf0df85b2000-06-22 00:17:42 +00001210 error = clazz->attach_file( face, stream );
David Turnere49ab252000-05-16 23:44:38 +00001211
David Turner7663f222000-02-13 13:37:38 +00001212 /* close the attached stream */
David Turner53b3fa12002-02-24 05:26:57 +00001213 ft_input_stream_free( stream,
Werner Lemberg58b17f92000-07-27 23:29:08 +00001214 (FT_Bool)( parameters->stream &&
David Turnerb08fe2d2002-08-27 20:20:29 +00001215 ( parameters->flags & FT_OPEN_STREAM ) ) );
David Turnere49ab252000-05-16 23:44:38 +00001216
David Turner7663f222000-02-13 13:37:38 +00001217 Exit:
1218 return error;
1219 }
1220
1221
Werner Lemberg90a03302000-11-07 17:21:11 +00001222 /* documentation is in freetype.h */
1223
Werner Lembergf814d0f2001-06-27 16:18:10 +00001224 FT_EXPORT_DEF( FT_Error )
1225 FT_Done_Face( FT_Face face )
David Turnerd2b1f351999-12-16 23:11:37 +00001226 {
Werner Lemberga929ba92000-06-25 06:47:11 +00001227 FT_Error error;
1228 FT_Driver driver;
1229 FT_Memory memory;
1230 FT_ListNode node;
1231
David Turnerd2b1f351999-12-16 23:11:37 +00001232
David Turnerf0df85b2000-06-22 00:17:42 +00001233 error = FT_Err_Invalid_Face_Handle;
1234 if ( face && face->driver )
David Turnerd2b1f351999-12-16 23:11:37 +00001235 {
David Turnerf0df85b2000-06-22 00:17:42 +00001236 driver = face->driver;
1237 memory = driver->root.memory;
Werner Lembergdeb4e982000-06-29 03:14:25 +00001238
David Turnerf0df85b2000-06-22 00:17:42 +00001239 /* find face in driver's list */
1240 node = FT_List_Find( &driver->faces_list, face );
1241 if ( node )
1242 {
1243 /* remove face object from the driver's list */
1244 FT_List_Remove( &driver->faces_list, node );
David Turnere459d742002-03-22 13:52:37 +00001245 FT_FREE( node );
Werner Lembergdeb4e982000-06-29 03:14:25 +00001246
David Turnerf0df85b2000-06-22 00:17:42 +00001247 /* now destroy the object proper */
1248 destroy_face( memory, face, driver );
1249 error = FT_Err_Ok;
1250 }
David Turnerd2b1f351999-12-16 23:11:37 +00001251 }
David Turnerd2b1f351999-12-16 23:11:37 +00001252 return error;
1253 }
1254
1255
Werner Lemberg90a03302000-11-07 17:21:11 +00001256 /* documentation is in ftobjs.h */
1257
Werner Lembergf814d0f2001-06-27 16:18:10 +00001258 FT_EXPORT_DEF( FT_Error )
1259 FT_New_Size( FT_Face face,
1260 FT_Size *asize )
David Turnerd2b1f351999-12-16 23:11:37 +00001261 {
Werner Lembergf8ba2002002-03-30 13:16:35 +00001262 FT_Error error;
1263 FT_Memory memory;
1264 FT_Driver driver;
David Turneref3c1262002-03-14 09:22:48 +00001265 FT_Driver_Class clazz;
David Turnerd2b1f351999-12-16 23:11:37 +00001266
Werner Lembergf8ba2002002-03-30 13:16:35 +00001267 FT_Size size = 0;
1268 FT_ListNode node = 0;
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001269
Werner Lemberga929ba92000-06-25 06:47:11 +00001270
Werner Lembergb48a6092000-07-09 19:15:30 +00001271 if ( !face )
1272 return FT_Err_Invalid_Face_Handle;
1273
1274 if ( !asize )
1275 return FT_Err_Invalid_Size_Handle;
1276
1277 if ( !face->driver )
1278 return FT_Err_Invalid_Driver_Handle;
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001279
Werner Lembergdeb4e982000-06-29 03:14:25 +00001280 *asize = 0;
1281
David Turnerf0df85b2000-06-22 00:17:42 +00001282 driver = face->driver;
1283 clazz = driver->clazz;
1284 memory = face->memory;
David Turnerd2b1f351999-12-16 23:11:37 +00001285
1286 /* Allocate new size object and perform basic initialisation */
David Turnere459d742002-03-22 13:52:37 +00001287 if ( FT_ALLOC( size, clazz->size_object_size ) || FT_NEW( node ) )
David Turnerd2b1f351999-12-16 23:11:37 +00001288 goto Exit;
1289
1290 size->face = face;
David Turner61d6b2b2001-05-16 17:49:07 +00001291
David Turner54e75742000-11-04 02:52:02 +00001292 /* for now, do not use any internal fields in size objects */
1293 size->internal = 0;
David Turnerd2b1f351999-12-16 23:11:37 +00001294
Werner Lemberga929ba92000-06-25 06:47:11 +00001295 if ( clazz->init_size )
David Turnerf0df85b2000-06-22 00:17:42 +00001296 error = clazz->init_size( size );
David Turnerd2b1f351999-12-16 23:11:37 +00001297
1298 /* in case of success, add to the face's list */
1299 if ( !error )
1300 {
1301 *asize = size;
1302 node->data = size;
1303 FT_List_Add( &face->sizes_list, node );
David Turnerd2b1f351999-12-16 23:11:37 +00001304 }
1305
1306 Exit:
1307 if ( error )
1308 {
David Turnere459d742002-03-22 13:52:37 +00001309 FT_FREE( node );
1310 FT_FREE( size );
David Turnerd2b1f351999-12-16 23:11:37 +00001311 }
1312
1313 return error;
1314 }
1315
1316
Werner Lemberg90a03302000-11-07 17:21:11 +00001317 /* documentation is in ftobjs.h */
1318
Werner Lembergf814d0f2001-06-27 16:18:10 +00001319 FT_EXPORT_DEF( FT_Error )
1320 FT_Done_Size( FT_Size size )
David Turnerd2b1f351999-12-16 23:11:37 +00001321 {
1322 FT_Error error;
1323 FT_Driver driver;
1324 FT_Memory memory;
1325 FT_Face face;
1326 FT_ListNode node;
1327
1328
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001329 if ( !size )
David Turnerd2b1f351999-12-16 23:11:37 +00001330 return FT_Err_Invalid_Size_Handle;
1331
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001332 face = size->face;
1333 if ( !face )
1334 return FT_Err_Invalid_Face_Handle;
1335
1336 driver = face->driver;
David Turnerd2b1f351999-12-16 23:11:37 +00001337 if ( !driver )
1338 return FT_Err_Invalid_Driver_Handle;
1339
David Turnerf0df85b2000-06-22 00:17:42 +00001340 memory = driver->root.memory;
David Turnerd2b1f351999-12-16 23:11:37 +00001341
1342 error = FT_Err_Ok;
David Turnerd2b1f351999-12-16 23:11:37 +00001343 node = FT_List_Find( &face->sizes_list, size );
1344 if ( node )
1345 {
1346 FT_List_Remove( &face->sizes_list, node );
David Turnere459d742002-03-22 13:52:37 +00001347 FT_FREE( node );
David Turnerd2b1f351999-12-16 23:11:37 +00001348
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001349 if ( face->size == size )
David Turnerd2b1f351999-12-16 23:11:37 +00001350 {
1351 face->size = 0;
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001352 if ( face->sizes_list.head )
David Turnerd2b1f351999-12-16 23:11:37 +00001353 face->size = (FT_Size)(face->sizes_list.head->data);
1354 }
1355
1356 destroy_size( memory, size, driver );
1357 }
1358 else
1359 error = FT_Err_Invalid_Size_Handle;
1360
Werner Lembergcf24d512001-06-18 14:23:45 +00001361 return error;
David Turnerd2b1f351999-12-16 23:11:37 +00001362 }
1363
1364
Werner Lembergf814d0f2001-06-27 16:18:10 +00001365 static void
1366 ft_recompute_scaled_metrics( FT_Face face,
1367 FT_Size_Metrics* metrics )
Werner Lembergdeb4e982000-06-29 03:14:25 +00001368 {
Werner Lemberga929ba92000-06-25 06:47:11 +00001369 /* Compute root ascender, descender, test height, and max_advance */
Werner Lembergdeb4e982000-06-29 03:14:25 +00001370
Werner Lemberga929ba92000-06-25 06:47:11 +00001371 metrics->ascender = ( FT_MulFix( face->ascender,
David Turnerba4511b2003-02-18 22:25:22 +00001372 metrics->y_scale ) + 63 ) & -64;
Werner Lemberga929ba92000-06-25 06:47:11 +00001373
1374 metrics->descender = ( FT_MulFix( face->descender,
David Turnerba4511b2003-02-18 22:25:22 +00001375 metrics->y_scale ) + 0 ) & -64;
Werner Lemberga929ba92000-06-25 06:47:11 +00001376
1377 metrics->height = ( FT_MulFix( face->height,
1378 metrics->y_scale ) + 32 ) & -64;
1379
1380 metrics->max_advance = ( FT_MulFix( face->max_advance_width,
1381 metrics->x_scale ) + 32 ) & -64;
1382 }
1383
1384
Werner Lemberg90a03302000-11-07 17:21:11 +00001385 /* documentation is in freetype.h */
1386
Werner Lembergf814d0f2001-06-27 16:18:10 +00001387 FT_EXPORT_DEF( FT_Error )
1388 FT_Set_Char_Size( FT_Face face,
1389 FT_F26Dot6 char_width,
1390 FT_F26Dot6 char_height,
1391 FT_UInt horz_resolution,
1392 FT_UInt vert_resolution )
David Turnerd2b1f351999-12-16 23:11:37 +00001393 {
David Turnerf0df85b2000-06-22 00:17:42 +00001394 FT_Error error = FT_Err_Ok;
1395 FT_Driver driver;
Werner Lembergf8ba2002002-03-30 13:16:35 +00001396 FT_Driver_Class clazz;
David Turnerf0df85b2000-06-22 00:17:42 +00001397 FT_Size_Metrics* metrics;
1398 FT_Long dim_x, dim_y;
David Turnerd2b1f351999-12-16 23:11:37 +00001399
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001400
David Turnerf0df85b2000-06-22 00:17:42 +00001401 if ( !face || !face->size || !face->driver )
David Turnerd2b1f351999-12-16 23:11:37 +00001402 return FT_Err_Invalid_Face_Handle;
1403
David Turnerf0df85b2000-06-22 00:17:42 +00001404 driver = face->driver;
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001405 metrics = &face->size->metrics;
1406
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001407 if ( !char_width )
David Turnerd2b1f351999-12-16 23:11:37 +00001408 char_width = char_height;
Werner Lembergdeb4e982000-06-29 03:14:25 +00001409
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001410 else if ( !char_height )
David Turnerd2b1f351999-12-16 23:11:37 +00001411 char_height = char_width;
Werner Lemberg7880dd62000-01-10 17:19:45 +00001412
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001413 if ( !horz_resolution )
David Turnerd2b1f351999-12-16 23:11:37 +00001414 horz_resolution = 72;
Werner Lembergdeb4e982000-06-29 03:14:25 +00001415
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001416 if ( !vert_resolution )
David Turnerd2b1f351999-12-16 23:11:37 +00001417 vert_resolution = 72;
1418
David Turnerf0df85b2000-06-22 00:17:42 +00001419 driver = face->driver;
1420 clazz = driver->clazz;
David Turnerd2b1f351999-12-16 23:11:37 +00001421
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001422 /* default processing -- this can be overridden by the driver */
Werner Lembergdeb4e982000-06-29 03:14:25 +00001423 if ( char_width < 1 * 64 )
1424 char_width = 1 * 64;
1425 if ( char_height < 1 * 64 )
1426 char_height = 1 * 64;
David Turnerd42c68e2000-01-27 13:56:02 +00001427
David Turner5158fbc2003-03-27 21:35:44 +00001428 /* Compute pixel sizes in 26.6 units. we use rounding
1429 */
1430 dim_x = ( ( char_width * horz_resolution + (36+32*72) ) / 72 ) & -64;
1431 dim_y = ( ( char_height * vert_resolution + (36+32*72) ) / 72 ) & -64;
David Turnerd42c68e2000-01-27 13:56:02 +00001432
Werner Lembergdeb4e982000-06-29 03:14:25 +00001433 metrics->x_ppem = (FT_UShort)( dim_x >> 6 );
1434 metrics->y_ppem = (FT_UShort)( dim_y >> 6 );
David Turnerd42c68e2000-01-27 13:56:02 +00001435
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001436 metrics->x_scale = 0x10000L;
1437 metrics->y_scale = 0x10000L;
1438
1439 if ( face->face_flags & FT_FACE_FLAG_SCALABLE )
David Turnerd42c68e2000-01-27 13:56:02 +00001440 {
1441 metrics->x_scale = FT_DivFix( dim_x, face->units_per_EM );
1442 metrics->y_scale = FT_DivFix( dim_y, face->units_per_EM );
David Turnerd42c68e2000-01-27 13:56:02 +00001443
David Turner9b3d1c72000-07-07 19:47:34 +00001444 ft_recompute_scaled_metrics( face, metrics );
1445 }
David Turnerf0df85b2000-06-22 00:17:42 +00001446
Werner Lemberga929ba92000-06-25 06:47:11 +00001447 if ( clazz->set_char_sizes )
David Turnerf0df85b2000-06-22 00:17:42 +00001448 error = clazz->set_char_sizes( face->size,
1449 char_width,
1450 char_height,
1451 horz_resolution,
1452 vert_resolution );
David Turnerd2b1f351999-12-16 23:11:37 +00001453 return error;
1454 }
1455
1456
Werner Lemberg90a03302000-11-07 17:21:11 +00001457 /* documentation is in freetype.h */
1458
Werner Lembergf814d0f2001-06-27 16:18:10 +00001459 FT_EXPORT_DEF( FT_Error )
1460 FT_Set_Pixel_Sizes( FT_Face face,
1461 FT_UInt pixel_width,
1462 FT_UInt pixel_height )
David Turnerd2b1f351999-12-16 23:11:37 +00001463 {
David Turnerf0df85b2000-06-22 00:17:42 +00001464 FT_Error error = FT_Err_Ok;
1465 FT_Driver driver;
Werner Lembergf8ba2002002-03-30 13:16:35 +00001466 FT_Driver_Class clazz;
David Turnerf0df85b2000-06-22 00:17:42 +00001467 FT_Size_Metrics* metrics = &face->size->metrics;
David Turnerd2b1f351999-12-16 23:11:37 +00001468
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001469
David Turnerf0df85b2000-06-22 00:17:42 +00001470 if ( !face || !face->size || !face->driver )
David Turnerd2b1f351999-12-16 23:11:37 +00001471 return FT_Err_Invalid_Face_Handle;
1472
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001473 driver = face->driver;
David Turnerf0df85b2000-06-22 00:17:42 +00001474 clazz = driver->clazz;
David Turnerd2b1f351999-12-16 23:11:37 +00001475
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001476 /* default processing -- this can be overridden by the driver */
1477 if ( pixel_width == 0 )
David Turner11187202000-05-26 17:13:23 +00001478 pixel_width = pixel_height;
David Turnerf0df85b2000-06-22 00:17:42 +00001479
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001480 else if ( pixel_height == 0 )
David Turner11187202000-05-26 17:13:23 +00001481 pixel_height = pixel_width;
Werner Lembergeb81e372000-06-03 06:03:11 +00001482
Werner Lembergdeb4e982000-06-29 03:14:25 +00001483 if ( pixel_width < 1 )
1484 pixel_width = 1;
1485 if ( pixel_height < 1 )
1486 pixel_height = 1;
David Turnerd2b1f351999-12-16 23:11:37 +00001487
David Turner8edbcab2001-06-19 08:28:24 +00001488 metrics->x_ppem = (FT_UShort)pixel_width;
1489 metrics->y_ppem = (FT_UShort)pixel_height;
David Turnerd42c68e2000-01-27 13:56:02 +00001490
1491 if ( face->face_flags & FT_FACE_FLAG_SCALABLE )
1492 {
1493 metrics->x_scale = FT_DivFix( metrics->x_ppem << 6,
1494 face->units_per_EM );
1495
1496 metrics->y_scale = FT_DivFix( metrics->y_ppem << 6,
1497 face->units_per_EM );
Werner Lemberg7fa51b52000-07-08 19:51:42 +00001498
David Turner9b3d1c72000-07-07 19:47:34 +00001499 ft_recompute_scaled_metrics( face, metrics );
David Turnerd42c68e2000-01-27 13:56:02 +00001500 }
1501
Werner Lemberga929ba92000-06-25 06:47:11 +00001502 if ( clazz->set_pixel_sizes )
David Turnerf0df85b2000-06-22 00:17:42 +00001503 error = clazz->set_pixel_sizes( face->size,
1504 pixel_width,
1505 pixel_height );
David Turnerd2b1f351999-12-16 23:11:37 +00001506 return error;
1507 }
1508
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001509
Werner Lemberg90a03302000-11-07 17:21:11 +00001510 /* documentation is in freetype.h */
1511
Werner Lembergf814d0f2001-06-27 16:18:10 +00001512 FT_EXPORT_DEF( FT_Error )
1513 FT_Get_Kerning( FT_Face face,
1514 FT_UInt left_glyph,
1515 FT_UInt right_glyph,
1516 FT_UInt kern_mode,
1517 FT_Vector *akerning )
David Turnerd2b1f351999-12-16 23:11:37 +00001518 {
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001519 FT_Error error = FT_Err_Ok;
David Turnerd2b1f351999-12-16 23:11:37 +00001520 FT_Driver driver;
David Turnerd2b1f351999-12-16 23:11:37 +00001521
Werner Lemberga8bbc262000-07-01 14:06:46 +00001522
David Turnerd2b1f351999-12-16 23:11:37 +00001523 if ( !face )
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001524 return FT_Err_Invalid_Face_Handle;
1525
Werner Lemberg4b680072000-11-07 06:30:29 +00001526 if ( !akerning )
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001527 return FT_Err_Invalid_Argument;
David Turnerd2b1f351999-12-16 23:11:37 +00001528
1529 driver = face->driver;
David Turnerd2b1f351999-12-16 23:11:37 +00001530
Werner Lemberg4b680072000-11-07 06:30:29 +00001531 akerning->x = 0;
1532 akerning->y = 0;
Werner Lemberg5aa646c2000-07-14 06:16:47 +00001533
David Turnerf0df85b2000-06-22 00:17:42 +00001534 if ( driver->clazz->get_kerning )
David Turnerd2b1f351999-12-16 23:11:37 +00001535 {
David Turnerf0df85b2000-06-22 00:17:42 +00001536 error = driver->clazz->get_kerning( face,
Werner Lemberga929ba92000-06-25 06:47:11 +00001537 left_glyph,
1538 right_glyph,
Werner Lemberg4b680072000-11-07 06:30:29 +00001539 akerning );
Werner Lemberg5aa646c2000-07-14 06:16:47 +00001540 if ( !error )
David Turnerf9ca2bb2000-06-30 23:12:55 +00001541 {
David Turnerb08fe2d2002-08-27 20:20:29 +00001542 if ( kern_mode != FT_KERNING_UNSCALED )
David Turnerf9ca2bb2000-06-30 23:12:55 +00001543 {
Werner Lemberg4b680072000-11-07 06:30:29 +00001544 akerning->x = FT_MulFix( akerning->x, face->size->metrics.x_scale );
1545 akerning->y = FT_MulFix( akerning->y, face->size->metrics.y_scale );
Werner Lemberg5aa646c2000-07-14 06:16:47 +00001546
David Turnerb08fe2d2002-08-27 20:20:29 +00001547 if ( kern_mode != FT_KERNING_UNFITTED )
Werner Lemberg5aa646c2000-07-14 06:16:47 +00001548 {
Werner Lemberg4b680072000-11-07 06:30:29 +00001549 akerning->x = ( akerning->x + 32 ) & -64;
1550 akerning->y = ( akerning->y + 32 ) & -64;
Werner Lemberg5aa646c2000-07-14 06:16:47 +00001551 }
David Turnerf9ca2bb2000-06-30 23:12:55 +00001552 }
1553 }
1554 }
David Turnerd2b1f351999-12-16 23:11:37 +00001555
David Turnerd2b1f351999-12-16 23:11:37 +00001556 return error;
1557 }
1558
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001559
Werner Lemberg90a03302000-11-07 17:21:11 +00001560 /* documentation is in freetype.h */
1561
Werner Lembergf814d0f2001-06-27 16:18:10 +00001562 FT_EXPORT_DEF( FT_Error )
1563 FT_Select_Charmap( FT_Face face,
1564 FT_Encoding encoding )
David Turner0a29c692000-05-12 17:09:38 +00001565 {
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001566 FT_CharMap* cur;
1567 FT_CharMap* limit;
David Turnere49ab252000-05-16 23:44:38 +00001568
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001569
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001570 if ( !face )
1571 return FT_Err_Invalid_Face_Handle;
1572
Werner Lembergc8c6bf52003-04-23 05:38:13 +00001573 /* FT_ENCODING_UNICODE is special. We try to find the `best' Unicode */
1574 /* charmap available, i.e., one with UCS-4 characters, if possible. */
1575 /* */
1576 /* This is done by find_unicode_charmap() above, to share code. */
Antoine Lecac96f69d2002-12-03 00:39:16 +00001577 if ( encoding == FT_ENCODING_UNICODE )
1578 return find_unicode_charmap( face );
1579
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001580 cur = face->charmaps;
1581 if ( !cur )
1582 return FT_Err_Invalid_CharMap_Handle;
1583
1584 limit = cur + face->num_charmaps;
1585
David Turner0a29c692000-05-12 17:09:38 +00001586 for ( ; cur < limit; cur++ )
1587 {
1588 if ( cur[0]->encoding == encoding )
1589 {
1590 face->charmap = cur[0];
1591 return 0;
1592 }
1593 }
Werner Lembergdeb4e982000-06-29 03:14:25 +00001594
David Turner0a29c692000-05-12 17:09:38 +00001595 return FT_Err_Invalid_Argument;
1596 }
1597
1598
Werner Lemberg90a03302000-11-07 17:21:11 +00001599 /* documentation is in freetype.h */
1600
Werner Lembergf814d0f2001-06-27 16:18:10 +00001601 FT_EXPORT_DEF( FT_Error )
1602 FT_Set_Charmap( FT_Face face,
1603 FT_CharMap charmap )
David Turner0a29c692000-05-12 17:09:38 +00001604 {
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001605 FT_CharMap* cur;
1606 FT_CharMap* limit;
David Turnere49ab252000-05-16 23:44:38 +00001607
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001608
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001609 if ( !face )
1610 return FT_Err_Invalid_Face_Handle;
1611
1612 cur = face->charmaps;
1613 if ( !cur )
1614 return FT_Err_Invalid_CharMap_Handle;
1615
1616 limit = cur + face->num_charmaps;
1617
David Turner0a29c692000-05-12 17:09:38 +00001618 for ( ; cur < limit; cur++ )
1619 {
1620 if ( cur[0] == charmap )
1621 {
1622 face->charmap = cur[0];
1623 return 0;
1624 }
1625 }
1626 return FT_Err_Invalid_Argument;
1627 }
David Turnerd2b1f351999-12-16 23:11:37 +00001628
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001629
David Turner4e7eeee2002-02-28 16:10:29 +00001630 FT_BASE_DEF( void )
1631 FT_CMap_Done( FT_CMap cmap )
1632 {
1633 if ( cmap )
1634 {
1635 FT_CMap_Class clazz = cmap->clazz;
1636 FT_Face face = cmap->charmap.face;
1637 FT_Memory memory = FT_FACE_MEMORY(face);
David Turnerbc82f1b2002-03-01 02:26:22 +00001638
Werner Lembergf8ba2002002-03-30 13:16:35 +00001639
David Turner4e7eeee2002-02-28 16:10:29 +00001640 if ( clazz->done )
David Turnerbc82f1b2002-03-01 02:26:22 +00001641 clazz->done( cmap );
David Turner4e7eeee2002-02-28 16:10:29 +00001642
David Turnere459d742002-03-22 13:52:37 +00001643 FT_FREE( cmap );
David Turner4e7eeee2002-02-28 16:10:29 +00001644 }
1645 }
1646
1647
1648 FT_BASE_DEF( FT_Error )
1649 FT_CMap_New( FT_CMap_Class clazz,
David Turnerbc82f1b2002-03-01 02:26:22 +00001650 FT_Pointer init_data,
David Turner4e7eeee2002-02-28 16:10:29 +00001651 FT_CharMap charmap,
1652 FT_CMap *acmap )
David Turnerbc82f1b2002-03-01 02:26:22 +00001653 {
David Turner4e7eeee2002-02-28 16:10:29 +00001654 FT_Error error = 0;
1655 FT_Face face;
1656 FT_Memory memory;
1657 FT_CMap cmap;
David Turnerbc82f1b2002-03-01 02:26:22 +00001658
Werner Lembergf8ba2002002-03-30 13:16:35 +00001659
David Turner4e7eeee2002-02-28 16:10:29 +00001660 if ( clazz == NULL || charmap == NULL || charmap->face == NULL )
1661 return FT_Err_Invalid_Argument;
1662
1663 face = charmap->face;
1664 memory = FT_FACE_MEMORY(face);
1665
David Turnere459d742002-03-22 13:52:37 +00001666 if ( !FT_ALLOC( cmap, clazz->size ) )
David Turner4e7eeee2002-02-28 16:10:29 +00001667 {
1668 cmap->charmap = *charmap;
1669 cmap->clazz = clazz;
David Turnerbc82f1b2002-03-01 02:26:22 +00001670
David Turner4e7eeee2002-02-28 16:10:29 +00001671 if ( clazz->init )
1672 {
David Turnerbc82f1b2002-03-01 02:26:22 +00001673 error = clazz->init( cmap, init_data );
Werner Lembergf8ba2002002-03-30 13:16:35 +00001674 if ( error )
David Turner4e7eeee2002-02-28 16:10:29 +00001675 goto Fail;
1676 }
David Turnerbc82f1b2002-03-01 02:26:22 +00001677
David Turner4e7eeee2002-02-28 16:10:29 +00001678 /* add it to our list of charmaps */
David Turnere459d742002-03-22 13:52:37 +00001679 if ( FT_RENEW_ARRAY( face->charmaps,
1680 face->num_charmaps,
1681 face->num_charmaps+1 ) )
David Turner4e7eeee2002-02-28 16:10:29 +00001682 goto Fail;
David Turnerbc82f1b2002-03-01 02:26:22 +00001683
Werner Lembergf8ba2002002-03-30 13:16:35 +00001684 face->charmaps[face->num_charmaps++] = (FT_CharMap)cmap;
David Turner4e7eeee2002-02-28 16:10:29 +00001685 }
David Turnerbc82f1b2002-03-01 02:26:22 +00001686
David Turner4e7eeee2002-02-28 16:10:29 +00001687 Exit:
1688 if ( acmap )
1689 *acmap = cmap;
1690
1691 return error;
David Turnerbc82f1b2002-03-01 02:26:22 +00001692
David Turner4e7eeee2002-02-28 16:10:29 +00001693 Fail:
1694 FT_CMap_Done( cmap );
1695 cmap = NULL;
1696 goto Exit;
David Turnerbc82f1b2002-03-01 02:26:22 +00001697 }
David Turner4e7eeee2002-02-28 16:10:29 +00001698
1699
Werner Lemberg90a03302000-11-07 17:21:11 +00001700 /* documentation is in freetype.h */
1701
Werner Lembergf814d0f2001-06-27 16:18:10 +00001702 FT_EXPORT_DEF( FT_UInt )
1703 FT_Get_Char_Index( FT_Face face,
1704 FT_ULong charcode )
David Turnerd2b1f351999-12-16 23:11:37 +00001705 {
David Turnered54f282002-03-22 17:09:52 +00001706 FT_UInt result = 0;
1707
1708
1709 if ( face && face->charmap )
1710 {
1711 FT_CMap cmap = FT_CMAP( face->charmap );
David Turner25a6e3a2002-06-10 23:03:35 +00001712
Werner Lembergf8ba2002002-03-30 13:16:35 +00001713
David Turnered54f282002-03-22 17:09:52 +00001714 result = cmap->clazz->char_index( cmap, charcode );
1715 }
1716 return result;
1717 }
1718
David Turnered54f282002-03-22 17:09:52 +00001719
1720
Werner Lemberg0f7c2f12002-02-04 20:55:58 +00001721 /* documentation is in freetype.h */
1722
1723 FT_EXPORT_DEF( FT_ULong )
David Turner041889e2002-02-28 19:28:26 +00001724 FT_Get_First_Char( FT_Face face,
1725 FT_UInt *agindex )
Werner Lemberg0f7c2f12002-02-04 20:55:58 +00001726 {
Werner Lembergf8ba2002002-03-30 13:16:35 +00001727 FT_ULong result = 0;
1728 FT_UInt gindex = 0;
1729
David Turnerbc82f1b2002-03-01 02:26:22 +00001730
David Turner041889e2002-02-28 19:28:26 +00001731 if ( face && face->charmap )
1732 {
1733 gindex = FT_Get_Char_Index( face, 0 );
1734 if ( gindex == 0 )
1735 result = FT_Get_Next_Char( face, 0, &gindex );
1736 }
David Turnerbc82f1b2002-03-01 02:26:22 +00001737
David Turner041889e2002-02-28 19:28:26 +00001738 if ( agindex )
1739 *agindex = gindex;
David Turnerbc82f1b2002-03-01 02:26:22 +00001740
David Turner041889e2002-02-28 19:28:26 +00001741 return result;
1742 }
1743
1744 /* documentation is in freetype.h */
1745
David Turnered54f282002-03-22 17:09:52 +00001746
David Turnered54f282002-03-22 17:09:52 +00001747 FT_EXPORT_DEF( FT_ULong )
1748 FT_Get_Next_Char( FT_Face face,
1749 FT_ULong charcode,
1750 FT_UInt *agindex )
1751 {
Werner Lembergf8ba2002002-03-30 13:16:35 +00001752 FT_ULong result = 0;
1753 FT_UInt gindex = 0;
David Turnered54f282002-03-22 17:09:52 +00001754
1755
1756 if ( face && face->charmap )
1757 {
1758 FT_UInt32 code = (FT_UInt32)charcode;
1759 FT_CMap cmap = FT_CMAP( face->charmap );
1760
Werner Lembergf8ba2002002-03-30 13:16:35 +00001761
David Turnered54f282002-03-22 17:09:52 +00001762 gindex = cmap->clazz->char_next( cmap, &code );
1763 result = ( gindex == 0 ) ? 0 : code;
1764 }
1765
1766 if ( agindex )
1767 *agindex = gindex;
1768
1769 return result;
1770 }
1771
David Turnered54f282002-03-22 17:09:52 +00001772
David Turnerd2b1f351999-12-16 23:11:37 +00001773
Werner Lemberg90a03302000-11-07 17:21:11 +00001774 /* documentation is in freetype.h */
1775
Tom Kacvinskyff2714f2001-08-08 10:58:08 +00001776 FT_EXPORT_DEF( FT_UInt )
1777 FT_Get_Name_Index( FT_Face face,
1778 FT_String* glyph_name )
1779 {
1780 FT_UInt result = 0;
1781
1782
1783 if ( face && FT_HAS_GLYPH_NAMES( face ) )
1784 {
1785 /* now, lookup for glyph name */
Werner Lemberg5dea4442001-08-13 11:44:29 +00001786 FT_Driver driver = face->driver;
1787 FT_Module_Class* clazz = FT_MODULE_CLASS( driver );
Tom Kacvinskyff2714f2001-08-08 10:58:08 +00001788
1789
1790 if ( clazz->get_interface )
1791 {
David Turnerb93b0f52002-03-14 09:28:51 +00001792 FT_Face_GetGlyphNameIndexFunc requester;
Tom Kacvinskyff2714f2001-08-08 10:58:08 +00001793
1794
David Turnerb93b0f52002-03-14 09:28:51 +00001795 requester = (FT_Face_GetGlyphNameIndexFunc)clazz->get_interface(
Tom Kacvinskyff2714f2001-08-08 10:58:08 +00001796 FT_MODULE( driver ), "name_index" );
1797 if ( requester )
1798 result = requester( face, glyph_name );
1799 }
1800 }
1801
1802 return result;
1803 }
1804
Werner Lembergaef3fc82001-12-17 16:21:22 +00001805
Tom Kacvinskyff2714f2001-08-08 10:58:08 +00001806 /* documentation is in freetype.h */
1807
Werner Lembergf814d0f2001-06-27 16:18:10 +00001808 FT_EXPORT_DEF( FT_Error )
1809 FT_Get_Glyph_Name( FT_Face face,
1810 FT_UInt glyph_index,
1811 FT_Pointer buffer,
1812 FT_UInt buffer_max )
David Turner6930b452000-07-19 17:13:03 +00001813 {
1814 FT_Error error = FT_Err_Invalid_Argument;
Werner Lembergeddd9902000-10-12 05:05:40 +00001815
Werner Lembergd060a752000-07-20 06:57:41 +00001816
David Turner6930b452000-07-19 17:13:03 +00001817 /* clean up buffer */
Werner Lembergd060a752000-07-20 06:57:41 +00001818 if ( buffer && buffer_max > 0 )
David Turner6930b452000-07-19 17:13:03 +00001819 ((FT_Byte*)buffer)[0] = 0;
Werner Lembergeddd9902000-10-12 05:05:40 +00001820
Werner Lembergfd97d132002-06-16 01:14:16 +00001821 if ( face &&
1822 glyph_index <= (FT_UInt)face->num_glyphs &&
1823 FT_HAS_GLYPH_NAMES( face ) )
David Turner6930b452000-07-19 17:13:03 +00001824 {
1825 /* now, lookup for glyph name */
Werner Lembergf8ba2002002-03-30 13:16:35 +00001826 FT_Driver driver = face->driver;
1827 FT_Module_Class* clazz = FT_MODULE_CLASS( driver );
David Turner6930b452000-07-19 17:13:03 +00001828
Werner Lembergd060a752000-07-20 06:57:41 +00001829
1830 if ( clazz->get_interface )
David Turner6930b452000-07-19 17:13:03 +00001831 {
David Turnerb93b0f52002-03-14 09:28:51 +00001832 FT_Face_GetGlyphNameFunc requester;
Werner Lembergeddd9902000-10-12 05:05:40 +00001833
Werner Lembergd060a752000-07-20 06:57:41 +00001834
David Turnerb93b0f52002-03-14 09:28:51 +00001835 requester = (FT_Face_GetGlyphNameFunc)clazz->get_interface(
Werner Lembergd060a752000-07-20 06:57:41 +00001836 FT_MODULE( driver ), "glyph_name" );
1837 if ( requester )
David Turner6930b452000-07-19 17:13:03 +00001838 error = requester( face, glyph_index, buffer, buffer_max );
1839 }
1840 }
Werner Lembergd060a752000-07-20 06:57:41 +00001841
David Turner6930b452000-07-19 17:13:03 +00001842 return error;
Werner Lembergeddd9902000-10-12 05:05:40 +00001843 }
David Turner6930b452000-07-19 17:13:03 +00001844
1845
David Turner23bcde12001-10-17 13:48:10 +00001846 /* documentation is in freetype.h */
1847
1848 FT_EXPORT_DEF( const char* )
1849 FT_Get_Postscript_Name( FT_Face face )
1850 {
1851 const char* result = NULL;
Werner Lemberg1a0a9792002-01-03 22:06:13 +00001852
Werner Lembergc3b21602001-12-05 01:22:05 +00001853
David Turner23bcde12001-10-17 13:48:10 +00001854 if ( !face )
1855 goto Exit;
1856
1857 result = face->internal->postscript_name;
1858 if ( !result )
1859 {
Werner Lembergf8ba2002002-03-30 13:16:35 +00001860 /* now, look up glyph name */
Werner Lembergc3b21602001-12-05 01:22:05 +00001861 FT_Driver driver = face->driver;
1862 FT_Module_Class* clazz = FT_MODULE_CLASS( driver );
1863
David Turner23bcde12001-10-17 13:48:10 +00001864
1865 if ( clazz->get_interface )
1866 {
David Turnerb93b0f52002-03-14 09:28:51 +00001867 FT_Face_GetPostscriptNameFunc requester;
David Turner23bcde12001-10-17 13:48:10 +00001868
Werner Lembergc3b21602001-12-05 01:22:05 +00001869
David Turnerb93b0f52002-03-14 09:28:51 +00001870 requester = (FT_Face_GetPostscriptNameFunc)clazz->get_interface(
David Turner23bcde12001-10-17 13:48:10 +00001871 FT_MODULE( driver ), "postscript_name" );
1872 if ( requester )
1873 result = requester( face );
1874 }
1875 }
1876 Exit:
1877 return result;
1878 }
1879
1880
Werner Lemberg90a03302000-11-07 17:21:11 +00001881 /* documentation is in tttables.h */
1882
Werner Lembergf814d0f2001-06-27 16:18:10 +00001883 FT_EXPORT_DEF( void* )
1884 FT_Get_Sfnt_Table( FT_Face face,
1885 FT_Sfnt_Tag tag )
David Turner99a4d932000-04-25 16:10:50 +00001886 {
1887 void* table = 0;
1888 FT_Get_Sfnt_Table_Func func;
1889 FT_Driver driver;
David Turnere49ab252000-05-16 23:44:38 +00001890
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001891
1892 if ( !face || !FT_IS_SFNT( face ) )
David Turner99a4d932000-04-25 16:10:50 +00001893 goto Exit;
David Turnere49ab252000-05-16 23:44:38 +00001894
David Turner99a4d932000-04-25 16:10:50 +00001895 driver = face->driver;
David Turnerf0df85b2000-06-22 00:17:42 +00001896 func = (FT_Get_Sfnt_Table_Func)driver->root.clazz->get_interface(
Werner Lemberga929ba92000-06-25 06:47:11 +00001897 FT_MODULE( driver ), "get_sfnt" );
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001898 if ( func )
1899 table = func( face, tag );
David Turnere49ab252000-05-16 23:44:38 +00001900
David Turner99a4d932000-04-25 16:10:50 +00001901 Exit:
1902 return table;
David Turnere49ab252000-05-16 23:44:38 +00001903 }
David Turner99a4d932000-04-25 16:10:50 +00001904
1905
David Turner621e4882002-12-16 21:51:24 +00001906 /* documentation is in tttables.h */
1907
1908 FT_EXPORT_DEF( FT_Error )
Werner Lembergc8c6bf52003-04-23 05:38:13 +00001909 FT_Load_Sfnt_Table( FT_Face face,
1910 FT_ULong tag,
1911 FT_Long offset,
1912 FT_Byte* buffer,
1913 FT_ULong* length )
David Turner621e4882002-12-16 21:51:24 +00001914 {
1915 SFNT_Load_Table_Func func;
1916 FT_Driver driver;
1917
1918
1919 if ( !face || !FT_IS_SFNT( face ) )
1920 return FT_Err_Invalid_Face_Handle;
1921
1922 driver = face->driver;
1923 func = (SFNT_Load_Table_Func) driver->root.clazz->get_interface(
1924 FT_MODULE( driver ), "load_sfnt" );
1925 if ( !func )
1926 return FT_Err_Unimplemented_Feature;
1927
1928 return func( face, tag, offset, buffer, length );
1929 }
1930
1931
David Turnerb3ba40d2001-10-07 13:30:26 +00001932 FT_EXPORT_DEF( FT_Error )
Werner Lemberg80b8d772001-10-10 19:56:42 +00001933 FT_Activate_Size( FT_Size size )
David Turnerb3ba40d2001-10-07 13:30:26 +00001934 {
1935 FT_Face face;
Werner Lemberg1a0a9792002-01-03 22:06:13 +00001936
Werner Lemberg80b8d772001-10-10 19:56:42 +00001937
David Turnerb3ba40d2001-10-07 13:30:26 +00001938 if ( size == NULL )
1939 return FT_Err_Bad_Argument;
Werner Lemberg1a0a9792002-01-03 22:06:13 +00001940
David Turnerb3ba40d2001-10-07 13:30:26 +00001941 face = size->face;
1942 if ( face == NULL || face->driver == NULL )
1943 return FT_Err_Bad_Argument;
Werner Lemberg1a0a9792002-01-03 22:06:13 +00001944
Werner Lemberg80b8d772001-10-10 19:56:42 +00001945 /* we don't need anything more complex than that; all size objects */
1946 /* are already listed by the face */
David Turnerb3ba40d2001-10-07 13:30:26 +00001947 face->size = size;
Werner Lemberg1a0a9792002-01-03 22:06:13 +00001948
David Turnerb3ba40d2001-10-07 13:30:26 +00001949 return FT_Err_Ok;
1950 }
1951
1952
David Turnerd2b1f351999-12-16 23:11:37 +00001953 /*************************************************************************/
David Turnerf0df85b2000-06-22 00:17:42 +00001954 /*************************************************************************/
1955 /*************************************************************************/
1956 /**** ****/
1957 /**** ****/
1958 /**** R E N D E R E R S ****/
1959 /**** ****/
1960 /**** ****/
1961 /*************************************************************************/
1962 /*************************************************************************/
1963 /*************************************************************************/
1964
Werner Lembergdeb4e982000-06-29 03:14:25 +00001965 /* lookup a renderer by glyph format in the library's list */
Werner Lembergf814d0f2001-06-27 16:18:10 +00001966 FT_BASE_DEF( FT_Renderer )
1967 FT_Lookup_Renderer( FT_Library library,
1968 FT_Glyph_Format format,
1969 FT_ListNode* node )
David Turnerf0df85b2000-06-22 00:17:42 +00001970 {
Werner Lembergf8ba2002002-03-30 13:16:35 +00001971 FT_ListNode cur;
1972 FT_Renderer result = 0;
Werner Lemberga929ba92000-06-25 06:47:11 +00001973
Werner Lembergdeb4e982000-06-29 03:14:25 +00001974
1975 if ( !library )
1976 goto Exit;
1977
1978 cur = library->renderers.head;
1979
1980 if ( node )
David Turner74abee82000-06-27 23:31:53 +00001981 {
Werner Lembergdeb4e982000-06-29 03:14:25 +00001982 if ( *node )
David Turner74abee82000-06-27 23:31:53 +00001983 cur = (*node)->next;
David Turnerf0df85b2000-06-22 00:17:42 +00001984 *node = 0;
David Turner74abee82000-06-27 23:31:53 +00001985 }
Werner Lembergdeb4e982000-06-29 03:14:25 +00001986
Werner Lemberga929ba92000-06-25 06:47:11 +00001987 while ( cur )
David Turnerf0df85b2000-06-22 00:17:42 +00001988 {
Werner Lemberga929ba92000-06-25 06:47:11 +00001989 FT_Renderer renderer = FT_RENDERER( cur->data );
Werner Lembergdeb4e982000-06-29 03:14:25 +00001990
Werner Lemberga929ba92000-06-25 06:47:11 +00001991
1992 if ( renderer->glyph_format == format )
David Turnerf0df85b2000-06-22 00:17:42 +00001993 {
Werner Lemberga929ba92000-06-25 06:47:11 +00001994 if ( node )
David Turnerf0df85b2000-06-22 00:17:42 +00001995 *node = cur;
Werner Lembergdeb4e982000-06-29 03:14:25 +00001996
David Turnerf0df85b2000-06-22 00:17:42 +00001997 result = renderer;
1998 break;
1999 }
David Turner74abee82000-06-27 23:31:53 +00002000 cur = cur->next;
David Turnerf0df85b2000-06-22 00:17:42 +00002001 }
Werner Lemberga929ba92000-06-25 06:47:11 +00002002
Werner Lembergdeb4e982000-06-29 03:14:25 +00002003 Exit:
David Turnerf0df85b2000-06-22 00:17:42 +00002004 return result;
2005 }
2006
Werner Lemberga929ba92000-06-25 06:47:11 +00002007
Werner Lembergf814d0f2001-06-27 16:18:10 +00002008 static FT_Renderer
2009 ft_lookup_glyph_renderer( FT_GlyphSlot slot )
Werner Lembergdeb4e982000-06-29 03:14:25 +00002010 {
2011 FT_Face face = slot->face;
2012 FT_Library library = FT_FACE_LIBRARY( face );
2013 FT_Renderer result = library->cur_renderer;
2014
2015
Werner Lemberga929ba92000-06-25 06:47:11 +00002016 if ( !result || result->glyph_format != slot->format )
David Turner81bb4ad2000-06-28 04:19:49 +00002017 result = FT_Lookup_Renderer( library, slot->format, 0 );
Werner Lembergfbeb41d2000-07-02 00:27:53 +00002018
David Turnerf0df85b2000-06-22 00:17:42 +00002019 return result;
2020 }
2021
Werner Lembergdeb4e982000-06-29 03:14:25 +00002022
Werner Lembergf814d0f2001-06-27 16:18:10 +00002023 static void
2024 ft_set_current_renderer( FT_Library library )
David Turnerf0df85b2000-06-22 00:17:42 +00002025 {
2026 FT_Renderer renderer;
2027
Werner Lembergdeb4e982000-06-29 03:14:25 +00002028
David Turnerb08fe2d2002-08-27 20:20:29 +00002029 renderer = FT_Lookup_Renderer( library, FT_GLYPH_FORMAT_OUTLINE, 0 );
David Turnerf0df85b2000-06-22 00:17:42 +00002030 library->cur_renderer = renderer;
2031 }
2032
2033
Werner Lembergf814d0f2001-06-27 16:18:10 +00002034 static FT_Error
2035 ft_add_renderer( FT_Module module )
David Turnerf0df85b2000-06-22 00:17:42 +00002036 {
2037 FT_Library library = module->library;
2038 FT_Memory memory = library->memory;
2039 FT_Error error;
2040 FT_ListNode node;
Werner Lembergdeb4e982000-06-29 03:14:25 +00002041
2042
David Turnere459d742002-03-22 13:52:37 +00002043 if ( FT_NEW( node ) )
David Turnerf0df85b2000-06-22 00:17:42 +00002044 goto Exit;
Werner Lembergdeb4e982000-06-29 03:14:25 +00002045
David Turnerf0df85b2000-06-22 00:17:42 +00002046 {
Werner Lemberga929ba92000-06-25 06:47:11 +00002047 FT_Renderer render = FT_RENDERER( module );
David Turnerf0df85b2000-06-22 00:17:42 +00002048 FT_Renderer_Class* clazz = (FT_Renderer_Class*)module->clazz;
2049
Werner Lemberga929ba92000-06-25 06:47:11 +00002050
David Turnerf0df85b2000-06-22 00:17:42 +00002051 render->clazz = clazz;
2052 render->glyph_format = clazz->glyph_format;
Werner Lembergdeb4e982000-06-29 03:14:25 +00002053
David Turnerf0df85b2000-06-22 00:17:42 +00002054 /* allocate raster object if needed */
David Turnerb08fe2d2002-08-27 20:20:29 +00002055 if ( clazz->glyph_format == FT_GLYPH_FORMAT_OUTLINE &&
David Turnerf0df85b2000-06-22 00:17:42 +00002056 clazz->raster_class->raster_new )
2057 {
2058 error = clazz->raster_class->raster_new( memory, &render->raster );
Werner Lemberga929ba92000-06-25 06:47:11 +00002059 if ( error )
2060 goto Fail;
Werner Lembergdeb4e982000-06-29 03:14:25 +00002061
David Turnerf0df85b2000-06-22 00:17:42 +00002062 render->raster_render = clazz->raster_class->raster_render;
2063 render->render = clazz->render_glyph;
Werner Lembergdeb4e982000-06-29 03:14:25 +00002064 }
2065
David Turnerf0df85b2000-06-22 00:17:42 +00002066 /* add to list */
2067 node->data = module;
2068 FT_List_Add( &library->renderers, node );
2069
2070 ft_set_current_renderer( library );
2071 }
2072
2073 Fail:
Werner Lemberga929ba92000-06-25 06:47:11 +00002074 if ( error )
David Turnere459d742002-03-22 13:52:37 +00002075 FT_FREE( node );
David Turnerf0df85b2000-06-22 00:17:42 +00002076
2077 Exit:
2078 return error;
Werner Lembergdeb4e982000-06-29 03:14:25 +00002079 }
David Turnerf0df85b2000-06-22 00:17:42 +00002080
2081
Werner Lembergf814d0f2001-06-27 16:18:10 +00002082 static void
2083 ft_remove_renderer( FT_Module module )
David Turnerf0df85b2000-06-22 00:17:42 +00002084 {
2085 FT_Library library = module->library;
2086 FT_Memory memory = library->memory;
2087 FT_ListNode node;
2088
Werner Lemberga929ba92000-06-25 06:47:11 +00002089
David Turnerf0df85b2000-06-22 00:17:42 +00002090 node = FT_List_Find( &library->renderers, module );
Werner Lemberga929ba92000-06-25 06:47:11 +00002091 if ( node )
David Turnerf0df85b2000-06-22 00:17:42 +00002092 {
Werner Lemberga929ba92000-06-25 06:47:11 +00002093 FT_Renderer render = FT_RENDERER( module );
Werner Lembergdeb4e982000-06-29 03:14:25 +00002094
Werner Lemberga929ba92000-06-25 06:47:11 +00002095
David Turnerf0df85b2000-06-22 00:17:42 +00002096 /* release raster object, if any */
Werner Lemberga929ba92000-06-25 06:47:11 +00002097 if ( render->raster )
David Turnerf0df85b2000-06-22 00:17:42 +00002098 render->clazz->raster_class->raster_done( render->raster );
Werner Lembergdeb4e982000-06-29 03:14:25 +00002099
David Turnerf0df85b2000-06-22 00:17:42 +00002100 /* remove from list */
2101 FT_List_Remove( &library->renderers, node );
David Turnere459d742002-03-22 13:52:37 +00002102 FT_FREE( node );
Werner Lembergdeb4e982000-06-29 03:14:25 +00002103
David Turnerf0df85b2000-06-22 00:17:42 +00002104 ft_set_current_renderer( library );
2105 }
2106 }
2107
2108
Werner Lemberg90a03302000-11-07 17:21:11 +00002109 /* documentation is in ftrender.h */
2110
Werner Lembergf814d0f2001-06-27 16:18:10 +00002111 FT_EXPORT_DEF( FT_Renderer )
2112 FT_Get_Renderer( FT_Library library,
2113 FT_Glyph_Format format )
David Turnerf0df85b2000-06-22 00:17:42 +00002114 {
Werner Lembergdeb4e982000-06-29 03:14:25 +00002115 /* test for valid `library' delayed to FT_Lookup_Renderer() */
2116
Werner Lembergf8ba2002002-03-30 13:16:35 +00002117 return FT_Lookup_Renderer( library, format, 0 );
Werner Lembergdeb4e982000-06-29 03:14:25 +00002118 }
David Turnerf0df85b2000-06-22 00:17:42 +00002119
2120
Werner Lemberg90a03302000-11-07 17:21:11 +00002121 /* documentation is in ftrender.h */
2122
Werner Lembergf814d0f2001-06-27 16:18:10 +00002123 FT_EXPORT_DEF( FT_Error )
2124 FT_Set_Renderer( FT_Library library,
2125 FT_Renderer renderer,
2126 FT_UInt num_params,
2127 FT_Parameter* parameters )
David Turnerf0df85b2000-06-22 00:17:42 +00002128 {
2129 FT_ListNode node;
2130 FT_Error error = FT_Err_Ok;
Werner Lembergdeb4e982000-06-29 03:14:25 +00002131
2132
2133 if ( !library )
2134 return FT_Err_Invalid_Library_Handle;
2135
2136 if ( !renderer )
2137 return FT_Err_Invalid_Argument;
Werner Lemberga929ba92000-06-25 06:47:11 +00002138
David Turnerf0df85b2000-06-22 00:17:42 +00002139 node = FT_List_Find( &library->renderers, renderer );
Werner Lemberga929ba92000-06-25 06:47:11 +00002140 if ( !node )
David Turnerf0df85b2000-06-22 00:17:42 +00002141 {
2142 error = FT_Err_Invalid_Argument;
2143 goto Exit;
2144 }
David Turner74abee82000-06-27 23:31:53 +00002145
David Turnerf0df85b2000-06-22 00:17:42 +00002146 FT_List_Up( &library->renderers, node );
Werner Lembergdeb4e982000-06-29 03:14:25 +00002147
David Turnerb08fe2d2002-08-27 20:20:29 +00002148 if ( renderer->glyph_format == FT_GLYPH_FORMAT_OUTLINE )
David Turnerf0df85b2000-06-22 00:17:42 +00002149 library->cur_renderer = renderer;
Werner Lembergdeb4e982000-06-29 03:14:25 +00002150
Werner Lemberga929ba92000-06-25 06:47:11 +00002151 if ( num_params > 0 )
David Turnerf0df85b2000-06-22 00:17:42 +00002152 {
David Turnerb08fe2d2002-08-27 20:20:29 +00002153 FT_Renderer_SetModeFunc set_mode = renderer->clazz->set_mode;
Werner Lembergdeb4e982000-06-29 03:14:25 +00002154
Werner Lemberga929ba92000-06-25 06:47:11 +00002155
David Turnerf0df85b2000-06-22 00:17:42 +00002156 for ( ; num_params > 0; num_params-- )
2157 {
2158 error = set_mode( renderer, parameters->tag, parameters->data );
Werner Lemberga929ba92000-06-25 06:47:11 +00002159 if ( error )
David Turnerf0df85b2000-06-22 00:17:42 +00002160 break;
2161 }
2162 }
Werner Lembergdeb4e982000-06-29 03:14:25 +00002163
David Turnerf0df85b2000-06-22 00:17:42 +00002164 Exit:
2165 return error;
Werner Lembergdeb4e982000-06-29 03:14:25 +00002166 }
David Turnerf0df85b2000-06-22 00:17:42 +00002167
2168
David Turner7504e482002-06-07 07:24:55 +00002169 FT_BASE_DEF( FT_Error )
Werner Lemberg68e9f922002-09-27 11:09:23 +00002170 FT_Render_Glyph_Internal( FT_Library library,
2171 FT_GlyphSlot slot,
2172 FT_Render_Mode render_mode )
David Turnerf0df85b2000-06-22 00:17:42 +00002173 {
2174 FT_Error error = FT_Err_Ok;
2175 FT_Renderer renderer;
Werner Lemberga929ba92000-06-25 06:47:11 +00002176
Werner Lembergdeb4e982000-06-29 03:14:25 +00002177
2178 /* if it is already a bitmap, no need to do anything */
2179 switch ( slot->format )
David Turnerf0df85b2000-06-22 00:17:42 +00002180 {
David Turnerb08fe2d2002-08-27 20:20:29 +00002181 case FT_GLYPH_FORMAT_BITMAP: /* already a bitmap, don't do anything */
Werner Lembergdeb4e982000-06-29 03:14:25 +00002182 break;
2183
2184 default:
David Turner74abee82000-06-27 23:31:53 +00002185 {
2186 FT_ListNode node = 0;
2187 FT_Bool update = 0;
Werner Lembergdeb4e982000-06-29 03:14:25 +00002188
2189
Werner Lemberga929ba92000-06-25 06:47:11 +00002190 /* small shortcut for the very common case */
David Turnerb08fe2d2002-08-27 20:20:29 +00002191 if ( slot->format == FT_GLYPH_FORMAT_OUTLINE )
David Turner74abee82000-06-27 23:31:53 +00002192 {
Werner Lemberga929ba92000-06-25 06:47:11 +00002193 renderer = library->cur_renderer;
David Turner74abee82000-06-27 23:31:53 +00002194 node = library->renderers.head;
2195 }
Werner Lemberga929ba92000-06-25 06:47:11 +00002196 else
David Turner74abee82000-06-27 23:31:53 +00002197 renderer = FT_Lookup_Renderer( library, slot->format, &node );
2198
Werner Lemberga929ba92000-06-25 06:47:11 +00002199 error = FT_Err_Unimplemented_Feature;
Werner Lembergdeb4e982000-06-29 03:14:25 +00002200 while ( renderer )
David Turner74abee82000-06-27 23:31:53 +00002201 {
David Turnerc8ad30a2001-12-05 17:24:34 +00002202 error = renderer->render( renderer, slot, render_mode, NULL );
Werner Lemberg79860702001-06-08 21:17:29 +00002203 if ( !error ||
2204 FT_ERROR_BASE( error ) != FT_Err_Cannot_Render_Glyph )
Werner Lembergdeb4e982000-06-29 03:14:25 +00002205 break;
David Turner74abee82000-06-27 23:31:53 +00002206
Werner Lembergdeb4e982000-06-29 03:14:25 +00002207 /* FT_Err_Cannot_Render_Glyph is returned if the render mode */
David Turner74abee82000-06-27 23:31:53 +00002208 /* is unsupported by the current renderer for this glyph image */
Werner Lembergdeb4e982000-06-29 03:14:25 +00002209 /* format. */
2210
2211 /* now, look for another renderer that supports the same */
2212 /* format. */
David Turner74abee82000-06-27 23:31:53 +00002213 renderer = FT_Lookup_Renderer( library, slot->format, &node );
2214 update = 1;
2215 }
2216
2217 /* if we changed the current renderer for the glyph image format */
Werner Lembergdeb4e982000-06-29 03:14:25 +00002218 /* we need to select it as the next current one */
2219 if ( !error && update && renderer )
David Turner74abee82000-06-27 23:31:53 +00002220 FT_Set_Renderer( library, renderer, 0, 0 );
David Turnerf0df85b2000-06-22 00:17:42 +00002221 }
2222 }
Werner Lembergdeb4e982000-06-29 03:14:25 +00002223
David Turnerf0df85b2000-06-22 00:17:42 +00002224 return error;
2225 }
Werner Lemberga929ba92000-06-25 06:47:11 +00002226
David Turner74abee82000-06-27 23:31:53 +00002227
Werner Lemberg90a03302000-11-07 17:21:11 +00002228 /* documentation is in freetype.h */
2229
Werner Lembergf814d0f2001-06-27 16:18:10 +00002230 FT_EXPORT_DEF( FT_Error )
Werner Lemberg68e9f922002-09-27 11:09:23 +00002231 FT_Render_Glyph( FT_GlyphSlot slot,
2232 FT_Render_Mode render_mode )
David Turner74abee82000-06-27 23:31:53 +00002233 {
Werner Lembergf8ba2002002-03-30 13:16:35 +00002234 FT_Library library;
Werner Lembergdeb4e982000-06-29 03:14:25 +00002235
2236
2237 if ( !slot )
David Turner74abee82000-06-27 23:31:53 +00002238 return FT_Err_Invalid_Argument;
Werner Lembergdeb4e982000-06-29 03:14:25 +00002239
2240 library = FT_FACE_LIBRARY( slot->face );
2241
David Turner74abee82000-06-27 23:31:53 +00002242 return FT_Render_Glyph_Internal( library, slot, render_mode );
2243 }
2244
Werner Lembergdeb4e982000-06-29 03:14:25 +00002245
David Turnerf0df85b2000-06-22 00:17:42 +00002246 /*************************************************************************/
2247 /*************************************************************************/
2248 /*************************************************************************/
2249 /**** ****/
2250 /**** ****/
2251 /**** M O D U L E S ****/
2252 /**** ****/
2253 /**** ****/
2254 /*************************************************************************/
2255 /*************************************************************************/
2256 /*************************************************************************/
2257
Werner Lemberga929ba92000-06-25 06:47:11 +00002258
David Turnerf0df85b2000-06-22 00:17:42 +00002259 /*************************************************************************/
2260 /* */
2261 /* <Function> */
2262 /* Destroy_Module */
2263 /* */
2264 /* <Description> */
2265 /* Destroys a given module object. For drivers, this also destroys */
Werner Lemberga929ba92000-06-25 06:47:11 +00002266 /* all child faces. */
David Turnerf0df85b2000-06-22 00:17:42 +00002267 /* */
2268 /* <InOut> */
2269 /* module :: A handle to the target driver object. */
2270 /* */
2271 /* <Note> */
2272 /* The driver _must_ be LOCKED! */
2273 /* */
Werner Lembergf814d0f2001-06-27 16:18:10 +00002274 static void
2275 Destroy_Module( FT_Module module )
David Turnerf0df85b2000-06-22 00:17:42 +00002276 {
David Turner5ae831c2000-06-30 01:31:22 +00002277 FT_Memory memory = module->memory;
2278 FT_Module_Class* clazz = module->clazz;
2279 FT_Library library = module->library;
David Turnerf0df85b2000-06-22 00:17:42 +00002280
Werner Lemberga929ba92000-06-25 06:47:11 +00002281
David Turnerf0df85b2000-06-22 00:17:42 +00002282 /* finalize client-data - before anything else */
2283 if ( module->generic.finalizer )
2284 module->generic.finalizer( module );
2285
David Turner5ae831c2000-06-30 01:31:22 +00002286 if ( library && library->auto_hinter == module )
2287 library->auto_hinter = 0;
2288
David Turnerf0df85b2000-06-22 00:17:42 +00002289 /* if the module is a renderer */
Werner Lemberga929ba92000-06-25 06:47:11 +00002290 if ( FT_MODULE_IS_RENDERER( module ) )
2291 ft_remove_renderer( module );
David Turnerf0df85b2000-06-22 00:17:42 +00002292
2293 /* if the module is a font driver, add some steps */
Werner Lemberga929ba92000-06-25 06:47:11 +00002294 if ( FT_MODULE_IS_DRIVER( module ) )
2295 Destroy_Driver( FT_DRIVER( module ) );
David Turnerf0df85b2000-06-22 00:17:42 +00002296
2297 /* finalize the module object */
Werner Lemberga929ba92000-06-25 06:47:11 +00002298 if ( clazz->module_done )
2299 clazz->module_done( module );
David Turnerf0df85b2000-06-22 00:17:42 +00002300
2301 /* discard it */
David Turnere459d742002-03-22 13:52:37 +00002302 FT_FREE( module );
David Turnerf0df85b2000-06-22 00:17:42 +00002303 }
2304
David Turnerf0df85b2000-06-22 00:17:42 +00002305
Werner Lemberg90a03302000-11-07 17:21:11 +00002306 /* documentation is in ftmodule.h */
2307
Werner Lembergf814d0f2001-06-27 16:18:10 +00002308 FT_EXPORT_DEF( FT_Error )
2309 FT_Add_Module( FT_Library library,
2310 const FT_Module_Class* clazz )
David Turnerf0df85b2000-06-22 00:17:42 +00002311 {
2312 FT_Error error;
2313 FT_Memory memory;
2314 FT_Module module;
2315 FT_UInt nn;
2316
David Turnerf0df85b2000-06-22 00:17:42 +00002317
Werner Lembergdeb4e982000-06-29 03:14:25 +00002318#define FREETYPE_VER_FIXED ( ( (FT_Long)FREETYPE_MAJOR << 16 ) | \
2319 FREETYPE_MINOR )
Werner Lemberga929ba92000-06-25 06:47:11 +00002320
Werner Lembergdeb4e982000-06-29 03:14:25 +00002321 if ( !library )
2322 return FT_Err_Invalid_Library_Handle;
2323
2324 if ( !clazz )
David Turnerf0df85b2000-06-22 00:17:42 +00002325 return FT_Err_Invalid_Argument;
2326
2327 /* check freetype version */
2328 if ( clazz->module_requires > FREETYPE_VER_FIXED )
2329 return FT_Err_Invalid_Version;
2330
2331 /* look for a module with the same name in the library's table */
2332 for ( nn = 0; nn < library->num_modules; nn++ )
2333 {
2334 module = library->modules[nn];
David Turnerd15bc0d2002-04-12 09:31:48 +00002335 if ( ft_strcmp( module->clazz->module_name, clazz->module_name ) == 0 )
David Turnerf0df85b2000-06-22 00:17:42 +00002336 {
2337 /* this installed module has the same name, compare their versions */
2338 if ( clazz->module_version <= module->clazz->module_version )
2339 return FT_Err_Lower_Module_Version;
2340
2341 /* remove the module from our list, then exit the loop to replace */
2342 /* it by our new version.. */
2343 FT_Remove_Module( library, module );
2344 break;
2345 }
2346 }
2347
2348 memory = library->memory;
2349 error = FT_Err_Ok;
2350
2351 if ( library->num_modules >= FT_MAX_MODULES )
2352 {
2353 error = FT_Err_Too_Many_Drivers;
2354 goto Exit;
2355 }
2356
2357 /* allocate module object */
Werner Lemberg68e9f922002-09-27 11:09:23 +00002358 if ( FT_ALLOC( module, clazz->module_size ) )
David Turnerf0df85b2000-06-22 00:17:42 +00002359 goto Exit;
2360
Werner Lembergdeb4e982000-06-29 03:14:25 +00002361 /* base initialization */
David Turnerf0df85b2000-06-22 00:17:42 +00002362 module->library = library;
2363 module->memory = memory;
2364 module->clazz = (FT_Module_Class*)clazz;
2365
Werner Lembergdeb4e982000-06-29 03:14:25 +00002366 /* check whether the module is a renderer - this must be performed */
2367 /* before the normal module initialization */
Werner Lemberga929ba92000-06-25 06:47:11 +00002368 if ( FT_MODULE_IS_RENDERER( module ) )
David Turnerf0df85b2000-06-22 00:17:42 +00002369 {
2370 /* add to the renderers list */
Werner Lemberga929ba92000-06-25 06:47:11 +00002371 error = ft_add_renderer( module );
2372 if ( error )
2373 goto Fail;
David Turnerf0df85b2000-06-22 00:17:42 +00002374 }
2375
Werner Lembergcc9fc492000-06-30 06:21:26 +00002376 /* is the module a auto-hinter? */
2377 if ( FT_MODULE_IS_HINTER( module ) )
David Turner5ae831c2000-06-30 01:31:22 +00002378 library->auto_hinter = module;
Werner Lembergfbeb41d2000-07-02 00:27:53 +00002379
David Turnerf0df85b2000-06-22 00:17:42 +00002380 /* if the module is a font driver */
Werner Lemberga929ba92000-06-25 06:47:11 +00002381 if ( FT_MODULE_IS_DRIVER( module ) )
David Turnerf0df85b2000-06-22 00:17:42 +00002382 {
2383 /* allocate glyph loader if needed */
Werner Lembergf8ba2002002-03-30 13:16:35 +00002384 FT_Driver driver = FT_DRIVER( module );
Werner Lemberga929ba92000-06-25 06:47:11 +00002385
Werner Lembergdeb4e982000-06-29 03:14:25 +00002386
David Turneref3c1262002-03-14 09:22:48 +00002387 driver->clazz = (FT_Driver_Class)module->clazz;
Werner Lemberga929ba92000-06-25 06:47:11 +00002388 if ( FT_DRIVER_USES_OUTLINES( driver ) )
David Turnerf0df85b2000-06-22 00:17:42 +00002389 {
2390 error = FT_GlyphLoader_New( memory, &driver->glyph_loader );
Werner Lemberga929ba92000-06-25 06:47:11 +00002391 if ( error )
2392 goto Fail;
David Turnerf0df85b2000-06-22 00:17:42 +00002393 }
2394 }
2395
Werner Lemberga929ba92000-06-25 06:47:11 +00002396 if ( clazz->module_init )
David Turnerf0df85b2000-06-22 00:17:42 +00002397 {
Werner Lemberga929ba92000-06-25 06:47:11 +00002398 error = clazz->module_init( module );
2399 if ( error )
2400 goto Fail;
David Turnerf0df85b2000-06-22 00:17:42 +00002401 }
2402
2403 /* add module to the library's table */
Werner Lemberga929ba92000-06-25 06:47:11 +00002404 library->modules[library->num_modules++] = module;
Werner Lembergdeb4e982000-06-29 03:14:25 +00002405
David Turnerf0df85b2000-06-22 00:17:42 +00002406 Exit:
2407 return error;
Werner Lembergdeb4e982000-06-29 03:14:25 +00002408
David Turnerf0df85b2000-06-22 00:17:42 +00002409 Fail:
Werner Lemberga929ba92000-06-25 06:47:11 +00002410 if ( FT_MODULE_IS_DRIVER( module ) )
David Turnerf0df85b2000-06-22 00:17:42 +00002411 {
Werner Lemberga929ba92000-06-25 06:47:11 +00002412 FT_Driver driver = FT_DRIVER( module );
Werner Lembergdeb4e982000-06-29 03:14:25 +00002413
Werner Lemberga929ba92000-06-25 06:47:11 +00002414
2415 if ( FT_DRIVER_USES_OUTLINES( driver ) )
David Turnerf0df85b2000-06-22 00:17:42 +00002416 FT_GlyphLoader_Done( driver->glyph_loader );
2417 }
Werner Lembergdeb4e982000-06-29 03:14:25 +00002418
Werner Lemberga929ba92000-06-25 06:47:11 +00002419 if ( FT_MODULE_IS_RENDERER( module ) )
David Turnerf0df85b2000-06-22 00:17:42 +00002420 {
Werner Lemberga929ba92000-06-25 06:47:11 +00002421 FT_Renderer renderer = FT_RENDERER( module );
2422
2423
2424 if ( renderer->raster )
David Turnerf0df85b2000-06-22 00:17:42 +00002425 renderer->clazz->raster_class->raster_done( renderer->raster );
2426 }
Werner Lemberga929ba92000-06-25 06:47:11 +00002427
David Turnere459d742002-03-22 13:52:37 +00002428 FT_FREE( module );
David Turnerf0df85b2000-06-22 00:17:42 +00002429 goto Exit;
2430 }
2431
David Turnerf0df85b2000-06-22 00:17:42 +00002432
Werner Lemberg90a03302000-11-07 17:21:11 +00002433 /* documentation is in ftmodule.h */
2434
Werner Lembergf814d0f2001-06-27 16:18:10 +00002435 FT_EXPORT_DEF( FT_Module )
2436 FT_Get_Module( FT_Library library,
2437 const char* module_name )
David Turnerf0df85b2000-06-22 00:17:42 +00002438 {
Werner Lembergdeb4e982000-06-29 03:14:25 +00002439 FT_Module result = 0;
2440 FT_Module* cur;
2441 FT_Module* limit;
David Turnerf0df85b2000-06-22 00:17:42 +00002442
Werner Lemberga929ba92000-06-25 06:47:11 +00002443
Werner Lembergdeb4e982000-06-29 03:14:25 +00002444 if ( !library || !module_name )
2445 return result;
2446
2447 cur = library->modules;
2448 limit = cur + library->num_modules;
2449
David Turnerf0df85b2000-06-22 00:17:42 +00002450 for ( ; cur < limit; cur++ )
David Turnerd15bc0d2002-04-12 09:31:48 +00002451 if ( ft_strcmp( cur[0]->clazz->module_name, module_name ) == 0 )
David Turnerf0df85b2000-06-22 00:17:42 +00002452 {
2453 result = cur[0];
2454 break;
2455 }
2456
2457 return result;
2458 }
2459
Werner Lemberga929ba92000-06-25 06:47:11 +00002460
Werner Lemberg8ec9dfd2000-11-07 23:56:02 +00002461 /* documentation is in ftobjs.h */
2462
Werner Lembergf814d0f2001-06-27 16:18:10 +00002463 FT_BASE_DEF( const void* )
2464 FT_Get_Module_Interface( FT_Library library,
2465 const char* mod_name )
David Turnerf0df85b2000-06-22 00:17:42 +00002466 {
2467 FT_Module module;
Werner Lembergdeb4e982000-06-29 03:14:25 +00002468
2469
2470 /* test for valid `library' delayed to FT_Get_Module() */
Werner Lemberga929ba92000-06-25 06:47:11 +00002471
David Turnerf0df85b2000-06-22 00:17:42 +00002472 module = FT_Get_Module( library, mod_name );
Werner Lemberga929ba92000-06-25 06:47:11 +00002473
David Turnerf0df85b2000-06-22 00:17:42 +00002474 return module ? module->clazz->module_interface : 0;
Werner Lembergdeb4e982000-06-29 03:14:25 +00002475 }
David Turnerf0df85b2000-06-22 00:17:42 +00002476
2477
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_Error )
2481 FT_Remove_Module( FT_Library library,
2482 FT_Module module )
David Turnerf0df85b2000-06-22 00:17:42 +00002483 {
2484 /* try to find the module from the table, then remove it from there */
Werner Lembergdeb4e982000-06-29 03:14:25 +00002485
2486 if ( !library )
2487 return FT_Err_Invalid_Library_Handle;
2488
2489 if ( module )
David Turnerf0df85b2000-06-22 00:17:42 +00002490 {
2491 FT_Module* cur = library->modules;
2492 FT_Module* limit = cur + library->num_modules;
2493
Werner Lemberga929ba92000-06-25 06:47:11 +00002494
David Turnerf0df85b2000-06-22 00:17:42 +00002495 for ( ; cur < limit; cur++ )
2496 {
Werner Lembergdeb4e982000-06-29 03:14:25 +00002497 if ( cur[0] == module )
David Turnerf0df85b2000-06-22 00:17:42 +00002498 {
2499 /* remove it from the table */
2500 library->num_modules--;
2501 limit--;
Werner Lemberga929ba92000-06-25 06:47:11 +00002502 while ( cur < limit )
David Turnerf0df85b2000-06-22 00:17:42 +00002503 {
2504 cur[0] = cur[1];
2505 cur++;
2506 }
2507 limit[0] = 0;
2508
2509 /* destroy the module */
Werner Lemberga929ba92000-06-25 06:47:11 +00002510 Destroy_Module( module );
David Turnerf0df85b2000-06-22 00:17:42 +00002511
2512 return FT_Err_Ok;
2513 }
2514 }
2515 }
Werner Lembergb48a6092000-07-09 19:15:30 +00002516 return FT_Err_Invalid_Driver_Handle;
David Turnerf0df85b2000-06-22 00:17:42 +00002517 }
2518
2519
David Turnerf0df85b2000-06-22 00:17:42 +00002520 /*************************************************************************/
2521 /*************************************************************************/
2522 /*************************************************************************/
2523 /**** ****/
2524 /**** ****/
2525 /**** L I B R A R Y ****/
2526 /**** ****/
2527 /**** ****/
2528 /*************************************************************************/
2529 /*************************************************************************/
2530 /*************************************************************************/
2531
Werner Lemberga929ba92000-06-25 06:47:11 +00002532
Werner Lemberg90a03302000-11-07 17:21:11 +00002533 /* documentation is in ftmodule.h */
2534
Werner Lembergf814d0f2001-06-27 16:18:10 +00002535 FT_EXPORT_DEF( FT_Error )
2536 FT_New_Library( FT_Memory memory,
2537 FT_Library *alibrary )
David Turnerf0df85b2000-06-22 00:17:42 +00002538 {
2539 FT_Library library = 0;
2540 FT_Error error;
2541
2542
2543 if ( !memory )
2544 return FT_Err_Invalid_Argument;
2545
David Turnerf5749602002-04-18 10:07:26 +00002546#ifdef FT_DEBUG_LEVEL_ERROR
David Turner53b3fa12002-02-24 05:26:57 +00002547 /* init debugging support */
2548 ft_debug_init();
David Turnerf5749602002-04-18 10:07:26 +00002549#endif
David Turner53b3fa12002-02-24 05:26:57 +00002550
David Turnerf0df85b2000-06-22 00:17:42 +00002551 /* first of all, allocate the library object */
David Turnere459d742002-03-22 13:52:37 +00002552 if ( FT_NEW( library ) )
David Turnerf0df85b2000-06-22 00:17:42 +00002553 return error;
2554
2555 library->memory = memory;
2556
2557 /* allocate the render pool */
2558 library->raster_pool_size = FT_RENDER_POOL_SIZE;
David Turnere459d742002-03-22 13:52:37 +00002559 if ( FT_ALLOC( library->raster_pool, FT_RENDER_POOL_SIZE ) )
David Turnerf0df85b2000-06-22 00:17:42 +00002560 goto Fail;
2561
2562 /* That's ok now */
2563 *alibrary = library;
2564
2565 return FT_Err_Ok;
2566
2567 Fail:
David Turnere459d742002-03-22 13:52:37 +00002568 FT_FREE( library );
David Turnerf0df85b2000-06-22 00:17:42 +00002569 return error;
2570 }
2571
2572
David Turner83b4a4b2002-03-06 12:42:34 +00002573 /* documentation is in freetype.h */
David Turner25a6e3a2002-06-10 23:03:35 +00002574
David Turner83b4a4b2002-03-06 12:42:34 +00002575 FT_EXPORT_DEF( void )
2576 FT_Library_Version( FT_Library library,
2577 FT_Int *amajor,
2578 FT_Int *aminor,
2579 FT_Int *apatch )
2580 {
2581 FT_Int major = 0;
2582 FT_Int minor = 0;
2583 FT_Int patch = 0;
2584
David Turner25a6e3a2002-06-10 23:03:35 +00002585
David Turner83b4a4b2002-03-06 12:42:34 +00002586 if ( library )
2587 {
2588 major = library->version_major;
2589 minor = library->version_minor;
2590 patch = library->version_patch;
2591 }
David Turner25a6e3a2002-06-10 23:03:35 +00002592
David Turnerd48575e2002-09-18 23:18:36 +00002593 if ( amajor )
David Turner83b4a4b2002-03-06 12:42:34 +00002594 *amajor = major;
David Turner25a6e3a2002-06-10 23:03:35 +00002595
David Turnerd48575e2002-09-18 23:18:36 +00002596 if ( aminor )
David Turner83b4a4b2002-03-06 12:42:34 +00002597 *aminor = minor;
David Turner25a6e3a2002-06-10 23:03:35 +00002598
David Turnerd48575e2002-09-18 23:18:36 +00002599 if ( apatch )
David Turner83b4a4b2002-03-06 12:42:34 +00002600 *apatch = patch;
David Turner25a6e3a2002-06-10 23:03:35 +00002601 }
David Turner83b4a4b2002-03-06 12:42:34 +00002602
2603
Werner Lemberg90a03302000-11-07 17:21:11 +00002604 /* documentation is in ftmodule.h */
2605
Werner Lembergf814d0f2001-06-27 16:18:10 +00002606 FT_EXPORT_DEF( FT_Error )
2607 FT_Done_Library( FT_Library library )
David Turnerf0df85b2000-06-22 00:17:42 +00002608 {
2609 FT_Memory memory;
David Turnerf0df85b2000-06-22 00:17:42 +00002610
2611
2612 if ( !library )
2613 return FT_Err_Invalid_Library_Handle;
2614
2615 memory = library->memory;
2616
2617 /* Discard client-data */
2618 if ( library->generic.finalizer )
2619 library->generic.finalizer( library );
2620
2621 /* Close all modules in the library */
Werner Lembergf41e71a2001-12-20 21:22:02 +00002622#if 1
David Turnerc8087482001-12-20 13:14:18 +00002623 while ( library->num_modules > 0 )
2624 FT_Remove_Module( library, library->modules[0] );
Werner Lembergf41e71a2001-12-20 21:22:02 +00002625#else
David Turnerf0df85b2000-06-22 00:17:42 +00002626 {
Werner Lembergf41e71a2001-12-20 21:22:02 +00002627 FT_UInt n;
David Turnerf0df85b2000-06-22 00:17:42 +00002628
Werner Lemberga929ba92000-06-25 06:47:11 +00002629
Werner Lembergf41e71a2001-12-20 21:22:02 +00002630 for ( n = 0; n < library->num_modules; n++ )
David Turnerf0df85b2000-06-22 00:17:42 +00002631 {
Werner Lembergf41e71a2001-12-20 21:22:02 +00002632 FT_Module module = library->modules[n];
2633
2634
2635 if ( module )
2636 {
2637 Destroy_Module( module );
2638 library->modules[n] = 0;
2639 }
David Turnerf0df85b2000-06-22 00:17:42 +00002640 }
2641 }
David Turnerc8087482001-12-20 13:14:18 +00002642#endif
David Turnerf0df85b2000-06-22 00:17:42 +00002643
2644 /* Destroy raster objects */
David Turnere459d742002-03-22 13:52:37 +00002645 FT_FREE( library->raster_pool );
David Turnerf0df85b2000-06-22 00:17:42 +00002646 library->raster_pool_size = 0;
2647
David Turnere459d742002-03-22 13:52:37 +00002648 FT_FREE( library );
David Turnerf0df85b2000-06-22 00:17:42 +00002649 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 */