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