]> git.ipfire.org Git - thirdparty/cups.git/blob - pstoraster/zfunc.c
Merge changes from 1.1 tree.
[thirdparty/cups.git] / pstoraster / zfunc.c
1 /*
2 Copyright 2001 by Easy Software Products.
3 Copyright 1997, 1998 Aladdin Enterprises. All rights reserved.
4
5 This file is part of GNU Ghostscript.
6
7 GNU Ghostscript is distributed in the hope that it will be useful, but
8 WITHOUT ANY WARRANTY. No author or distributor accepts responsibility
9 to anyone for the consequences of using it or for whether it serves any
10 particular purpose or works at all, unless he says so in writing. Refer
11 to the GNU General Public License for full details.
12
13 Everyone is granted permission to copy, modify and redistribute GNU
14 Ghostscript, but only under the conditions described in the GNU General
15 Public License. A copy of this license is supposed to have been given
16 to you along with GNU Ghostscript so you can know your rights and
17 responsibilities. It should be in a file named COPYING. Among other
18 things, the copyright notice and this notice must be preserved on all
19 copies.
20
21 Aladdin Enterprises supports the work of the GNU Project, but is not
22 affiliated with the Free Software Foundation or the GNU Project. GNU
23 Ghostscript, as distributed by Aladdin Enterprises, does not require any
24 GNU software to build or run it.
25 */
26
27 /*$Id: zfunc.c,v 1.1.2.1 2001/05/13 18:38:33 mike Exp $ */
28 /* Generic PostScript language interface to Functions */
29 #include "memory_.h"
30 #include "ghost.h"
31 #include "oper.h"
32 #include "gsfunc.h"
33 #include "gsstruct.h"
34 #include "ialloc.h"
35 #include "idict.h"
36 #include "idparam.h"
37 #include "ifunc.h"
38 #include "store.h"
39
40 /* Define the maximum depth of nesting of subsidiary functions. */
41 #define MAX_SUB_FUNCTION_DEPTH 3
42
43 /* Define the table of build procedures. */
44 build_function_proc((*build_function_procs[5])) = {
45 build_function_undefined, build_function_undefined, build_function_undefined,
46 build_function_undefined, build_function_undefined
47 };
48
49 int
50 build_function_undefined(const_os_ptr op, const gs_function_params_t * mnDR,
51 int depth, gs_function_t ** ppfn)
52 {
53 return_error(e_rangecheck);
54 }
55
56 /* GC descriptors */
57 gs_private_st_ptr(st_function_ptr, gs_function_t *, "gs_function_t *",
58 function_ptr_enum_ptrs, function_ptr_reloc_ptrs);
59 gs_private_st_element(st_function_ptr_element, gs_function_t *,
60 "gs_function_t *[]", function_ptr_element_enum_ptrs,
61 function_ptr_element_reloc_ptrs, st_function_ptr);
62
63 /* ------ Operators ------ */
64
65 private int zexecfunction(P1(os_ptr op));
66
67 /* <dict> .buildfunction <function_struct> */
68 private int
69 zbuildfunction(os_ptr op)
70 {
71 gs_function_t *pfn;
72 ref cref; /* closure */
73 int code;
74
75 code = ialloc_ref_array(&cref, a_executable | a_execute, 2,
76 ".buildfunction");
77 if (code < 0)
78 return code;
79 code = fn_build_function(op, &pfn);
80 if (code < 0) {
81 ifree_ref_array(&cref, ".buildfunction");
82 return code;
83 }
84 make_istruct_new(cref.value.refs, a_executable | a_execute, pfn);
85 make_oper_new(cref.value.refs + 1, 0, zexecfunction);
86 ref_assign(op, &cref);
87 return 0;
88 }
89
90 /* <in1> ... <function_struct> %execfunction <out1> ... */
91 private int
92 zexecfunction(os_ptr op)
93 { /*
94 * Since this operator's name begins with %, the name is not defined
95 * in systemdict. The only place this operator can ever appear is
96 * in the execute-only closure created by .buildfunction.
97 * Therefore, in principle it is unnecessary to check the argument.
98 * However, we do a little checking anyway just on general
99 * principles. Note that since the argument may be an instance of
100 * any subclass of gs_function_t, we currently have no way to check
101 * its type.
102 */
103 if (!r_is_struct(op) ||
104 r_has_masked_attrs(op, a_executable | a_execute, a_all)
105 )
106 return_error(e_typecheck);
107 {
108 gs_function_t *pfn = (gs_function_t *) op->value.pstruct;
109 int m = pfn->params.m, n = pfn->params.n;
110 int diff = n - (m + 1);
111
112 if (diff > 0)
113 check_ostack(diff);
114 {
115 float *in = (float *)ialloc_byte_array(m, sizeof(float),
116 "%execfunction(in)");
117 float *out = (float *)ialloc_byte_array(n, sizeof(float),
118 "%execfunction(out)");
119 int code;
120
121 if (in == 0 || out == 0)
122 code = gs_note_error(e_VMerror);
123 else if ((code = float_params(op - 1, m, in)) < 0 ||
124 (code = gs_function_evaluate(pfn, in, out)) < 0
125 )
126 DO_NOTHING;
127 else {
128 if (diff > 0)
129 push(diff) /* can't fail */ /* MRS: No trailing ; */
130 else if (diff < 0) {
131 pop(-diff);
132 op = osp;
133 }
134 code = make_floats(op + 1 - n, out, n);
135 }
136 ifree_object(out, "%execfunction(out)");
137 ifree_object(in, "%execfunction(in)");
138 return code;
139 }
140 }
141 }
142
143 /* ------ Procedures ------ */
144
145 /* Build a function structure from a PostScript dictionary. */
146 int
147 fn_build_sub_function(const ref * op, gs_function_t ** ppfn, int depth)
148 {
149 int code, type;
150 gs_function_params_t params;
151
152 if (depth > MAX_SUB_FUNCTION_DEPTH)
153 return_error(e_limitcheck);
154 check_type(*op, t_dictionary);
155 code = dict_int_param(op, "FunctionType", 0,
156 countof(build_function_procs) - 1, -1, &type);
157 if (code < 0)
158 return code;
159 /* Collect parameters common to all function types. */
160 params.Domain = 0;
161 params.Range = 0;
162 code = fn_build_float_array(op, "Domain", true, true, &params.Domain);
163 if (code < 0)
164 goto fail;
165 params.m = code >> 1;
166 code = fn_build_float_array(op, "Range", false, true, &params.Range);
167 if (code < 0)
168 goto fail;
169 params.n = code >> 1;
170 /* Finish building the function. */
171 /* If this fails, it will free all the parameters. */
172 return (*build_function_procs[type]) (op, &params, depth + 1, ppfn);
173 fail:
174 ifree_object((void *)params.Range, "Range"); /* break const */
175 ifree_object((void *)params.Domain, "Domain"); /* break const */
176 return code;
177 }
178
179 /* Allocate an array of function objects. */
180 int
181 ialloc_function_array(uint count, gs_function_t *** pFunctions)
182 {
183 gs_function_t **ptr;
184
185 if (count == 0)
186 return_error(e_rangecheck);
187 ptr = ialloc_struct_array(count, gs_function_t *,
188 &st_function_ptr_element, "Functions");
189 if (ptr == 0)
190 return_error(e_VMerror);
191 memset(ptr, 0, sizeof(*ptr) * count);
192 *pFunctions = ptr;
193 return 0;
194 }
195
196 /*
197 * Collect a heap-allocated array of floats. If the key is missing, set
198 * *pparray = 0 and return 0; otherwise set *pparray and return the number
199 * of elements. Note that 0-length arrays are acceptable, so if the value
200 * returned is 0, the caller must check whether *pparray == 0.
201 */
202 int
203 fn_build_float_array(const ref * op, const char *kstr, bool required,
204 bool even, const float **pparray)
205 {
206 ref *par;
207 int code;
208
209 *pparray = 0;
210 if (dict_find_string(op, kstr, &par) <= 0)
211 return (required ? gs_note_error(e_rangecheck) : 0);
212 if (!r_is_array(par))
213 return_error(e_typecheck);
214 {
215 uint size = r_size(par);
216 float *ptr = (float *)ialloc_byte_array(size, sizeof(float), kstr);
217
218 if (ptr == 0)
219 return_error(e_VMerror);
220 code = dict_float_array_param(op, kstr, size, ptr, NULL);
221 if (code < 0 || (even && (code & 1) != 0)) {
222 ifree_object(ptr, kstr);
223 return(code < 0 ? code : gs_note_error(e_rangecheck));
224 }
225 *pparray = ptr;
226 }
227 return code;
228 }
229
230 /* ------ Initialization procedure ------ */
231
232 const op_def zfunc_op_defs[] =
233 {
234 {"1.buildfunction", zbuildfunction},
235 {"1%execfunction", zexecfunction},
236 op_def_end(0)
237 };