]> git.saurik.com Git - wxWidgets.git/blame - src/freetype/cff/t2parse.c
Doc/distribution script mods
[wxWidgets.git] / src / freetype / cff / t2parse.c
CommitLineData
cabec872
RR
1/***************************************************************************/
2/* */
3/* t2parse.c */
4/* */
5/* OpenType 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
18
19#ifdef FT_FLAT_COMPILE
20
21#include "t2parse.h"
22
23#else
24
25#include <cff/t2parse.h>
26
27#endif
28
29
30#include <freetype/internal/t2errors.h>
31
32
33 /*************************************************************************/
34 /* */
35 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
36 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
37 /* messages during execution. */
38 /* */
39#undef FT_COMPONENT
40#define FT_COMPONENT trace_t2parse
41
42
43#define T2_Err_Stack_Underflow FT_Err_Invalid_Argument
44#define T2_Err_Syntax_Error FT_Err_Invalid_Argument
45
46
47 enum
48 {
49 t2_kind_none = 0,
50 t2_kind_num,
51 t2_kind_fixed,
52 t2_kind_string,
53 t2_kind_bool,
54 t2_kind_delta,
55 t2_kind_callback,
56
57 t2_kind_max /* do not remove */
58 };
59
60
61 /* now generate handlers for the most simple fields */
62 typedef FT_Error (*T2_Field_Reader)( T2_Parser* parser );
63
64 typedef struct T2_Field_Handler_
65 {
66 int kind;
67 int code;
68 FT_UInt offset;
69 FT_Byte size;
70 T2_Field_Reader reader;
71 FT_UInt array_max;
72 FT_UInt count_offset;
73
74 } T2_Field_Handler;
75
76
77 LOCAL_FUNC
78 void T2_Parser_Init( T2_Parser* parser,
79 FT_UInt code,
80 void* object )
81 {
82 MEM_Set( parser, 0, sizeof ( *parser ) );
83
84 parser->top = parser->stack;
85 parser->object_code = code;
86 parser->object = object;
87 }
88
89
90 /* reads an integer */
91 static
92 FT_Long parse_t2_integer( FT_Byte* start,
93 FT_Byte* limit )
94 {
95 FT_Byte* p = start;
96 FT_Int v = *p++;
97 FT_Long val = 0;
98
99
100 if ( v == 28 )
101 {
102 if ( p + 2 > limit )
103 goto Bad;
104
105 val = (FT_Short)( ( (FT_Int)p[0] << 8 ) | p[1] );
106 p += 2;
107 }
108 else if ( v == 29 )
109 {
110 if ( p + 4 > limit )
111 goto Bad;
112
113 val = ( (FT_Long)p[0] << 24 ) |
114 ( (FT_Long)p[1] << 16 ) |
115 ( (FT_Long)p[2] << 8 ) |
116 p[3];
117 p += 4;
118 }
119 else if ( v < 247 )
120 {
121 val = v - 139;
122 }
123 else if ( v < 251 )
124 {
125 if ( p + 1 > limit )
126 goto Bad;
127
128 val = ( v - 247 ) * 256 + p[0] + 108;
129 p++;
130 }
131 else
132 {
133 if ( p + 1 > limit )
134 goto Bad;
135
136 val = -( v - 251 ) * 256 - p[0] - 108;
137 p++;
138 }
139
140 Exit:
141 return val;
142
143 Bad:
144 val = 0;
145 goto Exit;
146 }
147
148
149 /* read a real */
150 static
151 FT_Fixed parse_t2_real( FT_Byte* start,
152 FT_Byte* limit,
153 FT_Int power_ten )
154 {
155 FT_Byte* p = start;
156 FT_Long num, divider, result, exp;
157 FT_Int sign = 0, exp_sign = 0;
158 FT_Byte nib;
159 FT_Byte phase;
160
161
162 result = 0;
163 num = 0;
164 divider = 1;
165
166 /* first of all, read the integer part */
167 phase = 4;
168 p--;
169
170 for (;;)
171 {
172 /* read one nibble at a time */
173 if ( phase && ++p >= limit )
174 goto Bad;
175
176 nib = ( p[0] >> phase ) & 0xF;
177 phase = 4 - phase;
178
179 if ( nib == 0xE )
180 sign = 1;
181 else if ( nib > 9 )
182 break;
183 else
184 result = result * 10 + nib;
185 }
186
187 /* read decimal part, if any */
188 if ( nib == 0xa )
189 for (;;)
190 {
191 /* read one nibble at a time */
192 if ( !phase && ++p >= limit )
193 goto Bad;
194
195 phase = 4 - phase;
196 nib = ( p[0] >> phase ) & 0xF;
197
198 if ( nib >= 10 )
199 break;
200
201 if (divider < 10000000L)
202 {
203 num = num * 10 + nib;
204 divider *= 10;
205 }
206 }
207
208 /* read exponent, if any */
209 if ( nib == 12 )
210 {
211 exp_sign = 1;
212 nib = 11;
213 }
214
215 if ( nib == 11 )
216 {
217 exp = 0;
218
219 for (;;)
220 {
221 /* read one nibble at a time */
222 if ( !phase && ++p >= limit )
223 goto Bad;
224
225 phase = 4 - phase;
226 nib = ( p[0] >> phase ) & 0xF;
227
228 if ( nib >= 10 )
229 break;
230
231 exp = exp * 10 + nib;
232 }
233
234 if ( exp_sign )
235 exp = -exp;
236
237 power_ten += exp;
238 }
239
240 /* raise to power of ten if needed */
241 while ( power_ten > 0 )
242 {
243 result = result * 10;
244 num = num * 10;
245
246 power_ten--;
247 }
248
249 while ( power_ten < 0 )
250 {
251 result = result / 10;
252 divider = divider * 10;
253
254 power_ten++;
255 }
256
257 if ( num )
258 result += FT_DivFix( num, divider );
259
260 if ( sign )
261 result = -result;
262
263 Exit:
264 return result;
265
266 Bad:
267 result = 0;
268 goto Exit;
269 }
270
271
272 /* read a number, either integer or real */
273 static
274 FT_Long t2_parse_num( FT_Byte** d )
275 {
276 return ( **d == 30 ? ( parse_t2_real( d[0], d[1], 0 ) >> 16 )
277 : parse_t2_integer( d[0], d[1] ) );
278 }
279
280
281 /* reads a floating point number, either integer or real */
282 static
283 FT_Fixed t2_parse_fixed( FT_Byte** d )
284 {
285 return ( **d == 30 ? parse_t2_real( d[0], d[1], 0 )
286 : parse_t2_integer( d[0], d[1] ) << 16 );
287 }
288
289
290 static
291 FT_Error parse_font_matrix( T2_Parser* parser )
292 {
293 CFF_Font_Dict* dict = (CFF_Font_Dict*)parser->object;
294 FT_Matrix* matrix = &dict->font_matrix;
295 FT_Byte** data = parser->stack;
296 FT_Error error;
297
298
299 error = T2_Err_Stack_Underflow;
300
301 if ( parser->top >= parser->stack + 4 )
302 {
303 matrix->xx = t2_parse_fixed( data++ );
304 matrix->yx = t2_parse_fixed( data++ );
305 matrix->xy = t2_parse_fixed( data++ );
306 matrix->yy = t2_parse_fixed( data );
307 error = T2_Err_Ok;
308 }
309
310 return error;
311 }
312
313
314 static
315 FT_Error parse_font_bbox( T2_Parser* parser )
316 {
317 CFF_Font_Dict* dict = (CFF_Font_Dict*)parser->object;
318 FT_BBox* bbox = &dict->font_bbox;
319 FT_Byte** data = parser->stack;
320 FT_Error error;
321
322
323 error = T2_Err_Stack_Underflow;
324
325 if ( parser->top >= parser->stack + 4 )
326 {
327 bbox->xMin = t2_parse_num( data++ );
328 bbox->yMin = t2_parse_num( data++ );
329 bbox->xMax = t2_parse_num( data++ );
330 bbox->yMax = t2_parse_num( data );
331 error = T2_Err_Ok;
332 }
333
334 return error;
335 }
336
337
338 static
339 FT_Error parse_private_dict( T2_Parser* parser )
340 {
341 CFF_Font_Dict* dict = (CFF_Font_Dict*)parser->object;
342 FT_Byte** data = parser->stack;
343 FT_Error error;
344
345
346 error = T2_Err_Stack_Underflow;
347
348 if ( parser->top >= parser->stack + 2 )
349 {
350 dict->private_size = t2_parse_num( data++ );
351 dict->private_offset = t2_parse_num( data );
352 error = T2_Err_Ok;
353 }
354
355 return error;
356 }
357
358
359 static
360 FT_Error parse_cid_ros( T2_Parser* parser )
361 {
362 CFF_Font_Dict* dict = (CFF_Font_Dict*)parser->object;
363 FT_Byte** data = parser->stack;
364 FT_Error error;
365
366
367 error = T2_Err_Stack_Underflow;
368
369 if ( parser->top >= parser->stack + 3 )
370 {
371 dict->cid_registry = (FT_UInt)t2_parse_num( data++ );
372 dict->cid_ordering = (FT_UInt)t2_parse_num( data++ );
373 dict->cid_supplement = (FT_ULong)t2_parse_num( data );
374 error = T2_Err_Ok;
375 }
376
377 return error;
378 }
379
380
381#define T2_FIELD_NUM( code, name ) \
382 T2_FIELD( code, name, t2_kind_num )
383#define T2_FIELD_FIXED( code, name ) \
384 T2_FIELD( code, name, t2_kind_fixed )
385#define T2_FIELD_STRING( code, name ) \
386 T2_FIELD( code, name, t2_kind_string )
387#define T2_FIELD_BOOL( code, name ) \
388 T2_FIELD( code, name, t2_kind_bool )
389#define T2_FIELD_DELTA( code, name,max ) \
390 T2_FIELD( code, name, t2_kind_delta )
391
392#define T2_REF( s, f ) ( ((s*)0)->f )
393
394#define T2_FIELD_CALLBACK( code, name ) \
395 { \
396 t2_kind_callback, \
397 code | T2CODE, \
398 0, 0, \
399 parse_ ## name, \
400 0, 0 \
401 },
402
403#undef T2_FIELD
404#define T2_FIELD( code, name, kind ) \
405 { \
406 kind, \
407 code | T2CODE, \
408 (FT_UInt)(char*)&T2_REF( T2TYPE, name ), \
409 sizeof( T2_REF( T2TYPE, name ) ), \
410 0, 0, 0 \
411 },
412
413#undef T2_FIELD_DELTA
414#define T2_FIELD_DELTA( code, name, max ) \
415 { \
416 t2_kind_delta, \
417 code | T2CODE, \
418 (FT_UInt)(char*)&T2_REF( T2TYPE, name ), \
419 sizeof( T2_REF( T2TYPE, name )[0] ), \
420 0, \
421 max, \
422 (FT_UInt)(char*)&T2_REF( T2TYPE, num_ ## name ) \
423 },
424
425#define T2CODE_TOPDICT 0x1000
426#define T2CODE_PRIVATE 0x2000
427
428 static const T2_Field_Handler t2_field_handlers[] =
429 {
430
431#ifdef FT_FLAT_COMPILE
432
433#include "t2tokens.h"
434
435#else
436
437#include <cff/t2tokens.h>
438
439#endif
440
441 { 0, 0, 0, 0, 0, 0, 0 }
442 };
443
444
445 LOCAL_FUNC
446 FT_Error T2_Parser_Run( T2_Parser* parser,
447 FT_Byte* start,
448 FT_Byte* limit )
449 {
450 FT_Byte* p = start;
451 FT_Error error = T2_Err_Ok;
452
453
454 parser->top = parser->stack;
455 parser->start = start;
456 parser->limit = limit;
457 parser->cursor = start;
458
459 while ( p < limit )
460 {
461 FT_Byte v = *p;
462
463
464 if ( v >= 27 && v != 31 )
465 {
466 /* it's a number; we will push its position on the stack */
467 if ( parser->top - parser->stack >= T2_MAX_STACK_DEPTH )
468 goto Stack_Overflow;
469
470 *parser->top ++ = p;
471
472 /* now, skip it */
473 if ( v == 30 )
474 {
475 /* skip real number */
476 for (;;)
477 {
478 if ( p >= limit )
479 goto Syntax_Error;
480 v = p[0] >> 4;
481 if ( v == 15 )
482 break;
483 v = p[0] & 0xF;
484 if ( v == 15 )
485 break;
486 p++;
487 }
488 p++;
489 }
490 else if ( v == 28 )
491 p += 2;
492 else if ( v == 29 )
493 p += 4;
494 else if ( v > 246 )
495 p += 1;
496 }
497 else
498 {
499 /* This is not a number, hence it's an operator. Compute its code */
500 /* and look for it in our current list. */
501
502 FT_UInt code;
503 FT_UInt num_args = (FT_UInt)
504 ( parser->top - parser->stack );
505 const T2_Field_Handler* field;
506
507
508 /* first of all, a trivial check */
509 if ( num_args < 1 )
510 goto Stack_Underflow;
511
512 *parser->top = p;
513 code = v;
514 if ( v == 12 )
515 {
516 /* two byte operator */
517 p++;
518 code = 0x100 | p[0];
519 }
520 code = code | parser->object_code;
521
522 for ( field = t2_field_handlers; field->kind; field++ )
523 {
524 if ( field->code == (FT_Int)code )
525 {
526 /* we found our field's handler; read it */
527 FT_Long val;
528 FT_Byte* q = (FT_Byte*)parser->object + field->offset;
529
530
531 switch ( field->kind )
532 {
533 case t2_kind_bool:
534 case t2_kind_string:
535 case t2_kind_num:
536 val = t2_parse_num( parser->stack );
537 goto Store_Number;
538
539 case t2_kind_fixed:
540 val = t2_parse_fixed( parser->stack );
541
542 Store_Number:
543 switch ( field->size )
544 {
545 case 1:
546 *(FT_Byte*)q = (FT_Byte)val;
547 break;
548
549 case 2:
550 *(FT_Short*)q = (FT_Short)val;
551 break;
552
553 case 4:
554 *(FT_Int32*)q = (FT_Int)val;
555 break;
556
557 default: /* for 64-bit systems where long is 8 bytes */
558 *(FT_Long*)q = val;
559 }
560 break;
561
562 case t2_kind_delta:
563 {
564 FT_Byte* qcount = (FT_Byte*)parser->object +
565 field->count_offset;
566
567 FT_Long val;
568 FT_Byte** data = parser->stack;
569
570
571 if ( num_args > field->array_max )
572 num_args = field->array_max;
573
574 /* store count */
575 *qcount = (FT_Byte)num_args;
576
577 val = 0;
578 while ( num_args > 0 )
579 {
580 val += t2_parse_num( data++ );
581 switch ( field->size )
582 {
583 case 1:
584 *(FT_Byte*)q = (FT_Byte)val;
585 break;
586
587 case 2:
588 *(FT_Short*)q = (FT_Short)val;
589 break;
590
591 case 4:
592 *(FT_Int32*)q = (FT_Int)val;
593 break;
594
595 default: /* for 64-bit systems */
596 *(FT_Long*)q = val;
597 }
598
599 q += field->size;
600 num_args--;
601 }
602 }
603 break;
604
605 default: /* callback */
606 error = field->reader( parser );
607 if ( error )
608 goto Exit;
609 }
610 goto Found;
611 }
612 }
613
614 /* this is an unknown operator, or it is unsupported; */
615 /* we will ignore it for now. */
616
617 Found:
618 /* clear stack */
619 parser->top = parser->stack;
620 }
621 p++;
622 }
623
624 Exit:
625 return error;
626
627 Stack_Overflow:
628 error = T2_Err_Invalid_Argument;
629 goto Exit;
630
631 Stack_Underflow:
632 error = T2_Err_Invalid_Argument;
633 goto Exit;
634
635 Syntax_Error:
636 error = T2_Err_Invalid_Argument;
637 goto Exit;
638 }
639
640
641/* END */