blob: 362c70abd46d800df89040fba0269d4c75a4958f [file] [log] [blame]
David Turner19ed8af2000-12-08 02:42:29 +00001/***************************************************************************/
2/* */
3/* cffparse.c */
4/* */
5/* CFF token stream parser (body) */
6/* */
7/* Copyright 1996-2000 by */
8/* 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,
41 cff_kind_string,
42 cff_kind_bool,
43 cff_kind_delta,
44 cff_kind_callback,
45
46 cff_kind_max /* do not remove */
47 };
48
49
50 /* now generate handlers for the most simple fields */
51 typedef FT_Error (*CFF_Field_Reader)( CFF_Parser* parser );
52
53 typedef struct CFF_Field_Handler_
54 {
55 int kind;
56 int code;
57 FT_UInt offset;
58 FT_Byte size;
59 CFF_Field_Reader reader;
60 FT_UInt array_max;
61 FT_UInt count_offset;
62
63 } CFF_Field_Handler;
64
65
Werner Lembergcc069be2000-12-08 16:17:16 +000066 FT_LOCAL_DEF
67 void CFF_Parser_Init( CFF_Parser* parser,
68 FT_UInt code,
69 void* object )
David Turner19ed8af2000-12-08 02:42:29 +000070 {
71 MEM_Set( parser, 0, sizeof ( *parser ) );
72
73 parser->top = parser->stack;
74 parser->object_code = code;
75 parser->object = object;
76 }
77
78
Werner Lembergcc069be2000-12-08 16:17:16 +000079 /* read an integer */
80 static
81 FT_Long cff_parse_integer( FT_Byte* start,
82 FT_Byte* limit )
David Turner19ed8af2000-12-08 02:42:29 +000083 {
84 FT_Byte* p = start;
85 FT_Int v = *p++;
86 FT_Long val = 0;
87
88
89 if ( v == 28 )
90 {
91 if ( p + 2 > limit )
92 goto Bad;
93
94 val = (FT_Short)( ( (FT_Int)p[0] << 8 ) | p[1] );
95 p += 2;
96 }
97 else if ( v == 29 )
98 {
99 if ( p + 4 > limit )
100 goto Bad;
101
102 val = ( (FT_Long)p[0] << 24 ) |
103 ( (FT_Long)p[1] << 16 ) |
104 ( (FT_Long)p[2] << 8 ) |
105 p[3];
106 p += 4;
107 }
108 else if ( v < 247 )
109 {
110 val = v - 139;
111 }
112 else if ( v < 251 )
113 {
114 if ( p + 1 > limit )
115 goto Bad;
116
117 val = ( v - 247 ) * 256 + p[0] + 108;
118 p++;
119 }
120 else
121 {
122 if ( p + 1 > limit )
123 goto Bad;
124
125 val = -( v - 251 ) * 256 - p[0] - 108;
126 p++;
127 }
128
129 Exit:
130 return val;
131
132 Bad:
133 val = 0;
134 goto Exit;
135 }
136
137
138 /* read a real */
Werner Lembergcc069be2000-12-08 16:17:16 +0000139 static
140 FT_Fixed cff_parse_real( FT_Byte* start,
141 FT_Byte* limit,
142 FT_Int power_ten )
David Turner19ed8af2000-12-08 02:42:29 +0000143 {
144 FT_Byte* p = start;
145 FT_Long num, divider, result, exp;
146 FT_Int sign = 0, exp_sign = 0;
David Turner8edbcab2001-06-19 08:28:24 +0000147 FT_UInt nib;
148 FT_UInt phase;
David Turner19ed8af2000-12-08 02:42:29 +0000149
150
151 result = 0;
152 num = 0;
153 divider = 1;
154
155 /* first of all, read the integer part */
156 phase = 4;
157
158 for (;;)
159 {
David Turner19ed8af2000-12-08 02:42:29 +0000160 /* If we entered this iteration with phase == 4, we need to */
161 /* read a new byte. This also skips past the intial 0x1E. */
162 if ( phase )
163 {
164 p++;
165
166 /* Make sure we don't read past the end. */
167 if ( p >= limit )
168 goto Bad;
169 }
170
171 /* Get the nibble. */
172 nib = ( p[0] >> phase ) & 0xF;
173 phase = 4 - phase;
174
175 if ( nib == 0xE )
176 sign = 1;
177 else if ( nib > 9 )
178 break;
179 else
180 result = result * 10 + nib;
181 }
182
183 /* read decimal part, if any */
184 if ( nib == 0xa )
185 for (;;)
186 {
David Turner19ed8af2000-12-08 02:42:29 +0000187 /* If we entered this iteration with phase == 4, we need */
188 /* to read a new byte. */
189 if ( phase )
Werner Lembergcc069be2000-12-08 16:17:16 +0000190 {
David Turner19ed8af2000-12-08 02:42:29 +0000191 p++;
192
193 /* Make sure we don't read past the end. */
194 if ( p >= limit )
195 goto Bad;
Werner Lembergcc069be2000-12-08 16:17:16 +0000196 }
David Turner19ed8af2000-12-08 02:42:29 +0000197
198 /* Get the nibble. */
199 nib = ( p[0] >> phase ) & 0xF;
200 phase = 4 - phase;
201 if ( nib >= 10 )
202 break;
203
Werner Lembergcc069be2000-12-08 16:17:16 +0000204 if ( divider < 10000000L )
David Turner19ed8af2000-12-08 02:42:29 +0000205 {
206 num = num * 10 + nib;
207 divider *= 10;
208 }
209 }
210
211 /* read exponent, if any */
212 if ( nib == 12 )
213 {
214 exp_sign = 1;
215 nib = 11;
216 }
217
218 if ( nib == 11 )
219 {
220 exp = 0;
221
222 for (;;)
223 {
224 /* If we entered this iteration with phase == 4, we need */
225 /* to read a new byte. */
226 if ( phase )
Werner Lembergcc069be2000-12-08 16:17:16 +0000227 {
David Turner19ed8af2000-12-08 02:42:29 +0000228 p++;
229
230 /* Make sure we don't read past the end. */
231 if ( p >= limit )
232 goto Bad;
Werner Lembergcc069be2000-12-08 16:17:16 +0000233 }
David Turner19ed8af2000-12-08 02:42:29 +0000234
235 /* Get the nibble. */
236 nib = ( p[0] >> phase ) & 0xF;
237 phase = 4 - phase;
238 if ( nib >= 10 )
239 break;
240
241 exp = exp * 10 + nib;
242 }
243
244 if ( exp_sign )
245 exp = -exp;
246
247 power_ten += exp;
248 }
249
250 /* raise to power of ten if needed */
251 while ( power_ten > 0 )
252 {
253 result = result * 10;
254 num = num * 10;
255
256 power_ten--;
257 }
258
259 while ( power_ten < 0 )
260 {
261 result = result / 10;
262 divider = divider * 10;
263
264 power_ten++;
265 }
266
Tom Kacvinskyc27cd282001-02-07 01:11:54 +0000267 /* Move the integer part into the high 16 bits. */
268 result <<= 16;
269
270 /* Place the decimal part into the low 16 bits. */
David Turner19ed8af2000-12-08 02:42:29 +0000271 if ( num )
Tom Kacvinskyc27cd282001-02-07 01:11:54 +0000272 result |= FT_DivFix( num, divider );
David Turner19ed8af2000-12-08 02:42:29 +0000273
274 if ( sign )
275 result = -result;
276
277 Exit:
278 return result;
279
280 Bad:
281 result = 0;
282 goto Exit;
283 }
284
285
286 /* read a number, either integer or real */
Werner Lembergcc069be2000-12-08 16:17:16 +0000287 static
288 FT_Long cff_parse_num( FT_Byte** d )
David Turner19ed8af2000-12-08 02:42:29 +0000289 {
290 return ( **d == 30 ? ( cff_parse_real ( d[0], d[1], 0 ) >> 16 )
291 : cff_parse_integer( d[0], d[1] ) );
292 }
293
294
Werner Lembergcc069be2000-12-08 16:17:16 +0000295 /* read a floating point number, either integer or real */
296 static
297 FT_Fixed cff_parse_fixed( FT_Byte** d )
David Turner19ed8af2000-12-08 02:42:29 +0000298 {
299 return ( **d == 30 ? cff_parse_real ( d[0], d[1], 0 )
300 : cff_parse_integer( d[0], d[1] ) << 16 );
301 }
302
Tom Kacvinskyc27cd282001-02-07 01:11:54 +0000303 /* read a floating point number, either integer or real, */
304 /* but return 1000 times the number read in. */
305 static
Werner Lemberg500dc852001-02-10 17:45:01 +0000306 FT_Fixed cff_parse_fixed_thousand( FT_Byte** d )
Tom Kacvinskyc27cd282001-02-07 01:11:54 +0000307 {
Werner Lemberg500dc852001-02-10 17:45:01 +0000308 return **d ==
309 30 ? cff_parse_real ( d[0], d[1], 3 )
310 : (FT_Fixed)FT_MulFix( cff_parse_integer( d[0], d[1] ) << 16, 1000 );
Tom Kacvinskyc27cd282001-02-07 01:11:54 +0000311 }
David Turner19ed8af2000-12-08 02:42:29 +0000312
Werner Lembergcc069be2000-12-08 16:17:16 +0000313 static
314 FT_Error cff_parse_font_matrix( CFF_Parser* parser )
David Turner19ed8af2000-12-08 02:42:29 +0000315 {
316 CFF_Font_Dict* dict = (CFF_Font_Dict*)parser->object;
317 FT_Matrix* matrix = &dict->font_matrix;
318 FT_Vector* offset = &dict->font_offset;
Tom Kacvinskyc27cd282001-02-07 01:11:54 +0000319 FT_UShort* upm = &dict->units_per_em;
David Turner19ed8af2000-12-08 02:42:29 +0000320 FT_Byte** data = parser->stack;
321 FT_Error error;
Tom Kacvinskya05c02c2000-12-24 09:57:28 +0000322 FT_Fixed temp;
David Turner19ed8af2000-12-08 02:42:29 +0000323
Werner Lemberg6b766632000-12-30 22:14:58 +0000324
Tom Kacvinsky8d1f6042001-01-03 00:21:59 +0000325 error = CFF_Err_Stack_Underflow;
David Turner19ed8af2000-12-08 02:42:29 +0000326
327 if ( parser->top >= parser->stack + 6 )
328 {
Tom Kacvinskyc27cd282001-02-07 01:11:54 +0000329 matrix->xx = cff_parse_fixed_thousand( data++ );
330 matrix->yx = cff_parse_fixed_thousand( data++ );
331 matrix->xy = cff_parse_fixed_thousand( data++ );
332 matrix->yy = cff_parse_fixed_thousand( data++ );
333 offset->x = cff_parse_fixed_thousand( data++ );
334 offset->y = cff_parse_fixed_thousand( data );
Tom Kacvinskya05c02c2000-12-24 09:57:28 +0000335
336 temp = ABS( matrix->yy );
337
David Turner09d55ce2001-05-11 18:08:58 +0000338 *upm = (FT_UShort)FT_DivFix( 0x10000L, FT_DivFix( temp, 1000 ) );
Tom Kacvinskyc27cd282001-02-07 01:11:54 +0000339
Tom Kacvinskya05c02c2000-12-24 09:57:28 +0000340 if ( temp != 0x10000L )
341 {
342 matrix->xx = FT_DivFix( matrix->xx, temp );
343 matrix->yx = FT_DivFix( matrix->yx, temp );
344 matrix->xy = FT_DivFix( matrix->xy, temp );
345 matrix->yy = FT_DivFix( matrix->yy, temp );
346 offset->x = FT_DivFix( offset->x, temp );
347 offset->y = FT_DivFix( offset->y, temp );
348 }
349
350 /* note that the offsets must be expressed in integer font units */
351 offset->x >>= 16;
352 offset->y >>= 16;
353
Tom Kacvinsky8d1f6042001-01-03 00:21:59 +0000354 error = CFF_Err_Ok;
David Turner19ed8af2000-12-08 02:42:29 +0000355 }
356
357 return error;
358 }
359
360
Werner Lembergcc069be2000-12-08 16:17:16 +0000361 static
362 FT_Error cff_parse_font_bbox( CFF_Parser* parser )
David Turner19ed8af2000-12-08 02:42:29 +0000363 {
364 CFF_Font_Dict* dict = (CFF_Font_Dict*)parser->object;
365 FT_BBox* bbox = &dict->font_bbox;
366 FT_Byte** data = parser->stack;
367 FT_Error error;
368
369
Tom Kacvinsky8d1f6042001-01-03 00:21:59 +0000370 error = CFF_Err_Stack_Underflow;
David Turner19ed8af2000-12-08 02:42:29 +0000371
372 if ( parser->top >= parser->stack + 4 )
373 {
Tom Kacvinskyc24eff82001-03-17 19:01:25 +0000374 bbox->xMin = FT_RoundFix( cff_parse_fixed( data++ ) );
375 bbox->yMin = FT_RoundFix( cff_parse_fixed( data++ ) );
376 bbox->xMax = FT_RoundFix( cff_parse_fixed( data++ ) );
377 bbox->yMax = FT_RoundFix( cff_parse_fixed( data ) );
Tom Kacvinsky8d1f6042001-01-03 00:21:59 +0000378 error = CFF_Err_Ok;
David Turner19ed8af2000-12-08 02:42:29 +0000379 }
380
381 return error;
382 }
383
384
Werner Lembergcc069be2000-12-08 16:17:16 +0000385 static
386 FT_Error cff_parse_private_dict( CFF_Parser* parser )
David Turner19ed8af2000-12-08 02:42:29 +0000387 {
388 CFF_Font_Dict* dict = (CFF_Font_Dict*)parser->object;
389 FT_Byte** data = parser->stack;
390 FT_Error error;
391
392
Tom Kacvinsky8d1f6042001-01-03 00:21:59 +0000393 error = CFF_Err_Stack_Underflow;
David Turner19ed8af2000-12-08 02:42:29 +0000394
395 if ( parser->top >= parser->stack + 2 )
396 {
397 dict->private_size = cff_parse_num( data++ );
398 dict->private_offset = cff_parse_num( data );
Tom Kacvinsky8d1f6042001-01-03 00:21:59 +0000399 error = CFF_Err_Ok;
David Turner19ed8af2000-12-08 02:42:29 +0000400 }
401
402 return error;
403 }
404
405
Werner Lembergcc069be2000-12-08 16:17:16 +0000406 static
407 FT_Error cff_parse_cid_ros( CFF_Parser* parser )
David Turner19ed8af2000-12-08 02:42:29 +0000408 {
409 CFF_Font_Dict* dict = (CFF_Font_Dict*)parser->object;
410 FT_Byte** data = parser->stack;
411 FT_Error error;
412
413
Tom Kacvinsky8d1f6042001-01-03 00:21:59 +0000414 error = CFF_Err_Stack_Underflow;
David Turner19ed8af2000-12-08 02:42:29 +0000415
416 if ( parser->top >= parser->stack + 3 )
417 {
418 dict->cid_registry = (FT_UInt)cff_parse_num ( data++ );
419 dict->cid_ordering = (FT_UInt)cff_parse_num ( data++ );
420 dict->cid_supplement = (FT_ULong)cff_parse_num( data );
Tom Kacvinsky8d1f6042001-01-03 00:21:59 +0000421 error = CFF_Err_Ok;
David Turner19ed8af2000-12-08 02:42:29 +0000422 }
423
424 return error;
425 }
426
427
428#define CFF_FIELD_NUM( code, name ) \
429 CFF_FIELD( code, name, cff_kind_num )
430#define CFF_FIELD_FIXED( code, name ) \
431 CFF_FIELD( code, name, cff_kind_fixed )
432#define CFF_FIELD_STRING( code, name ) \
433 CFF_FIELD( code, name, cff_kind_string )
434#define CFF_FIELD_BOOL( code, name ) \
435 CFF_FIELD( code, name, cff_kind_bool )
436#define CFF_FIELD_DELTA( code, name, max ) \
437 CFF_FIELD( code, name, cff_kind_delta )
438
439#define CFF_FIELD_CALLBACK( code, name ) \
440 { \
441 cff_kind_callback, \
442 code | CFFCODE, \
443 0, 0, \
444 cff_parse_ ## name, \
445 0, 0 \
446 },
447
448#undef CFF_FIELD
449#define CFF_FIELD( code, name, kind ) \
450 { \
451 kind, \
452 code | CFFCODE, \
453 FT_FIELD_OFFSET( name ), \
454 FT_FIELD_SIZE( name ), \
455 0, 0, 0 \
456 },
457
458#undef CFF_FIELD_DELTA
459#define CFF_FIELD_DELTA( code, name, max ) \
460 { \
461 cff_kind_delta, \
462 code | CFFCODE, \
463 FT_FIELD_OFFSET( name ), \
464 FT_FIELD_SIZE_DELTA( name ), \
465 0, \
466 max, \
467 FT_FIELD_OFFSET( num_ ## name ) \
468 },
469
470#define CFFCODE_TOPDICT 0x1000
471#define CFFCODE_PRIVATE 0x2000
472
473 static const CFF_Field_Handler cff_field_handlers[] =
474 {
475
David Turner8d3a4012001-03-20 11:14:24 +0000476#include "cfftoken.h"
David Turner19ed8af2000-12-08 02:42:29 +0000477
478 { 0, 0, 0, 0, 0, 0, 0 }
479 };
480
481
Werner Lembergcc069be2000-12-08 16:17:16 +0000482 FT_LOCAL_DEF
483 FT_Error CFF_Parser_Run( CFF_Parser* parser,
484 FT_Byte* start,
485 FT_Byte* limit )
David Turner19ed8af2000-12-08 02:42:29 +0000486 {
487 FT_Byte* p = start;
Tom Kacvinsky8d1f6042001-01-03 00:21:59 +0000488 FT_Error error = CFF_Err_Ok;
David Turner19ed8af2000-12-08 02:42:29 +0000489
490
491 parser->top = parser->stack;
492 parser->start = start;
493 parser->limit = limit;
494 parser->cursor = start;
495
496 while ( p < limit )
497 {
David Turner8edbcab2001-06-19 08:28:24 +0000498 FT_UInt v = *p;
David Turner19ed8af2000-12-08 02:42:29 +0000499
500
501 if ( v >= 27 && v != 31 )
502 {
503 /* it's a number; we will push its position on the stack */
504 if ( parser->top - parser->stack >= CFF_MAX_STACK_DEPTH )
505 goto Stack_Overflow;
506
507 *parser->top ++ = p;
508
509 /* now, skip it */
510 if ( v == 30 )
511 {
512 /* skip real number */
513 p++;
514 for (;;)
515 {
516 if ( p >= limit )
517 goto Syntax_Error;
518 v = p[0] >> 4;
519 if ( v == 15 )
520 break;
521 v = p[0] & 0xF;
522 if ( v == 15 )
523 break;
524 p++;
525 }
526 }
527 else if ( v == 28 )
528 p += 2;
529 else if ( v == 29 )
530 p += 4;
531 else if ( v > 246 )
532 p += 1;
533 }
534 else
535 {
536 /* This is not a number, hence it's an operator. Compute its code */
537 /* and look for it in our current list. */
538
Werner Lembergcc069be2000-12-08 16:17:16 +0000539 FT_UInt code;
540 FT_UInt num_args = (FT_UInt)
541 ( parser->top - parser->stack );
David Turner19ed8af2000-12-08 02:42:29 +0000542 const CFF_Field_Handler* field;
543
544
545 /* first of all, a trivial check */
546 if ( num_args < 1 )
547 goto Stack_Underflow;
548
549 *parser->top = p;
550 code = v;
551 if ( v == 12 )
552 {
553 /* two byte operator */
554 p++;
555 code = 0x100 | p[0];
556 }
557 code = code | parser->object_code;
558
559 for ( field = cff_field_handlers; field->kind; field++ )
560 {
561 if ( field->code == (FT_Int)code )
562 {
563 /* we found our field's handler; read it */
564 FT_Long val;
565 FT_Byte* q = (FT_Byte*)parser->object + field->offset;
566
Werner Lembergcc069be2000-12-08 16:17:16 +0000567
David Turner19ed8af2000-12-08 02:42:29 +0000568 switch ( field->kind )
569 {
570 case cff_kind_bool:
571 case cff_kind_string:
572 case cff_kind_num:
573 val = cff_parse_num( parser->stack );
574 goto Store_Number;
575
576 case cff_kind_fixed:
577 val = cff_parse_fixed( parser->stack );
578
579 Store_Number:
580 switch ( field->size )
581 {
582 case 1:
583 *(FT_Byte*)q = (FT_Byte)val;
584 break;
585
586 case 2:
587 *(FT_Short*)q = (FT_Short)val;
588 break;
589
590 case 4:
591 *(FT_Int32*)q = (FT_Int)val;
592 break;
593
594 default: /* for 64-bit systems where long is 8 bytes */
595 *(FT_Long*)q = val;
596 }
597 break;
598
599 case cff_kind_delta:
600 {
601 FT_Byte* qcount = (FT_Byte*)parser->object +
602 field->count_offset;
603
604 FT_Byte** data = parser->stack;
605
606
607 if ( num_args > field->array_max )
608 num_args = field->array_max;
609
610 /* store count */
611 *qcount = (FT_Byte)num_args;
612
613 val = 0;
614 while ( num_args > 0 )
615 {
616 val += cff_parse_num( data++ );
617 switch ( field->size )
618 {
619 case 1:
620 *(FT_Byte*)q = (FT_Byte)val;
621 break;
622
623 case 2:
624 *(FT_Short*)q = (FT_Short)val;
625 break;
626
627 case 4:
628 *(FT_Int32*)q = (FT_Int)val;
629 break;
630
631 default: /* for 64-bit systems */
632 *(FT_Long*)q = val;
633 }
634
635 q += field->size;
636 num_args--;
637 }
638 }
639 break;
640
641 default: /* callback */
642 error = field->reader( parser );
643 if ( error )
644 goto Exit;
645 }
646 goto Found;
647 }
648 }
649
650 /* this is an unknown operator, or it is unsupported; */
651 /* we will ignore it for now. */
652
653 Found:
654 /* clear stack */
655 parser->top = parser->stack;
656 }
657 p++;
658 }
659
660 Exit:
661 return error;
662
663 Stack_Overflow:
Tom Kacvinsky8d1f6042001-01-03 00:21:59 +0000664 error = CFF_Err_Invalid_Argument;
David Turner19ed8af2000-12-08 02:42:29 +0000665 goto Exit;
666
667 Stack_Underflow:
Tom Kacvinsky8d1f6042001-01-03 00:21:59 +0000668 error = CFF_Err_Invalid_Argument;
David Turner19ed8af2000-12-08 02:42:29 +0000669 goto Exit;
670
671 Syntax_Error:
Tom Kacvinsky8d1f6042001-01-03 00:21:59 +0000672 error = CFF_Err_Invalid_Argument;
David Turner19ed8af2000-12-08 02:42:29 +0000673 goto Exit;
674 }
675
676
677/* END */