blob: af276f7f342b17ca92e5bae5cbb18ad7b57d1cc0 [file] [log] [blame]
David Turner19ed8af2000-12-08 02:42:29 +00001/***************************************************************************/
2/* */
3/* cffparse.c */
4/* */
5/* CFF token stream parser (body) */
6/* */
Werner Lemberg210d6182008-04-01 05:55:48 +00007/* Copyright 1996-2001, 2002, 2003, 2004, 2007, 2008 by */
David Turner19ed8af2000-12-08 02:42:29 +00008/* David Turner, Robert Wilhelm, and Werner Lemberg. */
9/* */
10/* This file is part of the FreeType project, and may only be used, */
11/* modified, and distributed under the terms of the FreeType project */
12/* 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>
David Turner8d3a4012001-03-20 11:14:24 +000020#include "cffparse.h"
David Turner19ed8af2000-12-08 02:42:29 +000021#include FT_INTERNAL_STREAM_H
22
Werner Lemberg1f7f0e82001-06-06 17:30:41 +000023#include "cfferrs.h"
24
Werner Lembergcc069be2000-12-08 16:17:16 +000025
David Turner19ed8af2000-12-08 02:42:29 +000026 /*************************************************************************/
27 /* */
28 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
29 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
30 /* messages during execution. */
31 /* */
32#undef FT_COMPONENT
Tom Kacvinsky8d1f6042001-01-03 00:21:59 +000033#define FT_COMPONENT trace_cffparse
David Turner19ed8af2000-12-08 02:42:29 +000034
35
David Turner19ed8af2000-12-08 02:42:29 +000036 enum
37 {
38 cff_kind_none = 0,
39 cff_kind_num,
40 cff_kind_fixed,
Werner Lembergbf7c8322003-06-06 05:07:53 +000041 cff_kind_fixed_thousand,
David Turner19ed8af2000-12-08 02:42:29 +000042 cff_kind_string,
43 cff_kind_bool,
44 cff_kind_delta,
45 cff_kind_callback,
46
47 cff_kind_max /* do not remove */
48 };
49
50
51 /* now generate handlers for the most simple fields */
Werner Lemberg48c984b2002-03-30 16:41:09 +000052 typedef FT_Error (*CFF_Field_Reader)( CFF_Parser parser );
David Turner19ed8af2000-12-08 02:42:29 +000053
54 typedef struct CFF_Field_Handler_
55 {
56 int kind;
57 int code;
58 FT_UInt offset;
59 FT_Byte size;
60 CFF_Field_Reader reader;
61 FT_UInt array_max;
62 FT_UInt count_offset;
63
64 } CFF_Field_Handler;
65
66
David Turnerbc82f1b2002-03-01 02:26:22 +000067 FT_LOCAL_DEF( void )
David Turnerb9b2cac2002-07-10 16:52:06 +000068 cff_parser_init( CFF_Parser parser,
Werner Lemberg48c984b2002-03-30 16:41:09 +000069 FT_UInt code,
70 void* object )
David Turner19ed8af2000-12-08 02:42:29 +000071 {
Werner Lembergb3d5e9c2002-07-28 05:05:24 +000072 FT_MEM_ZERO( parser, sizeof ( *parser ) );
David Turner19ed8af2000-12-08 02:42:29 +000073
74 parser->top = parser->stack;
75 parser->object_code = code;
76 parser->object = object;
77 }
78
79
Werner Lembergcc069be2000-12-08 16:17:16 +000080 /* read an integer */
Werner Lemberg93616ec2001-06-27 19:46:12 +000081 static FT_Long
82 cff_parse_integer( FT_Byte* start,
83 FT_Byte* limit )
David Turner19ed8af2000-12-08 02:42:29 +000084 {
85 FT_Byte* p = start;
86 FT_Int v = *p++;
87 FT_Long val = 0;
88
89
90 if ( v == 28 )
91 {
92 if ( p + 2 > limit )
93 goto Bad;
94
95 val = (FT_Short)( ( (FT_Int)p[0] << 8 ) | p[1] );
96 p += 2;
97 }
98 else if ( v == 29 )
99 {
100 if ( p + 4 > limit )
101 goto Bad;
102
103 val = ( (FT_Long)p[0] << 24 ) |
104 ( (FT_Long)p[1] << 16 ) |
105 ( (FT_Long)p[2] << 8 ) |
106 p[3];
107 p += 4;
108 }
109 else if ( v < 247 )
110 {
111 val = v - 139;
112 }
113 else if ( v < 251 )
114 {
115 if ( p + 1 > limit )
116 goto Bad;
117
118 val = ( v - 247 ) * 256 + p[0] + 108;
119 p++;
120 }
121 else
122 {
123 if ( p + 1 > limit )
124 goto Bad;
125
126 val = -( v - 251 ) * 256 - p[0] - 108;
127 p++;
128 }
129
130 Exit:
131 return val;
132
133 Bad:
134 val = 0;
135 goto Exit;
136 }
137
138
139 /* read a real */
Werner Lemberg93616ec2001-06-27 19:46:12 +0000140 static FT_Fixed
141 cff_parse_real( FT_Byte* start,
142 FT_Byte* limit,
143 FT_Int power_ten )
David Turner19ed8af2000-12-08 02:42:29 +0000144 {
145 FT_Byte* p = start;
Werner Lemberg4b8397c2004-08-29 16:50:09 +0000146 FT_Long num, divider, result, exponent;
147 FT_Int sign = 0, exponent_sign = 0;
David Turner8edbcab2001-06-19 08:28:24 +0000148 FT_UInt nib;
149 FT_UInt phase;
David Turner19ed8af2000-12-08 02:42:29 +0000150
151
152 result = 0;
153 num = 0;
154 divider = 1;
155
156 /* first of all, read the integer part */
157 phase = 4;
158
159 for (;;)
160 {
David Turner19ed8af2000-12-08 02:42:29 +0000161 /* If we entered this iteration with phase == 4, we need to */
Werner Lemberg6e87ed92007-01-26 22:18:56 +0000162 /* read a new byte. This also skips past the initial 0x1E. */
David Turner19ed8af2000-12-08 02:42:29 +0000163 if ( phase )
164 {
165 p++;
166
167 /* Make sure we don't read past the end. */
168 if ( p >= limit )
169 goto Bad;
170 }
171
172 /* Get the nibble. */
173 nib = ( p[0] >> phase ) & 0xF;
174 phase = 4 - phase;
175
176 if ( nib == 0xE )
177 sign = 1;
178 else if ( nib > 9 )
179 break;
180 else
181 result = result * 10 + nib;
182 }
183
184 /* read decimal part, if any */
185 if ( nib == 0xa )
186 for (;;)
187 {
David Turner19ed8af2000-12-08 02:42:29 +0000188 /* If we entered this iteration with phase == 4, we need */
189 /* to read a new byte. */
190 if ( phase )
Werner Lembergcc069be2000-12-08 16:17:16 +0000191 {
David Turner19ed8af2000-12-08 02:42:29 +0000192 p++;
193
194 /* Make sure we don't read past the end. */
195 if ( p >= limit )
196 goto Bad;
Werner Lembergcc069be2000-12-08 16:17:16 +0000197 }
David Turner19ed8af2000-12-08 02:42:29 +0000198
199 /* Get the nibble. */
200 nib = ( p[0] >> phase ) & 0xF;
201 phase = 4 - phase;
202 if ( nib >= 10 )
203 break;
204
Werner Lemberg210d6182008-04-01 05:55:48 +0000205 /* Increase precision if the integer part is zero */
206 /* and we have to scale the real number. */
207 if ( !result && power_ten )
David Turner19ed8af2000-12-08 02:42:29 +0000208 {
Werner Lemberg210d6182008-04-01 05:55:48 +0000209 power_ten--;
210 num = num * 10 + nib;
211 }
212 else
213 {
214 if ( divider < 10000000L )
215 {
216 num = num * 10 + nib;
217 divider *= 10;
218 }
David Turner19ed8af2000-12-08 02:42:29 +0000219 }
220 }
221
222 /* read exponent, if any */
223 if ( nib == 12 )
224 {
Werner Lemberg4b8397c2004-08-29 16:50:09 +0000225 exponent_sign = 1;
226 nib = 11;
David Turner19ed8af2000-12-08 02:42:29 +0000227 }
228
229 if ( nib == 11 )
230 {
Werner Lemberg4b8397c2004-08-29 16:50:09 +0000231 exponent = 0;
David Turner19ed8af2000-12-08 02:42:29 +0000232
233 for (;;)
234 {
235 /* If we entered this iteration with phase == 4, we need */
236 /* to read a new byte. */
237 if ( phase )
Werner Lembergcc069be2000-12-08 16:17:16 +0000238 {
David Turner19ed8af2000-12-08 02:42:29 +0000239 p++;
240
241 /* Make sure we don't read past the end. */
242 if ( p >= limit )
243 goto Bad;
Werner Lembergcc069be2000-12-08 16:17:16 +0000244 }
David Turner19ed8af2000-12-08 02:42:29 +0000245
246 /* Get the nibble. */
247 nib = ( p[0] >> phase ) & 0xF;
248 phase = 4 - phase;
249 if ( nib >= 10 )
250 break;
251
Werner Lemberg4b8397c2004-08-29 16:50:09 +0000252 exponent = exponent * 10 + nib;
David Turner19ed8af2000-12-08 02:42:29 +0000253 }
254
Werner Lemberg4b8397c2004-08-29 16:50:09 +0000255 if ( exponent_sign )
256 exponent = -exponent;
David Turner19ed8af2000-12-08 02:42:29 +0000257
Werner Lemberg4b8397c2004-08-29 16:50:09 +0000258 power_ten += (FT_Int)exponent;
David Turner19ed8af2000-12-08 02:42:29 +0000259 }
260
Werner Lemberg210d6182008-04-01 05:55:48 +0000261 /* Move the integer part into the higher 16 bits. */
Tom Kacvinskyc27cd282001-02-07 01:11:54 +0000262 result <<= 16;
263
Werner Lemberg210d6182008-04-01 05:55:48 +0000264 /* Place the decimal part into the lower 16 bits. */
David Turner19ed8af2000-12-08 02:42:29 +0000265 if ( num )
Tom Kacvinskyc27cd282001-02-07 01:11:54 +0000266 result |= FT_DivFix( num, divider );
David Turner19ed8af2000-12-08 02:42:29 +0000267
Werner Lembergd156cab2007-12-14 07:48:32 +0000268 /* apply power of 10 if needed */
269 if ( power_ten > 0 )
270 {
271 divider = 10; /* actually, this will be used as multiplier here */
272 while ( --power_ten > 0 )
273 divider = divider * 10;
274
275 result = FT_MulFix( divider << 16, result );
276 }
277 else if ( power_ten < 0 )
278 {
279 divider = 10;
280 while ( ++power_ten < 0 )
281 divider = divider * 10;
282
283 result = FT_DivFix( result, divider << 16 );
284 }
285
David Turner19ed8af2000-12-08 02:42:29 +0000286 if ( sign )
287 result = -result;
288
289 Exit:
290 return result;
291
292 Bad:
293 result = 0;
294 goto Exit;
295 }
296
297
298 /* read a number, either integer or real */
Werner Lemberg93616ec2001-06-27 19:46:12 +0000299 static FT_Long
300 cff_parse_num( FT_Byte** d )
David Turner19ed8af2000-12-08 02:42:29 +0000301 {
302 return ( **d == 30 ? ( cff_parse_real ( d[0], d[1], 0 ) >> 16 )
303 : cff_parse_integer( d[0], d[1] ) );
304 }
305
306
Werner Lembergcc069be2000-12-08 16:17:16 +0000307 /* read a floating point number, either integer or real */
Werner Lemberg93616ec2001-06-27 19:46:12 +0000308 static FT_Fixed
309 cff_parse_fixed( FT_Byte** d )
David Turner19ed8af2000-12-08 02:42:29 +0000310 {
311 return ( **d == 30 ? cff_parse_real ( d[0], d[1], 0 )
312 : cff_parse_integer( d[0], d[1] ) << 16 );
313 }
314
Tom Kacvinskyc27cd282001-02-07 01:11:54 +0000315 /* read a floating point number, either integer or real, */
316 /* but return 1000 times the number read in. */
Werner Lemberg93616ec2001-06-27 19:46:12 +0000317 static FT_Fixed
318 cff_parse_fixed_thousand( FT_Byte** d )
Tom Kacvinskyc27cd282001-02-07 01:11:54 +0000319 {
Werner Lemberg500dc852001-02-10 17:45:01 +0000320 return **d ==
321 30 ? cff_parse_real ( d[0], d[1], 3 )
322 : (FT_Fixed)FT_MulFix( cff_parse_integer( d[0], d[1] ) << 16, 1000 );
Tom Kacvinskyc27cd282001-02-07 01:11:54 +0000323 }
David Turner19ed8af2000-12-08 02:42:29 +0000324
Werner Lemberg93616ec2001-06-27 19:46:12 +0000325 static FT_Error
Werner Lemberg48c984b2002-03-30 16:41:09 +0000326 cff_parse_font_matrix( CFF_Parser parser )
David Turner19ed8af2000-12-08 02:42:29 +0000327 {
David Turnerab4fc4d2002-03-14 08:57:10 +0000328 CFF_FontRecDict dict = (CFF_FontRecDict)parser->object;
Werner Lemberg48c984b2002-03-30 16:41:09 +0000329 FT_Matrix* matrix = &dict->font_matrix;
330 FT_Vector* offset = &dict->font_offset;
331 FT_UShort* upm = &dict->units_per_em;
332 FT_Byte** data = parser->stack;
333 FT_Error error;
334 FT_Fixed temp;
David Turner19ed8af2000-12-08 02:42:29 +0000335
Werner Lemberg6b766632000-12-30 22:14:58 +0000336
Tom Kacvinsky8d1f6042001-01-03 00:21:59 +0000337 error = CFF_Err_Stack_Underflow;
David Turner19ed8af2000-12-08 02:42:29 +0000338
339 if ( parser->top >= parser->stack + 6 )
340 {
Tom Kacvinskyc27cd282001-02-07 01:11:54 +0000341 matrix->xx = cff_parse_fixed_thousand( data++ );
342 matrix->yx = cff_parse_fixed_thousand( data++ );
343 matrix->xy = cff_parse_fixed_thousand( data++ );
344 matrix->yy = cff_parse_fixed_thousand( data++ );
345 offset->x = cff_parse_fixed_thousand( data++ );
346 offset->y = cff_parse_fixed_thousand( data );
Tom Kacvinskya05c02c2000-12-24 09:57:28 +0000347
Werner Lembergdfa46192004-03-05 09:26:24 +0000348 temp = FT_ABS( matrix->yy );
Tom Kacvinskya05c02c2000-12-24 09:57:28 +0000349
Werner Lemberg210d6182008-04-01 05:55:48 +0000350 *upm = (FT_UShort)FT_DivFix( 1000, temp );
351
352 /* we normalize the matrix so that `matrix->xx' is 1; */
353 /* the scaling is done with `units_per_em' then */
Tom Kacvinskyc27cd282001-02-07 01:11:54 +0000354
Tom Kacvinskya05c02c2000-12-24 09:57:28 +0000355 if ( temp != 0x10000L )
356 {
357 matrix->xx = FT_DivFix( matrix->xx, temp );
358 matrix->yx = FT_DivFix( matrix->yx, temp );
359 matrix->xy = FT_DivFix( matrix->xy, temp );
360 matrix->yy = FT_DivFix( matrix->yy, temp );
361 offset->x = FT_DivFix( offset->x, temp );
362 offset->y = FT_DivFix( offset->y, temp );
363 }
364
365 /* note that the offsets must be expressed in integer font units */
366 offset->x >>= 16;
367 offset->y >>= 16;
368
Tom Kacvinsky8d1f6042001-01-03 00:21:59 +0000369 error = CFF_Err_Ok;
David Turner19ed8af2000-12-08 02:42:29 +0000370 }
371
372 return error;
373 }
374
375
Werner Lemberg93616ec2001-06-27 19:46:12 +0000376 static FT_Error
Werner Lemberg48c984b2002-03-30 16:41:09 +0000377 cff_parse_font_bbox( CFF_Parser parser )
David Turner19ed8af2000-12-08 02:42:29 +0000378 {
David Turnerab4fc4d2002-03-14 08:57:10 +0000379 CFF_FontRecDict dict = (CFF_FontRecDict)parser->object;
Werner Lemberg48c984b2002-03-30 16:41:09 +0000380 FT_BBox* bbox = &dict->font_bbox;
381 FT_Byte** data = parser->stack;
382 FT_Error error;
David Turner19ed8af2000-12-08 02:42:29 +0000383
384
Tom Kacvinsky8d1f6042001-01-03 00:21:59 +0000385 error = CFF_Err_Stack_Underflow;
David Turner19ed8af2000-12-08 02:42:29 +0000386
387 if ( parser->top >= parser->stack + 4 )
388 {
Tom Kacvinskyc24eff82001-03-17 19:01:25 +0000389 bbox->xMin = FT_RoundFix( cff_parse_fixed( data++ ) );
390 bbox->yMin = FT_RoundFix( cff_parse_fixed( data++ ) );
391 bbox->xMax = FT_RoundFix( cff_parse_fixed( data++ ) );
392 bbox->yMax = FT_RoundFix( cff_parse_fixed( data ) );
Tom Kacvinsky8d1f6042001-01-03 00:21:59 +0000393 error = CFF_Err_Ok;
David Turner19ed8af2000-12-08 02:42:29 +0000394 }
395
396 return error;
397 }
398
399
Werner Lemberg93616ec2001-06-27 19:46:12 +0000400 static FT_Error
Werner Lemberg48c984b2002-03-30 16:41:09 +0000401 cff_parse_private_dict( CFF_Parser parser )
David Turner19ed8af2000-12-08 02:42:29 +0000402 {
David Turnerab4fc4d2002-03-14 08:57:10 +0000403 CFF_FontRecDict dict = (CFF_FontRecDict)parser->object;
Werner Lemberg48c984b2002-03-30 16:41:09 +0000404 FT_Byte** data = parser->stack;
405 FT_Error error;
David Turner19ed8af2000-12-08 02:42:29 +0000406
407
Tom Kacvinsky8d1f6042001-01-03 00:21:59 +0000408 error = CFF_Err_Stack_Underflow;
David Turner19ed8af2000-12-08 02:42:29 +0000409
410 if ( parser->top >= parser->stack + 2 )
411 {
412 dict->private_size = cff_parse_num( data++ );
413 dict->private_offset = cff_parse_num( data );
Tom Kacvinsky8d1f6042001-01-03 00:21:59 +0000414 error = CFF_Err_Ok;
David Turner19ed8af2000-12-08 02:42:29 +0000415 }
416
417 return error;
418 }
419
420
Werner Lemberg93616ec2001-06-27 19:46:12 +0000421 static FT_Error
Werner Lemberg48c984b2002-03-30 16:41:09 +0000422 cff_parse_cid_ros( CFF_Parser parser )
David Turner19ed8af2000-12-08 02:42:29 +0000423 {
David Turnerab4fc4d2002-03-14 08:57:10 +0000424 CFF_FontRecDict dict = (CFF_FontRecDict)parser->object;
Werner Lemberg48c984b2002-03-30 16:41:09 +0000425 FT_Byte** data = parser->stack;
426 FT_Error error;
David Turner19ed8af2000-12-08 02:42:29 +0000427
428
Tom Kacvinsky8d1f6042001-01-03 00:21:59 +0000429 error = CFF_Err_Stack_Underflow;
David Turner19ed8af2000-12-08 02:42:29 +0000430
431 if ( parser->top >= parser->stack + 3 )
432 {
433 dict->cid_registry = (FT_UInt)cff_parse_num ( data++ );
434 dict->cid_ordering = (FT_UInt)cff_parse_num ( data++ );
435 dict->cid_supplement = (FT_ULong)cff_parse_num( data );
Tom Kacvinsky8d1f6042001-01-03 00:21:59 +0000436 error = CFF_Err_Ok;
David Turner19ed8af2000-12-08 02:42:29 +0000437 }
438
439 return error;
440 }
441
442
443#define CFF_FIELD_NUM( code, name ) \
444 CFF_FIELD( code, name, cff_kind_num )
445#define CFF_FIELD_FIXED( code, name ) \
446 CFF_FIELD( code, name, cff_kind_fixed )
Werner Lembergbf7c8322003-06-06 05:07:53 +0000447#define CFF_FIELD_FIXED_1000( code, name ) \
448 CFF_FIELD( code, name, cff_kind_fixed_thousand )
David Turner19ed8af2000-12-08 02:42:29 +0000449#define CFF_FIELD_STRING( code, name ) \
450 CFF_FIELD( code, name, cff_kind_string )
451#define CFF_FIELD_BOOL( code, name ) \
452 CFF_FIELD( code, name, cff_kind_bool )
453#define CFF_FIELD_DELTA( code, name, max ) \
454 CFF_FIELD( code, name, cff_kind_delta )
455
456#define CFF_FIELD_CALLBACK( code, name ) \
457 { \
458 cff_kind_callback, \
459 code | CFFCODE, \
460 0, 0, \
461 cff_parse_ ## name, \
462 0, 0 \
463 },
464
465#undef CFF_FIELD
466#define CFF_FIELD( code, name, kind ) \
467 { \
468 kind, \
469 code | CFFCODE, \
470 FT_FIELD_OFFSET( name ), \
471 FT_FIELD_SIZE( name ), \
472 0, 0, 0 \
473 },
474
475#undef CFF_FIELD_DELTA
476#define CFF_FIELD_DELTA( code, name, max ) \
477 { \
478 cff_kind_delta, \
479 code | CFFCODE, \
480 FT_FIELD_OFFSET( name ), \
481 FT_FIELD_SIZE_DELTA( name ), \
482 0, \
483 max, \
484 FT_FIELD_OFFSET( num_ ## name ) \
485 },
486
487#define CFFCODE_TOPDICT 0x1000
488#define CFFCODE_PRIVATE 0x2000
489
490 static const CFF_Field_Handler cff_field_handlers[] =
491 {
492
David Turner8d3a4012001-03-20 11:14:24 +0000493#include "cfftoken.h"
David Turner19ed8af2000-12-08 02:42:29 +0000494
495 { 0, 0, 0, 0, 0, 0, 0 }
496 };
497
498
David Turnerbc82f1b2002-03-01 02:26:22 +0000499 FT_LOCAL_DEF( FT_Error )
David Turnerb9b2cac2002-07-10 16:52:06 +0000500 cff_parser_run( CFF_Parser parser,
Werner Lemberg48c984b2002-03-30 16:41:09 +0000501 FT_Byte* start,
502 FT_Byte* limit )
David Turner19ed8af2000-12-08 02:42:29 +0000503 {
504 FT_Byte* p = start;
Tom Kacvinsky8d1f6042001-01-03 00:21:59 +0000505 FT_Error error = CFF_Err_Ok;
David Turner19ed8af2000-12-08 02:42:29 +0000506
507
508 parser->top = parser->stack;
509 parser->start = start;
510 parser->limit = limit;
511 parser->cursor = start;
512
513 while ( p < limit )
514 {
David Turner8edbcab2001-06-19 08:28:24 +0000515 FT_UInt v = *p;
David Turner19ed8af2000-12-08 02:42:29 +0000516
517
518 if ( v >= 27 && v != 31 )
519 {
520 /* it's a number; we will push its position on the stack */
521 if ( parser->top - parser->stack >= CFF_MAX_STACK_DEPTH )
522 goto Stack_Overflow;
523
524 *parser->top ++ = p;
525
526 /* now, skip it */
527 if ( v == 30 )
528 {
529 /* skip real number */
530 p++;
531 for (;;)
532 {
533 if ( p >= limit )
534 goto Syntax_Error;
535 v = p[0] >> 4;
536 if ( v == 15 )
537 break;
538 v = p[0] & 0xF;
539 if ( v == 15 )
540 break;
541 p++;
542 }
543 }
544 else if ( v == 28 )
545 p += 2;
546 else if ( v == 29 )
547 p += 4;
548 else if ( v > 246 )
549 p += 1;
550 }
551 else
552 {
553 /* This is not a number, hence it's an operator. Compute its code */
554 /* and look for it in our current list. */
555
Werner Lembergcc069be2000-12-08 16:17:16 +0000556 FT_UInt code;
557 FT_UInt num_args = (FT_UInt)
558 ( parser->top - parser->stack );
David Turner19ed8af2000-12-08 02:42:29 +0000559 const CFF_Field_Handler* field;
560
561
David Turner19ed8af2000-12-08 02:42:29 +0000562 *parser->top = p;
563 code = v;
564 if ( v == 12 )
565 {
566 /* two byte operator */
567 p++;
David Turner25f845a2002-09-09 23:45:29 +0000568 if ( p >= limit )
569 goto Syntax_Error;
570
David Turner19ed8af2000-12-08 02:42:29 +0000571 code = 0x100 | p[0];
572 }
573 code = code | parser->object_code;
574
575 for ( field = cff_field_handlers; field->kind; field++ )
576 {
577 if ( field->code == (FT_Int)code )
578 {
579 /* we found our field's handler; read it */
580 FT_Long val;
581 FT_Byte* q = (FT_Byte*)parser->object + field->offset;
582
Werner Lembergcc069be2000-12-08 16:17:16 +0000583
David Turner25f845a2002-09-09 23:45:29 +0000584 /* check that we have enough arguments -- except for */
585 /* delta encoded arrays, which can be empty */
586 if ( field->kind != cff_kind_delta && num_args < 1 )
587 goto Stack_Underflow;
588
David Turner19ed8af2000-12-08 02:42:29 +0000589 switch ( field->kind )
590 {
591 case cff_kind_bool:
592 case cff_kind_string:
593 case cff_kind_num:
594 val = cff_parse_num( parser->stack );
595 goto Store_Number;
596
597 case cff_kind_fixed:
598 val = cff_parse_fixed( parser->stack );
Werner Lembergbf7c8322003-06-06 05:07:53 +0000599 goto Store_Number;
600
601 case cff_kind_fixed_thousand:
602 val = cff_parse_fixed_thousand( parser->stack );
David Turner19ed8af2000-12-08 02:42:29 +0000603
604 Store_Number:
605 switch ( field->size )
606 {
Werner Lemberg2b32a172004-04-24 06:06:39 +0000607 case (8 / FT_CHAR_BIT):
David Turner19ed8af2000-12-08 02:42:29 +0000608 *(FT_Byte*)q = (FT_Byte)val;
609 break;
610
Werner Lemberg2b32a172004-04-24 06:06:39 +0000611 case (16 / FT_CHAR_BIT):
David Turner19ed8af2000-12-08 02:42:29 +0000612 *(FT_Short*)q = (FT_Short)val;
613 break;
614
Werner Lemberg2b32a172004-04-24 06:06:39 +0000615 case (32 / FT_CHAR_BIT):
David Turner19ed8af2000-12-08 02:42:29 +0000616 *(FT_Int32*)q = (FT_Int)val;
617 break;
618
Werner Lemberg2b32a172004-04-24 06:06:39 +0000619 default: /* for 64-bit systems */
David Turner19ed8af2000-12-08 02:42:29 +0000620 *(FT_Long*)q = val;
621 }
622 break;
623
624 case cff_kind_delta:
625 {
626 FT_Byte* qcount = (FT_Byte*)parser->object +
627 field->count_offset;
628
629 FT_Byte** data = parser->stack;
630
631
632 if ( num_args > field->array_max )
633 num_args = field->array_max;
634
635 /* store count */
636 *qcount = (FT_Byte)num_args;
637
638 val = 0;
639 while ( num_args > 0 )
640 {
641 val += cff_parse_num( data++ );
642 switch ( field->size )
643 {
Werner Lemberg2b32a172004-04-24 06:06:39 +0000644 case (8 / FT_CHAR_BIT):
David Turner19ed8af2000-12-08 02:42:29 +0000645 *(FT_Byte*)q = (FT_Byte)val;
646 break;
647
Werner Lemberg2b32a172004-04-24 06:06:39 +0000648 case (16 / FT_CHAR_BIT):
David Turner19ed8af2000-12-08 02:42:29 +0000649 *(FT_Short*)q = (FT_Short)val;
650 break;
651
Werner Lemberg2b32a172004-04-24 06:06:39 +0000652 case (32 / FT_CHAR_BIT):
David Turner19ed8af2000-12-08 02:42:29 +0000653 *(FT_Int32*)q = (FT_Int)val;
654 break;
655
656 default: /* for 64-bit systems */
657 *(FT_Long*)q = val;
658 }
659
660 q += field->size;
661 num_args--;
662 }
663 }
664 break;
665
666 default: /* callback */
667 error = field->reader( parser );
668 if ( error )
669 goto Exit;
670 }
671 goto Found;
672 }
673 }
674
675 /* this is an unknown operator, or it is unsupported; */
676 /* we will ignore it for now. */
677
678 Found:
679 /* clear stack */
680 parser->top = parser->stack;
681 }
682 p++;
683 }
684
685 Exit:
686 return error;
687
688 Stack_Overflow:
Tom Kacvinsky8d1f6042001-01-03 00:21:59 +0000689 error = CFF_Err_Invalid_Argument;
David Turner19ed8af2000-12-08 02:42:29 +0000690 goto Exit;
691
692 Stack_Underflow:
Tom Kacvinsky8d1f6042001-01-03 00:21:59 +0000693 error = CFF_Err_Invalid_Argument;
David Turner19ed8af2000-12-08 02:42:29 +0000694 goto Exit;
695
696 Syntax_Error:
Tom Kacvinsky8d1f6042001-01-03 00:21:59 +0000697 error = CFF_Err_Invalid_Argument;
David Turner19ed8af2000-12-08 02:42:29 +0000698 goto Exit;
699 }
700
701
702/* END */