1 /* Copyright (C) 1997, 2000 Aladdin Enterprises. All rights reserved. 2 3 This software is provided AS-IS with no warranty, either express or 4 implied. 5 6 This software is distributed under license and may not be copied, 7 modified or distributed except as expressly authorized under the terms 8 of the license contained in the file LICENSE in this distribution. 9 10 For more information about licensing, please refer to 11 http://www.ghostscript.com/licensing/. For information on 12 commercial licensing, go to http://www.artifex.com/licensing/ or 13 contact Artifex Software, Inc., 101 Lucas Valley Road #110, 14 San Rafael, CA 94903, U.S.A., +1(415)492-9861. 15 */ 16 17 /* $Id: zfunc.c,v 1.14 2004/08/04 19:36:13 stefan Exp $ */ 18 /* Generic PostScript language interface to Functions */ 19 #include "memory_.h" 20 #include "ghost.h" 21 #include "oper.h" 22 #include "gscdefs.h" 23 #include "gsfunc.h" 24 #include "gsstruct.h" 25 #include "ialloc.h" 26 #include "idict.h" 27 #include "idparam.h" 28 #include "ifunc.h" 29 #include "store.h" 30 31 /*#define TEST*/ 32 33 /* Define the maximum depth of nesting of subsidiary functions. */ 34 #define MAX_SUB_FUNCTION_DEPTH 3 35 36 /* ------ Operators ------ */ 37 38 /* Create a function procedure from a function structure. */ 39 private int 40 make_function_proc(i_ctx_t *i_ctx_p, ref *op, gs_function_t *pfn) 41 { 42 ref cref; /* closure */ 43 int code; 44 45 code = ialloc_ref_array(&cref, a_executable | a_execute, 2, 46 ".buildfunction"); 47 if (code < 0) 48 return code; 49 make_istruct_new(cref.value.refs, a_executable | a_execute, pfn); 50 make_oper_new(cref.value.refs + 1, 0, zexecfunction); 51 ref_assign(op, &cref); 52 return 0; 53 } 54 55 /* <dict> .buildfunction <function_proc> */ 56 private int 57 zbuildfunction(i_ctx_t *i_ctx_p) 58 { 59 os_ptr op = osp; 60 gs_function_t *pfn; 61 int code = fn_build_function(i_ctx_p, op, &pfn, imemory); 62 63 if (code < 0) 64 return code; 65 code = make_function_proc(i_ctx_p, op, pfn); 66 if (code < 0) 67 gs_function_free(pfn, true, imemory); 68 return 0; 69 } 70 71 #ifdef TEST 72 73 /* <function_proc> <array> .scalefunction <function_proc> */ 74 private int 75 zscalefunction(i_ctx_t *i_ctx_p) 76 { 77 os_ptr op = osp; 78 gs_function_t *pfn; 79 gs_function_t *psfn; 80 gs_range_t *ranges; 81 int code; 82 uint i; 83 84 check_proc(op[-1]); 85 pfn = ref_function(op - 1); 86 if (pfn == 0 || !r_is_array(op)) 87 return_error(e_typecheck); 88 if (r_size(op) != 2 * pfn->params.n) 89 return_error(e_rangecheck); 90 ranges = (gs_range_t *) 91 gs_alloc_byte_array(imemory, pfn->params.n, sizeof(gs_range_t), 92 "zscalefunction"); 93 if (ranges == 0) 94 return_error(e_VMerror); 95 for (i = 0; i < pfn->params.n; ++i) { 96 ref rval[2]; 97 float val[2]; 98 99 if ((code = array_get(op, 2 * i, &rval[0])) < 0 || 100 (code = array_get(op, 2 * i + 1, &rval[1])) < 0 || 101 (code = float_params(rval + 1, 2, val)) < 0) 102 return code; 103 ranges[i].rmin = val[0]; 104 ranges[i].rmax = val[1]; 105 } 106 code = gs_function_make_scaled(pfn, &psfn, ranges, imemory); 107 gs_free_object(imemory, ranges, "zscalefunction"); 108 if (code < 0 || 109 (code = make_function_proc(i_ctx_p, op - 1, psfn)) < 0) { 110 gs_function_free(psfn, true, imemory); 111 return code; 112 } 113 pop(1); 114 return 0; 115 } 116 117 #endif /* TEST */ 118 119 /* <in1> ... <function_struct> %execfunction <out1> ... */ 120 int 121 zexecfunction(i_ctx_t *i_ctx_p) 122 { 123 os_ptr op = osp; 124 125 /* 126 * Since this operator's name begins with %, the name is not defined 127 * in systemdict. The only place this operator can ever appear is 128 * in the execute-only closure created by .buildfunction. 129 * Therefore, in principle it is unnecessary to check the argument. 130 * However, we do a little checking anyway just on general 131 * principles. Note that since the argument may be an instance of 132 * any subclass of gs_function_t, we currently have no way to check 133 * its type. 134 */ 135 if (!r_is_struct(op) || 136 !r_has_masked_attrs(op, a_executable | a_execute, a_executable | a_all) 137 ) 138 return_error(e_typecheck); 139 { 140 gs_function_t *pfn = (gs_function_t *) op->value.pstruct; 141 int m = pfn->params.m, n = pfn->params.n; 142 int diff = n - (m + 1); 143 144 if (diff > 0) 145 check_ostack(diff); 146 { 147 float params[20]; /* arbitrary size, just to avoid allocs */ 148 float *in; 149 float *out; 150 int code = 0; 151 152 if (m + n <= countof(params)) { 153 in = params; 154 } else { 155 in = (float *)ialloc_byte_array(m + n, sizeof(float), 156 "%execfunction(in/out)"); 157 if (in == 0) 158 code = gs_note_error(e_VMerror); 159 } 160 out = in + m; 161 if (code < 0 || 162 (code = float_params(op - 1, m, in)) < 0 || 163 (code = gs_function_evaluate(pfn, in, out)) < 0 164 ) 165 DO_NOTHING; 166 else { 167 if (diff > 0) 168 push(diff); /* can't fail */ 169 else if (diff < 0) { 170 pop(-diff); 171 op = osp; 172 } 173 code = make_floats(op + 1 - n, out, n); 174 } 175 if (in != params) 176 ifree_object(in, "%execfunction(in)"); 177 return code; 178 } 179 } 180 } 181 182 /* 183 * <proc> .isencapfunction <bool> 184 * 185 * This routine checks if a given Postscript procedure is an "encapsulated" 186 * function of the type made by .buildfunction. These functions can then 187 * be executed without executing the interpreter. These functions can be 188 * executed directly from within C code inside the graphics library. 189 */ 190 private int 191 zisencapfunction(i_ctx_t *i_ctx_p) 192 { 193 os_ptr op = osp; 194 gs_function_t *pfn; 195 196 check_proc(*op); 197 pfn = ref_function(op); 198 make_bool(op, pfn != NULL); 199 return 0; 200 } 201 202 /* ------ Procedures ------ */ 203 204 /* Build a function structure from a PostScript dictionary. */ 205 int 206 fn_build_function(i_ctx_t *i_ctx_p, const ref * op, gs_function_t ** ppfn, gs_memory_t *mem) 207 { 208 return fn_build_sub_function(i_ctx_p, op, ppfn, 0, mem); 209 } 210 int 211 fn_build_sub_function(i_ctx_t *i_ctx_p, const ref * op, gs_function_t ** ppfn, 212 int depth, gs_memory_t *mem) 213 { 214 int code, type, i; 215 gs_function_params_t params; 216 217 if (depth > MAX_SUB_FUNCTION_DEPTH) 218 return_error(e_limitcheck); 219 check_type(*op, t_dictionary); 220 code = dict_int_param(op, "FunctionType", 0, max_int, -1, &type); 221 if (code < 0) 222 return code; 223 for (i = 0; i < build_function_type_table_count; ++i) 224 if (build_function_type_table[i].type == type) 225 break; 226 if (i == build_function_type_table_count) 227 return_error(e_rangecheck); 228 /* Collect parameters common to all function types. */ 229 params.Domain = 0; 230 params.Range = 0; 231 code = fn_build_float_array(op, "Domain", true, true, ¶ms.Domain, mem); 232 if (code < 0) 233 goto fail; 234 params.m = code >> 1; 235 code = fn_build_float_array(op, "Range", false, true, ¶ms.Range, mem); 236 if (code < 0) 237 goto fail; 238 params.n = code >> 1; 239 /* Finish building the function. */ 240 /* If this fails, it will free all the parameters. */ 241 return (*build_function_type_table[i].proc) 242 (i_ctx_p, op, ¶ms, depth + 1, ppfn, mem); 243 fail: 244 gs_free_const_object(mem, params.Range, "Range"); 245 gs_free_const_object(mem, params.Domain, "Domain"); 246 return code; 247 } 248 249 /* 250 * Collect a heap-allocated array of floats. If the key is missing, set 251 * *pparray = 0 and return 0; otherwise set *pparray and return the number 252 * of elements. Note that 0-length arrays are acceptable, so if the value 253 * returned is 0, the caller must check whether *pparray == 0. 254 */ 255 int 256 fn_build_float_array(const ref * op, const char *kstr, bool required, 257 bool even, const float **pparray, gs_memory_t *mem) 258 { 259 ref *par; 260 int code; 261 262 *pparray = 0; 263 if (dict_find_string(op, kstr, &par) <= 0) 264 return (required ? gs_note_error(e_rangecheck) : 0); 265 if (!r_is_array(par)) 266 return_error(e_typecheck); 267 { 268 uint size = r_size(par); 269 float *ptr = (float *) 270 gs_alloc_byte_array(mem, size, sizeof(float), kstr); 271 272 if (ptr == 0) 273 return_error(e_VMerror); 274 code = dict_float_array_check_param(mem, op, kstr, size, 275 ptr, NULL, 276 0, e_rangecheck); 277 if (code < 0 || (even && (code & 1) != 0)) { 278 gs_free_object(mem, ptr, kstr); 279 return(code < 0 ? code : gs_note_error(e_rangecheck)); 280 } 281 *pparray = ptr; 282 } 283 return code; 284 } 285 286 /* 287 * Similar to fn_build_float_array() except 288 * - numeric parameter is accepted and converted to 1-element array 289 * - number of elements is not checked for even/odd 290 */ 291 int 292 fn_build_float_array_forced(const ref * op, const char *kstr, bool required, 293 const float **pparray, gs_memory_t *mem) 294 { 295 ref *par; 296 int code; 297 uint size; 298 float *ptr; 299 300 *pparray = 0; 301 if (dict_find_string(op, kstr, &par) <= 0) 302 return (required ? gs_note_error(e_rangecheck) : 0); 303 304 if( r_is_array(par) ) 305 size = r_size(par); 306 else if(r_type(par) == t_integer || r_type(par) == t_real) 307 size = 1; 308 else 309 return_error(e_typecheck); 310 ptr = (float *)gs_alloc_byte_array(mem, size, sizeof(float), kstr); 311 312 if (ptr == 0) 313 return_error(e_VMerror); 314 if(r_is_array(par) ) 315 code = dict_float_array_check_param(mem, op, kstr, 316 size, ptr, NULL, 317 0, e_rangecheck); 318 else { 319 code = dict_float_param(op, kstr, 0., ptr); /* defailt cannot happen */ 320 if( code == 0 ) 321 code = 1; 322 } 323 324 if (code < 0 ) { 325 gs_free_object(mem, ptr, kstr); 326 return code; 327 } 328 *pparray = ptr; 329 return code; 330 } 331 332 /* 333 * If a PostScript object is a Function procedure, return the function 334 * object, otherwise return 0. 335 */ 336 gs_function_t * 337 ref_function(const ref *op) 338 { 339 if (r_has_type(op, t_array) && 340 r_has_masked_attrs(op, a_executable | a_execute, 341 a_executable | a_all) && 342 r_size(op) == 2 && 343 r_has_type_attrs(op->value.refs + 1, t_operator, a_executable) && 344 op->value.refs[1].value.opproc == zexecfunction && 345 r_is_struct(op->value.refs) && 346 r_has_masked_attrs(op->value.refs, a_executable | a_execute, 347 a_executable | a_all) 348 ) 349 return (gs_function_t *)op->value.refs->value.pstruct; 350 return 0; 351 } 352 353 /* ------ Initialization procedure ------ */ 354 355 const op_def zfunc_op_defs[] = 356 { 357 {"1.buildfunction", zbuildfunction}, 358 #ifdef TEST 359 {"2.scalefunction", zscalefunction}, 360 #endif /* TEST */ 361 {"1%execfunction", zexecfunction}, 362 {"1.isencapfunction", zisencapfunction}, 363 op_def_end(0) 364 }; 365