xref: /plan9/sys/src/cmd/gs/src/gsfunc.c (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
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