blob: efa5ffe2723d2bf19e8b33fdc20565063ad785cf [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 Lembergc32e83f2008-04-01 06:07:37 +00007/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 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 Lemberg645af082004-09-06 07:06:56 +000022#include FT_INTERNAL_VALIDATE_H
Werner Lembergcc069be2000-12-08 16:17:16 +000023#include FT_INTERNAL_OBJECTS_H
24#include FT_INTERNAL_DEBUG_H
Werner Lemberg75435332004-02-25 12:58:54 +000025#include FT_INTERNAL_RFORK_H
Werner Lembergcc069be2000-12-08 16:17:16 +000026#include FT_INTERNAL_STREAM_H
David Turner621e4882002-12-16 21:51:24 +000027#include FT_INTERNAL_SFNT_H /* for SFNT_Load_Table_Func */
Werner Lembergcc069be2000-12-08 16:17:16 +000028#include FT_TRUETYPE_TABLES_H
Antoine Lecac96f69d2002-12-03 00:39:16 +000029#include FT_TRUETYPE_IDS_H
David Turnerf86709a2002-01-07 10:04:09 +000030#include FT_OUTLINE_H
Werner Lemberg7880dd62000-01-10 17:19:45 +000031
Werner Lemberg5e3614f2003-09-12 19:38:13 +000032#include FT_SERVICE_SFNT_H
David Turnerc313c502003-09-11 19:51:54 +000033#include FT_SERVICE_POSTSCRIPT_NAME_H
34#include FT_SERVICE_GLYPH_DICT_H
Werner Lemberg91a67472003-12-17 14:28:22 +000035#include FT_SERVICE_TT_CMAP_H
Wu, Chia-I (吳佳一)108fdbb2006-01-16 15:35:56 +000036#include FT_SERVICE_KERNING_H
David Turner0b5dc4d2006-02-21 22:36:23 +000037#include FT_SERVICE_TRUETYPE_ENGINE_H
David Turnerc313c502003-09-11 19:51:54 +000038
Wu, Chia-I (吳佳一)2e48a1a2006-02-27 09:18:07 +000039#define GRID_FIT_METRICS
Werner Lemberg013efd12003-09-17 05:26:33 +000040
David Turnerc313c502003-09-11 19:51:54 +000041 FT_BASE_DEF( FT_Pointer )
42 ft_service_list_lookup( FT_ServiceDesc service_descriptors,
43 const char* service_id )
44 {
45 FT_Pointer result = NULL;
46 FT_ServiceDesc desc = service_descriptors;
David Turnere2d12842003-09-21 17:15:55 +000047
Werner Lemberg013efd12003-09-17 05:26:33 +000048
David Turnerc313c502003-09-11 19:51:54 +000049 if ( desc && service_id )
50 {
51 for ( ; desc->serv_id != NULL; desc++ )
52 {
53 if ( ft_strcmp( desc->serv_id, service_id ) == 0 )
54 {
Werner Lemberg013efd12003-09-17 05:26:33 +000055 result = (FT_Pointer)desc->serv_data;
David Turnerc313c502003-09-11 19:51:54 +000056 break;
57 }
58 }
59 }
Werner Lemberg013efd12003-09-17 05:26:33 +000060
David Turnerc313c502003-09-11 19:51:54 +000061 return result;
David Turnere2d12842003-09-21 17:15:55 +000062 }
Werner Lemberg3c403e42002-08-06 21:47:40 +000063
Werner Lemberg013efd12003-09-17 05:26:33 +000064
David Turnered54f282002-03-22 17:09:52 +000065 FT_BASE_DEF( void )
66 ft_validator_init( FT_Validator valid,
67 const FT_Byte* base,
68 const FT_Byte* limit,
69 FT_ValidationLevel level )
70 {
71 valid->base = base;
72 valid->limit = limit;
73 valid->level = level;
Werner Lemberg8acb8672005-03-08 11:43:36 +000074 valid->error = FT_Err_Ok;
David Turnered54f282002-03-22 17:09:52 +000075 }
David Turner25a6e3a2002-06-10 23:03:35 +000076
David Turnered54f282002-03-22 17:09:52 +000077
78 FT_BASE_DEF( FT_Int )
79 ft_validator_run( FT_Validator valid )
80 {
Werner Lemberg12342992006-08-19 11:18:09 +000081 /* This function doesn't work! None should call it. */
82 FT_UNUSED( valid );
83
David Turner2b21a932006-08-16 09:24:32 +000084 return -1;
David Turnered54f282002-03-22 17:09:52 +000085 }
86
Werner Lembergf8ba2002002-03-30 13:16:35 +000087
David Turnered54f282002-03-22 17:09:52 +000088 FT_BASE_DEF( void )
89 ft_validator_error( FT_Validator valid,
90 FT_Error error )
91 {
Jens Claudiusa787f452006-08-27 11:26:18 +000092 /* since the cast below also disables the compiler's */
93 /* type check, we introduce a dummy variable, which */
94 /* will be optimized away */
Werner Lemberg607dec72007-05-15 06:49:37 +000095 volatile ft_jmp_buf* jump_buffer = &valid->jump_buffer;
Jens Claudiusa787f452006-08-27 11:26:18 +000096
97
David Turnered54f282002-03-22 17:09:52 +000098 valid->error = error;
Jens Claudiusa787f452006-08-27 11:26:18 +000099
100 /* throw away volatileness; use `jump_buffer' or the */
101 /* compiler may warn about an unused local variable */
Werner Lemberg607dec72007-05-15 06:49:37 +0000102 ft_longjmp( *(ft_jmp_buf*) jump_buffer, 1 );
David Turner25a6e3a2002-06-10 23:03:35 +0000103 }
Werner Lemberga929ba92000-06-25 06:47:11 +0000104
Werner Lemberga3b6c6c2000-05-31 06:55:12 +0000105
David Turnerd2b1f351999-12-16 23:11:37 +0000106 /*************************************************************************/
107 /*************************************************************************/
108 /*************************************************************************/
109 /**** ****/
110 /**** ****/
David Turnerf0df85b2000-06-22 00:17:42 +0000111 /**** S T R E A M ****/
112 /**** ****/
113 /**** ****/
114 /*************************************************************************/
115 /*************************************************************************/
116 /*************************************************************************/
117
Werner Lemberg7880dd62000-01-10 17:19:45 +0000118
Werner Lemberg75435332004-02-25 12:58:54 +0000119 /* create a new input stream from an FT_Open_Args structure */
120 /* */
121 FT_BASE_DEF( FT_Error )
122 FT_Stream_New( FT_Library library,
123 const FT_Open_Args* args,
124 FT_Stream *astream )
David Turner7663f222000-02-13 13:37:38 +0000125 {
Werner Lemberg547a2522000-02-16 08:23:58 +0000126 FT_Error error;
127 FT_Memory memory;
128 FT_Stream stream;
129
Werner Lemberga3b6c6c2000-05-31 06:55:12 +0000130
Werner Lemberg2fbf7e42000-06-02 00:01:14 +0000131 if ( !library )
132 return FT_Err_Invalid_Library_Handle;
133
134 if ( !args )
135 return FT_Err_Invalid_Argument;
136
David Turner37379e22000-03-28 11:22:31 +0000137 *astream = 0;
138 memory = library->memory;
Werner Lembergf8ba2002002-03-30 13:16:35 +0000139
David Turnere459d742002-03-22 13:52:37 +0000140 if ( FT_NEW( stream ) )
David Turner37379e22000-03-28 11:22:31 +0000141 goto Exit;
David Turnere49ab252000-05-16 23:44:38 +0000142
David Turner7663f222000-02-13 13:37:38 +0000143 stream->memory = memory;
David Turnere49ab252000-05-16 23:44:38 +0000144
David Turnerb08fe2d2002-08-27 20:20:29 +0000145 if ( args->flags & FT_OPEN_MEMORY )
Just van Rossumd35aea72000-03-02 01:07:50 +0000146 {
David Turner53b3fa12002-02-24 05:26:57 +0000147 /* create a memory-based stream */
David Turner7d3a2642002-03-20 10:49:31 +0000148 FT_Stream_OpenMemory( stream,
Werner Lembergf8ba2002002-03-30 13:16:35 +0000149 (const FT_Byte*)args->memory_base,
150 args->memory_size );
David Turner4f2c5542000-05-12 10:19:41 +0000151 }
David Turnerb08fe2d2002-08-27 20:20:29 +0000152 else if ( args->flags & FT_OPEN_PATHNAME )
David Turner4f2c5542000-05-12 10:19:41 +0000153 {
David Turner53b3fa12002-02-24 05:26:57 +0000154 /* create a normal system stream */
155 error = FT_Stream_Open( stream, args->pathname );
David Turner4f2c5542000-05-12 10:19:41 +0000156 stream->pathname.pointer = args->pathname;
157 }
David Turnerb08fe2d2002-08-27 20:20:29 +0000158 else if ( ( args->flags & FT_OPEN_STREAM ) && args->stream )
David Turner4f2c5542000-05-12 10:19:41 +0000159 {
David Turner53b3fa12002-02-24 05:26:57 +0000160 /* use an existing, user-provided stream */
161
Werner Lemberg58b17f92000-07-27 23:29:08 +0000162 /* in this case, we do not need to allocate a new stream object */
163 /* since the caller is responsible for closing it himself */
David Turnere459d742002-03-22 13:52:37 +0000164 FT_FREE( stream );
David Turnerc5cdf8b2000-07-27 21:40:22 +0000165 stream = args->stream;
David Turner4f2c5542000-05-12 10:19:41 +0000166 }
167 else
David Turner4f2c5542000-05-12 10:19:41 +0000168 error = FT_Err_Invalid_Argument;
David Turnere49ab252000-05-16 23:44:38 +0000169
Werner Lemberg547a2522000-02-16 08:23:58 +0000170 if ( error )
David Turnere459d742002-03-22 13:52:37 +0000171 FT_FREE( stream );
David Turner53b3fa12002-02-24 05:26:57 +0000172 else
173 stream->memory = memory; /* just to be certain */
David Turnere49ab252000-05-16 23:44:38 +0000174
David Turner7663f222000-02-13 13:37:38 +0000175 *astream = stream;
Werner Lemberga3b6c6c2000-05-31 06:55:12 +0000176
David Turner37379e22000-03-28 11:22:31 +0000177 Exit:
David Turner7663f222000-02-13 13:37:38 +0000178 return error;
179 }
180
181
Werner Lemberg75435332004-02-25 12:58:54 +0000182 FT_BASE_DEF( void )
183 FT_Stream_Free( FT_Stream stream,
184 FT_Int external )
David Turner7663f222000-02-13 13:37:38 +0000185 {
David Turner53b3fa12002-02-24 05:26:57 +0000186 if ( stream )
David Turnerc5cdf8b2000-07-27 21:40:22 +0000187 {
188 FT_Memory memory = stream->memory;
Werner Lemberg58b17f92000-07-27 23:29:08 +0000189
Werner Lembergf8ba2002002-03-30 13:16:35 +0000190
David Turner53b3fa12002-02-24 05:26:57 +0000191 FT_Stream_Close( stream );
Werner Lemberg58b17f92000-07-27 23:29:08 +0000192
David Turner53b3fa12002-02-24 05:26:57 +0000193 if ( !external )
David Turnere459d742002-03-22 13:52:37 +0000194 FT_FREE( stream );
David Turnerc5cdf8b2000-07-27 21:40:22 +0000195 }
David Turner7663f222000-02-13 13:37:38 +0000196 }
197
Werner Lemberga3b6c6c2000-05-31 06:55:12 +0000198
Werner Lembergeb81e372000-06-03 06:03:11 +0000199#undef FT_COMPONENT
200#define FT_COMPONENT trace_objs
201
Werner Lembergdeb4e982000-06-29 03:14:25 +0000202
David Turnerf0df85b2000-06-22 00:17:42 +0000203 /*************************************************************************/
204 /*************************************************************************/
205 /*************************************************************************/
206 /**** ****/
207 /**** ****/
208 /**** FACE, SIZE & GLYPH SLOT OBJECTS ****/
209 /**** ****/
210 /**** ****/
211 /*************************************************************************/
212 /*************************************************************************/
213 /*************************************************************************/
214
Werner Lembergdeb4e982000-06-29 03:14:25 +0000215
Werner Lembergf814d0f2001-06-27 16:18:10 +0000216 static FT_Error
217 ft_glyphslot_init( FT_GlyphSlot slot )
David Turnerf0df85b2000-06-22 00:17:42 +0000218 {
219 FT_Driver driver = slot->face->driver;
Werner Lembergf8ba2002002-03-30 13:16:35 +0000220 FT_Driver_Class clazz = driver->clazz;
David Turnerf0df85b2000-06-22 00:17:42 +0000221 FT_Memory memory = driver->root.memory;
222 FT_Error error = FT_Err_Ok;
David Turner54e75742000-11-04 02:52:02 +0000223 FT_Slot_Internal internal;
David Turnerf0df85b2000-06-22 00:17:42 +0000224
Werner Lemberga8bbc262000-07-01 14:06:46 +0000225
David Turnerf9ca2bb2000-06-30 23:12:55 +0000226 slot->library = driver->root.library;
Werner Lembergfbeb41d2000-07-02 00:27:53 +0000227
David Turnere459d742002-03-22 13:52:37 +0000228 if ( FT_NEW( internal ) )
David Turner54e75742000-11-04 02:52:02 +0000229 goto Exit;
230
231 slot->internal = internal;
232
Werner Lemberga929ba92000-06-25 06:47:11 +0000233 if ( FT_DRIVER_USES_OUTLINES( driver ) )
David Turner54e75742000-11-04 02:52:02 +0000234 error = FT_GlyphLoader_New( memory, &internal->loader );
David Turnerf0df85b2000-06-22 00:17:42 +0000235
Werner Lemberga929ba92000-06-25 06:47:11 +0000236 if ( !error && clazz->init_slot )
David Turnerf0df85b2000-06-22 00:17:42 +0000237 error = clazz->init_slot( slot );
238
David Turner54e75742000-11-04 02:52:02 +0000239 Exit:
David Turnerf0df85b2000-06-22 00:17:42 +0000240 return error;
241 }
242
Werner Lemberge20ab692003-06-02 07:24:33 +0000243
David Turner66cbc202003-03-20 07:04:40 +0000244 FT_BASE_DEF( void )
245 ft_glyphslot_free_bitmap( FT_GlyphSlot slot )
246 {
Werner Lemberg7a024102003-06-18 06:59:57 +0000247 if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP )
David Turner66cbc202003-03-20 07:04:40 +0000248 {
249 FT_Memory memory = FT_FACE_MEMORY( slot->face );
Werner Lemberg51daa4f2003-05-18 22:40:11 +0000250
251
David Turner66cbc202003-03-20 07:04:40 +0000252 FT_FREE( slot->bitmap.buffer );
Werner Lemberg7a024102003-06-18 06:59:57 +0000253 slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP;
David Turner66cbc202003-03-20 07:04:40 +0000254 }
255 else
256 {
257 /* assume that the bitmap buffer was stolen or not */
258 /* allocated from the heap */
259 slot->bitmap.buffer = NULL;
260 }
261 }
262
263
264 FT_BASE_DEF( void )
265 ft_glyphslot_set_bitmap( FT_GlyphSlot slot,
Werner Lemberg319c00d2003-04-23 19:48:24 +0000266 FT_Byte* buffer )
David Turner66cbc202003-03-20 07:04:40 +0000267 {
268 ft_glyphslot_free_bitmap( slot );
Werner Lemberg51daa4f2003-05-18 22:40:11 +0000269
David Turner66cbc202003-03-20 07:04:40 +0000270 slot->bitmap.buffer = buffer;
Werner Lemberg51daa4f2003-05-18 22:40:11 +0000271
Werner Lemberg7a024102003-06-18 06:59:57 +0000272 FT_ASSERT( (slot->internal->flags & FT_GLYPH_OWN_BITMAP) == 0 );
Werner Lemberg51daa4f2003-05-18 22:40:11 +0000273 }
David Turner66cbc202003-03-20 07:04:40 +0000274
275
276 FT_BASE_DEF( FT_Error )
277 ft_glyphslot_alloc_bitmap( FT_GlyphSlot slot,
278 FT_ULong size )
279 {
Werner Lembergbe3c9812006-01-27 14:16:16 +0000280 FT_Memory memory = FT_FACE_MEMORY( slot->face );
281 FT_Error error;
Werner Lemberg51daa4f2003-05-18 22:40:11 +0000282
283
Werner Lemberg7a024102003-06-18 06:59:57 +0000284 if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP )
David Turner66cbc202003-03-20 07:04:40 +0000285 FT_FREE( slot->bitmap.buffer );
286 else
Werner Lemberg7a024102003-06-18 06:59:57 +0000287 slot->internal->flags |= FT_GLYPH_OWN_BITMAP;
Werner Lemberg51daa4f2003-05-18 22:40:11 +0000288
David Turner6a681fa2006-01-27 12:11:22 +0000289 (void)FT_ALLOC( slot->bitmap.buffer, size );
290 return error;
Werner Lemberg51daa4f2003-05-18 22:40:11 +0000291 }
David Turner66cbc202003-03-20 07:04:40 +0000292
David Turnerf0df85b2000-06-22 00:17:42 +0000293
Werner Lembergf814d0f2001-06-27 16:18:10 +0000294 static void
295 ft_glyphslot_clear( FT_GlyphSlot slot )
David Turnerf0df85b2000-06-22 00:17:42 +0000296 {
David Turner5ae831c2000-06-30 01:31:22 +0000297 /* free bitmap if needed */
David Turner66cbc202003-03-20 07:04:40 +0000298 ft_glyphslot_free_bitmap( slot );
Werner Lembergfbeb41d2000-07-02 00:27:53 +0000299
David Turnerf0df85b2000-06-22 00:17:42 +0000300 /* clear all public fields in the glyph slot */
David Turner3249c622002-10-31 08:30:19 +0000301 FT_ZERO( &slot->metrics );
302 FT_ZERO( &slot->outline );
303
Werner Lemberg0f1c4fa2005-06-06 07:01:47 +0000304 slot->bitmap.width = 0;
305 slot->bitmap.rows = 0;
306 slot->bitmap.pitch = 0;
David Turner3249c622002-10-31 08:30:19 +0000307 slot->bitmap.pixel_mode = 0;
Werner Lemberg0f1c4fa2005-06-06 07:01:47 +0000308 /* `slot->bitmap.buffer' has been handled by ft_glyphslot_free_bitmap */
David Turnerf0df85b2000-06-22 00:17:42 +0000309
310 slot->bitmap_left = 0;
311 slot->bitmap_top = 0;
312 slot->num_subglyphs = 0;
313 slot->subglyphs = 0;
314 slot->control_data = 0;
315 slot->control_len = 0;
316 slot->other = 0;
David Turnerb08fe2d2002-08-27 20:20:29 +0000317 slot->format = FT_GLYPH_FORMAT_NONE;
David Turnerf0df85b2000-06-22 00:17:42 +0000318
319 slot->linearHoriAdvance = 0;
320 slot->linearVertAdvance = 0;
Werner Lemberg34f4f392004-12-09 22:22:52 +0000321 slot->lsb_delta = 0;
322 slot->rsb_delta = 0;
David Turnerf0df85b2000-06-22 00:17:42 +0000323 }
324
325
Werner Lembergf814d0f2001-06-27 16:18:10 +0000326 static void
327 ft_glyphslot_done( FT_GlyphSlot slot )
David Turnerf0df85b2000-06-22 00:17:42 +0000328 {
Werner Lemberg9cc4aed2006-01-26 21:03:58 +0000329 FT_Driver driver = slot->face->driver;
330 FT_Driver_Class clazz = driver->clazz;
331 FT_Memory memory = driver->root.memory;
David Turnerf0df85b2000-06-22 00:17:42 +0000332
Werner Lemberga929ba92000-06-25 06:47:11 +0000333
David Turner54e75742000-11-04 02:52:02 +0000334 if ( clazz->done_slot )
335 clazz->done_slot( slot );
336
David Turnerf0df85b2000-06-22 00:17:42 +0000337 /* free bitmap buffer if needed */
David Turner66cbc202003-03-20 07:04:40 +0000338 ft_glyphslot_free_bitmap( slot );
David Turnerf0df85b2000-06-22 00:17:42 +0000339
340 /* free glyph loader */
Werner Lemberga929ba92000-06-25 06:47:11 +0000341 if ( FT_DRIVER_USES_OUTLINES( driver ) )
David Turnerf0df85b2000-06-22 00:17:42 +0000342 {
David Turner54e75742000-11-04 02:52:02 +0000343 FT_GlyphLoader_Done( slot->internal->loader );
344 slot->internal->loader = 0;
David Turnerf0df85b2000-06-22 00:17:42 +0000345 }
346
David Turnere459d742002-03-22 13:52:37 +0000347 FT_FREE( slot->internal );
David Turnerf0df85b2000-06-22 00:17:42 +0000348 }
349
350
Werner Lemberg8ec9dfd2000-11-07 23:56:02 +0000351 /* documentation is in ftobjs.h */
352
Werner Lembergf814d0f2001-06-27 16:18:10 +0000353 FT_BASE_DEF( FT_Error )
354 FT_New_GlyphSlot( FT_Face face,
355 FT_GlyphSlot *aslot )
David Turnerf0df85b2000-06-22 00:17:42 +0000356 {
Werner Lemberg9cc4aed2006-01-26 21:03:58 +0000357 FT_Error error;
358 FT_Driver driver;
359 FT_Driver_Class clazz;
360 FT_Memory memory;
361 FT_GlyphSlot slot;
Werner Lemberga929ba92000-06-25 06:47:11 +0000362
David Turnerf0df85b2000-06-22 00:17:42 +0000363
Werner Lembergb9ee7372005-05-20 21:52:19 +0000364 if ( !face || !face->driver )
David Turnerf0df85b2000-06-22 00:17:42 +0000365 return FT_Err_Invalid_Argument;
366
367 driver = face->driver;
368 clazz = driver->clazz;
369 memory = driver->root.memory;
370
371 FT_TRACE4(( "FT_New_GlyphSlot: Creating new slot object\n" ));
David Turnere459d742002-03-22 13:52:37 +0000372 if ( !FT_ALLOC( slot, clazz->slot_object_size ) )
David Turnerf0df85b2000-06-22 00:17:42 +0000373 {
374 slot->face = face;
375
376 error = ft_glyphslot_init( slot );
Werner Lemberga929ba92000-06-25 06:47:11 +0000377 if ( error )
David Turnerf0df85b2000-06-22 00:17:42 +0000378 {
379 ft_glyphslot_done( slot );
David Turnere459d742002-03-22 13:52:37 +0000380 FT_FREE( slot );
David Turnerf0df85b2000-06-22 00:17:42 +0000381 goto Exit;
382 }
383
Werner Lembergb9ee7372005-05-20 21:52:19 +0000384 slot->next = face->glyph;
385 face->glyph = slot;
386
387 if ( aslot )
388 *aslot = slot;
David Turnerf0df85b2000-06-22 00:17:42 +0000389 }
Werner Lembergb9ee7372005-05-20 21:52:19 +0000390 else if ( aslot )
391 *aslot = 0;
392
David Turnerf0df85b2000-06-22 00:17:42 +0000393
394 Exit:
395 FT_TRACE4(( "FT_New_GlyphSlot: Return %d\n", error ));
396 return error;
397 }
398
399
Werner Lemberg8ec9dfd2000-11-07 23:56:02 +0000400 /* documentation is in ftobjs.h */
401
Werner Lembergf814d0f2001-06-27 16:18:10 +0000402 FT_BASE_DEF( void )
403 FT_Done_GlyphSlot( FT_GlyphSlot slot )
David Turnerf0df85b2000-06-22 00:17:42 +0000404 {
405 if ( slot )
406 {
Werner Lembergb9ee7372005-05-20 21:52:19 +0000407 FT_Driver driver = slot->face->driver;
408 FT_Memory memory = driver->root.memory;
409 FT_GlyphSlot prev;
410 FT_GlyphSlot cur;
David Turnerf0df85b2000-06-22 00:17:42 +0000411
Werner Lemberga929ba92000-06-25 06:47:11 +0000412
David Turnerf0df85b2000-06-22 00:17:42 +0000413 /* Remove slot from its parent face's list */
Werner Lembergb9ee7372005-05-20 21:52:19 +0000414 prev = NULL;
415 cur = slot->face->glyph;
Werner Lemberga929ba92000-06-25 06:47:11 +0000416
David Turnerf0df85b2000-06-22 00:17:42 +0000417 while ( cur )
418 {
419 if ( cur == slot )
420 {
Werner Lembergb9ee7372005-05-20 21:52:19 +0000421 if ( !prev )
422 slot->face->glyph = cur->next;
423 else
424 prev->next = cur->next;
425
Werner Lemberga929ba92000-06-25 06:47:11 +0000426 ft_glyphslot_done( slot );
David Turnere459d742002-03-22 13:52:37 +0000427 FT_FREE( slot );
David Turnerf0df85b2000-06-22 00:17:42 +0000428 break;
429 }
Werner Lembergb9ee7372005-05-20 21:52:19 +0000430 prev = cur;
431 cur = cur->next;
David Turnerf0df85b2000-06-22 00:17:42 +0000432 }
433 }
434 }
435
436
Werner Lemberg90a03302000-11-07 17:21:11 +0000437 /* documentation is in freetype.h */
438
Werner Lembergf814d0f2001-06-27 16:18:10 +0000439 FT_EXPORT_DEF( void )
440 FT_Set_Transform( FT_Face face,
441 FT_Matrix* matrix,
442 FT_Vector* delta )
David Turnerf0df85b2000-06-22 00:17:42 +0000443 {
David Turner54e75742000-11-04 02:52:02 +0000444 FT_Face_Internal internal;
David Turner61d6b2b2001-05-16 17:49:07 +0000445
David Turner54e75742000-11-04 02:52:02 +0000446
David Turnerf0df85b2000-06-22 00:17:42 +0000447 if ( !face )
448 return;
449
David Turner54e75742000-11-04 02:52:02 +0000450 internal = face->internal;
451
452 internal->transform_flags = 0;
David Turnerf0df85b2000-06-22 00:17:42 +0000453
454 if ( !matrix )
455 {
David Turner54e75742000-11-04 02:52:02 +0000456 internal->transform_matrix.xx = 0x10000L;
457 internal->transform_matrix.xy = 0;
458 internal->transform_matrix.yx = 0;
459 internal->transform_matrix.yy = 0x10000L;
460 matrix = &internal->transform_matrix;
David Turnerf0df85b2000-06-22 00:17:42 +0000461 }
462 else
David Turner54e75742000-11-04 02:52:02 +0000463 internal->transform_matrix = *matrix;
David Turnerf0df85b2000-06-22 00:17:42 +0000464
465 /* set transform_flags bit flag 0 if `matrix' isn't the identity */
466 if ( ( matrix->xy | matrix->yx ) ||
467 matrix->xx != 0x10000L ||
468 matrix->yy != 0x10000L )
David Turner54e75742000-11-04 02:52:02 +0000469 internal->transform_flags |= 1;
David Turnerf0df85b2000-06-22 00:17:42 +0000470
471 if ( !delta )
472 {
David Turner54e75742000-11-04 02:52:02 +0000473 internal->transform_delta.x = 0;
474 internal->transform_delta.y = 0;
475 delta = &internal->transform_delta;
David Turnerf0df85b2000-06-22 00:17:42 +0000476 }
477 else
David Turner54e75742000-11-04 02:52:02 +0000478 internal->transform_delta = *delta;
David Turnerf0df85b2000-06-22 00:17:42 +0000479
480 /* set transform_flags bit flag 1 if `delta' isn't the null vector */
481 if ( delta->x | delta->y )
David Turner54e75742000-11-04 02:52:02 +0000482 internal->transform_flags |= 2;
David Turnerf0df85b2000-06-22 00:17:42 +0000483 }
484
485
Werner Lembergf814d0f2001-06-27 16:18:10 +0000486 static FT_Renderer
487 ft_lookup_glyph_renderer( FT_GlyphSlot slot );
Werner Lembergdeb4e982000-06-29 03:14:25 +0000488
489
Wu, Chia-I (吳佳一)2e48a1a2006-02-27 09:18:07 +0000490#ifdef GRID_FIT_METRICS
491 static void
492 ft_glyphslot_grid_fit_metrics( FT_GlyphSlot slot,
493 FT_Bool vertical )
494 {
495 FT_Glyph_Metrics* metrics = &slot->metrics;
496 FT_Pos right, bottom;
497
498
499 if ( vertical )
500 {
501 metrics->horiBearingX = FT_PIX_FLOOR( metrics->horiBearingX );
502 metrics->horiBearingY = FT_PIX_CEIL ( metrics->horiBearingY );
503
504 right = FT_PIX_CEIL( metrics->vertBearingX + metrics->width );
505 bottom = FT_PIX_CEIL( metrics->vertBearingY + metrics->height );
506
507 metrics->vertBearingX = FT_PIX_FLOOR( metrics->vertBearingX );
508 metrics->vertBearingY = FT_PIX_FLOOR( metrics->vertBearingY );
509
510 metrics->width = right - metrics->vertBearingX;
511 metrics->height = bottom - metrics->vertBearingY;
512 }
513 else
514 {
515 metrics->vertBearingX = FT_PIX_FLOOR( metrics->vertBearingX );
516 metrics->vertBearingY = FT_PIX_FLOOR( metrics->vertBearingY );
517
518 right = FT_PIX_CEIL ( metrics->horiBearingX + metrics->width );
519 bottom = FT_PIX_FLOOR( metrics->horiBearingY - metrics->height );
520
521 metrics->horiBearingX = FT_PIX_FLOOR( metrics->horiBearingX );
522 metrics->horiBearingY = FT_PIX_CEIL ( metrics->horiBearingY );
523
524 metrics->width = right - metrics->horiBearingX;
525 metrics->height = metrics->horiBearingY - bottom;
526 }
527
528 metrics->horiAdvance = FT_PIX_ROUND( metrics->horiAdvance );
529 metrics->vertAdvance = FT_PIX_ROUND( metrics->vertAdvance );
530 }
531#endif /* GRID_FIT_METRICS */
532
533
Werner Lemberg90a03302000-11-07 17:21:11 +0000534 /* documentation is in freetype.h */
535
Werner Lembergf814d0f2001-06-27 16:18:10 +0000536 FT_EXPORT_DEF( FT_Error )
Werner Lemberg6b5c6692002-09-05 15:10:54 +0000537 FT_Load_Glyph( FT_Face face,
538 FT_UInt glyph_index,
539 FT_Int32 load_flags )
David Turnerf0df85b2000-06-22 00:17:42 +0000540 {
541 FT_Error error;
542 FT_Driver driver;
543 FT_GlyphSlot slot;
David Turner5ae831c2000-06-30 01:31:22 +0000544 FT_Library library;
Wu, Chia-I (吳佳一)e5ff0592006-01-15 06:00:49 +0000545 FT_Bool autohint = 0;
David Turner5ae831c2000-06-30 01:31:22 +0000546 FT_Module hinter;
David Turnerf0df85b2000-06-22 00:17:42 +0000547
Werner Lemberga929ba92000-06-25 06:47:11 +0000548
David Turnerf0df85b2000-06-22 00:17:42 +0000549 if ( !face || !face->size || !face->glyph )
550 return FT_Err_Invalid_Face_Handle;
551
Werner Lemberg913a3652006-11-19 09:19:17 +0000552 /* The validity test for `glyph_index' is performed by the */
553 /* font drivers. */
David Turnerf0df85b2000-06-22 00:17:42 +0000554
555 slot = face->glyph;
556 ft_glyphslot_clear( slot );
557
Wu, Chia-I (吳佳一)e5ff0592006-01-15 06:00:49 +0000558 driver = face->driver;
559 library = driver->root.library;
560 hinter = library->auto_hinter;
David Turnerf0df85b2000-06-22 00:17:42 +0000561
Wu, Chia-I (吳佳一)e5ff0592006-01-15 06:00:49 +0000562 /* resolve load flags dependencies */
563
David Turnerf0df85b2000-06-22 00:17:42 +0000564 if ( load_flags & FT_LOAD_NO_RECURSE )
Werner Lembergeddd9902000-10-12 05:05:40 +0000565 load_flags |= FT_LOAD_NO_SCALE |
David Turnerc9ce9e42000-09-15 17:16:49 +0000566 FT_LOAD_IGNORE_TRANSFORM;
Werner Lembergeddd9902000-10-12 05:05:40 +0000567
Wu, Chia-I (吳佳一)e5ff0592006-01-15 06:00:49 +0000568 if ( load_flags & FT_LOAD_NO_SCALE )
569 {
570 load_flags |= FT_LOAD_NO_HINTING |
571 FT_LOAD_NO_BITMAP;
572
Werner Lembergeddd9902000-10-12 05:05:40 +0000573 load_flags &= ~FT_LOAD_RENDER;
David Turnerc9ce9e42000-09-15 17:16:49 +0000574 }
David Turnerf0df85b2000-06-22 00:17:42 +0000575
Werner Lemberg046bf8b2006-10-03 08:43:42 +0000576 /*
577 * Determine whether we need to auto-hint or not.
578 * The general rules are:
579 *
580 * - Do only auto-hinting if we have a hinter module,
581 * a scalable font format dealing with outlines,
582 * and no transforms except simple slants.
583 *
584 * - Then, autohint if FT_LOAD_FORCE_AUTOHINT is set
585 * or if we don't have a native font hinter.
586 *
587 * - Otherwise, auto-hint for LIGHT hinting mode.
588 *
589 * - Exception: The font requires the unpatented
590 * bytecode interpreter to load properly.
591 */
David Turnere6bb9532005-12-23 13:32:06 +0000592
David Turnerdf430e12006-10-01 00:09:35 +0000593 autohint = 0;
Werner Lemberg046bf8b2006-10-03 08:43:42 +0000594 if ( hinter &&
595 ( load_flags & FT_LOAD_NO_HINTING ) == 0 &&
596 ( load_flags & FT_LOAD_NO_AUTOHINT ) == 0 &&
597 FT_DRIVER_IS_SCALABLE( driver ) &&
598 FT_DRIVER_USES_OUTLINES( driver ) &&
599 face->internal->transform_matrix.yy > 0 &&
600 face->internal->transform_matrix.yx == 0 )
David Turner5ae831c2000-06-30 01:31:22 +0000601 {
Werner Lemberg046bf8b2006-10-03 08:43:42 +0000602 if ( ( load_flags & FT_LOAD_FORCE_AUTOHINT ) != 0 ||
603 !FT_DRIVER_HAS_HINTER( driver ) )
David Turnerdf430e12006-10-01 00:09:35 +0000604 autohint = 1;
David Turnerdf430e12006-10-01 00:09:35 +0000605 else
606 {
Werner Lemberg046bf8b2006-10-03 08:43:42 +0000607 FT_Render_Mode mode = FT_LOAD_TARGET_MODE( load_flags );
608
David Turnerdf430e12006-10-01 00:09:35 +0000609
610 if ( mode == FT_RENDER_MODE_LIGHT ||
611 face->internal->ignore_unpatented_hinter )
David Turnerdf430e12006-10-01 00:09:35 +0000612 autohint = 1;
David Turnerdf430e12006-10-01 00:09:35 +0000613 }
Werner Lembergcc9fc492000-06-30 06:21:26 +0000614 }
Werner Lembergfbeb41d2000-07-02 00:27:53 +0000615
Wu, Chia-I (吳佳一)e5ff0592006-01-15 06:00:49 +0000616 if ( autohint )
David Turner5ae831c2000-06-30 01:31:22 +0000617 {
David Turner9657ef02002-03-14 08:49:59 +0000618 FT_AutoHinter_Service hinting;
Werner Lembergfbeb41d2000-07-02 00:27:53 +0000619
Werner Lembergcc9fc492000-06-30 06:21:26 +0000620
Werner Lemberg0d535112001-12-19 22:26:12 +0000621 /* try to load embedded bitmaps first if available */
622 /* */
623 /* XXX: This is really a temporary hack that should disappear */
624 /* promptly with FreeType 2.1! */
David Turner4937a3e2001-12-19 21:09:16 +0000625 /* */
Werner Lembergeacb9302002-10-07 10:12:43 +0000626 if ( FT_HAS_FIXED_SIZES( face ) &&
David Turner80171e02002-10-05 14:57:03 +0000627 ( load_flags & FT_LOAD_NO_BITMAP ) == 0 )
David Turner4937a3e2001-12-19 21:09:16 +0000628 {
629 error = driver->clazz->load_glyph( slot, face->size,
630 glyph_index,
631 load_flags | FT_LOAD_SBITS_ONLY );
632
David Turnerb08fe2d2002-08-27 20:20:29 +0000633 if ( !error && slot->format == FT_GLYPH_FORMAT_BITMAP )
David Turner4937a3e2001-12-19 21:09:16 +0000634 goto Load_Ok;
635 }
636
Werner Lemberg6d29f0f2008-05-03 15:54:15 +0000637 {
638 FT_Face_Internal internal = face->internal;
639 FT_Int transform_flags = internal->transform_flags;
David Turner76a5f622000-11-04 01:55:49 +0000640
Werner Lemberg6d29f0f2008-05-03 15:54:15 +0000641
642 /* since the auto-hinter calls FT_Load_Glyph by itself, */
643 /* make sure that glyphs aren't transformed */
644 internal->transform_flags = 0;
645
646 /* load auto-hinted outline */
647 hinting = (FT_AutoHinter_Service)hinter->clazz->module_interface;
648
649 error = hinting->load_glyph( (FT_AutoHinter)hinter,
650 slot, face->size,
651 glyph_index, load_flags );
652
653 internal->transform_flags = transform_flags;
654 }
David Turner5ae831c2000-06-30 01:31:22 +0000655 }
656 else
David Turner662b3442002-01-03 16:56:59 +0000657 {
David Turner5ae831c2000-06-30 01:31:22 +0000658 error = driver->clazz->load_glyph( slot,
659 face->size,
Werner Lembergcc9fc492000-06-30 06:21:26 +0000660 glyph_index,
661 load_flags );
David Turner662b3442002-01-03 16:56:59 +0000662 if ( error )
663 goto Exit;
664
Wu, Chia-I (吳佳一)2e48a1a2006-02-27 09:18:07 +0000665 if ( slot->format == FT_GLYPH_FORMAT_OUTLINE )
666 {
667 /* check that the loaded outline is correct */
668 error = FT_Outline_Check( &slot->outline );
669 if ( error )
670 goto Exit;
671
672#ifdef GRID_FIT_METRICS
673 if ( !( load_flags & FT_LOAD_NO_HINTING ) )
674 ft_glyphslot_grid_fit_metrics( slot,
David Turnerda95af62006-03-20 13:32:33 +0000675 FT_BOOL( load_flags & FT_LOAD_VERTICAL_LAYOUT ) );
Wu, Chia-I (吳佳一)2e48a1a2006-02-27 09:18:07 +0000676#endif
677 }
David Turner662b3442002-01-03 16:56:59 +0000678 }
David Turnerf0df85b2000-06-22 00:17:42 +0000679
David Turner4937a3e2001-12-19 21:09:16 +0000680 Load_Ok:
David Turnerf0df85b2000-06-22 00:17:42 +0000681 /* compute the advance */
Werner Lemberga929ba92000-06-25 06:47:11 +0000682 if ( load_flags & FT_LOAD_VERTICAL_LAYOUT )
David Turnerf0df85b2000-06-22 00:17:42 +0000683 {
684 slot->advance.x = 0;
685 slot->advance.y = slot->metrics.vertAdvance;
686 }
687 else
688 {
689 slot->advance.x = slot->metrics.horiAdvance;
690 slot->advance.y = 0;
691 }
692
David Turnerc9ce9e42000-09-15 17:16:49 +0000693 /* compute the linear advance in 16.16 pixels */
Werner Lemberg51daa4f2003-05-18 22:40:11 +0000694 if ( ( load_flags & FT_LOAD_LINEAR_DESIGN ) == 0 &&
695 ( face->face_flags & FT_FACE_FLAG_SCALABLE ) )
David Turnerc9ce9e42000-09-15 17:16:49 +0000696 {
David Turnerc9ce9e42000-09-15 17:16:49 +0000697 FT_Size_Metrics* metrics = &face->size->metrics;
Werner Lembergeddd9902000-10-12 05:05:40 +0000698
Werner Lembergf8ba2002002-03-30 13:16:35 +0000699
Wu, Chia-I (吳佳一)e5ff0592006-01-15 06:00:49 +0000700 /* it's tricky! */
David Turnerc9ce9e42000-09-15 17:16:49 +0000701 slot->linearHoriAdvance = FT_MulDiv( slot->linearHoriAdvance,
Werner Lembergbe67c4e2003-11-24 22:54:58 +0000702 metrics->x_scale, 64 );
David Turnerc9ce9e42000-09-15 17:16:49 +0000703
704 slot->linearVertAdvance = FT_MulDiv( slot->linearVertAdvance,
Werner Lembergbe67c4e2003-11-24 22:54:58 +0000705 metrics->y_scale, 64 );
David Turnerc9ce9e42000-09-15 17:16:49 +0000706 }
707
708 if ( ( load_flags & FT_LOAD_IGNORE_TRANSFORM ) == 0 )
David Turnerf0df85b2000-06-22 00:17:42 +0000709 {
David Turner54e75742000-11-04 02:52:02 +0000710 FT_Face_Internal internal = face->internal;
David Turner61d6b2b2001-05-16 17:49:07 +0000711
712
Werner Lembergd1b74752000-08-24 16:29:15 +0000713 /* now, transform the glyph image if needed */
David Turner54e75742000-11-04 02:52:02 +0000714 if ( internal->transform_flags )
David Turner35db7322000-08-24 12:39:40 +0000715 {
716 /* get renderer */
717 FT_Renderer renderer = ft_lookup_glyph_renderer( slot );
Werner Lembergdeb4e982000-06-29 03:14:25 +0000718
Werner Lemberga929ba92000-06-25 06:47:11 +0000719
David Turner35db7322000-08-24 12:39:40 +0000720 if ( renderer )
Werner Lembergdc72aff2000-11-04 08:33:38 +0000721 error = renderer->clazz->transform_glyph(
722 renderer, slot,
723 &internal->transform_matrix,
724 &internal->transform_delta );
David Turner35db7322000-08-24 12:39:40 +0000725 /* transform advance */
David Turner54e75742000-11-04 02:52:02 +0000726 FT_Vector_Transform( &slot->advance, &internal->transform_matrix );
David Turner35db7322000-08-24 12:39:40 +0000727 }
David Turnerc9ce9e42000-09-15 17:16:49 +0000728 }
David Turnerf0df85b2000-06-22 00:17:42 +0000729
David Turnerc9ce9e42000-09-15 17:16:49 +0000730 /* do we need to render the image now? */
731 if ( !error &&
David Turnerb08fe2d2002-08-27 20:20:29 +0000732 slot->format != FT_GLYPH_FORMAT_BITMAP &&
733 slot->format != FT_GLYPH_FORMAT_COMPOSITE &&
David Turnerc9ce9e42000-09-15 17:16:49 +0000734 load_flags & FT_LOAD_RENDER )
735 {
David Turner00d9f402002-09-08 21:29:11 +0000736 FT_Render_Mode mode = FT_LOAD_TARGET_MODE( load_flags );
737
Werner Lemberg68e9f922002-09-27 11:09:23 +0000738
David Turner00d9f402002-09-08 21:29:11 +0000739 if ( mode == FT_RENDER_MODE_NORMAL &&
740 (load_flags & FT_LOAD_MONOCHROME ) )
741 mode = FT_RENDER_MODE_MONO;
742
743 error = FT_Render_Glyph( slot, mode );
Werner Lembergd060a752000-07-20 06:57:41 +0000744 }
David Turner5ae831c2000-06-30 01:31:22 +0000745
Werner Lembergdeb4e982000-06-29 03:14:25 +0000746 Exit:
David Turnerf0df85b2000-06-22 00:17:42 +0000747 return error;
748 }
749
750
Werner Lemberg90a03302000-11-07 17:21:11 +0000751 /* documentation is in freetype.h */
752
Werner Lembergf814d0f2001-06-27 16:18:10 +0000753 FT_EXPORT_DEF( FT_Error )
754 FT_Load_Char( FT_Face face,
755 FT_ULong char_code,
David Turnerf467e6a2002-08-21 21:39:28 +0000756 FT_Int32 load_flags )
David Turnerf0df85b2000-06-22 00:17:42 +0000757 {
Werner Lembergdeb4e982000-06-29 03:14:25 +0000758 FT_UInt glyph_index;
David Turnerf0df85b2000-06-22 00:17:42 +0000759
Werner Lemberga929ba92000-06-25 06:47:11 +0000760
David Turnerf0df85b2000-06-22 00:17:42 +0000761 if ( !face )
762 return FT_Err_Invalid_Face_Handle;
763
764 glyph_index = (FT_UInt)char_code;
Werner Lemberga929ba92000-06-25 06:47:11 +0000765 if ( face->charmap )
David Turnerf0df85b2000-06-22 00:17:42 +0000766 glyph_index = FT_Get_Char_Index( face, char_code );
767
David Turner5ae831c2000-06-30 01:31:22 +0000768 return FT_Load_Glyph( face, glyph_index, load_flags );
David Turnerf0df85b2000-06-22 00:17:42 +0000769 }
770
771
Werner Lemberg7880dd62000-01-10 17:19:45 +0000772 /* destructor for sizes list */
Werner Lembergf814d0f2001-06-27 16:18:10 +0000773 static void
774 destroy_size( FT_Memory memory,
775 FT_Size size,
776 FT_Driver driver )
Werner Lemberg7880dd62000-01-10 17:19:45 +0000777 {
David Turnerf0df85b2000-06-22 00:17:42 +0000778 /* finalize client-specific data */
Werner Lemberga929ba92000-06-25 06:47:11 +0000779 if ( size->generic.finalizer )
David Turnerf0df85b2000-06-22 00:17:42 +0000780 size->generic.finalizer( size );
781
Werner Lemberg7880dd62000-01-10 17:19:45 +0000782 /* finalize format-specific stuff */
Werner Lemberga929ba92000-06-25 06:47:11 +0000783 if ( driver->clazz->done_size )
David Turnerf0df85b2000-06-22 00:17:42 +0000784 driver->clazz->done_size( size );
785
David Turnere459d742002-03-22 13:52:37 +0000786 FT_FREE( size->internal );
787 FT_FREE( size );
Werner Lemberg7880dd62000-01-10 17:19:45 +0000788 }
David Turnerd2b1f351999-12-16 23:11:37 +0000789
790
Werner Lemberg4338dab2004-01-05 14:41:59 +0000791 static void
Werner Lemberge70371c2005-05-27 06:01:28 +0000792 ft_cmap_done_internal( FT_CMap cmap );
793
794
795 static void
Werner Lemberg4338dab2004-01-05 14:41:59 +0000796 destroy_charmaps( FT_Face face,
797 FT_Memory memory )
798 {
799 FT_Int n;
800
801
Werner Lemberg3d507fe2007-06-03 16:54:55 +0000802 if ( !face )
803 return;
804
Werner Lemberg4338dab2004-01-05 14:41:59 +0000805 for ( n = 0; n < face->num_charmaps; n++ )
806 {
807 FT_CMap cmap = FT_CMAP( face->charmaps[n] );
808
809
Werner Lemberge70371c2005-05-27 06:01:28 +0000810 ft_cmap_done_internal( cmap );
Werner Lemberg4338dab2004-01-05 14:41:59 +0000811
812 face->charmaps[n] = NULL;
813 }
814
815 FT_FREE( face->charmaps );
816 face->num_charmaps = 0;
817 }
818
819
Werner Lemberg7880dd62000-01-10 17:19:45 +0000820 /* destructor for faces list */
Werner Lembergf814d0f2001-06-27 16:18:10 +0000821 static void
822 destroy_face( FT_Memory memory,
823 FT_Face face,
824 FT_Driver driver )
Werner Lemberg7880dd62000-01-10 17:19:45 +0000825 {
David Turneref3c1262002-03-14 09:22:48 +0000826 FT_Driver_Class clazz = driver->clazz;
David Turnerf0df85b2000-06-22 00:17:42 +0000827
Werner Lembergd060a752000-07-20 06:57:41 +0000828
David Turnerc49f69c2000-07-20 03:44:50 +0000829 /* discard auto-hinting data */
830 if ( face->autohint.finalizer )
831 face->autohint.finalizer( face->autohint.data );
Werner Lembergeddd9902000-10-12 05:05:40 +0000832
Werner Lembergf8ba2002002-03-30 13:16:35 +0000833 /* Discard glyph slots for this face. */
David Turner23bcde12001-10-17 13:48:10 +0000834 /* Beware! FT_Done_GlyphSlot() changes the field `face->glyph' */
Werner Lemberg7880dd62000-01-10 17:19:45 +0000835 while ( face->glyph )
836 FT_Done_GlyphSlot( face->glyph );
837
Werner Lembergf8ba2002002-03-30 13:16:35 +0000838 /* discard all sizes for this face */
Werner Lemberg7880dd62000-01-10 17:19:45 +0000839 FT_List_Finalize( &face->sizes_list,
Werner Lemberg74184152003-10-18 16:56:13 +0000840 (FT_List_Destructor)destroy_size,
841 memory,
842 driver );
Werner Lemberg7880dd62000-01-10 17:19:45 +0000843 face->size = 0;
844
Werner Lembergf8ba2002002-03-30 13:16:35 +0000845 /* now discard client data */
Werner Lemberg7880dd62000-01-10 17:19:45 +0000846 if ( face->generic.finalizer )
847 face->generic.finalizer( face );
848
David Turner2ded2c12002-03-22 22:37:40 +0000849 /* discard charmaps */
Werner Lemberg4338dab2004-01-05 14:41:59 +0000850 destroy_charmaps( face, memory );
Werner Lemberg75435332004-02-25 12:58:54 +0000851
David Turnerf0df85b2000-06-22 00:17:42 +0000852 /* finalize format-specific stuff */
Werner Lemberga929ba92000-06-25 06:47:11 +0000853 if ( clazz->done_face )
854 clazz->done_face( face );
David Turnerf0df85b2000-06-22 00:17:42 +0000855
856 /* close the stream for this face if needed */
Werner Lemberg75435332004-02-25 12:58:54 +0000857 FT_Stream_Free(
Werner Lembergf8ba2002002-03-30 13:16:35 +0000858 face->stream,
Werner Lemberg58b17f92000-07-27 23:29:08 +0000859 ( face->face_flags & FT_FACE_FLAG_EXTERNAL_STREAM ) != 0 );
David Turner7663f222000-02-13 13:37:38 +0000860
David Turner53b3fa12002-02-24 05:26:57 +0000861 face->stream = 0;
862
Werner Lemberg7880dd62000-01-10 17:19:45 +0000863 /* get rid of it */
David Turner23bcde12001-10-17 13:48:10 +0000864 if ( face->internal )
865 {
David Turnere459d742002-03-22 13:52:37 +0000866 FT_FREE( face->internal );
David Turner23bcde12001-10-17 13:48:10 +0000867 }
David Turnere459d742002-03-22 13:52:37 +0000868 FT_FREE( face );
Werner Lemberg7880dd62000-01-10 17:19:45 +0000869 }
David Turnerd2b1f351999-12-16 23:11:37 +0000870
871
Werner Lembergf814d0f2001-06-27 16:18:10 +0000872 static void
873 Destroy_Driver( FT_Driver driver )
David Turnerd2b1f351999-12-16 23:11:37 +0000874 {
David Turnerd2b1f351999-12-16 23:11:37 +0000875 FT_List_Finalize( &driver->faces_list,
876 (FT_List_Destructor)destroy_face,
David Turnerf0df85b2000-06-22 00:17:42 +0000877 driver->root.memory,
David Turnerd2b1f351999-12-16 23:11:37 +0000878 driver );
879
Werner Lembergdeb4e982000-06-29 03:14:25 +0000880 /* check whether we need to drop the driver's glyph loader */
Werner Lemberga929ba92000-06-25 06:47:11 +0000881 if ( FT_DRIVER_USES_OUTLINES( driver ) )
David Turnerf0df85b2000-06-22 00:17:42 +0000882 FT_GlyphLoader_Done( driver->glyph_loader );
David Turnerd2b1f351999-12-16 23:11:37 +0000883 }
884
885
Werner Lemberg547a2522000-02-16 08:23:58 +0000886 /*************************************************************************/
887 /* */
888 /* <Function> */
Antoine Lecac96f69d2002-12-03 00:39:16 +0000889 /* find_unicode_charmap */
890 /* */
891 /* <Description> */
892 /* This function finds a Unicode charmap, if there is one. */
893 /* And if there is more than one, it tries to favour the more */
Werner Lembergc8c6bf52003-04-23 05:38:13 +0000894 /* extensive one, i.e., one that supports UCS-4 against those which */
Antoine Lecac96f69d2002-12-03 00:39:16 +0000895 /* are limited to the BMP (said UCS-2 encoding.) */
896 /* */
897 /* This function is called from open_face() (just below), and also */
Werner Lemberg74597cc2007-10-01 07:08:56 +0000898 /* from FT_Select_Charmap( ..., FT_ENCODING_UNICODE ). */
Antoine Lecac96f69d2002-12-03 00:39:16 +0000899 /* */
900 static FT_Error
901 find_unicode_charmap( FT_Face face )
902 {
903 FT_CharMap* first;
904 FT_CharMap* cur;
Antoine Lecac96f69d2002-12-03 00:39:16 +0000905
906
907 /* caller should have already checked that `face' is valid */
Werner Lemberg74184152003-10-18 16:56:13 +0000908 FT_ASSERT( face );
Antoine Lecac96f69d2002-12-03 00:39:16 +0000909
910 first = face->charmaps;
911
912 if ( !first )
913 return FT_Err_Invalid_CharMap_Handle;
914
David Turnerc528f6f2002-12-18 22:43:07 +0000915 /*
Werner Lembergc8c6bf52003-04-23 05:38:13 +0000916 * The original TrueType specification(s) only specified charmap
David Turnerc528f6f2002-12-18 22:43:07 +0000917 * formats that are capable of mapping 8 or 16 bit character codes to
918 * glyph indices.
919 *
Werner Lembergc8c6bf52003-04-23 05:38:13 +0000920 * However, recent updates to the Apple and OpenType specifications
David Turnerc528f6f2002-12-18 22:43:07 +0000921 * introduced new formats that are capable of mapping 32-bit character
Werner Lembergc8c6bf52003-04-23 05:38:13 +0000922 * codes as well. And these are already used on some fonts, mainly to
David Turnerae26c682003-02-25 20:37:50 +0000923 * map non-BMP Asian ideographs as defined in Unicode.
David Turnerc528f6f2002-12-18 22:43:07 +0000924 *
Werner Lembergc8c6bf52003-04-23 05:38:13 +0000925 * For compatibility purposes, these fonts generally come with
David Turnerc528f6f2002-12-18 22:43:07 +0000926 * *several* Unicode charmaps:
927 *
Werner Lembergc8c6bf52003-04-23 05:38:13 +0000928 * - One of them in the "old" 16-bit format, that cannot access
929 * all glyphs in the font.
David Turnerc528f6f2002-12-18 22:43:07 +0000930 *
Werner Lembergc8c6bf52003-04-23 05:38:13 +0000931 * - Another one in the "new" 32-bit format, that can access all
David Turnerc528f6f2002-12-18 22:43:07 +0000932 * the glyphs.
933 *
Werner Lembergc8c6bf52003-04-23 05:38:13 +0000934 * This function has been written to always favor a 32-bit charmap
935 * when found. Otherwise, a 16-bit one is returned when found.
David Turnerc528f6f2002-12-18 22:43:07 +0000936 */
937
Werner Lemberg8acb8672005-03-08 11:43:36 +0000938 /* Since the `interesting' table, with IDs (3,10), is normally the */
Werner Lemberg1e259de2007-03-08 15:39:21 +0000939 /* last one, we loop backwards. This loses with type1 fonts with */
Werner Lemberg8acb8672005-03-08 11:43:36 +0000940 /* non-BMP characters (<.0001%), this wins with .ttf with non-BMP */
941 /* chars (.01% ?), and this is the same about 99.99% of the time! */
Antoine Lecac96f69d2002-12-03 00:39:16 +0000942
943 cur = first + face->num_charmaps; /* points after the last one */
944
945 for ( ; --cur >= first; )
946 {
947 if ( cur[0]->encoding == FT_ENCODING_UNICODE )
948 {
Werner Lemberg74597cc2007-10-01 07:08:56 +0000949 /* XXX If some new encodings to represent UCS-4 are added, */
950 /* they should be added here. */
David Turnerc528f6f2002-12-18 22:43:07 +0000951 if ( ( cur[0]->platform_id == TT_PLATFORM_MICROSOFT &&
Werner Lemberg74597cc2007-10-01 07:08:56 +0000952 cur[0]->encoding_id == TT_MS_ID_UCS_4 ) ||
David Turnerc528f6f2002-12-18 22:43:07 +0000953 ( cur[0]->platform_id == TT_PLATFORM_APPLE_UNICODE &&
Werner Lemberg74597cc2007-10-01 07:08:56 +0000954 cur[0]->encoding_id == TT_APPLE_ID_UNICODE_32 ) )
Antoine Lecac96f69d2002-12-03 00:39:16 +0000955 {
956 face->charmap = cur[0];
Werner Lemberg74597cc2007-10-01 07:08:56 +0000957 return FT_Err_Ok;
Antoine Lecac96f69d2002-12-03 00:39:16 +0000958 }
959 }
960 }
961
Werner Lemberg74597cc2007-10-01 07:08:56 +0000962 /* We do not have any UCS-4 charmap. */
963 /* Do the loop again and search for UCS-2 charmaps. */
964 cur = first + face->num_charmaps;
965
966 for ( ; --cur >= first; )
Antoine Lecac96f69d2002-12-03 00:39:16 +0000967 {
Werner Lemberg74597cc2007-10-01 07:08:56 +0000968 if ( cur[0]->encoding == FT_ENCODING_UNICODE )
969 {
970 face->charmap = cur[0];
971 return FT_Err_Ok;
972 }
Antoine Lecac96f69d2002-12-03 00:39:16 +0000973 }
974
David Turner6453a812003-01-08 09:28:34 +0000975 return FT_Err_Invalid_CharMap_Handle;
Antoine Lecac96f69d2002-12-03 00:39:16 +0000976 }
977
978
979 /*************************************************************************/
980 /* */
981 /* <Function> */
Werner Lemberg9a966b72007-10-15 17:21:32 +0000982 /* find_variant_selector_charmap */
983 /* */
984 /* <Description> */
985 /* This function finds the variant selector charmap, if there is one. */
986 /* There can only be one (platform=0, specific=5, format=14). */
987 /* */
988 static FT_CharMap
989 find_variant_selector_charmap( FT_Face face )
990 {
991 FT_CharMap* first;
992 FT_CharMap* end;
993 FT_CharMap* cur;
994
995
996 /* caller should have already checked that `face' is valid */
997 FT_ASSERT( face );
998
999 first = face->charmaps;
1000
1001 if ( !first )
1002 return NULL;
1003
1004 end = first + face->num_charmaps; /* points after the last one */
1005
1006 for ( cur = first; cur < end; ++cur )
1007 {
1008 if ( cur[0]->platform_id == TT_PLATFORM_APPLE_UNICODE &&
1009 cur[0]->encoding_id == TT_APPLE_ID_VARIANT_SELECTOR &&
1010 FT_Get_CMap_Format( cur[0] ) == 14 )
1011 return cur[0];
1012 }
1013
1014 return NULL;
1015 }
1016
1017
1018 /*************************************************************************/
1019 /* */
1020 /* <Function> */
Werner Lemberg547a2522000-02-16 08:23:58 +00001021 /* open_face */
1022 /* */
1023 /* <Description> */
1024 /* This function does some work for FT_Open_Face(). */
1025 /* */
Werner Lembergf814d0f2001-06-27 16:18:10 +00001026 static FT_Error
1027 open_face( FT_Driver driver,
1028 FT_Stream stream,
1029 FT_Long face_index,
1030 FT_Int num_params,
1031 FT_Parameter* params,
Werner Lemberg6d798992003-07-01 07:28:55 +00001032 FT_Face *aface )
David Turnerd2b1f351999-12-16 23:11:37 +00001033 {
David Turnerf0df85b2000-06-22 00:17:42 +00001034 FT_Memory memory;
Werner Lemberg77c34b82003-05-20 22:06:38 +00001035 FT_Driver_Class clazz;
David Turnerf0df85b2000-06-22 00:17:42 +00001036 FT_Face face = 0;
Antoine Lecac96f69d2002-12-03 00:39:16 +00001037 FT_Error error, error2;
David Turner6a681fa2006-01-27 12:11:22 +00001038 FT_Face_Internal internal = NULL;
David Turnerd2b1f351999-12-16 23:11:37 +00001039
Werner Lemberg3c403e42002-08-06 21:47:40 +00001040
David Turnerf0df85b2000-06-22 00:17:42 +00001041 clazz = driver->clazz;
1042 memory = driver->root.memory;
David Turnerd2b1f351999-12-16 23:11:37 +00001043
Werner Lembergdeb4e982000-06-29 03:14:25 +00001044 /* allocate the face object and perform basic initialization */
David Turnere459d742002-03-22 13:52:37 +00001045 if ( FT_ALLOC( face, clazz->face_object_size ) )
David Turnerd2b1f351999-12-16 23:11:37 +00001046 goto Fail;
1047
David Turnere459d742002-03-22 13:52:37 +00001048 if ( FT_NEW( internal ) )
David Turner54e75742000-11-04 02:52:02 +00001049 goto Fail;
David Turner61d6b2b2001-05-16 17:49:07 +00001050
David Turner54e75742000-11-04 02:52:02 +00001051 face->internal = internal;
1052
1053 face->driver = driver;
1054 face->memory = memory;
1055 face->stream = stream;
Graham Asherce121822002-08-01 15:29:17 +00001056
Graham Asherd53cf1d2002-07-18 15:04:29 +00001057#ifdef FT_CONFIG_OPTION_INCREMENTAL
Werner Lemberg3c403e42002-08-06 21:47:40 +00001058 {
1059 int i;
1060
1061
1062 face->internal->incremental_interface = 0;
1063 for ( i = 0; i < num_params && !face->internal->incremental_interface;
1064 i++ )
1065 if ( params[i].tag == FT_PARAM_TAG_INCREMENTAL )
Werner Lemberg1e1b6df2007-07-07 07:30:40 +00001066 face->internal->incremental_interface =
1067 (FT_Incremental_Interface)params[i].data;
Antoine Lecac96f69d2002-12-03 00:39:16 +00001068 }
Graham Asherd53cf1d2002-07-18 15:04:29 +00001069#endif
David Turnerd2b1f351999-12-16 23:11:37 +00001070
David Turnerf0df85b2000-06-22 00:17:42 +00001071 error = clazz->init_face( stream,
1072 face,
Werner Lemberg68e9f922002-09-27 11:09:23 +00001073 (FT_Int)face_index,
David Turnerf0df85b2000-06-22 00:17:42 +00001074 num_params,
1075 params );
David Turnerd2b1f351999-12-16 23:11:37 +00001076 if ( error )
1077 goto Fail;
1078
David Turnerfed59b72002-07-17 22:51:06 +00001079 /* select Unicode charmap by default */
Antoine Lecac96f69d2002-12-03 00:39:16 +00001080 error2 = find_unicode_charmap( face );
David Turnerc528f6f2002-12-18 22:43:07 +00001081
Werner Lemberg6d798992003-07-01 07:28:55 +00001082 /* if no Unicode charmap can be found, FT_Err_Invalid_CharMap_Handle */
1083 /* is returned. */
Antoine Lecac96f69d2002-12-03 00:39:16 +00001084
Werner Lemberg6d798992003-07-01 07:28:55 +00001085 /* no error should happen, but we want to play safe */
David Turnerc528f6f2002-12-18 22:43:07 +00001086 if ( error2 && error2 != FT_Err_Invalid_CharMap_Handle )
David Turnerfed59b72002-07-17 22:51:06 +00001087 {
Antoine Lecac96f69d2002-12-03 00:39:16 +00001088 error = error2;
1089 goto Fail;
David Turnerfed59b72002-07-17 22:51:06 +00001090 }
1091
David Turnerd2b1f351999-12-16 23:11:37 +00001092 *aface = face;
1093
1094 Fail:
1095 if ( error )
1096 {
Werner Lemberg4338dab2004-01-05 14:41:59 +00001097 destroy_charmaps( face, memory );
David Turnerf0df85b2000-06-22 00:17:42 +00001098 clazz->done_face( face );
Werner Lemberg77c34b82003-05-20 22:06:38 +00001099 FT_FREE( internal );
David Turnere459d742002-03-22 13:52:37 +00001100 FT_FREE( face );
David Turnerd2b1f351999-12-16 23:11:37 +00001101 *aface = 0;
1102 }
1103
1104 return error;
1105 }
1106
1107
Werner Lemberg05c21b82000-07-29 20:38:19 +00001108 /* there's a Mac-specific extended implementation of FT_New_Face() */
Werner Lemberg4d631e42002-05-27 13:02:37 +00001109 /* in src/base/ftmac.c */
Werner Lemberg05c21b82000-07-29 20:38:19 +00001110
Werner Lemberg9ca7a152002-04-30 14:26:49 +00001111#ifndef FT_MACINTOSH
Just van Rossum9e830c52000-07-28 01:12:34 +00001112
Werner Lemberg90a03302000-11-07 17:21:11 +00001113 /* documentation is in freetype.h */
1114
Werner Lembergf814d0f2001-06-27 16:18:10 +00001115 FT_EXPORT_DEF( FT_Error )
1116 FT_New_Face( FT_Library library,
1117 const char* pathname,
1118 FT_Long face_index,
1119 FT_Face *aface )
David Turnerd2b1f351999-12-16 23:11:37 +00001120 {
David Turner37379e22000-03-28 11:22:31 +00001121 FT_Open_Args args;
Werner Lemberg547a2522000-02-16 08:23:58 +00001122
Werner Lemberga929ba92000-06-25 06:47:11 +00001123
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001124 /* test for valid `library' and `aface' delayed to FT_Open_Face() */
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001125 if ( !pathname )
1126 return FT_Err_Invalid_Argument;
1127
David Turnerb08fe2d2002-08-27 20:20:29 +00001128 args.flags = FT_OPEN_PATHNAME;
David Turner4f2c5542000-05-12 10:19:41 +00001129 args.pathname = (char*)pathname;
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001130
David Turnercda32b72000-02-10 16:14:35 +00001131 return FT_Open_Face( library, &args, face_index, aface );
David Turnerd2b1f351999-12-16 23:11:37 +00001132 }
1133
Werner Lemberg9ca7a152002-04-30 14:26:49 +00001134#endif /* !FT_MACINTOSH */
Just van Rossum9e830c52000-07-28 01:12:34 +00001135
Werner Lemberg7880dd62000-01-10 17:19:45 +00001136
Werner Lemberg90a03302000-11-07 17:21:11 +00001137 /* documentation is in freetype.h */
1138
Werner Lembergf814d0f2001-06-27 16:18:10 +00001139 FT_EXPORT_DEF( FT_Error )
1140 FT_New_Memory_Face( FT_Library library,
1141 const FT_Byte* file_base,
1142 FT_Long file_size,
1143 FT_Long face_index,
1144 FT_Face *aface )
David Turnerd2b1f351999-12-16 23:11:37 +00001145 {
David Turner37379e22000-03-28 11:22:31 +00001146 FT_Open_Args args;
Werner Lemberg7880dd62000-01-10 17:19:45 +00001147
Werner Lemberga929ba92000-06-25 06:47:11 +00001148
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001149 /* test for valid `library' and `face' delayed to FT_Open_Face() */
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001150 if ( !file_base )
1151 return FT_Err_Invalid_Argument;
1152
David Turnerb08fe2d2002-08-27 20:20:29 +00001153 args.flags = FT_OPEN_MEMORY;
David Turnercda32b72000-02-10 16:14:35 +00001154 args.memory_base = file_base;
1155 args.memory_size = file_size;
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001156
Werner Lemberg4b680072000-11-07 06:30:29 +00001157 return FT_Open_Face( library, &args, face_index, aface );
David Turnerd2b1f351999-12-16 23:11:37 +00001158 }
1159
Werner Lemberg7880dd62000-01-10 17:19:45 +00001160
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001161#if !defined( FT_MACINTOSH ) && defined( FT_CONFIG_OPTION_MAC_FONTS )
1162
1163 /* The behavior here is very similar to that in base/ftmac.c, but it */
1164 /* is designed to work on non-mac systems, so no mac specific calls. */
1165 /* */
1166 /* We look at the file and determine if it is a mac dfont file or a mac */
1167 /* resource file, or a macbinary file containing a mac resource file. */
1168 /* */
1169 /* Unlike ftmac I'm not going to look at a `FOND'. I don't really see */
1170 /* the point, especially since there may be multiple `FOND' resources. */
1171 /* Instead I'll just look for `sfnt' and `POST' resources, ordered as */
1172 /* they occur in the file. */
1173 /* */
1174 /* Note that multiple `POST' resources do not mean multiple postscript */
1175 /* fonts; they all get jammed together to make what is essentially a */
1176 /* pfb file. */
1177 /* */
1178 /* We aren't interested in `NFNT' or `FONT' bitmap resources. */
1179 /* */
1180 /* As soon as we get an `sfnt' load it into memory and pass it off to */
1181 /* FT_Open_Face. */
1182 /* */
1183 /* If we have a (set of) `POST' resources, massage them into a (memory) */
1184 /* pfb file and pass that to FT_Open_Face. (As with ftmac.c I'm not */
1185 /* going to try to save the kerning info. After all that lives in the */
1186 /* `FOND' which isn't in the file containing the `POST' resources so */
1187 /* we don't really have access to it. */
1188
1189
1190 /* Finalizer for a memory stream; gets called by FT_Done_Face().
1191 It frees the memory it uses. */
1192 /* from ftmac.c */
1193 static void
1194 memory_stream_close( FT_Stream stream )
1195 {
1196 FT_Memory memory = stream->memory;
1197
1198
1199 FT_FREE( stream->base );
1200
1201 stream->size = 0;
1202 stream->base = 0;
1203 stream->close = 0;
1204 }
1205
1206
1207 /* Create a new memory stream from a buffer and a size. */
1208 /* from ftmac.c */
1209 static FT_Error
1210 new_memory_stream( FT_Library library,
1211 FT_Byte* base,
1212 FT_ULong size,
1213 FT_Stream_CloseFunc close,
1214 FT_Stream *astream )
1215 {
1216 FT_Error error;
1217 FT_Memory memory;
1218 FT_Stream stream;
1219
1220
1221 if ( !library )
1222 return FT_Err_Invalid_Library_Handle;
1223
1224 if ( !base )
1225 return FT_Err_Invalid_Argument;
1226
1227 *astream = 0;
1228 memory = library->memory;
1229 if ( FT_NEW( stream ) )
1230 goto Exit;
1231
1232 FT_Stream_OpenMemory( stream, base, size );
1233
1234 stream->close = close;
1235
1236 *astream = stream;
1237
1238 Exit:
1239 return error;
1240 }
1241
1242
1243 /* Create a new FT_Face given a buffer and a driver name. */
1244 /* from ftmac.c */
1245 static FT_Error
1246 open_face_from_buffer( FT_Library library,
1247 FT_Byte* base,
1248 FT_ULong size,
1249 FT_Long face_index,
1250 const char* driver_name,
1251 FT_Face *aface )
1252 {
1253 FT_Open_Args args;
1254 FT_Error error;
Werner Lemberg607dec72007-05-15 06:49:37 +00001255 FT_Stream stream = NULL;
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001256 FT_Memory memory = library->memory;
1257
1258
1259 error = new_memory_stream( library,
1260 base,
1261 size,
1262 memory_stream_close,
1263 &stream );
1264 if ( error )
1265 {
1266 FT_FREE( base );
1267 return error;
1268 }
1269
1270 args.flags = FT_OPEN_STREAM;
1271 args.stream = stream;
1272 if ( driver_name )
1273 {
Werner Lemberg7a024102003-06-18 06:59:57 +00001274 args.flags = args.flags | FT_OPEN_DRIVER;
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001275 args.driver = FT_Get_Module( library, driver_name );
1276 }
1277
1278 error = FT_Open_Face( library, &args, face_index, aface );
1279
1280 if ( error == FT_Err_Ok )
1281 (*aface)->face_flags &= ~FT_FACE_FLAG_EXTERNAL_STREAM;
1282 else
1283 {
1284 FT_Stream_Close( stream );
1285 FT_FREE( stream );
1286 }
1287
1288 return error;
1289 }
1290
1291
1292 /* The resource header says we've got resource_cnt `POST' (type1) */
1293 /* resources in this file. They all need to be coalesced into */
1294 /* one lump which gets passed on to the type1 driver. */
1295 /* Here can be only one PostScript font in a file so face_index */
1296 /* must be 0 (or -1). */
1297 /* */
1298 static FT_Error
1299 Mac_Read_POST_Resource( FT_Library library,
1300 FT_Stream stream,
Werner Lemberg75435332004-02-25 12:58:54 +00001301 FT_Long *offsets,
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001302 FT_Long resource_cnt,
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001303 FT_Long face_index,
1304 FT_Face *aface )
1305 {
1306 FT_Error error = FT_Err_Cannot_Open_Resource;
1307 FT_Memory memory = library->memory;
1308 FT_Byte* pfb_data;
Werner Lembergdc8ad542003-12-09 02:12:14 +00001309 int i, type, flags;
1310 FT_Long len;
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001311 FT_Long pfb_len, pfb_pos, pfb_lenpos;
Werner Lembergdc8ad542003-12-09 02:12:14 +00001312 FT_Long rlen, temp;
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001313
1314
1315 if ( face_index == -1 )
1316 face_index = 0;
1317 if ( face_index != 0 )
Werner Lemberg77c34b82003-05-20 22:06:38 +00001318 return error;
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001319
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001320 /* Find the length of all the POST resources, concatenated. Assume */
1321 /* worst case (each resource in its own section). */
1322 pfb_len = 0;
1323 for ( i = 0; i < resource_cnt; ++i )
1324 {
1325 error = FT_Stream_Seek( stream, offsets[i] );
1326 if ( error )
1327 goto Exit;
1328 if ( FT_READ_LONG( temp ) )
1329 goto Exit;
1330 pfb_len += temp + 6;
1331 }
1332
1333 if ( FT_ALLOC( pfb_data, (FT_Long)pfb_len + 2 ) )
1334 goto Exit;
1335
David Turnerc313c502003-09-11 19:51:54 +00001336 pfb_data[0] = 0x80;
1337 pfb_data[1] = 1; /* Ascii section */
1338 pfb_data[2] = 0; /* 4-byte length, fill in later */
1339 pfb_data[3] = 0;
1340 pfb_data[4] = 0;
1341 pfb_data[5] = 0;
Suzuki, Toshiya (鈴木俊哉)a2295402006-04-30 04:46:17 +00001342 pfb_pos = 6;
David Turnere2d12842003-09-21 17:15:55 +00001343 pfb_lenpos = 2;
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001344
1345 len = 0;
1346 type = 1;
1347 for ( i = 0; i < resource_cnt; ++i )
1348 {
1349 error = FT_Stream_Seek( stream, offsets[i] );
1350 if ( error )
1351 goto Exit2;
1352 if ( FT_READ_LONG( rlen ) )
1353 goto Exit;
1354 if ( FT_READ_USHORT( flags ) )
1355 goto Exit;
1356 rlen -= 2; /* the flags are part of the resource */
1357 if ( ( flags >> 8 ) == type )
1358 len += rlen;
1359 else
1360 {
David Turnerc313c502003-09-11 19:51:54 +00001361 pfb_data[pfb_lenpos ] = (FT_Byte)( len );
1362 pfb_data[pfb_lenpos + 1] = (FT_Byte)( len >> 8 );
1363 pfb_data[pfb_lenpos + 2] = (FT_Byte)( len >> 16 );
1364 pfb_data[pfb_lenpos + 3] = (FT_Byte)( len >> 24 );
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001365
1366 if ( ( flags >> 8 ) == 5 ) /* End of font mark */
1367 break;
1368
1369 pfb_data[pfb_pos++] = 0x80;
1370
1371 type = flags >> 8;
1372 len = rlen;
1373
Werner Lemberg013efd12003-09-17 05:26:33 +00001374 pfb_data[pfb_pos++] = (FT_Byte)type;
Suzuki, Toshiya (鈴木俊哉)a2295402006-04-30 04:46:17 +00001375 pfb_lenpos = pfb_pos;
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001376 pfb_data[pfb_pos++] = 0; /* 4-byte length, fill in later */
1377 pfb_data[pfb_pos++] = 0;
1378 pfb_data[pfb_pos++] = 0;
1379 pfb_data[pfb_pos++] = 0;
1380 }
1381
1382 error = FT_Stream_Read( stream, (FT_Byte *)pfb_data + pfb_pos, rlen );
1383 pfb_pos += rlen;
1384 }
1385
1386 pfb_data[pfb_pos++] = 0x80;
1387 pfb_data[pfb_pos++] = 3;
1388
David Turnerc313c502003-09-11 19:51:54 +00001389 pfb_data[pfb_lenpos ] = (FT_Byte)( len );
1390 pfb_data[pfb_lenpos + 1] = (FT_Byte)( len >> 8 );
1391 pfb_data[pfb_lenpos + 2] = (FT_Byte)( len >> 16 );
1392 pfb_data[pfb_lenpos + 3] = (FT_Byte)( len >> 24 );
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001393
1394 return open_face_from_buffer( library,
1395 pfb_data,
1396 pfb_pos,
1397 face_index,
1398 "type1",
1399 aface );
1400
1401 Exit2:
1402 FT_FREE( pfb_data );
1403
1404 Exit:
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001405 return error;
1406 }
1407
1408
1409 /* The resource header says we've got resource_cnt `sfnt' */
1410 /* (TrueType/OpenType) resources in this file. Look through */
1411 /* them for the one indicated by face_index, load it into mem, */
1412 /* pass it on the the truetype driver and return it. */
1413 /* */
1414 static FT_Error
1415 Mac_Read_sfnt_Resource( FT_Library library,
1416 FT_Stream stream,
Werner Lemberg75435332004-02-25 12:58:54 +00001417 FT_Long *offsets,
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001418 FT_Long resource_cnt,
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001419 FT_Long face_index,
1420 FT_Face *aface )
1421 {
1422 FT_Memory memory = library->memory;
1423 FT_Byte* sfnt_data;
1424 FT_Error error;
Werner Lemberg75435332004-02-25 12:58:54 +00001425 FT_Long flag_offset;
Werner Lembergdc8ad542003-12-09 02:12:14 +00001426 FT_Long rlen;
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001427 int is_cff;
Suzuki, Toshiya (鈴木俊哉)7a7d4032006-12-15 14:47:42 +00001428 FT_Long face_index_in_resource = 0;
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001429
1430
1431 if ( face_index == -1 )
1432 face_index = 0;
1433 if ( face_index >= resource_cnt )
1434 return FT_Err_Cannot_Open_Resource;
1435
Werner Lemberg75435332004-02-25 12:58:54 +00001436 flag_offset = offsets[face_index];
1437 error = FT_Stream_Seek( stream, flag_offset );
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001438 if ( error )
1439 goto Exit;
1440
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001441 if ( FT_READ_LONG( rlen ) )
1442 goto Exit;
1443 if ( rlen == -1 )
1444 return FT_Err_Cannot_Open_Resource;
1445
1446 if ( FT_ALLOC( sfnt_data, (FT_Long)rlen ) )
1447 return error;
1448 error = FT_Stream_Read( stream, (FT_Byte *)sfnt_data, rlen );
1449 if ( error )
1450 goto Exit;
1451
1452 is_cff = rlen > 4 && sfnt_data[0] == 'O' &&
1453 sfnt_data[1] == 'T' &&
1454 sfnt_data[2] == 'T' &&
1455 sfnt_data[3] == 'O';
1456
1457 error = open_face_from_buffer( library,
1458 sfnt_data,
1459 rlen,
Suzuki, Toshiya (鈴木俊哉)7a7d4032006-12-15 14:47:42 +00001460 face_index_in_resource,
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001461 is_cff ? "cff" : "truetype",
1462 aface );
1463
1464 Exit:
1465 return error;
1466 }
1467
1468
1469 /* Check for a valid resource fork header, or a valid dfont */
1470 /* header. In a resource fork the first 16 bytes are repeated */
1471 /* at the location specified by bytes 4-7. In a dfont bytes */
1472 /* 4-7 point to 16 bytes of zeroes instead. */
1473 /* */
1474 static FT_Error
1475 IsMacResource( FT_Library library,
1476 FT_Stream stream,
1477 FT_Long resource_offset,
1478 FT_Long face_index,
1479 FT_Face *aface )
1480 {
Werner Lemberg75435332004-02-25 12:58:54 +00001481 FT_Memory memory = library->memory;
1482 FT_Error error;
1483 FT_Long map_offset, rdara_pos;
1484 FT_Long *data_offsets;
1485 FT_Long count;
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001486
1487
Werner Lemberg75435332004-02-25 12:58:54 +00001488 error = FT_Raccess_Get_HeaderInfo( library, stream, resource_offset,
1489 &map_offset, &rdara_pos );
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001490 if ( error )
Werner Lemberg75435332004-02-25 12:58:54 +00001491 return error;
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001492
Werner Lemberg75435332004-02-25 12:58:54 +00001493 error = FT_Raccess_Get_DataOffsets( library, stream,
1494 map_offset, rdara_pos,
1495 FT_MAKE_TAG( 'P', 'O', 'S', 'T' ),
1496 &data_offsets, &count );
1497 if ( !error )
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001498 {
Werner Lemberg75435332004-02-25 12:58:54 +00001499 error = Mac_Read_POST_Resource( library, stream, data_offsets, count,
1500 face_index, aface );
1501 FT_FREE( data_offsets );
Werner Lemberg0fd08bd2006-12-16 02:57:46 +00001502 /* POST exists in an LWFN providing a single face */
Werner Lemberg17432b52007-01-12 09:28:44 +00001503 if ( !error )
David Turner7a3c5642007-01-11 15:09:01 +00001504 (*aface)->num_faces = 1;
Werner Lemberg75435332004-02-25 12:58:54 +00001505 return error;
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001506 }
1507
Werner Lemberg75435332004-02-25 12:58:54 +00001508 error = FT_Raccess_Get_DataOffsets( library, stream,
1509 map_offset, rdara_pos,
1510 FT_MAKE_TAG( 's', 'f', 'n', 't' ),
1511 &data_offsets, &count );
1512 if ( !error )
1513 {
Werner Lemberg0fd08bd2006-12-16 02:57:46 +00001514 FT_Long face_index_internal = face_index % count;
Suzuki, Toshiya (鈴木俊哉)7a7d4032006-12-15 14:47:42 +00001515
1516
Werner Lemberg75435332004-02-25 12:58:54 +00001517 error = Mac_Read_sfnt_Resource( library, stream, data_offsets, count,
Suzuki, Toshiya (鈴木俊哉)7a7d4032006-12-15 14:47:42 +00001518 face_index_internal, aface );
Werner Lemberg75435332004-02-25 12:58:54 +00001519 FT_FREE( data_offsets );
Werner Lemberg17432b52007-01-12 09:28:44 +00001520 if ( !error )
David Turner7a3c5642007-01-11 15:09:01 +00001521 (*aface)->num_faces = count;
Werner Lemberg75435332004-02-25 12:58:54 +00001522 }
1523
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001524 return error;
1525 }
1526
1527
1528 /* Check for a valid macbinary header, and if we find one */
1529 /* check that the (flattened) resource fork in it is valid. */
1530 /* */
1531 static FT_Error
1532 IsMacBinary( FT_Library library,
1533 FT_Stream stream,
1534 FT_Long face_index,
1535 FT_Face *aface )
1536 {
1537 unsigned char header[128];
1538 FT_Error error;
1539 FT_Long dlen, offset;
1540
1541
Suzuki, Toshiya (鈴木俊哉)86c0f902007-11-20 14:00:17 +00001542 if ( NULL == stream )
1543 return FT_Err_Invalid_Stream_Operation;
1544
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001545 error = FT_Stream_Seek( stream, 0 );
1546 if ( error )
1547 goto Exit;
1548
1549 error = FT_Stream_Read( stream, (FT_Byte*)header, 128 );
1550 if ( error )
1551 goto Exit;
1552
1553 if ( header[ 0] != 0 ||
1554 header[74] != 0 ||
1555 header[82] != 0 ||
1556 header[ 1] == 0 ||
1557 header[ 1] > 33 ||
1558 header[63] != 0 ||
1559 header[2 + header[1]] != 0 )
1560 return FT_Err_Unknown_File_Format;
1561
1562 dlen = ( header[0x53] << 24 ) |
1563 ( header[0x54] << 16 ) |
1564 ( header[0x55] << 8 ) |
1565 header[0x56];
1566#if 0
1567 rlen = ( header[0x57] << 24 ) |
1568 ( header[0x58] << 16 ) |
1569 ( header[0x59] << 8 ) |
1570 header[0x5a];
1571#endif /* 0 */
1572 offset = 128 + ( ( dlen + 127 ) & ~127 );
1573
1574 return IsMacResource( library, stream, offset, face_index, aface );
1575
1576 Exit:
1577 return error;
1578 }
1579
1580
Werner Lemberg75435332004-02-25 12:58:54 +00001581 static FT_Error
1582 load_face_in_embedded_rfork( FT_Library library,
1583 FT_Stream stream,
1584 FT_Long face_index,
1585 FT_Face *aface,
1586 const FT_Open_Args *args )
1587 {
1588
1589#undef FT_COMPONENT
1590#define FT_COMPONENT trace_raccess
1591
1592 FT_Memory memory = library->memory;
1593 FT_Error error = FT_Err_Unknown_File_Format;
1594 int i;
1595
1596 char * file_names[FT_RACCESS_N_RULES];
1597 FT_Long offsets[FT_RACCESS_N_RULES];
1598 FT_Error errors[FT_RACCESS_N_RULES];
1599
1600 FT_Open_Args args2;
1601 FT_Stream stream2;
1602
1603
1604 FT_Raccess_Guess( library, stream,
1605 args->pathname, file_names, offsets, errors );
1606
1607 for ( i = 0; i < FT_RACCESS_N_RULES; i++ )
1608 {
1609 if ( errors[i] )
1610 {
1611 FT_TRACE3(( "Error[%d] has occurred in rule %d\n", errors[i], i ));
1612 continue;
1613 }
1614
1615 args2.flags = FT_OPEN_PATHNAME;
1616 args2.pathname = file_names[i] ? file_names[i] : args->pathname;
1617
1618 FT_TRACE3(( "Try rule %d: %s (offset=%d) ...",
1619 i, args2.pathname, offsets[i] ));
1620
1621 error = FT_Stream_New( library, &args2, &stream2 );
1622 if ( error )
1623 {
1624 FT_TRACE3(( "failed\n" ));
1625 continue;
1626 }
1627
1628 error = IsMacResource( library, stream2, offsets[i],
1629 face_index, aface );
Suzuki, Toshiya (鈴木俊哉)de0a96c2006-05-19 23:16:12 +00001630 FT_Stream_Free( stream2, 0 );
Werner Lemberg75435332004-02-25 12:58:54 +00001631
1632 FT_TRACE3(( "%s\n", error ? "failed": "successful" ));
1633
1634 if ( !error )
1635 break;
1636 }
1637
1638 for (i = 0; i < FT_RACCESS_N_RULES; i++)
1639 {
1640 if ( file_names[i] )
1641 FT_FREE( file_names[i] );
1642 }
1643
1644 /* Caller (load_mac_face) requires FT_Err_Unknown_File_Format. */
1645 if ( error )
1646 error = FT_Err_Unknown_File_Format;
1647
1648 return error;
1649
1650#undef FT_COMPONENT
1651#define FT_COMPONENT trace_objs
1652
1653 }
1654
1655
1656 /* Check for some macintosh formats. */
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001657 /* Is this a macbinary file? If so look at the resource fork. */
1658 /* Is this a mac dfont file? */
1659 /* Is this an old style resource fork? (in data) */
Werner Lemberg75435332004-02-25 12:58:54 +00001660 /* Else call load_face_in_embedded_rfork to try extra rules */
1661 /* (defined in `ftrfork.c'). */
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001662 /* */
1663 static FT_Error
1664 load_mac_face( FT_Library library,
1665 FT_Stream stream,
1666 FT_Long face_index,
1667 FT_Face *aface,
1668 const FT_Open_Args *args )
1669 {
1670 FT_Error error;
1671 FT_UNUSED( args );
1672
1673
1674 error = IsMacBinary( library, stream, face_index, aface );
1675 if ( FT_ERROR_BASE( error ) == FT_Err_Unknown_File_Format )
Werner Lemberg75435332004-02-25 12:58:54 +00001676 {
1677
1678#undef FT_COMPONENT
1679#define FT_COMPONENT trace_raccess
1680
1681 FT_TRACE3(( "Try as dfont: %s ...", args->pathname ));
1682
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001683 error = IsMacResource( library, stream, 0, face_index, aface );
1684
Werner Lemberg75435332004-02-25 12:58:54 +00001685 FT_TRACE3(( "%s\n", error ? "failed" : "successful" ));
David Turnere2d12842003-09-21 17:15:55 +00001686
Werner Lemberg75435332004-02-25 12:58:54 +00001687#undef FT_COMPONENT
1688#define FT_COMPONENT trace_objs
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001689
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001690 }
1691
Werner Lemberg75435332004-02-25 12:58:54 +00001692 if ( ( FT_ERROR_BASE( error ) == FT_Err_Unknown_File_Format ||
1693 FT_ERROR_BASE( error ) == FT_Err_Invalid_Stream_Operation ) &&
1694 ( args->flags & FT_OPEN_PATHNAME ) )
1695 error = load_face_in_embedded_rfork( library, stream,
1696 face_index, aface, args );
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001697 return error;
1698 }
1699
1700#endif /* !FT_MACINTOSH && FT_CONFIG_OPTION_MAC_FONTS */
1701
1702
Werner Lemberg90a03302000-11-07 17:21:11 +00001703 /* documentation is in freetype.h */
1704
Werner Lembergf814d0f2001-06-27 16:18:10 +00001705 FT_EXPORT_DEF( FT_Error )
Werner Lembergc4c373c2002-10-07 09:15:20 +00001706 FT_Open_Face( FT_Library library,
1707 const FT_Open_Args* args,
1708 FT_Long face_index,
1709 FT_Face *aface )
David Turnerd2b1f351999-12-16 23:11:37 +00001710 {
1711 FT_Error error;
1712 FT_Driver driver;
1713 FT_Memory memory;
David Turnercda32b72000-02-10 16:14:35 +00001714 FT_Stream stream;
David Turnerd2b1f351999-12-16 23:11:37 +00001715 FT_Face face = 0;
1716 FT_ListNode node = 0;
David Turnerc5cdf8b2000-07-27 21:40:22 +00001717 FT_Bool external_stream;
Werner Lembergc32e83f2008-04-01 06:07:37 +00001718 FT_Module* cur;
1719 FT_Module* limit;
Werner Lemberg547a2522000-02-16 08:23:58 +00001720
Werner Lemberg58b17f92000-07-27 23:29:08 +00001721
Werner Lembergf9b03752000-09-11 22:50:13 +00001722 /* test for valid `library' delayed to */
Werner Lemberg75435332004-02-25 12:58:54 +00001723 /* FT_Stream_New() */
David Turnerd2b1f351999-12-16 23:11:37 +00001724
Werner Lembergce235ea2005-05-17 20:35:23 +00001725 if ( ( !aface && face_index >= 0 ) || !args )
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001726 return FT_Err_Invalid_Argument;
1727
David Turnerb08fe2d2002-08-27 20:20:29 +00001728 external_stream = FT_BOOL( ( args->flags & FT_OPEN_STREAM ) &&
Werner Lemberg8eb03532001-06-19 23:03:41 +00001729 args->stream );
David Turnerc5cdf8b2000-07-27 21:40:22 +00001730
David Turnercda32b72000-02-10 16:14:35 +00001731 /* create input stream */
Werner Lemberg75435332004-02-25 12:58:54 +00001732 error = FT_Stream_New( library, args, &stream );
Werner Lembergdeb4e982000-06-29 03:14:25 +00001733 if ( error )
Suzuki, Toshiya (鈴木俊哉)86c0f902007-11-20 14:00:17 +00001734 goto Fail3;
David Turnercda32b72000-02-10 16:14:35 +00001735
David Turnerd2b1f351999-12-16 23:11:37 +00001736 memory = library->memory;
1737
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001738 /* If the font driver is specified in the `args' structure, use */
Werner Lembergdeb4e982000-06-29 03:14:25 +00001739 /* it. Otherwise, we scan the list of registered drivers. */
David Turnerb08fe2d2002-08-27 20:20:29 +00001740 if ( ( args->flags & FT_OPEN_DRIVER ) && args->driver )
David Turner7663f222000-02-13 13:37:38 +00001741 {
Werner Lemberga929ba92000-06-25 06:47:11 +00001742 driver = FT_DRIVER( args->driver );
David Turnerf0df85b2000-06-22 00:17:42 +00001743
1744 /* not all modules are drivers, so check... */
Werner Lemberga929ba92000-06-25 06:47:11 +00001745 if ( FT_MODULE_IS_DRIVER( driver ) )
David Turner7663f222000-02-13 13:37:38 +00001746 {
Werner Lemberg3c403e42002-08-06 21:47:40 +00001747 FT_Int num_params = 0;
1748 FT_Parameter* params = 0;
1749
Werner Lemberga929ba92000-06-25 06:47:11 +00001750
David Turnerb08fe2d2002-08-27 20:20:29 +00001751 if ( args->flags & FT_OPEN_PARAMS )
David Turner4f2c5542000-05-12 10:19:41 +00001752 {
1753 num_params = args->num_params;
1754 params = args->params;
1755 }
David Turnere49ab252000-05-16 23:44:38 +00001756
David Turner4f2c5542000-05-12 10:19:41 +00001757 error = open_face( driver, stream, face_index,
1758 num_params, params, &face );
Werner Lemberg547a2522000-02-16 08:23:58 +00001759 if ( !error )
1760 goto Success;
David Turner7663f222000-02-13 13:37:38 +00001761 }
1762 else
1763 error = FT_Err_Invalid_Handle;
1764
Werner Lemberg75435332004-02-25 12:58:54 +00001765 FT_Stream_Free( stream, external_stream );
David Turner7663f222000-02-13 13:37:38 +00001766 goto Fail;
1767 }
Just van Rossum1e5754f2000-03-02 10:52:57 +00001768 else
David Turnerd2b1f351999-12-16 23:11:37 +00001769 {
1770 /* check each font driver for an appropriate format */
Werner Lembergc32e83f2008-04-01 06:07:37 +00001771 cur = library->modules;
1772 limit = cur + library->num_modules;
David Turnerd2b1f351999-12-16 23:11:37 +00001773
Werner Lemberga929ba92000-06-25 06:47:11 +00001774
David Turnerd2b1f351999-12-16 23:11:37 +00001775 for ( ; cur < limit; cur++ )
1776 {
David Turnerf0df85b2000-06-22 00:17:42 +00001777 /* not all modules are font drivers, so check... */
Werner Lemberga929ba92000-06-25 06:47:11 +00001778 if ( FT_MODULE_IS_DRIVER( cur[0] ) )
David Turnerd2b1f351999-12-16 23:11:37 +00001779 {
David Turner4f2c5542000-05-12 10:19:41 +00001780 FT_Int num_params = 0;
1781 FT_Parameter* params = 0;
David Turnere49ab252000-05-16 23:44:38 +00001782
Werner Lemberg3c403e42002-08-06 21:47:40 +00001783
Werner Lemberga929ba92000-06-25 06:47:11 +00001784 driver = FT_DRIVER( cur[0] );
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001785
David Turnerb08fe2d2002-08-27 20:20:29 +00001786 if ( args->flags & FT_OPEN_PARAMS )
David Turner4f2c5542000-05-12 10:19:41 +00001787 {
1788 num_params = args->num_params;
1789 params = args->params;
1790 }
David Turnere49ab252000-05-16 23:44:38 +00001791
Graham Asherd53cf1d2002-07-18 15:04:29 +00001792 error = open_face( driver, stream, face_index,
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001793 num_params, params, &face );
David Turnerd2b1f351999-12-16 23:11:37 +00001794 if ( !error )
1795 goto Success;
1796
Werner Lemberg79860702001-06-08 21:17:29 +00001797 if ( FT_ERROR_BASE( error ) != FT_Err_Unknown_File_Format )
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001798 goto Fail3;
David Turnerd2b1f351999-12-16 23:11:37 +00001799 }
1800 }
1801
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001802 Fail3:
1803 /* If we are on the mac, and we get an FT_Err_Invalid_Stream_Operation */
1804 /* it may be because we have an empty data fork, so we need to check */
1805 /* the resource fork. */
Suzuki, Toshiya (鈴木俊哉)86c0f902007-11-20 14:00:17 +00001806 if ( FT_ERROR_BASE( error ) != FT_Err_Cannot_Open_Stream &&
1807 FT_ERROR_BASE( error ) != FT_Err_Unknown_File_Format &&
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001808 FT_ERROR_BASE( error ) != FT_Err_Invalid_Stream_Operation )
1809 goto Fail2;
1810
Werner Lembergdc8ad542003-12-09 02:12:14 +00001811#if !defined( FT_MACINTOSH ) && defined( FT_CONFIG_OPTION_MAC_FONTS )
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001812 error = load_mac_face( library, stream, face_index, aface, args );
1813 if ( !error )
1814 {
1815 /* We don't want to go to Success here. We've already done that. */
1816 /* On the other hand, if we succeeded we still need to close this */
1817 /* stream (we opened a different stream which extracted the */
1818 /* interesting information out of this stream here. That stream */
1819 /* will still be open and the face will point to it). */
Werner Lemberg75435332004-02-25 12:58:54 +00001820 FT_Stream_Free( stream, external_stream );
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001821 return error;
1822 }
1823
1824 if ( FT_ERROR_BASE( error ) != FT_Err_Unknown_File_Format )
1825 goto Fail2;
Werner Lembergdc8ad542003-12-09 02:12:14 +00001826#endif /* !FT_MACINTOSH && FT_CONFIG_OPTION_MAC_FONTS */
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001827
David Turnerd2b1f351999-12-16 23:11:37 +00001828 /* no driver is able to handle this format */
1829 error = FT_Err_Unknown_File_Format;
David Turnerebe85f52001-05-11 14:25:57 +00001830
1831 Fail2:
Werner Lemberg75435332004-02-25 12:58:54 +00001832 FT_Stream_Free( stream, external_stream );
David Turnercda32b72000-02-10 16:14:35 +00001833 goto Fail;
David Turnerd2b1f351999-12-16 23:11:37 +00001834 }
1835
1836 Success:
Werner Lembergf9b03752000-09-11 22:50:13 +00001837 FT_TRACE4(( "FT_Open_Face: New face object, adding to list\n" ));
David Turnerd2b1f351999-12-16 23:11:37 +00001838
Werner Lembergdeb4e982000-06-29 03:14:25 +00001839 /* set the FT_FACE_FLAG_EXTERNAL_STREAM bit for FT_Done_Face */
David Turnerc5cdf8b2000-07-27 21:40:22 +00001840 if ( external_stream )
David Turnerf0df85b2000-06-22 00:17:42 +00001841 face->face_flags |= FT_FACE_FLAG_EXTERNAL_STREAM;
1842
Werner Lemberg547a2522000-02-16 08:23:58 +00001843 /* add the face object to its driver's list */
David Turnere459d742002-03-22 13:52:37 +00001844 if ( FT_NEW( node ) )
David Turnerd2b1f351999-12-16 23:11:37 +00001845 goto Fail;
1846
1847 node->data = face;
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001848 /* don't assume driver is the same as face->driver, so use */
1849 /* face->driver instead. */
Just van Rossum7eef5362000-03-05 16:07:58 +00001850 FT_List_Add( &face->driver->faces_list, node );
David Turnerd2b1f351999-12-16 23:11:37 +00001851
Werner Lemberg547a2522000-02-16 08:23:58 +00001852 /* now allocate a glyph slot object for the face */
Werner Lembergb9ee7372005-05-20 21:52:19 +00001853 FT_TRACE4(( "FT_Open_Face: Creating glyph slot\n" ));
David Turnerd2b1f351999-12-16 23:11:37 +00001854
David Turner92f30c82005-10-17 21:17:20 +00001855 if ( face_index >= 0 )
David Turnerd2b1f351999-12-16 23:11:37 +00001856 {
David Turner92f30c82005-10-17 21:17:20 +00001857 error = FT_New_GlyphSlot( face, NULL );
Werner Lembergdeb4e982000-06-29 03:14:25 +00001858 if ( error )
1859 goto Fail;
1860
David Turner92f30c82005-10-17 21:17:20 +00001861 /* finally, allocate a size object for the face */
1862 {
1863 FT_Size size;
1864
1865
1866 FT_TRACE4(( "FT_Open_Face: Creating size object\n" ));
1867
1868 error = FT_New_Size( face, &size );
1869 if ( error )
1870 goto Fail;
1871
1872 face->size = size;
1873 }
David Turnerd2b1f351999-12-16 23:11:37 +00001874 }
Werner Lemberg7880dd62000-01-10 17:19:45 +00001875
Wu, Chia-I (吳佳一)e5ff0592006-01-15 06:00:49 +00001876 /* some checks */
1877
1878 if ( FT_IS_SCALABLE( face ) )
1879 {
1880 if ( face->height < 0 )
Werner Lembergbe3c9812006-01-27 14:16:16 +00001881 face->height = (FT_Short)-face->height;
Wu, Chia-I (吳佳一)e5ff0592006-01-15 06:00:49 +00001882
1883 if ( !FT_HAS_VERTICAL( face ) )
Werner Lembergbe3c9812006-01-27 14:16:16 +00001884 face->max_advance_height = (FT_Short)face->height;
Wu, Chia-I (吳佳一)e5ff0592006-01-15 06:00:49 +00001885 }
1886
1887 if ( FT_HAS_FIXED_SIZES( face ) )
1888 {
Werner Lemberg1723dcc2006-01-15 07:30:32 +00001889 FT_Int i;
Wu, Chia-I (吳佳一)e5ff0592006-01-15 06:00:49 +00001890
David Turnercda2d952006-02-16 22:45:31 +00001891
Wu, Chia-I (吳佳一)e5ff0592006-01-15 06:00:49 +00001892 for ( i = 0; i < face->num_fixed_sizes; i++ )
1893 {
1894 FT_Bitmap_Size* bsize = face->available_sizes + i;
1895
1896
1897 if ( bsize->height < 0 )
Werner Lembergbe3c9812006-01-27 14:16:16 +00001898 bsize->height = (FT_Short)-bsize->height;
Wu, Chia-I (吳佳一)e5ff0592006-01-15 06:00:49 +00001899 if ( bsize->x_ppem < 0 )
Werner Lembergbe3c9812006-01-27 14:16:16 +00001900 bsize->x_ppem = (FT_Short)-bsize->x_ppem;
Wu, Chia-I (吳佳一)e5ff0592006-01-15 06:00:49 +00001901 if ( bsize->y_ppem < 0 )
1902 bsize->y_ppem = -bsize->y_ppem;
1903 }
1904 }
1905
David Turner54e75742000-11-04 02:52:02 +00001906 /* initialize internal face data */
1907 {
1908 FT_Face_Internal internal = face->internal;
David Turner61d6b2b2001-05-16 17:49:07 +00001909
David Turner37379e22000-03-28 11:22:31 +00001910
David Turner54e75742000-11-04 02:52:02 +00001911 internal->transform_matrix.xx = 0x10000L;
1912 internal->transform_matrix.xy = 0;
1913 internal->transform_matrix.yx = 0;
1914 internal->transform_matrix.yy = 0x10000L;
David Turner61d6b2b2001-05-16 17:49:07 +00001915
David Turner54e75742000-11-04 02:52:02 +00001916 internal->transform_delta.x = 0;
1917 internal->transform_delta.y = 0;
1918 }
David Turner37379e22000-03-28 11:22:31 +00001919
Werner Lembergce235ea2005-05-17 20:35:23 +00001920 if ( aface )
1921 *aface = face;
Werner Lembergb2d02532005-11-04 06:58:49 +00001922 else
1923 FT_Done_Face( face );
1924
David Turnerd2b1f351999-12-16 23:11:37 +00001925 goto Exit;
1926
1927 Fail:
1928 FT_Done_Face( face );
1929
David Turnerd2b1f351999-12-16 23:11:37 +00001930 Exit:
1931 FT_TRACE4(( "FT_Open_Face: Return %d\n", error ));
Werner Lembergdeb4e982000-06-29 03:14:25 +00001932
David Turnerd2b1f351999-12-16 23:11:37 +00001933 return error;
1934 }
1935
1936
Werner Lemberg90a03302000-11-07 17:21:11 +00001937 /* documentation is in freetype.h */
1938
Werner Lembergf814d0f2001-06-27 16:18:10 +00001939 FT_EXPORT_DEF( FT_Error )
1940 FT_Attach_File( FT_Face face,
1941 const char* filepathname )
David Turner7663f222000-02-13 13:37:38 +00001942 {
David Turner37379e22000-03-28 11:22:31 +00001943 FT_Open_Args open;
David Turner7663f222000-02-13 13:37:38 +00001944
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001945
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001946 /* test for valid `face' delayed to FT_Attach_Stream() */
1947
1948 if ( !filepathname )
1949 return FT_Err_Invalid_Argument;
1950
Werner Lembergb8fdcd62004-08-03 03:28:11 +00001951 open.stream = NULL;
David Turnerb08fe2d2002-08-27 20:20:29 +00001952 open.flags = FT_OPEN_PATHNAME;
David Turner4f2c5542000-05-12 10:19:41 +00001953 open.pathname = (char*)filepathname;
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001954
David Turner7663f222000-02-13 13:37:38 +00001955 return FT_Attach_Stream( face, &open );
1956 }
Werner Lemberg547a2522000-02-16 08:23:58 +00001957
David Turnere49ab252000-05-16 23:44:38 +00001958
Werner Lemberg90a03302000-11-07 17:21:11 +00001959 /* documentation is in freetype.h */
1960
Werner Lembergf814d0f2001-06-27 16:18:10 +00001961 FT_EXPORT_DEF( FT_Error )
1962 FT_Attach_Stream( FT_Face face,
1963 FT_Open_Args* parameters )
David Turner7663f222000-02-13 13:37:38 +00001964 {
1965 FT_Stream stream;
1966 FT_Error error;
1967 FT_Driver driver;
David Turnere49ab252000-05-16 23:44:38 +00001968
David Turneref3c1262002-03-14 09:22:48 +00001969 FT_Driver_Class clazz;
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001970
Werner Lemberga929ba92000-06-25 06:47:11 +00001971
Werner Lemberg75435332004-02-25 12:58:54 +00001972 /* test for valid `parameters' delayed to FT_Stream_New() */
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001973
1974 if ( !face )
1975 return FT_Err_Invalid_Face_Handle;
David Turnere49ab252000-05-16 23:44:38 +00001976
David Turner7663f222000-02-13 13:37:38 +00001977 driver = face->driver;
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001978 if ( !driver )
1979 return FT_Err_Invalid_Driver_Handle;
1980
Werner Lemberg75435332004-02-25 12:58:54 +00001981 error = FT_Stream_New( driver->root.library, parameters, &stream );
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001982 if ( error )
1983 goto Exit;
David Turnere49ab252000-05-16 23:44:38 +00001984
David Turner7663f222000-02-13 13:37:38 +00001985 /* we implement FT_Attach_Stream in each driver through the */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001986 /* `attach_file' interface */
1987
David Turner7663f222000-02-13 13:37:38 +00001988 error = FT_Err_Unimplemented_Feature;
David Turnerf0df85b2000-06-22 00:17:42 +00001989 clazz = driver->clazz;
Werner Lemberga929ba92000-06-25 06:47:11 +00001990 if ( clazz->attach_file )
David Turnerf0df85b2000-06-22 00:17:42 +00001991 error = clazz->attach_file( face, stream );
David Turnere49ab252000-05-16 23:44:38 +00001992
David Turner7663f222000-02-13 13:37:38 +00001993 /* close the attached stream */
Werner Lemberg75435332004-02-25 12:58:54 +00001994 FT_Stream_Free( stream,
Werner Lemberg58b17f92000-07-27 23:29:08 +00001995 (FT_Bool)( parameters->stream &&
David Turnerb08fe2d2002-08-27 20:20:29 +00001996 ( parameters->flags & FT_OPEN_STREAM ) ) );
David Turnere49ab252000-05-16 23:44:38 +00001997
David Turner7663f222000-02-13 13:37:38 +00001998 Exit:
1999 return error;
2000 }
2001
2002
Werner Lemberg90a03302000-11-07 17:21:11 +00002003 /* documentation is in freetype.h */
2004
Werner Lembergf814d0f2001-06-27 16:18:10 +00002005 FT_EXPORT_DEF( FT_Error )
2006 FT_Done_Face( FT_Face face )
David Turnerd2b1f351999-12-16 23:11:37 +00002007 {
Werner Lemberga929ba92000-06-25 06:47:11 +00002008 FT_Error error;
2009 FT_Driver driver;
2010 FT_Memory memory;
2011 FT_ListNode node;
2012
David Turnerd2b1f351999-12-16 23:11:37 +00002013
David Turnerf0df85b2000-06-22 00:17:42 +00002014 error = FT_Err_Invalid_Face_Handle;
2015 if ( face && face->driver )
David Turnerd2b1f351999-12-16 23:11:37 +00002016 {
David Turnerf0df85b2000-06-22 00:17:42 +00002017 driver = face->driver;
2018 memory = driver->root.memory;
Werner Lembergdeb4e982000-06-29 03:14:25 +00002019
David Turnerf0df85b2000-06-22 00:17:42 +00002020 /* find face in driver's list */
2021 node = FT_List_Find( &driver->faces_list, face );
2022 if ( node )
2023 {
2024 /* remove face object from the driver's list */
2025 FT_List_Remove( &driver->faces_list, node );
David Turnere459d742002-03-22 13:52:37 +00002026 FT_FREE( node );
Werner Lembergdeb4e982000-06-29 03:14:25 +00002027
David Turnerf0df85b2000-06-22 00:17:42 +00002028 /* now destroy the object proper */
2029 destroy_face( memory, face, driver );
2030 error = FT_Err_Ok;
2031 }
David Turnerd2b1f351999-12-16 23:11:37 +00002032 }
David Turnerd2b1f351999-12-16 23:11:37 +00002033 return error;
2034 }
2035
2036
Werner Lemberg90a03302000-11-07 17:21:11 +00002037 /* documentation is in ftobjs.h */
2038
Werner Lembergf814d0f2001-06-27 16:18:10 +00002039 FT_EXPORT_DEF( FT_Error )
2040 FT_New_Size( FT_Face face,
2041 FT_Size *asize )
David Turnerd2b1f351999-12-16 23:11:37 +00002042 {
Werner Lembergf8ba2002002-03-30 13:16:35 +00002043 FT_Error error;
2044 FT_Memory memory;
2045 FT_Driver driver;
David Turneref3c1262002-03-14 09:22:48 +00002046 FT_Driver_Class clazz;
David Turnerd2b1f351999-12-16 23:11:37 +00002047
Werner Lembergf8ba2002002-03-30 13:16:35 +00002048 FT_Size size = 0;
2049 FT_ListNode node = 0;
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00002050
Werner Lemberga929ba92000-06-25 06:47:11 +00002051
Werner Lembergb48a6092000-07-09 19:15:30 +00002052 if ( !face )
2053 return FT_Err_Invalid_Face_Handle;
2054
2055 if ( !asize )
2056 return FT_Err_Invalid_Size_Handle;
2057
2058 if ( !face->driver )
2059 return FT_Err_Invalid_Driver_Handle;
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00002060
Werner Lembergdeb4e982000-06-29 03:14:25 +00002061 *asize = 0;
2062
David Turnerf0df85b2000-06-22 00:17:42 +00002063 driver = face->driver;
2064 clazz = driver->clazz;
2065 memory = face->memory;
David Turnerd2b1f351999-12-16 23:11:37 +00002066
2067 /* Allocate new size object and perform basic initialisation */
David Turnere459d742002-03-22 13:52:37 +00002068 if ( FT_ALLOC( size, clazz->size_object_size ) || FT_NEW( node ) )
David Turnerd2b1f351999-12-16 23:11:37 +00002069 goto Exit;
2070
2071 size->face = face;
David Turner61d6b2b2001-05-16 17:49:07 +00002072
David Turner54e75742000-11-04 02:52:02 +00002073 /* for now, do not use any internal fields in size objects */
2074 size->internal = 0;
David Turnerd2b1f351999-12-16 23:11:37 +00002075
Werner Lemberga929ba92000-06-25 06:47:11 +00002076 if ( clazz->init_size )
David Turnerf0df85b2000-06-22 00:17:42 +00002077 error = clazz->init_size( size );
David Turnerd2b1f351999-12-16 23:11:37 +00002078
2079 /* in case of success, add to the face's list */
2080 if ( !error )
2081 {
2082 *asize = size;
2083 node->data = size;
2084 FT_List_Add( &face->sizes_list, node );
David Turnerd2b1f351999-12-16 23:11:37 +00002085 }
2086
2087 Exit:
2088 if ( error )
2089 {
David Turnere459d742002-03-22 13:52:37 +00002090 FT_FREE( node );
2091 FT_FREE( size );
David Turnerd2b1f351999-12-16 23:11:37 +00002092 }
2093
2094 return error;
2095 }
2096
2097
Werner Lemberg90a03302000-11-07 17:21:11 +00002098 /* documentation is in ftobjs.h */
2099
Werner Lembergf814d0f2001-06-27 16:18:10 +00002100 FT_EXPORT_DEF( FT_Error )
2101 FT_Done_Size( FT_Size size )
David Turnerd2b1f351999-12-16 23:11:37 +00002102 {
2103 FT_Error error;
2104 FT_Driver driver;
2105 FT_Memory memory;
2106 FT_Face face;
2107 FT_ListNode node;
2108
2109
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00002110 if ( !size )
David Turnerd2b1f351999-12-16 23:11:37 +00002111 return FT_Err_Invalid_Size_Handle;
2112
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00002113 face = size->face;
2114 if ( !face )
2115 return FT_Err_Invalid_Face_Handle;
2116
2117 driver = face->driver;
David Turnerd2b1f351999-12-16 23:11:37 +00002118 if ( !driver )
2119 return FT_Err_Invalid_Driver_Handle;
2120
David Turnerf0df85b2000-06-22 00:17:42 +00002121 memory = driver->root.memory;
David Turnerd2b1f351999-12-16 23:11:37 +00002122
2123 error = FT_Err_Ok;
David Turnerd2b1f351999-12-16 23:11:37 +00002124 node = FT_List_Find( &face->sizes_list, size );
2125 if ( node )
2126 {
2127 FT_List_Remove( &face->sizes_list, node );
David Turnere459d742002-03-22 13:52:37 +00002128 FT_FREE( node );
David Turnerd2b1f351999-12-16 23:11:37 +00002129
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00002130 if ( face->size == size )
David Turnerd2b1f351999-12-16 23:11:37 +00002131 {
2132 face->size = 0;
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00002133 if ( face->sizes_list.head )
David Turnerd2b1f351999-12-16 23:11:37 +00002134 face->size = (FT_Size)(face->sizes_list.head->data);
2135 }
2136
2137 destroy_size( memory, size, driver );
2138 }
2139 else
2140 error = FT_Err_Invalid_Size_Handle;
2141
Werner Lembergcf24d512001-06-18 14:23:45 +00002142 return error;
David Turnerd2b1f351999-12-16 23:11:37 +00002143 }
2144
2145
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002146 /* documentation is in ftobjs.h */
2147
2148 FT_BASE_DEF( FT_Error )
2149 FT_Match_Size( FT_Face face,
2150 FT_Size_Request req,
2151 FT_Bool ignore_width,
Werner Lemberg8c4120d2007-01-15 06:42:40 +00002152 FT_ULong* size_index )
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002153 {
2154 FT_Int i;
2155 FT_Long w, h;
2156
2157
2158 if ( !FT_HAS_FIXED_SIZES( face ) )
2159 return FT_Err_Invalid_Face_Handle;
2160
2161 /* FT_Bitmap_Size doesn't provide enough info... */
2162 if ( req->type != FT_SIZE_REQUEST_TYPE_NOMINAL )
2163 return FT_Err_Unimplemented_Feature;
2164
Werner Lemberg9cc4aed2006-01-26 21:03:58 +00002165 w = FT_REQUEST_WIDTH ( req );
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002166 h = FT_REQUEST_HEIGHT( req );
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002167
2168 if ( req->width && !req->height )
2169 h = w;
2170 else if ( !req->width && req->height )
2171 w = h;
2172
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002173 w = FT_PIX_ROUND( w );
2174 h = FT_PIX_ROUND( h );
2175
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002176 for ( i = 0; i < face->num_fixed_sizes; i++ )
2177 {
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002178 FT_Bitmap_Size* bsize = face->available_sizes + i;
2179
2180
2181 if ( h != FT_PIX_ROUND( bsize->y_ppem ) )
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002182 continue;
2183
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002184 if ( w == FT_PIX_ROUND( bsize->x_ppem ) || ignore_width )
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002185 {
Werner Lemberg8c4120d2007-01-15 06:42:40 +00002186 if ( size_index )
2187 *size_index = (FT_ULong)i;
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002188
2189 return FT_Err_Ok;
2190 }
2191 }
2192
2193 return FT_Err_Invalid_Pixel_Size;
2194 }
2195
2196
Wu, Chia-I (吳佳一)212aee02006-01-15 06:24:53 +00002197 /* documentation is in ftobjs.h */
2198
2199 FT_BASE_DEF( void )
Wu, Chia-I (吳佳一)ea1e8d32006-01-15 15:01:45 +00002200 ft_synthesize_vertical_metrics( FT_Glyph_Metrics* metrics,
2201 FT_Pos advance )
Wu, Chia-I (吳佳一)212aee02006-01-15 06:24:53 +00002202 {
Werner Lemberg1723dcc2006-01-15 07:30:32 +00002203 /* the factor 1.2 is a heuristical value */
Wu, Chia-I (吳佳一)212aee02006-01-15 06:24:53 +00002204 if ( !advance )
2205 advance = metrics->height * 12 / 10;
2206
2207 metrics->vertBearingX = -( metrics->width / 2 );
2208 metrics->vertBearingY = ( advance - metrics->height ) / 2;
2209 metrics->vertAdvance = advance;
2210 }
2211
2212
Werner Lembergf814d0f2001-06-27 16:18:10 +00002213 static void
2214 ft_recompute_scaled_metrics( FT_Face face,
2215 FT_Size_Metrics* metrics )
Werner Lembergdeb4e982000-06-29 03:14:25 +00002216 {
Werner Lemberga929ba92000-06-25 06:47:11 +00002217 /* Compute root ascender, descender, test height, and max_advance */
Werner Lembergdeb4e982000-06-29 03:14:25 +00002218
Wu, Chia-I (吳佳一)2e48a1a2006-02-27 09:18:07 +00002219#ifdef GRID_FIT_METRICS
David Turnerb4636652006-02-26 07:57:45 +00002220 metrics->ascender = FT_PIX_CEIL( FT_MulFix( face->ascender,
2221 metrics->y_scale ) );
2222
2223 metrics->descender = FT_PIX_FLOOR( FT_MulFix( face->descender,
2224 metrics->y_scale ) );
2225
2226 metrics->height = FT_PIX_ROUND( FT_MulFix( face->height,
2227 metrics->y_scale ) );
2228
2229 metrics->max_advance = FT_PIX_ROUND( FT_MulFix( face->max_advance_width,
2230 metrics->x_scale ) );
Wu, Chia-I (吳佳一)2e48a1a2006-02-27 09:18:07 +00002231#else /* !GRID_FIT_METRICS */
Wu, Chia-I (吳佳一)dcb8b712005-12-16 14:27:14 +00002232 metrics->ascender = FT_MulFix( face->ascender,
2233 metrics->y_scale );
Werner Lemberga929ba92000-06-25 06:47:11 +00002234
Wu, Chia-I (吳佳一)dcb8b712005-12-16 14:27:14 +00002235 metrics->descender = FT_MulFix( face->descender,
2236 metrics->y_scale );
Werner Lemberga929ba92000-06-25 06:47:11 +00002237
Wu, Chia-I (吳佳一)dcb8b712005-12-16 14:27:14 +00002238 metrics->height = FT_MulFix( face->height,
2239 metrics->y_scale );
Werner Lemberga929ba92000-06-25 06:47:11 +00002240
Wu, Chia-I (吳佳一)dcb8b712005-12-16 14:27:14 +00002241 metrics->max_advance = FT_MulFix( face->max_advance_width,
2242 metrics->x_scale );
Wu, Chia-I (吳佳一)2e48a1a2006-02-27 09:18:07 +00002243#endif /* !GRID_FIT_METRICS */
Werner Lemberga929ba92000-06-25 06:47:11 +00002244 }
2245
2246
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002247 FT_BASE_DEF( void )
2248 FT_Select_Metrics( FT_Face face,
2249 FT_ULong strike_index )
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002250 {
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002251 FT_Size_Metrics* metrics;
2252 FT_Bitmap_Size* bsize;
2253
2254
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002255 metrics = &face->size->metrics;
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002256 bsize = face->available_sizes + strike_index;
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002257
Werner Lembergbe3c9812006-01-27 14:16:16 +00002258 metrics->x_ppem = (FT_UShort)( ( bsize->x_ppem + 32 ) >> 6 );
2259 metrics->y_ppem = (FT_UShort)( ( bsize->y_ppem + 32 ) >> 6 );
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002260
2261 if ( FT_IS_SCALABLE( face ) )
2262 {
2263 metrics->x_scale = FT_DivFix( bsize->x_ppem,
2264 face->units_per_EM );
2265 metrics->y_scale = FT_DivFix( bsize->y_ppem,
2266 face->units_per_EM );
2267
2268 ft_recompute_scaled_metrics( face, metrics );
2269 }
2270 else
2271 {
Werner Lemberg1723dcc2006-01-15 07:30:32 +00002272 metrics->x_scale = 1L << 22;
2273 metrics->y_scale = 1L << 22;
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002274 metrics->ascender = bsize->y_ppem;
2275 metrics->descender = 0;
2276 metrics->height = bsize->height << 6;
2277 metrics->max_advance = bsize->x_ppem;
2278 }
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002279 }
2280
2281
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002282 FT_BASE_DEF( void )
2283 FT_Request_Metrics( FT_Face face,
2284 FT_Size_Request req )
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002285 {
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002286 FT_Size_Metrics* metrics;
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002287
2288
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002289 metrics = &face->size->metrics;
2290
2291 if ( FT_IS_SCALABLE( face ) )
2292 {
Werner Lembergce280a22007-06-03 05:58:30 +00002293 FT_Long w = 0, h = 0, scaled_w = 0, scaled_h = 0;
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002294
2295
2296 switch ( req->type )
2297 {
2298 case FT_SIZE_REQUEST_TYPE_NOMINAL:
2299 w = h = face->units_per_EM;
2300 break;
Werner Lembergf1c2b912006-01-13 14:53:28 +00002301
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002302 case FT_SIZE_REQUEST_TYPE_REAL_DIM:
2303 w = h = face->ascender - face->descender;
2304 break;
Werner Lembergf1c2b912006-01-13 14:53:28 +00002305
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002306 case FT_SIZE_REQUEST_TYPE_BBOX:
2307 w = face->bbox.xMax - face->bbox.xMin;
2308 h = face->bbox.yMax - face->bbox.yMin;
2309 break;
Werner Lembergf1c2b912006-01-13 14:53:28 +00002310
Werner Lembergb9933f42007-06-01 21:27:12 +00002311 case FT_SIZE_REQUEST_TYPE_CELL:
2312 w = face->max_advance_width;
2313 h = face->ascender - face->descender;
2314 break;
2315
Wu, Chia-I (吳佳一)a8e7a012006-02-24 06:11:30 +00002316 case FT_SIZE_REQUEST_TYPE_SCALES:
2317 metrics->x_scale = (FT_Fixed)req->width;
2318 metrics->y_scale = (FT_Fixed)req->height;
2319 if ( !metrics->x_scale )
2320 metrics->x_scale = metrics->y_scale;
2321 else if ( !metrics->y_scale )
2322 metrics->y_scale = metrics->x_scale;
2323 goto Calculate_Ppem;
Wu, Chia-I (吳佳一)a8e7a012006-02-24 06:11:30 +00002324
Werner Lembergb9933f42007-06-01 21:27:12 +00002325 case FT_SIZE_REQUEST_TYPE_MAX:
2326 break;
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002327 }
2328
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002329 /* to be on the safe side */
Wu, Chia-I (吳佳一)e5ff0592006-01-15 06:00:49 +00002330 if ( w < 0 )
2331 w = -w;
2332
2333 if ( h < 0 )
2334 h = -h;
2335
Werner Lemberg9cc4aed2006-01-26 21:03:58 +00002336 scaled_w = FT_REQUEST_WIDTH ( req );
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002337 scaled_h = FT_REQUEST_HEIGHT( req );
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002338
2339 /* determine scales */
2340 if ( req->width )
2341 {
2342 metrics->x_scale = FT_DivFix( scaled_w, w );
2343
2344 if ( req->height )
2345 {
2346 metrics->y_scale = FT_DivFix( scaled_h, h );
2347
2348 if ( req->type == FT_SIZE_REQUEST_TYPE_CELL )
2349 {
2350 if ( metrics->y_scale > metrics->x_scale )
2351 metrics->y_scale = metrics->x_scale;
2352 else
2353 metrics->x_scale = metrics->y_scale;
2354 }
2355 }
2356 else
2357 {
2358 metrics->y_scale = metrics->x_scale;
2359 scaled_h = FT_MulDiv( scaled_w, h, w );
2360 }
2361 }
2362 else
2363 {
2364 metrics->x_scale = metrics->y_scale = FT_DivFix( scaled_h, h );
2365 scaled_w = FT_MulDiv( scaled_h, w, h );
2366 }
2367
Wu, Chia-I (吳佳一)a8e7a012006-02-24 06:11:30 +00002368 Calculate_Ppem:
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002369 /* calculate the ppems */
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002370 if ( req->type != FT_SIZE_REQUEST_TYPE_NOMINAL )
2371 {
2372 scaled_w = FT_MulFix( face->units_per_EM, metrics->x_scale );
2373 scaled_h = FT_MulFix( face->units_per_EM, metrics->y_scale );
2374 }
2375
Werner Lembergbe3c9812006-01-27 14:16:16 +00002376 metrics->x_ppem = (FT_UShort)( ( scaled_w + 32 ) >> 6 );
2377 metrics->y_ppem = (FT_UShort)( ( scaled_h + 32 ) >> 6 );
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002378
2379 ft_recompute_scaled_metrics( face, metrics );
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002380 }
2381 else
2382 {
2383 FT_ZERO( metrics );
Werner Lemberg1723dcc2006-01-15 07:30:32 +00002384 metrics->x_scale = 1L << 22;
2385 metrics->y_scale = 1L << 22;
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002386 }
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002387 }
2388
2389
2390 /* documentation is in freetype.h */
2391
2392 FT_EXPORT_DEF( FT_Error )
2393 FT_Select_Size( FT_Face face,
2394 FT_Int strike_index )
2395 {
Werner Lemberg9cc4aed2006-01-26 21:03:58 +00002396 FT_Driver_Class clazz;
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002397
2398
2399 if ( !face || !FT_HAS_FIXED_SIZES( face ) )
2400 return FT_Err_Invalid_Face_Handle;
2401
2402 if ( strike_index < 0 || strike_index >= face->num_fixed_sizes )
2403 return FT_Err_Invalid_Argument;
2404
2405 clazz = face->driver->clazz;
2406
2407 if ( clazz->select_size )
2408 return clazz->select_size( face->size, (FT_ULong)strike_index );
2409
2410 FT_Select_Metrics( face, (FT_ULong)strike_index );
2411
2412 return FT_Err_Ok;
2413 }
2414
2415
2416 /* documentation is in freetype.h */
2417
2418 FT_EXPORT_DEF( FT_Error )
2419 FT_Request_Size( FT_Face face,
2420 FT_Size_Request req )
2421 {
Werner Lemberg9cc4aed2006-01-26 21:03:58 +00002422 FT_Driver_Class clazz;
2423 FT_ULong strike_index;
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002424
2425
2426 if ( !face )
2427 return FT_Err_Invalid_Face_Handle;
2428
2429 if ( !req || req->width < 0 || req->height < 0 ||
2430 req->type >= FT_SIZE_REQUEST_TYPE_MAX )
2431 return FT_Err_Invalid_Argument;
2432
2433 clazz = face->driver->clazz;
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002434
2435 if ( clazz->request_size )
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002436 return clazz->request_size( face->size, req );
2437
Wu, Chia-I (吳佳一)e33dc2e2006-01-14 05:09:30 +00002438 /*
Werner Lemberg3d8eeb82006-01-14 07:10:45 +00002439 * The reason that a driver doesn't have `request_size' defined is
2440 * either that the scaling here suffices or that the supported formats
2441 * are bitmap-only and size matching is not implemented.
Wu, Chia-I (吳佳一)e33dc2e2006-01-14 05:09:30 +00002442 *
2443 * In the latter case, a simple size matching is done.
2444 */
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002445 if ( !FT_IS_SCALABLE( face ) && FT_HAS_FIXED_SIZES( face ) )
Wu, Chia-I (吳佳一)e33dc2e2006-01-14 05:09:30 +00002446 {
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002447 FT_Error error;
Wu, Chia-I (吳佳一)e33dc2e2006-01-14 05:09:30 +00002448
2449
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002450 error = FT_Match_Size( face, req, 0, &strike_index );
2451 if ( error )
2452 return error;
Wu, Chia-I (吳佳一)e33dc2e2006-01-14 05:09:30 +00002453
Werner Lemberg9cc4aed2006-01-26 21:03:58 +00002454 FT_TRACE3(( "FT_Request_Size: bitmap strike %lu matched\n",
2455 strike_index ));
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002456
2457 return FT_Select_Size( face, (FT_Int)strike_index );
Wu, Chia-I (吳佳一)e33dc2e2006-01-14 05:09:30 +00002458 }
2459
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002460 FT_Request_Metrics( face, req );
2461
2462 return FT_Err_Ok;
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002463 }
2464
2465
2466 /* documentation is in freetype.h */
2467
2468 FT_EXPORT_DEF( FT_Error )
Werner Lembergf814d0f2001-06-27 16:18:10 +00002469 FT_Set_Char_Size( FT_Face face,
2470 FT_F26Dot6 char_width,
2471 FT_F26Dot6 char_height,
2472 FT_UInt horz_resolution,
2473 FT_UInt vert_resolution )
David Turnerd2b1f351999-12-16 23:11:37 +00002474 {
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002475 FT_Size_RequestRec req;
David Turnerd2b1f351999-12-16 23:11:37 +00002476
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00002477
Wu, Chia-I (吳佳一)cffa8b62006-02-27 11:11:40 +00002478 if ( !char_width )
2479 char_width = char_height;
2480 else if ( !char_height )
2481 char_height = char_width;
2482
Werner Lemberg74781972007-04-03 19:39:28 +00002483 if ( !horz_resolution )
David Turner7338ec22007-04-03 14:30:34 +00002484 horz_resolution = vert_resolution;
Werner Lemberg74781972007-04-03 19:39:28 +00002485 else if ( !vert_resolution )
David Turner7338ec22007-04-03 14:30:34 +00002486 vert_resolution = horz_resolution;
2487
Wu, Chia-I (吳佳一)2e48a1a2006-02-27 09:18:07 +00002488 if ( char_width < 1 * 64 )
2489 char_width = 1 * 64;
2490 if ( char_height < 1 * 64 )
2491 char_height = 1 * 64;
2492
Werner Lemberg106eaf12007-05-03 07:07:47 +00002493 if ( !horz_resolution )
2494 horz_resolution = vert_resolution = 72;
2495
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002496 req.type = FT_SIZE_REQUEST_TYPE_NOMINAL;
2497 req.width = char_width;
2498 req.height = char_height;
Werner Lemberg106eaf12007-05-03 07:07:47 +00002499 req.horiResolution = horz_resolution;
2500 req.vertResolution = vert_resolution;
David Turnerd2b1f351999-12-16 23:11:37 +00002501
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002502 return FT_Request_Size( face, &req );
David Turnerd2b1f351999-12-16 23:11:37 +00002503 }
2504
2505
Werner Lemberg90a03302000-11-07 17:21:11 +00002506 /* documentation is in freetype.h */
2507
Werner Lembergf814d0f2001-06-27 16:18:10 +00002508 FT_EXPORT_DEF( FT_Error )
2509 FT_Set_Pixel_Sizes( FT_Face face,
2510 FT_UInt pixel_width,
2511 FT_UInt pixel_height )
David Turnerd2b1f351999-12-16 23:11:37 +00002512 {
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002513 FT_Size_RequestRec req;
David Turnerd2b1f351999-12-16 23:11:37 +00002514
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00002515
Wu, Chia-I (吳佳一)2e48a1a2006-02-27 09:18:07 +00002516 if ( pixel_width == 0 )
2517 pixel_width = pixel_height;
2518 else if ( pixel_height == 0 )
2519 pixel_height = pixel_width;
2520
2521 if ( pixel_width < 1 )
2522 pixel_width = 1;
2523 if ( pixel_height < 1 )
2524 pixel_height = 1;
2525
Werner Lemberg6e87ed92007-01-26 22:18:56 +00002526 /* use `>=' to avoid potential compiler warning on 16bit platforms */
Wu, Chia-I (吳佳一)2e48a1a2006-02-27 09:18:07 +00002527 if ( pixel_width >= 0xFFFFU )
2528 pixel_width = 0xFFFFU;
2529 if ( pixel_height >= 0xFFFFU )
2530 pixel_height = 0xFFFFU;
2531
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002532 req.type = FT_SIZE_REQUEST_TYPE_NOMINAL;
2533 req.width = pixel_width << 6;
2534 req.height = pixel_height << 6;
2535 req.horiResolution = 0;
2536 req.vertResolution = 0;
David Turnerd2b1f351999-12-16 23:11:37 +00002537
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002538 return FT_Request_Size( face, &req );
David Turnerd2b1f351999-12-16 23:11:37 +00002539 }
2540
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00002541
Werner Lemberg90a03302000-11-07 17:21:11 +00002542 /* documentation is in freetype.h */
2543
Werner Lembergf814d0f2001-06-27 16:18:10 +00002544 FT_EXPORT_DEF( FT_Error )
2545 FT_Get_Kerning( FT_Face face,
2546 FT_UInt left_glyph,
2547 FT_UInt right_glyph,
2548 FT_UInt kern_mode,
2549 FT_Vector *akerning )
David Turnerd2b1f351999-12-16 23:11:37 +00002550 {
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00002551 FT_Error error = FT_Err_Ok;
David Turnerd2b1f351999-12-16 23:11:37 +00002552 FT_Driver driver;
David Turnerd2b1f351999-12-16 23:11:37 +00002553
Werner Lemberga8bbc262000-07-01 14:06:46 +00002554
David Turnerd2b1f351999-12-16 23:11:37 +00002555 if ( !face )
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00002556 return FT_Err_Invalid_Face_Handle;
2557
Werner Lemberg4b680072000-11-07 06:30:29 +00002558 if ( !akerning )
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00002559 return FT_Err_Invalid_Argument;
David Turnerd2b1f351999-12-16 23:11:37 +00002560
2561 driver = face->driver;
David Turnerd2b1f351999-12-16 23:11:37 +00002562
Werner Lemberg4b680072000-11-07 06:30:29 +00002563 akerning->x = 0;
2564 akerning->y = 0;
Werner Lemberg5aa646c2000-07-14 06:16:47 +00002565
David Turnerf0df85b2000-06-22 00:17:42 +00002566 if ( driver->clazz->get_kerning )
David Turnerd2b1f351999-12-16 23:11:37 +00002567 {
David Turnerf0df85b2000-06-22 00:17:42 +00002568 error = driver->clazz->get_kerning( face,
Werner Lemberga929ba92000-06-25 06:47:11 +00002569 left_glyph,
2570 right_glyph,
Werner Lemberg4b680072000-11-07 06:30:29 +00002571 akerning );
Werner Lemberg5aa646c2000-07-14 06:16:47 +00002572 if ( !error )
David Turnerf9ca2bb2000-06-30 23:12:55 +00002573 {
David Turnerb08fe2d2002-08-27 20:20:29 +00002574 if ( kern_mode != FT_KERNING_UNSCALED )
David Turnerf9ca2bb2000-06-30 23:12:55 +00002575 {
Werner Lemberg4b680072000-11-07 06:30:29 +00002576 akerning->x = FT_MulFix( akerning->x, face->size->metrics.x_scale );
2577 akerning->y = FT_MulFix( akerning->y, face->size->metrics.y_scale );
Werner Lemberg5aa646c2000-07-14 06:16:47 +00002578
David Turnerb08fe2d2002-08-27 20:20:29 +00002579 if ( kern_mode != FT_KERNING_UNFITTED )
Werner Lemberg5aa646c2000-07-14 06:16:47 +00002580 {
Werner Lemberg133eee02004-12-12 06:55:40 +00002581 /* we scale down kerning values for small ppem values */
2582 /* to avoid that rounding makes them too big. */
2583 /* `25' has been determined heuristically. */
2584 if ( face->size->metrics.x_ppem < 25 )
2585 akerning->x = FT_MulDiv( akerning->x,
2586 face->size->metrics.x_ppem, 25 );
2587 if ( face->size->metrics.y_ppem < 25 )
2588 akerning->y = FT_MulDiv( akerning->y,
2589 face->size->metrics.y_ppem, 25 );
2590
2591 akerning->x = FT_PIX_ROUND( akerning->x );
2592 akerning->y = FT_PIX_ROUND( akerning->y );
Werner Lemberg5aa646c2000-07-14 06:16:47 +00002593 }
David Turnerf9ca2bb2000-06-30 23:12:55 +00002594 }
2595 }
2596 }
David Turnerd2b1f351999-12-16 23:11:37 +00002597
David Turnerd2b1f351999-12-16 23:11:37 +00002598 return error;
2599 }
2600
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00002601
Werner Lemberg90a03302000-11-07 17:21:11 +00002602 /* documentation is in freetype.h */
2603
Werner Lembergf814d0f2001-06-27 16:18:10 +00002604 FT_EXPORT_DEF( FT_Error )
Wu, Chia-I (吳佳一)108fdbb2006-01-16 15:35:56 +00002605 FT_Get_Track_Kerning( FT_Face face,
2606 FT_Fixed point_size,
2607 FT_Int degree,
2608 FT_Fixed* akerning )
2609 {
2610 FT_Service_Kerning service;
2611 FT_Error error = FT_Err_Ok;
Wu, Chia-I (吳佳一)108fdbb2006-01-16 15:35:56 +00002612
2613
2614 if ( !face )
2615 return FT_Err_Invalid_Face_Handle;
2616
2617 if ( !akerning )
2618 return FT_Err_Invalid_Argument;
2619
Wu, Chia-I (吳佳一)108fdbb2006-01-16 15:35:56 +00002620 FT_FACE_FIND_SERVICE( face, service, KERNING );
2621 if ( !service )
2622 return FT_Err_Unimplemented_Feature;
2623
2624 error = service->get_track( face,
2625 point_size,
2626 degree,
2627 akerning );
2628
2629 return error;
2630 }
2631
2632
2633 /* documentation is in freetype.h */
2634
2635 FT_EXPORT_DEF( FT_Error )
Werner Lembergf814d0f2001-06-27 16:18:10 +00002636 FT_Select_Charmap( FT_Face face,
2637 FT_Encoding encoding )
David Turner0a29c692000-05-12 17:09:38 +00002638 {
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00002639 FT_CharMap* cur;
2640 FT_CharMap* limit;
David Turnere49ab252000-05-16 23:44:38 +00002641
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00002642
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00002643 if ( !face )
2644 return FT_Err_Invalid_Face_Handle;
2645
Werner Lemberge88c5262006-10-24 05:46:26 +00002646 if ( encoding == FT_ENCODING_NONE )
2647 return FT_Err_Invalid_Argument;
2648
Werner Lembergc8c6bf52003-04-23 05:38:13 +00002649 /* FT_ENCODING_UNICODE is special. We try to find the `best' Unicode */
2650 /* charmap available, i.e., one with UCS-4 characters, if possible. */
2651 /* */
2652 /* This is done by find_unicode_charmap() above, to share code. */
Antoine Lecac96f69d2002-12-03 00:39:16 +00002653 if ( encoding == FT_ENCODING_UNICODE )
2654 return find_unicode_charmap( face );
2655
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00002656 cur = face->charmaps;
2657 if ( !cur )
2658 return FT_Err_Invalid_CharMap_Handle;
2659
2660 limit = cur + face->num_charmaps;
2661
David Turner0a29c692000-05-12 17:09:38 +00002662 for ( ; cur < limit; cur++ )
2663 {
2664 if ( cur[0]->encoding == encoding )
2665 {
2666 face->charmap = cur[0];
2667 return 0;
2668 }
2669 }
Werner Lembergdeb4e982000-06-29 03:14:25 +00002670
David Turner0a29c692000-05-12 17:09:38 +00002671 return FT_Err_Invalid_Argument;
2672 }
2673
2674
Werner Lemberg90a03302000-11-07 17:21:11 +00002675 /* documentation is in freetype.h */
2676
Werner Lembergf814d0f2001-06-27 16:18:10 +00002677 FT_EXPORT_DEF( FT_Error )
2678 FT_Set_Charmap( FT_Face face,
2679 FT_CharMap charmap )
David Turner0a29c692000-05-12 17:09:38 +00002680 {
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00002681 FT_CharMap* cur;
2682 FT_CharMap* limit;
David Turnere49ab252000-05-16 23:44:38 +00002683
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00002684
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00002685 if ( !face )
2686 return FT_Err_Invalid_Face_Handle;
2687
2688 cur = face->charmaps;
2689 if ( !cur )
2690 return FT_Err_Invalid_CharMap_Handle;
Werner Lemberg9a966b72007-10-15 17:21:32 +00002691 if ( FT_Get_CMap_Format( charmap ) == 14 )
2692 return FT_Err_Invalid_Argument;
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00002693
2694 limit = cur + face->num_charmaps;
2695
David Turner0a29c692000-05-12 17:09:38 +00002696 for ( ; cur < limit; cur++ )
2697 {
2698 if ( cur[0] == charmap )
2699 {
2700 face->charmap = cur[0];
2701 return 0;
2702 }
2703 }
2704 return FT_Err_Invalid_Argument;
2705 }
David Turnerd2b1f351999-12-16 23:11:37 +00002706
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00002707
Werner Lemberge95365b2004-04-24 14:43:37 +00002708 /* documentation is in freetype.h */
2709
2710 FT_EXPORT_DEF( FT_Int )
2711 FT_Get_Charmap_Index( FT_CharMap charmap )
2712 {
2713 FT_Int i;
2714
2715
2716 for ( i = 0; i < charmap->face->num_charmaps; i++ )
2717 if ( charmap->face->charmaps[i] == charmap )
2718 break;
2719
2720 FT_ASSERT( i < charmap->face->num_charmaps );
2721
2722 return i;
2723 }
2724
2725
Werner Lemberge70371c2005-05-27 06:01:28 +00002726 static void
2727 ft_cmap_done_internal( FT_CMap cmap )
2728 {
2729 FT_CMap_Class clazz = cmap->clazz;
2730 FT_Face face = cmap->charmap.face;
2731 FT_Memory memory = FT_FACE_MEMORY(face);
2732
2733
2734 if ( clazz->done )
2735 clazz->done( cmap );
2736
2737 FT_FREE( cmap );
2738 }
2739
2740
David Turner4e7eeee2002-02-28 16:10:29 +00002741 FT_BASE_DEF( void )
2742 FT_CMap_Done( FT_CMap cmap )
2743 {
2744 if ( cmap )
2745 {
Werner Lemberge70371c2005-05-27 06:01:28 +00002746 FT_Face face = cmap->charmap.face;
2747 FT_Memory memory = FT_FACE_MEMORY( face );
2748 FT_Error error;
2749 FT_Int i, j;
David Turnerbc82f1b2002-03-01 02:26:22 +00002750
Werner Lembergf8ba2002002-03-30 13:16:35 +00002751
Werner Lemberge70371c2005-05-27 06:01:28 +00002752 for ( i = 0; i < face->num_charmaps; i++ )
2753 {
2754 if ( (FT_CMap)face->charmaps[i] == cmap )
2755 {
2756 FT_CharMap last_charmap = face->charmaps[face->num_charmaps - 1];
David Turner4e7eeee2002-02-28 16:10:29 +00002757
Werner Lemberge70371c2005-05-27 06:01:28 +00002758
2759 if ( FT_RENEW_ARRAY( face->charmaps,
2760 face->num_charmaps,
2761 face->num_charmaps - 1 ) )
2762 return;
2763
2764 /* remove it from our list of charmaps */
2765 for ( j = i + 1; j < face->num_charmaps; j++ )
2766 {
2767 if ( j == face->num_charmaps - 1 )
2768 face->charmaps[j - 1] = last_charmap;
2769 else
2770 face->charmaps[j - 1] = face->charmaps[j];
2771 }
2772
2773 face->num_charmaps--;
2774
2775 if ( (FT_CMap)face->charmap == cmap )
2776 face->charmap = NULL;
2777
2778 ft_cmap_done_internal( cmap );
2779
2780 break;
2781 }
2782 }
David Turner4e7eeee2002-02-28 16:10:29 +00002783 }
2784 }
2785
2786
2787 FT_BASE_DEF( FT_Error )
Werner Lemberg9cc4aed2006-01-26 21:03:58 +00002788 FT_CMap_New( FT_CMap_Class clazz,
2789 FT_Pointer init_data,
2790 FT_CharMap charmap,
2791 FT_CMap *acmap )
David Turnerbc82f1b2002-03-01 02:26:22 +00002792 {
Werner Lemberg8acb8672005-03-08 11:43:36 +00002793 FT_Error error = FT_Err_Ok;
David Turner4e7eeee2002-02-28 16:10:29 +00002794 FT_Face face;
2795 FT_Memory memory;
2796 FT_CMap cmap;
David Turnerbc82f1b2002-03-01 02:26:22 +00002797
Werner Lembergf8ba2002002-03-30 13:16:35 +00002798
David Turner4e7eeee2002-02-28 16:10:29 +00002799 if ( clazz == NULL || charmap == NULL || charmap->face == NULL )
2800 return FT_Err_Invalid_Argument;
2801
2802 face = charmap->face;
Werner Lembergf35ff802003-06-02 21:58:05 +00002803 memory = FT_FACE_MEMORY( face );
David Turner4e7eeee2002-02-28 16:10:29 +00002804
David Turnere459d742002-03-22 13:52:37 +00002805 if ( !FT_ALLOC( cmap, clazz->size ) )
David Turner4e7eeee2002-02-28 16:10:29 +00002806 {
2807 cmap->charmap = *charmap;
2808 cmap->clazz = clazz;
David Turnerbc82f1b2002-03-01 02:26:22 +00002809
David Turner4e7eeee2002-02-28 16:10:29 +00002810 if ( clazz->init )
2811 {
David Turnerbc82f1b2002-03-01 02:26:22 +00002812 error = clazz->init( cmap, init_data );
Werner Lembergf8ba2002002-03-30 13:16:35 +00002813 if ( error )
David Turner4e7eeee2002-02-28 16:10:29 +00002814 goto Fail;
2815 }
David Turnerbc82f1b2002-03-01 02:26:22 +00002816
David Turner4e7eeee2002-02-28 16:10:29 +00002817 /* add it to our list of charmaps */
David Turnere459d742002-03-22 13:52:37 +00002818 if ( FT_RENEW_ARRAY( face->charmaps,
2819 face->num_charmaps,
Werner Lemberg8acb8672005-03-08 11:43:36 +00002820 face->num_charmaps + 1 ) )
David Turner4e7eeee2002-02-28 16:10:29 +00002821 goto Fail;
David Turnerbc82f1b2002-03-01 02:26:22 +00002822
Werner Lembergf8ba2002002-03-30 13:16:35 +00002823 face->charmaps[face->num_charmaps++] = (FT_CharMap)cmap;
David Turner4e7eeee2002-02-28 16:10:29 +00002824 }
David Turnerbc82f1b2002-03-01 02:26:22 +00002825
David Turner4e7eeee2002-02-28 16:10:29 +00002826 Exit:
2827 if ( acmap )
2828 *acmap = cmap;
2829
2830 return error;
David Turnerbc82f1b2002-03-01 02:26:22 +00002831
David Turner4e7eeee2002-02-28 16:10:29 +00002832 Fail:
Werner Lemberge70371c2005-05-27 06:01:28 +00002833 ft_cmap_done_internal( cmap );
David Turner4e7eeee2002-02-28 16:10:29 +00002834 cmap = NULL;
2835 goto Exit;
David Turnerbc82f1b2002-03-01 02:26:22 +00002836 }
David Turner4e7eeee2002-02-28 16:10:29 +00002837
2838
Werner Lemberg90a03302000-11-07 17:21:11 +00002839 /* documentation is in freetype.h */
2840
Werner Lembergf814d0f2001-06-27 16:18:10 +00002841 FT_EXPORT_DEF( FT_UInt )
2842 FT_Get_Char_Index( FT_Face face,
2843 FT_ULong charcode )
David Turnerd2b1f351999-12-16 23:11:37 +00002844 {
David Turnered54f282002-03-22 17:09:52 +00002845 FT_UInt result = 0;
2846
2847
2848 if ( face && face->charmap )
2849 {
2850 FT_CMap cmap = FT_CMAP( face->charmap );
David Turner25a6e3a2002-06-10 23:03:35 +00002851
Werner Lembergf8ba2002002-03-30 13:16:35 +00002852
David Turnered54f282002-03-22 17:09:52 +00002853 result = cmap->clazz->char_index( cmap, charcode );
2854 }
2855 return result;
2856 }
2857
David Turnered54f282002-03-22 17:09:52 +00002858
Werner Lemberg0f7c2f12002-02-04 20:55:58 +00002859 /* documentation is in freetype.h */
2860
2861 FT_EXPORT_DEF( FT_ULong )
David Turner041889e2002-02-28 19:28:26 +00002862 FT_Get_First_Char( FT_Face face,
2863 FT_UInt *agindex )
Werner Lemberg0f7c2f12002-02-04 20:55:58 +00002864 {
Werner Lembergf8ba2002002-03-30 13:16:35 +00002865 FT_ULong result = 0;
2866 FT_UInt gindex = 0;
2867
David Turnerbc82f1b2002-03-01 02:26:22 +00002868
David Turner041889e2002-02-28 19:28:26 +00002869 if ( face && face->charmap )
2870 {
2871 gindex = FT_Get_Char_Index( face, 0 );
2872 if ( gindex == 0 )
2873 result = FT_Get_Next_Char( face, 0, &gindex );
2874 }
David Turnerbc82f1b2002-03-01 02:26:22 +00002875
David Turner041889e2002-02-28 19:28:26 +00002876 if ( agindex )
2877 *agindex = gindex;
David Turnerbc82f1b2002-03-01 02:26:22 +00002878
David Turner041889e2002-02-28 19:28:26 +00002879 return result;
2880 }
2881
David Turner041889e2002-02-28 19:28:26 +00002882
Werner Lemberg7b0cc662003-07-05 07:46:49 +00002883 /* documentation is in freetype.h */
David Turnered54f282002-03-22 17:09:52 +00002884
David Turnered54f282002-03-22 17:09:52 +00002885 FT_EXPORT_DEF( FT_ULong )
2886 FT_Get_Next_Char( FT_Face face,
2887 FT_ULong charcode,
2888 FT_UInt *agindex )
2889 {
Werner Lembergf8ba2002002-03-30 13:16:35 +00002890 FT_ULong result = 0;
2891 FT_UInt gindex = 0;
David Turnered54f282002-03-22 17:09:52 +00002892
2893
2894 if ( face && face->charmap )
2895 {
2896 FT_UInt32 code = (FT_UInt32)charcode;
2897 FT_CMap cmap = FT_CMAP( face->charmap );
2898
Werner Lembergf8ba2002002-03-30 13:16:35 +00002899
David Turnered54f282002-03-22 17:09:52 +00002900 gindex = cmap->clazz->char_next( cmap, &code );
2901 result = ( gindex == 0 ) ? 0 : code;
2902 }
2903
2904 if ( agindex )
2905 *agindex = gindex;
2906
2907 return result;
2908 }
2909
David Turnered54f282002-03-22 17:09:52 +00002910
Werner Lemberg90a03302000-11-07 17:21:11 +00002911 /* documentation is in freetype.h */
2912
Tom Kacvinskyff2714f2001-08-08 10:58:08 +00002913 FT_EXPORT_DEF( FT_UInt )
David Turnercf432db2007-10-19 12:36:40 +00002914 FT_Face_GetCharVariantIndex( FT_Face face,
2915 FT_ULong charcode,
2916 FT_ULong variantSelector )
Werner Lemberg9a966b72007-10-15 17:21:32 +00002917 {
2918 FT_UInt result = 0;
2919
2920
2921 if ( face && face->charmap &&
2922 face->charmap->encoding == FT_ENCODING_UNICODE )
2923 {
2924 FT_CharMap charmap = find_variant_selector_charmap( face );
2925 FT_CMap ucmap = FT_CMAP( face->charmap );
2926
2927
2928 if ( charmap != NULL )
2929 {
2930 FT_CMap vcmap = FT_CMAP( charmap );
2931
2932
2933 result = vcmap->clazz->char_var_index( vcmap, ucmap, charcode,
2934 variantSelector );
2935 }
2936 }
2937
2938 return result;
2939 }
2940
2941
2942 /* documentation is in freetype.h */
2943
2944 FT_EXPORT_DEF( FT_Int )
David Turnercf432db2007-10-19 12:36:40 +00002945 FT_Face_GetCharVariantIsDefault( FT_Face face,
2946 FT_ULong charcode,
2947 FT_ULong variantSelector )
Werner Lemberg9a966b72007-10-15 17:21:32 +00002948 {
2949 FT_Int result = -1;
2950
2951
2952 if ( face )
2953 {
2954 FT_CharMap charmap = find_variant_selector_charmap( face );
2955
2956
2957 if ( charmap != NULL )
2958 {
2959 FT_CMap vcmap = FT_CMAP( charmap );
2960
2961
2962 result = vcmap->clazz->char_var_default( vcmap, charcode,
2963 variantSelector );
2964 }
2965 }
2966
2967 return result;
2968 }
2969
2970
2971 /* documentation is in freetype.h */
2972
2973 FT_EXPORT_DEF( FT_UInt32* )
David Turnercf432db2007-10-19 12:36:40 +00002974 FT_Face_GetVariantSelectors( FT_Face face )
Werner Lemberg9a966b72007-10-15 17:21:32 +00002975 {
2976 FT_UInt32 *result = NULL;
2977
2978
2979 if ( face )
2980 {
2981 FT_CharMap charmap = find_variant_selector_charmap( face );
2982
2983
2984 if ( charmap != NULL )
2985 {
2986 FT_CMap vcmap = FT_CMAP( charmap );
2987 FT_Memory memory = FT_FACE_MEMORY( face );
2988
2989
2990 result = vcmap->clazz->variant_list( vcmap, memory );
2991 }
2992 }
2993
2994 return result;
2995 }
2996
2997
2998 /* documentation is in freetype.h */
2999
3000 FT_EXPORT_DEF( FT_UInt32* )
David Turnercf432db2007-10-19 12:36:40 +00003001 FT_Face_GetVariantsOfChar( FT_Face face,
3002 FT_ULong charcode )
Werner Lemberg9a966b72007-10-15 17:21:32 +00003003 {
3004 FT_UInt32 *result = NULL;
3005
3006
3007 if ( face )
3008 {
3009 FT_CharMap charmap = find_variant_selector_charmap( face );
3010
3011
3012 if ( charmap != NULL )
3013 {
3014 FT_CMap vcmap = FT_CMAP( charmap );
3015 FT_Memory memory = FT_FACE_MEMORY( face );
3016
3017
3018 result = vcmap->clazz->charvariant_list( vcmap, memory, charcode );
3019 }
3020 }
3021 return result;
3022 }
3023
3024
3025 /* documentation is in freetype.h */
3026
3027 FT_EXPORT_DEF( FT_UInt32* )
David Turnercf432db2007-10-19 12:36:40 +00003028 FT_Face_GetCharsOfVariant( FT_Face face,
3029 FT_ULong variantSelector )
Werner Lemberg9a966b72007-10-15 17:21:32 +00003030 {
3031 FT_UInt32 *result = NULL;
3032
3033
3034 if ( face )
3035 {
3036 FT_CharMap charmap = find_variant_selector_charmap( face );
3037
3038
3039 if ( charmap != NULL )
3040 {
3041 FT_CMap vcmap = FT_CMAP( charmap );
3042 FT_Memory memory = FT_FACE_MEMORY( face );
3043
3044
3045 result = vcmap->clazz->variantchar_list( vcmap, memory,
3046 variantSelector );
3047 }
3048 }
3049
3050 return result;
3051 }
3052
3053
3054 /* documentation is in freetype.h */
3055
3056 FT_EXPORT_DEF( FT_UInt )
Tom Kacvinskyff2714f2001-08-08 10:58:08 +00003057 FT_Get_Name_Index( FT_Face face,
3058 FT_String* glyph_name )
3059 {
3060 FT_UInt result = 0;
3061
3062
3063 if ( face && FT_HAS_GLYPH_NAMES( face ) )
3064 {
David Turnerc313c502003-09-11 19:51:54 +00003065 FT_Service_GlyphDict service;
Tom Kacvinskyff2714f2001-08-08 10:58:08 +00003066
Werner Lemberg013efd12003-09-17 05:26:33 +00003067
Werner Lemberg46333a12003-09-17 19:20:02 +00003068 FT_FACE_LOOKUP_SERVICE( face,
David Turnere2d12842003-09-21 17:15:55 +00003069 service,
3070 GLYPH_DICT );
Werner Lemberg013efd12003-09-17 05:26:33 +00003071
David Turnerc313c502003-09-11 19:51:54 +00003072 if ( service && service->name_index )
3073 result = service->name_index( face, glyph_name );
Werner Lemberg013efd12003-09-17 05:26:33 +00003074 }
3075
Tom Kacvinskyff2714f2001-08-08 10:58:08 +00003076 return result;
3077 }
3078
Werner Lembergaef3fc82001-12-17 16:21:22 +00003079
Tom Kacvinskyff2714f2001-08-08 10:58:08 +00003080 /* documentation is in freetype.h */
3081
Werner Lembergf814d0f2001-06-27 16:18:10 +00003082 FT_EXPORT_DEF( FT_Error )
3083 FT_Get_Glyph_Name( FT_Face face,
3084 FT_UInt glyph_index,
3085 FT_Pointer buffer,
3086 FT_UInt buffer_max )
David Turner6930b452000-07-19 17:13:03 +00003087 {
3088 FT_Error error = FT_Err_Invalid_Argument;
Werner Lembergeddd9902000-10-12 05:05:40 +00003089
Werner Lembergd060a752000-07-20 06:57:41 +00003090
David Turner6930b452000-07-19 17:13:03 +00003091 /* clean up buffer */
Werner Lembergd060a752000-07-20 06:57:41 +00003092 if ( buffer && buffer_max > 0 )
David Turner6930b452000-07-19 17:13:03 +00003093 ((FT_Byte*)buffer)[0] = 0;
Werner Lembergeddd9902000-10-12 05:05:40 +00003094
Werner Lembergfd97d132002-06-16 01:14:16 +00003095 if ( face &&
3096 glyph_index <= (FT_UInt)face->num_glyphs &&
3097 FT_HAS_GLYPH_NAMES( face ) )
David Turner6930b452000-07-19 17:13:03 +00003098 {
David Turnerc313c502003-09-11 19:51:54 +00003099 FT_Service_GlyphDict service;
David Turner6930b452000-07-19 17:13:03 +00003100
Werner Lemberg013efd12003-09-17 05:26:33 +00003101
Werner Lemberg46333a12003-09-17 19:20:02 +00003102 FT_FACE_LOOKUP_SERVICE( face,
David Turnere2d12842003-09-21 17:15:55 +00003103 service,
3104 GLYPH_DICT );
Werner Lembergd060a752000-07-20 06:57:41 +00003105
David Turnerc313c502003-09-11 19:51:54 +00003106 if ( service && service->get_name )
David Turnerc313c502003-09-11 19:51:54 +00003107 error = service->get_name( face, glyph_index, buffer, buffer_max );
David Turner6930b452000-07-19 17:13:03 +00003108 }
Werner Lembergd060a752000-07-20 06:57:41 +00003109
David Turner6930b452000-07-19 17:13:03 +00003110 return error;
Werner Lembergeddd9902000-10-12 05:05:40 +00003111 }
David Turner6930b452000-07-19 17:13:03 +00003112
3113
David Turner23bcde12001-10-17 13:48:10 +00003114 /* documentation is in freetype.h */
3115
3116 FT_EXPORT_DEF( const char* )
3117 FT_Get_Postscript_Name( FT_Face face )
3118 {
3119 const char* result = NULL;
Werner Lemberg1a0a9792002-01-03 22:06:13 +00003120
Werner Lembergc3b21602001-12-05 01:22:05 +00003121
David Turner23bcde12001-10-17 13:48:10 +00003122 if ( !face )
3123 goto Exit;
3124
David Turner23bcde12001-10-17 13:48:10 +00003125 if ( !result )
3126 {
David Turnerb72d8a82003-09-29 20:33:37 +00003127 FT_Service_PsFontName service;
Werner Lembergc3b21602001-12-05 01:22:05 +00003128
Werner Lemberg013efd12003-09-17 05:26:33 +00003129
Werner Lemberg46333a12003-09-17 19:20:02 +00003130 FT_FACE_LOOKUP_SERVICE( face,
David Turnere2d12842003-09-21 17:15:55 +00003131 service,
David Turnerb72d8a82003-09-29 20:33:37 +00003132 POSTSCRIPT_FONT_NAME );
David Turner23bcde12001-10-17 13:48:10 +00003133
David Turnerb72d8a82003-09-29 20:33:37 +00003134 if ( service && service->get_ps_font_name )
3135 result = service->get_ps_font_name( face );
David Turner23bcde12001-10-17 13:48:10 +00003136 }
Werner Lemberg013efd12003-09-17 05:26:33 +00003137
David Turner23bcde12001-10-17 13:48:10 +00003138 Exit:
3139 return result;
3140 }
3141
3142
Werner Lemberg90a03302000-11-07 17:21:11 +00003143 /* documentation is in tttables.h */
3144
Werner Lembergf814d0f2001-06-27 16:18:10 +00003145 FT_EXPORT_DEF( void* )
3146 FT_Get_Sfnt_Table( FT_Face face,
3147 FT_Sfnt_Tag tag )
David Turner99a4d932000-04-25 16:10:50 +00003148 {
Werner Lemberg40bb0962003-11-01 14:36:20 +00003149 void* table = 0;
3150 FT_Service_SFNT_Table service;
David Turnere49ab252000-05-16 23:44:38 +00003151
Werner Lemberg013efd12003-09-17 05:26:33 +00003152
David Turnerc313c502003-09-11 19:51:54 +00003153 if ( face && FT_IS_SFNT( face ) )
3154 {
David Turnerb72d8a82003-09-29 20:33:37 +00003155 FT_FACE_FIND_SERVICE( face, service, SFNT_TABLE );
David Turnerc313c502003-09-11 19:51:54 +00003156 if ( service != NULL )
3157 table = service->get_table( face, tag );
3158 }
David Turnere2d12842003-09-21 17:15:55 +00003159
David Turner99a4d932000-04-25 16:10:50 +00003160 return table;
David Turnere49ab252000-05-16 23:44:38 +00003161 }
David Turner99a4d932000-04-25 16:10:50 +00003162
3163
David Turner621e4882002-12-16 21:51:24 +00003164 /* documentation is in tttables.h */
3165
3166 FT_EXPORT_DEF( FT_Error )
Werner Lembergc8c6bf52003-04-23 05:38:13 +00003167 FT_Load_Sfnt_Table( FT_Face face,
3168 FT_ULong tag,
3169 FT_Long offset,
3170 FT_Byte* buffer,
3171 FT_ULong* length )
David Turner621e4882002-12-16 21:51:24 +00003172 {
David Turnerc313c502003-09-11 19:51:54 +00003173 FT_Service_SFNT_Table service;
David Turner621e4882002-12-16 21:51:24 +00003174
3175
3176 if ( !face || !FT_IS_SFNT( face ) )
3177 return FT_Err_Invalid_Face_Handle;
3178
David Turnerb72d8a82003-09-29 20:33:37 +00003179 FT_FACE_FIND_SERVICE( face, service, SFNT_TABLE );
David Turnerc313c502003-09-11 19:51:54 +00003180 if ( service == NULL )
David Turner621e4882002-12-16 21:51:24 +00003181 return FT_Err_Unimplemented_Feature;
David Turnere2d12842003-09-21 17:15:55 +00003182
David Turnerc313c502003-09-11 19:51:54 +00003183 return service->load_table( face, tag, offset, buffer, length );
David Turner621e4882002-12-16 21:51:24 +00003184 }
3185
3186
Werner Lemberg17439422004-08-11 05:25:37 +00003187 /* documentation is in tttables.h */
3188
3189 FT_EXPORT_DEF( FT_Error )
3190 FT_Sfnt_Table_Info( FT_Face face,
3191 FT_UInt table_index,
3192 FT_ULong *tag,
3193 FT_ULong *length )
3194 {
3195 FT_Service_SFNT_Table service;
3196
3197
3198 if ( !face || !FT_IS_SFNT( face ) )
3199 return FT_Err_Invalid_Face_Handle;
3200
3201 FT_FACE_FIND_SERVICE( face, service, SFNT_TABLE );
3202 if ( service == NULL )
3203 return FT_Err_Unimplemented_Feature;
3204
3205 return service->table_info( face, table_index, tag, length );
3206 }
3207
3208
Werner Lembergece8b202004-12-13 23:16:59 +00003209 /* documentation is in tttables.h */
3210
Werner Lemberg91a67472003-12-17 14:28:22 +00003211 FT_EXPORT_DEF( FT_ULong )
3212 FT_Get_CMap_Language_ID( FT_CharMap charmap )
3213 {
3214 FT_Service_TTCMaps service;
3215 FT_Face face;
3216 TT_CMapInfo cmap_info;
3217
David Turner87c0d302003-12-24 01:10:46 +00003218
Werner Lemberg91a67472003-12-17 14:28:22 +00003219 if ( !charmap || !charmap->face )
3220 return 0;
3221
3222 face = charmap->face;
3223 FT_FACE_FIND_SERVICE( face, service, TT_CMAP );
3224 if ( service == NULL )
3225 return 0;
3226 if ( service->get_cmap_info( charmap, &cmap_info ))
3227 return 0;
3228
3229 return cmap_info.language;
3230 }
3231
3232
Werner Lembergb826fa72007-05-19 07:18:48 +00003233 /* documentation is in tttables.h */
3234
3235 FT_EXPORT_DEF( FT_Long )
3236 FT_Get_CMap_Format( FT_CharMap charmap )
3237 {
3238 FT_Service_TTCMaps service;
3239 FT_Face face;
3240 TT_CMapInfo cmap_info;
3241
3242
3243 if ( !charmap || !charmap->face )
3244 return -1;
3245
3246 face = charmap->face;
3247 FT_FACE_FIND_SERVICE( face, service, TT_CMAP );
3248 if ( service == NULL )
3249 return -1;
3250 if ( service->get_cmap_info( charmap, &cmap_info ))
3251 return -1;
3252
3253 return cmap_info.format;
3254 }
3255
3256
Werner Lembergece8b202004-12-13 23:16:59 +00003257 /* documentation is in ftsizes.h */
3258
David Turnerb3ba40d2001-10-07 13:30:26 +00003259 FT_EXPORT_DEF( FT_Error )
Werner Lemberg80b8d772001-10-10 19:56:42 +00003260 FT_Activate_Size( FT_Size size )
David Turnerb3ba40d2001-10-07 13:30:26 +00003261 {
3262 FT_Face face;
Werner Lemberg1a0a9792002-01-03 22:06:13 +00003263
Werner Lemberg80b8d772001-10-10 19:56:42 +00003264
David Turnerb3ba40d2001-10-07 13:30:26 +00003265 if ( size == NULL )
3266 return FT_Err_Bad_Argument;
Werner Lemberg1a0a9792002-01-03 22:06:13 +00003267
David Turnerb3ba40d2001-10-07 13:30:26 +00003268 face = size->face;
3269 if ( face == NULL || face->driver == NULL )
3270 return FT_Err_Bad_Argument;
Werner Lemberg1a0a9792002-01-03 22:06:13 +00003271
Werner Lemberg80b8d772001-10-10 19:56:42 +00003272 /* we don't need anything more complex than that; all size objects */
3273 /* are already listed by the face */
David Turnerb3ba40d2001-10-07 13:30:26 +00003274 face->size = size;
Werner Lemberg1a0a9792002-01-03 22:06:13 +00003275
David Turnerb3ba40d2001-10-07 13:30:26 +00003276 return FT_Err_Ok;
3277 }
3278
3279
David Turnerd2b1f351999-12-16 23:11:37 +00003280 /*************************************************************************/
David Turnerf0df85b2000-06-22 00:17:42 +00003281 /*************************************************************************/
3282 /*************************************************************************/
3283 /**** ****/
3284 /**** ****/
3285 /**** R E N D E R E R S ****/
3286 /**** ****/
3287 /**** ****/
3288 /*************************************************************************/
3289 /*************************************************************************/
3290 /*************************************************************************/
3291
Werner Lembergdeb4e982000-06-29 03:14:25 +00003292 /* lookup a renderer by glyph format in the library's list */
Werner Lembergf814d0f2001-06-27 16:18:10 +00003293 FT_BASE_DEF( FT_Renderer )
3294 FT_Lookup_Renderer( FT_Library library,
3295 FT_Glyph_Format format,
3296 FT_ListNode* node )
David Turnerf0df85b2000-06-22 00:17:42 +00003297 {
Werner Lembergf8ba2002002-03-30 13:16:35 +00003298 FT_ListNode cur;
3299 FT_Renderer result = 0;
Werner Lemberga929ba92000-06-25 06:47:11 +00003300
Werner Lembergdeb4e982000-06-29 03:14:25 +00003301
3302 if ( !library )
3303 goto Exit;
3304
3305 cur = library->renderers.head;
3306
3307 if ( node )
David Turner74abee82000-06-27 23:31:53 +00003308 {
Werner Lembergdeb4e982000-06-29 03:14:25 +00003309 if ( *node )
David Turner74abee82000-06-27 23:31:53 +00003310 cur = (*node)->next;
David Turnerf0df85b2000-06-22 00:17:42 +00003311 *node = 0;
David Turner74abee82000-06-27 23:31:53 +00003312 }
Werner Lembergdeb4e982000-06-29 03:14:25 +00003313
Werner Lemberga929ba92000-06-25 06:47:11 +00003314 while ( cur )
David Turnerf0df85b2000-06-22 00:17:42 +00003315 {
Werner Lemberga929ba92000-06-25 06:47:11 +00003316 FT_Renderer renderer = FT_RENDERER( cur->data );
Werner Lembergdeb4e982000-06-29 03:14:25 +00003317
Werner Lemberga929ba92000-06-25 06:47:11 +00003318
3319 if ( renderer->glyph_format == format )
David Turnerf0df85b2000-06-22 00:17:42 +00003320 {
Werner Lemberga929ba92000-06-25 06:47:11 +00003321 if ( node )
David Turnerf0df85b2000-06-22 00:17:42 +00003322 *node = cur;
Werner Lembergdeb4e982000-06-29 03:14:25 +00003323
David Turnerf0df85b2000-06-22 00:17:42 +00003324 result = renderer;
3325 break;
3326 }
David Turner74abee82000-06-27 23:31:53 +00003327 cur = cur->next;
David Turnerf0df85b2000-06-22 00:17:42 +00003328 }
Werner Lemberga929ba92000-06-25 06:47:11 +00003329
Werner Lembergdeb4e982000-06-29 03:14:25 +00003330 Exit:
David Turnerf0df85b2000-06-22 00:17:42 +00003331 return result;
3332 }
3333
Werner Lemberga929ba92000-06-25 06:47:11 +00003334
Werner Lembergf814d0f2001-06-27 16:18:10 +00003335 static FT_Renderer
3336 ft_lookup_glyph_renderer( FT_GlyphSlot slot )
Werner Lembergdeb4e982000-06-29 03:14:25 +00003337 {
3338 FT_Face face = slot->face;
3339 FT_Library library = FT_FACE_LIBRARY( face );
3340 FT_Renderer result = library->cur_renderer;
3341
3342
Werner Lemberga929ba92000-06-25 06:47:11 +00003343 if ( !result || result->glyph_format != slot->format )
David Turner81bb4ad2000-06-28 04:19:49 +00003344 result = FT_Lookup_Renderer( library, slot->format, 0 );
Werner Lembergfbeb41d2000-07-02 00:27:53 +00003345
David Turnerf0df85b2000-06-22 00:17:42 +00003346 return result;
3347 }
3348
Werner Lembergdeb4e982000-06-29 03:14:25 +00003349
Werner Lembergf814d0f2001-06-27 16:18:10 +00003350 static void
3351 ft_set_current_renderer( FT_Library library )
David Turnerf0df85b2000-06-22 00:17:42 +00003352 {
3353 FT_Renderer renderer;
3354
Werner Lembergdeb4e982000-06-29 03:14:25 +00003355
David Turnerb08fe2d2002-08-27 20:20:29 +00003356 renderer = FT_Lookup_Renderer( library, FT_GLYPH_FORMAT_OUTLINE, 0 );
David Turnerf0df85b2000-06-22 00:17:42 +00003357 library->cur_renderer = renderer;
3358 }
3359
3360
Werner Lembergf814d0f2001-06-27 16:18:10 +00003361 static FT_Error
3362 ft_add_renderer( FT_Module module )
David Turnerf0df85b2000-06-22 00:17:42 +00003363 {
3364 FT_Library library = module->library;
3365 FT_Memory memory = library->memory;
3366 FT_Error error;
3367 FT_ListNode node;
Werner Lembergdeb4e982000-06-29 03:14:25 +00003368
3369
David Turnere459d742002-03-22 13:52:37 +00003370 if ( FT_NEW( node ) )
David Turnerf0df85b2000-06-22 00:17:42 +00003371 goto Exit;
Werner Lembergdeb4e982000-06-29 03:14:25 +00003372
David Turnerf0df85b2000-06-22 00:17:42 +00003373 {
Werner Lemberga929ba92000-06-25 06:47:11 +00003374 FT_Renderer render = FT_RENDERER( module );
David Turnerf0df85b2000-06-22 00:17:42 +00003375 FT_Renderer_Class* clazz = (FT_Renderer_Class*)module->clazz;
3376
Werner Lemberga929ba92000-06-25 06:47:11 +00003377
David Turnerf0df85b2000-06-22 00:17:42 +00003378 render->clazz = clazz;
3379 render->glyph_format = clazz->glyph_format;
Werner Lembergdeb4e982000-06-29 03:14:25 +00003380
David Turnerf0df85b2000-06-22 00:17:42 +00003381 /* allocate raster object if needed */
David Turnerb08fe2d2002-08-27 20:20:29 +00003382 if ( clazz->glyph_format == FT_GLYPH_FORMAT_OUTLINE &&
David Turnerf0df85b2000-06-22 00:17:42 +00003383 clazz->raster_class->raster_new )
3384 {
3385 error = clazz->raster_class->raster_new( memory, &render->raster );
Werner Lemberga929ba92000-06-25 06:47:11 +00003386 if ( error )
3387 goto Fail;
Werner Lembergdeb4e982000-06-29 03:14:25 +00003388
David Turnerf0df85b2000-06-22 00:17:42 +00003389 render->raster_render = clazz->raster_class->raster_render;
3390 render->render = clazz->render_glyph;
Werner Lembergdeb4e982000-06-29 03:14:25 +00003391 }
3392
David Turnerf0df85b2000-06-22 00:17:42 +00003393 /* add to list */
3394 node->data = module;
3395 FT_List_Add( &library->renderers, node );
3396
3397 ft_set_current_renderer( library );
3398 }
3399
3400 Fail:
Werner Lemberga929ba92000-06-25 06:47:11 +00003401 if ( error )
David Turnere459d742002-03-22 13:52:37 +00003402 FT_FREE( node );
David Turnerf0df85b2000-06-22 00:17:42 +00003403
3404 Exit:
3405 return error;
Werner Lembergdeb4e982000-06-29 03:14:25 +00003406 }
David Turnerf0df85b2000-06-22 00:17:42 +00003407
3408
Werner Lembergf814d0f2001-06-27 16:18:10 +00003409 static void
3410 ft_remove_renderer( FT_Module module )
David Turnerf0df85b2000-06-22 00:17:42 +00003411 {
3412 FT_Library library = module->library;
3413 FT_Memory memory = library->memory;
3414 FT_ListNode node;
3415
Werner Lemberga929ba92000-06-25 06:47:11 +00003416
David Turnerf0df85b2000-06-22 00:17:42 +00003417 node = FT_List_Find( &library->renderers, module );
Werner Lemberga929ba92000-06-25 06:47:11 +00003418 if ( node )
David Turnerf0df85b2000-06-22 00:17:42 +00003419 {
Werner Lemberga929ba92000-06-25 06:47:11 +00003420 FT_Renderer render = FT_RENDERER( module );
Werner Lembergdeb4e982000-06-29 03:14:25 +00003421
Werner Lemberga929ba92000-06-25 06:47:11 +00003422
David Turnerf0df85b2000-06-22 00:17:42 +00003423 /* release raster object, if any */
Werner Lemberga929ba92000-06-25 06:47:11 +00003424 if ( render->raster )
David Turnerf0df85b2000-06-22 00:17:42 +00003425 render->clazz->raster_class->raster_done( render->raster );
Werner Lembergdeb4e982000-06-29 03:14:25 +00003426
David Turnerf0df85b2000-06-22 00:17:42 +00003427 /* remove from list */
3428 FT_List_Remove( &library->renderers, node );
David Turnere459d742002-03-22 13:52:37 +00003429 FT_FREE( node );
Werner Lembergdeb4e982000-06-29 03:14:25 +00003430
David Turnerf0df85b2000-06-22 00:17:42 +00003431 ft_set_current_renderer( library );
3432 }
3433 }
3434
3435
Werner Lemberg90a03302000-11-07 17:21:11 +00003436 /* documentation is in ftrender.h */
3437
Werner Lembergf814d0f2001-06-27 16:18:10 +00003438 FT_EXPORT_DEF( FT_Renderer )
3439 FT_Get_Renderer( FT_Library library,
3440 FT_Glyph_Format format )
David Turnerf0df85b2000-06-22 00:17:42 +00003441 {
Werner Lembergdeb4e982000-06-29 03:14:25 +00003442 /* test for valid `library' delayed to FT_Lookup_Renderer() */
3443
Werner Lembergf8ba2002002-03-30 13:16:35 +00003444 return FT_Lookup_Renderer( library, format, 0 );
Werner Lembergdeb4e982000-06-29 03:14:25 +00003445 }
David Turnerf0df85b2000-06-22 00:17:42 +00003446
3447
Werner Lemberg90a03302000-11-07 17:21:11 +00003448 /* documentation is in ftrender.h */
3449
Werner Lembergf814d0f2001-06-27 16:18:10 +00003450 FT_EXPORT_DEF( FT_Error )
3451 FT_Set_Renderer( FT_Library library,
3452 FT_Renderer renderer,
3453 FT_UInt num_params,
3454 FT_Parameter* parameters )
David Turnerf0df85b2000-06-22 00:17:42 +00003455 {
3456 FT_ListNode node;
3457 FT_Error error = FT_Err_Ok;
Werner Lembergdeb4e982000-06-29 03:14:25 +00003458
3459
3460 if ( !library )
3461 return FT_Err_Invalid_Library_Handle;
3462
3463 if ( !renderer )
3464 return FT_Err_Invalid_Argument;
Werner Lemberga929ba92000-06-25 06:47:11 +00003465
David Turnerf0df85b2000-06-22 00:17:42 +00003466 node = FT_List_Find( &library->renderers, renderer );
Werner Lemberga929ba92000-06-25 06:47:11 +00003467 if ( !node )
David Turnerf0df85b2000-06-22 00:17:42 +00003468 {
3469 error = FT_Err_Invalid_Argument;
3470 goto Exit;
3471 }
David Turner74abee82000-06-27 23:31:53 +00003472
David Turnerf0df85b2000-06-22 00:17:42 +00003473 FT_List_Up( &library->renderers, node );
Werner Lembergdeb4e982000-06-29 03:14:25 +00003474
David Turnerb08fe2d2002-08-27 20:20:29 +00003475 if ( renderer->glyph_format == FT_GLYPH_FORMAT_OUTLINE )
David Turnerf0df85b2000-06-22 00:17:42 +00003476 library->cur_renderer = renderer;
Werner Lembergdeb4e982000-06-29 03:14:25 +00003477
Werner Lemberga929ba92000-06-25 06:47:11 +00003478 if ( num_params > 0 )
David Turnerf0df85b2000-06-22 00:17:42 +00003479 {
David Turnerb08fe2d2002-08-27 20:20:29 +00003480 FT_Renderer_SetModeFunc set_mode = renderer->clazz->set_mode;
Werner Lembergdeb4e982000-06-29 03:14:25 +00003481
Werner Lemberga929ba92000-06-25 06:47:11 +00003482
David Turnerf0df85b2000-06-22 00:17:42 +00003483 for ( ; num_params > 0; num_params-- )
3484 {
3485 error = set_mode( renderer, parameters->tag, parameters->data );
Werner Lemberga929ba92000-06-25 06:47:11 +00003486 if ( error )
David Turnerf0df85b2000-06-22 00:17:42 +00003487 break;
3488 }
3489 }
Werner Lembergdeb4e982000-06-29 03:14:25 +00003490
David Turnerf0df85b2000-06-22 00:17:42 +00003491 Exit:
3492 return error;
Werner Lembergdeb4e982000-06-29 03:14:25 +00003493 }
David Turnerf0df85b2000-06-22 00:17:42 +00003494
3495
David Turner7504e482002-06-07 07:24:55 +00003496 FT_BASE_DEF( FT_Error )
Werner Lemberg68e9f922002-09-27 11:09:23 +00003497 FT_Render_Glyph_Internal( FT_Library library,
3498 FT_GlyphSlot slot,
3499 FT_Render_Mode render_mode )
David Turnerf0df85b2000-06-22 00:17:42 +00003500 {
3501 FT_Error error = FT_Err_Ok;
3502 FT_Renderer renderer;
Werner Lemberga929ba92000-06-25 06:47:11 +00003503
Werner Lembergdeb4e982000-06-29 03:14:25 +00003504
3505 /* if it is already a bitmap, no need to do anything */
3506 switch ( slot->format )
David Turnerf0df85b2000-06-22 00:17:42 +00003507 {
David Turnerb08fe2d2002-08-27 20:20:29 +00003508 case FT_GLYPH_FORMAT_BITMAP: /* already a bitmap, don't do anything */
Werner Lembergdeb4e982000-06-29 03:14:25 +00003509 break;
3510
3511 default:
David Turner74abee82000-06-27 23:31:53 +00003512 {
3513 FT_ListNode node = 0;
3514 FT_Bool update = 0;
Werner Lembergdeb4e982000-06-29 03:14:25 +00003515
3516
Werner Lemberga929ba92000-06-25 06:47:11 +00003517 /* small shortcut for the very common case */
David Turnerb08fe2d2002-08-27 20:20:29 +00003518 if ( slot->format == FT_GLYPH_FORMAT_OUTLINE )
David Turner74abee82000-06-27 23:31:53 +00003519 {
Werner Lemberga929ba92000-06-25 06:47:11 +00003520 renderer = library->cur_renderer;
David Turner74abee82000-06-27 23:31:53 +00003521 node = library->renderers.head;
3522 }
Werner Lemberga929ba92000-06-25 06:47:11 +00003523 else
David Turner74abee82000-06-27 23:31:53 +00003524 renderer = FT_Lookup_Renderer( library, slot->format, &node );
3525
Werner Lemberga929ba92000-06-25 06:47:11 +00003526 error = FT_Err_Unimplemented_Feature;
Werner Lembergdeb4e982000-06-29 03:14:25 +00003527 while ( renderer )
David Turner74abee82000-06-27 23:31:53 +00003528 {
David Turnerc8ad30a2001-12-05 17:24:34 +00003529 error = renderer->render( renderer, slot, render_mode, NULL );
Werner Lemberg79860702001-06-08 21:17:29 +00003530 if ( !error ||
3531 FT_ERROR_BASE( error ) != FT_Err_Cannot_Render_Glyph )
Werner Lembergdeb4e982000-06-29 03:14:25 +00003532 break;
David Turner74abee82000-06-27 23:31:53 +00003533
Werner Lembergdeb4e982000-06-29 03:14:25 +00003534 /* FT_Err_Cannot_Render_Glyph is returned if the render mode */
David Turner74abee82000-06-27 23:31:53 +00003535 /* is unsupported by the current renderer for this glyph image */
Werner Lembergdeb4e982000-06-29 03:14:25 +00003536 /* format. */
3537
3538 /* now, look for another renderer that supports the same */
3539 /* format. */
David Turner74abee82000-06-27 23:31:53 +00003540 renderer = FT_Lookup_Renderer( library, slot->format, &node );
3541 update = 1;
3542 }
3543
3544 /* if we changed the current renderer for the glyph image format */
Werner Lembergdeb4e982000-06-29 03:14:25 +00003545 /* we need to select it as the next current one */
3546 if ( !error && update && renderer )
David Turner74abee82000-06-27 23:31:53 +00003547 FT_Set_Renderer( library, renderer, 0, 0 );
David Turnerf0df85b2000-06-22 00:17:42 +00003548 }
3549 }
Werner Lembergdeb4e982000-06-29 03:14:25 +00003550
David Turnerf0df85b2000-06-22 00:17:42 +00003551 return error;
3552 }
Werner Lemberga929ba92000-06-25 06:47:11 +00003553
David Turner74abee82000-06-27 23:31:53 +00003554
Werner Lemberg90a03302000-11-07 17:21:11 +00003555 /* documentation is in freetype.h */
3556
Werner Lembergf814d0f2001-06-27 16:18:10 +00003557 FT_EXPORT_DEF( FT_Error )
Werner Lemberg68e9f922002-09-27 11:09:23 +00003558 FT_Render_Glyph( FT_GlyphSlot slot,
3559 FT_Render_Mode render_mode )
David Turner74abee82000-06-27 23:31:53 +00003560 {
Werner Lembergf8ba2002002-03-30 13:16:35 +00003561 FT_Library library;
Werner Lembergdeb4e982000-06-29 03:14:25 +00003562
3563
3564 if ( !slot )
David Turner74abee82000-06-27 23:31:53 +00003565 return FT_Err_Invalid_Argument;
Werner Lembergdeb4e982000-06-29 03:14:25 +00003566
3567 library = FT_FACE_LIBRARY( slot->face );
3568
David Turner74abee82000-06-27 23:31:53 +00003569 return FT_Render_Glyph_Internal( library, slot, render_mode );
3570 }
3571
Werner Lembergdeb4e982000-06-29 03:14:25 +00003572
David Turnerf0df85b2000-06-22 00:17:42 +00003573 /*************************************************************************/
3574 /*************************************************************************/
3575 /*************************************************************************/
3576 /**** ****/
3577 /**** ****/
3578 /**** M O D U L E S ****/
3579 /**** ****/
3580 /**** ****/
3581 /*************************************************************************/
3582 /*************************************************************************/
3583 /*************************************************************************/
3584
Werner Lemberga929ba92000-06-25 06:47:11 +00003585
David Turnerf0df85b2000-06-22 00:17:42 +00003586 /*************************************************************************/
3587 /* */
3588 /* <Function> */
3589 /* Destroy_Module */
3590 /* */
3591 /* <Description> */
3592 /* Destroys a given module object. For drivers, this also destroys */
Werner Lemberga929ba92000-06-25 06:47:11 +00003593 /* all child faces. */
David Turnerf0df85b2000-06-22 00:17:42 +00003594 /* */
3595 /* <InOut> */
3596 /* module :: A handle to the target driver object. */
3597 /* */
3598 /* <Note> */
3599 /* The driver _must_ be LOCKED! */
3600 /* */
Werner Lembergf814d0f2001-06-27 16:18:10 +00003601 static void
3602 Destroy_Module( FT_Module module )
David Turnerf0df85b2000-06-22 00:17:42 +00003603 {
David Turner5ae831c2000-06-30 01:31:22 +00003604 FT_Memory memory = module->memory;
3605 FT_Module_Class* clazz = module->clazz;
3606 FT_Library library = module->library;
David Turnerf0df85b2000-06-22 00:17:42 +00003607
Werner Lemberga929ba92000-06-25 06:47:11 +00003608
David Turnerf0df85b2000-06-22 00:17:42 +00003609 /* finalize client-data - before anything else */
3610 if ( module->generic.finalizer )
3611 module->generic.finalizer( module );
3612
David Turner5ae831c2000-06-30 01:31:22 +00003613 if ( library && library->auto_hinter == module )
3614 library->auto_hinter = 0;
3615
David Turnerf0df85b2000-06-22 00:17:42 +00003616 /* if the module is a renderer */
Werner Lemberga929ba92000-06-25 06:47:11 +00003617 if ( FT_MODULE_IS_RENDERER( module ) )
3618 ft_remove_renderer( module );
David Turnerf0df85b2000-06-22 00:17:42 +00003619
3620 /* if the module is a font driver, add some steps */
Werner Lemberga929ba92000-06-25 06:47:11 +00003621 if ( FT_MODULE_IS_DRIVER( module ) )
3622 Destroy_Driver( FT_DRIVER( module ) );
David Turnerf0df85b2000-06-22 00:17:42 +00003623
3624 /* finalize the module object */
Werner Lemberga929ba92000-06-25 06:47:11 +00003625 if ( clazz->module_done )
3626 clazz->module_done( module );
David Turnerf0df85b2000-06-22 00:17:42 +00003627
3628 /* discard it */
David Turnere459d742002-03-22 13:52:37 +00003629 FT_FREE( module );
David Turnerf0df85b2000-06-22 00:17:42 +00003630 }
3631
David Turnerf0df85b2000-06-22 00:17:42 +00003632
Werner Lemberg748b1712005-12-25 09:15:09 +00003633 /* documentation is in ftmodapi.h */
Werner Lemberg90a03302000-11-07 17:21:11 +00003634
Werner Lembergf814d0f2001-06-27 16:18:10 +00003635 FT_EXPORT_DEF( FT_Error )
3636 FT_Add_Module( FT_Library library,
3637 const FT_Module_Class* clazz )
David Turnerf0df85b2000-06-22 00:17:42 +00003638 {
3639 FT_Error error;
3640 FT_Memory memory;
3641 FT_Module module;
3642 FT_UInt nn;
3643
David Turnerf0df85b2000-06-22 00:17:42 +00003644
Werner Lembergdeb4e982000-06-29 03:14:25 +00003645#define FREETYPE_VER_FIXED ( ( (FT_Long)FREETYPE_MAJOR << 16 ) | \
3646 FREETYPE_MINOR )
Werner Lemberga929ba92000-06-25 06:47:11 +00003647
Werner Lembergdeb4e982000-06-29 03:14:25 +00003648 if ( !library )
3649 return FT_Err_Invalid_Library_Handle;
3650
3651 if ( !clazz )
David Turnerf0df85b2000-06-22 00:17:42 +00003652 return FT_Err_Invalid_Argument;
3653
3654 /* check freetype version */
3655 if ( clazz->module_requires > FREETYPE_VER_FIXED )
3656 return FT_Err_Invalid_Version;
3657
3658 /* look for a module with the same name in the library's table */
3659 for ( nn = 0; nn < library->num_modules; nn++ )
3660 {
3661 module = library->modules[nn];
David Turnerd15bc0d2002-04-12 09:31:48 +00003662 if ( ft_strcmp( module->clazz->module_name, clazz->module_name ) == 0 )
David Turnerf0df85b2000-06-22 00:17:42 +00003663 {
3664 /* this installed module has the same name, compare their versions */
3665 if ( clazz->module_version <= module->clazz->module_version )
3666 return FT_Err_Lower_Module_Version;
3667
3668 /* remove the module from our list, then exit the loop to replace */
3669 /* it by our new version.. */
3670 FT_Remove_Module( library, module );
3671 break;
3672 }
3673 }
3674
3675 memory = library->memory;
3676 error = FT_Err_Ok;
3677
3678 if ( library->num_modules >= FT_MAX_MODULES )
3679 {
3680 error = FT_Err_Too_Many_Drivers;
3681 goto Exit;
3682 }
3683
3684 /* allocate module object */
Werner Lemberg68e9f922002-09-27 11:09:23 +00003685 if ( FT_ALLOC( module, clazz->module_size ) )
David Turnerf0df85b2000-06-22 00:17:42 +00003686 goto Exit;
3687
Werner Lembergdeb4e982000-06-29 03:14:25 +00003688 /* base initialization */
David Turnerf0df85b2000-06-22 00:17:42 +00003689 module->library = library;
3690 module->memory = memory;
3691 module->clazz = (FT_Module_Class*)clazz;
3692
Werner Lembergdeb4e982000-06-29 03:14:25 +00003693 /* check whether the module is a renderer - this must be performed */
3694 /* before the normal module initialization */
Werner Lemberga929ba92000-06-25 06:47:11 +00003695 if ( FT_MODULE_IS_RENDERER( module ) )
David Turnerf0df85b2000-06-22 00:17:42 +00003696 {
3697 /* add to the renderers list */
Werner Lemberga929ba92000-06-25 06:47:11 +00003698 error = ft_add_renderer( module );
3699 if ( error )
3700 goto Fail;
David Turnerf0df85b2000-06-22 00:17:42 +00003701 }
3702
Werner Lembergcc9fc492000-06-30 06:21:26 +00003703 /* is the module a auto-hinter? */
3704 if ( FT_MODULE_IS_HINTER( module ) )
David Turner5ae831c2000-06-30 01:31:22 +00003705 library->auto_hinter = module;
Werner Lembergfbeb41d2000-07-02 00:27:53 +00003706
David Turnerf0df85b2000-06-22 00:17:42 +00003707 /* if the module is a font driver */
Werner Lemberga929ba92000-06-25 06:47:11 +00003708 if ( FT_MODULE_IS_DRIVER( module ) )
David Turnerf0df85b2000-06-22 00:17:42 +00003709 {
3710 /* allocate glyph loader if needed */
Werner Lembergf8ba2002002-03-30 13:16:35 +00003711 FT_Driver driver = FT_DRIVER( module );
Werner Lemberga929ba92000-06-25 06:47:11 +00003712
Werner Lembergdeb4e982000-06-29 03:14:25 +00003713
David Turneref3c1262002-03-14 09:22:48 +00003714 driver->clazz = (FT_Driver_Class)module->clazz;
Werner Lemberga929ba92000-06-25 06:47:11 +00003715 if ( FT_DRIVER_USES_OUTLINES( driver ) )
David Turnerf0df85b2000-06-22 00:17:42 +00003716 {
3717 error = FT_GlyphLoader_New( memory, &driver->glyph_loader );
Werner Lemberga929ba92000-06-25 06:47:11 +00003718 if ( error )
3719 goto Fail;
David Turnerf0df85b2000-06-22 00:17:42 +00003720 }
3721 }
3722
Werner Lemberga929ba92000-06-25 06:47:11 +00003723 if ( clazz->module_init )
David Turnerf0df85b2000-06-22 00:17:42 +00003724 {
Werner Lemberga929ba92000-06-25 06:47:11 +00003725 error = clazz->module_init( module );
3726 if ( error )
3727 goto Fail;
David Turnerf0df85b2000-06-22 00:17:42 +00003728 }
3729
3730 /* add module to the library's table */
Werner Lemberga929ba92000-06-25 06:47:11 +00003731 library->modules[library->num_modules++] = module;
Werner Lembergdeb4e982000-06-29 03:14:25 +00003732
David Turnerf0df85b2000-06-22 00:17:42 +00003733 Exit:
3734 return error;
Werner Lembergdeb4e982000-06-29 03:14:25 +00003735
David Turnerf0df85b2000-06-22 00:17:42 +00003736 Fail:
Werner Lemberga929ba92000-06-25 06:47:11 +00003737 if ( FT_MODULE_IS_DRIVER( module ) )
David Turnerf0df85b2000-06-22 00:17:42 +00003738 {
Werner Lemberga929ba92000-06-25 06:47:11 +00003739 FT_Driver driver = FT_DRIVER( module );
Werner Lembergdeb4e982000-06-29 03:14:25 +00003740
Werner Lemberga929ba92000-06-25 06:47:11 +00003741
3742 if ( FT_DRIVER_USES_OUTLINES( driver ) )
David Turnerf0df85b2000-06-22 00:17:42 +00003743 FT_GlyphLoader_Done( driver->glyph_loader );
3744 }
Werner Lembergdeb4e982000-06-29 03:14:25 +00003745
Werner Lemberga929ba92000-06-25 06:47:11 +00003746 if ( FT_MODULE_IS_RENDERER( module ) )
David Turnerf0df85b2000-06-22 00:17:42 +00003747 {
Werner Lemberga929ba92000-06-25 06:47:11 +00003748 FT_Renderer renderer = FT_RENDERER( module );
3749
3750
3751 if ( renderer->raster )
David Turnerf0df85b2000-06-22 00:17:42 +00003752 renderer->clazz->raster_class->raster_done( renderer->raster );
3753 }
Werner Lemberga929ba92000-06-25 06:47:11 +00003754
David Turnere459d742002-03-22 13:52:37 +00003755 FT_FREE( module );
David Turnerf0df85b2000-06-22 00:17:42 +00003756 goto Exit;
3757 }
3758
David Turnerf0df85b2000-06-22 00:17:42 +00003759
Werner Lemberg748b1712005-12-25 09:15:09 +00003760 /* documentation is in ftmodapi.h */
Werner Lemberg90a03302000-11-07 17:21:11 +00003761
Werner Lembergf814d0f2001-06-27 16:18:10 +00003762 FT_EXPORT_DEF( FT_Module )
3763 FT_Get_Module( FT_Library library,
3764 const char* module_name )
David Turnerf0df85b2000-06-22 00:17:42 +00003765 {
Werner Lembergdeb4e982000-06-29 03:14:25 +00003766 FT_Module result = 0;
3767 FT_Module* cur;
3768 FT_Module* limit;
David Turnerf0df85b2000-06-22 00:17:42 +00003769
Werner Lemberga929ba92000-06-25 06:47:11 +00003770
Werner Lembergdeb4e982000-06-29 03:14:25 +00003771 if ( !library || !module_name )
3772 return result;
3773
3774 cur = library->modules;
3775 limit = cur + library->num_modules;
3776
David Turnerf0df85b2000-06-22 00:17:42 +00003777 for ( ; cur < limit; cur++ )
David Turnerd15bc0d2002-04-12 09:31:48 +00003778 if ( ft_strcmp( cur[0]->clazz->module_name, module_name ) == 0 )
David Turnerf0df85b2000-06-22 00:17:42 +00003779 {
3780 result = cur[0];
3781 break;
3782 }
3783
3784 return result;
3785 }
3786
Werner Lemberga929ba92000-06-25 06:47:11 +00003787
Werner Lemberg8ec9dfd2000-11-07 23:56:02 +00003788 /* documentation is in ftobjs.h */
3789
Werner Lembergf814d0f2001-06-27 16:18:10 +00003790 FT_BASE_DEF( const void* )
3791 FT_Get_Module_Interface( FT_Library library,
3792 const char* mod_name )
David Turnerf0df85b2000-06-22 00:17:42 +00003793 {
3794 FT_Module module;
Werner Lembergdeb4e982000-06-29 03:14:25 +00003795
3796
3797 /* test for valid `library' delayed to FT_Get_Module() */
Werner Lemberga929ba92000-06-25 06:47:11 +00003798
David Turnerf0df85b2000-06-22 00:17:42 +00003799 module = FT_Get_Module( library, mod_name );
Werner Lemberga929ba92000-06-25 06:47:11 +00003800
David Turnerf0df85b2000-06-22 00:17:42 +00003801 return module ? module->clazz->module_interface : 0;
Werner Lembergdeb4e982000-06-29 03:14:25 +00003802 }
David Turnerf0df85b2000-06-22 00:17:42 +00003803
3804
David Turnerb72d8a82003-09-29 20:33:37 +00003805 FT_BASE_DEF( FT_Pointer )
3806 ft_module_get_service( FT_Module module,
3807 const char* service_id )
3808 {
3809 FT_Pointer result = NULL;
3810
3811 if ( module )
3812 {
3813 FT_ASSERT( module->clazz && module->clazz->get_interface );
3814
3815 /* first, look for the service in the module
3816 */
3817 if ( module->clazz->get_interface )
3818 result = module->clazz->get_interface( module, service_id );
3819
3820 if ( result == NULL )
3821 {
3822 /* we didn't find it, look in all other modules then
3823 */
3824 FT_Library library = module->library;
3825 FT_Module* cur = library->modules;
3826 FT_Module* limit = cur + library->num_modules;
3827
3828 for ( ; cur < limit; cur++ )
3829 {
3830 if ( cur[0] != module )
3831 {
3832 FT_ASSERT( cur[0]->clazz );
3833
3834 if ( cur[0]->clazz->get_interface )
3835 {
3836 result = cur[0]->clazz->get_interface( cur[0], service_id );
3837 if ( result != NULL )
3838 break;
3839 }
3840 }
3841 }
3842 }
3843 }
3844
3845 return result;
3846 }
3847
3848
Werner Lemberg748b1712005-12-25 09:15:09 +00003849 /* documentation is in ftmodapi.h */
Werner Lemberg90a03302000-11-07 17:21:11 +00003850
Werner Lembergf814d0f2001-06-27 16:18:10 +00003851 FT_EXPORT_DEF( FT_Error )
3852 FT_Remove_Module( FT_Library library,
3853 FT_Module module )
David Turnerf0df85b2000-06-22 00:17:42 +00003854 {
3855 /* try to find the module from the table, then remove it from there */
Werner Lembergdeb4e982000-06-29 03:14:25 +00003856
3857 if ( !library )
3858 return FT_Err_Invalid_Library_Handle;
3859
3860 if ( module )
David Turnerf0df85b2000-06-22 00:17:42 +00003861 {
3862 FT_Module* cur = library->modules;
3863 FT_Module* limit = cur + library->num_modules;
3864
Werner Lemberga929ba92000-06-25 06:47:11 +00003865
David Turnerf0df85b2000-06-22 00:17:42 +00003866 for ( ; cur < limit; cur++ )
3867 {
Werner Lembergdeb4e982000-06-29 03:14:25 +00003868 if ( cur[0] == module )
David Turnerf0df85b2000-06-22 00:17:42 +00003869 {
3870 /* remove it from the table */
3871 library->num_modules--;
3872 limit--;
Werner Lemberga929ba92000-06-25 06:47:11 +00003873 while ( cur < limit )
David Turnerf0df85b2000-06-22 00:17:42 +00003874 {
3875 cur[0] = cur[1];
3876 cur++;
3877 }
3878 limit[0] = 0;
3879
3880 /* destroy the module */
Werner Lemberga929ba92000-06-25 06:47:11 +00003881 Destroy_Module( module );
David Turnerf0df85b2000-06-22 00:17:42 +00003882
3883 return FT_Err_Ok;
3884 }
3885 }
3886 }
Werner Lembergb48a6092000-07-09 19:15:30 +00003887 return FT_Err_Invalid_Driver_Handle;
David Turnerf0df85b2000-06-22 00:17:42 +00003888 }
3889
3890
David Turnerf0df85b2000-06-22 00:17:42 +00003891 /*************************************************************************/
3892 /*************************************************************************/
3893 /*************************************************************************/
3894 /**** ****/
3895 /**** ****/
3896 /**** L I B R A R Y ****/
3897 /**** ****/
3898 /**** ****/
3899 /*************************************************************************/
3900 /*************************************************************************/
3901 /*************************************************************************/
3902
Werner Lemberga929ba92000-06-25 06:47:11 +00003903
Werner Lemberg748b1712005-12-25 09:15:09 +00003904 /* documentation is in ftmodapi.h */
Werner Lemberg90a03302000-11-07 17:21:11 +00003905
Werner Lembergf814d0f2001-06-27 16:18:10 +00003906 FT_EXPORT_DEF( FT_Error )
3907 FT_New_Library( FT_Memory memory,
3908 FT_Library *alibrary )
David Turnerf0df85b2000-06-22 00:17:42 +00003909 {
3910 FT_Library library = 0;
3911 FT_Error error;
3912
3913
3914 if ( !memory )
3915 return FT_Err_Invalid_Argument;
3916
David Turnerf5749602002-04-18 10:07:26 +00003917#ifdef FT_DEBUG_LEVEL_ERROR
David Turner53b3fa12002-02-24 05:26:57 +00003918 /* init debugging support */
3919 ft_debug_init();
David Turnerf5749602002-04-18 10:07:26 +00003920#endif
David Turner53b3fa12002-02-24 05:26:57 +00003921
David Turnerf0df85b2000-06-22 00:17:42 +00003922 /* first of all, allocate the library object */
David Turnere459d742002-03-22 13:52:37 +00003923 if ( FT_NEW( library ) )
David Turnerf0df85b2000-06-22 00:17:42 +00003924 return error;
3925
3926 library->memory = memory;
3927
3928 /* allocate the render pool */
3929 library->raster_pool_size = FT_RENDER_POOL_SIZE;
Werner Lemberg39c91ad2007-07-28 05:40:40 +00003930#if FT_RENDER_POOL_SIZE > 0
3931 if ( FT_ALLOC( library->raster_pool, FT_RENDER_POOL_SIZE ) )
3932 goto Fail;
3933#endif
David Turnerf0df85b2000-06-22 00:17:42 +00003934
3935 /* That's ok now */
3936 *alibrary = library;
3937
3938 return FT_Err_Ok;
3939
3940 Fail:
David Turnere459d742002-03-22 13:52:37 +00003941 FT_FREE( library );
David Turnerf0df85b2000-06-22 00:17:42 +00003942 return error;
3943 }
3944
3945
David Turner83b4a4b2002-03-06 12:42:34 +00003946 /* documentation is in freetype.h */
David Turner25a6e3a2002-06-10 23:03:35 +00003947
David Turner83b4a4b2002-03-06 12:42:34 +00003948 FT_EXPORT_DEF( void )
3949 FT_Library_Version( FT_Library library,
3950 FT_Int *amajor,
3951 FT_Int *aminor,
3952 FT_Int *apatch )
3953 {
3954 FT_Int major = 0;
3955 FT_Int minor = 0;
3956 FT_Int patch = 0;
3957
David Turner25a6e3a2002-06-10 23:03:35 +00003958
David Turner83b4a4b2002-03-06 12:42:34 +00003959 if ( library )
3960 {
3961 major = library->version_major;
3962 minor = library->version_minor;
3963 patch = library->version_patch;
3964 }
David Turner25a6e3a2002-06-10 23:03:35 +00003965
David Turnerd48575e2002-09-18 23:18:36 +00003966 if ( amajor )
David Turner83b4a4b2002-03-06 12:42:34 +00003967 *amajor = major;
David Turner25a6e3a2002-06-10 23:03:35 +00003968
David Turnerd48575e2002-09-18 23:18:36 +00003969 if ( aminor )
David Turner83b4a4b2002-03-06 12:42:34 +00003970 *aminor = minor;
David Turner25a6e3a2002-06-10 23:03:35 +00003971
David Turnerd48575e2002-09-18 23:18:36 +00003972 if ( apatch )
David Turner83b4a4b2002-03-06 12:42:34 +00003973 *apatch = patch;
David Turner25a6e3a2002-06-10 23:03:35 +00003974 }
David Turner83b4a4b2002-03-06 12:42:34 +00003975
3976
Werner Lemberg748b1712005-12-25 09:15:09 +00003977 /* documentation is in ftmodapi.h */
Werner Lemberg90a03302000-11-07 17:21:11 +00003978
Werner Lembergf814d0f2001-06-27 16:18:10 +00003979 FT_EXPORT_DEF( FT_Error )
3980 FT_Done_Library( FT_Library library )
David Turnerf0df85b2000-06-22 00:17:42 +00003981 {
3982 FT_Memory memory;
David Turnerf0df85b2000-06-22 00:17:42 +00003983
3984
3985 if ( !library )
3986 return FT_Err_Invalid_Library_Handle;
3987
3988 memory = library->memory;
3989
3990 /* Discard client-data */
3991 if ( library->generic.finalizer )
3992 library->generic.finalizer( library );
3993
Werner Lemberg4ea0a7f2007-01-05 09:03:31 +00003994 /* Close all faces in the library. If we don't do
David Turnera8cf42b2007-01-04 16:46:46 +00003995 * this, we can have some subtle memory leaks.
Werner Lemberg4ea0a7f2007-01-05 09:03:31 +00003996 * Example:
David Turnera8cf42b2007-01-04 16:46:46 +00003997 *
3998 * - the cff font driver uses the pshinter module in cff_size_done
3999 * - if the pshinter module is destroyed before the cff font driver,
Werner Lemberg4ea0a7f2007-01-05 09:03:31 +00004000 * opened FT_Face objects managed by the driver are not properly
David Turnera8cf42b2007-01-04 16:46:46 +00004001 * destroyed, resulting in a memory leak
4002 */
4003 {
4004 FT_UInt n;
4005
Werner Lemberg4ea0a7f2007-01-05 09:03:31 +00004006
David Turnera8cf42b2007-01-04 16:46:46 +00004007 for ( n = 0; n < library->num_modules; n++ )
4008 {
4009 FT_Module module = library->modules[n];
4010 FT_List faces;
4011
Werner Lemberg4ea0a7f2007-01-05 09:03:31 +00004012
4013 if ( ( module->clazz->module_flags & FT_MODULE_FONT_DRIVER ) == 0 )
David Turnera8cf42b2007-01-04 16:46:46 +00004014 continue;
4015
4016 faces = &FT_DRIVER(module)->faces_list;
Werner Lemberg4ea0a7f2007-01-05 09:03:31 +00004017 while ( faces->head )
4018 FT_Done_Face( FT_FACE( faces->head->data ) );
David Turnera8cf42b2007-01-04 16:46:46 +00004019 }
4020 }
4021
David Turnera8cf42b2007-01-04 16:46:46 +00004022 /* Close all other modules in the library */
Werner Lembergf41e71a2001-12-20 21:22:02 +00004023#if 1
Wu, Chia-I (吳佳一)a87b08a2006-02-28 09:53:23 +00004024 /* XXX Modules are removed in the reversed order so that */
David Turner2b21a932006-08-16 09:24:32 +00004025 /* type42 module is removed before truetype module. This */
Wu, Chia-I (吳佳一)a87b08a2006-02-28 09:53:23 +00004026 /* avoids double free in some occasions. It is a hack. */
David Turnerc8087482001-12-20 13:14:18 +00004027 while ( library->num_modules > 0 )
Wu, Chia-I (吳佳一)a87b08a2006-02-28 09:53:23 +00004028 FT_Remove_Module( library,
4029 library->modules[library->num_modules - 1] );
Werner Lembergf41e71a2001-12-20 21:22:02 +00004030#else
David Turnerf0df85b2000-06-22 00:17:42 +00004031 {
Werner Lembergf41e71a2001-12-20 21:22:02 +00004032 FT_UInt n;
David Turnerf0df85b2000-06-22 00:17:42 +00004033
Werner Lemberga929ba92000-06-25 06:47:11 +00004034
Werner Lembergf41e71a2001-12-20 21:22:02 +00004035 for ( n = 0; n < library->num_modules; n++ )
David Turnerf0df85b2000-06-22 00:17:42 +00004036 {
Werner Lembergf41e71a2001-12-20 21:22:02 +00004037 FT_Module module = library->modules[n];
4038
4039
4040 if ( module )
4041 {
4042 Destroy_Module( module );
4043 library->modules[n] = 0;
4044 }
David Turnerf0df85b2000-06-22 00:17:42 +00004045 }
4046 }
David Turnerc8087482001-12-20 13:14:18 +00004047#endif
David Turnerf0df85b2000-06-22 00:17:42 +00004048
4049 /* Destroy raster objects */
David Turnere459d742002-03-22 13:52:37 +00004050 FT_FREE( library->raster_pool );
David Turnerf0df85b2000-06-22 00:17:42 +00004051 library->raster_pool_size = 0;
4052
David Turnere459d742002-03-22 13:52:37 +00004053 FT_FREE( library );
David Turnerf0df85b2000-06-22 00:17:42 +00004054 return FT_Err_Ok;
4055 }
4056
4057
Werner Lemberg748b1712005-12-25 09:15:09 +00004058 /* documentation is in ftmodapi.h */
Werner Lemberg90a03302000-11-07 17:21:11 +00004059
Werner Lembergf814d0f2001-06-27 16:18:10 +00004060 FT_EXPORT_DEF( void )
4061 FT_Set_Debug_Hook( FT_Library library,
4062 FT_UInt hook_index,
4063 FT_DebugHook_Func debug_hook )
David Turnerf0df85b2000-06-22 00:17:42 +00004064 {
4065 if ( library && debug_hook &&
4066 hook_index <
4067 ( sizeof ( library->debug_hooks ) / sizeof ( void* ) ) )
4068 library->debug_hooks[hook_index] = debug_hook;
4069 }
4070
Werner Lemberg8e6f8c42006-02-17 08:07:09 +00004071
David Turner0b5dc4d2006-02-21 22:36:23 +00004072 /* documentation is in ftmodapi.h */
4073
4074 FT_EXPORT_DEF( FT_TrueTypeEngineType )
4075 FT_Get_TrueType_Engine_Type( FT_Library library )
4076 {
4077 FT_TrueTypeEngineType result = FT_TRUETYPE_ENGINE_TYPE_NONE;
4078
Werner Lemberg5edafed2006-02-22 08:23:35 +00004079
David Turner0b5dc4d2006-02-21 22:36:23 +00004080 if ( library )
4081 {
4082 FT_Module module = FT_Get_Module( library, "truetype" );
4083
Werner Lemberg5edafed2006-02-22 08:23:35 +00004084
David Turner0b5dc4d2006-02-21 22:36:23 +00004085 if ( module )
4086 {
4087 FT_Service_TrueTypeEngine service;
4088
Werner Lemberg5edafed2006-02-22 08:23:35 +00004089
David Turner6c71c6b2006-02-25 12:49:40 +00004090 service = (FT_Service_TrueTypeEngine)
4091 ft_module_get_service( module,
4092 FT_SERVICE_ID_TRUETYPE_ENGINE );
David Turner0b5dc4d2006-02-21 22:36:23 +00004093 if ( service )
4094 result = service->engine_type;
4095 }
4096 }
Werner Lemberg5edafed2006-02-22 08:23:35 +00004097
David Turner0b5dc4d2006-02-21 22:36:23 +00004098 return result;
4099 }
4100
Werner Lemberg5edafed2006-02-22 08:23:35 +00004101
David Turnercda2d952006-02-16 22:45:31 +00004102#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
Werner Lemberg8e6f8c42006-02-17 08:07:09 +00004103
David Turnercda2d952006-02-16 22:45:31 +00004104 FT_BASE_DEF( FT_Error )
4105 ft_stub_set_char_sizes( FT_Size size,
4106 FT_F26Dot6 width,
4107 FT_F26Dot6 height,
4108 FT_UInt horz_res,
4109 FT_UInt vert_res )
4110 {
4111 FT_Size_RequestRec req;
4112 FT_Driver driver = size->face->driver;
4113
Werner Lemberg8e6f8c42006-02-17 08:07:09 +00004114
David Turnercda2d952006-02-16 22:45:31 +00004115 if ( driver->clazz->request_size )
4116 {
4117 req.type = FT_SIZE_REQUEST_TYPE_NOMINAL;
4118 req.width = width;
4119 req.height = height;
4120
4121 if ( horz_res == 0 )
4122 horz_res = vert_res;
4123
4124 if ( vert_res == 0 )
4125 vert_res = horz_res;
4126
4127 if ( horz_res == 0 )
4128 horz_res = vert_res = 72;
4129
4130 req.horiResolution = horz_res;
4131 req.vertResolution = vert_res;
4132
4133 return driver->clazz->request_size( size, &req );
4134 }
Werner Lemberg8e6f8c42006-02-17 08:07:09 +00004135
David Turnercda2d952006-02-16 22:45:31 +00004136 return 0;
4137 }
4138
4139
4140 FT_BASE_DEF( FT_Error )
Werner Lemberg8e6f8c42006-02-17 08:07:09 +00004141 ft_stub_set_pixel_sizes( FT_Size size,
4142 FT_UInt width,
4143 FT_UInt height )
David Turnercda2d952006-02-16 22:45:31 +00004144 {
4145 FT_Size_RequestRec req;
4146 FT_Driver driver = size->face->driver;
4147
Werner Lemberg8e6f8c42006-02-17 08:07:09 +00004148
David Turnercda2d952006-02-16 22:45:31 +00004149 if ( driver->clazz->request_size )
4150 {
4151 req.type = FT_SIZE_REQUEST_TYPE_NOMINAL;
Werner Lemberg8e6f8c42006-02-17 08:07:09 +00004152 req.width = width << 6;
David Turnercda2d952006-02-16 22:45:31 +00004153 req.height = height << 6;
4154 req.horiResolution = 0;
4155 req.vertResolution = 0;
4156
4157 return driver->clazz->request_size( size, &req );
4158 }
Werner Lemberg8e6f8c42006-02-17 08:07:09 +00004159
David Turnercda2d952006-02-16 22:45:31 +00004160 return 0;
4161 }
Werner Lemberg8e6f8c42006-02-17 08:07:09 +00004162
David Turnercda2d952006-02-16 22:45:31 +00004163#endif /* FT_CONFIG_OPTION_OLD_INTERNALS */
David Turnerf0df85b2000-06-22 00:17:42 +00004164
David Turner2b21a932006-08-16 09:24:32 +00004165
David Turner2ce92032006-03-23 20:58:20 +00004166 FT_EXPORT_DEF( FT_Error )
4167 FT_Get_SubGlyph_Info( FT_GlyphSlot glyph,
4168 FT_UInt sub_index,
Werner Lemberg4db32ec2006-03-24 11:54:53 +00004169 FT_Int *p_index,
4170 FT_UInt *p_flags,
4171 FT_Int *p_arg1,
4172 FT_Int *p_arg2,
4173 FT_Matrix *p_transform )
David Turner2ce92032006-03-23 20:58:20 +00004174 {
Werner Lemberg4db32ec2006-03-24 11:54:53 +00004175 FT_Error error = FT_Err_Invalid_Argument;
Werner Lemberg4db32ec2006-03-24 11:54:53 +00004176
David Turner2b21a932006-08-16 09:24:32 +00004177
4178 if ( glyph != NULL &&
Werner Lemberg4db32ec2006-03-24 11:54:53 +00004179 glyph->format == FT_GLYPH_FORMAT_COMPOSITE &&
4180 sub_index < glyph->num_subglyphs )
4181 {
David Turner2ce92032006-03-23 20:58:20 +00004182 FT_SubGlyph subg = glyph->subglyphs + sub_index;
David Turner2b21a932006-08-16 09:24:32 +00004183
Werner Lemberg4db32ec2006-03-24 11:54:53 +00004184
4185 *p_index = subg->index;
4186 *p_flags = subg->flags;
4187 *p_arg1 = subg->arg1;
4188 *p_arg2 = subg->arg2;
4189 *p_transform = subg->transform;
4190 }
4191
4192 return error;
David Turner2ce92032006-03-23 20:58:20 +00004193 }
4194
Werner Lemberg4db32ec2006-03-24 11:54:53 +00004195
David Turnerd2b1f351999-12-16 23:11:37 +00004196/* END */