PageRenderTime 57ms CodeModel.GetById 19ms app.highlight 32ms RepoModel.GetById 1ms app.codeStats 0ms

/modules/freetype2/src/cff/cffparse.c

http://github.com/zpao/v8monkey
C | 924 lines | 669 code | 175 blank | 80 comment | 116 complexity | 55bd232aa6fa77d2666be27dcaf9a206 MD5 | raw file
  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 )
 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
 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
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
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
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
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
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
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
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
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
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
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
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 )
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 */