blob: ed9fc96fa4a1cca74f74f2bdb80aa0878d267683 [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
637 /* load auto-hinted outline */
David Turner9657ef02002-03-14 08:49:59 +0000638 hinting = (FT_AutoHinter_Service)hinter->clazz->module_interface;
David Turner76a5f622000-11-04 01:55:49 +0000639
640 error = hinting->load_glyph( (FT_AutoHinter)hinter,
641 slot, face->size,
642 glyph_index, load_flags );
David Turner5ae831c2000-06-30 01:31:22 +0000643 }
644 else
David Turner662b3442002-01-03 16:56:59 +0000645 {
David Turner5ae831c2000-06-30 01:31:22 +0000646 error = driver->clazz->load_glyph( slot,
647 face->size,
Werner Lembergcc9fc492000-06-30 06:21:26 +0000648 glyph_index,
649 load_flags );
David Turner662b3442002-01-03 16:56:59 +0000650 if ( error )
651 goto Exit;
652
Wu, Chia-I (吳佳一)2e48a1a2006-02-27 09:18:07 +0000653 if ( slot->format == FT_GLYPH_FORMAT_OUTLINE )
654 {
655 /* check that the loaded outline is correct */
656 error = FT_Outline_Check( &slot->outline );
657 if ( error )
658 goto Exit;
659
660#ifdef GRID_FIT_METRICS
661 if ( !( load_flags & FT_LOAD_NO_HINTING ) )
662 ft_glyphslot_grid_fit_metrics( slot,
David Turnerda95af62006-03-20 13:32:33 +0000663 FT_BOOL( load_flags & FT_LOAD_VERTICAL_LAYOUT ) );
Wu, Chia-I (吳佳一)2e48a1a2006-02-27 09:18:07 +0000664#endif
665 }
David Turner662b3442002-01-03 16:56:59 +0000666 }
David Turnerf0df85b2000-06-22 00:17:42 +0000667
David Turner4937a3e2001-12-19 21:09:16 +0000668 Load_Ok:
David Turnerf0df85b2000-06-22 00:17:42 +0000669 /* compute the advance */
Werner Lemberga929ba92000-06-25 06:47:11 +0000670 if ( load_flags & FT_LOAD_VERTICAL_LAYOUT )
David Turnerf0df85b2000-06-22 00:17:42 +0000671 {
672 slot->advance.x = 0;
673 slot->advance.y = slot->metrics.vertAdvance;
674 }
675 else
676 {
677 slot->advance.x = slot->metrics.horiAdvance;
678 slot->advance.y = 0;
679 }
680
David Turnerc9ce9e42000-09-15 17:16:49 +0000681 /* compute the linear advance in 16.16 pixels */
Werner Lemberg51daa4f2003-05-18 22:40:11 +0000682 if ( ( load_flags & FT_LOAD_LINEAR_DESIGN ) == 0 &&
683 ( face->face_flags & FT_FACE_FLAG_SCALABLE ) )
David Turnerc9ce9e42000-09-15 17:16:49 +0000684 {
David Turnerc9ce9e42000-09-15 17:16:49 +0000685 FT_Size_Metrics* metrics = &face->size->metrics;
Werner Lembergeddd9902000-10-12 05:05:40 +0000686
Werner Lembergf8ba2002002-03-30 13:16:35 +0000687
Wu, Chia-I (吳佳一)e5ff0592006-01-15 06:00:49 +0000688 /* it's tricky! */
David Turnerc9ce9e42000-09-15 17:16:49 +0000689 slot->linearHoriAdvance = FT_MulDiv( slot->linearHoriAdvance,
Werner Lembergbe67c4e2003-11-24 22:54:58 +0000690 metrics->x_scale, 64 );
David Turnerc9ce9e42000-09-15 17:16:49 +0000691
692 slot->linearVertAdvance = FT_MulDiv( slot->linearVertAdvance,
Werner Lembergbe67c4e2003-11-24 22:54:58 +0000693 metrics->y_scale, 64 );
David Turnerc9ce9e42000-09-15 17:16:49 +0000694 }
695
696 if ( ( load_flags & FT_LOAD_IGNORE_TRANSFORM ) == 0 )
David Turnerf0df85b2000-06-22 00:17:42 +0000697 {
David Turner54e75742000-11-04 02:52:02 +0000698 FT_Face_Internal internal = face->internal;
David Turner61d6b2b2001-05-16 17:49:07 +0000699
700
Werner Lembergd1b74752000-08-24 16:29:15 +0000701 /* now, transform the glyph image if needed */
David Turner54e75742000-11-04 02:52:02 +0000702 if ( internal->transform_flags )
David Turner35db7322000-08-24 12:39:40 +0000703 {
704 /* get renderer */
705 FT_Renderer renderer = ft_lookup_glyph_renderer( slot );
Werner Lembergdeb4e982000-06-29 03:14:25 +0000706
Werner Lemberga929ba92000-06-25 06:47:11 +0000707
David Turner35db7322000-08-24 12:39:40 +0000708 if ( renderer )
Werner Lembergdc72aff2000-11-04 08:33:38 +0000709 error = renderer->clazz->transform_glyph(
710 renderer, slot,
711 &internal->transform_matrix,
712 &internal->transform_delta );
David Turner35db7322000-08-24 12:39:40 +0000713 /* transform advance */
David Turner54e75742000-11-04 02:52:02 +0000714 FT_Vector_Transform( &slot->advance, &internal->transform_matrix );
David Turner35db7322000-08-24 12:39:40 +0000715 }
David Turnerc9ce9e42000-09-15 17:16:49 +0000716 }
David Turnerf0df85b2000-06-22 00:17:42 +0000717
David Turnerc9ce9e42000-09-15 17:16:49 +0000718 /* do we need to render the image now? */
719 if ( !error &&
David Turnerb08fe2d2002-08-27 20:20:29 +0000720 slot->format != FT_GLYPH_FORMAT_BITMAP &&
721 slot->format != FT_GLYPH_FORMAT_COMPOSITE &&
David Turnerc9ce9e42000-09-15 17:16:49 +0000722 load_flags & FT_LOAD_RENDER )
723 {
David Turner00d9f402002-09-08 21:29:11 +0000724 FT_Render_Mode mode = FT_LOAD_TARGET_MODE( load_flags );
725
Werner Lemberg68e9f922002-09-27 11:09:23 +0000726
David Turner00d9f402002-09-08 21:29:11 +0000727 if ( mode == FT_RENDER_MODE_NORMAL &&
728 (load_flags & FT_LOAD_MONOCHROME ) )
729 mode = FT_RENDER_MODE_MONO;
730
731 error = FT_Render_Glyph( slot, mode );
Werner Lembergd060a752000-07-20 06:57:41 +0000732 }
David Turner5ae831c2000-06-30 01:31:22 +0000733
Werner Lembergdeb4e982000-06-29 03:14:25 +0000734 Exit:
David Turnerf0df85b2000-06-22 00:17:42 +0000735 return error;
736 }
737
738
Werner Lemberg90a03302000-11-07 17:21:11 +0000739 /* documentation is in freetype.h */
740
Werner Lembergf814d0f2001-06-27 16:18:10 +0000741 FT_EXPORT_DEF( FT_Error )
742 FT_Load_Char( FT_Face face,
743 FT_ULong char_code,
David Turnerf467e6a2002-08-21 21:39:28 +0000744 FT_Int32 load_flags )
David Turnerf0df85b2000-06-22 00:17:42 +0000745 {
Werner Lembergdeb4e982000-06-29 03:14:25 +0000746 FT_UInt glyph_index;
David Turnerf0df85b2000-06-22 00:17:42 +0000747
Werner Lemberga929ba92000-06-25 06:47:11 +0000748
David Turnerf0df85b2000-06-22 00:17:42 +0000749 if ( !face )
750 return FT_Err_Invalid_Face_Handle;
751
752 glyph_index = (FT_UInt)char_code;
Werner Lemberga929ba92000-06-25 06:47:11 +0000753 if ( face->charmap )
David Turnerf0df85b2000-06-22 00:17:42 +0000754 glyph_index = FT_Get_Char_Index( face, char_code );
755
David Turner5ae831c2000-06-30 01:31:22 +0000756 return FT_Load_Glyph( face, glyph_index, load_flags );
David Turnerf0df85b2000-06-22 00:17:42 +0000757 }
758
759
Werner Lemberg7880dd62000-01-10 17:19:45 +0000760 /* destructor for sizes list */
Werner Lembergf814d0f2001-06-27 16:18:10 +0000761 static void
762 destroy_size( FT_Memory memory,
763 FT_Size size,
764 FT_Driver driver )
Werner Lemberg7880dd62000-01-10 17:19:45 +0000765 {
David Turnerf0df85b2000-06-22 00:17:42 +0000766 /* finalize client-specific data */
Werner Lemberga929ba92000-06-25 06:47:11 +0000767 if ( size->generic.finalizer )
David Turnerf0df85b2000-06-22 00:17:42 +0000768 size->generic.finalizer( size );
769
Werner Lemberg7880dd62000-01-10 17:19:45 +0000770 /* finalize format-specific stuff */
Werner Lemberga929ba92000-06-25 06:47:11 +0000771 if ( driver->clazz->done_size )
David Turnerf0df85b2000-06-22 00:17:42 +0000772 driver->clazz->done_size( size );
773
David Turnere459d742002-03-22 13:52:37 +0000774 FT_FREE( size->internal );
775 FT_FREE( size );
Werner Lemberg7880dd62000-01-10 17:19:45 +0000776 }
David Turnerd2b1f351999-12-16 23:11:37 +0000777
778
Werner Lemberg4338dab2004-01-05 14:41:59 +0000779 static void
Werner Lemberge70371c2005-05-27 06:01:28 +0000780 ft_cmap_done_internal( FT_CMap cmap );
781
782
783 static void
Werner Lemberg4338dab2004-01-05 14:41:59 +0000784 destroy_charmaps( FT_Face face,
785 FT_Memory memory )
786 {
787 FT_Int n;
788
789
Werner Lemberg3d507fe2007-06-03 16:54:55 +0000790 if ( !face )
791 return;
792
Werner Lemberg4338dab2004-01-05 14:41:59 +0000793 for ( n = 0; n < face->num_charmaps; n++ )
794 {
795 FT_CMap cmap = FT_CMAP( face->charmaps[n] );
796
797
Werner Lemberge70371c2005-05-27 06:01:28 +0000798 ft_cmap_done_internal( cmap );
Werner Lemberg4338dab2004-01-05 14:41:59 +0000799
800 face->charmaps[n] = NULL;
801 }
802
803 FT_FREE( face->charmaps );
804 face->num_charmaps = 0;
805 }
806
807
Werner Lemberg7880dd62000-01-10 17:19:45 +0000808 /* destructor for faces list */
Werner Lembergf814d0f2001-06-27 16:18:10 +0000809 static void
810 destroy_face( FT_Memory memory,
811 FT_Face face,
812 FT_Driver driver )
Werner Lemberg7880dd62000-01-10 17:19:45 +0000813 {
David Turneref3c1262002-03-14 09:22:48 +0000814 FT_Driver_Class clazz = driver->clazz;
David Turnerf0df85b2000-06-22 00:17:42 +0000815
Werner Lembergd060a752000-07-20 06:57:41 +0000816
David Turnerc49f69c2000-07-20 03:44:50 +0000817 /* discard auto-hinting data */
818 if ( face->autohint.finalizer )
819 face->autohint.finalizer( face->autohint.data );
Werner Lembergeddd9902000-10-12 05:05:40 +0000820
Werner Lembergf8ba2002002-03-30 13:16:35 +0000821 /* Discard glyph slots for this face. */
David Turner23bcde12001-10-17 13:48:10 +0000822 /* Beware! FT_Done_GlyphSlot() changes the field `face->glyph' */
Werner Lemberg7880dd62000-01-10 17:19:45 +0000823 while ( face->glyph )
824 FT_Done_GlyphSlot( face->glyph );
825
Werner Lembergf8ba2002002-03-30 13:16:35 +0000826 /* discard all sizes for this face */
Werner Lemberg7880dd62000-01-10 17:19:45 +0000827 FT_List_Finalize( &face->sizes_list,
Werner Lemberg74184152003-10-18 16:56:13 +0000828 (FT_List_Destructor)destroy_size,
829 memory,
830 driver );
Werner Lemberg7880dd62000-01-10 17:19:45 +0000831 face->size = 0;
832
Werner Lembergf8ba2002002-03-30 13:16:35 +0000833 /* now discard client data */
Werner Lemberg7880dd62000-01-10 17:19:45 +0000834 if ( face->generic.finalizer )
835 face->generic.finalizer( face );
836
David Turner2ded2c12002-03-22 22:37:40 +0000837 /* discard charmaps */
Werner Lemberg4338dab2004-01-05 14:41:59 +0000838 destroy_charmaps( face, memory );
Werner Lemberg75435332004-02-25 12:58:54 +0000839
David Turnerf0df85b2000-06-22 00:17:42 +0000840 /* finalize format-specific stuff */
Werner Lemberga929ba92000-06-25 06:47:11 +0000841 if ( clazz->done_face )
842 clazz->done_face( face );
David Turnerf0df85b2000-06-22 00:17:42 +0000843
844 /* close the stream for this face if needed */
Werner Lemberg75435332004-02-25 12:58:54 +0000845 FT_Stream_Free(
Werner Lembergf8ba2002002-03-30 13:16:35 +0000846 face->stream,
Werner Lemberg58b17f92000-07-27 23:29:08 +0000847 ( face->face_flags & FT_FACE_FLAG_EXTERNAL_STREAM ) != 0 );
David Turner7663f222000-02-13 13:37:38 +0000848
David Turner53b3fa12002-02-24 05:26:57 +0000849 face->stream = 0;
850
Werner Lemberg7880dd62000-01-10 17:19:45 +0000851 /* get rid of it */
David Turner23bcde12001-10-17 13:48:10 +0000852 if ( face->internal )
853 {
David Turnere459d742002-03-22 13:52:37 +0000854 FT_FREE( face->internal );
David Turner23bcde12001-10-17 13:48:10 +0000855 }
David Turnere459d742002-03-22 13:52:37 +0000856 FT_FREE( face );
Werner Lemberg7880dd62000-01-10 17:19:45 +0000857 }
David Turnerd2b1f351999-12-16 23:11:37 +0000858
859
Werner Lembergf814d0f2001-06-27 16:18:10 +0000860 static void
861 Destroy_Driver( FT_Driver driver )
David Turnerd2b1f351999-12-16 23:11:37 +0000862 {
David Turnerd2b1f351999-12-16 23:11:37 +0000863 FT_List_Finalize( &driver->faces_list,
864 (FT_List_Destructor)destroy_face,
David Turnerf0df85b2000-06-22 00:17:42 +0000865 driver->root.memory,
David Turnerd2b1f351999-12-16 23:11:37 +0000866 driver );
867
Werner Lembergdeb4e982000-06-29 03:14:25 +0000868 /* check whether we need to drop the driver's glyph loader */
Werner Lemberga929ba92000-06-25 06:47:11 +0000869 if ( FT_DRIVER_USES_OUTLINES( driver ) )
David Turnerf0df85b2000-06-22 00:17:42 +0000870 FT_GlyphLoader_Done( driver->glyph_loader );
David Turnerd2b1f351999-12-16 23:11:37 +0000871 }
872
873
Werner Lemberg547a2522000-02-16 08:23:58 +0000874 /*************************************************************************/
875 /* */
876 /* <Function> */
Antoine Lecac96f69d2002-12-03 00:39:16 +0000877 /* find_unicode_charmap */
878 /* */
879 /* <Description> */
880 /* This function finds a Unicode charmap, if there is one. */
881 /* And if there is more than one, it tries to favour the more */
Werner Lembergc8c6bf52003-04-23 05:38:13 +0000882 /* extensive one, i.e., one that supports UCS-4 against those which */
Antoine Lecac96f69d2002-12-03 00:39:16 +0000883 /* are limited to the BMP (said UCS-2 encoding.) */
884 /* */
885 /* This function is called from open_face() (just below), and also */
Werner Lemberg74597cc2007-10-01 07:08:56 +0000886 /* from FT_Select_Charmap( ..., FT_ENCODING_UNICODE ). */
Antoine Lecac96f69d2002-12-03 00:39:16 +0000887 /* */
888 static FT_Error
889 find_unicode_charmap( FT_Face face )
890 {
891 FT_CharMap* first;
892 FT_CharMap* cur;
Antoine Lecac96f69d2002-12-03 00:39:16 +0000893
894
895 /* caller should have already checked that `face' is valid */
Werner Lemberg74184152003-10-18 16:56:13 +0000896 FT_ASSERT( face );
Antoine Lecac96f69d2002-12-03 00:39:16 +0000897
898 first = face->charmaps;
899
900 if ( !first )
901 return FT_Err_Invalid_CharMap_Handle;
902
David Turnerc528f6f2002-12-18 22:43:07 +0000903 /*
Werner Lembergc8c6bf52003-04-23 05:38:13 +0000904 * The original TrueType specification(s) only specified charmap
David Turnerc528f6f2002-12-18 22:43:07 +0000905 * formats that are capable of mapping 8 or 16 bit character codes to
906 * glyph indices.
907 *
Werner Lembergc8c6bf52003-04-23 05:38:13 +0000908 * However, recent updates to the Apple and OpenType specifications
David Turnerc528f6f2002-12-18 22:43:07 +0000909 * introduced new formats that are capable of mapping 32-bit character
Werner Lembergc8c6bf52003-04-23 05:38:13 +0000910 * codes as well. And these are already used on some fonts, mainly to
David Turnerae26c682003-02-25 20:37:50 +0000911 * map non-BMP Asian ideographs as defined in Unicode.
David Turnerc528f6f2002-12-18 22:43:07 +0000912 *
Werner Lembergc8c6bf52003-04-23 05:38:13 +0000913 * For compatibility purposes, these fonts generally come with
David Turnerc528f6f2002-12-18 22:43:07 +0000914 * *several* Unicode charmaps:
915 *
Werner Lembergc8c6bf52003-04-23 05:38:13 +0000916 * - One of them in the "old" 16-bit format, that cannot access
917 * all glyphs in the font.
David Turnerc528f6f2002-12-18 22:43:07 +0000918 *
Werner Lembergc8c6bf52003-04-23 05:38:13 +0000919 * - Another one in the "new" 32-bit format, that can access all
David Turnerc528f6f2002-12-18 22:43:07 +0000920 * the glyphs.
921 *
Werner Lembergc8c6bf52003-04-23 05:38:13 +0000922 * This function has been written to always favor a 32-bit charmap
923 * when found. Otherwise, a 16-bit one is returned when found.
David Turnerc528f6f2002-12-18 22:43:07 +0000924 */
925
Werner Lemberg8acb8672005-03-08 11:43:36 +0000926 /* Since the `interesting' table, with IDs (3,10), is normally the */
Werner Lemberg1e259de2007-03-08 15:39:21 +0000927 /* last one, we loop backwards. This loses with type1 fonts with */
Werner Lemberg8acb8672005-03-08 11:43:36 +0000928 /* non-BMP characters (<.0001%), this wins with .ttf with non-BMP */
929 /* chars (.01% ?), and this is the same about 99.99% of the time! */
Antoine Lecac96f69d2002-12-03 00:39:16 +0000930
931 cur = first + face->num_charmaps; /* points after the last one */
932
933 for ( ; --cur >= first; )
934 {
935 if ( cur[0]->encoding == FT_ENCODING_UNICODE )
936 {
Werner Lemberg74597cc2007-10-01 07:08:56 +0000937 /* XXX If some new encodings to represent UCS-4 are added, */
938 /* they should be added here. */
David Turnerc528f6f2002-12-18 22:43:07 +0000939 if ( ( cur[0]->platform_id == TT_PLATFORM_MICROSOFT &&
Werner Lemberg74597cc2007-10-01 07:08:56 +0000940 cur[0]->encoding_id == TT_MS_ID_UCS_4 ) ||
David Turnerc528f6f2002-12-18 22:43:07 +0000941 ( cur[0]->platform_id == TT_PLATFORM_APPLE_UNICODE &&
Werner Lemberg74597cc2007-10-01 07:08:56 +0000942 cur[0]->encoding_id == TT_APPLE_ID_UNICODE_32 ) )
Antoine Lecac96f69d2002-12-03 00:39:16 +0000943 {
944 face->charmap = cur[0];
Werner Lemberg74597cc2007-10-01 07:08:56 +0000945 return FT_Err_Ok;
Antoine Lecac96f69d2002-12-03 00:39:16 +0000946 }
947 }
948 }
949
Werner Lemberg74597cc2007-10-01 07:08:56 +0000950 /* We do not have any UCS-4 charmap. */
951 /* Do the loop again and search for UCS-2 charmaps. */
952 cur = first + face->num_charmaps;
953
954 for ( ; --cur >= first; )
Antoine Lecac96f69d2002-12-03 00:39:16 +0000955 {
Werner Lemberg74597cc2007-10-01 07:08:56 +0000956 if ( cur[0]->encoding == FT_ENCODING_UNICODE )
957 {
958 face->charmap = cur[0];
959 return FT_Err_Ok;
960 }
Antoine Lecac96f69d2002-12-03 00:39:16 +0000961 }
962
David Turner6453a812003-01-08 09:28:34 +0000963 return FT_Err_Invalid_CharMap_Handle;
Antoine Lecac96f69d2002-12-03 00:39:16 +0000964 }
965
966
967 /*************************************************************************/
968 /* */
969 /* <Function> */
Werner Lemberg9a966b72007-10-15 17:21:32 +0000970 /* find_variant_selector_charmap */
971 /* */
972 /* <Description> */
973 /* This function finds the variant selector charmap, if there is one. */
974 /* There can only be one (platform=0, specific=5, format=14). */
975 /* */
976 static FT_CharMap
977 find_variant_selector_charmap( FT_Face face )
978 {
979 FT_CharMap* first;
980 FT_CharMap* end;
981 FT_CharMap* cur;
982
983
984 /* caller should have already checked that `face' is valid */
985 FT_ASSERT( face );
986
987 first = face->charmaps;
988
989 if ( !first )
990 return NULL;
991
992 end = first + face->num_charmaps; /* points after the last one */
993
994 for ( cur = first; cur < end; ++cur )
995 {
996 if ( cur[0]->platform_id == TT_PLATFORM_APPLE_UNICODE &&
997 cur[0]->encoding_id == TT_APPLE_ID_VARIANT_SELECTOR &&
998 FT_Get_CMap_Format( cur[0] ) == 14 )
999 return cur[0];
1000 }
1001
1002 return NULL;
1003 }
1004
1005
1006 /*************************************************************************/
1007 /* */
1008 /* <Function> */
Werner Lemberg547a2522000-02-16 08:23:58 +00001009 /* open_face */
1010 /* */
1011 /* <Description> */
1012 /* This function does some work for FT_Open_Face(). */
1013 /* */
Werner Lembergf814d0f2001-06-27 16:18:10 +00001014 static FT_Error
1015 open_face( FT_Driver driver,
1016 FT_Stream stream,
1017 FT_Long face_index,
1018 FT_Int num_params,
1019 FT_Parameter* params,
Werner Lemberg6d798992003-07-01 07:28:55 +00001020 FT_Face *aface )
David Turnerd2b1f351999-12-16 23:11:37 +00001021 {
David Turnerf0df85b2000-06-22 00:17:42 +00001022 FT_Memory memory;
Werner Lemberg77c34b82003-05-20 22:06:38 +00001023 FT_Driver_Class clazz;
David Turnerf0df85b2000-06-22 00:17:42 +00001024 FT_Face face = 0;
Antoine Lecac96f69d2002-12-03 00:39:16 +00001025 FT_Error error, error2;
David Turner6a681fa2006-01-27 12:11:22 +00001026 FT_Face_Internal internal = NULL;
David Turnerd2b1f351999-12-16 23:11:37 +00001027
Werner Lemberg3c403e42002-08-06 21:47:40 +00001028
David Turnerf0df85b2000-06-22 00:17:42 +00001029 clazz = driver->clazz;
1030 memory = driver->root.memory;
David Turnerd2b1f351999-12-16 23:11:37 +00001031
Werner Lembergdeb4e982000-06-29 03:14:25 +00001032 /* allocate the face object and perform basic initialization */
David Turnere459d742002-03-22 13:52:37 +00001033 if ( FT_ALLOC( face, clazz->face_object_size ) )
David Turnerd2b1f351999-12-16 23:11:37 +00001034 goto Fail;
1035
David Turnere459d742002-03-22 13:52:37 +00001036 if ( FT_NEW( internal ) )
David Turner54e75742000-11-04 02:52:02 +00001037 goto Fail;
David Turner61d6b2b2001-05-16 17:49:07 +00001038
David Turner54e75742000-11-04 02:52:02 +00001039 face->internal = internal;
1040
1041 face->driver = driver;
1042 face->memory = memory;
1043 face->stream = stream;
Graham Asherce121822002-08-01 15:29:17 +00001044
Graham Asherd53cf1d2002-07-18 15:04:29 +00001045#ifdef FT_CONFIG_OPTION_INCREMENTAL
Werner Lemberg3c403e42002-08-06 21:47:40 +00001046 {
1047 int i;
1048
1049
1050 face->internal->incremental_interface = 0;
1051 for ( i = 0; i < num_params && !face->internal->incremental_interface;
1052 i++ )
1053 if ( params[i].tag == FT_PARAM_TAG_INCREMENTAL )
Werner Lemberg1e1b6df2007-07-07 07:30:40 +00001054 face->internal->incremental_interface =
1055 (FT_Incremental_Interface)params[i].data;
Antoine Lecac96f69d2002-12-03 00:39:16 +00001056 }
Graham Asherd53cf1d2002-07-18 15:04:29 +00001057#endif
David Turnerd2b1f351999-12-16 23:11:37 +00001058
David Turnerf0df85b2000-06-22 00:17:42 +00001059 error = clazz->init_face( stream,
1060 face,
Werner Lemberg68e9f922002-09-27 11:09:23 +00001061 (FT_Int)face_index,
David Turnerf0df85b2000-06-22 00:17:42 +00001062 num_params,
1063 params );
David Turnerd2b1f351999-12-16 23:11:37 +00001064 if ( error )
1065 goto Fail;
1066
David Turnerfed59b72002-07-17 22:51:06 +00001067 /* select Unicode charmap by default */
Antoine Lecac96f69d2002-12-03 00:39:16 +00001068 error2 = find_unicode_charmap( face );
David Turnerc528f6f2002-12-18 22:43:07 +00001069
Werner Lemberg6d798992003-07-01 07:28:55 +00001070 /* if no Unicode charmap can be found, FT_Err_Invalid_CharMap_Handle */
1071 /* is returned. */
Antoine Lecac96f69d2002-12-03 00:39:16 +00001072
Werner Lemberg6d798992003-07-01 07:28:55 +00001073 /* no error should happen, but we want to play safe */
David Turnerc528f6f2002-12-18 22:43:07 +00001074 if ( error2 && error2 != FT_Err_Invalid_CharMap_Handle )
David Turnerfed59b72002-07-17 22:51:06 +00001075 {
Antoine Lecac96f69d2002-12-03 00:39:16 +00001076 error = error2;
1077 goto Fail;
David Turnerfed59b72002-07-17 22:51:06 +00001078 }
1079
David Turnerd2b1f351999-12-16 23:11:37 +00001080 *aface = face;
1081
1082 Fail:
1083 if ( error )
1084 {
Werner Lemberg4338dab2004-01-05 14:41:59 +00001085 destroy_charmaps( face, memory );
David Turnerf0df85b2000-06-22 00:17:42 +00001086 clazz->done_face( face );
Werner Lemberg77c34b82003-05-20 22:06:38 +00001087 FT_FREE( internal );
David Turnere459d742002-03-22 13:52:37 +00001088 FT_FREE( face );
David Turnerd2b1f351999-12-16 23:11:37 +00001089 *aface = 0;
1090 }
1091
1092 return error;
1093 }
1094
1095
Werner Lemberg05c21b82000-07-29 20:38:19 +00001096 /* there's a Mac-specific extended implementation of FT_New_Face() */
Werner Lemberg4d631e42002-05-27 13:02:37 +00001097 /* in src/base/ftmac.c */
Werner Lemberg05c21b82000-07-29 20:38:19 +00001098
Werner Lemberg9ca7a152002-04-30 14:26:49 +00001099#ifndef FT_MACINTOSH
Just van Rossum9e830c52000-07-28 01:12:34 +00001100
Werner Lemberg90a03302000-11-07 17:21:11 +00001101 /* documentation is in freetype.h */
1102
Werner Lembergf814d0f2001-06-27 16:18:10 +00001103 FT_EXPORT_DEF( FT_Error )
1104 FT_New_Face( FT_Library library,
1105 const char* pathname,
1106 FT_Long face_index,
1107 FT_Face *aface )
David Turnerd2b1f351999-12-16 23:11:37 +00001108 {
David Turner37379e22000-03-28 11:22:31 +00001109 FT_Open_Args args;
Werner Lemberg547a2522000-02-16 08:23:58 +00001110
Werner Lemberga929ba92000-06-25 06:47:11 +00001111
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001112 /* test for valid `library' and `aface' delayed to FT_Open_Face() */
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001113 if ( !pathname )
1114 return FT_Err_Invalid_Argument;
1115
David Turnerb08fe2d2002-08-27 20:20:29 +00001116 args.flags = FT_OPEN_PATHNAME;
David Turner4f2c5542000-05-12 10:19:41 +00001117 args.pathname = (char*)pathname;
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001118
David Turnercda32b72000-02-10 16:14:35 +00001119 return FT_Open_Face( library, &args, face_index, aface );
David Turnerd2b1f351999-12-16 23:11:37 +00001120 }
1121
Werner Lemberg9ca7a152002-04-30 14:26:49 +00001122#endif /* !FT_MACINTOSH */
Just van Rossum9e830c52000-07-28 01:12:34 +00001123
Werner Lemberg7880dd62000-01-10 17:19:45 +00001124
Werner Lemberg90a03302000-11-07 17:21:11 +00001125 /* documentation is in freetype.h */
1126
Werner Lembergf814d0f2001-06-27 16:18:10 +00001127 FT_EXPORT_DEF( FT_Error )
1128 FT_New_Memory_Face( FT_Library library,
1129 const FT_Byte* file_base,
1130 FT_Long file_size,
1131 FT_Long face_index,
1132 FT_Face *aface )
David Turnerd2b1f351999-12-16 23:11:37 +00001133 {
David Turner37379e22000-03-28 11:22:31 +00001134 FT_Open_Args args;
Werner Lemberg7880dd62000-01-10 17:19:45 +00001135
Werner Lemberga929ba92000-06-25 06:47:11 +00001136
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001137 /* test for valid `library' and `face' delayed to FT_Open_Face() */
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001138 if ( !file_base )
1139 return FT_Err_Invalid_Argument;
1140
David Turnerb08fe2d2002-08-27 20:20:29 +00001141 args.flags = FT_OPEN_MEMORY;
David Turnercda32b72000-02-10 16:14:35 +00001142 args.memory_base = file_base;
1143 args.memory_size = file_size;
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001144
Werner Lemberg4b680072000-11-07 06:30:29 +00001145 return FT_Open_Face( library, &args, face_index, aface );
David Turnerd2b1f351999-12-16 23:11:37 +00001146 }
1147
Werner Lemberg7880dd62000-01-10 17:19:45 +00001148
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001149#if !defined( FT_MACINTOSH ) && defined( FT_CONFIG_OPTION_MAC_FONTS )
1150
1151 /* The behavior here is very similar to that in base/ftmac.c, but it */
1152 /* is designed to work on non-mac systems, so no mac specific calls. */
1153 /* */
1154 /* We look at the file and determine if it is a mac dfont file or a mac */
1155 /* resource file, or a macbinary file containing a mac resource file. */
1156 /* */
1157 /* Unlike ftmac I'm not going to look at a `FOND'. I don't really see */
1158 /* the point, especially since there may be multiple `FOND' resources. */
1159 /* Instead I'll just look for `sfnt' and `POST' resources, ordered as */
1160 /* they occur in the file. */
1161 /* */
1162 /* Note that multiple `POST' resources do not mean multiple postscript */
1163 /* fonts; they all get jammed together to make what is essentially a */
1164 /* pfb file. */
1165 /* */
1166 /* We aren't interested in `NFNT' or `FONT' bitmap resources. */
1167 /* */
1168 /* As soon as we get an `sfnt' load it into memory and pass it off to */
1169 /* FT_Open_Face. */
1170 /* */
1171 /* If we have a (set of) `POST' resources, massage them into a (memory) */
1172 /* pfb file and pass that to FT_Open_Face. (As with ftmac.c I'm not */
1173 /* going to try to save the kerning info. After all that lives in the */
1174 /* `FOND' which isn't in the file containing the `POST' resources so */
1175 /* we don't really have access to it. */
1176
1177
1178 /* Finalizer for a memory stream; gets called by FT_Done_Face().
1179 It frees the memory it uses. */
1180 /* from ftmac.c */
1181 static void
1182 memory_stream_close( FT_Stream stream )
1183 {
1184 FT_Memory memory = stream->memory;
1185
1186
1187 FT_FREE( stream->base );
1188
1189 stream->size = 0;
1190 stream->base = 0;
1191 stream->close = 0;
1192 }
1193
1194
1195 /* Create a new memory stream from a buffer and a size. */
1196 /* from ftmac.c */
1197 static FT_Error
1198 new_memory_stream( FT_Library library,
1199 FT_Byte* base,
1200 FT_ULong size,
1201 FT_Stream_CloseFunc close,
1202 FT_Stream *astream )
1203 {
1204 FT_Error error;
1205 FT_Memory memory;
1206 FT_Stream stream;
1207
1208
1209 if ( !library )
1210 return FT_Err_Invalid_Library_Handle;
1211
1212 if ( !base )
1213 return FT_Err_Invalid_Argument;
1214
1215 *astream = 0;
1216 memory = library->memory;
1217 if ( FT_NEW( stream ) )
1218 goto Exit;
1219
1220 FT_Stream_OpenMemory( stream, base, size );
1221
1222 stream->close = close;
1223
1224 *astream = stream;
1225
1226 Exit:
1227 return error;
1228 }
1229
1230
1231 /* Create a new FT_Face given a buffer and a driver name. */
1232 /* from ftmac.c */
1233 static FT_Error
1234 open_face_from_buffer( FT_Library library,
1235 FT_Byte* base,
1236 FT_ULong size,
1237 FT_Long face_index,
1238 const char* driver_name,
1239 FT_Face *aface )
1240 {
1241 FT_Open_Args args;
1242 FT_Error error;
Werner Lemberg607dec72007-05-15 06:49:37 +00001243 FT_Stream stream = NULL;
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001244 FT_Memory memory = library->memory;
1245
1246
1247 error = new_memory_stream( library,
1248 base,
1249 size,
1250 memory_stream_close,
1251 &stream );
1252 if ( error )
1253 {
1254 FT_FREE( base );
1255 return error;
1256 }
1257
1258 args.flags = FT_OPEN_STREAM;
1259 args.stream = stream;
1260 if ( driver_name )
1261 {
Werner Lemberg7a024102003-06-18 06:59:57 +00001262 args.flags = args.flags | FT_OPEN_DRIVER;
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001263 args.driver = FT_Get_Module( library, driver_name );
1264 }
1265
1266 error = FT_Open_Face( library, &args, face_index, aface );
1267
1268 if ( error == FT_Err_Ok )
1269 (*aface)->face_flags &= ~FT_FACE_FLAG_EXTERNAL_STREAM;
1270 else
1271 {
1272 FT_Stream_Close( stream );
1273 FT_FREE( stream );
1274 }
1275
1276 return error;
1277 }
1278
1279
1280 /* The resource header says we've got resource_cnt `POST' (type1) */
1281 /* resources in this file. They all need to be coalesced into */
1282 /* one lump which gets passed on to the type1 driver. */
1283 /* Here can be only one PostScript font in a file so face_index */
1284 /* must be 0 (or -1). */
1285 /* */
1286 static FT_Error
1287 Mac_Read_POST_Resource( FT_Library library,
1288 FT_Stream stream,
Werner Lemberg75435332004-02-25 12:58:54 +00001289 FT_Long *offsets,
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001290 FT_Long resource_cnt,
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001291 FT_Long face_index,
1292 FT_Face *aface )
1293 {
1294 FT_Error error = FT_Err_Cannot_Open_Resource;
1295 FT_Memory memory = library->memory;
1296 FT_Byte* pfb_data;
Werner Lembergdc8ad542003-12-09 02:12:14 +00001297 int i, type, flags;
1298 FT_Long len;
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001299 FT_Long pfb_len, pfb_pos, pfb_lenpos;
Werner Lembergdc8ad542003-12-09 02:12:14 +00001300 FT_Long rlen, temp;
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001301
1302
1303 if ( face_index == -1 )
1304 face_index = 0;
1305 if ( face_index != 0 )
Werner Lemberg77c34b82003-05-20 22:06:38 +00001306 return error;
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001307
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001308 /* Find the length of all the POST resources, concatenated. Assume */
1309 /* worst case (each resource in its own section). */
1310 pfb_len = 0;
1311 for ( i = 0; i < resource_cnt; ++i )
1312 {
1313 error = FT_Stream_Seek( stream, offsets[i] );
1314 if ( error )
1315 goto Exit;
1316 if ( FT_READ_LONG( temp ) )
1317 goto Exit;
1318 pfb_len += temp + 6;
1319 }
1320
1321 if ( FT_ALLOC( pfb_data, (FT_Long)pfb_len + 2 ) )
1322 goto Exit;
1323
David Turnerc313c502003-09-11 19:51:54 +00001324 pfb_data[0] = 0x80;
1325 pfb_data[1] = 1; /* Ascii section */
1326 pfb_data[2] = 0; /* 4-byte length, fill in later */
1327 pfb_data[3] = 0;
1328 pfb_data[4] = 0;
1329 pfb_data[5] = 0;
Suzuki, Toshiya (鈴木俊哉)a2295402006-04-30 04:46:17 +00001330 pfb_pos = 6;
David Turnere2d12842003-09-21 17:15:55 +00001331 pfb_lenpos = 2;
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001332
1333 len = 0;
1334 type = 1;
1335 for ( i = 0; i < resource_cnt; ++i )
1336 {
1337 error = FT_Stream_Seek( stream, offsets[i] );
1338 if ( error )
1339 goto Exit2;
1340 if ( FT_READ_LONG( rlen ) )
1341 goto Exit;
1342 if ( FT_READ_USHORT( flags ) )
1343 goto Exit;
1344 rlen -= 2; /* the flags are part of the resource */
1345 if ( ( flags >> 8 ) == type )
1346 len += rlen;
1347 else
1348 {
David Turnerc313c502003-09-11 19:51:54 +00001349 pfb_data[pfb_lenpos ] = (FT_Byte)( len );
1350 pfb_data[pfb_lenpos + 1] = (FT_Byte)( len >> 8 );
1351 pfb_data[pfb_lenpos + 2] = (FT_Byte)( len >> 16 );
1352 pfb_data[pfb_lenpos + 3] = (FT_Byte)( len >> 24 );
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001353
1354 if ( ( flags >> 8 ) == 5 ) /* End of font mark */
1355 break;
1356
1357 pfb_data[pfb_pos++] = 0x80;
1358
1359 type = flags >> 8;
1360 len = rlen;
1361
Werner Lemberg013efd12003-09-17 05:26:33 +00001362 pfb_data[pfb_pos++] = (FT_Byte)type;
Suzuki, Toshiya (鈴木俊哉)a2295402006-04-30 04:46:17 +00001363 pfb_lenpos = pfb_pos;
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001364 pfb_data[pfb_pos++] = 0; /* 4-byte length, fill in later */
1365 pfb_data[pfb_pos++] = 0;
1366 pfb_data[pfb_pos++] = 0;
1367 pfb_data[pfb_pos++] = 0;
1368 }
1369
1370 error = FT_Stream_Read( stream, (FT_Byte *)pfb_data + pfb_pos, rlen );
1371 pfb_pos += rlen;
1372 }
1373
1374 pfb_data[pfb_pos++] = 0x80;
1375 pfb_data[pfb_pos++] = 3;
1376
David Turnerc313c502003-09-11 19:51:54 +00001377 pfb_data[pfb_lenpos ] = (FT_Byte)( len );
1378 pfb_data[pfb_lenpos + 1] = (FT_Byte)( len >> 8 );
1379 pfb_data[pfb_lenpos + 2] = (FT_Byte)( len >> 16 );
1380 pfb_data[pfb_lenpos + 3] = (FT_Byte)( len >> 24 );
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001381
1382 return open_face_from_buffer( library,
1383 pfb_data,
1384 pfb_pos,
1385 face_index,
1386 "type1",
1387 aface );
1388
1389 Exit2:
1390 FT_FREE( pfb_data );
1391
1392 Exit:
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001393 return error;
1394 }
1395
1396
1397 /* The resource header says we've got resource_cnt `sfnt' */
1398 /* (TrueType/OpenType) resources in this file. Look through */
1399 /* them for the one indicated by face_index, load it into mem, */
1400 /* pass it on the the truetype driver and return it. */
1401 /* */
1402 static FT_Error
1403 Mac_Read_sfnt_Resource( FT_Library library,
1404 FT_Stream stream,
Werner Lemberg75435332004-02-25 12:58:54 +00001405 FT_Long *offsets,
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001406 FT_Long resource_cnt,
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001407 FT_Long face_index,
1408 FT_Face *aface )
1409 {
1410 FT_Memory memory = library->memory;
1411 FT_Byte* sfnt_data;
1412 FT_Error error;
Werner Lemberg75435332004-02-25 12:58:54 +00001413 FT_Long flag_offset;
Werner Lembergdc8ad542003-12-09 02:12:14 +00001414 FT_Long rlen;
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001415 int is_cff;
Suzuki, Toshiya (鈴木俊哉)7a7d4032006-12-15 14:47:42 +00001416 FT_Long face_index_in_resource = 0;
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001417
1418
1419 if ( face_index == -1 )
1420 face_index = 0;
1421 if ( face_index >= resource_cnt )
1422 return FT_Err_Cannot_Open_Resource;
1423
Werner Lemberg75435332004-02-25 12:58:54 +00001424 flag_offset = offsets[face_index];
1425 error = FT_Stream_Seek( stream, flag_offset );
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001426 if ( error )
1427 goto Exit;
1428
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001429 if ( FT_READ_LONG( rlen ) )
1430 goto Exit;
1431 if ( rlen == -1 )
1432 return FT_Err_Cannot_Open_Resource;
1433
1434 if ( FT_ALLOC( sfnt_data, (FT_Long)rlen ) )
1435 return error;
1436 error = FT_Stream_Read( stream, (FT_Byte *)sfnt_data, rlen );
1437 if ( error )
1438 goto Exit;
1439
1440 is_cff = rlen > 4 && sfnt_data[0] == 'O' &&
1441 sfnt_data[1] == 'T' &&
1442 sfnt_data[2] == 'T' &&
1443 sfnt_data[3] == 'O';
1444
1445 error = open_face_from_buffer( library,
1446 sfnt_data,
1447 rlen,
Suzuki, Toshiya (鈴木俊哉)7a7d4032006-12-15 14:47:42 +00001448 face_index_in_resource,
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001449 is_cff ? "cff" : "truetype",
1450 aface );
1451
1452 Exit:
1453 return error;
1454 }
1455
1456
1457 /* Check for a valid resource fork header, or a valid dfont */
1458 /* header. In a resource fork the first 16 bytes are repeated */
1459 /* at the location specified by bytes 4-7. In a dfont bytes */
1460 /* 4-7 point to 16 bytes of zeroes instead. */
1461 /* */
1462 static FT_Error
1463 IsMacResource( FT_Library library,
1464 FT_Stream stream,
1465 FT_Long resource_offset,
1466 FT_Long face_index,
1467 FT_Face *aface )
1468 {
Werner Lemberg75435332004-02-25 12:58:54 +00001469 FT_Memory memory = library->memory;
1470 FT_Error error;
1471 FT_Long map_offset, rdara_pos;
1472 FT_Long *data_offsets;
1473 FT_Long count;
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001474
1475
Werner Lemberg75435332004-02-25 12:58:54 +00001476 error = FT_Raccess_Get_HeaderInfo( library, stream, resource_offset,
1477 &map_offset, &rdara_pos );
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001478 if ( error )
Werner Lemberg75435332004-02-25 12:58:54 +00001479 return error;
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001480
Werner Lemberg75435332004-02-25 12:58:54 +00001481 error = FT_Raccess_Get_DataOffsets( library, stream,
1482 map_offset, rdara_pos,
1483 FT_MAKE_TAG( 'P', 'O', 'S', 'T' ),
1484 &data_offsets, &count );
1485 if ( !error )
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001486 {
Werner Lemberg75435332004-02-25 12:58:54 +00001487 error = Mac_Read_POST_Resource( library, stream, data_offsets, count,
1488 face_index, aface );
1489 FT_FREE( data_offsets );
Werner Lemberg0fd08bd2006-12-16 02:57:46 +00001490 /* POST exists in an LWFN providing a single face */
Werner Lemberg17432b52007-01-12 09:28:44 +00001491 if ( !error )
David Turner7a3c5642007-01-11 15:09:01 +00001492 (*aface)->num_faces = 1;
Werner Lemberg75435332004-02-25 12:58:54 +00001493 return error;
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001494 }
1495
Werner Lemberg75435332004-02-25 12:58:54 +00001496 error = FT_Raccess_Get_DataOffsets( library, stream,
1497 map_offset, rdara_pos,
1498 FT_MAKE_TAG( 's', 'f', 'n', 't' ),
1499 &data_offsets, &count );
1500 if ( !error )
1501 {
Werner Lemberg0fd08bd2006-12-16 02:57:46 +00001502 FT_Long face_index_internal = face_index % count;
Suzuki, Toshiya (鈴木俊哉)7a7d4032006-12-15 14:47:42 +00001503
1504
Werner Lemberg75435332004-02-25 12:58:54 +00001505 error = Mac_Read_sfnt_Resource( library, stream, data_offsets, count,
Suzuki, Toshiya (鈴木俊哉)7a7d4032006-12-15 14:47:42 +00001506 face_index_internal, aface );
Werner Lemberg75435332004-02-25 12:58:54 +00001507 FT_FREE( data_offsets );
Werner Lemberg17432b52007-01-12 09:28:44 +00001508 if ( !error )
David Turner7a3c5642007-01-11 15:09:01 +00001509 (*aface)->num_faces = count;
Werner Lemberg75435332004-02-25 12:58:54 +00001510 }
1511
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001512 return error;
1513 }
1514
1515
1516 /* Check for a valid macbinary header, and if we find one */
1517 /* check that the (flattened) resource fork in it is valid. */
1518 /* */
1519 static FT_Error
1520 IsMacBinary( FT_Library library,
1521 FT_Stream stream,
1522 FT_Long face_index,
1523 FT_Face *aface )
1524 {
1525 unsigned char header[128];
1526 FT_Error error;
1527 FT_Long dlen, offset;
1528
1529
Suzuki, Toshiya (鈴木俊哉)86c0f902007-11-20 14:00:17 +00001530 if ( NULL == stream )
1531 return FT_Err_Invalid_Stream_Operation;
1532
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001533 error = FT_Stream_Seek( stream, 0 );
1534 if ( error )
1535 goto Exit;
1536
1537 error = FT_Stream_Read( stream, (FT_Byte*)header, 128 );
1538 if ( error )
1539 goto Exit;
1540
1541 if ( header[ 0] != 0 ||
1542 header[74] != 0 ||
1543 header[82] != 0 ||
1544 header[ 1] == 0 ||
1545 header[ 1] > 33 ||
1546 header[63] != 0 ||
1547 header[2 + header[1]] != 0 )
1548 return FT_Err_Unknown_File_Format;
1549
1550 dlen = ( header[0x53] << 24 ) |
1551 ( header[0x54] << 16 ) |
1552 ( header[0x55] << 8 ) |
1553 header[0x56];
1554#if 0
1555 rlen = ( header[0x57] << 24 ) |
1556 ( header[0x58] << 16 ) |
1557 ( header[0x59] << 8 ) |
1558 header[0x5a];
1559#endif /* 0 */
1560 offset = 128 + ( ( dlen + 127 ) & ~127 );
1561
1562 return IsMacResource( library, stream, offset, face_index, aface );
1563
1564 Exit:
1565 return error;
1566 }
1567
1568
Werner Lemberg75435332004-02-25 12:58:54 +00001569 static FT_Error
1570 load_face_in_embedded_rfork( FT_Library library,
1571 FT_Stream stream,
1572 FT_Long face_index,
1573 FT_Face *aface,
1574 const FT_Open_Args *args )
1575 {
1576
1577#undef FT_COMPONENT
1578#define FT_COMPONENT trace_raccess
1579
1580 FT_Memory memory = library->memory;
1581 FT_Error error = FT_Err_Unknown_File_Format;
1582 int i;
1583
1584 char * file_names[FT_RACCESS_N_RULES];
1585 FT_Long offsets[FT_RACCESS_N_RULES];
1586 FT_Error errors[FT_RACCESS_N_RULES];
1587
1588 FT_Open_Args args2;
1589 FT_Stream stream2;
1590
1591
1592 FT_Raccess_Guess( library, stream,
1593 args->pathname, file_names, offsets, errors );
1594
1595 for ( i = 0; i < FT_RACCESS_N_RULES; i++ )
1596 {
1597 if ( errors[i] )
1598 {
1599 FT_TRACE3(( "Error[%d] has occurred in rule %d\n", errors[i], i ));
1600 continue;
1601 }
1602
1603 args2.flags = FT_OPEN_PATHNAME;
1604 args2.pathname = file_names[i] ? file_names[i] : args->pathname;
1605
1606 FT_TRACE3(( "Try rule %d: %s (offset=%d) ...",
1607 i, args2.pathname, offsets[i] ));
1608
1609 error = FT_Stream_New( library, &args2, &stream2 );
1610 if ( error )
1611 {
1612 FT_TRACE3(( "failed\n" ));
1613 continue;
1614 }
1615
1616 error = IsMacResource( library, stream2, offsets[i],
1617 face_index, aface );
Suzuki, Toshiya (鈴木俊哉)de0a96c2006-05-19 23:16:12 +00001618 FT_Stream_Free( stream2, 0 );
Werner Lemberg75435332004-02-25 12:58:54 +00001619
1620 FT_TRACE3(( "%s\n", error ? "failed": "successful" ));
1621
1622 if ( !error )
1623 break;
1624 }
1625
1626 for (i = 0; i < FT_RACCESS_N_RULES; i++)
1627 {
1628 if ( file_names[i] )
1629 FT_FREE( file_names[i] );
1630 }
1631
1632 /* Caller (load_mac_face) requires FT_Err_Unknown_File_Format. */
1633 if ( error )
1634 error = FT_Err_Unknown_File_Format;
1635
1636 return error;
1637
1638#undef FT_COMPONENT
1639#define FT_COMPONENT trace_objs
1640
1641 }
1642
1643
1644 /* Check for some macintosh formats. */
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001645 /* Is this a macbinary file? If so look at the resource fork. */
1646 /* Is this a mac dfont file? */
1647 /* Is this an old style resource fork? (in data) */
Werner Lemberg75435332004-02-25 12:58:54 +00001648 /* Else call load_face_in_embedded_rfork to try extra rules */
1649 /* (defined in `ftrfork.c'). */
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001650 /* */
1651 static FT_Error
1652 load_mac_face( FT_Library library,
1653 FT_Stream stream,
1654 FT_Long face_index,
1655 FT_Face *aface,
1656 const FT_Open_Args *args )
1657 {
1658 FT_Error error;
1659 FT_UNUSED( args );
1660
1661
1662 error = IsMacBinary( library, stream, face_index, aface );
1663 if ( FT_ERROR_BASE( error ) == FT_Err_Unknown_File_Format )
Werner Lemberg75435332004-02-25 12:58:54 +00001664 {
1665
1666#undef FT_COMPONENT
1667#define FT_COMPONENT trace_raccess
1668
1669 FT_TRACE3(( "Try as dfont: %s ...", args->pathname ));
1670
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001671 error = IsMacResource( library, stream, 0, face_index, aface );
1672
Werner Lemberg75435332004-02-25 12:58:54 +00001673 FT_TRACE3(( "%s\n", error ? "failed" : "successful" ));
David Turnere2d12842003-09-21 17:15:55 +00001674
Werner Lemberg75435332004-02-25 12:58:54 +00001675#undef FT_COMPONENT
1676#define FT_COMPONENT trace_objs
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001677
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001678 }
1679
Werner Lemberg75435332004-02-25 12:58:54 +00001680 if ( ( FT_ERROR_BASE( error ) == FT_Err_Unknown_File_Format ||
1681 FT_ERROR_BASE( error ) == FT_Err_Invalid_Stream_Operation ) &&
1682 ( args->flags & FT_OPEN_PATHNAME ) )
1683 error = load_face_in_embedded_rfork( library, stream,
1684 face_index, aface, args );
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001685 return error;
1686 }
1687
1688#endif /* !FT_MACINTOSH && FT_CONFIG_OPTION_MAC_FONTS */
1689
1690
Werner Lemberg90a03302000-11-07 17:21:11 +00001691 /* documentation is in freetype.h */
1692
Werner Lembergf814d0f2001-06-27 16:18:10 +00001693 FT_EXPORT_DEF( FT_Error )
Werner Lembergc4c373c2002-10-07 09:15:20 +00001694 FT_Open_Face( FT_Library library,
1695 const FT_Open_Args* args,
1696 FT_Long face_index,
1697 FT_Face *aface )
David Turnerd2b1f351999-12-16 23:11:37 +00001698 {
1699 FT_Error error;
1700 FT_Driver driver;
1701 FT_Memory memory;
David Turnercda32b72000-02-10 16:14:35 +00001702 FT_Stream stream;
David Turnerd2b1f351999-12-16 23:11:37 +00001703 FT_Face face = 0;
1704 FT_ListNode node = 0;
David Turnerc5cdf8b2000-07-27 21:40:22 +00001705 FT_Bool external_stream;
Werner Lembergc32e83f2008-04-01 06:07:37 +00001706 FT_Module* cur;
1707 FT_Module* limit;
Werner Lemberg547a2522000-02-16 08:23:58 +00001708
Werner Lemberg58b17f92000-07-27 23:29:08 +00001709
Werner Lembergf9b03752000-09-11 22:50:13 +00001710 /* test for valid `library' delayed to */
Werner Lemberg75435332004-02-25 12:58:54 +00001711 /* FT_Stream_New() */
David Turnerd2b1f351999-12-16 23:11:37 +00001712
Werner Lembergce235ea2005-05-17 20:35:23 +00001713 if ( ( !aface && face_index >= 0 ) || !args )
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001714 return FT_Err_Invalid_Argument;
1715
David Turnerb08fe2d2002-08-27 20:20:29 +00001716 external_stream = FT_BOOL( ( args->flags & FT_OPEN_STREAM ) &&
Werner Lemberg8eb03532001-06-19 23:03:41 +00001717 args->stream );
David Turnerc5cdf8b2000-07-27 21:40:22 +00001718
David Turnercda32b72000-02-10 16:14:35 +00001719 /* create input stream */
Werner Lemberg75435332004-02-25 12:58:54 +00001720 error = FT_Stream_New( library, args, &stream );
Werner Lembergdeb4e982000-06-29 03:14:25 +00001721 if ( error )
Suzuki, Toshiya (鈴木俊哉)86c0f902007-11-20 14:00:17 +00001722 goto Fail3;
David Turnercda32b72000-02-10 16:14:35 +00001723
David Turnerd2b1f351999-12-16 23:11:37 +00001724 memory = library->memory;
1725
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001726 /* If the font driver is specified in the `args' structure, use */
Werner Lembergdeb4e982000-06-29 03:14:25 +00001727 /* it. Otherwise, we scan the list of registered drivers. */
David Turnerb08fe2d2002-08-27 20:20:29 +00001728 if ( ( args->flags & FT_OPEN_DRIVER ) && args->driver )
David Turner7663f222000-02-13 13:37:38 +00001729 {
Werner Lemberga929ba92000-06-25 06:47:11 +00001730 driver = FT_DRIVER( args->driver );
David Turnerf0df85b2000-06-22 00:17:42 +00001731
1732 /* not all modules are drivers, so check... */
Werner Lemberga929ba92000-06-25 06:47:11 +00001733 if ( FT_MODULE_IS_DRIVER( driver ) )
David Turner7663f222000-02-13 13:37:38 +00001734 {
Werner Lemberg3c403e42002-08-06 21:47:40 +00001735 FT_Int num_params = 0;
1736 FT_Parameter* params = 0;
1737
Werner Lemberga929ba92000-06-25 06:47:11 +00001738
David Turnerb08fe2d2002-08-27 20:20:29 +00001739 if ( args->flags & FT_OPEN_PARAMS )
David Turner4f2c5542000-05-12 10:19:41 +00001740 {
1741 num_params = args->num_params;
1742 params = args->params;
1743 }
David Turnere49ab252000-05-16 23:44:38 +00001744
David Turner4f2c5542000-05-12 10:19:41 +00001745 error = open_face( driver, stream, face_index,
1746 num_params, params, &face );
Werner Lemberg547a2522000-02-16 08:23:58 +00001747 if ( !error )
1748 goto Success;
David Turner7663f222000-02-13 13:37:38 +00001749 }
1750 else
1751 error = FT_Err_Invalid_Handle;
1752
Werner Lemberg75435332004-02-25 12:58:54 +00001753 FT_Stream_Free( stream, external_stream );
David Turner7663f222000-02-13 13:37:38 +00001754 goto Fail;
1755 }
Just van Rossum1e5754f2000-03-02 10:52:57 +00001756 else
David Turnerd2b1f351999-12-16 23:11:37 +00001757 {
1758 /* check each font driver for an appropriate format */
Werner Lembergc32e83f2008-04-01 06:07:37 +00001759 cur = library->modules;
1760 limit = cur + library->num_modules;
David Turnerd2b1f351999-12-16 23:11:37 +00001761
Werner Lemberga929ba92000-06-25 06:47:11 +00001762
David Turnerd2b1f351999-12-16 23:11:37 +00001763 for ( ; cur < limit; cur++ )
1764 {
David Turnerf0df85b2000-06-22 00:17:42 +00001765 /* not all modules are font drivers, so check... */
Werner Lemberga929ba92000-06-25 06:47:11 +00001766 if ( FT_MODULE_IS_DRIVER( cur[0] ) )
David Turnerd2b1f351999-12-16 23:11:37 +00001767 {
David Turner4f2c5542000-05-12 10:19:41 +00001768 FT_Int num_params = 0;
1769 FT_Parameter* params = 0;
David Turnere49ab252000-05-16 23:44:38 +00001770
Werner Lemberg3c403e42002-08-06 21:47:40 +00001771
Werner Lemberga929ba92000-06-25 06:47:11 +00001772 driver = FT_DRIVER( cur[0] );
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001773
David Turnerb08fe2d2002-08-27 20:20:29 +00001774 if ( args->flags & FT_OPEN_PARAMS )
David Turner4f2c5542000-05-12 10:19:41 +00001775 {
1776 num_params = args->num_params;
1777 params = args->params;
1778 }
David Turnere49ab252000-05-16 23:44:38 +00001779
Graham Asherd53cf1d2002-07-18 15:04:29 +00001780 error = open_face( driver, stream, face_index,
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001781 num_params, params, &face );
David Turnerd2b1f351999-12-16 23:11:37 +00001782 if ( !error )
1783 goto Success;
1784
Werner Lemberg79860702001-06-08 21:17:29 +00001785 if ( FT_ERROR_BASE( error ) != FT_Err_Unknown_File_Format )
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001786 goto Fail3;
David Turnerd2b1f351999-12-16 23:11:37 +00001787 }
1788 }
1789
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001790 Fail3:
1791 /* If we are on the mac, and we get an FT_Err_Invalid_Stream_Operation */
1792 /* it may be because we have an empty data fork, so we need to check */
1793 /* the resource fork. */
Suzuki, Toshiya (鈴木俊哉)86c0f902007-11-20 14:00:17 +00001794 if ( FT_ERROR_BASE( error ) != FT_Err_Cannot_Open_Stream &&
1795 FT_ERROR_BASE( error ) != FT_Err_Unknown_File_Format &&
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001796 FT_ERROR_BASE( error ) != FT_Err_Invalid_Stream_Operation )
1797 goto Fail2;
1798
Werner Lembergdc8ad542003-12-09 02:12:14 +00001799#if !defined( FT_MACINTOSH ) && defined( FT_CONFIG_OPTION_MAC_FONTS )
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001800 error = load_mac_face( library, stream, face_index, aface, args );
1801 if ( !error )
1802 {
1803 /* We don't want to go to Success here. We've already done that. */
1804 /* On the other hand, if we succeeded we still need to close this */
1805 /* stream (we opened a different stream which extracted the */
1806 /* interesting information out of this stream here. That stream */
1807 /* will still be open and the face will point to it). */
Werner Lemberg75435332004-02-25 12:58:54 +00001808 FT_Stream_Free( stream, external_stream );
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001809 return error;
1810 }
1811
1812 if ( FT_ERROR_BASE( error ) != FT_Err_Unknown_File_Format )
1813 goto Fail2;
Werner Lembergdc8ad542003-12-09 02:12:14 +00001814#endif /* !FT_MACINTOSH && FT_CONFIG_OPTION_MAC_FONTS */
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001815
David Turnerd2b1f351999-12-16 23:11:37 +00001816 /* no driver is able to handle this format */
1817 error = FT_Err_Unknown_File_Format;
David Turnerebe85f52001-05-11 14:25:57 +00001818
1819 Fail2:
Werner Lemberg75435332004-02-25 12:58:54 +00001820 FT_Stream_Free( stream, external_stream );
David Turnercda32b72000-02-10 16:14:35 +00001821 goto Fail;
David Turnerd2b1f351999-12-16 23:11:37 +00001822 }
1823
1824 Success:
Werner Lembergf9b03752000-09-11 22:50:13 +00001825 FT_TRACE4(( "FT_Open_Face: New face object, adding to list\n" ));
David Turnerd2b1f351999-12-16 23:11:37 +00001826
Werner Lembergdeb4e982000-06-29 03:14:25 +00001827 /* set the FT_FACE_FLAG_EXTERNAL_STREAM bit for FT_Done_Face */
David Turnerc5cdf8b2000-07-27 21:40:22 +00001828 if ( external_stream )
David Turnerf0df85b2000-06-22 00:17:42 +00001829 face->face_flags |= FT_FACE_FLAG_EXTERNAL_STREAM;
1830
Werner Lemberg547a2522000-02-16 08:23:58 +00001831 /* add the face object to its driver's list */
David Turnere459d742002-03-22 13:52:37 +00001832 if ( FT_NEW( node ) )
David Turnerd2b1f351999-12-16 23:11:37 +00001833 goto Fail;
1834
1835 node->data = face;
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001836 /* don't assume driver is the same as face->driver, so use */
1837 /* face->driver instead. */
Just van Rossum7eef5362000-03-05 16:07:58 +00001838 FT_List_Add( &face->driver->faces_list, node );
David Turnerd2b1f351999-12-16 23:11:37 +00001839
Werner Lemberg547a2522000-02-16 08:23:58 +00001840 /* now allocate a glyph slot object for the face */
Werner Lembergb9ee7372005-05-20 21:52:19 +00001841 FT_TRACE4(( "FT_Open_Face: Creating glyph slot\n" ));
David Turnerd2b1f351999-12-16 23:11:37 +00001842
David Turner92f30c82005-10-17 21:17:20 +00001843 if ( face_index >= 0 )
David Turnerd2b1f351999-12-16 23:11:37 +00001844 {
David Turner92f30c82005-10-17 21:17:20 +00001845 error = FT_New_GlyphSlot( face, NULL );
Werner Lembergdeb4e982000-06-29 03:14:25 +00001846 if ( error )
1847 goto Fail;
1848
David Turner92f30c82005-10-17 21:17:20 +00001849 /* finally, allocate a size object for the face */
1850 {
1851 FT_Size size;
1852
1853
1854 FT_TRACE4(( "FT_Open_Face: Creating size object\n" ));
1855
1856 error = FT_New_Size( face, &size );
1857 if ( error )
1858 goto Fail;
1859
1860 face->size = size;
1861 }
David Turnerd2b1f351999-12-16 23:11:37 +00001862 }
Werner Lemberg7880dd62000-01-10 17:19:45 +00001863
Wu, Chia-I (吳佳一)e5ff0592006-01-15 06:00:49 +00001864 /* some checks */
1865
1866 if ( FT_IS_SCALABLE( face ) )
1867 {
1868 if ( face->height < 0 )
Werner Lembergbe3c9812006-01-27 14:16:16 +00001869 face->height = (FT_Short)-face->height;
Wu, Chia-I (吳佳一)e5ff0592006-01-15 06:00:49 +00001870
1871 if ( !FT_HAS_VERTICAL( face ) )
Werner Lembergbe3c9812006-01-27 14:16:16 +00001872 face->max_advance_height = (FT_Short)face->height;
Wu, Chia-I (吳佳一)e5ff0592006-01-15 06:00:49 +00001873 }
1874
1875 if ( FT_HAS_FIXED_SIZES( face ) )
1876 {
Werner Lemberg1723dcc2006-01-15 07:30:32 +00001877 FT_Int i;
Wu, Chia-I (吳佳一)e5ff0592006-01-15 06:00:49 +00001878
David Turnercda2d952006-02-16 22:45:31 +00001879
Wu, Chia-I (吳佳一)e5ff0592006-01-15 06:00:49 +00001880 for ( i = 0; i < face->num_fixed_sizes; i++ )
1881 {
1882 FT_Bitmap_Size* bsize = face->available_sizes + i;
1883
1884
1885 if ( bsize->height < 0 )
Werner Lembergbe3c9812006-01-27 14:16:16 +00001886 bsize->height = (FT_Short)-bsize->height;
Wu, Chia-I (吳佳一)e5ff0592006-01-15 06:00:49 +00001887 if ( bsize->x_ppem < 0 )
Werner Lembergbe3c9812006-01-27 14:16:16 +00001888 bsize->x_ppem = (FT_Short)-bsize->x_ppem;
Wu, Chia-I (吳佳一)e5ff0592006-01-15 06:00:49 +00001889 if ( bsize->y_ppem < 0 )
1890 bsize->y_ppem = -bsize->y_ppem;
1891 }
1892 }
1893
David Turner54e75742000-11-04 02:52:02 +00001894 /* initialize internal face data */
1895 {
1896 FT_Face_Internal internal = face->internal;
David Turner61d6b2b2001-05-16 17:49:07 +00001897
David Turner37379e22000-03-28 11:22:31 +00001898
David Turner54e75742000-11-04 02:52:02 +00001899 internal->transform_matrix.xx = 0x10000L;
1900 internal->transform_matrix.xy = 0;
1901 internal->transform_matrix.yx = 0;
1902 internal->transform_matrix.yy = 0x10000L;
David Turner61d6b2b2001-05-16 17:49:07 +00001903
David Turner54e75742000-11-04 02:52:02 +00001904 internal->transform_delta.x = 0;
1905 internal->transform_delta.y = 0;
1906 }
David Turner37379e22000-03-28 11:22:31 +00001907
Werner Lembergce235ea2005-05-17 20:35:23 +00001908 if ( aface )
1909 *aface = face;
Werner Lembergb2d02532005-11-04 06:58:49 +00001910 else
1911 FT_Done_Face( face );
1912
David Turnerd2b1f351999-12-16 23:11:37 +00001913 goto Exit;
1914
1915 Fail:
1916 FT_Done_Face( face );
1917
David Turnerd2b1f351999-12-16 23:11:37 +00001918 Exit:
1919 FT_TRACE4(( "FT_Open_Face: Return %d\n", error ));
Werner Lembergdeb4e982000-06-29 03:14:25 +00001920
David Turnerd2b1f351999-12-16 23:11:37 +00001921 return error;
1922 }
1923
1924
Werner Lemberg90a03302000-11-07 17:21:11 +00001925 /* documentation is in freetype.h */
1926
Werner Lembergf814d0f2001-06-27 16:18:10 +00001927 FT_EXPORT_DEF( FT_Error )
1928 FT_Attach_File( FT_Face face,
1929 const char* filepathname )
David Turner7663f222000-02-13 13:37:38 +00001930 {
David Turner37379e22000-03-28 11:22:31 +00001931 FT_Open_Args open;
David Turner7663f222000-02-13 13:37:38 +00001932
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001933
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001934 /* test for valid `face' delayed to FT_Attach_Stream() */
1935
1936 if ( !filepathname )
1937 return FT_Err_Invalid_Argument;
1938
Werner Lembergb8fdcd62004-08-03 03:28:11 +00001939 open.stream = NULL;
David Turnerb08fe2d2002-08-27 20:20:29 +00001940 open.flags = FT_OPEN_PATHNAME;
David Turner4f2c5542000-05-12 10:19:41 +00001941 open.pathname = (char*)filepathname;
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001942
David Turner7663f222000-02-13 13:37:38 +00001943 return FT_Attach_Stream( face, &open );
1944 }
Werner Lemberg547a2522000-02-16 08:23:58 +00001945
David Turnere49ab252000-05-16 23:44:38 +00001946
Werner Lemberg90a03302000-11-07 17:21:11 +00001947 /* documentation is in freetype.h */
1948
Werner Lembergf814d0f2001-06-27 16:18:10 +00001949 FT_EXPORT_DEF( FT_Error )
1950 FT_Attach_Stream( FT_Face face,
1951 FT_Open_Args* parameters )
David Turner7663f222000-02-13 13:37:38 +00001952 {
1953 FT_Stream stream;
1954 FT_Error error;
1955 FT_Driver driver;
David Turnere49ab252000-05-16 23:44:38 +00001956
David Turneref3c1262002-03-14 09:22:48 +00001957 FT_Driver_Class clazz;
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001958
Werner Lemberga929ba92000-06-25 06:47:11 +00001959
Werner Lemberg75435332004-02-25 12:58:54 +00001960 /* test for valid `parameters' delayed to FT_Stream_New() */
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001961
1962 if ( !face )
1963 return FT_Err_Invalid_Face_Handle;
David Turnere49ab252000-05-16 23:44:38 +00001964
David Turner7663f222000-02-13 13:37:38 +00001965 driver = face->driver;
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001966 if ( !driver )
1967 return FT_Err_Invalid_Driver_Handle;
1968
Werner Lemberg75435332004-02-25 12:58:54 +00001969 error = FT_Stream_New( driver->root.library, parameters, &stream );
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001970 if ( error )
1971 goto Exit;
David Turnere49ab252000-05-16 23:44:38 +00001972
David Turner7663f222000-02-13 13:37:38 +00001973 /* we implement FT_Attach_Stream in each driver through the */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001974 /* `attach_file' interface */
1975
David Turner7663f222000-02-13 13:37:38 +00001976 error = FT_Err_Unimplemented_Feature;
David Turnerf0df85b2000-06-22 00:17:42 +00001977 clazz = driver->clazz;
Werner Lemberga929ba92000-06-25 06:47:11 +00001978 if ( clazz->attach_file )
David Turnerf0df85b2000-06-22 00:17:42 +00001979 error = clazz->attach_file( face, stream );
David Turnere49ab252000-05-16 23:44:38 +00001980
David Turner7663f222000-02-13 13:37:38 +00001981 /* close the attached stream */
Werner Lemberg75435332004-02-25 12:58:54 +00001982 FT_Stream_Free( stream,
Werner Lemberg58b17f92000-07-27 23:29:08 +00001983 (FT_Bool)( parameters->stream &&
David Turnerb08fe2d2002-08-27 20:20:29 +00001984 ( parameters->flags & FT_OPEN_STREAM ) ) );
David Turnere49ab252000-05-16 23:44:38 +00001985
David Turner7663f222000-02-13 13:37:38 +00001986 Exit:
1987 return error;
1988 }
1989
1990
Werner Lemberg90a03302000-11-07 17:21:11 +00001991 /* documentation is in freetype.h */
1992
Werner Lembergf814d0f2001-06-27 16:18:10 +00001993 FT_EXPORT_DEF( FT_Error )
1994 FT_Done_Face( FT_Face face )
David Turnerd2b1f351999-12-16 23:11:37 +00001995 {
Werner Lemberga929ba92000-06-25 06:47:11 +00001996 FT_Error error;
1997 FT_Driver driver;
1998 FT_Memory memory;
1999 FT_ListNode node;
2000
David Turnerd2b1f351999-12-16 23:11:37 +00002001
David Turnerf0df85b2000-06-22 00:17:42 +00002002 error = FT_Err_Invalid_Face_Handle;
2003 if ( face && face->driver )
David Turnerd2b1f351999-12-16 23:11:37 +00002004 {
David Turnerf0df85b2000-06-22 00:17:42 +00002005 driver = face->driver;
2006 memory = driver->root.memory;
Werner Lembergdeb4e982000-06-29 03:14:25 +00002007
David Turnerf0df85b2000-06-22 00:17:42 +00002008 /* find face in driver's list */
2009 node = FT_List_Find( &driver->faces_list, face );
2010 if ( node )
2011 {
2012 /* remove face object from the driver's list */
2013 FT_List_Remove( &driver->faces_list, node );
David Turnere459d742002-03-22 13:52:37 +00002014 FT_FREE( node );
Werner Lembergdeb4e982000-06-29 03:14:25 +00002015
David Turnerf0df85b2000-06-22 00:17:42 +00002016 /* now destroy the object proper */
2017 destroy_face( memory, face, driver );
2018 error = FT_Err_Ok;
2019 }
David Turnerd2b1f351999-12-16 23:11:37 +00002020 }
David Turnerd2b1f351999-12-16 23:11:37 +00002021 return error;
2022 }
2023
2024
Werner Lemberg90a03302000-11-07 17:21:11 +00002025 /* documentation is in ftobjs.h */
2026
Werner Lembergf814d0f2001-06-27 16:18:10 +00002027 FT_EXPORT_DEF( FT_Error )
2028 FT_New_Size( FT_Face face,
2029 FT_Size *asize )
David Turnerd2b1f351999-12-16 23:11:37 +00002030 {
Werner Lembergf8ba2002002-03-30 13:16:35 +00002031 FT_Error error;
2032 FT_Memory memory;
2033 FT_Driver driver;
David Turneref3c1262002-03-14 09:22:48 +00002034 FT_Driver_Class clazz;
David Turnerd2b1f351999-12-16 23:11:37 +00002035
Werner Lembergf8ba2002002-03-30 13:16:35 +00002036 FT_Size size = 0;
2037 FT_ListNode node = 0;
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00002038
Werner Lemberga929ba92000-06-25 06:47:11 +00002039
Werner Lembergb48a6092000-07-09 19:15:30 +00002040 if ( !face )
2041 return FT_Err_Invalid_Face_Handle;
2042
2043 if ( !asize )
2044 return FT_Err_Invalid_Size_Handle;
2045
2046 if ( !face->driver )
2047 return FT_Err_Invalid_Driver_Handle;
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00002048
Werner Lembergdeb4e982000-06-29 03:14:25 +00002049 *asize = 0;
2050
David Turnerf0df85b2000-06-22 00:17:42 +00002051 driver = face->driver;
2052 clazz = driver->clazz;
2053 memory = face->memory;
David Turnerd2b1f351999-12-16 23:11:37 +00002054
2055 /* Allocate new size object and perform basic initialisation */
David Turnere459d742002-03-22 13:52:37 +00002056 if ( FT_ALLOC( size, clazz->size_object_size ) || FT_NEW( node ) )
David Turnerd2b1f351999-12-16 23:11:37 +00002057 goto Exit;
2058
2059 size->face = face;
David Turner61d6b2b2001-05-16 17:49:07 +00002060
David Turner54e75742000-11-04 02:52:02 +00002061 /* for now, do not use any internal fields in size objects */
2062 size->internal = 0;
David Turnerd2b1f351999-12-16 23:11:37 +00002063
Werner Lemberga929ba92000-06-25 06:47:11 +00002064 if ( clazz->init_size )
David Turnerf0df85b2000-06-22 00:17:42 +00002065 error = clazz->init_size( size );
David Turnerd2b1f351999-12-16 23:11:37 +00002066
2067 /* in case of success, add to the face's list */
2068 if ( !error )
2069 {
2070 *asize = size;
2071 node->data = size;
2072 FT_List_Add( &face->sizes_list, node );
David Turnerd2b1f351999-12-16 23:11:37 +00002073 }
2074
2075 Exit:
2076 if ( error )
2077 {
David Turnere459d742002-03-22 13:52:37 +00002078 FT_FREE( node );
2079 FT_FREE( size );
David Turnerd2b1f351999-12-16 23:11:37 +00002080 }
2081
2082 return error;
2083 }
2084
2085
Werner Lemberg90a03302000-11-07 17:21:11 +00002086 /* documentation is in ftobjs.h */
2087
Werner Lembergf814d0f2001-06-27 16:18:10 +00002088 FT_EXPORT_DEF( FT_Error )
2089 FT_Done_Size( FT_Size size )
David Turnerd2b1f351999-12-16 23:11:37 +00002090 {
2091 FT_Error error;
2092 FT_Driver driver;
2093 FT_Memory memory;
2094 FT_Face face;
2095 FT_ListNode node;
2096
2097
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00002098 if ( !size )
David Turnerd2b1f351999-12-16 23:11:37 +00002099 return FT_Err_Invalid_Size_Handle;
2100
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00002101 face = size->face;
2102 if ( !face )
2103 return FT_Err_Invalid_Face_Handle;
2104
2105 driver = face->driver;
David Turnerd2b1f351999-12-16 23:11:37 +00002106 if ( !driver )
2107 return FT_Err_Invalid_Driver_Handle;
2108
David Turnerf0df85b2000-06-22 00:17:42 +00002109 memory = driver->root.memory;
David Turnerd2b1f351999-12-16 23:11:37 +00002110
2111 error = FT_Err_Ok;
David Turnerd2b1f351999-12-16 23:11:37 +00002112 node = FT_List_Find( &face->sizes_list, size );
2113 if ( node )
2114 {
2115 FT_List_Remove( &face->sizes_list, node );
David Turnere459d742002-03-22 13:52:37 +00002116 FT_FREE( node );
David Turnerd2b1f351999-12-16 23:11:37 +00002117
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00002118 if ( face->size == size )
David Turnerd2b1f351999-12-16 23:11:37 +00002119 {
2120 face->size = 0;
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00002121 if ( face->sizes_list.head )
David Turnerd2b1f351999-12-16 23:11:37 +00002122 face->size = (FT_Size)(face->sizes_list.head->data);
2123 }
2124
2125 destroy_size( memory, size, driver );
2126 }
2127 else
2128 error = FT_Err_Invalid_Size_Handle;
2129
Werner Lembergcf24d512001-06-18 14:23:45 +00002130 return error;
David Turnerd2b1f351999-12-16 23:11:37 +00002131 }
2132
2133
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002134 /* documentation is in ftobjs.h */
2135
2136 FT_BASE_DEF( FT_Error )
2137 FT_Match_Size( FT_Face face,
2138 FT_Size_Request req,
2139 FT_Bool ignore_width,
Werner Lemberg8c4120d2007-01-15 06:42:40 +00002140 FT_ULong* size_index )
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002141 {
2142 FT_Int i;
2143 FT_Long w, h;
2144
2145
2146 if ( !FT_HAS_FIXED_SIZES( face ) )
2147 return FT_Err_Invalid_Face_Handle;
2148
2149 /* FT_Bitmap_Size doesn't provide enough info... */
2150 if ( req->type != FT_SIZE_REQUEST_TYPE_NOMINAL )
2151 return FT_Err_Unimplemented_Feature;
2152
Werner Lemberg9cc4aed2006-01-26 21:03:58 +00002153 w = FT_REQUEST_WIDTH ( req );
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002154 h = FT_REQUEST_HEIGHT( req );
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002155
2156 if ( req->width && !req->height )
2157 h = w;
2158 else if ( !req->width && req->height )
2159 w = h;
2160
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002161 w = FT_PIX_ROUND( w );
2162 h = FT_PIX_ROUND( h );
2163
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002164 for ( i = 0; i < face->num_fixed_sizes; i++ )
2165 {
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002166 FT_Bitmap_Size* bsize = face->available_sizes + i;
2167
2168
2169 if ( h != FT_PIX_ROUND( bsize->y_ppem ) )
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002170 continue;
2171
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002172 if ( w == FT_PIX_ROUND( bsize->x_ppem ) || ignore_width )
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002173 {
Werner Lemberg8c4120d2007-01-15 06:42:40 +00002174 if ( size_index )
2175 *size_index = (FT_ULong)i;
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002176
2177 return FT_Err_Ok;
2178 }
2179 }
2180
2181 return FT_Err_Invalid_Pixel_Size;
2182 }
2183
2184
Wu, Chia-I (吳佳一)212aee02006-01-15 06:24:53 +00002185 /* documentation is in ftobjs.h */
2186
2187 FT_BASE_DEF( void )
Wu, Chia-I (吳佳一)ea1e8d32006-01-15 15:01:45 +00002188 ft_synthesize_vertical_metrics( FT_Glyph_Metrics* metrics,
2189 FT_Pos advance )
Wu, Chia-I (吳佳一)212aee02006-01-15 06:24:53 +00002190 {
Werner Lemberg1723dcc2006-01-15 07:30:32 +00002191 /* the factor 1.2 is a heuristical value */
Wu, Chia-I (吳佳一)212aee02006-01-15 06:24:53 +00002192 if ( !advance )
2193 advance = metrics->height * 12 / 10;
2194
2195 metrics->vertBearingX = -( metrics->width / 2 );
2196 metrics->vertBearingY = ( advance - metrics->height ) / 2;
2197 metrics->vertAdvance = advance;
2198 }
2199
2200
Werner Lembergf814d0f2001-06-27 16:18:10 +00002201 static void
2202 ft_recompute_scaled_metrics( FT_Face face,
2203 FT_Size_Metrics* metrics )
Werner Lembergdeb4e982000-06-29 03:14:25 +00002204 {
Werner Lemberga929ba92000-06-25 06:47:11 +00002205 /* Compute root ascender, descender, test height, and max_advance */
Werner Lembergdeb4e982000-06-29 03:14:25 +00002206
Wu, Chia-I (吳佳一)2e48a1a2006-02-27 09:18:07 +00002207#ifdef GRID_FIT_METRICS
David Turnerb4636652006-02-26 07:57:45 +00002208 metrics->ascender = FT_PIX_CEIL( FT_MulFix( face->ascender,
2209 metrics->y_scale ) );
2210
2211 metrics->descender = FT_PIX_FLOOR( FT_MulFix( face->descender,
2212 metrics->y_scale ) );
2213
2214 metrics->height = FT_PIX_ROUND( FT_MulFix( face->height,
2215 metrics->y_scale ) );
2216
2217 metrics->max_advance = FT_PIX_ROUND( FT_MulFix( face->max_advance_width,
2218 metrics->x_scale ) );
Wu, Chia-I (吳佳一)2e48a1a2006-02-27 09:18:07 +00002219#else /* !GRID_FIT_METRICS */
Wu, Chia-I (吳佳一)dcb8b712005-12-16 14:27:14 +00002220 metrics->ascender = FT_MulFix( face->ascender,
2221 metrics->y_scale );
Werner Lemberga929ba92000-06-25 06:47:11 +00002222
Wu, Chia-I (吳佳一)dcb8b712005-12-16 14:27:14 +00002223 metrics->descender = FT_MulFix( face->descender,
2224 metrics->y_scale );
Werner Lemberga929ba92000-06-25 06:47:11 +00002225
Wu, Chia-I (吳佳一)dcb8b712005-12-16 14:27:14 +00002226 metrics->height = FT_MulFix( face->height,
2227 metrics->y_scale );
Werner Lemberga929ba92000-06-25 06:47:11 +00002228
Wu, Chia-I (吳佳一)dcb8b712005-12-16 14:27:14 +00002229 metrics->max_advance = FT_MulFix( face->max_advance_width,
2230 metrics->x_scale );
Wu, Chia-I (吳佳一)2e48a1a2006-02-27 09:18:07 +00002231#endif /* !GRID_FIT_METRICS */
Werner Lemberga929ba92000-06-25 06:47:11 +00002232 }
2233
2234
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002235 FT_BASE_DEF( void )
2236 FT_Select_Metrics( FT_Face face,
2237 FT_ULong strike_index )
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002238 {
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002239 FT_Size_Metrics* metrics;
2240 FT_Bitmap_Size* bsize;
2241
2242
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002243 metrics = &face->size->metrics;
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002244 bsize = face->available_sizes + strike_index;
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002245
Werner Lembergbe3c9812006-01-27 14:16:16 +00002246 metrics->x_ppem = (FT_UShort)( ( bsize->x_ppem + 32 ) >> 6 );
2247 metrics->y_ppem = (FT_UShort)( ( bsize->y_ppem + 32 ) >> 6 );
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002248
2249 if ( FT_IS_SCALABLE( face ) )
2250 {
2251 metrics->x_scale = FT_DivFix( bsize->x_ppem,
2252 face->units_per_EM );
2253 metrics->y_scale = FT_DivFix( bsize->y_ppem,
2254 face->units_per_EM );
2255
2256 ft_recompute_scaled_metrics( face, metrics );
2257 }
2258 else
2259 {
Werner Lemberg1723dcc2006-01-15 07:30:32 +00002260 metrics->x_scale = 1L << 22;
2261 metrics->y_scale = 1L << 22;
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002262 metrics->ascender = bsize->y_ppem;
2263 metrics->descender = 0;
2264 metrics->height = bsize->height << 6;
2265 metrics->max_advance = bsize->x_ppem;
2266 }
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002267 }
2268
2269
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002270 FT_BASE_DEF( void )
2271 FT_Request_Metrics( FT_Face face,
2272 FT_Size_Request req )
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002273 {
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002274 FT_Size_Metrics* metrics;
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002275
2276
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002277 metrics = &face->size->metrics;
2278
2279 if ( FT_IS_SCALABLE( face ) )
2280 {
Werner Lembergce280a22007-06-03 05:58:30 +00002281 FT_Long w = 0, h = 0, scaled_w = 0, scaled_h = 0;
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002282
2283
2284 switch ( req->type )
2285 {
2286 case FT_SIZE_REQUEST_TYPE_NOMINAL:
2287 w = h = face->units_per_EM;
2288 break;
Werner Lembergf1c2b912006-01-13 14:53:28 +00002289
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002290 case FT_SIZE_REQUEST_TYPE_REAL_DIM:
2291 w = h = face->ascender - face->descender;
2292 break;
Werner Lembergf1c2b912006-01-13 14:53:28 +00002293
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002294 case FT_SIZE_REQUEST_TYPE_BBOX:
2295 w = face->bbox.xMax - face->bbox.xMin;
2296 h = face->bbox.yMax - face->bbox.yMin;
2297 break;
Werner Lembergf1c2b912006-01-13 14:53:28 +00002298
Werner Lembergb9933f42007-06-01 21:27:12 +00002299 case FT_SIZE_REQUEST_TYPE_CELL:
2300 w = face->max_advance_width;
2301 h = face->ascender - face->descender;
2302 break;
2303
Wu, Chia-I (吳佳一)a8e7a012006-02-24 06:11:30 +00002304 case FT_SIZE_REQUEST_TYPE_SCALES:
2305 metrics->x_scale = (FT_Fixed)req->width;
2306 metrics->y_scale = (FT_Fixed)req->height;
2307 if ( !metrics->x_scale )
2308 metrics->x_scale = metrics->y_scale;
2309 else if ( !metrics->y_scale )
2310 metrics->y_scale = metrics->x_scale;
2311 goto Calculate_Ppem;
Wu, Chia-I (吳佳一)a8e7a012006-02-24 06:11:30 +00002312
Werner Lembergb9933f42007-06-01 21:27:12 +00002313 case FT_SIZE_REQUEST_TYPE_MAX:
2314 break;
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002315 }
2316
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002317 /* to be on the safe side */
Wu, Chia-I (吳佳一)e5ff0592006-01-15 06:00:49 +00002318 if ( w < 0 )
2319 w = -w;
2320
2321 if ( h < 0 )
2322 h = -h;
2323
Werner Lemberg9cc4aed2006-01-26 21:03:58 +00002324 scaled_w = FT_REQUEST_WIDTH ( req );
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002325 scaled_h = FT_REQUEST_HEIGHT( req );
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002326
2327 /* determine scales */
2328 if ( req->width )
2329 {
2330 metrics->x_scale = FT_DivFix( scaled_w, w );
2331
2332 if ( req->height )
2333 {
2334 metrics->y_scale = FT_DivFix( scaled_h, h );
2335
2336 if ( req->type == FT_SIZE_REQUEST_TYPE_CELL )
2337 {
2338 if ( metrics->y_scale > metrics->x_scale )
2339 metrics->y_scale = metrics->x_scale;
2340 else
2341 metrics->x_scale = metrics->y_scale;
2342 }
2343 }
2344 else
2345 {
2346 metrics->y_scale = metrics->x_scale;
2347 scaled_h = FT_MulDiv( scaled_w, h, w );
2348 }
2349 }
2350 else
2351 {
2352 metrics->x_scale = metrics->y_scale = FT_DivFix( scaled_h, h );
2353 scaled_w = FT_MulDiv( scaled_h, w, h );
2354 }
2355
Wu, Chia-I (吳佳一)a8e7a012006-02-24 06:11:30 +00002356 Calculate_Ppem:
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002357 /* calculate the ppems */
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002358 if ( req->type != FT_SIZE_REQUEST_TYPE_NOMINAL )
2359 {
2360 scaled_w = FT_MulFix( face->units_per_EM, metrics->x_scale );
2361 scaled_h = FT_MulFix( face->units_per_EM, metrics->y_scale );
2362 }
2363
Werner Lembergbe3c9812006-01-27 14:16:16 +00002364 metrics->x_ppem = (FT_UShort)( ( scaled_w + 32 ) >> 6 );
2365 metrics->y_ppem = (FT_UShort)( ( scaled_h + 32 ) >> 6 );
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002366
2367 ft_recompute_scaled_metrics( face, metrics );
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002368 }
2369 else
2370 {
2371 FT_ZERO( metrics );
Werner Lemberg1723dcc2006-01-15 07:30:32 +00002372 metrics->x_scale = 1L << 22;
2373 metrics->y_scale = 1L << 22;
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002374 }
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002375 }
2376
2377
2378 /* documentation is in freetype.h */
2379
2380 FT_EXPORT_DEF( FT_Error )
2381 FT_Select_Size( FT_Face face,
2382 FT_Int strike_index )
2383 {
Werner Lemberg9cc4aed2006-01-26 21:03:58 +00002384 FT_Driver_Class clazz;
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002385
2386
2387 if ( !face || !FT_HAS_FIXED_SIZES( face ) )
2388 return FT_Err_Invalid_Face_Handle;
2389
2390 if ( strike_index < 0 || strike_index >= face->num_fixed_sizes )
2391 return FT_Err_Invalid_Argument;
2392
2393 clazz = face->driver->clazz;
2394
2395 if ( clazz->select_size )
2396 return clazz->select_size( face->size, (FT_ULong)strike_index );
2397
2398 FT_Select_Metrics( face, (FT_ULong)strike_index );
2399
2400 return FT_Err_Ok;
2401 }
2402
2403
2404 /* documentation is in freetype.h */
2405
2406 FT_EXPORT_DEF( FT_Error )
2407 FT_Request_Size( FT_Face face,
2408 FT_Size_Request req )
2409 {
Werner Lemberg9cc4aed2006-01-26 21:03:58 +00002410 FT_Driver_Class clazz;
2411 FT_ULong strike_index;
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002412
2413
2414 if ( !face )
2415 return FT_Err_Invalid_Face_Handle;
2416
2417 if ( !req || req->width < 0 || req->height < 0 ||
2418 req->type >= FT_SIZE_REQUEST_TYPE_MAX )
2419 return FT_Err_Invalid_Argument;
2420
2421 clazz = face->driver->clazz;
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002422
2423 if ( clazz->request_size )
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002424 return clazz->request_size( face->size, req );
2425
Wu, Chia-I (吳佳一)e33dc2e2006-01-14 05:09:30 +00002426 /*
Werner Lemberg3d8eeb82006-01-14 07:10:45 +00002427 * The reason that a driver doesn't have `request_size' defined is
2428 * either that the scaling here suffices or that the supported formats
2429 * are bitmap-only and size matching is not implemented.
Wu, Chia-I (吳佳一)e33dc2e2006-01-14 05:09:30 +00002430 *
2431 * In the latter case, a simple size matching is done.
2432 */
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002433 if ( !FT_IS_SCALABLE( face ) && FT_HAS_FIXED_SIZES( face ) )
Wu, Chia-I (吳佳一)e33dc2e2006-01-14 05:09:30 +00002434 {
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002435 FT_Error error;
Wu, Chia-I (吳佳一)e33dc2e2006-01-14 05:09:30 +00002436
2437
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002438 error = FT_Match_Size( face, req, 0, &strike_index );
2439 if ( error )
2440 return error;
Wu, Chia-I (吳佳一)e33dc2e2006-01-14 05:09:30 +00002441
Werner Lemberg9cc4aed2006-01-26 21:03:58 +00002442 FT_TRACE3(( "FT_Request_Size: bitmap strike %lu matched\n",
2443 strike_index ));
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002444
2445 return FT_Select_Size( face, (FT_Int)strike_index );
Wu, Chia-I (吳佳一)e33dc2e2006-01-14 05:09:30 +00002446 }
2447
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002448 FT_Request_Metrics( face, req );
2449
2450 return FT_Err_Ok;
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002451 }
2452
2453
2454 /* documentation is in freetype.h */
2455
2456 FT_EXPORT_DEF( FT_Error )
Werner Lembergf814d0f2001-06-27 16:18:10 +00002457 FT_Set_Char_Size( FT_Face face,
2458 FT_F26Dot6 char_width,
2459 FT_F26Dot6 char_height,
2460 FT_UInt horz_resolution,
2461 FT_UInt vert_resolution )
David Turnerd2b1f351999-12-16 23:11:37 +00002462 {
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002463 FT_Size_RequestRec req;
David Turnerd2b1f351999-12-16 23:11:37 +00002464
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00002465
Wu, Chia-I (吳佳一)cffa8b62006-02-27 11:11:40 +00002466 if ( !char_width )
2467 char_width = char_height;
2468 else if ( !char_height )
2469 char_height = char_width;
2470
Werner Lemberg74781972007-04-03 19:39:28 +00002471 if ( !horz_resolution )
David Turner7338ec22007-04-03 14:30:34 +00002472 horz_resolution = vert_resolution;
Werner Lemberg74781972007-04-03 19:39:28 +00002473 else if ( !vert_resolution )
David Turner7338ec22007-04-03 14:30:34 +00002474 vert_resolution = horz_resolution;
2475
Wu, Chia-I (吳佳一)2e48a1a2006-02-27 09:18:07 +00002476 if ( char_width < 1 * 64 )
2477 char_width = 1 * 64;
2478 if ( char_height < 1 * 64 )
2479 char_height = 1 * 64;
2480
Werner Lemberg106eaf12007-05-03 07:07:47 +00002481 if ( !horz_resolution )
2482 horz_resolution = vert_resolution = 72;
2483
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002484 req.type = FT_SIZE_REQUEST_TYPE_NOMINAL;
2485 req.width = char_width;
2486 req.height = char_height;
Werner Lemberg106eaf12007-05-03 07:07:47 +00002487 req.horiResolution = horz_resolution;
2488 req.vertResolution = vert_resolution;
David Turnerd2b1f351999-12-16 23:11:37 +00002489
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002490 return FT_Request_Size( face, &req );
David Turnerd2b1f351999-12-16 23:11:37 +00002491 }
2492
2493
Werner Lemberg90a03302000-11-07 17:21:11 +00002494 /* documentation is in freetype.h */
2495
Werner Lembergf814d0f2001-06-27 16:18:10 +00002496 FT_EXPORT_DEF( FT_Error )
2497 FT_Set_Pixel_Sizes( FT_Face face,
2498 FT_UInt pixel_width,
2499 FT_UInt pixel_height )
David Turnerd2b1f351999-12-16 23:11:37 +00002500 {
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002501 FT_Size_RequestRec req;
David Turnerd2b1f351999-12-16 23:11:37 +00002502
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00002503
Wu, Chia-I (吳佳一)2e48a1a2006-02-27 09:18:07 +00002504 if ( pixel_width == 0 )
2505 pixel_width = pixel_height;
2506 else if ( pixel_height == 0 )
2507 pixel_height = pixel_width;
2508
2509 if ( pixel_width < 1 )
2510 pixel_width = 1;
2511 if ( pixel_height < 1 )
2512 pixel_height = 1;
2513
Werner Lemberg6e87ed92007-01-26 22:18:56 +00002514 /* use `>=' to avoid potential compiler warning on 16bit platforms */
Wu, Chia-I (吳佳一)2e48a1a2006-02-27 09:18:07 +00002515 if ( pixel_width >= 0xFFFFU )
2516 pixel_width = 0xFFFFU;
2517 if ( pixel_height >= 0xFFFFU )
2518 pixel_height = 0xFFFFU;
2519
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002520 req.type = FT_SIZE_REQUEST_TYPE_NOMINAL;
2521 req.width = pixel_width << 6;
2522 req.height = pixel_height << 6;
2523 req.horiResolution = 0;
2524 req.vertResolution = 0;
David Turnerd2b1f351999-12-16 23:11:37 +00002525
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002526 return FT_Request_Size( face, &req );
David Turnerd2b1f351999-12-16 23:11:37 +00002527 }
2528
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00002529
Werner Lemberg90a03302000-11-07 17:21:11 +00002530 /* documentation is in freetype.h */
2531
Werner Lembergf814d0f2001-06-27 16:18:10 +00002532 FT_EXPORT_DEF( FT_Error )
2533 FT_Get_Kerning( FT_Face face,
2534 FT_UInt left_glyph,
2535 FT_UInt right_glyph,
2536 FT_UInt kern_mode,
2537 FT_Vector *akerning )
David Turnerd2b1f351999-12-16 23:11:37 +00002538 {
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00002539 FT_Error error = FT_Err_Ok;
David Turnerd2b1f351999-12-16 23:11:37 +00002540 FT_Driver driver;
David Turnerd2b1f351999-12-16 23:11:37 +00002541
Werner Lemberga8bbc262000-07-01 14:06:46 +00002542
David Turnerd2b1f351999-12-16 23:11:37 +00002543 if ( !face )
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00002544 return FT_Err_Invalid_Face_Handle;
2545
Werner Lemberg4b680072000-11-07 06:30:29 +00002546 if ( !akerning )
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00002547 return FT_Err_Invalid_Argument;
David Turnerd2b1f351999-12-16 23:11:37 +00002548
2549 driver = face->driver;
David Turnerd2b1f351999-12-16 23:11:37 +00002550
Werner Lemberg4b680072000-11-07 06:30:29 +00002551 akerning->x = 0;
2552 akerning->y = 0;
Werner Lemberg5aa646c2000-07-14 06:16:47 +00002553
David Turnerf0df85b2000-06-22 00:17:42 +00002554 if ( driver->clazz->get_kerning )
David Turnerd2b1f351999-12-16 23:11:37 +00002555 {
David Turnerf0df85b2000-06-22 00:17:42 +00002556 error = driver->clazz->get_kerning( face,
Werner Lemberga929ba92000-06-25 06:47:11 +00002557 left_glyph,
2558 right_glyph,
Werner Lemberg4b680072000-11-07 06:30:29 +00002559 akerning );
Werner Lemberg5aa646c2000-07-14 06:16:47 +00002560 if ( !error )
David Turnerf9ca2bb2000-06-30 23:12:55 +00002561 {
David Turnerb08fe2d2002-08-27 20:20:29 +00002562 if ( kern_mode != FT_KERNING_UNSCALED )
David Turnerf9ca2bb2000-06-30 23:12:55 +00002563 {
Werner Lemberg4b680072000-11-07 06:30:29 +00002564 akerning->x = FT_MulFix( akerning->x, face->size->metrics.x_scale );
2565 akerning->y = FT_MulFix( akerning->y, face->size->metrics.y_scale );
Werner Lemberg5aa646c2000-07-14 06:16:47 +00002566
David Turnerb08fe2d2002-08-27 20:20:29 +00002567 if ( kern_mode != FT_KERNING_UNFITTED )
Werner Lemberg5aa646c2000-07-14 06:16:47 +00002568 {
Werner Lemberg133eee02004-12-12 06:55:40 +00002569 /* we scale down kerning values for small ppem values */
2570 /* to avoid that rounding makes them too big. */
2571 /* `25' has been determined heuristically. */
2572 if ( face->size->metrics.x_ppem < 25 )
2573 akerning->x = FT_MulDiv( akerning->x,
2574 face->size->metrics.x_ppem, 25 );
2575 if ( face->size->metrics.y_ppem < 25 )
2576 akerning->y = FT_MulDiv( akerning->y,
2577 face->size->metrics.y_ppem, 25 );
2578
2579 akerning->x = FT_PIX_ROUND( akerning->x );
2580 akerning->y = FT_PIX_ROUND( akerning->y );
Werner Lemberg5aa646c2000-07-14 06:16:47 +00002581 }
David Turnerf9ca2bb2000-06-30 23:12:55 +00002582 }
2583 }
2584 }
David Turnerd2b1f351999-12-16 23:11:37 +00002585
David Turnerd2b1f351999-12-16 23:11:37 +00002586 return error;
2587 }
2588
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00002589
Werner Lemberg90a03302000-11-07 17:21:11 +00002590 /* documentation is in freetype.h */
2591
Werner Lembergf814d0f2001-06-27 16:18:10 +00002592 FT_EXPORT_DEF( FT_Error )
Wu, Chia-I (吳佳一)108fdbb2006-01-16 15:35:56 +00002593 FT_Get_Track_Kerning( FT_Face face,
2594 FT_Fixed point_size,
2595 FT_Int degree,
2596 FT_Fixed* akerning )
2597 {
2598 FT_Service_Kerning service;
2599 FT_Error error = FT_Err_Ok;
Wu, Chia-I (吳佳一)108fdbb2006-01-16 15:35:56 +00002600
2601
2602 if ( !face )
2603 return FT_Err_Invalid_Face_Handle;
2604
2605 if ( !akerning )
2606 return FT_Err_Invalid_Argument;
2607
Wu, Chia-I (吳佳一)108fdbb2006-01-16 15:35:56 +00002608 FT_FACE_FIND_SERVICE( face, service, KERNING );
2609 if ( !service )
2610 return FT_Err_Unimplemented_Feature;
2611
2612 error = service->get_track( face,
2613 point_size,
2614 degree,
2615 akerning );
2616
2617 return error;
2618 }
2619
2620
2621 /* documentation is in freetype.h */
2622
2623 FT_EXPORT_DEF( FT_Error )
Werner Lembergf814d0f2001-06-27 16:18:10 +00002624 FT_Select_Charmap( FT_Face face,
2625 FT_Encoding encoding )
David Turner0a29c692000-05-12 17:09:38 +00002626 {
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00002627 FT_CharMap* cur;
2628 FT_CharMap* limit;
David Turnere49ab252000-05-16 23:44:38 +00002629
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00002630
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00002631 if ( !face )
2632 return FT_Err_Invalid_Face_Handle;
2633
Werner Lemberge88c5262006-10-24 05:46:26 +00002634 if ( encoding == FT_ENCODING_NONE )
2635 return FT_Err_Invalid_Argument;
2636
Werner Lembergc8c6bf52003-04-23 05:38:13 +00002637 /* FT_ENCODING_UNICODE is special. We try to find the `best' Unicode */
2638 /* charmap available, i.e., one with UCS-4 characters, if possible. */
2639 /* */
2640 /* This is done by find_unicode_charmap() above, to share code. */
Antoine Lecac96f69d2002-12-03 00:39:16 +00002641 if ( encoding == FT_ENCODING_UNICODE )
2642 return find_unicode_charmap( face );
2643
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00002644 cur = face->charmaps;
2645 if ( !cur )
2646 return FT_Err_Invalid_CharMap_Handle;
2647
2648 limit = cur + face->num_charmaps;
2649
David Turner0a29c692000-05-12 17:09:38 +00002650 for ( ; cur < limit; cur++ )
2651 {
2652 if ( cur[0]->encoding == encoding )
2653 {
2654 face->charmap = cur[0];
2655 return 0;
2656 }
2657 }
Werner Lembergdeb4e982000-06-29 03:14:25 +00002658
David Turner0a29c692000-05-12 17:09:38 +00002659 return FT_Err_Invalid_Argument;
2660 }
2661
2662
Werner Lemberg90a03302000-11-07 17:21:11 +00002663 /* documentation is in freetype.h */
2664
Werner Lembergf814d0f2001-06-27 16:18:10 +00002665 FT_EXPORT_DEF( FT_Error )
2666 FT_Set_Charmap( FT_Face face,
2667 FT_CharMap charmap )
David Turner0a29c692000-05-12 17:09:38 +00002668 {
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00002669 FT_CharMap* cur;
2670 FT_CharMap* limit;
David Turnere49ab252000-05-16 23:44:38 +00002671
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00002672
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00002673 if ( !face )
2674 return FT_Err_Invalid_Face_Handle;
2675
2676 cur = face->charmaps;
2677 if ( !cur )
2678 return FT_Err_Invalid_CharMap_Handle;
Werner Lemberg9a966b72007-10-15 17:21:32 +00002679 if ( FT_Get_CMap_Format( charmap ) == 14 )
2680 return FT_Err_Invalid_Argument;
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00002681
2682 limit = cur + face->num_charmaps;
2683
David Turner0a29c692000-05-12 17:09:38 +00002684 for ( ; cur < limit; cur++ )
2685 {
2686 if ( cur[0] == charmap )
2687 {
2688 face->charmap = cur[0];
2689 return 0;
2690 }
2691 }
2692 return FT_Err_Invalid_Argument;
2693 }
David Turnerd2b1f351999-12-16 23:11:37 +00002694
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00002695
Werner Lemberge95365b2004-04-24 14:43:37 +00002696 /* documentation is in freetype.h */
2697
2698 FT_EXPORT_DEF( FT_Int )
2699 FT_Get_Charmap_Index( FT_CharMap charmap )
2700 {
2701 FT_Int i;
2702
2703
2704 for ( i = 0; i < charmap->face->num_charmaps; i++ )
2705 if ( charmap->face->charmaps[i] == charmap )
2706 break;
2707
2708 FT_ASSERT( i < charmap->face->num_charmaps );
2709
2710 return i;
2711 }
2712
2713
Werner Lemberge70371c2005-05-27 06:01:28 +00002714 static void
2715 ft_cmap_done_internal( FT_CMap cmap )
2716 {
2717 FT_CMap_Class clazz = cmap->clazz;
2718 FT_Face face = cmap->charmap.face;
2719 FT_Memory memory = FT_FACE_MEMORY(face);
2720
2721
2722 if ( clazz->done )
2723 clazz->done( cmap );
2724
2725 FT_FREE( cmap );
2726 }
2727
2728
David Turner4e7eeee2002-02-28 16:10:29 +00002729 FT_BASE_DEF( void )
2730 FT_CMap_Done( FT_CMap cmap )
2731 {
2732 if ( cmap )
2733 {
Werner Lemberge70371c2005-05-27 06:01:28 +00002734 FT_Face face = cmap->charmap.face;
2735 FT_Memory memory = FT_FACE_MEMORY( face );
2736 FT_Error error;
2737 FT_Int i, j;
David Turnerbc82f1b2002-03-01 02:26:22 +00002738
Werner Lembergf8ba2002002-03-30 13:16:35 +00002739
Werner Lemberge70371c2005-05-27 06:01:28 +00002740 for ( i = 0; i < face->num_charmaps; i++ )
2741 {
2742 if ( (FT_CMap)face->charmaps[i] == cmap )
2743 {
2744 FT_CharMap last_charmap = face->charmaps[face->num_charmaps - 1];
David Turner4e7eeee2002-02-28 16:10:29 +00002745
Werner Lemberge70371c2005-05-27 06:01:28 +00002746
2747 if ( FT_RENEW_ARRAY( face->charmaps,
2748 face->num_charmaps,
2749 face->num_charmaps - 1 ) )
2750 return;
2751
2752 /* remove it from our list of charmaps */
2753 for ( j = i + 1; j < face->num_charmaps; j++ )
2754 {
2755 if ( j == face->num_charmaps - 1 )
2756 face->charmaps[j - 1] = last_charmap;
2757 else
2758 face->charmaps[j - 1] = face->charmaps[j];
2759 }
2760
2761 face->num_charmaps--;
2762
2763 if ( (FT_CMap)face->charmap == cmap )
2764 face->charmap = NULL;
2765
2766 ft_cmap_done_internal( cmap );
2767
2768 break;
2769 }
2770 }
David Turner4e7eeee2002-02-28 16:10:29 +00002771 }
2772 }
2773
2774
2775 FT_BASE_DEF( FT_Error )
Werner Lemberg9cc4aed2006-01-26 21:03:58 +00002776 FT_CMap_New( FT_CMap_Class clazz,
2777 FT_Pointer init_data,
2778 FT_CharMap charmap,
2779 FT_CMap *acmap )
David Turnerbc82f1b2002-03-01 02:26:22 +00002780 {
Werner Lemberg8acb8672005-03-08 11:43:36 +00002781 FT_Error error = FT_Err_Ok;
David Turner4e7eeee2002-02-28 16:10:29 +00002782 FT_Face face;
2783 FT_Memory memory;
2784 FT_CMap cmap;
David Turnerbc82f1b2002-03-01 02:26:22 +00002785
Werner Lembergf8ba2002002-03-30 13:16:35 +00002786
David Turner4e7eeee2002-02-28 16:10:29 +00002787 if ( clazz == NULL || charmap == NULL || charmap->face == NULL )
2788 return FT_Err_Invalid_Argument;
2789
2790 face = charmap->face;
Werner Lembergf35ff802003-06-02 21:58:05 +00002791 memory = FT_FACE_MEMORY( face );
David Turner4e7eeee2002-02-28 16:10:29 +00002792
David Turnere459d742002-03-22 13:52:37 +00002793 if ( !FT_ALLOC( cmap, clazz->size ) )
David Turner4e7eeee2002-02-28 16:10:29 +00002794 {
2795 cmap->charmap = *charmap;
2796 cmap->clazz = clazz;
David Turnerbc82f1b2002-03-01 02:26:22 +00002797
David Turner4e7eeee2002-02-28 16:10:29 +00002798 if ( clazz->init )
2799 {
David Turnerbc82f1b2002-03-01 02:26:22 +00002800 error = clazz->init( cmap, init_data );
Werner Lembergf8ba2002002-03-30 13:16:35 +00002801 if ( error )
David Turner4e7eeee2002-02-28 16:10:29 +00002802 goto Fail;
2803 }
David Turnerbc82f1b2002-03-01 02:26:22 +00002804
David Turner4e7eeee2002-02-28 16:10:29 +00002805 /* add it to our list of charmaps */
David Turnere459d742002-03-22 13:52:37 +00002806 if ( FT_RENEW_ARRAY( face->charmaps,
2807 face->num_charmaps,
Werner Lemberg8acb8672005-03-08 11:43:36 +00002808 face->num_charmaps + 1 ) )
David Turner4e7eeee2002-02-28 16:10:29 +00002809 goto Fail;
David Turnerbc82f1b2002-03-01 02:26:22 +00002810
Werner Lembergf8ba2002002-03-30 13:16:35 +00002811 face->charmaps[face->num_charmaps++] = (FT_CharMap)cmap;
David Turner4e7eeee2002-02-28 16:10:29 +00002812 }
David Turnerbc82f1b2002-03-01 02:26:22 +00002813
David Turner4e7eeee2002-02-28 16:10:29 +00002814 Exit:
2815 if ( acmap )
2816 *acmap = cmap;
2817
2818 return error;
David Turnerbc82f1b2002-03-01 02:26:22 +00002819
David Turner4e7eeee2002-02-28 16:10:29 +00002820 Fail:
Werner Lemberge70371c2005-05-27 06:01:28 +00002821 ft_cmap_done_internal( cmap );
David Turner4e7eeee2002-02-28 16:10:29 +00002822 cmap = NULL;
2823 goto Exit;
David Turnerbc82f1b2002-03-01 02:26:22 +00002824 }
David Turner4e7eeee2002-02-28 16:10:29 +00002825
2826
Werner Lemberg90a03302000-11-07 17:21:11 +00002827 /* documentation is in freetype.h */
2828
Werner Lembergf814d0f2001-06-27 16:18:10 +00002829 FT_EXPORT_DEF( FT_UInt )
2830 FT_Get_Char_Index( FT_Face face,
2831 FT_ULong charcode )
David Turnerd2b1f351999-12-16 23:11:37 +00002832 {
David Turnered54f282002-03-22 17:09:52 +00002833 FT_UInt result = 0;
2834
2835
2836 if ( face && face->charmap )
2837 {
2838 FT_CMap cmap = FT_CMAP( face->charmap );
David Turner25a6e3a2002-06-10 23:03:35 +00002839
Werner Lembergf8ba2002002-03-30 13:16:35 +00002840
David Turnered54f282002-03-22 17:09:52 +00002841 result = cmap->clazz->char_index( cmap, charcode );
2842 }
2843 return result;
2844 }
2845
David Turnered54f282002-03-22 17:09:52 +00002846
Werner Lemberg0f7c2f12002-02-04 20:55:58 +00002847 /* documentation is in freetype.h */
2848
2849 FT_EXPORT_DEF( FT_ULong )
David Turner041889e2002-02-28 19:28:26 +00002850 FT_Get_First_Char( FT_Face face,
2851 FT_UInt *agindex )
Werner Lemberg0f7c2f12002-02-04 20:55:58 +00002852 {
Werner Lembergf8ba2002002-03-30 13:16:35 +00002853 FT_ULong result = 0;
2854 FT_UInt gindex = 0;
2855
David Turnerbc82f1b2002-03-01 02:26:22 +00002856
David Turner041889e2002-02-28 19:28:26 +00002857 if ( face && face->charmap )
2858 {
2859 gindex = FT_Get_Char_Index( face, 0 );
2860 if ( gindex == 0 )
2861 result = FT_Get_Next_Char( face, 0, &gindex );
2862 }
David Turnerbc82f1b2002-03-01 02:26:22 +00002863
David Turner041889e2002-02-28 19:28:26 +00002864 if ( agindex )
2865 *agindex = gindex;
David Turnerbc82f1b2002-03-01 02:26:22 +00002866
David Turner041889e2002-02-28 19:28:26 +00002867 return result;
2868 }
2869
David Turner041889e2002-02-28 19:28:26 +00002870
Werner Lemberg7b0cc662003-07-05 07:46:49 +00002871 /* documentation is in freetype.h */
David Turnered54f282002-03-22 17:09:52 +00002872
David Turnered54f282002-03-22 17:09:52 +00002873 FT_EXPORT_DEF( FT_ULong )
2874 FT_Get_Next_Char( FT_Face face,
2875 FT_ULong charcode,
2876 FT_UInt *agindex )
2877 {
Werner Lembergf8ba2002002-03-30 13:16:35 +00002878 FT_ULong result = 0;
2879 FT_UInt gindex = 0;
David Turnered54f282002-03-22 17:09:52 +00002880
2881
2882 if ( face && face->charmap )
2883 {
2884 FT_UInt32 code = (FT_UInt32)charcode;
2885 FT_CMap cmap = FT_CMAP( face->charmap );
2886
Werner Lembergf8ba2002002-03-30 13:16:35 +00002887
David Turnered54f282002-03-22 17:09:52 +00002888 gindex = cmap->clazz->char_next( cmap, &code );
2889 result = ( gindex == 0 ) ? 0 : code;
2890 }
2891
2892 if ( agindex )
2893 *agindex = gindex;
2894
2895 return result;
2896 }
2897
David Turnered54f282002-03-22 17:09:52 +00002898
Werner Lemberg90a03302000-11-07 17:21:11 +00002899 /* documentation is in freetype.h */
2900
Tom Kacvinskyff2714f2001-08-08 10:58:08 +00002901 FT_EXPORT_DEF( FT_UInt )
David Turnercf432db2007-10-19 12:36:40 +00002902 FT_Face_GetCharVariantIndex( FT_Face face,
2903 FT_ULong charcode,
2904 FT_ULong variantSelector )
Werner Lemberg9a966b72007-10-15 17:21:32 +00002905 {
2906 FT_UInt result = 0;
2907
2908
2909 if ( face && face->charmap &&
2910 face->charmap->encoding == FT_ENCODING_UNICODE )
2911 {
2912 FT_CharMap charmap = find_variant_selector_charmap( face );
2913 FT_CMap ucmap = FT_CMAP( face->charmap );
2914
2915
2916 if ( charmap != NULL )
2917 {
2918 FT_CMap vcmap = FT_CMAP( charmap );
2919
2920
2921 result = vcmap->clazz->char_var_index( vcmap, ucmap, charcode,
2922 variantSelector );
2923 }
2924 }
2925
2926 return result;
2927 }
2928
2929
2930 /* documentation is in freetype.h */
2931
2932 FT_EXPORT_DEF( FT_Int )
David Turnercf432db2007-10-19 12:36:40 +00002933 FT_Face_GetCharVariantIsDefault( FT_Face face,
2934 FT_ULong charcode,
2935 FT_ULong variantSelector )
Werner Lemberg9a966b72007-10-15 17:21:32 +00002936 {
2937 FT_Int result = -1;
2938
2939
2940 if ( face )
2941 {
2942 FT_CharMap charmap = find_variant_selector_charmap( face );
2943
2944
2945 if ( charmap != NULL )
2946 {
2947 FT_CMap vcmap = FT_CMAP( charmap );
2948
2949
2950 result = vcmap->clazz->char_var_default( vcmap, charcode,
2951 variantSelector );
2952 }
2953 }
2954
2955 return result;
2956 }
2957
2958
2959 /* documentation is in freetype.h */
2960
2961 FT_EXPORT_DEF( FT_UInt32* )
David Turnercf432db2007-10-19 12:36:40 +00002962 FT_Face_GetVariantSelectors( FT_Face face )
Werner Lemberg9a966b72007-10-15 17:21:32 +00002963 {
2964 FT_UInt32 *result = NULL;
2965
2966
2967 if ( face )
2968 {
2969 FT_CharMap charmap = find_variant_selector_charmap( face );
2970
2971
2972 if ( charmap != NULL )
2973 {
2974 FT_CMap vcmap = FT_CMAP( charmap );
2975 FT_Memory memory = FT_FACE_MEMORY( face );
2976
2977
2978 result = vcmap->clazz->variant_list( vcmap, memory );
2979 }
2980 }
2981
2982 return result;
2983 }
2984
2985
2986 /* documentation is in freetype.h */
2987
2988 FT_EXPORT_DEF( FT_UInt32* )
David Turnercf432db2007-10-19 12:36:40 +00002989 FT_Face_GetVariantsOfChar( FT_Face face,
2990 FT_ULong charcode )
Werner Lemberg9a966b72007-10-15 17:21:32 +00002991 {
2992 FT_UInt32 *result = NULL;
2993
2994
2995 if ( face )
2996 {
2997 FT_CharMap charmap = find_variant_selector_charmap( face );
2998
2999
3000 if ( charmap != NULL )
3001 {
3002 FT_CMap vcmap = FT_CMAP( charmap );
3003 FT_Memory memory = FT_FACE_MEMORY( face );
3004
3005
3006 result = vcmap->clazz->charvariant_list( vcmap, memory, charcode );
3007 }
3008 }
3009 return result;
3010 }
3011
3012
3013 /* documentation is in freetype.h */
3014
3015 FT_EXPORT_DEF( FT_UInt32* )
David Turnercf432db2007-10-19 12:36:40 +00003016 FT_Face_GetCharsOfVariant( FT_Face face,
3017 FT_ULong variantSelector )
Werner Lemberg9a966b72007-10-15 17:21:32 +00003018 {
3019 FT_UInt32 *result = NULL;
3020
3021
3022 if ( face )
3023 {
3024 FT_CharMap charmap = find_variant_selector_charmap( face );
3025
3026
3027 if ( charmap != NULL )
3028 {
3029 FT_CMap vcmap = FT_CMAP( charmap );
3030 FT_Memory memory = FT_FACE_MEMORY( face );
3031
3032
3033 result = vcmap->clazz->variantchar_list( vcmap, memory,
3034 variantSelector );
3035 }
3036 }
3037
3038 return result;
3039 }
3040
3041
3042 /* documentation is in freetype.h */
3043
3044 FT_EXPORT_DEF( FT_UInt )
Tom Kacvinskyff2714f2001-08-08 10:58:08 +00003045 FT_Get_Name_Index( FT_Face face,
3046 FT_String* glyph_name )
3047 {
3048 FT_UInt result = 0;
3049
3050
3051 if ( face && FT_HAS_GLYPH_NAMES( face ) )
3052 {
David Turnerc313c502003-09-11 19:51:54 +00003053 FT_Service_GlyphDict service;
Tom Kacvinskyff2714f2001-08-08 10:58:08 +00003054
Werner Lemberg013efd12003-09-17 05:26:33 +00003055
Werner Lemberg46333a12003-09-17 19:20:02 +00003056 FT_FACE_LOOKUP_SERVICE( face,
David Turnere2d12842003-09-21 17:15:55 +00003057 service,
3058 GLYPH_DICT );
Werner Lemberg013efd12003-09-17 05:26:33 +00003059
David Turnerc313c502003-09-11 19:51:54 +00003060 if ( service && service->name_index )
3061 result = service->name_index( face, glyph_name );
Werner Lemberg013efd12003-09-17 05:26:33 +00003062 }
3063
Tom Kacvinskyff2714f2001-08-08 10:58:08 +00003064 return result;
3065 }
3066
Werner Lembergaef3fc82001-12-17 16:21:22 +00003067
Tom Kacvinskyff2714f2001-08-08 10:58:08 +00003068 /* documentation is in freetype.h */
3069
Werner Lembergf814d0f2001-06-27 16:18:10 +00003070 FT_EXPORT_DEF( FT_Error )
3071 FT_Get_Glyph_Name( FT_Face face,
3072 FT_UInt glyph_index,
3073 FT_Pointer buffer,
3074 FT_UInt buffer_max )
David Turner6930b452000-07-19 17:13:03 +00003075 {
3076 FT_Error error = FT_Err_Invalid_Argument;
Werner Lembergeddd9902000-10-12 05:05:40 +00003077
Werner Lembergd060a752000-07-20 06:57:41 +00003078
David Turner6930b452000-07-19 17:13:03 +00003079 /* clean up buffer */
Werner Lembergd060a752000-07-20 06:57:41 +00003080 if ( buffer && buffer_max > 0 )
David Turner6930b452000-07-19 17:13:03 +00003081 ((FT_Byte*)buffer)[0] = 0;
Werner Lembergeddd9902000-10-12 05:05:40 +00003082
Werner Lembergfd97d132002-06-16 01:14:16 +00003083 if ( face &&
3084 glyph_index <= (FT_UInt)face->num_glyphs &&
3085 FT_HAS_GLYPH_NAMES( face ) )
David Turner6930b452000-07-19 17:13:03 +00003086 {
David Turnerc313c502003-09-11 19:51:54 +00003087 FT_Service_GlyphDict service;
David Turner6930b452000-07-19 17:13:03 +00003088
Werner Lemberg013efd12003-09-17 05:26:33 +00003089
Werner Lemberg46333a12003-09-17 19:20:02 +00003090 FT_FACE_LOOKUP_SERVICE( face,
David Turnere2d12842003-09-21 17:15:55 +00003091 service,
3092 GLYPH_DICT );
Werner Lembergd060a752000-07-20 06:57:41 +00003093
David Turnerc313c502003-09-11 19:51:54 +00003094 if ( service && service->get_name )
David Turnerc313c502003-09-11 19:51:54 +00003095 error = service->get_name( face, glyph_index, buffer, buffer_max );
David Turner6930b452000-07-19 17:13:03 +00003096 }
Werner Lembergd060a752000-07-20 06:57:41 +00003097
David Turner6930b452000-07-19 17:13:03 +00003098 return error;
Werner Lembergeddd9902000-10-12 05:05:40 +00003099 }
David Turner6930b452000-07-19 17:13:03 +00003100
3101
David Turner23bcde12001-10-17 13:48:10 +00003102 /* documentation is in freetype.h */
3103
3104 FT_EXPORT_DEF( const char* )
3105 FT_Get_Postscript_Name( FT_Face face )
3106 {
3107 const char* result = NULL;
Werner Lemberg1a0a9792002-01-03 22:06:13 +00003108
Werner Lembergc3b21602001-12-05 01:22:05 +00003109
David Turner23bcde12001-10-17 13:48:10 +00003110 if ( !face )
3111 goto Exit;
3112
David Turner23bcde12001-10-17 13:48:10 +00003113 if ( !result )
3114 {
David Turnerb72d8a82003-09-29 20:33:37 +00003115 FT_Service_PsFontName service;
Werner Lembergc3b21602001-12-05 01:22:05 +00003116
Werner Lemberg013efd12003-09-17 05:26:33 +00003117
Werner Lemberg46333a12003-09-17 19:20:02 +00003118 FT_FACE_LOOKUP_SERVICE( face,
David Turnere2d12842003-09-21 17:15:55 +00003119 service,
David Turnerb72d8a82003-09-29 20:33:37 +00003120 POSTSCRIPT_FONT_NAME );
David Turner23bcde12001-10-17 13:48:10 +00003121
David Turnerb72d8a82003-09-29 20:33:37 +00003122 if ( service && service->get_ps_font_name )
3123 result = service->get_ps_font_name( face );
David Turner23bcde12001-10-17 13:48:10 +00003124 }
Werner Lemberg013efd12003-09-17 05:26:33 +00003125
David Turner23bcde12001-10-17 13:48:10 +00003126 Exit:
3127 return result;
3128 }
3129
3130
Werner Lemberg90a03302000-11-07 17:21:11 +00003131 /* documentation is in tttables.h */
3132
Werner Lembergf814d0f2001-06-27 16:18:10 +00003133 FT_EXPORT_DEF( void* )
3134 FT_Get_Sfnt_Table( FT_Face face,
3135 FT_Sfnt_Tag tag )
David Turner99a4d932000-04-25 16:10:50 +00003136 {
Werner Lemberg40bb0962003-11-01 14:36:20 +00003137 void* table = 0;
3138 FT_Service_SFNT_Table service;
David Turnere49ab252000-05-16 23:44:38 +00003139
Werner Lemberg013efd12003-09-17 05:26:33 +00003140
David Turnerc313c502003-09-11 19:51:54 +00003141 if ( face && FT_IS_SFNT( face ) )
3142 {
David Turnerb72d8a82003-09-29 20:33:37 +00003143 FT_FACE_FIND_SERVICE( face, service, SFNT_TABLE );
David Turnerc313c502003-09-11 19:51:54 +00003144 if ( service != NULL )
3145 table = service->get_table( face, tag );
3146 }
David Turnere2d12842003-09-21 17:15:55 +00003147
David Turner99a4d932000-04-25 16:10:50 +00003148 return table;
David Turnere49ab252000-05-16 23:44:38 +00003149 }
David Turner99a4d932000-04-25 16:10:50 +00003150
3151
David Turner621e4882002-12-16 21:51:24 +00003152 /* documentation is in tttables.h */
3153
3154 FT_EXPORT_DEF( FT_Error )
Werner Lembergc8c6bf52003-04-23 05:38:13 +00003155 FT_Load_Sfnt_Table( FT_Face face,
3156 FT_ULong tag,
3157 FT_Long offset,
3158 FT_Byte* buffer,
3159 FT_ULong* length )
David Turner621e4882002-12-16 21:51:24 +00003160 {
David Turnerc313c502003-09-11 19:51:54 +00003161 FT_Service_SFNT_Table service;
David Turner621e4882002-12-16 21:51:24 +00003162
3163
3164 if ( !face || !FT_IS_SFNT( face ) )
3165 return FT_Err_Invalid_Face_Handle;
3166
David Turnerb72d8a82003-09-29 20:33:37 +00003167 FT_FACE_FIND_SERVICE( face, service, SFNT_TABLE );
David Turnerc313c502003-09-11 19:51:54 +00003168 if ( service == NULL )
David Turner621e4882002-12-16 21:51:24 +00003169 return FT_Err_Unimplemented_Feature;
David Turnere2d12842003-09-21 17:15:55 +00003170
David Turnerc313c502003-09-11 19:51:54 +00003171 return service->load_table( face, tag, offset, buffer, length );
David Turner621e4882002-12-16 21:51:24 +00003172 }
3173
3174
Werner Lemberg17439422004-08-11 05:25:37 +00003175 /* documentation is in tttables.h */
3176
3177 FT_EXPORT_DEF( FT_Error )
3178 FT_Sfnt_Table_Info( FT_Face face,
3179 FT_UInt table_index,
3180 FT_ULong *tag,
3181 FT_ULong *length )
3182 {
3183 FT_Service_SFNT_Table service;
3184
3185
3186 if ( !face || !FT_IS_SFNT( face ) )
3187 return FT_Err_Invalid_Face_Handle;
3188
3189 FT_FACE_FIND_SERVICE( face, service, SFNT_TABLE );
3190 if ( service == NULL )
3191 return FT_Err_Unimplemented_Feature;
3192
3193 return service->table_info( face, table_index, tag, length );
3194 }
3195
3196
Werner Lembergece8b202004-12-13 23:16:59 +00003197 /* documentation is in tttables.h */
3198
Werner Lemberg91a67472003-12-17 14:28:22 +00003199 FT_EXPORT_DEF( FT_ULong )
3200 FT_Get_CMap_Language_ID( FT_CharMap charmap )
3201 {
3202 FT_Service_TTCMaps service;
3203 FT_Face face;
3204 TT_CMapInfo cmap_info;
3205
David Turner87c0d302003-12-24 01:10:46 +00003206
Werner Lemberg91a67472003-12-17 14:28:22 +00003207 if ( !charmap || !charmap->face )
3208 return 0;
3209
3210 face = charmap->face;
3211 FT_FACE_FIND_SERVICE( face, service, TT_CMAP );
3212 if ( service == NULL )
3213 return 0;
3214 if ( service->get_cmap_info( charmap, &cmap_info ))
3215 return 0;
3216
3217 return cmap_info.language;
3218 }
3219
3220
Werner Lembergb826fa72007-05-19 07:18:48 +00003221 /* documentation is in tttables.h */
3222
3223 FT_EXPORT_DEF( FT_Long )
3224 FT_Get_CMap_Format( FT_CharMap charmap )
3225 {
3226 FT_Service_TTCMaps service;
3227 FT_Face face;
3228 TT_CMapInfo cmap_info;
3229
3230
3231 if ( !charmap || !charmap->face )
3232 return -1;
3233
3234 face = charmap->face;
3235 FT_FACE_FIND_SERVICE( face, service, TT_CMAP );
3236 if ( service == NULL )
3237 return -1;
3238 if ( service->get_cmap_info( charmap, &cmap_info ))
3239 return -1;
3240
3241 return cmap_info.format;
3242 }
3243
3244
Werner Lembergece8b202004-12-13 23:16:59 +00003245 /* documentation is in ftsizes.h */
3246
David Turnerb3ba40d2001-10-07 13:30:26 +00003247 FT_EXPORT_DEF( FT_Error )
Werner Lemberg80b8d772001-10-10 19:56:42 +00003248 FT_Activate_Size( FT_Size size )
David Turnerb3ba40d2001-10-07 13:30:26 +00003249 {
3250 FT_Face face;
Werner Lemberg1a0a9792002-01-03 22:06:13 +00003251
Werner Lemberg80b8d772001-10-10 19:56:42 +00003252
David Turnerb3ba40d2001-10-07 13:30:26 +00003253 if ( size == NULL )
3254 return FT_Err_Bad_Argument;
Werner Lemberg1a0a9792002-01-03 22:06:13 +00003255
David Turnerb3ba40d2001-10-07 13:30:26 +00003256 face = size->face;
3257 if ( face == NULL || face->driver == NULL )
3258 return FT_Err_Bad_Argument;
Werner Lemberg1a0a9792002-01-03 22:06:13 +00003259
Werner Lemberg80b8d772001-10-10 19:56:42 +00003260 /* we don't need anything more complex than that; all size objects */
3261 /* are already listed by the face */
David Turnerb3ba40d2001-10-07 13:30:26 +00003262 face->size = size;
Werner Lemberg1a0a9792002-01-03 22:06:13 +00003263
David Turnerb3ba40d2001-10-07 13:30:26 +00003264 return FT_Err_Ok;
3265 }
3266
3267
David Turnerd2b1f351999-12-16 23:11:37 +00003268 /*************************************************************************/
David Turnerf0df85b2000-06-22 00:17:42 +00003269 /*************************************************************************/
3270 /*************************************************************************/
3271 /**** ****/
3272 /**** ****/
3273 /**** R E N D E R E R S ****/
3274 /**** ****/
3275 /**** ****/
3276 /*************************************************************************/
3277 /*************************************************************************/
3278 /*************************************************************************/
3279
Werner Lembergdeb4e982000-06-29 03:14:25 +00003280 /* lookup a renderer by glyph format in the library's list */
Werner Lembergf814d0f2001-06-27 16:18:10 +00003281 FT_BASE_DEF( FT_Renderer )
3282 FT_Lookup_Renderer( FT_Library library,
3283 FT_Glyph_Format format,
3284 FT_ListNode* node )
David Turnerf0df85b2000-06-22 00:17:42 +00003285 {
Werner Lembergf8ba2002002-03-30 13:16:35 +00003286 FT_ListNode cur;
3287 FT_Renderer result = 0;
Werner Lemberga929ba92000-06-25 06:47:11 +00003288
Werner Lembergdeb4e982000-06-29 03:14:25 +00003289
3290 if ( !library )
3291 goto Exit;
3292
3293 cur = library->renderers.head;
3294
3295 if ( node )
David Turner74abee82000-06-27 23:31:53 +00003296 {
Werner Lembergdeb4e982000-06-29 03:14:25 +00003297 if ( *node )
David Turner74abee82000-06-27 23:31:53 +00003298 cur = (*node)->next;
David Turnerf0df85b2000-06-22 00:17:42 +00003299 *node = 0;
David Turner74abee82000-06-27 23:31:53 +00003300 }
Werner Lembergdeb4e982000-06-29 03:14:25 +00003301
Werner Lemberga929ba92000-06-25 06:47:11 +00003302 while ( cur )
David Turnerf0df85b2000-06-22 00:17:42 +00003303 {
Werner Lemberga929ba92000-06-25 06:47:11 +00003304 FT_Renderer renderer = FT_RENDERER( cur->data );
Werner Lembergdeb4e982000-06-29 03:14:25 +00003305
Werner Lemberga929ba92000-06-25 06:47:11 +00003306
3307 if ( renderer->glyph_format == format )
David Turnerf0df85b2000-06-22 00:17:42 +00003308 {
Werner Lemberga929ba92000-06-25 06:47:11 +00003309 if ( node )
David Turnerf0df85b2000-06-22 00:17:42 +00003310 *node = cur;
Werner Lembergdeb4e982000-06-29 03:14:25 +00003311
David Turnerf0df85b2000-06-22 00:17:42 +00003312 result = renderer;
3313 break;
3314 }
David Turner74abee82000-06-27 23:31:53 +00003315 cur = cur->next;
David Turnerf0df85b2000-06-22 00:17:42 +00003316 }
Werner Lemberga929ba92000-06-25 06:47:11 +00003317
Werner Lembergdeb4e982000-06-29 03:14:25 +00003318 Exit:
David Turnerf0df85b2000-06-22 00:17:42 +00003319 return result;
3320 }
3321
Werner Lemberga929ba92000-06-25 06:47:11 +00003322
Werner Lembergf814d0f2001-06-27 16:18:10 +00003323 static FT_Renderer
3324 ft_lookup_glyph_renderer( FT_GlyphSlot slot )
Werner Lembergdeb4e982000-06-29 03:14:25 +00003325 {
3326 FT_Face face = slot->face;
3327 FT_Library library = FT_FACE_LIBRARY( face );
3328 FT_Renderer result = library->cur_renderer;
3329
3330
Werner Lemberga929ba92000-06-25 06:47:11 +00003331 if ( !result || result->glyph_format != slot->format )
David Turner81bb4ad2000-06-28 04:19:49 +00003332 result = FT_Lookup_Renderer( library, slot->format, 0 );
Werner Lembergfbeb41d2000-07-02 00:27:53 +00003333
David Turnerf0df85b2000-06-22 00:17:42 +00003334 return result;
3335 }
3336
Werner Lembergdeb4e982000-06-29 03:14:25 +00003337
Werner Lembergf814d0f2001-06-27 16:18:10 +00003338 static void
3339 ft_set_current_renderer( FT_Library library )
David Turnerf0df85b2000-06-22 00:17:42 +00003340 {
3341 FT_Renderer renderer;
3342
Werner Lembergdeb4e982000-06-29 03:14:25 +00003343
David Turnerb08fe2d2002-08-27 20:20:29 +00003344 renderer = FT_Lookup_Renderer( library, FT_GLYPH_FORMAT_OUTLINE, 0 );
David Turnerf0df85b2000-06-22 00:17:42 +00003345 library->cur_renderer = renderer;
3346 }
3347
3348
Werner Lembergf814d0f2001-06-27 16:18:10 +00003349 static FT_Error
3350 ft_add_renderer( FT_Module module )
David Turnerf0df85b2000-06-22 00:17:42 +00003351 {
3352 FT_Library library = module->library;
3353 FT_Memory memory = library->memory;
3354 FT_Error error;
3355 FT_ListNode node;
Werner Lembergdeb4e982000-06-29 03:14:25 +00003356
3357
David Turnere459d742002-03-22 13:52:37 +00003358 if ( FT_NEW( node ) )
David Turnerf0df85b2000-06-22 00:17:42 +00003359 goto Exit;
Werner Lembergdeb4e982000-06-29 03:14:25 +00003360
David Turnerf0df85b2000-06-22 00:17:42 +00003361 {
Werner Lemberga929ba92000-06-25 06:47:11 +00003362 FT_Renderer render = FT_RENDERER( module );
David Turnerf0df85b2000-06-22 00:17:42 +00003363 FT_Renderer_Class* clazz = (FT_Renderer_Class*)module->clazz;
3364
Werner Lemberga929ba92000-06-25 06:47:11 +00003365
David Turnerf0df85b2000-06-22 00:17:42 +00003366 render->clazz = clazz;
3367 render->glyph_format = clazz->glyph_format;
Werner Lembergdeb4e982000-06-29 03:14:25 +00003368
David Turnerf0df85b2000-06-22 00:17:42 +00003369 /* allocate raster object if needed */
David Turnerb08fe2d2002-08-27 20:20:29 +00003370 if ( clazz->glyph_format == FT_GLYPH_FORMAT_OUTLINE &&
David Turnerf0df85b2000-06-22 00:17:42 +00003371 clazz->raster_class->raster_new )
3372 {
3373 error = clazz->raster_class->raster_new( memory, &render->raster );
Werner Lemberga929ba92000-06-25 06:47:11 +00003374 if ( error )
3375 goto Fail;
Werner Lembergdeb4e982000-06-29 03:14:25 +00003376
David Turnerf0df85b2000-06-22 00:17:42 +00003377 render->raster_render = clazz->raster_class->raster_render;
3378 render->render = clazz->render_glyph;
Werner Lembergdeb4e982000-06-29 03:14:25 +00003379 }
3380
David Turnerf0df85b2000-06-22 00:17:42 +00003381 /* add to list */
3382 node->data = module;
3383 FT_List_Add( &library->renderers, node );
3384
3385 ft_set_current_renderer( library );
3386 }
3387
3388 Fail:
Werner Lemberga929ba92000-06-25 06:47:11 +00003389 if ( error )
David Turnere459d742002-03-22 13:52:37 +00003390 FT_FREE( node );
David Turnerf0df85b2000-06-22 00:17:42 +00003391
3392 Exit:
3393 return error;
Werner Lembergdeb4e982000-06-29 03:14:25 +00003394 }
David Turnerf0df85b2000-06-22 00:17:42 +00003395
3396
Werner Lembergf814d0f2001-06-27 16:18:10 +00003397 static void
3398 ft_remove_renderer( FT_Module module )
David Turnerf0df85b2000-06-22 00:17:42 +00003399 {
3400 FT_Library library = module->library;
3401 FT_Memory memory = library->memory;
3402 FT_ListNode node;
3403
Werner Lemberga929ba92000-06-25 06:47:11 +00003404
David Turnerf0df85b2000-06-22 00:17:42 +00003405 node = FT_List_Find( &library->renderers, module );
Werner Lemberga929ba92000-06-25 06:47:11 +00003406 if ( node )
David Turnerf0df85b2000-06-22 00:17:42 +00003407 {
Werner Lemberga929ba92000-06-25 06:47:11 +00003408 FT_Renderer render = FT_RENDERER( module );
Werner Lembergdeb4e982000-06-29 03:14:25 +00003409
Werner Lemberga929ba92000-06-25 06:47:11 +00003410
David Turnerf0df85b2000-06-22 00:17:42 +00003411 /* release raster object, if any */
Werner Lemberga929ba92000-06-25 06:47:11 +00003412 if ( render->raster )
David Turnerf0df85b2000-06-22 00:17:42 +00003413 render->clazz->raster_class->raster_done( render->raster );
Werner Lembergdeb4e982000-06-29 03:14:25 +00003414
David Turnerf0df85b2000-06-22 00:17:42 +00003415 /* remove from list */
3416 FT_List_Remove( &library->renderers, node );
David Turnere459d742002-03-22 13:52:37 +00003417 FT_FREE( node );
Werner Lembergdeb4e982000-06-29 03:14:25 +00003418
David Turnerf0df85b2000-06-22 00:17:42 +00003419 ft_set_current_renderer( library );
3420 }
3421 }
3422
3423
Werner Lemberg90a03302000-11-07 17:21:11 +00003424 /* documentation is in ftrender.h */
3425
Werner Lembergf814d0f2001-06-27 16:18:10 +00003426 FT_EXPORT_DEF( FT_Renderer )
3427 FT_Get_Renderer( FT_Library library,
3428 FT_Glyph_Format format )
David Turnerf0df85b2000-06-22 00:17:42 +00003429 {
Werner Lembergdeb4e982000-06-29 03:14:25 +00003430 /* test for valid `library' delayed to FT_Lookup_Renderer() */
3431
Werner Lembergf8ba2002002-03-30 13:16:35 +00003432 return FT_Lookup_Renderer( library, format, 0 );
Werner Lembergdeb4e982000-06-29 03:14:25 +00003433 }
David Turnerf0df85b2000-06-22 00:17:42 +00003434
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_Error )
3439 FT_Set_Renderer( FT_Library library,
3440 FT_Renderer renderer,
3441 FT_UInt num_params,
3442 FT_Parameter* parameters )
David Turnerf0df85b2000-06-22 00:17:42 +00003443 {
3444 FT_ListNode node;
3445 FT_Error error = FT_Err_Ok;
Werner Lembergdeb4e982000-06-29 03:14:25 +00003446
3447
3448 if ( !library )
3449 return FT_Err_Invalid_Library_Handle;
3450
3451 if ( !renderer )
3452 return FT_Err_Invalid_Argument;
Werner Lemberga929ba92000-06-25 06:47:11 +00003453
David Turnerf0df85b2000-06-22 00:17:42 +00003454 node = FT_List_Find( &library->renderers, renderer );
Werner Lemberga929ba92000-06-25 06:47:11 +00003455 if ( !node )
David Turnerf0df85b2000-06-22 00:17:42 +00003456 {
3457 error = FT_Err_Invalid_Argument;
3458 goto Exit;
3459 }
David Turner74abee82000-06-27 23:31:53 +00003460
David Turnerf0df85b2000-06-22 00:17:42 +00003461 FT_List_Up( &library->renderers, node );
Werner Lembergdeb4e982000-06-29 03:14:25 +00003462
David Turnerb08fe2d2002-08-27 20:20:29 +00003463 if ( renderer->glyph_format == FT_GLYPH_FORMAT_OUTLINE )
David Turnerf0df85b2000-06-22 00:17:42 +00003464 library->cur_renderer = renderer;
Werner Lembergdeb4e982000-06-29 03:14:25 +00003465
Werner Lemberga929ba92000-06-25 06:47:11 +00003466 if ( num_params > 0 )
David Turnerf0df85b2000-06-22 00:17:42 +00003467 {
David Turnerb08fe2d2002-08-27 20:20:29 +00003468 FT_Renderer_SetModeFunc set_mode = renderer->clazz->set_mode;
Werner Lembergdeb4e982000-06-29 03:14:25 +00003469
Werner Lemberga929ba92000-06-25 06:47:11 +00003470
David Turnerf0df85b2000-06-22 00:17:42 +00003471 for ( ; num_params > 0; num_params-- )
3472 {
3473 error = set_mode( renderer, parameters->tag, parameters->data );
Werner Lemberga929ba92000-06-25 06:47:11 +00003474 if ( error )
David Turnerf0df85b2000-06-22 00:17:42 +00003475 break;
3476 }
3477 }
Werner Lembergdeb4e982000-06-29 03:14:25 +00003478
David Turnerf0df85b2000-06-22 00:17:42 +00003479 Exit:
3480 return error;
Werner Lembergdeb4e982000-06-29 03:14:25 +00003481 }
David Turnerf0df85b2000-06-22 00:17:42 +00003482
3483
David Turner7504e482002-06-07 07:24:55 +00003484 FT_BASE_DEF( FT_Error )
Werner Lemberg68e9f922002-09-27 11:09:23 +00003485 FT_Render_Glyph_Internal( FT_Library library,
3486 FT_GlyphSlot slot,
3487 FT_Render_Mode render_mode )
David Turnerf0df85b2000-06-22 00:17:42 +00003488 {
3489 FT_Error error = FT_Err_Ok;
3490 FT_Renderer renderer;
Werner Lemberga929ba92000-06-25 06:47:11 +00003491
Werner Lembergdeb4e982000-06-29 03:14:25 +00003492
3493 /* if it is already a bitmap, no need to do anything */
3494 switch ( slot->format )
David Turnerf0df85b2000-06-22 00:17:42 +00003495 {
David Turnerb08fe2d2002-08-27 20:20:29 +00003496 case FT_GLYPH_FORMAT_BITMAP: /* already a bitmap, don't do anything */
Werner Lembergdeb4e982000-06-29 03:14:25 +00003497 break;
3498
3499 default:
David Turner74abee82000-06-27 23:31:53 +00003500 {
3501 FT_ListNode node = 0;
3502 FT_Bool update = 0;
Werner Lembergdeb4e982000-06-29 03:14:25 +00003503
3504
Werner Lemberga929ba92000-06-25 06:47:11 +00003505 /* small shortcut for the very common case */
David Turnerb08fe2d2002-08-27 20:20:29 +00003506 if ( slot->format == FT_GLYPH_FORMAT_OUTLINE )
David Turner74abee82000-06-27 23:31:53 +00003507 {
Werner Lemberga929ba92000-06-25 06:47:11 +00003508 renderer = library->cur_renderer;
David Turner74abee82000-06-27 23:31:53 +00003509 node = library->renderers.head;
3510 }
Werner Lemberga929ba92000-06-25 06:47:11 +00003511 else
David Turner74abee82000-06-27 23:31:53 +00003512 renderer = FT_Lookup_Renderer( library, slot->format, &node );
3513
Werner Lemberga929ba92000-06-25 06:47:11 +00003514 error = FT_Err_Unimplemented_Feature;
Werner Lembergdeb4e982000-06-29 03:14:25 +00003515 while ( renderer )
David Turner74abee82000-06-27 23:31:53 +00003516 {
David Turnerc8ad30a2001-12-05 17:24:34 +00003517 error = renderer->render( renderer, slot, render_mode, NULL );
Werner Lemberg79860702001-06-08 21:17:29 +00003518 if ( !error ||
3519 FT_ERROR_BASE( error ) != FT_Err_Cannot_Render_Glyph )
Werner Lembergdeb4e982000-06-29 03:14:25 +00003520 break;
David Turner74abee82000-06-27 23:31:53 +00003521
Werner Lembergdeb4e982000-06-29 03:14:25 +00003522 /* FT_Err_Cannot_Render_Glyph is returned if the render mode */
David Turner74abee82000-06-27 23:31:53 +00003523 /* is unsupported by the current renderer for this glyph image */
Werner Lembergdeb4e982000-06-29 03:14:25 +00003524 /* format. */
3525
3526 /* now, look for another renderer that supports the same */
3527 /* format. */
David Turner74abee82000-06-27 23:31:53 +00003528 renderer = FT_Lookup_Renderer( library, slot->format, &node );
3529 update = 1;
3530 }
3531
3532 /* if we changed the current renderer for the glyph image format */
Werner Lembergdeb4e982000-06-29 03:14:25 +00003533 /* we need to select it as the next current one */
3534 if ( !error && update && renderer )
David Turner74abee82000-06-27 23:31:53 +00003535 FT_Set_Renderer( library, renderer, 0, 0 );
David Turnerf0df85b2000-06-22 00:17:42 +00003536 }
3537 }
Werner Lembergdeb4e982000-06-29 03:14:25 +00003538
David Turnerf0df85b2000-06-22 00:17:42 +00003539 return error;
3540 }
Werner Lemberga929ba92000-06-25 06:47:11 +00003541
David Turner74abee82000-06-27 23:31:53 +00003542
Werner Lemberg90a03302000-11-07 17:21:11 +00003543 /* documentation is in freetype.h */
3544
Werner Lembergf814d0f2001-06-27 16:18:10 +00003545 FT_EXPORT_DEF( FT_Error )
Werner Lemberg68e9f922002-09-27 11:09:23 +00003546 FT_Render_Glyph( FT_GlyphSlot slot,
3547 FT_Render_Mode render_mode )
David Turner74abee82000-06-27 23:31:53 +00003548 {
Werner Lembergf8ba2002002-03-30 13:16:35 +00003549 FT_Library library;
Werner Lembergdeb4e982000-06-29 03:14:25 +00003550
3551
3552 if ( !slot )
David Turner74abee82000-06-27 23:31:53 +00003553 return FT_Err_Invalid_Argument;
Werner Lembergdeb4e982000-06-29 03:14:25 +00003554
3555 library = FT_FACE_LIBRARY( slot->face );
3556
David Turner74abee82000-06-27 23:31:53 +00003557 return FT_Render_Glyph_Internal( library, slot, render_mode );
3558 }
3559
Werner Lembergdeb4e982000-06-29 03:14:25 +00003560
David Turnerf0df85b2000-06-22 00:17:42 +00003561 /*************************************************************************/
3562 /*************************************************************************/
3563 /*************************************************************************/
3564 /**** ****/
3565 /**** ****/
3566 /**** M O D U L E S ****/
3567 /**** ****/
3568 /**** ****/
3569 /*************************************************************************/
3570 /*************************************************************************/
3571 /*************************************************************************/
3572
Werner Lemberga929ba92000-06-25 06:47:11 +00003573
David Turnerf0df85b2000-06-22 00:17:42 +00003574 /*************************************************************************/
3575 /* */
3576 /* <Function> */
3577 /* Destroy_Module */
3578 /* */
3579 /* <Description> */
3580 /* Destroys a given module object. For drivers, this also destroys */
Werner Lemberga929ba92000-06-25 06:47:11 +00003581 /* all child faces. */
David Turnerf0df85b2000-06-22 00:17:42 +00003582 /* */
3583 /* <InOut> */
3584 /* module :: A handle to the target driver object. */
3585 /* */
3586 /* <Note> */
3587 /* The driver _must_ be LOCKED! */
3588 /* */
Werner Lembergf814d0f2001-06-27 16:18:10 +00003589 static void
3590 Destroy_Module( FT_Module module )
David Turnerf0df85b2000-06-22 00:17:42 +00003591 {
David Turner5ae831c2000-06-30 01:31:22 +00003592 FT_Memory memory = module->memory;
3593 FT_Module_Class* clazz = module->clazz;
3594 FT_Library library = module->library;
David Turnerf0df85b2000-06-22 00:17:42 +00003595
Werner Lemberga929ba92000-06-25 06:47:11 +00003596
David Turnerf0df85b2000-06-22 00:17:42 +00003597 /* finalize client-data - before anything else */
3598 if ( module->generic.finalizer )
3599 module->generic.finalizer( module );
3600
David Turner5ae831c2000-06-30 01:31:22 +00003601 if ( library && library->auto_hinter == module )
3602 library->auto_hinter = 0;
3603
David Turnerf0df85b2000-06-22 00:17:42 +00003604 /* if the module is a renderer */
Werner Lemberga929ba92000-06-25 06:47:11 +00003605 if ( FT_MODULE_IS_RENDERER( module ) )
3606 ft_remove_renderer( module );
David Turnerf0df85b2000-06-22 00:17:42 +00003607
3608 /* if the module is a font driver, add some steps */
Werner Lemberga929ba92000-06-25 06:47:11 +00003609 if ( FT_MODULE_IS_DRIVER( module ) )
3610 Destroy_Driver( FT_DRIVER( module ) );
David Turnerf0df85b2000-06-22 00:17:42 +00003611
3612 /* finalize the module object */
Werner Lemberga929ba92000-06-25 06:47:11 +00003613 if ( clazz->module_done )
3614 clazz->module_done( module );
David Turnerf0df85b2000-06-22 00:17:42 +00003615
3616 /* discard it */
David Turnere459d742002-03-22 13:52:37 +00003617 FT_FREE( module );
David Turnerf0df85b2000-06-22 00:17:42 +00003618 }
3619
David Turnerf0df85b2000-06-22 00:17:42 +00003620
Werner Lemberg748b1712005-12-25 09:15:09 +00003621 /* documentation is in ftmodapi.h */
Werner Lemberg90a03302000-11-07 17:21:11 +00003622
Werner Lembergf814d0f2001-06-27 16:18:10 +00003623 FT_EXPORT_DEF( FT_Error )
3624 FT_Add_Module( FT_Library library,
3625 const FT_Module_Class* clazz )
David Turnerf0df85b2000-06-22 00:17:42 +00003626 {
3627 FT_Error error;
3628 FT_Memory memory;
3629 FT_Module module;
3630 FT_UInt nn;
3631
David Turnerf0df85b2000-06-22 00:17:42 +00003632
Werner Lembergdeb4e982000-06-29 03:14:25 +00003633#define FREETYPE_VER_FIXED ( ( (FT_Long)FREETYPE_MAJOR << 16 ) | \
3634 FREETYPE_MINOR )
Werner Lemberga929ba92000-06-25 06:47:11 +00003635
Werner Lembergdeb4e982000-06-29 03:14:25 +00003636 if ( !library )
3637 return FT_Err_Invalid_Library_Handle;
3638
3639 if ( !clazz )
David Turnerf0df85b2000-06-22 00:17:42 +00003640 return FT_Err_Invalid_Argument;
3641
3642 /* check freetype version */
3643 if ( clazz->module_requires > FREETYPE_VER_FIXED )
3644 return FT_Err_Invalid_Version;
3645
3646 /* look for a module with the same name in the library's table */
3647 for ( nn = 0; nn < library->num_modules; nn++ )
3648 {
3649 module = library->modules[nn];
David Turnerd15bc0d2002-04-12 09:31:48 +00003650 if ( ft_strcmp( module->clazz->module_name, clazz->module_name ) == 0 )
David Turnerf0df85b2000-06-22 00:17:42 +00003651 {
3652 /* this installed module has the same name, compare their versions */
3653 if ( clazz->module_version <= module->clazz->module_version )
3654 return FT_Err_Lower_Module_Version;
3655
3656 /* remove the module from our list, then exit the loop to replace */
3657 /* it by our new version.. */
3658 FT_Remove_Module( library, module );
3659 break;
3660 }
3661 }
3662
3663 memory = library->memory;
3664 error = FT_Err_Ok;
3665
3666 if ( library->num_modules >= FT_MAX_MODULES )
3667 {
3668 error = FT_Err_Too_Many_Drivers;
3669 goto Exit;
3670 }
3671
3672 /* allocate module object */
Werner Lemberg68e9f922002-09-27 11:09:23 +00003673 if ( FT_ALLOC( module, clazz->module_size ) )
David Turnerf0df85b2000-06-22 00:17:42 +00003674 goto Exit;
3675
Werner Lembergdeb4e982000-06-29 03:14:25 +00003676 /* base initialization */
David Turnerf0df85b2000-06-22 00:17:42 +00003677 module->library = library;
3678 module->memory = memory;
3679 module->clazz = (FT_Module_Class*)clazz;
3680
Werner Lembergdeb4e982000-06-29 03:14:25 +00003681 /* check whether the module is a renderer - this must be performed */
3682 /* before the normal module initialization */
Werner Lemberga929ba92000-06-25 06:47:11 +00003683 if ( FT_MODULE_IS_RENDERER( module ) )
David Turnerf0df85b2000-06-22 00:17:42 +00003684 {
3685 /* add to the renderers list */
Werner Lemberga929ba92000-06-25 06:47:11 +00003686 error = ft_add_renderer( module );
3687 if ( error )
3688 goto Fail;
David Turnerf0df85b2000-06-22 00:17:42 +00003689 }
3690
Werner Lembergcc9fc492000-06-30 06:21:26 +00003691 /* is the module a auto-hinter? */
3692 if ( FT_MODULE_IS_HINTER( module ) )
David Turner5ae831c2000-06-30 01:31:22 +00003693 library->auto_hinter = module;
Werner Lembergfbeb41d2000-07-02 00:27:53 +00003694
David Turnerf0df85b2000-06-22 00:17:42 +00003695 /* if the module is a font driver */
Werner Lemberga929ba92000-06-25 06:47:11 +00003696 if ( FT_MODULE_IS_DRIVER( module ) )
David Turnerf0df85b2000-06-22 00:17:42 +00003697 {
3698 /* allocate glyph loader if needed */
Werner Lembergf8ba2002002-03-30 13:16:35 +00003699 FT_Driver driver = FT_DRIVER( module );
Werner Lemberga929ba92000-06-25 06:47:11 +00003700
Werner Lembergdeb4e982000-06-29 03:14:25 +00003701
David Turneref3c1262002-03-14 09:22:48 +00003702 driver->clazz = (FT_Driver_Class)module->clazz;
Werner Lemberga929ba92000-06-25 06:47:11 +00003703 if ( FT_DRIVER_USES_OUTLINES( driver ) )
David Turnerf0df85b2000-06-22 00:17:42 +00003704 {
3705 error = FT_GlyphLoader_New( memory, &driver->glyph_loader );
Werner Lemberga929ba92000-06-25 06:47:11 +00003706 if ( error )
3707 goto Fail;
David Turnerf0df85b2000-06-22 00:17:42 +00003708 }
3709 }
3710
Werner Lemberga929ba92000-06-25 06:47:11 +00003711 if ( clazz->module_init )
David Turnerf0df85b2000-06-22 00:17:42 +00003712 {
Werner Lemberga929ba92000-06-25 06:47:11 +00003713 error = clazz->module_init( module );
3714 if ( error )
3715 goto Fail;
David Turnerf0df85b2000-06-22 00:17:42 +00003716 }
3717
3718 /* add module to the library's table */
Werner Lemberga929ba92000-06-25 06:47:11 +00003719 library->modules[library->num_modules++] = module;
Werner Lembergdeb4e982000-06-29 03:14:25 +00003720
David Turnerf0df85b2000-06-22 00:17:42 +00003721 Exit:
3722 return error;
Werner Lembergdeb4e982000-06-29 03:14:25 +00003723
David Turnerf0df85b2000-06-22 00:17:42 +00003724 Fail:
Werner Lemberga929ba92000-06-25 06:47:11 +00003725 if ( FT_MODULE_IS_DRIVER( module ) )
David Turnerf0df85b2000-06-22 00:17:42 +00003726 {
Werner Lemberga929ba92000-06-25 06:47:11 +00003727 FT_Driver driver = FT_DRIVER( module );
Werner Lembergdeb4e982000-06-29 03:14:25 +00003728
Werner Lemberga929ba92000-06-25 06:47:11 +00003729
3730 if ( FT_DRIVER_USES_OUTLINES( driver ) )
David Turnerf0df85b2000-06-22 00:17:42 +00003731 FT_GlyphLoader_Done( driver->glyph_loader );
3732 }
Werner Lembergdeb4e982000-06-29 03:14:25 +00003733
Werner Lemberga929ba92000-06-25 06:47:11 +00003734 if ( FT_MODULE_IS_RENDERER( module ) )
David Turnerf0df85b2000-06-22 00:17:42 +00003735 {
Werner Lemberga929ba92000-06-25 06:47:11 +00003736 FT_Renderer renderer = FT_RENDERER( module );
3737
3738
3739 if ( renderer->raster )
David Turnerf0df85b2000-06-22 00:17:42 +00003740 renderer->clazz->raster_class->raster_done( renderer->raster );
3741 }
Werner Lemberga929ba92000-06-25 06:47:11 +00003742
David Turnere459d742002-03-22 13:52:37 +00003743 FT_FREE( module );
David Turnerf0df85b2000-06-22 00:17:42 +00003744 goto Exit;
3745 }
3746
David Turnerf0df85b2000-06-22 00:17:42 +00003747
Werner Lemberg748b1712005-12-25 09:15:09 +00003748 /* documentation is in ftmodapi.h */
Werner Lemberg90a03302000-11-07 17:21:11 +00003749
Werner Lembergf814d0f2001-06-27 16:18:10 +00003750 FT_EXPORT_DEF( FT_Module )
3751 FT_Get_Module( FT_Library library,
3752 const char* module_name )
David Turnerf0df85b2000-06-22 00:17:42 +00003753 {
Werner Lembergdeb4e982000-06-29 03:14:25 +00003754 FT_Module result = 0;
3755 FT_Module* cur;
3756 FT_Module* limit;
David Turnerf0df85b2000-06-22 00:17:42 +00003757
Werner Lemberga929ba92000-06-25 06:47:11 +00003758
Werner Lembergdeb4e982000-06-29 03:14:25 +00003759 if ( !library || !module_name )
3760 return result;
3761
3762 cur = library->modules;
3763 limit = cur + library->num_modules;
3764
David Turnerf0df85b2000-06-22 00:17:42 +00003765 for ( ; cur < limit; cur++ )
David Turnerd15bc0d2002-04-12 09:31:48 +00003766 if ( ft_strcmp( cur[0]->clazz->module_name, module_name ) == 0 )
David Turnerf0df85b2000-06-22 00:17:42 +00003767 {
3768 result = cur[0];
3769 break;
3770 }
3771
3772 return result;
3773 }
3774
Werner Lemberga929ba92000-06-25 06:47:11 +00003775
Werner Lemberg8ec9dfd2000-11-07 23:56:02 +00003776 /* documentation is in ftobjs.h */
3777
Werner Lembergf814d0f2001-06-27 16:18:10 +00003778 FT_BASE_DEF( const void* )
3779 FT_Get_Module_Interface( FT_Library library,
3780 const char* mod_name )
David Turnerf0df85b2000-06-22 00:17:42 +00003781 {
3782 FT_Module module;
Werner Lembergdeb4e982000-06-29 03:14:25 +00003783
3784
3785 /* test for valid `library' delayed to FT_Get_Module() */
Werner Lemberga929ba92000-06-25 06:47:11 +00003786
David Turnerf0df85b2000-06-22 00:17:42 +00003787 module = FT_Get_Module( library, mod_name );
Werner Lemberga929ba92000-06-25 06:47:11 +00003788
David Turnerf0df85b2000-06-22 00:17:42 +00003789 return module ? module->clazz->module_interface : 0;
Werner Lembergdeb4e982000-06-29 03:14:25 +00003790 }
David Turnerf0df85b2000-06-22 00:17:42 +00003791
3792
David Turnerb72d8a82003-09-29 20:33:37 +00003793 FT_BASE_DEF( FT_Pointer )
3794 ft_module_get_service( FT_Module module,
3795 const char* service_id )
3796 {
3797 FT_Pointer result = NULL;
3798
3799 if ( module )
3800 {
3801 FT_ASSERT( module->clazz && module->clazz->get_interface );
3802
3803 /* first, look for the service in the module
3804 */
3805 if ( module->clazz->get_interface )
3806 result = module->clazz->get_interface( module, service_id );
3807
3808 if ( result == NULL )
3809 {
3810 /* we didn't find it, look in all other modules then
3811 */
3812 FT_Library library = module->library;
3813 FT_Module* cur = library->modules;
3814 FT_Module* limit = cur + library->num_modules;
3815
3816 for ( ; cur < limit; cur++ )
3817 {
3818 if ( cur[0] != module )
3819 {
3820 FT_ASSERT( cur[0]->clazz );
3821
3822 if ( cur[0]->clazz->get_interface )
3823 {
3824 result = cur[0]->clazz->get_interface( cur[0], service_id );
3825 if ( result != NULL )
3826 break;
3827 }
3828 }
3829 }
3830 }
3831 }
3832
3833 return result;
3834 }
3835
3836
Werner Lemberg748b1712005-12-25 09:15:09 +00003837 /* documentation is in ftmodapi.h */
Werner Lemberg90a03302000-11-07 17:21:11 +00003838
Werner Lembergf814d0f2001-06-27 16:18:10 +00003839 FT_EXPORT_DEF( FT_Error )
3840 FT_Remove_Module( FT_Library library,
3841 FT_Module module )
David Turnerf0df85b2000-06-22 00:17:42 +00003842 {
3843 /* try to find the module from the table, then remove it from there */
Werner Lembergdeb4e982000-06-29 03:14:25 +00003844
3845 if ( !library )
3846 return FT_Err_Invalid_Library_Handle;
3847
3848 if ( module )
David Turnerf0df85b2000-06-22 00:17:42 +00003849 {
3850 FT_Module* cur = library->modules;
3851 FT_Module* limit = cur + library->num_modules;
3852
Werner Lemberga929ba92000-06-25 06:47:11 +00003853
David Turnerf0df85b2000-06-22 00:17:42 +00003854 for ( ; cur < limit; cur++ )
3855 {
Werner Lembergdeb4e982000-06-29 03:14:25 +00003856 if ( cur[0] == module )
David Turnerf0df85b2000-06-22 00:17:42 +00003857 {
3858 /* remove it from the table */
3859 library->num_modules--;
3860 limit--;
Werner Lemberga929ba92000-06-25 06:47:11 +00003861 while ( cur < limit )
David Turnerf0df85b2000-06-22 00:17:42 +00003862 {
3863 cur[0] = cur[1];
3864 cur++;
3865 }
3866 limit[0] = 0;
3867
3868 /* destroy the module */
Werner Lemberga929ba92000-06-25 06:47:11 +00003869 Destroy_Module( module );
David Turnerf0df85b2000-06-22 00:17:42 +00003870
3871 return FT_Err_Ok;
3872 }
3873 }
3874 }
Werner Lembergb48a6092000-07-09 19:15:30 +00003875 return FT_Err_Invalid_Driver_Handle;
David Turnerf0df85b2000-06-22 00:17:42 +00003876 }
3877
3878
David Turnerf0df85b2000-06-22 00:17:42 +00003879 /*************************************************************************/
3880 /*************************************************************************/
3881 /*************************************************************************/
3882 /**** ****/
3883 /**** ****/
3884 /**** L I B R A R Y ****/
3885 /**** ****/
3886 /**** ****/
3887 /*************************************************************************/
3888 /*************************************************************************/
3889 /*************************************************************************/
3890
Werner Lemberga929ba92000-06-25 06:47:11 +00003891
Werner Lemberg748b1712005-12-25 09:15:09 +00003892 /* documentation is in ftmodapi.h */
Werner Lemberg90a03302000-11-07 17:21:11 +00003893
Werner Lembergf814d0f2001-06-27 16:18:10 +00003894 FT_EXPORT_DEF( FT_Error )
3895 FT_New_Library( FT_Memory memory,
3896 FT_Library *alibrary )
David Turnerf0df85b2000-06-22 00:17:42 +00003897 {
3898 FT_Library library = 0;
3899 FT_Error error;
3900
3901
3902 if ( !memory )
3903 return FT_Err_Invalid_Argument;
3904
David Turnerf5749602002-04-18 10:07:26 +00003905#ifdef FT_DEBUG_LEVEL_ERROR
David Turner53b3fa12002-02-24 05:26:57 +00003906 /* init debugging support */
3907 ft_debug_init();
David Turnerf5749602002-04-18 10:07:26 +00003908#endif
David Turner53b3fa12002-02-24 05:26:57 +00003909
David Turnerf0df85b2000-06-22 00:17:42 +00003910 /* first of all, allocate the library object */
David Turnere459d742002-03-22 13:52:37 +00003911 if ( FT_NEW( library ) )
David Turnerf0df85b2000-06-22 00:17:42 +00003912 return error;
3913
3914 library->memory = memory;
3915
3916 /* allocate the render pool */
3917 library->raster_pool_size = FT_RENDER_POOL_SIZE;
Werner Lemberg39c91ad2007-07-28 05:40:40 +00003918#if FT_RENDER_POOL_SIZE > 0
3919 if ( FT_ALLOC( library->raster_pool, FT_RENDER_POOL_SIZE ) )
3920 goto Fail;
3921#endif
David Turnerf0df85b2000-06-22 00:17:42 +00003922
3923 /* That's ok now */
3924 *alibrary = library;
3925
3926 return FT_Err_Ok;
3927
3928 Fail:
David Turnere459d742002-03-22 13:52:37 +00003929 FT_FREE( library );
David Turnerf0df85b2000-06-22 00:17:42 +00003930 return error;
3931 }
3932
3933
David Turner83b4a4b2002-03-06 12:42:34 +00003934 /* documentation is in freetype.h */
David Turner25a6e3a2002-06-10 23:03:35 +00003935
David Turner83b4a4b2002-03-06 12:42:34 +00003936 FT_EXPORT_DEF( void )
3937 FT_Library_Version( FT_Library library,
3938 FT_Int *amajor,
3939 FT_Int *aminor,
3940 FT_Int *apatch )
3941 {
3942 FT_Int major = 0;
3943 FT_Int minor = 0;
3944 FT_Int patch = 0;
3945
David Turner25a6e3a2002-06-10 23:03:35 +00003946
David Turner83b4a4b2002-03-06 12:42:34 +00003947 if ( library )
3948 {
3949 major = library->version_major;
3950 minor = library->version_minor;
3951 patch = library->version_patch;
3952 }
David Turner25a6e3a2002-06-10 23:03:35 +00003953
David Turnerd48575e2002-09-18 23:18:36 +00003954 if ( amajor )
David Turner83b4a4b2002-03-06 12:42:34 +00003955 *amajor = major;
David Turner25a6e3a2002-06-10 23:03:35 +00003956
David Turnerd48575e2002-09-18 23:18:36 +00003957 if ( aminor )
David Turner83b4a4b2002-03-06 12:42:34 +00003958 *aminor = minor;
David Turner25a6e3a2002-06-10 23:03:35 +00003959
David Turnerd48575e2002-09-18 23:18:36 +00003960 if ( apatch )
David Turner83b4a4b2002-03-06 12:42:34 +00003961 *apatch = patch;
David Turner25a6e3a2002-06-10 23:03:35 +00003962 }
David Turner83b4a4b2002-03-06 12:42:34 +00003963
3964
Werner Lemberg748b1712005-12-25 09:15:09 +00003965 /* documentation is in ftmodapi.h */
Werner Lemberg90a03302000-11-07 17:21:11 +00003966
Werner Lembergf814d0f2001-06-27 16:18:10 +00003967 FT_EXPORT_DEF( FT_Error )
3968 FT_Done_Library( FT_Library library )
David Turnerf0df85b2000-06-22 00:17:42 +00003969 {
3970 FT_Memory memory;
David Turnerf0df85b2000-06-22 00:17:42 +00003971
3972
3973 if ( !library )
3974 return FT_Err_Invalid_Library_Handle;
3975
3976 memory = library->memory;
3977
3978 /* Discard client-data */
3979 if ( library->generic.finalizer )
3980 library->generic.finalizer( library );
3981
Werner Lemberg4ea0a7f2007-01-05 09:03:31 +00003982 /* Close all faces in the library. If we don't do
David Turnera8cf42b2007-01-04 16:46:46 +00003983 * this, we can have some subtle memory leaks.
Werner Lemberg4ea0a7f2007-01-05 09:03:31 +00003984 * Example:
David Turnera8cf42b2007-01-04 16:46:46 +00003985 *
3986 * - the cff font driver uses the pshinter module in cff_size_done
3987 * - if the pshinter module is destroyed before the cff font driver,
Werner Lemberg4ea0a7f2007-01-05 09:03:31 +00003988 * opened FT_Face objects managed by the driver are not properly
David Turnera8cf42b2007-01-04 16:46:46 +00003989 * destroyed, resulting in a memory leak
3990 */
3991 {
3992 FT_UInt n;
3993
Werner Lemberg4ea0a7f2007-01-05 09:03:31 +00003994
David Turnera8cf42b2007-01-04 16:46:46 +00003995 for ( n = 0; n < library->num_modules; n++ )
3996 {
3997 FT_Module module = library->modules[n];
3998 FT_List faces;
3999
Werner Lemberg4ea0a7f2007-01-05 09:03:31 +00004000
4001 if ( ( module->clazz->module_flags & FT_MODULE_FONT_DRIVER ) == 0 )
David Turnera8cf42b2007-01-04 16:46:46 +00004002 continue;
4003
4004 faces = &FT_DRIVER(module)->faces_list;
Werner Lemberg4ea0a7f2007-01-05 09:03:31 +00004005 while ( faces->head )
4006 FT_Done_Face( FT_FACE( faces->head->data ) );
David Turnera8cf42b2007-01-04 16:46:46 +00004007 }
4008 }
4009
David Turnera8cf42b2007-01-04 16:46:46 +00004010 /* Close all other modules in the library */
Werner Lembergf41e71a2001-12-20 21:22:02 +00004011#if 1
Wu, Chia-I (吳佳一)a87b08a2006-02-28 09:53:23 +00004012 /* XXX Modules are removed in the reversed order so that */
David Turner2b21a932006-08-16 09:24:32 +00004013 /* type42 module is removed before truetype module. This */
Wu, Chia-I (吳佳一)a87b08a2006-02-28 09:53:23 +00004014 /* avoids double free in some occasions. It is a hack. */
David Turnerc8087482001-12-20 13:14:18 +00004015 while ( library->num_modules > 0 )
Wu, Chia-I (吳佳一)a87b08a2006-02-28 09:53:23 +00004016 FT_Remove_Module( library,
4017 library->modules[library->num_modules - 1] );
Werner Lembergf41e71a2001-12-20 21:22:02 +00004018#else
David Turnerf0df85b2000-06-22 00:17:42 +00004019 {
Werner Lembergf41e71a2001-12-20 21:22:02 +00004020 FT_UInt n;
David Turnerf0df85b2000-06-22 00:17:42 +00004021
Werner Lemberga929ba92000-06-25 06:47:11 +00004022
Werner Lembergf41e71a2001-12-20 21:22:02 +00004023 for ( n = 0; n < library->num_modules; n++ )
David Turnerf0df85b2000-06-22 00:17:42 +00004024 {
Werner Lembergf41e71a2001-12-20 21:22:02 +00004025 FT_Module module = library->modules[n];
4026
4027
4028 if ( module )
4029 {
4030 Destroy_Module( module );
4031 library->modules[n] = 0;
4032 }
David Turnerf0df85b2000-06-22 00:17:42 +00004033 }
4034 }
David Turnerc8087482001-12-20 13:14:18 +00004035#endif
David Turnerf0df85b2000-06-22 00:17:42 +00004036
4037 /* Destroy raster objects */
David Turnere459d742002-03-22 13:52:37 +00004038 FT_FREE( library->raster_pool );
David Turnerf0df85b2000-06-22 00:17:42 +00004039 library->raster_pool_size = 0;
4040
David Turnere459d742002-03-22 13:52:37 +00004041 FT_FREE( library );
David Turnerf0df85b2000-06-22 00:17:42 +00004042 return FT_Err_Ok;
4043 }
4044
4045
Werner Lemberg748b1712005-12-25 09:15:09 +00004046 /* documentation is in ftmodapi.h */
Werner Lemberg90a03302000-11-07 17:21:11 +00004047
Werner Lembergf814d0f2001-06-27 16:18:10 +00004048 FT_EXPORT_DEF( void )
4049 FT_Set_Debug_Hook( FT_Library library,
4050 FT_UInt hook_index,
4051 FT_DebugHook_Func debug_hook )
David Turnerf0df85b2000-06-22 00:17:42 +00004052 {
4053 if ( library && debug_hook &&
4054 hook_index <
4055 ( sizeof ( library->debug_hooks ) / sizeof ( void* ) ) )
4056 library->debug_hooks[hook_index] = debug_hook;
4057 }
4058
Werner Lemberg8e6f8c42006-02-17 08:07:09 +00004059
David Turner0b5dc4d2006-02-21 22:36:23 +00004060 /* documentation is in ftmodapi.h */
4061
4062 FT_EXPORT_DEF( FT_TrueTypeEngineType )
4063 FT_Get_TrueType_Engine_Type( FT_Library library )
4064 {
4065 FT_TrueTypeEngineType result = FT_TRUETYPE_ENGINE_TYPE_NONE;
4066
Werner Lemberg5edafed2006-02-22 08:23:35 +00004067
David Turner0b5dc4d2006-02-21 22:36:23 +00004068 if ( library )
4069 {
4070 FT_Module module = FT_Get_Module( library, "truetype" );
4071
Werner Lemberg5edafed2006-02-22 08:23:35 +00004072
David Turner0b5dc4d2006-02-21 22:36:23 +00004073 if ( module )
4074 {
4075 FT_Service_TrueTypeEngine service;
4076
Werner Lemberg5edafed2006-02-22 08:23:35 +00004077
David Turner6c71c6b2006-02-25 12:49:40 +00004078 service = (FT_Service_TrueTypeEngine)
4079 ft_module_get_service( module,
4080 FT_SERVICE_ID_TRUETYPE_ENGINE );
David Turner0b5dc4d2006-02-21 22:36:23 +00004081 if ( service )
4082 result = service->engine_type;
4083 }
4084 }
Werner Lemberg5edafed2006-02-22 08:23:35 +00004085
David Turner0b5dc4d2006-02-21 22:36:23 +00004086 return result;
4087 }
4088
Werner Lemberg5edafed2006-02-22 08:23:35 +00004089
David Turnercda2d952006-02-16 22:45:31 +00004090#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
Werner Lemberg8e6f8c42006-02-17 08:07:09 +00004091
David Turnercda2d952006-02-16 22:45:31 +00004092 FT_BASE_DEF( FT_Error )
4093 ft_stub_set_char_sizes( FT_Size size,
4094 FT_F26Dot6 width,
4095 FT_F26Dot6 height,
4096 FT_UInt horz_res,
4097 FT_UInt vert_res )
4098 {
4099 FT_Size_RequestRec req;
4100 FT_Driver driver = size->face->driver;
4101
Werner Lemberg8e6f8c42006-02-17 08:07:09 +00004102
David Turnercda2d952006-02-16 22:45:31 +00004103 if ( driver->clazz->request_size )
4104 {
4105 req.type = FT_SIZE_REQUEST_TYPE_NOMINAL;
4106 req.width = width;
4107 req.height = height;
4108
4109 if ( horz_res == 0 )
4110 horz_res = vert_res;
4111
4112 if ( vert_res == 0 )
4113 vert_res = horz_res;
4114
4115 if ( horz_res == 0 )
4116 horz_res = vert_res = 72;
4117
4118 req.horiResolution = horz_res;
4119 req.vertResolution = vert_res;
4120
4121 return driver->clazz->request_size( size, &req );
4122 }
Werner Lemberg8e6f8c42006-02-17 08:07:09 +00004123
David Turnercda2d952006-02-16 22:45:31 +00004124 return 0;
4125 }
4126
4127
4128 FT_BASE_DEF( FT_Error )
Werner Lemberg8e6f8c42006-02-17 08:07:09 +00004129 ft_stub_set_pixel_sizes( FT_Size size,
4130 FT_UInt width,
4131 FT_UInt height )
David Turnercda2d952006-02-16 22:45:31 +00004132 {
4133 FT_Size_RequestRec req;
4134 FT_Driver driver = size->face->driver;
4135
Werner Lemberg8e6f8c42006-02-17 08:07:09 +00004136
David Turnercda2d952006-02-16 22:45:31 +00004137 if ( driver->clazz->request_size )
4138 {
4139 req.type = FT_SIZE_REQUEST_TYPE_NOMINAL;
Werner Lemberg8e6f8c42006-02-17 08:07:09 +00004140 req.width = width << 6;
David Turnercda2d952006-02-16 22:45:31 +00004141 req.height = height << 6;
4142 req.horiResolution = 0;
4143 req.vertResolution = 0;
4144
4145 return driver->clazz->request_size( size, &req );
4146 }
Werner Lemberg8e6f8c42006-02-17 08:07:09 +00004147
David Turnercda2d952006-02-16 22:45:31 +00004148 return 0;
4149 }
Werner Lemberg8e6f8c42006-02-17 08:07:09 +00004150
David Turnercda2d952006-02-16 22:45:31 +00004151#endif /* FT_CONFIG_OPTION_OLD_INTERNALS */
David Turnerf0df85b2000-06-22 00:17:42 +00004152
David Turner2b21a932006-08-16 09:24:32 +00004153
David Turner2ce92032006-03-23 20:58:20 +00004154 FT_EXPORT_DEF( FT_Error )
4155 FT_Get_SubGlyph_Info( FT_GlyphSlot glyph,
4156 FT_UInt sub_index,
Werner Lemberg4db32ec2006-03-24 11:54:53 +00004157 FT_Int *p_index,
4158 FT_UInt *p_flags,
4159 FT_Int *p_arg1,
4160 FT_Int *p_arg2,
4161 FT_Matrix *p_transform )
David Turner2ce92032006-03-23 20:58:20 +00004162 {
Werner Lemberg4db32ec2006-03-24 11:54:53 +00004163 FT_Error error = FT_Err_Invalid_Argument;
Werner Lemberg4db32ec2006-03-24 11:54:53 +00004164
David Turner2b21a932006-08-16 09:24:32 +00004165
4166 if ( glyph != NULL &&
Werner Lemberg4db32ec2006-03-24 11:54:53 +00004167 glyph->format == FT_GLYPH_FORMAT_COMPOSITE &&
4168 sub_index < glyph->num_subglyphs )
4169 {
David Turner2ce92032006-03-23 20:58:20 +00004170 FT_SubGlyph subg = glyph->subglyphs + sub_index;
David Turner2b21a932006-08-16 09:24:32 +00004171
Werner Lemberg4db32ec2006-03-24 11:54:53 +00004172
4173 *p_index = subg->index;
4174 *p_flags = subg->flags;
4175 *p_arg1 = subg->arg1;
4176 *p_arg2 = subg->arg2;
4177 *p_transform = subg->transform;
4178 }
4179
4180 return error;
David Turner2ce92032006-03-23 20:58:20 +00004181 }
4182
Werner Lemberg4db32ec2006-03-24 11:54:53 +00004183
David Turnerd2b1f351999-12-16 23:11:37 +00004184/* END */