cidparse.c revision a1be2dcee38dd4448a365fd8932c52cca52f5445
1/***************************************************************************/
2/*                                                                         */
3/*  cidparse.c                                                             */
4/*                                                                         */
5/*    CID-keyed Type1 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#include <freetype/internal/ftdebug.h>
20#include <freetype/internal/ftcalc.h>
21#include <freetype/internal/ftobjs.h>
22#include <freetype/internal/ftstream.h>
23#include <freetype/internal/t1errors.h>
24#include <cidparse.h>
25
26#include <string.h>     /* for strncmp() */
27
28
29  /*************************************************************************/
30  /*                                                                       */
31  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
32  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
33  /* messages during execution.                                            */
34  /*                                                                       */
35#undef FT_COMPONENT
36#define FT_COMPONENT  trace_cidparse
37
38
39#if 0
40
41  /*************************************************************************/
42  /*************************************************************************/
43  /*************************************************************************/
44  /*****                                                               *****/
45  /*****           IMPLEMENTATION OF CID_TABLE OBJECT                   *****/
46  /*****                                                               *****/
47  /*************************************************************************/
48  /*************************************************************************/
49  /*************************************************************************/
50
51
52  /*************************************************************************/
53  /*                                                                       */
54  /* <Function>                                                            */
55  /*    CID_New_Table                                                       */
56  /*                                                                       */
57  /* <Description>                                                         */
58  /*    Initializes a CID_Table.                                            */
59  /*                                                                       */
60  /* <InOut>                                                               */
61  /*    table  :: The address of the target table.                         */
62  /*                                                                       */
63  /* <Input>                                                               */
64  /*    count  :: The table size, i.e., the maximal number of elements.    */
65  /*                                                                       */
66  /*    memory :: The memory object to be used for all subsequent          */
67  /*              reallocations.                                           */
68  /*                                                                       */
69  /* <Return>                                                              */
70  /*    FreeType error code.  0 means success.                             */
71  /*                                                                       */
72  LOCAL_FUNC
73  FT_Error  CID_New_Table( CID_Table*  table,
74                          FT_Int     count,
75                          FT_Memory  memory )
76  {
77    FT_Error  error;
78
79
80    table->memory = memory;
81    if ( ALLOC_ARRAY( table->elements, count, FT_Byte*  ) ||
82         ALLOC_ARRAY( table->lengths, count, FT_Byte* )   )
83      goto Exit;
84
85    table->max_elems = count;
86    table->init      = 0xDEADBEEFL;
87    table->num_elems = 0;
88    table->block     = 0;
89    table->capacity  = 0;
90    table->cursor    = 0;
91
92  Exit:
93    if ( error )
94      FREE( table->elements );
95
96    return error;
97  }
98
99
100  static
101  void  shift_elements( CID_Table*  table,
102                        FT_Byte*   old_base )
103  {
104    FT_Long    delta  = table->block - old_base;
105    FT_Byte**  offset = table->elements;
106    FT_Byte**  limit  = offset + table->max_elems;
107
108
109    if ( delta )
110      for ( ; offset < limit; offset++ )
111      {
112        if ( offset[0] )
113          offset[0] += delta;
114      }
115  }
116
117
118  static
119  FT_Error  reallocate_t1_table( CID_Table*  table,
120                                 FT_Int     new_size )
121  {
122    FT_Memory  memory   = table->memory;
123    FT_Byte*   old_base = table->block;
124    FT_Error   error;
125
126
127    /* realloc the base block */
128    if ( REALLOC( table->block, table->capacity, new_size ) )
129      return error;
130
131    table->capacity = new_size;
132
133    /* shift all offsets when needed */
134    if ( old_base )
135      shift_elements( table, old_base );
136
137    return T1_Err_Ok;
138  }
139
140
141  /*************************************************************************/
142  /*                                                                       */
143  /* <Function>                                                            */
144  /*    CID_Add_Table                                                       */
145  /*                                                                       */
146  /* <Description>                                                         */
147  /*    Adds an object to a CID_Table, possibly growing its memory block.   */
148  /*                                                                       */
149  /* <InOut>                                                               */
150  /*    table  :: The target table.                                        */
151  /*                                                                       */
152  /* <Input>                                                               */
153  /*    index  :: The index of the object in the table.                    */
154  /*                                                                       */
155  /*    object :: The address of the object to copy in the memory.         */
156  /*                                                                       */
157  /*    length :: The length in bytes of the source object.                */
158  /*                                                                       */
159  /* <Return>                                                              */
160  /*    FreeType error code.  0 means success.  An error is returned if    */
161  /*    reallocation fails.                                                */
162  /*                                                                       */
163  LOCAL_FUNC
164  FT_Error  CID_Add_Table( CID_Table*  table,
165                          FT_Int     index,
166                          void*      object,
167                          FT_Int     length )
168  {
169    if ( index < 0 || index > table->max_elems )
170    {
171      FT_ERROR(( "CID_Add_Table: invalid index\n" ));
172      return T1_Err_Syntax_Error;
173    }
174
175    /* grow the base block if needed */
176    if ( table->cursor + length > table->capacity )
177    {
178      FT_Error  error;
179      FT_Int    new_size = table->capacity;
180
181
182      while ( new_size < table->cursor + length )
183        new_size += 1024;
184
185      error = reallocate_t1_table( table, new_size );
186      if ( error )
187        return error;
188    }
189
190    /* add the object to the base block and adjust offset */
191    table->elements[index] = table->block + table->cursor;
192    table->lengths [index] = length;
193
194    MEM_Copy( table->block + table->cursor, object, length );
195
196    table->cursor += length;
197
198    return T1_Err_Ok;
199  }
200
201
202  /*************************************************************************/
203  /*                                                                       */
204  /* <Function>                                                            */
205  /*    CID_Done_Table                                                      */
206  /*                                                                       */
207  /* <Description>                                                         */
208  /*    Finalizes a CID_Table (reallocate it to its current cursor).        */
209  /*                                                                       */
210  /* <InOut>                                                               */
211  /*    table :: The target table.                                         */
212  /*                                                                       */
213  /* <Note>                                                                */
214  /*    This function does NOT release the heap's memory block.  It is up  */
215  /*    to the caller to clean it, or reference it in its own structures.  */
216  /*                                                                       */
217  LOCAL_FUNC
218  void  CID_Done_Table( CID_Table*  table )
219  {
220    FT_Memory  memory = table->memory;
221    FT_Error   error;
222    FT_Byte*   old_base;
223
224
225    /* should never fail, as rec.cursor <= rec.size */
226    old_base = table->block;
227    if ( !old_base )
228      return;
229
230    (void)REALLOC( table->block, table->capacity, table->cursor );
231    table->capacity = table->cursor;
232
233    if ( old_base != table->block )
234      shift_elements( table, old_base );
235  }
236
237
238  LOCAL_FUNC
239  void  CID_Release_Table( CID_Table*  table )
240  {
241    FT_Memory  memory = table->memory;
242
243
244    if ( table->init == 0xDEADBEEFL )
245    {
246      FREE( table->block );
247      FREE( table->elements );
248      FREE( table->lengths );
249      table->init = 0;
250    }
251  }
252
253#endif /* 0 */
254
255
256  /*************************************************************************/
257  /*************************************************************************/
258  /*************************************************************************/
259  /*****                                                               *****/
260  /*****                    INPUT STREAM PARSER                        *****/
261  /*****                                                               *****/
262  /*************************************************************************/
263  /*************************************************************************/
264  /*************************************************************************/
265
266
267#define IS_CID_WHITESPACE( c )  ( (c) == ' '  || (c) == '\t' )
268#define IS_CID_LINESPACE( c )   ( (c) == '\r' || (c) == '\n' )
269
270#define IS_CID_SPACE( c )  ( IS_CID_WHITESPACE( c ) || IS_CID_LINESPACE( c ) )
271
272
273  LOCAL_FUNC
274  void  CID_Skip_Spaces( CID_Parser*  parser )
275  {
276    FT_Byte* cur   = parser->cursor;
277    FT_Byte* limit = parser->limit;
278
279
280    while ( cur < limit )
281    {
282      FT_Byte  c = *cur;
283
284
285      if ( !IS_CID_SPACE( c ) )
286        break;
287      cur++;
288    }
289
290    parser->cursor = cur;
291  }
292
293
294  LOCAL_FUNC
295  void  CID_ToToken( CID_Parser*    parser,
296                     CID_Token_Rec*  token )
297  {
298    FT_Byte*  cur;
299    FT_Byte*  limit;
300    FT_Byte   starter, ender;
301    FT_Int    embed;
302
303
304    token->type  = t1_token_none;
305    token->start = 0;
306    token->limit = 0;
307
308    /* first of all, skip space */
309    CID_Skip_Spaces( parser );
310
311    cur   = parser->cursor;
312    limit = parser->limit;
313
314    if ( cur < limit )
315    {
316      switch ( *cur )
317      {
318        /************* check for strings ***********************/
319      case '(':
320        token->type = t1_token_string;
321        ender = ')';
322        goto Lookup_Ender;
323
324        /************* check for programs/array ****************/
325      case '{':
326        token->type = t1_token_array;
327        ender = '}';
328        goto Lookup_Ender;
329
330        /************* check for table/array ******************/
331      case '[':
332        token->type = t1_token_array;
333        ender = ']';
334
335      Lookup_Ender:
336        embed   = 1;
337        starter = *cur++;
338        token->start = cur;
339
340        while ( cur < limit )
341        {
342          if ( *cur == starter )
343            embed++;
344          else if ( *cur == ender )
345          {
346            embed--;
347            if ( embed <= 0 )
348            {
349              token->limit = cur++;
350              break;
351            }
352          }
353          cur++;
354        }
355        break;
356
357        /* **************** otherwise, it's any token **********/
358      default:
359        token->start = cur++;
360        token->type  = t1_token_any;
361        while ( cur < limit && !IS_CID_SPACE( *cur ) )
362          cur++;
363
364        token->limit = cur;
365      }
366
367      if ( !token->limit )
368      {
369        token->start = 0;
370        token->type  = t1_token_none;
371      }
372
373      parser->cursor = cur;
374    }
375  }
376
377
378  LOCAL_FUNC
379  void  CID_ToTokenArray( CID_Parser*    parser,
380                          CID_Token_Rec*  tokens,
381                          FT_UInt        max_tokens,
382                          FT_Int*        pnum_tokens )
383  {
384    CID_Token_Rec  master;
385
386
387    *pnum_tokens = -1;
388
389    CID_ToToken( parser, &master );
390
391    if ( master.type == t1_token_array )
392    {
393      FT_Byte*       old_cursor = parser->cursor;
394      FT_Byte*       old_limit  = parser->limit;
395      CID_Token_Rec*  cur        = tokens;
396      CID_Token_Rec*  limit      = cur + max_tokens;
397
398
399      parser->cursor = master.start;
400      parser->limit  = master.limit;
401
402      while ( parser->cursor < parser->limit )
403      {
404        CID_Token_Rec  token;
405
406
407        CID_ToToken( parser, &token );
408        if ( !token.type )
409          break;
410
411        if ( cur < limit )
412          *cur = token;
413
414        cur++;
415      }
416
417      *pnum_tokens = cur - tokens;
418
419      parser->cursor = old_cursor;
420      parser->limit  = old_limit;
421    }
422  }
423
424
425  static
426  FT_Long  t1_toint( FT_Byte**  cursor,
427                     FT_Byte*   limit )
428  {
429    FT_Long   result = 0;
430    FT_Byte*  cur    = *cursor;
431    FT_Byte   c, d;
432
433
434    for ( ; cur < limit; cur++ )
435    {
436      c = *cur;
437      d = (FT_Byte)( c - '0' );
438      if ( d < 10 )
439        break;
440
441      if ( c == '-' )
442      {
443        cur++;
444        break;
445      }
446    }
447
448    if ( cur < limit )
449    {
450      do
451      {
452        d = (FT_Byte)( cur[0] - '0' );
453        if ( d >= 10 )
454          break;
455
456        result = result * 10 + d;
457        cur++;
458
459      } while ( cur < limit );
460
461      if ( c == '-' )
462        result = -result;
463    }
464
465    *cursor = cur;
466
467    return result;
468  }
469
470
471  static
472  FT_Long  t1_tofixed( FT_Byte**  cursor,
473                       FT_Byte*   limit,
474                       FT_Long    power_ten )
475  {
476    FT_Byte*  cur = *cursor;
477    FT_Long   num, divider, result;
478    FT_Int    sign = 0;
479    FT_Byte   d;
480
481
482    if ( cur >= limit )
483      return 0;
484
485    /* first of all, read the integer part */
486    result  = t1_toint( &cur, limit ) << 16;
487    num     = 0;
488    divider = 1;
489
490    if ( result < 0 )
491    {
492      sign   = 1;
493      result = -result;
494    }
495
496    if ( cur >= limit )
497      goto Exit;
498
499    /* read decimal part, if any */
500    if ( *cur == '.' && cur + 1 < limit )
501    {
502      cur++;
503
504      for (;;)
505      {
506        d = (FT_Byte)( *cur - '0' );
507        if ( d >= 10 ) break;
508
509        if ( divider < 10000000L )
510        {
511          num      = num * 10 + d;
512          divider *= 10;
513        }
514
515        cur++;
516        if ( cur >= limit )
517          break;
518      }
519    }
520
521    /* read exponent, if any */
522    if ( cur + 1 < limit && ( *cur == 'e' || *cur == 'E' ) )
523    {
524      cur++;
525      power_ten += t1_toint( &cur, limit );
526    }
527
528  Exit:
529    /* raise to power of ten if needed */
530    while ( power_ten > 0 )
531    {
532      result = result * 10;
533      num    = num * 10;
534      power_ten--;
535    }
536
537    while ( power_ten < 0 )
538    {
539      result  = result / 10;
540      divider = divider * 10;
541      power_ten++;
542    }
543
544    if ( num )
545      result += FT_DivFix( num, divider );
546
547    if ( sign )
548      result = -result;
549
550    *cursor = cur;
551
552    return result;
553  }
554
555
556  static
557  int  t1_tobool( FT_Byte**  cursor,
558                  FT_Byte*   limit )
559  {
560    FT_Byte*  cur    = *cursor;
561    FT_Bool   result = 0;
562
563
564    /* return 1 if we find a "true", 0 otherwise */
565    if ( cur + 3 < limit &&
566         cur[0] == 't'   &&
567         cur[1] == 'r'   &&
568         cur[2] == 'u'   &&
569         cur[3] == 'e'   )
570    {
571      result = 1;
572      cur   += 5;
573    }
574    else if ( cur + 4 < limit &&
575              cur[0] == 'f'   &&
576              cur[1] == 'a'   &&
577              cur[2] == 'l'   &&
578              cur[3] == 's'   &&
579              cur[4] == 'e'   )
580    {
581      result = 0;
582      cur   += 6;
583    }
584    *cursor = cur;
585    return result;
586  }
587
588
589  static
590  FT_Int  t1_tocoordarray( FT_Byte**  cursor,
591                           FT_Byte*   limit,
592                           FT_Int     max_coords,
593                           FT_Short*  coords )
594  {
595    FT_Byte*  cur   = *cursor;
596    FT_Int    count = 0;
597    FT_Byte   c, ender;
598
599
600    if ( cur >= limit )
601      goto Exit;
602
603    /* check for the beginning of an array. */
604    /* If not, only one number will be read */
605    c     = *cur;
606    ender = 0;
607
608    if ( c == '[' )
609      ender = ']';
610
611    if ( c == '{' )
612      ender = '}';
613
614    if ( ender )
615      cur++;
616
617    /* now, read the coordinates */
618    for ( ; cur < limit; )
619    {
620      /* skip whitespace in front of data */
621      for (;;)
622      {
623        c = *cur;
624        if ( c != ' ' && c != '\t' )
625          break;
626
627        cur++;
628        if ( cur >= limit )
629          goto Exit;
630      }
631
632      if ( count >= max_coords || c == ender )
633        break;
634
635      coords[count] = (FT_Short)( t1_tofixed( &cur, limit, 0 ) >> 16 );
636      count++;
637
638      if ( !ender )
639        break;
640    }
641
642  Exit:
643    *cursor = cur;
644    return count;
645  }
646
647
648  static
649  FT_Int  t1_tofixedarray( FT_Byte**  cursor,
650                           FT_Byte*   limit,
651                           FT_Int     max_values,
652                           FT_Fixed*  values,
653                           FT_Int     power_ten )
654  {
655    FT_Byte*  cur   = *cursor;
656    FT_Int    count = 0;
657    FT_Byte   c, ender;
658
659
660    if ( cur >= limit )
661      goto Exit;
662
663    /* check for the beginning of an array. */
664    /* If not, only one number will be read */
665    c     = *cur;
666    ender = 0;
667
668    if ( c == '[' )
669      ender = ']';
670
671    if ( c == '{' )
672      ender = '}';
673
674    if ( ender )
675      cur++;
676
677    /* now, read the values */
678    for ( ; cur < limit; )
679    {
680      /* skip whitespace in front of data */
681      for (;;)
682      {
683        c = *cur;
684        if ( c != ' ' && c != '\t' )
685          break;
686
687        cur++;
688        if ( cur >= limit )
689          goto Exit;
690      }
691
692      if ( count >= max_values || c == ender )
693        break;
694
695      values[count] = t1_tofixed( &cur, limit, power_ten );
696      count++;
697
698      if ( !ender )
699        break;
700    }
701
702  Exit:
703    *cursor = cur;
704
705    return count;
706  }
707
708
709
710  /* Loads a simple field (i.e. non-table) into the current */
711  /* list of objects                                        */
712  LOCAL_FUNC
713  FT_Error  CID_Load_Field( CID_Parser*          parser,
714                            const CID_Field_Rec*  field,
715                            void*                object )
716  {
717    CID_Token_Rec  token;
718    FT_Byte*      cur;
719    FT_Byte*      limit;
720    FT_UInt       count;
721    FT_UInt       index;
722    FT_Error      error;
723
724
725    CID_ToToken( parser, &token );
726    if ( !token.type )
727      goto Fail;
728
729    count = 1;
730    index = 0;
731    cur   = token.start;
732    limit = token.limit;
733
734    {
735      FT_Byte*   q = (FT_Byte*)object + field->offset;
736      FT_Long    val;
737      FT_String* string;
738
739
740      switch ( field->type )
741      {
742      case t1_field_bool:
743        val = t1_tobool( &cur, limit );
744        goto Store_Integer;
745
746      case t1_field_fixed:
747        val = t1_tofixed( &cur, limit, 0 );
748        goto Store_Integer;
749
750      case t1_field_integer:
751        val = t1_toint( &cur, limit );
752
753      Store_Integer:
754        switch ( field->size )
755        {
756          case 1:
757            *(FT_Byte*)q = (FT_Byte)val;
758            break;
759
760          case 2:
761            *(FT_UShort*)q = (FT_UShort)val;
762            break;
763
764          default:
765            *(FT_Long*)q = val;
766        }
767        break;
768
769      case t1_field_string:
770        {
771          FT_Memory  memory = parser->memory;
772          FT_UInt    len    = limit-cur;
773
774
775          if ( ALLOC( string, len + 1 ) )
776            goto Exit;
777
778          MEM_Copy( string, cur, len );
779          string[len] = 0;
780
781          *(FT_String**)q = string;
782        }
783        break;
784
785      default:
786        /* an error occured */
787        goto Fail;
788      }
789    }
790
791    error = 0;
792
793  Exit:
794    return error;
795
796  Fail:
797    error = T1_Err_Invalid_File_Format;
798    goto Exit;
799  }
800
801
802#define T1_MAX_TABLE_ELEMENTS  32
803
804
805  LOCAL_FUNC
806  FT_Error  CID_Load_Field_Table( CID_Parser*          parser,
807                                  const CID_Field_Rec*  field,
808                                  void*                object )
809  {
810    CID_Token_Rec   elements[T1_MAX_TABLE_ELEMENTS];
811    CID_Token_Rec*  token;
812    FT_Int         num_elements;
813    FT_Error       error = 0;
814    FT_Byte*       old_cursor;
815    FT_Byte*       old_limit;
816    CID_Field_Rec   fieldrec = *(CID_Field_Rec*)field;
817
818
819    fieldrec.type = t1_field_integer;
820    if ( field->type == t1_field_fixed_array )
821      fieldrec.type = t1_field_fixed;
822
823    CID_ToTokenArray( parser, elements, 32, &num_elements );
824    if ( num_elements < 0 )
825      goto Fail;
826
827    if ( num_elements > T1_MAX_TABLE_ELEMENTS )
828      num_elements = T1_MAX_TABLE_ELEMENTS;
829
830    old_cursor = parser->cursor;
831    old_limit  = parser->limit;
832
833    /* we store the elements count */
834    if ( field->count_offset )
835      *(FT_Byte*)( (FT_Byte*)object + field->count_offset ) = num_elements;
836
837    /* we now load each element, adjusting the field.offset on each one */
838    token = elements;
839    for ( ; num_elements > 0; num_elements--, token++ )
840    {
841      parser->cursor = token->start;
842      parser->limit  = token->limit;
843      CID_Load_Field( parser, &fieldrec, object );
844      fieldrec.offset += fieldrec.size;
845    }
846
847    parser->cursor = old_cursor;
848    parser->limit  = old_limit;
849
850  Exit:
851    return error;
852
853  Fail:
854    error = T1_Err_Invalid_File_Format;
855    goto Exit;
856  }
857
858
859  LOCAL_FUNC
860  FT_Long  CID_ToInt( CID_Parser*  parser )
861  {
862    return t1_toint( &parser->cursor, parser->limit );
863  }
864
865
866  LOCAL_FUNC
867  FT_Int  CID_ToCoordArray( CID_Parser*  parser,
868                            FT_Int       max_coords,
869                            FT_Short*    coords )
870  {
871    return t1_tocoordarray( &parser->cursor, parser->limit,
872                            max_coords, coords );
873  }
874
875
876  LOCAL_FUNC
877  FT_Int  CID_ToFixedArray( CID_Parser*  parser,
878                            FT_Int       max_values,
879                            FT_Fixed*    values,
880                            FT_Int       power_ten )
881  {
882    return t1_tofixedarray( &parser->cursor, parser->limit,
883                            max_values, values, power_ten );
884  }
885
886
887#if 0
888
889  /* return the value of an hexadecimal digit */
890  static
891  int  hexa_value( char  c )
892  {
893    unsigned int  d;
894
895
896    d = (unsigned int)( c - '0' );
897    if ( d <= 9 )
898      return (int)d;
899
900    d = (unsigned int)( c - 'a' );
901    if ( d <= 5 )
902      return (int)( d + 10 );
903
904    d = (unsigned int)( c - 'A' );
905    if ( d <= 5 )
906      return (int)( d + 10 );
907
908    return -1;
909  }
910
911#endif /* 0 */
912
913
914  LOCAL_FUNC
915  FT_Error  CID_New_Parser( CID_Parser*  parser,
916                            FT_Stream    stream,
917                            FT_Memory    memory )
918  {
919    FT_Error  error;
920    FT_ULong  base_offset, offset, ps_len;
921    FT_Byte   buffer[256 + 10];
922    FT_Int    buff_len;
923
924
925    MEM_Set( parser, 0, sizeof ( *parser ) );
926    parser->stream = stream;
927    parser->memory = memory;
928
929    base_offset = FILE_Pos();
930
931    /* first of all, check the font format in the  header */
932    if ( ACCESS_Frame( 31 ) )
933      goto Exit;
934
935    if ( strncmp( stream->cursor, "%!PS-Adobe-3.0 Resource-CIDFont", 31 ) )
936    {
937      FT_TRACE2(( "[not a valid CID-keyed font]\n" ));
938      error = FT_Err_Unknown_File_Format;
939    }
940
941    FORGET_Frame();
942    if ( error )
943      goto Exit;
944
945    /* now, read the rest of the file, until we find a `StartData' */
946    buff_len = 256;
947    for (;;)
948    {
949      FT_Byte *p, *limit = buffer + 256;
950
951      /* fill input buffer */
952      buff_len -= 256;
953      if ( buff_len > 0 )
954        MEM_Move( buffer, limit, buff_len );
955
956      if ( FILE_Read( buffer, 256 + 10 - buff_len ) )
957        goto Exit;
958
959      buff_len = 256 + 10;
960
961      /* look for "StartData" */
962      for ( p = buffer; p < limit; p++ )
963      {
964        if ( p[0] == 'S' && strncmp( (char*)p, "StartData", 9 ) == 0 )
965        {
966          /* save offset of binary data after "StartData" */
967          offset = FILE_Pos() - ( limit - p ) + 10;
968          goto Found;
969        }
970      }
971    }
972
973  Found:
974    /* all right, we found the start of the binary data.  We will now  */
975    /* rewind and extract the frame of corresponding to the Postscript */
976    /* section                                                         */
977
978    ps_len = offset - base_offset;
979    if ( FILE_Seek( base_offset )                    ||
980         EXTRACT_Frame( ps_len, parser->postscript ) )
981      goto Exit;
982
983    parser->data_offset    = offset;
984    parser->postscript_len = ps_len;
985    parser->cursor         = parser->postscript;
986    parser->limit          = parser->cursor + ps_len;
987    parser->num_dict       = -1;
988
989  Exit:
990    return error;
991  }
992
993
994  LOCAL_FUNC
995  void  CID_Done_Parser( CID_Parser*  parser )
996  {
997    /* always free the private dictionary */
998    if ( parser->postscript )
999    {
1000      FT_Stream  stream = parser->stream;
1001
1002
1003      RELEASE_Frame( parser->postscript );
1004    }
1005  }
1006
1007
1008/* END */
1009