blob: 68f4b077df7ac94674fdf6e10fc6e11c506086ee [file] [log] [blame]
David Turnerd2b1f351999-12-16 23:11:37 +00001/***************************************************************************/
2/* */
3/* ttgload.c */
4/* */
5/* TrueType Glyph Loader (body). */
6/* */
Werner Lemberg780d7e02009-06-17 06:45:20 +02007/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 by */
David Turnerd2b1f351999-12-16 23:11:37 +00008/* David Turner, Robert Wilhelm, and Werner Lemberg. */
9/* */
Werner Lemberg78575dc2000-06-12 19:36:41 +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
David Turner19ed8af2000-12-08 02:42:29 +000019#include <ft2build.h>
20#include FT_INTERNAL_DEBUG_H
21#include FT_INTERNAL_CALC_H
22#include FT_INTERNAL_STREAM_H
23#include FT_INTERNAL_SFNT_H
24#include FT_TRUETYPE_TAGS_H
25#include FT_OUTLINE_H
David Turnerd2b1f351999-12-16 23:11:37 +000026
David Turner8d3a4012001-03-20 11:14:24 +000027#include "ttgload.h"
Werner Lembergf13516c2005-03-03 17:09:08 +000028#include "ttpload.h"
Werner Lemberg78575dc2000-06-12 19:36:41 +000029
Werner Lemberg44bb3032004-04-25 20:15:11 +000030#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
31#include "ttgxvar.h"
32#endif
33
Werner Lemberg1f7f0e82001-06-06 17:30:41 +000034#include "tterrors.h"
35
David Turnera90663f2000-07-08 00:41:13 +000036
Werner Lemberg78575dc2000-06-12 19:36:41 +000037 /*************************************************************************/
38 /* */
39 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
40 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
41 /* messages during execution. */
42 /* */
David Turnerd2b1f351999-12-16 23:11:37 +000043#undef FT_COMPONENT
44#define FT_COMPONENT trace_ttgload
45
46
47 /*************************************************************************/
48 /* */
49 /* Composite font flags. */
50 /* */
Werner Lembergeed446d2002-08-16 12:46:52 +000051#define ARGS_ARE_WORDS 0x0001
52#define ARGS_ARE_XY_VALUES 0x0002
53#define ROUND_XY_TO_GRID 0x0004
54#define WE_HAVE_A_SCALE 0x0008
55/* reserved 0x0010 */
56#define MORE_COMPONENTS 0x0020
57#define WE_HAVE_AN_XY_SCALE 0x0040
58#define WE_HAVE_A_2X2 0x0080
59#define WE_HAVE_INSTR 0x0100
60#define USE_MY_METRICS 0x0200
61#define OVERLAP_COMPOUND 0x0400
62#define SCALED_COMPONENT_OFFSET 0x0800
63#define UNSCALED_COMPONENT_OFFSET 0x1000
David Turnerd2b1f351999-12-16 23:11:37 +000064
David Turnerf9b8dec2000-06-16 19:34:52 +000065
David Turnerd2b1f351999-12-16 23:11:37 +000066 /*************************************************************************/
Werner Lemberg78575dc2000-06-12 19:36:41 +000067 /* */
Werner Lembergdcd2e142000-06-25 07:43:15 +000068 /* Returns the horizontal metrics in font units for a given glyph. If */
69 /* `check' is true, take care of monospaced fonts by returning the */
70 /* advance width maximum. */
David Turnerd2b1f351999-12-16 23:11:37 +000071 /* */
Werner Lembergac0d52d2009-11-02 08:35:24 +010072 FT_LOCAL_DEF( void )
David Turner28534d62008-09-01 21:35:21 +000073 TT_Get_HMetrics( TT_Face face,
74 FT_UInt idx,
75 FT_Bool check,
76 FT_Short* lsb,
77 FT_UShort* aw )
David Turnerd2b1f351999-12-16 23:11:37 +000078 {
Wu, Chia-I (吳佳一)f5aa47b2006-02-14 06:40:10 +000079 ( (SFNT_Service)face->sfnt )->get_metrics( face, 0, idx, lsb, aw );
David Turnerd2b1f351999-12-16 23:11:37 +000080
81 if ( check && face->postscript.isFixedPitch )
82 *aw = face->horizontal.advance_Width_Max;
Werner Lembergc4b22142009-11-15 10:10:00 +010083
84 FT_TRACE5(( " advance width (font units): %d\n", *aw ));
85 FT_TRACE5(( " left side bearing (font units): %d\n", *lsb ));
David Turnerd2b1f351999-12-16 23:11:37 +000086 }
87
88
89 /*************************************************************************/
Werner Lemberg78575dc2000-06-12 19:36:41 +000090 /* */
Werner Lemberg8bb07e62004-03-27 08:43:17 +000091 /* Returns the vertical metrics in font units for a given glyph. */
92 /* Greg Hitchcock from Microsoft told us that if there were no `vmtx' */
93 /* table, typoAscender/Descender from the `OS/2' table would be used */
94 /* instead, and if there were no `OS/2' table, use ascender/descender */
95 /* from the `hhea' table. But that is not what Microsoft's rasterizer */
96 /* apparently does: It uses the ppem value as the advance height, and */
97 /* sets the top side bearing to be zero. */
98 /* */
99 /* The monospace `check' is probably not meaningful here, but we leave */
100 /* it in for a consistent interface. */
101 /* */
Werner Lembergac0d52d2009-11-02 08:35:24 +0100102 FT_LOCAL_DEF( void )
David Turner28534d62008-09-01 21:35:21 +0000103 TT_Get_VMetrics( TT_Face face,
104 FT_UInt idx,
105 FT_Bool check,
106 FT_Short* tsb,
107 FT_UShort* ah )
Werner Lemberg8bb07e62004-03-27 08:43:17 +0000108 {
109 FT_UNUSED( check );
110
111 if ( face->vertical_info )
Wu, Chia-I (吳佳一)f5aa47b2006-02-14 06:40:10 +0000112 ( (SFNT_Service)face->sfnt )->get_metrics( face, 1, idx, tsb, ah );
Werner Lemberg8bb07e62004-03-27 08:43:17 +0000113
Werner Lemberg4b2e83d2007-02-01 07:58:02 +0000114#if 1 /* Empirically determined, at variance with what MS said */
Werner Lemberg8bb07e62004-03-27 08:43:17 +0000115
116 else
117 {
118 *tsb = 0;
119 *ah = face->root.units_per_EM;
120 }
121
122#else /* This is what MS said to do. It isn't what they do, however. */
123
124 else if ( face->os2.version != 0xFFFFU )
125 {
126 *tsb = face->os2.sTypoAscender;
127 *ah = face->os2.sTypoAscender - face->os2.sTypoDescender;
128 }
David Turner2f0fdb92004-06-21 21:16:56 +0000129 else
Werner Lemberg8bb07e62004-03-27 08:43:17 +0000130 {
131 *tsb = face->horizontal.Ascender;
132 *ah = face->horizontal.Ascender - face->horizontal.Descender;
133 }
134
135#endif
136
Werner Lembergc4b22142009-11-15 10:10:00 +0100137 FT_TRACE5(( " advance height (font units): %d\n", *ah ));
138 FT_TRACE5(( " top side bearing (font units): %d\n", *tsb ));
Werner Lemberg8bb07e62004-03-27 08:43:17 +0000139 }
140
141
Werner Lemberg422210b2009-11-03 08:11:02 +0100142 static void
143 tt_get_metrics( TT_Loader loader,
144 FT_UInt glyph_index )
145 {
146 TT_Face face = (TT_Face)loader->face;
147
148 FT_Short left_bearing = 0, top_bearing = 0;
149 FT_UShort advance_width = 0, advance_height = 0;
150
151
152 TT_Get_HMetrics( face, glyph_index,
153 (FT_Bool)!( loader->load_flags &
154 FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ),
155 &left_bearing,
156 &advance_width );
157 TT_Get_VMetrics( face, glyph_index,
158 (FT_Bool)!( loader->load_flags &
159 FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ),
160 &top_bearing,
161 &advance_height );
162
163#ifdef FT_CONFIG_OPTION_INCREMENTAL
164
165 /* If this is an incrementally loaded font see if there are */
166 /* overriding metrics for this glyph. */
167 if ( face->root.internal->incremental_interface &&
168 face->root.internal->incremental_interface->funcs->get_glyph_metrics )
169 {
170 FT_Incremental_MetricsRec metrics;
171 FT_Error error;
172
173
174 metrics.bearing_x = left_bearing;
175 metrics.bearing_y = 0;
176 metrics.advance = advance_width;
177
178 error = face->root.internal->incremental_interface->funcs->get_glyph_metrics(
179 face->root.internal->incremental_interface->object,
180 glyph_index, FALSE, &metrics );
181 if ( error )
182 goto Exit;
183
184 left_bearing = (FT_Short)metrics.bearing_x;
185 advance_width = (FT_UShort)metrics.advance;
186
187#if 0
188
189 /* GWW: Do I do the same for vertical metrics? */
190 metrics.bearing_x = 0;
191 metrics.bearing_y = top_bearing;
192 metrics.advance = advance_height;
193
194 error = face->root.internal->incremental_interface->funcs->get_glyph_metrics(
195 face->root.internal->incremental_interface->object,
196 glyph_index, TRUE, &metrics );
197 if ( error )
198 goto Exit;
199
200 top_bearing = (FT_Short)metrics.bearing_y;
201 advance_height = (FT_UShort)metrics.advance;
202
203#endif /* 0 */
204
205 }
206
Werner Lemberg9045f5b2009-12-03 05:57:30 +0100207 Exit:
208
Werner Lemberg422210b2009-11-03 08:11:02 +0100209#endif /* FT_CONFIG_OPTION_INCREMENTAL */
210
Werner Lemberg422210b2009-11-03 08:11:02 +0100211 loader->left_bearing = left_bearing;
212 loader->advance = advance_width;
213 loader->top_bearing = top_bearing;
214 loader->vadvance = advance_height;
215
216 if ( !loader->linear_def )
217 {
218 loader->linear_def = 1;
219 loader->linear = advance_width;
220 }
221 }
222
223
David Turnerd2b1f351999-12-16 23:11:37 +0000224 /*************************************************************************/
Werner Lemberg78575dc2000-06-12 19:36:41 +0000225 /* */
Werner Lemberg91db04c2002-04-01 14:25:28 +0000226 /* Translates an array of coordinates. */
David Turnerd2b1f351999-12-16 23:11:37 +0000227 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +0000228 static void
229 translate_array( FT_UInt n,
230 FT_Vector* coords,
231 FT_Pos delta_x,
232 FT_Pos delta_y )
David Turnerd2b1f351999-12-16 23:11:37 +0000233 {
David Turnerf9b8dec2000-06-16 19:34:52 +0000234 FT_UInt k;
Werner Lemberg78575dc2000-06-12 19:36:41 +0000235
Werner Lemberg5811c7c2000-07-02 13:53:16 +0000236
David Turnerd2b1f351999-12-16 23:11:37 +0000237 if ( delta_x )
238 for ( k = 0; k < n; k++ )
239 coords[k].x += delta_x;
240
241 if ( delta_y )
242 for ( k = 0; k < n; k++ )
243 coords[k].y += delta_y;
244 }
245
246
David Turner8f43c712000-02-02 12:16:19 +0000247#undef IS_HINTED
Werner Lemberg78575dc2000-06-12 19:36:41 +0000248#define IS_HINTED( flags ) ( ( flags & FT_LOAD_NO_HINTING ) == 0 )
249
David Turner8f43c712000-02-02 12:16:19 +0000250
David Turnerd2b1f351999-12-16 23:11:37 +0000251 /*************************************************************************/
252 /* */
Werner Lemberg91db04c2002-04-01 14:25:28 +0000253 /* The following functions are used by default with TrueType fonts. */
254 /* However, they can be replaced by alternatives if we need to support */
255 /* TrueType-compressed formats (like MicroType) in the future. */
David Turnerd2b1f351999-12-16 23:11:37 +0000256 /* */
Werner Lemberga929ba92000-06-25 06:47:11 +0000257 /*************************************************************************/
David Turner90f68b72000-06-23 12:26:14 +0000258
Werner Lemberg4a2305c2001-06-28 07:17:51 +0000259 FT_CALLBACK_DEF( FT_Error )
Werner Lemberg91db04c2002-04-01 14:25:28 +0000260 TT_Access_Glyph_Frame( TT_Loader loader,
261 FT_UInt glyph_index,
262 FT_ULong offset,
263 FT_UInt byte_count )
David Turner90f68b72000-06-23 12:26:14 +0000264 {
Werner Lemberge72c9fe2000-07-31 18:59:02 +0000265 FT_Error error;
266 FT_Stream stream = loader->stream;
Werner Lembergbd5ae402000-07-05 04:32:02 +0000267
Werner Lemberg353dfea2000-08-29 18:58:41 +0000268 /* for non-debug mode */
269 FT_UNUSED( glyph_index );
270
Werner Lemberga929ba92000-06-25 06:47:11 +0000271
David Turner90f68b72000-06-23 12:26:14 +0000272 FT_TRACE5(( "Glyph %ld\n", glyph_index ));
Werner Lemberge72c9fe2000-07-31 18:59:02 +0000273
274 /* the following line sets the `error' variable through macros! */
David Turner7d3a2642002-03-20 10:49:31 +0000275 if ( FT_STREAM_SEEK( offset ) || FT_FRAME_ENTER( byte_count ) )
Werner Lemberge72c9fe2000-07-31 18:59:02 +0000276 return error;
277
David Turner281679d2006-05-17 13:34:21 +0000278 loader->cursor = stream->cursor;
279 loader->limit = stream->limit;
280
Werner Lemberge72c9fe2000-07-31 18:59:02 +0000281 return TT_Err_Ok;
Werner Lembergbd5ae402000-07-05 04:32:02 +0000282 }
David Turner90f68b72000-06-23 12:26:14 +0000283
284
Werner Lemberg4a2305c2001-06-28 07:17:51 +0000285 FT_CALLBACK_DEF( void )
Werner Lemberg91db04c2002-04-01 14:25:28 +0000286 TT_Forget_Glyph_Frame( TT_Loader loader )
David Turner90f68b72000-06-23 12:26:14 +0000287 {
288 FT_Stream stream = loader->stream;
Werner Lemberga929ba92000-06-25 06:47:11 +0000289
290
David Turner7d3a2642002-03-20 10:49:31 +0000291 FT_FRAME_EXIT();
Werner Lembergbd5ae402000-07-05 04:32:02 +0000292 }
David Turner90f68b72000-06-23 12:26:14 +0000293
294
Werner Lemberg4a2305c2001-06-28 07:17:51 +0000295 FT_CALLBACK_DEF( FT_Error )
Werner Lemberg91db04c2002-04-01 14:25:28 +0000296 TT_Load_Glyph_Header( TT_Loader loader )
David Turner90f68b72000-06-23 12:26:14 +0000297 {
Werner Lemberg545c4e52006-05-17 22:55:04 +0000298 FT_Byte* p = loader->cursor;
299 FT_Byte* limit = loader->limit;
Werner Lembergbd5ae402000-07-05 04:32:02 +0000300
Werner Lembergac812952002-01-06 16:42:44 +0000301
David Turner281679d2006-05-17 13:34:21 +0000302 if ( p + 10 > limit )
David Turnerf7f82d72002-01-06 10:13:40 +0000303 return TT_Err_Invalid_Outline;
Werner Lemberga929ba92000-06-25 06:47:11 +0000304
Werner Lemberg545c4e52006-05-17 22:55:04 +0000305 loader->n_contours = FT_NEXT_SHORT( p );
David Turner90f68b72000-06-23 12:26:14 +0000306
Werner Lemberg545c4e52006-05-17 22:55:04 +0000307 loader->bbox.xMin = FT_NEXT_SHORT( p );
308 loader->bbox.yMin = FT_NEXT_SHORT( p );
309 loader->bbox.xMax = FT_NEXT_SHORT( p );
310 loader->bbox.yMax = FT_NEXT_SHORT( p );
David Turner90f68b72000-06-23 12:26:14 +0000311
312 FT_TRACE5(( " # of contours: %d\n", loader->n_contours ));
313 FT_TRACE5(( " xMin: %4d xMax: %4d\n", loader->bbox.xMin,
314 loader->bbox.xMax ));
315 FT_TRACE5(( " yMin: %4d yMax: %4d\n", loader->bbox.yMin,
316 loader->bbox.yMax ));
David Turner281679d2006-05-17 13:34:21 +0000317 loader->cursor = p;
Werner Lembergbd5ae402000-07-05 04:32:02 +0000318
Werner Lemberg1429db62001-04-02 23:54:01 +0000319 return TT_Err_Ok;
Werner Lembergbd5ae402000-07-05 04:32:02 +0000320 }
David Turner90f68b72000-06-23 12:26:14 +0000321
322
Werner Lemberg4a2305c2001-06-28 07:17:51 +0000323 FT_CALLBACK_DEF( FT_Error )
Werner Lemberg91db04c2002-04-01 14:25:28 +0000324 TT_Load_Simple_Glyph( TT_Loader load )
David Turnerd2b1f351999-12-16 23:11:37 +0000325 {
Werner Lemberg91db04c2002-04-01 14:25:28 +0000326 FT_Error error;
David Turner281679d2006-05-17 13:34:21 +0000327 FT_Byte* p = load->cursor;
328 FT_Byte* limit = load->limit;
Werner Lemberg91db04c2002-04-01 14:25:28 +0000329 FT_GlyphLoader gloader = load->gloader;
330 FT_Int n_contours = load->n_contours;
331 FT_Outline* outline;
332 TT_Face face = (TT_Face)load->face;
Werner Lemberg91db04c2002-04-01 14:25:28 +0000333 FT_UShort n_ins;
David Turner7fa30ee2007-06-11 00:55:23 +0000334 FT_Int n_points;
David Turnere49ab252000-05-16 23:44:38 +0000335
Werner Lemberg0240d292003-06-09 15:54:18 +0000336 FT_Byte *flag, *flag_limit;
337 FT_Byte c, count;
338 FT_Vector *vec, *vec_limit;
339 FT_Pos x;
David Turner815911a2007-06-16 17:07:20 +0000340 FT_Short *cont, *cont_limit, prev_cont;
David Turner5f5e5442007-06-11 00:18:00 +0000341 FT_Int xy_size = 0;
Werner Lemberg0240d292003-06-09 15:54:18 +0000342
Werner Lemberg78575dc2000-06-12 19:36:41 +0000343
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +0000344 /* check that we can add the contours to the glyph */
David Turner9fbd2ab2005-10-28 16:14:14 +0000345 error = FT_GLYPHLOADER_CHECK_POINTS( gloader, 0, n_contours );
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +0000346 if ( error )
347 goto Fail;
348
Werner Lemberg44bb3032004-04-25 20:15:11 +0000349 /* reading the contours' endpoints & number of points */
Werner Lemberg0240d292003-06-09 15:54:18 +0000350 cont = gloader->current.outline.contours;
351 cont_limit = cont + n_contours;
Werner Lembergbd5ae402000-07-05 04:32:02 +0000352
Werner Lemberg0240d292003-06-09 15:54:18 +0000353 /* check space for contours array + instructions count */
Werner Lemberge12ed562007-06-17 05:31:23 +0000354 if ( n_contours >= 0xFFF || p + ( n_contours + 1 ) * 2 > limit )
Werner Lemberg0240d292003-06-09 15:54:18 +0000355 goto Invalid_Outline;
Werner Lembergac812952002-01-06 16:42:44 +0000356
Werner Lemberg89d64fa2008-05-17 20:06:13 +0000357 prev_cont = FT_NEXT_USHORT( p );
358
359 if ( n_contours > 0 )
360 cont[0] = prev_cont;
361
David Turner815911a2007-06-16 17:07:20 +0000362 for ( cont++; cont < cont_limit; cont++ )
363 {
Werner Lemberg545c4e52006-05-17 22:55:04 +0000364 cont[0] = FT_NEXT_USHORT( p );
David Turner8f626b02007-06-22 22:22:38 +0000365 if ( cont[0] <= prev_cont )
David Turner815911a2007-06-16 17:07:20 +0000366 {
Werner Lemberge12ed562007-06-17 05:31:23 +0000367 /* unordered contours: this is invalid */
David Turner815911a2007-06-16 17:07:20 +0000368 error = FT_Err_Invalid_Table;
369 goto Fail;
370 }
371 prev_cont = cont[0];
372 }
Werner Lemberg0240d292003-06-09 15:54:18 +0000373
374 n_points = 0;
375 if ( n_contours > 0 )
Werner Lembergd0692462007-05-16 15:48:02 +0000376 {
Werner Lemberg0240d292003-06-09 15:54:18 +0000377 n_points = cont[-1] + 1;
Werner Lembergd0692462007-05-16 15:48:02 +0000378 if ( n_points < 0 )
379 goto Invalid_Outline;
380 }
Werner Lemberg0240d292003-06-09 15:54:18 +0000381
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +0000382 /* note that we will add four phantom points later */
David Turner9fbd2ab2005-10-28 16:14:14 +0000383 error = FT_GLYPHLOADER_CHECK_POINTS( gloader, n_points + 4, 0 );
Werner Lemberg0240d292003-06-09 15:54:18 +0000384 if ( error )
385 goto Fail;
386
387 /* we'd better check the contours table right now */
388 outline = &gloader->current.outline;
389
390 for ( cont = outline->contours + 1; cont < cont_limit; cont++ )
391 if ( cont[-1] >= cont[0] )
David Turnerf7f82d72002-01-06 10:13:40 +0000392 goto Invalid_Outline;
Werner Lemberga929ba92000-06-25 06:47:11 +0000393
Werner Lemberg78575dc2000-06-12 19:36:41 +0000394 /* reading the bytecode instructions */
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +0000395 load->glyph->control_len = 0;
396 load->glyph->control_data = 0;
Werner Lembergbd5ae402000-07-05 04:32:02 +0000397
Werner Lemberg545c4e52006-05-17 22:55:04 +0000398 if ( p + 2 > limit )
David Turner281679d2006-05-17 13:34:21 +0000399 goto Invalid_Outline;
400
Werner Lemberg545c4e52006-05-17 22:55:04 +0000401 n_ins = FT_NEXT_USHORT( p );
David Turnerd2b1f351999-12-16 23:11:37 +0000402
Werner Lemberg0240d292003-06-09 15:54:18 +0000403 FT_TRACE5(( " Instructions size: %u\n", n_ins ));
David Turnerd2b1f351999-12-16 23:11:37 +0000404
405 if ( n_ins > face->max_profile.maxSizeOfInstructions )
406 {
Werner Lemberg858abbe2009-06-26 06:15:41 +0200407 FT_TRACE0(( "TT_Load_Simple_Glyph: too many instructions (%d)\n",
Werner Lemberg6e2f9d52007-06-05 06:58:48 +0000408 n_ins ));
Werner Lemberg1f7f0e82001-06-06 17:30:41 +0000409 error = TT_Err_Too_Many_Hints;
David Turnerd2b1f351999-12-16 23:11:37 +0000410 goto Fail;
411 }
412
Werner Lemberg545c4e52006-05-17 22:55:04 +0000413 if ( ( limit - p ) < n_ins )
David Turnerd2b1f351999-12-16 23:11:37 +0000414 {
Werner Lemberg858abbe2009-06-26 06:15:41 +0200415 FT_TRACE0(( "TT_Load_Simple_Glyph: instruction count mismatch\n" ));
Werner Lemberg1f7f0e82001-06-06 17:30:41 +0000416 error = TT_Err_Too_Many_Hints;
David Turnerd2b1f351999-12-16 23:11:37 +0000417 goto Fail;
418 }
David Turnerd2b1f351999-12-16 23:11:37 +0000419
David Turner6aa260c2006-08-25 22:45:13 +0000420#ifdef TT_USE_BYTECODE_INTERPRETER
Werner Lemberga929ba92000-06-25 06:47:11 +0000421
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +0000422 if ( IS_HINTED( load->load_flags ) )
David Turner08fdac92000-02-21 16:01:33 +0000423 {
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +0000424 load->glyph->control_len = n_ins;
425 load->glyph->control_data = load->exec->glyphIns;
Werner Lembergbd5ae402000-07-05 04:32:02 +0000426
David Turner281679d2006-05-17 13:34:21 +0000427 FT_MEM_COPY( load->exec->glyphIns, p, (FT_Long)n_ins );
David Turner08fdac92000-02-21 16:01:33 +0000428 }
Werner Lemberga929ba92000-06-25 06:47:11 +0000429
David Turner6aa260c2006-08-25 22:45:13 +0000430#endif /* TT_USE_BYTECODE_INTERPRETER */
David Turnerd2b1f351999-12-16 23:11:37 +0000431
David Turner281679d2006-05-17 13:34:21 +0000432 p += n_ins;
David Turnere49ab252000-05-16 23:44:38 +0000433
Werner Lemberg78575dc2000-06-12 19:36:41 +0000434 /* reading the point tags */
Werner Lemberg0240d292003-06-09 15:54:18 +0000435 flag = (FT_Byte*)outline->tags;
436 flag_limit = flag + n_points;
437
Werner Lemberg685dd4f2004-10-13 05:15:44 +0000438 FT_ASSERT( flag != NULL );
439
Werner Lembergf946fc62003-12-31 08:48:21 +0000440 while ( flag < flag_limit )
David Turnere49ab252000-05-16 23:44:38 +0000441 {
Werner Lemberg545c4e52006-05-17 22:55:04 +0000442 if ( p + 1 > limit )
Werner Lemberg0240d292003-06-09 15:54:18 +0000443 goto Invalid_Outline;
David Turnere49ab252000-05-16 23:44:38 +0000444
Werner Lemberg545c4e52006-05-17 22:55:04 +0000445 *flag++ = c = FT_NEXT_BYTE( p );
Werner Lemberg0240d292003-06-09 15:54:18 +0000446 if ( c & 8 )
David Turnerd2b1f351999-12-16 23:11:37 +0000447 {
Werner Lemberg545c4e52006-05-17 22:55:04 +0000448 if ( p + 1 > limit )
David Turnerf7f82d72002-01-06 10:13:40 +0000449 goto Invalid_Outline;
450
Werner Lemberg545c4e52006-05-17 22:55:04 +0000451 count = FT_NEXT_BYTE( p );
Werner Lemberg0240d292003-06-09 15:54:18 +0000452 if ( flag + (FT_Int)count > flag_limit )
453 goto Invalid_Outline;
David Turnerf7f82d72002-01-06 10:13:40 +0000454
Werner Lemberg0240d292003-06-09 15:54:18 +0000455 for ( ; count > 0; count-- )
456 *flag++ = c;
David Turnerd2b1f351999-12-16 23:11:37 +0000457 }
458 }
459
Werner Lemberg78575dc2000-06-12 19:36:41 +0000460 /* reading the X coordinates */
David Turnere49ab252000-05-16 23:44:38 +0000461
Werner Lemberg0240d292003-06-09 15:54:18 +0000462 vec = outline->points;
463 vec_limit = vec + n_points;
464 flag = (FT_Byte*)outline->tags;
465 x = 0;
466
David Turner5f5e5442007-06-11 00:18:00 +0000467 if ( p + xy_size > limit )
468 goto Invalid_Outline;
469
Werner Lemberg0240d292003-06-09 15:54:18 +0000470 for ( ; vec < vec_limit; vec++, flag++ )
David Turnerd2b1f351999-12-16 23:11:37 +0000471 {
Werner Lemberg35ae5742008-10-02 10:40:52 +0000472 FT_Pos y = 0;
473 FT_Byte f = *flag;
David Turnere49ab252000-05-16 23:44:38 +0000474
Werner Lemberg78575dc2000-06-12 19:36:41 +0000475
David Turner5f5e5442007-06-11 00:18:00 +0000476 if ( f & 2 )
David Turnerd2b1f351999-12-16 23:11:37 +0000477 {
Werner Lembergf6c120f2007-06-11 04:55:58 +0000478 if ( p + 1 > limit )
David Turner281679d2006-05-17 13:34:21 +0000479 goto Invalid_Outline;
480
Werner Lemberg545c4e52006-05-17 22:55:04 +0000481 y = (FT_Pos)FT_NEXT_BYTE( p );
David Turner5f5e5442007-06-11 00:18:00 +0000482 if ( ( f & 16 ) == 0 )
Werner Lemberg0240d292003-06-09 15:54:18 +0000483 y = -y;
David Turnerd2b1f351999-12-16 23:11:37 +0000484 }
David Turner5f5e5442007-06-11 00:18:00 +0000485 else if ( ( f & 16 ) == 0 )
David Turner281679d2006-05-17 13:34:21 +0000486 {
Werner Lembergf6c120f2007-06-11 04:55:58 +0000487 if ( p + 2 > limit )
David Turner281679d2006-05-17 13:34:21 +0000488 goto Invalid_Outline;
489
Werner Lemberg545c4e52006-05-17 22:55:04 +0000490 y = (FT_Pos)FT_NEXT_SHORT( p );
David Turner281679d2006-05-17 13:34:21 +0000491 }
Werner Lemberg0240d292003-06-09 15:54:18 +0000492
493 x += y;
494 vec->x = x;
Werner Lemberg35ae5742008-10-02 10:40:52 +0000495 /* the cast is for stupid compilers */
496 *flag = (FT_Byte)( f & ~( 2 | 16 ) );
David Turnerd2b1f351999-12-16 23:11:37 +0000497 }
498
Werner Lemberg78575dc2000-06-12 19:36:41 +0000499 /* reading the Y coordinates */
David Turnerd2b1f351999-12-16 23:11:37 +0000500
Werner Lemberg0240d292003-06-09 15:54:18 +0000501 vec = gloader->current.outline.points;
502 vec_limit = vec + n_points;
503 flag = (FT_Byte*)outline->tags;
504 x = 0;
505
506 for ( ; vec < vec_limit; vec++, flag++ )
David Turnerd2b1f351999-12-16 23:11:37 +0000507 {
Werner Lemberg35ae5742008-10-02 10:40:52 +0000508 FT_Pos y = 0;
509 FT_Byte f = *flag;
David Turnere49ab252000-05-16 23:44:38 +0000510
Werner Lemberg78575dc2000-06-12 19:36:41 +0000511
David Turner5f5e5442007-06-11 00:18:00 +0000512 if ( f & 4 )
David Turnerd2b1f351999-12-16 23:11:37 +0000513 {
Werner Lembergf6c120f2007-06-11 04:55:58 +0000514 if ( p + 1 > limit )
David Turner281679d2006-05-17 13:34:21 +0000515 goto Invalid_Outline;
516
Werner Lemberg545c4e52006-05-17 22:55:04 +0000517 y = (FT_Pos)FT_NEXT_BYTE( p );
David Turner5f5e5442007-06-11 00:18:00 +0000518 if ( ( f & 32 ) == 0 )
Werner Lemberg0240d292003-06-09 15:54:18 +0000519 y = -y;
David Turnerd2b1f351999-12-16 23:11:37 +0000520 }
David Turner5f5e5442007-06-11 00:18:00 +0000521 else if ( ( f & 32 ) == 0 )
David Turner281679d2006-05-17 13:34:21 +0000522 {
Werner Lembergf6c120f2007-06-11 04:55:58 +0000523 if ( p + 2 > limit )
David Turner281679d2006-05-17 13:34:21 +0000524 goto Invalid_Outline;
525
Werner Lemberg545c4e52006-05-17 22:55:04 +0000526 y = (FT_Pos)FT_NEXT_SHORT( p );
David Turner281679d2006-05-17 13:34:21 +0000527 }
Werner Lemberg0240d292003-06-09 15:54:18 +0000528
529 x += y;
530 vec->y = x;
Werner Lemberg35ae5742008-10-02 10:40:52 +0000531 /* the cast is for stupid compilers */
532 *flag = (FT_Byte)( f & FT_CURVE_TAG_ON );
David Turnerd2b1f351999-12-16 23:11:37 +0000533 }
534
David Turner8edbcab2001-06-19 08:28:24 +0000535 outline->n_points = (FT_UShort)n_points;
536 outline->n_contours = (FT_Short) n_contours;
David Turnerc3128612000-06-23 05:02:13 +0000537
David Turner281679d2006-05-17 13:34:21 +0000538 load->cursor = p;
David Turnerf7f82d72002-01-06 10:13:40 +0000539
Werner Lembergbd5ae402000-07-05 04:32:02 +0000540 Fail:
David Turnerc3128612000-06-23 05:02:13 +0000541 return error;
David Turnerf7f82d72002-01-06 10:13:40 +0000542
543 Invalid_Outline:
544 error = TT_Err_Invalid_Outline;
545 goto Fail;
David Turnerc3128612000-06-23 05:02:13 +0000546 }
547
548
Werner Lemberg4a2305c2001-06-28 07:17:51 +0000549 FT_CALLBACK_DEF( FT_Error )
Werner Lemberg91db04c2002-04-01 14:25:28 +0000550 TT_Load_Composite_Glyph( TT_Loader loader )
David Turner90f68b72000-06-23 12:26:14 +0000551 {
Werner Lemberg91db04c2002-04-01 14:25:28 +0000552 FT_Error error;
David Turner281679d2006-05-17 13:34:21 +0000553 FT_Byte* p = loader->cursor;
554 FT_Byte* limit = loader->limit;
Werner Lemberg91db04c2002-04-01 14:25:28 +0000555 FT_GlyphLoader gloader = loader->gloader;
David Turnereba5ad42002-03-14 12:56:35 +0000556 FT_SubGlyph subglyph;
Werner Lemberg91db04c2002-04-01 14:25:28 +0000557 FT_UInt num_subglyphs;
David Turner90f68b72000-06-23 12:26:14 +0000558
Werner Lemberga929ba92000-06-25 06:47:11 +0000559
David Turner90f68b72000-06-23 12:26:14 +0000560 num_subglyphs = 0;
Werner Lemberga929ba92000-06-25 06:47:11 +0000561
David Turner90f68b72000-06-23 12:26:14 +0000562 do
563 {
564 FT_Fixed xx, xy, yy, yx;
David Turner281679d2006-05-17 13:34:21 +0000565 FT_UInt count;
David Turner90f68b72000-06-23 12:26:14 +0000566
Werner Lemberga929ba92000-06-25 06:47:11 +0000567
David Turner90f68b72000-06-23 12:26:14 +0000568 /* check that we can load a new subglyph */
David Turnereba5ad42002-03-14 12:56:35 +0000569 error = FT_GlyphLoader_CheckSubGlyphs( gloader, num_subglyphs + 1 );
Werner Lemberga929ba92000-06-25 06:47:11 +0000570 if ( error )
571 goto Fail;
Werner Lembergbd5ae402000-07-05 04:32:02 +0000572
Werner Lembergac812952002-01-06 16:42:44 +0000573 /* check space */
Werner Lemberg545c4e52006-05-17 22:55:04 +0000574 if ( p + 4 > limit )
David Turnerf7f82d72002-01-06 10:13:40 +0000575 goto Invalid_Composite;
576
David Turner90f68b72000-06-23 12:26:14 +0000577 subglyph = gloader->current.subglyphs + num_subglyphs;
578
579 subglyph->arg1 = subglyph->arg2 = 0;
580
Werner Lemberg545c4e52006-05-17 22:55:04 +0000581 subglyph->flags = FT_NEXT_USHORT( p );
582 subglyph->index = FT_NEXT_USHORT( p );
David Turner90f68b72000-06-23 12:26:14 +0000583
Werner Lembergac812952002-01-06 16:42:44 +0000584 /* check space */
David Turner281679d2006-05-17 13:34:21 +0000585 count = 2;
David Turnerf7f82d72002-01-06 10:13:40 +0000586 if ( subglyph->flags & ARGS_ARE_WORDS )
David Turner281679d2006-05-17 13:34:21 +0000587 count += 2;
David Turnerf7f82d72002-01-06 10:13:40 +0000588 if ( subglyph->flags & WE_HAVE_A_SCALE )
David Turner281679d2006-05-17 13:34:21 +0000589 count += 2;
David Turnerf7f82d72002-01-06 10:13:40 +0000590 else if ( subglyph->flags & WE_HAVE_AN_XY_SCALE )
David Turner281679d2006-05-17 13:34:21 +0000591 count += 4;
David Turnerf7f82d72002-01-06 10:13:40 +0000592 else if ( subglyph->flags & WE_HAVE_A_2X2 )
David Turner281679d2006-05-17 13:34:21 +0000593 count += 8;
David Turnerf7f82d72002-01-06 10:13:40 +0000594
David Turner281679d2006-05-17 13:34:21 +0000595 if ( p + count > limit )
David Turnerf7f82d72002-01-06 10:13:40 +0000596 goto Invalid_Composite;
597
David Turner90f68b72000-06-23 12:26:14 +0000598 /* read arguments */
599 if ( subglyph->flags & ARGS_ARE_WORDS )
600 {
Werner Lemberg545c4e52006-05-17 22:55:04 +0000601 subglyph->arg1 = FT_NEXT_SHORT( p );
602 subglyph->arg2 = FT_NEXT_SHORT( p );
David Turner90f68b72000-06-23 12:26:14 +0000603 }
604 else
605 {
Werner Lemberg545c4e52006-05-17 22:55:04 +0000606 subglyph->arg1 = FT_NEXT_CHAR( p );
607 subglyph->arg2 = FT_NEXT_CHAR( p );
David Turner90f68b72000-06-23 12:26:14 +0000608 }
609
610 /* read transform */
611 xx = yy = 0x10000L;
612 xy = yx = 0;
613
614 if ( subglyph->flags & WE_HAVE_A_SCALE )
615 {
Werner Lemberg545c4e52006-05-17 22:55:04 +0000616 xx = (FT_Fixed)FT_NEXT_SHORT( p ) << 2;
David Turner90f68b72000-06-23 12:26:14 +0000617 yy = xx;
618 }
619 else if ( subglyph->flags & WE_HAVE_AN_XY_SCALE )
620 {
Werner Lemberg545c4e52006-05-17 22:55:04 +0000621 xx = (FT_Fixed)FT_NEXT_SHORT( p ) << 2;
622 yy = (FT_Fixed)FT_NEXT_SHORT( p ) << 2;
David Turner90f68b72000-06-23 12:26:14 +0000623 }
624 else if ( subglyph->flags & WE_HAVE_A_2X2 )
625 {
Werner Lemberg545c4e52006-05-17 22:55:04 +0000626 xx = (FT_Fixed)FT_NEXT_SHORT( p ) << 2;
627 yx = (FT_Fixed)FT_NEXT_SHORT( p ) << 2;
628 xy = (FT_Fixed)FT_NEXT_SHORT( p ) << 2;
629 yy = (FT_Fixed)FT_NEXT_SHORT( p ) << 2;
David Turner90f68b72000-06-23 12:26:14 +0000630 }
631
632 subglyph->transform.xx = xx;
633 subglyph->transform.xy = xy;
634 subglyph->transform.yx = yx;
635 subglyph->transform.yy = yy;
636
637 num_subglyphs++;
Werner Lemberg5811c7c2000-07-02 13:53:16 +0000638
Werner Lembergdcd2e142000-06-25 07:43:15 +0000639 } while ( subglyph->flags & MORE_COMPONENTS );
David Turner90f68b72000-06-23 12:26:14 +0000640
641 gloader->current.num_subglyphs = num_subglyphs;
642
David Turner6aa260c2006-08-25 22:45:13 +0000643#ifdef TT_USE_BYTECODE_INTERPRETER
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +0000644
David Turner90f68b72000-06-23 12:26:14 +0000645 {
Werner Lemberg545c4e52006-05-17 22:55:04 +0000646 FT_Stream stream = loader->stream;
647
648
Werner Lemberg5df5dbb2008-06-22 13:40:08 +0000649 /* we must undo the FT_FRAME_ENTER in order to point */
650 /* to the composite instructions, if we find some. */
651 /* We will process them later. */
652 /* */
David Turner7d3a2642002-03-20 10:49:31 +0000653 loader->ins_pos = (FT_ULong)( FT_STREAM_POS() +
David Turner281679d2006-05-17 13:34:21 +0000654 p - limit );
David Turner90f68b72000-06-23 12:26:14 +0000655 }
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +0000656
David Turner90f68b72000-06-23 12:26:14 +0000657#endif
658
David Turner281679d2006-05-17 13:34:21 +0000659 loader->cursor = p;
David Turnerf7f82d72002-01-06 10:13:40 +0000660
David Turner90f68b72000-06-23 12:26:14 +0000661 Fail:
662 return error;
David Turnerf7f82d72002-01-06 10:13:40 +0000663
664 Invalid_Composite:
665 error = TT_Err_Invalid_Composite;
666 goto Fail;
David Turner90f68b72000-06-23 12:26:14 +0000667 }
668
David Turnerc3128612000-06-23 05:02:13 +0000669
David Turnerbc82f1b2002-03-01 02:26:22 +0000670 FT_LOCAL_DEF( void )
Werner Lemberg4a2305c2001-06-28 07:17:51 +0000671 TT_Init_Glyph_Loading( TT_Face face )
David Turner994d7742000-06-25 04:49:19 +0000672 {
673 face->access_glyph_frame = TT_Access_Glyph_Frame;
674 face->read_glyph_header = TT_Load_Glyph_Header;
675 face->read_simple_glyph = TT_Load_Simple_Glyph;
676 face->read_composite_glyph = TT_Load_Composite_Glyph;
677 face->forget_glyph_frame = TT_Forget_Glyph_Frame;
678 }
679
David Turnerc3128612000-06-23 05:02:13 +0000680
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +0000681 static void
682 tt_prepare_zone( TT_GlyphZone zone,
683 FT_GlyphLoad load,
684 FT_UInt start_point,
685 FT_UInt start_contour )
686 {
Werner Lemberge12ed562007-06-17 05:31:23 +0000687 zone->n_points = (FT_UShort)( load->outline.n_points - start_point );
688 zone->n_contours = (FT_Short) ( load->outline.n_contours -
689 start_contour );
690 zone->org = load->extra_points + start_point;
691 zone->cur = load->outline.points + start_point;
692 zone->orus = load->extra_points2 + start_point;
693 zone->tags = (FT_Byte*)load->outline.tags + start_point;
694 zone->contours = (FT_UShort*)load->outline.contours + start_contour;
David Turner9fbfc6a2006-08-16 09:11:31 +0000695 zone->first_point = (FT_UShort)start_point;
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +0000696 }
697
698
699 /*************************************************************************/
700 /* */
701 /* <Function> */
702 /* TT_Hint_Glyph */
703 /* */
704 /* <Description> */
705 /* Hint the glyph using the zone prepared by the caller. Note that */
706 /* the zone is supposed to include four phantom points. */
707 /* */
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +0000708 static FT_Error
Werner Lemberg7c259462005-09-28 07:34:45 +0000709 TT_Hint_Glyph( TT_Loader loader,
710 FT_Bool is_composite )
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +0000711 {
712 TT_GlyphZone zone = &loader->zone;
713 FT_Pos origin;
714
David Turner6aa260c2006-08-25 22:45:13 +0000715#ifdef TT_USE_BYTECODE_INTERPRETER
Werner Lemberg7c259462005-09-28 07:34:45 +0000716 FT_UInt n_ins;
717#else
718 FT_UNUSED( is_composite );
719#endif
720
David Turner18e44432005-09-23 13:22:10 +0000721
David Turner6aa260c2006-08-25 22:45:13 +0000722#ifdef TT_USE_BYTECODE_INTERPRETER
suzuki toshiya1b6f1d22009-08-01 00:32:16 +0900723 if ( loader->glyph->control_len > 0xFFFFL )
724 {
725 FT_TRACE1(( "TT_Hint_Glyph: too long instructions " ));
726 FT_TRACE1(( "(0x%lx byte) is truncated\n",
727 loader->glyph->control_len ));
728 }
729 n_ins = (FT_UInt)( loader->glyph->control_len );
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +0000730#endif
731
732 origin = zone->cur[zone->n_points - 4].x;
733 origin = FT_PIX_ROUND( origin ) - origin;
734 if ( origin )
735 translate_array( zone->n_points, zone->cur, origin, 0 );
736
David Turner6aa260c2006-08-25 22:45:13 +0000737#ifdef TT_USE_BYTECODE_INTERPRETER
Werner Lemberg6e87ed92007-01-26 22:18:56 +0000738 /* save original point position in org */
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +0000739 if ( n_ins > 0 )
Werner Lemberg12342992006-08-19 11:18:09 +0000740 FT_ARRAY_COPY( zone->org, zone->cur, zone->n_points );
Werner Lembergffa49652008-05-25 12:43:57 +0000741
742 /* Reset graphics state. */
743 loader->exec->GS = ((TT_Size)loader->size)->GS;
744
745 /* XXX: UNDOCUMENTED! Hinting instructions of a composite glyph */
746 /* completely refer to the (already) hinted subglyphs. */
747 if ( is_composite )
748 {
749 loader->exec->metrics.x_scale = 1 << 16;
750 loader->exec->metrics.y_scale = 1 << 16;
751
752 FT_ARRAY_COPY( zone->orus, zone->cur, zone->n_points );
753 }
754 else
755 {
Werner Lemberg0c52faa2008-05-25 20:04:56 +0000756 loader->exec->metrics.x_scale =
757 ((TT_Size)loader->size)->metrics.x_scale;
758 loader->exec->metrics.y_scale =
759 ((TT_Size)loader->size)->metrics.y_scale;
Werner Lembergffa49652008-05-25 12:43:57 +0000760 }
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +0000761#endif
762
763 /* round pp2 and pp4 */
Werner Lemberg7c259462005-09-28 07:34:45 +0000764 zone->cur[zone->n_points - 3].x =
765 FT_PIX_ROUND( zone->cur[zone->n_points - 3].x );
766 zone->cur[zone->n_points - 1].y =
767 FT_PIX_ROUND( zone->cur[zone->n_points - 1].y );
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +0000768
David Turner6aa260c2006-08-25 22:45:13 +0000769#ifdef TT_USE_BYTECODE_INTERPRETER
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +0000770
771 if ( n_ins > 0 )
772 {
773 FT_Bool debug;
774 FT_Error error;
775
Werner Lemberg72271142009-06-18 15:42:52 +0200776 FT_GlyphLoader gloader = loader->gloader;
777 FT_Outline current_outline = gloader->current.outline;
778
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +0000779
780 error = TT_Set_CodeRange( loader->exec, tt_coderange_glyph,
781 loader->exec->glyphIns, n_ins );
782 if ( error )
783 return error;
784
Werner Lemberg7c259462005-09-28 07:34:45 +0000785 loader->exec->is_composite = is_composite;
786 loader->exec->pts = *zone;
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +0000787
David Turner115b4422006-12-22 11:37:05 +0000788 debug = FT_BOOL( !( loader->load_flags & FT_LOAD_NO_SCALE ) &&
Werner Lemberg6b87e6f2007-01-02 19:20:08 +0000789 ((TT_Size)loader->size)->debug );
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +0000790
791 error = TT_Run_Context( loader->exec, debug );
792 if ( error && loader->exec->pedantic_hinting )
793 return error;
Werner Lemberg72271142009-06-18 15:42:52 +0200794
795 /* store drop-out mode in bits 5-7; set bit 2 also as a marker */
796 current_outline.tags[0] |=
797 ( loader->exec->GS.scan_type << 5 ) | FT_CURVE_TAG_HAS_SCANMODE;
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +0000798 }
799
800#endif
801
802 /* save glyph phantom points */
803 if ( !loader->preserve_pps )
804 {
805 loader->pp1 = zone->cur[zone->n_points - 4];
806 loader->pp2 = zone->cur[zone->n_points - 3];
807 loader->pp3 = zone->cur[zone->n_points - 2];
808 loader->pp4 = zone->cur[zone->n_points - 1];
809 }
810
811 return TT_Err_Ok;
812 }
813
814
David Turnerc3128612000-06-23 05:02:13 +0000815 /*************************************************************************/
816 /* */
817 /* <Function> */
818 /* TT_Process_Simple_Glyph */
819 /* */
820 /* <Description> */
821 /* Once a simple glyph has been loaded, it needs to be processed. */
822 /* Usually, this means scaling and hinting through bytecode */
Werner Lemberga929ba92000-06-25 06:47:11 +0000823 /* interpretation. */
David Turnerc3128612000-06-23 05:02:13 +0000824 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +0000825 static FT_Error
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +0000826 TT_Process_Simple_Glyph( TT_Loader loader )
David Turnerc3128612000-06-23 05:02:13 +0000827 {
Werner Lemberg7c259462005-09-28 07:34:45 +0000828 FT_GlyphLoader gloader = loader->gloader;
829 FT_Error error = TT_Err_Ok;
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +0000830 FT_Outline* outline;
Werner Lembergd21fe6e2007-07-10 23:10:39 +0000831 FT_Int n_points;
Werner Lemberga929ba92000-06-25 06:47:11 +0000832
Werner Lemberge4b32a52000-10-31 20:42:18 +0000833
Werner Lemberg7c259462005-09-28 07:34:45 +0000834 outline = &gloader->current.outline;
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +0000835 n_points = outline->n_points;
David Turnerc3128612000-06-23 05:02:13 +0000836
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +0000837 /* set phantom points */
David Turnere49ab252000-05-16 23:44:38 +0000838
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +0000839 outline->points[n_points ] = loader->pp1;
840 outline->points[n_points + 1] = loader->pp2;
841 outline->points[n_points + 2] = loader->pp3;
842 outline->points[n_points + 3] = loader->pp4;
David Turnerd2b1f351999-12-16 23:11:37 +0000843
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +0000844 outline->tags[n_points ] = 0;
845 outline->tags[n_points + 1] = 0;
846 outline->tags[n_points + 2] = 0;
847 outline->tags[n_points + 3] = 0;
David Turnerd2b1f351999-12-16 23:11:37 +0000848
Werner Lemberg8bb07e62004-03-27 08:43:17 +0000849 n_points += 4;
David Turnerd2b1f351999-12-16 23:11:37 +0000850
Werner Lemberg44bb3032004-04-25 20:15:11 +0000851#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
852
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +0000853 if ( ((TT_Face)loader->face)->doblend )
Werner Lemberg44bb3032004-04-25 20:15:11 +0000854 {
855 /* Deltas apply to the unscaled data. */
Werner Lemberg7c259462005-09-28 07:34:45 +0000856 FT_Vector* deltas;
857 FT_Memory memory = loader->face->memory;
Werner Lembergd21fe6e2007-07-10 23:10:39 +0000858 FT_Int i;
Werner Lemberg44bb3032004-04-25 20:15:11 +0000859
860
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +0000861 error = TT_Vary_Get_Glyph_Deltas( (TT_Face)(loader->face),
862 loader->glyph_index,
Werner Lemberg2b54eba2004-05-07 07:08:14 +0000863 &deltas,
864 n_points );
Werner Lemberg2b54eba2004-05-07 07:08:14 +0000865 if ( error )
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +0000866 return error;
Werner Lemberg44bb3032004-04-25 20:15:11 +0000867
868 for ( i = 0; i < n_points; ++i )
869 {
870 outline->points[i].x += deltas[i].x;
871 outline->points[i].y += deltas[i].y;
872 }
873
874 FT_FREE( deltas );
875 }
876
877#endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
878
David Turner33f5f242006-08-16 16:50:55 +0000879 if ( IS_HINTED( loader->load_flags ) )
880 {
881 tt_prepare_zone( &loader->zone, &gloader->current, 0, 0 );
882
883 FT_ARRAY_COPY( loader->zone.orus, loader->zone.cur,
884 loader->zone.n_points + 4 );
885 }
886
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +0000887 /* scale the glyph */
888 if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
David Turnerd2b1f351999-12-16 23:11:37 +0000889 {
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +0000890 FT_Vector* vec = outline->points;
891 FT_Vector* limit = outline->points + n_points;
892 FT_Fixed x_scale = ((TT_Size)loader->size)->metrics.x_scale;
893 FT_Fixed y_scale = ((TT_Size)loader->size)->metrics.y_scale;
Werner Lemberg5811c7c2000-07-02 13:53:16 +0000894
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +0000895
Werner Lemberg78575dc2000-06-12 19:36:41 +0000896 for ( ; vec < limit; vec++ )
David Turnerd2b1f351999-12-16 23:11:37 +0000897 {
David Turner8f43c712000-02-02 12:16:19 +0000898 vec->x = FT_MulFix( vec->x, x_scale );
899 vec->y = FT_MulFix( vec->y, y_scale );
David Turnerd2b1f351999-12-16 23:11:37 +0000900 }
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +0000901
902 loader->pp1 = outline->points[n_points - 4];
903 loader->pp2 = outline->points[n_points - 3];
904 loader->pp3 = outline->points[n_points - 2];
905 loader->pp4 = outline->points[n_points - 1];
David Turnerf0df85b2000-06-22 00:17:42 +0000906 }
David Turnerd2b1f351999-12-16 23:11:37 +0000907
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +0000908 if ( IS_HINTED( loader->load_flags ) )
David Turnerf0df85b2000-06-22 00:17:42 +0000909 {
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +0000910 loader->zone.n_points += 4;
Werner Lemberg78575dc2000-06-12 19:36:41 +0000911
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +0000912 error = TT_Hint_Glyph( loader, 0 );
David Turnerd2b1f351999-12-16 23:11:37 +0000913 }
914
David Turnerd2b1f351999-12-16 23:11:37 +0000915 return error;
916 }
917
918
919 /*************************************************************************/
920 /* */
921 /* <Function> */
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +0000922 /* TT_Process_Composite_Component */
923 /* */
924 /* <Description> */
925 /* Once a composite component has been loaded, it needs to be */
926 /* processed. Usually, this means transforming and translating. */
927 /* */
928 static FT_Error
929 TT_Process_Composite_Component( TT_Loader loader,
930 FT_SubGlyph subglyph,
931 FT_UInt start_point,
932 FT_UInt num_base_points )
933 {
934 FT_GlyphLoader gloader = loader->gloader;
935 FT_Vector* base_vec = gloader->base.outline.points;
936 FT_UInt num_points = gloader->base.outline.n_points;
937 FT_Bool have_scale;
938 FT_Pos x, y;
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +0000939
David Turner18e44432005-09-23 13:22:10 +0000940
941 have_scale = FT_BOOL( subglyph->flags & ( WE_HAVE_A_SCALE |
942 WE_HAVE_AN_XY_SCALE |
943 WE_HAVE_A_2X2 ) );
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +0000944
945 /* perform the transform required for this subglyph */
946 if ( have_scale )
947 {
Werner Lembergffa033b2005-08-19 08:56:29 +0000948 FT_UInt i;
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +0000949
950
951 for ( i = num_base_points; i < num_points; i++ )
952 FT_Vector_Transform( base_vec + i, &subglyph->transform );
953 }
954
955 /* get offset */
956 if ( !( subglyph->flags & ARGS_ARE_XY_VALUES ) )
957 {
958 FT_UInt k = subglyph->arg1;
959 FT_UInt l = subglyph->arg2;
960 FT_Vector* p1;
961 FT_Vector* p2;
962
963
Werner Lembergffa033b2005-08-19 08:56:29 +0000964 /* match l-th point of the newly loaded component to the k-th point */
965 /* of the previously loaded components. */
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +0000966
967 /* change to the point numbers used by our outline */
968 k += start_point;
969 l += num_base_points;
Werner Lembergffa033b2005-08-19 08:56:29 +0000970 if ( k >= num_base_points ||
971 l >= num_points )
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +0000972 return TT_Err_Invalid_Composite;
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +0000973
974 p1 = gloader->base.outline.points + k;
975 p2 = gloader->base.outline.points + l;
976
977 x = p1->x - p2->x;
978 y = p1->y - p2->y;
979 }
980 else
981 {
982 x = subglyph->arg1;
983 y = subglyph->arg2;
984
985 if ( !x && !y )
986 return TT_Err_Ok;
987
Werner Lembergffa033b2005-08-19 08:56:29 +0000988 /* Use a default value dependent on */
989 /* TT_CONFIG_OPTION_COMPONENT_OFFSET_SCALED. This is useful for old TT */
990 /* fonts which don't set the xxx_COMPONENT_OFFSET bit. */
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +0000991
992 if ( have_scale &&
993#ifdef TT_CONFIG_OPTION_COMPONENT_OFFSET_SCALED
994 !( subglyph->flags & UNSCALED_COMPONENT_OFFSET ) )
995#else
996 ( subglyph->flags & SCALED_COMPONENT_OFFSET ) )
997#endif
998 {
Werner Lemberg7c259462005-09-28 07:34:45 +0000999
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001000#if 0
1001
Werner Lembergffa033b2005-08-19 08:56:29 +00001002 /*************************************************************************/
1003 /* */
1004 /* This algorithm is what Apple documents. But it doesn't work. */
1005 /* */
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001006 int a = subglyph->transform.xx > 0 ? subglyph->transform.xx
1007 : -subglyph->transform.xx;
1008 int b = subglyph->transform.yx > 0 ? subglyph->transform.yx
1009 : -subglyph->transform.yx;
1010 int c = subglyph->transform.xy > 0 ? subglyph->transform.xy
1011 : -subglyph->transform.xy;
1012 int d = subglyph->transform.yy > 0 ? subglyph->transform.yy
1013 : -subglyph->transform.yy;
1014 int m = a > b ? a : b;
1015 int n = c > d ? c : d;
1016
1017
1018 if ( a - b <= 33 && a - b >= -33 )
1019 m *= 2;
1020 if ( c - d <= 33 && c - d >= -33 )
1021 n *= 2;
1022 x = FT_MulFix( x, m );
1023 y = FT_MulFix( y, n );
1024
1025#else /* 0 */
1026
Werner Lembergffa033b2005-08-19 08:56:29 +00001027 /*************************************************************************/
1028 /* */
1029 /* This algorithm is a guess and works much better than the above. */
1030 /* */
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001031 FT_Fixed mac_xscale = FT_SqrtFixed(
suzuki toshiya9fc40942009-08-01 00:32:14 +09001032 (FT_Int32)FT_MulFix( subglyph->transform.xx,
1033 subglyph->transform.xx ) +
1034 (FT_Int32)FT_MulFix( subglyph->transform.xy,
1035 subglyph->transform.xy ) );
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001036 FT_Fixed mac_yscale = FT_SqrtFixed(
suzuki toshiya9fc40942009-08-01 00:32:14 +09001037 (FT_Int32)FT_MulFix( subglyph->transform.yy,
1038 subglyph->transform.yy ) +
1039 (FT_Int32)FT_MulFix( subglyph->transform.yx,
1040 subglyph->transform.yx ) );
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001041
1042
1043 x = FT_MulFix( x, mac_xscale );
1044 y = FT_MulFix( y, mac_yscale );
1045
1046#endif /* 0 */
1047
1048 }
1049
1050 if ( !( loader->load_flags & FT_LOAD_NO_SCALE ) )
1051 {
Werner Lembergffa033b2005-08-19 08:56:29 +00001052 FT_Fixed x_scale = ((TT_Size)loader->size)->metrics.x_scale;
1053 FT_Fixed y_scale = ((TT_Size)loader->size)->metrics.y_scale;
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001054
1055
1056 x = FT_MulFix( x, x_scale );
1057 y = FT_MulFix( y, y_scale );
1058
1059 if ( subglyph->flags & ROUND_XY_TO_GRID )
1060 {
1061 x = FT_PIX_ROUND( x );
1062 y = FT_PIX_ROUND( y );
1063 }
1064 }
1065 }
1066
1067 if ( x || y )
1068 translate_array( num_points - num_base_points,
1069 base_vec + num_base_points,
1070 x, y );
1071
1072 return TT_Err_Ok;
1073 }
1074
1075
1076 /*************************************************************************/
1077 /* */
1078 /* <Function> */
1079 /* TT_Process_Composite_Glyph */
1080 /* */
1081 /* <Description> */
1082 /* This is slightly different from TT_Process_Simple_Glyph, in that */
Werner Lemberg4b2e83d2007-02-01 07:58:02 +00001083 /* its sole purpose is to hint the glyph. Thus this function is */
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001084 /* only available when bytecode interpreter is enabled. */
1085 /* */
1086 static FT_Error
1087 TT_Process_Composite_Glyph( TT_Loader loader,
1088 FT_UInt start_point,
1089 FT_UInt start_contour )
1090 {
1091 FT_Error error;
1092 FT_Outline* outline;
Werner Lemberga2da05c2006-06-25 06:27:27 +00001093 FT_UInt i;
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001094
1095
1096 outline = &loader->gloader->base.outline;
1097
1098 /* make room for phantom points */
David Turner9fbd2ab2005-10-28 16:14:14 +00001099 error = FT_GLYPHLOADER_CHECK_POINTS( loader->gloader,
1100 outline->n_points + 4,
1101 0 );
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001102 if ( error )
1103 return error;
1104
1105 outline->points[outline->n_points ] = loader->pp1;
1106 outline->points[outline->n_points + 1] = loader->pp2;
1107 outline->points[outline->n_points + 2] = loader->pp3;
1108 outline->points[outline->n_points + 3] = loader->pp4;
1109
1110 outline->tags[outline->n_points ] = 0;
1111 outline->tags[outline->n_points + 1] = 0;
1112 outline->tags[outline->n_points + 2] = 0;
1113 outline->tags[outline->n_points + 3] = 0;
1114
David Turner6aa260c2006-08-25 22:45:13 +00001115#ifdef TT_USE_BYTECODE_INTERPRETER
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001116
1117 {
1118 FT_Stream stream = loader->stream;
1119 FT_UShort n_ins;
1120
1121
1122 /* TT_Load_Composite_Glyph only gives us the offset of instructions */
Werner Lemberg7c259462005-09-28 07:34:45 +00001123 /* so we read them here */
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001124 if ( FT_STREAM_SEEK( loader->ins_pos ) ||
Werner Lembergffa033b2005-08-19 08:56:29 +00001125 FT_READ_USHORT( n_ins ) )
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001126 return error;
1127
1128 FT_TRACE5(( " Instructions size = %d\n", n_ins ));
1129
1130 /* check it */
1131 if ( n_ins > ((TT_Face)loader->face)->max_profile.maxSizeOfInstructions )
1132 {
Werner Lemberg858abbe2009-06-26 06:15:41 +02001133 FT_TRACE0(( "TT_Process_Composite_Glyph: too many instructions (%d)\n",
Werner Lemberg6e2f9d52007-06-05 06:58:48 +00001134 n_ins ));
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001135
1136 return TT_Err_Too_Many_Hints;
1137 }
1138 else if ( n_ins == 0 )
1139 return TT_Err_Ok;
1140
1141 if ( FT_STREAM_READ( loader->exec->glyphIns, n_ins ) )
1142 return error;
1143
1144 loader->glyph->control_data = loader->exec->glyphIns;
1145 loader->glyph->control_len = n_ins;
1146 }
1147
1148#endif
1149
Werner Lembergffa033b2005-08-19 08:56:29 +00001150 tt_prepare_zone( &loader->zone, &loader->gloader->base,
1151 start_point, start_contour );
Werner Lemberga2da05c2006-06-25 06:27:27 +00001152
1153 /* Some points are likely touched during execution of */
1154 /* instructions on components. So let's untouch them. */
1155 for ( i = start_point; i < loader->zone.n_points; i++ )
Werner Lemberg780d7e02009-06-17 06:45:20 +02001156 loader->zone.tags[i] &= ~FT_CURVE_TAG_TOUCH_BOTH;
Werner Lemberga2da05c2006-06-25 06:27:27 +00001157
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001158 loader->zone.n_points += 4;
1159
1160 return TT_Hint_Glyph( loader, 1 );
1161 }
1162
1163
1164 /* Calculate the four phantom points. */
1165 /* The first two stand for horizontal origin and advance. */
1166 /* The last two stand for vertical origin and advance. */
1167#define TT_LOADER_SET_PP( loader ) \
1168 do { \
1169 (loader)->pp1.x = (loader)->bbox.xMin - (loader)->left_bearing; \
1170 (loader)->pp1.y = 0; \
1171 (loader)->pp2.x = (loader)->pp1.x + (loader)->advance; \
1172 (loader)->pp2.y = 0; \
1173 (loader)->pp3.x = 0; \
1174 (loader)->pp3.y = (loader)->top_bearing + (loader)->bbox.yMax; \
1175 (loader)->pp4.x = 0; \
1176 (loader)->pp4.y = (loader)->pp3.y - (loader)->vadvance; \
1177 } while ( 0 )
1178
1179
1180 /*************************************************************************/
1181 /* */
1182 /* <Function> */
David Turner8f43c712000-02-02 12:16:19 +00001183 /* load_truetype_glyph */
David Turnerd2b1f351999-12-16 23:11:37 +00001184 /* */
1185 /* <Description> */
Werner Lemberg78575dc2000-06-12 19:36:41 +00001186 /* Loads a given truetype glyph. Handles composites and uses a */
1187 /* TT_Loader object. */
David Turnerd2b1f351999-12-16 23:11:37 +00001188 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00001189 static FT_Error
Werner Lemberg91db04c2002-04-01 14:25:28 +00001190 load_truetype_glyph( TT_Loader loader,
David Turner77b68b82003-01-08 09:59:17 +00001191 FT_UInt glyph_index,
Werner Lembergf186ba62009-11-03 15:46:35 +01001192 FT_UInt recurse_count,
1193 FT_Bool header_only )
David Turnerd2b1f351999-12-16 23:11:37 +00001194 {
Werner Lembergc0aeef42009-11-08 07:58:05 +01001195 FT_Error error = TT_Err_Ok;
Werner Lemberg91db04c2002-04-01 14:25:28 +00001196 FT_Fixed x_scale, y_scale;
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001197 FT_ULong offset;
1198 TT_Face face = (TT_Face)loader->face;
1199 FT_GlyphLoader gloader = loader->gloader;
Werner Lemberg91db04c2002-04-01 14:25:28 +00001200 FT_Bool opened_frame = 0;
David Turnere49ab252000-05-16 23:44:38 +00001201
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001202#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001203 FT_Vector* deltas = NULL;
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001204#endif
1205
Graham Asher13217f22002-07-18 15:59:23 +00001206#ifdef FT_CONFIG_OPTION_INCREMENTAL
Werner Lemberg2b54eba2004-05-07 07:08:14 +00001207 FT_StreamRec inc_stream;
1208 FT_Data glyph_data;
1209 FT_Bool glyph_data_loaded = 0;
Werner Lemberg44bb3032004-04-25 20:15:11 +00001210#endif
1211
Werner Lemberg6ab56242003-06-04 07:59:58 +00001212
Werner Lemberg0f6f3672007-07-04 19:57:45 +00001213 /* some fonts have an incorrect value of `maxComponentDepth', */
1214 /* thus we allow depth 1 to catch the majority of them */
1215 if ( recurse_count > 1 &&
1216 recurse_count > face->max_profile.maxComponentDepth )
David Turner77b68b82003-01-08 09:59:17 +00001217 {
1218 error = TT_Err_Invalid_Composite;
1219 goto Exit;
1220 }
Werner Lemberg7f74a522002-07-26 09:09:10 +00001221
David Turner8f43c712000-02-02 12:16:19 +00001222 /* check glyph index */
Graham Asher13217f22002-07-18 15:59:23 +00001223 if ( glyph_index >= (FT_UInt)face->root.num_glyphs )
David Turnerd2b1f351999-12-16 23:11:37 +00001224 {
David Turner8f43c712000-02-02 12:16:19 +00001225 error = TT_Err_Invalid_Glyph_Index;
David Turner90f68b72000-06-23 12:26:14 +00001226 goto Exit;
David Turnerd2b1f351999-12-16 23:11:37 +00001227 }
1228
David Turner861ba622000-02-15 12:54:51 +00001229 loader->glyph_index = glyph_index;
David Turnere49ab252000-05-16 23:44:38 +00001230
Werner Lemberg78575dc2000-06-12 19:36:41 +00001231 if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
David Turnerd2b1f351999-12-16 23:11:37 +00001232 {
David Turner2f0fdb92004-06-21 21:16:56 +00001233 x_scale = ((TT_Size)loader->size)->metrics.x_scale;
1234 y_scale = ((TT_Size)loader->size)->metrics.y_scale;
David Turner8f43c712000-02-02 12:16:19 +00001235 }
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001236 else
1237 {
1238 x_scale = 0x10000L;
1239 y_scale = 0x10000L;
1240 }
David Turnerd2b1f351999-12-16 23:11:37 +00001241
Werner Lemberg422210b2009-11-03 08:11:02 +01001242 tt_get_metrics( loader, glyph_index );
David Turnerd2b1f351999-12-16 23:11:37 +00001243
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001244 /* Set `offset' to the start of the glyph relative to the start of */
Werner Lembergffa033b2005-08-19 08:56:29 +00001245 /* the `glyf' table, and `byte_len' to the length of the glyph in */
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001246 /* bytes. */
1247
Graham Asher13217f22002-07-18 15:59:23 +00001248#ifdef FT_CONFIG_OPTION_INCREMENTAL
David Turnere49ab252000-05-16 23:44:38 +00001249
Werner Lemberg7f74a522002-07-26 09:09:10 +00001250 /* If we are loading glyph data via the incremental interface, set */
1251 /* the loader stream to a memory stream reading the data returned */
1252 /* by the interface. */
Graham Asherce121822002-08-01 15:29:17 +00001253 if ( face->root.internal->incremental_interface )
Graham Asher13217f22002-07-18 15:59:23 +00001254 {
Graham Asherce121822002-08-01 15:29:17 +00001255 error = face->root.internal->incremental_interface->funcs->get_glyph_data(
1256 face->root.internal->incremental_interface->object,
1257 glyph_index, &glyph_data );
Werner Lemberg7f74a522002-07-26 09:09:10 +00001258 if ( error )
Graham Asher13217f22002-07-18 15:59:23 +00001259 goto Exit;
Werner Lemberg7f74a522002-07-26 09:09:10 +00001260
Graham Asherce121822002-08-01 15:29:17 +00001261 glyph_data_loaded = 1;
Werner Lemberg3c403e42002-08-06 21:47:40 +00001262 offset = 0;
Wu, Chia-I (吳佳一)9a2b3b62006-02-14 08:37:03 +00001263 loader->byte_len = glyph_data.length;
Werner Lemberg3c403e42002-08-06 21:47:40 +00001264
Werner Lembergb3d5e9c2002-07-28 05:05:24 +00001265 FT_MEM_ZERO( &inc_stream, sizeof ( inc_stream ) );
Werner Lemberg3c403e42002-08-06 21:47:40 +00001266 FT_Stream_OpenMemory( &inc_stream,
1267 glyph_data.pointer, glyph_data.length );
1268
Graham Asher13217f22002-07-18 15:59:23 +00001269 loader->stream = &inc_stream;
1270 }
1271 else
Werner Lemberg7f74a522002-07-26 09:09:10 +00001272
1273#endif /* FT_CONFIG_OPTION_INCREMENTAL */
Graham Asher13217f22002-07-18 15:59:23 +00001274
Werner Lembergffa033b2005-08-19 08:56:29 +00001275 offset = tt_face_get_location( face, glyph_index,
1276 (FT_UInt*)&loader->byte_len );
David Turnerd2b1f351999-12-16 23:11:37 +00001277
Werner Lembergbf391cb2008-01-10 08:47:08 +00001278 if ( loader->byte_len > 0 )
David Turner8f43c712000-02-02 12:16:19 +00001279 {
Werner Lemberg1474f432008-12-09 06:51:56 +00001280 if ( !loader->glyf_offset )
1281 {
Werner Lemberg858abbe2009-06-26 06:15:41 +02001282 FT_TRACE2(( "no `glyf' table but non-zero `loca' entry\n" ));
Werner Lemberg1474f432008-12-09 06:51:56 +00001283 error = TT_Err_Invalid_Table;
1284 goto Exit;
1285 }
1286
Werner Lembergbf391cb2008-01-10 08:47:08 +00001287 error = face->access_glyph_frame( loader, glyph_index,
1288 loader->glyf_offset + offset,
1289 loader->byte_len );
1290 if ( error )
1291 goto Exit;
1292
1293 opened_frame = 1;
1294
Werner Lembergf186ba62009-11-03 15:46:35 +01001295 /* read glyph header first */
Werner Lembergbf391cb2008-01-10 08:47:08 +00001296 error = face->read_glyph_header( loader );
Werner Lembergf186ba62009-11-03 15:46:35 +01001297 if ( error || header_only )
Werner Lembergbf391cb2008-01-10 08:47:08 +00001298 goto Exit;
1299 }
1300
1301 if ( loader->byte_len == 0 || loader->n_contours == 0 )
1302 {
David Turner8f43c712000-02-02 12:16:19 +00001303 loader->bbox.xMin = 0;
1304 loader->bbox.xMax = 0;
1305 loader->bbox.yMin = 0;
1306 loader->bbox.yMax = 0;
David Turnerd2b1f351999-12-16 23:11:37 +00001307
Werner Lembergf186ba62009-11-03 15:46:35 +01001308 if ( header_only )
1309 goto Exit;
1310
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001311 TT_LOADER_SET_PP( loader );
David Turnerd2b1f351999-12-16 23:11:37 +00001312
Werner Lemberg44bb3032004-04-25 20:15:11 +00001313#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001314
Werner Lemberg44bb3032004-04-25 20:15:11 +00001315 if ( ((TT_Face)(loader->face))->doblend )
1316 {
1317 /* this must be done before scaling */
1318 FT_Memory memory = loader->face->memory;
1319
1320
Werner Lemberg5afaa672004-06-28 14:19:15 +00001321 error = TT_Vary_Get_Glyph_Deltas( (TT_Face)(loader->face),
1322 glyph_index, &deltas, 4 );
David Turnerc28b8c12004-06-24 20:18:24 +00001323 if ( error )
Werner Lemberg44bb3032004-04-25 20:15:11 +00001324 goto Exit;
1325
1326 loader->pp1.x += deltas[0].x; loader->pp1.y += deltas[0].y;
1327 loader->pp2.x += deltas[1].x; loader->pp2.y += deltas[1].y;
1328 loader->pp3.x += deltas[2].x; loader->pp3.y += deltas[2].y;
1329 loader->pp4.x += deltas[3].x; loader->pp4.y += deltas[3].y;
1330
1331 FT_FREE( deltas );
1332 }
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001333
Werner Lemberg44bb3032004-04-25 20:15:11 +00001334#endif
1335
Werner Lemberg78575dc2000-06-12 19:36:41 +00001336 if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
Werner Lemberg8bb07e62004-03-27 08:43:17 +00001337 {
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001338 loader->pp1.x = FT_MulFix( loader->pp1.x, x_scale );
David Turner8f43c712000-02-02 12:16:19 +00001339 loader->pp2.x = FT_MulFix( loader->pp2.x, x_scale );
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001340 loader->pp3.y = FT_MulFix( loader->pp3.y, y_scale );
Werner Lemberg8bb07e62004-03-27 08:43:17 +00001341 loader->pp4.y = FT_MulFix( loader->pp4.y, y_scale );
1342 }
David Turnerd2b1f351999-12-16 23:11:37 +00001343
Werner Lemberg1429db62001-04-02 23:54:01 +00001344 error = TT_Err_Ok;
David Turner90f68b72000-06-23 12:26:14 +00001345 goto Exit;
David Turner8f43c712000-02-02 12:16:19 +00001346 }
David Turnerd2b1f351999-12-16 23:11:37 +00001347
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001348 TT_LOADER_SET_PP( loader );
Werner Lemberg8bb07e62004-03-27 08:43:17 +00001349
Werner Lemberg78575dc2000-06-12 19:36:41 +00001350 /***********************************************************************/
1351 /***********************************************************************/
1352 /***********************************************************************/
David Turnerd2b1f351999-12-16 23:11:37 +00001353
Werner Lemberg78575dc2000-06-12 19:36:41 +00001354 /* if it is a simple glyph, load it */
1355
Werner Lembergbf391cb2008-01-10 08:47:08 +00001356 if ( loader->n_contours > 0 )
David Turner8f43c712000-02-02 12:16:19 +00001357 {
David Turner994d7742000-06-25 04:49:19 +00001358 error = face->read_simple_glyph( loader );
Werner Lemberga929ba92000-06-25 06:47:11 +00001359 if ( error )
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001360 goto Exit;
Werner Lembergbd5ae402000-07-05 04:32:02 +00001361
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001362 /* all data have been read */
1363 face->forget_glyph_frame( loader );
1364 opened_frame = 0;
Werner Lemberg5811c7c2000-07-02 13:53:16 +00001365
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001366 error = TT_Process_Simple_Glyph( loader );
Werner Lembergdcd2e142000-06-25 07:43:15 +00001367 if ( error )
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001368 goto Exit;
David Turnerf0df85b2000-06-22 00:17:42 +00001369
1370 FT_GlyphLoader_Add( gloader );
David Turner8f43c712000-02-02 12:16:19 +00001371 }
David Turner8f43c712000-02-02 12:16:19 +00001372
Werner Lemberg78575dc2000-06-12 19:36:41 +00001373 /***********************************************************************/
1374 /***********************************************************************/
1375 /***********************************************************************/
1376
1377 /* otherwise, load a composite! */
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001378 else if ( loader->n_contours == -1 )
David Turner8f43c712000-02-02 12:16:19 +00001379 {
Werner Lemberg6f99c882007-05-19 07:01:49 +00001380 FT_UInt start_point;
1381 FT_UInt start_contour;
1382 FT_ULong ins_pos; /* position of composite instructions, if any */
Werner Lemberga929ba92000-06-25 06:47:11 +00001383
Werner Lembergbd5ae402000-07-05 04:32:02 +00001384
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001385 start_point = gloader->base.outline.n_points;
1386 start_contour = gloader->base.outline.n_contours;
1387
David Turner8f43c712000-02-02 12:16:19 +00001388 /* for each subglyph, read composite header */
David Turner994d7742000-06-25 04:49:19 +00001389 error = face->read_composite_glyph( loader );
Werner Lemberga929ba92000-06-25 06:47:11 +00001390 if ( error )
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001391 goto Exit;
David Turnered7f62a2000-03-28 11:19:28 +00001392
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001393 /* store the offset of instructions */
David Turnerc6a92202000-07-04 18:12:13 +00001394 ins_pos = loader->ins_pos;
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001395
1396 /* all data we need are read */
David Turner994d7742000-06-25 04:49:19 +00001397 face->forget_glyph_frame( loader );
David Turner90f68b72000-06-23 12:26:14 +00001398 opened_frame = 0;
1399
Werner Lemberg44bb3032004-04-25 20:15:11 +00001400#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
1401
1402 if ( face->doblend )
1403 {
1404 FT_Int i, limit;
1405 FT_SubGlyph subglyph;
1406 FT_Memory memory = face->root.memory;
1407
1408
1409 /* this provides additional offsets */
1410 /* for each component's translation */
1411
Werner Lemberge12ed562007-06-17 05:31:23 +00001412 if ( ( error = TT_Vary_Get_Glyph_Deltas(
1413 face,
1414 glyph_index,
1415 &deltas,
1416 gloader->current.num_subglyphs + 4 )) != 0 )
Werner Lemberg44bb3032004-04-25 20:15:11 +00001417 goto Exit;
1418
Werner Lemberg44bb3032004-04-25 20:15:11 +00001419 subglyph = gloader->current.subglyphs + gloader->base.num_subglyphs;
1420 limit = gloader->current.num_subglyphs;
1421
1422 for ( i = 0; i < limit; ++i, ++subglyph )
1423 {
1424 if ( subglyph->flags & ARGS_ARE_XY_VALUES )
1425 {
suzuki toshiya9206eba2009-08-01 00:32:17 +09001426 /* XXX: overflow check for subglyph->{arg1,arg2}. */
1427 /* deltas[i].{x,y} must be within signed 16-bit, */
1428 /* but the restriction of summed delta is not clear */
1429 subglyph->arg1 += (FT_Int16)deltas[i].x;
1430 subglyph->arg2 += (FT_Int16)deltas[i].y;
Werner Lemberg44bb3032004-04-25 20:15:11 +00001431 }
1432 }
1433
1434 loader->pp1.x += deltas[i + 0].x; loader->pp1.y += deltas[i + 0].y;
1435 loader->pp2.x += deltas[i + 1].x; loader->pp2.y += deltas[i + 1].y;
1436 loader->pp3.x += deltas[i + 2].x; loader->pp3.y += deltas[i + 2].y;
1437 loader->pp4.x += deltas[i + 3].x; loader->pp4.y += deltas[i + 3].y;
1438
1439 FT_FREE( deltas );
1440 }
1441
1442#endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
1443
1444 if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
1445 {
1446 loader->pp1.x = FT_MulFix( loader->pp1.x, x_scale );
1447 loader->pp2.x = FT_MulFix( loader->pp2.x, x_scale );
1448 loader->pp3.y = FT_MulFix( loader->pp3.y, y_scale );
1449 loader->pp4.y = FT_MulFix( loader->pp4.y, y_scale );
1450 }
1451
David Turnered7f62a2000-03-28 11:19:28 +00001452 /* if the flag FT_LOAD_NO_RECURSE is set, we return the subglyph */
Werner Lemberg78575dc2000-06-12 19:36:41 +00001453 /* `as is' in the glyph slot (the client application will be */
Werner Lembergeed446d2002-08-16 12:46:52 +00001454 /* responsible for interpreting these data)... */
David Turnered7f62a2000-03-28 11:19:28 +00001455 if ( loader->load_flags & FT_LOAD_NO_RECURSE )
1456 {
David Turnerf0df85b2000-06-22 00:17:42 +00001457 FT_GlyphLoader_Add( gloader );
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001458 loader->glyph->format = FT_GLYPH_FORMAT_COMPOSITE;
Werner Lembergbd5ae402000-07-05 04:32:02 +00001459
David Turner90f68b72000-06-23 12:26:14 +00001460 goto Exit;
David Turnered7f62a2000-03-28 11:19:28 +00001461 }
1462
David Turner8f43c712000-02-02 12:16:19 +00001463 /*********************************************************************/
Werner Lembergdcd2e142000-06-25 07:43:15 +00001464 /*********************************************************************/
1465 /*********************************************************************/
1466
David Turner8f43c712000-02-02 12:16:19 +00001467 {
Werner Lemberg57a94c42008-05-25 16:49:29 +00001468 FT_UInt n, num_base_points;
1469 FT_SubGlyph subglyph = 0;
Werner Lembergbd5ae402000-07-05 04:32:02 +00001470
Werner Lemberg57a94c42008-05-25 16:49:29 +00001471 FT_UInt num_points = start_point;
1472 FT_UInt num_subglyphs = gloader->current.num_subglyphs;
1473 FT_UInt num_base_subgs = gloader->base.num_subglyphs;
Werner Lembergbd5ae402000-07-05 04:32:02 +00001474
Werner Lemberg57a94c42008-05-25 16:49:29 +00001475 FT_Stream old_stream = loader->stream;
Werner Lemberg6f99c882007-05-19 07:01:49 +00001476
David Turnerc3128612000-06-23 05:02:13 +00001477
David Turnerf0df85b2000-06-22 00:17:42 +00001478 FT_GlyphLoader_Add( gloader );
Werner Lembergbd5ae402000-07-05 04:32:02 +00001479
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001480 /* read each subglyph independently */
Werner Lembergffa033b2005-08-19 08:56:29 +00001481 for ( n = 0; n < num_subglyphs; n++ )
David Turnerd2b1f351999-12-16 23:11:37 +00001482 {
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001483 FT_Vector pp[4];
David Turnere49ab252000-05-16 23:44:38 +00001484
Werner Lembergdcd2e142000-06-25 07:43:15 +00001485
Werner Lemberga929ba92000-06-25 06:47:11 +00001486 /* Each time we call load_truetype_glyph in this loop, the */
1487 /* value of `gloader.base.subglyphs' can change due to table */
1488 /* reallocations. We thus need to recompute the subglyph */
1489 /* pointer on each iteration. */
David Turnerf0df85b2000-06-22 00:17:42 +00001490 subglyph = gloader->base.subglyphs + num_base_subgs + n;
Werner Lemberg78575dc2000-06-12 19:36:41 +00001491
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001492 pp[0] = loader->pp1;
1493 pp[1] = loader->pp2;
1494 pp[2] = loader->pp3;
1495 pp[3] = loader->pp4;
David Turnerd2b1f351999-12-16 23:11:37 +00001496
David Turnerf0df85b2000-06-22 00:17:42 +00001497 num_base_points = gloader->base.outline.n_points;
David Turnere49ab252000-05-16 23:44:38 +00001498
David Turner77b68b82003-01-08 09:59:17 +00001499 error = load_truetype_glyph( loader, subglyph->index,
Werner Lembergf186ba62009-11-03 15:46:35 +01001500 recurse_count + 1, FALSE );
Werner Lemberg78575dc2000-06-12 19:36:41 +00001501 if ( error )
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001502 goto Exit;
David Turner3475e7f2000-05-17 20:56:01 +00001503
David Turner61d6b2b2001-05-16 17:49:07 +00001504 /* restore subglyph pointer */
David Turnerf0df85b2000-06-22 00:17:42 +00001505 subglyph = gloader->base.subglyphs + num_base_subgs + n;
1506
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001507 if ( !( subglyph->flags & USE_MY_METRICS ) )
David Turner7bb7fed2000-02-28 11:23:36 +00001508 {
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001509 loader->pp1 = pp[0];
1510 loader->pp2 = pp[1];
1511 loader->pp3 = pp[2];
1512 loader->pp4 = pp[3];
David Turnerd2b1f351999-12-16 23:11:37 +00001513 }
David Turnere49ab252000-05-16 23:44:38 +00001514
Werner Lembergdcd2e142000-06-25 07:43:15 +00001515 num_points = gloader->base.outline.n_points;
David Turnere49ab252000-05-16 23:44:38 +00001516
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001517 if ( num_points == num_base_points )
1518 continue;
David Turnere49ab252000-05-16 23:44:38 +00001519
Werner Lemberg6f99c882007-05-19 07:01:49 +00001520 /* gloader->base.outline consists of three parts: */
1521 /* 0 -(1)-> start_point -(2)-> num_base_points -(3)-> n_points. */
1522 /* */
1523 /* (1): exists from the beginning */
1524 /* (2): components that have been loaded so far */
1525 /* (3): the newly loaded component */
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001526 TT_Process_Composite_Component( loader, subglyph, start_point,
1527 num_base_points );
David Turnerd2b1f351999-12-16 23:11:37 +00001528 }
David Turnere49ab252000-05-16 23:44:38 +00001529
Werner Lembergf4a52a62007-04-09 08:40:11 +00001530 loader->stream = old_stream;
David Turnerd2b1f351999-12-16 23:11:37 +00001531
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001532 /* process the glyph */
1533 loader->ins_pos = ins_pos;
1534 if ( IS_HINTED( loader->load_flags ) &&
David Turnerd2b1f351999-12-16 23:11:37 +00001535
David Turner6aa260c2006-08-25 22:45:13 +00001536#ifdef TT_USE_BYTECODE_INTERPRETER
Werner Lemberg78575dc2000-06-12 19:36:41 +00001537
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001538 subglyph->flags & WE_HAVE_INSTR &&
David Turnere49ab252000-05-16 23:44:38 +00001539
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001540#endif
Werner Lemberg78575dc2000-06-12 19:36:41 +00001541
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001542 num_points > start_point )
1543 TT_Process_Composite_Glyph( loader, start_point, start_contour );
Werner Lembergdcd2e142000-06-25 07:43:15 +00001544
David Turnerd2b1f351999-12-16 23:11:37 +00001545 }
1546 }
David Turner77b68b82003-01-08 09:59:17 +00001547 else
1548 {
Werner Lemberg6f99c882007-05-19 07:01:49 +00001549 /* invalid composite count (negative but not -1) */
David Turner77b68b82003-01-08 09:59:17 +00001550 error = TT_Err_Invalid_Outline;
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001551 goto Exit;
David Turner77b68b82003-01-08 09:59:17 +00001552 }
David Turnerd2b1f351999-12-16 23:11:37 +00001553
Werner Lemberg78575dc2000-06-12 19:36:41 +00001554 /***********************************************************************/
1555 /***********************************************************************/
1556 /***********************************************************************/
David Turnerd2b1f351999-12-16 23:11:37 +00001557
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001558 Exit:
1559
Werner Lemberga929ba92000-06-25 06:47:11 +00001560 if ( opened_frame )
David Turner994d7742000-06-25 04:49:19 +00001561 face->forget_glyph_frame( loader );
David Turner90f68b72000-06-23 12:26:14 +00001562
Graham Asherce121822002-08-01 15:29:17 +00001563#ifdef FT_CONFIG_OPTION_INCREMENTAL
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001564
Werner Lemberg3c403e42002-08-06 21:47:40 +00001565 if ( glyph_data_loaded )
1566 face->root.internal->incremental_interface->funcs->free_glyph_data(
1567 face->root.internal->incremental_interface->object,
1568 &glyph_data );
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001569
Graham Asherce121822002-08-01 15:29:17 +00001570#endif
1571
David Turnere49ab252000-05-16 23:44:38 +00001572 return error;
David Turner8f43c712000-02-02 12:16:19 +00001573 }
1574
1575
Graham Asher13217f22002-07-18 15:59:23 +00001576 static FT_Error
Werner Lemberg6f99c882007-05-19 07:01:49 +00001577 compute_glyph_metrics( TT_Loader loader,
1578 FT_UInt glyph_index )
David Turner8f43c712000-02-02 12:16:19 +00001579 {
David Turnerf9b8dec2000-06-16 19:34:52 +00001580 FT_BBox bbox;
David Turnerc3128612000-06-23 05:02:13 +00001581 TT_Face face = (TT_Face)loader->face;
Werner Lembergcf24d512001-06-18 14:23:45 +00001582 FT_Fixed y_scale;
David Turner8f43c712000-02-02 12:16:19 +00001583 TT_GlyphSlot glyph = loader->glyph;
David Turnerc3128612000-06-23 05:02:13 +00001584 TT_Size size = (TT_Size)loader->size;
David Turnere49ab252000-05-16 23:44:38 +00001585
Werner Lembergdcd2e142000-06-25 07:43:15 +00001586
Werner Lemberg78575dc2000-06-12 19:36:41 +00001587 y_scale = 0x10000L;
1588 if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
David Turner8f43c712000-02-02 12:16:19 +00001589 y_scale = size->root.metrics.y_scale;
David Turnere49ab252000-05-16 23:44:38 +00001590
David Turnerb08fe2d2002-08-27 20:20:29 +00001591 if ( glyph->format != FT_GLYPH_FORMAT_COMPOSITE )
David Turnered7f62a2000-03-28 11:19:28 +00001592 FT_Outline_Get_CBox( &glyph->outline, &bbox );
David Turnered7f62a2000-03-28 11:19:28 +00001593 else
1594 bbox = loader->bbox;
David Turnerd2b1f351999-12-16 23:11:37 +00001595
Werner Lemberg6f99c882007-05-19 07:01:49 +00001596 /* get the device-independent horizontal advance; it is scaled later */
1597 /* by the base layer. */
David Turnerd2b1f351999-12-16 23:11:37 +00001598 {
David Turner57d4de02001-06-08 13:29:36 +00001599 FT_Pos advance = loader->linear;
David Turnerd2b1f351999-12-16 23:11:37 +00001600
Werner Lemberga929ba92000-06-25 06:47:11 +00001601
Werner Lemberg5811c7c2000-07-02 13:53:16 +00001602 /* the flag FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH was introduced to */
1603 /* correctly support DynaLab fonts, which have an incorrect */
1604 /* `advance_Width_Max' field! It is used, to my knowledge, */
1605 /* exclusively in the X-TrueType font server. */
1606 /* */
Werner Lemberg91db04c2002-04-01 14:25:28 +00001607 if ( face->postscript.isFixedPitch &&
Werner Lemberg78575dc2000-06-12 19:36:41 +00001608 ( loader->load_flags & FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ) == 0 )
David Turnerd2b1f351999-12-16 23:11:37 +00001609 advance = face->horizontal.advance_Width_Max;
1610
David Turnerf0df85b2000-06-22 00:17:42 +00001611 /* we need to return the advance in font units in linearHoriAdvance, */
Werner Lemberga929ba92000-06-25 06:47:11 +00001612 /* it will be scaled later by the base layer. */
David Turnerf0df85b2000-06-22 00:17:42 +00001613 glyph->linearHoriAdvance = advance;
David Turnerd2b1f351999-12-16 23:11:37 +00001614 }
1615
1616 glyph->metrics.horiBearingX = bbox.xMin;
1617 glyph->metrics.horiBearingY = bbox.yMax;
David Turner8f43c712000-02-02 12:16:19 +00001618 glyph->metrics.horiAdvance = loader->pp2.x - loader->pp1.x;
David Turnerd2b1f351999-12-16 23:11:37 +00001619
Bram Tassyns4694ea22009-09-02 13:06:33 +02001620 /* adjust advance width to the value contained in the hdmx table */
1621 if ( !face->postscript.isFixedPitch &&
1622 IS_HINTED( loader->load_flags ) )
1623 {
1624 FT_Byte* widthp;
David Turnerd2b1f351999-12-16 23:11:37 +00001625
Bram Tassyns4694ea22009-09-02 13:06:33 +02001626
1627 widthp = tt_face_get_device_metrics( face,
1628 size->root.metrics.x_ppem,
1629 glyph_index );
1630
1631 if ( widthp )
1632 glyph->metrics.horiAdvance = *widthp << 6;
1633 }
1634
1635 /* set glyph dimensions */
1636 glyph->metrics.width = bbox.xMax - bbox.xMin;
1637 glyph->metrics.height = bbox.yMax - bbox.yMin;
1638
1639 /* Now take care of vertical metrics. In the case where there is */
1640 /* no vertical information within the font (relatively common), */
1641 /* create some metrics manually */
David Turnerd2b1f351999-12-16 23:11:37 +00001642 {
Werner Lemberg1723dcc2006-01-15 07:30:32 +00001643 FT_Pos top; /* scaled vertical top side bearing */
1644 FT_Pos advance; /* scaled vertical advance height */
David Turnerd2b1f351999-12-16 23:11:37 +00001645
Werner Lemberg56a4d872004-06-03 07:56:21 +00001646
Graham Asher13217f22002-07-18 15:59:23 +00001647 /* Get the unscaled top bearing and advance height. */
Werner Lembergd30062d2009-09-08 07:06:54 +02001648 if ( face->vertical_info &&
David Turnerd2b1f351999-12-16 23:11:37 +00001649 face->vertical.number_Of_VMetrics > 0 )
1650 {
Wu, Chia-I (吳佳一)212aee02006-01-15 06:24:53 +00001651 top = (FT_Short)FT_DivFix( loader->pp3.y - bbox.yMax,
1652 y_scale );
Werner Lemberg49f4d342005-06-16 19:07:08 +00001653
1654 if ( loader->pp3.y <= loader->pp4.y )
Wu, Chia-I (吳佳一)212aee02006-01-15 06:24:53 +00001655 advance = 0;
Werner Lemberg49f4d342005-06-16 19:07:08 +00001656 else
Wu, Chia-I (吳佳一)212aee02006-01-15 06:24:53 +00001657 advance = (FT_UShort)FT_DivFix( loader->pp3.y - loader->pp4.y,
1658 y_scale );
David Turnerd2b1f351999-12-16 23:11:37 +00001659 }
1660 else
1661 {
Wu, Chia-I (吳佳一)212aee02006-01-15 06:24:53 +00001662 FT_Pos height;
Werner Lemberg49f4d342005-06-16 19:07:08 +00001663
1664
1665 /* XXX Compute top side bearing and advance height in */
1666 /* Get_VMetrics instead of here. */
David Turnerd2b1f351999-12-16 23:11:37 +00001667
Werner Lemberg78575dc2000-06-12 19:36:41 +00001668 /* NOTE: The OS/2 values are the only `portable' ones, */
1669 /* which is why we use them, if there is an OS/2 */
1670 /* table in the font. Otherwise, we use the */
1671 /* values defined in the horizontal header. */
Werner Lemberg49f4d342005-06-16 19:07:08 +00001672
Wu, Chia-I (吳佳一)212aee02006-01-15 06:24:53 +00001673 height = (FT_Short)FT_DivFix( bbox.yMax - bbox.yMin,
1674 y_scale );
Werner Lemberg91db04c2002-04-01 14:25:28 +00001675 if ( face->os2.version != 0xFFFFU )
Wu, Chia-I (吳佳一)212aee02006-01-15 06:24:53 +00001676 advance = (FT_Pos)( face->os2.sTypoAscender -
1677 face->os2.sTypoDescender );
David Turnerd2b1f351999-12-16 23:11:37 +00001678 else
Wu, Chia-I (吳佳一)212aee02006-01-15 06:24:53 +00001679 advance = (FT_Pos)( face->horizontal.Ascender -
1680 face->horizontal.Descender );
Werner Lemberg49f4d342005-06-16 19:07:08 +00001681
Wu, Chia-I (吳佳一)212aee02006-01-15 06:24:53 +00001682 top = ( advance - height ) / 2;
David Turnerd2b1f351999-12-16 23:11:37 +00001683 }
1684
Graham Asher46960df2003-02-13 17:49:27 +00001685#ifdef FT_CONFIG_OPTION_INCREMENTAL
Graham Asher46960df2003-02-13 17:49:27 +00001686 {
Wu, Chia-I (吳佳一)212aee02006-01-15 06:24:53 +00001687 FT_Incremental_InterfaceRec* incr;
1688 FT_Incremental_MetricsRec metrics;
1689 FT_Error error;
Graham Asher46960df2003-02-13 17:49:27 +00001690
Werner Lembergb442ca12003-04-23 15:50:27 +00001691
Wu, Chia-I (吳佳一)212aee02006-01-15 06:24:53 +00001692 incr = face->root.internal->incremental_interface;
Graham Asher46960df2003-02-13 17:49:27 +00001693
Wu, Chia-I (吳佳一)212aee02006-01-15 06:24:53 +00001694 /* If this is an incrementally loaded font see if there are */
1695 /* overriding metrics for this glyph. */
1696 if ( incr && incr->funcs->get_glyph_metrics )
1697 {
1698 metrics.bearing_x = 0;
1699 metrics.bearing_y = top;
1700 metrics.advance = advance;
Werner Lemberg1723dcc2006-01-15 07:30:32 +00001701
Wu, Chia-I (吳佳一)212aee02006-01-15 06:24:53 +00001702 error = incr->funcs->get_glyph_metrics( incr->object,
1703 glyph_index,
1704 TRUE,
1705 &metrics );
1706 if ( error )
1707 return error;
Graham Asher46960df2003-02-13 17:49:27 +00001708
Wu, Chia-I (吳佳一)212aee02006-01-15 06:24:53 +00001709 top = metrics.bearing_y;
1710 advance = metrics.advance;
1711 }
Graham Asher46960df2003-02-13 17:49:27 +00001712 }
1713
Werner Lemberg8bb07e62004-03-27 08:43:17 +00001714 /* GWW: Do vertical metrics get loaded incrementally too? */
1715
Graham Asher46960df2003-02-13 17:49:27 +00001716#endif /* FT_CONFIG_OPTION_INCREMENTAL */
1717
Wu, Chia-I (吳佳一)212aee02006-01-15 06:24:53 +00001718 glyph->linearVertAdvance = advance;
1719
David Turnerd2b1f351999-12-16 23:11:37 +00001720 /* scale the metrics */
Werner Lemberg78575dc2000-06-12 19:36:41 +00001721 if ( !( loader->load_flags & FT_LOAD_NO_SCALE ) )
David Turnerd2b1f351999-12-16 23:11:37 +00001722 {
Werner Lembergf186ba62009-11-03 15:46:35 +01001723 top = FT_MulFix( top, y_scale );
Wu, Chia-I (吳佳一)212aee02006-01-15 06:24:53 +00001724 advance = FT_MulFix( advance, y_scale );
David Turnerd2b1f351999-12-16 23:11:37 +00001725 }
David Turnerd2b1f351999-12-16 23:11:37 +00001726
Werner Lemberga929ba92000-06-25 06:47:11 +00001727 /* XXX: for now, we have no better algorithm for the lsb, but it */
1728 /* should work fine. */
1729 /* */
Bram Tassyns4694ea22009-09-02 13:06:33 +02001730 glyph->metrics.vertBearingX = glyph->metrics.horiBearingX -
1731 glyph->metrics.horiAdvance / 2;
David Turnerd2b1f351999-12-16 23:11:37 +00001732 glyph->metrics.vertBearingY = top;
1733 glyph->metrics.vertAdvance = advance;
1734 }
1735
Graham Asher13217f22002-07-18 15:59:23 +00001736 return 0;
David Turner8f43c712000-02-02 12:16:19 +00001737 }
David Turnerd2b1f351999-12-16 23:11:37 +00001738
David Turnerd2b1f351999-12-16 23:11:37 +00001739
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001740#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
Werner Lembergffa033b2005-08-19 08:56:29 +00001741
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001742 static FT_Error
1743 load_sbit_image( TT_Size size,
1744 TT_GlyphSlot glyph,
1745 FT_UInt glyph_index,
1746 FT_Int32 load_flags )
1747 {
1748 TT_Face face;
1749 SFNT_Service sfnt;
1750 FT_Stream stream;
1751 FT_Error error;
1752 TT_SBit_MetricsRec metrics;
1753
Werner Lembergffa033b2005-08-19 08:56:29 +00001754
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001755 face = (TT_Face)glyph->face;
1756 sfnt = (SFNT_Service)face->sfnt;
1757 stream = face->root.stream;
1758
1759 error = sfnt->load_sbit_image( face,
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00001760 size->strike_index,
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001761 glyph_index,
1762 (FT_Int)load_flags,
1763 stream,
1764 &glyph->bitmap,
1765 &metrics );
1766 if ( !error )
1767 {
1768 glyph->outline.n_points = 0;
1769 glyph->outline.n_contours = 0;
1770
1771 glyph->metrics.width = (FT_Pos)metrics.width << 6;
1772 glyph->metrics.height = (FT_Pos)metrics.height << 6;
1773
1774 glyph->metrics.horiBearingX = (FT_Pos)metrics.horiBearingX << 6;
1775 glyph->metrics.horiBearingY = (FT_Pos)metrics.horiBearingY << 6;
1776 glyph->metrics.horiAdvance = (FT_Pos)metrics.horiAdvance << 6;
1777
1778 glyph->metrics.vertBearingX = (FT_Pos)metrics.vertBearingX << 6;
1779 glyph->metrics.vertBearingY = (FT_Pos)metrics.vertBearingY << 6;
1780 glyph->metrics.vertAdvance = (FT_Pos)metrics.vertAdvance << 6;
1781
1782 glyph->format = FT_GLYPH_FORMAT_BITMAP;
Werner Lembergf186ba62009-11-03 15:46:35 +01001783
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001784 if ( load_flags & FT_LOAD_VERTICAL_LAYOUT )
1785 {
1786 glyph->bitmap_left = metrics.vertBearingX;
1787 glyph->bitmap_top = metrics.vertBearingY;
1788 }
1789 else
1790 {
1791 glyph->bitmap_left = metrics.horiBearingX;
1792 glyph->bitmap_top = metrics.horiBearingY;
1793 }
1794 }
1795
1796 return error;
1797 }
Werner Lembergffa033b2005-08-19 08:56:29 +00001798
1799#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001800
1801
1802 static FT_Error
1803 tt_loader_init( TT_Loader loader,
1804 TT_Size size,
1805 TT_GlyphSlot glyph,
Werner Lembergf186ba62009-11-03 15:46:35 +01001806 FT_Int32 load_flags,
1807 FT_Bool glyf_table_only )
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001808 {
Werner Lembergffa033b2005-08-19 08:56:29 +00001809 TT_Face face;
1810 FT_Stream stream;
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001811
1812
Werner Lembergffa033b2005-08-19 08:56:29 +00001813 face = (TT_Face)glyph->face;
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001814 stream = face->root.stream;
1815
1816 FT_MEM_ZERO( loader, sizeof ( TT_LoaderRec ) );
1817
David Turner6aa260c2006-08-25 22:45:13 +00001818#ifdef TT_USE_BYTECODE_INTERPRETER
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001819
1820 /* load execution context */
Werner Lembergf186ba62009-11-03 15:46:35 +01001821 if ( IS_HINTED( load_flags ) && !glyf_table_only )
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001822 {
1823 TT_ExecContext exec;
Werner Lemberg91959bf2006-11-22 10:36:55 +00001824 FT_Bool grayscale;
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001825
1826
David Turner384be232007-01-05 15:32:01 +00001827 if ( !size->cvt_ready )
1828 {
1829 FT_Error error = tt_size_ready_bytecode( size );
1830 if ( error )
1831 return error;
1832 }
1833
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001834 /* query new execution context */
1835 exec = size->debug ? size->context
1836 : ( (TT_Driver)FT_FACE_DRIVER( face ) )->context;
1837 if ( !exec )
1838 return TT_Err_Could_Not_Find_Context;
1839
Werner Lemberg91959bf2006-11-22 10:36:55 +00001840 grayscale =
1841 FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) != FT_RENDER_MODE_MONO );
1842
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001843 TT_Load_Context( exec, face, size );
1844
Werner Lemberg91959bf2006-11-22 10:36:55 +00001845 /* a change from mono to grayscale rendering (and vice versa) */
1846 /* requires a re-execution of the CVT program */
1847 if ( grayscale != exec->grayscale )
1848 {
1849 FT_UInt i;
1850
1851
1852 exec->grayscale = grayscale;
1853
1854 for ( i = 0; i < size->cvt_size; i++ )
1855 size->cvt[i] = FT_MulFix( face->cvt[i], size->ttmetrics.scale );
1856 tt_size_run_prep( size );
1857 }
1858
Werner Lemberg6f99c882007-05-19 07:01:49 +00001859 /* see whether the cvt program has disabled hinting */
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001860 if ( exec->GS.instruct_control & 1 )
1861 load_flags |= FT_LOAD_NO_HINTING;
1862
Werner Lemberg6f99c882007-05-19 07:01:49 +00001863 /* load default graphics state -- if needed */
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001864 if ( exec->GS.instruct_control & 2 )
1865 exec->GS = tt_default_graphics_state;
1866
1867 exec->pedantic_hinting = FT_BOOL( load_flags & FT_LOAD_PEDANTIC );
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001868 loader->exec = exec;
1869 loader->instructions = exec->glyphIns;
1870 }
1871
David Turner6aa260c2006-08-25 22:45:13 +00001872#endif /* TT_USE_BYTECODE_INTERPRETER */
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001873
Werner Lemberg6f99c882007-05-19 07:01:49 +00001874 /* seek to the beginning of the glyph table -- for Type 42 fonts */
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001875 /* the table might be accessed from a Postscript stream or something */
1876 /* else... */
1877
1878#ifdef FT_CONFIG_OPTION_INCREMENTAL
1879
1880 if ( face->root.internal->incremental_interface )
1881 loader->glyf_offset = 0;
1882 else
1883
1884#endif
1885
1886 {
1887 FT_Error error = face->goto_table( face, TTAG_glyf, stream, 0 );
Werner Lembergffa033b2005-08-19 08:56:29 +00001888
1889
Werner Lemberg1474f432008-12-09 06:51:56 +00001890 if ( error == TT_Err_Table_Missing )
1891 loader->glyf_offset = 0;
1892 else if ( error )
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001893 {
Werner Lemberg858abbe2009-06-26 06:15:41 +02001894 FT_ERROR(( "tt_loader_init: could not access glyph table\n" ));
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001895 return error;
1896 }
Werner Lemberg1474f432008-12-09 06:51:56 +00001897 else
1898 loader->glyf_offset = FT_STREAM_POS();
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001899 }
1900
1901 /* get face's glyph loader */
Werner Lembergf186ba62009-11-03 15:46:35 +01001902 if ( !glyf_table_only )
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001903 {
1904 FT_GlyphLoader gloader = glyph->internal->loader;
1905
Werner Lembergffa033b2005-08-19 08:56:29 +00001906
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001907 FT_GlyphLoader_Rewind( gloader );
1908 loader->gloader = gloader;
1909 }
1910
Werner Lemberg1474f432008-12-09 06:51:56 +00001911 loader->load_flags = load_flags;
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001912
1913 loader->face = (FT_Face)face;
1914 loader->size = (FT_Size)size;
1915 loader->glyph = (FT_GlyphSlot)glyph;
1916 loader->stream = stream;
1917
1918 return TT_Err_Ok;
1919 }
1920
1921
Werner Lemberg78575dc2000-06-12 19:36:41 +00001922 /*************************************************************************/
1923 /* */
1924 /* <Function> */
1925 /* TT_Load_Glyph */
1926 /* */
1927 /* <Description> */
1928 /* A function used to load a single glyph within a given glyph slot, */
1929 /* for a given size. */
1930 /* */
1931 /* <Input> */
1932 /* glyph :: A handle to a target slot object where the glyph */
1933 /* will be loaded. */
1934 /* */
1935 /* size :: A handle to the source face size at which the glyph */
1936 /* must be scaled/loaded. */
1937 /* */
1938 /* glyph_index :: The index of the glyph in the font file. */
1939 /* */
1940 /* load_flags :: A flag indicating what to load for this glyph. The */
1941 /* FT_LOAD_XXX constants can be used to control the */
1942 /* glyph loading process (e.g., whether the outline */
1943 /* should be scaled, whether to load bitmaps or not, */
1944 /* whether to hint the outline, etc). */
1945 /* */
1946 /* <Return> */
Werner Lemberga929ba92000-06-25 06:47:11 +00001947 /* FreeType error code. 0 means success. */
Werner Lemberg78575dc2000-06-12 19:36:41 +00001948 /* */
David Turnerbc82f1b2002-03-01 02:26:22 +00001949 FT_LOCAL_DEF( FT_Error )
Werner Lemberg4a2305c2001-06-28 07:17:51 +00001950 TT_Load_Glyph( TT_Size size,
1951 TT_GlyphSlot glyph,
Werner Lembergc3dc56b2004-04-19 06:13:50 +00001952 FT_UInt glyph_index,
Werner Lemberge59dc912002-09-21 18:43:10 +00001953 FT_Int32 load_flags )
David Turner8f43c712000-02-02 12:16:19 +00001954 {
Werner Lemberg91db04c2002-04-01 14:25:28 +00001955 TT_Face face;
Werner Lemberg91db04c2002-04-01 14:25:28 +00001956 FT_Error error;
1957 TT_LoaderRec loader;
David Turnere49ab252000-05-16 23:44:38 +00001958
Werner Lemberg78575dc2000-06-12 19:36:41 +00001959
David Turner8f43c712000-02-02 12:16:19 +00001960 face = (TT_Face)glyph->face;
Werner Lemberg3ab770b2005-03-08 20:24:56 +00001961 error = TT_Err_Ok;
David Turnered7f62a2000-03-28 11:19:28 +00001962
David Turner8f43c712000-02-02 12:16:19 +00001963#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
Werner Lemberg4b680072000-11-07 06:30:29 +00001964
1965 /* try to load embedded bitmap if any */
1966 /* */
1967 /* XXX: The convention should be emphasized in */
1968 /* the documents because it can be confusing. */
Werner Lembergf1c2b912006-01-13 14:53:28 +00001969 if ( size->strike_index != 0xFFFFFFFFUL &&
David Turnerf96594f2000-11-06 23:07:51 +00001970 ( load_flags & FT_LOAD_NO_BITMAP ) == 0 )
David Turner8f43c712000-02-02 12:16:19 +00001971 {
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001972 error = load_sbit_image( size, glyph, glyph_index, load_flags );
David Turner8f43c712000-02-02 12:16:19 +00001973 if ( !error )
Werner Lembergf186ba62009-11-03 15:46:35 +01001974 {
1975 FT_Face root = &face->root;
1976
1977
1978 if ( FT_IS_SCALABLE( root ) )
1979 {
1980 /* for the bbox we need the header only */
1981 (void)tt_loader_init( &loader, size, glyph, load_flags, TRUE );
1982 (void)load_truetype_glyph( &loader, glyph_index, 0, TRUE );
1983 glyph->linearHoriAdvance = loader.linear;
1984 glyph->linearVertAdvance = loader.top_bearing + loader.bbox.yMax -
1985 loader.vadvance;
1986 if ( face->postscript.isFixedPitch &&
1987 ( load_flags & FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ) == 0 )
1988 glyph->linearHoriAdvance = face->horizontal.advance_Width_Max;
1989 }
1990
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001991 return TT_Err_Ok;
Werner Lembergf186ba62009-11-03 15:46:35 +01001992 }
David Turner8f43c712000-02-02 12:16:19 +00001993 }
Werner Lemberg78575dc2000-06-12 19:36:41 +00001994
David Turner8f43c712000-02-02 12:16:19 +00001995#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
1996
Werner Lemberg560d5fe2005-10-21 09:08:28 +00001997 /* if FT_LOAD_NO_SCALE is not set, `ttmetrics' must be valid */
Wu, Chia-I (吳佳一)2293bb12005-10-19 08:07:38 +00001998 if ( !( load_flags & FT_LOAD_NO_SCALE ) && !size->ttmetrics.valid )
Wu, Chia-I (吳佳一)15c1f5d2005-08-20 08:17:44 +00001999 return TT_Err_Invalid_Size_Handle;
2000
David Turner4937a3e2001-12-19 21:09:16 +00002001 if ( load_flags & FT_LOAD_SBITS_ONLY )
Werner Lemberg779afe42003-06-22 15:33:53 +00002002 return TT_Err_Invalid_Argument;
David Turner4937a3e2001-12-19 21:09:16 +00002003
Werner Lembergf186ba62009-11-03 15:46:35 +01002004 error = tt_loader_init( &loader, size, glyph, load_flags, FALSE );
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00002005 if ( error )
2006 return error;
Werner Lemberg7f74a522002-07-26 09:09:10 +00002007
David Turnerb08fe2d2002-08-27 20:20:29 +00002008 glyph->format = FT_GLYPH_FORMAT_OUTLINE;
Werner Lemberg78575dc2000-06-12 19:36:41 +00002009 glyph->num_subglyphs = 0;
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00002010 glyph->outline.flags = 0;
Werner Lemberg91db04c2002-04-01 14:25:28 +00002011
Werner Lemberg6f99c882007-05-19 07:01:49 +00002012 /* main loading loop */
Werner Lembergf186ba62009-11-03 15:46:35 +01002013 error = load_truetype_glyph( &loader, glyph_index, 0, FALSE );
Werner Lemberg78575dc2000-06-12 19:36:41 +00002014 if ( !error )
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00002015 {
2016 if ( glyph->format == FT_GLYPH_FORMAT_COMPOSITE )
2017 {
2018 glyph->num_subglyphs = loader.gloader->base.num_subglyphs;
2019 glyph->subglyphs = loader.gloader->base.subglyphs;
2020 }
2021 else
2022 {
Werner Lembergffa033b2005-08-19 08:56:29 +00002023 glyph->outline = loader.gloader->base.outline;
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00002024 glyph->outline.flags &= ~FT_OUTLINE_SINGLE_PASS;
2025
Werner Lemberg2752bd12005-08-22 07:11:31 +00002026 /* In case bit 1 of the `flags' field in the `head' table isn't */
2027 /* set, translate array so that (0,0) is the glyph's origin. */
2028 if ( ( face->header.Flags & 2 ) == 0 && loader.pp1.x )
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00002029 FT_Outline_Translate( &glyph->outline, -loader.pp1.x, 0 );
2030 }
2031
Werner Lemberg5df5dbb2008-06-22 13:40:08 +00002032#ifdef TT_USE_BYTECODE_INTERPRETER
2033
Werner Lemberg745a4f42008-06-22 22:41:24 +00002034 if ( IS_HINTED( load_flags ) )
Werner Lemberg5df5dbb2008-06-22 13:40:08 +00002035 {
Werner Lemberg745a4f42008-06-22 22:41:24 +00002036 if ( loader.exec->GS.scan_control )
Werner Lemberg5df5dbb2008-06-22 13:40:08 +00002037 {
Werner Lemberg745a4f42008-06-22 22:41:24 +00002038 /* convert scan conversion mode to FT_OUTLINE_XXX flags */
2039 switch ( loader.exec->GS.scan_type )
2040 {
2041 case 0: /* simple drop-outs including stubs */
2042 glyph->outline.flags |= FT_OUTLINE_INCLUDE_STUBS;
2043 break;
2044 case 1: /* simple drop-outs excluding stubs */
2045 /* nothing; it's the default rendering mode */
2046 break;
2047 case 4: /* smart drop-outs including stubs */
2048 glyph->outline.flags |= FT_OUTLINE_SMART_DROPOUTS |
2049 FT_OUTLINE_INCLUDE_STUBS;
2050 break;
2051 case 5: /* smart drop-outs excluding stubs */
2052 glyph->outline.flags |= FT_OUTLINE_SMART_DROPOUTS;
2053 break;
Werner Lemberg5df5dbb2008-06-22 13:40:08 +00002054
Werner Lemberg745a4f42008-06-22 22:41:24 +00002055 default: /* no drop-out control */
2056 glyph->outline.flags |= FT_OUTLINE_IGNORE_DROPOUTS;
2057 break;
2058 }
Werner Lemberg5df5dbb2008-06-22 13:40:08 +00002059 }
Bram Tassyns4694ea22009-09-02 13:06:33 +02002060 else
Werner Lemberg745a4f42008-06-22 22:41:24 +00002061 glyph->outline.flags |= FT_OUTLINE_IGNORE_DROPOUTS;
Werner Lemberg5df5dbb2008-06-22 13:40:08 +00002062 }
Werner Lemberg5df5dbb2008-06-22 13:40:08 +00002063
2064#endif /* TT_USE_BYTECODE_INTERPRETER */
2065
David Turner8f43c712000-02-02 12:16:19 +00002066 compute_glyph_metrics( &loader, glyph_index );
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00002067 }
David Turnerd2b1f351999-12-16 23:11:37 +00002068
Werner Lemberg26aca022002-05-05 07:40:16 +00002069 /* Set the `high precision' bit flag. */
2070 /* This is _critical_ to get correct output for monochrome */
2071 /* TrueType glyphs at all sizes using the bytecode interpreter. */
2072 /* */
Werner Lemberg560d5fe2005-10-21 09:08:28 +00002073 if ( !( load_flags & FT_LOAD_NO_SCALE ) &&
2074 size->root.metrics.y_ppem < 24 )
David Turnerb08fe2d2002-08-27 20:20:29 +00002075 glyph->outline.flags |= FT_OUTLINE_HIGH_PRECISION;
David Turner8cd89072002-05-04 18:02:59 +00002076
David Turnerd2b1f351999-12-16 23:11:37 +00002077 return error;
2078 }
2079
2080
David Turnerd2b1f351999-12-16 23:11:37 +00002081/* END */