1 /****************************************************************************
2  *
3  * psobjs.c
4  *
5  *   Auxiliary functions for PostScript fonts (body).
6  *
7  * Copyright (C) 1996-2020 by
8  * David Turner, Robert Wilhelm, and Werner Lemberg.
9  *
10  * This file is part of the FreeType project, and may only be used,
11  * modified, and distributed under the terms of the FreeType project
12  * license, LICENSE.TXT.  By continuing to use, modify, or distribute
13  * this file you indicate that you have read the license and
14  * understand and accept it fully.
15  *
16  */
17 
18 
19 #include <freetype/internal/psaux.h>
20 #include <freetype/internal/ftdebug.h>
21 #include <freetype/internal/ftcalc.h>
22 #include <freetype/ftdriver.h>
23 
24 #include "psobjs.h"
25 #include "psconv.h"
26 
27 #include "psauxerr.h"
28 #include "psauxmod.h"
29 
30 
31   /**************************************************************************
32    *
33    * The macro FT_COMPONENT is used in trace mode.  It is an implicit
34    * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
35    * messages during execution.
36    */
37 #undef  FT_COMPONENT
38 #define FT_COMPONENT  psobjs
39 
40 
41   /*************************************************************************/
42   /*************************************************************************/
43   /*****                                                               *****/
44   /*****                             PS_TABLE                          *****/
45   /*****                                                               *****/
46   /*************************************************************************/
47   /*************************************************************************/
48 
49   /**************************************************************************
50    *
51    * @Function:
52    *   ps_table_new
53    *
54    * @Description:
55    *   Initializes a PS_Table.
56    *
57    * @InOut:
58    *   table ::
59    *     The address of the target table.
60    *
61    * @Input:
62    *   count ::
63    *     The table size = the maximum number of elements.
64    *
65    *   memory ::
66    *     The memory object to use for all subsequent
67    *     reallocations.
68    *
69    * @Return:
70    *   FreeType error code.  0 means success.
71    */
72   FT_LOCAL_DEF( FT_Error )
ps_table_new(PS_Table table,FT_Int count,FT_Memory memory)73   ps_table_new( PS_Table   table,
74                 FT_Int     count,
75                 FT_Memory  memory )
76   {
77     FT_Error  error;
78 
79 
80     table->memory = memory;
81     if ( FT_NEW_ARRAY( table->elements, count ) ||
82          FT_NEW_ARRAY( table->lengths,  count ) )
83       goto Exit;
84 
85     table->max_elems = count;
86     table->init      = 0xDEADBEEFUL;
87     table->num_elems = 0;
88     table->block     = NULL;
89     table->capacity  = 0;
90     table->cursor    = 0;
91 
92     *(PS_Table_FuncsRec*)&table->funcs = ps_table_funcs;
93 
94   Exit:
95     if ( error )
96       FT_FREE( table->elements );
97 
98     return error;
99   }
100 
101 
102   static void
shift_elements(PS_Table table,FT_Byte * old_base)103   shift_elements( PS_Table  table,
104                   FT_Byte*  old_base )
105   {
106     FT_PtrDist  delta  = table->block - old_base;
107     FT_Byte**   offset = table->elements;
108     FT_Byte**   limit  = offset + table->max_elems;
109 
110 
111     for ( ; offset < limit; offset++ )
112     {
113       if ( offset[0] )
114         offset[0] += delta;
115     }
116   }
117 
118 
119   static FT_Error
reallocate_t1_table(PS_Table table,FT_Offset new_size)120   reallocate_t1_table( PS_Table   table,
121                        FT_Offset  new_size )
122   {
123     FT_Memory  memory   = table->memory;
124     FT_Byte*   old_base = table->block;
125     FT_Error   error;
126 
127 
128     /* allocate new base block */
129     if ( FT_ALLOC( table->block, new_size ) )
130     {
131       table->block = old_base;
132       return error;
133     }
134 
135     /* copy elements and shift offsets */
136     if ( old_base )
137     {
138       FT_MEM_COPY( table->block, old_base, table->capacity );
139       shift_elements( table, old_base );
140       FT_FREE( old_base );
141     }
142 
143     table->capacity = new_size;
144 
145     return FT_Err_Ok;
146   }
147 
148 
149   /**************************************************************************
150    *
151    * @Function:
152    *   ps_table_add
153    *
154    * @Description:
155    *   Adds an object to a PS_Table, possibly growing its memory block.
156    *
157    * @InOut:
158    *   table ::
159    *     The target table.
160    *
161    * @Input:
162    *   idx ::
163    *     The index of the object in the table.
164    *
165    *   object ::
166    *     The address of the object to copy in memory.
167    *
168    *   length ::
169    *     The length in bytes of the source object.
170    *
171    * @Return:
172    *   FreeType error code.  0 means success.  An error is returned if a
173    *   reallocation fails.
174    */
175   FT_LOCAL_DEF( FT_Error )
ps_table_add(PS_Table table,FT_Int idx,const void * object,FT_UInt length)176   ps_table_add( PS_Table     table,
177                 FT_Int       idx,
178                 const void*  object,
179                 FT_UInt      length )
180   {
181     if ( idx < 0 || idx >= table->max_elems )
182     {
183       FT_ERROR(( "ps_table_add: invalid index\n" ));
184       return FT_THROW( Invalid_Argument );
185     }
186 
187     /* grow the base block if needed */
188     if ( table->cursor + length > table->capacity )
189     {
190       FT_Error    error;
191       FT_Offset   new_size = table->capacity;
192       FT_PtrDist  in_offset;
193 
194 
195       in_offset = (FT_Byte*)object - table->block;
196       if ( in_offset < 0 || (FT_Offset)in_offset >= table->capacity )
197         in_offset = -1;
198 
199       while ( new_size < table->cursor + length )
200       {
201         /* increase size by 25% and round up to the nearest multiple
202            of 1024 */
203         new_size += ( new_size >> 2 ) + 1;
204         new_size  = FT_PAD_CEIL( new_size, 1024 );
205       }
206 
207       error = reallocate_t1_table( table, new_size );
208       if ( error )
209         return error;
210 
211       if ( in_offset >= 0 )
212         object = table->block + in_offset;
213     }
214 
215     /* add the object to the base block and adjust offset */
216     table->elements[idx] = FT_OFFSET( table->block, table->cursor );
217     table->lengths [idx] = length;
218     FT_MEM_COPY( table->block + table->cursor, object, length );
219 
220     table->cursor += length;
221     return FT_Err_Ok;
222   }
223 
224 
225   /**************************************************************************
226    *
227    * @Function:
228    *   ps_table_done
229    *
230    * @Description:
231    *   Finalizes a PS_TableRec (i.e., reallocate it to its current
232    *   cursor).
233    *
234    * @InOut:
235    *   table ::
236    *     The target table.
237    *
238    * @Note:
239    *   This function does NOT release the heap's memory block.  It is up
240    *   to the caller to clean it, or reference it in its own structures.
241    */
242   FT_LOCAL_DEF( void )
ps_table_done(PS_Table table)243   ps_table_done( PS_Table  table )
244   {
245     FT_Memory  memory = table->memory;
246     FT_Error   error;
247     FT_Byte*   old_base = table->block;
248 
249 
250     /* should never fail, because rec.cursor <= rec.size */
251     if ( !old_base )
252       return;
253 
254     if ( FT_ALLOC( table->block, table->cursor ) )
255       return;
256     FT_MEM_COPY( table->block, old_base, table->cursor );
257     shift_elements( table, old_base );
258 
259     table->capacity = table->cursor;
260     FT_FREE( old_base );
261 
262     FT_UNUSED( error );
263   }
264 
265 
266   FT_LOCAL_DEF( void )
ps_table_release(PS_Table table)267   ps_table_release( PS_Table  table )
268   {
269     FT_Memory  memory = table->memory;
270 
271 
272     if ( (FT_ULong)table->init == 0xDEADBEEFUL )
273     {
274       FT_FREE( table->block );
275       FT_FREE( table->elements );
276       FT_FREE( table->lengths );
277       table->init = 0;
278     }
279   }
280 
281 
282   /*************************************************************************/
283   /*************************************************************************/
284   /*****                                                               *****/
285   /*****                            T1 PARSER                          *****/
286   /*****                                                               *****/
287   /*************************************************************************/
288   /*************************************************************************/
289 
290 
291   /* first character must be already part of the comment */
292 
293   static void
skip_comment(FT_Byte ** acur,FT_Byte * limit)294   skip_comment( FT_Byte*  *acur,
295                 FT_Byte*   limit )
296   {
297     FT_Byte*  cur = *acur;
298 
299 
300     while ( cur < limit )
301     {
302       if ( IS_PS_NEWLINE( *cur ) )
303         break;
304       cur++;
305     }
306 
307     *acur = cur;
308   }
309 
310 
311   static void
skip_spaces(FT_Byte ** acur,FT_Byte * limit)312   skip_spaces( FT_Byte*  *acur,
313                FT_Byte*   limit )
314   {
315     FT_Byte*  cur = *acur;
316 
317 
318     while ( cur < limit )
319     {
320       if ( !IS_PS_SPACE( *cur ) )
321       {
322         if ( *cur == '%' )
323           /* According to the PLRM, a comment is equal to a space. */
324           skip_comment( &cur, limit );
325         else
326           break;
327       }
328       cur++;
329     }
330 
331     *acur = cur;
332   }
333 
334 
335 #define IS_OCTAL_DIGIT( c ) ( '0' <= (c) && (c) <= '7' )
336 
337 
338   /* first character must be `(';                               */
339   /* *acur is positioned at the character after the closing `)' */
340 
341   static FT_Error
skip_literal_string(FT_Byte ** acur,FT_Byte * limit)342   skip_literal_string( FT_Byte*  *acur,
343                        FT_Byte*   limit )
344   {
345     FT_Byte*      cur   = *acur;
346     FT_Int        embed = 0;
347     FT_Error      error = FT_ERR( Invalid_File_Format );
348     unsigned int  i;
349 
350 
351     while ( cur < limit )
352     {
353       FT_Byte  c = *cur;
354 
355 
356       cur++;
357 
358       if ( c == '\\' )
359       {
360         /* Red Book 3rd ed., section `Literal Text Strings', p. 29:     */
361         /* A backslash can introduce three different types              */
362         /* of escape sequences:                                         */
363         /*   - a special escaped char like \r, \n, etc.                 */
364         /*   - a one-, two-, or three-digit octal number                */
365         /*   - none of the above in which case the backslash is ignored */
366 
367         if ( cur == limit )
368           /* error (or to be ignored?) */
369           break;
370 
371         switch ( *cur )
372         {
373           /* skip `special' escape */
374         case 'n':
375         case 'r':
376         case 't':
377         case 'b':
378         case 'f':
379         case '\\':
380         case '(':
381         case ')':
382           cur++;
383           break;
384 
385         default:
386           /* skip octal escape or ignore backslash */
387           for ( i = 0; i < 3 && cur < limit; i++ )
388           {
389             if ( !IS_OCTAL_DIGIT( *cur ) )
390               break;
391 
392             cur++;
393           }
394         }
395       }
396       else if ( c == '(' )
397         embed++;
398       else if ( c == ')' )
399       {
400         embed--;
401         if ( embed == 0 )
402         {
403           error = FT_Err_Ok;
404           break;
405         }
406       }
407     }
408 
409     *acur = cur;
410 
411     return error;
412   }
413 
414 
415   /* first character must be `<' */
416 
417   static FT_Error
skip_string(FT_Byte ** acur,FT_Byte * limit)418   skip_string( FT_Byte*  *acur,
419                FT_Byte*   limit )
420   {
421     FT_Byte*  cur = *acur;
422     FT_Error  err =  FT_Err_Ok;
423 
424 
425     while ( ++cur < limit )
426     {
427       /* All whitespace characters are ignored. */
428       skip_spaces( &cur, limit );
429       if ( cur >= limit )
430         break;
431 
432       if ( !IS_PS_XDIGIT( *cur ) )
433         break;
434     }
435 
436     if ( cur < limit && *cur != '>' )
437     {
438       FT_ERROR(( "skip_string: missing closing delimiter `>'\n" ));
439       err = FT_THROW( Invalid_File_Format );
440     }
441     else
442       cur++;
443 
444     *acur = cur;
445     return err;
446   }
447 
448 
449   /* first character must be the opening brace that */
450   /* starts the procedure                           */
451 
452   /* NB: [ and ] need not match:                    */
453   /* `/foo {[} def' is a valid PostScript fragment, */
454   /* even within a Type1 font                       */
455 
456   static FT_Error
skip_procedure(FT_Byte ** acur,FT_Byte * limit)457   skip_procedure( FT_Byte*  *acur,
458                   FT_Byte*   limit )
459   {
460     FT_Byte*  cur;
461     FT_Int    embed = 0;
462     FT_Error  error = FT_Err_Ok;
463 
464 
465     FT_ASSERT( **acur == '{' );
466 
467     for ( cur = *acur; cur < limit && error == FT_Err_Ok; cur++ )
468     {
469       switch ( *cur )
470       {
471       case '{':
472         embed++;
473         break;
474 
475       case '}':
476         embed--;
477         if ( embed == 0 )
478         {
479           cur++;
480           goto end;
481         }
482         break;
483 
484       case '(':
485         error = skip_literal_string( &cur, limit );
486         break;
487 
488       case '<':
489         error = skip_string( &cur, limit );
490         break;
491 
492       case '%':
493         skip_comment( &cur, limit );
494         break;
495       }
496     }
497 
498   end:
499     if ( embed != 0 )
500       error = FT_THROW( Invalid_File_Format );
501 
502     *acur = cur;
503 
504     return error;
505   }
506 
507 
508   /************************************************************************
509    *
510    * All exported parsing routines handle leading whitespace and stop at
511    * the first character which isn't part of the just handled token.
512    *
513    */
514 
515 
516   FT_LOCAL_DEF( void )
ps_parser_skip_PS_token(PS_Parser parser)517   ps_parser_skip_PS_token( PS_Parser  parser )
518   {
519     /* Note: PostScript allows any non-delimiting, non-whitespace        */
520     /*       character in a name (PS Ref Manual, 3rd ed, p31).           */
521     /*       PostScript delimiters are (, ), <, >, [, ], {, }, /, and %. */
522 
523     FT_Byte*  cur   = parser->cursor;
524     FT_Byte*  limit = parser->limit;
525     FT_Error  error = FT_Err_Ok;
526 
527 
528     skip_spaces( &cur, limit );             /* this also skips comments */
529     if ( cur >= limit )
530       goto Exit;
531 
532     /* self-delimiting, single-character tokens */
533     if ( *cur == '[' || *cur == ']' )
534     {
535       cur++;
536       goto Exit;
537     }
538 
539     /* skip balanced expressions (procedures and strings) */
540 
541     if ( *cur == '{' )                              /* {...} */
542     {
543       error = skip_procedure( &cur, limit );
544       goto Exit;
545     }
546 
547     if ( *cur == '(' )                              /* (...) */
548     {
549       error = skip_literal_string( &cur, limit );
550       goto Exit;
551     }
552 
553     if ( *cur == '<' )                              /* <...> */
554     {
555       if ( cur + 1 < limit && *(cur + 1) == '<' )   /* << */
556       {
557         cur++;
558         cur++;
559       }
560       else
561         error = skip_string( &cur, limit );
562 
563       goto Exit;
564     }
565 
566     if ( *cur == '>' )
567     {
568       cur++;
569       if ( cur >= limit || *cur != '>' )             /* >> */
570       {
571         FT_ERROR(( "ps_parser_skip_PS_token:"
572                    " unexpected closing delimiter `>'\n" ));
573         error = FT_THROW( Invalid_File_Format );
574         goto Exit;
575       }
576       cur++;
577       goto Exit;
578     }
579 
580     if ( *cur == '/' )
581       cur++;
582 
583     /* anything else */
584     while ( cur < limit )
585     {
586       /* *cur might be invalid (e.g., ')' or '}'), but this   */
587       /* is handled by the test `cur == parser->cursor' below */
588       if ( IS_PS_DELIM( *cur ) )
589         break;
590 
591       cur++;
592     }
593 
594   Exit:
595     if ( cur < limit && cur == parser->cursor )
596     {
597       FT_ERROR(( "ps_parser_skip_PS_token:"
598                  " current token is `%c' which is self-delimiting\n"
599                  "                        "
600                  " but invalid at this point\n",
601                  *cur ));
602 
603       error = FT_THROW( Invalid_File_Format );
604     }
605 
606     if ( cur > limit )
607       cur = limit;
608 
609     parser->error  = error;
610     parser->cursor = cur;
611   }
612 
613 
614   FT_LOCAL_DEF( void )
ps_parser_skip_spaces(PS_Parser parser)615   ps_parser_skip_spaces( PS_Parser  parser )
616   {
617     skip_spaces( &parser->cursor, parser->limit );
618   }
619 
620 
621   /* `token' here means either something between balanced delimiters */
622   /* or the next token; the delimiters are not removed.              */
623 
624   FT_LOCAL_DEF( void )
ps_parser_to_token(PS_Parser parser,T1_Token token)625   ps_parser_to_token( PS_Parser  parser,
626                       T1_Token   token )
627   {
628     FT_Byte*  cur;
629     FT_Byte*  limit;
630     FT_Int    embed;
631 
632 
633     token->type  = T1_TOKEN_TYPE_NONE;
634     token->start = NULL;
635     token->limit = NULL;
636 
637     /* first of all, skip leading whitespace */
638     ps_parser_skip_spaces( parser );
639 
640     cur   = parser->cursor;
641     limit = parser->limit;
642 
643     if ( cur >= limit )
644       return;
645 
646     switch ( *cur )
647     {
648       /************* check for literal string *****************/
649     case '(':
650       token->type  = T1_TOKEN_TYPE_STRING;
651       token->start = cur;
652 
653       if ( skip_literal_string( &cur, limit ) == FT_Err_Ok )
654         token->limit = cur;
655       break;
656 
657       /************* check for programs/array *****************/
658     case '{':
659       token->type  = T1_TOKEN_TYPE_ARRAY;
660       token->start = cur;
661 
662       if ( skip_procedure( &cur, limit ) == FT_Err_Ok )
663         token->limit = cur;
664       break;
665 
666       /************* check for table/array ********************/
667       /* XXX: in theory we should also look for "<<"          */
668       /*      since this is semantically equivalent to "[";   */
669       /*      in practice it doesn't matter (?)               */
670     case '[':
671       token->type  = T1_TOKEN_TYPE_ARRAY;
672       embed        = 1;
673       token->start = cur++;
674 
675       /* we need this to catch `[ ]' */
676       parser->cursor = cur;
677       ps_parser_skip_spaces( parser );
678       cur = parser->cursor;
679 
680       while ( cur < limit && !parser->error )
681       {
682         /* XXX: this is wrong because it does not      */
683         /*      skip comments, procedures, and strings */
684         if ( *cur == '[' )
685           embed++;
686         else if ( *cur == ']' )
687         {
688           embed--;
689           if ( embed <= 0 )
690           {
691             token->limit = ++cur;
692             break;
693           }
694         }
695 
696         parser->cursor = cur;
697         ps_parser_skip_PS_token( parser );
698         /* we need this to catch `[XXX ]' */
699         ps_parser_skip_spaces  ( parser );
700         cur = parser->cursor;
701       }
702       break;
703 
704       /* ************ otherwise, it is any token **************/
705     default:
706       token->start = cur;
707       token->type  = ( *cur == '/' ) ? T1_TOKEN_TYPE_KEY : T1_TOKEN_TYPE_ANY;
708       ps_parser_skip_PS_token( parser );
709       cur = parser->cursor;
710       if ( !parser->error )
711         token->limit = cur;
712     }
713 
714     if ( !token->limit )
715     {
716       token->start = NULL;
717       token->type  = T1_TOKEN_TYPE_NONE;
718     }
719 
720     parser->cursor = cur;
721   }
722 
723 
724   /* NB: `tokens' can be NULL if we only want to count */
725   /* the number of array elements                      */
726 
727   FT_LOCAL_DEF( void )
ps_parser_to_token_array(PS_Parser parser,T1_Token tokens,FT_UInt max_tokens,FT_Int * pnum_tokens)728   ps_parser_to_token_array( PS_Parser  parser,
729                             T1_Token   tokens,
730                             FT_UInt    max_tokens,
731                             FT_Int*    pnum_tokens )
732   {
733     T1_TokenRec  master;
734 
735 
736     *pnum_tokens = -1;
737 
738     /* this also handles leading whitespace */
739     ps_parser_to_token( parser, &master );
740 
741     if ( master.type == T1_TOKEN_TYPE_ARRAY )
742     {
743       FT_Byte*  old_cursor = parser->cursor;
744       FT_Byte*  old_limit  = parser->limit;
745       T1_Token  cur        = tokens;
746       T1_Token  limit      = cur + max_tokens;
747 
748 
749       /* don't include outermost delimiters */
750       parser->cursor = master.start + 1;
751       parser->limit  = master.limit - 1;
752 
753       while ( parser->cursor < parser->limit )
754       {
755         T1_TokenRec  token;
756 
757 
758         ps_parser_to_token( parser, &token );
759         if ( !token.type )
760           break;
761 
762         if ( tokens && cur < limit )
763           *cur = token;
764 
765         cur++;
766       }
767 
768       *pnum_tokens = (FT_Int)( cur - tokens );
769 
770       parser->cursor = old_cursor;
771       parser->limit  = old_limit;
772     }
773   }
774 
775 
776   /* first character must be a delimiter or a part of a number */
777   /* NB: `coords' can be NULL if we just want to skip the      */
778   /*     array; in this case we ignore `max_coords'            */
779 
780   static FT_Int
ps_tocoordarray(FT_Byte ** acur,FT_Byte * limit,FT_Int max_coords,FT_Short * coords)781   ps_tocoordarray( FT_Byte*  *acur,
782                    FT_Byte*   limit,
783                    FT_Int     max_coords,
784                    FT_Short*  coords )
785   {
786     FT_Byte*  cur   = *acur;
787     FT_Int    count = 0;
788     FT_Byte   c, ender;
789 
790 
791     if ( cur >= limit )
792       goto Exit;
793 
794     /* check for the beginning of an array; otherwise, only one number */
795     /* will be read                                                    */
796     c     = *cur;
797     ender = 0;
798 
799     if ( c == '[' )
800       ender = ']';
801     else if ( c == '{' )
802       ender = '}';
803 
804     if ( ender )
805       cur++;
806 
807     /* now, read the coordinates */
808     while ( cur < limit )
809     {
810       FT_Short  dummy;
811       FT_Byte*  old_cur;
812 
813 
814       /* skip whitespace in front of data */
815       skip_spaces( &cur, limit );
816       if ( cur >= limit )
817         goto Exit;
818 
819       if ( *cur == ender )
820       {
821         cur++;
822         break;
823       }
824 
825       old_cur = cur;
826 
827       if ( coords && count >= max_coords )
828         break;
829 
830       /* call PS_Conv_ToFixed() even if coords == NULL */
831       /* to properly parse number at `cur'             */
832       *( coords ? &coords[count] : &dummy ) =
833         (FT_Short)( PS_Conv_ToFixed( &cur, limit, 0 ) >> 16 );
834 
835       if ( old_cur == cur )
836       {
837         count = -1;
838         goto Exit;
839       }
840       else
841         count++;
842 
843       if ( !ender )
844         break;
845     }
846 
847   Exit:
848     *acur = cur;
849     return count;
850   }
851 
852 
853   /* first character must be a delimiter or a part of a number */
854   /* NB: `values' can be NULL if we just want to skip the      */
855   /*     array; in this case we ignore `max_values'            */
856   /*                                                           */
857   /* return number of successfully parsed values               */
858 
859   static FT_Int
ps_tofixedarray(FT_Byte ** acur,FT_Byte * limit,FT_Int max_values,FT_Fixed * values,FT_Int power_ten)860   ps_tofixedarray( FT_Byte*  *acur,
861                    FT_Byte*   limit,
862                    FT_Int     max_values,
863                    FT_Fixed*  values,
864                    FT_Int     power_ten )
865   {
866     FT_Byte*  cur   = *acur;
867     FT_Int    count = 0;
868     FT_Byte   c, ender;
869 
870 
871     if ( cur >= limit )
872       goto Exit;
873 
874     /* Check for the beginning of an array.  Otherwise, only one number */
875     /* will be read.                                                    */
876     c     = *cur;
877     ender = 0;
878 
879     if ( c == '[' )
880       ender = ']';
881     else if ( c == '{' )
882       ender = '}';
883 
884     if ( ender )
885       cur++;
886 
887     /* now, read the values */
888     while ( cur < limit )
889     {
890       FT_Fixed  dummy;
891       FT_Byte*  old_cur;
892 
893 
894       /* skip whitespace in front of data */
895       skip_spaces( &cur, limit );
896       if ( cur >= limit )
897         goto Exit;
898 
899       if ( *cur == ender )
900       {
901         cur++;
902         break;
903       }
904 
905       old_cur = cur;
906 
907       if ( values && count >= max_values )
908         break;
909 
910       /* call PS_Conv_ToFixed() even if coords == NULL */
911       /* to properly parse number at `cur'             */
912       *( values ? &values[count] : &dummy ) =
913         PS_Conv_ToFixed( &cur, limit, power_ten );
914 
915       if ( old_cur == cur )
916       {
917         count = -1;
918         goto Exit;
919       }
920       else
921         count++;
922 
923       if ( !ender )
924         break;
925     }
926 
927   Exit:
928     *acur = cur;
929     return count;
930   }
931 
932 
933 #if 0
934 
935   static FT_String*
936   ps_tostring( FT_Byte**  cursor,
937                FT_Byte*   limit,
938                FT_Memory  memory )
939   {
940     FT_Byte*    cur = *cursor;
941     FT_UInt     len = 0;
942     FT_Int      count;
943     FT_String*  result;
944     FT_Error    error;
945 
946 
947     /* XXX: some stupid fonts have a `Notice' or `Copyright' string     */
948     /*      that simply doesn't begin with an opening parenthesis, even */
949     /*      though they have a closing one!  E.g. "amuncial.pfb"        */
950     /*                                                                  */
951     /*      We must deal with these ill-fated cases there.  Note that   */
952     /*      these fonts didn't work with the old Type 1 driver as the   */
953     /*      notice/copyright was not recognized as a valid string token */
954     /*      and made the old token parser commit errors.                */
955 
956     while ( cur < limit && ( *cur == ' ' || *cur == '\t' ) )
957       cur++;
958     if ( cur + 1 >= limit )
959       return 0;
960 
961     if ( *cur == '(' )
962       cur++;  /* skip the opening parenthesis, if there is one */
963 
964     *cursor = cur;
965     count   = 0;
966 
967     /* then, count its length */
968     for ( ; cur < limit; cur++ )
969     {
970       if ( *cur == '(' )
971         count++;
972 
973       else if ( *cur == ')' )
974       {
975         count--;
976         if ( count < 0 )
977           break;
978       }
979     }
980 
981     len = (FT_UInt)( cur - *cursor );
982     if ( cur >= limit || FT_ALLOC( result, len + 1 ) )
983       return 0;
984 
985     /* now copy the string */
986     FT_MEM_COPY( result, *cursor, len );
987     result[len] = '\0';
988     *cursor = cur;
989     return result;
990   }
991 
992 #endif /* 0 */
993 
994 
995   static int
ps_tobool(FT_Byte ** acur,FT_Byte * limit)996   ps_tobool( FT_Byte*  *acur,
997              FT_Byte*   limit )
998   {
999     FT_Byte*  cur    = *acur;
1000     FT_Bool   result = 0;
1001 
1002 
1003     /* return 1 if we find `true', 0 otherwise */
1004     if ( cur + 3 < limit &&
1005          cur[0] == 't'   &&
1006          cur[1] == 'r'   &&
1007          cur[2] == 'u'   &&
1008          cur[3] == 'e'   )
1009     {
1010       result = 1;
1011       cur   += 5;
1012     }
1013     else if ( cur + 4 < limit &&
1014               cur[0] == 'f'   &&
1015               cur[1] == 'a'   &&
1016               cur[2] == 'l'   &&
1017               cur[3] == 's'   &&
1018               cur[4] == 'e'   )
1019     {
1020       result = 0;
1021       cur   += 6;
1022     }
1023 
1024     *acur = cur;
1025     return result;
1026   }
1027 
1028 
1029   /* load a simple field (i.e. non-table) into the current list of objects */
1030 
1031   FT_LOCAL_DEF( FT_Error )
ps_parser_load_field(PS_Parser parser,const T1_Field field,void ** objects,FT_UInt max_objects,FT_ULong * pflags)1032   ps_parser_load_field( PS_Parser       parser,
1033                         const T1_Field  field,
1034                         void**          objects,
1035                         FT_UInt         max_objects,
1036                         FT_ULong*       pflags )
1037   {
1038     T1_TokenRec   token;
1039     FT_Byte*      cur;
1040     FT_Byte*      limit;
1041     FT_UInt       count;
1042     FT_UInt       idx;
1043     FT_Error      error;
1044     T1_FieldType  type;
1045 
1046 
1047     /* this also skips leading whitespace */
1048     ps_parser_to_token( parser, &token );
1049     if ( !token.type )
1050       goto Fail;
1051 
1052     count = 1;
1053     idx   = 0;
1054     cur   = token.start;
1055     limit = token.limit;
1056 
1057     type = field->type;
1058 
1059     /* we must detect arrays in /FontBBox */
1060     if ( type == T1_FIELD_TYPE_BBOX )
1061     {
1062       T1_TokenRec  token2;
1063       FT_Byte*     old_cur   = parser->cursor;
1064       FT_Byte*     old_limit = parser->limit;
1065 
1066 
1067       /* don't include delimiters */
1068       parser->cursor = token.start + 1;
1069       parser->limit  = token.limit - 1;
1070 
1071       ps_parser_to_token( parser, &token2 );
1072       parser->cursor = old_cur;
1073       parser->limit  = old_limit;
1074 
1075       if ( token2.type == T1_TOKEN_TYPE_ARRAY )
1076       {
1077         type = T1_FIELD_TYPE_MM_BBOX;
1078         goto FieldArray;
1079       }
1080     }
1081     else if ( token.type == T1_TOKEN_TYPE_ARRAY )
1082     {
1083       count = max_objects;
1084 
1085     FieldArray:
1086       /* if this is an array and we have no blend, an error occurs */
1087       if ( max_objects == 0 )
1088         goto Fail;
1089 
1090       idx = 1;
1091 
1092       /* don't include delimiters */
1093       cur++;
1094       limit--;
1095     }
1096 
1097     for ( ; count > 0; count--, idx++ )
1098     {
1099       FT_Byte*    q      = (FT_Byte*)objects[idx] + field->offset;
1100       FT_Long     val;
1101       FT_String*  string = NULL;
1102 
1103 
1104       skip_spaces( &cur, limit );
1105 
1106       switch ( type )
1107       {
1108       case T1_FIELD_TYPE_BOOL:
1109         val = ps_tobool( &cur, limit );
1110         FT_TRACE4(( " %s", val ? "true" : "false" ));
1111         goto Store_Integer;
1112 
1113       case T1_FIELD_TYPE_FIXED:
1114         val = PS_Conv_ToFixed( &cur, limit, 0 );
1115         FT_TRACE4(( " %f", (double)val / 65536 ));
1116         goto Store_Integer;
1117 
1118       case T1_FIELD_TYPE_FIXED_1000:
1119         val = PS_Conv_ToFixed( &cur, limit, 3 );
1120         FT_TRACE4(( " %f", (double)val / 65536 / 1000 ));
1121         goto Store_Integer;
1122 
1123       case T1_FIELD_TYPE_INTEGER:
1124         val = PS_Conv_ToInt( &cur, limit );
1125         FT_TRACE4(( " %ld", val ));
1126         /* fall through */
1127 
1128       Store_Integer:
1129         switch ( field->size )
1130         {
1131         case (8 / FT_CHAR_BIT):
1132           *(FT_Byte*)q = (FT_Byte)val;
1133           break;
1134 
1135         case (16 / FT_CHAR_BIT):
1136           *(FT_UShort*)q = (FT_UShort)val;
1137           break;
1138 
1139         case (32 / FT_CHAR_BIT):
1140           *(FT_UInt32*)q = (FT_UInt32)val;
1141           break;
1142 
1143         default:                /* for 64-bit systems */
1144           *(FT_Long*)q = val;
1145         }
1146         break;
1147 
1148       case T1_FIELD_TYPE_STRING:
1149       case T1_FIELD_TYPE_KEY:
1150         {
1151           FT_Memory  memory = parser->memory;
1152           FT_UInt    len    = (FT_UInt)( limit - cur );
1153 
1154 
1155           if ( cur >= limit )
1156             break;
1157 
1158           /* we allow both a string or a name   */
1159           /* for cases like /FontName (foo) def */
1160           if ( token.type == T1_TOKEN_TYPE_KEY )
1161           {
1162             /* don't include leading `/' */
1163             len--;
1164             cur++;
1165           }
1166           else if ( token.type == T1_TOKEN_TYPE_STRING )
1167           {
1168             /* don't include delimiting parentheses    */
1169             /* XXX we don't handle <<...>> here        */
1170             /* XXX should we convert octal escapes?    */
1171             /*     if so, what encoding should we use? */
1172             cur++;
1173             len -= 2;
1174           }
1175           else
1176           {
1177             FT_ERROR(( "ps_parser_load_field:"
1178                        " expected a name or string\n"
1179                        "                     "
1180                        " but found token of type %d instead\n",
1181                        token.type ));
1182             error = FT_THROW( Invalid_File_Format );
1183             goto Exit;
1184           }
1185 
1186           /* for this to work (FT_String**)q must have been */
1187           /* initialized to NULL                            */
1188           if ( *(FT_String**)q )
1189           {
1190             FT_TRACE0(( "ps_parser_load_field: overwriting field %s\n",
1191                         field->ident ));
1192             FT_FREE( *(FT_String**)q );
1193             *(FT_String**)q = NULL;
1194           }
1195 
1196           if ( FT_ALLOC( string, len + 1 ) )
1197             goto Exit;
1198 
1199           FT_MEM_COPY( string, cur, len );
1200           string[len] = 0;
1201 
1202 #ifdef FT_DEBUG_LEVEL_TRACE
1203           if ( token.type == T1_TOKEN_TYPE_STRING )
1204             FT_TRACE4(( " (%s)", string ));
1205           else
1206             FT_TRACE4(( " /%s", string ));
1207 #endif
1208 
1209           *(FT_String**)q = string;
1210         }
1211         break;
1212 
1213       case T1_FIELD_TYPE_BBOX:
1214         {
1215           FT_Fixed  temp[4];
1216           FT_BBox*  bbox = (FT_BBox*)q;
1217           FT_Int    result;
1218 
1219 
1220           result = ps_tofixedarray( &cur, limit, 4, temp, 0 );
1221 
1222           if ( result < 4 )
1223           {
1224             FT_ERROR(( "ps_parser_load_field:"
1225                        " expected four integers in bounding box\n" ));
1226             error = FT_THROW( Invalid_File_Format );
1227             goto Exit;
1228           }
1229 
1230           bbox->xMin = FT_RoundFix( temp[0] );
1231           bbox->yMin = FT_RoundFix( temp[1] );
1232           bbox->xMax = FT_RoundFix( temp[2] );
1233           bbox->yMax = FT_RoundFix( temp[3] );
1234 
1235           FT_TRACE4(( " [%ld %ld %ld %ld]",
1236                       bbox->xMin / 65536,
1237                       bbox->yMin / 65536,
1238                       bbox->xMax / 65536,
1239                       bbox->yMax / 65536 ));
1240         }
1241         break;
1242 
1243       case T1_FIELD_TYPE_MM_BBOX:
1244         {
1245           FT_Memory  memory = parser->memory;
1246           FT_Fixed*  temp   = NULL;
1247           FT_Int     result;
1248           FT_UInt    i;
1249 
1250 
1251           if ( FT_NEW_ARRAY( temp, max_objects * 4 ) )
1252             goto Exit;
1253 
1254           for ( i = 0; i < 4; i++ )
1255           {
1256             result = ps_tofixedarray( &cur, limit, (FT_Int)max_objects,
1257                                       temp + i * max_objects, 0 );
1258             if ( result < 0 || (FT_UInt)result < max_objects )
1259             {
1260               FT_ERROR(( "ps_parser_load_field:"
1261                          " expected %d integer%s in the %s subarray\n"
1262                          "                     "
1263                          " of /FontBBox in the /Blend dictionary\n",
1264                          max_objects, max_objects > 1 ? "s" : "",
1265                          i == 0 ? "first"
1266                                 : ( i == 1 ? "second"
1267                                            : ( i == 2 ? "third"
1268                                                       : "fourth" ) ) ));
1269               error = FT_THROW( Invalid_File_Format );
1270 
1271               FT_FREE( temp );
1272               goto Exit;
1273             }
1274 
1275             skip_spaces( &cur, limit );
1276           }
1277 
1278           FT_TRACE4(( " [" ));
1279           for ( i = 0; i < max_objects; i++ )
1280           {
1281             FT_BBox*  bbox = (FT_BBox*)objects[i];
1282 
1283 
1284             bbox->xMin = FT_RoundFix( temp[i                  ] );
1285             bbox->yMin = FT_RoundFix( temp[i +     max_objects] );
1286             bbox->xMax = FT_RoundFix( temp[i + 2 * max_objects] );
1287             bbox->yMax = FT_RoundFix( temp[i + 3 * max_objects] );
1288 
1289             FT_TRACE4(( " [%ld %ld %ld %ld]",
1290                         bbox->xMin / 65536,
1291                         bbox->yMin / 65536,
1292                         bbox->xMax / 65536,
1293                         bbox->yMax / 65536 ));
1294           }
1295           FT_TRACE4(( "]" ));
1296 
1297           FT_FREE( temp );
1298         }
1299         break;
1300 
1301       default:
1302         /* an error occurred */
1303         goto Fail;
1304       }
1305     }
1306 
1307 #if 0  /* obsolete -- keep for reference */
1308     if ( pflags )
1309       *pflags |= 1L << field->flag_bit;
1310 #else
1311     FT_UNUSED( pflags );
1312 #endif
1313 
1314     error = FT_Err_Ok;
1315 
1316   Exit:
1317     return error;
1318 
1319   Fail:
1320     error = FT_THROW( Invalid_File_Format );
1321     goto Exit;
1322   }
1323 
1324 
1325 #define T1_MAX_TABLE_ELEMENTS  32
1326 
1327 
1328   FT_LOCAL_DEF( FT_Error )
ps_parser_load_field_table(PS_Parser parser,const T1_Field field,void ** objects,FT_UInt max_objects,FT_ULong * pflags)1329   ps_parser_load_field_table( PS_Parser       parser,
1330                               const T1_Field  field,
1331                               void**          objects,
1332                               FT_UInt         max_objects,
1333                               FT_ULong*       pflags )
1334   {
1335     T1_TokenRec  elements[T1_MAX_TABLE_ELEMENTS];
1336     T1_Token     token;
1337     FT_Int       num_elements;
1338     FT_Error     error = FT_Err_Ok;
1339     FT_Byte*     old_cursor;
1340     FT_Byte*     old_limit;
1341     T1_FieldRec  fieldrec = *(T1_Field)field;
1342 
1343 
1344     fieldrec.type = T1_FIELD_TYPE_INTEGER;
1345     if ( field->type == T1_FIELD_TYPE_FIXED_ARRAY ||
1346          field->type == T1_FIELD_TYPE_BBOX        )
1347       fieldrec.type = T1_FIELD_TYPE_FIXED;
1348 
1349     ps_parser_to_token_array( parser, elements,
1350                               T1_MAX_TABLE_ELEMENTS, &num_elements );
1351     if ( num_elements < 0 )
1352     {
1353       error = FT_ERR( Ignore );
1354       goto Exit;
1355     }
1356     if ( (FT_UInt)num_elements > field->array_max )
1357       num_elements = (FT_Int)field->array_max;
1358 
1359     old_cursor = parser->cursor;
1360     old_limit  = parser->limit;
1361 
1362     /* we store the elements count if necessary;           */
1363     /* we further assume that `count_offset' can't be zero */
1364     if ( field->type != T1_FIELD_TYPE_BBOX && field->count_offset != 0 )
1365       *(FT_Byte*)( (FT_Byte*)objects[0] + field->count_offset ) =
1366         (FT_Byte)num_elements;
1367 
1368     FT_TRACE4(( " [" ));
1369 
1370     /* we now load each element, adjusting the field.offset on each one */
1371     token = elements;
1372     for ( ; num_elements > 0; num_elements--, token++ )
1373     {
1374       parser->cursor = token->start;
1375       parser->limit  = token->limit;
1376 
1377       error = ps_parser_load_field( parser,
1378                                     &fieldrec,
1379                                     objects,
1380                                     max_objects,
1381                                     0 );
1382       if ( error )
1383         break;
1384 
1385       fieldrec.offset += fieldrec.size;
1386     }
1387 
1388     FT_TRACE4(( "]" ));
1389 
1390 #if 0  /* obsolete -- keep for reference */
1391     if ( pflags )
1392       *pflags |= 1L << field->flag_bit;
1393 #else
1394     FT_UNUSED( pflags );
1395 #endif
1396 
1397     parser->cursor = old_cursor;
1398     parser->limit  = old_limit;
1399 
1400   Exit:
1401     return error;
1402   }
1403 
1404 
1405   FT_LOCAL_DEF( FT_Long )
ps_parser_to_int(PS_Parser parser)1406   ps_parser_to_int( PS_Parser  parser )
1407   {
1408     ps_parser_skip_spaces( parser );
1409     return PS_Conv_ToInt( &parser->cursor, parser->limit );
1410   }
1411 
1412 
1413   /* first character must be `<' if `delimiters' is non-zero */
1414 
1415   FT_LOCAL_DEF( FT_Error )
ps_parser_to_bytes(PS_Parser parser,FT_Byte * bytes,FT_Offset max_bytes,FT_ULong * pnum_bytes,FT_Bool delimiters)1416   ps_parser_to_bytes( PS_Parser  parser,
1417                       FT_Byte*   bytes,
1418                       FT_Offset  max_bytes,
1419                       FT_ULong*  pnum_bytes,
1420                       FT_Bool    delimiters )
1421   {
1422     FT_Error  error = FT_Err_Ok;
1423     FT_Byte*  cur;
1424 
1425 
1426     ps_parser_skip_spaces( parser );
1427     cur = parser->cursor;
1428 
1429     if ( cur >= parser->limit )
1430       goto Exit;
1431 
1432     if ( delimiters )
1433     {
1434       if ( *cur != '<' )
1435       {
1436         FT_ERROR(( "ps_parser_to_bytes: Missing starting delimiter `<'\n" ));
1437         error = FT_THROW( Invalid_File_Format );
1438         goto Exit;
1439       }
1440 
1441       cur++;
1442     }
1443 
1444     *pnum_bytes = PS_Conv_ASCIIHexDecode( &cur,
1445                                           parser->limit,
1446                                           bytes,
1447                                           max_bytes );
1448 
1449     parser->cursor = cur;
1450 
1451     if ( delimiters )
1452     {
1453       if ( cur < parser->limit && *cur != '>' )
1454       {
1455         FT_ERROR(( "ps_parser_to_bytes: Missing closing delimiter `>'\n" ));
1456         error = FT_THROW( Invalid_File_Format );
1457         goto Exit;
1458       }
1459 
1460       parser->cursor++;
1461     }
1462 
1463   Exit:
1464     return error;
1465   }
1466 
1467 
1468   FT_LOCAL_DEF( FT_Fixed )
ps_parser_to_fixed(PS_Parser parser,FT_Int power_ten)1469   ps_parser_to_fixed( PS_Parser  parser,
1470                       FT_Int     power_ten )
1471   {
1472     ps_parser_skip_spaces( parser );
1473     return PS_Conv_ToFixed( &parser->cursor, parser->limit, power_ten );
1474   }
1475 
1476 
1477   FT_LOCAL_DEF( FT_Int )
ps_parser_to_coord_array(PS_Parser parser,FT_Int max_coords,FT_Short * coords)1478   ps_parser_to_coord_array( PS_Parser  parser,
1479                             FT_Int     max_coords,
1480                             FT_Short*  coords )
1481   {
1482     ps_parser_skip_spaces( parser );
1483     return ps_tocoordarray( &parser->cursor, parser->limit,
1484                             max_coords, coords );
1485   }
1486 
1487 
1488   FT_LOCAL_DEF( FT_Int )
ps_parser_to_fixed_array(PS_Parser parser,FT_Int max_values,FT_Fixed * values,FT_Int power_ten)1489   ps_parser_to_fixed_array( PS_Parser  parser,
1490                             FT_Int     max_values,
1491                             FT_Fixed*  values,
1492                             FT_Int     power_ten )
1493   {
1494     ps_parser_skip_spaces( parser );
1495     return ps_tofixedarray( &parser->cursor, parser->limit,
1496                             max_values, values, power_ten );
1497   }
1498 
1499 
1500 #if 0
1501 
1502   FT_LOCAL_DEF( FT_String* )
1503   T1_ToString( PS_Parser  parser )
1504   {
1505     return ps_tostring( &parser->cursor, parser->limit, parser->memory );
1506   }
1507 
1508 
1509   FT_LOCAL_DEF( FT_Bool )
1510   T1_ToBool( PS_Parser  parser )
1511   {
1512     return ps_tobool( &parser->cursor, parser->limit );
1513   }
1514 
1515 #endif /* 0 */
1516 
1517 
1518   FT_LOCAL_DEF( void )
ps_parser_init(PS_Parser parser,FT_Byte * base,FT_Byte * limit,FT_Memory memory)1519   ps_parser_init( PS_Parser  parser,
1520                   FT_Byte*   base,
1521                   FT_Byte*   limit,
1522                   FT_Memory  memory )
1523   {
1524     parser->error  = FT_Err_Ok;
1525     parser->base   = base;
1526     parser->limit  = limit;
1527     parser->cursor = base;
1528     parser->memory = memory;
1529     parser->funcs  = ps_parser_funcs;
1530   }
1531 
1532 
1533   FT_LOCAL_DEF( void )
ps_parser_done(PS_Parser parser)1534   ps_parser_done( PS_Parser  parser )
1535   {
1536     FT_UNUSED( parser );
1537   }
1538 
1539 
1540   /*************************************************************************/
1541   /*************************************************************************/
1542   /*****                                                               *****/
1543   /*****                            T1 BUILDER                         *****/
1544   /*****                                                               *****/
1545   /*************************************************************************/
1546   /*************************************************************************/
1547 
1548   /**************************************************************************
1549    *
1550    * @Function:
1551    *   t1_builder_init
1552    *
1553    * @Description:
1554    *   Initializes a given glyph builder.
1555    *
1556    * @InOut:
1557    *   builder ::
1558    *     A pointer to the glyph builder to initialize.
1559    *
1560    * @Input:
1561    *   face ::
1562    *     The current face object.
1563    *
1564    *   size ::
1565    *     The current size object.
1566    *
1567    *   glyph ::
1568    *     The current glyph object.
1569    *
1570    *   hinting ::
1571    *     Whether hinting should be applied.
1572    */
1573   FT_LOCAL_DEF( void )
t1_builder_init(T1_Builder builder,FT_Face face,FT_Size size,FT_GlyphSlot glyph,FT_Bool hinting)1574   t1_builder_init( T1_Builder    builder,
1575                    FT_Face       face,
1576                    FT_Size       size,
1577                    FT_GlyphSlot  glyph,
1578                    FT_Bool       hinting )
1579   {
1580     builder->parse_state = T1_Parse_Start;
1581     builder->load_points = 1;
1582 
1583     builder->face   = face;
1584     builder->glyph  = glyph;
1585     builder->memory = face->memory;
1586 
1587     if ( glyph )
1588     {
1589       FT_GlyphLoader  loader = glyph->internal->loader;
1590 
1591 
1592       builder->loader  = loader;
1593       builder->base    = &loader->base.outline;
1594       builder->current = &loader->current.outline;
1595       FT_GlyphLoader_Rewind( loader );
1596 
1597       builder->hints_globals = size->internal->module_data;
1598       builder->hints_funcs   = NULL;
1599 
1600       if ( hinting )
1601         builder->hints_funcs = glyph->internal->glyph_hints;
1602     }
1603 
1604     builder->pos_x = 0;
1605     builder->pos_y = 0;
1606 
1607     builder->left_bearing.x = 0;
1608     builder->left_bearing.y = 0;
1609     builder->advance.x      = 0;
1610     builder->advance.y      = 0;
1611 
1612     builder->funcs = t1_builder_funcs;
1613   }
1614 
1615 
1616   /**************************************************************************
1617    *
1618    * @Function:
1619    *   t1_builder_done
1620    *
1621    * @Description:
1622    *   Finalizes a given glyph builder.  Its contents can still be used
1623    *   after the call, but the function saves important information
1624    *   within the corresponding glyph slot.
1625    *
1626    * @Input:
1627    *   builder ::
1628    *     A pointer to the glyph builder to finalize.
1629    */
1630   FT_LOCAL_DEF( void )
t1_builder_done(T1_Builder builder)1631   t1_builder_done( T1_Builder  builder )
1632   {
1633     FT_GlyphSlot  glyph = builder->glyph;
1634 
1635 
1636     if ( glyph )
1637       glyph->outline = *builder->base;
1638   }
1639 
1640 
1641   /* check that there is enough space for `count' more points */
1642   FT_LOCAL_DEF( FT_Error )
t1_builder_check_points(T1_Builder builder,FT_Int count)1643   t1_builder_check_points( T1_Builder  builder,
1644                            FT_Int      count )
1645   {
1646     return FT_GLYPHLOADER_CHECK_POINTS( builder->loader, count, 0 );
1647   }
1648 
1649 
1650   /* add a new point, do not check space */
1651   FT_LOCAL_DEF( void )
t1_builder_add_point(T1_Builder builder,FT_Pos x,FT_Pos y,FT_Byte flag)1652   t1_builder_add_point( T1_Builder  builder,
1653                         FT_Pos      x,
1654                         FT_Pos      y,
1655                         FT_Byte     flag )
1656   {
1657     FT_Outline*  outline = builder->current;
1658 
1659 
1660     if ( builder->load_points )
1661     {
1662       FT_Vector*  point   = outline->points + outline->n_points;
1663       FT_Byte*    control = (FT_Byte*)outline->tags + outline->n_points;
1664 
1665 
1666       point->x = FIXED_TO_INT( x );
1667       point->y = FIXED_TO_INT( y );
1668       *control = (FT_Byte)( flag ? FT_CURVE_TAG_ON : FT_CURVE_TAG_CUBIC );
1669     }
1670     outline->n_points++;
1671   }
1672 
1673 
1674   /* check space for a new on-curve point, then add it */
1675   FT_LOCAL_DEF( FT_Error )
t1_builder_add_point1(T1_Builder builder,FT_Pos x,FT_Pos y)1676   t1_builder_add_point1( T1_Builder  builder,
1677                          FT_Pos      x,
1678                          FT_Pos      y )
1679   {
1680     FT_Error  error;
1681 
1682 
1683     error = t1_builder_check_points( builder, 1 );
1684     if ( !error )
1685       t1_builder_add_point( builder, x, y, 1 );
1686 
1687     return error;
1688   }
1689 
1690 
1691   /* check space for a new contour, then add it */
1692   FT_LOCAL_DEF( FT_Error )
t1_builder_add_contour(T1_Builder builder)1693   t1_builder_add_contour( T1_Builder  builder )
1694   {
1695     FT_Outline*  outline = builder->current;
1696     FT_Error     error;
1697 
1698 
1699     /* this might happen in invalid fonts */
1700     if ( !outline )
1701     {
1702       FT_ERROR(( "t1_builder_add_contour: no outline to add points to\n" ));
1703       return FT_THROW( Invalid_File_Format );
1704     }
1705 
1706     if ( !builder->load_points )
1707     {
1708       outline->n_contours++;
1709       return FT_Err_Ok;
1710     }
1711 
1712     error = FT_GLYPHLOADER_CHECK_POINTS( builder->loader, 0, 1 );
1713     if ( !error )
1714     {
1715       if ( outline->n_contours > 0 )
1716         outline->contours[outline->n_contours - 1] =
1717           (short)( outline->n_points - 1 );
1718 
1719       outline->n_contours++;
1720     }
1721 
1722     return error;
1723   }
1724 
1725 
1726   /* if a path was begun, add its first on-curve point */
1727   FT_LOCAL_DEF( FT_Error )
t1_builder_start_point(T1_Builder builder,FT_Pos x,FT_Pos y)1728   t1_builder_start_point( T1_Builder  builder,
1729                           FT_Pos      x,
1730                           FT_Pos      y )
1731   {
1732     FT_Error  error = FT_ERR( Invalid_File_Format );
1733 
1734 
1735     /* test whether we are building a new contour */
1736 
1737     if ( builder->parse_state == T1_Parse_Have_Path )
1738       error = FT_Err_Ok;
1739     else
1740     {
1741       builder->parse_state = T1_Parse_Have_Path;
1742       error = t1_builder_add_contour( builder );
1743       if ( !error )
1744         error = t1_builder_add_point1( builder, x, y );
1745     }
1746 
1747     return error;
1748   }
1749 
1750 
1751   /* close the current contour */
1752   FT_LOCAL_DEF( void )
t1_builder_close_contour(T1_Builder builder)1753   t1_builder_close_contour( T1_Builder  builder )
1754   {
1755     FT_Outline*  outline = builder->current;
1756     FT_Int       first;
1757 
1758 
1759     if ( !outline )
1760       return;
1761 
1762     first = outline->n_contours <= 1
1763             ? 0 : outline->contours[outline->n_contours - 2] + 1;
1764 
1765     /* in malformed fonts it can happen that a contour was started */
1766     /* but no points were added                                    */
1767     if ( outline->n_contours && first == outline->n_points )
1768     {
1769       outline->n_contours--;
1770       return;
1771     }
1772 
1773     /* We must not include the last point in the path if it */
1774     /* is located on the first point.                       */
1775     if ( outline->n_points > 1 )
1776     {
1777       FT_Vector*  p1      = outline->points + first;
1778       FT_Vector*  p2      = outline->points + outline->n_points - 1;
1779       FT_Byte*    control = (FT_Byte*)outline->tags + outline->n_points - 1;
1780 
1781 
1782       /* `delete' last point only if it coincides with the first */
1783       /* point and it is not a control point (which can happen). */
1784       if ( p1->x == p2->x && p1->y == p2->y )
1785         if ( *control == FT_CURVE_TAG_ON )
1786           outline->n_points--;
1787     }
1788 
1789     if ( outline->n_contours > 0 )
1790     {
1791       /* Don't add contours only consisting of one point, i.e.,  */
1792       /* check whether the first and the last point is the same. */
1793       if ( first == outline->n_points - 1 )
1794       {
1795         outline->n_contours--;
1796         outline->n_points--;
1797       }
1798       else
1799         outline->contours[outline->n_contours - 1] =
1800           (short)( outline->n_points - 1 );
1801     }
1802   }
1803 
1804 
1805   /*************************************************************************/
1806   /*************************************************************************/
1807   /*****                                                               *****/
1808   /*****                           CFF BUILDER                         *****/
1809   /*****                                                               *****/
1810   /*************************************************************************/
1811   /*************************************************************************/
1812 
1813 
1814   /**************************************************************************
1815    *
1816    * @Function:
1817    *   cff_builder_init
1818    *
1819    * @Description:
1820    *   Initializes a given glyph builder.
1821    *
1822    * @InOut:
1823    *   builder ::
1824    *     A pointer to the glyph builder to initialize.
1825    *
1826    * @Input:
1827    *   face ::
1828    *     The current face object.
1829    *
1830    *   size ::
1831    *     The current size object.
1832    *
1833    *   glyph ::
1834    *     The current glyph object.
1835    *
1836    *   hinting ::
1837    *     Whether hinting is active.
1838    */
1839   FT_LOCAL_DEF( void )
cff_builder_init(CFF_Builder * builder,TT_Face face,CFF_Size size,CFF_GlyphSlot glyph,FT_Bool hinting)1840   cff_builder_init( CFF_Builder*   builder,
1841                     TT_Face        face,
1842                     CFF_Size       size,
1843                     CFF_GlyphSlot  glyph,
1844                     FT_Bool        hinting )
1845   {
1846     builder->path_begun  = 0;
1847     builder->load_points = 1;
1848 
1849     builder->face   = face;
1850     builder->glyph  = glyph;
1851     builder->memory = face->root.memory;
1852 
1853     if ( glyph )
1854     {
1855       FT_GlyphLoader  loader = glyph->root.internal->loader;
1856 
1857 
1858       builder->loader  = loader;
1859       builder->base    = &loader->base.outline;
1860       builder->current = &loader->current.outline;
1861       FT_GlyphLoader_Rewind( loader );
1862 
1863       builder->hints_globals = NULL;
1864       builder->hints_funcs   = NULL;
1865 
1866       if ( hinting && size )
1867       {
1868         FT_Size       ftsize   = FT_SIZE( size );
1869         CFF_Internal  internal = (CFF_Internal)ftsize->internal->module_data;
1870 
1871         if ( internal )
1872         {
1873           builder->hints_globals = (void *)internal->topfont;
1874           builder->hints_funcs   = glyph->root.internal->glyph_hints;
1875         }
1876       }
1877     }
1878 
1879     builder->pos_x = 0;
1880     builder->pos_y = 0;
1881 
1882     builder->left_bearing.x = 0;
1883     builder->left_bearing.y = 0;
1884     builder->advance.x      = 0;
1885     builder->advance.y      = 0;
1886 
1887     builder->funcs = cff_builder_funcs;
1888   }
1889 
1890 
1891   /**************************************************************************
1892    *
1893    * @Function:
1894    *   cff_builder_done
1895    *
1896    * @Description:
1897    *   Finalizes a given glyph builder.  Its contents can still be used
1898    *   after the call, but the function saves important information
1899    *   within the corresponding glyph slot.
1900    *
1901    * @Input:
1902    *   builder ::
1903    *     A pointer to the glyph builder to finalize.
1904    */
1905   FT_LOCAL_DEF( void )
cff_builder_done(CFF_Builder * builder)1906   cff_builder_done( CFF_Builder*  builder )
1907   {
1908     CFF_GlyphSlot  glyph = builder->glyph;
1909 
1910 
1911     if ( glyph )
1912       glyph->root.outline = *builder->base;
1913   }
1914 
1915 
1916   /* check that there is enough space for `count' more points */
1917   FT_LOCAL_DEF( FT_Error )
cff_check_points(CFF_Builder * builder,FT_Int count)1918   cff_check_points( CFF_Builder*  builder,
1919                     FT_Int        count )
1920   {
1921     return FT_GLYPHLOADER_CHECK_POINTS( builder->loader, count, 0 );
1922   }
1923 
1924 
1925   /* add a new point, do not check space */
1926   FT_LOCAL_DEF( void )
cff_builder_add_point(CFF_Builder * builder,FT_Pos x,FT_Pos y,FT_Byte flag)1927   cff_builder_add_point( CFF_Builder*  builder,
1928                          FT_Pos        x,
1929                          FT_Pos        y,
1930                          FT_Byte       flag )
1931   {
1932     FT_Outline*  outline = builder->current;
1933 
1934 
1935     if ( builder->load_points )
1936     {
1937       FT_Vector*  point   = outline->points + outline->n_points;
1938       FT_Byte*    control = (FT_Byte*)outline->tags + outline->n_points;
1939 
1940 #ifdef CFF_CONFIG_OPTION_OLD_ENGINE
1941       PS_Driver  driver   = (PS_Driver)FT_FACE_DRIVER( builder->face );
1942 
1943 
1944       if ( driver->hinting_engine == FT_HINTING_FREETYPE )
1945       {
1946         point->x = x >> 16;
1947         point->y = y >> 16;
1948       }
1949       else
1950 #endif
1951       {
1952         /* cf2_decoder_parse_charstrings uses 16.16 coordinates */
1953         point->x = x >> 10;
1954         point->y = y >> 10;
1955       }
1956       *control = (FT_Byte)( flag ? FT_CURVE_TAG_ON : FT_CURVE_TAG_CUBIC );
1957     }
1958 
1959     outline->n_points++;
1960   }
1961 
1962 
1963   /* check space for a new on-curve point, then add it */
1964   FT_LOCAL_DEF( FT_Error )
cff_builder_add_point1(CFF_Builder * builder,FT_Pos x,FT_Pos y)1965   cff_builder_add_point1( CFF_Builder*  builder,
1966                           FT_Pos        x,
1967                           FT_Pos        y )
1968   {
1969     FT_Error  error;
1970 
1971 
1972     error = cff_check_points( builder, 1 );
1973     if ( !error )
1974       cff_builder_add_point( builder, x, y, 1 );
1975 
1976     return error;
1977   }
1978 
1979 
1980   /* check space for a new contour, then add it */
1981   FT_LOCAL_DEF( FT_Error )
cff_builder_add_contour(CFF_Builder * builder)1982   cff_builder_add_contour( CFF_Builder*  builder )
1983   {
1984     FT_Outline*  outline = builder->current;
1985     FT_Error     error;
1986 
1987 
1988     if ( !builder->load_points )
1989     {
1990       outline->n_contours++;
1991       return FT_Err_Ok;
1992     }
1993 
1994     error = FT_GLYPHLOADER_CHECK_POINTS( builder->loader, 0, 1 );
1995     if ( !error )
1996     {
1997       if ( outline->n_contours > 0 )
1998         outline->contours[outline->n_contours - 1] =
1999           (short)( outline->n_points - 1 );
2000 
2001       outline->n_contours++;
2002     }
2003 
2004     return error;
2005   }
2006 
2007 
2008   /* if a path was begun, add its first on-curve point */
2009   FT_LOCAL_DEF( FT_Error )
cff_builder_start_point(CFF_Builder * builder,FT_Pos x,FT_Pos y)2010   cff_builder_start_point( CFF_Builder*  builder,
2011                            FT_Pos        x,
2012                            FT_Pos        y )
2013   {
2014     FT_Error  error = FT_Err_Ok;
2015 
2016 
2017     /* test whether we are building a new contour */
2018     if ( !builder->path_begun )
2019     {
2020       builder->path_begun = 1;
2021       error = cff_builder_add_contour( builder );
2022       if ( !error )
2023         error = cff_builder_add_point1( builder, x, y );
2024     }
2025 
2026     return error;
2027   }
2028 
2029 
2030   /* close the current contour */
2031   FT_LOCAL_DEF( void )
cff_builder_close_contour(CFF_Builder * builder)2032   cff_builder_close_contour( CFF_Builder*  builder )
2033   {
2034     FT_Outline*  outline = builder->current;
2035     FT_Int       first;
2036 
2037 
2038     if ( !outline )
2039       return;
2040 
2041     first = outline->n_contours <= 1
2042             ? 0 : outline->contours[outline->n_contours - 2] + 1;
2043 
2044     /* in malformed fonts it can happen that a contour was started */
2045     /* but no points were added                                    */
2046     if ( outline->n_contours && first == outline->n_points )
2047     {
2048       outline->n_contours--;
2049       return;
2050     }
2051 
2052     /* We must not include the last point in the path if it */
2053     /* is located on the first point.                       */
2054     if ( outline->n_points > 1 )
2055     {
2056       FT_Vector*  p1      = outline->points + first;
2057       FT_Vector*  p2      = outline->points + outline->n_points - 1;
2058       FT_Byte*    control = (FT_Byte*)outline->tags + outline->n_points - 1;
2059 
2060 
2061       /* `delete' last point only if it coincides with the first    */
2062       /* point and if it is not a control point (which can happen). */
2063       if ( p1->x == p2->x && p1->y == p2->y )
2064         if ( *control == FT_CURVE_TAG_ON )
2065           outline->n_points--;
2066     }
2067 
2068     if ( outline->n_contours > 0 )
2069     {
2070       /* Don't add contours only consisting of one point, i.e., */
2071       /* check whether begin point and last point are the same. */
2072       if ( first == outline->n_points - 1 )
2073       {
2074         outline->n_contours--;
2075         outline->n_points--;
2076       }
2077       else
2078         outline->contours[outline->n_contours - 1] =
2079           (short)( outline->n_points - 1 );
2080     }
2081   }
2082 
2083 
2084   /*************************************************************************/
2085   /*************************************************************************/
2086   /*****                                                               *****/
2087   /*****                            PS BUILDER                         *****/
2088   /*****                                                               *****/
2089   /*************************************************************************/
2090   /*************************************************************************/
2091 
2092   /**************************************************************************
2093    *
2094    * @Function:
2095    *   ps_builder_init
2096    *
2097    * @Description:
2098    *   Initializes a given glyph builder.
2099    *
2100    * @InOut:
2101    *   builder ::
2102    *     A pointer to the glyph builder to initialize.
2103    *
2104    * @Input:
2105    *   face ::
2106    *     The current face object.
2107    *
2108    *   size ::
2109    *     The current size object.
2110    *
2111    *   glyph ::
2112    *     The current glyph object.
2113    *
2114    *   hinting ::
2115    *     Whether hinting should be applied.
2116    */
2117   FT_LOCAL_DEF( void )
ps_builder_init(PS_Builder * ps_builder,void * builder,FT_Bool is_t1)2118   ps_builder_init( PS_Builder*  ps_builder,
2119                    void*        builder,
2120                    FT_Bool      is_t1 )
2121   {
2122     FT_ZERO( ps_builder );
2123 
2124     if ( is_t1 )
2125     {
2126       T1_Builder  t1builder = (T1_Builder)builder;
2127 
2128 
2129       ps_builder->memory  = t1builder->memory;
2130       ps_builder->face    = (FT_Face)t1builder->face;
2131       ps_builder->glyph   = (CFF_GlyphSlot)t1builder->glyph;
2132       ps_builder->loader  = t1builder->loader;
2133       ps_builder->base    = t1builder->base;
2134       ps_builder->current = t1builder->current;
2135 
2136       ps_builder->pos_x = &t1builder->pos_x;
2137       ps_builder->pos_y = &t1builder->pos_y;
2138 
2139       ps_builder->left_bearing = &t1builder->left_bearing;
2140       ps_builder->advance      = &t1builder->advance;
2141 
2142       ps_builder->bbox        = &t1builder->bbox;
2143       ps_builder->path_begun  = 0;
2144       ps_builder->load_points = t1builder->load_points;
2145       ps_builder->no_recurse  = t1builder->no_recurse;
2146 
2147       ps_builder->metrics_only = t1builder->metrics_only;
2148     }
2149     else
2150     {
2151       CFF_Builder*  cffbuilder = (CFF_Builder*)builder;
2152 
2153 
2154       ps_builder->memory  = cffbuilder->memory;
2155       ps_builder->face    = (FT_Face)cffbuilder->face;
2156       ps_builder->glyph   = cffbuilder->glyph;
2157       ps_builder->loader  = cffbuilder->loader;
2158       ps_builder->base    = cffbuilder->base;
2159       ps_builder->current = cffbuilder->current;
2160 
2161       ps_builder->pos_x = &cffbuilder->pos_x;
2162       ps_builder->pos_y = &cffbuilder->pos_y;
2163 
2164       ps_builder->left_bearing = &cffbuilder->left_bearing;
2165       ps_builder->advance      = &cffbuilder->advance;
2166 
2167       ps_builder->bbox        = &cffbuilder->bbox;
2168       ps_builder->path_begun  = cffbuilder->path_begun;
2169       ps_builder->load_points = cffbuilder->load_points;
2170       ps_builder->no_recurse  = cffbuilder->no_recurse;
2171 
2172       ps_builder->metrics_only = cffbuilder->metrics_only;
2173     }
2174 
2175     ps_builder->is_t1 = is_t1;
2176     ps_builder->funcs = ps_builder_funcs;
2177   }
2178 
2179 
2180   /**************************************************************************
2181    *
2182    * @Function:
2183    *   ps_builder_done
2184    *
2185    * @Description:
2186    *   Finalizes a given glyph builder.  Its contents can still be used
2187    *   after the call, but the function saves important information
2188    *   within the corresponding glyph slot.
2189    *
2190    * @Input:
2191    *   builder ::
2192    *     A pointer to the glyph builder to finalize.
2193    */
2194   FT_LOCAL_DEF( void )
ps_builder_done(PS_Builder * builder)2195   ps_builder_done( PS_Builder*  builder )
2196   {
2197     CFF_GlyphSlot  glyph = builder->glyph;
2198 
2199 
2200     if ( glyph )
2201       glyph->root.outline = *builder->base;
2202   }
2203 
2204 
2205   /* check that there is enough space for `count' more points */
2206   FT_LOCAL_DEF( FT_Error )
ps_builder_check_points(PS_Builder * builder,FT_Int count)2207   ps_builder_check_points( PS_Builder*  builder,
2208                            FT_Int       count )
2209   {
2210     return FT_GLYPHLOADER_CHECK_POINTS( builder->loader, count, 0 );
2211   }
2212 
2213 
2214   /* add a new point, do not check space */
2215   FT_LOCAL_DEF( void )
ps_builder_add_point(PS_Builder * builder,FT_Pos x,FT_Pos y,FT_Byte flag)2216   ps_builder_add_point( PS_Builder*  builder,
2217                         FT_Pos       x,
2218                         FT_Pos       y,
2219                         FT_Byte      flag )
2220   {
2221     FT_Outline*  outline = builder->current;
2222 
2223 
2224     if ( builder->load_points )
2225     {
2226       FT_Vector*  point   = outline->points + outline->n_points;
2227       FT_Byte*    control = (FT_Byte*)outline->tags + outline->n_points;
2228 
2229 #ifdef CFF_CONFIG_OPTION_OLD_ENGINE
2230       PS_Driver  driver   = (PS_Driver)FT_FACE_DRIVER( builder->face );
2231 
2232 
2233       if ( !builder->is_t1 &&
2234            driver->hinting_engine == FT_HINTING_FREETYPE )
2235       {
2236         point->x = x >> 16;
2237         point->y = y >> 16;
2238       }
2239       else
2240 #endif
2241 #ifdef T1_CONFIG_OPTION_OLD_ENGINE
2242 #ifndef CFF_CONFIG_OPTION_OLD_ENGINE
2243       PS_Driver  driver   = (PS_Driver)FT_FACE_DRIVER( builder->face );
2244 #endif
2245       if ( builder->is_t1 &&
2246            driver->hinting_engine == FT_HINTING_FREETYPE )
2247       {
2248         point->x = FIXED_TO_INT( x );
2249         point->y = FIXED_TO_INT( y );
2250       }
2251       else
2252 #endif
2253       {
2254         /* cf2_decoder_parse_charstrings uses 16.16 coordinates */
2255         point->x = x >> 10;
2256         point->y = y >> 10;
2257       }
2258       *control = (FT_Byte)( flag ? FT_CURVE_TAG_ON : FT_CURVE_TAG_CUBIC );
2259     }
2260     outline->n_points++;
2261   }
2262 
2263 
2264   /* check space for a new on-curve point, then add it */
2265   FT_LOCAL_DEF( FT_Error )
ps_builder_add_point1(PS_Builder * builder,FT_Pos x,FT_Pos y)2266   ps_builder_add_point1( PS_Builder*  builder,
2267                          FT_Pos       x,
2268                          FT_Pos       y )
2269   {
2270     FT_Error  error;
2271 
2272 
2273     error = ps_builder_check_points( builder, 1 );
2274     if ( !error )
2275       ps_builder_add_point( builder, x, y, 1 );
2276 
2277     return error;
2278   }
2279 
2280 
2281   /* check space for a new contour, then add it */
2282   FT_LOCAL_DEF( FT_Error )
ps_builder_add_contour(PS_Builder * builder)2283   ps_builder_add_contour( PS_Builder*  builder )
2284   {
2285     FT_Outline*  outline = builder->current;
2286     FT_Error     error;
2287 
2288 
2289     /* this might happen in invalid fonts */
2290     if ( !outline )
2291     {
2292       FT_ERROR(( "ps_builder_add_contour: no outline to add points to\n" ));
2293       return FT_THROW( Invalid_File_Format );
2294     }
2295 
2296     if ( !builder->load_points )
2297     {
2298       outline->n_contours++;
2299       return FT_Err_Ok;
2300     }
2301 
2302     error = FT_GLYPHLOADER_CHECK_POINTS( builder->loader, 0, 1 );
2303     if ( !error )
2304     {
2305       if ( outline->n_contours > 0 )
2306         outline->contours[outline->n_contours - 1] =
2307           (short)( outline->n_points - 1 );
2308 
2309       outline->n_contours++;
2310     }
2311 
2312     return error;
2313   }
2314 
2315 
2316   /* if a path was begun, add its first on-curve point */
2317   FT_LOCAL_DEF( FT_Error )
ps_builder_start_point(PS_Builder * builder,FT_Pos x,FT_Pos y)2318   ps_builder_start_point( PS_Builder*  builder,
2319                           FT_Pos       x,
2320                           FT_Pos       y )
2321   {
2322     FT_Error  error = FT_Err_Ok;
2323 
2324 
2325     /* test whether we are building a new contour */
2326     if ( !builder->path_begun )
2327     {
2328       builder->path_begun = 1;
2329       error = ps_builder_add_contour( builder );
2330       if ( !error )
2331         error = ps_builder_add_point1( builder, x, y );
2332     }
2333 
2334     return error;
2335   }
2336 
2337 
2338   /* close the current contour */
2339   FT_LOCAL_DEF( void )
ps_builder_close_contour(PS_Builder * builder)2340   ps_builder_close_contour( PS_Builder*  builder )
2341   {
2342     FT_Outline*  outline = builder->current;
2343     FT_Int       first;
2344 
2345 
2346     if ( !outline )
2347       return;
2348 
2349     first = outline->n_contours <= 1
2350             ? 0 : outline->contours[outline->n_contours - 2] + 1;
2351 
2352     /* in malformed fonts it can happen that a contour was started */
2353     /* but no points were added                                    */
2354     if ( outline->n_contours && first == outline->n_points )
2355     {
2356       outline->n_contours--;
2357       return;
2358     }
2359 
2360     /* We must not include the last point in the path if it */
2361     /* is located on the first point.                       */
2362     if ( outline->n_points > 1 )
2363     {
2364       FT_Vector*  p1      = outline->points + first;
2365       FT_Vector*  p2      = outline->points + outline->n_points - 1;
2366       FT_Byte*    control = (FT_Byte*)outline->tags + outline->n_points - 1;
2367 
2368 
2369       /* `delete' last point only if it coincides with the first */
2370       /* point and it is not a control point (which can happen). */
2371       if ( p1->x == p2->x && p1->y == p2->y )
2372         if ( *control == FT_CURVE_TAG_ON )
2373           outline->n_points--;
2374     }
2375 
2376     if ( outline->n_contours > 0 )
2377     {
2378       /* Don't add contours only consisting of one point, i.e.,  */
2379       /* check whether the first and the last point is the same. */
2380       if ( first == outline->n_points - 1 )
2381       {
2382         outline->n_contours--;
2383         outline->n_points--;
2384       }
2385       else
2386         outline->contours[outline->n_contours - 1] =
2387           (short)( outline->n_points - 1 );
2388     }
2389   }
2390 
2391 
2392   /*************************************************************************/
2393   /*************************************************************************/
2394   /*****                                                               *****/
2395   /*****                            OTHER                              *****/
2396   /*****                                                               *****/
2397   /*************************************************************************/
2398   /*************************************************************************/
2399 
2400 
2401   /**************************************************************************
2402    *
2403    * @Function:
2404    *   ps_decoder_init
2405    *
2406    * @Description:
2407    *   Creates a wrapper decoder for use in the combined
2408    *   Type 1 / CFF interpreter.
2409    *
2410    * @InOut:
2411    *   ps_decoder ::
2412    *     A pointer to the decoder to initialize.
2413    *
2414    * @Input:
2415    *   decoder ::
2416    *     A pointer to the original decoder.
2417    *
2418    *   is_t1 ::
2419    *     Flag indicating Type 1 or CFF
2420    */
2421   FT_LOCAL_DEF( void )
ps_decoder_init(PS_Decoder * ps_decoder,void * decoder,FT_Bool is_t1)2422   ps_decoder_init( PS_Decoder*  ps_decoder,
2423                    void*        decoder,
2424                    FT_Bool      is_t1 )
2425   {
2426     FT_ZERO( ps_decoder );
2427 
2428     if ( is_t1 )
2429     {
2430       T1_Decoder  t1_decoder = (T1_Decoder)decoder;
2431 
2432 
2433       ps_builder_init( &ps_decoder->builder,
2434                        &t1_decoder->builder,
2435                        is_t1 );
2436 
2437       ps_decoder->cf2_instance = &t1_decoder->cf2_instance;
2438       ps_decoder->psnames      = t1_decoder->psnames;
2439 
2440       ps_decoder->num_glyphs  = t1_decoder->num_glyphs;
2441       ps_decoder->glyph_names = t1_decoder->glyph_names;
2442       ps_decoder->hint_mode   = t1_decoder->hint_mode;
2443       ps_decoder->blend       = t1_decoder->blend;
2444 
2445       ps_decoder->num_locals  = (FT_UInt)t1_decoder->num_subrs;
2446       ps_decoder->locals      = t1_decoder->subrs;
2447       ps_decoder->locals_len  = t1_decoder->subrs_len;
2448       ps_decoder->locals_hash = t1_decoder->subrs_hash;
2449 
2450       ps_decoder->buildchar     = t1_decoder->buildchar;
2451       ps_decoder->len_buildchar = t1_decoder->len_buildchar;
2452 
2453       ps_decoder->lenIV = t1_decoder->lenIV;
2454     }
2455     else
2456     {
2457       CFF_Decoder*  cff_decoder = (CFF_Decoder*)decoder;
2458 
2459 
2460       ps_builder_init( &ps_decoder->builder,
2461                        &cff_decoder->builder,
2462                        is_t1 );
2463 
2464       ps_decoder->cff             = cff_decoder->cff;
2465       ps_decoder->cf2_instance    = &cff_decoder->cff->cf2_instance;
2466       ps_decoder->current_subfont = cff_decoder->current_subfont;
2467 
2468       ps_decoder->num_globals  = cff_decoder->num_globals;
2469       ps_decoder->globals      = cff_decoder->globals;
2470       ps_decoder->globals_bias = cff_decoder->globals_bias;
2471       ps_decoder->num_locals   = cff_decoder->num_locals;
2472       ps_decoder->locals       = cff_decoder->locals;
2473       ps_decoder->locals_bias  = cff_decoder->locals_bias;
2474 
2475       ps_decoder->glyph_width   = &cff_decoder->glyph_width;
2476       ps_decoder->width_only    = cff_decoder->width_only;
2477 
2478       ps_decoder->hint_mode = cff_decoder->hint_mode;
2479 
2480       ps_decoder->get_glyph_callback  = cff_decoder->get_glyph_callback;
2481       ps_decoder->free_glyph_callback = cff_decoder->free_glyph_callback;
2482     }
2483   }
2484 
2485 
2486   /* Synthesize a SubFont object for Type 1 fonts, for use in the  */
2487   /* new interpreter to access Private dict data.                  */
2488   FT_LOCAL_DEF( void )
t1_make_subfont(FT_Face face,PS_Private priv,CFF_SubFont subfont)2489   t1_make_subfont( FT_Face      face,
2490                    PS_Private   priv,
2491                    CFF_SubFont  subfont )
2492   {
2493     CFF_Private  cpriv = &subfont->private_dict;
2494     FT_UInt      n, count;
2495 
2496 
2497     FT_ZERO( subfont );
2498     FT_ZERO( cpriv );
2499 
2500     count = cpriv->num_blue_values = priv->num_blue_values;
2501     for ( n = 0; n < count; n++ )
2502       cpriv->blue_values[n] = (FT_Pos)priv->blue_values[n];
2503 
2504     count = cpriv->num_other_blues = priv->num_other_blues;
2505     for ( n = 0; n < count; n++ )
2506       cpriv->other_blues[n] = (FT_Pos)priv->other_blues[n];
2507 
2508     count = cpriv->num_family_blues = priv->num_family_blues;
2509     for ( n = 0; n < count; n++ )
2510       cpriv->family_blues[n] = (FT_Pos)priv->family_blues[n];
2511 
2512     count = cpriv->num_family_other_blues = priv->num_family_other_blues;
2513     for ( n = 0; n < count; n++ )
2514       cpriv->family_other_blues[n] = (FT_Pos)priv->family_other_blues[n];
2515 
2516     cpriv->blue_scale = priv->blue_scale;
2517     cpriv->blue_shift = (FT_Pos)priv->blue_shift;
2518     cpriv->blue_fuzz  = (FT_Pos)priv->blue_fuzz;
2519 
2520     cpriv->standard_width  = (FT_Pos)priv->standard_width[0];
2521     cpriv->standard_height = (FT_Pos)priv->standard_height[0];
2522 
2523     count = cpriv->num_snap_widths = priv->num_snap_widths;
2524     for ( n = 0; n < count; n++ )
2525       cpriv->snap_widths[n] = (FT_Pos)priv->snap_widths[n];
2526 
2527     count = cpriv->num_snap_heights = priv->num_snap_heights;
2528     for ( n = 0; n < count; n++ )
2529       cpriv->snap_heights[n] = (FT_Pos)priv->snap_heights[n];
2530 
2531     cpriv->force_bold       = priv->force_bold;
2532     cpriv->lenIV            = priv->lenIV;
2533     cpriv->language_group   = priv->language_group;
2534     cpriv->expansion_factor = priv->expansion_factor;
2535 
2536     cpriv->subfont = subfont;
2537 
2538 
2539     /* Initialize the random number generator. */
2540     if ( face->internal->random_seed != -1 )
2541     {
2542       /* If we have a face-specific seed, use it.    */
2543       /* If non-zero, update it to a positive value. */
2544       subfont->random = (FT_UInt32)face->internal->random_seed;
2545       if ( face->internal->random_seed )
2546       {
2547         do
2548         {
2549           face->internal->random_seed = (FT_Int32)cff_random(
2550             (FT_UInt32)face->internal->random_seed );
2551 
2552         } while ( face->internal->random_seed < 0 );
2553       }
2554     }
2555     if ( !subfont->random )
2556     {
2557       FT_UInt32  seed;
2558 
2559 
2560       /* compute random seed from some memory addresses */
2561       seed = (FT_UInt32)( (FT_Offset)(char*)&seed    ^
2562                           (FT_Offset)(char*)&face    ^
2563                           (FT_Offset)(char*)&subfont );
2564       seed = seed ^ ( seed >> 10 ) ^ ( seed >> 20 );
2565       if ( seed == 0 )
2566         seed = 0x7384;
2567 
2568       subfont->random = seed;
2569     }
2570   }
2571 
2572 
2573   FT_LOCAL_DEF( void )
t1_decrypt(FT_Byte * buffer,FT_Offset length,FT_UShort seed)2574   t1_decrypt( FT_Byte*   buffer,
2575               FT_Offset  length,
2576               FT_UShort  seed )
2577   {
2578     PS_Conv_EexecDecode( &buffer,
2579                          FT_OFFSET( buffer, length ),
2580                          buffer,
2581                          length,
2582                          &seed );
2583   }
2584 
2585 
2586   FT_LOCAL_DEF( FT_UInt32 )
cff_random(FT_UInt32 r)2587   cff_random( FT_UInt32  r )
2588   {
2589     /* a 32bit version of the `xorshift' algorithm */
2590     r ^= r << 13;
2591     r ^= r >> 17;
2592     r ^= r << 5;
2593 
2594     return r;
2595   }
2596 
2597 
2598 /* END */
2599