OLD | NEW |
| (Empty) |
1 /***************************************************************************/ | |
2 /* */ | |
3 /* t1decode.c */ | |
4 /* */ | |
5 /* PostScript Type 1 decoding routines (body). */ | |
6 /* */ | |
7 /* Copyright 2000-2013 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 "../../include/ft2build.h" | |
20 #include "../../include/freetype/internal/ftcalc.h" | |
21 #include "../../include/freetype/internal/ftdebug.h" | |
22 #include "../../include/freetype/internal/pshints.h" | |
23 #include "../../include/freetype/ftoutln.h" | |
24 | |
25 #include "t1decode.h" | |
26 #include "psobjs.h" | |
27 | |
28 #include "psauxerr.h" | |
29 | |
30 /* ensure proper sign extension */ | |
31 #define Fix2Int( f ) ( (FT_Int)(FT_Short)( (f) >> 16 ) ) | |
32 | |
33 /*************************************************************************/ | |
34 /* */ | |
35 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ | |
36 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ | |
37 /* messages during execution. */ | |
38 /* */ | |
39 #undef FT_COMPONENT | |
40 #define FT_COMPONENT trace_t1decode | |
41 | |
42 | |
43 typedef enum T1_Operator_ | |
44 { | |
45 op_none = 0, | |
46 op_endchar, | |
47 op_hsbw, | |
48 op_seac, | |
49 op_sbw, | |
50 op_closepath, | |
51 op_hlineto, | |
52 op_hmoveto, | |
53 op_hvcurveto, | |
54 op_rlineto, | |
55 op_rmoveto, | |
56 op_rrcurveto, | |
57 op_vhcurveto, | |
58 op_vlineto, | |
59 op_vmoveto, | |
60 op_dotsection, | |
61 op_hstem, | |
62 op_hstem3, | |
63 op_vstem, | |
64 op_vstem3, | |
65 op_div, | |
66 op_callothersubr, | |
67 op_callsubr, | |
68 op_pop, | |
69 op_return, | |
70 op_setcurrentpoint, | |
71 op_unknown15, | |
72 | |
73 op_max /* never remove this one */ | |
74 | |
75 } T1_Operator; | |
76 | |
77 | |
78 static | |
79 const FT_Int t1_args_count[op_max] = | |
80 { | |
81 0, /* none */ | |
82 0, /* endchar */ | |
83 2, /* hsbw */ | |
84 5, /* seac */ | |
85 4, /* sbw */ | |
86 0, /* closepath */ | |
87 1, /* hlineto */ | |
88 1, /* hmoveto */ | |
89 4, /* hvcurveto */ | |
90 2, /* rlineto */ | |
91 2, /* rmoveto */ | |
92 6, /* rrcurveto */ | |
93 4, /* vhcurveto */ | |
94 1, /* vlineto */ | |
95 1, /* vmoveto */ | |
96 0, /* dotsection */ | |
97 2, /* hstem */ | |
98 6, /* hstem3 */ | |
99 2, /* vstem */ | |
100 6, /* vstem3 */ | |
101 2, /* div */ | |
102 -1, /* callothersubr */ | |
103 1, /* callsubr */ | |
104 0, /* pop */ | |
105 0, /* return */ | |
106 2, /* setcurrentpoint */ | |
107 2 /* opcode 15 (undocumented and obsolete) */ | |
108 }; | |
109 | |
110 | |
111 /*************************************************************************/ | |
112 /* */ | |
113 /* <Function> */ | |
114 /* t1_lookup_glyph_by_stdcharcode */ | |
115 /* */ | |
116 /* <Description> */ | |
117 /* Looks up a given glyph by its StandardEncoding charcode. Used to */ | |
118 /* implement the SEAC Type 1 operator. */ | |
119 /* */ | |
120 /* <Input> */ | |
121 /* face :: The current face object. */ | |
122 /* */ | |
123 /* charcode :: The character code to look for. */ | |
124 /* */ | |
125 /* <Return> */ | |
126 /* A glyph index in the font face. Returns -1 if the corresponding */ | |
127 /* glyph wasn't found. */ | |
128 /* */ | |
129 static FT_Int | |
130 t1_lookup_glyph_by_stdcharcode( T1_Decoder decoder, | |
131 FT_Int charcode ) | |
132 { | |
133 FT_UInt n; | |
134 const FT_String* glyph_name; | |
135 FT_Service_PsCMaps psnames = decoder->psnames; | |
136 | |
137 | |
138 /* check range of standard char code */ | |
139 if ( charcode < 0 || charcode > 255 ) | |
140 return -1; | |
141 | |
142 glyph_name = psnames->adobe_std_strings( | |
143 psnames->adobe_std_encoding[charcode]); | |
144 | |
145 for ( n = 0; n < decoder->num_glyphs; n++ ) | |
146 { | |
147 FT_String* name = (FT_String*)decoder->glyph_names[n]; | |
148 | |
149 | |
150 if ( name && | |
151 name[0] == glyph_name[0] && | |
152 ft_strcmp( name, glyph_name ) == 0 ) | |
153 return n; | |
154 } | |
155 | |
156 return -1; | |
157 } | |
158 | |
159 | |
160 /*************************************************************************/ | |
161 /* */ | |
162 /* <Function> */ | |
163 /* t1operator_seac */ | |
164 /* */ | |
165 /* <Description> */ | |
166 /* Implements the `seac' Type 1 operator for a Type 1 decoder. */ | |
167 /* */ | |
168 /* <Input> */ | |
169 /* decoder :: The current CID decoder. */ | |
170 /* */ | |
171 /* asb :: The accent's side bearing. */ | |
172 /* */ | |
173 /* adx :: The horizontal offset of the accent. */ | |
174 /* */ | |
175 /* ady :: The vertical offset of the accent. */ | |
176 /* */ | |
177 /* bchar :: The base character's StandardEncoding charcode. */ | |
178 /* */ | |
179 /* achar :: The accent character's StandardEncoding charcode. */ | |
180 /* */ | |
181 /* <Return> */ | |
182 /* FreeType error code. 0 means success. */ | |
183 /* */ | |
184 static FT_Error | |
185 t1operator_seac( T1_Decoder decoder, | |
186 FT_Pos asb, | |
187 FT_Pos adx, | |
188 FT_Pos ady, | |
189 FT_Int bchar, | |
190 FT_Int achar ) | |
191 { | |
192 FT_Error error; | |
193 FT_Int bchar_index, achar_index; | |
194 #if 0 | |
195 FT_Int n_base_points; | |
196 FT_Outline* base = decoder->builder.base; | |
197 #endif | |
198 FT_Vector left_bearing, advance; | |
199 | |
200 #ifdef FT_CONFIG_OPTION_INCREMENTAL | |
201 T1_Face face = (T1_Face)decoder->builder.face; | |
202 #endif | |
203 | |
204 | |
205 if ( decoder->seac ) | |
206 { | |
207 FT_ERROR(( "t1operator_seac: invalid nested seac\n" )); | |
208 return FT_THROW( Syntax_Error ); | |
209 } | |
210 | |
211 if ( decoder->builder.metrics_only ) | |
212 { | |
213 FT_ERROR(( "t1operator_seac: unexpected seac\n" )); | |
214 return FT_THROW( Syntax_Error ); | |
215 } | |
216 | |
217 /* seac weirdness */ | |
218 adx += decoder->builder.left_bearing.x; | |
219 | |
220 /* `glyph_names' is set to 0 for CID fonts which do not */ | |
221 /* include an encoding. How can we deal with these? */ | |
222 #ifdef FT_CONFIG_OPTION_INCREMENTAL | |
223 if ( decoder->glyph_names == 0 && | |
224 !face->root.internal->incremental_interface ) | |
225 #else | |
226 if ( decoder->glyph_names == 0 ) | |
227 #endif /* FT_CONFIG_OPTION_INCREMENTAL */ | |
228 { | |
229 FT_ERROR(( "t1operator_seac:" | |
230 " glyph names table not available in this font\n" )); | |
231 return FT_THROW( Syntax_Error ); | |
232 } | |
233 | |
234 #ifdef FT_CONFIG_OPTION_INCREMENTAL | |
235 if ( face->root.internal->incremental_interface ) | |
236 { | |
237 /* the caller must handle the font encoding also */ | |
238 bchar_index = bchar; | |
239 achar_index = achar; | |
240 } | |
241 else | |
242 #endif | |
243 { | |
244 bchar_index = t1_lookup_glyph_by_stdcharcode( decoder, bchar ); | |
245 achar_index = t1_lookup_glyph_by_stdcharcode( decoder, achar ); | |
246 } | |
247 | |
248 if ( bchar_index < 0 || achar_index < 0 ) | |
249 { | |
250 FT_ERROR(( "t1operator_seac:" | |
251 " invalid seac character code arguments\n" )); | |
252 return FT_THROW( Syntax_Error ); | |
253 } | |
254 | |
255 /* if we are trying to load a composite glyph, do not load the */ | |
256 /* accent character and return the array of subglyphs. */ | |
257 if ( decoder->builder.no_recurse ) | |
258 { | |
259 FT_GlyphSlot glyph = (FT_GlyphSlot)decoder->builder.glyph; | |
260 FT_GlyphLoader loader = glyph->internal->loader; | |
261 FT_SubGlyph subg; | |
262 | |
263 | |
264 /* reallocate subglyph array if necessary */ | |
265 error = FT_GlyphLoader_CheckSubGlyphs( loader, 2 ); | |
266 if ( error ) | |
267 goto Exit; | |
268 | |
269 subg = loader->current.subglyphs; | |
270 | |
271 /* subglyph 0 = base character */ | |
272 subg->index = bchar_index; | |
273 subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES | | |
274 FT_SUBGLYPH_FLAG_USE_MY_METRICS; | |
275 subg->arg1 = 0; | |
276 subg->arg2 = 0; | |
277 subg++; | |
278 | |
279 /* subglyph 1 = accent character */ | |
280 subg->index = achar_index; | |
281 subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES; | |
282 subg->arg1 = (FT_Int)FIXED_TO_INT( adx - asb ); | |
283 subg->arg2 = (FT_Int)FIXED_TO_INT( ady ); | |
284 | |
285 /* set up remaining glyph fields */ | |
286 glyph->num_subglyphs = 2; | |
287 glyph->subglyphs = loader->base.subglyphs; | |
288 glyph->format = FT_GLYPH_FORMAT_COMPOSITE; | |
289 | |
290 loader->current.num_subglyphs = 2; | |
291 goto Exit; | |
292 } | |
293 | |
294 /* First load `bchar' in builder */ | |
295 /* now load the unscaled outline */ | |
296 | |
297 FT_GlyphLoader_Prepare( decoder->builder.loader ); /* prepare loader */ | |
298 | |
299 /* the seac operator must not be nested */ | |
300 decoder->seac = TRUE; | |
301 error = t1_decoder_parse_glyph( decoder, bchar_index ); | |
302 decoder->seac = FALSE; | |
303 if ( error ) | |
304 goto Exit; | |
305 | |
306 /* save the left bearing and width of the base character */ | |
307 /* as they will be erased by the next load. */ | |
308 | |
309 left_bearing = decoder->builder.left_bearing; | |
310 advance = decoder->builder.advance; | |
311 | |
312 decoder->builder.left_bearing.x = 0; | |
313 decoder->builder.left_bearing.y = 0; | |
314 | |
315 decoder->builder.pos_x = adx - asb; | |
316 decoder->builder.pos_y = ady; | |
317 | |
318 /* Now load `achar' on top of */ | |
319 /* the base outline */ | |
320 | |
321 /* the seac operator must not be nested */ | |
322 decoder->seac = TRUE; | |
323 error = t1_decoder_parse_glyph( decoder, achar_index ); | |
324 decoder->seac = FALSE; | |
325 if ( error ) | |
326 goto Exit; | |
327 | |
328 /* restore the left side bearing and */ | |
329 /* advance width of the base character */ | |
330 | |
331 decoder->builder.left_bearing = left_bearing; | |
332 decoder->builder.advance = advance; | |
333 | |
334 decoder->builder.pos_x = 0; | |
335 decoder->builder.pos_y = 0; | |
336 | |
337 Exit: | |
338 return error; | |
339 } | |
340 | |
341 | |
342 /*************************************************************************/ | |
343 /* */ | |
344 /* <Function> */ | |
345 /* t1_decoder_parse_charstrings */ | |
346 /* */ | |
347 /* <Description> */ | |
348 /* Parses a given Type 1 charstrings program. */ | |
349 /* */ | |
350 /* <Input> */ | |
351 /* decoder :: The current Type 1 decoder. */ | |
352 /* */ | |
353 /* charstring_base :: The base address of the charstring stream. */ | |
354 /* */ | |
355 /* charstring_len :: The length in bytes of the charstring stream. */ | |
356 /* */ | |
357 /* <Return> */ | |
358 /* FreeType error code. 0 means success. */ | |
359 /* */ | |
360 FT_LOCAL_DEF( FT_Error ) | |
361 t1_decoder_parse_charstrings( T1_Decoder decoder, | |
362 FT_Byte* charstring_base, | |
363 FT_UInt charstring_len ) | |
364 { | |
365 FT_Error error; | |
366 T1_Decoder_Zone zone; | |
367 FT_Byte* ip; | |
368 FT_Byte* limit; | |
369 T1_Builder builder = &decoder->builder; | |
370 FT_Pos x, y, orig_x, orig_y; | |
371 FT_Int known_othersubr_result_cnt = 0; | |
372 FT_Int unknown_othersubr_result_cnt = 0; | |
373 FT_Bool large_int; | |
374 FT_Fixed seed; | |
375 | |
376 T1_Hints_Funcs hinter; | |
377 | |
378 #ifdef FT_DEBUG_LEVEL_TRACE | |
379 FT_Bool bol = TRUE; | |
380 #endif | |
381 | |
382 | |
383 /* compute random seed from stack address of parameter */ | |
384 seed = (FT_Fixed)( ( (FT_PtrDist)(char*)&seed ^ | |
385 (FT_PtrDist)(char*)&decoder ^ | |
386 (FT_PtrDist)(char*)&charstring_base ) & | |
387 FT_ULONG_MAX ) ; | |
388 seed = ( seed ^ ( seed >> 10 ) ^ ( seed >> 20 ) ) & 0xFFFFL; | |
389 if ( seed == 0 ) | |
390 seed = 0x7384; | |
391 | |
392 /* First of all, initialize the decoder */ | |
393 decoder->top = decoder->stack; | |
394 decoder->zone = decoder->zones; | |
395 zone = decoder->zones; | |
396 | |
397 builder->parse_state = T1_Parse_Start; | |
398 | |
399 hinter = (T1_Hints_Funcs)builder->hints_funcs; | |
400 | |
401 /* a font that reads BuildCharArray without setting */ | |
402 /* its values first is buggy, but ... */ | |
403 FT_ASSERT( ( decoder->len_buildchar == 0 ) == | |
404 ( decoder->buildchar == NULL ) ); | |
405 | |
406 if ( decoder->buildchar && decoder->len_buildchar > 0 ) | |
407 ft_memset( &decoder->buildchar[0], | |
408 0, | |
409 sizeof ( decoder->buildchar[0] ) * decoder->len_buildchar ); | |
410 | |
411 FT_TRACE4(( "\n" | |
412 "Start charstring\n" )); | |
413 | |
414 zone->base = charstring_base; | |
415 limit = zone->limit = charstring_base + charstring_len; | |
416 ip = zone->cursor = zone->base; | |
417 | |
418 error = FT_Err_Ok; | |
419 | |
420 x = orig_x = builder->pos_x; | |
421 y = orig_y = builder->pos_y; | |
422 | |
423 /* begin hints recording session, if any */ | |
424 if ( hinter ) | |
425 hinter->open( hinter->hints ); | |
426 | |
427 large_int = FALSE; | |
428 | |
429 /* now, execute loop */ | |
430 while ( ip < limit ) | |
431 { | |
432 FT_Long* top = decoder->top; | |
433 T1_Operator op = op_none; | |
434 FT_Int32 value = 0; | |
435 | |
436 | |
437 FT_ASSERT( known_othersubr_result_cnt == 0 || | |
438 unknown_othersubr_result_cnt == 0 ); | |
439 | |
440 #ifdef FT_DEBUG_LEVEL_TRACE | |
441 if ( bol ) | |
442 { | |
443 FT_TRACE5(( " (%d)", decoder->top - decoder->stack )); | |
444 bol = FALSE; | |
445 } | |
446 #endif | |
447 | |
448 /*********************************************************************/ | |
449 /* */ | |
450 /* Decode operator or operand */ | |
451 /* */ | |
452 /* */ | |
453 | |
454 /* first of all, decompress operator or value */ | |
455 switch ( *ip++ ) | |
456 { | |
457 case 1: | |
458 op = op_hstem; | |
459 break; | |
460 | |
461 case 3: | |
462 op = op_vstem; | |
463 break; | |
464 case 4: | |
465 op = op_vmoveto; | |
466 break; | |
467 case 5: | |
468 op = op_rlineto; | |
469 break; | |
470 case 6: | |
471 op = op_hlineto; | |
472 break; | |
473 case 7: | |
474 op = op_vlineto; | |
475 break; | |
476 case 8: | |
477 op = op_rrcurveto; | |
478 break; | |
479 case 9: | |
480 op = op_closepath; | |
481 break; | |
482 case 10: | |
483 op = op_callsubr; | |
484 break; | |
485 case 11: | |
486 op = op_return; | |
487 break; | |
488 | |
489 case 13: | |
490 op = op_hsbw; | |
491 break; | |
492 case 14: | |
493 op = op_endchar; | |
494 break; | |
495 | |
496 case 15: /* undocumented, obsolete operator */ | |
497 op = op_unknown15; | |
498 break; | |
499 | |
500 case 21: | |
501 op = op_rmoveto; | |
502 break; | |
503 case 22: | |
504 op = op_hmoveto; | |
505 break; | |
506 | |
507 case 30: | |
508 op = op_vhcurveto; | |
509 break; | |
510 case 31: | |
511 op = op_hvcurveto; | |
512 break; | |
513 | |
514 case 12: | |
515 if ( ip > limit ) | |
516 { | |
517 FT_ERROR(( "t1_decoder_parse_charstrings:" | |
518 " invalid escape (12+EOF)\n" )); | |
519 goto Syntax_Error; | |
520 } | |
521 | |
522 switch ( *ip++ ) | |
523 { | |
524 case 0: | |
525 op = op_dotsection; | |
526 break; | |
527 case 1: | |
528 op = op_vstem3; | |
529 break; | |
530 case 2: | |
531 op = op_hstem3; | |
532 break; | |
533 case 6: | |
534 op = op_seac; | |
535 break; | |
536 case 7: | |
537 op = op_sbw; | |
538 break; | |
539 case 12: | |
540 op = op_div; | |
541 break; | |
542 case 16: | |
543 op = op_callothersubr; | |
544 break; | |
545 case 17: | |
546 op = op_pop; | |
547 break; | |
548 case 33: | |
549 op = op_setcurrentpoint; | |
550 break; | |
551 | |
552 default: | |
553 FT_ERROR(( "t1_decoder_parse_charstrings:" | |
554 " invalid escape (12+%d)\n", | |
555 ip[-1] )); | |
556 goto Syntax_Error; | |
557 } | |
558 break; | |
559 | |
560 case 255: /* four bytes integer */ | |
561 if ( ip + 4 > limit ) | |
562 { | |
563 FT_ERROR(( "t1_decoder_parse_charstrings:" | |
564 " unexpected EOF in integer\n" )); | |
565 goto Syntax_Error; | |
566 } | |
567 | |
568 value = (FT_Int32)( ( (FT_UInt32)ip[0] << 24 ) | | |
569 ( (FT_UInt32)ip[1] << 16 ) | | |
570 ( (FT_UInt32)ip[2] << 8 ) | | |
571 (FT_UInt32)ip[3] ); | |
572 ip += 4; | |
573 | |
574 /* According to the specification, values > 32000 or < -32000 must */ | |
575 /* be followed by a `div' operator to make the result be in the */ | |
576 /* range [-32000;32000]. We expect that the second argument of */ | |
577 /* `div' is not a large number. Additionally, we don't handle */ | |
578 /* stuff like `<large1> <large2> <num> div <num> div' or */ | |
579 /* <large1> <large2> <num> div div'. This is probably not allowed */ | |
580 /* anyway. */ | |
581 if ( value > 32000 || value < -32000 ) | |
582 { | |
583 if ( large_int ) | |
584 { | |
585 FT_ERROR(( "t1_decoder_parse_charstrings:" | |
586 " no `div' after large integer\n" )); | |
587 } | |
588 else | |
589 large_int = TRUE; | |
590 } | |
591 else | |
592 { | |
593 if ( !large_int ) | |
594 value = (FT_Int32)( (FT_UInt32)value << 16 ); | |
595 } | |
596 | |
597 break; | |
598 | |
599 default: | |
600 if ( ip[-1] >= 32 ) | |
601 { | |
602 if ( ip[-1] < 247 ) | |
603 value = (FT_Int32)ip[-1] - 139; | |
604 else | |
605 { | |
606 if ( ++ip > limit ) | |
607 { | |
608 FT_ERROR(( "t1_decoder_parse_charstrings:" | |
609 " unexpected EOF in integer\n" )); | |
610 goto Syntax_Error; | |
611 } | |
612 | |
613 if ( ip[-2] < 251 ) | |
614 value = ( ( ip[-2] - 247 ) * 256 ) + ip[-1] + 108; | |
615 else | |
616 value = -( ( ( ip[-2] - 251 ) * 256 ) + ip[-1] + 108 ); | |
617 } | |
618 | |
619 if ( !large_int ) | |
620 value = (FT_Int32)( (FT_UInt32)value << 16 ); | |
621 } | |
622 else | |
623 { | |
624 FT_ERROR(( "t1_decoder_parse_charstrings:" | |
625 " invalid byte (%d)\n", ip[-1] )); | |
626 goto Syntax_Error; | |
627 } | |
628 } | |
629 | |
630 if ( unknown_othersubr_result_cnt > 0 ) | |
631 { | |
632 switch ( op ) | |
633 { | |
634 case op_callsubr: | |
635 case op_return: | |
636 case op_none: | |
637 case op_pop: | |
638 break; | |
639 | |
640 default: | |
641 /* all operands have been transferred by previous pops */ | |
642 unknown_othersubr_result_cnt = 0; | |
643 break; | |
644 } | |
645 } | |
646 | |
647 if ( large_int && !( op == op_none || op == op_div ) ) | |
648 { | |
649 FT_ERROR(( "t1_decoder_parse_charstrings:" | |
650 " no `div' after large integer\n" )); | |
651 | |
652 large_int = FALSE; | |
653 } | |
654 | |
655 /*********************************************************************/ | |
656 /* */ | |
657 /* Push value on stack, or process operator */ | |
658 /* */ | |
659 /* */ | |
660 if ( op == op_none ) | |
661 { | |
662 if ( top - decoder->stack >= T1_MAX_CHARSTRINGS_OPERANDS ) | |
663 { | |
664 FT_ERROR(( "t1_decoder_parse_charstrings: stack overflow\n" )); | |
665 goto Syntax_Error; | |
666 } | |
667 | |
668 #ifdef FT_DEBUG_LEVEL_TRACE | |
669 if ( large_int ) | |
670 FT_TRACE4(( " %ld", value )); | |
671 else | |
672 FT_TRACE4(( " %ld", Fix2Int( value ) )); | |
673 #endif | |
674 | |
675 *top++ = value; | |
676 decoder->top = top; | |
677 } | |
678 else if ( op == op_callothersubr ) /* callothersubr */ | |
679 { | |
680 FT_Int subr_no; | |
681 FT_Int arg_cnt; | |
682 | |
683 | |
684 #ifdef FT_DEBUG_LEVEL_TRACE | |
685 FT_TRACE4(( " callothersubr\n" )); | |
686 bol = TRUE; | |
687 #endif | |
688 | |
689 if ( top - decoder->stack < 2 ) | |
690 goto Stack_Underflow; | |
691 | |
692 top -= 2; | |
693 | |
694 subr_no = Fix2Int( top[1] ); | |
695 arg_cnt = Fix2Int( top[0] ); | |
696 | |
697 /***********************************************************/ | |
698 /* */ | |
699 /* remove all operands to callothersubr from the stack */ | |
700 /* */ | |
701 /* for handled othersubrs, where we know the number of */ | |
702 /* arguments, we increase the stack by the value of */ | |
703 /* known_othersubr_result_cnt */ | |
704 /* */ | |
705 /* for unhandled othersubrs the following pops adjust the */ | |
706 /* stack pointer as necessary */ | |
707 | |
708 if ( arg_cnt > top - decoder->stack ) | |
709 goto Stack_Underflow; | |
710 | |
711 top -= arg_cnt; | |
712 | |
713 known_othersubr_result_cnt = 0; | |
714 unknown_othersubr_result_cnt = 0; | |
715 | |
716 /* XXX TODO: The checks to `arg_count == <whatever>' */ | |
717 /* might not be correct; an othersubr expects a certain */ | |
718 /* number of operands on the PostScript stack (as opposed */ | |
719 /* to the T1 stack) but it doesn't have to put them there */ | |
720 /* by itself; previous othersubrs might have left the */ | |
721 /* operands there if they were not followed by an */ | |
722 /* appropriate number of pops */ | |
723 /* */ | |
724 /* On the other hand, Adobe Reader 7.0.8 for Linux doesn't */ | |
725 /* accept a font that contains charstrings like */ | |
726 /* */ | |
727 /* 100 200 2 20 callothersubr */ | |
728 /* 300 1 20 callothersubr pop */ | |
729 /* */ | |
730 /* Perhaps this is the reason why BuildCharArray exists. */ | |
731 | |
732 switch ( subr_no ) | |
733 { | |
734 case 0: /* end flex feature */ | |
735 if ( arg_cnt != 3 ) | |
736 goto Unexpected_OtherSubr; | |
737 | |
738 if ( decoder->flex_state == 0 || | |
739 decoder->num_flex_vectors != 7 ) | |
740 { | |
741 FT_ERROR(( "t1_decoder_parse_charstrings:" | |
742 " unexpected flex end\n" )); | |
743 goto Syntax_Error; | |
744 } | |
745 | |
746 /* the two `results' are popped by the following setcurrentpoint */ | |
747 top[0] = x; | |
748 top[1] = y; | |
749 known_othersubr_result_cnt = 2; | |
750 break; | |
751 | |
752 case 1: /* start flex feature */ | |
753 if ( arg_cnt != 0 ) | |
754 goto Unexpected_OtherSubr; | |
755 | |
756 decoder->flex_state = 1; | |
757 decoder->num_flex_vectors = 0; | |
758 if ( ( error = t1_builder_start_point( builder, x, y ) ) | |
759 != FT_Err_Ok || | |
760 ( error = t1_builder_check_points( builder, 6 ) ) | |
761 != FT_Err_Ok ) | |
762 goto Fail; | |
763 break; | |
764 | |
765 case 2: /* add flex vectors */ | |
766 { | |
767 FT_Int idx; | |
768 | |
769 | |
770 if ( arg_cnt != 0 ) | |
771 goto Unexpected_OtherSubr; | |
772 | |
773 if ( decoder->flex_state == 0 ) | |
774 { | |
775 FT_ERROR(( "t1_decoder_parse_charstrings:" | |
776 " missing flex start\n" )); | |
777 goto Syntax_Error; | |
778 } | |
779 | |
780 /* note that we should not add a point for index 0; */ | |
781 /* this will move our current position to the flex */ | |
782 /* point without adding any point to the outline */ | |
783 idx = decoder->num_flex_vectors++; | |
784 if ( idx > 0 && idx < 7 ) | |
785 t1_builder_add_point( builder, | |
786 x, | |
787 y, | |
788 (FT_Byte)( idx == 3 || idx == 6 ) ); | |
789 } | |
790 break; | |
791 | |
792 case 3: /* change hints */ | |
793 if ( arg_cnt != 1 ) | |
794 goto Unexpected_OtherSubr; | |
795 | |
796 known_othersubr_result_cnt = 1; | |
797 | |
798 if ( hinter ) | |
799 hinter->reset( hinter->hints, builder->current->n_points ); | |
800 break; | |
801 | |
802 case 12: | |
803 case 13: | |
804 /* counter control hints, clear stack */ | |
805 top = decoder->stack; | |
806 break; | |
807 | |
808 case 14: | |
809 case 15: | |
810 case 16: | |
811 case 17: | |
812 case 18: /* multiple masters */ | |
813 { | |
814 PS_Blend blend = decoder->blend; | |
815 FT_UInt num_points, nn, mm; | |
816 FT_Long* delta; | |
817 FT_Long* values; | |
818 | |
819 | |
820 if ( !blend ) | |
821 { | |
822 FT_ERROR(( "t1_decoder_parse_charstrings:" | |
823 " unexpected multiple masters operator\n" )); | |
824 goto Syntax_Error; | |
825 } | |
826 | |
827 num_points = (FT_UInt)subr_no - 13 + ( subr_no == 18 ); | |
828 if ( arg_cnt != (FT_Int)( num_points * blend->num_designs ) ) | |
829 { | |
830 FT_ERROR(( "t1_decoder_parse_charstrings:" | |
831 " incorrect number of multiple masters arguments\n" )); | |
832 goto Syntax_Error; | |
833 } | |
834 | |
835 /* We want to compute */ | |
836 /* */ | |
837 /* a0*w0 + a1*w1 + ... + ak*wk */ | |
838 /* */ | |
839 /* but we only have a0, a1-a0, a2-a0, ..., ak-a0. */ | |
840 /* */ | |
841 /* However, given that w0 + w1 + ... + wk == 1, we can */ | |
842 /* rewrite it easily as */ | |
843 /* */ | |
844 /* a0 + (a1-a0)*w1 + (a2-a0)*w2 + ... + (ak-a0)*wk */ | |
845 /* */ | |
846 /* where k == num_designs-1. */ | |
847 /* */ | |
848 /* I guess that's why it's written in this `compact' */ | |
849 /* form. */ | |
850 /* */ | |
851 delta = top + num_points; | |
852 values = top; | |
853 for ( nn = 0; nn < num_points; nn++ ) | |
854 { | |
855 FT_Long tmp = values[0]; | |
856 | |
857 | |
858 for ( mm = 1; mm < blend->num_designs; mm++ ) | |
859 tmp += FT_MulFix( *delta++, blend->weight_vector[mm] ); | |
860 | |
861 *values++ = tmp; | |
862 } | |
863 | |
864 known_othersubr_result_cnt = num_points; | |
865 break; | |
866 } | |
867 | |
868 case 19: | |
869 /* <idx> 1 19 callothersubr */ | |
870 /* => replace elements starting from index cvi( <idx> ) */ | |
871 /* of BuildCharArray with WeightVector */ | |
872 { | |
873 FT_Int idx; | |
874 PS_Blend blend = decoder->blend; | |
875 | |
876 | |
877 if ( arg_cnt != 1 || blend == NULL ) | |
878 goto Unexpected_OtherSubr; | |
879 | |
880 idx = Fix2Int( top[0] ); | |
881 | |
882 if ( idx < 0 || | |
883 idx + blend->num_designs > decoder->len_buildchar ) | |
884 goto Unexpected_OtherSubr; | |
885 | |
886 ft_memcpy( &decoder->buildchar[idx], | |
887 blend->weight_vector, | |
888 blend->num_designs * | |
889 sizeof ( blend->weight_vector[0] ) ); | |
890 } | |
891 break; | |
892 | |
893 case 20: | |
894 /* <arg1> <arg2> 2 20 callothersubr pop */ | |
895 /* ==> push <arg1> + <arg2> onto T1 stack */ | |
896 if ( arg_cnt != 2 ) | |
897 goto Unexpected_OtherSubr; | |
898 | |
899 top[0] += top[1]; /* XXX (over|under)flow */ | |
900 | |
901 known_othersubr_result_cnt = 1; | |
902 break; | |
903 | |
904 case 21: | |
905 /* <arg1> <arg2> 2 21 callothersubr pop */ | |
906 /* ==> push <arg1> - <arg2> onto T1 stack */ | |
907 if ( arg_cnt != 2 ) | |
908 goto Unexpected_OtherSubr; | |
909 | |
910 top[0] -= top[1]; /* XXX (over|under)flow */ | |
911 | |
912 known_othersubr_result_cnt = 1; | |
913 break; | |
914 | |
915 case 22: | |
916 /* <arg1> <arg2> 2 22 callothersubr pop */ | |
917 /* ==> push <arg1> * <arg2> onto T1 stack */ | |
918 if ( arg_cnt != 2 ) | |
919 goto Unexpected_OtherSubr; | |
920 | |
921 top[0] = FT_MulFix( top[0], top[1] ); | |
922 | |
923 known_othersubr_result_cnt = 1; | |
924 break; | |
925 | |
926 case 23: | |
927 /* <arg1> <arg2> 2 23 callothersubr pop */ | |
928 /* ==> push <arg1> / <arg2> onto T1 stack */ | |
929 if ( arg_cnt != 2 || top[1] == 0 ) | |
930 goto Unexpected_OtherSubr; | |
931 | |
932 top[0] = FT_DivFix( top[0], top[1] ); | |
933 | |
934 known_othersubr_result_cnt = 1; | |
935 break; | |
936 | |
937 case 24: | |
938 /* <val> <idx> 2 24 callothersubr */ | |
939 /* ==> set BuildCharArray[cvi( <idx> )] = <val> */ | |
940 { | |
941 FT_Int idx; | |
942 PS_Blend blend = decoder->blend; | |
943 | |
944 | |
945 if ( arg_cnt != 2 || blend == NULL ) | |
946 goto Unexpected_OtherSubr; | |
947 | |
948 idx = Fix2Int( top[1] ); | |
949 | |
950 if ( idx < 0 || (FT_UInt) idx >= decoder->len_buildchar ) | |
951 goto Unexpected_OtherSubr; | |
952 | |
953 decoder->buildchar[idx] = top[0]; | |
954 } | |
955 break; | |
956 | |
957 case 25: | |
958 /* <idx> 1 25 callothersubr pop */ | |
959 /* ==> push BuildCharArray[cvi( idx )] */ | |
960 /* onto T1 stack */ | |
961 { | |
962 FT_Int idx; | |
963 PS_Blend blend = decoder->blend; | |
964 | |
965 | |
966 if ( arg_cnt != 1 || blend == NULL ) | |
967 goto Unexpected_OtherSubr; | |
968 | |
969 idx = Fix2Int( top[0] ); | |
970 | |
971 if ( idx < 0 || (FT_UInt) idx >= decoder->len_buildchar ) | |
972 goto Unexpected_OtherSubr; | |
973 | |
974 top[0] = decoder->buildchar[idx]; | |
975 } | |
976 | |
977 known_othersubr_result_cnt = 1; | |
978 break; | |
979 | |
980 #if 0 | |
981 case 26: | |
982 /* <val> mark <idx> ==> set BuildCharArray[cvi( <idx> )] = <val>, */ | |
983 /* leave mark on T1 stack */ | |
984 /* <val> <idx> ==> set BuildCharArray[cvi( <idx> )] = <val> */ | |
985 XXX which routine has left its mark on the (PostScript) stack?; | |
986 break; | |
987 #endif | |
988 | |
989 case 27: | |
990 /* <res1> <res2> <val1> <val2> 4 27 callothersubr pop */ | |
991 /* ==> push <res1> onto T1 stack if <val1> <= <val2>, */ | |
992 /* otherwise push <res2> */ | |
993 if ( arg_cnt != 4 ) | |
994 goto Unexpected_OtherSubr; | |
995 | |
996 if ( top[2] > top[3] ) | |
997 top[0] = top[1]; | |
998 | |
999 known_othersubr_result_cnt = 1; | |
1000 break; | |
1001 | |
1002 case 28: | |
1003 /* 0 28 callothersubr pop */ | |
1004 /* => push random value from interval [0, 1) onto stack */ | |
1005 if ( arg_cnt != 0 ) | |
1006 goto Unexpected_OtherSubr; | |
1007 | |
1008 { | |
1009 FT_Fixed Rand; | |
1010 | |
1011 | |
1012 Rand = seed; | |
1013 if ( Rand >= 0x8000L ) | |
1014 Rand++; | |
1015 | |
1016 top[0] = Rand; | |
1017 | |
1018 seed = FT_MulFix( seed, 0x10000L - seed ); | |
1019 if ( seed == 0 ) | |
1020 seed += 0x2873; | |
1021 } | |
1022 | |
1023 known_othersubr_result_cnt = 1; | |
1024 break; | |
1025 | |
1026 default: | |
1027 if ( arg_cnt >= 0 && subr_no >= 0 ) | |
1028 { | |
1029 FT_ERROR(( "t1_decoder_parse_charstrings:" | |
1030 " unknown othersubr [%d %d], wish me luck\n", | |
1031 arg_cnt, subr_no )); | |
1032 unknown_othersubr_result_cnt = arg_cnt; | |
1033 break; | |
1034 } | |
1035 /* fall through */ | |
1036 | |
1037 Unexpected_OtherSubr: | |
1038 FT_ERROR(( "t1_decoder_parse_charstrings:" | |
1039 " invalid othersubr [%d %d]\n", arg_cnt, subr_no )); | |
1040 goto Syntax_Error; | |
1041 } | |
1042 | |
1043 top += known_othersubr_result_cnt; | |
1044 | |
1045 decoder->top = top; | |
1046 } | |
1047 else /* general operator */ | |
1048 { | |
1049 FT_Int num_args = t1_args_count[op]; | |
1050 | |
1051 | |
1052 FT_ASSERT( num_args >= 0 ); | |
1053 | |
1054 if ( top - decoder->stack < num_args ) | |
1055 goto Stack_Underflow; | |
1056 | |
1057 /* XXX Operators usually take their operands from the */ | |
1058 /* bottom of the stack, i.e., the operands are */ | |
1059 /* decoder->stack[0], ..., decoder->stack[num_args - 1]; */ | |
1060 /* only div, callsubr, and callothersubr are different. */ | |
1061 /* In practice it doesn't matter (?). */ | |
1062 | |
1063 #ifdef FT_DEBUG_LEVEL_TRACE | |
1064 | |
1065 switch ( op ) | |
1066 { | |
1067 case op_callsubr: | |
1068 case op_div: | |
1069 case op_callothersubr: | |
1070 case op_pop: | |
1071 case op_return: | |
1072 break; | |
1073 | |
1074 default: | |
1075 if ( top - decoder->stack != num_args ) | |
1076 FT_TRACE0(( "t1_decoder_parse_charstrings:" | |
1077 " too much operands on the stack" | |
1078 " (seen %d, expected %d)\n", | |
1079 top - decoder->stack, num_args )); | |
1080 break; | |
1081 } | |
1082 | |
1083 #endif /* FT_DEBUG_LEVEL_TRACE */ | |
1084 | |
1085 top -= num_args; | |
1086 | |
1087 switch ( op ) | |
1088 { | |
1089 case op_endchar: | |
1090 FT_TRACE4(( " endchar\n" )); | |
1091 | |
1092 t1_builder_close_contour( builder ); | |
1093 | |
1094 /* close hints recording session */ | |
1095 if ( hinter ) | |
1096 { | |
1097 if ( hinter->close( hinter->hints, builder->current->n_points ) ) | |
1098 goto Syntax_Error; | |
1099 | |
1100 /* apply hints to the loaded glyph outline now */ | |
1101 hinter->apply( hinter->hints, | |
1102 builder->current, | |
1103 (PSH_Globals)builder->hints_globals, | |
1104 decoder->hint_mode ); | |
1105 } | |
1106 | |
1107 /* add current outline to the glyph slot */ | |
1108 FT_GlyphLoader_Add( builder->loader ); | |
1109 | |
1110 /* the compiler should optimize away this empty loop but ... */ | |
1111 | |
1112 #ifdef FT_DEBUG_LEVEL_TRACE | |
1113 | |
1114 if ( decoder->len_buildchar > 0 ) | |
1115 { | |
1116 FT_UInt i; | |
1117 | |
1118 | |
1119 FT_TRACE4(( "BuildCharArray = [ " )); | |
1120 | |
1121 for ( i = 0; i < decoder->len_buildchar; ++i ) | |
1122 FT_TRACE4(( "%d ", decoder->buildchar[i] )); | |
1123 | |
1124 FT_TRACE4(( "]\n" )); | |
1125 } | |
1126 | |
1127 #endif /* FT_DEBUG_LEVEL_TRACE */ | |
1128 | |
1129 FT_TRACE4(( "\n" )); | |
1130 | |
1131 /* return now! */ | |
1132 return FT_Err_Ok; | |
1133 | |
1134 case op_hsbw: | |
1135 FT_TRACE4(( " hsbw" )); | |
1136 | |
1137 builder->parse_state = T1_Parse_Have_Width; | |
1138 | |
1139 builder->left_bearing.x += top[0]; | |
1140 builder->advance.x = top[1]; | |
1141 builder->advance.y = 0; | |
1142 | |
1143 orig_x = x = builder->pos_x + top[0]; | |
1144 orig_y = y = builder->pos_y; | |
1145 | |
1146 FT_UNUSED( orig_y ); | |
1147 | |
1148 /* the `metrics_only' indicates that we only want to compute */ | |
1149 /* the glyph's metrics (lsb + advance width), not load the */ | |
1150 /* rest of it; so exit immediately */ | |
1151 if ( builder->metrics_only ) | |
1152 return FT_Err_Ok; | |
1153 | |
1154 break; | |
1155 | |
1156 case op_seac: | |
1157 return t1operator_seac( decoder, | |
1158 top[0], | |
1159 top[1], | |
1160 top[2], | |
1161 Fix2Int( top[3] ), | |
1162 Fix2Int( top[4] ) ); | |
1163 | |
1164 case op_sbw: | |
1165 FT_TRACE4(( " sbw" )); | |
1166 | |
1167 builder->parse_state = T1_Parse_Have_Width; | |
1168 | |
1169 builder->left_bearing.x += top[0]; | |
1170 builder->left_bearing.y += top[1]; | |
1171 builder->advance.x = top[2]; | |
1172 builder->advance.y = top[3]; | |
1173 | |
1174 x = builder->pos_x + top[0]; | |
1175 y = builder->pos_y + top[1]; | |
1176 | |
1177 /* the `metrics_only' indicates that we only want to compute */ | |
1178 /* the glyph's metrics (lsb + advance width), not load the */ | |
1179 /* rest of it; so exit immediately */ | |
1180 if ( builder->metrics_only ) | |
1181 return FT_Err_Ok; | |
1182 | |
1183 break; | |
1184 | |
1185 case op_closepath: | |
1186 FT_TRACE4(( " closepath" )); | |
1187 | |
1188 /* if there is no path, `closepath' is a no-op */ | |
1189 if ( builder->parse_state == T1_Parse_Have_Path || | |
1190 builder->parse_state == T1_Parse_Have_Moveto ) | |
1191 t1_builder_close_contour( builder ); | |
1192 | |
1193 builder->parse_state = T1_Parse_Have_Width; | |
1194 break; | |
1195 | |
1196 case op_hlineto: | |
1197 FT_TRACE4(( " hlineto" )); | |
1198 | |
1199 if ( ( error = t1_builder_start_point( builder, x, y ) ) | |
1200 != FT_Err_Ok ) | |
1201 goto Fail; | |
1202 | |
1203 x += top[0]; | |
1204 goto Add_Line; | |
1205 | |
1206 case op_hmoveto: | |
1207 FT_TRACE4(( " hmoveto" )); | |
1208 | |
1209 x += top[0]; | |
1210 if ( !decoder->flex_state ) | |
1211 { | |
1212 if ( builder->parse_state == T1_Parse_Start ) | |
1213 goto Syntax_Error; | |
1214 builder->parse_state = T1_Parse_Have_Moveto; | |
1215 } | |
1216 break; | |
1217 | |
1218 case op_hvcurveto: | |
1219 FT_TRACE4(( " hvcurveto" )); | |
1220 | |
1221 if ( ( error = t1_builder_start_point( builder, x, y ) ) | |
1222 != FT_Err_Ok || | |
1223 ( error = t1_builder_check_points( builder, 3 ) ) | |
1224 != FT_Err_Ok ) | |
1225 goto Fail; | |
1226 | |
1227 x += top[0]; | |
1228 t1_builder_add_point( builder, x, y, 0 ); | |
1229 x += top[1]; | |
1230 y += top[2]; | |
1231 t1_builder_add_point( builder, x, y, 0 ); | |
1232 y += top[3]; | |
1233 t1_builder_add_point( builder, x, y, 1 ); | |
1234 break; | |
1235 | |
1236 case op_rlineto: | |
1237 FT_TRACE4(( " rlineto" )); | |
1238 | |
1239 if ( ( error = t1_builder_start_point( builder, x, y ) ) | |
1240 != FT_Err_Ok ) | |
1241 goto Fail; | |
1242 | |
1243 x += top[0]; | |
1244 y += top[1]; | |
1245 | |
1246 Add_Line: | |
1247 if ( ( error = t1_builder_add_point1( builder, x, y ) ) | |
1248 != FT_Err_Ok ) | |
1249 goto Fail; | |
1250 break; | |
1251 | |
1252 case op_rmoveto: | |
1253 FT_TRACE4(( " rmoveto" )); | |
1254 | |
1255 x += top[0]; | |
1256 y += top[1]; | |
1257 if ( !decoder->flex_state ) | |
1258 { | |
1259 if ( builder->parse_state == T1_Parse_Start ) | |
1260 goto Syntax_Error; | |
1261 builder->parse_state = T1_Parse_Have_Moveto; | |
1262 } | |
1263 break; | |
1264 | |
1265 case op_rrcurveto: | |
1266 FT_TRACE4(( " rrcurveto" )); | |
1267 | |
1268 if ( ( error = t1_builder_start_point( builder, x, y ) ) | |
1269 != FT_Err_Ok || | |
1270 ( error = t1_builder_check_points( builder, 3 ) ) | |
1271 != FT_Err_Ok ) | |
1272 goto Fail; | |
1273 | |
1274 x += top[0]; | |
1275 y += top[1]; | |
1276 t1_builder_add_point( builder, x, y, 0 ); | |
1277 | |
1278 x += top[2]; | |
1279 y += top[3]; | |
1280 t1_builder_add_point( builder, x, y, 0 ); | |
1281 | |
1282 x += top[4]; | |
1283 y += top[5]; | |
1284 t1_builder_add_point( builder, x, y, 1 ); | |
1285 break; | |
1286 | |
1287 case op_vhcurveto: | |
1288 FT_TRACE4(( " vhcurveto" )); | |
1289 | |
1290 if ( ( error = t1_builder_start_point( builder, x, y ) ) | |
1291 != FT_Err_Ok || | |
1292 ( error = t1_builder_check_points( builder, 3 ) ) | |
1293 != FT_Err_Ok ) | |
1294 goto Fail; | |
1295 | |
1296 y += top[0]; | |
1297 t1_builder_add_point( builder, x, y, 0 ); | |
1298 x += top[1]; | |
1299 y += top[2]; | |
1300 t1_builder_add_point( builder, x, y, 0 ); | |
1301 x += top[3]; | |
1302 t1_builder_add_point( builder, x, y, 1 ); | |
1303 break; | |
1304 | |
1305 case op_vlineto: | |
1306 FT_TRACE4(( " vlineto" )); | |
1307 | |
1308 if ( ( error = t1_builder_start_point( builder, x, y ) ) | |
1309 != FT_Err_Ok ) | |
1310 goto Fail; | |
1311 | |
1312 y += top[0]; | |
1313 goto Add_Line; | |
1314 | |
1315 case op_vmoveto: | |
1316 FT_TRACE4(( " vmoveto" )); | |
1317 | |
1318 y += top[0]; | |
1319 if ( !decoder->flex_state ) | |
1320 { | |
1321 if ( builder->parse_state == T1_Parse_Start ) | |
1322 goto Syntax_Error; | |
1323 builder->parse_state = T1_Parse_Have_Moveto; | |
1324 } | |
1325 break; | |
1326 | |
1327 case op_div: | |
1328 FT_TRACE4(( " div" )); | |
1329 | |
1330 /* if `large_int' is set, we divide unscaled numbers; */ | |
1331 /* otherwise, we divide numbers in 16.16 format -- */ | |
1332 /* in both cases, it is the same operation */ | |
1333 *top = FT_DivFix( top[0], top[1] ); | |
1334 ++top; | |
1335 | |
1336 large_int = FALSE; | |
1337 break; | |
1338 | |
1339 case op_callsubr: | |
1340 { | |
1341 FT_Int idx; | |
1342 | |
1343 | |
1344 FT_TRACE4(( " callsubr" )); | |
1345 | |
1346 idx = Fix2Int( top[0] ); | |
1347 if ( idx < 0 || idx >= (FT_Int)decoder->num_subrs ) | |
1348 { | |
1349 FT_ERROR(( "t1_decoder_parse_charstrings:" | |
1350 " invalid subrs index\n" )); | |
1351 goto Syntax_Error; | |
1352 } | |
1353 | |
1354 if ( zone - decoder->zones >= T1_MAX_SUBRS_CALLS ) | |
1355 { | |
1356 FT_ERROR(( "t1_decoder_parse_charstrings:" | |
1357 " too many nested subrs\n" )); | |
1358 goto Syntax_Error; | |
1359 } | |
1360 | |
1361 zone->cursor = ip; /* save current instruction pointer */ | |
1362 | |
1363 zone++; | |
1364 | |
1365 /* The Type 1 driver stores subroutines without the seed bytes. */ | |
1366 /* The CID driver stores subroutines with seed bytes. This */ | |
1367 /* case is taken care of when decoder->subrs_len == 0. */ | |
1368 zone->base = decoder->subrs[idx]; | |
1369 | |
1370 if ( decoder->subrs_len ) | |
1371 zone->limit = zone->base + decoder->subrs_len[idx]; | |
1372 else | |
1373 { | |
1374 /* We are using subroutines from a CID font. We must adjust */ | |
1375 /* for the seed bytes. */ | |
1376 zone->base += ( decoder->lenIV >= 0 ? decoder->lenIV : 0 ); | |
1377 zone->limit = decoder->subrs[idx + 1]; | |
1378 } | |
1379 | |
1380 zone->cursor = zone->base; | |
1381 | |
1382 if ( !zone->base ) | |
1383 { | |
1384 FT_ERROR(( "t1_decoder_parse_charstrings:" | |
1385 " invoking empty subrs\n" )); | |
1386 goto Syntax_Error; | |
1387 } | |
1388 | |
1389 decoder->zone = zone; | |
1390 ip = zone->base; | |
1391 limit = zone->limit; | |
1392 break; | |
1393 } | |
1394 | |
1395 case op_pop: | |
1396 FT_TRACE4(( " pop" )); | |
1397 | |
1398 if ( known_othersubr_result_cnt > 0 ) | |
1399 { | |
1400 known_othersubr_result_cnt--; | |
1401 /* ignore, we pushed the operands ourselves */ | |
1402 break; | |
1403 } | |
1404 | |
1405 if ( unknown_othersubr_result_cnt == 0 ) | |
1406 { | |
1407 FT_ERROR(( "t1_decoder_parse_charstrings:" | |
1408 " no more operands for othersubr\n" )); | |
1409 goto Syntax_Error; | |
1410 } | |
1411 | |
1412 unknown_othersubr_result_cnt--; | |
1413 top++; /* `push' the operand to callothersubr onto the stack */ | |
1414 break; | |
1415 | |
1416 case op_return: | |
1417 FT_TRACE4(( " return" )); | |
1418 | |
1419 if ( zone <= decoder->zones ) | |
1420 { | |
1421 FT_ERROR(( "t1_decoder_parse_charstrings:" | |
1422 " unexpected return\n" )); | |
1423 goto Syntax_Error; | |
1424 } | |
1425 | |
1426 zone--; | |
1427 ip = zone->cursor; | |
1428 limit = zone->limit; | |
1429 decoder->zone = zone; | |
1430 break; | |
1431 | |
1432 case op_dotsection: | |
1433 FT_TRACE4(( " dotsection" )); | |
1434 | |
1435 break; | |
1436 | |
1437 case op_hstem: | |
1438 FT_TRACE4(( " hstem" )); | |
1439 | |
1440 /* record horizontal hint */ | |
1441 if ( hinter ) | |
1442 { | |
1443 /* top[0] += builder->left_bearing.y; */ | |
1444 hinter->stem( hinter->hints, 1, top ); | |
1445 } | |
1446 break; | |
1447 | |
1448 case op_hstem3: | |
1449 FT_TRACE4(( " hstem3" )); | |
1450 | |
1451 /* record horizontal counter-controlled hints */ | |
1452 if ( hinter ) | |
1453 hinter->stem3( hinter->hints, 1, top ); | |
1454 break; | |
1455 | |
1456 case op_vstem: | |
1457 FT_TRACE4(( " vstem" )); | |
1458 | |
1459 /* record vertical hint */ | |
1460 if ( hinter ) | |
1461 { | |
1462 top[0] += orig_x; | |
1463 hinter->stem( hinter->hints, 0, top ); | |
1464 } | |
1465 break; | |
1466 | |
1467 case op_vstem3: | |
1468 FT_TRACE4(( " vstem3" )); | |
1469 | |
1470 /* record vertical counter-controlled hints */ | |
1471 if ( hinter ) | |
1472 { | |
1473 FT_Pos dx = orig_x; | |
1474 | |
1475 | |
1476 top[0] += dx; | |
1477 top[2] += dx; | |
1478 top[4] += dx; | |
1479 hinter->stem3( hinter->hints, 0, top ); | |
1480 } | |
1481 break; | |
1482 | |
1483 case op_setcurrentpoint: | |
1484 FT_TRACE4(( " setcurrentpoint" )); | |
1485 | |
1486 /* From the T1 specification, section 6.4: */ | |
1487 /* */ | |
1488 /* The setcurrentpoint command is used only in */ | |
1489 /* conjunction with results from OtherSubrs procedures. */ | |
1490 | |
1491 /* known_othersubr_result_cnt != 0 is already handled */ | |
1492 /* above. */ | |
1493 | |
1494 /* Note, however, that both Ghostscript and Adobe */ | |
1495 /* Distiller handle this situation by silently ignoring */ | |
1496 /* the inappropriate `setcurrentpoint' instruction. So */ | |
1497 /* we do the same. */ | |
1498 #if 0 | |
1499 | |
1500 if ( decoder->flex_state != 1 ) | |
1501 { | |
1502 FT_ERROR(( "t1_decoder_parse_charstrings:" | |
1503 " unexpected `setcurrentpoint'\n" )); | |
1504 goto Syntax_Error; | |
1505 } | |
1506 else | |
1507 ... | |
1508 #endif | |
1509 | |
1510 x = top[0]; | |
1511 y = top[1]; | |
1512 decoder->flex_state = 0; | |
1513 break; | |
1514 | |
1515 case op_unknown15: | |
1516 FT_TRACE4(( " opcode_15" )); | |
1517 /* nothing to do except to pop the two arguments */ | |
1518 break; | |
1519 | |
1520 default: | |
1521 FT_ERROR(( "t1_decoder_parse_charstrings:" | |
1522 " unhandled opcode %d\n", op )); | |
1523 goto Syntax_Error; | |
1524 } | |
1525 | |
1526 /* XXX Operators usually clear the operand stack; */ | |
1527 /* only div, callsubr, callothersubr, pop, and */ | |
1528 /* return are different. */ | |
1529 /* In practice it doesn't matter (?). */ | |
1530 | |
1531 decoder->top = top; | |
1532 | |
1533 #ifdef FT_DEBUG_LEVEL_TRACE | |
1534 FT_TRACE4(( "\n" )); | |
1535 bol = TRUE; | |
1536 #endif | |
1537 | |
1538 } /* general operator processing */ | |
1539 | |
1540 } /* while ip < limit */ | |
1541 | |
1542 FT_TRACE4(( "..end..\n\n" )); | |
1543 | |
1544 Fail: | |
1545 return error; | |
1546 | |
1547 Syntax_Error: | |
1548 return FT_THROW( Syntax_Error ); | |
1549 | |
1550 Stack_Underflow: | |
1551 return FT_THROW( Stack_Underflow ); | |
1552 } | |
1553 | |
1554 | |
1555 /* parse a single Type 1 glyph */ | |
1556 FT_LOCAL_DEF( FT_Error ) | |
1557 t1_decoder_parse_glyph( T1_Decoder decoder, | |
1558 FT_UInt glyph ) | |
1559 { | |
1560 return decoder->parse_callback( decoder, glyph ); | |
1561 } | |
1562 | |
1563 | |
1564 /* initialize T1 decoder */ | |
1565 FT_LOCAL_DEF( FT_Error ) | |
1566 t1_decoder_init( T1_Decoder decoder, | |
1567 FT_Face face, | |
1568 FT_Size size, | |
1569 FT_GlyphSlot slot, | |
1570 FT_Byte** glyph_names, | |
1571 PS_Blend blend, | |
1572 FT_Bool hinting, | |
1573 FT_Render_Mode hint_mode, | |
1574 T1_Decoder_Callback parse_callback ) | |
1575 { | |
1576 FT_MEM_ZERO( decoder, sizeof ( *decoder ) ); | |
1577 | |
1578 /* retrieve PSNames interface from list of current modules */ | |
1579 { | |
1580 FT_Service_PsCMaps psnames = 0; | |
1581 | |
1582 | |
1583 FT_FACE_FIND_GLOBAL_SERVICE( face, psnames, POSTSCRIPT_CMAPS ); | |
1584 if ( !psnames ) | |
1585 { | |
1586 FT_ERROR(( "t1_decoder_init:" | |
1587 " the `psnames' module is not available\n" )); | |
1588 return FT_THROW( Unimplemented_Feature ); | |
1589 } | |
1590 | |
1591 decoder->psnames = psnames; | |
1592 } | |
1593 | |
1594 t1_builder_init( &decoder->builder, face, size, slot, hinting ); | |
1595 | |
1596 /* decoder->buildchar and decoder->len_buildchar have to be */ | |
1597 /* initialized by the caller since we cannot know the length */ | |
1598 /* of the BuildCharArray */ | |
1599 | |
1600 decoder->num_glyphs = (FT_UInt)face->num_glyphs; | |
1601 decoder->glyph_names = glyph_names; | |
1602 decoder->hint_mode = hint_mode; | |
1603 decoder->blend = blend; | |
1604 decoder->parse_callback = parse_callback; | |
1605 | |
1606 decoder->funcs = t1_decoder_funcs; | |
1607 | |
1608 return FT_Err_Ok; | |
1609 } | |
1610 | |
1611 | |
1612 /* finalize T1 decoder */ | |
1613 FT_LOCAL_DEF( void ) | |
1614 t1_decoder_done( T1_Decoder decoder ) | |
1615 { | |
1616 t1_builder_done( &decoder->builder ); | |
1617 } | |
1618 | |
1619 | |
1620 /* END */ | |
OLD | NEW |