The BIG graph update
[rrdtool.git] / libraries / freetype-2.0.5 / psobjs.c
1 /***************************************************************************/
2 /*                                                                         */
3 /*  psobjs.c                                                               */
4 /*                                                                         */
5 /*    Auxiliary functions for PostScript fonts (body).                     */
6 /*                                                                         */
7 /*  Copyright 1996-2001 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 FT_INTERNAL_POSTSCRIPT_AUX_H
21 #include FT_INTERNAL_DEBUG_H
22
23 #include "psobjs.h"
24
25 #include "psauxerr.h"
26
27
28   /*************************************************************************/
29   /*************************************************************************/
30   /*****                                                               *****/
31   /*****                             PS_TABLE                          *****/
32   /*****                                                               *****/
33   /*************************************************************************/
34   /*************************************************************************/
35
36   /*************************************************************************/
37   /*                                                                       */
38   /* <Function>                                                            */
39   /*    PS_Table_New                                                       */
40   /*                                                                       */
41   /* <Description>                                                         */
42   /*    Initializes a PS_Table.                                            */
43   /*                                                                       */
44   /* <InOut>                                                               */
45   /*    table  :: The address of the target table.                         */
46   /*                                                                       */
47   /* <Input>                                                               */
48   /*    count  :: The table size = the maximum number of elements.         */
49   /*                                                                       */
50   /*    memory :: The memory object to use for all subsequent              */
51   /*              reallocations.                                           */
52   /*                                                                       */
53   /* <Return>                                                              */
54   /*    FreeType error code.  0 means success.                             */
55   /*                                                                       */
56   FT_LOCAL_DEF FT_Error
57   PS_Table_New( PS_Table*  table,
58                 FT_Int     count,
59                 FT_Memory  memory )
60   {
61     FT_Error  error;
62
63
64     table->memory = memory;
65     if ( ALLOC_ARRAY( table->elements, count, FT_Byte*  ) ||
66          ALLOC_ARRAY( table->lengths, count, FT_Byte* )   )
67       goto Exit;
68
69     table->max_elems = count;
70     table->init      = 0xDEADBEEFUL;
71     table->num_elems = 0;
72     table->block     = 0;
73     table->capacity  = 0;
74     table->cursor    = 0;
75     table->funcs     = ps_table_funcs;
76
77   Exit:
78     if ( error )
79       FREE( table->elements );
80
81     return error;
82   }
83
84
85   static void
86   shift_elements( PS_Table*  table,
87                   FT_Byte*   old_base )
88   {
89     FT_Long    delta  = (FT_Long)( table->block - old_base );
90     FT_Byte**  offset = table->elements;
91     FT_Byte**  limit  = offset + table->max_elems;
92
93
94     for ( ; offset < limit; offset++ )
95     {
96       if ( offset[0] )
97         offset[0] += delta;
98     }
99   }
100
101
102   static FT_Error
103   reallocate_t1_table( PS_Table*  table,
104                        FT_Long    new_size )
105   {
106     FT_Memory  memory   = table->memory;
107     FT_Byte*   old_base = table->block;
108     FT_Error   error;
109
110
111     /* allocate new base block */
112     if ( ALLOC( table->block, new_size ) )
113       return error;
114
115     /* copy elements and shift offsets */
116     if (old_base )
117     {
118       MEM_Copy( table->block, old_base, table->capacity );
119       shift_elements( table, old_base );
120       FREE( old_base );
121     }
122
123     table->capacity = new_size;
124
125     return PSaux_Err_Ok;
126   }
127
128
129   /*************************************************************************/
130   /*                                                                       */
131   /* <Function>                                                            */
132   /*    PS_Table_Add                                                       */
133   /*                                                                       */
134   /* <Description>                                                         */
135   /*    Adds an object to a PS_Table, possibly growing its memory block.   */
136   /*                                                                       */
137   /* <InOut>                                                               */
138   /*    table  :: The target table.                                        */
139   /*                                                                       */
140   /* <Input>                                                               */
141   /*    index  :: The index of the object in the table.                    */
142   /*                                                                       */
143   /*    object :: The address of the object to copy in memory.             */
144   /*                                                                       */
145   /*    length :: The length in bytes of the source object.                */
146   /*                                                                       */
147   /* <Return>                                                              */
148   /*    FreeType error code.  0 means success.  An error is returned if a  */
149   /*    reallocation fails.                                                */
150   /*                                                                       */
151   FT_LOCAL_DEF FT_Error
152   PS_Table_Add( PS_Table*  table,
153                 FT_Int     index,
154                 void*      object,
155                 FT_Int     length )
156   {
157     if ( index < 0 || index > table->max_elems )
158     {
159       FT_ERROR(( "PS_Table_Add: invalid index\n" ));
160       return PSaux_Err_Invalid_Argument;
161     }
162
163     /* grow the base block if needed */
164     if ( table->cursor + length > table->capacity )
165     {
166       FT_Error   error;
167       FT_Offset  new_size  = table->capacity;
168       FT_Long    in_offset;
169       
170
171       in_offset = (FT_Long)((FT_Byte*)object - table->block);
172       if ( (FT_ULong)in_offset >= table->capacity )
173         in_offset = -1;
174
175       while ( new_size < table->cursor + length )
176         new_size += 1024;
177
178       error = reallocate_t1_table( table, new_size );
179       if ( error )
180         return error;
181       
182       if ( in_offset >= 0 )
183         object = table->block + in_offset;
184     }
185
186     /* add the object to the base block and adjust offset */
187     table->elements[index] = table->block + table->cursor;
188     table->lengths [index] = length;
189     MEM_Copy( table->block + table->cursor, object, length );
190
191     table->cursor += length;
192     return PSaux_Err_Ok;
193   }
194
195
196   /*************************************************************************/
197   /*                                                                       */
198   /* <Function>                                                            */
199   /*    PS_Table_Done                                                      */
200   /*                                                                       */
201   /* <Description>                                                         */
202   /*    Finalizes a PS_Table (i.e., reallocate it to its current cursor).  */
203   /*                                                                       */
204   /* <InOut>                                                               */
205   /*    table :: The target table.                                         */
206   /*                                                                       */
207   /* <Note>                                                                */
208   /*    This function does NOT release the heap's memory block.  It is up  */
209   /*    to the caller to clean it, or reference it in its own structures.  */
210   /*                                                                       */
211   FT_LOCAL_DEF void
212   PS_Table_Done( PS_Table*  table )
213   {
214     FT_Memory  memory = table->memory;
215     FT_Error   error;
216     FT_Byte*   old_base = table->block;
217
218
219     /* should never fail, because rec.cursor <= rec.size */
220     if ( !old_base )
221       return;
222
223     if ( ALLOC( table->block, table->cursor ) )
224       return;
225     MEM_Copy( table->block, old_base, table->cursor );
226     shift_elements( table, old_base );
227
228     table->capacity = table->cursor;
229     FREE( old_base );
230   }
231
232
233   FT_LOCAL_DEF void
234   PS_Table_Release( PS_Table*  table )
235   {
236     FT_Memory  memory = table->memory;
237
238
239     if ( (FT_ULong)table->init == 0xDEADBEEFUL )
240     {
241       FREE( table->block );
242       FREE( table->elements );
243       FREE( table->lengths );
244       table->init = 0;
245     }
246   }
247
248
249   /*************************************************************************/
250   /*************************************************************************/
251   /*****                                                               *****/
252   /*****                            T1 PARSER                          *****/
253   /*****                                                               *****/
254   /*************************************************************************/
255   /*************************************************************************/
256
257
258 #define IS_T1_WHITESPACE( c )  ( (c) == ' '  || (c) == '\t' )
259 #define IS_T1_LINESPACE( c )   ( (c) == '\r' || (c) == '\n' )
260
261 #define IS_T1_SPACE( c )  ( IS_T1_WHITESPACE( c ) || IS_T1_LINESPACE( c ) )
262
263
264   FT_LOCAL_DEF void
265   T1_Skip_Spaces( T1_Parser*  parser )
266   {
267     FT_Byte* cur   = parser->cursor;
268     FT_Byte* limit = parser->limit;
269
270
271     while ( cur < limit )
272     {
273       FT_Byte  c = *cur;
274
275
276       if ( !IS_T1_SPACE( c ) )
277         break;
278       cur++;
279     }
280     parser->cursor = cur;
281   }
282
283
284   FT_LOCAL_DEF void
285   T1_Skip_Alpha( T1_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_T1_SPACE( c ) )
297         break;
298       cur++;
299     }
300     parser->cursor = cur;
301   }
302
303
304   FT_LOCAL_DEF void
305   T1_ToToken( T1_Parser*  parser,
306               T1_Token*   token )
307   {
308     FT_Byte*  cur;
309     FT_Byte*  limit;
310     FT_Byte   starter, ender;
311     FT_Int    embed;
312
313
314     token->type  = t1_token_none;
315     token->start = 0;
316     token->limit = 0;
317
318     /* first of all, skip space */
319     T1_Skip_Spaces( parser );
320
321     cur   = parser->cursor;
322     limit = parser->limit;
323
324     if ( cur < limit )
325     {
326       switch ( *cur )
327       {
328         /************* check for strings ***********************/
329       case '(':
330         token->type = t1_token_string;
331         ender = ')';
332         goto Lookup_Ender;
333
334         /************* check for programs/array ****************/
335       case '{':
336         token->type = t1_token_array;
337         ender = '}';
338         goto Lookup_Ender;
339
340         /************* check for table/array ******************/
341       case '[':
342         token->type = t1_token_array;
343         ender = ']';
344
345       Lookup_Ender:
346         embed   = 1;
347         starter = *cur++;
348         token->start = cur;
349         while ( cur < limit )
350         {
351           if ( *cur == starter )
352             embed++;
353           else if ( *cur == ender )
354           {
355             embed--;
356             if ( embed <= 0 )
357             {
358               token->limit = cur++;
359               break;
360             }
361           }
362           cur++;
363         }
364         break;
365
366         /* **************** otherwise, it's any token **********/
367       default:
368         token->start = cur++;
369         token->type  = t1_token_any;
370         while ( cur < limit && !IS_T1_SPACE( *cur ) )
371           cur++;
372
373         token->limit = cur;
374       }
375
376       if ( !token->limit )
377       {
378         token->start = 0;
379         token->type  = t1_token_none;
380       }
381
382       parser->cursor = cur;
383     }
384   }
385
386
387   FT_LOCAL_DEF void
388   T1_ToTokenArray( T1_Parser*  parser,
389                    T1_Token*   tokens,
390                    FT_UInt     max_tokens,
391                    FT_Int*     pnum_tokens )
392   {
393     T1_Token  master;
394
395
396     *pnum_tokens = -1;
397
398     T1_ToToken( parser, &master );
399     if ( master.type == t1_token_array )
400     {
401       FT_Byte*   old_cursor = parser->cursor;
402       FT_Byte*   old_limit  = parser->limit;
403       T1_Token*  cur        = tokens;
404       T1_Token*  limit      = cur + max_tokens;
405
406
407       parser->cursor = master.start;
408       parser->limit  = master.limit;
409
410       while ( parser->cursor < parser->limit )
411       {
412         T1_Token  token;
413
414
415         T1_ToToken( parser, &token );
416         if ( !token.type )
417           break;
418
419         if ( cur < limit )
420           *cur = token;
421
422         cur++;
423       }
424
425       *pnum_tokens = (FT_Int)( cur - tokens );
426
427       parser->cursor = old_cursor;
428       parser->limit  = old_limit;
429     }
430   }
431
432
433   static FT_Long
434   t1_toint( FT_Byte**  cursor,
435             FT_Byte*   limit )
436   {
437     FT_Long   result = 0;
438     FT_Byte*  cur    = *cursor;
439     FT_Byte   c = '\0', d;
440
441
442     for ( ; cur < limit; cur++ )
443     {
444       c = *cur;
445       d = (FT_Byte)( c - '0' );
446       if ( d < 10 )
447         break;
448
449       if ( c == '-' )
450       {
451         cur++;
452         break;
453       }
454     }
455
456     if ( cur < limit )
457     {
458       do
459       {
460         d = (FT_Byte)( cur[0] - '0' );
461         if ( d >= 10 )
462           break;
463
464         result = result * 10 + d;
465         cur++;
466
467       } while ( cur < limit );
468
469       if ( c == '-' )
470         result = -result;
471     }
472
473     *cursor = cur;
474     return result;
475   }
476
477
478   static FT_Long
479   t1_tofixed( FT_Byte**  cursor,
480               FT_Byte*   limit,
481               FT_Long    power_ten )
482   {
483     FT_Byte*  cur  = *cursor;
484     FT_Long   num, divider, result;
485     FT_Int    sign = 0;
486     FT_Byte   d;
487
488
489     if ( cur >= limit )
490       return 0;
491
492     /* first of all, check the sign */
493     if ( *cur == '-' )
494     {
495       sign = 1;
496       cur++;
497     }
498
499     /* then, read the integer part, if any */
500     if ( *cur != '.' )
501       result = t1_toint( &cur, limit ) << 16;
502     else
503       result = 0;
504
505     num     = 0;
506     divider = 1;
507
508     if ( cur >= limit )
509       goto Exit;
510
511     /* read decimal part, if any */
512     if ( *cur == '.' && cur + 1 < limit )
513     {
514       cur++;
515
516       for (;;)
517       {
518         d = (FT_Byte)( *cur - '0' );
519         if ( d >= 10 )
520           break;
521
522         if ( divider < 10000000L )
523         {
524           num      = num * 10 + d;
525           divider *= 10;
526         }
527
528         cur++;
529         if ( cur >= limit )
530           break;
531       }
532     }
533
534     /* read exponent, if any */
535     if ( cur + 1 < limit && ( *cur == 'e' || *cur == 'E' ) )
536     {
537       cur++;
538       power_ten += t1_toint( &cur, limit );
539     }
540
541   Exit:
542     /* raise to power of ten if needed */
543     while ( power_ten > 0 )
544     {
545       result = result * 10;
546       num    = num * 10;
547       power_ten--;
548     }
549
550     while ( power_ten < 0 )
551     {
552       result  = result / 10;
553       divider = divider * 10;
554       power_ten++;
555     }
556
557     if ( num )
558       result += FT_DivFix( num, divider );
559
560     if ( sign )
561       result = -result;
562
563     *cursor = cur;
564     return result;
565   }
566
567
568   static FT_Int
569   t1_tocoordarray( FT_Byte**  cursor,
570                    FT_Byte*   limit,
571                    FT_Int     max_coords,
572                    FT_Short*  coords )
573   {
574     FT_Byte*  cur   = *cursor;
575     FT_Int    count = 0;
576     FT_Byte   c, ender;
577
578
579     if ( cur >= limit )
580       goto Exit;
581
582     /* check for the beginning of an array; if not, only one number will */
583     /* be read                                                           */
584     c     = *cur;
585     ender = 0;
586
587     if ( c == '[' )
588       ender = ']';
589
590     if ( c == '{' )
591       ender = '}';
592
593     if ( ender )
594       cur++;
595
596     /* now, read the coordinates */
597     for ( ; cur < limit; )
598     {
599       /* skip whitespace in front of data */
600       for (;;)
601       {
602         c = *cur;
603         if ( c != ' ' && c != '\t' )
604           break;
605
606         cur++;
607         if ( cur >= limit )
608           goto Exit;
609       }
610
611       if ( count >= max_coords || c == ender )
612         break;
613
614       coords[count] = (FT_Short)( t1_tofixed( &cur, limit, 0 ) >> 16 );
615       count++;
616
617       if ( !ender )
618         break;
619     }
620
621   Exit:
622     *cursor = cur;
623     return count;
624   }
625
626
627   static FT_Int
628   t1_tofixedarray( FT_Byte**  cursor,
629                    FT_Byte*   limit,
630                    FT_Int     max_values,
631                    FT_Fixed*  values,
632                    FT_Int     power_ten )
633   {
634     FT_Byte*  cur   = *cursor;
635     FT_Int    count = 0;
636     FT_Byte   c, ender;
637
638
639     if ( cur >= limit ) goto Exit;
640
641     /* check for the beginning of an array. If not, only one number will */
642     /* be read                                                           */
643     c     = *cur;
644     ender = 0;
645
646     if ( c == '[' )
647       ender = ']';
648
649     if ( c == '{' )
650       ender = '}';
651
652     if ( ender )
653       cur++;
654
655     /* now, read the values */
656     for ( ; cur < limit; )
657     {
658       /* skip whitespace in front of data */
659       for (;;)
660       {
661         c = *cur;
662         if ( c != ' ' && c != '\t' )
663           break;
664
665         cur++;
666         if ( cur >= limit )
667           goto Exit;
668       }
669
670       if ( count >= max_values || c == ender )
671         break;
672
673       values[count] = t1_tofixed( &cur, limit, power_ten );
674       count++;
675
676       if ( !ender )
677         break;
678     }
679
680   Exit:
681     *cursor = cur;
682     return count;
683   }
684
685
686 #if 0
687
688   static FT_String*
689   t1_tostring( FT_Byte**  cursor,
690                FT_Byte*   limit,
691                FT_Memory  memory )
692   {
693     FT_Byte*    cur = *cursor;
694     FT_Int      len = 0;
695     FT_Int      count;
696     FT_String*  result;
697     FT_Error    error;
698
699
700     /* XXX: some stupid fonts have a `Notice' or `Copyright' string     */
701     /*      that simply doesn't begin with an opening parenthesis, even */
702     /*      though they have a closing one!  E.g. "amuncial.pfb"        */
703     /*                                                                  */
704     /*      We must deal with these ill-fated cases there.  Note that   */
705     /*      these fonts didn't work with the old Type 1 driver as the   */
706     /*      notice/copyright was not recognized as a valid string token */
707     /*      and made the old token parser commit errors.                */
708
709     while ( cur < limit && ( *cur == ' ' || *cur == '\t' ) )
710       cur++;
711     if ( cur + 1 >= limit )
712       return 0;
713
714     if ( *cur == '(' )
715       cur++;  /* skip the opening parenthesis, if there is one */
716
717     *cursor = cur;
718     count   = 0;
719
720     /* then, count its length */
721     for ( ; cur < limit; cur++ )
722     {
723       if ( *cur == '(' )
724         count++;
725
726       else if ( *cur == ')' )
727       {
728         count--;
729         if ( count < 0 )
730           break;
731       }
732     }
733
734     len = cur - *cursor;
735     if ( cur >= limit || ALLOC( result, len + 1 ) )
736       return 0;
737
738     /* now copy the string */
739     MEM_Copy( result, *cursor, len );
740     result[len] = '\0';
741     *cursor = cur;
742     return result;
743   }
744
745 #endif /* 0 */
746
747
748   static int
749   t1_tobool( FT_Byte**  cursor,
750              FT_Byte*   limit )
751   {
752     FT_Byte*  cur    = *cursor;
753     FT_Bool   result = 0;
754
755
756     /* return 1 if we find `true', 0 otherwise */
757     if ( cur + 3 < limit &&
758          cur[0] == 't' &&
759          cur[1] == 'r' &&
760          cur[2] == 'u' &&
761          cur[3] == 'e' )
762     {
763       result = 1;
764       cur   += 5;
765     }
766     else if ( cur + 4 < limit &&
767               cur[0] == 'f' &&
768               cur[1] == 'a' &&
769               cur[2] == 'l' &&
770               cur[3] == 's' &&
771               cur[4] == 'e' )
772     {
773       result = 0;
774       cur   += 6;
775     }
776
777     *cursor = cur;
778     return result;
779   }
780
781
782   /* Load a simple field (i.e. non-table) into the current list of objects */
783   FT_LOCAL_DEF FT_Error
784   T1_Load_Field( T1_Parser*       parser,
785                  const T1_Field*  field,
786                  void**           objects,
787                  FT_UInt          max_objects,
788                  FT_ULong*        pflags )
789   {
790     T1_Token  token;
791     FT_Byte*  cur;
792     FT_Byte*  limit;
793     FT_UInt   count;
794     FT_UInt   index;
795     FT_Error  error;
796
797
798     T1_ToToken( parser, &token );
799     if ( !token.type )
800       goto Fail;
801
802     count = 1;
803     index = 0;
804     cur   = token.start;
805     limit = token.limit;
806
807     if ( token.type == t1_token_array )
808     {
809       /* if this is an array, and we have no blend, an error occurs */
810       if ( max_objects == 0 )
811         goto Fail;
812
813       count = max_objects;
814       index = 1;
815     }
816
817     for ( ; count > 0; count--, index++ )
818     {
819       FT_Byte*    q = (FT_Byte*)objects[index] + field->offset;
820       FT_Long     val;
821       FT_String*  string;
822
823
824       switch ( field->type )
825       {
826       case t1_field_bool:
827         val = t1_tobool( &cur, limit );
828         goto Store_Integer;
829
830       case t1_field_fixed:
831         val = t1_tofixed( &cur, limit, 3 );
832         goto Store_Integer;
833
834       case t1_field_integer:
835         val = t1_toint( &cur, limit );
836
837       Store_Integer:
838         switch ( field->size )
839         {
840         case 1:
841           *(FT_Byte*)q = (FT_Byte)val;
842           break;
843
844         case 2:
845           *(FT_UShort*)q = (FT_UShort)val;
846           break;
847
848         case 4:
849           *(FT_UInt32*)q = (FT_UInt32)val;
850           break;
851
852         default:  /* for 64-bit systems */
853           *(FT_Long*)q = val;
854         }
855         break;
856
857       case t1_field_string:
858         {
859           FT_Memory  memory = parser->memory;
860           FT_UInt    len    = (FT_UInt)( limit - cur );
861
862
863           if ( *(FT_String**)q )
864             /* with synthetic fonts, it's possible to find a field twice */
865             break;
866
867           if ( ALLOC( string, len + 1 ) )
868             goto Exit;
869
870           MEM_Copy( string, cur, len );
871           string[len] = 0;
872
873           *(FT_String**)q = string;
874         }
875         break;
876
877       default:
878         /* an error occured */
879         goto Fail;
880       }
881     }
882
883 #if 0  /* obsolete - keep for reference */
884     if ( pflags )
885       *pflags |= 1L << field->flag_bit;
886 #else
887     FT_UNUSED( pflags );
888 #endif
889
890     error = PSaux_Err_Ok;
891
892   Exit:
893     return error;
894
895   Fail:
896     error = PSaux_Err_Invalid_File_Format;
897     goto Exit;
898   }
899
900
901 #define T1_MAX_TABLE_ELEMENTS  32
902
903
904   FT_LOCAL_DEF FT_Error
905   T1_Load_Field_Table( T1_Parser*       parser,
906                        const T1_Field*  field,
907                        void**           objects,
908                        FT_UInt          max_objects,
909                        FT_ULong*        pflags )
910   {
911     T1_Token   elements[T1_MAX_TABLE_ELEMENTS];
912     T1_Token*  token;
913     FT_Int     num_elements;
914     FT_Error   error = 0;
915     FT_Byte*   old_cursor;
916     FT_Byte*   old_limit;
917     T1_Field   fieldrec = *(T1_Field*)field;
918
919 #if 1
920     fieldrec.type = t1_field_integer;
921     if ( field->type == t1_field_fixed_array )
922       fieldrec.type = t1_field_fixed;
923 #endif
924
925     T1_ToTokenArray( parser, elements, 32, &num_elements );
926     if ( num_elements < 0 )
927       goto Fail;
928
929     if ( num_elements > T1_MAX_TABLE_ELEMENTS )
930       num_elements = T1_MAX_TABLE_ELEMENTS;
931
932     old_cursor = parser->cursor;
933     old_limit  = parser->limit;
934
935     /* we store the elements count */
936     *(FT_Byte*)( (FT_Byte*)objects[0] + field->count_offset ) =
937       (FT_Byte)num_elements;
938
939     /* we now load each element, adjusting the field.offset on each one */
940     token = elements;
941     for ( ; num_elements > 0; num_elements--, token++ )
942     {
943       parser->cursor = token->start;
944       parser->limit  = token->limit;
945       T1_Load_Field( parser, &fieldrec, objects, max_objects, 0 );
946       fieldrec.offset += fieldrec.size;
947     }
948
949 #if 0  /* obsolete -- keep for reference */
950     if ( pflags )
951       *pflags |= 1L << field->flag_bit;
952 #else
953     FT_UNUSED( pflags );
954 #endif
955
956     parser->cursor = old_cursor;
957     parser->limit  = old_limit;
958
959   Exit:
960     return error;
961
962   Fail:
963     error = PSaux_Err_Invalid_File_Format;
964     goto Exit;
965   }
966
967
968   FT_LOCAL_DEF FT_Long
969   T1_ToInt( T1_Parser*  parser )
970   {
971     return t1_toint( &parser->cursor, parser->limit );
972   }
973
974
975   FT_LOCAL_DEF FT_Fixed
976   T1_ToFixed( T1_Parser*  parser,
977               FT_Int      power_ten )
978   {
979     return t1_tofixed( &parser->cursor, parser->limit, power_ten );
980   }
981
982
983   FT_LOCAL_DEF FT_Int
984   T1_ToCoordArray( T1_Parser*  parser,
985                    FT_Int      max_coords,
986                    FT_Short*   coords )
987   {
988     return t1_tocoordarray( &parser->cursor, parser->limit,
989                             max_coords, coords );
990   }
991
992
993   FT_LOCAL_DEF FT_Int
994   T1_ToFixedArray( T1_Parser*  parser,
995                    FT_Int      max_values,
996                    FT_Fixed*   values,
997                    FT_Int      power_ten )
998   {
999     return t1_tofixedarray( &parser->cursor, parser->limit,
1000                             max_values, values, power_ten );
1001   }
1002
1003
1004 #if 0
1005
1006   FT_LOCAL_DEF FT_String*
1007   T1_ToString( T1_Parser*  parser )
1008   {
1009     return t1_tostring( &parser->cursor, parser->limit, parser->memory );
1010   }
1011
1012
1013   FT_LOCAL_DEF FT_Bool
1014   T1_ToBool( T1_Parser*  parser )
1015   {
1016     return t1_tobool( &parser->cursor, parser->limit );
1017   }
1018
1019 #endif /* 0 */
1020
1021
1022   FT_LOCAL_DEF void
1023   T1_Init_Parser( T1_Parser*  parser,
1024                   FT_Byte*    base,
1025                   FT_Byte*    limit,
1026                   FT_Memory   memory )
1027   {
1028     parser->error  = 0;
1029     parser->base   = base;
1030     parser->limit  = limit;
1031     parser->cursor = base;
1032     parser->memory = memory;
1033     parser->funcs  = t1_parser_funcs;
1034   }
1035
1036
1037   FT_LOCAL_DEF void
1038   T1_Done_Parser( T1_Parser*  parser )
1039   {
1040     FT_UNUSED( parser );
1041   }
1042
1043
1044   /*************************************************************************/
1045   /*************************************************************************/
1046   /*****                                                               *****/
1047   /*****                            T1 BUILDER                         *****/
1048   /*****                                                               *****/
1049   /*************************************************************************/
1050   /*************************************************************************/
1051
1052   /*************************************************************************/
1053   /*                                                                       */
1054   /* <Function>                                                            */
1055   /*    T1_Builder_Init                                                    */
1056   /*                                                                       */
1057   /* <Description>                                                         */
1058   /*    Initializes a given glyph builder.                                 */
1059   /*                                                                       */
1060   /* <InOut>                                                               */
1061   /*    builder :: A pointer to the glyph builder to initialize.           */
1062   /*                                                                       */
1063   /* <Input>                                                               */
1064   /*    face    :: The current face object.                                */
1065   /*                                                                       */
1066   /*    size    :: The current size object.                                */
1067   /*                                                                       */
1068   /*    glyph   :: The current glyph object.                               */
1069   /*                                                                       */
1070   FT_LOCAL_DEF void
1071   T1_Builder_Init( T1_Builder*   builder,
1072                    FT_Face       face,
1073                    FT_Size       size,
1074                    FT_GlyphSlot  glyph )
1075   {
1076     builder->path_begun  = 0;
1077     builder->load_points = 1;
1078
1079     builder->face   = face;
1080     builder->glyph  = glyph;
1081     builder->memory = face->memory;
1082
1083     if ( glyph )
1084     {
1085       FT_GlyphLoader*  loader = glyph->internal->loader;
1086
1087
1088       builder->loader  = loader;
1089       builder->base    = &loader->base.outline;
1090       builder->current = &loader->current.outline;
1091       FT_GlyphLoader_Rewind( loader );
1092     }
1093
1094     if ( size )
1095     {
1096       builder->scale_x = size->metrics.x_scale;
1097       builder->scale_y = size->metrics.y_scale;
1098     }
1099
1100     builder->pos_x = 0;
1101     builder->pos_y = 0;
1102
1103     builder->left_bearing.x = 0;
1104     builder->left_bearing.y = 0;
1105     builder->advance.x      = 0;
1106     builder->advance.y      = 0;
1107
1108     builder->funcs = t1_builder_funcs;
1109   }
1110
1111
1112   /*************************************************************************/
1113   /*                                                                       */
1114   /* <Function>                                                            */
1115   /*    T1_Builder_Done                                                    */
1116   /*                                                                       */
1117   /* <Description>                                                         */
1118   /*    Finalizes a given glyph builder.  Its contents can still be used   */
1119   /*    after the call, but the function saves important information       */
1120   /*    within the corresponding glyph slot.                               */
1121   /*                                                                       */
1122   /* <Input>                                                               */
1123   /*    builder :: A pointer to the glyph builder to finalize.             */
1124   /*                                                                       */
1125   FT_LOCAL_DEF void
1126   T1_Builder_Done( T1_Builder*  builder )
1127   {
1128     FT_GlyphSlot  glyph = builder->glyph;
1129
1130
1131     if ( glyph )
1132       glyph->outline = *builder->base;
1133   }
1134
1135
1136   /* check that there is enough room for `count' more points */
1137   FT_LOCAL_DEF FT_Error
1138   T1_Builder_Check_Points( T1_Builder*  builder,
1139                            FT_Int       count )
1140   {
1141     return FT_GlyphLoader_Check_Points( builder->loader, count, 0 );
1142   }
1143
1144
1145   /* add a new point, do not check space */
1146   FT_LOCAL_DEF void
1147   T1_Builder_Add_Point( T1_Builder*  builder,
1148                         FT_Pos       x,
1149                         FT_Pos       y,
1150                         FT_Byte      flag )
1151   {
1152     FT_Outline*  outline = builder->current;
1153
1154
1155     if ( builder->load_points )
1156     {
1157       FT_Vector*  point   = outline->points + outline->n_points;
1158       FT_Byte*    control = (FT_Byte*)outline->tags + outline->n_points;
1159
1160
1161       if ( builder->shift )
1162       {
1163         x >>= 16;
1164         y >>= 16;
1165       }
1166       point->x = x;
1167       point->y = y;
1168       *control = (FT_Byte)( flag ? FT_Curve_Tag_On : FT_Curve_Tag_Cubic );
1169
1170       builder->last = *point;
1171     }
1172     outline->n_points++;
1173   }
1174
1175
1176   /* check space for a new on-curve point, then add it */
1177   FT_LOCAL_DEF FT_Error
1178   T1_Builder_Add_Point1( T1_Builder*  builder,
1179                          FT_Pos       x,
1180                          FT_Pos       y )
1181   {
1182     FT_Error  error;
1183
1184
1185     error = T1_Builder_Check_Points( builder, 1 );
1186     if ( !error )
1187       T1_Builder_Add_Point( builder, x, y, 1 );
1188
1189     return error;
1190   }
1191
1192
1193   /* check room for a new contour, then add it */
1194   FT_LOCAL_DEF FT_Error
1195   T1_Builder_Add_Contour( T1_Builder*  builder )
1196   {
1197     FT_Outline*  outline = builder->current;
1198     FT_Error     error;
1199
1200
1201     if ( !builder->load_points )
1202     {
1203       outline->n_contours++;
1204       return PSaux_Err_Ok;
1205     }
1206
1207     error = FT_GlyphLoader_Check_Points( builder->loader, 0, 1 );
1208     if ( !error )
1209     {
1210       if ( outline->n_contours > 0 )
1211         outline->contours[outline->n_contours - 1] =
1212           (short)( outline->n_points - 1 );
1213
1214       outline->n_contours++;
1215     }
1216
1217     return error;
1218   }
1219
1220
1221   /* if a path was begun, add its first on-curve point */
1222   FT_LOCAL_DEF FT_Error
1223   T1_Builder_Start_Point( T1_Builder*  builder,
1224                           FT_Pos       x,
1225                           FT_Pos       y )
1226   {
1227     FT_Error  error = 0;
1228
1229
1230     /* test whether we are building a new contour */
1231     if ( !builder->path_begun )
1232     {
1233       builder->path_begun = 1;
1234       error = T1_Builder_Add_Contour( builder );
1235       if ( !error )
1236         error = T1_Builder_Add_Point1( builder, x, y );
1237     }
1238     return error;
1239   }
1240
1241
1242   /* close the current contour */
1243   FT_LOCAL_DEF void
1244   T1_Builder_Close_Contour( T1_Builder*  builder )
1245   {
1246     FT_Outline*  outline = builder->current;
1247
1248
1249     /* XXXX: We must not include the last point in the path if it */
1250     /*       is located on the first point.                       */
1251     if ( outline->n_points > 1 )
1252     {
1253       FT_Int      first   = 0;
1254       FT_Vector*  p1      = outline->points + first;
1255       FT_Vector*  p2      = outline->points + outline->n_points - 1;
1256       FT_Byte*    control = (FT_Byte*)outline->tags + outline->n_points - 1;
1257
1258
1259       if ( outline->n_contours > 1 )
1260       {
1261         first = outline->contours[outline->n_contours - 2] + 1;
1262         p1    = outline->points + first;
1263       }
1264
1265       /* `delete' last point only if it coincides with the first */
1266       /* point and it is not a control point (which can happen). */
1267       if ( p1->x == p2->x && p1->y == p2->y )
1268         if ( *control == FT_Curve_Tag_On )
1269           outline->n_points--;
1270     }
1271
1272     if ( outline->n_contours > 0 )
1273       outline->contours[outline->n_contours - 1] =
1274         (short)( outline->n_points - 1 );
1275   }
1276
1277
1278   /*************************************************************************/
1279   /*************************************************************************/
1280   /*****                                                               *****/
1281   /*****                            OTHER                              *****/
1282   /*****                                                               *****/
1283   /*************************************************************************/
1284   /*************************************************************************/
1285
1286   FT_LOCAL_DEF void
1287   T1_Decrypt( FT_Byte*   buffer,
1288               FT_Offset  length,
1289               FT_UShort  seed )
1290   {
1291     while ( length > 0 )
1292     {
1293       FT_Byte  plain;
1294
1295
1296       plain     = (FT_Byte)( *buffer ^ ( seed >> 8 ) );
1297       seed      = (FT_UShort)( ( *buffer + seed ) * 52845U + 22719 );
1298       *buffer++ = plain;
1299       length--;
1300     }
1301   }
1302
1303
1304 /* END */