1
/* Copyright (C) 2001-2006 Artifex Software, Inc.
4
This software is provided AS-IS with no warranty, either express or
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.
14
/* $Id: gxclist.h 9288 2008-12-13 20:05:37Z leonardo $ */
15
/* Command list definitions for Ghostscript. */
16
/* Requires gxdevice.h and gxdevmem.h */
18
#ifndef gxclist_INCLUDED
19
# define gxclist_INCLUDED
30
* A command list is essentially a compressed list of driver calls.
31
* Command lists are used to record an image that must be rendered in bands
32
* for high-resolution and/or limited-memory printers.
34
* Command lists work in two phases. The first phase records driver calls,
35
* sorting them according to the band(s) they affect. The second phase
36
* reads back the commands band-by-band to create the bitmap images.
37
* When opened, a command list is in the recording state; it switches
38
* automatically from recording to reading when its get_bits procedure
39
* is called. Currently, there is a hack to reopen the device after
40
* each page is processed, in order to switch back to recording.
44
* The command list contains both commands for particular bands (the vast
45
* majority) and commands that apply to a range of bands. In order to
46
* synchronize the two, we maintain the following invariant for buffered
49
* If there are any band-range commands in the buffer, they are the
50
* first commands in the buffer, before any specific-band commands.
52
* To maintain this invariant, whenever we are about to put an band-range
53
* command in the buffer, we check to see if the buffer already has any
54
* band-range commands in it, and if so, whether they are the last commands
55
* in the buffer and are for the same range; if the answer to any of these
56
* questions is negative, we flush the buffer.
59
#ifndef gs_pattern1_instance_t_DEFINED
60
# define gs_pattern1_instance_t_DEFINED
61
typedef struct gs_pattern1_instance_s gs_pattern1_instance_t;
64
/* ---------------- Public structures ---------------- */
67
* Define a saved page object. This consists of a snapshot of the device
68
* structure, information about the page per se, and the num_copies
69
* parameter of output_page.
71
typedef struct gx_saved_page_s {
73
char dname[8 + 1]; /* device name for checking */
74
gx_band_page_info_t info;
79
* Define a saved page placed at a particular (X,Y) offset for rendering.
81
typedef struct gx_placed_page_s {
87
* Define a procedure to cause some bandlist memory to be freed up,
88
* probably by rendering current bandlist contents.
90
#define proc_free_up_bandlist_memory(proc)\
91
int proc(gx_device *dev, bool flush_current)
93
/* ---------------- Internal structures ---------------- */
96
* Currently, halftoning occurs during the first phase, producing calls
97
* to tile_rectangle. Both phases keep a cache of recently seen bitmaps
98
* (halftone cells and characters), which allows writing only a short cache
99
* index in the command list rather than the entire bitmap.
101
* We keep only a single cache for all bands, but since the second phase
102
* reads the command lists for each band separately, we have to keep track
103
* for each cache entry E and band B whether the definition of E has been
104
* written into B's list. We do this with a bit mask in each entry.
106
* Eventually, we will replace this entire arrangement with one in which
107
* we pass the actual halftone screen (whitening order) to all bands
108
* through the command list, and halftoning occurs on the second phase.
109
* This not only will shrink the command list, but will allow us to apply
110
* other rendering algorithms such as error diffusion in the second phase.
113
ulong offset; /* writing: offset from cdev->data, */
115
/* reading: offset from cdev->chunk.data */
118
gx_cached_bits_common;
119
/* To save space, instead of storing rep_width and rep_height, */
120
/* we store width / rep_width and height / rep_height. */
123
ushort index; /* index in table (hash table when writing) */
124
ushort num_bands; /* # of 1-bits in the band mask */
125
/* byte band_mask[]; */
126
#define ts_mask(pts) (byte *)((pts) + 1)
128
#define ts_bits(cldev,pts) (ts_mask(pts) + (cldev)->tile_band_mask_size)
131
/* Define the prefix on each command run in the writing buffer. */
132
typedef struct cmd_prefix_s cmd_prefix;
133
struct cmd_prefix_s {
136
ulong id; /* Debug purpose only. */
139
/* Define the pointers for managing a list of command runs in the buffer. */
140
/* There is one of these for each band, plus one for band-range commands. */
141
typedef struct cmd_list_s {
142
cmd_prefix *head, *tail; /* list of commands for band */
146
* In order to keep the per-band state down to a reasonable size,
147
* we store only a single set of the imager state parameters;
148
* for each parameter, each band has a flag that says whether that band
149
* 'knows' the current value of the parameters.
151
extern const gs_imager_state clist_imager_state_initial;
154
* Define the main structure for holding command list state.
155
* Unless otherwise noted, all elements are used in both the writing (first)
156
* and reading (second) phase.
158
typedef struct gx_clist_state_s gx_clist_state;
160
#define gx_device_clist_common_members\
161
gx_device_forward_common; /* (see gxdevice.h) */\
162
/* Following must be set before writing or reading. */\
163
/* See gx_device_clist_writer, below, for more that must be init'd */\
164
/* gx_device *target; */ /* device for which commands */\
165
/* are being buffered */\
166
gx_device_buf_procs_t buf_procs;\
167
gs_memory_t *bandlist_memory; /* allocator for in-memory bandlist files */\
168
byte *data; /* buffer area */\
169
uint data_size; /* size of buffer */\
170
gx_band_params_t band_params; /* band buffering parameters */\
171
bool do_not_open_or_close_bandfiles; /* if true, do not open/close bandfiles */\
172
bool page_uses_transparency; /* if true then page uses PDF 1.4 transparency */\
173
/* Following are used for both writing and reading. */\
174
gx_bits_cache_chunk chunk; /* the only chunk of bits */\
176
uint tile_hash_mask; /* size of tile hash table -1 */\
177
uint tile_band_mask_size; /* size of band mask preceding */\
178
/* each tile in the cache */\
179
tile_hash *tile_table; /* table for tile cache: */\
180
/* see tile_hash above */\
181
/* (a hash table when writing) */\
182
int ymin, ymax; /* current band, <0 when writing */\
183
/* Following are set when writing, read when reading. */\
184
gx_band_page_info_t page_info; /* page information */\
185
int nbands /* # of bands */
188
* Chech whether a clist is used for storing a pattern command stream.
189
* Useful for both reader and writer.
191
#define IS_CLIST_FOR_PATTERN(cdev) (cdev->procs.open_device == pattern_clist_open_device)
193
typedef struct gx_device_clist_common_s {
194
gx_device_clist_common_members;
195
} gx_device_clist_common;
197
#define clist_band_height(cldev) ((cldev)->page_info.band_height)
198
#define clist_cfname(cldev) ((cldev)->page_info.cfname)
199
#define clist_cfile(cldev) ((cldev)->page_info.cfile)
200
#define clist_bfname(cldev) ((cldev)->page_info.bfname)
201
#define clist_bfile(cldev) ((cldev)->page_info.bfile)
203
/* Define the length of the longest dash pattern we are willing to store. */
204
/* (Strokes with longer patterns are converted to fills.) */
205
#define cmd_max_dash 11
207
/* Define a clist cropping buffer,
208
which represents a cropping stack element while clist writing. */
209
typedef struct clist_writer_cropping_buffer_s clist_writer_cropping_buffer_t;
211
struct clist_writer_cropping_buffer_s {
212
int cropping_min, cropping_max;
213
uint mask_id, temp_mask_id;
214
clist_writer_cropping_buffer_t *next;
217
#define private_st_clist_writer_cropping_buffer()\
218
gs_private_st_ptrs1(st_clist_writer_cropping_buffer,\
219
clist_writer_cropping_buffer_t, "clist_writer_transparency_buffer",\
220
clist_writer_cropping_buffer_enum_ptrs, clist_writer_cropping_buffer_reloc_ptrs, next)
223
/* Define the state of a band list when writing. */
224
typedef struct clist_color_space_s {
225
byte byte1; /* see cmd_opv_set_color_space in gxclpath.h */
226
gs_id id; /* space->id for comparisons */
227
const gs_color_space *space;
228
} clist_color_space_t;
229
struct gx_device_clist_writer_s {
230
gx_device_clist_common_members; /* (must be first) */
231
int error_code; /* error returned by cmd_put_op */
232
gx_clist_state *states; /* current state of each band */
233
byte *cbuf; /* start of command buffer */
234
byte *cnext; /* next slot in command buffer */
235
byte *cend; /* end of command buffer */
236
cmd_list *ccl; /* &clist_state.list of last command */
237
cmd_list band_range_list; /* list of band-range commands */
238
int band_range_min, band_range_max; /* range for list */
239
uint tile_max_size; /* max size of a single tile (bytes) */
240
uint tile_max_count; /* max # of hash table entries */
241
gx_strip_bitmap tile_params; /* current tile parameters */
242
int tile_depth; /* current tile depth */
243
int tile_known_min, tile_known_max; /* range of bands that knows the */
244
/* current tile parameters */
246
* NOTE: we must not set the line_params.dash.pattern member of the
247
* imager state to point to the dash_pattern member of the writer
248
* state (except transiently), since this would confuse the
251
gs_imager_state imager_state; /* current values of imager params */
252
float dash_pattern[cmd_max_dash]; /* current dash pattern */
253
const gx_clip_path *clip_path; /* current clip path, */
254
/* only non-transient for images */
255
gs_id clip_path_id; /* id of current clip path */
256
clist_color_space_t color_space; /* current color space, */
257
/* only used for non-mask images */
258
gs_id transfer_ids[4]; /* ids of transfer maps */
259
gs_id black_generation_id; /* id of black generation map */
260
gs_id undercolor_removal_id; /* id of u.c.r. map */
261
gs_id device_halftone_id; /* id of device halftone */
262
gs_id image_enum_id; /* non-0 if we are inside an image */
263
/* that we are passing through */
264
int error_is_retryable; /* Extra status used to distinguish hard VMerrors */
265
/* from warnings upgraded to VMerrors. */
266
/* T if err ret'd by cmd_put_op et al can be retried */
267
int permanent_error; /* if < 0, error only cleared by clist_reset() */
268
int driver_call_nesting; /* nesting level of non-retryable driver calls */
269
int ignore_lo_mem_warnings; /* ignore warnings from clist file/mem */
270
/* Following must be set before writing */
271
proc_free_up_bandlist_memory((*free_up_bandlist_memory)); /* if nz, proc to free some bandlist memory */
272
int disable_mask; /* mask of routines to disable clist_disable_xxx */
273
gs_pattern1_instance_t *pinst; /* Used when it is a pattern clist. */
274
int cropping_min, cropping_max;
275
int save_cropping_min, save_cropping_max;
276
bool cropping_saved; /* for clist_fill_path only. */
278
clist_writer_cropping_buffer_t *cropping_stack;
282
uint temp_mask_id; /* Mask id of a mask of an image with SMask. */
285
#ifndef gx_device_clist_writer_DEFINED
286
#define gx_device_clist_writer_DEFINED
287
typedef struct gx_device_clist_writer_s gx_device_clist_writer;
290
/* Bits for gx_device_clist_writer.disable_mask. Bit set disables behavior */
291
#define clist_disable_fill_path (1 << 0)
292
#define clist_disable_stroke_path (1 << 1)
293
#define clist_disable_hl_image (1 << 2)
294
#define clist_disable_complex_clip (1 << 3)
295
#define clist_disable_nonrect_hl_image (1 << 4)
296
#define clist_disable_pass_thru_params (1 << 5) /* disable EXCEPT at top of page */
297
#define clist_disable_copy_alpha (1 << 6) /* target does not support copy_alpha */
299
#ifndef clist_render_thread_control_t_DEFINED
300
# define clist_render_thread_control_t_DEFINED
301
typedef struct clist_render_thread_control_s clist_render_thread_control_t;
304
/* Define the state of a band list when reading. */
305
/* For normal rasterizing, pages and num_pages are both 0. */
306
typedef struct gx_device_clist_reader_s {
307
gx_device_clist_common_members; /* (must be first) */
308
gx_render_plane_t yplane; /* current plane, index = -1 */
309
/* means all planes */
310
const gx_placed_page *pages;
312
gx_band_complexity_t *band_complexity_array; /* num_bands elements */
313
void *offset_map; /* Just against collecting the map as garbage. */
314
int num_render_threads; /* number of threads being used */
315
clist_render_thread_control_t *render_threads; /* array of threads */
316
byte *main_thread_data; /* saved data pointer of main thread */
317
int curr_render_thread; /* index into array */
318
int thread_lookahead_direction; /* +1 or -1 */
319
} gx_device_clist_reader;
321
union gx_device_clist_s {
322
gx_device_clist_common common;
323
gx_device_clist_reader reader;
324
gx_device_clist_writer writer;
327
#ifndef gx_device_clist_DEFINED
328
#define gx_device_clist_DEFINED
329
typedef union gx_device_clist_s gx_device_clist;
332
extern_st(st_device_clist);
333
#define public_st_device_clist() /* in gxclist.c */\
334
gs_public_st_complex_only(st_device_clist, gx_device_clist,\
335
"gx_device_clist", 0, device_clist_enum_ptrs, device_clist_reloc_ptrs,\
337
#define st_device_clist_max_ptrs\
338
(st_device_forward_max_ptrs + st_imager_state_num_ptrs + 4)
340
#define CLIST_IS_WRITER(cdev) ((cdev)->common.ymin < 0)
342
/* setup before opening clist device */
343
#define clist_init_params(xclist, xdata, xdata_size, xtarget, xbuf_procs, xband_params, xexternal, xmemory, xfree_bandlist, xdisable, pageusestransparency)\
345
(xclist)->common.data = (xdata);\
346
(xclist)->common.data_size = (xdata_size);\
347
(xclist)->common.target = (xtarget);\
348
(xclist)->common.buf_procs = (xbuf_procs);\
349
(xclist)->common.band_params = (xband_params);\
350
(xclist)->common.do_not_open_or_close_bandfiles = (xexternal);\
351
(xclist)->common.bandlist_memory = (xmemory);\
352
(xclist)->writer.free_up_bandlist_memory = (xfree_bandlist);\
353
(xclist)->writer.disable_mask = (xdisable);\
354
(xclist)->writer.page_uses_transparency = (pageusestransparency);\
355
(xclist)->writer.pinst = NULL;\
358
/* Determine whether this clist device is able to recover VMerrors */
359
#define clist_test_VMerror_recoverable(cldev)\
360
((cldev)->free_up_bandlist_memory != 0)
362
/* The device template itself is never used, only the procedures. */
363
extern const gx_device_procs gs_clist_device_procs;
365
void clist_init_io_procs(gx_device_clist *pclist_dev, bool in_memory);
367
/* Reset (or prepare to append to) the command list after printing a page. */
368
int clist_finish_page(gx_device * dev, bool flush);
370
/* Close the band files and delete their contents. */
371
int clist_close_output_file(gx_device *dev);
374
* Close and delete the contents of the band files associated with a
375
* page_info structure (a page that has been separated from the device).
377
int clist_close_page_info(gx_band_page_info_t *ppi);
380
* Compute the colors-used information in the page_info structure from the
381
* information in the individual writer bands. This is only useful at the
382
* end of a page. gdev_prn_colors_used calls this procedure if it hasn't
383
* been called since the page was started. clist_end_page also calls it.
385
void clist_compute_colors_used(gx_device_clist_writer *cldev);
387
/* Define the abstract type for a printer device. */
388
#ifndef gx_device_printer_DEFINED
389
# define gx_device_printer_DEFINED
390
typedef struct gx_device_printer_s gx_device_printer;
393
/* Do device setup from params passed in the command list. */
394
int clist_setup_params(gx_device *dev);
397
* Render a rectangle to a client-supplied image. This implements
398
* gdev_prn_render_rectangle for devices that are using banding.
400
* Note that clist_render_rectangle only guarantees to render *at least* the
401
* requested rectangle to bdev, offset by (-prect->p.x, -prect->p.y):
402
* anything it does to avoid rendering regions outside the rectangle is
403
* merely an optimization. If the client really wants the output clipped to
404
* some rectangle smaller than ((0, 0), (bdev->width, bdev->height)), it
405
* must set up a clipping device.
407
int clist_render_rectangle(gx_device_clist *cdev,
408
const gs_int_rect *prect, gx_device *bdev,
409
const gx_render_plane_t *render_plane,
412
/* A null pointer is used to denote not banding.
413
* Since false == NULL the old usage of for_banding = false works even if it's hackish.
415
* returns the complexity for a band given the y offset from top of page.
417
gx_band_complexity_t *
418
clist_get_band_complexity(gx_device *dev, int y);
420
/* Free any band_complexity_array memory used by the clist reader device */
421
void gx_clist_reader_free_band_complexity_array(gx_device_clist *cldev);
423
/* deep copy constructor if from != NULL
424
* default constructor if from == NULL
427
clist_copy_band_complexity(gx_band_complexity_t *this, const gx_band_complexity_t *from);
429
/* Retrieve total size for cfile and bfile. */
430
int clist_data_size(const gx_device_clist *cdev, int select);
431
/* Get command list data. */
432
int clist_get_data(const gx_device_clist *cdev, int select, int offset, byte *buf, int length);
433
/* Put command list data. */
434
int clist_put_data(const gx_device_clist *cdev, int select, int offset, const byte *buf, int length);
436
/* Exports from gxclread used by the multi-threading logic */
438
/* Initialize for reading. */
439
int clist_render_init(gx_device_clist *dev);
442
clist_close_writer_and_init_reader(gx_device_clist *cldev);
445
clist_select_render_plane(gx_device *dev, int y, int height,
446
gx_render_plane_t *render_plane, int index);
448
int clist_rasterize_lines(gx_device *dev, int y, int lineCount,
450
const gx_render_plane_t *render_plane,
453
/* Enable multi threaded rendering. Returns > 0 if supported, < 0 if single threaded */
455
clist_enable_multi_thread_render(gx_device *dev);
457
/* Shutdown render threads and free up the related memory */
459
clist_teardown_render_threads(gx_device *dev);
462
#define clist_debug_rect clist_debug_rect_imp
463
void clist_debug_rect_imp(int x, int y, int width, int height);
464
#define clist_debug_image_rect clist_debug_image_rect_imp
465
void clist_debug_image_rect_imp(int x, int y, int width, int height);
466
#define clist_debug_set_ctm clist_debug_set_ctm_imp
467
void clist_debug_set_ctm_imp(const gs_matrix *m);
469
#define clist_debug_rect (void)
470
#define clist_debug_image_rect (void)
471
#define clist_debug_set_ctm (void)
474
/* Cropping by Y is necessary when the shading path is smaller than shading.
475
In this case the clipping path is written into the path's bands only.
476
Thus bands outside the shading path are not clipped,
477
but the shading may paint into them, so use this macro to crop them.
479
Besides that, cropping by Y is necessary when a transparency compositor
480
is installed over clist writer. Transparency compositors change the number
481
of device color components, so transparency group's elements
482
must not paint to bands that are not covered by the transparency bbox
483
to prevent a failure when clist reader recieves a wrong number of color components.
485
#define crop_fill_y(cdev, ry, rheight)\
487
if (ry < cdev->cropping_min) {\
488
rheight = ry + rheight - cdev->cropping_min;\
489
ry = cdev->cropping_min;\
491
if (ry + rheight > cdev->cropping_max)\
492
rheight = cdev->cropping_max - ry;\
495
#define crop_fill(dev, x, y, w, h)\
499
fit_fill_w(dev, x, w);\
500
crop_fill_y(dev, y, h);\
503
#define crop_copy_y(cdev, data, data_x, raster, id, ry, rheight)\
505
if (ry < cdev->cropping_min) {\
506
rheight = ry + rheight - cdev->cropping_min;\
507
data += (cdev->cropping_min - ry) * raster;\
508
id = gx_no_bitmap_id;\
509
ry = cdev->cropping_min;\
511
if (ry + rheight > cdev->cropping_max)\
512
rheight = cdev->cropping_max - ry;\
515
#define crop_copy(dev, data, data_x, raster, id, x, y, w, h)\
518
w += x, data_x -= x, x = 0;\
519
fit_fill_w(dev, x, w);\
520
crop_copy_y(dev, data, data_x, raster, id, y, h);\
523
#endif /* gxclist_INCLUDED */