1 /* Copyright (C) 2001-2006 Artifex Software, Inc.
2    All Rights Reserved.
3 
4    This software is provided AS-IS with no warranty, either express or
5    implied.
6 
7    This software is distributed under license and may not be copied, modified
8    or distributed except as expressly authorized under the terms of that
9    license.  Refer to licensing information at http://www.artifex.com/
10    or contact Artifex Software, Inc.,  7 Mt. Lassen Drive - Suite A-134,
11    San Rafael, CA  94903, U.S.A., +1(415)492-9861, for further information.
12 */
13 
14 /*$Id: zchar.c 9222 2008-11-16 14:47:49Z leonardo $ */
15 /* Character operators */
16 #include "ghost.h"
17 #include "oper.h"
18 #include "gsstruct.h"
19 #include "gstext.h"
20 #include "gxarith.h"
21 #include "gxfixed.h"
22 #include "gxmatrix.h"		/* for ifont.h */
23 #include "gxdevice.h"		/* for gxfont.h */
24 #include "gxfont.h"
25 #include "gxfont42.h"
26 #include "gxfont0.h"
27 #include "gzstate.h"
28 #include "dstack.h"		/* for stack depth */
29 #include "estack.h"
30 #include "ialloc.h"
31 #include "ichar.h"
32 #include "ichar1.h"
33 #include "idict.h"
34 #include "ifont.h"
35 #include "igstate.h"
36 #include "ilevel.h"
37 #include "iname.h"
38 #include "ipacked.h"
39 #include "store.h"
40 #include "zchar42.h"
41 
42 extern bool CPSI_mode;
43 
44 /* Forward references */
45 static bool map_glyph_to_char(const gs_memory_t *mem,
46 			       const ref *, const ref *, ref *);
47 static int finish_show(i_ctx_t *);
48 static int op_show_cleanup(i_ctx_t *);
49 static int op_show_return_width(i_ctx_t *, uint, double *);
50 
51 /* <string> show - */
52 static int
zshow(i_ctx_t * i_ctx_p)53 zshow(i_ctx_t *i_ctx_p)
54 {
55     os_ptr op = osp;
56     gs_text_enum_t *penum;
57     int code = op_show_setup(i_ctx_p, op);
58 
59     if (code != 0 ||
60 	(code = gs_show_begin(igs, op->value.bytes, r_size(op), imemory, &penum)) < 0)
61 	return code;
62     *(op_proc_t *)&penum->enum_client_data = zshow;
63     if ((code = op_show_finish_setup(i_ctx_p, penum, 1, finish_show)) < 0) {
64 	ifree_object(penum, "op_show_enum_setup");
65 	return code;
66     }
67     return op_show_continue_pop(i_ctx_p, 1);
68 }
69 
70 /* <ax> <ay> <string> ashow - */
71 static int
zashow(i_ctx_t * i_ctx_p)72 zashow(i_ctx_t *i_ctx_p)
73 {
74     os_ptr op = osp;
75     gs_text_enum_t *penum;
76     double axy[2];
77     int code = num_params(op - 1, 2, axy);
78 
79     if (code < 0 ||
80 	(code = op_show_setup(i_ctx_p, op)) != 0 ||
81 	(code = gs_ashow_begin(igs, axy[0], axy[1], op->value.bytes, r_size(op), imemory, &penum)) < 0)
82 	return code;
83     *(op_proc_t *)&penum->enum_client_data = zashow;
84     if ((code = op_show_finish_setup(i_ctx_p, penum, 3, finish_show)) < 0) {
85 	ifree_object(penum, "op_show_enum_setup");
86 	return code;
87     }
88     return op_show_continue_pop(i_ctx_p, 3);
89 }
90 
91 /* <cx> <cy> <char> <string> widthshow - */
92 static int
zwidthshow(i_ctx_t * i_ctx_p)93 zwidthshow(i_ctx_t *i_ctx_p)
94 {
95     os_ptr op = osp;
96     gs_text_enum_t *penum;
97     double cxy[2];
98     int code;
99 
100     if ((code = op_show_setup(i_ctx_p, op)) != 0 )
101 	return code;
102     check_type(op[-1], t_integer);
103     if (gs_currentfont(igs)->FontType == ft_composite) {
104         if ((gs_char) (op[-1].value.intval) != op[-1].value.intval)
105 	    return_error(e_rangecheck);
106     } else {
107         if (op[-1].value.intval < 0 || op[-1].value.intval > 255)
108 	    return_error(e_rangecheck); /* per PLRM and CET 13-26 */
109     }
110     if ((code = num_params(op - 2, 2, cxy)) < 0 )
111         return code;
112     if ((code = gs_widthshow_begin(igs, cxy[0], cxy[1],
113 				   (gs_char) op[-1].value.intval,
114 				   op->value.bytes, r_size(op),
115 				   imemory, &penum)) < 0)
116 	return code;
117     *(op_proc_t *)&penum->enum_client_data = zwidthshow;
118     if ((code = op_show_finish_setup(i_ctx_p, penum, 4, finish_show)) < 0) {
119 	ifree_object(penum, "op_show_enum_setup");
120 	return code;
121     }
122     return op_show_continue_pop(i_ctx_p, 4);
123 }
124 
125 /* <cx> <cy> <char> <ax> <ay> <string> awidthshow - */
126 static int
zawidthshow(i_ctx_t * i_ctx_p)127 zawidthshow(i_ctx_t *i_ctx_p)
128 {
129     os_ptr op = osp;
130     gs_text_enum_t *penum;
131     double cxy[2], axy[2];
132     int code;
133 
134     if ((code = op_show_setup(i_ctx_p, op)) != 0 )
135 	return code;
136     if ((code = num_params(op - 1, 2, axy)) < 0 )
137 	return code;
138     check_type(op[-3], t_integer);
139     if (gs_currentfont(igs)->FontType == ft_composite) {
140         if ((gs_char) (op[-3].value.intval) != op[-3].value.intval)
141 	    return_error(e_rangecheck);
142     } else {
143         if (op[-3].value.intval < 0 || op[-3].value.intval > 255)
144 	    return_error(e_rangecheck); /* per PLRM and CET 13-02 */
145     }
146     if ((code = num_params(op - 4, 2, cxy)) < 0 )
147 	return code;
148     if ((code = gs_awidthshow_begin(igs, cxy[0], cxy[1],
149 				    (gs_char) op[-3].value.intval,
150 				    axy[0], axy[1],
151 				    op->value.bytes, r_size(op),
152 				    imemory, &penum)) < 0)
153 	return code;
154     *(op_proc_t *)&penum->enum_client_data = zawidthshow;
155     if ((code = op_show_finish_setup(i_ctx_p, penum, 6, finish_show)) < 0) {
156 	ifree_object(penum, "op_show_enum_setup");
157 	return code;
158     }
159     return op_show_continue_pop(i_ctx_p, 6);
160 }
161 
162 /* <proc> <string> kshow - */
163 static int
zkshow(i_ctx_t * i_ctx_p)164 zkshow(i_ctx_t *i_ctx_p)
165 {
166     os_ptr op = osp;
167     gs_text_enum_t *penum;
168     int code;
169 
170     check_read_type(*op, t_string);
171     check_proc(op[-1]);
172     /*
173      * Per PLRM Section xx.x, kshow is illegal if the current font is a
174      * composite font.  The graphics library does not have this limitation,
175      * so we check for it here.
176      */
177     if (gs_currentfont(igs)->FontType == ft_composite)
178 	return_error(e_invalidfont);
179     if ((code = op_show_setup(i_ctx_p, op)) != 0 ||
180 	(code = gs_kshow_begin(igs, op->value.bytes, r_size(op),
181 			       imemory, &penum)) < 0)
182 	return code;
183     *(op_proc_t *)&penum->enum_client_data = zkshow;
184     if ((code = op_show_finish_setup(i_ctx_p, penum, 2, finish_show)) < 0) {
185 	ifree_object(penum, "op_show_enum_setup");
186 	return code;
187     }
188     sslot = op[-1];		/* save kerning proc */
189     return op_show_continue_pop(i_ctx_p, 2);
190 }
191 
192 /* Common finish procedure for all show operations. */
193 /* Doesn't have to do anything. */
194 static int
finish_show(i_ctx_t * i_ctx_p)195 finish_show(i_ctx_t *i_ctx_p)
196 {
197     return 0;
198 }
199 
200 /* <string> stringwidth <wx> <wy> */
201 static int
zstringwidth(i_ctx_t * i_ctx_p)202 zstringwidth(i_ctx_t *i_ctx_p)
203 {
204     os_ptr op = osp;
205     gs_text_enum_t *penum;
206     int code = op_show_setup(i_ctx_p, op);
207 
208     if (code != 0 ||
209 	(code = gs_stringwidth_begin(igs, op->value.bytes, r_size(op),
210 				     imemory, &penum)) < 0)
211 	return code;
212     *(op_proc_t *)&penum->enum_client_data = zstringwidth;
213     if ((code = op_show_finish_setup(i_ctx_p, penum, 1, finish_stringwidth)) < 0) {
214 	ifree_object(penum, "op_show_enum_setup");
215 	return code;
216     }
217     return op_show_continue_pop(i_ctx_p, 1);
218 }
219 /* Finishing procedure for stringwidth. */
220 /* Pushes the accumulated width. */
221 /* This is exported for .glyphwidth (in zcharx.c). */
222 int
finish_stringwidth(i_ctx_t * i_ctx_p)223 finish_stringwidth(i_ctx_t *i_ctx_p)
224 {
225     os_ptr op = osp;
226     gs_point width;
227 
228     gs_text_total_width(senum, &width);
229     push(2);
230     make_real(op - 1, width.x);
231     make_real(op, width.y);
232     return 0;
233 }
234 
235 /* Common code for charpath and .charboxpath. */
236 static int
zchar_path(i_ctx_t * i_ctx_p,op_proc_t proc,int (* begin)(gs_state *,const byte *,uint,bool,gs_memory_t *,gs_text_enum_t **))237 zchar_path(i_ctx_t *i_ctx_p, op_proc_t proc,
238 	   int (*begin)(gs_state *, const byte *, uint,
239 			bool, gs_memory_t *, gs_text_enum_t **))
240 {
241     os_ptr op = osp;
242     gs_text_enum_t *penum;
243     int code;
244 
245     check_type(*op, t_boolean);
246     code = op_show_setup(i_ctx_p, op - 1);
247     if (code != 0 ||
248 	(code = begin(igs, op[-1].value.bytes, r_size(op - 1),
249 		      op->value.boolval, imemory, &penum)) < 0)
250 	return code;
251     *(op_proc_t *)&penum->enum_client_data = proc;
252     if ((code = op_show_finish_setup(i_ctx_p, penum, 2, finish_show)) < 0) {
253 	ifree_object(penum, "op_show_enum_setup");
254 	return code;
255     }
256     return op_show_continue_pop(i_ctx_p, 2);
257 }
258 /* <string> <outline_bool> charpath - */
259 static int
zcharpath(i_ctx_t * i_ctx_p)260 zcharpath(i_ctx_t *i_ctx_p)
261 {
262     return zchar_path(i_ctx_p, zcharpath, gs_charpath_begin);
263 }
264 /* <string> <box_bool> .charboxpath - */
265 static int
zcharboxpath(i_ctx_t * i_ctx_p)266 zcharboxpath(i_ctx_t *i_ctx_p)
267 {
268     return zchar_path(i_ctx_p, zcharboxpath, gs_charboxpath_begin);
269 }
270 
271 /* <wx> <wy> <llx> <lly> <urx> <ury> setcachedevice - */
272 int
zsetcachedevice(i_ctx_t * i_ctx_p)273 zsetcachedevice(i_ctx_t *i_ctx_p)
274 {
275     os_ptr op = osp;
276     double wbox[6];
277     gs_text_enum_t *penum = op_show_find(i_ctx_p);
278     int code = num_params(op, 6, wbox);
279 
280     if (penum == 0)
281 	return_error(e_undefined);
282     if (code < 0)
283 	return code;
284     if (zchar_show_width_only(penum))
285 	return op_show_return_width(i_ctx_p, 6, &wbox[0]);
286     code = gs_text_setcachedevice(penum, wbox);
287     if (code < 0)
288 	return code;
289     pop(6);
290     if (code == 1)
291 	clear_pagedevice(istate);
292     return 0;
293 }
294 
295 /* <w0x> <w0y> <llx> <lly> <urx> <ury> <w1x> <w1y> <vx> <vy> setcachedevice2 - */
296 int
zsetcachedevice2(i_ctx_t * i_ctx_p)297 zsetcachedevice2(i_ctx_t *i_ctx_p)
298 {
299     os_ptr op = osp;
300     double wbox[10];
301     gs_text_enum_t *penum = op_show_find(i_ctx_p);
302     int code = num_params(op, 10, wbox);
303 
304     if (penum == 0)
305 	return_error(e_undefined);
306     if (code < 0)
307 	return code;
308     if (zchar_show_width_only(penum))
309 	return op_show_return_width(i_ctx_p, 10,
310 				    (gs_rootfont(igs)->WMode ?
311 				     &wbox[6] : &wbox[0]));
312     code = gs_text_setcachedevice2(penum, wbox);
313     if (code < 0)
314 	return code;
315     pop(10);
316     if (code == 1)
317 	clear_pagedevice(istate);
318     return 0;
319 }
320 
321 /* <wx> <wy> setcharwidth - */
322 static int
zsetcharwidth(i_ctx_t * i_ctx_p)323 zsetcharwidth(i_ctx_t *i_ctx_p)
324 {
325     os_ptr op = osp;
326     double width[2];
327     gs_text_enum_t *penum = op_show_find(i_ctx_p);
328     int code = num_params(op, 2, width);
329 
330     if (penum == 0)
331 	return_error(e_undefined);
332     if (code < 0)
333 	return code;
334     if (zchar_show_width_only(penum))
335 	return op_show_return_width(i_ctx_p, 2, &width[0]);
336     code = gs_text_setcharwidth(penum, width);
337     if (code < 0)
338 	return code;
339     pop(2);
340     return 0;
341 }
342 
343 /* <dict> .fontbbox <llx> <lly> <urx> <ury> -true- */
344 /* <dict> .fontbbox -false- */
345 static int
zfontbbox(i_ctx_t * i_ctx_p)346 zfontbbox(i_ctx_t *i_ctx_p)
347 {
348     os_ptr op = osp;
349     double bbox[4];
350     int code;
351 
352     check_type(*op, t_dictionary);
353     check_dict_read(*op);
354     code = font_bbox_param(imemory, op, bbox);
355     if (code < 0)
356 	return code;
357     if (bbox[0] < bbox[2] && bbox[1] < bbox[3]) {
358 	push(4);
359 	make_reals(op - 4, bbox, 4);
360 	make_true(op);
361     } else {			/* No bbox, or an empty one. */
362 	make_false(op);
363     }
364     return 0;
365 }
366 
367 /* Export in_cachedevice flag for PDF interpreter, which, unlike
368  * PS unterpreter, ignores color operations in the inappropriate context.
369  */
370 /* - .incachedevice <bool> */
371 static int
zincachedevice(i_ctx_t * i_ctx_p)372 zincachedevice(i_ctx_t *i_ctx_p)
373 {
374     os_ptr op = osp;
375 
376     push(1);
377     make_bool(op, !!igs->in_cachedevice);
378     return 0;
379 }
380 
381 
382 /* ------ Initialization procedure ------ */
383 
384 const op_def zchar_a_op_defs[] =
385 {
386     {"3ashow", zashow},
387     {"6awidthshow", zawidthshow},
388     {"2charpath", zcharpath},
389     {"2.charboxpath", zcharboxpath},
390     {"2kshow", zkshow},
391     {"6setcachedevice", zsetcachedevice},
392     {":setcachedevice2", zsetcachedevice2},
393     {"2setcharwidth", zsetcharwidth},
394     {"1show", zshow},
395     {"1stringwidth", zstringwidth},
396     {"4widthshow", zwidthshow},
397 		/* Extensions */
398     {"1.fontbbox", zfontbbox},
399 		/* Internal operators */
400     {"0%finish_show", finish_show},
401     {"0%finish_stringwidth", finish_stringwidth},
402     {"0%op_show_continue", op_show_continue},
403     op_def_end(0)
404 };
405 
406 const op_def zchar_b_op_defs[] =
407 {
408     {"0.incachedevice", zincachedevice},
409     op_def_end(0)
410 };
411 
412 /* ------ Subroutines ------ */
413 
414 /* Most of these are exported for zchar2.c. */
415 
416 /* Convert a glyph to a ref. */
417 void
glyph_ref(const gs_memory_t * mem,gs_glyph glyph,ref * gref)418 glyph_ref(const gs_memory_t *mem, gs_glyph glyph, ref * gref)
419 {
420     if (glyph < gs_min_cid_glyph)
421         name_index_ref(mem, glyph, gref);
422     else
423 	make_int(gref, glyph - gs_min_cid_glyph);
424 }
425 
426 /* Prepare to set up for a text operator. */
427 /* Don't change any state yet. */
428 int
op_show_setup(i_ctx_t * i_ctx_p,os_ptr op)429 op_show_setup(i_ctx_t *i_ctx_p, os_ptr op)
430 {
431     check_read_type(*op, t_string);
432     return op_show_enum_setup(i_ctx_p);
433 }
434 int
op_show_enum_setup(i_ctx_t * i_ctx_p)435 op_show_enum_setup(i_ctx_t *i_ctx_p)
436 {
437     check_estack(snumpush + 2);
438     return 0;
439 }
440 
441 /* Finish setting up a text operator. */
442 int
op_show_finish_setup(i_ctx_t * i_ctx_p,gs_text_enum_t * penum,int npop,op_proc_t endproc)443 op_show_finish_setup(i_ctx_t *i_ctx_p, gs_text_enum_t * penum, int npop,
444 		     op_proc_t endproc /* end procedure */ )
445 {
446     gs_text_enum_t *osenum = op_show_find(i_ctx_p);
447     es_ptr ep = esp + snumpush;
448     gs_glyph glyph;
449     extern bool CPSI_mode;
450 
451     if (CPSI_mode) {
452 	/* CET 14-03.PS page 2 emits rangecheck before rendering a character.
453 	   Early check the text to font compatibility
454 	   with decomposing the text into characters.*/
455 	int code = gs_text_count_chars(igs, gs_get_text_params(penum), imemory);
456 
457 	if (code < 0)
458 	    return code;
459     }
460     /*
461      * If we are in the procedure of a cshow for a CID font and this is
462      * a show operator, do something special, per the Red Book.
463      */
464     if (osenum &&
465 	SHOW_IS_ALL_OF(osenum,
466 		       TEXT_FROM_STRING | TEXT_DO_NONE | TEXT_INTERVENE) &&
467 	SHOW_IS_ALL_OF(penum, TEXT_FROM_STRING | TEXT_RETURN_WIDTH) &&
468 	(glyph = gs_text_current_glyph(osenum)) != gs_no_glyph &&
469 	glyph >= gs_min_cid_glyph &&
470 
471         /* According to PLRM, we don't need to raise a rangecheck error,
472            if currentfont is changed in the proc of the operator 'cshow'. */
473 	gs_default_same_font (gs_text_current_font(osenum),
474 			      gs_text_current_font(penum), true)
475 	) {
476 	gs_text_params_t text;
477 
478 	if (!(penum->text.size == 1 &&
479 	      penum->text.data.bytes[0] ==
480 	        (gs_text_current_char(osenum) & 0xff))
481 	    )
482 	    return_error(e_rangecheck);
483 	text = penum->text;
484 	text.operation =
485 	    (text.operation &
486 	     ~(TEXT_FROM_STRING | TEXT_FROM_BYTES | TEXT_FROM_CHARS |
487 	       TEXT_FROM_GLYPHS | TEXT_FROM_SINGLE_CHAR)) |
488 	    TEXT_FROM_SINGLE_GLYPH;
489 	text.data.d_glyph = glyph;
490 	text.size = 1;
491 	gs_text_restart(penum, &text);
492     }
493     if (osenum && osenum->current_font->FontType == ft_user_defined &&
494 	osenum->orig_font->FontType == ft_composite &&
495 	((const gs_font_type0 *)osenum->orig_font)->data.FMapType == fmap_CMap) {
496 	/* A special behavior defined in PLRM3 section 5.11 page 389. */
497 	penum->outer_CID = osenum->returned.current_glyph;
498     }
499     if (osenum == NULL && !(penum->text.operation & (TEXT_FROM_GLYPHS | TEXT_FROM_SINGLE_GLYPH))) {
500         int ft = igs->root_font->FontType;
501 
502         if ((ft >= ft_CID_encrypted && ft <= ft_CID_TrueType) || ft == ft_CID_bitmap)
503             return_error(e_typecheck);
504     }
505     make_mark_estack(ep - (snumpush - 1), es_show, op_show_cleanup);
506     if (endproc == NULL)
507 	endproc = finish_show;
508     make_null(&esslot(ep));
509     make_int(&esodepth(ep), ref_stack_count_inline(&o_stack) - npop); /* Save stack depth for */
510     make_int(&esddepth(ep), ref_stack_count_inline(&d_stack));        /* correct interrupt processing */
511     make_int(&esgslevel(ep), igs->level);
512     make_null(&essfont(ep));
513     make_null(&esrfont(ep));
514     make_op_estack(&eseproc(ep), endproc);
515     make_istruct(ep, 0, penum);
516     esp = ep;
517     return 0;
518 }
519 
520 /* Continuation operator for character rendering. */
521 int
op_show_continue(i_ctx_t * i_ctx_p)522 op_show_continue(i_ctx_t *i_ctx_p)
523 {
524     int code = gs_text_update_dev_color(igs, senum);
525 
526     if (code >= 0)
527 	code = op_show_continue_dispatch(i_ctx_p, 0, gs_text_process(senum));
528     return code;
529 }
530 int
op_show_continue_pop(i_ctx_t * i_ctx_p,int npop)531 op_show_continue_pop(i_ctx_t *i_ctx_p, int npop)
532 {
533     return op_show_continue_dispatch(i_ctx_p, npop, gs_text_process(senum));
534 }
535 /*
536  * Note that op_show_continue_dispatch sets osp = op explicitly iff the
537  * dispatch succeeds.  This is so that the show operators don't pop anything
538  * from the o-stack if they don't succeed.  Note also that if it returns an
539  * error, it has freed the enumerator.
540  */
541 int
op_show_continue_dispatch(i_ctx_t * i_ctx_p,int npop,int code)542 op_show_continue_dispatch(i_ctx_t *i_ctx_p, int npop, int code)
543 {
544     os_ptr op = osp - npop;
545     gs_text_enum_t *penum = senum;
546 
547     switch (code) {
548 	case 0: {		/* all done */
549 	    os_ptr save_osp = osp;
550 
551 	    osp = op;
552 	    code = (*real_opproc(&seproc)) (i_ctx_p);
553 	    op_show_free(i_ctx_p, code);
554 	    if (code < 0) {
555 		osp = save_osp;
556 		return code;
557 	    }
558 	    return o_pop_estack;
559 	}
560 	case TEXT_PROCESS_INTERVENE: {
561 	    ref *pslot = &sslot; /* only used for kshow */
562 
563 	    push(2);
564 	    make_int(op - 1, gs_text_current_char(penum)); /* previous char */
565 	    make_int(op, gs_text_next_char(penum));
566 	    push_op_estack(op_show_continue);	/* continue after kerning */
567 	    *++esp = *pslot;	/* kerning procedure */
568 	    return o_push_estack;
569 	}
570 	case TEXT_PROCESS_RENDER: {
571 	    gs_font *pfont = gs_currentfont(igs);
572 	    font_data *pfdata = pfont_data(pfont);
573 	    gs_char chr = gs_text_current_char(penum);
574 	    gs_glyph glyph = gs_text_current_glyph(penum);
575 
576 	    push(2);
577 	    op[-1] = pfdata->dict;	/* push the font */
578 	    /*
579 	     * For Type 1 and Type 4 fonts, prefer BuildChar to BuildGlyph
580 	     * if there is no glyph, or if there is both a character and a
581 	     * glyph and the glyph is the one that corresponds to the
582 	     * character in the Encoding, so that PostScript procedures
583 	     * appearing in the CharStrings dictionary will receive the
584 	     * character code rather than the character name; for Type 3
585 	     * fonts, prefer BuildGlyph to BuildChar.  For other font types
586 	     * (such as CID fonts), only BuildGlyph will be present.
587 	     */
588 	    if (pfont->FontType == ft_user_defined) {
589 		/* Type 3 font, prefer BuildGlyph. */
590 		if (level2_enabled &&
591 		    !r_has_type(&pfdata->BuildGlyph, t_null) &&
592 		    glyph != gs_no_glyph
593 		    ) {
594 		    glyph_ref(imemory, glyph, op);
595 		    esp[2] = pfdata->BuildGlyph;
596 		} else if (r_has_type(&pfdata->BuildChar, t_null))
597 		    goto err;
598 		else if (chr == gs_no_char) {
599 		    /* glyphshow, reverse map the character */
600 		    /* through the Encoding */
601 		    ref gref;
602 		    const ref *pencoding = &pfdata->Encoding;
603 
604 		    glyph_ref(imemory, glyph, &gref);
605 		    if (!map_glyph_to_char(imemory, &gref, pencoding,
606 					   (ref *) op)
607 			) {	/* Not found, try .notdef */
608 		        name_enter_string(imemory, ".notdef", &gref);
609 			if (!map_glyph_to_char(imemory, &gref,
610 					       pencoding,
611 					       (ref *) op)
612 			    )
613 			    goto err;
614 		    }
615 		    esp[2] = pfdata->BuildChar;
616 		} else {
617 		    make_int(op, chr & 0xff);
618 		    esp[2] = pfdata->BuildChar;
619 		}
620 	    } else {
621 		/*
622 		 * For a Type 1 or Type 4 font, prefer BuildChar or
623 		 * BuildGlyph as described above: we know that both
624 		 * BuildChar and BuildGlyph are present.  For other font
625 		 * types, only BuildGlyph is available.
626 		 */
627 		ref eref, gref;
628 
629 		if (chr != gs_no_char &&
630 		    !r_has_type(&pfdata->BuildChar, t_null) &&
631 		    (glyph == gs_no_glyph ||
632 		     (array_get(imemory, &pfdata->Encoding, (long)(chr & 0xff), &eref) >= 0 &&
633 		      (glyph_ref(imemory, glyph, &gref), obj_eq(imemory, &gref, &eref))))
634 		    ) {
635 		    make_int(op, chr & 0xff);
636 		    esp[2] = pfdata->BuildChar;
637 		} else {
638 		    /* We might not have a glyph: substitute 0. **HACK** */
639 		    if (glyph == gs_no_glyph)
640 			make_int(op, 0);
641 		    else
642 		        glyph_ref(imemory, glyph, op);
643 		    esp[2] = pfdata->BuildGlyph;
644 		}
645 	    }
646 	    /* Save the stack depths in case we bail out. */
647 	    sodepth.value.intval = ref_stack_count(&o_stack) - 2;
648 	    sddepth.value.intval = ref_stack_count(&d_stack);
649 	    push_op_estack(op_show_continue);
650 	    ++esp;		/* skip BuildChar or BuildGlyph proc */
651 	    return o_push_estack;
652 	}
653 	case TEXT_PROCESS_CDEVPROC:
654 	    {   gs_font *pfont = penum->current_font;
655 		ref cnref;
656 		op_proc_t cont = op_show_continue, exec_cont = 0;
657 		gs_glyph glyph = penum->returned.current_glyph;
658 		int code;
659 
660 		pop(npop);
661 		op = osp;
662 		glyph_ref(imemory, glyph, &cnref);
663 		if (pfont->FontType == ft_CID_TrueType) {
664 		    gs_font_type42 *pfont42 = (gs_font_type42 *)pfont;
665 		    uint glyph_index = pfont42->data.get_glyph_index(pfont42, glyph);
666 
667 		    code = zchar42_set_cache(i_ctx_p, (gs_font_base *)pfont42,
668 				    &cnref, glyph_index, cont, &exec_cont);
669 		} else if (pfont->FontType == ft_CID_encrypted)
670 		    code = z1_set_cache(i_ctx_p, (gs_font_base *)pfont,
671 				    &cnref, glyph, cont, &exec_cont);
672 		else
673 		    return_error(e_unregistered); /* Unimplemented. */
674 		if (exec_cont != 0)
675 		    return_error(e_unregistered); /* Must not happen. */
676 		return code;
677 	    }
678 	default:		/* error */
679 err:
680 	    if (code >= 0)
681 		code = gs_note_error(e_invalidfont);
682 	    return op_show_free(i_ctx_p, code);
683     }
684 }
685 /* Reverse-map a glyph name to a character code for glyphshow. */
686 static bool
map_glyph_to_char(const gs_memory_t * mem,const ref * pgref,const ref * pencoding,ref * pch)687 map_glyph_to_char(const gs_memory_t *mem, const ref * pgref, const ref * pencoding, ref * pch)
688 {
689     uint esize = r_size(pencoding);
690     uint ch;
691     ref eref;
692 
693     for (ch = 0; ch < esize; ch++) {
694         array_get(mem, pencoding, (long)ch, &eref);
695 	if (obj_eq(mem, pgref, &eref)) {
696 	    make_int(pch, ch);
697 	    return true;
698 	}
699     }
700     return false;
701 }
702 
703 /* Find the index of the e-stack mark for the current show enumerator. */
704 /* Return 0 if we can't find the mark. */
705 static uint
op_show_find_index(i_ctx_t * i_ctx_p)706 op_show_find_index(i_ctx_t *i_ctx_p)
707 {
708     ref_stack_enum_t rsenum;
709     uint count = 0;
710 
711     ref_stack_enum_begin(&rsenum, &e_stack);
712     do {
713 	es_ptr ep = rsenum.ptr;
714 	uint size = rsenum.size;
715 
716 	for (ep += size - 1; size != 0; size--, ep--, count++)
717 	    if (r_is_estack_mark(ep) && estack_mark_index(ep) == es_show)
718 		return count;
719     } while (ref_stack_enum_next(&rsenum));
720     return 0;		/* no mark */
721 }
722 
723 /* Find the current show enumerator on the e-stack. */
724 gs_text_enum_t *
op_show_find(i_ctx_t * i_ctx_p)725 op_show_find(i_ctx_t *i_ctx_p)
726 {
727     uint index = op_show_find_index(i_ctx_p);
728 
729     if (index == 0)
730 	return 0;		/* no mark */
731     return r_ptr(ref_stack_index(&e_stack, index - (snumpush - 1)),
732 		 gs_text_enum_t);
733 }
734 
735 /*
736  * Return true if we only need the width from the rasterizer
737  * and can short-circuit the full rendering of the character,
738  * false if we need the actual character bits.  This is only safe if
739  * we know the character is well-behaved, i.e., is not defined by an
740  * arbitrary PostScript procedure.
741  */
742 bool
zchar_show_width_only(const gs_text_enum_t * penum)743 zchar_show_width_only(const gs_text_enum_t * penum)
744 {
745     if (!gs_text_is_width_only(penum))
746 	return false;
747     switch (penum->orig_font->FontType) {
748     case ft_encrypted:
749     case ft_encrypted2:
750     case ft_CID_encrypted:
751     case ft_CID_TrueType:
752     case ft_CID_bitmap:
753     case ft_TrueType:
754 	return true;
755     default:
756 	return false;
757     }
758 }
759 
760 /* Shortcut the BuildChar or BuildGlyph procedure at the point */
761 /* of the setcharwidth or the setcachedevice[2] if we are in */
762 /* a stringwidth or cshow, or if we are only collecting the scalable */
763 /* width for an xfont character. */
764 static int
op_show_return_width(i_ctx_t * i_ctx_p,uint npop,double * pwidth)765 op_show_return_width(i_ctx_t *i_ctx_p, uint npop, double *pwidth)
766 {
767     uint index = op_show_find_index(i_ctx_p);
768     es_ptr ep = (es_ptr) ref_stack_index(&e_stack, index - (snumpush - 1));
769     int code = gs_text_setcharwidth(esenum(ep), pwidth);
770     uint ocount, dsaved, dcount;
771 
772     if (code < 0)
773 	return code;
774     /* Restore the operand and dictionary stacks. */
775     ocount = ref_stack_count(&o_stack) - (uint) esodepth(ep).value.intval;
776     if (ocount < npop)
777 	return_error(e_stackunderflow);
778     dsaved = (uint) esddepth(ep).value.intval;
779     dcount = ref_stack_count(&d_stack);
780     if (dcount < dsaved)
781 	return_error(e_dictstackunderflow);
782     while (dcount > dsaved) {
783 	code = zend(i_ctx_p);
784 	if (code < 0)
785 	    return code;
786 	dcount--;
787     }
788     ref_stack_pop(&o_stack, ocount);
789     /* We don't want to pop the mark or the continuation */
790     /* procedure (op_show_continue or cshow_continue). */
791     pop_estack(i_ctx_p, index - snumpush);
792     return o_pop_estack;
793 }
794 
795 /*
796  * Restore state after finishing, or unwinding from an error within, a show
797  * operation.  Note that we assume op == osp, and may reset osp.
798  */
799 static int
op_show_restore(i_ctx_t * i_ctx_p,bool for_error)800 op_show_restore(i_ctx_t *i_ctx_p, bool for_error)
801 {
802     register es_ptr ep = esp + snumpush;
803     gs_text_enum_t *penum = esenum(ep);
804     int saved_level = esgslevel(ep).value.intval;
805     int code = 0;
806 
807     if (for_error) {
808 #if 0 /* Disabled for CPSI compatibility for 13-12-4.
809          CPSI doesn't remove cshow, kshow proc operands. */
810 	uint saved_count = esodepth(ep).value.intval;
811 	uint count = ref_stack_count(&o_stack);
812 
813 	if (count > saved_count)	/* if <, we're in trouble */
814 	    ref_stack_pop(&o_stack, count - saved_count);
815 #endif
816 	if (ep[1].value.opproc == op_show_continue && penum->enum_client_data != NULL) {
817 	    /* Replace the continuation operaton on estack with the right operator : */
818 	    op_proc_t proc;
819 
820 	    *(void **)&proc = penum->enum_client_data;
821 	    make_op_estack(ep + 1, proc);
822 	}
823     }
824     if (SHOW_IS_STRINGWIDTH(penum) && igs->text_rendering_mode != 3) {
825 	/* stringwidth does an extra gsave */
826 	--saved_level;
827     }
828     if (penum->text.operation & TEXT_REPLACE_WIDTHS) {
829 	gs_free_const_object(penum->memory, penum->text.y_widths, "y_widths");
830 	if (penum->text.x_widths != penum->text.y_widths)
831 	    gs_free_const_object(penum->memory, penum->text.x_widths, "x_widths");
832     }
833     /*
834      * We might have been inside a cshow, in which case currentfont was
835      * reset temporarily, as though we were inside a BuildChar/ BuildGlyph
836      * procedure.  To handle this case, set currentfont back to its original
837      * state.  NOTE: this code previously used fstack[0] in the enumerator
838      * for the root font: we aren't sure that this change is correct.
839      */
840     gs_set_currentfont(igs, penum->orig_font);
841     while (igs->level > saved_level && code >= 0) {
842 	if (igs->saved == 0 || igs->saved->saved == 0) {
843 	    /*
844 	     * Bad news: we got an error inside a save inside a BuildChar or
845 	     * BuildGlyph.  Don't attempt to recover.
846 	     */
847 	    code = gs_note_error(e_Fatal);
848 	} else
849 	    code = gs_grestore(igs);
850     }
851     gs_text_release(penum, "op_show_restore");
852     return code;
853 }
854 /* Clean up after an error. */
855 static int
op_show_cleanup(i_ctx_t * i_ctx_p)856 op_show_cleanup(i_ctx_t *i_ctx_p)
857 {
858     return op_show_restore(i_ctx_p, true);
859 }
860 /* Clean up after termination of a show operation. */
861 int
op_show_free(i_ctx_t * i_ctx_p,int code)862 op_show_free(i_ctx_t *i_ctx_p, int code)
863 {
864     int rcode;
865 
866     esp -= snumpush;
867     rcode = op_show_restore(i_ctx_p, code < 0);
868     return (rcode < 0 ? rcode : code);
869 }
870 
871 /* Get a FontBBox parameter from a font dictionary. */
872 int
font_bbox_param(const gs_memory_t * mem,const ref * pfdict,double bbox[4])873 font_bbox_param(const gs_memory_t *mem, const ref * pfdict, double bbox[4])
874 {
875     ref *pbbox;
876 
877     /*
878      * Pre-clear the bbox in case it's invalid.  The Red Books say that
879      * FontBBox is required, but old Adobe interpreters don't require
880      * it, and a few user-written fonts don't supply it, or supply one
881      * of the wrong size (!); also, PageMaker 5.0 (an Adobe product!)
882      * sometimes emits an absurd bbox for Type 1 fonts converted from
883      * TrueType.
884      */
885     bbox[0] = bbox[1] = bbox[2] = bbox[3] = 0.0;
886     if (dict_find_string(pfdict, "FontBBox", &pbbox) > 0) {
887 	if (!r_is_array(pbbox))
888 	    return_error(e_typecheck);
889 	if (r_size(pbbox) == 4) {
890 	    const ref_packed *pbe = pbbox->value.packed;
891 	    ref rbe[4];
892 	    int i;
893 	    int code;
894 	    float dx, dy, ratio;
895 	    const float max_ratio = 12; /* From the bug 687594. */
896 
897 	    for (i = 0; i < 4; i++) {
898 		packed_get(mem, pbe, rbe + i);
899 		pbe = packed_next(pbe);
900 	    }
901 	    if ((code = num_params(rbe + 3, 4, bbox)) < 0)
902 		return code;
903  	    /* Require "reasonable" values. */
904 	    dx = bbox[2] - bbox[0];
905 	    dy = bbox[3] - bbox[1];
906 	    if (dx <= 0 || dy <= 0 ||
907 		(ratio = dy / dx) < 1 / max_ratio || ratio > max_ratio
908 		)
909 		bbox[0] = bbox[1] = bbox[2] = bbox[3] = 0.0;
910 	}
911     } else if (CPSI_mode) {
912         return_error(e_invalidfont); /* CPSI requires FontBBox */
913     }
914     return 0;
915 }
916