blob: 5702996c827a7b99ed74822941fbe159f61dd0b5 [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 Lemberg6cdab922006-01-08 22:34:01 +00007/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006 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 Turnerc313c502003-09-11 19:51:54 +000037
Werner Lemberg013efd12003-09-17 05:26:33 +000038
David Turnerc313c502003-09-11 19:51:54 +000039 FT_BASE_DEF( FT_Pointer )
40 ft_service_list_lookup( FT_ServiceDesc service_descriptors,
41 const char* service_id )
42 {
43 FT_Pointer result = NULL;
44 FT_ServiceDesc desc = service_descriptors;
David Turnere2d12842003-09-21 17:15:55 +000045
Werner Lemberg013efd12003-09-17 05:26:33 +000046
David Turnerc313c502003-09-11 19:51:54 +000047 if ( desc && service_id )
48 {
49 for ( ; desc->serv_id != NULL; desc++ )
50 {
51 if ( ft_strcmp( desc->serv_id, service_id ) == 0 )
52 {
Werner Lemberg013efd12003-09-17 05:26:33 +000053 result = (FT_Pointer)desc->serv_data;
David Turnerc313c502003-09-11 19:51:54 +000054 break;
55 }
56 }
57 }
Werner Lemberg013efd12003-09-17 05:26:33 +000058
David Turnerc313c502003-09-11 19:51:54 +000059 return result;
David Turnere2d12842003-09-21 17:15:55 +000060 }
Werner Lemberg3c403e42002-08-06 21:47:40 +000061
Werner Lemberg013efd12003-09-17 05:26:33 +000062
David Turnered54f282002-03-22 17:09:52 +000063 FT_BASE_DEF( void )
64 ft_validator_init( FT_Validator valid,
65 const FT_Byte* base,
66 const FT_Byte* limit,
67 FT_ValidationLevel level )
68 {
69 valid->base = base;
70 valid->limit = limit;
71 valid->level = level;
Werner Lemberg8acb8672005-03-08 11:43:36 +000072 valid->error = FT_Err_Ok;
David Turnered54f282002-03-22 17:09:52 +000073 }
David Turner25a6e3a2002-06-10 23:03:35 +000074
David Turnered54f282002-03-22 17:09:52 +000075
76 FT_BASE_DEF( FT_Int )
77 ft_validator_run( FT_Validator valid )
78 {
79 int result;
Werner Lembergf8ba2002002-03-30 13:16:35 +000080
David Turner25a6e3a2002-06-10 23:03:35 +000081
82 result = ft_setjmp( valid->jump_buffer );
David Turnered54f282002-03-22 17:09:52 +000083 return result;
84 }
85
Werner Lembergf8ba2002002-03-30 13:16:35 +000086
David Turnered54f282002-03-22 17:09:52 +000087 FT_BASE_DEF( void )
88 ft_validator_error( FT_Validator valid,
89 FT_Error error )
90 {
91 valid->error = error;
David Turner25a6e3a2002-06-10 23:03:35 +000092 ft_longjmp( valid->jump_buffer, 1 );
93 }
Werner Lemberga929ba92000-06-25 06:47:11 +000094
Werner Lemberga3b6c6c2000-05-31 06:55:12 +000095
David Turnerd2b1f351999-12-16 23:11:37 +000096 /*************************************************************************/
97 /*************************************************************************/
98 /*************************************************************************/
99 /**** ****/
100 /**** ****/
David Turnerf0df85b2000-06-22 00:17:42 +0000101 /**** S T R E A M ****/
102 /**** ****/
103 /**** ****/
104 /*************************************************************************/
105 /*************************************************************************/
106 /*************************************************************************/
107
Werner Lemberg7880dd62000-01-10 17:19:45 +0000108
Werner Lemberg75435332004-02-25 12:58:54 +0000109 /* create a new input stream from an FT_Open_Args structure */
110 /* */
111 FT_BASE_DEF( FT_Error )
112 FT_Stream_New( FT_Library library,
113 const FT_Open_Args* args,
114 FT_Stream *astream )
David Turner7663f222000-02-13 13:37:38 +0000115 {
Werner Lemberg547a2522000-02-16 08:23:58 +0000116 FT_Error error;
117 FT_Memory memory;
118 FT_Stream stream;
119
Werner Lemberga3b6c6c2000-05-31 06:55:12 +0000120
Werner Lemberg2fbf7e42000-06-02 00:01:14 +0000121 if ( !library )
122 return FT_Err_Invalid_Library_Handle;
123
124 if ( !args )
125 return FT_Err_Invalid_Argument;
126
David Turner37379e22000-03-28 11:22:31 +0000127 *astream = 0;
128 memory = library->memory;
Werner Lembergf8ba2002002-03-30 13:16:35 +0000129
David Turnere459d742002-03-22 13:52:37 +0000130 if ( FT_NEW( stream ) )
David Turner37379e22000-03-28 11:22:31 +0000131 goto Exit;
David Turnere49ab252000-05-16 23:44:38 +0000132
David Turner7663f222000-02-13 13:37:38 +0000133 stream->memory = memory;
David Turnere49ab252000-05-16 23:44:38 +0000134
David Turnerb08fe2d2002-08-27 20:20:29 +0000135 if ( args->flags & FT_OPEN_MEMORY )
Just van Rossumd35aea72000-03-02 01:07:50 +0000136 {
David Turner53b3fa12002-02-24 05:26:57 +0000137 /* create a memory-based stream */
David Turner7d3a2642002-03-20 10:49:31 +0000138 FT_Stream_OpenMemory( stream,
Werner Lembergf8ba2002002-03-30 13:16:35 +0000139 (const FT_Byte*)args->memory_base,
140 args->memory_size );
David Turner4f2c5542000-05-12 10:19:41 +0000141 }
David Turnerb08fe2d2002-08-27 20:20:29 +0000142 else if ( args->flags & FT_OPEN_PATHNAME )
David Turner4f2c5542000-05-12 10:19:41 +0000143 {
David Turner53b3fa12002-02-24 05:26:57 +0000144 /* create a normal system stream */
145 error = FT_Stream_Open( stream, args->pathname );
David Turner4f2c5542000-05-12 10:19:41 +0000146 stream->pathname.pointer = args->pathname;
147 }
David Turnerb08fe2d2002-08-27 20:20:29 +0000148 else if ( ( args->flags & FT_OPEN_STREAM ) && args->stream )
David Turner4f2c5542000-05-12 10:19:41 +0000149 {
David Turner53b3fa12002-02-24 05:26:57 +0000150 /* use an existing, user-provided stream */
151
Werner Lemberg58b17f92000-07-27 23:29:08 +0000152 /* in this case, we do not need to allocate a new stream object */
153 /* since the caller is responsible for closing it himself */
David Turnere459d742002-03-22 13:52:37 +0000154 FT_FREE( stream );
David Turnerc5cdf8b2000-07-27 21:40:22 +0000155 stream = args->stream;
David Turner4f2c5542000-05-12 10:19:41 +0000156 }
157 else
David Turner4f2c5542000-05-12 10:19:41 +0000158 error = FT_Err_Invalid_Argument;
David Turnere49ab252000-05-16 23:44:38 +0000159
Werner Lemberg547a2522000-02-16 08:23:58 +0000160 if ( error )
David Turnere459d742002-03-22 13:52:37 +0000161 FT_FREE( stream );
David Turner53b3fa12002-02-24 05:26:57 +0000162 else
163 stream->memory = memory; /* just to be certain */
David Turnere49ab252000-05-16 23:44:38 +0000164
David Turner7663f222000-02-13 13:37:38 +0000165 *astream = stream;
Werner Lemberga3b6c6c2000-05-31 06:55:12 +0000166
David Turner37379e22000-03-28 11:22:31 +0000167 Exit:
David Turner7663f222000-02-13 13:37:38 +0000168 return error;
169 }
170
171
Werner Lemberg75435332004-02-25 12:58:54 +0000172 FT_BASE_DEF( void )
173 FT_Stream_Free( FT_Stream stream,
174 FT_Int external )
David Turner7663f222000-02-13 13:37:38 +0000175 {
David Turner53b3fa12002-02-24 05:26:57 +0000176 if ( stream )
David Turnerc5cdf8b2000-07-27 21:40:22 +0000177 {
178 FT_Memory memory = stream->memory;
Werner Lemberg58b17f92000-07-27 23:29:08 +0000179
Werner Lembergf8ba2002002-03-30 13:16:35 +0000180
David Turner53b3fa12002-02-24 05:26:57 +0000181 FT_Stream_Close( stream );
Werner Lemberg58b17f92000-07-27 23:29:08 +0000182
David Turner53b3fa12002-02-24 05:26:57 +0000183 if ( !external )
David Turnere459d742002-03-22 13:52:37 +0000184 FT_FREE( stream );
David Turnerc5cdf8b2000-07-27 21:40:22 +0000185 }
David Turner7663f222000-02-13 13:37:38 +0000186 }
187
Werner Lemberga3b6c6c2000-05-31 06:55:12 +0000188
Werner Lembergeb81e372000-06-03 06:03:11 +0000189#undef FT_COMPONENT
190#define FT_COMPONENT trace_objs
191
Werner Lembergdeb4e982000-06-29 03:14:25 +0000192
David Turnerf0df85b2000-06-22 00:17:42 +0000193 /*************************************************************************/
194 /*************************************************************************/
195 /*************************************************************************/
196 /**** ****/
197 /**** ****/
198 /**** FACE, SIZE & GLYPH SLOT OBJECTS ****/
199 /**** ****/
200 /**** ****/
201 /*************************************************************************/
202 /*************************************************************************/
203 /*************************************************************************/
204
Werner Lembergdeb4e982000-06-29 03:14:25 +0000205
Werner Lembergf814d0f2001-06-27 16:18:10 +0000206 static FT_Error
207 ft_glyphslot_init( FT_GlyphSlot slot )
David Turnerf0df85b2000-06-22 00:17:42 +0000208 {
209 FT_Driver driver = slot->face->driver;
Werner Lembergf8ba2002002-03-30 13:16:35 +0000210 FT_Driver_Class clazz = driver->clazz;
David Turnerf0df85b2000-06-22 00:17:42 +0000211 FT_Memory memory = driver->root.memory;
212 FT_Error error = FT_Err_Ok;
David Turner54e75742000-11-04 02:52:02 +0000213 FT_Slot_Internal internal;
David Turnerf0df85b2000-06-22 00:17:42 +0000214
Werner Lemberga8bbc262000-07-01 14:06:46 +0000215
David Turnerf9ca2bb2000-06-30 23:12:55 +0000216 slot->library = driver->root.library;
Werner Lembergfbeb41d2000-07-02 00:27:53 +0000217
David Turnere459d742002-03-22 13:52:37 +0000218 if ( FT_NEW( internal ) )
David Turner54e75742000-11-04 02:52:02 +0000219 goto Exit;
220
221 slot->internal = internal;
222
Werner Lemberga929ba92000-06-25 06:47:11 +0000223 if ( FT_DRIVER_USES_OUTLINES( driver ) )
David Turner54e75742000-11-04 02:52:02 +0000224 error = FT_GlyphLoader_New( memory, &internal->loader );
David Turnerf0df85b2000-06-22 00:17:42 +0000225
Werner Lemberga929ba92000-06-25 06:47:11 +0000226 if ( !error && clazz->init_slot )
David Turnerf0df85b2000-06-22 00:17:42 +0000227 error = clazz->init_slot( slot );
228
David Turner54e75742000-11-04 02:52:02 +0000229 Exit:
David Turnerf0df85b2000-06-22 00:17:42 +0000230 return error;
231 }
232
Werner Lemberge20ab692003-06-02 07:24:33 +0000233
David Turner66cbc202003-03-20 07:04:40 +0000234 FT_BASE_DEF( void )
235 ft_glyphslot_free_bitmap( FT_GlyphSlot slot )
236 {
Werner Lemberg7a024102003-06-18 06:59:57 +0000237 if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP )
David Turner66cbc202003-03-20 07:04:40 +0000238 {
239 FT_Memory memory = FT_FACE_MEMORY( slot->face );
Werner Lemberg51daa4f2003-05-18 22:40:11 +0000240
241
David Turner66cbc202003-03-20 07:04:40 +0000242 FT_FREE( slot->bitmap.buffer );
Werner Lemberg7a024102003-06-18 06:59:57 +0000243 slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP;
David Turner66cbc202003-03-20 07:04:40 +0000244 }
245 else
246 {
247 /* assume that the bitmap buffer was stolen or not */
248 /* allocated from the heap */
249 slot->bitmap.buffer = NULL;
250 }
251 }
252
253
254 FT_BASE_DEF( void )
255 ft_glyphslot_set_bitmap( FT_GlyphSlot slot,
Werner Lemberg319c00d2003-04-23 19:48:24 +0000256 FT_Byte* buffer )
David Turner66cbc202003-03-20 07:04:40 +0000257 {
258 ft_glyphslot_free_bitmap( slot );
Werner Lemberg51daa4f2003-05-18 22:40:11 +0000259
David Turner66cbc202003-03-20 07:04:40 +0000260 slot->bitmap.buffer = buffer;
Werner Lemberg51daa4f2003-05-18 22:40:11 +0000261
Werner Lemberg7a024102003-06-18 06:59:57 +0000262 FT_ASSERT( (slot->internal->flags & FT_GLYPH_OWN_BITMAP) == 0 );
Werner Lemberg51daa4f2003-05-18 22:40:11 +0000263 }
David Turner66cbc202003-03-20 07:04:40 +0000264
265
266 FT_BASE_DEF( FT_Error )
267 ft_glyphslot_alloc_bitmap( FT_GlyphSlot slot,
268 FT_ULong size )
269 {
270 FT_Memory memory = FT_FACE_MEMORY( slot->face );
Werner Lemberg51daa4f2003-05-18 22:40:11 +0000271
272
Werner Lemberg7a024102003-06-18 06:59:57 +0000273 if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP )
David Turner66cbc202003-03-20 07:04:40 +0000274 FT_FREE( slot->bitmap.buffer );
275 else
Werner Lemberg7a024102003-06-18 06:59:57 +0000276 slot->internal->flags |= FT_GLYPH_OWN_BITMAP;
Werner Lemberg51daa4f2003-05-18 22:40:11 +0000277
David Turner66cbc202003-03-20 07:04:40 +0000278 return FT_MEM_ALLOC( slot->bitmap.buffer, size );
Werner Lemberg51daa4f2003-05-18 22:40:11 +0000279 }
David Turner66cbc202003-03-20 07:04:40 +0000280
David Turnerf0df85b2000-06-22 00:17:42 +0000281
Werner Lembergf814d0f2001-06-27 16:18:10 +0000282 static void
283 ft_glyphslot_clear( FT_GlyphSlot slot )
David Turnerf0df85b2000-06-22 00:17:42 +0000284 {
David Turner5ae831c2000-06-30 01:31:22 +0000285 /* free bitmap if needed */
David Turner66cbc202003-03-20 07:04:40 +0000286 ft_glyphslot_free_bitmap( slot );
Werner Lembergfbeb41d2000-07-02 00:27:53 +0000287
David Turnerf0df85b2000-06-22 00:17:42 +0000288 /* clear all public fields in the glyph slot */
David Turner3249c622002-10-31 08:30:19 +0000289 FT_ZERO( &slot->metrics );
290 FT_ZERO( &slot->outline );
291
Werner Lemberg0f1c4fa2005-06-06 07:01:47 +0000292 slot->bitmap.width = 0;
293 slot->bitmap.rows = 0;
294 slot->bitmap.pitch = 0;
David Turner3249c622002-10-31 08:30:19 +0000295 slot->bitmap.pixel_mode = 0;
Werner Lemberg0f1c4fa2005-06-06 07:01:47 +0000296 /* `slot->bitmap.buffer' has been handled by ft_glyphslot_free_bitmap */
David Turnerf0df85b2000-06-22 00:17:42 +0000297
298 slot->bitmap_left = 0;
299 slot->bitmap_top = 0;
300 slot->num_subglyphs = 0;
301 slot->subglyphs = 0;
302 slot->control_data = 0;
303 slot->control_len = 0;
304 slot->other = 0;
David Turnerb08fe2d2002-08-27 20:20:29 +0000305 slot->format = FT_GLYPH_FORMAT_NONE;
David Turnerf0df85b2000-06-22 00:17:42 +0000306
307 slot->linearHoriAdvance = 0;
308 slot->linearVertAdvance = 0;
Werner Lemberg34f4f392004-12-09 22:22:52 +0000309 slot->lsb_delta = 0;
310 slot->rsb_delta = 0;
David Turnerf0df85b2000-06-22 00:17:42 +0000311 }
312
313
Werner Lembergf814d0f2001-06-27 16:18:10 +0000314 static void
315 ft_glyphslot_done( FT_GlyphSlot slot )
David Turnerf0df85b2000-06-22 00:17:42 +0000316 {
317 FT_Driver driver = slot->face->driver;
Werner Lembergf8ba2002002-03-30 13:16:35 +0000318 FT_Driver_Class clazz = driver->clazz;
David Turnerf0df85b2000-06-22 00:17:42 +0000319 FT_Memory memory = driver->root.memory;
320
Werner Lemberga929ba92000-06-25 06:47:11 +0000321
David Turner54e75742000-11-04 02:52:02 +0000322 if ( clazz->done_slot )
323 clazz->done_slot( slot );
324
David Turnerf0df85b2000-06-22 00:17:42 +0000325 /* free bitmap buffer if needed */
David Turner66cbc202003-03-20 07:04:40 +0000326 ft_glyphslot_free_bitmap( slot );
David Turnerf0df85b2000-06-22 00:17:42 +0000327
328 /* free glyph loader */
Werner Lemberga929ba92000-06-25 06:47:11 +0000329 if ( FT_DRIVER_USES_OUTLINES( driver ) )
David Turnerf0df85b2000-06-22 00:17:42 +0000330 {
David Turner54e75742000-11-04 02:52:02 +0000331 FT_GlyphLoader_Done( slot->internal->loader );
332 slot->internal->loader = 0;
David Turnerf0df85b2000-06-22 00:17:42 +0000333 }
334
David Turnere459d742002-03-22 13:52:37 +0000335 FT_FREE( slot->internal );
David Turnerf0df85b2000-06-22 00:17:42 +0000336 }
337
338
Werner Lemberg8ec9dfd2000-11-07 23:56:02 +0000339 /* documentation is in ftobjs.h */
340
Werner Lembergf814d0f2001-06-27 16:18:10 +0000341 FT_BASE_DEF( FT_Error )
342 FT_New_GlyphSlot( FT_Face face,
343 FT_GlyphSlot *aslot )
David Turnerf0df85b2000-06-22 00:17:42 +0000344 {
Werner Lemberga929ba92000-06-25 06:47:11 +0000345 FT_Error error;
346 FT_Driver driver;
Werner Lembergf8ba2002002-03-30 13:16:35 +0000347 FT_Driver_Class clazz;
Werner Lemberga929ba92000-06-25 06:47:11 +0000348 FT_Memory memory;
349 FT_GlyphSlot slot;
350
David Turnerf0df85b2000-06-22 00:17:42 +0000351
Werner Lembergb9ee7372005-05-20 21:52:19 +0000352 if ( !face || !face->driver )
David Turnerf0df85b2000-06-22 00:17:42 +0000353 return FT_Err_Invalid_Argument;
354
355 driver = face->driver;
356 clazz = driver->clazz;
357 memory = driver->root.memory;
358
359 FT_TRACE4(( "FT_New_GlyphSlot: Creating new slot object\n" ));
David Turnere459d742002-03-22 13:52:37 +0000360 if ( !FT_ALLOC( slot, clazz->slot_object_size ) )
David Turnerf0df85b2000-06-22 00:17:42 +0000361 {
362 slot->face = face;
363
364 error = ft_glyphslot_init( slot );
Werner Lemberga929ba92000-06-25 06:47:11 +0000365 if ( error )
David Turnerf0df85b2000-06-22 00:17:42 +0000366 {
367 ft_glyphslot_done( slot );
David Turnere459d742002-03-22 13:52:37 +0000368 FT_FREE( slot );
David Turnerf0df85b2000-06-22 00:17:42 +0000369 goto Exit;
370 }
371
Werner Lembergb9ee7372005-05-20 21:52:19 +0000372 slot->next = face->glyph;
373 face->glyph = slot;
374
375 if ( aslot )
376 *aslot = slot;
David Turnerf0df85b2000-06-22 00:17:42 +0000377 }
Werner Lembergb9ee7372005-05-20 21:52:19 +0000378 else if ( aslot )
379 *aslot = 0;
380
David Turnerf0df85b2000-06-22 00:17:42 +0000381
382 Exit:
383 FT_TRACE4(( "FT_New_GlyphSlot: Return %d\n", error ));
384 return error;
385 }
386
387
Werner Lemberg8ec9dfd2000-11-07 23:56:02 +0000388 /* documentation is in ftobjs.h */
389
Werner Lembergf814d0f2001-06-27 16:18:10 +0000390 FT_BASE_DEF( void )
391 FT_Done_GlyphSlot( FT_GlyphSlot slot )
David Turnerf0df85b2000-06-22 00:17:42 +0000392 {
393 if ( slot )
394 {
Werner Lembergb9ee7372005-05-20 21:52:19 +0000395 FT_Driver driver = slot->face->driver;
396 FT_Memory memory = driver->root.memory;
397 FT_GlyphSlot prev;
398 FT_GlyphSlot cur;
David Turnerf0df85b2000-06-22 00:17:42 +0000399
Werner Lemberga929ba92000-06-25 06:47:11 +0000400
David Turnerf0df85b2000-06-22 00:17:42 +0000401 /* Remove slot from its parent face's list */
Werner Lembergb9ee7372005-05-20 21:52:19 +0000402 prev = NULL;
403 cur = slot->face->glyph;
Werner Lemberga929ba92000-06-25 06:47:11 +0000404
David Turnerf0df85b2000-06-22 00:17:42 +0000405 while ( cur )
406 {
407 if ( cur == slot )
408 {
Werner Lembergb9ee7372005-05-20 21:52:19 +0000409 if ( !prev )
410 slot->face->glyph = cur->next;
411 else
412 prev->next = cur->next;
413
Werner Lemberga929ba92000-06-25 06:47:11 +0000414 ft_glyphslot_done( slot );
David Turnere459d742002-03-22 13:52:37 +0000415 FT_FREE( slot );
David Turnerf0df85b2000-06-22 00:17:42 +0000416 break;
417 }
Werner Lembergb9ee7372005-05-20 21:52:19 +0000418 prev = cur;
419 cur = cur->next;
David Turnerf0df85b2000-06-22 00:17:42 +0000420 }
421 }
422 }
423
424
Werner Lemberg90a03302000-11-07 17:21:11 +0000425 /* documentation is in freetype.h */
426
Werner Lembergf814d0f2001-06-27 16:18:10 +0000427 FT_EXPORT_DEF( void )
428 FT_Set_Transform( FT_Face face,
429 FT_Matrix* matrix,
430 FT_Vector* delta )
David Turnerf0df85b2000-06-22 00:17:42 +0000431 {
David Turner54e75742000-11-04 02:52:02 +0000432 FT_Face_Internal internal;
David Turner61d6b2b2001-05-16 17:49:07 +0000433
David Turner54e75742000-11-04 02:52:02 +0000434
David Turnerf0df85b2000-06-22 00:17:42 +0000435 if ( !face )
436 return;
437
David Turner54e75742000-11-04 02:52:02 +0000438 internal = face->internal;
439
440 internal->transform_flags = 0;
David Turnerf0df85b2000-06-22 00:17:42 +0000441
442 if ( !matrix )
443 {
David Turner54e75742000-11-04 02:52:02 +0000444 internal->transform_matrix.xx = 0x10000L;
445 internal->transform_matrix.xy = 0;
446 internal->transform_matrix.yx = 0;
447 internal->transform_matrix.yy = 0x10000L;
448 matrix = &internal->transform_matrix;
David Turnerf0df85b2000-06-22 00:17:42 +0000449 }
450 else
David Turner54e75742000-11-04 02:52:02 +0000451 internal->transform_matrix = *matrix;
David Turnerf0df85b2000-06-22 00:17:42 +0000452
453 /* set transform_flags bit flag 0 if `matrix' isn't the identity */
454 if ( ( matrix->xy | matrix->yx ) ||
455 matrix->xx != 0x10000L ||
456 matrix->yy != 0x10000L )
David Turner54e75742000-11-04 02:52:02 +0000457 internal->transform_flags |= 1;
David Turnerf0df85b2000-06-22 00:17:42 +0000458
459 if ( !delta )
460 {
David Turner54e75742000-11-04 02:52:02 +0000461 internal->transform_delta.x = 0;
462 internal->transform_delta.y = 0;
463 delta = &internal->transform_delta;
David Turnerf0df85b2000-06-22 00:17:42 +0000464 }
465 else
David Turner54e75742000-11-04 02:52:02 +0000466 internal->transform_delta = *delta;
David Turnerf0df85b2000-06-22 00:17:42 +0000467
468 /* set transform_flags bit flag 1 if `delta' isn't the null vector */
469 if ( delta->x | delta->y )
David Turner54e75742000-11-04 02:52:02 +0000470 internal->transform_flags |= 2;
David Turnerf0df85b2000-06-22 00:17:42 +0000471 }
472
473
Werner Lembergf814d0f2001-06-27 16:18:10 +0000474 static FT_Renderer
475 ft_lookup_glyph_renderer( FT_GlyphSlot slot );
Werner Lembergdeb4e982000-06-29 03:14:25 +0000476
477
Werner Lemberg90a03302000-11-07 17:21:11 +0000478 /* documentation is in freetype.h */
479
Werner Lembergf814d0f2001-06-27 16:18:10 +0000480 FT_EXPORT_DEF( FT_Error )
Werner Lemberg6b5c6692002-09-05 15:10:54 +0000481 FT_Load_Glyph( FT_Face face,
482 FT_UInt glyph_index,
483 FT_Int32 load_flags )
David Turnerf0df85b2000-06-22 00:17:42 +0000484 {
485 FT_Error error;
486 FT_Driver driver;
487 FT_GlyphSlot slot;
David Turner5ae831c2000-06-30 01:31:22 +0000488 FT_Library library;
Wu, Chia-I (吳佳一)e5ff0592006-01-15 06:00:49 +0000489 FT_Bool autohint = 0;
David Turner5ae831c2000-06-30 01:31:22 +0000490 FT_Module hinter;
David Turnerf0df85b2000-06-22 00:17:42 +0000491
Werner Lemberga929ba92000-06-25 06:47:11 +0000492
David Turnerf0df85b2000-06-22 00:17:42 +0000493 if ( !face || !face->size || !face->glyph )
494 return FT_Err_Invalid_Face_Handle;
495
Werner Lemberg2cba64d2003-04-28 08:51:07 +0000496 if ( glyph_index >= (FT_UInt)face->num_glyphs )
David Turnerf0df85b2000-06-22 00:17:42 +0000497 return FT_Err_Invalid_Argument;
498
499 slot = face->glyph;
500 ft_glyphslot_clear( slot );
501
Wu, Chia-I (吳佳一)e5ff0592006-01-15 06:00:49 +0000502 driver = face->driver;
503 library = driver->root.library;
504 hinter = library->auto_hinter;
David Turnerf0df85b2000-06-22 00:17:42 +0000505
Wu, Chia-I (吳佳一)e5ff0592006-01-15 06:00:49 +0000506 /* resolve load flags dependencies */
507
David Turnerf0df85b2000-06-22 00:17:42 +0000508 if ( load_flags & FT_LOAD_NO_RECURSE )
Werner Lembergeddd9902000-10-12 05:05:40 +0000509 load_flags |= FT_LOAD_NO_SCALE |
David Turnerc9ce9e42000-09-15 17:16:49 +0000510 FT_LOAD_IGNORE_TRANSFORM;
Werner Lembergeddd9902000-10-12 05:05:40 +0000511
Wu, Chia-I (吳佳一)e5ff0592006-01-15 06:00:49 +0000512 if ( load_flags & FT_LOAD_NO_SCALE )
513 {
514 load_flags |= FT_LOAD_NO_HINTING |
515 FT_LOAD_NO_BITMAP;
516
Werner Lembergeddd9902000-10-12 05:05:40 +0000517 load_flags &= ~FT_LOAD_RENDER;
David Turnerc9ce9e42000-09-15 17:16:49 +0000518 }
David Turnerf0df85b2000-06-22 00:17:42 +0000519
Wu, Chia-I (吳佳一)e5ff0592006-01-15 06:00:49 +0000520 if ( FT_LOAD_TARGET_MODE( load_flags ) == FT_RENDER_MODE_LIGHT )
David Turnere6bb9532005-12-23 13:32:06 +0000521 load_flags |= FT_LOAD_FORCE_AUTOHINT;
522
Wu, Chia-I (吳佳一)e5ff0592006-01-15 06:00:49 +0000523 /* auto-hinter is preferred and should be used */
Werner Lemberg1723dcc2006-01-15 07:30:32 +0000524 if ( ( !FT_DRIVER_HAS_HINTER( driver ) ||
Wu, Chia-I (吳佳一)e5ff0592006-01-15 06:00:49 +0000525 ( load_flags & FT_LOAD_FORCE_AUTOHINT ) ) &&
526 !( load_flags & FT_LOAD_NO_HINTING ) &&
Werner Lemberg1723dcc2006-01-15 07:30:32 +0000527 !( load_flags & FT_LOAD_NO_AUTOHINT ) )
David Turner5ae831c2000-06-30 01:31:22 +0000528 {
Werner Lemberg1723dcc2006-01-15 07:30:32 +0000529 /* check whether it works for this face */
Wu, Chia-I (吳佳一)e5ff0592006-01-15 06:00:49 +0000530 autohint =
531 FT_BOOL( hinter &&
532 FT_DRIVER_IS_SCALABLE( driver ) &&
533 FT_DRIVER_USES_OUTLINES( driver ) &&
534 face->internal->transform_matrix.yy > 0 &&
535 face->internal->transform_matrix.yx == 0 );
Werner Lembergcc9fc492000-06-30 06:21:26 +0000536 }
Werner Lembergfbeb41d2000-07-02 00:27:53 +0000537
Wu, Chia-I (吳佳一)e5ff0592006-01-15 06:00:49 +0000538 if ( autohint )
David Turner5ae831c2000-06-30 01:31:22 +0000539 {
David Turner9657ef02002-03-14 08:49:59 +0000540 FT_AutoHinter_Service hinting;
Werner Lembergfbeb41d2000-07-02 00:27:53 +0000541
Werner Lembergcc9fc492000-06-30 06:21:26 +0000542
Werner Lemberg0d535112001-12-19 22:26:12 +0000543 /* try to load embedded bitmaps first if available */
544 /* */
545 /* XXX: This is really a temporary hack that should disappear */
546 /* promptly with FreeType 2.1! */
David Turner4937a3e2001-12-19 21:09:16 +0000547 /* */
Werner Lembergeacb9302002-10-07 10:12:43 +0000548 if ( FT_HAS_FIXED_SIZES( face ) &&
David Turner80171e02002-10-05 14:57:03 +0000549 ( load_flags & FT_LOAD_NO_BITMAP ) == 0 )
David Turner4937a3e2001-12-19 21:09:16 +0000550 {
551 error = driver->clazz->load_glyph( slot, face->size,
552 glyph_index,
553 load_flags | FT_LOAD_SBITS_ONLY );
554
David Turnerb08fe2d2002-08-27 20:20:29 +0000555 if ( !error && slot->format == FT_GLYPH_FORMAT_BITMAP )
David Turner4937a3e2001-12-19 21:09:16 +0000556 goto Load_Ok;
557 }
558
559 /* load auto-hinted outline */
David Turner9657ef02002-03-14 08:49:59 +0000560 hinting = (FT_AutoHinter_Service)hinter->clazz->module_interface;
David Turner76a5f622000-11-04 01:55:49 +0000561
562 error = hinting->load_glyph( (FT_AutoHinter)hinter,
563 slot, face->size,
564 glyph_index, load_flags );
David Turner5ae831c2000-06-30 01:31:22 +0000565 }
566 else
David Turner662b3442002-01-03 16:56:59 +0000567 {
David Turner5ae831c2000-06-30 01:31:22 +0000568 error = driver->clazz->load_glyph( slot,
569 face->size,
Werner Lembergcc9fc492000-06-30 06:21:26 +0000570 glyph_index,
571 load_flags );
David Turner662b3442002-01-03 16:56:59 +0000572 if ( error )
573 goto Exit;
574
Werner Lemberg1a0a9792002-01-03 22:06:13 +0000575 /* check that the loaded outline is correct */
David Turner662b3442002-01-03 16:56:59 +0000576 error = FT_Outline_Check( &slot->outline );
577 if ( error )
578 goto Exit;
579 }
David Turnerf0df85b2000-06-22 00:17:42 +0000580
David Turner4937a3e2001-12-19 21:09:16 +0000581 Load_Ok:
David Turnerf0df85b2000-06-22 00:17:42 +0000582 /* compute the advance */
Werner Lemberga929ba92000-06-25 06:47:11 +0000583 if ( load_flags & FT_LOAD_VERTICAL_LAYOUT )
David Turnerf0df85b2000-06-22 00:17:42 +0000584 {
585 slot->advance.x = 0;
586 slot->advance.y = slot->metrics.vertAdvance;
587 }
588 else
589 {
590 slot->advance.x = slot->metrics.horiAdvance;
591 slot->advance.y = 0;
592 }
593
David Turnerc9ce9e42000-09-15 17:16:49 +0000594 /* compute the linear advance in 16.16 pixels */
Werner Lemberg51daa4f2003-05-18 22:40:11 +0000595 if ( ( load_flags & FT_LOAD_LINEAR_DESIGN ) == 0 &&
596 ( face->face_flags & FT_FACE_FLAG_SCALABLE ) )
David Turnerc9ce9e42000-09-15 17:16:49 +0000597 {
David Turnerc9ce9e42000-09-15 17:16:49 +0000598 FT_Size_Metrics* metrics = &face->size->metrics;
Werner Lembergeddd9902000-10-12 05:05:40 +0000599
Werner Lembergf8ba2002002-03-30 13:16:35 +0000600
Wu, Chia-I (吳佳一)e5ff0592006-01-15 06:00:49 +0000601 /* it's tricky! */
David Turnerc9ce9e42000-09-15 17:16:49 +0000602 slot->linearHoriAdvance = FT_MulDiv( slot->linearHoriAdvance,
Werner Lembergbe67c4e2003-11-24 22:54:58 +0000603 metrics->x_scale, 64 );
David Turnerc9ce9e42000-09-15 17:16:49 +0000604
605 slot->linearVertAdvance = FT_MulDiv( slot->linearVertAdvance,
Werner Lembergbe67c4e2003-11-24 22:54:58 +0000606 metrics->y_scale, 64 );
David Turnerc9ce9e42000-09-15 17:16:49 +0000607 }
608
609 if ( ( load_flags & FT_LOAD_IGNORE_TRANSFORM ) == 0 )
David Turnerf0df85b2000-06-22 00:17:42 +0000610 {
David Turner54e75742000-11-04 02:52:02 +0000611 FT_Face_Internal internal = face->internal;
David Turner61d6b2b2001-05-16 17:49:07 +0000612
613
Werner Lembergd1b74752000-08-24 16:29:15 +0000614 /* now, transform the glyph image if needed */
David Turner54e75742000-11-04 02:52:02 +0000615 if ( internal->transform_flags )
David Turner35db7322000-08-24 12:39:40 +0000616 {
617 /* get renderer */
618 FT_Renderer renderer = ft_lookup_glyph_renderer( slot );
Werner Lembergdeb4e982000-06-29 03:14:25 +0000619
Werner Lemberga929ba92000-06-25 06:47:11 +0000620
David Turner35db7322000-08-24 12:39:40 +0000621 if ( renderer )
Werner Lembergdc72aff2000-11-04 08:33:38 +0000622 error = renderer->clazz->transform_glyph(
623 renderer, slot,
624 &internal->transform_matrix,
625 &internal->transform_delta );
David Turner35db7322000-08-24 12:39:40 +0000626 /* transform advance */
David Turner54e75742000-11-04 02:52:02 +0000627 FT_Vector_Transform( &slot->advance, &internal->transform_matrix );
David Turner35db7322000-08-24 12:39:40 +0000628 }
David Turnerc9ce9e42000-09-15 17:16:49 +0000629 }
David Turnerf0df85b2000-06-22 00:17:42 +0000630
David Turnerc9ce9e42000-09-15 17:16:49 +0000631 /* do we need to render the image now? */
632 if ( !error &&
David Turnerb08fe2d2002-08-27 20:20:29 +0000633 slot->format != FT_GLYPH_FORMAT_BITMAP &&
634 slot->format != FT_GLYPH_FORMAT_COMPOSITE &&
David Turnerc9ce9e42000-09-15 17:16:49 +0000635 load_flags & FT_LOAD_RENDER )
636 {
David Turner00d9f402002-09-08 21:29:11 +0000637 FT_Render_Mode mode = FT_LOAD_TARGET_MODE( load_flags );
638
Werner Lemberg68e9f922002-09-27 11:09:23 +0000639
David Turner00d9f402002-09-08 21:29:11 +0000640 if ( mode == FT_RENDER_MODE_NORMAL &&
641 (load_flags & FT_LOAD_MONOCHROME ) )
642 mode = FT_RENDER_MODE_MONO;
643
644 error = FT_Render_Glyph( slot, mode );
Werner Lembergd060a752000-07-20 06:57:41 +0000645 }
David Turner5ae831c2000-06-30 01:31:22 +0000646
Werner Lembergdeb4e982000-06-29 03:14:25 +0000647 Exit:
David Turnerf0df85b2000-06-22 00:17:42 +0000648 return error;
649 }
650
651
Werner Lemberg90a03302000-11-07 17:21:11 +0000652 /* documentation is in freetype.h */
653
Werner Lembergf814d0f2001-06-27 16:18:10 +0000654 FT_EXPORT_DEF( FT_Error )
655 FT_Load_Char( FT_Face face,
656 FT_ULong char_code,
David Turnerf467e6a2002-08-21 21:39:28 +0000657 FT_Int32 load_flags )
David Turnerf0df85b2000-06-22 00:17:42 +0000658 {
Werner Lembergdeb4e982000-06-29 03:14:25 +0000659 FT_UInt glyph_index;
David Turnerf0df85b2000-06-22 00:17:42 +0000660
Werner Lemberga929ba92000-06-25 06:47:11 +0000661
David Turnerf0df85b2000-06-22 00:17:42 +0000662 if ( !face )
663 return FT_Err_Invalid_Face_Handle;
664
665 glyph_index = (FT_UInt)char_code;
Werner Lemberga929ba92000-06-25 06:47:11 +0000666 if ( face->charmap )
David Turnerf0df85b2000-06-22 00:17:42 +0000667 glyph_index = FT_Get_Char_Index( face, char_code );
668
David Turner5ae831c2000-06-30 01:31:22 +0000669 return FT_Load_Glyph( face, glyph_index, load_flags );
David Turnerf0df85b2000-06-22 00:17:42 +0000670 }
671
672
Werner Lemberg7880dd62000-01-10 17:19:45 +0000673 /* destructor for sizes list */
Werner Lembergf814d0f2001-06-27 16:18:10 +0000674 static void
675 destroy_size( FT_Memory memory,
676 FT_Size size,
677 FT_Driver driver )
Werner Lemberg7880dd62000-01-10 17:19:45 +0000678 {
David Turnerf0df85b2000-06-22 00:17:42 +0000679 /* finalize client-specific data */
Werner Lemberga929ba92000-06-25 06:47:11 +0000680 if ( size->generic.finalizer )
David Turnerf0df85b2000-06-22 00:17:42 +0000681 size->generic.finalizer( size );
682
Werner Lemberg7880dd62000-01-10 17:19:45 +0000683 /* finalize format-specific stuff */
Werner Lemberga929ba92000-06-25 06:47:11 +0000684 if ( driver->clazz->done_size )
David Turnerf0df85b2000-06-22 00:17:42 +0000685 driver->clazz->done_size( size );
686
David Turnere459d742002-03-22 13:52:37 +0000687 FT_FREE( size->internal );
688 FT_FREE( size );
Werner Lemberg7880dd62000-01-10 17:19:45 +0000689 }
David Turnerd2b1f351999-12-16 23:11:37 +0000690
691
Werner Lemberg4338dab2004-01-05 14:41:59 +0000692 static void
Werner Lemberge70371c2005-05-27 06:01:28 +0000693 ft_cmap_done_internal( FT_CMap cmap );
694
695
696 static void
Werner Lemberg4338dab2004-01-05 14:41:59 +0000697 destroy_charmaps( FT_Face face,
698 FT_Memory memory )
699 {
700 FT_Int n;
701
702
703 for ( n = 0; n < face->num_charmaps; n++ )
704 {
705 FT_CMap cmap = FT_CMAP( face->charmaps[n] );
706
707
Werner Lemberge70371c2005-05-27 06:01:28 +0000708 ft_cmap_done_internal( cmap );
Werner Lemberg4338dab2004-01-05 14:41:59 +0000709
710 face->charmaps[n] = NULL;
711 }
712
713 FT_FREE( face->charmaps );
714 face->num_charmaps = 0;
715 }
716
717
Werner Lemberg7880dd62000-01-10 17:19:45 +0000718 /* destructor for faces list */
Werner Lembergf814d0f2001-06-27 16:18:10 +0000719 static void
720 destroy_face( FT_Memory memory,
721 FT_Face face,
722 FT_Driver driver )
Werner Lemberg7880dd62000-01-10 17:19:45 +0000723 {
David Turneref3c1262002-03-14 09:22:48 +0000724 FT_Driver_Class clazz = driver->clazz;
David Turnerf0df85b2000-06-22 00:17:42 +0000725
Werner Lembergd060a752000-07-20 06:57:41 +0000726
David Turnerc49f69c2000-07-20 03:44:50 +0000727 /* discard auto-hinting data */
728 if ( face->autohint.finalizer )
729 face->autohint.finalizer( face->autohint.data );
Werner Lembergeddd9902000-10-12 05:05:40 +0000730
Werner Lembergf8ba2002002-03-30 13:16:35 +0000731 /* Discard glyph slots for this face. */
David Turner23bcde12001-10-17 13:48:10 +0000732 /* Beware! FT_Done_GlyphSlot() changes the field `face->glyph' */
Werner Lemberg7880dd62000-01-10 17:19:45 +0000733 while ( face->glyph )
734 FT_Done_GlyphSlot( face->glyph );
735
Werner Lembergf8ba2002002-03-30 13:16:35 +0000736 /* discard all sizes for this face */
Werner Lemberg7880dd62000-01-10 17:19:45 +0000737 FT_List_Finalize( &face->sizes_list,
Werner Lemberg74184152003-10-18 16:56:13 +0000738 (FT_List_Destructor)destroy_size,
739 memory,
740 driver );
Werner Lemberg7880dd62000-01-10 17:19:45 +0000741 face->size = 0;
742
Werner Lembergf8ba2002002-03-30 13:16:35 +0000743 /* now discard client data */
Werner Lemberg7880dd62000-01-10 17:19:45 +0000744 if ( face->generic.finalizer )
745 face->generic.finalizer( face );
746
David Turner2ded2c12002-03-22 22:37:40 +0000747 /* discard charmaps */
Werner Lemberg4338dab2004-01-05 14:41:59 +0000748 destroy_charmaps( face, memory );
Werner Lemberg75435332004-02-25 12:58:54 +0000749
David Turnerf0df85b2000-06-22 00:17:42 +0000750 /* finalize format-specific stuff */
Werner Lemberga929ba92000-06-25 06:47:11 +0000751 if ( clazz->done_face )
752 clazz->done_face( face );
David Turnerf0df85b2000-06-22 00:17:42 +0000753
754 /* close the stream for this face if needed */
Werner Lemberg75435332004-02-25 12:58:54 +0000755 FT_Stream_Free(
Werner Lembergf8ba2002002-03-30 13:16:35 +0000756 face->stream,
Werner Lemberg58b17f92000-07-27 23:29:08 +0000757 ( face->face_flags & FT_FACE_FLAG_EXTERNAL_STREAM ) != 0 );
David Turner7663f222000-02-13 13:37:38 +0000758
David Turner53b3fa12002-02-24 05:26:57 +0000759 face->stream = 0;
760
Werner Lemberg7880dd62000-01-10 17:19:45 +0000761 /* get rid of it */
David Turner23bcde12001-10-17 13:48:10 +0000762 if ( face->internal )
763 {
David Turnere459d742002-03-22 13:52:37 +0000764 FT_FREE( face->internal );
David Turner23bcde12001-10-17 13:48:10 +0000765 }
David Turnere459d742002-03-22 13:52:37 +0000766 FT_FREE( face );
Werner Lemberg7880dd62000-01-10 17:19:45 +0000767 }
David Turnerd2b1f351999-12-16 23:11:37 +0000768
769
Werner Lembergf814d0f2001-06-27 16:18:10 +0000770 static void
771 Destroy_Driver( FT_Driver driver )
David Turnerd2b1f351999-12-16 23:11:37 +0000772 {
David Turnerd2b1f351999-12-16 23:11:37 +0000773 FT_List_Finalize( &driver->faces_list,
774 (FT_List_Destructor)destroy_face,
David Turnerf0df85b2000-06-22 00:17:42 +0000775 driver->root.memory,
David Turnerd2b1f351999-12-16 23:11:37 +0000776 driver );
777
Werner Lembergdeb4e982000-06-29 03:14:25 +0000778 /* check whether we need to drop the driver's glyph loader */
Werner Lemberga929ba92000-06-25 06:47:11 +0000779 if ( FT_DRIVER_USES_OUTLINES( driver ) )
David Turnerf0df85b2000-06-22 00:17:42 +0000780 FT_GlyphLoader_Done( driver->glyph_loader );
David Turnerd2b1f351999-12-16 23:11:37 +0000781 }
782
783
Werner Lemberg547a2522000-02-16 08:23:58 +0000784 /*************************************************************************/
785 /* */
786 /* <Function> */
Antoine Lecac96f69d2002-12-03 00:39:16 +0000787 /* find_unicode_charmap */
788 /* */
789 /* <Description> */
790 /* This function finds a Unicode charmap, if there is one. */
791 /* And if there is more than one, it tries to favour the more */
Werner Lembergc8c6bf52003-04-23 05:38:13 +0000792 /* extensive one, i.e., one that supports UCS-4 against those which */
Antoine Lecac96f69d2002-12-03 00:39:16 +0000793 /* are limited to the BMP (said UCS-2 encoding.) */
794 /* */
795 /* This function is called from open_face() (just below), and also */
Werner Lembergc8c6bf52003-04-23 05:38:13 +0000796 /* from FT_Select_Charmap( ..., FT_ENCODING_UNICODE). */
Antoine Lecac96f69d2002-12-03 00:39:16 +0000797 /* */
798 static FT_Error
799 find_unicode_charmap( FT_Face face )
800 {
801 FT_CharMap* first;
802 FT_CharMap* cur;
803 FT_CharMap* unicmap = NULL; /* some UCS-2 map, if we found it */
804
805
806 /* caller should have already checked that `face' is valid */
Werner Lemberg74184152003-10-18 16:56:13 +0000807 FT_ASSERT( face );
Antoine Lecac96f69d2002-12-03 00:39:16 +0000808
809 first = face->charmaps;
810
811 if ( !first )
812 return FT_Err_Invalid_CharMap_Handle;
813
David Turnerc528f6f2002-12-18 22:43:07 +0000814 /*
Werner Lembergc8c6bf52003-04-23 05:38:13 +0000815 * The original TrueType specification(s) only specified charmap
David Turnerc528f6f2002-12-18 22:43:07 +0000816 * formats that are capable of mapping 8 or 16 bit character codes to
817 * glyph indices.
818 *
Werner Lembergc8c6bf52003-04-23 05:38:13 +0000819 * However, recent updates to the Apple and OpenType specifications
David Turnerc528f6f2002-12-18 22:43:07 +0000820 * introduced new formats that are capable of mapping 32-bit character
Werner Lembergc8c6bf52003-04-23 05:38:13 +0000821 * codes as well. And these are already used on some fonts, mainly to
David Turnerae26c682003-02-25 20:37:50 +0000822 * map non-BMP Asian ideographs as defined in Unicode.
David Turnerc528f6f2002-12-18 22:43:07 +0000823 *
Werner Lembergc8c6bf52003-04-23 05:38:13 +0000824 * For compatibility purposes, these fonts generally come with
David Turnerc528f6f2002-12-18 22:43:07 +0000825 * *several* Unicode charmaps:
826 *
Werner Lembergc8c6bf52003-04-23 05:38:13 +0000827 * - One of them in the "old" 16-bit format, that cannot access
828 * all glyphs in the font.
David Turnerc528f6f2002-12-18 22:43:07 +0000829 *
Werner Lembergc8c6bf52003-04-23 05:38:13 +0000830 * - Another one in the "new" 32-bit format, that can access all
David Turnerc528f6f2002-12-18 22:43:07 +0000831 * the glyphs.
832 *
Werner Lembergc8c6bf52003-04-23 05:38:13 +0000833 * This function has been written to always favor a 32-bit charmap
834 * when found. Otherwise, a 16-bit one is returned when found.
David Turnerc528f6f2002-12-18 22:43:07 +0000835 */
836
Werner Lemberg8acb8672005-03-08 11:43:36 +0000837 /* Since the `interesting' table, with IDs (3,10), is normally the */
838 /* last one, we loop backwards. This looses with type1 fonts with */
839 /* non-BMP characters (<.0001%), this wins with .ttf with non-BMP */
840 /* chars (.01% ?), and this is the same about 99.99% of the time! */
Antoine Lecac96f69d2002-12-03 00:39:16 +0000841
842 cur = first + face->num_charmaps; /* points after the last one */
843
844 for ( ; --cur >= first; )
845 {
846 if ( cur[0]->encoding == FT_ENCODING_UNICODE )
847 {
848 unicmap = cur; /* record we found a Unicode charmap */
849
850 /* XXX If some new encodings to represent UCS-4 are added, */
851 /* they should be added here. */
David Turnerc528f6f2002-12-18 22:43:07 +0000852 if ( ( cur[0]->platform_id == TT_PLATFORM_MICROSOFT &&
853 cur[0]->encoding_id == TT_MS_ID_UCS_4 ) ||
854 ( cur[0]->platform_id == TT_PLATFORM_APPLE_UNICODE &&
855 cur[0]->encoding_id == TT_APPLE_ID_UNICODE_32 ) )
856
Werner Lemberg8acb8672005-03-08 11:43:36 +0000857 /* Hurray! We found a UCS-4 charmap. We can stop the scan! */
Antoine Lecac96f69d2002-12-03 00:39:16 +0000858 {
859 face->charmap = cur[0];
860 return 0;
861 }
862 }
863 }
864
Werner Lemberg8acb8672005-03-08 11:43:36 +0000865 /* We do not have any UCS-4 charmap. Sigh. */
866 /* Let's see if we have some other kind of Unicode charmap, though. */
Antoine Lecac96f69d2002-12-03 00:39:16 +0000867 if ( unicmap != NULL )
868 {
869 face->charmap = unicmap[0];
870 return 0;
871 }
872
873 /* Chou blanc! */
David Turner6453a812003-01-08 09:28:34 +0000874 return FT_Err_Invalid_CharMap_Handle;
Antoine Lecac96f69d2002-12-03 00:39:16 +0000875 }
876
877
878 /*************************************************************************/
879 /* */
880 /* <Function> */
Werner Lemberg547a2522000-02-16 08:23:58 +0000881 /* open_face */
882 /* */
883 /* <Description> */
884 /* This function does some work for FT_Open_Face(). */
885 /* */
Werner Lembergf814d0f2001-06-27 16:18:10 +0000886 static FT_Error
887 open_face( FT_Driver driver,
888 FT_Stream stream,
889 FT_Long face_index,
890 FT_Int num_params,
891 FT_Parameter* params,
Werner Lemberg6d798992003-07-01 07:28:55 +0000892 FT_Face *aface )
David Turnerd2b1f351999-12-16 23:11:37 +0000893 {
David Turnerf0df85b2000-06-22 00:17:42 +0000894 FT_Memory memory;
Werner Lemberg77c34b82003-05-20 22:06:38 +0000895 FT_Driver_Class clazz;
David Turnerf0df85b2000-06-22 00:17:42 +0000896 FT_Face face = 0;
Antoine Lecac96f69d2002-12-03 00:39:16 +0000897 FT_Error error, error2;
David Turner54e75742000-11-04 02:52:02 +0000898 FT_Face_Internal internal;
David Turnerd2b1f351999-12-16 23:11:37 +0000899
Werner Lemberg3c403e42002-08-06 21:47:40 +0000900
David Turnerf0df85b2000-06-22 00:17:42 +0000901 clazz = driver->clazz;
902 memory = driver->root.memory;
David Turnerd2b1f351999-12-16 23:11:37 +0000903
Werner Lembergdeb4e982000-06-29 03:14:25 +0000904 /* allocate the face object and perform basic initialization */
David Turnere459d742002-03-22 13:52:37 +0000905 if ( FT_ALLOC( face, clazz->face_object_size ) )
David Turnerd2b1f351999-12-16 23:11:37 +0000906 goto Fail;
907
David Turnere459d742002-03-22 13:52:37 +0000908 if ( FT_NEW( internal ) )
David Turner54e75742000-11-04 02:52:02 +0000909 goto Fail;
David Turner61d6b2b2001-05-16 17:49:07 +0000910
David Turner54e75742000-11-04 02:52:02 +0000911 face->internal = internal;
912
913 face->driver = driver;
914 face->memory = memory;
915 face->stream = stream;
Graham Asherce121822002-08-01 15:29:17 +0000916
Graham Asherd53cf1d2002-07-18 15:04:29 +0000917#ifdef FT_CONFIG_OPTION_INCREMENTAL
Werner Lemberg3c403e42002-08-06 21:47:40 +0000918 {
919 int i;
920
921
922 face->internal->incremental_interface = 0;
923 for ( i = 0; i < num_params && !face->internal->incremental_interface;
924 i++ )
925 if ( params[i].tag == FT_PARAM_TAG_INCREMENTAL )
926 face->internal->incremental_interface = params[i].data;
Antoine Lecac96f69d2002-12-03 00:39:16 +0000927 }
Graham Asherd53cf1d2002-07-18 15:04:29 +0000928#endif
David Turnerd2b1f351999-12-16 23:11:37 +0000929
David Turnerf0df85b2000-06-22 00:17:42 +0000930 error = clazz->init_face( stream,
931 face,
Werner Lemberg68e9f922002-09-27 11:09:23 +0000932 (FT_Int)face_index,
David Turnerf0df85b2000-06-22 00:17:42 +0000933 num_params,
934 params );
David Turnerd2b1f351999-12-16 23:11:37 +0000935 if ( error )
936 goto Fail;
937
David Turnerfed59b72002-07-17 22:51:06 +0000938 /* select Unicode charmap by default */
Antoine Lecac96f69d2002-12-03 00:39:16 +0000939 error2 = find_unicode_charmap( face );
David Turnerc528f6f2002-12-18 22:43:07 +0000940
Werner Lemberg6d798992003-07-01 07:28:55 +0000941 /* if no Unicode charmap can be found, FT_Err_Invalid_CharMap_Handle */
942 /* is returned. */
Antoine Lecac96f69d2002-12-03 00:39:16 +0000943
Werner Lemberg6d798992003-07-01 07:28:55 +0000944 /* no error should happen, but we want to play safe */
David Turnerc528f6f2002-12-18 22:43:07 +0000945 if ( error2 && error2 != FT_Err_Invalid_CharMap_Handle )
David Turnerfed59b72002-07-17 22:51:06 +0000946 {
Antoine Lecac96f69d2002-12-03 00:39:16 +0000947 error = error2;
948 goto Fail;
David Turnerfed59b72002-07-17 22:51:06 +0000949 }
950
David Turnerd2b1f351999-12-16 23:11:37 +0000951 *aface = face;
952
953 Fail:
954 if ( error )
955 {
Werner Lemberg4338dab2004-01-05 14:41:59 +0000956 destroy_charmaps( face, memory );
David Turnerf0df85b2000-06-22 00:17:42 +0000957 clazz->done_face( face );
Werner Lemberg77c34b82003-05-20 22:06:38 +0000958 FT_FREE( internal );
David Turnere459d742002-03-22 13:52:37 +0000959 FT_FREE( face );
David Turnerd2b1f351999-12-16 23:11:37 +0000960 *aface = 0;
961 }
962
963 return error;
964 }
965
966
Werner Lemberg05c21b82000-07-29 20:38:19 +0000967 /* there's a Mac-specific extended implementation of FT_New_Face() */
Werner Lemberg4d631e42002-05-27 13:02:37 +0000968 /* in src/base/ftmac.c */
Werner Lemberg05c21b82000-07-29 20:38:19 +0000969
Werner Lemberg9ca7a152002-04-30 14:26:49 +0000970#ifndef FT_MACINTOSH
Just van Rossum9e830c52000-07-28 01:12:34 +0000971
Werner Lemberg90a03302000-11-07 17:21:11 +0000972 /* documentation is in freetype.h */
973
Werner Lembergf814d0f2001-06-27 16:18:10 +0000974 FT_EXPORT_DEF( FT_Error )
975 FT_New_Face( FT_Library library,
976 const char* pathname,
977 FT_Long face_index,
978 FT_Face *aface )
David Turnerd2b1f351999-12-16 23:11:37 +0000979 {
David Turner37379e22000-03-28 11:22:31 +0000980 FT_Open_Args args;
Werner Lemberg547a2522000-02-16 08:23:58 +0000981
Werner Lemberga929ba92000-06-25 06:47:11 +0000982
Werner Lemberg2fbf7e42000-06-02 00:01:14 +0000983 /* test for valid `library' and `aface' delayed to FT_Open_Face() */
Werner Lemberg2fbf7e42000-06-02 00:01:14 +0000984 if ( !pathname )
985 return FT_Err_Invalid_Argument;
986
David Turnerb08fe2d2002-08-27 20:20:29 +0000987 args.flags = FT_OPEN_PATHNAME;
David Turner4f2c5542000-05-12 10:19:41 +0000988 args.pathname = (char*)pathname;
Werner Lemberga3b6c6c2000-05-31 06:55:12 +0000989
David Turnercda32b72000-02-10 16:14:35 +0000990 return FT_Open_Face( library, &args, face_index, aface );
David Turnerd2b1f351999-12-16 23:11:37 +0000991 }
992
Werner Lemberg9ca7a152002-04-30 14:26:49 +0000993#endif /* !FT_MACINTOSH */
Just van Rossum9e830c52000-07-28 01:12:34 +0000994
Werner Lemberg7880dd62000-01-10 17:19:45 +0000995
Werner Lemberg90a03302000-11-07 17:21:11 +0000996 /* documentation is in freetype.h */
997
Werner Lembergf814d0f2001-06-27 16:18:10 +0000998 FT_EXPORT_DEF( FT_Error )
999 FT_New_Memory_Face( FT_Library library,
1000 const FT_Byte* file_base,
1001 FT_Long file_size,
1002 FT_Long face_index,
1003 FT_Face *aface )
David Turnerd2b1f351999-12-16 23:11:37 +00001004 {
David Turner37379e22000-03-28 11:22:31 +00001005 FT_Open_Args args;
Werner Lemberg7880dd62000-01-10 17:19:45 +00001006
Werner Lemberga929ba92000-06-25 06:47:11 +00001007
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001008 /* test for valid `library' and `face' delayed to FT_Open_Face() */
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001009 if ( !file_base )
1010 return FT_Err_Invalid_Argument;
1011
David Turnerb08fe2d2002-08-27 20:20:29 +00001012 args.flags = FT_OPEN_MEMORY;
David Turnercda32b72000-02-10 16:14:35 +00001013 args.memory_base = file_base;
1014 args.memory_size = file_size;
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001015
Werner Lemberg4b680072000-11-07 06:30:29 +00001016 return FT_Open_Face( library, &args, face_index, aface );
David Turnerd2b1f351999-12-16 23:11:37 +00001017 }
1018
Werner Lemberg7880dd62000-01-10 17:19:45 +00001019
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001020#if !defined( FT_MACINTOSH ) && defined( FT_CONFIG_OPTION_MAC_FONTS )
1021
1022 /* The behavior here is very similar to that in base/ftmac.c, but it */
1023 /* is designed to work on non-mac systems, so no mac specific calls. */
1024 /* */
1025 /* We look at the file and determine if it is a mac dfont file or a mac */
1026 /* resource file, or a macbinary file containing a mac resource file. */
1027 /* */
1028 /* Unlike ftmac I'm not going to look at a `FOND'. I don't really see */
1029 /* the point, especially since there may be multiple `FOND' resources. */
1030 /* Instead I'll just look for `sfnt' and `POST' resources, ordered as */
1031 /* they occur in the file. */
1032 /* */
1033 /* Note that multiple `POST' resources do not mean multiple postscript */
1034 /* fonts; they all get jammed together to make what is essentially a */
1035 /* pfb file. */
1036 /* */
1037 /* We aren't interested in `NFNT' or `FONT' bitmap resources. */
1038 /* */
1039 /* As soon as we get an `sfnt' load it into memory and pass it off to */
1040 /* FT_Open_Face. */
1041 /* */
1042 /* If we have a (set of) `POST' resources, massage them into a (memory) */
1043 /* pfb file and pass that to FT_Open_Face. (As with ftmac.c I'm not */
1044 /* going to try to save the kerning info. After all that lives in the */
1045 /* `FOND' which isn't in the file containing the `POST' resources so */
1046 /* we don't really have access to it. */
1047
1048
1049 /* Finalizer for a memory stream; gets called by FT_Done_Face().
1050 It frees the memory it uses. */
1051 /* from ftmac.c */
1052 static void
1053 memory_stream_close( FT_Stream stream )
1054 {
1055 FT_Memory memory = stream->memory;
1056
1057
1058 FT_FREE( stream->base );
1059
1060 stream->size = 0;
1061 stream->base = 0;
1062 stream->close = 0;
1063 }
1064
1065
1066 /* Create a new memory stream from a buffer and a size. */
1067 /* from ftmac.c */
1068 static FT_Error
1069 new_memory_stream( FT_Library library,
1070 FT_Byte* base,
1071 FT_ULong size,
1072 FT_Stream_CloseFunc close,
1073 FT_Stream *astream )
1074 {
1075 FT_Error error;
1076 FT_Memory memory;
1077 FT_Stream stream;
1078
1079
1080 if ( !library )
1081 return FT_Err_Invalid_Library_Handle;
1082
1083 if ( !base )
1084 return FT_Err_Invalid_Argument;
1085
1086 *astream = 0;
1087 memory = library->memory;
1088 if ( FT_NEW( stream ) )
1089 goto Exit;
1090
1091 FT_Stream_OpenMemory( stream, base, size );
1092
1093 stream->close = close;
1094
1095 *astream = stream;
1096
1097 Exit:
1098 return error;
1099 }
1100
1101
1102 /* Create a new FT_Face given a buffer and a driver name. */
1103 /* from ftmac.c */
1104 static FT_Error
1105 open_face_from_buffer( FT_Library library,
1106 FT_Byte* base,
1107 FT_ULong size,
1108 FT_Long face_index,
1109 const char* driver_name,
1110 FT_Face *aface )
1111 {
1112 FT_Open_Args args;
1113 FT_Error error;
1114 FT_Stream stream;
1115 FT_Memory memory = library->memory;
1116
1117
1118 error = new_memory_stream( library,
1119 base,
1120 size,
1121 memory_stream_close,
1122 &stream );
1123 if ( error )
1124 {
1125 FT_FREE( base );
1126 return error;
1127 }
1128
1129 args.flags = FT_OPEN_STREAM;
1130 args.stream = stream;
1131 if ( driver_name )
1132 {
Werner Lemberg7a024102003-06-18 06:59:57 +00001133 args.flags = args.flags | FT_OPEN_DRIVER;
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001134 args.driver = FT_Get_Module( library, driver_name );
1135 }
1136
1137 error = FT_Open_Face( library, &args, face_index, aface );
1138
1139 if ( error == FT_Err_Ok )
1140 (*aface)->face_flags &= ~FT_FACE_FLAG_EXTERNAL_STREAM;
1141 else
1142 {
1143 FT_Stream_Close( stream );
1144 FT_FREE( stream );
1145 }
1146
1147 return error;
1148 }
1149
1150
1151 /* The resource header says we've got resource_cnt `POST' (type1) */
1152 /* resources in this file. They all need to be coalesced into */
1153 /* one lump which gets passed on to the type1 driver. */
1154 /* Here can be only one PostScript font in a file so face_index */
1155 /* must be 0 (or -1). */
1156 /* */
1157 static FT_Error
1158 Mac_Read_POST_Resource( FT_Library library,
1159 FT_Stream stream,
Werner Lemberg75435332004-02-25 12:58:54 +00001160 FT_Long *offsets,
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001161 FT_Long resource_cnt,
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001162 FT_Long face_index,
1163 FT_Face *aface )
1164 {
1165 FT_Error error = FT_Err_Cannot_Open_Resource;
1166 FT_Memory memory = library->memory;
1167 FT_Byte* pfb_data;
Werner Lembergdc8ad542003-12-09 02:12:14 +00001168 int i, type, flags;
1169 FT_Long len;
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001170 FT_Long pfb_len, pfb_pos, pfb_lenpos;
Werner Lembergdc8ad542003-12-09 02:12:14 +00001171 FT_Long rlen, temp;
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001172
1173
1174 if ( face_index == -1 )
1175 face_index = 0;
1176 if ( face_index != 0 )
Werner Lemberg77c34b82003-05-20 22:06:38 +00001177 return error;
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001178
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001179 /* Find the length of all the POST resources, concatenated. Assume */
1180 /* worst case (each resource in its own section). */
1181 pfb_len = 0;
1182 for ( i = 0; i < resource_cnt; ++i )
1183 {
1184 error = FT_Stream_Seek( stream, offsets[i] );
1185 if ( error )
1186 goto Exit;
1187 if ( FT_READ_LONG( temp ) )
1188 goto Exit;
1189 pfb_len += temp + 6;
1190 }
1191
1192 if ( FT_ALLOC( pfb_data, (FT_Long)pfb_len + 2 ) )
1193 goto Exit;
1194
David Turnerc313c502003-09-11 19:51:54 +00001195 pfb_data[0] = 0x80;
1196 pfb_data[1] = 1; /* Ascii section */
1197 pfb_data[2] = 0; /* 4-byte length, fill in later */
1198 pfb_data[3] = 0;
1199 pfb_data[4] = 0;
1200 pfb_data[5] = 0;
1201 pfb_pos = 7;
David Turnere2d12842003-09-21 17:15:55 +00001202 pfb_lenpos = 2;
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001203
1204 len = 0;
1205 type = 1;
1206 for ( i = 0; i < resource_cnt; ++i )
1207 {
1208 error = FT_Stream_Seek( stream, offsets[i] );
1209 if ( error )
1210 goto Exit2;
1211 if ( FT_READ_LONG( rlen ) )
1212 goto Exit;
1213 if ( FT_READ_USHORT( flags ) )
1214 goto Exit;
1215 rlen -= 2; /* the flags are part of the resource */
1216 if ( ( flags >> 8 ) == type )
1217 len += rlen;
1218 else
1219 {
David Turnerc313c502003-09-11 19:51:54 +00001220 pfb_data[pfb_lenpos ] = (FT_Byte)( len );
1221 pfb_data[pfb_lenpos + 1] = (FT_Byte)( len >> 8 );
1222 pfb_data[pfb_lenpos + 2] = (FT_Byte)( len >> 16 );
1223 pfb_data[pfb_lenpos + 3] = (FT_Byte)( len >> 24 );
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001224
1225 if ( ( flags >> 8 ) == 5 ) /* End of font mark */
1226 break;
1227
1228 pfb_data[pfb_pos++] = 0x80;
1229
1230 type = flags >> 8;
1231 len = rlen;
1232
Werner Lemberg013efd12003-09-17 05:26:33 +00001233 pfb_data[pfb_pos++] = (FT_Byte)type;
1234 pfb_lenpos = (FT_Byte)pfb_pos;
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001235 pfb_data[pfb_pos++] = 0; /* 4-byte length, fill in later */
1236 pfb_data[pfb_pos++] = 0;
1237 pfb_data[pfb_pos++] = 0;
1238 pfb_data[pfb_pos++] = 0;
1239 }
1240
1241 error = FT_Stream_Read( stream, (FT_Byte *)pfb_data + pfb_pos, rlen );
1242 pfb_pos += rlen;
1243 }
1244
1245 pfb_data[pfb_pos++] = 0x80;
1246 pfb_data[pfb_pos++] = 3;
1247
David Turnerc313c502003-09-11 19:51:54 +00001248 pfb_data[pfb_lenpos ] = (FT_Byte)( len );
1249 pfb_data[pfb_lenpos + 1] = (FT_Byte)( len >> 8 );
1250 pfb_data[pfb_lenpos + 2] = (FT_Byte)( len >> 16 );
1251 pfb_data[pfb_lenpos + 3] = (FT_Byte)( len >> 24 );
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001252
1253 return open_face_from_buffer( library,
1254 pfb_data,
1255 pfb_pos,
1256 face_index,
1257 "type1",
1258 aface );
1259
1260 Exit2:
1261 FT_FREE( pfb_data );
1262
1263 Exit:
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001264 return error;
1265 }
1266
1267
1268 /* The resource header says we've got resource_cnt `sfnt' */
1269 /* (TrueType/OpenType) resources in this file. Look through */
1270 /* them for the one indicated by face_index, load it into mem, */
1271 /* pass it on the the truetype driver and return it. */
1272 /* */
1273 static FT_Error
1274 Mac_Read_sfnt_Resource( FT_Library library,
1275 FT_Stream stream,
Werner Lemberg75435332004-02-25 12:58:54 +00001276 FT_Long *offsets,
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001277 FT_Long resource_cnt,
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001278 FT_Long face_index,
1279 FT_Face *aface )
1280 {
1281 FT_Memory memory = library->memory;
1282 FT_Byte* sfnt_data;
1283 FT_Error error;
Werner Lemberg75435332004-02-25 12:58:54 +00001284 FT_Long flag_offset;
Werner Lembergdc8ad542003-12-09 02:12:14 +00001285 FT_Long rlen;
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001286 int is_cff;
1287
1288
1289 if ( face_index == -1 )
1290 face_index = 0;
1291 if ( face_index >= resource_cnt )
1292 return FT_Err_Cannot_Open_Resource;
1293
Werner Lemberg75435332004-02-25 12:58:54 +00001294 flag_offset = offsets[face_index];
1295 error = FT_Stream_Seek( stream, flag_offset );
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001296 if ( error )
1297 goto Exit;
1298
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001299 if ( FT_READ_LONG( rlen ) )
1300 goto Exit;
1301 if ( rlen == -1 )
1302 return FT_Err_Cannot_Open_Resource;
1303
1304 if ( FT_ALLOC( sfnt_data, (FT_Long)rlen ) )
1305 return error;
1306 error = FT_Stream_Read( stream, (FT_Byte *)sfnt_data, rlen );
1307 if ( error )
1308 goto Exit;
1309
1310 is_cff = rlen > 4 && sfnt_data[0] == 'O' &&
1311 sfnt_data[1] == 'T' &&
1312 sfnt_data[2] == 'T' &&
1313 sfnt_data[3] == 'O';
1314
1315 error = open_face_from_buffer( library,
1316 sfnt_data,
1317 rlen,
1318 face_index,
1319 is_cff ? "cff" : "truetype",
1320 aface );
1321
1322 Exit:
1323 return error;
1324 }
1325
1326
1327 /* Check for a valid resource fork header, or a valid dfont */
1328 /* header. In a resource fork the first 16 bytes are repeated */
1329 /* at the location specified by bytes 4-7. In a dfont bytes */
1330 /* 4-7 point to 16 bytes of zeroes instead. */
1331 /* */
1332 static FT_Error
1333 IsMacResource( FT_Library library,
1334 FT_Stream stream,
1335 FT_Long resource_offset,
1336 FT_Long face_index,
1337 FT_Face *aface )
1338 {
Werner Lemberg75435332004-02-25 12:58:54 +00001339 FT_Memory memory = library->memory;
1340 FT_Error error;
1341 FT_Long map_offset, rdara_pos;
1342 FT_Long *data_offsets;
1343 FT_Long count;
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001344
1345
Werner Lemberg75435332004-02-25 12:58:54 +00001346 error = FT_Raccess_Get_HeaderInfo( library, stream, resource_offset,
1347 &map_offset, &rdara_pos );
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001348 if ( error )
Werner Lemberg75435332004-02-25 12:58:54 +00001349 return error;
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001350
Werner Lemberg75435332004-02-25 12:58:54 +00001351 error = FT_Raccess_Get_DataOffsets( library, stream,
1352 map_offset, rdara_pos,
1353 FT_MAKE_TAG( 'P', 'O', 'S', 'T' ),
1354 &data_offsets, &count );
1355 if ( !error )
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001356 {
Werner Lemberg75435332004-02-25 12:58:54 +00001357 error = Mac_Read_POST_Resource( library, stream, data_offsets, count,
1358 face_index, aface );
1359 FT_FREE( data_offsets );
1360 return error;
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001361 }
1362
Werner Lemberg75435332004-02-25 12:58:54 +00001363 error = FT_Raccess_Get_DataOffsets( library, stream,
1364 map_offset, rdara_pos,
1365 FT_MAKE_TAG( 's', 'f', 'n', 't' ),
1366 &data_offsets, &count );
1367 if ( !error )
1368 {
1369 error = Mac_Read_sfnt_Resource( library, stream, data_offsets, count,
1370 face_index, aface );
1371 FT_FREE( data_offsets );
1372 }
1373
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001374 return error;
1375 }
1376
1377
1378 /* Check for a valid macbinary header, and if we find one */
1379 /* check that the (flattened) resource fork in it is valid. */
1380 /* */
1381 static FT_Error
1382 IsMacBinary( FT_Library library,
1383 FT_Stream stream,
1384 FT_Long face_index,
1385 FT_Face *aface )
1386 {
1387 unsigned char header[128];
1388 FT_Error error;
1389 FT_Long dlen, offset;
1390
1391
1392 error = FT_Stream_Seek( stream, 0 );
1393 if ( error )
1394 goto Exit;
1395
1396 error = FT_Stream_Read( stream, (FT_Byte*)header, 128 );
1397 if ( error )
1398 goto Exit;
1399
1400 if ( header[ 0] != 0 ||
1401 header[74] != 0 ||
1402 header[82] != 0 ||
1403 header[ 1] == 0 ||
1404 header[ 1] > 33 ||
1405 header[63] != 0 ||
1406 header[2 + header[1]] != 0 )
1407 return FT_Err_Unknown_File_Format;
1408
1409 dlen = ( header[0x53] << 24 ) |
1410 ( header[0x54] << 16 ) |
1411 ( header[0x55] << 8 ) |
1412 header[0x56];
1413#if 0
1414 rlen = ( header[0x57] << 24 ) |
1415 ( header[0x58] << 16 ) |
1416 ( header[0x59] << 8 ) |
1417 header[0x5a];
1418#endif /* 0 */
1419 offset = 128 + ( ( dlen + 127 ) & ~127 );
1420
1421 return IsMacResource( library, stream, offset, face_index, aface );
1422
1423 Exit:
1424 return error;
1425 }
1426
1427
Werner Lemberg75435332004-02-25 12:58:54 +00001428 static FT_Error
1429 load_face_in_embedded_rfork( FT_Library library,
1430 FT_Stream stream,
1431 FT_Long face_index,
1432 FT_Face *aface,
1433 const FT_Open_Args *args )
1434 {
1435
1436#undef FT_COMPONENT
1437#define FT_COMPONENT trace_raccess
1438
1439 FT_Memory memory = library->memory;
1440 FT_Error error = FT_Err_Unknown_File_Format;
1441 int i;
1442
1443 char * file_names[FT_RACCESS_N_RULES];
1444 FT_Long offsets[FT_RACCESS_N_RULES];
1445 FT_Error errors[FT_RACCESS_N_RULES];
1446
1447 FT_Open_Args args2;
1448 FT_Stream stream2;
1449
1450
1451 FT_Raccess_Guess( library, stream,
1452 args->pathname, file_names, offsets, errors );
1453
1454 for ( i = 0; i < FT_RACCESS_N_RULES; i++ )
1455 {
1456 if ( errors[i] )
1457 {
1458 FT_TRACE3(( "Error[%d] has occurred in rule %d\n", errors[i], i ));
1459 continue;
1460 }
1461
1462 args2.flags = FT_OPEN_PATHNAME;
1463 args2.pathname = file_names[i] ? file_names[i] : args->pathname;
1464
1465 FT_TRACE3(( "Try rule %d: %s (offset=%d) ...",
1466 i, args2.pathname, offsets[i] ));
1467
1468 error = FT_Stream_New( library, &args2, &stream2 );
1469 if ( error )
1470 {
1471 FT_TRACE3(( "failed\n" ));
1472 continue;
1473 }
1474
1475 error = IsMacResource( library, stream2, offsets[i],
1476 face_index, aface );
1477 FT_Stream_Close( stream2 );
1478
1479 FT_TRACE3(( "%s\n", error ? "failed": "successful" ));
1480
1481 if ( !error )
1482 break;
1483 }
1484
1485 for (i = 0; i < FT_RACCESS_N_RULES; i++)
1486 {
1487 if ( file_names[i] )
1488 FT_FREE( file_names[i] );
1489 }
1490
1491 /* Caller (load_mac_face) requires FT_Err_Unknown_File_Format. */
1492 if ( error )
1493 error = FT_Err_Unknown_File_Format;
1494
1495 return error;
1496
1497#undef FT_COMPONENT
1498#define FT_COMPONENT trace_objs
1499
1500 }
1501
1502
1503 /* Check for some macintosh formats. */
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001504 /* Is this a macbinary file? If so look at the resource fork. */
1505 /* Is this a mac dfont file? */
1506 /* Is this an old style resource fork? (in data) */
Werner Lemberg75435332004-02-25 12:58:54 +00001507 /* Else call load_face_in_embedded_rfork to try extra rules */
1508 /* (defined in `ftrfork.c'). */
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001509 /* */
1510 static FT_Error
1511 load_mac_face( FT_Library library,
1512 FT_Stream stream,
1513 FT_Long face_index,
1514 FT_Face *aface,
1515 const FT_Open_Args *args )
1516 {
1517 FT_Error error;
1518 FT_UNUSED( args );
1519
1520
1521 error = IsMacBinary( library, stream, face_index, aface );
1522 if ( FT_ERROR_BASE( error ) == FT_Err_Unknown_File_Format )
Werner Lemberg75435332004-02-25 12:58:54 +00001523 {
1524
1525#undef FT_COMPONENT
1526#define FT_COMPONENT trace_raccess
1527
1528 FT_TRACE3(( "Try as dfont: %s ...", args->pathname ));
1529
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001530 error = IsMacResource( library, stream, 0, face_index, aface );
1531
Werner Lemberg75435332004-02-25 12:58:54 +00001532 FT_TRACE3(( "%s\n", error ? "failed" : "successful" ));
David Turnere2d12842003-09-21 17:15:55 +00001533
Werner Lemberg75435332004-02-25 12:58:54 +00001534#undef FT_COMPONENT
1535#define FT_COMPONENT trace_objs
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001536
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001537 }
1538
Werner Lemberg75435332004-02-25 12:58:54 +00001539 if ( ( FT_ERROR_BASE( error ) == FT_Err_Unknown_File_Format ||
1540 FT_ERROR_BASE( error ) == FT_Err_Invalid_Stream_Operation ) &&
1541 ( args->flags & FT_OPEN_PATHNAME ) )
1542 error = load_face_in_embedded_rfork( library, stream,
1543 face_index, aface, args );
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001544 return error;
1545 }
1546
1547#endif /* !FT_MACINTOSH && FT_CONFIG_OPTION_MAC_FONTS */
1548
1549
Werner Lemberg90a03302000-11-07 17:21:11 +00001550 /* documentation is in freetype.h */
1551
Werner Lembergf814d0f2001-06-27 16:18:10 +00001552 FT_EXPORT_DEF( FT_Error )
Werner Lembergc4c373c2002-10-07 09:15:20 +00001553 FT_Open_Face( FT_Library library,
1554 const FT_Open_Args* args,
1555 FT_Long face_index,
1556 FT_Face *aface )
David Turnerd2b1f351999-12-16 23:11:37 +00001557 {
1558 FT_Error error;
1559 FT_Driver driver;
1560 FT_Memory memory;
David Turnercda32b72000-02-10 16:14:35 +00001561 FT_Stream stream;
David Turnerd2b1f351999-12-16 23:11:37 +00001562 FT_Face face = 0;
1563 FT_ListNode node = 0;
David Turnerc5cdf8b2000-07-27 21:40:22 +00001564 FT_Bool external_stream;
Werner Lemberg547a2522000-02-16 08:23:58 +00001565
Werner Lemberg58b17f92000-07-27 23:29:08 +00001566
Werner Lembergf9b03752000-09-11 22:50:13 +00001567 /* test for valid `library' delayed to */
Werner Lemberg75435332004-02-25 12:58:54 +00001568 /* FT_Stream_New() */
David Turnerd2b1f351999-12-16 23:11:37 +00001569
Werner Lembergce235ea2005-05-17 20:35:23 +00001570 if ( ( !aface && face_index >= 0 ) || !args )
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001571 return FT_Err_Invalid_Argument;
1572
David Turnerb08fe2d2002-08-27 20:20:29 +00001573 external_stream = FT_BOOL( ( args->flags & FT_OPEN_STREAM ) &&
Werner Lemberg8eb03532001-06-19 23:03:41 +00001574 args->stream );
David Turnerc5cdf8b2000-07-27 21:40:22 +00001575
David Turnercda32b72000-02-10 16:14:35 +00001576 /* create input stream */
Werner Lemberg75435332004-02-25 12:58:54 +00001577 error = FT_Stream_New( library, args, &stream );
Werner Lembergdeb4e982000-06-29 03:14:25 +00001578 if ( error )
1579 goto Exit;
David Turnercda32b72000-02-10 16:14:35 +00001580
David Turnerd2b1f351999-12-16 23:11:37 +00001581 memory = library->memory;
1582
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001583 /* If the font driver is specified in the `args' structure, use */
Werner Lembergdeb4e982000-06-29 03:14:25 +00001584 /* it. Otherwise, we scan the list of registered drivers. */
David Turnerb08fe2d2002-08-27 20:20:29 +00001585 if ( ( args->flags & FT_OPEN_DRIVER ) && args->driver )
David Turner7663f222000-02-13 13:37:38 +00001586 {
Werner Lemberga929ba92000-06-25 06:47:11 +00001587 driver = FT_DRIVER( args->driver );
David Turnerf0df85b2000-06-22 00:17:42 +00001588
1589 /* not all modules are drivers, so check... */
Werner Lemberga929ba92000-06-25 06:47:11 +00001590 if ( FT_MODULE_IS_DRIVER( driver ) )
David Turner7663f222000-02-13 13:37:38 +00001591 {
Werner Lemberg3c403e42002-08-06 21:47:40 +00001592 FT_Int num_params = 0;
1593 FT_Parameter* params = 0;
1594
Werner Lemberga929ba92000-06-25 06:47:11 +00001595
David Turnerb08fe2d2002-08-27 20:20:29 +00001596 if ( args->flags & FT_OPEN_PARAMS )
David Turner4f2c5542000-05-12 10:19:41 +00001597 {
1598 num_params = args->num_params;
1599 params = args->params;
1600 }
David Turnere49ab252000-05-16 23:44:38 +00001601
David Turner4f2c5542000-05-12 10:19:41 +00001602 error = open_face( driver, stream, face_index,
1603 num_params, params, &face );
Werner Lemberg547a2522000-02-16 08:23:58 +00001604 if ( !error )
1605 goto Success;
David Turner7663f222000-02-13 13:37:38 +00001606 }
1607 else
1608 error = FT_Err_Invalid_Handle;
1609
Werner Lemberg75435332004-02-25 12:58:54 +00001610 FT_Stream_Free( stream, external_stream );
David Turner7663f222000-02-13 13:37:38 +00001611 goto Fail;
1612 }
Just van Rossum1e5754f2000-03-02 10:52:57 +00001613 else
David Turnerd2b1f351999-12-16 23:11:37 +00001614 {
1615 /* check each font driver for an appropriate format */
David Turnerf0df85b2000-06-22 00:17:42 +00001616 FT_Module* cur = library->modules;
1617 FT_Module* limit = cur + library->num_modules;
David Turnerd2b1f351999-12-16 23:11:37 +00001618
Werner Lemberga929ba92000-06-25 06:47:11 +00001619
David Turnerd2b1f351999-12-16 23:11:37 +00001620 for ( ; cur < limit; cur++ )
1621 {
David Turnerf0df85b2000-06-22 00:17:42 +00001622 /* not all modules are font drivers, so check... */
Werner Lemberga929ba92000-06-25 06:47:11 +00001623 if ( FT_MODULE_IS_DRIVER( cur[0] ) )
David Turnerd2b1f351999-12-16 23:11:37 +00001624 {
David Turner4f2c5542000-05-12 10:19:41 +00001625 FT_Int num_params = 0;
1626 FT_Parameter* params = 0;
David Turnere49ab252000-05-16 23:44:38 +00001627
Werner Lemberg3c403e42002-08-06 21:47:40 +00001628
Werner Lemberga929ba92000-06-25 06:47:11 +00001629 driver = FT_DRIVER( cur[0] );
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001630
David Turnerb08fe2d2002-08-27 20:20:29 +00001631 if ( args->flags & FT_OPEN_PARAMS )
David Turner4f2c5542000-05-12 10:19:41 +00001632 {
1633 num_params = args->num_params;
1634 params = args->params;
1635 }
David Turnere49ab252000-05-16 23:44:38 +00001636
Graham Asherd53cf1d2002-07-18 15:04:29 +00001637 error = open_face( driver, stream, face_index,
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001638 num_params, params, &face );
David Turnerd2b1f351999-12-16 23:11:37 +00001639 if ( !error )
1640 goto Success;
1641
Werner Lemberg79860702001-06-08 21:17:29 +00001642 if ( FT_ERROR_BASE( error ) != FT_Err_Unknown_File_Format )
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001643 goto Fail3;
David Turnerd2b1f351999-12-16 23:11:37 +00001644 }
1645 }
1646
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001647 Fail3:
1648 /* If we are on the mac, and we get an FT_Err_Invalid_Stream_Operation */
1649 /* it may be because we have an empty data fork, so we need to check */
1650 /* the resource fork. */
1651 if ( FT_ERROR_BASE( error ) != FT_Err_Unknown_File_Format &&
1652 FT_ERROR_BASE( error ) != FT_Err_Invalid_Stream_Operation )
1653 goto Fail2;
1654
Werner Lembergdc8ad542003-12-09 02:12:14 +00001655#if !defined( FT_MACINTOSH ) && defined( FT_CONFIG_OPTION_MAC_FONTS )
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001656 error = load_mac_face( library, stream, face_index, aface, args );
1657 if ( !error )
1658 {
1659 /* We don't want to go to Success here. We've already done that. */
1660 /* On the other hand, if we succeeded we still need to close this */
1661 /* stream (we opened a different stream which extracted the */
1662 /* interesting information out of this stream here. That stream */
1663 /* will still be open and the face will point to it). */
Werner Lemberg75435332004-02-25 12:58:54 +00001664 FT_Stream_Free( stream, external_stream );
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001665 return error;
1666 }
1667
1668 if ( FT_ERROR_BASE( error ) != FT_Err_Unknown_File_Format )
1669 goto Fail2;
Werner Lembergdc8ad542003-12-09 02:12:14 +00001670#endif /* !FT_MACINTOSH && FT_CONFIG_OPTION_MAC_FONTS */
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001671
David Turnerd2b1f351999-12-16 23:11:37 +00001672 /* no driver is able to handle this format */
1673 error = FT_Err_Unknown_File_Format;
David Turnerebe85f52001-05-11 14:25:57 +00001674
1675 Fail2:
Werner Lemberg75435332004-02-25 12:58:54 +00001676 FT_Stream_Free( stream, external_stream );
David Turnercda32b72000-02-10 16:14:35 +00001677 goto Fail;
David Turnerd2b1f351999-12-16 23:11:37 +00001678 }
1679
1680 Success:
Werner Lembergf9b03752000-09-11 22:50:13 +00001681 FT_TRACE4(( "FT_Open_Face: New face object, adding to list\n" ));
David Turnerd2b1f351999-12-16 23:11:37 +00001682
Werner Lembergdeb4e982000-06-29 03:14:25 +00001683 /* set the FT_FACE_FLAG_EXTERNAL_STREAM bit for FT_Done_Face */
David Turnerc5cdf8b2000-07-27 21:40:22 +00001684 if ( external_stream )
David Turnerf0df85b2000-06-22 00:17:42 +00001685 face->face_flags |= FT_FACE_FLAG_EXTERNAL_STREAM;
1686
Werner Lemberg547a2522000-02-16 08:23:58 +00001687 /* add the face object to its driver's list */
David Turnere459d742002-03-22 13:52:37 +00001688 if ( FT_NEW( node ) )
David Turnerd2b1f351999-12-16 23:11:37 +00001689 goto Fail;
1690
1691 node->data = face;
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001692 /* don't assume driver is the same as face->driver, so use */
1693 /* face->driver instead. */
Just van Rossum7eef5362000-03-05 16:07:58 +00001694 FT_List_Add( &face->driver->faces_list, node );
David Turnerd2b1f351999-12-16 23:11:37 +00001695
Werner Lemberg547a2522000-02-16 08:23:58 +00001696 /* now allocate a glyph slot object for the face */
Werner Lembergb9ee7372005-05-20 21:52:19 +00001697 FT_TRACE4(( "FT_Open_Face: Creating glyph slot\n" ));
David Turnerd2b1f351999-12-16 23:11:37 +00001698
David Turner92f30c82005-10-17 21:17:20 +00001699 if ( face_index >= 0 )
David Turnerd2b1f351999-12-16 23:11:37 +00001700 {
David Turner92f30c82005-10-17 21:17:20 +00001701 error = FT_New_GlyphSlot( face, NULL );
Werner Lembergdeb4e982000-06-29 03:14:25 +00001702 if ( error )
1703 goto Fail;
1704
David Turner92f30c82005-10-17 21:17:20 +00001705 /* finally, allocate a size object for the face */
1706 {
1707 FT_Size size;
1708
1709
1710 FT_TRACE4(( "FT_Open_Face: Creating size object\n" ));
1711
1712 error = FT_New_Size( face, &size );
1713 if ( error )
1714 goto Fail;
1715
1716 face->size = size;
1717 }
David Turnerd2b1f351999-12-16 23:11:37 +00001718 }
Werner Lemberg7880dd62000-01-10 17:19:45 +00001719
Wu, Chia-I (吳佳一)e5ff0592006-01-15 06:00:49 +00001720 /* some checks */
1721
1722 if ( FT_IS_SCALABLE( face ) )
1723 {
1724 if ( face->height < 0 )
1725 face->height = -face->height;
1726
1727 if ( !FT_HAS_VERTICAL( face ) )
1728 face->max_advance_height = face->height;
1729 }
1730
1731 if ( FT_HAS_FIXED_SIZES( face ) )
1732 {
Werner Lemberg1723dcc2006-01-15 07:30:32 +00001733 FT_Int i;
Wu, Chia-I (吳佳一)e5ff0592006-01-15 06:00:49 +00001734
1735
1736 for ( i = 0; i < face->num_fixed_sizes; i++ )
1737 {
1738 FT_Bitmap_Size* bsize = face->available_sizes + i;
1739
1740
1741 if ( bsize->height < 0 )
1742 bsize->height = -bsize->height;
1743 if ( bsize->x_ppem < 0 )
1744 bsize->x_ppem = -bsize->x_ppem;
1745 if ( bsize->y_ppem < 0 )
1746 bsize->y_ppem = -bsize->y_ppem;
1747 }
1748 }
1749
David Turner54e75742000-11-04 02:52:02 +00001750 /* initialize internal face data */
1751 {
1752 FT_Face_Internal internal = face->internal;
David Turner61d6b2b2001-05-16 17:49:07 +00001753
David Turner37379e22000-03-28 11:22:31 +00001754
David Turner54e75742000-11-04 02:52:02 +00001755 internal->transform_matrix.xx = 0x10000L;
1756 internal->transform_matrix.xy = 0;
1757 internal->transform_matrix.yx = 0;
1758 internal->transform_matrix.yy = 0x10000L;
David Turner61d6b2b2001-05-16 17:49:07 +00001759
David Turner54e75742000-11-04 02:52:02 +00001760 internal->transform_delta.x = 0;
1761 internal->transform_delta.y = 0;
1762 }
David Turner37379e22000-03-28 11:22:31 +00001763
Werner Lembergce235ea2005-05-17 20:35:23 +00001764 if ( aface )
1765 *aface = face;
Werner Lembergb2d02532005-11-04 06:58:49 +00001766 else
1767 FT_Done_Face( face );
1768
David Turnerd2b1f351999-12-16 23:11:37 +00001769 goto Exit;
1770
1771 Fail:
1772 FT_Done_Face( face );
1773
David Turnerd2b1f351999-12-16 23:11:37 +00001774 Exit:
1775 FT_TRACE4(( "FT_Open_Face: Return %d\n", error ));
Werner Lembergdeb4e982000-06-29 03:14:25 +00001776
David Turnerd2b1f351999-12-16 23:11:37 +00001777 return error;
1778 }
1779
1780
Werner Lemberg90a03302000-11-07 17:21:11 +00001781 /* documentation is in freetype.h */
1782
Werner Lembergf814d0f2001-06-27 16:18:10 +00001783 FT_EXPORT_DEF( FT_Error )
1784 FT_Attach_File( FT_Face face,
1785 const char* filepathname )
David Turner7663f222000-02-13 13:37:38 +00001786 {
David Turner37379e22000-03-28 11:22:31 +00001787 FT_Open_Args open;
David Turner7663f222000-02-13 13:37:38 +00001788
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001789
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001790 /* test for valid `face' delayed to FT_Attach_Stream() */
1791
1792 if ( !filepathname )
1793 return FT_Err_Invalid_Argument;
1794
Werner Lembergb8fdcd62004-08-03 03:28:11 +00001795 open.stream = NULL;
David Turnerb08fe2d2002-08-27 20:20:29 +00001796 open.flags = FT_OPEN_PATHNAME;
David Turner4f2c5542000-05-12 10:19:41 +00001797 open.pathname = (char*)filepathname;
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001798
David Turner7663f222000-02-13 13:37:38 +00001799 return FT_Attach_Stream( face, &open );
1800 }
Werner Lemberg547a2522000-02-16 08:23:58 +00001801
David Turnere49ab252000-05-16 23:44:38 +00001802
Werner Lemberg90a03302000-11-07 17:21:11 +00001803 /* documentation is in freetype.h */
1804
Werner Lembergf814d0f2001-06-27 16:18:10 +00001805 FT_EXPORT_DEF( FT_Error )
1806 FT_Attach_Stream( FT_Face face,
1807 FT_Open_Args* parameters )
David Turner7663f222000-02-13 13:37:38 +00001808 {
1809 FT_Stream stream;
1810 FT_Error error;
1811 FT_Driver driver;
David Turnere49ab252000-05-16 23:44:38 +00001812
David Turneref3c1262002-03-14 09:22:48 +00001813 FT_Driver_Class clazz;
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001814
Werner Lemberga929ba92000-06-25 06:47:11 +00001815
Werner Lemberg75435332004-02-25 12:58:54 +00001816 /* test for valid `parameters' delayed to FT_Stream_New() */
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001817
1818 if ( !face )
1819 return FT_Err_Invalid_Face_Handle;
David Turnere49ab252000-05-16 23:44:38 +00001820
David Turner7663f222000-02-13 13:37:38 +00001821 driver = face->driver;
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001822 if ( !driver )
1823 return FT_Err_Invalid_Driver_Handle;
1824
Werner Lemberg75435332004-02-25 12:58:54 +00001825 error = FT_Stream_New( driver->root.library, parameters, &stream );
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001826 if ( error )
1827 goto Exit;
David Turnere49ab252000-05-16 23:44:38 +00001828
David Turner7663f222000-02-13 13:37:38 +00001829 /* we implement FT_Attach_Stream in each driver through the */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001830 /* `attach_file' interface */
1831
David Turner7663f222000-02-13 13:37:38 +00001832 error = FT_Err_Unimplemented_Feature;
David Turnerf0df85b2000-06-22 00:17:42 +00001833 clazz = driver->clazz;
Werner Lemberga929ba92000-06-25 06:47:11 +00001834 if ( clazz->attach_file )
David Turnerf0df85b2000-06-22 00:17:42 +00001835 error = clazz->attach_file( face, stream );
David Turnere49ab252000-05-16 23:44:38 +00001836
David Turner7663f222000-02-13 13:37:38 +00001837 /* close the attached stream */
Werner Lemberg75435332004-02-25 12:58:54 +00001838 FT_Stream_Free( stream,
Werner Lemberg58b17f92000-07-27 23:29:08 +00001839 (FT_Bool)( parameters->stream &&
David Turnerb08fe2d2002-08-27 20:20:29 +00001840 ( parameters->flags & FT_OPEN_STREAM ) ) );
David Turnere49ab252000-05-16 23:44:38 +00001841
David Turner7663f222000-02-13 13:37:38 +00001842 Exit:
1843 return error;
1844 }
1845
1846
Werner Lemberg90a03302000-11-07 17:21:11 +00001847 /* documentation is in freetype.h */
1848
Werner Lembergf814d0f2001-06-27 16:18:10 +00001849 FT_EXPORT_DEF( FT_Error )
1850 FT_Done_Face( FT_Face face )
David Turnerd2b1f351999-12-16 23:11:37 +00001851 {
Werner Lemberga929ba92000-06-25 06:47:11 +00001852 FT_Error error;
1853 FT_Driver driver;
1854 FT_Memory memory;
1855 FT_ListNode node;
1856
David Turnerd2b1f351999-12-16 23:11:37 +00001857
David Turnerf0df85b2000-06-22 00:17:42 +00001858 error = FT_Err_Invalid_Face_Handle;
1859 if ( face && face->driver )
David Turnerd2b1f351999-12-16 23:11:37 +00001860 {
David Turnerf0df85b2000-06-22 00:17:42 +00001861 driver = face->driver;
1862 memory = driver->root.memory;
Werner Lembergdeb4e982000-06-29 03:14:25 +00001863
David Turnerf0df85b2000-06-22 00:17:42 +00001864 /* find face in driver's list */
1865 node = FT_List_Find( &driver->faces_list, face );
1866 if ( node )
1867 {
1868 /* remove face object from the driver's list */
1869 FT_List_Remove( &driver->faces_list, node );
David Turnere459d742002-03-22 13:52:37 +00001870 FT_FREE( node );
Werner Lembergdeb4e982000-06-29 03:14:25 +00001871
David Turnerf0df85b2000-06-22 00:17:42 +00001872 /* now destroy the object proper */
1873 destroy_face( memory, face, driver );
1874 error = FT_Err_Ok;
1875 }
David Turnerd2b1f351999-12-16 23:11:37 +00001876 }
David Turnerd2b1f351999-12-16 23:11:37 +00001877 return error;
1878 }
1879
1880
Werner Lemberg90a03302000-11-07 17:21:11 +00001881 /* documentation is in ftobjs.h */
1882
Werner Lembergf814d0f2001-06-27 16:18:10 +00001883 FT_EXPORT_DEF( FT_Error )
1884 FT_New_Size( FT_Face face,
1885 FT_Size *asize )
David Turnerd2b1f351999-12-16 23:11:37 +00001886 {
Werner Lembergf8ba2002002-03-30 13:16:35 +00001887 FT_Error error;
1888 FT_Memory memory;
1889 FT_Driver driver;
David Turneref3c1262002-03-14 09:22:48 +00001890 FT_Driver_Class clazz;
David Turnerd2b1f351999-12-16 23:11:37 +00001891
Werner Lembergf8ba2002002-03-30 13:16:35 +00001892 FT_Size size = 0;
1893 FT_ListNode node = 0;
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001894
Werner Lemberga929ba92000-06-25 06:47:11 +00001895
Werner Lembergb48a6092000-07-09 19:15:30 +00001896 if ( !face )
1897 return FT_Err_Invalid_Face_Handle;
1898
1899 if ( !asize )
1900 return FT_Err_Invalid_Size_Handle;
1901
1902 if ( !face->driver )
1903 return FT_Err_Invalid_Driver_Handle;
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001904
Werner Lembergdeb4e982000-06-29 03:14:25 +00001905 *asize = 0;
1906
David Turnerf0df85b2000-06-22 00:17:42 +00001907 driver = face->driver;
1908 clazz = driver->clazz;
1909 memory = face->memory;
David Turnerd2b1f351999-12-16 23:11:37 +00001910
1911 /* Allocate new size object and perform basic initialisation */
David Turnere459d742002-03-22 13:52:37 +00001912 if ( FT_ALLOC( size, clazz->size_object_size ) || FT_NEW( node ) )
David Turnerd2b1f351999-12-16 23:11:37 +00001913 goto Exit;
1914
1915 size->face = face;
David Turner61d6b2b2001-05-16 17:49:07 +00001916
David Turner54e75742000-11-04 02:52:02 +00001917 /* for now, do not use any internal fields in size objects */
1918 size->internal = 0;
David Turnerd2b1f351999-12-16 23:11:37 +00001919
Werner Lemberga929ba92000-06-25 06:47:11 +00001920 if ( clazz->init_size )
David Turnerf0df85b2000-06-22 00:17:42 +00001921 error = clazz->init_size( size );
David Turnerd2b1f351999-12-16 23:11:37 +00001922
1923 /* in case of success, add to the face's list */
1924 if ( !error )
1925 {
1926 *asize = size;
1927 node->data = size;
1928 FT_List_Add( &face->sizes_list, node );
David Turnerd2b1f351999-12-16 23:11:37 +00001929 }
1930
1931 Exit:
1932 if ( error )
1933 {
David Turnere459d742002-03-22 13:52:37 +00001934 FT_FREE( node );
1935 FT_FREE( size );
David Turnerd2b1f351999-12-16 23:11:37 +00001936 }
1937
1938 return error;
1939 }
1940
1941
Werner Lemberg90a03302000-11-07 17:21:11 +00001942 /* documentation is in ftobjs.h */
1943
Werner Lembergf814d0f2001-06-27 16:18:10 +00001944 FT_EXPORT_DEF( FT_Error )
1945 FT_Done_Size( FT_Size size )
David Turnerd2b1f351999-12-16 23:11:37 +00001946 {
1947 FT_Error error;
1948 FT_Driver driver;
1949 FT_Memory memory;
1950 FT_Face face;
1951 FT_ListNode node;
1952
1953
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001954 if ( !size )
David Turnerd2b1f351999-12-16 23:11:37 +00001955 return FT_Err_Invalid_Size_Handle;
1956
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001957 face = size->face;
1958 if ( !face )
1959 return FT_Err_Invalid_Face_Handle;
1960
1961 driver = face->driver;
David Turnerd2b1f351999-12-16 23:11:37 +00001962 if ( !driver )
1963 return FT_Err_Invalid_Driver_Handle;
1964
David Turnerf0df85b2000-06-22 00:17:42 +00001965 memory = driver->root.memory;
David Turnerd2b1f351999-12-16 23:11:37 +00001966
1967 error = FT_Err_Ok;
David Turnerd2b1f351999-12-16 23:11:37 +00001968 node = FT_List_Find( &face->sizes_list, size );
1969 if ( node )
1970 {
1971 FT_List_Remove( &face->sizes_list, node );
David Turnere459d742002-03-22 13:52:37 +00001972 FT_FREE( node );
David Turnerd2b1f351999-12-16 23:11:37 +00001973
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001974 if ( face->size == size )
David Turnerd2b1f351999-12-16 23:11:37 +00001975 {
1976 face->size = 0;
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001977 if ( face->sizes_list.head )
David Turnerd2b1f351999-12-16 23:11:37 +00001978 face->size = (FT_Size)(face->sizes_list.head->data);
1979 }
1980
1981 destroy_size( memory, size, driver );
1982 }
1983 else
1984 error = FT_Err_Invalid_Size_Handle;
1985
Werner Lembergcf24d512001-06-18 14:23:45 +00001986 return error;
David Turnerd2b1f351999-12-16 23:11:37 +00001987 }
1988
1989
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00001990 /* documentation is in ftobjs.h */
1991
1992 FT_BASE_DEF( FT_Error )
1993 FT_Match_Size( FT_Face face,
1994 FT_Size_Request req,
1995 FT_Bool ignore_width,
1996 FT_ULong* index )
1997 {
1998 FT_Int i;
1999 FT_Long w, h;
2000
2001
2002 if ( !FT_HAS_FIXED_SIZES( face ) )
2003 return FT_Err_Invalid_Face_Handle;
2004
2005 /* FT_Bitmap_Size doesn't provide enough info... */
2006 if ( req->type != FT_SIZE_REQUEST_TYPE_NOMINAL )
2007 return FT_Err_Unimplemented_Feature;
2008
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002009 w = FT_REQUEST_WIDTH( req );
2010 h = FT_REQUEST_HEIGHT( req );
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002011
2012 if ( req->width && !req->height )
2013 h = w;
2014 else if ( !req->width && req->height )
2015 w = h;
2016
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002017 w = FT_PIX_ROUND( w );
2018 h = FT_PIX_ROUND( h );
2019
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002020 for ( i = 0; i < face->num_fixed_sizes; i++ )
2021 {
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002022 FT_Bitmap_Size* bsize = face->available_sizes + i;
2023
2024
2025 if ( h != FT_PIX_ROUND( bsize->y_ppem ) )
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002026 continue;
2027
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002028 if ( w == FT_PIX_ROUND( bsize->x_ppem ) || ignore_width )
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002029 {
2030 if ( index )
2031 *index = (FT_ULong)i;
2032
2033 return FT_Err_Ok;
2034 }
2035 }
2036
2037 return FT_Err_Invalid_Pixel_Size;
2038 }
2039
2040
Wu, Chia-I (吳佳一)212aee02006-01-15 06:24:53 +00002041 /* documentation is in ftobjs.h */
2042
2043 FT_BASE_DEF( void )
Wu, Chia-I (吳佳一)ea1e8d32006-01-15 15:01:45 +00002044 ft_synthesize_vertical_metrics( FT_Glyph_Metrics* metrics,
2045 FT_Pos advance )
Wu, Chia-I (吳佳一)212aee02006-01-15 06:24:53 +00002046 {
Werner Lemberg1723dcc2006-01-15 07:30:32 +00002047 /* the factor 1.2 is a heuristical value */
Wu, Chia-I (吳佳一)212aee02006-01-15 06:24:53 +00002048 if ( !advance )
2049 advance = metrics->height * 12 / 10;
2050
2051 metrics->vertBearingX = -( metrics->width / 2 );
2052 metrics->vertBearingY = ( advance - metrics->height ) / 2;
2053 metrics->vertAdvance = advance;
2054 }
2055
2056
Werner Lembergf814d0f2001-06-27 16:18:10 +00002057 static void
2058 ft_recompute_scaled_metrics( FT_Face face,
2059 FT_Size_Metrics* metrics )
Werner Lembergdeb4e982000-06-29 03:14:25 +00002060 {
Werner Lemberga929ba92000-06-25 06:47:11 +00002061 /* Compute root ascender, descender, test height, and max_advance */
Werner Lembergdeb4e982000-06-29 03:14:25 +00002062
Wu, Chia-I (吳佳一)dcb8b712005-12-16 14:27:14 +00002063 metrics->ascender = FT_MulFix( face->ascender,
2064 metrics->y_scale );
Werner Lemberga929ba92000-06-25 06:47:11 +00002065
Wu, Chia-I (吳佳一)dcb8b712005-12-16 14:27:14 +00002066 metrics->descender = FT_MulFix( face->descender,
2067 metrics->y_scale );
Werner Lemberga929ba92000-06-25 06:47:11 +00002068
Wu, Chia-I (吳佳一)dcb8b712005-12-16 14:27:14 +00002069 metrics->height = FT_MulFix( face->height,
2070 metrics->y_scale );
Werner Lemberga929ba92000-06-25 06:47:11 +00002071
Wu, Chia-I (吳佳一)dcb8b712005-12-16 14:27:14 +00002072 metrics->max_advance = FT_MulFix( face->max_advance_width,
2073 metrics->x_scale );
Werner Lemberga929ba92000-06-25 06:47:11 +00002074 }
2075
2076
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002077 FT_BASE_DEF( void )
2078 FT_Select_Metrics( FT_Face face,
2079 FT_ULong strike_index )
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002080 {
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002081 FT_Size_Metrics* metrics;
2082 FT_Bitmap_Size* bsize;
2083
2084
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002085 metrics = &face->size->metrics;
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002086 bsize = face->available_sizes + strike_index;
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002087
2088 metrics->x_ppem = ( bsize->x_ppem + 32 ) >> 6;
2089 metrics->y_ppem = ( bsize->y_ppem + 32 ) >> 6;
2090
2091 if ( FT_IS_SCALABLE( face ) )
2092 {
2093 metrics->x_scale = FT_DivFix( bsize->x_ppem,
2094 face->units_per_EM );
2095 metrics->y_scale = FT_DivFix( bsize->y_ppem,
2096 face->units_per_EM );
2097
2098 ft_recompute_scaled_metrics( face, metrics );
2099 }
2100 else
2101 {
Werner Lemberg1723dcc2006-01-15 07:30:32 +00002102 metrics->x_scale = 1L << 22;
2103 metrics->y_scale = 1L << 22;
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002104 metrics->ascender = bsize->y_ppem;
2105 metrics->descender = 0;
2106 metrics->height = bsize->height << 6;
2107 metrics->max_advance = bsize->x_ppem;
2108 }
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002109 }
2110
2111
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002112 FT_BASE_DEF( void )
2113 FT_Request_Metrics( FT_Face face,
2114 FT_Size_Request req )
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002115 {
2116 FT_Driver_Class clazz;
2117 FT_Size_Metrics* metrics;
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002118
2119
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002120 clazz = face->driver->clazz;
2121 metrics = &face->size->metrics;
2122
2123 if ( FT_IS_SCALABLE( face ) )
2124 {
2125 FT_Long w, h, scaled_w, scaled_h;
2126
2127
2128 switch ( req->type )
2129 {
2130 case FT_SIZE_REQUEST_TYPE_NOMINAL:
2131 w = h = face->units_per_EM;
2132 break;
Werner Lembergf1c2b912006-01-13 14:53:28 +00002133
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002134 case FT_SIZE_REQUEST_TYPE_REAL_DIM:
2135 w = h = face->ascender - face->descender;
2136 break;
Werner Lembergf1c2b912006-01-13 14:53:28 +00002137
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002138 case FT_SIZE_REQUEST_TYPE_CELL:
2139 w = face->max_advance_width;
2140 h = face->ascender - face->descender;
2141 break;
Werner Lembergf1c2b912006-01-13 14:53:28 +00002142
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002143 case FT_SIZE_REQUEST_TYPE_BBOX:
2144 w = face->bbox.xMax - face->bbox.xMin;
2145 h = face->bbox.yMax - face->bbox.yMin;
2146 break;
Werner Lembergf1c2b912006-01-13 14:53:28 +00002147
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002148 default:
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002149 /* this never happens */
2150 return;
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002151 break;
2152 }
2153
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002154 /* to be on the safe side */
Wu, Chia-I (吳佳一)e5ff0592006-01-15 06:00:49 +00002155 if ( w < 0 )
2156 w = -w;
2157
2158 if ( h < 0 )
2159 h = -h;
2160
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002161 scaled_w = FT_REQUEST_WIDTH( req );
2162 scaled_h = FT_REQUEST_HEIGHT( req );
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002163
2164 /* determine scales */
2165 if ( req->width )
2166 {
2167 metrics->x_scale = FT_DivFix( scaled_w, w );
2168
2169 if ( req->height )
2170 {
2171 metrics->y_scale = FT_DivFix( scaled_h, h );
2172
2173 if ( req->type == FT_SIZE_REQUEST_TYPE_CELL )
2174 {
2175 if ( metrics->y_scale > metrics->x_scale )
2176 metrics->y_scale = metrics->x_scale;
2177 else
2178 metrics->x_scale = metrics->y_scale;
2179 }
2180 }
2181 else
2182 {
2183 metrics->y_scale = metrics->x_scale;
2184 scaled_h = FT_MulDiv( scaled_w, h, w );
2185 }
2186 }
2187 else
2188 {
2189 metrics->x_scale = metrics->y_scale = FT_DivFix( scaled_h, h );
2190 scaled_w = FT_MulDiv( scaled_h, w, h );
2191 }
2192
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002193 /* calculate the ppems */
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002194 if ( req->type != FT_SIZE_REQUEST_TYPE_NOMINAL )
2195 {
2196 scaled_w = FT_MulFix( face->units_per_EM, metrics->x_scale );
2197 scaled_h = FT_MulFix( face->units_per_EM, metrics->y_scale );
2198 }
2199
2200 metrics->x_ppem = ( scaled_w + 32 ) >> 6;
2201 metrics->y_ppem = ( scaled_h + 32 ) >> 6;
2202
2203 ft_recompute_scaled_metrics( face, metrics );
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002204 }
2205 else
2206 {
2207 FT_ZERO( metrics );
Werner Lemberg1723dcc2006-01-15 07:30:32 +00002208 metrics->x_scale = 1L << 22;
2209 metrics->y_scale = 1L << 22;
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002210 }
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002211 }
2212
2213
2214 /* documentation is in freetype.h */
2215
2216 FT_EXPORT_DEF( FT_Error )
2217 FT_Select_Size( FT_Face face,
2218 FT_Int strike_index )
2219 {
2220 FT_Driver_Class clazz;
2221
2222
2223 if ( !face || !FT_HAS_FIXED_SIZES( face ) )
2224 return FT_Err_Invalid_Face_Handle;
2225
2226 if ( strike_index < 0 || strike_index >= face->num_fixed_sizes )
2227 return FT_Err_Invalid_Argument;
2228
2229 clazz = face->driver->clazz;
2230
2231 if ( clazz->select_size )
2232 return clazz->select_size( face->size, (FT_ULong)strike_index );
2233
2234 FT_Select_Metrics( face, (FT_ULong)strike_index );
2235
2236 return FT_Err_Ok;
2237 }
2238
2239
2240 /* documentation is in freetype.h */
2241
2242 FT_EXPORT_DEF( FT_Error )
2243 FT_Request_Size( FT_Face face,
2244 FT_Size_Request req )
2245 {
2246 FT_Driver_Class clazz;
2247 FT_ULong strike_index;
2248
2249
2250 if ( !face )
2251 return FT_Err_Invalid_Face_Handle;
2252
2253 if ( !req || req->width < 0 || req->height < 0 ||
2254 req->type >= FT_SIZE_REQUEST_TYPE_MAX )
2255 return FT_Err_Invalid_Argument;
2256
2257 clazz = face->driver->clazz;
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002258
2259 if ( clazz->request_size )
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002260 return clazz->request_size( face->size, req );
2261
Wu, Chia-I (吳佳一)e33dc2e2006-01-14 05:09:30 +00002262 /*
Werner Lemberg3d8eeb82006-01-14 07:10:45 +00002263 * The reason that a driver doesn't have `request_size' defined is
2264 * either that the scaling here suffices or that the supported formats
2265 * are bitmap-only and size matching is not implemented.
Wu, Chia-I (吳佳一)e33dc2e2006-01-14 05:09:30 +00002266 *
2267 * In the latter case, a simple size matching is done.
2268 */
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002269 if ( !FT_IS_SCALABLE( face ) && FT_HAS_FIXED_SIZES( face ) )
Wu, Chia-I (吳佳一)e33dc2e2006-01-14 05:09:30 +00002270 {
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002271 FT_Error error;
Wu, Chia-I (吳佳一)e33dc2e2006-01-14 05:09:30 +00002272
2273
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002274 error = FT_Match_Size( face, req, 0, &strike_index );
2275 if ( error )
2276 return error;
Wu, Chia-I (吳佳一)e33dc2e2006-01-14 05:09:30 +00002277
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002278 FT_TRACE3(( "FT_Request_Size: bitmap strike %lu matched\n", strike_index ));
2279
2280 return FT_Select_Size( face, (FT_Int)strike_index );
Wu, Chia-I (吳佳一)e33dc2e2006-01-14 05:09:30 +00002281 }
2282
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002283 FT_Request_Metrics( face, req );
2284
2285 return FT_Err_Ok;
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002286 }
2287
2288
2289 /* documentation is in freetype.h */
2290
2291 FT_EXPORT_DEF( FT_Error )
Werner Lembergf814d0f2001-06-27 16:18:10 +00002292 FT_Set_Char_Size( FT_Face face,
2293 FT_F26Dot6 char_width,
2294 FT_F26Dot6 char_height,
2295 FT_UInt horz_resolution,
2296 FT_UInt vert_resolution )
David Turnerd2b1f351999-12-16 23:11:37 +00002297 {
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002298 FT_Size_RequestRec req;
David Turnerd2b1f351999-12-16 23:11:37 +00002299
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00002300
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002301 req.type = FT_SIZE_REQUEST_TYPE_NOMINAL;
2302 req.width = char_width;
2303 req.height = char_height;
2304 req.horiResolution = ( horz_resolution ) ? horz_resolution : 72;
2305 req.vertResolution = ( vert_resolution ) ? vert_resolution : 72;
David Turnerd2b1f351999-12-16 23:11:37 +00002306
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002307 return FT_Request_Size( face, &req );
David Turnerd2b1f351999-12-16 23:11:37 +00002308 }
2309
2310
Werner Lemberg90a03302000-11-07 17:21:11 +00002311 /* documentation is in freetype.h */
2312
Werner Lembergf814d0f2001-06-27 16:18:10 +00002313 FT_EXPORT_DEF( FT_Error )
2314 FT_Set_Pixel_Sizes( FT_Face face,
2315 FT_UInt pixel_width,
2316 FT_UInt pixel_height )
David Turnerd2b1f351999-12-16 23:11:37 +00002317 {
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002318 FT_Size_RequestRec req;
David Turnerd2b1f351999-12-16 23:11:37 +00002319
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00002320
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002321 req.type = FT_SIZE_REQUEST_TYPE_NOMINAL;
2322 req.width = pixel_width << 6;
2323 req.height = pixel_height << 6;
2324 req.horiResolution = 0;
2325 req.vertResolution = 0;
David Turnerd2b1f351999-12-16 23:11:37 +00002326
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002327 return FT_Request_Size( face, &req );
David Turnerd2b1f351999-12-16 23:11:37 +00002328 }
2329
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00002330
Werner Lemberg90a03302000-11-07 17:21:11 +00002331 /* documentation is in freetype.h */
2332
Werner Lembergf814d0f2001-06-27 16:18:10 +00002333 FT_EXPORT_DEF( FT_Error )
2334 FT_Get_Kerning( FT_Face face,
2335 FT_UInt left_glyph,
2336 FT_UInt right_glyph,
2337 FT_UInt kern_mode,
2338 FT_Vector *akerning )
David Turnerd2b1f351999-12-16 23:11:37 +00002339 {
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00002340 FT_Error error = FT_Err_Ok;
David Turnerd2b1f351999-12-16 23:11:37 +00002341 FT_Driver driver;
David Turnerd2b1f351999-12-16 23:11:37 +00002342
Werner Lemberga8bbc262000-07-01 14:06:46 +00002343
David Turnerd2b1f351999-12-16 23:11:37 +00002344 if ( !face )
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00002345 return FT_Err_Invalid_Face_Handle;
2346
Werner Lemberg4b680072000-11-07 06:30:29 +00002347 if ( !akerning )
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00002348 return FT_Err_Invalid_Argument;
David Turnerd2b1f351999-12-16 23:11:37 +00002349
2350 driver = face->driver;
David Turnerd2b1f351999-12-16 23:11:37 +00002351
Werner Lemberg4b680072000-11-07 06:30:29 +00002352 akerning->x = 0;
2353 akerning->y = 0;
Werner Lemberg5aa646c2000-07-14 06:16:47 +00002354
David Turnerf0df85b2000-06-22 00:17:42 +00002355 if ( driver->clazz->get_kerning )
David Turnerd2b1f351999-12-16 23:11:37 +00002356 {
David Turnerf0df85b2000-06-22 00:17:42 +00002357 error = driver->clazz->get_kerning( face,
Werner Lemberga929ba92000-06-25 06:47:11 +00002358 left_glyph,
2359 right_glyph,
Werner Lemberg4b680072000-11-07 06:30:29 +00002360 akerning );
Werner Lemberg5aa646c2000-07-14 06:16:47 +00002361 if ( !error )
David Turnerf9ca2bb2000-06-30 23:12:55 +00002362 {
David Turnerb08fe2d2002-08-27 20:20:29 +00002363 if ( kern_mode != FT_KERNING_UNSCALED )
David Turnerf9ca2bb2000-06-30 23:12:55 +00002364 {
Werner Lemberg4b680072000-11-07 06:30:29 +00002365 akerning->x = FT_MulFix( akerning->x, face->size->metrics.x_scale );
2366 akerning->y = FT_MulFix( akerning->y, face->size->metrics.y_scale );
Werner Lemberg5aa646c2000-07-14 06:16:47 +00002367
David Turnerb08fe2d2002-08-27 20:20:29 +00002368 if ( kern_mode != FT_KERNING_UNFITTED )
Werner Lemberg5aa646c2000-07-14 06:16:47 +00002369 {
Werner Lemberg133eee02004-12-12 06:55:40 +00002370 /* we scale down kerning values for small ppem values */
2371 /* to avoid that rounding makes them too big. */
2372 /* `25' has been determined heuristically. */
2373 if ( face->size->metrics.x_ppem < 25 )
2374 akerning->x = FT_MulDiv( akerning->x,
2375 face->size->metrics.x_ppem, 25 );
2376 if ( face->size->metrics.y_ppem < 25 )
2377 akerning->y = FT_MulDiv( akerning->y,
2378 face->size->metrics.y_ppem, 25 );
2379
2380 akerning->x = FT_PIX_ROUND( akerning->x );
2381 akerning->y = FT_PIX_ROUND( akerning->y );
Werner Lemberg5aa646c2000-07-14 06:16:47 +00002382 }
David Turnerf9ca2bb2000-06-30 23:12:55 +00002383 }
2384 }
2385 }
David Turnerd2b1f351999-12-16 23:11:37 +00002386
David Turnerd2b1f351999-12-16 23:11:37 +00002387 return error;
2388 }
2389
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00002390
Werner Lemberg90a03302000-11-07 17:21:11 +00002391 /* documentation is in freetype.h */
2392
Werner Lembergf814d0f2001-06-27 16:18:10 +00002393 FT_EXPORT_DEF( FT_Error )
Wu, Chia-I (吳佳一)108fdbb2006-01-16 15:35:56 +00002394 FT_Get_Track_Kerning( FT_Face face,
2395 FT_Fixed point_size,
2396 FT_Int degree,
2397 FT_Fixed* akerning )
2398 {
2399 FT_Service_Kerning service;
2400 FT_Error error = FT_Err_Ok;
2401 FT_Driver driver;
2402
2403
2404 if ( !face )
2405 return FT_Err_Invalid_Face_Handle;
2406
2407 if ( !akerning )
2408 return FT_Err_Invalid_Argument;
2409
2410 driver = face->driver;
2411
2412 FT_FACE_FIND_SERVICE( face, service, KERNING );
2413 if ( !service )
2414 return FT_Err_Unimplemented_Feature;
2415
2416 error = service->get_track( face,
2417 point_size,
2418 degree,
2419 akerning );
2420
2421 return error;
2422 }
2423
2424
2425 /* documentation is in freetype.h */
2426
2427 FT_EXPORT_DEF( FT_Error )
Werner Lembergf814d0f2001-06-27 16:18:10 +00002428 FT_Select_Charmap( FT_Face face,
2429 FT_Encoding encoding )
David Turner0a29c692000-05-12 17:09:38 +00002430 {
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00002431 FT_CharMap* cur;
2432 FT_CharMap* limit;
David Turnere49ab252000-05-16 23:44:38 +00002433
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00002434
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00002435 if ( !face )
2436 return FT_Err_Invalid_Face_Handle;
2437
Werner Lembergc8c6bf52003-04-23 05:38:13 +00002438 /* FT_ENCODING_UNICODE is special. We try to find the `best' Unicode */
2439 /* charmap available, i.e., one with UCS-4 characters, if possible. */
2440 /* */
2441 /* This is done by find_unicode_charmap() above, to share code. */
Antoine Lecac96f69d2002-12-03 00:39:16 +00002442 if ( encoding == FT_ENCODING_UNICODE )
2443 return find_unicode_charmap( face );
2444
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00002445 cur = face->charmaps;
2446 if ( !cur )
2447 return FT_Err_Invalid_CharMap_Handle;
2448
2449 limit = cur + face->num_charmaps;
2450
David Turner0a29c692000-05-12 17:09:38 +00002451 for ( ; cur < limit; cur++ )
2452 {
2453 if ( cur[0]->encoding == encoding )
2454 {
2455 face->charmap = cur[0];
2456 return 0;
2457 }
2458 }
Werner Lembergdeb4e982000-06-29 03:14:25 +00002459
David Turner0a29c692000-05-12 17:09:38 +00002460 return FT_Err_Invalid_Argument;
2461 }
2462
2463
Werner Lemberg90a03302000-11-07 17:21:11 +00002464 /* documentation is in freetype.h */
2465
Werner Lembergf814d0f2001-06-27 16:18:10 +00002466 FT_EXPORT_DEF( FT_Error )
2467 FT_Set_Charmap( FT_Face face,
2468 FT_CharMap charmap )
David Turner0a29c692000-05-12 17:09:38 +00002469 {
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00002470 FT_CharMap* cur;
2471 FT_CharMap* limit;
David Turnere49ab252000-05-16 23:44:38 +00002472
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00002473
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00002474 if ( !face )
2475 return FT_Err_Invalid_Face_Handle;
2476
2477 cur = face->charmaps;
2478 if ( !cur )
2479 return FT_Err_Invalid_CharMap_Handle;
2480
2481 limit = cur + face->num_charmaps;
2482
David Turner0a29c692000-05-12 17:09:38 +00002483 for ( ; cur < limit; cur++ )
2484 {
2485 if ( cur[0] == charmap )
2486 {
2487 face->charmap = cur[0];
2488 return 0;
2489 }
2490 }
2491 return FT_Err_Invalid_Argument;
2492 }
David Turnerd2b1f351999-12-16 23:11:37 +00002493
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00002494
Werner Lemberge95365b2004-04-24 14:43:37 +00002495 /* documentation is in freetype.h */
2496
2497 FT_EXPORT_DEF( FT_Int )
2498 FT_Get_Charmap_Index( FT_CharMap charmap )
2499 {
2500 FT_Int i;
2501
2502
2503 for ( i = 0; i < charmap->face->num_charmaps; i++ )
2504 if ( charmap->face->charmaps[i] == charmap )
2505 break;
2506
2507 FT_ASSERT( i < charmap->face->num_charmaps );
2508
2509 return i;
2510 }
2511
2512
Werner Lemberge70371c2005-05-27 06:01:28 +00002513 static void
2514 ft_cmap_done_internal( FT_CMap cmap )
2515 {
2516 FT_CMap_Class clazz = cmap->clazz;
2517 FT_Face face = cmap->charmap.face;
2518 FT_Memory memory = FT_FACE_MEMORY(face);
2519
2520
2521 if ( clazz->done )
2522 clazz->done( cmap );
2523
2524 FT_FREE( cmap );
2525 }
2526
2527
David Turner4e7eeee2002-02-28 16:10:29 +00002528 FT_BASE_DEF( void )
2529 FT_CMap_Done( FT_CMap cmap )
2530 {
2531 if ( cmap )
2532 {
Werner Lemberge70371c2005-05-27 06:01:28 +00002533 FT_Face face = cmap->charmap.face;
2534 FT_Memory memory = FT_FACE_MEMORY( face );
2535 FT_Error error;
2536 FT_Int i, j;
David Turnerbc82f1b2002-03-01 02:26:22 +00002537
Werner Lembergf8ba2002002-03-30 13:16:35 +00002538
Werner Lemberge70371c2005-05-27 06:01:28 +00002539 for ( i = 0; i < face->num_charmaps; i++ )
2540 {
2541 if ( (FT_CMap)face->charmaps[i] == cmap )
2542 {
2543 FT_CharMap last_charmap = face->charmaps[face->num_charmaps - 1];
David Turner4e7eeee2002-02-28 16:10:29 +00002544
Werner Lemberge70371c2005-05-27 06:01:28 +00002545
2546 if ( FT_RENEW_ARRAY( face->charmaps,
2547 face->num_charmaps,
2548 face->num_charmaps - 1 ) )
2549 return;
2550
2551 /* remove it from our list of charmaps */
2552 for ( j = i + 1; j < face->num_charmaps; j++ )
2553 {
2554 if ( j == face->num_charmaps - 1 )
2555 face->charmaps[j - 1] = last_charmap;
2556 else
2557 face->charmaps[j - 1] = face->charmaps[j];
2558 }
2559
2560 face->num_charmaps--;
2561
2562 if ( (FT_CMap)face->charmap == cmap )
2563 face->charmap = NULL;
2564
2565 ft_cmap_done_internal( cmap );
2566
2567 break;
2568 }
2569 }
David Turner4e7eeee2002-02-28 16:10:29 +00002570 }
2571 }
2572
2573
2574 FT_BASE_DEF( FT_Error )
2575 FT_CMap_New( FT_CMap_Class clazz,
David Turnerbc82f1b2002-03-01 02:26:22 +00002576 FT_Pointer init_data,
David Turner4e7eeee2002-02-28 16:10:29 +00002577 FT_CharMap charmap,
2578 FT_CMap *acmap )
David Turnerbc82f1b2002-03-01 02:26:22 +00002579 {
Werner Lemberg8acb8672005-03-08 11:43:36 +00002580 FT_Error error = FT_Err_Ok;
David Turner4e7eeee2002-02-28 16:10:29 +00002581 FT_Face face;
2582 FT_Memory memory;
2583 FT_CMap cmap;
David Turnerbc82f1b2002-03-01 02:26:22 +00002584
Werner Lembergf8ba2002002-03-30 13:16:35 +00002585
David Turner4e7eeee2002-02-28 16:10:29 +00002586 if ( clazz == NULL || charmap == NULL || charmap->face == NULL )
2587 return FT_Err_Invalid_Argument;
2588
2589 face = charmap->face;
Werner Lembergf35ff802003-06-02 21:58:05 +00002590 memory = FT_FACE_MEMORY( face );
David Turner4e7eeee2002-02-28 16:10:29 +00002591
David Turnere459d742002-03-22 13:52:37 +00002592 if ( !FT_ALLOC( cmap, clazz->size ) )
David Turner4e7eeee2002-02-28 16:10:29 +00002593 {
2594 cmap->charmap = *charmap;
2595 cmap->clazz = clazz;
David Turnerbc82f1b2002-03-01 02:26:22 +00002596
David Turner4e7eeee2002-02-28 16:10:29 +00002597 if ( clazz->init )
2598 {
David Turnerbc82f1b2002-03-01 02:26:22 +00002599 error = clazz->init( cmap, init_data );
Werner Lembergf8ba2002002-03-30 13:16:35 +00002600 if ( error )
David Turner4e7eeee2002-02-28 16:10:29 +00002601 goto Fail;
2602 }
David Turnerbc82f1b2002-03-01 02:26:22 +00002603
David Turner4e7eeee2002-02-28 16:10:29 +00002604 /* add it to our list of charmaps */
David Turnere459d742002-03-22 13:52:37 +00002605 if ( FT_RENEW_ARRAY( face->charmaps,
2606 face->num_charmaps,
Werner Lemberg8acb8672005-03-08 11:43:36 +00002607 face->num_charmaps + 1 ) )
David Turner4e7eeee2002-02-28 16:10:29 +00002608 goto Fail;
David Turnerbc82f1b2002-03-01 02:26:22 +00002609
Werner Lembergf8ba2002002-03-30 13:16:35 +00002610 face->charmaps[face->num_charmaps++] = (FT_CharMap)cmap;
David Turner4e7eeee2002-02-28 16:10:29 +00002611 }
David Turnerbc82f1b2002-03-01 02:26:22 +00002612
David Turner4e7eeee2002-02-28 16:10:29 +00002613 Exit:
2614 if ( acmap )
2615 *acmap = cmap;
2616
2617 return error;
David Turnerbc82f1b2002-03-01 02:26:22 +00002618
David Turner4e7eeee2002-02-28 16:10:29 +00002619 Fail:
Werner Lemberge70371c2005-05-27 06:01:28 +00002620 ft_cmap_done_internal( cmap );
David Turner4e7eeee2002-02-28 16:10:29 +00002621 cmap = NULL;
2622 goto Exit;
David Turnerbc82f1b2002-03-01 02:26:22 +00002623 }
David Turner4e7eeee2002-02-28 16:10:29 +00002624
2625
Werner Lemberg90a03302000-11-07 17:21:11 +00002626 /* documentation is in freetype.h */
2627
Werner Lembergf814d0f2001-06-27 16:18:10 +00002628 FT_EXPORT_DEF( FT_UInt )
2629 FT_Get_Char_Index( FT_Face face,
2630 FT_ULong charcode )
David Turnerd2b1f351999-12-16 23:11:37 +00002631 {
David Turnered54f282002-03-22 17:09:52 +00002632 FT_UInt result = 0;
2633
2634
2635 if ( face && face->charmap )
2636 {
2637 FT_CMap cmap = FT_CMAP( face->charmap );
David Turner25a6e3a2002-06-10 23:03:35 +00002638
Werner Lembergf8ba2002002-03-30 13:16:35 +00002639
David Turnered54f282002-03-22 17:09:52 +00002640 result = cmap->clazz->char_index( cmap, charcode );
2641 }
2642 return result;
2643 }
2644
David Turnered54f282002-03-22 17:09:52 +00002645
Werner Lemberg0f7c2f12002-02-04 20:55:58 +00002646 /* documentation is in freetype.h */
2647
2648 FT_EXPORT_DEF( FT_ULong )
David Turner041889e2002-02-28 19:28:26 +00002649 FT_Get_First_Char( FT_Face face,
2650 FT_UInt *agindex )
Werner Lemberg0f7c2f12002-02-04 20:55:58 +00002651 {
Werner Lembergf8ba2002002-03-30 13:16:35 +00002652 FT_ULong result = 0;
2653 FT_UInt gindex = 0;
2654
David Turnerbc82f1b2002-03-01 02:26:22 +00002655
David Turner041889e2002-02-28 19:28:26 +00002656 if ( face && face->charmap )
2657 {
2658 gindex = FT_Get_Char_Index( face, 0 );
2659 if ( gindex == 0 )
2660 result = FT_Get_Next_Char( face, 0, &gindex );
2661 }
David Turnerbc82f1b2002-03-01 02:26:22 +00002662
David Turner041889e2002-02-28 19:28:26 +00002663 if ( agindex )
2664 *agindex = gindex;
David Turnerbc82f1b2002-03-01 02:26:22 +00002665
David Turner041889e2002-02-28 19:28:26 +00002666 return result;
2667 }
2668
David Turner041889e2002-02-28 19:28:26 +00002669
Werner Lemberg7b0cc662003-07-05 07:46:49 +00002670 /* documentation is in freetype.h */
David Turnered54f282002-03-22 17:09:52 +00002671
David Turnered54f282002-03-22 17:09:52 +00002672 FT_EXPORT_DEF( FT_ULong )
2673 FT_Get_Next_Char( FT_Face face,
2674 FT_ULong charcode,
2675 FT_UInt *agindex )
2676 {
Werner Lembergf8ba2002002-03-30 13:16:35 +00002677 FT_ULong result = 0;
2678 FT_UInt gindex = 0;
David Turnered54f282002-03-22 17:09:52 +00002679
2680
2681 if ( face && face->charmap )
2682 {
2683 FT_UInt32 code = (FT_UInt32)charcode;
2684 FT_CMap cmap = FT_CMAP( face->charmap );
2685
Werner Lembergf8ba2002002-03-30 13:16:35 +00002686
David Turnered54f282002-03-22 17:09:52 +00002687 gindex = cmap->clazz->char_next( cmap, &code );
2688 result = ( gindex == 0 ) ? 0 : code;
2689 }
2690
2691 if ( agindex )
2692 *agindex = gindex;
2693
2694 return result;
2695 }
2696
David Turnered54f282002-03-22 17:09:52 +00002697
Werner Lemberg90a03302000-11-07 17:21:11 +00002698 /* documentation is in freetype.h */
2699
Tom Kacvinskyff2714f2001-08-08 10:58:08 +00002700 FT_EXPORT_DEF( FT_UInt )
2701 FT_Get_Name_Index( FT_Face face,
2702 FT_String* glyph_name )
2703 {
2704 FT_UInt result = 0;
2705
2706
2707 if ( face && FT_HAS_GLYPH_NAMES( face ) )
2708 {
David Turnerc313c502003-09-11 19:51:54 +00002709 FT_Service_GlyphDict service;
Tom Kacvinskyff2714f2001-08-08 10:58:08 +00002710
Werner Lemberg013efd12003-09-17 05:26:33 +00002711
Werner Lemberg46333a12003-09-17 19:20:02 +00002712 FT_FACE_LOOKUP_SERVICE( face,
David Turnere2d12842003-09-21 17:15:55 +00002713 service,
2714 GLYPH_DICT );
Werner Lemberg013efd12003-09-17 05:26:33 +00002715
David Turnerc313c502003-09-11 19:51:54 +00002716 if ( service && service->name_index )
2717 result = service->name_index( face, glyph_name );
Werner Lemberg013efd12003-09-17 05:26:33 +00002718 }
2719
Tom Kacvinskyff2714f2001-08-08 10:58:08 +00002720 return result;
2721 }
2722
Werner Lembergaef3fc82001-12-17 16:21:22 +00002723
Tom Kacvinskyff2714f2001-08-08 10:58:08 +00002724 /* documentation is in freetype.h */
2725
Werner Lembergf814d0f2001-06-27 16:18:10 +00002726 FT_EXPORT_DEF( FT_Error )
2727 FT_Get_Glyph_Name( FT_Face face,
2728 FT_UInt glyph_index,
2729 FT_Pointer buffer,
2730 FT_UInt buffer_max )
David Turner6930b452000-07-19 17:13:03 +00002731 {
2732 FT_Error error = FT_Err_Invalid_Argument;
Werner Lembergeddd9902000-10-12 05:05:40 +00002733
Werner Lembergd060a752000-07-20 06:57:41 +00002734
David Turner6930b452000-07-19 17:13:03 +00002735 /* clean up buffer */
Werner Lembergd060a752000-07-20 06:57:41 +00002736 if ( buffer && buffer_max > 0 )
David Turner6930b452000-07-19 17:13:03 +00002737 ((FT_Byte*)buffer)[0] = 0;
Werner Lembergeddd9902000-10-12 05:05:40 +00002738
Werner Lembergfd97d132002-06-16 01:14:16 +00002739 if ( face &&
2740 glyph_index <= (FT_UInt)face->num_glyphs &&
2741 FT_HAS_GLYPH_NAMES( face ) )
David Turner6930b452000-07-19 17:13:03 +00002742 {
David Turnerc313c502003-09-11 19:51:54 +00002743 FT_Service_GlyphDict service;
David Turner6930b452000-07-19 17:13:03 +00002744
Werner Lemberg013efd12003-09-17 05:26:33 +00002745
Werner Lemberg46333a12003-09-17 19:20:02 +00002746 FT_FACE_LOOKUP_SERVICE( face,
David Turnere2d12842003-09-21 17:15:55 +00002747 service,
2748 GLYPH_DICT );
Werner Lembergd060a752000-07-20 06:57:41 +00002749
David Turnerc313c502003-09-11 19:51:54 +00002750 if ( service && service->get_name )
David Turnerc313c502003-09-11 19:51:54 +00002751 error = service->get_name( face, glyph_index, buffer, buffer_max );
David Turner6930b452000-07-19 17:13:03 +00002752 }
Werner Lembergd060a752000-07-20 06:57:41 +00002753
David Turner6930b452000-07-19 17:13:03 +00002754 return error;
Werner Lembergeddd9902000-10-12 05:05:40 +00002755 }
David Turner6930b452000-07-19 17:13:03 +00002756
2757
David Turner23bcde12001-10-17 13:48:10 +00002758 /* documentation is in freetype.h */
2759
2760 FT_EXPORT_DEF( const char* )
2761 FT_Get_Postscript_Name( FT_Face face )
2762 {
2763 const char* result = NULL;
Werner Lemberg1a0a9792002-01-03 22:06:13 +00002764
Werner Lembergc3b21602001-12-05 01:22:05 +00002765
David Turner23bcde12001-10-17 13:48:10 +00002766 if ( !face )
2767 goto Exit;
2768
David Turner23bcde12001-10-17 13:48:10 +00002769 if ( !result )
2770 {
David Turnerb72d8a82003-09-29 20:33:37 +00002771 FT_Service_PsFontName service;
Werner Lembergc3b21602001-12-05 01:22:05 +00002772
Werner Lemberg013efd12003-09-17 05:26:33 +00002773
Werner Lemberg46333a12003-09-17 19:20:02 +00002774 FT_FACE_LOOKUP_SERVICE( face,
David Turnere2d12842003-09-21 17:15:55 +00002775 service,
David Turnerb72d8a82003-09-29 20:33:37 +00002776 POSTSCRIPT_FONT_NAME );
David Turner23bcde12001-10-17 13:48:10 +00002777
David Turnerb72d8a82003-09-29 20:33:37 +00002778 if ( service && service->get_ps_font_name )
2779 result = service->get_ps_font_name( face );
David Turner23bcde12001-10-17 13:48:10 +00002780 }
Werner Lemberg013efd12003-09-17 05:26:33 +00002781
David Turner23bcde12001-10-17 13:48:10 +00002782 Exit:
2783 return result;
2784 }
2785
2786
Werner Lemberg90a03302000-11-07 17:21:11 +00002787 /* documentation is in tttables.h */
2788
Werner Lembergf814d0f2001-06-27 16:18:10 +00002789 FT_EXPORT_DEF( void* )
2790 FT_Get_Sfnt_Table( FT_Face face,
2791 FT_Sfnt_Tag tag )
David Turner99a4d932000-04-25 16:10:50 +00002792 {
Werner Lemberg40bb0962003-11-01 14:36:20 +00002793 void* table = 0;
2794 FT_Service_SFNT_Table service;
David Turnere49ab252000-05-16 23:44:38 +00002795
Werner Lemberg013efd12003-09-17 05:26:33 +00002796
David Turnerc313c502003-09-11 19:51:54 +00002797 if ( face && FT_IS_SFNT( face ) )
2798 {
David Turnerb72d8a82003-09-29 20:33:37 +00002799 FT_FACE_FIND_SERVICE( face, service, SFNT_TABLE );
David Turnerc313c502003-09-11 19:51:54 +00002800 if ( service != NULL )
2801 table = service->get_table( face, tag );
2802 }
David Turnere2d12842003-09-21 17:15:55 +00002803
David Turner99a4d932000-04-25 16:10:50 +00002804 return table;
David Turnere49ab252000-05-16 23:44:38 +00002805 }
David Turner99a4d932000-04-25 16:10:50 +00002806
2807
David Turner621e4882002-12-16 21:51:24 +00002808 /* documentation is in tttables.h */
2809
2810 FT_EXPORT_DEF( FT_Error )
Werner Lembergc8c6bf52003-04-23 05:38:13 +00002811 FT_Load_Sfnt_Table( FT_Face face,
2812 FT_ULong tag,
2813 FT_Long offset,
2814 FT_Byte* buffer,
2815 FT_ULong* length )
David Turner621e4882002-12-16 21:51:24 +00002816 {
David Turnerc313c502003-09-11 19:51:54 +00002817 FT_Service_SFNT_Table service;
David Turner621e4882002-12-16 21:51:24 +00002818
2819
2820 if ( !face || !FT_IS_SFNT( face ) )
2821 return FT_Err_Invalid_Face_Handle;
2822
David Turnerb72d8a82003-09-29 20:33:37 +00002823 FT_FACE_FIND_SERVICE( face, service, SFNT_TABLE );
David Turnerc313c502003-09-11 19:51:54 +00002824 if ( service == NULL )
David Turner621e4882002-12-16 21:51:24 +00002825 return FT_Err_Unimplemented_Feature;
David Turnere2d12842003-09-21 17:15:55 +00002826
David Turnerc313c502003-09-11 19:51:54 +00002827 return service->load_table( face, tag, offset, buffer, length );
David Turner621e4882002-12-16 21:51:24 +00002828 }
2829
2830
Werner Lemberg17439422004-08-11 05:25:37 +00002831 /* documentation is in tttables.h */
2832
2833 FT_EXPORT_DEF( FT_Error )
2834 FT_Sfnt_Table_Info( FT_Face face,
2835 FT_UInt table_index,
2836 FT_ULong *tag,
2837 FT_ULong *length )
2838 {
2839 FT_Service_SFNT_Table service;
2840
2841
2842 if ( !face || !FT_IS_SFNT( face ) )
2843 return FT_Err_Invalid_Face_Handle;
2844
2845 FT_FACE_FIND_SERVICE( face, service, SFNT_TABLE );
2846 if ( service == NULL )
2847 return FT_Err_Unimplemented_Feature;
2848
2849 return service->table_info( face, table_index, tag, length );
2850 }
2851
2852
Werner Lembergece8b202004-12-13 23:16:59 +00002853 /* documentation is in tttables.h */
2854
Werner Lemberg91a67472003-12-17 14:28:22 +00002855 FT_EXPORT_DEF( FT_ULong )
2856 FT_Get_CMap_Language_ID( FT_CharMap charmap )
2857 {
2858 FT_Service_TTCMaps service;
2859 FT_Face face;
2860 TT_CMapInfo cmap_info;
2861
David Turner87c0d302003-12-24 01:10:46 +00002862
Werner Lemberg91a67472003-12-17 14:28:22 +00002863 if ( !charmap || !charmap->face )
2864 return 0;
2865
2866 face = charmap->face;
2867 FT_FACE_FIND_SERVICE( face, service, TT_CMAP );
2868 if ( service == NULL )
2869 return 0;
2870 if ( service->get_cmap_info( charmap, &cmap_info ))
2871 return 0;
2872
2873 return cmap_info.language;
2874 }
2875
2876
Werner Lembergece8b202004-12-13 23:16:59 +00002877 /* documentation is in ftsizes.h */
2878
David Turnerb3ba40d2001-10-07 13:30:26 +00002879 FT_EXPORT_DEF( FT_Error )
Werner Lemberg80b8d772001-10-10 19:56:42 +00002880 FT_Activate_Size( FT_Size size )
David Turnerb3ba40d2001-10-07 13:30:26 +00002881 {
2882 FT_Face face;
Werner Lemberg1a0a9792002-01-03 22:06:13 +00002883
Werner Lemberg80b8d772001-10-10 19:56:42 +00002884
David Turnerb3ba40d2001-10-07 13:30:26 +00002885 if ( size == NULL )
2886 return FT_Err_Bad_Argument;
Werner Lemberg1a0a9792002-01-03 22:06:13 +00002887
David Turnerb3ba40d2001-10-07 13:30:26 +00002888 face = size->face;
2889 if ( face == NULL || face->driver == NULL )
2890 return FT_Err_Bad_Argument;
Werner Lemberg1a0a9792002-01-03 22:06:13 +00002891
Werner Lemberg80b8d772001-10-10 19:56:42 +00002892 /* we don't need anything more complex than that; all size objects */
2893 /* are already listed by the face */
David Turnerb3ba40d2001-10-07 13:30:26 +00002894 face->size = size;
Werner Lemberg1a0a9792002-01-03 22:06:13 +00002895
David Turnerb3ba40d2001-10-07 13:30:26 +00002896 return FT_Err_Ok;
2897 }
2898
2899
David Turnerd2b1f351999-12-16 23:11:37 +00002900 /*************************************************************************/
David Turnerf0df85b2000-06-22 00:17:42 +00002901 /*************************************************************************/
2902 /*************************************************************************/
2903 /**** ****/
2904 /**** ****/
2905 /**** R E N D E R E R S ****/
2906 /**** ****/
2907 /**** ****/
2908 /*************************************************************************/
2909 /*************************************************************************/
2910 /*************************************************************************/
2911
Werner Lembergdeb4e982000-06-29 03:14:25 +00002912 /* lookup a renderer by glyph format in the library's list */
Werner Lembergf814d0f2001-06-27 16:18:10 +00002913 FT_BASE_DEF( FT_Renderer )
2914 FT_Lookup_Renderer( FT_Library library,
2915 FT_Glyph_Format format,
2916 FT_ListNode* node )
David Turnerf0df85b2000-06-22 00:17:42 +00002917 {
Werner Lembergf8ba2002002-03-30 13:16:35 +00002918 FT_ListNode cur;
2919 FT_Renderer result = 0;
Werner Lemberga929ba92000-06-25 06:47:11 +00002920
Werner Lembergdeb4e982000-06-29 03:14:25 +00002921
2922 if ( !library )
2923 goto Exit;
2924
2925 cur = library->renderers.head;
2926
2927 if ( node )
David Turner74abee82000-06-27 23:31:53 +00002928 {
Werner Lembergdeb4e982000-06-29 03:14:25 +00002929 if ( *node )
David Turner74abee82000-06-27 23:31:53 +00002930 cur = (*node)->next;
David Turnerf0df85b2000-06-22 00:17:42 +00002931 *node = 0;
David Turner74abee82000-06-27 23:31:53 +00002932 }
Werner Lembergdeb4e982000-06-29 03:14:25 +00002933
Werner Lemberga929ba92000-06-25 06:47:11 +00002934 while ( cur )
David Turnerf0df85b2000-06-22 00:17:42 +00002935 {
Werner Lemberga929ba92000-06-25 06:47:11 +00002936 FT_Renderer renderer = FT_RENDERER( cur->data );
Werner Lembergdeb4e982000-06-29 03:14:25 +00002937
Werner Lemberga929ba92000-06-25 06:47:11 +00002938
2939 if ( renderer->glyph_format == format )
David Turnerf0df85b2000-06-22 00:17:42 +00002940 {
Werner Lemberga929ba92000-06-25 06:47:11 +00002941 if ( node )
David Turnerf0df85b2000-06-22 00:17:42 +00002942 *node = cur;
Werner Lembergdeb4e982000-06-29 03:14:25 +00002943
David Turnerf0df85b2000-06-22 00:17:42 +00002944 result = renderer;
2945 break;
2946 }
David Turner74abee82000-06-27 23:31:53 +00002947 cur = cur->next;
David Turnerf0df85b2000-06-22 00:17:42 +00002948 }
Werner Lemberga929ba92000-06-25 06:47:11 +00002949
Werner Lembergdeb4e982000-06-29 03:14:25 +00002950 Exit:
David Turnerf0df85b2000-06-22 00:17:42 +00002951 return result;
2952 }
2953
Werner Lemberga929ba92000-06-25 06:47:11 +00002954
Werner Lembergf814d0f2001-06-27 16:18:10 +00002955 static FT_Renderer
2956 ft_lookup_glyph_renderer( FT_GlyphSlot slot )
Werner Lembergdeb4e982000-06-29 03:14:25 +00002957 {
2958 FT_Face face = slot->face;
2959 FT_Library library = FT_FACE_LIBRARY( face );
2960 FT_Renderer result = library->cur_renderer;
2961
2962
Werner Lemberga929ba92000-06-25 06:47:11 +00002963 if ( !result || result->glyph_format != slot->format )
David Turner81bb4ad2000-06-28 04:19:49 +00002964 result = FT_Lookup_Renderer( library, slot->format, 0 );
Werner Lembergfbeb41d2000-07-02 00:27:53 +00002965
David Turnerf0df85b2000-06-22 00:17:42 +00002966 return result;
2967 }
2968
Werner Lembergdeb4e982000-06-29 03:14:25 +00002969
Werner Lembergf814d0f2001-06-27 16:18:10 +00002970 static void
2971 ft_set_current_renderer( FT_Library library )
David Turnerf0df85b2000-06-22 00:17:42 +00002972 {
2973 FT_Renderer renderer;
2974
Werner Lembergdeb4e982000-06-29 03:14:25 +00002975
David Turnerb08fe2d2002-08-27 20:20:29 +00002976 renderer = FT_Lookup_Renderer( library, FT_GLYPH_FORMAT_OUTLINE, 0 );
David Turnerf0df85b2000-06-22 00:17:42 +00002977 library->cur_renderer = renderer;
2978 }
2979
2980
Werner Lembergf814d0f2001-06-27 16:18:10 +00002981 static FT_Error
2982 ft_add_renderer( FT_Module module )
David Turnerf0df85b2000-06-22 00:17:42 +00002983 {
2984 FT_Library library = module->library;
2985 FT_Memory memory = library->memory;
2986 FT_Error error;
2987 FT_ListNode node;
Werner Lembergdeb4e982000-06-29 03:14:25 +00002988
2989
David Turnere459d742002-03-22 13:52:37 +00002990 if ( FT_NEW( node ) )
David Turnerf0df85b2000-06-22 00:17:42 +00002991 goto Exit;
Werner Lembergdeb4e982000-06-29 03:14:25 +00002992
David Turnerf0df85b2000-06-22 00:17:42 +00002993 {
Werner Lemberga929ba92000-06-25 06:47:11 +00002994 FT_Renderer render = FT_RENDERER( module );
David Turnerf0df85b2000-06-22 00:17:42 +00002995 FT_Renderer_Class* clazz = (FT_Renderer_Class*)module->clazz;
2996
Werner Lemberga929ba92000-06-25 06:47:11 +00002997
David Turnerf0df85b2000-06-22 00:17:42 +00002998 render->clazz = clazz;
2999 render->glyph_format = clazz->glyph_format;
Werner Lembergdeb4e982000-06-29 03:14:25 +00003000
David Turnerf0df85b2000-06-22 00:17:42 +00003001 /* allocate raster object if needed */
David Turnerb08fe2d2002-08-27 20:20:29 +00003002 if ( clazz->glyph_format == FT_GLYPH_FORMAT_OUTLINE &&
David Turnerf0df85b2000-06-22 00:17:42 +00003003 clazz->raster_class->raster_new )
3004 {
3005 error = clazz->raster_class->raster_new( memory, &render->raster );
Werner Lemberga929ba92000-06-25 06:47:11 +00003006 if ( error )
3007 goto Fail;
Werner Lembergdeb4e982000-06-29 03:14:25 +00003008
David Turnerf0df85b2000-06-22 00:17:42 +00003009 render->raster_render = clazz->raster_class->raster_render;
3010 render->render = clazz->render_glyph;
Werner Lembergdeb4e982000-06-29 03:14:25 +00003011 }
3012
David Turnerf0df85b2000-06-22 00:17:42 +00003013 /* add to list */
3014 node->data = module;
3015 FT_List_Add( &library->renderers, node );
3016
3017 ft_set_current_renderer( library );
3018 }
3019
3020 Fail:
Werner Lemberga929ba92000-06-25 06:47:11 +00003021 if ( error )
David Turnere459d742002-03-22 13:52:37 +00003022 FT_FREE( node );
David Turnerf0df85b2000-06-22 00:17:42 +00003023
3024 Exit:
3025 return error;
Werner Lembergdeb4e982000-06-29 03:14:25 +00003026 }
David Turnerf0df85b2000-06-22 00:17:42 +00003027
3028
Werner Lembergf814d0f2001-06-27 16:18:10 +00003029 static void
3030 ft_remove_renderer( FT_Module module )
David Turnerf0df85b2000-06-22 00:17:42 +00003031 {
3032 FT_Library library = module->library;
3033 FT_Memory memory = library->memory;
3034 FT_ListNode node;
3035
Werner Lemberga929ba92000-06-25 06:47:11 +00003036
David Turnerf0df85b2000-06-22 00:17:42 +00003037 node = FT_List_Find( &library->renderers, module );
Werner Lemberga929ba92000-06-25 06:47:11 +00003038 if ( node )
David Turnerf0df85b2000-06-22 00:17:42 +00003039 {
Werner Lemberga929ba92000-06-25 06:47:11 +00003040 FT_Renderer render = FT_RENDERER( module );
Werner Lembergdeb4e982000-06-29 03:14:25 +00003041
Werner Lemberga929ba92000-06-25 06:47:11 +00003042
David Turnerf0df85b2000-06-22 00:17:42 +00003043 /* release raster object, if any */
Werner Lemberga929ba92000-06-25 06:47:11 +00003044 if ( render->raster )
David Turnerf0df85b2000-06-22 00:17:42 +00003045 render->clazz->raster_class->raster_done( render->raster );
Werner Lembergdeb4e982000-06-29 03:14:25 +00003046
David Turnerf0df85b2000-06-22 00:17:42 +00003047 /* remove from list */
3048 FT_List_Remove( &library->renderers, node );
David Turnere459d742002-03-22 13:52:37 +00003049 FT_FREE( node );
Werner Lembergdeb4e982000-06-29 03:14:25 +00003050
David Turnerf0df85b2000-06-22 00:17:42 +00003051 ft_set_current_renderer( library );
3052 }
3053 }
3054
3055
Werner Lemberg90a03302000-11-07 17:21:11 +00003056 /* documentation is in ftrender.h */
3057
Werner Lembergf814d0f2001-06-27 16:18:10 +00003058 FT_EXPORT_DEF( FT_Renderer )
3059 FT_Get_Renderer( FT_Library library,
3060 FT_Glyph_Format format )
David Turnerf0df85b2000-06-22 00:17:42 +00003061 {
Werner Lembergdeb4e982000-06-29 03:14:25 +00003062 /* test for valid `library' delayed to FT_Lookup_Renderer() */
3063
Werner Lembergf8ba2002002-03-30 13:16:35 +00003064 return FT_Lookup_Renderer( library, format, 0 );
Werner Lembergdeb4e982000-06-29 03:14:25 +00003065 }
David Turnerf0df85b2000-06-22 00:17:42 +00003066
3067
Werner Lemberg90a03302000-11-07 17:21:11 +00003068 /* documentation is in ftrender.h */
3069
Werner Lembergf814d0f2001-06-27 16:18:10 +00003070 FT_EXPORT_DEF( FT_Error )
3071 FT_Set_Renderer( FT_Library library,
3072 FT_Renderer renderer,
3073 FT_UInt num_params,
3074 FT_Parameter* parameters )
David Turnerf0df85b2000-06-22 00:17:42 +00003075 {
3076 FT_ListNode node;
3077 FT_Error error = FT_Err_Ok;
Werner Lembergdeb4e982000-06-29 03:14:25 +00003078
3079
3080 if ( !library )
3081 return FT_Err_Invalid_Library_Handle;
3082
3083 if ( !renderer )
3084 return FT_Err_Invalid_Argument;
Werner Lemberga929ba92000-06-25 06:47:11 +00003085
David Turnerf0df85b2000-06-22 00:17:42 +00003086 node = FT_List_Find( &library->renderers, renderer );
Werner Lemberga929ba92000-06-25 06:47:11 +00003087 if ( !node )
David Turnerf0df85b2000-06-22 00:17:42 +00003088 {
3089 error = FT_Err_Invalid_Argument;
3090 goto Exit;
3091 }
David Turner74abee82000-06-27 23:31:53 +00003092
David Turnerf0df85b2000-06-22 00:17:42 +00003093 FT_List_Up( &library->renderers, node );
Werner Lembergdeb4e982000-06-29 03:14:25 +00003094
David Turnerb08fe2d2002-08-27 20:20:29 +00003095 if ( renderer->glyph_format == FT_GLYPH_FORMAT_OUTLINE )
David Turnerf0df85b2000-06-22 00:17:42 +00003096 library->cur_renderer = renderer;
Werner Lembergdeb4e982000-06-29 03:14:25 +00003097
Werner Lemberga929ba92000-06-25 06:47:11 +00003098 if ( num_params > 0 )
David Turnerf0df85b2000-06-22 00:17:42 +00003099 {
David Turnerb08fe2d2002-08-27 20:20:29 +00003100 FT_Renderer_SetModeFunc set_mode = renderer->clazz->set_mode;
Werner Lembergdeb4e982000-06-29 03:14:25 +00003101
Werner Lemberga929ba92000-06-25 06:47:11 +00003102
David Turnerf0df85b2000-06-22 00:17:42 +00003103 for ( ; num_params > 0; num_params-- )
3104 {
3105 error = set_mode( renderer, parameters->tag, parameters->data );
Werner Lemberga929ba92000-06-25 06:47:11 +00003106 if ( error )
David Turnerf0df85b2000-06-22 00:17:42 +00003107 break;
3108 }
3109 }
Werner Lembergdeb4e982000-06-29 03:14:25 +00003110
David Turnerf0df85b2000-06-22 00:17:42 +00003111 Exit:
3112 return error;
Werner Lembergdeb4e982000-06-29 03:14:25 +00003113 }
David Turnerf0df85b2000-06-22 00:17:42 +00003114
3115
David Turner7504e482002-06-07 07:24:55 +00003116 FT_BASE_DEF( FT_Error )
Werner Lemberg68e9f922002-09-27 11:09:23 +00003117 FT_Render_Glyph_Internal( FT_Library library,
3118 FT_GlyphSlot slot,
3119 FT_Render_Mode render_mode )
David Turnerf0df85b2000-06-22 00:17:42 +00003120 {
3121 FT_Error error = FT_Err_Ok;
3122 FT_Renderer renderer;
Werner Lemberga929ba92000-06-25 06:47:11 +00003123
Werner Lembergdeb4e982000-06-29 03:14:25 +00003124
3125 /* if it is already a bitmap, no need to do anything */
3126 switch ( slot->format )
David Turnerf0df85b2000-06-22 00:17:42 +00003127 {
David Turnerb08fe2d2002-08-27 20:20:29 +00003128 case FT_GLYPH_FORMAT_BITMAP: /* already a bitmap, don't do anything */
Werner Lembergdeb4e982000-06-29 03:14:25 +00003129 break;
3130
3131 default:
David Turner74abee82000-06-27 23:31:53 +00003132 {
3133 FT_ListNode node = 0;
3134 FT_Bool update = 0;
Werner Lembergdeb4e982000-06-29 03:14:25 +00003135
3136
Werner Lemberga929ba92000-06-25 06:47:11 +00003137 /* small shortcut for the very common case */
David Turnerb08fe2d2002-08-27 20:20:29 +00003138 if ( slot->format == FT_GLYPH_FORMAT_OUTLINE )
David Turner74abee82000-06-27 23:31:53 +00003139 {
Werner Lemberga929ba92000-06-25 06:47:11 +00003140 renderer = library->cur_renderer;
David Turner74abee82000-06-27 23:31:53 +00003141 node = library->renderers.head;
3142 }
Werner Lemberga929ba92000-06-25 06:47:11 +00003143 else
David Turner74abee82000-06-27 23:31:53 +00003144 renderer = FT_Lookup_Renderer( library, slot->format, &node );
3145
Werner Lemberga929ba92000-06-25 06:47:11 +00003146 error = FT_Err_Unimplemented_Feature;
Werner Lembergdeb4e982000-06-29 03:14:25 +00003147 while ( renderer )
David Turner74abee82000-06-27 23:31:53 +00003148 {
David Turnerc8ad30a2001-12-05 17:24:34 +00003149 error = renderer->render( renderer, slot, render_mode, NULL );
Werner Lemberg79860702001-06-08 21:17:29 +00003150 if ( !error ||
3151 FT_ERROR_BASE( error ) != FT_Err_Cannot_Render_Glyph )
Werner Lembergdeb4e982000-06-29 03:14:25 +00003152 break;
David Turner74abee82000-06-27 23:31:53 +00003153
Werner Lembergdeb4e982000-06-29 03:14:25 +00003154 /* FT_Err_Cannot_Render_Glyph is returned if the render mode */
David Turner74abee82000-06-27 23:31:53 +00003155 /* is unsupported by the current renderer for this glyph image */
Werner Lembergdeb4e982000-06-29 03:14:25 +00003156 /* format. */
3157
3158 /* now, look for another renderer that supports the same */
3159 /* format. */
David Turner74abee82000-06-27 23:31:53 +00003160 renderer = FT_Lookup_Renderer( library, slot->format, &node );
3161 update = 1;
3162 }
3163
3164 /* if we changed the current renderer for the glyph image format */
Werner Lembergdeb4e982000-06-29 03:14:25 +00003165 /* we need to select it as the next current one */
3166 if ( !error && update && renderer )
David Turner74abee82000-06-27 23:31:53 +00003167 FT_Set_Renderer( library, renderer, 0, 0 );
David Turnerf0df85b2000-06-22 00:17:42 +00003168 }
3169 }
Werner Lembergdeb4e982000-06-29 03:14:25 +00003170
David Turnerf0df85b2000-06-22 00:17:42 +00003171 return error;
3172 }
Werner Lemberga929ba92000-06-25 06:47:11 +00003173
David Turner74abee82000-06-27 23:31:53 +00003174
Werner Lemberg90a03302000-11-07 17:21:11 +00003175 /* documentation is in freetype.h */
3176
Werner Lembergf814d0f2001-06-27 16:18:10 +00003177 FT_EXPORT_DEF( FT_Error )
Werner Lemberg68e9f922002-09-27 11:09:23 +00003178 FT_Render_Glyph( FT_GlyphSlot slot,
3179 FT_Render_Mode render_mode )
David Turner74abee82000-06-27 23:31:53 +00003180 {
Werner Lembergf8ba2002002-03-30 13:16:35 +00003181 FT_Library library;
Werner Lembergdeb4e982000-06-29 03:14:25 +00003182
3183
3184 if ( !slot )
David Turner74abee82000-06-27 23:31:53 +00003185 return FT_Err_Invalid_Argument;
Werner Lembergdeb4e982000-06-29 03:14:25 +00003186
3187 library = FT_FACE_LIBRARY( slot->face );
3188
David Turner74abee82000-06-27 23:31:53 +00003189 return FT_Render_Glyph_Internal( library, slot, render_mode );
3190 }
3191
Werner Lembergdeb4e982000-06-29 03:14:25 +00003192
David Turnerf0df85b2000-06-22 00:17:42 +00003193 /*************************************************************************/
3194 /*************************************************************************/
3195 /*************************************************************************/
3196 /**** ****/
3197 /**** ****/
3198 /**** M O D U L E S ****/
3199 /**** ****/
3200 /**** ****/
3201 /*************************************************************************/
3202 /*************************************************************************/
3203 /*************************************************************************/
3204
Werner Lemberga929ba92000-06-25 06:47:11 +00003205
David Turnerf0df85b2000-06-22 00:17:42 +00003206 /*************************************************************************/
3207 /* */
3208 /* <Function> */
3209 /* Destroy_Module */
3210 /* */
3211 /* <Description> */
3212 /* Destroys a given module object. For drivers, this also destroys */
Werner Lemberga929ba92000-06-25 06:47:11 +00003213 /* all child faces. */
David Turnerf0df85b2000-06-22 00:17:42 +00003214 /* */
3215 /* <InOut> */
3216 /* module :: A handle to the target driver object. */
3217 /* */
3218 /* <Note> */
3219 /* The driver _must_ be LOCKED! */
3220 /* */
Werner Lembergf814d0f2001-06-27 16:18:10 +00003221 static void
3222 Destroy_Module( FT_Module module )
David Turnerf0df85b2000-06-22 00:17:42 +00003223 {
David Turner5ae831c2000-06-30 01:31:22 +00003224 FT_Memory memory = module->memory;
3225 FT_Module_Class* clazz = module->clazz;
3226 FT_Library library = module->library;
David Turnerf0df85b2000-06-22 00:17:42 +00003227
Werner Lemberga929ba92000-06-25 06:47:11 +00003228
David Turnerf0df85b2000-06-22 00:17:42 +00003229 /* finalize client-data - before anything else */
3230 if ( module->generic.finalizer )
3231 module->generic.finalizer( module );
3232
David Turner5ae831c2000-06-30 01:31:22 +00003233 if ( library && library->auto_hinter == module )
3234 library->auto_hinter = 0;
3235
David Turnerf0df85b2000-06-22 00:17:42 +00003236 /* if the module is a renderer */
Werner Lemberga929ba92000-06-25 06:47:11 +00003237 if ( FT_MODULE_IS_RENDERER( module ) )
3238 ft_remove_renderer( module );
David Turnerf0df85b2000-06-22 00:17:42 +00003239
3240 /* if the module is a font driver, add some steps */
Werner Lemberga929ba92000-06-25 06:47:11 +00003241 if ( FT_MODULE_IS_DRIVER( module ) )
3242 Destroy_Driver( FT_DRIVER( module ) );
David Turnerf0df85b2000-06-22 00:17:42 +00003243
3244 /* finalize the module object */
Werner Lemberga929ba92000-06-25 06:47:11 +00003245 if ( clazz->module_done )
3246 clazz->module_done( module );
David Turnerf0df85b2000-06-22 00:17:42 +00003247
3248 /* discard it */
David Turnere459d742002-03-22 13:52:37 +00003249 FT_FREE( module );
David Turnerf0df85b2000-06-22 00:17:42 +00003250 }
3251
David Turnerf0df85b2000-06-22 00:17:42 +00003252
Werner Lemberg748b1712005-12-25 09:15:09 +00003253 /* documentation is in ftmodapi.h */
Werner Lemberg90a03302000-11-07 17:21:11 +00003254
Werner Lembergf814d0f2001-06-27 16:18:10 +00003255 FT_EXPORT_DEF( FT_Error )
3256 FT_Add_Module( FT_Library library,
3257 const FT_Module_Class* clazz )
David Turnerf0df85b2000-06-22 00:17:42 +00003258 {
3259 FT_Error error;
3260 FT_Memory memory;
3261 FT_Module module;
3262 FT_UInt nn;
3263
David Turnerf0df85b2000-06-22 00:17:42 +00003264
Werner Lembergdeb4e982000-06-29 03:14:25 +00003265#define FREETYPE_VER_FIXED ( ( (FT_Long)FREETYPE_MAJOR << 16 ) | \
3266 FREETYPE_MINOR )
Werner Lemberga929ba92000-06-25 06:47:11 +00003267
Werner Lembergdeb4e982000-06-29 03:14:25 +00003268 if ( !library )
3269 return FT_Err_Invalid_Library_Handle;
3270
3271 if ( !clazz )
David Turnerf0df85b2000-06-22 00:17:42 +00003272 return FT_Err_Invalid_Argument;
3273
3274 /* check freetype version */
3275 if ( clazz->module_requires > FREETYPE_VER_FIXED )
3276 return FT_Err_Invalid_Version;
3277
3278 /* look for a module with the same name in the library's table */
3279 for ( nn = 0; nn < library->num_modules; nn++ )
3280 {
3281 module = library->modules[nn];
David Turnerd15bc0d2002-04-12 09:31:48 +00003282 if ( ft_strcmp( module->clazz->module_name, clazz->module_name ) == 0 )
David Turnerf0df85b2000-06-22 00:17:42 +00003283 {
3284 /* this installed module has the same name, compare their versions */
3285 if ( clazz->module_version <= module->clazz->module_version )
3286 return FT_Err_Lower_Module_Version;
3287
3288 /* remove the module from our list, then exit the loop to replace */
3289 /* it by our new version.. */
3290 FT_Remove_Module( library, module );
3291 break;
3292 }
3293 }
3294
3295 memory = library->memory;
3296 error = FT_Err_Ok;
3297
3298 if ( library->num_modules >= FT_MAX_MODULES )
3299 {
3300 error = FT_Err_Too_Many_Drivers;
3301 goto Exit;
3302 }
3303
3304 /* allocate module object */
Werner Lemberg68e9f922002-09-27 11:09:23 +00003305 if ( FT_ALLOC( module, clazz->module_size ) )
David Turnerf0df85b2000-06-22 00:17:42 +00003306 goto Exit;
3307
Werner Lembergdeb4e982000-06-29 03:14:25 +00003308 /* base initialization */
David Turnerf0df85b2000-06-22 00:17:42 +00003309 module->library = library;
3310 module->memory = memory;
3311 module->clazz = (FT_Module_Class*)clazz;
3312
Werner Lembergdeb4e982000-06-29 03:14:25 +00003313 /* check whether the module is a renderer - this must be performed */
3314 /* before the normal module initialization */
Werner Lemberga929ba92000-06-25 06:47:11 +00003315 if ( FT_MODULE_IS_RENDERER( module ) )
David Turnerf0df85b2000-06-22 00:17:42 +00003316 {
3317 /* add to the renderers list */
Werner Lemberga929ba92000-06-25 06:47:11 +00003318 error = ft_add_renderer( module );
3319 if ( error )
3320 goto Fail;
David Turnerf0df85b2000-06-22 00:17:42 +00003321 }
3322
Werner Lembergcc9fc492000-06-30 06:21:26 +00003323 /* is the module a auto-hinter? */
3324 if ( FT_MODULE_IS_HINTER( module ) )
David Turner5ae831c2000-06-30 01:31:22 +00003325 library->auto_hinter = module;
Werner Lembergfbeb41d2000-07-02 00:27:53 +00003326
David Turnerf0df85b2000-06-22 00:17:42 +00003327 /* if the module is a font driver */
Werner Lemberga929ba92000-06-25 06:47:11 +00003328 if ( FT_MODULE_IS_DRIVER( module ) )
David Turnerf0df85b2000-06-22 00:17:42 +00003329 {
3330 /* allocate glyph loader if needed */
Werner Lembergf8ba2002002-03-30 13:16:35 +00003331 FT_Driver driver = FT_DRIVER( module );
Werner Lemberga929ba92000-06-25 06:47:11 +00003332
Werner Lembergdeb4e982000-06-29 03:14:25 +00003333
David Turneref3c1262002-03-14 09:22:48 +00003334 driver->clazz = (FT_Driver_Class)module->clazz;
Werner Lemberga929ba92000-06-25 06:47:11 +00003335 if ( FT_DRIVER_USES_OUTLINES( driver ) )
David Turnerf0df85b2000-06-22 00:17:42 +00003336 {
3337 error = FT_GlyphLoader_New( memory, &driver->glyph_loader );
Werner Lemberga929ba92000-06-25 06:47:11 +00003338 if ( error )
3339 goto Fail;
David Turnerf0df85b2000-06-22 00:17:42 +00003340 }
3341 }
3342
Werner Lemberga929ba92000-06-25 06:47:11 +00003343 if ( clazz->module_init )
David Turnerf0df85b2000-06-22 00:17:42 +00003344 {
Werner Lemberga929ba92000-06-25 06:47:11 +00003345 error = clazz->module_init( module );
3346 if ( error )
3347 goto Fail;
David Turnerf0df85b2000-06-22 00:17:42 +00003348 }
3349
3350 /* add module to the library's table */
Werner Lemberga929ba92000-06-25 06:47:11 +00003351 library->modules[library->num_modules++] = module;
Werner Lembergdeb4e982000-06-29 03:14:25 +00003352
David Turnerf0df85b2000-06-22 00:17:42 +00003353 Exit:
3354 return error;
Werner Lembergdeb4e982000-06-29 03:14:25 +00003355
David Turnerf0df85b2000-06-22 00:17:42 +00003356 Fail:
Werner Lemberga929ba92000-06-25 06:47:11 +00003357 if ( FT_MODULE_IS_DRIVER( module ) )
David Turnerf0df85b2000-06-22 00:17:42 +00003358 {
Werner Lemberga929ba92000-06-25 06:47:11 +00003359 FT_Driver driver = FT_DRIVER( module );
Werner Lembergdeb4e982000-06-29 03:14:25 +00003360
Werner Lemberga929ba92000-06-25 06:47:11 +00003361
3362 if ( FT_DRIVER_USES_OUTLINES( driver ) )
David Turnerf0df85b2000-06-22 00:17:42 +00003363 FT_GlyphLoader_Done( driver->glyph_loader );
3364 }
Werner Lembergdeb4e982000-06-29 03:14:25 +00003365
Werner Lemberga929ba92000-06-25 06:47:11 +00003366 if ( FT_MODULE_IS_RENDERER( module ) )
David Turnerf0df85b2000-06-22 00:17:42 +00003367 {
Werner Lemberga929ba92000-06-25 06:47:11 +00003368 FT_Renderer renderer = FT_RENDERER( module );
3369
3370
3371 if ( renderer->raster )
David Turnerf0df85b2000-06-22 00:17:42 +00003372 renderer->clazz->raster_class->raster_done( renderer->raster );
3373 }
Werner Lemberga929ba92000-06-25 06:47:11 +00003374
David Turnere459d742002-03-22 13:52:37 +00003375 FT_FREE( module );
David Turnerf0df85b2000-06-22 00:17:42 +00003376 goto Exit;
3377 }
3378
David Turnerf0df85b2000-06-22 00:17:42 +00003379
Werner Lemberg748b1712005-12-25 09:15:09 +00003380 /* documentation is in ftmodapi.h */
Werner Lemberg90a03302000-11-07 17:21:11 +00003381
Werner Lembergf814d0f2001-06-27 16:18:10 +00003382 FT_EXPORT_DEF( FT_Module )
3383 FT_Get_Module( FT_Library library,
3384 const char* module_name )
David Turnerf0df85b2000-06-22 00:17:42 +00003385 {
Werner Lembergdeb4e982000-06-29 03:14:25 +00003386 FT_Module result = 0;
3387 FT_Module* cur;
3388 FT_Module* limit;
David Turnerf0df85b2000-06-22 00:17:42 +00003389
Werner Lemberga929ba92000-06-25 06:47:11 +00003390
Werner Lembergdeb4e982000-06-29 03:14:25 +00003391 if ( !library || !module_name )
3392 return result;
3393
3394 cur = library->modules;
3395 limit = cur + library->num_modules;
3396
David Turnerf0df85b2000-06-22 00:17:42 +00003397 for ( ; cur < limit; cur++ )
David Turnerd15bc0d2002-04-12 09:31:48 +00003398 if ( ft_strcmp( cur[0]->clazz->module_name, module_name ) == 0 )
David Turnerf0df85b2000-06-22 00:17:42 +00003399 {
3400 result = cur[0];
3401 break;
3402 }
3403
3404 return result;
3405 }
3406
Werner Lemberga929ba92000-06-25 06:47:11 +00003407
Werner Lemberg6cdab922006-01-08 22:34:01 +00003408 /* documentation is in ftmodapi.h */
3409
3410 FT_EXPORT_DEF( FT_Error )
3411 FT_Module_Get_Flags( FT_Module module,
3412 FT_ULong* flags )
3413 {
3414 if ( !module )
3415 return FT_Err_Invalid_Driver_Handle;
3416
3417 if ( !flags )
3418 return FT_Err_Invalid_Argument;
3419
3420 *flags = module->clazz->module_flags;
3421 return FT_Err_Ok;
3422 }
3423
3424
Werner Lemberg8ec9dfd2000-11-07 23:56:02 +00003425 /* documentation is in ftobjs.h */
3426
Werner Lembergf814d0f2001-06-27 16:18:10 +00003427 FT_BASE_DEF( const void* )
3428 FT_Get_Module_Interface( FT_Library library,
3429 const char* mod_name )
David Turnerf0df85b2000-06-22 00:17:42 +00003430 {
3431 FT_Module module;
Werner Lembergdeb4e982000-06-29 03:14:25 +00003432
3433
3434 /* test for valid `library' delayed to FT_Get_Module() */
Werner Lemberga929ba92000-06-25 06:47:11 +00003435
David Turnerf0df85b2000-06-22 00:17:42 +00003436 module = FT_Get_Module( library, mod_name );
Werner Lemberga929ba92000-06-25 06:47:11 +00003437
David Turnerf0df85b2000-06-22 00:17:42 +00003438 return module ? module->clazz->module_interface : 0;
Werner Lembergdeb4e982000-06-29 03:14:25 +00003439 }
David Turnerf0df85b2000-06-22 00:17:42 +00003440
3441
David Turnerb72d8a82003-09-29 20:33:37 +00003442 FT_BASE_DEF( FT_Pointer )
3443 ft_module_get_service( FT_Module module,
3444 const char* service_id )
3445 {
3446 FT_Pointer result = NULL;
3447
3448 if ( module )
3449 {
3450 FT_ASSERT( module->clazz && module->clazz->get_interface );
3451
3452 /* first, look for the service in the module
3453 */
3454 if ( module->clazz->get_interface )
3455 result = module->clazz->get_interface( module, service_id );
3456
3457 if ( result == NULL )
3458 {
3459 /* we didn't find it, look in all other modules then
3460 */
3461 FT_Library library = module->library;
3462 FT_Module* cur = library->modules;
3463 FT_Module* limit = cur + library->num_modules;
3464
3465 for ( ; cur < limit; cur++ )
3466 {
3467 if ( cur[0] != module )
3468 {
3469 FT_ASSERT( cur[0]->clazz );
3470
3471 if ( cur[0]->clazz->get_interface )
3472 {
3473 result = cur[0]->clazz->get_interface( cur[0], service_id );
3474 if ( result != NULL )
3475 break;
3476 }
3477 }
3478 }
3479 }
3480 }
3481
3482 return result;
3483 }
3484
3485
Werner Lemberg748b1712005-12-25 09:15:09 +00003486 /* documentation is in ftmodapi.h */
Werner Lemberg90a03302000-11-07 17:21:11 +00003487
Werner Lembergf814d0f2001-06-27 16:18:10 +00003488 FT_EXPORT_DEF( FT_Error )
3489 FT_Remove_Module( FT_Library library,
3490 FT_Module module )
David Turnerf0df85b2000-06-22 00:17:42 +00003491 {
3492 /* try to find the module from the table, then remove it from there */
Werner Lembergdeb4e982000-06-29 03:14:25 +00003493
3494 if ( !library )
3495 return FT_Err_Invalid_Library_Handle;
3496
3497 if ( module )
David Turnerf0df85b2000-06-22 00:17:42 +00003498 {
3499 FT_Module* cur = library->modules;
3500 FT_Module* limit = cur + library->num_modules;
3501
Werner Lemberga929ba92000-06-25 06:47:11 +00003502
David Turnerf0df85b2000-06-22 00:17:42 +00003503 for ( ; cur < limit; cur++ )
3504 {
Werner Lembergdeb4e982000-06-29 03:14:25 +00003505 if ( cur[0] == module )
David Turnerf0df85b2000-06-22 00:17:42 +00003506 {
3507 /* remove it from the table */
3508 library->num_modules--;
3509 limit--;
Werner Lemberga929ba92000-06-25 06:47:11 +00003510 while ( cur < limit )
David Turnerf0df85b2000-06-22 00:17:42 +00003511 {
3512 cur[0] = cur[1];
3513 cur++;
3514 }
3515 limit[0] = 0;
3516
3517 /* destroy the module */
Werner Lemberga929ba92000-06-25 06:47:11 +00003518 Destroy_Module( module );
David Turnerf0df85b2000-06-22 00:17:42 +00003519
3520 return FT_Err_Ok;
3521 }
3522 }
3523 }
Werner Lembergb48a6092000-07-09 19:15:30 +00003524 return FT_Err_Invalid_Driver_Handle;
David Turnerf0df85b2000-06-22 00:17:42 +00003525 }
3526
3527
David Turnerf0df85b2000-06-22 00:17:42 +00003528 /*************************************************************************/
3529 /*************************************************************************/
3530 /*************************************************************************/
3531 /**** ****/
3532 /**** ****/
3533 /**** L I B R A R Y ****/
3534 /**** ****/
3535 /**** ****/
3536 /*************************************************************************/
3537 /*************************************************************************/
3538 /*************************************************************************/
3539
Werner Lemberga929ba92000-06-25 06:47:11 +00003540
Werner Lemberg748b1712005-12-25 09:15:09 +00003541 /* documentation is in ftmodapi.h */
Werner Lemberg90a03302000-11-07 17:21:11 +00003542
Werner Lembergf814d0f2001-06-27 16:18:10 +00003543 FT_EXPORT_DEF( FT_Error )
3544 FT_New_Library( FT_Memory memory,
3545 FT_Library *alibrary )
David Turnerf0df85b2000-06-22 00:17:42 +00003546 {
3547 FT_Library library = 0;
3548 FT_Error error;
3549
3550
3551 if ( !memory )
3552 return FT_Err_Invalid_Argument;
3553
David Turnerf5749602002-04-18 10:07:26 +00003554#ifdef FT_DEBUG_LEVEL_ERROR
David Turner53b3fa12002-02-24 05:26:57 +00003555 /* init debugging support */
3556 ft_debug_init();
David Turnerf5749602002-04-18 10:07:26 +00003557#endif
David Turner53b3fa12002-02-24 05:26:57 +00003558
David Turnerf0df85b2000-06-22 00:17:42 +00003559 /* first of all, allocate the library object */
David Turnere459d742002-03-22 13:52:37 +00003560 if ( FT_NEW( library ) )
David Turnerf0df85b2000-06-22 00:17:42 +00003561 return error;
3562
3563 library->memory = memory;
3564
3565 /* allocate the render pool */
3566 library->raster_pool_size = FT_RENDER_POOL_SIZE;
David Turnere459d742002-03-22 13:52:37 +00003567 if ( FT_ALLOC( library->raster_pool, FT_RENDER_POOL_SIZE ) )
David Turnerf0df85b2000-06-22 00:17:42 +00003568 goto Fail;
3569
3570 /* That's ok now */
3571 *alibrary = library;
3572
3573 return FT_Err_Ok;
3574
3575 Fail:
David Turnere459d742002-03-22 13:52:37 +00003576 FT_FREE( library );
David Turnerf0df85b2000-06-22 00:17:42 +00003577 return error;
3578 }
3579
3580
David Turner83b4a4b2002-03-06 12:42:34 +00003581 /* documentation is in freetype.h */
David Turner25a6e3a2002-06-10 23:03:35 +00003582
David Turner83b4a4b2002-03-06 12:42:34 +00003583 FT_EXPORT_DEF( void )
3584 FT_Library_Version( FT_Library library,
3585 FT_Int *amajor,
3586 FT_Int *aminor,
3587 FT_Int *apatch )
3588 {
3589 FT_Int major = 0;
3590 FT_Int minor = 0;
3591 FT_Int patch = 0;
3592
David Turner25a6e3a2002-06-10 23:03:35 +00003593
David Turner83b4a4b2002-03-06 12:42:34 +00003594 if ( library )
3595 {
3596 major = library->version_major;
3597 minor = library->version_minor;
3598 patch = library->version_patch;
3599 }
David Turner25a6e3a2002-06-10 23:03:35 +00003600
David Turnerd48575e2002-09-18 23:18:36 +00003601 if ( amajor )
David Turner83b4a4b2002-03-06 12:42:34 +00003602 *amajor = major;
David Turner25a6e3a2002-06-10 23:03:35 +00003603
David Turnerd48575e2002-09-18 23:18:36 +00003604 if ( aminor )
David Turner83b4a4b2002-03-06 12:42:34 +00003605 *aminor = minor;
David Turner25a6e3a2002-06-10 23:03:35 +00003606
David Turnerd48575e2002-09-18 23:18:36 +00003607 if ( apatch )
David Turner83b4a4b2002-03-06 12:42:34 +00003608 *apatch = patch;
David Turner25a6e3a2002-06-10 23:03:35 +00003609 }
David Turner83b4a4b2002-03-06 12:42:34 +00003610
3611
Werner Lemberg748b1712005-12-25 09:15:09 +00003612 /* documentation is in ftmodapi.h */
Werner Lemberg90a03302000-11-07 17:21:11 +00003613
Werner Lembergf814d0f2001-06-27 16:18:10 +00003614 FT_EXPORT_DEF( FT_Error )
3615 FT_Done_Library( FT_Library library )
David Turnerf0df85b2000-06-22 00:17:42 +00003616 {
3617 FT_Memory memory;
David Turnerf0df85b2000-06-22 00:17:42 +00003618
3619
3620 if ( !library )
3621 return FT_Err_Invalid_Library_Handle;
3622
3623 memory = library->memory;
3624
3625 /* Discard client-data */
3626 if ( library->generic.finalizer )
3627 library->generic.finalizer( library );
3628
3629 /* Close all modules in the library */
Werner Lembergf41e71a2001-12-20 21:22:02 +00003630#if 1
David Turnerc8087482001-12-20 13:14:18 +00003631 while ( library->num_modules > 0 )
3632 FT_Remove_Module( library, library->modules[0] );
Werner Lembergf41e71a2001-12-20 21:22:02 +00003633#else
David Turnerf0df85b2000-06-22 00:17:42 +00003634 {
Werner Lembergf41e71a2001-12-20 21:22:02 +00003635 FT_UInt n;
David Turnerf0df85b2000-06-22 00:17:42 +00003636
Werner Lemberga929ba92000-06-25 06:47:11 +00003637
Werner Lembergf41e71a2001-12-20 21:22:02 +00003638 for ( n = 0; n < library->num_modules; n++ )
David Turnerf0df85b2000-06-22 00:17:42 +00003639 {
Werner Lembergf41e71a2001-12-20 21:22:02 +00003640 FT_Module module = library->modules[n];
3641
3642
3643 if ( module )
3644 {
3645 Destroy_Module( module );
3646 library->modules[n] = 0;
3647 }
David Turnerf0df85b2000-06-22 00:17:42 +00003648 }
3649 }
David Turnerc8087482001-12-20 13:14:18 +00003650#endif
David Turnerf0df85b2000-06-22 00:17:42 +00003651
3652 /* Destroy raster objects */
David Turnere459d742002-03-22 13:52:37 +00003653 FT_FREE( library->raster_pool );
David Turnerf0df85b2000-06-22 00:17:42 +00003654 library->raster_pool_size = 0;
3655
David Turnere459d742002-03-22 13:52:37 +00003656 FT_FREE( library );
David Turnerf0df85b2000-06-22 00:17:42 +00003657 return FT_Err_Ok;
3658 }
3659
3660
Werner Lemberg748b1712005-12-25 09:15:09 +00003661 /* documentation is in ftmodapi.h */
Werner Lemberg90a03302000-11-07 17:21:11 +00003662
Werner Lembergf814d0f2001-06-27 16:18:10 +00003663 FT_EXPORT_DEF( void )
3664 FT_Set_Debug_Hook( FT_Library library,
3665 FT_UInt hook_index,
3666 FT_DebugHook_Func debug_hook )
David Turnerf0df85b2000-06-22 00:17:42 +00003667 {
3668 if ( library && debug_hook &&
3669 hook_index <
3670 ( sizeof ( library->debug_hooks ) / sizeof ( void* ) ) )
3671 library->debug_hooks[hook_index] = debug_hook;
3672 }
3673
3674
David Turnerd2b1f351999-12-16 23:11:37 +00003675/* END */