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: zfunc4.c 9778 2009-06-05 05:55:54Z alexcher $ */
15 /* PostScript language support for FunctionType 4 (PS Calculator) Functions */
16 #include "memory_.h"
17 #include "ghost.h"
18 #include "oper.h"
19 #include "opextern.h"
20 #include "gsfunc.h"
21 #include "gsfunc4.h"
22 #include "gsutil.h"
23 #include "idict.h"
24 #include "ifunc.h"
25 #include "iname.h"
26 #include "dstack.h"
27 #include "ialloc.h"
28 #include "gzstate.h"	    /* these are needed to check if device is pdfwrite */
29 #include "gxdevcli.h"	    /* these are needed to check if device is pdfwrite */
30 #include "string_.h"	    /* these are needed to check if device is pdfwrite */
31 #include "zfunc.h"
32 #include "zcolor.h"
33 
34 /*
35  * FunctionType 4 functions are not defined in the PostScript language.  We
36  * provide support for them because they are needed for PDF 1.3.  In
37  * addition to the standard FunctionType, Domain, and Range keys, they have
38  * a Function key whose value is a procedure in a restricted subset of the
39  * PostScript language.  Specifically, the procedure must (recursively)
40  * contain only integer, real, Boolean, and procedure constants (only as
41  * literal operands of if and and ifelse), and operators chosen from the set
42  * given below.  Note that names other than true and false are not allowed:
43  * the procedure must be 'bound'.
44  *
45  * The following list is taken directly from the PDF 1.3 documentation.
46  */
47 #define XOP(zfn) int zfn(i_ctx_t *)
48 XOP(zabs); XOP(zand); XOP(zatan); XOP(zbitshift);
49 XOP(zceiling); XOP(zcos); XOP(zcvi); XOP(zcvr);
50 XOP(zdiv); XOP(zexp); XOP(zfloor); XOP(zidiv);
51 XOP(zln); XOP(zlog); XOP(zmod); XOP(zmul);
52 XOP(zneg); XOP(znot); XOP(zor); XOP(zround);
53 XOP(zsin); XOP(zsqrt); XOP(ztruncate); XOP(zxor);
54 XOP(zeq); XOP(zge); XOP(zgt); XOP(zle); XOP(zlt); XOP(zne);
55 XOP(z2copy);
56 #undef XOP
57 typedef struct calc_op_s {
58     op_proc_t proc;
59     gs_PtCr_opcode_t opcode;
60 } calc_op_t;
61 static const calc_op_t calc_ops[] = {
62 
63     /* Arithmetic operators */
64 
65     {zabs, PtCr_abs},
66     {zadd, PtCr_add},
67     {zand, PtCr_and},
68     {zatan, PtCr_atan},
69     {zbitshift, PtCr_bitshift},
70     {zceiling, PtCr_ceiling},
71     {zcos, PtCr_cos},
72     {zcvi, PtCr_cvi},
73     {zcvr, PtCr_cvr},
74     {zdiv, PtCr_div},
75     {zexp, PtCr_exp},
76     {zfloor, PtCr_floor},
77     {zidiv, PtCr_idiv},
78     {zln, PtCr_ln},
79     {zlog, PtCr_log},
80     {zmod, PtCr_mod},
81     {zmul, PtCr_mul},
82     {zneg, PtCr_neg},
83     {znot, PtCr_not},
84     {zor, PtCr_or},
85     {zround, PtCr_round},
86     {zsin, PtCr_sin},
87     {zsqrt, PtCr_sqrt},
88     {zsub, PtCr_sub},
89     {ztruncate, PtCr_truncate},
90     {zxor, PtCr_xor},
91 
92     /* Comparison operators */
93 
94     {zeq, PtCr_eq},
95     {zge, PtCr_ge},
96     {zgt, PtCr_gt},
97     {zle, PtCr_le},
98     {zlt, PtCr_lt},
99     {zne, PtCr_ne},
100 
101     /* Stack operators */
102 
103     {zcopy, PtCr_copy},
104     {z2copy, PtCr_copy},
105     {zdup, PtCr_dup},
106     {zexch, PtCr_exch},
107     {zindex, PtCr_index},
108     {zpop, PtCr_pop},
109     {zroll, PtCr_roll}
110 
111     /* Special operators */
112 
113     /*{zif, PtCr_if},*/
114     /*{zifelse, PtCr_ifelse},*/
115     /*{ztrue, PtCr_true},*/
116     /*{zfalse, PtCr_false}*/
117 };
118 
119 /* Fix up an if or ifelse forward reference. */
120 static void
psc_fixup(byte * p,byte * to)121 psc_fixup(byte *p, byte *to)
122 {
123     int skip = to - (p + 3);
124 
125     p[1] = (byte)(skip >> 8);
126     p[2] = (byte)skip;
127 }
128 
129 /* Check whether the ref is a given operator or resolves to it */
130 static bool
resolves_to_oper(i_ctx_t * i_ctx_p,const ref * pref,const op_proc_t proc)131 resolves_to_oper(i_ctx_t *i_ctx_p, const ref *pref, const op_proc_t proc)
132 {
133     if (!r_has_attr(pref, a_executable))
134         return false;
135     if (r_btype(pref) == t_operator) {
136         return pref->value.opproc == proc;
137     } else if (r_btype(pref) == t_name) {
138         ref * val;
139         if (dict_find(systemdict, pref, &val) <= 0)
140 	    return false;
141         if (r_btype(val) != t_operator)
142 	    return false;
143         if (!r_has_attr(val, a_executable))
144 	    return false;
145         return val->value.opproc == proc;
146     }
147    else
148       return false;
149 }
150 
151 /*
152  * Check a calculator function for validity, optionally storing its encoded
153  * representation and add the size of the encoded representation to *psize.
154  * Note that we arbitrarily limit the depth of procedure nesting.  pref is
155  * known to be a procedure.
156  */
157 static int
check_psc_function(i_ctx_t * i_ctx_p,const ref * pref,int depth,byte * ops,int * psize)158 check_psc_function(i_ctx_t *i_ctx_p, const ref *pref, int depth, byte *ops, int *psize)
159 {
160     uint i;
161     uint size = r_size(pref);
162 
163     for (i = 0; i < size; ++i) {
164 	byte no_ops[1 + max(sizeof(int), sizeof(float))];
165 	byte *p = (ops ? ops + *psize : no_ops);
166 	ref elt, elt2, elt3;
167 	ref * delp;
168 	int code;
169 
170 	array_get(imemory, pref, i, &elt);
171 	switch (r_btype(&elt)) {
172 	case t_integer: {
173 	    int i = elt.value.intval;
174 
175 	    if (i == (byte)i) {
176 		*p = PtCr_byte;
177 		p[1] = (byte)i;
178 		*psize += 2;
179 	    } else {
180 		*p = PtCr_int;
181 		memcpy(p + 1, &i, sizeof(i));
182 		*psize += 1 + sizeof(int);
183 	    }
184 	    break;
185 	}
186 	case t_real: {
187 	    float f = elt.value.realval;
188 
189 	    *p = PtCr_float;
190 	    memcpy(p + 1, &f, sizeof(f));
191 	    *psize += 1 + sizeof(float);
192 	    break;
193 	}
194 	case t_boolean:
195 	    *p = (elt.value.boolval ? PtCr_true : PtCr_false);
196 	    ++*psize;
197 	    break;
198 	case t_name:
199 	    if (!r_has_attr(&elt, a_executable))
200 		return_error(e_rangecheck);
201 	    name_string_ref(imemory, &elt, &elt);
202 	    if (!bytes_compare(elt.value.bytes, r_size(&elt),
203 			       (const byte *)"true", 4)) {
204 		*p = PtCr_true;
205 	        ++*psize;
206 	        break;
207 	    }
208 	    if (!bytes_compare(elt.value.bytes, r_size(&elt),
209 				      (const byte *)"false", 5)) {
210 		*p = PtCr_false;
211 	        ++*psize;
212 	        break;
213 	    }
214 	    /* Check if the name is a valid operator in systemdict */
215 	    if (dict_find(systemdict, &elt, &delp) <= 0)
216 		return_error(e_undefined);
217 	    if (r_btype(delp) != t_operator)
218 		return_error(e_typecheck);
219 	    if (!r_has_attr(delp, a_executable))
220 		return_error(e_rangecheck);
221 	    elt = *delp;
222 	    /* Fall into the operator case */
223 	case t_operator: {
224 	    int j;
225 
226 	    for (j = 0; j < countof(calc_ops); ++j)
227 		if (elt.value.opproc == calc_ops[j].proc) {
228 		    *p = calc_ops[j].opcode;
229 		    ++*psize;
230 		    goto next;
231 		}
232 	    return_error(e_rangecheck);
233 	}
234 	default: {
235 	    if (!r_is_proc(&elt))
236 		return_error(e_typecheck);
237 	    if (depth == MAX_PSC_FUNCTION_NESTING)
238 		return_error(e_limitcheck);
239 	    if ((code = array_get(imemory, pref, ++i, &elt2)) < 0)
240 		return code;
241 	    *psize += 3;
242 	    code = check_psc_function(i_ctx_p, &elt, depth + 1, ops, psize);
243 	    if (code < 0)
244 		return code;
245 	    /* Check for { proc } repeat | {proc} if | {proc1} {proc2} ifelse */
246 	    if (resolves_to_oper(i_ctx_p, &elt2, zrepeat)) {
247 		/* We can't handle 'repeat' with pdfwrite since it emits FunctionType 4 */
248 		if (strcmp(i_ctx_p->pgs->device->dname, "pdfwrite") == 0)
249 		    return_error(e_rangecheck);
250 		if (ops) {
251 		    *p = PtCr_repeat;
252 		    psc_fixup(p, ops + *psize);
253 		    p = ops + *psize;
254 		    *p++ = PtCr_repeat_end;
255 		}
256 		*psize += 1;	/* extra room for repeat_end */
257 	    } else if (resolves_to_oper(i_ctx_p, &elt2, zif)) {
258 		if (ops) {
259 		    *p = PtCr_if;
260 		    psc_fixup(p, ops + *psize);
261 		}
262 	    } else if (!r_is_proc(&elt2))
263 		return_error(e_rangecheck);
264     	    else if ((code = array_get(imemory, pref, ++i, &elt3)) < 0)
265 		return code;
266 	    else if (resolves_to_oper(i_ctx_p, &elt3, zifelse)) {
267 		if (ops) {
268 		    *p = PtCr_if;
269 		    psc_fixup(p, ops + *psize + 3);
270 		    p = ops + *psize;
271 		    *p = PtCr_else;
272 		}
273 		*psize += 3;
274 		code = check_psc_function(i_ctx_p, &elt2, depth + 1, ops, psize);
275 		if (code < 0)
276 		    return code;
277 		if (ops)
278 		    psc_fixup(p, ops + *psize);
279 	    } else
280 		return_error(e_rangecheck);
281 	    }	 /* end 'default' */
282 	}
283     next:
284 	DO_NOTHING;
285     }
286     return 0;
287 }
288 #undef MAX_PSC_FUNCTION_NESTING
289 
290 /* Check prototype */
291 build_function_proc(gs_build_function_4);
292 
293 /* Finish building a FunctionType 4 (PostScript Calculator) function. */
294 int
gs_build_function_4(i_ctx_t * i_ctx_p,const ref * op,const gs_function_params_t * mnDR,int depth,gs_function_t ** ppfn,gs_memory_t * mem)295 gs_build_function_4(i_ctx_t *i_ctx_p, const ref *op, const gs_function_params_t * mnDR,
296 		    int depth, gs_function_t ** ppfn, gs_memory_t *mem)
297 {
298     gs_function_PtCr_params_t params;
299     ref *proc;
300     int code;
301     byte *ops;
302     int size;
303 
304     *(gs_function_params_t *)&params = *mnDR;
305     params.ops.data = 0;	/* in case of failure */
306     params.ops.size = 0;	/* ditto */
307     if (dict_find_string(op, "Function", &proc) <= 0) {
308 	code = gs_note_error(e_rangecheck);
309 	goto fail;
310     }
311     if (!r_is_proc(proc)) {
312 	code = gs_note_error(e_typecheck);
313 	goto fail;
314     }
315     size = 0;
316     code = check_psc_function(i_ctx_p, proc, 0, NULL, &size);
317     if (code < 0)
318 	goto fail;
319     ops = gs_alloc_string(mem, size + 1, "gs_build_function_4(ops)");
320     if (ops == 0) {
321 	code = gs_note_error(e_VMerror);
322 	goto fail;
323     }
324     size = 0;
325     check_psc_function(i_ctx_p, proc, 0, ops, &size); /* can't fail */
326     ops[size] = PtCr_return;
327     params.ops.data = ops;
328     params.ops.size = size + 1;
329     code = gs_function_PtCr_init(ppfn, &params, mem);
330     if (code >= 0)
331 	return 0;
332     /* free_params will free the ops string */
333 fail:
334     gs_function_PtCr_free_params(&params, mem);
335     return (code < 0 ? code : gs_note_error(e_rangecheck));
336 }
337 
make_type4_function(i_ctx_t * i_ctx_p,ref * arr,ref * pproc,gs_function_t ** func)338 int make_type4_function(i_ctx_t * i_ctx_p, ref *arr, ref *pproc, gs_function_t **func)
339 {
340     int code, size, num_components, CIESubst;
341     byte *ops;
342     gs_function_PtCr_params_t params;
343     float *ptr;
344     ref alternatespace, *palternatespace = &alternatespace;
345     PS_colour_space_t *space, *altspace;
346 
347     code = get_space_object(i_ctx_p, arr, &space);
348     if (code < 0)
349 	return code;
350     if (!space->alternateproc)
351 	return e_typecheck;
352     code = space->alternateproc(i_ctx_p, arr, &palternatespace, &CIESubst);
353     if (code < 0)
354 	return code;
355     code = get_space_object(i_ctx_p, palternatespace, &altspace);
356     if (code < 0)
357 	return code;
358 
359     code = space->numcomponents(i_ctx_p, arr, &num_components);
360     if (code < 0)
361 	return code;
362     ptr = (float *)gs_alloc_byte_array(imemory, num_components * 2, sizeof(float), "make_type4_function(Domain)");
363     if (!ptr)
364 	return e_VMerror;
365     code = space->domain(i_ctx_p, arr, ptr);
366     if (code < 0) {
367 	gs_free_const_object(imemory, ptr, "make_type4_function(Domain)");
368 	return code;
369     }
370     params.Domain = ptr;
371     params.m = num_components;
372 
373     code = altspace->numcomponents(i_ctx_p, &alternatespace, &num_components);
374     if (code < 0) {
375 	gs_free_const_object(imemory, params.Domain, "make_type4_function(Domain)");
376 	return code;
377     }
378     ptr = (float *)gs_alloc_byte_array(imemory, num_components * 2, sizeof(float), "make_type4_function(Range)");
379     if (!ptr) {
380 	gs_free_const_object(imemory, params.Domain, "make_type4_function(Domain)");
381 	return e_VMerror;
382     }
383     code = altspace->range(i_ctx_p, &alternatespace, ptr);
384     if (code < 0) {
385 	gs_free_const_object(imemory, ptr, "make_type4_function(Domain)");
386 	gs_free_const_object(imemory, params.Domain, "make_type4_function(Range)");
387 	return code;
388     }
389     params.Range = ptr;
390     params.n = num_components;
391 
392     params.ops.data = 0;	/* in case of failure, see gs_function_PtCr_free_params */
393     params.ops.size = 0;	/* ditto */
394     size = 0;
395     code = check_psc_function(i_ctx_p, (const ref *)pproc, 0, NULL, &size);
396     if (code < 0) {
397 	gs_function_PtCr_free_params(&params, imemory);
398 	return code;
399     }
400     ops = gs_alloc_string(imemory, size + 1, "make_type4_function(ops)");
401     size = 0;
402     check_psc_function(i_ctx_p, (const ref *)pproc, 0, ops, &size); /* can't fail */
403     ops[size] = PtCr_return;
404     params.ops.data = ops;
405     params.ops.size = size + 1;
406     code = gs_function_PtCr_init(func, &params, imemory);
407     if (code < 0)
408 	gs_function_PtCr_free_params(&params, imemory);
409 
410     return code;
411 }
412