~ubuntu-branches/ubuntu/oneiric/ghostscript/oneiric

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 = &current_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
}