source: trunk/poppler/freetype-2.1.10/src/psaux/psobjs.c @ 2

Last change on this file since 2 was 2, checked in by Eugene Romanenko, 15 years ago

First import

File size: 46.6 KB
Line 
1/***************************************************************************/
2/*                                                                         */
3/*  psobjs.c                                                               */
4/*                                                                         */
5/*    Auxiliary functions for PostScript fonts (body).                     */
6/*                                                                         */
7/*  Copyright 1996-2001, 2002, 2003, 2004, 2005 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 ( FT_NEW_ARRAY( table->elements, count ) ||
66         FT_NEW_ARRAY( table->lengths,  count ) )
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
76    *(PS_Table_FuncsRec*)&table->funcs = ps_table_funcs;
77
78  Exit:
79    if ( error )
80      FT_FREE( table->elements );
81
82    return error;
83  }
84
85
86  static void
87  shift_elements( PS_Table  table,
88                  FT_Byte*  old_base )
89  {
90    FT_Long    delta  = (FT_Long)( table->block - old_base );
91    FT_Byte**  offset = table->elements;
92    FT_Byte**  limit  = offset + table->max_elems;
93
94
95    for ( ; offset < limit; offset++ )
96    {
97      if ( offset[0] )
98        offset[0] += delta;
99    }
100  }
101
102
103  static FT_Error
104  reallocate_t1_table( PS_Table  table,
105                       FT_Long   new_size )
106  {
107    FT_Memory  memory   = table->memory;
108    FT_Byte*   old_base = table->block;
109    FT_Error   error;
110
111
112    /* allocate new base block */
113    if ( FT_ALLOC( table->block, new_size ) )
114    {
115      table->block = old_base;
116      return error;
117    }
118
119    /* copy elements and shift offsets */
120    if (old_base )
121    {
122      FT_MEM_COPY( table->block, old_base, table->capacity );
123      shift_elements( table, old_base );
124      FT_FREE( old_base );
125    }
126
127    table->capacity = new_size;
128
129    return PSaux_Err_Ok;
130  }
131
132
133  /*************************************************************************/
134  /*                                                                       */
135  /* <Function>                                                            */
136  /*    ps_table_add                                                       */
137  /*                                                                       */
138  /* <Description>                                                         */
139  /*    Adds an object to a PS_Table, possibly growing its memory block.   */
140  /*                                                                       */
141  /* <InOut>                                                               */
142  /*    table  :: The target table.                                        */
143  /*                                                                       */
144  /* <Input>                                                               */
145  /*    idx    :: The index of the object in the table.                    */
146  /*                                                                       */
147  /*    object :: The address of the object to copy in memory.             */
148  /*                                                                       */
149  /*    length :: The length in bytes of the source object.                */
150  /*                                                                       */
151  /* <Return>                                                              */
152  /*    FreeType error code.  0 means success.  An error is returned if a  */
153  /*    reallocation fails.                                                */
154  /*                                                                       */
155  FT_LOCAL_DEF( FT_Error )
156  ps_table_add( PS_Table    table,
157                FT_Int      idx,
158                void*       object,
159                FT_PtrDist  length )
160  {
161    if ( idx < 0 || idx > table->max_elems )
162    {
163      FT_ERROR(( "ps_table_add: invalid index\n" ));
164      return PSaux_Err_Invalid_Argument;
165    }
166
167    /* grow the base block if needed */
168    if ( table->cursor + length > table->capacity )
169    {
170      FT_Error   error;
171      FT_Offset  new_size  = table->capacity;
172      FT_Long    in_offset;
173
174
175      in_offset = (FT_Long)((FT_Byte*)object - table->block);
176      if ( (FT_ULong)in_offset >= table->capacity )
177        in_offset = -1;
178
179      while ( new_size < table->cursor + length )
180      {
181        /* increase size by 25% and round up to the nearest multiple
182           of 1024 */
183        new_size += ( new_size >> 2 ) + 1;
184        new_size  = FT_PAD_CEIL( new_size, 1024 );
185      }
186
187      error = reallocate_t1_table( table, new_size );
188      if ( error )
189        return error;
190
191      if ( in_offset >= 0 )
192        object = table->block + in_offset;
193    }
194
195    /* add the object to the base block and adjust offset */
196    table->elements[idx] = table->block + table->cursor;
197    table->lengths [idx] = length;
198    FT_MEM_COPY( table->block + table->cursor, object, length );
199
200    table->cursor += length;
201    return PSaux_Err_Ok;
202  }
203
204
205  /*************************************************************************/
206  /*                                                                       */
207  /* <Function>                                                            */
208  /*    ps_table_done                                                      */
209  /*                                                                       */
210  /* <Description>                                                         */
211  /*    Finalizes a PS_TableRec (i.e., reallocate it to its current        */
212  /*    cursor).                                                           */
213  /*                                                                       */
214  /* <InOut>                                                               */
215  /*    table :: The target table.                                         */
216  /*                                                                       */
217  /* <Note>                                                                */
218  /*    This function does NOT release the heap's memory block.  It is up  */
219  /*    to the caller to clean it, or reference it in its own structures.  */
220  /*                                                                       */
221  FT_LOCAL_DEF( void )
222  ps_table_done( PS_Table  table )
223  {
224    FT_Memory  memory = table->memory;
225    FT_Error   error;
226    FT_Byte*   old_base = table->block;
227
228
229    /* should never fail, because rec.cursor <= rec.size */
230    if ( !old_base )
231      return;
232
233    if ( FT_ALLOC( table->block, table->cursor ) )
234      return;
235    FT_MEM_COPY( table->block, old_base, table->cursor );
236    shift_elements( table, old_base );
237
238    table->capacity = table->cursor;
239    FT_FREE( old_base );
240
241    FT_UNUSED( error );
242  }
243
244
245  FT_LOCAL_DEF( void )
246  ps_table_release( PS_Table  table )
247  {
248    FT_Memory  memory = table->memory;
249
250
251    if ( (FT_ULong)table->init == 0xDEADBEEFUL )
252    {
253      FT_FREE( table->block );
254      FT_FREE( table->elements );
255      FT_FREE( table->lengths );
256      table->init = 0;
257    }
258  }
259
260
261  /*************************************************************************/
262  /*************************************************************************/
263  /*****                                                               *****/
264  /*****                            T1 PARSER                          *****/
265  /*****                                                               *****/
266  /*************************************************************************/
267  /*************************************************************************/
268
269  /* In the PostScript Language Reference Manual (PLRM) the following */
270  /* characters are called `whitespace characters'.                   */
271#define IS_T1_WHITESPACE( c )  ( (c) == ' '  || (c) == '\t' )
272#define IS_T1_LINESPACE( c )   ( (c) == '\r' || (c) == '\n' || (c) == '\f' )
273#define IS_T1_NULLSPACE( c )   ( (c) == '\0' )
274
275  /* According to the PLRM all whitespace characters are equivalent, */
276  /* except in comments and strings.                                 */
277#define IS_T1_SPACE( c )  ( IS_T1_WHITESPACE( c ) || \
278                            IS_T1_LINESPACE( c )  || \
279                            IS_T1_NULLSPACE( c )  )
280
281
282  /* The following array is used by various functions to quickly convert */
283  /* digits (both decimal and non-decimal) into numbers.                 */
284
285#if 'A' == 65
286  /* ASCII */
287
288  static const char  ft_char_table[128] =
289  {
290    /* 0x00 */
291    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
292    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
293    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
294     0,  1,  2,  3,  4,  5,  6,  7,  8,  9, -1, -1, -1, -1, -1, -1,
295    -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
296    25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1,
297    -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
298    25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1,
299  };
300
301  /* no character >= 0x80 can represent a valid number */
302#define OP  >=
303
304#endif /* 'A' == 65 */
305
306#if 'A' == 193
307  /* EBCDIC */
308
309  static const char  ft_char_table[128] =
310  {
311    /* 0x80 */
312    -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, -1, -1, -1, -1, -1, -1,
313    -1, 19, 20, 21, 22, 23, 24, 25, 26, 27, -1, -1, -1, -1, -1, -1,
314    -1, -1, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1, -1,
315    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
316    -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, -1, -1, -1, -1, -1, -1,
317    -1, 19, 20, 21, 22, 23, 24, 25, 26, 27, -1, -1, -1, -1, -1, -1,
318    -1, -1, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1, -1,
319     0,  1,  2,  3,  4,  5,  6,  7,  8,  9, -1, -1, -1, -1, -1, -1,
320  }
321
322  /* no character < 0x80 can represent a valid number */
323#define OP  <
324
325#endif /* 'A' == 193 */
326
327
328  /* first character must be already part of the comment */
329
330  static void
331  skip_comment( FT_Byte*  *acur,
332                FT_Byte*   limit )
333  {
334    FT_Byte*  cur = *acur;
335
336
337    while ( cur < limit )
338    {
339      if ( IS_T1_LINESPACE( *cur ) )
340        break;
341      cur++;
342    }
343
344    *acur = cur;
345  }
346
347
348  static void
349  skip_spaces( FT_Byte*  *acur,
350               FT_Byte*   limit )
351  {
352    FT_Byte*  cur = *acur;
353
354
355    while ( cur < limit )
356    {
357      if ( !IS_T1_SPACE( *cur ) )
358      {
359        if ( *cur == '%' )
360          /* According to the PLRM, a comment is equal to a space. */
361          skip_comment( &cur, limit );
362        else
363          break;
364      }
365      cur++;
366    }
367
368    *acur = cur;
369  }
370
371
372  /* first character must be `(' */
373
374  static void
375  skip_literal_string( FT_Byte*  *acur,
376                       FT_Byte*   limit )
377  {
378    FT_Byte*  cur   = *acur;
379    FT_Int    embed = 0;
380
381
382    while ( cur < limit )
383    {
384      if ( *cur == '\\' )
385        cur++;
386      else if ( *cur == '(' )
387        embed++;
388      else if ( *cur == ')' )
389      {
390        embed--;
391        if ( embed == 0 )
392        {
393          cur++;
394          break;
395        }
396      }
397      cur++;
398    }
399
400    *acur = cur;
401  }
402
403
404  /* first character must be `<' */
405
406  static void
407  skip_string( PS_Parser  parser )
408  {
409    FT_Byte*  cur   = parser->cursor;
410    FT_Byte*  limit = parser->limit;
411
412
413    while ( ++cur < limit )
414    {
415      int  d;
416
417
418      /* All whitespace characters are ignored. */
419      skip_spaces( &cur, limit );
420      if ( cur >= limit )
421        break;
422
423      if ( *cur OP 0x80 )
424        break;
425
426      d = ft_char_table[*cur & 0x7F];
427      if ( d < 0 || d >= 16 )
428        break;
429    }
430
431    if ( cur < limit && *cur != '>' )
432    {
433      FT_ERROR(( "skip_string: missing closing delimiter `>'\n" ));
434      parser->error = PSaux_Err_Invalid_File_Format;
435    }
436    else
437      cur++;
438
439    parser->cursor = cur;
440  }
441
442
443  /***********************************************************************/
444  /*                                                                     */
445  /* All exported parsing routines handle leading whitespace and stop at */
446  /* the first character which isn't part of the just handled token.     */
447  /*                                                                     */
448  /***********************************************************************/
449
450
451  FT_LOCAL_DEF( void )
452  ps_parser_skip_PS_token( PS_Parser  parser )
453  {
454    /* Note: PostScript allows any non-delimiting, non-whitespace        */
455    /*       character in a name (PS Ref Manual, 3rd ed, p31).           */
456    /*       PostScript delimiters are (, ), <, >, [, ], {, }, /, and %. */
457
458    FT_Byte*  cur   = parser->cursor;
459    FT_Byte*  limit = parser->limit;
460
461
462    skip_spaces( &cur, limit );             /* this also skips comments */
463    if ( cur >= limit )
464      goto Exit;
465
466    /* self-delimiting, single-character tokens */
467    if ( *cur == '[' || *cur == ']' ||
468         *cur == '{' || *cur == '}' )
469    {
470      cur++;
471      goto Exit;
472    }
473
474    if ( *cur == '(' )                              /* (...) */
475    {
476      skip_literal_string( &cur, limit );
477      goto Exit;
478    }
479
480    if ( *cur == '<' )                              /* <...> */
481    {
482      if ( cur + 1 < limit && *(cur + 1) == '<' )   /* << */
483      {
484        cur++;
485        cur++;
486        goto Exit;
487      }
488      parser->cursor = cur;
489      skip_string( parser );
490      return;
491    }
492
493    if ( *cur == '>' )
494    {
495      cur++;
496      if ( cur >= limit || *cur != '>' )             /* >> */
497      {
498        FT_ERROR(( "ps_parser_skip_PS_token: "
499                   "unexpected closing delimiter `>'\n" ));
500        parser->error = PSaux_Err_Invalid_File_Format;
501        goto Exit;
502      }
503      cur++;
504      goto Exit;
505    }
506
507    if ( *cur == '/' )
508      cur++;
509
510    /* anything else */
511    while ( cur < limit )
512    {
513      if ( IS_T1_SPACE( *cur )        ||
514           *cur == '('                ||
515           *cur == '/'                ||
516           *cur == '%'                ||
517           *cur == '[' || *cur == ']' ||
518           *cur == '{' || *cur == '}' ||
519           *cur == '<' || *cur == '>' )
520        break;
521
522      if ( *cur == ')' )
523      {
524        FT_ERROR(( "ps_parser_skip_PS_token: "
525                   "unexpected closing delimiter `)'\n" ));
526        parser->error = PSaux_Err_Invalid_File_Format;
527        goto Exit;
528      }
529
530      cur++;
531    }
532
533  Exit:
534    parser->cursor = cur;
535  }
536
537
538  FT_LOCAL_DEF( void )
539  ps_parser_skip_spaces( PS_Parser  parser )
540  {
541    skip_spaces( &parser->cursor, parser->limit );
542  }
543
544
545  /* `token' here means either something between balanced delimiters */
546  /* or the next token; the delimiters are not removed.              */
547
548  FT_LOCAL_DEF( void )
549  ps_parser_to_token( PS_Parser  parser,
550                      T1_Token   token )
551  {
552    FT_Byte*  cur;
553    FT_Byte*  limit;
554    FT_Byte   starter, ender;
555    FT_Int    embed;
556
557
558    token->type  = T1_TOKEN_TYPE_NONE;
559    token->start = 0;
560    token->limit = 0;
561
562    /* first of all, skip leading whitespace */
563    ps_parser_skip_spaces( parser );
564
565    cur   = parser->cursor;
566    limit = parser->limit;
567
568    if ( cur >= limit )
569      return;
570
571    switch ( *cur )
572    {
573      /************* check for literal string *****************/
574    case '(':
575      token->type  = T1_TOKEN_TYPE_STRING;
576      token->start = cur;
577      skip_literal_string( &cur, limit );
578      if ( cur < limit )
579        token->limit = cur;
580      break;
581
582      /************* check for programs/array *****************/
583    case '{':
584      token->type = T1_TOKEN_TYPE_ARRAY;
585      ender = '}';
586      goto Lookup_Ender;
587
588      /************* check for table/array ********************/
589    case '[':
590      token->type = T1_TOKEN_TYPE_ARRAY;
591      ender = ']';
592      /* fall through */
593
594    Lookup_Ender:
595      embed        = 1;
596      starter      = *cur;
597      token->start = cur++;
598
599      /* we need this to catch `[ ]' */
600      parser->cursor = cur;
601      ps_parser_skip_spaces( parser );
602      cur = parser->cursor;
603
604      while ( cur < limit && !parser->error )
605      {
606        if ( *cur == starter )
607          embed++;
608        else if ( *cur == ender )
609        {
610          embed--;
611          if ( embed <= 0 )
612          {
613            token->limit = ++cur;
614            break;
615          }
616        }
617
618        parser->cursor = cur;
619        ps_parser_skip_PS_token( parser );
620        /* we need this to catch `[XXX ]' */
621        ps_parser_skip_spaces  ( parser );
622        cur = parser->cursor;
623      }
624      break;
625
626      /* ************ otherwise, it is any token **************/
627    default:
628      token->start = cur;
629      token->type  = T1_TOKEN_TYPE_ANY;
630      ps_parser_skip_PS_token( parser );
631      cur = parser->cursor;
632      if ( !parser->error )
633        token->limit = cur;
634    }
635
636    if ( !token->limit )
637    {
638      token->start = 0;
639      token->type  = T1_TOKEN_TYPE_NONE;
640    }
641
642    parser->cursor = cur;
643  }
644
645
646  FT_LOCAL_DEF( void )
647  ps_parser_to_token_array( PS_Parser  parser,
648                            T1_Token   tokens,
649                            FT_UInt    max_tokens,
650                            FT_Int*    pnum_tokens )
651  {
652    T1_TokenRec  master;
653
654
655    *pnum_tokens = -1;
656
657    /* this also handles leading whitespace */
658    ps_parser_to_token( parser, &master );
659
660    if ( master.type == T1_TOKEN_TYPE_ARRAY )
661    {
662      FT_Byte*  old_cursor = parser->cursor;
663      FT_Byte*  old_limit  = parser->limit;
664      T1_Token  cur        = tokens;
665      T1_Token  limit      = cur + max_tokens;
666
667
668      /* don't include outermost delimiters */
669      parser->cursor = master.start + 1;
670      parser->limit  = master.limit - 1;
671
672      while ( parser->cursor < parser->limit )
673      {
674        T1_TokenRec  token;
675
676
677        ps_parser_to_token( parser, &token );
678        if ( !token.type )
679          break;
680
681        if ( cur < limit )
682          *cur = token;
683
684        cur++;
685      }
686
687      *pnum_tokens = (FT_Int)( cur - tokens );
688
689      parser->cursor = old_cursor;
690      parser->limit  = old_limit;
691    }
692  }
693
694
695  /* first character must be already part of the number */
696
697  static FT_Long
698  ps_radix( FT_Long    radixBase,
699            FT_Byte*  *acur,
700            FT_Byte*   limit )
701  {
702    FT_Long   result = 0;
703    FT_Byte*  cur    = *acur;
704
705
706    if ( radixBase < 2 || radixBase > 36 )
707      return 0;
708
709    while ( cur < limit )
710    {
711      int  d;
712
713
714      if ( *cur OP 0x80 )
715        break;
716
717      d = ft_char_table[*cur & 0x7F];
718      if ( d < 0 || d >= radixBase )
719        break;
720
721      result = result * radixBase + d;
722
723      cur++;
724    }
725
726    *acur = cur;
727
728    return result;
729  }
730
731
732  /* first character must be already part of the number */
733
734  static FT_Long
735  ps_toint( FT_Byte*  *acur,
736            FT_Byte*   limit )
737  {
738    FT_Long   result = 0;
739    FT_Byte*  cur    = *acur;
740    FT_Byte   c;
741
742
743    if ( cur >= limit )
744      goto Exit;
745
746    c = *cur;
747    if ( c == '-' )
748      cur++;
749
750    while ( cur < limit )
751    {
752      int  d;
753
754
755      if ( *cur == '#' )
756      {
757        cur++;
758        result = ps_radix( result, &cur, limit );
759        break;
760      }
761
762      if ( *cur OP 0x80 )
763        break;
764
765      d = ft_char_table[*cur & 0x7F];
766      if ( d < 0 || d >= 10 )
767        break;
768      result = result * 10 + d;
769
770      cur++;
771    };
772
773    if ( c == '-' )
774      result = -result;
775
776  Exit:
777    *acur = cur;
778    return result;
779  }
780
781
782  /* first character must be `<' if `delimiters' is non-zero */
783
784  static FT_Error
785  ps_tobytes( FT_Byte*  *acur,
786              FT_Byte*   limit,
787              FT_Long    max_bytes,
788              FT_Byte*   bytes,
789              FT_Long*   pnum_bytes,
790              FT_Bool    delimiters )
791  {
792    FT_Error  error = PSaux_Err_Ok;
793
794    FT_Byte*  cur = *acur;
795    FT_Long   n   = 0;
796
797
798    if ( cur >= limit )
799      goto Exit;
800
801    if ( delimiters )
802    {
803      if ( *cur != '<' )
804      {
805        FT_ERROR(( "ps_tobytes: Missing starting delimiter `<'\n" ));
806        error = PSaux_Err_Invalid_File_Format;
807        goto Exit;
808      }
809
810      cur++;
811    }
812
813    max_bytes = max_bytes * 2;
814
815    for ( n = 0; cur < limit; n++, cur++ )
816    {
817      int  d;
818
819
820      if ( n >= max_bytes )
821        /* buffer is full */
822        goto Exit;
823
824      /* All whitespace characters are ignored. */
825      skip_spaces( &cur, limit );
826      if ( cur >= limit )
827        break;
828
829      if ( *cur OP 0x80 )
830        break;
831
832      d = ft_char_table[*cur & 0x7F];
833      if ( d < 0 || d >= 16 )
834        break;
835
836      /* <f> == <f0> != <0f> */
837      bytes[n / 2] = (FT_Byte)( ( n % 2 ) ? bytes[n / 2] + d
838                                          : d * 16 );
839    }
840
841    if ( delimiters )
842    {
843      if ( cur < limit && *cur != '>' )
844      {
845        FT_ERROR(( "ps_tobytes: Missing closing delimiter `>'\n" ));
846        error = PSaux_Err_Invalid_File_Format;
847        goto Exit;
848      }
849
850      cur++;
851    }
852
853    *acur = cur;
854
855  Exit:
856    *pnum_bytes = ( n + 1 ) / 2;
857
858    return error;
859  }
860
861
862  /* first character must be already part of the number */
863
864  static FT_Long
865  ps_tofixed( FT_Byte*  *acur,
866              FT_Byte*   limit,
867              FT_Long    power_ten )
868  {
869    FT_Byte*  cur  = *acur;
870    FT_Long   num, divider, result;
871    FT_Int    sign = 0;
872
873
874    if ( cur >= limit )
875      return 0;
876
877    /* first of all, check the sign */
878    if ( *cur == '-' && cur + 1 < limit )
879    {
880      sign = 1;
881      cur++;
882    }
883
884    /* then, read the integer part, if any */
885    if ( *cur != '.' )
886      result = ps_toint( &cur, limit ) << 16;
887    else
888      result = 0;
889
890    num     = 0;
891    divider = 1;
892
893    if ( cur >= limit )
894      goto Exit;
895
896    /* read decimal part, if any */
897    if ( *cur == '.' && cur + 1 < limit )
898    {
899      cur++;
900
901      for (;;)
902      {
903        int  d;
904
905
906        if ( *cur OP 0x80 )
907          break;
908
909        d = ft_char_table[*cur & 0x7F];
910        if ( d < 0 || d >= 10 )
911          break;
912
913        if ( divider < 10000000L )
914        {
915          num      = num * 10 + d;
916          divider *= 10;
917        }
918
919        cur++;
920        if ( cur >= limit )
921          break;
922      }
923    }
924
925    /* read exponent, if any */
926    if ( cur + 1 < limit && ( *cur == 'e' || *cur == 'E' ) )
927    {
928      cur++;
929      power_ten += ps_toint( &cur, limit );
930    }
931
932  Exit:
933    /* raise to power of ten if needed */
934    while ( power_ten > 0 )
935    {
936      result = result * 10;
937      num    = num * 10;
938      power_ten--;
939    }
940
941    while ( power_ten < 0 )
942    {
943      result  = result / 10;
944      divider = divider * 10;
945      power_ten++;
946    }
947
948    if ( num )
949      result += FT_DivFix( num, divider );
950
951    if ( sign )
952      result = -result;
953
954    *acur = cur;
955    return result;
956  }
957
958
959  /* first character must be a delimiter or a part of a number */
960
961  static FT_Int
962  ps_tocoordarray( FT_Byte*  *acur,
963                   FT_Byte*   limit,
964                   FT_Int     max_coords,
965                   FT_Short*  coords )
966  {
967    FT_Byte*  cur   = *acur;
968    FT_Int    count = 0;
969    FT_Byte   c, ender;
970
971
972    if ( cur >= limit )
973      goto Exit;
974
975    /* check for the beginning of an array; otherwise, only one number */
976    /* will be read                                                    */
977    c     = *cur;
978    ender = 0;
979
980    if ( c == '[' )
981      ender = ']';
982
983    if ( c == '{' )
984      ender = '}';
985
986    if ( ender )
987      cur++;
988
989    /* now, read the coordinates */
990    while ( cur < limit )
991    {
992      /* skip whitespace in front of data */
993      skip_spaces( &cur, limit );
994      if ( cur >= limit )
995        goto Exit;
996
997      if ( count >= max_coords )
998        break;
999
1000      if ( c == ender )
1001      {
1002        cur++;
1003        break;
1004      }
1005
1006      coords[count] = (FT_Short)( ps_tofixed( &cur, limit, 0 ) >> 16 );
1007      count++;
1008
1009      if ( !ender )
1010        break;
1011    }
1012
1013  Exit:
1014    *acur = cur;
1015    return count;
1016  }
1017
1018
1019  /* first character must be a delimiter or a part of a number */
1020
1021  static FT_Int
1022  ps_tofixedarray( FT_Byte*  *acur,
1023                   FT_Byte*   limit,
1024                   FT_Int     max_values,
1025                   FT_Fixed*  values,
1026                   FT_Int     power_ten )
1027  {
1028    FT_Byte*  cur   = *acur;
1029    FT_Int    count = 0;
1030    FT_Byte   c, ender;
1031
1032
1033    if ( cur >= limit )
1034      goto Exit;
1035
1036    /* Check for the beginning of an array.  Otherwise, only one number */
1037    /* will be read.                                                    */
1038    c     = *cur;
1039    ender = 0;
1040
1041    if ( c == '[' )
1042      ender = ']';
1043
1044    if ( c == '{' )
1045      ender = '}';
1046
1047    if ( ender )
1048      cur++;
1049
1050    /* now, read the values */
1051    while ( cur < limit )
1052    {
1053      /* skip whitespace in front of data */
1054      skip_spaces( &cur, limit );
1055      if ( cur >= limit )
1056        goto Exit;
1057
1058      if ( count >= max_values )
1059        break;
1060
1061      if ( c == ender )
1062      {
1063        cur++;
1064        break;
1065      }
1066
1067      values[count] = ps_tofixed( &cur, limit, power_ten );
1068      count++;
1069
1070      if ( !ender )
1071        break;
1072    }
1073
1074  Exit:
1075    *acur = cur;
1076    return count;
1077  }
1078
1079
1080#if 0
1081
1082  static FT_String*
1083  ps_tostring( FT_Byte**  cursor,
1084               FT_Byte*   limit,
1085               FT_Memory  memory )
1086  {
1087    FT_Byte*    cur = *cursor;
1088    FT_PtrDist  len = 0;
1089    FT_Int      count;
1090    FT_String*  result;
1091    FT_Error    error;
1092
1093
1094    /* XXX: some stupid fonts have a `Notice' or `Copyright' string     */
1095    /*      that simply doesn't begin with an opening parenthesis, even */
1096    /*      though they have a closing one!  E.g. "amuncial.pfb"        */
1097    /*                                                                  */
1098    /*      We must deal with these ill-fated cases there.  Note that   */
1099    /*      these fonts didn't work with the old Type 1 driver as the   */
1100    /*      notice/copyright was not recognized as a valid string token */
1101    /*      and made the old token parser commit errors.                */
1102
1103    while ( cur < limit && ( *cur == ' ' || *cur == '\t' ) )
1104      cur++;
1105    if ( cur + 1 >= limit )
1106      return 0;
1107
1108    if ( *cur == '(' )
1109      cur++;  /* skip the opening parenthesis, if there is one */
1110
1111    *cursor = cur;
1112    count   = 0;
1113
1114    /* then, count its length */
1115    for ( ; cur < limit; cur++ )
1116    {
1117      if ( *cur == '(' )
1118        count++;
1119
1120      else if ( *cur == ')' )
1121      {
1122        count--;
1123        if ( count < 0 )
1124          break;
1125      }
1126    }
1127
1128    len = cur - *cursor;
1129    if ( cur >= limit || FT_ALLOC( result, len + 1 ) )
1130      return 0;
1131
1132    /* now copy the string */
1133    FT_MEM_COPY( result, *cursor, len );
1134    result[len] = '\0';
1135    *cursor = cur;
1136    return result;
1137  }
1138
1139#endif /* 0 */
1140
1141
1142  static int
1143  ps_tobool( FT_Byte*  *acur,
1144             FT_Byte*   limit )
1145  {
1146    FT_Byte*  cur    = *acur;
1147    FT_Bool   result = 0;
1148
1149
1150    /* return 1 if we find `true', 0 otherwise */
1151    if ( cur + 3 < limit &&
1152         cur[0] == 't'   &&
1153         cur[1] == 'r'   &&
1154         cur[2] == 'u'   &&
1155         cur[3] == 'e'   )
1156    {
1157      result = 1;
1158      cur   += 5;
1159    }
1160    else if ( cur + 4 < limit &&
1161              cur[0] == 'f'   &&
1162              cur[1] == 'a'   &&
1163              cur[2] == 'l'   &&
1164              cur[3] == 's'   &&
1165              cur[4] == 'e'   )
1166    {
1167      result = 0;
1168      cur   += 6;
1169    }
1170
1171    *acur = cur;
1172    return result;
1173  }
1174
1175
1176  /* load a simple field (i.e. non-table) into the current list of objects */
1177
1178  FT_LOCAL_DEF( FT_Error )
1179  ps_parser_load_field( PS_Parser       parser,
1180                        const T1_Field  field,
1181                        void**          objects,
1182                        FT_UInt         max_objects,
1183                        FT_ULong*       pflags )
1184  {
1185    T1_TokenRec  token;
1186    FT_Byte*     cur;
1187    FT_Byte*     limit;
1188    FT_UInt      count;
1189    FT_UInt      idx;
1190    FT_Error     error;
1191
1192
1193    /* this also skips leading whitespace */
1194    ps_parser_to_token( parser, &token );
1195    if ( !token.type )
1196      goto Fail;
1197
1198    count = 1;
1199    idx   = 0;
1200    cur   = token.start;
1201    limit = token.limit;
1202
1203    /* we must detect arrays in /FontBBox */
1204    if ( field->type == T1_FIELD_TYPE_BBOX )
1205    {
1206      T1_TokenRec  token2;
1207      FT_Byte*     old_cur   = parser->cursor;
1208      FT_Byte*     old_limit = parser->limit;
1209
1210
1211      /* don't include delimiters */
1212      parser->cursor = token.start + 1;
1213      parser->limit  = token.limit - 1;
1214
1215      ps_parser_to_token( parser, &token2 );
1216      parser->cursor = old_cur;
1217      parser->limit  = old_limit;
1218
1219      if ( token2.type == T1_TOKEN_TYPE_ARRAY )
1220        goto FieldArray;
1221    }
1222    else if ( token.type == T1_TOKEN_TYPE_ARRAY )
1223    {
1224    FieldArray:
1225      /* if this is an array and we have no blend, an error occurs */
1226      if ( max_objects == 0 )
1227        goto Fail;
1228
1229      count = max_objects;
1230      idx   = 1;
1231
1232      /* don't include delimiters */
1233      cur++;
1234      limit--;
1235    }
1236
1237    for ( ; count > 0; count--, idx++ )
1238    {
1239      FT_Byte*    q = (FT_Byte*)objects[idx] + field->offset;
1240      FT_Long     val;
1241      FT_String*  string;
1242
1243
1244      skip_spaces( &cur, limit );
1245
1246      switch ( field->type )
1247      {
1248      case T1_FIELD_TYPE_BOOL:
1249        val = ps_tobool( &cur, limit );
1250        goto Store_Integer;
1251
1252      case T1_FIELD_TYPE_FIXED:
1253        val = ps_tofixed( &cur, limit, 0 );
1254        goto Store_Integer;
1255
1256      case T1_FIELD_TYPE_FIXED_1000:
1257        val = ps_tofixed( &cur, limit, 3 );
1258        goto Store_Integer;
1259
1260      case T1_FIELD_TYPE_INTEGER:
1261        val = ps_toint( &cur, limit );
1262        /* fall through */
1263
1264      Store_Integer:
1265        switch ( field->size )
1266        {
1267        case (8 / FT_CHAR_BIT):
1268          *(FT_Byte*)q = (FT_Byte)val;
1269          break;
1270
1271        case (16 / FT_CHAR_BIT):
1272          *(FT_UShort*)q = (FT_UShort)val;
1273          break;
1274
1275        case (32 / FT_CHAR_BIT):
1276          *(FT_UInt32*)q = (FT_UInt32)val;
1277          break;
1278
1279        default:                /* for 64-bit systems */
1280          *(FT_Long*)q = val;
1281        }
1282        break;
1283
1284      case T1_FIELD_TYPE_STRING:
1285      case T1_FIELD_TYPE_KEY:
1286        {
1287          FT_Memory  memory = parser->memory;
1288          FT_UInt    len    = (FT_UInt)( limit - cur );
1289
1290
1291          if ( cur >= limit )
1292            break;
1293
1294          if ( field->type == T1_FIELD_TYPE_KEY )
1295          {
1296            /* don't include leading `/' */
1297            len--;
1298            cur++;
1299          }
1300          else
1301          {
1302            /* don't include delimiting parentheses */
1303            cur++;
1304            len -= 2;
1305          }
1306
1307          if ( FT_ALLOC( string, len + 1 ) )
1308            goto Exit;
1309
1310          FT_MEM_COPY( string, cur, len );
1311          string[len] = 0;
1312
1313          *(FT_String**)q = string;
1314        }
1315        break;
1316
1317      case T1_FIELD_TYPE_BBOX:
1318        {
1319          FT_Fixed  temp[4];
1320          FT_BBox*  bbox = (FT_BBox*)q;
1321
1322
1323          (void)ps_tofixedarray( &token.start, token.limit, 4, temp, 0 );
1324
1325          bbox->xMin = FT_RoundFix( temp[0] );
1326          bbox->yMin = FT_RoundFix( temp[1] );
1327          bbox->xMax = FT_RoundFix( temp[2] );
1328          bbox->yMax = FT_RoundFix( temp[3] );
1329        }
1330        break;
1331
1332      default:
1333        /* an error occured */
1334        goto Fail;
1335      }
1336    }
1337
1338#if 0  /* obsolete -- keep for reference */
1339    if ( pflags )
1340      *pflags |= 1L << field->flag_bit;
1341#else
1342    FT_UNUSED( pflags );
1343#endif
1344
1345    error = PSaux_Err_Ok;
1346
1347  Exit:
1348    return error;
1349
1350  Fail:
1351    error = PSaux_Err_Invalid_File_Format;
1352    goto Exit;
1353  }
1354
1355
1356#define T1_MAX_TABLE_ELEMENTS  32
1357
1358
1359  FT_LOCAL_DEF( FT_Error )
1360  ps_parser_load_field_table( PS_Parser       parser,
1361                              const T1_Field  field,
1362                              void**          objects,
1363                              FT_UInt         max_objects,
1364                              FT_ULong*       pflags )
1365  {
1366    T1_TokenRec  elements[T1_MAX_TABLE_ELEMENTS];
1367    T1_Token     token;
1368    FT_Int       num_elements;
1369    FT_Error     error = PSaux_Err_Ok;
1370    FT_Byte*     old_cursor;
1371    FT_Byte*     old_limit;
1372    T1_FieldRec  fieldrec = *(T1_Field)field;
1373
1374
1375#if 1
1376    fieldrec.type = T1_FIELD_TYPE_INTEGER;
1377    if ( field->type == T1_FIELD_TYPE_FIXED_ARRAY )
1378      fieldrec.type = T1_FIELD_TYPE_FIXED;
1379#endif
1380
1381    ps_parser_to_token_array( parser, elements,
1382                              T1_MAX_TABLE_ELEMENTS, &num_elements );
1383    if ( num_elements < 0 )
1384    {
1385      error = PSaux_Err_Ignore;
1386      goto Exit;
1387    }
1388    if ( num_elements > T1_MAX_TABLE_ELEMENTS )
1389      num_elements = T1_MAX_TABLE_ELEMENTS;
1390
1391    old_cursor = parser->cursor;
1392    old_limit  = parser->limit;
1393
1394    /* we store the elements count */
1395    *(FT_Byte*)( (FT_Byte*)objects[0] + field->count_offset ) =
1396      (FT_Byte)num_elements;
1397
1398    /* we now load each element, adjusting the field.offset on each one */
1399    token = elements;
1400    for ( ; num_elements > 0; num_elements--, token++ )
1401    {
1402      parser->cursor = token->start;
1403      parser->limit  = token->limit;
1404      ps_parser_load_field( parser, &fieldrec, objects, max_objects, 0 );
1405      fieldrec.offset += fieldrec.size;
1406    }
1407
1408#if 0  /* obsolete -- keep for reference */
1409    if ( pflags )
1410      *pflags |= 1L << field->flag_bit;
1411#else
1412    FT_UNUSED( pflags );
1413#endif
1414
1415    parser->cursor = old_cursor;
1416    parser->limit  = old_limit;
1417
1418  Exit:
1419    return error;
1420  }
1421
1422
1423  FT_LOCAL_DEF( FT_Long )
1424  ps_parser_to_int( PS_Parser  parser )
1425  {
1426    ps_parser_skip_spaces( parser );
1427    return ps_toint( &parser->cursor, parser->limit );
1428  }
1429
1430
1431  FT_LOCAL_DEF( FT_Error )
1432  ps_parser_to_bytes( PS_Parser  parser,
1433                      FT_Byte*   bytes,
1434                      FT_Long    max_bytes,
1435                      FT_Long*   pnum_bytes,
1436                      FT_Bool    delimiters )
1437  {
1438    ps_parser_skip_spaces( parser );
1439    return ps_tobytes( &parser->cursor,
1440                       parser->limit,
1441                       max_bytes,
1442                       bytes,
1443                       pnum_bytes,
1444                       delimiters );
1445  }
1446
1447
1448  FT_LOCAL_DEF( FT_Fixed )
1449  ps_parser_to_fixed( PS_Parser  parser,
1450                      FT_Int     power_ten )
1451  {
1452    ps_parser_skip_spaces( parser );
1453    return ps_tofixed( &parser->cursor, parser->limit, power_ten );
1454  }
1455
1456
1457  FT_LOCAL_DEF( FT_Int )
1458  ps_parser_to_coord_array( PS_Parser  parser,
1459                            FT_Int     max_coords,
1460                            FT_Short*  coords )
1461  {
1462    ps_parser_skip_spaces( parser );
1463    return ps_tocoordarray( &parser->cursor, parser->limit,
1464                            max_coords, coords );
1465  }
1466
1467
1468  FT_LOCAL_DEF( FT_Int )
1469  ps_parser_to_fixed_array( PS_Parser  parser,
1470                            FT_Int     max_values,
1471                            FT_Fixed*  values,
1472                            FT_Int     power_ten )
1473  {
1474    ps_parser_skip_spaces( parser );
1475    return ps_tofixedarray( &parser->cursor, parser->limit,
1476                            max_values, values, power_ten );
1477  }
1478
1479
1480#if 0
1481
1482  FT_LOCAL_DEF( FT_String* )
1483  T1_ToString( PS_Parser  parser )
1484  {
1485    return ps_tostring( &parser->cursor, parser->limit, parser->memory );
1486  }
1487
1488
1489  FT_LOCAL_DEF( FT_Bool )
1490  T1_ToBool( PS_Parser  parser )
1491  {
1492    return ps_tobool( &parser->cursor, parser->limit );
1493  }
1494
1495#endif /* 0 */
1496
1497
1498  FT_LOCAL_DEF( void )
1499  ps_parser_init( PS_Parser  parser,
1500                  FT_Byte*   base,
1501                  FT_Byte*   limit,
1502                  FT_Memory  memory )
1503  {
1504    parser->error  = PSaux_Err_Ok;
1505    parser->base   = base;
1506    parser->limit  = limit;
1507    parser->cursor = base;
1508    parser->memory = memory;
1509    parser->funcs  = ps_parser_funcs;
1510  }
1511
1512
1513  FT_LOCAL_DEF( void )
1514  ps_parser_done( PS_Parser  parser )
1515  {
1516    FT_UNUSED( parser );
1517  }
1518
1519
1520  /*************************************************************************/
1521  /*************************************************************************/
1522  /*****                                                               *****/
1523  /*****                            T1 BUILDER                         *****/
1524  /*****                                                               *****/
1525  /*************************************************************************/
1526  /*************************************************************************/
1527
1528  /*************************************************************************/
1529  /*                                                                       */
1530  /* <Function>                                                            */
1531  /*    t1_builder_init                                                    */
1532  /*                                                                       */
1533  /* <Description>                                                         */
1534  /*    Initializes a given glyph builder.                                 */
1535  /*                                                                       */
1536  /* <InOut>                                                               */
1537  /*    builder :: A pointer to the glyph builder to initialize.           */
1538  /*                                                                       */
1539  /* <Input>                                                               */
1540  /*    face    :: The current face object.                                */
1541  /*                                                                       */
1542  /*    size    :: The current size object.                                */
1543  /*                                                                       */
1544  /*    glyph   :: The current glyph object.                               */
1545  /*                                                                       */
1546  /*    hinting :: Whether hinting should be applied.                      */
1547  /*                                                                       */
1548  FT_LOCAL_DEF( void )
1549  t1_builder_init( T1_Builder    builder,
1550                   FT_Face       face,
1551                   FT_Size       size,
1552                   FT_GlyphSlot  glyph,
1553                   FT_Bool       hinting )
1554  {
1555    builder->parse_state = T1_Parse_Start;
1556    builder->load_points = 1;
1557
1558    builder->face   = face;
1559    builder->glyph  = glyph;
1560    builder->memory = face->memory;
1561
1562    if ( glyph )
1563    {
1564      FT_GlyphLoader  loader = glyph->internal->loader;
1565
1566
1567      builder->loader  = loader;
1568      builder->base    = &loader->base.outline;
1569      builder->current = &loader->current.outline;
1570      FT_GlyphLoader_Rewind( loader );
1571
1572      builder->hints_globals = size->internal;
1573      builder->hints_funcs   = 0;
1574
1575      if ( hinting )
1576        builder->hints_funcs = glyph->internal->glyph_hints;
1577    }
1578
1579    if ( size )
1580    {
1581      builder->scale_x = size->metrics.x_scale;
1582      builder->scale_y = size->metrics.y_scale;
1583    }
1584
1585    builder->pos_x = 0;
1586    builder->pos_y = 0;
1587
1588    builder->left_bearing.x = 0;
1589    builder->left_bearing.y = 0;
1590    builder->advance.x      = 0;
1591    builder->advance.y      = 0;
1592
1593    builder->funcs = t1_builder_funcs;
1594  }
1595
1596
1597  /*************************************************************************/
1598  /*                                                                       */
1599  /* <Function>                                                            */
1600  /*    t1_builder_done                                                    */
1601  /*                                                                       */
1602  /* <Description>                                                         */
1603  /*    Finalizes a given glyph builder.  Its contents can still be used   */
1604  /*    after the call, but the function saves important information       */
1605  /*    within the corresponding glyph slot.                               */
1606  /*                                                                       */
1607  /* <Input>                                                               */
1608  /*    builder :: A pointer to the glyph builder to finalize.             */
1609  /*                                                                       */
1610  FT_LOCAL_DEF( void )
1611  t1_builder_done( T1_Builder  builder )
1612  {
1613    FT_GlyphSlot  glyph = builder->glyph;
1614
1615
1616    if ( glyph )
1617      glyph->outline = *builder->base;
1618  }
1619
1620
1621  /* check that there is enough space for `count' more points */
1622  FT_LOCAL_DEF( FT_Error )
1623  t1_builder_check_points( T1_Builder  builder,
1624                           FT_Int      count )
1625  {
1626    return FT_GlyphLoader_CheckPoints( builder->loader, count, 0 );
1627  }
1628
1629
1630  /* add a new point, do not check space */
1631  FT_LOCAL_DEF( void )
1632  t1_builder_add_point( T1_Builder  builder,
1633                        FT_Pos      x,
1634                        FT_Pos      y,
1635                        FT_Byte     flag )
1636  {
1637    FT_Outline*  outline = builder->current;
1638
1639
1640    if ( builder->load_points )
1641    {
1642      FT_Vector*  point   = outline->points + outline->n_points;
1643      FT_Byte*    control = (FT_Byte*)outline->tags + outline->n_points;
1644
1645
1646      if ( builder->shift )
1647      {
1648        x >>= 16;
1649        y >>= 16;
1650      }
1651      point->x = x;
1652      point->y = y;
1653      *control = (FT_Byte)( flag ? FT_CURVE_TAG_ON : FT_CURVE_TAG_CUBIC );
1654
1655      builder->last = *point;
1656    }
1657    outline->n_points++;
1658  }
1659
1660
1661  /* check space for a new on-curve point, then add it */
1662  FT_LOCAL_DEF( FT_Error )
1663  t1_builder_add_point1( T1_Builder  builder,
1664                         FT_Pos      x,
1665                         FT_Pos      y )
1666  {
1667    FT_Error  error;
1668
1669
1670    error = t1_builder_check_points( builder, 1 );
1671    if ( !error )
1672      t1_builder_add_point( builder, x, y, 1 );
1673
1674    return error;
1675  }
1676
1677
1678  /* check space for a new contour, then add it */
1679  FT_LOCAL_DEF( FT_Error )
1680  t1_builder_add_contour( T1_Builder  builder )
1681  {
1682    FT_Outline*  outline = builder->current;
1683    FT_Error     error;
1684
1685
1686    if ( !builder->load_points )
1687    {
1688      outline->n_contours++;
1689      return PSaux_Err_Ok;
1690    }
1691
1692    error = FT_GlyphLoader_CheckPoints( builder->loader, 0, 1 );
1693    if ( !error )
1694    {
1695      if ( outline->n_contours > 0 )
1696        outline->contours[outline->n_contours - 1] =
1697          (short)( outline->n_points - 1 );
1698
1699      outline->n_contours++;
1700    }
1701
1702    return error;
1703  }
1704
1705
1706  /* if a path was begun, add its first on-curve point */
1707  FT_LOCAL_DEF( FT_Error )
1708  t1_builder_start_point( T1_Builder  builder,
1709                          FT_Pos      x,
1710                          FT_Pos      y )
1711  {
1712    FT_Error  error = PSaux_Err_Invalid_File_Format;
1713
1714
1715    /* test whether we are building a new contour */
1716
1717    if ( builder->parse_state == T1_Parse_Have_Path )
1718      error = PSaux_Err_Ok;
1719    else if ( builder->parse_state == T1_Parse_Have_Moveto )
1720    {
1721      builder->parse_state = T1_Parse_Have_Path;
1722      error = t1_builder_add_contour( builder );
1723      if ( !error )
1724        error = t1_builder_add_point1( builder, x, y );
1725    }
1726
1727    return error;
1728  }
1729
1730
1731  /* close the current contour */
1732  FT_LOCAL_DEF( void )
1733  t1_builder_close_contour( T1_Builder  builder )
1734  {
1735    FT_Outline*  outline = builder->current;
1736
1737
1738    /* XXXX: We must not include the last point in the path if it */
1739    /*       is located on the first point.                       */
1740    if ( outline->n_points > 1 )
1741    {
1742      FT_Int      first   = 0;
1743      FT_Vector*  p1      = outline->points + first;
1744      FT_Vector*  p2      = outline->points + outline->n_points - 1;
1745      FT_Byte*    control = (FT_Byte*)outline->tags + outline->n_points - 1;
1746
1747
1748      if ( outline->n_contours > 1 )
1749      {
1750        first = outline->contours[outline->n_contours - 2] + 1;
1751        p1    = outline->points + first;
1752      }
1753
1754      /* `delete' last point only if it coincides with the first */
1755      /* point and it is not a control point (which can happen). */
1756      if ( p1->x == p2->x && p1->y == p2->y )
1757        if ( *control == FT_CURVE_TAG_ON )
1758          outline->n_points--;
1759    }
1760
1761    if ( outline->n_contours > 0 )
1762      outline->contours[outline->n_contours - 1] =
1763        (short)( outline->n_points - 1 );
1764  }
1765
1766
1767  /*************************************************************************/
1768  /*************************************************************************/
1769  /*****                                                               *****/
1770  /*****                            OTHER                              *****/
1771  /*****                                                               *****/
1772  /*************************************************************************/
1773  /*************************************************************************/
1774
1775  FT_LOCAL_DEF( void )
1776  t1_decrypt( FT_Byte*   buffer,
1777              FT_Offset  length,
1778              FT_UShort  seed )
1779  {
1780    while ( length > 0 )
1781    {
1782      FT_Byte  plain;
1783
1784
1785      plain     = (FT_Byte)( *buffer ^ ( seed >> 8 ) );
1786      seed      = (FT_UShort)( ( *buffer + seed ) * 52845U + 22719 );
1787      *buffer++ = plain;
1788      length--;
1789    }
1790  }
1791
1792
1793/* END */
Note: See TracBrowser for help on using the repository browser.