/src/ghostpdl/psi/zshade.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* Copyright (C) 2001-2023 Artifex Software, Inc. |
2 | | All Rights Reserved. |
3 | | |
4 | | This software is provided AS-IS with no warranty, either express or |
5 | | implied. |
6 | | |
7 | | This software is distributed under license and may not be copied, |
8 | | modified or distributed except as expressly authorized under the terms |
9 | | of the license contained in the file LICENSE in this distribution. |
10 | | |
11 | | Refer to licensing information at http://www.artifex.com or contact |
12 | | Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco, |
13 | | CA 94129, USA, for further information. |
14 | | */ |
15 | | |
16 | | |
17 | | /* PostScript language interface to shading */ |
18 | | #include "memory_.h" |
19 | | #include "ghost.h" |
20 | | #include "oper.h" |
21 | | #include "gscolor3.h" |
22 | | #include "gscspace.h" |
23 | | #include "gscolor2.h" /* requires gscspace.h */ |
24 | | #include "gsfunc3.h" |
25 | | #include "gsptype2.h" |
26 | | #include "gsstruct.h" /* must precede gsshade.h */ |
27 | | #include "gsshade.h" |
28 | | #include "gsuid.h" |
29 | | #include "gscie.h" |
30 | | #include "stream.h" /* for files.h */ |
31 | | #include "files.h" |
32 | | #include "ialloc.h" |
33 | | #include "idict.h" |
34 | | #include "idparam.h" |
35 | | #include "ifunc.h" |
36 | | #include "igstate.h" |
37 | | #include "ipcolor.h" |
38 | | #include "store.h" |
39 | | |
40 | | /* Forward references */ |
41 | | static int shading_param(const_os_ptr op, const gs_shading_t ** ppsh); |
42 | | |
43 | | /* ---------------- Standard operators ---------------- */ |
44 | | |
45 | | /* - currentsmoothness <smoothness> */ |
46 | | static int |
47 | | zcurrentsmoothness(i_ctx_t *i_ctx_p) |
48 | 0 | { |
49 | 0 | os_ptr op = osp; |
50 | |
|
51 | 0 | push(1); |
52 | 0 | make_real(op, gs_currentsmoothness(igs)); |
53 | 0 | return 0; |
54 | 0 | } |
55 | | |
56 | | /* <smoothness> setsmoothness - */ |
57 | | static int |
58 | | zsetsmoothness(i_ctx_t *i_ctx_p) |
59 | 9.57k | { |
60 | 9.57k | os_ptr op = osp; |
61 | 9.57k | double smoothness; |
62 | 9.57k | int code; |
63 | | |
64 | 9.57k | check_op(1); |
65 | 9.57k | if (real_param(op, &smoothness) < 0) |
66 | 9.57k | return_op_typecheck(op); |
67 | 9.57k | if ((code = gs_setsmoothness(igs, smoothness)) < 0) |
68 | 0 | return code; |
69 | 9.57k | pop(1); |
70 | 9.57k | return 0; |
71 | 9.57k | } |
72 | | |
73 | | /* <shading> .shfill - */ |
74 | | static int |
75 | | zshfill(i_ctx_t *i_ctx_p) |
76 | 0 | { |
77 | 0 | os_ptr op = osp; |
78 | 0 | const gs_shading_t *psh; |
79 | 0 | int code; |
80 | |
|
81 | 0 | check_op(1); |
82 | 0 | code = shading_param(op, &psh); |
83 | 0 | if (code < 0 || (code = gs_shfill(igs, psh)) < 0) |
84 | 0 | return code; |
85 | 0 | pop(1); |
86 | 0 | return 0; |
87 | 0 | } |
88 | | |
89 | | /* ------ Non-standard operators ------ */ |
90 | | |
91 | | /* <pattern> <matrix> <shading> .buildshadingpattern <pattern> <instance> */ |
92 | | static int |
93 | | zbuildshadingpattern(i_ctx_t *i_ctx_p) |
94 | 0 | { |
95 | 0 | os_ptr op = osp; |
96 | 0 | os_ptr op2 = op - 2; |
97 | 0 | gs_matrix mat; |
98 | 0 | gs_pattern2_template_t templat; |
99 | 0 | int_pattern *pdata; |
100 | 0 | gs_client_color cc_instance; |
101 | 0 | int code; |
102 | |
|
103 | 0 | check_op(3); |
104 | 0 | check_type(*op2, t_dictionary); |
105 | 0 | check_dict_read(*op2); |
106 | 0 | gs_pattern2_init(&templat); |
107 | 0 | if ((code = read_matrix(imemory, op - 1, &mat)) < 0 || |
108 | 0 | (code = dict_uid_param(op2, &templat.uid, 1, imemory, i_ctx_p)) != 1 || |
109 | 0 | (code = shading_param(op, &templat.Shading)) < 0 || |
110 | 0 | (code = int_pattern_alloc(&pdata, op2, imemory)) < 0 |
111 | 0 | ) |
112 | 0 | return_error((code < 0 ? code : gs_error_rangecheck)); |
113 | 0 | code = gs_make_pattern(&cc_instance, |
114 | 0 | (const gs_pattern_template_t *)&templat, |
115 | 0 | &mat, igs, imemory); |
116 | 0 | if (code < 0) { |
117 | 0 | ifree_object(pdata, "int_pattern"); |
118 | 0 | return code; |
119 | 0 | } |
120 | 0 | cc_instance.pattern->client_data = pdata; |
121 | 0 | make_istruct(op - 1, a_readonly, cc_instance.pattern); |
122 | 0 | pop(1); |
123 | 0 | return code; |
124 | 0 | } |
125 | | |
126 | | /* ------ Internal procedures ------ */ |
127 | | |
128 | | /* Get a shading parameter. */ |
129 | | static int |
130 | | shading_param(const_os_ptr op, const gs_shading_t ** ppsh) |
131 | 0 | { /* |
132 | | * Since shadings form a subclass hierarchy, we currently have |
133 | | * no way to check whether a structure is actually a shading. |
134 | | */ |
135 | 0 | if (!r_is_struct(op) || |
136 | 0 | r_has_masked_attrs(op, a_execute, a_all) |
137 | 0 | ) |
138 | 0 | return_error(gs_error_typecheck); |
139 | 0 | *ppsh = (gs_shading_t *) op->value.pstruct; |
140 | 0 | return 0; |
141 | 0 | } |
142 | | |
143 | | /* ---------------- Shading dictionaries ---------------- */ |
144 | | |
145 | | /* ------ Common code ------ */ |
146 | | |
147 | | extern_st(st_color_space); |
148 | | |
149 | | typedef int (*build_shading_proc_t) |
150 | | (i_ctx_t *i_ctx_p, const ref *op, const gs_shading_params_t *params, |
151 | | gs_shading_t **ppsh, gs_memory_t *mem); |
152 | | |
153 | | /* Operators */ |
154 | | |
155 | | /* Common framework for building shadings. */ |
156 | | static int |
157 | | build_shading(i_ctx_t *i_ctx_p, build_shading_proc_t proc) |
158 | 0 | { |
159 | 0 | os_ptr op = osp; |
160 | 0 | int code; |
161 | 0 | float box[4]; |
162 | 0 | gs_shading_params_t params; |
163 | 0 | gs_shading_t *psh; |
164 | 0 | ref *pvalue; |
165 | |
|
166 | 0 | check_type(*op, t_dictionary); |
167 | 0 | params.ColorSpace = 0; |
168 | 0 | params.cie_joint_caches = 0; |
169 | 0 | params.Background = 0; |
170 | | /* Collect parameters common to all shading types. */ |
171 | 0 | { |
172 | 0 | gs_color_space *pcs = gs_currentcolorspace(igs); |
173 | 0 | int num_comp = gs_color_space_num_components(pcs); |
174 | |
|
175 | 0 | if (num_comp < 0) { /* Pattern color space */ |
176 | 0 | gs_errorinfo_put_pair_from_dict(i_ctx_p, op, "ColorSpace"); |
177 | 0 | return_error(gs_error_typecheck); |
178 | 0 | } |
179 | 0 | params.ColorSpace = pcs; |
180 | 0 | rc_increment_cs(pcs); |
181 | 0 | if (dict_find_string(op, "Background", &pvalue) > 0) { |
182 | 0 | gs_client_color *pcc = |
183 | 0 | ialloc_struct(gs_client_color, &st_client_color, |
184 | 0 | "build_shading"); |
185 | |
|
186 | 0 | if (pcc == 0) { |
187 | 0 | code = gs_note_error(gs_error_VMerror); |
188 | 0 | goto fail; |
189 | 0 | } |
190 | 0 | pcc->pattern = 0; |
191 | 0 | params.Background = pcc; |
192 | 0 | code = dict_floats_param(imemory, op, "Background", |
193 | 0 | gs_color_space_num_components(pcs), |
194 | 0 | pcc->paint.values, NULL); |
195 | 0 | if (code < 0) { |
196 | 0 | gs_errorinfo_put_pair_from_dict(i_ctx_p, op, "Background"); |
197 | 0 | goto fail; |
198 | 0 | } |
199 | 0 | } |
200 | 0 | } |
201 | 0 | if (dict_find_string(op, "BBox", &pvalue) <= 0) |
202 | 0 | params.have_BBox = false; |
203 | 0 | else if ((code = dict_floats_param(imemory, op, "BBox", |
204 | 0 | 4, box, NULL)) == 4) { |
205 | | /* Adobe Interpreters accept denormalised BBox - bug 688937 */ |
206 | 0 | if (box[0] <= box[2]) { |
207 | 0 | params.BBox.p.x = box[0]; |
208 | 0 | params.BBox.q.x = box[2]; |
209 | 0 | } else { |
210 | 0 | params.BBox.p.x = box[2]; |
211 | 0 | params.BBox.q.x = box[0]; |
212 | 0 | } |
213 | 0 | if (box[1] <= box[3]) { |
214 | 0 | params.BBox.p.y = box[1]; |
215 | 0 | params.BBox.q.y = box[3]; |
216 | 0 | } else { |
217 | 0 | params.BBox.p.y = box[3]; |
218 | 0 | params.BBox.q.y = box[1]; |
219 | 0 | } |
220 | 0 | params.have_BBox = true; |
221 | 0 | } else { |
222 | 0 | gs_errorinfo_put_pair_from_dict(i_ctx_p, op, "BBox"); |
223 | 0 | goto fail; |
224 | 0 | } |
225 | 0 | code = dict_bool_param(op, "AntiAlias", false, ¶ms.AntiAlias); |
226 | 0 | if (code < 0) { |
227 | 0 | gs_errorinfo_put_pair_from_dict(i_ctx_p, op, "AntiAlias"); |
228 | 0 | goto fail; |
229 | 0 | } |
230 | | /* Finish building the shading. */ |
231 | 0 | code = (*proc)(i_ctx_p, op, ¶ms, &psh, imemory); |
232 | 0 | if (code < 0) |
233 | 0 | goto fail; |
234 | 0 | if (gx_color_space_needs_cie_caches(psh->params.ColorSpace)) { |
235 | 0 | rc_decrement(psh->params.cie_joint_caches, "build_shading"); |
236 | | /* gx_currentciecaches_for_mem passes us a new reference */ |
237 | 0 | psh->params.cie_joint_caches = gx_get_cie_caches_ref(igs, imemory); |
238 | 0 | if (psh->params.cie_joint_caches == NULL) |
239 | 0 | return gs_error_VMerror; |
240 | 0 | } |
241 | 0 | make_istruct_new(op, 0, psh); |
242 | 0 | return code; |
243 | 0 | fail: |
244 | 0 | gs_free_object(imemory, params.Background, "Background"); |
245 | 0 | if (params.ColorSpace) { |
246 | 0 | rc_decrement_only_cs(params.ColorSpace, "build_shading"); |
247 | 0 | } |
248 | 0 | return (code < 0 ? code : gs_note_error(gs_error_rangecheck)); |
249 | 0 | } |
250 | | |
251 | | /* Collect a Function value. */ |
252 | | static int |
253 | | build_shading_function(i_ctx_t *i_ctx_p, const ref * op, gs_function_t ** ppfn, |
254 | | int num_inputs, gs_memory_t *mem, const float *shading_domain) |
255 | 0 | { |
256 | 0 | ref *pFunction; |
257 | 0 | int code; |
258 | |
|
259 | 0 | *ppfn = 0; |
260 | 0 | if (dict_find_string(op, "Function", &pFunction) <= 0) |
261 | 0 | return 0; |
262 | 0 | if (r_is_array(pFunction)) { |
263 | 0 | uint size = r_size(pFunction); |
264 | 0 | gs_function_t **Functions; |
265 | 0 | uint i; |
266 | 0 | gs_function_AdOt_params_t params; |
267 | |
|
268 | 0 | check_read(*pFunction); |
269 | 0 | if (size == 0) |
270 | 0 | return_error(gs_error_rangecheck); |
271 | 0 | code = alloc_function_array(size, &Functions, mem); |
272 | 0 | if (code < 0) |
273 | 0 | return code; |
274 | 0 | for (i = 0; i < size; ++i) { |
275 | 0 | ref rsubfn; |
276 | |
|
277 | 0 | array_get(imemory, pFunction, (long)i, &rsubfn); |
278 | 0 | code = fn_build_function(i_ctx_p, &rsubfn, &Functions[i], mem, |
279 | 0 | shading_domain, num_inputs); |
280 | 0 | if (code < 0) |
281 | 0 | break; |
282 | 0 | } |
283 | 0 | params.m = num_inputs; |
284 | 0 | params.Domain = 0; |
285 | 0 | params.n = size; |
286 | 0 | params.Range = 0; |
287 | 0 | params.Functions = (const gs_function_t * const *)Functions; |
288 | 0 | if (code >= 0) |
289 | 0 | code = gs_function_AdOt_init(ppfn, ¶ms, mem); |
290 | 0 | if (code < 0) |
291 | 0 | gs_function_AdOt_free_params(¶ms, mem); |
292 | 0 | } else { |
293 | 0 | code = fn_build_function(i_ctx_p, pFunction, ppfn, mem, |
294 | 0 | shading_domain, num_inputs); |
295 | 0 | if (code < 0) |
296 | 0 | return code; |
297 | 0 | if ((*ppfn)->params.m != num_inputs) { |
298 | 0 | gs_function_free(*ppfn, true, mem); |
299 | 0 | return_error(gs_error_rangecheck); |
300 | 0 | } |
301 | 0 | } |
302 | 0 | return code; |
303 | 0 | } |
304 | | |
305 | | /* According to PLRM 3rd ed, p. 264 "indexed color space is not |
306 | | * allowed in any shading whose color values are generated by a function; |
307 | | * this applies to any shading dictionary that contains a Function entry." |
308 | | * Adobe interpreters follow PLRM in this respect and we follow them. |
309 | | */ |
310 | | static int |
311 | | check_indexed_vs_function(i_ctx_t *i_ctx_p, const ref *op, |
312 | | const gs_color_space *pcs, const gs_function_t *funct) |
313 | 0 | { if (funct && gs_color_space_get_index(pcs) == gs_color_space_index_Indexed) { |
314 | 0 | static const char fn[] = "Function"; |
315 | 0 | ref *f; |
316 | 0 | if (dict_find_string(op, fn, &f) > 0) |
317 | 0 | gs_errorinfo_put_pair(i_ctx_p, fn, sizeof(fn) - 1, f); |
318 | 0 | return_error(gs_error_typecheck); /* CET 12-14a */ |
319 | 0 | } |
320 | 0 | return 0; |
321 | 0 | } |
322 | | |
323 | | /* ------ Build shadings ------ */ |
324 | | |
325 | | /* Build a ShadingType 1 (Function-based) shading. */ |
326 | | static int |
327 | | build_shading_1(i_ctx_t *i_ctx_p, const ref * op, const gs_shading_params_t * pcommon, |
328 | | gs_shading_t ** ppsh, gs_memory_t *mem) |
329 | 0 | { |
330 | 0 | gs_shading_Fb_params_t params; |
331 | 0 | int code; |
332 | 0 | static const float default_Domain[4] = {0, 1, 0, 1}; |
333 | 0 | ref *pmatrix; |
334 | |
|
335 | 0 | *(gs_shading_params_t *)¶ms = *pcommon; |
336 | 0 | gs_make_identity(¶ms.Matrix); |
337 | 0 | params.Function = 0; |
338 | 0 | code = dict_floats_param_errorinfo(i_ctx_p, op, "Domain", |
339 | 0 | 4, params.Domain, default_Domain); |
340 | 0 | if (code < 0) |
341 | 0 | goto out; |
342 | 0 | if (params.Domain[0] > params.Domain[1] || params.Domain[2] > params.Domain[3]) { |
343 | 0 | gs_errorinfo_put_pair_from_dict(i_ctx_p, op, "Domain"); |
344 | 0 | code = gs_note_error(gs_error_rangecheck); |
345 | 0 | goto out; /* CPSI 3017 and CET 12-14b reject un-normalised domain */ |
346 | 0 | } |
347 | 0 | if (dict_find_string(op, "Matrix", &pmatrix) > 0 ) { |
348 | 0 | code = read_matrix(imemory, pmatrix, ¶ms.Matrix); |
349 | 0 | if (code < 0) { |
350 | 0 | gs_errorinfo_put_pair_from_dict(i_ctx_p, op, "Matrix"); |
351 | 0 | goto out; |
352 | 0 | } |
353 | 0 | } |
354 | 0 | code = build_shading_function(i_ctx_p, op, ¶ms.Function, 2, mem, params.Domain); |
355 | 0 | if (code < 0) |
356 | 0 | goto out; |
357 | 0 | if (params.Function == 0) { /* Function is required */ |
358 | 0 | code = gs_note_error(gs_error_undefined); |
359 | 0 | gs_errorinfo_put_pair_from_dict(i_ctx_p, op, "Function"); |
360 | 0 | goto out; |
361 | 0 | } |
362 | 0 | code = check_indexed_vs_function(i_ctx_p, op, params.ColorSpace, params.Function); |
363 | 0 | if (code < 0) |
364 | 0 | goto out; |
365 | 0 | code = gs_shading_Fb_init(ppsh, ¶ms, mem); |
366 | 0 | out:; |
367 | 0 | if (code < 0 && params.Function) |
368 | 0 | gs_free_object(mem, params.Function, "Function"); |
369 | 0 | return code; |
370 | 0 | } |
371 | | /* <dict> .buildshading1 <shading_struct> */ |
372 | | static int |
373 | | zbuildshading1(i_ctx_t *i_ctx_p) |
374 | 0 | { |
375 | 0 | return build_shading(i_ctx_p, build_shading_1); |
376 | 0 | } |
377 | | |
378 | | /* Collect parameters for an Axial or Radial shading. */ |
379 | | static int |
380 | | build_directional_shading(i_ctx_t *i_ctx_p, const ref * op, float *Coords, int num_Coords, |
381 | | float Domain[2], gs_function_t ** pFunction, |
382 | | bool Extend[2], gs_memory_t *mem) |
383 | 0 | { |
384 | 0 | int code = dict_floats_param(imemory, op, "Coords", |
385 | 0 | num_Coords, Coords, NULL); |
386 | 0 | static const float default_Domain[2] = {0, 1}; |
387 | 0 | ref *pExtend; |
388 | |
|
389 | 0 | if (code >= 0 && code < num_Coords) { |
390 | 0 | code = gs_note_error(gs_error_rangecheck); |
391 | 0 | } |
392 | |
|
393 | 0 | *pFunction = 0; |
394 | 0 | if (code < 0 || |
395 | 0 | (code = dict_floats_param_errorinfo(i_ctx_p, op, "Domain", 2, Domain, |
396 | 0 | default_Domain)) < 0 || |
397 | 0 | (code = build_shading_function(i_ctx_p, op, pFunction, 1, mem, Domain)) < 0 |
398 | 0 | ) |
399 | 0 | return code; |
400 | 0 | if (!*pFunction) |
401 | 0 | return_error(gs_error_undefined); |
402 | 0 | if (dict_find_string(op, "Extend", &pExtend) <= 0) |
403 | 0 | Extend[0] = Extend[1] = false; |
404 | 0 | else { |
405 | 0 | ref E0, E1; |
406 | |
|
407 | 0 | if (!r_is_array(pExtend)) |
408 | 0 | return_error(gs_error_typecheck); |
409 | 0 | else if (r_size(pExtend) != 2) |
410 | 0 | return_error(gs_error_rangecheck); |
411 | 0 | else if ((array_get(imemory, pExtend, 0L, &E0), |
412 | 0 | !r_has_type(&E0, t_boolean)) || |
413 | 0 | (array_get(imemory, pExtend, 1L, &E1), |
414 | 0 | !r_has_type(&E1, t_boolean)) |
415 | 0 | ) |
416 | 0 | return_error(gs_error_typecheck); |
417 | 0 | Extend[0] = E0.value.boolval, Extend[1] = E1.value.boolval; |
418 | 0 | } |
419 | 0 | return 0; |
420 | 0 | } |
421 | | |
422 | | /* Build a ShadingType 2 (Axial) shading. */ |
423 | | static int |
424 | | build_shading_2(i_ctx_t *i_ctx_p, const ref * op, const gs_shading_params_t * pcommon, |
425 | | gs_shading_t ** ppsh, gs_memory_t *mem) |
426 | 0 | { |
427 | 0 | gs_shading_A_params_t params; |
428 | 0 | int code; |
429 | |
|
430 | 0 | check_op(1); |
431 | 0 | *(gs_shading_params_t *)¶ms = *pcommon; |
432 | 0 | if ((code = build_directional_shading(i_ctx_p, op, params.Coords, 4, |
433 | 0 | params.Domain, ¶ms.Function, |
434 | 0 | params.Extend, mem)) < 0 || |
435 | 0 | (code = check_indexed_vs_function(i_ctx_p, op, params.ColorSpace, params.Function)) < 0 || |
436 | 0 | (code = gs_shading_A_init(ppsh, ¶ms, mem)) < 0 |
437 | 0 | ) { |
438 | 0 | gs_free_object(mem, params.Function, "Function"); |
439 | 0 | } |
440 | 0 | return code; |
441 | 0 | } |
442 | | /* <dict> .buildshading2 <shading_struct> */ |
443 | | static int |
444 | | zbuildshading2(i_ctx_t *i_ctx_p) |
445 | 0 | { |
446 | 0 | return build_shading(i_ctx_p, build_shading_2); |
447 | 0 | } |
448 | | |
449 | | /* Build a ShadingType 3 (Radial) shading. */ |
450 | | static int |
451 | | build_shading_3(i_ctx_t *i_ctx_p, const ref * op, const gs_shading_params_t * pcommon, |
452 | | gs_shading_t ** ppsh, gs_memory_t *mem) |
453 | 0 | { |
454 | 0 | gs_shading_R_params_t params; |
455 | 0 | int code; |
456 | |
|
457 | 0 | *(gs_shading_params_t *)¶ms = *pcommon; |
458 | 0 | if ((code = build_directional_shading(i_ctx_p, op, params.Coords, 6, |
459 | 0 | params.Domain, ¶ms.Function, |
460 | 0 | params.Extend, mem)) < 0 || |
461 | 0 | (code = check_indexed_vs_function(i_ctx_p, op, params.ColorSpace, params.Function)) < 0 || |
462 | 0 | (code = gs_shading_R_init(ppsh, ¶ms, mem)) < 0 |
463 | 0 | ) { |
464 | 0 | gs_free_object(mem, params.Function, "Function"); |
465 | 0 | } |
466 | 0 | if (params.Function == 0) /* Function is required */ |
467 | 0 | return_error(gs_error_undefined); |
468 | 0 | return code; |
469 | 0 | } |
470 | | /* <dict> .buildshading3 <shading_struct> */ |
471 | | static int |
472 | | zbuildshading3(i_ctx_t *i_ctx_p) |
473 | 0 | { |
474 | 0 | return build_shading(i_ctx_p, build_shading_3); |
475 | 0 | } |
476 | | |
477 | | /* Collect parameters for a mesh shading. */ |
478 | | static int |
479 | | build_mesh_shading(i_ctx_t *i_ctx_p, const ref * op, |
480 | | gs_shading_mesh_params_t * params, |
481 | | float **pDecode, gs_function_t ** pFunction, |
482 | | gs_memory_t *mem) |
483 | 0 | { |
484 | 0 | int code; |
485 | 0 | float *data = 0; |
486 | 0 | ref *pDataSource; |
487 | |
|
488 | 0 | *pDecode = 0; |
489 | 0 | *pFunction = 0; |
490 | 0 | if (dict_find_string(op, "DataSource", &pDataSource) <= 0) |
491 | 0 | return_error(gs_error_rangecheck); |
492 | 0 | if (r_is_array(pDataSource)) { |
493 | 0 | uint size = r_size(pDataSource); |
494 | |
|
495 | 0 | data = (float *)gs_alloc_byte_array(mem, size, sizeof(float), |
496 | 0 | "build_mesh_shading"); |
497 | 0 | if (data == 0) |
498 | 0 | return_error(gs_error_VMerror); |
499 | 0 | code = process_float_array(mem, pDataSource, size, data); |
500 | 0 | if (code < 0) { |
501 | 0 | gs_free_object(mem, data, "build_mesh_shading"); |
502 | 0 | return code; |
503 | 0 | } |
504 | 0 | data_source_init_floats(¶ms->DataSource, data, size); |
505 | 0 | } else |
506 | 0 | switch (r_type(pDataSource)) { |
507 | 0 | case t_file: { |
508 | 0 | stream *s; |
509 | |
|
510 | 0 | check_read_file(i_ctx_p, s, pDataSource); |
511 | 0 | data_source_init_stream(¶ms->DataSource, s); |
512 | 0 | break; |
513 | 0 | } |
514 | 0 | case t_string: |
515 | 0 | check_read(*pDataSource); |
516 | 0 | data_source_init_string2(¶ms->DataSource, |
517 | 0 | pDataSource->value.bytes, |
518 | 0 | r_size(pDataSource)); |
519 | 0 | break; |
520 | 0 | default: |
521 | 0 | return_error(gs_error_typecheck); |
522 | 0 | } |
523 | 0 | code = build_shading_function(i_ctx_p, op, pFunction, 1, mem, NULL); |
524 | 0 | if (code < 0) { |
525 | 0 | gs_free_object(mem, data, "build_mesh_shading"); |
526 | 0 | return code; |
527 | 0 | } |
528 | 0 | if (data_source_is_array(params->DataSource)) { |
529 | 0 | params->BitsPerCoordinate = 0; |
530 | 0 | params->BitsPerComponent = 0; |
531 | 0 | } else { |
532 | 0 | int num_decode = 4 + |
533 | 0 | (*pFunction != 0 ? 1 : |
534 | 0 | gs_color_space_num_components(params->ColorSpace)) * 2; |
535 | |
|
536 | 0 | if ((code = dict_int_param(op, "BitsPerCoordinate", 1, 32, 0, |
537 | 0 | ¶ms->BitsPerCoordinate)) >= 0 && |
538 | 0 | (code = dict_int_param(op, "BitsPerComponent", 1, 16, 0, |
539 | 0 | ¶ms->BitsPerComponent)) >= 0 |
540 | 0 | ) { |
541 | 0 | *pDecode = (float *) |
542 | 0 | gs_alloc_byte_array(mem, num_decode, sizeof(float), |
543 | 0 | "build_mesh_shading"); |
544 | 0 | if (*pDecode == 0) |
545 | 0 | code = gs_note_error(gs_error_VMerror); |
546 | 0 | else { |
547 | 0 | code = dict_floats_param(mem, op, "Decode", num_decode, *pDecode, NULL); |
548 | 0 | if (code < 0) { |
549 | 0 | gs_free_object(mem, *pDecode, "build_mesh_shading"); |
550 | 0 | *pDecode = 0; |
551 | 0 | } |
552 | 0 | } |
553 | 0 | } |
554 | 0 | } |
555 | 0 | if (code < 0) { |
556 | 0 | if (*pFunction != 0) { |
557 | 0 | gs_function_free(*pFunction, true, mem); |
558 | 0 | *pFunction = 0; |
559 | 0 | } |
560 | 0 | gs_free_object(mem, data, "build_mesh_shading"); |
561 | 0 | } |
562 | 0 | return code; |
563 | 0 | } |
564 | | |
565 | | /* Collect the BitsPerFlag parameter, if relevant. */ |
566 | | static int |
567 | | flag_bits_param(const ref * op, const gs_shading_mesh_params_t * params, |
568 | | int *pBitsPerFlag) |
569 | 0 | { |
570 | 0 | if (data_source_is_array(params->DataSource)) { |
571 | 0 | *pBitsPerFlag = 0; |
572 | 0 | return 0; |
573 | 0 | } else { |
574 | 0 | return dict_int_param(op, "BitsPerFlag", 2, 8, 0, pBitsPerFlag); |
575 | 0 | } |
576 | 0 | } |
577 | | |
578 | | /* Build a ShadingType 4 (Free-form Gouraud triangle mesh) shading. */ |
579 | | static int |
580 | | build_shading_4(i_ctx_t *i_ctx_p, const ref * op, const gs_shading_params_t * pcommon, |
581 | | gs_shading_t ** ppsh, gs_memory_t *mem) |
582 | 0 | { |
583 | 0 | gs_shading_FfGt_params_t params; |
584 | 0 | int code; |
585 | |
|
586 | 0 | *(gs_shading_params_t *)¶ms = *pcommon; |
587 | 0 | if ((code = |
588 | 0 | build_mesh_shading(i_ctx_p, op, (gs_shading_mesh_params_t *)¶ms, |
589 | 0 | ¶ms.Decode, ¶ms.Function, mem)) < 0 || |
590 | 0 | (code = check_indexed_vs_function(i_ctx_p, op, params.ColorSpace, params.Function)) < 0 || |
591 | 0 | (code = flag_bits_param(op, (gs_shading_mesh_params_t *)¶ms, |
592 | 0 | ¶ms.BitsPerFlag)) < 0 || |
593 | 0 | (code = gs_shading_FfGt_init(ppsh, ¶ms, mem)) < 0 |
594 | 0 | ) { |
595 | 0 | gs_free_object(mem, params.Function, "Function"); |
596 | 0 | gs_free_object(mem, params.Decode, "Decode"); |
597 | 0 | } |
598 | 0 | return code; |
599 | 0 | } |
600 | | /* <dict> .buildshading4 <shading_struct> */ |
601 | | static int |
602 | | zbuildshading4(i_ctx_t *i_ctx_p) |
603 | 0 | { |
604 | 0 | return build_shading(i_ctx_p, build_shading_4); |
605 | 0 | } |
606 | | |
607 | | /* Build a ShadingType 5 (Lattice-form Gouraud triangle mesh) shading. */ |
608 | | static int |
609 | | build_shading_5(i_ctx_t *i_ctx_p, const ref * op, const gs_shading_params_t * pcommon, |
610 | | gs_shading_t ** ppsh, gs_memory_t *mem) |
611 | 0 | { |
612 | 0 | gs_shading_LfGt_params_t params; |
613 | 0 | int code; |
614 | |
|
615 | 0 | *(gs_shading_params_t *)¶ms = *pcommon; |
616 | 0 | if ((code = |
617 | 0 | build_mesh_shading(i_ctx_p, op, (gs_shading_mesh_params_t *)¶ms, |
618 | 0 | ¶ms.Decode, ¶ms.Function, mem)) < 0 || |
619 | 0 | (code = check_indexed_vs_function(i_ctx_p, op, params.ColorSpace, params.Function)) < 0 || |
620 | 0 | (code = dict_int_param(op, "VerticesPerRow", 2, max_int, 0, |
621 | 0 | ¶ms.VerticesPerRow)) < 0 || |
622 | 0 | (code = gs_shading_LfGt_init(ppsh, ¶ms, mem)) < 0 |
623 | 0 | ) { |
624 | 0 | gs_free_object(mem, params.Function, "Function"); |
625 | 0 | gs_free_object(mem, params.Decode, "Decode"); |
626 | 0 | } |
627 | 0 | return code; |
628 | 0 | } |
629 | | /* <dict> .buildshading5 <shading_struct> */ |
630 | | static int |
631 | | zbuildshading5(i_ctx_t *i_ctx_p) |
632 | 0 | { |
633 | 0 | return build_shading(i_ctx_p, build_shading_5); |
634 | 0 | } |
635 | | |
636 | | /* Build a ShadingType 6 (Coons patch mesh) shading. */ |
637 | | static int |
638 | | build_shading_6(i_ctx_t *i_ctx_p, const ref * op, const gs_shading_params_t * pcommon, |
639 | | gs_shading_t ** ppsh, gs_memory_t *mem) |
640 | 0 | { |
641 | 0 | gs_shading_Cp_params_t params; |
642 | 0 | int code; |
643 | |
|
644 | 0 | *(gs_shading_params_t *)¶ms = *pcommon; |
645 | 0 | if ((code = |
646 | 0 | build_mesh_shading(i_ctx_p, op, (gs_shading_mesh_params_t *)¶ms, |
647 | 0 | ¶ms.Decode, ¶ms.Function, mem)) < 0 || |
648 | 0 | (code = check_indexed_vs_function(i_ctx_p, op, params.ColorSpace, params.Function)) < 0 || |
649 | 0 | (code = flag_bits_param(op, (gs_shading_mesh_params_t *)¶ms, |
650 | 0 | ¶ms.BitsPerFlag)) < 0 || |
651 | 0 | (code = gs_shading_Cp_init(ppsh, ¶ms, mem)) < 0 |
652 | 0 | ) { |
653 | 0 | gs_free_object(mem, params.Function, "Function"); |
654 | 0 | gs_free_object(mem, params.Decode, "Decode"); |
655 | 0 | } |
656 | 0 | return code; |
657 | 0 | } |
658 | | /* <dict> .buildshading6 <shading_struct> */ |
659 | | static int |
660 | | zbuildshading6(i_ctx_t *i_ctx_p) |
661 | 0 | { |
662 | 0 | return build_shading(i_ctx_p, build_shading_6); |
663 | 0 | } |
664 | | |
665 | | /* Build a ShadingType 7 (Tensor product patch mesh) shading. */ |
666 | | static int |
667 | | build_shading_7(i_ctx_t *i_ctx_p, const ref * op, const gs_shading_params_t * pcommon, |
668 | | gs_shading_t ** ppsh, gs_memory_t *mem) |
669 | 0 | { |
670 | 0 | gs_shading_Tpp_params_t params; |
671 | 0 | int code; |
672 | |
|
673 | 0 | *(gs_shading_params_t *)¶ms = *pcommon; |
674 | 0 | if ((code = |
675 | 0 | build_mesh_shading(i_ctx_p, op, (gs_shading_mesh_params_t *)¶ms, |
676 | 0 | ¶ms.Decode, ¶ms.Function, mem)) < 0 || |
677 | 0 | (code = check_indexed_vs_function(i_ctx_p, op, params.ColorSpace, params.Function)) < 0 || |
678 | 0 | (code = flag_bits_param(op, (gs_shading_mesh_params_t *)¶ms, |
679 | 0 | ¶ms.BitsPerFlag)) < 0 || |
680 | 0 | (code = gs_shading_Tpp_init(ppsh, ¶ms, mem)) < 0 |
681 | 0 | ) { |
682 | 0 | gs_free_object(mem, params.Function, "Function"); |
683 | 0 | gs_free_object(mem, params.Decode, "Decode"); |
684 | 0 | } |
685 | 0 | return code; |
686 | 0 | } |
687 | | /* <dict> .buildshading7 <shading_struct> */ |
688 | | static int |
689 | | zbuildshading7(i_ctx_t *i_ctx_p) |
690 | 0 | { |
691 | 0 | return build_shading(i_ctx_p, build_shading_7); |
692 | 0 | } |
693 | | |
694 | | /* ------ Initialization procedure ------ */ |
695 | | |
696 | | const op_def zshade_op_defs[] = |
697 | | { |
698 | | op_def_begin_ll3(), |
699 | | {"0currentsmoothness", zcurrentsmoothness}, |
700 | | {"1setsmoothness", zsetsmoothness}, |
701 | | {"1.shfill", zshfill}, |
702 | | {"1.buildshading1", zbuildshading1}, |
703 | | {"1.buildshading2", zbuildshading2}, |
704 | | {"1.buildshading3", zbuildshading3}, |
705 | | {"1.buildshading4", zbuildshading4}, |
706 | | {"1.buildshading5", zbuildshading5}, |
707 | | {"1.buildshading6", zbuildshading6}, |
708 | | {"1.buildshading7", zbuildshading7}, |
709 | | {"3.buildshadingpattern", zbuildshadingpattern}, |
710 | | op_def_end(0) |
711 | | }; |