blob: f35521e17b5f763b60de968211e74bad99359964 [file] [log] [blame]
David Turnerd2b1f351999-12-16 23:11:37 +00001/***************************************************************************/
2/* */
3/* ttgload.c */
4/* */
5/* TrueType Glyph Loader (body). */
6/* */
Werner Lemberg91a97162011-01-30 20:12:54 +01007/* Copyright 1996-2011 */
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 /* */
Werner Lemberg6e3fee02011-03-21 09:28:52 +010049 /* Composite glyph flags. */
David Turnerd2b1f351999-12-16 23:11:37 +000050 /* */
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 /* */
Behdad Esfahbod8c82ec52011-04-21 08:21:37 +020068 /* Return the horizontal metrics in font units for a given glyph. */
David Turnerd2b1f351999-12-16 23:11:37 +000069 /* */
Werner Lembergac0d52d2009-11-02 08:35:24 +010070 FT_LOCAL_DEF( void )
David Turner28534d62008-09-01 21:35:21 +000071 TT_Get_HMetrics( TT_Face face,
72 FT_UInt idx,
David Turner28534d62008-09-01 21:35:21 +000073 FT_Short* lsb,
74 FT_UShort* aw )
David Turnerd2b1f351999-12-16 23:11:37 +000075 {
Wu, Chia-I (吳佳一)f5aa47b2006-02-14 06:40:10 +000076 ( (SFNT_Service)face->sfnt )->get_metrics( face, 0, idx, lsb, aw );
David Turnerd2b1f351999-12-16 23:11:37 +000077
Werner Lembergc4b22142009-11-15 10:10:00 +010078 FT_TRACE5(( " advance width (font units): %d\n", *aw ));
79 FT_TRACE5(( " left side bearing (font units): %d\n", *lsb ));
David Turnerd2b1f351999-12-16 23:11:37 +000080 }
81
82
83 /*************************************************************************/
Werner Lemberg78575dc2000-06-12 19:36:41 +000084 /* */
Behdad Esfahbod8c82ec52011-04-21 08:21:37 +020085 /* Return the vertical metrics in font units for a given glyph. */
Werner Lemberg8bb07e62004-03-27 08:43:17 +000086 /* Greg Hitchcock from Microsoft told us that if there were no `vmtx' */
87 /* table, typoAscender/Descender from the `OS/2' table would be used */
88 /* instead, and if there were no `OS/2' table, use ascender/descender */
89 /* from the `hhea' table. But that is not what Microsoft's rasterizer */
90 /* apparently does: It uses the ppem value as the advance height, and */
91 /* sets the top side bearing to be zero. */
92 /* */
Werner Lembergac0d52d2009-11-02 08:35:24 +010093 FT_LOCAL_DEF( void )
David Turner28534d62008-09-01 21:35:21 +000094 TT_Get_VMetrics( TT_Face face,
95 FT_UInt idx,
David Turner28534d62008-09-01 21:35:21 +000096 FT_Short* tsb,
97 FT_UShort* ah )
Werner Lemberg8bb07e62004-03-27 08:43:17 +000098 {
Werner Lemberg8bb07e62004-03-27 08:43:17 +000099 if ( face->vertical_info )
Wu, Chia-I (吳佳一)f5aa47b2006-02-14 06:40:10 +0000100 ( (SFNT_Service)face->sfnt )->get_metrics( face, 1, idx, tsb, ah );
Werner Lemberg8bb07e62004-03-27 08:43:17 +0000101
Werner Lemberg4b2e83d2007-02-01 07:58:02 +0000102#if 1 /* Empirically determined, at variance with what MS said */
Werner Lemberg8bb07e62004-03-27 08:43:17 +0000103
104 else
105 {
106 *tsb = 0;
107 *ah = face->root.units_per_EM;
108 }
109
110#else /* This is what MS said to do. It isn't what they do, however. */
111
112 else if ( face->os2.version != 0xFFFFU )
113 {
114 *tsb = face->os2.sTypoAscender;
115 *ah = face->os2.sTypoAscender - face->os2.sTypoDescender;
116 }
David Turner2f0fdb92004-06-21 21:16:56 +0000117 else
Werner Lemberg8bb07e62004-03-27 08:43:17 +0000118 {
119 *tsb = face->horizontal.Ascender;
120 *ah = face->horizontal.Ascender - face->horizontal.Descender;
121 }
122
123#endif
124
Werner Lembergc4b22142009-11-15 10:10:00 +0100125 FT_TRACE5(( " advance height (font units): %d\n", *ah ));
126 FT_TRACE5(( " top side bearing (font units): %d\n", *tsb ));
Werner Lemberg8bb07e62004-03-27 08:43:17 +0000127 }
128
129
Werner Lemberg422210b2009-11-03 08:11:02 +0100130 static void
131 tt_get_metrics( TT_Loader loader,
132 FT_UInt glyph_index )
133 {
134 TT_Face face = (TT_Face)loader->face;
135
136 FT_Short left_bearing = 0, top_bearing = 0;
137 FT_UShort advance_width = 0, advance_height = 0;
138
139
140 TT_Get_HMetrics( face, glyph_index,
Werner Lemberg422210b2009-11-03 08:11:02 +0100141 &left_bearing,
142 &advance_width );
143 TT_Get_VMetrics( face, glyph_index,
Werner Lemberg422210b2009-11-03 08:11:02 +0100144 &top_bearing,
145 &advance_height );
146
Chris Liddell10cf3882010-02-18 17:09:30 +0100147 loader->left_bearing = left_bearing;
148 loader->advance = advance_width;
149 loader->top_bearing = top_bearing;
150 loader->vadvance = advance_height;
151
152 if ( !loader->linear_def )
153 {
154 loader->linear_def = 1;
155 loader->linear = advance_width;
156 }
157 }
158
159
Werner Lemberg422210b2009-11-03 08:11:02 +0100160#ifdef FT_CONFIG_OPTION_INCREMENTAL
161
Chris Liddell10cf3882010-02-18 17:09:30 +0100162 static void
163 tt_get_metrics_incr_overrides( TT_Loader loader,
164 FT_UInt glyph_index )
165 {
166 TT_Face face = (TT_Face)loader->face;
167
168 FT_Short left_bearing = 0, top_bearing = 0;
169 FT_UShort advance_width = 0, advance_height = 0;
170
171
Ken Sharp980b76e2010-02-10 07:02:43 +0100172 /* If this is an incrementally loaded font check whether there are */
173 /* overriding metrics for this glyph. */
174 if ( face->root.internal->incremental_interface &&
Werner Lemberg422210b2009-11-03 08:11:02 +0100175 face->root.internal->incremental_interface->funcs->get_glyph_metrics )
176 {
177 FT_Incremental_MetricsRec metrics;
178 FT_Error error;
179
180
Chris Liddell10cf3882010-02-18 17:09:30 +0100181 metrics.bearing_x = loader->left_bearing;
Werner Lemberg422210b2009-11-03 08:11:02 +0100182 metrics.bearing_y = 0;
Chris Liddell10cf3882010-02-18 17:09:30 +0100183 metrics.advance = loader->advance;
Ken Sharp980b76e2010-02-10 07:02:43 +0100184 metrics.advance_v = 0;
Werner Lemberg422210b2009-11-03 08:11:02 +0100185
186 error = face->root.internal->incremental_interface->funcs->get_glyph_metrics(
187 face->root.internal->incremental_interface->object,
188 glyph_index, FALSE, &metrics );
189 if ( error )
190 goto Exit;
191
192 left_bearing = (FT_Short)metrics.bearing_x;
193 advance_width = (FT_UShort)metrics.advance;
194
195#if 0
196
197 /* GWW: Do I do the same for vertical metrics? */
198 metrics.bearing_x = 0;
Chris Liddell10cf3882010-02-18 17:09:30 +0100199 metrics.bearing_y = loader->top_bearing;
200 metrics.advance = loader->vadvance;
Werner Lemberg422210b2009-11-03 08:11:02 +0100201
202 error = face->root.internal->incremental_interface->funcs->get_glyph_metrics(
203 face->root.internal->incremental_interface->object,
204 glyph_index, TRUE, &metrics );
205 if ( error )
206 goto Exit;
207
208 top_bearing = (FT_Short)metrics.bearing_y;
209 advance_height = (FT_UShort)metrics.advance;
210
211#endif /* 0 */
212
Chris Liddell10cf3882010-02-18 17:09:30 +0100213 loader->left_bearing = left_bearing;
214 loader->advance = advance_width;
215 loader->top_bearing = top_bearing;
216 loader->vadvance = advance_height;
217
218 if ( !loader->linear_def )
219 {
220 loader->linear_def = 1;
221 loader->linear = advance_width;
222 }
Werner Lemberg422210b2009-11-03 08:11:02 +0100223 }
224
Werner Lemberg9045f5b2009-12-03 05:57:30 +0100225 Exit:
Chris Liddell10cf3882010-02-18 17:09:30 +0100226 return;
227 }
Werner Lemberg9045f5b2009-12-03 05:57:30 +0100228
Werner Lemberg422210b2009-11-03 08:11:02 +0100229#endif /* FT_CONFIG_OPTION_INCREMENTAL */
230
Werner Lemberg422210b2009-11-03 08:11:02 +0100231
David Turnerd2b1f351999-12-16 23:11:37 +0000232 /*************************************************************************/
Werner Lemberg78575dc2000-06-12 19:36:41 +0000233 /* */
Werner Lemberg91db04c2002-04-01 14:25:28 +0000234 /* Translates an array of coordinates. */
David Turnerd2b1f351999-12-16 23:11:37 +0000235 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +0000236 static void
237 translate_array( FT_UInt n,
238 FT_Vector* coords,
239 FT_Pos delta_x,
240 FT_Pos delta_y )
David Turnerd2b1f351999-12-16 23:11:37 +0000241 {
David Turnerf9b8dec2000-06-16 19:34:52 +0000242 FT_UInt k;
Werner Lemberg78575dc2000-06-12 19:36:41 +0000243
Werner Lemberg5811c7c2000-07-02 13:53:16 +0000244
David Turnerd2b1f351999-12-16 23:11:37 +0000245 if ( delta_x )
246 for ( k = 0; k < n; k++ )
247 coords[k].x += delta_x;
248
249 if ( delta_y )
250 for ( k = 0; k < n; k++ )
251 coords[k].y += delta_y;
252 }
253
254
David Turner8f43c712000-02-02 12:16:19 +0000255#undef IS_HINTED
Werner Lemberg78575dc2000-06-12 19:36:41 +0000256#define IS_HINTED( flags ) ( ( flags & FT_LOAD_NO_HINTING ) == 0 )
257
David Turner8f43c712000-02-02 12:16:19 +0000258
David Turnerd2b1f351999-12-16 23:11:37 +0000259 /*************************************************************************/
260 /* */
Werner Lemberg91db04c2002-04-01 14:25:28 +0000261 /* The following functions are used by default with TrueType fonts. */
262 /* However, they can be replaced by alternatives if we need to support */
263 /* TrueType-compressed formats (like MicroType) in the future. */
David Turnerd2b1f351999-12-16 23:11:37 +0000264 /* */
Werner Lemberga929ba92000-06-25 06:47:11 +0000265 /*************************************************************************/
David Turner90f68b72000-06-23 12:26:14 +0000266
Werner Lemberg4a2305c2001-06-28 07:17:51 +0000267 FT_CALLBACK_DEF( FT_Error )
Werner Lemberg91db04c2002-04-01 14:25:28 +0000268 TT_Access_Glyph_Frame( TT_Loader loader,
269 FT_UInt glyph_index,
270 FT_ULong offset,
271 FT_UInt byte_count )
David Turner90f68b72000-06-23 12:26:14 +0000272 {
Werner Lemberge72c9fe2000-07-31 18:59:02 +0000273 FT_Error error;
274 FT_Stream stream = loader->stream;
Werner Lembergbd5ae402000-07-05 04:32:02 +0000275
Werner Lemberg353dfea2000-08-29 18:58:41 +0000276 /* for non-debug mode */
277 FT_UNUSED( glyph_index );
278
Werner Lemberga929ba92000-06-25 06:47:11 +0000279
Werner Lembergae425e52010-06-29 12:31:08 +0200280 FT_TRACE4(( "Glyph %ld\n", glyph_index ));
Werner Lemberge72c9fe2000-07-31 18:59:02 +0000281
282 /* the following line sets the `error' variable through macros! */
David Turner7d3a2642002-03-20 10:49:31 +0000283 if ( FT_STREAM_SEEK( offset ) || FT_FRAME_ENTER( byte_count ) )
Werner Lemberge72c9fe2000-07-31 18:59:02 +0000284 return error;
285
David Turner281679d2006-05-17 13:34:21 +0000286 loader->cursor = stream->cursor;
287 loader->limit = stream->limit;
288
Werner Lemberge72c9fe2000-07-31 18:59:02 +0000289 return TT_Err_Ok;
Werner Lembergbd5ae402000-07-05 04:32:02 +0000290 }
David Turner90f68b72000-06-23 12:26:14 +0000291
292
Werner Lemberg4a2305c2001-06-28 07:17:51 +0000293 FT_CALLBACK_DEF( void )
Werner Lemberg91db04c2002-04-01 14:25:28 +0000294 TT_Forget_Glyph_Frame( TT_Loader loader )
David Turner90f68b72000-06-23 12:26:14 +0000295 {
296 FT_Stream stream = loader->stream;
Werner Lemberga929ba92000-06-25 06:47:11 +0000297
298
David Turner7d3a2642002-03-20 10:49:31 +0000299 FT_FRAME_EXIT();
Werner Lembergbd5ae402000-07-05 04:32:02 +0000300 }
David Turner90f68b72000-06-23 12:26:14 +0000301
302
Werner Lemberg4a2305c2001-06-28 07:17:51 +0000303 FT_CALLBACK_DEF( FT_Error )
Werner Lemberg91db04c2002-04-01 14:25:28 +0000304 TT_Load_Glyph_Header( TT_Loader loader )
David Turner90f68b72000-06-23 12:26:14 +0000305 {
Werner Lemberg545c4e52006-05-17 22:55:04 +0000306 FT_Byte* p = loader->cursor;
307 FT_Byte* limit = loader->limit;
Werner Lembergbd5ae402000-07-05 04:32:02 +0000308
Werner Lembergac812952002-01-06 16:42:44 +0000309
David Turner281679d2006-05-17 13:34:21 +0000310 if ( p + 10 > limit )
David Turnerf7f82d72002-01-06 10:13:40 +0000311 return TT_Err_Invalid_Outline;
Werner Lemberga929ba92000-06-25 06:47:11 +0000312
Werner Lemberg545c4e52006-05-17 22:55:04 +0000313 loader->n_contours = FT_NEXT_SHORT( p );
David Turner90f68b72000-06-23 12:26:14 +0000314
Werner Lemberg545c4e52006-05-17 22:55:04 +0000315 loader->bbox.xMin = FT_NEXT_SHORT( p );
316 loader->bbox.yMin = FT_NEXT_SHORT( p );
317 loader->bbox.xMax = FT_NEXT_SHORT( p );
318 loader->bbox.yMax = FT_NEXT_SHORT( p );
David Turner90f68b72000-06-23 12:26:14 +0000319
320 FT_TRACE5(( " # of contours: %d\n", loader->n_contours ));
321 FT_TRACE5(( " xMin: %4d xMax: %4d\n", loader->bbox.xMin,
322 loader->bbox.xMax ));
323 FT_TRACE5(( " yMin: %4d yMax: %4d\n", loader->bbox.yMin,
324 loader->bbox.yMax ));
David Turner281679d2006-05-17 13:34:21 +0000325 loader->cursor = p;
Werner Lembergbd5ae402000-07-05 04:32:02 +0000326
Werner Lemberg1429db62001-04-02 23:54:01 +0000327 return TT_Err_Ok;
Werner Lembergbd5ae402000-07-05 04:32:02 +0000328 }
David Turner90f68b72000-06-23 12:26:14 +0000329
330
Werner Lemberg4a2305c2001-06-28 07:17:51 +0000331 FT_CALLBACK_DEF( FT_Error )
Werner Lemberg91db04c2002-04-01 14:25:28 +0000332 TT_Load_Simple_Glyph( TT_Loader load )
David Turnerd2b1f351999-12-16 23:11:37 +0000333 {
Werner Lemberg91db04c2002-04-01 14:25:28 +0000334 FT_Error error;
David Turner281679d2006-05-17 13:34:21 +0000335 FT_Byte* p = load->cursor;
336 FT_Byte* limit = load->limit;
Werner Lemberg91db04c2002-04-01 14:25:28 +0000337 FT_GlyphLoader gloader = load->gloader;
338 FT_Int n_contours = load->n_contours;
339 FT_Outline* outline;
340 TT_Face face = (TT_Face)load->face;
Werner Lemberg91db04c2002-04-01 14:25:28 +0000341 FT_UShort n_ins;
David Turner7fa30ee2007-06-11 00:55:23 +0000342 FT_Int n_points;
David Turnere49ab252000-05-16 23:44:38 +0000343
Werner Lemberg0240d292003-06-09 15:54:18 +0000344 FT_Byte *flag, *flag_limit;
345 FT_Byte c, count;
346 FT_Vector *vec, *vec_limit;
347 FT_Pos x;
David Turner815911a2007-06-16 17:07:20 +0000348 FT_Short *cont, *cont_limit, prev_cont;
David Turner5f5e5442007-06-11 00:18:00 +0000349 FT_Int xy_size = 0;
Werner Lemberg0240d292003-06-09 15:54:18 +0000350
Werner Lemberg78575dc2000-06-12 19:36:41 +0000351
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +0000352 /* check that we can add the contours to the glyph */
David Turner9fbd2ab2005-10-28 16:14:14 +0000353 error = FT_GLYPHLOADER_CHECK_POINTS( gloader, 0, n_contours );
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +0000354 if ( error )
355 goto Fail;
356
Werner Lemberg44bb3032004-04-25 20:15:11 +0000357 /* reading the contours' endpoints & number of points */
Werner Lemberg0240d292003-06-09 15:54:18 +0000358 cont = gloader->current.outline.contours;
359 cont_limit = cont + n_contours;
Werner Lembergbd5ae402000-07-05 04:32:02 +0000360
Werner Lemberg0240d292003-06-09 15:54:18 +0000361 /* check space for contours array + instructions count */
Werner Lemberge12ed562007-06-17 05:31:23 +0000362 if ( n_contours >= 0xFFF || p + ( n_contours + 1 ) * 2 > limit )
Werner Lemberg0240d292003-06-09 15:54:18 +0000363 goto Invalid_Outline;
Werner Lembergac812952002-01-06 16:42:44 +0000364
Werner Lemberg89d64fa2008-05-17 20:06:13 +0000365 prev_cont = FT_NEXT_USHORT( p );
366
367 if ( n_contours > 0 )
368 cont[0] = prev_cont;
369
David Turner815911a2007-06-16 17:07:20 +0000370 for ( cont++; cont < cont_limit; cont++ )
371 {
Werner Lemberg545c4e52006-05-17 22:55:04 +0000372 cont[0] = FT_NEXT_USHORT( p );
David Turner8f626b02007-06-22 22:22:38 +0000373 if ( cont[0] <= prev_cont )
David Turner815911a2007-06-16 17:07:20 +0000374 {
Werner Lemberge12ed562007-06-17 05:31:23 +0000375 /* unordered contours: this is invalid */
Werner Lembergf765e442010-06-24 10:34:29 +0200376 error = TT_Err_Invalid_Table;
David Turner815911a2007-06-16 17:07:20 +0000377 goto Fail;
378 }
379 prev_cont = cont[0];
380 }
Werner Lemberg0240d292003-06-09 15:54:18 +0000381
382 n_points = 0;
383 if ( n_contours > 0 )
Werner Lembergd0692462007-05-16 15:48:02 +0000384 {
Werner Lemberg0240d292003-06-09 15:54:18 +0000385 n_points = cont[-1] + 1;
Werner Lembergd0692462007-05-16 15:48:02 +0000386 if ( n_points < 0 )
387 goto Invalid_Outline;
388 }
Werner Lemberg0240d292003-06-09 15:54:18 +0000389
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +0000390 /* note that we will add four phantom points later */
David Turner9fbd2ab2005-10-28 16:14:14 +0000391 error = FT_GLYPHLOADER_CHECK_POINTS( gloader, n_points + 4, 0 );
Werner Lemberg0240d292003-06-09 15:54:18 +0000392 if ( error )
393 goto Fail;
394
395 /* we'd better check the contours table right now */
396 outline = &gloader->current.outline;
397
398 for ( cont = outline->contours + 1; cont < cont_limit; cont++ )
399 if ( cont[-1] >= cont[0] )
David Turnerf7f82d72002-01-06 10:13:40 +0000400 goto Invalid_Outline;
Werner Lemberga929ba92000-06-25 06:47:11 +0000401
Werner Lemberg78575dc2000-06-12 19:36:41 +0000402 /* reading the bytecode instructions */
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +0000403 load->glyph->control_len = 0;
404 load->glyph->control_data = 0;
Werner Lembergbd5ae402000-07-05 04:32:02 +0000405
Werner Lemberg545c4e52006-05-17 22:55:04 +0000406 if ( p + 2 > limit )
David Turner281679d2006-05-17 13:34:21 +0000407 goto Invalid_Outline;
408
Werner Lemberg545c4e52006-05-17 22:55:04 +0000409 n_ins = FT_NEXT_USHORT( p );
David Turnerd2b1f351999-12-16 23:11:37 +0000410
Werner Lemberg0240d292003-06-09 15:54:18 +0000411 FT_TRACE5(( " Instructions size: %u\n", n_ins ));
David Turnerd2b1f351999-12-16 23:11:37 +0000412
413 if ( n_ins > face->max_profile.maxSizeOfInstructions )
414 {
Werner Lemberg858abbe2009-06-26 06:15:41 +0200415 FT_TRACE0(( "TT_Load_Simple_Glyph: too many instructions (%d)\n",
Werner Lemberg6e2f9d52007-06-05 06:58:48 +0000416 n_ins ));
Werner Lemberg1f7f0e82001-06-06 17:30:41 +0000417 error = TT_Err_Too_Many_Hints;
David Turnerd2b1f351999-12-16 23:11:37 +0000418 goto Fail;
419 }
420
Werner Lemberg545c4e52006-05-17 22:55:04 +0000421 if ( ( limit - p ) < n_ins )
David Turnerd2b1f351999-12-16 23:11:37 +0000422 {
Werner Lemberg858abbe2009-06-26 06:15:41 +0200423 FT_TRACE0(( "TT_Load_Simple_Glyph: instruction count mismatch\n" ));
Werner Lemberg1f7f0e82001-06-06 17:30:41 +0000424 error = TT_Err_Too_Many_Hints;
David Turnerd2b1f351999-12-16 23:11:37 +0000425 goto Fail;
426 }
David Turnerd2b1f351999-12-16 23:11:37 +0000427
David Turner6aa260c2006-08-25 22:45:13 +0000428#ifdef TT_USE_BYTECODE_INTERPRETER
Werner Lemberga929ba92000-06-25 06:47:11 +0000429
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +0000430 if ( IS_HINTED( load->load_flags ) )
David Turner08fdac92000-02-21 16:01:33 +0000431 {
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +0000432 load->glyph->control_len = n_ins;
433 load->glyph->control_data = load->exec->glyphIns;
Werner Lembergbd5ae402000-07-05 04:32:02 +0000434
David Turner281679d2006-05-17 13:34:21 +0000435 FT_MEM_COPY( load->exec->glyphIns, p, (FT_Long)n_ins );
David Turner08fdac92000-02-21 16:01:33 +0000436 }
Werner Lemberga929ba92000-06-25 06:47:11 +0000437
David Turner6aa260c2006-08-25 22:45:13 +0000438#endif /* TT_USE_BYTECODE_INTERPRETER */
David Turnerd2b1f351999-12-16 23:11:37 +0000439
David Turner281679d2006-05-17 13:34:21 +0000440 p += n_ins;
David Turnere49ab252000-05-16 23:44:38 +0000441
Werner Lemberg78575dc2000-06-12 19:36:41 +0000442 /* reading the point tags */
Werner Lemberg0240d292003-06-09 15:54:18 +0000443 flag = (FT_Byte*)outline->tags;
444 flag_limit = flag + n_points;
445
Werner Lemberg685dd4f2004-10-13 05:15:44 +0000446 FT_ASSERT( flag != NULL );
447
Werner Lembergf946fc62003-12-31 08:48:21 +0000448 while ( flag < flag_limit )
David Turnere49ab252000-05-16 23:44:38 +0000449 {
Werner Lemberg545c4e52006-05-17 22:55:04 +0000450 if ( p + 1 > limit )
Werner Lemberg0240d292003-06-09 15:54:18 +0000451 goto Invalid_Outline;
David Turnere49ab252000-05-16 23:44:38 +0000452
Werner Lemberg545c4e52006-05-17 22:55:04 +0000453 *flag++ = c = FT_NEXT_BYTE( p );
Werner Lemberg0240d292003-06-09 15:54:18 +0000454 if ( c & 8 )
David Turnerd2b1f351999-12-16 23:11:37 +0000455 {
Werner Lemberg545c4e52006-05-17 22:55:04 +0000456 if ( p + 1 > limit )
David Turnerf7f82d72002-01-06 10:13:40 +0000457 goto Invalid_Outline;
458
Werner Lemberg545c4e52006-05-17 22:55:04 +0000459 count = FT_NEXT_BYTE( p );
Werner Lemberg0240d292003-06-09 15:54:18 +0000460 if ( flag + (FT_Int)count > flag_limit )
461 goto Invalid_Outline;
David Turnerf7f82d72002-01-06 10:13:40 +0000462
Werner Lemberg0240d292003-06-09 15:54:18 +0000463 for ( ; count > 0; count-- )
464 *flag++ = c;
David Turnerd2b1f351999-12-16 23:11:37 +0000465 }
466 }
467
Werner Lemberg78575dc2000-06-12 19:36:41 +0000468 /* reading the X coordinates */
David Turnere49ab252000-05-16 23:44:38 +0000469
Werner Lemberg0240d292003-06-09 15:54:18 +0000470 vec = outline->points;
471 vec_limit = vec + n_points;
472 flag = (FT_Byte*)outline->tags;
473 x = 0;
474
David Turner5f5e5442007-06-11 00:18:00 +0000475 if ( p + xy_size > limit )
476 goto Invalid_Outline;
477
Werner Lemberg0240d292003-06-09 15:54:18 +0000478 for ( ; vec < vec_limit; vec++, flag++ )
David Turnerd2b1f351999-12-16 23:11:37 +0000479 {
Werner Lemberg35ae5742008-10-02 10:40:52 +0000480 FT_Pos y = 0;
481 FT_Byte f = *flag;
David Turnere49ab252000-05-16 23:44:38 +0000482
Werner Lemberg78575dc2000-06-12 19:36:41 +0000483
David Turner5f5e5442007-06-11 00:18:00 +0000484 if ( f & 2 )
David Turnerd2b1f351999-12-16 23:11:37 +0000485 {
Werner Lembergf6c120f2007-06-11 04:55:58 +0000486 if ( p + 1 > limit )
David Turner281679d2006-05-17 13:34:21 +0000487 goto Invalid_Outline;
488
Werner Lemberg545c4e52006-05-17 22:55:04 +0000489 y = (FT_Pos)FT_NEXT_BYTE( p );
David Turner5f5e5442007-06-11 00:18:00 +0000490 if ( ( f & 16 ) == 0 )
Werner Lemberg0240d292003-06-09 15:54:18 +0000491 y = -y;
David Turnerd2b1f351999-12-16 23:11:37 +0000492 }
David Turner5f5e5442007-06-11 00:18:00 +0000493 else if ( ( f & 16 ) == 0 )
David Turner281679d2006-05-17 13:34:21 +0000494 {
Werner Lembergf6c120f2007-06-11 04:55:58 +0000495 if ( p + 2 > limit )
David Turner281679d2006-05-17 13:34:21 +0000496 goto Invalid_Outline;
497
Werner Lemberg545c4e52006-05-17 22:55:04 +0000498 y = (FT_Pos)FT_NEXT_SHORT( p );
David Turner281679d2006-05-17 13:34:21 +0000499 }
Werner Lemberg0240d292003-06-09 15:54:18 +0000500
501 x += y;
502 vec->x = x;
Werner Lemberg35ae5742008-10-02 10:40:52 +0000503 /* the cast is for stupid compilers */
504 *flag = (FT_Byte)( f & ~( 2 | 16 ) );
David Turnerd2b1f351999-12-16 23:11:37 +0000505 }
506
Werner Lemberg78575dc2000-06-12 19:36:41 +0000507 /* reading the Y coordinates */
David Turnerd2b1f351999-12-16 23:11:37 +0000508
Werner Lemberg0240d292003-06-09 15:54:18 +0000509 vec = gloader->current.outline.points;
510 vec_limit = vec + n_points;
511 flag = (FT_Byte*)outline->tags;
512 x = 0;
513
514 for ( ; vec < vec_limit; vec++, flag++ )
David Turnerd2b1f351999-12-16 23:11:37 +0000515 {
Werner Lemberg35ae5742008-10-02 10:40:52 +0000516 FT_Pos y = 0;
517 FT_Byte f = *flag;
David Turnere49ab252000-05-16 23:44:38 +0000518
Werner Lemberg78575dc2000-06-12 19:36:41 +0000519
David Turner5f5e5442007-06-11 00:18:00 +0000520 if ( f & 4 )
David Turnerd2b1f351999-12-16 23:11:37 +0000521 {
Werner Lembergf6c120f2007-06-11 04:55:58 +0000522 if ( p + 1 > limit )
David Turner281679d2006-05-17 13:34:21 +0000523 goto Invalid_Outline;
524
Werner Lemberg545c4e52006-05-17 22:55:04 +0000525 y = (FT_Pos)FT_NEXT_BYTE( p );
David Turner5f5e5442007-06-11 00:18:00 +0000526 if ( ( f & 32 ) == 0 )
Werner Lemberg0240d292003-06-09 15:54:18 +0000527 y = -y;
David Turnerd2b1f351999-12-16 23:11:37 +0000528 }
David Turner5f5e5442007-06-11 00:18:00 +0000529 else if ( ( f & 32 ) == 0 )
David Turner281679d2006-05-17 13:34:21 +0000530 {
Werner Lembergf6c120f2007-06-11 04:55:58 +0000531 if ( p + 2 > limit )
David Turner281679d2006-05-17 13:34:21 +0000532 goto Invalid_Outline;
533
Werner Lemberg545c4e52006-05-17 22:55:04 +0000534 y = (FT_Pos)FT_NEXT_SHORT( p );
David Turner281679d2006-05-17 13:34:21 +0000535 }
Werner Lemberg0240d292003-06-09 15:54:18 +0000536
537 x += y;
538 vec->y = x;
Werner Lemberg35ae5742008-10-02 10:40:52 +0000539 /* the cast is for stupid compilers */
540 *flag = (FT_Byte)( f & FT_CURVE_TAG_ON );
David Turnerd2b1f351999-12-16 23:11:37 +0000541 }
542
David Turner8edbcab2001-06-19 08:28:24 +0000543 outline->n_points = (FT_UShort)n_points;
544 outline->n_contours = (FT_Short) n_contours;
David Turnerc3128612000-06-23 05:02:13 +0000545
David Turner281679d2006-05-17 13:34:21 +0000546 load->cursor = p;
David Turnerf7f82d72002-01-06 10:13:40 +0000547
Werner Lembergbd5ae402000-07-05 04:32:02 +0000548 Fail:
David Turnerc3128612000-06-23 05:02:13 +0000549 return error;
David Turnerf7f82d72002-01-06 10:13:40 +0000550
551 Invalid_Outline:
552 error = TT_Err_Invalid_Outline;
553 goto Fail;
David Turnerc3128612000-06-23 05:02:13 +0000554 }
555
556
Werner Lemberg4a2305c2001-06-28 07:17:51 +0000557 FT_CALLBACK_DEF( FT_Error )
Werner Lemberg91db04c2002-04-01 14:25:28 +0000558 TT_Load_Composite_Glyph( TT_Loader loader )
David Turner90f68b72000-06-23 12:26:14 +0000559 {
Werner Lemberg91db04c2002-04-01 14:25:28 +0000560 FT_Error error;
David Turner281679d2006-05-17 13:34:21 +0000561 FT_Byte* p = loader->cursor;
562 FT_Byte* limit = loader->limit;
Werner Lemberg91db04c2002-04-01 14:25:28 +0000563 FT_GlyphLoader gloader = loader->gloader;
David Turnereba5ad42002-03-14 12:56:35 +0000564 FT_SubGlyph subglyph;
Werner Lemberg91db04c2002-04-01 14:25:28 +0000565 FT_UInt num_subglyphs;
David Turner90f68b72000-06-23 12:26:14 +0000566
Werner Lemberga929ba92000-06-25 06:47:11 +0000567
David Turner90f68b72000-06-23 12:26:14 +0000568 num_subglyphs = 0;
Werner Lemberga929ba92000-06-25 06:47:11 +0000569
David Turner90f68b72000-06-23 12:26:14 +0000570 do
571 {
572 FT_Fixed xx, xy, yy, yx;
David Turner281679d2006-05-17 13:34:21 +0000573 FT_UInt count;
David Turner90f68b72000-06-23 12:26:14 +0000574
Werner Lemberga929ba92000-06-25 06:47:11 +0000575
David Turner90f68b72000-06-23 12:26:14 +0000576 /* check that we can load a new subglyph */
David Turnereba5ad42002-03-14 12:56:35 +0000577 error = FT_GlyphLoader_CheckSubGlyphs( gloader, num_subglyphs + 1 );
Werner Lemberga929ba92000-06-25 06:47:11 +0000578 if ( error )
579 goto Fail;
Werner Lembergbd5ae402000-07-05 04:32:02 +0000580
Werner Lembergac812952002-01-06 16:42:44 +0000581 /* check space */
Werner Lemberg545c4e52006-05-17 22:55:04 +0000582 if ( p + 4 > limit )
David Turnerf7f82d72002-01-06 10:13:40 +0000583 goto Invalid_Composite;
584
David Turner90f68b72000-06-23 12:26:14 +0000585 subglyph = gloader->current.subglyphs + num_subglyphs;
586
587 subglyph->arg1 = subglyph->arg2 = 0;
588
Werner Lemberg545c4e52006-05-17 22:55:04 +0000589 subglyph->flags = FT_NEXT_USHORT( p );
590 subglyph->index = FT_NEXT_USHORT( p );
David Turner90f68b72000-06-23 12:26:14 +0000591
Werner Lembergac812952002-01-06 16:42:44 +0000592 /* check space */
David Turner281679d2006-05-17 13:34:21 +0000593 count = 2;
David Turnerf7f82d72002-01-06 10:13:40 +0000594 if ( subglyph->flags & ARGS_ARE_WORDS )
David Turner281679d2006-05-17 13:34:21 +0000595 count += 2;
David Turnerf7f82d72002-01-06 10:13:40 +0000596 if ( subglyph->flags & WE_HAVE_A_SCALE )
David Turner281679d2006-05-17 13:34:21 +0000597 count += 2;
David Turnerf7f82d72002-01-06 10:13:40 +0000598 else if ( subglyph->flags & WE_HAVE_AN_XY_SCALE )
David Turner281679d2006-05-17 13:34:21 +0000599 count += 4;
David Turnerf7f82d72002-01-06 10:13:40 +0000600 else if ( subglyph->flags & WE_HAVE_A_2X2 )
David Turner281679d2006-05-17 13:34:21 +0000601 count += 8;
David Turnerf7f82d72002-01-06 10:13:40 +0000602
David Turner281679d2006-05-17 13:34:21 +0000603 if ( p + count > limit )
David Turnerf7f82d72002-01-06 10:13:40 +0000604 goto Invalid_Composite;
605
David Turner90f68b72000-06-23 12:26:14 +0000606 /* read arguments */
607 if ( subglyph->flags & ARGS_ARE_WORDS )
608 {
Werner Lemberg545c4e52006-05-17 22:55:04 +0000609 subglyph->arg1 = FT_NEXT_SHORT( p );
610 subglyph->arg2 = FT_NEXT_SHORT( p );
David Turner90f68b72000-06-23 12:26:14 +0000611 }
612 else
613 {
Werner Lemberg545c4e52006-05-17 22:55:04 +0000614 subglyph->arg1 = FT_NEXT_CHAR( p );
615 subglyph->arg2 = FT_NEXT_CHAR( p );
David Turner90f68b72000-06-23 12:26:14 +0000616 }
617
618 /* read transform */
619 xx = yy = 0x10000L;
620 xy = yx = 0;
621
622 if ( subglyph->flags & WE_HAVE_A_SCALE )
623 {
Werner Lemberg545c4e52006-05-17 22:55:04 +0000624 xx = (FT_Fixed)FT_NEXT_SHORT( p ) << 2;
David Turner90f68b72000-06-23 12:26:14 +0000625 yy = xx;
626 }
627 else if ( subglyph->flags & WE_HAVE_AN_XY_SCALE )
628 {
Werner Lemberg545c4e52006-05-17 22:55:04 +0000629 xx = (FT_Fixed)FT_NEXT_SHORT( p ) << 2;
630 yy = (FT_Fixed)FT_NEXT_SHORT( p ) << 2;
David Turner90f68b72000-06-23 12:26:14 +0000631 }
632 else if ( subglyph->flags & WE_HAVE_A_2X2 )
633 {
Werner Lemberg545c4e52006-05-17 22:55:04 +0000634 xx = (FT_Fixed)FT_NEXT_SHORT( p ) << 2;
635 yx = (FT_Fixed)FT_NEXT_SHORT( p ) << 2;
636 xy = (FT_Fixed)FT_NEXT_SHORT( p ) << 2;
637 yy = (FT_Fixed)FT_NEXT_SHORT( p ) << 2;
David Turner90f68b72000-06-23 12:26:14 +0000638 }
639
640 subglyph->transform.xx = xx;
641 subglyph->transform.xy = xy;
642 subglyph->transform.yx = yx;
643 subglyph->transform.yy = yy;
644
645 num_subglyphs++;
Werner Lemberg5811c7c2000-07-02 13:53:16 +0000646
Werner Lembergdcd2e142000-06-25 07:43:15 +0000647 } while ( subglyph->flags & MORE_COMPONENTS );
David Turner90f68b72000-06-23 12:26:14 +0000648
649 gloader->current.num_subglyphs = num_subglyphs;
650
David Turner6aa260c2006-08-25 22:45:13 +0000651#ifdef TT_USE_BYTECODE_INTERPRETER
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +0000652
David Turner90f68b72000-06-23 12:26:14 +0000653 {
Werner Lemberg545c4e52006-05-17 22:55:04 +0000654 FT_Stream stream = loader->stream;
655
656
Werner Lemberg5df5dbb2008-06-22 13:40:08 +0000657 /* we must undo the FT_FRAME_ENTER in order to point */
658 /* to the composite instructions, if we find some. */
659 /* We will process them later. */
660 /* */
David Turner7d3a2642002-03-20 10:49:31 +0000661 loader->ins_pos = (FT_ULong)( FT_STREAM_POS() +
David Turner281679d2006-05-17 13:34:21 +0000662 p - limit );
David Turner90f68b72000-06-23 12:26:14 +0000663 }
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +0000664
David Turner90f68b72000-06-23 12:26:14 +0000665#endif
666
David Turner281679d2006-05-17 13:34:21 +0000667 loader->cursor = p;
David Turnerf7f82d72002-01-06 10:13:40 +0000668
David Turner90f68b72000-06-23 12:26:14 +0000669 Fail:
670 return error;
David Turnerf7f82d72002-01-06 10:13:40 +0000671
672 Invalid_Composite:
673 error = TT_Err_Invalid_Composite;
674 goto Fail;
David Turner90f68b72000-06-23 12:26:14 +0000675 }
676
David Turnerc3128612000-06-23 05:02:13 +0000677
David Turnerbc82f1b2002-03-01 02:26:22 +0000678 FT_LOCAL_DEF( void )
Werner Lemberg4a2305c2001-06-28 07:17:51 +0000679 TT_Init_Glyph_Loading( TT_Face face )
David Turner994d7742000-06-25 04:49:19 +0000680 {
681 face->access_glyph_frame = TT_Access_Glyph_Frame;
682 face->read_glyph_header = TT_Load_Glyph_Header;
683 face->read_simple_glyph = TT_Load_Simple_Glyph;
684 face->read_composite_glyph = TT_Load_Composite_Glyph;
685 face->forget_glyph_frame = TT_Forget_Glyph_Frame;
686 }
687
David Turnerc3128612000-06-23 05:02:13 +0000688
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +0000689 static void
690 tt_prepare_zone( TT_GlyphZone zone,
691 FT_GlyphLoad load,
692 FT_UInt start_point,
693 FT_UInt start_contour )
694 {
Werner Lemberge12ed562007-06-17 05:31:23 +0000695 zone->n_points = (FT_UShort)( load->outline.n_points - start_point );
696 zone->n_contours = (FT_Short) ( load->outline.n_contours -
697 start_contour );
698 zone->org = load->extra_points + start_point;
699 zone->cur = load->outline.points + start_point;
700 zone->orus = load->extra_points2 + start_point;
701 zone->tags = (FT_Byte*)load->outline.tags + start_point;
702 zone->contours = (FT_UShort*)load->outline.contours + start_contour;
David Turner9fbfc6a2006-08-16 09:11:31 +0000703 zone->first_point = (FT_UShort)start_point;
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +0000704 }
705
706
707 /*************************************************************************/
708 /* */
709 /* <Function> */
710 /* TT_Hint_Glyph */
711 /* */
712 /* <Description> */
713 /* Hint the glyph using the zone prepared by the caller. Note that */
714 /* the zone is supposed to include four phantom points. */
715 /* */
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +0000716 static FT_Error
Werner Lemberg7c259462005-09-28 07:34:45 +0000717 TT_Hint_Glyph( TT_Loader loader,
718 FT_Bool is_composite )
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +0000719 {
720 TT_GlyphZone zone = &loader->zone;
721 FT_Pos origin;
722
David Turner6aa260c2006-08-25 22:45:13 +0000723#ifdef TT_USE_BYTECODE_INTERPRETER
Werner Lemberg7c259462005-09-28 07:34:45 +0000724 FT_UInt n_ins;
725#else
726 FT_UNUSED( is_composite );
727#endif
728
David Turner18e44432005-09-23 13:22:10 +0000729
David Turner6aa260c2006-08-25 22:45:13 +0000730#ifdef TT_USE_BYTECODE_INTERPRETER
suzuki toshiya1b6f1d22009-08-01 00:32:16 +0900731 if ( loader->glyph->control_len > 0xFFFFL )
732 {
733 FT_TRACE1(( "TT_Hint_Glyph: too long instructions " ));
734 FT_TRACE1(( "(0x%lx byte) is truncated\n",
735 loader->glyph->control_len ));
736 }
737 n_ins = (FT_UInt)( loader->glyph->control_len );
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +0000738#endif
739
740 origin = zone->cur[zone->n_points - 4].x;
741 origin = FT_PIX_ROUND( origin ) - origin;
742 if ( origin )
743 translate_array( zone->n_points, zone->cur, origin, 0 );
744
David Turner6aa260c2006-08-25 22:45:13 +0000745#ifdef TT_USE_BYTECODE_INTERPRETER
Werner Lemberg6e87ed92007-01-26 22:18:56 +0000746 /* save original point position in org */
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +0000747 if ( n_ins > 0 )
Werner Lemberg12342992006-08-19 11:18:09 +0000748 FT_ARRAY_COPY( zone->org, zone->cur, zone->n_points );
Werner Lembergffa49652008-05-25 12:43:57 +0000749
750 /* Reset graphics state. */
751 loader->exec->GS = ((TT_Size)loader->size)->GS;
752
753 /* XXX: UNDOCUMENTED! Hinting instructions of a composite glyph */
754 /* completely refer to the (already) hinted subglyphs. */
755 if ( is_composite )
756 {
757 loader->exec->metrics.x_scale = 1 << 16;
758 loader->exec->metrics.y_scale = 1 << 16;
759
760 FT_ARRAY_COPY( zone->orus, zone->cur, zone->n_points );
761 }
762 else
763 {
Werner Lemberg0c52faa2008-05-25 20:04:56 +0000764 loader->exec->metrics.x_scale =
765 ((TT_Size)loader->size)->metrics.x_scale;
766 loader->exec->metrics.y_scale =
767 ((TT_Size)loader->size)->metrics.y_scale;
Werner Lembergffa49652008-05-25 12:43:57 +0000768 }
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +0000769#endif
770
771 /* round pp2 and pp4 */
Werner Lemberg7c259462005-09-28 07:34:45 +0000772 zone->cur[zone->n_points - 3].x =
773 FT_PIX_ROUND( zone->cur[zone->n_points - 3].x );
774 zone->cur[zone->n_points - 1].y =
775 FT_PIX_ROUND( zone->cur[zone->n_points - 1].y );
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +0000776
David Turner6aa260c2006-08-25 22:45:13 +0000777#ifdef TT_USE_BYTECODE_INTERPRETER
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +0000778
779 if ( n_ins > 0 )
780 {
781 FT_Bool debug;
782 FT_Error error;
783
Werner Lemberg72271142009-06-18 15:42:52 +0200784 FT_GlyphLoader gloader = loader->gloader;
785 FT_Outline current_outline = gloader->current.outline;
786
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +0000787
788 error = TT_Set_CodeRange( loader->exec, tt_coderange_glyph,
789 loader->exec->glyphIns, n_ins );
790 if ( error )
791 return error;
792
Werner Lemberg7c259462005-09-28 07:34:45 +0000793 loader->exec->is_composite = is_composite;
794 loader->exec->pts = *zone;
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +0000795
David Turner115b4422006-12-22 11:37:05 +0000796 debug = FT_BOOL( !( loader->load_flags & FT_LOAD_NO_SCALE ) &&
Werner Lemberg6b87e6f2007-01-02 19:20:08 +0000797 ((TT_Size)loader->size)->debug );
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +0000798
799 error = TT_Run_Context( loader->exec, debug );
800 if ( error && loader->exec->pedantic_hinting )
801 return error;
Werner Lemberg72271142009-06-18 15:42:52 +0200802
803 /* store drop-out mode in bits 5-7; set bit 2 also as a marker */
804 current_outline.tags[0] |=
805 ( loader->exec->GS.scan_type << 5 ) | FT_CURVE_TAG_HAS_SCANMODE;
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +0000806 }
807
808#endif
809
810 /* save glyph phantom points */
811 if ( !loader->preserve_pps )
812 {
813 loader->pp1 = zone->cur[zone->n_points - 4];
814 loader->pp2 = zone->cur[zone->n_points - 3];
815 loader->pp3 = zone->cur[zone->n_points - 2];
816 loader->pp4 = zone->cur[zone->n_points - 1];
817 }
818
819 return TT_Err_Ok;
820 }
821
822
David Turnerc3128612000-06-23 05:02:13 +0000823 /*************************************************************************/
824 /* */
825 /* <Function> */
826 /* TT_Process_Simple_Glyph */
827 /* */
828 /* <Description> */
829 /* Once a simple glyph has been loaded, it needs to be processed. */
830 /* Usually, this means scaling and hinting through bytecode */
Werner Lemberga929ba92000-06-25 06:47:11 +0000831 /* interpretation. */
David Turnerc3128612000-06-23 05:02:13 +0000832 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +0000833 static FT_Error
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +0000834 TT_Process_Simple_Glyph( TT_Loader loader )
David Turnerc3128612000-06-23 05:02:13 +0000835 {
Werner Lemberg7c259462005-09-28 07:34:45 +0000836 FT_GlyphLoader gloader = loader->gloader;
837 FT_Error error = TT_Err_Ok;
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +0000838 FT_Outline* outline;
Werner Lembergd21fe6e2007-07-10 23:10:39 +0000839 FT_Int n_points;
Werner Lemberga929ba92000-06-25 06:47:11 +0000840
Werner Lemberge4b32a52000-10-31 20:42:18 +0000841
Werner Lemberg7c259462005-09-28 07:34:45 +0000842 outline = &gloader->current.outline;
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +0000843 n_points = outline->n_points;
David Turnerc3128612000-06-23 05:02:13 +0000844
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +0000845 /* set phantom points */
David Turnere49ab252000-05-16 23:44:38 +0000846
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +0000847 outline->points[n_points ] = loader->pp1;
848 outline->points[n_points + 1] = loader->pp2;
849 outline->points[n_points + 2] = loader->pp3;
850 outline->points[n_points + 3] = loader->pp4;
David Turnerd2b1f351999-12-16 23:11:37 +0000851
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +0000852 outline->tags[n_points ] = 0;
853 outline->tags[n_points + 1] = 0;
854 outline->tags[n_points + 2] = 0;
855 outline->tags[n_points + 3] = 0;
David Turnerd2b1f351999-12-16 23:11:37 +0000856
Werner Lemberg8bb07e62004-03-27 08:43:17 +0000857 n_points += 4;
David Turnerd2b1f351999-12-16 23:11:37 +0000858
Werner Lemberg44bb3032004-04-25 20:15:11 +0000859#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
860
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +0000861 if ( ((TT_Face)loader->face)->doblend )
Werner Lemberg44bb3032004-04-25 20:15:11 +0000862 {
863 /* Deltas apply to the unscaled data. */
Werner Lemberg7c259462005-09-28 07:34:45 +0000864 FT_Vector* deltas;
865 FT_Memory memory = loader->face->memory;
Werner Lembergd21fe6e2007-07-10 23:10:39 +0000866 FT_Int i;
Werner Lemberg44bb3032004-04-25 20:15:11 +0000867
868
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +0000869 error = TT_Vary_Get_Glyph_Deltas( (TT_Face)(loader->face),
870 loader->glyph_index,
Werner Lemberg2b54eba2004-05-07 07:08:14 +0000871 &deltas,
872 n_points );
Werner Lemberg2b54eba2004-05-07 07:08:14 +0000873 if ( error )
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +0000874 return error;
Werner Lemberg44bb3032004-04-25 20:15:11 +0000875
876 for ( i = 0; i < n_points; ++i )
877 {
878 outline->points[i].x += deltas[i].x;
879 outline->points[i].y += deltas[i].y;
880 }
881
882 FT_FREE( deltas );
883 }
884
885#endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
886
David Turner33f5f242006-08-16 16:50:55 +0000887 if ( IS_HINTED( loader->load_flags ) )
888 {
889 tt_prepare_zone( &loader->zone, &gloader->current, 0, 0 );
890
891 FT_ARRAY_COPY( loader->zone.orus, loader->zone.cur,
892 loader->zone.n_points + 4 );
893 }
894
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +0000895 /* scale the glyph */
896 if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
David Turnerd2b1f351999-12-16 23:11:37 +0000897 {
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +0000898 FT_Vector* vec = outline->points;
899 FT_Vector* limit = outline->points + n_points;
900 FT_Fixed x_scale = ((TT_Size)loader->size)->metrics.x_scale;
901 FT_Fixed y_scale = ((TT_Size)loader->size)->metrics.y_scale;
Werner Lemberg5811c7c2000-07-02 13:53:16 +0000902
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +0000903
Werner Lemberg78575dc2000-06-12 19:36:41 +0000904 for ( ; vec < limit; vec++ )
David Turnerd2b1f351999-12-16 23:11:37 +0000905 {
David Turner8f43c712000-02-02 12:16:19 +0000906 vec->x = FT_MulFix( vec->x, x_scale );
907 vec->y = FT_MulFix( vec->y, y_scale );
David Turnerd2b1f351999-12-16 23:11:37 +0000908 }
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +0000909
910 loader->pp1 = outline->points[n_points - 4];
911 loader->pp2 = outline->points[n_points - 3];
912 loader->pp3 = outline->points[n_points - 2];
913 loader->pp4 = outline->points[n_points - 1];
David Turnerf0df85b2000-06-22 00:17:42 +0000914 }
David Turnerd2b1f351999-12-16 23:11:37 +0000915
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +0000916 if ( IS_HINTED( loader->load_flags ) )
David Turnerf0df85b2000-06-22 00:17:42 +0000917 {
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +0000918 loader->zone.n_points += 4;
Werner Lemberg78575dc2000-06-12 19:36:41 +0000919
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +0000920 error = TT_Hint_Glyph( loader, 0 );
David Turnerd2b1f351999-12-16 23:11:37 +0000921 }
922
David Turnerd2b1f351999-12-16 23:11:37 +0000923 return error;
924 }
925
926
927 /*************************************************************************/
928 /* */
929 /* <Function> */
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +0000930 /* TT_Process_Composite_Component */
931 /* */
932 /* <Description> */
933 /* Once a composite component has been loaded, it needs to be */
934 /* processed. Usually, this means transforming and translating. */
935 /* */
936 static FT_Error
937 TT_Process_Composite_Component( TT_Loader loader,
938 FT_SubGlyph subglyph,
939 FT_UInt start_point,
940 FT_UInt num_base_points )
941 {
942 FT_GlyphLoader gloader = loader->gloader;
943 FT_Vector* base_vec = gloader->base.outline.points;
944 FT_UInt num_points = gloader->base.outline.n_points;
945 FT_Bool have_scale;
946 FT_Pos x, y;
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +0000947
David Turner18e44432005-09-23 13:22:10 +0000948
949 have_scale = FT_BOOL( subglyph->flags & ( WE_HAVE_A_SCALE |
950 WE_HAVE_AN_XY_SCALE |
951 WE_HAVE_A_2X2 ) );
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +0000952
953 /* perform the transform required for this subglyph */
954 if ( have_scale )
955 {
Werner Lembergffa033b2005-08-19 08:56:29 +0000956 FT_UInt i;
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +0000957
958
959 for ( i = num_base_points; i < num_points; i++ )
960 FT_Vector_Transform( base_vec + i, &subglyph->transform );
961 }
962
963 /* get offset */
964 if ( !( subglyph->flags & ARGS_ARE_XY_VALUES ) )
965 {
966 FT_UInt k = subglyph->arg1;
967 FT_UInt l = subglyph->arg2;
968 FT_Vector* p1;
969 FT_Vector* p2;
970
971
Werner Lembergffa033b2005-08-19 08:56:29 +0000972 /* match l-th point of the newly loaded component to the k-th point */
973 /* of the previously loaded components. */
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +0000974
975 /* change to the point numbers used by our outline */
976 k += start_point;
977 l += num_base_points;
Werner Lembergffa033b2005-08-19 08:56:29 +0000978 if ( k >= num_base_points ||
979 l >= num_points )
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +0000980 return TT_Err_Invalid_Composite;
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +0000981
982 p1 = gloader->base.outline.points + k;
983 p2 = gloader->base.outline.points + l;
984
985 x = p1->x - p2->x;
986 y = p1->y - p2->y;
987 }
988 else
989 {
990 x = subglyph->arg1;
991 y = subglyph->arg2;
992
993 if ( !x && !y )
994 return TT_Err_Ok;
995
Werner Lembergffa033b2005-08-19 08:56:29 +0000996 /* Use a default value dependent on */
997 /* TT_CONFIG_OPTION_COMPONENT_OFFSET_SCALED. This is useful for old TT */
998 /* fonts which don't set the xxx_COMPONENT_OFFSET bit. */
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +0000999
1000 if ( have_scale &&
1001#ifdef TT_CONFIG_OPTION_COMPONENT_OFFSET_SCALED
1002 !( subglyph->flags & UNSCALED_COMPONENT_OFFSET ) )
1003#else
1004 ( subglyph->flags & SCALED_COMPONENT_OFFSET ) )
1005#endif
1006 {
Werner Lemberg7c259462005-09-28 07:34:45 +00001007
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001008#if 0
1009
Werner Lembergffa033b2005-08-19 08:56:29 +00001010 /*************************************************************************/
1011 /* */
1012 /* This algorithm is what Apple documents. But it doesn't work. */
1013 /* */
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001014 int a = subglyph->transform.xx > 0 ? subglyph->transform.xx
1015 : -subglyph->transform.xx;
1016 int b = subglyph->transform.yx > 0 ? subglyph->transform.yx
1017 : -subglyph->transform.yx;
1018 int c = subglyph->transform.xy > 0 ? subglyph->transform.xy
1019 : -subglyph->transform.xy;
1020 int d = subglyph->transform.yy > 0 ? subglyph->transform.yy
1021 : -subglyph->transform.yy;
1022 int m = a > b ? a : b;
1023 int n = c > d ? c : d;
1024
1025
1026 if ( a - b <= 33 && a - b >= -33 )
1027 m *= 2;
1028 if ( c - d <= 33 && c - d >= -33 )
1029 n *= 2;
1030 x = FT_MulFix( x, m );
1031 y = FT_MulFix( y, n );
1032
1033#else /* 0 */
1034
Werner Lembergffa033b2005-08-19 08:56:29 +00001035 /*************************************************************************/
1036 /* */
1037 /* This algorithm is a guess and works much better than the above. */
1038 /* */
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001039 FT_Fixed mac_xscale = FT_SqrtFixed(
suzuki toshiya9fc40942009-08-01 00:32:14 +09001040 (FT_Int32)FT_MulFix( subglyph->transform.xx,
1041 subglyph->transform.xx ) +
1042 (FT_Int32)FT_MulFix( subglyph->transform.xy,
1043 subglyph->transform.xy ) );
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001044 FT_Fixed mac_yscale = FT_SqrtFixed(
suzuki toshiya9fc40942009-08-01 00:32:14 +09001045 (FT_Int32)FT_MulFix( subglyph->transform.yy,
1046 subglyph->transform.yy ) +
1047 (FT_Int32)FT_MulFix( subglyph->transform.yx,
1048 subglyph->transform.yx ) );
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001049
1050
1051 x = FT_MulFix( x, mac_xscale );
1052 y = FT_MulFix( y, mac_yscale );
1053
1054#endif /* 0 */
1055
1056 }
1057
1058 if ( !( loader->load_flags & FT_LOAD_NO_SCALE ) )
1059 {
Werner Lembergffa033b2005-08-19 08:56:29 +00001060 FT_Fixed x_scale = ((TT_Size)loader->size)->metrics.x_scale;
1061 FT_Fixed y_scale = ((TT_Size)loader->size)->metrics.y_scale;
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001062
1063
1064 x = FT_MulFix( x, x_scale );
1065 y = FT_MulFix( y, y_scale );
1066
1067 if ( subglyph->flags & ROUND_XY_TO_GRID )
1068 {
1069 x = FT_PIX_ROUND( x );
1070 y = FT_PIX_ROUND( y );
1071 }
1072 }
1073 }
1074
1075 if ( x || y )
1076 translate_array( num_points - num_base_points,
1077 base_vec + num_base_points,
1078 x, y );
1079
1080 return TT_Err_Ok;
1081 }
1082
1083
1084 /*************************************************************************/
1085 /* */
1086 /* <Function> */
1087 /* TT_Process_Composite_Glyph */
1088 /* */
1089 /* <Description> */
1090 /* This is slightly different from TT_Process_Simple_Glyph, in that */
Werner Lemberg4b2e83d2007-02-01 07:58:02 +00001091 /* its sole purpose is to hint the glyph. Thus this function is */
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001092 /* only available when bytecode interpreter is enabled. */
1093 /* */
1094 static FT_Error
1095 TT_Process_Composite_Glyph( TT_Loader loader,
1096 FT_UInt start_point,
1097 FT_UInt start_contour )
1098 {
1099 FT_Error error;
1100 FT_Outline* outline;
Werner Lemberga2da05c2006-06-25 06:27:27 +00001101 FT_UInt i;
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001102
1103
1104 outline = &loader->gloader->base.outline;
1105
1106 /* make room for phantom points */
David Turner9fbd2ab2005-10-28 16:14:14 +00001107 error = FT_GLYPHLOADER_CHECK_POINTS( loader->gloader,
1108 outline->n_points + 4,
1109 0 );
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001110 if ( error )
1111 return error;
1112
1113 outline->points[outline->n_points ] = loader->pp1;
1114 outline->points[outline->n_points + 1] = loader->pp2;
1115 outline->points[outline->n_points + 2] = loader->pp3;
1116 outline->points[outline->n_points + 3] = loader->pp4;
1117
1118 outline->tags[outline->n_points ] = 0;
1119 outline->tags[outline->n_points + 1] = 0;
1120 outline->tags[outline->n_points + 2] = 0;
1121 outline->tags[outline->n_points + 3] = 0;
1122
David Turner6aa260c2006-08-25 22:45:13 +00001123#ifdef TT_USE_BYTECODE_INTERPRETER
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001124
1125 {
1126 FT_Stream stream = loader->stream;
Werner Lemberg6da023d2010-05-20 15:38:00 +02001127 FT_UShort n_ins, max_ins;
1128 FT_ULong tmp;
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001129
1130
1131 /* TT_Load_Composite_Glyph only gives us the offset of instructions */
Werner Lemberg7c259462005-09-28 07:34:45 +00001132 /* so we read them here */
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001133 if ( FT_STREAM_SEEK( loader->ins_pos ) ||
Werner Lembergffa033b2005-08-19 08:56:29 +00001134 FT_READ_USHORT( n_ins ) )
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001135 return error;
1136
1137 FT_TRACE5(( " Instructions size = %d\n", n_ins ));
1138
1139 /* check it */
Werner Lemberg6da023d2010-05-20 15:38:00 +02001140 max_ins = ((TT_Face)loader->face)->max_profile.maxSizeOfInstructions;
1141 if ( n_ins > max_ins )
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001142 {
Werner Lemberg6da023d2010-05-20 15:38:00 +02001143 /* acroread ignores this field, so we only do a rough safety check */
1144 if ( (FT_Int)n_ins > loader->byte_len )
1145 {
1146 FT_TRACE1(( "TT_Process_Composite_Glyph: "
Werner Lembergae425e52010-06-29 12:31:08 +02001147 "too many instructions (%d) for glyph with length %d\n",
Werner Lemberg6da023d2010-05-20 15:38:00 +02001148 n_ins, loader->byte_len ));
1149 return TT_Err_Too_Many_Hints;
1150 }
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001151
Werner Lemberg6da023d2010-05-20 15:38:00 +02001152 tmp = loader->exec->glyphSize;
1153 error = Update_Max( loader->exec->memory,
1154 &tmp,
1155 sizeof ( FT_Byte ),
1156 (void*)&loader->exec->glyphIns,
1157 n_ins );
1158 loader->exec->glyphSize = (FT_UShort)tmp;
1159 if ( error )
1160 return error;
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001161 }
1162 else if ( n_ins == 0 )
1163 return TT_Err_Ok;
1164
1165 if ( FT_STREAM_READ( loader->exec->glyphIns, n_ins ) )
1166 return error;
1167
1168 loader->glyph->control_data = loader->exec->glyphIns;
1169 loader->glyph->control_len = n_ins;
1170 }
1171
1172#endif
1173
Werner Lembergffa033b2005-08-19 08:56:29 +00001174 tt_prepare_zone( &loader->zone, &loader->gloader->base,
1175 start_point, start_contour );
Werner Lemberga2da05c2006-06-25 06:27:27 +00001176
1177 /* Some points are likely touched during execution of */
1178 /* instructions on components. So let's untouch them. */
1179 for ( i = start_point; i < loader->zone.n_points; i++ )
Werner Lemberg780d7e02009-06-17 06:45:20 +02001180 loader->zone.tags[i] &= ~FT_CURVE_TAG_TOUCH_BOTH;
Werner Lemberga2da05c2006-06-25 06:27:27 +00001181
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001182 loader->zone.n_points += 4;
1183
1184 return TT_Hint_Glyph( loader, 1 );
1185 }
1186
1187
1188 /* Calculate the four phantom points. */
1189 /* The first two stand for horizontal origin and advance. */
1190 /* The last two stand for vertical origin and advance. */
1191#define TT_LOADER_SET_PP( loader ) \
1192 do { \
1193 (loader)->pp1.x = (loader)->bbox.xMin - (loader)->left_bearing; \
1194 (loader)->pp1.y = 0; \
1195 (loader)->pp2.x = (loader)->pp1.x + (loader)->advance; \
1196 (loader)->pp2.y = 0; \
1197 (loader)->pp3.x = 0; \
1198 (loader)->pp3.y = (loader)->top_bearing + (loader)->bbox.yMax; \
1199 (loader)->pp4.x = 0; \
1200 (loader)->pp4.y = (loader)->pp3.y - (loader)->vadvance; \
1201 } while ( 0 )
1202
1203
1204 /*************************************************************************/
1205 /* */
1206 /* <Function> */
David Turner8f43c712000-02-02 12:16:19 +00001207 /* load_truetype_glyph */
David Turnerd2b1f351999-12-16 23:11:37 +00001208 /* */
1209 /* <Description> */
Werner Lemberg78575dc2000-06-12 19:36:41 +00001210 /* Loads a given truetype glyph. Handles composites and uses a */
1211 /* TT_Loader object. */
David Turnerd2b1f351999-12-16 23:11:37 +00001212 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00001213 static FT_Error
Werner Lemberg91db04c2002-04-01 14:25:28 +00001214 load_truetype_glyph( TT_Loader loader,
David Turner77b68b82003-01-08 09:59:17 +00001215 FT_UInt glyph_index,
Werner Lembergf186ba62009-11-03 15:46:35 +01001216 FT_UInt recurse_count,
1217 FT_Bool header_only )
David Turnerd2b1f351999-12-16 23:11:37 +00001218 {
Werner Lembergc0aeef42009-11-08 07:58:05 +01001219 FT_Error error = TT_Err_Ok;
Werner Lemberg91db04c2002-04-01 14:25:28 +00001220 FT_Fixed x_scale, y_scale;
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001221 FT_ULong offset;
1222 TT_Face face = (TT_Face)loader->face;
1223 FT_GlyphLoader gloader = loader->gloader;
Werner Lemberg91db04c2002-04-01 14:25:28 +00001224 FT_Bool opened_frame = 0;
David Turnere49ab252000-05-16 23:44:38 +00001225
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001226#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001227 FT_Vector* deltas = NULL;
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001228#endif
1229
Graham Asher13217f22002-07-18 15:59:23 +00001230#ifdef FT_CONFIG_OPTION_INCREMENTAL
Werner Lemberg2b54eba2004-05-07 07:08:14 +00001231 FT_StreamRec inc_stream;
1232 FT_Data glyph_data;
1233 FT_Bool glyph_data_loaded = 0;
Werner Lemberg44bb3032004-04-25 20:15:11 +00001234#endif
1235
Werner Lemberg6ab56242003-06-04 07:59:58 +00001236
Werner Lemberg0f6f3672007-07-04 19:57:45 +00001237 /* some fonts have an incorrect value of `maxComponentDepth', */
1238 /* thus we allow depth 1 to catch the majority of them */
1239 if ( recurse_count > 1 &&
1240 recurse_count > face->max_profile.maxComponentDepth )
David Turner77b68b82003-01-08 09:59:17 +00001241 {
1242 error = TT_Err_Invalid_Composite;
1243 goto Exit;
1244 }
Werner Lemberg7f74a522002-07-26 09:09:10 +00001245
David Turner8f43c712000-02-02 12:16:19 +00001246 /* check glyph index */
Graham Asher13217f22002-07-18 15:59:23 +00001247 if ( glyph_index >= (FT_UInt)face->root.num_glyphs )
David Turnerd2b1f351999-12-16 23:11:37 +00001248 {
David Turner8f43c712000-02-02 12:16:19 +00001249 error = TT_Err_Invalid_Glyph_Index;
David Turner90f68b72000-06-23 12:26:14 +00001250 goto Exit;
David Turnerd2b1f351999-12-16 23:11:37 +00001251 }
1252
David Turner861ba622000-02-15 12:54:51 +00001253 loader->glyph_index = glyph_index;
David Turnere49ab252000-05-16 23:44:38 +00001254
Werner Lemberg78575dc2000-06-12 19:36:41 +00001255 if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
David Turnerd2b1f351999-12-16 23:11:37 +00001256 {
David Turner2f0fdb92004-06-21 21:16:56 +00001257 x_scale = ((TT_Size)loader->size)->metrics.x_scale;
1258 y_scale = ((TT_Size)loader->size)->metrics.y_scale;
David Turner8f43c712000-02-02 12:16:19 +00001259 }
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001260 else
1261 {
1262 x_scale = 0x10000L;
1263 y_scale = 0x10000L;
1264 }
David Turnerd2b1f351999-12-16 23:11:37 +00001265
Werner Lemberg422210b2009-11-03 08:11:02 +01001266 tt_get_metrics( loader, glyph_index );
David Turnerd2b1f351999-12-16 23:11:37 +00001267
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001268 /* Set `offset' to the start of the glyph relative to the start of */
Werner Lembergffa033b2005-08-19 08:56:29 +00001269 /* the `glyf' table, and `byte_len' to the length of the glyph in */
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001270 /* bytes. */
1271
Graham Asher13217f22002-07-18 15:59:23 +00001272#ifdef FT_CONFIG_OPTION_INCREMENTAL
David Turnere49ab252000-05-16 23:44:38 +00001273
Werner Lemberg7f74a522002-07-26 09:09:10 +00001274 /* If we are loading glyph data via the incremental interface, set */
1275 /* the loader stream to a memory stream reading the data returned */
1276 /* by the interface. */
Graham Asherce121822002-08-01 15:29:17 +00001277 if ( face->root.internal->incremental_interface )
Graham Asher13217f22002-07-18 15:59:23 +00001278 {
Graham Asherce121822002-08-01 15:29:17 +00001279 error = face->root.internal->incremental_interface->funcs->get_glyph_data(
1280 face->root.internal->incremental_interface->object,
1281 glyph_index, &glyph_data );
Werner Lemberg7f74a522002-07-26 09:09:10 +00001282 if ( error )
Graham Asher13217f22002-07-18 15:59:23 +00001283 goto Exit;
Werner Lemberg7f74a522002-07-26 09:09:10 +00001284
Graham Asherce121822002-08-01 15:29:17 +00001285 glyph_data_loaded = 1;
Werner Lemberg3c403e42002-08-06 21:47:40 +00001286 offset = 0;
Wu, Chia-I (吳佳一)9a2b3b62006-02-14 08:37:03 +00001287 loader->byte_len = glyph_data.length;
Werner Lemberg3c403e42002-08-06 21:47:40 +00001288
Werner Lembergb3d5e9c2002-07-28 05:05:24 +00001289 FT_MEM_ZERO( &inc_stream, sizeof ( inc_stream ) );
Werner Lemberg3c403e42002-08-06 21:47:40 +00001290 FT_Stream_OpenMemory( &inc_stream,
1291 glyph_data.pointer, glyph_data.length );
1292
Graham Asher13217f22002-07-18 15:59:23 +00001293 loader->stream = &inc_stream;
1294 }
1295 else
Werner Lemberg7f74a522002-07-26 09:09:10 +00001296
1297#endif /* FT_CONFIG_OPTION_INCREMENTAL */
Graham Asher13217f22002-07-18 15:59:23 +00001298
Werner Lembergffa033b2005-08-19 08:56:29 +00001299 offset = tt_face_get_location( face, glyph_index,
1300 (FT_UInt*)&loader->byte_len );
David Turnerd2b1f351999-12-16 23:11:37 +00001301
Werner Lembergbf391cb2008-01-10 08:47:08 +00001302 if ( loader->byte_len > 0 )
David Turner8f43c712000-02-02 12:16:19 +00001303 {
Werner Lembergfe6da502010-01-05 10:10:15 +01001304#ifdef FT_CONFIG_OPTION_INCREMENTAL
Werner Lemberg3445e4f2010-01-04 15:53:27 +01001305 /* for the incremental interface, `glyf_offset' is always zero */
1306 if ( !loader->glyf_offset &&
1307 !face->root.internal->incremental_interface )
Werner Lembergfe6da502010-01-05 10:10:15 +01001308#else
1309 if ( !loader->glyf_offset )
1310#endif /* FT_CONFIG_OPTION_INCREMENTAL */
Werner Lemberg1474f432008-12-09 06:51:56 +00001311 {
Werner Lemberg858abbe2009-06-26 06:15:41 +02001312 FT_TRACE2(( "no `glyf' table but non-zero `loca' entry\n" ));
Werner Lemberg1474f432008-12-09 06:51:56 +00001313 error = TT_Err_Invalid_Table;
1314 goto Exit;
1315 }
1316
Werner Lembergbf391cb2008-01-10 08:47:08 +00001317 error = face->access_glyph_frame( loader, glyph_index,
1318 loader->glyf_offset + offset,
1319 loader->byte_len );
1320 if ( error )
1321 goto Exit;
1322
1323 opened_frame = 1;
1324
Werner Lembergf186ba62009-11-03 15:46:35 +01001325 /* read glyph header first */
Werner Lembergbf391cb2008-01-10 08:47:08 +00001326 error = face->read_glyph_header( loader );
Werner Lembergf186ba62009-11-03 15:46:35 +01001327 if ( error || header_only )
Werner Lembergbf391cb2008-01-10 08:47:08 +00001328 goto Exit;
1329 }
1330
1331 if ( loader->byte_len == 0 || loader->n_contours == 0 )
1332 {
David Turner8f43c712000-02-02 12:16:19 +00001333 loader->bbox.xMin = 0;
1334 loader->bbox.xMax = 0;
1335 loader->bbox.yMin = 0;
1336 loader->bbox.yMax = 0;
David Turnerd2b1f351999-12-16 23:11:37 +00001337
Werner Lembergf186ba62009-11-03 15:46:35 +01001338 if ( header_only )
1339 goto Exit;
1340
Chris Liddell10cf3882010-02-18 17:09:30 +01001341 /* must initialize points before (possibly) overriding */
1342 /* glyph metrics from the incremental interface */
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001343 TT_LOADER_SET_PP( loader );
David Turnerd2b1f351999-12-16 23:11:37 +00001344
Chris Liddell10cf3882010-02-18 17:09:30 +01001345#ifdef FT_CONFIG_OPTION_INCREMENTAL
1346 tt_get_metrics_incr_overrides( loader, glyph_index );
1347#endif
1348
Werner Lemberg44bb3032004-04-25 20:15:11 +00001349#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001350
Werner Lemberg44bb3032004-04-25 20:15:11 +00001351 if ( ((TT_Face)(loader->face))->doblend )
1352 {
1353 /* this must be done before scaling */
1354 FT_Memory memory = loader->face->memory;
1355
1356
Werner Lemberg5afaa672004-06-28 14:19:15 +00001357 error = TT_Vary_Get_Glyph_Deltas( (TT_Face)(loader->face),
1358 glyph_index, &deltas, 4 );
David Turnerc28b8c12004-06-24 20:18:24 +00001359 if ( error )
Werner Lemberg44bb3032004-04-25 20:15:11 +00001360 goto Exit;
1361
1362 loader->pp1.x += deltas[0].x; loader->pp1.y += deltas[0].y;
1363 loader->pp2.x += deltas[1].x; loader->pp2.y += deltas[1].y;
1364 loader->pp3.x += deltas[2].x; loader->pp3.y += deltas[2].y;
1365 loader->pp4.x += deltas[3].x; loader->pp4.y += deltas[3].y;
1366
1367 FT_FREE( deltas );
1368 }
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001369
Werner Lemberg44bb3032004-04-25 20:15:11 +00001370#endif
1371
Werner Lemberg78575dc2000-06-12 19:36:41 +00001372 if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
Werner Lemberg8bb07e62004-03-27 08:43:17 +00001373 {
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001374 loader->pp1.x = FT_MulFix( loader->pp1.x, x_scale );
David Turner8f43c712000-02-02 12:16:19 +00001375 loader->pp2.x = FT_MulFix( loader->pp2.x, x_scale );
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001376 loader->pp3.y = FT_MulFix( loader->pp3.y, y_scale );
Werner Lemberg8bb07e62004-03-27 08:43:17 +00001377 loader->pp4.y = FT_MulFix( loader->pp4.y, y_scale );
1378 }
David Turnerd2b1f351999-12-16 23:11:37 +00001379
Werner Lemberg1429db62001-04-02 23:54:01 +00001380 error = TT_Err_Ok;
David Turner90f68b72000-06-23 12:26:14 +00001381 goto Exit;
David Turner8f43c712000-02-02 12:16:19 +00001382 }
David Turnerd2b1f351999-12-16 23:11:37 +00001383
Chris Liddell10cf3882010-02-18 17:09:30 +01001384 /* must initialize points before (possibly) overriding */
1385 /* glyph metrics from the incremental interface */
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001386 TT_LOADER_SET_PP( loader );
Werner Lemberg8bb07e62004-03-27 08:43:17 +00001387
Chris Liddell10cf3882010-02-18 17:09:30 +01001388#ifdef FT_CONFIG_OPTION_INCREMENTAL
1389 tt_get_metrics_incr_overrides( loader, glyph_index );
1390#endif
1391
Werner Lemberg78575dc2000-06-12 19:36:41 +00001392 /***********************************************************************/
1393 /***********************************************************************/
1394 /***********************************************************************/
David Turnerd2b1f351999-12-16 23:11:37 +00001395
Werner Lemberg78575dc2000-06-12 19:36:41 +00001396 /* if it is a simple glyph, load it */
1397
Werner Lembergbf391cb2008-01-10 08:47:08 +00001398 if ( loader->n_contours > 0 )
David Turner8f43c712000-02-02 12:16:19 +00001399 {
David Turner994d7742000-06-25 04:49:19 +00001400 error = face->read_simple_glyph( loader );
Werner Lemberga929ba92000-06-25 06:47:11 +00001401 if ( error )
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001402 goto Exit;
Werner Lembergbd5ae402000-07-05 04:32:02 +00001403
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001404 /* all data have been read */
1405 face->forget_glyph_frame( loader );
1406 opened_frame = 0;
Werner Lemberg5811c7c2000-07-02 13:53:16 +00001407
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001408 error = TT_Process_Simple_Glyph( loader );
Werner Lembergdcd2e142000-06-25 07:43:15 +00001409 if ( error )
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001410 goto Exit;
David Turnerf0df85b2000-06-22 00:17:42 +00001411
1412 FT_GlyphLoader_Add( gloader );
David Turner8f43c712000-02-02 12:16:19 +00001413 }
David Turner8f43c712000-02-02 12:16:19 +00001414
Werner Lemberg78575dc2000-06-12 19:36:41 +00001415 /***********************************************************************/
1416 /***********************************************************************/
1417 /***********************************************************************/
1418
1419 /* otherwise, load a composite! */
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001420 else if ( loader->n_contours == -1 )
David Turner8f43c712000-02-02 12:16:19 +00001421 {
Werner Lemberg6f99c882007-05-19 07:01:49 +00001422 FT_UInt start_point;
1423 FT_UInt start_contour;
1424 FT_ULong ins_pos; /* position of composite instructions, if any */
Werner Lemberga929ba92000-06-25 06:47:11 +00001425
Werner Lembergbd5ae402000-07-05 04:32:02 +00001426
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001427 start_point = gloader->base.outline.n_points;
1428 start_contour = gloader->base.outline.n_contours;
1429
David Turner8f43c712000-02-02 12:16:19 +00001430 /* for each subglyph, read composite header */
David Turner994d7742000-06-25 04:49:19 +00001431 error = face->read_composite_glyph( loader );
Werner Lemberga929ba92000-06-25 06:47:11 +00001432 if ( error )
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001433 goto Exit;
David Turnered7f62a2000-03-28 11:19:28 +00001434
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001435 /* store the offset of instructions */
David Turnerc6a92202000-07-04 18:12:13 +00001436 ins_pos = loader->ins_pos;
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001437
1438 /* all data we need are read */
David Turner994d7742000-06-25 04:49:19 +00001439 face->forget_glyph_frame( loader );
David Turner90f68b72000-06-23 12:26:14 +00001440 opened_frame = 0;
1441
Werner Lemberg44bb3032004-04-25 20:15:11 +00001442#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
1443
1444 if ( face->doblend )
1445 {
1446 FT_Int i, limit;
1447 FT_SubGlyph subglyph;
1448 FT_Memory memory = face->root.memory;
1449
1450
1451 /* this provides additional offsets */
1452 /* for each component's translation */
1453
Werner Lemberge12ed562007-06-17 05:31:23 +00001454 if ( ( error = TT_Vary_Get_Glyph_Deltas(
1455 face,
1456 glyph_index,
1457 &deltas,
1458 gloader->current.num_subglyphs + 4 )) != 0 )
Werner Lemberg44bb3032004-04-25 20:15:11 +00001459 goto Exit;
1460
Werner Lemberg44bb3032004-04-25 20:15:11 +00001461 subglyph = gloader->current.subglyphs + gloader->base.num_subglyphs;
1462 limit = gloader->current.num_subglyphs;
1463
1464 for ( i = 0; i < limit; ++i, ++subglyph )
1465 {
1466 if ( subglyph->flags & ARGS_ARE_XY_VALUES )
1467 {
suzuki toshiya9206eba2009-08-01 00:32:17 +09001468 /* XXX: overflow check for subglyph->{arg1,arg2}. */
1469 /* deltas[i].{x,y} must be within signed 16-bit, */
1470 /* but the restriction of summed delta is not clear */
1471 subglyph->arg1 += (FT_Int16)deltas[i].x;
1472 subglyph->arg2 += (FT_Int16)deltas[i].y;
Werner Lemberg44bb3032004-04-25 20:15:11 +00001473 }
1474 }
1475
1476 loader->pp1.x += deltas[i + 0].x; loader->pp1.y += deltas[i + 0].y;
1477 loader->pp2.x += deltas[i + 1].x; loader->pp2.y += deltas[i + 1].y;
1478 loader->pp3.x += deltas[i + 2].x; loader->pp3.y += deltas[i + 2].y;
1479 loader->pp4.x += deltas[i + 3].x; loader->pp4.y += deltas[i + 3].y;
1480
1481 FT_FREE( deltas );
1482 }
1483
1484#endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
1485
1486 if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
1487 {
1488 loader->pp1.x = FT_MulFix( loader->pp1.x, x_scale );
1489 loader->pp2.x = FT_MulFix( loader->pp2.x, x_scale );
1490 loader->pp3.y = FT_MulFix( loader->pp3.y, y_scale );
1491 loader->pp4.y = FT_MulFix( loader->pp4.y, y_scale );
1492 }
1493
David Turnered7f62a2000-03-28 11:19:28 +00001494 /* if the flag FT_LOAD_NO_RECURSE is set, we return the subglyph */
Werner Lemberg78575dc2000-06-12 19:36:41 +00001495 /* `as is' in the glyph slot (the client application will be */
Werner Lembergeed446d2002-08-16 12:46:52 +00001496 /* responsible for interpreting these data)... */
David Turnered7f62a2000-03-28 11:19:28 +00001497 if ( loader->load_flags & FT_LOAD_NO_RECURSE )
1498 {
David Turnerf0df85b2000-06-22 00:17:42 +00001499 FT_GlyphLoader_Add( gloader );
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001500 loader->glyph->format = FT_GLYPH_FORMAT_COMPOSITE;
Werner Lembergbd5ae402000-07-05 04:32:02 +00001501
David Turner90f68b72000-06-23 12:26:14 +00001502 goto Exit;
David Turnered7f62a2000-03-28 11:19:28 +00001503 }
1504
David Turner8f43c712000-02-02 12:16:19 +00001505 /*********************************************************************/
Werner Lembergdcd2e142000-06-25 07:43:15 +00001506 /*********************************************************************/
1507 /*********************************************************************/
1508
David Turner8f43c712000-02-02 12:16:19 +00001509 {
Werner Lemberg57a94c42008-05-25 16:49:29 +00001510 FT_UInt n, num_base_points;
1511 FT_SubGlyph subglyph = 0;
Werner Lembergbd5ae402000-07-05 04:32:02 +00001512
Werner Lemberg57a94c42008-05-25 16:49:29 +00001513 FT_UInt num_points = start_point;
1514 FT_UInt num_subglyphs = gloader->current.num_subglyphs;
1515 FT_UInt num_base_subgs = gloader->base.num_subglyphs;
Werner Lembergbd5ae402000-07-05 04:32:02 +00001516
Werner Lemberg57a94c42008-05-25 16:49:29 +00001517 FT_Stream old_stream = loader->stream;
Werner Lemberg6da023d2010-05-20 15:38:00 +02001518 FT_Int old_byte_len = loader->byte_len;
Werner Lemberg6f99c882007-05-19 07:01:49 +00001519
David Turnerc3128612000-06-23 05:02:13 +00001520
David Turnerf0df85b2000-06-22 00:17:42 +00001521 FT_GlyphLoader_Add( gloader );
Werner Lembergbd5ae402000-07-05 04:32:02 +00001522
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001523 /* read each subglyph independently */
Werner Lembergffa033b2005-08-19 08:56:29 +00001524 for ( n = 0; n < num_subglyphs; n++ )
David Turnerd2b1f351999-12-16 23:11:37 +00001525 {
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001526 FT_Vector pp[4];
David Turnere49ab252000-05-16 23:44:38 +00001527
Werner Lembergdcd2e142000-06-25 07:43:15 +00001528
Werner Lemberga929ba92000-06-25 06:47:11 +00001529 /* Each time we call load_truetype_glyph in this loop, the */
1530 /* value of `gloader.base.subglyphs' can change due to table */
1531 /* reallocations. We thus need to recompute the subglyph */
1532 /* pointer on each iteration. */
David Turnerf0df85b2000-06-22 00:17:42 +00001533 subglyph = gloader->base.subglyphs + num_base_subgs + n;
Werner Lemberg78575dc2000-06-12 19:36:41 +00001534
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001535 pp[0] = loader->pp1;
1536 pp[1] = loader->pp2;
1537 pp[2] = loader->pp3;
1538 pp[3] = loader->pp4;
David Turnerd2b1f351999-12-16 23:11:37 +00001539
David Turnerf0df85b2000-06-22 00:17:42 +00001540 num_base_points = gloader->base.outline.n_points;
David Turnere49ab252000-05-16 23:44:38 +00001541
David Turner77b68b82003-01-08 09:59:17 +00001542 error = load_truetype_glyph( loader, subglyph->index,
Werner Lembergf186ba62009-11-03 15:46:35 +01001543 recurse_count + 1, FALSE );
Werner Lemberg78575dc2000-06-12 19:36:41 +00001544 if ( error )
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001545 goto Exit;
David Turner3475e7f2000-05-17 20:56:01 +00001546
David Turner61d6b2b2001-05-16 17:49:07 +00001547 /* restore subglyph pointer */
David Turnerf0df85b2000-06-22 00:17:42 +00001548 subglyph = gloader->base.subglyphs + num_base_subgs + n;
1549
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001550 if ( !( subglyph->flags & USE_MY_METRICS ) )
David Turner7bb7fed2000-02-28 11:23:36 +00001551 {
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001552 loader->pp1 = pp[0];
1553 loader->pp2 = pp[1];
1554 loader->pp3 = pp[2];
1555 loader->pp4 = pp[3];
David Turnerd2b1f351999-12-16 23:11:37 +00001556 }
David Turnere49ab252000-05-16 23:44:38 +00001557
Werner Lembergdcd2e142000-06-25 07:43:15 +00001558 num_points = gloader->base.outline.n_points;
David Turnere49ab252000-05-16 23:44:38 +00001559
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001560 if ( num_points == num_base_points )
1561 continue;
David Turnere49ab252000-05-16 23:44:38 +00001562
Werner Lemberg6f99c882007-05-19 07:01:49 +00001563 /* gloader->base.outline consists of three parts: */
1564 /* 0 -(1)-> start_point -(2)-> num_base_points -(3)-> n_points. */
1565 /* */
1566 /* (1): exists from the beginning */
1567 /* (2): components that have been loaded so far */
1568 /* (3): the newly loaded component */
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001569 TT_Process_Composite_Component( loader, subglyph, start_point,
1570 num_base_points );
David Turnerd2b1f351999-12-16 23:11:37 +00001571 }
David Turnere49ab252000-05-16 23:44:38 +00001572
Werner Lemberg6da023d2010-05-20 15:38:00 +02001573 loader->stream = old_stream;
1574 loader->byte_len = old_byte_len;
David Turnerd2b1f351999-12-16 23:11:37 +00001575
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001576 /* process the glyph */
1577 loader->ins_pos = ins_pos;
1578 if ( IS_HINTED( loader->load_flags ) &&
David Turnerd2b1f351999-12-16 23:11:37 +00001579
David Turner6aa260c2006-08-25 22:45:13 +00001580#ifdef TT_USE_BYTECODE_INTERPRETER
Werner Lemberg78575dc2000-06-12 19:36:41 +00001581
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001582 subglyph->flags & WE_HAVE_INSTR &&
David Turnere49ab252000-05-16 23:44:38 +00001583
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001584#endif
Werner Lemberg78575dc2000-06-12 19:36:41 +00001585
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001586 num_points > start_point )
1587 TT_Process_Composite_Glyph( loader, start_point, start_contour );
Werner Lembergdcd2e142000-06-25 07:43:15 +00001588
David Turnerd2b1f351999-12-16 23:11:37 +00001589 }
1590 }
David Turner77b68b82003-01-08 09:59:17 +00001591 else
1592 {
Werner Lemberg6f99c882007-05-19 07:01:49 +00001593 /* invalid composite count (negative but not -1) */
David Turner77b68b82003-01-08 09:59:17 +00001594 error = TT_Err_Invalid_Outline;
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001595 goto Exit;
David Turner77b68b82003-01-08 09:59:17 +00001596 }
David Turnerd2b1f351999-12-16 23:11:37 +00001597
Werner Lemberg78575dc2000-06-12 19:36:41 +00001598 /***********************************************************************/
1599 /***********************************************************************/
1600 /***********************************************************************/
David Turnerd2b1f351999-12-16 23:11:37 +00001601
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001602 Exit:
1603
Werner Lemberga929ba92000-06-25 06:47:11 +00001604 if ( opened_frame )
David Turner994d7742000-06-25 04:49:19 +00001605 face->forget_glyph_frame( loader );
David Turner90f68b72000-06-23 12:26:14 +00001606
Graham Asherce121822002-08-01 15:29:17 +00001607#ifdef FT_CONFIG_OPTION_INCREMENTAL
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001608
Werner Lemberg3c403e42002-08-06 21:47:40 +00001609 if ( glyph_data_loaded )
1610 face->root.internal->incremental_interface->funcs->free_glyph_data(
1611 face->root.internal->incremental_interface->object,
1612 &glyph_data );
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001613
Graham Asherce121822002-08-01 15:29:17 +00001614#endif
1615
David Turnere49ab252000-05-16 23:44:38 +00001616 return error;
David Turner8f43c712000-02-02 12:16:19 +00001617 }
1618
1619
Graham Asher13217f22002-07-18 15:59:23 +00001620 static FT_Error
Werner Lemberg6f99c882007-05-19 07:01:49 +00001621 compute_glyph_metrics( TT_Loader loader,
1622 FT_UInt glyph_index )
David Turner8f43c712000-02-02 12:16:19 +00001623 {
David Turnerf9b8dec2000-06-16 19:34:52 +00001624 FT_BBox bbox;
David Turnerc3128612000-06-23 05:02:13 +00001625 TT_Face face = (TT_Face)loader->face;
Werner Lembergcf24d512001-06-18 14:23:45 +00001626 FT_Fixed y_scale;
David Turner8f43c712000-02-02 12:16:19 +00001627 TT_GlyphSlot glyph = loader->glyph;
David Turnerc3128612000-06-23 05:02:13 +00001628 TT_Size size = (TT_Size)loader->size;
David Turnere49ab252000-05-16 23:44:38 +00001629
Werner Lembergdcd2e142000-06-25 07:43:15 +00001630
Werner Lemberg78575dc2000-06-12 19:36:41 +00001631 y_scale = 0x10000L;
1632 if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
David Turner8f43c712000-02-02 12:16:19 +00001633 y_scale = size->root.metrics.y_scale;
David Turnere49ab252000-05-16 23:44:38 +00001634
David Turnerb08fe2d2002-08-27 20:20:29 +00001635 if ( glyph->format != FT_GLYPH_FORMAT_COMPOSITE )
David Turnered7f62a2000-03-28 11:19:28 +00001636 FT_Outline_Get_CBox( &glyph->outline, &bbox );
David Turnered7f62a2000-03-28 11:19:28 +00001637 else
1638 bbox = loader->bbox;
David Turnerd2b1f351999-12-16 23:11:37 +00001639
Werner Lemberg6f99c882007-05-19 07:01:49 +00001640 /* get the device-independent horizontal advance; it is scaled later */
1641 /* by the base layer. */
Behdad Esfahbod8c82ec52011-04-21 08:21:37 +02001642 glyph->linearHoriAdvance = loader->linear;
David Turnerd2b1f351999-12-16 23:11:37 +00001643
1644 glyph->metrics.horiBearingX = bbox.xMin;
1645 glyph->metrics.horiBearingY = bbox.yMax;
David Turner8f43c712000-02-02 12:16:19 +00001646 glyph->metrics.horiAdvance = loader->pp2.x - loader->pp1.x;
David Turnerd2b1f351999-12-16 23:11:37 +00001647
Bram Tassyns4694ea22009-09-02 13:06:33 +02001648 /* adjust advance width to the value contained in the hdmx table */
1649 if ( !face->postscript.isFixedPitch &&
1650 IS_HINTED( loader->load_flags ) )
1651 {
1652 FT_Byte* widthp;
David Turnerd2b1f351999-12-16 23:11:37 +00001653
Bram Tassyns4694ea22009-09-02 13:06:33 +02001654
1655 widthp = tt_face_get_device_metrics( face,
1656 size->root.metrics.x_ppem,
1657 glyph_index );
1658
1659 if ( widthp )
1660 glyph->metrics.horiAdvance = *widthp << 6;
1661 }
1662
1663 /* set glyph dimensions */
1664 glyph->metrics.width = bbox.xMax - bbox.xMin;
1665 glyph->metrics.height = bbox.yMax - bbox.yMin;
1666
1667 /* Now take care of vertical metrics. In the case where there is */
1668 /* no vertical information within the font (relatively common), */
1669 /* create some metrics manually */
David Turnerd2b1f351999-12-16 23:11:37 +00001670 {
Werner Lemberg1723dcc2006-01-15 07:30:32 +00001671 FT_Pos top; /* scaled vertical top side bearing */
1672 FT_Pos advance; /* scaled vertical advance height */
David Turnerd2b1f351999-12-16 23:11:37 +00001673
Werner Lemberg56a4d872004-06-03 07:56:21 +00001674
Graham Asher13217f22002-07-18 15:59:23 +00001675 /* Get the unscaled top bearing and advance height. */
Werner Lembergd30062d2009-09-08 07:06:54 +02001676 if ( face->vertical_info &&
David Turnerd2b1f351999-12-16 23:11:37 +00001677 face->vertical.number_Of_VMetrics > 0 )
1678 {
Wu, Chia-I (吳佳一)212aee02006-01-15 06:24:53 +00001679 top = (FT_Short)FT_DivFix( loader->pp3.y - bbox.yMax,
1680 y_scale );
Werner Lemberg49f4d342005-06-16 19:07:08 +00001681
1682 if ( loader->pp3.y <= loader->pp4.y )
Wu, Chia-I (吳佳一)212aee02006-01-15 06:24:53 +00001683 advance = 0;
Werner Lemberg49f4d342005-06-16 19:07:08 +00001684 else
Wu, Chia-I (吳佳一)212aee02006-01-15 06:24:53 +00001685 advance = (FT_UShort)FT_DivFix( loader->pp3.y - loader->pp4.y,
1686 y_scale );
David Turnerd2b1f351999-12-16 23:11:37 +00001687 }
1688 else
1689 {
Wu, Chia-I (吳佳一)212aee02006-01-15 06:24:53 +00001690 FT_Pos height;
Werner Lemberg49f4d342005-06-16 19:07:08 +00001691
1692
1693 /* XXX Compute top side bearing and advance height in */
1694 /* Get_VMetrics instead of here. */
David Turnerd2b1f351999-12-16 23:11:37 +00001695
Werner Lemberg78575dc2000-06-12 19:36:41 +00001696 /* NOTE: The OS/2 values are the only `portable' ones, */
1697 /* which is why we use them, if there is an OS/2 */
1698 /* table in the font. Otherwise, we use the */
1699 /* values defined in the horizontal header. */
Werner Lemberg49f4d342005-06-16 19:07:08 +00001700
Wu, Chia-I (吳佳一)212aee02006-01-15 06:24:53 +00001701 height = (FT_Short)FT_DivFix( bbox.yMax - bbox.yMin,
1702 y_scale );
Werner Lemberg91db04c2002-04-01 14:25:28 +00001703 if ( face->os2.version != 0xFFFFU )
Wu, Chia-I (吳佳一)212aee02006-01-15 06:24:53 +00001704 advance = (FT_Pos)( face->os2.sTypoAscender -
1705 face->os2.sTypoDescender );
David Turnerd2b1f351999-12-16 23:11:37 +00001706 else
Wu, Chia-I (吳佳一)212aee02006-01-15 06:24:53 +00001707 advance = (FT_Pos)( face->horizontal.Ascender -
1708 face->horizontal.Descender );
Werner Lemberg49f4d342005-06-16 19:07:08 +00001709
Wu, Chia-I (吳佳一)212aee02006-01-15 06:24:53 +00001710 top = ( advance - height ) / 2;
David Turnerd2b1f351999-12-16 23:11:37 +00001711 }
1712
Graham Asher46960df2003-02-13 17:49:27 +00001713#ifdef FT_CONFIG_OPTION_INCREMENTAL
Graham Asher46960df2003-02-13 17:49:27 +00001714 {
Wu, Chia-I (吳佳一)212aee02006-01-15 06:24:53 +00001715 FT_Incremental_InterfaceRec* incr;
1716 FT_Incremental_MetricsRec metrics;
1717 FT_Error error;
Graham Asher46960df2003-02-13 17:49:27 +00001718
Werner Lembergb442ca12003-04-23 15:50:27 +00001719
Wu, Chia-I (吳佳一)212aee02006-01-15 06:24:53 +00001720 incr = face->root.internal->incremental_interface;
Graham Asher46960df2003-02-13 17:49:27 +00001721
Wu, Chia-I (吳佳一)212aee02006-01-15 06:24:53 +00001722 /* If this is an incrementally loaded font see if there are */
1723 /* overriding metrics for this glyph. */
1724 if ( incr && incr->funcs->get_glyph_metrics )
1725 {
1726 metrics.bearing_x = 0;
1727 metrics.bearing_y = top;
1728 metrics.advance = advance;
Werner Lemberg1723dcc2006-01-15 07:30:32 +00001729
Wu, Chia-I (吳佳一)212aee02006-01-15 06:24:53 +00001730 error = incr->funcs->get_glyph_metrics( incr->object,
1731 glyph_index,
1732 TRUE,
1733 &metrics );
1734 if ( error )
1735 return error;
Graham Asher46960df2003-02-13 17:49:27 +00001736
Wu, Chia-I (吳佳一)212aee02006-01-15 06:24:53 +00001737 top = metrics.bearing_y;
1738 advance = metrics.advance;
1739 }
Graham Asher46960df2003-02-13 17:49:27 +00001740 }
1741
Werner Lemberg8bb07e62004-03-27 08:43:17 +00001742 /* GWW: Do vertical metrics get loaded incrementally too? */
1743
Graham Asher46960df2003-02-13 17:49:27 +00001744#endif /* FT_CONFIG_OPTION_INCREMENTAL */
1745
Wu, Chia-I (吳佳一)212aee02006-01-15 06:24:53 +00001746 glyph->linearVertAdvance = advance;
1747
David Turnerd2b1f351999-12-16 23:11:37 +00001748 /* scale the metrics */
Werner Lemberg78575dc2000-06-12 19:36:41 +00001749 if ( !( loader->load_flags & FT_LOAD_NO_SCALE ) )
David Turnerd2b1f351999-12-16 23:11:37 +00001750 {
Werner Lembergf186ba62009-11-03 15:46:35 +01001751 top = FT_MulFix( top, y_scale );
Wu, Chia-I (吳佳一)212aee02006-01-15 06:24:53 +00001752 advance = FT_MulFix( advance, y_scale );
David Turnerd2b1f351999-12-16 23:11:37 +00001753 }
David Turnerd2b1f351999-12-16 23:11:37 +00001754
Werner Lemberga929ba92000-06-25 06:47:11 +00001755 /* XXX: for now, we have no better algorithm for the lsb, but it */
1756 /* should work fine. */
1757 /* */
Bram Tassyns4694ea22009-09-02 13:06:33 +02001758 glyph->metrics.vertBearingX = glyph->metrics.horiBearingX -
1759 glyph->metrics.horiAdvance / 2;
David Turnerd2b1f351999-12-16 23:11:37 +00001760 glyph->metrics.vertBearingY = top;
1761 glyph->metrics.vertAdvance = advance;
1762 }
1763
Graham Asher13217f22002-07-18 15:59:23 +00001764 return 0;
David Turner8f43c712000-02-02 12:16:19 +00001765 }
David Turnerd2b1f351999-12-16 23:11:37 +00001766
David Turnerd2b1f351999-12-16 23:11:37 +00001767
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001768#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
Werner Lembergffa033b2005-08-19 08:56:29 +00001769
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001770 static FT_Error
1771 load_sbit_image( TT_Size size,
1772 TT_GlyphSlot glyph,
1773 FT_UInt glyph_index,
1774 FT_Int32 load_flags )
1775 {
1776 TT_Face face;
1777 SFNT_Service sfnt;
1778 FT_Stream stream;
1779 FT_Error error;
1780 TT_SBit_MetricsRec metrics;
1781
Werner Lembergffa033b2005-08-19 08:56:29 +00001782
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001783 face = (TT_Face)glyph->face;
1784 sfnt = (SFNT_Service)face->sfnt;
1785 stream = face->root.stream;
1786
1787 error = sfnt->load_sbit_image( face,
Wu, Chia-I (吳佳一)fa7d6ab2006-01-13 12:21:31 +00001788 size->strike_index,
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001789 glyph_index,
1790 (FT_Int)load_flags,
1791 stream,
1792 &glyph->bitmap,
1793 &metrics );
1794 if ( !error )
1795 {
1796 glyph->outline.n_points = 0;
1797 glyph->outline.n_contours = 0;
1798
1799 glyph->metrics.width = (FT_Pos)metrics.width << 6;
1800 glyph->metrics.height = (FT_Pos)metrics.height << 6;
1801
1802 glyph->metrics.horiBearingX = (FT_Pos)metrics.horiBearingX << 6;
1803 glyph->metrics.horiBearingY = (FT_Pos)metrics.horiBearingY << 6;
1804 glyph->metrics.horiAdvance = (FT_Pos)metrics.horiAdvance << 6;
1805
1806 glyph->metrics.vertBearingX = (FT_Pos)metrics.vertBearingX << 6;
1807 glyph->metrics.vertBearingY = (FT_Pos)metrics.vertBearingY << 6;
1808 glyph->metrics.vertAdvance = (FT_Pos)metrics.vertAdvance << 6;
1809
1810 glyph->format = FT_GLYPH_FORMAT_BITMAP;
Werner Lembergf186ba62009-11-03 15:46:35 +01001811
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001812 if ( load_flags & FT_LOAD_VERTICAL_LAYOUT )
1813 {
1814 glyph->bitmap_left = metrics.vertBearingX;
1815 glyph->bitmap_top = metrics.vertBearingY;
1816 }
1817 else
1818 {
1819 glyph->bitmap_left = metrics.horiBearingX;
1820 glyph->bitmap_top = metrics.horiBearingY;
1821 }
1822 }
1823
1824 return error;
1825 }
Werner Lembergffa033b2005-08-19 08:56:29 +00001826
1827#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001828
1829
1830 static FT_Error
1831 tt_loader_init( TT_Loader loader,
1832 TT_Size size,
1833 TT_GlyphSlot glyph,
Werner Lembergf186ba62009-11-03 15:46:35 +01001834 FT_Int32 load_flags,
1835 FT_Bool glyf_table_only )
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001836 {
Werner Lembergffa033b2005-08-19 08:56:29 +00001837 TT_Face face;
1838 FT_Stream stream;
Werner Lemberg18931a52011-02-01 07:08:43 +01001839 FT_Bool pedantic = FT_BOOL( load_flags & FT_LOAD_PEDANTIC );
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001840
1841
Werner Lembergffa033b2005-08-19 08:56:29 +00001842 face = (TT_Face)glyph->face;
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001843 stream = face->root.stream;
1844
1845 FT_MEM_ZERO( loader, sizeof ( TT_LoaderRec ) );
1846
David Turner6aa260c2006-08-25 22:45:13 +00001847#ifdef TT_USE_BYTECODE_INTERPRETER
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001848
1849 /* load execution context */
Werner Lembergf186ba62009-11-03 15:46:35 +01001850 if ( IS_HINTED( load_flags ) && !glyf_table_only )
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001851 {
1852 TT_ExecContext exec;
Werner Lemberg91959bf2006-11-22 10:36:55 +00001853 FT_Bool grayscale;
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001854
1855
David Turner384be232007-01-05 15:32:01 +00001856 if ( !size->cvt_ready )
1857 {
Werner Lemberg18931a52011-02-01 07:08:43 +01001858 FT_Error error = tt_size_ready_bytecode( size, pedantic );
Werner Lemberg91a97162011-01-30 20:12:54 +01001859
1860
David Turner384be232007-01-05 15:32:01 +00001861 if ( error )
1862 return error;
1863 }
1864
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001865 /* query new execution context */
1866 exec = size->debug ? size->context
1867 : ( (TT_Driver)FT_FACE_DRIVER( face ) )->context;
1868 if ( !exec )
1869 return TT_Err_Could_Not_Find_Context;
1870
Werner Lemberg91959bf2006-11-22 10:36:55 +00001871 grayscale =
1872 FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) != FT_RENDER_MODE_MONO );
1873
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001874 TT_Load_Context( exec, face, size );
1875
Werner Lemberg91959bf2006-11-22 10:36:55 +00001876 /* a change from mono to grayscale rendering (and vice versa) */
1877 /* requires a re-execution of the CVT program */
1878 if ( grayscale != exec->grayscale )
1879 {
1880 FT_UInt i;
1881
1882
Werner Lemberg6abb9232010-09-14 09:02:10 +02001883 FT_TRACE4(( "tt_loader_init: grayscale change,"
1884 " re-executing `prep' table\n" ));
1885
Werner Lemberg91959bf2006-11-22 10:36:55 +00001886 exec->grayscale = grayscale;
1887
1888 for ( i = 0; i < size->cvt_size; i++ )
1889 size->cvt[i] = FT_MulFix( face->cvt[i], size->ttmetrics.scale );
Werner Lemberg18931a52011-02-01 07:08:43 +01001890 tt_size_run_prep( size, pedantic );
Werner Lemberg91959bf2006-11-22 10:36:55 +00001891 }
1892
Werner Lemberg6f99c882007-05-19 07:01:49 +00001893 /* see whether the cvt program has disabled hinting */
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001894 if ( exec->GS.instruct_control & 1 )
1895 load_flags |= FT_LOAD_NO_HINTING;
1896
Werner Lemberg6f99c882007-05-19 07:01:49 +00001897 /* load default graphics state -- if needed */
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001898 if ( exec->GS.instruct_control & 2 )
1899 exec->GS = tt_default_graphics_state;
1900
1901 exec->pedantic_hinting = FT_BOOL( load_flags & FT_LOAD_PEDANTIC );
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001902 loader->exec = exec;
1903 loader->instructions = exec->glyphIns;
1904 }
1905
David Turner6aa260c2006-08-25 22:45:13 +00001906#endif /* TT_USE_BYTECODE_INTERPRETER */
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001907
Werner Lemberg6f99c882007-05-19 07:01:49 +00001908 /* seek to the beginning of the glyph table -- for Type 42 fonts */
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001909 /* the table might be accessed from a Postscript stream or something */
1910 /* else... */
1911
1912#ifdef FT_CONFIG_OPTION_INCREMENTAL
1913
1914 if ( face->root.internal->incremental_interface )
1915 loader->glyf_offset = 0;
1916 else
1917
1918#endif
1919
1920 {
1921 FT_Error error = face->goto_table( face, TTAG_glyf, stream, 0 );
Werner Lembergffa033b2005-08-19 08:56:29 +00001922
1923
Werner Lemberg1474f432008-12-09 06:51:56 +00001924 if ( error == TT_Err_Table_Missing )
1925 loader->glyf_offset = 0;
1926 else if ( error )
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001927 {
Werner Lemberg858abbe2009-06-26 06:15:41 +02001928 FT_ERROR(( "tt_loader_init: could not access glyph table\n" ));
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001929 return error;
1930 }
Werner Lemberg1474f432008-12-09 06:51:56 +00001931 else
1932 loader->glyf_offset = FT_STREAM_POS();
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001933 }
1934
1935 /* get face's glyph loader */
Werner Lembergf186ba62009-11-03 15:46:35 +01001936 if ( !glyf_table_only )
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001937 {
1938 FT_GlyphLoader gloader = glyph->internal->loader;
1939
Werner Lembergffa033b2005-08-19 08:56:29 +00001940
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001941 FT_GlyphLoader_Rewind( gloader );
1942 loader->gloader = gloader;
1943 }
1944
Werner Lemberg1474f432008-12-09 06:51:56 +00001945 loader->load_flags = load_flags;
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00001946
1947 loader->face = (FT_Face)face;
1948 loader->size = (FT_Size)size;
1949 loader->glyph = (FT_GlyphSlot)glyph;
1950 loader->stream = stream;
1951
1952 return TT_Err_Ok;
1953 }
1954
1955
Werner Lemberg78575dc2000-06-12 19:36:41 +00001956 /*************************************************************************/
1957 /* */
1958 /* <Function> */
1959 /* TT_Load_Glyph */
1960 /* */
1961 /* <Description> */
1962 /* A function used to load a single glyph within a given glyph slot, */
1963 /* for a given size. */
1964 /* */
1965 /* <Input> */
1966 /* glyph :: A handle to a target slot object where the glyph */
1967 /* will be loaded. */
1968 /* */
1969 /* size :: A handle to the source face size at which the glyph */
1970 /* must be scaled/loaded. */
1971 /* */
1972 /* glyph_index :: The index of the glyph in the font file. */
1973 /* */
1974 /* load_flags :: A flag indicating what to load for this glyph. The */
1975 /* FT_LOAD_XXX constants can be used to control the */
1976 /* glyph loading process (e.g., whether the outline */
1977 /* should be scaled, whether to load bitmaps or not, */
1978 /* whether to hint the outline, etc). */
1979 /* */
1980 /* <Return> */
Werner Lemberga929ba92000-06-25 06:47:11 +00001981 /* FreeType error code. 0 means success. */
Werner Lemberg78575dc2000-06-12 19:36:41 +00001982 /* */
David Turnerbc82f1b2002-03-01 02:26:22 +00001983 FT_LOCAL_DEF( FT_Error )
Werner Lemberg4a2305c2001-06-28 07:17:51 +00001984 TT_Load_Glyph( TT_Size size,
1985 TT_GlyphSlot glyph,
Werner Lembergc3dc56b2004-04-19 06:13:50 +00001986 FT_UInt glyph_index,
Werner Lemberge59dc912002-09-21 18:43:10 +00001987 FT_Int32 load_flags )
David Turner8f43c712000-02-02 12:16:19 +00001988 {
Werner Lemberg91db04c2002-04-01 14:25:28 +00001989 TT_Face face;
Werner Lemberg91db04c2002-04-01 14:25:28 +00001990 FT_Error error;
1991 TT_LoaderRec loader;
David Turnere49ab252000-05-16 23:44:38 +00001992
Werner Lemberg78575dc2000-06-12 19:36:41 +00001993
David Turner8f43c712000-02-02 12:16:19 +00001994 face = (TT_Face)glyph->face;
Werner Lemberg3ab770b2005-03-08 20:24:56 +00001995 error = TT_Err_Ok;
David Turnered7f62a2000-03-28 11:19:28 +00001996
David Turner8f43c712000-02-02 12:16:19 +00001997#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
Werner Lemberg4b680072000-11-07 06:30:29 +00001998
1999 /* try to load embedded bitmap if any */
2000 /* */
2001 /* XXX: The convention should be emphasized in */
2002 /* the documents because it can be confusing. */
Werner Lembergf1c2b912006-01-13 14:53:28 +00002003 if ( size->strike_index != 0xFFFFFFFFUL &&
David Turnerf96594f2000-11-06 23:07:51 +00002004 ( load_flags & FT_LOAD_NO_BITMAP ) == 0 )
David Turner8f43c712000-02-02 12:16:19 +00002005 {
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00002006 error = load_sbit_image( size, glyph, glyph_index, load_flags );
David Turner8f43c712000-02-02 12:16:19 +00002007 if ( !error )
Werner Lembergf186ba62009-11-03 15:46:35 +01002008 {
2009 FT_Face root = &face->root;
2010
2011
2012 if ( FT_IS_SCALABLE( root ) )
2013 {
2014 /* for the bbox we need the header only */
2015 (void)tt_loader_init( &loader, size, glyph, load_flags, TRUE );
2016 (void)load_truetype_glyph( &loader, glyph_index, 0, TRUE );
2017 glyph->linearHoriAdvance = loader.linear;
2018 glyph->linearVertAdvance = loader.top_bearing + loader.bbox.yMax -
2019 loader.vadvance;
Werner Lembergf186ba62009-11-03 15:46:35 +01002020 }
2021
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00002022 return TT_Err_Ok;
Werner Lembergf186ba62009-11-03 15:46:35 +01002023 }
David Turner8f43c712000-02-02 12:16:19 +00002024 }
Werner Lemberg78575dc2000-06-12 19:36:41 +00002025
David Turner8f43c712000-02-02 12:16:19 +00002026#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
2027
Werner Lemberg560d5fe2005-10-21 09:08:28 +00002028 /* if FT_LOAD_NO_SCALE is not set, `ttmetrics' must be valid */
Wu, Chia-I (吳佳一)2293bb12005-10-19 08:07:38 +00002029 if ( !( load_flags & FT_LOAD_NO_SCALE ) && !size->ttmetrics.valid )
Wu, Chia-I (吳佳一)15c1f5d2005-08-20 08:17:44 +00002030 return TT_Err_Invalid_Size_Handle;
2031
David Turner4937a3e2001-12-19 21:09:16 +00002032 if ( load_flags & FT_LOAD_SBITS_ONLY )
Werner Lemberg779afe42003-06-22 15:33:53 +00002033 return TT_Err_Invalid_Argument;
David Turner4937a3e2001-12-19 21:09:16 +00002034
Werner Lembergf186ba62009-11-03 15:46:35 +01002035 error = tt_loader_init( &loader, size, glyph, load_flags, FALSE );
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00002036 if ( error )
2037 return error;
Werner Lemberg7f74a522002-07-26 09:09:10 +00002038
David Turnerb08fe2d2002-08-27 20:20:29 +00002039 glyph->format = FT_GLYPH_FORMAT_OUTLINE;
Werner Lemberg78575dc2000-06-12 19:36:41 +00002040 glyph->num_subglyphs = 0;
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00002041 glyph->outline.flags = 0;
Werner Lemberg91db04c2002-04-01 14:25:28 +00002042
Werner Lemberg6f99c882007-05-19 07:01:49 +00002043 /* main loading loop */
Werner Lembergf186ba62009-11-03 15:46:35 +01002044 error = load_truetype_glyph( &loader, glyph_index, 0, FALSE );
Werner Lemberg78575dc2000-06-12 19:36:41 +00002045 if ( !error )
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00002046 {
2047 if ( glyph->format == FT_GLYPH_FORMAT_COMPOSITE )
2048 {
2049 glyph->num_subglyphs = loader.gloader->base.num_subglyphs;
2050 glyph->subglyphs = loader.gloader->base.subglyphs;
2051 }
2052 else
2053 {
Werner Lembergffa033b2005-08-19 08:56:29 +00002054 glyph->outline = loader.gloader->base.outline;
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00002055 glyph->outline.flags &= ~FT_OUTLINE_SINGLE_PASS;
2056
John Tytgat8c4cce52010-04-05 08:22:22 +02002057 /* Translate array so that (0,0) is the glyph's origin. Note */
2058 /* that this behaviour is independent on the value of bit 1 of */
2059 /* the `flags' field in the `head' table -- at least major */
2060 /* applications like Acroread indicate that. */
2061 if ( loader.pp1.x )
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00002062 FT_Outline_Translate( &glyph->outline, -loader.pp1.x, 0 );
2063 }
2064
Werner Lemberg5df5dbb2008-06-22 13:40:08 +00002065#ifdef TT_USE_BYTECODE_INTERPRETER
2066
Werner Lemberg745a4f42008-06-22 22:41:24 +00002067 if ( IS_HINTED( load_flags ) )
Werner Lemberg5df5dbb2008-06-22 13:40:08 +00002068 {
Werner Lemberg745a4f42008-06-22 22:41:24 +00002069 if ( loader.exec->GS.scan_control )
Werner Lemberg5df5dbb2008-06-22 13:40:08 +00002070 {
Werner Lemberg745a4f42008-06-22 22:41:24 +00002071 /* convert scan conversion mode to FT_OUTLINE_XXX flags */
2072 switch ( loader.exec->GS.scan_type )
2073 {
2074 case 0: /* simple drop-outs including stubs */
2075 glyph->outline.flags |= FT_OUTLINE_INCLUDE_STUBS;
2076 break;
2077 case 1: /* simple drop-outs excluding stubs */
2078 /* nothing; it's the default rendering mode */
2079 break;
2080 case 4: /* smart drop-outs including stubs */
2081 glyph->outline.flags |= FT_OUTLINE_SMART_DROPOUTS |
2082 FT_OUTLINE_INCLUDE_STUBS;
2083 break;
2084 case 5: /* smart drop-outs excluding stubs */
2085 glyph->outline.flags |= FT_OUTLINE_SMART_DROPOUTS;
2086 break;
Werner Lemberg5df5dbb2008-06-22 13:40:08 +00002087
Werner Lemberg745a4f42008-06-22 22:41:24 +00002088 default: /* no drop-out control */
2089 glyph->outline.flags |= FT_OUTLINE_IGNORE_DROPOUTS;
2090 break;
2091 }
Werner Lemberg5df5dbb2008-06-22 13:40:08 +00002092 }
Bram Tassyns4694ea22009-09-02 13:06:33 +02002093 else
Werner Lemberg745a4f42008-06-22 22:41:24 +00002094 glyph->outline.flags |= FT_OUTLINE_IGNORE_DROPOUTS;
Werner Lemberg5df5dbb2008-06-22 13:40:08 +00002095 }
Werner Lemberg5df5dbb2008-06-22 13:40:08 +00002096
2097#endif /* TT_USE_BYTECODE_INTERPRETER */
2098
David Turner8f43c712000-02-02 12:16:19 +00002099 compute_glyph_metrics( &loader, glyph_index );
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +00002100 }
David Turnerd2b1f351999-12-16 23:11:37 +00002101
Werner Lemberg26aca022002-05-05 07:40:16 +00002102 /* Set the `high precision' bit flag. */
2103 /* This is _critical_ to get correct output for monochrome */
2104 /* TrueType glyphs at all sizes using the bytecode interpreter. */
2105 /* */
Werner Lemberg560d5fe2005-10-21 09:08:28 +00002106 if ( !( load_flags & FT_LOAD_NO_SCALE ) &&
2107 size->root.metrics.y_ppem < 24 )
David Turnerb08fe2d2002-08-27 20:20:29 +00002108 glyph->outline.flags |= FT_OUTLINE_HIGH_PRECISION;
David Turner8cd89072002-05-04 18:02:59 +00002109
David Turnerd2b1f351999-12-16 23:11:37 +00002110 return error;
2111 }
2112
2113
David Turnerd2b1f351999-12-16 23:11:37 +00002114/* END */