1.1.10
by Till Kamppeter
Import upstream version 8.64.dfsg.1~svn9377 |
1 |
/* Copyright (C) 2001-2006 Artifex Software, Inc.
|
2 |
All Rights Reserved.
|
|
1.1.23
by Till Kamppeter
Import upstream version 9.04~dfsg~20110715 |
3 |
|
1.1.10
by Till Kamppeter
Import upstream version 8.64.dfsg.1~svn9377 |
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, modified
|
|
8 |
or distributed except as expressly authorized under the terms of that
|
|
9 |
license. Refer to licensing information at http://www.artifex.com/
|
|
10 |
or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134,
|
|
11 |
San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information.
|
|
12 |
*/
|
|
13 |
||
1.1.23
by Till Kamppeter
Import upstream version 9.04~dfsg~20110715 |
14 |
/* $Id$ */
|
1.1.10
by Till Kamppeter
Import upstream version 8.64.dfsg.1~svn9377 |
15 |
/* Command list reading for Ghostscript. */
|
16 |
#include "memory_.h" |
|
17 |
#include "gx.h" |
|
18 |
#include "gp.h" /* for gp_fmode_rb */ |
|
19 |
#include "gpcheck.h" |
|
20 |
#include "gserrors.h" |
|
21 |
#include "gxdevice.h" |
|
22 |
#include "gscoord.h" /* requires gsmatrix.h */ |
|
23 |
#include "gsdevice.h" /* for gs_deviceinitialmatrix */ |
|
24 |
#include "gxdevmem.h" /* must precede gxcldev.h */ |
|
25 |
#include "gxcldev.h" |
|
26 |
#include "gxgetbit.h" |
|
27 |
#include "gxhttile.h" |
|
28 |
#include "gdevplnx.h" |
|
29 |
#include "gsmemory.h" |
|
1.1.23
by Till Kamppeter
Import upstream version 9.04~dfsg~20110715 |
30 |
#include "gsmemlok.h" |
1.1.10
by Till Kamppeter
Import upstream version 8.64.dfsg.1~svn9377 |
31 |
#include "vdtrace.h" |
1.4.1
by Jonas Smedegaard
Import upstream version 9.00~dfsg |
32 |
#include "gsicc_cache.h" |
1.1.10
by Till Kamppeter
Import upstream version 8.64.dfsg.1~svn9377 |
33 |
/*
|
34 |
* We really don't like the fact that gdevprn.h is included here, since
|
|
35 |
* command lists are supposed to be usable for purposes other than printer
|
|
36 |
* devices; but gdev_prn_colors_used and gdev_create_buf_device are
|
|
37 |
* currently only applicable to printer devices.
|
|
38 |
*/
|
|
39 |
#include "gdevprn.h" |
|
40 |
#include "stream.h" |
|
41 |
#include "strimpl.h" |
|
42 |
||
43 |
/* forward decl */
|
|
44 |
static int gx_clist_reader_read_band_complexity(gx_device_clist *dev); |
|
1.4.1
by Jonas Smedegaard
Import upstream version 9.00~dfsg |
45 |
private_st_clist_icctable_entry(); |
46 |
private_st_clist_icctable(); |
|
1.1.10
by Till Kamppeter
Import upstream version 8.64.dfsg.1~svn9377 |
47 |
|
48 |
/* ------ Band file reading stream ------ */
|
|
49 |
||
50 |
#ifdef DEBUG
|
|
51 |
/* An auxiliary table for mapping clist buffer offsets to cfile offsets. */
|
|
52 |
typedef struct { |
|
53 |
uint buffered; |
|
54 |
int64_t file_offset; |
|
55 |
} cbuf_offset_map_elem; |
|
56 |
#endif
|
|
57 |
||
58 |
/*
|
|
59 |
* To separate banding per se from command list interpretation,
|
|
60 |
* we make the command list interpreter simply read from a stream.
|
|
61 |
* When we are actually doing banding, the stream filters the band file
|
|
62 |
* and only passes through the commands for the current bands (or band
|
|
63 |
* ranges that include a current band).
|
|
64 |
*/
|
|
65 |
typedef struct stream_band_read_state_s { |
|
66 |
stream_state_common; |
|
67 |
gx_band_page_info_t page_info; |
|
68 |
int band_first, band_last; |
|
69 |
uint left; /* amount of data left in this run */ |
|
70 |
cmd_block b_this; |
|
71 |
#ifdef DEBUG
|
|
72 |
bool skip_first; |
|
73 |
cbuf_offset_map_elem *offset_map; |
|
74 |
int offset_map_length; |
|
75 |
int offset_map_max_length; |
|
76 |
#endif
|
|
77 |
} stream_band_read_state; |
|
78 |
||
79 |
static int |
|
80 |
s_band_read_init(stream_state * st) |
|
81 |
{
|
|
82 |
stream_band_read_state *const ss = (stream_band_read_state *) st; |
|
83 |
const clist_io_procs_t *io_procs = ss->page_info.io_procs; |
|
84 |
||
85 |
ss->left = 0; |
|
86 |
ss->b_this.band_min = 0; |
|
87 |
ss->b_this.band_max = 0; |
|
88 |
ss->b_this.pos = 0; |
|
89 |
io_procs->rewind(ss->page_bfile, false, ss->page_bfname); |
|
90 |
return 0; |
|
91 |
}
|
|
92 |
||
93 |
#ifdef DEBUG
|
|
94 |
static int |
|
95 |
s_band_read_init_offset_map(gx_device_clist_reader *crdev, stream_state * st) |
|
96 |
{
|
|
97 |
stream_band_read_state *const ss = (stream_band_read_state *) st; |
|
98 |
||
99 |
if (gs_debug_c('L')) { |
|
1.1.23
by Till Kamppeter
Import upstream version 9.04~dfsg~20110715 |
100 |
ss->offset_map_length = 0; |
101 |
ss->offset_map_max_length = cbuf_size + 1; /* fixme: Wanted a more accurate implementation. */ |
|
102 |
ss->offset_map = (cbuf_offset_map_elem *)gs_alloc_byte_array(crdev->memory, |
|
103 |
ss->offset_map_max_length, sizeof(*ss->offset_map), "s_band_read_init_offset_map"); |
|
104 |
if (ss->offset_map == NULL) |
|
105 |
return_error(gs_error_VMerror); |
|
106 |
ss->offset_map[0].buffered = 0; |
|
107 |
crdev->offset_map = ss->offset_map; /* Prevent collecting it as garbage. |
|
108 |
Debugged with ppmraw -r300 014-09.ps . */
|
|
1.1.10
by Till Kamppeter
Import upstream version 8.64.dfsg.1~svn9377 |
109 |
} else { |
1.1.23
by Till Kamppeter
Import upstream version 9.04~dfsg~20110715 |
110 |
ss->offset_map_length = 0; |
111 |
ss->offset_map_max_length = 0; |
|
112 |
ss->offset_map = NULL; |
|
113 |
crdev->offset_map = NULL; |
|
1.1.10
by Till Kamppeter
Import upstream version 8.64.dfsg.1~svn9377 |
114 |
}
|
115 |
ss->skip_first = true; |
|
116 |
return 0; |
|
117 |
}
|
|
118 |
||
119 |
static void |
|
120 |
s_band_read_dnit_offset_map(gx_device_clist_reader *crdev, stream_state * st) |
|
121 |
{
|
|
122 |
if (gs_debug_c('L')) { |
|
1.1.23
by Till Kamppeter
Import upstream version 9.04~dfsg~20110715 |
123 |
stream_band_read_state *const ss = (stream_band_read_state *) st; |
1.1.10
by Till Kamppeter
Import upstream version 8.64.dfsg.1~svn9377 |
124 |
|
1.1.23
by Till Kamppeter
Import upstream version 9.04~dfsg~20110715 |
125 |
gs_free_object(crdev->memory, ss->offset_map, "s_band_read_dnit_offset_map"); |
126 |
crdev->offset_map = 0; |
|
1.1.10
by Till Kamppeter
Import upstream version 8.64.dfsg.1~svn9377 |
127 |
}
|
128 |
}
|
|
129 |
#endif
|
|
130 |
||
131 |
static int |
|
132 |
s_band_read_process(stream_state * st, stream_cursor_read * ignore_pr, |
|
1.1.23
by Till Kamppeter
Import upstream version 9.04~dfsg~20110715 |
133 |
stream_cursor_write * pw, bool last) |
1.1.10
by Till Kamppeter
Import upstream version 8.64.dfsg.1~svn9377 |
134 |
{
|
135 |
stream_band_read_state *const ss = (stream_band_read_state *) st; |
|
136 |
register byte *q = pw->ptr; |
|
137 |
byte *wlimit = pw->limit; |
|
138 |
clist_file_ptr cfile = ss->page_cfile; |
|
139 |
clist_file_ptr bfile = ss->page_bfile; |
|
140 |
uint left = ss->left; |
|
141 |
int status = 1; |
|
142 |
uint count; |
|
143 |
const clist_io_procs_t *io_procs = ss->page_info.io_procs; |
|
144 |
||
145 |
while ((count = wlimit - q) != 0) { |
|
1.1.23
by Till Kamppeter
Import upstream version 9.04~dfsg~20110715 |
146 |
if (left) { /* Read more data for the current run. */ |
147 |
if (count > left) |
|
148 |
count = left; |
|
1.1.10
by Till Kamppeter
Import upstream version 8.64.dfsg.1~svn9377 |
149 |
# ifdef DEBUG
|
1.1.23
by Till Kamppeter
Import upstream version 9.04~dfsg~20110715 |
150 |
if (gs_debug_c('L')) |
151 |
ss->offset_map[ss->offset_map_length - 1].buffered += count; |
|
1.1.10
by Till Kamppeter
Import upstream version 8.64.dfsg.1~svn9377 |
152 |
# endif
|
1.1.23
by Till Kamppeter
Import upstream version 9.04~dfsg~20110715 |
153 |
io_procs->fread_chars(q + 1, count, cfile); |
154 |
if (io_procs->ferror_code(cfile) < 0) { |
|
155 |
status = ERRC; |
|
156 |
break; |
|
157 |
}
|
|
158 |
q += count; |
|
159 |
left -= count; |
|
160 |
process_interrupts(st->memory); |
|
161 |
continue; |
|
162 |
}
|
|
1.1.10
by Till Kamppeter
Import upstream version 8.64.dfsg.1~svn9377 |
163 |
rb: |
1.1.23
by Till Kamppeter
Import upstream version 9.04~dfsg~20110715 |
164 |
/*
|
165 |
* Scan for the next run for the current bands (or a band range
|
|
166 |
* that includes a current band).
|
|
167 |
*/
|
|
168 |
if (ss->b_this.band_min == cmd_band_end && |
|
169 |
io_procs->ftell(bfile) == ss->page_bfile_end_pos |
|
170 |
) { |
|
171 |
status = EOFC; |
|
172 |
break; |
|
173 |
} { |
|
174 |
int bmin = ss->b_this.band_min; |
|
175 |
int bmax = ss->b_this.band_max; |
|
176 |
int64_t pos = ss->b_this.pos; |
|
177 |
int nread; |
|
1.1.10
by Till Kamppeter
Import upstream version 8.64.dfsg.1~svn9377 |
178 |
|
1.1.23
by Till Kamppeter
Import upstream version 9.04~dfsg~20110715 |
179 |
nread = io_procs->fread_chars(&ss->b_this, sizeof(ss->b_this), bfile); |
180 |
if (nread < sizeof(ss->b_this)) { |
|
181 |
DISCARD(gs_note_error(gs_error_unregistered)); /* Must not happen. */ |
|
182 |
return ERRC; |
|
183 |
}
|
|
184 |
if (!(ss->band_last >= bmin && ss->band_first <= bmax)) |
|
185 |
goto rb; |
|
186 |
io_procs->fseek(cfile, pos, SEEK_SET, ss->page_cfname); |
|
187 |
left = (uint) (ss->b_this.pos - pos); |
|
1.1.10
by Till Kamppeter
Import upstream version 8.64.dfsg.1~svn9377 |
188 |
# ifdef DEBUG
|
1.1.23
by Till Kamppeter
Import upstream version 9.04~dfsg~20110715 |
189 |
if (left > 0 && gs_debug_c('L')) { |
190 |
if (ss->offset_map_length >= ss->offset_map_max_length) { |
|
191 |
DISCARD(gs_note_error(gs_error_unregistered)); /* Must not happen. */ |
|
192 |
return ERRC; |
|
193 |
}
|
|
194 |
ss->offset_map[ss->offset_map_length].file_offset = pos; |
|
195 |
ss->offset_map[ss->offset_map_length].buffered = 0; |
|
196 |
ss->offset_map_length++; |
|
197 |
}
|
|
1.1.10
by Till Kamppeter
Import upstream version 8.64.dfsg.1~svn9377 |
198 |
# endif
|
1.1.23
by Till Kamppeter
Import upstream version 9.04~dfsg~20110715 |
199 |
if_debug7('l', |
200 |
"[l]reading for bands (%d,%d) at bfile %ld, cfile %ld, length %u color %d rop %d\n", |
|
201 |
bmin, bmax, |
|
202 |
(long)(io_procs->ftell(bfile) - sizeof(ss->b_this)), /* stefan foo was: 2 * sizeof ?? */ |
|
203 |
(long)pos, left, ss->b_this.band_complexity.uses_color, |
|
204 |
ss->b_this.band_complexity.nontrivial_rops); |
|
205 |
}
|
|
1.1.10
by Till Kamppeter
Import upstream version 8.64.dfsg.1~svn9377 |
206 |
}
|
207 |
pw->ptr = q; |
|
208 |
ss->left = left; |
|
209 |
return status; |
|
210 |
}
|
|
211 |
||
212 |
/* Stream template */
|
|
213 |
static const stream_template s_band_read_template = { |
|
214 |
&st_stream_state, s_band_read_init, s_band_read_process, 1, cbuf_size |
|
215 |
};
|
|
216 |
||
217 |
#ifdef DEBUG
|
|
218 |
static int |
|
219 |
buffer_segment_index(const stream_band_read_state *ss, uint buffer_offset, uint *poffset0) |
|
220 |
{
|
|
221 |
uint i, offset0, offset = 0; |
|
222 |
||
223 |
for (i = 0; i < ss->offset_map_length; i++) { |
|
1.1.23
by Till Kamppeter
Import upstream version 9.04~dfsg~20110715 |
224 |
offset0 = offset; |
225 |
offset += ss->offset_map[i].buffered; |
|
226 |
if (buffer_offset < offset) { |
|
227 |
*poffset0 = offset0; |
|
228 |
return i; |
|
229 |
}
|
|
1.1.10
by Till Kamppeter
Import upstream version 8.64.dfsg.1~svn9377 |
230 |
}
|
231 |
gs_note_error(gs_error_unregistered); /* Must not happen. */ |
|
232 |
return -1; |
|
233 |
}
|
|
234 |
||
235 |
int64_t
|
|
236 |
clist_file_offset(const stream_state * st, uint buffer_offset) |
|
237 |
{
|
|
238 |
const stream_band_read_state *ss = (const stream_band_read_state *) st; |
|
239 |
uint offset0; |
|
240 |
int i = buffer_segment_index(ss, buffer_offset, &offset0); |
|
241 |
||
242 |
if (i < 0) |
|
1.1.23
by Till Kamppeter
Import upstream version 9.04~dfsg~20110715 |
243 |
return -1; |
1.1.10
by Till Kamppeter
Import upstream version 8.64.dfsg.1~svn9377 |
244 |
return ss->offset_map[i].file_offset + (uint)(buffer_offset - offset0); |
245 |
}
|
|
246 |
||
247 |
int
|
|
248 |
top_up_offset_map(stream_state * st, const byte *buf, const byte *ptr, const byte *end) |
|
249 |
{
|
|
1.1.23
by Till Kamppeter
Import upstream version 9.04~dfsg~20110715 |
250 |
/* NOTE: The clist data are buffered in the clist reader buffer and in the
|
1.1.10
by Till Kamppeter
Import upstream version 8.64.dfsg.1~svn9377 |
251 |
internal buffer of the clist stream. Since the 1st buffer is not accessible
|
252 |
from s_band_read_process, offset_map corresponds the union of the 2 buffers.
|
|
253 |
*/
|
|
254 |
stream_band_read_state *const ss = (stream_band_read_state *) st; |
|
255 |
||
256 |
if (!gs_debug_c('L')) { |
|
1.1.23
by Till Kamppeter
Import upstream version 9.04~dfsg~20110715 |
257 |
return 0; |
1.1.10
by Till Kamppeter
Import upstream version 8.64.dfsg.1~svn9377 |
258 |
} else if (ss->skip_first) { |
1.1.23
by Till Kamppeter
Import upstream version 9.04~dfsg~20110715 |
259 |
/* Work around the trick with initializing the buffer pointer with the buffer end. */
|
260 |
ss->skip_first = false; |
|
261 |
return 0; |
|
1.1.10
by Till Kamppeter
Import upstream version 8.64.dfsg.1~svn9377 |
262 |
} else if (ptr == buf) |
1.1.23
by Till Kamppeter
Import upstream version 9.04~dfsg~20110715 |
263 |
return 0; |
1.1.10
by Till Kamppeter
Import upstream version 8.64.dfsg.1~svn9377 |
264 |
else { |
1.1.23
by Till Kamppeter
Import upstream version 9.04~dfsg~20110715 |
265 |
uint buffer_offset = ptr - buf; |
266 |
uint offset0, consumed; |
|
267 |
int i = buffer_segment_index(ss, buffer_offset, &offset0); |
|
268 |
||
269 |
if (i < 0) |
|
270 |
return_error(gs_error_unregistered); /* Must not happen. */ |
|
271 |
consumed = buffer_offset - offset0; |
|
272 |
ss->offset_map[i].buffered -= consumed; |
|
273 |
ss->offset_map[i].file_offset += consumed; |
|
274 |
if (i) { |
|
275 |
memmove(ss->offset_map, ss->offset_map + i, |
|
276 |
(ss->offset_map_length - i) * sizeof(*ss->offset_map)); |
|
277 |
ss->offset_map_length -= i; |
|
278 |
}
|
|
1.1.10
by Till Kamppeter
Import upstream version 8.64.dfsg.1~svn9377 |
279 |
}
|
280 |
return 0; |
|
281 |
}
|
|
282 |
#endif /* DEBUG */ |
|
283 |
||
284 |
/* ------ Reading/rendering ------ */
|
|
285 |
||
286 |
/* Calculate the raster for a chunky or planar device. */
|
|
287 |
static int |
|
288 |
clist_plane_raster(const gx_device *dev, const gx_render_plane_t *render_plane) |
|
289 |
{
|
|
290 |
return bitmap_raster(dev->width * |
|
1.1.23
by Till Kamppeter
Import upstream version 9.04~dfsg~20110715 |
291 |
(render_plane && render_plane->index >= 0 ? |
292 |
render_plane->depth : dev->color_info.depth)); |
|
1.1.10
by Till Kamppeter
Import upstream version 8.64.dfsg.1~svn9377 |
293 |
}
|
294 |
||
295 |
/* Select full-pixel rendering if required for RasterOp. */
|
|
296 |
void
|
|
297 |
clist_select_render_plane(gx_device *dev, int y, int height, |
|
1.1.23
by Till Kamppeter
Import upstream version 9.04~dfsg~20110715 |
298 |
gx_render_plane_t *render_plane, int index) |
1.1.10
by Till Kamppeter
Import upstream version 8.64.dfsg.1~svn9377 |
299 |
{
|
300 |
if (index >= 0) { |
|
1.1.23
by Till Kamppeter
Import upstream version 9.04~dfsg~20110715 |
301 |
gx_colors_used_t colors_used; |
302 |
int ignore_start; |
|
1.1.10
by Till Kamppeter
Import upstream version 8.64.dfsg.1~svn9377 |
303 |
|
1.1.23
by Till Kamppeter
Import upstream version 9.04~dfsg~20110715 |
304 |
gdev_prn_colors_used(dev, y, height, &colors_used, &ignore_start); |
305 |
if (colors_used.slow_rop) |
|
306 |
index = -1; |
|
1.1.10
by Till Kamppeter
Import upstream version 8.64.dfsg.1~svn9377 |
307 |
}
|
308 |
if (index < 0) |
|
1.1.23
by Till Kamppeter
Import upstream version 9.04~dfsg~20110715 |
309 |
render_plane->index = index; |
1.1.10
by Till Kamppeter
Import upstream version 8.64.dfsg.1~svn9377 |
310 |
else
|
1.1.23
by Till Kamppeter
Import upstream version 9.04~dfsg~20110715 |
311 |
gx_render_plane_init(render_plane, dev, index); |
1.1.10
by Till Kamppeter
Import upstream version 8.64.dfsg.1~svn9377 |
312 |
}
|
313 |
||
314 |
/*
|
|
315 |
* Do device setup from params stored in command list. This is only for
|
|
316 |
* async rendering & assumes that the first command in every command list
|
|
317 |
* is a put_params command which sets all space-related parameters to the
|
|
318 |
* value they will have for the duration of that command list.
|
|
319 |
*/
|
|
320 |
int
|
|
321 |
clist_setup_params(gx_device *dev) |
|
322 |
{
|
|
323 |
gx_device_clist *cldev = (gx_device_clist *)dev; |
|
324 |
gx_device_clist_reader * const crdev = &cldev->reader; |
|
325 |
int code = clist_render_init(cldev); |
|
326 |
||
327 |
if (code < 0) |
|
1.1.23
by Till Kamppeter
Import upstream version 9.04~dfsg~20110715 |
328 |
return code; |
1.1.10
by Till Kamppeter
Import upstream version 8.64.dfsg.1~svn9377 |
329 |
|
330 |
code = clist_playback_file_bands(playback_action_setup, |
|
1.1.23
by Till Kamppeter
Import upstream version 9.04~dfsg~20110715 |
331 |
crdev, &crdev->page_info, 0, 0, 0, 0, 0); |
1.1.10
by Till Kamppeter
Import upstream version 8.64.dfsg.1~svn9377 |
332 |
|
333 |
/* put_params may have reinitialized device into a writer */
|
|
334 |
clist_render_init(cldev); |
|
335 |
||
336 |
return code; |
|
337 |
}
|
|
338 |
||
1.1.23
by Till Kamppeter
Import upstream version 9.04~dfsg~20110715 |
339 |
int
|
1.1.10
by Till Kamppeter
Import upstream version 8.64.dfsg.1~svn9377 |
340 |
clist_close_writer_and_init_reader(gx_device_clist *cldev) |
341 |
{
|
|
342 |
gx_device_clist_reader * const crdev = &cldev->reader; |
|
1.1.23
by Till Kamppeter
Import upstream version 9.04~dfsg~20110715 |
343 |
gs_memory_t *base_mem = crdev->memory->thread_safe_memory; |
344 |
gs_memory_status_t mem_status; |
|
1.1.10
by Till Kamppeter
Import upstream version 8.64.dfsg.1~svn9377 |
345 |
int code = 0; |
346 |
||
347 |
/* Initialize for rendering if we haven't done so yet. */
|
|
348 |
if (crdev->ymin < 0) { |
|
1.1.23
by Till Kamppeter
Import upstream version 9.04~dfsg~20110715 |
349 |
code = clist_end_page(&cldev->writer); |
350 |
if (code < 0) |
|
351 |
return code; |
|
352 |
code = clist_render_init(cldev); |
|
353 |
if (code < 0) |
|
354 |
return code; |
|
1.4.1
by Jonas Smedegaard
Import upstream version 9.00~dfsg |
355 |
/* Check for and get ICC profile table */
|
356 |
code = clist_read_icctable(crdev); |
|
1.1.23
by Till Kamppeter
Import upstream version 9.04~dfsg~20110715 |
357 |
if (code < 0) |
358 |
return code; |
|
1.4.1
by Jonas Smedegaard
Import upstream version 9.00~dfsg |
359 |
/* Allocate the icc cache for the clist reader */
|
1.1.23
by Till Kamppeter
Import upstream version 9.04~dfsg~20110715 |
360 |
/* Since we may be rendering in multiple threads, make sure the memory */
|
361 |
/* is thread safe by using a known thread_safe memory allocator */
|
|
362 |
gs_memory_status(base_mem, &mem_status); |
|
363 |
if (mem_status.is_thread_safe == false) { |
|
364 |
return_error(gs_error_VMerror); |
|
365 |
}
|
|
366 |
||
367 |
code = (crdev->icc_cache_cl = gsicc_cache_new(base_mem)) == NULL ? gs_error_VMerror : code; |
|
1.1.10
by Till Kamppeter
Import upstream version 8.64.dfsg.1~svn9377 |
368 |
}
|
369 |
return code; |
|
370 |
}
|
|
371 |
||
1.4.1
by Jonas Smedegaard
Import upstream version 9.00~dfsg |
372 |
/* Used to find the command block information in the bfile
|
373 |
that is related to extra information stored in a psuedo band.
|
|
374 |
Currently application of this is storage of the ICC profile
|
|
375 |
table. We may eventually use this for storing other information
|
|
376 |
like compressed images. */
|
|
377 |
||
378 |
static int |
|
379 |
clist_find_pseudoband(gx_device_clist_reader *crdev, int band, cmd_block *cb) |
|
380 |
{
|
|
381 |
||
382 |
clist_file_ptr bfile = crdev->page_info.bfile; |
|
383 |
int64_t save_pos = crdev->page_info.bfile_end_pos; |
|
384 |
int64_t start_pos; |
|
385 |
||
386 |
/* Go to the start of the last command block */
|
|
387 |
start_pos = crdev->page_info.bfile_end_pos - sizeof(cmd_block); |
|
388 |
crdev->page_info.io_procs->fseek(bfile, start_pos, SEEK_SET, crdev->page_info.bfname); |
|
389 |
while( 1 ) { |
|
390 |
crdev->page_info.io_procs->fread_chars(cb, sizeof(cmd_block), bfile); |
|
391 |
if (cb->band_max == band && cb->band_min == band) { |
|
392 |
crdev->page_info.io_procs->fseek(bfile, save_pos, SEEK_SET, crdev->page_info.bfname); |
|
393 |
return(0); /* Found it */ |
|
1.1.23
by Till Kamppeter
Import upstream version 9.04~dfsg~20110715 |
394 |
}
|
1.4.1
by Jonas Smedegaard
Import upstream version 9.00~dfsg |
395 |
start_pos -= sizeof(cmd_block); |
396 |
if (start_pos < 0) { |
|
397 |
crdev->page_info.io_procs->fseek(bfile, save_pos, SEEK_SET, crdev->page_info.bfname); |
|
398 |
return(-1); /* Did not find it before getting into other stuff in normal bands */ |
|
399 |
}
|
|
400 |
crdev->page_info.io_procs->fseek(bfile, start_pos, SEEK_SET, crdev->page_info.bfname); |
|
401 |
}
|
|
402 |
}
|
|
403 |
||
404 |
/* A procedure to read a chunk of data from the cfile at a particular location into buff */
|
|
405 |
int
|
|
406 |
clist_read_chunk(gx_device_clist_reader *crdev, int64_t position, int size, unsigned char *buf) |
|
407 |
{
|
|
408 |
clist_file_ptr cfile = crdev->page_info.cfile; |
|
409 |
int64_t save_pos; |
|
410 |
||
411 |
/* Save our current location */
|
|
412 |
save_pos = crdev->page_info.io_procs->ftell(cfile); |
|
413 |
/* Go to our new position */
|
|
414 |
crdev->page_info.io_procs->fseek(cfile, position, SEEK_SET, crdev->page_info.cfname); |
|
415 |
/* Get the data */
|
|
416 |
crdev->page_info.io_procs->fread_chars(buf, size, cfile); |
|
417 |
/* Restore our position */
|
|
418 |
crdev->page_info.io_procs->fseek(cfile, save_pos, SEEK_SET, crdev->page_info.cfname); |
|
419 |
return(0); |
|
420 |
}
|
|
421 |
||
422 |
/* Unserialize the icc table information stored in the cfile and
|
|
423 |
place it in the reader device */
|
|
424 |
static int |
|
425 |
clist_unserialize_icctable(gx_device_clist_reader *crdev, cmd_block *cb) |
|
426 |
{
|
|
427 |
clist_file_ptr cfile = crdev->page_info.cfile; |
|
428 |
clist_icctable_t *icc_table = crdev->icc_table; |
|
429 |
int64_t save_pos; |
|
430 |
int number_entries, size_data; |
|
1.1.23
by Till Kamppeter
Import upstream version 9.04~dfsg~20110715 |
431 |
unsigned char *buf, *buf_start; |
1.4.1
by Jonas Smedegaard
Import upstream version 9.00~dfsg |
432 |
clist_icctable_entry_t *curr_entry; |
433 |
int k; |
|
434 |
||
1.1.23
by Till Kamppeter
Import upstream version 9.04~dfsg~20110715 |
435 |
if ( icc_table != NULL ) |
1.4.1
by Jonas Smedegaard
Import upstream version 9.00~dfsg |
436 |
return(0); |
437 |
save_pos = crdev->page_info.io_procs->ftell(cfile); |
|
438 |
crdev->page_info.io_procs->fseek(cfile, cb->pos, SEEK_SET, crdev->page_info.cfname); |
|
439 |
/* First four bytes tell us the number of entries. */
|
|
440 |
crdev->page_info.io_procs->fread_chars(&number_entries, sizeof(number_entries), cfile); |
|
441 |
/* Allocate the space */
|
|
442 |
size_data = number_entries*sizeof(clist_icc_serial_entry_t); |
|
443 |
buf = gs_alloc_bytes(crdev->memory, size_data, "clist_read_icctable"); |
|
1.1.23
by Till Kamppeter
Import upstream version 9.04~dfsg~20110715 |
444 |
buf_start = buf; |
1.4.1
by Jonas Smedegaard
Import upstream version 9.00~dfsg |
445 |
if (buf == NULL) |
446 |
return gs_rethrow(-1, "insufficient memory for icc table buffer reader"); |
|
447 |
/* Get the data */
|
|
448 |
clist_read_chunk(crdev, cb->pos + 4, size_data, buf); |
|
1.1.23
by Till Kamppeter
Import upstream version 9.04~dfsg~20110715 |
449 |
icc_table = gs_alloc_struct(crdev->memory, |
450 |
clist_icctable_t, |
|
451 |
&st_clist_icctable, "clist_read_icctable"); |
|
452 |
if (icc_table == NULL) { |
|
453 |
gs_free_object(crdev->memory, buf_start, "clist_read_icctable"); |
|
1.4.1
by Jonas Smedegaard
Import upstream version 9.00~dfsg |
454 |
return gs_rethrow(-1, "insufficient memory for icc table buffer reader"); |
1.1.23
by Till Kamppeter
Import upstream version 9.04~dfsg~20110715 |
455 |
}
|
1.4.1
by Jonas Smedegaard
Import upstream version 9.00~dfsg |
456 |
icc_table->head = NULL; |
457 |
icc_table->final = NULL; |
|
458 |
/* Allocate and fill each entry */
|
|
459 |
icc_table->tablesize = number_entries; |
|
460 |
crdev->icc_table = icc_table; |
|
461 |
for (k = 0; k < number_entries; k++) { |
|
1.1.23
by Till Kamppeter
Import upstream version 9.04~dfsg~20110715 |
462 |
curr_entry = gs_alloc_struct(crdev->memory, |
463 |
clist_icctable_entry_t, |
|
464 |
&st_clist_icctable_entry, "clist_read_icctable"); |
|
465 |
if (curr_entry == NULL) { |
|
466 |
gs_free_object(crdev->memory, buf_start, "clist_read_icctable"); |
|
1.4.1
by Jonas Smedegaard
Import upstream version 9.00~dfsg |
467 |
return gs_rethrow(-1, "insufficient memory for icc table entry"); |
1.1.23
by Till Kamppeter
Import upstream version 9.04~dfsg~20110715 |
468 |
}
|
1.4.1
by Jonas Smedegaard
Import upstream version 9.00~dfsg |
469 |
memcpy(&(curr_entry->serial_data), buf, sizeof(clist_icc_serial_entry_t)); |
470 |
buf += sizeof(clist_icc_serial_entry_t); |
|
471 |
curr_entry->icc_profile = NULL; |
|
472 |
if ( icc_table->head == NULL ) { |
|
473 |
icc_table->head = curr_entry; |
|
474 |
icc_table->final = curr_entry; |
|
475 |
} else { |
|
476 |
icc_table->final->next = curr_entry; |
|
477 |
icc_table->final = curr_entry; |
|
478 |
}
|
|
479 |
curr_entry->next = NULL; |
|
480 |
}
|
|
1.1.23
by Till Kamppeter
Import upstream version 9.04~dfsg~20110715 |
481 |
gs_free_object(crdev->memory, buf_start, "clist_read_icctable"); |
1.4.1
by Jonas Smedegaard
Import upstream version 9.00~dfsg |
482 |
crdev->page_info.io_procs->fseek(cfile, save_pos, SEEK_SET, crdev->page_info.cfname); |
483 |
return(0); |
|
484 |
}
|
|
485 |
||
486 |
/* Get the ICC profile table information from the clist */
|
|
487 |
int
|
|
488 |
clist_read_icctable(gx_device_clist_reader *crdev) |
|
489 |
{
|
|
490 |
/* Look for the command block of the ICC Profile. */
|
|
491 |
cmd_block cb; |
|
492 |
int code; |
|
493 |
||
1.1.23
by Till Kamppeter
Import upstream version 9.04~dfsg~20110715 |
494 |
/* First get the command block which will tell us where the
|
1.4.1
by Jonas Smedegaard
Import upstream version 9.00~dfsg |
495 |
information is stored in the cfile */
|
496 |
code = clist_find_pseudoband(crdev, crdev->nbands + ICC_BAND_OFFSET - 1, &cb); |
|
497 |
if (code < 0) |
|
498 |
return(0); /* No ICC information */ |
|
499 |
/* Unserialize the icc_table from the cfile */
|
|
500 |
code = clist_unserialize_icctable(crdev, &cb); |
|
501 |
return(code); |
|
502 |
}
|
|
503 |
||
1.1.10
by Till Kamppeter
Import upstream version 8.64.dfsg.1~svn9377 |
504 |
/* Initialize for reading. */
|
505 |
int
|
|
506 |
clist_render_init(gx_device_clist *dev) |
|
507 |
{
|
|
508 |
gx_device_clist_reader * const crdev = &dev->reader; |
|
1.4.1
by Jonas Smedegaard
Import upstream version 9.00~dfsg |
509 |
int code; |
1.1.10
by Till Kamppeter
Import upstream version 8.64.dfsg.1~svn9377 |
510 |
|
511 |
crdev->ymin = crdev->ymax = 0; |
|
512 |
crdev->yplane.index = -1; |
|
513 |
/* For normal rasterizing, pages and num_pages are zero. */
|
|
514 |
crdev->pages = 0; |
|
515 |
crdev->num_pages = 0; |
|
516 |
crdev->band_complexity_array = NULL; |
|
517 |
crdev->offset_map = NULL; |
|
1.4.1
by Jonas Smedegaard
Import upstream version 9.00~dfsg |
518 |
crdev->icc_table = NULL; |
519 |
crdev->icc_cache_cl = NULL; |
|
1.1.10
by Till Kamppeter
Import upstream version 8.64.dfsg.1~svn9377 |
520 |
crdev->render_threads = NULL; |
1.4.1
by Jonas Smedegaard
Import upstream version 9.00~dfsg |
521 |
|
522 |
code = gx_clist_reader_read_band_complexity(dev); |
|
523 |
return code; |
|
1.1.10
by Till Kamppeter
Import upstream version 8.64.dfsg.1~svn9377 |
524 |
}
|
525 |
||
526 |
/* Copy a rasterized rectangle to the client, rasterizing if needed. */
|
|
527 |
int
|
|
528 |
clist_get_bits_rectangle(gx_device *dev, const gs_int_rect * prect, |
|
1.1.23
by Till Kamppeter
Import upstream version 9.04~dfsg~20110715 |
529 |
gs_get_bits_params_t *params, gs_int_rect **unread) |
1.1.10
by Till Kamppeter
Import upstream version 8.64.dfsg.1~svn9377 |
530 |
{
|
531 |
gx_device_clist *cldev = (gx_device_clist *)dev; |
|
532 |
gx_device_clist_common *cdev = (gx_device_clist_common *)dev; |
|
533 |
gs_get_bits_options_t options = params->options; |
|
534 |
int y = prect->p.y; |
|
535 |
int end_y = prect->q.y; |
|
536 |
int line_count = end_y - y; |
|
537 |
gs_int_rect band_rect; |
|
538 |
int lines_rasterized; |
|
539 |
gx_device *bdev; |
|
540 |
int num_planes = |
|
1.1.23
by Till Kamppeter
Import upstream version 9.04~dfsg~20110715 |
541 |
(options & GB_PACKING_CHUNKY ? 1 : |
542 |
options & GB_PACKING_PLANAR ? dev->color_info.num_components : |
|
543 |
options & GB_PACKING_BIT_PLANAR ? dev->color_info.depth : |
|
544 |
0 /****** NOT POSSIBLE ******/); |
|
1.1.10
by Till Kamppeter
Import upstream version 8.64.dfsg.1~svn9377 |
545 |
gx_render_plane_t render_plane; |
546 |
int plane_index; |
|
547 |
int my; |
|
548 |
int code; |
|
549 |
||
550 |
if (prect->p.x < 0 || prect->q.x > dev->width || |
|
1.1.23
by Till Kamppeter
Import upstream version 9.04~dfsg~20110715 |
551 |
y < 0 || end_y > dev->height |
552 |
)
|
|
553 |
return_error(gs_error_rangecheck); |
|
1.1.10
by Till Kamppeter
Import upstream version 8.64.dfsg.1~svn9377 |
554 |
if (line_count <= 0 || prect->p.x >= prect->q.x) |
1.1.23
by Till Kamppeter
Import upstream version 9.04~dfsg~20110715 |
555 |
return 0; |
1.1.10
by Till Kamppeter
Import upstream version 8.64.dfsg.1~svn9377 |
556 |
|
557 |
/*
|
|
558 |
* Calculate the render_plane from the params. There are two cases:
|
|
559 |
* full pixels, or a single plane.
|
|
560 |
*/
|
|
561 |
plane_index = -1; |
|
562 |
if (options & GB_SELECT_PLANES) { |
|
1.1.23
by Till Kamppeter
Import upstream version 9.04~dfsg~20110715 |
563 |
/* Look for the one selected plane. */
|
564 |
int i; |
|
1.1.10
by Till Kamppeter
Import upstream version 8.64.dfsg.1~svn9377 |
565 |
|
1.1.23
by Till Kamppeter
Import upstream version 9.04~dfsg~20110715 |
566 |
for (i = 0; i < num_planes; ++i) |
567 |
if (params->data[i]) { |
|
568 |
if (plane_index >= 0) /* >1 plane requested */ |
|
569 |
return gx_default_get_bits_rectangle(dev, prect, params, |
|
570 |
unread); |
|
571 |
plane_index = i; |
|
572 |
}
|
|
1.1.10
by Till Kamppeter
Import upstream version 8.64.dfsg.1~svn9377 |
573 |
}
|
574 |
||
575 |
if (0 > (code = clist_close_writer_and_init_reader(cldev))) |
|
1.1.23
by Till Kamppeter
Import upstream version 9.04~dfsg~20110715 |
576 |
return code; |
1.1.10
by Till Kamppeter
Import upstream version 8.64.dfsg.1~svn9377 |
577 |
|
578 |
clist_select_render_plane(dev, y, line_count, &render_plane, plane_index); |
|
579 |
code = gdev_create_buf_device(cdev->buf_procs.create_buf_device, |
|
1.1.23
by Till Kamppeter
Import upstream version 9.04~dfsg~20110715 |
580 |
&bdev, cdev->target, y, &render_plane, |
581 |
dev->memory, clist_get_band_complexity(dev,y)); |
|
1.1.10
by Till Kamppeter
Import upstream version 8.64.dfsg.1~svn9377 |
582 |
if (code < 0) |
1.1.23
by Till Kamppeter
Import upstream version 9.04~dfsg~20110715 |
583 |
return code; |
1.1.10
by Till Kamppeter
Import upstream version 8.64.dfsg.1~svn9377 |
584 |
code = clist_rasterize_lines(dev, y, line_count, bdev, &render_plane, &my); |
585 |
if (code < 0) |
|
1.1.23
by Till Kamppeter
Import upstream version 9.04~dfsg~20110715 |
586 |
return code; |
1.1.10
by Till Kamppeter
Import upstream version 8.64.dfsg.1~svn9377 |
587 |
lines_rasterized = min(code, line_count); |
588 |
/* Return as much of the rectangle as falls within the rasterized lines. */
|
|
589 |
band_rect = *prect; |
|
590 |
band_rect.p.y = my; |
|
591 |
band_rect.q.y = my + lines_rasterized; |
|
592 |
code = dev_proc(bdev, get_bits_rectangle) |
|
1.1.23
by Till Kamppeter
Import upstream version 9.04~dfsg~20110715 |
593 |
(bdev, &band_rect, params, unread); |
1.1.10
by Till Kamppeter
Import upstream version 8.64.dfsg.1~svn9377 |
594 |
cdev->buf_procs.destroy_buf_device(bdev); |
595 |
if (code < 0 || lines_rasterized == line_count) |
|
1.1.23
by Till Kamppeter
Import upstream version 9.04~dfsg~20110715 |
596 |
return code; |
1.1.10
by Till Kamppeter
Import upstream version 8.64.dfsg.1~svn9377 |
597 |
/*
|
598 |
* We'll have to return the rectangle in pieces. Force GB_RETURN_COPY
|
|
599 |
* rather than GB_RETURN_POINTER, and require all subsequent pieces to
|
|
600 |
* use the same values as the first piece for all of the other format
|
|
601 |
* options. If copying isn't allowed, or if there are any unread
|
|
602 |
* rectangles, punt.
|
|
603 |
*/
|
|
604 |
if (!(options & GB_RETURN_COPY) || code > 0) |
|
1.1.23
by Till Kamppeter
Import upstream version 9.04~dfsg~20110715 |
605 |
return gx_default_get_bits_rectangle(dev, prect, params, unread); |
1.1.10
by Till Kamppeter
Import upstream version 8.64.dfsg.1~svn9377 |
606 |
options = params->options; |
607 |
if (!(options & GB_RETURN_COPY)) { |
|
1.1.23
by Till Kamppeter
Import upstream version 9.04~dfsg~20110715 |
608 |
/* Redo the first piece with copying. */
|
609 |
params->options = options = |
|
610 |
(params->options & ~GB_RETURN_ALL) | GB_RETURN_COPY; |
|
611 |
lines_rasterized = 0; |
|
1.1.10
by Till Kamppeter
Import upstream version 8.64.dfsg.1~svn9377 |
612 |
}
|
613 |
{
|
|
1.1.23
by Till Kamppeter
Import upstream version 9.04~dfsg~20110715 |
614 |
gs_get_bits_params_t band_params; |
615 |
uint raster = gx_device_raster(bdev, true); |
|
616 |
||
617 |
code = gdev_create_buf_device(cdev->buf_procs.create_buf_device, |
|
618 |
&bdev, cdev->target, y, &render_plane, |
|
619 |
dev->memory, clist_get_band_complexity(dev, y)); |
|
620 |
if (code < 0) |
|
621 |
return code; |
|
622 |
band_params = *params; |
|
623 |
while ((y += lines_rasterized) < end_y) { |
|
624 |
int i; |
|
625 |
||
626 |
/* Increment data pointers by lines_rasterized. */
|
|
627 |
for (i = 0; i < num_planes; ++i) |
|
628 |
if (band_params.data[i]) |
|
629 |
band_params.data[i] += raster * lines_rasterized; |
|
630 |
line_count = end_y - y; |
|
631 |
code = clist_rasterize_lines(dev, y, line_count, bdev, |
|
632 |
&render_plane, &my); |
|
633 |
if (code < 0) |
|
634 |
break; |
|
635 |
lines_rasterized = min(code, line_count); |
|
636 |
band_rect.p.y = my; |
|
637 |
band_rect.q.y = my + lines_rasterized; |
|
638 |
code = dev_proc(bdev, get_bits_rectangle) |
|
639 |
(bdev, &band_rect, &band_params, unread); |
|
640 |
if (code < 0) |
|
641 |
break; |
|
642 |
params->options = options = band_params.options; |
|
643 |
if (lines_rasterized == line_count) |
|
644 |
break; |
|
645 |
}
|
|
646 |
cdev->buf_procs.destroy_buf_device(bdev); |
|
1.1.10
by Till Kamppeter
Import upstream version 8.64.dfsg.1~svn9377 |
647 |
}
|
648 |
return code; |
|
649 |
}
|
|
650 |
||
651 |
/* Copy scan lines to the client. This is where rendering gets done. */
|
|
652 |
/* Processes min(requested # lines, # lines available thru end of band) */
|
|
653 |
int /* returns -ve error code, or # scan lines copied */ |
|
654 |
clist_rasterize_lines(gx_device *dev, int y, int line_count, |
|
1.1.23
by Till Kamppeter
Import upstream version 9.04~dfsg~20110715 |
655 |
gx_device *bdev, const gx_render_plane_t *render_plane, |
656 |
int *pmy) |
|
1.1.10
by Till Kamppeter
Import upstream version 8.64.dfsg.1~svn9377 |
657 |
{
|
658 |
gx_device_clist * const cldev = (gx_device_clist *)dev; |
|
659 |
gx_device_clist_reader * const crdev = &cldev->reader; |
|
660 |
gx_device *target = crdev->target; |
|
661 |
uint raster = clist_plane_raster(target, render_plane); |
|
662 |
byte *mdata = crdev->data + crdev->page_tile_cache_size; |
|
663 |
int plane_index = (render_plane ? render_plane->index : -1); |
|
664 |
int code; |
|
665 |
||
666 |
/* Render a band if necessary, and copy it incrementally. */
|
|
667 |
if (crdev->ymin < 0 || crdev->yplane.index != plane_index || |
|
1.1.23
by Till Kamppeter
Import upstream version 9.04~dfsg~20110715 |
668 |
!(y >= crdev->ymin && y < crdev->ymax) |
669 |
) { |
|
670 |
int band_height = crdev->page_band_height; |
|
671 |
int band = y / band_height; |
|
672 |
int band_begin_line = band * band_height; |
|
673 |
int band_end_line = band_begin_line + band_height; |
|
674 |
int band_num_lines; |
|
675 |
gs_int_rect band_rect; |
|
676 |
||
677 |
if (band_end_line > dev->height) |
|
678 |
band_end_line = dev->height; |
|
679 |
/* Clip line_count to current band */
|
|
680 |
if (line_count > band_end_line - y) |
|
681 |
line_count = band_end_line - y; |
|
682 |
band_num_lines = band_end_line - band_begin_line; |
|
683 |
||
684 |
if (y < 0 || y > dev->height) |
|
685 |
return_error(gs_error_rangecheck); |
|
686 |
code = crdev->buf_procs.setup_buf_device |
|
687 |
(bdev, mdata, raster, NULL, 0, band_num_lines, band_num_lines); |
|
688 |
band_rect.p.x = 0; |
|
689 |
band_rect.p.y = band_begin_line; |
|
690 |
band_rect.q.x = dev->width; |
|
691 |
band_rect.q.y = band_end_line; |
|
692 |
if (code >= 0) |
|
693 |
code = clist_render_rectangle(cldev, &band_rect, bdev, render_plane, |
|
694 |
true); |
|
695 |
/* Reset the band boundaries now, so that we don't get */
|
|
696 |
/* an infinite loop. */
|
|
697 |
crdev->ymin = band_begin_line; |
|
698 |
crdev->ymax = band_end_line; |
|
699 |
crdev->offset_map = NULL; |
|
700 |
if (code < 0) |
|
701 |
return code; |
|
1.1.10
by Till Kamppeter
Import upstream version 8.64.dfsg.1~svn9377 |
702 |
}
|
703 |
||
704 |
if (line_count > crdev->ymax - y) |
|
1.1.23
by Till Kamppeter
Import upstream version 9.04~dfsg~20110715 |
705 |
line_count = crdev->ymax - y; |
1.1.10
by Till Kamppeter
Import upstream version 8.64.dfsg.1~svn9377 |
706 |
code = crdev->buf_procs.setup_buf_device |
1.1.23
by Till Kamppeter
Import upstream version 9.04~dfsg~20110715 |
707 |
(bdev, mdata, raster, NULL, y - crdev->ymin, line_count, |
708 |
crdev->ymax - crdev->ymin); |
|
1.1.10
by Till Kamppeter
Import upstream version 8.64.dfsg.1~svn9377 |
709 |
if (code < 0) |
1.1.23
by Till Kamppeter
Import upstream version 9.04~dfsg~20110715 |
710 |
return code; |
1.1.10
by Till Kamppeter
Import upstream version 8.64.dfsg.1~svn9377 |
711 |
|
712 |
*pmy = 0; |
|
713 |
return line_count; |
|
714 |
}
|
|
715 |
||
716 |
/*
|
|
717 |
* Render a rectangle to a client-supplied device. There is no necessary
|
|
718 |
* relationship between band boundaries and the region being rendered.
|
|
719 |
*/
|
|
720 |
int
|
|
721 |
clist_render_rectangle(gx_device_clist *cldev, const gs_int_rect *prect, |
|
1.1.23
by Till Kamppeter
Import upstream version 9.04~dfsg~20110715 |
722 |
gx_device *bdev, |
723 |
const gx_render_plane_t *render_plane, bool clear) |
|
1.1.10
by Till Kamppeter
Import upstream version 8.64.dfsg.1~svn9377 |
724 |
{
|
725 |
gx_device_clist_reader * const crdev = &cldev->reader; |
|
726 |
const gx_placed_page *ppages; |
|
727 |
int num_pages = crdev->num_pages; |
|
728 |
int band_height = crdev->page_band_height; |
|
729 |
int band_first = prect->p.y / band_height; |
|
730 |
int band_last = (prect->q.y - 1) / band_height; |
|
731 |
gx_saved_page current_page; |
|
732 |
gx_placed_page placed_page; |
|
733 |
int code = 0; |
|
734 |
int i; |
|
735 |
||
736 |
if (render_plane) |
|
1.1.23
by Till Kamppeter
Import upstream version 9.04~dfsg~20110715 |
737 |
crdev->yplane = *render_plane; |
1.1.10
by Till Kamppeter
Import upstream version 8.64.dfsg.1~svn9377 |
738 |
else
|
1.1.23
by Till Kamppeter
Import upstream version 9.04~dfsg~20110715 |
739 |
crdev->yplane.index = -1; |
1.1.10
by Till Kamppeter
Import upstream version 8.64.dfsg.1~svn9377 |
740 |
if_debug2('l', "[l]rendering bands (%d,%d)\n", band_first, band_last); |
741 |
#if 0 /* Disabled because it is slow and appears to have no useful effect. */ |
|
742 |
if (clear)
|
|
1.1.23
by Till Kamppeter
Import upstream version 9.04~dfsg~20110715 |
743 |
dev_proc(bdev, fill_rectangle)
|
744 |
(bdev, 0, 0, bdev->width, bdev->height, gx_device_white(bdev));
|
|
1.1.10
by Till Kamppeter
Import upstream version 8.64.dfsg.1~svn9377 |
745 |
#endif
|
746 |
||
747 |
/*
|
|
748 |
* If we aren't rendering saved pages, do the current one.
|
|
749 |
* Note that this is the only case in which we may encounter
|
|
750 |
* a gx_saved_page with non-zero cfile or bfile.
|
|
751 |
*/
|
|
752 |
ppages = crdev->pages; |
|
753 |
if (ppages == 0) { |
|
1.1.23
by Till Kamppeter
Import upstream version 9.04~dfsg~20110715 |
754 |
current_page.info = crdev->page_info; |
755 |
placed_page.page = ¤t_page; |
|
756 |
placed_page.offset.x = placed_page.offset.y = 0; |
|
757 |
ppages = &placed_page; |
|
758 |
num_pages = 1; |
|
1.1.10
by Till Kamppeter
Import upstream version 8.64.dfsg.1~svn9377 |
759 |
}
|
760 |
for (i = 0; i < num_pages && code >= 0; ++i) { |
|
1.1.23
by Till Kamppeter
Import upstream version 9.04~dfsg~20110715 |
761 |
const gx_placed_page *ppage = &ppages[i]; |
1.1.10
by Till Kamppeter
Import upstream version 8.64.dfsg.1~svn9377 |
762 |
|
1.1.23
by Till Kamppeter
Import upstream version 9.04~dfsg~20110715 |
763 |
/*
|
764 |
* Set the band_offset_? values in case the buffer device
|
|
765 |
* needs this. Example, wtsimdi device needs to adjust the
|
|
766 |
* phase of the dithering based on the page position, NOT
|
|
767 |
* the position within the band buffer to avoid band stitch
|
|
768 |
* lines in the dither pattern.
|
|
769 |
*
|
|
770 |
* The band_offset_x is not important for placed pages that
|
|
771 |
* are nested on a 'master' page (imposition) since each
|
|
772 |
* page expects to be dithered independently, but setting
|
|
773 |
* this allows pages to be contiguous without a dithering
|
|
774 |
* shift.
|
|
775 |
*
|
|
776 |
* The following sets the band_offset_? relative to the
|
|
777 |
* master page.
|
|
778 |
*/
|
|
779 |
bdev->band_offset_x = ppage->offset.x; |
|
780 |
bdev->band_offset_y = ppage->offset.y + (band_first * band_height); |
|
781 |
code = clist_playback_file_bands(playback_action_render, |
|
782 |
crdev, &ppage->page->info, |
|
783 |
bdev, band_first, band_last, |
|
784 |
prect->p.x - ppage->offset.x, |
|
785 |
prect->p.y); |
|
1.1.10
by Till Kamppeter
Import upstream version 8.64.dfsg.1~svn9377 |
786 |
}
|
787 |
return code; |
|
788 |
}
|
|
789 |
||
790 |
/* Playback the band file, taking the indicated action w/ its contents. */
|
|
791 |
int
|
|
1.1.23
by Till Kamppeter
Import upstream version 9.04~dfsg~20110715 |
792 |
clist_playback_file_bands(clist_playback_action action, |
793 |
gx_device_clist_reader *crdev, |
|
794 |
gx_band_page_info_t *page_info, gx_device *target, |
|
795 |
int band_first, int band_last, int x0, int y0) |
|
1.1.10
by Till Kamppeter
Import upstream version 8.64.dfsg.1~svn9377 |
796 |
{
|
797 |
int code = 0; |
|
798 |
bool opened_bfile = false; |
|
799 |
bool opened_cfile = false; |
|
800 |
||
801 |
/* We have to pick some allocator for rendering.... */
|
|
802 |
gs_memory_t *mem =crdev->memory; |
|
1.1.23
by Till Kamppeter
Import upstream version 9.04~dfsg~20110715 |
803 |
|
1.1.10
by Till Kamppeter
Import upstream version 8.64.dfsg.1~svn9377 |
804 |
stream_band_read_state rs; |
805 |
||
806 |
/* setup stream */
|
|
807 |
s_init_state((stream_state *)&rs, &s_band_read_template, |
|
1.1.23
by Till Kamppeter
Import upstream version 9.04~dfsg~20110715 |
808 |
(gs_memory_t *)0); |
1.1.10
by Till Kamppeter
Import upstream version 8.64.dfsg.1~svn9377 |
809 |
rs.band_first = band_first; |
810 |
rs.band_last = band_last; |
|
811 |
rs.page_info = *page_info; |
|
812 |
||
813 |
/* If this is a saved page, open the files. */
|
|
814 |
if (rs.page_cfile == 0) { |
|
1.1.23
by Till Kamppeter
Import upstream version 9.04~dfsg~20110715 |
815 |
code = crdev->page_info.io_procs->fopen(rs.page_cfname, |
816 |
gp_fmode_rb, &rs.page_cfile, crdev->bandlist_memory, |
|
817 |
crdev->bandlist_memory, true); |
|
818 |
opened_cfile = (code >= 0); |
|
1.1.10
by Till Kamppeter
Import upstream version 8.64.dfsg.1~svn9377 |
819 |
}
|
820 |
if (rs.page_bfile == 0 && code >= 0) { |
|
1.1.23
by Till Kamppeter
Import upstream version 9.04~dfsg~20110715 |
821 |
code = crdev->page_info.io_procs->fopen(rs.page_bfname, |
822 |
gp_fmode_rb, &rs.page_bfile, crdev->bandlist_memory, |
|
823 |
crdev->bandlist_memory, false); |
|
824 |
opened_bfile = (code >= 0); |
|
1.1.10
by Till Kamppeter
Import upstream version 8.64.dfsg.1~svn9377 |
825 |
}
|
826 |
if (rs.page_cfile != 0 && rs.page_bfile != 0) { |
|
1.1.23
by Till Kamppeter
Import upstream version 9.04~dfsg~20110715 |
827 |
stream s; |
828 |
byte sbuf[cbuf_size]; |
|
829 |
static const stream_procs no_procs = { |
|
830 |
s_std_noavailable, s_std_noseek, s_std_read_reset, |
|
831 |
s_std_read_flush, s_std_close, s_band_read_process |
|
832 |
};
|
|
1.1.10
by Till Kamppeter
Import upstream version 8.64.dfsg.1~svn9377 |
833 |
|
1.1.23
by Till Kamppeter
Import upstream version 9.04~dfsg~20110715 |
834 |
s_band_read_init((stream_state *)&rs); |
1.1.10
by Till Kamppeter
Import upstream version 8.64.dfsg.1~svn9377 |
835 |
# ifdef DEBUG
|
1.1.23
by Till Kamppeter
Import upstream version 9.04~dfsg~20110715 |
836 |
s_band_read_init_offset_map(crdev, (stream_state *)&rs); |
1.1.10
by Till Kamppeter
Import upstream version 8.64.dfsg.1~svn9377 |
837 |
# endif
|
1.1.23
by Till Kamppeter
Import upstream version 9.04~dfsg~20110715 |
838 |
/* The stream doesn't need a memory, but we'll need to access s.memory->gs_lib_ctx. */
|
839 |
s_init(&s, mem); |
|
840 |
s_std_init(&s, sbuf, cbuf_size, &no_procs, s_mode_read); |
|
841 |
s.foreign = 1; |
|
842 |
s.state = (stream_state *)&rs; |
|
1.1.10
by Till Kamppeter
Import upstream version 8.64.dfsg.1~svn9377 |
843 |
|
1.1.23
by Till Kamppeter
Import upstream version 9.04~dfsg~20110715 |
844 |
if (vd_allowed('s')) { |
845 |
vd_get_dc('s'); |
|
846 |
} else if (vd_allowed('i')) { |
|
847 |
vd_get_dc('i'); |
|
848 |
}
|
|
849 |
vd_set_shift(0, 0); |
|
850 |
vd_set_scale(0.01); |
|
851 |
vd_set_origin(0, 0); |
|
852 |
code = clist_playback_band(action, crdev, &s, target, x0, y0, mem); |
|
853 |
vd_release_dc; |
|
1.1.10
by Till Kamppeter
Import upstream version 8.64.dfsg.1~svn9377 |
854 |
# ifdef DEBUG
|
1.1.23
by Till Kamppeter
Import upstream version 9.04~dfsg~20110715 |
855 |
s_band_read_dnit_offset_map(crdev, (stream_state *)&rs); |
1.1.10
by Till Kamppeter
Import upstream version 8.64.dfsg.1~svn9377 |
856 |
# endif
|
857 |
}
|
|
858 |
||
859 |
/* Close the files if we just opened them. */
|
|
860 |
if (opened_bfile && rs.page_bfile != 0) |
|
1.1.23
by Till Kamppeter
Import upstream version 9.04~dfsg~20110715 |
861 |
crdev->page_info.io_procs->fclose(rs.page_bfile, rs.page_bfname, false); |
1.1.10
by Till Kamppeter
Import upstream version 8.64.dfsg.1~svn9377 |
862 |
if (opened_cfile && rs.page_cfile != 0) |
1.1.23
by Till Kamppeter
Import upstream version 9.04~dfsg~20110715 |
863 |
crdev->page_info.io_procs->fclose(rs.page_cfile, rs.page_cfname, false); |
1.1.10
by Till Kamppeter
Import upstream version 8.64.dfsg.1~svn9377 |
864 |
|
865 |
return code; |
|
866 |
}
|
|
867 |
||
868 |
/*
|
|
869 |
* return pointer to list indexed by (y /band_height)
|
|
870 |
* Don't free the returned pointer.
|
|
871 |
*/
|
|
872 |
gx_band_complexity_t * |
|
873 |
clist_get_band_complexity(gx_device *dev, int y) |
|
874 |
{
|
|
875 |
if (dev != NULL) { |
|
1.1.23
by Till Kamppeter
Import upstream version 9.04~dfsg~20110715 |
876 |
gx_device_clist *cldev = (gx_device_clist *)dev; |
877 |
gx_device_clist_reader * const crdev = &cldev->reader; |
|
878 |
int band_number = y / crdev->page_info.band_params.BandHeight; |
|
879 |
||
880 |
if (crdev->band_complexity_array == NULL) |
|
881 |
return NULL; |
|
1.1.10
by Till Kamppeter
Import upstream version 8.64.dfsg.1~svn9377 |
882 |
|
883 |
{
|
|
884 |
/* NB this is a temporary workaround until the band
|
|
885 |
complexity machinery can be removed entirely. */
|
|
886 |
gx_colors_used_t colors_used; |
|
887 |
int range_ignored; |
|
888 |
gdev_prn_colors_used(dev, y, 1, &colors_used, &range_ignored); |
|
889 |
crdev->band_complexity_array[band_number].nontrivial_rops = (int)colors_used.slow_rop; |
|
890 |
crdev->band_complexity_array[band_number].uses_color = (int)colors_used.or; |
|
891 |
}
|
|
1.1.23
by Till Kamppeter
Import upstream version 9.04~dfsg~20110715 |
892 |
return &crdev->band_complexity_array[band_number]; |
1.1.10
by Till Kamppeter
Import upstream version 8.64.dfsg.1~svn9377 |
893 |
}
|
894 |
return NULL; |
|
895 |
}
|
|
896 |
||
897 |
/* Free any band_complexity_array memory used by the clist reader device */
|
|
898 |
void gx_clist_reader_free_band_complexity_array( gx_device_clist *cldev ) |
|
899 |
{
|
|
1.1.23
by Till Kamppeter
Import upstream version 9.04~dfsg~20110715 |
900 |
if (cldev != NULL) { |
901 |
gx_device_clist_reader * const crdev = &cldev->reader; |
|
902 |
||
903 |
if ( crdev->band_complexity_array ) { |
|
904 |
gs_free_object( crdev->memory, crdev->band_complexity_array, |
|
905 |
"gx_clist_reader_free_band_complexity_array" ); |
|
906 |
crdev->band_complexity_array = NULL; |
|
907 |
}
|
|
908 |
}
|
|
1.1.10
by Till Kamppeter
Import upstream version 8.64.dfsg.1~svn9377 |
909 |
}
|
910 |
||
1.1.23
by Till Kamppeter
Import upstream version 9.04~dfsg~20110715 |
911 |
/* call once per read page to read the band complexity from clist file
|
1.1.10
by Till Kamppeter
Import upstream version 8.64.dfsg.1~svn9377 |
912 |
*/
|
913 |
static int |
|
914 |
gx_clist_reader_read_band_complexity(gx_device_clist *dev) |
|
915 |
{
|
|
916 |
int code = -1; /* no dev bad call */ |
|
917 |
||
918 |
if (dev) { |
|
1.1.23
by Till Kamppeter
Import upstream version 9.04~dfsg~20110715 |
919 |
gx_device_clist *cldev = (gx_device_clist *)dev; |
920 |
gx_device_clist_reader * const crdev = &cldev->reader; |
|
921 |
int i; |
|
922 |
stream_band_read_state rs; |
|
923 |
cmd_block cb; |
|
924 |
int64_t save_pos; |
|
925 |
int pos = 0; |
|
926 |
||
927 |
/* setup stream */
|
|
928 |
s_init_state((stream_state *)&rs, &s_band_read_template, (gs_memory_t *)0); |
|
929 |
rs.band_first = 0; |
|
930 |
rs.band_last = crdev->nbands; |
|
931 |
rs.page_info = crdev->page_info; |
|
932 |
||
933 |
save_pos = crdev->page_info.io_procs->ftell(rs.page_bfile); |
|
934 |
crdev->page_info.io_procs->fseek(rs.page_bfile, pos, SEEK_SET, rs.page_bfname); |
|
935 |
||
936 |
if ( crdev->band_complexity_array == NULL ) |
|
937 |
crdev->band_complexity_array = (gx_band_complexity_t*) |
|
938 |
gs_alloc_byte_array( crdev->memory, crdev->nbands, |
|
939 |
sizeof( gx_band_complexity_t ), "gx_clist_reader_read_band_complexity" ); |
|
940 |
||
941 |
if ( crdev->band_complexity_array == NULL ) |
|
942 |
return_error(gs_error_VMerror); |
|
943 |
||
944 |
for (i=0; i < crdev->nbands; i++) { |
|
945 |
crdev->page_info.io_procs->fread_chars(&cb, sizeof(cb), rs.page_bfile); |
|
946 |
crdev->band_complexity_array[i] = cb.band_complexity; |
|
947 |
}
|
|
948 |
||
949 |
crdev->page_info.io_procs->fseek(rs.page_bfile, save_pos, SEEK_SET, rs.page_bfname); |
|
950 |
code = 0; |
|
1.1.10
by Till Kamppeter
Import upstream version 8.64.dfsg.1~svn9377 |
951 |
}
|
952 |
return code; |
|
953 |
}
|