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