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