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