ReactOS 0.4.15-dev-8061-g57b775e
t1decode.c
Go to the documentation of this file.
1/***************************************************************************/
2/* */
3/* t1decode.c */
4/* */
5/* PostScript Type 1 decoding routines (body). */
6/* */
7/* Copyright 2000-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_CALC_H
21#include FT_INTERNAL_DEBUG_H
22#include FT_INTERNAL_POSTSCRIPT_HINTS_H
23#include FT_INTERNAL_HASH_H
24#include FT_OUTLINE_H
25
26#include "t1decode.h"
27#include "psobjs.h"
28
29#include "psauxerr.h"
30
31/* ensure proper sign extension */
32#define Fix2Int( f ) ( (FT_Int)(FT_Short)( (f) >> 16 ) )
33
34 /*************************************************************************/
35 /* */
36 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
37 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
38 /* messages during execution. */
39 /* */
40#undef FT_COMPONENT
41#define FT_COMPONENT trace_t1decode
42
43
44 typedef enum T1_Operator_
45 {
73
74 op_max /* never remove this one */
75
77
78
79 static
81 {
82 0, /* none */
83 0, /* endchar */
84 2, /* hsbw */
85 5, /* seac */
86 4, /* sbw */
87 0, /* closepath */
88 1, /* hlineto */
89 1, /* hmoveto */
90 4, /* hvcurveto */
91 2, /* rlineto */
92 2, /* rmoveto */
93 6, /* rrcurveto */
94 4, /* vhcurveto */
95 1, /* vlineto */
96 1, /* vmoveto */
97 0, /* dotsection */
98 2, /* hstem */
99 6, /* hstem3 */
100 2, /* vstem */
101 6, /* vstem3 */
102 2, /* div */
103 -1, /* callothersubr */
104 1, /* callsubr */
105 0, /* pop */
106 0, /* return */
107 2, /* setcurrentpoint */
108 2 /* opcode 15 (undocumented and obsolete) */
109 };
110
111
112 /*************************************************************************/
113 /* */
114 /* <Function> */
115 /* t1_lookup_glyph_by_stdcharcode_ps */
116 /* */
117 /* <Description> */
118 /* Looks up a given glyph by its StandardEncoding charcode. Used to */
119 /* implement the SEAC Type 1 operator in the Adobe engine */
120 /* */
121 /* <Input> */
122 /* face :: The current face object. */
123 /* */
124 /* charcode :: The character code to look for. */
125 /* */
126 /* <Return> */
127 /* A glyph index in the font face. Returns -1 if the corresponding */
128 /* glyph wasn't found. */
129 /* */
132 FT_Int charcode )
133 {
134 FT_UInt n;
135 const FT_String* glyph_name;
136 FT_Service_PsCMaps psnames = decoder->psnames;
137
138
139 /* check range of standard char code */
140 if ( charcode < 0 || charcode > 255 )
141 return -1;
142
143 glyph_name = psnames->adobe_std_strings(
144 psnames->adobe_std_encoding[charcode]);
145
146 for ( n = 0; n < decoder->num_glyphs; n++ )
147 {
148 FT_String* name = (FT_String*)decoder->glyph_names[n];
149
150
151 if ( name &&
152 name[0] == glyph_name[0] &&
153 ft_strcmp( name, glyph_name ) == 0 )
154 return (FT_Int)n;
155 }
156
157 return -1;
158 }
159
160
161#ifdef T1_CONFIG_OPTION_OLD_ENGINE
162 /*************************************************************************/
163 /* */
164 /* <Function> */
165 /* t1_lookup_glyph_by_stdcharcode */
166 /* */
167 /* <Description> */
168 /* Looks up a given glyph by its StandardEncoding charcode. Used to */
169 /* implement the SEAC Type 1 operator. */
170 /* */
171 /* <Input> */
172 /* face :: The current face object. */
173 /* */
174 /* charcode :: The character code to look for. */
175 /* */
176 /* <Return> */
177 /* A glyph index in the font face. Returns -1 if the corresponding */
178 /* glyph wasn't found. */
179 /* */
180 static FT_Int
181 t1_lookup_glyph_by_stdcharcode( T1_Decoder decoder,
182 FT_Int charcode )
183 {
184 FT_UInt n;
185 const FT_String* glyph_name;
186 FT_Service_PsCMaps psnames = decoder->psnames;
187
188
189 /* check range of standard char code */
190 if ( charcode < 0 || charcode > 255 )
191 return -1;
192
193 glyph_name = psnames->adobe_std_strings(
194 psnames->adobe_std_encoding[charcode]);
195
196 for ( n = 0; n < decoder->num_glyphs; n++ )
197 {
198 FT_String* name = (FT_String*)decoder->glyph_names[n];
199
200
201 if ( name &&
202 name[0] == glyph_name[0] &&
203 ft_strcmp( name, glyph_name ) == 0 )
204 return (FT_Int)n;
205 }
206
207 return -1;
208 }
209
210
211 /* parse a single Type 1 glyph */
213 t1_decoder_parse_glyph( T1_Decoder decoder,
214 FT_UInt glyph )
215 {
216 return decoder->parse_callback( decoder, glyph );
217 }
218
219
220 /*************************************************************************/
221 /* */
222 /* <Function> */
223 /* t1operator_seac */
224 /* */
225 /* <Description> */
226 /* Implements the `seac' Type 1 operator for a Type 1 decoder. */
227 /* */
228 /* <Input> */
229 /* decoder :: The current CID decoder. */
230 /* */
231 /* asb :: The accent's side bearing. */
232 /* */
233 /* adx :: The horizontal offset of the accent. */
234 /* */
235 /* ady :: The vertical offset of the accent. */
236 /* */
237 /* bchar :: The base character's StandardEncoding charcode. */
238 /* */
239 /* achar :: The accent character's StandardEncoding charcode. */
240 /* */
241 /* <Return> */
242 /* FreeType error code. 0 means success. */
243 /* */
244 static FT_Error
245 t1operator_seac( T1_Decoder decoder,
246 FT_Pos asb,
247 FT_Pos adx,
248 FT_Pos ady,
249 FT_Int bchar,
250 FT_Int achar )
251 {
253 FT_Int bchar_index, achar_index;
254#if 0
255 FT_Int n_base_points;
256 FT_Outline* base = decoder->builder.base;
257#endif
258 FT_Vector left_bearing, advance;
259
260#ifdef FT_CONFIG_OPTION_INCREMENTAL
261 T1_Face face = (T1_Face)decoder->builder.face;
262#endif
263
264
265 if ( decoder->seac )
266 {
267 FT_ERROR(( "t1operator_seac: invalid nested seac\n" ));
268 return FT_THROW( Syntax_Error );
269 }
270
271 if ( decoder->builder.metrics_only )
272 {
273 FT_ERROR(( "t1operator_seac: unexpected seac\n" ));
274 return FT_THROW( Syntax_Error );
275 }
276
277 /* seac weirdness */
278 adx += decoder->builder.left_bearing.x;
279
280 /* `glyph_names' is set to 0 for CID fonts which do not */
281 /* include an encoding. How can we deal with these? */
282#ifdef FT_CONFIG_OPTION_INCREMENTAL
283 if ( decoder->glyph_names == 0 &&
284 !face->root.internal->incremental_interface )
285#else
286 if ( decoder->glyph_names == 0 )
287#endif /* FT_CONFIG_OPTION_INCREMENTAL */
288 {
289 FT_ERROR(( "t1operator_seac:"
290 " glyph names table not available in this font\n" ));
291 return FT_THROW( Syntax_Error );
292 }
293
294#ifdef FT_CONFIG_OPTION_INCREMENTAL
295 if ( face->root.internal->incremental_interface )
296 {
297 /* the caller must handle the font encoding also */
298 bchar_index = bchar;
299 achar_index = achar;
300 }
301 else
302#endif
303 {
304 bchar_index = t1_lookup_glyph_by_stdcharcode( decoder, bchar );
305 achar_index = t1_lookup_glyph_by_stdcharcode( decoder, achar );
306 }
307
308 if ( bchar_index < 0 || achar_index < 0 )
309 {
310 FT_ERROR(( "t1operator_seac:"
311 " invalid seac character code arguments\n" ));
312 return FT_THROW( Syntax_Error );
313 }
314
315 /* if we are trying to load a composite glyph, do not load the */
316 /* accent character and return the array of subglyphs. */
317 if ( decoder->builder.no_recurse )
318 {
319 FT_GlyphSlot glyph = (FT_GlyphSlot)decoder->builder.glyph;
320 FT_GlyphLoader loader = glyph->internal->loader;
321 FT_SubGlyph subg;
322
323
324 /* reallocate subglyph array if necessary */
326 if ( error )
327 goto Exit;
328
329 subg = loader->current.subglyphs;
330
331 /* subglyph 0 = base character */
332 subg->index = bchar_index;
335 subg->arg1 = 0;
336 subg->arg2 = 0;
337 subg++;
338
339 /* subglyph 1 = accent character */
340 subg->index = achar_index;
342 subg->arg1 = (FT_Int)FIXED_TO_INT( adx - asb );
343 subg->arg2 = (FT_Int)FIXED_TO_INT( ady );
344
345 /* set up remaining glyph fields */
346 glyph->num_subglyphs = 2;
347 glyph->subglyphs = loader->base.subglyphs;
348 glyph->format = FT_GLYPH_FORMAT_COMPOSITE;
349
350 loader->current.num_subglyphs = 2;
351 goto Exit;
352 }
353
354 /* First load `bchar' in builder */
355 /* now load the unscaled outline */
356
357 FT_GlyphLoader_Prepare( decoder->builder.loader ); /* prepare loader */
358
359 /* the seac operator must not be nested */
360 decoder->seac = TRUE;
361 error = t1_decoder_parse_glyph( decoder, (FT_UInt)bchar_index );
362 decoder->seac = FALSE;
363 if ( error )
364 goto Exit;
365
366 /* save the left bearing and width of the base character */
367 /* as they will be erased by the next load. */
368
369 left_bearing = decoder->builder.left_bearing;
370 advance = decoder->builder.advance;
371
372 decoder->builder.left_bearing.x = 0;
373 decoder->builder.left_bearing.y = 0;
374
375 decoder->builder.pos_x = adx - asb;
376 decoder->builder.pos_y = ady;
377
378 /* Now load `achar' on top of */
379 /* the base outline */
380
381 /* the seac operator must not be nested */
382 decoder->seac = TRUE;
383 error = t1_decoder_parse_glyph( decoder, (FT_UInt)achar_index );
384 decoder->seac = FALSE;
385 if ( error )
386 goto Exit;
387
388 /* restore the left side bearing and */
389 /* advance width of the base character */
390
391 decoder->builder.left_bearing = left_bearing;
392 decoder->builder.advance = advance;
393
394 decoder->builder.pos_x = 0;
395 decoder->builder.pos_y = 0;
396
397 Exit:
398 return error;
399 }
400
401
402 /*************************************************************************/
403 /* */
404 /* <Function> */
405 /* t1_decoder_parse_charstrings */
406 /* */
407 /* <Description> */
408 /* Parses a given Type 1 charstrings program. */
409 /* */
410 /* <Input> */
411 /* decoder :: The current Type 1 decoder. */
412 /* */
413 /* charstring_base :: The base address of the charstring stream. */
414 /* */
415 /* charstring_len :: The length in bytes of the charstring stream. */
416 /* */
417 /* <Return> */
418 /* FreeType error code. 0 means success. */
419 /* */
421 t1_decoder_parse_charstrings( T1_Decoder decoder,
422 FT_Byte* charstring_base,
423 FT_UInt charstring_len )
424 {
427 FT_Byte* ip;
428 FT_Byte* limit;
429 T1_Builder builder = &decoder->builder;
430 FT_Pos x, y, orig_x, orig_y;
431 FT_Int known_othersubr_result_cnt = 0;
432 FT_Int unknown_othersubr_result_cnt = 0;
433 FT_Bool large_int;
434 FT_Fixed seed;
435
436 T1_Hints_Funcs hinter;
437
438#ifdef FT_DEBUG_LEVEL_TRACE
439 FT_Bool bol = TRUE;
440#endif
441
442
443 /* compute random seed from stack address of parameter */
444 seed = (FT_Fixed)( ( (FT_Offset)(char*)&seed ^
445 (FT_Offset)(char*)&decoder ^
446 (FT_Offset)(char*)&charstring_base ) &
447 FT_ULONG_MAX );
448 seed = ( seed ^ ( seed >> 10 ) ^ ( seed >> 20 ) ) & 0xFFFFL;
449 if ( seed == 0 )
450 seed = 0x7384;
451
452 /* First of all, initialize the decoder */
453 decoder->top = decoder->stack;
454 decoder->zone = decoder->zones;
455 zone = decoder->zones;
456
457 builder->parse_state = T1_Parse_Start;
458
459 hinter = (T1_Hints_Funcs)builder->hints_funcs;
460
461 /* a font that reads BuildCharArray without setting */
462 /* its values first is buggy, but ... */
463 FT_ASSERT( ( decoder->len_buildchar == 0 ) ==
464 ( decoder->buildchar == NULL ) );
465
466 if ( decoder->buildchar && decoder->len_buildchar > 0 )
467 FT_ARRAY_ZERO( decoder->buildchar, decoder->len_buildchar );
468
469 FT_TRACE4(( "\n"
470 "Start charstring\n" ));
471
472 zone->base = charstring_base;
473 limit = zone->limit = charstring_base + charstring_len;
474 ip = zone->cursor = zone->base;
475
477
478 x = orig_x = builder->pos_x;
479 y = orig_y = builder->pos_y;
480
481 /* begin hints recording session, if any */
482 if ( hinter )
483 hinter->open( hinter->hints );
484
485 large_int = FALSE;
486
487 /* now, execute loop */
488 while ( ip < limit )
489 {
490 FT_Long* top = decoder->top;
492 FT_Int32 value = 0;
493
494
495 FT_ASSERT( known_othersubr_result_cnt == 0 ||
496 unknown_othersubr_result_cnt == 0 );
497
498#ifdef FT_DEBUG_LEVEL_TRACE
499 if ( bol )
500 {
501 FT_TRACE5(( " (%d)", decoder->top - decoder->stack ));
502 bol = FALSE;
503 }
504#endif
505
506 /*********************************************************************/
507 /* */
508 /* Decode operator or operand */
509 /* */
510 /* */
511
512 /* first of all, decompress operator or value */
513 switch ( *ip++ )
514 {
515 case 1:
516 op = op_hstem;
517 break;
518
519 case 3:
520 op = op_vstem;
521 break;
522 case 4:
523 op = op_vmoveto;
524 break;
525 case 5:
526 op = op_rlineto;
527 break;
528 case 6:
529 op = op_hlineto;
530 break;
531 case 7:
532 op = op_vlineto;
533 break;
534 case 8:
536 break;
537 case 9:
539 break;
540 case 10:
541 op = op_callsubr;
542 break;
543 case 11:
544 op = op_return;
545 break;
546
547 case 13:
548 op = op_hsbw;
549 break;
550 case 14:
551 op = op_endchar;
552 break;
553
554 case 15: /* undocumented, obsolete operator */
556 break;
557
558 case 21:
559 op = op_rmoveto;
560 break;
561 case 22:
562 op = op_hmoveto;
563 break;
564
565 case 30:
567 break;
568 case 31:
570 break;
571
572 case 12:
573 if ( ip >= limit )
574 {
575 FT_ERROR(( "t1_decoder_parse_charstrings:"
576 " invalid escape (12+EOF)\n" ));
577 goto Syntax_Error;
578 }
579
580 switch ( *ip++ )
581 {
582 case 0:
584 break;
585 case 1:
586 op = op_vstem3;
587 break;
588 case 2:
589 op = op_hstem3;
590 break;
591 case 6:
592 op = op_seac;
593 break;
594 case 7:
595 op = op_sbw;
596 break;
597 case 12:
598 op = op_div;
599 break;
600 case 16:
602 break;
603 case 17:
604 op = op_pop;
605 break;
606 case 33:
608 break;
609
610 default:
611 FT_ERROR(( "t1_decoder_parse_charstrings:"
612 " invalid escape (12+%d)\n",
613 ip[-1] ));
614 goto Syntax_Error;
615 }
616 break;
617
618 case 255: /* four bytes integer */
619 if ( ip + 4 > limit )
620 {
621 FT_ERROR(( "t1_decoder_parse_charstrings:"
622 " unexpected EOF in integer\n" ));
623 goto Syntax_Error;
624 }
625
626 value = (FT_Int32)( ( (FT_UInt32)ip[0] << 24 ) |
627 ( (FT_UInt32)ip[1] << 16 ) |
628 ( (FT_UInt32)ip[2] << 8 ) |
629 (FT_UInt32)ip[3] );
630 ip += 4;
631
632 /* According to the specification, values > 32000 or < -32000 must */
633 /* be followed by a `div' operator to make the result be in the */
634 /* range [-32000;32000]. We expect that the second argument of */
635 /* `div' is not a large number. Additionally, we don't handle */
636 /* stuff like `<large1> <large2> <num> div <num> div' or */
637 /* <large1> <large2> <num> div div'. This is probably not allowed */
638 /* anyway. */
639 if ( value > 32000 || value < -32000 )
640 {
641 if ( large_int )
642 {
643 FT_ERROR(( "t1_decoder_parse_charstrings:"
644 " no `div' after large integer\n" ));
645 }
646 else
647 large_int = TRUE;
648 }
649 else
650 {
651 if ( !large_int )
652 value = (FT_Int32)( (FT_UInt32)value << 16 );
653 }
654
655 break;
656
657 default:
658 if ( ip[-1] >= 32 )
659 {
660 if ( ip[-1] < 247 )
661 value = (FT_Int32)ip[-1] - 139;
662 else
663 {
664 if ( ++ip > limit )
665 {
666 FT_ERROR(( "t1_decoder_parse_charstrings:"
667 " unexpected EOF in integer\n" ));
668 goto Syntax_Error;
669 }
670
671 if ( ip[-2] < 251 )
672 value = ( ( ip[-2] - 247 ) * 256 ) + ip[-1] + 108;
673 else
674 value = -( ( ( ip[-2] - 251 ) * 256 ) + ip[-1] + 108 );
675 }
676
677 if ( !large_int )
678 value = (FT_Int32)( (FT_UInt32)value << 16 );
679 }
680 else
681 {
682 FT_ERROR(( "t1_decoder_parse_charstrings:"
683 " invalid byte (%d)\n", ip[-1] ));
684 goto Syntax_Error;
685 }
686 }
687
688 if ( unknown_othersubr_result_cnt > 0 )
689 {
690 switch ( op )
691 {
692 case op_callsubr:
693 case op_return:
694 case op_none:
695 case op_pop:
696 break;
697
698 default:
699 /* all operands have been transferred by previous pops */
700 unknown_othersubr_result_cnt = 0;
701 break;
702 }
703 }
704
705 if ( large_int && !( op == op_none || op == op_div ) )
706 {
707 FT_ERROR(( "t1_decoder_parse_charstrings:"
708 " no `div' after large integer\n" ));
709
710 large_int = FALSE;
711 }
712
713 /*********************************************************************/
714 /* */
715 /* Push value on stack, or process operator */
716 /* */
717 /* */
718 if ( op == op_none )
719 {
720 if ( top - decoder->stack >= T1_MAX_CHARSTRINGS_OPERANDS )
721 {
722 FT_ERROR(( "t1_decoder_parse_charstrings: stack overflow\n" ));
723 goto Syntax_Error;
724 }
725
726#ifdef FT_DEBUG_LEVEL_TRACE
727 if ( large_int )
728 FT_TRACE4(( " %d", value ));
729 else
730 FT_TRACE4(( " %d", value / 65536 ));
731#endif
732
733 *top++ = value;
734 decoder->top = top;
735 }
736 else if ( op == op_callothersubr ) /* callothersubr */
737 {
738 FT_Int subr_no;
740
741
742#ifdef FT_DEBUG_LEVEL_TRACE
743 FT_TRACE4(( " callothersubr\n" ));
744 bol = TRUE;
745#endif
746
747 if ( top - decoder->stack < 2 )
748 goto Stack_Underflow;
749
750 top -= 2;
751
752 subr_no = Fix2Int( top[1] );
753 arg_cnt = Fix2Int( top[0] );
754
755 /***********************************************************/
756 /* */
757 /* remove all operands to callothersubr from the stack */
758 /* */
759 /* for handled othersubrs, where we know the number of */
760 /* arguments, we increase the stack by the value of */
761 /* known_othersubr_result_cnt */
762 /* */
763 /* for unhandled othersubrs the following pops adjust the */
764 /* stack pointer as necessary */
765
766 if ( arg_cnt > top - decoder->stack )
767 goto Stack_Underflow;
768
769 top -= arg_cnt;
770
771 known_othersubr_result_cnt = 0;
772 unknown_othersubr_result_cnt = 0;
773
774 /* XXX TODO: The checks to `arg_count == <whatever>' */
775 /* might not be correct; an othersubr expects a certain */
776 /* number of operands on the PostScript stack (as opposed */
777 /* to the T1 stack) but it doesn't have to put them there */
778 /* by itself; previous othersubrs might have left the */
779 /* operands there if they were not followed by an */
780 /* appropriate number of pops */
781 /* */
782 /* On the other hand, Adobe Reader 7.0.8 for Linux doesn't */
783 /* accept a font that contains charstrings like */
784 /* */
785 /* 100 200 2 20 callothersubr */
786 /* 300 1 20 callothersubr pop */
787 /* */
788 /* Perhaps this is the reason why BuildCharArray exists. */
789
790 switch ( subr_no )
791 {
792 case 0: /* end flex feature */
793 if ( arg_cnt != 3 )
794 goto Unexpected_OtherSubr;
795
796 if ( !decoder->flex_state ||
797 decoder->num_flex_vectors != 7 )
798 {
799 FT_ERROR(( "t1_decoder_parse_charstrings:"
800 " unexpected flex end\n" ));
801 goto Syntax_Error;
802 }
803
804 /* the two `results' are popped by the following setcurrentpoint */
805 top[0] = x;
806 top[1] = y;
807 known_othersubr_result_cnt = 2;
808 break;
809
810 case 1: /* start flex feature */
811 if ( arg_cnt != 0 )
812 goto Unexpected_OtherSubr;
813
814 if ( FT_SET_ERROR( t1_builder_start_point( builder, x, y ) ) ||
815 FT_SET_ERROR( t1_builder_check_points( builder, 6 ) ) )
816 goto Fail;
817
818 decoder->flex_state = 1;
819 decoder->num_flex_vectors = 0;
820 break;
821
822 case 2: /* add flex vectors */
823 {
824 FT_Int idx;
825
826
827 if ( arg_cnt != 0 )
828 goto Unexpected_OtherSubr;
829
830 if ( !decoder->flex_state )
831 {
832 FT_ERROR(( "t1_decoder_parse_charstrings:"
833 " missing flex start\n" ));
834 goto Syntax_Error;
835 }
836
837 /* note that we should not add a point for index 0; */
838 /* this will move our current position to the flex */
839 /* point without adding any point to the outline */
840 idx = decoder->num_flex_vectors++;
841 if ( idx > 0 && idx < 7 )
842 {
843 /* in malformed fonts it is possible to have other */
844 /* opcodes in the middle of a flex (which don't */
845 /* increase `num_flex_vectors'); we thus have to */
846 /* check whether we can add a point */
847 if ( FT_SET_ERROR( t1_builder_check_points( builder, 1 ) ) )
848 goto Syntax_Error;
849
850 t1_builder_add_point( builder,
851 x,
852 y,
853 (FT_Byte)( idx == 3 || idx == 6 ) );
854 }
855 }
856 break;
857
858 case 3: /* change hints */
859 if ( arg_cnt != 1 )
860 goto Unexpected_OtherSubr;
861
862 known_othersubr_result_cnt = 1;
863
864 if ( hinter )
865 hinter->reset( hinter->hints,
866 (FT_UInt)builder->current->n_points );
867 break;
868
869 case 12:
870 case 13:
871 /* counter control hints, clear stack */
872 top = decoder->stack;
873 break;
874
875 case 14:
876 case 15:
877 case 16:
878 case 17:
879 case 18: /* multiple masters */
880 {
881 PS_Blend blend = decoder->blend;
882 FT_UInt num_points, nn, mm;
883 FT_Long* delta;
885
886
887 if ( !blend )
888 {
889 FT_ERROR(( "t1_decoder_parse_charstrings:"
890 " unexpected multiple masters operator\n" ));
891 goto Syntax_Error;
892 }
893
894 num_points = (FT_UInt)subr_no - 13 + ( subr_no == 18 );
895 if ( arg_cnt != (FT_Int)( num_points * blend->num_designs ) )
896 {
897 FT_ERROR(( "t1_decoder_parse_charstrings:"
898 " incorrect number of multiple masters arguments\n" ));
899 goto Syntax_Error;
900 }
901
902 /* We want to compute */
903 /* */
904 /* a0*w0 + a1*w1 + ... + ak*wk */
905 /* */
906 /* but we only have a0, a1-a0, a2-a0, ..., ak-a0. */
907 /* */
908 /* However, given that w0 + w1 + ... + wk == 1, we can */
909 /* rewrite it easily as */
910 /* */
911 /* a0 + (a1-a0)*w1 + (a2-a0)*w2 + ... + (ak-a0)*wk */
912 /* */
913 /* where k == num_designs-1. */
914 /* */
915 /* I guess that's why it's written in this `compact' */
916 /* form. */
917 /* */
918 delta = top + num_points;
919 values = top;
920 for ( nn = 0; nn < num_points; nn++ )
921 {
922 FT_Long tmp = values[0];
923
924
925 for ( mm = 1; mm < blend->num_designs; mm++ )
926 tmp = ADD_LONG( tmp,
927 FT_MulFix( *delta++,
928 blend->weight_vector[mm] ) );
929
930 *values++ = tmp;
931 }
932
933 known_othersubr_result_cnt = (FT_Int)num_points;
934 break;
935 }
936
937 case 19:
938 /* <idx> 1 19 callothersubr */
939 /* => replace elements starting from index cvi( <idx> ) */
940 /* of BuildCharArray with WeightVector */
941 {
942 FT_Int idx;
943 PS_Blend blend = decoder->blend;
944
945
946 if ( arg_cnt != 1 || !blend )
947 goto Unexpected_OtherSubr;
948
949 idx = Fix2Int( top[0] );
950
951 if ( idx < 0 ||
952 (FT_UInt)idx + blend->num_designs > decoder->len_buildchar )
953 goto Unexpected_OtherSubr;
954
955 ft_memcpy( &decoder->buildchar[idx],
956 blend->weight_vector,
957 blend->num_designs *
958 sizeof ( blend->weight_vector[0] ) );
959 }
960 break;
961
962 case 20:
963 /* <arg1> <arg2> 2 20 callothersubr pop */
964 /* ==> push <arg1> + <arg2> onto T1 stack */
965 if ( arg_cnt != 2 )
966 goto Unexpected_OtherSubr;
967
968 top[0] = ADD_LONG( top[0], top[1] );
969
970 known_othersubr_result_cnt = 1;
971 break;
972
973 case 21:
974 /* <arg1> <arg2> 2 21 callothersubr pop */
975 /* ==> push <arg1> - <arg2> onto T1 stack */
976 if ( arg_cnt != 2 )
977 goto Unexpected_OtherSubr;
978
979 top[0] = SUB_LONG( top[0], top[1] );
980
981 known_othersubr_result_cnt = 1;
982 break;
983
984 case 22:
985 /* <arg1> <arg2> 2 22 callothersubr pop */
986 /* ==> push <arg1> * <arg2> onto T1 stack */
987 if ( arg_cnt != 2 )
988 goto Unexpected_OtherSubr;
989
990 top[0] = FT_MulFix( top[0], top[1] );
991
992 known_othersubr_result_cnt = 1;
993 break;
994
995 case 23:
996 /* <arg1> <arg2> 2 23 callothersubr pop */
997 /* ==> push <arg1> / <arg2> onto T1 stack */
998 if ( arg_cnt != 2 || top[1] == 0 )
999 goto Unexpected_OtherSubr;
1000
1001 top[0] = FT_DivFix( top[0], top[1] );
1002
1003 known_othersubr_result_cnt = 1;
1004 break;
1005
1006 case 24:
1007 /* <val> <idx> 2 24 callothersubr */
1008 /* ==> set BuildCharArray[cvi( <idx> )] = <val> */
1009 {
1010 FT_Int idx;
1011 PS_Blend blend = decoder->blend;
1012
1013
1014 if ( arg_cnt != 2 || !blend )
1015 goto Unexpected_OtherSubr;
1016
1017 idx = Fix2Int( top[1] );
1018
1019 if ( idx < 0 || (FT_UInt) idx >= decoder->len_buildchar )
1020 goto Unexpected_OtherSubr;
1021
1022 decoder->buildchar[idx] = top[0];
1023 }
1024 break;
1025
1026 case 25:
1027 /* <idx> 1 25 callothersubr pop */
1028 /* ==> push BuildCharArray[cvi( idx )] */
1029 /* onto T1 stack */
1030 {
1031 FT_Int idx;
1032 PS_Blend blend = decoder->blend;
1033
1034
1035 if ( arg_cnt != 1 || !blend )
1036 goto Unexpected_OtherSubr;
1037
1038 idx = Fix2Int( top[0] );
1039
1040 if ( idx < 0 || (FT_UInt) idx >= decoder->len_buildchar )
1041 goto Unexpected_OtherSubr;
1042
1043 top[0] = decoder->buildchar[idx];
1044 }
1045
1046 known_othersubr_result_cnt = 1;
1047 break;
1048
1049#if 0
1050 case 26:
1051 /* <val> mark <idx> ==> set BuildCharArray[cvi( <idx> )] = <val>, */
1052 /* leave mark on T1 stack */
1053 /* <val> <idx> ==> set BuildCharArray[cvi( <idx> )] = <val> */
1054 XXX which routine has left its mark on the (PostScript) stack?;
1055 break;
1056#endif
1057
1058 case 27:
1059 /* <res1> <res2> <val1> <val2> 4 27 callothersubr pop */
1060 /* ==> push <res1> onto T1 stack if <val1> <= <val2>, */
1061 /* otherwise push <res2> */
1062 if ( arg_cnt != 4 )
1063 goto Unexpected_OtherSubr;
1064
1065 if ( top[2] > top[3] )
1066 top[0] = top[1];
1067
1068 known_othersubr_result_cnt = 1;
1069 break;
1070
1071 case 28:
1072 /* 0 28 callothersubr pop */
1073 /* => push random value from interval [0, 1) onto stack */
1074 if ( arg_cnt != 0 )
1075 goto Unexpected_OtherSubr;
1076
1077 {
1078 FT_Fixed Rand;
1079
1080
1081 Rand = seed;
1082 if ( Rand >= 0x8000L )
1083 Rand++;
1084
1085 top[0] = Rand;
1086
1087 seed = FT_MulFix( seed, 0x10000L - seed );
1088 if ( seed == 0 )
1089 seed += 0x2873;
1090 }
1091
1092 known_othersubr_result_cnt = 1;
1093 break;
1094
1095 default:
1096 if ( arg_cnt >= 0 && subr_no >= 0 )
1097 {
1098 FT_ERROR(( "t1_decoder_parse_charstrings:"
1099 " unknown othersubr [%d %d], wish me luck\n",
1100 arg_cnt, subr_no ));
1101 unknown_othersubr_result_cnt = arg_cnt;
1102 break;
1103 }
1104 /* fall through */
1105
1106 Unexpected_OtherSubr:
1107 FT_ERROR(( "t1_decoder_parse_charstrings:"
1108 " invalid othersubr [%d %d]\n", arg_cnt, subr_no ));
1109 goto Syntax_Error;
1110 }
1111
1112 top += known_othersubr_result_cnt;
1113
1114 decoder->top = top;
1115 }
1116 else /* general operator */
1117 {
1118 FT_Int num_args = t1_args_count[op];
1119
1120
1121 FT_ASSERT( num_args >= 0 );
1122
1123 if ( top - decoder->stack < num_args )
1124 goto Stack_Underflow;
1125
1126 /* XXX Operators usually take their operands from the */
1127 /* bottom of the stack, i.e., the operands are */
1128 /* decoder->stack[0], ..., decoder->stack[num_args - 1]; */
1129 /* only div, callsubr, and callothersubr are different. */
1130 /* In practice it doesn't matter (?). */
1131
1132#ifdef FT_DEBUG_LEVEL_TRACE
1133
1134 switch ( op )
1135 {
1136 case op_callsubr:
1137 case op_div:
1138 case op_callothersubr:
1139 case op_pop:
1140 case op_return:
1141 break;
1142
1143 default:
1144 if ( top - decoder->stack != num_args )
1145 FT_TRACE0(( "t1_decoder_parse_charstrings:"
1146 " too much operands on the stack"
1147 " (seen %d, expected %d)\n",
1148 top - decoder->stack, num_args ));
1149 break;
1150 }
1151
1152#endif /* FT_DEBUG_LEVEL_TRACE */
1153
1154 top -= num_args;
1155
1156 switch ( op )
1157 {
1158 case op_endchar:
1159 FT_TRACE4(( " endchar\n" ));
1160
1161 t1_builder_close_contour( builder );
1162
1163 /* close hints recording session */
1164 if ( hinter )
1165 {
1166 if ( hinter->close( hinter->hints,
1167 (FT_UInt)builder->current->n_points ) )
1168 goto Syntax_Error;
1169
1170 /* apply hints to the loaded glyph outline now */
1171 error = hinter->apply( hinter->hints,
1172 builder->current,
1173 (PSH_Globals)builder->hints_globals,
1174 decoder->hint_mode );
1175 if ( error )
1176 goto Fail;
1177 }
1178
1179 /* add current outline to the glyph slot */
1180 FT_GlyphLoader_Add( builder->loader );
1181
1182 /* the compiler should optimize away this empty loop but ... */
1183
1184#ifdef FT_DEBUG_LEVEL_TRACE
1185
1186 if ( decoder->len_buildchar > 0 )
1187 {
1188 FT_UInt i;
1189
1190
1191 FT_TRACE4(( "BuildCharArray = [ " ));
1192
1193 for ( i = 0; i < decoder->len_buildchar; i++ )
1194 FT_TRACE4(( "%d ", decoder->buildchar[i] ));
1195
1196 FT_TRACE4(( "]\n" ));
1197 }
1198
1199#endif /* FT_DEBUG_LEVEL_TRACE */
1200
1201 FT_TRACE4(( "\n" ));
1202
1203 /* return now! */
1204 return FT_Err_Ok;
1205
1206 case op_hsbw:
1207 FT_TRACE4(( " hsbw" ));
1208
1210
1211 builder->left_bearing.x = ADD_LONG( builder->left_bearing.x,
1212 top[0] );
1213
1214 builder->advance.x = top[1];
1215 builder->advance.y = 0;
1216
1217 orig_x = x = ADD_LONG( builder->pos_x, top[0] );
1218 orig_y = y = builder->pos_y;
1219
1220 FT_UNUSED( orig_y );
1221
1222 /* the `metrics_only' indicates that we only want to compute */
1223 /* the glyph's metrics (lsb + advance width), not load the */
1224 /* rest of it; so exit immediately */
1225 if ( builder->metrics_only )
1226 return FT_Err_Ok;
1227
1228 break;
1229
1230 case op_seac:
1231 return t1operator_seac( decoder,
1232 top[0],
1233 top[1],
1234 top[2],
1235 Fix2Int( top[3] ),
1236 Fix2Int( top[4] ) );
1237
1238 case op_sbw:
1239 FT_TRACE4(( " sbw" ));
1240
1242
1243 builder->left_bearing.x = ADD_LONG( builder->left_bearing.x,
1244 top[0] );
1245 builder->left_bearing.y = ADD_LONG( builder->left_bearing.y,
1246 top[1] );
1247
1248 builder->advance.x = top[2];
1249 builder->advance.y = top[3];
1250
1251 x = ADD_LONG( builder->pos_x, top[0] );
1252 y = ADD_LONG( builder->pos_y, top[1] );
1253
1254 /* the `metrics_only' indicates that we only want to compute */
1255 /* the glyph's metrics (lsb + advance width), not load the */
1256 /* rest of it; so exit immediately */
1257 if ( builder->metrics_only )
1258 return FT_Err_Ok;
1259
1260 break;
1261
1262 case op_closepath:
1263 FT_TRACE4(( " closepath" ));
1264
1265 /* if there is no path, `closepath' is a no-op */
1266 if ( builder->parse_state == T1_Parse_Have_Path ||
1267 builder->parse_state == T1_Parse_Have_Moveto )
1268 t1_builder_close_contour( builder );
1269
1271 break;
1272
1273 case op_hlineto:
1274 FT_TRACE4(( " hlineto" ));
1275
1276 if ( FT_SET_ERROR( t1_builder_start_point( builder, x, y ) ) )
1277 goto Fail;
1278
1279 x = ADD_LONG( x, top[0] );
1280 goto Add_Line;
1281
1282 case op_hmoveto:
1283 FT_TRACE4(( " hmoveto" ));
1284
1285 x = ADD_LONG( x, top[0] );
1286
1287 if ( !decoder->flex_state )
1288 {
1289 if ( builder->parse_state == T1_Parse_Start )
1290 goto Syntax_Error;
1292 }
1293 break;
1294
1295 case op_hvcurveto:
1296 FT_TRACE4(( " hvcurveto" ));
1297
1298 if ( FT_SET_ERROR( t1_builder_start_point( builder, x, y ) ) ||
1299 FT_SET_ERROR( t1_builder_check_points( builder, 3 ) ) )
1300 goto Fail;
1301
1302 x = ADD_LONG( x, top[0] );
1303 t1_builder_add_point( builder, x, y, 0 );
1304
1305 x = ADD_LONG( x, top[1] );
1306 y = ADD_LONG( y, top[2] );
1307 t1_builder_add_point( builder, x, y, 0 );
1308
1309 y = ADD_LONG( y, top[3] );
1310 t1_builder_add_point( builder, x, y, 1 );
1311 break;
1312
1313 case op_rlineto:
1314 FT_TRACE4(( " rlineto" ));
1315
1316 if ( FT_SET_ERROR( t1_builder_start_point( builder, x, y ) ) )
1317 goto Fail;
1318
1319 x = ADD_LONG( x, top[0] );
1320 y = ADD_LONG( y, top[1] );
1321
1322 Add_Line:
1323 if ( FT_SET_ERROR( t1_builder_add_point1( builder, x, y ) ) )
1324 goto Fail;
1325 break;
1326
1327 case op_rmoveto:
1328 FT_TRACE4(( " rmoveto" ));
1329
1330 x = ADD_LONG( x, top[0] );
1331 y = ADD_LONG( y, top[1] );
1332
1333 if ( !decoder->flex_state )
1334 {
1335 if ( builder->parse_state == T1_Parse_Start )
1336 goto Syntax_Error;
1338 }
1339 break;
1340
1341 case op_rrcurveto:
1342 FT_TRACE4(( " rrcurveto" ));
1343
1344 if ( FT_SET_ERROR( t1_builder_start_point( builder, x, y ) ) ||
1345 FT_SET_ERROR( t1_builder_check_points( builder, 3 ) ) )
1346 goto Fail;
1347
1348 x = ADD_LONG( x, top[0] );
1349 y = ADD_LONG( y, top[1] );
1350 t1_builder_add_point( builder, x, y, 0 );
1351
1352 x = ADD_LONG( x, top[2] );
1353 y = ADD_LONG( y, top[3] );
1354 t1_builder_add_point( builder, x, y, 0 );
1355
1356 x = ADD_LONG( x, top[4] );
1357 y = ADD_LONG( y, top[5] );
1358 t1_builder_add_point( builder, x, y, 1 );
1359 break;
1360
1361 case op_vhcurveto:
1362 FT_TRACE4(( " vhcurveto" ));
1363
1364 if ( FT_SET_ERROR( t1_builder_start_point( builder, x, y ) ) ||
1365 FT_SET_ERROR( t1_builder_check_points( builder, 3 ) ) )
1366 goto Fail;
1367
1368 y = ADD_LONG( y, top[0] );
1369 t1_builder_add_point( builder, x, y, 0 );
1370
1371 x = ADD_LONG( x, top[1] );
1372 y = ADD_LONG( y, top[2] );
1373 t1_builder_add_point( builder, x, y, 0 );
1374
1375 x = ADD_LONG( x, top[3] );
1376 t1_builder_add_point( builder, x, y, 1 );
1377 break;
1378
1379 case op_vlineto:
1380 FT_TRACE4(( " vlineto" ));
1381
1382 if ( FT_SET_ERROR( t1_builder_start_point( builder, x, y ) ) )
1383 goto Fail;
1384
1385 y = ADD_LONG( y, top[0] );
1386 goto Add_Line;
1387
1388 case op_vmoveto:
1389 FT_TRACE4(( " vmoveto" ));
1390
1391 y = ADD_LONG( y, top[0] );
1392
1393 if ( !decoder->flex_state )
1394 {
1395 if ( builder->parse_state == T1_Parse_Start )
1396 goto Syntax_Error;
1398 }
1399 break;
1400
1401 case op_div:
1402 FT_TRACE4(( " div" ));
1403
1404 /* if `large_int' is set, we divide unscaled numbers; */
1405 /* otherwise, we divide numbers in 16.16 format -- */
1406 /* in both cases, it is the same operation */
1407 *top = FT_DivFix( top[0], top[1] );
1408 top++;
1409
1410 large_int = FALSE;
1411 break;
1412
1413 case op_callsubr:
1414 {
1415 FT_Int idx;
1416
1417
1418 FT_TRACE4(( " callsubr" ));
1419
1420 idx = Fix2Int( top[0] );
1421
1422 if ( decoder->subrs_hash )
1423 {
1424 size_t* val = ft_hash_num_lookup( idx,
1425 decoder->subrs_hash );
1426
1427
1428 if ( val )
1429 idx = *val;
1430 else
1431 idx = -1;
1432 }
1433
1434 if ( idx < 0 || idx >= decoder->num_subrs )
1435 {
1436 FT_ERROR(( "t1_decoder_parse_charstrings:"
1437 " invalid subrs index\n" ));
1438 goto Syntax_Error;
1439 }
1440
1441 if ( zone - decoder->zones >= T1_MAX_SUBRS_CALLS )
1442 {
1443 FT_ERROR(( "t1_decoder_parse_charstrings:"
1444 " too many nested subrs\n" ));
1445 goto Syntax_Error;
1446 }
1447
1448 zone->cursor = ip; /* save current instruction pointer */
1449
1450 zone++;
1451
1452 /* The Type 1 driver stores subroutines without the seed bytes. */
1453 /* The CID driver stores subroutines with seed bytes. This */
1454 /* case is taken care of when decoder->subrs_len == 0. */
1455 zone->base = decoder->subrs[idx];
1456
1457 if ( decoder->subrs_len )
1458 zone->limit = zone->base + decoder->subrs_len[idx];
1459 else
1460 {
1461 /* We are using subroutines from a CID font. We must adjust */
1462 /* for the seed bytes. */
1463 zone->base += ( decoder->lenIV >= 0 ? decoder->lenIV : 0 );
1464 zone->limit = decoder->subrs[idx + 1];
1465 }
1466
1467 zone->cursor = zone->base;
1468
1469 if ( !zone->base )
1470 {
1471 FT_ERROR(( "t1_decoder_parse_charstrings:"
1472 " invoking empty subrs\n" ));
1473 goto Syntax_Error;
1474 }
1475
1476 decoder->zone = zone;
1477 ip = zone->base;
1478 limit = zone->limit;
1479 break;
1480 }
1481
1482 case op_pop:
1483 FT_TRACE4(( " pop" ));
1484
1485 if ( known_othersubr_result_cnt > 0 )
1486 {
1487 known_othersubr_result_cnt--;
1488 /* ignore, we pushed the operands ourselves */
1489 break;
1490 }
1491
1492 if ( unknown_othersubr_result_cnt == 0 )
1493 {
1494 FT_ERROR(( "t1_decoder_parse_charstrings:"
1495 " no more operands for othersubr\n" ));
1496 goto Syntax_Error;
1497 }
1498
1499 unknown_othersubr_result_cnt--;
1500 top++; /* `push' the operand to callothersubr onto the stack */
1501 break;
1502
1503 case op_return:
1504 FT_TRACE4(( " return" ));
1505
1506 if ( zone <= decoder->zones )
1507 {
1508 FT_ERROR(( "t1_decoder_parse_charstrings:"
1509 " unexpected return\n" ));
1510 goto Syntax_Error;
1511 }
1512
1513 zone--;
1514 ip = zone->cursor;
1515 limit = zone->limit;
1516 decoder->zone = zone;
1517 break;
1518
1519 case op_dotsection:
1520 FT_TRACE4(( " dotsection" ));
1521
1522 break;
1523
1524 case op_hstem:
1525 FT_TRACE4(( " hstem" ));
1526
1527 /* record horizontal hint */
1528 if ( hinter )
1529 {
1530 /* top[0] += builder->left_bearing.y; */
1531 hinter->stem( hinter->hints, 1, top );
1532 }
1533 break;
1534
1535 case op_hstem3:
1536 FT_TRACE4(( " hstem3" ));
1537
1538 /* record horizontal counter-controlled hints */
1539 if ( hinter )
1540 hinter->stem3( hinter->hints, 1, top );
1541 break;
1542
1543 case op_vstem:
1544 FT_TRACE4(( " vstem" ));
1545
1546 /* record vertical hint */
1547 if ( hinter )
1548 {
1549 top[0] = ADD_LONG( top[0], orig_x );
1550 hinter->stem( hinter->hints, 0, top );
1551 }
1552 break;
1553
1554 case op_vstem3:
1555 FT_TRACE4(( " vstem3" ));
1556
1557 /* record vertical counter-controlled hints */
1558 if ( hinter )
1559 {
1560 FT_Pos dx = orig_x;
1561
1562
1563 top[0] = ADD_LONG( top[0], dx );
1564 top[2] = ADD_LONG( top[2], dx );
1565 top[4] = ADD_LONG( top[4], dx );
1566 hinter->stem3( hinter->hints, 0, top );
1567 }
1568 break;
1569
1570 case op_setcurrentpoint:
1571 FT_TRACE4(( " setcurrentpoint" ));
1572
1573 /* From the T1 specification, section 6.4: */
1574 /* */
1575 /* The setcurrentpoint command is used only in */
1576 /* conjunction with results from OtherSubrs procedures. */
1577
1578 /* known_othersubr_result_cnt != 0 is already handled */
1579 /* above. */
1580
1581 /* Note, however, that both Ghostscript and Adobe */
1582 /* Distiller handle this situation by silently ignoring */
1583 /* the inappropriate `setcurrentpoint' instruction. So */
1584 /* we do the same. */
1585#if 0
1586
1587 if ( decoder->flex_state != 1 )
1588 {
1589 FT_ERROR(( "t1_decoder_parse_charstrings:"
1590 " unexpected `setcurrentpoint'\n" ));
1591 goto Syntax_Error;
1592 }
1593 else
1594 ...
1595#endif
1596
1597 x = top[0];
1598 y = top[1];
1599 decoder->flex_state = 0;
1600 break;
1601
1602 case op_unknown15:
1603 FT_TRACE4(( " opcode_15" ));
1604 /* nothing to do except to pop the two arguments */
1605 break;
1606
1607 default:
1608 FT_ERROR(( "t1_decoder_parse_charstrings:"
1609 " unhandled opcode %d\n", op ));
1610 goto Syntax_Error;
1611 }
1612
1613 /* XXX Operators usually clear the operand stack; */
1614 /* only div, callsubr, callothersubr, pop, and */
1615 /* return are different. */
1616 /* In practice it doesn't matter (?). */
1617
1618 decoder->top = top;
1619
1620#ifdef FT_DEBUG_LEVEL_TRACE
1621 FT_TRACE4(( "\n" ));
1622 bol = TRUE;
1623#endif
1624
1625 } /* general operator processing */
1626
1627 } /* while ip < limit */
1628
1629 FT_TRACE4(( "..end..\n\n" ));
1630
1631 Fail:
1632 return error;
1633
1634 Syntax_Error:
1635 return FT_THROW( Syntax_Error );
1636
1637 Stack_Underflow:
1638 return FT_THROW( Stack_Underflow );
1639 }
1640
1641#else /* T1_CONFIG_OPTION_OLD_ENGINE */
1642
1643 /*************************************************************************/
1644 /* */
1645 /* <Function> */
1646 /* t1_decoder_parse_metrics */
1647 /* */
1648 /* <Description> */
1649 /* Parses a given Type 1 charstrings program to extract width */
1650 /* */
1651 /* <Input> */
1652 /* decoder :: The current Type 1 decoder. */
1653 /* */
1654 /* charstring_base :: The base address of the charstring stream. */
1655 /* */
1656 /* charstring_len :: The length in bytes of the charstring stream. */
1657 /* */
1658 /* <Return> */
1659 /* FreeType error code. 0 means success. */
1660 /* */
1663 FT_Byte* charstring_base,
1664 FT_UInt charstring_len )
1665 {
1667 FT_Byte* ip;
1668 FT_Byte* limit;
1669 T1_Builder builder = &decoder->builder;
1670
1671#ifdef FT_DEBUG_LEVEL_TRACE
1672 FT_Bool bol = TRUE;
1673#endif
1674
1675
1676 /* First of all, initialize the decoder */
1677 decoder->top = decoder->stack;
1678 decoder->zone = decoder->zones;
1679 zone = decoder->zones;
1680
1681 builder->parse_state = T1_Parse_Start;
1682
1683 FT_TRACE4(( "\n"
1684 "Start charstring: get width\n" ));
1685
1686 zone->base = charstring_base;
1687 limit = zone->limit = charstring_base + charstring_len;
1688 ip = zone->cursor = zone->base;
1689
1690 /* now, execute loop */
1691 while ( ip < limit )
1692 {
1693 FT_Long* top = decoder->top;
1695 FT_Int32 value = 0;
1696
1697
1698#ifdef FT_DEBUG_LEVEL_TRACE
1699 if ( bol )
1700 {
1701 FT_TRACE5(( " (%d)", decoder->top - decoder->stack ));
1702 bol = FALSE;
1703 }
1704#endif
1705
1706 /*********************************************************************/
1707 /* */
1708 /* Decode operator or operand */
1709 /* */
1710 /* */
1711
1712 /* first of all, decompress operator or value */
1713 switch ( *ip++ )
1714 {
1715 case 1:
1716 case 3:
1717 case 4:
1718 case 5:
1719 case 6:
1720 case 7:
1721 case 8:
1722 case 9:
1723 case 10:
1724 case 11:
1725 case 14:
1726 case 15:
1727 case 21:
1728 case 22:
1729 case 30:
1730 case 31:
1731 goto No_Width;
1732
1733 case 13:
1734 op = op_hsbw;
1735 break;
1736
1737 case 12:
1738 if ( ip >= limit )
1739 {
1740 FT_ERROR(( "t1_decoder_parse_metrics:"
1741 " invalid escape (12+EOF)\n" ));
1742 goto Syntax_Error;
1743 }
1744
1745 switch ( *ip++ )
1746 {
1747 case 7:
1748 op = op_sbw;
1749 break;
1750
1751 default:
1752 goto No_Width;
1753 }
1754 break;
1755
1756 case 255: /* four bytes integer */
1757 if ( ip + 4 > limit )
1758 {
1759 FT_ERROR(( "t1_decoder_parse_metrics:"
1760 " unexpected EOF in integer\n" ));
1761 goto Syntax_Error;
1762 }
1763
1764 value = (FT_Int32)( ( (FT_UInt32)ip[0] << 24 ) |
1765 ( (FT_UInt32)ip[1] << 16 ) |
1766 ( (FT_UInt32)ip[2] << 8 ) |
1767 (FT_UInt32)ip[3] );
1768 ip += 4;
1769
1770 /* According to the specification, values > 32000 or < -32000 must */
1771 /* be followed by a `div' operator to make the result be in the */
1772 /* range [-32000;32000]. We expect that the second argument of */
1773 /* `div' is not a large number. Additionally, we don't handle */
1774 /* stuff like `<large1> <large2> <num> div <num> div' or */
1775 /* <large1> <large2> <num> div div'. This is probably not allowed */
1776 /* anyway. */
1777 if ( value > 32000 || value < -32000 )
1778 {
1779 FT_ERROR(( "t1_decoder_parse_metrics:"
1780 " large integer found for width\n" ));
1781 goto Syntax_Error;
1782 }
1783 else
1784 {
1785 value = (FT_Int32)( (FT_UInt32)value << 16 );
1786 }
1787
1788 break;
1789
1790 default:
1791 if ( ip[-1] >= 32 )
1792 {
1793 if ( ip[-1] < 247 )
1794 value = (FT_Int32)ip[-1] - 139;
1795 else
1796 {
1797 if ( ++ip > limit )
1798 {
1799 FT_ERROR(( "t1_decoder_parse_metrics:"
1800 " unexpected EOF in integer\n" ));
1801 goto Syntax_Error;
1802 }
1803
1804 if ( ip[-2] < 251 )
1805 value = ( ( ip[-2] - 247 ) * 256 ) + ip[-1] + 108;
1806 else
1807 value = -( ( ( ip[-2] - 251 ) * 256 ) + ip[-1] + 108 );
1808 }
1809
1810 value = (FT_Int32)( (FT_UInt32)value << 16 );
1811 }
1812 else
1813 {
1814 FT_ERROR(( "t1_decoder_parse_metrics:"
1815 " invalid byte (%d)\n", ip[-1] ));
1816 goto Syntax_Error;
1817 }
1818 }
1819
1820 /*********************************************************************/
1821 /* */
1822 /* Push value on stack, or process operator */
1823 /* */
1824 /* */
1825 if ( op == op_none )
1826 {
1827 if ( top - decoder->stack >= T1_MAX_CHARSTRINGS_OPERANDS )
1828 {
1829 FT_ERROR(( "t1_decoder_parse_metrics: stack overflow\n" ));
1830 goto Syntax_Error;
1831 }
1832
1833#ifdef FT_DEBUG_LEVEL_TRACE
1834 FT_TRACE4(( " %d", value / 65536 ));
1835#endif
1836
1837 *top++ = value;
1838 decoder->top = top;
1839 }
1840 else /* general operator */
1841 {
1842 FT_Int num_args = t1_args_count[op];
1843
1844
1845 FT_ASSERT( num_args >= 0 );
1846
1847 if ( top - decoder->stack < num_args )
1848 goto Stack_Underflow;
1849
1850#ifdef FT_DEBUG_LEVEL_TRACE
1851
1852 if ( top - decoder->stack != num_args )
1853 FT_TRACE0(( "t1_decoder_parse_metrics:"
1854 " too much operands on the stack"
1855 " (seen %d, expected %d)\n",
1856 top - decoder->stack, num_args ));
1857
1858#endif /* FT_DEBUG_LEVEL_TRACE */
1859
1860 top -= num_args;
1861
1862 switch ( op )
1863 {
1864 case op_hsbw:
1865 FT_TRACE4(( " hsbw" ));
1866
1868
1869 builder->left_bearing.x = ADD_LONG( builder->left_bearing.x,
1870 top[0] );
1871
1872 builder->advance.x = top[1];
1873 builder->advance.y = 0;
1874
1875 /* we only want to compute the glyph's metrics */
1876 /* (lsb + advance width), not load the rest of */
1877 /* it; so exit immediately */
1878 return FT_Err_Ok;
1879
1880 case op_sbw:
1881 FT_TRACE4(( " sbw" ));
1882
1884
1885 builder->left_bearing.x = ADD_LONG( builder->left_bearing.x,
1886 top[0] );
1887 builder->left_bearing.y = ADD_LONG( builder->left_bearing.y,
1888 top[1] );
1889
1890 builder->advance.x = top[2];
1891 builder->advance.y = top[3];
1892
1893 /* we only want to compute the glyph's metrics */
1894 /* (lsb + advance width), not load the rest of */
1895 /* it; so exit immediately */
1896 return FT_Err_Ok;
1897
1898 default:
1899 FT_ERROR(( "t1_decoder_parse_metrics:"
1900 " unhandled opcode %d\n", op ));
1901 goto Syntax_Error;
1902 }
1903
1904 } /* general operator processing */
1905
1906 } /* while ip < limit */
1907
1908 FT_TRACE4(( "..end..\n\n" ));
1909
1910 No_Width:
1911 FT_ERROR(( "t1_decoder_parse_metrics:"
1912 " no width, found op %d instead\n",
1913 ip[-1] ));
1914 Syntax_Error:
1915 return FT_THROW( Syntax_Error );
1916
1917 Stack_Underflow:
1918 return FT_THROW( Stack_Underflow );
1919 }
1920#endif /* T1_CONFIG_OPTION_OLD_ENGINE */
1921
1922
1923 /* initialize T1 decoder */
1926 FT_Face face,
1927 FT_Size size,
1929 FT_Byte** glyph_names,
1930 PS_Blend blend,
1931 FT_Bool hinting,
1932 FT_Render_Mode hint_mode,
1933 T1_Decoder_Callback parse_callback )
1934 {
1935 FT_ZERO( decoder );
1936
1937 /* retrieve PSNames interface from list of current modules */
1938 {
1939 FT_Service_PsCMaps psnames;
1940
1941
1942 FT_FACE_FIND_GLOBAL_SERVICE( face, psnames, POSTSCRIPT_CMAPS );
1943 if ( !psnames )
1944 {
1945 FT_ERROR(( "t1_decoder_init:"
1946 " the `psnames' module is not available\n" ));
1947 return FT_THROW( Unimplemented_Feature );
1948 }
1949
1950 decoder->psnames = psnames;
1951 }
1952
1953 t1_builder_init( &decoder->builder, face, size, slot, hinting );
1954
1955 /* decoder->buildchar and decoder->len_buildchar have to be */
1956 /* initialized by the caller since we cannot know the length */
1957 /* of the BuildCharArray */
1958
1959 decoder->num_glyphs = (FT_UInt)face->num_glyphs;
1960 decoder->glyph_names = glyph_names;
1961 decoder->hint_mode = hint_mode;
1962 decoder->blend = blend;
1963 decoder->parse_callback = parse_callback;
1964
1965 decoder->funcs = t1_decoder_funcs;
1966
1967 return FT_Err_Ok;
1968 }
1969
1970
1971 /* finalize T1 decoder */
1972 FT_LOCAL_DEF( void )
1974 {
1975 FT_Memory memory = decoder->builder.memory;
1976
1977
1978 t1_builder_done( &decoder->builder );
1979
1980 if ( decoder->cf2_instance.finalizer )
1981 {
1982 decoder->cf2_instance.finalizer( decoder->cf2_instance.data );
1983 FT_FREE( decoder->cf2_instance.data );
1984 }
1985 }
1986
1987
1988/* END */
_STLP_MOVE_TO_STD_NAMESPACE void _STLP_CALL advance(_InputIterator &__i, _Distance __n)
Definition: _stack.h:55
#define T1_MAX_CHARSTRINGS_OPERANDS
Definition: ftoption.h:725
#define T1_MAX_SUBRS_CALLS
Definition: ftoption.h:715
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
UINT op
Definition: effect.c:236
unsigned int idx
Definition: utils.c:41
int Fail
Definition: ehthrow.cxx:24
enum FT_Render_Mode_ FT_Render_Mode
FT_DivFix(FT_Long a, FT_Long b)
Definition: ftcalc.c:608
#define FT_SUBGLYPH_FLAG_USE_MY_METRICS
Definition: freetype.h:3928
struct FT_GlyphSlotRec_ * FT_GlyphSlot
Definition: freetype.h:554
#define FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES
Definition: freetype.h:3923
FT_MulFix(FT_Long a, FT_Long b)
Definition: ftcalc.c:509
return FT_Err_Ok
Definition: ftbbox.c:511
#define FIXED_TO_INT(x)
Definition: ftcalc.h:406
#define SUB_LONG(a, b)
Definition: ftcalc.h:422
#define ADD_LONG(a, b)
Definition: ftcalc.h:420
#define FT_LOCAL_DEF(x)
Definition: ftconfig.h:388
#define FT_UNUSED(arg)
Definition: ftconfig.h:101
#define FT_ASSERT(condition)
Definition: ftdebug.h:211
#define FT_TRACE0(varformat)
Definition: ftdebug.h:157
#define FT_ERROR(varformat)
Definition: ftdebug.h:181
#define FT_TRACE5(varformat)
Definition: ftdebug.h:162
#define FT_THROW(e)
Definition: ftdebug.h:213
#define FT_TRACE4(varformat)
Definition: ftdebug.h:161
cannot open resource broken file module version is too low unimplemented feature broken offset within table missing module invalid glyph index unsupported glyph image format invalid outline too many hints invalid object handle invalid module handle invalid size handle invalid charmap handle invalid stream handle too many extensions unlisted object invalid stream seek invalid stream read invalid frame operation invalid frame read raster corrupted negative height while rastering invalid opcode stack overflow bad argument invalid reference found ENDF opcode in execution stream invalid code range too many function definitions SFNT font table missing name table missing horizontal PostScript(post) table missing" ) FT_ERRORDEF_( Invalid_Horiz_Metrics
FT_GlyphLoader_Add(FT_GlyphLoader loader)
Definition: ftgloadr.c:328
FT_GlyphLoader_Prepare(FT_GlyphLoader loader)
Definition: ftgloadr.c:312
FT_GlyphLoader_CheckSubGlyphs(FT_GlyphLoader loader, FT_UInt n_subs)
Definition: ftgloadr.c:281
size_t * ft_hash_num_lookup(FT_Int num, FT_Hash hash)
Definition: fthash.c:327
FT_BEGIN_HEADER typedef signed long FT_Pos
Definition: ftimage.h:58
#define FT_SET_ERROR(expression)
Definition: ftmemory.h:42
#define FT_FREE(ptr)
Definition: ftmemory.h:329
#define FT_ZERO(p)
Definition: ftmemory.h:237
#define FT_ARRAY_ZERO(dest, count)
Definition: ftmemory.h:240
#define FT_FACE_FIND_GLOBAL_SERVICE(face, ptr, id)
Definition: ftserv.h:125
#define ft_memcpy
Definition: ftstdlib.h:82
#define ft_strcmp
Definition: ftstdlib.h:86
#define FT_ULONG_MAX
Definition: ftstdlib.h:68
typedefFT_BEGIN_HEADER struct FT_MemoryRec_ * FT_Memory
Definition: ftsystem.h:66
FT_BEGIN_HEADER typedef unsigned char FT_Bool
Definition: fttypes.h:108
unsigned char FT_Byte
Definition: fttypes.h:154
signed long FT_Fixed
Definition: fttypes.h:288
int FT_Error
Definition: fttypes.h:300
signed long FT_Long
Definition: fttypes.h:242
char FT_String
Definition: fttypes.h:187
unsigned int FT_UInt
Definition: fttypes.h:231
size_t FT_Offset
Definition: fttypes.h:324
signed int FT_Int
Definition: fttypes.h:220
GLint GLint GLint GLint GLint x
Definition: gl.h:1548
GLint GLint GLint GLint GLint GLint y
Definition: gl.h:1548
GLsizeiptr size
Definition: glext.h:5919
GLdouble n
Definition: glext.h:7729
GLdouble GLdouble GLdouble GLdouble top
Definition: glext.h:10859
GLenum GLuint GLint GLenum face
Definition: glext.h:7025
GLint limit
Definition: glext.h:10326
GLint left
Definition: glext.h:7726
GLboolean GLenum GLenum GLvoid * values
Definition: glext.h:5666
GLuint GLfloat * val
Definition: glext.h:7180
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
const struct T1_Hints_FuncsRec_ * T1_Hints_Funcs
Definition: pshints.h:117
typedefFT_BEGIN_HEADER struct PSH_GlobalsRec_ * PSH_Globals
Definition: pshints.h:41
int jpeg_marker_parser_method routine
Definition: jpeglib.h:1093
if(dx< 0)
Definition: linetemp.h:194
GLint dx
Definition: linetemp.h:97
#define error(str)
Definition: mkdosfs.c:1605
static char memory[1024 *256]
Definition: process.c:116
DWORD zone
Definition: sec_mgr.c:1754
FT_Error(* T1_Decoder_Callback)(T1_Decoder decoder, FT_UInt glyph_index)
Definition: psaux.h:852
@ T1_Parse_Have_Width
Definition: psaux.h:725
@ T1_Parse_Have_Path
Definition: psaux.h:727
@ T1_Parse_Start
Definition: psaux.h:724
@ T1_Parse_Have_Moveto
Definition: psaux.h:726
FT_CALLBACK_TABLE_DEF const T1_Decoder_FuncsRec t1_decoder_funcs
Definition: psauxmod.c:88
t1_builder_close_contour(T1_Builder builder)
Definition: psobjs.c:1711
t1_builder_start_point(T1_Builder builder, FT_Pos x, FT_Pos y)
Definition: psobjs.c:1686
t1_builder_init(T1_Builder builder, FT_Face face, FT_Size size, FT_GlyphSlot glyph, FT_Bool hinting)
Definition: psobjs.c:1533
t1_builder_add_point1(T1_Builder builder, FT_Pos x, FT_Pos y)
Definition: psobjs.c:1634
t1_builder_check_points(T1_Builder builder, FT_Int count)
Definition: psobjs.c:1601
t1_builder_done(T1_Builder builder)
Definition: psobjs.c:1589
t1_builder_add_point(T1_Builder builder, FT_Pos x, FT_Pos y, FT_Byte flag)
Definition: psobjs.c:1610
static void Exit(void)
Definition: sock.c:1330
FT_SubGlyph subglyphs
Definition: freetype.h:1930
FT_UInt num_subglyphs
Definition: freetype.h:1929
FT_Slot_Internal internal
Definition: freetype.h:1940
FT_Glyph_Format format
Definition: freetype.h:1921
short n_points
Definition: ftimage.h:337
FT_GlyphLoader loader
Definition: ftobjs.h:467
FT_Pos x
Definition: ftimage.h:76
FT_Pos y
Definition: ftimage.h:77
FT_UInt num_designs
Definition: t1tables.h:300
FT_Fixed * weight_vector
Definition: t1tables.h:307
FT_Bool no_recurse
Definition: psaux.h:798
FT_GlyphSlot glyph
Definition: psaux.h:784
FT_Vector advance
Definition: psaux.h:793
FT_Outline * base
Definition: psaux.h:786
FT_Face face
Definition: psaux.h:783
FT_Outline * current
Definition: psaux.h:787
FT_Vector left_bearing
Definition: psaux.h:792
FT_Bool metrics_only
Definition: psaux.h:800
FT_Pos pos_y
Definition: psaux.h:790
FT_Pos pos_x
Definition: psaux.h:789
FT_GlyphLoader loader
Definition: psaux.h:785
void * hints_globals
Definition: psaux.h:803
void * hints_funcs
Definition: psaux.h:802
T1_ParseState parse_state
Definition: psaux.h:796
FT_Byte ** subrs
Definition: psaux.h:909
FT_UInt * subrs_len
Definition: psaux.h:910
PS_Blend blend
Definition: psaux.h:920
FT_UInt num_glyphs
Definition: psaux.h:904
FT_Int flex_state
Definition: psaux.h:916
FT_Render_Mode hint_mode
Definition: psaux.h:922
FT_Int num_flex_vectors
Definition: psaux.h:917
FT_Bool seac
Definition: psaux.h:930
T1_Decoder_ZoneRec zones[T1_MAX_SUBRS_CALLS+1]
Definition: psaux.h:900
FT_UInt len_buildchar
Definition: psaux.h:928
FT_Long * top
Definition: psaux.h:898
FT_Int num_subrs
Definition: psaux.h:908
T1_BuilderRec builder
Definition: psaux.h:895
T1_Decoder_Callback parse_callback
Definition: psaux.h:924
FT_Long * buildchar
Definition: psaux.h:927
FT_Service_PsCMaps psnames
Definition: psaux.h:903
FT_Hash subrs_hash
Definition: psaux.h:911
FT_Byte ** glyph_names
Definition: psaux.h:905
T1_Decoder_Zone zone
Definition: psaux.h:901
FT_Int lenIV
Definition: psaux.h:907
FT_Long stack[T1_MAX_CHARSTRINGS_OPERANDS]
Definition: psaux.h:897
T1_Hints_ApplyFunc apply
Definition: pshints.h:350
T1_Hints_OpenFunc open
Definition: pshints.h:345
T1_Hints_ResetFunc reset
Definition: pshints.h:349
T1_Hints hints
Definition: pshints.h:344
T1_Hints_CloseFunc close
Definition: pshints.h:346
T1_Hints_SetStemFunc stem
Definition: pshints.h:347
T1_Hints_SetStem3Func stem3
Definition: pshints.h:348
Definition: vfat.h:185
Definition: dhcpd.h:62
Definition: name.c:39
static const FT_Int t1_args_count[op_max]
Definition: t1decode.c:80
#define Fix2Int(f)
Definition: t1decode.c:32
t1_decoder_parse_metrics(T1_Decoder decoder, FT_Byte *charstring_base, FT_UInt charstring_len)
Definition: t1decode.c:1662
enum T1_Operator_ T1_Operator
t1_decoder_done(T1_Decoder decoder)
Definition: t1decode.c:1973
t1_decoder_init(T1_Decoder decoder, FT_Face face, FT_Size size, FT_GlyphSlot slot, FT_Byte **glyph_names, PS_Blend blend, FT_Bool hinting, FT_Render_Mode hint_mode, T1_Decoder_Callback parse_callback)
Definition: t1decode.c:1925
t1_lookup_glyph_by_stdcharcode_ps(PS_Decoder *decoder, FT_Int charcode)
Definition: t1decode.c:131
T1_Operator_
Definition: t1decode.c:45
@ op_hmoveto
Definition: t1decode.c:53
@ op_vstem
Definition: t1decode.c:64
@ op_dotsection
Definition: t1decode.c:61
@ op_vmoveto
Definition: t1decode.c:60
@ op_hlineto
Definition: t1decode.c:52
@ op_rlineto
Definition: t1decode.c:55
@ op_hstem
Definition: t1decode.c:62
@ op_rrcurveto
Definition: t1decode.c:57
@ op_vhcurveto
Definition: t1decode.c:58
@ op_unknown15
Definition: t1decode.c:72
@ op_seac
Definition: t1decode.c:49
@ op_hsbw
Definition: t1decode.c:48
@ op_closepath
Definition: t1decode.c:51
@ op_div
Definition: t1decode.c:66
@ op_setcurrentpoint
Definition: t1decode.c:71
@ op_rmoveto
Definition: t1decode.c:56
@ op_sbw
Definition: t1decode.c:50
@ op_vlineto
Definition: t1decode.c:59
@ op_pop
Definition: t1decode.c:69
@ op_callsubr
Definition: t1decode.c:68
@ op_max
Definition: t1decode.c:74
@ op_callothersubr
Definition: t1decode.c:67
@ op_hstem3
Definition: t1decode.c:63
@ op_vstem3
Definition: t1decode.c:65
@ op_return
Definition: t1decode.c:70
@ op_endchar
Definition: t1decode.c:47
@ op_none
Definition: t1decode.c:46
@ op_hvcurveto
Definition: t1decode.c:54
struct T1_FaceRec_ * T1_Face
Definition: t1types.h:196
Definition: pdh_main.c:94
static unsigned arg_cnt(const DISPPARAMS *dp)
Definition: vbscript.h:162
static GLenum which
Definition: wgl_font.c:159
ActualNumberDriverObjects * sizeof(PDRIVER_OBJECT)) PDRIVER_OBJECT *DriverObjectList