sdk-world v2026.11.05
PS2 SDK - world tier (copyleft-allowed, non-essential packages)
Loading...
Searching...
No Matches
cffdecode.c
1/****************************************************************************
2 *
3 * cffdecode.c
4 *
5 * PostScript CFF (Type 2) decoding routines (body).
6 *
7 * Copyright (C) 2017-2025 by
8 * David Turner, Robert Wilhelm, and Werner Lemberg.
9 *
10 * This file is part of the FreeType project, and may only be used,
11 * modified, and distributed under the terms of the FreeType project
12 * license, LICENSE.TXT. By continuing to use, modify, or distribute
13 * this file you indicate that you have read the license and
14 * understand and accept it fully.
15 *
16 */
17
18
19#include <freetype/freetype.h>
24
25#include "cffdecode.h"
26#include "psobjs.h"
27
28#include "psauxerr.h"
29
30
31 /**************************************************************************
32 *
33 * The macro FT_COMPONENT is used in trace mode. It is an implicit
34 * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
35 * messages during execution.
36 */
37#undef FT_COMPONENT
38#define FT_COMPONENT cffdecode
39
40
41#ifdef CFF_CONFIG_OPTION_OLD_ENGINE
42
43 typedef enum CFF_Operator_
44 {
45 cff_op_unknown = 0,
46
47 cff_op_rmoveto,
48 cff_op_hmoveto,
49 cff_op_vmoveto,
50
51 cff_op_rlineto,
52 cff_op_hlineto,
53 cff_op_vlineto,
54
55 cff_op_rrcurveto,
56 cff_op_hhcurveto,
57 cff_op_hvcurveto,
58 cff_op_rcurveline,
59 cff_op_rlinecurve,
60 cff_op_vhcurveto,
61 cff_op_vvcurveto,
62
63 cff_op_flex,
64 cff_op_hflex,
65 cff_op_hflex1,
66 cff_op_flex1,
67
68 cff_op_endchar,
69
70 cff_op_hstem,
71 cff_op_vstem,
72 cff_op_hstemhm,
73 cff_op_vstemhm,
74
75 cff_op_hintmask,
76 cff_op_cntrmask,
77 cff_op_dotsection, /* deprecated, acts as no-op */
78
79 cff_op_abs,
80 cff_op_add,
81 cff_op_sub,
82 cff_op_div,
83 cff_op_neg,
84 cff_op_random,
85 cff_op_mul,
86 cff_op_sqrt,
87
88 cff_op_blend,
89
90 cff_op_drop,
91 cff_op_exch,
92 cff_op_index,
93 cff_op_roll,
94 cff_op_dup,
95
96 cff_op_put,
97 cff_op_get,
98 cff_op_store,
99 cff_op_load,
100
101 cff_op_and,
102 cff_op_or,
103 cff_op_not,
104 cff_op_eq,
105 cff_op_ifelse,
106
107 cff_op_callsubr,
108 cff_op_callgsubr,
109 cff_op_return,
110
111 /* Type 1 opcodes: invalid but seen in real life */
112 cff_op_hsbw,
113 cff_op_closepath,
114 cff_op_callothersubr,
115 cff_op_pop,
116 cff_op_seac,
117 cff_op_sbw,
118 cff_op_setcurrentpoint,
119
120 /* do not remove */
121 cff_op_max
122
123 } CFF_Operator;
124
125
126#define CFF_COUNT_CHECK_WIDTH 0x80
127#define CFF_COUNT_EXACT 0x40
128#define CFF_COUNT_CLEAR_STACK 0x20
129
130 /* count values which have the `CFF_COUNT_CHECK_WIDTH' flag set are */
131 /* used for checking the width and requested numbers of arguments */
132 /* only; they are set to zero afterwards */
133
134 /* the other two flags are informative only and unused currently */
135
136 static const FT_Byte cff_argument_counts[] =
137 {
138 0, /* unknown */
139
140 2 | CFF_COUNT_CHECK_WIDTH | CFF_COUNT_EXACT, /* rmoveto */
141 1 | CFF_COUNT_CHECK_WIDTH | CFF_COUNT_EXACT,
142 1 | CFF_COUNT_CHECK_WIDTH | CFF_COUNT_EXACT,
143
144 0 | CFF_COUNT_CLEAR_STACK, /* rlineto */
145 0 | CFF_COUNT_CLEAR_STACK,
146 0 | CFF_COUNT_CLEAR_STACK,
147
148 0 | CFF_COUNT_CLEAR_STACK, /* rrcurveto */
149 0 | CFF_COUNT_CLEAR_STACK,
150 0 | CFF_COUNT_CLEAR_STACK,
151 0 | CFF_COUNT_CLEAR_STACK,
152 0 | CFF_COUNT_CLEAR_STACK,
153 0 | CFF_COUNT_CLEAR_STACK,
154 0 | CFF_COUNT_CLEAR_STACK,
155
156 13, /* flex */
157 7,
158 9,
159 11,
160
161 0 | CFF_COUNT_CHECK_WIDTH, /* endchar */
162
163 2 | CFF_COUNT_CHECK_WIDTH, /* hstem */
164 2 | CFF_COUNT_CHECK_WIDTH,
165 2 | CFF_COUNT_CHECK_WIDTH,
166 2 | CFF_COUNT_CHECK_WIDTH,
167
168 0 | CFF_COUNT_CHECK_WIDTH, /* hintmask */
169 0 | CFF_COUNT_CHECK_WIDTH, /* cntrmask */
170 0, /* dotsection */
171
172 1, /* abs */
173 2,
174 2,
175 2,
176 1,
177 0,
178 2,
179 1,
180
181 1, /* blend */
182
183 1, /* drop */
184 2,
185 1,
186 2,
187 1,
188
189 2, /* put */
190 1,
191 4,
192 3,
193
194 2, /* and */
195 2,
196 1,
197 2,
198 4,
199
200 1, /* callsubr */
201 1,
202 0,
203
204 2, /* hsbw */
205 0,
206 0,
207 0,
208 5, /* seac */
209 4, /* sbw */
210 2 /* setcurrentpoint */
211 };
212
213
214 static FT_Error
215 cff_operator_seac( CFF_Decoder* decoder,
216 FT_Pos asb,
217 FT_Pos adx,
218 FT_Pos ady,
219 FT_Int bchar,
220 FT_Int achar )
221 {
222 FT_Error error;
223 CFF_Builder* builder = &decoder->builder;
224 FT_Int bchar_index, achar_index;
225 TT_Face face = decoder->builder.face;
226 FT_Vector left_bearing, advance;
227 FT_Byte* charstring;
228 FT_ULong charstring_len;
229 FT_Pos glyph_width;
230
231
232 if ( decoder->seac )
233 {
234 FT_ERROR(( "cff_operator_seac: invalid nested seac\n" ));
235 return FT_THROW( Syntax_Error );
236 }
237
238 adx = ADD_LONG( adx, decoder->builder.left_bearing.x );
239 ady = ADD_LONG( ady, decoder->builder.left_bearing.y );
240
241#ifdef FT_CONFIG_OPTION_INCREMENTAL
242 /* Incremental fonts don't necessarily have valid charsets. */
243 /* They use the character code, not the glyph index, in this case. */
244 if ( face->root.internal->incremental_interface )
245 {
246 bchar_index = bchar;
247 achar_index = achar;
248 }
249 else
250#endif /* FT_CONFIG_OPTION_INCREMENTAL */
251 {
252 CFF_Font cff = (CFF_Font)( face->extra.data );
253
254
255 bchar_index = cff_lookup_glyph_by_stdcharcode( cff, bchar );
256 achar_index = cff_lookup_glyph_by_stdcharcode( cff, achar );
257 }
258
259 if ( bchar_index < 0 || achar_index < 0 )
260 {
261 FT_ERROR(( "cff_operator_seac:"
262 " invalid seac character code arguments\n" ));
263 return FT_THROW( Syntax_Error );
264 }
265
266 /* If we are trying to load a composite glyph, do not load the */
267 /* accent character and return the array of subglyphs. */
268 if ( builder->no_recurse )
269 {
270 FT_GlyphSlot glyph = (FT_GlyphSlot)builder->glyph;
271 FT_GlyphLoader loader = glyph->internal->loader;
272 FT_SubGlyph subg;
273
274
275 /* reallocate subglyph array if necessary */
276 error = FT_GlyphLoader_CheckSubGlyphs( loader, 2 );
277 if ( error )
278 goto Exit;
279
280 subg = loader->current.subglyphs;
281
282 /* subglyph 0 = base character */
283 subg->index = bchar_index;
284 subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES |
285 FT_SUBGLYPH_FLAG_USE_MY_METRICS;
286 subg->arg1 = 0;
287 subg->arg2 = 0;
288 subg++;
289
290 /* subglyph 1 = accent character */
291 subg->index = achar_index;
292 subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES;
293 subg->arg1 = (FT_Int)( adx >> 16 );
294 subg->arg2 = (FT_Int)( ady >> 16 );
295
296 /* set up remaining glyph fields */
297 glyph->num_subglyphs = 2;
298 glyph->subglyphs = loader->base.subglyphs;
299 glyph->format = FT_GLYPH_FORMAT_COMPOSITE;
300
301 loader->current.num_subglyphs = 2;
302 }
303
304 FT_GlyphLoader_Prepare( builder->loader );
305
306 /* First load `bchar' in builder */
307 error = decoder->get_glyph_callback( face, (FT_UInt)bchar_index,
308 &charstring, &charstring_len );
309 if ( !error )
310 {
311 /* the seac operator must not be nested */
312 decoder->seac = TRUE;
313 error = cff_decoder_parse_charstrings( decoder, charstring,
314 charstring_len, 0 );
315 decoder->seac = FALSE;
316
317 decoder->free_glyph_callback( face, &charstring, charstring_len );
318
319 if ( error )
320 goto Exit;
321 }
322
323 /* Save the left bearing, advance and glyph width of the base */
324 /* character as they will be erased by the next load. */
325
326 left_bearing = builder->left_bearing;
327 advance = builder->advance;
328 glyph_width = decoder->glyph_width;
329
330 builder->left_bearing.x = 0;
331 builder->left_bearing.y = 0;
332
333 builder->pos_x = SUB_LONG( adx, asb );
334 builder->pos_y = ady;
335
336 /* Now load `achar' on top of the base outline. */
337 error = decoder->get_glyph_callback( face, (FT_UInt)achar_index,
338 &charstring, &charstring_len );
339 if ( !error )
340 {
341 /* the seac operator must not be nested */
342 decoder->seac = TRUE;
343 error = cff_decoder_parse_charstrings( decoder, charstring,
344 charstring_len, 0 );
345 decoder->seac = FALSE;
346
347 decoder->free_glyph_callback( face, &charstring, charstring_len );
348
349 if ( error )
350 goto Exit;
351 }
352
353 /* Restore the left side bearing, advance and glyph width */
354 /* of the base character. */
355 builder->left_bearing = left_bearing;
356 builder->advance = advance;
357 decoder->glyph_width = glyph_width;
358
359 builder->pos_x = 0;
360 builder->pos_y = 0;
361
362 Exit:
363 return error;
364 }
365
366#endif /* CFF_CONFIG_OPTION_OLD_ENGINE */
367
368
369 /*************************************************************************/
370 /*************************************************************************/
371 /*************************************************************************/
372 /********** *********/
373 /********** *********/
374 /********** GENERIC CHARSTRING PARSING *********/
375 /********** *********/
376 /********** *********/
377 /*************************************************************************/
378 /*************************************************************************/
379 /*************************************************************************/
380
381 /**************************************************************************
382 *
383 * @Function:
384 * cff_compute_bias
385 *
386 * @Description:
387 * Computes the bias value in dependence of the number of glyph
388 * subroutines.
389 *
390 * @Input:
391 * in_charstring_type ::
392 * The `CharstringType' value of the top DICT
393 * dictionary.
394 *
395 * num_subrs ::
396 * The number of glyph subroutines.
397 *
398 * @Return:
399 * The bias value.
400 */
401 static FT_Int
402 cff_compute_bias( FT_Int in_charstring_type,
403 FT_UInt num_subrs )
404 {
405 FT_Int result;
406
407
408 if ( in_charstring_type == 1 )
409 result = 0;
410 else if ( num_subrs < 1240 )
411 result = 107;
412 else if ( num_subrs < 33900U )
413 result = 1131;
414 else
415 result = 32768U;
416
417 return result;
418 }
419
420
421 FT_LOCAL_DEF( FT_Int )
422 cff_lookup_glyph_by_stdcharcode( CFF_Font cff,
423 FT_Int charcode )
424 {
425 FT_UInt n;
426 FT_UShort glyph_sid;
427
428 FT_Service_CFFLoad cffload;
429
430
431 /* CID-keyed fonts don't have glyph names */
432 if ( !cff->charset.sids )
433 return -1;
434
435 /* check range of standard char code */
436 if ( charcode < 0 || charcode > 255 )
437 return -1;
438
439#if 0
440 /* retrieve cffload from list of current modules */
441 FT_Service_CFFLoad cffload;
442
443
444 FT_FACE_FIND_GLOBAL_SERVICE( face, cffload, CFF_LOAD );
445 if ( !cffload )
446 {
447 FT_ERROR(( "cff_lookup_glyph_by_stdcharcode:"
448 " the `cffload' module is not available\n" ));
449 return FT_THROW( Unimplemented_Feature );
450 }
451#endif
452
453 cffload = (FT_Service_CFFLoad)cff->cffload;
454
455 /* Get code to SID mapping from `cff_standard_encoding'. */
456 glyph_sid = cffload->get_standard_encoding( (FT_UInt)charcode );
457
458 for ( n = 0; n < cff->num_glyphs; n++ )
459 {
460 if ( cff->charset.sids[n] == glyph_sid )
461 return (FT_Int)n;
462 }
463
464 return -1;
465 }
466
467
468#ifdef CFF_CONFIG_OPTION_OLD_ENGINE
469
470 /**************************************************************************
471 *
472 * @Function:
473 * cff_decoder_parse_charstrings
474 *
475 * @Description:
476 * Parses a given Type 2 charstrings program.
477 *
478 * @InOut:
479 * decoder ::
480 * The current Type 1 decoder.
481 *
482 * @Input:
483 * charstring_base ::
484 * The base of the charstring stream.
485 *
486 * charstring_len ::
487 * The length in bytes of the charstring stream.
488 *
489 * in_dict ::
490 * Set to 1 if function is called from top or
491 * private DICT (needed for Multiple Master CFFs).
492 *
493 * @Return:
494 * FreeType error code. 0 means success.
495 */
496 FT_LOCAL_DEF( FT_Error )
497 cff_decoder_parse_charstrings( CFF_Decoder* decoder,
498 FT_Byte* charstring_base,
499 FT_ULong charstring_len,
500 FT_Bool in_dict )
501 {
502 FT_Error error;
503 CFF_Decoder_Zone* zone;
504 FT_Byte* ip;
505 FT_Byte* limit;
506 CFF_Builder* builder = &decoder->builder;
507 FT_Pos x, y;
508 FT_Fixed* stack;
509 FT_Int charstring_type =
510 decoder->cff->top_font.font_dict.charstring_type;
511 FT_UShort num_designs =
512 decoder->cff->top_font.font_dict.num_designs;
513 FT_UShort num_axes =
514 decoder->cff->top_font.font_dict.num_axes;
515
516 T2_Hints_Funcs hinter;
517
518
519 /* set default width */
520 decoder->num_hints = 0;
521 decoder->read_width = 1;
522
523 /* initialize the decoder */
524 decoder->top = decoder->stack;
525 decoder->zone = decoder->zones;
526 zone = decoder->zones;
527 stack = decoder->top;
528
529 hinter = (T2_Hints_Funcs)builder->hints_funcs;
530
531 builder->path_begun = 0;
532
533 if ( !charstring_base )
534 return FT_Err_Ok;
535
536 zone->base = charstring_base;
537 limit = zone->limit = charstring_base + charstring_len;
538 ip = zone->cursor = zone->base;
539
540 error = FT_Err_Ok;
541
542 x = builder->pos_x;
543 y = builder->pos_y;
544
545 /* begin hints recording session, if any */
546 if ( hinter )
547 hinter->open( hinter->hints );
548
549 /* now execute loop */
550 while ( ip < limit )
551 {
552 CFF_Operator op;
553 FT_Byte v;
554
555
556 /*********************************************************************
557 *
558 * Decode operator or operand
559 */
560 v = *ip++;
561 if ( v >= 32 || v == 28 )
562 {
563 FT_Int shift = 16;
564 FT_Int32 val;
565
566
567 /* this is an operand, push it on the stack */
568
569 /* if we use shifts, all computations are done with unsigned */
570 /* values; the conversion to a signed value is the last step */
571 if ( v == 28 )
572 {
573 if ( ip + 1 >= limit )
574 goto Syntax_Error;
575 val = (FT_Short)( ( (FT_UShort)ip[0] << 8 ) | ip[1] );
576 ip += 2;
577 }
578 else if ( v < 247 )
579 val = (FT_Int32)v - 139;
580 else if ( v < 251 )
581 {
582 if ( ip >= limit )
583 goto Syntax_Error;
584 val = ( (FT_Int32)v - 247 ) * 256 + *ip++ + 108;
585 }
586 else if ( v < 255 )
587 {
588 if ( ip >= limit )
589 goto Syntax_Error;
590 val = -( (FT_Int32)v - 251 ) * 256 - *ip++ - 108;
591 }
592 else
593 {
594 if ( ip + 3 >= limit )
595 goto Syntax_Error;
596 val = (FT_Int32)( ( (FT_UInt32)ip[0] << 24 ) |
597 ( (FT_UInt32)ip[1] << 16 ) |
598 ( (FT_UInt32)ip[2] << 8 ) |
599 (FT_UInt32)ip[3] );
600 ip += 4;
601 if ( charstring_type == 2 )
602 shift = 0;
603 }
604 if ( decoder->top - stack >= CFF_MAX_OPERANDS )
605 goto Stack_Overflow;
606
607 val = (FT_Int32)( (FT_UInt32)val << shift );
608 *decoder->top++ = val;
609
610#ifdef FT_DEBUG_LEVEL_TRACE
611 if ( !( val & 0xFFFFL ) )
612 FT_TRACE4(( " %hd", (FT_Short)( (FT_UInt32)val >> 16 ) ));
613 else
614 FT_TRACE4(( " %.5f", val / 65536.0 ));
615#endif
616
617 }
618 else
619 {
620 /* The specification says that normally arguments are to be taken */
621 /* from the bottom of the stack. However, this seems not to be */
622 /* correct, at least for Acroread 7.0.8 on GNU/Linux: It pops the */
623 /* arguments similar to a PS interpreter. */
624
625 FT_Fixed* args = decoder->top;
626 FT_Int num_args = (FT_Int)( args - decoder->stack );
627 FT_Int req_args;
628
629
630 /* find operator */
631 op = cff_op_unknown;
632
633 switch ( v )
634 {
635 case 1:
636 op = cff_op_hstem;
637 break;
638 case 3:
639 op = cff_op_vstem;
640 break;
641 case 4:
642 op = cff_op_vmoveto;
643 break;
644 case 5:
645 op = cff_op_rlineto;
646 break;
647 case 6:
648 op = cff_op_hlineto;
649 break;
650 case 7:
651 op = cff_op_vlineto;
652 break;
653 case 8:
654 op = cff_op_rrcurveto;
655 break;
656 case 9:
657 op = cff_op_closepath;
658 break;
659 case 10:
660 op = cff_op_callsubr;
661 break;
662 case 11:
663 op = cff_op_return;
664 break;
665 case 12:
666 if ( ip >= limit )
667 goto Syntax_Error;
668 v = *ip++;
669
670 switch ( v )
671 {
672 case 0:
673 op = cff_op_dotsection;
674 break;
675 case 1: /* this is actually the Type1 vstem3 operator */
676 op = cff_op_vstem;
677 break;
678 case 2: /* this is actually the Type1 hstem3 operator */
679 op = cff_op_hstem;
680 break;
681 case 3:
682 op = cff_op_and;
683 break;
684 case 4:
685 op = cff_op_or;
686 break;
687 case 5:
688 op = cff_op_not;
689 break;
690 case 6:
691 op = cff_op_seac;
692 break;
693 case 7:
694 op = cff_op_sbw;
695 break;
696 case 8:
697 op = cff_op_store;
698 break;
699 case 9:
700 op = cff_op_abs;
701 break;
702 case 10:
703 op = cff_op_add;
704 break;
705 case 11:
706 op = cff_op_sub;
707 break;
708 case 12:
709 op = cff_op_div;
710 break;
711 case 13:
712 op = cff_op_load;
713 break;
714 case 14:
715 op = cff_op_neg;
716 break;
717 case 15:
718 op = cff_op_eq;
719 break;
720 case 16:
721 op = cff_op_callothersubr;
722 break;
723 case 17:
724 op = cff_op_pop;
725 break;
726 case 18:
727 op = cff_op_drop;
728 break;
729 case 20:
730 op = cff_op_put;
731 break;
732 case 21:
733 op = cff_op_get;
734 break;
735 case 22:
736 op = cff_op_ifelse;
737 break;
738 case 23:
739 op = cff_op_random;
740 break;
741 case 24:
742 op = cff_op_mul;
743 break;
744 case 26:
745 op = cff_op_sqrt;
746 break;
747 case 27:
748 op = cff_op_dup;
749 break;
750 case 28:
751 op = cff_op_exch;
752 break;
753 case 29:
754 op = cff_op_index;
755 break;
756 case 30:
757 op = cff_op_roll;
758 break;
759 case 33:
760 op = cff_op_setcurrentpoint;
761 break;
762 case 34:
763 op = cff_op_hflex;
764 break;
765 case 35:
766 op = cff_op_flex;
767 break;
768 case 36:
769 op = cff_op_hflex1;
770 break;
771 case 37:
772 op = cff_op_flex1;
773 break;
774 default:
775 FT_TRACE4(( " unknown op (12, %d)\n", v ));
776 break;
777 }
778 break;
779 case 13:
780 op = cff_op_hsbw;
781 break;
782 case 14:
783 op = cff_op_endchar;
784 break;
785 case 16:
786 op = cff_op_blend;
787 break;
788 case 18:
789 op = cff_op_hstemhm;
790 break;
791 case 19:
792 op = cff_op_hintmask;
793 break;
794 case 20:
795 op = cff_op_cntrmask;
796 break;
797 case 21:
798 op = cff_op_rmoveto;
799 break;
800 case 22:
801 op = cff_op_hmoveto;
802 break;
803 case 23:
804 op = cff_op_vstemhm;
805 break;
806 case 24:
807 op = cff_op_rcurveline;
808 break;
809 case 25:
810 op = cff_op_rlinecurve;
811 break;
812 case 26:
813 op = cff_op_vvcurveto;
814 break;
815 case 27:
816 op = cff_op_hhcurveto;
817 break;
818 case 29:
819 op = cff_op_callgsubr;
820 break;
821 case 30:
822 op = cff_op_vhcurveto;
823 break;
824 case 31:
825 op = cff_op_hvcurveto;
826 break;
827 default:
828 FT_TRACE4(( " unknown op (%d)\n", v ));
829 break;
830 }
831
832 if ( op == cff_op_unknown )
833 continue;
834
835 /* in Multiple Master CFFs, T2 charstrings can appear in */
836 /* dictionaries, but some operators are prohibited */
837 if ( in_dict )
838 {
839 switch ( op )
840 {
841 case cff_op_hstem:
842 case cff_op_vstem:
843 case cff_op_vmoveto:
844 case cff_op_rlineto:
845 case cff_op_hlineto:
846 case cff_op_vlineto:
847 case cff_op_rrcurveto:
848 case cff_op_hstemhm:
849 case cff_op_hintmask:
850 case cff_op_cntrmask:
851 case cff_op_rmoveto:
852 case cff_op_hmoveto:
853 case cff_op_vstemhm:
854 case cff_op_rcurveline:
855 case cff_op_rlinecurve:
856 case cff_op_vvcurveto:
857 case cff_op_hhcurveto:
858 case cff_op_vhcurveto:
859 case cff_op_hvcurveto:
860 case cff_op_hflex:
861 case cff_op_flex:
862 case cff_op_hflex1:
863 case cff_op_flex1:
864 case cff_op_callsubr:
865 case cff_op_callgsubr:
866 /* deprecated opcodes */
867 case cff_op_dotsection:
868 /* invalid Type 1 opcodes */
869 case cff_op_hsbw:
870 case cff_op_closepath:
871 case cff_op_callothersubr:
872 case cff_op_seac:
873 case cff_op_sbw:
874 case cff_op_setcurrentpoint:
875 goto MM_Error;
876
877 default:
878 break;
879 }
880 }
881
882 /* check arguments */
883 req_args = cff_argument_counts[op];
884 if ( req_args & CFF_COUNT_CHECK_WIDTH )
885 {
886 if ( num_args > 0 && decoder->read_width )
887 {
888 /* If `nominal_width' is non-zero, the number is really a */
889 /* difference against `nominal_width'. Else, the number here */
890 /* is truly a width, not a difference against `nominal_width'. */
891 /* If the font does not set `nominal_width', then */
892 /* `nominal_width' defaults to zero, and so we can set */
893 /* `glyph_width' to `nominal_width' plus number on the stack */
894 /* -- for either case. */
895
896 FT_Int set_width_ok;
897
898
899 switch ( op )
900 {
901 case cff_op_hmoveto:
902 case cff_op_vmoveto:
903 set_width_ok = num_args & 2;
904 break;
905
906 case cff_op_hstem:
907 case cff_op_vstem:
908 case cff_op_hstemhm:
909 case cff_op_vstemhm:
910 case cff_op_rmoveto:
911 case cff_op_hintmask:
912 case cff_op_cntrmask:
913 set_width_ok = num_args & 1;
914 break;
915
916 case cff_op_endchar:
917 /* If there is a width specified for endchar, we either have */
918 /* 1 argument or 5 arguments. We like to argue. */
919 set_width_ok = in_dict
920 ? 0
921 : ( ( num_args == 5 ) || ( num_args == 1 ) );
922 break;
923
924 default:
925 set_width_ok = 0;
926 break;
927 }
928
929 if ( set_width_ok )
930 {
931 decoder->glyph_width = decoder->nominal_width +
932 ( stack[0] >> 16 );
933
934 if ( decoder->width_only )
935 {
936 /* we only want the advance width; stop here */
937 break;
938 }
939
940 /* Consumed an argument. */
941 num_args--;
942 }
943 }
944
945 decoder->read_width = 0;
946 req_args = 0;
947 }
948
949 req_args &= 0x000F;
950 if ( num_args < req_args )
951 goto Stack_Underflow;
952 args -= req_args;
953 num_args -= req_args;
954
955 /* At this point, `args' points to the first argument of the */
956 /* operand in case `req_args' isn't zero. Otherwise, we have */
957 /* to adjust `args' manually. */
958
959 /* Note that we only pop arguments from the stack which we */
960 /* really need and can digest so that we can continue in case */
961 /* of superfluous stack elements. */
962
963 switch ( op )
964 {
965 case cff_op_hstem:
966 case cff_op_vstem:
967 case cff_op_hstemhm:
968 case cff_op_vstemhm:
969 /* the number of arguments is always even here */
970 FT_TRACE4(( "%s\n",
971 op == cff_op_hstem ? " hstem" :
972 ( op == cff_op_vstem ? " vstem" :
973 ( op == cff_op_hstemhm ? " hstemhm" : " vstemhm" ) ) ));
974
975 if ( hinter )
976 hinter->stems( hinter->hints,
977 ( op == cff_op_hstem || op == cff_op_hstemhm ),
978 num_args / 2,
979 args - ( num_args & ~1 ) );
980
981 decoder->num_hints += num_args / 2;
982 args = stack;
983 break;
984
985 case cff_op_hintmask:
986 case cff_op_cntrmask:
987 FT_TRACE4(( "%s", op == cff_op_hintmask ? " hintmask"
988 : " cntrmask" ));
989
990 /* implement vstem when needed -- */
991 /* the specification doesn't say it, but this also works */
992 /* with the 'cntrmask' operator */
993 /* */
994 if ( num_args > 0 )
995 {
996 if ( hinter )
997 hinter->stems( hinter->hints,
998 0,
999 num_args / 2,
1000 args - ( num_args & ~1 ) );
1001
1002 decoder->num_hints += num_args / 2;
1003 }
1004
1005 /* In a valid charstring there must be at least one byte */
1006 /* after `hintmask' or `cntrmask' (e.g., for a `return' */
1007 /* instruction). Additionally, there must be space for */
1008 /* `num_hints' bits. */
1009
1010 if ( ( ip + ( ( decoder->num_hints + 7 ) >> 3 ) ) >= limit )
1011 goto Syntax_Error;
1012
1013 if ( hinter )
1014 {
1015 if ( op == cff_op_hintmask )
1016 hinter->hintmask( hinter->hints,
1017 (FT_UInt)builder->current->n_points,
1018 (FT_UInt)decoder->num_hints,
1019 ip );
1020 else
1021 hinter->counter( hinter->hints,
1022 (FT_UInt)decoder->num_hints,
1023 ip );
1024 }
1025
1026#ifdef FT_DEBUG_LEVEL_TRACE
1027 {
1028 FT_UInt maskbyte;
1029
1030
1031 FT_TRACE4(( " (maskbytes:" ));
1032
1033 for ( maskbyte = 0;
1034 maskbyte < (FT_UInt)( ( decoder->num_hints + 7 ) >> 3 );
1035 maskbyte++, ip++ )
1036 FT_TRACE4(( " 0x%02X", *ip ));
1037
1038 FT_TRACE4(( ")\n" ));
1039 }
1040#else
1041 ip += ( decoder->num_hints + 7 ) >> 3;
1042#endif
1043 args = stack;
1044 break;
1045
1046 case cff_op_rmoveto:
1047 FT_TRACE4(( " rmoveto\n" ));
1048
1049 cff_builder_close_contour( builder );
1050 builder->path_begun = 0;
1051 x = ADD_LONG( x, args[-2] );
1052 y = ADD_LONG( y, args[-1] );
1053 args = stack;
1054 break;
1055
1056 case cff_op_vmoveto:
1057 FT_TRACE4(( " vmoveto\n" ));
1058
1059 cff_builder_close_contour( builder );
1060 builder->path_begun = 0;
1061 y = ADD_LONG( y, args[-1] );
1062 args = stack;
1063 break;
1064
1065 case cff_op_hmoveto:
1066 FT_TRACE4(( " hmoveto\n" ));
1067
1068 cff_builder_close_contour( builder );
1069 builder->path_begun = 0;
1070 x = ADD_LONG( x, args[-1] );
1071 args = stack;
1072 break;
1073
1074 case cff_op_rlineto:
1075 FT_TRACE4(( " rlineto\n" ));
1076
1077 if ( cff_builder_start_point( builder, x, y ) ||
1078 cff_check_points( builder, num_args / 2 ) )
1079 goto Fail;
1080
1081 if ( num_args < 2 )
1082 goto Stack_Underflow;
1083
1084 args -= num_args & ~1;
1085 while ( args < decoder->top )
1086 {
1087 x = ADD_LONG( x, args[0] );
1088 y = ADD_LONG( y, args[1] );
1089 cff_builder_add_point( builder, x, y, 1 );
1090 args += 2;
1091 }
1092 args = stack;
1093 break;
1094
1095 case cff_op_hlineto:
1096 case cff_op_vlineto:
1097 {
1098 FT_Int phase = ( op == cff_op_hlineto );
1099
1100
1101 FT_TRACE4(( "%s\n", op == cff_op_hlineto ? " hlineto"
1102 : " vlineto" ));
1103
1104 if ( num_args < 0 )
1105 goto Stack_Underflow;
1106
1107 /* there exist subsetted fonts (found in PDFs) */
1108 /* which call `hlineto' without arguments */
1109 if ( num_args == 0 )
1110 break;
1111
1112 if ( cff_builder_start_point( builder, x, y ) ||
1113 cff_check_points( builder, num_args ) )
1114 goto Fail;
1115
1116 args = stack;
1117 while ( args < decoder->top )
1118 {
1119 if ( phase )
1120 x = ADD_LONG( x, args[0] );
1121 else
1122 y = ADD_LONG( y, args[0] );
1123
1124 if ( cff_builder_add_point1( builder, x, y ) )
1125 goto Fail;
1126
1127 args++;
1128 phase ^= 1;
1129 }
1130 args = stack;
1131 }
1132 break;
1133
1134 case cff_op_rrcurveto:
1135 {
1136 FT_Int nargs;
1137
1138
1139 FT_TRACE4(( " rrcurveto\n" ));
1140
1141 if ( num_args < 6 )
1142 goto Stack_Underflow;
1143
1144 nargs = num_args - num_args % 6;
1145
1146 if ( cff_builder_start_point( builder, x, y ) ||
1147 cff_check_points( builder, nargs / 2 ) )
1148 goto Fail;
1149
1150 args -= nargs;
1151 while ( args < decoder->top )
1152 {
1153 x = ADD_LONG( x, args[0] );
1154 y = ADD_LONG( y, args[1] );
1155 cff_builder_add_point( builder, x, y, 0 );
1156
1157 x = ADD_LONG( x, args[2] );
1158 y = ADD_LONG( y, args[3] );
1159 cff_builder_add_point( builder, x, y, 0 );
1160
1161 x = ADD_LONG( x, args[4] );
1162 y = ADD_LONG( y, args[5] );
1163 cff_builder_add_point( builder, x, y, 1 );
1164
1165 args += 6;
1166 }
1167 args = stack;
1168 }
1169 break;
1170
1171 case cff_op_vvcurveto:
1172 {
1173 FT_Int nargs;
1174
1175
1176 FT_TRACE4(( " vvcurveto\n" ));
1177
1178 if ( num_args < 4 )
1179 goto Stack_Underflow;
1180
1181 /* if num_args isn't of the form 4n or 4n+1, */
1182 /* we enforce it by clearing the second bit */
1183
1184 nargs = num_args & ~2;
1185
1186 if ( cff_builder_start_point( builder, x, y ) )
1187 goto Fail;
1188
1189 args -= nargs;
1190
1191 if ( nargs & 1 )
1192 {
1193 x = ADD_LONG( x, args[0] );
1194 args++;
1195 nargs--;
1196 }
1197
1198 if ( cff_check_points( builder, 3 * ( nargs / 4 ) ) )
1199 goto Fail;
1200
1201 while ( args < decoder->top )
1202 {
1203 y = ADD_LONG( y, args[0] );
1204 cff_builder_add_point( builder, x, y, 0 );
1205
1206 x = ADD_LONG( x, args[1] );
1207 y = ADD_LONG( y, args[2] );
1208 cff_builder_add_point( builder, x, y, 0 );
1209
1210 y = ADD_LONG( y, args[3] );
1211 cff_builder_add_point( builder, x, y, 1 );
1212
1213 args += 4;
1214 }
1215 args = stack;
1216 }
1217 break;
1218
1219 case cff_op_hhcurveto:
1220 {
1221 FT_Int nargs;
1222
1223
1224 FT_TRACE4(( " hhcurveto\n" ));
1225
1226 if ( num_args < 4 )
1227 goto Stack_Underflow;
1228
1229 /* if num_args isn't of the form 4n or 4n+1, */
1230 /* we enforce it by clearing the second bit */
1231
1232 nargs = num_args & ~2;
1233
1234 if ( cff_builder_start_point( builder, x, y ) )
1235 goto Fail;
1236
1237 args -= nargs;
1238 if ( nargs & 1 )
1239 {
1240 y = ADD_LONG( y, args[0] );
1241 args++;
1242 nargs--;
1243 }
1244
1245 if ( cff_check_points( builder, 3 * ( nargs / 4 ) ) )
1246 goto Fail;
1247
1248 while ( args < decoder->top )
1249 {
1250 x = ADD_LONG( x, args[0] );
1251 cff_builder_add_point( builder, x, y, 0 );
1252
1253 x = ADD_LONG( x, args[1] );
1254 y = ADD_LONG( y, args[2] );
1255 cff_builder_add_point( builder, x, y, 0 );
1256
1257 x = ADD_LONG( x, args[3] );
1258 cff_builder_add_point( builder, x, y, 1 );
1259
1260 args += 4;
1261 }
1262 args = stack;
1263 }
1264 break;
1265
1266 case cff_op_vhcurveto:
1267 case cff_op_hvcurveto:
1268 {
1269 FT_Int phase;
1270 FT_Int nargs;
1271
1272
1273 FT_TRACE4(( "%s\n", op == cff_op_vhcurveto ? " vhcurveto"
1274 : " hvcurveto" ));
1275
1276 if ( cff_builder_start_point( builder, x, y ) )
1277 goto Fail;
1278
1279 if ( num_args < 4 )
1280 goto Stack_Underflow;
1281
1282 /* if num_args isn't of the form 8n, 8n+1, 8n+4, or 8n+5, */
1283 /* we enforce it by clearing the second bit */
1284
1285 nargs = num_args & ~2;
1286
1287 args -= nargs;
1288 if ( cff_check_points( builder, ( nargs / 4 ) * 3 ) )
1289 goto Stack_Underflow;
1290
1291 phase = ( op == cff_op_hvcurveto );
1292
1293 while ( nargs >= 4 )
1294 {
1295 nargs -= 4;
1296 if ( phase )
1297 {
1298 x = ADD_LONG( x, args[0] );
1299 cff_builder_add_point( builder, x, y, 0 );
1300
1301 x = ADD_LONG( x, args[1] );
1302 y = ADD_LONG( y, args[2] );
1303 cff_builder_add_point( builder, x, y, 0 );
1304
1305 y = ADD_LONG( y, args[3] );
1306 if ( nargs == 1 )
1307 x = ADD_LONG( x, args[4] );
1308 cff_builder_add_point( builder, x, y, 1 );
1309 }
1310 else
1311 {
1312 y = ADD_LONG( y, args[0] );
1313 cff_builder_add_point( builder, x, y, 0 );
1314
1315 x = ADD_LONG( x, args[1] );
1316 y = ADD_LONG( y, args[2] );
1317 cff_builder_add_point( builder, x, y, 0 );
1318
1319 x = ADD_LONG( x, args[3] );
1320 if ( nargs == 1 )
1321 y = ADD_LONG( y, args[4] );
1322 cff_builder_add_point( builder, x, y, 1 );
1323 }
1324 args += 4;
1325 phase ^= 1;
1326 }
1327 args = stack;
1328 }
1329 break;
1330
1331 case cff_op_rlinecurve:
1332 {
1333 FT_Int num_lines;
1334 FT_Int nargs;
1335
1336
1337 FT_TRACE4(( " rlinecurve\n" ));
1338
1339 if ( num_args < 8 )
1340 goto Stack_Underflow;
1341
1342 nargs = num_args & ~1;
1343 num_lines = ( nargs - 6 ) / 2;
1344
1345 if ( cff_builder_start_point( builder, x, y ) ||
1346 cff_check_points( builder, num_lines + 3 ) )
1347 goto Fail;
1348
1349 args -= nargs;
1350
1351 /* first, add the line segments */
1352 while ( num_lines > 0 )
1353 {
1354 x = ADD_LONG( x, args[0] );
1355 y = ADD_LONG( y, args[1] );
1356 cff_builder_add_point( builder, x, y, 1 );
1357
1358 args += 2;
1359 num_lines--;
1360 }
1361
1362 /* then the curve */
1363 x = ADD_LONG( x, args[0] );
1364 y = ADD_LONG( y, args[1] );
1365 cff_builder_add_point( builder, x, y, 0 );
1366
1367 x = ADD_LONG( x, args[2] );
1368 y = ADD_LONG( y, args[3] );
1369 cff_builder_add_point( builder, x, y, 0 );
1370
1371 x = ADD_LONG( x, args[4] );
1372 y = ADD_LONG( y, args[5] );
1373 cff_builder_add_point( builder, x, y, 1 );
1374
1375 args = stack;
1376 }
1377 break;
1378
1379 case cff_op_rcurveline:
1380 {
1381 FT_Int num_curves;
1382 FT_Int nargs;
1383
1384
1385 FT_TRACE4(( " rcurveline\n" ));
1386
1387 if ( num_args < 8 )
1388 goto Stack_Underflow;
1389
1390 nargs = num_args - 2;
1391 nargs = nargs - nargs % 6 + 2;
1392 num_curves = ( nargs - 2 ) / 6;
1393
1394 if ( cff_builder_start_point( builder, x, y ) ||
1395 cff_check_points( builder, num_curves * 3 + 2 ) )
1396 goto Fail;
1397
1398 args -= nargs;
1399
1400 /* first, add the curves */
1401 while ( num_curves > 0 )
1402 {
1403 x = ADD_LONG( x, args[0] );
1404 y = ADD_LONG( y, args[1] );
1405 cff_builder_add_point( builder, x, y, 0 );
1406
1407 x = ADD_LONG( x, args[2] );
1408 y = ADD_LONG( y, args[3] );
1409 cff_builder_add_point( builder, x, y, 0 );
1410
1411 x = ADD_LONG( x, args[4] );
1412 y = ADD_LONG( y, args[5] );
1413 cff_builder_add_point( builder, x, y, 1 );
1414
1415 args += 6;
1416 num_curves--;
1417 }
1418
1419 /* then the final line */
1420 x = ADD_LONG( x, args[0] );
1421 y = ADD_LONG( y, args[1] );
1422 cff_builder_add_point( builder, x, y, 1 );
1423
1424 args = stack;
1425 }
1426 break;
1427
1428 case cff_op_hflex1:
1429 {
1430 FT_Pos start_y;
1431
1432
1433 FT_TRACE4(( " hflex1\n" ));
1434
1435 /* adding five more points: 4 control points, 1 on-curve point */
1436 /* -- make sure we have enough space for the start point if it */
1437 /* needs to be added */
1438 if ( cff_builder_start_point( builder, x, y ) ||
1439 cff_check_points( builder, 6 ) )
1440 goto Fail;
1441
1442 /* record the starting point's y position for later use */
1443 start_y = y;
1444
1445 /* first control point */
1446 x = ADD_LONG( x, args[0] );
1447 y = ADD_LONG( y, args[1] );
1448 cff_builder_add_point( builder, x, y, 0 );
1449
1450 /* second control point */
1451 x = ADD_LONG( x, args[2] );
1452 y = ADD_LONG( y, args[3] );
1453 cff_builder_add_point( builder, x, y, 0 );
1454
1455 /* join point; on curve, with y-value the same as the last */
1456 /* control point's y-value */
1457 x = ADD_LONG( x, args[4] );
1458 cff_builder_add_point( builder, x, y, 1 );
1459
1460 /* third control point, with y-value the same as the join */
1461 /* point's y-value */
1462 x = ADD_LONG( x, args[5] );
1463 cff_builder_add_point( builder, x, y, 0 );
1464
1465 /* fourth control point */
1466 x = ADD_LONG( x, args[6] );
1467 y = ADD_LONG( y, args[7] );
1468 cff_builder_add_point( builder, x, y, 0 );
1469
1470 /* ending point, with y-value the same as the start */
1471 x = ADD_LONG( x, args[8] );
1472 y = start_y;
1473 cff_builder_add_point( builder, x, y, 1 );
1474
1475 args = stack;
1476 break;
1477 }
1478
1479 case cff_op_hflex:
1480 {
1481 FT_Pos start_y;
1482
1483
1484 FT_TRACE4(( " hflex\n" ));
1485
1486 /* adding six more points; 4 control points, 2 on-curve points */
1487 if ( cff_builder_start_point( builder, x, y ) ||
1488 cff_check_points( builder, 6 ) )
1489 goto Fail;
1490
1491 /* record the starting point's y-position for later use */
1492 start_y = y;
1493
1494 /* first control point */
1495 x = ADD_LONG( x, args[0] );
1496 cff_builder_add_point( builder, x, y, 0 );
1497
1498 /* second control point */
1499 x = ADD_LONG( x, args[1] );
1500 y = ADD_LONG( y, args[2] );
1501 cff_builder_add_point( builder, x, y, 0 );
1502
1503 /* join point; on curve, with y-value the same as the last */
1504 /* control point's y-value */
1505 x = ADD_LONG( x, args[3] );
1506 cff_builder_add_point( builder, x, y, 1 );
1507
1508 /* third control point, with y-value the same as the join */
1509 /* point's y-value */
1510 x = ADD_LONG( x, args[4] );
1511 cff_builder_add_point( builder, x, y, 0 );
1512
1513 /* fourth control point */
1514 x = ADD_LONG( x, args[5] );
1515 y = start_y;
1516 cff_builder_add_point( builder, x, y, 0 );
1517
1518 /* ending point, with y-value the same as the start point's */
1519 /* y-value -- we don't add this point, though */
1520 x = ADD_LONG( x, args[6] );
1521 cff_builder_add_point( builder, x, y, 1 );
1522
1523 args = stack;
1524 break;
1525 }
1526
1527 case cff_op_flex1:
1528 {
1529 FT_Pos start_x, start_y; /* record start x, y values for */
1530 /* alter use */
1531 FT_Fixed dx = 0, dy = 0; /* used in horizontal/vertical */
1532 /* algorithm below */
1533 FT_Int horizontal, count;
1534 FT_Fixed* temp;
1535
1536
1537 FT_TRACE4(( " flex1\n" ));
1538
1539 /* adding six more points; 4 control points, 2 on-curve points */
1540 if ( cff_builder_start_point( builder, x, y ) ||
1541 cff_check_points( builder, 6 ) )
1542 goto Fail;
1543
1544 /* record the starting point's x, y position for later use */
1545 start_x = x;
1546 start_y = y;
1547
1548 /* XXX: figure out whether this is supposed to be a horizontal */
1549 /* or vertical flex; the Type 2 specification is vague... */
1550
1551 temp = args;
1552
1553 /* grab up to the last argument */
1554 for ( count = 5; count > 0; count-- )
1555 {
1556 dx = ADD_LONG( dx, temp[0] );
1557 dy = ADD_LONG( dy, temp[1] );
1558 temp += 2;
1559 }
1560
1561 if ( dx < 0 )
1562 dx = NEG_LONG( dx );
1563 if ( dy < 0 )
1564 dy = NEG_LONG( dy );
1565
1566 /* strange test, but here it is... */
1567 horizontal = ( dx > dy );
1568
1569 for ( count = 5; count > 0; count-- )
1570 {
1571 x = ADD_LONG( x, args[0] );
1572 y = ADD_LONG( y, args[1] );
1573 cff_builder_add_point( builder, x, y,
1574 FT_BOOL( count == 3 ) );
1575 args += 2;
1576 }
1577
1578 /* is last operand an x- or y-delta? */
1579 if ( horizontal )
1580 {
1581 x = ADD_LONG( x, args[0] );
1582 y = start_y;
1583 }
1584 else
1585 {
1586 x = start_x;
1587 y = ADD_LONG( y, args[0] );
1588 }
1589
1590 cff_builder_add_point( builder, x, y, 1 );
1591
1592 args = stack;
1593 break;
1594 }
1595
1596 case cff_op_flex:
1597 {
1598 FT_UInt count;
1599
1600
1601 FT_TRACE4(( " flex\n" ));
1602
1603 if ( cff_builder_start_point( builder, x, y ) ||
1604 cff_check_points( builder, 6 ) )
1605 goto Fail;
1606
1607 for ( count = 6; count > 0; count-- )
1608 {
1609 x = ADD_LONG( x, args[0] );
1610 y = ADD_LONG( y, args[1] );
1611 cff_builder_add_point( builder, x, y,
1612 FT_BOOL( count == 4 || count == 1 ) );
1613 args += 2;
1614 }
1615
1616 args = stack;
1617 }
1618 break;
1619
1620 case cff_op_seac:
1621 FT_TRACE4(( " seac\n" ));
1622
1623 error = cff_operator_seac( decoder,
1624 args[0], args[1], args[2],
1625 (FT_Int)( args[3] >> 16 ),
1626 (FT_Int)( args[4] >> 16 ) );
1627
1628 /* add current outline to the glyph slot */
1629 FT_GlyphLoader_Add( builder->loader );
1630
1631 /* return now! */
1632 FT_TRACE4(( "\n" ));
1633 return error;
1634
1635 case cff_op_endchar:
1636 /* in dictionaries, `endchar' simply indicates end of data */
1637 if ( in_dict )
1638 return error;
1639
1640 FT_TRACE4(( " endchar\n" ));
1641
1642 /* We are going to emulate the seac operator. */
1643 if ( num_args >= 4 )
1644 {
1645 /* Save glyph width so that the subglyphs don't overwrite it. */
1646 FT_Pos glyph_width = decoder->glyph_width;
1647
1648
1649 error = cff_operator_seac( decoder,
1650 0L, args[-4], args[-3],
1651 (FT_Int)( args[-2] >> 16 ),
1652 (FT_Int)( args[-1] >> 16 ) );
1653
1654 decoder->glyph_width = glyph_width;
1655 }
1656 else
1657 {
1658 cff_builder_close_contour( builder );
1659
1660 /* close hints recording session */
1661 if ( hinter )
1662 {
1663 if ( hinter->close( hinter->hints,
1664 (FT_UInt)builder->current->n_points ) )
1665 goto Syntax_Error;
1666
1667 /* apply hints to the loaded glyph outline now */
1668 error = hinter->apply( hinter->hints,
1669 builder->current,
1670 (PSH_Globals)builder->hints_globals,
1671 decoder->hint_mode );
1672 if ( error )
1673 goto Fail;
1674 }
1675
1676 /* add current outline to the glyph slot */
1677 FT_GlyphLoader_Add( builder->loader );
1678 }
1679
1680 /* return now! */
1681 FT_TRACE4(( "\n" ));
1682 return error;
1683
1684 case cff_op_abs:
1685 FT_TRACE4(( " abs\n" ));
1686
1687 if ( args[0] < 0 )
1688 {
1689 if ( args[0] == FT_LONG_MIN )
1690 args[0] = FT_LONG_MAX;
1691 else
1692 args[0] = -args[0];
1693 }
1694 args++;
1695 break;
1696
1697 case cff_op_add:
1698 FT_TRACE4(( " add\n" ));
1699
1700 args[0] = ADD_LONG( args[0], args[1] );
1701 args++;
1702 break;
1703
1704 case cff_op_sub:
1705 FT_TRACE4(( " sub\n" ));
1706
1707 args[0] = SUB_LONG( args[0], args[1] );
1708 args++;
1709 break;
1710
1711 case cff_op_div:
1712 FT_TRACE4(( " div\n" ));
1713
1714 args[0] = FT_DivFix( args[0], args[1] );
1715 args++;
1716 break;
1717
1718 case cff_op_neg:
1719 FT_TRACE4(( " neg\n" ));
1720
1721 if ( args[0] == FT_LONG_MIN )
1722 args[0] = FT_LONG_MAX;
1723 args[0] = -args[0];
1724 args++;
1725 break;
1726
1727 case cff_op_random:
1728 {
1729 FT_UInt32* randval = in_dict ? &decoder->cff->top_font.random
1730 : &decoder->current_subfont->random;
1731
1732
1733 FT_TRACE4(( " random\n" ));
1734
1735 /* only use the lower 16 bits of `random' */
1736 /* to generate a number in the range (0;1] */
1737 args[0] = (FT_Fixed)( ( *randval & 0xFFFF ) + 1 );
1738 args++;
1739
1740 *randval = cff_random( *randval );
1741 }
1742 break;
1743
1744 case cff_op_mul:
1745 FT_TRACE4(( " mul\n" ));
1746
1747 args[0] = FT_MulFix( args[0], args[1] );
1748 args++;
1749 break;
1750
1751 case cff_op_sqrt:
1752 FT_TRACE4(( " sqrt\n" ));
1753
1754 /* without upper limit the loop below might not finish */
1755 if ( args[0] > 0x7FFFFFFFL )
1756 args[0] = 0xB504F4L; /* sqrt( 32768.0044 ) */
1757 else if ( args[0] > 0 )
1758 args[0] = (FT_Fixed)FT_SqrtFixed( args[0] );
1759 else
1760 args[0] = 0;
1761 args++;
1762 break;
1763
1764 case cff_op_drop:
1765 /* nothing */
1766 FT_TRACE4(( " drop\n" ));
1767
1768 break;
1769
1770 case cff_op_exch:
1771 {
1772 FT_Fixed tmp;
1773
1774
1775 FT_TRACE4(( " exch\n" ));
1776
1777 tmp = args[0];
1778 args[0] = args[1];
1779 args[1] = tmp;
1780 args += 2;
1781 }
1782 break;
1783
1784 case cff_op_index:
1785 {
1786 FT_Int idx = (FT_Int)( args[0] >> 16 );
1787
1788
1789 FT_TRACE4(( " index\n" ));
1790
1791 if ( idx < 0 )
1792 idx = 0;
1793 else if ( idx > num_args - 2 )
1794 idx = num_args - 2;
1795 args[0] = args[-( idx + 1 )];
1796 args++;
1797 }
1798 break;
1799
1800 case cff_op_roll:
1801 {
1802 FT_Int count = (FT_Int)( args[0] >> 16 );
1803 FT_Int idx = (FT_Int)( args[1] >> 16 );
1804
1805
1806 FT_TRACE4(( " roll\n" ));
1807
1808 if ( count <= 0 )
1809 count = 1;
1810
1811 args -= count;
1812 if ( args < stack )
1813 goto Stack_Underflow;
1814
1815 if ( idx >= 0 )
1816 {
1817 idx = idx % count;
1818 while ( idx > 0 )
1819 {
1820 FT_Fixed tmp = args[count - 1];
1821 FT_Int i;
1822
1823
1824 for ( i = count - 2; i >= 0; i-- )
1825 args[i + 1] = args[i];
1826 args[0] = tmp;
1827 idx--;
1828 }
1829 }
1830 else
1831 {
1832 /* before C99 it is implementation-defined whether */
1833 /* the result of `%' is negative if the first operand */
1834 /* is negative */
1835 idx = -( NEG_INT( idx ) % count );
1836 while ( idx < 0 )
1837 {
1838 FT_Fixed tmp = args[0];
1839 FT_Int i;
1840
1841
1842 for ( i = 0; i < count - 1; i++ )
1843 args[i] = args[i + 1];
1844 args[count - 1] = tmp;
1845 idx++;
1846 }
1847 }
1848 args += count;
1849 }
1850 break;
1851
1852 case cff_op_dup:
1853 FT_TRACE4(( " dup\n" ));
1854
1855 args[1] = args[0];
1856 args += 2;
1857 break;
1858
1859 case cff_op_put:
1860 {
1861 FT_Fixed val = args[0];
1862 FT_UInt idx = (FT_UInt)( args[1] >> 16 );
1863
1864
1865 FT_TRACE4(( " put\n" ));
1866
1867 /* the Type2 specification before version 16-March-2000 */
1868 /* didn't give a hard-coded size limit of the temporary */
1869 /* storage array; instead, an argument of the */
1870 /* `MultipleMaster' operator set the size */
1871 if ( idx < CFF_MAX_TRANS_ELEMENTS )
1872 decoder->buildchar[idx] = val;
1873 }
1874 break;
1875
1876 case cff_op_get:
1877 {
1878 FT_UInt idx = (FT_UInt)( args[0] >> 16 );
1879 FT_Fixed val = 0;
1880
1881
1882 FT_TRACE4(( " get\n" ));
1883
1884 if ( idx < CFF_MAX_TRANS_ELEMENTS )
1885 val = decoder->buildchar[idx];
1886
1887 args[0] = val;
1888 args++;
1889 }
1890 break;
1891
1892 case cff_op_store:
1893 /* this operator was removed from the Type2 specification */
1894 /* in version 16-March-2000 */
1895
1896 /* since we currently don't handle interpolation of multiple */
1897 /* master fonts, this is a no-op */
1898 FT_TRACE4(( " store\n" ));
1899 break;
1900
1901 case cff_op_load:
1902 /* this operator was removed from the Type2 specification */
1903 /* in version 16-March-2000 */
1904 {
1905 FT_UInt reg_idx = (FT_UInt)args[0];
1906 FT_UInt idx = (FT_UInt)args[1];
1907 FT_UInt count = (FT_UInt)args[2];
1908
1909
1910 FT_TRACE4(( " load\n" ));
1911
1912 /* since we currently don't handle interpolation of multiple */
1913 /* master fonts, we store a vector [1 0 0 ...] in the */
1914 /* temporary storage array regardless of the Registry index */
1915 if ( reg_idx <= 2 &&
1916 idx < CFF_MAX_TRANS_ELEMENTS &&
1917 count <= num_axes )
1918 {
1919 FT_UInt end, i;
1920
1921
1922 end = FT_MIN( idx + count, CFF_MAX_TRANS_ELEMENTS );
1923
1924 if ( idx < end )
1925 decoder->buildchar[idx] = 1 << 16;
1926
1927 for ( i = idx + 1; i < end; i++ )
1928 decoder->buildchar[i] = 0;
1929 }
1930 }
1931 break;
1932
1933 case cff_op_blend:
1934 /* this operator was removed from the Type2 specification */
1935 /* in version 16-March-2000 */
1936 if ( num_designs )
1937 {
1938 FT_Int num_results = (FT_Int)( args[0] >> 16 );
1939
1940
1941 FT_TRACE4(( " blend\n" ));
1942
1943 if ( num_results < 0 )
1944 goto Syntax_Error;
1945
1946 if ( num_results > num_args ||
1947 num_results * (FT_Int)num_designs > num_args )
1948 goto Stack_Underflow;
1949
1950 /* since we currently don't handle interpolation of multiple */
1951 /* master fonts, return the `num_results' values of the */
1952 /* first master */
1953 args -= num_results * ( num_designs - 1 );
1954 num_args -= num_results * ( num_designs - 1 );
1955 }
1956 else
1957 goto Syntax_Error;
1958 break;
1959
1960 case cff_op_dotsection:
1961 /* this operator is deprecated and ignored by the parser */
1962 FT_TRACE4(( " dotsection\n" ));
1963 break;
1964
1965 case cff_op_closepath:
1966 /* this is an invalid Type 2 operator; however, there */
1967 /* exist fonts which are incorrectly converted from probably */
1968 /* Type 1 to CFF, and some parsers seem to accept it */
1969
1970 FT_TRACE4(( " closepath (invalid op)\n" ));
1971
1972 args = stack;
1973 break;
1974
1975 case cff_op_hsbw:
1976 /* this is an invalid Type 2 operator; however, there */
1977 /* exist fonts which are incorrectly converted from probably */
1978 /* Type 1 to CFF, and some parsers seem to accept it */
1979
1980 FT_TRACE4(( " hsbw (invalid op)\n" ));
1981
1982 decoder->glyph_width =
1983 ADD_LONG( decoder->nominal_width, ( args[1] >> 16 ) );
1984
1985 decoder->builder.left_bearing.x = args[0];
1986 decoder->builder.left_bearing.y = 0;
1987
1988 x = ADD_LONG( decoder->builder.pos_x, args[0] );
1989 y = decoder->builder.pos_y;
1990 args = stack;
1991 break;
1992
1993 case cff_op_sbw:
1994 /* this is an invalid Type 2 operator; however, there */
1995 /* exist fonts which are incorrectly converted from probably */
1996 /* Type 1 to CFF, and some parsers seem to accept it */
1997
1998 FT_TRACE4(( " sbw (invalid op)\n" ));
1999
2000 decoder->glyph_width =
2001 ADD_LONG( decoder->nominal_width, ( args[2] >> 16 ) );
2002
2003 decoder->builder.left_bearing.x = args[0];
2004 decoder->builder.left_bearing.y = args[1];
2005
2006 x = ADD_LONG( decoder->builder.pos_x, args[0] );
2007 y = ADD_LONG( decoder->builder.pos_y, args[1] );
2008 args = stack;
2009 break;
2010
2011 case cff_op_setcurrentpoint:
2012 /* this is an invalid Type 2 operator; however, there */
2013 /* exist fonts which are incorrectly converted from probably */
2014 /* Type 1 to CFF, and some parsers seem to accept it */
2015
2016 FT_TRACE4(( " setcurrentpoint (invalid op)\n" ));
2017
2018 x = ADD_LONG( decoder->builder.pos_x, args[0] );
2019 y = ADD_LONG( decoder->builder.pos_y, args[1] );
2020 args = stack;
2021 break;
2022
2023 case cff_op_callothersubr:
2024 {
2025 FT_Fixed arg;
2026
2027
2028 /* this is an invalid Type 2 operator; however, there */
2029 /* exist fonts which are incorrectly converted from */
2030 /* probably Type 1 to CFF, and some parsers seem to accept */
2031 /* it */
2032
2033 FT_TRACE4(( " callothersubr (invalid op)\n" ));
2034
2035 /* subsequent `pop' operands should add the arguments, */
2036 /* this is the implementation described for `unknown' */
2037 /* other subroutines in the Type1 spec. */
2038 /* */
2039 /* XXX Fix return arguments (see discussion below). */
2040
2041 arg = 2 + ( args[-2] >> 16 );
2042 if ( arg >= CFF_MAX_OPERANDS )
2043 goto Stack_Underflow;
2044
2045 args -= arg;
2046 if ( args < stack )
2047 goto Stack_Underflow;
2048 }
2049 break;
2050
2051 case cff_op_pop:
2052 /* this is an invalid Type 2 operator; however, there */
2053 /* exist fonts which are incorrectly converted from probably */
2054 /* Type 1 to CFF, and some parsers seem to accept it */
2055
2056 FT_TRACE4(( " pop (invalid op)\n" ));
2057
2058 /* XXX Increasing `args' is wrong: After a certain number of */
2059 /* `pop's we get a stack overflow. Reason for doing it is */
2060 /* code like this (actually found in a CFF font): */
2061 /* */
2062 /* 17 1 3 callothersubr */
2063 /* pop */
2064 /* callsubr */
2065 /* */
2066 /* Since we handle `callothersubr' as a no-op, and */
2067 /* `callsubr' needs at least one argument, `pop' can't be a */
2068 /* no-op too as it basically should be. */
2069 /* */
2070 /* The right solution would be to provide real support for */
2071 /* `callothersubr' as done in `t1decode.c', however, given */
2072 /* the fact that CFF fonts with `pop' are invalid, it is */
2073 /* questionable whether it is worth the time. */
2074 args++;
2075 break;
2076
2077 case cff_op_and:
2078 {
2079 FT_Fixed cond = ( args[0] && args[1] );
2080
2081
2082 FT_TRACE4(( " and\n" ));
2083
2084 args[0] = cond ? 0x10000L : 0;
2085 args++;
2086 }
2087 break;
2088
2089 case cff_op_or:
2090 {
2091 FT_Fixed cond = ( args[0] || args[1] );
2092
2093
2094 FT_TRACE4(( " or\n" ));
2095
2096 args[0] = cond ? 0x10000L : 0;
2097 args++;
2098 }
2099 break;
2100
2101 case cff_op_not:
2102 {
2103 FT_Fixed cond = !args[0];
2104
2105
2106 FT_TRACE4(( " not\n" ));
2107
2108 args[0] = cond ? 0x10000L : 0;
2109 args++;
2110 }
2111 break;
2112
2113 case cff_op_eq:
2114 {
2115 FT_Fixed cond = ( args[0] == args[1] );
2116
2117
2118 FT_TRACE4(( " eq\n" ));
2119
2120 args[0] = cond ? 0x10000L : 0;
2121 args++;
2122 }
2123 break;
2124
2125 case cff_op_ifelse:
2126 {
2127 FT_Fixed cond = ( args[2] <= args[3] );
2128
2129
2130 FT_TRACE4(( " ifelse\n" ));
2131
2132 if ( !cond )
2133 args[0] = args[1];
2134 args++;
2135 }
2136 break;
2137
2138 case cff_op_callsubr:
2139 {
2140 FT_UInt idx = (FT_UInt)( ( args[0] >> 16 ) +
2141 decoder->locals_bias );
2142
2143
2144 FT_TRACE4(( " callsubr (idx %u, entering level %td)\n",
2145 idx,
2146 zone - decoder->zones + 1 ));
2147
2148 if ( idx >= decoder->num_locals )
2149 {
2150 FT_ERROR(( "cff_decoder_parse_charstrings:"
2151 " invalid local subr index\n" ));
2152 goto Syntax_Error;
2153 }
2154
2155 if ( zone - decoder->zones >= CFF_MAX_SUBRS_CALLS )
2156 {
2157 FT_ERROR(( "cff_decoder_parse_charstrings:"
2158 " too many nested subrs\n" ));
2159 goto Syntax_Error;
2160 }
2161
2162 zone->cursor = ip; /* save current instruction pointer */
2163
2164 zone++;
2165 zone->base = decoder->locals[idx];
2166 zone->limit = decoder->locals[idx + 1];
2167 zone->cursor = zone->base;
2168
2169 if ( !zone->base || zone->limit == zone->base )
2170 {
2171 FT_ERROR(( "cff_decoder_parse_charstrings:"
2172 " invoking empty subrs\n" ));
2173 goto Syntax_Error;
2174 }
2175
2176 decoder->zone = zone;
2177 ip = zone->base;
2178 limit = zone->limit;
2179 }
2180 break;
2181
2182 case cff_op_callgsubr:
2183 {
2184 FT_UInt idx = (FT_UInt)( ( args[0] >> 16 ) +
2185 decoder->globals_bias );
2186
2187
2188 FT_TRACE4(( " callgsubr (idx %u, entering level %td)\n",
2189 idx,
2190 zone - decoder->zones + 1 ));
2191
2192 if ( idx >= decoder->num_globals )
2193 {
2194 FT_ERROR(( "cff_decoder_parse_charstrings:"
2195 " invalid global subr index\n" ));
2196 goto Syntax_Error;
2197 }
2198
2199 if ( zone - decoder->zones >= CFF_MAX_SUBRS_CALLS )
2200 {
2201 FT_ERROR(( "cff_decoder_parse_charstrings:"
2202 " too many nested subrs\n" ));
2203 goto Syntax_Error;
2204 }
2205
2206 zone->cursor = ip; /* save current instruction pointer */
2207
2208 zone++;
2209 zone->base = decoder->globals[idx];
2210 zone->limit = decoder->globals[idx + 1];
2211 zone->cursor = zone->base;
2212
2213 if ( !zone->base || zone->limit == zone->base )
2214 {
2215 FT_ERROR(( "cff_decoder_parse_charstrings:"
2216 " invoking empty subrs\n" ));
2217 goto Syntax_Error;
2218 }
2219
2220 decoder->zone = zone;
2221 ip = zone->base;
2222 limit = zone->limit;
2223 }
2224 break;
2225
2226 case cff_op_return:
2227 FT_TRACE4(( " return (leaving level %td)\n",
2228 decoder->zone - decoder->zones ));
2229
2230 if ( decoder->zone <= decoder->zones )
2231 {
2232 FT_ERROR(( "cff_decoder_parse_charstrings:"
2233 " unexpected return\n" ));
2234 goto Syntax_Error;
2235 }
2236
2237 decoder->zone--;
2238 zone = decoder->zone;
2239 ip = zone->cursor;
2240 limit = zone->limit;
2241 break;
2242
2243 default:
2244 FT_ERROR(( "Unimplemented opcode: %d", ip[-1] ));
2245
2246 if ( ip[-1] == 12 )
2247 FT_ERROR(( " %d", ip[0] ));
2248 FT_ERROR(( "\n" ));
2249
2250 return FT_THROW( Unimplemented_Feature );
2251 }
2252
2253 decoder->top = args;
2254
2255 if ( decoder->top - stack >= CFF_MAX_OPERANDS )
2256 goto Stack_Overflow;
2257
2258 } /* general operator processing */
2259
2260 } /* while ip < limit */
2261
2262 FT_TRACE4(( "..end..\n" ));
2263 FT_TRACE4(( "\n" ));
2264
2265 Fail:
2266 return error;
2267
2268 MM_Error:
2269 FT_TRACE4(( "cff_decoder_parse_charstrings:"
2270 " invalid opcode found in top DICT charstring\n"));
2271 return FT_THROW( Invalid_File_Format );
2272
2273 Syntax_Error:
2274 FT_TRACE4(( "cff_decoder_parse_charstrings: syntax error\n" ));
2275 return FT_THROW( Invalid_File_Format );
2276
2277 Stack_Underflow:
2278 FT_TRACE4(( "cff_decoder_parse_charstrings: stack underflow\n" ));
2279 return FT_THROW( Too_Few_Arguments );
2280
2281 Stack_Overflow:
2282 FT_TRACE4(( "cff_decoder_parse_charstrings: stack overflow\n" ));
2283 return FT_THROW( Stack_Overflow );
2284 }
2285
2286#endif /* CFF_CONFIG_OPTION_OLD_ENGINE */
2287
2288
2289 /**************************************************************************
2290 *
2291 * @Function:
2292 * cff_decoder_init
2293 *
2294 * @Description:
2295 * Initializes a given glyph decoder.
2296 *
2297 * @InOut:
2298 * decoder ::
2299 * A pointer to the glyph builder to initialize.
2300 *
2301 * @Input:
2302 * face ::
2303 * The current face object.
2304 *
2305 * size ::
2306 * The current size object.
2307 *
2308 * slot ::
2309 * The current glyph object.
2310 *
2311 * hinting ::
2312 * Whether hinting is active.
2313 *
2314 * hint_mode ::
2315 * The hinting mode.
2316 */
2317 FT_LOCAL_DEF( void )
2318 cff_decoder_init( CFF_Decoder* decoder,
2319 TT_Face face,
2320 CFF_Size size,
2321 CFF_GlyphSlot slot,
2322 FT_Bool hinting,
2323 FT_Render_Mode hint_mode,
2324 CFF_Decoder_Get_Glyph_Callback get_callback,
2325 CFF_Decoder_Free_Glyph_Callback free_callback )
2326 {
2327 CFF_Font cff = (CFF_Font)face->extra.data;
2328
2329
2330 /* clear everything */
2331 FT_ZERO( decoder );
2332
2333 /* initialize builder */
2334 cff_builder_init( &decoder->builder, face, size, slot, hinting );
2335
2336 /* initialize Type2 decoder */
2337 decoder->cff = cff;
2338 decoder->num_globals = cff->global_subrs_index.count;
2339 decoder->globals = cff->global_subrs;
2340 decoder->globals_bias = cff_compute_bias(
2341 cff->top_font.font_dict.charstring_type,
2342 decoder->num_globals );
2343
2344 decoder->hint_mode = hint_mode;
2345
2346 decoder->get_glyph_callback = get_callback;
2347 decoder->free_glyph_callback = free_callback;
2348 }
2349
2350
2351 /* this function is used to select the subfont */
2352 /* and the locals subrs array */
2353 FT_LOCAL_DEF( FT_Error )
2354 cff_decoder_prepare( CFF_Decoder* decoder,
2355 CFF_Size size,
2356 FT_UInt glyph_index )
2357 {
2358 CFF_Builder *builder = &decoder->builder;
2359 CFF_Font cff = (CFF_Font)builder->face->extra.data;
2360 CFF_SubFont sub = &cff->top_font;
2361 FT_Error error = FT_Err_Ok;
2362
2363 FT_Service_CFFLoad cffload = (FT_Service_CFFLoad)cff->cffload;
2364
2365
2366 /* manage CID fonts */
2367 if ( cff->num_subfonts )
2368 {
2369 FT_Byte fd_index = cffload->fd_select_get( &cff->fd_select,
2370 glyph_index );
2371
2372
2373 if ( fd_index >= cff->num_subfonts )
2374 {
2375 FT_TRACE4(( "cff_decoder_prepare: invalid CID subfont index\n" ));
2376 error = FT_THROW( Invalid_File_Format );
2377 goto Exit;
2378 }
2379
2380 FT_TRACE3(( " in subfont %d:\n", fd_index ));
2381
2382 sub = cff->subfonts[fd_index];
2383
2384 if ( builder->hints_funcs && size )
2385 {
2386 FT_Size ftsize = FT_SIZE( size );
2387 CFF_Internal internal = (CFF_Internal)ftsize->internal->module_data;
2388
2389
2390 /* for CFFs without subfonts, this value has already been set */
2391 builder->hints_globals = (void *)internal->subfonts[fd_index];
2392 }
2393 }
2394
2395 decoder->num_locals = sub->local_subrs_index.count;
2396 decoder->locals = sub->local_subrs;
2397 decoder->locals_bias = cff_compute_bias(
2398 decoder->cff->top_font.font_dict.charstring_type,
2399 decoder->num_locals );
2400
2401 decoder->glyph_width = sub->private_dict.default_width;
2402 decoder->nominal_width = sub->private_dict.nominal_width;
2403
2404 decoder->current_subfont = sub;
2405
2406 Exit:
2407 return error;
2408 }
2409
2410
2411/* END */