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