• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /***************************************************************************/
2 /*                                                                         */
3 /*  cffparse.c                                                             */
4 /*                                                                         */
5 /*    CFF token stream parser (body)                                       */
6 /*                                                                         */
7 /*  Copyright 1996-2001, 2002, 2003, 2004, 2007, 2008, 2009, 2010 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 #include <ft2build.h>
20 #include "cffparse.h"
21 #include FT_INTERNAL_STREAM_H
22 #include FT_INTERNAL_DEBUG_H
23 
24 #include "cfferrs.h"
25 #include "cffpic.h"
26 
27 
28   /*************************************************************************/
29   /*                                                                       */
30   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
31   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
32   /* messages during execution.                                            */
33   /*                                                                       */
34 #undef  FT_COMPONENT
35 #define FT_COMPONENT  trace_cffparse
36 
37 
38 
39 
40   FT_LOCAL_DEF( void )
cff_parser_init(CFF_Parser parser,FT_UInt code,void * object,FT_Library library)41   cff_parser_init( CFF_Parser  parser,
42                    FT_UInt     code,
43                    void*       object,
44                    FT_Library  library)
45   {
46     FT_MEM_ZERO( parser, sizeof ( *parser ) );
47 
48     parser->top         = parser->stack;
49     parser->object_code = code;
50     parser->object      = object;
51     parser->library     = library;
52   }
53 
54 
55   /* read an integer */
56   static FT_Long
cff_parse_integer(FT_Byte * start,FT_Byte * limit)57   cff_parse_integer( FT_Byte*  start,
58                      FT_Byte*  limit )
59   {
60     FT_Byte*  p   = start;
61     FT_Int    v   = *p++;
62     FT_Long   val = 0;
63 
64 
65     if ( v == 28 )
66     {
67       if ( p + 2 > limit )
68         goto Bad;
69 
70       val = (FT_Short)( ( (FT_Int)p[0] << 8 ) | p[1] );
71       p  += 2;
72     }
73     else if ( v == 29 )
74     {
75       if ( p + 4 > limit )
76         goto Bad;
77 
78       val = ( (FT_Long)p[0] << 24 ) |
79             ( (FT_Long)p[1] << 16 ) |
80             ( (FT_Long)p[2] <<  8 ) |
81                        p[3];
82       p += 4;
83     }
84     else if ( v < 247 )
85     {
86       val = v - 139;
87     }
88     else if ( v < 251 )
89     {
90       if ( p + 1 > limit )
91         goto Bad;
92 
93       val = ( v - 247 ) * 256 + p[0] + 108;
94       p++;
95     }
96     else
97     {
98       if ( p + 1 > limit )
99         goto Bad;
100 
101       val = -( v - 251 ) * 256 - p[0] - 108;
102       p++;
103     }
104 
105   Exit:
106     return val;
107 
108   Bad:
109     val = 0;
110     goto Exit;
111   }
112 
113 
114   static const FT_Long power_tens[] =
115   {
116     1L,
117     10L,
118     100L,
119     1000L,
120     10000L,
121     100000L,
122     1000000L,
123     10000000L,
124     100000000L,
125     1000000000L
126   };
127 
128 
129   /* read a real */
130   static FT_Fixed
cff_parse_real(FT_Byte * start,FT_Byte * limit,FT_Long power_ten,FT_Long * scaling)131   cff_parse_real( FT_Byte*  start,
132                   FT_Byte*  limit,
133                   FT_Long   power_ten,
134                   FT_Long*  scaling )
135   {
136     FT_Byte*  p = start;
137     FT_UInt   nib;
138     FT_UInt   phase;
139 
140     FT_Long   result, number, exponent;
141     FT_Int    sign = 0, exponent_sign = 0;
142     FT_Long   exponent_add, integer_length, fraction_length;
143 
144 
145     if ( scaling )
146       *scaling = 0;
147 
148     result = 0;
149 
150     number   = 0;
151     exponent = 0;
152 
153     exponent_add    = 0;
154     integer_length  = 0;
155     fraction_length = 0;
156 
157     /* First of all, read the integer part. */
158     phase = 4;
159 
160     for (;;)
161     {
162       /* If we entered this iteration with phase == 4, we need to */
163       /* read a new byte.  This also skips past the initial 0x1E. */
164       if ( phase )
165       {
166         p++;
167 
168         /* Make sure we don't read past the end. */
169         if ( p >= limit )
170           goto Exit;
171       }
172 
173       /* Get the nibble. */
174       nib   = ( p[0] >> phase ) & 0xF;
175       phase = 4 - phase;
176 
177       if ( nib == 0xE )
178         sign = 1;
179       else if ( nib > 9 )
180         break;
181       else
182       {
183         /* Increase exponent if we can't add the digit. */
184         if ( number >= 0xCCCCCCCL )
185           exponent_add++;
186         /* Skip leading zeros. */
187         else if ( nib || number )
188         {
189           integer_length++;
190           number = number * 10 + nib;
191         }
192       }
193     }
194 
195     /* Read fraction part, if any. */
196     if ( nib == 0xa )
197       for (;;)
198       {
199         /* If we entered this iteration with phase == 4, we need */
200         /* to read a new byte.                                   */
201         if ( phase )
202         {
203           p++;
204 
205           /* Make sure we don't read past the end. */
206           if ( p >= limit )
207             goto Exit;
208         }
209 
210         /* Get the nibble. */
211         nib   = ( p[0] >> phase ) & 0xF;
212         phase = 4 - phase;
213         if ( nib >= 10 )
214           break;
215 
216         /* Skip leading zeros if possible. */
217         if ( !nib && !number )
218           exponent_add--;
219         /* Only add digit if we don't overflow. */
220         else if ( number < 0xCCCCCCCL && fraction_length < 9 )
221         {
222           fraction_length++;
223           number = number * 10 + nib;
224         }
225       }
226 
227     /* Read exponent, if any. */
228     if ( nib == 12 )
229     {
230       exponent_sign = 1;
231       nib           = 11;
232     }
233 
234     if ( nib == 11 )
235     {
236       for (;;)
237       {
238         /* If we entered this iteration with phase == 4, */
239         /* we need to read a new byte.                   */
240         if ( phase )
241         {
242           p++;
243 
244           /* Make sure we don't read past the end. */
245           if ( p >= limit )
246             goto Exit;
247         }
248 
249         /* Get the nibble. */
250         nib   = ( p[0] >> phase ) & 0xF;
251         phase = 4 - phase;
252         if ( nib >= 10 )
253           break;
254 
255         exponent = exponent * 10 + nib;
256 
257         /* Arbitrarily limit exponent. */
258         if ( exponent > 1000 )
259           goto Exit;
260       }
261 
262       if ( exponent_sign )
263         exponent = -exponent;
264     }
265 
266     /* We don't check `power_ten' and `exponent_add'. */
267     exponent += power_ten + exponent_add;
268 
269     if ( scaling )
270     {
271       /* Only use `fraction_length'. */
272       fraction_length += integer_length;
273       exponent        += integer_length;
274 
275       if ( fraction_length <= 5 )
276       {
277         if ( number > 0x7FFFL )
278         {
279           result   = FT_DivFix( number, 10 );
280           *scaling = exponent - fraction_length + 1;
281         }
282         else
283         {
284           if ( exponent > 0 )
285           {
286             FT_Long  new_fraction_length, shift;
287 
288 
289             /* Make `scaling' as small as possible. */
290             new_fraction_length = FT_MIN( exponent, 5 );
291             exponent           -= new_fraction_length;
292             shift               = new_fraction_length - fraction_length;
293 
294             number *= power_tens[shift];
295             if ( number > 0x7FFFL )
296             {
297               number   /= 10;
298               exponent += 1;
299             }
300           }
301           else
302             exponent -= fraction_length;
303 
304           result   = number << 16;
305           *scaling = exponent;
306         }
307       }
308       else
309       {
310         if ( ( number / power_tens[fraction_length - 5] ) > 0x7FFFL )
311         {
312           result   = FT_DivFix( number, power_tens[fraction_length - 4] );
313           *scaling = exponent - 4;
314         }
315         else
316         {
317           result   = FT_DivFix( number, power_tens[fraction_length - 5] );
318           *scaling = exponent - 5;
319         }
320       }
321     }
322     else
323     {
324       integer_length  += exponent;
325       fraction_length -= exponent;
326 
327       /* Check for overflow and underflow. */
328       if ( FT_ABS( integer_length ) > 5 )
329         goto Exit;
330 
331       /* Remove non-significant digits. */
332       if ( integer_length < 0 )
333       {
334         number          /= power_tens[-integer_length];
335         fraction_length += integer_length;
336       }
337 
338       /* this can only happen if exponent was non-zero */
339       if ( fraction_length == 10 )
340       {
341         number          /= 10;
342         fraction_length -= 1;
343       }
344 
345       /* Convert into 16.16 format. */
346       if ( fraction_length > 0 )
347       {
348         if ( ( number / power_tens[fraction_length] ) > 0x7FFFL )
349           goto Exit;
350 
351         result = FT_DivFix( number, power_tens[fraction_length] );
352       }
353       else
354       {
355         number *= power_tens[-fraction_length];
356 
357         if ( number > 0x7FFFL )
358           goto Exit;
359 
360         result = number << 16;
361       }
362     }
363 
364     if ( sign )
365       result = -result;
366 
367   Exit:
368     return result;
369   }
370 
371 
372   /* read a number, either integer or real */
373   static FT_Long
cff_parse_num(FT_Byte ** d)374   cff_parse_num( FT_Byte**  d )
375   {
376     return **d == 30 ? ( cff_parse_real( d[0], d[1], 0, NULL ) >> 16 )
377                      :   cff_parse_integer( d[0], d[1] );
378   }
379 
380 
381   /* read a floating point number, either integer or real */
382   static FT_Fixed
cff_parse_fixed(FT_Byte ** d)383   cff_parse_fixed( FT_Byte**  d )
384   {
385     return **d == 30 ? cff_parse_real( d[0], d[1], 0, NULL )
386                      : cff_parse_integer( d[0], d[1] ) << 16;
387   }
388 
389 
390   /* read a floating point number, either integer or real, */
391   /* but return `10^scaling' times the number read in      */
392   static FT_Fixed
cff_parse_fixed_scaled(FT_Byte ** d,FT_Long scaling)393   cff_parse_fixed_scaled( FT_Byte**  d,
394                           FT_Long    scaling )
395   {
396     return **d == 30 ? cff_parse_real( d[0], d[1], scaling, NULL )
397                      : ( cff_parse_integer( d[0], d[1] ) *
398                            power_tens[scaling] ) << 16;
399   }
400 
401 
402   /* read a floating point number, either integer or real,     */
403   /* and return it as precise as possible -- `scaling' returns */
404   /* the scaling factor (as a power of 10)                     */
405   static FT_Fixed
cff_parse_fixed_dynamic(FT_Byte ** d,FT_Long * scaling)406   cff_parse_fixed_dynamic( FT_Byte**  d,
407                            FT_Long*   scaling )
408   {
409     FT_ASSERT( scaling );
410 
411     if ( **d == 30 )
412       return cff_parse_real( d[0], d[1], 0, scaling );
413     else
414     {
415       FT_Long  number;
416       FT_Int   integer_length;
417 
418 
419       number = cff_parse_integer( d[0], d[1] );
420 
421       if ( number > 0x7FFFL )
422       {
423         for ( integer_length = 5; integer_length < 10; integer_length++ )
424           if ( number < power_tens[integer_length] )
425             break;
426 
427         if ( ( number / power_tens[integer_length - 5] ) > 0x7FFFL )
428         {
429           *scaling = integer_length - 4;
430           return FT_DivFix( number, power_tens[integer_length - 4] );
431         }
432         else
433         {
434           *scaling = integer_length - 5;
435           return FT_DivFix( number, power_tens[integer_length - 5] );
436         }
437       }
438       else
439       {
440         *scaling = 0;
441         return number << 16;
442       }
443     }
444   }
445 
446 
447   static FT_Error
cff_parse_font_matrix(CFF_Parser parser)448   cff_parse_font_matrix( CFF_Parser  parser )
449   {
450     CFF_FontRecDict  dict   = (CFF_FontRecDict)parser->object;
451     FT_Matrix*       matrix = &dict->font_matrix;
452     FT_Vector*       offset = &dict->font_offset;
453     FT_ULong*        upm    = &dict->units_per_em;
454     FT_Byte**        data   = parser->stack;
455     FT_Error         error  = CFF_Err_Stack_Underflow;
456 
457 
458     if ( parser->top >= parser->stack + 6 )
459     {
460       FT_Long  scaling;
461 
462 
463       error = CFF_Err_Ok;
464 
465       /* We expect a well-formed font matrix, this is, the matrix elements */
466       /* `xx' and `yy' are of approximately the same magnitude.  To avoid  */
467       /* loss of precision, we use the magnitude of element `xx' to scale  */
468       /* all other elements.  The scaling factor is then contained in the  */
469       /* `units_per_em' value.                                             */
470 
471       matrix->xx = cff_parse_fixed_dynamic( data++, &scaling );
472 
473       scaling = -scaling;
474 
475       if ( scaling < 0 || scaling > 9 )
476       {
477         /* Return default matrix in case of unlikely values. */
478         matrix->xx = 0x10000L;
479         matrix->yx = 0;
480         matrix->yx = 0;
481         matrix->yy = 0x10000L;
482         offset->x  = 0;
483         offset->y  = 0;
484         *upm       = 1;
485 
486         goto Exit;
487       }
488 
489       matrix->yx = cff_parse_fixed_scaled( data++, scaling );
490       matrix->xy = cff_parse_fixed_scaled( data++, scaling );
491       matrix->yy = cff_parse_fixed_scaled( data++, scaling );
492       offset->x  = cff_parse_fixed_scaled( data++, scaling );
493       offset->y  = cff_parse_fixed_scaled( data,   scaling );
494 
495       *upm = power_tens[scaling];
496     }
497 
498   Exit:
499     return error;
500   }
501 
502 
503   static FT_Error
cff_parse_font_bbox(CFF_Parser parser)504   cff_parse_font_bbox( CFF_Parser  parser )
505   {
506     CFF_FontRecDict  dict = (CFF_FontRecDict)parser->object;
507     FT_BBox*         bbox = &dict->font_bbox;
508     FT_Byte**        data = parser->stack;
509     FT_Error         error;
510 
511 
512     error = CFF_Err_Stack_Underflow;
513 
514     if ( parser->top >= parser->stack + 4 )
515     {
516       bbox->xMin = FT_RoundFix( cff_parse_fixed( data++ ) );
517       bbox->yMin = FT_RoundFix( cff_parse_fixed( data++ ) );
518       bbox->xMax = FT_RoundFix( cff_parse_fixed( data++ ) );
519       bbox->yMax = FT_RoundFix( cff_parse_fixed( data   ) );
520       error = CFF_Err_Ok;
521     }
522 
523     return error;
524   }
525 
526 
527   static FT_Error
cff_parse_private_dict(CFF_Parser parser)528   cff_parse_private_dict( CFF_Parser  parser )
529   {
530     CFF_FontRecDict  dict = (CFF_FontRecDict)parser->object;
531     FT_Byte**        data = parser->stack;
532     FT_Error         error;
533 
534 
535     error = CFF_Err_Stack_Underflow;
536 
537     if ( parser->top >= parser->stack + 2 )
538     {
539       dict->private_size   = cff_parse_num( data++ );
540       dict->private_offset = cff_parse_num( data   );
541       error = CFF_Err_Ok;
542     }
543 
544     return error;
545   }
546 
547 
548   static FT_Error
cff_parse_cid_ros(CFF_Parser parser)549   cff_parse_cid_ros( CFF_Parser  parser )
550   {
551     CFF_FontRecDict  dict = (CFF_FontRecDict)parser->object;
552     FT_Byte**        data = parser->stack;
553     FT_Error         error;
554 
555 
556     error = CFF_Err_Stack_Underflow;
557 
558     if ( parser->top >= parser->stack + 3 )
559     {
560       dict->cid_registry   = (FT_UInt)cff_parse_num ( data++ );
561       dict->cid_ordering   = (FT_UInt)cff_parse_num ( data++ );
562       if ( **data == 30 )
563         FT_TRACE1(( "cff_parse_cid_ros: real supplement is rounded\n" ));
564       dict->cid_supplement = cff_parse_num( data );
565       if ( dict->cid_supplement < 0 )
566         FT_TRACE1(( "cff_parse_cid_ros: negative supplement %d is found\n",
567                    dict->cid_supplement ));
568       error = CFF_Err_Ok;
569     }
570 
571     return error;
572   }
573 
574 
575 #define CFF_FIELD_NUM( code, name ) \
576           CFF_FIELD( code, name, cff_kind_num )
577 #define CFF_FIELD_FIXED( code, name ) \
578           CFF_FIELD( code, name, cff_kind_fixed )
579 #define CFF_FIELD_FIXED_1000( code, name ) \
580           CFF_FIELD( code, name, cff_kind_fixed_thousand )
581 #define CFF_FIELD_STRING( code, name ) \
582           CFF_FIELD( code, name, cff_kind_string )
583 #define CFF_FIELD_BOOL( code, name ) \
584           CFF_FIELD( code, name, cff_kind_bool )
585 #define CFF_FIELD_DELTA( code, name, max ) \
586           CFF_FIELD( code, name, cff_kind_delta )
587 
588 #define CFFCODE_TOPDICT  0x1000
589 #define CFFCODE_PRIVATE  0x2000
590 
591 #ifndef FT_CONFIG_OPTION_PIC
592 
593 #define CFF_FIELD_CALLBACK( code, name ) \
594           {                              \
595             cff_kind_callback,           \
596             code | CFFCODE,              \
597             0, 0,                        \
598             cff_parse_ ## name,          \
599             0, 0                         \
600           },
601 
602 #undef  CFF_FIELD
603 #define CFF_FIELD( code, name, kind ) \
604           {                          \
605             kind,                    \
606             code | CFFCODE,          \
607             FT_FIELD_OFFSET( name ), \
608             FT_FIELD_SIZE( name ),   \
609             0, 0, 0                  \
610           },
611 
612 #undef  CFF_FIELD_DELTA
613 #define CFF_FIELD_DELTA( code, name, max ) \
614         {                                  \
615           cff_kind_delta,                  \
616           code | CFFCODE,                  \
617           FT_FIELD_OFFSET( name ),         \
618           FT_FIELD_SIZE_DELTA( name ),     \
619           0,                               \
620           max,                             \
621           FT_FIELD_OFFSET( num_ ## name )  \
622         },
623 
624   static const CFF_Field_Handler  cff_field_handlers[] =
625   {
626 
627 #include "cfftoken.h"
628 
629     { 0, 0, 0, 0, 0, 0, 0 }
630   };
631 
632 
633 #else /* FT_CONFIG_OPTION_PIC */
634 
FT_Destroy_Class_cff_field_handlers(FT_Library library,CFF_Field_Handler * clazz)635   void FT_Destroy_Class_cff_field_handlers(FT_Library library, CFF_Field_Handler* clazz)
636   {
637     FT_Memory memory = library->memory;
638     if ( clazz )
639       FT_FREE( clazz );
640   }
641 
FT_Create_Class_cff_field_handlers(FT_Library library,CFF_Field_Handler ** output_class)642   FT_Error FT_Create_Class_cff_field_handlers(FT_Library library, CFF_Field_Handler** output_class)
643   {
644     CFF_Field_Handler*  clazz;
645     FT_Error          error;
646     FT_Memory memory = library->memory;
647     int i=0;
648 
649 #undef CFF_FIELD
650 #undef CFF_FIELD_DELTA
651 #undef CFF_FIELD_CALLBACK
652 #define CFF_FIELD_CALLBACK( code, name ) i++;
653 #define CFF_FIELD( code, name, kind ) i++;
654 #define CFF_FIELD_DELTA( code, name, max ) i++;
655 
656 #include "cfftoken.h"
657     i++;/*{ 0, 0, 0, 0, 0, 0, 0 }*/
658 
659     if ( FT_ALLOC( clazz, sizeof(CFF_Field_Handler)*i ) )
660       return error;
661 
662     i=0;
663 #undef CFF_FIELD
664 #undef CFF_FIELD_DELTA
665 #undef CFF_FIELD_CALLBACK
666 
667 #define CFF_FIELD_CALLBACK( code_, name_ )                                   \
668     clazz[i].kind = cff_kind_callback;                                       \
669     clazz[i].code = code_ | CFFCODE;                                         \
670     clazz[i].offset = 0;                                                     \
671     clazz[i].size = 0;                                                       \
672     clazz[i].reader = cff_parse_ ## name_;                                   \
673     clazz[i].array_max = 0;                                                  \
674     clazz[i].count_offset = 0;                                               \
675     i++;
676 
677 #undef  CFF_FIELD
678 #define CFF_FIELD( code_, name_, kind_ )                                     \
679     clazz[i].kind = kind_;                                                   \
680     clazz[i].code = code_ | CFFCODE;                                         \
681     clazz[i].offset = FT_FIELD_OFFSET( name_ );                              \
682     clazz[i].size = FT_FIELD_SIZE( name_ );                                  \
683     clazz[i].reader = 0;                                                     \
684     clazz[i].array_max = 0;                                                  \
685     clazz[i].count_offset = 0;                                               \
686     i++;                                                                     \
687 
688 #undef  CFF_FIELD_DELTA
689 #define CFF_FIELD_DELTA( code_, name_, max_ )                                \
690     clazz[i].kind = cff_kind_delta;                                          \
691     clazz[i].code = code_ | CFFCODE;                                         \
692     clazz[i].offset = FT_FIELD_OFFSET( name_ );                              \
693     clazz[i].size = FT_FIELD_SIZE_DELTA( name_ );                            \
694     clazz[i].reader = 0;                                                     \
695     clazz[i].array_max = max_;                                               \
696     clazz[i].count_offset = FT_FIELD_OFFSET( num_ ## name_ );                \
697     i++;
698 
699 #include "cfftoken.h"
700 
701     clazz[i].kind = 0;
702     clazz[i].code = 0;
703     clazz[i].offset = 0;
704     clazz[i].size = 0;
705     clazz[i].reader = 0;
706     clazz[i].array_max = 0;
707     clazz[i].count_offset = 0;
708 
709     *output_class = clazz;
710     return CFF_Err_Ok;
711   }
712 
713 
714 #endif /* FT_CONFIG_OPTION_PIC */
715 
716 
717   FT_LOCAL_DEF( FT_Error )
cff_parser_run(CFF_Parser parser,FT_Byte * start,FT_Byte * limit)718   cff_parser_run( CFF_Parser  parser,
719                   FT_Byte*    start,
720                   FT_Byte*    limit )
721   {
722     FT_Byte*    p       = start;
723     FT_Error    error   = CFF_Err_Ok;
724     FT_Library  library = parser->library;
725     FT_UNUSED(library);
726 
727 
728     parser->top    = parser->stack;
729     parser->start  = start;
730     parser->limit  = limit;
731     parser->cursor = start;
732 
733     while ( p < limit )
734     {
735       FT_UInt  v = *p;
736 
737 
738       if ( v >= 27 && v != 31 )
739       {
740         /* it's a number; we will push its position on the stack */
741         if ( parser->top - parser->stack >= CFF_MAX_STACK_DEPTH )
742           goto Stack_Overflow;
743 
744         *parser->top ++ = p;
745 
746         /* now, skip it */
747         if ( v == 30 )
748         {
749           /* skip real number */
750           p++;
751           for (;;)
752           {
753             /* An unterminated floating point number at the */
754             /* end of a dictionary is invalid but harmless. */
755             if ( p >= limit )
756               goto Exit;
757             v = p[0] >> 4;
758             if ( v == 15 )
759               break;
760             v = p[0] & 0xF;
761             if ( v == 15 )
762               break;
763             p++;
764           }
765         }
766         else if ( v == 28 )
767           p += 2;
768         else if ( v == 29 )
769           p += 4;
770         else if ( v > 246 )
771           p += 1;
772       }
773       else
774       {
775         /* This is not a number, hence it's an operator.  Compute its code */
776         /* and look for it in our current list.                            */
777 
778         FT_UInt                   code;
779         FT_UInt                   num_args = (FT_UInt)
780                                              ( parser->top - parser->stack );
781         const CFF_Field_Handler*  field;
782 
783 
784         *parser->top = p;
785         code = v;
786         if ( v == 12 )
787         {
788           /* two byte operator */
789           p++;
790           if ( p >= limit )
791             goto Syntax_Error;
792 
793           code = 0x100 | p[0];
794         }
795         code = code | parser->object_code;
796 
797         for ( field = FT_CFF_FIELD_HANDLERS_GET; field->kind; field++ )
798         {
799           if ( field->code == (FT_Int)code )
800           {
801             /* we found our field's handler; read it */
802             FT_Long   val;
803             FT_Byte*  q = (FT_Byte*)parser->object + field->offset;
804 
805 
806             /* check that we have enough arguments -- except for */
807             /* delta encoded arrays, which can be empty          */
808             if ( field->kind != cff_kind_delta && num_args < 1 )
809               goto Stack_Underflow;
810 
811             switch ( field->kind )
812             {
813             case cff_kind_bool:
814             case cff_kind_string:
815             case cff_kind_num:
816               val = cff_parse_num( parser->stack );
817               goto Store_Number;
818 
819             case cff_kind_fixed:
820               val = cff_parse_fixed( parser->stack );
821               goto Store_Number;
822 
823             case cff_kind_fixed_thousand:
824               val = cff_parse_fixed_scaled( parser->stack, 3 );
825 
826             Store_Number:
827               switch ( field->size )
828               {
829               case (8 / FT_CHAR_BIT):
830                 *(FT_Byte*)q = (FT_Byte)val;
831                 break;
832 
833               case (16 / FT_CHAR_BIT):
834                 *(FT_Short*)q = (FT_Short)val;
835                 break;
836 
837               case (32 / FT_CHAR_BIT):
838                 *(FT_Int32*)q = (FT_Int)val;
839                 break;
840 
841               default:  /* for 64-bit systems */
842                 *(FT_Long*)q = val;
843               }
844               break;
845 
846             case cff_kind_delta:
847               {
848                 FT_Byte*   qcount = (FT_Byte*)parser->object +
849                                       field->count_offset;
850 
851                 FT_Byte**  data = parser->stack;
852 
853 
854                 if ( num_args > field->array_max )
855                   num_args = field->array_max;
856 
857                 /* store count */
858                 *qcount = (FT_Byte)num_args;
859 
860                 val = 0;
861                 while ( num_args > 0 )
862                 {
863                   val += cff_parse_num( data++ );
864                   switch ( field->size )
865                   {
866                   case (8 / FT_CHAR_BIT):
867                     *(FT_Byte*)q = (FT_Byte)val;
868                     break;
869 
870                   case (16 / FT_CHAR_BIT):
871                     *(FT_Short*)q = (FT_Short)val;
872                     break;
873 
874                   case (32 / FT_CHAR_BIT):
875                     *(FT_Int32*)q = (FT_Int)val;
876                     break;
877 
878                   default:  /* for 64-bit systems */
879                     *(FT_Long*)q = val;
880                   }
881 
882                   q += field->size;
883                   num_args--;
884                 }
885               }
886               break;
887 
888             default:  /* callback */
889               error = field->reader( parser );
890               if ( error )
891                 goto Exit;
892             }
893             goto Found;
894           }
895         }
896 
897         /* this is an unknown operator, or it is unsupported; */
898         /* we will ignore it for now.                         */
899 
900       Found:
901         /* clear stack */
902         parser->top = parser->stack;
903       }
904       p++;
905     }
906 
907   Exit:
908     return error;
909 
910   Stack_Overflow:
911     error = CFF_Err_Invalid_Argument;
912     goto Exit;
913 
914   Stack_Underflow:
915     error = CFF_Err_Invalid_Argument;
916     goto Exit;
917 
918   Syntax_Error:
919     error = CFF_Err_Invalid_Argument;
920     goto Exit;
921   }
922 
923 
924 /* END */
925