1 /* Copyright (C) 1996, 2000 Aladdin Enterprises. All rights reserved.
2
3 This software is provided AS-IS with no warranty, either express or
4 implied.
5
6 This software is distributed under license and may not be copied,
7 modified or distributed except as expressly authorized under the terms
8 of the license contained in the file LICENSE in this distribution.
9
10 For more information about licensing, please refer to
11 http://www.ghostscript.com/licensing/. For information on
12 commercial licensing, go to http://www.artifex.com/licensing/ or
13 contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14 San Rafael, CA 94903, U.S.A., +1(415)492-9861.
15 */
16
17 /* $Id: gstype2.c,v 1.36 2004/10/28 08:39:21 igor Exp $ */
18 /* Adobe Type 2 charstring interpreter */
19 #include "math_.h"
20 #include "memory_.h"
21 #include "gx.h"
22 #include "gserrors.h"
23 #include "gsstruct.h"
24 #include "gxarith.h"
25 #include "gxfixed.h"
26 #include "gxmatrix.h"
27 #include "gxcoord.h"
28 #include "gxistate.h"
29 #include "gxpath.h"
30 #include "gxfont.h"
31 #include "gxfont1.h"
32 #include "gxtype1.h"
33 #include "gxhintn.h"
34
35 /* NOTE: The following are not yet implemented:
36 * Registry items other than 0
37 * Counter masks (but they are parsed correctly)
38 * 'random' operator
39 */
40
41 /* ------ Internal routines ------ */
42
43 /*
44 * Set the character width. This is provided as an optional extra operand
45 * on the stack for the first operator. After setting the width, we remove
46 * the extra operand, and back up the interpreter pointer so we will
47 * re-execute the operator when control re-enters the interpreter.
48 */
49 #define check_first_operator(explicit_width)\
50 BEGIN\
51 if ( pcis->init_done < 0 )\
52 { ipsp->ip = cip, ipsp->dstate = state;\
53 return type2_sbw(pcis, csp, cstack, ipsp, explicit_width);\
54 }\
55 END
56 private int
type2_sbw(gs_type1_state * pcis,cs_ptr csp,cs_ptr cstack,ip_state_t * ipsp,bool explicit_width)57 type2_sbw(gs_type1_state * pcis, cs_ptr csp, cs_ptr cstack, ip_state_t * ipsp,
58 bool explicit_width)
59 {
60 t1_hinter *h = &pcis->h;
61 fixed sbx = fixed_0, sby = fixed_0, wx, wy = fixed_0;
62 int code;
63
64 if (explicit_width) {
65 wx = cstack[0] + pcis->pfont->data.nominalWidthX;
66 memmove(cstack, cstack + 1, (csp - cstack) * sizeof(*cstack));
67 --csp;
68 } else
69 wx = pcis->pfont->data.defaultWidthX;
70 if (pcis->seac_accent < 0) {
71 if (pcis->sb_set) {
72 sbx = pcis->lsb.x;
73 sby = pcis->lsb.y;
74 }
75 if (pcis->width_set) {
76 wx = pcis->width.x;
77 wy = pcis->width.y;
78 }
79 }
80 code = t1_hinter__sbw(h, sbx, sby, wx, wy);
81 if (code < 0)
82 return code;
83 gs_type1_sbw(pcis, fixed_0, fixed_0, wx, fixed_0);
84 /* Back up the interpretation pointer. */
85 ipsp->ip--;
86 decrypt_skip_previous(*ipsp->ip, ipsp->dstate);
87 /* Save the interpreter state. */
88 pcis->os_count = csp + 1 - cstack;
89 pcis->ips_count = ipsp - &pcis->ipstack[0] + 1;
90 memcpy(pcis->ostack, cstack, pcis->os_count * sizeof(cstack[0]));
91 if (pcis->init_done < 0) { /* Finish init when we return. */
92 pcis->init_done = 0;
93 }
94 return type1_result_sbw;
95 }
96 private int
type2_vstem(gs_type1_state * pcis,cs_ptr csp,cs_ptr cstack)97 type2_vstem(gs_type1_state * pcis, cs_ptr csp, cs_ptr cstack)
98 {
99 fixed x = 0;
100 cs_ptr ap;
101 t1_hinter *h = &pcis->h;
102 int code;
103
104 for (ap = cstack; ap + 1 <= csp; x += ap[1], ap += 2) {
105 code = t1_hinter__vstem(h, x += ap[0], ap[1]);
106 if (code < 0)
107 return code;
108 }
109 pcis->num_hints += (csp + 1 - cstack) >> 1;
110 return 0;
111 }
112
113 /* ------ Main interpreter ------ */
114
115 /*
116 * Continue interpreting a Type 2 charstring. If str != 0, it is taken as
117 * the byte string to interpret. Return 0 on successful completion, <0 on
118 * error, or >0 when client intervention is required (or allowed). The int*
119 * argument is only for compatibility with the Type 1 charstring interpreter.
120 */
121 int
gs_type2_interpret(gs_type1_state * pcis,const gs_glyph_data_t * pgd,int * ignore_pindex)122 gs_type2_interpret(gs_type1_state * pcis, const gs_glyph_data_t *pgd,
123 int *ignore_pindex)
124 {
125 gs_font_type1 *pfont = pcis->pfont;
126 gs_type1_data *pdata = &pfont->data;
127 t1_hinter *h = &pcis->h;
128 bool encrypted = pdata->lenIV >= 0;
129 fixed cstack[ostack_size];
130 cs_ptr csp;
131 #define clear CLEAR_CSTACK(cstack, csp)
132 ip_state_t *ipsp = &pcis->ipstack[pcis->ips_count - 1];
133 register const byte *cip;
134 register crypt_state state;
135 register int c;
136 cs_ptr ap;
137 bool vertical;
138 int code = 0;
139
140 /****** FAKE THE REGISTRY ******/
141 struct {
142 float *values;
143 uint size;
144 } Registry[1];
145
146 Registry[0].values = pcis->pfont->data.WeightVector.values;
147
148 switch (pcis->init_done) {
149 case -1:
150 t1_hinter__init(h, pcis->path);
151 break;
152 case 0:
153 gs_type1_finish_init(pcis); /* sets origin */
154 code = t1_hinter__set_mapping(h, &pcis->pis->ctm,
155 &pfont->FontMatrix, &pfont->base->FontMatrix,
156 pcis->scale.x.log2_unit, pcis->scale.x.log2_unit,
157 pcis->scale.x.log2_unit - pcis->log2_subpixels.x,
158 pcis->scale.y.log2_unit - pcis->log2_subpixels.y,
159 pcis->origin.x, pcis->origin.y,
160 gs_currentaligntopixels(pfont->dir));
161 if (code < 0)
162 return code;
163 code = t1_hinter__set_font_data(h, 2, pdata, pcis->no_grid_fitting);
164 if (code < 0)
165 return code;
166 break;
167 default /*case 1 */ :
168 break;
169 }
170 INIT_CSTACK(cstack, csp, pcis);
171
172 if (pgd == 0)
173 goto cont;
174 ipsp->cs_data = *pgd;
175 cip = pgd->bits.data;
176 call:state = crypt_charstring_seed;
177 if (encrypted) {
178 int skip = pdata->lenIV;
179
180 /* Skip initial random bytes */
181 for (; skip > 0; ++cip, --skip)
182 decrypt_skip_next(*cip, state);
183 }
184 goto top;
185 cont:cip = ipsp->ip;
186 state = ipsp->dstate;
187 top:for (;;) {
188 uint c0 = *cip++;
189
190 charstring_next(c0, state, c, encrypted);
191 if (c >= c_num1) {
192 /* This is a number, decode it and push it on the stack. */
193
194 if (c < c_pos2_0) { /* 1-byte number */
195 decode_push_num1(csp, cstack, c);
196 } else if (c < cx_num4) { /* 2-byte number */
197 decode_push_num2(csp, cstack, c, cip, state, encrypted);
198 } else if (c == cx_num4) { /* 4-byte number */
199 long lw;
200
201 decode_num4(lw, cip, state, encrypted);
202 /* 32-bit numbers are 16:16. */
203 CS_CHECK_PUSH(csp, cstack);
204 *++csp = arith_rshift(lw, 16 - _fixed_shift);
205 } else /* not possible */
206 return_error(gs_error_invalidfont);
207 pushed:if_debug3('1', "[1]%d: (%d) %f\n",
208 (int)(csp - cstack), c, fixed2float(*csp));
209 continue;
210 }
211 #ifdef DEBUG
212 if (gs_debug['1']) {
213 static const char *const c2names[] =
214 {char2_command_names};
215
216 if (c2names[c] == 0)
217 dlprintf2("[1]0x%lx: %02x??\n", (ulong) (cip - 1), c);
218 else
219 dlprintf3("[1]0x%lx: %02x %s\n", (ulong) (cip - 1), c,
220 c2names[c]);
221 }
222 #endif
223 switch ((char_command) c) {
224 #define cnext clear; goto top
225
226 /* Commands with identical functions in Type 1 and Type 2, */
227 /* except for 'escape'. */
228
229 case c_undef0:
230 case c_undef2:
231 case c_undef17:
232 return_error(gs_error_invalidfont);
233 case c_callsubr:
234 c = fixed2int_var(*csp) + pdata->subroutineNumberBias;
235 code = pdata->procs.subr_data
236 (pfont, c, false, &ipsp[1].cs_data);
237 subr:if (code < 0) {
238 /* Calling a Subr with an out-of-range index is clearly a error:
239 * the Adobe documentation says the results of doing this are
240 * undefined. However, we have seen a PDF file produced by Adobe
241 * PDF Library 4.16 that included a Type 2 font that called an
242 * out-of-range Subr, and Acrobat Reader did not signal an error.
243 * Therefore, we ignore such calls.
244 */
245 cip++;
246 goto top;
247 }
248 --csp;
249 ipsp->ip = cip, ipsp->dstate = state;
250 ++ipsp;
251 cip = ipsp->cs_data.bits.data;
252 goto call;
253 case c_return:
254 gs_glyph_data_free(&ipsp->cs_data, "gs_type2_interpret");
255 --ipsp;
256 goto cont;
257 case c_undoc15:
258 /* See gstype1.h for information on this opcode. */
259 cnext;
260
261 /* Commands with similar but not identical functions */
262 /* in Type 1 and Type 2 charstrings. */
263
264 case cx_hstem:
265 goto hstem;
266 case cx_vstem:
267 goto vstem;
268 case cx_vmoveto:
269 check_first_operator(csp > cstack);
270 code = t1_hinter__rmoveto(h, 0, *csp);
271 move:
272 cc:
273 if (code < 0)
274 return code;
275 goto pp;
276 case cx_rlineto:
277 for (ap = cstack; ap + 1 <= csp; ap += 2) {
278 code = t1_hinter__rlineto(h, ap[0], ap[1]);
279 if (code < 0)
280 return code;
281 }
282 pp:
283 cnext;
284 case cx_hlineto:
285 vertical = false;
286 goto hvl;
287 case cx_vlineto:
288 vertical = true;
289 hvl:for (ap = cstack; ap <= csp; vertical = !vertical, ++ap) {
290 if (vertical) {
291 code = t1_hinter__rlineto(h, 0, ap[0]);
292 } else {
293 code = t1_hinter__rlineto(h, ap[0], 0);
294 }
295 if (code < 0)
296 return code;
297 }
298 goto pp;
299 case cx_rrcurveto:
300 for (ap = cstack; ap + 5 <= csp; ap += 6) {
301 code = t1_hinter__rcurveto(h, ap[0], ap[1], ap[2],
302 ap[3], ap[4], ap[5]);
303 if (code < 0)
304 return code;
305 }
306 goto pp;
307 case cx_endchar:
308 /*
309 * It is a feature of Type 2 CharStrings that if endchar is
310 * invoked with 4 or 5 operands, it is equivalent to the
311 * Type 1 seac operator. In this case, the asb operand of
312 * seac is missing: we assume it is the same as the
313 * l.s.b. of the accented character. This feature was
314 * undocumented until the 16 March 2000 version of the Type
315 * 2 Charstring Format specification, but, thankfully, is
316 * described in that revision.
317 */
318 if (csp >= cstack + 3) {
319 check_first_operator(csp > cstack + 3);
320 code = gs_type1_seac(pcis, cstack, 0, ipsp);
321 if (code < 0)
322 return code;
323 clear;
324 cip = ipsp->cs_data.bits.data;
325 goto call;
326 }
327 /*
328 * This might be the only operator in the charstring.
329 * In this case, there might be a width on the stack.
330 */
331 check_first_operator(csp >= cstack);
332 code = t1_hinter__endchar(h, (pcis->seac_accent >= 0));
333 if (code < 0)
334 return code;
335 if (pcis->seac_accent < 0) {
336 code = t1_hinter__endglyph(h);
337 if (code < 0)
338 return code;
339 code = gx_setcurrentpoint_from_path(pcis->pis, pcis->path);
340 if (code < 0)
341 return code;
342 } else
343 t1_hinter__setcurrentpoint(h, pcis->save_adxy.x, pcis->save_adxy.y);
344 code = gs_type1_endchar(pcis);
345 if (code == 1) {
346 /*
347 * Reset the total hint count so that hintmask will
348 * parse its following data correctly.
349 * (gs_type1_endchar already reset the actual hint
350 * tables.)
351 */
352 pcis->num_hints = 0;
353 /* do accent of seac */
354 ipsp = &pcis->ipstack[pcis->ips_count - 1];
355 cip = ipsp->cs_data.bits.data;
356 goto call;
357 }
358 return code;
359 case cx_rmoveto:
360 /* See vmoveto above re closing the subpath. */
361 check_first_operator(!((csp - cstack) & 1));
362 if (csp > cstack + 1) {
363 /* Some Type 2 charstrings omit the vstemhm operator before rmoveto,
364 even though this is only allowed before hintmask and cntrmask.
365 Thanks to Felix Pahl.
366 */
367 type2_vstem(pcis, csp - 2, cstack);
368 cstack [0] = csp [-1];
369 cstack [1] = csp [ 0];
370 csp = cstack + 1;
371 }
372 code = t1_hinter__rmoveto(h, csp[-1], *csp);
373 goto move;
374 case cx_hmoveto:
375 /* See vmoveto above re closing the subpath. */
376 check_first_operator(csp > cstack);
377 code = t1_hinter__rmoveto(h, *csp, 0);
378 goto move;
379 case cx_vhcurveto:
380 vertical = true;
381 goto hvc;
382 case cx_hvcurveto:
383 vertical = false;
384 hvc:for (ap = cstack; ap + 3 <= csp; vertical = !vertical, ap += 4) {
385 gs_fixed_point pt[2] = {{0, 0}, {0, 0}};
386 if (vertical) {
387 pt[0].y = ap[0];
388 pt[1].x = ap[3];
389 if (ap + 4 == csp)
390 pt[1].y = ap[4];
391 } else {
392 pt[0].x = ap[0];
393 if (ap + 4 == csp)
394 pt[1].x = ap[4];
395 pt[1].y = ap[3];
396 }
397 code = t1_hinter__rcurveto(h, pt[0].x, pt[0].y, ap[1], ap[2], pt[1].x, pt[1].y);
398 if (code < 0)
399 return code;
400 }
401 goto pp;
402
403 /***********************
404 * New Type 2 commands *
405 ***********************/
406
407 case c2_blend:
408 {
409 int n = fixed2int_var(*csp);
410 int num_values = csp - cstack;
411 gs_font_type1 *pfont = pcis->pfont;
412 int k = pfont->data.WeightVector.count;
413 int i, j;
414 cs_ptr base, deltas;
415
416 base = csp - 1 - num_values;
417 deltas = base + n - 1;
418 for (j = 0; j < n; j++, base++, deltas += k - 1)
419 for (i = 1; i < k; i++)
420 *base += (fixed)(deltas[i] *
421 pfont->data.WeightVector.values[i]);
422 }
423 cnext;
424 case c2_hstemhm:
425 hstem:check_first_operator(!((csp - cstack) & 1));
426 {
427 fixed x = 0;
428
429 for (ap = cstack; ap + 1 <= csp; x += ap[1], ap += 2) {
430 code = t1_hinter__hstem(h, x += ap[0], ap[1]);
431 if (code < 0)
432 return code;
433 }
434 }
435 pcis->num_hints += (csp + 1 - cstack) >> 1;
436 cnext;
437 case c2_hintmask:
438 /*
439 * A hintmask at the beginning of the CharString is
440 * equivalent to vstemhm + hintmask. For simplicity, we use
441 * this interpretation everywhere.
442 */
443 case c2_cntrmask:
444 check_first_operator(!((csp - cstack) & 1));
445 type2_vstem(pcis, csp, cstack);
446 /*
447 * We should clear the stack here only if this is the
448 * initial mask operator that includes the implicit
449 * vstemhm, but currently this is too much trouble to
450 * detect.
451 */
452 clear;
453 {
454 byte mask[max_total_stem_hints / 8];
455 int i;
456
457 for (i = 0; i < pcis->num_hints; ++cip, i += 8) {
458 charstring_next(*cip, state, mask[i >> 3], encrypted);
459 if_debug1('1', " 0x%02x", mask[i >> 3]);
460 }
461 if_debug0('1', "\n");
462 ipsp->ip = cip;
463 ipsp->dstate = state;
464 if (c == c2_cntrmask) {
465 /****** NYI ******/
466 } else { /* hintmask or equivalent */
467 if_debug0('1', "[1]hstem hints:\n");
468 if_debug0('1', "[1]vstem hints:\n");
469 code = t1_hinter__hint_mask(h, mask);
470 if (code < 0)
471 return code;
472 }
473 }
474 break;
475 case c2_vstemhm:
476 vstem:check_first_operator(!((csp - cstack) & 1));
477 type2_vstem(pcis, csp, cstack);
478 cnext;
479 case c2_rcurveline:
480 for (ap = cstack; ap + 5 <= csp; ap += 6) {
481 code = t1_hinter__rcurveto(h, ap[0], ap[1], ap[2], ap[3],
482 ap[4], ap[5]);
483 if (code < 0)
484 return code;
485 }
486 code = t1_hinter__rlineto(h, ap[0], ap[1]);
487 goto cc;
488 case c2_rlinecurve:
489 for (ap = cstack; ap + 7 <= csp; ap += 2) {
490 code = t1_hinter__rlineto(h, ap[0], ap[1]);
491 if (code < 0)
492 return code;
493 }
494 code = t1_hinter__rcurveto(h, ap[0], ap[1], ap[2], ap[3],
495 ap[4], ap[5]);
496 goto cc;
497 case c2_vvcurveto:
498 ap = cstack;
499 {
500 int n = csp + 1 - cstack;
501 fixed dxa = (n & 1 ? *ap++ : 0);
502
503 for (; ap + 3 <= csp; ap += 4) {
504 code = t1_hinter__rcurveto(h, dxa, ap[0], ap[1], ap[2],
505 fixed_0, ap[3]);
506 if (code < 0)
507 return code;
508 dxa = 0;
509 }
510 }
511 goto pp;
512 case c2_hhcurveto:
513 ap = cstack;
514 {
515 int n = csp + 1 - cstack;
516 fixed dya = (n & 1 ? *ap++ : 0);
517
518 for (; ap + 3 <= csp; ap += 4) {
519 code = t1_hinter__rcurveto(h, ap[0], dya, ap[1], ap[2],
520 ap[3], fixed_0);
521 if (code < 0)
522 return code;
523 dya = 0;
524 }
525 }
526 goto pp;
527 case c2_shortint:
528 {
529 int c1, c2;
530
531 charstring_next(*cip, state, c1, encrypted);
532 ++cip;
533 charstring_next(*cip, state, c2, encrypted);
534 ++cip;
535 CS_CHECK_PUSH(csp, cstack);
536 *++csp = int2fixed((((c1 ^ 0x80) - 0x80) << 8) + c2);
537 }
538 goto pushed;
539 case c2_callgsubr:
540 c = fixed2int_var(*csp) + pdata->gsubrNumberBias;
541 code = pdata->procs.subr_data
542 (pfont, c, true, &ipsp[1].cs_data);
543 goto subr;
544 case cx_escape:
545 charstring_next(*cip, state, c, encrypted);
546 ++cip;
547 #ifdef DEBUG
548 if (gs_debug['1'] && c < char2_extended_command_count) {
549 static const char *const ce2names[] =
550 {char2_extended_command_names};
551
552 if (ce2names[c] == 0)
553 dlprintf2("[1]0x%lx: %02x??\n", (ulong) (cip - 1), c);
554 else
555 dlprintf3("[1]0x%lx: %02x %s\n", (ulong) (cip - 1), c,
556 ce2names[c]);
557 }
558 #endif
559 switch ((char2_extended_command) c) {
560 case ce2_and:
561 csp[-1] = ((csp[-1] != 0) & (*csp != 0) ? fixed_1 : 0);
562 --csp;
563 break;
564 case ce2_or:
565 csp[-1] = (csp[-1] | *csp ? fixed_1 : 0);
566 --csp;
567 break;
568 case ce2_not:
569 *csp = (*csp ? 0 : fixed_1);
570 break;
571 case ce2_store:
572 {
573 int i, n = fixed2int_var(*csp);
574 float *to = Registry[fixed2int_var(csp[-3])].values +
575 fixed2int_var(csp[-2]);
576 const fixed *from =
577 pcis->transient_array + fixed2int_var(csp[-1]);
578
579 for (i = 0; i < n; ++i)
580 to[i] = fixed2float(from[i]);
581 }
582 csp -= 4;
583 break;
584 case ce2_abs:
585 if (*csp < 0)
586 *csp = -*csp;
587 break;
588 case ce2_add:
589 csp[-1] += *csp;
590 --csp;
591 break;
592 case ce2_sub:
593 csp[-1] -= *csp;
594 --csp;
595 break;
596 case ce2_div:
597 csp[-1] = float2fixed((double)csp[-1] / *csp);
598 --csp;
599 break;
600 case ce2_load:
601 /* The specification says there is no j (starting index */
602 /* in registry array) argument.... */
603 {
604 int i, n = fixed2int_var(*csp);
605 const float *from = Registry[fixed2int_var(csp[-2])].values;
606 fixed *to =
607 pcis->transient_array + fixed2int_var(csp[-1]);
608
609 for (i = 0; i < n; ++i)
610 to[i] = float2fixed(from[i]);
611 }
612 csp -= 3;
613 break;
614 case ce2_neg:
615 *csp = -*csp;
616 break;
617 case ce2_eq:
618 csp[-1] = (csp[-1] == *csp ? fixed_1 : 0);
619 --csp;
620 break;
621 case ce2_drop:
622 --csp;
623 break;
624 case ce2_put:
625 pcis->transient_array[fixed2int_var(*csp)] = csp[-1];
626 csp -= 2;
627 break;
628 case ce2_get:
629 *csp = pcis->transient_array[fixed2int_var(*csp)];
630 break;
631 case ce2_ifelse:
632 if (csp[-1] > *csp)
633 csp[-3] = csp[-2];
634 csp -= 3;
635 break;
636 case ce2_random:
637 CS_CHECK_PUSH(csp, cstack);
638 ++csp;
639 /****** NYI ******/
640 break;
641 case ce2_mul:
642 {
643 double prod = fixed2float(csp[-1]) * *csp;
644
645 csp[-1] =
646 (prod > max_fixed ? max_fixed :
647 prod < min_fixed ? min_fixed : (fixed)prod);
648 }
649 --csp;
650 break;
651 case ce2_sqrt:
652 if (*csp >= 0)
653 *csp = float2fixed(sqrt(fixed2float(*csp)));
654 break;
655 case ce2_dup:
656 CS_CHECK_PUSH(csp, cstack);
657 csp[1] = *csp;
658 ++csp;
659 break;
660 case ce2_exch:
661 {
662 fixed top = *csp;
663
664 *csp = csp[-1], csp[-1] = top;
665 }
666 break;
667 case ce2_index:
668 *csp =
669 (*csp < 0 ? csp[-1] : csp[-1 - fixed2int_var(csp[-1])]);
670 break;
671 case ce2_roll:
672 {
673 int distance = fixed2int_var(*csp);
674 int count = fixed2int_var(csp[-1]);
675 cs_ptr bot;
676
677 csp -= 2;
678 if (count < 0 || count > csp + 1 - cstack)
679 return_error(gs_error_invalidfont);
680 if (count == 0)
681 break;
682 if (distance < 0)
683 distance = count - (-distance % count);
684 bot = csp + 1 - count;
685 while (--distance >= 0) {
686 fixed top = *csp;
687
688 memmove(bot + 1, bot,
689 (count - 1) * sizeof(fixed));
690 *bot = top;
691 }
692 }
693 break;
694 case ce2_hflex:
695 csp[6] = fixed_half; /* fd/100 */
696 csp[4] = *csp, csp[5] = 0; /* dx6, dy6 */
697 csp[2] = csp[-1], csp[3] = -csp[-4]; /* dx5, dy5 */
698 *csp = csp[-2], csp[1] = 0; /* dx4, dy4 */
699 csp[-2] = csp[-3], csp[-1] = 0; /* dx3, dy3 */
700 csp[-3] = csp[-4], csp[-4] = csp[-5]; /* dx2, dy2 */
701 csp[-5] = 0; /* dy1 */
702 csp += 6;
703 goto flex;
704 case ce2_flex:
705 *csp /= 100; /* fd/100 */
706 flex: {
707 fixed x_join = csp[-12] + csp[-10] + csp[-8];
708 fixed y_join = csp[-11] + csp[-9] + csp[-7];
709 fixed x_end = x_join + csp[-6] + csp[-4] + csp[-2];
710 fixed y_end = y_join + csp[-5] + csp[-3] + csp[-1];
711 gs_point join, end;
712 double flex_depth;
713
714 if ((code =
715 gs_distance_transform(fixed2float(x_join),
716 fixed2float(y_join),
717 &ctm_only(pcis->pis),
718 &join)) < 0 ||
719 (code =
720 gs_distance_transform(fixed2float(x_end),
721 fixed2float(y_end),
722 &ctm_only(pcis->pis),
723 &end)) < 0
724 )
725 return code;
726 /*
727 * Use the X or Y distance depending on whether
728 * the curve is more horizontal or more
729 * vertical.
730 */
731 if (any_abs(end.y) > any_abs(end.x))
732 flex_depth = join.x;
733 else
734 flex_depth = join.y;
735 if (fabs(flex_depth) < fixed2float(*csp)) {
736 /* Do flex as line. */
737 code = t1_hinter__rlineto(h, x_end, y_end);
738 } else {
739 /*
740 * Do flex as curve. We can't jump to rrc,
741 * because the flex operators don't clear
742 * the stack (!).
743 */
744 code = t1_hinter__rcurveto(h,
745 csp[-12], csp[-11], csp[-10],
746 csp[-9], csp[-8], csp[-7]);
747 if (code < 0)
748 return code;
749 code = t1_hinter__rcurveto(h,
750 csp[-6], csp[-5], csp[-4],
751 csp[-3], csp[-2], csp[-1]);
752 }
753 if (code < 0)
754 return code;
755 csp -= 13;
756 }
757 cnext;
758 case ce2_hflex1:
759 csp[4] = fixed_half; /* fd/100 */
760 csp[2] = *csp; /* dx6 */
761 csp[3] = -(csp[-7] + csp[-5] + csp[-1]); /* dy6 */
762 *csp = csp[-2], csp[1] = csp[-1]; /* dx5, dy5 */
763 csp[-2] = csp[-3], csp[-1] = 0; /* dx4, dy4 */
764 csp[-3] = 0; /* dy3 */
765 csp += 4;
766 goto flex;
767 case ce2_flex1:
768 {
769 fixed dx = csp[-10] + csp[-8] + csp[-6] + csp[-4] + csp[-2];
770 fixed dy = csp[-9] + csp[-7] + csp[-5] + csp[-3] + csp[-1];
771
772 if (any_abs(dx) > any_abs(dy))
773 csp[1] = -dy; /* d6 is dx6 */
774 else
775 csp[1] = *csp, *csp = -dx; /* d6 is dy6 */
776 }
777 csp[2] = fixed_half; /* fd/100 */
778 csp += 2;
779 goto flex;
780 }
781 break;
782
783 /* Fill up the dispatch up to 32. */
784
785 case_c2_undefs:
786 default: /* pacify compiler */
787 return_error(gs_error_invalidfont);
788 }
789 }
790 }
791