blob: 8f53eac61a76e48038e65d1aee32c5c3d21abe8b [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 Turner0b5dc4d2006-02-21 22:36:23 +000037#include FT_SERVICE_TRUETYPE_ENGINE_H
David Turnerc313c502003-09-11 19:51:54 +000038
Werner Lemberg013efd12003-09-17 05:26:33 +000039
David Turnerc313c502003-09-11 19:51:54 +000040 FT_BASE_DEF( FT_Pointer )
41 ft_service_list_lookup( FT_ServiceDesc service_descriptors,
42 const char* service_id )
43 {
44 FT_Pointer result = NULL;
45 FT_ServiceDesc desc = service_descriptors;
David Turnere2d12842003-09-21 17:15:55 +000046
Werner Lemberg013efd12003-09-17 05:26:33 +000047
David Turnerc313c502003-09-11 19:51:54 +000048 if ( desc && service_id )
49 {
50 for ( ; desc->serv_id != NULL; desc++ )
51 {
52 if ( ft_strcmp( desc->serv_id, service_id ) == 0 )
53 {
Werner Lemberg013efd12003-09-17 05:26:33 +000054 result = (FT_Pointer)desc->serv_data;
David Turnerc313c502003-09-11 19:51:54 +000055 break;
56 }
57 }
58 }
Werner Lemberg013efd12003-09-17 05:26:33 +000059
David Turnerc313c502003-09-11 19:51:54 +000060 return result;
David Turnere2d12842003-09-21 17:15:55 +000061 }
Werner Lemberg3c403e42002-08-06 21:47:40 +000062
Werner Lemberg013efd12003-09-17 05:26:33 +000063
David Turnered54f282002-03-22 17:09:52 +000064 FT_BASE_DEF( void )
65 ft_validator_init( FT_Validator valid,
66 const FT_Byte* base,
67 const FT_Byte* limit,
68 FT_ValidationLevel level )
69 {
70 valid->base = base;
71 valid->limit = limit;
72 valid->level = level;
Werner Lemberg8acb8672005-03-08 11:43:36 +000073 valid->error = FT_Err_Ok;
David Turnered54f282002-03-22 17:09:52 +000074 }
David Turner25a6e3a2002-06-10 23:03:35 +000075
David Turnered54f282002-03-22 17:09:52 +000076
77 FT_BASE_DEF( FT_Int )
78 ft_validator_run( FT_Validator valid )
79 {
80 int result;
Werner Lembergf8ba2002002-03-30 13:16:35 +000081
David Turner25a6e3a2002-06-10 23:03:35 +000082
83 result = ft_setjmp( valid->jump_buffer );
David Turnered54f282002-03-22 17:09:52 +000084 return result;
85 }
86
Werner Lembergf8ba2002002-03-30 13:16:35 +000087
David Turnered54f282002-03-22 17:09:52 +000088 FT_BASE_DEF( void )
89 ft_validator_error( FT_Validator valid,
90 FT_Error error )
91 {
92 valid->error = error;
David Turner25a6e3a2002-06-10 23:03:35 +000093 ft_longjmp( valid->jump_buffer, 1 );
94 }
Werner Lemberga929ba92000-06-25 06:47:11 +000095
Werner Lemberga3b6c6c2000-05-31 06:55:12 +000096
David Turnerd2b1f351999-12-16 23:11:37 +000097 /*************************************************************************/
98 /*************************************************************************/
99 /*************************************************************************/
100 /**** ****/
101 /**** ****/
David Turnerf0df85b2000-06-22 00:17:42 +0000102 /**** S T R E A M ****/
103 /**** ****/
104 /**** ****/
105 /*************************************************************************/
106 /*************************************************************************/
107 /*************************************************************************/
108
Werner Lemberg7880dd62000-01-10 17:19:45 +0000109
Werner Lemberg75435332004-02-25 12:58:54 +0000110 /* create a new input stream from an FT_Open_Args structure */
111 /* */
112 FT_BASE_DEF( FT_Error )
113 FT_Stream_New( FT_Library library,
114 const FT_Open_Args* args,
115 FT_Stream *astream )
David Turner7663f222000-02-13 13:37:38 +0000116 {
Werner Lemberg547a2522000-02-16 08:23:58 +0000117 FT_Error error;
118 FT_Memory memory;
119 FT_Stream stream;
120
Werner Lemberga3b6c6c2000-05-31 06:55:12 +0000121
Werner Lemberg2fbf7e42000-06-02 00:01:14 +0000122 if ( !library )
123 return FT_Err_Invalid_Library_Handle;
124
125 if ( !args )
126 return FT_Err_Invalid_Argument;
127
David Turner37379e22000-03-28 11:22:31 +0000128 *astream = 0;
129 memory = library->memory;
Werner Lembergf8ba2002002-03-30 13:16:35 +0000130
David Turnere459d742002-03-22 13:52:37 +0000131 if ( FT_NEW( stream ) )
David Turner37379e22000-03-28 11:22:31 +0000132 goto Exit;
David Turnere49ab252000-05-16 23:44:38 +0000133
David Turner7663f222000-02-13 13:37:38 +0000134 stream->memory = memory;
David Turnere49ab252000-05-16 23:44:38 +0000135
David Turnerb08fe2d2002-08-27 20:20:29 +0000136 if ( args->flags & FT_OPEN_MEMORY )
Just van Rossumd35aea72000-03-02 01:07:50 +0000137 {
David Turner53b3fa12002-02-24 05:26:57 +0000138 /* create a memory-based stream */
David Turner7d3a2642002-03-20 10:49:31 +0000139 FT_Stream_OpenMemory( stream,
Werner Lembergf8ba2002002-03-30 13:16:35 +0000140 (const FT_Byte*)args->memory_base,
141 args->memory_size );
David Turner4f2c5542000-05-12 10:19:41 +0000142 }
David Turnerb08fe2d2002-08-27 20:20:29 +0000143 else if ( args->flags & FT_OPEN_PATHNAME )
David Turner4f2c5542000-05-12 10:19:41 +0000144 {
David Turner53b3fa12002-02-24 05:26:57 +0000145 /* create a normal system stream */
146 error = FT_Stream_Open( stream, args->pathname );
David Turner4f2c5542000-05-12 10:19:41 +0000147 stream->pathname.pointer = args->pathname;
148 }
David Turnerb08fe2d2002-08-27 20:20:29 +0000149 else if ( ( args->flags & FT_OPEN_STREAM ) && args->stream )
David Turner4f2c5542000-05-12 10:19:41 +0000150 {
David Turner53b3fa12002-02-24 05:26:57 +0000151 /* use an existing, user-provided stream */
152
Werner Lemberg58b17f92000-07-27 23:29:08 +0000153 /* in this case, we do not need to allocate a new stream object */
154 /* since the caller is responsible for closing it himself */
David Turnere459d742002-03-22 13:52:37 +0000155 FT_FREE( stream );
David Turnerc5cdf8b2000-07-27 21:40:22 +0000156 stream = args->stream;
David Turner4f2c5542000-05-12 10:19:41 +0000157 }
158 else
David Turner4f2c5542000-05-12 10:19:41 +0000159 error = FT_Err_Invalid_Argument;
David Turnere49ab252000-05-16 23:44:38 +0000160
Werner Lemberg547a2522000-02-16 08:23:58 +0000161 if ( error )
David Turnere459d742002-03-22 13:52:37 +0000162 FT_FREE( stream );
David Turner53b3fa12002-02-24 05:26:57 +0000163 else
164 stream->memory = memory; /* just to be certain */
David Turnere49ab252000-05-16 23:44:38 +0000165
David Turner7663f222000-02-13 13:37:38 +0000166 *astream = stream;
Werner Lemberga3b6c6c2000-05-31 06:55:12 +0000167
David Turner37379e22000-03-28 11:22:31 +0000168 Exit:
David Turner7663f222000-02-13 13:37:38 +0000169 return error;
170 }
171
172
Werner Lemberg75435332004-02-25 12:58:54 +0000173 FT_BASE_DEF( void )
174 FT_Stream_Free( FT_Stream stream,
175 FT_Int external )
David Turner7663f222000-02-13 13:37:38 +0000176 {
David Turner53b3fa12002-02-24 05:26:57 +0000177 if ( stream )
David Turnerc5cdf8b2000-07-27 21:40:22 +0000178 {
179 FT_Memory memory = stream->memory;
Werner Lemberg58b17f92000-07-27 23:29:08 +0000180
Werner Lembergf8ba2002002-03-30 13:16:35 +0000181
David Turner53b3fa12002-02-24 05:26:57 +0000182 FT_Stream_Close( stream );
Werner Lemberg58b17f92000-07-27 23:29:08 +0000183
David Turner53b3fa12002-02-24 05:26:57 +0000184 if ( !external )
David Turnere459d742002-03-22 13:52:37 +0000185 FT_FREE( stream );
David Turnerc5cdf8b2000-07-27 21:40:22 +0000186 }
David Turner7663f222000-02-13 13:37:38 +0000187 }
188
Werner Lemberga3b6c6c2000-05-31 06:55:12 +0000189
Werner Lembergeb81e372000-06-03 06:03:11 +0000190#undef FT_COMPONENT
191#define FT_COMPONENT trace_objs
192
Werner Lembergdeb4e982000-06-29 03:14:25 +0000193
David Turnerf0df85b2000-06-22 00:17:42 +0000194 /*************************************************************************/
195 /*************************************************************************/
196 /*************************************************************************/
197 /**** ****/
198 /**** ****/
199 /**** FACE, SIZE & GLYPH SLOT OBJECTS ****/
200 /**** ****/
201 /**** ****/
202 /*************************************************************************/
203 /*************************************************************************/
204 /*************************************************************************/
205
Werner Lembergdeb4e982000-06-29 03:14:25 +0000206
Werner Lembergf814d0f2001-06-27 16:18:10 +0000207 static FT_Error
208 ft_glyphslot_init( FT_GlyphSlot slot )
David Turnerf0df85b2000-06-22 00:17:42 +0000209 {
210 FT_Driver driver = slot->face->driver;
Werner Lembergf8ba2002002-03-30 13:16:35 +0000211 FT_Driver_Class clazz = driver->clazz;
David Turnerf0df85b2000-06-22 00:17:42 +0000212 FT_Memory memory = driver->root.memory;
213 FT_Error error = FT_Err_Ok;
David Turner54e75742000-11-04 02:52:02 +0000214 FT_Slot_Internal internal;
David Turnerf0df85b2000-06-22 00:17:42 +0000215
Werner Lemberga8bbc262000-07-01 14:06:46 +0000216
David Turnerf9ca2bb2000-06-30 23:12:55 +0000217 slot->library = driver->root.library;
Werner Lembergfbeb41d2000-07-02 00:27:53 +0000218
David Turnere459d742002-03-22 13:52:37 +0000219 if ( FT_NEW( internal ) )
David Turner54e75742000-11-04 02:52:02 +0000220 goto Exit;
221
222 slot->internal = internal;
223
Werner Lemberga929ba92000-06-25 06:47:11 +0000224 if ( FT_DRIVER_USES_OUTLINES( driver ) )
David Turner54e75742000-11-04 02:52:02 +0000225 error = FT_GlyphLoader_New( memory, &internal->loader );
David Turnerf0df85b2000-06-22 00:17:42 +0000226
Werner Lemberga929ba92000-06-25 06:47:11 +0000227 if ( !error && clazz->init_slot )
David Turnerf0df85b2000-06-22 00:17:42 +0000228 error = clazz->init_slot( slot );
229
David Turner54e75742000-11-04 02:52:02 +0000230 Exit:
David Turnerf0df85b2000-06-22 00:17:42 +0000231 return error;
232 }
233
Werner Lemberge20ab692003-06-02 07:24:33 +0000234
David Turner66cbc202003-03-20 07:04:40 +0000235 FT_BASE_DEF( void )
236 ft_glyphslot_free_bitmap( FT_GlyphSlot slot )
237 {
Werner Lemberg7a024102003-06-18 06:59:57 +0000238 if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP )
David Turner66cbc202003-03-20 07:04:40 +0000239 {
240 FT_Memory memory = FT_FACE_MEMORY( slot->face );
Werner Lemberg51daa4f2003-05-18 22:40:11 +0000241
242
David Turner66cbc202003-03-20 07:04:40 +0000243 FT_FREE( slot->bitmap.buffer );
Werner Lemberg7a024102003-06-18 06:59:57 +0000244 slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP;
David Turner66cbc202003-03-20 07:04:40 +0000245 }
246 else
247 {
248 /* assume that the bitmap buffer was stolen or not */
249 /* allocated from the heap */
250 slot->bitmap.buffer = NULL;
251 }
252 }
253
254
255 FT_BASE_DEF( void )
256 ft_glyphslot_set_bitmap( FT_GlyphSlot slot,
Werner Lemberg319c00d2003-04-23 19:48:24 +0000257 FT_Byte* buffer )
David Turner66cbc202003-03-20 07:04:40 +0000258 {
259 ft_glyphslot_free_bitmap( slot );
Werner Lemberg51daa4f2003-05-18 22:40:11 +0000260
David Turner66cbc202003-03-20 07:04:40 +0000261 slot->bitmap.buffer = buffer;
Werner Lemberg51daa4f2003-05-18 22:40:11 +0000262
Werner Lemberg7a024102003-06-18 06:59:57 +0000263 FT_ASSERT( (slot->internal->flags & FT_GLYPH_OWN_BITMAP) == 0 );
Werner Lemberg51daa4f2003-05-18 22:40:11 +0000264 }
David Turner66cbc202003-03-20 07:04:40 +0000265
266
267 FT_BASE_DEF( FT_Error )
268 ft_glyphslot_alloc_bitmap( FT_GlyphSlot slot,
269 FT_ULong size )
270 {
Werner Lembergbe3c9812006-01-27 14:16:16 +0000271 FT_Memory memory = FT_FACE_MEMORY( slot->face );
272 FT_Error error;
Werner Lemberg51daa4f2003-05-18 22:40:11 +0000273
274
Werner Lemberg7a024102003-06-18 06:59:57 +0000275 if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP )
David Turner66cbc202003-03-20 07:04:40 +0000276 FT_FREE( slot->bitmap.buffer );
277 else
Werner Lemberg7a024102003-06-18 06:59:57 +0000278 slot->internal->flags |= FT_GLYPH_OWN_BITMAP;
Werner Lemberg51daa4f2003-05-18 22:40:11 +0000279
David Turner6a681fa2006-01-27 12:11:22 +0000280 (void)FT_ALLOC( slot->bitmap.buffer, size );
281 return error;
Werner Lemberg51daa4f2003-05-18 22:40:11 +0000282 }
David Turner66cbc202003-03-20 07:04:40 +0000283
David Turnerf0df85b2000-06-22 00:17:42 +0000284
Werner Lembergf814d0f2001-06-27 16:18:10 +0000285 static void
286 ft_glyphslot_clear( FT_GlyphSlot slot )
David Turnerf0df85b2000-06-22 00:17:42 +0000287 {
David Turner5ae831c2000-06-30 01:31:22 +0000288 /* free bitmap if needed */
David Turner66cbc202003-03-20 07:04:40 +0000289 ft_glyphslot_free_bitmap( slot );
Werner Lembergfbeb41d2000-07-02 00:27:53 +0000290
David Turnerf0df85b2000-06-22 00:17:42 +0000291 /* clear all public fields in the glyph slot */
David Turner3249c622002-10-31 08:30:19 +0000292 FT_ZERO( &slot->metrics );
293 FT_ZERO( &slot->outline );
294
Werner Lemberg0f1c4fa2005-06-06 07:01:47 +0000295 slot->bitmap.width = 0;
296 slot->bitmap.rows = 0;
297 slot->bitmap.pitch = 0;
David Turner3249c622002-10-31 08:30:19 +0000298 slot->bitmap.pixel_mode = 0;
Werner Lemberg0f1c4fa2005-06-06 07:01:47 +0000299 /* `slot->bitmap.buffer' has been handled by ft_glyphslot_free_bitmap */
David Turnerf0df85b2000-06-22 00:17:42 +0000300
301 slot->bitmap_left = 0;
302 slot->bitmap_top = 0;
303 slot->num_subglyphs = 0;
304 slot->subglyphs = 0;
305 slot->control_data = 0;
306 slot->control_len = 0;
307 slot->other = 0;
David Turnerb08fe2d2002-08-27 20:20:29 +0000308 slot->format = FT_GLYPH_FORMAT_NONE;
David Turnerf0df85b2000-06-22 00:17:42 +0000309
310 slot->linearHoriAdvance = 0;
311 slot->linearVertAdvance = 0;
Werner Lemberg34f4f392004-12-09 22:22:52 +0000312 slot->lsb_delta = 0;
313 slot->rsb_delta = 0;
David Turnerf0df85b2000-06-22 00:17:42 +0000314 }
315
316
Werner Lembergf814d0f2001-06-27 16:18:10 +0000317 static void
318 ft_glyphslot_done( FT_GlyphSlot slot )
David Turnerf0df85b2000-06-22 00:17:42 +0000319 {
Werner Lemberg9cc4aed2006-01-26 21:03:58 +0000320 FT_Driver driver = slot->face->driver;
321 FT_Driver_Class clazz = driver->clazz;
322 FT_Memory memory = driver->root.memory;
David Turnerf0df85b2000-06-22 00:17:42 +0000323
Werner Lemberga929ba92000-06-25 06:47:11 +0000324
David Turner54e75742000-11-04 02:52:02 +0000325 if ( clazz->done_slot )
326 clazz->done_slot( slot );
327
David Turnerf0df85b2000-06-22 00:17:42 +0000328 /* free bitmap buffer if needed */
David Turner66cbc202003-03-20 07:04:40 +0000329 ft_glyphslot_free_bitmap( slot );
David Turnerf0df85b2000-06-22 00:17:42 +0000330
331 /* free glyph loader */
Werner Lemberga929ba92000-06-25 06:47:11 +0000332 if ( FT_DRIVER_USES_OUTLINES( driver ) )
David Turnerf0df85b2000-06-22 00:17:42 +0000333 {
David Turner54e75742000-11-04 02:52:02 +0000334 FT_GlyphLoader_Done( slot->internal->loader );
335 slot->internal->loader = 0;
David Turnerf0df85b2000-06-22 00:17:42 +0000336 }
337
David Turnere459d742002-03-22 13:52:37 +0000338 FT_FREE( slot->internal );
David Turnerf0df85b2000-06-22 00:17:42 +0000339 }
340
341
Werner Lemberg8ec9dfd2000-11-07 23:56:02 +0000342 /* documentation is in ftobjs.h */
343
Werner Lembergf814d0f2001-06-27 16:18:10 +0000344 FT_BASE_DEF( FT_Error )
345 FT_New_GlyphSlot( FT_Face face,
346 FT_GlyphSlot *aslot )
David Turnerf0df85b2000-06-22 00:17:42 +0000347 {
Werner Lemberg9cc4aed2006-01-26 21:03:58 +0000348 FT_Error error;
349 FT_Driver driver;
350 FT_Driver_Class clazz;
351 FT_Memory memory;
352 FT_GlyphSlot slot;
Werner Lemberga929ba92000-06-25 06:47:11 +0000353
David Turnerf0df85b2000-06-22 00:17:42 +0000354
Werner Lembergb9ee7372005-05-20 21:52:19 +0000355 if ( !face || !face->driver )
David Turnerf0df85b2000-06-22 00:17:42 +0000356 return FT_Err_Invalid_Argument;
357
358 driver = face->driver;
359 clazz = driver->clazz;
360 memory = driver->root.memory;
361
362 FT_TRACE4(( "FT_New_GlyphSlot: Creating new slot object\n" ));
David Turnere459d742002-03-22 13:52:37 +0000363 if ( !FT_ALLOC( slot, clazz->slot_object_size ) )
David Turnerf0df85b2000-06-22 00:17:42 +0000364 {
365 slot->face = face;
366
367 error = ft_glyphslot_init( slot );
Werner Lemberga929ba92000-06-25 06:47:11 +0000368 if ( error )
David Turnerf0df85b2000-06-22 00:17:42 +0000369 {
370 ft_glyphslot_done( slot );
David Turnere459d742002-03-22 13:52:37 +0000371 FT_FREE( slot );
David Turnerf0df85b2000-06-22 00:17:42 +0000372 goto Exit;
373 }
374
Werner Lembergb9ee7372005-05-20 21:52:19 +0000375 slot->next = face->glyph;
376 face->glyph = slot;
377
378 if ( aslot )
379 *aslot = slot;
David Turnerf0df85b2000-06-22 00:17:42 +0000380 }
Werner Lembergb9ee7372005-05-20 21:52:19 +0000381 else if ( aslot )
382 *aslot = 0;
383
David Turnerf0df85b2000-06-22 00:17:42 +0000384
385 Exit:
386 FT_TRACE4(( "FT_New_GlyphSlot: Return %d\n", error ));
387 return error;
388 }
389
390
Werner Lemberg8ec9dfd2000-11-07 23:56:02 +0000391 /* documentation is in ftobjs.h */
392
Werner Lembergf814d0f2001-06-27 16:18:10 +0000393 FT_BASE_DEF( void )
394 FT_Done_GlyphSlot( FT_GlyphSlot slot )
David Turnerf0df85b2000-06-22 00:17:42 +0000395 {
396 if ( slot )
397 {
Werner Lembergb9ee7372005-05-20 21:52:19 +0000398 FT_Driver driver = slot->face->driver;
399 FT_Memory memory = driver->root.memory;
400 FT_GlyphSlot prev;
401 FT_GlyphSlot cur;
David Turnerf0df85b2000-06-22 00:17:42 +0000402
Werner Lemberga929ba92000-06-25 06:47:11 +0000403
David Turnerf0df85b2000-06-22 00:17:42 +0000404 /* Remove slot from its parent face's list */
Werner Lembergb9ee7372005-05-20 21:52:19 +0000405 prev = NULL;
406 cur = slot->face->glyph;
Werner Lemberga929ba92000-06-25 06:47:11 +0000407
David Turnerf0df85b2000-06-22 00:17:42 +0000408 while ( cur )
409 {
410 if ( cur == slot )
411 {
Werner Lembergb9ee7372005-05-20 21:52:19 +0000412 if ( !prev )
413 slot->face->glyph = cur->next;
414 else
415 prev->next = cur->next;
416
Werner Lemberga929ba92000-06-25 06:47:11 +0000417 ft_glyphslot_done( slot );
David Turnere459d742002-03-22 13:52:37 +0000418 FT_FREE( slot );
David Turnerf0df85b2000-06-22 00:17:42 +0000419 break;
420 }
Werner Lembergb9ee7372005-05-20 21:52:19 +0000421 prev = cur;
422 cur = cur->next;
David Turnerf0df85b2000-06-22 00:17:42 +0000423 }
424 }
425 }
426
427
Werner Lemberg90a03302000-11-07 17:21:11 +0000428 /* documentation is in freetype.h */
429
Werner Lembergf814d0f2001-06-27 16:18:10 +0000430 FT_EXPORT_DEF( void )
431 FT_Set_Transform( FT_Face face,
432 FT_Matrix* matrix,
433 FT_Vector* delta )
David Turnerf0df85b2000-06-22 00:17:42 +0000434 {
David Turner54e75742000-11-04 02:52:02 +0000435 FT_Face_Internal internal;
David Turner61d6b2b2001-05-16 17:49:07 +0000436
David Turner54e75742000-11-04 02:52:02 +0000437
David Turnerf0df85b2000-06-22 00:17:42 +0000438 if ( !face )
439 return;
440
David Turner54e75742000-11-04 02:52:02 +0000441 internal = face->internal;
442
443 internal->transform_flags = 0;
David Turnerf0df85b2000-06-22 00:17:42 +0000444
445 if ( !matrix )
446 {
David Turner54e75742000-11-04 02:52:02 +0000447 internal->transform_matrix.xx = 0x10000L;
448 internal->transform_matrix.xy = 0;
449 internal->transform_matrix.yx = 0;
450 internal->transform_matrix.yy = 0x10000L;
451 matrix = &internal->transform_matrix;
David Turnerf0df85b2000-06-22 00:17:42 +0000452 }
453 else
David Turner54e75742000-11-04 02:52:02 +0000454 internal->transform_matrix = *matrix;
David Turnerf0df85b2000-06-22 00:17:42 +0000455
456 /* set transform_flags bit flag 0 if `matrix' isn't the identity */
457 if ( ( matrix->xy | matrix->yx ) ||
458 matrix->xx != 0x10000L ||
459 matrix->yy != 0x10000L )
David Turner54e75742000-11-04 02:52:02 +0000460 internal->transform_flags |= 1;
David Turnerf0df85b2000-06-22 00:17:42 +0000461
462 if ( !delta )
463 {
David Turner54e75742000-11-04 02:52:02 +0000464 internal->transform_delta.x = 0;
465 internal->transform_delta.y = 0;
466 delta = &internal->transform_delta;
David Turnerf0df85b2000-06-22 00:17:42 +0000467 }
468 else
David Turner54e75742000-11-04 02:52:02 +0000469 internal->transform_delta = *delta;
David Turnerf0df85b2000-06-22 00:17:42 +0000470
471 /* set transform_flags bit flag 1 if `delta' isn't the null vector */
472 if ( delta->x | delta->y )
David Turner54e75742000-11-04 02:52:02 +0000473 internal->transform_flags |= 2;
David Turnerf0df85b2000-06-22 00:17:42 +0000474 }
475
476
Werner Lembergf814d0f2001-06-27 16:18:10 +0000477 static FT_Renderer
478 ft_lookup_glyph_renderer( FT_GlyphSlot slot );
Werner Lembergdeb4e982000-06-29 03:14:25 +0000479
480
Werner Lemberg90a03302000-11-07 17:21:11 +0000481 /* documentation is in freetype.h */
482
Werner Lembergf814d0f2001-06-27 16:18:10 +0000483 FT_EXPORT_DEF( FT_Error )
Werner Lemberg6b5c6692002-09-05 15:10:54 +0000484 FT_Load_Glyph( FT_Face face,
485 FT_UInt glyph_index,
486 FT_Int32 load_flags )
David Turnerf0df85b2000-06-22 00:17:42 +0000487 {
488 FT_Error error;
489 FT_Driver driver;
490 FT_GlyphSlot slot;
David Turner5ae831c2000-06-30 01:31:22 +0000491 FT_Library library;
Wu, Chia-I (吳佳一)e5ff0592006-01-15 06:00:49 +0000492 FT_Bool autohint = 0;
David Turner5ae831c2000-06-30 01:31:22 +0000493 FT_Module hinter;
David Turnerf0df85b2000-06-22 00:17:42 +0000494
Werner Lemberga929ba92000-06-25 06:47:11 +0000495
David Turnerf0df85b2000-06-22 00:17:42 +0000496 if ( !face || !face->size || !face->glyph )
497 return FT_Err_Invalid_Face_Handle;
498
Werner Lemberg2cba64d2003-04-28 08:51:07 +0000499 if ( glyph_index >= (FT_UInt)face->num_glyphs )
David Turnerf0df85b2000-06-22 00:17:42 +0000500 return FT_Err_Invalid_Argument;
501
502 slot = face->glyph;
503 ft_glyphslot_clear( slot );
504
Wu, Chia-I (吳佳一)e5ff0592006-01-15 06:00:49 +0000505 driver = face->driver;
506 library = driver->root.library;
507 hinter = library->auto_hinter;
David Turnerf0df85b2000-06-22 00:17:42 +0000508
Wu, Chia-I (吳佳一)e5ff0592006-01-15 06:00:49 +0000509 /* resolve load flags dependencies */
510
David Turnerf0df85b2000-06-22 00:17:42 +0000511 if ( load_flags & FT_LOAD_NO_RECURSE )
Werner Lembergeddd9902000-10-12 05:05:40 +0000512 load_flags |= FT_LOAD_NO_SCALE |
David Turnerc9ce9e42000-09-15 17:16:49 +0000513 FT_LOAD_IGNORE_TRANSFORM;
Werner Lembergeddd9902000-10-12 05:05:40 +0000514
Wu, Chia-I (吳佳一)e5ff0592006-01-15 06:00:49 +0000515 if ( load_flags & FT_LOAD_NO_SCALE )
516 {
517 load_flags |= FT_LOAD_NO_HINTING |
518 FT_LOAD_NO_BITMAP;
519
Werner Lembergeddd9902000-10-12 05:05:40 +0000520 load_flags &= ~FT_LOAD_RENDER;
David Turnerc9ce9e42000-09-15 17:16:49 +0000521 }
David Turnerf0df85b2000-06-22 00:17:42 +0000522
Wu, Chia-I (吳佳一)e5ff0592006-01-15 06:00:49 +0000523 if ( FT_LOAD_TARGET_MODE( load_flags ) == FT_RENDER_MODE_LIGHT )
David Turnere6bb9532005-12-23 13:32:06 +0000524 load_flags |= FT_LOAD_FORCE_AUTOHINT;
525
Wu, Chia-I (吳佳一)e5ff0592006-01-15 06:00:49 +0000526 /* auto-hinter is preferred and should be used */
Werner Lemberg1723dcc2006-01-15 07:30:32 +0000527 if ( ( !FT_DRIVER_HAS_HINTER( driver ) ||
Wu, Chia-I (吳佳一)e5ff0592006-01-15 06:00:49 +0000528 ( load_flags & FT_LOAD_FORCE_AUTOHINT ) ) &&
529 !( load_flags & FT_LOAD_NO_HINTING ) &&
Werner Lemberg1723dcc2006-01-15 07:30:32 +0000530 !( load_flags & FT_LOAD_NO_AUTOHINT ) )
David Turner5ae831c2000-06-30 01:31:22 +0000531 {
Werner Lemberg1723dcc2006-01-15 07:30:32 +0000532 /* check whether it works for this face */
Wu, Chia-I (吳佳一)e5ff0592006-01-15 06:00:49 +0000533 autohint =
534 FT_BOOL( hinter &&
535 FT_DRIVER_IS_SCALABLE( driver ) &&
536 FT_DRIVER_USES_OUTLINES( driver ) &&
537 face->internal->transform_matrix.yy > 0 &&
538 face->internal->transform_matrix.yx == 0 );
Werner Lembergcc9fc492000-06-30 06:21:26 +0000539 }
Werner Lembergfbeb41d2000-07-02 00:27:53 +0000540
Wu, Chia-I (吳佳一)e5ff0592006-01-15 06:00:49 +0000541 if ( autohint )
David Turner5ae831c2000-06-30 01:31:22 +0000542 {
David Turner9657ef02002-03-14 08:49:59 +0000543 FT_AutoHinter_Service hinting;
Werner Lembergfbeb41d2000-07-02 00:27:53 +0000544
Werner Lembergcc9fc492000-06-30 06:21:26 +0000545
Werner Lemberg0d535112001-12-19 22:26:12 +0000546 /* try to load embedded bitmaps first if available */
547 /* */
548 /* XXX: This is really a temporary hack that should disappear */
549 /* promptly with FreeType 2.1! */
David Turner4937a3e2001-12-19 21:09:16 +0000550 /* */
Werner Lembergeacb9302002-10-07 10:12:43 +0000551 if ( FT_HAS_FIXED_SIZES( face ) &&
David Turner80171e02002-10-05 14:57:03 +0000552 ( load_flags & FT_LOAD_NO_BITMAP ) == 0 )
David Turner4937a3e2001-12-19 21:09:16 +0000553 {
554 error = driver->clazz->load_glyph( slot, face->size,
555 glyph_index,
556 load_flags | FT_LOAD_SBITS_ONLY );
557
David Turnerb08fe2d2002-08-27 20:20:29 +0000558 if ( !error && slot->format == FT_GLYPH_FORMAT_BITMAP )
David Turner4937a3e2001-12-19 21:09:16 +0000559 goto Load_Ok;
560 }
561
562 /* load auto-hinted outline */
David Turner9657ef02002-03-14 08:49:59 +0000563 hinting = (FT_AutoHinter_Service)hinter->clazz->module_interface;
David Turner76a5f622000-11-04 01:55:49 +0000564
565 error = hinting->load_glyph( (FT_AutoHinter)hinter,
566 slot, face->size,
567 glyph_index, load_flags );
David Turner5ae831c2000-06-30 01:31:22 +0000568 }
569 else
David Turner662b3442002-01-03 16:56:59 +0000570 {
David Turner5ae831c2000-06-30 01:31:22 +0000571 error = driver->clazz->load_glyph( slot,
572 face->size,
Werner Lembergcc9fc492000-06-30 06:21:26 +0000573 glyph_index,
574 load_flags );
David Turner662b3442002-01-03 16:56:59 +0000575 if ( error )
576 goto Exit;
577
Werner Lemberg1a0a9792002-01-03 22:06:13 +0000578 /* check that the loaded outline is correct */
David Turner662b3442002-01-03 16:56:59 +0000579 error = FT_Outline_Check( &slot->outline );
580 if ( error )
581 goto Exit;
582 }
David Turnerf0df85b2000-06-22 00:17:42 +0000583
David Turner4937a3e2001-12-19 21:09:16 +0000584 Load_Ok:
David Turnerf0df85b2000-06-22 00:17:42 +0000585 /* compute the advance */
Werner Lemberga929ba92000-06-25 06:47:11 +0000586 if ( load_flags & FT_LOAD_VERTICAL_LAYOUT )
David Turnerf0df85b2000-06-22 00:17:42 +0000587 {
588 slot->advance.x = 0;
589 slot->advance.y = slot->metrics.vertAdvance;
590 }
591 else
592 {
593 slot->advance.x = slot->metrics.horiAdvance;
594 slot->advance.y = 0;
595 }
596
David Turnerc9ce9e42000-09-15 17:16:49 +0000597 /* compute the linear advance in 16.16 pixels */
Werner Lemberg51daa4f2003-05-18 22:40:11 +0000598 if ( ( load_flags & FT_LOAD_LINEAR_DESIGN ) == 0 &&
599 ( face->face_flags & FT_FACE_FLAG_SCALABLE ) )
David Turnerc9ce9e42000-09-15 17:16:49 +0000600 {
David Turnerc9ce9e42000-09-15 17:16:49 +0000601 FT_Size_Metrics* metrics = &face->size->metrics;
Werner Lembergeddd9902000-10-12 05:05:40 +0000602
Werner Lembergf8ba2002002-03-30 13:16:35 +0000603
Wu, Chia-I (吳佳一)e5ff0592006-01-15 06:00:49 +0000604 /* it's tricky! */
David Turnerc9ce9e42000-09-15 17:16:49 +0000605 slot->linearHoriAdvance = FT_MulDiv( slot->linearHoriAdvance,
Werner Lembergbe67c4e2003-11-24 22:54:58 +0000606 metrics->x_scale, 64 );
David Turnerc9ce9e42000-09-15 17:16:49 +0000607
608 slot->linearVertAdvance = FT_MulDiv( slot->linearVertAdvance,
Werner Lembergbe67c4e2003-11-24 22:54:58 +0000609 metrics->y_scale, 64 );
David Turnerc9ce9e42000-09-15 17:16:49 +0000610 }
611
612 if ( ( load_flags & FT_LOAD_IGNORE_TRANSFORM ) == 0 )
David Turnerf0df85b2000-06-22 00:17:42 +0000613 {
David Turner54e75742000-11-04 02:52:02 +0000614 FT_Face_Internal internal = face->internal;
David Turner61d6b2b2001-05-16 17:49:07 +0000615
616
Werner Lembergd1b74752000-08-24 16:29:15 +0000617 /* now, transform the glyph image if needed */
David Turner54e75742000-11-04 02:52:02 +0000618 if ( internal->transform_flags )
David Turner35db7322000-08-24 12:39:40 +0000619 {
620 /* get renderer */
621 FT_Renderer renderer = ft_lookup_glyph_renderer( slot );
Werner Lembergdeb4e982000-06-29 03:14:25 +0000622
Werner Lemberga929ba92000-06-25 06:47:11 +0000623
David Turner35db7322000-08-24 12:39:40 +0000624 if ( renderer )
Werner Lembergdc72aff2000-11-04 08:33:38 +0000625 error = renderer->clazz->transform_glyph(
626 renderer, slot,
627 &internal->transform_matrix,
628 &internal->transform_delta );
David Turner35db7322000-08-24 12:39:40 +0000629 /* transform advance */
David Turner54e75742000-11-04 02:52:02 +0000630 FT_Vector_Transform( &slot->advance, &internal->transform_matrix );
David Turner35db7322000-08-24 12:39:40 +0000631 }
David Turnerc9ce9e42000-09-15 17:16:49 +0000632 }
David Turnerf0df85b2000-06-22 00:17:42 +0000633
David Turnerc9ce9e42000-09-15 17:16:49 +0000634 /* do we need to render the image now? */
635 if ( !error &&
David Turnerb08fe2d2002-08-27 20:20:29 +0000636 slot->format != FT_GLYPH_FORMAT_BITMAP &&
637 slot->format != FT_GLYPH_FORMAT_COMPOSITE &&
David Turnerc9ce9e42000-09-15 17:16:49 +0000638 load_flags & FT_LOAD_RENDER )
639 {
David Turner00d9f402002-09-08 21:29:11 +0000640 FT_Render_Mode mode = FT_LOAD_TARGET_MODE( load_flags );
641
Werner Lemberg68e9f922002-09-27 11:09:23 +0000642
David Turner00d9f402002-09-08 21:29:11 +0000643 if ( mode == FT_RENDER_MODE_NORMAL &&
644 (load_flags & FT_LOAD_MONOCHROME ) )
645 mode = FT_RENDER_MODE_MONO;
646
647 error = FT_Render_Glyph( slot, mode );
Werner Lembergd060a752000-07-20 06:57:41 +0000648 }
David Turner5ae831c2000-06-30 01:31:22 +0000649
Werner Lembergdeb4e982000-06-29 03:14:25 +0000650 Exit:
David Turnerf0df85b2000-06-22 00:17:42 +0000651 return error;
652 }
653
654
Werner Lemberg90a03302000-11-07 17:21:11 +0000655 /* documentation is in freetype.h */
656
Werner Lembergf814d0f2001-06-27 16:18:10 +0000657 FT_EXPORT_DEF( FT_Error )
658 FT_Load_Char( FT_Face face,
659 FT_ULong char_code,
David Turnerf467e6a2002-08-21 21:39:28 +0000660 FT_Int32 load_flags )
David Turnerf0df85b2000-06-22 00:17:42 +0000661 {
Werner Lembergdeb4e982000-06-29 03:14:25 +0000662 FT_UInt glyph_index;
David Turnerf0df85b2000-06-22 00:17:42 +0000663
Werner Lemberga929ba92000-06-25 06:47:11 +0000664
David Turnerf0df85b2000-06-22 00:17:42 +0000665 if ( !face )
666 return FT_Err_Invalid_Face_Handle;
667
668 glyph_index = (FT_UInt)char_code;
Werner Lemberga929ba92000-06-25 06:47:11 +0000669 if ( face->charmap )
David Turnerf0df85b2000-06-22 00:17:42 +0000670 glyph_index = FT_Get_Char_Index( face, char_code );
671
David Turner5ae831c2000-06-30 01:31:22 +0000672 return FT_Load_Glyph( face, glyph_index, load_flags );
David Turnerf0df85b2000-06-22 00:17:42 +0000673 }
674
675
Werner Lemberg7880dd62000-01-10 17:19:45 +0000676 /* destructor for sizes list */
Werner Lembergf814d0f2001-06-27 16:18:10 +0000677 static void
678 destroy_size( FT_Memory memory,
679 FT_Size size,
680 FT_Driver driver )
Werner Lemberg7880dd62000-01-10 17:19:45 +0000681 {
David Turnerf0df85b2000-06-22 00:17:42 +0000682 /* finalize client-specific data */
Werner Lemberga929ba92000-06-25 06:47:11 +0000683 if ( size->generic.finalizer )
David Turnerf0df85b2000-06-22 00:17:42 +0000684 size->generic.finalizer( size );
685
Werner Lemberg7880dd62000-01-10 17:19:45 +0000686 /* finalize format-specific stuff */
Werner Lemberga929ba92000-06-25 06:47:11 +0000687 if ( driver->clazz->done_size )
David Turnerf0df85b2000-06-22 00:17:42 +0000688 driver->clazz->done_size( size );
689
David Turnere459d742002-03-22 13:52:37 +0000690 FT_FREE( size->internal );
691 FT_FREE( size );
Werner Lemberg7880dd62000-01-10 17:19:45 +0000692 }
David Turnerd2b1f351999-12-16 23:11:37 +0000693
694
Werner Lemberg4338dab2004-01-05 14:41:59 +0000695 static void
Werner Lemberge70371c2005-05-27 06:01:28 +0000696 ft_cmap_done_internal( FT_CMap cmap );
697
698
699 static void
Werner Lemberg4338dab2004-01-05 14:41:59 +0000700 destroy_charmaps( FT_Face face,
701 FT_Memory memory )
702 {
703 FT_Int n;
704
705
706 for ( n = 0; n < face->num_charmaps; n++ )
707 {
708 FT_CMap cmap = FT_CMAP( face->charmaps[n] );
709
710
Werner Lemberge70371c2005-05-27 06:01:28 +0000711 ft_cmap_done_internal( cmap );
Werner Lemberg4338dab2004-01-05 14:41:59 +0000712
713 face->charmaps[n] = NULL;
714 }
715
716 FT_FREE( face->charmaps );
717 face->num_charmaps = 0;
718 }
719
720
Werner Lemberg7880dd62000-01-10 17:19:45 +0000721 /* destructor for faces list */
Werner Lembergf814d0f2001-06-27 16:18:10 +0000722 static void
723 destroy_face( FT_Memory memory,
724 FT_Face face,
725 FT_Driver driver )
Werner Lemberg7880dd62000-01-10 17:19:45 +0000726 {
David Turneref3c1262002-03-14 09:22:48 +0000727 FT_Driver_Class clazz = driver->clazz;
David Turnerf0df85b2000-06-22 00:17:42 +0000728
Werner Lembergd060a752000-07-20 06:57:41 +0000729
David Turnerc49f69c2000-07-20 03:44:50 +0000730 /* discard auto-hinting data */
731 if ( face->autohint.finalizer )
732 face->autohint.finalizer( face->autohint.data );
Werner Lembergeddd9902000-10-12 05:05:40 +0000733
Werner Lembergf8ba2002002-03-30 13:16:35 +0000734 /* Discard glyph slots for this face. */
David Turner23bcde12001-10-17 13:48:10 +0000735 /* Beware! FT_Done_GlyphSlot() changes the field `face->glyph' */
Werner Lemberg7880dd62000-01-10 17:19:45 +0000736 while ( face->glyph )
737 FT_Done_GlyphSlot( face->glyph );
738
Werner Lembergf8ba2002002-03-30 13:16:35 +0000739 /* discard all sizes for this face */
Werner Lemberg7880dd62000-01-10 17:19:45 +0000740 FT_List_Finalize( &face->sizes_list,
Werner Lemberg74184152003-10-18 16:56:13 +0000741 (FT_List_Destructor)destroy_size,
742 memory,
743 driver );
Werner Lemberg7880dd62000-01-10 17:19:45 +0000744 face->size = 0;
745
Werner Lembergf8ba2002002-03-30 13:16:35 +0000746 /* now discard client data */
Werner Lemberg7880dd62000-01-10 17:19:45 +0000747 if ( face->generic.finalizer )
748 face->generic.finalizer( face );
749
David Turner2ded2c12002-03-22 22:37:40 +0000750 /* discard charmaps */
Werner Lemberg4338dab2004-01-05 14:41:59 +0000751 destroy_charmaps( face, memory );
Werner Lemberg75435332004-02-25 12:58:54 +0000752
David Turnerf0df85b2000-06-22 00:17:42 +0000753 /* finalize format-specific stuff */
Werner Lemberga929ba92000-06-25 06:47:11 +0000754 if ( clazz->done_face )
755 clazz->done_face( face );
David Turnerf0df85b2000-06-22 00:17:42 +0000756
757 /* close the stream for this face if needed */
Werner Lemberg75435332004-02-25 12:58:54 +0000758 FT_Stream_Free(
Werner Lembergf8ba2002002-03-30 13:16:35 +0000759 face->stream,
Werner Lemberg58b17f92000-07-27 23:29:08 +0000760 ( face->face_flags & FT_FACE_FLAG_EXTERNAL_STREAM ) != 0 );
David Turner7663f222000-02-13 13:37:38 +0000761
David Turner53b3fa12002-02-24 05:26:57 +0000762 face->stream = 0;
763
Werner Lemberg7880dd62000-01-10 17:19:45 +0000764 /* get rid of it */
David Turner23bcde12001-10-17 13:48:10 +0000765 if ( face->internal )
766 {
David Turnere459d742002-03-22 13:52:37 +0000767 FT_FREE( face->internal );
David Turner23bcde12001-10-17 13:48:10 +0000768 }
David Turnere459d742002-03-22 13:52:37 +0000769 FT_FREE( face );
Werner Lemberg7880dd62000-01-10 17:19:45 +0000770 }
David Turnerd2b1f351999-12-16 23:11:37 +0000771
772
Werner Lembergf814d0f2001-06-27 16:18:10 +0000773 static void
774 Destroy_Driver( FT_Driver driver )
David Turnerd2b1f351999-12-16 23:11:37 +0000775 {
David Turnerd2b1f351999-12-16 23:11:37 +0000776 FT_List_Finalize( &driver->faces_list,
777 (FT_List_Destructor)destroy_face,
David Turnerf0df85b2000-06-22 00:17:42 +0000778 driver->root.memory,
David Turnerd2b1f351999-12-16 23:11:37 +0000779 driver );
780
Werner Lembergdeb4e982000-06-29 03:14:25 +0000781 /* check whether we need to drop the driver's glyph loader */
Werner Lemberga929ba92000-06-25 06:47:11 +0000782 if ( FT_DRIVER_USES_OUTLINES( driver ) )
David Turnerf0df85b2000-06-22 00:17:42 +0000783 FT_GlyphLoader_Done( driver->glyph_loader );
David Turnerd2b1f351999-12-16 23:11:37 +0000784 }
785
786
Werner Lemberg547a2522000-02-16 08:23:58 +0000787 /*************************************************************************/
788 /* */
789 /* <Function> */
Antoine Lecac96f69d2002-12-03 00:39:16 +0000790 /* find_unicode_charmap */
791 /* */
792 /* <Description> */
793 /* This function finds a Unicode charmap, if there is one. */
794 /* And if there is more than one, it tries to favour the more */
Werner Lembergc8c6bf52003-04-23 05:38:13 +0000795 /* extensive one, i.e., one that supports UCS-4 against those which */
Antoine Lecac96f69d2002-12-03 00:39:16 +0000796 /* are limited to the BMP (said UCS-2 encoding.) */
797 /* */
798 /* This function is called from open_face() (just below), and also */
Werner Lembergc8c6bf52003-04-23 05:38:13 +0000799 /* from FT_Select_Charmap( ..., FT_ENCODING_UNICODE). */
Antoine Lecac96f69d2002-12-03 00:39:16 +0000800 /* */
801 static FT_Error
802 find_unicode_charmap( FT_Face face )
803 {
804 FT_CharMap* first;
805 FT_CharMap* cur;
806 FT_CharMap* unicmap = NULL; /* some UCS-2 map, if we found it */
807
808
809 /* caller should have already checked that `face' is valid */
Werner Lemberg74184152003-10-18 16:56:13 +0000810 FT_ASSERT( face );
Antoine Lecac96f69d2002-12-03 00:39:16 +0000811
812 first = face->charmaps;
813
814 if ( !first )
815 return FT_Err_Invalid_CharMap_Handle;
816
David Turnerc528f6f2002-12-18 22:43:07 +0000817 /*
Werner Lembergc8c6bf52003-04-23 05:38:13 +0000818 * The original TrueType specification(s) only specified charmap
David Turnerc528f6f2002-12-18 22:43:07 +0000819 * formats that are capable of mapping 8 or 16 bit character codes to
820 * glyph indices.
821 *
Werner Lembergc8c6bf52003-04-23 05:38:13 +0000822 * However, recent updates to the Apple and OpenType specifications
David Turnerc528f6f2002-12-18 22:43:07 +0000823 * introduced new formats that are capable of mapping 32-bit character
Werner Lembergc8c6bf52003-04-23 05:38:13 +0000824 * codes as well. And these are already used on some fonts, mainly to
David Turnerae26c682003-02-25 20:37:50 +0000825 * map non-BMP Asian ideographs as defined in Unicode.
David Turnerc528f6f2002-12-18 22:43:07 +0000826 *
Werner Lembergc8c6bf52003-04-23 05:38:13 +0000827 * For compatibility purposes, these fonts generally come with
David Turnerc528f6f2002-12-18 22:43:07 +0000828 * *several* Unicode charmaps:
829 *
Werner Lembergc8c6bf52003-04-23 05:38:13 +0000830 * - One of them in the "old" 16-bit format, that cannot access
831 * all glyphs in the font.
David Turnerc528f6f2002-12-18 22:43:07 +0000832 *
Werner Lembergc8c6bf52003-04-23 05:38:13 +0000833 * - Another one in the "new" 32-bit format, that can access all
David Turnerc528f6f2002-12-18 22:43:07 +0000834 * the glyphs.
835 *
Werner Lembergc8c6bf52003-04-23 05:38:13 +0000836 * This function has been written to always favor a 32-bit charmap
837 * when found. Otherwise, a 16-bit one is returned when found.
David Turnerc528f6f2002-12-18 22:43:07 +0000838 */
839
Werner Lemberg8acb8672005-03-08 11:43:36 +0000840 /* Since the `interesting' table, with IDs (3,10), is normally the */
841 /* last one, we loop backwards. This looses with type1 fonts with */
842 /* non-BMP characters (<.0001%), this wins with .ttf with non-BMP */
843 /* chars (.01% ?), and this is the same about 99.99% of the time! */
Antoine Lecac96f69d2002-12-03 00:39:16 +0000844
845 cur = first + face->num_charmaps; /* points after the last one */
846
847 for ( ; --cur >= first; )
848 {
849 if ( cur[0]->encoding == FT_ENCODING_UNICODE )
850 {
851 unicmap = cur; /* record we found a Unicode charmap */
852
853 /* XXX If some new encodings to represent UCS-4 are added, */
854 /* they should be added here. */
David Turnerc528f6f2002-12-18 22:43:07 +0000855 if ( ( cur[0]->platform_id == TT_PLATFORM_MICROSOFT &&
856 cur[0]->encoding_id == TT_MS_ID_UCS_4 ) ||
857 ( cur[0]->platform_id == TT_PLATFORM_APPLE_UNICODE &&
858 cur[0]->encoding_id == TT_APPLE_ID_UNICODE_32 ) )
859
Werner Lemberg8acb8672005-03-08 11:43:36 +0000860 /* Hurray! We found a UCS-4 charmap. We can stop the scan! */
Antoine Lecac96f69d2002-12-03 00:39:16 +0000861 {
862 face->charmap = cur[0];
863 return 0;
864 }
865 }
866 }
867
Werner Lemberg8acb8672005-03-08 11:43:36 +0000868 /* We do not have any UCS-4 charmap. Sigh. */
869 /* Let's see if we have some other kind of Unicode charmap, though. */
Antoine Lecac96f69d2002-12-03 00:39:16 +0000870 if ( unicmap != NULL )
871 {
872 face->charmap = unicmap[0];
873 return 0;
874 }
875
876 /* Chou blanc! */
David Turner6453a812003-01-08 09:28:34 +0000877 return FT_Err_Invalid_CharMap_Handle;
Antoine Lecac96f69d2002-12-03 00:39:16 +0000878 }
879
880
881 /*************************************************************************/
882 /* */
883 /* <Function> */
Werner Lemberg547a2522000-02-16 08:23:58 +0000884 /* open_face */
885 /* */
886 /* <Description> */
887 /* This function does some work for FT_Open_Face(). */
888 /* */
Werner Lembergf814d0f2001-06-27 16:18:10 +0000889 static FT_Error
890 open_face( FT_Driver driver,
891 FT_Stream stream,
892 FT_Long face_index,
893 FT_Int num_params,
894 FT_Parameter* params,
Werner Lemberg6d798992003-07-01 07:28:55 +0000895 FT_Face *aface )
David Turnerd2b1f351999-12-16 23:11:37 +0000896 {
David Turnerf0df85b2000-06-22 00:17:42 +0000897 FT_Memory memory;
Werner Lemberg77c34b82003-05-20 22:06:38 +0000898 FT_Driver_Class clazz;
David Turnerf0df85b2000-06-22 00:17:42 +0000899 FT_Face face = 0;
Antoine Lecac96f69d2002-12-03 00:39:16 +0000900 FT_Error error, error2;
David Turner6a681fa2006-01-27 12:11:22 +0000901 FT_Face_Internal internal = NULL;
David Turnerd2b1f351999-12-16 23:11:37 +0000902
Werner Lemberg3c403e42002-08-06 21:47:40 +0000903
David Turnerf0df85b2000-06-22 00:17:42 +0000904 clazz = driver->clazz;
905 memory = driver->root.memory;
David Turnerd2b1f351999-12-16 23:11:37 +0000906
Werner Lembergdeb4e982000-06-29 03:14:25 +0000907 /* allocate the face object and perform basic initialization */
David Turnere459d742002-03-22 13:52:37 +0000908 if ( FT_ALLOC( face, clazz->face_object_size ) )
David Turnerd2b1f351999-12-16 23:11:37 +0000909 goto Fail;
910
David Turnere459d742002-03-22 13:52:37 +0000911 if ( FT_NEW( internal ) )
David Turner54e75742000-11-04 02:52:02 +0000912 goto Fail;
David Turner61d6b2b2001-05-16 17:49:07 +0000913
David Turner54e75742000-11-04 02:52:02 +0000914 face->internal = internal;
915
916 face->driver = driver;
917 face->memory = memory;
918 face->stream = stream;
Graham Asherce121822002-08-01 15:29:17 +0000919
Graham Asherd53cf1d2002-07-18 15:04:29 +0000920#ifdef FT_CONFIG_OPTION_INCREMENTAL
Werner Lemberg3c403e42002-08-06 21:47:40 +0000921 {
922 int i;
923
924
925 face->internal->incremental_interface = 0;
926 for ( i = 0; i < num_params && !face->internal->incremental_interface;
927 i++ )
928 if ( params[i].tag == FT_PARAM_TAG_INCREMENTAL )
929 face->internal->incremental_interface = params[i].data;
Antoine Lecac96f69d2002-12-03 00:39:16 +0000930 }
Graham Asherd53cf1d2002-07-18 15:04:29 +0000931#endif
David Turnerd2b1f351999-12-16 23:11:37 +0000932
David Turnerf0df85b2000-06-22 00:17:42 +0000933 error = clazz->init_face( stream,
934 face,
Werner Lemberg68e9f922002-09-27 11:09:23 +0000935 (FT_Int)face_index,
David Turnerf0df85b2000-06-22 00:17:42 +0000936 num_params,
937 params );
David Turnerd2b1f351999-12-16 23:11:37 +0000938 if ( error )
939 goto Fail;
940
David Turnerfed59b72002-07-17 22:51:06 +0000941 /* select Unicode charmap by default */
Antoine Lecac96f69d2002-12-03 00:39:16 +0000942 error2 = find_unicode_charmap( face );
David Turnerc528f6f2002-12-18 22:43:07 +0000943
Werner Lemberg6d798992003-07-01 07:28:55 +0000944 /* if no Unicode charmap can be found, FT_Err_Invalid_CharMap_Handle */
945 /* is returned. */
Antoine Lecac96f69d2002-12-03 00:39:16 +0000946
Werner Lemberg6d798992003-07-01 07:28:55 +0000947 /* no error should happen, but we want to play safe */
David Turnerc528f6f2002-12-18 22:43:07 +0000948 if ( error2 && error2 != FT_Err_Invalid_CharMap_Handle )
David Turnerfed59b72002-07-17 22:51:06 +0000949 {
Antoine Lecac96f69d2002-12-03 00:39:16 +0000950 error = error2;
951 goto Fail;
David Turnerfed59b72002-07-17 22:51:06 +0000952 }
953
David Turnerd2b1f351999-12-16 23:11:37 +0000954 *aface = face;
955
956 Fail:
957 if ( error )
958 {
Werner Lemberg4338dab2004-01-05 14:41:59 +0000959 destroy_charmaps( face, memory );
David Turnerf0df85b2000-06-22 00:17:42 +0000960 clazz->done_face( face );
Werner Lemberg77c34b82003-05-20 22:06:38 +0000961 FT_FREE( internal );
David Turnere459d742002-03-22 13:52:37 +0000962 FT_FREE( face );
David Turnerd2b1f351999-12-16 23:11:37 +0000963 *aface = 0;
964 }
965
966 return error;
967 }
968
969
Werner Lemberg05c21b82000-07-29 20:38:19 +0000970 /* there's a Mac-specific extended implementation of FT_New_Face() */
Werner Lemberg4d631e42002-05-27 13:02:37 +0000971 /* in src/base/ftmac.c */
Werner Lemberg05c21b82000-07-29 20:38:19 +0000972
Werner Lemberg9ca7a152002-04-30 14:26:49 +0000973#ifndef FT_MACINTOSH
Just van Rossum9e830c52000-07-28 01:12:34 +0000974
Werner Lemberg90a03302000-11-07 17:21:11 +0000975 /* documentation is in freetype.h */
976
Werner Lembergf814d0f2001-06-27 16:18:10 +0000977 FT_EXPORT_DEF( FT_Error )
978 FT_New_Face( FT_Library library,
979 const char* pathname,
980 FT_Long face_index,
981 FT_Face *aface )
David Turnerd2b1f351999-12-16 23:11:37 +0000982 {
David Turner37379e22000-03-28 11:22:31 +0000983 FT_Open_Args args;
Werner Lemberg547a2522000-02-16 08:23:58 +0000984
Werner Lemberga929ba92000-06-25 06:47:11 +0000985
Werner Lemberg2fbf7e42000-06-02 00:01:14 +0000986 /* test for valid `library' and `aface' delayed to FT_Open_Face() */
Werner Lemberg2fbf7e42000-06-02 00:01:14 +0000987 if ( !pathname )
988 return FT_Err_Invalid_Argument;
989
David Turnerb08fe2d2002-08-27 20:20:29 +0000990 args.flags = FT_OPEN_PATHNAME;
David Turner4f2c5542000-05-12 10:19:41 +0000991 args.pathname = (char*)pathname;
Werner Lemberga3b6c6c2000-05-31 06:55:12 +0000992
David Turnercda32b72000-02-10 16:14:35 +0000993 return FT_Open_Face( library, &args, face_index, aface );
David Turnerd2b1f351999-12-16 23:11:37 +0000994 }
995
Werner Lemberg9ca7a152002-04-30 14:26:49 +0000996#endif /* !FT_MACINTOSH */
Just van Rossum9e830c52000-07-28 01:12:34 +0000997
Werner Lemberg7880dd62000-01-10 17:19:45 +0000998
Werner Lemberg90a03302000-11-07 17:21:11 +0000999 /* documentation is in freetype.h */
1000
Werner Lembergf814d0f2001-06-27 16:18:10 +00001001 FT_EXPORT_DEF( FT_Error )
1002 FT_New_Memory_Face( FT_Library library,
1003 const FT_Byte* file_base,
1004 FT_Long file_size,
1005 FT_Long face_index,
1006 FT_Face *aface )
David Turnerd2b1f351999-12-16 23:11:37 +00001007 {
David Turner37379e22000-03-28 11:22:31 +00001008 FT_Open_Args args;
Werner Lemberg7880dd62000-01-10 17:19:45 +00001009
Werner Lemberga929ba92000-06-25 06:47:11 +00001010
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001011 /* test for valid `library' and `face' delayed to FT_Open_Face() */
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001012 if ( !file_base )
1013 return FT_Err_Invalid_Argument;
1014
David Turnerb08fe2d2002-08-27 20:20:29 +00001015 args.flags = FT_OPEN_MEMORY;
David Turnercda32b72000-02-10 16:14:35 +00001016 args.memory_base = file_base;
1017 args.memory_size = file_size;
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001018
Werner Lemberg4b680072000-11-07 06:30:29 +00001019 return FT_Open_Face( library, &args, face_index, aface );
David Turnerd2b1f351999-12-16 23:11:37 +00001020 }
1021
Werner Lemberg7880dd62000-01-10 17:19:45 +00001022
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001023#if !defined( FT_MACINTOSH ) && defined( FT_CONFIG_OPTION_MAC_FONTS )
1024
1025 /* The behavior here is very similar to that in base/ftmac.c, but it */
1026 /* is designed to work on non-mac systems, so no mac specific calls. */
1027 /* */
1028 /* We look at the file and determine if it is a mac dfont file or a mac */
1029 /* resource file, or a macbinary file containing a mac resource file. */
1030 /* */
1031 /* Unlike ftmac I'm not going to look at a `FOND'. I don't really see */
1032 /* the point, especially since there may be multiple `FOND' resources. */
1033 /* Instead I'll just look for `sfnt' and `POST' resources, ordered as */
1034 /* they occur in the file. */
1035 /* */
1036 /* Note that multiple `POST' resources do not mean multiple postscript */
1037 /* fonts; they all get jammed together to make what is essentially a */
1038 /* pfb file. */
1039 /* */
1040 /* We aren't interested in `NFNT' or `FONT' bitmap resources. */
1041 /* */
1042 /* As soon as we get an `sfnt' load it into memory and pass it off to */
1043 /* FT_Open_Face. */
1044 /* */
1045 /* If we have a (set of) `POST' resources, massage them into a (memory) */
1046 /* pfb file and pass that to FT_Open_Face. (As with ftmac.c I'm not */
1047 /* going to try to save the kerning info. After all that lives in the */
1048 /* `FOND' which isn't in the file containing the `POST' resources so */
1049 /* we don't really have access to it. */
1050
1051
1052 /* Finalizer for a memory stream; gets called by FT_Done_Face().
1053 It frees the memory it uses. */
1054 /* from ftmac.c */
1055 static void
1056 memory_stream_close( FT_Stream stream )
1057 {
1058 FT_Memory memory = stream->memory;
1059
1060
1061 FT_FREE( stream->base );
1062
1063 stream->size = 0;
1064 stream->base = 0;
1065 stream->close = 0;
1066 }
1067
1068
1069 /* Create a new memory stream from a buffer and a size. */
1070 /* from ftmac.c */
1071 static FT_Error
1072 new_memory_stream( FT_Library library,
1073 FT_Byte* base,
1074 FT_ULong size,
1075 FT_Stream_CloseFunc close,
1076 FT_Stream *astream )
1077 {
1078 FT_Error error;
1079 FT_Memory memory;
1080 FT_Stream stream;
1081
1082
1083 if ( !library )
1084 return FT_Err_Invalid_Library_Handle;
1085
1086 if ( !base )
1087 return FT_Err_Invalid_Argument;
1088
1089 *astream = 0;
1090 memory = library->memory;
1091 if ( FT_NEW( stream ) )
1092 goto Exit;
1093
1094 FT_Stream_OpenMemory( stream, base, size );
1095
1096 stream->close = close;
1097
1098 *astream = stream;
1099
1100 Exit:
1101 return error;
1102 }
1103
1104
1105 /* Create a new FT_Face given a buffer and a driver name. */
1106 /* from ftmac.c */
1107 static FT_Error
1108 open_face_from_buffer( FT_Library library,
1109 FT_Byte* base,
1110 FT_ULong size,
1111 FT_Long face_index,
1112 const char* driver_name,
1113 FT_Face *aface )
1114 {
1115 FT_Open_Args args;
1116 FT_Error error;
1117 FT_Stream stream;
1118 FT_Memory memory = library->memory;
1119
1120
1121 error = new_memory_stream( library,
1122 base,
1123 size,
1124 memory_stream_close,
1125 &stream );
1126 if ( error )
1127 {
1128 FT_FREE( base );
1129 return error;
1130 }
1131
1132 args.flags = FT_OPEN_STREAM;
1133 args.stream = stream;
1134 if ( driver_name )
1135 {
Werner Lemberg7a024102003-06-18 06:59:57 +00001136 args.flags = args.flags | FT_OPEN_DRIVER;
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001137 args.driver = FT_Get_Module( library, driver_name );
1138 }
1139
1140 error = FT_Open_Face( library, &args, face_index, aface );
1141
1142 if ( error == FT_Err_Ok )
1143 (*aface)->face_flags &= ~FT_FACE_FLAG_EXTERNAL_STREAM;
1144 else
1145 {
1146 FT_Stream_Close( stream );
1147 FT_FREE( stream );
1148 }
1149
1150 return error;
1151 }
1152
1153
1154 /* The resource header says we've got resource_cnt `POST' (type1) */
1155 /* resources in this file. They all need to be coalesced into */
1156 /* one lump which gets passed on to the type1 driver. */
1157 /* Here can be only one PostScript font in a file so face_index */
1158 /* must be 0 (or -1). */
1159 /* */
1160 static FT_Error
1161 Mac_Read_POST_Resource( FT_Library library,
1162 FT_Stream stream,
Werner Lemberg75435332004-02-25 12:58:54 +00001163 FT_Long *offsets,
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001164 FT_Long resource_cnt,
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001165 FT_Long face_index,
1166 FT_Face *aface )
1167 {
1168 FT_Error error = FT_Err_Cannot_Open_Resource;
1169 FT_Memory memory = library->memory;
1170 FT_Byte* pfb_data;
Werner Lembergdc8ad542003-12-09 02:12:14 +00001171 int i, type, flags;
1172 FT_Long len;
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001173 FT_Long pfb_len, pfb_pos, pfb_lenpos;
Werner Lembergdc8ad542003-12-09 02:12:14 +00001174 FT_Long rlen, temp;
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001175
1176
1177 if ( face_index == -1 )
1178 face_index = 0;
1179 if ( face_index != 0 )
Werner Lemberg77c34b82003-05-20 22:06:38 +00001180 return error;
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001181
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001182 /* Find the length of all the POST resources, concatenated. Assume */
1183 /* worst case (each resource in its own section). */
1184 pfb_len = 0;
1185 for ( i = 0; i < resource_cnt; ++i )
1186 {
1187 error = FT_Stream_Seek( stream, offsets[i] );
1188 if ( error )
1189 goto Exit;
1190 if ( FT_READ_LONG( temp ) )
1191 goto Exit;
1192 pfb_len += temp + 6;
1193 }
1194
1195 if ( FT_ALLOC( pfb_data, (FT_Long)pfb_len + 2 ) )
1196 goto Exit;
1197
David Turnerc313c502003-09-11 19:51:54 +00001198 pfb_data[0] = 0x80;
1199 pfb_data[1] = 1; /* Ascii section */
1200 pfb_data[2] = 0; /* 4-byte length, fill in later */
1201 pfb_data[3] = 0;
1202 pfb_data[4] = 0;
1203 pfb_data[5] = 0;
1204 pfb_pos = 7;
David Turnere2d12842003-09-21 17:15:55 +00001205 pfb_lenpos = 2;
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001206
1207 len = 0;
1208 type = 1;
1209 for ( i = 0; i < resource_cnt; ++i )
1210 {
1211 error = FT_Stream_Seek( stream, offsets[i] );
1212 if ( error )
1213 goto Exit2;
1214 if ( FT_READ_LONG( rlen ) )
1215 goto Exit;
1216 if ( FT_READ_USHORT( flags ) )
1217 goto Exit;
1218 rlen -= 2; /* the flags are part of the resource */
1219 if ( ( flags >> 8 ) == type )
1220 len += rlen;
1221 else
1222 {
David Turnerc313c502003-09-11 19:51:54 +00001223 pfb_data[pfb_lenpos ] = (FT_Byte)( len );
1224 pfb_data[pfb_lenpos + 1] = (FT_Byte)( len >> 8 );
1225 pfb_data[pfb_lenpos + 2] = (FT_Byte)( len >> 16 );
1226 pfb_data[pfb_lenpos + 3] = (FT_Byte)( len >> 24 );
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001227
1228 if ( ( flags >> 8 ) == 5 ) /* End of font mark */
1229 break;
1230
1231 pfb_data[pfb_pos++] = 0x80;
1232
1233 type = flags >> 8;
1234 len = rlen;
1235
Werner Lemberg013efd12003-09-17 05:26:33 +00001236 pfb_data[pfb_pos++] = (FT_Byte)type;
1237 pfb_lenpos = (FT_Byte)pfb_pos;
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001238 pfb_data[pfb_pos++] = 0; /* 4-byte length, fill in later */
1239 pfb_data[pfb_pos++] = 0;
1240 pfb_data[pfb_pos++] = 0;
1241 pfb_data[pfb_pos++] = 0;
1242 }
1243
1244 error = FT_Stream_Read( stream, (FT_Byte *)pfb_data + pfb_pos, rlen );
1245 pfb_pos += rlen;
1246 }
1247
1248 pfb_data[pfb_pos++] = 0x80;
1249 pfb_data[pfb_pos++] = 3;
1250
David Turnerc313c502003-09-11 19:51:54 +00001251 pfb_data[pfb_lenpos ] = (FT_Byte)( len );
1252 pfb_data[pfb_lenpos + 1] = (FT_Byte)( len >> 8 );
1253 pfb_data[pfb_lenpos + 2] = (FT_Byte)( len >> 16 );
1254 pfb_data[pfb_lenpos + 3] = (FT_Byte)( len >> 24 );
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001255
1256 return open_face_from_buffer( library,
1257 pfb_data,
1258 pfb_pos,
1259 face_index,
1260 "type1",
1261 aface );
1262
1263 Exit2:
1264 FT_FREE( pfb_data );
1265
1266 Exit:
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001267 return error;
1268 }
1269
1270
1271 /* The resource header says we've got resource_cnt `sfnt' */
1272 /* (TrueType/OpenType) resources in this file. Look through */
1273 /* them for the one indicated by face_index, load it into mem, */
1274 /* pass it on the the truetype driver and return it. */
1275 /* */
1276 static FT_Error
1277 Mac_Read_sfnt_Resource( FT_Library library,
1278 FT_Stream stream,
Werner Lemberg75435332004-02-25 12:58:54 +00001279 FT_Long *offsets,
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001280 FT_Long resource_cnt,
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001281 FT_Long face_index,
1282 FT_Face *aface )
1283 {
1284 FT_Memory memory = library->memory;
1285 FT_Byte* sfnt_data;
1286 FT_Error error;
Werner Lemberg75435332004-02-25 12:58:54 +00001287 FT_Long flag_offset;
Werner Lembergdc8ad542003-12-09 02:12:14 +00001288 FT_Long rlen;
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001289 int is_cff;
1290
1291
1292 if ( face_index == -1 )
1293 face_index = 0;
1294 if ( face_index >= resource_cnt )
1295 return FT_Err_Cannot_Open_Resource;
1296
Werner Lemberg75435332004-02-25 12:58:54 +00001297 flag_offset = offsets[face_index];
1298 error = FT_Stream_Seek( stream, flag_offset );
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001299 if ( error )
1300 goto Exit;
1301
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001302 if ( FT_READ_LONG( rlen ) )
1303 goto Exit;
1304 if ( rlen == -1 )
1305 return FT_Err_Cannot_Open_Resource;
1306
1307 if ( FT_ALLOC( sfnt_data, (FT_Long)rlen ) )
1308 return error;
1309 error = FT_Stream_Read( stream, (FT_Byte *)sfnt_data, rlen );
1310 if ( error )
1311 goto Exit;
1312
1313 is_cff = rlen > 4 && sfnt_data[0] == 'O' &&
1314 sfnt_data[1] == 'T' &&
1315 sfnt_data[2] == 'T' &&
1316 sfnt_data[3] == 'O';
1317
1318 error = open_face_from_buffer( library,
1319 sfnt_data,
1320 rlen,
1321 face_index,
1322 is_cff ? "cff" : "truetype",
1323 aface );
1324
1325 Exit:
1326 return error;
1327 }
1328
1329
1330 /* Check for a valid resource fork header, or a valid dfont */
1331 /* header. In a resource fork the first 16 bytes are repeated */
1332 /* at the location specified by bytes 4-7. In a dfont bytes */
1333 /* 4-7 point to 16 bytes of zeroes instead. */
1334 /* */
1335 static FT_Error
1336 IsMacResource( FT_Library library,
1337 FT_Stream stream,
1338 FT_Long resource_offset,
1339 FT_Long face_index,
1340 FT_Face *aface )
1341 {
Werner Lemberg75435332004-02-25 12:58:54 +00001342 FT_Memory memory = library->memory;
1343 FT_Error error;
1344 FT_Long map_offset, rdara_pos;
1345 FT_Long *data_offsets;
1346 FT_Long count;
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001347
1348
Werner Lemberg75435332004-02-25 12:58:54 +00001349 error = FT_Raccess_Get_HeaderInfo( library, stream, resource_offset,
1350 &map_offset, &rdara_pos );
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001351 if ( error )
Werner Lemberg75435332004-02-25 12:58:54 +00001352 return error;
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001353
Werner Lemberg75435332004-02-25 12:58:54 +00001354 error = FT_Raccess_Get_DataOffsets( library, stream,
1355 map_offset, rdara_pos,
1356 FT_MAKE_TAG( 'P', 'O', 'S', 'T' ),
1357 &data_offsets, &count );
1358 if ( !error )
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001359 {
Werner Lemberg75435332004-02-25 12:58:54 +00001360 error = Mac_Read_POST_Resource( library, stream, data_offsets, count,
1361 face_index, aface );
1362 FT_FREE( data_offsets );
1363 return error;
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001364 }
1365
Werner Lemberg75435332004-02-25 12:58:54 +00001366 error = FT_Raccess_Get_DataOffsets( library, stream,
1367 map_offset, rdara_pos,
1368 FT_MAKE_TAG( 's', 'f', 'n', 't' ),
1369 &data_offsets, &count );
1370 if ( !error )
1371 {
1372 error = Mac_Read_sfnt_Resource( library, stream, data_offsets, count,
1373 face_index, aface );
1374 FT_FREE( data_offsets );
1375 }
1376
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001377 return error;
1378 }
1379
1380
1381 /* Check for a valid macbinary header, and if we find one */
1382 /* check that the (flattened) resource fork in it is valid. */
1383 /* */
1384 static FT_Error
1385 IsMacBinary( FT_Library library,
1386 FT_Stream stream,
1387 FT_Long face_index,
1388 FT_Face *aface )
1389 {
1390 unsigned char header[128];
1391 FT_Error error;
1392 FT_Long dlen, offset;
1393
1394
1395 error = FT_Stream_Seek( stream, 0 );
1396 if ( error )
1397 goto Exit;
1398
1399 error = FT_Stream_Read( stream, (FT_Byte*)header, 128 );
1400 if ( error )
1401 goto Exit;
1402
1403 if ( header[ 0] != 0 ||
1404 header[74] != 0 ||
1405 header[82] != 0 ||
1406 header[ 1] == 0 ||
1407 header[ 1] > 33 ||
1408 header[63] != 0 ||
1409 header[2 + header[1]] != 0 )
1410 return FT_Err_Unknown_File_Format;
1411
1412 dlen = ( header[0x53] << 24 ) |
1413 ( header[0x54] << 16 ) |
1414 ( header[0x55] << 8 ) |
1415 header[0x56];
1416#if 0
1417 rlen = ( header[0x57] << 24 ) |
1418 ( header[0x58] << 16 ) |
1419 ( header[0x59] << 8 ) |
1420 header[0x5a];
1421#endif /* 0 */
1422 offset = 128 + ( ( dlen + 127 ) & ~127 );
1423
1424 return IsMacResource( library, stream, offset, face_index, aface );
1425
1426 Exit:
1427 return error;
1428 }
1429
1430
Werner Lemberg75435332004-02-25 12:58:54 +00001431 static FT_Error
1432 load_face_in_embedded_rfork( FT_Library library,
1433 FT_Stream stream,
1434 FT_Long face_index,
1435 FT_Face *aface,
1436 const FT_Open_Args *args )
1437 {
1438
1439#undef FT_COMPONENT
1440#define FT_COMPONENT trace_raccess
1441
1442 FT_Memory memory = library->memory;
1443 FT_Error error = FT_Err_Unknown_File_Format;
1444 int i;
1445
1446 char * file_names[FT_RACCESS_N_RULES];
1447 FT_Long offsets[FT_RACCESS_N_RULES];
1448 FT_Error errors[FT_RACCESS_N_RULES];
1449
1450 FT_Open_Args args2;
1451 FT_Stream stream2;
1452
1453
1454 FT_Raccess_Guess( library, stream,
1455 args->pathname, file_names, offsets, errors );
1456
1457 for ( i = 0; i < FT_RACCESS_N_RULES; i++ )
1458 {
1459 if ( errors[i] )
1460 {
1461 FT_TRACE3(( "Error[%d] has occurred in rule %d\n", errors[i], i ));
1462 continue;
1463 }
1464
1465 args2.flags = FT_OPEN_PATHNAME;
1466 args2.pathname = file_names[i] ? file_names[i] : args->pathname;
1467
1468 FT_TRACE3(( "Try rule %d: %s (offset=%d) ...",
1469 i, args2.pathname, offsets[i] ));
1470
1471 error = FT_Stream_New( library, &args2, &stream2 );
1472 if ( error )
1473 {
1474 FT_TRACE3(( "failed\n" ));
1475 continue;
1476 }
1477
1478 error = IsMacResource( library, stream2, offsets[i],
1479 face_index, aface );
1480 FT_Stream_Close( stream2 );
1481
1482 FT_TRACE3(( "%s\n", error ? "failed": "successful" ));
1483
1484 if ( !error )
1485 break;
1486 }
1487
1488 for (i = 0; i < FT_RACCESS_N_RULES; i++)
1489 {
1490 if ( file_names[i] )
1491 FT_FREE( file_names[i] );
1492 }
1493
1494 /* Caller (load_mac_face) requires FT_Err_Unknown_File_Format. */
1495 if ( error )
1496 error = FT_Err_Unknown_File_Format;
1497
1498 return error;
1499
1500#undef FT_COMPONENT
1501#define FT_COMPONENT trace_objs
1502
1503 }
1504
1505
1506 /* Check for some macintosh formats. */
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001507 /* Is this a macbinary file? If so look at the resource fork. */
1508 /* Is this a mac dfont file? */
1509 /* Is this an old style resource fork? (in data) */
Werner Lemberg75435332004-02-25 12:58:54 +00001510 /* Else call load_face_in_embedded_rfork to try extra rules */
1511 /* (defined in `ftrfork.c'). */
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001512 /* */
1513 static FT_Error
1514 load_mac_face( FT_Library library,
1515 FT_Stream stream,
1516 FT_Long face_index,
1517 FT_Face *aface,
1518 const FT_Open_Args *args )
1519 {
1520 FT_Error error;
1521 FT_UNUSED( args );
1522
1523
1524 error = IsMacBinary( library, stream, face_index, aface );
1525 if ( FT_ERROR_BASE( error ) == FT_Err_Unknown_File_Format )
Werner Lemberg75435332004-02-25 12:58:54 +00001526 {
1527
1528#undef FT_COMPONENT
1529#define FT_COMPONENT trace_raccess
1530
1531 FT_TRACE3(( "Try as dfont: %s ...", args->pathname ));
1532
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001533 error = IsMacResource( library, stream, 0, face_index, aface );
1534
Werner Lemberg75435332004-02-25 12:58:54 +00001535 FT_TRACE3(( "%s\n", error ? "failed" : "successful" ));
David Turnere2d12842003-09-21 17:15:55 +00001536
Werner Lemberg75435332004-02-25 12:58:54 +00001537#undef FT_COMPONENT
1538#define FT_COMPONENT trace_objs
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001539
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001540 }
1541
Werner Lemberg75435332004-02-25 12:58:54 +00001542 if ( ( FT_ERROR_BASE( error ) == FT_Err_Unknown_File_Format ||
1543 FT_ERROR_BASE( error ) == FT_Err_Invalid_Stream_Operation ) &&
1544 ( args->flags & FT_OPEN_PATHNAME ) )
1545 error = load_face_in_embedded_rfork( library, stream,
1546 face_index, aface, args );
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001547 return error;
1548 }
1549
1550#endif /* !FT_MACINTOSH && FT_CONFIG_OPTION_MAC_FONTS */
1551
1552
Werner Lemberg90a03302000-11-07 17:21:11 +00001553 /* documentation is in freetype.h */
1554
Werner Lembergf814d0f2001-06-27 16:18:10 +00001555 FT_EXPORT_DEF( FT_Error )
Werner Lembergc4c373c2002-10-07 09:15:20 +00001556 FT_Open_Face( FT_Library library,
1557 const FT_Open_Args* args,
1558 FT_Long face_index,
1559 FT_Face *aface )
David Turnerd2b1f351999-12-16 23:11:37 +00001560 {
1561 FT_Error error;
1562 FT_Driver driver;
1563 FT_Memory memory;
David Turnercda32b72000-02-10 16:14:35 +00001564 FT_Stream stream;
David Turnerd2b1f351999-12-16 23:11:37 +00001565 FT_Face face = 0;
1566 FT_ListNode node = 0;
David Turnerc5cdf8b2000-07-27 21:40:22 +00001567 FT_Bool external_stream;
Werner Lemberg547a2522000-02-16 08:23:58 +00001568
Werner Lemberg58b17f92000-07-27 23:29:08 +00001569
Werner Lembergf9b03752000-09-11 22:50:13 +00001570 /* test for valid `library' delayed to */
Werner Lemberg75435332004-02-25 12:58:54 +00001571 /* FT_Stream_New() */
David Turnerd2b1f351999-12-16 23:11:37 +00001572
Werner Lembergce235ea2005-05-17 20:35:23 +00001573 if ( ( !aface && face_index >= 0 ) || !args )
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001574 return FT_Err_Invalid_Argument;
1575
David Turnerb08fe2d2002-08-27 20:20:29 +00001576 external_stream = FT_BOOL( ( args->flags & FT_OPEN_STREAM ) &&
Werner Lemberg8eb03532001-06-19 23:03:41 +00001577 args->stream );
David Turnerc5cdf8b2000-07-27 21:40:22 +00001578
David Turnercda32b72000-02-10 16:14:35 +00001579 /* create input stream */
Werner Lemberg75435332004-02-25 12:58:54 +00001580 error = FT_Stream_New( library, args, &stream );
Werner Lembergdeb4e982000-06-29 03:14:25 +00001581 if ( error )
1582 goto Exit;
David Turnercda32b72000-02-10 16:14:35 +00001583
David Turnerd2b1f351999-12-16 23:11:37 +00001584 memory = library->memory;
1585
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001586 /* If the font driver is specified in the `args' structure, use */
Werner Lembergdeb4e982000-06-29 03:14:25 +00001587 /* it. Otherwise, we scan the list of registered drivers. */
David Turnerb08fe2d2002-08-27 20:20:29 +00001588 if ( ( args->flags & FT_OPEN_DRIVER ) && args->driver )
David Turner7663f222000-02-13 13:37:38 +00001589 {
Werner Lemberga929ba92000-06-25 06:47:11 +00001590 driver = FT_DRIVER( args->driver );
David Turnerf0df85b2000-06-22 00:17:42 +00001591
1592 /* not all modules are drivers, so check... */
Werner Lemberga929ba92000-06-25 06:47:11 +00001593 if ( FT_MODULE_IS_DRIVER( driver ) )
David Turner7663f222000-02-13 13:37:38 +00001594 {
Werner Lemberg3c403e42002-08-06 21:47:40 +00001595 FT_Int num_params = 0;
1596 FT_Parameter* params = 0;
1597
Werner Lemberga929ba92000-06-25 06:47:11 +00001598
David Turnerb08fe2d2002-08-27 20:20:29 +00001599 if ( args->flags & FT_OPEN_PARAMS )
David Turner4f2c5542000-05-12 10:19:41 +00001600 {
1601 num_params = args->num_params;
1602 params = args->params;
1603 }
David Turnere49ab252000-05-16 23:44:38 +00001604
David Turner4f2c5542000-05-12 10:19:41 +00001605 error = open_face( driver, stream, face_index,
1606 num_params, params, &face );
Werner Lemberg547a2522000-02-16 08:23:58 +00001607 if ( !error )
1608 goto Success;
David Turner7663f222000-02-13 13:37:38 +00001609 }
1610 else
1611 error = FT_Err_Invalid_Handle;
1612
Werner Lemberg75435332004-02-25 12:58:54 +00001613 FT_Stream_Free( stream, external_stream );
David Turner7663f222000-02-13 13:37:38 +00001614 goto Fail;
1615 }
Just van Rossum1e5754f2000-03-02 10:52:57 +00001616 else
David Turnerd2b1f351999-12-16 23:11:37 +00001617 {
1618 /* check each font driver for an appropriate format */
David Turnerf0df85b2000-06-22 00:17:42 +00001619 FT_Module* cur = library->modules;
1620 FT_Module* limit = cur + library->num_modules;
David Turnerd2b1f351999-12-16 23:11:37 +00001621
Werner Lemberga929ba92000-06-25 06:47:11 +00001622
David Turnerd2b1f351999-12-16 23:11:37 +00001623 for ( ; cur < limit; cur++ )
1624 {
David Turnerf0df85b2000-06-22 00:17:42 +00001625 /* not all modules are font drivers, so check... */
Werner Lemberga929ba92000-06-25 06:47:11 +00001626 if ( FT_MODULE_IS_DRIVER( cur[0] ) )
David Turnerd2b1f351999-12-16 23:11:37 +00001627 {
David Turner4f2c5542000-05-12 10:19:41 +00001628 FT_Int num_params = 0;
1629 FT_Parameter* params = 0;
David Turnere49ab252000-05-16 23:44:38 +00001630
Werner Lemberg3c403e42002-08-06 21:47:40 +00001631
Werner Lemberga929ba92000-06-25 06:47:11 +00001632 driver = FT_DRIVER( cur[0] );
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001633
David Turnerb08fe2d2002-08-27 20:20:29 +00001634 if ( args->flags & FT_OPEN_PARAMS )
David Turner4f2c5542000-05-12 10:19:41 +00001635 {
1636 num_params = args->num_params;
1637 params = args->params;
1638 }
David Turnere49ab252000-05-16 23:44:38 +00001639
Graham Asherd53cf1d2002-07-18 15:04:29 +00001640 error = open_face( driver, stream, face_index,
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001641 num_params, params, &face );
David Turnerd2b1f351999-12-16 23:11:37 +00001642 if ( !error )
1643 goto Success;
1644
Werner Lemberg79860702001-06-08 21:17:29 +00001645 if ( FT_ERROR_BASE( error ) != FT_Err_Unknown_File_Format )
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001646 goto Fail3;
David Turnerd2b1f351999-12-16 23:11:37 +00001647 }
1648 }
1649
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001650 Fail3:
1651 /* If we are on the mac, and we get an FT_Err_Invalid_Stream_Operation */
1652 /* it may be because we have an empty data fork, so we need to check */
1653 /* the resource fork. */
1654 if ( FT_ERROR_BASE( error ) != FT_Err_Unknown_File_Format &&
1655 FT_ERROR_BASE( error ) != FT_Err_Invalid_Stream_Operation )
1656 goto Fail2;
1657
Werner Lembergdc8ad542003-12-09 02:12:14 +00001658#if !defined( FT_MACINTOSH ) && defined( FT_CONFIG_OPTION_MAC_FONTS )
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001659 error = load_mac_face( library, stream, face_index, aface, args );
1660 if ( !error )
1661 {
1662 /* We don't want to go to Success here. We've already done that. */
1663 /* On the other hand, if we succeeded we still need to close this */
1664 /* stream (we opened a different stream which extracted the */
1665 /* interesting information out of this stream here. That stream */
1666 /* will still be open and the face will point to it). */
Werner Lemberg75435332004-02-25 12:58:54 +00001667 FT_Stream_Free( stream, external_stream );
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001668 return error;
1669 }
1670
1671 if ( FT_ERROR_BASE( error ) != FT_Err_Unknown_File_Format )
1672 goto Fail2;
Werner Lembergdc8ad542003-12-09 02:12:14 +00001673#endif /* !FT_MACINTOSH && FT_CONFIG_OPTION_MAC_FONTS */
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001674
David Turnerd2b1f351999-12-16 23:11:37 +00001675 /* no driver is able to handle this format */
1676 error = FT_Err_Unknown_File_Format;
David Turnerebe85f52001-05-11 14:25:57 +00001677
1678 Fail2:
Werner Lemberg75435332004-02-25 12:58:54 +00001679 FT_Stream_Free( stream, external_stream );
David Turnercda32b72000-02-10 16:14:35 +00001680 goto Fail;
David Turnerd2b1f351999-12-16 23:11:37 +00001681 }
1682
1683 Success:
Werner Lembergf9b03752000-09-11 22:50:13 +00001684 FT_TRACE4(( "FT_Open_Face: New face object, adding to list\n" ));
David Turnerd2b1f351999-12-16 23:11:37 +00001685
Werner Lembergdeb4e982000-06-29 03:14:25 +00001686 /* set the FT_FACE_FLAG_EXTERNAL_STREAM bit for FT_Done_Face */
David Turnerc5cdf8b2000-07-27 21:40:22 +00001687 if ( external_stream )
David Turnerf0df85b2000-06-22 00:17:42 +00001688 face->face_flags |= FT_FACE_FLAG_EXTERNAL_STREAM;
1689
Werner Lemberg547a2522000-02-16 08:23:58 +00001690 /* add the face object to its driver's list */
David Turnere459d742002-03-22 13:52:37 +00001691 if ( FT_NEW( node ) )
David Turnerd2b1f351999-12-16 23:11:37 +00001692 goto Fail;
1693
1694 node->data = face;
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001695 /* don't assume driver is the same as face->driver, so use */
1696 /* face->driver instead. */
Just van Rossum7eef5362000-03-05 16:07:58 +00001697 FT_List_Add( &face->driver->faces_list, node );
David Turnerd2b1f351999-12-16 23:11:37 +00001698
Werner Lemberg547a2522000-02-16 08:23:58 +00001699 /* now allocate a glyph slot object for the face */
Werner Lembergb9ee7372005-05-20 21:52:19 +00001700 FT_TRACE4(( "FT_Open_Face: Creating glyph slot\n" ));
David Turnerd2b1f351999-12-16 23:11:37 +00001701
David Turner92f30c82005-10-17 21:17:20 +00001702 if ( face_index >= 0 )
David Turnerd2b1f351999-12-16 23:11:37 +00001703 {
David Turner92f30c82005-10-17 21:17:20 +00001704 error = FT_New_GlyphSlot( face, NULL );
Werner Lembergdeb4e982000-06-29 03:14:25 +00001705 if ( error )
1706 goto Fail;
1707
David Turner92f30c82005-10-17 21:17:20 +00001708 /* finally, allocate a size object for the face */
1709 {
1710 FT_Size size;
1711
1712
1713 FT_TRACE4(( "FT_Open_Face: Creating size object\n" ));
1714
1715 error = FT_New_Size( face, &size );
1716 if ( error )
1717 goto Fail;
1718
1719 face->size = size;
1720 }
David Turnerd2b1f351999-12-16 23:11:37 +00001721 }
Werner Lemberg7880dd62000-01-10 17:19:45 +00001722
Wu, Chia-I (吳佳一)e5ff0592006-01-15 06:00:49 +00001723 /* some checks */
1724
1725 if ( FT_IS_SCALABLE( face ) )
1726 {
1727 if ( face->height < 0 )
Werner Lembergbe3c9812006-01-27 14:16:16 +00001728 face->height = (FT_Short)-face->height;
Wu, Chia-I (吳佳一)e5ff0592006-01-15 06:00:49 +00001729
1730 if ( !FT_HAS_VERTICAL( face ) )
Werner Lembergbe3c9812006-01-27 14:16:16 +00001731 face->max_advance_height = (FT_Short)face->height;
Wu, Chia-I (吳佳一)e5ff0592006-01-15 06:00:49 +00001732 }
1733
1734 if ( FT_HAS_FIXED_SIZES( face ) )
1735 {
Werner Lemberg1723dcc2006-01-15 07:30:32 +00001736 FT_Int i;
Wu, Chia-I (吳佳一)e5ff0592006-01-15 06:00:49 +00001737
David Turnercda2d952006-02-16 22:45:31 +00001738
Wu, Chia-I (吳佳一)e5ff0592006-01-15 06:00:49 +00001739 for ( i = 0; i < face->num_fixed_sizes; i++ )
1740 {
1741 FT_Bitmap_Size* bsize = face->available_sizes + i;
1742
1743
1744 if ( bsize->height < 0 )
Werner Lembergbe3c9812006-01-27 14:16:16 +00001745 bsize->height = (FT_Short)-bsize->height;
Wu, Chia-I (吳佳一)e5ff0592006-01-15 06:00:49 +00001746 if ( bsize->x_ppem < 0 )
Werner Lembergbe3c9812006-01-27 14:16:16 +00001747 bsize->x_ppem = (FT_Short)-bsize->x_ppem;
Wu, Chia-I (吳佳一)e5ff0592006-01-15 06:00:49 +00001748 if ( bsize->y_ppem < 0 )
1749 bsize->y_ppem = -bsize->y_ppem;
1750 }
1751 }
1752
David Turner54e75742000-11-04 02:52:02 +00001753 /* initialize internal face data */
1754 {
1755 FT_Face_Internal internal = face->internal;
David Turner61d6b2b2001-05-16 17:49:07 +00001756
David Turner37379e22000-03-28 11:22:31 +00001757
David Turner54e75742000-11-04 02:52:02 +00001758 internal->transform_matrix.xx = 0x10000L;
1759 internal->transform_matrix.xy = 0;
1760 internal->transform_matrix.yx = 0;
1761 internal->transform_matrix.yy = 0x10000L;
David Turner61d6b2b2001-05-16 17:49:07 +00001762
David Turner54e75742000-11-04 02:52:02 +00001763 internal->transform_delta.x = 0;
1764 internal->transform_delta.y = 0;
1765 }
David Turner37379e22000-03-28 11:22:31 +00001766
Werner Lembergce235ea2005-05-17 20:35:23 +00001767 if ( aface )
1768 *aface = face;
Werner Lembergb2d02532005-11-04 06:58:49 +00001769 else
1770 FT_Done_Face( face );
1771
David Turnerd2b1f351999-12-16 23:11:37 +00001772 goto Exit;
1773
1774 Fail:
1775 FT_Done_Face( face );
1776
David Turnerd2b1f351999-12-16 23:11:37 +00001777 Exit:
1778 FT_TRACE4(( "FT_Open_Face: Return %d\n", error ));
Werner Lembergdeb4e982000-06-29 03:14:25 +00001779
David Turnerd2b1f351999-12-16 23:11:37 +00001780 return error;
1781 }
1782
1783
Werner Lemberg90a03302000-11-07 17:21:11 +00001784 /* documentation is in freetype.h */
1785
Werner Lembergf814d0f2001-06-27 16:18:10 +00001786 FT_EXPORT_DEF( FT_Error )
1787 FT_Attach_File( FT_Face face,
1788 const char* filepathname )
David Turner7663f222000-02-13 13:37:38 +00001789 {
David Turner37379e22000-03-28 11:22:31 +00001790 FT_Open_Args open;
David Turner7663f222000-02-13 13:37:38 +00001791
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001792
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001793 /* test for valid `face' delayed to FT_Attach_Stream() */
1794
1795 if ( !filepathname )
1796 return FT_Err_Invalid_Argument;
1797
Werner Lembergb8fdcd62004-08-03 03:28:11 +00001798 open.stream = NULL;
David Turnerb08fe2d2002-08-27 20:20:29 +00001799 open.flags = FT_OPEN_PATHNAME;
David Turner4f2c5542000-05-12 10:19:41 +00001800 open.pathname = (char*)filepathname;
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001801
David Turner7663f222000-02-13 13:37:38 +00001802 return FT_Attach_Stream( face, &open );
1803 }
Werner Lemberg547a2522000-02-16 08:23:58 +00001804
David Turnere49ab252000-05-16 23:44:38 +00001805
Werner Lemberg90a03302000-11-07 17:21:11 +00001806 /* documentation is in freetype.h */
1807
Werner Lembergf814d0f2001-06-27 16:18:10 +00001808 FT_EXPORT_DEF( FT_Error )
1809 FT_Attach_Stream( FT_Face face,
1810 FT_Open_Args* parameters )
David Turner7663f222000-02-13 13:37:38 +00001811 {
1812 FT_Stream stream;
1813 FT_Error error;
1814 FT_Driver driver;
David Turnere49ab252000-05-16 23:44:38 +00001815
David Turneref3c1262002-03-14 09:22:48 +00001816 FT_Driver_Class clazz;
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001817
Werner Lemberga929ba92000-06-25 06:47:11 +00001818
Werner Lemberg75435332004-02-25 12:58:54 +00001819 /* test for valid `parameters' delayed to FT_Stream_New() */
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001820
1821 if ( !face )
1822 return FT_Err_Invalid_Face_Handle;
David Turnere49ab252000-05-16 23:44:38 +00001823
David Turner7663f222000-02-13 13:37:38 +00001824 driver = face->driver;
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001825 if ( !driver )
1826 return FT_Err_Invalid_Driver_Handle;
1827
Werner Lemberg75435332004-02-25 12:58:54 +00001828 error = FT_Stream_New( driver->root.library, parameters, &stream );
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001829 if ( error )
1830 goto Exit;
David Turnere49ab252000-05-16 23:44:38 +00001831
David Turner7663f222000-02-13 13:37:38 +00001832 /* we implement FT_Attach_Stream in each driver through the */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001833 /* `attach_file' interface */
1834
David Turner7663f222000-02-13 13:37:38 +00001835 error = FT_Err_Unimplemented_Feature;
David Turnerf0df85b2000-06-22 00:17:42 +00001836 clazz = driver->clazz;
Werner Lemberga929ba92000-06-25 06:47:11 +00001837 if ( clazz->attach_file )
David Turnerf0df85b2000-06-22 00:17:42 +00001838 error = clazz->attach_file( face, stream );
David Turnere49ab252000-05-16 23:44:38 +00001839
David Turner7663f222000-02-13 13:37:38 +00001840 /* close the attached stream */
Werner Lemberg75435332004-02-25 12:58:54 +00001841 FT_Stream_Free( stream,
Werner Lemberg58b17f92000-07-27 23:29:08 +00001842 (FT_Bool)( parameters->stream &&
David Turnerb08fe2d2002-08-27 20:20:29 +00001843 ( parameters->flags & FT_OPEN_STREAM ) ) );
David Turnere49ab252000-05-16 23:44:38 +00001844
David Turner7663f222000-02-13 13:37:38 +00001845 Exit:
1846 return error;
1847 }
1848
1849
Werner Lemberg90a03302000-11-07 17:21:11 +00001850 /* documentation is in freetype.h */
1851
Werner Lembergf814d0f2001-06-27 16:18:10 +00001852 FT_EXPORT_DEF( FT_Error )
1853 FT_Done_Face( FT_Face face )
David Turnerd2b1f351999-12-16 23:11:37 +00001854 {
Werner Lemberga929ba92000-06-25 06:47:11 +00001855 FT_Error error;
1856 FT_Driver driver;
1857 FT_Memory memory;
1858 FT_ListNode node;
1859
David Turnerd2b1f351999-12-16 23:11:37 +00001860
David Turnerf0df85b2000-06-22 00:17:42 +00001861 error = FT_Err_Invalid_Face_Handle;
1862 if ( face && face->driver )
David Turnerd2b1f351999-12-16 23:11:37 +00001863 {
David Turnerf0df85b2000-06-22 00:17:42 +00001864 driver = face->driver;
1865 memory = driver->root.memory;
Werner Lembergdeb4e982000-06-29 03:14:25 +00001866
David Turnerf0df85b2000-06-22 00:17:42 +00001867 /* find face in driver's list */
1868 node = FT_List_Find( &driver->faces_list, face );
1869 if ( node )
1870 {
1871 /* remove face object from the driver's list */
1872 FT_List_Remove( &driver->faces_list, node );
David Turnere459d742002-03-22 13:52:37 +00001873 FT_FREE( node );
Werner Lembergdeb4e982000-06-29 03:14:25 +00001874
David Turnerf0df85b2000-06-22 00:17:42 +00001875 /* now destroy the object proper */
1876 destroy_face( memory, face, driver );
1877 error = FT_Err_Ok;
1878 }
David Turnerd2b1f351999-12-16 23:11:37 +00001879 }
David Turnerd2b1f351999-12-16 23:11:37 +00001880 return error;
1881 }
1882
1883
Werner Lemberg90a03302000-11-07 17:21:11 +00001884 /* documentation is in ftobjs.h */
1885
Werner Lembergf814d0f2001-06-27 16:18:10 +00001886 FT_EXPORT_DEF( FT_Error )
1887 FT_New_Size( FT_Face face,
1888 FT_Size *asize )
David Turnerd2b1f351999-12-16 23:11:37 +00001889 {
Werner Lembergf8ba2002002-03-30 13:16:35 +00001890 FT_Error error;
1891 FT_Memory memory;
1892 FT_Driver driver;
David Turneref3c1262002-03-14 09:22:48 +00001893 FT_Driver_Class clazz;
David Turnerd2b1f351999-12-16 23:11:37 +00001894
Werner Lembergf8ba2002002-03-30 13:16:35 +00001895 FT_Size size = 0;
1896 FT_ListNode node = 0;
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001897
Werner Lemberga929ba92000-06-25 06:47:11 +00001898
Werner Lembergb48a6092000-07-09 19:15:30 +00001899 if ( !face )
1900 return FT_Err_Invalid_Face_Handle;
1901
1902 if ( !asize )
1903 return FT_Err_Invalid_Size_Handle;
1904
1905 if ( !face->driver )
1906 return FT_Err_Invalid_Driver_Handle;
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001907
Werner Lembergdeb4e982000-06-29 03:14:25 +00001908 *asize = 0;
1909
David Turnerf0df85b2000-06-22 00:17:42 +00001910 driver = face->driver;
1911 clazz = driver->clazz;
1912 memory = face->memory;
David Turnerd2b1f351999-12-16 23:11:37 +00001913
1914 /* Allocate new size object and perform basic initialisation */
David Turnere459d742002-03-22 13:52:37 +00001915 if ( FT_ALLOC( size, clazz->size_object_size ) || FT_NEW( node ) )
David Turnerd2b1f351999-12-16 23:11:37 +00001916 goto Exit;
1917
1918 size->face = face;
David Turner61d6b2b2001-05-16 17:49:07 +00001919
David Turner54e75742000-11-04 02:52:02 +00001920 /* for now, do not use any internal fields in size objects */
1921 size->internal = 0;
David Turnerd2b1f351999-12-16 23:11:37 +00001922
Werner Lemberga929ba92000-06-25 06:47:11 +00001923 if ( clazz->init_size )
David Turnerf0df85b2000-06-22 00:17:42 +00001924 error = clazz->init_size( size );
David Turnerd2b1f351999-12-16 23:11:37 +00001925
1926 /* in case of success, add to the face's list */
1927 if ( !error )
1928 {
1929 *asize = size;
1930 node->data = size;
1931 FT_List_Add( &face->sizes_list, node );
David Turnerd2b1f351999-12-16 23:11:37 +00001932 }
1933
1934 Exit:
1935 if ( error )
1936 {
David Turnere459d742002-03-22 13:52:37 +00001937 FT_FREE( node );
1938 FT_FREE( size );
David Turnerd2b1f351999-12-16 23:11:37 +00001939 }
1940
1941 return error;
1942 }
1943
1944
Werner Lemberg90a03302000-11-07 17:21:11 +00001945 /* documentation is in ftobjs.h */
1946
Werner Lembergf814d0f2001-06-27 16:18:10 +00001947 FT_EXPORT_DEF( FT_Error )
1948 FT_Done_Size( FT_Size size )
David Turnerd2b1f351999-12-16 23:11:37 +00001949 {
1950 FT_Error error;
1951 FT_Driver driver;
1952 FT_Memory memory;
1953 FT_Face face;
1954 FT_ListNode node;
1955
1956
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001957 if ( !size )
David Turnerd2b1f351999-12-16 23:11:37 +00001958 return FT_Err_Invalid_Size_Handle;
1959
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001960 face = size->face;
1961 if ( !face )
1962 return FT_Err_Invalid_Face_Handle;
1963
1964 driver = face->driver;
David Turnerd2b1f351999-12-16 23:11:37 +00001965 if ( !driver )
1966 return FT_Err_Invalid_Driver_Handle;
1967
David Turnerf0df85b2000-06-22 00:17:42 +00001968 memory = driver->root.memory;
David Turnerd2b1f351999-12-16 23:11:37 +00001969
1970 error = FT_Err_Ok;
David Turnerd2b1f351999-12-16 23:11:37 +00001971 node = FT_List_Find( &face->sizes_list, size );
1972 if ( node )
1973 {
1974 FT_List_Remove( &face->sizes_list, node );
David Turnere459d742002-03-22 13:52:37 +00001975 FT_FREE( node );
David Turnerd2b1f351999-12-16 23:11:37 +00001976
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001977 if ( face->size == size )
David Turnerd2b1f351999-12-16 23:11:37 +00001978 {
1979 face->size = 0;
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001980 if ( face->sizes_list.head )
David Turnerd2b1f351999-12-16 23:11:37 +00001981 face->size = (FT_Size)(face->sizes_list.head->data);
1982 }
1983
1984 destroy_size( memory, size, driver );
1985 }
1986 else
1987 error = FT_Err_Invalid_Size_Handle;
1988
Werner Lembergcf24d512001-06-18 14:23:45 +00001989 return error;
David Turnerd2b1f351999-12-16 23:11:37 +00001990 }
1991
1992
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00001993 /* documentation is in ftobjs.h */
1994
1995 FT_BASE_DEF( FT_Error )
1996 FT_Match_Size( FT_Face face,
1997 FT_Size_Request req,
1998 FT_Bool ignore_width,
1999 FT_ULong* index )
2000 {
2001 FT_Int i;
2002 FT_Long w, h;
2003
2004
2005 if ( !FT_HAS_FIXED_SIZES( face ) )
2006 return FT_Err_Invalid_Face_Handle;
2007
2008 /* FT_Bitmap_Size doesn't provide enough info... */
2009 if ( req->type != FT_SIZE_REQUEST_TYPE_NOMINAL )
2010 return FT_Err_Unimplemented_Feature;
2011
Werner Lemberg9cc4aed2006-01-26 21:03:58 +00002012 w = FT_REQUEST_WIDTH ( req );
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002013 h = FT_REQUEST_HEIGHT( req );
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002014
2015 if ( req->width && !req->height )
2016 h = w;
2017 else if ( !req->width && req->height )
2018 w = h;
2019
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002020 w = FT_PIX_ROUND( w );
2021 h = FT_PIX_ROUND( h );
2022
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002023 for ( i = 0; i < face->num_fixed_sizes; i++ )
2024 {
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002025 FT_Bitmap_Size* bsize = face->available_sizes + i;
2026
2027
2028 if ( h != FT_PIX_ROUND( bsize->y_ppem ) )
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002029 continue;
2030
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002031 if ( w == FT_PIX_ROUND( bsize->x_ppem ) || ignore_width )
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002032 {
2033 if ( index )
2034 *index = (FT_ULong)i;
2035
2036 return FT_Err_Ok;
2037 }
2038 }
2039
2040 return FT_Err_Invalid_Pixel_Size;
2041 }
2042
2043
Wu, Chia-I (吳佳一)212aee02006-01-15 06:24:53 +00002044 /* documentation is in ftobjs.h */
2045
2046 FT_BASE_DEF( void )
Wu, Chia-I (吳佳一)ea1e8d32006-01-15 15:01:45 +00002047 ft_synthesize_vertical_metrics( FT_Glyph_Metrics* metrics,
2048 FT_Pos advance )
Wu, Chia-I (吳佳一)212aee02006-01-15 06:24:53 +00002049 {
Werner Lemberg1723dcc2006-01-15 07:30:32 +00002050 /* the factor 1.2 is a heuristical value */
Wu, Chia-I (吳佳一)212aee02006-01-15 06:24:53 +00002051 if ( !advance )
2052 advance = metrics->height * 12 / 10;
2053
2054 metrics->vertBearingX = -( metrics->width / 2 );
2055 metrics->vertBearingY = ( advance - metrics->height ) / 2;
2056 metrics->vertAdvance = advance;
2057 }
2058
2059
Werner Lembergf814d0f2001-06-27 16:18:10 +00002060 static void
2061 ft_recompute_scaled_metrics( FT_Face face,
2062 FT_Size_Metrics* metrics )
Werner Lembergdeb4e982000-06-29 03:14:25 +00002063 {
Werner Lemberga929ba92000-06-25 06:47:11 +00002064 /* Compute root ascender, descender, test height, and max_advance */
Werner Lembergdeb4e982000-06-29 03:14:25 +00002065
Wu, Chia-I (吳佳一)dcb8b712005-12-16 14:27:14 +00002066 metrics->ascender = FT_MulFix( face->ascender,
2067 metrics->y_scale );
Werner Lemberga929ba92000-06-25 06:47:11 +00002068
Wu, Chia-I (吳佳一)dcb8b712005-12-16 14:27:14 +00002069 metrics->descender = FT_MulFix( face->descender,
2070 metrics->y_scale );
Werner Lemberga929ba92000-06-25 06:47:11 +00002071
Wu, Chia-I (吳佳一)dcb8b712005-12-16 14:27:14 +00002072 metrics->height = FT_MulFix( face->height,
2073 metrics->y_scale );
Werner Lemberga929ba92000-06-25 06:47:11 +00002074
Wu, Chia-I (吳佳一)dcb8b712005-12-16 14:27:14 +00002075 metrics->max_advance = FT_MulFix( face->max_advance_width,
2076 metrics->x_scale );
Werner Lemberga929ba92000-06-25 06:47:11 +00002077 }
2078
2079
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002080 FT_BASE_DEF( void )
2081 FT_Select_Metrics( FT_Face face,
2082 FT_ULong strike_index )
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002083 {
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002084 FT_Size_Metrics* metrics;
2085 FT_Bitmap_Size* bsize;
2086
2087
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002088 metrics = &face->size->metrics;
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002089 bsize = face->available_sizes + strike_index;
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002090
Werner Lembergbe3c9812006-01-27 14:16:16 +00002091 metrics->x_ppem = (FT_UShort)( ( bsize->x_ppem + 32 ) >> 6 );
2092 metrics->y_ppem = (FT_UShort)( ( bsize->y_ppem + 32 ) >> 6 );
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002093
2094 if ( FT_IS_SCALABLE( face ) )
2095 {
2096 metrics->x_scale = FT_DivFix( bsize->x_ppem,
2097 face->units_per_EM );
2098 metrics->y_scale = FT_DivFix( bsize->y_ppem,
2099 face->units_per_EM );
2100
2101 ft_recompute_scaled_metrics( face, metrics );
2102 }
2103 else
2104 {
Werner Lemberg1723dcc2006-01-15 07:30:32 +00002105 metrics->x_scale = 1L << 22;
2106 metrics->y_scale = 1L << 22;
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002107 metrics->ascender = bsize->y_ppem;
2108 metrics->descender = 0;
2109 metrics->height = bsize->height << 6;
2110 metrics->max_advance = bsize->x_ppem;
2111 }
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002112 }
2113
2114
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002115 FT_BASE_DEF( void )
2116 FT_Request_Metrics( FT_Face face,
2117 FT_Size_Request req )
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002118 {
2119 FT_Driver_Class clazz;
2120 FT_Size_Metrics* metrics;
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002121
2122
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002123 clazz = face->driver->clazz;
2124 metrics = &face->size->metrics;
2125
2126 if ( FT_IS_SCALABLE( face ) )
2127 {
2128 FT_Long w, h, scaled_w, scaled_h;
2129
2130
2131 switch ( req->type )
2132 {
2133 case FT_SIZE_REQUEST_TYPE_NOMINAL:
2134 w = h = face->units_per_EM;
2135 break;
Werner Lembergf1c2b912006-01-13 14:53:28 +00002136
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002137 case FT_SIZE_REQUEST_TYPE_REAL_DIM:
2138 w = h = face->ascender - face->descender;
2139 break;
Werner Lembergf1c2b912006-01-13 14:53:28 +00002140
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002141 case FT_SIZE_REQUEST_TYPE_CELL:
2142 w = face->max_advance_width;
2143 h = face->ascender - face->descender;
2144 break;
Werner Lembergf1c2b912006-01-13 14:53:28 +00002145
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002146 case FT_SIZE_REQUEST_TYPE_BBOX:
2147 w = face->bbox.xMax - face->bbox.xMin;
2148 h = face->bbox.yMax - face->bbox.yMin;
2149 break;
Werner Lembergf1c2b912006-01-13 14:53:28 +00002150
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002151 default:
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002152 /* this never happens */
2153 return;
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002154 break;
2155 }
2156
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002157 /* to be on the safe side */
Wu, Chia-I (吳佳一)e5ff0592006-01-15 06:00:49 +00002158 if ( w < 0 )
2159 w = -w;
2160
2161 if ( h < 0 )
2162 h = -h;
2163
Werner Lemberg9cc4aed2006-01-26 21:03:58 +00002164 scaled_w = FT_REQUEST_WIDTH ( req );
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002165 scaled_h = FT_REQUEST_HEIGHT( req );
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002166
2167 /* determine scales */
2168 if ( req->width )
2169 {
2170 metrics->x_scale = FT_DivFix( scaled_w, w );
2171
2172 if ( req->height )
2173 {
2174 metrics->y_scale = FT_DivFix( scaled_h, h );
2175
2176 if ( req->type == FT_SIZE_REQUEST_TYPE_CELL )
2177 {
2178 if ( metrics->y_scale > metrics->x_scale )
2179 metrics->y_scale = metrics->x_scale;
2180 else
2181 metrics->x_scale = metrics->y_scale;
2182 }
2183 }
2184 else
2185 {
2186 metrics->y_scale = metrics->x_scale;
2187 scaled_h = FT_MulDiv( scaled_w, h, w );
2188 }
2189 }
2190 else
2191 {
2192 metrics->x_scale = metrics->y_scale = FT_DivFix( scaled_h, h );
2193 scaled_w = FT_MulDiv( scaled_h, w, h );
2194 }
2195
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002196 /* calculate the ppems */
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002197 if ( req->type != FT_SIZE_REQUEST_TYPE_NOMINAL )
2198 {
2199 scaled_w = FT_MulFix( face->units_per_EM, metrics->x_scale );
2200 scaled_h = FT_MulFix( face->units_per_EM, metrics->y_scale );
2201 }
2202
Werner Lembergbe3c9812006-01-27 14:16:16 +00002203 metrics->x_ppem = (FT_UShort)( ( scaled_w + 32 ) >> 6 );
2204 metrics->y_ppem = (FT_UShort)( ( scaled_h + 32 ) >> 6 );
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002205
2206 ft_recompute_scaled_metrics( face, metrics );
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002207 }
2208 else
2209 {
2210 FT_ZERO( metrics );
Werner Lemberg1723dcc2006-01-15 07:30:32 +00002211 metrics->x_scale = 1L << 22;
2212 metrics->y_scale = 1L << 22;
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002213 }
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002214 }
2215
2216
2217 /* documentation is in freetype.h */
2218
2219 FT_EXPORT_DEF( FT_Error )
2220 FT_Select_Size( FT_Face face,
2221 FT_Int strike_index )
2222 {
Werner Lemberg9cc4aed2006-01-26 21:03:58 +00002223 FT_Driver_Class clazz;
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002224
2225
2226 if ( !face || !FT_HAS_FIXED_SIZES( face ) )
2227 return FT_Err_Invalid_Face_Handle;
2228
2229 if ( strike_index < 0 || strike_index >= face->num_fixed_sizes )
2230 return FT_Err_Invalid_Argument;
2231
2232 clazz = face->driver->clazz;
2233
2234 if ( clazz->select_size )
2235 return clazz->select_size( face->size, (FT_ULong)strike_index );
2236
2237 FT_Select_Metrics( face, (FT_ULong)strike_index );
2238
2239 return FT_Err_Ok;
2240 }
2241
2242
2243 /* documentation is in freetype.h */
2244
2245 FT_EXPORT_DEF( FT_Error )
2246 FT_Request_Size( FT_Face face,
2247 FT_Size_Request req )
2248 {
Werner Lemberg9cc4aed2006-01-26 21:03:58 +00002249 FT_Driver_Class clazz;
2250 FT_ULong strike_index;
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002251
2252
2253 if ( !face )
2254 return FT_Err_Invalid_Face_Handle;
2255
2256 if ( !req || req->width < 0 || req->height < 0 ||
2257 req->type >= FT_SIZE_REQUEST_TYPE_MAX )
2258 return FT_Err_Invalid_Argument;
2259
2260 clazz = face->driver->clazz;
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002261
2262 if ( clazz->request_size )
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002263 return clazz->request_size( face->size, req );
2264
Wu, Chia-I (吳佳一)e33dc2e2006-01-14 05:09:30 +00002265 /*
Werner Lemberg3d8eeb82006-01-14 07:10:45 +00002266 * The reason that a driver doesn't have `request_size' defined is
2267 * either that the scaling here suffices or that the supported formats
2268 * are bitmap-only and size matching is not implemented.
Wu, Chia-I (吳佳一)e33dc2e2006-01-14 05:09:30 +00002269 *
2270 * In the latter case, a simple size matching is done.
2271 */
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002272 if ( !FT_IS_SCALABLE( face ) && FT_HAS_FIXED_SIZES( face ) )
Wu, Chia-I (吳佳一)e33dc2e2006-01-14 05:09:30 +00002273 {
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002274 FT_Error error;
Wu, Chia-I (吳佳一)e33dc2e2006-01-14 05:09:30 +00002275
2276
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002277 error = FT_Match_Size( face, req, 0, &strike_index );
2278 if ( error )
2279 return error;
Wu, Chia-I (吳佳一)e33dc2e2006-01-14 05:09:30 +00002280
Werner Lemberg9cc4aed2006-01-26 21:03:58 +00002281 FT_TRACE3(( "FT_Request_Size: bitmap strike %lu matched\n",
2282 strike_index ));
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002283
2284 return FT_Select_Size( face, (FT_Int)strike_index );
Wu, Chia-I (吳佳一)e33dc2e2006-01-14 05:09:30 +00002285 }
2286
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002287 FT_Request_Metrics( face, req );
2288
2289 return FT_Err_Ok;
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002290 }
2291
2292
2293 /* documentation is in freetype.h */
2294
2295 FT_EXPORT_DEF( FT_Error )
Werner Lembergf814d0f2001-06-27 16:18:10 +00002296 FT_Set_Char_Size( FT_Face face,
2297 FT_F26Dot6 char_width,
2298 FT_F26Dot6 char_height,
2299 FT_UInt horz_resolution,
2300 FT_UInt vert_resolution )
David Turnerd2b1f351999-12-16 23:11:37 +00002301 {
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002302 FT_Size_RequestRec req;
David Turnerd2b1f351999-12-16 23:11:37 +00002303
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00002304
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002305 req.type = FT_SIZE_REQUEST_TYPE_NOMINAL;
2306 req.width = char_width;
2307 req.height = char_height;
2308 req.horiResolution = ( horz_resolution ) ? horz_resolution : 72;
2309 req.vertResolution = ( vert_resolution ) ? vert_resolution : 72;
David Turnerd2b1f351999-12-16 23:11:37 +00002310
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002311 return FT_Request_Size( face, &req );
David Turnerd2b1f351999-12-16 23:11:37 +00002312 }
2313
2314
Werner Lemberg90a03302000-11-07 17:21:11 +00002315 /* documentation is in freetype.h */
2316
Werner Lembergf814d0f2001-06-27 16:18:10 +00002317 FT_EXPORT_DEF( FT_Error )
2318 FT_Set_Pixel_Sizes( FT_Face face,
2319 FT_UInt pixel_width,
2320 FT_UInt pixel_height )
David Turnerd2b1f351999-12-16 23:11:37 +00002321 {
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002322 FT_Size_RequestRec req;
David Turnerd2b1f351999-12-16 23:11:37 +00002323
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00002324
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002325 req.type = FT_SIZE_REQUEST_TYPE_NOMINAL;
2326 req.width = pixel_width << 6;
2327 req.height = pixel_height << 6;
2328 req.horiResolution = 0;
2329 req.vertResolution = 0;
David Turnerd2b1f351999-12-16 23:11:37 +00002330
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002331 return FT_Request_Size( face, &req );
David Turnerd2b1f351999-12-16 23:11:37 +00002332 }
2333
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00002334
Werner Lemberg90a03302000-11-07 17:21:11 +00002335 /* documentation is in freetype.h */
2336
Werner Lembergf814d0f2001-06-27 16:18:10 +00002337 FT_EXPORT_DEF( FT_Error )
2338 FT_Get_Kerning( FT_Face face,
2339 FT_UInt left_glyph,
2340 FT_UInt right_glyph,
2341 FT_UInt kern_mode,
2342 FT_Vector *akerning )
David Turnerd2b1f351999-12-16 23:11:37 +00002343 {
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00002344 FT_Error error = FT_Err_Ok;
David Turnerd2b1f351999-12-16 23:11:37 +00002345 FT_Driver driver;
David Turnerd2b1f351999-12-16 23:11:37 +00002346
Werner Lemberga8bbc262000-07-01 14:06:46 +00002347
David Turnerd2b1f351999-12-16 23:11:37 +00002348 if ( !face )
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00002349 return FT_Err_Invalid_Face_Handle;
2350
Werner Lemberg4b680072000-11-07 06:30:29 +00002351 if ( !akerning )
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00002352 return FT_Err_Invalid_Argument;
David Turnerd2b1f351999-12-16 23:11:37 +00002353
2354 driver = face->driver;
David Turnerd2b1f351999-12-16 23:11:37 +00002355
Werner Lemberg4b680072000-11-07 06:30:29 +00002356 akerning->x = 0;
2357 akerning->y = 0;
Werner Lemberg5aa646c2000-07-14 06:16:47 +00002358
David Turnerf0df85b2000-06-22 00:17:42 +00002359 if ( driver->clazz->get_kerning )
David Turnerd2b1f351999-12-16 23:11:37 +00002360 {
David Turnerf0df85b2000-06-22 00:17:42 +00002361 error = driver->clazz->get_kerning( face,
Werner Lemberga929ba92000-06-25 06:47:11 +00002362 left_glyph,
2363 right_glyph,
Werner Lemberg4b680072000-11-07 06:30:29 +00002364 akerning );
Werner Lemberg5aa646c2000-07-14 06:16:47 +00002365 if ( !error )
David Turnerf9ca2bb2000-06-30 23:12:55 +00002366 {
David Turnerb08fe2d2002-08-27 20:20:29 +00002367 if ( kern_mode != FT_KERNING_UNSCALED )
David Turnerf9ca2bb2000-06-30 23:12:55 +00002368 {
Werner Lemberg4b680072000-11-07 06:30:29 +00002369 akerning->x = FT_MulFix( akerning->x, face->size->metrics.x_scale );
2370 akerning->y = FT_MulFix( akerning->y, face->size->metrics.y_scale );
Werner Lemberg5aa646c2000-07-14 06:16:47 +00002371
David Turnerb08fe2d2002-08-27 20:20:29 +00002372 if ( kern_mode != FT_KERNING_UNFITTED )
Werner Lemberg5aa646c2000-07-14 06:16:47 +00002373 {
Werner Lemberg133eee02004-12-12 06:55:40 +00002374 /* we scale down kerning values for small ppem values */
2375 /* to avoid that rounding makes them too big. */
2376 /* `25' has been determined heuristically. */
2377 if ( face->size->metrics.x_ppem < 25 )
2378 akerning->x = FT_MulDiv( akerning->x,
2379 face->size->metrics.x_ppem, 25 );
2380 if ( face->size->metrics.y_ppem < 25 )
2381 akerning->y = FT_MulDiv( akerning->y,
2382 face->size->metrics.y_ppem, 25 );
2383
2384 akerning->x = FT_PIX_ROUND( akerning->x );
2385 akerning->y = FT_PIX_ROUND( akerning->y );
Werner Lemberg5aa646c2000-07-14 06:16:47 +00002386 }
David Turnerf9ca2bb2000-06-30 23:12:55 +00002387 }
2388 }
2389 }
David Turnerd2b1f351999-12-16 23:11:37 +00002390
David Turnerd2b1f351999-12-16 23:11:37 +00002391 return error;
2392 }
2393
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00002394
Werner Lemberg90a03302000-11-07 17:21:11 +00002395 /* documentation is in freetype.h */
2396
Werner Lembergf814d0f2001-06-27 16:18:10 +00002397 FT_EXPORT_DEF( FT_Error )
Wu, Chia-I (吳佳一)108fdbb2006-01-16 15:35:56 +00002398 FT_Get_Track_Kerning( FT_Face face,
2399 FT_Fixed point_size,
2400 FT_Int degree,
2401 FT_Fixed* akerning )
2402 {
2403 FT_Service_Kerning service;
2404 FT_Error error = FT_Err_Ok;
2405 FT_Driver driver;
2406
2407
2408 if ( !face )
2409 return FT_Err_Invalid_Face_Handle;
2410
2411 if ( !akerning )
2412 return FT_Err_Invalid_Argument;
2413
2414 driver = face->driver;
2415
2416 FT_FACE_FIND_SERVICE( face, service, KERNING );
2417 if ( !service )
2418 return FT_Err_Unimplemented_Feature;
2419
2420 error = service->get_track( face,
2421 point_size,
2422 degree,
2423 akerning );
2424
2425 return error;
2426 }
2427
2428
2429 /* documentation is in freetype.h */
2430
2431 FT_EXPORT_DEF( FT_Error )
Werner Lembergf814d0f2001-06-27 16:18:10 +00002432 FT_Select_Charmap( FT_Face face,
2433 FT_Encoding encoding )
David Turner0a29c692000-05-12 17:09:38 +00002434 {
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00002435 FT_CharMap* cur;
2436 FT_CharMap* limit;
David Turnere49ab252000-05-16 23:44:38 +00002437
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00002438
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00002439 if ( !face )
2440 return FT_Err_Invalid_Face_Handle;
2441
Werner Lembergc8c6bf52003-04-23 05:38:13 +00002442 /* FT_ENCODING_UNICODE is special. We try to find the `best' Unicode */
2443 /* charmap available, i.e., one with UCS-4 characters, if possible. */
2444 /* */
2445 /* This is done by find_unicode_charmap() above, to share code. */
Antoine Lecac96f69d2002-12-03 00:39:16 +00002446 if ( encoding == FT_ENCODING_UNICODE )
2447 return find_unicode_charmap( face );
2448
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00002449 cur = face->charmaps;
2450 if ( !cur )
2451 return FT_Err_Invalid_CharMap_Handle;
2452
2453 limit = cur + face->num_charmaps;
2454
David Turner0a29c692000-05-12 17:09:38 +00002455 for ( ; cur < limit; cur++ )
2456 {
2457 if ( cur[0]->encoding == encoding )
2458 {
2459 face->charmap = cur[0];
2460 return 0;
2461 }
2462 }
Werner Lembergdeb4e982000-06-29 03:14:25 +00002463
David Turner0a29c692000-05-12 17:09:38 +00002464 return FT_Err_Invalid_Argument;
2465 }
2466
2467
Werner Lemberg90a03302000-11-07 17:21:11 +00002468 /* documentation is in freetype.h */
2469
Werner Lembergf814d0f2001-06-27 16:18:10 +00002470 FT_EXPORT_DEF( FT_Error )
2471 FT_Set_Charmap( FT_Face face,
2472 FT_CharMap charmap )
David Turner0a29c692000-05-12 17:09:38 +00002473 {
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00002474 FT_CharMap* cur;
2475 FT_CharMap* limit;
David Turnere49ab252000-05-16 23:44:38 +00002476
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00002477
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00002478 if ( !face )
2479 return FT_Err_Invalid_Face_Handle;
2480
2481 cur = face->charmaps;
2482 if ( !cur )
2483 return FT_Err_Invalid_CharMap_Handle;
2484
2485 limit = cur + face->num_charmaps;
2486
David Turner0a29c692000-05-12 17:09:38 +00002487 for ( ; cur < limit; cur++ )
2488 {
2489 if ( cur[0] == charmap )
2490 {
2491 face->charmap = cur[0];
2492 return 0;
2493 }
2494 }
2495 return FT_Err_Invalid_Argument;
2496 }
David Turnerd2b1f351999-12-16 23:11:37 +00002497
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00002498
Werner Lemberge95365b2004-04-24 14:43:37 +00002499 /* documentation is in freetype.h */
2500
2501 FT_EXPORT_DEF( FT_Int )
2502 FT_Get_Charmap_Index( FT_CharMap charmap )
2503 {
2504 FT_Int i;
2505
2506
2507 for ( i = 0; i < charmap->face->num_charmaps; i++ )
2508 if ( charmap->face->charmaps[i] == charmap )
2509 break;
2510
2511 FT_ASSERT( i < charmap->face->num_charmaps );
2512
2513 return i;
2514 }
2515
2516
Werner Lemberge70371c2005-05-27 06:01:28 +00002517 static void
2518 ft_cmap_done_internal( FT_CMap cmap )
2519 {
2520 FT_CMap_Class clazz = cmap->clazz;
2521 FT_Face face = cmap->charmap.face;
2522 FT_Memory memory = FT_FACE_MEMORY(face);
2523
2524
2525 if ( clazz->done )
2526 clazz->done( cmap );
2527
2528 FT_FREE( cmap );
2529 }
2530
2531
David Turner4e7eeee2002-02-28 16:10:29 +00002532 FT_BASE_DEF( void )
2533 FT_CMap_Done( FT_CMap cmap )
2534 {
2535 if ( cmap )
2536 {
Werner Lemberge70371c2005-05-27 06:01:28 +00002537 FT_Face face = cmap->charmap.face;
2538 FT_Memory memory = FT_FACE_MEMORY( face );
2539 FT_Error error;
2540 FT_Int i, j;
David Turnerbc82f1b2002-03-01 02:26:22 +00002541
Werner Lembergf8ba2002002-03-30 13:16:35 +00002542
Werner Lemberge70371c2005-05-27 06:01:28 +00002543 for ( i = 0; i < face->num_charmaps; i++ )
2544 {
2545 if ( (FT_CMap)face->charmaps[i] == cmap )
2546 {
2547 FT_CharMap last_charmap = face->charmaps[face->num_charmaps - 1];
David Turner4e7eeee2002-02-28 16:10:29 +00002548
Werner Lemberge70371c2005-05-27 06:01:28 +00002549
2550 if ( FT_RENEW_ARRAY( face->charmaps,
2551 face->num_charmaps,
2552 face->num_charmaps - 1 ) )
2553 return;
2554
2555 /* remove it from our list of charmaps */
2556 for ( j = i + 1; j < face->num_charmaps; j++ )
2557 {
2558 if ( j == face->num_charmaps - 1 )
2559 face->charmaps[j - 1] = last_charmap;
2560 else
2561 face->charmaps[j - 1] = face->charmaps[j];
2562 }
2563
2564 face->num_charmaps--;
2565
2566 if ( (FT_CMap)face->charmap == cmap )
2567 face->charmap = NULL;
2568
2569 ft_cmap_done_internal( cmap );
2570
2571 break;
2572 }
2573 }
David Turner4e7eeee2002-02-28 16:10:29 +00002574 }
2575 }
2576
2577
2578 FT_BASE_DEF( FT_Error )
Werner Lemberg9cc4aed2006-01-26 21:03:58 +00002579 FT_CMap_New( FT_CMap_Class clazz,
2580 FT_Pointer init_data,
2581 FT_CharMap charmap,
2582 FT_CMap *acmap )
David Turnerbc82f1b2002-03-01 02:26:22 +00002583 {
Werner Lemberg8acb8672005-03-08 11:43:36 +00002584 FT_Error error = FT_Err_Ok;
David Turner4e7eeee2002-02-28 16:10:29 +00002585 FT_Face face;
2586 FT_Memory memory;
2587 FT_CMap cmap;
David Turnerbc82f1b2002-03-01 02:26:22 +00002588
Werner Lembergf8ba2002002-03-30 13:16:35 +00002589
David Turner4e7eeee2002-02-28 16:10:29 +00002590 if ( clazz == NULL || charmap == NULL || charmap->face == NULL )
2591 return FT_Err_Invalid_Argument;
2592
2593 face = charmap->face;
Werner Lembergf35ff802003-06-02 21:58:05 +00002594 memory = FT_FACE_MEMORY( face );
David Turner4e7eeee2002-02-28 16:10:29 +00002595
David Turnere459d742002-03-22 13:52:37 +00002596 if ( !FT_ALLOC( cmap, clazz->size ) )
David Turner4e7eeee2002-02-28 16:10:29 +00002597 {
2598 cmap->charmap = *charmap;
2599 cmap->clazz = clazz;
David Turnerbc82f1b2002-03-01 02:26:22 +00002600
David Turner4e7eeee2002-02-28 16:10:29 +00002601 if ( clazz->init )
2602 {
David Turnerbc82f1b2002-03-01 02:26:22 +00002603 error = clazz->init( cmap, init_data );
Werner Lembergf8ba2002002-03-30 13:16:35 +00002604 if ( error )
David Turner4e7eeee2002-02-28 16:10:29 +00002605 goto Fail;
2606 }
David Turnerbc82f1b2002-03-01 02:26:22 +00002607
David Turner4e7eeee2002-02-28 16:10:29 +00002608 /* add it to our list of charmaps */
David Turnere459d742002-03-22 13:52:37 +00002609 if ( FT_RENEW_ARRAY( face->charmaps,
2610 face->num_charmaps,
Werner Lemberg8acb8672005-03-08 11:43:36 +00002611 face->num_charmaps + 1 ) )
David Turner4e7eeee2002-02-28 16:10:29 +00002612 goto Fail;
David Turnerbc82f1b2002-03-01 02:26:22 +00002613
Werner Lembergf8ba2002002-03-30 13:16:35 +00002614 face->charmaps[face->num_charmaps++] = (FT_CharMap)cmap;
David Turner4e7eeee2002-02-28 16:10:29 +00002615 }
David Turnerbc82f1b2002-03-01 02:26:22 +00002616
David Turner4e7eeee2002-02-28 16:10:29 +00002617 Exit:
2618 if ( acmap )
2619 *acmap = cmap;
2620
2621 return error;
David Turnerbc82f1b2002-03-01 02:26:22 +00002622
David Turner4e7eeee2002-02-28 16:10:29 +00002623 Fail:
Werner Lemberge70371c2005-05-27 06:01:28 +00002624 ft_cmap_done_internal( cmap );
David Turner4e7eeee2002-02-28 16:10:29 +00002625 cmap = NULL;
2626 goto Exit;
David Turnerbc82f1b2002-03-01 02:26:22 +00002627 }
David Turner4e7eeee2002-02-28 16:10:29 +00002628
2629
Werner Lemberg90a03302000-11-07 17:21:11 +00002630 /* documentation is in freetype.h */
2631
Werner Lembergf814d0f2001-06-27 16:18:10 +00002632 FT_EXPORT_DEF( FT_UInt )
2633 FT_Get_Char_Index( FT_Face face,
2634 FT_ULong charcode )
David Turnerd2b1f351999-12-16 23:11:37 +00002635 {
David Turnered54f282002-03-22 17:09:52 +00002636 FT_UInt result = 0;
2637
2638
2639 if ( face && face->charmap )
2640 {
2641 FT_CMap cmap = FT_CMAP( face->charmap );
David Turner25a6e3a2002-06-10 23:03:35 +00002642
Werner Lembergf8ba2002002-03-30 13:16:35 +00002643
David Turnered54f282002-03-22 17:09:52 +00002644 result = cmap->clazz->char_index( cmap, charcode );
2645 }
2646 return result;
2647 }
2648
David Turnered54f282002-03-22 17:09:52 +00002649
Werner Lemberg0f7c2f12002-02-04 20:55:58 +00002650 /* documentation is in freetype.h */
2651
2652 FT_EXPORT_DEF( FT_ULong )
David Turner041889e2002-02-28 19:28:26 +00002653 FT_Get_First_Char( FT_Face face,
2654 FT_UInt *agindex )
Werner Lemberg0f7c2f12002-02-04 20:55:58 +00002655 {
Werner Lembergf8ba2002002-03-30 13:16:35 +00002656 FT_ULong result = 0;
2657 FT_UInt gindex = 0;
2658
David Turnerbc82f1b2002-03-01 02:26:22 +00002659
David Turner041889e2002-02-28 19:28:26 +00002660 if ( face && face->charmap )
2661 {
2662 gindex = FT_Get_Char_Index( face, 0 );
2663 if ( gindex == 0 )
2664 result = FT_Get_Next_Char( face, 0, &gindex );
2665 }
David Turnerbc82f1b2002-03-01 02:26:22 +00002666
David Turner041889e2002-02-28 19:28:26 +00002667 if ( agindex )
2668 *agindex = gindex;
David Turnerbc82f1b2002-03-01 02:26:22 +00002669
David Turner041889e2002-02-28 19:28:26 +00002670 return result;
2671 }
2672
David Turner041889e2002-02-28 19:28:26 +00002673
Werner Lemberg7b0cc662003-07-05 07:46:49 +00002674 /* documentation is in freetype.h */
David Turnered54f282002-03-22 17:09:52 +00002675
David Turnered54f282002-03-22 17:09:52 +00002676 FT_EXPORT_DEF( FT_ULong )
2677 FT_Get_Next_Char( FT_Face face,
2678 FT_ULong charcode,
2679 FT_UInt *agindex )
2680 {
Werner Lembergf8ba2002002-03-30 13:16:35 +00002681 FT_ULong result = 0;
2682 FT_UInt gindex = 0;
David Turnered54f282002-03-22 17:09:52 +00002683
2684
2685 if ( face && face->charmap )
2686 {
2687 FT_UInt32 code = (FT_UInt32)charcode;
2688 FT_CMap cmap = FT_CMAP( face->charmap );
2689
Werner Lembergf8ba2002002-03-30 13:16:35 +00002690
David Turnered54f282002-03-22 17:09:52 +00002691 gindex = cmap->clazz->char_next( cmap, &code );
2692 result = ( gindex == 0 ) ? 0 : code;
2693 }
2694
2695 if ( agindex )
2696 *agindex = gindex;
2697
2698 return result;
2699 }
2700
David Turnered54f282002-03-22 17:09:52 +00002701
Werner Lemberg90a03302000-11-07 17:21:11 +00002702 /* documentation is in freetype.h */
2703
Tom Kacvinskyff2714f2001-08-08 10:58:08 +00002704 FT_EXPORT_DEF( FT_UInt )
2705 FT_Get_Name_Index( FT_Face face,
2706 FT_String* glyph_name )
2707 {
2708 FT_UInt result = 0;
2709
2710
2711 if ( face && FT_HAS_GLYPH_NAMES( face ) )
2712 {
David Turnerc313c502003-09-11 19:51:54 +00002713 FT_Service_GlyphDict service;
Tom Kacvinskyff2714f2001-08-08 10:58:08 +00002714
Werner Lemberg013efd12003-09-17 05:26:33 +00002715
Werner Lemberg46333a12003-09-17 19:20:02 +00002716 FT_FACE_LOOKUP_SERVICE( face,
David Turnere2d12842003-09-21 17:15:55 +00002717 service,
2718 GLYPH_DICT );
Werner Lemberg013efd12003-09-17 05:26:33 +00002719
David Turnerc313c502003-09-11 19:51:54 +00002720 if ( service && service->name_index )
2721 result = service->name_index( face, glyph_name );
Werner Lemberg013efd12003-09-17 05:26:33 +00002722 }
2723
Tom Kacvinskyff2714f2001-08-08 10:58:08 +00002724 return result;
2725 }
2726
Werner Lembergaef3fc82001-12-17 16:21:22 +00002727
Tom Kacvinskyff2714f2001-08-08 10:58:08 +00002728 /* documentation is in freetype.h */
2729
Werner Lembergf814d0f2001-06-27 16:18:10 +00002730 FT_EXPORT_DEF( FT_Error )
2731 FT_Get_Glyph_Name( FT_Face face,
2732 FT_UInt glyph_index,
2733 FT_Pointer buffer,
2734 FT_UInt buffer_max )
David Turner6930b452000-07-19 17:13:03 +00002735 {
2736 FT_Error error = FT_Err_Invalid_Argument;
Werner Lembergeddd9902000-10-12 05:05:40 +00002737
Werner Lembergd060a752000-07-20 06:57:41 +00002738
David Turner6930b452000-07-19 17:13:03 +00002739 /* clean up buffer */
Werner Lembergd060a752000-07-20 06:57:41 +00002740 if ( buffer && buffer_max > 0 )
David Turner6930b452000-07-19 17:13:03 +00002741 ((FT_Byte*)buffer)[0] = 0;
Werner Lembergeddd9902000-10-12 05:05:40 +00002742
Werner Lembergfd97d132002-06-16 01:14:16 +00002743 if ( face &&
2744 glyph_index <= (FT_UInt)face->num_glyphs &&
2745 FT_HAS_GLYPH_NAMES( face ) )
David Turner6930b452000-07-19 17:13:03 +00002746 {
David Turnerc313c502003-09-11 19:51:54 +00002747 FT_Service_GlyphDict service;
David Turner6930b452000-07-19 17:13:03 +00002748
Werner Lemberg013efd12003-09-17 05:26:33 +00002749
Werner Lemberg46333a12003-09-17 19:20:02 +00002750 FT_FACE_LOOKUP_SERVICE( face,
David Turnere2d12842003-09-21 17:15:55 +00002751 service,
2752 GLYPH_DICT );
Werner Lembergd060a752000-07-20 06:57:41 +00002753
David Turnerc313c502003-09-11 19:51:54 +00002754 if ( service && service->get_name )
David Turnerc313c502003-09-11 19:51:54 +00002755 error = service->get_name( face, glyph_index, buffer, buffer_max );
David Turner6930b452000-07-19 17:13:03 +00002756 }
Werner Lembergd060a752000-07-20 06:57:41 +00002757
David Turner6930b452000-07-19 17:13:03 +00002758 return error;
Werner Lembergeddd9902000-10-12 05:05:40 +00002759 }
David Turner6930b452000-07-19 17:13:03 +00002760
2761
David Turner23bcde12001-10-17 13:48:10 +00002762 /* documentation is in freetype.h */
2763
2764 FT_EXPORT_DEF( const char* )
2765 FT_Get_Postscript_Name( FT_Face face )
2766 {
2767 const char* result = NULL;
Werner Lemberg1a0a9792002-01-03 22:06:13 +00002768
Werner Lembergc3b21602001-12-05 01:22:05 +00002769
David Turner23bcde12001-10-17 13:48:10 +00002770 if ( !face )
2771 goto Exit;
2772
David Turner23bcde12001-10-17 13:48:10 +00002773 if ( !result )
2774 {
David Turnerb72d8a82003-09-29 20:33:37 +00002775 FT_Service_PsFontName service;
Werner Lembergc3b21602001-12-05 01:22:05 +00002776
Werner Lemberg013efd12003-09-17 05:26:33 +00002777
Werner Lemberg46333a12003-09-17 19:20:02 +00002778 FT_FACE_LOOKUP_SERVICE( face,
David Turnere2d12842003-09-21 17:15:55 +00002779 service,
David Turnerb72d8a82003-09-29 20:33:37 +00002780 POSTSCRIPT_FONT_NAME );
David Turner23bcde12001-10-17 13:48:10 +00002781
David Turnerb72d8a82003-09-29 20:33:37 +00002782 if ( service && service->get_ps_font_name )
2783 result = service->get_ps_font_name( face );
David Turner23bcde12001-10-17 13:48:10 +00002784 }
Werner Lemberg013efd12003-09-17 05:26:33 +00002785
David Turner23bcde12001-10-17 13:48:10 +00002786 Exit:
2787 return result;
2788 }
2789
2790
Werner Lemberg90a03302000-11-07 17:21:11 +00002791 /* documentation is in tttables.h */
2792
Werner Lembergf814d0f2001-06-27 16:18:10 +00002793 FT_EXPORT_DEF( void* )
2794 FT_Get_Sfnt_Table( FT_Face face,
2795 FT_Sfnt_Tag tag )
David Turner99a4d932000-04-25 16:10:50 +00002796 {
Werner Lemberg40bb0962003-11-01 14:36:20 +00002797 void* table = 0;
2798 FT_Service_SFNT_Table service;
David Turnere49ab252000-05-16 23:44:38 +00002799
Werner Lemberg013efd12003-09-17 05:26:33 +00002800
David Turnerc313c502003-09-11 19:51:54 +00002801 if ( face && FT_IS_SFNT( face ) )
2802 {
David Turnerb72d8a82003-09-29 20:33:37 +00002803 FT_FACE_FIND_SERVICE( face, service, SFNT_TABLE );
David Turnerc313c502003-09-11 19:51:54 +00002804 if ( service != NULL )
2805 table = service->get_table( face, tag );
2806 }
David Turnere2d12842003-09-21 17:15:55 +00002807
David Turner99a4d932000-04-25 16:10:50 +00002808 return table;
David Turnere49ab252000-05-16 23:44:38 +00002809 }
David Turner99a4d932000-04-25 16:10:50 +00002810
2811
David Turner621e4882002-12-16 21:51:24 +00002812 /* documentation is in tttables.h */
2813
2814 FT_EXPORT_DEF( FT_Error )
Werner Lembergc8c6bf52003-04-23 05:38:13 +00002815 FT_Load_Sfnt_Table( FT_Face face,
2816 FT_ULong tag,
2817 FT_Long offset,
2818 FT_Byte* buffer,
2819 FT_ULong* length )
David Turner621e4882002-12-16 21:51:24 +00002820 {
David Turnerc313c502003-09-11 19:51:54 +00002821 FT_Service_SFNT_Table service;
David Turner621e4882002-12-16 21:51:24 +00002822
2823
2824 if ( !face || !FT_IS_SFNT( face ) )
2825 return FT_Err_Invalid_Face_Handle;
2826
David Turnerb72d8a82003-09-29 20:33:37 +00002827 FT_FACE_FIND_SERVICE( face, service, SFNT_TABLE );
David Turnerc313c502003-09-11 19:51:54 +00002828 if ( service == NULL )
David Turner621e4882002-12-16 21:51:24 +00002829 return FT_Err_Unimplemented_Feature;
David Turnere2d12842003-09-21 17:15:55 +00002830
David Turnerc313c502003-09-11 19:51:54 +00002831 return service->load_table( face, tag, offset, buffer, length );
David Turner621e4882002-12-16 21:51:24 +00002832 }
2833
2834
Werner Lemberg17439422004-08-11 05:25:37 +00002835 /* documentation is in tttables.h */
2836
2837 FT_EXPORT_DEF( FT_Error )
2838 FT_Sfnt_Table_Info( FT_Face face,
2839 FT_UInt table_index,
2840 FT_ULong *tag,
2841 FT_ULong *length )
2842 {
2843 FT_Service_SFNT_Table service;
2844
2845
2846 if ( !face || !FT_IS_SFNT( face ) )
2847 return FT_Err_Invalid_Face_Handle;
2848
2849 FT_FACE_FIND_SERVICE( face, service, SFNT_TABLE );
2850 if ( service == NULL )
2851 return FT_Err_Unimplemented_Feature;
2852
2853 return service->table_info( face, table_index, tag, length );
2854 }
2855
2856
Werner Lembergece8b202004-12-13 23:16:59 +00002857 /* documentation is in tttables.h */
2858
Werner Lemberg91a67472003-12-17 14:28:22 +00002859 FT_EXPORT_DEF( FT_ULong )
2860 FT_Get_CMap_Language_ID( FT_CharMap charmap )
2861 {
2862 FT_Service_TTCMaps service;
2863 FT_Face face;
2864 TT_CMapInfo cmap_info;
2865
David Turner87c0d302003-12-24 01:10:46 +00002866
Werner Lemberg91a67472003-12-17 14:28:22 +00002867 if ( !charmap || !charmap->face )
2868 return 0;
2869
2870 face = charmap->face;
2871 FT_FACE_FIND_SERVICE( face, service, TT_CMAP );
2872 if ( service == NULL )
2873 return 0;
2874 if ( service->get_cmap_info( charmap, &cmap_info ))
2875 return 0;
2876
2877 return cmap_info.language;
2878 }
2879
2880
Werner Lembergece8b202004-12-13 23:16:59 +00002881 /* documentation is in ftsizes.h */
2882
David Turnerb3ba40d2001-10-07 13:30:26 +00002883 FT_EXPORT_DEF( FT_Error )
Werner Lemberg80b8d772001-10-10 19:56:42 +00002884 FT_Activate_Size( FT_Size size )
David Turnerb3ba40d2001-10-07 13:30:26 +00002885 {
2886 FT_Face face;
Werner Lemberg1a0a9792002-01-03 22:06:13 +00002887
Werner Lemberg80b8d772001-10-10 19:56:42 +00002888
David Turnerb3ba40d2001-10-07 13:30:26 +00002889 if ( size == NULL )
2890 return FT_Err_Bad_Argument;
Werner Lemberg1a0a9792002-01-03 22:06:13 +00002891
David Turnerb3ba40d2001-10-07 13:30:26 +00002892 face = size->face;
2893 if ( face == NULL || face->driver == NULL )
2894 return FT_Err_Bad_Argument;
Werner Lemberg1a0a9792002-01-03 22:06:13 +00002895
Werner Lemberg80b8d772001-10-10 19:56:42 +00002896 /* we don't need anything more complex than that; all size objects */
2897 /* are already listed by the face */
David Turnerb3ba40d2001-10-07 13:30:26 +00002898 face->size = size;
Werner Lemberg1a0a9792002-01-03 22:06:13 +00002899
David Turnerb3ba40d2001-10-07 13:30:26 +00002900 return FT_Err_Ok;
2901 }
2902
2903
David Turnerd2b1f351999-12-16 23:11:37 +00002904 /*************************************************************************/
David Turnerf0df85b2000-06-22 00:17:42 +00002905 /*************************************************************************/
2906 /*************************************************************************/
2907 /**** ****/
2908 /**** ****/
2909 /**** R E N D E R E R S ****/
2910 /**** ****/
2911 /**** ****/
2912 /*************************************************************************/
2913 /*************************************************************************/
2914 /*************************************************************************/
2915
Werner Lembergdeb4e982000-06-29 03:14:25 +00002916 /* lookup a renderer by glyph format in the library's list */
Werner Lembergf814d0f2001-06-27 16:18:10 +00002917 FT_BASE_DEF( FT_Renderer )
2918 FT_Lookup_Renderer( FT_Library library,
2919 FT_Glyph_Format format,
2920 FT_ListNode* node )
David Turnerf0df85b2000-06-22 00:17:42 +00002921 {
Werner Lembergf8ba2002002-03-30 13:16:35 +00002922 FT_ListNode cur;
2923 FT_Renderer result = 0;
Werner Lemberga929ba92000-06-25 06:47:11 +00002924
Werner Lembergdeb4e982000-06-29 03:14:25 +00002925
2926 if ( !library )
2927 goto Exit;
2928
2929 cur = library->renderers.head;
2930
2931 if ( node )
David Turner74abee82000-06-27 23:31:53 +00002932 {
Werner Lembergdeb4e982000-06-29 03:14:25 +00002933 if ( *node )
David Turner74abee82000-06-27 23:31:53 +00002934 cur = (*node)->next;
David Turnerf0df85b2000-06-22 00:17:42 +00002935 *node = 0;
David Turner74abee82000-06-27 23:31:53 +00002936 }
Werner Lembergdeb4e982000-06-29 03:14:25 +00002937
Werner Lemberga929ba92000-06-25 06:47:11 +00002938 while ( cur )
David Turnerf0df85b2000-06-22 00:17:42 +00002939 {
Werner Lemberga929ba92000-06-25 06:47:11 +00002940 FT_Renderer renderer = FT_RENDERER( cur->data );
Werner Lembergdeb4e982000-06-29 03:14:25 +00002941
Werner Lemberga929ba92000-06-25 06:47:11 +00002942
2943 if ( renderer->glyph_format == format )
David Turnerf0df85b2000-06-22 00:17:42 +00002944 {
Werner Lemberga929ba92000-06-25 06:47:11 +00002945 if ( node )
David Turnerf0df85b2000-06-22 00:17:42 +00002946 *node = cur;
Werner Lembergdeb4e982000-06-29 03:14:25 +00002947
David Turnerf0df85b2000-06-22 00:17:42 +00002948 result = renderer;
2949 break;
2950 }
David Turner74abee82000-06-27 23:31:53 +00002951 cur = cur->next;
David Turnerf0df85b2000-06-22 00:17:42 +00002952 }
Werner Lemberga929ba92000-06-25 06:47:11 +00002953
Werner Lembergdeb4e982000-06-29 03:14:25 +00002954 Exit:
David Turnerf0df85b2000-06-22 00:17:42 +00002955 return result;
2956 }
2957
Werner Lemberga929ba92000-06-25 06:47:11 +00002958
Werner Lembergf814d0f2001-06-27 16:18:10 +00002959 static FT_Renderer
2960 ft_lookup_glyph_renderer( FT_GlyphSlot slot )
Werner Lembergdeb4e982000-06-29 03:14:25 +00002961 {
2962 FT_Face face = slot->face;
2963 FT_Library library = FT_FACE_LIBRARY( face );
2964 FT_Renderer result = library->cur_renderer;
2965
2966
Werner Lemberga929ba92000-06-25 06:47:11 +00002967 if ( !result || result->glyph_format != slot->format )
David Turner81bb4ad2000-06-28 04:19:49 +00002968 result = FT_Lookup_Renderer( library, slot->format, 0 );
Werner Lembergfbeb41d2000-07-02 00:27:53 +00002969
David Turnerf0df85b2000-06-22 00:17:42 +00002970 return result;
2971 }
2972
Werner Lembergdeb4e982000-06-29 03:14:25 +00002973
Werner Lembergf814d0f2001-06-27 16:18:10 +00002974 static void
2975 ft_set_current_renderer( FT_Library library )
David Turnerf0df85b2000-06-22 00:17:42 +00002976 {
2977 FT_Renderer renderer;
2978
Werner Lembergdeb4e982000-06-29 03:14:25 +00002979
David Turnerb08fe2d2002-08-27 20:20:29 +00002980 renderer = FT_Lookup_Renderer( library, FT_GLYPH_FORMAT_OUTLINE, 0 );
David Turnerf0df85b2000-06-22 00:17:42 +00002981 library->cur_renderer = renderer;
2982 }
2983
2984
Werner Lembergf814d0f2001-06-27 16:18:10 +00002985 static FT_Error
2986 ft_add_renderer( FT_Module module )
David Turnerf0df85b2000-06-22 00:17:42 +00002987 {
2988 FT_Library library = module->library;
2989 FT_Memory memory = library->memory;
2990 FT_Error error;
2991 FT_ListNode node;
Werner Lembergdeb4e982000-06-29 03:14:25 +00002992
2993
David Turnere459d742002-03-22 13:52:37 +00002994 if ( FT_NEW( node ) )
David Turnerf0df85b2000-06-22 00:17:42 +00002995 goto Exit;
Werner Lembergdeb4e982000-06-29 03:14:25 +00002996
David Turnerf0df85b2000-06-22 00:17:42 +00002997 {
Werner Lemberga929ba92000-06-25 06:47:11 +00002998 FT_Renderer render = FT_RENDERER( module );
David Turnerf0df85b2000-06-22 00:17:42 +00002999 FT_Renderer_Class* clazz = (FT_Renderer_Class*)module->clazz;
3000
Werner Lemberga929ba92000-06-25 06:47:11 +00003001
David Turnerf0df85b2000-06-22 00:17:42 +00003002 render->clazz = clazz;
3003 render->glyph_format = clazz->glyph_format;
Werner Lembergdeb4e982000-06-29 03:14:25 +00003004
David Turnerf0df85b2000-06-22 00:17:42 +00003005 /* allocate raster object if needed */
David Turnerb08fe2d2002-08-27 20:20:29 +00003006 if ( clazz->glyph_format == FT_GLYPH_FORMAT_OUTLINE &&
David Turnerf0df85b2000-06-22 00:17:42 +00003007 clazz->raster_class->raster_new )
3008 {
3009 error = clazz->raster_class->raster_new( memory, &render->raster );
Werner Lemberga929ba92000-06-25 06:47:11 +00003010 if ( error )
3011 goto Fail;
Werner Lembergdeb4e982000-06-29 03:14:25 +00003012
David Turnerf0df85b2000-06-22 00:17:42 +00003013 render->raster_render = clazz->raster_class->raster_render;
3014 render->render = clazz->render_glyph;
Werner Lembergdeb4e982000-06-29 03:14:25 +00003015 }
3016
David Turnerf0df85b2000-06-22 00:17:42 +00003017 /* add to list */
3018 node->data = module;
3019 FT_List_Add( &library->renderers, node );
3020
3021 ft_set_current_renderer( library );
3022 }
3023
3024 Fail:
Werner Lemberga929ba92000-06-25 06:47:11 +00003025 if ( error )
David Turnere459d742002-03-22 13:52:37 +00003026 FT_FREE( node );
David Turnerf0df85b2000-06-22 00:17:42 +00003027
3028 Exit:
3029 return error;
Werner Lembergdeb4e982000-06-29 03:14:25 +00003030 }
David Turnerf0df85b2000-06-22 00:17:42 +00003031
3032
Werner Lembergf814d0f2001-06-27 16:18:10 +00003033 static void
3034 ft_remove_renderer( FT_Module module )
David Turnerf0df85b2000-06-22 00:17:42 +00003035 {
3036 FT_Library library = module->library;
3037 FT_Memory memory = library->memory;
3038 FT_ListNode node;
3039
Werner Lemberga929ba92000-06-25 06:47:11 +00003040
David Turnerf0df85b2000-06-22 00:17:42 +00003041 node = FT_List_Find( &library->renderers, module );
Werner Lemberga929ba92000-06-25 06:47:11 +00003042 if ( node )
David Turnerf0df85b2000-06-22 00:17:42 +00003043 {
Werner Lemberga929ba92000-06-25 06:47:11 +00003044 FT_Renderer render = FT_RENDERER( module );
Werner Lembergdeb4e982000-06-29 03:14:25 +00003045
Werner Lemberga929ba92000-06-25 06:47:11 +00003046
David Turnerf0df85b2000-06-22 00:17:42 +00003047 /* release raster object, if any */
Werner Lemberga929ba92000-06-25 06:47:11 +00003048 if ( render->raster )
David Turnerf0df85b2000-06-22 00:17:42 +00003049 render->clazz->raster_class->raster_done( render->raster );
Werner Lembergdeb4e982000-06-29 03:14:25 +00003050
David Turnerf0df85b2000-06-22 00:17:42 +00003051 /* remove from list */
3052 FT_List_Remove( &library->renderers, node );
David Turnere459d742002-03-22 13:52:37 +00003053 FT_FREE( node );
Werner Lembergdeb4e982000-06-29 03:14:25 +00003054
David Turnerf0df85b2000-06-22 00:17:42 +00003055 ft_set_current_renderer( library );
3056 }
3057 }
3058
3059
Werner Lemberg90a03302000-11-07 17:21:11 +00003060 /* documentation is in ftrender.h */
3061
Werner Lembergf814d0f2001-06-27 16:18:10 +00003062 FT_EXPORT_DEF( FT_Renderer )
3063 FT_Get_Renderer( FT_Library library,
3064 FT_Glyph_Format format )
David Turnerf0df85b2000-06-22 00:17:42 +00003065 {
Werner Lembergdeb4e982000-06-29 03:14:25 +00003066 /* test for valid `library' delayed to FT_Lookup_Renderer() */
3067
Werner Lembergf8ba2002002-03-30 13:16:35 +00003068 return FT_Lookup_Renderer( library, format, 0 );
Werner Lembergdeb4e982000-06-29 03:14:25 +00003069 }
David Turnerf0df85b2000-06-22 00:17:42 +00003070
3071
Werner Lemberg90a03302000-11-07 17:21:11 +00003072 /* documentation is in ftrender.h */
3073
Werner Lembergf814d0f2001-06-27 16:18:10 +00003074 FT_EXPORT_DEF( FT_Error )
3075 FT_Set_Renderer( FT_Library library,
3076 FT_Renderer renderer,
3077 FT_UInt num_params,
3078 FT_Parameter* parameters )
David Turnerf0df85b2000-06-22 00:17:42 +00003079 {
3080 FT_ListNode node;
3081 FT_Error error = FT_Err_Ok;
Werner Lembergdeb4e982000-06-29 03:14:25 +00003082
3083
3084 if ( !library )
3085 return FT_Err_Invalid_Library_Handle;
3086
3087 if ( !renderer )
3088 return FT_Err_Invalid_Argument;
Werner Lemberga929ba92000-06-25 06:47:11 +00003089
David Turnerf0df85b2000-06-22 00:17:42 +00003090 node = FT_List_Find( &library->renderers, renderer );
Werner Lemberga929ba92000-06-25 06:47:11 +00003091 if ( !node )
David Turnerf0df85b2000-06-22 00:17:42 +00003092 {
3093 error = FT_Err_Invalid_Argument;
3094 goto Exit;
3095 }
David Turner74abee82000-06-27 23:31:53 +00003096
David Turnerf0df85b2000-06-22 00:17:42 +00003097 FT_List_Up( &library->renderers, node );
Werner Lembergdeb4e982000-06-29 03:14:25 +00003098
David Turnerb08fe2d2002-08-27 20:20:29 +00003099 if ( renderer->glyph_format == FT_GLYPH_FORMAT_OUTLINE )
David Turnerf0df85b2000-06-22 00:17:42 +00003100 library->cur_renderer = renderer;
Werner Lembergdeb4e982000-06-29 03:14:25 +00003101
Werner Lemberga929ba92000-06-25 06:47:11 +00003102 if ( num_params > 0 )
David Turnerf0df85b2000-06-22 00:17:42 +00003103 {
David Turnerb08fe2d2002-08-27 20:20:29 +00003104 FT_Renderer_SetModeFunc set_mode = renderer->clazz->set_mode;
Werner Lembergdeb4e982000-06-29 03:14:25 +00003105
Werner Lemberga929ba92000-06-25 06:47:11 +00003106
David Turnerf0df85b2000-06-22 00:17:42 +00003107 for ( ; num_params > 0; num_params-- )
3108 {
3109 error = set_mode( renderer, parameters->tag, parameters->data );
Werner Lemberga929ba92000-06-25 06:47:11 +00003110 if ( error )
David Turnerf0df85b2000-06-22 00:17:42 +00003111 break;
3112 }
3113 }
Werner Lembergdeb4e982000-06-29 03:14:25 +00003114
David Turnerf0df85b2000-06-22 00:17:42 +00003115 Exit:
3116 return error;
Werner Lembergdeb4e982000-06-29 03:14:25 +00003117 }
David Turnerf0df85b2000-06-22 00:17:42 +00003118
3119
David Turner7504e482002-06-07 07:24:55 +00003120 FT_BASE_DEF( FT_Error )
Werner Lemberg68e9f922002-09-27 11:09:23 +00003121 FT_Render_Glyph_Internal( FT_Library library,
3122 FT_GlyphSlot slot,
3123 FT_Render_Mode render_mode )
David Turnerf0df85b2000-06-22 00:17:42 +00003124 {
3125 FT_Error error = FT_Err_Ok;
3126 FT_Renderer renderer;
Werner Lemberga929ba92000-06-25 06:47:11 +00003127
Werner Lembergdeb4e982000-06-29 03:14:25 +00003128
3129 /* if it is already a bitmap, no need to do anything */
3130 switch ( slot->format )
David Turnerf0df85b2000-06-22 00:17:42 +00003131 {
David Turnerb08fe2d2002-08-27 20:20:29 +00003132 case FT_GLYPH_FORMAT_BITMAP: /* already a bitmap, don't do anything */
Werner Lembergdeb4e982000-06-29 03:14:25 +00003133 break;
3134
3135 default:
David Turner74abee82000-06-27 23:31:53 +00003136 {
3137 FT_ListNode node = 0;
3138 FT_Bool update = 0;
Werner Lembergdeb4e982000-06-29 03:14:25 +00003139
3140
Werner Lemberga929ba92000-06-25 06:47:11 +00003141 /* small shortcut for the very common case */
David Turnerb08fe2d2002-08-27 20:20:29 +00003142 if ( slot->format == FT_GLYPH_FORMAT_OUTLINE )
David Turner74abee82000-06-27 23:31:53 +00003143 {
Werner Lemberga929ba92000-06-25 06:47:11 +00003144 renderer = library->cur_renderer;
David Turner74abee82000-06-27 23:31:53 +00003145 node = library->renderers.head;
3146 }
Werner Lemberga929ba92000-06-25 06:47:11 +00003147 else
David Turner74abee82000-06-27 23:31:53 +00003148 renderer = FT_Lookup_Renderer( library, slot->format, &node );
3149
Werner Lemberga929ba92000-06-25 06:47:11 +00003150 error = FT_Err_Unimplemented_Feature;
Werner Lembergdeb4e982000-06-29 03:14:25 +00003151 while ( renderer )
David Turner74abee82000-06-27 23:31:53 +00003152 {
David Turnerc8ad30a2001-12-05 17:24:34 +00003153 error = renderer->render( renderer, slot, render_mode, NULL );
Werner Lemberg79860702001-06-08 21:17:29 +00003154 if ( !error ||
3155 FT_ERROR_BASE( error ) != FT_Err_Cannot_Render_Glyph )
Werner Lembergdeb4e982000-06-29 03:14:25 +00003156 break;
David Turner74abee82000-06-27 23:31:53 +00003157
Werner Lembergdeb4e982000-06-29 03:14:25 +00003158 /* FT_Err_Cannot_Render_Glyph is returned if the render mode */
David Turner74abee82000-06-27 23:31:53 +00003159 /* is unsupported by the current renderer for this glyph image */
Werner Lembergdeb4e982000-06-29 03:14:25 +00003160 /* format. */
3161
3162 /* now, look for another renderer that supports the same */
3163 /* format. */
David Turner74abee82000-06-27 23:31:53 +00003164 renderer = FT_Lookup_Renderer( library, slot->format, &node );
3165 update = 1;
3166 }
3167
3168 /* if we changed the current renderer for the glyph image format */
Werner Lembergdeb4e982000-06-29 03:14:25 +00003169 /* we need to select it as the next current one */
3170 if ( !error && update && renderer )
David Turner74abee82000-06-27 23:31:53 +00003171 FT_Set_Renderer( library, renderer, 0, 0 );
David Turnerf0df85b2000-06-22 00:17:42 +00003172 }
3173 }
Werner Lembergdeb4e982000-06-29 03:14:25 +00003174
David Turnerf0df85b2000-06-22 00:17:42 +00003175 return error;
3176 }
Werner Lemberga929ba92000-06-25 06:47:11 +00003177
David Turner74abee82000-06-27 23:31:53 +00003178
Werner Lemberg90a03302000-11-07 17:21:11 +00003179 /* documentation is in freetype.h */
3180
Werner Lembergf814d0f2001-06-27 16:18:10 +00003181 FT_EXPORT_DEF( FT_Error )
Werner Lemberg68e9f922002-09-27 11:09:23 +00003182 FT_Render_Glyph( FT_GlyphSlot slot,
3183 FT_Render_Mode render_mode )
David Turner74abee82000-06-27 23:31:53 +00003184 {
Werner Lembergf8ba2002002-03-30 13:16:35 +00003185 FT_Library library;
Werner Lembergdeb4e982000-06-29 03:14:25 +00003186
3187
3188 if ( !slot )
David Turner74abee82000-06-27 23:31:53 +00003189 return FT_Err_Invalid_Argument;
Werner Lembergdeb4e982000-06-29 03:14:25 +00003190
3191 library = FT_FACE_LIBRARY( slot->face );
3192
David Turner74abee82000-06-27 23:31:53 +00003193 return FT_Render_Glyph_Internal( library, slot, render_mode );
3194 }
3195
Werner Lembergdeb4e982000-06-29 03:14:25 +00003196
David Turnerf0df85b2000-06-22 00:17:42 +00003197 /*************************************************************************/
3198 /*************************************************************************/
3199 /*************************************************************************/
3200 /**** ****/
3201 /**** ****/
3202 /**** M O D U L E S ****/
3203 /**** ****/
3204 /**** ****/
3205 /*************************************************************************/
3206 /*************************************************************************/
3207 /*************************************************************************/
3208
Werner Lemberga929ba92000-06-25 06:47:11 +00003209
David Turnerf0df85b2000-06-22 00:17:42 +00003210 /*************************************************************************/
3211 /* */
3212 /* <Function> */
3213 /* Destroy_Module */
3214 /* */
3215 /* <Description> */
3216 /* Destroys a given module object. For drivers, this also destroys */
Werner Lemberga929ba92000-06-25 06:47:11 +00003217 /* all child faces. */
David Turnerf0df85b2000-06-22 00:17:42 +00003218 /* */
3219 /* <InOut> */
3220 /* module :: A handle to the target driver object. */
3221 /* */
3222 /* <Note> */
3223 /* The driver _must_ be LOCKED! */
3224 /* */
Werner Lembergf814d0f2001-06-27 16:18:10 +00003225 static void
3226 Destroy_Module( FT_Module module )
David Turnerf0df85b2000-06-22 00:17:42 +00003227 {
David Turner5ae831c2000-06-30 01:31:22 +00003228 FT_Memory memory = module->memory;
3229 FT_Module_Class* clazz = module->clazz;
3230 FT_Library library = module->library;
David Turnerf0df85b2000-06-22 00:17:42 +00003231
Werner Lemberga929ba92000-06-25 06:47:11 +00003232
David Turnerf0df85b2000-06-22 00:17:42 +00003233 /* finalize client-data - before anything else */
3234 if ( module->generic.finalizer )
3235 module->generic.finalizer( module );
3236
David Turner5ae831c2000-06-30 01:31:22 +00003237 if ( library && library->auto_hinter == module )
3238 library->auto_hinter = 0;
3239
David Turnerf0df85b2000-06-22 00:17:42 +00003240 /* if the module is a renderer */
Werner Lemberga929ba92000-06-25 06:47:11 +00003241 if ( FT_MODULE_IS_RENDERER( module ) )
3242 ft_remove_renderer( module );
David Turnerf0df85b2000-06-22 00:17:42 +00003243
3244 /* if the module is a font driver, add some steps */
Werner Lemberga929ba92000-06-25 06:47:11 +00003245 if ( FT_MODULE_IS_DRIVER( module ) )
3246 Destroy_Driver( FT_DRIVER( module ) );
David Turnerf0df85b2000-06-22 00:17:42 +00003247
3248 /* finalize the module object */
Werner Lemberga929ba92000-06-25 06:47:11 +00003249 if ( clazz->module_done )
3250 clazz->module_done( module );
David Turnerf0df85b2000-06-22 00:17:42 +00003251
3252 /* discard it */
David Turnere459d742002-03-22 13:52:37 +00003253 FT_FREE( module );
David Turnerf0df85b2000-06-22 00:17:42 +00003254 }
3255
David Turnerf0df85b2000-06-22 00:17:42 +00003256
Werner Lemberg748b1712005-12-25 09:15:09 +00003257 /* documentation is in ftmodapi.h */
Werner Lemberg90a03302000-11-07 17:21:11 +00003258
Werner Lembergf814d0f2001-06-27 16:18:10 +00003259 FT_EXPORT_DEF( FT_Error )
3260 FT_Add_Module( FT_Library library,
3261 const FT_Module_Class* clazz )
David Turnerf0df85b2000-06-22 00:17:42 +00003262 {
3263 FT_Error error;
3264 FT_Memory memory;
3265 FT_Module module;
3266 FT_UInt nn;
3267
David Turnerf0df85b2000-06-22 00:17:42 +00003268
Werner Lembergdeb4e982000-06-29 03:14:25 +00003269#define FREETYPE_VER_FIXED ( ( (FT_Long)FREETYPE_MAJOR << 16 ) | \
3270 FREETYPE_MINOR )
Werner Lemberga929ba92000-06-25 06:47:11 +00003271
Werner Lembergdeb4e982000-06-29 03:14:25 +00003272 if ( !library )
3273 return FT_Err_Invalid_Library_Handle;
3274
3275 if ( !clazz )
David Turnerf0df85b2000-06-22 00:17:42 +00003276 return FT_Err_Invalid_Argument;
3277
3278 /* check freetype version */
3279 if ( clazz->module_requires > FREETYPE_VER_FIXED )
3280 return FT_Err_Invalid_Version;
3281
3282 /* look for a module with the same name in the library's table */
3283 for ( nn = 0; nn < library->num_modules; nn++ )
3284 {
3285 module = library->modules[nn];
David Turnerd15bc0d2002-04-12 09:31:48 +00003286 if ( ft_strcmp( module->clazz->module_name, clazz->module_name ) == 0 )
David Turnerf0df85b2000-06-22 00:17:42 +00003287 {
3288 /* this installed module has the same name, compare their versions */
3289 if ( clazz->module_version <= module->clazz->module_version )
3290 return FT_Err_Lower_Module_Version;
3291
3292 /* remove the module from our list, then exit the loop to replace */
3293 /* it by our new version.. */
3294 FT_Remove_Module( library, module );
3295 break;
3296 }
3297 }
3298
3299 memory = library->memory;
3300 error = FT_Err_Ok;
3301
3302 if ( library->num_modules >= FT_MAX_MODULES )
3303 {
3304 error = FT_Err_Too_Many_Drivers;
3305 goto Exit;
3306 }
3307
3308 /* allocate module object */
Werner Lemberg68e9f922002-09-27 11:09:23 +00003309 if ( FT_ALLOC( module, clazz->module_size ) )
David Turnerf0df85b2000-06-22 00:17:42 +00003310 goto Exit;
3311
Werner Lembergdeb4e982000-06-29 03:14:25 +00003312 /* base initialization */
David Turnerf0df85b2000-06-22 00:17:42 +00003313 module->library = library;
3314 module->memory = memory;
3315 module->clazz = (FT_Module_Class*)clazz;
3316
Werner Lembergdeb4e982000-06-29 03:14:25 +00003317 /* check whether the module is a renderer - this must be performed */
3318 /* before the normal module initialization */
Werner Lemberga929ba92000-06-25 06:47:11 +00003319 if ( FT_MODULE_IS_RENDERER( module ) )
David Turnerf0df85b2000-06-22 00:17:42 +00003320 {
3321 /* add to the renderers list */
Werner Lemberga929ba92000-06-25 06:47:11 +00003322 error = ft_add_renderer( module );
3323 if ( error )
3324 goto Fail;
David Turnerf0df85b2000-06-22 00:17:42 +00003325 }
3326
Werner Lembergcc9fc492000-06-30 06:21:26 +00003327 /* is the module a auto-hinter? */
3328 if ( FT_MODULE_IS_HINTER( module ) )
David Turner5ae831c2000-06-30 01:31:22 +00003329 library->auto_hinter = module;
Werner Lembergfbeb41d2000-07-02 00:27:53 +00003330
David Turnerf0df85b2000-06-22 00:17:42 +00003331 /* if the module is a font driver */
Werner Lemberga929ba92000-06-25 06:47:11 +00003332 if ( FT_MODULE_IS_DRIVER( module ) )
David Turnerf0df85b2000-06-22 00:17:42 +00003333 {
3334 /* allocate glyph loader if needed */
Werner Lembergf8ba2002002-03-30 13:16:35 +00003335 FT_Driver driver = FT_DRIVER( module );
Werner Lemberga929ba92000-06-25 06:47:11 +00003336
Werner Lembergdeb4e982000-06-29 03:14:25 +00003337
David Turneref3c1262002-03-14 09:22:48 +00003338 driver->clazz = (FT_Driver_Class)module->clazz;
Werner Lemberga929ba92000-06-25 06:47:11 +00003339 if ( FT_DRIVER_USES_OUTLINES( driver ) )
David Turnerf0df85b2000-06-22 00:17:42 +00003340 {
3341 error = FT_GlyphLoader_New( memory, &driver->glyph_loader );
Werner Lemberga929ba92000-06-25 06:47:11 +00003342 if ( error )
3343 goto Fail;
David Turnerf0df85b2000-06-22 00:17:42 +00003344 }
3345 }
3346
Werner Lemberga929ba92000-06-25 06:47:11 +00003347 if ( clazz->module_init )
David Turnerf0df85b2000-06-22 00:17:42 +00003348 {
Werner Lemberga929ba92000-06-25 06:47:11 +00003349 error = clazz->module_init( module );
3350 if ( error )
3351 goto Fail;
David Turnerf0df85b2000-06-22 00:17:42 +00003352 }
3353
3354 /* add module to the library's table */
Werner Lemberga929ba92000-06-25 06:47:11 +00003355 library->modules[library->num_modules++] = module;
Werner Lembergdeb4e982000-06-29 03:14:25 +00003356
David Turnerf0df85b2000-06-22 00:17:42 +00003357 Exit:
3358 return error;
Werner Lembergdeb4e982000-06-29 03:14:25 +00003359
David Turnerf0df85b2000-06-22 00:17:42 +00003360 Fail:
Werner Lemberga929ba92000-06-25 06:47:11 +00003361 if ( FT_MODULE_IS_DRIVER( module ) )
David Turnerf0df85b2000-06-22 00:17:42 +00003362 {
Werner Lemberga929ba92000-06-25 06:47:11 +00003363 FT_Driver driver = FT_DRIVER( module );
Werner Lembergdeb4e982000-06-29 03:14:25 +00003364
Werner Lemberga929ba92000-06-25 06:47:11 +00003365
3366 if ( FT_DRIVER_USES_OUTLINES( driver ) )
David Turnerf0df85b2000-06-22 00:17:42 +00003367 FT_GlyphLoader_Done( driver->glyph_loader );
3368 }
Werner Lembergdeb4e982000-06-29 03:14:25 +00003369
Werner Lemberga929ba92000-06-25 06:47:11 +00003370 if ( FT_MODULE_IS_RENDERER( module ) )
David Turnerf0df85b2000-06-22 00:17:42 +00003371 {
Werner Lemberga929ba92000-06-25 06:47:11 +00003372 FT_Renderer renderer = FT_RENDERER( module );
3373
3374
3375 if ( renderer->raster )
David Turnerf0df85b2000-06-22 00:17:42 +00003376 renderer->clazz->raster_class->raster_done( renderer->raster );
3377 }
Werner Lemberga929ba92000-06-25 06:47:11 +00003378
David Turnere459d742002-03-22 13:52:37 +00003379 FT_FREE( module );
David Turnerf0df85b2000-06-22 00:17:42 +00003380 goto Exit;
3381 }
3382
David Turnerf0df85b2000-06-22 00:17:42 +00003383
Werner Lemberg748b1712005-12-25 09:15:09 +00003384 /* documentation is in ftmodapi.h */
Werner Lemberg90a03302000-11-07 17:21:11 +00003385
Werner Lembergf814d0f2001-06-27 16:18:10 +00003386 FT_EXPORT_DEF( FT_Module )
3387 FT_Get_Module( FT_Library library,
3388 const char* module_name )
David Turnerf0df85b2000-06-22 00:17:42 +00003389 {
Werner Lembergdeb4e982000-06-29 03:14:25 +00003390 FT_Module result = 0;
3391 FT_Module* cur;
3392 FT_Module* limit;
David Turnerf0df85b2000-06-22 00:17:42 +00003393
Werner Lemberga929ba92000-06-25 06:47:11 +00003394
Werner Lembergdeb4e982000-06-29 03:14:25 +00003395 if ( !library || !module_name )
3396 return result;
3397
3398 cur = library->modules;
3399 limit = cur + library->num_modules;
3400
David Turnerf0df85b2000-06-22 00:17:42 +00003401 for ( ; cur < limit; cur++ )
David Turnerd15bc0d2002-04-12 09:31:48 +00003402 if ( ft_strcmp( cur[0]->clazz->module_name, module_name ) == 0 )
David Turnerf0df85b2000-06-22 00:17:42 +00003403 {
3404 result = cur[0];
3405 break;
3406 }
3407
3408 return result;
3409 }
3410
Werner Lemberga929ba92000-06-25 06:47:11 +00003411
Werner Lemberg8ec9dfd2000-11-07 23:56:02 +00003412 /* documentation is in ftobjs.h */
3413
Werner Lembergf814d0f2001-06-27 16:18:10 +00003414 FT_BASE_DEF( const void* )
3415 FT_Get_Module_Interface( FT_Library library,
3416 const char* mod_name )
David Turnerf0df85b2000-06-22 00:17:42 +00003417 {
3418 FT_Module module;
Werner Lembergdeb4e982000-06-29 03:14:25 +00003419
3420
3421 /* test for valid `library' delayed to FT_Get_Module() */
Werner Lemberga929ba92000-06-25 06:47:11 +00003422
David Turnerf0df85b2000-06-22 00:17:42 +00003423 module = FT_Get_Module( library, mod_name );
Werner Lemberga929ba92000-06-25 06:47:11 +00003424
David Turnerf0df85b2000-06-22 00:17:42 +00003425 return module ? module->clazz->module_interface : 0;
Werner Lembergdeb4e982000-06-29 03:14:25 +00003426 }
David Turnerf0df85b2000-06-22 00:17:42 +00003427
3428
David Turnerb72d8a82003-09-29 20:33:37 +00003429 FT_BASE_DEF( FT_Pointer )
3430 ft_module_get_service( FT_Module module,
3431 const char* service_id )
3432 {
3433 FT_Pointer result = NULL;
3434
3435 if ( module )
3436 {
3437 FT_ASSERT( module->clazz && module->clazz->get_interface );
3438
3439 /* first, look for the service in the module
3440 */
3441 if ( module->clazz->get_interface )
3442 result = module->clazz->get_interface( module, service_id );
3443
3444 if ( result == NULL )
3445 {
3446 /* we didn't find it, look in all other modules then
3447 */
3448 FT_Library library = module->library;
3449 FT_Module* cur = library->modules;
3450 FT_Module* limit = cur + library->num_modules;
3451
3452 for ( ; cur < limit; cur++ )
3453 {
3454 if ( cur[0] != module )
3455 {
3456 FT_ASSERT( cur[0]->clazz );
3457
3458 if ( cur[0]->clazz->get_interface )
3459 {
3460 result = cur[0]->clazz->get_interface( cur[0], service_id );
3461 if ( result != NULL )
3462 break;
3463 }
3464 }
3465 }
3466 }
3467 }
3468
3469 return result;
3470 }
3471
3472
Werner Lemberg748b1712005-12-25 09:15:09 +00003473 /* documentation is in ftmodapi.h */
Werner Lemberg90a03302000-11-07 17:21:11 +00003474
Werner Lembergf814d0f2001-06-27 16:18:10 +00003475 FT_EXPORT_DEF( FT_Error )
3476 FT_Remove_Module( FT_Library library,
3477 FT_Module module )
David Turnerf0df85b2000-06-22 00:17:42 +00003478 {
3479 /* try to find the module from the table, then remove it from there */
Werner Lembergdeb4e982000-06-29 03:14:25 +00003480
3481 if ( !library )
3482 return FT_Err_Invalid_Library_Handle;
3483
3484 if ( module )
David Turnerf0df85b2000-06-22 00:17:42 +00003485 {
3486 FT_Module* cur = library->modules;
3487 FT_Module* limit = cur + library->num_modules;
3488
Werner Lemberga929ba92000-06-25 06:47:11 +00003489
David Turnerf0df85b2000-06-22 00:17:42 +00003490 for ( ; cur < limit; cur++ )
3491 {
Werner Lembergdeb4e982000-06-29 03:14:25 +00003492 if ( cur[0] == module )
David Turnerf0df85b2000-06-22 00:17:42 +00003493 {
3494 /* remove it from the table */
3495 library->num_modules--;
3496 limit--;
Werner Lemberga929ba92000-06-25 06:47:11 +00003497 while ( cur < limit )
David Turnerf0df85b2000-06-22 00:17:42 +00003498 {
3499 cur[0] = cur[1];
3500 cur++;
3501 }
3502 limit[0] = 0;
3503
3504 /* destroy the module */
Werner Lemberga929ba92000-06-25 06:47:11 +00003505 Destroy_Module( module );
David Turnerf0df85b2000-06-22 00:17:42 +00003506
3507 return FT_Err_Ok;
3508 }
3509 }
3510 }
Werner Lembergb48a6092000-07-09 19:15:30 +00003511 return FT_Err_Invalid_Driver_Handle;
David Turnerf0df85b2000-06-22 00:17:42 +00003512 }
3513
3514
David Turnerf0df85b2000-06-22 00:17:42 +00003515 /*************************************************************************/
3516 /*************************************************************************/
3517 /*************************************************************************/
3518 /**** ****/
3519 /**** ****/
3520 /**** L I B R A R Y ****/
3521 /**** ****/
3522 /**** ****/
3523 /*************************************************************************/
3524 /*************************************************************************/
3525 /*************************************************************************/
3526
Werner Lemberga929ba92000-06-25 06:47:11 +00003527
Werner Lemberg748b1712005-12-25 09:15:09 +00003528 /* documentation is in ftmodapi.h */
Werner Lemberg90a03302000-11-07 17:21:11 +00003529
Werner Lembergf814d0f2001-06-27 16:18:10 +00003530 FT_EXPORT_DEF( FT_Error )
3531 FT_New_Library( FT_Memory memory,
3532 FT_Library *alibrary )
David Turnerf0df85b2000-06-22 00:17:42 +00003533 {
3534 FT_Library library = 0;
3535 FT_Error error;
3536
3537
3538 if ( !memory )
3539 return FT_Err_Invalid_Argument;
3540
David Turnerf5749602002-04-18 10:07:26 +00003541#ifdef FT_DEBUG_LEVEL_ERROR
David Turner53b3fa12002-02-24 05:26:57 +00003542 /* init debugging support */
3543 ft_debug_init();
David Turnerf5749602002-04-18 10:07:26 +00003544#endif
David Turner53b3fa12002-02-24 05:26:57 +00003545
David Turnerf0df85b2000-06-22 00:17:42 +00003546 /* first of all, allocate the library object */
David Turnere459d742002-03-22 13:52:37 +00003547 if ( FT_NEW( library ) )
David Turnerf0df85b2000-06-22 00:17:42 +00003548 return error;
3549
3550 library->memory = memory;
3551
3552 /* allocate the render pool */
3553 library->raster_pool_size = FT_RENDER_POOL_SIZE;
David Turnere459d742002-03-22 13:52:37 +00003554 if ( FT_ALLOC( library->raster_pool, FT_RENDER_POOL_SIZE ) )
David Turnerf0df85b2000-06-22 00:17:42 +00003555 goto Fail;
3556
3557 /* That's ok now */
3558 *alibrary = library;
3559
3560 return FT_Err_Ok;
3561
3562 Fail:
David Turnere459d742002-03-22 13:52:37 +00003563 FT_FREE( library );
David Turnerf0df85b2000-06-22 00:17:42 +00003564 return error;
3565 }
3566
3567
David Turner83b4a4b2002-03-06 12:42:34 +00003568 /* documentation is in freetype.h */
David Turner25a6e3a2002-06-10 23:03:35 +00003569
David Turner83b4a4b2002-03-06 12:42:34 +00003570 FT_EXPORT_DEF( void )
3571 FT_Library_Version( FT_Library library,
3572 FT_Int *amajor,
3573 FT_Int *aminor,
3574 FT_Int *apatch )
3575 {
3576 FT_Int major = 0;
3577 FT_Int minor = 0;
3578 FT_Int patch = 0;
3579
David Turner25a6e3a2002-06-10 23:03:35 +00003580
David Turner83b4a4b2002-03-06 12:42:34 +00003581 if ( library )
3582 {
3583 major = library->version_major;
3584 minor = library->version_minor;
3585 patch = library->version_patch;
3586 }
David Turner25a6e3a2002-06-10 23:03:35 +00003587
David Turnerd48575e2002-09-18 23:18:36 +00003588 if ( amajor )
David Turner83b4a4b2002-03-06 12:42:34 +00003589 *amajor = major;
David Turner25a6e3a2002-06-10 23:03:35 +00003590
David Turnerd48575e2002-09-18 23:18:36 +00003591 if ( aminor )
David Turner83b4a4b2002-03-06 12:42:34 +00003592 *aminor = minor;
David Turner25a6e3a2002-06-10 23:03:35 +00003593
David Turnerd48575e2002-09-18 23:18:36 +00003594 if ( apatch )
David Turner83b4a4b2002-03-06 12:42:34 +00003595 *apatch = patch;
David Turner25a6e3a2002-06-10 23:03:35 +00003596 }
David Turner83b4a4b2002-03-06 12:42:34 +00003597
3598
Werner Lemberg748b1712005-12-25 09:15:09 +00003599 /* documentation is in ftmodapi.h */
Werner Lemberg90a03302000-11-07 17:21:11 +00003600
Werner Lembergf814d0f2001-06-27 16:18:10 +00003601 FT_EXPORT_DEF( FT_Error )
3602 FT_Done_Library( FT_Library library )
David Turnerf0df85b2000-06-22 00:17:42 +00003603 {
3604 FT_Memory memory;
David Turnerf0df85b2000-06-22 00:17:42 +00003605
3606
3607 if ( !library )
3608 return FT_Err_Invalid_Library_Handle;
3609
3610 memory = library->memory;
3611
3612 /* Discard client-data */
3613 if ( library->generic.finalizer )
3614 library->generic.finalizer( library );
3615
3616 /* Close all modules in the library */
Werner Lembergf41e71a2001-12-20 21:22:02 +00003617#if 1
David Turnerc8087482001-12-20 13:14:18 +00003618 while ( library->num_modules > 0 )
3619 FT_Remove_Module( library, library->modules[0] );
Werner Lembergf41e71a2001-12-20 21:22:02 +00003620#else
David Turnerf0df85b2000-06-22 00:17:42 +00003621 {
Werner Lembergf41e71a2001-12-20 21:22:02 +00003622 FT_UInt n;
David Turnerf0df85b2000-06-22 00:17:42 +00003623
Werner Lemberga929ba92000-06-25 06:47:11 +00003624
Werner Lembergf41e71a2001-12-20 21:22:02 +00003625 for ( n = 0; n < library->num_modules; n++ )
David Turnerf0df85b2000-06-22 00:17:42 +00003626 {
Werner Lembergf41e71a2001-12-20 21:22:02 +00003627 FT_Module module = library->modules[n];
3628
3629
3630 if ( module )
3631 {
3632 Destroy_Module( module );
3633 library->modules[n] = 0;
3634 }
David Turnerf0df85b2000-06-22 00:17:42 +00003635 }
3636 }
David Turnerc8087482001-12-20 13:14:18 +00003637#endif
David Turnerf0df85b2000-06-22 00:17:42 +00003638
3639 /* Destroy raster objects */
David Turnere459d742002-03-22 13:52:37 +00003640 FT_FREE( library->raster_pool );
David Turnerf0df85b2000-06-22 00:17:42 +00003641 library->raster_pool_size = 0;
3642
David Turnere459d742002-03-22 13:52:37 +00003643 FT_FREE( library );
David Turnerf0df85b2000-06-22 00:17:42 +00003644 return FT_Err_Ok;
3645 }
3646
3647
Werner Lemberg748b1712005-12-25 09:15:09 +00003648 /* documentation is in ftmodapi.h */
Werner Lemberg90a03302000-11-07 17:21:11 +00003649
Werner Lembergf814d0f2001-06-27 16:18:10 +00003650 FT_EXPORT_DEF( void )
3651 FT_Set_Debug_Hook( FT_Library library,
3652 FT_UInt hook_index,
3653 FT_DebugHook_Func debug_hook )
David Turnerf0df85b2000-06-22 00:17:42 +00003654 {
3655 if ( library && debug_hook &&
3656 hook_index <
3657 ( sizeof ( library->debug_hooks ) / sizeof ( void* ) ) )
3658 library->debug_hooks[hook_index] = debug_hook;
3659 }
3660
Werner Lemberg8e6f8c42006-02-17 08:07:09 +00003661
David Turner0b5dc4d2006-02-21 22:36:23 +00003662 /* documentation is in ftmodapi.h */
3663
3664 FT_EXPORT_DEF( FT_TrueTypeEngineType )
3665 FT_Get_TrueType_Engine_Type( FT_Library library )
3666 {
3667 FT_TrueTypeEngineType result = FT_TRUETYPE_ENGINE_TYPE_NONE;
3668
Werner Lemberg5edafed2006-02-22 08:23:35 +00003669
David Turner0b5dc4d2006-02-21 22:36:23 +00003670 if ( library )
3671 {
3672 FT_Module module = FT_Get_Module( library, "truetype" );
3673
Werner Lemberg5edafed2006-02-22 08:23:35 +00003674
David Turner0b5dc4d2006-02-21 22:36:23 +00003675 if ( module )
3676 {
3677 FT_Service_TrueTypeEngine service;
3678
Werner Lemberg5edafed2006-02-22 08:23:35 +00003679
3680 service = ft_module_get_service( module,
3681 FT_SERVICE_ID_TRUETYPE_ENGINE );
David Turner0b5dc4d2006-02-21 22:36:23 +00003682 if ( service )
3683 result = service->engine_type;
3684 }
3685 }
Werner Lemberg5edafed2006-02-22 08:23:35 +00003686
David Turner0b5dc4d2006-02-21 22:36:23 +00003687 return result;
3688 }
3689
Werner Lemberg5edafed2006-02-22 08:23:35 +00003690
David Turnercda2d952006-02-16 22:45:31 +00003691#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
Werner Lemberg8e6f8c42006-02-17 08:07:09 +00003692
David Turnercda2d952006-02-16 22:45:31 +00003693 FT_BASE_DEF( FT_Error )
3694 ft_stub_set_char_sizes( FT_Size size,
3695 FT_F26Dot6 width,
3696 FT_F26Dot6 height,
3697 FT_UInt horz_res,
3698 FT_UInt vert_res )
3699 {
3700 FT_Size_RequestRec req;
3701 FT_Driver driver = size->face->driver;
3702
Werner Lemberg8e6f8c42006-02-17 08:07:09 +00003703
David Turnercda2d952006-02-16 22:45:31 +00003704 if ( driver->clazz->request_size )
3705 {
3706 req.type = FT_SIZE_REQUEST_TYPE_NOMINAL;
3707 req.width = width;
3708 req.height = height;
3709
3710 if ( horz_res == 0 )
3711 horz_res = vert_res;
3712
3713 if ( vert_res == 0 )
3714 vert_res = horz_res;
3715
3716 if ( horz_res == 0 )
3717 horz_res = vert_res = 72;
3718
3719 req.horiResolution = horz_res;
3720 req.vertResolution = vert_res;
3721
3722 return driver->clazz->request_size( size, &req );
3723 }
Werner Lemberg8e6f8c42006-02-17 08:07:09 +00003724
David Turnercda2d952006-02-16 22:45:31 +00003725 return 0;
3726 }
3727
3728
3729 FT_BASE_DEF( FT_Error )
Werner Lemberg8e6f8c42006-02-17 08:07:09 +00003730 ft_stub_set_pixel_sizes( FT_Size size,
3731 FT_UInt width,
3732 FT_UInt height )
David Turnercda2d952006-02-16 22:45:31 +00003733 {
3734 FT_Size_RequestRec req;
3735 FT_Driver driver = size->face->driver;
3736
Werner Lemberg8e6f8c42006-02-17 08:07:09 +00003737
David Turnercda2d952006-02-16 22:45:31 +00003738 if ( driver->clazz->request_size )
3739 {
3740 req.type = FT_SIZE_REQUEST_TYPE_NOMINAL;
Werner Lemberg8e6f8c42006-02-17 08:07:09 +00003741 req.width = width << 6;
David Turnercda2d952006-02-16 22:45:31 +00003742 req.height = height << 6;
3743 req.horiResolution = 0;
3744 req.vertResolution = 0;
3745
3746 return driver->clazz->request_size( size, &req );
3747 }
Werner Lemberg8e6f8c42006-02-17 08:07:09 +00003748
David Turnercda2d952006-02-16 22:45:31 +00003749 return 0;
3750 }
Werner Lemberg8e6f8c42006-02-17 08:07:09 +00003751
David Turnercda2d952006-02-16 22:45:31 +00003752#endif /* FT_CONFIG_OPTION_OLD_INTERNALS */
David Turnerf0df85b2000-06-22 00:17:42 +00003753
David Turnerd2b1f351999-12-16 23:11:37 +00003754/* END */