/* Make a scaled copy of an Arrayed Output function. */ static int fn_AdOt_make_scaled(const gs_function_AdOt_t *pfn, gs_function_AdOt_t **ppsfn, const gs_range_t *pranges, gs_memory_t *mem) { gs_function_AdOt_t *psfn = gs_alloc_struct(mem, gs_function_AdOt_t, &st_function_AdOt, "fn_AdOt_make_scaled"); int code; if (psfn == 0) return_error(gs_error_VMerror); psfn->params = pfn->params; psfn->params.Functions = 0; /* in case of failure */ if ((code = fn_common_scale((gs_function_t *)psfn, (const gs_function_t *)pfn, pranges, mem)) < 0 || (code = fn_scale_functions((gs_function_t ***)&psfn->params.Functions, pfn->params.Functions, pfn->params.n, pranges, true, mem)) < 0) { gs_function_free((gs_function_t *)psfn, true, mem); return code; } *ppsfn = psfn; return 0; }
/* Make a scaled copy of a 1-Input Stitching function. */ static int fn_1ItSg_make_scaled(const gs_function_1ItSg_t *pfn, gs_function_1ItSg_t **ppsfn, const gs_range_t *pranges, gs_memory_t *mem) { gs_function_1ItSg_t *psfn = gs_alloc_struct(mem, gs_function_1ItSg_t, &st_function_1ItSg, "fn_1ItSg_make_scaled"); int code; if (psfn == 0) return_error(gs_error_VMerror); psfn->params = pfn->params; psfn->params.Functions = 0; /* in case of failure */ psfn->params.Bounds = fn_copy_values(pfn->params.Bounds, pfn->params.k - 1, sizeof(float), mem); psfn->params.Encode = fn_copy_values(pfn->params.Encode, 2 * pfn->params.k, sizeof(float), mem); if ((code = (psfn->params.Bounds == 0 || psfn->params.Encode == 0 ? gs_note_error(gs_error_VMerror) : 0)) < 0 || (code = fn_common_scale((gs_function_t *)psfn, (const gs_function_t *)pfn, pranges, mem)) < 0 || (code = fn_scale_functions((gs_function_t ***)&psfn->params.Functions, pfn->params.Functions, pfn->params.n, pranges, false, mem)) < 0) { gs_function_free((gs_function_t *)psfn, true, mem); return code; } *ppsfn = psfn; return 0; }
/* * Free an array of subsidiary Functions. Note that this may be called * before the Functions array has been fully initialized. Note also that * its argument conforms to the Functions array in the parameter structure, * but it (necessarily) deconstifies it. */ static void fn_free_functions(const gs_function_t *const * Functions, int count, gs_memory_t * mem) { int i; for (i = count; --i >= 0;) if (Functions[i]) gs_function_free((gs_function_t *)Functions[i], true, mem); gs_free_const_object(mem, Functions, "Functions"); }
/* Collect a Function value. */ static int build_shading_function(i_ctx_t *i_ctx_p, const ref * op, gs_function_t ** ppfn, int num_inputs, gs_memory_t *mem, const float *shading_domain) { ref *pFunction; int code; *ppfn = 0; if (dict_find_string(op, "Function", &pFunction) <= 0) return 0; if (r_is_array(pFunction)) { uint size = r_size(pFunction); gs_function_t **Functions; uint i; gs_function_AdOt_params_t params; check_read(*pFunction); if (size == 0) return_error(gs_error_rangecheck); code = alloc_function_array(size, &Functions, mem); if (code < 0) return code; for (i = 0; i < size; ++i) { ref rsubfn; array_get(imemory, pFunction, (long)i, &rsubfn); code = fn_build_function(i_ctx_p, &rsubfn, &Functions[i], mem, shading_domain, num_inputs); if (code < 0) break; } params.m = num_inputs; params.Domain = 0; params.n = size; params.Range = 0; params.Functions = (const gs_function_t * const *)Functions; if (code >= 0) code = gs_function_AdOt_init(ppfn, ¶ms, mem); if (code < 0) gs_function_AdOt_free_params(¶ms, mem); } else { code = fn_build_function(i_ctx_p, pFunction, ppfn, mem, shading_domain, num_inputs); if (code < 0) return code; if ((*ppfn)->params.m != num_inputs) { gs_function_free(*ppfn, true, mem); return_error(gs_error_rangecheck); } } return code; }
/* <dict> .buildfunction <function_proc> */ static int zbuildfunction(i_ctx_t *i_ctx_p) { os_ptr op = osp; gs_function_t *pfn; int code = fn_build_function(i_ctx_p, op, &pfn, imemory, 0, 0); if (code < 0) return code; code = make_function_proc(i_ctx_p, op, pfn); if (code < 0) gs_function_free(pfn, true, imemory); return 0; }
/* <function_proc> <array> .scalefunction <function_proc> */ static int zscalefunction(i_ctx_t *i_ctx_p) { os_ptr op = osp; gs_function_t *pfn; gs_function_t *psfn; gs_range_t *ranges; int code; uint i; check_proc(op[-1]); pfn = ref_function(op - 1); if (pfn == 0 || !r_is_array(op)) return_error(gs_error_typecheck); if (r_size(op) != 2 * pfn->params.n) return_error(gs_error_rangecheck); ranges = (gs_range_t *) gs_alloc_byte_array(imemory, pfn->params.n, sizeof(gs_range_t), "zscalefunction"); if (ranges == 0) return_error(gs_error_VMerror); for (i = 0; i < pfn->params.n; ++i) { ref rval[2]; float val[2]; if ((code = array_get(op, 2 * i, &rval[0])) < 0 || (code = array_get(op, 2 * i + 1, &rval[1])) < 0 || (code = float_params(rval + 1, 2, val)) < 0) return code; ranges[i].rmin = val[0]; ranges[i].rmax = val[1]; } code = gs_function_make_scaled(pfn, &psfn, ranges, imemory); gs_free_object(imemory, ranges, "zscalefunction"); if (code < 0 || (code = make_function_proc(i_ctx_p, op - 1, psfn)) < 0) { gs_function_free(psfn, true, imemory); return code; } pop(1); return 0; }
int buildfunction(i_ctx_t * i_ctx_p, ref *arr, ref *pproc, int type) { os_ptr op = osp; gs_function_t *pfn=NULL; int code=0; switch(type) { case 0: code = make_sampled_function(i_ctx_p, arr, pproc, &pfn); break; case 4: code = make_type4_function(i_ctx_p, arr, pproc, &pfn); if (code == 0) { code = make_function_proc(i_ctx_p, op, pfn); if (code < 0) { gs_function_free(pfn, true, imemory); } } break; } return code; }
/* Make a scaled copy of an Exponential Interpolation function. */ static int fn_ElIn_make_scaled(const gs_function_ElIn_t *pfn, gs_function_ElIn_t **ppsfn, const gs_range_t *pranges, gs_memory_t *mem) { gs_function_ElIn_t *psfn = gs_alloc_struct(mem, gs_function_ElIn_t, &st_function_ElIn, "fn_ElIn_make_scaled"); float *c0; float *c1; int code, i; if (psfn == 0) return_error(gs_error_VMerror); psfn->params = pfn->params; psfn->params.C0 = c0 = fn_copy_values(pfn->params.C0, pfn->params.n, sizeof(float), mem); psfn->params.C1 = c1 = fn_copy_values(pfn->params.C1, pfn->params.n, sizeof(float), mem); if ((code = ((c0 == 0 && pfn->params.C0 != 0) || (c1 == 0 && pfn->params.C1 != 0) ? gs_note_error(gs_error_VMerror) : 0)) < 0 || (code = fn_common_scale((gs_function_t *)psfn, (const gs_function_t *)pfn, pranges, mem)) < 0) { gs_function_free((gs_function_t *)psfn, true, mem); return code; } for (i = 0; i < pfn->params.n; ++i) { double base = pranges[i].rmin, factor = pranges[i].rmax - base; c1[i] = c1[i] * factor + base; c0[i] = c0[i] * factor + base; } *ppsfn = psfn; return 0; }
/* Allocate and initialize an Arrayed Output function. */ int gs_function_AdOt_init(gs_function_t ** ppfn, const gs_function_AdOt_params_t * params, gs_memory_t * mem) { static const gs_function_head_t function_AdOt_head = { function_type_ArrayedOutput, { (fn_evaluate_proc_t) fn_AdOt_evaluate, (fn_is_monotonic_proc_t) fn_AdOt_is_monotonic, (fn_get_info_proc_t) fn_AdOt_get_info, fn_common_get_params, /****** WHAT TO DO ABOUT THIS? ******/ (fn_make_scaled_proc_t) fn_AdOt_make_scaled, (fn_free_params_proc_t) gs_function_AdOt_free_params, fn_common_free, (fn_serialize_proc_t) gs_function_AdOt_serialize, } }; int m = params->m, n = params->n; *ppfn = 0; /* in case of error */ if (m <= 0 || n <= 0) return_error(gs_error_rangecheck); { gs_function_AdOt_t *pfn = gs_alloc_struct(mem, gs_function_AdOt_t, &st_function_AdOt, "gs_function_AdOt_init"); float *domain = (float *) gs_alloc_byte_array(mem, 2 * m, sizeof(float), "gs_function_AdOt_init(Domain)"); int i, j; if (pfn == 0) return_error(gs_error_VMerror); pfn->params = *params; pfn->params.Domain = domain; pfn->params.Range = 0; pfn->head = function_AdOt_head; if (domain == 0) { gs_function_free((gs_function_t *)pfn, true, mem); return_error(gs_error_VMerror); } /* * We compute the Domain as the intersection of the Domains of * the individual subfunctions. This isn't quite right: some * subfunction might actually make use of a larger domain of * input values. However, the only place that Arrayed Output * functions are used is in Shading and similar dictionaries, * where the input values are clamped to the intersection of * the individual Domains anyway. */ memcpy(domain, params->Functions[0]->params.Domain, 2 * sizeof(float) * m); for (i = 1; i < n; ++i) { const float *dom = params->Functions[i]->params.Domain; for (j = 0; j < 2 * m; j += 2, dom += 2) { domain[j] = max(domain[j], dom[0]); domain[j + 1] = min(domain[j + 1], dom[1]); } } *ppfn = (gs_function_t *) pfn; } return 0; }
/* Collect parameters for a mesh shading. */ static int build_mesh_shading(i_ctx_t *i_ctx_p, const ref * op, gs_shading_mesh_params_t * params, float **pDecode, gs_function_t ** pFunction, gs_memory_t *mem) { int code; float *data = 0; ref *pDataSource; *pDecode = 0; *pFunction = 0; if (dict_find_string(op, "DataSource", &pDataSource) <= 0) return_error(gs_error_rangecheck); if (r_is_array(pDataSource)) { uint size = r_size(pDataSource); data = (float *)gs_alloc_byte_array(mem, size, sizeof(float), "build_mesh_shading"); if (data == 0) return_error(gs_error_VMerror); code = process_float_array(mem, pDataSource, size, data); if (code < 0) { gs_free_object(mem, data, "build_mesh_shading"); return code; } data_source_init_floats(¶ms->DataSource, data, size); } else switch (r_type(pDataSource)) { case t_file: { stream *s; check_read_file(i_ctx_p, s, pDataSource); data_source_init_stream(¶ms->DataSource, s); break; } case t_string: check_read(*pDataSource); data_source_init_string2(¶ms->DataSource, pDataSource->value.bytes, r_size(pDataSource)); break; default: return_error(gs_error_typecheck); } code = build_shading_function(i_ctx_p, op, pFunction, 1, mem, NULL); if (code < 0) { gs_free_object(mem, data, "build_mesh_shading"); return code; } if (data_source_is_array(params->DataSource)) { params->BitsPerCoordinate = 0; params->BitsPerComponent = 0; } else { int num_decode = 4 + (*pFunction != 0 ? 1 : gs_color_space_num_components(params->ColorSpace)) * 2; if ((code = dict_int_param(op, "BitsPerCoordinate", 1, 32, 0, ¶ms->BitsPerCoordinate)) >= 0 && (code = dict_int_param(op, "BitsPerComponent", 1, 16, 0, ¶ms->BitsPerComponent)) >= 0 ) { *pDecode = (float *) gs_alloc_byte_array(mem, num_decode, sizeof(float), "build_mesh_shading"); if (*pDecode == 0) code = gs_note_error(gs_error_VMerror); else { code = dict_floats_param(mem, op, "Decode", num_decode, *pDecode, NULL); if (code < 0) { gs_free_object(mem, *pDecode, "build_mesh_shading"); *pDecode = 0; } } } } if (code < 0) { if (*pFunction != 0) { gs_function_free(*pFunction, true, mem); *pFunction = 0; } gs_free_object(mem, data, "build_mesh_shading"); } return code; }