Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 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
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
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
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
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
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
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
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
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
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
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
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
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
					     &params, pdevc, NULL);
363
}