2 Copyright 2001 by Easy Software Products.
3 Copyright 1997, 1998 Aladdin Enterprises. All rights reserved.
5 This file is part of GNU Ghostscript.
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.
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
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.
27 /*$Id: zfunc.c,v 1.1.2.1 2001/05/13 18:38:33 mike Exp $ */
28 /* Generic PostScript language interface to Functions */
40 /* Define the maximum depth of nesting of subsidiary functions. */
41 #define MAX_SUB_FUNCTION_DEPTH 3
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
50 build_function_undefined(const_os_ptr op
, const gs_function_params_t
* mnDR
,
51 int depth
, gs_function_t
** ppfn
)
53 return_error(e_rangecheck
);
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
);
63 /* ------ Operators ------ */
65 private int zexecfunction(P1(os_ptr op
));
67 /* <dict> .buildfunction <function_struct> */
69 zbuildfunction(os_ptr op
)
72 ref cref
; /* closure */
75 code
= ialloc_ref_array(&cref
, a_executable
| a_execute
, 2,
79 code
= fn_build_function(op
, &pfn
);
81 ifree_ref_array(&cref
, ".buildfunction");
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
);
90 /* <in1> ... <function_struct> %execfunction <out1> ... */
92 zexecfunction(os_ptr op
)
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
103 if (!r_is_struct(op
) ||
104 r_has_masked_attrs(op
, a_executable
| a_execute
, a_all
)
106 return_error(e_typecheck
);
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);
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)");
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
129 push(diff
) /* can't fail */ /* MRS: No trailing ; */
134 code
= make_floats(op
+ 1 - n
, out
, n
);
136 ifree_object(out
, "%execfunction(out)");
137 ifree_object(in
, "%execfunction(in)");
143 /* ------ Procedures ------ */
145 /* Build a function structure from a PostScript dictionary. */
147 fn_build_sub_function(const ref
* op
, gs_function_t
** ppfn
, int depth
)
150 gs_function_params_t params
;
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
);
159 /* Collect parameters common to all function types. */
162 code
= fn_build_float_array(op
, "Domain", true, true, ¶ms
.Domain
);
165 params
.m
= code
>> 1;
166 code
= fn_build_float_array(op
, "Range", false, true, ¶ms
.Range
);
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
, ¶ms
, depth
+ 1, ppfn
);
174 ifree_object((void *)params
.Range
, "Range"); /* break const */
175 ifree_object((void *)params
.Domain
, "Domain"); /* break const */
179 /* Allocate an array of function objects. */
181 ialloc_function_array(uint count
, gs_function_t
*** pFunctions
)
186 return_error(e_rangecheck
);
187 ptr
= ialloc_struct_array(count
, gs_function_t
*,
188 &st_function_ptr_element
, "Functions");
190 return_error(e_VMerror
);
191 memset(ptr
, 0, sizeof(*ptr
) * count
);
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.
203 fn_build_float_array(const ref
* op
, const char *kstr
, bool required
,
204 bool even
, const float **pparray
)
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
);
215 uint size
= r_size(par
);
216 float *ptr
= (float *)ialloc_byte_array(size
, sizeof(float), kstr
);
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
));
230 /* ------ Initialization procedure ------ */
232 const op_def zfunc_op_defs
[] =
234 {"1.buildfunction", zbuildfunction
},
235 {"1%execfunction", zexecfunction
},