blob: 9dce576e145048f7714b19db3895ade3630c1d75 [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 Lembergd40cd0b2010-01-14 20:32:21 +01007/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, */
8/* 2010 by */
Werner Lemberg4e6dd852000-06-05 05:26:15 +00009/* David Turner, Robert Wilhelm, and Werner Lemberg. */
David Turnerd2b1f351999-12-16 23:11:37 +000010/* */
Werner Lemberg4e6dd852000-06-05 05:26:15 +000011/* This file is part of the FreeType project, and may only be used, */
12/* modified, and distributed under the terms of the FreeType project */
David Turnerd2b1f351999-12-16 23:11:37 +000013/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
14/* this file you indicate that you have read the license and */
15/* understand and accept it fully. */
16/* */
17/***************************************************************************/
18
Werner Lembergcc069be2000-12-08 16:17:16 +000019
20#include <ft2build.h>
21#include FT_LIST_H
David Turner7fe38a52002-01-04 09:47:30 +000022#include FT_OUTLINE_H
Werner Lemberg645af082004-09-06 07:06:56 +000023#include FT_INTERNAL_VALIDATE_H
Werner Lembergcc069be2000-12-08 16:17:16 +000024#include FT_INTERNAL_OBJECTS_H
25#include FT_INTERNAL_DEBUG_H
Werner Lemberg75435332004-02-25 12:58:54 +000026#include FT_INTERNAL_RFORK_H
Werner Lembergcc069be2000-12-08 16:17:16 +000027#include FT_INTERNAL_STREAM_H
David Turner621e4882002-12-16 21:51:24 +000028#include FT_INTERNAL_SFNT_H /* for SFNT_Load_Table_Func */
Werner Lembergcc069be2000-12-08 16:17:16 +000029#include FT_TRUETYPE_TABLES_H
Suzuki, Toshiya (鈴木俊哉)af48cb02008-10-05 02:53:06 +000030#include FT_TRUETYPE_TAGS_H
Antoine Lecac96f69d2002-12-03 00:39:16 +000031#include FT_TRUETYPE_IDS_H
Werner Lemberg7880dd62000-01-10 17:19:45 +000032
Werner Lemberg5e3614f2003-09-12 19:38:13 +000033#include FT_SERVICE_SFNT_H
David Turnerc313c502003-09-11 19:51:54 +000034#include FT_SERVICE_POSTSCRIPT_NAME_H
35#include FT_SERVICE_GLYPH_DICT_H
Werner Lemberg91a67472003-12-17 14:28:22 +000036#include FT_SERVICE_TT_CMAP_H
Wu, Chia-I (吳佳一)108fdbb2006-01-16 15:35:56 +000037#include FT_SERVICE_KERNING_H
David Turner0b5dc4d2006-02-21 22:36:23 +000038#include FT_SERVICE_TRUETYPE_ENGINE_H
David Turnerc313c502003-09-11 19:51:54 +000039
Werner Lembergd40cd0b2010-01-14 20:32:21 +010040#ifdef FT_CONFIG_OPTION_MAC_FONTS
Suzuki, Toshiya (鈴木俊哉)f4147022008-10-02 01:43:18 +000041#include "ftbase.h"
Werner Lembergd40cd0b2010-01-14 20:32:21 +010042#endif
Suzuki, Toshiya (鈴木俊哉)f4147022008-10-02 01:43:18 +000043
Wu, Chia-I (吳佳一)2e48a1a2006-02-27 09:18:07 +000044#define GRID_FIT_METRICS
Werner Lemberg013efd12003-09-17 05:26:33 +000045
Werner Lembergb972a2a2008-12-11 08:55:48 +000046
David Turnerc313c502003-09-11 19:51:54 +000047 FT_BASE_DEF( FT_Pointer )
48 ft_service_list_lookup( FT_ServiceDesc service_descriptors,
49 const char* service_id )
50 {
51 FT_Pointer result = NULL;
52 FT_ServiceDesc desc = service_descriptors;
David Turnere2d12842003-09-21 17:15:55 +000053
Werner Lemberg013efd12003-09-17 05:26:33 +000054
David Turnerc313c502003-09-11 19:51:54 +000055 if ( desc && service_id )
56 {
57 for ( ; desc->serv_id != NULL; desc++ )
58 {
59 if ( ft_strcmp( desc->serv_id, service_id ) == 0 )
60 {
Werner Lemberg013efd12003-09-17 05:26:33 +000061 result = (FT_Pointer)desc->serv_data;
David Turnerc313c502003-09-11 19:51:54 +000062 break;
63 }
64 }
65 }
Werner Lemberg013efd12003-09-17 05:26:33 +000066
David Turnerc313c502003-09-11 19:51:54 +000067 return result;
David Turnere2d12842003-09-21 17:15:55 +000068 }
Werner Lemberg3c403e42002-08-06 21:47:40 +000069
Werner Lemberg013efd12003-09-17 05:26:33 +000070
David Turnered54f282002-03-22 17:09:52 +000071 FT_BASE_DEF( void )
72 ft_validator_init( FT_Validator valid,
73 const FT_Byte* base,
74 const FT_Byte* limit,
75 FT_ValidationLevel level )
76 {
77 valid->base = base;
78 valid->limit = limit;
79 valid->level = level;
Werner Lemberg8acb8672005-03-08 11:43:36 +000080 valid->error = FT_Err_Ok;
David Turnered54f282002-03-22 17:09:52 +000081 }
David Turner25a6e3a2002-06-10 23:03:35 +000082
David Turnered54f282002-03-22 17:09:52 +000083
84 FT_BASE_DEF( FT_Int )
85 ft_validator_run( FT_Validator valid )
86 {
Werner Lemberg12342992006-08-19 11:18:09 +000087 /* This function doesn't work! None should call it. */
88 FT_UNUSED( valid );
89
David Turner2b21a932006-08-16 09:24:32 +000090 return -1;
David Turnered54f282002-03-22 17:09:52 +000091 }
92
Werner Lembergf8ba2002002-03-30 13:16:35 +000093
David Turnered54f282002-03-22 17:09:52 +000094 FT_BASE_DEF( void )
95 ft_validator_error( FT_Validator valid,
96 FT_Error error )
97 {
Jens Claudiusa787f452006-08-27 11:26:18 +000098 /* since the cast below also disables the compiler's */
99 /* type check, we introduce a dummy variable, which */
100 /* will be optimized away */
Werner Lemberg607dec72007-05-15 06:49:37 +0000101 volatile ft_jmp_buf* jump_buffer = &valid->jump_buffer;
Jens Claudiusa787f452006-08-27 11:26:18 +0000102
103
David Turnered54f282002-03-22 17:09:52 +0000104 valid->error = error;
Jens Claudiusa787f452006-08-27 11:26:18 +0000105
106 /* throw away volatileness; use `jump_buffer' or the */
107 /* compiler may warn about an unused local variable */
Werner Lemberg607dec72007-05-15 06:49:37 +0000108 ft_longjmp( *(ft_jmp_buf*) jump_buffer, 1 );
David Turner25a6e3a2002-06-10 23:03:35 +0000109 }
Werner Lemberga929ba92000-06-25 06:47:11 +0000110
Werner Lemberga3b6c6c2000-05-31 06:55:12 +0000111
David Turnerd2b1f351999-12-16 23:11:37 +0000112 /*************************************************************************/
113 /*************************************************************************/
114 /*************************************************************************/
115 /**** ****/
116 /**** ****/
David Turnerf0df85b2000-06-22 00:17:42 +0000117 /**** S T R E A M ****/
118 /**** ****/
119 /**** ****/
120 /*************************************************************************/
121 /*************************************************************************/
122 /*************************************************************************/
123
Werner Lemberg7880dd62000-01-10 17:19:45 +0000124
Werner Lemberg75435332004-02-25 12:58:54 +0000125 /* create a new input stream from an FT_Open_Args structure */
126 /* */
127 FT_BASE_DEF( FT_Error )
128 FT_Stream_New( FT_Library library,
129 const FT_Open_Args* args,
130 FT_Stream *astream )
David Turner7663f222000-02-13 13:37:38 +0000131 {
Werner Lemberg547a2522000-02-16 08:23:58 +0000132 FT_Error error;
133 FT_Memory memory;
134 FT_Stream stream;
135
Werner Lemberga3b6c6c2000-05-31 06:55:12 +0000136
Suzuki, Toshiya (鈴木俊哉)4c60bd92008-08-19 15:35:44 +0000137 *astream = 0;
138
Werner Lemberg2fbf7e42000-06-02 00:01:14 +0000139 if ( !library )
140 return FT_Err_Invalid_Library_Handle;
141
142 if ( !args )
143 return FT_Err_Invalid_Argument;
144
Werner Lembergfe3433c2010-07-18 18:41:47 +0200145 memory = library->memory;
Werner Lembergf8ba2002002-03-30 13:16:35 +0000146
David Turnere459d742002-03-22 13:52:37 +0000147 if ( FT_NEW( stream ) )
David Turner37379e22000-03-28 11:22:31 +0000148 goto Exit;
David Turnere49ab252000-05-16 23:44:38 +0000149
David Turner7663f222000-02-13 13:37:38 +0000150 stream->memory = memory;
David Turnere49ab252000-05-16 23:44:38 +0000151
David Turnerb08fe2d2002-08-27 20:20:29 +0000152 if ( args->flags & FT_OPEN_MEMORY )
Just van Rossumd35aea72000-03-02 01:07:50 +0000153 {
David Turner53b3fa12002-02-24 05:26:57 +0000154 /* create a memory-based stream */
David Turner7d3a2642002-03-20 10:49:31 +0000155 FT_Stream_OpenMemory( stream,
Werner Lembergf8ba2002002-03-30 13:16:35 +0000156 (const FT_Byte*)args->memory_base,
157 args->memory_size );
David Turner4f2c5542000-05-12 10:19:41 +0000158 }
David Turnerb08fe2d2002-08-27 20:20:29 +0000159 else if ( args->flags & FT_OPEN_PATHNAME )
David Turner4f2c5542000-05-12 10:19:41 +0000160 {
David Turner53b3fa12002-02-24 05:26:57 +0000161 /* create a normal system stream */
162 error = FT_Stream_Open( stream, args->pathname );
David Turner4f2c5542000-05-12 10:19:41 +0000163 stream->pathname.pointer = args->pathname;
164 }
David Turnerb08fe2d2002-08-27 20:20:29 +0000165 else if ( ( args->flags & FT_OPEN_STREAM ) && args->stream )
David Turner4f2c5542000-05-12 10:19:41 +0000166 {
David Turner53b3fa12002-02-24 05:26:57 +0000167 /* use an existing, user-provided stream */
168
Werner Lemberg58b17f92000-07-27 23:29:08 +0000169 /* in this case, we do not need to allocate a new stream object */
170 /* since the caller is responsible for closing it himself */
David Turnere459d742002-03-22 13:52:37 +0000171 FT_FREE( stream );
David Turnerc5cdf8b2000-07-27 21:40:22 +0000172 stream = args->stream;
David Turner4f2c5542000-05-12 10:19:41 +0000173 }
174 else
David Turner4f2c5542000-05-12 10:19:41 +0000175 error = FT_Err_Invalid_Argument;
David Turnere49ab252000-05-16 23:44:38 +0000176
Werner Lemberg547a2522000-02-16 08:23:58 +0000177 if ( error )
David Turnere459d742002-03-22 13:52:37 +0000178 FT_FREE( stream );
David Turner53b3fa12002-02-24 05:26:57 +0000179 else
180 stream->memory = memory; /* just to be certain */
David Turnere49ab252000-05-16 23:44:38 +0000181
David Turner7663f222000-02-13 13:37:38 +0000182 *astream = stream;
Werner Lemberga3b6c6c2000-05-31 06:55:12 +0000183
David Turner37379e22000-03-28 11:22:31 +0000184 Exit:
David Turner7663f222000-02-13 13:37:38 +0000185 return error;
186 }
187
188
Werner Lemberg75435332004-02-25 12:58:54 +0000189 FT_BASE_DEF( void )
190 FT_Stream_Free( FT_Stream stream,
191 FT_Int external )
David Turner7663f222000-02-13 13:37:38 +0000192 {
David Turner53b3fa12002-02-24 05:26:57 +0000193 if ( stream )
David Turnerc5cdf8b2000-07-27 21:40:22 +0000194 {
195 FT_Memory memory = stream->memory;
Werner Lemberg58b17f92000-07-27 23:29:08 +0000196
Werner Lembergf8ba2002002-03-30 13:16:35 +0000197
David Turner53b3fa12002-02-24 05:26:57 +0000198 FT_Stream_Close( stream );
Werner Lemberg58b17f92000-07-27 23:29:08 +0000199
David Turner53b3fa12002-02-24 05:26:57 +0000200 if ( !external )
David Turnere459d742002-03-22 13:52:37 +0000201 FT_FREE( stream );
David Turnerc5cdf8b2000-07-27 21:40:22 +0000202 }
David Turner7663f222000-02-13 13:37:38 +0000203 }
204
Werner Lemberga3b6c6c2000-05-31 06:55:12 +0000205
Werner Lemberg6874d852008-09-20 11:50:47 +0000206 /*************************************************************************/
207 /* */
208 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
209 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
210 /* messages during execution. */
211 /* */
Werner Lembergeb81e372000-06-03 06:03:11 +0000212#undef FT_COMPONENT
213#define FT_COMPONENT trace_objs
214
Werner Lembergdeb4e982000-06-29 03:14:25 +0000215
David Turnerf0df85b2000-06-22 00:17:42 +0000216 /*************************************************************************/
217 /*************************************************************************/
218 /*************************************************************************/
219 /**** ****/
220 /**** ****/
221 /**** FACE, SIZE & GLYPH SLOT OBJECTS ****/
222 /**** ****/
223 /**** ****/
224 /*************************************************************************/
225 /*************************************************************************/
226 /*************************************************************************/
227
Werner Lembergdeb4e982000-06-29 03:14:25 +0000228
Werner Lembergf814d0f2001-06-27 16:18:10 +0000229 static FT_Error
230 ft_glyphslot_init( FT_GlyphSlot slot )
David Turnerf0df85b2000-06-22 00:17:42 +0000231 {
Werner Lembergc8f5b982010-07-12 21:13:22 +0200232 FT_Driver driver = slot->face->driver;
233 FT_Driver_Class clazz = driver->clazz;
234 FT_Memory memory = driver->root.memory;
235 FT_Error error = FT_Err_Ok;
236 FT_Slot_Internal internal = NULL;
David Turnerf0df85b2000-06-22 00:17:42 +0000237
Werner Lemberga8bbc262000-07-01 14:06:46 +0000238
David Turnerf9ca2bb2000-06-30 23:12:55 +0000239 slot->library = driver->root.library;
Werner Lembergfbeb41d2000-07-02 00:27:53 +0000240
David Turnere459d742002-03-22 13:52:37 +0000241 if ( FT_NEW( internal ) )
David Turner54e75742000-11-04 02:52:02 +0000242 goto Exit;
243
244 slot->internal = internal;
245
Werner Lemberga929ba92000-06-25 06:47:11 +0000246 if ( FT_DRIVER_USES_OUTLINES( driver ) )
David Turner54e75742000-11-04 02:52:02 +0000247 error = FT_GlyphLoader_New( memory, &internal->loader );
David Turnerf0df85b2000-06-22 00:17:42 +0000248
Werner Lemberga929ba92000-06-25 06:47:11 +0000249 if ( !error && clazz->init_slot )
David Turnerf0df85b2000-06-22 00:17:42 +0000250 error = clazz->init_slot( slot );
251
David Turner54e75742000-11-04 02:52:02 +0000252 Exit:
David Turnerf0df85b2000-06-22 00:17:42 +0000253 return error;
254 }
255
Werner Lemberge20ab692003-06-02 07:24:33 +0000256
David Turner66cbc202003-03-20 07:04:40 +0000257 FT_BASE_DEF( void )
258 ft_glyphslot_free_bitmap( FT_GlyphSlot slot )
259 {
Werner Lembergb6192822008-11-08 07:28:39 +0000260 if ( slot->internal && ( slot->internal->flags & FT_GLYPH_OWN_BITMAP ) )
David Turner66cbc202003-03-20 07:04:40 +0000261 {
262 FT_Memory memory = FT_FACE_MEMORY( slot->face );
Werner Lemberg51daa4f2003-05-18 22:40:11 +0000263
264
David Turner66cbc202003-03-20 07:04:40 +0000265 FT_FREE( slot->bitmap.buffer );
Werner Lemberg7a024102003-06-18 06:59:57 +0000266 slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP;
David Turner66cbc202003-03-20 07:04:40 +0000267 }
268 else
269 {
270 /* assume that the bitmap buffer was stolen or not */
271 /* allocated from the heap */
272 slot->bitmap.buffer = NULL;
273 }
274 }
275
276
277 FT_BASE_DEF( void )
278 ft_glyphslot_set_bitmap( FT_GlyphSlot slot,
Werner Lemberg319c00d2003-04-23 19:48:24 +0000279 FT_Byte* buffer )
David Turner66cbc202003-03-20 07:04:40 +0000280 {
281 ft_glyphslot_free_bitmap( slot );
Werner Lemberg51daa4f2003-05-18 22:40:11 +0000282
David Turner66cbc202003-03-20 07:04:40 +0000283 slot->bitmap.buffer = buffer;
Werner Lemberg51daa4f2003-05-18 22:40:11 +0000284
Werner Lemberg7a024102003-06-18 06:59:57 +0000285 FT_ASSERT( (slot->internal->flags & FT_GLYPH_OWN_BITMAP) == 0 );
Werner Lemberg51daa4f2003-05-18 22:40:11 +0000286 }
David Turner66cbc202003-03-20 07:04:40 +0000287
288
289 FT_BASE_DEF( FT_Error )
290 ft_glyphslot_alloc_bitmap( FT_GlyphSlot slot,
291 FT_ULong size )
292 {
Werner Lembergbe3c9812006-01-27 14:16:16 +0000293 FT_Memory memory = FT_FACE_MEMORY( slot->face );
294 FT_Error error;
Werner Lemberg51daa4f2003-05-18 22:40:11 +0000295
296
Werner Lemberg7a024102003-06-18 06:59:57 +0000297 if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP )
David Turner66cbc202003-03-20 07:04:40 +0000298 FT_FREE( slot->bitmap.buffer );
299 else
Werner Lemberg7a024102003-06-18 06:59:57 +0000300 slot->internal->flags |= FT_GLYPH_OWN_BITMAP;
Werner Lemberg51daa4f2003-05-18 22:40:11 +0000301
David Turner6a681fa2006-01-27 12:11:22 +0000302 (void)FT_ALLOC( slot->bitmap.buffer, size );
303 return error;
Werner Lemberg51daa4f2003-05-18 22:40:11 +0000304 }
David Turner66cbc202003-03-20 07:04:40 +0000305
David Turnerf0df85b2000-06-22 00:17:42 +0000306
Werner Lembergf814d0f2001-06-27 16:18:10 +0000307 static void
308 ft_glyphslot_clear( FT_GlyphSlot slot )
David Turnerf0df85b2000-06-22 00:17:42 +0000309 {
David Turner5ae831c2000-06-30 01:31:22 +0000310 /* free bitmap if needed */
David Turner66cbc202003-03-20 07:04:40 +0000311 ft_glyphslot_free_bitmap( slot );
Werner Lembergfbeb41d2000-07-02 00:27:53 +0000312
David Turnerf0df85b2000-06-22 00:17:42 +0000313 /* clear all public fields in the glyph slot */
David Turner3249c622002-10-31 08:30:19 +0000314 FT_ZERO( &slot->metrics );
315 FT_ZERO( &slot->outline );
316
Werner Lemberg0f1c4fa2005-06-06 07:01:47 +0000317 slot->bitmap.width = 0;
318 slot->bitmap.rows = 0;
319 slot->bitmap.pitch = 0;
David Turner3249c622002-10-31 08:30:19 +0000320 slot->bitmap.pixel_mode = 0;
Werner Lemberg0f1c4fa2005-06-06 07:01:47 +0000321 /* `slot->bitmap.buffer' has been handled by ft_glyphslot_free_bitmap */
David Turnerf0df85b2000-06-22 00:17:42 +0000322
323 slot->bitmap_left = 0;
324 slot->bitmap_top = 0;
325 slot->num_subglyphs = 0;
326 slot->subglyphs = 0;
327 slot->control_data = 0;
328 slot->control_len = 0;
329 slot->other = 0;
David Turnerb08fe2d2002-08-27 20:20:29 +0000330 slot->format = FT_GLYPH_FORMAT_NONE;
David Turnerf0df85b2000-06-22 00:17:42 +0000331
332 slot->linearHoriAdvance = 0;
333 slot->linearVertAdvance = 0;
Werner Lemberg34f4f392004-12-09 22:22:52 +0000334 slot->lsb_delta = 0;
335 slot->rsb_delta = 0;
David Turnerf0df85b2000-06-22 00:17:42 +0000336 }
337
338
Werner Lembergf814d0f2001-06-27 16:18:10 +0000339 static void
340 ft_glyphslot_done( FT_GlyphSlot slot )
David Turnerf0df85b2000-06-22 00:17:42 +0000341 {
Werner Lemberg9cc4aed2006-01-26 21:03:58 +0000342 FT_Driver driver = slot->face->driver;
343 FT_Driver_Class clazz = driver->clazz;
344 FT_Memory memory = driver->root.memory;
David Turnerf0df85b2000-06-22 00:17:42 +0000345
Werner Lemberga929ba92000-06-25 06:47:11 +0000346
David Turner54e75742000-11-04 02:52:02 +0000347 if ( clazz->done_slot )
348 clazz->done_slot( slot );
349
David Turnerf0df85b2000-06-22 00:17:42 +0000350 /* free bitmap buffer if needed */
David Turner66cbc202003-03-20 07:04:40 +0000351 ft_glyphslot_free_bitmap( slot );
David Turnerf0df85b2000-06-22 00:17:42 +0000352
Werner Lembergc6788a32009-06-07 13:09:21 +0200353 /* slot->internal might be NULL in out-of-memory situations */
354 if ( slot->internal )
David Turnerf0df85b2000-06-22 00:17:42 +0000355 {
Werner Lembergc6788a32009-06-07 13:09:21 +0200356 /* free glyph loader */
357 if ( FT_DRIVER_USES_OUTLINES( driver ) )
358 {
359 FT_GlyphLoader_Done( slot->internal->loader );
360 slot->internal->loader = 0;
361 }
David Turnerf0df85b2000-06-22 00:17:42 +0000362
Werner Lembergc6788a32009-06-07 13:09:21 +0200363 FT_FREE( slot->internal );
364 }
David Turnerf0df85b2000-06-22 00:17:42 +0000365 }
366
367
Werner Lemberg8ec9dfd2000-11-07 23:56:02 +0000368 /* documentation is in ftobjs.h */
369
Werner Lembergf814d0f2001-06-27 16:18:10 +0000370 FT_BASE_DEF( FT_Error )
371 FT_New_GlyphSlot( FT_Face face,
372 FT_GlyphSlot *aslot )
David Turnerf0df85b2000-06-22 00:17:42 +0000373 {
Werner Lemberg9cc4aed2006-01-26 21:03:58 +0000374 FT_Error error;
375 FT_Driver driver;
376 FT_Driver_Class clazz;
377 FT_Memory memory;
378 FT_GlyphSlot slot;
Werner Lemberga929ba92000-06-25 06:47:11 +0000379
David Turnerf0df85b2000-06-22 00:17:42 +0000380
Werner Lembergb9ee7372005-05-20 21:52:19 +0000381 if ( !face || !face->driver )
David Turnerf0df85b2000-06-22 00:17:42 +0000382 return FT_Err_Invalid_Argument;
383
384 driver = face->driver;
385 clazz = driver->clazz;
386 memory = driver->root.memory;
387
388 FT_TRACE4(( "FT_New_GlyphSlot: Creating new slot object\n" ));
David Turnere459d742002-03-22 13:52:37 +0000389 if ( !FT_ALLOC( slot, clazz->slot_object_size ) )
David Turnerf0df85b2000-06-22 00:17:42 +0000390 {
391 slot->face = face;
392
393 error = ft_glyphslot_init( slot );
Werner Lemberga929ba92000-06-25 06:47:11 +0000394 if ( error )
David Turnerf0df85b2000-06-22 00:17:42 +0000395 {
396 ft_glyphslot_done( slot );
David Turnere459d742002-03-22 13:52:37 +0000397 FT_FREE( slot );
David Turnerf0df85b2000-06-22 00:17:42 +0000398 goto Exit;
399 }
400
Werner Lembergb9ee7372005-05-20 21:52:19 +0000401 slot->next = face->glyph;
402 face->glyph = slot;
403
404 if ( aslot )
405 *aslot = slot;
David Turnerf0df85b2000-06-22 00:17:42 +0000406 }
Werner Lembergb9ee7372005-05-20 21:52:19 +0000407 else if ( aslot )
408 *aslot = 0;
409
David Turnerf0df85b2000-06-22 00:17:42 +0000410
411 Exit:
412 FT_TRACE4(( "FT_New_GlyphSlot: Return %d\n", error ));
413 return error;
414 }
415
416
Werner Lemberg8ec9dfd2000-11-07 23:56:02 +0000417 /* documentation is in ftobjs.h */
418
Werner Lembergf814d0f2001-06-27 16:18:10 +0000419 FT_BASE_DEF( void )
420 FT_Done_GlyphSlot( FT_GlyphSlot slot )
David Turnerf0df85b2000-06-22 00:17:42 +0000421 {
422 if ( slot )
423 {
Werner Lembergb9ee7372005-05-20 21:52:19 +0000424 FT_Driver driver = slot->face->driver;
425 FT_Memory memory = driver->root.memory;
426 FT_GlyphSlot prev;
427 FT_GlyphSlot cur;
David Turnerf0df85b2000-06-22 00:17:42 +0000428
Werner Lemberga929ba92000-06-25 06:47:11 +0000429
David Turnerf0df85b2000-06-22 00:17:42 +0000430 /* Remove slot from its parent face's list */
Werner Lembergb9ee7372005-05-20 21:52:19 +0000431 prev = NULL;
432 cur = slot->face->glyph;
Werner Lemberga929ba92000-06-25 06:47:11 +0000433
David Turnerf0df85b2000-06-22 00:17:42 +0000434 while ( cur )
435 {
436 if ( cur == slot )
437 {
Werner Lembergb9ee7372005-05-20 21:52:19 +0000438 if ( !prev )
439 slot->face->glyph = cur->next;
440 else
441 prev->next = cur->next;
442
Werner Lemberga929ba92000-06-25 06:47:11 +0000443 ft_glyphslot_done( slot );
David Turnere459d742002-03-22 13:52:37 +0000444 FT_FREE( slot );
David Turnerf0df85b2000-06-22 00:17:42 +0000445 break;
446 }
Werner Lembergb9ee7372005-05-20 21:52:19 +0000447 prev = cur;
448 cur = cur->next;
David Turnerf0df85b2000-06-22 00:17:42 +0000449 }
450 }
451 }
452
453
Werner Lemberg90a03302000-11-07 17:21:11 +0000454 /* documentation is in freetype.h */
455
Werner Lembergf814d0f2001-06-27 16:18:10 +0000456 FT_EXPORT_DEF( void )
457 FT_Set_Transform( FT_Face face,
458 FT_Matrix* matrix,
459 FT_Vector* delta )
David Turnerf0df85b2000-06-22 00:17:42 +0000460 {
David Turner54e75742000-11-04 02:52:02 +0000461 FT_Face_Internal internal;
David Turner61d6b2b2001-05-16 17:49:07 +0000462
David Turner54e75742000-11-04 02:52:02 +0000463
David Turnerf0df85b2000-06-22 00:17:42 +0000464 if ( !face )
465 return;
466
David Turner54e75742000-11-04 02:52:02 +0000467 internal = face->internal;
468
469 internal->transform_flags = 0;
David Turnerf0df85b2000-06-22 00:17:42 +0000470
471 if ( !matrix )
472 {
David Turner54e75742000-11-04 02:52:02 +0000473 internal->transform_matrix.xx = 0x10000L;
474 internal->transform_matrix.xy = 0;
475 internal->transform_matrix.yx = 0;
476 internal->transform_matrix.yy = 0x10000L;
477 matrix = &internal->transform_matrix;
David Turnerf0df85b2000-06-22 00:17:42 +0000478 }
479 else
David Turner54e75742000-11-04 02:52:02 +0000480 internal->transform_matrix = *matrix;
David Turnerf0df85b2000-06-22 00:17:42 +0000481
482 /* set transform_flags bit flag 0 if `matrix' isn't the identity */
483 if ( ( matrix->xy | matrix->yx ) ||
484 matrix->xx != 0x10000L ||
485 matrix->yy != 0x10000L )
David Turner54e75742000-11-04 02:52:02 +0000486 internal->transform_flags |= 1;
David Turnerf0df85b2000-06-22 00:17:42 +0000487
488 if ( !delta )
489 {
David Turner54e75742000-11-04 02:52:02 +0000490 internal->transform_delta.x = 0;
491 internal->transform_delta.y = 0;
492 delta = &internal->transform_delta;
David Turnerf0df85b2000-06-22 00:17:42 +0000493 }
494 else
David Turner54e75742000-11-04 02:52:02 +0000495 internal->transform_delta = *delta;
David Turnerf0df85b2000-06-22 00:17:42 +0000496
497 /* set transform_flags bit flag 1 if `delta' isn't the null vector */
498 if ( delta->x | delta->y )
David Turner54e75742000-11-04 02:52:02 +0000499 internal->transform_flags |= 2;
David Turnerf0df85b2000-06-22 00:17:42 +0000500 }
501
502
Werner Lembergf814d0f2001-06-27 16:18:10 +0000503 static FT_Renderer
504 ft_lookup_glyph_renderer( FT_GlyphSlot slot );
Werner Lembergdeb4e982000-06-29 03:14:25 +0000505
506
Wu, Chia-I (吳佳一)2e48a1a2006-02-27 09:18:07 +0000507#ifdef GRID_FIT_METRICS
508 static void
509 ft_glyphslot_grid_fit_metrics( FT_GlyphSlot slot,
510 FT_Bool vertical )
511 {
512 FT_Glyph_Metrics* metrics = &slot->metrics;
513 FT_Pos right, bottom;
514
515
516 if ( vertical )
517 {
518 metrics->horiBearingX = FT_PIX_FLOOR( metrics->horiBearingX );
519 metrics->horiBearingY = FT_PIX_CEIL ( metrics->horiBearingY );
520
521 right = FT_PIX_CEIL( metrics->vertBearingX + metrics->width );
522 bottom = FT_PIX_CEIL( metrics->vertBearingY + metrics->height );
523
524 metrics->vertBearingX = FT_PIX_FLOOR( metrics->vertBearingX );
525 metrics->vertBearingY = FT_PIX_FLOOR( metrics->vertBearingY );
526
527 metrics->width = right - metrics->vertBearingX;
528 metrics->height = bottom - metrics->vertBearingY;
529 }
530 else
531 {
532 metrics->vertBearingX = FT_PIX_FLOOR( metrics->vertBearingX );
533 metrics->vertBearingY = FT_PIX_FLOOR( metrics->vertBearingY );
534
535 right = FT_PIX_CEIL ( metrics->horiBearingX + metrics->width );
536 bottom = FT_PIX_FLOOR( metrics->horiBearingY - metrics->height );
537
538 metrics->horiBearingX = FT_PIX_FLOOR( metrics->horiBearingX );
539 metrics->horiBearingY = FT_PIX_CEIL ( metrics->horiBearingY );
540
541 metrics->width = right - metrics->horiBearingX;
542 metrics->height = metrics->horiBearingY - bottom;
543 }
544
545 metrics->horiAdvance = FT_PIX_ROUND( metrics->horiAdvance );
546 metrics->vertAdvance = FT_PIX_ROUND( metrics->vertAdvance );
547 }
548#endif /* GRID_FIT_METRICS */
549
550
Werner Lemberg90a03302000-11-07 17:21:11 +0000551 /* documentation is in freetype.h */
552
Werner Lembergf814d0f2001-06-27 16:18:10 +0000553 FT_EXPORT_DEF( FT_Error )
Werner Lemberg6b5c6692002-09-05 15:10:54 +0000554 FT_Load_Glyph( FT_Face face,
555 FT_UInt glyph_index,
556 FT_Int32 load_flags )
David Turnerf0df85b2000-06-22 00:17:42 +0000557 {
558 FT_Error error;
559 FT_Driver driver;
560 FT_GlyphSlot slot;
David Turner5ae831c2000-06-30 01:31:22 +0000561 FT_Library library;
Werner Lembergb972a2a2008-12-11 08:55:48 +0000562 FT_Bool autohint = FALSE;
David Turner5ae831c2000-06-30 01:31:22 +0000563 FT_Module hinter;
David Turnerf0df85b2000-06-22 00:17:42 +0000564
Werner Lemberga929ba92000-06-25 06:47:11 +0000565
David Turnerf0df85b2000-06-22 00:17:42 +0000566 if ( !face || !face->size || !face->glyph )
567 return FT_Err_Invalid_Face_Handle;
568
Werner Lemberg913a3652006-11-19 09:19:17 +0000569 /* The validity test for `glyph_index' is performed by the */
570 /* font drivers. */
David Turnerf0df85b2000-06-22 00:17:42 +0000571
572 slot = face->glyph;
573 ft_glyphslot_clear( slot );
574
Wu, Chia-I (吳佳一)e5ff0592006-01-15 06:00:49 +0000575 driver = face->driver;
576 library = driver->root.library;
577 hinter = library->auto_hinter;
David Turnerf0df85b2000-06-22 00:17:42 +0000578
Wu, Chia-I (吳佳一)e5ff0592006-01-15 06:00:49 +0000579 /* resolve load flags dependencies */
580
David Turnerf0df85b2000-06-22 00:17:42 +0000581 if ( load_flags & FT_LOAD_NO_RECURSE )
Werner Lembergeddd9902000-10-12 05:05:40 +0000582 load_flags |= FT_LOAD_NO_SCALE |
David Turnerc9ce9e42000-09-15 17:16:49 +0000583 FT_LOAD_IGNORE_TRANSFORM;
Werner Lembergeddd9902000-10-12 05:05:40 +0000584
Wu, Chia-I (吳佳一)e5ff0592006-01-15 06:00:49 +0000585 if ( load_flags & FT_LOAD_NO_SCALE )
586 {
587 load_flags |= FT_LOAD_NO_HINTING |
588 FT_LOAD_NO_BITMAP;
589
Werner Lembergeddd9902000-10-12 05:05:40 +0000590 load_flags &= ~FT_LOAD_RENDER;
David Turnerc9ce9e42000-09-15 17:16:49 +0000591 }
David Turnerf0df85b2000-06-22 00:17:42 +0000592
Werner Lemberg046bf8b2006-10-03 08:43:42 +0000593 /*
594 * Determine whether we need to auto-hint or not.
595 * The general rules are:
596 *
James Cloos15e8e232009-05-29 12:59:42 +0200597 * - Do only auto-hinting if we have a hinter module, a scalable font
598 * format dealing with outlines, and no transforms except simple
599 * slants and/or rotations by integer multiples of 90 degrees.
Werner Lemberg046bf8b2006-10-03 08:43:42 +0000600 *
James Cloos15e8e232009-05-29 12:59:42 +0200601 * - Then, auto-hint if FT_LOAD_FORCE_AUTOHINT is set or if we don't
602 * have a native font hinter.
Werner Lemberg046bf8b2006-10-03 08:43:42 +0000603 *
604 * - Otherwise, auto-hint for LIGHT hinting mode.
605 *
James Cloos15e8e232009-05-29 12:59:42 +0200606 * - Exception: The font is `tricky' and requires the native hinter to
607 * load properly.
Werner Lemberg046bf8b2006-10-03 08:43:42 +0000608 */
David Turnere6bb9532005-12-23 13:32:06 +0000609
James Cloos15e8e232009-05-29 12:59:42 +0200610 if ( hinter &&
611 !( load_flags & FT_LOAD_NO_HINTING ) &&
612 !( load_flags & FT_LOAD_NO_AUTOHINT ) &&
613 FT_DRIVER_IS_SCALABLE( driver ) &&
614 FT_DRIVER_USES_OUTLINES( driver ) &&
615 !FT_IS_TRICKY( face ) &&
616 ( ( face->internal->transform_matrix.yx == 0 &&
617 face->internal->transform_matrix.xx != 0 ) ||
618 ( face->internal->transform_matrix.xx == 0 &&
619 face->internal->transform_matrix.yx != 0 ) ) )
David Turner5ae831c2000-06-30 01:31:22 +0000620 {
Werner Lembergb972a2a2008-12-11 08:55:48 +0000621 if ( ( load_flags & FT_LOAD_FORCE_AUTOHINT ) ||
622 !FT_DRIVER_HAS_HINTER( driver ) )
623 autohint = TRUE;
David Turnerdf430e12006-10-01 00:09:35 +0000624 else
625 {
Werner Lemberg046bf8b2006-10-03 08:43:42 +0000626 FT_Render_Mode mode = FT_LOAD_TARGET_MODE( load_flags );
627
David Turnerdf430e12006-10-01 00:09:35 +0000628
629 if ( mode == FT_RENDER_MODE_LIGHT ||
630 face->internal->ignore_unpatented_hinter )
Werner Lembergb972a2a2008-12-11 08:55:48 +0000631 autohint = TRUE;
David Turnerdf430e12006-10-01 00:09:35 +0000632 }
Werner Lembergcc9fc492000-06-30 06:21:26 +0000633 }
Werner Lembergfbeb41d2000-07-02 00:27:53 +0000634
Wu, Chia-I (吳佳一)e5ff0592006-01-15 06:00:49 +0000635 if ( autohint )
David Turner5ae831c2000-06-30 01:31:22 +0000636 {
David Turner9657ef02002-03-14 08:49:59 +0000637 FT_AutoHinter_Service hinting;
Werner Lembergfbeb41d2000-07-02 00:27:53 +0000638
Werner Lembergcc9fc492000-06-30 06:21:26 +0000639
Werner Lemberg0d535112001-12-19 22:26:12 +0000640 /* try to load embedded bitmaps first if available */
641 /* */
642 /* XXX: This is really a temporary hack that should disappear */
643 /* promptly with FreeType 2.1! */
David Turner4937a3e2001-12-19 21:09:16 +0000644 /* */
Werner Lembergeacb9302002-10-07 10:12:43 +0000645 if ( FT_HAS_FIXED_SIZES( face ) &&
David Turner80171e02002-10-05 14:57:03 +0000646 ( load_flags & FT_LOAD_NO_BITMAP ) == 0 )
David Turner4937a3e2001-12-19 21:09:16 +0000647 {
648 error = driver->clazz->load_glyph( slot, face->size,
649 glyph_index,
650 load_flags | FT_LOAD_SBITS_ONLY );
651
David Turnerb08fe2d2002-08-27 20:20:29 +0000652 if ( !error && slot->format == FT_GLYPH_FORMAT_BITMAP )
David Turner4937a3e2001-12-19 21:09:16 +0000653 goto Load_Ok;
654 }
655
Werner Lemberg6d29f0f2008-05-03 15:54:15 +0000656 {
657 FT_Face_Internal internal = face->internal;
658 FT_Int transform_flags = internal->transform_flags;
David Turner76a5f622000-11-04 01:55:49 +0000659
Werner Lemberg6d29f0f2008-05-03 15:54:15 +0000660
661 /* since the auto-hinter calls FT_Load_Glyph by itself, */
662 /* make sure that glyphs aren't transformed */
663 internal->transform_flags = 0;
664
665 /* load auto-hinted outline */
666 hinting = (FT_AutoHinter_Service)hinter->clazz->module_interface;
667
668 error = hinting->load_glyph( (FT_AutoHinter)hinter,
669 slot, face->size,
670 glyph_index, load_flags );
671
672 internal->transform_flags = transform_flags;
673 }
David Turner5ae831c2000-06-30 01:31:22 +0000674 }
675 else
David Turner662b3442002-01-03 16:56:59 +0000676 {
David Turner5ae831c2000-06-30 01:31:22 +0000677 error = driver->clazz->load_glyph( slot,
678 face->size,
Werner Lembergcc9fc492000-06-30 06:21:26 +0000679 glyph_index,
680 load_flags );
David Turner662b3442002-01-03 16:56:59 +0000681 if ( error )
682 goto Exit;
683
Wu, Chia-I (吳佳一)2e48a1a2006-02-27 09:18:07 +0000684 if ( slot->format == FT_GLYPH_FORMAT_OUTLINE )
685 {
686 /* check that the loaded outline is correct */
687 error = FT_Outline_Check( &slot->outline );
688 if ( error )
689 goto Exit;
690
691#ifdef GRID_FIT_METRICS
692 if ( !( load_flags & FT_LOAD_NO_HINTING ) )
693 ft_glyphslot_grid_fit_metrics( slot,
David Turnerda95af62006-03-20 13:32:33 +0000694 FT_BOOL( load_flags & FT_LOAD_VERTICAL_LAYOUT ) );
Wu, Chia-I (吳佳一)2e48a1a2006-02-27 09:18:07 +0000695#endif
696 }
David Turner662b3442002-01-03 16:56:59 +0000697 }
David Turnerf0df85b2000-06-22 00:17:42 +0000698
David Turner4937a3e2001-12-19 21:09:16 +0000699 Load_Ok:
David Turnerf0df85b2000-06-22 00:17:42 +0000700 /* compute the advance */
Werner Lemberga929ba92000-06-25 06:47:11 +0000701 if ( load_flags & FT_LOAD_VERTICAL_LAYOUT )
David Turnerf0df85b2000-06-22 00:17:42 +0000702 {
703 slot->advance.x = 0;
704 slot->advance.y = slot->metrics.vertAdvance;
705 }
706 else
707 {
708 slot->advance.x = slot->metrics.horiAdvance;
709 slot->advance.y = 0;
710 }
711
David Turnerc9ce9e42000-09-15 17:16:49 +0000712 /* compute the linear advance in 16.16 pixels */
Werner Lemberg38449dc2009-10-26 07:26:25 +0100713 if ( ( load_flags & FT_LOAD_LINEAR_DESIGN ) == 0 &&
714 ( FT_IS_SCALABLE( face ) ) )
David Turnerc9ce9e42000-09-15 17:16:49 +0000715 {
David Turnerc9ce9e42000-09-15 17:16:49 +0000716 FT_Size_Metrics* metrics = &face->size->metrics;
Werner Lembergeddd9902000-10-12 05:05:40 +0000717
Werner Lembergf8ba2002002-03-30 13:16:35 +0000718
Wu, Chia-I (吳佳一)e5ff0592006-01-15 06:00:49 +0000719 /* it's tricky! */
David Turnerc9ce9e42000-09-15 17:16:49 +0000720 slot->linearHoriAdvance = FT_MulDiv( slot->linearHoriAdvance,
Werner Lembergbe67c4e2003-11-24 22:54:58 +0000721 metrics->x_scale, 64 );
David Turnerc9ce9e42000-09-15 17:16:49 +0000722
723 slot->linearVertAdvance = FT_MulDiv( slot->linearVertAdvance,
Werner Lembergbe67c4e2003-11-24 22:54:58 +0000724 metrics->y_scale, 64 );
David Turnerc9ce9e42000-09-15 17:16:49 +0000725 }
726
727 if ( ( load_flags & FT_LOAD_IGNORE_TRANSFORM ) == 0 )
David Turnerf0df85b2000-06-22 00:17:42 +0000728 {
David Turner54e75742000-11-04 02:52:02 +0000729 FT_Face_Internal internal = face->internal;
David Turner61d6b2b2001-05-16 17:49:07 +0000730
731
Werner Lembergd1b74752000-08-24 16:29:15 +0000732 /* now, transform the glyph image if needed */
David Turner54e75742000-11-04 02:52:02 +0000733 if ( internal->transform_flags )
David Turner35db7322000-08-24 12:39:40 +0000734 {
735 /* get renderer */
736 FT_Renderer renderer = ft_lookup_glyph_renderer( slot );
Werner Lembergdeb4e982000-06-29 03:14:25 +0000737
Werner Lemberga929ba92000-06-25 06:47:11 +0000738
David Turner35db7322000-08-24 12:39:40 +0000739 if ( renderer )
Werner Lembergdc72aff2000-11-04 08:33:38 +0000740 error = renderer->clazz->transform_glyph(
741 renderer, slot,
742 &internal->transform_matrix,
743 &internal->transform_delta );
Werner Lemberg13fa21b2010-01-14 21:34:08 +0100744 else if ( slot->format == FT_GLYPH_FORMAT_OUTLINE )
745 {
746 /* apply `standard' transformation if no renderer is available */
747 if ( &internal->transform_matrix )
748 FT_Outline_Transform( &slot->outline,
749 &internal->transform_matrix );
750
751 if ( &internal->transform_delta )
752 FT_Outline_Translate( &slot->outline,
753 internal->transform_delta.x,
754 internal->transform_delta.y );
755 }
756
David Turner35db7322000-08-24 12:39:40 +0000757 /* transform advance */
David Turner54e75742000-11-04 02:52:02 +0000758 FT_Vector_Transform( &slot->advance, &internal->transform_matrix );
David Turner35db7322000-08-24 12:39:40 +0000759 }
David Turnerc9ce9e42000-09-15 17:16:49 +0000760 }
David Turnerf0df85b2000-06-22 00:17:42 +0000761
Werner Lembergc4b22142009-11-15 10:10:00 +0100762 FT_TRACE5(( " x advance: %d\n" , slot->advance.x ));
763 FT_TRACE5(( " y advance: %d\n" , slot->advance.y ));
764
765 FT_TRACE5(( " linear x advance: %d\n" , slot->linearHoriAdvance ));
766 FT_TRACE5(( " linear y advance: %d\n" , slot->linearVertAdvance ));
767
David Turnerc9ce9e42000-09-15 17:16:49 +0000768 /* do we need to render the image now? */
769 if ( !error &&
David Turnerb08fe2d2002-08-27 20:20:29 +0000770 slot->format != FT_GLYPH_FORMAT_BITMAP &&
771 slot->format != FT_GLYPH_FORMAT_COMPOSITE &&
David Turnerc9ce9e42000-09-15 17:16:49 +0000772 load_flags & FT_LOAD_RENDER )
773 {
David Turner00d9f402002-09-08 21:29:11 +0000774 FT_Render_Mode mode = FT_LOAD_TARGET_MODE( load_flags );
775
Werner Lemberg68e9f922002-09-27 11:09:23 +0000776
David Turner00d9f402002-09-08 21:29:11 +0000777 if ( mode == FT_RENDER_MODE_NORMAL &&
778 (load_flags & FT_LOAD_MONOCHROME ) )
779 mode = FT_RENDER_MODE_MONO;
780
781 error = FT_Render_Glyph( slot, mode );
Werner Lembergd060a752000-07-20 06:57:41 +0000782 }
David Turner5ae831c2000-06-30 01:31:22 +0000783
Werner Lembergdeb4e982000-06-29 03:14:25 +0000784 Exit:
David Turnerf0df85b2000-06-22 00:17:42 +0000785 return error;
786 }
787
788
Werner Lemberg90a03302000-11-07 17:21:11 +0000789 /* documentation is in freetype.h */
790
Werner Lembergf814d0f2001-06-27 16:18:10 +0000791 FT_EXPORT_DEF( FT_Error )
792 FT_Load_Char( FT_Face face,
793 FT_ULong char_code,
David Turnerf467e6a2002-08-21 21:39:28 +0000794 FT_Int32 load_flags )
David Turnerf0df85b2000-06-22 00:17:42 +0000795 {
Werner Lembergdeb4e982000-06-29 03:14:25 +0000796 FT_UInt glyph_index;
David Turnerf0df85b2000-06-22 00:17:42 +0000797
Werner Lemberga929ba92000-06-25 06:47:11 +0000798
David Turnerf0df85b2000-06-22 00:17:42 +0000799 if ( !face )
800 return FT_Err_Invalid_Face_Handle;
801
802 glyph_index = (FT_UInt)char_code;
Werner Lemberga929ba92000-06-25 06:47:11 +0000803 if ( face->charmap )
David Turnerf0df85b2000-06-22 00:17:42 +0000804 glyph_index = FT_Get_Char_Index( face, char_code );
805
David Turner5ae831c2000-06-30 01:31:22 +0000806 return FT_Load_Glyph( face, glyph_index, load_flags );
David Turnerf0df85b2000-06-22 00:17:42 +0000807 }
808
809
Werner Lemberg7880dd62000-01-10 17:19:45 +0000810 /* destructor for sizes list */
Werner Lembergf814d0f2001-06-27 16:18:10 +0000811 static void
812 destroy_size( FT_Memory memory,
813 FT_Size size,
814 FT_Driver driver )
Werner Lemberg7880dd62000-01-10 17:19:45 +0000815 {
David Turnerf0df85b2000-06-22 00:17:42 +0000816 /* finalize client-specific data */
Werner Lemberga929ba92000-06-25 06:47:11 +0000817 if ( size->generic.finalizer )
David Turnerf0df85b2000-06-22 00:17:42 +0000818 size->generic.finalizer( size );
819
Werner Lemberg7880dd62000-01-10 17:19:45 +0000820 /* finalize format-specific stuff */
Werner Lemberga929ba92000-06-25 06:47:11 +0000821 if ( driver->clazz->done_size )
David Turnerf0df85b2000-06-22 00:17:42 +0000822 driver->clazz->done_size( size );
823
David Turnere459d742002-03-22 13:52:37 +0000824 FT_FREE( size->internal );
825 FT_FREE( size );
Werner Lemberg7880dd62000-01-10 17:19:45 +0000826 }
David Turnerd2b1f351999-12-16 23:11:37 +0000827
828
Werner Lemberg4338dab2004-01-05 14:41:59 +0000829 static void
Werner Lemberge70371c2005-05-27 06:01:28 +0000830 ft_cmap_done_internal( FT_CMap cmap );
831
832
833 static void
Werner Lemberg4338dab2004-01-05 14:41:59 +0000834 destroy_charmaps( FT_Face face,
835 FT_Memory memory )
836 {
837 FT_Int n;
838
839
Werner Lemberg3d507fe2007-06-03 16:54:55 +0000840 if ( !face )
841 return;
842
Werner Lemberg4338dab2004-01-05 14:41:59 +0000843 for ( n = 0; n < face->num_charmaps; n++ )
844 {
845 FT_CMap cmap = FT_CMAP( face->charmaps[n] );
846
847
Werner Lemberge70371c2005-05-27 06:01:28 +0000848 ft_cmap_done_internal( cmap );
Werner Lemberg4338dab2004-01-05 14:41:59 +0000849
850 face->charmaps[n] = NULL;
851 }
852
853 FT_FREE( face->charmaps );
854 face->num_charmaps = 0;
855 }
856
857
Werner Lemberg7880dd62000-01-10 17:19:45 +0000858 /* destructor for faces list */
Werner Lembergf814d0f2001-06-27 16:18:10 +0000859 static void
860 destroy_face( FT_Memory memory,
861 FT_Face face,
862 FT_Driver driver )
Werner Lemberg7880dd62000-01-10 17:19:45 +0000863 {
David Turneref3c1262002-03-14 09:22:48 +0000864 FT_Driver_Class clazz = driver->clazz;
David Turnerf0df85b2000-06-22 00:17:42 +0000865
Werner Lembergd060a752000-07-20 06:57:41 +0000866
David Turnerc49f69c2000-07-20 03:44:50 +0000867 /* discard auto-hinting data */
868 if ( face->autohint.finalizer )
869 face->autohint.finalizer( face->autohint.data );
Werner Lembergeddd9902000-10-12 05:05:40 +0000870
Werner Lembergf8ba2002002-03-30 13:16:35 +0000871 /* Discard glyph slots for this face. */
David Turner23bcde12001-10-17 13:48:10 +0000872 /* Beware! FT_Done_GlyphSlot() changes the field `face->glyph' */
Werner Lemberg7880dd62000-01-10 17:19:45 +0000873 while ( face->glyph )
874 FT_Done_GlyphSlot( face->glyph );
875
Werner Lembergf8ba2002002-03-30 13:16:35 +0000876 /* discard all sizes for this face */
Werner Lemberg7880dd62000-01-10 17:19:45 +0000877 FT_List_Finalize( &face->sizes_list,
Werner Lemberg74184152003-10-18 16:56:13 +0000878 (FT_List_Destructor)destroy_size,
879 memory,
880 driver );
Werner Lemberg7880dd62000-01-10 17:19:45 +0000881 face->size = 0;
882
Werner Lembergf8ba2002002-03-30 13:16:35 +0000883 /* now discard client data */
Werner Lemberg7880dd62000-01-10 17:19:45 +0000884 if ( face->generic.finalizer )
885 face->generic.finalizer( face );
886
David Turner2ded2c12002-03-22 22:37:40 +0000887 /* discard charmaps */
Werner Lemberg4338dab2004-01-05 14:41:59 +0000888 destroy_charmaps( face, memory );
Werner Lemberg75435332004-02-25 12:58:54 +0000889
David Turnerf0df85b2000-06-22 00:17:42 +0000890 /* finalize format-specific stuff */
Werner Lemberga929ba92000-06-25 06:47:11 +0000891 if ( clazz->done_face )
892 clazz->done_face( face );
David Turnerf0df85b2000-06-22 00:17:42 +0000893
894 /* close the stream for this face if needed */
Werner Lemberg75435332004-02-25 12:58:54 +0000895 FT_Stream_Free(
Werner Lembergf8ba2002002-03-30 13:16:35 +0000896 face->stream,
Werner Lemberg58b17f92000-07-27 23:29:08 +0000897 ( face->face_flags & FT_FACE_FLAG_EXTERNAL_STREAM ) != 0 );
David Turner7663f222000-02-13 13:37:38 +0000898
David Turner53b3fa12002-02-24 05:26:57 +0000899 face->stream = 0;
900
Werner Lemberg7880dd62000-01-10 17:19:45 +0000901 /* get rid of it */
David Turner23bcde12001-10-17 13:48:10 +0000902 if ( face->internal )
903 {
David Turnere459d742002-03-22 13:52:37 +0000904 FT_FREE( face->internal );
David Turner23bcde12001-10-17 13:48:10 +0000905 }
David Turnere459d742002-03-22 13:52:37 +0000906 FT_FREE( face );
Werner Lemberg7880dd62000-01-10 17:19:45 +0000907 }
David Turnerd2b1f351999-12-16 23:11:37 +0000908
909
Werner Lembergf814d0f2001-06-27 16:18:10 +0000910 static void
911 Destroy_Driver( FT_Driver driver )
David Turnerd2b1f351999-12-16 23:11:37 +0000912 {
David Turnerd2b1f351999-12-16 23:11:37 +0000913 FT_List_Finalize( &driver->faces_list,
914 (FT_List_Destructor)destroy_face,
David Turnerf0df85b2000-06-22 00:17:42 +0000915 driver->root.memory,
David Turnerd2b1f351999-12-16 23:11:37 +0000916 driver );
917
Werner Lembergdeb4e982000-06-29 03:14:25 +0000918 /* check whether we need to drop the driver's glyph loader */
Werner Lemberga929ba92000-06-25 06:47:11 +0000919 if ( FT_DRIVER_USES_OUTLINES( driver ) )
David Turnerf0df85b2000-06-22 00:17:42 +0000920 FT_GlyphLoader_Done( driver->glyph_loader );
David Turnerd2b1f351999-12-16 23:11:37 +0000921 }
922
923
Werner Lemberg547a2522000-02-16 08:23:58 +0000924 /*************************************************************************/
925 /* */
926 /* <Function> */
Antoine Lecac96f69d2002-12-03 00:39:16 +0000927 /* find_unicode_charmap */
928 /* */
929 /* <Description> */
930 /* This function finds a Unicode charmap, if there is one. */
931 /* And if there is more than one, it tries to favour the more */
Werner Lembergc8c6bf52003-04-23 05:38:13 +0000932 /* extensive one, i.e., one that supports UCS-4 against those which */
Antoine Lecac96f69d2002-12-03 00:39:16 +0000933 /* are limited to the BMP (said UCS-2 encoding.) */
934 /* */
935 /* This function is called from open_face() (just below), and also */
Werner Lemberg74597cc2007-10-01 07:08:56 +0000936 /* from FT_Select_Charmap( ..., FT_ENCODING_UNICODE ). */
Antoine Lecac96f69d2002-12-03 00:39:16 +0000937 /* */
938 static FT_Error
939 find_unicode_charmap( FT_Face face )
940 {
941 FT_CharMap* first;
942 FT_CharMap* cur;
Antoine Lecac96f69d2002-12-03 00:39:16 +0000943
944
945 /* caller should have already checked that `face' is valid */
Werner Lemberg74184152003-10-18 16:56:13 +0000946 FT_ASSERT( face );
Antoine Lecac96f69d2002-12-03 00:39:16 +0000947
948 first = face->charmaps;
949
950 if ( !first )
951 return FT_Err_Invalid_CharMap_Handle;
952
David Turnerc528f6f2002-12-18 22:43:07 +0000953 /*
Werner Lembergc8c6bf52003-04-23 05:38:13 +0000954 * The original TrueType specification(s) only specified charmap
David Turnerc528f6f2002-12-18 22:43:07 +0000955 * formats that are capable of mapping 8 or 16 bit character codes to
956 * glyph indices.
957 *
Werner Lembergc8c6bf52003-04-23 05:38:13 +0000958 * However, recent updates to the Apple and OpenType specifications
David Turnerc528f6f2002-12-18 22:43:07 +0000959 * introduced new formats that are capable of mapping 32-bit character
Werner Lembergc8c6bf52003-04-23 05:38:13 +0000960 * codes as well. And these are already used on some fonts, mainly to
David Turnerae26c682003-02-25 20:37:50 +0000961 * map non-BMP Asian ideographs as defined in Unicode.
David Turnerc528f6f2002-12-18 22:43:07 +0000962 *
Werner Lembergc8c6bf52003-04-23 05:38:13 +0000963 * For compatibility purposes, these fonts generally come with
David Turnerc528f6f2002-12-18 22:43:07 +0000964 * *several* Unicode charmaps:
965 *
Werner Lembergc8c6bf52003-04-23 05:38:13 +0000966 * - One of them in the "old" 16-bit format, that cannot access
967 * all glyphs in the font.
David Turnerc528f6f2002-12-18 22:43:07 +0000968 *
Werner Lembergc8c6bf52003-04-23 05:38:13 +0000969 * - Another one in the "new" 32-bit format, that can access all
David Turnerc528f6f2002-12-18 22:43:07 +0000970 * the glyphs.
971 *
Werner Lembergc8c6bf52003-04-23 05:38:13 +0000972 * This function has been written to always favor a 32-bit charmap
973 * when found. Otherwise, a 16-bit one is returned when found.
David Turnerc528f6f2002-12-18 22:43:07 +0000974 */
975
Werner Lemberg8acb8672005-03-08 11:43:36 +0000976 /* Since the `interesting' table, with IDs (3,10), is normally the */
Werner Lemberg1e259de2007-03-08 15:39:21 +0000977 /* last one, we loop backwards. This loses with type1 fonts with */
Werner Lemberg8acb8672005-03-08 11:43:36 +0000978 /* non-BMP characters (<.0001%), this wins with .ttf with non-BMP */
979 /* chars (.01% ?), and this is the same about 99.99% of the time! */
Antoine Lecac96f69d2002-12-03 00:39:16 +0000980
981 cur = first + face->num_charmaps; /* points after the last one */
982
983 for ( ; --cur >= first; )
984 {
985 if ( cur[0]->encoding == FT_ENCODING_UNICODE )
986 {
Werner Lemberg74597cc2007-10-01 07:08:56 +0000987 /* XXX If some new encodings to represent UCS-4 are added, */
988 /* they should be added here. */
David Turnerc528f6f2002-12-18 22:43:07 +0000989 if ( ( cur[0]->platform_id == TT_PLATFORM_MICROSOFT &&
Werner Lemberg74597cc2007-10-01 07:08:56 +0000990 cur[0]->encoding_id == TT_MS_ID_UCS_4 ) ||
David Turnerc528f6f2002-12-18 22:43:07 +0000991 ( cur[0]->platform_id == TT_PLATFORM_APPLE_UNICODE &&
Werner Lemberg74597cc2007-10-01 07:08:56 +0000992 cur[0]->encoding_id == TT_APPLE_ID_UNICODE_32 ) )
Antoine Lecac96f69d2002-12-03 00:39:16 +0000993 {
suzuki toshiya0ae32712010-07-04 20:14:18 +0900994#ifdef FT_MAX_CHARMAP_CACHEABLE
995 if ( cur - first > FT_MAX_CHARMAP_CACHEABLE )
996 {
997 FT_ERROR(( "find_unicode_charmap: UCS-4 cmap is found "
998 "at too late position (%d)\n", cur - first ));
999 continue;
1000 }
1001#endif
Antoine Lecac96f69d2002-12-03 00:39:16 +00001002 face->charmap = cur[0];
Werner Lemberg74597cc2007-10-01 07:08:56 +00001003 return FT_Err_Ok;
Antoine Lecac96f69d2002-12-03 00:39:16 +00001004 }
1005 }
1006 }
1007
Werner Lemberg74597cc2007-10-01 07:08:56 +00001008 /* We do not have any UCS-4 charmap. */
1009 /* Do the loop again and search for UCS-2 charmaps. */
1010 cur = first + face->num_charmaps;
1011
1012 for ( ; --cur >= first; )
Antoine Lecac96f69d2002-12-03 00:39:16 +00001013 {
Werner Lemberg74597cc2007-10-01 07:08:56 +00001014 if ( cur[0]->encoding == FT_ENCODING_UNICODE )
1015 {
suzuki toshiya0ae32712010-07-04 20:14:18 +09001016#ifdef FT_MAX_CHARMAP_CACHEABLE
1017 if ( cur - first > FT_MAX_CHARMAP_CACHEABLE )
1018 {
1019 FT_ERROR(( "find_unicode_charmap: UCS-2 cmap is found "
1020 "at too late position (%d)\n", cur - first ));
1021 continue;
1022 }
1023#endif
Werner Lemberg74597cc2007-10-01 07:08:56 +00001024 face->charmap = cur[0];
1025 return FT_Err_Ok;
1026 }
Antoine Lecac96f69d2002-12-03 00:39:16 +00001027 }
1028
David Turner6453a812003-01-08 09:28:34 +00001029 return FT_Err_Invalid_CharMap_Handle;
Antoine Lecac96f69d2002-12-03 00:39:16 +00001030 }
1031
1032
1033 /*************************************************************************/
1034 /* */
1035 /* <Function> */
Werner Lemberg9a966b72007-10-15 17:21:32 +00001036 /* find_variant_selector_charmap */
1037 /* */
1038 /* <Description> */
1039 /* This function finds the variant selector charmap, if there is one. */
1040 /* There can only be one (platform=0, specific=5, format=14). */
1041 /* */
1042 static FT_CharMap
1043 find_variant_selector_charmap( FT_Face face )
1044 {
1045 FT_CharMap* first;
1046 FT_CharMap* end;
1047 FT_CharMap* cur;
1048
1049
1050 /* caller should have already checked that `face' is valid */
1051 FT_ASSERT( face );
1052
1053 first = face->charmaps;
1054
1055 if ( !first )
1056 return NULL;
1057
1058 end = first + face->num_charmaps; /* points after the last one */
1059
1060 for ( cur = first; cur < end; ++cur )
1061 {
1062 if ( cur[0]->platform_id == TT_PLATFORM_APPLE_UNICODE &&
1063 cur[0]->encoding_id == TT_APPLE_ID_VARIANT_SELECTOR &&
1064 FT_Get_CMap_Format( cur[0] ) == 14 )
suzuki toshiya0ae32712010-07-04 20:14:18 +09001065#ifdef FT_MAX_CHARMAP_CACHEABLE
1066 if ( cur - first > FT_MAX_CHARMAP_CACHEABLE )
1067 {
1068 FT_ERROR(( "find_unicode_charmap: UVS cmap is found "
1069 "at too late position (%d)\n", cur - first ));
1070 continue;
1071 }
1072#endif
Werner Lemberg9a966b72007-10-15 17:21:32 +00001073 return cur[0];
1074 }
1075
1076 return NULL;
1077 }
1078
1079
1080 /*************************************************************************/
1081 /* */
1082 /* <Function> */
Werner Lemberg547a2522000-02-16 08:23:58 +00001083 /* open_face */
1084 /* */
1085 /* <Description> */
1086 /* This function does some work for FT_Open_Face(). */
1087 /* */
Werner Lembergf814d0f2001-06-27 16:18:10 +00001088 static FT_Error
1089 open_face( FT_Driver driver,
1090 FT_Stream stream,
1091 FT_Long face_index,
1092 FT_Int num_params,
1093 FT_Parameter* params,
Werner Lemberg6d798992003-07-01 07:28:55 +00001094 FT_Face *aface )
David Turnerd2b1f351999-12-16 23:11:37 +00001095 {
David Turnerf0df85b2000-06-22 00:17:42 +00001096 FT_Memory memory;
Werner Lemberg77c34b82003-05-20 22:06:38 +00001097 FT_Driver_Class clazz;
David Turnerf0df85b2000-06-22 00:17:42 +00001098 FT_Face face = 0;
Antoine Lecac96f69d2002-12-03 00:39:16 +00001099 FT_Error error, error2;
David Turner6a681fa2006-01-27 12:11:22 +00001100 FT_Face_Internal internal = NULL;
David Turnerd2b1f351999-12-16 23:11:37 +00001101
Werner Lemberg3c403e42002-08-06 21:47:40 +00001102
David Turnerf0df85b2000-06-22 00:17:42 +00001103 clazz = driver->clazz;
1104 memory = driver->root.memory;
David Turnerd2b1f351999-12-16 23:11:37 +00001105
Werner Lembergdeb4e982000-06-29 03:14:25 +00001106 /* allocate the face object and perform basic initialization */
David Turnere459d742002-03-22 13:52:37 +00001107 if ( FT_ALLOC( face, clazz->face_object_size ) )
David Turnerd2b1f351999-12-16 23:11:37 +00001108 goto Fail;
1109
David Turnere459d742002-03-22 13:52:37 +00001110 if ( FT_NEW( internal ) )
David Turner54e75742000-11-04 02:52:02 +00001111 goto Fail;
David Turner61d6b2b2001-05-16 17:49:07 +00001112
David Turner54e75742000-11-04 02:52:02 +00001113 face->internal = internal;
1114
1115 face->driver = driver;
1116 face->memory = memory;
1117 face->stream = stream;
Graham Asherce121822002-08-01 15:29:17 +00001118
Graham Asherd53cf1d2002-07-18 15:04:29 +00001119#ifdef FT_CONFIG_OPTION_INCREMENTAL
Werner Lemberg3c403e42002-08-06 21:47:40 +00001120 {
1121 int i;
1122
1123
1124 face->internal->incremental_interface = 0;
1125 for ( i = 0; i < num_params && !face->internal->incremental_interface;
1126 i++ )
1127 if ( params[i].tag == FT_PARAM_TAG_INCREMENTAL )
Werner Lemberg1e1b6df2007-07-07 07:30:40 +00001128 face->internal->incremental_interface =
1129 (FT_Incremental_Interface)params[i].data;
Antoine Lecac96f69d2002-12-03 00:39:16 +00001130 }
Graham Asherd53cf1d2002-07-18 15:04:29 +00001131#endif
David Turnerd2b1f351999-12-16 23:11:37 +00001132
Werner Lembergf3200fa2008-06-10 04:57:57 +00001133 if ( clazz->init_face )
Werner Lemberg102bb832008-06-10 04:57:19 +00001134 error = clazz->init_face( stream,
1135 face,
1136 (FT_Int)face_index,
1137 num_params,
1138 params );
David Turnerd2b1f351999-12-16 23:11:37 +00001139 if ( error )
1140 goto Fail;
1141
David Turnerfed59b72002-07-17 22:51:06 +00001142 /* select Unicode charmap by default */
Antoine Lecac96f69d2002-12-03 00:39:16 +00001143 error2 = find_unicode_charmap( face );
David Turnerc528f6f2002-12-18 22:43:07 +00001144
Werner Lemberg6d798992003-07-01 07:28:55 +00001145 /* if no Unicode charmap can be found, FT_Err_Invalid_CharMap_Handle */
1146 /* is returned. */
Antoine Lecac96f69d2002-12-03 00:39:16 +00001147
Werner Lemberg6d798992003-07-01 07:28:55 +00001148 /* no error should happen, but we want to play safe */
David Turnerc528f6f2002-12-18 22:43:07 +00001149 if ( error2 && error2 != FT_Err_Invalid_CharMap_Handle )
David Turnerfed59b72002-07-17 22:51:06 +00001150 {
Antoine Lecac96f69d2002-12-03 00:39:16 +00001151 error = error2;
1152 goto Fail;
David Turnerfed59b72002-07-17 22:51:06 +00001153 }
1154
David Turnerd2b1f351999-12-16 23:11:37 +00001155 *aface = face;
1156
1157 Fail:
1158 if ( error )
1159 {
Werner Lemberg4338dab2004-01-05 14:41:59 +00001160 destroy_charmaps( face, memory );
Werner Lemberg102bb832008-06-10 04:57:19 +00001161 if ( clazz->done_face )
1162 clazz->done_face( face );
Werner Lemberg77c34b82003-05-20 22:06:38 +00001163 FT_FREE( internal );
David Turnere459d742002-03-22 13:52:37 +00001164 FT_FREE( face );
David Turnerd2b1f351999-12-16 23:11:37 +00001165 *aface = 0;
1166 }
1167
1168 return error;
1169 }
1170
1171
Werner Lemberg05c21b82000-07-29 20:38:19 +00001172 /* there's a Mac-specific extended implementation of FT_New_Face() */
Werner Lemberg4d631e42002-05-27 13:02:37 +00001173 /* in src/base/ftmac.c */
Werner Lemberg05c21b82000-07-29 20:38:19 +00001174
Suzuki, Toshiya (鈴木俊哉)9e2b9902008-10-03 11:52:22 +00001175#if !defined( FT_MACINTOSH ) || defined( DARWIN_NO_CARBON )
Just van Rossum9e830c52000-07-28 01:12:34 +00001176
Werner Lemberg90a03302000-11-07 17:21:11 +00001177 /* documentation is in freetype.h */
1178
Werner Lembergf814d0f2001-06-27 16:18:10 +00001179 FT_EXPORT_DEF( FT_Error )
1180 FT_New_Face( FT_Library library,
1181 const char* pathname,
1182 FT_Long face_index,
1183 FT_Face *aface )
David Turnerd2b1f351999-12-16 23:11:37 +00001184 {
David Turner37379e22000-03-28 11:22:31 +00001185 FT_Open_Args args;
Werner Lemberg547a2522000-02-16 08:23:58 +00001186
Werner Lemberga929ba92000-06-25 06:47:11 +00001187
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001188 /* test for valid `library' and `aface' delayed to FT_Open_Face() */
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001189 if ( !pathname )
1190 return FT_Err_Invalid_Argument;
1191
David Turnerb08fe2d2002-08-27 20:20:29 +00001192 args.flags = FT_OPEN_PATHNAME;
David Turner4f2c5542000-05-12 10:19:41 +00001193 args.pathname = (char*)pathname;
Werner Lembergb66efef2009-03-12 08:07:49 +00001194 args.stream = NULL;
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001195
David Turnercda32b72000-02-10 16:14:35 +00001196 return FT_Open_Face( library, &args, face_index, aface );
David Turnerd2b1f351999-12-16 23:11:37 +00001197 }
1198
Suzuki, Toshiya (鈴木俊哉)9e2b9902008-10-03 11:52:22 +00001199#endif /* defined( FT_MACINTOSH ) && !defined( DARWIN_NO_CARBON ) */
Just van Rossum9e830c52000-07-28 01:12:34 +00001200
Werner Lemberg7880dd62000-01-10 17:19:45 +00001201
Werner Lemberg90a03302000-11-07 17:21:11 +00001202 /* documentation is in freetype.h */
1203
Werner Lembergf814d0f2001-06-27 16:18:10 +00001204 FT_EXPORT_DEF( FT_Error )
1205 FT_New_Memory_Face( FT_Library library,
1206 const FT_Byte* file_base,
1207 FT_Long file_size,
1208 FT_Long face_index,
1209 FT_Face *aface )
David Turnerd2b1f351999-12-16 23:11:37 +00001210 {
David Turner37379e22000-03-28 11:22:31 +00001211 FT_Open_Args args;
Werner Lemberg7880dd62000-01-10 17:19:45 +00001212
Werner Lemberga929ba92000-06-25 06:47:11 +00001213
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001214 /* test for valid `library' and `face' delayed to FT_Open_Face() */
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001215 if ( !file_base )
1216 return FT_Err_Invalid_Argument;
1217
David Turnerb08fe2d2002-08-27 20:20:29 +00001218 args.flags = FT_OPEN_MEMORY;
David Turnercda32b72000-02-10 16:14:35 +00001219 args.memory_base = file_base;
1220 args.memory_size = file_size;
Werner Lembergb66efef2009-03-12 08:07:49 +00001221 args.stream = NULL;
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001222
Werner Lemberg4b680072000-11-07 06:30:29 +00001223 return FT_Open_Face( library, &args, face_index, aface );
David Turnerd2b1f351999-12-16 23:11:37 +00001224 }
1225
Werner Lemberg7880dd62000-01-10 17:19:45 +00001226
Werner Lemberg02197282008-11-29 09:31:44 +00001227#ifdef FT_CONFIG_OPTION_MAC_FONTS
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001228
1229 /* The behavior here is very similar to that in base/ftmac.c, but it */
1230 /* is designed to work on non-mac systems, so no mac specific calls. */
1231 /* */
1232 /* We look at the file and determine if it is a mac dfont file or a mac */
1233 /* resource file, or a macbinary file containing a mac resource file. */
1234 /* */
1235 /* Unlike ftmac I'm not going to look at a `FOND'. I don't really see */
1236 /* the point, especially since there may be multiple `FOND' resources. */
1237 /* Instead I'll just look for `sfnt' and `POST' resources, ordered as */
1238 /* they occur in the file. */
1239 /* */
1240 /* Note that multiple `POST' resources do not mean multiple postscript */
1241 /* fonts; they all get jammed together to make what is essentially a */
1242 /* pfb file. */
1243 /* */
1244 /* We aren't interested in `NFNT' or `FONT' bitmap resources. */
1245 /* */
1246 /* As soon as we get an `sfnt' load it into memory and pass it off to */
1247 /* FT_Open_Face. */
1248 /* */
1249 /* If we have a (set of) `POST' resources, massage them into a (memory) */
1250 /* pfb file and pass that to FT_Open_Face. (As with ftmac.c I'm not */
1251 /* going to try to save the kerning info. After all that lives in the */
1252 /* `FOND' which isn't in the file containing the `POST' resources so */
1253 /* we don't really have access to it. */
1254
1255
Werner Lembergcff15b02008-10-02 05:38:29 +00001256 /* Finalizer for a memory stream; gets called by FT_Done_Face(). */
1257 /* It frees the memory it uses. */
1258 /* From ftmac.c. */
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001259 static void
1260 memory_stream_close( FT_Stream stream )
1261 {
1262 FT_Memory memory = stream->memory;
1263
1264
1265 FT_FREE( stream->base );
1266
1267 stream->size = 0;
1268 stream->base = 0;
1269 stream->close = 0;
1270 }
1271
1272
1273 /* Create a new memory stream from a buffer and a size. */
Werner Lembergcff15b02008-10-02 05:38:29 +00001274 /* From ftmac.c. */
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001275 static FT_Error
1276 new_memory_stream( FT_Library library,
1277 FT_Byte* base,
1278 FT_ULong size,
1279 FT_Stream_CloseFunc close,
1280 FT_Stream *astream )
1281 {
1282 FT_Error error;
1283 FT_Memory memory;
1284 FT_Stream stream;
1285
1286
1287 if ( !library )
1288 return FT_Err_Invalid_Library_Handle;
1289
1290 if ( !base )
1291 return FT_Err_Invalid_Argument;
1292
1293 *astream = 0;
1294 memory = library->memory;
1295 if ( FT_NEW( stream ) )
1296 goto Exit;
1297
1298 FT_Stream_OpenMemory( stream, base, size );
1299
1300 stream->close = close;
1301
1302 *astream = stream;
1303
1304 Exit:
1305 return error;
1306 }
1307
1308
1309 /* Create a new FT_Face given a buffer and a driver name. */
1310 /* from ftmac.c */
Suzuki, Toshiya (鈴木俊哉)f4147022008-10-02 01:43:18 +00001311 FT_LOCAL_DEF( FT_Error )
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001312 open_face_from_buffer( FT_Library library,
1313 FT_Byte* base,
1314 FT_ULong size,
1315 FT_Long face_index,
1316 const char* driver_name,
1317 FT_Face *aface )
1318 {
1319 FT_Open_Args args;
1320 FT_Error error;
Werner Lemberg607dec72007-05-15 06:49:37 +00001321 FT_Stream stream = NULL;
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001322 FT_Memory memory = library->memory;
1323
1324
1325 error = new_memory_stream( library,
1326 base,
1327 size,
1328 memory_stream_close,
1329 &stream );
1330 if ( error )
1331 {
1332 FT_FREE( base );
1333 return error;
1334 }
1335
1336 args.flags = FT_OPEN_STREAM;
1337 args.stream = stream;
1338 if ( driver_name )
1339 {
Werner Lemberg7a024102003-06-18 06:59:57 +00001340 args.flags = args.flags | FT_OPEN_DRIVER;
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001341 args.driver = FT_Get_Module( library, driver_name );
1342 }
1343
Werner Lemberg02197282008-11-29 09:31:44 +00001344#ifdef FT_MACINTOSH
Suzuki, Toshiya (鈴木俊哉)f4147022008-10-02 01:43:18 +00001345 /* At this point, face_index has served its purpose; */
1346 /* whoever calls this function has already used it to */
1347 /* locate the correct font data. We should not propagate */
1348 /* this index to FT_Open_Face() (unless it is negative). */
1349
1350 if ( face_index > 0 )
1351 face_index = 0;
1352#endif
1353
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001354 error = FT_Open_Face( library, &args, face_index, aface );
1355
Suzuki, Toshiya (鈴木俊哉)f4147022008-10-02 01:43:18 +00001356 if ( error == FT_Err_Ok )
1357 (*aface)->face_flags &= ~FT_FACE_FLAG_EXTERNAL_STREAM;
1358 else
Werner Lemberg02197282008-11-29 09:31:44 +00001359#ifdef FT_MACINTOSH
Suzuki, Toshiya (鈴木俊哉)f4147022008-10-02 01:43:18 +00001360 FT_Stream_Free( stream, 0 );
1361#else
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001362 {
1363 FT_Stream_Close( stream );
1364 FT_FREE( stream );
1365 }
Suzuki, Toshiya (鈴木俊哉)f4147022008-10-02 01:43:18 +00001366#endif
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001367
1368 return error;
1369 }
1370
1371
Suzuki, Toshiya (鈴木俊哉)f4147022008-10-02 01:43:18 +00001372 /* Look up `TYP1' or `CID ' table from sfnt table directory. */
1373 /* `offset' and `length' must exclude the binary header in tables. */
1374
1375 /* Type 1 and CID-keyed font drivers should recognize sfnt-wrapped */
1376 /* format too. Here, since we can't expect that the TrueType font */
1377 /* driver is loaded unconditially, we must parse the font by */
1378 /* ourselves. We are only interested in the name of the table and */
Werner Lembergcff15b02008-10-02 05:38:29 +00001379 /* the offset. */
Suzuki, Toshiya (鈴木俊哉)f4147022008-10-02 01:43:18 +00001380
Suzuki, Toshiya (鈴木俊哉)1137d042008-10-04 07:11:58 +00001381 static FT_Error
1382 ft_lookup_PS_in_sfnt_stream( FT_Stream stream,
1383 FT_Long face_index,
1384 FT_ULong* offset,
1385 FT_ULong* length,
1386 FT_Bool* is_sfnt_cid )
Suzuki, Toshiya (鈴木俊哉)f4147022008-10-02 01:43:18 +00001387 {
Suzuki, Toshiya (鈴木俊哉)1137d042008-10-04 07:11:58 +00001388 FT_Error error;
1389 FT_UShort numTables;
1390 FT_Long pstable_index;
1391 FT_ULong tag;
1392 int i;
Suzuki, Toshiya (鈴木俊哉)f4147022008-10-02 01:43:18 +00001393
1394
Suzuki, Toshiya (鈴木俊哉)f4147022008-10-02 01:43:18 +00001395 *offset = 0;
1396 *length = 0;
Suzuki, Toshiya (鈴木俊哉)bc2c4982008-10-03 12:28:52 +00001397 *is_sfnt_cid = FALSE;
Suzuki, Toshiya (鈴木俊哉)1137d042008-10-04 07:11:58 +00001398
Suzuki, Toshiya (鈴木俊哉)72eb2702008-10-04 17:49:58 +00001399 /* TODO: support for sfnt-wrapped PS/CID in TTC format */
1400
Suzuki, Toshiya (鈴木俊哉)1137d042008-10-04 07:11:58 +00001401 /* version check for 'typ1' (should be ignored?) */
1402 if ( FT_READ_ULONG( tag ) )
1403 return error;
Suzuki, Toshiya (鈴木俊哉)21bd5162008-10-04 18:10:28 +00001404 if ( tag != TTAG_typ1 )
Suzuki, Toshiya (鈴木俊哉)1137d042008-10-04 07:11:58 +00001405 return FT_Err_Unknown_File_Format;
1406
Suzuki, Toshiya (鈴木俊哉)1137d042008-10-04 07:11:58 +00001407 if ( FT_READ_USHORT( numTables ) )
1408 return error;
1409 if ( FT_STREAM_SKIP( 2 * 3 ) ) /* skip binary search header */
1410 return error;
1411
Suzuki, Toshiya (鈴木俊哉)1137d042008-10-04 07:11:58 +00001412 pstable_index = -1;
Werner Lemberg45489582008-10-04 11:39:03 +00001413 *is_sfnt_cid = FALSE;
1414
1415 for ( i = 0; i < numTables; i++ )
Suzuki, Toshiya (鈴木俊哉)1137d042008-10-04 07:11:58 +00001416 {
Werner Lemberg45489582008-10-04 11:39:03 +00001417 if ( FT_READ_ULONG( tag ) || FT_STREAM_SKIP( 4 ) ||
Suzuki, Toshiya (鈴木俊哉)1137d042008-10-04 07:11:58 +00001418 FT_READ_ULONG( *offset ) || FT_READ_ULONG( *length ) )
1419 return error;
1420
Suzuki, Toshiya (鈴木俊哉)21bd5162008-10-04 18:10:28 +00001421 if ( tag == TTAG_CID )
Suzuki, Toshiya (鈴木俊哉)1137d042008-10-04 07:11:58 +00001422 {
Werner Lemberg45489582008-10-04 11:39:03 +00001423 pstable_index++;
Suzuki, Toshiya (鈴木俊哉)1137d042008-10-04 07:11:58 +00001424 *offset += 22;
1425 *length -= 22;
1426 *is_sfnt_cid = TRUE;
1427 if ( face_index < 0 )
1428 return FT_Err_Ok;
1429 }
Suzuki, Toshiya (鈴木俊哉)21bd5162008-10-04 18:10:28 +00001430 else if ( tag == TTAG_TYP1 )
Suzuki, Toshiya (鈴木俊哉)1137d042008-10-04 07:11:58 +00001431 {
Werner Lemberg45489582008-10-04 11:39:03 +00001432 pstable_index++;
Suzuki, Toshiya (鈴木俊哉)1137d042008-10-04 07:11:58 +00001433 *offset += 24;
1434 *length -= 24;
1435 *is_sfnt_cid = FALSE;
1436 if ( face_index < 0 )
1437 return FT_Err_Ok;
1438 }
1439 if ( face_index >= 0 && pstable_index == face_index )
1440 return FT_Err_Ok;
1441 }
1442 return FT_Err_Table_Missing;
1443 }
1444
1445
1446 FT_LOCAL_DEF( FT_Error )
Werner Lemberg45489582008-10-04 11:39:03 +00001447 open_face_PS_from_sfnt_stream( FT_Library library,
1448 FT_Stream stream,
1449 FT_Long face_index,
1450 FT_Int num_params,
Suzuki, Toshiya (鈴木俊哉)1137d042008-10-04 07:11:58 +00001451 FT_Parameter *params,
1452 FT_Face *aface )
1453 {
1454 FT_Error error;
1455 FT_Memory memory = library->memory;
1456 FT_ULong offset, length;
1457 FT_Long pos;
1458 FT_Bool is_sfnt_cid;
1459 FT_Byte* sfnt_ps;
1460
Werner Lemberg45489582008-10-04 11:39:03 +00001461 FT_UNUSED( num_params );
1462 FT_UNUSED( params );
1463
Suzuki, Toshiya (鈴木俊哉)1137d042008-10-04 07:11:58 +00001464
1465 pos = FT_Stream_Pos( stream );
1466
1467 error = ft_lookup_PS_in_sfnt_stream( stream,
1468 face_index,
1469 &offset,
1470 &length,
1471 &is_sfnt_cid );
1472 if ( error )
Suzuki, Toshiya (鈴木俊哉)5a009092009-01-22 03:50:37 +00001473 goto Exit;
Suzuki, Toshiya (鈴木俊哉)1137d042008-10-04 07:11:58 +00001474
1475 if ( FT_Stream_Seek( stream, pos + offset ) )
1476 goto Exit;
1477
1478 if ( FT_ALLOC( sfnt_ps, (FT_Long)length ) )
1479 goto Exit;
1480
1481 error = FT_Stream_Read( stream, (FT_Byte *)sfnt_ps, length );
1482 if ( error )
1483 goto Exit;
1484
1485 error = open_face_from_buffer( library,
1486 sfnt_ps,
1487 length,
1488 face_index < 0 ? face_index : 0,
1489 is_sfnt_cid ? "cid" : "type1",
1490 aface );
1491 Exit:
Werner Lembergb66efef2009-03-12 08:07:49 +00001492 {
1493 FT_Error error1;
1494
1495
1496 if ( error == FT_Err_Unknown_File_Format )
1497 {
1498 error1 = FT_Stream_Seek( stream, pos );
1499 if ( error1 )
1500 return error1;
1501 }
1502
1503 return error;
1504 }
Suzuki, Toshiya (鈴木俊哉)f4147022008-10-02 01:43:18 +00001505 }
1506
1507
1508#if !defined( FT_MACINTOSH ) || defined( DARWIN_NO_CARBON )
Werner Lembergcff15b02008-10-02 05:38:29 +00001509
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001510 /* The resource header says we've got resource_cnt `POST' (type1) */
1511 /* resources in this file. They all need to be coalesced into */
1512 /* one lump which gets passed on to the type1 driver. */
1513 /* Here can be only one PostScript font in a file so face_index */
1514 /* must be 0 (or -1). */
1515 /* */
1516 static FT_Error
1517 Mac_Read_POST_Resource( FT_Library library,
1518 FT_Stream stream,
Werner Lemberg75435332004-02-25 12:58:54 +00001519 FT_Long *offsets,
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001520 FT_Long resource_cnt,
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001521 FT_Long face_index,
1522 FT_Face *aface )
1523 {
1524 FT_Error error = FT_Err_Cannot_Open_Resource;
1525 FT_Memory memory = library->memory;
1526 FT_Byte* pfb_data;
Werner Lembergdc8ad542003-12-09 02:12:14 +00001527 int i, type, flags;
1528 FT_Long len;
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001529 FT_Long pfb_len, pfb_pos, pfb_lenpos;
Werner Lembergdc8ad542003-12-09 02:12:14 +00001530 FT_Long rlen, temp;
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001531
1532
1533 if ( face_index == -1 )
1534 face_index = 0;
1535 if ( face_index != 0 )
Werner Lemberg77c34b82003-05-20 22:06:38 +00001536 return error;
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001537
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001538 /* Find the length of all the POST resources, concatenated. Assume */
1539 /* worst case (each resource in its own section). */
1540 pfb_len = 0;
1541 for ( i = 0; i < resource_cnt; ++i )
1542 {
1543 error = FT_Stream_Seek( stream, offsets[i] );
1544 if ( error )
1545 goto Exit;
1546 if ( FT_READ_LONG( temp ) )
1547 goto Exit;
1548 pfb_len += temp + 6;
1549 }
1550
1551 if ( FT_ALLOC( pfb_data, (FT_Long)pfb_len + 2 ) )
1552 goto Exit;
1553
David Turnerc313c502003-09-11 19:51:54 +00001554 pfb_data[0] = 0x80;
1555 pfb_data[1] = 1; /* Ascii section */
1556 pfb_data[2] = 0; /* 4-byte length, fill in later */
1557 pfb_data[3] = 0;
1558 pfb_data[4] = 0;
1559 pfb_data[5] = 0;
Suzuki, Toshiya (鈴木俊哉)a2295402006-04-30 04:46:17 +00001560 pfb_pos = 6;
David Turnere2d12842003-09-21 17:15:55 +00001561 pfb_lenpos = 2;
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001562
1563 len = 0;
1564 type = 1;
1565 for ( i = 0; i < resource_cnt; ++i )
1566 {
1567 error = FT_Stream_Seek( stream, offsets[i] );
1568 if ( error )
1569 goto Exit2;
1570 if ( FT_READ_LONG( rlen ) )
1571 goto Exit;
1572 if ( FT_READ_USHORT( flags ) )
1573 goto Exit;
suzuki toshiya5ef20c82010-07-01 18:39:04 +09001574 FT_TRACE3(( "POST fragment[%d]: offsets=0x%08x, rlen=0x%08x, flags=0x%04x\n",
1575 i, offsets[i], rlen, flags ));
1576
suzuki toshiyab2ea64b2010-07-02 18:16:02 +09001577 if ( ( flags >> 8 ) == 0 ) /* Comment, should not be loaded */
1578 continue;
1579
suzuki toshiya5ef20c82010-07-01 18:39:04 +09001580 /* the flags are part of the resource, so rlen >= 2. */
1581 /* but some fonts declare rlen = 0 for empty fragment */
1582 if ( rlen > 2 )
1583 rlen -= 2;
1584 else
1585 rlen = 0;
1586
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001587 if ( ( flags >> 8 ) == type )
1588 len += rlen;
1589 else
1590 {
suzuki toshiyaf29f7412010-07-01 17:31:03 +09001591 if ( pfb_lenpos + 3 > pfb_len + 2 )
1592 goto Exit2;
David Turnerc313c502003-09-11 19:51:54 +00001593 pfb_data[pfb_lenpos ] = (FT_Byte)( len );
1594 pfb_data[pfb_lenpos + 1] = (FT_Byte)( len >> 8 );
1595 pfb_data[pfb_lenpos + 2] = (FT_Byte)( len >> 16 );
1596 pfb_data[pfb_lenpos + 3] = (FT_Byte)( len >> 24 );
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001597
1598 if ( ( flags >> 8 ) == 5 ) /* End of font mark */
1599 break;
1600
suzuki toshiyaf29f7412010-07-01 17:31:03 +09001601 if ( pfb_pos + 6 > pfb_len + 2 )
1602 goto Exit2;
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001603 pfb_data[pfb_pos++] = 0x80;
1604
1605 type = flags >> 8;
1606 len = rlen;
1607
Werner Lemberg013efd12003-09-17 05:26:33 +00001608 pfb_data[pfb_pos++] = (FT_Byte)type;
Suzuki, Toshiya (鈴木俊哉)a2295402006-04-30 04:46:17 +00001609 pfb_lenpos = pfb_pos;
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001610 pfb_data[pfb_pos++] = 0; /* 4-byte length, fill in later */
1611 pfb_data[pfb_pos++] = 0;
1612 pfb_data[pfb_pos++] = 0;
1613 pfb_data[pfb_pos++] = 0;
1614 }
1615
1616 error = FT_Stream_Read( stream, (FT_Byte *)pfb_data + pfb_pos, rlen );
suzuki toshiyac69891a2010-06-25 09:02:18 +09001617 if ( error )
1618 goto Exit2;
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001619 pfb_pos += rlen;
1620 }
1621
suzuki toshiyaf29f7412010-07-01 17:31:03 +09001622 if ( pfb_pos + 2 > pfb_len + 2 )
1623 goto Exit2;
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001624 pfb_data[pfb_pos++] = 0x80;
1625 pfb_data[pfb_pos++] = 3;
1626
suzuki toshiyaf29f7412010-07-01 17:31:03 +09001627 if ( pfb_lenpos + 3 > pfb_len + 2 )
1628 goto Exit2;
David Turnerc313c502003-09-11 19:51:54 +00001629 pfb_data[pfb_lenpos ] = (FT_Byte)( len );
1630 pfb_data[pfb_lenpos + 1] = (FT_Byte)( len >> 8 );
1631 pfb_data[pfb_lenpos + 2] = (FT_Byte)( len >> 16 );
1632 pfb_data[pfb_lenpos + 3] = (FT_Byte)( len >> 24 );
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001633
1634 return open_face_from_buffer( library,
1635 pfb_data,
1636 pfb_pos,
1637 face_index,
1638 "type1",
1639 aface );
1640
1641 Exit2:
1642 FT_FREE( pfb_data );
1643
1644 Exit:
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001645 return error;
1646 }
1647
1648
1649 /* The resource header says we've got resource_cnt `sfnt' */
1650 /* (TrueType/OpenType) resources in this file. Look through */
1651 /* them for the one indicated by face_index, load it into mem, */
1652 /* pass it on the the truetype driver and return it. */
1653 /* */
1654 static FT_Error
1655 Mac_Read_sfnt_Resource( FT_Library library,
1656 FT_Stream stream,
Werner Lemberg75435332004-02-25 12:58:54 +00001657 FT_Long *offsets,
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001658 FT_Long resource_cnt,
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001659 FT_Long face_index,
1660 FT_Face *aface )
1661 {
1662 FT_Memory memory = library->memory;
1663 FT_Byte* sfnt_data;
1664 FT_Error error;
Werner Lemberg75435332004-02-25 12:58:54 +00001665 FT_Long flag_offset;
Werner Lembergdc8ad542003-12-09 02:12:14 +00001666 FT_Long rlen;
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001667 int is_cff;
Suzuki, Toshiya (鈴木俊哉)7a7d4032006-12-15 14:47:42 +00001668 FT_Long face_index_in_resource = 0;
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001669
1670
1671 if ( face_index == -1 )
1672 face_index = 0;
1673 if ( face_index >= resource_cnt )
1674 return FT_Err_Cannot_Open_Resource;
1675
Werner Lemberg75435332004-02-25 12:58:54 +00001676 flag_offset = offsets[face_index];
1677 error = FT_Stream_Seek( stream, flag_offset );
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001678 if ( error )
1679 goto Exit;
1680
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001681 if ( FT_READ_LONG( rlen ) )
1682 goto Exit;
1683 if ( rlen == -1 )
1684 return FT_Err_Cannot_Open_Resource;
1685
Suzuki, Toshiya (鈴木俊哉)1137d042008-10-04 07:11:58 +00001686 error = open_face_PS_from_sfnt_stream( library,
1687 stream,
1688 face_index,
1689 0, NULL,
1690 aface );
1691 if ( !error )
1692 goto Exit;
1693
Suzuki, Toshiya (鈴木俊哉)5a009092009-01-22 03:50:37 +00001694 /* rewind sfnt stream before open_face_PS_from_sfnt_stream() */
1695 if ( FT_Stream_Seek( stream, flag_offset + 4 ) )
1696 goto Exit;
1697
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001698 if ( FT_ALLOC( sfnt_data, (FT_Long)rlen ) )
1699 return error;
1700 error = FT_Stream_Read( stream, (FT_Byte *)sfnt_data, rlen );
1701 if ( error )
1702 goto Exit;
1703
Suzuki, Toshiya (鈴木俊哉)1137d042008-10-04 07:11:58 +00001704 is_cff = rlen > 4 && !ft_memcmp( sfnt_data, "OTTO", 4 );
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001705 error = open_face_from_buffer( library,
1706 sfnt_data,
1707 rlen,
Suzuki, Toshiya (鈴木俊哉)7a7d4032006-12-15 14:47:42 +00001708 face_index_in_resource,
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001709 is_cff ? "cff" : "truetype",
1710 aface );
1711
1712 Exit:
1713 return error;
1714 }
1715
1716
1717 /* Check for a valid resource fork header, or a valid dfont */
1718 /* header. In a resource fork the first 16 bytes are repeated */
1719 /* at the location specified by bytes 4-7. In a dfont bytes */
1720 /* 4-7 point to 16 bytes of zeroes instead. */
1721 /* */
1722 static FT_Error
1723 IsMacResource( FT_Library library,
1724 FT_Stream stream,
1725 FT_Long resource_offset,
1726 FT_Long face_index,
1727 FT_Face *aface )
1728 {
Werner Lemberg75435332004-02-25 12:58:54 +00001729 FT_Memory memory = library->memory;
1730 FT_Error error;
1731 FT_Long map_offset, rdara_pos;
1732 FT_Long *data_offsets;
1733 FT_Long count;
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001734
1735
Werner Lemberg75435332004-02-25 12:58:54 +00001736 error = FT_Raccess_Get_HeaderInfo( library, stream, resource_offset,
1737 &map_offset, &rdara_pos );
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001738 if ( error )
Werner Lemberg75435332004-02-25 12:58:54 +00001739 return error;
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001740
Werner Lemberg75435332004-02-25 12:58:54 +00001741 error = FT_Raccess_Get_DataOffsets( library, stream,
1742 map_offset, rdara_pos,
Suzuki, Toshiya (鈴木俊哉)21bd5162008-10-04 18:10:28 +00001743 TTAG_POST,
Werner Lemberg75435332004-02-25 12:58:54 +00001744 &data_offsets, &count );
1745 if ( !error )
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001746 {
Werner Lemberg75435332004-02-25 12:58:54 +00001747 error = Mac_Read_POST_Resource( library, stream, data_offsets, count,
1748 face_index, aface );
1749 FT_FREE( data_offsets );
Werner Lemberg0fd08bd2006-12-16 02:57:46 +00001750 /* POST exists in an LWFN providing a single face */
Werner Lemberg17432b52007-01-12 09:28:44 +00001751 if ( !error )
David Turner7a3c5642007-01-11 15:09:01 +00001752 (*aface)->num_faces = 1;
Werner Lemberg75435332004-02-25 12:58:54 +00001753 return error;
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001754 }
1755
Werner Lemberg75435332004-02-25 12:58:54 +00001756 error = FT_Raccess_Get_DataOffsets( library, stream,
1757 map_offset, rdara_pos,
Suzuki, Toshiya (鈴木俊哉)21bd5162008-10-04 18:10:28 +00001758 TTAG_sfnt,
Werner Lemberg75435332004-02-25 12:58:54 +00001759 &data_offsets, &count );
1760 if ( !error )
1761 {
Werner Lemberg0fd08bd2006-12-16 02:57:46 +00001762 FT_Long face_index_internal = face_index % count;
Suzuki, Toshiya (鈴木俊哉)7a7d4032006-12-15 14:47:42 +00001763
1764
Werner Lemberg75435332004-02-25 12:58:54 +00001765 error = Mac_Read_sfnt_Resource( library, stream, data_offsets, count,
Suzuki, Toshiya (鈴木俊哉)7a7d4032006-12-15 14:47:42 +00001766 face_index_internal, aface );
Werner Lemberg75435332004-02-25 12:58:54 +00001767 FT_FREE( data_offsets );
Werner Lemberg17432b52007-01-12 09:28:44 +00001768 if ( !error )
David Turner7a3c5642007-01-11 15:09:01 +00001769 (*aface)->num_faces = count;
Werner Lemberg75435332004-02-25 12:58:54 +00001770 }
1771
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001772 return error;
1773 }
1774
1775
1776 /* Check for a valid macbinary header, and if we find one */
1777 /* check that the (flattened) resource fork in it is valid. */
1778 /* */
1779 static FT_Error
1780 IsMacBinary( FT_Library library,
1781 FT_Stream stream,
1782 FT_Long face_index,
1783 FT_Face *aface )
1784 {
1785 unsigned char header[128];
1786 FT_Error error;
1787 FT_Long dlen, offset;
1788
1789
Suzuki, Toshiya (鈴木俊哉)86c0f902007-11-20 14:00:17 +00001790 if ( NULL == stream )
1791 return FT_Err_Invalid_Stream_Operation;
1792
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001793 error = FT_Stream_Seek( stream, 0 );
1794 if ( error )
1795 goto Exit;
1796
1797 error = FT_Stream_Read( stream, (FT_Byte*)header, 128 );
1798 if ( error )
1799 goto Exit;
1800
1801 if ( header[ 0] != 0 ||
1802 header[74] != 0 ||
1803 header[82] != 0 ||
1804 header[ 1] == 0 ||
1805 header[ 1] > 33 ||
1806 header[63] != 0 ||
1807 header[2 + header[1]] != 0 )
1808 return FT_Err_Unknown_File_Format;
1809
1810 dlen = ( header[0x53] << 24 ) |
1811 ( header[0x54] << 16 ) |
1812 ( header[0x55] << 8 ) |
1813 header[0x56];
1814#if 0
1815 rlen = ( header[0x57] << 24 ) |
1816 ( header[0x58] << 16 ) |
1817 ( header[0x59] << 8 ) |
1818 header[0x5a];
1819#endif /* 0 */
1820 offset = 128 + ( ( dlen + 127 ) & ~127 );
1821
1822 return IsMacResource( library, stream, offset, face_index, aface );
1823
1824 Exit:
1825 return error;
1826 }
1827
1828
Werner Lemberg75435332004-02-25 12:58:54 +00001829 static FT_Error
1830 load_face_in_embedded_rfork( FT_Library library,
1831 FT_Stream stream,
1832 FT_Long face_index,
1833 FT_Face *aface,
1834 const FT_Open_Args *args )
1835 {
1836
1837#undef FT_COMPONENT
1838#define FT_COMPONENT trace_raccess
1839
1840 FT_Memory memory = library->memory;
1841 FT_Error error = FT_Err_Unknown_File_Format;
1842 int i;
1843
1844 char * file_names[FT_RACCESS_N_RULES];
1845 FT_Long offsets[FT_RACCESS_N_RULES];
1846 FT_Error errors[FT_RACCESS_N_RULES];
1847
1848 FT_Open_Args args2;
Suzuki, Toshiya (鈴木俊哉)4c60bd92008-08-19 15:35:44 +00001849 FT_Stream stream2 = 0;
Werner Lemberg75435332004-02-25 12:58:54 +00001850
1851
1852 FT_Raccess_Guess( library, stream,
1853 args->pathname, file_names, offsets, errors );
1854
1855 for ( i = 0; i < FT_RACCESS_N_RULES; i++ )
1856 {
1857 if ( errors[i] )
1858 {
1859 FT_TRACE3(( "Error[%d] has occurred in rule %d\n", errors[i], i ));
1860 continue;
1861 }
1862
1863 args2.flags = FT_OPEN_PATHNAME;
1864 args2.pathname = file_names[i] ? file_names[i] : args->pathname;
1865
1866 FT_TRACE3(( "Try rule %d: %s (offset=%d) ...",
1867 i, args2.pathname, offsets[i] ));
1868
1869 error = FT_Stream_New( library, &args2, &stream2 );
1870 if ( error )
1871 {
1872 FT_TRACE3(( "failed\n" ));
1873 continue;
1874 }
1875
1876 error = IsMacResource( library, stream2, offsets[i],
1877 face_index, aface );
Suzuki, Toshiya (鈴木俊哉)de0a96c2006-05-19 23:16:12 +00001878 FT_Stream_Free( stream2, 0 );
Werner Lemberg75435332004-02-25 12:58:54 +00001879
1880 FT_TRACE3(( "%s\n", error ? "failed": "successful" ));
1881
1882 if ( !error )
1883 break;
1884 }
1885
1886 for (i = 0; i < FT_RACCESS_N_RULES; i++)
1887 {
1888 if ( file_names[i] )
1889 FT_FREE( file_names[i] );
1890 }
1891
1892 /* Caller (load_mac_face) requires FT_Err_Unknown_File_Format. */
1893 if ( error )
1894 error = FT_Err_Unknown_File_Format;
1895
1896 return error;
1897
1898#undef FT_COMPONENT
1899#define FT_COMPONENT trace_objs
1900
1901 }
1902
1903
Suzuki, Toshiya (鈴木俊哉)f4147022008-10-02 01:43:18 +00001904 /* Check for some macintosh formats without Carbon framework. */
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001905 /* Is this a macbinary file? If so look at the resource fork. */
1906 /* Is this a mac dfont file? */
1907 /* Is this an old style resource fork? (in data) */
Werner Lemberg75435332004-02-25 12:58:54 +00001908 /* Else call load_face_in_embedded_rfork to try extra rules */
1909 /* (defined in `ftrfork.c'). */
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001910 /* */
1911 static FT_Error
1912 load_mac_face( FT_Library library,
1913 FT_Stream stream,
1914 FT_Long face_index,
1915 FT_Face *aface,
1916 const FT_Open_Args *args )
1917 {
1918 FT_Error error;
1919 FT_UNUSED( args );
1920
1921
1922 error = IsMacBinary( library, stream, face_index, aface );
1923 if ( FT_ERROR_BASE( error ) == FT_Err_Unknown_File_Format )
Werner Lemberg75435332004-02-25 12:58:54 +00001924 {
1925
1926#undef FT_COMPONENT
1927#define FT_COMPONENT trace_raccess
1928
1929 FT_TRACE3(( "Try as dfont: %s ...", args->pathname ));
1930
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001931 error = IsMacResource( library, stream, 0, face_index, aface );
1932
Werner Lemberg75435332004-02-25 12:58:54 +00001933 FT_TRACE3(( "%s\n", error ? "failed" : "successful" ));
David Turnere2d12842003-09-21 17:15:55 +00001934
Werner Lemberg75435332004-02-25 12:58:54 +00001935#undef FT_COMPONENT
1936#define FT_COMPONENT trace_objs
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001937
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001938 }
1939
Werner Lemberg75435332004-02-25 12:58:54 +00001940 if ( ( FT_ERROR_BASE( error ) == FT_Err_Unknown_File_Format ||
1941 FT_ERROR_BASE( error ) == FT_Err_Invalid_Stream_Operation ) &&
1942 ( args->flags & FT_OPEN_PATHNAME ) )
1943 error = load_face_in_embedded_rfork( library, stream,
1944 face_index, aface, args );
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001945 return error;
1946 }
Suzuki, Toshiya (鈴木俊哉)f4147022008-10-02 01:43:18 +00001947#endif
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001948
1949#endif /* !FT_MACINTOSH && FT_CONFIG_OPTION_MAC_FONTS */
1950
1951
Werner Lemberg90a03302000-11-07 17:21:11 +00001952 /* documentation is in freetype.h */
1953
Werner Lembergf814d0f2001-06-27 16:18:10 +00001954 FT_EXPORT_DEF( FT_Error )
Werner Lembergc4c373c2002-10-07 09:15:20 +00001955 FT_Open_Face( FT_Library library,
1956 const FT_Open_Args* args,
1957 FT_Long face_index,
1958 FT_Face *aface )
David Turnerd2b1f351999-12-16 23:11:37 +00001959 {
1960 FT_Error error;
1961 FT_Driver driver;
1962 FT_Memory memory;
Werner Lembergfe3433c2010-07-18 18:41:47 +02001963 FT_Stream stream = NULL;
1964 FT_Face face = NULL;
1965 FT_ListNode node = NULL;
David Turnerc5cdf8b2000-07-27 21:40:22 +00001966 FT_Bool external_stream;
Werner Lembergc32e83f2008-04-01 06:07:37 +00001967 FT_Module* cur;
1968 FT_Module* limit;
Werner Lemberg547a2522000-02-16 08:23:58 +00001969
Werner Lemberg58b17f92000-07-27 23:29:08 +00001970
Werner Lembergf9b03752000-09-11 22:50:13 +00001971 /* test for valid `library' delayed to */
Werner Lemberg75435332004-02-25 12:58:54 +00001972 /* FT_Stream_New() */
David Turnerd2b1f351999-12-16 23:11:37 +00001973
Werner Lembergce235ea2005-05-17 20:35:23 +00001974 if ( ( !aface && face_index >= 0 ) || !args )
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001975 return FT_Err_Invalid_Argument;
1976
David Turnerb08fe2d2002-08-27 20:20:29 +00001977 external_stream = FT_BOOL( ( args->flags & FT_OPEN_STREAM ) &&
Werner Lemberg8eb03532001-06-19 23:03:41 +00001978 args->stream );
David Turnerc5cdf8b2000-07-27 21:40:22 +00001979
David Turnercda32b72000-02-10 16:14:35 +00001980 /* create input stream */
Werner Lemberg75435332004-02-25 12:58:54 +00001981 error = FT_Stream_New( library, args, &stream );
Werner Lembergdeb4e982000-06-29 03:14:25 +00001982 if ( error )
Suzuki, Toshiya (鈴木俊哉)86c0f902007-11-20 14:00:17 +00001983 goto Fail3;
David Turnercda32b72000-02-10 16:14:35 +00001984
David Turnerd2b1f351999-12-16 23:11:37 +00001985 memory = library->memory;
1986
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001987 /* If the font driver is specified in the `args' structure, use */
Werner Lembergdeb4e982000-06-29 03:14:25 +00001988 /* it. Otherwise, we scan the list of registered drivers. */
David Turnerb08fe2d2002-08-27 20:20:29 +00001989 if ( ( args->flags & FT_OPEN_DRIVER ) && args->driver )
David Turner7663f222000-02-13 13:37:38 +00001990 {
Werner Lemberga929ba92000-06-25 06:47:11 +00001991 driver = FT_DRIVER( args->driver );
David Turnerf0df85b2000-06-22 00:17:42 +00001992
1993 /* not all modules are drivers, so check... */
Werner Lemberga929ba92000-06-25 06:47:11 +00001994 if ( FT_MODULE_IS_DRIVER( driver ) )
David Turner7663f222000-02-13 13:37:38 +00001995 {
Werner Lemberg3c403e42002-08-06 21:47:40 +00001996 FT_Int num_params = 0;
1997 FT_Parameter* params = 0;
1998
Werner Lemberga929ba92000-06-25 06:47:11 +00001999
David Turnerb08fe2d2002-08-27 20:20:29 +00002000 if ( args->flags & FT_OPEN_PARAMS )
David Turner4f2c5542000-05-12 10:19:41 +00002001 {
2002 num_params = args->num_params;
2003 params = args->params;
2004 }
David Turnere49ab252000-05-16 23:44:38 +00002005
David Turner4f2c5542000-05-12 10:19:41 +00002006 error = open_face( driver, stream, face_index,
2007 num_params, params, &face );
Werner Lemberg547a2522000-02-16 08:23:58 +00002008 if ( !error )
2009 goto Success;
David Turner7663f222000-02-13 13:37:38 +00002010 }
2011 else
2012 error = FT_Err_Invalid_Handle;
2013
Werner Lemberg75435332004-02-25 12:58:54 +00002014 FT_Stream_Free( stream, external_stream );
David Turner7663f222000-02-13 13:37:38 +00002015 goto Fail;
2016 }
Just van Rossum1e5754f2000-03-02 10:52:57 +00002017 else
David Turnerd2b1f351999-12-16 23:11:37 +00002018 {
2019 /* check each font driver for an appropriate format */
Werner Lembergc32e83f2008-04-01 06:07:37 +00002020 cur = library->modules;
2021 limit = cur + library->num_modules;
David Turnerd2b1f351999-12-16 23:11:37 +00002022
Werner Lemberga929ba92000-06-25 06:47:11 +00002023
David Turnerd2b1f351999-12-16 23:11:37 +00002024 for ( ; cur < limit; cur++ )
2025 {
David Turnerf0df85b2000-06-22 00:17:42 +00002026 /* not all modules are font drivers, so check... */
Werner Lemberga929ba92000-06-25 06:47:11 +00002027 if ( FT_MODULE_IS_DRIVER( cur[0] ) )
David Turnerd2b1f351999-12-16 23:11:37 +00002028 {
David Turner4f2c5542000-05-12 10:19:41 +00002029 FT_Int num_params = 0;
2030 FT_Parameter* params = 0;
David Turnere49ab252000-05-16 23:44:38 +00002031
Werner Lemberg3c403e42002-08-06 21:47:40 +00002032
Werner Lemberga929ba92000-06-25 06:47:11 +00002033 driver = FT_DRIVER( cur[0] );
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00002034
David Turnerb08fe2d2002-08-27 20:20:29 +00002035 if ( args->flags & FT_OPEN_PARAMS )
David Turner4f2c5542000-05-12 10:19:41 +00002036 {
2037 num_params = args->num_params;
2038 params = args->params;
2039 }
David Turnere49ab252000-05-16 23:44:38 +00002040
Graham Asherd53cf1d2002-07-18 15:04:29 +00002041 error = open_face( driver, stream, face_index,
Werner Lemberg51daa4f2003-05-18 22:40:11 +00002042 num_params, params, &face );
David Turnerd2b1f351999-12-16 23:11:37 +00002043 if ( !error )
2044 goto Success;
2045
Suzuki, Toshiya (鈴木俊哉)2d3e0af2008-10-05 02:38:57 +00002046#ifdef FT_CONFIG_OPTION_MAC_FONTS
2047 if ( ft_strcmp( cur[0]->clazz->module_name, "truetype" ) == 0 &&
Werner Lemberg570b1fd2008-10-05 06:08:40 +00002048 FT_ERROR_BASE( error ) == FT_Err_Table_Missing )
Suzuki, Toshiya (鈴木俊哉)2d3e0af2008-10-05 02:38:57 +00002049 {
2050 /* TrueType but essential tables are missing */
2051 if ( FT_Stream_Seek( stream, 0 ) )
2052 break;
2053
2054 error = open_face_PS_from_sfnt_stream( library,
2055 stream,
2056 face_index,
2057 num_params,
2058 params,
2059 aface );
2060 if ( !error )
2061 {
2062 FT_Stream_Free( stream, external_stream );
2063 return error;
2064 }
2065 }
2066#endif
2067
Werner Lemberg79860702001-06-08 21:17:29 +00002068 if ( FT_ERROR_BASE( error ) != FT_Err_Unknown_File_Format )
Werner Lemberg51daa4f2003-05-18 22:40:11 +00002069 goto Fail3;
David Turnerd2b1f351999-12-16 23:11:37 +00002070 }
2071 }
2072
Werner Lemberg51daa4f2003-05-18 22:40:11 +00002073 Fail3:
2074 /* If we are on the mac, and we get an FT_Err_Invalid_Stream_Operation */
2075 /* it may be because we have an empty data fork, so we need to check */
2076 /* the resource fork. */
Suzuki, Toshiya (鈴木俊哉)86c0f902007-11-20 14:00:17 +00002077 if ( FT_ERROR_BASE( error ) != FT_Err_Cannot_Open_Stream &&
2078 FT_ERROR_BASE( error ) != FT_Err_Unknown_File_Format &&
Werner Lemberg51daa4f2003-05-18 22:40:11 +00002079 FT_ERROR_BASE( error ) != FT_Err_Invalid_Stream_Operation )
2080 goto Fail2;
2081
Werner Lembergdc8ad542003-12-09 02:12:14 +00002082#if !defined( FT_MACINTOSH ) && defined( FT_CONFIG_OPTION_MAC_FONTS )
Werner Lemberg51daa4f2003-05-18 22:40:11 +00002083 error = load_mac_face( library, stream, face_index, aface, args );
2084 if ( !error )
2085 {
2086 /* We don't want to go to Success here. We've already done that. */
2087 /* On the other hand, if we succeeded we still need to close this */
2088 /* stream (we opened a different stream which extracted the */
2089 /* interesting information out of this stream here. That stream */
2090 /* will still be open and the face will point to it). */
Werner Lemberg75435332004-02-25 12:58:54 +00002091 FT_Stream_Free( stream, external_stream );
Werner Lemberg51daa4f2003-05-18 22:40:11 +00002092 return error;
2093 }
2094
2095 if ( FT_ERROR_BASE( error ) != FT_Err_Unknown_File_Format )
2096 goto Fail2;
Werner Lembergdc8ad542003-12-09 02:12:14 +00002097#endif /* !FT_MACINTOSH && FT_CONFIG_OPTION_MAC_FONTS */
Werner Lemberg51daa4f2003-05-18 22:40:11 +00002098
David Turnerd2b1f351999-12-16 23:11:37 +00002099 /* no driver is able to handle this format */
2100 error = FT_Err_Unknown_File_Format;
David Turnerebe85f52001-05-11 14:25:57 +00002101
2102 Fail2:
Werner Lemberg75435332004-02-25 12:58:54 +00002103 FT_Stream_Free( stream, external_stream );
David Turnercda32b72000-02-10 16:14:35 +00002104 goto Fail;
David Turnerd2b1f351999-12-16 23:11:37 +00002105 }
2106
2107 Success:
Werner Lembergf9b03752000-09-11 22:50:13 +00002108 FT_TRACE4(( "FT_Open_Face: New face object, adding to list\n" ));
David Turnerd2b1f351999-12-16 23:11:37 +00002109
Werner Lembergdeb4e982000-06-29 03:14:25 +00002110 /* set the FT_FACE_FLAG_EXTERNAL_STREAM bit for FT_Done_Face */
David Turnerc5cdf8b2000-07-27 21:40:22 +00002111 if ( external_stream )
David Turnerf0df85b2000-06-22 00:17:42 +00002112 face->face_flags |= FT_FACE_FLAG_EXTERNAL_STREAM;
2113
Werner Lemberg547a2522000-02-16 08:23:58 +00002114 /* add the face object to its driver's list */
David Turnere459d742002-03-22 13:52:37 +00002115 if ( FT_NEW( node ) )
David Turnerd2b1f351999-12-16 23:11:37 +00002116 goto Fail;
2117
2118 node->data = face;
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00002119 /* don't assume driver is the same as face->driver, so use */
2120 /* face->driver instead. */
Just van Rossum7eef5362000-03-05 16:07:58 +00002121 FT_List_Add( &face->driver->faces_list, node );
David Turnerd2b1f351999-12-16 23:11:37 +00002122
Werner Lemberg547a2522000-02-16 08:23:58 +00002123 /* now allocate a glyph slot object for the face */
Werner Lembergb9ee7372005-05-20 21:52:19 +00002124 FT_TRACE4(( "FT_Open_Face: Creating glyph slot\n" ));
David Turnerd2b1f351999-12-16 23:11:37 +00002125
David Turner92f30c82005-10-17 21:17:20 +00002126 if ( face_index >= 0 )
David Turnerd2b1f351999-12-16 23:11:37 +00002127 {
David Turner92f30c82005-10-17 21:17:20 +00002128 error = FT_New_GlyphSlot( face, NULL );
Werner Lembergdeb4e982000-06-29 03:14:25 +00002129 if ( error )
2130 goto Fail;
2131
David Turner92f30c82005-10-17 21:17:20 +00002132 /* finally, allocate a size object for the face */
2133 {
2134 FT_Size size;
2135
2136
2137 FT_TRACE4(( "FT_Open_Face: Creating size object\n" ));
2138
2139 error = FT_New_Size( face, &size );
2140 if ( error )
2141 goto Fail;
2142
2143 face->size = size;
2144 }
David Turnerd2b1f351999-12-16 23:11:37 +00002145 }
Werner Lemberg7880dd62000-01-10 17:19:45 +00002146
Wu, Chia-I (吳佳一)e5ff0592006-01-15 06:00:49 +00002147 /* some checks */
2148
2149 if ( FT_IS_SCALABLE( face ) )
2150 {
2151 if ( face->height < 0 )
Werner Lembergbe3c9812006-01-27 14:16:16 +00002152 face->height = (FT_Short)-face->height;
Wu, Chia-I (吳佳一)e5ff0592006-01-15 06:00:49 +00002153
2154 if ( !FT_HAS_VERTICAL( face ) )
Werner Lembergbe3c9812006-01-27 14:16:16 +00002155 face->max_advance_height = (FT_Short)face->height;
Wu, Chia-I (吳佳一)e5ff0592006-01-15 06:00:49 +00002156 }
2157
2158 if ( FT_HAS_FIXED_SIZES( face ) )
2159 {
Werner Lemberg1723dcc2006-01-15 07:30:32 +00002160 FT_Int i;
Wu, Chia-I (吳佳一)e5ff0592006-01-15 06:00:49 +00002161
David Turnercda2d952006-02-16 22:45:31 +00002162
Wu, Chia-I (吳佳一)e5ff0592006-01-15 06:00:49 +00002163 for ( i = 0; i < face->num_fixed_sizes; i++ )
2164 {
2165 FT_Bitmap_Size* bsize = face->available_sizes + i;
2166
2167
2168 if ( bsize->height < 0 )
Werner Lembergbe3c9812006-01-27 14:16:16 +00002169 bsize->height = (FT_Short)-bsize->height;
Wu, Chia-I (吳佳一)e5ff0592006-01-15 06:00:49 +00002170 if ( bsize->x_ppem < 0 )
Werner Lembergbe3c9812006-01-27 14:16:16 +00002171 bsize->x_ppem = (FT_Short)-bsize->x_ppem;
Wu, Chia-I (吳佳一)e5ff0592006-01-15 06:00:49 +00002172 if ( bsize->y_ppem < 0 )
2173 bsize->y_ppem = -bsize->y_ppem;
2174 }
2175 }
2176
David Turner54e75742000-11-04 02:52:02 +00002177 /* initialize internal face data */
2178 {
2179 FT_Face_Internal internal = face->internal;
David Turner61d6b2b2001-05-16 17:49:07 +00002180
David Turner37379e22000-03-28 11:22:31 +00002181
David Turner54e75742000-11-04 02:52:02 +00002182 internal->transform_matrix.xx = 0x10000L;
2183 internal->transform_matrix.xy = 0;
2184 internal->transform_matrix.yx = 0;
2185 internal->transform_matrix.yy = 0x10000L;
David Turner61d6b2b2001-05-16 17:49:07 +00002186
David Turner54e75742000-11-04 02:52:02 +00002187 internal->transform_delta.x = 0;
2188 internal->transform_delta.y = 0;
Werner Lembergfe3433c2010-07-18 18:41:47 +02002189
2190 internal->refcount = 1;
David Turner54e75742000-11-04 02:52:02 +00002191 }
David Turner37379e22000-03-28 11:22:31 +00002192
Werner Lembergce235ea2005-05-17 20:35:23 +00002193 if ( aface )
2194 *aface = face;
Werner Lembergb2d02532005-11-04 06:58:49 +00002195 else
2196 FT_Done_Face( face );
2197
David Turnerd2b1f351999-12-16 23:11:37 +00002198 goto Exit;
2199
2200 Fail:
2201 FT_Done_Face( face );
2202
David Turnerd2b1f351999-12-16 23:11:37 +00002203 Exit:
2204 FT_TRACE4(( "FT_Open_Face: Return %d\n", error ));
Werner Lembergdeb4e982000-06-29 03:14:25 +00002205
David Turnerd2b1f351999-12-16 23:11:37 +00002206 return error;
2207 }
2208
2209
Werner Lemberg90a03302000-11-07 17:21:11 +00002210 /* documentation is in freetype.h */
2211
Werner Lembergf814d0f2001-06-27 16:18:10 +00002212 FT_EXPORT_DEF( FT_Error )
2213 FT_Attach_File( FT_Face face,
2214 const char* filepathname )
David Turner7663f222000-02-13 13:37:38 +00002215 {
David Turner37379e22000-03-28 11:22:31 +00002216 FT_Open_Args open;
David Turner7663f222000-02-13 13:37:38 +00002217
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00002218
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00002219 /* test for valid `face' delayed to FT_Attach_Stream() */
2220
2221 if ( !filepathname )
2222 return FT_Err_Invalid_Argument;
2223
Werner Lembergb8fdcd62004-08-03 03:28:11 +00002224 open.stream = NULL;
David Turnerb08fe2d2002-08-27 20:20:29 +00002225 open.flags = FT_OPEN_PATHNAME;
David Turner4f2c5542000-05-12 10:19:41 +00002226 open.pathname = (char*)filepathname;
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00002227
David Turner7663f222000-02-13 13:37:38 +00002228 return FT_Attach_Stream( face, &open );
2229 }
Werner Lemberg547a2522000-02-16 08:23:58 +00002230
David Turnere49ab252000-05-16 23:44:38 +00002231
Werner Lemberg90a03302000-11-07 17:21:11 +00002232 /* documentation is in freetype.h */
2233
Werner Lembergf814d0f2001-06-27 16:18:10 +00002234 FT_EXPORT_DEF( FT_Error )
2235 FT_Attach_Stream( FT_Face face,
2236 FT_Open_Args* parameters )
David Turner7663f222000-02-13 13:37:38 +00002237 {
2238 FT_Stream stream;
2239 FT_Error error;
2240 FT_Driver driver;
David Turnere49ab252000-05-16 23:44:38 +00002241
David Turneref3c1262002-03-14 09:22:48 +00002242 FT_Driver_Class clazz;
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00002243
Werner Lemberga929ba92000-06-25 06:47:11 +00002244
Werner Lemberg75435332004-02-25 12:58:54 +00002245 /* test for valid `parameters' delayed to FT_Stream_New() */
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00002246
2247 if ( !face )
2248 return FT_Err_Invalid_Face_Handle;
David Turnere49ab252000-05-16 23:44:38 +00002249
David Turner7663f222000-02-13 13:37:38 +00002250 driver = face->driver;
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00002251 if ( !driver )
2252 return FT_Err_Invalid_Driver_Handle;
2253
Werner Lemberg75435332004-02-25 12:58:54 +00002254 error = FT_Stream_New( driver->root.library, parameters, &stream );
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00002255 if ( error )
2256 goto Exit;
David Turnere49ab252000-05-16 23:44:38 +00002257
David Turner7663f222000-02-13 13:37:38 +00002258 /* we implement FT_Attach_Stream in each driver through the */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00002259 /* `attach_file' interface */
2260
David Turner7663f222000-02-13 13:37:38 +00002261 error = FT_Err_Unimplemented_Feature;
David Turnerf0df85b2000-06-22 00:17:42 +00002262 clazz = driver->clazz;
Werner Lemberga929ba92000-06-25 06:47:11 +00002263 if ( clazz->attach_file )
David Turnerf0df85b2000-06-22 00:17:42 +00002264 error = clazz->attach_file( face, stream );
David Turnere49ab252000-05-16 23:44:38 +00002265
David Turner7663f222000-02-13 13:37:38 +00002266 /* close the attached stream */
Werner Lemberg75435332004-02-25 12:58:54 +00002267 FT_Stream_Free( stream,
Werner Lemberg58b17f92000-07-27 23:29:08 +00002268 (FT_Bool)( parameters->stream &&
David Turnerb08fe2d2002-08-27 20:20:29 +00002269 ( parameters->flags & FT_OPEN_STREAM ) ) );
David Turnere49ab252000-05-16 23:44:38 +00002270
David Turner7663f222000-02-13 13:37:38 +00002271 Exit:
2272 return error;
2273 }
2274
2275
Werner Lemberg90a03302000-11-07 17:21:11 +00002276 /* documentation is in freetype.h */
2277
Werner Lembergf814d0f2001-06-27 16:18:10 +00002278 FT_EXPORT_DEF( FT_Error )
Werner Lembergfe3433c2010-07-18 18:41:47 +02002279 FT_Reference_Face( FT_Face face )
2280 {
2281 face->internal->refcount++;
2282
2283 return FT_Err_Ok;
2284 }
2285
2286
2287 /* documentation is in freetype.h */
2288
2289 FT_EXPORT_DEF( FT_Error )
Werner Lembergf814d0f2001-06-27 16:18:10 +00002290 FT_Done_Face( FT_Face face )
David Turnerd2b1f351999-12-16 23:11:37 +00002291 {
Werner Lemberga929ba92000-06-25 06:47:11 +00002292 FT_Error error;
2293 FT_Driver driver;
2294 FT_Memory memory;
2295 FT_ListNode node;
2296
David Turnerd2b1f351999-12-16 23:11:37 +00002297
David Turnerf0df85b2000-06-22 00:17:42 +00002298 error = FT_Err_Invalid_Face_Handle;
2299 if ( face && face->driver )
David Turnerd2b1f351999-12-16 23:11:37 +00002300 {
Werner Lembergfe3433c2010-07-18 18:41:47 +02002301 face->internal->refcount--;
2302 if ( face->internal->refcount > 0 )
David Turnerf0df85b2000-06-22 00:17:42 +00002303 error = FT_Err_Ok;
Werner Lembergfe3433c2010-07-18 18:41:47 +02002304 else
2305 {
2306 driver = face->driver;
2307 memory = driver->root.memory;
2308
2309 /* find face in driver's list */
2310 node = FT_List_Find( &driver->faces_list, face );
2311 if ( node )
2312 {
2313 /* remove face object from the driver's list */
2314 FT_List_Remove( &driver->faces_list, node );
2315 FT_FREE( node );
2316
2317 /* now destroy the object proper */
2318 destroy_face( memory, face, driver );
2319 error = FT_Err_Ok;
2320 }
David Turnerf0df85b2000-06-22 00:17:42 +00002321 }
David Turnerd2b1f351999-12-16 23:11:37 +00002322 }
Werner Lembergfe3433c2010-07-18 18:41:47 +02002323
David Turnerd2b1f351999-12-16 23:11:37 +00002324 return error;
2325 }
2326
2327
Werner Lemberg90a03302000-11-07 17:21:11 +00002328 /* documentation is in ftobjs.h */
2329
Werner Lembergf814d0f2001-06-27 16:18:10 +00002330 FT_EXPORT_DEF( FT_Error )
2331 FT_New_Size( FT_Face face,
2332 FT_Size *asize )
David Turnerd2b1f351999-12-16 23:11:37 +00002333 {
Werner Lembergf8ba2002002-03-30 13:16:35 +00002334 FT_Error error;
2335 FT_Memory memory;
2336 FT_Driver driver;
David Turneref3c1262002-03-14 09:22:48 +00002337 FT_Driver_Class clazz;
David Turnerd2b1f351999-12-16 23:11:37 +00002338
Werner Lembergf8ba2002002-03-30 13:16:35 +00002339 FT_Size size = 0;
2340 FT_ListNode node = 0;
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00002341
Werner Lemberga929ba92000-06-25 06:47:11 +00002342
Werner Lembergb48a6092000-07-09 19:15:30 +00002343 if ( !face )
2344 return FT_Err_Invalid_Face_Handle;
2345
2346 if ( !asize )
2347 return FT_Err_Invalid_Size_Handle;
2348
2349 if ( !face->driver )
2350 return FT_Err_Invalid_Driver_Handle;
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00002351
Werner Lembergdeb4e982000-06-29 03:14:25 +00002352 *asize = 0;
2353
David Turnerf0df85b2000-06-22 00:17:42 +00002354 driver = face->driver;
2355 clazz = driver->clazz;
2356 memory = face->memory;
David Turnerd2b1f351999-12-16 23:11:37 +00002357
2358 /* Allocate new size object and perform basic initialisation */
David Turnere459d742002-03-22 13:52:37 +00002359 if ( FT_ALLOC( size, clazz->size_object_size ) || FT_NEW( node ) )
David Turnerd2b1f351999-12-16 23:11:37 +00002360 goto Exit;
2361
2362 size->face = face;
David Turner61d6b2b2001-05-16 17:49:07 +00002363
David Turner54e75742000-11-04 02:52:02 +00002364 /* for now, do not use any internal fields in size objects */
2365 size->internal = 0;
David Turnerd2b1f351999-12-16 23:11:37 +00002366
Werner Lemberga929ba92000-06-25 06:47:11 +00002367 if ( clazz->init_size )
David Turnerf0df85b2000-06-22 00:17:42 +00002368 error = clazz->init_size( size );
David Turnerd2b1f351999-12-16 23:11:37 +00002369
2370 /* in case of success, add to the face's list */
2371 if ( !error )
2372 {
2373 *asize = size;
2374 node->data = size;
2375 FT_List_Add( &face->sizes_list, node );
David Turnerd2b1f351999-12-16 23:11:37 +00002376 }
2377
2378 Exit:
2379 if ( error )
2380 {
David Turnere459d742002-03-22 13:52:37 +00002381 FT_FREE( node );
2382 FT_FREE( size );
David Turnerd2b1f351999-12-16 23:11:37 +00002383 }
2384
2385 return error;
2386 }
2387
2388
Werner Lemberg90a03302000-11-07 17:21:11 +00002389 /* documentation is in ftobjs.h */
2390
Werner Lembergf814d0f2001-06-27 16:18:10 +00002391 FT_EXPORT_DEF( FT_Error )
2392 FT_Done_Size( FT_Size size )
David Turnerd2b1f351999-12-16 23:11:37 +00002393 {
2394 FT_Error error;
2395 FT_Driver driver;
2396 FT_Memory memory;
2397 FT_Face face;
2398 FT_ListNode node;
2399
2400
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00002401 if ( !size )
David Turnerd2b1f351999-12-16 23:11:37 +00002402 return FT_Err_Invalid_Size_Handle;
2403
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00002404 face = size->face;
2405 if ( !face )
2406 return FT_Err_Invalid_Face_Handle;
2407
2408 driver = face->driver;
David Turnerd2b1f351999-12-16 23:11:37 +00002409 if ( !driver )
2410 return FT_Err_Invalid_Driver_Handle;
2411
David Turnerf0df85b2000-06-22 00:17:42 +00002412 memory = driver->root.memory;
David Turnerd2b1f351999-12-16 23:11:37 +00002413
2414 error = FT_Err_Ok;
David Turnerd2b1f351999-12-16 23:11:37 +00002415 node = FT_List_Find( &face->sizes_list, size );
2416 if ( node )
2417 {
2418 FT_List_Remove( &face->sizes_list, node );
David Turnere459d742002-03-22 13:52:37 +00002419 FT_FREE( node );
David Turnerd2b1f351999-12-16 23:11:37 +00002420
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00002421 if ( face->size == size )
David Turnerd2b1f351999-12-16 23:11:37 +00002422 {
2423 face->size = 0;
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00002424 if ( face->sizes_list.head )
David Turnerd2b1f351999-12-16 23:11:37 +00002425 face->size = (FT_Size)(face->sizes_list.head->data);
2426 }
2427
2428 destroy_size( memory, size, driver );
2429 }
2430 else
2431 error = FT_Err_Invalid_Size_Handle;
2432
Werner Lembergcf24d512001-06-18 14:23:45 +00002433 return error;
David Turnerd2b1f351999-12-16 23:11:37 +00002434 }
2435
2436
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002437 /* documentation is in ftobjs.h */
2438
2439 FT_BASE_DEF( FT_Error )
2440 FT_Match_Size( FT_Face face,
2441 FT_Size_Request req,
2442 FT_Bool ignore_width,
Werner Lemberg8c4120d2007-01-15 06:42:40 +00002443 FT_ULong* size_index )
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002444 {
2445 FT_Int i;
2446 FT_Long w, h;
2447
2448
2449 if ( !FT_HAS_FIXED_SIZES( face ) )
2450 return FT_Err_Invalid_Face_Handle;
2451
2452 /* FT_Bitmap_Size doesn't provide enough info... */
2453 if ( req->type != FT_SIZE_REQUEST_TYPE_NOMINAL )
2454 return FT_Err_Unimplemented_Feature;
2455
Werner Lemberg9cc4aed2006-01-26 21:03:58 +00002456 w = FT_REQUEST_WIDTH ( req );
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002457 h = FT_REQUEST_HEIGHT( req );
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002458
2459 if ( req->width && !req->height )
2460 h = w;
2461 else if ( !req->width && req->height )
2462 w = h;
2463
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002464 w = FT_PIX_ROUND( w );
2465 h = FT_PIX_ROUND( h );
2466
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002467 for ( i = 0; i < face->num_fixed_sizes; i++ )
2468 {
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002469 FT_Bitmap_Size* bsize = face->available_sizes + i;
2470
2471
2472 if ( h != FT_PIX_ROUND( bsize->y_ppem ) )
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002473 continue;
2474
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002475 if ( w == FT_PIX_ROUND( bsize->x_ppem ) || ignore_width )
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002476 {
Werner Lemberg8c4120d2007-01-15 06:42:40 +00002477 if ( size_index )
2478 *size_index = (FT_ULong)i;
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002479
2480 return FT_Err_Ok;
2481 }
2482 }
2483
2484 return FT_Err_Invalid_Pixel_Size;
2485 }
2486
2487
Wu, Chia-I (吳佳一)212aee02006-01-15 06:24:53 +00002488 /* documentation is in ftobjs.h */
2489
2490 FT_BASE_DEF( void )
Wu, Chia-I (吳佳一)ea1e8d32006-01-15 15:01:45 +00002491 ft_synthesize_vertical_metrics( FT_Glyph_Metrics* metrics,
2492 FT_Pos advance )
Wu, Chia-I (吳佳一)212aee02006-01-15 06:24:53 +00002493 {
Bram Tassyns4694ea22009-09-02 13:06:33 +02002494 FT_Pos height = metrics->height;
2495
2496
2497 /* compensate for glyph with bbox above/below the baseline */
2498 if ( metrics->horiBearingY < 0 )
2499 {
2500 if ( height < metrics->horiBearingY )
2501 height = metrics->horiBearingY;
2502 }
2503 else if ( metrics->horiBearingY > 0 )
2504 height -= metrics->horiBearingY;
2505
Werner Lemberg1723dcc2006-01-15 07:30:32 +00002506 /* the factor 1.2 is a heuristical value */
Wu, Chia-I (吳佳一)212aee02006-01-15 06:24:53 +00002507 if ( !advance )
Bram Tassyns4694ea22009-09-02 13:06:33 +02002508 advance = height * 12 / 10;
Wu, Chia-I (吳佳一)212aee02006-01-15 06:24:53 +00002509
Bram Tassyns4694ea22009-09-02 13:06:33 +02002510 metrics->vertBearingX = metrics->horiBearingX - metrics->horiAdvance / 2;
2511 metrics->vertBearingY = ( advance - height ) / 2;
Wu, Chia-I (吳佳一)212aee02006-01-15 06:24:53 +00002512 metrics->vertAdvance = advance;
2513 }
2514
2515
Werner Lembergf814d0f2001-06-27 16:18:10 +00002516 static void
2517 ft_recompute_scaled_metrics( FT_Face face,
2518 FT_Size_Metrics* metrics )
Werner Lembergdeb4e982000-06-29 03:14:25 +00002519 {
Werner Lemberga929ba92000-06-25 06:47:11 +00002520 /* Compute root ascender, descender, test height, and max_advance */
Werner Lembergdeb4e982000-06-29 03:14:25 +00002521
Wu, Chia-I (吳佳一)2e48a1a2006-02-27 09:18:07 +00002522#ifdef GRID_FIT_METRICS
David Turnerb4636652006-02-26 07:57:45 +00002523 metrics->ascender = FT_PIX_CEIL( FT_MulFix( face->ascender,
2524 metrics->y_scale ) );
2525
2526 metrics->descender = FT_PIX_FLOOR( FT_MulFix( face->descender,
2527 metrics->y_scale ) );
2528
2529 metrics->height = FT_PIX_ROUND( FT_MulFix( face->height,
2530 metrics->y_scale ) );
2531
2532 metrics->max_advance = FT_PIX_ROUND( FT_MulFix( face->max_advance_width,
2533 metrics->x_scale ) );
Wu, Chia-I (吳佳一)2e48a1a2006-02-27 09:18:07 +00002534#else /* !GRID_FIT_METRICS */
Wu, Chia-I (吳佳一)dcb8b712005-12-16 14:27:14 +00002535 metrics->ascender = FT_MulFix( face->ascender,
2536 metrics->y_scale );
Werner Lemberga929ba92000-06-25 06:47:11 +00002537
Wu, Chia-I (吳佳一)dcb8b712005-12-16 14:27:14 +00002538 metrics->descender = FT_MulFix( face->descender,
2539 metrics->y_scale );
Werner Lemberga929ba92000-06-25 06:47:11 +00002540
Wu, Chia-I (吳佳一)dcb8b712005-12-16 14:27:14 +00002541 metrics->height = FT_MulFix( face->height,
2542 metrics->y_scale );
Werner Lemberga929ba92000-06-25 06:47:11 +00002543
Wu, Chia-I (吳佳一)dcb8b712005-12-16 14:27:14 +00002544 metrics->max_advance = FT_MulFix( face->max_advance_width,
2545 metrics->x_scale );
Wu, Chia-I (吳佳一)2e48a1a2006-02-27 09:18:07 +00002546#endif /* !GRID_FIT_METRICS */
Werner Lemberga929ba92000-06-25 06:47:11 +00002547 }
2548
2549
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002550 FT_BASE_DEF( void )
2551 FT_Select_Metrics( FT_Face face,
2552 FT_ULong strike_index )
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002553 {
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002554 FT_Size_Metrics* metrics;
2555 FT_Bitmap_Size* bsize;
2556
2557
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002558 metrics = &face->size->metrics;
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002559 bsize = face->available_sizes + strike_index;
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002560
Werner Lembergbe3c9812006-01-27 14:16:16 +00002561 metrics->x_ppem = (FT_UShort)( ( bsize->x_ppem + 32 ) >> 6 );
2562 metrics->y_ppem = (FT_UShort)( ( bsize->y_ppem + 32 ) >> 6 );
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002563
2564 if ( FT_IS_SCALABLE( face ) )
2565 {
2566 metrics->x_scale = FT_DivFix( bsize->x_ppem,
2567 face->units_per_EM );
2568 metrics->y_scale = FT_DivFix( bsize->y_ppem,
2569 face->units_per_EM );
2570
2571 ft_recompute_scaled_metrics( face, metrics );
2572 }
2573 else
2574 {
Werner Lemberg14de1112009-02-24 21:34:51 +00002575 metrics->x_scale = 1L << 16;
2576 metrics->y_scale = 1L << 16;
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002577 metrics->ascender = bsize->y_ppem;
2578 metrics->descender = 0;
2579 metrics->height = bsize->height << 6;
2580 metrics->max_advance = bsize->x_ppem;
2581 }
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002582 }
2583
2584
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002585 FT_BASE_DEF( void )
2586 FT_Request_Metrics( FT_Face face,
2587 FT_Size_Request req )
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002588 {
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002589 FT_Size_Metrics* metrics;
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002590
2591
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002592 metrics = &face->size->metrics;
2593
2594 if ( FT_IS_SCALABLE( face ) )
2595 {
Werner Lembergce280a22007-06-03 05:58:30 +00002596 FT_Long w = 0, h = 0, scaled_w = 0, scaled_h = 0;
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002597
2598
2599 switch ( req->type )
2600 {
2601 case FT_SIZE_REQUEST_TYPE_NOMINAL:
2602 w = h = face->units_per_EM;
2603 break;
Werner Lembergf1c2b912006-01-13 14:53:28 +00002604
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002605 case FT_SIZE_REQUEST_TYPE_REAL_DIM:
2606 w = h = face->ascender - face->descender;
2607 break;
Werner Lembergf1c2b912006-01-13 14:53:28 +00002608
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002609 case FT_SIZE_REQUEST_TYPE_BBOX:
2610 w = face->bbox.xMax - face->bbox.xMin;
2611 h = face->bbox.yMax - face->bbox.yMin;
2612 break;
Werner Lembergf1c2b912006-01-13 14:53:28 +00002613
Werner Lembergb9933f42007-06-01 21:27:12 +00002614 case FT_SIZE_REQUEST_TYPE_CELL:
2615 w = face->max_advance_width;
2616 h = face->ascender - face->descender;
2617 break;
2618
Wu, Chia-I (吳佳一)a8e7a012006-02-24 06:11:30 +00002619 case FT_SIZE_REQUEST_TYPE_SCALES:
2620 metrics->x_scale = (FT_Fixed)req->width;
2621 metrics->y_scale = (FT_Fixed)req->height;
2622 if ( !metrics->x_scale )
2623 metrics->x_scale = metrics->y_scale;
2624 else if ( !metrics->y_scale )
2625 metrics->y_scale = metrics->x_scale;
2626 goto Calculate_Ppem;
Wu, Chia-I (吳佳一)a8e7a012006-02-24 06:11:30 +00002627
Werner Lembergb9933f42007-06-01 21:27:12 +00002628 case FT_SIZE_REQUEST_TYPE_MAX:
2629 break;
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002630 }
2631
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002632 /* to be on the safe side */
Wu, Chia-I (吳佳一)e5ff0592006-01-15 06:00:49 +00002633 if ( w < 0 )
2634 w = -w;
2635
2636 if ( h < 0 )
2637 h = -h;
2638
Werner Lemberg9cc4aed2006-01-26 21:03:58 +00002639 scaled_w = FT_REQUEST_WIDTH ( req );
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002640 scaled_h = FT_REQUEST_HEIGHT( req );
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002641
2642 /* determine scales */
2643 if ( req->width )
2644 {
2645 metrics->x_scale = FT_DivFix( scaled_w, w );
2646
2647 if ( req->height )
2648 {
2649 metrics->y_scale = FT_DivFix( scaled_h, h );
2650
2651 if ( req->type == FT_SIZE_REQUEST_TYPE_CELL )
2652 {
2653 if ( metrics->y_scale > metrics->x_scale )
2654 metrics->y_scale = metrics->x_scale;
2655 else
2656 metrics->x_scale = metrics->y_scale;
2657 }
2658 }
2659 else
2660 {
2661 metrics->y_scale = metrics->x_scale;
2662 scaled_h = FT_MulDiv( scaled_w, h, w );
2663 }
2664 }
2665 else
2666 {
2667 metrics->x_scale = metrics->y_scale = FT_DivFix( scaled_h, h );
2668 scaled_w = FT_MulDiv( scaled_h, w, h );
2669 }
2670
Wu, Chia-I (吳佳一)a8e7a012006-02-24 06:11:30 +00002671 Calculate_Ppem:
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002672 /* calculate the ppems */
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002673 if ( req->type != FT_SIZE_REQUEST_TYPE_NOMINAL )
2674 {
2675 scaled_w = FT_MulFix( face->units_per_EM, metrics->x_scale );
2676 scaled_h = FT_MulFix( face->units_per_EM, metrics->y_scale );
2677 }
2678
Werner Lembergbe3c9812006-01-27 14:16:16 +00002679 metrics->x_ppem = (FT_UShort)( ( scaled_w + 32 ) >> 6 );
2680 metrics->y_ppem = (FT_UShort)( ( scaled_h + 32 ) >> 6 );
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002681
2682 ft_recompute_scaled_metrics( face, metrics );
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002683 }
2684 else
2685 {
2686 FT_ZERO( metrics );
Werner Lemberg14de1112009-02-24 21:34:51 +00002687 metrics->x_scale = 1L << 16;
2688 metrics->y_scale = 1L << 16;
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002689 }
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002690 }
2691
2692
2693 /* documentation is in freetype.h */
2694
2695 FT_EXPORT_DEF( FT_Error )
2696 FT_Select_Size( FT_Face face,
2697 FT_Int strike_index )
2698 {
Werner Lemberg9cc4aed2006-01-26 21:03:58 +00002699 FT_Driver_Class clazz;
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002700
2701
2702 if ( !face || !FT_HAS_FIXED_SIZES( face ) )
2703 return FT_Err_Invalid_Face_Handle;
2704
2705 if ( strike_index < 0 || strike_index >= face->num_fixed_sizes )
2706 return FT_Err_Invalid_Argument;
2707
2708 clazz = face->driver->clazz;
2709
2710 if ( clazz->select_size )
2711 return clazz->select_size( face->size, (FT_ULong)strike_index );
2712
2713 FT_Select_Metrics( face, (FT_ULong)strike_index );
2714
2715 return FT_Err_Ok;
2716 }
2717
2718
2719 /* documentation is in freetype.h */
2720
2721 FT_EXPORT_DEF( FT_Error )
2722 FT_Request_Size( FT_Face face,
2723 FT_Size_Request req )
2724 {
Werner Lemberg9cc4aed2006-01-26 21:03:58 +00002725 FT_Driver_Class clazz;
2726 FT_ULong strike_index;
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002727
2728
2729 if ( !face )
2730 return FT_Err_Invalid_Face_Handle;
2731
2732 if ( !req || req->width < 0 || req->height < 0 ||
2733 req->type >= FT_SIZE_REQUEST_TYPE_MAX )
2734 return FT_Err_Invalid_Argument;
2735
2736 clazz = face->driver->clazz;
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002737
2738 if ( clazz->request_size )
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002739 return clazz->request_size( face->size, req );
2740
Wu, Chia-I (吳佳一)e33dc2e2006-01-14 05:09:30 +00002741 /*
Werner Lemberg3d8eeb82006-01-14 07:10:45 +00002742 * The reason that a driver doesn't have `request_size' defined is
2743 * either that the scaling here suffices or that the supported formats
2744 * are bitmap-only and size matching is not implemented.
Wu, Chia-I (吳佳一)e33dc2e2006-01-14 05:09:30 +00002745 *
2746 * In the latter case, a simple size matching is done.
2747 */
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002748 if ( !FT_IS_SCALABLE( face ) && FT_HAS_FIXED_SIZES( face ) )
Wu, Chia-I (吳佳一)e33dc2e2006-01-14 05:09:30 +00002749 {
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002750 FT_Error error;
Wu, Chia-I (吳佳一)e33dc2e2006-01-14 05:09:30 +00002751
2752
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002753 error = FT_Match_Size( face, req, 0, &strike_index );
2754 if ( error )
2755 return error;
Wu, Chia-I (吳佳一)e33dc2e2006-01-14 05:09:30 +00002756
Werner Lemberg9cc4aed2006-01-26 21:03:58 +00002757 FT_TRACE3(( "FT_Request_Size: bitmap strike %lu matched\n",
2758 strike_index ));
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002759
2760 return FT_Select_Size( face, (FT_Int)strike_index );
Wu, Chia-I (吳佳一)e33dc2e2006-01-14 05:09:30 +00002761 }
2762
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002763 FT_Request_Metrics( face, req );
2764
2765 return FT_Err_Ok;
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002766 }
2767
2768
2769 /* documentation is in freetype.h */
2770
2771 FT_EXPORT_DEF( FT_Error )
Werner Lembergf814d0f2001-06-27 16:18:10 +00002772 FT_Set_Char_Size( FT_Face face,
2773 FT_F26Dot6 char_width,
2774 FT_F26Dot6 char_height,
2775 FT_UInt horz_resolution,
2776 FT_UInt vert_resolution )
David Turnerd2b1f351999-12-16 23:11:37 +00002777 {
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002778 FT_Size_RequestRec req;
David Turnerd2b1f351999-12-16 23:11:37 +00002779
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00002780
Wu, Chia-I (吳佳一)cffa8b62006-02-27 11:11:40 +00002781 if ( !char_width )
2782 char_width = char_height;
2783 else if ( !char_height )
2784 char_height = char_width;
2785
Werner Lemberg74781972007-04-03 19:39:28 +00002786 if ( !horz_resolution )
David Turner7338ec22007-04-03 14:30:34 +00002787 horz_resolution = vert_resolution;
Werner Lemberg74781972007-04-03 19:39:28 +00002788 else if ( !vert_resolution )
David Turner7338ec22007-04-03 14:30:34 +00002789 vert_resolution = horz_resolution;
2790
Wu, Chia-I (吳佳一)2e48a1a2006-02-27 09:18:07 +00002791 if ( char_width < 1 * 64 )
2792 char_width = 1 * 64;
2793 if ( char_height < 1 * 64 )
2794 char_height = 1 * 64;
2795
Werner Lemberg106eaf12007-05-03 07:07:47 +00002796 if ( !horz_resolution )
2797 horz_resolution = vert_resolution = 72;
2798
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002799 req.type = FT_SIZE_REQUEST_TYPE_NOMINAL;
2800 req.width = char_width;
2801 req.height = char_height;
Werner Lemberg106eaf12007-05-03 07:07:47 +00002802 req.horiResolution = horz_resolution;
2803 req.vertResolution = vert_resolution;
David Turnerd2b1f351999-12-16 23:11:37 +00002804
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002805 return FT_Request_Size( face, &req );
David Turnerd2b1f351999-12-16 23:11:37 +00002806 }
2807
2808
Werner Lemberg90a03302000-11-07 17:21:11 +00002809 /* documentation is in freetype.h */
2810
Werner Lembergf814d0f2001-06-27 16:18:10 +00002811 FT_EXPORT_DEF( FT_Error )
2812 FT_Set_Pixel_Sizes( FT_Face face,
2813 FT_UInt pixel_width,
2814 FT_UInt pixel_height )
David Turnerd2b1f351999-12-16 23:11:37 +00002815 {
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002816 FT_Size_RequestRec req;
David Turnerd2b1f351999-12-16 23:11:37 +00002817
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00002818
Wu, Chia-I (吳佳一)2e48a1a2006-02-27 09:18:07 +00002819 if ( pixel_width == 0 )
2820 pixel_width = pixel_height;
2821 else if ( pixel_height == 0 )
2822 pixel_height = pixel_width;
2823
2824 if ( pixel_width < 1 )
2825 pixel_width = 1;
2826 if ( pixel_height < 1 )
2827 pixel_height = 1;
2828
Werner Lemberg6e87ed92007-01-26 22:18:56 +00002829 /* use `>=' to avoid potential compiler warning on 16bit platforms */
Wu, Chia-I (吳佳一)2e48a1a2006-02-27 09:18:07 +00002830 if ( pixel_width >= 0xFFFFU )
2831 pixel_width = 0xFFFFU;
2832 if ( pixel_height >= 0xFFFFU )
2833 pixel_height = 0xFFFFU;
2834
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002835 req.type = FT_SIZE_REQUEST_TYPE_NOMINAL;
2836 req.width = pixel_width << 6;
2837 req.height = pixel_height << 6;
2838 req.horiResolution = 0;
2839 req.vertResolution = 0;
David Turnerd2b1f351999-12-16 23:11:37 +00002840
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002841 return FT_Request_Size( face, &req );
David Turnerd2b1f351999-12-16 23:11:37 +00002842 }
2843
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00002844
Werner Lemberg90a03302000-11-07 17:21:11 +00002845 /* documentation is in freetype.h */
2846
Werner Lembergf814d0f2001-06-27 16:18:10 +00002847 FT_EXPORT_DEF( FT_Error )
2848 FT_Get_Kerning( FT_Face face,
2849 FT_UInt left_glyph,
2850 FT_UInt right_glyph,
2851 FT_UInt kern_mode,
2852 FT_Vector *akerning )
David Turnerd2b1f351999-12-16 23:11:37 +00002853 {
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00002854 FT_Error error = FT_Err_Ok;
David Turnerd2b1f351999-12-16 23:11:37 +00002855 FT_Driver driver;
David Turnerd2b1f351999-12-16 23:11:37 +00002856
Werner Lemberga8bbc262000-07-01 14:06:46 +00002857
David Turnerd2b1f351999-12-16 23:11:37 +00002858 if ( !face )
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00002859 return FT_Err_Invalid_Face_Handle;
2860
Werner Lemberg4b680072000-11-07 06:30:29 +00002861 if ( !akerning )
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00002862 return FT_Err_Invalid_Argument;
David Turnerd2b1f351999-12-16 23:11:37 +00002863
2864 driver = face->driver;
David Turnerd2b1f351999-12-16 23:11:37 +00002865
Werner Lemberg4b680072000-11-07 06:30:29 +00002866 akerning->x = 0;
2867 akerning->y = 0;
Werner Lemberg5aa646c2000-07-14 06:16:47 +00002868
David Turnerf0df85b2000-06-22 00:17:42 +00002869 if ( driver->clazz->get_kerning )
David Turnerd2b1f351999-12-16 23:11:37 +00002870 {
David Turnerf0df85b2000-06-22 00:17:42 +00002871 error = driver->clazz->get_kerning( face,
Werner Lemberga929ba92000-06-25 06:47:11 +00002872 left_glyph,
2873 right_glyph,
Werner Lemberg4b680072000-11-07 06:30:29 +00002874 akerning );
Werner Lemberg5aa646c2000-07-14 06:16:47 +00002875 if ( !error )
David Turnerf9ca2bb2000-06-30 23:12:55 +00002876 {
David Turnerb08fe2d2002-08-27 20:20:29 +00002877 if ( kern_mode != FT_KERNING_UNSCALED )
David Turnerf9ca2bb2000-06-30 23:12:55 +00002878 {
Werner Lemberg4b680072000-11-07 06:30:29 +00002879 akerning->x = FT_MulFix( akerning->x, face->size->metrics.x_scale );
2880 akerning->y = FT_MulFix( akerning->y, face->size->metrics.y_scale );
Werner Lemberg5aa646c2000-07-14 06:16:47 +00002881
David Turnerb08fe2d2002-08-27 20:20:29 +00002882 if ( kern_mode != FT_KERNING_UNFITTED )
Werner Lemberg5aa646c2000-07-14 06:16:47 +00002883 {
Werner Lemberg133eee02004-12-12 06:55:40 +00002884 /* we scale down kerning values for small ppem values */
2885 /* to avoid that rounding makes them too big. */
2886 /* `25' has been determined heuristically. */
2887 if ( face->size->metrics.x_ppem < 25 )
2888 akerning->x = FT_MulDiv( akerning->x,
2889 face->size->metrics.x_ppem, 25 );
2890 if ( face->size->metrics.y_ppem < 25 )
2891 akerning->y = FT_MulDiv( akerning->y,
2892 face->size->metrics.y_ppem, 25 );
2893
2894 akerning->x = FT_PIX_ROUND( akerning->x );
2895 akerning->y = FT_PIX_ROUND( akerning->y );
Werner Lemberg5aa646c2000-07-14 06:16:47 +00002896 }
David Turnerf9ca2bb2000-06-30 23:12:55 +00002897 }
2898 }
2899 }
David Turnerd2b1f351999-12-16 23:11:37 +00002900
David Turnerd2b1f351999-12-16 23:11:37 +00002901 return error;
2902 }
2903
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00002904
Werner Lemberg90a03302000-11-07 17:21:11 +00002905 /* documentation is in freetype.h */
2906
Werner Lembergf814d0f2001-06-27 16:18:10 +00002907 FT_EXPORT_DEF( FT_Error )
Wu, Chia-I (吳佳一)108fdbb2006-01-16 15:35:56 +00002908 FT_Get_Track_Kerning( FT_Face face,
2909 FT_Fixed point_size,
2910 FT_Int degree,
2911 FT_Fixed* akerning )
2912 {
2913 FT_Service_Kerning service;
2914 FT_Error error = FT_Err_Ok;
Wu, Chia-I (吳佳一)108fdbb2006-01-16 15:35:56 +00002915
2916
2917 if ( !face )
2918 return FT_Err_Invalid_Face_Handle;
2919
2920 if ( !akerning )
2921 return FT_Err_Invalid_Argument;
2922
Wu, Chia-I (吳佳一)108fdbb2006-01-16 15:35:56 +00002923 FT_FACE_FIND_SERVICE( face, service, KERNING );
2924 if ( !service )
2925 return FT_Err_Unimplemented_Feature;
2926
2927 error = service->get_track( face,
2928 point_size,
2929 degree,
2930 akerning );
2931
2932 return error;
2933 }
2934
2935
2936 /* documentation is in freetype.h */
2937
2938 FT_EXPORT_DEF( FT_Error )
Werner Lembergf814d0f2001-06-27 16:18:10 +00002939 FT_Select_Charmap( FT_Face face,
2940 FT_Encoding encoding )
David Turner0a29c692000-05-12 17:09:38 +00002941 {
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00002942 FT_CharMap* cur;
2943 FT_CharMap* limit;
David Turnere49ab252000-05-16 23:44:38 +00002944
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00002945
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00002946 if ( !face )
2947 return FT_Err_Invalid_Face_Handle;
2948
Werner Lemberge88c5262006-10-24 05:46:26 +00002949 if ( encoding == FT_ENCODING_NONE )
2950 return FT_Err_Invalid_Argument;
2951
Werner Lembergc8c6bf52003-04-23 05:38:13 +00002952 /* FT_ENCODING_UNICODE is special. We try to find the `best' Unicode */
2953 /* charmap available, i.e., one with UCS-4 characters, if possible. */
2954 /* */
2955 /* This is done by find_unicode_charmap() above, to share code. */
Antoine Lecac96f69d2002-12-03 00:39:16 +00002956 if ( encoding == FT_ENCODING_UNICODE )
2957 return find_unicode_charmap( face );
2958
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00002959 cur = face->charmaps;
2960 if ( !cur )
2961 return FT_Err_Invalid_CharMap_Handle;
2962
2963 limit = cur + face->num_charmaps;
2964
David Turner0a29c692000-05-12 17:09:38 +00002965 for ( ; cur < limit; cur++ )
2966 {
2967 if ( cur[0]->encoding == encoding )
2968 {
suzuki toshiya0ae32712010-07-04 20:14:18 +09002969#ifdef FT_MAX_CHARMAP_CACHEABLE
2970 if ( cur - face->charmaps > FT_MAX_CHARMAP_CACHEABLE )
2971 {
2972 FT_ERROR(( "FT_Select_Charmap: requested charmap is found (%d), "
2973 "but in too late position to cache\n",
2974 cur - face->charmaps ));
2975 continue;
2976 }
2977#endif
David Turner0a29c692000-05-12 17:09:38 +00002978 face->charmap = cur[0];
2979 return 0;
2980 }
2981 }
Werner Lembergdeb4e982000-06-29 03:14:25 +00002982
David Turner0a29c692000-05-12 17:09:38 +00002983 return FT_Err_Invalid_Argument;
2984 }
2985
2986
Werner Lemberg90a03302000-11-07 17:21:11 +00002987 /* documentation is in freetype.h */
2988
Werner Lembergf814d0f2001-06-27 16:18:10 +00002989 FT_EXPORT_DEF( FT_Error )
2990 FT_Set_Charmap( FT_Face face,
2991 FT_CharMap charmap )
David Turner0a29c692000-05-12 17:09:38 +00002992 {
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00002993 FT_CharMap* cur;
2994 FT_CharMap* limit;
David Turnere49ab252000-05-16 23:44:38 +00002995
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00002996
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00002997 if ( !face )
2998 return FT_Err_Invalid_Face_Handle;
2999
3000 cur = face->charmaps;
3001 if ( !cur )
3002 return FT_Err_Invalid_CharMap_Handle;
Werner Lemberg9a966b72007-10-15 17:21:32 +00003003 if ( FT_Get_CMap_Format( charmap ) == 14 )
3004 return FT_Err_Invalid_Argument;
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00003005
3006 limit = cur + face->num_charmaps;
3007
David Turner0a29c692000-05-12 17:09:38 +00003008 for ( ; cur < limit; cur++ )
3009 {
3010 if ( cur[0] == charmap )
3011 {
suzuki toshiya0ae32712010-07-04 20:14:18 +09003012#ifdef FT_MAX_CHARMAP_CACHEABLE
3013 if ( cur - face->charmaps > FT_MAX_CHARMAP_CACHEABLE )
3014 {
3015 FT_ERROR(( "FT_Set_Charmap: requested charmap is found (%d), "
3016 "but in too late position to cache\n",
3017 cur - face->charmaps ));
3018 continue;
3019 }
3020#endif
David Turner0a29c692000-05-12 17:09:38 +00003021 face->charmap = cur[0];
3022 return 0;
3023 }
3024 }
3025 return FT_Err_Invalid_Argument;
3026 }
David Turnerd2b1f351999-12-16 23:11:37 +00003027
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00003028
Werner Lemberge95365b2004-04-24 14:43:37 +00003029 /* documentation is in freetype.h */
3030
3031 FT_EXPORT_DEF( FT_Int )
3032 FT_Get_Charmap_Index( FT_CharMap charmap )
3033 {
3034 FT_Int i;
3035
3036
Werner Lemberge30de292010-05-22 20:03:41 +02003037 if ( !charmap || !charmap->face )
3038 return -1;
3039
Werner Lemberge95365b2004-04-24 14:43:37 +00003040 for ( i = 0; i < charmap->face->num_charmaps; i++ )
3041 if ( charmap->face->charmaps[i] == charmap )
3042 break;
3043
3044 FT_ASSERT( i < charmap->face->num_charmaps );
3045
suzuki toshiya0ae32712010-07-04 20:14:18 +09003046#ifdef FT_MAX_CHARMAP_CACHEABLE
3047 if ( i > FT_MAX_CHARMAP_CACHEABLE )
3048 {
3049 FT_ERROR(( "FT_Get_Charmap_Index: requested charmap is found (%d), "
3050 "but in too late position to cache\n",
3051 i ));
3052 return -i;
3053 }
3054#endif
Werner Lemberge95365b2004-04-24 14:43:37 +00003055 return i;
3056 }
3057
3058
Werner Lemberge70371c2005-05-27 06:01:28 +00003059 static void
3060 ft_cmap_done_internal( FT_CMap cmap )
3061 {
3062 FT_CMap_Class clazz = cmap->clazz;
3063 FT_Face face = cmap->charmap.face;
3064 FT_Memory memory = FT_FACE_MEMORY(face);
3065
3066
3067 if ( clazz->done )
3068 clazz->done( cmap );
3069
3070 FT_FREE( cmap );
3071 }
3072
3073
David Turner4e7eeee2002-02-28 16:10:29 +00003074 FT_BASE_DEF( void )
3075 FT_CMap_Done( FT_CMap cmap )
3076 {
3077 if ( cmap )
3078 {
Werner Lemberge70371c2005-05-27 06:01:28 +00003079 FT_Face face = cmap->charmap.face;
3080 FT_Memory memory = FT_FACE_MEMORY( face );
3081 FT_Error error;
3082 FT_Int i, j;
David Turnerbc82f1b2002-03-01 02:26:22 +00003083
Werner Lembergf8ba2002002-03-30 13:16:35 +00003084
Werner Lemberge70371c2005-05-27 06:01:28 +00003085 for ( i = 0; i < face->num_charmaps; i++ )
3086 {
3087 if ( (FT_CMap)face->charmaps[i] == cmap )
3088 {
3089 FT_CharMap last_charmap = face->charmaps[face->num_charmaps - 1];
David Turner4e7eeee2002-02-28 16:10:29 +00003090
Werner Lemberge70371c2005-05-27 06:01:28 +00003091
3092 if ( FT_RENEW_ARRAY( face->charmaps,
3093 face->num_charmaps,
3094 face->num_charmaps - 1 ) )
3095 return;
3096
3097 /* remove it from our list of charmaps */
3098 for ( j = i + 1; j < face->num_charmaps; j++ )
3099 {
3100 if ( j == face->num_charmaps - 1 )
3101 face->charmaps[j - 1] = last_charmap;
3102 else
3103 face->charmaps[j - 1] = face->charmaps[j];
3104 }
3105
3106 face->num_charmaps--;
3107
3108 if ( (FT_CMap)face->charmap == cmap )
3109 face->charmap = NULL;
3110
3111 ft_cmap_done_internal( cmap );
3112
3113 break;
3114 }
3115 }
David Turner4e7eeee2002-02-28 16:10:29 +00003116 }
3117 }
3118
3119
3120 FT_BASE_DEF( FT_Error )
Werner Lemberg9cc4aed2006-01-26 21:03:58 +00003121 FT_CMap_New( FT_CMap_Class clazz,
3122 FT_Pointer init_data,
3123 FT_CharMap charmap,
3124 FT_CMap *acmap )
David Turnerbc82f1b2002-03-01 02:26:22 +00003125 {
Werner Lemberg8acb8672005-03-08 11:43:36 +00003126 FT_Error error = FT_Err_Ok;
David Turner4e7eeee2002-02-28 16:10:29 +00003127 FT_Face face;
3128 FT_Memory memory;
3129 FT_CMap cmap;
David Turnerbc82f1b2002-03-01 02:26:22 +00003130
Werner Lembergf8ba2002002-03-30 13:16:35 +00003131
David Turner4e7eeee2002-02-28 16:10:29 +00003132 if ( clazz == NULL || charmap == NULL || charmap->face == NULL )
3133 return FT_Err_Invalid_Argument;
3134
3135 face = charmap->face;
Werner Lembergf35ff802003-06-02 21:58:05 +00003136 memory = FT_FACE_MEMORY( face );
David Turner4e7eeee2002-02-28 16:10:29 +00003137
David Turnere459d742002-03-22 13:52:37 +00003138 if ( !FT_ALLOC( cmap, clazz->size ) )
David Turner4e7eeee2002-02-28 16:10:29 +00003139 {
3140 cmap->charmap = *charmap;
3141 cmap->clazz = clazz;
David Turnerbc82f1b2002-03-01 02:26:22 +00003142
David Turner4e7eeee2002-02-28 16:10:29 +00003143 if ( clazz->init )
3144 {
David Turnerbc82f1b2002-03-01 02:26:22 +00003145 error = clazz->init( cmap, init_data );
Werner Lembergf8ba2002002-03-30 13:16:35 +00003146 if ( error )
David Turner4e7eeee2002-02-28 16:10:29 +00003147 goto Fail;
3148 }
David Turnerbc82f1b2002-03-01 02:26:22 +00003149
David Turner4e7eeee2002-02-28 16:10:29 +00003150 /* add it to our list of charmaps */
David Turnere459d742002-03-22 13:52:37 +00003151 if ( FT_RENEW_ARRAY( face->charmaps,
3152 face->num_charmaps,
Werner Lemberg8acb8672005-03-08 11:43:36 +00003153 face->num_charmaps + 1 ) )
David Turner4e7eeee2002-02-28 16:10:29 +00003154 goto Fail;
David Turnerbc82f1b2002-03-01 02:26:22 +00003155
Werner Lembergf8ba2002002-03-30 13:16:35 +00003156 face->charmaps[face->num_charmaps++] = (FT_CharMap)cmap;
David Turner4e7eeee2002-02-28 16:10:29 +00003157 }
David Turnerbc82f1b2002-03-01 02:26:22 +00003158
David Turner4e7eeee2002-02-28 16:10:29 +00003159 Exit:
3160 if ( acmap )
3161 *acmap = cmap;
3162
3163 return error;
David Turnerbc82f1b2002-03-01 02:26:22 +00003164
David Turner4e7eeee2002-02-28 16:10:29 +00003165 Fail:
Werner Lemberge70371c2005-05-27 06:01:28 +00003166 ft_cmap_done_internal( cmap );
David Turner4e7eeee2002-02-28 16:10:29 +00003167 cmap = NULL;
3168 goto Exit;
David Turnerbc82f1b2002-03-01 02:26:22 +00003169 }
David Turner4e7eeee2002-02-28 16:10:29 +00003170
3171
Werner Lemberg90a03302000-11-07 17:21:11 +00003172 /* documentation is in freetype.h */
3173
Werner Lembergf814d0f2001-06-27 16:18:10 +00003174 FT_EXPORT_DEF( FT_UInt )
3175 FT_Get_Char_Index( FT_Face face,
3176 FT_ULong charcode )
David Turnerd2b1f351999-12-16 23:11:37 +00003177 {
David Turnered54f282002-03-22 17:09:52 +00003178 FT_UInt result = 0;
3179
3180
3181 if ( face && face->charmap )
3182 {
3183 FT_CMap cmap = FT_CMAP( face->charmap );
David Turner25a6e3a2002-06-10 23:03:35 +00003184
Werner Lembergf8ba2002002-03-30 13:16:35 +00003185
suzuki toshiya0d226c32009-08-01 00:30:24 +09003186 if ( charcode > 0xFFFFFFFFUL )
3187 {
3188 FT_TRACE1(( "FT_Get_Char_Index: too large charcode" ));
3189 FT_TRACE1(( " 0x%x is truncated\n", charcode ));
3190 }
3191 result = cmap->clazz->char_index( cmap, (FT_UInt32)charcode );
David Turnered54f282002-03-22 17:09:52 +00003192 }
Behdad Esfahbod2415cbf2010-02-26 23:48:53 +01003193 return result;
David Turnered54f282002-03-22 17:09:52 +00003194 }
3195
David Turnered54f282002-03-22 17:09:52 +00003196
Werner Lemberg0f7c2f12002-02-04 20:55:58 +00003197 /* documentation is in freetype.h */
3198
3199 FT_EXPORT_DEF( FT_ULong )
David Turner041889e2002-02-28 19:28:26 +00003200 FT_Get_First_Char( FT_Face face,
3201 FT_UInt *agindex )
Werner Lemberg0f7c2f12002-02-04 20:55:58 +00003202 {
Werner Lembergf8ba2002002-03-30 13:16:35 +00003203 FT_ULong result = 0;
3204 FT_UInt gindex = 0;
3205
David Turnerbc82f1b2002-03-01 02:26:22 +00003206
Werner Lembergd0871992010-06-07 08:46:01 +02003207 if ( face && face->charmap && face->num_glyphs )
David Turner041889e2002-02-28 19:28:26 +00003208 {
3209 gindex = FT_Get_Char_Index( face, 0 );
Behdad Esfahbod2415cbf2010-02-26 23:48:53 +01003210 if ( gindex == 0 || gindex >= (FT_UInt)face->num_glyphs )
Werner Lemberge0717d42010-02-27 08:10:11 +01003211 result = FT_Get_Next_Char( face, 0, &gindex );
David Turner041889e2002-02-28 19:28:26 +00003212 }
David Turnerbc82f1b2002-03-01 02:26:22 +00003213
Behdad Esfahbod2415cbf2010-02-26 23:48:53 +01003214 if ( agindex )
David Turner041889e2002-02-28 19:28:26 +00003215 *agindex = gindex;
David Turnerbc82f1b2002-03-01 02:26:22 +00003216
David Turner041889e2002-02-28 19:28:26 +00003217 return result;
3218 }
3219
David Turner041889e2002-02-28 19:28:26 +00003220
Werner Lemberg7b0cc662003-07-05 07:46:49 +00003221 /* documentation is in freetype.h */
David Turnered54f282002-03-22 17:09:52 +00003222
David Turnered54f282002-03-22 17:09:52 +00003223 FT_EXPORT_DEF( FT_ULong )
3224 FT_Get_Next_Char( FT_Face face,
3225 FT_ULong charcode,
3226 FT_UInt *agindex )
3227 {
Werner Lembergf8ba2002002-03-30 13:16:35 +00003228 FT_ULong result = 0;
3229 FT_UInt gindex = 0;
David Turnered54f282002-03-22 17:09:52 +00003230
3231
Werner Lembergd0871992010-06-07 08:46:01 +02003232 if ( face && face->charmap && face->num_glyphs )
David Turnered54f282002-03-22 17:09:52 +00003233 {
3234 FT_UInt32 code = (FT_UInt32)charcode;
3235 FT_CMap cmap = FT_CMAP( face->charmap );
3236
Werner Lembergf8ba2002002-03-30 13:16:35 +00003237
Behdad Esfahbod2415cbf2010-02-26 23:48:53 +01003238 do {
3239 gindex = cmap->clazz->char_next( cmap, &code );
3240 } while ( gindex >= (FT_UInt)face->num_glyphs );
3241
David Turnered54f282002-03-22 17:09:52 +00003242 result = ( gindex == 0 ) ? 0 : code;
3243 }
3244
3245 if ( agindex )
3246 *agindex = gindex;
3247
3248 return result;
3249 }
3250
David Turnered54f282002-03-22 17:09:52 +00003251
Werner Lemberg90a03302000-11-07 17:21:11 +00003252 /* documentation is in freetype.h */
3253
Tom Kacvinskyff2714f2001-08-08 10:58:08 +00003254 FT_EXPORT_DEF( FT_UInt )
David Turnercf432db2007-10-19 12:36:40 +00003255 FT_Face_GetCharVariantIndex( FT_Face face,
3256 FT_ULong charcode,
3257 FT_ULong variantSelector )
Werner Lemberg9a966b72007-10-15 17:21:32 +00003258 {
3259 FT_UInt result = 0;
3260
3261
3262 if ( face && face->charmap &&
3263 face->charmap->encoding == FT_ENCODING_UNICODE )
3264 {
3265 FT_CharMap charmap = find_variant_selector_charmap( face );
3266 FT_CMap ucmap = FT_CMAP( face->charmap );
3267
3268
3269 if ( charmap != NULL )
3270 {
3271 FT_CMap vcmap = FT_CMAP( charmap );
3272
3273
suzuki toshiya0d226c32009-08-01 00:30:24 +09003274 if ( charcode > 0xFFFFFFFFUL )
3275 {
3276 FT_TRACE1(( "FT_Get_Char_Index: too large charcode" ));
3277 FT_TRACE1(( " 0x%x is truncated\n", charcode ));
3278 }
3279 if ( variantSelector > 0xFFFFFFFFUL )
3280 {
3281 FT_TRACE1(( "FT_Get_Char_Index: too large variantSelector" ));
3282 FT_TRACE1(( " 0x%x is truncated\n", variantSelector ));
3283 }
3284
3285 result = vcmap->clazz->char_var_index( vcmap, ucmap,
3286 (FT_UInt32)charcode,
3287 (FT_UInt32)variantSelector );
Werner Lemberg9a966b72007-10-15 17:21:32 +00003288 }
3289 }
3290
3291 return result;
3292 }
3293
3294
3295 /* documentation is in freetype.h */
3296
3297 FT_EXPORT_DEF( FT_Int )
David Turnercf432db2007-10-19 12:36:40 +00003298 FT_Face_GetCharVariantIsDefault( FT_Face face,
3299 FT_ULong charcode,
3300 FT_ULong variantSelector )
Werner Lemberg9a966b72007-10-15 17:21:32 +00003301 {
3302 FT_Int result = -1;
3303
3304
3305 if ( face )
3306 {
3307 FT_CharMap charmap = find_variant_selector_charmap( face );
3308
3309
3310 if ( charmap != NULL )
3311 {
3312 FT_CMap vcmap = FT_CMAP( charmap );
3313
3314
suzuki toshiya0d226c32009-08-01 00:30:24 +09003315 if ( charcode > 0xFFFFFFFFUL )
3316 {
3317 FT_TRACE1(( "FT_Get_Char_Index: too large charcode" ));
3318 FT_TRACE1(( " 0x%x is truncated\n", charcode ));
3319 }
3320 if ( variantSelector > 0xFFFFFFFFUL )
3321 {
3322 FT_TRACE1(( "FT_Get_Char_Index: too large variantSelector" ));
3323 FT_TRACE1(( " 0x%x is truncated\n", variantSelector ));
3324 }
3325
3326 result = vcmap->clazz->char_var_default( vcmap,
3327 (FT_UInt32)charcode,
3328 (FT_UInt32)variantSelector );
Werner Lemberg9a966b72007-10-15 17:21:32 +00003329 }
3330 }
3331
3332 return result;
3333 }
3334
3335
3336 /* documentation is in freetype.h */
3337
3338 FT_EXPORT_DEF( FT_UInt32* )
David Turnercf432db2007-10-19 12:36:40 +00003339 FT_Face_GetVariantSelectors( FT_Face face )
Werner Lemberg9a966b72007-10-15 17:21:32 +00003340 {
3341 FT_UInt32 *result = NULL;
3342
3343
3344 if ( face )
3345 {
3346 FT_CharMap charmap = find_variant_selector_charmap( face );
3347
3348
3349 if ( charmap != NULL )
3350 {
3351 FT_CMap vcmap = FT_CMAP( charmap );
3352 FT_Memory memory = FT_FACE_MEMORY( face );
3353
3354
3355 result = vcmap->clazz->variant_list( vcmap, memory );
3356 }
3357 }
3358
3359 return result;
3360 }
3361
3362
3363 /* documentation is in freetype.h */
3364
3365 FT_EXPORT_DEF( FT_UInt32* )
David Turnercf432db2007-10-19 12:36:40 +00003366 FT_Face_GetVariantsOfChar( FT_Face face,
3367 FT_ULong charcode )
Werner Lemberg9a966b72007-10-15 17:21:32 +00003368 {
3369 FT_UInt32 *result = NULL;
3370
3371
3372 if ( face )
3373 {
3374 FT_CharMap charmap = find_variant_selector_charmap( face );
3375
3376
3377 if ( charmap != NULL )
3378 {
3379 FT_CMap vcmap = FT_CMAP( charmap );
3380 FT_Memory memory = FT_FACE_MEMORY( face );
3381
3382
suzuki toshiya0d226c32009-08-01 00:30:24 +09003383 if ( charcode > 0xFFFFFFFFUL )
3384 {
3385 FT_TRACE1(( "FT_Get_Char_Index: too large charcode" ));
3386 FT_TRACE1(( " 0x%x is truncated\n", charcode ));
3387 }
3388
3389 result = vcmap->clazz->charvariant_list( vcmap, memory,
3390 (FT_UInt32)charcode );
Werner Lemberg9a966b72007-10-15 17:21:32 +00003391 }
3392 }
3393 return result;
3394 }
3395
3396
3397 /* documentation is in freetype.h */
3398
3399 FT_EXPORT_DEF( FT_UInt32* )
David Turnercf432db2007-10-19 12:36:40 +00003400 FT_Face_GetCharsOfVariant( FT_Face face,
3401 FT_ULong variantSelector )
Werner Lemberg9a966b72007-10-15 17:21:32 +00003402 {
3403 FT_UInt32 *result = NULL;
3404
3405
3406 if ( face )
3407 {
3408 FT_CharMap charmap = find_variant_selector_charmap( face );
3409
3410
3411 if ( charmap != NULL )
3412 {
3413 FT_CMap vcmap = FT_CMAP( charmap );
3414 FT_Memory memory = FT_FACE_MEMORY( face );
3415
3416
suzuki toshiya0d226c32009-08-01 00:30:24 +09003417 if ( variantSelector > 0xFFFFFFFFUL )
3418 {
3419 FT_TRACE1(( "FT_Get_Char_Index: too large variantSelector" ));
3420 FT_TRACE1(( " 0x%x is truncated\n", variantSelector ));
3421 }
3422
Werner Lemberg9a966b72007-10-15 17:21:32 +00003423 result = vcmap->clazz->variantchar_list( vcmap, memory,
suzuki toshiya0d226c32009-08-01 00:30:24 +09003424 (FT_UInt32)variantSelector );
Werner Lemberg9a966b72007-10-15 17:21:32 +00003425 }
3426 }
3427
3428 return result;
3429 }
3430
3431
3432 /* documentation is in freetype.h */
3433
3434 FT_EXPORT_DEF( FT_UInt )
Tom Kacvinskyff2714f2001-08-08 10:58:08 +00003435 FT_Get_Name_Index( FT_Face face,
3436 FT_String* glyph_name )
3437 {
3438 FT_UInt result = 0;
3439
3440
3441 if ( face && FT_HAS_GLYPH_NAMES( face ) )
3442 {
David Turnerc313c502003-09-11 19:51:54 +00003443 FT_Service_GlyphDict service;
Tom Kacvinskyff2714f2001-08-08 10:58:08 +00003444
Werner Lemberg013efd12003-09-17 05:26:33 +00003445
Werner Lemberg46333a12003-09-17 19:20:02 +00003446 FT_FACE_LOOKUP_SERVICE( face,
David Turnere2d12842003-09-21 17:15:55 +00003447 service,
3448 GLYPH_DICT );
Werner Lemberg013efd12003-09-17 05:26:33 +00003449
David Turnerc313c502003-09-11 19:51:54 +00003450 if ( service && service->name_index )
3451 result = service->name_index( face, glyph_name );
Werner Lemberg013efd12003-09-17 05:26:33 +00003452 }
3453
Tom Kacvinskyff2714f2001-08-08 10:58:08 +00003454 return result;
3455 }
3456
Werner Lembergaef3fc82001-12-17 16:21:22 +00003457
Tom Kacvinskyff2714f2001-08-08 10:58:08 +00003458 /* documentation is in freetype.h */
3459
Werner Lembergf814d0f2001-06-27 16:18:10 +00003460 FT_EXPORT_DEF( FT_Error )
3461 FT_Get_Glyph_Name( FT_Face face,
3462 FT_UInt glyph_index,
3463 FT_Pointer buffer,
3464 FT_UInt buffer_max )
David Turner6930b452000-07-19 17:13:03 +00003465 {
3466 FT_Error error = FT_Err_Invalid_Argument;
Werner Lembergeddd9902000-10-12 05:05:40 +00003467
Werner Lembergd060a752000-07-20 06:57:41 +00003468
David Turner6930b452000-07-19 17:13:03 +00003469 /* clean up buffer */
Werner Lembergd060a752000-07-20 06:57:41 +00003470 if ( buffer && buffer_max > 0 )
David Turner6930b452000-07-19 17:13:03 +00003471 ((FT_Byte*)buffer)[0] = 0;
Werner Lembergeddd9902000-10-12 05:05:40 +00003472
Werner Lembergfd97d132002-06-16 01:14:16 +00003473 if ( face &&
suzuki toshiya95aeebf2009-08-01 00:30:13 +09003474 (FT_Long)glyph_index <= face->num_glyphs &&
Werner Lembergfd97d132002-06-16 01:14:16 +00003475 FT_HAS_GLYPH_NAMES( face ) )
David Turner6930b452000-07-19 17:13:03 +00003476 {
David Turnerc313c502003-09-11 19:51:54 +00003477 FT_Service_GlyphDict service;
David Turner6930b452000-07-19 17:13:03 +00003478
Werner Lemberg013efd12003-09-17 05:26:33 +00003479
Werner Lemberg46333a12003-09-17 19:20:02 +00003480 FT_FACE_LOOKUP_SERVICE( face,
David Turnere2d12842003-09-21 17:15:55 +00003481 service,
3482 GLYPH_DICT );
Werner Lembergd060a752000-07-20 06:57:41 +00003483
David Turnerc313c502003-09-11 19:51:54 +00003484 if ( service && service->get_name )
David Turnerc313c502003-09-11 19:51:54 +00003485 error = service->get_name( face, glyph_index, buffer, buffer_max );
David Turner6930b452000-07-19 17:13:03 +00003486 }
Werner Lembergd060a752000-07-20 06:57:41 +00003487
David Turner6930b452000-07-19 17:13:03 +00003488 return error;
Werner Lembergeddd9902000-10-12 05:05:40 +00003489 }
David Turner6930b452000-07-19 17:13:03 +00003490
3491
David Turner23bcde12001-10-17 13:48:10 +00003492 /* documentation is in freetype.h */
3493
3494 FT_EXPORT_DEF( const char* )
3495 FT_Get_Postscript_Name( FT_Face face )
3496 {
3497 const char* result = NULL;
Werner Lemberg1a0a9792002-01-03 22:06:13 +00003498
Werner Lembergc3b21602001-12-05 01:22:05 +00003499
David Turner23bcde12001-10-17 13:48:10 +00003500 if ( !face )
3501 goto Exit;
3502
David Turner23bcde12001-10-17 13:48:10 +00003503 if ( !result )
3504 {
David Turnerb72d8a82003-09-29 20:33:37 +00003505 FT_Service_PsFontName service;
Werner Lembergc3b21602001-12-05 01:22:05 +00003506
Werner Lemberg013efd12003-09-17 05:26:33 +00003507
Werner Lemberg46333a12003-09-17 19:20:02 +00003508 FT_FACE_LOOKUP_SERVICE( face,
David Turnere2d12842003-09-21 17:15:55 +00003509 service,
David Turnerb72d8a82003-09-29 20:33:37 +00003510 POSTSCRIPT_FONT_NAME );
David Turner23bcde12001-10-17 13:48:10 +00003511
David Turnerb72d8a82003-09-29 20:33:37 +00003512 if ( service && service->get_ps_font_name )
3513 result = service->get_ps_font_name( face );
David Turner23bcde12001-10-17 13:48:10 +00003514 }
Werner Lemberg013efd12003-09-17 05:26:33 +00003515
David Turner23bcde12001-10-17 13:48:10 +00003516 Exit:
3517 return result;
3518 }
3519
3520
Werner Lemberg90a03302000-11-07 17:21:11 +00003521 /* documentation is in tttables.h */
3522
Werner Lembergf814d0f2001-06-27 16:18:10 +00003523 FT_EXPORT_DEF( void* )
3524 FT_Get_Sfnt_Table( FT_Face face,
3525 FT_Sfnt_Tag tag )
David Turner99a4d932000-04-25 16:10:50 +00003526 {
Werner Lemberg40bb0962003-11-01 14:36:20 +00003527 void* table = 0;
3528 FT_Service_SFNT_Table service;
David Turnere49ab252000-05-16 23:44:38 +00003529
Werner Lemberg013efd12003-09-17 05:26:33 +00003530
David Turnerc313c502003-09-11 19:51:54 +00003531 if ( face && FT_IS_SFNT( face ) )
3532 {
David Turnerb72d8a82003-09-29 20:33:37 +00003533 FT_FACE_FIND_SERVICE( face, service, SFNT_TABLE );
David Turnerc313c502003-09-11 19:51:54 +00003534 if ( service != NULL )
3535 table = service->get_table( face, tag );
3536 }
David Turnere2d12842003-09-21 17:15:55 +00003537
David Turner99a4d932000-04-25 16:10:50 +00003538 return table;
David Turnere49ab252000-05-16 23:44:38 +00003539 }
David Turner99a4d932000-04-25 16:10:50 +00003540
3541
David Turner621e4882002-12-16 21:51:24 +00003542 /* documentation is in tttables.h */
3543
3544 FT_EXPORT_DEF( FT_Error )
Werner Lembergc8c6bf52003-04-23 05:38:13 +00003545 FT_Load_Sfnt_Table( FT_Face face,
3546 FT_ULong tag,
3547 FT_Long offset,
3548 FT_Byte* buffer,
3549 FT_ULong* length )
David Turner621e4882002-12-16 21:51:24 +00003550 {
David Turnerc313c502003-09-11 19:51:54 +00003551 FT_Service_SFNT_Table service;
David Turner621e4882002-12-16 21:51:24 +00003552
3553
3554 if ( !face || !FT_IS_SFNT( face ) )
3555 return FT_Err_Invalid_Face_Handle;
3556
David Turnerb72d8a82003-09-29 20:33:37 +00003557 FT_FACE_FIND_SERVICE( face, service, SFNT_TABLE );
David Turnerc313c502003-09-11 19:51:54 +00003558 if ( service == NULL )
David Turner621e4882002-12-16 21:51:24 +00003559 return FT_Err_Unimplemented_Feature;
David Turnere2d12842003-09-21 17:15:55 +00003560
David Turnerc313c502003-09-11 19:51:54 +00003561 return service->load_table( face, tag, offset, buffer, length );
David Turner621e4882002-12-16 21:51:24 +00003562 }
3563
3564
Werner Lemberg17439422004-08-11 05:25:37 +00003565 /* documentation is in tttables.h */
3566
3567 FT_EXPORT_DEF( FT_Error )
3568 FT_Sfnt_Table_Info( FT_Face face,
3569 FT_UInt table_index,
3570 FT_ULong *tag,
3571 FT_ULong *length )
3572 {
3573 FT_Service_SFNT_Table service;
suzuki toshiyaad289d12009-06-29 03:09:17 +09003574 FT_ULong offset;
Werner Lemberg17439422004-08-11 05:25:37 +00003575
3576
3577 if ( !face || !FT_IS_SFNT( face ) )
3578 return FT_Err_Invalid_Face_Handle;
3579
3580 FT_FACE_FIND_SERVICE( face, service, SFNT_TABLE );
3581 if ( service == NULL )
3582 return FT_Err_Unimplemented_Feature;
3583
suzuki toshiyaad289d12009-06-29 03:09:17 +09003584 return service->table_info( face, table_index, tag, &offset, length );
Werner Lemberg17439422004-08-11 05:25:37 +00003585 }
3586
3587
Werner Lembergece8b202004-12-13 23:16:59 +00003588 /* documentation is in tttables.h */
3589
Werner Lemberg91a67472003-12-17 14:28:22 +00003590 FT_EXPORT_DEF( FT_ULong )
3591 FT_Get_CMap_Language_ID( FT_CharMap charmap )
3592 {
3593 FT_Service_TTCMaps service;
3594 FT_Face face;
3595 TT_CMapInfo cmap_info;
3596
David Turner87c0d302003-12-24 01:10:46 +00003597
Werner Lemberg91a67472003-12-17 14:28:22 +00003598 if ( !charmap || !charmap->face )
3599 return 0;
3600
3601 face = charmap->face;
3602 FT_FACE_FIND_SERVICE( face, service, TT_CMAP );
3603 if ( service == NULL )
3604 return 0;
3605 if ( service->get_cmap_info( charmap, &cmap_info ))
3606 return 0;
3607
3608 return cmap_info.language;
3609 }
3610
3611
Werner Lembergb826fa72007-05-19 07:18:48 +00003612 /* documentation is in tttables.h */
3613
3614 FT_EXPORT_DEF( FT_Long )
3615 FT_Get_CMap_Format( FT_CharMap charmap )
3616 {
3617 FT_Service_TTCMaps service;
3618 FT_Face face;
3619 TT_CMapInfo cmap_info;
3620
3621
3622 if ( !charmap || !charmap->face )
3623 return -1;
3624
3625 face = charmap->face;
3626 FT_FACE_FIND_SERVICE( face, service, TT_CMAP );
3627 if ( service == NULL )
3628 return -1;
3629 if ( service->get_cmap_info( charmap, &cmap_info ))
3630 return -1;
3631
3632 return cmap_info.format;
3633 }
3634
3635
Werner Lembergece8b202004-12-13 23:16:59 +00003636 /* documentation is in ftsizes.h */
3637
David Turnerb3ba40d2001-10-07 13:30:26 +00003638 FT_EXPORT_DEF( FT_Error )
Werner Lemberg80b8d772001-10-10 19:56:42 +00003639 FT_Activate_Size( FT_Size size )
David Turnerb3ba40d2001-10-07 13:30:26 +00003640 {
3641 FT_Face face;
Werner Lemberg1a0a9792002-01-03 22:06:13 +00003642
Werner Lemberg80b8d772001-10-10 19:56:42 +00003643
David Turnerb3ba40d2001-10-07 13:30:26 +00003644 if ( size == NULL )
Werner Lemberg3c5ad952008-12-21 17:51:12 +00003645 return FT_Err_Invalid_Argument;
Werner Lemberg1a0a9792002-01-03 22:06:13 +00003646
David Turnerb3ba40d2001-10-07 13:30:26 +00003647 face = size->face;
3648 if ( face == NULL || face->driver == NULL )
Werner Lemberg3c5ad952008-12-21 17:51:12 +00003649 return FT_Err_Invalid_Argument;
Werner Lemberg1a0a9792002-01-03 22:06:13 +00003650
Werner Lemberg80b8d772001-10-10 19:56:42 +00003651 /* we don't need anything more complex than that; all size objects */
3652 /* are already listed by the face */
David Turnerb3ba40d2001-10-07 13:30:26 +00003653 face->size = size;
Werner Lemberg1a0a9792002-01-03 22:06:13 +00003654
David Turnerb3ba40d2001-10-07 13:30:26 +00003655 return FT_Err_Ok;
3656 }
3657
3658
David Turnerd2b1f351999-12-16 23:11:37 +00003659 /*************************************************************************/
David Turnerf0df85b2000-06-22 00:17:42 +00003660 /*************************************************************************/
3661 /*************************************************************************/
3662 /**** ****/
3663 /**** ****/
3664 /**** R E N D E R E R S ****/
3665 /**** ****/
3666 /**** ****/
3667 /*************************************************************************/
3668 /*************************************************************************/
3669 /*************************************************************************/
3670
Werner Lembergdeb4e982000-06-29 03:14:25 +00003671 /* lookup a renderer by glyph format in the library's list */
Werner Lembergf814d0f2001-06-27 16:18:10 +00003672 FT_BASE_DEF( FT_Renderer )
3673 FT_Lookup_Renderer( FT_Library library,
3674 FT_Glyph_Format format,
3675 FT_ListNode* node )
David Turnerf0df85b2000-06-22 00:17:42 +00003676 {
Werner Lembergf8ba2002002-03-30 13:16:35 +00003677 FT_ListNode cur;
3678 FT_Renderer result = 0;
Werner Lemberga929ba92000-06-25 06:47:11 +00003679
Werner Lembergdeb4e982000-06-29 03:14:25 +00003680
3681 if ( !library )
3682 goto Exit;
3683
3684 cur = library->renderers.head;
3685
3686 if ( node )
David Turner74abee82000-06-27 23:31:53 +00003687 {
Werner Lembergdeb4e982000-06-29 03:14:25 +00003688 if ( *node )
David Turner74abee82000-06-27 23:31:53 +00003689 cur = (*node)->next;
David Turnerf0df85b2000-06-22 00:17:42 +00003690 *node = 0;
David Turner74abee82000-06-27 23:31:53 +00003691 }
Werner Lembergdeb4e982000-06-29 03:14:25 +00003692
Werner Lemberga929ba92000-06-25 06:47:11 +00003693 while ( cur )
David Turnerf0df85b2000-06-22 00:17:42 +00003694 {
Werner Lemberga929ba92000-06-25 06:47:11 +00003695 FT_Renderer renderer = FT_RENDERER( cur->data );
Werner Lembergdeb4e982000-06-29 03:14:25 +00003696
Werner Lemberga929ba92000-06-25 06:47:11 +00003697
3698 if ( renderer->glyph_format == format )
David Turnerf0df85b2000-06-22 00:17:42 +00003699 {
Werner Lemberga929ba92000-06-25 06:47:11 +00003700 if ( node )
David Turnerf0df85b2000-06-22 00:17:42 +00003701 *node = cur;
Werner Lembergdeb4e982000-06-29 03:14:25 +00003702
David Turnerf0df85b2000-06-22 00:17:42 +00003703 result = renderer;
3704 break;
3705 }
David Turner74abee82000-06-27 23:31:53 +00003706 cur = cur->next;
David Turnerf0df85b2000-06-22 00:17:42 +00003707 }
Werner Lemberga929ba92000-06-25 06:47:11 +00003708
Werner Lembergdeb4e982000-06-29 03:14:25 +00003709 Exit:
David Turnerf0df85b2000-06-22 00:17:42 +00003710 return result;
3711 }
3712
Werner Lemberga929ba92000-06-25 06:47:11 +00003713
Werner Lembergf814d0f2001-06-27 16:18:10 +00003714 static FT_Renderer
3715 ft_lookup_glyph_renderer( FT_GlyphSlot slot )
Werner Lembergdeb4e982000-06-29 03:14:25 +00003716 {
3717 FT_Face face = slot->face;
3718 FT_Library library = FT_FACE_LIBRARY( face );
3719 FT_Renderer result = library->cur_renderer;
3720
3721
Werner Lemberga929ba92000-06-25 06:47:11 +00003722 if ( !result || result->glyph_format != slot->format )
David Turner81bb4ad2000-06-28 04:19:49 +00003723 result = FT_Lookup_Renderer( library, slot->format, 0 );
Werner Lembergfbeb41d2000-07-02 00:27:53 +00003724
David Turnerf0df85b2000-06-22 00:17:42 +00003725 return result;
3726 }
3727
Werner Lembergdeb4e982000-06-29 03:14:25 +00003728
Werner Lembergf814d0f2001-06-27 16:18:10 +00003729 static void
3730 ft_set_current_renderer( FT_Library library )
David Turnerf0df85b2000-06-22 00:17:42 +00003731 {
3732 FT_Renderer renderer;
3733
Werner Lembergdeb4e982000-06-29 03:14:25 +00003734
David Turnerb08fe2d2002-08-27 20:20:29 +00003735 renderer = FT_Lookup_Renderer( library, FT_GLYPH_FORMAT_OUTLINE, 0 );
David Turnerf0df85b2000-06-22 00:17:42 +00003736 library->cur_renderer = renderer;
3737 }
3738
3739
Werner Lembergf814d0f2001-06-27 16:18:10 +00003740 static FT_Error
3741 ft_add_renderer( FT_Module module )
David Turnerf0df85b2000-06-22 00:17:42 +00003742 {
3743 FT_Library library = module->library;
3744 FT_Memory memory = library->memory;
3745 FT_Error error;
Werner Lembergc8f5b982010-07-12 21:13:22 +02003746 FT_ListNode node = NULL;
Werner Lembergdeb4e982000-06-29 03:14:25 +00003747
3748
David Turnere459d742002-03-22 13:52:37 +00003749 if ( FT_NEW( node ) )
David Turnerf0df85b2000-06-22 00:17:42 +00003750 goto Exit;
Werner Lembergdeb4e982000-06-29 03:14:25 +00003751
David Turnerf0df85b2000-06-22 00:17:42 +00003752 {
Werner Lemberga929ba92000-06-25 06:47:11 +00003753 FT_Renderer render = FT_RENDERER( module );
David Turnerf0df85b2000-06-22 00:17:42 +00003754 FT_Renderer_Class* clazz = (FT_Renderer_Class*)module->clazz;
3755
Werner Lemberga929ba92000-06-25 06:47:11 +00003756
David Turnerf0df85b2000-06-22 00:17:42 +00003757 render->clazz = clazz;
3758 render->glyph_format = clazz->glyph_format;
Werner Lembergdeb4e982000-06-29 03:14:25 +00003759
David Turnerf0df85b2000-06-22 00:17:42 +00003760 /* allocate raster object if needed */
David Turnerb08fe2d2002-08-27 20:20:29 +00003761 if ( clazz->glyph_format == FT_GLYPH_FORMAT_OUTLINE &&
Eugene A. Shatokhinb33b8562010-07-05 22:36:30 +02003762 clazz->raster_class->raster_new )
David Turnerf0df85b2000-06-22 00:17:42 +00003763 {
3764 error = clazz->raster_class->raster_new( memory, &render->raster );
Werner Lemberga929ba92000-06-25 06:47:11 +00003765 if ( error )
3766 goto Fail;
Werner Lembergdeb4e982000-06-29 03:14:25 +00003767
David Turnerf0df85b2000-06-22 00:17:42 +00003768 render->raster_render = clazz->raster_class->raster_render;
3769 render->render = clazz->render_glyph;
Werner Lembergdeb4e982000-06-29 03:14:25 +00003770 }
3771
David Turnerf0df85b2000-06-22 00:17:42 +00003772 /* add to list */
3773 node->data = module;
3774 FT_List_Add( &library->renderers, node );
3775
3776 ft_set_current_renderer( library );
3777 }
3778
3779 Fail:
Werner Lemberga929ba92000-06-25 06:47:11 +00003780 if ( error )
David Turnere459d742002-03-22 13:52:37 +00003781 FT_FREE( node );
David Turnerf0df85b2000-06-22 00:17:42 +00003782
3783 Exit:
3784 return error;
Werner Lembergdeb4e982000-06-29 03:14:25 +00003785 }
David Turnerf0df85b2000-06-22 00:17:42 +00003786
3787
Werner Lembergf814d0f2001-06-27 16:18:10 +00003788 static void
3789 ft_remove_renderer( FT_Module module )
David Turnerf0df85b2000-06-22 00:17:42 +00003790 {
3791 FT_Library library = module->library;
3792 FT_Memory memory = library->memory;
3793 FT_ListNode node;
3794
Werner Lemberga929ba92000-06-25 06:47:11 +00003795
David Turnerf0df85b2000-06-22 00:17:42 +00003796 node = FT_List_Find( &library->renderers, module );
Werner Lemberga929ba92000-06-25 06:47:11 +00003797 if ( node )
David Turnerf0df85b2000-06-22 00:17:42 +00003798 {
Werner Lemberga929ba92000-06-25 06:47:11 +00003799 FT_Renderer render = FT_RENDERER( module );
Werner Lembergdeb4e982000-06-29 03:14:25 +00003800
Werner Lemberga929ba92000-06-25 06:47:11 +00003801
David Turnerf0df85b2000-06-22 00:17:42 +00003802 /* release raster object, if any */
Eugene A. Shatokhinb33b8562010-07-05 22:36:30 +02003803 if ( render->clazz->glyph_format == FT_GLYPH_FORMAT_OUTLINE &&
3804 render->raster )
David Turnerf0df85b2000-06-22 00:17:42 +00003805 render->clazz->raster_class->raster_done( render->raster );
Werner Lembergdeb4e982000-06-29 03:14:25 +00003806
David Turnerf0df85b2000-06-22 00:17:42 +00003807 /* remove from list */
3808 FT_List_Remove( &library->renderers, node );
David Turnere459d742002-03-22 13:52:37 +00003809 FT_FREE( node );
Werner Lembergdeb4e982000-06-29 03:14:25 +00003810
David Turnerf0df85b2000-06-22 00:17:42 +00003811 ft_set_current_renderer( library );
3812 }
3813 }
3814
3815
Werner Lemberg90a03302000-11-07 17:21:11 +00003816 /* documentation is in ftrender.h */
3817
Werner Lembergf814d0f2001-06-27 16:18:10 +00003818 FT_EXPORT_DEF( FT_Renderer )
3819 FT_Get_Renderer( FT_Library library,
3820 FT_Glyph_Format format )
David Turnerf0df85b2000-06-22 00:17:42 +00003821 {
Werner Lembergdeb4e982000-06-29 03:14:25 +00003822 /* test for valid `library' delayed to FT_Lookup_Renderer() */
3823
Werner Lembergf8ba2002002-03-30 13:16:35 +00003824 return FT_Lookup_Renderer( library, format, 0 );
Werner Lembergdeb4e982000-06-29 03:14:25 +00003825 }
David Turnerf0df85b2000-06-22 00:17:42 +00003826
3827
Werner Lemberg90a03302000-11-07 17:21:11 +00003828 /* documentation is in ftrender.h */
3829
Werner Lembergf814d0f2001-06-27 16:18:10 +00003830 FT_EXPORT_DEF( FT_Error )
3831 FT_Set_Renderer( FT_Library library,
3832 FT_Renderer renderer,
3833 FT_UInt num_params,
3834 FT_Parameter* parameters )
David Turnerf0df85b2000-06-22 00:17:42 +00003835 {
3836 FT_ListNode node;
3837 FT_Error error = FT_Err_Ok;
Werner Lembergdeb4e982000-06-29 03:14:25 +00003838
3839
3840 if ( !library )
3841 return FT_Err_Invalid_Library_Handle;
3842
3843 if ( !renderer )
3844 return FT_Err_Invalid_Argument;
Werner Lemberga929ba92000-06-25 06:47:11 +00003845
David Turnerf0df85b2000-06-22 00:17:42 +00003846 node = FT_List_Find( &library->renderers, renderer );
Werner Lemberga929ba92000-06-25 06:47:11 +00003847 if ( !node )
David Turnerf0df85b2000-06-22 00:17:42 +00003848 {
3849 error = FT_Err_Invalid_Argument;
3850 goto Exit;
3851 }
David Turner74abee82000-06-27 23:31:53 +00003852
David Turnerf0df85b2000-06-22 00:17:42 +00003853 FT_List_Up( &library->renderers, node );
Werner Lembergdeb4e982000-06-29 03:14:25 +00003854
David Turnerb08fe2d2002-08-27 20:20:29 +00003855 if ( renderer->glyph_format == FT_GLYPH_FORMAT_OUTLINE )
David Turnerf0df85b2000-06-22 00:17:42 +00003856 library->cur_renderer = renderer;
Werner Lembergdeb4e982000-06-29 03:14:25 +00003857
Werner Lemberga929ba92000-06-25 06:47:11 +00003858 if ( num_params > 0 )
David Turnerf0df85b2000-06-22 00:17:42 +00003859 {
David Turnerb08fe2d2002-08-27 20:20:29 +00003860 FT_Renderer_SetModeFunc set_mode = renderer->clazz->set_mode;
Werner Lembergdeb4e982000-06-29 03:14:25 +00003861
Werner Lemberga929ba92000-06-25 06:47:11 +00003862
David Turnerf0df85b2000-06-22 00:17:42 +00003863 for ( ; num_params > 0; num_params-- )
3864 {
3865 error = set_mode( renderer, parameters->tag, parameters->data );
Werner Lemberga929ba92000-06-25 06:47:11 +00003866 if ( error )
David Turnerf0df85b2000-06-22 00:17:42 +00003867 break;
3868 }
3869 }
Werner Lembergdeb4e982000-06-29 03:14:25 +00003870
David Turnerf0df85b2000-06-22 00:17:42 +00003871 Exit:
3872 return error;
Werner Lembergdeb4e982000-06-29 03:14:25 +00003873 }
David Turnerf0df85b2000-06-22 00:17:42 +00003874
3875
David Turner7504e482002-06-07 07:24:55 +00003876 FT_BASE_DEF( FT_Error )
Werner Lemberg68e9f922002-09-27 11:09:23 +00003877 FT_Render_Glyph_Internal( FT_Library library,
3878 FT_GlyphSlot slot,
3879 FT_Render_Mode render_mode )
David Turnerf0df85b2000-06-22 00:17:42 +00003880 {
3881 FT_Error error = FT_Err_Ok;
3882 FT_Renderer renderer;
Werner Lemberga929ba92000-06-25 06:47:11 +00003883
Werner Lembergdeb4e982000-06-29 03:14:25 +00003884
3885 /* if it is already a bitmap, no need to do anything */
3886 switch ( slot->format )
David Turnerf0df85b2000-06-22 00:17:42 +00003887 {
David Turnerb08fe2d2002-08-27 20:20:29 +00003888 case FT_GLYPH_FORMAT_BITMAP: /* already a bitmap, don't do anything */
Werner Lembergdeb4e982000-06-29 03:14:25 +00003889 break;
3890
3891 default:
David Turner74abee82000-06-27 23:31:53 +00003892 {
3893 FT_ListNode node = 0;
3894 FT_Bool update = 0;
Werner Lembergdeb4e982000-06-29 03:14:25 +00003895
3896
Werner Lemberga929ba92000-06-25 06:47:11 +00003897 /* small shortcut for the very common case */
David Turnerb08fe2d2002-08-27 20:20:29 +00003898 if ( slot->format == FT_GLYPH_FORMAT_OUTLINE )
David Turner74abee82000-06-27 23:31:53 +00003899 {
Werner Lemberga929ba92000-06-25 06:47:11 +00003900 renderer = library->cur_renderer;
David Turner74abee82000-06-27 23:31:53 +00003901 node = library->renderers.head;
3902 }
Werner Lemberga929ba92000-06-25 06:47:11 +00003903 else
David Turner74abee82000-06-27 23:31:53 +00003904 renderer = FT_Lookup_Renderer( library, slot->format, &node );
3905
Werner Lemberga929ba92000-06-25 06:47:11 +00003906 error = FT_Err_Unimplemented_Feature;
Werner Lembergdeb4e982000-06-29 03:14:25 +00003907 while ( renderer )
David Turner74abee82000-06-27 23:31:53 +00003908 {
David Turnerc8ad30a2001-12-05 17:24:34 +00003909 error = renderer->render( renderer, slot, render_mode, NULL );
Werner Lemberg858abbe2009-06-26 06:15:41 +02003910 if ( !error ||
Werner Lemberg79860702001-06-08 21:17:29 +00003911 FT_ERROR_BASE( error ) != FT_Err_Cannot_Render_Glyph )
Werner Lembergdeb4e982000-06-29 03:14:25 +00003912 break;
David Turner74abee82000-06-27 23:31:53 +00003913
Werner Lembergdeb4e982000-06-29 03:14:25 +00003914 /* FT_Err_Cannot_Render_Glyph is returned if the render mode */
David Turner74abee82000-06-27 23:31:53 +00003915 /* is unsupported by the current renderer for this glyph image */
Werner Lembergdeb4e982000-06-29 03:14:25 +00003916 /* format. */
3917
3918 /* now, look for another renderer that supports the same */
3919 /* format. */
David Turner74abee82000-06-27 23:31:53 +00003920 renderer = FT_Lookup_Renderer( library, slot->format, &node );
3921 update = 1;
3922 }
3923
3924 /* if we changed the current renderer for the glyph image format */
Werner Lembergdeb4e982000-06-29 03:14:25 +00003925 /* we need to select it as the next current one */
3926 if ( !error && update && renderer )
David Turner74abee82000-06-27 23:31:53 +00003927 FT_Set_Renderer( library, renderer, 0, 0 );
David Turnerf0df85b2000-06-22 00:17:42 +00003928 }
3929 }
Werner Lembergdeb4e982000-06-29 03:14:25 +00003930
David Turnerf0df85b2000-06-22 00:17:42 +00003931 return error;
3932 }
Werner Lemberga929ba92000-06-25 06:47:11 +00003933
David Turner74abee82000-06-27 23:31:53 +00003934
Werner Lemberg90a03302000-11-07 17:21:11 +00003935 /* documentation is in freetype.h */
3936
Werner Lembergf814d0f2001-06-27 16:18:10 +00003937 FT_EXPORT_DEF( FT_Error )
Werner Lemberg68e9f922002-09-27 11:09:23 +00003938 FT_Render_Glyph( FT_GlyphSlot slot,
3939 FT_Render_Mode render_mode )
David Turner74abee82000-06-27 23:31:53 +00003940 {
Werner Lembergf8ba2002002-03-30 13:16:35 +00003941 FT_Library library;
Werner Lembergdeb4e982000-06-29 03:14:25 +00003942
3943
Werner Lemberge30de292010-05-22 20:03:41 +02003944 if ( !slot || !slot->face )
David Turner74abee82000-06-27 23:31:53 +00003945 return FT_Err_Invalid_Argument;
Werner Lembergdeb4e982000-06-29 03:14:25 +00003946
3947 library = FT_FACE_LIBRARY( slot->face );
3948
David Turner74abee82000-06-27 23:31:53 +00003949 return FT_Render_Glyph_Internal( library, slot, render_mode );
3950 }
3951
Werner Lembergdeb4e982000-06-29 03:14:25 +00003952
David Turnerf0df85b2000-06-22 00:17:42 +00003953 /*************************************************************************/
3954 /*************************************************************************/
3955 /*************************************************************************/
3956 /**** ****/
3957 /**** ****/
3958 /**** M O D U L E S ****/
3959 /**** ****/
3960 /**** ****/
3961 /*************************************************************************/
3962 /*************************************************************************/
3963 /*************************************************************************/
3964
Werner Lemberga929ba92000-06-25 06:47:11 +00003965
David Turnerf0df85b2000-06-22 00:17:42 +00003966 /*************************************************************************/
3967 /* */
3968 /* <Function> */
3969 /* Destroy_Module */
3970 /* */
3971 /* <Description> */
3972 /* Destroys a given module object. For drivers, this also destroys */
Werner Lemberga929ba92000-06-25 06:47:11 +00003973 /* all child faces. */
David Turnerf0df85b2000-06-22 00:17:42 +00003974 /* */
3975 /* <InOut> */
3976 /* module :: A handle to the target driver object. */
3977 /* */
3978 /* <Note> */
3979 /* The driver _must_ be LOCKED! */
3980 /* */
Werner Lembergf814d0f2001-06-27 16:18:10 +00003981 static void
3982 Destroy_Module( FT_Module module )
David Turnerf0df85b2000-06-22 00:17:42 +00003983 {
David Turner5ae831c2000-06-30 01:31:22 +00003984 FT_Memory memory = module->memory;
3985 FT_Module_Class* clazz = module->clazz;
3986 FT_Library library = module->library;
David Turnerf0df85b2000-06-22 00:17:42 +00003987
Werner Lemberga929ba92000-06-25 06:47:11 +00003988
David Turnerf0df85b2000-06-22 00:17:42 +00003989 /* finalize client-data - before anything else */
3990 if ( module->generic.finalizer )
3991 module->generic.finalizer( module );
3992
David Turner5ae831c2000-06-30 01:31:22 +00003993 if ( library && library->auto_hinter == module )
3994 library->auto_hinter = 0;
3995
David Turnerf0df85b2000-06-22 00:17:42 +00003996 /* if the module is a renderer */
Werner Lemberga929ba92000-06-25 06:47:11 +00003997 if ( FT_MODULE_IS_RENDERER( module ) )
3998 ft_remove_renderer( module );
David Turnerf0df85b2000-06-22 00:17:42 +00003999
4000 /* if the module is a font driver, add some steps */
Werner Lemberga929ba92000-06-25 06:47:11 +00004001 if ( FT_MODULE_IS_DRIVER( module ) )
4002 Destroy_Driver( FT_DRIVER( module ) );
David Turnerf0df85b2000-06-22 00:17:42 +00004003
4004 /* finalize the module object */
Werner Lemberga929ba92000-06-25 06:47:11 +00004005 if ( clazz->module_done )
4006 clazz->module_done( module );
David Turnerf0df85b2000-06-22 00:17:42 +00004007
4008 /* discard it */
David Turnere459d742002-03-22 13:52:37 +00004009 FT_FREE( module );
David Turnerf0df85b2000-06-22 00:17:42 +00004010 }
4011
David Turnerf0df85b2000-06-22 00:17:42 +00004012
Werner Lemberg748b1712005-12-25 09:15:09 +00004013 /* documentation is in ftmodapi.h */
Werner Lemberg90a03302000-11-07 17:21:11 +00004014
Werner Lembergf814d0f2001-06-27 16:18:10 +00004015 FT_EXPORT_DEF( FT_Error )
4016 FT_Add_Module( FT_Library library,
4017 const FT_Module_Class* clazz )
David Turnerf0df85b2000-06-22 00:17:42 +00004018 {
4019 FT_Error error;
4020 FT_Memory memory;
4021 FT_Module module;
4022 FT_UInt nn;
4023
David Turnerf0df85b2000-06-22 00:17:42 +00004024
Werner Lembergdeb4e982000-06-29 03:14:25 +00004025#define FREETYPE_VER_FIXED ( ( (FT_Long)FREETYPE_MAJOR << 16 ) | \
4026 FREETYPE_MINOR )
Werner Lemberga929ba92000-06-25 06:47:11 +00004027
Werner Lembergdeb4e982000-06-29 03:14:25 +00004028 if ( !library )
4029 return FT_Err_Invalid_Library_Handle;
4030
4031 if ( !clazz )
David Turnerf0df85b2000-06-22 00:17:42 +00004032 return FT_Err_Invalid_Argument;
4033
4034 /* check freetype version */
4035 if ( clazz->module_requires > FREETYPE_VER_FIXED )
4036 return FT_Err_Invalid_Version;
4037
4038 /* look for a module with the same name in the library's table */
4039 for ( nn = 0; nn < library->num_modules; nn++ )
4040 {
4041 module = library->modules[nn];
David Turnerd15bc0d2002-04-12 09:31:48 +00004042 if ( ft_strcmp( module->clazz->module_name, clazz->module_name ) == 0 )
David Turnerf0df85b2000-06-22 00:17:42 +00004043 {
4044 /* this installed module has the same name, compare their versions */
4045 if ( clazz->module_version <= module->clazz->module_version )
4046 return FT_Err_Lower_Module_Version;
4047
4048 /* remove the module from our list, then exit the loop to replace */
4049 /* it by our new version.. */
4050 FT_Remove_Module( library, module );
4051 break;
4052 }
4053 }
4054
4055 memory = library->memory;
4056 error = FT_Err_Ok;
4057
4058 if ( library->num_modules >= FT_MAX_MODULES )
4059 {
4060 error = FT_Err_Too_Many_Drivers;
4061 goto Exit;
4062 }
4063
4064 /* allocate module object */
Werner Lemberg68e9f922002-09-27 11:09:23 +00004065 if ( FT_ALLOC( module, clazz->module_size ) )
David Turnerf0df85b2000-06-22 00:17:42 +00004066 goto Exit;
4067
Werner Lembergdeb4e982000-06-29 03:14:25 +00004068 /* base initialization */
David Turnerf0df85b2000-06-22 00:17:42 +00004069 module->library = library;
4070 module->memory = memory;
4071 module->clazz = (FT_Module_Class*)clazz;
4072
Werner Lembergdeb4e982000-06-29 03:14:25 +00004073 /* check whether the module is a renderer - this must be performed */
4074 /* before the normal module initialization */
Werner Lemberga929ba92000-06-25 06:47:11 +00004075 if ( FT_MODULE_IS_RENDERER( module ) )
David Turnerf0df85b2000-06-22 00:17:42 +00004076 {
4077 /* add to the renderers list */
Werner Lemberga929ba92000-06-25 06:47:11 +00004078 error = ft_add_renderer( module );
4079 if ( error )
4080 goto Fail;
David Turnerf0df85b2000-06-22 00:17:42 +00004081 }
4082
Werner Lembergcc9fc492000-06-30 06:21:26 +00004083 /* is the module a auto-hinter? */
4084 if ( FT_MODULE_IS_HINTER( module ) )
David Turner5ae831c2000-06-30 01:31:22 +00004085 library->auto_hinter = module;
Werner Lembergfbeb41d2000-07-02 00:27:53 +00004086
David Turnerf0df85b2000-06-22 00:17:42 +00004087 /* if the module is a font driver */
Werner Lemberga929ba92000-06-25 06:47:11 +00004088 if ( FT_MODULE_IS_DRIVER( module ) )
David Turnerf0df85b2000-06-22 00:17:42 +00004089 {
4090 /* allocate glyph loader if needed */
Werner Lembergf8ba2002002-03-30 13:16:35 +00004091 FT_Driver driver = FT_DRIVER( module );
Werner Lemberga929ba92000-06-25 06:47:11 +00004092
Werner Lembergdeb4e982000-06-29 03:14:25 +00004093
David Turneref3c1262002-03-14 09:22:48 +00004094 driver->clazz = (FT_Driver_Class)module->clazz;
Werner Lemberga929ba92000-06-25 06:47:11 +00004095 if ( FT_DRIVER_USES_OUTLINES( driver ) )
David Turnerf0df85b2000-06-22 00:17:42 +00004096 {
4097 error = FT_GlyphLoader_New( memory, &driver->glyph_loader );
Werner Lemberga929ba92000-06-25 06:47:11 +00004098 if ( error )
4099 goto Fail;
David Turnerf0df85b2000-06-22 00:17:42 +00004100 }
4101 }
4102
Werner Lemberga929ba92000-06-25 06:47:11 +00004103 if ( clazz->module_init )
David Turnerf0df85b2000-06-22 00:17:42 +00004104 {
Werner Lemberga929ba92000-06-25 06:47:11 +00004105 error = clazz->module_init( module );
4106 if ( error )
4107 goto Fail;
David Turnerf0df85b2000-06-22 00:17:42 +00004108 }
4109
4110 /* add module to the library's table */
Werner Lemberga929ba92000-06-25 06:47:11 +00004111 library->modules[library->num_modules++] = module;
Werner Lembergdeb4e982000-06-29 03:14:25 +00004112
David Turnerf0df85b2000-06-22 00:17:42 +00004113 Exit:
4114 return error;
Werner Lembergdeb4e982000-06-29 03:14:25 +00004115
David Turnerf0df85b2000-06-22 00:17:42 +00004116 Fail:
Werner Lemberga929ba92000-06-25 06:47:11 +00004117 if ( FT_MODULE_IS_DRIVER( module ) )
David Turnerf0df85b2000-06-22 00:17:42 +00004118 {
Werner Lemberga929ba92000-06-25 06:47:11 +00004119 FT_Driver driver = FT_DRIVER( module );
Werner Lembergdeb4e982000-06-29 03:14:25 +00004120
Werner Lemberga929ba92000-06-25 06:47:11 +00004121
4122 if ( FT_DRIVER_USES_OUTLINES( driver ) )
David Turnerf0df85b2000-06-22 00:17:42 +00004123 FT_GlyphLoader_Done( driver->glyph_loader );
4124 }
Werner Lembergdeb4e982000-06-29 03:14:25 +00004125
Werner Lemberga929ba92000-06-25 06:47:11 +00004126 if ( FT_MODULE_IS_RENDERER( module ) )
David Turnerf0df85b2000-06-22 00:17:42 +00004127 {
Werner Lemberga929ba92000-06-25 06:47:11 +00004128 FT_Renderer renderer = FT_RENDERER( module );
4129
4130
Eugene A. Shatokhinb33b8562010-07-05 22:36:30 +02004131 if ( renderer->clazz->glyph_format == FT_GLYPH_FORMAT_OUTLINE &&
4132 renderer->raster )
David Turnerf0df85b2000-06-22 00:17:42 +00004133 renderer->clazz->raster_class->raster_done( renderer->raster );
4134 }
Werner Lemberga929ba92000-06-25 06:47:11 +00004135
David Turnere459d742002-03-22 13:52:37 +00004136 FT_FREE( module );
David Turnerf0df85b2000-06-22 00:17:42 +00004137 goto Exit;
4138 }
4139
David Turnerf0df85b2000-06-22 00:17:42 +00004140
Werner Lemberg748b1712005-12-25 09:15:09 +00004141 /* documentation is in ftmodapi.h */
Werner Lemberg90a03302000-11-07 17:21:11 +00004142
Werner Lembergf814d0f2001-06-27 16:18:10 +00004143 FT_EXPORT_DEF( FT_Module )
4144 FT_Get_Module( FT_Library library,
4145 const char* module_name )
David Turnerf0df85b2000-06-22 00:17:42 +00004146 {
Werner Lembergdeb4e982000-06-29 03:14:25 +00004147 FT_Module result = 0;
4148 FT_Module* cur;
4149 FT_Module* limit;
David Turnerf0df85b2000-06-22 00:17:42 +00004150
Werner Lemberga929ba92000-06-25 06:47:11 +00004151
Werner Lembergdeb4e982000-06-29 03:14:25 +00004152 if ( !library || !module_name )
4153 return result;
4154
4155 cur = library->modules;
4156 limit = cur + library->num_modules;
4157
David Turnerf0df85b2000-06-22 00:17:42 +00004158 for ( ; cur < limit; cur++ )
David Turnerd15bc0d2002-04-12 09:31:48 +00004159 if ( ft_strcmp( cur[0]->clazz->module_name, module_name ) == 0 )
David Turnerf0df85b2000-06-22 00:17:42 +00004160 {
4161 result = cur[0];
4162 break;
4163 }
4164
4165 return result;
4166 }
4167
Werner Lemberga929ba92000-06-25 06:47:11 +00004168
Werner Lemberg8ec9dfd2000-11-07 23:56:02 +00004169 /* documentation is in ftobjs.h */
4170
Werner Lembergf814d0f2001-06-27 16:18:10 +00004171 FT_BASE_DEF( const void* )
4172 FT_Get_Module_Interface( FT_Library library,
4173 const char* mod_name )
David Turnerf0df85b2000-06-22 00:17:42 +00004174 {
4175 FT_Module module;
Werner Lembergdeb4e982000-06-29 03:14:25 +00004176
4177
4178 /* test for valid `library' delayed to FT_Get_Module() */
Werner Lemberga929ba92000-06-25 06:47:11 +00004179
David Turnerf0df85b2000-06-22 00:17:42 +00004180 module = FT_Get_Module( library, mod_name );
Werner Lemberga929ba92000-06-25 06:47:11 +00004181
David Turnerf0df85b2000-06-22 00:17:42 +00004182 return module ? module->clazz->module_interface : 0;
Werner Lembergdeb4e982000-06-29 03:14:25 +00004183 }
David Turnerf0df85b2000-06-22 00:17:42 +00004184
4185
David Turnerb72d8a82003-09-29 20:33:37 +00004186 FT_BASE_DEF( FT_Pointer )
4187 ft_module_get_service( FT_Module module,
4188 const char* service_id )
4189 {
4190 FT_Pointer result = NULL;
4191
4192 if ( module )
4193 {
4194 FT_ASSERT( module->clazz && module->clazz->get_interface );
4195
4196 /* first, look for the service in the module
4197 */
4198 if ( module->clazz->get_interface )
4199 result = module->clazz->get_interface( module, service_id );
4200
4201 if ( result == NULL )
4202 {
4203 /* we didn't find it, look in all other modules then
4204 */
4205 FT_Library library = module->library;
4206 FT_Module* cur = library->modules;
4207 FT_Module* limit = cur + library->num_modules;
4208
4209 for ( ; cur < limit; cur++ )
4210 {
4211 if ( cur[0] != module )
4212 {
4213 FT_ASSERT( cur[0]->clazz );
4214
4215 if ( cur[0]->clazz->get_interface )
4216 {
4217 result = cur[0]->clazz->get_interface( cur[0], service_id );
4218 if ( result != NULL )
4219 break;
4220 }
4221 }
4222 }
4223 }
4224 }
4225
4226 return result;
4227 }
4228
4229
Werner Lemberg748b1712005-12-25 09:15:09 +00004230 /* documentation is in ftmodapi.h */
Werner Lemberg90a03302000-11-07 17:21:11 +00004231
Werner Lembergf814d0f2001-06-27 16:18:10 +00004232 FT_EXPORT_DEF( FT_Error )
4233 FT_Remove_Module( FT_Library library,
4234 FT_Module module )
David Turnerf0df85b2000-06-22 00:17:42 +00004235 {
4236 /* try to find the module from the table, then remove it from there */
Werner Lembergdeb4e982000-06-29 03:14:25 +00004237
4238 if ( !library )
4239 return FT_Err_Invalid_Library_Handle;
4240
4241 if ( module )
David Turnerf0df85b2000-06-22 00:17:42 +00004242 {
4243 FT_Module* cur = library->modules;
4244 FT_Module* limit = cur + library->num_modules;
4245
Werner Lemberga929ba92000-06-25 06:47:11 +00004246
David Turnerf0df85b2000-06-22 00:17:42 +00004247 for ( ; cur < limit; cur++ )
4248 {
Werner Lembergdeb4e982000-06-29 03:14:25 +00004249 if ( cur[0] == module )
David Turnerf0df85b2000-06-22 00:17:42 +00004250 {
4251 /* remove it from the table */
4252 library->num_modules--;
4253 limit--;
Werner Lemberga929ba92000-06-25 06:47:11 +00004254 while ( cur < limit )
David Turnerf0df85b2000-06-22 00:17:42 +00004255 {
4256 cur[0] = cur[1];
4257 cur++;
4258 }
4259 limit[0] = 0;
4260
4261 /* destroy the module */
Werner Lemberga929ba92000-06-25 06:47:11 +00004262 Destroy_Module( module );
David Turnerf0df85b2000-06-22 00:17:42 +00004263
4264 return FT_Err_Ok;
4265 }
4266 }
4267 }
Werner Lembergb48a6092000-07-09 19:15:30 +00004268 return FT_Err_Invalid_Driver_Handle;
David Turnerf0df85b2000-06-22 00:17:42 +00004269 }
4270
4271
David Turnerf0df85b2000-06-22 00:17:42 +00004272 /*************************************************************************/
4273 /*************************************************************************/
4274 /*************************************************************************/
4275 /**** ****/
4276 /**** ****/
4277 /**** L I B R A R Y ****/
4278 /**** ****/
4279 /**** ****/
4280 /*************************************************************************/
4281 /*************************************************************************/
4282 /*************************************************************************/
4283
Werner Lemberga929ba92000-06-25 06:47:11 +00004284
Werner Lemberg748b1712005-12-25 09:15:09 +00004285 /* documentation is in ftmodapi.h */
Werner Lemberg90a03302000-11-07 17:21:11 +00004286
Werner Lembergf814d0f2001-06-27 16:18:10 +00004287 FT_EXPORT_DEF( FT_Error )
Werner Lembergfe3433c2010-07-18 18:41:47 +02004288 FT_Reference_Library( FT_Library library )
4289 {
4290 library->refcount++;
4291
4292 return FT_Err_Ok;
4293 }
4294
4295
4296 /* documentation is in ftmodapi.h */
4297
4298 FT_EXPORT_DEF( FT_Error )
Werner Lembergf814d0f2001-06-27 16:18:10 +00004299 FT_New_Library( FT_Memory memory,
4300 FT_Library *alibrary )
David Turnerf0df85b2000-06-22 00:17:42 +00004301 {
Werner Lembergfe3433c2010-07-18 18:41:47 +02004302 FT_Library library = NULL;
David Turnerf0df85b2000-06-22 00:17:42 +00004303 FT_Error error;
4304
4305
4306 if ( !memory )
4307 return FT_Err_Invalid_Argument;
4308
David Turnerf5749602002-04-18 10:07:26 +00004309#ifdef FT_DEBUG_LEVEL_ERROR
David Turner53b3fa12002-02-24 05:26:57 +00004310 /* init debugging support */
4311 ft_debug_init();
David Turnerf5749602002-04-18 10:07:26 +00004312#endif
David Turner53b3fa12002-02-24 05:26:57 +00004313
David Turnerf0df85b2000-06-22 00:17:42 +00004314 /* first of all, allocate the library object */
David Turnere459d742002-03-22 13:52:37 +00004315 if ( FT_NEW( library ) )
David Turnerf0df85b2000-06-22 00:17:42 +00004316 return error;
4317
4318 library->memory = memory;
4319
Oran Agra636c2942009-04-05 17:59:26 +03004320#ifdef FT_CONFIG_OPTION_PIC
4321 /* initialize position independent code containers */
4322 error = ft_pic_container_init( library );
4323 if ( error )
4324 goto Fail;
4325#endif
4326
David Turnerf0df85b2000-06-22 00:17:42 +00004327 /* allocate the render pool */
4328 library->raster_pool_size = FT_RENDER_POOL_SIZE;
Werner Lemberg39c91ad2007-07-28 05:40:40 +00004329#if FT_RENDER_POOL_SIZE > 0
4330 if ( FT_ALLOC( library->raster_pool, FT_RENDER_POOL_SIZE ) )
4331 goto Fail;
4332#endif
David Turnerf0df85b2000-06-22 00:17:42 +00004333
Werner Lemberg777d6d52009-06-25 16:46:39 +02004334 library->version_major = FREETYPE_MAJOR;
4335 library->version_minor = FREETYPE_MINOR;
4336 library->version_patch = FREETYPE_PATCH;
4337
Werner Lembergfe3433c2010-07-18 18:41:47 +02004338 library->refcount = 1;
4339
David Turnerf0df85b2000-06-22 00:17:42 +00004340 /* That's ok now */
4341 *alibrary = library;
4342
4343 return FT_Err_Ok;
4344
4345 Fail:
Oran Agra636c2942009-04-05 17:59:26 +03004346#ifdef FT_CONFIG_OPTION_PIC
4347 ft_pic_container_destroy( library );
4348#endif
David Turnere459d742002-03-22 13:52:37 +00004349 FT_FREE( library );
David Turnerf0df85b2000-06-22 00:17:42 +00004350 return error;
4351 }
4352
4353
David Turner83b4a4b2002-03-06 12:42:34 +00004354 /* documentation is in freetype.h */
David Turner25a6e3a2002-06-10 23:03:35 +00004355
David Turner83b4a4b2002-03-06 12:42:34 +00004356 FT_EXPORT_DEF( void )
4357 FT_Library_Version( FT_Library library,
4358 FT_Int *amajor,
4359 FT_Int *aminor,
4360 FT_Int *apatch )
4361 {
4362 FT_Int major = 0;
4363 FT_Int minor = 0;
4364 FT_Int patch = 0;
4365
David Turner25a6e3a2002-06-10 23:03:35 +00004366
David Turner83b4a4b2002-03-06 12:42:34 +00004367 if ( library )
4368 {
4369 major = library->version_major;
4370 minor = library->version_minor;
4371 patch = library->version_patch;
4372 }
David Turner25a6e3a2002-06-10 23:03:35 +00004373
David Turnerd48575e2002-09-18 23:18:36 +00004374 if ( amajor )
David Turner83b4a4b2002-03-06 12:42:34 +00004375 *amajor = major;
David Turner25a6e3a2002-06-10 23:03:35 +00004376
David Turnerd48575e2002-09-18 23:18:36 +00004377 if ( aminor )
David Turner83b4a4b2002-03-06 12:42:34 +00004378 *aminor = minor;
David Turner25a6e3a2002-06-10 23:03:35 +00004379
David Turnerd48575e2002-09-18 23:18:36 +00004380 if ( apatch )
David Turner83b4a4b2002-03-06 12:42:34 +00004381 *apatch = patch;
David Turner25a6e3a2002-06-10 23:03:35 +00004382 }
David Turner83b4a4b2002-03-06 12:42:34 +00004383
4384
Werner Lemberg748b1712005-12-25 09:15:09 +00004385 /* documentation is in ftmodapi.h */
Werner Lemberg90a03302000-11-07 17:21:11 +00004386
Werner Lembergf814d0f2001-06-27 16:18:10 +00004387 FT_EXPORT_DEF( FT_Error )
4388 FT_Done_Library( FT_Library library )
David Turnerf0df85b2000-06-22 00:17:42 +00004389 {
4390 FT_Memory memory;
David Turnerf0df85b2000-06-22 00:17:42 +00004391
4392
4393 if ( !library )
4394 return FT_Err_Invalid_Library_Handle;
4395
Werner Lembergfe3433c2010-07-18 18:41:47 +02004396 library->refcount--;
4397 if ( library->refcount > 0 )
4398 goto Exit;
4399
David Turnerf0df85b2000-06-22 00:17:42 +00004400 memory = library->memory;
4401
4402 /* Discard client-data */
4403 if ( library->generic.finalizer )
4404 library->generic.finalizer( library );
4405
Werner Lemberg4ea0a7f2007-01-05 09:03:31 +00004406 /* Close all faces in the library. If we don't do
David Turnera8cf42b2007-01-04 16:46:46 +00004407 * this, we can have some subtle memory leaks.
Werner Lemberg4ea0a7f2007-01-05 09:03:31 +00004408 * Example:
David Turnera8cf42b2007-01-04 16:46:46 +00004409 *
4410 * - the cff font driver uses the pshinter module in cff_size_done
4411 * - if the pshinter module is destroyed before the cff font driver,
Werner Lemberg4ea0a7f2007-01-05 09:03:31 +00004412 * opened FT_Face objects managed by the driver are not properly
David Turnera8cf42b2007-01-04 16:46:46 +00004413 * destroyed, resulting in a memory leak
4414 */
4415 {
4416 FT_UInt n;
4417
Werner Lemberg4ea0a7f2007-01-05 09:03:31 +00004418
David Turnera8cf42b2007-01-04 16:46:46 +00004419 for ( n = 0; n < library->num_modules; n++ )
4420 {
4421 FT_Module module = library->modules[n];
4422 FT_List faces;
4423
Werner Lemberg4ea0a7f2007-01-05 09:03:31 +00004424
4425 if ( ( module->clazz->module_flags & FT_MODULE_FONT_DRIVER ) == 0 )
David Turnera8cf42b2007-01-04 16:46:46 +00004426 continue;
4427
4428 faces = &FT_DRIVER(module)->faces_list;
Werner Lemberg4ea0a7f2007-01-05 09:03:31 +00004429 while ( faces->head )
Werner Lemberg9b1da082009-01-09 06:21:04 +00004430 {
Werner Lemberg4ea0a7f2007-01-05 09:03:31 +00004431 FT_Done_Face( FT_FACE( faces->head->data ) );
Werner Lemberg9b1da082009-01-09 06:21:04 +00004432 if ( faces->head )
Werner Lemberg858abbe2009-06-26 06:15:41 +02004433 FT_TRACE0(( "FT_Done_Library: failed to free some faces\n" ));
Werner Lemberg9b1da082009-01-09 06:21:04 +00004434 }
David Turnera8cf42b2007-01-04 16:46:46 +00004435 }
4436 }
4437
David Turnera8cf42b2007-01-04 16:46:46 +00004438 /* Close all other modules in the library */
Werner Lembergf41e71a2001-12-20 21:22:02 +00004439#if 1
Wu, Chia-I (吳佳一)a87b08a2006-02-28 09:53:23 +00004440 /* XXX Modules are removed in the reversed order so that */
David Turner2b21a932006-08-16 09:24:32 +00004441 /* type42 module is removed before truetype module. This */
Wu, Chia-I (吳佳一)a87b08a2006-02-28 09:53:23 +00004442 /* avoids double free in some occasions. It is a hack. */
David Turnerc8087482001-12-20 13:14:18 +00004443 while ( library->num_modules > 0 )
Wu, Chia-I (吳佳一)a87b08a2006-02-28 09:53:23 +00004444 FT_Remove_Module( library,
4445 library->modules[library->num_modules - 1] );
Werner Lembergf41e71a2001-12-20 21:22:02 +00004446#else
David Turnerf0df85b2000-06-22 00:17:42 +00004447 {
Werner Lembergf41e71a2001-12-20 21:22:02 +00004448 FT_UInt n;
David Turnerf0df85b2000-06-22 00:17:42 +00004449
Werner Lemberga929ba92000-06-25 06:47:11 +00004450
Werner Lembergf41e71a2001-12-20 21:22:02 +00004451 for ( n = 0; n < library->num_modules; n++ )
David Turnerf0df85b2000-06-22 00:17:42 +00004452 {
Werner Lembergf41e71a2001-12-20 21:22:02 +00004453 FT_Module module = library->modules[n];
4454
4455
4456 if ( module )
4457 {
4458 Destroy_Module( module );
4459 library->modules[n] = 0;
4460 }
David Turnerf0df85b2000-06-22 00:17:42 +00004461 }
4462 }
David Turnerc8087482001-12-20 13:14:18 +00004463#endif
David Turnerf0df85b2000-06-22 00:17:42 +00004464
4465 /* Destroy raster objects */
David Turnere459d742002-03-22 13:52:37 +00004466 FT_FREE( library->raster_pool );
David Turnerf0df85b2000-06-22 00:17:42 +00004467 library->raster_pool_size = 0;
4468
Oran Agra636c2942009-04-05 17:59:26 +03004469#ifdef FT_CONFIG_OPTION_PIC
4470 /* Destroy pic container contents */
4471 ft_pic_container_destroy( library );
4472#endif
4473
David Turnere459d742002-03-22 13:52:37 +00004474 FT_FREE( library );
Werner Lembergfe3433c2010-07-18 18:41:47 +02004475
4476 Exit:
David Turnerf0df85b2000-06-22 00:17:42 +00004477 return FT_Err_Ok;
4478 }
4479
4480
Werner Lemberg748b1712005-12-25 09:15:09 +00004481 /* documentation is in ftmodapi.h */
Werner Lemberg90a03302000-11-07 17:21:11 +00004482
Werner Lembergf814d0f2001-06-27 16:18:10 +00004483 FT_EXPORT_DEF( void )
4484 FT_Set_Debug_Hook( FT_Library library,
4485 FT_UInt hook_index,
4486 FT_DebugHook_Func debug_hook )
David Turnerf0df85b2000-06-22 00:17:42 +00004487 {
4488 if ( library && debug_hook &&
4489 hook_index <
4490 ( sizeof ( library->debug_hooks ) / sizeof ( void* ) ) )
4491 library->debug_hooks[hook_index] = debug_hook;
4492 }
4493
Werner Lemberg8e6f8c42006-02-17 08:07:09 +00004494
David Turner0b5dc4d2006-02-21 22:36:23 +00004495 /* documentation is in ftmodapi.h */
4496
4497 FT_EXPORT_DEF( FT_TrueTypeEngineType )
4498 FT_Get_TrueType_Engine_Type( FT_Library library )
4499 {
4500 FT_TrueTypeEngineType result = FT_TRUETYPE_ENGINE_TYPE_NONE;
4501
Werner Lemberg5edafed2006-02-22 08:23:35 +00004502
David Turner0b5dc4d2006-02-21 22:36:23 +00004503 if ( library )
4504 {
4505 FT_Module module = FT_Get_Module( library, "truetype" );
4506
Werner Lemberg5edafed2006-02-22 08:23:35 +00004507
David Turner0b5dc4d2006-02-21 22:36:23 +00004508 if ( module )
4509 {
4510 FT_Service_TrueTypeEngine service;
4511
Werner Lemberg5edafed2006-02-22 08:23:35 +00004512
David Turner6c71c6b2006-02-25 12:49:40 +00004513 service = (FT_Service_TrueTypeEngine)
4514 ft_module_get_service( module,
4515 FT_SERVICE_ID_TRUETYPE_ENGINE );
David Turner0b5dc4d2006-02-21 22:36:23 +00004516 if ( service )
4517 result = service->engine_type;
4518 }
4519 }
Werner Lemberg5edafed2006-02-22 08:23:35 +00004520
David Turner0b5dc4d2006-02-21 22:36:23 +00004521 return result;
4522 }
4523
Werner Lemberg5edafed2006-02-22 08:23:35 +00004524
David Turnercda2d952006-02-16 22:45:31 +00004525#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
Werner Lemberg8e6f8c42006-02-17 08:07:09 +00004526
David Turnercda2d952006-02-16 22:45:31 +00004527 FT_BASE_DEF( FT_Error )
4528 ft_stub_set_char_sizes( FT_Size size,
4529 FT_F26Dot6 width,
4530 FT_F26Dot6 height,
4531 FT_UInt horz_res,
4532 FT_UInt vert_res )
4533 {
4534 FT_Size_RequestRec req;
4535 FT_Driver driver = size->face->driver;
4536
Werner Lemberg8e6f8c42006-02-17 08:07:09 +00004537
David Turnercda2d952006-02-16 22:45:31 +00004538 if ( driver->clazz->request_size )
4539 {
4540 req.type = FT_SIZE_REQUEST_TYPE_NOMINAL;
4541 req.width = width;
4542 req.height = height;
4543
4544 if ( horz_res == 0 )
4545 horz_res = vert_res;
4546
4547 if ( vert_res == 0 )
4548 vert_res = horz_res;
4549
4550 if ( horz_res == 0 )
4551 horz_res = vert_res = 72;
4552
4553 req.horiResolution = horz_res;
4554 req.vertResolution = vert_res;
4555
4556 return driver->clazz->request_size( size, &req );
4557 }
Werner Lemberg8e6f8c42006-02-17 08:07:09 +00004558
David Turnercda2d952006-02-16 22:45:31 +00004559 return 0;
4560 }
4561
4562
4563 FT_BASE_DEF( FT_Error )
Werner Lemberg8e6f8c42006-02-17 08:07:09 +00004564 ft_stub_set_pixel_sizes( FT_Size size,
4565 FT_UInt width,
4566 FT_UInt height )
David Turnercda2d952006-02-16 22:45:31 +00004567 {
4568 FT_Size_RequestRec req;
4569 FT_Driver driver = size->face->driver;
4570
Werner Lemberg8e6f8c42006-02-17 08:07:09 +00004571
David Turnercda2d952006-02-16 22:45:31 +00004572 if ( driver->clazz->request_size )
4573 {
4574 req.type = FT_SIZE_REQUEST_TYPE_NOMINAL;
Werner Lemberg8e6f8c42006-02-17 08:07:09 +00004575 req.width = width << 6;
David Turnercda2d952006-02-16 22:45:31 +00004576 req.height = height << 6;
4577 req.horiResolution = 0;
4578 req.vertResolution = 0;
4579
4580 return driver->clazz->request_size( size, &req );
4581 }
Werner Lemberg8e6f8c42006-02-17 08:07:09 +00004582
David Turnercda2d952006-02-16 22:45:31 +00004583 return 0;
4584 }
Werner Lemberg8e6f8c42006-02-17 08:07:09 +00004585
David Turnercda2d952006-02-16 22:45:31 +00004586#endif /* FT_CONFIG_OPTION_OLD_INTERNALS */
David Turnerf0df85b2000-06-22 00:17:42 +00004587
David Turner2b21a932006-08-16 09:24:32 +00004588
Werner Lemberge30de292010-05-22 20:03:41 +02004589 /* documentation is in freetype.h */
4590
David Turner2ce92032006-03-23 20:58:20 +00004591 FT_EXPORT_DEF( FT_Error )
4592 FT_Get_SubGlyph_Info( FT_GlyphSlot glyph,
4593 FT_UInt sub_index,
Werner Lemberg4db32ec2006-03-24 11:54:53 +00004594 FT_Int *p_index,
4595 FT_UInt *p_flags,
4596 FT_Int *p_arg1,
4597 FT_Int *p_arg2,
4598 FT_Matrix *p_transform )
David Turner2ce92032006-03-23 20:58:20 +00004599 {
Werner Lemberg4db32ec2006-03-24 11:54:53 +00004600 FT_Error error = FT_Err_Invalid_Argument;
Werner Lemberg4db32ec2006-03-24 11:54:53 +00004601
David Turner2b21a932006-08-16 09:24:32 +00004602
Werner Lemberge30de292010-05-22 20:03:41 +02004603 if ( glyph &&
4604 glyph->subglyphs &&
Werner Lemberg4db32ec2006-03-24 11:54:53 +00004605 glyph->format == FT_GLYPH_FORMAT_COMPOSITE &&
4606 sub_index < glyph->num_subglyphs )
4607 {
David Turner2ce92032006-03-23 20:58:20 +00004608 FT_SubGlyph subg = glyph->subglyphs + sub_index;
David Turner2b21a932006-08-16 09:24:32 +00004609
Werner Lemberg4db32ec2006-03-24 11:54:53 +00004610
4611 *p_index = subg->index;
4612 *p_flags = subg->flags;
4613 *p_arg1 = subg->arg1;
4614 *p_arg2 = subg->arg2;
4615 *p_transform = subg->transform;
4616 }
4617
4618 return error;
David Turner2ce92032006-03-23 20:58:20 +00004619 }
4620
Werner Lemberg4db32ec2006-03-24 11:54:53 +00004621
David Turnerd2b1f351999-12-16 23:11:37 +00004622/* END */