]> git.ipfire.org Git - thirdparty/cups.git/blame - pstoraster/zfunc.c
Merge changes from 1.1 tree.
[thirdparty/cups.git] / pstoraster / zfunc.c
CommitLineData
b5cb0608 1/*
2 Copyright 2001 by Easy Software Products.
3 Copyright 1997, 1998 Aladdin Enterprises. All rights reserved.
caddbb58 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
b5cb0608 27/*$Id: zfunc.c,v 1.1.2.1 2001/05/13 18:38:33 mike Exp $ */
caddbb58 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. */
44build_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
49int
50build_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 */
57gs_private_st_ptr(st_function_ptr, gs_function_t *, "gs_function_t *",
58 function_ptr_enum_ptrs, function_ptr_reloc_ptrs);
59gs_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
65private int zexecfunction(P1(os_ptr op));
66
67/* <dict> .buildfunction <function_struct> */
68private int
69zbuildfunction(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> ... */
91private int
92zexecfunction(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)
b5cb0608 129 push(diff) /* can't fail */ /* MRS: No trailing ; */
caddbb58 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. */
146int
147fn_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);
173fail:
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. */
180int
181ialloc_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 */
202int
203fn_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
232const op_def zfunc_op_defs[] =
233{
234 {"1.buildfunction", zbuildfunction},
235 {"1%execfunction", zexecfunction},
236 op_def_end(0)
237};