blob: 89892df57c9be7695ba984062dd540d2318591ee [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 Lemberg9bf73ec2009-01-13 17:42:00 +00007/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 by */
Werner Lemberg4e6dd852000-06-05 05:26:15 +00008/* David Turner, Robert Wilhelm, and Werner Lemberg. */
David Turnerd2b1f351999-12-16 23:11:37 +00009/* */
Werner Lemberg4e6dd852000-06-05 05:26:15 +000010/* This file is part of the FreeType project, and may only be used, */
11/* modified, and distributed under the terms of the FreeType project */
David Turnerd2b1f351999-12-16 23:11:37 +000012/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
13/* this file you indicate that you have read the license and */
14/* understand and accept it fully. */
15/* */
16/***************************************************************************/
17
Werner Lembergcc069be2000-12-08 16:17:16 +000018
19#include <ft2build.h>
20#include FT_LIST_H
David Turner7fe38a52002-01-04 09:47:30 +000021#include FT_OUTLINE_H
Werner Lemberg645af082004-09-06 07:06:56 +000022#include FT_INTERNAL_VALIDATE_H
Werner Lembergcc069be2000-12-08 16:17:16 +000023#include FT_INTERNAL_OBJECTS_H
24#include FT_INTERNAL_DEBUG_H
Werner Lemberg75435332004-02-25 12:58:54 +000025#include FT_INTERNAL_RFORK_H
Werner Lembergcc069be2000-12-08 16:17:16 +000026#include FT_INTERNAL_STREAM_H
David Turner621e4882002-12-16 21:51:24 +000027#include FT_INTERNAL_SFNT_H /* for SFNT_Load_Table_Func */
Werner Lembergcc069be2000-12-08 16:17:16 +000028#include FT_TRUETYPE_TABLES_H
Suzuki, Toshiya (鈴木俊哉)af48cb02008-10-05 02:53:06 +000029#include FT_TRUETYPE_TAGS_H
Antoine Lecac96f69d2002-12-03 00:39:16 +000030#include FT_TRUETYPE_IDS_H
David Turnerf86709a2002-01-07 10:04:09 +000031#include FT_OUTLINE_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
Suzuki, Toshiya (鈴木俊哉)f4147022008-10-02 01:43:18 +000040#include "ftbase.h"
41
Wu, Chia-I (吳佳一)2e48a1a2006-02-27 09:18:07 +000042#define GRID_FIT_METRICS
Werner Lemberg013efd12003-09-17 05:26:33 +000043
Werner Lembergb972a2a2008-12-11 08:55:48 +000044
David Turnerc313c502003-09-11 19:51:54 +000045 FT_BASE_DEF( FT_Pointer )
46 ft_service_list_lookup( FT_ServiceDesc service_descriptors,
47 const char* service_id )
48 {
49 FT_Pointer result = NULL;
50 FT_ServiceDesc desc = service_descriptors;
David Turnere2d12842003-09-21 17:15:55 +000051
Werner Lemberg013efd12003-09-17 05:26:33 +000052
David Turnerc313c502003-09-11 19:51:54 +000053 if ( desc && service_id )
54 {
55 for ( ; desc->serv_id != NULL; desc++ )
56 {
57 if ( ft_strcmp( desc->serv_id, service_id ) == 0 )
58 {
Werner Lemberg013efd12003-09-17 05:26:33 +000059 result = (FT_Pointer)desc->serv_data;
David Turnerc313c502003-09-11 19:51:54 +000060 break;
61 }
62 }
63 }
Werner Lemberg013efd12003-09-17 05:26:33 +000064
David Turnerc313c502003-09-11 19:51:54 +000065 return result;
David Turnere2d12842003-09-21 17:15:55 +000066 }
Werner Lemberg3c403e42002-08-06 21:47:40 +000067
Werner Lemberg013efd12003-09-17 05:26:33 +000068
David Turnered54f282002-03-22 17:09:52 +000069 FT_BASE_DEF( void )
70 ft_validator_init( FT_Validator valid,
71 const FT_Byte* base,
72 const FT_Byte* limit,
73 FT_ValidationLevel level )
74 {
75 valid->base = base;
76 valid->limit = limit;
77 valid->level = level;
Werner Lemberg8acb8672005-03-08 11:43:36 +000078 valid->error = FT_Err_Ok;
David Turnered54f282002-03-22 17:09:52 +000079 }
David Turner25a6e3a2002-06-10 23:03:35 +000080
David Turnered54f282002-03-22 17:09:52 +000081
82 FT_BASE_DEF( FT_Int )
83 ft_validator_run( FT_Validator valid )
84 {
Werner Lemberg12342992006-08-19 11:18:09 +000085 /* This function doesn't work! None should call it. */
86 FT_UNUSED( valid );
87
David Turner2b21a932006-08-16 09:24:32 +000088 return -1;
David Turnered54f282002-03-22 17:09:52 +000089 }
90
Werner Lembergf8ba2002002-03-30 13:16:35 +000091
David Turnered54f282002-03-22 17:09:52 +000092 FT_BASE_DEF( void )
93 ft_validator_error( FT_Validator valid,
94 FT_Error error )
95 {
Jens Claudiusa787f452006-08-27 11:26:18 +000096 /* since the cast below also disables the compiler's */
97 /* type check, we introduce a dummy variable, which */
98 /* will be optimized away */
Werner Lemberg607dec72007-05-15 06:49:37 +000099 volatile ft_jmp_buf* jump_buffer = &valid->jump_buffer;
Jens Claudiusa787f452006-08-27 11:26:18 +0000100
101
David Turnered54f282002-03-22 17:09:52 +0000102 valid->error = error;
Jens Claudiusa787f452006-08-27 11:26:18 +0000103
104 /* throw away volatileness; use `jump_buffer' or the */
105 /* compiler may warn about an unused local variable */
Werner Lemberg607dec72007-05-15 06:49:37 +0000106 ft_longjmp( *(ft_jmp_buf*) jump_buffer, 1 );
David Turner25a6e3a2002-06-10 23:03:35 +0000107 }
Werner Lemberga929ba92000-06-25 06:47:11 +0000108
Werner Lemberga3b6c6c2000-05-31 06:55:12 +0000109
David Turnerd2b1f351999-12-16 23:11:37 +0000110 /*************************************************************************/
111 /*************************************************************************/
112 /*************************************************************************/
113 /**** ****/
114 /**** ****/
David Turnerf0df85b2000-06-22 00:17:42 +0000115 /**** S T R E A M ****/
116 /**** ****/
117 /**** ****/
118 /*************************************************************************/
119 /*************************************************************************/
120 /*************************************************************************/
121
Werner Lemberg7880dd62000-01-10 17:19:45 +0000122
Werner Lemberg75435332004-02-25 12:58:54 +0000123 /* create a new input stream from an FT_Open_Args structure */
124 /* */
125 FT_BASE_DEF( FT_Error )
126 FT_Stream_New( FT_Library library,
127 const FT_Open_Args* args,
128 FT_Stream *astream )
David Turner7663f222000-02-13 13:37:38 +0000129 {
Werner Lemberg547a2522000-02-16 08:23:58 +0000130 FT_Error error;
131 FT_Memory memory;
132 FT_Stream stream;
133
Werner Lemberga3b6c6c2000-05-31 06:55:12 +0000134
Suzuki, Toshiya (鈴木俊哉)4c60bd92008-08-19 15:35:44 +0000135 *astream = 0;
136
Werner Lemberg2fbf7e42000-06-02 00:01:14 +0000137 if ( !library )
138 return FT_Err_Invalid_Library_Handle;
139
140 if ( !args )
141 return FT_Err_Invalid_Argument;
142
David Turner37379e22000-03-28 11:22:31 +0000143 memory = library->memory;
Werner Lembergf8ba2002002-03-30 13:16:35 +0000144
David Turnere459d742002-03-22 13:52:37 +0000145 if ( FT_NEW( stream ) )
David Turner37379e22000-03-28 11:22:31 +0000146 goto Exit;
David Turnere49ab252000-05-16 23:44:38 +0000147
David Turner7663f222000-02-13 13:37:38 +0000148 stream->memory = memory;
David Turnere49ab252000-05-16 23:44:38 +0000149
David Turnerb08fe2d2002-08-27 20:20:29 +0000150 if ( args->flags & FT_OPEN_MEMORY )
Just van Rossumd35aea72000-03-02 01:07:50 +0000151 {
David Turner53b3fa12002-02-24 05:26:57 +0000152 /* create a memory-based stream */
David Turner7d3a2642002-03-20 10:49:31 +0000153 FT_Stream_OpenMemory( stream,
Werner Lembergf8ba2002002-03-30 13:16:35 +0000154 (const FT_Byte*)args->memory_base,
155 args->memory_size );
David Turner4f2c5542000-05-12 10:19:41 +0000156 }
David Turnerb08fe2d2002-08-27 20:20:29 +0000157 else if ( args->flags & FT_OPEN_PATHNAME )
David Turner4f2c5542000-05-12 10:19:41 +0000158 {
David Turner53b3fa12002-02-24 05:26:57 +0000159 /* create a normal system stream */
160 error = FT_Stream_Open( stream, args->pathname );
David Turner4f2c5542000-05-12 10:19:41 +0000161 stream->pathname.pointer = args->pathname;
162 }
David Turnerb08fe2d2002-08-27 20:20:29 +0000163 else if ( ( args->flags & FT_OPEN_STREAM ) && args->stream )
David Turner4f2c5542000-05-12 10:19:41 +0000164 {
David Turner53b3fa12002-02-24 05:26:57 +0000165 /* use an existing, user-provided stream */
166
Werner Lemberg58b17f92000-07-27 23:29:08 +0000167 /* in this case, we do not need to allocate a new stream object */
168 /* since the caller is responsible for closing it himself */
David Turnere459d742002-03-22 13:52:37 +0000169 FT_FREE( stream );
David Turnerc5cdf8b2000-07-27 21:40:22 +0000170 stream = args->stream;
David Turner4f2c5542000-05-12 10:19:41 +0000171 }
172 else
David Turner4f2c5542000-05-12 10:19:41 +0000173 error = FT_Err_Invalid_Argument;
David Turnere49ab252000-05-16 23:44:38 +0000174
Werner Lemberg547a2522000-02-16 08:23:58 +0000175 if ( error )
David Turnere459d742002-03-22 13:52:37 +0000176 FT_FREE( stream );
David Turner53b3fa12002-02-24 05:26:57 +0000177 else
178 stream->memory = memory; /* just to be certain */
David Turnere49ab252000-05-16 23:44:38 +0000179
David Turner7663f222000-02-13 13:37:38 +0000180 *astream = stream;
Werner Lemberga3b6c6c2000-05-31 06:55:12 +0000181
David Turner37379e22000-03-28 11:22:31 +0000182 Exit:
David Turner7663f222000-02-13 13:37:38 +0000183 return error;
184 }
185
186
Werner Lemberg75435332004-02-25 12:58:54 +0000187 FT_BASE_DEF( void )
188 FT_Stream_Free( FT_Stream stream,
189 FT_Int external )
David Turner7663f222000-02-13 13:37:38 +0000190 {
David Turner53b3fa12002-02-24 05:26:57 +0000191 if ( stream )
David Turnerc5cdf8b2000-07-27 21:40:22 +0000192 {
193 FT_Memory memory = stream->memory;
Werner Lemberg58b17f92000-07-27 23:29:08 +0000194
Werner Lembergf8ba2002002-03-30 13:16:35 +0000195
David Turner53b3fa12002-02-24 05:26:57 +0000196 FT_Stream_Close( stream );
Werner Lemberg58b17f92000-07-27 23:29:08 +0000197
David Turner53b3fa12002-02-24 05:26:57 +0000198 if ( !external )
David Turnere459d742002-03-22 13:52:37 +0000199 FT_FREE( stream );
David Turnerc5cdf8b2000-07-27 21:40:22 +0000200 }
David Turner7663f222000-02-13 13:37:38 +0000201 }
202
Werner Lemberga3b6c6c2000-05-31 06:55:12 +0000203
Werner Lemberg6874d852008-09-20 11:50:47 +0000204 /*************************************************************************/
205 /* */
206 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
207 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
208 /* messages during execution. */
209 /* */
Werner Lembergeb81e372000-06-03 06:03:11 +0000210#undef FT_COMPONENT
211#define FT_COMPONENT trace_objs
212
Werner Lembergdeb4e982000-06-29 03:14:25 +0000213
David Turnerf0df85b2000-06-22 00:17:42 +0000214 /*************************************************************************/
215 /*************************************************************************/
216 /*************************************************************************/
217 /**** ****/
218 /**** ****/
219 /**** FACE, SIZE & GLYPH SLOT OBJECTS ****/
220 /**** ****/
221 /**** ****/
222 /*************************************************************************/
223 /*************************************************************************/
224 /*************************************************************************/
225
Werner Lembergdeb4e982000-06-29 03:14:25 +0000226
Werner Lembergf814d0f2001-06-27 16:18:10 +0000227 static FT_Error
228 ft_glyphslot_init( FT_GlyphSlot slot )
David Turnerf0df85b2000-06-22 00:17:42 +0000229 {
230 FT_Driver driver = slot->face->driver;
Werner Lembergf8ba2002002-03-30 13:16:35 +0000231 FT_Driver_Class clazz = driver->clazz;
David Turnerf0df85b2000-06-22 00:17:42 +0000232 FT_Memory memory = driver->root.memory;
233 FT_Error error = FT_Err_Ok;
David Turner54e75742000-11-04 02:52:02 +0000234 FT_Slot_Internal internal;
David Turnerf0df85b2000-06-22 00:17:42 +0000235
Werner Lemberga8bbc262000-07-01 14:06:46 +0000236
David Turnerf9ca2bb2000-06-30 23:12:55 +0000237 slot->library = driver->root.library;
Werner Lembergfbeb41d2000-07-02 00:27:53 +0000238
David Turnere459d742002-03-22 13:52:37 +0000239 if ( FT_NEW( internal ) )
David Turner54e75742000-11-04 02:52:02 +0000240 goto Exit;
241
242 slot->internal = internal;
243
Werner Lemberga929ba92000-06-25 06:47:11 +0000244 if ( FT_DRIVER_USES_OUTLINES( driver ) )
David Turner54e75742000-11-04 02:52:02 +0000245 error = FT_GlyphLoader_New( memory, &internal->loader );
David Turnerf0df85b2000-06-22 00:17:42 +0000246
Werner Lemberga929ba92000-06-25 06:47:11 +0000247 if ( !error && clazz->init_slot )
David Turnerf0df85b2000-06-22 00:17:42 +0000248 error = clazz->init_slot( slot );
249
David Turner54e75742000-11-04 02:52:02 +0000250 Exit:
David Turnerf0df85b2000-06-22 00:17:42 +0000251 return error;
252 }
253
Werner Lemberge20ab692003-06-02 07:24:33 +0000254
David Turner66cbc202003-03-20 07:04:40 +0000255 FT_BASE_DEF( void )
256 ft_glyphslot_free_bitmap( FT_GlyphSlot slot )
257 {
Werner Lembergb6192822008-11-08 07:28:39 +0000258 if ( slot->internal && ( slot->internal->flags & FT_GLYPH_OWN_BITMAP ) )
David Turner66cbc202003-03-20 07:04:40 +0000259 {
260 FT_Memory memory = FT_FACE_MEMORY( slot->face );
Werner Lemberg51daa4f2003-05-18 22:40:11 +0000261
262
David Turner66cbc202003-03-20 07:04:40 +0000263 FT_FREE( slot->bitmap.buffer );
Werner Lemberg7a024102003-06-18 06:59:57 +0000264 slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP;
David Turner66cbc202003-03-20 07:04:40 +0000265 }
266 else
267 {
268 /* assume that the bitmap buffer was stolen or not */
269 /* allocated from the heap */
270 slot->bitmap.buffer = NULL;
271 }
272 }
273
274
275 FT_BASE_DEF( void )
276 ft_glyphslot_set_bitmap( FT_GlyphSlot slot,
Werner Lemberg319c00d2003-04-23 19:48:24 +0000277 FT_Byte* buffer )
David Turner66cbc202003-03-20 07:04:40 +0000278 {
279 ft_glyphslot_free_bitmap( slot );
Werner Lemberg51daa4f2003-05-18 22:40:11 +0000280
David Turner66cbc202003-03-20 07:04:40 +0000281 slot->bitmap.buffer = buffer;
Werner Lemberg51daa4f2003-05-18 22:40:11 +0000282
Werner Lemberg7a024102003-06-18 06:59:57 +0000283 FT_ASSERT( (slot->internal->flags & FT_GLYPH_OWN_BITMAP) == 0 );
Werner Lemberg51daa4f2003-05-18 22:40:11 +0000284 }
David Turner66cbc202003-03-20 07:04:40 +0000285
286
287 FT_BASE_DEF( FT_Error )
288 ft_glyphslot_alloc_bitmap( FT_GlyphSlot slot,
289 FT_ULong size )
290 {
Werner Lembergbe3c9812006-01-27 14:16:16 +0000291 FT_Memory memory = FT_FACE_MEMORY( slot->face );
292 FT_Error error;
Werner Lemberg51daa4f2003-05-18 22:40:11 +0000293
294
Werner Lemberg7a024102003-06-18 06:59:57 +0000295 if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP )
David Turner66cbc202003-03-20 07:04:40 +0000296 FT_FREE( slot->bitmap.buffer );
297 else
Werner Lemberg7a024102003-06-18 06:59:57 +0000298 slot->internal->flags |= FT_GLYPH_OWN_BITMAP;
Werner Lemberg51daa4f2003-05-18 22:40:11 +0000299
David Turner6a681fa2006-01-27 12:11:22 +0000300 (void)FT_ALLOC( slot->bitmap.buffer, size );
301 return error;
Werner Lemberg51daa4f2003-05-18 22:40:11 +0000302 }
David Turner66cbc202003-03-20 07:04:40 +0000303
David Turnerf0df85b2000-06-22 00:17:42 +0000304
Werner Lembergf814d0f2001-06-27 16:18:10 +0000305 static void
306 ft_glyphslot_clear( FT_GlyphSlot slot )
David Turnerf0df85b2000-06-22 00:17:42 +0000307 {
David Turner5ae831c2000-06-30 01:31:22 +0000308 /* free bitmap if needed */
David Turner66cbc202003-03-20 07:04:40 +0000309 ft_glyphslot_free_bitmap( slot );
Werner Lembergfbeb41d2000-07-02 00:27:53 +0000310
David Turnerf0df85b2000-06-22 00:17:42 +0000311 /* clear all public fields in the glyph slot */
David Turner3249c622002-10-31 08:30:19 +0000312 FT_ZERO( &slot->metrics );
313 FT_ZERO( &slot->outline );
314
Werner Lemberg0f1c4fa2005-06-06 07:01:47 +0000315 slot->bitmap.width = 0;
316 slot->bitmap.rows = 0;
317 slot->bitmap.pitch = 0;
David Turner3249c622002-10-31 08:30:19 +0000318 slot->bitmap.pixel_mode = 0;
Werner Lemberg0f1c4fa2005-06-06 07:01:47 +0000319 /* `slot->bitmap.buffer' has been handled by ft_glyphslot_free_bitmap */
David Turnerf0df85b2000-06-22 00:17:42 +0000320
321 slot->bitmap_left = 0;
322 slot->bitmap_top = 0;
323 slot->num_subglyphs = 0;
324 slot->subglyphs = 0;
325 slot->control_data = 0;
326 slot->control_len = 0;
327 slot->other = 0;
David Turnerb08fe2d2002-08-27 20:20:29 +0000328 slot->format = FT_GLYPH_FORMAT_NONE;
David Turnerf0df85b2000-06-22 00:17:42 +0000329
330 slot->linearHoriAdvance = 0;
331 slot->linearVertAdvance = 0;
Werner Lemberg34f4f392004-12-09 22:22:52 +0000332 slot->lsb_delta = 0;
333 slot->rsb_delta = 0;
David Turnerf0df85b2000-06-22 00:17:42 +0000334 }
335
336
Werner Lembergf814d0f2001-06-27 16:18:10 +0000337 static void
338 ft_glyphslot_done( FT_GlyphSlot slot )
David Turnerf0df85b2000-06-22 00:17:42 +0000339 {
Werner Lemberg9cc4aed2006-01-26 21:03:58 +0000340 FT_Driver driver = slot->face->driver;
341 FT_Driver_Class clazz = driver->clazz;
342 FT_Memory memory = driver->root.memory;
David Turnerf0df85b2000-06-22 00:17:42 +0000343
Werner Lemberga929ba92000-06-25 06:47:11 +0000344
David Turner54e75742000-11-04 02:52:02 +0000345 if ( clazz->done_slot )
346 clazz->done_slot( slot );
347
David Turnerf0df85b2000-06-22 00:17:42 +0000348 /* free bitmap buffer if needed */
David Turner66cbc202003-03-20 07:04:40 +0000349 ft_glyphslot_free_bitmap( slot );
David Turnerf0df85b2000-06-22 00:17:42 +0000350
351 /* free glyph loader */
Werner Lemberga929ba92000-06-25 06:47:11 +0000352 if ( FT_DRIVER_USES_OUTLINES( driver ) )
David Turnerf0df85b2000-06-22 00:17:42 +0000353 {
David Turner54e75742000-11-04 02:52:02 +0000354 FT_GlyphLoader_Done( slot->internal->loader );
355 slot->internal->loader = 0;
David Turnerf0df85b2000-06-22 00:17:42 +0000356 }
357
David Turnere459d742002-03-22 13:52:37 +0000358 FT_FREE( slot->internal );
David Turnerf0df85b2000-06-22 00:17:42 +0000359 }
360
361
Werner Lemberg8ec9dfd2000-11-07 23:56:02 +0000362 /* documentation is in ftobjs.h */
363
Werner Lembergf814d0f2001-06-27 16:18:10 +0000364 FT_BASE_DEF( FT_Error )
365 FT_New_GlyphSlot( FT_Face face,
366 FT_GlyphSlot *aslot )
David Turnerf0df85b2000-06-22 00:17:42 +0000367 {
Werner Lemberg9cc4aed2006-01-26 21:03:58 +0000368 FT_Error error;
369 FT_Driver driver;
370 FT_Driver_Class clazz;
371 FT_Memory memory;
372 FT_GlyphSlot slot;
Werner Lemberga929ba92000-06-25 06:47:11 +0000373
David Turnerf0df85b2000-06-22 00:17:42 +0000374
Werner Lembergb9ee7372005-05-20 21:52:19 +0000375 if ( !face || !face->driver )
David Turnerf0df85b2000-06-22 00:17:42 +0000376 return FT_Err_Invalid_Argument;
377
378 driver = face->driver;
379 clazz = driver->clazz;
380 memory = driver->root.memory;
381
382 FT_TRACE4(( "FT_New_GlyphSlot: Creating new slot object\n" ));
David Turnere459d742002-03-22 13:52:37 +0000383 if ( !FT_ALLOC( slot, clazz->slot_object_size ) )
David Turnerf0df85b2000-06-22 00:17:42 +0000384 {
385 slot->face = face;
386
387 error = ft_glyphslot_init( slot );
Werner Lemberga929ba92000-06-25 06:47:11 +0000388 if ( error )
David Turnerf0df85b2000-06-22 00:17:42 +0000389 {
390 ft_glyphslot_done( slot );
David Turnere459d742002-03-22 13:52:37 +0000391 FT_FREE( slot );
David Turnerf0df85b2000-06-22 00:17:42 +0000392 goto Exit;
393 }
394
Werner Lembergb9ee7372005-05-20 21:52:19 +0000395 slot->next = face->glyph;
396 face->glyph = slot;
397
398 if ( aslot )
399 *aslot = slot;
David Turnerf0df85b2000-06-22 00:17:42 +0000400 }
Werner Lembergb9ee7372005-05-20 21:52:19 +0000401 else if ( aslot )
402 *aslot = 0;
403
David Turnerf0df85b2000-06-22 00:17:42 +0000404
405 Exit:
406 FT_TRACE4(( "FT_New_GlyphSlot: Return %d\n", error ));
407 return error;
408 }
409
410
Werner Lemberg8ec9dfd2000-11-07 23:56:02 +0000411 /* documentation is in ftobjs.h */
412
Werner Lembergf814d0f2001-06-27 16:18:10 +0000413 FT_BASE_DEF( void )
414 FT_Done_GlyphSlot( FT_GlyphSlot slot )
David Turnerf0df85b2000-06-22 00:17:42 +0000415 {
416 if ( slot )
417 {
Werner Lembergb9ee7372005-05-20 21:52:19 +0000418 FT_Driver driver = slot->face->driver;
419 FT_Memory memory = driver->root.memory;
420 FT_GlyphSlot prev;
421 FT_GlyphSlot cur;
David Turnerf0df85b2000-06-22 00:17:42 +0000422
Werner Lemberga929ba92000-06-25 06:47:11 +0000423
David Turnerf0df85b2000-06-22 00:17:42 +0000424 /* Remove slot from its parent face's list */
Werner Lembergb9ee7372005-05-20 21:52:19 +0000425 prev = NULL;
426 cur = slot->face->glyph;
Werner Lemberga929ba92000-06-25 06:47:11 +0000427
David Turnerf0df85b2000-06-22 00:17:42 +0000428 while ( cur )
429 {
430 if ( cur == slot )
431 {
Werner Lembergb9ee7372005-05-20 21:52:19 +0000432 if ( !prev )
433 slot->face->glyph = cur->next;
434 else
435 prev->next = cur->next;
436
Werner Lemberga929ba92000-06-25 06:47:11 +0000437 ft_glyphslot_done( slot );
David Turnere459d742002-03-22 13:52:37 +0000438 FT_FREE( slot );
David Turnerf0df85b2000-06-22 00:17:42 +0000439 break;
440 }
Werner Lembergb9ee7372005-05-20 21:52:19 +0000441 prev = cur;
442 cur = cur->next;
David Turnerf0df85b2000-06-22 00:17:42 +0000443 }
444 }
445 }
446
447
Werner Lemberg90a03302000-11-07 17:21:11 +0000448 /* documentation is in freetype.h */
449
Werner Lembergf814d0f2001-06-27 16:18:10 +0000450 FT_EXPORT_DEF( void )
451 FT_Set_Transform( FT_Face face,
452 FT_Matrix* matrix,
453 FT_Vector* delta )
David Turnerf0df85b2000-06-22 00:17:42 +0000454 {
David Turner54e75742000-11-04 02:52:02 +0000455 FT_Face_Internal internal;
David Turner61d6b2b2001-05-16 17:49:07 +0000456
David Turner54e75742000-11-04 02:52:02 +0000457
David Turnerf0df85b2000-06-22 00:17:42 +0000458 if ( !face )
459 return;
460
David Turner54e75742000-11-04 02:52:02 +0000461 internal = face->internal;
462
463 internal->transform_flags = 0;
David Turnerf0df85b2000-06-22 00:17:42 +0000464
465 if ( !matrix )
466 {
David Turner54e75742000-11-04 02:52:02 +0000467 internal->transform_matrix.xx = 0x10000L;
468 internal->transform_matrix.xy = 0;
469 internal->transform_matrix.yx = 0;
470 internal->transform_matrix.yy = 0x10000L;
471 matrix = &internal->transform_matrix;
David Turnerf0df85b2000-06-22 00:17:42 +0000472 }
473 else
David Turner54e75742000-11-04 02:52:02 +0000474 internal->transform_matrix = *matrix;
David Turnerf0df85b2000-06-22 00:17:42 +0000475
476 /* set transform_flags bit flag 0 if `matrix' isn't the identity */
477 if ( ( matrix->xy | matrix->yx ) ||
478 matrix->xx != 0x10000L ||
479 matrix->yy != 0x10000L )
David Turner54e75742000-11-04 02:52:02 +0000480 internal->transform_flags |= 1;
David Turnerf0df85b2000-06-22 00:17:42 +0000481
482 if ( !delta )
483 {
David Turner54e75742000-11-04 02:52:02 +0000484 internal->transform_delta.x = 0;
485 internal->transform_delta.y = 0;
486 delta = &internal->transform_delta;
David Turnerf0df85b2000-06-22 00:17:42 +0000487 }
488 else
David Turner54e75742000-11-04 02:52:02 +0000489 internal->transform_delta = *delta;
David Turnerf0df85b2000-06-22 00:17:42 +0000490
491 /* set transform_flags bit flag 1 if `delta' isn't the null vector */
492 if ( delta->x | delta->y )
David Turner54e75742000-11-04 02:52:02 +0000493 internal->transform_flags |= 2;
David Turnerf0df85b2000-06-22 00:17:42 +0000494 }
495
496
Werner Lembergf814d0f2001-06-27 16:18:10 +0000497 static FT_Renderer
498 ft_lookup_glyph_renderer( FT_GlyphSlot slot );
Werner Lembergdeb4e982000-06-29 03:14:25 +0000499
500
Wu, Chia-I (吳佳一)2e48a1a2006-02-27 09:18:07 +0000501#ifdef GRID_FIT_METRICS
502 static void
503 ft_glyphslot_grid_fit_metrics( FT_GlyphSlot slot,
504 FT_Bool vertical )
505 {
506 FT_Glyph_Metrics* metrics = &slot->metrics;
507 FT_Pos right, bottom;
508
509
510 if ( vertical )
511 {
512 metrics->horiBearingX = FT_PIX_FLOOR( metrics->horiBearingX );
513 metrics->horiBearingY = FT_PIX_CEIL ( metrics->horiBearingY );
514
515 right = FT_PIX_CEIL( metrics->vertBearingX + metrics->width );
516 bottom = FT_PIX_CEIL( metrics->vertBearingY + metrics->height );
517
518 metrics->vertBearingX = FT_PIX_FLOOR( metrics->vertBearingX );
519 metrics->vertBearingY = FT_PIX_FLOOR( metrics->vertBearingY );
520
521 metrics->width = right - metrics->vertBearingX;
522 metrics->height = bottom - metrics->vertBearingY;
523 }
524 else
525 {
526 metrics->vertBearingX = FT_PIX_FLOOR( metrics->vertBearingX );
527 metrics->vertBearingY = FT_PIX_FLOOR( metrics->vertBearingY );
528
529 right = FT_PIX_CEIL ( metrics->horiBearingX + metrics->width );
530 bottom = FT_PIX_FLOOR( metrics->horiBearingY - metrics->height );
531
532 metrics->horiBearingX = FT_PIX_FLOOR( metrics->horiBearingX );
533 metrics->horiBearingY = FT_PIX_CEIL ( metrics->horiBearingY );
534
535 metrics->width = right - metrics->horiBearingX;
536 metrics->height = metrics->horiBearingY - bottom;
537 }
538
539 metrics->horiAdvance = FT_PIX_ROUND( metrics->horiAdvance );
540 metrics->vertAdvance = FT_PIX_ROUND( metrics->vertAdvance );
541 }
542#endif /* GRID_FIT_METRICS */
543
544
Werner Lemberg90a03302000-11-07 17:21:11 +0000545 /* documentation is in freetype.h */
546
Werner Lembergf814d0f2001-06-27 16:18:10 +0000547 FT_EXPORT_DEF( FT_Error )
Werner Lemberg6b5c6692002-09-05 15:10:54 +0000548 FT_Load_Glyph( FT_Face face,
549 FT_UInt glyph_index,
550 FT_Int32 load_flags )
David Turnerf0df85b2000-06-22 00:17:42 +0000551 {
552 FT_Error error;
553 FT_Driver driver;
554 FT_GlyphSlot slot;
David Turner5ae831c2000-06-30 01:31:22 +0000555 FT_Library library;
Werner Lembergb972a2a2008-12-11 08:55:48 +0000556 FT_Bool autohint = FALSE;
David Turner5ae831c2000-06-30 01:31:22 +0000557 FT_Module hinter;
David Turnerf0df85b2000-06-22 00:17:42 +0000558
Werner Lemberga929ba92000-06-25 06:47:11 +0000559
David Turnerf0df85b2000-06-22 00:17:42 +0000560 if ( !face || !face->size || !face->glyph )
561 return FT_Err_Invalid_Face_Handle;
562
Werner Lemberg913a3652006-11-19 09:19:17 +0000563 /* The validity test for `glyph_index' is performed by the */
564 /* font drivers. */
David Turnerf0df85b2000-06-22 00:17:42 +0000565
566 slot = face->glyph;
567 ft_glyphslot_clear( slot );
568
Wu, Chia-I (吳佳一)e5ff0592006-01-15 06:00:49 +0000569 driver = face->driver;
570 library = driver->root.library;
571 hinter = library->auto_hinter;
David Turnerf0df85b2000-06-22 00:17:42 +0000572
Wu, Chia-I (吳佳一)e5ff0592006-01-15 06:00:49 +0000573 /* resolve load flags dependencies */
574
David Turnerf0df85b2000-06-22 00:17:42 +0000575 if ( load_flags & FT_LOAD_NO_RECURSE )
Werner Lembergeddd9902000-10-12 05:05:40 +0000576 load_flags |= FT_LOAD_NO_SCALE |
David Turnerc9ce9e42000-09-15 17:16:49 +0000577 FT_LOAD_IGNORE_TRANSFORM;
Werner Lembergeddd9902000-10-12 05:05:40 +0000578
Wu, Chia-I (吳佳一)e5ff0592006-01-15 06:00:49 +0000579 if ( load_flags & FT_LOAD_NO_SCALE )
580 {
581 load_flags |= FT_LOAD_NO_HINTING |
582 FT_LOAD_NO_BITMAP;
583
Werner Lembergeddd9902000-10-12 05:05:40 +0000584 load_flags &= ~FT_LOAD_RENDER;
David Turnerc9ce9e42000-09-15 17:16:49 +0000585 }
David Turnerf0df85b2000-06-22 00:17:42 +0000586
Werner Lemberg046bf8b2006-10-03 08:43:42 +0000587 /*
588 * Determine whether we need to auto-hint or not.
589 * The general rules are:
590 *
591 * - Do only auto-hinting if we have a hinter module,
592 * a scalable font format dealing with outlines,
593 * and no transforms except simple slants.
594 *
595 * - Then, autohint if FT_LOAD_FORCE_AUTOHINT is set
596 * or if we don't have a native font hinter.
597 *
598 * - Otherwise, auto-hint for LIGHT hinting mode.
599 *
Werner Lembergb972a2a2008-12-11 08:55:48 +0000600 * - Exception: The font is `tricky' and requires
601 * the native hinter to load properly.
Werner Lemberg046bf8b2006-10-03 08:43:42 +0000602 */
David Turnere6bb9532005-12-23 13:32:06 +0000603
Werner Lembergb972a2a2008-12-11 08:55:48 +0000604 if ( hinter &&
605 !( load_flags & FT_LOAD_NO_HINTING ) &&
606 !( load_flags & FT_LOAD_NO_AUTOHINT ) &&
607 FT_DRIVER_IS_SCALABLE( driver ) &&
608 FT_DRIVER_USES_OUTLINES( driver ) &&
609 !FT_IS_TRICKY( face ) &&
610 face->internal->transform_matrix.yy > 0 &&
611 face->internal->transform_matrix.yx == 0 )
David Turner5ae831c2000-06-30 01:31:22 +0000612 {
Werner Lembergb972a2a2008-12-11 08:55:48 +0000613 if ( ( load_flags & FT_LOAD_FORCE_AUTOHINT ) ||
614 !FT_DRIVER_HAS_HINTER( driver ) )
615 autohint = TRUE;
David Turnerdf430e12006-10-01 00:09:35 +0000616 else
617 {
Werner Lemberg046bf8b2006-10-03 08:43:42 +0000618 FT_Render_Mode mode = FT_LOAD_TARGET_MODE( load_flags );
619
David Turnerdf430e12006-10-01 00:09:35 +0000620
621 if ( mode == FT_RENDER_MODE_LIGHT ||
622 face->internal->ignore_unpatented_hinter )
Werner Lembergb972a2a2008-12-11 08:55:48 +0000623 autohint = TRUE;
David Turnerdf430e12006-10-01 00:09:35 +0000624 }
Werner Lembergcc9fc492000-06-30 06:21:26 +0000625 }
Werner Lembergfbeb41d2000-07-02 00:27:53 +0000626
Wu, Chia-I (吳佳一)e5ff0592006-01-15 06:00:49 +0000627 if ( autohint )
David Turner5ae831c2000-06-30 01:31:22 +0000628 {
David Turner9657ef02002-03-14 08:49:59 +0000629 FT_AutoHinter_Service hinting;
Werner Lembergfbeb41d2000-07-02 00:27:53 +0000630
Werner Lembergcc9fc492000-06-30 06:21:26 +0000631
Werner Lemberg0d535112001-12-19 22:26:12 +0000632 /* try to load embedded bitmaps first if available */
633 /* */
634 /* XXX: This is really a temporary hack that should disappear */
635 /* promptly with FreeType 2.1! */
David Turner4937a3e2001-12-19 21:09:16 +0000636 /* */
Werner Lembergeacb9302002-10-07 10:12:43 +0000637 if ( FT_HAS_FIXED_SIZES( face ) &&
David Turner80171e02002-10-05 14:57:03 +0000638 ( load_flags & FT_LOAD_NO_BITMAP ) == 0 )
David Turner4937a3e2001-12-19 21:09:16 +0000639 {
640 error = driver->clazz->load_glyph( slot, face->size,
641 glyph_index,
642 load_flags | FT_LOAD_SBITS_ONLY );
643
David Turnerb08fe2d2002-08-27 20:20:29 +0000644 if ( !error && slot->format == FT_GLYPH_FORMAT_BITMAP )
David Turner4937a3e2001-12-19 21:09:16 +0000645 goto Load_Ok;
646 }
647
Werner Lemberg6d29f0f2008-05-03 15:54:15 +0000648 {
649 FT_Face_Internal internal = face->internal;
650 FT_Int transform_flags = internal->transform_flags;
David Turner76a5f622000-11-04 01:55:49 +0000651
Werner Lemberg6d29f0f2008-05-03 15:54:15 +0000652
653 /* since the auto-hinter calls FT_Load_Glyph by itself, */
654 /* make sure that glyphs aren't transformed */
655 internal->transform_flags = 0;
656
657 /* load auto-hinted outline */
658 hinting = (FT_AutoHinter_Service)hinter->clazz->module_interface;
659
660 error = hinting->load_glyph( (FT_AutoHinter)hinter,
661 slot, face->size,
662 glyph_index, load_flags );
663
664 internal->transform_flags = transform_flags;
665 }
David Turner5ae831c2000-06-30 01:31:22 +0000666 }
667 else
David Turner662b3442002-01-03 16:56:59 +0000668 {
David Turner5ae831c2000-06-30 01:31:22 +0000669 error = driver->clazz->load_glyph( slot,
670 face->size,
Werner Lembergcc9fc492000-06-30 06:21:26 +0000671 glyph_index,
672 load_flags );
David Turner662b3442002-01-03 16:56:59 +0000673 if ( error )
674 goto Exit;
675
Wu, Chia-I (吳佳一)2e48a1a2006-02-27 09:18:07 +0000676 if ( slot->format == FT_GLYPH_FORMAT_OUTLINE )
677 {
678 /* check that the loaded outline is correct */
679 error = FT_Outline_Check( &slot->outline );
680 if ( error )
681 goto Exit;
682
683#ifdef GRID_FIT_METRICS
684 if ( !( load_flags & FT_LOAD_NO_HINTING ) )
685 ft_glyphslot_grid_fit_metrics( slot,
David Turnerda95af62006-03-20 13:32:33 +0000686 FT_BOOL( load_flags & FT_LOAD_VERTICAL_LAYOUT ) );
Wu, Chia-I (吳佳一)2e48a1a2006-02-27 09:18:07 +0000687#endif
688 }
David Turner662b3442002-01-03 16:56:59 +0000689 }
David Turnerf0df85b2000-06-22 00:17:42 +0000690
David Turner4937a3e2001-12-19 21:09:16 +0000691 Load_Ok:
David Turnerf0df85b2000-06-22 00:17:42 +0000692 /* compute the advance */
Werner Lemberga929ba92000-06-25 06:47:11 +0000693 if ( load_flags & FT_LOAD_VERTICAL_LAYOUT )
David Turnerf0df85b2000-06-22 00:17:42 +0000694 {
695 slot->advance.x = 0;
696 slot->advance.y = slot->metrics.vertAdvance;
697 }
698 else
699 {
700 slot->advance.x = slot->metrics.horiAdvance;
701 slot->advance.y = 0;
702 }
703
David Turnerc9ce9e42000-09-15 17:16:49 +0000704 /* compute the linear advance in 16.16 pixels */
Werner Lemberg51daa4f2003-05-18 22:40:11 +0000705 if ( ( load_flags & FT_LOAD_LINEAR_DESIGN ) == 0 &&
Werner Lemberg76fffcd2008-12-05 18:37:44 +0000706 ( FT_IS_SCALABLE( face ) ) )
David Turnerc9ce9e42000-09-15 17:16:49 +0000707 {
David Turnerc9ce9e42000-09-15 17:16:49 +0000708 FT_Size_Metrics* metrics = &face->size->metrics;
Werner Lembergeddd9902000-10-12 05:05:40 +0000709
Werner Lembergf8ba2002002-03-30 13:16:35 +0000710
Wu, Chia-I (吳佳一)e5ff0592006-01-15 06:00:49 +0000711 /* it's tricky! */
David Turnerc9ce9e42000-09-15 17:16:49 +0000712 slot->linearHoriAdvance = FT_MulDiv( slot->linearHoriAdvance,
Werner Lembergbe67c4e2003-11-24 22:54:58 +0000713 metrics->x_scale, 64 );
David Turnerc9ce9e42000-09-15 17:16:49 +0000714
715 slot->linearVertAdvance = FT_MulDiv( slot->linearVertAdvance,
Werner Lembergbe67c4e2003-11-24 22:54:58 +0000716 metrics->y_scale, 64 );
David Turnerc9ce9e42000-09-15 17:16:49 +0000717 }
718
719 if ( ( load_flags & FT_LOAD_IGNORE_TRANSFORM ) == 0 )
David Turnerf0df85b2000-06-22 00:17:42 +0000720 {
David Turner54e75742000-11-04 02:52:02 +0000721 FT_Face_Internal internal = face->internal;
David Turner61d6b2b2001-05-16 17:49:07 +0000722
723
Werner Lembergd1b74752000-08-24 16:29:15 +0000724 /* now, transform the glyph image if needed */
David Turner54e75742000-11-04 02:52:02 +0000725 if ( internal->transform_flags )
David Turner35db7322000-08-24 12:39:40 +0000726 {
727 /* get renderer */
728 FT_Renderer renderer = ft_lookup_glyph_renderer( slot );
Werner Lembergdeb4e982000-06-29 03:14:25 +0000729
Werner Lemberga929ba92000-06-25 06:47:11 +0000730
David Turner35db7322000-08-24 12:39:40 +0000731 if ( renderer )
Werner Lembergdc72aff2000-11-04 08:33:38 +0000732 error = renderer->clazz->transform_glyph(
733 renderer, slot,
734 &internal->transform_matrix,
735 &internal->transform_delta );
David Turner35db7322000-08-24 12:39:40 +0000736 /* transform advance */
David Turner54e75742000-11-04 02:52:02 +0000737 FT_Vector_Transform( &slot->advance, &internal->transform_matrix );
David Turner35db7322000-08-24 12:39:40 +0000738 }
David Turnerc9ce9e42000-09-15 17:16:49 +0000739 }
David Turnerf0df85b2000-06-22 00:17:42 +0000740
David Turnerc9ce9e42000-09-15 17:16:49 +0000741 /* do we need to render the image now? */
742 if ( !error &&
David Turnerb08fe2d2002-08-27 20:20:29 +0000743 slot->format != FT_GLYPH_FORMAT_BITMAP &&
744 slot->format != FT_GLYPH_FORMAT_COMPOSITE &&
David Turnerc9ce9e42000-09-15 17:16:49 +0000745 load_flags & FT_LOAD_RENDER )
746 {
David Turner00d9f402002-09-08 21:29:11 +0000747 FT_Render_Mode mode = FT_LOAD_TARGET_MODE( load_flags );
748
Werner Lemberg68e9f922002-09-27 11:09:23 +0000749
David Turner00d9f402002-09-08 21:29:11 +0000750 if ( mode == FT_RENDER_MODE_NORMAL &&
751 (load_flags & FT_LOAD_MONOCHROME ) )
752 mode = FT_RENDER_MODE_MONO;
753
754 error = FT_Render_Glyph( slot, mode );
Werner Lembergd060a752000-07-20 06:57:41 +0000755 }
David Turner5ae831c2000-06-30 01:31:22 +0000756
Werner Lembergdeb4e982000-06-29 03:14:25 +0000757 Exit:
David Turnerf0df85b2000-06-22 00:17:42 +0000758 return error;
759 }
760
761
Werner Lemberg90a03302000-11-07 17:21:11 +0000762 /* documentation is in freetype.h */
763
Werner Lembergf814d0f2001-06-27 16:18:10 +0000764 FT_EXPORT_DEF( FT_Error )
765 FT_Load_Char( FT_Face face,
766 FT_ULong char_code,
David Turnerf467e6a2002-08-21 21:39:28 +0000767 FT_Int32 load_flags )
David Turnerf0df85b2000-06-22 00:17:42 +0000768 {
Werner Lembergdeb4e982000-06-29 03:14:25 +0000769 FT_UInt glyph_index;
David Turnerf0df85b2000-06-22 00:17:42 +0000770
Werner Lemberga929ba92000-06-25 06:47:11 +0000771
David Turnerf0df85b2000-06-22 00:17:42 +0000772 if ( !face )
773 return FT_Err_Invalid_Face_Handle;
774
775 glyph_index = (FT_UInt)char_code;
Werner Lemberga929ba92000-06-25 06:47:11 +0000776 if ( face->charmap )
David Turnerf0df85b2000-06-22 00:17:42 +0000777 glyph_index = FT_Get_Char_Index( face, char_code );
778
David Turner5ae831c2000-06-30 01:31:22 +0000779 return FT_Load_Glyph( face, glyph_index, load_flags );
David Turnerf0df85b2000-06-22 00:17:42 +0000780 }
781
782
Werner Lemberg7880dd62000-01-10 17:19:45 +0000783 /* destructor for sizes list */
Werner Lembergf814d0f2001-06-27 16:18:10 +0000784 static void
785 destroy_size( FT_Memory memory,
786 FT_Size size,
787 FT_Driver driver )
Werner Lemberg7880dd62000-01-10 17:19:45 +0000788 {
David Turnerf0df85b2000-06-22 00:17:42 +0000789 /* finalize client-specific data */
Werner Lemberga929ba92000-06-25 06:47:11 +0000790 if ( size->generic.finalizer )
David Turnerf0df85b2000-06-22 00:17:42 +0000791 size->generic.finalizer( size );
792
Werner Lemberg7880dd62000-01-10 17:19:45 +0000793 /* finalize format-specific stuff */
Werner Lemberga929ba92000-06-25 06:47:11 +0000794 if ( driver->clazz->done_size )
David Turnerf0df85b2000-06-22 00:17:42 +0000795 driver->clazz->done_size( size );
796
David Turnere459d742002-03-22 13:52:37 +0000797 FT_FREE( size->internal );
798 FT_FREE( size );
Werner Lemberg7880dd62000-01-10 17:19:45 +0000799 }
David Turnerd2b1f351999-12-16 23:11:37 +0000800
801
Werner Lemberg4338dab2004-01-05 14:41:59 +0000802 static void
Werner Lemberge70371c2005-05-27 06:01:28 +0000803 ft_cmap_done_internal( FT_CMap cmap );
804
805
806 static void
Werner Lemberg4338dab2004-01-05 14:41:59 +0000807 destroy_charmaps( FT_Face face,
808 FT_Memory memory )
809 {
810 FT_Int n;
811
812
Werner Lemberg3d507fe2007-06-03 16:54:55 +0000813 if ( !face )
814 return;
815
Werner Lemberg4338dab2004-01-05 14:41:59 +0000816 for ( n = 0; n < face->num_charmaps; n++ )
817 {
818 FT_CMap cmap = FT_CMAP( face->charmaps[n] );
819
820
Werner Lemberge70371c2005-05-27 06:01:28 +0000821 ft_cmap_done_internal( cmap );
Werner Lemberg4338dab2004-01-05 14:41:59 +0000822
823 face->charmaps[n] = NULL;
824 }
825
826 FT_FREE( face->charmaps );
827 face->num_charmaps = 0;
828 }
829
830
Werner Lemberg7880dd62000-01-10 17:19:45 +0000831 /* destructor for faces list */
Werner Lembergf814d0f2001-06-27 16:18:10 +0000832 static void
833 destroy_face( FT_Memory memory,
834 FT_Face face,
835 FT_Driver driver )
Werner Lemberg7880dd62000-01-10 17:19:45 +0000836 {
David Turneref3c1262002-03-14 09:22:48 +0000837 FT_Driver_Class clazz = driver->clazz;
David Turnerf0df85b2000-06-22 00:17:42 +0000838
Werner Lembergd060a752000-07-20 06:57:41 +0000839
David Turnerc49f69c2000-07-20 03:44:50 +0000840 /* discard auto-hinting data */
841 if ( face->autohint.finalizer )
842 face->autohint.finalizer( face->autohint.data );
Werner Lembergeddd9902000-10-12 05:05:40 +0000843
Werner Lembergf8ba2002002-03-30 13:16:35 +0000844 /* Discard glyph slots for this face. */
David Turner23bcde12001-10-17 13:48:10 +0000845 /* Beware! FT_Done_GlyphSlot() changes the field `face->glyph' */
Werner Lemberg7880dd62000-01-10 17:19:45 +0000846 while ( face->glyph )
847 FT_Done_GlyphSlot( face->glyph );
848
Werner Lembergf8ba2002002-03-30 13:16:35 +0000849 /* discard all sizes for this face */
Werner Lemberg7880dd62000-01-10 17:19:45 +0000850 FT_List_Finalize( &face->sizes_list,
Werner Lemberg74184152003-10-18 16:56:13 +0000851 (FT_List_Destructor)destroy_size,
852 memory,
853 driver );
Werner Lemberg7880dd62000-01-10 17:19:45 +0000854 face->size = 0;
855
Werner Lembergf8ba2002002-03-30 13:16:35 +0000856 /* now discard client data */
Werner Lemberg7880dd62000-01-10 17:19:45 +0000857 if ( face->generic.finalizer )
858 face->generic.finalizer( face );
859
David Turner2ded2c12002-03-22 22:37:40 +0000860 /* discard charmaps */
Werner Lemberg4338dab2004-01-05 14:41:59 +0000861 destroy_charmaps( face, memory );
Werner Lemberg75435332004-02-25 12:58:54 +0000862
David Turnerf0df85b2000-06-22 00:17:42 +0000863 /* finalize format-specific stuff */
Werner Lemberga929ba92000-06-25 06:47:11 +0000864 if ( clazz->done_face )
865 clazz->done_face( face );
David Turnerf0df85b2000-06-22 00:17:42 +0000866
867 /* close the stream for this face if needed */
Werner Lemberg75435332004-02-25 12:58:54 +0000868 FT_Stream_Free(
Werner Lembergf8ba2002002-03-30 13:16:35 +0000869 face->stream,
Werner Lemberg58b17f92000-07-27 23:29:08 +0000870 ( face->face_flags & FT_FACE_FLAG_EXTERNAL_STREAM ) != 0 );
David Turner7663f222000-02-13 13:37:38 +0000871
David Turner53b3fa12002-02-24 05:26:57 +0000872 face->stream = 0;
873
Werner Lemberg7880dd62000-01-10 17:19:45 +0000874 /* get rid of it */
David Turner23bcde12001-10-17 13:48:10 +0000875 if ( face->internal )
876 {
David Turnere459d742002-03-22 13:52:37 +0000877 FT_FREE( face->internal );
David Turner23bcde12001-10-17 13:48:10 +0000878 }
David Turnere459d742002-03-22 13:52:37 +0000879 FT_FREE( face );
Werner Lemberg7880dd62000-01-10 17:19:45 +0000880 }
David Turnerd2b1f351999-12-16 23:11:37 +0000881
882
Werner Lembergf814d0f2001-06-27 16:18:10 +0000883 static void
884 Destroy_Driver( FT_Driver driver )
David Turnerd2b1f351999-12-16 23:11:37 +0000885 {
David Turnerd2b1f351999-12-16 23:11:37 +0000886 FT_List_Finalize( &driver->faces_list,
887 (FT_List_Destructor)destroy_face,
David Turnerf0df85b2000-06-22 00:17:42 +0000888 driver->root.memory,
David Turnerd2b1f351999-12-16 23:11:37 +0000889 driver );
890
Werner Lembergdeb4e982000-06-29 03:14:25 +0000891 /* check whether we need to drop the driver's glyph loader */
Werner Lemberga929ba92000-06-25 06:47:11 +0000892 if ( FT_DRIVER_USES_OUTLINES( driver ) )
David Turnerf0df85b2000-06-22 00:17:42 +0000893 FT_GlyphLoader_Done( driver->glyph_loader );
David Turnerd2b1f351999-12-16 23:11:37 +0000894 }
895
896
Werner Lemberg547a2522000-02-16 08:23:58 +0000897 /*************************************************************************/
898 /* */
899 /* <Function> */
Antoine Lecac96f69d2002-12-03 00:39:16 +0000900 /* find_unicode_charmap */
901 /* */
902 /* <Description> */
903 /* This function finds a Unicode charmap, if there is one. */
904 /* And if there is more than one, it tries to favour the more */
Werner Lembergc8c6bf52003-04-23 05:38:13 +0000905 /* extensive one, i.e., one that supports UCS-4 against those which */
Antoine Lecac96f69d2002-12-03 00:39:16 +0000906 /* are limited to the BMP (said UCS-2 encoding.) */
907 /* */
908 /* This function is called from open_face() (just below), and also */
Werner Lemberg74597cc2007-10-01 07:08:56 +0000909 /* from FT_Select_Charmap( ..., FT_ENCODING_UNICODE ). */
Antoine Lecac96f69d2002-12-03 00:39:16 +0000910 /* */
911 static FT_Error
912 find_unicode_charmap( FT_Face face )
913 {
914 FT_CharMap* first;
915 FT_CharMap* cur;
Antoine Lecac96f69d2002-12-03 00:39:16 +0000916
917
918 /* caller should have already checked that `face' is valid */
Werner Lemberg74184152003-10-18 16:56:13 +0000919 FT_ASSERT( face );
Antoine Lecac96f69d2002-12-03 00:39:16 +0000920
921 first = face->charmaps;
922
923 if ( !first )
924 return FT_Err_Invalid_CharMap_Handle;
925
David Turnerc528f6f2002-12-18 22:43:07 +0000926 /*
Werner Lembergc8c6bf52003-04-23 05:38:13 +0000927 * The original TrueType specification(s) only specified charmap
David Turnerc528f6f2002-12-18 22:43:07 +0000928 * formats that are capable of mapping 8 or 16 bit character codes to
929 * glyph indices.
930 *
Werner Lembergc8c6bf52003-04-23 05:38:13 +0000931 * However, recent updates to the Apple and OpenType specifications
David Turnerc528f6f2002-12-18 22:43:07 +0000932 * introduced new formats that are capable of mapping 32-bit character
Werner Lembergc8c6bf52003-04-23 05:38:13 +0000933 * codes as well. And these are already used on some fonts, mainly to
David Turnerae26c682003-02-25 20:37:50 +0000934 * map non-BMP Asian ideographs as defined in Unicode.
David Turnerc528f6f2002-12-18 22:43:07 +0000935 *
Werner Lembergc8c6bf52003-04-23 05:38:13 +0000936 * For compatibility purposes, these fonts generally come with
David Turnerc528f6f2002-12-18 22:43:07 +0000937 * *several* Unicode charmaps:
938 *
Werner Lembergc8c6bf52003-04-23 05:38:13 +0000939 * - One of them in the "old" 16-bit format, that cannot access
940 * all glyphs in the font.
David Turnerc528f6f2002-12-18 22:43:07 +0000941 *
Werner Lembergc8c6bf52003-04-23 05:38:13 +0000942 * - Another one in the "new" 32-bit format, that can access all
David Turnerc528f6f2002-12-18 22:43:07 +0000943 * the glyphs.
944 *
Werner Lembergc8c6bf52003-04-23 05:38:13 +0000945 * This function has been written to always favor a 32-bit charmap
946 * when found. Otherwise, a 16-bit one is returned when found.
David Turnerc528f6f2002-12-18 22:43:07 +0000947 */
948
Werner Lemberg8acb8672005-03-08 11:43:36 +0000949 /* Since the `interesting' table, with IDs (3,10), is normally the */
Werner Lemberg1e259de2007-03-08 15:39:21 +0000950 /* last one, we loop backwards. This loses with type1 fonts with */
Werner Lemberg8acb8672005-03-08 11:43:36 +0000951 /* non-BMP characters (<.0001%), this wins with .ttf with non-BMP */
952 /* chars (.01% ?), and this is the same about 99.99% of the time! */
Antoine Lecac96f69d2002-12-03 00:39:16 +0000953
954 cur = first + face->num_charmaps; /* points after the last one */
955
956 for ( ; --cur >= first; )
957 {
958 if ( cur[0]->encoding == FT_ENCODING_UNICODE )
959 {
Werner Lemberg74597cc2007-10-01 07:08:56 +0000960 /* XXX If some new encodings to represent UCS-4 are added, */
961 /* they should be added here. */
David Turnerc528f6f2002-12-18 22:43:07 +0000962 if ( ( cur[0]->platform_id == TT_PLATFORM_MICROSOFT &&
Werner Lemberg74597cc2007-10-01 07:08:56 +0000963 cur[0]->encoding_id == TT_MS_ID_UCS_4 ) ||
David Turnerc528f6f2002-12-18 22:43:07 +0000964 ( cur[0]->platform_id == TT_PLATFORM_APPLE_UNICODE &&
Werner Lemberg74597cc2007-10-01 07:08:56 +0000965 cur[0]->encoding_id == TT_APPLE_ID_UNICODE_32 ) )
Antoine Lecac96f69d2002-12-03 00:39:16 +0000966 {
967 face->charmap = cur[0];
Werner Lemberg74597cc2007-10-01 07:08:56 +0000968 return FT_Err_Ok;
Antoine Lecac96f69d2002-12-03 00:39:16 +0000969 }
970 }
971 }
972
Werner Lemberg74597cc2007-10-01 07:08:56 +0000973 /* We do not have any UCS-4 charmap. */
974 /* Do the loop again and search for UCS-2 charmaps. */
975 cur = first + face->num_charmaps;
976
977 for ( ; --cur >= first; )
Antoine Lecac96f69d2002-12-03 00:39:16 +0000978 {
Werner Lemberg74597cc2007-10-01 07:08:56 +0000979 if ( cur[0]->encoding == FT_ENCODING_UNICODE )
980 {
981 face->charmap = cur[0];
982 return FT_Err_Ok;
983 }
Antoine Lecac96f69d2002-12-03 00:39:16 +0000984 }
985
David Turner6453a812003-01-08 09:28:34 +0000986 return FT_Err_Invalid_CharMap_Handle;
Antoine Lecac96f69d2002-12-03 00:39:16 +0000987 }
988
989
990 /*************************************************************************/
991 /* */
992 /* <Function> */
Werner Lemberg9a966b72007-10-15 17:21:32 +0000993 /* find_variant_selector_charmap */
994 /* */
995 /* <Description> */
996 /* This function finds the variant selector charmap, if there is one. */
997 /* There can only be one (platform=0, specific=5, format=14). */
998 /* */
999 static FT_CharMap
1000 find_variant_selector_charmap( FT_Face face )
1001 {
1002 FT_CharMap* first;
1003 FT_CharMap* end;
1004 FT_CharMap* cur;
1005
1006
1007 /* caller should have already checked that `face' is valid */
1008 FT_ASSERT( face );
1009
1010 first = face->charmaps;
1011
1012 if ( !first )
1013 return NULL;
1014
1015 end = first + face->num_charmaps; /* points after the last one */
1016
1017 for ( cur = first; cur < end; ++cur )
1018 {
1019 if ( cur[0]->platform_id == TT_PLATFORM_APPLE_UNICODE &&
1020 cur[0]->encoding_id == TT_APPLE_ID_VARIANT_SELECTOR &&
1021 FT_Get_CMap_Format( cur[0] ) == 14 )
1022 return cur[0];
1023 }
1024
1025 return NULL;
1026 }
1027
1028
1029 /*************************************************************************/
1030 /* */
1031 /* <Function> */
Werner Lemberg547a2522000-02-16 08:23:58 +00001032 /* open_face */
1033 /* */
1034 /* <Description> */
1035 /* This function does some work for FT_Open_Face(). */
1036 /* */
Werner Lembergf814d0f2001-06-27 16:18:10 +00001037 static FT_Error
1038 open_face( FT_Driver driver,
1039 FT_Stream stream,
1040 FT_Long face_index,
1041 FT_Int num_params,
1042 FT_Parameter* params,
Werner Lemberg6d798992003-07-01 07:28:55 +00001043 FT_Face *aface )
David Turnerd2b1f351999-12-16 23:11:37 +00001044 {
David Turnerf0df85b2000-06-22 00:17:42 +00001045 FT_Memory memory;
Werner Lemberg77c34b82003-05-20 22:06:38 +00001046 FT_Driver_Class clazz;
David Turnerf0df85b2000-06-22 00:17:42 +00001047 FT_Face face = 0;
Antoine Lecac96f69d2002-12-03 00:39:16 +00001048 FT_Error error, error2;
David Turner6a681fa2006-01-27 12:11:22 +00001049 FT_Face_Internal internal = NULL;
David Turnerd2b1f351999-12-16 23:11:37 +00001050
Werner Lemberg3c403e42002-08-06 21:47:40 +00001051
David Turnerf0df85b2000-06-22 00:17:42 +00001052 clazz = driver->clazz;
1053 memory = driver->root.memory;
David Turnerd2b1f351999-12-16 23:11:37 +00001054
Werner Lembergdeb4e982000-06-29 03:14:25 +00001055 /* allocate the face object and perform basic initialization */
David Turnere459d742002-03-22 13:52:37 +00001056 if ( FT_ALLOC( face, clazz->face_object_size ) )
David Turnerd2b1f351999-12-16 23:11:37 +00001057 goto Fail;
1058
David Turnere459d742002-03-22 13:52:37 +00001059 if ( FT_NEW( internal ) )
David Turner54e75742000-11-04 02:52:02 +00001060 goto Fail;
David Turner61d6b2b2001-05-16 17:49:07 +00001061
David Turner54e75742000-11-04 02:52:02 +00001062 face->internal = internal;
1063
1064 face->driver = driver;
1065 face->memory = memory;
1066 face->stream = stream;
Graham Asherce121822002-08-01 15:29:17 +00001067
Graham Asherd53cf1d2002-07-18 15:04:29 +00001068#ifdef FT_CONFIG_OPTION_INCREMENTAL
Werner Lemberg3c403e42002-08-06 21:47:40 +00001069 {
1070 int i;
1071
1072
1073 face->internal->incremental_interface = 0;
1074 for ( i = 0; i < num_params && !face->internal->incremental_interface;
1075 i++ )
1076 if ( params[i].tag == FT_PARAM_TAG_INCREMENTAL )
Werner Lemberg1e1b6df2007-07-07 07:30:40 +00001077 face->internal->incremental_interface =
1078 (FT_Incremental_Interface)params[i].data;
Antoine Lecac96f69d2002-12-03 00:39:16 +00001079 }
Graham Asherd53cf1d2002-07-18 15:04:29 +00001080#endif
David Turnerd2b1f351999-12-16 23:11:37 +00001081
Werner Lembergf3200fa2008-06-10 04:57:57 +00001082 if ( clazz->init_face )
Werner Lemberg102bb832008-06-10 04:57:19 +00001083 error = clazz->init_face( stream,
1084 face,
1085 (FT_Int)face_index,
1086 num_params,
1087 params );
David Turnerd2b1f351999-12-16 23:11:37 +00001088 if ( error )
1089 goto Fail;
1090
David Turnerfed59b72002-07-17 22:51:06 +00001091 /* select Unicode charmap by default */
Antoine Lecac96f69d2002-12-03 00:39:16 +00001092 error2 = find_unicode_charmap( face );
David Turnerc528f6f2002-12-18 22:43:07 +00001093
Werner Lemberg6d798992003-07-01 07:28:55 +00001094 /* if no Unicode charmap can be found, FT_Err_Invalid_CharMap_Handle */
1095 /* is returned. */
Antoine Lecac96f69d2002-12-03 00:39:16 +00001096
Werner Lemberg6d798992003-07-01 07:28:55 +00001097 /* no error should happen, but we want to play safe */
David Turnerc528f6f2002-12-18 22:43:07 +00001098 if ( error2 && error2 != FT_Err_Invalid_CharMap_Handle )
David Turnerfed59b72002-07-17 22:51:06 +00001099 {
Antoine Lecac96f69d2002-12-03 00:39:16 +00001100 error = error2;
1101 goto Fail;
David Turnerfed59b72002-07-17 22:51:06 +00001102 }
1103
David Turnerd2b1f351999-12-16 23:11:37 +00001104 *aface = face;
1105
1106 Fail:
1107 if ( error )
1108 {
Werner Lemberg4338dab2004-01-05 14:41:59 +00001109 destroy_charmaps( face, memory );
Werner Lemberg102bb832008-06-10 04:57:19 +00001110 if ( clazz->done_face )
1111 clazz->done_face( face );
Werner Lemberg77c34b82003-05-20 22:06:38 +00001112 FT_FREE( internal );
David Turnere459d742002-03-22 13:52:37 +00001113 FT_FREE( face );
David Turnerd2b1f351999-12-16 23:11:37 +00001114 *aface = 0;
1115 }
1116
1117 return error;
1118 }
1119
1120
Werner Lemberg05c21b82000-07-29 20:38:19 +00001121 /* there's a Mac-specific extended implementation of FT_New_Face() */
Werner Lemberg4d631e42002-05-27 13:02:37 +00001122 /* in src/base/ftmac.c */
Werner Lemberg05c21b82000-07-29 20:38:19 +00001123
Suzuki, Toshiya (鈴木俊哉)9e2b9902008-10-03 11:52:22 +00001124#if !defined( FT_MACINTOSH ) || defined( DARWIN_NO_CARBON )
Just van Rossum9e830c52000-07-28 01:12:34 +00001125
Werner Lemberg90a03302000-11-07 17:21:11 +00001126 /* documentation is in freetype.h */
1127
Werner Lembergf814d0f2001-06-27 16:18:10 +00001128 FT_EXPORT_DEF( FT_Error )
1129 FT_New_Face( FT_Library library,
1130 const char* pathname,
1131 FT_Long face_index,
1132 FT_Face *aface )
David Turnerd2b1f351999-12-16 23:11:37 +00001133 {
David Turner37379e22000-03-28 11:22:31 +00001134 FT_Open_Args args;
Werner Lemberg547a2522000-02-16 08:23:58 +00001135
Werner Lemberga929ba92000-06-25 06:47:11 +00001136
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001137 /* test for valid `library' and `aface' delayed to FT_Open_Face() */
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001138 if ( !pathname )
1139 return FT_Err_Invalid_Argument;
1140
David Turnerb08fe2d2002-08-27 20:20:29 +00001141 args.flags = FT_OPEN_PATHNAME;
David Turner4f2c5542000-05-12 10:19:41 +00001142 args.pathname = (char*)pathname;
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001143
David Turnercda32b72000-02-10 16:14:35 +00001144 return FT_Open_Face( library, &args, face_index, aface );
David Turnerd2b1f351999-12-16 23:11:37 +00001145 }
1146
Suzuki, Toshiya (鈴木俊哉)9e2b9902008-10-03 11:52:22 +00001147#endif /* defined( FT_MACINTOSH ) && !defined( DARWIN_NO_CARBON ) */
Just van Rossum9e830c52000-07-28 01:12:34 +00001148
Werner Lemberg7880dd62000-01-10 17:19:45 +00001149
Werner Lemberg90a03302000-11-07 17:21:11 +00001150 /* documentation is in freetype.h */
1151
Werner Lembergf814d0f2001-06-27 16:18:10 +00001152 FT_EXPORT_DEF( FT_Error )
1153 FT_New_Memory_Face( FT_Library library,
1154 const FT_Byte* file_base,
1155 FT_Long file_size,
1156 FT_Long face_index,
1157 FT_Face *aface )
David Turnerd2b1f351999-12-16 23:11:37 +00001158 {
David Turner37379e22000-03-28 11:22:31 +00001159 FT_Open_Args args;
Werner Lemberg7880dd62000-01-10 17:19:45 +00001160
Werner Lemberga929ba92000-06-25 06:47:11 +00001161
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001162 /* test for valid `library' and `face' delayed to FT_Open_Face() */
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001163 if ( !file_base )
1164 return FT_Err_Invalid_Argument;
1165
David Turnerb08fe2d2002-08-27 20:20:29 +00001166 args.flags = FT_OPEN_MEMORY;
David Turnercda32b72000-02-10 16:14:35 +00001167 args.memory_base = file_base;
1168 args.memory_size = file_size;
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001169
Werner Lemberg4b680072000-11-07 06:30:29 +00001170 return FT_Open_Face( library, &args, face_index, aface );
David Turnerd2b1f351999-12-16 23:11:37 +00001171 }
1172
Werner Lemberg7880dd62000-01-10 17:19:45 +00001173
Werner Lemberg02197282008-11-29 09:31:44 +00001174#ifdef FT_CONFIG_OPTION_MAC_FONTS
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001175
1176 /* The behavior here is very similar to that in base/ftmac.c, but it */
1177 /* is designed to work on non-mac systems, so no mac specific calls. */
1178 /* */
1179 /* We look at the file and determine if it is a mac dfont file or a mac */
1180 /* resource file, or a macbinary file containing a mac resource file. */
1181 /* */
1182 /* Unlike ftmac I'm not going to look at a `FOND'. I don't really see */
1183 /* the point, especially since there may be multiple `FOND' resources. */
1184 /* Instead I'll just look for `sfnt' and `POST' resources, ordered as */
1185 /* they occur in the file. */
1186 /* */
1187 /* Note that multiple `POST' resources do not mean multiple postscript */
1188 /* fonts; they all get jammed together to make what is essentially a */
1189 /* pfb file. */
1190 /* */
1191 /* We aren't interested in `NFNT' or `FONT' bitmap resources. */
1192 /* */
1193 /* As soon as we get an `sfnt' load it into memory and pass it off to */
1194 /* FT_Open_Face. */
1195 /* */
1196 /* If we have a (set of) `POST' resources, massage them into a (memory) */
1197 /* pfb file and pass that to FT_Open_Face. (As with ftmac.c I'm not */
1198 /* going to try to save the kerning info. After all that lives in the */
1199 /* `FOND' which isn't in the file containing the `POST' resources so */
1200 /* we don't really have access to it. */
1201
1202
Werner Lembergcff15b02008-10-02 05:38:29 +00001203 /* Finalizer for a memory stream; gets called by FT_Done_Face(). */
1204 /* It frees the memory it uses. */
1205 /* From ftmac.c. */
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001206 static void
1207 memory_stream_close( FT_Stream stream )
1208 {
1209 FT_Memory memory = stream->memory;
1210
1211
1212 FT_FREE( stream->base );
1213
1214 stream->size = 0;
1215 stream->base = 0;
1216 stream->close = 0;
1217 }
1218
1219
1220 /* Create a new memory stream from a buffer and a size. */
Werner Lembergcff15b02008-10-02 05:38:29 +00001221 /* From ftmac.c. */
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001222 static FT_Error
1223 new_memory_stream( FT_Library library,
1224 FT_Byte* base,
1225 FT_ULong size,
1226 FT_Stream_CloseFunc close,
1227 FT_Stream *astream )
1228 {
1229 FT_Error error;
1230 FT_Memory memory;
1231 FT_Stream stream;
1232
1233
1234 if ( !library )
1235 return FT_Err_Invalid_Library_Handle;
1236
1237 if ( !base )
1238 return FT_Err_Invalid_Argument;
1239
1240 *astream = 0;
1241 memory = library->memory;
1242 if ( FT_NEW( stream ) )
1243 goto Exit;
1244
1245 FT_Stream_OpenMemory( stream, base, size );
1246
1247 stream->close = close;
1248
1249 *astream = stream;
1250
1251 Exit:
1252 return error;
1253 }
1254
1255
1256 /* Create a new FT_Face given a buffer and a driver name. */
1257 /* from ftmac.c */
Suzuki, Toshiya (鈴木俊哉)f4147022008-10-02 01:43:18 +00001258 FT_LOCAL_DEF( FT_Error )
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001259 open_face_from_buffer( FT_Library library,
1260 FT_Byte* base,
1261 FT_ULong size,
1262 FT_Long face_index,
1263 const char* driver_name,
1264 FT_Face *aface )
1265 {
1266 FT_Open_Args args;
1267 FT_Error error;
Werner Lemberg607dec72007-05-15 06:49:37 +00001268 FT_Stream stream = NULL;
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001269 FT_Memory memory = library->memory;
1270
1271
1272 error = new_memory_stream( library,
1273 base,
1274 size,
1275 memory_stream_close,
1276 &stream );
1277 if ( error )
1278 {
1279 FT_FREE( base );
1280 return error;
1281 }
1282
1283 args.flags = FT_OPEN_STREAM;
1284 args.stream = stream;
1285 if ( driver_name )
1286 {
Werner Lemberg7a024102003-06-18 06:59:57 +00001287 args.flags = args.flags | FT_OPEN_DRIVER;
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001288 args.driver = FT_Get_Module( library, driver_name );
1289 }
1290
Werner Lemberg02197282008-11-29 09:31:44 +00001291#ifdef FT_MACINTOSH
Suzuki, Toshiya (鈴木俊哉)f4147022008-10-02 01:43:18 +00001292 /* At this point, face_index has served its purpose; */
1293 /* whoever calls this function has already used it to */
1294 /* locate the correct font data. We should not propagate */
1295 /* this index to FT_Open_Face() (unless it is negative). */
1296
1297 if ( face_index > 0 )
1298 face_index = 0;
1299#endif
1300
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001301 error = FT_Open_Face( library, &args, face_index, aface );
1302
Suzuki, Toshiya (鈴木俊哉)f4147022008-10-02 01:43:18 +00001303 if ( error == FT_Err_Ok )
1304 (*aface)->face_flags &= ~FT_FACE_FLAG_EXTERNAL_STREAM;
1305 else
Werner Lemberg02197282008-11-29 09:31:44 +00001306#ifdef FT_MACINTOSH
Suzuki, Toshiya (鈴木俊哉)f4147022008-10-02 01:43:18 +00001307 FT_Stream_Free( stream, 0 );
1308#else
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001309 {
1310 FT_Stream_Close( stream );
1311 FT_FREE( stream );
1312 }
Suzuki, Toshiya (鈴木俊哉)f4147022008-10-02 01:43:18 +00001313#endif
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001314
1315 return error;
1316 }
1317
1318
Suzuki, Toshiya (鈴木俊哉)f4147022008-10-02 01:43:18 +00001319 /* Look up `TYP1' or `CID ' table from sfnt table directory. */
1320 /* `offset' and `length' must exclude the binary header in tables. */
1321
1322 /* Type 1 and CID-keyed font drivers should recognize sfnt-wrapped */
1323 /* format too. Here, since we can't expect that the TrueType font */
1324 /* driver is loaded unconditially, we must parse the font by */
1325 /* ourselves. We are only interested in the name of the table and */
Werner Lembergcff15b02008-10-02 05:38:29 +00001326 /* the offset. */
Suzuki, Toshiya (鈴木俊哉)f4147022008-10-02 01:43:18 +00001327
Suzuki, Toshiya (鈴木俊哉)1137d042008-10-04 07:11:58 +00001328 static FT_Error
1329 ft_lookup_PS_in_sfnt_stream( FT_Stream stream,
1330 FT_Long face_index,
1331 FT_ULong* offset,
1332 FT_ULong* length,
1333 FT_Bool* is_sfnt_cid )
Suzuki, Toshiya (鈴木俊哉)f4147022008-10-02 01:43:18 +00001334 {
Suzuki, Toshiya (鈴木俊哉)1137d042008-10-04 07:11:58 +00001335 FT_Error error;
1336 FT_UShort numTables;
1337 FT_Long pstable_index;
1338 FT_ULong tag;
1339 int i;
Suzuki, Toshiya (鈴木俊哉)f4147022008-10-02 01:43:18 +00001340
1341
Suzuki, Toshiya (鈴木俊哉)f4147022008-10-02 01:43:18 +00001342 *offset = 0;
1343 *length = 0;
Suzuki, Toshiya (鈴木俊哉)bc2c4982008-10-03 12:28:52 +00001344 *is_sfnt_cid = FALSE;
Suzuki, Toshiya (鈴木俊哉)1137d042008-10-04 07:11:58 +00001345
Suzuki, Toshiya (鈴木俊哉)72eb2702008-10-04 17:49:58 +00001346 /* TODO: support for sfnt-wrapped PS/CID in TTC format */
1347
Suzuki, Toshiya (鈴木俊哉)1137d042008-10-04 07:11:58 +00001348 /* version check for 'typ1' (should be ignored?) */
1349 if ( FT_READ_ULONG( tag ) )
1350 return error;
Suzuki, Toshiya (鈴木俊哉)21bd5162008-10-04 18:10:28 +00001351 if ( tag != TTAG_typ1 )
Suzuki, Toshiya (鈴木俊哉)1137d042008-10-04 07:11:58 +00001352 return FT_Err_Unknown_File_Format;
1353
Suzuki, Toshiya (鈴木俊哉)1137d042008-10-04 07:11:58 +00001354 if ( FT_READ_USHORT( numTables ) )
1355 return error;
1356 if ( FT_STREAM_SKIP( 2 * 3 ) ) /* skip binary search header */
1357 return error;
1358
Suzuki, Toshiya (鈴木俊哉)1137d042008-10-04 07:11:58 +00001359 pstable_index = -1;
Werner Lemberg45489582008-10-04 11:39:03 +00001360 *is_sfnt_cid = FALSE;
1361
1362 for ( i = 0; i < numTables; i++ )
Suzuki, Toshiya (鈴木俊哉)1137d042008-10-04 07:11:58 +00001363 {
Werner Lemberg45489582008-10-04 11:39:03 +00001364 if ( FT_READ_ULONG( tag ) || FT_STREAM_SKIP( 4 ) ||
Suzuki, Toshiya (鈴木俊哉)1137d042008-10-04 07:11:58 +00001365 FT_READ_ULONG( *offset ) || FT_READ_ULONG( *length ) )
1366 return error;
1367
Suzuki, Toshiya (鈴木俊哉)21bd5162008-10-04 18:10:28 +00001368 if ( tag == TTAG_CID )
Suzuki, Toshiya (鈴木俊哉)1137d042008-10-04 07:11:58 +00001369 {
Werner Lemberg45489582008-10-04 11:39:03 +00001370 pstable_index++;
Suzuki, Toshiya (鈴木俊哉)1137d042008-10-04 07:11:58 +00001371 *offset += 22;
1372 *length -= 22;
1373 *is_sfnt_cid = TRUE;
1374 if ( face_index < 0 )
1375 return FT_Err_Ok;
1376 }
Suzuki, Toshiya (鈴木俊哉)21bd5162008-10-04 18:10:28 +00001377 else if ( tag == TTAG_TYP1 )
Suzuki, Toshiya (鈴木俊哉)1137d042008-10-04 07:11:58 +00001378 {
Werner Lemberg45489582008-10-04 11:39:03 +00001379 pstable_index++;
Suzuki, Toshiya (鈴木俊哉)1137d042008-10-04 07:11:58 +00001380 *offset += 24;
1381 *length -= 24;
1382 *is_sfnt_cid = FALSE;
1383 if ( face_index < 0 )
1384 return FT_Err_Ok;
1385 }
1386 if ( face_index >= 0 && pstable_index == face_index )
1387 return FT_Err_Ok;
1388 }
1389 return FT_Err_Table_Missing;
1390 }
1391
1392
1393 FT_LOCAL_DEF( FT_Error )
Werner Lemberg45489582008-10-04 11:39:03 +00001394 open_face_PS_from_sfnt_stream( FT_Library library,
1395 FT_Stream stream,
1396 FT_Long face_index,
1397 FT_Int num_params,
Suzuki, Toshiya (鈴木俊哉)1137d042008-10-04 07:11:58 +00001398 FT_Parameter *params,
1399 FT_Face *aface )
1400 {
1401 FT_Error error;
1402 FT_Memory memory = library->memory;
1403 FT_ULong offset, length;
1404 FT_Long pos;
1405 FT_Bool is_sfnt_cid;
1406 FT_Byte* sfnt_ps;
1407
Werner Lemberg45489582008-10-04 11:39:03 +00001408 FT_UNUSED( num_params );
1409 FT_UNUSED( params );
1410
Suzuki, Toshiya (鈴木俊哉)1137d042008-10-04 07:11:58 +00001411
1412 pos = FT_Stream_Pos( stream );
1413
1414 error = ft_lookup_PS_in_sfnt_stream( stream,
1415 face_index,
1416 &offset,
1417 &length,
1418 &is_sfnt_cid );
1419 if ( error )
Suzuki, Toshiya (鈴木俊哉)5a009092009-01-22 03:50:37 +00001420 goto Exit;
Suzuki, Toshiya (鈴木俊哉)1137d042008-10-04 07:11:58 +00001421
1422 if ( FT_Stream_Seek( stream, pos + offset ) )
1423 goto Exit;
1424
1425 if ( FT_ALLOC( sfnt_ps, (FT_Long)length ) )
1426 goto Exit;
1427
1428 error = FT_Stream_Read( stream, (FT_Byte *)sfnt_ps, length );
1429 if ( error )
1430 goto Exit;
1431
1432 error = open_face_from_buffer( library,
1433 sfnt_ps,
1434 length,
1435 face_index < 0 ? face_index : 0,
1436 is_sfnt_cid ? "cid" : "type1",
1437 aface );
1438 Exit:
1439 FT_Stream_Seek( stream, pos );
1440 return error;
Suzuki, Toshiya (鈴木俊哉)f4147022008-10-02 01:43:18 +00001441 }
1442
1443
1444#if !defined( FT_MACINTOSH ) || defined( DARWIN_NO_CARBON )
Werner Lembergcff15b02008-10-02 05:38:29 +00001445
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001446 /* The resource header says we've got resource_cnt `POST' (type1) */
1447 /* resources in this file. They all need to be coalesced into */
1448 /* one lump which gets passed on to the type1 driver. */
1449 /* Here can be only one PostScript font in a file so face_index */
1450 /* must be 0 (or -1). */
1451 /* */
1452 static FT_Error
1453 Mac_Read_POST_Resource( FT_Library library,
1454 FT_Stream stream,
Werner Lemberg75435332004-02-25 12:58:54 +00001455 FT_Long *offsets,
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001456 FT_Long resource_cnt,
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001457 FT_Long face_index,
1458 FT_Face *aface )
1459 {
1460 FT_Error error = FT_Err_Cannot_Open_Resource;
1461 FT_Memory memory = library->memory;
1462 FT_Byte* pfb_data;
Werner Lembergdc8ad542003-12-09 02:12:14 +00001463 int i, type, flags;
1464 FT_Long len;
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001465 FT_Long pfb_len, pfb_pos, pfb_lenpos;
Werner Lembergdc8ad542003-12-09 02:12:14 +00001466 FT_Long rlen, temp;
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001467
1468
1469 if ( face_index == -1 )
1470 face_index = 0;
1471 if ( face_index != 0 )
Werner Lemberg77c34b82003-05-20 22:06:38 +00001472 return error;
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001473
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001474 /* Find the length of all the POST resources, concatenated. Assume */
1475 /* worst case (each resource in its own section). */
1476 pfb_len = 0;
1477 for ( i = 0; i < resource_cnt; ++i )
1478 {
1479 error = FT_Stream_Seek( stream, offsets[i] );
1480 if ( error )
1481 goto Exit;
1482 if ( FT_READ_LONG( temp ) )
1483 goto Exit;
1484 pfb_len += temp + 6;
1485 }
1486
1487 if ( FT_ALLOC( pfb_data, (FT_Long)pfb_len + 2 ) )
1488 goto Exit;
1489
David Turnerc313c502003-09-11 19:51:54 +00001490 pfb_data[0] = 0x80;
1491 pfb_data[1] = 1; /* Ascii section */
1492 pfb_data[2] = 0; /* 4-byte length, fill in later */
1493 pfb_data[3] = 0;
1494 pfb_data[4] = 0;
1495 pfb_data[5] = 0;
Suzuki, Toshiya (鈴木俊哉)a2295402006-04-30 04:46:17 +00001496 pfb_pos = 6;
David Turnere2d12842003-09-21 17:15:55 +00001497 pfb_lenpos = 2;
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001498
1499 len = 0;
1500 type = 1;
1501 for ( i = 0; i < resource_cnt; ++i )
1502 {
1503 error = FT_Stream_Seek( stream, offsets[i] );
1504 if ( error )
1505 goto Exit2;
1506 if ( FT_READ_LONG( rlen ) )
1507 goto Exit;
1508 if ( FT_READ_USHORT( flags ) )
1509 goto Exit;
1510 rlen -= 2; /* the flags are part of the resource */
1511 if ( ( flags >> 8 ) == type )
1512 len += rlen;
1513 else
1514 {
David Turnerc313c502003-09-11 19:51:54 +00001515 pfb_data[pfb_lenpos ] = (FT_Byte)( len );
1516 pfb_data[pfb_lenpos + 1] = (FT_Byte)( len >> 8 );
1517 pfb_data[pfb_lenpos + 2] = (FT_Byte)( len >> 16 );
1518 pfb_data[pfb_lenpos + 3] = (FT_Byte)( len >> 24 );
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001519
1520 if ( ( flags >> 8 ) == 5 ) /* End of font mark */
1521 break;
1522
1523 pfb_data[pfb_pos++] = 0x80;
1524
1525 type = flags >> 8;
1526 len = rlen;
1527
Werner Lemberg013efd12003-09-17 05:26:33 +00001528 pfb_data[pfb_pos++] = (FT_Byte)type;
Suzuki, Toshiya (鈴木俊哉)a2295402006-04-30 04:46:17 +00001529 pfb_lenpos = pfb_pos;
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001530 pfb_data[pfb_pos++] = 0; /* 4-byte length, fill in later */
1531 pfb_data[pfb_pos++] = 0;
1532 pfb_data[pfb_pos++] = 0;
1533 pfb_data[pfb_pos++] = 0;
1534 }
1535
1536 error = FT_Stream_Read( stream, (FT_Byte *)pfb_data + pfb_pos, rlen );
1537 pfb_pos += rlen;
1538 }
1539
1540 pfb_data[pfb_pos++] = 0x80;
1541 pfb_data[pfb_pos++] = 3;
1542
David Turnerc313c502003-09-11 19:51:54 +00001543 pfb_data[pfb_lenpos ] = (FT_Byte)( len );
1544 pfb_data[pfb_lenpos + 1] = (FT_Byte)( len >> 8 );
1545 pfb_data[pfb_lenpos + 2] = (FT_Byte)( len >> 16 );
1546 pfb_data[pfb_lenpos + 3] = (FT_Byte)( len >> 24 );
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001547
1548 return open_face_from_buffer( library,
1549 pfb_data,
1550 pfb_pos,
1551 face_index,
1552 "type1",
1553 aface );
1554
1555 Exit2:
1556 FT_FREE( pfb_data );
1557
1558 Exit:
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001559 return error;
1560 }
1561
1562
1563 /* The resource header says we've got resource_cnt `sfnt' */
1564 /* (TrueType/OpenType) resources in this file. Look through */
1565 /* them for the one indicated by face_index, load it into mem, */
1566 /* pass it on the the truetype driver and return it. */
1567 /* */
1568 static FT_Error
1569 Mac_Read_sfnt_Resource( FT_Library library,
1570 FT_Stream stream,
Werner Lemberg75435332004-02-25 12:58:54 +00001571 FT_Long *offsets,
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001572 FT_Long resource_cnt,
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001573 FT_Long face_index,
1574 FT_Face *aface )
1575 {
1576 FT_Memory memory = library->memory;
1577 FT_Byte* sfnt_data;
1578 FT_Error error;
Werner Lemberg75435332004-02-25 12:58:54 +00001579 FT_Long flag_offset;
Werner Lembergdc8ad542003-12-09 02:12:14 +00001580 FT_Long rlen;
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001581 int is_cff;
Suzuki, Toshiya (鈴木俊哉)7a7d4032006-12-15 14:47:42 +00001582 FT_Long face_index_in_resource = 0;
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001583
1584
1585 if ( face_index == -1 )
1586 face_index = 0;
1587 if ( face_index >= resource_cnt )
1588 return FT_Err_Cannot_Open_Resource;
1589
Werner Lemberg75435332004-02-25 12:58:54 +00001590 flag_offset = offsets[face_index];
1591 error = FT_Stream_Seek( stream, flag_offset );
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001592 if ( error )
1593 goto Exit;
1594
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001595 if ( FT_READ_LONG( rlen ) )
1596 goto Exit;
1597 if ( rlen == -1 )
1598 return FT_Err_Cannot_Open_Resource;
1599
Suzuki, Toshiya (鈴木俊哉)1137d042008-10-04 07:11:58 +00001600 error = open_face_PS_from_sfnt_stream( library,
1601 stream,
1602 face_index,
1603 0, NULL,
1604 aface );
1605 if ( !error )
1606 goto Exit;
1607
Suzuki, Toshiya (鈴木俊哉)5a009092009-01-22 03:50:37 +00001608 /* rewind sfnt stream before open_face_PS_from_sfnt_stream() */
1609 if ( FT_Stream_Seek( stream, flag_offset + 4 ) )
1610 goto Exit;
1611
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001612 if ( FT_ALLOC( sfnt_data, (FT_Long)rlen ) )
1613 return error;
1614 error = FT_Stream_Read( stream, (FT_Byte *)sfnt_data, rlen );
1615 if ( error )
1616 goto Exit;
1617
Suzuki, Toshiya (鈴木俊哉)1137d042008-10-04 07:11:58 +00001618 is_cff = rlen > 4 && !ft_memcmp( sfnt_data, "OTTO", 4 );
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001619 error = open_face_from_buffer( library,
1620 sfnt_data,
1621 rlen,
Suzuki, Toshiya (鈴木俊哉)7a7d4032006-12-15 14:47:42 +00001622 face_index_in_resource,
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001623 is_cff ? "cff" : "truetype",
1624 aface );
1625
1626 Exit:
1627 return error;
1628 }
1629
1630
1631 /* Check for a valid resource fork header, or a valid dfont */
1632 /* header. In a resource fork the first 16 bytes are repeated */
1633 /* at the location specified by bytes 4-7. In a dfont bytes */
1634 /* 4-7 point to 16 bytes of zeroes instead. */
1635 /* */
1636 static FT_Error
1637 IsMacResource( FT_Library library,
1638 FT_Stream stream,
1639 FT_Long resource_offset,
1640 FT_Long face_index,
1641 FT_Face *aface )
1642 {
Werner Lemberg75435332004-02-25 12:58:54 +00001643 FT_Memory memory = library->memory;
1644 FT_Error error;
1645 FT_Long map_offset, rdara_pos;
1646 FT_Long *data_offsets;
1647 FT_Long count;
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001648
1649
Werner Lemberg75435332004-02-25 12:58:54 +00001650 error = FT_Raccess_Get_HeaderInfo( library, stream, resource_offset,
1651 &map_offset, &rdara_pos );
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001652 if ( error )
Werner Lemberg75435332004-02-25 12:58:54 +00001653 return error;
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001654
Werner Lemberg75435332004-02-25 12:58:54 +00001655 error = FT_Raccess_Get_DataOffsets( library, stream,
1656 map_offset, rdara_pos,
Suzuki, Toshiya (鈴木俊哉)21bd5162008-10-04 18:10:28 +00001657 TTAG_POST,
Werner Lemberg75435332004-02-25 12:58:54 +00001658 &data_offsets, &count );
1659 if ( !error )
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001660 {
Werner Lemberg75435332004-02-25 12:58:54 +00001661 error = Mac_Read_POST_Resource( library, stream, data_offsets, count,
1662 face_index, aface );
1663 FT_FREE( data_offsets );
Werner Lemberg0fd08bd2006-12-16 02:57:46 +00001664 /* POST exists in an LWFN providing a single face */
Werner Lemberg17432b52007-01-12 09:28:44 +00001665 if ( !error )
David Turner7a3c5642007-01-11 15:09:01 +00001666 (*aface)->num_faces = 1;
Werner Lemberg75435332004-02-25 12:58:54 +00001667 return error;
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001668 }
1669
Werner Lemberg75435332004-02-25 12:58:54 +00001670 error = FT_Raccess_Get_DataOffsets( library, stream,
1671 map_offset, rdara_pos,
Suzuki, Toshiya (鈴木俊哉)21bd5162008-10-04 18:10:28 +00001672 TTAG_sfnt,
Werner Lemberg75435332004-02-25 12:58:54 +00001673 &data_offsets, &count );
1674 if ( !error )
1675 {
Werner Lemberg0fd08bd2006-12-16 02:57:46 +00001676 FT_Long face_index_internal = face_index % count;
Suzuki, Toshiya (鈴木俊哉)7a7d4032006-12-15 14:47:42 +00001677
1678
Werner Lemberg75435332004-02-25 12:58:54 +00001679 error = Mac_Read_sfnt_Resource( library, stream, data_offsets, count,
Suzuki, Toshiya (鈴木俊哉)7a7d4032006-12-15 14:47:42 +00001680 face_index_internal, aface );
Werner Lemberg75435332004-02-25 12:58:54 +00001681 FT_FREE( data_offsets );
Werner Lemberg17432b52007-01-12 09:28:44 +00001682 if ( !error )
David Turner7a3c5642007-01-11 15:09:01 +00001683 (*aface)->num_faces = count;
Werner Lemberg75435332004-02-25 12:58:54 +00001684 }
1685
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001686 return error;
1687 }
1688
1689
1690 /* Check for a valid macbinary header, and if we find one */
1691 /* check that the (flattened) resource fork in it is valid. */
1692 /* */
1693 static FT_Error
1694 IsMacBinary( FT_Library library,
1695 FT_Stream stream,
1696 FT_Long face_index,
1697 FT_Face *aface )
1698 {
1699 unsigned char header[128];
1700 FT_Error error;
1701 FT_Long dlen, offset;
1702
1703
Suzuki, Toshiya (鈴木俊哉)86c0f902007-11-20 14:00:17 +00001704 if ( NULL == stream )
1705 return FT_Err_Invalid_Stream_Operation;
1706
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001707 error = FT_Stream_Seek( stream, 0 );
1708 if ( error )
1709 goto Exit;
1710
1711 error = FT_Stream_Read( stream, (FT_Byte*)header, 128 );
1712 if ( error )
1713 goto Exit;
1714
1715 if ( header[ 0] != 0 ||
1716 header[74] != 0 ||
1717 header[82] != 0 ||
1718 header[ 1] == 0 ||
1719 header[ 1] > 33 ||
1720 header[63] != 0 ||
1721 header[2 + header[1]] != 0 )
1722 return FT_Err_Unknown_File_Format;
1723
1724 dlen = ( header[0x53] << 24 ) |
1725 ( header[0x54] << 16 ) |
1726 ( header[0x55] << 8 ) |
1727 header[0x56];
1728#if 0
1729 rlen = ( header[0x57] << 24 ) |
1730 ( header[0x58] << 16 ) |
1731 ( header[0x59] << 8 ) |
1732 header[0x5a];
1733#endif /* 0 */
1734 offset = 128 + ( ( dlen + 127 ) & ~127 );
1735
1736 return IsMacResource( library, stream, offset, face_index, aface );
1737
1738 Exit:
1739 return error;
1740 }
1741
1742
Werner Lemberg75435332004-02-25 12:58:54 +00001743 static FT_Error
1744 load_face_in_embedded_rfork( FT_Library library,
1745 FT_Stream stream,
1746 FT_Long face_index,
1747 FT_Face *aface,
1748 const FT_Open_Args *args )
1749 {
1750
1751#undef FT_COMPONENT
1752#define FT_COMPONENT trace_raccess
1753
1754 FT_Memory memory = library->memory;
1755 FT_Error error = FT_Err_Unknown_File_Format;
1756 int i;
1757
1758 char * file_names[FT_RACCESS_N_RULES];
1759 FT_Long offsets[FT_RACCESS_N_RULES];
1760 FT_Error errors[FT_RACCESS_N_RULES];
1761
1762 FT_Open_Args args2;
Suzuki, Toshiya (鈴木俊哉)4c60bd92008-08-19 15:35:44 +00001763 FT_Stream stream2 = 0;
Werner Lemberg75435332004-02-25 12:58:54 +00001764
1765
1766 FT_Raccess_Guess( library, stream,
1767 args->pathname, file_names, offsets, errors );
1768
1769 for ( i = 0; i < FT_RACCESS_N_RULES; i++ )
1770 {
1771 if ( errors[i] )
1772 {
1773 FT_TRACE3(( "Error[%d] has occurred in rule %d\n", errors[i], i ));
1774 continue;
1775 }
1776
1777 args2.flags = FT_OPEN_PATHNAME;
1778 args2.pathname = file_names[i] ? file_names[i] : args->pathname;
1779
1780 FT_TRACE3(( "Try rule %d: %s (offset=%d) ...",
1781 i, args2.pathname, offsets[i] ));
1782
1783 error = FT_Stream_New( library, &args2, &stream2 );
1784 if ( error )
1785 {
1786 FT_TRACE3(( "failed\n" ));
1787 continue;
1788 }
1789
1790 error = IsMacResource( library, stream2, offsets[i],
1791 face_index, aface );
Suzuki, Toshiya (鈴木俊哉)de0a96c2006-05-19 23:16:12 +00001792 FT_Stream_Free( stream2, 0 );
Werner Lemberg75435332004-02-25 12:58:54 +00001793
1794 FT_TRACE3(( "%s\n", error ? "failed": "successful" ));
1795
1796 if ( !error )
1797 break;
1798 }
1799
1800 for (i = 0; i < FT_RACCESS_N_RULES; i++)
1801 {
1802 if ( file_names[i] )
1803 FT_FREE( file_names[i] );
1804 }
1805
1806 /* Caller (load_mac_face) requires FT_Err_Unknown_File_Format. */
1807 if ( error )
1808 error = FT_Err_Unknown_File_Format;
1809
1810 return error;
1811
1812#undef FT_COMPONENT
1813#define FT_COMPONENT trace_objs
1814
1815 }
1816
1817
Suzuki, Toshiya (鈴木俊哉)f4147022008-10-02 01:43:18 +00001818 /* Check for some macintosh formats without Carbon framework. */
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001819 /* Is this a macbinary file? If so look at the resource fork. */
1820 /* Is this a mac dfont file? */
1821 /* Is this an old style resource fork? (in data) */
Werner Lemberg75435332004-02-25 12:58:54 +00001822 /* Else call load_face_in_embedded_rfork to try extra rules */
1823 /* (defined in `ftrfork.c'). */
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001824 /* */
1825 static FT_Error
1826 load_mac_face( FT_Library library,
1827 FT_Stream stream,
1828 FT_Long face_index,
1829 FT_Face *aface,
1830 const FT_Open_Args *args )
1831 {
1832 FT_Error error;
1833 FT_UNUSED( args );
1834
1835
1836 error = IsMacBinary( library, stream, face_index, aface );
1837 if ( FT_ERROR_BASE( error ) == FT_Err_Unknown_File_Format )
Werner Lemberg75435332004-02-25 12:58:54 +00001838 {
1839
1840#undef FT_COMPONENT
1841#define FT_COMPONENT trace_raccess
1842
1843 FT_TRACE3(( "Try as dfont: %s ...", args->pathname ));
1844
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001845 error = IsMacResource( library, stream, 0, face_index, aface );
1846
Werner Lemberg75435332004-02-25 12:58:54 +00001847 FT_TRACE3(( "%s\n", error ? "failed" : "successful" ));
David Turnere2d12842003-09-21 17:15:55 +00001848
Werner Lemberg75435332004-02-25 12:58:54 +00001849#undef FT_COMPONENT
1850#define FT_COMPONENT trace_objs
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001851
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001852 }
1853
Werner Lemberg75435332004-02-25 12:58:54 +00001854 if ( ( FT_ERROR_BASE( error ) == FT_Err_Unknown_File_Format ||
1855 FT_ERROR_BASE( error ) == FT_Err_Invalid_Stream_Operation ) &&
1856 ( args->flags & FT_OPEN_PATHNAME ) )
1857 error = load_face_in_embedded_rfork( library, stream,
1858 face_index, aface, args );
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001859 return error;
1860 }
Suzuki, Toshiya (鈴木俊哉)f4147022008-10-02 01:43:18 +00001861#endif
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001862
1863#endif /* !FT_MACINTOSH && FT_CONFIG_OPTION_MAC_FONTS */
1864
1865
Werner Lemberg90a03302000-11-07 17:21:11 +00001866 /* documentation is in freetype.h */
1867
Werner Lembergf814d0f2001-06-27 16:18:10 +00001868 FT_EXPORT_DEF( FT_Error )
Werner Lembergc4c373c2002-10-07 09:15:20 +00001869 FT_Open_Face( FT_Library library,
1870 const FT_Open_Args* args,
1871 FT_Long face_index,
1872 FT_Face *aface )
David Turnerd2b1f351999-12-16 23:11:37 +00001873 {
1874 FT_Error error;
1875 FT_Driver driver;
1876 FT_Memory memory;
Suzuki, Toshiya (鈴木俊哉)4c60bd92008-08-19 15:35:44 +00001877 FT_Stream stream = 0;
David Turnerd2b1f351999-12-16 23:11:37 +00001878 FT_Face face = 0;
1879 FT_ListNode node = 0;
David Turnerc5cdf8b2000-07-27 21:40:22 +00001880 FT_Bool external_stream;
Werner Lembergc32e83f2008-04-01 06:07:37 +00001881 FT_Module* cur;
1882 FT_Module* limit;
Werner Lemberg547a2522000-02-16 08:23:58 +00001883
Werner Lemberg58b17f92000-07-27 23:29:08 +00001884
Werner Lembergf9b03752000-09-11 22:50:13 +00001885 /* test for valid `library' delayed to */
Werner Lemberg75435332004-02-25 12:58:54 +00001886 /* FT_Stream_New() */
David Turnerd2b1f351999-12-16 23:11:37 +00001887
Werner Lembergce235ea2005-05-17 20:35:23 +00001888 if ( ( !aface && face_index >= 0 ) || !args )
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00001889 return FT_Err_Invalid_Argument;
1890
David Turnerb08fe2d2002-08-27 20:20:29 +00001891 external_stream = FT_BOOL( ( args->flags & FT_OPEN_STREAM ) &&
Werner Lemberg8eb03532001-06-19 23:03:41 +00001892 args->stream );
David Turnerc5cdf8b2000-07-27 21:40:22 +00001893
David Turnercda32b72000-02-10 16:14:35 +00001894 /* create input stream */
Werner Lemberg75435332004-02-25 12:58:54 +00001895 error = FT_Stream_New( library, args, &stream );
Werner Lembergdeb4e982000-06-29 03:14:25 +00001896 if ( error )
Suzuki, Toshiya (鈴木俊哉)86c0f902007-11-20 14:00:17 +00001897 goto Fail3;
David Turnercda32b72000-02-10 16:14:35 +00001898
David Turnerd2b1f351999-12-16 23:11:37 +00001899 memory = library->memory;
1900
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001901 /* If the font driver is specified in the `args' structure, use */
Werner Lembergdeb4e982000-06-29 03:14:25 +00001902 /* it. Otherwise, we scan the list of registered drivers. */
David Turnerb08fe2d2002-08-27 20:20:29 +00001903 if ( ( args->flags & FT_OPEN_DRIVER ) && args->driver )
David Turner7663f222000-02-13 13:37:38 +00001904 {
Werner Lemberga929ba92000-06-25 06:47:11 +00001905 driver = FT_DRIVER( args->driver );
David Turnerf0df85b2000-06-22 00:17:42 +00001906
1907 /* not all modules are drivers, so check... */
Werner Lemberga929ba92000-06-25 06:47:11 +00001908 if ( FT_MODULE_IS_DRIVER( driver ) )
David Turner7663f222000-02-13 13:37:38 +00001909 {
Werner Lemberg3c403e42002-08-06 21:47:40 +00001910 FT_Int num_params = 0;
1911 FT_Parameter* params = 0;
1912
Werner Lemberga929ba92000-06-25 06:47:11 +00001913
David Turnerb08fe2d2002-08-27 20:20:29 +00001914 if ( args->flags & FT_OPEN_PARAMS )
David Turner4f2c5542000-05-12 10:19:41 +00001915 {
1916 num_params = args->num_params;
1917 params = args->params;
1918 }
David Turnere49ab252000-05-16 23:44:38 +00001919
David Turner4f2c5542000-05-12 10:19:41 +00001920 error = open_face( driver, stream, face_index,
1921 num_params, params, &face );
Werner Lemberg547a2522000-02-16 08:23:58 +00001922 if ( !error )
1923 goto Success;
David Turner7663f222000-02-13 13:37:38 +00001924 }
1925 else
1926 error = FT_Err_Invalid_Handle;
1927
Werner Lemberg75435332004-02-25 12:58:54 +00001928 FT_Stream_Free( stream, external_stream );
David Turner7663f222000-02-13 13:37:38 +00001929 goto Fail;
1930 }
Just van Rossum1e5754f2000-03-02 10:52:57 +00001931 else
David Turnerd2b1f351999-12-16 23:11:37 +00001932 {
1933 /* check each font driver for an appropriate format */
Werner Lembergc32e83f2008-04-01 06:07:37 +00001934 cur = library->modules;
1935 limit = cur + library->num_modules;
David Turnerd2b1f351999-12-16 23:11:37 +00001936
Werner Lemberga929ba92000-06-25 06:47:11 +00001937
David Turnerd2b1f351999-12-16 23:11:37 +00001938 for ( ; cur < limit; cur++ )
1939 {
David Turnerf0df85b2000-06-22 00:17:42 +00001940 /* not all modules are font drivers, so check... */
Werner Lemberga929ba92000-06-25 06:47:11 +00001941 if ( FT_MODULE_IS_DRIVER( cur[0] ) )
David Turnerd2b1f351999-12-16 23:11:37 +00001942 {
David Turner4f2c5542000-05-12 10:19:41 +00001943 FT_Int num_params = 0;
1944 FT_Parameter* params = 0;
David Turnere49ab252000-05-16 23:44:38 +00001945
Werner Lemberg3c403e42002-08-06 21:47:40 +00001946
Werner Lemberga929ba92000-06-25 06:47:11 +00001947 driver = FT_DRIVER( cur[0] );
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00001948
David Turnerb08fe2d2002-08-27 20:20:29 +00001949 if ( args->flags & FT_OPEN_PARAMS )
David Turner4f2c5542000-05-12 10:19:41 +00001950 {
1951 num_params = args->num_params;
1952 params = args->params;
1953 }
David Turnere49ab252000-05-16 23:44:38 +00001954
Graham Asherd53cf1d2002-07-18 15:04:29 +00001955 error = open_face( driver, stream, face_index,
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001956 num_params, params, &face );
David Turnerd2b1f351999-12-16 23:11:37 +00001957 if ( !error )
1958 goto Success;
1959
Suzuki, Toshiya (鈴木俊哉)2d3e0af2008-10-05 02:38:57 +00001960#ifdef FT_CONFIG_OPTION_MAC_FONTS
1961 if ( ft_strcmp( cur[0]->clazz->module_name, "truetype" ) == 0 &&
Werner Lemberg570b1fd2008-10-05 06:08:40 +00001962 FT_ERROR_BASE( error ) == FT_Err_Table_Missing )
Suzuki, Toshiya (鈴木俊哉)2d3e0af2008-10-05 02:38:57 +00001963 {
1964 /* TrueType but essential tables are missing */
1965 if ( FT_Stream_Seek( stream, 0 ) )
1966 break;
1967
1968 error = open_face_PS_from_sfnt_stream( library,
1969 stream,
1970 face_index,
1971 num_params,
1972 params,
1973 aface );
1974 if ( !error )
1975 {
1976 FT_Stream_Free( stream, external_stream );
1977 return error;
1978 }
1979 }
1980#endif
1981
Werner Lemberg79860702001-06-08 21:17:29 +00001982 if ( FT_ERROR_BASE( error ) != FT_Err_Unknown_File_Format )
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001983 goto Fail3;
David Turnerd2b1f351999-12-16 23:11:37 +00001984 }
1985 }
1986
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001987 Fail3:
1988 /* If we are on the mac, and we get an FT_Err_Invalid_Stream_Operation */
1989 /* it may be because we have an empty data fork, so we need to check */
1990 /* the resource fork. */
Suzuki, Toshiya (鈴木俊哉)86c0f902007-11-20 14:00:17 +00001991 if ( FT_ERROR_BASE( error ) != FT_Err_Cannot_Open_Stream &&
1992 FT_ERROR_BASE( error ) != FT_Err_Unknown_File_Format &&
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001993 FT_ERROR_BASE( error ) != FT_Err_Invalid_Stream_Operation )
1994 goto Fail2;
1995
Werner Lembergdc8ad542003-12-09 02:12:14 +00001996#if !defined( FT_MACINTOSH ) && defined( FT_CONFIG_OPTION_MAC_FONTS )
Werner Lemberg51daa4f2003-05-18 22:40:11 +00001997 error = load_mac_face( library, stream, face_index, aface, args );
1998 if ( !error )
1999 {
2000 /* We don't want to go to Success here. We've already done that. */
2001 /* On the other hand, if we succeeded we still need to close this */
2002 /* stream (we opened a different stream which extracted the */
2003 /* interesting information out of this stream here. That stream */
2004 /* will still be open and the face will point to it). */
Werner Lemberg75435332004-02-25 12:58:54 +00002005 FT_Stream_Free( stream, external_stream );
Werner Lemberg51daa4f2003-05-18 22:40:11 +00002006 return error;
2007 }
2008
2009 if ( FT_ERROR_BASE( error ) != FT_Err_Unknown_File_Format )
2010 goto Fail2;
Werner Lembergdc8ad542003-12-09 02:12:14 +00002011#endif /* !FT_MACINTOSH && FT_CONFIG_OPTION_MAC_FONTS */
Werner Lemberg51daa4f2003-05-18 22:40:11 +00002012
David Turnerd2b1f351999-12-16 23:11:37 +00002013 /* no driver is able to handle this format */
2014 error = FT_Err_Unknown_File_Format;
David Turnerebe85f52001-05-11 14:25:57 +00002015
2016 Fail2:
Werner Lemberg75435332004-02-25 12:58:54 +00002017 FT_Stream_Free( stream, external_stream );
David Turnercda32b72000-02-10 16:14:35 +00002018 goto Fail;
David Turnerd2b1f351999-12-16 23:11:37 +00002019 }
2020
2021 Success:
Werner Lembergf9b03752000-09-11 22:50:13 +00002022 FT_TRACE4(( "FT_Open_Face: New face object, adding to list\n" ));
David Turnerd2b1f351999-12-16 23:11:37 +00002023
Werner Lembergdeb4e982000-06-29 03:14:25 +00002024 /* set the FT_FACE_FLAG_EXTERNAL_STREAM bit for FT_Done_Face */
David Turnerc5cdf8b2000-07-27 21:40:22 +00002025 if ( external_stream )
David Turnerf0df85b2000-06-22 00:17:42 +00002026 face->face_flags |= FT_FACE_FLAG_EXTERNAL_STREAM;
2027
Werner Lemberg547a2522000-02-16 08:23:58 +00002028 /* add the face object to its driver's list */
David Turnere459d742002-03-22 13:52:37 +00002029 if ( FT_NEW( node ) )
David Turnerd2b1f351999-12-16 23:11:37 +00002030 goto Fail;
2031
2032 node->data = face;
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00002033 /* don't assume driver is the same as face->driver, so use */
2034 /* face->driver instead. */
Just van Rossum7eef5362000-03-05 16:07:58 +00002035 FT_List_Add( &face->driver->faces_list, node );
David Turnerd2b1f351999-12-16 23:11:37 +00002036
Werner Lemberg547a2522000-02-16 08:23:58 +00002037 /* now allocate a glyph slot object for the face */
Werner Lembergb9ee7372005-05-20 21:52:19 +00002038 FT_TRACE4(( "FT_Open_Face: Creating glyph slot\n" ));
David Turnerd2b1f351999-12-16 23:11:37 +00002039
David Turner92f30c82005-10-17 21:17:20 +00002040 if ( face_index >= 0 )
David Turnerd2b1f351999-12-16 23:11:37 +00002041 {
David Turner92f30c82005-10-17 21:17:20 +00002042 error = FT_New_GlyphSlot( face, NULL );
Werner Lembergdeb4e982000-06-29 03:14:25 +00002043 if ( error )
2044 goto Fail;
2045
David Turner92f30c82005-10-17 21:17:20 +00002046 /* finally, allocate a size object for the face */
2047 {
2048 FT_Size size;
2049
2050
2051 FT_TRACE4(( "FT_Open_Face: Creating size object\n" ));
2052
2053 error = FT_New_Size( face, &size );
2054 if ( error )
2055 goto Fail;
2056
2057 face->size = size;
2058 }
David Turnerd2b1f351999-12-16 23:11:37 +00002059 }
Werner Lemberg7880dd62000-01-10 17:19:45 +00002060
Wu, Chia-I (吳佳一)e5ff0592006-01-15 06:00:49 +00002061 /* some checks */
2062
2063 if ( FT_IS_SCALABLE( face ) )
2064 {
2065 if ( face->height < 0 )
Werner Lembergbe3c9812006-01-27 14:16:16 +00002066 face->height = (FT_Short)-face->height;
Wu, Chia-I (吳佳一)e5ff0592006-01-15 06:00:49 +00002067
2068 if ( !FT_HAS_VERTICAL( face ) )
Werner Lembergbe3c9812006-01-27 14:16:16 +00002069 face->max_advance_height = (FT_Short)face->height;
Wu, Chia-I (吳佳一)e5ff0592006-01-15 06:00:49 +00002070 }
2071
2072 if ( FT_HAS_FIXED_SIZES( face ) )
2073 {
Werner Lemberg1723dcc2006-01-15 07:30:32 +00002074 FT_Int i;
Wu, Chia-I (吳佳一)e5ff0592006-01-15 06:00:49 +00002075
David Turnercda2d952006-02-16 22:45:31 +00002076
Wu, Chia-I (吳佳一)e5ff0592006-01-15 06:00:49 +00002077 for ( i = 0; i < face->num_fixed_sizes; i++ )
2078 {
2079 FT_Bitmap_Size* bsize = face->available_sizes + i;
2080
2081
2082 if ( bsize->height < 0 )
Werner Lembergbe3c9812006-01-27 14:16:16 +00002083 bsize->height = (FT_Short)-bsize->height;
Wu, Chia-I (吳佳一)e5ff0592006-01-15 06:00:49 +00002084 if ( bsize->x_ppem < 0 )
Werner Lembergbe3c9812006-01-27 14:16:16 +00002085 bsize->x_ppem = (FT_Short)-bsize->x_ppem;
Wu, Chia-I (吳佳一)e5ff0592006-01-15 06:00:49 +00002086 if ( bsize->y_ppem < 0 )
2087 bsize->y_ppem = -bsize->y_ppem;
2088 }
2089 }
2090
David Turner54e75742000-11-04 02:52:02 +00002091 /* initialize internal face data */
2092 {
2093 FT_Face_Internal internal = face->internal;
David Turner61d6b2b2001-05-16 17:49:07 +00002094
David Turner37379e22000-03-28 11:22:31 +00002095
David Turner54e75742000-11-04 02:52:02 +00002096 internal->transform_matrix.xx = 0x10000L;
2097 internal->transform_matrix.xy = 0;
2098 internal->transform_matrix.yx = 0;
2099 internal->transform_matrix.yy = 0x10000L;
David Turner61d6b2b2001-05-16 17:49:07 +00002100
David Turner54e75742000-11-04 02:52:02 +00002101 internal->transform_delta.x = 0;
2102 internal->transform_delta.y = 0;
2103 }
David Turner37379e22000-03-28 11:22:31 +00002104
Werner Lembergce235ea2005-05-17 20:35:23 +00002105 if ( aface )
2106 *aface = face;
Werner Lembergb2d02532005-11-04 06:58:49 +00002107 else
2108 FT_Done_Face( face );
2109
David Turnerd2b1f351999-12-16 23:11:37 +00002110 goto Exit;
2111
2112 Fail:
2113 FT_Done_Face( face );
2114
David Turnerd2b1f351999-12-16 23:11:37 +00002115 Exit:
2116 FT_TRACE4(( "FT_Open_Face: Return %d\n", error ));
Werner Lembergdeb4e982000-06-29 03:14:25 +00002117
David Turnerd2b1f351999-12-16 23:11:37 +00002118 return error;
2119 }
2120
2121
Werner Lemberg90a03302000-11-07 17:21:11 +00002122 /* documentation is in freetype.h */
2123
Werner Lembergf814d0f2001-06-27 16:18:10 +00002124 FT_EXPORT_DEF( FT_Error )
2125 FT_Attach_File( FT_Face face,
2126 const char* filepathname )
David Turner7663f222000-02-13 13:37:38 +00002127 {
David Turner37379e22000-03-28 11:22:31 +00002128 FT_Open_Args open;
David Turner7663f222000-02-13 13:37:38 +00002129
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00002130
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00002131 /* test for valid `face' delayed to FT_Attach_Stream() */
2132
2133 if ( !filepathname )
2134 return FT_Err_Invalid_Argument;
2135
Werner Lembergb8fdcd62004-08-03 03:28:11 +00002136 open.stream = NULL;
David Turnerb08fe2d2002-08-27 20:20:29 +00002137 open.flags = FT_OPEN_PATHNAME;
David Turner4f2c5542000-05-12 10:19:41 +00002138 open.pathname = (char*)filepathname;
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00002139
David Turner7663f222000-02-13 13:37:38 +00002140 return FT_Attach_Stream( face, &open );
2141 }
Werner Lemberg547a2522000-02-16 08:23:58 +00002142
David Turnere49ab252000-05-16 23:44:38 +00002143
Werner Lemberg90a03302000-11-07 17:21:11 +00002144 /* documentation is in freetype.h */
2145
Werner Lembergf814d0f2001-06-27 16:18:10 +00002146 FT_EXPORT_DEF( FT_Error )
2147 FT_Attach_Stream( FT_Face face,
2148 FT_Open_Args* parameters )
David Turner7663f222000-02-13 13:37:38 +00002149 {
2150 FT_Stream stream;
2151 FT_Error error;
2152 FT_Driver driver;
David Turnere49ab252000-05-16 23:44:38 +00002153
David Turneref3c1262002-03-14 09:22:48 +00002154 FT_Driver_Class clazz;
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00002155
Werner Lemberga929ba92000-06-25 06:47:11 +00002156
Werner Lemberg75435332004-02-25 12:58:54 +00002157 /* test for valid `parameters' delayed to FT_Stream_New() */
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00002158
2159 if ( !face )
2160 return FT_Err_Invalid_Face_Handle;
David Turnere49ab252000-05-16 23:44:38 +00002161
David Turner7663f222000-02-13 13:37:38 +00002162 driver = face->driver;
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00002163 if ( !driver )
2164 return FT_Err_Invalid_Driver_Handle;
2165
Werner Lemberg75435332004-02-25 12:58:54 +00002166 error = FT_Stream_New( driver->root.library, parameters, &stream );
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00002167 if ( error )
2168 goto Exit;
David Turnere49ab252000-05-16 23:44:38 +00002169
David Turner7663f222000-02-13 13:37:38 +00002170 /* we implement FT_Attach_Stream in each driver through the */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00002171 /* `attach_file' interface */
2172
David Turner7663f222000-02-13 13:37:38 +00002173 error = FT_Err_Unimplemented_Feature;
David Turnerf0df85b2000-06-22 00:17:42 +00002174 clazz = driver->clazz;
Werner Lemberga929ba92000-06-25 06:47:11 +00002175 if ( clazz->attach_file )
David Turnerf0df85b2000-06-22 00:17:42 +00002176 error = clazz->attach_file( face, stream );
David Turnere49ab252000-05-16 23:44:38 +00002177
David Turner7663f222000-02-13 13:37:38 +00002178 /* close the attached stream */
Werner Lemberg75435332004-02-25 12:58:54 +00002179 FT_Stream_Free( stream,
Werner Lemberg58b17f92000-07-27 23:29:08 +00002180 (FT_Bool)( parameters->stream &&
David Turnerb08fe2d2002-08-27 20:20:29 +00002181 ( parameters->flags & FT_OPEN_STREAM ) ) );
David Turnere49ab252000-05-16 23:44:38 +00002182
David Turner7663f222000-02-13 13:37:38 +00002183 Exit:
2184 return error;
2185 }
2186
2187
Werner Lemberg90a03302000-11-07 17:21:11 +00002188 /* documentation is in freetype.h */
2189
Werner Lembergf814d0f2001-06-27 16:18:10 +00002190 FT_EXPORT_DEF( FT_Error )
2191 FT_Done_Face( FT_Face face )
David Turnerd2b1f351999-12-16 23:11:37 +00002192 {
Werner Lemberga929ba92000-06-25 06:47:11 +00002193 FT_Error error;
2194 FT_Driver driver;
2195 FT_Memory memory;
2196 FT_ListNode node;
2197
David Turnerd2b1f351999-12-16 23:11:37 +00002198
David Turnerf0df85b2000-06-22 00:17:42 +00002199 error = FT_Err_Invalid_Face_Handle;
2200 if ( face && face->driver )
David Turnerd2b1f351999-12-16 23:11:37 +00002201 {
David Turnerf0df85b2000-06-22 00:17:42 +00002202 driver = face->driver;
2203 memory = driver->root.memory;
Werner Lembergdeb4e982000-06-29 03:14:25 +00002204
David Turnerf0df85b2000-06-22 00:17:42 +00002205 /* find face in driver's list */
2206 node = FT_List_Find( &driver->faces_list, face );
2207 if ( node )
2208 {
2209 /* remove face object from the driver's list */
2210 FT_List_Remove( &driver->faces_list, node );
David Turnere459d742002-03-22 13:52:37 +00002211 FT_FREE( node );
Werner Lembergdeb4e982000-06-29 03:14:25 +00002212
David Turnerf0df85b2000-06-22 00:17:42 +00002213 /* now destroy the object proper */
2214 destroy_face( memory, face, driver );
2215 error = FT_Err_Ok;
2216 }
David Turnerd2b1f351999-12-16 23:11:37 +00002217 }
David Turnerd2b1f351999-12-16 23:11:37 +00002218 return error;
2219 }
2220
2221
Werner Lemberg90a03302000-11-07 17:21:11 +00002222 /* documentation is in ftobjs.h */
2223
Werner Lembergf814d0f2001-06-27 16:18:10 +00002224 FT_EXPORT_DEF( FT_Error )
2225 FT_New_Size( FT_Face face,
2226 FT_Size *asize )
David Turnerd2b1f351999-12-16 23:11:37 +00002227 {
Werner Lembergf8ba2002002-03-30 13:16:35 +00002228 FT_Error error;
2229 FT_Memory memory;
2230 FT_Driver driver;
David Turneref3c1262002-03-14 09:22:48 +00002231 FT_Driver_Class clazz;
David Turnerd2b1f351999-12-16 23:11:37 +00002232
Werner Lembergf8ba2002002-03-30 13:16:35 +00002233 FT_Size size = 0;
2234 FT_ListNode node = 0;
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00002235
Werner Lemberga929ba92000-06-25 06:47:11 +00002236
Werner Lembergb48a6092000-07-09 19:15:30 +00002237 if ( !face )
2238 return FT_Err_Invalid_Face_Handle;
2239
2240 if ( !asize )
2241 return FT_Err_Invalid_Size_Handle;
2242
2243 if ( !face->driver )
2244 return FT_Err_Invalid_Driver_Handle;
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00002245
Werner Lembergdeb4e982000-06-29 03:14:25 +00002246 *asize = 0;
2247
David Turnerf0df85b2000-06-22 00:17:42 +00002248 driver = face->driver;
2249 clazz = driver->clazz;
2250 memory = face->memory;
David Turnerd2b1f351999-12-16 23:11:37 +00002251
2252 /* Allocate new size object and perform basic initialisation */
David Turnere459d742002-03-22 13:52:37 +00002253 if ( FT_ALLOC( size, clazz->size_object_size ) || FT_NEW( node ) )
David Turnerd2b1f351999-12-16 23:11:37 +00002254 goto Exit;
2255
2256 size->face = face;
David Turner61d6b2b2001-05-16 17:49:07 +00002257
David Turner54e75742000-11-04 02:52:02 +00002258 /* for now, do not use any internal fields in size objects */
2259 size->internal = 0;
David Turnerd2b1f351999-12-16 23:11:37 +00002260
Werner Lemberga929ba92000-06-25 06:47:11 +00002261 if ( clazz->init_size )
David Turnerf0df85b2000-06-22 00:17:42 +00002262 error = clazz->init_size( size );
David Turnerd2b1f351999-12-16 23:11:37 +00002263
2264 /* in case of success, add to the face's list */
2265 if ( !error )
2266 {
2267 *asize = size;
2268 node->data = size;
2269 FT_List_Add( &face->sizes_list, node );
David Turnerd2b1f351999-12-16 23:11:37 +00002270 }
2271
2272 Exit:
2273 if ( error )
2274 {
David Turnere459d742002-03-22 13:52:37 +00002275 FT_FREE( node );
2276 FT_FREE( size );
David Turnerd2b1f351999-12-16 23:11:37 +00002277 }
2278
2279 return error;
2280 }
2281
2282
Werner Lemberg90a03302000-11-07 17:21:11 +00002283 /* documentation is in ftobjs.h */
2284
Werner Lembergf814d0f2001-06-27 16:18:10 +00002285 FT_EXPORT_DEF( FT_Error )
2286 FT_Done_Size( FT_Size size )
David Turnerd2b1f351999-12-16 23:11:37 +00002287 {
2288 FT_Error error;
2289 FT_Driver driver;
2290 FT_Memory memory;
2291 FT_Face face;
2292 FT_ListNode node;
2293
2294
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00002295 if ( !size )
David Turnerd2b1f351999-12-16 23:11:37 +00002296 return FT_Err_Invalid_Size_Handle;
2297
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00002298 face = size->face;
2299 if ( !face )
2300 return FT_Err_Invalid_Face_Handle;
2301
2302 driver = face->driver;
David Turnerd2b1f351999-12-16 23:11:37 +00002303 if ( !driver )
2304 return FT_Err_Invalid_Driver_Handle;
2305
David Turnerf0df85b2000-06-22 00:17:42 +00002306 memory = driver->root.memory;
David Turnerd2b1f351999-12-16 23:11:37 +00002307
2308 error = FT_Err_Ok;
David Turnerd2b1f351999-12-16 23:11:37 +00002309 node = FT_List_Find( &face->sizes_list, size );
2310 if ( node )
2311 {
2312 FT_List_Remove( &face->sizes_list, node );
David Turnere459d742002-03-22 13:52:37 +00002313 FT_FREE( node );
David Turnerd2b1f351999-12-16 23:11:37 +00002314
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00002315 if ( face->size == size )
David Turnerd2b1f351999-12-16 23:11:37 +00002316 {
2317 face->size = 0;
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00002318 if ( face->sizes_list.head )
David Turnerd2b1f351999-12-16 23:11:37 +00002319 face->size = (FT_Size)(face->sizes_list.head->data);
2320 }
2321
2322 destroy_size( memory, size, driver );
2323 }
2324 else
2325 error = FT_Err_Invalid_Size_Handle;
2326
Werner Lembergcf24d512001-06-18 14:23:45 +00002327 return error;
David Turnerd2b1f351999-12-16 23:11:37 +00002328 }
2329
2330
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002331 /* documentation is in ftobjs.h */
2332
2333 FT_BASE_DEF( FT_Error )
2334 FT_Match_Size( FT_Face face,
2335 FT_Size_Request req,
2336 FT_Bool ignore_width,
Werner Lemberg8c4120d2007-01-15 06:42:40 +00002337 FT_ULong* size_index )
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002338 {
2339 FT_Int i;
2340 FT_Long w, h;
2341
2342
2343 if ( !FT_HAS_FIXED_SIZES( face ) )
2344 return FT_Err_Invalid_Face_Handle;
2345
2346 /* FT_Bitmap_Size doesn't provide enough info... */
2347 if ( req->type != FT_SIZE_REQUEST_TYPE_NOMINAL )
2348 return FT_Err_Unimplemented_Feature;
2349
Werner Lemberg9cc4aed2006-01-26 21:03:58 +00002350 w = FT_REQUEST_WIDTH ( req );
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002351 h = FT_REQUEST_HEIGHT( req );
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002352
2353 if ( req->width && !req->height )
2354 h = w;
2355 else if ( !req->width && req->height )
2356 w = h;
2357
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002358 w = FT_PIX_ROUND( w );
2359 h = FT_PIX_ROUND( h );
2360
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002361 for ( i = 0; i < face->num_fixed_sizes; i++ )
2362 {
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002363 FT_Bitmap_Size* bsize = face->available_sizes + i;
2364
2365
2366 if ( h != FT_PIX_ROUND( bsize->y_ppem ) )
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002367 continue;
2368
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002369 if ( w == FT_PIX_ROUND( bsize->x_ppem ) || ignore_width )
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002370 {
Werner Lemberg8c4120d2007-01-15 06:42:40 +00002371 if ( size_index )
2372 *size_index = (FT_ULong)i;
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002373
2374 return FT_Err_Ok;
2375 }
2376 }
2377
2378 return FT_Err_Invalid_Pixel_Size;
2379 }
2380
2381
Wu, Chia-I (吳佳一)212aee02006-01-15 06:24:53 +00002382 /* documentation is in ftobjs.h */
2383
2384 FT_BASE_DEF( void )
Wu, Chia-I (吳佳一)ea1e8d32006-01-15 15:01:45 +00002385 ft_synthesize_vertical_metrics( FT_Glyph_Metrics* metrics,
2386 FT_Pos advance )
Wu, Chia-I (吳佳一)212aee02006-01-15 06:24:53 +00002387 {
Werner Lemberg1723dcc2006-01-15 07:30:32 +00002388 /* the factor 1.2 is a heuristical value */
Wu, Chia-I (吳佳一)212aee02006-01-15 06:24:53 +00002389 if ( !advance )
2390 advance = metrics->height * 12 / 10;
2391
2392 metrics->vertBearingX = -( metrics->width / 2 );
2393 metrics->vertBearingY = ( advance - metrics->height ) / 2;
2394 metrics->vertAdvance = advance;
2395 }
2396
2397
Werner Lembergf814d0f2001-06-27 16:18:10 +00002398 static void
2399 ft_recompute_scaled_metrics( FT_Face face,
2400 FT_Size_Metrics* metrics )
Werner Lembergdeb4e982000-06-29 03:14:25 +00002401 {
Werner Lemberga929ba92000-06-25 06:47:11 +00002402 /* Compute root ascender, descender, test height, and max_advance */
Werner Lembergdeb4e982000-06-29 03:14:25 +00002403
Wu, Chia-I (吳佳一)2e48a1a2006-02-27 09:18:07 +00002404#ifdef GRID_FIT_METRICS
David Turnerb4636652006-02-26 07:57:45 +00002405 metrics->ascender = FT_PIX_CEIL( FT_MulFix( face->ascender,
2406 metrics->y_scale ) );
2407
2408 metrics->descender = FT_PIX_FLOOR( FT_MulFix( face->descender,
2409 metrics->y_scale ) );
2410
2411 metrics->height = FT_PIX_ROUND( FT_MulFix( face->height,
2412 metrics->y_scale ) );
2413
2414 metrics->max_advance = FT_PIX_ROUND( FT_MulFix( face->max_advance_width,
2415 metrics->x_scale ) );
Wu, Chia-I (吳佳一)2e48a1a2006-02-27 09:18:07 +00002416#else /* !GRID_FIT_METRICS */
Wu, Chia-I (吳佳一)dcb8b712005-12-16 14:27:14 +00002417 metrics->ascender = FT_MulFix( face->ascender,
2418 metrics->y_scale );
Werner Lemberga929ba92000-06-25 06:47:11 +00002419
Wu, Chia-I (吳佳一)dcb8b712005-12-16 14:27:14 +00002420 metrics->descender = FT_MulFix( face->descender,
2421 metrics->y_scale );
Werner Lemberga929ba92000-06-25 06:47:11 +00002422
Wu, Chia-I (吳佳一)dcb8b712005-12-16 14:27:14 +00002423 metrics->height = FT_MulFix( face->height,
2424 metrics->y_scale );
Werner Lemberga929ba92000-06-25 06:47:11 +00002425
Wu, Chia-I (吳佳一)dcb8b712005-12-16 14:27:14 +00002426 metrics->max_advance = FT_MulFix( face->max_advance_width,
2427 metrics->x_scale );
Wu, Chia-I (吳佳一)2e48a1a2006-02-27 09:18:07 +00002428#endif /* !GRID_FIT_METRICS */
Werner Lemberga929ba92000-06-25 06:47:11 +00002429 }
2430
2431
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002432 FT_BASE_DEF( void )
2433 FT_Select_Metrics( FT_Face face,
2434 FT_ULong strike_index )
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002435 {
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002436 FT_Size_Metrics* metrics;
2437 FT_Bitmap_Size* bsize;
2438
2439
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002440 metrics = &face->size->metrics;
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002441 bsize = face->available_sizes + strike_index;
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002442
Werner Lembergbe3c9812006-01-27 14:16:16 +00002443 metrics->x_ppem = (FT_UShort)( ( bsize->x_ppem + 32 ) >> 6 );
2444 metrics->y_ppem = (FT_UShort)( ( bsize->y_ppem + 32 ) >> 6 );
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002445
2446 if ( FT_IS_SCALABLE( face ) )
2447 {
2448 metrics->x_scale = FT_DivFix( bsize->x_ppem,
2449 face->units_per_EM );
2450 metrics->y_scale = FT_DivFix( bsize->y_ppem,
2451 face->units_per_EM );
2452
2453 ft_recompute_scaled_metrics( face, metrics );
2454 }
2455 else
2456 {
Werner Lemberg14de1112009-02-24 21:34:51 +00002457 metrics->x_scale = 1L << 16;
2458 metrics->y_scale = 1L << 16;
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002459 metrics->ascender = bsize->y_ppem;
2460 metrics->descender = 0;
2461 metrics->height = bsize->height << 6;
2462 metrics->max_advance = bsize->x_ppem;
2463 }
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002464 }
2465
2466
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002467 FT_BASE_DEF( void )
2468 FT_Request_Metrics( FT_Face face,
2469 FT_Size_Request req )
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002470 {
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002471 FT_Size_Metrics* metrics;
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002472
2473
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002474 metrics = &face->size->metrics;
2475
2476 if ( FT_IS_SCALABLE( face ) )
2477 {
Werner Lembergce280a22007-06-03 05:58:30 +00002478 FT_Long w = 0, h = 0, scaled_w = 0, scaled_h = 0;
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002479
2480
2481 switch ( req->type )
2482 {
2483 case FT_SIZE_REQUEST_TYPE_NOMINAL:
2484 w = h = face->units_per_EM;
2485 break;
Werner Lembergf1c2b912006-01-13 14:53:28 +00002486
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002487 case FT_SIZE_REQUEST_TYPE_REAL_DIM:
2488 w = h = face->ascender - face->descender;
2489 break;
Werner Lembergf1c2b912006-01-13 14:53:28 +00002490
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002491 case FT_SIZE_REQUEST_TYPE_BBOX:
2492 w = face->bbox.xMax - face->bbox.xMin;
2493 h = face->bbox.yMax - face->bbox.yMin;
2494 break;
Werner Lembergf1c2b912006-01-13 14:53:28 +00002495
Werner Lembergb9933f42007-06-01 21:27:12 +00002496 case FT_SIZE_REQUEST_TYPE_CELL:
2497 w = face->max_advance_width;
2498 h = face->ascender - face->descender;
2499 break;
2500
Wu, Chia-I (吳佳一)a8e7a012006-02-24 06:11:30 +00002501 case FT_SIZE_REQUEST_TYPE_SCALES:
2502 metrics->x_scale = (FT_Fixed)req->width;
2503 metrics->y_scale = (FT_Fixed)req->height;
2504 if ( !metrics->x_scale )
2505 metrics->x_scale = metrics->y_scale;
2506 else if ( !metrics->y_scale )
2507 metrics->y_scale = metrics->x_scale;
2508 goto Calculate_Ppem;
Wu, Chia-I (吳佳一)a8e7a012006-02-24 06:11:30 +00002509
Werner Lembergb9933f42007-06-01 21:27:12 +00002510 case FT_SIZE_REQUEST_TYPE_MAX:
2511 break;
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002512 }
2513
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002514 /* to be on the safe side */
Wu, Chia-I (吳佳一)e5ff0592006-01-15 06:00:49 +00002515 if ( w < 0 )
2516 w = -w;
2517
2518 if ( h < 0 )
2519 h = -h;
2520
Werner Lemberg9cc4aed2006-01-26 21:03:58 +00002521 scaled_w = FT_REQUEST_WIDTH ( req );
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002522 scaled_h = FT_REQUEST_HEIGHT( req );
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002523
2524 /* determine scales */
2525 if ( req->width )
2526 {
2527 metrics->x_scale = FT_DivFix( scaled_w, w );
2528
2529 if ( req->height )
2530 {
2531 metrics->y_scale = FT_DivFix( scaled_h, h );
2532
2533 if ( req->type == FT_SIZE_REQUEST_TYPE_CELL )
2534 {
2535 if ( metrics->y_scale > metrics->x_scale )
2536 metrics->y_scale = metrics->x_scale;
2537 else
2538 metrics->x_scale = metrics->y_scale;
2539 }
2540 }
2541 else
2542 {
2543 metrics->y_scale = metrics->x_scale;
2544 scaled_h = FT_MulDiv( scaled_w, h, w );
2545 }
2546 }
2547 else
2548 {
2549 metrics->x_scale = metrics->y_scale = FT_DivFix( scaled_h, h );
2550 scaled_w = FT_MulDiv( scaled_h, w, h );
2551 }
2552
Wu, Chia-I (吳佳一)a8e7a012006-02-24 06:11:30 +00002553 Calculate_Ppem:
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002554 /* calculate the ppems */
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002555 if ( req->type != FT_SIZE_REQUEST_TYPE_NOMINAL )
2556 {
2557 scaled_w = FT_MulFix( face->units_per_EM, metrics->x_scale );
2558 scaled_h = FT_MulFix( face->units_per_EM, metrics->y_scale );
2559 }
2560
Werner Lembergbe3c9812006-01-27 14:16:16 +00002561 metrics->x_ppem = (FT_UShort)( ( scaled_w + 32 ) >> 6 );
2562 metrics->y_ppem = (FT_UShort)( ( scaled_h + 32 ) >> 6 );
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002563
2564 ft_recompute_scaled_metrics( face, metrics );
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002565 }
2566 else
2567 {
2568 FT_ZERO( metrics );
Werner Lemberg14de1112009-02-24 21:34:51 +00002569 metrics->x_scale = 1L << 16;
2570 metrics->y_scale = 1L << 16;
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002571 }
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002572 }
2573
2574
2575 /* documentation is in freetype.h */
2576
2577 FT_EXPORT_DEF( FT_Error )
2578 FT_Select_Size( FT_Face face,
2579 FT_Int strike_index )
2580 {
Werner Lemberg9cc4aed2006-01-26 21:03:58 +00002581 FT_Driver_Class clazz;
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002582
2583
2584 if ( !face || !FT_HAS_FIXED_SIZES( face ) )
2585 return FT_Err_Invalid_Face_Handle;
2586
2587 if ( strike_index < 0 || strike_index >= face->num_fixed_sizes )
2588 return FT_Err_Invalid_Argument;
2589
2590 clazz = face->driver->clazz;
2591
2592 if ( clazz->select_size )
2593 return clazz->select_size( face->size, (FT_ULong)strike_index );
2594
2595 FT_Select_Metrics( face, (FT_ULong)strike_index );
2596
2597 return FT_Err_Ok;
2598 }
2599
2600
2601 /* documentation is in freetype.h */
2602
2603 FT_EXPORT_DEF( FT_Error )
2604 FT_Request_Size( FT_Face face,
2605 FT_Size_Request req )
2606 {
Werner Lemberg9cc4aed2006-01-26 21:03:58 +00002607 FT_Driver_Class clazz;
2608 FT_ULong strike_index;
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002609
2610
2611 if ( !face )
2612 return FT_Err_Invalid_Face_Handle;
2613
2614 if ( !req || req->width < 0 || req->height < 0 ||
2615 req->type >= FT_SIZE_REQUEST_TYPE_MAX )
2616 return FT_Err_Invalid_Argument;
2617
2618 clazz = face->driver->clazz;
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002619
2620 if ( clazz->request_size )
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002621 return clazz->request_size( face->size, req );
2622
Wu, Chia-I (吳佳一)e33dc2e2006-01-14 05:09:30 +00002623 /*
Werner Lemberg3d8eeb82006-01-14 07:10:45 +00002624 * The reason that a driver doesn't have `request_size' defined is
2625 * either that the scaling here suffices or that the supported formats
2626 * are bitmap-only and size matching is not implemented.
Wu, Chia-I (吳佳一)e33dc2e2006-01-14 05:09:30 +00002627 *
2628 * In the latter case, a simple size matching is done.
2629 */
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002630 if ( !FT_IS_SCALABLE( face ) && FT_HAS_FIXED_SIZES( face ) )
Wu, Chia-I (吳佳一)e33dc2e2006-01-14 05:09:30 +00002631 {
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002632 FT_Error error;
Wu, Chia-I (吳佳一)e33dc2e2006-01-14 05:09:30 +00002633
2634
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002635 error = FT_Match_Size( face, req, 0, &strike_index );
2636 if ( error )
2637 return error;
Wu, Chia-I (吳佳一)e33dc2e2006-01-14 05:09:30 +00002638
Werner Lemberg9cc4aed2006-01-26 21:03:58 +00002639 FT_TRACE3(( "FT_Request_Size: bitmap strike %lu matched\n",
2640 strike_index ));
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002641
2642 return FT_Select_Size( face, (FT_Int)strike_index );
Wu, Chia-I (吳佳一)e33dc2e2006-01-14 05:09:30 +00002643 }
2644
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00002645 FT_Request_Metrics( face, req );
2646
2647 return FT_Err_Ok;
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002648 }
2649
2650
2651 /* documentation is in freetype.h */
2652
2653 FT_EXPORT_DEF( FT_Error )
Werner Lembergf814d0f2001-06-27 16:18:10 +00002654 FT_Set_Char_Size( FT_Face face,
2655 FT_F26Dot6 char_width,
2656 FT_F26Dot6 char_height,
2657 FT_UInt horz_resolution,
2658 FT_UInt vert_resolution )
David Turnerd2b1f351999-12-16 23:11:37 +00002659 {
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002660 FT_Size_RequestRec req;
David Turnerd2b1f351999-12-16 23:11:37 +00002661
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00002662
Wu, Chia-I (吳佳一)cffa8b62006-02-27 11:11:40 +00002663 if ( !char_width )
2664 char_width = char_height;
2665 else if ( !char_height )
2666 char_height = char_width;
2667
Werner Lemberg74781972007-04-03 19:39:28 +00002668 if ( !horz_resolution )
David Turner7338ec22007-04-03 14:30:34 +00002669 horz_resolution = vert_resolution;
Werner Lemberg74781972007-04-03 19:39:28 +00002670 else if ( !vert_resolution )
David Turner7338ec22007-04-03 14:30:34 +00002671 vert_resolution = horz_resolution;
2672
Wu, Chia-I (吳佳一)2e48a1a2006-02-27 09:18:07 +00002673 if ( char_width < 1 * 64 )
2674 char_width = 1 * 64;
2675 if ( char_height < 1 * 64 )
2676 char_height = 1 * 64;
2677
Werner Lemberg106eaf12007-05-03 07:07:47 +00002678 if ( !horz_resolution )
2679 horz_resolution = vert_resolution = 72;
2680
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002681 req.type = FT_SIZE_REQUEST_TYPE_NOMINAL;
2682 req.width = char_width;
2683 req.height = char_height;
Werner Lemberg106eaf12007-05-03 07:07:47 +00002684 req.horiResolution = horz_resolution;
2685 req.vertResolution = vert_resolution;
David Turnerd2b1f351999-12-16 23:11:37 +00002686
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002687 return FT_Request_Size( face, &req );
David Turnerd2b1f351999-12-16 23:11:37 +00002688 }
2689
2690
Werner Lemberg90a03302000-11-07 17:21:11 +00002691 /* documentation is in freetype.h */
2692
Werner Lembergf814d0f2001-06-27 16:18:10 +00002693 FT_EXPORT_DEF( FT_Error )
2694 FT_Set_Pixel_Sizes( FT_Face face,
2695 FT_UInt pixel_width,
2696 FT_UInt pixel_height )
David Turnerd2b1f351999-12-16 23:11:37 +00002697 {
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002698 FT_Size_RequestRec req;
David Turnerd2b1f351999-12-16 23:11:37 +00002699
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00002700
Wu, Chia-I (吳佳一)2e48a1a2006-02-27 09:18:07 +00002701 if ( pixel_width == 0 )
2702 pixel_width = pixel_height;
2703 else if ( pixel_height == 0 )
2704 pixel_height = pixel_width;
2705
2706 if ( pixel_width < 1 )
2707 pixel_width = 1;
2708 if ( pixel_height < 1 )
2709 pixel_height = 1;
2710
Werner Lemberg6e87ed92007-01-26 22:18:56 +00002711 /* use `>=' to avoid potential compiler warning on 16bit platforms */
Wu, Chia-I (吳佳一)2e48a1a2006-02-27 09:18:07 +00002712 if ( pixel_width >= 0xFFFFU )
2713 pixel_width = 0xFFFFU;
2714 if ( pixel_height >= 0xFFFFU )
2715 pixel_height = 0xFFFFU;
2716
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002717 req.type = FT_SIZE_REQUEST_TYPE_NOMINAL;
2718 req.width = pixel_width << 6;
2719 req.height = pixel_height << 6;
2720 req.horiResolution = 0;
2721 req.vertResolution = 0;
David Turnerd2b1f351999-12-16 23:11:37 +00002722
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00002723 return FT_Request_Size( face, &req );
David Turnerd2b1f351999-12-16 23:11:37 +00002724 }
2725
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00002726
Werner Lemberg90a03302000-11-07 17:21:11 +00002727 /* documentation is in freetype.h */
2728
Werner Lembergf814d0f2001-06-27 16:18:10 +00002729 FT_EXPORT_DEF( FT_Error )
2730 FT_Get_Kerning( FT_Face face,
2731 FT_UInt left_glyph,
2732 FT_UInt right_glyph,
2733 FT_UInt kern_mode,
2734 FT_Vector *akerning )
David Turnerd2b1f351999-12-16 23:11:37 +00002735 {
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00002736 FT_Error error = FT_Err_Ok;
David Turnerd2b1f351999-12-16 23:11:37 +00002737 FT_Driver driver;
David Turnerd2b1f351999-12-16 23:11:37 +00002738
Werner Lemberga8bbc262000-07-01 14:06:46 +00002739
David Turnerd2b1f351999-12-16 23:11:37 +00002740 if ( !face )
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00002741 return FT_Err_Invalid_Face_Handle;
2742
Werner Lemberg4b680072000-11-07 06:30:29 +00002743 if ( !akerning )
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00002744 return FT_Err_Invalid_Argument;
David Turnerd2b1f351999-12-16 23:11:37 +00002745
2746 driver = face->driver;
David Turnerd2b1f351999-12-16 23:11:37 +00002747
Werner Lemberg4b680072000-11-07 06:30:29 +00002748 akerning->x = 0;
2749 akerning->y = 0;
Werner Lemberg5aa646c2000-07-14 06:16:47 +00002750
David Turnerf0df85b2000-06-22 00:17:42 +00002751 if ( driver->clazz->get_kerning )
David Turnerd2b1f351999-12-16 23:11:37 +00002752 {
David Turnerf0df85b2000-06-22 00:17:42 +00002753 error = driver->clazz->get_kerning( face,
Werner Lemberga929ba92000-06-25 06:47:11 +00002754 left_glyph,
2755 right_glyph,
Werner Lemberg4b680072000-11-07 06:30:29 +00002756 akerning );
Werner Lemberg5aa646c2000-07-14 06:16:47 +00002757 if ( !error )
David Turnerf9ca2bb2000-06-30 23:12:55 +00002758 {
David Turnerb08fe2d2002-08-27 20:20:29 +00002759 if ( kern_mode != FT_KERNING_UNSCALED )
David Turnerf9ca2bb2000-06-30 23:12:55 +00002760 {
Werner Lemberg4b680072000-11-07 06:30:29 +00002761 akerning->x = FT_MulFix( akerning->x, face->size->metrics.x_scale );
2762 akerning->y = FT_MulFix( akerning->y, face->size->metrics.y_scale );
Werner Lemberg5aa646c2000-07-14 06:16:47 +00002763
David Turnerb08fe2d2002-08-27 20:20:29 +00002764 if ( kern_mode != FT_KERNING_UNFITTED )
Werner Lemberg5aa646c2000-07-14 06:16:47 +00002765 {
Werner Lemberg133eee02004-12-12 06:55:40 +00002766 /* we scale down kerning values for small ppem values */
2767 /* to avoid that rounding makes them too big. */
2768 /* `25' has been determined heuristically. */
2769 if ( face->size->metrics.x_ppem < 25 )
2770 akerning->x = FT_MulDiv( akerning->x,
2771 face->size->metrics.x_ppem, 25 );
2772 if ( face->size->metrics.y_ppem < 25 )
2773 akerning->y = FT_MulDiv( akerning->y,
2774 face->size->metrics.y_ppem, 25 );
2775
2776 akerning->x = FT_PIX_ROUND( akerning->x );
2777 akerning->y = FT_PIX_ROUND( akerning->y );
Werner Lemberg5aa646c2000-07-14 06:16:47 +00002778 }
David Turnerf9ca2bb2000-06-30 23:12:55 +00002779 }
2780 }
2781 }
David Turnerd2b1f351999-12-16 23:11:37 +00002782
David Turnerd2b1f351999-12-16 23:11:37 +00002783 return error;
2784 }
2785
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00002786
Werner Lemberg90a03302000-11-07 17:21:11 +00002787 /* documentation is in freetype.h */
2788
Werner Lembergf814d0f2001-06-27 16:18:10 +00002789 FT_EXPORT_DEF( FT_Error )
Wu, Chia-I (吳佳一)108fdbb2006-01-16 15:35:56 +00002790 FT_Get_Track_Kerning( FT_Face face,
2791 FT_Fixed point_size,
2792 FT_Int degree,
2793 FT_Fixed* akerning )
2794 {
2795 FT_Service_Kerning service;
2796 FT_Error error = FT_Err_Ok;
Wu, Chia-I (吳佳一)108fdbb2006-01-16 15:35:56 +00002797
2798
2799 if ( !face )
2800 return FT_Err_Invalid_Face_Handle;
2801
2802 if ( !akerning )
2803 return FT_Err_Invalid_Argument;
2804
Wu, Chia-I (吳佳一)108fdbb2006-01-16 15:35:56 +00002805 FT_FACE_FIND_SERVICE( face, service, KERNING );
2806 if ( !service )
2807 return FT_Err_Unimplemented_Feature;
2808
2809 error = service->get_track( face,
2810 point_size,
2811 degree,
2812 akerning );
2813
2814 return error;
2815 }
2816
2817
2818 /* documentation is in freetype.h */
2819
2820 FT_EXPORT_DEF( FT_Error )
Werner Lembergf814d0f2001-06-27 16:18:10 +00002821 FT_Select_Charmap( FT_Face face,
2822 FT_Encoding encoding )
David Turner0a29c692000-05-12 17:09:38 +00002823 {
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00002824 FT_CharMap* cur;
2825 FT_CharMap* limit;
David Turnere49ab252000-05-16 23:44:38 +00002826
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00002827
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00002828 if ( !face )
2829 return FT_Err_Invalid_Face_Handle;
2830
Werner Lemberge88c5262006-10-24 05:46:26 +00002831 if ( encoding == FT_ENCODING_NONE )
2832 return FT_Err_Invalid_Argument;
2833
Werner Lembergc8c6bf52003-04-23 05:38:13 +00002834 /* FT_ENCODING_UNICODE is special. We try to find the `best' Unicode */
2835 /* charmap available, i.e., one with UCS-4 characters, if possible. */
2836 /* */
2837 /* This is done by find_unicode_charmap() above, to share code. */
Antoine Lecac96f69d2002-12-03 00:39:16 +00002838 if ( encoding == FT_ENCODING_UNICODE )
2839 return find_unicode_charmap( face );
2840
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00002841 cur = face->charmaps;
2842 if ( !cur )
2843 return FT_Err_Invalid_CharMap_Handle;
2844
2845 limit = cur + face->num_charmaps;
2846
David Turner0a29c692000-05-12 17:09:38 +00002847 for ( ; cur < limit; cur++ )
2848 {
2849 if ( cur[0]->encoding == encoding )
2850 {
2851 face->charmap = cur[0];
2852 return 0;
2853 }
2854 }
Werner Lembergdeb4e982000-06-29 03:14:25 +00002855
David Turner0a29c692000-05-12 17:09:38 +00002856 return FT_Err_Invalid_Argument;
2857 }
2858
2859
Werner Lemberg90a03302000-11-07 17:21:11 +00002860 /* documentation is in freetype.h */
2861
Werner Lembergf814d0f2001-06-27 16:18:10 +00002862 FT_EXPORT_DEF( FT_Error )
2863 FT_Set_Charmap( FT_Face face,
2864 FT_CharMap charmap )
David Turner0a29c692000-05-12 17:09:38 +00002865 {
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00002866 FT_CharMap* cur;
2867 FT_CharMap* limit;
David Turnere49ab252000-05-16 23:44:38 +00002868
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00002869
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00002870 if ( !face )
2871 return FT_Err_Invalid_Face_Handle;
2872
2873 cur = face->charmaps;
2874 if ( !cur )
2875 return FT_Err_Invalid_CharMap_Handle;
Werner Lemberg9a966b72007-10-15 17:21:32 +00002876 if ( FT_Get_CMap_Format( charmap ) == 14 )
2877 return FT_Err_Invalid_Argument;
Werner Lemberg2fbf7e42000-06-02 00:01:14 +00002878
2879 limit = cur + face->num_charmaps;
2880
David Turner0a29c692000-05-12 17:09:38 +00002881 for ( ; cur < limit; cur++ )
2882 {
2883 if ( cur[0] == charmap )
2884 {
2885 face->charmap = cur[0];
2886 return 0;
2887 }
2888 }
2889 return FT_Err_Invalid_Argument;
2890 }
David Turnerd2b1f351999-12-16 23:11:37 +00002891
Werner Lemberga3b6c6c2000-05-31 06:55:12 +00002892
Werner Lemberge95365b2004-04-24 14:43:37 +00002893 /* documentation is in freetype.h */
2894
2895 FT_EXPORT_DEF( FT_Int )
2896 FT_Get_Charmap_Index( FT_CharMap charmap )
2897 {
2898 FT_Int i;
2899
2900
2901 for ( i = 0; i < charmap->face->num_charmaps; i++ )
2902 if ( charmap->face->charmaps[i] == charmap )
2903 break;
2904
2905 FT_ASSERT( i < charmap->face->num_charmaps );
2906
2907 return i;
2908 }
2909
2910
Werner Lemberge70371c2005-05-27 06:01:28 +00002911 static void
2912 ft_cmap_done_internal( FT_CMap cmap )
2913 {
2914 FT_CMap_Class clazz = cmap->clazz;
2915 FT_Face face = cmap->charmap.face;
2916 FT_Memory memory = FT_FACE_MEMORY(face);
2917
2918
2919 if ( clazz->done )
2920 clazz->done( cmap );
2921
2922 FT_FREE( cmap );
2923 }
2924
2925
David Turner4e7eeee2002-02-28 16:10:29 +00002926 FT_BASE_DEF( void )
2927 FT_CMap_Done( FT_CMap cmap )
2928 {
2929 if ( cmap )
2930 {
Werner Lemberge70371c2005-05-27 06:01:28 +00002931 FT_Face face = cmap->charmap.face;
2932 FT_Memory memory = FT_FACE_MEMORY( face );
2933 FT_Error error;
2934 FT_Int i, j;
David Turnerbc82f1b2002-03-01 02:26:22 +00002935
Werner Lembergf8ba2002002-03-30 13:16:35 +00002936
Werner Lemberge70371c2005-05-27 06:01:28 +00002937 for ( i = 0; i < face->num_charmaps; i++ )
2938 {
2939 if ( (FT_CMap)face->charmaps[i] == cmap )
2940 {
2941 FT_CharMap last_charmap = face->charmaps[face->num_charmaps - 1];
David Turner4e7eeee2002-02-28 16:10:29 +00002942
Werner Lemberge70371c2005-05-27 06:01:28 +00002943
2944 if ( FT_RENEW_ARRAY( face->charmaps,
2945 face->num_charmaps,
2946 face->num_charmaps - 1 ) )
2947 return;
2948
2949 /* remove it from our list of charmaps */
2950 for ( j = i + 1; j < face->num_charmaps; j++ )
2951 {
2952 if ( j == face->num_charmaps - 1 )
2953 face->charmaps[j - 1] = last_charmap;
2954 else
2955 face->charmaps[j - 1] = face->charmaps[j];
2956 }
2957
2958 face->num_charmaps--;
2959
2960 if ( (FT_CMap)face->charmap == cmap )
2961 face->charmap = NULL;
2962
2963 ft_cmap_done_internal( cmap );
2964
2965 break;
2966 }
2967 }
David Turner4e7eeee2002-02-28 16:10:29 +00002968 }
2969 }
2970
2971
2972 FT_BASE_DEF( FT_Error )
Werner Lemberg9cc4aed2006-01-26 21:03:58 +00002973 FT_CMap_New( FT_CMap_Class clazz,
2974 FT_Pointer init_data,
2975 FT_CharMap charmap,
2976 FT_CMap *acmap )
David Turnerbc82f1b2002-03-01 02:26:22 +00002977 {
Werner Lemberg8acb8672005-03-08 11:43:36 +00002978 FT_Error error = FT_Err_Ok;
David Turner4e7eeee2002-02-28 16:10:29 +00002979 FT_Face face;
2980 FT_Memory memory;
2981 FT_CMap cmap;
David Turnerbc82f1b2002-03-01 02:26:22 +00002982
Werner Lembergf8ba2002002-03-30 13:16:35 +00002983
David Turner4e7eeee2002-02-28 16:10:29 +00002984 if ( clazz == NULL || charmap == NULL || charmap->face == NULL )
2985 return FT_Err_Invalid_Argument;
2986
2987 face = charmap->face;
Werner Lembergf35ff802003-06-02 21:58:05 +00002988 memory = FT_FACE_MEMORY( face );
David Turner4e7eeee2002-02-28 16:10:29 +00002989
David Turnere459d742002-03-22 13:52:37 +00002990 if ( !FT_ALLOC( cmap, clazz->size ) )
David Turner4e7eeee2002-02-28 16:10:29 +00002991 {
2992 cmap->charmap = *charmap;
2993 cmap->clazz = clazz;
David Turnerbc82f1b2002-03-01 02:26:22 +00002994
David Turner4e7eeee2002-02-28 16:10:29 +00002995 if ( clazz->init )
2996 {
David Turnerbc82f1b2002-03-01 02:26:22 +00002997 error = clazz->init( cmap, init_data );
Werner Lembergf8ba2002002-03-30 13:16:35 +00002998 if ( error )
David Turner4e7eeee2002-02-28 16:10:29 +00002999 goto Fail;
3000 }
David Turnerbc82f1b2002-03-01 02:26:22 +00003001
David Turner4e7eeee2002-02-28 16:10:29 +00003002 /* add it to our list of charmaps */
David Turnere459d742002-03-22 13:52:37 +00003003 if ( FT_RENEW_ARRAY( face->charmaps,
3004 face->num_charmaps,
Werner Lemberg8acb8672005-03-08 11:43:36 +00003005 face->num_charmaps + 1 ) )
David Turner4e7eeee2002-02-28 16:10:29 +00003006 goto Fail;
David Turnerbc82f1b2002-03-01 02:26:22 +00003007
Werner Lembergf8ba2002002-03-30 13:16:35 +00003008 face->charmaps[face->num_charmaps++] = (FT_CharMap)cmap;
David Turner4e7eeee2002-02-28 16:10:29 +00003009 }
David Turnerbc82f1b2002-03-01 02:26:22 +00003010
David Turner4e7eeee2002-02-28 16:10:29 +00003011 Exit:
3012 if ( acmap )
3013 *acmap = cmap;
3014
3015 return error;
David Turnerbc82f1b2002-03-01 02:26:22 +00003016
David Turner4e7eeee2002-02-28 16:10:29 +00003017 Fail:
Werner Lemberge70371c2005-05-27 06:01:28 +00003018 ft_cmap_done_internal( cmap );
David Turner4e7eeee2002-02-28 16:10:29 +00003019 cmap = NULL;
3020 goto Exit;
David Turnerbc82f1b2002-03-01 02:26:22 +00003021 }
David Turner4e7eeee2002-02-28 16:10:29 +00003022
3023
Werner Lemberg90a03302000-11-07 17:21:11 +00003024 /* documentation is in freetype.h */
3025
Werner Lembergf814d0f2001-06-27 16:18:10 +00003026 FT_EXPORT_DEF( FT_UInt )
3027 FT_Get_Char_Index( FT_Face face,
3028 FT_ULong charcode )
David Turnerd2b1f351999-12-16 23:11:37 +00003029 {
David Turnered54f282002-03-22 17:09:52 +00003030 FT_UInt result = 0;
3031
3032
3033 if ( face && face->charmap )
3034 {
3035 FT_CMap cmap = FT_CMAP( face->charmap );
David Turner25a6e3a2002-06-10 23:03:35 +00003036
Werner Lembergf8ba2002002-03-30 13:16:35 +00003037
David Turnered54f282002-03-22 17:09:52 +00003038 result = cmap->clazz->char_index( cmap, charcode );
3039 }
3040 return result;
3041 }
3042
David Turnered54f282002-03-22 17:09:52 +00003043
Werner Lemberg0f7c2f12002-02-04 20:55:58 +00003044 /* documentation is in freetype.h */
3045
3046 FT_EXPORT_DEF( FT_ULong )
David Turner041889e2002-02-28 19:28:26 +00003047 FT_Get_First_Char( FT_Face face,
3048 FT_UInt *agindex )
Werner Lemberg0f7c2f12002-02-04 20:55:58 +00003049 {
Werner Lembergf8ba2002002-03-30 13:16:35 +00003050 FT_ULong result = 0;
3051 FT_UInt gindex = 0;
3052
David Turnerbc82f1b2002-03-01 02:26:22 +00003053
David Turner041889e2002-02-28 19:28:26 +00003054 if ( face && face->charmap )
3055 {
3056 gindex = FT_Get_Char_Index( face, 0 );
3057 if ( gindex == 0 )
3058 result = FT_Get_Next_Char( face, 0, &gindex );
3059 }
David Turnerbc82f1b2002-03-01 02:26:22 +00003060
David Turner041889e2002-02-28 19:28:26 +00003061 if ( agindex )
3062 *agindex = gindex;
David Turnerbc82f1b2002-03-01 02:26:22 +00003063
David Turner041889e2002-02-28 19:28:26 +00003064 return result;
3065 }
3066
David Turner041889e2002-02-28 19:28:26 +00003067
Werner Lemberg7b0cc662003-07-05 07:46:49 +00003068 /* documentation is in freetype.h */
David Turnered54f282002-03-22 17:09:52 +00003069
David Turnered54f282002-03-22 17:09:52 +00003070 FT_EXPORT_DEF( FT_ULong )
3071 FT_Get_Next_Char( FT_Face face,
3072 FT_ULong charcode,
3073 FT_UInt *agindex )
3074 {
Werner Lembergf8ba2002002-03-30 13:16:35 +00003075 FT_ULong result = 0;
3076 FT_UInt gindex = 0;
David Turnered54f282002-03-22 17:09:52 +00003077
3078
3079 if ( face && face->charmap )
3080 {
3081 FT_UInt32 code = (FT_UInt32)charcode;
3082 FT_CMap cmap = FT_CMAP( face->charmap );
3083
Werner Lembergf8ba2002002-03-30 13:16:35 +00003084
David Turnered54f282002-03-22 17:09:52 +00003085 gindex = cmap->clazz->char_next( cmap, &code );
3086 result = ( gindex == 0 ) ? 0 : code;
3087 }
3088
3089 if ( agindex )
3090 *agindex = gindex;
3091
3092 return result;
3093 }
3094
David Turnered54f282002-03-22 17:09:52 +00003095
Werner Lemberg90a03302000-11-07 17:21:11 +00003096 /* documentation is in freetype.h */
3097
Tom Kacvinskyff2714f2001-08-08 10:58:08 +00003098 FT_EXPORT_DEF( FT_UInt )
David Turnercf432db2007-10-19 12:36:40 +00003099 FT_Face_GetCharVariantIndex( FT_Face face,
3100 FT_ULong charcode,
3101 FT_ULong variantSelector )
Werner Lemberg9a966b72007-10-15 17:21:32 +00003102 {
3103 FT_UInt result = 0;
3104
3105
3106 if ( face && face->charmap &&
3107 face->charmap->encoding == FT_ENCODING_UNICODE )
3108 {
3109 FT_CharMap charmap = find_variant_selector_charmap( face );
3110 FT_CMap ucmap = FT_CMAP( face->charmap );
3111
3112
3113 if ( charmap != NULL )
3114 {
3115 FT_CMap vcmap = FT_CMAP( charmap );
3116
3117
3118 result = vcmap->clazz->char_var_index( vcmap, ucmap, charcode,
3119 variantSelector );
3120 }
3121 }
3122
3123 return result;
3124 }
3125
3126
3127 /* documentation is in freetype.h */
3128
3129 FT_EXPORT_DEF( FT_Int )
David Turnercf432db2007-10-19 12:36:40 +00003130 FT_Face_GetCharVariantIsDefault( FT_Face face,
3131 FT_ULong charcode,
3132 FT_ULong variantSelector )
Werner Lemberg9a966b72007-10-15 17:21:32 +00003133 {
3134 FT_Int result = -1;
3135
3136
3137 if ( face )
3138 {
3139 FT_CharMap charmap = find_variant_selector_charmap( face );
3140
3141
3142 if ( charmap != NULL )
3143 {
3144 FT_CMap vcmap = FT_CMAP( charmap );
3145
3146
3147 result = vcmap->clazz->char_var_default( vcmap, charcode,
3148 variantSelector );
3149 }
3150 }
3151
3152 return result;
3153 }
3154
3155
3156 /* documentation is in freetype.h */
3157
3158 FT_EXPORT_DEF( FT_UInt32* )
David Turnercf432db2007-10-19 12:36:40 +00003159 FT_Face_GetVariantSelectors( FT_Face face )
Werner Lemberg9a966b72007-10-15 17:21:32 +00003160 {
3161 FT_UInt32 *result = NULL;
3162
3163
3164 if ( face )
3165 {
3166 FT_CharMap charmap = find_variant_selector_charmap( face );
3167
3168
3169 if ( charmap != NULL )
3170 {
3171 FT_CMap vcmap = FT_CMAP( charmap );
3172 FT_Memory memory = FT_FACE_MEMORY( face );
3173
3174
3175 result = vcmap->clazz->variant_list( vcmap, memory );
3176 }
3177 }
3178
3179 return result;
3180 }
3181
3182
3183 /* documentation is in freetype.h */
3184
3185 FT_EXPORT_DEF( FT_UInt32* )
David Turnercf432db2007-10-19 12:36:40 +00003186 FT_Face_GetVariantsOfChar( FT_Face face,
3187 FT_ULong charcode )
Werner Lemberg9a966b72007-10-15 17:21:32 +00003188 {
3189 FT_UInt32 *result = NULL;
3190
3191
3192 if ( face )
3193 {
3194 FT_CharMap charmap = find_variant_selector_charmap( face );
3195
3196
3197 if ( charmap != NULL )
3198 {
3199 FT_CMap vcmap = FT_CMAP( charmap );
3200 FT_Memory memory = FT_FACE_MEMORY( face );
3201
3202
3203 result = vcmap->clazz->charvariant_list( vcmap, memory, charcode );
3204 }
3205 }
3206 return result;
3207 }
3208
3209
3210 /* documentation is in freetype.h */
3211
3212 FT_EXPORT_DEF( FT_UInt32* )
David Turnercf432db2007-10-19 12:36:40 +00003213 FT_Face_GetCharsOfVariant( FT_Face face,
3214 FT_ULong variantSelector )
Werner Lemberg9a966b72007-10-15 17:21:32 +00003215 {
3216 FT_UInt32 *result = NULL;
3217
3218
3219 if ( face )
3220 {
3221 FT_CharMap charmap = find_variant_selector_charmap( face );
3222
3223
3224 if ( charmap != NULL )
3225 {
3226 FT_CMap vcmap = FT_CMAP( charmap );
3227 FT_Memory memory = FT_FACE_MEMORY( face );
3228
3229
3230 result = vcmap->clazz->variantchar_list( vcmap, memory,
3231 variantSelector );
3232 }
3233 }
3234
3235 return result;
3236 }
3237
3238
3239 /* documentation is in freetype.h */
3240
3241 FT_EXPORT_DEF( FT_UInt )
Tom Kacvinskyff2714f2001-08-08 10:58:08 +00003242 FT_Get_Name_Index( FT_Face face,
3243 FT_String* glyph_name )
3244 {
3245 FT_UInt result = 0;
3246
3247
3248 if ( face && FT_HAS_GLYPH_NAMES( face ) )
3249 {
David Turnerc313c502003-09-11 19:51:54 +00003250 FT_Service_GlyphDict service;
Tom Kacvinskyff2714f2001-08-08 10:58:08 +00003251
Werner Lemberg013efd12003-09-17 05:26:33 +00003252
Werner Lemberg46333a12003-09-17 19:20:02 +00003253 FT_FACE_LOOKUP_SERVICE( face,
David Turnere2d12842003-09-21 17:15:55 +00003254 service,
3255 GLYPH_DICT );
Werner Lemberg013efd12003-09-17 05:26:33 +00003256
David Turnerc313c502003-09-11 19:51:54 +00003257 if ( service && service->name_index )
3258 result = service->name_index( face, glyph_name );
Werner Lemberg013efd12003-09-17 05:26:33 +00003259 }
3260
Tom Kacvinskyff2714f2001-08-08 10:58:08 +00003261 return result;
3262 }
3263
Werner Lembergaef3fc82001-12-17 16:21:22 +00003264
Tom Kacvinskyff2714f2001-08-08 10:58:08 +00003265 /* documentation is in freetype.h */
3266
Werner Lembergf814d0f2001-06-27 16:18:10 +00003267 FT_EXPORT_DEF( FT_Error )
3268 FT_Get_Glyph_Name( FT_Face face,
3269 FT_UInt glyph_index,
3270 FT_Pointer buffer,
3271 FT_UInt buffer_max )
David Turner6930b452000-07-19 17:13:03 +00003272 {
3273 FT_Error error = FT_Err_Invalid_Argument;
Werner Lembergeddd9902000-10-12 05:05:40 +00003274
Werner Lembergd060a752000-07-20 06:57:41 +00003275
David Turner6930b452000-07-19 17:13:03 +00003276 /* clean up buffer */
Werner Lembergd060a752000-07-20 06:57:41 +00003277 if ( buffer && buffer_max > 0 )
David Turner6930b452000-07-19 17:13:03 +00003278 ((FT_Byte*)buffer)[0] = 0;
Werner Lembergeddd9902000-10-12 05:05:40 +00003279
Werner Lembergfd97d132002-06-16 01:14:16 +00003280 if ( face &&
3281 glyph_index <= (FT_UInt)face->num_glyphs &&
3282 FT_HAS_GLYPH_NAMES( face ) )
David Turner6930b452000-07-19 17:13:03 +00003283 {
David Turnerc313c502003-09-11 19:51:54 +00003284 FT_Service_GlyphDict service;
David Turner6930b452000-07-19 17:13:03 +00003285
Werner Lemberg013efd12003-09-17 05:26:33 +00003286
Werner Lemberg46333a12003-09-17 19:20:02 +00003287 FT_FACE_LOOKUP_SERVICE( face,
David Turnere2d12842003-09-21 17:15:55 +00003288 service,
3289 GLYPH_DICT );
Werner Lembergd060a752000-07-20 06:57:41 +00003290
David Turnerc313c502003-09-11 19:51:54 +00003291 if ( service && service->get_name )
David Turnerc313c502003-09-11 19:51:54 +00003292 error = service->get_name( face, glyph_index, buffer, buffer_max );
David Turner6930b452000-07-19 17:13:03 +00003293 }
Werner Lembergd060a752000-07-20 06:57:41 +00003294
David Turner6930b452000-07-19 17:13:03 +00003295 return error;
Werner Lembergeddd9902000-10-12 05:05:40 +00003296 }
David Turner6930b452000-07-19 17:13:03 +00003297
3298
David Turner23bcde12001-10-17 13:48:10 +00003299 /* documentation is in freetype.h */
3300
3301 FT_EXPORT_DEF( const char* )
3302 FT_Get_Postscript_Name( FT_Face face )
3303 {
3304 const char* result = NULL;
Werner Lemberg1a0a9792002-01-03 22:06:13 +00003305
Werner Lembergc3b21602001-12-05 01:22:05 +00003306
David Turner23bcde12001-10-17 13:48:10 +00003307 if ( !face )
3308 goto Exit;
3309
David Turner23bcde12001-10-17 13:48:10 +00003310 if ( !result )
3311 {
David Turnerb72d8a82003-09-29 20:33:37 +00003312 FT_Service_PsFontName service;
Werner Lembergc3b21602001-12-05 01:22:05 +00003313
Werner Lemberg013efd12003-09-17 05:26:33 +00003314
Werner Lemberg46333a12003-09-17 19:20:02 +00003315 FT_FACE_LOOKUP_SERVICE( face,
David Turnere2d12842003-09-21 17:15:55 +00003316 service,
David Turnerb72d8a82003-09-29 20:33:37 +00003317 POSTSCRIPT_FONT_NAME );
David Turner23bcde12001-10-17 13:48:10 +00003318
David Turnerb72d8a82003-09-29 20:33:37 +00003319 if ( service && service->get_ps_font_name )
3320 result = service->get_ps_font_name( face );
David Turner23bcde12001-10-17 13:48:10 +00003321 }
Werner Lemberg013efd12003-09-17 05:26:33 +00003322
David Turner23bcde12001-10-17 13:48:10 +00003323 Exit:
3324 return result;
3325 }
3326
3327
Werner Lemberg90a03302000-11-07 17:21:11 +00003328 /* documentation is in tttables.h */
3329
Werner Lembergf814d0f2001-06-27 16:18:10 +00003330 FT_EXPORT_DEF( void* )
3331 FT_Get_Sfnt_Table( FT_Face face,
3332 FT_Sfnt_Tag tag )
David Turner99a4d932000-04-25 16:10:50 +00003333 {
Werner Lemberg40bb0962003-11-01 14:36:20 +00003334 void* table = 0;
3335 FT_Service_SFNT_Table service;
David Turnere49ab252000-05-16 23:44:38 +00003336
Werner Lemberg013efd12003-09-17 05:26:33 +00003337
David Turnerc313c502003-09-11 19:51:54 +00003338 if ( face && FT_IS_SFNT( face ) )
3339 {
David Turnerb72d8a82003-09-29 20:33:37 +00003340 FT_FACE_FIND_SERVICE( face, service, SFNT_TABLE );
David Turnerc313c502003-09-11 19:51:54 +00003341 if ( service != NULL )
3342 table = service->get_table( face, tag );
3343 }
David Turnere2d12842003-09-21 17:15:55 +00003344
David Turner99a4d932000-04-25 16:10:50 +00003345 return table;
David Turnere49ab252000-05-16 23:44:38 +00003346 }
David Turner99a4d932000-04-25 16:10:50 +00003347
3348
David Turner621e4882002-12-16 21:51:24 +00003349 /* documentation is in tttables.h */
3350
3351 FT_EXPORT_DEF( FT_Error )
Werner Lembergc8c6bf52003-04-23 05:38:13 +00003352 FT_Load_Sfnt_Table( FT_Face face,
3353 FT_ULong tag,
3354 FT_Long offset,
3355 FT_Byte* buffer,
3356 FT_ULong* length )
David Turner621e4882002-12-16 21:51:24 +00003357 {
David Turnerc313c502003-09-11 19:51:54 +00003358 FT_Service_SFNT_Table service;
David Turner621e4882002-12-16 21:51:24 +00003359
3360
3361 if ( !face || !FT_IS_SFNT( face ) )
3362 return FT_Err_Invalid_Face_Handle;
3363
David Turnerb72d8a82003-09-29 20:33:37 +00003364 FT_FACE_FIND_SERVICE( face, service, SFNT_TABLE );
David Turnerc313c502003-09-11 19:51:54 +00003365 if ( service == NULL )
David Turner621e4882002-12-16 21:51:24 +00003366 return FT_Err_Unimplemented_Feature;
David Turnere2d12842003-09-21 17:15:55 +00003367
David Turnerc313c502003-09-11 19:51:54 +00003368 return service->load_table( face, tag, offset, buffer, length );
David Turner621e4882002-12-16 21:51:24 +00003369 }
3370
3371
Werner Lemberg17439422004-08-11 05:25:37 +00003372 /* documentation is in tttables.h */
3373
3374 FT_EXPORT_DEF( FT_Error )
3375 FT_Sfnt_Table_Info( FT_Face face,
3376 FT_UInt table_index,
3377 FT_ULong *tag,
3378 FT_ULong *length )
3379 {
3380 FT_Service_SFNT_Table service;
3381
3382
3383 if ( !face || !FT_IS_SFNT( face ) )
3384 return FT_Err_Invalid_Face_Handle;
3385
3386 FT_FACE_FIND_SERVICE( face, service, SFNT_TABLE );
3387 if ( service == NULL )
3388 return FT_Err_Unimplemented_Feature;
3389
3390 return service->table_info( face, table_index, tag, length );
3391 }
3392
3393
Werner Lembergece8b202004-12-13 23:16:59 +00003394 /* documentation is in tttables.h */
3395
Werner Lemberg91a67472003-12-17 14:28:22 +00003396 FT_EXPORT_DEF( FT_ULong )
3397 FT_Get_CMap_Language_ID( FT_CharMap charmap )
3398 {
3399 FT_Service_TTCMaps service;
3400 FT_Face face;
3401 TT_CMapInfo cmap_info;
3402
David Turner87c0d302003-12-24 01:10:46 +00003403
Werner Lemberg91a67472003-12-17 14:28:22 +00003404 if ( !charmap || !charmap->face )
3405 return 0;
3406
3407 face = charmap->face;
3408 FT_FACE_FIND_SERVICE( face, service, TT_CMAP );
3409 if ( service == NULL )
3410 return 0;
3411 if ( service->get_cmap_info( charmap, &cmap_info ))
3412 return 0;
3413
3414 return cmap_info.language;
3415 }
3416
3417
Werner Lembergb826fa72007-05-19 07:18:48 +00003418 /* documentation is in tttables.h */
3419
3420 FT_EXPORT_DEF( FT_Long )
3421 FT_Get_CMap_Format( FT_CharMap charmap )
3422 {
3423 FT_Service_TTCMaps service;
3424 FT_Face face;
3425 TT_CMapInfo cmap_info;
3426
3427
3428 if ( !charmap || !charmap->face )
3429 return -1;
3430
3431 face = charmap->face;
3432 FT_FACE_FIND_SERVICE( face, service, TT_CMAP );
3433 if ( service == NULL )
3434 return -1;
3435 if ( service->get_cmap_info( charmap, &cmap_info ))
3436 return -1;
3437
3438 return cmap_info.format;
3439 }
3440
3441
Werner Lembergece8b202004-12-13 23:16:59 +00003442 /* documentation is in ftsizes.h */
3443
David Turnerb3ba40d2001-10-07 13:30:26 +00003444 FT_EXPORT_DEF( FT_Error )
Werner Lemberg80b8d772001-10-10 19:56:42 +00003445 FT_Activate_Size( FT_Size size )
David Turnerb3ba40d2001-10-07 13:30:26 +00003446 {
3447 FT_Face face;
Werner Lemberg1a0a9792002-01-03 22:06:13 +00003448
Werner Lemberg80b8d772001-10-10 19:56:42 +00003449
David Turnerb3ba40d2001-10-07 13:30:26 +00003450 if ( size == NULL )
Werner Lemberg3c5ad952008-12-21 17:51:12 +00003451 return FT_Err_Invalid_Argument;
Werner Lemberg1a0a9792002-01-03 22:06:13 +00003452
David Turnerb3ba40d2001-10-07 13:30:26 +00003453 face = size->face;
3454 if ( face == NULL || face->driver == NULL )
Werner Lemberg3c5ad952008-12-21 17:51:12 +00003455 return FT_Err_Invalid_Argument;
Werner Lemberg1a0a9792002-01-03 22:06:13 +00003456
Werner Lemberg80b8d772001-10-10 19:56:42 +00003457 /* we don't need anything more complex than that; all size objects */
3458 /* are already listed by the face */
David Turnerb3ba40d2001-10-07 13:30:26 +00003459 face->size = size;
Werner Lemberg1a0a9792002-01-03 22:06:13 +00003460
David Turnerb3ba40d2001-10-07 13:30:26 +00003461 return FT_Err_Ok;
3462 }
3463
3464
David Turnerd2b1f351999-12-16 23:11:37 +00003465 /*************************************************************************/
David Turnerf0df85b2000-06-22 00:17:42 +00003466 /*************************************************************************/
3467 /*************************************************************************/
3468 /**** ****/
3469 /**** ****/
3470 /**** R E N D E R E R S ****/
3471 /**** ****/
3472 /**** ****/
3473 /*************************************************************************/
3474 /*************************************************************************/
3475 /*************************************************************************/
3476
Werner Lembergdeb4e982000-06-29 03:14:25 +00003477 /* lookup a renderer by glyph format in the library's list */
Werner Lembergf814d0f2001-06-27 16:18:10 +00003478 FT_BASE_DEF( FT_Renderer )
3479 FT_Lookup_Renderer( FT_Library library,
3480 FT_Glyph_Format format,
3481 FT_ListNode* node )
David Turnerf0df85b2000-06-22 00:17:42 +00003482 {
Werner Lembergf8ba2002002-03-30 13:16:35 +00003483 FT_ListNode cur;
3484 FT_Renderer result = 0;
Werner Lemberga929ba92000-06-25 06:47:11 +00003485
Werner Lembergdeb4e982000-06-29 03:14:25 +00003486
3487 if ( !library )
3488 goto Exit;
3489
3490 cur = library->renderers.head;
3491
3492 if ( node )
David Turner74abee82000-06-27 23:31:53 +00003493 {
Werner Lembergdeb4e982000-06-29 03:14:25 +00003494 if ( *node )
David Turner74abee82000-06-27 23:31:53 +00003495 cur = (*node)->next;
David Turnerf0df85b2000-06-22 00:17:42 +00003496 *node = 0;
David Turner74abee82000-06-27 23:31:53 +00003497 }
Werner Lembergdeb4e982000-06-29 03:14:25 +00003498
Werner Lemberga929ba92000-06-25 06:47:11 +00003499 while ( cur )
David Turnerf0df85b2000-06-22 00:17:42 +00003500 {
Werner Lemberga929ba92000-06-25 06:47:11 +00003501 FT_Renderer renderer = FT_RENDERER( cur->data );
Werner Lembergdeb4e982000-06-29 03:14:25 +00003502
Werner Lemberga929ba92000-06-25 06:47:11 +00003503
3504 if ( renderer->glyph_format == format )
David Turnerf0df85b2000-06-22 00:17:42 +00003505 {
Werner Lemberga929ba92000-06-25 06:47:11 +00003506 if ( node )
David Turnerf0df85b2000-06-22 00:17:42 +00003507 *node = cur;
Werner Lembergdeb4e982000-06-29 03:14:25 +00003508
David Turnerf0df85b2000-06-22 00:17:42 +00003509 result = renderer;
3510 break;
3511 }
David Turner74abee82000-06-27 23:31:53 +00003512 cur = cur->next;
David Turnerf0df85b2000-06-22 00:17:42 +00003513 }
Werner Lemberga929ba92000-06-25 06:47:11 +00003514
Werner Lembergdeb4e982000-06-29 03:14:25 +00003515 Exit:
David Turnerf0df85b2000-06-22 00:17:42 +00003516 return result;
3517 }
3518
Werner Lemberga929ba92000-06-25 06:47:11 +00003519
Werner Lembergf814d0f2001-06-27 16:18:10 +00003520 static FT_Renderer
3521 ft_lookup_glyph_renderer( FT_GlyphSlot slot )
Werner Lembergdeb4e982000-06-29 03:14:25 +00003522 {
3523 FT_Face face = slot->face;
3524 FT_Library library = FT_FACE_LIBRARY( face );
3525 FT_Renderer result = library->cur_renderer;
3526
3527
Werner Lemberga929ba92000-06-25 06:47:11 +00003528 if ( !result || result->glyph_format != slot->format )
David Turner81bb4ad2000-06-28 04:19:49 +00003529 result = FT_Lookup_Renderer( library, slot->format, 0 );
Werner Lembergfbeb41d2000-07-02 00:27:53 +00003530
David Turnerf0df85b2000-06-22 00:17:42 +00003531 return result;
3532 }
3533
Werner Lembergdeb4e982000-06-29 03:14:25 +00003534
Werner Lembergf814d0f2001-06-27 16:18:10 +00003535 static void
3536 ft_set_current_renderer( FT_Library library )
David Turnerf0df85b2000-06-22 00:17:42 +00003537 {
3538 FT_Renderer renderer;
3539
Werner Lembergdeb4e982000-06-29 03:14:25 +00003540
David Turnerb08fe2d2002-08-27 20:20:29 +00003541 renderer = FT_Lookup_Renderer( library, FT_GLYPH_FORMAT_OUTLINE, 0 );
David Turnerf0df85b2000-06-22 00:17:42 +00003542 library->cur_renderer = renderer;
3543 }
3544
3545
Werner Lembergf814d0f2001-06-27 16:18:10 +00003546 static FT_Error
3547 ft_add_renderer( FT_Module module )
David Turnerf0df85b2000-06-22 00:17:42 +00003548 {
3549 FT_Library library = module->library;
3550 FT_Memory memory = library->memory;
3551 FT_Error error;
3552 FT_ListNode node;
Werner Lembergdeb4e982000-06-29 03:14:25 +00003553
3554
David Turnere459d742002-03-22 13:52:37 +00003555 if ( FT_NEW( node ) )
David Turnerf0df85b2000-06-22 00:17:42 +00003556 goto Exit;
Werner Lembergdeb4e982000-06-29 03:14:25 +00003557
David Turnerf0df85b2000-06-22 00:17:42 +00003558 {
Werner Lemberga929ba92000-06-25 06:47:11 +00003559 FT_Renderer render = FT_RENDERER( module );
David Turnerf0df85b2000-06-22 00:17:42 +00003560 FT_Renderer_Class* clazz = (FT_Renderer_Class*)module->clazz;
3561
Werner Lemberga929ba92000-06-25 06:47:11 +00003562
David Turnerf0df85b2000-06-22 00:17:42 +00003563 render->clazz = clazz;
3564 render->glyph_format = clazz->glyph_format;
Werner Lembergdeb4e982000-06-29 03:14:25 +00003565
David Turnerf0df85b2000-06-22 00:17:42 +00003566 /* allocate raster object if needed */
David Turnerb08fe2d2002-08-27 20:20:29 +00003567 if ( clazz->glyph_format == FT_GLYPH_FORMAT_OUTLINE &&
David Turnerf0df85b2000-06-22 00:17:42 +00003568 clazz->raster_class->raster_new )
3569 {
3570 error = clazz->raster_class->raster_new( memory, &render->raster );
Werner Lemberga929ba92000-06-25 06:47:11 +00003571 if ( error )
3572 goto Fail;
Werner Lembergdeb4e982000-06-29 03:14:25 +00003573
David Turnerf0df85b2000-06-22 00:17:42 +00003574 render->raster_render = clazz->raster_class->raster_render;
3575 render->render = clazz->render_glyph;
Werner Lembergdeb4e982000-06-29 03:14:25 +00003576 }
3577
David Turnerf0df85b2000-06-22 00:17:42 +00003578 /* add to list */
3579 node->data = module;
3580 FT_List_Add( &library->renderers, node );
3581
3582 ft_set_current_renderer( library );
3583 }
3584
3585 Fail:
Werner Lemberga929ba92000-06-25 06:47:11 +00003586 if ( error )
David Turnere459d742002-03-22 13:52:37 +00003587 FT_FREE( node );
David Turnerf0df85b2000-06-22 00:17:42 +00003588
3589 Exit:
3590 return error;
Werner Lembergdeb4e982000-06-29 03:14:25 +00003591 }
David Turnerf0df85b2000-06-22 00:17:42 +00003592
3593
Werner Lembergf814d0f2001-06-27 16:18:10 +00003594 static void
3595 ft_remove_renderer( FT_Module module )
David Turnerf0df85b2000-06-22 00:17:42 +00003596 {
3597 FT_Library library = module->library;
3598 FT_Memory memory = library->memory;
3599 FT_ListNode node;
3600
Werner Lemberga929ba92000-06-25 06:47:11 +00003601
David Turnerf0df85b2000-06-22 00:17:42 +00003602 node = FT_List_Find( &library->renderers, module );
Werner Lemberga929ba92000-06-25 06:47:11 +00003603 if ( node )
David Turnerf0df85b2000-06-22 00:17:42 +00003604 {
Werner Lemberga929ba92000-06-25 06:47:11 +00003605 FT_Renderer render = FT_RENDERER( module );
Werner Lembergdeb4e982000-06-29 03:14:25 +00003606
Werner Lemberga929ba92000-06-25 06:47:11 +00003607
David Turnerf0df85b2000-06-22 00:17:42 +00003608 /* release raster object, if any */
Werner Lemberga929ba92000-06-25 06:47:11 +00003609 if ( render->raster )
David Turnerf0df85b2000-06-22 00:17:42 +00003610 render->clazz->raster_class->raster_done( render->raster );
Werner Lembergdeb4e982000-06-29 03:14:25 +00003611
David Turnerf0df85b2000-06-22 00:17:42 +00003612 /* remove from list */
3613 FT_List_Remove( &library->renderers, node );
David Turnere459d742002-03-22 13:52:37 +00003614 FT_FREE( node );
Werner Lembergdeb4e982000-06-29 03:14:25 +00003615
David Turnerf0df85b2000-06-22 00:17:42 +00003616 ft_set_current_renderer( library );
3617 }
3618 }
3619
3620
Werner Lemberg90a03302000-11-07 17:21:11 +00003621 /* documentation is in ftrender.h */
3622
Werner Lembergf814d0f2001-06-27 16:18:10 +00003623 FT_EXPORT_DEF( FT_Renderer )
3624 FT_Get_Renderer( FT_Library library,
3625 FT_Glyph_Format format )
David Turnerf0df85b2000-06-22 00:17:42 +00003626 {
Werner Lembergdeb4e982000-06-29 03:14:25 +00003627 /* test for valid `library' delayed to FT_Lookup_Renderer() */
3628
Werner Lembergf8ba2002002-03-30 13:16:35 +00003629 return FT_Lookup_Renderer( library, format, 0 );
Werner Lembergdeb4e982000-06-29 03:14:25 +00003630 }
David Turnerf0df85b2000-06-22 00:17:42 +00003631
3632
Werner Lemberg90a03302000-11-07 17:21:11 +00003633 /* documentation is in ftrender.h */
3634
Werner Lembergf814d0f2001-06-27 16:18:10 +00003635 FT_EXPORT_DEF( FT_Error )
3636 FT_Set_Renderer( FT_Library library,
3637 FT_Renderer renderer,
3638 FT_UInt num_params,
3639 FT_Parameter* parameters )
David Turnerf0df85b2000-06-22 00:17:42 +00003640 {
3641 FT_ListNode node;
3642 FT_Error error = FT_Err_Ok;
Werner Lembergdeb4e982000-06-29 03:14:25 +00003643
3644
3645 if ( !library )
3646 return FT_Err_Invalid_Library_Handle;
3647
3648 if ( !renderer )
3649 return FT_Err_Invalid_Argument;
Werner Lemberga929ba92000-06-25 06:47:11 +00003650
David Turnerf0df85b2000-06-22 00:17:42 +00003651 node = FT_List_Find( &library->renderers, renderer );
Werner Lemberga929ba92000-06-25 06:47:11 +00003652 if ( !node )
David Turnerf0df85b2000-06-22 00:17:42 +00003653 {
3654 error = FT_Err_Invalid_Argument;
3655 goto Exit;
3656 }
David Turner74abee82000-06-27 23:31:53 +00003657
David Turnerf0df85b2000-06-22 00:17:42 +00003658 FT_List_Up( &library->renderers, node );
Werner Lembergdeb4e982000-06-29 03:14:25 +00003659
David Turnerb08fe2d2002-08-27 20:20:29 +00003660 if ( renderer->glyph_format == FT_GLYPH_FORMAT_OUTLINE )
David Turnerf0df85b2000-06-22 00:17:42 +00003661 library->cur_renderer = renderer;
Werner Lembergdeb4e982000-06-29 03:14:25 +00003662
Werner Lemberga929ba92000-06-25 06:47:11 +00003663 if ( num_params > 0 )
David Turnerf0df85b2000-06-22 00:17:42 +00003664 {
David Turnerb08fe2d2002-08-27 20:20:29 +00003665 FT_Renderer_SetModeFunc set_mode = renderer->clazz->set_mode;
Werner Lembergdeb4e982000-06-29 03:14:25 +00003666
Werner Lemberga929ba92000-06-25 06:47:11 +00003667
David Turnerf0df85b2000-06-22 00:17:42 +00003668 for ( ; num_params > 0; num_params-- )
3669 {
3670 error = set_mode( renderer, parameters->tag, parameters->data );
Werner Lemberga929ba92000-06-25 06:47:11 +00003671 if ( error )
David Turnerf0df85b2000-06-22 00:17:42 +00003672 break;
3673 }
3674 }
Werner Lembergdeb4e982000-06-29 03:14:25 +00003675
David Turnerf0df85b2000-06-22 00:17:42 +00003676 Exit:
3677 return error;
Werner Lembergdeb4e982000-06-29 03:14:25 +00003678 }
David Turnerf0df85b2000-06-22 00:17:42 +00003679
3680
David Turner7504e482002-06-07 07:24:55 +00003681 FT_BASE_DEF( FT_Error )
Werner Lemberg68e9f922002-09-27 11:09:23 +00003682 FT_Render_Glyph_Internal( FT_Library library,
3683 FT_GlyphSlot slot,
3684 FT_Render_Mode render_mode )
David Turnerf0df85b2000-06-22 00:17:42 +00003685 {
3686 FT_Error error = FT_Err_Ok;
3687 FT_Renderer renderer;
Werner Lemberga929ba92000-06-25 06:47:11 +00003688
Werner Lembergdeb4e982000-06-29 03:14:25 +00003689
3690 /* if it is already a bitmap, no need to do anything */
3691 switch ( slot->format )
David Turnerf0df85b2000-06-22 00:17:42 +00003692 {
David Turnerb08fe2d2002-08-27 20:20:29 +00003693 case FT_GLYPH_FORMAT_BITMAP: /* already a bitmap, don't do anything */
Werner Lembergdeb4e982000-06-29 03:14:25 +00003694 break;
3695
3696 default:
David Turner74abee82000-06-27 23:31:53 +00003697 {
3698 FT_ListNode node = 0;
3699 FT_Bool update = 0;
Werner Lembergdeb4e982000-06-29 03:14:25 +00003700
3701
Werner Lemberga929ba92000-06-25 06:47:11 +00003702 /* small shortcut for the very common case */
David Turnerb08fe2d2002-08-27 20:20:29 +00003703 if ( slot->format == FT_GLYPH_FORMAT_OUTLINE )
David Turner74abee82000-06-27 23:31:53 +00003704 {
Werner Lemberga929ba92000-06-25 06:47:11 +00003705 renderer = library->cur_renderer;
David Turner74abee82000-06-27 23:31:53 +00003706 node = library->renderers.head;
3707 }
Werner Lemberga929ba92000-06-25 06:47:11 +00003708 else
David Turner74abee82000-06-27 23:31:53 +00003709 renderer = FT_Lookup_Renderer( library, slot->format, &node );
3710
Werner Lemberga929ba92000-06-25 06:47:11 +00003711 error = FT_Err_Unimplemented_Feature;
Werner Lembergdeb4e982000-06-29 03:14:25 +00003712 while ( renderer )
David Turner74abee82000-06-27 23:31:53 +00003713 {
David Turnerc8ad30a2001-12-05 17:24:34 +00003714 error = renderer->render( renderer, slot, render_mode, NULL );
Werner Lemberg79860702001-06-08 21:17:29 +00003715 if ( !error ||
3716 FT_ERROR_BASE( error ) != FT_Err_Cannot_Render_Glyph )
Werner Lembergdeb4e982000-06-29 03:14:25 +00003717 break;
David Turner74abee82000-06-27 23:31:53 +00003718
Werner Lembergdeb4e982000-06-29 03:14:25 +00003719 /* FT_Err_Cannot_Render_Glyph is returned if the render mode */
David Turner74abee82000-06-27 23:31:53 +00003720 /* is unsupported by the current renderer for this glyph image */
Werner Lembergdeb4e982000-06-29 03:14:25 +00003721 /* format. */
3722
3723 /* now, look for another renderer that supports the same */
3724 /* format. */
David Turner74abee82000-06-27 23:31:53 +00003725 renderer = FT_Lookup_Renderer( library, slot->format, &node );
3726 update = 1;
3727 }
3728
3729 /* if we changed the current renderer for the glyph image format */
Werner Lembergdeb4e982000-06-29 03:14:25 +00003730 /* we need to select it as the next current one */
3731 if ( !error && update && renderer )
David Turner74abee82000-06-27 23:31:53 +00003732 FT_Set_Renderer( library, renderer, 0, 0 );
David Turnerf0df85b2000-06-22 00:17:42 +00003733 }
3734 }
Werner Lembergdeb4e982000-06-29 03:14:25 +00003735
David Turnerf0df85b2000-06-22 00:17:42 +00003736 return error;
3737 }
Werner Lemberga929ba92000-06-25 06:47:11 +00003738
David Turner74abee82000-06-27 23:31:53 +00003739
Werner Lemberg90a03302000-11-07 17:21:11 +00003740 /* documentation is in freetype.h */
3741
Werner Lembergf814d0f2001-06-27 16:18:10 +00003742 FT_EXPORT_DEF( FT_Error )
Werner Lemberg68e9f922002-09-27 11:09:23 +00003743 FT_Render_Glyph( FT_GlyphSlot slot,
3744 FT_Render_Mode render_mode )
David Turner74abee82000-06-27 23:31:53 +00003745 {
Werner Lembergf8ba2002002-03-30 13:16:35 +00003746 FT_Library library;
Werner Lembergdeb4e982000-06-29 03:14:25 +00003747
3748
3749 if ( !slot )
David Turner74abee82000-06-27 23:31:53 +00003750 return FT_Err_Invalid_Argument;
Werner Lembergdeb4e982000-06-29 03:14:25 +00003751
3752 library = FT_FACE_LIBRARY( slot->face );
3753
David Turner74abee82000-06-27 23:31:53 +00003754 return FT_Render_Glyph_Internal( library, slot, render_mode );
3755 }
3756
Werner Lembergdeb4e982000-06-29 03:14:25 +00003757
David Turnerf0df85b2000-06-22 00:17:42 +00003758 /*************************************************************************/
3759 /*************************************************************************/
3760 /*************************************************************************/
3761 /**** ****/
3762 /**** ****/
3763 /**** M O D U L E S ****/
3764 /**** ****/
3765 /**** ****/
3766 /*************************************************************************/
3767 /*************************************************************************/
3768 /*************************************************************************/
3769
Werner Lemberga929ba92000-06-25 06:47:11 +00003770
David Turnerf0df85b2000-06-22 00:17:42 +00003771 /*************************************************************************/
3772 /* */
3773 /* <Function> */
3774 /* Destroy_Module */
3775 /* */
3776 /* <Description> */
3777 /* Destroys a given module object. For drivers, this also destroys */
Werner Lemberga929ba92000-06-25 06:47:11 +00003778 /* all child faces. */
David Turnerf0df85b2000-06-22 00:17:42 +00003779 /* */
3780 /* <InOut> */
3781 /* module :: A handle to the target driver object. */
3782 /* */
3783 /* <Note> */
3784 /* The driver _must_ be LOCKED! */
3785 /* */
Werner Lembergf814d0f2001-06-27 16:18:10 +00003786 static void
3787 Destroy_Module( FT_Module module )
David Turnerf0df85b2000-06-22 00:17:42 +00003788 {
David Turner5ae831c2000-06-30 01:31:22 +00003789 FT_Memory memory = module->memory;
3790 FT_Module_Class* clazz = module->clazz;
3791 FT_Library library = module->library;
David Turnerf0df85b2000-06-22 00:17:42 +00003792
Werner Lemberga929ba92000-06-25 06:47:11 +00003793
David Turnerf0df85b2000-06-22 00:17:42 +00003794 /* finalize client-data - before anything else */
3795 if ( module->generic.finalizer )
3796 module->generic.finalizer( module );
3797
David Turner5ae831c2000-06-30 01:31:22 +00003798 if ( library && library->auto_hinter == module )
3799 library->auto_hinter = 0;
3800
David Turnerf0df85b2000-06-22 00:17:42 +00003801 /* if the module is a renderer */
Werner Lemberga929ba92000-06-25 06:47:11 +00003802 if ( FT_MODULE_IS_RENDERER( module ) )
3803 ft_remove_renderer( module );
David Turnerf0df85b2000-06-22 00:17:42 +00003804
3805 /* if the module is a font driver, add some steps */
Werner Lemberga929ba92000-06-25 06:47:11 +00003806 if ( FT_MODULE_IS_DRIVER( module ) )
3807 Destroy_Driver( FT_DRIVER( module ) );
David Turnerf0df85b2000-06-22 00:17:42 +00003808
3809 /* finalize the module object */
Werner Lemberga929ba92000-06-25 06:47:11 +00003810 if ( clazz->module_done )
3811 clazz->module_done( module );
David Turnerf0df85b2000-06-22 00:17:42 +00003812
3813 /* discard it */
David Turnere459d742002-03-22 13:52:37 +00003814 FT_FREE( module );
David Turnerf0df85b2000-06-22 00:17:42 +00003815 }
3816
David Turnerf0df85b2000-06-22 00:17:42 +00003817
Werner Lemberg748b1712005-12-25 09:15:09 +00003818 /* documentation is in ftmodapi.h */
Werner Lemberg90a03302000-11-07 17:21:11 +00003819
Werner Lembergf814d0f2001-06-27 16:18:10 +00003820 FT_EXPORT_DEF( FT_Error )
3821 FT_Add_Module( FT_Library library,
3822 const FT_Module_Class* clazz )
David Turnerf0df85b2000-06-22 00:17:42 +00003823 {
3824 FT_Error error;
3825 FT_Memory memory;
3826 FT_Module module;
3827 FT_UInt nn;
3828
David Turnerf0df85b2000-06-22 00:17:42 +00003829
Werner Lembergdeb4e982000-06-29 03:14:25 +00003830#define FREETYPE_VER_FIXED ( ( (FT_Long)FREETYPE_MAJOR << 16 ) | \
3831 FREETYPE_MINOR )
Werner Lemberga929ba92000-06-25 06:47:11 +00003832
Werner Lembergdeb4e982000-06-29 03:14:25 +00003833 if ( !library )
3834 return FT_Err_Invalid_Library_Handle;
3835
3836 if ( !clazz )
David Turnerf0df85b2000-06-22 00:17:42 +00003837 return FT_Err_Invalid_Argument;
3838
3839 /* check freetype version */
3840 if ( clazz->module_requires > FREETYPE_VER_FIXED )
3841 return FT_Err_Invalid_Version;
3842
3843 /* look for a module with the same name in the library's table */
3844 for ( nn = 0; nn < library->num_modules; nn++ )
3845 {
3846 module = library->modules[nn];
David Turnerd15bc0d2002-04-12 09:31:48 +00003847 if ( ft_strcmp( module->clazz->module_name, clazz->module_name ) == 0 )
David Turnerf0df85b2000-06-22 00:17:42 +00003848 {
3849 /* this installed module has the same name, compare their versions */
3850 if ( clazz->module_version <= module->clazz->module_version )
3851 return FT_Err_Lower_Module_Version;
3852
3853 /* remove the module from our list, then exit the loop to replace */
3854 /* it by our new version.. */
3855 FT_Remove_Module( library, module );
3856 break;
3857 }
3858 }
3859
3860 memory = library->memory;
3861 error = FT_Err_Ok;
3862
3863 if ( library->num_modules >= FT_MAX_MODULES )
3864 {
3865 error = FT_Err_Too_Many_Drivers;
3866 goto Exit;
3867 }
3868
3869 /* allocate module object */
Werner Lemberg68e9f922002-09-27 11:09:23 +00003870 if ( FT_ALLOC( module, clazz->module_size ) )
David Turnerf0df85b2000-06-22 00:17:42 +00003871 goto Exit;
3872
Werner Lembergdeb4e982000-06-29 03:14:25 +00003873 /* base initialization */
David Turnerf0df85b2000-06-22 00:17:42 +00003874 module->library = library;
3875 module->memory = memory;
3876 module->clazz = (FT_Module_Class*)clazz;
3877
Werner Lembergdeb4e982000-06-29 03:14:25 +00003878 /* check whether the module is a renderer - this must be performed */
3879 /* before the normal module initialization */
Werner Lemberga929ba92000-06-25 06:47:11 +00003880 if ( FT_MODULE_IS_RENDERER( module ) )
David Turnerf0df85b2000-06-22 00:17:42 +00003881 {
3882 /* add to the renderers list */
Werner Lemberga929ba92000-06-25 06:47:11 +00003883 error = ft_add_renderer( module );
3884 if ( error )
3885 goto Fail;
David Turnerf0df85b2000-06-22 00:17:42 +00003886 }
3887
Werner Lembergcc9fc492000-06-30 06:21:26 +00003888 /* is the module a auto-hinter? */
3889 if ( FT_MODULE_IS_HINTER( module ) )
David Turner5ae831c2000-06-30 01:31:22 +00003890 library->auto_hinter = module;
Werner Lembergfbeb41d2000-07-02 00:27:53 +00003891
David Turnerf0df85b2000-06-22 00:17:42 +00003892 /* if the module is a font driver */
Werner Lemberga929ba92000-06-25 06:47:11 +00003893 if ( FT_MODULE_IS_DRIVER( module ) )
David Turnerf0df85b2000-06-22 00:17:42 +00003894 {
3895 /* allocate glyph loader if needed */
Werner Lembergf8ba2002002-03-30 13:16:35 +00003896 FT_Driver driver = FT_DRIVER( module );
Werner Lemberga929ba92000-06-25 06:47:11 +00003897
Werner Lembergdeb4e982000-06-29 03:14:25 +00003898
David Turneref3c1262002-03-14 09:22:48 +00003899 driver->clazz = (FT_Driver_Class)module->clazz;
Werner Lemberga929ba92000-06-25 06:47:11 +00003900 if ( FT_DRIVER_USES_OUTLINES( driver ) )
David Turnerf0df85b2000-06-22 00:17:42 +00003901 {
3902 error = FT_GlyphLoader_New( memory, &driver->glyph_loader );
Werner Lemberga929ba92000-06-25 06:47:11 +00003903 if ( error )
3904 goto Fail;
David Turnerf0df85b2000-06-22 00:17:42 +00003905 }
3906 }
3907
Werner Lemberga929ba92000-06-25 06:47:11 +00003908 if ( clazz->module_init )
David Turnerf0df85b2000-06-22 00:17:42 +00003909 {
Werner Lemberga929ba92000-06-25 06:47:11 +00003910 error = clazz->module_init( module );
3911 if ( error )
3912 goto Fail;
David Turnerf0df85b2000-06-22 00:17:42 +00003913 }
3914
3915 /* add module to the library's table */
Werner Lemberga929ba92000-06-25 06:47:11 +00003916 library->modules[library->num_modules++] = module;
Werner Lembergdeb4e982000-06-29 03:14:25 +00003917
David Turnerf0df85b2000-06-22 00:17:42 +00003918 Exit:
3919 return error;
Werner Lembergdeb4e982000-06-29 03:14:25 +00003920
David Turnerf0df85b2000-06-22 00:17:42 +00003921 Fail:
Werner Lemberga929ba92000-06-25 06:47:11 +00003922 if ( FT_MODULE_IS_DRIVER( module ) )
David Turnerf0df85b2000-06-22 00:17:42 +00003923 {
Werner Lemberga929ba92000-06-25 06:47:11 +00003924 FT_Driver driver = FT_DRIVER( module );
Werner Lembergdeb4e982000-06-29 03:14:25 +00003925
Werner Lemberga929ba92000-06-25 06:47:11 +00003926
3927 if ( FT_DRIVER_USES_OUTLINES( driver ) )
David Turnerf0df85b2000-06-22 00:17:42 +00003928 FT_GlyphLoader_Done( driver->glyph_loader );
3929 }
Werner Lembergdeb4e982000-06-29 03:14:25 +00003930
Werner Lemberga929ba92000-06-25 06:47:11 +00003931 if ( FT_MODULE_IS_RENDERER( module ) )
David Turnerf0df85b2000-06-22 00:17:42 +00003932 {
Werner Lemberga929ba92000-06-25 06:47:11 +00003933 FT_Renderer renderer = FT_RENDERER( module );
3934
3935
3936 if ( renderer->raster )
David Turnerf0df85b2000-06-22 00:17:42 +00003937 renderer->clazz->raster_class->raster_done( renderer->raster );
3938 }
Werner Lemberga929ba92000-06-25 06:47:11 +00003939
David Turnere459d742002-03-22 13:52:37 +00003940 FT_FREE( module );
David Turnerf0df85b2000-06-22 00:17:42 +00003941 goto Exit;
3942 }
3943
David Turnerf0df85b2000-06-22 00:17:42 +00003944
Werner Lemberg748b1712005-12-25 09:15:09 +00003945 /* documentation is in ftmodapi.h */
Werner Lemberg90a03302000-11-07 17:21:11 +00003946
Werner Lembergf814d0f2001-06-27 16:18:10 +00003947 FT_EXPORT_DEF( FT_Module )
3948 FT_Get_Module( FT_Library library,
3949 const char* module_name )
David Turnerf0df85b2000-06-22 00:17:42 +00003950 {
Werner Lembergdeb4e982000-06-29 03:14:25 +00003951 FT_Module result = 0;
3952 FT_Module* cur;
3953 FT_Module* limit;
David Turnerf0df85b2000-06-22 00:17:42 +00003954
Werner Lemberga929ba92000-06-25 06:47:11 +00003955
Werner Lembergdeb4e982000-06-29 03:14:25 +00003956 if ( !library || !module_name )
3957 return result;
3958
3959 cur = library->modules;
3960 limit = cur + library->num_modules;
3961
David Turnerf0df85b2000-06-22 00:17:42 +00003962 for ( ; cur < limit; cur++ )
David Turnerd15bc0d2002-04-12 09:31:48 +00003963 if ( ft_strcmp( cur[0]->clazz->module_name, module_name ) == 0 )
David Turnerf0df85b2000-06-22 00:17:42 +00003964 {
3965 result = cur[0];
3966 break;
3967 }
3968
3969 return result;
3970 }
3971
Werner Lemberga929ba92000-06-25 06:47:11 +00003972
Werner Lemberg8ec9dfd2000-11-07 23:56:02 +00003973 /* documentation is in ftobjs.h */
3974
Werner Lembergf814d0f2001-06-27 16:18:10 +00003975 FT_BASE_DEF( const void* )
3976 FT_Get_Module_Interface( FT_Library library,
3977 const char* mod_name )
David Turnerf0df85b2000-06-22 00:17:42 +00003978 {
3979 FT_Module module;
Werner Lembergdeb4e982000-06-29 03:14:25 +00003980
3981
3982 /* test for valid `library' delayed to FT_Get_Module() */
Werner Lemberga929ba92000-06-25 06:47:11 +00003983
David Turnerf0df85b2000-06-22 00:17:42 +00003984 module = FT_Get_Module( library, mod_name );
Werner Lemberga929ba92000-06-25 06:47:11 +00003985
David Turnerf0df85b2000-06-22 00:17:42 +00003986 return module ? module->clazz->module_interface : 0;
Werner Lembergdeb4e982000-06-29 03:14:25 +00003987 }
David Turnerf0df85b2000-06-22 00:17:42 +00003988
3989
David Turnerb72d8a82003-09-29 20:33:37 +00003990 FT_BASE_DEF( FT_Pointer )
3991 ft_module_get_service( FT_Module module,
3992 const char* service_id )
3993 {
3994 FT_Pointer result = NULL;
3995
3996 if ( module )
3997 {
3998 FT_ASSERT( module->clazz && module->clazz->get_interface );
3999
4000 /* first, look for the service in the module
4001 */
4002 if ( module->clazz->get_interface )
4003 result = module->clazz->get_interface( module, service_id );
4004
4005 if ( result == NULL )
4006 {
4007 /* we didn't find it, look in all other modules then
4008 */
4009 FT_Library library = module->library;
4010 FT_Module* cur = library->modules;
4011 FT_Module* limit = cur + library->num_modules;
4012
4013 for ( ; cur < limit; cur++ )
4014 {
4015 if ( cur[0] != module )
4016 {
4017 FT_ASSERT( cur[0]->clazz );
4018
4019 if ( cur[0]->clazz->get_interface )
4020 {
4021 result = cur[0]->clazz->get_interface( cur[0], service_id );
4022 if ( result != NULL )
4023 break;
4024 }
4025 }
4026 }
4027 }
4028 }
4029
4030 return result;
4031 }
4032
4033
Werner Lemberg748b1712005-12-25 09:15:09 +00004034 /* documentation is in ftmodapi.h */
Werner Lemberg90a03302000-11-07 17:21:11 +00004035
Werner Lembergf814d0f2001-06-27 16:18:10 +00004036 FT_EXPORT_DEF( FT_Error )
4037 FT_Remove_Module( FT_Library library,
4038 FT_Module module )
David Turnerf0df85b2000-06-22 00:17:42 +00004039 {
4040 /* try to find the module from the table, then remove it from there */
Werner Lembergdeb4e982000-06-29 03:14:25 +00004041
4042 if ( !library )
4043 return FT_Err_Invalid_Library_Handle;
4044
4045 if ( module )
David Turnerf0df85b2000-06-22 00:17:42 +00004046 {
4047 FT_Module* cur = library->modules;
4048 FT_Module* limit = cur + library->num_modules;
4049
Werner Lemberga929ba92000-06-25 06:47:11 +00004050
David Turnerf0df85b2000-06-22 00:17:42 +00004051 for ( ; cur < limit; cur++ )
4052 {
Werner Lembergdeb4e982000-06-29 03:14:25 +00004053 if ( cur[0] == module )
David Turnerf0df85b2000-06-22 00:17:42 +00004054 {
4055 /* remove it from the table */
4056 library->num_modules--;
4057 limit--;
Werner Lemberga929ba92000-06-25 06:47:11 +00004058 while ( cur < limit )
David Turnerf0df85b2000-06-22 00:17:42 +00004059 {
4060 cur[0] = cur[1];
4061 cur++;
4062 }
4063 limit[0] = 0;
4064
4065 /* destroy the module */
Werner Lemberga929ba92000-06-25 06:47:11 +00004066 Destroy_Module( module );
David Turnerf0df85b2000-06-22 00:17:42 +00004067
4068 return FT_Err_Ok;
4069 }
4070 }
4071 }
Werner Lembergb48a6092000-07-09 19:15:30 +00004072 return FT_Err_Invalid_Driver_Handle;
David Turnerf0df85b2000-06-22 00:17:42 +00004073 }
4074
4075
David Turnerf0df85b2000-06-22 00:17:42 +00004076 /*************************************************************************/
4077 /*************************************************************************/
4078 /*************************************************************************/
4079 /**** ****/
4080 /**** ****/
4081 /**** L I B R A R Y ****/
4082 /**** ****/
4083 /**** ****/
4084 /*************************************************************************/
4085 /*************************************************************************/
4086 /*************************************************************************/
4087
Werner Lemberga929ba92000-06-25 06:47:11 +00004088
Werner Lemberg748b1712005-12-25 09:15:09 +00004089 /* documentation is in ftmodapi.h */
Werner Lemberg90a03302000-11-07 17:21:11 +00004090
Werner Lembergf814d0f2001-06-27 16:18:10 +00004091 FT_EXPORT_DEF( FT_Error )
4092 FT_New_Library( FT_Memory memory,
4093 FT_Library *alibrary )
David Turnerf0df85b2000-06-22 00:17:42 +00004094 {
4095 FT_Library library = 0;
4096 FT_Error error;
4097
4098
4099 if ( !memory )
4100 return FT_Err_Invalid_Argument;
4101
David Turnerf5749602002-04-18 10:07:26 +00004102#ifdef FT_DEBUG_LEVEL_ERROR
David Turner53b3fa12002-02-24 05:26:57 +00004103 /* init debugging support */
4104 ft_debug_init();
David Turnerf5749602002-04-18 10:07:26 +00004105#endif
David Turner53b3fa12002-02-24 05:26:57 +00004106
David Turnerf0df85b2000-06-22 00:17:42 +00004107 /* first of all, allocate the library object */
David Turnere459d742002-03-22 13:52:37 +00004108 if ( FT_NEW( library ) )
David Turnerf0df85b2000-06-22 00:17:42 +00004109 return error;
4110
4111 library->memory = memory;
4112
4113 /* allocate the render pool */
4114 library->raster_pool_size = FT_RENDER_POOL_SIZE;
Werner Lemberg39c91ad2007-07-28 05:40:40 +00004115#if FT_RENDER_POOL_SIZE > 0
4116 if ( FT_ALLOC( library->raster_pool, FT_RENDER_POOL_SIZE ) )
4117 goto Fail;
4118#endif
David Turnerf0df85b2000-06-22 00:17:42 +00004119
4120 /* That's ok now */
4121 *alibrary = library;
4122
4123 return FT_Err_Ok;
4124
4125 Fail:
David Turnere459d742002-03-22 13:52:37 +00004126 FT_FREE( library );
David Turnerf0df85b2000-06-22 00:17:42 +00004127 return error;
4128 }
4129
4130
David Turner83b4a4b2002-03-06 12:42:34 +00004131 /* documentation is in freetype.h */
David Turner25a6e3a2002-06-10 23:03:35 +00004132
David Turner83b4a4b2002-03-06 12:42:34 +00004133 FT_EXPORT_DEF( void )
4134 FT_Library_Version( FT_Library library,
4135 FT_Int *amajor,
4136 FT_Int *aminor,
4137 FT_Int *apatch )
4138 {
4139 FT_Int major = 0;
4140 FT_Int minor = 0;
4141 FT_Int patch = 0;
4142
David Turner25a6e3a2002-06-10 23:03:35 +00004143
David Turner83b4a4b2002-03-06 12:42:34 +00004144 if ( library )
4145 {
4146 major = library->version_major;
4147 minor = library->version_minor;
4148 patch = library->version_patch;
4149 }
David Turner25a6e3a2002-06-10 23:03:35 +00004150
David Turnerd48575e2002-09-18 23:18:36 +00004151 if ( amajor )
David Turner83b4a4b2002-03-06 12:42:34 +00004152 *amajor = major;
David Turner25a6e3a2002-06-10 23:03:35 +00004153
David Turnerd48575e2002-09-18 23:18:36 +00004154 if ( aminor )
David Turner83b4a4b2002-03-06 12:42:34 +00004155 *aminor = minor;
David Turner25a6e3a2002-06-10 23:03:35 +00004156
David Turnerd48575e2002-09-18 23:18:36 +00004157 if ( apatch )
David Turner83b4a4b2002-03-06 12:42:34 +00004158 *apatch = patch;
David Turner25a6e3a2002-06-10 23:03:35 +00004159 }
David Turner83b4a4b2002-03-06 12:42:34 +00004160
4161
Werner Lemberg748b1712005-12-25 09:15:09 +00004162 /* documentation is in ftmodapi.h */
Werner Lemberg90a03302000-11-07 17:21:11 +00004163
Werner Lembergf814d0f2001-06-27 16:18:10 +00004164 FT_EXPORT_DEF( FT_Error )
4165 FT_Done_Library( FT_Library library )
David Turnerf0df85b2000-06-22 00:17:42 +00004166 {
4167 FT_Memory memory;
David Turnerf0df85b2000-06-22 00:17:42 +00004168
4169
4170 if ( !library )
4171 return FT_Err_Invalid_Library_Handle;
4172
4173 memory = library->memory;
4174
4175 /* Discard client-data */
4176 if ( library->generic.finalizer )
4177 library->generic.finalizer( library );
4178
Werner Lemberg4ea0a7f2007-01-05 09:03:31 +00004179 /* Close all faces in the library. If we don't do
David Turnera8cf42b2007-01-04 16:46:46 +00004180 * this, we can have some subtle memory leaks.
Werner Lemberg4ea0a7f2007-01-05 09:03:31 +00004181 * Example:
David Turnera8cf42b2007-01-04 16:46:46 +00004182 *
4183 * - the cff font driver uses the pshinter module in cff_size_done
4184 * - if the pshinter module is destroyed before the cff font driver,
Werner Lemberg4ea0a7f2007-01-05 09:03:31 +00004185 * opened FT_Face objects managed by the driver are not properly
David Turnera8cf42b2007-01-04 16:46:46 +00004186 * destroyed, resulting in a memory leak
4187 */
4188 {
4189 FT_UInt n;
4190
Werner Lemberg4ea0a7f2007-01-05 09:03:31 +00004191
David Turnera8cf42b2007-01-04 16:46:46 +00004192 for ( n = 0; n < library->num_modules; n++ )
4193 {
4194 FT_Module module = library->modules[n];
4195 FT_List faces;
4196
Werner Lemberg4ea0a7f2007-01-05 09:03:31 +00004197
4198 if ( ( module->clazz->module_flags & FT_MODULE_FONT_DRIVER ) == 0 )
David Turnera8cf42b2007-01-04 16:46:46 +00004199 continue;
4200
4201 faces = &FT_DRIVER(module)->faces_list;
Werner Lemberg4ea0a7f2007-01-05 09:03:31 +00004202 while ( faces->head )
Werner Lemberg9b1da082009-01-09 06:21:04 +00004203 {
Werner Lemberg4ea0a7f2007-01-05 09:03:31 +00004204 FT_Done_Face( FT_FACE( faces->head->data ) );
Werner Lemberg9b1da082009-01-09 06:21:04 +00004205 if ( faces->head )
Suzuki, Toshiya (鈴木俊哉)2dc10792009-01-09 05:07:15 +00004206 FT_ERROR(( "FT_Done_Library: failed to free some faces\n" ));
Werner Lemberg9b1da082009-01-09 06:21:04 +00004207 }
David Turnera8cf42b2007-01-04 16:46:46 +00004208 }
4209 }
4210
David Turnera8cf42b2007-01-04 16:46:46 +00004211 /* Close all other modules in the library */
Werner Lembergf41e71a2001-12-20 21:22:02 +00004212#if 1
Wu, Chia-I (吳佳一)a87b08a2006-02-28 09:53:23 +00004213 /* XXX Modules are removed in the reversed order so that */
David Turner2b21a932006-08-16 09:24:32 +00004214 /* type42 module is removed before truetype module. This */
Wu, Chia-I (吳佳一)a87b08a2006-02-28 09:53:23 +00004215 /* avoids double free in some occasions. It is a hack. */
David Turnerc8087482001-12-20 13:14:18 +00004216 while ( library->num_modules > 0 )
Wu, Chia-I (吳佳一)a87b08a2006-02-28 09:53:23 +00004217 FT_Remove_Module( library,
4218 library->modules[library->num_modules - 1] );
Werner Lembergf41e71a2001-12-20 21:22:02 +00004219#else
David Turnerf0df85b2000-06-22 00:17:42 +00004220 {
Werner Lembergf41e71a2001-12-20 21:22:02 +00004221 FT_UInt n;
David Turnerf0df85b2000-06-22 00:17:42 +00004222
Werner Lemberga929ba92000-06-25 06:47:11 +00004223
Werner Lembergf41e71a2001-12-20 21:22:02 +00004224 for ( n = 0; n < library->num_modules; n++ )
David Turnerf0df85b2000-06-22 00:17:42 +00004225 {
Werner Lembergf41e71a2001-12-20 21:22:02 +00004226 FT_Module module = library->modules[n];
4227
4228
4229 if ( module )
4230 {
4231 Destroy_Module( module );
4232 library->modules[n] = 0;
4233 }
David Turnerf0df85b2000-06-22 00:17:42 +00004234 }
4235 }
David Turnerc8087482001-12-20 13:14:18 +00004236#endif
David Turnerf0df85b2000-06-22 00:17:42 +00004237
4238 /* Destroy raster objects */
David Turnere459d742002-03-22 13:52:37 +00004239 FT_FREE( library->raster_pool );
David Turnerf0df85b2000-06-22 00:17:42 +00004240 library->raster_pool_size = 0;
4241
David Turnere459d742002-03-22 13:52:37 +00004242 FT_FREE( library );
David Turnerf0df85b2000-06-22 00:17:42 +00004243 return FT_Err_Ok;
4244 }
4245
4246
Werner Lemberg748b1712005-12-25 09:15:09 +00004247 /* documentation is in ftmodapi.h */
Werner Lemberg90a03302000-11-07 17:21:11 +00004248
Werner Lembergf814d0f2001-06-27 16:18:10 +00004249 FT_EXPORT_DEF( void )
4250 FT_Set_Debug_Hook( FT_Library library,
4251 FT_UInt hook_index,
4252 FT_DebugHook_Func debug_hook )
David Turnerf0df85b2000-06-22 00:17:42 +00004253 {
4254 if ( library && debug_hook &&
4255 hook_index <
4256 ( sizeof ( library->debug_hooks ) / sizeof ( void* ) ) )
4257 library->debug_hooks[hook_index] = debug_hook;
4258 }
4259
Werner Lemberg8e6f8c42006-02-17 08:07:09 +00004260
David Turner0b5dc4d2006-02-21 22:36:23 +00004261 /* documentation is in ftmodapi.h */
4262
4263 FT_EXPORT_DEF( FT_TrueTypeEngineType )
4264 FT_Get_TrueType_Engine_Type( FT_Library library )
4265 {
4266 FT_TrueTypeEngineType result = FT_TRUETYPE_ENGINE_TYPE_NONE;
4267
Werner Lemberg5edafed2006-02-22 08:23:35 +00004268
David Turner0b5dc4d2006-02-21 22:36:23 +00004269 if ( library )
4270 {
4271 FT_Module module = FT_Get_Module( library, "truetype" );
4272
Werner Lemberg5edafed2006-02-22 08:23:35 +00004273
David Turner0b5dc4d2006-02-21 22:36:23 +00004274 if ( module )
4275 {
4276 FT_Service_TrueTypeEngine service;
4277
Werner Lemberg5edafed2006-02-22 08:23:35 +00004278
David Turner6c71c6b2006-02-25 12:49:40 +00004279 service = (FT_Service_TrueTypeEngine)
4280 ft_module_get_service( module,
4281 FT_SERVICE_ID_TRUETYPE_ENGINE );
David Turner0b5dc4d2006-02-21 22:36:23 +00004282 if ( service )
4283 result = service->engine_type;
4284 }
4285 }
Werner Lemberg5edafed2006-02-22 08:23:35 +00004286
David Turner0b5dc4d2006-02-21 22:36:23 +00004287 return result;
4288 }
4289
Werner Lemberg5edafed2006-02-22 08:23:35 +00004290
David Turnercda2d952006-02-16 22:45:31 +00004291#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
Werner Lemberg8e6f8c42006-02-17 08:07:09 +00004292
David Turnercda2d952006-02-16 22:45:31 +00004293 FT_BASE_DEF( FT_Error )
4294 ft_stub_set_char_sizes( FT_Size size,
4295 FT_F26Dot6 width,
4296 FT_F26Dot6 height,
4297 FT_UInt horz_res,
4298 FT_UInt vert_res )
4299 {
4300 FT_Size_RequestRec req;
4301 FT_Driver driver = size->face->driver;
4302
Werner Lemberg8e6f8c42006-02-17 08:07:09 +00004303
David Turnercda2d952006-02-16 22:45:31 +00004304 if ( driver->clazz->request_size )
4305 {
4306 req.type = FT_SIZE_REQUEST_TYPE_NOMINAL;
4307 req.width = width;
4308 req.height = height;
4309
4310 if ( horz_res == 0 )
4311 horz_res = vert_res;
4312
4313 if ( vert_res == 0 )
4314 vert_res = horz_res;
4315
4316 if ( horz_res == 0 )
4317 horz_res = vert_res = 72;
4318
4319 req.horiResolution = horz_res;
4320 req.vertResolution = vert_res;
4321
4322 return driver->clazz->request_size( size, &req );
4323 }
Werner Lemberg8e6f8c42006-02-17 08:07:09 +00004324
David Turnercda2d952006-02-16 22:45:31 +00004325 return 0;
4326 }
4327
4328
4329 FT_BASE_DEF( FT_Error )
Werner Lemberg8e6f8c42006-02-17 08:07:09 +00004330 ft_stub_set_pixel_sizes( FT_Size size,
4331 FT_UInt width,
4332 FT_UInt height )
David Turnercda2d952006-02-16 22:45:31 +00004333 {
4334 FT_Size_RequestRec req;
4335 FT_Driver driver = size->face->driver;
4336
Werner Lemberg8e6f8c42006-02-17 08:07:09 +00004337
David Turnercda2d952006-02-16 22:45:31 +00004338 if ( driver->clazz->request_size )
4339 {
4340 req.type = FT_SIZE_REQUEST_TYPE_NOMINAL;
Werner Lemberg8e6f8c42006-02-17 08:07:09 +00004341 req.width = width << 6;
David Turnercda2d952006-02-16 22:45:31 +00004342 req.height = height << 6;
4343 req.horiResolution = 0;
4344 req.vertResolution = 0;
4345
4346 return driver->clazz->request_size( size, &req );
4347 }
Werner Lemberg8e6f8c42006-02-17 08:07:09 +00004348
David Turnercda2d952006-02-16 22:45:31 +00004349 return 0;
4350 }
Werner Lemberg8e6f8c42006-02-17 08:07:09 +00004351
David Turnercda2d952006-02-16 22:45:31 +00004352#endif /* FT_CONFIG_OPTION_OLD_INTERNALS */
David Turnerf0df85b2000-06-22 00:17:42 +00004353
David Turner2b21a932006-08-16 09:24:32 +00004354
David Turner2ce92032006-03-23 20:58:20 +00004355 FT_EXPORT_DEF( FT_Error )
4356 FT_Get_SubGlyph_Info( FT_GlyphSlot glyph,
4357 FT_UInt sub_index,
Werner Lemberg4db32ec2006-03-24 11:54:53 +00004358 FT_Int *p_index,
4359 FT_UInt *p_flags,
4360 FT_Int *p_arg1,
4361 FT_Int *p_arg2,
4362 FT_Matrix *p_transform )
David Turner2ce92032006-03-23 20:58:20 +00004363 {
Werner Lemberg4db32ec2006-03-24 11:54:53 +00004364 FT_Error error = FT_Err_Invalid_Argument;
Werner Lemberg4db32ec2006-03-24 11:54:53 +00004365
David Turner2b21a932006-08-16 09:24:32 +00004366
4367 if ( glyph != NULL &&
Werner Lemberg4db32ec2006-03-24 11:54:53 +00004368 glyph->format == FT_GLYPH_FORMAT_COMPOSITE &&
4369 sub_index < glyph->num_subglyphs )
4370 {
David Turner2ce92032006-03-23 20:58:20 +00004371 FT_SubGlyph subg = glyph->subglyphs + sub_index;
David Turner2b21a932006-08-16 09:24:32 +00004372
Werner Lemberg4db32ec2006-03-24 11:54:53 +00004373
4374 *p_index = subg->index;
4375 *p_flags = subg->flags;
4376 *p_arg1 = subg->arg1;
4377 *p_arg2 = subg->arg2;
4378 *p_transform = subg->transform;
4379 }
4380
4381 return error;
David Turner2ce92032006-03-23 20:58:20 +00004382 }
4383
Werner Lemberg4db32ec2006-03-24 11:54:53 +00004384
David Turnerd2b1f351999-12-16 23:11:37 +00004385/* END */