1 /* Copyright (C) 1990, 2000 artofcode LLC. All rights reserved.
2
3 This program is free software; you can redistribute it and/or modify it
4 under the terms of the GNU General Public License as published by the
5 Free Software Foundation; either version 2 of the License, or (at your
6 option) any later version.
7
8 This program is distributed in the hope that it will be useful, but
9 WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 General Public License for more details.
12
13 You should have received a copy of the GNU General Public License along
14 with this program; if not, write to the Free Software Foundation, Inc.,
15 59 Temple Place, Suite 330, Boston, MA, 02111-1307.
16
17 */
18
19 /*$Id: gstype1.c,v 1.6.4.1.2.1 2003/01/17 00:49:03 giles Exp $ */
20 /* Adobe Type 1 charstring interpreter */
21 #include "math_.h"
22 #include "memory_.h"
23 #include "gx.h"
24 #include "gserrors.h"
25 #include "gsstruct.h"
26 #include "gxarith.h"
27 #include "gxfixed.h"
28 #include "gxmatrix.h"
29 #include "gxcoord.h"
30 #include "gxistate.h"
31 #include "gzpath.h"
32 #include "gxfont.h"
33 #include "gxfont1.h"
34 #include "gxtype1.h"
35
36 /*
37 * Define whether to always do Flex segments as curves.
38 * This is only an issue because some old Adobe DPS fonts
39 * seem to violate the Flex specification in a way that requires this.
40 * We changed this from 1 to 0 in release 5.02: if it causes any
41 * problems, we'll implement a more sophisticated test.
42 */
43 #define ALWAYS_DO_FLEX_AS_CURVE 0
44
45 /* ------ Main interpreter ------ */
46
47 /*
48 * Continue interpreting a Type 1 charstring. If str != 0, it is taken as
49 * the byte string to interpret. Return 0 on successful completion, <0 on
50 * error, or >0 when client intervention is required (or allowed). The int*
51 * argument is where the othersubr # is stored for callothersubr.
52 */
53 int
gs_type1_interpret(gs_type1_state * pcis,const gs_const_string * str,int * pindex)54 gs_type1_interpret(gs_type1_state * pcis, const gs_const_string * str,
55 int *pindex)
56 {
57 gs_font_type1 *pfont = pcis->pfont;
58 gs_type1_data *pdata = &pfont->data;
59 bool encrypted = pdata->lenIV >= 0;
60 gs_op1_state s;
61 fixed cstack[ostack_size];
62
63 #define cs0 cstack[0]
64 #define ics0 fixed2int_var(cs0)
65 #define cs1 cstack[1]
66 #define ics1 fixed2int_var(cs1)
67 #define cs2 cstack[2]
68 #define ics2 fixed2int_var(cs2)
69 #define cs3 cstack[3]
70 #define ics3 fixed2int_var(cs3)
71 #define cs4 cstack[4]
72 #define ics4 fixed2int_var(cs4)
73 #define cs5 cstack[5]
74 #define ics5 fixed2int_var(cs5)
75 cs_ptr csp;
76 #define clear CLEAR_CSTACK(cstack, csp)
77 ip_state_t *ipsp = &pcis->ipstack[pcis->ips_count - 1];
78 register const byte *cip;
79 register crypt_state state;
80 register int c;
81 int code = 0;
82 fixed ftx = pcis->origin.x, fty = pcis->origin.y;
83
84 switch (pcis->init_done) {
85 case -1:
86 break;
87 case 0:
88 gs_type1_finish_init(pcis, &s); /* sets sfc, ptx, pty, origin */
89 ftx = pcis->origin.x, fty = pcis->origin.y;
90 break;
91 default /*case 1 */ :
92 ptx = pcis->position.x;
93 pty = pcis->position.y;
94 sfc = pcis->fc;
95 }
96 sppath = pcis->path;
97 s.pcis = pcis;
98 INIT_CSTACK(cstack, csp, pcis);
99
100 if (str == 0)
101 goto cont;
102 ipsp->char_string = *str;
103 ipsp->free_char_string = 0; /* don't free caller-supplied strings */
104 cip = str->data;
105 call:state = crypt_charstring_seed;
106 if (encrypted) {
107 int skip = pdata->lenIV;
108
109 /* Skip initial random bytes */
110 for (; skip > 0; ++cip, --skip)
111 decrypt_skip_next(*cip, state);
112 }
113 goto top;
114 cont:cip = ipsp->ip;
115 state = ipsp->dstate;
116 top:for (;;) {
117 uint c0 = *cip++;
118
119 charstring_next(c0, state, c, encrypted);
120 if (c >= c_num1) {
121 /* This is a number, decode it and push it on the stack. */
122
123 if (c < c_pos2_0) { /* 1-byte number */
124 decode_push_num1(csp, c);
125 } else if (c < cx_num4) { /* 2-byte number */
126 decode_push_num2(csp, c, cip, state, encrypted);
127 } else if (c == cx_num4) { /* 4-byte number */
128 long lw;
129
130 decode_num4(lw, cip, state, encrypted);
131 *++csp = int2fixed(lw);
132 if (lw != fixed2long(*csp)) {
133 /*
134 * We handle the only case we've ever seen that
135 * actually uses such large numbers specially.
136 */
137 long denom;
138
139 c0 = *cip++;
140 charstring_next(c0, state, c, encrypted);
141 if (c < c_num1)
142 return_error(gs_error_rangecheck);
143 if (c < c_pos2_0)
144 decode_num1(denom, c);
145 else if (c < cx_num4)
146 decode_num2(denom, c, cip, state, encrypted);
147 else if (c == cx_num4)
148 decode_num4(denom, cip, state, encrypted);
149 else
150 return_error(gs_error_invalidfont);
151 c0 = *cip++;
152 charstring_next(c0, state, c, encrypted);
153 if (c != cx_escape)
154 return_error(gs_error_rangecheck);
155 c0 = *cip++;
156 charstring_next(c0, state, c, encrypted);
157 if (c != ce1_div)
158 return_error(gs_error_rangecheck);
159 *csp = float2fixed((double)lw / denom);
160 }
161 } else /* not possible */
162 return_error(gs_error_invalidfont);
163 pushed:if_debug3('1', "[1]%d: (%d) %f\n",
164 (int)(csp - cstack), c, fixed2float(*csp));
165 continue;
166 }
167 #ifdef DEBUG
168 if (gs_debug['1']) {
169 static const char *const c1names[] =
170 {char1_command_names};
171
172 if (c1names[c] == 0)
173 dlprintf2("[1]0x%lx: %02x??\n", (ulong) (cip - 1), c);
174 else
175 dlprintf3("[1]0x%lx: %02x %s\n", (ulong) (cip - 1), c,
176 c1names[c]);
177 }
178 #endif
179 switch ((char_command) c) {
180 #define cnext clear; goto top
181 #define inext goto top
182
183 /* Commands with identical functions in Type 1 and Type 2, */
184 /* except for 'escape'. */
185
186 case c_undef0:
187 case c_undef2:
188 case c_undef17:
189 return_error(gs_error_invalidfont);
190 case c_callsubr:
191 c = fixed2int_var(*csp) + pdata->subroutineNumberBias;
192 code = pdata->procs.subr_data
193 (pfont, c, false, &ipsp[1].char_string);
194 if (code < 0)
195 return_error(code);
196 --csp;
197 ipsp->ip = cip, ipsp->dstate = state;
198 ++ipsp;
199 ipsp->free_char_string = code;
200 cip = ipsp->char_string.data;
201 goto call;
202 case c_return:
203 if (ipsp->free_char_string > 0)
204 gs_free_const_string(pfont->memory,
205 ipsp->char_string.data,
206 ipsp->char_string.size,
207 "gs_type1_interpret");
208 --ipsp;
209 goto cont;
210 case c_undoc15:
211 /* See gstype1.h for information on this opcode. */
212 cnext;
213
214 /* Commands with similar but not identical functions */
215 /* in Type 1 and Type 2 charstrings. */
216
217 case cx_hstem:
218 apply_path_hints(pcis, false);
219 type1_hstem(pcis, cs0, cs1);
220 cnext;
221 case cx_vstem:
222 apply_path_hints(pcis, false);
223 type1_vstem(pcis, cs0, cs1);
224 cnext;
225 case cx_vmoveto:
226 cs1 = cs0;
227 cs0 = 0;
228 accum_y(cs1);
229 move: /* cs0 = dx, cs1 = dy for hint checking. */
230 if ((pcis->hint_next != 0 || path_is_drawing(sppath)) &&
231 pcis->flex_count == flex_max
232 )
233 apply_path_hints(pcis, true);
234 code = gx_path_add_point(sppath, ptx, pty);
235 goto cc;
236 case cx_rlineto:
237 accum_xy(cs0, cs1);
238 line: /* cs0 = dx, cs1 = dy for hint checking. */
239 code = gx_path_add_line(sppath, ptx, pty);
240 cc:if (code < 0)
241 return code;
242 pp:if_debug2('1', "[1]pt=(%g,%g)\n",
243 fixed2float(ptx), fixed2float(pty));
244 cnext;
245 case cx_hlineto:
246 accum_x(cs0);
247 cs1 = 0;
248 goto line;
249 case cx_vlineto:
250 cs1 = cs0;
251 cs0 = 0;
252 accum_y(cs1);
253 goto line;
254 case cx_rrcurveto:
255 code = gs_op1_rrcurveto(&s, cs0, cs1, cs2, cs3, cs4, cs5);
256 goto cc;
257 case cx_endchar:
258 code = gs_type1_endchar(pcis);
259 if (code == 1) {
260 /* do accent of seac */
261 spt = pcis->position;
262 ipsp = &pcis->ipstack[pcis->ips_count - 1];
263 cip = ipsp->char_string.data;
264 goto call;
265 }
266 return code;
267 case cx_rmoveto:
268 accum_xy(cs0, cs1);
269 goto move;
270 case cx_hmoveto:
271 accum_x(cs0);
272 cs1 = 0;
273 goto move;
274 case cx_vhcurveto:
275 {
276 gs_fixed_point pt1, pt2;
277 fixed ax0 = sppath->position.x - ptx;
278 fixed ay0 = sppath->position.y - pty;
279
280 accum_y(cs0);
281 pt1.x = ptx + ax0, pt1.y = pty + ay0;
282 accum_xy(cs1, cs2);
283 pt2.x = ptx, pt2.y = pty;
284 accum_x(cs3);
285 code = gx_path_add_curve(sppath, pt1.x, pt1.y, pt2.x, pt2.y, ptx, pty);
286 }
287 goto cc;
288 case cx_hvcurveto:
289 {
290 gs_fixed_point pt1, pt2;
291 fixed ax0 = sppath->position.x - ptx;
292 fixed ay0 = sppath->position.y - pty;
293
294 accum_x(cs0);
295 pt1.x = ptx + ax0, pt1.y = pty + ay0;
296 accum_xy(cs1, cs2);
297 pt2.x = ptx, pt2.y = pty;
298 accum_y(cs3);
299 code = gx_path_add_curve(sppath, pt1.x, pt1.y, pt2.x, pt2.y, ptx, pty);
300 }
301 goto cc;
302
303 /* Commands only recognized in Type 1 charstrings, */
304 /* plus 'escape'. */
305
306 case c1_closepath:
307 code = gs_op1_closepath(&s);
308 apply_path_hints(pcis, true);
309 goto cc;
310 case c1_hsbw:
311 gs_type1_sbw(pcis, cs0, fixed_0, cs1, fixed_0);
312 cs1 = fixed_0;
313 rsbw: /* Give the caller the opportunity to intervene. */
314 pcis->os_count = 0; /* clear */
315 ipsp->ip = cip, ipsp->dstate = state;
316 pcis->ips_count = ipsp - &pcis->ipstack[0] + 1;
317 /* If we aren't in a seac, do nothing else now; */
318 /* finish_init will take care of the rest. */
319 if (pcis->init_done < 0) {
320 /* Finish init when we return. */
321 pcis->init_done = 0;
322 } else {
323 /*
324 * Accumulate the side bearing now, but don't do it
325 * a second time for the base character of a seac.
326 */
327 if (pcis->seac_accent >= 0) {
328 /*
329 * As a special hack to work around a bug in
330 * Fontographer, we deal with the (illegal)
331 * situation in which the side bearing of the
332 * accented character (save_lsbx) is different from
333 * the side bearing of the base character (cs0/cs1).
334 */
335 fixed dsbx = cs0 - pcis->save_lsb.x;
336 fixed dsby = cs1 - pcis->save_lsb.y;
337
338 if (dsbx | dsby) {
339 accum_xy(dsbx, dsby);
340 pcis->lsb.x += dsbx;
341 pcis->lsb.y += dsby;
342 pcis->save_adxy.x -= dsbx;
343 pcis->save_adxy.y -= dsby;
344 }
345 } else
346 accum_xy(pcis->lsb.x, pcis->lsb.y);
347 pcis->position.x = ptx;
348 pcis->position.y = pty;
349 }
350 return type1_result_sbw;
351 case cx_escape:
352 charstring_next(*cip, state, c, encrypted);
353 ++cip;
354 #ifdef DEBUG
355 if (gs_debug['1'] && c < char1_extended_command_count) {
356 static const char *const ce1names[] =
357 {char1_extended_command_names};
358
359 if (ce1names[c] == 0)
360 dlprintf2("[1]0x%lx: %02x??\n", (ulong) (cip - 1), c);
361 else
362 dlprintf3("[1]0x%lx: %02x %s\n", (ulong) (cip - 1), c,
363 ce1names[c]);
364 }
365 #endif
366 switch ((char1_extended_command) c) {
367 case ce1_dotsection:
368 pcis->dotsection_flag ^=
369 (dotsection_in ^ dotsection_out);
370 cnext;
371 case ce1_vstem3:
372 apply_path_hints(pcis, false);
373 if (!pcis->vstem3_set && pcis->fh.use_x_hints) {
374 center_vstem(pcis, pcis->lsb.x + cs2, cs3);
375 /* Adjust the current point */
376 /* (center_vstem handles everything else). */
377 ptx += pcis->vs_offset.x;
378 pty += pcis->vs_offset.y;
379 pcis->vstem3_set = true;
380 }
381 type1_vstem(pcis, cs0, cs1);
382 type1_vstem(pcis, cs2, cs3);
383 type1_vstem(pcis, cs4, cs5);
384 cnext;
385 case ce1_hstem3:
386 apply_path_hints(pcis, false);
387 type1_hstem(pcis, cs0, cs1);
388 type1_hstem(pcis, cs2, cs3);
389 type1_hstem(pcis, cs4, cs5);
390 cnext;
391 case ce1_seac:
392 code = gs_type1_seac(pcis, cstack + 1, cstack[0],
393 ipsp);
394 if (code != 0) {
395 *pindex = ics3;
396 return code;
397 }
398 clear;
399 cip = ipsp->char_string.data;
400 goto call;
401 case ce1_sbw:
402 gs_type1_sbw(pcis, cs0, cs1, cs2, cs3);
403 goto rsbw;
404 case ce1_div:
405 csp[-1] = float2fixed((double)csp[-1] / (double)*csp);
406 --csp;
407 goto pushed;
408 case ce1_undoc15:
409 /* See gstype1.h for information on this opcode. */
410 cnext;
411 case ce1_callothersubr:
412 {
413 int num_results;
414
415 #define fpts pcis->flex_points
416 /* We must remember to pop both the othersubr # */
417 /* and the argument count off the stack. */
418 switch (*pindex = fixed2int_var(*csp)) {
419 case 0:
420 { /* We have to do something really sleazy */
421 /* here, namely, make it look as though */
422 /* the rmovetos never really happened, */
423 /* because we don't want to interrupt */
424 /* the current subpath. */
425 gs_fixed_point ept;
426
427 #if defined(DEBUG) || !ALWAYS_DO_FLEX_AS_CURVE
428 fixed fheight = csp[-4];
429 gs_fixed_point hpt;
430
431 #endif
432
433 if (pcis->flex_count != 8)
434 return_error(gs_error_invalidfont);
435 /* Assume the next two opcodes */
436 /* are `pop' `pop'. Unfortunately, some */
437 /* Monotype fonts put these in a Subr, */
438 /* so we can't just look ahead in the */
439 /* opcode stream. */
440 pcis->ignore_pops = 2;
441 csp[-4] = csp[-3] - pcis->asb_diff;
442 csp[-3] = csp[-2];
443 csp -= 3;
444 gx_path_current_point(sppath, &ept);
445 gx_path_add_point(sppath, fpts[0].x, fpts[0].y);
446 sppath->state_flags = /* <--- sleaze */
447 pcis->flex_path_state_flags;
448 #if defined(DEBUG) || !ALWAYS_DO_FLEX_AS_CURVE
449 /* Decide whether to do the flex as a curve. */
450 hpt.x = fpts[1].x - fpts[4].x;
451 hpt.y = fpts[1].y - fpts[4].y;
452 if_debug3('1',
453 "[1]flex: d=(%g,%g), height=%g\n",
454 fixed2float(hpt.x), fixed2float(hpt.y),
455 fixed2float(fheight) / 100);
456 #endif
457 #if !ALWAYS_DO_FLEX_AS_CURVE /* See beginning of file. */
458 if (any_abs(hpt.x) + any_abs(hpt.y) <
459 fheight / 100
460 ) { /* Do the flex as a line. */
461 code = gx_path_add_line(sppath,
462 ept.x, ept.y);
463 } else
464 #endif
465 { /* Do the flex as a curve. */
466 code = gx_path_add_curve(sppath,
467 fpts[2].x, fpts[2].y,
468 fpts[3].x, fpts[3].y,
469 fpts[4].x, fpts[4].y);
470 if (code < 0)
471 return code;
472 code = gx_path_add_curve(sppath,
473 fpts[5].x, fpts[5].y,
474 fpts[6].x, fpts[6].y,
475 fpts[7].x, fpts[7].y);
476 }
477 }
478 if (code < 0)
479 return code;
480 pcis->flex_count = flex_max; /* not inside flex */
481 inext;
482 case 1:
483 gx_path_current_point(sppath, &fpts[0]);
484 pcis->flex_path_state_flags = /* <--- more sleaze */
485 sppath->state_flags;
486 pcis->flex_count = 1;
487 csp -= 2;
488 inext;
489 case 2:
490 if (pcis->flex_count >= flex_max)
491 return_error(gs_error_invalidfont);
492 gx_path_current_point(sppath,
493 &fpts[pcis->flex_count++]);
494 csp -= 2;
495 inext;
496 case 3:
497 /* Assume the next opcode is a `pop'. */
498 /* See above as to why we don't just */
499 /* look ahead in the opcode stream. */
500 pcis->ignore_pops = 1;
501 replace_stem_hints(pcis);
502 csp -= 2;
503 inext;
504 case 12:
505 case 13:
506 /* Counter control isn't implemented. */
507 cnext;
508 case 14:
509 num_results = 1;
510 blend:
511 code = gs_type1_blend(pcis, csp,
512 num_results);
513 if (code < 0)
514 return code;
515 csp -= code;
516 inext;
517 case 15:
518 num_results = 2;
519 goto blend;
520 case 16:
521 num_results = 3;
522 goto blend;
523 case 17:
524 num_results = 4;
525 goto blend;
526 case 18:
527 num_results = 6;
528 goto blend;
529 }
530 }
531 #undef fpts
532 /* Not a recognized othersubr, */
533 /* let the client handle it. */
534 {
535 int scount = csp - cstack;
536 int n;
537
538 /* Copy the arguments to the caller's stack. */
539 if (scount < 1 || csp[-1] < 0 ||
540 csp[-1] > int2fixed(scount - 1)
541 )
542 return_error(gs_error_invalidfont);
543 n = fixed2int_var(csp[-1]);
544 code = (*pdata->procs.push_values)
545 (pcis->callback_data, csp - (n + 1), n);
546 if (code < 0)
547 return_error(code);
548 scount -= n + 1;
549 pcis->position.x = ptx;
550 pcis->position.y = pty;
551 apply_path_hints(pcis, false);
552 /* Exit to caller */
553 ipsp->ip = cip, ipsp->dstate = state;
554 pcis->os_count = scount;
555 pcis->ips_count = ipsp - &pcis->ipstack[0] + 1;
556 if (scount)
557 memcpy(pcis->ostack, cstack, scount * sizeof(fixed));
558 return type1_result_callothersubr;
559 }
560 case ce1_pop:
561 /* Check whether we're ignoring the pops after */
562 /* a known othersubr. */
563 if (pcis->ignore_pops != 0) {
564 pcis->ignore_pops--;
565 inext;
566 }
567 ++csp;
568 code = (*pdata->procs.pop_value)
569 (pcis->callback_data, csp);
570 if (code < 0)
571 return_error(code);
572 goto pushed;
573 case ce1_setcurrentpoint:
574 ptx = ftx, pty = fty;
575 cs0 += pcis->adxy.x;
576 cs1 += pcis->adxy.y;
577 accum_xy(cs0, cs1);
578 goto pp;
579 default:
580 return_error(gs_error_invalidfont);
581 }
582 /*NOTREACHED */
583
584 /* Fill up the dispatch up to 32. */
585
586 case_c1_undefs:
587 default: /* pacify compiler */
588 return_error(gs_error_invalidfont);
589 }
590 }
591 }
592