2 |
- |
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
|
|
|
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
|
|
|
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
|
|
|
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
|
|
|
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
|
|
|
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
|
|
|
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 *
|
|
|
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
|
|
|
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
|
|
|
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
|
|
|
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 |
|