1 /* Copyright (C) 1998, 1999 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: gxshade.c,v 1.22 2005/01/31 03:08:43 igor Exp $ */
18 /* Shading rendering support */
19 #include "math_.h"
20 #include "gx.h"
21 #include "gserrors.h"
22 #include "gsrect.h"
23 #include "gxcspace.h"
24 #include "gscindex.h"
25 #include "gscie.h" /* requires gscspace.h */
26 #include "gxdevcli.h"
27 #include "gxistate.h"
28 #include "gxdht.h" /* for computing # of different colors */
29 #include "gxpaint.h"
30 #include "gxshade.h"
31 #include "gxshade4.h"
32 #include "gsicc.h"
33
34 /* Define a maximum smoothness value. */
35 /* smoothness > 0.2 produces severely blocky output. */
36 #define MAX_SMOOTHNESS 0.2
37
38 /* ================ Packed coordinate streams ================ */
39
40 /* Forward references */
41 private int cs_next_packed_value(shade_coord_stream_t *, int, uint *);
42 private int cs_next_array_value(shade_coord_stream_t *, int, uint *);
43 private int cs_next_packed_decoded(shade_coord_stream_t *, int,
44 const float[2], float *);
45 private int cs_next_array_decoded(shade_coord_stream_t *, int,
46 const float[2], float *);
47 private bool cs_eod(const shade_coord_stream_t * cs);
48
49 /* Initialize a packed value stream. */
50 void
shade_next_init(shade_coord_stream_t * cs,const gs_shading_mesh_params_t * params,const gs_imager_state * pis)51 shade_next_init(shade_coord_stream_t * cs,
52 const gs_shading_mesh_params_t * params,
53 const gs_imager_state * pis)
54 {
55 cs->params = params;
56 cs->pctm = &pis->ctm;
57 if (data_source_is_stream(params->DataSource)) {
58 /*
59 * Reset the data stream iff it is reusable -- either a reusable
60 * file or a reusable string.
61 */
62 stream *s = cs->s = params->DataSource.data.strm;
63
64 if ((s->file != 0 && s->file_limit != max_long) ||
65 (s->file == 0 && s->strm == 0)
66 )
67 sreset(s);
68 } else {
69 sread_string(&cs->ds, params->DataSource.data.str.data,
70 params->DataSource.data.str.size);
71 cs->s = &cs->ds;
72 }
73 if (data_source_is_array(params->DataSource)) {
74 cs->get_value = cs_next_array_value;
75 cs->get_decoded = cs_next_array_decoded;
76 } else {
77 cs->get_value = cs_next_packed_value;
78 cs->get_decoded = cs_next_packed_decoded;
79 }
80 cs->is_eod = cs_eod;
81 cs->left = 0;
82 cs->ds_EOF = false;
83 }
84
85 /* Check for the End-Of-Data state form a stream. */
86 private bool
cs_eod(const shade_coord_stream_t * cs)87 cs_eod(const shade_coord_stream_t * cs)
88 {
89 return cs->ds_EOF;
90 }
91
92 /* Get the next (integer) value from a packed value stream. */
93 /* 1 <= num_bits <= sizeof(uint) * 8. */
94 private int
cs_next_packed_value(shade_coord_stream_t * cs,int num_bits,uint * pvalue)95 cs_next_packed_value(shade_coord_stream_t * cs, int num_bits, uint * pvalue)
96 {
97 uint bits = cs->bits;
98 int left = cs->left;
99
100 if (left >= num_bits) {
101 /* We can satisfy this request with the current buffered bits. */
102 cs->left = left -= num_bits;
103 *pvalue = (bits >> left) & ((1 << num_bits) - 1);
104 } else {
105 /* We need more bits. */
106 int needed = num_bits - left;
107 uint value = bits & ((1 << left) - 1); /* all the remaining bits */
108
109 for (; needed >= 8; needed -= 8) {
110 int b = sgetc(cs->s);
111
112 if (b < 0) {
113 cs->ds_EOF = true;
114 return_error(gs_error_rangecheck);
115 }
116 value = (value << 8) + b;
117 }
118 if (needed == 0) {
119 cs->left = 0;
120 *pvalue = value;
121 } else {
122 int b = sgetc(cs->s);
123
124 if (b < 0) {
125 cs->ds_EOF = true;
126 return_error(gs_error_rangecheck);
127 }
128 cs->bits = b;
129 cs->left = left = 8 - needed;
130 *pvalue = (value << needed) + (b >> left);
131 }
132 }
133 return 0;
134 }
135
136 /*
137 * Get the next (integer) value from an unpacked array. Note that
138 * num_bits may be 0 if we are reading a coordinate or color value.
139 */
140 private int
cs_next_array_value(shade_coord_stream_t * cs,int num_bits,uint * pvalue)141 cs_next_array_value(shade_coord_stream_t * cs, int num_bits, uint * pvalue)
142 {
143 float value;
144 uint read;
145
146 if (sgets(cs->s, (byte *)&value, sizeof(float), &read) < 0 ||
147 read != sizeof(float)) {
148 cs->ds_EOF = true;
149 return_error(gs_error_rangecheck);
150 }
151 if (value < 0 || (num_bits != 0 && num_bits < sizeof(uint) * 8 &&
152 value >= (1 << num_bits)) ||
153 value != (uint)value
154 )
155 return_error(gs_error_rangecheck);
156 *pvalue = (uint) value;
157 return 0;
158 }
159
160 /* Get the next decoded floating point value. */
161 private int
cs_next_packed_decoded(shade_coord_stream_t * cs,int num_bits,const float decode[2],float * pvalue)162 cs_next_packed_decoded(shade_coord_stream_t * cs, int num_bits,
163 const float decode[2], float *pvalue)
164 {
165 uint value;
166 int code = cs->get_value(cs, num_bits, &value);
167 #if ARCH_CAN_SHIFT_FULL_LONG
168 double max_value = (double)(uint) ((1 << num_bits) - 1);
169 #else
170 double max_value = (double)(uint)
171 (num_bits == sizeof(uint) * 8 ? ~0 : ((1 << num_bits) - 1));
172 #endif
173
174 if (code < 0)
175 return code;
176 *pvalue =
177 (decode == 0 ? value / max_value :
178 decode[0] + value * (decode[1] - decode[0]) / max_value);
179 return 0;
180 }
181
182 /* Get the next floating point value from an array, without decoding. */
183 private int
cs_next_array_decoded(shade_coord_stream_t * cs,int num_bits,const float decode[2],float * pvalue)184 cs_next_array_decoded(shade_coord_stream_t * cs, int num_bits,
185 const float decode[2], float *pvalue)
186 {
187 float value;
188 uint read;
189
190 if (sgets(cs->s, (byte *)&value, sizeof(float), &read) < 0 ||
191 read != sizeof(float)
192 ) {
193 cs->ds_EOF = true;
194 return_error(gs_error_rangecheck);
195 }
196 *pvalue = value;
197 return 0;
198 }
199
200 /* Get the next flag value. */
201 /* Note that this always starts a new data byte. */
202 int
shade_next_flag(shade_coord_stream_t * cs,int BitsPerFlag)203 shade_next_flag(shade_coord_stream_t * cs, int BitsPerFlag)
204 {
205 uint flag;
206 int code;
207
208 cs->left = 0; /* start a new byte if packed */
209 code = cs->get_value(cs, BitsPerFlag, &flag);
210 return (code < 0 ? code : flag);
211 }
212
213 /* Get one or more coordinate pairs. */
214 int
shade_next_coords(shade_coord_stream_t * cs,gs_fixed_point * ppt,int num_points)215 shade_next_coords(shade_coord_stream_t * cs, gs_fixed_point * ppt,
216 int num_points)
217 {
218 int num_bits = cs->params->BitsPerCoordinate;
219 const float *decode = cs->params->Decode;
220 int code = 0;
221 int i;
222
223 for (i = 0; i < num_points; ++i) {
224 float x, y;
225
226 if ((code = cs->get_decoded(cs, num_bits, decode, &x)) < 0 ||
227 (code = cs->get_decoded(cs, num_bits, decode + 2, &y)) < 0 ||
228 (code = gs_point_transform2fixed(cs->pctm, x, y, &ppt[i])) < 0
229 )
230 break;
231 }
232 return code;
233 }
234
235 /* Get a color. Currently all this does is look up Indexed colors. */
236 int
shade_next_color(shade_coord_stream_t * cs,float * pc)237 shade_next_color(shade_coord_stream_t * cs, float *pc)
238 {
239 const float *decode = cs->params->Decode + 4; /* skip coord decode */
240 const gs_color_space *pcs = cs->params->ColorSpace;
241 gs_color_space_index index = gs_color_space_get_index(pcs);
242 int num_bits = cs->params->BitsPerComponent;
243
244 if (index == gs_color_space_index_Indexed) {
245 int ncomp = gs_color_space_num_components(gs_cspace_base_space(pcs));
246 uint ci;
247 int code = cs->get_value(cs, num_bits, &ci);
248 gs_client_color cc;
249 int i;
250
251 if (code < 0)
252 return code;
253 if (ci >= gs_cspace_indexed_num_entries(pcs))
254 return_error(gs_error_rangecheck);
255 code = gs_cspace_indexed_lookup(&pcs->params.indexed, (int)ci, &cc);
256 if (code < 0)
257 return code;
258 for (i = 0; i < ncomp; ++i)
259 pc[i] = cc.paint.values[i];
260 } else {
261 int i, code;
262 int ncomp = (cs->params->Function != 0 ? 1 :
263 gs_color_space_num_components(pcs));
264
265 for (i = 0; i < ncomp; ++i)
266 if ((code = cs->get_decoded(cs, num_bits, decode + i * 2, &pc[i])) < 0)
267 return code;
268 }
269 return 0;
270 }
271
272 /* Get the next vertex for a mesh element. */
273 int
shade_next_vertex(shade_coord_stream_t * cs,shading_vertex_t * vertex)274 shade_next_vertex(shade_coord_stream_t * cs, shading_vertex_t * vertex)
275 {
276 int code = shade_next_coords(cs, &vertex->p, 1);
277
278 vertex->c.cc.paint.values[1] = 0; /* safety. (patch_fill may assume 2 arguments) */
279 if (code >= 0)
280 code = shade_next_color(cs, vertex->c.cc.paint.values);
281 return code;
282 }
283
284 /* ================ Shading rendering ================ */
285
286 /* Initialize the common parts of the recursion state. */
287 void
shade_init_fill_state(shading_fill_state_t * pfs,const gs_shading_t * psh,gx_device * dev,gs_imager_state * pis)288 shade_init_fill_state(shading_fill_state_t * pfs, const gs_shading_t * psh,
289 gx_device * dev, gs_imager_state * pis)
290 {
291 const gs_color_space *pcs = psh->params.ColorSpace;
292 float max_error = min(pis->smoothness, MAX_SMOOTHNESS);
293 /*
294 * There's no point in trying to achieve smoothness beyond what
295 * the device can implement, i.e., the number of representable
296 * colors times the number of halftone levels.
297 */
298 long num_colors =
299 max(dev->color_info.max_gray, dev->color_info.max_color) + 1;
300 const gs_range *ranges = 0;
301 int ci;
302
303 pfs->dev = dev;
304 pfs->pis = pis;
305 top:
306 pfs->direct_space = pcs;
307 pfs->num_components = gs_color_space_num_components(pcs);
308 switch ( gs_color_space_get_index(pcs) )
309 {
310 case gs_color_space_index_Indexed:
311 pcs = gs_cspace_base_space(pcs);
312 goto top;
313 case gs_color_space_index_CIEDEFG:
314 ranges = pcs->params.defg->RangeDEFG.ranges;
315 break;
316 case gs_color_space_index_CIEDEF:
317 ranges = pcs->params.def->RangeDEF.ranges;
318 break;
319 case gs_color_space_index_CIEABC:
320 ranges = pcs->params.abc->RangeABC.ranges;
321 break;
322 case gs_color_space_index_CIEA:
323 ranges = &pcs->params.a->RangeA;
324 break;
325 case gs_color_space_index_CIEICC:
326 ranges = pcs->params.icc.picc_info->Range.ranges;
327 default:
328 break;
329 }
330 if (num_colors <= 32) {
331 gx_ht_order_component *components = pis->dev_ht->components;
332 if (components && components[0].corder.wts)
333 num_colors = 256;
334 else
335 /****** WRONG FOR MULTI-PLANE HALFTONES ******/
336 num_colors *= pis->dev_ht->components[0].corder.num_levels;
337 }
338 if (psh->head.type == 2 || psh->head.type == 3) {
339 max_error *= 0.25;
340 num_colors *= 2;
341 }
342 if (max_error < 1.0 / num_colors)
343 max_error = 1.0 / num_colors;
344 for (ci = 0; ci < pfs->num_components; ++ci)
345 pfs->cc_max_error[ci] =
346 (ranges == 0 ? max_error :
347 max_error * (ranges[ci].rmax - ranges[ci].rmin));
348 }
349
350 /* Fill one piece of a shading. */
351 int
shade_fill_path(const shading_fill_state_t * pfs,gx_path * ppath,gx_device_color * pdevc,const gs_fixed_point * fill_adjust)352 shade_fill_path(const shading_fill_state_t * pfs, gx_path * ppath,
353 gx_device_color * pdevc, const gs_fixed_point *fill_adjust)
354 {
355 gx_fill_params params;
356
357 params.rule = -1; /* irrelevant */
358 params.adjust = *fill_adjust;
359 params.flatness = 0; /* irrelevant */
360 params.fill_zero_width = false;
361 return (*dev_proc(pfs->dev, fill_path)) (pfs->dev, pfs->pis, ppath,
362 ¶ms, pdevc, NULL);
363 }
364