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