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