blob: a9c19bf6fb689ec1d72d24c07284c91c0a18c01c [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
18
David Turnerefce08d2000-05-11 18:23:52 +000019#include <freetype/internal/ftdebug.h>
20#include <freetype/internal/ftcalc.h>
21#include <freetype/internal/ftstream.h>
22#include <freetype/internal/sfnt.h>
23#include <freetype/tttags.h>
David Turnerf9ca2bb2000-06-30 23:12:55 +000024#include <freetype/ftoutln.h>
David Turnerd2b1f351999-12-16 23:11:37 +000025
David Turnerd2b1f351999-12-16 23:11:37 +000026
Werner Lemberg7fa51b52000-07-08 19:51:42 +000027#ifdef FT_FLAT_COMPILE
28
29#include "ttgload.h"
30
31#else
32
33#include <truetype/ttgload.h>
34
35#endif
Werner Lemberg78575dc2000-06-12 19:36:41 +000036
David Turnera90663f2000-07-08 00:41:13 +000037
Werner Lemberg78575dc2000-06-12 19:36:41 +000038 /*************************************************************************/
39 /* */
40 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
41 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
42 /* messages during execution. */
43 /* */
David Turnerd2b1f351999-12-16 23:11:37 +000044#undef FT_COMPONENT
45#define FT_COMPONENT trace_ttgload
46
47
48 /*************************************************************************/
49 /* */
50 /* Composite font flags. */
51 /* */
52#define ARGS_ARE_WORDS 0x001
53#define ARGS_ARE_XY_VALUES 0x002
54#define ROUND_XY_TO_GRID 0x004
55#define WE_HAVE_A_SCALE 0x008
56/* reserved 0x010 */
57#define MORE_COMPONENTS 0x020
58#define WE_HAVE_AN_XY_SCALE 0x040
59#define WE_HAVE_A_2X2 0x080
60#define WE_HAVE_INSTR 0x100
61#define USE_MY_METRICS 0x200
62
63
David Turnerf9b8dec2000-06-16 19:34:52 +000064
David Turnerd2b1f351999-12-16 23:11:37 +000065 /*************************************************************************/
Werner Lemberg78575dc2000-06-12 19:36:41 +000066 /* */
67 /* <Function> */
68 /* TT_Get_Metrics */
69 /* */
70 /* <Description> */
David Turnerd2b1f351999-12-16 23:11:37 +000071 /* Returns the horizontal or vertical metrics in font units for a */
72 /* given glyph. The metrics are the left side bearing (resp. top */
73 /* side bearing) and advance width (resp. advance height). */
74 /* */
Werner Lemberg78575dc2000-06-12 19:36:41 +000075 /* <Input> */
76 /* header :: A pointer to either the horizontal or vertical metrics */
77 /* structure. */
78 /* */
79 /* index :: The glyph index. */
80 /* */
81 /* <Output> */
82 /* bearing :: The bearing, either left side or top side. */
83 /* */
84 /* advance :: The advance width resp. advance height. */
85 /* */
86 /* <Note> */
87 /* This function will much probably move to another component in the */
88 /* near future, but I haven't decided which yet. */
89 /* */
David Turner76a5f622000-11-04 01:55:49 +000090 FT_LOCAL_DEF
David Turnerd2b1f351999-12-16 23:11:37 +000091 void TT_Get_Metrics( TT_HoriHeader* header,
David Turnerf9b8dec2000-06-16 19:34:52 +000092 FT_UInt index,
93 FT_Short* bearing,
94 FT_UShort* advance )
David Turnerd2b1f351999-12-16 23:11:37 +000095 {
96 TT_LongMetrics* longs_m;
David Turnerf9b8dec2000-06-16 19:34:52 +000097 FT_UShort k = header->number_Of_HMetrics;
David Turnerd2b1f351999-12-16 23:11:37 +000098
99
100 if ( index < k )
101 {
102 longs_m = (TT_LongMetrics*)header->long_metrics + index;
103 *bearing = longs_m->bearing;
104 *advance = longs_m->advance;
105 }
106 else
107 {
108 *bearing = ((TT_ShortMetrics*)header->short_metrics)[index - k];
109 *advance = ((TT_LongMetrics*)header->long_metrics)[k - 1].advance;
110 }
111 }
112
113
114 /*************************************************************************/
Werner Lemberg78575dc2000-06-12 19:36:41 +0000115 /* */
Werner Lembergdcd2e142000-06-25 07:43:15 +0000116 /* Returns the horizontal metrics in font units for a given glyph. If */
117 /* `check' is true, take care of monospaced fonts by returning the */
118 /* advance width maximum. */
David Turnerd2b1f351999-12-16 23:11:37 +0000119 /* */
David Turnerd2b1f351999-12-16 23:11:37 +0000120 static
121 void Get_HMetrics( TT_Face face,
David Turnerf9b8dec2000-06-16 19:34:52 +0000122 FT_UInt index,
123 FT_Bool check,
124 FT_Short* lsb,
125 FT_UShort* aw )
David Turnerd2b1f351999-12-16 23:11:37 +0000126 {
127 TT_Get_Metrics( &face->horizontal, index, lsb, aw );
128
129 if ( check && face->postscript.isFixedPitch )
130 *aw = face->horizontal.advance_Width_Max;
131 }
132
133
134 /*************************************************************************/
Werner Lemberg78575dc2000-06-12 19:36:41 +0000135 /* */
David Turnerd2b1f351999-12-16 23:11:37 +0000136 /* Returns the advance width table for a given pixel size if it is */
137 /* found in the font's `hdmx' table (if any). */
138 /* */
David Turnerd2b1f351999-12-16 23:11:37 +0000139 static
David Turnerf9b8dec2000-06-16 19:34:52 +0000140 FT_Byte* Get_Advance_Widths( TT_Face face,
141 FT_UShort ppem )
David Turnerd2b1f351999-12-16 23:11:37 +0000142 {
David Turnerf9b8dec2000-06-16 19:34:52 +0000143 FT_UShort n;
David Turnerd2b1f351999-12-16 23:11:37 +0000144
145 for ( n = 0; n < face->hdmx.num_records; n++ )
146 if ( face->hdmx.records[n].ppem == ppem )
147 return face->hdmx.records[n].widths;
148
149 return NULL;
150 }
151
152
Werner Lemberg5811c7c2000-07-02 13:53:16 +0000153#define cur_to_org( n, zone ) \
David Turnerf9b8dec2000-06-16 19:34:52 +0000154 MEM_Copy( (zone)->org, (zone)->cur, n * sizeof ( FT_Vector ) )
David Turnerd2b1f351999-12-16 23:11:37 +0000155
Werner Lemberg5811c7c2000-07-02 13:53:16 +0000156#define org_to_cur( n, zone ) \
David Turnerf9b8dec2000-06-16 19:34:52 +0000157 MEM_Copy( (zone)->cur, (zone)->org, n * sizeof ( FT_Vector ) )
David Turnerd2b1f351999-12-16 23:11:37 +0000158
159
160 /*************************************************************************/
Werner Lemberg78575dc2000-06-12 19:36:41 +0000161 /* */
David Turnerd2b1f351999-12-16 23:11:37 +0000162 /* Translates an array of coordinates. */
163 /* */
David Turnerd2b1f351999-12-16 23:11:37 +0000164 static
David Turnerf9b8dec2000-06-16 19:34:52 +0000165 void translate_array( FT_UInt n,
166 FT_Vector* coords,
167 FT_Pos delta_x,
168 FT_Pos delta_y )
David Turnerd2b1f351999-12-16 23:11:37 +0000169 {
David Turnerf9b8dec2000-06-16 19:34:52 +0000170 FT_UInt k;
Werner Lemberg78575dc2000-06-12 19:36:41 +0000171
Werner Lemberg5811c7c2000-07-02 13:53:16 +0000172
David Turnerd2b1f351999-12-16 23:11:37 +0000173 if ( delta_x )
174 for ( k = 0; k < n; k++ )
175 coords[k].x += delta_x;
176
177 if ( delta_y )
178 for ( k = 0; k < n; k++ )
179 coords[k].y += delta_y;
180 }
181
182
Werner Lemberg5811c7c2000-07-02 13:53:16 +0000183 static
184 void tt_prepare_zone( TT_GlyphZone* zone,
185 FT_GlyphLoad* load,
186 FT_UInt start_point,
187 FT_UInt start_contour )
David Turnerd2b1f351999-12-16 23:11:37 +0000188 {
David Turnerf0df85b2000-06-22 00:17:42 +0000189 zone->n_points = load->outline.n_points - start_point;
190 zone->n_contours = load->outline.n_contours - start_contour;
191 zone->org = load->extra_points + start_point;
192 zone->cur = load->outline.points + start_point;
193 zone->tags = (FT_Byte*)load->outline.tags + start_point;
194 zone->contours = (FT_UShort*)load->outline.contours + start_contour;
Werner Lembergbd5ae402000-07-05 04:32:02 +0000195 }
David Turnerd2b1f351999-12-16 23:11:37 +0000196
197
David Turner8f43c712000-02-02 12:16:19 +0000198#undef IS_HINTED
Werner Lemberg78575dc2000-06-12 19:36:41 +0000199#define IS_HINTED( flags ) ( ( flags & FT_LOAD_NO_HINTING ) == 0 )
200
David Turner8f43c712000-02-02 12:16:19 +0000201
David Turnerd2b1f351999-12-16 23:11:37 +0000202 /*************************************************************************/
203 /* */
David Turner90f68b72000-06-23 12:26:14 +0000204 /* The following functions are used by default with TrueType fonts. */
205 /* However, they can be replaced by alternatives if we need to support */
Werner Lemberga929ba92000-06-25 06:47:11 +0000206 /* TrueType-compressed formats (like MicroType) in the future. */
David Turnerd2b1f351999-12-16 23:11:37 +0000207 /* */
Werner Lemberga929ba92000-06-25 06:47:11 +0000208 /*************************************************************************/
David Turner90f68b72000-06-23 12:26:14 +0000209
David Turner76a5f622000-11-04 01:55:49 +0000210 FT_CALLBACK_DEF
David Turner90f68b72000-06-23 12:26:14 +0000211 FT_Error TT_Access_Glyph_Frame( TT_Loader* loader,
212 FT_UInt glyph_index,
213 FT_ULong offset,
214 FT_UInt byte_count )
215 {
Werner Lemberge72c9fe2000-07-31 18:59:02 +0000216 FT_Error error;
217 FT_Stream stream = loader->stream;
Werner Lembergbd5ae402000-07-05 04:32:02 +0000218
Werner Lemberg353dfea2000-08-29 18:58:41 +0000219 /* for non-debug mode */
220 FT_UNUSED( glyph_index );
221
Werner Lemberga929ba92000-06-25 06:47:11 +0000222
David Turner90f68b72000-06-23 12:26:14 +0000223 FT_TRACE5(( "Glyph %ld\n", glyph_index ));
Werner Lemberge72c9fe2000-07-31 18:59:02 +0000224
225 /* the following line sets the `error' variable through macros! */
226 if ( FILE_Seek( offset ) || ACCESS_Frame( byte_count ) )
227 return error;
228
229 return TT_Err_Ok;
Werner Lembergbd5ae402000-07-05 04:32:02 +0000230 }
David Turner90f68b72000-06-23 12:26:14 +0000231
232
David Turner76a5f622000-11-04 01:55:49 +0000233 FT_CALLBACK_DEF
Werner Lemberga929ba92000-06-25 06:47:11 +0000234 void TT_Forget_Glyph_Frame( TT_Loader* loader )
David Turner90f68b72000-06-23 12:26:14 +0000235 {
236 FT_Stream stream = loader->stream;
Werner Lemberga929ba92000-06-25 06:47:11 +0000237
238
David Turner90f68b72000-06-23 12:26:14 +0000239 FORGET_Frame();
Werner Lembergbd5ae402000-07-05 04:32:02 +0000240 }
David Turner90f68b72000-06-23 12:26:14 +0000241
242
David Turner76a5f622000-11-04 01:55:49 +0000243 FT_CALLBACK_DEF
David Turner90f68b72000-06-23 12:26:14 +0000244 FT_Error TT_Load_Glyph_Header( TT_Loader* loader )
245 {
246 FT_Stream stream = loader->stream;
Werner Lembergbd5ae402000-07-05 04:32:02 +0000247
Werner Lemberga929ba92000-06-25 06:47:11 +0000248
David Turner90f68b72000-06-23 12:26:14 +0000249 loader->n_contours = GET_Short();
250
251 loader->bbox.xMin = GET_Short();
252 loader->bbox.yMin = GET_Short();
253 loader->bbox.xMax = GET_Short();
254 loader->bbox.yMax = GET_Short();
255
256 FT_TRACE5(( " # of contours: %d\n", loader->n_contours ));
257 FT_TRACE5(( " xMin: %4d xMax: %4d\n", loader->bbox.xMin,
258 loader->bbox.xMax ));
259 FT_TRACE5(( " yMin: %4d yMax: %4d\n", loader->bbox.yMin,
260 loader->bbox.yMax ));
Werner Lembergbd5ae402000-07-05 04:32:02 +0000261
David Turner90f68b72000-06-23 12:26:14 +0000262 return FT_Err_Ok;
Werner Lembergbd5ae402000-07-05 04:32:02 +0000263 }
David Turner90f68b72000-06-23 12:26:14 +0000264
265
David Turner76a5f622000-11-04 01:55:49 +0000266 FT_CALLBACK_DEF
David Turner994d7742000-06-25 04:49:19 +0000267 FT_Error TT_Load_Simple_Glyph( TT_Loader* load )
David Turnerd2b1f351999-12-16 23:11:37 +0000268 {
David Turnerf0df85b2000-06-22 00:17:42 +0000269 FT_Error error;
David Turner994d7742000-06-25 04:49:19 +0000270 FT_Stream stream = load->stream;
271 FT_GlyphLoader* gloader = load->gloader;
272 FT_Int n_contours = load->n_contours;
David Turnerf0df85b2000-06-22 00:17:42 +0000273 FT_Outline* outline;
David Turnerc3128612000-06-23 05:02:13 +0000274 TT_Face face = (TT_Face)load->face;
275 TT_GlyphSlot slot = (TT_GlyphSlot)load->glyph;
David Turnerf0df85b2000-06-22 00:17:42 +0000276 FT_UShort n_ins;
277 FT_Int n, n_points;
David Turnere49ab252000-05-16 23:44:38 +0000278
Werner Lemberg78575dc2000-06-12 19:36:41 +0000279
David Turnerf0df85b2000-06-22 00:17:42 +0000280 /* reading the contours endpoints & number of points */
281 {
282 short* cur = gloader->current.outline.contours;
283 short* limit = cur + n_contours;
Werner Lembergbd5ae402000-07-05 04:32:02 +0000284
Werner Lemberga929ba92000-06-25 06:47:11 +0000285
David Turnerf0df85b2000-06-22 00:17:42 +0000286 for ( ; cur < limit; cur++ )
287 cur[0] = GET_UShort();
Werner Lembergbd5ae402000-07-05 04:32:02 +0000288
David Turnerf0df85b2000-06-22 00:17:42 +0000289 n_points = 0;
Werner Lemberga929ba92000-06-25 06:47:11 +0000290 if ( n_contours > 0 )
291 n_points = cur[-1] + 1;
David Turnerd2b1f351999-12-16 23:11:37 +0000292
Werner Lemberga929ba92000-06-25 06:47:11 +0000293 error = FT_GlyphLoader_Check_Points( gloader, n_points + 2, 0 );
294 if ( error )
295 goto Fail;
Werner Lembergbd5ae402000-07-05 04:32:02 +0000296
David Turnerf0df85b2000-06-22 00:17:42 +0000297 outline = &gloader->current.outline;
298 }
299
Werner Lemberg78575dc2000-06-12 19:36:41 +0000300 /* reading the bytecode instructions */
David Turnerc3128612000-06-23 05:02:13 +0000301 slot->control_len = 0;
302 slot->control_data = 0;
Werner Lembergbd5ae402000-07-05 04:32:02 +0000303
David Turnerd2b1f351999-12-16 23:11:37 +0000304 n_ins = GET_UShort();
305
Werner Lemberg1c0d4ac2000-06-06 20:41:48 +0000306 FT_TRACE5(( " Instructions size: %d\n", n_ins ));
David Turnerd2b1f351999-12-16 23:11:37 +0000307
308 if ( n_ins > face->max_profile.maxSizeOfInstructions )
309 {
310 FT_TRACE0(( "ERROR: Too many instructions!\n" ));
311 error = TT_Err_Too_Many_Ins;
312 goto Fail;
313 }
314
Werner Lemberg78575dc2000-06-12 19:36:41 +0000315 if ( stream->cursor + n_ins > stream->limit )
David Turnerd2b1f351999-12-16 23:11:37 +0000316 {
317 FT_TRACE0(( "ERROR: Instruction count mismatch!\n" ));
318 error = TT_Err_Too_Many_Ins;
319 goto Fail;
320 }
David Turnerd2b1f351999-12-16 23:11:37 +0000321
David Turner8f43c712000-02-02 12:16:19 +0000322#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
Werner Lemberga929ba92000-06-25 06:47:11 +0000323
324 if ( ( load->load_flags &
David Turnerc3128612000-06-23 05:02:13 +0000325 ( FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING ) ) == 0 &&
326 load->instructions )
David Turner08fdac92000-02-21 16:01:33 +0000327 {
David Turnerc3128612000-06-23 05:02:13 +0000328 slot->control_len = n_ins;
329 slot->control_data = load->instructions;
Werner Lembergbd5ae402000-07-05 04:32:02 +0000330
David Turnerc3128612000-06-23 05:02:13 +0000331 MEM_Copy( load->instructions, stream->cursor, n_ins );
David Turner08fdac92000-02-21 16:01:33 +0000332 }
Werner Lemberga929ba92000-06-25 06:47:11 +0000333
Werner Lemberg78575dc2000-06-12 19:36:41 +0000334#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
David Turnerd2b1f351999-12-16 23:11:37 +0000335
David Turner8f43c712000-02-02 12:16:19 +0000336 stream->cursor += n_ins;
David Turnere49ab252000-05-16 23:44:38 +0000337
Werner Lemberg78575dc2000-06-12 19:36:41 +0000338 /* reading the point tags */
David Turnerd2b1f351999-12-16 23:11:37 +0000339
David Turnere49ab252000-05-16 23:44:38 +0000340 {
David Turnerf0df85b2000-06-22 00:17:42 +0000341 FT_Byte* flag = (FT_Byte*)outline->tags;
David Turnerf9b8dec2000-06-16 19:34:52 +0000342 FT_Byte* limit = flag + n_points;
343 FT_Byte c, count;
David Turnere49ab252000-05-16 23:44:38 +0000344
Werner Lemberga929ba92000-06-25 06:47:11 +0000345
Werner Lemberg78575dc2000-06-12 19:36:41 +0000346 for ( ; flag < limit; flag++ )
David Turnerd2b1f351999-12-16 23:11:37 +0000347 {
David Turner8f43c712000-02-02 12:16:19 +0000348 *flag = c = GET_Byte();
349 if ( c & 8 )
David Turnerd2b1f351999-12-16 23:11:37 +0000350 {
David Turner8f43c712000-02-02 12:16:19 +0000351 for ( count = GET_Byte(); count > 0; count-- )
352 *++flag = c;
David Turnerd2b1f351999-12-16 23:11:37 +0000353 }
354 }
355 }
356
Werner Lemberg78575dc2000-06-12 19:36:41 +0000357 /* reading the X coordinates */
David Turnere49ab252000-05-16 23:44:38 +0000358
David Turnerd2b1f351999-12-16 23:11:37 +0000359 {
David Turnerf0df85b2000-06-22 00:17:42 +0000360 FT_Vector* vec = outline->points;
David Turnerf9b8dec2000-06-16 19:34:52 +0000361 FT_Vector* limit = vec + n_points;
David Turnerf0df85b2000-06-22 00:17:42 +0000362 FT_Byte* flag = (FT_Byte*)outline->tags;
David Turnerf9b8dec2000-06-16 19:34:52 +0000363 FT_Pos x = 0;
David Turnere49ab252000-05-16 23:44:38 +0000364
Werner Lemberg78575dc2000-06-12 19:36:41 +0000365
David Turner8f43c712000-02-02 12:16:19 +0000366 for ( ; vec < limit; vec++, flag++ )
David Turnerd2b1f351999-12-16 23:11:37 +0000367 {
David Turnerf9b8dec2000-06-16 19:34:52 +0000368 FT_Pos y = 0;
David Turnere49ab252000-05-16 23:44:38 +0000369
Werner Lemberg78575dc2000-06-12 19:36:41 +0000370
David Turner8f43c712000-02-02 12:16:19 +0000371 if ( *flag & 2 )
372 {
373 y = GET_Byte();
Werner Lemberg78575dc2000-06-12 19:36:41 +0000374 if ( ( *flag & 16 ) == 0 )
375 y = -y;
David Turner8f43c712000-02-02 12:16:19 +0000376 }
Werner Lemberg78575dc2000-06-12 19:36:41 +0000377 else if ( ( *flag & 16 ) == 0 )
David Turner8f43c712000-02-02 12:16:19 +0000378 y = GET_Short();
David Turnere49ab252000-05-16 23:44:38 +0000379
David Turner8f43c712000-02-02 12:16:19 +0000380 x += y;
381 vec->x = x;
David Turnerd2b1f351999-12-16 23:11:37 +0000382 }
David Turnerd2b1f351999-12-16 23:11:37 +0000383 }
384
Werner Lemberg78575dc2000-06-12 19:36:41 +0000385 /* reading the Y coordinates */
David Turnerd2b1f351999-12-16 23:11:37 +0000386
David Turnerd2b1f351999-12-16 23:11:37 +0000387 {
David Turnerf0df85b2000-06-22 00:17:42 +0000388 FT_Vector* vec = gloader->current.outline.points;
David Turnerf9b8dec2000-06-16 19:34:52 +0000389 FT_Vector* limit = vec + n_points;
David Turnerf0df85b2000-06-22 00:17:42 +0000390 FT_Byte* flag = (FT_Byte*)outline->tags;
David Turnerf9b8dec2000-06-16 19:34:52 +0000391 FT_Pos x = 0;
David Turnere49ab252000-05-16 23:44:38 +0000392
Werner Lemberg78575dc2000-06-12 19:36:41 +0000393
David Turner8f43c712000-02-02 12:16:19 +0000394 for ( ; vec < limit; vec++, flag++ )
David Turnerd2b1f351999-12-16 23:11:37 +0000395 {
David Turnerf9b8dec2000-06-16 19:34:52 +0000396 FT_Pos y = 0;
David Turnere49ab252000-05-16 23:44:38 +0000397
Werner Lemberg78575dc2000-06-12 19:36:41 +0000398
David Turner8f43c712000-02-02 12:16:19 +0000399 if ( *flag & 4 )
400 {
401 y = GET_Byte();
Werner Lemberg78575dc2000-06-12 19:36:41 +0000402 if ( ( *flag & 32 ) == 0 )
403 y = -y;
David Turner8f43c712000-02-02 12:16:19 +0000404 }
Werner Lemberg78575dc2000-06-12 19:36:41 +0000405 else if ( ( *flag & 32 ) == 0 )
David Turner8f43c712000-02-02 12:16:19 +0000406 y = GET_Short();
David Turnere49ab252000-05-16 23:44:38 +0000407
David Turner8f43c712000-02-02 12:16:19 +0000408 x += y;
409 vec->y = x;
David Turnerd2b1f351999-12-16 23:11:37 +0000410 }
David Turnerd2b1f351999-12-16 23:11:37 +0000411 }
412
David Turnerc3128612000-06-23 05:02:13 +0000413 /* clear the touch tags */
414 for ( n = 0; n < n_points; n++ )
415 outline->tags[n] &= FT_Curve_Tag_On;
416
417 outline->n_points = n_points;
418 outline->n_contours = n_contours;
David Turnerc3128612000-06-23 05:02:13 +0000419
Werner Lembergbd5ae402000-07-05 04:32:02 +0000420 Fail:
David Turnerc3128612000-06-23 05:02:13 +0000421 return error;
422 }
423
424
David Turner76a5f622000-11-04 01:55:49 +0000425 FT_CALLBACK_DEF
David Turner994d7742000-06-25 04:49:19 +0000426 FT_Error TT_Load_Composite_Glyph( TT_Loader* loader )
David Turner90f68b72000-06-23 12:26:14 +0000427 {
428 FT_Error error;
Werner Lembergdcd2e142000-06-25 07:43:15 +0000429 FT_Stream stream = loader->stream;
430 FT_GlyphLoader* gloader = loader->gloader;
David Turner90f68b72000-06-23 12:26:14 +0000431 FT_SubGlyph* subglyph;
432 FT_UInt num_subglyphs;
433
Werner Lemberga929ba92000-06-25 06:47:11 +0000434
David Turner90f68b72000-06-23 12:26:14 +0000435 num_subglyphs = 0;
Werner Lemberga929ba92000-06-25 06:47:11 +0000436
David Turner90f68b72000-06-23 12:26:14 +0000437 do
438 {
439 FT_Fixed xx, xy, yy, yx;
440
Werner Lemberga929ba92000-06-25 06:47:11 +0000441
David Turner90f68b72000-06-23 12:26:14 +0000442 /* check that we can load a new subglyph */
Werner Lembergdcd2e142000-06-25 07:43:15 +0000443 error = FT_GlyphLoader_Check_Subglyphs( gloader, num_subglyphs + 1 );
Werner Lemberga929ba92000-06-25 06:47:11 +0000444 if ( error )
445 goto Fail;
Werner Lembergbd5ae402000-07-05 04:32:02 +0000446
David Turner90f68b72000-06-23 12:26:14 +0000447 subglyph = gloader->current.subglyphs + num_subglyphs;
448
449 subglyph->arg1 = subglyph->arg2 = 0;
450
451 subglyph->flags = GET_UShort();
452 subglyph->index = GET_UShort();
453
454 /* read arguments */
455 if ( subglyph->flags & ARGS_ARE_WORDS )
456 {
457 subglyph->arg1 = GET_Short();
458 subglyph->arg2 = GET_Short();
459 }
460 else
461 {
462 subglyph->arg1 = GET_Char();
463 subglyph->arg2 = GET_Char();
464 }
465
466 /* read transform */
467 xx = yy = 0x10000L;
468 xy = yx = 0;
469
470 if ( subglyph->flags & WE_HAVE_A_SCALE )
471 {
472 xx = (FT_Fixed)GET_Short() << 2;
473 yy = xx;
474 }
475 else if ( subglyph->flags & WE_HAVE_AN_XY_SCALE )
476 {
477 xx = (FT_Fixed)GET_Short() << 2;
478 yy = (FT_Fixed)GET_Short() << 2;
479 }
480 else if ( subglyph->flags & WE_HAVE_A_2X2 )
481 {
482 xx = (FT_Fixed)GET_Short() << 2;
483 xy = (FT_Fixed)GET_Short() << 2;
484 yx = (FT_Fixed)GET_Short() << 2;
485 yy = (FT_Fixed)GET_Short() << 2;
486 }
487
488 subglyph->transform.xx = xx;
489 subglyph->transform.xy = xy;
490 subglyph->transform.yx = yx;
491 subglyph->transform.yy = yy;
492
493 num_subglyphs++;
Werner Lemberg5811c7c2000-07-02 13:53:16 +0000494
Werner Lembergdcd2e142000-06-25 07:43:15 +0000495 } while ( subglyph->flags & MORE_COMPONENTS );
David Turner90f68b72000-06-23 12:26:14 +0000496
497 gloader->current.num_subglyphs = num_subglyphs;
498
499#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
500 {
501 /* we must undo the ACCESS_Frame in order to point to the */
502 /* composite instructions, if we find some. */
503 /* we will process them later... */
504 /* */
505 loader->ins_pos = FILE_Pos() + stream->cursor - stream->limit;
506 }
507#endif
508
509 Fail:
510 return error;
511 }
512
David Turnerc3128612000-06-23 05:02:13 +0000513
David Turner76a5f622000-11-04 01:55:49 +0000514 FT_LOCAL_DEF
David Turner994d7742000-06-25 04:49:19 +0000515 void TT_Init_Glyph_Loading( TT_Face face )
516 {
517 face->access_glyph_frame = TT_Access_Glyph_Frame;
518 face->read_glyph_header = TT_Load_Glyph_Header;
519 face->read_simple_glyph = TT_Load_Simple_Glyph;
520 face->read_composite_glyph = TT_Load_Composite_Glyph;
521 face->forget_glyph_frame = TT_Forget_Glyph_Frame;
522 }
523
David Turnerc3128612000-06-23 05:02:13 +0000524
525 /*************************************************************************/
526 /* */
527 /* <Function> */
528 /* TT_Process_Simple_Glyph */
529 /* */
530 /* <Description> */
531 /* Once a simple glyph has been loaded, it needs to be processed. */
532 /* Usually, this means scaling and hinting through bytecode */
Werner Lemberga929ba92000-06-25 06:47:11 +0000533 /* interpretation. */
David Turnerc3128612000-06-23 05:02:13 +0000534 /* */
535 static
Werner Lemberga929ba92000-06-25 06:47:11 +0000536 FT_Error TT_Process_Simple_Glyph( TT_Loader* load,
537 FT_Bool debug )
David Turnerc3128612000-06-23 05:02:13 +0000538 {
539 FT_GlyphLoader* gloader = load->gloader;
540 FT_Outline* outline = &gloader->current.outline;
541 FT_UInt n_points = outline->n_points;
542 FT_UInt n_ins;
543 TT_GlyphZone* zone = &load->zone;
544 FT_Error error = FT_Err_Ok;
545
Werner Lemberg58b17f92000-07-27 23:29:08 +0000546 FT_UNUSED( debug ); /* used by truetype interpreter only */
Werner Lemberga929ba92000-06-25 06:47:11 +0000547
Werner Lemberge4b32a52000-10-31 20:42:18 +0000548
David Turnerc3128612000-06-23 05:02:13 +0000549 n_ins = load->glyph->control_len;
550
Werner Lemberg78575dc2000-06-12 19:36:41 +0000551 /* add shadow points */
David Turnere49ab252000-05-16 23:44:38 +0000552
David Turnerd2b1f351999-12-16 23:11:37 +0000553 /* Now add the two shadow points at n and n + 1. */
554 /* We need the left side bearing and advance width. */
555
David Turner8f43c712000-02-02 12:16:19 +0000556 {
David Turnerf9b8dec2000-06-16 19:34:52 +0000557 FT_Vector* pp1;
558 FT_Vector* pp2;
David Turnere49ab252000-05-16 23:44:38 +0000559
Werner Lemberga929ba92000-06-25 06:47:11 +0000560
David Turner8f43c712000-02-02 12:16:19 +0000561 /* pp1 = xMin - lsb */
David Turnerf0df85b2000-06-22 00:17:42 +0000562 pp1 = outline->points + n_points;
David Turner8f43c712000-02-02 12:16:19 +0000563 pp1->x = load->bbox.xMin - load->left_bearing;
564 pp1->y = 0;
David Turnere49ab252000-05-16 23:44:38 +0000565
David Turner8f43c712000-02-02 12:16:19 +0000566 /* pp2 = pp1 + aw */
567 pp2 = pp1 + 1;
568 pp2->x = pp1->x + load->advance;
569 pp2->y = 0;
David Turnere49ab252000-05-16 23:44:38 +0000570
David Turnerf0df85b2000-06-22 00:17:42 +0000571 outline->tags[n_points ] = 0;
572 outline->tags[n_points + 1] = 0;
David Turner8f43c712000-02-02 12:16:19 +0000573 }
Werner Lemberg78575dc2000-06-12 19:36:41 +0000574
David Turnerd2b1f351999-12-16 23:11:37 +0000575 /* Note that we return two more points that are not */
576 /* part of the glyph outline. */
577
Werner Lembergdcd2e142000-06-25 07:43:15 +0000578 n_points += 2;
David Turnerd2b1f351999-12-16 23:11:37 +0000579
David Turnerf0df85b2000-06-22 00:17:42 +0000580 /* set up zone for hinting */
581 tt_prepare_zone( zone, &gloader->current, 0, 0 );
David Turnerd2b1f351999-12-16 23:11:37 +0000582
David Turnerf0df85b2000-06-22 00:17:42 +0000583 /* eventually scale the glyph */
Werner Lemberga929ba92000-06-25 06:47:11 +0000584 if ( !( load->load_flags & FT_LOAD_NO_SCALE ) )
David Turnerd2b1f351999-12-16 23:11:37 +0000585 {
David Turnerf0df85b2000-06-22 00:17:42 +0000586 FT_Vector* vec = zone->cur;
587 FT_Vector* limit = vec + n_points;
David Turnerc3128612000-06-23 05:02:13 +0000588 FT_Fixed x_scale = load->size->metrics.x_scale;
589 FT_Fixed y_scale = load->size->metrics.y_scale;
David Turner8f43c712000-02-02 12:16:19 +0000590
Werner Lemberg5811c7c2000-07-02 13:53:16 +0000591
David Turnerd2b1f351999-12-16 23:11:37 +0000592 /* first scale the glyph points */
Werner Lemberg78575dc2000-06-12 19:36:41 +0000593 for ( ; vec < limit; vec++ )
David Turnerd2b1f351999-12-16 23:11:37 +0000594 {
David Turner8f43c712000-02-02 12:16:19 +0000595 vec->x = FT_MulFix( vec->x, x_scale );
596 vec->y = FT_MulFix( vec->y, y_scale );
David Turnerd2b1f351999-12-16 23:11:37 +0000597 }
David Turnerf0df85b2000-06-22 00:17:42 +0000598 }
David Turnerd2b1f351999-12-16 23:11:37 +0000599
David Turnerf0df85b2000-06-22 00:17:42 +0000600 cur_to_org( n_points, zone );
Werner Lemberg78575dc2000-06-12 19:36:41 +0000601
David Turnerf0df85b2000-06-22 00:17:42 +0000602 /* eventually hint the glyph */
Werner Lemberga929ba92000-06-25 06:47:11 +0000603 if ( IS_HINTED( load->load_flags ) )
David Turnerf0df85b2000-06-22 00:17:42 +0000604 {
605 FT_Pos x = zone->org[n_points-2].x;
Werner Lemberg78575dc2000-06-12 19:36:41 +0000606
Werner Lemberga929ba92000-06-25 06:47:11 +0000607
David Turnerf0df85b2000-06-22 00:17:42 +0000608 x = ( ( x + 32 ) & -64 ) - x;
609 translate_array( n_points, zone->org, x, 0 );
David Turnerd2b1f351999-12-16 23:11:37 +0000610
David Turnerf0df85b2000-06-22 00:17:42 +0000611 org_to_cur( n_points, zone );
David Turnerd2b1f351999-12-16 23:11:37 +0000612
David Turnerf0df85b2000-06-22 00:17:42 +0000613 zone->cur[n_points - 1].x = ( zone->cur[n_points - 1].x + 32 ) & -64;
David Turnerd2b1f351999-12-16 23:11:37 +0000614
David Turner8f43c712000-02-02 12:16:19 +0000615#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
Werner Lemberga929ba92000-06-25 06:47:11 +0000616
David Turnerf0df85b2000-06-22 00:17:42 +0000617 /* now consider hinting */
618 if ( n_ins > 0 )
619 {
David Turnerc3128612000-06-23 05:02:13 +0000620 error = TT_Set_CodeRange( load->exec, tt_coderange_glyph,
621 load->exec->glyphIns, n_ins );
Werner Lemberga929ba92000-06-25 06:47:11 +0000622 if ( error )
623 goto Exit;
Werner Lembergbd5ae402000-07-05 04:32:02 +0000624
David Turnerf0df85b2000-06-22 00:17:42 +0000625 load->exec->is_composite = FALSE;
Werner Lemberga929ba92000-06-25 06:47:11 +0000626 load->exec->pedantic_hinting = (FT_Bool)( load->load_flags &
627 FT_LOAD_PEDANTIC );
David Turnerf0df85b2000-06-22 00:17:42 +0000628 load->exec->pts = *zone;
629 load->exec->pts.n_points += 2;
David Turnerd2b1f351999-12-16 23:11:37 +0000630
David Turnerf0df85b2000-06-22 00:17:42 +0000631 error = TT_Run_Context( load->exec, debug );
632 if ( error && load->exec->pedantic_hinting )
David Turnerc3128612000-06-23 05:02:13 +0000633 goto Exit;
Werner Lembergbd5ae402000-07-05 04:32:02 +0000634
David Turnerc3128612000-06-23 05:02:13 +0000635 error = FT_Err_Ok; /* ignore bytecode errors in non-pedantic mode */
David Turnerd2b1f351999-12-16 23:11:37 +0000636 }
Werner Lemberga929ba92000-06-25 06:47:11 +0000637
David Turnerf0df85b2000-06-22 00:17:42 +0000638#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
Werner Lemberga929ba92000-06-25 06:47:11 +0000639
David Turnerd2b1f351999-12-16 23:11:37 +0000640 }
641
642 /* save glyph phantom points */
David Turner8f43c712000-02-02 12:16:19 +0000643 if ( !load->preserve_pps )
David Turnerd2b1f351999-12-16 23:11:37 +0000644 {
David Turner8f43c712000-02-02 12:16:19 +0000645 load->pp1 = zone->cur[n_points - 2];
646 load->pp2 = zone->cur[n_points - 1];
David Turnerd2b1f351999-12-16 23:11:37 +0000647 }
648
David Turner5fe4c002000-07-26 19:04:08 +0000649#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
David Turnerc3128612000-06-23 05:02:13 +0000650 Exit:
Werner Lemberge4b32a52000-10-31 20:42:18 +0000651#endif
David Turnerd2b1f351999-12-16 23:11:37 +0000652 return error;
653 }
654
655
656 /*************************************************************************/
657 /* */
658 /* <Function> */
David Turner8f43c712000-02-02 12:16:19 +0000659 /* load_truetype_glyph */
David Turnerd2b1f351999-12-16 23:11:37 +0000660 /* */
661 /* <Description> */
Werner Lemberg78575dc2000-06-12 19:36:41 +0000662 /* Loads a given truetype glyph. Handles composites and uses a */
663 /* TT_Loader object. */
David Turnerd2b1f351999-12-16 23:11:37 +0000664 /* */
665 static
David Turnerf9b8dec2000-06-16 19:34:52 +0000666 FT_Error load_truetype_glyph( TT_Loader* loader,
667 FT_UInt glyph_index )
David Turnerd2b1f351999-12-16 23:11:37 +0000668 {
Werner Lemberg321cd272000-07-27 11:20:20 +0000669
670#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
David Turnerf0df85b2000-06-22 00:17:42 +0000671 FT_Stream stream = loader->stream;
Werner Lemberg321cd272000-07-27 11:20:20 +0000672#endif
673
David Turnerf0df85b2000-06-22 00:17:42 +0000674 FT_Error error;
David Turnerc3128612000-06-23 05:02:13 +0000675 TT_Face face = (TT_Face)loader->face;
David Turnerf0df85b2000-06-22 00:17:42 +0000676 FT_ULong offset;
David Turnerc3128612000-06-23 05:02:13 +0000677 FT_Int contours_count;
David Turnerf0df85b2000-06-22 00:17:42 +0000678 FT_UInt index, num_points, num_contours, count;
679 FT_Fixed x_scale, y_scale;
680 FT_ULong ins_offset;
681 FT_GlyphLoader* gloader = loader->gloader;
David Turner90f68b72000-06-23 12:26:14 +0000682 FT_Bool opened_frame = 0;
David Turnere49ab252000-05-16 23:44:38 +0000683
Werner Lemberg58b17f92000-07-27 23:29:08 +0000684
David Turner8f43c712000-02-02 12:16:19 +0000685 /* check glyph index */
David Turnered7f62a2000-03-28 11:19:28 +0000686 index = glyph_index;
David Turnerf9b8dec2000-06-16 19:34:52 +0000687 if ( index >= (FT_UInt)face->root.num_glyphs )
David Turnerd2b1f351999-12-16 23:11:37 +0000688 {
David Turner8f43c712000-02-02 12:16:19 +0000689 error = TT_Err_Invalid_Glyph_Index;
David Turner90f68b72000-06-23 12:26:14 +0000690 goto Exit;
David Turnerd2b1f351999-12-16 23:11:37 +0000691 }
692
David Turner861ba622000-02-15 12:54:51 +0000693 loader->glyph_index = glyph_index;
David Turnerd2b1f351999-12-16 23:11:37 +0000694 num_contours = 0;
David Turner8f43c712000-02-02 12:16:19 +0000695 num_points = 0;
696 ins_offset = 0;
David Turnere49ab252000-05-16 23:44:38 +0000697
Werner Lemberg78575dc2000-06-12 19:36:41 +0000698 x_scale = 0x10000L;
699 y_scale = 0x10000L;
700 if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
David Turnerd2b1f351999-12-16 23:11:37 +0000701 {
David Turnerc3128612000-06-23 05:02:13 +0000702 x_scale = loader->size->metrics.x_scale;
703 y_scale = loader->size->metrics.y_scale;
David Turner8f43c712000-02-02 12:16:19 +0000704 }
David Turnerd2b1f351999-12-16 23:11:37 +0000705
David Turner8f43c712000-02-02 12:16:19 +0000706 /* get horizontal metrics */
707 {
David Turnerf9b8dec2000-06-16 19:34:52 +0000708 FT_Short left_bearing;
709 FT_UShort advance_width;
David Turnerd2b1f351999-12-16 23:11:37 +0000710
Werner Lemberg78575dc2000-06-12 19:36:41 +0000711
David Turner71ec10e2000-02-10 16:09:35 +0000712 Get_HMetrics( face, index,
David Turnerf9b8dec2000-06-16 19:34:52 +0000713 (FT_Bool)!(loader->load_flags &
Werner Lembergdcd2e142000-06-25 07:43:15 +0000714 FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH),
David Turner8f43c712000-02-02 12:16:19 +0000715 &left_bearing,
716 &advance_width );
David Turnerd2b1f351999-12-16 23:11:37 +0000717
David Turner8f43c712000-02-02 12:16:19 +0000718 loader->left_bearing = left_bearing;
719 loader->advance = advance_width;
720 }
David Turnerd2b1f351999-12-16 23:11:37 +0000721
David Turner8f43c712000-02-02 12:16:19 +0000722 offset = face->glyph_locations[index];
723 count = 0;
David Turnere49ab252000-05-16 23:44:38 +0000724
David Turnerf9b8dec2000-06-16 19:34:52 +0000725 if ( index < (FT_UInt)face->num_locations - 1 )
Werner Lemberg78575dc2000-06-12 19:36:41 +0000726 count = face->glyph_locations[index + 1] - offset;
David Turnerd2b1f351999-12-16 23:11:37 +0000727
Werner Lemberg78575dc2000-06-12 19:36:41 +0000728 if ( count == 0 )
David Turner8f43c712000-02-02 12:16:19 +0000729 {
730 /* as described by Frederic Loyer, these are spaces, and */
731 /* not the unknown glyph. */
732 loader->bbox.xMin = 0;
733 loader->bbox.xMax = 0;
734 loader->bbox.yMin = 0;
735 loader->bbox.yMax = 0;
David Turnerd2b1f351999-12-16 23:11:37 +0000736
David Turner8f43c712000-02-02 12:16:19 +0000737 loader->pp1.x = 0;
738 loader->pp2.x = loader->advance;
David Turnerd2b1f351999-12-16 23:11:37 +0000739
Werner Lemberg78575dc2000-06-12 19:36:41 +0000740 if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
David Turner8f43c712000-02-02 12:16:19 +0000741 loader->pp2.x = FT_MulFix( loader->pp2.x, x_scale );
David Turnerd2b1f351999-12-16 23:11:37 +0000742
David Turner8f43c712000-02-02 12:16:19 +0000743#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
Werner Lembergdcd2e142000-06-25 07:43:15 +0000744
Werner Lemberg78575dc2000-06-12 19:36:41 +0000745 if ( loader->exec )
David Turner7bb7fed2000-02-28 11:23:36 +0000746 loader->exec->glyphSize = 0;
Werner Lembergdcd2e142000-06-25 07:43:15 +0000747
David Turner8f43c712000-02-02 12:16:19 +0000748#endif
Werner Lemberg5811c7c2000-07-02 13:53:16 +0000749
David Turner90f68b72000-06-23 12:26:14 +0000750 error = FT_Err_Ok;
751 goto Exit;
David Turner8f43c712000-02-02 12:16:19 +0000752 }
David Turnerd2b1f351999-12-16 23:11:37 +0000753
David Turner8f43c712000-02-02 12:16:19 +0000754 offset = loader->glyf_offset + offset;
David Turnerd2b1f351999-12-16 23:11:37 +0000755
David Turner90f68b72000-06-23 12:26:14 +0000756 /* access glyph frame */
David Turner994d7742000-06-25 04:49:19 +0000757 error = face->access_glyph_frame( loader, glyph_index, offset, count );
Werner Lemberga929ba92000-06-25 06:47:11 +0000758 if ( error )
759 goto Exit;
David Turner90f68b72000-06-23 12:26:14 +0000760
761 opened_frame = 1;
762
David Turner8f43c712000-02-02 12:16:19 +0000763 /* read first glyph header */
David Turner994d7742000-06-25 04:49:19 +0000764 error = face->read_glyph_header( loader );
Werner Lemberga929ba92000-06-25 06:47:11 +0000765 if ( error )
766 goto Fail;
David Turnerd2b1f351999-12-16 23:11:37 +0000767
David Turner90f68b72000-06-23 12:26:14 +0000768 contours_count = loader->n_contours;
David Turnerd2b1f351999-12-16 23:11:37 +0000769
David Turner8f43c712000-02-02 12:16:19 +0000770 count -= 10;
David Turnerd2b1f351999-12-16 23:11:37 +0000771
David Turner8f43c712000-02-02 12:16:19 +0000772 loader->pp1.x = loader->bbox.xMin - loader->left_bearing;
773 loader->pp1.y = 0;
774 loader->pp2.x = loader->pp1.x + loader->advance;
775 loader->pp2.y = 0;
David Turnere49ab252000-05-16 23:44:38 +0000776
Werner Lemberg78575dc2000-06-12 19:36:41 +0000777 if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
David Turner8f43c712000-02-02 12:16:19 +0000778 {
779 loader->pp1.x = FT_MulFix( loader->pp1.x, x_scale );
780 loader->pp2.x = FT_MulFix( loader->pp2.x, x_scale );
781 }
David Turnerd2b1f351999-12-16 23:11:37 +0000782
Werner Lemberg78575dc2000-06-12 19:36:41 +0000783 /***********************************************************************/
784 /***********************************************************************/
785 /***********************************************************************/
David Turnerd2b1f351999-12-16 23:11:37 +0000786
Werner Lemberg78575dc2000-06-12 19:36:41 +0000787 /* if it is a simple glyph, load it */
788
789 if ( contours_count >= 0 )
David Turner8f43c712000-02-02 12:16:19 +0000790 {
David Turnerf0df85b2000-06-22 00:17:42 +0000791 /* check that we can add the contours to the glyph */
792 error = FT_GlyphLoader_Check_Points( gloader, 0, contours_count );
Werner Lemberga929ba92000-06-25 06:47:11 +0000793 if ( error )
794 goto Fail;
Werner Lemberg78575dc2000-06-12 19:36:41 +0000795
David Turner994d7742000-06-25 04:49:19 +0000796 error = face->read_simple_glyph( loader );
Werner Lemberga929ba92000-06-25 06:47:11 +0000797 if ( error )
798 goto Fail;
Werner Lembergbd5ae402000-07-05 04:32:02 +0000799
David Turner8f43c712000-02-02 12:16:19 +0000800#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
Werner Lemberg5811c7c2000-07-02 13:53:16 +0000801
David Turnerc3128612000-06-23 05:02:13 +0000802 {
803 TT_Size size = (TT_Size)loader->size;
Werner Lembergdcd2e142000-06-25 07:43:15 +0000804
805
David Turnerc3128612000-06-23 05:02:13 +0000806 error = TT_Process_Simple_Glyph( loader,
807 (FT_Bool)( size && size->debug ) );
808 }
Werner Lembergdcd2e142000-06-25 07:43:15 +0000809
David Turner8f43c712000-02-02 12:16:19 +0000810#else
Werner Lembergdcd2e142000-06-25 07:43:15 +0000811
David Turner5fe4c002000-07-26 19:04:08 +0000812 error = TT_Process_Simple_Glyph( loader, 0 );
Werner Lembergdcd2e142000-06-25 07:43:15 +0000813
David Turnere49ab252000-05-16 23:44:38 +0000814#endif
Werner Lembergdcd2e142000-06-25 07:43:15 +0000815
816 if ( error )
817 goto Fail;
David Turnerf0df85b2000-06-22 00:17:42 +0000818
819 FT_GlyphLoader_Add( gloader );
David Turnerd2b1f351999-12-16 23:11:37 +0000820
David Turner8f43c712000-02-02 12:16:19 +0000821 /* Note: We could have put the simple loader source there */
822 /* but the code is fat enough already :-) */
David Turner8f43c712000-02-02 12:16:19 +0000823 }
David Turner8f43c712000-02-02 12:16:19 +0000824
Werner Lemberg78575dc2000-06-12 19:36:41 +0000825 /***********************************************************************/
826 /***********************************************************************/
827 /***********************************************************************/
828
829 /* otherwise, load a composite! */
830 else
David Turner8f43c712000-02-02 12:16:19 +0000831 {
David Turnerc3128612000-06-23 05:02:13 +0000832 TT_GlyphSlot glyph = (TT_GlyphSlot)loader->glyph;
833 FT_UInt start_point, start_contour;
David Turnerc6a92202000-07-04 18:12:13 +0000834 FT_ULong ins_pos; /* position of composite instructions, if any */
Werner Lemberga929ba92000-06-25 06:47:11 +0000835
Werner Lembergbd5ae402000-07-05 04:32:02 +0000836
David Turner8f43c712000-02-02 12:16:19 +0000837 /* for each subglyph, read composite header */
David Turnerf0df85b2000-06-22 00:17:42 +0000838 start_point = gloader->base.outline.n_points;
839 start_contour = gloader->base.outline.n_contours;
Werner Lembergbd5ae402000-07-05 04:32:02 +0000840
David Turner994d7742000-06-25 04:49:19 +0000841 error = face->read_composite_glyph( loader );
Werner Lemberga929ba92000-06-25 06:47:11 +0000842 if ( error )
843 goto Fail;
David Turnered7f62a2000-03-28 11:19:28 +0000844
David Turnerc6a92202000-07-04 18:12:13 +0000845 ins_pos = loader->ins_pos;
David Turner994d7742000-06-25 04:49:19 +0000846 face->forget_glyph_frame( loader );
David Turner90f68b72000-06-23 12:26:14 +0000847 opened_frame = 0;
848
David Turnered7f62a2000-03-28 11:19:28 +0000849 /* if the flag FT_LOAD_NO_RECURSE is set, we return the subglyph */
Werner Lemberg78575dc2000-06-12 19:36:41 +0000850 /* `as is' in the glyph slot (the client application will be */
851 /* responsible for interpreting this data)... */
852 /* */
David Turnered7f62a2000-03-28 11:19:28 +0000853 if ( loader->load_flags & FT_LOAD_NO_RECURSE )
854 {
David Turnered7f62a2000-03-28 11:19:28 +0000855 /* set up remaining glyph fields */
David Turnerf0df85b2000-06-22 00:17:42 +0000856 FT_GlyphLoader_Add( gloader );
Werner Lembergbd5ae402000-07-05 04:32:02 +0000857
David Turnerf0df85b2000-06-22 00:17:42 +0000858 glyph->num_subglyphs = gloader->base.num_subglyphs;
David Turner3475e7f2000-05-17 20:56:01 +0000859 glyph->format = ft_glyph_format_composite;
David Turnerf0df85b2000-06-22 00:17:42 +0000860 glyph->subglyphs = gloader->base.subglyphs;
Werner Lembergbd5ae402000-07-05 04:32:02 +0000861
David Turner90f68b72000-06-23 12:26:14 +0000862 goto Exit;
David Turnered7f62a2000-03-28 11:19:28 +0000863 }
864
David Turner8f43c712000-02-02 12:16:19 +0000865 /*********************************************************************/
Werner Lembergdcd2e142000-06-25 07:43:15 +0000866 /*********************************************************************/
867 /*********************************************************************/
868
869 /* Now, read each subglyph independently. */
David Turner8f43c712000-02-02 12:16:19 +0000870 {
David Turnerc3128612000-06-23 05:02:13 +0000871 FT_Int n, num_base_points, num_new_points;
Werner Lembergdcd2e142000-06-25 07:43:15 +0000872 FT_SubGlyph* subglyph = 0;
Werner Lembergbd5ae402000-07-05 04:32:02 +0000873
David Turnerc3128612000-06-23 05:02:13 +0000874 FT_UInt num_subglyphs = gloader->current.num_subglyphs;
875 FT_UInt num_base_subgs = gloader->base.num_subglyphs;
Werner Lembergbd5ae402000-07-05 04:32:02 +0000876
David Turnerc3128612000-06-23 05:02:13 +0000877
David Turnerf0df85b2000-06-22 00:17:42 +0000878 FT_GlyphLoader_Add( gloader );
Werner Lembergbd5ae402000-07-05 04:32:02 +0000879
David Turner74abee82000-06-27 23:31:53 +0000880 for ( n = 0; n < (FT_Int)num_subglyphs; n++ )
David Turnerd2b1f351999-12-16 23:11:37 +0000881 {
David Turnerf9b8dec2000-06-16 19:34:52 +0000882 FT_Vector pp1, pp2;
883 FT_Pos x, y;
David Turnere49ab252000-05-16 23:44:38 +0000884
Werner Lembergdcd2e142000-06-25 07:43:15 +0000885
Werner Lemberga929ba92000-06-25 06:47:11 +0000886 /* Each time we call load_truetype_glyph in this loop, the */
887 /* value of `gloader.base.subglyphs' can change due to table */
888 /* reallocations. We thus need to recompute the subglyph */
889 /* pointer on each iteration. */
David Turnerf0df85b2000-06-22 00:17:42 +0000890 subglyph = gloader->base.subglyphs + num_base_subgs + n;
Werner Lemberg78575dc2000-06-12 19:36:41 +0000891
David Turner8f43c712000-02-02 12:16:19 +0000892 pp1 = loader->pp1;
893 pp2 = loader->pp2;
David Turnerd2b1f351999-12-16 23:11:37 +0000894
David Turnerf0df85b2000-06-22 00:17:42 +0000895 num_base_points = gloader->base.outline.n_points;
David Turnere49ab252000-05-16 23:44:38 +0000896
David Turner8f43c712000-02-02 12:16:19 +0000897 error = load_truetype_glyph( loader, subglyph->index );
Werner Lemberg78575dc2000-06-12 19:36:41 +0000898 if ( error )
899 goto Fail;
David Turner3475e7f2000-05-17 20:56:01 +0000900
David Turnerf0df85b2000-06-22 00:17:42 +0000901 subglyph = gloader->base.subglyphs + num_base_subgs + n;
902
David Turner7bb7fed2000-02-28 11:23:36 +0000903 if ( subglyph->flags & USE_MY_METRICS )
904 {
905 pp1 = loader->pp1;
906 pp2 = loader->pp2;
907 }
908 else
David Turnerd2b1f351999-12-16 23:11:37 +0000909 {
David Turner8f43c712000-02-02 12:16:19 +0000910 loader->pp1 = pp1;
911 loader->pp2 = pp2;
David Turnerd2b1f351999-12-16 23:11:37 +0000912 }
David Turnere49ab252000-05-16 23:44:38 +0000913
Werner Lembergdcd2e142000-06-25 07:43:15 +0000914 num_points = gloader->base.outline.n_points;
David Turnere49ab252000-05-16 23:44:38 +0000915
David Turner8f43c712000-02-02 12:16:19 +0000916 num_new_points = num_points - num_base_points;
David Turnere49ab252000-05-16 23:44:38 +0000917
David Turner8f43c712000-02-02 12:16:19 +0000918 /* now perform the transform required for this subglyph */
David Turnere49ab252000-05-16 23:44:38 +0000919
David Turner8f43c712000-02-02 12:16:19 +0000920 if ( subglyph->flags & ( WE_HAVE_A_SCALE |
921 WE_HAVE_AN_XY_SCALE |
922 WE_HAVE_A_2X2 ) )
David Turnerd2b1f351999-12-16 23:11:37 +0000923 {
Werner Lemberga929ba92000-06-25 06:47:11 +0000924 FT_Vector* cur = gloader->base.outline.points +
925 num_base_points;
926 FT_Vector* org = gloader->base.extra_points +
927 num_base_points;
David Turnerf9b8dec2000-06-16 19:34:52 +0000928 FT_Vector* limit = cur + num_new_points;
David Turnerd2b1f351999-12-16 23:11:37 +0000929
Werner Lembergdcd2e142000-06-25 07:43:15 +0000930
David Turner8f43c712000-02-02 12:16:19 +0000931 for ( ; cur < limit; cur++, org++ )
David Turnerd2b1f351999-12-16 23:11:37 +0000932 {
David Turnerf0df85b2000-06-22 00:17:42 +0000933 FT_Vector_Transform( cur, &subglyph->transform );
934 FT_Vector_Transform( org, &subglyph->transform );
David Turnerd2b1f351999-12-16 23:11:37 +0000935 }
936 }
937
David Turnerd2b1f351999-12-16 23:11:37 +0000938 /* apply offset */
939
Werner Lemberg78575dc2000-06-12 19:36:41 +0000940 if ( !( subglyph->flags & ARGS_ARE_XY_VALUES ) )
David Turnerd2b1f351999-12-16 23:11:37 +0000941 {
David Turner74abee82000-06-27 23:31:53 +0000942 FT_UInt k = subglyph->arg1;
David Turnerf0df85b2000-06-22 00:17:42 +0000943 FT_UInt l = subglyph->arg2;
944 FT_Vector* p1;
945 FT_Vector* p2;
David Turnerd2b1f351999-12-16 23:11:37 +0000946
Werner Lembergdeb4e982000-06-29 03:14:25 +0000947
David Turner74abee82000-06-27 23:31:53 +0000948 if ( start_point + k >= (FT_UInt)num_base_points ||
David Turnerf0df85b2000-06-22 00:17:42 +0000949 l >= (FT_UInt)num_new_points )
David Turnerd2b1f351999-12-16 23:11:37 +0000950 {
951 error = TT_Err_Invalid_Composite;
952 goto Fail;
953 }
954
David Turnere49ab252000-05-16 23:44:38 +0000955 l += num_base_points;
956
David Turnerf0df85b2000-06-22 00:17:42 +0000957 p1 = gloader->base.outline.points + start_point + k;
958 p2 = gloader->base.outline.points + start_point + l;
Werner Lembergbd5ae402000-07-05 04:32:02 +0000959
David Turnerf0df85b2000-06-22 00:17:42 +0000960 x = p1->x - p2->x;
961 y = p1->y - p2->y;
David Turnerd2b1f351999-12-16 23:11:37 +0000962 }
963 else
964 {
David Turner8f43c712000-02-02 12:16:19 +0000965 x = subglyph->arg1;
966 y = subglyph->arg2;
David Turnerd2b1f351999-12-16 23:11:37 +0000967
Werner Lemberg78575dc2000-06-12 19:36:41 +0000968 if ( !( loader->load_flags & FT_LOAD_NO_SCALE ) )
David Turnerd2b1f351999-12-16 23:11:37 +0000969 {
David Turner8f43c712000-02-02 12:16:19 +0000970 x = FT_MulFix( x, x_scale );
971 y = FT_MulFix( y, y_scale );
David Turnere49ab252000-05-16 23:44:38 +0000972
David Turner8f43c712000-02-02 12:16:19 +0000973 if ( subglyph->flags & ROUND_XY_TO_GRID )
Werner Lemberg78575dc2000-06-12 19:36:41 +0000974 {
975 x = ( x + 32 ) & -64;
976 y = ( y + 32 ) & -64;
977 }
David Turnerd2b1f351999-12-16 23:11:37 +0000978 }
979 }
980
David Turner8f43c712000-02-02 12:16:19 +0000981 translate_array( num_new_points, loader->zone.cur, x, y );
982 cur_to_org( num_new_points, &loader->zone );
David Turnerd2b1f351999-12-16 23:11:37 +0000983 }
David Turnere49ab252000-05-16 23:44:38 +0000984
Werner Lembergdcd2e142000-06-25 07:43:15 +0000985 /*******************************************************************/
986 /*******************************************************************/
987 /*******************************************************************/
David Turnerd2b1f351999-12-16 23:11:37 +0000988
Werner Lemberg5811c7c2000-07-02 13:53:16 +0000989 /* we have finished loading all sub-glyphs; now, look for */
Werner Lemberg78575dc2000-06-12 19:36:41 +0000990 /* instructions for this composite! */
David Turnerd2b1f351999-12-16 23:11:37 +0000991
David Turner8f43c712000-02-02 12:16:19 +0000992#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
Werner Lemberg78575dc2000-06-12 19:36:41 +0000993
Werner Lemberg78575dc2000-06-12 19:36:41 +0000994 if ( num_subglyphs > 0 &&
995 loader->exec &&
David Turnerc6a92202000-07-04 18:12:13 +0000996 ins_pos > 0 &&
Werner Lemberg78575dc2000-06-12 19:36:41 +0000997 subglyph->flags & WE_HAVE_INSTR )
David Turner8f43c712000-02-02 12:16:19 +0000998 {
David Turnerf9b8dec2000-06-16 19:34:52 +0000999 FT_UShort n_ins;
David Turner8f43c712000-02-02 12:16:19 +00001000 TT_ExecContext exec = loader->exec;
David Turnerf9b8dec2000-06-16 19:34:52 +00001001 TT_GlyphZone* pts;
1002 FT_Vector* pp1;
David Turnere49ab252000-05-16 23:44:38 +00001003
Werner Lemberg78575dc2000-06-12 19:36:41 +00001004
David Turner8f43c712000-02-02 12:16:19 +00001005 /* read size of instructions */
David Turnerc6a92202000-07-04 18:12:13 +00001006 if ( FILE_Seek( ins_pos ) ||
1007 READ_UShort( n_ins ) )
Werner Lemberg78575dc2000-06-12 19:36:41 +00001008 goto Fail;
Werner Lemberg1c0d4ac2000-06-06 20:41:48 +00001009 FT_TRACE5(( " Instructions size = %d\n", n_ins ));
David Turnere49ab252000-05-16 23:44:38 +00001010
Werner Lemberg5811c7c2000-07-02 13:53:16 +00001011 /* in some fonts? */
Werner Lemberga929ba92000-06-25 06:47:11 +00001012 if ( n_ins == 0xFFFF )
David Turnerc3128612000-06-23 05:02:13 +00001013 n_ins = 0;
1014
David Turner8f43c712000-02-02 12:16:19 +00001015 /* check it */
1016 if ( n_ins > face->max_profile.maxSizeOfInstructions )
1017 {
David Turnerc3128612000-06-23 05:02:13 +00001018 FT_TRACE0(( "Too many instructions (%d) in composite glyph %ld\n",
1019 n_ins, subglyph->index ));
David Turner8f43c712000-02-02 12:16:19 +00001020 return TT_Err_Too_Many_Ins;
1021 }
David Turnere49ab252000-05-16 23:44:38 +00001022
David Turner8f43c712000-02-02 12:16:19 +00001023 /* read the instructions */
1024 if ( FILE_Read( exec->glyphIns, n_ins ) )
1025 goto Fail;
David Turnere49ab252000-05-16 23:44:38 +00001026
David Turnerc3128612000-06-23 05:02:13 +00001027 glyph->control_data = exec->glyphIns;
1028 glyph->control_len = n_ins;
1029
David Turner8f43c712000-02-02 12:16:19 +00001030 error = TT_Set_CodeRange( exec,
1031 tt_coderange_glyph,
1032 exec->glyphIns,
1033 n_ins );
Werner Lemberg78575dc2000-06-12 19:36:41 +00001034 if ( error )
1035 goto Fail;
David Turnere49ab252000-05-16 23:44:38 +00001036
David Turner8f43c712000-02-02 12:16:19 +00001037 /* prepare the execution context */
Werner Lemberga929ba92000-06-25 06:47:11 +00001038 tt_prepare_zone( &exec->pts, &gloader->base,
1039 start_point, start_contour );
David Turnerf0df85b2000-06-22 00:17:42 +00001040 pts = &exec->pts;
David Turnere49ab252000-05-16 23:44:38 +00001041
David Turner8f43c712000-02-02 12:16:19 +00001042 pts->n_points = num_points + 2;
David Turner43a2f652000-07-05 18:23:38 +00001043 pts->n_contours = gloader->base.outline.n_contours;
David Turnere49ab252000-05-16 23:44:38 +00001044
David Turner8f43c712000-02-02 12:16:19 +00001045 /* add phantom points */
1046 pp1 = pts->cur + num_points;
1047 pp1[0] = loader->pp1;
1048 pp1[1] = loader->pp2;
David Turnere49ab252000-05-16 23:44:38 +00001049
Werner Lembergdeb4e982000-06-29 03:14:25 +00001050 pts->tags[num_points ] = 0;
David Turner41dbcbf2000-03-09 11:46:25 +00001051 pts->tags[num_points + 1] = 0;
David Turnere49ab252000-05-16 23:44:38 +00001052
David Turner8f43c712000-02-02 12:16:19 +00001053 /* if hinting, round the phantom points */
Werner Lemberg78575dc2000-06-12 19:36:41 +00001054 if ( IS_HINTED( loader->load_flags ) )
David Turner8f43c712000-02-02 12:16:19 +00001055 {
Werner Lemberg78575dc2000-06-12 19:36:41 +00001056 pp1[0].x = ( ( loader->pp1.x + 32 ) & -64 );
1057 pp1[1].x = ( ( loader->pp2.x + 32 ) & -64 );
David Turner8f43c712000-02-02 12:16:19 +00001058 }
David Turnere49ab252000-05-16 23:44:38 +00001059
David Turner8f43c712000-02-02 12:16:19 +00001060 {
David Turnerf9b8dec2000-06-16 19:34:52 +00001061 FT_UInt k;
Werner Lemberg78575dc2000-06-12 19:36:41 +00001062
1063
David Turner43a2f652000-07-05 18:23:38 +00001064 for ( k = 0; k < num_points; k++ )
David Turner41dbcbf2000-03-09 11:46:25 +00001065 pts->tags[k] &= FT_Curve_Tag_On;
David Turner8f43c712000-02-02 12:16:19 +00001066 }
David Turnere49ab252000-05-16 23:44:38 +00001067
Werner Lemberg7fa51b52000-07-08 19:51:42 +00001068 cur_to_org( num_points + 2, pts );
David Turnere49ab252000-05-16 23:44:38 +00001069
David Turner8f43c712000-02-02 12:16:19 +00001070 /* now consider hinting */
Werner Lembergdcd2e142000-06-25 07:43:15 +00001071 if ( IS_HINTED( loader->load_flags ) && n_ins > 0 )
David Turner8f43c712000-02-02 12:16:19 +00001072 {
1073 exec->is_composite = TRUE;
1074 exec->pedantic_hinting =
Werner Lembergdcd2e142000-06-25 07:43:15 +00001075 (FT_Bool)( loader->load_flags & FT_LOAD_PEDANTIC );
David Turnere49ab252000-05-16 23:44:38 +00001076
David Turnerc3128612000-06-23 05:02:13 +00001077 error = TT_Run_Context( exec, ((TT_Size)loader->size)->debug );
David Turner8f43c712000-02-02 12:16:19 +00001078 if ( error && exec->pedantic_hinting )
1079 goto Fail;
1080 }
David Turnere49ab252000-05-16 23:44:38 +00001081
David Turner8f43c712000-02-02 12:16:19 +00001082 /* save glyph origin and advance points */
1083 loader->pp1 = pp1[0];
1084 loader->pp2 = pp1[1];
1085 }
Werner Lembergdcd2e142000-06-25 07:43:15 +00001086
Werner Lemberg78575dc2000-06-12 19:36:41 +00001087#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
Werner Lembergdcd2e142000-06-25 07:43:15 +00001088
David Turnerd2b1f351999-12-16 23:11:37 +00001089 }
Werner Lemberg78575dc2000-06-12 19:36:41 +00001090 /* end of composite loading */
David Turnerd2b1f351999-12-16 23:11:37 +00001091 }
1092
Werner Lemberg78575dc2000-06-12 19:36:41 +00001093 /***********************************************************************/
1094 /***********************************************************************/
1095 /***********************************************************************/
David Turnerd2b1f351999-12-16 23:11:37 +00001096
David Turner8f43c712000-02-02 12:16:19 +00001097 Fail:
Werner Lemberga929ba92000-06-25 06:47:11 +00001098 if ( opened_frame )
David Turner994d7742000-06-25 04:49:19 +00001099 face->forget_glyph_frame( loader );
David Turner90f68b72000-06-23 12:26:14 +00001100
1101 Exit:
David Turnere49ab252000-05-16 23:44:38 +00001102 return error;
David Turner8f43c712000-02-02 12:16:19 +00001103 }
1104
1105
David Turner8f43c712000-02-02 12:16:19 +00001106 static
Werner Lemberg78575dc2000-06-12 19:36:41 +00001107 void compute_glyph_metrics( TT_Loader* loader,
David Turnerf9b8dec2000-06-16 19:34:52 +00001108 FT_UInt glyph_index )
David Turner8f43c712000-02-02 12:16:19 +00001109 {
David Turnerf9b8dec2000-06-16 19:34:52 +00001110 FT_BBox bbox;
David Turnerc3128612000-06-23 05:02:13 +00001111 TT_Face face = (TT_Face)loader->face;
David Turnerf9b8dec2000-06-16 19:34:52 +00001112 FT_Fixed x_scale, y_scale;
David Turner8f43c712000-02-02 12:16:19 +00001113 TT_GlyphSlot glyph = loader->glyph;
David Turnerc3128612000-06-23 05:02:13 +00001114 TT_Size size = (TT_Size)loader->size;
David Turnere49ab252000-05-16 23:44:38 +00001115
Werner Lembergdcd2e142000-06-25 07:43:15 +00001116
Werner Lemberg78575dc2000-06-12 19:36:41 +00001117 x_scale = 0x10000L;
1118 y_scale = 0x10000L;
1119 if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
David Turner8f43c712000-02-02 12:16:19 +00001120 {
1121 x_scale = size->root.metrics.x_scale;
1122 y_scale = size->root.metrics.y_scale;
1123 }
David Turnere49ab252000-05-16 23:44:38 +00001124
David Turnered7f62a2000-03-28 11:19:28 +00001125 if ( glyph->format != ft_glyph_format_composite )
David Turner8f43c712000-02-02 12:16:19 +00001126 {
David Turnerf0df85b2000-06-22 00:17:42 +00001127 glyph->outline.flags &= ~ft_outline_single_pass;
Werner Lemberg78575dc2000-06-12 19:36:41 +00001128
David Turnerf0df85b2000-06-22 00:17:42 +00001129 /* copy outline to our glyph slot */
David Turner54e75742000-11-04 02:52:02 +00001130 FT_GlyphLoader_Copy_Points( glyph->internal->loader, loader->gloader );
1131 glyph->outline = glyph->internal->loader->base.outline;
Werner Lembergbd5ae402000-07-05 04:32:02 +00001132
David Turnered7f62a2000-03-28 11:19:28 +00001133 /* translate array so that (0,0) is the glyph's origin */
David Turnerf0df85b2000-06-22 00:17:42 +00001134 FT_Outline_Translate( &glyph->outline, -loader->pp1.x, 0 );
David Turnere49ab252000-05-16 23:44:38 +00001135
David Turnered7f62a2000-03-28 11:19:28 +00001136 FT_Outline_Get_CBox( &glyph->outline, &bbox );
1137
Werner Lemberg78575dc2000-06-12 19:36:41 +00001138 if ( IS_HINTED( loader->load_flags ) )
David Turnered7f62a2000-03-28 11:19:28 +00001139 {
1140 /* grid-fit the bounding box */
1141 bbox.xMin &= -64;
1142 bbox.yMin &= -64;
Werner Lemberg78575dc2000-06-12 19:36:41 +00001143 bbox.xMax = ( bbox.xMax + 63 ) & -64;
1144 bbox.yMax = ( bbox.yMax + 63 ) & -64;
David Turnered7f62a2000-03-28 11:19:28 +00001145 }
David Turner8f43c712000-02-02 12:16:19 +00001146 }
David Turnered7f62a2000-03-28 11:19:28 +00001147 else
1148 bbox = loader->bbox;
David Turnerd2b1f351999-12-16 23:11:37 +00001149
Werner Lemberga929ba92000-06-25 06:47:11 +00001150 /* get the device-independent horizontal advance. It is scaled later */
1151 /* by the base layer. */
David Turnerd2b1f351999-12-16 23:11:37 +00001152 {
David Turnerf0df85b2000-06-22 00:17:42 +00001153 FT_Pos advance = loader->advance;
David Turnerd2b1f351999-12-16 23:11:37 +00001154
Werner Lemberga929ba92000-06-25 06:47:11 +00001155
Werner Lemberg5811c7c2000-07-02 13:53:16 +00001156 /* the flag FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH was introduced to */
1157 /* correctly support DynaLab fonts, which have an incorrect */
1158 /* `advance_Width_Max' field! It is used, to my knowledge, */
1159 /* exclusively in the X-TrueType font server. */
1160 /* */
Werner Lemberg78575dc2000-06-12 19:36:41 +00001161 if ( face->postscript.isFixedPitch &&
1162 ( loader->load_flags & FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ) == 0 )
David Turnerd2b1f351999-12-16 23:11:37 +00001163 advance = face->horizontal.advance_Width_Max;
1164
David Turnerf0df85b2000-06-22 00:17:42 +00001165 /* we need to return the advance in font units in linearHoriAdvance, */
Werner Lemberga929ba92000-06-25 06:47:11 +00001166 /* it will be scaled later by the base layer. */
David Turnerf0df85b2000-06-22 00:17:42 +00001167 glyph->linearHoriAdvance = advance;
David Turnerd2b1f351999-12-16 23:11:37 +00001168 }
1169
1170 glyph->metrics.horiBearingX = bbox.xMin;
1171 glyph->metrics.horiBearingY = bbox.yMax;
David Turner8f43c712000-02-02 12:16:19 +00001172 glyph->metrics.horiAdvance = loader->pp2.x - loader->pp1.x;
David Turnerd2b1f351999-12-16 23:11:37 +00001173
1174 /* Now take care of vertical metrics. In the case where there is */
1175 /* no vertical information within the font (relatively common), make */
1176 /* up some metrics by `hand'... */
1177
1178 {
David Turnerf9b8dec2000-06-16 19:34:52 +00001179 FT_Short top_bearing; /* vertical top side bearing (EM units) */
1180 FT_UShort advance_height; /* vertical advance height (EM units) */
David Turnerd2b1f351999-12-16 23:11:37 +00001181
David Turnerf9b8dec2000-06-16 19:34:52 +00001182 FT_Pos left; /* scaled vertical left side bearing */
1183 FT_Pos Top; /* scaled original vertical top side bearing */
1184 FT_Pos top; /* scaled vertical top side bearing */
1185 FT_Pos advance; /* scaled vertical advance height */
David Turnerd2b1f351999-12-16 23:11:37 +00001186
1187
1188 /* Get the unscaled `tsb' and `ah' */
1189 if ( face->vertical_info &&
1190 face->vertical.number_Of_VMetrics > 0 )
1191 {
1192 /* Don't assume that both the vertical header and vertical */
1193 /* metrics are present in the same font :-) */
1194
1195 TT_Get_Metrics( (TT_HoriHeader*)&face->vertical,
1196 glyph_index,
1197 &top_bearing,
1198 &advance_height );
1199 }
1200 else
1201 {
Werner Lemberg78575dc2000-06-12 19:36:41 +00001202 /* Make up the distances from the horizontal header. */
David Turnerd2b1f351999-12-16 23:11:37 +00001203
Werner Lemberg78575dc2000-06-12 19:36:41 +00001204 /* NOTE: The OS/2 values are the only `portable' ones, */
1205 /* which is why we use them, if there is an OS/2 */
1206 /* table in the font. Otherwise, we use the */
1207 /* values defined in the horizontal header. */
1208 /* */
1209 /* NOTE2: The sTypoDescender is negative, which is why */
1210 /* we compute the baseline-to-baseline distance */
1211 /* here with: */
1212 /* ascender - descender + linegap */
1213 /* */
David Turnerd2b1f351999-12-16 23:11:37 +00001214 if ( face->os2.version != 0xFFFF )
1215 {
1216 top_bearing = face->os2.sTypoLineGap / 2;
David Turnerf9b8dec2000-06-16 19:34:52 +00001217 advance_height = (FT_UShort)( face->os2.sTypoAscender -
Werner Lemberg78575dc2000-06-12 19:36:41 +00001218 face->os2.sTypoDescender +
1219 face->os2.sTypoLineGap );
David Turnerd2b1f351999-12-16 23:11:37 +00001220 }
1221 else
1222 {
1223 top_bearing = face->horizontal.Line_Gap / 2;
David Turnerf9b8dec2000-06-16 19:34:52 +00001224 advance_height = (FT_UShort)( face->horizontal.Ascender +
Werner Lemberg78575dc2000-06-12 19:36:41 +00001225 face->horizontal.Descender +
1226 face->horizontal.Line_Gap );
David Turnerd2b1f351999-12-16 23:11:37 +00001227 }
1228 }
1229
Werner Lemberg78575dc2000-06-12 19:36:41 +00001230 /* We must adjust the top_bearing value from the bounding box given */
1231 /* in the glyph header to te bounding box calculated with */
David Turnerf0df85b2000-06-22 00:17:42 +00001232 /* FT_Get_Outline_CBox(). */
David Turnerfc1f9892000-01-07 18:44:50 +00001233
David Turnerd2b1f351999-12-16 23:11:37 +00001234 /* scale the metrics */
Werner Lemberg78575dc2000-06-12 19:36:41 +00001235 if ( !( loader->load_flags & FT_LOAD_NO_SCALE ) )
David Turnerd2b1f351999-12-16 23:11:37 +00001236 {
David Turner8f43c712000-02-02 12:16:19 +00001237 Top = FT_MulFix( top_bearing, y_scale );
1238 top = FT_MulFix( top_bearing + loader->bbox.yMax, y_scale )
1239 - bbox.yMax;
1240 advance = FT_MulFix( advance_height, y_scale );
David Turnerd2b1f351999-12-16 23:11:37 +00001241 }
1242 else
1243 {
David Turnerfc1f9892000-01-07 18:44:50 +00001244 Top = top_bearing;
David Turner8f43c712000-02-02 12:16:19 +00001245 top = top_bearing + loader->bbox.yMax - bbox.yMax;
David Turnerd2b1f351999-12-16 23:11:37 +00001246 advance = advance_height;
1247 }
1248
Werner Lemberga929ba92000-06-25 06:47:11 +00001249 /* set the advance height in design units. It is scaled later by */
1250 /* the base layer. */
David Turnerf0df85b2000-06-22 00:17:42 +00001251 glyph->linearVertAdvance = advance_height;
David Turnerd2b1f351999-12-16 23:11:37 +00001252
Werner Lemberga929ba92000-06-25 06:47:11 +00001253 /* XXX: for now, we have no better algorithm for the lsb, but it */
1254 /* should work fine. */
1255 /* */
David Turnerd2b1f351999-12-16 23:11:37 +00001256 left = ( bbox.xMin - bbox.xMax ) / 2;
1257
1258 /* grid-fit them if necessary */
Werner Lemberg78575dc2000-06-12 19:36:41 +00001259 if ( IS_HINTED( loader->load_flags ) )
David Turnerd2b1f351999-12-16 23:11:37 +00001260 {
1261 left &= -64;
Werner Lemberg78575dc2000-06-12 19:36:41 +00001262 top = ( top + 63 ) & -64;
1263 advance = ( advance + 32 ) & -64;
David Turnerd2b1f351999-12-16 23:11:37 +00001264 }
1265
1266 glyph->metrics.vertBearingX = left;
1267 glyph->metrics.vertBearingY = top;
1268 glyph->metrics.vertAdvance = advance;
1269 }
1270
Werner Lembergdcd2e142000-06-25 07:43:15 +00001271 /* adjust advance width to the value contained in the hdmx table */
David Turner8f43c712000-02-02 12:16:19 +00001272 if ( !face->postscript.isFixedPitch && size &&
Werner Lemberg78575dc2000-06-12 19:36:41 +00001273 IS_HINTED( loader->load_flags ) )
David Turnerd2b1f351999-12-16 23:11:37 +00001274 {
David Turnerf9b8dec2000-06-16 19:34:52 +00001275 FT_Byte* widths = Get_Advance_Widths( face,
Werner Lemberg78575dc2000-06-12 19:36:41 +00001276 size->root.metrics.x_ppem );
Werner Lembergdcd2e142000-06-25 07:43:15 +00001277
1278
David Turnerd2b1f351999-12-16 23:11:37 +00001279 if ( widths )
1280 glyph->metrics.horiAdvance = widths[glyph_index] << 6;
1281 }
1282
David Turnerd2b1f351999-12-16 23:11:37 +00001283 /* set glyph dimensions */
1284 glyph->metrics.width = bbox.xMax - bbox.xMin;
1285 glyph->metrics.height = bbox.yMax - bbox.yMin;
David Turner8f43c712000-02-02 12:16:19 +00001286 }
David Turnerd2b1f351999-12-16 23:11:37 +00001287
David Turnerd2b1f351999-12-16 23:11:37 +00001288
Werner Lemberg78575dc2000-06-12 19:36:41 +00001289 /*************************************************************************/
1290 /* */
1291 /* <Function> */
1292 /* TT_Load_Glyph */
1293 /* */
1294 /* <Description> */
1295 /* A function used to load a single glyph within a given glyph slot, */
1296 /* for a given size. */
1297 /* */
1298 /* <Input> */
1299 /* glyph :: A handle to a target slot object where the glyph */
1300 /* will be loaded. */
1301 /* */
1302 /* size :: A handle to the source face size at which the glyph */
1303 /* must be scaled/loaded. */
1304 /* */
1305 /* glyph_index :: The index of the glyph in the font file. */
1306 /* */
1307 /* load_flags :: A flag indicating what to load for this glyph. The */
1308 /* FT_LOAD_XXX constants can be used to control the */
1309 /* glyph loading process (e.g., whether the outline */
1310 /* should be scaled, whether to load bitmaps or not, */
1311 /* whether to hint the outline, etc). */
1312 /* */
1313 /* <Return> */
Werner Lemberga929ba92000-06-25 06:47:11 +00001314 /* FreeType error code. 0 means success. */
Werner Lemberg78575dc2000-06-12 19:36:41 +00001315 /* */
David Turner76a5f622000-11-04 01:55:49 +00001316 FT_LOCAL_DEF
David Turnerf9b8dec2000-06-16 19:34:52 +00001317 FT_Error TT_Load_Glyph( TT_Size size,
David Turner8f43c712000-02-02 12:16:19 +00001318 TT_GlyphSlot glyph,
David Turnerf9b8dec2000-06-16 19:34:52 +00001319 FT_UShort glyph_index,
1320 FT_UInt load_flags )
David Turner8f43c712000-02-02 12:16:19 +00001321 {
1322 SFNT_Interface* sfnt;
1323 TT_Face face;
1324 FT_Stream stream;
1325 FT_Memory memory;
David Turnerf9b8dec2000-06-16 19:34:52 +00001326 FT_Error error;
David Turner8f43c712000-02-02 12:16:19 +00001327 TT_Loader loader;
David Turnere49ab252000-05-16 23:44:38 +00001328
Werner Lemberg78575dc2000-06-12 19:36:41 +00001329
David Turner8f43c712000-02-02 12:16:19 +00001330 face = (TT_Face)glyph->face;
1331 sfnt = (SFNT_Interface*)face->sfnt;
1332 stream = face->root.stream;
1333 memory = face->root.memory;
1334 error = 0;
David Turnered7f62a2000-03-28 11:19:28 +00001335
Werner Lemberg78575dc2000-06-12 19:36:41 +00001336 if ( !size || ( load_flags & FT_LOAD_NO_SCALE ) ||
1337 ( load_flags & FT_LOAD_NO_RECURSE ) )
David Turner8f43c712000-02-02 12:16:19 +00001338 {
1339 size = NULL;
1340 load_flags |= FT_LOAD_NO_SCALE |
1341 FT_LOAD_NO_HINTING |
1342 FT_LOAD_NO_BITMAP;
1343 }
1344
David Turnered7f62a2000-03-28 11:19:28 +00001345 glyph->num_subglyphs = 0;
1346
David Turner8f43c712000-02-02 12:16:19 +00001347#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
Werner Lemberg78575dc2000-06-12 19:36:41 +00001348
1349 /* try to load embedded bitmap if any */
1350 if ( size &&
1351 ( load_flags & FT_LOAD_NO_BITMAP ) == 0 &&
1352 sfnt->load_sbits )
David Turner8f43c712000-02-02 12:16:19 +00001353 {
1354 TT_SBit_Metrics metrics;
David Turnere49ab252000-05-16 23:44:38 +00001355
Werner Lemberg78575dc2000-06-12 19:36:41 +00001356
David Turner8f43c712000-02-02 12:16:19 +00001357 error = sfnt->load_sbit_image( face,
1358 size->root.metrics.x_ppem,
1359 size->root.metrics.y_ppem,
1360 glyph_index,
David Turner109fcf62000-05-17 23:35:37 +00001361 load_flags,
David Turner8f43c712000-02-02 12:16:19 +00001362 stream,
1363 &glyph->bitmap,
1364 &metrics );
1365 if ( !error )
1366 {
1367 glyph->outline.n_points = 0;
1368 glyph->outline.n_contours = 0;
1369
David Turnerf9b8dec2000-06-16 19:34:52 +00001370 glyph->metrics.width = (FT_Pos)metrics.width << 6;
1371 glyph->metrics.height = (FT_Pos)metrics.height << 6;
David Turner8f43c712000-02-02 12:16:19 +00001372
David Turnerf9b8dec2000-06-16 19:34:52 +00001373 glyph->metrics.horiBearingX = (FT_Pos)metrics.horiBearingX << 6;
1374 glyph->metrics.horiBearingY = (FT_Pos)metrics.horiBearingY << 6;
1375 glyph->metrics.horiAdvance = (FT_Pos)metrics.horiAdvance << 6;
David Turner8f43c712000-02-02 12:16:19 +00001376
David Turnerf9b8dec2000-06-16 19:34:52 +00001377 glyph->metrics.vertBearingX = (FT_Pos)metrics.vertBearingX << 6;
1378 glyph->metrics.vertBearingY = (FT_Pos)metrics.vertBearingY << 6;
1379 glyph->metrics.vertAdvance = (FT_Pos)metrics.vertAdvance << 6;
David Turner8f43c712000-02-02 12:16:19 +00001380
1381 glyph->format = ft_glyph_format_bitmap;
David Turnerf0df85b2000-06-22 00:17:42 +00001382 if ( load_flags & FT_LOAD_VERTICAL_LAYOUT )
1383 {
David Turnere161ee42000-07-10 22:03:10 +00001384 glyph->bitmap_left = metrics.vertBearingX;
1385 glyph->bitmap_top = metrics.vertBearingY;
David Turnerf0df85b2000-06-22 00:17:42 +00001386 }
1387 else
1388 {
David Turnere161ee42000-07-10 22:03:10 +00001389 glyph->bitmap_left = metrics.horiBearingX;
1390 glyph->bitmap_top = metrics.horiBearingY;
David Turnerf0df85b2000-06-22 00:17:42 +00001391 }
David Turner8f43c712000-02-02 12:16:19 +00001392 return error;
1393 }
1394 }
Werner Lemberg78575dc2000-06-12 19:36:41 +00001395
David Turner8f43c712000-02-02 12:16:19 +00001396#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
1397
Werner Lemberg5811c7c2000-07-02 13:53:16 +00001398 /* seek to the beginning of the glyph table. For Type 42 fonts */
Werner Lemberg78575dc2000-06-12 19:36:41 +00001399 /* the table might be accessed from a Postscript stream or something */
1400 /* else... */
1401
David Turner8f43c712000-02-02 12:16:19 +00001402 error = face->goto_table( face, TTAG_glyf, stream, 0 );
Werner Lemberg78575dc2000-06-12 19:36:41 +00001403 if ( error )
David Turner8f43c712000-02-02 12:16:19 +00001404 {
Werner Lembergdcd2e142000-06-25 07:43:15 +00001405 FT_ERROR(( "TT_Load_Glyph: could not access glyph table\n" ));
David Turner08fdac92000-02-21 16:01:33 +00001406 goto Exit;
David Turner8f43c712000-02-02 12:16:19 +00001407 }
1408
Werner Lemberg78575dc2000-06-12 19:36:41 +00001409 MEM_Set( &loader, 0, sizeof ( loader ) );
David Turner8f43c712000-02-02 12:16:19 +00001410
David Turner08fdac92000-02-21 16:01:33 +00001411 /* update the glyph zone bounds */
David Turner08fdac92000-02-21 16:01:33 +00001412 {
David Turnerf0df85b2000-06-22 00:17:42 +00001413 FT_GlyphLoader* gloader = FT_FACE_DRIVER(face)->glyph_loader;
Werner Lemberga929ba92000-06-25 06:47:11 +00001414
Werner Lembergbd5ae402000-07-05 04:32:02 +00001415
David Turnerf0df85b2000-06-22 00:17:42 +00001416 loader.gloader = gloader;
Werner Lembergbd5ae402000-07-05 04:32:02 +00001417
David Turnerf0df85b2000-06-22 00:17:42 +00001418 FT_GlyphLoader_Rewind( gloader );
Werner Lembergbd5ae402000-07-05 04:32:02 +00001419
David Turnerf0df85b2000-06-22 00:17:42 +00001420 tt_prepare_zone( &loader.zone, &gloader->base, 0, 0 );
1421 tt_prepare_zone( &loader.base, &gloader->base, 0, 0 );
David Turner08fdac92000-02-21 16:01:33 +00001422 }
David Turner08fdac92000-02-21 16:01:33 +00001423
David Turner8f43c712000-02-02 12:16:19 +00001424#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
Werner Lemberg78575dc2000-06-12 19:36:41 +00001425
David Turner8f43c712000-02-02 12:16:19 +00001426 if ( size )
1427 {
1428 /* query new execution context */
Werner Lemberg78575dc2000-06-12 19:36:41 +00001429 loader.exec = size->debug ? size->context : TT_New_Context( face );
David Turner8f43c712000-02-02 12:16:19 +00001430 if ( !loader.exec )
1431 return TT_Err_Could_Not_Find_Context;
David Turnere49ab252000-05-16 23:44:38 +00001432
David Turner8f43c712000-02-02 12:16:19 +00001433 TT_Load_Context( loader.exec, face, size );
David Turnerc3128612000-06-23 05:02:13 +00001434 loader.instructions = loader.exec->glyphIns;
David Turner8f43c712000-02-02 12:16:19 +00001435
1436 /* load default graphics state - if needed */
1437 if ( size->GS.instruct_control & 2 )
1438 loader.exec->GS = tt_default_graphics_state;
1439 }
Werner Lemberg78575dc2000-06-12 19:36:41 +00001440
David Turner8f43c712000-02-02 12:16:19 +00001441#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
1442
Werner Lemberg78575dc2000-06-12 19:36:41 +00001443 /* clear all outline flags, except the `owner' one */
David Turner81bb4ad2000-06-28 04:19:49 +00001444 glyph->outline.flags = 0;
David Turnere49ab252000-05-16 23:44:38 +00001445
David Turner04aa8002000-06-01 03:27:48 +00001446 if ( size && size->root.metrics.y_ppem < 24 )
David Turner41dbcbf2000-03-09 11:46:25 +00001447 glyph->outline.flags |= ft_outline_high_precision;
David Turner8f43c712000-02-02 12:16:19 +00001448
Werner Lemberg78575dc2000-06-12 19:36:41 +00001449 /* let's initialize the rest of our loader now */
1450
David Turner8f43c712000-02-02 12:16:19 +00001451 loader.load_flags = load_flags;
1452
David Turnerc3128612000-06-23 05:02:13 +00001453 loader.face = (FT_Face)face;
1454 loader.size = (FT_Size)size;
1455 loader.glyph = (FT_GlyphSlot)glyph;
David Turner8f43c712000-02-02 12:16:19 +00001456 loader.stream = stream;
Werner Lembergbd5ae402000-07-05 04:32:02 +00001457
David Turnerc3128612000-06-23 05:02:13 +00001458 loader.glyf_offset = FILE_Pos();
David Turner8f43c712000-02-02 12:16:19 +00001459
1460#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
Werner Lemberg78575dc2000-06-12 19:36:41 +00001461
1462 /* if the cvt program has disabled hinting, the argument */
1463 /* is ignored. */
1464 if ( size && ( size->GS.instruct_control & 1 ) )
David Turner8f43c712000-02-02 12:16:19 +00001465 loader.load_flags |= FT_LOAD_NO_HINTING;
Werner Lemberg78575dc2000-06-12 19:36:41 +00001466
1467#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
David Turner8f43c712000-02-02 12:16:19 +00001468
1469 /* Main loading loop */
David Turner3475e7f2000-05-17 20:56:01 +00001470 glyph->format = ft_glyph_format_outline;
Werner Lemberg78575dc2000-06-12 19:36:41 +00001471 glyph->num_subglyphs = 0;
David Turner8f43c712000-02-02 12:16:19 +00001472 error = load_truetype_glyph( &loader, glyph_index );
Werner Lemberg78575dc2000-06-12 19:36:41 +00001473 if ( !error )
David Turner8f43c712000-02-02 12:16:19 +00001474 compute_glyph_metrics( &loader, glyph_index );
1475
1476#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
Werner Lembergdcd2e142000-06-25 07:43:15 +00001477
David Turnerd2b1f351999-12-16 23:11:37 +00001478 if ( !size || !size->debug )
David Turner8f43c712000-02-02 12:16:19 +00001479 TT_Done_Context( loader.exec );
Werner Lembergdcd2e142000-06-25 07:43:15 +00001480
1481#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
David Turnerd2b1f351999-12-16 23:11:37 +00001482
David Turner08fdac92000-02-21 16:01:33 +00001483 Exit:
David Turnerd2b1f351999-12-16 23:11:37 +00001484 return error;
1485 }
1486
1487
David Turnerd2b1f351999-12-16 23:11:37 +00001488/* END */