blob: ec81e1e73283f851c2967c9b3ed62239c91dea39 [file] [log] [blame]
David Turnerd2b1f351999-12-16 23:11:37 +00001/***************************************************************************/
2/* */
3/* ttgload.c */
4/* */
5/* TrueType Glyph Loader (body). */
6/* */
Werner Lemberg78575dc2000-06-12 19:36:41 +00007/* Copyright 1996-2000 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 Lemberg78575dc2000-06-12 19:36:41 +000028
David Turnera90663f2000-07-08 00:41:13 +000029
Werner Lemberg78575dc2000-06-12 19:36:41 +000030 /*************************************************************************/
31 /* */
32 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
33 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
34 /* messages during execution. */
35 /* */
David Turnerd2b1f351999-12-16 23:11:37 +000036#undef FT_COMPONENT
37#define FT_COMPONENT trace_ttgload
38
39
40 /*************************************************************************/
41 /* */
42 /* Composite font flags. */
43 /* */
44#define ARGS_ARE_WORDS 0x001
45#define ARGS_ARE_XY_VALUES 0x002
46#define ROUND_XY_TO_GRID 0x004
47#define WE_HAVE_A_SCALE 0x008
48/* reserved 0x010 */
49#define MORE_COMPONENTS 0x020
50#define WE_HAVE_AN_XY_SCALE 0x040
51#define WE_HAVE_A_2X2 0x080
52#define WE_HAVE_INSTR 0x100
53#define USE_MY_METRICS 0x200
54
55
David Turnerf9b8dec2000-06-16 19:34:52 +000056
David Turnerd2b1f351999-12-16 23:11:37 +000057 /*************************************************************************/
Werner Lemberg78575dc2000-06-12 19:36:41 +000058 /* */
59 /* <Function> */
60 /* TT_Get_Metrics */
61 /* */
62 /* <Description> */
David Turnerd2b1f351999-12-16 23:11:37 +000063 /* Returns the horizontal or vertical metrics in font units for a */
64 /* given glyph. The metrics are the left side bearing (resp. top */
65 /* side bearing) and advance width (resp. advance height). */
66 /* */
Werner Lemberg78575dc2000-06-12 19:36:41 +000067 /* <Input> */
68 /* header :: A pointer to either the horizontal or vertical metrics */
69 /* structure. */
70 /* */
71 /* index :: The glyph index. */
72 /* */
73 /* <Output> */
74 /* bearing :: The bearing, either left side or top side. */
75 /* */
76 /* advance :: The advance width resp. advance height. */
77 /* */
78 /* <Note> */
79 /* This function will much probably move to another component in the */
80 /* near future, but I haven't decided which yet. */
81 /* */
David Turner76a5f622000-11-04 01:55:49 +000082 FT_LOCAL_DEF
David Turnerd2b1f351999-12-16 23:11:37 +000083 void TT_Get_Metrics( TT_HoriHeader* header,
David Turnerf9b8dec2000-06-16 19:34:52 +000084 FT_UInt index,
85 FT_Short* bearing,
86 FT_UShort* advance )
David Turnerd2b1f351999-12-16 23:11:37 +000087 {
88 TT_LongMetrics* longs_m;
David Turnerf9b8dec2000-06-16 19:34:52 +000089 FT_UShort k = header->number_Of_HMetrics;
David Turnerd2b1f351999-12-16 23:11:37 +000090
91
David Turnerb1aabf42000-11-30 23:48:22 +000092 if ( index < (FT_UInt)k )
David Turnerd2b1f351999-12-16 23:11:37 +000093 {
94 longs_m = (TT_LongMetrics*)header->long_metrics + index;
95 *bearing = longs_m->bearing;
96 *advance = longs_m->advance;
97 }
98 else
99 {
100 *bearing = ((TT_ShortMetrics*)header->short_metrics)[index - k];
101 *advance = ((TT_LongMetrics*)header->long_metrics)[k - 1].advance;
102 }
103 }
104
105
106 /*************************************************************************/
Werner Lemberg78575dc2000-06-12 19:36:41 +0000107 /* */
Werner Lembergdcd2e142000-06-25 07:43:15 +0000108 /* Returns the horizontal metrics in font units for a given glyph. If */
109 /* `check' is true, take care of monospaced fonts by returning the */
110 /* advance width maximum. */
David Turnerd2b1f351999-12-16 23:11:37 +0000111 /* */
David Turnerd2b1f351999-12-16 23:11:37 +0000112 static
113 void Get_HMetrics( TT_Face face,
David Turnerf9b8dec2000-06-16 19:34:52 +0000114 FT_UInt index,
115 FT_Bool check,
116 FT_Short* lsb,
117 FT_UShort* aw )
David Turnerd2b1f351999-12-16 23:11:37 +0000118 {
119 TT_Get_Metrics( &face->horizontal, index, lsb, aw );
120
121 if ( check && face->postscript.isFixedPitch )
122 *aw = face->horizontal.advance_Width_Max;
123 }
124
125
126 /*************************************************************************/
Werner Lemberg78575dc2000-06-12 19:36:41 +0000127 /* */
David Turnerd2b1f351999-12-16 23:11:37 +0000128 /* Returns the advance width table for a given pixel size if it is */
129 /* found in the font's `hdmx' table (if any). */
130 /* */
David Turnerd2b1f351999-12-16 23:11:37 +0000131 static
David Turnerf9b8dec2000-06-16 19:34:52 +0000132 FT_Byte* Get_Advance_Widths( TT_Face face,
133 FT_UShort ppem )
David Turnerd2b1f351999-12-16 23:11:37 +0000134 {
David Turnerf9b8dec2000-06-16 19:34:52 +0000135 FT_UShort n;
David Turnerd2b1f351999-12-16 23:11:37 +0000136
137 for ( n = 0; n < face->hdmx.num_records; n++ )
138 if ( face->hdmx.records[n].ppem == ppem )
139 return face->hdmx.records[n].widths;
140
141 return NULL;
142 }
143
144
Werner Lemberg5811c7c2000-07-02 13:53:16 +0000145#define cur_to_org( n, zone ) \
David Turnerf9b8dec2000-06-16 19:34:52 +0000146 MEM_Copy( (zone)->org, (zone)->cur, n * sizeof ( FT_Vector ) )
David Turnerd2b1f351999-12-16 23:11:37 +0000147
Werner Lemberg5811c7c2000-07-02 13:53:16 +0000148#define org_to_cur( n, zone ) \
David Turnerf9b8dec2000-06-16 19:34:52 +0000149 MEM_Copy( (zone)->cur, (zone)->org, n * sizeof ( FT_Vector ) )
David Turnerd2b1f351999-12-16 23:11:37 +0000150
151
152 /*************************************************************************/
Werner Lemberg78575dc2000-06-12 19:36:41 +0000153 /* */
David Turnerd2b1f351999-12-16 23:11:37 +0000154 /* Translates an array of coordinates. */
155 /* */
David Turnerd2b1f351999-12-16 23:11:37 +0000156 static
David Turnerf9b8dec2000-06-16 19:34:52 +0000157 void translate_array( FT_UInt n,
158 FT_Vector* coords,
159 FT_Pos delta_x,
160 FT_Pos delta_y )
David Turnerd2b1f351999-12-16 23:11:37 +0000161 {
David Turnerf9b8dec2000-06-16 19:34:52 +0000162 FT_UInt k;
Werner Lemberg78575dc2000-06-12 19:36:41 +0000163
Werner Lemberg5811c7c2000-07-02 13:53:16 +0000164
David Turnerd2b1f351999-12-16 23:11:37 +0000165 if ( delta_x )
166 for ( k = 0; k < n; k++ )
167 coords[k].x += delta_x;
168
169 if ( delta_y )
170 for ( k = 0; k < n; k++ )
171 coords[k].y += delta_y;
172 }
173
174
Werner Lemberg5811c7c2000-07-02 13:53:16 +0000175 static
176 void tt_prepare_zone( TT_GlyphZone* zone,
177 FT_GlyphLoad* load,
178 FT_UInt start_point,
179 FT_UInt start_contour )
David Turnerd2b1f351999-12-16 23:11:37 +0000180 {
David Turnerf0df85b2000-06-22 00:17:42 +0000181 zone->n_points = load->outline.n_points - start_point;
182 zone->n_contours = load->outline.n_contours - start_contour;
183 zone->org = load->extra_points + start_point;
184 zone->cur = load->outline.points + start_point;
185 zone->tags = (FT_Byte*)load->outline.tags + start_point;
186 zone->contours = (FT_UShort*)load->outline.contours + start_contour;
Werner Lembergbd5ae402000-07-05 04:32:02 +0000187 }
David Turnerd2b1f351999-12-16 23:11:37 +0000188
189
David Turner8f43c712000-02-02 12:16:19 +0000190#undef IS_HINTED
Werner Lemberg78575dc2000-06-12 19:36:41 +0000191#define IS_HINTED( flags ) ( ( flags & FT_LOAD_NO_HINTING ) == 0 )
192
David Turner8f43c712000-02-02 12:16:19 +0000193
David Turnerd2b1f351999-12-16 23:11:37 +0000194 /*************************************************************************/
195 /* */
David Turner90f68b72000-06-23 12:26:14 +0000196 /* The following functions are used by default with TrueType fonts. */
197 /* However, they can be replaced by alternatives if we need to support */
Werner Lemberga929ba92000-06-25 06:47:11 +0000198 /* TrueType-compressed formats (like MicroType) in the future. */
David Turnerd2b1f351999-12-16 23:11:37 +0000199 /* */
Werner Lemberga929ba92000-06-25 06:47:11 +0000200 /*************************************************************************/
David Turner90f68b72000-06-23 12:26:14 +0000201
David Turner76a5f622000-11-04 01:55:49 +0000202 FT_CALLBACK_DEF
David Turner90f68b72000-06-23 12:26:14 +0000203 FT_Error TT_Access_Glyph_Frame( TT_Loader* loader,
204 FT_UInt glyph_index,
205 FT_ULong offset,
206 FT_UInt byte_count )
207 {
Werner Lemberge72c9fe2000-07-31 18:59:02 +0000208 FT_Error error;
209 FT_Stream stream = loader->stream;
Werner Lembergbd5ae402000-07-05 04:32:02 +0000210
Werner Lemberg353dfea2000-08-29 18:58:41 +0000211 /* for non-debug mode */
212 FT_UNUSED( glyph_index );
213
Werner Lemberga929ba92000-06-25 06:47:11 +0000214
David Turner90f68b72000-06-23 12:26:14 +0000215 FT_TRACE5(( "Glyph %ld\n", glyph_index ));
Werner Lemberge72c9fe2000-07-31 18:59:02 +0000216
217 /* the following line sets the `error' variable through macros! */
218 if ( FILE_Seek( offset ) || ACCESS_Frame( byte_count ) )
219 return error;
220
221 return TT_Err_Ok;
Werner Lembergbd5ae402000-07-05 04:32:02 +0000222 }
David Turner90f68b72000-06-23 12:26:14 +0000223
224
David Turner76a5f622000-11-04 01:55:49 +0000225 FT_CALLBACK_DEF
Werner Lemberga929ba92000-06-25 06:47:11 +0000226 void TT_Forget_Glyph_Frame( TT_Loader* loader )
David Turner90f68b72000-06-23 12:26:14 +0000227 {
228 FT_Stream stream = loader->stream;
Werner Lemberga929ba92000-06-25 06:47:11 +0000229
230
David Turner90f68b72000-06-23 12:26:14 +0000231 FORGET_Frame();
Werner Lembergbd5ae402000-07-05 04:32:02 +0000232 }
David Turner90f68b72000-06-23 12:26:14 +0000233
234
David Turner76a5f622000-11-04 01:55:49 +0000235 FT_CALLBACK_DEF
David Turner90f68b72000-06-23 12:26:14 +0000236 FT_Error TT_Load_Glyph_Header( TT_Loader* loader )
237 {
238 FT_Stream stream = loader->stream;
Werner Lembergbd5ae402000-07-05 04:32:02 +0000239
Werner Lemberga929ba92000-06-25 06:47:11 +0000240
David Turner90f68b72000-06-23 12:26:14 +0000241 loader->n_contours = GET_Short();
242
243 loader->bbox.xMin = GET_Short();
244 loader->bbox.yMin = GET_Short();
245 loader->bbox.xMax = GET_Short();
246 loader->bbox.yMax = GET_Short();
247
248 FT_TRACE5(( " # of contours: %d\n", loader->n_contours ));
249 FT_TRACE5(( " xMin: %4d xMax: %4d\n", loader->bbox.xMin,
250 loader->bbox.xMax ));
251 FT_TRACE5(( " yMin: %4d yMax: %4d\n", loader->bbox.yMin,
252 loader->bbox.yMax ));
Werner Lembergbd5ae402000-07-05 04:32:02 +0000253
Werner Lemberg1429db62001-04-02 23:54:01 +0000254 return TT_Err_Ok;
Werner Lembergbd5ae402000-07-05 04:32:02 +0000255 }
David Turner90f68b72000-06-23 12:26:14 +0000256
257
David Turner76a5f622000-11-04 01:55:49 +0000258 FT_CALLBACK_DEF
David Turner994d7742000-06-25 04:49:19 +0000259 FT_Error TT_Load_Simple_Glyph( TT_Loader* load )
David Turnerd2b1f351999-12-16 23:11:37 +0000260 {
David Turnerf0df85b2000-06-22 00:17:42 +0000261 FT_Error error;
David Turner994d7742000-06-25 04:49:19 +0000262 FT_Stream stream = load->stream;
263 FT_GlyphLoader* gloader = load->gloader;
264 FT_Int n_contours = load->n_contours;
David Turnerf0df85b2000-06-22 00:17:42 +0000265 FT_Outline* outline;
David Turnerc3128612000-06-23 05:02:13 +0000266 TT_Face face = (TT_Face)load->face;
267 TT_GlyphSlot slot = (TT_GlyphSlot)load->glyph;
David Turnerf0df85b2000-06-22 00:17:42 +0000268 FT_UShort n_ins;
269 FT_Int n, n_points;
David Turnere49ab252000-05-16 23:44:38 +0000270
Werner Lemberg78575dc2000-06-12 19:36:41 +0000271
David Turnerf0df85b2000-06-22 00:17:42 +0000272 /* reading the contours endpoints & number of points */
273 {
274 short* cur = gloader->current.outline.contours;
275 short* limit = cur + n_contours;
Werner Lembergbd5ae402000-07-05 04:32:02 +0000276
Werner Lemberga929ba92000-06-25 06:47:11 +0000277
David Turnerf0df85b2000-06-22 00:17:42 +0000278 for ( ; cur < limit; cur++ )
279 cur[0] = GET_UShort();
Werner Lembergbd5ae402000-07-05 04:32:02 +0000280
David Turnerf0df85b2000-06-22 00:17:42 +0000281 n_points = 0;
Werner Lemberga929ba92000-06-25 06:47:11 +0000282 if ( n_contours > 0 )
283 n_points = cur[-1] + 1;
David Turnerd2b1f351999-12-16 23:11:37 +0000284
Werner Lemberga929ba92000-06-25 06:47:11 +0000285 error = FT_GlyphLoader_Check_Points( gloader, n_points + 2, 0 );
286 if ( error )
287 goto Fail;
Werner Lembergbd5ae402000-07-05 04:32:02 +0000288
David Turnerf0df85b2000-06-22 00:17:42 +0000289 outline = &gloader->current.outline;
290 }
291
Werner Lemberg78575dc2000-06-12 19:36:41 +0000292 /* reading the bytecode instructions */
David Turnerc3128612000-06-23 05:02:13 +0000293 slot->control_len = 0;
294 slot->control_data = 0;
Werner Lembergbd5ae402000-07-05 04:32:02 +0000295
David Turnerd2b1f351999-12-16 23:11:37 +0000296 n_ins = GET_UShort();
297
Werner Lemberg1c0d4ac2000-06-06 20:41:48 +0000298 FT_TRACE5(( " Instructions size: %d\n", n_ins ));
David Turnerd2b1f351999-12-16 23:11:37 +0000299
300 if ( n_ins > face->max_profile.maxSizeOfInstructions )
301 {
302 FT_TRACE0(( "ERROR: Too many instructions!\n" ));
303 error = TT_Err_Too_Many_Ins;
304 goto Fail;
305 }
306
Werner Lemberg78575dc2000-06-12 19:36:41 +0000307 if ( stream->cursor + n_ins > stream->limit )
David Turnerd2b1f351999-12-16 23:11:37 +0000308 {
309 FT_TRACE0(( "ERROR: Instruction count mismatch!\n" ));
310 error = TT_Err_Too_Many_Ins;
311 goto Fail;
312 }
David Turnerd2b1f351999-12-16 23:11:37 +0000313
David Turner8f43c712000-02-02 12:16:19 +0000314#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
Werner Lemberga929ba92000-06-25 06:47:11 +0000315
316 if ( ( load->load_flags &
David Turnerc3128612000-06-23 05:02:13 +0000317 ( FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING ) ) == 0 &&
318 load->instructions )
David Turner08fdac92000-02-21 16:01:33 +0000319 {
David Turnerc3128612000-06-23 05:02:13 +0000320 slot->control_len = n_ins;
321 slot->control_data = load->instructions;
Werner Lembergbd5ae402000-07-05 04:32:02 +0000322
David Turnerc3128612000-06-23 05:02:13 +0000323 MEM_Copy( load->instructions, stream->cursor, n_ins );
David Turner08fdac92000-02-21 16:01:33 +0000324 }
Werner Lemberga929ba92000-06-25 06:47:11 +0000325
Werner Lemberg78575dc2000-06-12 19:36:41 +0000326#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
David Turnerd2b1f351999-12-16 23:11:37 +0000327
David Turner8f43c712000-02-02 12:16:19 +0000328 stream->cursor += n_ins;
David Turnere49ab252000-05-16 23:44:38 +0000329
Werner Lemberg78575dc2000-06-12 19:36:41 +0000330 /* reading the point tags */
David Turnerd2b1f351999-12-16 23:11:37 +0000331
David Turnere49ab252000-05-16 23:44:38 +0000332 {
David Turnerf0df85b2000-06-22 00:17:42 +0000333 FT_Byte* flag = (FT_Byte*)outline->tags;
David Turnerf9b8dec2000-06-16 19:34:52 +0000334 FT_Byte* limit = flag + n_points;
335 FT_Byte c, count;
David Turnere49ab252000-05-16 23:44:38 +0000336
Werner Lemberga929ba92000-06-25 06:47:11 +0000337
Werner Lemberg78575dc2000-06-12 19:36:41 +0000338 for ( ; flag < limit; flag++ )
David Turnerd2b1f351999-12-16 23:11:37 +0000339 {
David Turner8f43c712000-02-02 12:16:19 +0000340 *flag = c = GET_Byte();
341 if ( c & 8 )
David Turnerd2b1f351999-12-16 23:11:37 +0000342 {
David Turner8f43c712000-02-02 12:16:19 +0000343 for ( count = GET_Byte(); count > 0; count-- )
344 *++flag = c;
David Turnerd2b1f351999-12-16 23:11:37 +0000345 }
346 }
347 }
348
Werner Lemberg78575dc2000-06-12 19:36:41 +0000349 /* reading the X coordinates */
David Turnere49ab252000-05-16 23:44:38 +0000350
David Turnerd2b1f351999-12-16 23:11:37 +0000351 {
David Turnerf0df85b2000-06-22 00:17:42 +0000352 FT_Vector* vec = outline->points;
David Turnerf9b8dec2000-06-16 19:34:52 +0000353 FT_Vector* limit = vec + n_points;
David Turnerf0df85b2000-06-22 00:17:42 +0000354 FT_Byte* flag = (FT_Byte*)outline->tags;
David Turnerf9b8dec2000-06-16 19:34:52 +0000355 FT_Pos x = 0;
David Turnere49ab252000-05-16 23:44:38 +0000356
Werner Lemberg78575dc2000-06-12 19:36:41 +0000357
David Turner8f43c712000-02-02 12:16:19 +0000358 for ( ; vec < limit; vec++, flag++ )
David Turnerd2b1f351999-12-16 23:11:37 +0000359 {
David Turnerf9b8dec2000-06-16 19:34:52 +0000360 FT_Pos y = 0;
David Turnere49ab252000-05-16 23:44:38 +0000361
Werner Lemberg78575dc2000-06-12 19:36:41 +0000362
David Turner8f43c712000-02-02 12:16:19 +0000363 if ( *flag & 2 )
364 {
365 y = GET_Byte();
Werner Lemberg78575dc2000-06-12 19:36:41 +0000366 if ( ( *flag & 16 ) == 0 )
367 y = -y;
David Turner8f43c712000-02-02 12:16:19 +0000368 }
Werner Lemberg78575dc2000-06-12 19:36:41 +0000369 else if ( ( *flag & 16 ) == 0 )
David Turner8f43c712000-02-02 12:16:19 +0000370 y = GET_Short();
David Turnere49ab252000-05-16 23:44:38 +0000371
David Turner8f43c712000-02-02 12:16:19 +0000372 x += y;
373 vec->x = x;
David Turnerd2b1f351999-12-16 23:11:37 +0000374 }
David Turnerd2b1f351999-12-16 23:11:37 +0000375 }
376
Werner Lemberg78575dc2000-06-12 19:36:41 +0000377 /* reading the Y coordinates */
David Turnerd2b1f351999-12-16 23:11:37 +0000378
David Turnerd2b1f351999-12-16 23:11:37 +0000379 {
David Turnerf0df85b2000-06-22 00:17:42 +0000380 FT_Vector* vec = gloader->current.outline.points;
David Turnerf9b8dec2000-06-16 19:34:52 +0000381 FT_Vector* limit = vec + n_points;
David Turnerf0df85b2000-06-22 00:17:42 +0000382 FT_Byte* flag = (FT_Byte*)outline->tags;
David Turnerf9b8dec2000-06-16 19:34:52 +0000383 FT_Pos x = 0;
David Turnere49ab252000-05-16 23:44:38 +0000384
Werner Lemberg78575dc2000-06-12 19:36:41 +0000385
David Turner8f43c712000-02-02 12:16:19 +0000386 for ( ; vec < limit; vec++, flag++ )
David Turnerd2b1f351999-12-16 23:11:37 +0000387 {
David Turnerf9b8dec2000-06-16 19:34:52 +0000388 FT_Pos y = 0;
David Turnere49ab252000-05-16 23:44:38 +0000389
Werner Lemberg78575dc2000-06-12 19:36:41 +0000390
David Turner8f43c712000-02-02 12:16:19 +0000391 if ( *flag & 4 )
392 {
393 y = GET_Byte();
Werner Lemberg78575dc2000-06-12 19:36:41 +0000394 if ( ( *flag & 32 ) == 0 )
395 y = -y;
David Turner8f43c712000-02-02 12:16:19 +0000396 }
Werner Lemberg78575dc2000-06-12 19:36:41 +0000397 else if ( ( *flag & 32 ) == 0 )
David Turner8f43c712000-02-02 12:16:19 +0000398 y = GET_Short();
David Turnere49ab252000-05-16 23:44:38 +0000399
David Turner8f43c712000-02-02 12:16:19 +0000400 x += y;
401 vec->y = x;
David Turnerd2b1f351999-12-16 23:11:37 +0000402 }
David Turnerd2b1f351999-12-16 23:11:37 +0000403 }
404
David Turnerc3128612000-06-23 05:02:13 +0000405 /* clear the touch tags */
406 for ( n = 0; n < n_points; n++ )
407 outline->tags[n] &= FT_Curve_Tag_On;
408
409 outline->n_points = n_points;
410 outline->n_contours = n_contours;
David Turnerc3128612000-06-23 05:02:13 +0000411
Werner Lembergbd5ae402000-07-05 04:32:02 +0000412 Fail:
David Turnerc3128612000-06-23 05:02:13 +0000413 return error;
414 }
415
416
David Turner76a5f622000-11-04 01:55:49 +0000417 FT_CALLBACK_DEF
David Turner994d7742000-06-25 04:49:19 +0000418 FT_Error TT_Load_Composite_Glyph( TT_Loader* loader )
David Turner90f68b72000-06-23 12:26:14 +0000419 {
420 FT_Error error;
Werner Lembergdcd2e142000-06-25 07:43:15 +0000421 FT_Stream stream = loader->stream;
422 FT_GlyphLoader* gloader = loader->gloader;
David Turner90f68b72000-06-23 12:26:14 +0000423 FT_SubGlyph* subglyph;
424 FT_UInt num_subglyphs;
425
Werner Lemberga929ba92000-06-25 06:47:11 +0000426
David Turner90f68b72000-06-23 12:26:14 +0000427 num_subglyphs = 0;
Werner Lemberga929ba92000-06-25 06:47:11 +0000428
David Turner90f68b72000-06-23 12:26:14 +0000429 do
430 {
431 FT_Fixed xx, xy, yy, yx;
432
Werner Lemberga929ba92000-06-25 06:47:11 +0000433
David Turner90f68b72000-06-23 12:26:14 +0000434 /* check that we can load a new subglyph */
Werner Lembergdcd2e142000-06-25 07:43:15 +0000435 error = FT_GlyphLoader_Check_Subglyphs( gloader, num_subglyphs + 1 );
Werner Lemberga929ba92000-06-25 06:47:11 +0000436 if ( error )
437 goto Fail;
Werner Lembergbd5ae402000-07-05 04:32:02 +0000438
David Turner90f68b72000-06-23 12:26:14 +0000439 subglyph = gloader->current.subglyphs + num_subglyphs;
440
441 subglyph->arg1 = subglyph->arg2 = 0;
442
443 subglyph->flags = GET_UShort();
444 subglyph->index = GET_UShort();
445
446 /* read arguments */
447 if ( subglyph->flags & ARGS_ARE_WORDS )
448 {
449 subglyph->arg1 = GET_Short();
450 subglyph->arg2 = GET_Short();
451 }
452 else
453 {
454 subglyph->arg1 = GET_Char();
455 subglyph->arg2 = GET_Char();
456 }
457
458 /* read transform */
459 xx = yy = 0x10000L;
460 xy = yx = 0;
461
462 if ( subglyph->flags & WE_HAVE_A_SCALE )
463 {
464 xx = (FT_Fixed)GET_Short() << 2;
465 yy = xx;
466 }
467 else if ( subglyph->flags & WE_HAVE_AN_XY_SCALE )
468 {
469 xx = (FT_Fixed)GET_Short() << 2;
470 yy = (FT_Fixed)GET_Short() << 2;
471 }
472 else if ( subglyph->flags & WE_HAVE_A_2X2 )
473 {
474 xx = (FT_Fixed)GET_Short() << 2;
475 xy = (FT_Fixed)GET_Short() << 2;
476 yx = (FT_Fixed)GET_Short() << 2;
477 yy = (FT_Fixed)GET_Short() << 2;
478 }
479
480 subglyph->transform.xx = xx;
481 subglyph->transform.xy = xy;
482 subglyph->transform.yx = yx;
483 subglyph->transform.yy = yy;
484
485 num_subglyphs++;
Werner Lemberg5811c7c2000-07-02 13:53:16 +0000486
Werner Lembergdcd2e142000-06-25 07:43:15 +0000487 } while ( subglyph->flags & MORE_COMPONENTS );
David Turner90f68b72000-06-23 12:26:14 +0000488
489 gloader->current.num_subglyphs = num_subglyphs;
490
491#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
492 {
493 /* we must undo the ACCESS_Frame in order to point to the */
494 /* composite instructions, if we find some. */
495 /* we will process them later... */
496 /* */
Werner Lemberg914b2892001-03-10 17:07:42 +0000497 loader->ins_pos = (FT_ULong)( FILE_Pos() +
498 stream->cursor - stream->limit );
David Turner90f68b72000-06-23 12:26:14 +0000499 }
500#endif
501
502 Fail:
503 return error;
504 }
505
David Turnerc3128612000-06-23 05:02:13 +0000506
David Turner76a5f622000-11-04 01:55:49 +0000507 FT_LOCAL_DEF
David Turner994d7742000-06-25 04:49:19 +0000508 void TT_Init_Glyph_Loading( TT_Face face )
509 {
510 face->access_glyph_frame = TT_Access_Glyph_Frame;
511 face->read_glyph_header = TT_Load_Glyph_Header;
512 face->read_simple_glyph = TT_Load_Simple_Glyph;
513 face->read_composite_glyph = TT_Load_Composite_Glyph;
514 face->forget_glyph_frame = TT_Forget_Glyph_Frame;
515 }
516
David Turnerc3128612000-06-23 05:02:13 +0000517
518 /*************************************************************************/
519 /* */
520 /* <Function> */
521 /* TT_Process_Simple_Glyph */
522 /* */
523 /* <Description> */
524 /* Once a simple glyph has been loaded, it needs to be processed. */
525 /* Usually, this means scaling and hinting through bytecode */
Werner Lemberga929ba92000-06-25 06:47:11 +0000526 /* interpretation. */
David Turnerc3128612000-06-23 05:02:13 +0000527 /* */
528 static
Werner Lemberga929ba92000-06-25 06:47:11 +0000529 FT_Error TT_Process_Simple_Glyph( TT_Loader* load,
530 FT_Bool debug )
David Turnerc3128612000-06-23 05:02:13 +0000531 {
532 FT_GlyphLoader* gloader = load->gloader;
533 FT_Outline* outline = &gloader->current.outline;
534 FT_UInt n_points = outline->n_points;
535 FT_UInt n_ins;
536 TT_GlyphZone* zone = &load->zone;
Werner Lemberg1429db62001-04-02 23:54:01 +0000537 FT_Error error = TT_Err_Ok;
David Turnerc3128612000-06-23 05:02:13 +0000538
Werner Lemberg58b17f92000-07-27 23:29:08 +0000539 FT_UNUSED( debug ); /* used by truetype interpreter only */
Werner Lemberga929ba92000-06-25 06:47:11 +0000540
Werner Lemberge4b32a52000-10-31 20:42:18 +0000541
David Turnerc3128612000-06-23 05:02:13 +0000542 n_ins = load->glyph->control_len;
543
Werner Lemberg78575dc2000-06-12 19:36:41 +0000544 /* add shadow points */
David Turnere49ab252000-05-16 23:44:38 +0000545
David Turnerd2b1f351999-12-16 23:11:37 +0000546 /* Now add the two shadow points at n and n + 1. */
547 /* We need the left side bearing and advance width. */
548
David Turner8f43c712000-02-02 12:16:19 +0000549 {
David Turnerf9b8dec2000-06-16 19:34:52 +0000550 FT_Vector* pp1;
551 FT_Vector* pp2;
David Turnere49ab252000-05-16 23:44:38 +0000552
Werner Lemberga929ba92000-06-25 06:47:11 +0000553
David Turner8f43c712000-02-02 12:16:19 +0000554 /* pp1 = xMin - lsb */
David Turnerf0df85b2000-06-22 00:17:42 +0000555 pp1 = outline->points + n_points;
David Turner8f43c712000-02-02 12:16:19 +0000556 pp1->x = load->bbox.xMin - load->left_bearing;
557 pp1->y = 0;
David Turnere49ab252000-05-16 23:44:38 +0000558
David Turner8f43c712000-02-02 12:16:19 +0000559 /* pp2 = pp1 + aw */
560 pp2 = pp1 + 1;
561 pp2->x = pp1->x + load->advance;
562 pp2->y = 0;
David Turnere49ab252000-05-16 23:44:38 +0000563
David Turnerf0df85b2000-06-22 00:17:42 +0000564 outline->tags[n_points ] = 0;
565 outline->tags[n_points + 1] = 0;
David Turner8f43c712000-02-02 12:16:19 +0000566 }
Werner Lemberg78575dc2000-06-12 19:36:41 +0000567
David Turnerd2b1f351999-12-16 23:11:37 +0000568 /* Note that we return two more points that are not */
569 /* part of the glyph outline. */
570
Werner Lembergdcd2e142000-06-25 07:43:15 +0000571 n_points += 2;
David Turnerd2b1f351999-12-16 23:11:37 +0000572
David Turnerf0df85b2000-06-22 00:17:42 +0000573 /* set up zone for hinting */
574 tt_prepare_zone( zone, &gloader->current, 0, 0 );
David Turnerd2b1f351999-12-16 23:11:37 +0000575
David Turnerf0df85b2000-06-22 00:17:42 +0000576 /* eventually scale the glyph */
Werner Lemberga929ba92000-06-25 06:47:11 +0000577 if ( !( load->load_flags & FT_LOAD_NO_SCALE ) )
David Turnerd2b1f351999-12-16 23:11:37 +0000578 {
David Turnerf0df85b2000-06-22 00:17:42 +0000579 FT_Vector* vec = zone->cur;
580 FT_Vector* limit = vec + n_points;
David Turnerc3128612000-06-23 05:02:13 +0000581 FT_Fixed x_scale = load->size->metrics.x_scale;
582 FT_Fixed y_scale = load->size->metrics.y_scale;
David Turner8f43c712000-02-02 12:16:19 +0000583
Werner Lemberg5811c7c2000-07-02 13:53:16 +0000584
David Turnerd2b1f351999-12-16 23:11:37 +0000585 /* first scale the glyph points */
Werner Lemberg78575dc2000-06-12 19:36:41 +0000586 for ( ; vec < limit; vec++ )
David Turnerd2b1f351999-12-16 23:11:37 +0000587 {
David Turner8f43c712000-02-02 12:16:19 +0000588 vec->x = FT_MulFix( vec->x, x_scale );
589 vec->y = FT_MulFix( vec->y, y_scale );
David Turnerd2b1f351999-12-16 23:11:37 +0000590 }
David Turnerf0df85b2000-06-22 00:17:42 +0000591 }
David Turnerd2b1f351999-12-16 23:11:37 +0000592
David Turnerf0df85b2000-06-22 00:17:42 +0000593 cur_to_org( n_points, zone );
Werner Lemberg78575dc2000-06-12 19:36:41 +0000594
David Turnerf0df85b2000-06-22 00:17:42 +0000595 /* eventually hint the glyph */
Werner Lemberga929ba92000-06-25 06:47:11 +0000596 if ( IS_HINTED( load->load_flags ) )
David Turnerf0df85b2000-06-22 00:17:42 +0000597 {
598 FT_Pos x = zone->org[n_points-2].x;
Werner Lemberg78575dc2000-06-12 19:36:41 +0000599
Werner Lemberga929ba92000-06-25 06:47:11 +0000600
David Turnerf0df85b2000-06-22 00:17:42 +0000601 x = ( ( x + 32 ) & -64 ) - x;
602 translate_array( n_points, zone->org, x, 0 );
David Turnerd2b1f351999-12-16 23:11:37 +0000603
David Turnerf0df85b2000-06-22 00:17:42 +0000604 org_to_cur( n_points, zone );
David Turnerd2b1f351999-12-16 23:11:37 +0000605
David Turnerf0df85b2000-06-22 00:17:42 +0000606 zone->cur[n_points - 1].x = ( zone->cur[n_points - 1].x + 32 ) & -64;
David Turnerd2b1f351999-12-16 23:11:37 +0000607
David Turner8f43c712000-02-02 12:16:19 +0000608#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
Werner Lemberga929ba92000-06-25 06:47:11 +0000609
David Turnerf0df85b2000-06-22 00:17:42 +0000610 /* now consider hinting */
611 if ( n_ins > 0 )
612 {
David Turnerc3128612000-06-23 05:02:13 +0000613 error = TT_Set_CodeRange( load->exec, tt_coderange_glyph,
614 load->exec->glyphIns, n_ins );
Werner Lemberga929ba92000-06-25 06:47:11 +0000615 if ( error )
616 goto Exit;
Werner Lembergbd5ae402000-07-05 04:32:02 +0000617
David Turnerf0df85b2000-06-22 00:17:42 +0000618 load->exec->is_composite = FALSE;
Werner Lemberga929ba92000-06-25 06:47:11 +0000619 load->exec->pedantic_hinting = (FT_Bool)( load->load_flags &
620 FT_LOAD_PEDANTIC );
David Turnerf0df85b2000-06-22 00:17:42 +0000621 load->exec->pts = *zone;
622 load->exec->pts.n_points += 2;
David Turnerd2b1f351999-12-16 23:11:37 +0000623
David Turnerf0df85b2000-06-22 00:17:42 +0000624 error = TT_Run_Context( load->exec, debug );
625 if ( error && load->exec->pedantic_hinting )
David Turnerc3128612000-06-23 05:02:13 +0000626 goto Exit;
Werner Lembergbd5ae402000-07-05 04:32:02 +0000627
Werner Lemberg1429db62001-04-02 23:54:01 +0000628 error = TT_Err_Ok; /* ignore bytecode errors in non-pedantic mode */
David Turnerd2b1f351999-12-16 23:11:37 +0000629 }
Werner Lemberga929ba92000-06-25 06:47:11 +0000630
David Turnerf0df85b2000-06-22 00:17:42 +0000631#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
Werner Lemberga929ba92000-06-25 06:47:11 +0000632
David Turnerd2b1f351999-12-16 23:11:37 +0000633 }
634
635 /* save glyph phantom points */
David Turner8f43c712000-02-02 12:16:19 +0000636 if ( !load->preserve_pps )
David Turnerd2b1f351999-12-16 23:11:37 +0000637 {
David Turner8f43c712000-02-02 12:16:19 +0000638 load->pp1 = zone->cur[n_points - 2];
639 load->pp2 = zone->cur[n_points - 1];
David Turnerd2b1f351999-12-16 23:11:37 +0000640 }
641
David Turner5fe4c002000-07-26 19:04:08 +0000642#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
David Turnerc3128612000-06-23 05:02:13 +0000643 Exit:
Werner Lemberge4b32a52000-10-31 20:42:18 +0000644#endif
David Turnerd2b1f351999-12-16 23:11:37 +0000645 return error;
646 }
647
648
649 /*************************************************************************/
650 /* */
651 /* <Function> */
David Turner8f43c712000-02-02 12:16:19 +0000652 /* load_truetype_glyph */
David Turnerd2b1f351999-12-16 23:11:37 +0000653 /* */
654 /* <Description> */
Werner Lemberg78575dc2000-06-12 19:36:41 +0000655 /* Loads a given truetype glyph. Handles composites and uses a */
656 /* TT_Loader object. */
David Turnerd2b1f351999-12-16 23:11:37 +0000657 /* */
658 static
David Turnerf9b8dec2000-06-16 19:34:52 +0000659 FT_Error load_truetype_glyph( TT_Loader* loader,
660 FT_UInt glyph_index )
David Turnerd2b1f351999-12-16 23:11:37 +0000661 {
Werner Lemberg321cd272000-07-27 11:20:20 +0000662
663#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
David Turnerf0df85b2000-06-22 00:17:42 +0000664 FT_Stream stream = loader->stream;
Werner Lemberg321cd272000-07-27 11:20:20 +0000665#endif
666
David Turnerf0df85b2000-06-22 00:17:42 +0000667 FT_Error error;
David Turnerc3128612000-06-23 05:02:13 +0000668 TT_Face face = (TT_Face)loader->face;
David Turnerf0df85b2000-06-22 00:17:42 +0000669 FT_ULong offset;
David Turnerc3128612000-06-23 05:02:13 +0000670 FT_Int contours_count;
David Turnerf0df85b2000-06-22 00:17:42 +0000671 FT_UInt index, num_points, num_contours, count;
672 FT_Fixed x_scale, y_scale;
673 FT_ULong ins_offset;
674 FT_GlyphLoader* gloader = loader->gloader;
David Turner90f68b72000-06-23 12:26:14 +0000675 FT_Bool opened_frame = 0;
David Turnere49ab252000-05-16 23:44:38 +0000676
Werner Lemberg58b17f92000-07-27 23:29:08 +0000677
David Turner8f43c712000-02-02 12:16:19 +0000678 /* check glyph index */
David Turnered7f62a2000-03-28 11:19:28 +0000679 index = glyph_index;
David Turnerf9b8dec2000-06-16 19:34:52 +0000680 if ( index >= (FT_UInt)face->root.num_glyphs )
David Turnerd2b1f351999-12-16 23:11:37 +0000681 {
David Turner8f43c712000-02-02 12:16:19 +0000682 error = TT_Err_Invalid_Glyph_Index;
David Turner90f68b72000-06-23 12:26:14 +0000683 goto Exit;
David Turnerd2b1f351999-12-16 23:11:37 +0000684 }
685
David Turner861ba622000-02-15 12:54:51 +0000686 loader->glyph_index = glyph_index;
David Turnerd2b1f351999-12-16 23:11:37 +0000687 num_contours = 0;
David Turner8f43c712000-02-02 12:16:19 +0000688 num_points = 0;
689 ins_offset = 0;
David Turnere49ab252000-05-16 23:44:38 +0000690
Werner Lemberg78575dc2000-06-12 19:36:41 +0000691 x_scale = 0x10000L;
692 y_scale = 0x10000L;
693 if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
David Turnerd2b1f351999-12-16 23:11:37 +0000694 {
David Turnerc3128612000-06-23 05:02:13 +0000695 x_scale = loader->size->metrics.x_scale;
696 y_scale = loader->size->metrics.y_scale;
David Turner8f43c712000-02-02 12:16:19 +0000697 }
David Turnerd2b1f351999-12-16 23:11:37 +0000698
David Turner8f43c712000-02-02 12:16:19 +0000699 /* get horizontal metrics */
700 {
David Turnerf9b8dec2000-06-16 19:34:52 +0000701 FT_Short left_bearing;
702 FT_UShort advance_width;
David Turnerd2b1f351999-12-16 23:11:37 +0000703
Werner Lemberg78575dc2000-06-12 19:36:41 +0000704
David Turner71ec10e2000-02-10 16:09:35 +0000705 Get_HMetrics( face, index,
David Turnerf9b8dec2000-06-16 19:34:52 +0000706 (FT_Bool)!(loader->load_flags &
Werner Lembergdcd2e142000-06-25 07:43:15 +0000707 FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH),
David Turner8f43c712000-02-02 12:16:19 +0000708 &left_bearing,
709 &advance_width );
David Turnerd2b1f351999-12-16 23:11:37 +0000710
David Turner8f43c712000-02-02 12:16:19 +0000711 loader->left_bearing = left_bearing;
712 loader->advance = advance_width;
713 }
David Turnerd2b1f351999-12-16 23:11:37 +0000714
David Turner8f43c712000-02-02 12:16:19 +0000715 offset = face->glyph_locations[index];
716 count = 0;
David Turnere49ab252000-05-16 23:44:38 +0000717
David Turnerf9b8dec2000-06-16 19:34:52 +0000718 if ( index < (FT_UInt)face->num_locations - 1 )
Werner Lemberg78575dc2000-06-12 19:36:41 +0000719 count = face->glyph_locations[index + 1] - offset;
David Turnerd2b1f351999-12-16 23:11:37 +0000720
Werner Lemberg78575dc2000-06-12 19:36:41 +0000721 if ( count == 0 )
David Turner8f43c712000-02-02 12:16:19 +0000722 {
723 /* as described by Frederic Loyer, these are spaces, and */
724 /* not the unknown glyph. */
725 loader->bbox.xMin = 0;
726 loader->bbox.xMax = 0;
727 loader->bbox.yMin = 0;
728 loader->bbox.yMax = 0;
David Turnerd2b1f351999-12-16 23:11:37 +0000729
David Turner8f43c712000-02-02 12:16:19 +0000730 loader->pp1.x = 0;
731 loader->pp2.x = loader->advance;
David Turnerd2b1f351999-12-16 23:11:37 +0000732
Werner Lemberg78575dc2000-06-12 19:36:41 +0000733 if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
David Turner8f43c712000-02-02 12:16:19 +0000734 loader->pp2.x = FT_MulFix( loader->pp2.x, x_scale );
David Turnerd2b1f351999-12-16 23:11:37 +0000735
David Turner8f43c712000-02-02 12:16:19 +0000736#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
Werner Lembergdcd2e142000-06-25 07:43:15 +0000737
Werner Lemberg78575dc2000-06-12 19:36:41 +0000738 if ( loader->exec )
David Turner7bb7fed2000-02-28 11:23:36 +0000739 loader->exec->glyphSize = 0;
Werner Lembergdcd2e142000-06-25 07:43:15 +0000740
David Turner8f43c712000-02-02 12:16:19 +0000741#endif
Werner Lemberg5811c7c2000-07-02 13:53:16 +0000742
Werner Lemberg1429db62001-04-02 23:54:01 +0000743 error = TT_Err_Ok;
David Turner90f68b72000-06-23 12:26:14 +0000744 goto Exit;
David Turner8f43c712000-02-02 12:16:19 +0000745 }
David Turnerd2b1f351999-12-16 23:11:37 +0000746
David Turner8f43c712000-02-02 12:16:19 +0000747 offset = loader->glyf_offset + offset;
David Turnerd2b1f351999-12-16 23:11:37 +0000748
David Turner90f68b72000-06-23 12:26:14 +0000749 /* access glyph frame */
David Turner994d7742000-06-25 04:49:19 +0000750 error = face->access_glyph_frame( loader, glyph_index, offset, count );
Werner Lemberga929ba92000-06-25 06:47:11 +0000751 if ( error )
752 goto Exit;
David Turner90f68b72000-06-23 12:26:14 +0000753
754 opened_frame = 1;
755
David Turner8f43c712000-02-02 12:16:19 +0000756 /* read first glyph header */
David Turner994d7742000-06-25 04:49:19 +0000757 error = face->read_glyph_header( loader );
Werner Lemberga929ba92000-06-25 06:47:11 +0000758 if ( error )
759 goto Fail;
David Turnerd2b1f351999-12-16 23:11:37 +0000760
David Turner90f68b72000-06-23 12:26:14 +0000761 contours_count = loader->n_contours;
David Turnerd2b1f351999-12-16 23:11:37 +0000762
David Turner8f43c712000-02-02 12:16:19 +0000763 count -= 10;
David Turnerd2b1f351999-12-16 23:11:37 +0000764
David Turner8f43c712000-02-02 12:16:19 +0000765 loader->pp1.x = loader->bbox.xMin - loader->left_bearing;
766 loader->pp1.y = 0;
767 loader->pp2.x = loader->pp1.x + loader->advance;
768 loader->pp2.y = 0;
David Turnere49ab252000-05-16 23:44:38 +0000769
Werner Lemberg78575dc2000-06-12 19:36:41 +0000770 if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
David Turner8f43c712000-02-02 12:16:19 +0000771 {
772 loader->pp1.x = FT_MulFix( loader->pp1.x, x_scale );
773 loader->pp2.x = FT_MulFix( loader->pp2.x, x_scale );
774 }
David Turnerd2b1f351999-12-16 23:11:37 +0000775
Werner Lemberg78575dc2000-06-12 19:36:41 +0000776 /***********************************************************************/
777 /***********************************************************************/
778 /***********************************************************************/
David Turnerd2b1f351999-12-16 23:11:37 +0000779
Werner Lemberg78575dc2000-06-12 19:36:41 +0000780 /* if it is a simple glyph, load it */
781
782 if ( contours_count >= 0 )
David Turner8f43c712000-02-02 12:16:19 +0000783 {
David Turnerf0df85b2000-06-22 00:17:42 +0000784 /* check that we can add the contours to the glyph */
785 error = FT_GlyphLoader_Check_Points( gloader, 0, contours_count );
Werner Lemberga929ba92000-06-25 06:47:11 +0000786 if ( error )
787 goto Fail;
Werner Lemberg78575dc2000-06-12 19:36:41 +0000788
David Turner994d7742000-06-25 04:49:19 +0000789 error = face->read_simple_glyph( loader );
Werner Lemberga929ba92000-06-25 06:47:11 +0000790 if ( error )
791 goto Fail;
Werner Lembergbd5ae402000-07-05 04:32:02 +0000792
David Turner8f43c712000-02-02 12:16:19 +0000793#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
Werner Lemberg5811c7c2000-07-02 13:53:16 +0000794
David Turnerc3128612000-06-23 05:02:13 +0000795 {
796 TT_Size size = (TT_Size)loader->size;
Werner Lembergdcd2e142000-06-25 07:43:15 +0000797
798
David Turnerc3128612000-06-23 05:02:13 +0000799 error = TT_Process_Simple_Glyph( loader,
800 (FT_Bool)( size && size->debug ) );
801 }
Werner Lembergdcd2e142000-06-25 07:43:15 +0000802
David Turner8f43c712000-02-02 12:16:19 +0000803#else
Werner Lembergdcd2e142000-06-25 07:43:15 +0000804
David Turner5fe4c002000-07-26 19:04:08 +0000805 error = TT_Process_Simple_Glyph( loader, 0 );
Werner Lembergdcd2e142000-06-25 07:43:15 +0000806
David Turnere49ab252000-05-16 23:44:38 +0000807#endif
Werner Lembergdcd2e142000-06-25 07:43:15 +0000808
809 if ( error )
810 goto Fail;
David Turnerf0df85b2000-06-22 00:17:42 +0000811
812 FT_GlyphLoader_Add( gloader );
David Turnerd2b1f351999-12-16 23:11:37 +0000813
David Turner8f43c712000-02-02 12:16:19 +0000814 /* Note: We could have put the simple loader source there */
815 /* but the code is fat enough already :-) */
David Turner8f43c712000-02-02 12:16:19 +0000816 }
David Turner8f43c712000-02-02 12:16:19 +0000817
Werner Lemberg78575dc2000-06-12 19:36:41 +0000818 /***********************************************************************/
819 /***********************************************************************/
820 /***********************************************************************/
821
822 /* otherwise, load a composite! */
823 else
David Turner8f43c712000-02-02 12:16:19 +0000824 {
David Turnerc3128612000-06-23 05:02:13 +0000825 TT_GlyphSlot glyph = (TT_GlyphSlot)loader->glyph;
826 FT_UInt start_point, start_contour;
David Turnerc6a92202000-07-04 18:12:13 +0000827 FT_ULong ins_pos; /* position of composite instructions, if any */
Werner Lemberga929ba92000-06-25 06:47:11 +0000828
Werner Lembergbd5ae402000-07-05 04:32:02 +0000829
David Turner8f43c712000-02-02 12:16:19 +0000830 /* for each subglyph, read composite header */
David Turnerf0df85b2000-06-22 00:17:42 +0000831 start_point = gloader->base.outline.n_points;
832 start_contour = gloader->base.outline.n_contours;
Werner Lembergbd5ae402000-07-05 04:32:02 +0000833
David Turner994d7742000-06-25 04:49:19 +0000834 error = face->read_composite_glyph( loader );
Werner Lemberga929ba92000-06-25 06:47:11 +0000835 if ( error )
836 goto Fail;
David Turnered7f62a2000-03-28 11:19:28 +0000837
David Turnerc6a92202000-07-04 18:12:13 +0000838 ins_pos = loader->ins_pos;
David Turner994d7742000-06-25 04:49:19 +0000839 face->forget_glyph_frame( loader );
David Turner90f68b72000-06-23 12:26:14 +0000840 opened_frame = 0;
841
David Turnered7f62a2000-03-28 11:19:28 +0000842 /* if the flag FT_LOAD_NO_RECURSE is set, we return the subglyph */
Werner Lemberg78575dc2000-06-12 19:36:41 +0000843 /* `as is' in the glyph slot (the client application will be */
844 /* responsible for interpreting this data)... */
845 /* */
David Turnered7f62a2000-03-28 11:19:28 +0000846 if ( loader->load_flags & FT_LOAD_NO_RECURSE )
847 {
David Turnered7f62a2000-03-28 11:19:28 +0000848 /* set up remaining glyph fields */
David Turnerf0df85b2000-06-22 00:17:42 +0000849 FT_GlyphLoader_Add( gloader );
Werner Lembergbd5ae402000-07-05 04:32:02 +0000850
David Turnerf0df85b2000-06-22 00:17:42 +0000851 glyph->num_subglyphs = gloader->base.num_subglyphs;
David Turner3475e7f2000-05-17 20:56:01 +0000852 glyph->format = ft_glyph_format_composite;
David Turnerf0df85b2000-06-22 00:17:42 +0000853 glyph->subglyphs = gloader->base.subglyphs;
Werner Lembergbd5ae402000-07-05 04:32:02 +0000854
David Turner90f68b72000-06-23 12:26:14 +0000855 goto Exit;
David Turnered7f62a2000-03-28 11:19:28 +0000856 }
857
David Turner8f43c712000-02-02 12:16:19 +0000858 /*********************************************************************/
Werner Lembergdcd2e142000-06-25 07:43:15 +0000859 /*********************************************************************/
860 /*********************************************************************/
861
862 /* Now, read each subglyph independently. */
David Turner8f43c712000-02-02 12:16:19 +0000863 {
David Turnerc3128612000-06-23 05:02:13 +0000864 FT_Int n, num_base_points, num_new_points;
Werner Lembergdcd2e142000-06-25 07:43:15 +0000865 FT_SubGlyph* subglyph = 0;
Werner Lembergbd5ae402000-07-05 04:32:02 +0000866
David Turnerc3128612000-06-23 05:02:13 +0000867 FT_UInt num_subglyphs = gloader->current.num_subglyphs;
868 FT_UInt num_base_subgs = gloader->base.num_subglyphs;
Werner Lembergbd5ae402000-07-05 04:32:02 +0000869
David Turnerc3128612000-06-23 05:02:13 +0000870
David Turnerf0df85b2000-06-22 00:17:42 +0000871 FT_GlyphLoader_Add( gloader );
Werner Lembergbd5ae402000-07-05 04:32:02 +0000872
David Turner74abee82000-06-27 23:31:53 +0000873 for ( n = 0; n < (FT_Int)num_subglyphs; n++ )
David Turnerd2b1f351999-12-16 23:11:37 +0000874 {
David Turnerf9b8dec2000-06-16 19:34:52 +0000875 FT_Vector pp1, pp2;
876 FT_Pos x, y;
David Turnere49ab252000-05-16 23:44:38 +0000877
Werner Lembergdcd2e142000-06-25 07:43:15 +0000878
Werner Lemberga929ba92000-06-25 06:47:11 +0000879 /* Each time we call load_truetype_glyph in this loop, the */
880 /* value of `gloader.base.subglyphs' can change due to table */
881 /* reallocations. We thus need to recompute the subglyph */
882 /* pointer on each iteration. */
David Turnerf0df85b2000-06-22 00:17:42 +0000883 subglyph = gloader->base.subglyphs + num_base_subgs + n;
Werner Lemberg78575dc2000-06-12 19:36:41 +0000884
David Turner8f43c712000-02-02 12:16:19 +0000885 pp1 = loader->pp1;
886 pp2 = loader->pp2;
David Turnerd2b1f351999-12-16 23:11:37 +0000887
David Turnerf0df85b2000-06-22 00:17:42 +0000888 num_base_points = gloader->base.outline.n_points;
David Turnere49ab252000-05-16 23:44:38 +0000889
David Turner8f43c712000-02-02 12:16:19 +0000890 error = load_truetype_glyph( loader, subglyph->index );
Werner Lemberg78575dc2000-06-12 19:36:41 +0000891 if ( error )
892 goto Fail;
David Turner3475e7f2000-05-17 20:56:01 +0000893
David Turner61d6b2b2001-05-16 17:49:07 +0000894 /* restore subglyph pointer */
David Turnerf0df85b2000-06-22 00:17:42 +0000895 subglyph = gloader->base.subglyphs + num_base_subgs + n;
896
David Turner7bb7fed2000-02-28 11:23:36 +0000897 if ( subglyph->flags & USE_MY_METRICS )
898 {
899 pp1 = loader->pp1;
900 pp2 = loader->pp2;
901 }
902 else
David Turnerd2b1f351999-12-16 23:11:37 +0000903 {
David Turner8f43c712000-02-02 12:16:19 +0000904 loader->pp1 = pp1;
905 loader->pp2 = pp2;
David Turnerd2b1f351999-12-16 23:11:37 +0000906 }
David Turnere49ab252000-05-16 23:44:38 +0000907
Werner Lembergdcd2e142000-06-25 07:43:15 +0000908 num_points = gloader->base.outline.n_points;
David Turnere49ab252000-05-16 23:44:38 +0000909
David Turner8f43c712000-02-02 12:16:19 +0000910 num_new_points = num_points - num_base_points;
David Turnere49ab252000-05-16 23:44:38 +0000911
David Turner8f43c712000-02-02 12:16:19 +0000912 /* now perform the transform required for this subglyph */
David Turnere49ab252000-05-16 23:44:38 +0000913
David Turner8f43c712000-02-02 12:16:19 +0000914 if ( subglyph->flags & ( WE_HAVE_A_SCALE |
915 WE_HAVE_AN_XY_SCALE |
916 WE_HAVE_A_2X2 ) )
David Turnerd2b1f351999-12-16 23:11:37 +0000917 {
Werner Lemberga929ba92000-06-25 06:47:11 +0000918 FT_Vector* cur = gloader->base.outline.points +
919 num_base_points;
920 FT_Vector* org = gloader->base.extra_points +
921 num_base_points;
David Turnerf9b8dec2000-06-16 19:34:52 +0000922 FT_Vector* limit = cur + num_new_points;
David Turnerd2b1f351999-12-16 23:11:37 +0000923
Werner Lembergdcd2e142000-06-25 07:43:15 +0000924
David Turner8f43c712000-02-02 12:16:19 +0000925 for ( ; cur < limit; cur++, org++ )
David Turnerd2b1f351999-12-16 23:11:37 +0000926 {
David Turnerf0df85b2000-06-22 00:17:42 +0000927 FT_Vector_Transform( cur, &subglyph->transform );
928 FT_Vector_Transform( org, &subglyph->transform );
David Turnerd2b1f351999-12-16 23:11:37 +0000929 }
930 }
931
David Turnerd2b1f351999-12-16 23:11:37 +0000932 /* apply offset */
933
Werner Lemberg78575dc2000-06-12 19:36:41 +0000934 if ( !( subglyph->flags & ARGS_ARE_XY_VALUES ) )
David Turnerd2b1f351999-12-16 23:11:37 +0000935 {
David Turner74abee82000-06-27 23:31:53 +0000936 FT_UInt k = subglyph->arg1;
David Turnerf0df85b2000-06-22 00:17:42 +0000937 FT_UInt l = subglyph->arg2;
938 FT_Vector* p1;
939 FT_Vector* p2;
David Turnerd2b1f351999-12-16 23:11:37 +0000940
Werner Lembergdeb4e982000-06-29 03:14:25 +0000941
David Turner74abee82000-06-27 23:31:53 +0000942 if ( start_point + k >= (FT_UInt)num_base_points ||
David Turnerf0df85b2000-06-22 00:17:42 +0000943 l >= (FT_UInt)num_new_points )
David Turnerd2b1f351999-12-16 23:11:37 +0000944 {
945 error = TT_Err_Invalid_Composite;
946 goto Fail;
947 }
948
David Turnere49ab252000-05-16 23:44:38 +0000949 l += num_base_points;
950
David Turnerf0df85b2000-06-22 00:17:42 +0000951 p1 = gloader->base.outline.points + start_point + k;
952 p2 = gloader->base.outline.points + start_point + l;
Werner Lembergbd5ae402000-07-05 04:32:02 +0000953
David Turnerf0df85b2000-06-22 00:17:42 +0000954 x = p1->x - p2->x;
955 y = p1->y - p2->y;
David Turnerd2b1f351999-12-16 23:11:37 +0000956 }
957 else
958 {
David Turner8f43c712000-02-02 12:16:19 +0000959 x = subglyph->arg1;
960 y = subglyph->arg2;
David Turnerd2b1f351999-12-16 23:11:37 +0000961
Werner Lemberg78575dc2000-06-12 19:36:41 +0000962 if ( !( loader->load_flags & FT_LOAD_NO_SCALE ) )
David Turnerd2b1f351999-12-16 23:11:37 +0000963 {
David Turner8f43c712000-02-02 12:16:19 +0000964 x = FT_MulFix( x, x_scale );
965 y = FT_MulFix( y, y_scale );
David Turnere49ab252000-05-16 23:44:38 +0000966
David Turner8f43c712000-02-02 12:16:19 +0000967 if ( subglyph->flags & ROUND_XY_TO_GRID )
Werner Lemberg78575dc2000-06-12 19:36:41 +0000968 {
969 x = ( x + 32 ) & -64;
970 y = ( y + 32 ) & -64;
971 }
David Turnerd2b1f351999-12-16 23:11:37 +0000972 }
973 }
974
David Turner61d6b2b2001-05-16 17:49:07 +0000975 if ( x | y )
976 {
977 translate_array( num_new_points,
978 gloader->base.outline.points + num_base_points,
979 x, y );
980
981 translate_array( num_new_points,
982 gloader->base.extra_points + num_base_points,
983 x, y );
984 }
David Turnerd2b1f351999-12-16 23:11:37 +0000985 }
David Turnere49ab252000-05-16 23:44:38 +0000986
Werner Lembergdcd2e142000-06-25 07:43:15 +0000987 /*******************************************************************/
988 /*******************************************************************/
989 /*******************************************************************/
David Turnerd2b1f351999-12-16 23:11:37 +0000990
Werner Lemberg5811c7c2000-07-02 13:53:16 +0000991 /* we have finished loading all sub-glyphs; now, look for */
Werner Lemberg78575dc2000-06-12 19:36:41 +0000992 /* instructions for this composite! */
David Turnerd2b1f351999-12-16 23:11:37 +0000993
David Turner8f43c712000-02-02 12:16:19 +0000994#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
Werner Lemberg78575dc2000-06-12 19:36:41 +0000995
Werner Lemberg78575dc2000-06-12 19:36:41 +0000996 if ( num_subglyphs > 0 &&
997 loader->exec &&
David Turnerc6a92202000-07-04 18:12:13 +0000998 ins_pos > 0 &&
Werner Lemberg78575dc2000-06-12 19:36:41 +0000999 subglyph->flags & WE_HAVE_INSTR )
David Turner8f43c712000-02-02 12:16:19 +00001000 {
David Turnerf9b8dec2000-06-16 19:34:52 +00001001 FT_UShort n_ins;
David Turner8f43c712000-02-02 12:16:19 +00001002 TT_ExecContext exec = loader->exec;
David Turnerf9b8dec2000-06-16 19:34:52 +00001003 TT_GlyphZone* pts;
1004 FT_Vector* pp1;
David Turnere49ab252000-05-16 23:44:38 +00001005
Werner Lemberg78575dc2000-06-12 19:36:41 +00001006
David Turner8f43c712000-02-02 12:16:19 +00001007 /* read size of instructions */
David Turnerc6a92202000-07-04 18:12:13 +00001008 if ( FILE_Seek( ins_pos ) ||
1009 READ_UShort( n_ins ) )
Werner Lemberg78575dc2000-06-12 19:36:41 +00001010 goto Fail;
Werner Lemberg1c0d4ac2000-06-06 20:41:48 +00001011 FT_TRACE5(( " Instructions size = %d\n", n_ins ));
David Turnere49ab252000-05-16 23:44:38 +00001012
Werner Lemberg5811c7c2000-07-02 13:53:16 +00001013 /* in some fonts? */
Werner Lemberga929ba92000-06-25 06:47:11 +00001014 if ( n_ins == 0xFFFF )
David Turnerc3128612000-06-23 05:02:13 +00001015 n_ins = 0;
1016
David Turner8f43c712000-02-02 12:16:19 +00001017 /* check it */
1018 if ( n_ins > face->max_profile.maxSizeOfInstructions )
1019 {
David Turnerc3128612000-06-23 05:02:13 +00001020 FT_TRACE0(( "Too many instructions (%d) in composite glyph %ld\n",
1021 n_ins, subglyph->index ));
David Turner8f43c712000-02-02 12:16:19 +00001022 return TT_Err_Too_Many_Ins;
1023 }
David Turnere49ab252000-05-16 23:44:38 +00001024
David Turner8f43c712000-02-02 12:16:19 +00001025 /* read the instructions */
1026 if ( FILE_Read( exec->glyphIns, n_ins ) )
1027 goto Fail;
David Turnere49ab252000-05-16 23:44:38 +00001028
David Turnerc3128612000-06-23 05:02:13 +00001029 glyph->control_data = exec->glyphIns;
1030 glyph->control_len = n_ins;
1031
David Turner8f43c712000-02-02 12:16:19 +00001032 error = TT_Set_CodeRange( exec,
1033 tt_coderange_glyph,
1034 exec->glyphIns,
1035 n_ins );
Werner Lemberg78575dc2000-06-12 19:36:41 +00001036 if ( error )
1037 goto Fail;
David Turnere49ab252000-05-16 23:44:38 +00001038
David Turner8f43c712000-02-02 12:16:19 +00001039 /* prepare the execution context */
Werner Lemberga929ba92000-06-25 06:47:11 +00001040 tt_prepare_zone( &exec->pts, &gloader->base,
1041 start_point, start_contour );
David Turnerf0df85b2000-06-22 00:17:42 +00001042 pts = &exec->pts;
David Turnere49ab252000-05-16 23:44:38 +00001043
David Turner8f43c712000-02-02 12:16:19 +00001044 pts->n_points = num_points + 2;
David Turner43a2f652000-07-05 18:23:38 +00001045 pts->n_contours = gloader->base.outline.n_contours;
David Turnere49ab252000-05-16 23:44:38 +00001046
David Turner8f43c712000-02-02 12:16:19 +00001047 /* add phantom points */
1048 pp1 = pts->cur + num_points;
1049 pp1[0] = loader->pp1;
1050 pp1[1] = loader->pp2;
David Turnere49ab252000-05-16 23:44:38 +00001051
Werner Lembergdeb4e982000-06-29 03:14:25 +00001052 pts->tags[num_points ] = 0;
David Turner41dbcbf2000-03-09 11:46:25 +00001053 pts->tags[num_points + 1] = 0;
David Turnere49ab252000-05-16 23:44:38 +00001054
David Turner8f43c712000-02-02 12:16:19 +00001055 /* if hinting, round the phantom points */
Werner Lemberg78575dc2000-06-12 19:36:41 +00001056 if ( IS_HINTED( loader->load_flags ) )
David Turner8f43c712000-02-02 12:16:19 +00001057 {
Werner Lemberg78575dc2000-06-12 19:36:41 +00001058 pp1[0].x = ( ( loader->pp1.x + 32 ) & -64 );
1059 pp1[1].x = ( ( loader->pp2.x + 32 ) & -64 );
David Turner8f43c712000-02-02 12:16:19 +00001060 }
David Turnere49ab252000-05-16 23:44:38 +00001061
David Turner8f43c712000-02-02 12:16:19 +00001062 {
David Turnerf9b8dec2000-06-16 19:34:52 +00001063 FT_UInt k;
Werner Lemberg78575dc2000-06-12 19:36:41 +00001064
1065
David Turner43a2f652000-07-05 18:23:38 +00001066 for ( k = 0; k < num_points; k++ )
David Turner41dbcbf2000-03-09 11:46:25 +00001067 pts->tags[k] &= FT_Curve_Tag_On;
David Turner8f43c712000-02-02 12:16:19 +00001068 }
David Turnere49ab252000-05-16 23:44:38 +00001069
Werner Lemberg7fa51b52000-07-08 19:51:42 +00001070 cur_to_org( num_points + 2, pts );
David Turnere49ab252000-05-16 23:44:38 +00001071
David Turner8f43c712000-02-02 12:16:19 +00001072 /* now consider hinting */
Werner Lembergdcd2e142000-06-25 07:43:15 +00001073 if ( IS_HINTED( loader->load_flags ) && n_ins > 0 )
David Turner8f43c712000-02-02 12:16:19 +00001074 {
1075 exec->is_composite = TRUE;
1076 exec->pedantic_hinting =
Werner Lembergdcd2e142000-06-25 07:43:15 +00001077 (FT_Bool)( loader->load_flags & FT_LOAD_PEDANTIC );
David Turnere49ab252000-05-16 23:44:38 +00001078
David Turnerc3128612000-06-23 05:02:13 +00001079 error = TT_Run_Context( exec, ((TT_Size)loader->size)->debug );
David Turner8f43c712000-02-02 12:16:19 +00001080 if ( error && exec->pedantic_hinting )
1081 goto Fail;
1082 }
David Turnere49ab252000-05-16 23:44:38 +00001083
David Turner8f43c712000-02-02 12:16:19 +00001084 /* save glyph origin and advance points */
1085 loader->pp1 = pp1[0];
1086 loader->pp2 = pp1[1];
1087 }
Werner Lembergdcd2e142000-06-25 07:43:15 +00001088
Werner Lemberg78575dc2000-06-12 19:36:41 +00001089#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
Werner Lembergdcd2e142000-06-25 07:43:15 +00001090
David Turnerd2b1f351999-12-16 23:11:37 +00001091 }
Werner Lemberg78575dc2000-06-12 19:36:41 +00001092 /* end of composite loading */
David Turnerd2b1f351999-12-16 23:11:37 +00001093 }
1094
Werner Lemberg78575dc2000-06-12 19:36:41 +00001095 /***********************************************************************/
1096 /***********************************************************************/
1097 /***********************************************************************/
David Turnerd2b1f351999-12-16 23:11:37 +00001098
David Turner8f43c712000-02-02 12:16:19 +00001099 Fail:
Werner Lemberga929ba92000-06-25 06:47:11 +00001100 if ( opened_frame )
David Turner994d7742000-06-25 04:49:19 +00001101 face->forget_glyph_frame( loader );
David Turner90f68b72000-06-23 12:26:14 +00001102
1103 Exit:
David Turnere49ab252000-05-16 23:44:38 +00001104 return error;
David Turner8f43c712000-02-02 12:16:19 +00001105 }
1106
1107
David Turner8f43c712000-02-02 12:16:19 +00001108 static
Werner Lemberg78575dc2000-06-12 19:36:41 +00001109 void compute_glyph_metrics( TT_Loader* loader,
David Turnerf9b8dec2000-06-16 19:34:52 +00001110 FT_UInt glyph_index )
David Turner8f43c712000-02-02 12:16:19 +00001111 {
David Turnerf9b8dec2000-06-16 19:34:52 +00001112 FT_BBox bbox;
David Turnerc3128612000-06-23 05:02:13 +00001113 TT_Face face = (TT_Face)loader->face;
David Turnerf9b8dec2000-06-16 19:34:52 +00001114 FT_Fixed x_scale, y_scale;
David Turner8f43c712000-02-02 12:16:19 +00001115 TT_GlyphSlot glyph = loader->glyph;
David Turnerc3128612000-06-23 05:02:13 +00001116 TT_Size size = (TT_Size)loader->size;
David Turnere49ab252000-05-16 23:44:38 +00001117
Werner Lembergdcd2e142000-06-25 07:43:15 +00001118
Werner Lemberg78575dc2000-06-12 19:36:41 +00001119 x_scale = 0x10000L;
1120 y_scale = 0x10000L;
1121 if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
David Turner8f43c712000-02-02 12:16:19 +00001122 {
1123 x_scale = size->root.metrics.x_scale;
1124 y_scale = size->root.metrics.y_scale;
1125 }
David Turnere49ab252000-05-16 23:44:38 +00001126
David Turnered7f62a2000-03-28 11:19:28 +00001127 if ( glyph->format != ft_glyph_format_composite )
David Turner8f43c712000-02-02 12:16:19 +00001128 {
David Turnerf0df85b2000-06-22 00:17:42 +00001129 glyph->outline.flags &= ~ft_outline_single_pass;
Werner Lemberg78575dc2000-06-12 19:36:41 +00001130
David Turnerf0df85b2000-06-22 00:17:42 +00001131 /* copy outline to our glyph slot */
David Turner54e75742000-11-04 02:52:02 +00001132 FT_GlyphLoader_Copy_Points( glyph->internal->loader, loader->gloader );
1133 glyph->outline = glyph->internal->loader->base.outline;
Werner Lembergbd5ae402000-07-05 04:32:02 +00001134
David Turnered7f62a2000-03-28 11:19:28 +00001135 /* translate array so that (0,0) is the glyph's origin */
David Turnerf0df85b2000-06-22 00:17:42 +00001136 FT_Outline_Translate( &glyph->outline, -loader->pp1.x, 0 );
David Turnere49ab252000-05-16 23:44:38 +00001137
David Turnered7f62a2000-03-28 11:19:28 +00001138 FT_Outline_Get_CBox( &glyph->outline, &bbox );
1139
Werner Lemberg78575dc2000-06-12 19:36:41 +00001140 if ( IS_HINTED( loader->load_flags ) )
David Turnered7f62a2000-03-28 11:19:28 +00001141 {
1142 /* grid-fit the bounding box */
1143 bbox.xMin &= -64;
1144 bbox.yMin &= -64;
Werner Lemberg78575dc2000-06-12 19:36:41 +00001145 bbox.xMax = ( bbox.xMax + 63 ) & -64;
1146 bbox.yMax = ( bbox.yMax + 63 ) & -64;
David Turnered7f62a2000-03-28 11:19:28 +00001147 }
David Turner8f43c712000-02-02 12:16:19 +00001148 }
David Turnered7f62a2000-03-28 11:19:28 +00001149 else
1150 bbox = loader->bbox;
David Turnerd2b1f351999-12-16 23:11:37 +00001151
Werner Lemberga929ba92000-06-25 06:47:11 +00001152 /* get the device-independent horizontal advance. It is scaled later */
1153 /* by the base layer. */
David Turnerd2b1f351999-12-16 23:11:37 +00001154 {
David Turnerf0df85b2000-06-22 00:17:42 +00001155 FT_Pos advance = loader->advance;
David Turnerd2b1f351999-12-16 23:11:37 +00001156
Werner Lemberga929ba92000-06-25 06:47:11 +00001157
Werner Lemberg5811c7c2000-07-02 13:53:16 +00001158 /* the flag FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH was introduced to */
1159 /* correctly support DynaLab fonts, which have an incorrect */
1160 /* `advance_Width_Max' field! It is used, to my knowledge, */
1161 /* exclusively in the X-TrueType font server. */
1162 /* */
Werner Lemberg78575dc2000-06-12 19:36:41 +00001163 if ( face->postscript.isFixedPitch &&
1164 ( loader->load_flags & FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ) == 0 )
David Turnerd2b1f351999-12-16 23:11:37 +00001165 advance = face->horizontal.advance_Width_Max;
1166
David Turnerf0df85b2000-06-22 00:17:42 +00001167 /* we need to return the advance in font units in linearHoriAdvance, */
Werner Lemberga929ba92000-06-25 06:47:11 +00001168 /* it will be scaled later by the base layer. */
David Turnerf0df85b2000-06-22 00:17:42 +00001169 glyph->linearHoriAdvance = advance;
David Turnerd2b1f351999-12-16 23:11:37 +00001170 }
1171
1172 glyph->metrics.horiBearingX = bbox.xMin;
1173 glyph->metrics.horiBearingY = bbox.yMax;
David Turner8f43c712000-02-02 12:16:19 +00001174 glyph->metrics.horiAdvance = loader->pp2.x - loader->pp1.x;
David Turnerd2b1f351999-12-16 23:11:37 +00001175
1176 /* Now take care of vertical metrics. In the case where there is */
1177 /* no vertical information within the font (relatively common), make */
1178 /* up some metrics by `hand'... */
1179
1180 {
David Turnerf9b8dec2000-06-16 19:34:52 +00001181 FT_Short top_bearing; /* vertical top side bearing (EM units) */
1182 FT_UShort advance_height; /* vertical advance height (EM units) */
David Turnerd2b1f351999-12-16 23:11:37 +00001183
David Turnerf9b8dec2000-06-16 19:34:52 +00001184 FT_Pos left; /* scaled vertical left side bearing */
1185 FT_Pos Top; /* scaled original vertical top side bearing */
1186 FT_Pos top; /* scaled vertical top side bearing */
1187 FT_Pos advance; /* scaled vertical advance height */
David Turnerd2b1f351999-12-16 23:11:37 +00001188
1189
1190 /* Get the unscaled `tsb' and `ah' */
1191 if ( face->vertical_info &&
1192 face->vertical.number_Of_VMetrics > 0 )
1193 {
1194 /* Don't assume that both the vertical header and vertical */
1195 /* metrics are present in the same font :-) */
1196
1197 TT_Get_Metrics( (TT_HoriHeader*)&face->vertical,
1198 glyph_index,
1199 &top_bearing,
1200 &advance_height );
1201 }
1202 else
1203 {
Werner Lemberg78575dc2000-06-12 19:36:41 +00001204 /* Make up the distances from the horizontal header. */
David Turnerd2b1f351999-12-16 23:11:37 +00001205
Werner Lemberg78575dc2000-06-12 19:36:41 +00001206 /* NOTE: The OS/2 values are the only `portable' ones, */
1207 /* which is why we use them, if there is an OS/2 */
1208 /* table in the font. Otherwise, we use the */
1209 /* values defined in the horizontal header. */
1210 /* */
1211 /* NOTE2: The sTypoDescender is negative, which is why */
1212 /* we compute the baseline-to-baseline distance */
1213 /* here with: */
1214 /* ascender - descender + linegap */
1215 /* */
David Turnerd2b1f351999-12-16 23:11:37 +00001216 if ( face->os2.version != 0xFFFF )
1217 {
1218 top_bearing = face->os2.sTypoLineGap / 2;
David Turnerf9b8dec2000-06-16 19:34:52 +00001219 advance_height = (FT_UShort)( face->os2.sTypoAscender -
Werner Lemberg78575dc2000-06-12 19:36:41 +00001220 face->os2.sTypoDescender +
1221 face->os2.sTypoLineGap );
David Turnerd2b1f351999-12-16 23:11:37 +00001222 }
1223 else
1224 {
1225 top_bearing = face->horizontal.Line_Gap / 2;
David Turnerf9b8dec2000-06-16 19:34:52 +00001226 advance_height = (FT_UShort)( face->horizontal.Ascender +
Werner Lemberg78575dc2000-06-12 19:36:41 +00001227 face->horizontal.Descender +
1228 face->horizontal.Line_Gap );
David Turnerd2b1f351999-12-16 23:11:37 +00001229 }
1230 }
1231
Werner Lemberg78575dc2000-06-12 19:36:41 +00001232 /* We must adjust the top_bearing value from the bounding box given */
1233 /* in the glyph header to te bounding box calculated with */
David Turnerf0df85b2000-06-22 00:17:42 +00001234 /* FT_Get_Outline_CBox(). */
David Turnerfc1f9892000-01-07 18:44:50 +00001235
David Turnerd2b1f351999-12-16 23:11:37 +00001236 /* scale the metrics */
Werner Lemberg78575dc2000-06-12 19:36:41 +00001237 if ( !( loader->load_flags & FT_LOAD_NO_SCALE ) )
David Turnerd2b1f351999-12-16 23:11:37 +00001238 {
David Turner8f43c712000-02-02 12:16:19 +00001239 Top = FT_MulFix( top_bearing, y_scale );
1240 top = FT_MulFix( top_bearing + loader->bbox.yMax, y_scale )
1241 - bbox.yMax;
1242 advance = FT_MulFix( advance_height, y_scale );
David Turnerd2b1f351999-12-16 23:11:37 +00001243 }
1244 else
1245 {
David Turnerfc1f9892000-01-07 18:44:50 +00001246 Top = top_bearing;
David Turner8f43c712000-02-02 12:16:19 +00001247 top = top_bearing + loader->bbox.yMax - bbox.yMax;
David Turnerd2b1f351999-12-16 23:11:37 +00001248 advance = advance_height;
1249 }
1250
Werner Lemberga929ba92000-06-25 06:47:11 +00001251 /* set the advance height in design units. It is scaled later by */
1252 /* the base layer. */
David Turnerf0df85b2000-06-22 00:17:42 +00001253 glyph->linearVertAdvance = advance_height;
David Turnerd2b1f351999-12-16 23:11:37 +00001254
Werner Lemberga929ba92000-06-25 06:47:11 +00001255 /* XXX: for now, we have no better algorithm for the lsb, but it */
1256 /* should work fine. */
1257 /* */
David Turnerd2b1f351999-12-16 23:11:37 +00001258 left = ( bbox.xMin - bbox.xMax ) / 2;
1259
1260 /* grid-fit them if necessary */
Werner Lemberg78575dc2000-06-12 19:36:41 +00001261 if ( IS_HINTED( loader->load_flags ) )
David Turnerd2b1f351999-12-16 23:11:37 +00001262 {
1263 left &= -64;
Werner Lemberg78575dc2000-06-12 19:36:41 +00001264 top = ( top + 63 ) & -64;
1265 advance = ( advance + 32 ) & -64;
David Turnerd2b1f351999-12-16 23:11:37 +00001266 }
1267
1268 glyph->metrics.vertBearingX = left;
1269 glyph->metrics.vertBearingY = top;
1270 glyph->metrics.vertAdvance = advance;
1271 }
1272
Werner Lembergdcd2e142000-06-25 07:43:15 +00001273 /* adjust advance width to the value contained in the hdmx table */
David Turner8f43c712000-02-02 12:16:19 +00001274 if ( !face->postscript.isFixedPitch && size &&
Werner Lemberg78575dc2000-06-12 19:36:41 +00001275 IS_HINTED( loader->load_flags ) )
David Turnerd2b1f351999-12-16 23:11:37 +00001276 {
David Turnerf9b8dec2000-06-16 19:34:52 +00001277 FT_Byte* widths = Get_Advance_Widths( face,
Werner Lemberg78575dc2000-06-12 19:36:41 +00001278 size->root.metrics.x_ppem );
Werner Lembergdcd2e142000-06-25 07:43:15 +00001279
1280
David Turnerd2b1f351999-12-16 23:11:37 +00001281 if ( widths )
1282 glyph->metrics.horiAdvance = widths[glyph_index] << 6;
1283 }
1284
David Turnerd2b1f351999-12-16 23:11:37 +00001285 /* set glyph dimensions */
1286 glyph->metrics.width = bbox.xMax - bbox.xMin;
1287 glyph->metrics.height = bbox.yMax - bbox.yMin;
David Turner8f43c712000-02-02 12:16:19 +00001288 }
David Turnerd2b1f351999-12-16 23:11:37 +00001289
David Turnerd2b1f351999-12-16 23:11:37 +00001290
Werner Lemberg78575dc2000-06-12 19:36:41 +00001291 /*************************************************************************/
1292 /* */
1293 /* <Function> */
1294 /* TT_Load_Glyph */
1295 /* */
1296 /* <Description> */
1297 /* A function used to load a single glyph within a given glyph slot, */
1298 /* for a given size. */
1299 /* */
1300 /* <Input> */
1301 /* glyph :: A handle to a target slot object where the glyph */
1302 /* will be loaded. */
1303 /* */
1304 /* size :: A handle to the source face size at which the glyph */
1305 /* must be scaled/loaded. */
1306 /* */
1307 /* glyph_index :: The index of the glyph in the font file. */
1308 /* */
1309 /* load_flags :: A flag indicating what to load for this glyph. The */
1310 /* FT_LOAD_XXX constants can be used to control the */
1311 /* glyph loading process (e.g., whether the outline */
1312 /* should be scaled, whether to load bitmaps or not, */
1313 /* whether to hint the outline, etc). */
1314 /* */
1315 /* <Return> */
Werner Lemberga929ba92000-06-25 06:47:11 +00001316 /* FreeType error code. 0 means success. */
Werner Lemberg78575dc2000-06-12 19:36:41 +00001317 /* */
David Turner76a5f622000-11-04 01:55:49 +00001318 FT_LOCAL_DEF
David Turnerf9b8dec2000-06-16 19:34:52 +00001319 FT_Error TT_Load_Glyph( TT_Size size,
David Turner8f43c712000-02-02 12:16:19 +00001320 TT_GlyphSlot glyph,
David Turnerf9b8dec2000-06-16 19:34:52 +00001321 FT_UShort glyph_index,
1322 FT_UInt load_flags )
David Turner8f43c712000-02-02 12:16:19 +00001323 {
1324 SFNT_Interface* sfnt;
1325 TT_Face face;
1326 FT_Stream stream;
1327 FT_Memory memory;
David Turnerf9b8dec2000-06-16 19:34:52 +00001328 FT_Error error;
David Turner8f43c712000-02-02 12:16:19 +00001329 TT_Loader loader;
David Turnere49ab252000-05-16 23:44:38 +00001330
Werner Lemberg78575dc2000-06-12 19:36:41 +00001331
David Turner8f43c712000-02-02 12:16:19 +00001332 face = (TT_Face)glyph->face;
1333 sfnt = (SFNT_Interface*)face->sfnt;
1334 stream = face->root.stream;
1335 memory = face->root.memory;
1336 error = 0;
David Turnered7f62a2000-03-28 11:19:28 +00001337
Werner Lemberg78575dc2000-06-12 19:36:41 +00001338 if ( !size || ( load_flags & FT_LOAD_NO_SCALE ) ||
1339 ( load_flags & FT_LOAD_NO_RECURSE ) )
David Turner8f43c712000-02-02 12:16:19 +00001340 {
1341 size = NULL;
1342 load_flags |= FT_LOAD_NO_SCALE |
1343 FT_LOAD_NO_HINTING |
1344 FT_LOAD_NO_BITMAP;
1345 }
1346
David Turnered7f62a2000-03-28 11:19:28 +00001347 glyph->num_subglyphs = 0;
1348
David Turner8f43c712000-02-02 12:16:19 +00001349#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
Werner Lemberg4b680072000-11-07 06:30:29 +00001350
1351 /* try to load embedded bitmap if any */
1352 /* */
1353 /* XXX: The convention should be emphasized in */
1354 /* the documents because it can be confusing. */
Werner Lemberg78575dc2000-06-12 19:36:41 +00001355 if ( size &&
Werner Lemberg4b680072000-11-07 06:30:29 +00001356 size->strike_index != 0xFFFF &&
David Turnerf96594f2000-11-06 23:07:51 +00001357 sfnt->load_sbits &&
1358 ( load_flags & FT_LOAD_NO_BITMAP ) == 0 )
1359
David Turner8f43c712000-02-02 12:16:19 +00001360 {
1361 TT_SBit_Metrics metrics;
David Turnere49ab252000-05-16 23:44:38 +00001362
Werner Lemberg78575dc2000-06-12 19:36:41 +00001363
David Turner8f43c712000-02-02 12:16:19 +00001364 error = sfnt->load_sbit_image( face,
David Turnerf96594f2000-11-06 23:07:51 +00001365 size->strike_index,
David Turner8f43c712000-02-02 12:16:19 +00001366 glyph_index,
David Turner109fcf62000-05-17 23:35:37 +00001367 load_flags,
David Turner8f43c712000-02-02 12:16:19 +00001368 stream,
1369 &glyph->bitmap,
1370 &metrics );
1371 if ( !error )
1372 {
1373 glyph->outline.n_points = 0;
1374 glyph->outline.n_contours = 0;
1375
David Turnerf9b8dec2000-06-16 19:34:52 +00001376 glyph->metrics.width = (FT_Pos)metrics.width << 6;
1377 glyph->metrics.height = (FT_Pos)metrics.height << 6;
David Turner8f43c712000-02-02 12:16:19 +00001378
David Turnerf9b8dec2000-06-16 19:34:52 +00001379 glyph->metrics.horiBearingX = (FT_Pos)metrics.horiBearingX << 6;
1380 glyph->metrics.horiBearingY = (FT_Pos)metrics.horiBearingY << 6;
1381 glyph->metrics.horiAdvance = (FT_Pos)metrics.horiAdvance << 6;
David Turner8f43c712000-02-02 12:16:19 +00001382
David Turnerf9b8dec2000-06-16 19:34:52 +00001383 glyph->metrics.vertBearingX = (FT_Pos)metrics.vertBearingX << 6;
1384 glyph->metrics.vertBearingY = (FT_Pos)metrics.vertBearingY << 6;
1385 glyph->metrics.vertAdvance = (FT_Pos)metrics.vertAdvance << 6;
David Turner8f43c712000-02-02 12:16:19 +00001386
1387 glyph->format = ft_glyph_format_bitmap;
David Turnerf0df85b2000-06-22 00:17:42 +00001388 if ( load_flags & FT_LOAD_VERTICAL_LAYOUT )
1389 {
David Turnere161ee42000-07-10 22:03:10 +00001390 glyph->bitmap_left = metrics.vertBearingX;
1391 glyph->bitmap_top = metrics.vertBearingY;
David Turnerf0df85b2000-06-22 00:17:42 +00001392 }
1393 else
1394 {
David Turnere161ee42000-07-10 22:03:10 +00001395 glyph->bitmap_left = metrics.horiBearingX;
1396 glyph->bitmap_top = metrics.horiBearingY;
David Turnerf0df85b2000-06-22 00:17:42 +00001397 }
David Turner8f43c712000-02-02 12:16:19 +00001398 return error;
1399 }
1400 }
Werner Lemberg78575dc2000-06-12 19:36:41 +00001401
David Turner8f43c712000-02-02 12:16:19 +00001402#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
1403
Werner Lemberg5811c7c2000-07-02 13:53:16 +00001404 /* seek to the beginning of the glyph table. For Type 42 fonts */
Werner Lemberg78575dc2000-06-12 19:36:41 +00001405 /* the table might be accessed from a Postscript stream or something */
1406 /* else... */
1407
David Turner8f43c712000-02-02 12:16:19 +00001408 error = face->goto_table( face, TTAG_glyf, stream, 0 );
Werner Lemberg78575dc2000-06-12 19:36:41 +00001409 if ( error )
David Turner8f43c712000-02-02 12:16:19 +00001410 {
Werner Lembergdcd2e142000-06-25 07:43:15 +00001411 FT_ERROR(( "TT_Load_Glyph: could not access glyph table\n" ));
David Turner08fdac92000-02-21 16:01:33 +00001412 goto Exit;
David Turner8f43c712000-02-02 12:16:19 +00001413 }
1414
Werner Lemberg78575dc2000-06-12 19:36:41 +00001415 MEM_Set( &loader, 0, sizeof ( loader ) );
David Turner8f43c712000-02-02 12:16:19 +00001416
David Turner08fdac92000-02-21 16:01:33 +00001417 /* update the glyph zone bounds */
David Turner08fdac92000-02-21 16:01:33 +00001418 {
David Turnerf0df85b2000-06-22 00:17:42 +00001419 FT_GlyphLoader* gloader = FT_FACE_DRIVER(face)->glyph_loader;
Werner Lemberga929ba92000-06-25 06:47:11 +00001420
Werner Lembergbd5ae402000-07-05 04:32:02 +00001421
David Turnerf0df85b2000-06-22 00:17:42 +00001422 loader.gloader = gloader;
Werner Lembergbd5ae402000-07-05 04:32:02 +00001423
David Turnerf0df85b2000-06-22 00:17:42 +00001424 FT_GlyphLoader_Rewind( gloader );
Werner Lembergbd5ae402000-07-05 04:32:02 +00001425
David Turnerf0df85b2000-06-22 00:17:42 +00001426 tt_prepare_zone( &loader.zone, &gloader->base, 0, 0 );
1427 tt_prepare_zone( &loader.base, &gloader->base, 0, 0 );
David Turner08fdac92000-02-21 16:01:33 +00001428 }
David Turner08fdac92000-02-21 16:01:33 +00001429
David Turner8f43c712000-02-02 12:16:19 +00001430#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
Werner Lemberg78575dc2000-06-12 19:36:41 +00001431
David Turner8f43c712000-02-02 12:16:19 +00001432 if ( size )
1433 {
1434 /* query new execution context */
Werner Lemberg78575dc2000-06-12 19:36:41 +00001435 loader.exec = size->debug ? size->context : TT_New_Context( face );
David Turner8f43c712000-02-02 12:16:19 +00001436 if ( !loader.exec )
1437 return TT_Err_Could_Not_Find_Context;
David Turnere49ab252000-05-16 23:44:38 +00001438
David Turner8f43c712000-02-02 12:16:19 +00001439 TT_Load_Context( loader.exec, face, size );
David Turnerc3128612000-06-23 05:02:13 +00001440 loader.instructions = loader.exec->glyphIns;
David Turner8f43c712000-02-02 12:16:19 +00001441
1442 /* load default graphics state - if needed */
1443 if ( size->GS.instruct_control & 2 )
1444 loader.exec->GS = tt_default_graphics_state;
1445 }
Werner Lemberg78575dc2000-06-12 19:36:41 +00001446
David Turner8f43c712000-02-02 12:16:19 +00001447#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
1448
Werner Lemberg78575dc2000-06-12 19:36:41 +00001449 /* clear all outline flags, except the `owner' one */
David Turner81bb4ad2000-06-28 04:19:49 +00001450 glyph->outline.flags = 0;
David Turnere49ab252000-05-16 23:44:38 +00001451
David Turner04aa8002000-06-01 03:27:48 +00001452 if ( size && size->root.metrics.y_ppem < 24 )
David Turner41dbcbf2000-03-09 11:46:25 +00001453 glyph->outline.flags |= ft_outline_high_precision;
David Turner8f43c712000-02-02 12:16:19 +00001454
Werner Lemberg78575dc2000-06-12 19:36:41 +00001455 /* let's initialize the rest of our loader now */
1456
David Turner8f43c712000-02-02 12:16:19 +00001457 loader.load_flags = load_flags;
1458
David Turnerc3128612000-06-23 05:02:13 +00001459 loader.face = (FT_Face)face;
1460 loader.size = (FT_Size)size;
1461 loader.glyph = (FT_GlyphSlot)glyph;
David Turner8f43c712000-02-02 12:16:19 +00001462 loader.stream = stream;
Werner Lembergbd5ae402000-07-05 04:32:02 +00001463
David Turnerc3128612000-06-23 05:02:13 +00001464 loader.glyf_offset = FILE_Pos();
David Turner8f43c712000-02-02 12:16:19 +00001465
1466#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
Werner Lemberg78575dc2000-06-12 19:36:41 +00001467
1468 /* if the cvt program has disabled hinting, the argument */
1469 /* is ignored. */
1470 if ( size && ( size->GS.instruct_control & 1 ) )
David Turner8f43c712000-02-02 12:16:19 +00001471 loader.load_flags |= FT_LOAD_NO_HINTING;
Werner Lemberg78575dc2000-06-12 19:36:41 +00001472
1473#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
David Turner8f43c712000-02-02 12:16:19 +00001474
1475 /* Main loading loop */
David Turner3475e7f2000-05-17 20:56:01 +00001476 glyph->format = ft_glyph_format_outline;
Werner Lemberg78575dc2000-06-12 19:36:41 +00001477 glyph->num_subglyphs = 0;
David Turner8f43c712000-02-02 12:16:19 +00001478 error = load_truetype_glyph( &loader, glyph_index );
Werner Lemberg78575dc2000-06-12 19:36:41 +00001479 if ( !error )
David Turner8f43c712000-02-02 12:16:19 +00001480 compute_glyph_metrics( &loader, glyph_index );
1481
1482#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
Werner Lembergdcd2e142000-06-25 07:43:15 +00001483
David Turnerd2b1f351999-12-16 23:11:37 +00001484 if ( !size || !size->debug )
David Turner8f43c712000-02-02 12:16:19 +00001485 TT_Done_Context( loader.exec );
Werner Lembergdcd2e142000-06-25 07:43:15 +00001486
1487#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
David Turnerd2b1f351999-12-16 23:11:37 +00001488
David Turner08fdac92000-02-21 16:01:33 +00001489 Exit:
David Turnerd2b1f351999-12-16 23:11:37 +00001490 return error;
1491 }
1492
1493
David Turnerd2b1f351999-12-16 23:11:37 +00001494/* END */