blob: a83dbe328f8b9356232ec1896c8bf8e89ece7dd2 [file] [log] [blame]
David Turnerd2b1f351999-12-16 23:11:37 +00001/***************************************************************************/
2/* */
3/* ttgload.c */
4/* */
5/* TrueType Glyph Loader (body). */
6/* */
Werner Lemberge7930922005-03-01 02:13:50 +00007/* Copyright 1996-2001, 2002, 2003, 2004, 2005 by */
David Turnerd2b1f351999-12-16 23:11:37 +00008/* David Turner, Robert Wilhelm, and Werner Lemberg. */
9/* */
Werner Lemberg78575dc2000-06-12 19:36:41 +000010/* This file is part of the FreeType project, and may only be used, */
11/* modified, and distributed under the terms of the FreeType project */
David Turnerd2b1f351999-12-16 23:11:37 +000012/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
13/* this file you indicate that you have read the license and */
14/* understand and accept it fully. */
15/* */
16/***************************************************************************/
17
Werner Lembergcc069be2000-12-08 16:17:16 +000018
David Turner19ed8af2000-12-08 02:42:29 +000019#include <ft2build.h>
20#include FT_INTERNAL_DEBUG_H
21#include FT_INTERNAL_CALC_H
22#include FT_INTERNAL_STREAM_H
23#include FT_INTERNAL_SFNT_H
24#include FT_TRUETYPE_TAGS_H
25#include FT_OUTLINE_H
David Turnerd2b1f351999-12-16 23:11:37 +000026
David Turner8d3a4012001-03-20 11:14:24 +000027#include "ttgload.h"
Werner Lembergf13516c2005-03-03 17:09:08 +000028#include "ttpload.h"
Werner Lemberg78575dc2000-06-12 19:36:41 +000029
Werner Lemberg44bb3032004-04-25 20:15:11 +000030#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
31#include "ttgxvar.h"
32#endif
33
Werner Lemberg1f7f0e82001-06-06 17:30:41 +000034#include "tterrors.h"
35
David Turnera90663f2000-07-08 00:41:13 +000036
Werner Lemberg78575dc2000-06-12 19:36:41 +000037 /*************************************************************************/
38 /* */
39 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
40 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
41 /* messages during execution. */
42 /* */
David Turnerd2b1f351999-12-16 23:11:37 +000043#undef FT_COMPONENT
44#define FT_COMPONENT trace_ttgload
45
46
47 /*************************************************************************/
48 /* */
49 /* Composite font flags. */
50 /* */
Werner Lembergeed446d2002-08-16 12:46:52 +000051#define ARGS_ARE_WORDS 0x0001
52#define ARGS_ARE_XY_VALUES 0x0002
53#define ROUND_XY_TO_GRID 0x0004
54#define WE_HAVE_A_SCALE 0x0008
55/* reserved 0x0010 */
56#define MORE_COMPONENTS 0x0020
57#define WE_HAVE_AN_XY_SCALE 0x0040
58#define WE_HAVE_A_2X2 0x0080
59#define WE_HAVE_INSTR 0x0100
60#define USE_MY_METRICS 0x0200
61#define OVERLAP_COMPOUND 0x0400
62#define SCALED_COMPONENT_OFFSET 0x0800
63#define UNSCALED_COMPONENT_OFFSET 0x1000
David Turnerd2b1f351999-12-16 23:11:37 +000064
David Turnerf9b8dec2000-06-16 19:34:52 +000065
David Turner77b68b82003-01-08 09:59:17 +000066/* Maximum recursion depth we allow for composite glyphs.
67 * The TrueType spec doesn't say anything about recursion,
68 * so it isn't clear that recursion is allowed at all. But
69 * we'll be generous.
70 */
71#define TT_MAX_COMPOSITE_RECURSE 5
72
73
74
David Turnerd2b1f351999-12-16 23:11:37 +000075 /*************************************************************************/
Werner Lemberg78575dc2000-06-12 19:36:41 +000076 /* */
77 /* <Function> */
Werner Lemberg8744edf2005-04-06 14:48:55 +000078 /* tt_face_get_metrics */
Werner Lemberg78575dc2000-06-12 19:36:41 +000079 /* */
80 /* <Description> */
David Turnerd2b1f351999-12-16 23:11:37 +000081 /* Returns the horizontal or vertical metrics in font units for a */
82 /* given glyph. The metrics are the left side bearing (resp. top */
83 /* side bearing) and advance width (resp. advance height). */
84 /* */
Werner Lemberg78575dc2000-06-12 19:36:41 +000085 /* <Input> */
86 /* header :: A pointer to either the horizontal or vertical metrics */
87 /* structure. */
88 /* */
Werner Lemberg0d9165e2002-03-07 21:59:59 +000089 /* idx :: The glyph index. */
Werner Lemberg78575dc2000-06-12 19:36:41 +000090 /* */
91 /* <Output> */
92 /* bearing :: The bearing, either left side or top side. */
93 /* */
94 /* advance :: The advance width resp. advance height. */
95 /* */
96 /* <Note> */
97 /* This function will much probably move to another component in the */
98 /* near future, but I haven't decided which yet. */
99 /* */
David Turnere5680272005-02-26 00:12:04 +0000100#ifdef FT_OPTIMIZE_MEMORY
Werner Lemberge7930922005-03-01 02:13:50 +0000101
David Turnere5680272005-02-26 00:12:04 +0000102 static void
Werner Lemberge7930922005-03-01 02:13:50 +0000103 tt_face_get_metrics( TT_Face face,
104 FT_Bool vertical,
105 FT_UInt idx,
106 FT_Short *abearing,
107 FT_UShort *aadvance )
David Turnerd2b1f351999-12-16 23:11:37 +0000108 {
David Turnere5680272005-02-26 00:12:04 +0000109 TT_HoriHeader* header;
110 FT_Byte* p;
111 FT_Byte* limit;
112 FT_UShort k;
113
Werner Lemberge7930922005-03-01 02:13:50 +0000114
David Turnere5680272005-02-26 00:12:04 +0000115 if ( vertical )
116 {
117 header = (TT_HoriHeader*)&face->vertical;
118 p = face->vert_metrics;
119 limit = p + face->vert_metrics_size;
120 }
121 else
122 {
123 header = &face->horizontal;
124 p = face->horz_metrics;
125 limit = p + face->horz_metrics_size;
126 }
127
128 k = header->number_Of_HMetrics;
129
130 if ( k > 0 )
131 {
132 if ( idx < (FT_UInt)k )
133 {
Werner Lemberge7930922005-03-01 02:13:50 +0000134 p += 4 * idx;
Werner Lemberg8744edf2005-04-06 14:48:55 +0000135 if ( p + 4 > limit )
David Turnere5680272005-02-26 00:12:04 +0000136 goto NoData;
137
Werner Lemberge7930922005-03-01 02:13:50 +0000138 *aadvance = FT_NEXT_USHORT( p );
139 *abearing = FT_NEXT_SHORT( p );
David Turnere5680272005-02-26 00:12:04 +0000140 }
141 else
142 {
Werner Lemberge7930922005-03-01 02:13:50 +0000143 p += 4 * ( k - 1 );
144 if ( p + 4 > limit )
David Turnere5680272005-02-26 00:12:04 +0000145 goto NoData;
146
Werner Lemberge7930922005-03-01 02:13:50 +0000147 *aadvance = FT_NEXT_USHORT( p );
148 p += 2 + 2 * ( idx - k );
149 if ( p + 2 > limit )
David Turnere5680272005-02-26 00:12:04 +0000150 *abearing = 0;
151 else
Werner Lemberge7930922005-03-01 02:13:50 +0000152 *abearing = FT_PEEK_SHORT( p );
David Turnere5680272005-02-26 00:12:04 +0000153 }
154 }
155 else
156 {
157 NoData:
158 *abearing = 0;
159 *aadvance = 0;
160 }
161 }
Werner Lemberge7930922005-03-01 02:13:50 +0000162
163#else /* !FT_OPTIMIZE_MEMORY */
164
David Turnere5680272005-02-26 00:12:04 +0000165 static void
Werner Lemberge7930922005-03-01 02:13:50 +0000166 tt_face_get_metrics( TT_Face face,
167 FT_Bool vertical,
168 FT_UInt idx,
169 FT_Short *abearing,
170 FT_UShort *aadvance )
David Turnere5680272005-02-26 00:12:04 +0000171 {
Werner Lemberge7930922005-03-01 02:13:50 +0000172 TT_HoriHeader* header = vertical ? (TT_HoriHeader*)&face->vertical
173 : &face->horizontal;
Werner Lemberg91db04c2002-04-01 14:25:28 +0000174 TT_LongMetrics longs_m;
Werner Lemberge7930922005-03-01 02:13:50 +0000175 FT_UShort k = header->number_Of_HMetrics;
David Turnerd2b1f351999-12-16 23:11:37 +0000176
177
Werner Lemberg6b5c6692002-09-05 15:10:54 +0000178 if ( k == 0 )
Werner Lemberg215bf442002-08-21 17:36:20 +0000179 {
David Turnere5680272005-02-26 00:12:04 +0000180 *abearing = *aadvance = 0;
Werner Lemberg215bf442002-08-21 17:36:20 +0000181 return;
182 }
183
Werner Lemberg0d9165e2002-03-07 21:59:59 +0000184 if ( idx < (FT_UInt)k )
David Turnerd2b1f351999-12-16 23:11:37 +0000185 {
Werner Lemberge7930922005-03-01 02:13:50 +0000186 longs_m = (TT_LongMetrics)header->long_metrics + idx;
David Turnere5680272005-02-26 00:12:04 +0000187 *abearing = longs_m->bearing;
188 *aadvance = longs_m->advance;
David Turnerd2b1f351999-12-16 23:11:37 +0000189 }
190 else
191 {
David Turnere5680272005-02-26 00:12:04 +0000192 *abearing = ((TT_ShortMetrics*)header->short_metrics)[idx - k];
Werner Lemberge7930922005-03-01 02:13:50 +0000193 *aadvance = ((TT_LongMetrics)header->long_metrics)[k - 1].advance;
David Turnerd2b1f351999-12-16 23:11:37 +0000194 }
195 }
Werner Lemberge7930922005-03-01 02:13:50 +0000196
197#endif /* !FT_OPTIMIZE_MEMORY */
David Turnerd2b1f351999-12-16 23:11:37 +0000198
199
200 /*************************************************************************/
Werner Lemberg78575dc2000-06-12 19:36:41 +0000201 /* */
Werner Lembergdcd2e142000-06-25 07:43:15 +0000202 /* Returns the horizontal metrics in font units for a given glyph. If */
203 /* `check' is true, take care of monospaced fonts by returning the */
204 /* advance width maximum. */
David Turnerd2b1f351999-12-16 23:11:37 +0000205 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +0000206 static void
207 Get_HMetrics( TT_Face face,
Werner Lemberg0d9165e2002-03-07 21:59:59 +0000208 FT_UInt idx,
Werner Lemberg4a2305c2001-06-28 07:17:51 +0000209 FT_Bool check,
210 FT_Short* lsb,
211 FT_UShort* aw )
David Turnerd2b1f351999-12-16 23:11:37 +0000212 {
David Turnere5680272005-02-26 00:12:04 +0000213 tt_face_get_metrics( face, 0, idx, lsb, aw );
David Turnerd2b1f351999-12-16 23:11:37 +0000214
215 if ( check && face->postscript.isFixedPitch )
216 *aw = face->horizontal.advance_Width_Max;
217 }
218
219
220 /*************************************************************************/
Werner Lemberg78575dc2000-06-12 19:36:41 +0000221 /* */
Werner Lemberg91db04c2002-04-01 14:25:28 +0000222 /* Returns the advance width table for a given pixel size if it is found */
223 /* in the font's `hdmx' table (if any). */
David Turnerd2b1f351999-12-16 23:11:37 +0000224 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +0000225 static FT_Byte*
David Turnere5680272005-02-26 00:12:04 +0000226 Get_Advance_WidthPtr( TT_Face face,
227 FT_Int ppem,
228 FT_UInt gindex )
David Turnerd2b1f351999-12-16 23:11:37 +0000229 {
David Turnere5680272005-02-26 00:12:04 +0000230#ifdef FT_OPTIMIZE_MEMORY
Werner Lemberge7930922005-03-01 02:13:50 +0000231
David Turnere5680272005-02-26 00:12:04 +0000232 FT_UInt nn;
Werner Lemberge7930922005-03-01 02:13:50 +0000233 FT_Byte* result = NULL;
David Turnere5680272005-02-26 00:12:04 +0000234 FT_ULong record_size = face->hdmx_record_size;
235 FT_Byte* record = face->hdmx_table + 8;
236
Werner Lemberge7930922005-03-01 02:13:50 +0000237
David Turnere5680272005-02-26 00:12:04 +0000238 for ( nn = 0; nn < face->hdmx_record_count; nn++ )
239 if ( face->hdmx_record_sizes[nn] == ppem )
240 {
241 gindex += 2;
242 if ( gindex < record_size )
243 result = record + gindex;
244 break;
245 }
246
247 return result;
Werner Lemberge7930922005-03-01 02:13:50 +0000248
David Turnere5680272005-02-26 00:12:04 +0000249#else
Werner Lemberge7930922005-03-01 02:13:50 +0000250
David Turnerf9b8dec2000-06-16 19:34:52 +0000251 FT_UShort n;
David Turnerd2b1f351999-12-16 23:11:37 +0000252
Werner Lemberg91db04c2002-04-01 14:25:28 +0000253
David Turnerd2b1f351999-12-16 23:11:37 +0000254 for ( n = 0; n < face->hdmx.num_records; n++ )
255 if ( face->hdmx.records[n].ppem == ppem )
David Turnere5680272005-02-26 00:12:04 +0000256 return &face->hdmx.records[n].widths[gindex];
David Turnerd2b1f351999-12-16 23:11:37 +0000257
258 return NULL;
Werner Lemberge7930922005-03-01 02:13:50 +0000259
David Turnere5680272005-02-26 00:12:04 +0000260#endif
David Turnerd2b1f351999-12-16 23:11:37 +0000261 }
262
263
Werner Lemberg8bb07e62004-03-27 08:43:17 +0000264 /*************************************************************************/
265 /* */
266 /* Returns the vertical metrics in font units for a given glyph. */
267 /* Greg Hitchcock from Microsoft told us that if there were no `vmtx' */
268 /* table, typoAscender/Descender from the `OS/2' table would be used */
269 /* instead, and if there were no `OS/2' table, use ascender/descender */
270 /* from the `hhea' table. But that is not what Microsoft's rasterizer */
271 /* apparently does: It uses the ppem value as the advance height, and */
272 /* sets the top side bearing to be zero. */
273 /* */
274 /* The monospace `check' is probably not meaningful here, but we leave */
275 /* it in for a consistent interface. */
276 /* */
277 static void
278 Get_VMetrics( TT_Face face,
279 FT_UInt idx,
280 FT_Bool check,
281 FT_Short* tsb,
282 FT_UShort* ah )
283 {
284 FT_UNUSED( check );
285
286 if ( face->vertical_info )
David Turnere5680272005-02-26 00:12:04 +0000287 tt_face_get_metrics( face, 1, idx, tsb, ah );
Werner Lemberg8bb07e62004-03-27 08:43:17 +0000288
289#if 1 /* Emperically determined, at variance with what MS said */
290
291 else
292 {
293 *tsb = 0;
294 *ah = face->root.units_per_EM;
295 }
296
297#else /* This is what MS said to do. It isn't what they do, however. */
298
299 else if ( face->os2.version != 0xFFFFU )
300 {
301 *tsb = face->os2.sTypoAscender;
302 *ah = face->os2.sTypoAscender - face->os2.sTypoDescender;
303 }
David Turner2f0fdb92004-06-21 21:16:56 +0000304 else
Werner Lemberg8bb07e62004-03-27 08:43:17 +0000305 {
306 *tsb = face->horizontal.Ascender;
307 *ah = face->horizontal.Ascender - face->horizontal.Descender;
308 }
309
310#endif
311
312 }
313
314
Werner Lemberg5811c7c2000-07-02 13:53:16 +0000315#define cur_to_org( n, zone ) \
David Turner4632fcc2004-01-15 19:07:44 +0000316 FT_ARRAY_COPY( (zone)->org, (zone)->cur, (n) )
David Turnerd2b1f351999-12-16 23:11:37 +0000317
Werner Lemberg5811c7c2000-07-02 13:53:16 +0000318#define org_to_cur( n, zone ) \
David Turner4632fcc2004-01-15 19:07:44 +0000319 FT_ARRAY_COPY( (zone)->cur, (zone)->org, (n) )
David Turnerd2b1f351999-12-16 23:11:37 +0000320
321
322 /*************************************************************************/
Werner Lemberg78575dc2000-06-12 19:36:41 +0000323 /* */
Werner Lemberg91db04c2002-04-01 14:25:28 +0000324 /* Translates an array of coordinates. */
David Turnerd2b1f351999-12-16 23:11:37 +0000325 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +0000326 static void
327 translate_array( FT_UInt n,
328 FT_Vector* coords,
329 FT_Pos delta_x,
330 FT_Pos delta_y )
David Turnerd2b1f351999-12-16 23:11:37 +0000331 {
David Turnerf9b8dec2000-06-16 19:34:52 +0000332 FT_UInt k;
Werner Lemberg78575dc2000-06-12 19:36:41 +0000333
Werner Lemberg5811c7c2000-07-02 13:53:16 +0000334
David Turnerd2b1f351999-12-16 23:11:37 +0000335 if ( delta_x )
336 for ( k = 0; k < n; k++ )
337 coords[k].x += delta_x;
338
339 if ( delta_y )
340 for ( k = 0; k < n; k++ )
341 coords[k].y += delta_y;
342 }
343
344
Werner Lemberg4a2305c2001-06-28 07:17:51 +0000345 static void
Werner Lemberg91db04c2002-04-01 14:25:28 +0000346 tt_prepare_zone( TT_GlyphZone zone,
347 FT_GlyphLoad load,
348 FT_UInt start_point,
349 FT_UInt start_contour )
David Turnerd2b1f351999-12-16 23:11:37 +0000350 {
Werner Lemberg8eb03532001-06-19 23:03:41 +0000351 zone->n_points = (FT_UShort)( load->outline.n_points - start_point );
352 zone->n_contours = (FT_Short) ( load->outline.n_contours - start_contour );
David Turnerf0df85b2000-06-22 00:17:42 +0000353 zone->org = load->extra_points + start_point;
354 zone->cur = load->outline.points + start_point;
355 zone->tags = (FT_Byte*)load->outline.tags + start_point;
356 zone->contours = (FT_UShort*)load->outline.contours + start_contour;
Werner Lembergbd5ae402000-07-05 04:32:02 +0000357 }
David Turnerd2b1f351999-12-16 23:11:37 +0000358
359
David Turner8f43c712000-02-02 12:16:19 +0000360#undef IS_HINTED
Werner Lemberg78575dc2000-06-12 19:36:41 +0000361#define IS_HINTED( flags ) ( ( flags & FT_LOAD_NO_HINTING ) == 0 )
362
David Turner8f43c712000-02-02 12:16:19 +0000363
David Turnerd2b1f351999-12-16 23:11:37 +0000364 /*************************************************************************/
365 /* */
Werner Lemberg91db04c2002-04-01 14:25:28 +0000366 /* The following functions are used by default with TrueType fonts. */
367 /* However, they can be replaced by alternatives if we need to support */
368 /* TrueType-compressed formats (like MicroType) in the future. */
David Turnerd2b1f351999-12-16 23:11:37 +0000369 /* */
Werner Lemberga929ba92000-06-25 06:47:11 +0000370 /*************************************************************************/
David Turner90f68b72000-06-23 12:26:14 +0000371
Werner Lemberg4a2305c2001-06-28 07:17:51 +0000372 FT_CALLBACK_DEF( FT_Error )
Werner Lemberg91db04c2002-04-01 14:25:28 +0000373 TT_Access_Glyph_Frame( TT_Loader loader,
374 FT_UInt glyph_index,
375 FT_ULong offset,
376 FT_UInt byte_count )
David Turner90f68b72000-06-23 12:26:14 +0000377 {
Werner Lemberge72c9fe2000-07-31 18:59:02 +0000378 FT_Error error;
379 FT_Stream stream = loader->stream;
Werner Lembergbd5ae402000-07-05 04:32:02 +0000380
Werner Lemberg353dfea2000-08-29 18:58:41 +0000381 /* for non-debug mode */
382 FT_UNUSED( glyph_index );
383
Werner Lemberga929ba92000-06-25 06:47:11 +0000384
David Turner90f68b72000-06-23 12:26:14 +0000385 FT_TRACE5(( "Glyph %ld\n", glyph_index ));
Werner Lemberge72c9fe2000-07-31 18:59:02 +0000386
387 /* the following line sets the `error' variable through macros! */
David Turner7d3a2642002-03-20 10:49:31 +0000388 if ( FT_STREAM_SEEK( offset ) || FT_FRAME_ENTER( byte_count ) )
Werner Lemberge72c9fe2000-07-31 18:59:02 +0000389 return error;
390
391 return TT_Err_Ok;
Werner Lembergbd5ae402000-07-05 04:32:02 +0000392 }
David Turner90f68b72000-06-23 12:26:14 +0000393
394
Werner Lemberg4a2305c2001-06-28 07:17:51 +0000395 FT_CALLBACK_DEF( void )
Werner Lemberg91db04c2002-04-01 14:25:28 +0000396 TT_Forget_Glyph_Frame( TT_Loader loader )
David Turner90f68b72000-06-23 12:26:14 +0000397 {
398 FT_Stream stream = loader->stream;
Werner Lemberga929ba92000-06-25 06:47:11 +0000399
400
David Turner7d3a2642002-03-20 10:49:31 +0000401 FT_FRAME_EXIT();
Werner Lembergbd5ae402000-07-05 04:32:02 +0000402 }
David Turner90f68b72000-06-23 12:26:14 +0000403
404
Werner Lemberg4a2305c2001-06-28 07:17:51 +0000405 FT_CALLBACK_DEF( FT_Error )
Werner Lemberg91db04c2002-04-01 14:25:28 +0000406 TT_Load_Glyph_Header( TT_Loader loader )
David Turner90f68b72000-06-23 12:26:14 +0000407 {
Werner Lemberg91db04c2002-04-01 14:25:28 +0000408 FT_Stream stream = loader->stream;
409 FT_Int byte_len = loader->byte_len - 10;
Werner Lembergbd5ae402000-07-05 04:32:02 +0000410
Werner Lembergac812952002-01-06 16:42:44 +0000411
David Turnerf7f82d72002-01-06 10:13:40 +0000412 if ( byte_len < 0 )
413 return TT_Err_Invalid_Outline;
Werner Lemberga929ba92000-06-25 06:47:11 +0000414
David Turnera890c292002-03-22 12:55:23 +0000415 loader->n_contours = FT_GET_SHORT();
David Turner90f68b72000-06-23 12:26:14 +0000416
David Turnera890c292002-03-22 12:55:23 +0000417 loader->bbox.xMin = FT_GET_SHORT();
418 loader->bbox.yMin = FT_GET_SHORT();
419 loader->bbox.xMax = FT_GET_SHORT();
420 loader->bbox.yMax = FT_GET_SHORT();
David Turner90f68b72000-06-23 12:26:14 +0000421
422 FT_TRACE5(( " # of contours: %d\n", loader->n_contours ));
423 FT_TRACE5(( " xMin: %4d xMax: %4d\n", loader->bbox.xMin,
424 loader->bbox.xMax ));
425 FT_TRACE5(( " yMin: %4d yMax: %4d\n", loader->bbox.yMin,
426 loader->bbox.yMax ));
David Turnerf7f82d72002-01-06 10:13:40 +0000427 loader->byte_len = byte_len;
Werner Lembergbd5ae402000-07-05 04:32:02 +0000428
Werner Lemberg1429db62001-04-02 23:54:01 +0000429 return TT_Err_Ok;
Werner Lembergbd5ae402000-07-05 04:32:02 +0000430 }
David Turner90f68b72000-06-23 12:26:14 +0000431
432
Werner Lemberg4a2305c2001-06-28 07:17:51 +0000433 FT_CALLBACK_DEF( FT_Error )
Werner Lemberg91db04c2002-04-01 14:25:28 +0000434 TT_Load_Simple_Glyph( TT_Loader load )
David Turnerd2b1f351999-12-16 23:11:37 +0000435 {
Werner Lemberg91db04c2002-04-01 14:25:28 +0000436 FT_Error error;
437 FT_Stream stream = load->stream;
438 FT_GlyphLoader gloader = load->gloader;
439 FT_Int n_contours = load->n_contours;
440 FT_Outline* outline;
441 TT_Face face = (TT_Face)load->face;
442 TT_GlyphSlot slot = (TT_GlyphSlot)load->glyph;
443 FT_UShort n_ins;
444 FT_Int n, n_points;
445 FT_Int byte_len = load->byte_len;
David Turnere49ab252000-05-16 23:44:38 +0000446
Werner Lemberg0240d292003-06-09 15:54:18 +0000447 FT_Byte *flag, *flag_limit;
448 FT_Byte c, count;
449 FT_Vector *vec, *vec_limit;
450 FT_Pos x;
451 FT_Short *cont, *cont_limit;
452
Werner Lemberg78575dc2000-06-12 19:36:41 +0000453
Werner Lemberg44bb3032004-04-25 20:15:11 +0000454 /* reading the contours' endpoints & number of points */
Werner Lemberg0240d292003-06-09 15:54:18 +0000455 cont = gloader->current.outline.contours;
456 cont_limit = cont + n_contours;
Werner Lembergbd5ae402000-07-05 04:32:02 +0000457
Werner Lemberg0240d292003-06-09 15:54:18 +0000458 /* check space for contours array + instructions count */
459 byte_len -= 2 * ( n_contours + 1 );
460 if ( byte_len < 0 )
461 goto Invalid_Outline;
Werner Lembergac812952002-01-06 16:42:44 +0000462
Werner Lemberg0240d292003-06-09 15:54:18 +0000463 for ( ; cont < cont_limit; cont++ )
464 cont[0] = FT_GET_USHORT();
465
466 n_points = 0;
467 if ( n_contours > 0 )
468 n_points = cont[-1] + 1;
469
Werner Lemberg8bb07e62004-03-27 08:43:17 +0000470 error = FT_GlyphLoader_CheckPoints( gloader, n_points + 4, 0 );
Werner Lemberg0240d292003-06-09 15:54:18 +0000471 if ( error )
472 goto Fail;
473
474 /* we'd better check the contours table right now */
475 outline = &gloader->current.outline;
476
477 for ( cont = outline->contours + 1; cont < cont_limit; cont++ )
478 if ( cont[-1] >= cont[0] )
David Turnerf7f82d72002-01-06 10:13:40 +0000479 goto Invalid_Outline;
Werner Lemberga929ba92000-06-25 06:47:11 +0000480
Werner Lemberg78575dc2000-06-12 19:36:41 +0000481 /* reading the bytecode instructions */
David Turnerc3128612000-06-23 05:02:13 +0000482 slot->control_len = 0;
483 slot->control_data = 0;
Werner Lembergbd5ae402000-07-05 04:32:02 +0000484
David Turnera890c292002-03-22 12:55:23 +0000485 n_ins = FT_GET_USHORT();
David Turnerd2b1f351999-12-16 23:11:37 +0000486
Werner Lemberg0240d292003-06-09 15:54:18 +0000487 FT_TRACE5(( " Instructions size: %u\n", n_ins ));
David Turnerd2b1f351999-12-16 23:11:37 +0000488
489 if ( n_ins > face->max_profile.maxSizeOfInstructions )
490 {
Werner Lemberg91db04c2002-04-01 14:25:28 +0000491 FT_TRACE0(( "TT_Load_Simple_Glyph: Too many instructions!\n" ));
Werner Lemberg1f7f0e82001-06-06 17:30:41 +0000492 error = TT_Err_Too_Many_Hints;
David Turnerd2b1f351999-12-16 23:11:37 +0000493 goto Fail;
494 }
495
Werner Lemberg0240d292003-06-09 15:54:18 +0000496 byte_len -= (FT_Int)n_ins;
David Turnerf7f82d72002-01-06 10:13:40 +0000497 if ( byte_len < 0 )
David Turnerd2b1f351999-12-16 23:11:37 +0000498 {
Werner Lemberg91db04c2002-04-01 14:25:28 +0000499 FT_TRACE0(( "TT_Load_Simple_Glyph: Instruction count mismatch!\n" ));
Werner Lemberg1f7f0e82001-06-06 17:30:41 +0000500 error = TT_Err_Too_Many_Hints;
David Turnerd2b1f351999-12-16 23:11:37 +0000501 goto Fail;
502 }
David Turnerd2b1f351999-12-16 23:11:37 +0000503
David Turner8f43c712000-02-02 12:16:19 +0000504#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
Werner Lemberga929ba92000-06-25 06:47:11 +0000505
506 if ( ( load->load_flags &
David Turnerc3128612000-06-23 05:02:13 +0000507 ( FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING ) ) == 0 &&
508 load->instructions )
David Turner08fdac92000-02-21 16:01:33 +0000509 {
David Turnerc3128612000-06-23 05:02:13 +0000510 slot->control_len = n_ins;
511 slot->control_data = load->instructions;
Werner Lembergbd5ae402000-07-05 04:32:02 +0000512
Werner Lemberg0240d292003-06-09 15:54:18 +0000513 FT_MEM_COPY( load->instructions, stream->cursor, (FT_Long)n_ins );
David Turner08fdac92000-02-21 16:01:33 +0000514 }
Werner Lemberga929ba92000-06-25 06:47:11 +0000515
Werner Lemberg78575dc2000-06-12 19:36:41 +0000516#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
David Turnerd2b1f351999-12-16 23:11:37 +0000517
Werner Lemberg0240d292003-06-09 15:54:18 +0000518 stream->cursor += (FT_Int)n_ins;
David Turnere49ab252000-05-16 23:44:38 +0000519
Werner Lemberg78575dc2000-06-12 19:36:41 +0000520 /* reading the point tags */
Werner Lemberg0240d292003-06-09 15:54:18 +0000521 flag = (FT_Byte*)outline->tags;
522 flag_limit = flag + n_points;
523
Werner Lemberg685dd4f2004-10-13 05:15:44 +0000524 FT_ASSERT( flag != NULL );
525
Werner Lembergf946fc62003-12-31 08:48:21 +0000526 while ( flag < flag_limit )
David Turnere49ab252000-05-16 23:44:38 +0000527 {
Werner Lemberg0240d292003-06-09 15:54:18 +0000528 if ( --byte_len < 0 )
529 goto Invalid_Outline;
David Turnere49ab252000-05-16 23:44:38 +0000530
Werner Lemberg0240d292003-06-09 15:54:18 +0000531 *flag++ = c = FT_GET_BYTE();
532 if ( c & 8 )
David Turnerd2b1f351999-12-16 23:11:37 +0000533 {
David Turnerf7f82d72002-01-06 10:13:40 +0000534 if ( --byte_len < 0 )
535 goto Invalid_Outline;
536
Werner Lemberg0240d292003-06-09 15:54:18 +0000537 count = FT_GET_BYTE();
538 if ( flag + (FT_Int)count > flag_limit )
539 goto Invalid_Outline;
David Turnerf7f82d72002-01-06 10:13:40 +0000540
Werner Lemberg0240d292003-06-09 15:54:18 +0000541 for ( ; count > 0; count-- )
542 *flag++ = c;
David Turnerd2b1f351999-12-16 23:11:37 +0000543 }
544 }
545
Werner Lemberg0240d292003-06-09 15:54:18 +0000546 /* check that there is enough room to load the coordinates */
547 for ( flag = (FT_Byte*)outline->tags; flag < flag_limit; flag++ )
548 {
549 if ( *flag & 2 )
550 byte_len -= 1;
551 else if ( ( *flag & 16 ) == 0 )
552 byte_len -= 2;
553
554 if ( *flag & 4 )
555 byte_len -= 1;
556 else if ( ( *flag & 32 ) == 0 )
557 byte_len -= 2;
558 }
559
560 if ( byte_len < 0 )
561 goto Invalid_Outline;
562
Werner Lemberg78575dc2000-06-12 19:36:41 +0000563 /* reading the X coordinates */
David Turnere49ab252000-05-16 23:44:38 +0000564
Werner Lemberg0240d292003-06-09 15:54:18 +0000565 vec = outline->points;
566 vec_limit = vec + n_points;
567 flag = (FT_Byte*)outline->tags;
568 x = 0;
569
570 for ( ; vec < vec_limit; vec++, flag++ )
David Turnerd2b1f351999-12-16 23:11:37 +0000571 {
Werner Lemberg0240d292003-06-09 15:54:18 +0000572 FT_Pos y = 0;
David Turnere49ab252000-05-16 23:44:38 +0000573
Werner Lemberg78575dc2000-06-12 19:36:41 +0000574
Werner Lemberg0240d292003-06-09 15:54:18 +0000575 if ( *flag & 2 )
David Turnerd2b1f351999-12-16 23:11:37 +0000576 {
Werner Lemberg0240d292003-06-09 15:54:18 +0000577 y = (FT_Pos)FT_GET_BYTE();
578 if ( ( *flag & 16 ) == 0 )
579 y = -y;
David Turnerd2b1f351999-12-16 23:11:37 +0000580 }
Werner Lemberg0240d292003-06-09 15:54:18 +0000581 else if ( ( *flag & 16 ) == 0 )
582 y = (FT_Pos)FT_GET_SHORT();
583
584 x += y;
585 vec->x = x;
David Turnerd2b1f351999-12-16 23:11:37 +0000586 }
587
Werner Lemberg78575dc2000-06-12 19:36:41 +0000588 /* reading the Y coordinates */
David Turnerd2b1f351999-12-16 23:11:37 +0000589
Werner Lemberg0240d292003-06-09 15:54:18 +0000590 vec = gloader->current.outline.points;
591 vec_limit = vec + n_points;
592 flag = (FT_Byte*)outline->tags;
593 x = 0;
594
595 for ( ; vec < vec_limit; vec++, flag++ )
David Turnerd2b1f351999-12-16 23:11:37 +0000596 {
Werner Lemberg0240d292003-06-09 15:54:18 +0000597 FT_Pos y = 0;
David Turnere49ab252000-05-16 23:44:38 +0000598
Werner Lemberg78575dc2000-06-12 19:36:41 +0000599
Werner Lemberg0240d292003-06-09 15:54:18 +0000600 if ( *flag & 4 )
David Turnerd2b1f351999-12-16 23:11:37 +0000601 {
Werner Lemberg0240d292003-06-09 15:54:18 +0000602 y = (FT_Pos)FT_GET_BYTE();
603 if ( ( *flag & 32 ) == 0 )
604 y = -y;
David Turnerd2b1f351999-12-16 23:11:37 +0000605 }
Werner Lemberg0240d292003-06-09 15:54:18 +0000606 else if ( ( *flag & 32 ) == 0 )
607 y = (FT_Pos)FT_GET_SHORT();
608
609 x += y;
610 vec->y = x;
David Turnerd2b1f351999-12-16 23:11:37 +0000611 }
612
David Turnerc3128612000-06-23 05:02:13 +0000613 /* clear the touch tags */
614 for ( n = 0; n < n_points; n++ )
David Turnerb08fe2d2002-08-27 20:20:29 +0000615 outline->tags[n] &= FT_CURVE_TAG_ON;
David Turnerc3128612000-06-23 05:02:13 +0000616
David Turner8edbcab2001-06-19 08:28:24 +0000617 outline->n_points = (FT_UShort)n_points;
618 outline->n_contours = (FT_Short) n_contours;
David Turnerc3128612000-06-23 05:02:13 +0000619
David Turnerf7f82d72002-01-06 10:13:40 +0000620 load->byte_len = byte_len;
621
Werner Lembergbd5ae402000-07-05 04:32:02 +0000622 Fail:
David Turnerc3128612000-06-23 05:02:13 +0000623 return error;
David Turnerf7f82d72002-01-06 10:13:40 +0000624
625 Invalid_Outline:
626 error = TT_Err_Invalid_Outline;
627 goto Fail;
David Turnerc3128612000-06-23 05:02:13 +0000628 }
629
630
Werner Lemberg4a2305c2001-06-28 07:17:51 +0000631 FT_CALLBACK_DEF( FT_Error )
Werner Lemberg91db04c2002-04-01 14:25:28 +0000632 TT_Load_Composite_Glyph( TT_Loader loader )
David Turner90f68b72000-06-23 12:26:14 +0000633 {
Werner Lemberg91db04c2002-04-01 14:25:28 +0000634 FT_Error error;
635 FT_Stream stream = loader->stream;
636 FT_GlyphLoader gloader = loader->gloader;
David Turnereba5ad42002-03-14 12:56:35 +0000637 FT_SubGlyph subglyph;
Werner Lemberg91db04c2002-04-01 14:25:28 +0000638 FT_UInt num_subglyphs;
639 FT_Int byte_len = loader->byte_len;
David Turner90f68b72000-06-23 12:26:14 +0000640
Werner Lemberga929ba92000-06-25 06:47:11 +0000641
David Turner90f68b72000-06-23 12:26:14 +0000642 num_subglyphs = 0;
Werner Lemberga929ba92000-06-25 06:47:11 +0000643
David Turner90f68b72000-06-23 12:26:14 +0000644 do
645 {
646 FT_Fixed xx, xy, yy, yx;
647
Werner Lemberga929ba92000-06-25 06:47:11 +0000648
David Turner90f68b72000-06-23 12:26:14 +0000649 /* check that we can load a new subglyph */
David Turnereba5ad42002-03-14 12:56:35 +0000650 error = FT_GlyphLoader_CheckSubGlyphs( gloader, num_subglyphs + 1 );
Werner Lemberga929ba92000-06-25 06:47:11 +0000651 if ( error )
652 goto Fail;
Werner Lembergbd5ae402000-07-05 04:32:02 +0000653
Werner Lembergac812952002-01-06 16:42:44 +0000654 /* check space */
David Turnerf7f82d72002-01-06 10:13:40 +0000655 byte_len -= 4;
656 if ( byte_len < 0 )
657 goto Invalid_Composite;
658
David Turner90f68b72000-06-23 12:26:14 +0000659 subglyph = gloader->current.subglyphs + num_subglyphs;
660
661 subglyph->arg1 = subglyph->arg2 = 0;
662
David Turnera890c292002-03-22 12:55:23 +0000663 subglyph->flags = FT_GET_USHORT();
664 subglyph->index = FT_GET_USHORT();
David Turner90f68b72000-06-23 12:26:14 +0000665
Werner Lembergac812952002-01-06 16:42:44 +0000666 /* check space */
David Turnerf7f82d72002-01-06 10:13:40 +0000667 byte_len -= 2;
668 if ( subglyph->flags & ARGS_ARE_WORDS )
669 byte_len -= 2;
670 if ( subglyph->flags & WE_HAVE_A_SCALE )
671 byte_len -= 2;
672 else if ( subglyph->flags & WE_HAVE_AN_XY_SCALE )
673 byte_len -= 4;
674 else if ( subglyph->flags & WE_HAVE_A_2X2 )
675 byte_len -= 8;
676
677 if ( byte_len < 0 )
678 goto Invalid_Composite;
679
David Turner90f68b72000-06-23 12:26:14 +0000680 /* read arguments */
681 if ( subglyph->flags & ARGS_ARE_WORDS )
682 {
David Turnera890c292002-03-22 12:55:23 +0000683 subglyph->arg1 = FT_GET_SHORT();
684 subglyph->arg2 = FT_GET_SHORT();
David Turner90f68b72000-06-23 12:26:14 +0000685 }
686 else
687 {
David Turnera890c292002-03-22 12:55:23 +0000688 subglyph->arg1 = FT_GET_CHAR();
689 subglyph->arg2 = FT_GET_CHAR();
David Turner90f68b72000-06-23 12:26:14 +0000690 }
691
692 /* read transform */
693 xx = yy = 0x10000L;
694 xy = yx = 0;
695
696 if ( subglyph->flags & WE_HAVE_A_SCALE )
697 {
David Turnera890c292002-03-22 12:55:23 +0000698 xx = (FT_Fixed)FT_GET_SHORT() << 2;
David Turner90f68b72000-06-23 12:26:14 +0000699 yy = xx;
700 }
701 else if ( subglyph->flags & WE_HAVE_AN_XY_SCALE )
702 {
David Turnera890c292002-03-22 12:55:23 +0000703 xx = (FT_Fixed)FT_GET_SHORT() << 2;
704 yy = (FT_Fixed)FT_GET_SHORT() << 2;
David Turner90f68b72000-06-23 12:26:14 +0000705 }
706 else if ( subglyph->flags & WE_HAVE_A_2X2 )
707 {
David Turnera890c292002-03-22 12:55:23 +0000708 xx = (FT_Fixed)FT_GET_SHORT() << 2;
David Turnera890c292002-03-22 12:55:23 +0000709 yx = (FT_Fixed)FT_GET_SHORT() << 2;
David Turner318f3be2002-06-26 20:30:37 +0000710 xy = (FT_Fixed)FT_GET_SHORT() << 2;
David Turnera890c292002-03-22 12:55:23 +0000711 yy = (FT_Fixed)FT_GET_SHORT() << 2;
David Turner90f68b72000-06-23 12:26:14 +0000712 }
713
714 subglyph->transform.xx = xx;
715 subglyph->transform.xy = xy;
716 subglyph->transform.yx = yx;
717 subglyph->transform.yy = yy;
718
719 num_subglyphs++;
Werner Lemberg5811c7c2000-07-02 13:53:16 +0000720
Werner Lembergdcd2e142000-06-25 07:43:15 +0000721 } while ( subglyph->flags & MORE_COMPONENTS );
David Turner90f68b72000-06-23 12:26:14 +0000722
723 gloader->current.num_subglyphs = num_subglyphs;
724
725#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
726 {
David Turner7d3a2642002-03-20 10:49:31 +0000727 /* we must undo the FT_FRAME_ENTER in order to point to the */
David Turner90f68b72000-06-23 12:26:14 +0000728 /* composite instructions, if we find some. */
729 /* we will process them later... */
730 /* */
David Turner7d3a2642002-03-20 10:49:31 +0000731 loader->ins_pos = (FT_ULong)( FT_STREAM_POS() +
Werner Lemberg914b2892001-03-10 17:07:42 +0000732 stream->cursor - stream->limit );
David Turner90f68b72000-06-23 12:26:14 +0000733 }
734#endif
735
David Turnerf7f82d72002-01-06 10:13:40 +0000736 loader->byte_len = byte_len;
737
David Turner90f68b72000-06-23 12:26:14 +0000738 Fail:
739 return error;
David Turnerf7f82d72002-01-06 10:13:40 +0000740
741 Invalid_Composite:
742 error = TT_Err_Invalid_Composite;
743 goto Fail;
David Turner90f68b72000-06-23 12:26:14 +0000744 }
745
David Turnerc3128612000-06-23 05:02:13 +0000746
David Turnerbc82f1b2002-03-01 02:26:22 +0000747 FT_LOCAL_DEF( void )
Werner Lemberg4a2305c2001-06-28 07:17:51 +0000748 TT_Init_Glyph_Loading( TT_Face face )
David Turner994d7742000-06-25 04:49:19 +0000749 {
750 face->access_glyph_frame = TT_Access_Glyph_Frame;
751 face->read_glyph_header = TT_Load_Glyph_Header;
752 face->read_simple_glyph = TT_Load_Simple_Glyph;
753 face->read_composite_glyph = TT_Load_Composite_Glyph;
754 face->forget_glyph_frame = TT_Forget_Glyph_Frame;
755 }
756
David Turnerc3128612000-06-23 05:02:13 +0000757
758 /*************************************************************************/
759 /* */
760 /* <Function> */
761 /* TT_Process_Simple_Glyph */
762 /* */
763 /* <Description> */
764 /* Once a simple glyph has been loaded, it needs to be processed. */
765 /* Usually, this means scaling and hinting through bytecode */
Werner Lemberga929ba92000-06-25 06:47:11 +0000766 /* interpretation. */
David Turnerc3128612000-06-23 05:02:13 +0000767 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +0000768 static FT_Error
Werner Lemberg91db04c2002-04-01 14:25:28 +0000769 TT_Process_Simple_Glyph( TT_Loader load,
770 FT_Bool debug )
David Turnerc3128612000-06-23 05:02:13 +0000771 {
Werner Lemberg91db04c2002-04-01 14:25:28 +0000772 FT_GlyphLoader gloader = load->gloader;
773 FT_Outline* outline = &gloader->current.outline;
774 FT_UInt n_points = outline->n_points;
Werner Lembergb5349a92002-02-19 16:30:15 +0000775#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
Werner Lemberg91db04c2002-04-01 14:25:28 +0000776 FT_UInt n_ins;
Werner Lembergb5349a92002-02-19 16:30:15 +0000777#endif
Werner Lemberg91db04c2002-04-01 14:25:28 +0000778 TT_GlyphZone zone = &load->zone;
779 FT_Error error = TT_Err_Ok;
David Turnerc3128612000-06-23 05:02:13 +0000780
Werner Lemberg58b17f92000-07-27 23:29:08 +0000781 FT_UNUSED( debug ); /* used by truetype interpreter only */
Werner Lemberga929ba92000-06-25 06:47:11 +0000782
Werner Lemberge4b32a52000-10-31 20:42:18 +0000783
Werner Lembergb5349a92002-02-19 16:30:15 +0000784#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
David Turnerc3128612000-06-23 05:02:13 +0000785 n_ins = load->glyph->control_len;
Werner Lembergb5349a92002-02-19 16:30:15 +0000786#endif
David Turnerc3128612000-06-23 05:02:13 +0000787
Werner Lemberg78575dc2000-06-12 19:36:41 +0000788 /* add shadow points */
David Turnere49ab252000-05-16 23:44:38 +0000789
Werner Lemberg8bb07e62004-03-27 08:43:17 +0000790 /* Add two horizontal shadow points at n and n+1. */
David Turnerd2b1f351999-12-16 23:11:37 +0000791 /* We need the left side bearing and advance width. */
Werner Lemberg8bb07e62004-03-27 08:43:17 +0000792 /* Add two vertical shadow points at n+2 and n+3. */
793 /* We need the top side bearing and advance height. */
David Turnerd2b1f351999-12-16 23:11:37 +0000794
David Turner8f43c712000-02-02 12:16:19 +0000795 {
David Turnerf9b8dec2000-06-16 19:34:52 +0000796 FT_Vector* pp1;
797 FT_Vector* pp2;
Werner Lemberg8bb07e62004-03-27 08:43:17 +0000798 FT_Vector* pp3;
799 FT_Vector* pp4;
David Turnere49ab252000-05-16 23:44:38 +0000800
Werner Lemberga929ba92000-06-25 06:47:11 +0000801
David Turner8f43c712000-02-02 12:16:19 +0000802 /* pp1 = xMin - lsb */
David Turnerf0df85b2000-06-22 00:17:42 +0000803 pp1 = outline->points + n_points;
David Turner8f43c712000-02-02 12:16:19 +0000804 pp1->x = load->bbox.xMin - load->left_bearing;
805 pp1->y = 0;
David Turnere49ab252000-05-16 23:44:38 +0000806
David Turner8f43c712000-02-02 12:16:19 +0000807 /* pp2 = pp1 + aw */
808 pp2 = pp1 + 1;
809 pp2->x = pp1->x + load->advance;
810 pp2->y = 0;
David Turnere49ab252000-05-16 23:44:38 +0000811
Werner Lemberg8bb07e62004-03-27 08:43:17 +0000812 /* pp3 = top side bearing */
813 pp3 = pp1 + 2;
814 pp3->x = 0;
815 pp3->y = load->top_bearing + load->bbox.yMax;
816
817 /* pp4 = pp3 - ah */
818 pp4 = pp1 + 3;
819 pp4->x = 0;
820 pp4->y = pp3->y - load->vadvance;
821
David Turnerf0df85b2000-06-22 00:17:42 +0000822 outline->tags[n_points ] = 0;
823 outline->tags[n_points + 1] = 0;
Werner Lemberg8bb07e62004-03-27 08:43:17 +0000824 outline->tags[n_points + 2] = 0;
825 outline->tags[n_points + 3] = 0;
David Turner8f43c712000-02-02 12:16:19 +0000826 }
Werner Lemberg78575dc2000-06-12 19:36:41 +0000827
Werner Lemberg44bb3032004-04-25 20:15:11 +0000828 /* Note that we return four more points that are not */
829 /* part of the glyph outline. */
David Turnerd2b1f351999-12-16 23:11:37 +0000830
Werner Lemberg8bb07e62004-03-27 08:43:17 +0000831 n_points += 4;
David Turnerd2b1f351999-12-16 23:11:37 +0000832
Werner Lemberg44bb3032004-04-25 20:15:11 +0000833#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
834
835 if ( ((TT_Face)load->face)->doblend )
836 {
837 /* Deltas apply to the unscaled data. */
Werner Lemberg2b54eba2004-05-07 07:08:14 +0000838 FT_Vector* deltas;
839 FT_Memory memory = load->face->memory;
840 FT_StreamRec saved_stream = *(load->stream);
841 FT_UInt i;
Werner Lemberg44bb3032004-04-25 20:15:11 +0000842
843
Werner Lemberg2b54eba2004-05-07 07:08:14 +0000844 /* TT_Vary_Get_Glyph_Deltas uses a frame, thus we have to save */
845 /* (and restore) the current one */
846 load->stream->cursor = 0;
847 load->stream->limit = 0;
848
849 error = TT_Vary_Get_Glyph_Deltas( (TT_Face)(load->face),
850 load->glyph_index,
851 &deltas,
852 n_points );
853
854 *(load->stream) = saved_stream;
855
856 if ( error )
Werner Lemberg44bb3032004-04-25 20:15:11 +0000857 goto Exit;
858
859 for ( i = 0; i < n_points; ++i )
860 {
861 outline->points[i].x += deltas[i].x;
862 outline->points[i].y += deltas[i].y;
863 }
864
865 FT_FREE( deltas );
866 }
867
868#endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
869
David Turnerf0df85b2000-06-22 00:17:42 +0000870 /* set up zone for hinting */
871 tt_prepare_zone( zone, &gloader->current, 0, 0 );
David Turnerd2b1f351999-12-16 23:11:37 +0000872
David Turnerf0df85b2000-06-22 00:17:42 +0000873 /* eventually scale the glyph */
Werner Lemberga929ba92000-06-25 06:47:11 +0000874 if ( !( load->load_flags & FT_LOAD_NO_SCALE ) )
David Turnerd2b1f351999-12-16 23:11:37 +0000875 {
David Turnerf0df85b2000-06-22 00:17:42 +0000876 FT_Vector* vec = zone->cur;
877 FT_Vector* limit = vec + n_points;
David Turner2f0fdb92004-06-21 21:16:56 +0000878 FT_Fixed x_scale = ((TT_Size)load->size)->metrics.x_scale;
879 FT_Fixed y_scale = ((TT_Size)load->size)->metrics.y_scale;
Werner Lemberg5811c7c2000-07-02 13:53:16 +0000880
David Turnerd2b1f351999-12-16 23:11:37 +0000881 /* first scale the glyph points */
Werner Lemberg78575dc2000-06-12 19:36:41 +0000882 for ( ; vec < limit; vec++ )
David Turnerd2b1f351999-12-16 23:11:37 +0000883 {
David Turner8f43c712000-02-02 12:16:19 +0000884 vec->x = FT_MulFix( vec->x, x_scale );
885 vec->y = FT_MulFix( vec->y, y_scale );
David Turnerd2b1f351999-12-16 23:11:37 +0000886 }
David Turnerf0df85b2000-06-22 00:17:42 +0000887 }
David Turnerd2b1f351999-12-16 23:11:37 +0000888
David Turnerf0df85b2000-06-22 00:17:42 +0000889 cur_to_org( n_points, zone );
Werner Lemberg78575dc2000-06-12 19:36:41 +0000890
David Turnerf0df85b2000-06-22 00:17:42 +0000891 /* eventually hint the glyph */
Werner Lemberga929ba92000-06-25 06:47:11 +0000892 if ( IS_HINTED( load->load_flags ) )
David Turnerf0df85b2000-06-22 00:17:42 +0000893 {
Werner Lemberg8bb07e62004-03-27 08:43:17 +0000894 FT_Pos x = zone->org[n_points-4].x;
Werner Lemberg78575dc2000-06-12 19:36:41 +0000895
Werner Lemberga929ba92000-06-25 06:47:11 +0000896
David Turner87c0d302003-12-24 01:10:46 +0000897 x = FT_PIX_ROUND( x ) - x;
Werner Lembergb9ff4152004-11-19 10:35:52 +0000898 translate_array( n_points, zone->org, x, 0 );
David Turnerd2b1f351999-12-16 23:11:37 +0000899
David Turnerf0df85b2000-06-22 00:17:42 +0000900 org_to_cur( n_points, zone );
David Turnerd2b1f351999-12-16 23:11:37 +0000901
Werner Lemberg8bb07e62004-03-27 08:43:17 +0000902 zone->cur[n_points - 3].x = FT_PIX_ROUND( zone->cur[n_points - 3].x );
903 zone->cur[n_points - 1].y = FT_PIX_ROUND( zone->cur[n_points - 1].y );
David Turnerd2b1f351999-12-16 23:11:37 +0000904
David Turner8f43c712000-02-02 12:16:19 +0000905#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
Werner Lemberga929ba92000-06-25 06:47:11 +0000906
David Turnerf0df85b2000-06-22 00:17:42 +0000907 /* now consider hinting */
908 if ( n_ins > 0 )
909 {
David Turnerc3128612000-06-23 05:02:13 +0000910 error = TT_Set_CodeRange( load->exec, tt_coderange_glyph,
911 load->exec->glyphIns, n_ins );
Werner Lemberga929ba92000-06-25 06:47:11 +0000912 if ( error )
913 goto Exit;
Werner Lembergbd5ae402000-07-05 04:32:02 +0000914
David Turnerf0df85b2000-06-22 00:17:42 +0000915 load->exec->is_composite = FALSE;
David Turnerf0df85b2000-06-22 00:17:42 +0000916 load->exec->pts = *zone;
Werner Lemberg8bb07e62004-03-27 08:43:17 +0000917 load->exec->pts.n_points += 4;
David Turnerd2b1f351999-12-16 23:11:37 +0000918
David Turnerf0df85b2000-06-22 00:17:42 +0000919 error = TT_Run_Context( load->exec, debug );
920 if ( error && load->exec->pedantic_hinting )
David Turnerc3128612000-06-23 05:02:13 +0000921 goto Exit;
Werner Lembergbd5ae402000-07-05 04:32:02 +0000922
Werner Lemberg1429db62001-04-02 23:54:01 +0000923 error = TT_Err_Ok; /* ignore bytecode errors in non-pedantic mode */
David Turnerd2b1f351999-12-16 23:11:37 +0000924 }
Werner Lemberga929ba92000-06-25 06:47:11 +0000925
David Turnerf0df85b2000-06-22 00:17:42 +0000926#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
Werner Lemberga929ba92000-06-25 06:47:11 +0000927
David Turnerd2b1f351999-12-16 23:11:37 +0000928 }
929
930 /* save glyph phantom points */
David Turner8f43c712000-02-02 12:16:19 +0000931 if ( !load->preserve_pps )
David Turnerd2b1f351999-12-16 23:11:37 +0000932 {
Werner Lemberg8bb07e62004-03-27 08:43:17 +0000933 load->pp1 = zone->cur[n_points - 4];
934 load->pp2 = zone->cur[n_points - 3];
935 load->pp3 = zone->cur[n_points - 2];
936 load->pp4 = zone->cur[n_points - 1];
David Turnerd2b1f351999-12-16 23:11:37 +0000937 }
938
Werner Lemberg44bb3032004-04-25 20:15:11 +0000939#if defined( TT_CONFIG_OPTION_BYTECODE_INTERPRETER ) || \
940 defined( TT_CONFIG_OPTION_GX_VAR_SUPPORT )
David Turnerc3128612000-06-23 05:02:13 +0000941 Exit:
Werner Lemberge4b32a52000-10-31 20:42:18 +0000942#endif
Werner Lemberg44bb3032004-04-25 20:15:11 +0000943
David Turnerd2b1f351999-12-16 23:11:37 +0000944 return error;
945 }
946
947
948 /*************************************************************************/
949 /* */
950 /* <Function> */
David Turner8f43c712000-02-02 12:16:19 +0000951 /* load_truetype_glyph */
David Turnerd2b1f351999-12-16 23:11:37 +0000952 /* */
953 /* <Description> */
Werner Lemberg78575dc2000-06-12 19:36:41 +0000954 /* Loads a given truetype glyph. Handles composites and uses a */
955 /* TT_Loader object. */
David Turnerd2b1f351999-12-16 23:11:37 +0000956 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +0000957 static FT_Error
Werner Lemberg91db04c2002-04-01 14:25:28 +0000958 load_truetype_glyph( TT_Loader loader,
David Turner77b68b82003-01-08 09:59:17 +0000959 FT_UInt glyph_index,
960 FT_UInt recurse_count )
David Turnerd2b1f351999-12-16 23:11:37 +0000961 {
Werner Lemberg321cd272000-07-27 11:20:20 +0000962
963#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
Werner Lemberg91db04c2002-04-01 14:25:28 +0000964 FT_Stream stream = loader->stream;
Werner Lemberg321cd272000-07-27 11:20:20 +0000965#endif
966
Werner Lemberg91db04c2002-04-01 14:25:28 +0000967 FT_Error error;
Werner Lemberg2b54eba2004-05-07 07:08:14 +0000968 TT_Face face = (TT_Face)loader->face;
Werner Lemberg91db04c2002-04-01 14:25:28 +0000969 FT_ULong offset;
970 FT_Int contours_count;
Graham Asher13217f22002-07-18 15:59:23 +0000971 FT_UInt num_points, count;
Werner Lemberg91db04c2002-04-01 14:25:28 +0000972 FT_Fixed x_scale, y_scale;
973 FT_GlyphLoader gloader = loader->gloader;
974 FT_Bool opened_frame = 0;
David Turnere49ab252000-05-16 23:44:38 +0000975
Graham Asher13217f22002-07-18 15:59:23 +0000976#ifdef FT_CONFIG_OPTION_INCREMENTAL
Werner Lemberg2b54eba2004-05-07 07:08:14 +0000977 FT_StreamRec inc_stream;
978 FT_Data glyph_data;
979 FT_Bool glyph_data_loaded = 0;
Graham Asher13217f22002-07-18 15:59:23 +0000980#endif
Werner Lemberg58b17f92000-07-27 23:29:08 +0000981
Werner Lemberg44bb3032004-04-25 20:15:11 +0000982#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
983 FT_Vector *deltas;
984#endif
985
Werner Lemberg6ab56242003-06-04 07:59:58 +0000986
David Turner77b68b82003-01-08 09:59:17 +0000987 if ( recurse_count >= TT_MAX_COMPOSITE_RECURSE )
988 {
989 error = TT_Err_Invalid_Composite;
990 goto Exit;
991 }
Werner Lemberg7f74a522002-07-26 09:09:10 +0000992
David Turner8f43c712000-02-02 12:16:19 +0000993 /* check glyph index */
Graham Asher13217f22002-07-18 15:59:23 +0000994 if ( glyph_index >= (FT_UInt)face->root.num_glyphs )
David Turnerd2b1f351999-12-16 23:11:37 +0000995 {
David Turner8f43c712000-02-02 12:16:19 +0000996 error = TT_Err_Invalid_Glyph_Index;
David Turner90f68b72000-06-23 12:26:14 +0000997 goto Exit;
David Turnerd2b1f351999-12-16 23:11:37 +0000998 }
999
David Turner861ba622000-02-15 12:54:51 +00001000 loader->glyph_index = glyph_index;
Werner Lemberg0d9165e2002-03-07 21:59:59 +00001001 num_points = 0;
David Turnere49ab252000-05-16 23:44:38 +00001002
Werner Lemberg78575dc2000-06-12 19:36:41 +00001003 x_scale = 0x10000L;
1004 y_scale = 0x10000L;
1005 if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
David Turnerd2b1f351999-12-16 23:11:37 +00001006 {
David Turner2f0fdb92004-06-21 21:16:56 +00001007 x_scale = ((TT_Size)loader->size)->metrics.x_scale;
1008 y_scale = ((TT_Size)loader->size)->metrics.y_scale;
David Turner8f43c712000-02-02 12:16:19 +00001009 }
David Turnerd2b1f351999-12-16 23:11:37 +00001010
Werner Lemberg8bb07e62004-03-27 08:43:17 +00001011 /* get metrics, horizontal and vertical */
David Turner8f43c712000-02-02 12:16:19 +00001012 {
Werner Lemberg8bb07e62004-03-27 08:43:17 +00001013 FT_Short left_bearing = 0, top_bearing = 0;
1014 FT_UShort advance_width = 0, advance_height = 0;
1015
David Turnerd2b1f351999-12-16 23:11:37 +00001016
Graham Asher46960df2003-02-13 17:49:27 +00001017 Get_HMetrics( face, glyph_index,
1018 (FT_Bool)!( loader->load_flags &
1019 FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ),
1020 &left_bearing,
1021 &advance_width );
Werner Lemberg8bb07e62004-03-27 08:43:17 +00001022 Get_VMetrics( face, glyph_index,
1023 (FT_Bool)!( loader->load_flags &
1024 FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ),
1025 &top_bearing,
1026 &advance_height );
Werner Lemberg78575dc2000-06-12 19:36:41 +00001027
Graham Asher46960df2003-02-13 17:49:27 +00001028#ifdef FT_CONFIG_OPTION_INCREMENTAL
Werner Lemberg7f74a522002-07-26 09:09:10 +00001029
1030 /* If this is an incrementally loaded font see if there are */
1031 /* overriding metrics for this glyph. */
Graham Asherce121822002-08-01 15:29:17 +00001032 if ( face->root.internal->incremental_interface &&
1033 face->root.internal->incremental_interface->funcs->get_glyph_metrics )
Graham Asher13217f22002-07-18 15:59:23 +00001034 {
Graham Asher46960df2003-02-13 17:49:27 +00001035 FT_Incremental_MetricsRec metrics;
Werner Lemberg7f74a522002-07-26 09:09:10 +00001036
Werner Lembergb442ca12003-04-23 15:50:27 +00001037
1038 metrics.bearing_x = left_bearing;
1039 metrics.bearing_y = 0;
1040 metrics.advance = advance_width;
Graham Asherce121822002-08-01 15:29:17 +00001041 error = face->root.internal->incremental_interface->funcs->get_glyph_metrics(
1042 face->root.internal->incremental_interface->object,
Graham Asher46960df2003-02-13 17:49:27 +00001043 glyph_index, FALSE, &metrics );
Werner Lemberg7f74a522002-07-26 09:09:10 +00001044 if ( error )
1045 goto Exit;
Graham Asher46960df2003-02-13 17:49:27 +00001046 left_bearing = (FT_Short)metrics.bearing_x;
1047 advance_width = (FT_UShort)metrics.advance;
Graham Asher13217f22002-07-18 15:59:23 +00001048 }
1049
Werner Lemberg8bb07e62004-03-27 08:43:17 +00001050# if 0
1051 /* GWW: Do I do the same for vertical metrics ??? */
1052 if ( face->root.internal->incremental_interface &&
1053 face->root.internal->incremental_interface->funcs->get_glyph_metrics )
1054 {
1055 FT_Incremental_MetricsRec metrics;
1056
1057
1058 metrics.bearing_x = 0;
1059 metrics.bearing_y = top_bearing;
1060 metrics.advance = advance_height;
1061 error = face->root.internal->incremental_interface->funcs->get_glyph_metrics(
1062 face->root.internal->incremental_interface->object,
1063 glyph_index, TRUE, &metrics );
1064 if ( error )
1065 goto Exit;
1066 top_bearing = (FT_Short)metrics.bearing_y;
1067 advance_height = (FT_UShort)metrics.advance;
1068 }
1069# endif
1070
Werner Lemberg7f74a522002-07-26 09:09:10 +00001071#endif /* FT_CONFIG_OPTION_INCREMENTAL */
Graham Asher13217f22002-07-18 15:59:23 +00001072
David Turner8f43c712000-02-02 12:16:19 +00001073 loader->left_bearing = left_bearing;
1074 loader->advance = advance_width;
Werner Lemberg8bb07e62004-03-27 08:43:17 +00001075 loader->top_bearing = top_bearing;
1076 loader->vadvance = advance_height;
David Turner57d4de02001-06-08 13:29:36 +00001077
1078 if ( !loader->linear_def )
1079 {
1080 loader->linear_def = 1;
1081 loader->linear = advance_width;
1082 }
David Turner8f43c712000-02-02 12:16:19 +00001083 }
David Turnerd2b1f351999-12-16 23:11:37 +00001084
Graham Asher13217f22002-07-18 15:59:23 +00001085#ifdef FT_CONFIG_OPTION_INCREMENTAL
David Turnere49ab252000-05-16 23:44:38 +00001086
Werner Lemberg7f74a522002-07-26 09:09:10 +00001087 /* Set `offset' to the start of the glyph program relative to the */
1088 /* start of the 'glyf' table, and `count' to the length of the */
1089 /* glyph program in bytes. */
1090 /* */
1091 /* If we are loading glyph data via the incremental interface, set */
1092 /* the loader stream to a memory stream reading the data returned */
1093 /* by the interface. */
1094
Graham Asherce121822002-08-01 15:29:17 +00001095 if ( face->root.internal->incremental_interface )
Graham Asher13217f22002-07-18 15:59:23 +00001096 {
Graham Asherce121822002-08-01 15:29:17 +00001097 error = face->root.internal->incremental_interface->funcs->get_glyph_data(
1098 face->root.internal->incremental_interface->object,
1099 glyph_index, &glyph_data );
Werner Lemberg7f74a522002-07-26 09:09:10 +00001100 if ( error )
Graham Asher13217f22002-07-18 15:59:23 +00001101 goto Exit;
Werner Lemberg7f74a522002-07-26 09:09:10 +00001102
Graham Asherce121822002-08-01 15:29:17 +00001103 glyph_data_loaded = 1;
Werner Lemberg3c403e42002-08-06 21:47:40 +00001104 offset = 0;
1105 count = glyph_data.length;
1106
Werner Lembergb3d5e9c2002-07-28 05:05:24 +00001107 FT_MEM_ZERO( &inc_stream, sizeof ( inc_stream ) );
Werner Lemberg3c403e42002-08-06 21:47:40 +00001108 FT_Stream_OpenMemory( &inc_stream,
1109 glyph_data.pointer, glyph_data.length );
1110
Graham Asher13217f22002-07-18 15:59:23 +00001111 loader->stream = &inc_stream;
1112 }
1113 else
Werner Lemberg7f74a522002-07-26 09:09:10 +00001114
1115#endif /* FT_CONFIG_OPTION_INCREMENTAL */
Graham Asher13217f22002-07-18 15:59:23 +00001116
David Turnere70d5532005-02-22 16:53:06 +00001117 offset = tt_face_get_location( face, glyph_index, &count );
David Turnerd2b1f351999-12-16 23:11:37 +00001118
Werner Lemberg78575dc2000-06-12 19:36:41 +00001119 if ( count == 0 )
David Turner8f43c712000-02-02 12:16:19 +00001120 {
1121 /* as described by Frederic Loyer, these are spaces, and */
1122 /* not the unknown glyph. */
1123 loader->bbox.xMin = 0;
1124 loader->bbox.xMax = 0;
1125 loader->bbox.yMin = 0;
1126 loader->bbox.yMax = 0;
David Turnerd2b1f351999-12-16 23:11:37 +00001127
David Turner8f43c712000-02-02 12:16:19 +00001128 loader->pp1.x = 0;
1129 loader->pp2.x = loader->advance;
Werner Lemberg8bb07e62004-03-27 08:43:17 +00001130 loader->pp3.y = 0;
1131 loader->pp4.y = loader->pp3.y-loader->vadvance;
David Turnerd2b1f351999-12-16 23:11:37 +00001132
Werner Lemberg44bb3032004-04-25 20:15:11 +00001133#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
1134 if ( ((TT_Face)(loader->face))->doblend )
1135 {
1136 /* this must be done before scaling */
1137 FT_Memory memory = loader->face->memory;
1138
1139
Werner Lemberg5afaa672004-06-28 14:19:15 +00001140 error = TT_Vary_Get_Glyph_Deltas( (TT_Face)(loader->face),
1141 glyph_index, &deltas, 4 );
David Turnerc28b8c12004-06-24 20:18:24 +00001142 if ( error )
Werner Lemberg44bb3032004-04-25 20:15:11 +00001143 goto Exit;
1144
1145 loader->pp1.x += deltas[0].x; loader->pp1.y += deltas[0].y;
1146 loader->pp2.x += deltas[1].x; loader->pp2.y += deltas[1].y;
1147 loader->pp3.x += deltas[2].x; loader->pp3.y += deltas[2].y;
1148 loader->pp4.x += deltas[3].x; loader->pp4.y += deltas[3].y;
1149
1150 FT_FREE( deltas );
1151 }
1152#endif
1153
Werner Lemberg78575dc2000-06-12 19:36:41 +00001154 if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
Werner Lemberg8bb07e62004-03-27 08:43:17 +00001155 {
David Turner8f43c712000-02-02 12:16:19 +00001156 loader->pp2.x = FT_MulFix( loader->pp2.x, x_scale );
Werner Lemberg8bb07e62004-03-27 08:43:17 +00001157 loader->pp4.y = FT_MulFix( loader->pp4.y, y_scale );
1158 }
David Turnerd2b1f351999-12-16 23:11:37 +00001159
David Turner8f43c712000-02-02 12:16:19 +00001160#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
Werner Lembergdcd2e142000-06-25 07:43:15 +00001161
Werner Lemberg78575dc2000-06-12 19:36:41 +00001162 if ( loader->exec )
David Turner7bb7fed2000-02-28 11:23:36 +00001163 loader->exec->glyphSize = 0;
Werner Lembergdcd2e142000-06-25 07:43:15 +00001164
David Turner8f43c712000-02-02 12:16:19 +00001165#endif
Werner Lemberg5811c7c2000-07-02 13:53:16 +00001166
Werner Lemberg1429db62001-04-02 23:54:01 +00001167 error = TT_Err_Ok;
David Turner90f68b72000-06-23 12:26:14 +00001168 goto Exit;
David Turner8f43c712000-02-02 12:16:19 +00001169 }
David Turnerd2b1f351999-12-16 23:11:37 +00001170
Werner Lembergac812952002-01-06 16:42:44 +00001171 loader->byte_len = (FT_Int)count;
David Turnerf7f82d72002-01-06 10:13:40 +00001172
David Turner8f43c712000-02-02 12:16:19 +00001173 offset = loader->glyf_offset + offset;
David Turnerd2b1f351999-12-16 23:11:37 +00001174
David Turner90f68b72000-06-23 12:26:14 +00001175 /* access glyph frame */
David Turner994d7742000-06-25 04:49:19 +00001176 error = face->access_glyph_frame( loader, glyph_index, offset, count );
Werner Lemberga929ba92000-06-25 06:47:11 +00001177 if ( error )
1178 goto Exit;
David Turner90f68b72000-06-23 12:26:14 +00001179
1180 opened_frame = 1;
1181
David Turner8f43c712000-02-02 12:16:19 +00001182 /* read first glyph header */
David Turner994d7742000-06-25 04:49:19 +00001183 error = face->read_glyph_header( loader );
Werner Lemberga929ba92000-06-25 06:47:11 +00001184 if ( error )
1185 goto Fail;
David Turnerd2b1f351999-12-16 23:11:37 +00001186
David Turner90f68b72000-06-23 12:26:14 +00001187 contours_count = loader->n_contours;
David Turnerd2b1f351999-12-16 23:11:37 +00001188
David Turner8f43c712000-02-02 12:16:19 +00001189 count -= 10;
David Turnerd2b1f351999-12-16 23:11:37 +00001190
David Turner8f43c712000-02-02 12:16:19 +00001191 loader->pp1.x = loader->bbox.xMin - loader->left_bearing;
1192 loader->pp1.y = 0;
1193 loader->pp2.x = loader->pp1.x + loader->advance;
1194 loader->pp2.y = 0;
David Turnere49ab252000-05-16 23:44:38 +00001195
Werner Lemberg8bb07e62004-03-27 08:43:17 +00001196 loader->pp3.x = 0;
1197 loader->pp3.y = loader->top_bearing + loader->bbox.yMax;
1198 loader->pp4.x = 0;
1199 loader->pp4.y = loader->pp3.y - loader->vadvance;
1200
Werner Lemberg78575dc2000-06-12 19:36:41 +00001201 /***********************************************************************/
1202 /***********************************************************************/
1203 /***********************************************************************/
David Turnerd2b1f351999-12-16 23:11:37 +00001204
Werner Lemberg78575dc2000-06-12 19:36:41 +00001205 /* if it is a simple glyph, load it */
1206
1207 if ( contours_count >= 0 )
David Turner8f43c712000-02-02 12:16:19 +00001208 {
David Turnerf0df85b2000-06-22 00:17:42 +00001209 /* check that we can add the contours to the glyph */
David Turnereba5ad42002-03-14 12:56:35 +00001210 error = FT_GlyphLoader_CheckPoints( gloader, 0, contours_count );
Werner Lemberga929ba92000-06-25 06:47:11 +00001211 if ( error )
1212 goto Fail;
Werner Lemberg78575dc2000-06-12 19:36:41 +00001213
David Turner994d7742000-06-25 04:49:19 +00001214 error = face->read_simple_glyph( loader );
Werner Lemberga929ba92000-06-25 06:47:11 +00001215 if ( error )
1216 goto Fail;
Werner Lembergbd5ae402000-07-05 04:32:02 +00001217
David Turner8f43c712000-02-02 12:16:19 +00001218#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
Werner Lemberg5811c7c2000-07-02 13:53:16 +00001219
David Turnerc3128612000-06-23 05:02:13 +00001220 {
Werner Lemberg91db04c2002-04-01 14:25:28 +00001221 TT_Size size = (TT_Size)loader->size;
Werner Lembergdcd2e142000-06-25 07:43:15 +00001222
1223
David Turnerc3128612000-06-23 05:02:13 +00001224 error = TT_Process_Simple_Glyph( loader,
1225 (FT_Bool)( size && size->debug ) );
1226 }
Werner Lembergdcd2e142000-06-25 07:43:15 +00001227
David Turner8f43c712000-02-02 12:16:19 +00001228#else
Werner Lembergdcd2e142000-06-25 07:43:15 +00001229
David Turner5fe4c002000-07-26 19:04:08 +00001230 error = TT_Process_Simple_Glyph( loader, 0 );
Werner Lembergdcd2e142000-06-25 07:43:15 +00001231
David Turnere49ab252000-05-16 23:44:38 +00001232#endif
Werner Lembergdcd2e142000-06-25 07:43:15 +00001233
1234 if ( error )
1235 goto Fail;
David Turnerf0df85b2000-06-22 00:17:42 +00001236
1237 FT_GlyphLoader_Add( gloader );
David Turnerd2b1f351999-12-16 23:11:37 +00001238
David Turner8f43c712000-02-02 12:16:19 +00001239 /* Note: We could have put the simple loader source there */
1240 /* but the code is fat enough already :-) */
David Turner8f43c712000-02-02 12:16:19 +00001241 }
David Turner8f43c712000-02-02 12:16:19 +00001242
Werner Lemberg78575dc2000-06-12 19:36:41 +00001243 /***********************************************************************/
1244 /***********************************************************************/
1245 /***********************************************************************/
1246
1247 /* otherwise, load a composite! */
David Turner77b68b82003-01-08 09:59:17 +00001248 else if ( contours_count == -1 )
David Turner8f43c712000-02-02 12:16:19 +00001249 {
David Turnerc3128612000-06-23 05:02:13 +00001250 TT_GlyphSlot glyph = (TT_GlyphSlot)loader->glyph;
Werner Lembergb5349a92002-02-19 16:30:15 +00001251 FT_UInt start_point;
1252#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
1253 FT_UInt start_contour;
David Turnerc6a92202000-07-04 18:12:13 +00001254 FT_ULong ins_pos; /* position of composite instructions, if any */
Werner Lembergb5349a92002-02-19 16:30:15 +00001255#endif
Werner Lemberga929ba92000-06-25 06:47:11 +00001256
Werner Lembergbd5ae402000-07-05 04:32:02 +00001257
David Turner8f43c712000-02-02 12:16:19 +00001258 /* for each subglyph, read composite header */
David Turnerf0df85b2000-06-22 00:17:42 +00001259 start_point = gloader->base.outline.n_points;
Werner Lembergb5349a92002-02-19 16:30:15 +00001260#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
David Turnerf0df85b2000-06-22 00:17:42 +00001261 start_contour = gloader->base.outline.n_contours;
Werner Lembergb5349a92002-02-19 16:30:15 +00001262#endif
Werner Lembergbd5ae402000-07-05 04:32:02 +00001263
David Turner994d7742000-06-25 04:49:19 +00001264 error = face->read_composite_glyph( loader );
Werner Lemberga929ba92000-06-25 06:47:11 +00001265 if ( error )
1266 goto Fail;
David Turnered7f62a2000-03-28 11:19:28 +00001267
Werner Lembergb5349a92002-02-19 16:30:15 +00001268#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
David Turnerc6a92202000-07-04 18:12:13 +00001269 ins_pos = loader->ins_pos;
Werner Lembergb5349a92002-02-19 16:30:15 +00001270#endif
David Turner994d7742000-06-25 04:49:19 +00001271 face->forget_glyph_frame( loader );
David Turner90f68b72000-06-23 12:26:14 +00001272 opened_frame = 0;
1273
Werner Lemberg44bb3032004-04-25 20:15:11 +00001274#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
1275
1276 if ( face->doblend )
1277 {
1278 FT_Int i, limit;
1279 FT_SubGlyph subglyph;
1280 FT_Memory memory = face->root.memory;
1281
1282
1283 /* this provides additional offsets */
1284 /* for each component's translation */
1285
1286 if ( (error = TT_Vary_Get_Glyph_Deltas(
1287 face,
1288 glyph_index,
1289 &deltas,
David Turnerc28b8c12004-06-24 20:18:24 +00001290 gloader->current.num_subglyphs + 4 )) != 0 )
Werner Lemberg44bb3032004-04-25 20:15:11 +00001291 goto Exit;
1292
1293 /* Note: No subglyph reallocation here, our pointers are stable. */
1294 subglyph = gloader->current.subglyphs + gloader->base.num_subglyphs;
1295 limit = gloader->current.num_subglyphs;
1296
1297 for ( i = 0; i < limit; ++i, ++subglyph )
1298 {
1299 if ( subglyph->flags & ARGS_ARE_XY_VALUES )
1300 {
1301 subglyph->arg1 += deltas[i].x;
1302 subglyph->arg2 += deltas[i].y;
1303 }
1304 }
1305
1306 loader->pp1.x += deltas[i + 0].x; loader->pp1.y += deltas[i + 0].y;
1307 loader->pp2.x += deltas[i + 1].x; loader->pp2.y += deltas[i + 1].y;
1308 loader->pp3.x += deltas[i + 2].x; loader->pp3.y += deltas[i + 2].y;
1309 loader->pp4.x += deltas[i + 3].x; loader->pp4.y += deltas[i + 3].y;
1310
1311 FT_FREE( deltas );
1312 }
1313
1314#endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
1315
1316 if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
1317 {
1318 loader->pp1.x = FT_MulFix( loader->pp1.x, x_scale );
1319 loader->pp2.x = FT_MulFix( loader->pp2.x, x_scale );
1320 loader->pp3.y = FT_MulFix( loader->pp3.y, y_scale );
1321 loader->pp4.y = FT_MulFix( loader->pp4.y, y_scale );
1322 }
1323
David Turnered7f62a2000-03-28 11:19:28 +00001324 /* if the flag FT_LOAD_NO_RECURSE is set, we return the subglyph */
Werner Lemberg78575dc2000-06-12 19:36:41 +00001325 /* `as is' in the glyph slot (the client application will be */
Werner Lembergeed446d2002-08-16 12:46:52 +00001326 /* responsible for interpreting these data)... */
Werner Lemberg78575dc2000-06-12 19:36:41 +00001327 /* */
David Turnered7f62a2000-03-28 11:19:28 +00001328 if ( loader->load_flags & FT_LOAD_NO_RECURSE )
1329 {
David Turnered7f62a2000-03-28 11:19:28 +00001330 /* set up remaining glyph fields */
David Turnerf0df85b2000-06-22 00:17:42 +00001331 FT_GlyphLoader_Add( gloader );
Werner Lembergbd5ae402000-07-05 04:32:02 +00001332
Werner Lemberg91db04c2002-04-01 14:25:28 +00001333 glyph->num_subglyphs = gloader->base.num_subglyphs;
David Turnerb08fe2d2002-08-27 20:20:29 +00001334 glyph->format = FT_GLYPH_FORMAT_COMPOSITE;
Werner Lemberg91db04c2002-04-01 14:25:28 +00001335 glyph->subglyphs = gloader->base.subglyphs;
Werner Lembergbd5ae402000-07-05 04:32:02 +00001336
David Turner90f68b72000-06-23 12:26:14 +00001337 goto Exit;
David Turnered7f62a2000-03-28 11:19:28 +00001338 }
1339
David Turner8f43c712000-02-02 12:16:19 +00001340 /*********************************************************************/
Werner Lembergdcd2e142000-06-25 07:43:15 +00001341 /*********************************************************************/
1342 /*********************************************************************/
1343
1344 /* Now, read each subglyph independently. */
David Turner8f43c712000-02-02 12:16:19 +00001345 {
Werner Lemberg91db04c2002-04-01 14:25:28 +00001346 FT_Int n, num_base_points, num_new_points;
1347 FT_SubGlyph subglyph = 0;
Werner Lembergbd5ae402000-07-05 04:32:02 +00001348
Werner Lemberg91db04c2002-04-01 14:25:28 +00001349 FT_UInt num_subglyphs = gloader->current.num_subglyphs;
1350 FT_UInt num_base_subgs = gloader->base.num_subglyphs;
Werner Lembergbd5ae402000-07-05 04:32:02 +00001351
David Turnerc3128612000-06-23 05:02:13 +00001352
David Turnerf0df85b2000-06-22 00:17:42 +00001353 FT_GlyphLoader_Add( gloader );
Werner Lembergbd5ae402000-07-05 04:32:02 +00001354
David Turner74abee82000-06-27 23:31:53 +00001355 for ( n = 0; n < (FT_Int)num_subglyphs; n++ )
David Turnerd2b1f351999-12-16 23:11:37 +00001356 {
Werner Lemberg8bb07e62004-03-27 08:43:17 +00001357 FT_Vector pp1, pp2, pp3, pp4;
David Turnerf9b8dec2000-06-16 19:34:52 +00001358 FT_Pos x, y;
David Turnere49ab252000-05-16 23:44:38 +00001359
Werner Lembergdcd2e142000-06-25 07:43:15 +00001360
Werner Lemberga929ba92000-06-25 06:47:11 +00001361 /* Each time we call load_truetype_glyph in this loop, the */
1362 /* value of `gloader.base.subglyphs' can change due to table */
1363 /* reallocations. We thus need to recompute the subglyph */
1364 /* pointer on each iteration. */
David Turnerf0df85b2000-06-22 00:17:42 +00001365 subglyph = gloader->base.subglyphs + num_base_subgs + n;
Werner Lemberg78575dc2000-06-12 19:36:41 +00001366
David Turner8f43c712000-02-02 12:16:19 +00001367 pp1 = loader->pp1;
1368 pp2 = loader->pp2;
Werner Lemberg8bb07e62004-03-27 08:43:17 +00001369 pp3 = loader->pp3;
1370 pp4 = loader->pp4;
David Turnerd2b1f351999-12-16 23:11:37 +00001371
David Turnerf0df85b2000-06-22 00:17:42 +00001372 num_base_points = gloader->base.outline.n_points;
David Turnere49ab252000-05-16 23:44:38 +00001373
David Turner77b68b82003-01-08 09:59:17 +00001374 error = load_truetype_glyph( loader, subglyph->index,
Werner Lembergb442ca12003-04-23 15:50:27 +00001375 recurse_count + 1 );
Werner Lemberg78575dc2000-06-12 19:36:41 +00001376 if ( error )
1377 goto Fail;
David Turner3475e7f2000-05-17 20:56:01 +00001378
David Turner61d6b2b2001-05-16 17:49:07 +00001379 /* restore subglyph pointer */
David Turnerf0df85b2000-06-22 00:17:42 +00001380 subglyph = gloader->base.subglyphs + num_base_subgs + n;
1381
David Turner7bb7fed2000-02-28 11:23:36 +00001382 if ( subglyph->flags & USE_MY_METRICS )
1383 {
1384 pp1 = loader->pp1;
1385 pp2 = loader->pp2;
Werner Lemberg8bb07e62004-03-27 08:43:17 +00001386 pp3 = loader->pp3;
1387 pp4 = loader->pp4;
David Turner7bb7fed2000-02-28 11:23:36 +00001388 }
1389 else
David Turnerd2b1f351999-12-16 23:11:37 +00001390 {
David Turner8f43c712000-02-02 12:16:19 +00001391 loader->pp1 = pp1;
1392 loader->pp2 = pp2;
Werner Lemberg8bb07e62004-03-27 08:43:17 +00001393 loader->pp3 = pp3;
1394 loader->pp4 = pp4;
David Turnerd2b1f351999-12-16 23:11:37 +00001395 }
David Turnere49ab252000-05-16 23:44:38 +00001396
Werner Lembergdcd2e142000-06-25 07:43:15 +00001397 num_points = gloader->base.outline.n_points;
David Turnere49ab252000-05-16 23:44:38 +00001398
David Turner8f43c712000-02-02 12:16:19 +00001399 num_new_points = num_points - num_base_points;
David Turnere49ab252000-05-16 23:44:38 +00001400
David Turner8f43c712000-02-02 12:16:19 +00001401 /* now perform the transform required for this subglyph */
David Turnere49ab252000-05-16 23:44:38 +00001402
David Turner8f43c712000-02-02 12:16:19 +00001403 if ( subglyph->flags & ( WE_HAVE_A_SCALE |
1404 WE_HAVE_AN_XY_SCALE |
1405 WE_HAVE_A_2X2 ) )
David Turnerd2b1f351999-12-16 23:11:37 +00001406 {
Werner Lemberga929ba92000-06-25 06:47:11 +00001407 FT_Vector* cur = gloader->base.outline.points +
1408 num_base_points;
1409 FT_Vector* org = gloader->base.extra_points +
1410 num_base_points;
David Turnerf9b8dec2000-06-16 19:34:52 +00001411 FT_Vector* limit = cur + num_new_points;
David Turnerd2b1f351999-12-16 23:11:37 +00001412
Werner Lembergdcd2e142000-06-25 07:43:15 +00001413
David Turner8f43c712000-02-02 12:16:19 +00001414 for ( ; cur < limit; cur++, org++ )
David Turnerd2b1f351999-12-16 23:11:37 +00001415 {
David Turnerf0df85b2000-06-22 00:17:42 +00001416 FT_Vector_Transform( cur, &subglyph->transform );
1417 FT_Vector_Transform( org, &subglyph->transform );
David Turnerd2b1f351999-12-16 23:11:37 +00001418 }
1419 }
1420
David Turnerd2b1f351999-12-16 23:11:37 +00001421 /* apply offset */
1422
Werner Lemberg78575dc2000-06-12 19:36:41 +00001423 if ( !( subglyph->flags & ARGS_ARE_XY_VALUES ) )
David Turnerd2b1f351999-12-16 23:11:37 +00001424 {
David Turner74abee82000-06-27 23:31:53 +00001425 FT_UInt k = subglyph->arg1;
David Turnerf0df85b2000-06-22 00:17:42 +00001426 FT_UInt l = subglyph->arg2;
1427 FT_Vector* p1;
1428 FT_Vector* p2;
David Turnerd2b1f351999-12-16 23:11:37 +00001429
Werner Lembergdeb4e982000-06-29 03:14:25 +00001430
David Turner74abee82000-06-27 23:31:53 +00001431 if ( start_point + k >= (FT_UInt)num_base_points ||
David Turnerf0df85b2000-06-22 00:17:42 +00001432 l >= (FT_UInt)num_new_points )
David Turnerd2b1f351999-12-16 23:11:37 +00001433 {
1434 error = TT_Err_Invalid_Composite;
1435 goto Fail;
1436 }
1437
David Turnere49ab252000-05-16 23:44:38 +00001438 l += num_base_points;
1439
David Turnerf0df85b2000-06-22 00:17:42 +00001440 p1 = gloader->base.outline.points + start_point + k;
1441 p2 = gloader->base.outline.points + start_point + l;
Werner Lembergbd5ae402000-07-05 04:32:02 +00001442
David Turnerf0df85b2000-06-22 00:17:42 +00001443 x = p1->x - p2->x;
1444 y = p1->y - p2->y;
David Turnerd2b1f351999-12-16 23:11:37 +00001445 }
1446 else
1447 {
David Turner8f43c712000-02-02 12:16:19 +00001448 x = subglyph->arg1;
1449 y = subglyph->arg2;
David Turnerd2b1f351999-12-16 23:11:37 +00001450
Werner Lembergeed446d2002-08-16 12:46:52 +00001451 /* Use a default value dependent on */
1452 /* TT_CONFIG_OPTION_COMPONENT_OFFSET_SCALED. This is useful for old TT */
1453 /* fonts which don't set the xxx_COMPONENT_OFFSET bit. */
1454
1455#ifdef TT_CONFIG_OPTION_COMPONENT_OFFSET_SCALED
1456 if ( !( subglyph->flags & UNSCALED_COMPONENT_OFFSET ) &&
1457#else
1458 if ( ( subglyph->flags & SCALED_COMPONENT_OFFSET ) &&
1459#endif
1460 ( subglyph->flags & ( WE_HAVE_A_SCALE |
1461 WE_HAVE_AN_XY_SCALE |
1462 WE_HAVE_A_2X2 )) )
1463 {
1464#if 0
1465
1466 /*************************************************************************/
1467 /* */
1468 /* This algorithm is what Apple documents. But it doesn't work. */
1469 /* */
1470 int a = subglyph->transform.xx > 0 ? subglyph->transform.xx
1471 : -subglyph->transform.xx;
1472 int b = subglyph->transform.yx > 0 ? subglyph->transform.yx
1473 : -subglyph->transform.yx;
1474 int c = subglyph->transform.xy > 0 ? subglyph->transform.xy
1475 : -subglyph->transform.xy;
1476 int d = subglyph->transform.yy > 0 ? subglyph->transform.yy
1477 : -subglyph->transform.yy;
1478 int m = a > b ? a : b;
1479 int n = c > d ? c : d;
1480
1481
1482 if ( a - b <= 33 && a - b >= -33 )
1483 m *= 2;
1484 if ( c - d <= 33 && c - d >= -33 )
1485 n *= 2;
1486 x = FT_MulFix( x, m );
1487 y = FT_MulFix( y, n );
1488
1489#else /* 0 */
1490
1491 /*************************************************************************/
1492 /* */
1493 /* This algorithm is a guess and works much better than the above. */
1494 /* */
Werner Lemberg73861972003-06-05 04:31:05 +00001495 FT_Fixed mac_xscale = FT_SqrtFixed(
1496 FT_MulFix( subglyph->transform.xx,
1497 subglyph->transform.xx ) +
1498 FT_MulFix( subglyph->transform.xy,
1499 subglyph->transform.xy) );
1500 FT_Fixed mac_yscale = FT_SqrtFixed(
1501 FT_MulFix( subglyph->transform.yy,
1502 subglyph->transform.yy ) +
1503 FT_MulFix( subglyph->transform.yx,
1504 subglyph->transform.yx ) );
Werner Lembergeed446d2002-08-16 12:46:52 +00001505
1506
1507 x = FT_MulFix( x, mac_xscale );
1508 y = FT_MulFix( y, mac_yscale );
1509#endif /* 0 */
1510
1511 }
1512
Werner Lemberg78575dc2000-06-12 19:36:41 +00001513 if ( !( loader->load_flags & FT_LOAD_NO_SCALE ) )
David Turnerd2b1f351999-12-16 23:11:37 +00001514 {
David Turner8f43c712000-02-02 12:16:19 +00001515 x = FT_MulFix( x, x_scale );
1516 y = FT_MulFix( y, y_scale );
David Turnere49ab252000-05-16 23:44:38 +00001517
David Turner8f43c712000-02-02 12:16:19 +00001518 if ( subglyph->flags & ROUND_XY_TO_GRID )
Werner Lemberg78575dc2000-06-12 19:36:41 +00001519 {
David Turner87c0d302003-12-24 01:10:46 +00001520 x = FT_PIX_ROUND( x );
1521 y = FT_PIX_ROUND( y );
Werner Lemberg78575dc2000-06-12 19:36:41 +00001522 }
David Turnerd2b1f351999-12-16 23:11:37 +00001523 }
1524 }
1525
Werner Lemberg87a2bc72002-06-20 10:57:04 +00001526 if ( x || y )
David Turner61d6b2b2001-05-16 17:49:07 +00001527 {
1528 translate_array( num_new_points,
1529 gloader->base.outline.points + num_base_points,
1530 x, y );
1531
1532 translate_array( num_new_points,
1533 gloader->base.extra_points + num_base_points,
1534 x, y );
1535 }
David Turnerd2b1f351999-12-16 23:11:37 +00001536 }
David Turnere49ab252000-05-16 23:44:38 +00001537
Werner Lembergdcd2e142000-06-25 07:43:15 +00001538 /*******************************************************************/
1539 /*******************************************************************/
1540 /*******************************************************************/
David Turnerd2b1f351999-12-16 23:11:37 +00001541
Werner Lemberg5811c7c2000-07-02 13:53:16 +00001542 /* we have finished loading all sub-glyphs; now, look for */
Werner Lemberg78575dc2000-06-12 19:36:41 +00001543 /* instructions for this composite! */
David Turnerd2b1f351999-12-16 23:11:37 +00001544
David Turner8f43c712000-02-02 12:16:19 +00001545#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
Werner Lemberg78575dc2000-06-12 19:36:41 +00001546
Werner Lemberg78575dc2000-06-12 19:36:41 +00001547 if ( num_subglyphs > 0 &&
1548 loader->exec &&
Werner Lemberga7d2f5e2002-02-19 01:12:23 +00001549 ins_pos > 0 &&
Werner Lemberg78575dc2000-06-12 19:36:41 +00001550 subglyph->flags & WE_HAVE_INSTR )
David Turner8f43c712000-02-02 12:16:19 +00001551 {
David Turnerf9b8dec2000-06-16 19:34:52 +00001552 FT_UShort n_ins;
David Turner8f43c712000-02-02 12:16:19 +00001553 TT_ExecContext exec = loader->exec;
David Turnerb5713c52002-03-14 11:26:29 +00001554 TT_GlyphZone pts;
David Turnerf9b8dec2000-06-16 19:34:52 +00001555 FT_Vector* pp1;
David Turnere49ab252000-05-16 23:44:38 +00001556
Werner Lemberg78575dc2000-06-12 19:36:41 +00001557
David Turner8f43c712000-02-02 12:16:19 +00001558 /* read size of instructions */
David Turner7d3a2642002-03-20 10:49:31 +00001559 if ( FT_STREAM_SEEK( ins_pos ) ||
David Turnera890c292002-03-22 12:55:23 +00001560 FT_READ_USHORT( n_ins ) )
Werner Lemberg78575dc2000-06-12 19:36:41 +00001561 goto Fail;
Werner Lemberg1c0d4ac2000-06-06 20:41:48 +00001562 FT_TRACE5(( " Instructions size = %d\n", n_ins ));
David Turnere49ab252000-05-16 23:44:38 +00001563
Werner Lemberg5811c7c2000-07-02 13:53:16 +00001564 /* in some fonts? */
Werner Lemberg91db04c2002-04-01 14:25:28 +00001565 if ( n_ins == 0xFFFFU )
David Turnerc3128612000-06-23 05:02:13 +00001566 n_ins = 0;
1567
David Turner8f43c712000-02-02 12:16:19 +00001568 /* check it */
1569 if ( n_ins > face->max_profile.maxSizeOfInstructions )
1570 {
David Turnerc3128612000-06-23 05:02:13 +00001571 FT_TRACE0(( "Too many instructions (%d) in composite glyph %ld\n",
1572 n_ins, subglyph->index ));
David Turner662b3442002-01-03 16:56:59 +00001573 error = TT_Err_Too_Many_Hints;
1574 goto Fail;
David Turner8f43c712000-02-02 12:16:19 +00001575 }
David Turnere49ab252000-05-16 23:44:38 +00001576
David Turner8f43c712000-02-02 12:16:19 +00001577 /* read the instructions */
David Turner7d3a2642002-03-20 10:49:31 +00001578 if ( FT_STREAM_READ( exec->glyphIns, n_ins ) )
David Turner8f43c712000-02-02 12:16:19 +00001579 goto Fail;
David Turnere49ab252000-05-16 23:44:38 +00001580
David Turnerc3128612000-06-23 05:02:13 +00001581 glyph->control_data = exec->glyphIns;
1582 glyph->control_len = n_ins;
1583
David Turner8f43c712000-02-02 12:16:19 +00001584 error = TT_Set_CodeRange( exec,
1585 tt_coderange_glyph,
1586 exec->glyphIns,
1587 n_ins );
Werner Lemberg78575dc2000-06-12 19:36:41 +00001588 if ( error )
1589 goto Fail;
David Turnere49ab252000-05-16 23:44:38 +00001590
Werner Lemberg8bb07e62004-03-27 08:43:17 +00001591 error = FT_GlyphLoader_CheckPoints( gloader, num_points + 4, 0 );
Werner Lemberg6ab56242003-06-04 07:59:58 +00001592 if ( error )
1593 goto Fail;
1594
David Turner8f43c712000-02-02 12:16:19 +00001595 /* prepare the execution context */
Werner Lemberga929ba92000-06-25 06:47:11 +00001596 tt_prepare_zone( &exec->pts, &gloader->base,
1597 start_point, start_contour );
David Turnerf0df85b2000-06-22 00:17:42 +00001598 pts = &exec->pts;
David Turnere49ab252000-05-16 23:44:38 +00001599
Werner Lemberg8bb07e62004-03-27 08:43:17 +00001600 pts->n_points = (short)( num_points + 4 );
David Turner43a2f652000-07-05 18:23:38 +00001601 pts->n_contours = gloader->base.outline.n_contours;
David Turnere49ab252000-05-16 23:44:38 +00001602
David Turner8f43c712000-02-02 12:16:19 +00001603 /* add phantom points */
1604 pp1 = pts->cur + num_points;
1605 pp1[0] = loader->pp1;
1606 pp1[1] = loader->pp2;
Werner Lemberg8bb07e62004-03-27 08:43:17 +00001607 pp1[2] = loader->pp3;
1608 pp1[3] = loader->pp4;
David Turnere49ab252000-05-16 23:44:38 +00001609
Werner Lembergdeb4e982000-06-29 03:14:25 +00001610 pts->tags[num_points ] = 0;
David Turner41dbcbf2000-03-09 11:46:25 +00001611 pts->tags[num_points + 1] = 0;
Werner Lemberg8bb07e62004-03-27 08:43:17 +00001612 pts->tags[num_points + 2] = 0;
1613 pts->tags[num_points + 3] = 0;
David Turnere49ab252000-05-16 23:44:38 +00001614
David Turner8f43c712000-02-02 12:16:19 +00001615 /* if hinting, round the phantom points */
Werner Lemberg78575dc2000-06-12 19:36:41 +00001616 if ( IS_HINTED( loader->load_flags ) )
David Turner8f43c712000-02-02 12:16:19 +00001617 {
David Turner87c0d302003-12-24 01:10:46 +00001618 pp1[0].x = FT_PIX_ROUND( loader->pp1.x );
1619 pp1[1].x = FT_PIX_ROUND( loader->pp2.x );
Werner Lemberg8bb07e62004-03-27 08:43:17 +00001620 pp1[2].y = FT_PIX_ROUND( loader->pp3.y );
1621 pp1[3].y = FT_PIX_ROUND( loader->pp4.y );
David Turner8f43c712000-02-02 12:16:19 +00001622 }
David Turnere49ab252000-05-16 23:44:38 +00001623
David Turner8f43c712000-02-02 12:16:19 +00001624 {
David Turnerf9b8dec2000-06-16 19:34:52 +00001625 FT_UInt k;
Werner Lemberg78575dc2000-06-12 19:36:41 +00001626
1627
David Turner43a2f652000-07-05 18:23:38 +00001628 for ( k = 0; k < num_points; k++ )
David Turnerb08fe2d2002-08-27 20:20:29 +00001629 pts->tags[k] &= FT_CURVE_TAG_ON;
David Turner8f43c712000-02-02 12:16:19 +00001630 }
David Turnere49ab252000-05-16 23:44:38 +00001631
Werner Lemberg8bb07e62004-03-27 08:43:17 +00001632 cur_to_org( num_points + 4, pts );
David Turnere49ab252000-05-16 23:44:38 +00001633
David Turner8f43c712000-02-02 12:16:19 +00001634 /* now consider hinting */
Werner Lembergdcd2e142000-06-25 07:43:15 +00001635 if ( IS_HINTED( loader->load_flags ) && n_ins > 0 )
David Turner8f43c712000-02-02 12:16:19 +00001636 {
1637 exec->is_composite = TRUE;
David Turnerc3128612000-06-23 05:02:13 +00001638 error = TT_Run_Context( exec, ((TT_Size)loader->size)->debug );
David Turner8f43c712000-02-02 12:16:19 +00001639 if ( error && exec->pedantic_hinting )
1640 goto Fail;
1641 }
David Turnere49ab252000-05-16 23:44:38 +00001642
David Turner8f43c712000-02-02 12:16:19 +00001643 /* save glyph origin and advance points */
1644 loader->pp1 = pp1[0];
1645 loader->pp2 = pp1[1];
Werner Lemberg8bb07e62004-03-27 08:43:17 +00001646 loader->pp3 = pp1[2];
1647 loader->pp4 = pp1[3];
David Turner8f43c712000-02-02 12:16:19 +00001648 }
Werner Lembergdcd2e142000-06-25 07:43:15 +00001649
Werner Lemberg78575dc2000-06-12 19:36:41 +00001650#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
Werner Lembergdcd2e142000-06-25 07:43:15 +00001651
David Turnerd2b1f351999-12-16 23:11:37 +00001652 }
Werner Lemberg78575dc2000-06-12 19:36:41 +00001653 /* end of composite loading */
David Turnerd2b1f351999-12-16 23:11:37 +00001654 }
David Turner77b68b82003-01-08 09:59:17 +00001655 else
1656 {
1657 /* invalid composite count ( negative but not -1 ) */
1658 error = TT_Err_Invalid_Outline;
1659 goto Fail;
1660 }
David Turnerd2b1f351999-12-16 23:11:37 +00001661
Werner Lemberg78575dc2000-06-12 19:36:41 +00001662 /***********************************************************************/
1663 /***********************************************************************/
1664 /***********************************************************************/
David Turnerd2b1f351999-12-16 23:11:37 +00001665
David Turner8f43c712000-02-02 12:16:19 +00001666 Fail:
Werner Lemberga929ba92000-06-25 06:47:11 +00001667 if ( opened_frame )
David Turner994d7742000-06-25 04:49:19 +00001668 face->forget_glyph_frame( loader );
David Turner90f68b72000-06-23 12:26:14 +00001669
1670 Exit:
Graham Asherce121822002-08-01 15:29:17 +00001671
1672#ifdef FT_CONFIG_OPTION_INCREMENTAL
Werner Lemberg3c403e42002-08-06 21:47:40 +00001673 if ( glyph_data_loaded )
1674 face->root.internal->incremental_interface->funcs->free_glyph_data(
1675 face->root.internal->incremental_interface->object,
1676 &glyph_data );
Graham Asherce121822002-08-01 15:29:17 +00001677#endif
1678
David Turnere49ab252000-05-16 23:44:38 +00001679 return error;
David Turner8f43c712000-02-02 12:16:19 +00001680 }
1681
1682
Graham Asher13217f22002-07-18 15:59:23 +00001683 static FT_Error
David Turnerb5713c52002-03-14 11:26:29 +00001684 compute_glyph_metrics( TT_Loader loader,
Werner Lemberg4a2305c2001-06-28 07:17:51 +00001685 FT_UInt glyph_index )
David Turner8f43c712000-02-02 12:16:19 +00001686 {
David Turnerf9b8dec2000-06-16 19:34:52 +00001687 FT_BBox bbox;
David Turnerc3128612000-06-23 05:02:13 +00001688 TT_Face face = (TT_Face)loader->face;
Werner Lembergcf24d512001-06-18 14:23:45 +00001689 FT_Fixed y_scale;
David Turner8f43c712000-02-02 12:16:19 +00001690 TT_GlyphSlot glyph = loader->glyph;
David Turnerc3128612000-06-23 05:02:13 +00001691 TT_Size size = (TT_Size)loader->size;
David Turnere49ab252000-05-16 23:44:38 +00001692
Werner Lembergdcd2e142000-06-25 07:43:15 +00001693
Werner Lemberg78575dc2000-06-12 19:36:41 +00001694 y_scale = 0x10000L;
1695 if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
David Turner8f43c712000-02-02 12:16:19 +00001696 y_scale = size->root.metrics.y_scale;
David Turnere49ab252000-05-16 23:44:38 +00001697
David Turnerb08fe2d2002-08-27 20:20:29 +00001698 if ( glyph->format != FT_GLYPH_FORMAT_COMPOSITE )
David Turner8f43c712000-02-02 12:16:19 +00001699 {
David Turnerb08fe2d2002-08-27 20:20:29 +00001700 glyph->outline.flags &= ~FT_OUTLINE_SINGLE_PASS;
Werner Lemberg78575dc2000-06-12 19:36:41 +00001701
David Turnerf0df85b2000-06-22 00:17:42 +00001702 /* copy outline to our glyph slot */
David Turnereba5ad42002-03-14 12:56:35 +00001703 FT_GlyphLoader_CopyPoints( glyph->internal->loader, loader->gloader );
David Turner54e75742000-11-04 02:52:02 +00001704 glyph->outline = glyph->internal->loader->base.outline;
Werner Lembergbd5ae402000-07-05 04:32:02 +00001705
David Turnered7f62a2000-03-28 11:19:28 +00001706 /* translate array so that (0,0) is the glyph's origin */
David Turnerf0df85b2000-06-22 00:17:42 +00001707 FT_Outline_Translate( &glyph->outline, -loader->pp1.x, 0 );
David Turnere49ab252000-05-16 23:44:38 +00001708
David Turnered7f62a2000-03-28 11:19:28 +00001709 FT_Outline_Get_CBox( &glyph->outline, &bbox );
1710
Werner Lemberg78575dc2000-06-12 19:36:41 +00001711 if ( IS_HINTED( loader->load_flags ) )
David Turnered7f62a2000-03-28 11:19:28 +00001712 {
1713 /* grid-fit the bounding box */
David Turner87c0d302003-12-24 01:10:46 +00001714 bbox.xMin = FT_PIX_FLOOR( bbox.xMin );
1715 bbox.yMin = FT_PIX_FLOOR( bbox.yMin );
1716 bbox.xMax = FT_PIX_CEIL( bbox.xMax );
1717 bbox.yMax = FT_PIX_CEIL( bbox.yMax );
David Turnered7f62a2000-03-28 11:19:28 +00001718 }
David Turner8f43c712000-02-02 12:16:19 +00001719 }
David Turnered7f62a2000-03-28 11:19:28 +00001720 else
1721 bbox = loader->bbox;
David Turnerd2b1f351999-12-16 23:11:37 +00001722
Werner Lemberga929ba92000-06-25 06:47:11 +00001723 /* get the device-independent horizontal advance. It is scaled later */
1724 /* by the base layer. */
David Turnerd2b1f351999-12-16 23:11:37 +00001725 {
David Turner57d4de02001-06-08 13:29:36 +00001726 FT_Pos advance = loader->linear;
David Turnerd2b1f351999-12-16 23:11:37 +00001727
Werner Lemberga929ba92000-06-25 06:47:11 +00001728
Werner Lemberg5811c7c2000-07-02 13:53:16 +00001729 /* the flag FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH was introduced to */
1730 /* correctly support DynaLab fonts, which have an incorrect */
1731 /* `advance_Width_Max' field! It is used, to my knowledge, */
1732 /* exclusively in the X-TrueType font server. */
1733 /* */
Werner Lemberg91db04c2002-04-01 14:25:28 +00001734 if ( face->postscript.isFixedPitch &&
Werner Lemberg78575dc2000-06-12 19:36:41 +00001735 ( loader->load_flags & FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ) == 0 )
David Turnerd2b1f351999-12-16 23:11:37 +00001736 advance = face->horizontal.advance_Width_Max;
1737
David Turnerf0df85b2000-06-22 00:17:42 +00001738 /* we need to return the advance in font units in linearHoriAdvance, */
Werner Lemberga929ba92000-06-25 06:47:11 +00001739 /* it will be scaled later by the base layer. */
David Turnerf0df85b2000-06-22 00:17:42 +00001740 glyph->linearHoriAdvance = advance;
David Turnerd2b1f351999-12-16 23:11:37 +00001741 }
1742
1743 glyph->metrics.horiBearingX = bbox.xMin;
1744 glyph->metrics.horiBearingY = bbox.yMax;
David Turner8f43c712000-02-02 12:16:19 +00001745 glyph->metrics.horiAdvance = loader->pp2.x - loader->pp1.x;
David Turnerd2b1f351999-12-16 23:11:37 +00001746
David Turnerbce29862001-12-14 14:52:58 +00001747 /* don't forget to hint the advance when we need to */
1748 if ( IS_HINTED( loader->load_flags ) )
David Turner87c0d302003-12-24 01:10:46 +00001749 glyph->metrics.horiAdvance = FT_PIX_ROUND( glyph->metrics.horiAdvance );
David Turnerbce29862001-12-14 14:52:58 +00001750
David Turnerd2b1f351999-12-16 23:11:37 +00001751 /* Now take care of vertical metrics. In the case where there is */
1752 /* no vertical information within the font (relatively common), make */
1753 /* up some metrics by `hand'... */
1754
1755 {
David Turnerf9b8dec2000-06-16 19:34:52 +00001756 FT_Short top_bearing; /* vertical top side bearing (EM units) */
1757 FT_UShort advance_height; /* vertical advance height (EM units) */
David Turnerd2b1f351999-12-16 23:11:37 +00001758
Werner Lemberg91db04c2002-04-01 14:25:28 +00001759 FT_Pos left; /* scaled vertical left side bearing */
1760 FT_Pos top; /* scaled vertical top side bearing */
1761 FT_Pos advance; /* scaled vertical advance height */
David Turnerd2b1f351999-12-16 23:11:37 +00001762
Werner Lemberg56a4d872004-06-03 07:56:21 +00001763
Graham Asher13217f22002-07-18 15:59:23 +00001764 /* Get the unscaled top bearing and advance height. */
Graham Asher46960df2003-02-13 17:49:27 +00001765 if ( face->vertical_info &&
David Turnerd2b1f351999-12-16 23:11:37 +00001766 face->vertical.number_Of_VMetrics > 0 )
1767 {
Werner Lemberg49f4d342005-06-16 19:07:08 +00001768 top_bearing = (FT_Short)FT_DivFix( loader->pp3.y - bbox.yMax,
1769 y_scale );
1770
1771 if ( loader->pp3.y <= loader->pp4.y )
1772 advance_height = 0;
1773 else
1774 advance_height = (FT_UShort)FT_DivFix( loader->pp3.y - loader->pp4.y,
1775 y_scale );
David Turnerd2b1f351999-12-16 23:11:37 +00001776 }
1777 else
1778 {
Werner Lemberg49f4d342005-06-16 19:07:08 +00001779 FT_Short max_height, height;
1780
1781
1782 /* XXX Compute top side bearing and advance height in */
1783 /* Get_VMetrics instead of here. */
David Turnerd2b1f351999-12-16 23:11:37 +00001784
Werner Lemberg78575dc2000-06-12 19:36:41 +00001785 /* NOTE: The OS/2 values are the only `portable' ones, */
1786 /* which is why we use them, if there is an OS/2 */
1787 /* table in the font. Otherwise, we use the */
1788 /* values defined in the horizontal header. */
Werner Lemberg49f4d342005-06-16 19:07:08 +00001789
1790 height = FT_DivFix( bbox.yMax - bbox.yMin, y_scale );
Werner Lemberg91db04c2002-04-01 14:25:28 +00001791 if ( face->os2.version != 0xFFFFU )
David Turnerd2b1f351999-12-16 23:11:37 +00001792 {
Werner Lemberg49f4d342005-06-16 19:07:08 +00001793 /* sTypoDescender is negative */
1794 max_height = face->os2.sTypoAscender - face->os2.sTypoDescender;
1795
1796 top_bearing = (FT_Short)( ( max_height - height ) / 2 );
1797 advance_height = (FT_UShort)( max_height + face->os2.sTypoLineGap );
David Turnerd2b1f351999-12-16 23:11:37 +00001798 }
1799 else
1800 {
Werner Lemberg49f4d342005-06-16 19:07:08 +00001801 max_height = face->horizontal.Ascender + face->horizontal.Descender;
1802
1803 top_bearing = (FT_Short)( ( max_height - height ) / 2 );
1804 advance_height = (FT_UShort)( max_height +
Werner Lemberg78575dc2000-06-12 19:36:41 +00001805 face->horizontal.Line_Gap );
David Turnerd2b1f351999-12-16 23:11:37 +00001806 }
1807 }
1808
Graham Asher46960df2003-02-13 17:49:27 +00001809#ifdef FT_CONFIG_OPTION_INCREMENTAL
1810
1811 /* If this is an incrementally loaded font see if there are */
1812 /* overriding metrics for this glyph. */
1813 if ( face->root.internal->incremental_interface &&
1814 face->root.internal->incremental_interface->funcs->get_glyph_metrics )
1815 {
1816 FT_Incremental_MetricsRec metrics;
Werner Lemberg3ab770b2005-03-08 20:24:56 +00001817 FT_Error error = TT_Err_Ok;
Graham Asher46960df2003-02-13 17:49:27 +00001818
Werner Lembergb442ca12003-04-23 15:50:27 +00001819
1820 metrics.bearing_x = 0;
1821 metrics.bearing_y = top_bearing;
Werner Lemberg49f4d342005-06-16 19:07:08 +00001822 metrics.advance = advance_height;
Graham Asher46960df2003-02-13 17:49:27 +00001823 error =
1824 face->root.internal->incremental_interface->funcs->get_glyph_metrics(
1825 face->root.internal->incremental_interface->object,
1826 glyph_index, TRUE, &metrics );
1827
1828 if ( error )
1829 return error;
1830
1831 top_bearing = (FT_Short)metrics.bearing_y;
1832 advance_height = (FT_UShort)metrics.advance;
1833 }
1834
Werner Lemberg8bb07e62004-03-27 08:43:17 +00001835 /* GWW: Do vertical metrics get loaded incrementally too? */
1836
Graham Asher46960df2003-02-13 17:49:27 +00001837#endif /* FT_CONFIG_OPTION_INCREMENTAL */
1838
David Turnerd2b1f351999-12-16 23:11:37 +00001839 /* scale the metrics */
Werner Lemberg78575dc2000-06-12 19:36:41 +00001840 if ( !( loader->load_flags & FT_LOAD_NO_SCALE ) )
David Turnerd2b1f351999-12-16 23:11:37 +00001841 {
Werner Lemberg49f4d342005-06-16 19:07:08 +00001842 top = FT_MulFix( top_bearing, y_scale );
David Turner8f43c712000-02-02 12:16:19 +00001843 advance = FT_MulFix( advance_height, y_scale );
David Turnerd2b1f351999-12-16 23:11:37 +00001844 }
1845 else
1846 {
Werner Lemberg49f4d342005-06-16 19:07:08 +00001847 top = top_bearing;
David Turnerd2b1f351999-12-16 23:11:37 +00001848 advance = advance_height;
1849 }
1850
Werner Lemberga929ba92000-06-25 06:47:11 +00001851 /* set the advance height in design units. It is scaled later by */
1852 /* the base layer. */
David Turnerf0df85b2000-06-22 00:17:42 +00001853 glyph->linearVertAdvance = advance_height;
David Turnerd2b1f351999-12-16 23:11:37 +00001854
Werner Lemberga929ba92000-06-25 06:47:11 +00001855 /* XXX: for now, we have no better algorithm for the lsb, but it */
1856 /* should work fine. */
1857 /* */
David Turnerd2b1f351999-12-16 23:11:37 +00001858 left = ( bbox.xMin - bbox.xMax ) / 2;
1859
1860 /* grid-fit them if necessary */
Werner Lemberg78575dc2000-06-12 19:36:41 +00001861 if ( IS_HINTED( loader->load_flags ) )
David Turnerd2b1f351999-12-16 23:11:37 +00001862 {
David Turner87c0d302003-12-24 01:10:46 +00001863 left = FT_PIX_FLOOR( left );
Werner Lemberg49f4d342005-06-16 19:07:08 +00001864 /* top should be floor'ed */
1865 top = FT_PIX_FLOOR( top );
David Turner87c0d302003-12-24 01:10:46 +00001866 advance = FT_PIX_ROUND( advance );
David Turnerd2b1f351999-12-16 23:11:37 +00001867 }
1868
1869 glyph->metrics.vertBearingX = left;
1870 glyph->metrics.vertBearingY = top;
1871 glyph->metrics.vertAdvance = advance;
1872 }
1873
Werner Lembergdcd2e142000-06-25 07:43:15 +00001874 /* adjust advance width to the value contained in the hdmx table */
David Turner8f43c712000-02-02 12:16:19 +00001875 if ( !face->postscript.isFixedPitch && size &&
Werner Lemberg78575dc2000-06-12 19:36:41 +00001876 IS_HINTED( loader->load_flags ) )
David Turnerd2b1f351999-12-16 23:11:37 +00001877 {
David Turnere5680272005-02-26 00:12:04 +00001878 FT_Byte* widthp = Get_Advance_WidthPtr( face,
1879 size->root.metrics.x_ppem,
1880 glyph_index );
Werner Lembergdcd2e142000-06-25 07:43:15 +00001881
1882
David Turnere5680272005-02-26 00:12:04 +00001883 if ( widthp )
1884 glyph->metrics.horiAdvance = *widthp << 6;
David Turnerd2b1f351999-12-16 23:11:37 +00001885 }
1886
David Turnerd2b1f351999-12-16 23:11:37 +00001887 /* set glyph dimensions */
1888 glyph->metrics.width = bbox.xMax - bbox.xMin;
1889 glyph->metrics.height = bbox.yMax - bbox.yMin;
Graham Asher13217f22002-07-18 15:59:23 +00001890
1891 return 0;
David Turner8f43c712000-02-02 12:16:19 +00001892 }
David Turnerd2b1f351999-12-16 23:11:37 +00001893
David Turnerd2b1f351999-12-16 23:11:37 +00001894
Werner Lemberg78575dc2000-06-12 19:36:41 +00001895 /*************************************************************************/
1896 /* */
1897 /* <Function> */
1898 /* TT_Load_Glyph */
1899 /* */
1900 /* <Description> */
1901 /* A function used to load a single glyph within a given glyph slot, */
1902 /* for a given size. */
1903 /* */
1904 /* <Input> */
1905 /* glyph :: A handle to a target slot object where the glyph */
1906 /* will be loaded. */
1907 /* */
1908 /* size :: A handle to the source face size at which the glyph */
1909 /* must be scaled/loaded. */
1910 /* */
1911 /* glyph_index :: The index of the glyph in the font file. */
1912 /* */
1913 /* load_flags :: A flag indicating what to load for this glyph. The */
1914 /* FT_LOAD_XXX constants can be used to control the */
1915 /* glyph loading process (e.g., whether the outline */
1916 /* should be scaled, whether to load bitmaps or not, */
1917 /* whether to hint the outline, etc). */
1918 /* */
1919 /* <Return> */
Werner Lemberga929ba92000-06-25 06:47:11 +00001920 /* FreeType error code. 0 means success. */
Werner Lemberg78575dc2000-06-12 19:36:41 +00001921 /* */
David Turnerbc82f1b2002-03-01 02:26:22 +00001922 FT_LOCAL_DEF( FT_Error )
Werner Lemberg4a2305c2001-06-28 07:17:51 +00001923 TT_Load_Glyph( TT_Size size,
1924 TT_GlyphSlot glyph,
Werner Lembergc3dc56b2004-04-19 06:13:50 +00001925 FT_UInt glyph_index,
Werner Lemberge59dc912002-09-21 18:43:10 +00001926 FT_Int32 load_flags )
David Turner8f43c712000-02-02 12:16:19 +00001927 {
David Turner4e7eeee2002-02-28 16:10:29 +00001928 SFNT_Service sfnt;
Werner Lemberg91db04c2002-04-01 14:25:28 +00001929 TT_Face face;
1930 FT_Stream stream;
1931 FT_Error error;
1932 TT_LoaderRec loader;
David Turnere49ab252000-05-16 23:44:38 +00001933
Werner Lemberg78575dc2000-06-12 19:36:41 +00001934
David Turner8f43c712000-02-02 12:16:19 +00001935 face = (TT_Face)glyph->face;
David Turner4e7eeee2002-02-28 16:10:29 +00001936 sfnt = (SFNT_Service)face->sfnt;
David Turner8f43c712000-02-02 12:16:19 +00001937 stream = face->root.stream;
Werner Lemberg3ab770b2005-03-08 20:24:56 +00001938 error = TT_Err_Ok;
David Turnered7f62a2000-03-28 11:19:28 +00001939
Werner Lemberg78575dc2000-06-12 19:36:41 +00001940 if ( !size || ( load_flags & FT_LOAD_NO_SCALE ) ||
1941 ( load_flags & FT_LOAD_NO_RECURSE ) )
David Turner8f43c712000-02-02 12:16:19 +00001942 {
1943 size = NULL;
1944 load_flags |= FT_LOAD_NO_SCALE |
1945 FT_LOAD_NO_HINTING |
1946 FT_LOAD_NO_BITMAP;
1947 }
1948
David Turnered7f62a2000-03-28 11:19:28 +00001949 glyph->num_subglyphs = 0;
1950
David Turner8f43c712000-02-02 12:16:19 +00001951#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
Werner Lemberg4b680072000-11-07 06:30:29 +00001952
1953 /* try to load embedded bitmap if any */
1954 /* */
1955 /* XXX: The convention should be emphasized in */
1956 /* the documents because it can be confusing. */
Werner Lemberg78575dc2000-06-12 19:36:41 +00001957 if ( size &&
Werner Lemberg91db04c2002-04-01 14:25:28 +00001958 size->strike_index != 0xFFFFU &&
David Turnerf96594f2000-11-06 23:07:51 +00001959 sfnt->load_sbits &&
1960 ( load_flags & FT_LOAD_NO_BITMAP ) == 0 )
1961
David Turner8f43c712000-02-02 12:16:19 +00001962 {
David Turnerb5713c52002-03-14 11:26:29 +00001963 TT_SBit_MetricsRec metrics;
David Turnere49ab252000-05-16 23:44:38 +00001964
Werner Lemberg78575dc2000-06-12 19:36:41 +00001965
David Turner8f43c712000-02-02 12:16:19 +00001966 error = sfnt->load_sbit_image( face,
Werner Lemberg73861972003-06-05 04:31:05 +00001967 (FT_ULong)size->strike_index,
Werner Lembergc3dc56b2004-04-19 06:13:50 +00001968 glyph_index,
Werner Lemberg73861972003-06-05 04:31:05 +00001969 (FT_Int)load_flags,
David Turner8f43c712000-02-02 12:16:19 +00001970 stream,
1971 &glyph->bitmap,
1972 &metrics );
1973 if ( !error )
1974 {
1975 glyph->outline.n_points = 0;
1976 glyph->outline.n_contours = 0;
1977
David Turnerf9b8dec2000-06-16 19:34:52 +00001978 glyph->metrics.width = (FT_Pos)metrics.width << 6;
1979 glyph->metrics.height = (FT_Pos)metrics.height << 6;
David Turner8f43c712000-02-02 12:16:19 +00001980
David Turnerf9b8dec2000-06-16 19:34:52 +00001981 glyph->metrics.horiBearingX = (FT_Pos)metrics.horiBearingX << 6;
1982 glyph->metrics.horiBearingY = (FT_Pos)metrics.horiBearingY << 6;
1983 glyph->metrics.horiAdvance = (FT_Pos)metrics.horiAdvance << 6;
David Turner8f43c712000-02-02 12:16:19 +00001984
David Turnerf9b8dec2000-06-16 19:34:52 +00001985 glyph->metrics.vertBearingX = (FT_Pos)metrics.vertBearingX << 6;
1986 glyph->metrics.vertBearingY = (FT_Pos)metrics.vertBearingY << 6;
1987 glyph->metrics.vertAdvance = (FT_Pos)metrics.vertAdvance << 6;
David Turner8f43c712000-02-02 12:16:19 +00001988
David Turnerb08fe2d2002-08-27 20:20:29 +00001989 glyph->format = FT_GLYPH_FORMAT_BITMAP;
David Turnerf0df85b2000-06-22 00:17:42 +00001990 if ( load_flags & FT_LOAD_VERTICAL_LAYOUT )
1991 {
David Turnere161ee42000-07-10 22:03:10 +00001992 glyph->bitmap_left = metrics.vertBearingX;
1993 glyph->bitmap_top = metrics.vertBearingY;
David Turnerf0df85b2000-06-22 00:17:42 +00001994 }
1995 else
1996 {
David Turnere161ee42000-07-10 22:03:10 +00001997 glyph->bitmap_left = metrics.horiBearingX;
1998 glyph->bitmap_top = metrics.horiBearingY;
David Turnerf0df85b2000-06-22 00:17:42 +00001999 }
David Turner8f43c712000-02-02 12:16:19 +00002000 return error;
2001 }
2002 }
Werner Lemberg78575dc2000-06-12 19:36:41 +00002003
David Turner8f43c712000-02-02 12:16:19 +00002004#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
2005
Werner Lemberg0d535112001-12-19 22:26:12 +00002006 /* return immediately if we only want the embedded bitmaps */
David Turner4937a3e2001-12-19 21:09:16 +00002007 if ( load_flags & FT_LOAD_SBITS_ONLY )
Werner Lemberg779afe42003-06-22 15:33:53 +00002008 return TT_Err_Invalid_Argument;
David Turner4937a3e2001-12-19 21:09:16 +00002009
Werner Lemberg5811c7c2000-07-02 13:53:16 +00002010 /* seek to the beginning of the glyph table. For Type 42 fonts */
Werner Lemberg78575dc2000-06-12 19:36:41 +00002011 /* the table might be accessed from a Postscript stream or something */
2012 /* else... */
Werner Lemberg7f74a522002-07-26 09:09:10 +00002013
Graham Asher13217f22002-07-18 15:59:23 +00002014#ifdef FT_CONFIG_OPTION_INCREMENTAL
Werner Lemberg7f74a522002-07-26 09:09:10 +00002015
2016 /* Don't look for the glyph table if this is an incremental font. */
Graham Asherce121822002-08-01 15:29:17 +00002017 if ( !face->root.internal->incremental_interface )
Werner Lemberg7f74a522002-07-26 09:09:10 +00002018
Graham Asher13217f22002-07-18 15:59:23 +00002019#endif
Werner Lemberg7f74a522002-07-26 09:09:10 +00002020
2021 {
Graham Asher13217f22002-07-18 15:59:23 +00002022 error = face->goto_table( face, TTAG_glyf, stream, 0 );
2023 if ( error )
2024 {
2025 FT_ERROR(( "TT_Load_Glyph: could not access glyph table\n" ));
2026 goto Exit;
2027 }
Werner Lemberg7f74a522002-07-26 09:09:10 +00002028 }
David Turner8f43c712000-02-02 12:16:19 +00002029
Werner Lembergb3d5e9c2002-07-28 05:05:24 +00002030 FT_MEM_ZERO( &loader, sizeof ( loader ) );
David Turner8f43c712000-02-02 12:16:19 +00002031
David Turner08fdac92000-02-21 16:01:33 +00002032 /* update the glyph zone bounds */
David Turner08fdac92000-02-21 16:01:33 +00002033 {
Werner Lemberg3ab770b2005-03-08 20:24:56 +00002034 FT_GlyphLoader gloader = FT_FACE_DRIVER( face )->glyph_loader;
Werner Lemberga929ba92000-06-25 06:47:11 +00002035
Werner Lembergbd5ae402000-07-05 04:32:02 +00002036
David Turnerf0df85b2000-06-22 00:17:42 +00002037 loader.gloader = gloader;
Werner Lembergbd5ae402000-07-05 04:32:02 +00002038
David Turnerf0df85b2000-06-22 00:17:42 +00002039 FT_GlyphLoader_Rewind( gloader );
Werner Lembergbd5ae402000-07-05 04:32:02 +00002040
David Turnerf0df85b2000-06-22 00:17:42 +00002041 tt_prepare_zone( &loader.zone, &gloader->base, 0, 0 );
2042 tt_prepare_zone( &loader.base, &gloader->base, 0, 0 );
David Turner08fdac92000-02-21 16:01:33 +00002043 }
David Turner08fdac92000-02-21 16:01:33 +00002044
David Turner8f43c712000-02-02 12:16:19 +00002045#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
Werner Lemberg78575dc2000-06-12 19:36:41 +00002046
David Turner8f43c712000-02-02 12:16:19 +00002047 if ( size )
2048 {
2049 /* query new execution context */
Werner Lemberg78575dc2000-06-12 19:36:41 +00002050 loader.exec = size->debug ? size->context : TT_New_Context( face );
David Turner8f43c712000-02-02 12:16:19 +00002051 if ( !loader.exec )
2052 return TT_Err_Could_Not_Find_Context;
David Turnere49ab252000-05-16 23:44:38 +00002053
David Turner8f43c712000-02-02 12:16:19 +00002054 TT_Load_Context( loader.exec, face, size );
David Turnerc3128612000-06-23 05:02:13 +00002055 loader.instructions = loader.exec->glyphIns;
David Turner8f43c712000-02-02 12:16:19 +00002056
2057 /* load default graphics state - if needed */
2058 if ( size->GS.instruct_control & 2 )
2059 loader.exec->GS = tt_default_graphics_state;
Werner Lembergdea712b2004-08-07 15:08:33 +00002060
2061 loader.exec->pedantic_hinting =
2062 FT_BOOL( load_flags & FT_LOAD_PEDANTIC );
2063
2064 loader.exec->grayscale =
2065 FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) != FT_LOAD_TARGET_MONO );
David Turner8f43c712000-02-02 12:16:19 +00002066 }
Werner Lemberg78575dc2000-06-12 19:36:41 +00002067
David Turner8f43c712000-02-02 12:16:19 +00002068#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
2069
Werner Lemberg78575dc2000-06-12 19:36:41 +00002070 /* clear all outline flags, except the `owner' one */
David Turner81bb4ad2000-06-28 04:19:49 +00002071 glyph->outline.flags = 0;
David Turnere49ab252000-05-16 23:44:38 +00002072
Werner Lemberg78575dc2000-06-12 19:36:41 +00002073 /* let's initialize the rest of our loader now */
2074
David Turner8f43c712000-02-02 12:16:19 +00002075 loader.load_flags = load_flags;
2076
David Turnerc3128612000-06-23 05:02:13 +00002077 loader.face = (FT_Face)face;
2078 loader.size = (FT_Size)size;
2079 loader.glyph = (FT_GlyphSlot)glyph;
David Turner8f43c712000-02-02 12:16:19 +00002080 loader.stream = stream;
Werner Lembergbd5ae402000-07-05 04:32:02 +00002081
Graham Asher13217f22002-07-18 15:59:23 +00002082#ifdef FT_CONFIG_OPTION_INCREMENTAL
Werner Lemberg7f74a522002-07-26 09:09:10 +00002083
Graham Asherce121822002-08-01 15:29:17 +00002084 if ( face->root.internal->incremental_interface )
Graham Asher13217f22002-07-18 15:59:23 +00002085 loader.glyf_offset = 0;
Werner Lemberg7f74a522002-07-26 09:09:10 +00002086 else
2087
Graham Asher13217f22002-07-18 15:59:23 +00002088#endif
Werner Lemberg7f74a522002-07-26 09:09:10 +00002089
2090 loader.glyf_offset = FT_STREAM_POS();
David Turner8f43c712000-02-02 12:16:19 +00002091
2092#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
Werner Lemberg78575dc2000-06-12 19:36:41 +00002093
2094 /* if the cvt program has disabled hinting, the argument */
2095 /* is ignored. */
2096 if ( size && ( size->GS.instruct_control & 1 ) )
David Turner8f43c712000-02-02 12:16:19 +00002097 loader.load_flags |= FT_LOAD_NO_HINTING;
Werner Lemberg78575dc2000-06-12 19:36:41 +00002098
2099#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
David Turner8f43c712000-02-02 12:16:19 +00002100
2101 /* Main loading loop */
David Turnerb08fe2d2002-08-27 20:20:29 +00002102 glyph->format = FT_GLYPH_FORMAT_OUTLINE;
Werner Lemberg78575dc2000-06-12 19:36:41 +00002103 glyph->num_subglyphs = 0;
Werner Lemberg91db04c2002-04-01 14:25:28 +00002104
David Turner77b68b82003-01-08 09:59:17 +00002105 error = load_truetype_glyph( &loader, glyph_index, 0 );
Werner Lemberg78575dc2000-06-12 19:36:41 +00002106 if ( !error )
David Turner8f43c712000-02-02 12:16:19 +00002107 compute_glyph_metrics( &loader, glyph_index );
2108
2109#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
Werner Lembergdcd2e142000-06-25 07:43:15 +00002110
David Turnerd2b1f351999-12-16 23:11:37 +00002111 if ( !size || !size->debug )
David Turner8f43c712000-02-02 12:16:19 +00002112 TT_Done_Context( loader.exec );
Werner Lembergdcd2e142000-06-25 07:43:15 +00002113
2114#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
David Turnerd2b1f351999-12-16 23:11:37 +00002115
Werner Lemberg26aca022002-05-05 07:40:16 +00002116 /* Set the `high precision' bit flag. */
2117 /* This is _critical_ to get correct output for monochrome */
2118 /* TrueType glyphs at all sizes using the bytecode interpreter. */
2119 /* */
David Turner8cd89072002-05-04 18:02:59 +00002120 if ( size && size->root.metrics.y_ppem < 24 )
David Turnerb08fe2d2002-08-27 20:20:29 +00002121 glyph->outline.flags |= FT_OUTLINE_HIGH_PRECISION;
David Turner8cd89072002-05-04 18:02:59 +00002122
David Turner08fdac92000-02-21 16:01:33 +00002123 Exit:
David Turnerd2b1f351999-12-16 23:11:37 +00002124 return error;
2125 }
2126
2127
David Turnerd2b1f351999-12-16 23:11:37 +00002128/* END */