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: gsfunc.c,v 1.12 2005/04/19 14:35:12 igor Exp $ */
18 /* Generic Function support */
19 #include "memory_.h"
20 #include "gx.h"
21 #include "gserrors.h"
22 #include "gsparam.h"
23 #include "gxfunc.h"
24 #include "stream.h"
25
26 /* GC descriptors */
27 public_st_function();
28 gs_private_st_ptr(st_function_ptr, gs_function_t *, "gs_function_t *",
29 function_ptr_enum_ptrs, function_ptr_reloc_ptrs);
30 gs_private_st_element(st_function_ptr_element, gs_function_t *,
31 "gs_function_t *[]", function_ptr_element_enum_ptrs,
32 function_ptr_element_reloc_ptrs, st_function_ptr);
33
34 /* Allocate an array of function pointers. */
35 int
alloc_function_array(uint count,gs_function_t *** pFunctions,gs_memory_t * mem)36 alloc_function_array(uint count, gs_function_t *** pFunctions,
37 gs_memory_t *mem)
38 {
39 gs_function_t **ptr;
40
41 if (count == 0)
42 return_error(gs_error_rangecheck);
43 ptr = gs_alloc_struct_array(mem, count, gs_function_t *,
44 &st_function_ptr_element, "Functions");
45 if (ptr == 0)
46 return_error(gs_error_VMerror);
47 memset(ptr, 0, sizeof(*ptr) * count);
48 *pFunctions = ptr;
49 return 0;
50 }
51
52 /* Generic free_params implementation. */
53 void
fn_common_free_params(gs_function_params_t * params,gs_memory_t * mem)54 fn_common_free_params(gs_function_params_t * params, gs_memory_t * mem)
55 {
56 gs_free_const_object(mem, params->Range, "Range");
57 gs_free_const_object(mem, params->Domain, "Domain");
58 }
59
60 /* Generic free implementation. */
61 void
fn_common_free(gs_function_t * pfn,bool free_params,gs_memory_t * mem)62 fn_common_free(gs_function_t * pfn, bool free_params, gs_memory_t * mem)
63 {
64 if (free_params)
65 gs_function_free_params(pfn, mem);
66 gs_free_object(mem, pfn, "fn_common_free");
67 }
68
69 /* Check the values of m, n, Domain, and (if supplied) Range. */
70 int
fn_check_mnDR(const gs_function_params_t * params,int m,int n)71 fn_check_mnDR(const gs_function_params_t * params, int m, int n)
72 {
73 int i;
74
75 if (m <= 0 || n <= 0)
76 return_error(gs_error_rangecheck);
77 for (i = 0; i < m; ++i)
78 if (params->Domain[2 * i] > params->Domain[2 * i + 1])
79 return_error(gs_error_rangecheck);
80 if (params->Range != 0)
81 for (i = 0; i < n; ++i)
82 if (params->Range[2 * i] > params->Range[2 * i + 1])
83 return_error(gs_error_rangecheck);
84 return 0;
85 }
86
87 /* Return default function information. */
88 void
gs_function_get_info_default(const gs_function_t * pfn,gs_function_info_t * pfi)89 gs_function_get_info_default(const gs_function_t *pfn, gs_function_info_t *pfi)
90 {
91 pfi->DataSource = 0;
92 pfi->Functions = 0;
93 }
94
95 /*
96 * Write generic parameters (FunctionType, Domain, Range) on a parameter list.
97 */
98 int
fn_common_get_params(const gs_function_t * pfn,gs_param_list * plist)99 fn_common_get_params(const gs_function_t *pfn, gs_param_list *plist)
100 {
101 int ecode = param_write_int(plist, "FunctionType", &FunctionType(pfn));
102 int code;
103
104 if (pfn->params.Domain) {
105 code = param_write_float_values(plist, "Domain", pfn->params.Domain,
106 2 * pfn->params.m, false);
107 if (code < 0)
108 ecode = code;
109 }
110 if (pfn->params.Range) {
111 code = param_write_float_values(plist, "Range", pfn->params.Range,
112 2 * pfn->params.n, false);
113 if (code < 0)
114 ecode = code;
115 }
116 return ecode;
117 }
118
119 /*
120 * Copy an array of numeric values when scaling a function.
121 */
122 void *
fn_copy_values(const void * pvalues,int count,int size,gs_memory_t * mem)123 fn_copy_values(const void *pvalues, int count, int size, gs_memory_t *mem)
124 {
125 if (pvalues) {
126 void *values = gs_alloc_byte_array(mem, count, size, "fn_copy_values");
127
128 if (values)
129 memcpy(values, pvalues, count * size);
130 return values;
131 } else
132 return 0; /* caller must check */
133 }
134
135 /*
136 * If necessary, scale the Range or Decode array for fn_make_scaled.
137 * Note that we must always allocate a new array.
138 */
139 int
fn_scale_pairs(const float ** ppvalues,const float * pvalues,int npairs,const gs_range_t * pranges,gs_memory_t * mem)140 fn_scale_pairs(const float **ppvalues, const float *pvalues, int npairs,
141 const gs_range_t *pranges, gs_memory_t *mem)
142 {
143 if (pvalues == 0)
144 *ppvalues = 0;
145 else {
146 float *out = (float *)
147 gs_alloc_byte_array(mem, 2 * npairs, sizeof(*pvalues),
148 "fn_scale_pairs");
149
150 *ppvalues = out;
151 if (out == 0)
152 return_error(gs_error_VMerror);
153 if (pranges) {
154 /* Allocate and compute scaled ranges. */
155 int i;
156 for (i = 0; i < npairs; ++i) {
157 double base = pranges[i].rmin, factor = pranges[i].rmax - base;
158
159 out[2 * i] = pvalues[2 * i] * factor + base;
160 out[2 * i + 1] = pvalues[2 * i + 1] * factor + base;
161 }
162 } else
163 memcpy(out, pvalues, 2 * sizeof(*pvalues) * npairs);
164 }
165 return 0;
166 }
167
168 /*
169 * Scale the generic part of a function (Domain and Range).
170 * The client must have copied the parameters already.
171 */
172 int
fn_common_scale(gs_function_t * psfn,const gs_function_t * pfn,const gs_range_t * pranges,gs_memory_t * mem)173 fn_common_scale(gs_function_t *psfn, const gs_function_t *pfn,
174 const gs_range_t *pranges, gs_memory_t *mem)
175 {
176 int code;
177
178 psfn->head = pfn->head;
179 psfn->params.Domain = 0; /* in case of failure */
180 psfn->params.Range = 0;
181 if ((code = fn_scale_pairs(&psfn->params.Domain, pfn->params.Domain,
182 pfn->params.m, NULL, mem)) < 0 ||
183 (code = fn_scale_pairs(&psfn->params.Range, pfn->params.Range,
184 pfn->params.n, pranges, mem)) < 0)
185 return code;
186 return 0;
187 }
188
189 /* Serialize. */
190 int
fn_common_serialize(const gs_function_t * pfn,stream * s)191 fn_common_serialize(const gs_function_t * pfn, stream *s)
192 {
193 uint n;
194 const gs_function_params_t * p = &pfn->params;
195 int code = sputs(s, (const byte *)&pfn->head.type, sizeof(pfn->head.type), &n);
196 const float dummy[8] = {0, 0, 0, 0, 0, 0, 0, 0};
197
198 if (code < 0)
199 return code;
200 code = sputs(s, (const byte *)&p->m, sizeof(p->m), &n);
201 if (code < 0)
202 return code;
203 code = sputs(s, (const byte *)&p->Domain[0], sizeof(p->Domain[0]) * p->m * 2, &n);
204 if (code < 0)
205 return code;
206 code = sputs(s, (const byte *)&p->n, sizeof(p->n), &n);
207 if (code < 0)
208 return code;
209 if (p->Range == NULL && p->n * 2 > count_of(dummy))
210 return_error(gs_error_unregistered); /* Unimplemented. */
211 return sputs(s, (const byte *)(p->Range != NULL ? &p->Range[0] : dummy),
212 sizeof(p->Range[0]) * p->n * 2, &n);
213 }
214
215