2 |
- |
1 |
/* Copyright (C) 1991, 1995, 1996, 1997, 1998, 1999 Aladdin Enterprises. All rights reserved.
|
|
|
2 |
|
|
|
3 |
This software is provided AS-IS with no warranty, either express or
|
|
|
4 |
implied.
|
|
|
5 |
|
|
|
6 |
This software is distributed under license and may not be copied,
|
|
|
7 |
modified or distributed except as expressly authorized under the terms
|
|
|
8 |
of the license contained in the file LICENSE in this distribution.
|
|
|
9 |
|
|
|
10 |
For more information about licensing, please refer to
|
|
|
11 |
http://www.ghostscript.com/licensing/. For information on
|
|
|
12 |
commercial licensing, go to http://www.artifex.com/licensing/ or
|
|
|
13 |
contact Artifex Software, Inc., 101 Lucas Valley Road #110,
|
|
|
14 |
San Rafael, CA 94903, U.S.A., +1(415)492-9861.
|
|
|
15 |
*/
|
|
|
16 |
|
|
|
17 |
/* $Id: gxclist.h,v 1.7 2005/03/14 18:08:36 dan Exp $ */
|
|
|
18 |
/* Command list definitions for Ghostscript. */
|
|
|
19 |
/* Requires gxdevice.h and gxdevmem.h */
|
|
|
20 |
|
|
|
21 |
#ifndef gxclist_INCLUDED
|
|
|
22 |
# define gxclist_INCLUDED
|
|
|
23 |
|
|
|
24 |
#include "gscspace.h"
|
|
|
25 |
#include "gxband.h"
|
|
|
26 |
#include "gxbcache.h"
|
|
|
27 |
#include "gxclio.h"
|
|
|
28 |
#include "gxdevbuf.h"
|
|
|
29 |
#include "gxistate.h"
|
|
|
30 |
#include "gxrplane.h"
|
|
|
31 |
|
|
|
32 |
/*
|
|
|
33 |
* A command list is essentially a compressed list of driver calls.
|
|
|
34 |
* Command lists are used to record an image that must be rendered in bands
|
|
|
35 |
* for high-resolution and/or limited-memory printers.
|
|
|
36 |
*
|
|
|
37 |
* Command lists work in two phases. The first phase records driver calls,
|
|
|
38 |
* sorting them according to the band(s) they affect. The second phase
|
|
|
39 |
* reads back the commands band-by-band to create the bitmap images.
|
|
|
40 |
* When opened, a command list is in the recording state; it switches
|
|
|
41 |
* automatically from recording to reading when its get_bits procedure
|
|
|
42 |
* is called. Currently, there is a hack to reopen the device after
|
|
|
43 |
* each page is processed, in order to switch back to recording.
|
|
|
44 |
*/
|
|
|
45 |
|
|
|
46 |
/*
|
|
|
47 |
* The command list contains both commands for particular bands (the vast
|
|
|
48 |
* majority) and commands that apply to a range of bands. In order to
|
|
|
49 |
* synchronize the two, we maintain the following invariant for buffered
|
|
|
50 |
* commands:
|
|
|
51 |
*
|
|
|
52 |
* If there are any band-range commands in the buffer, they are the
|
|
|
53 |
* first commands in the buffer, before any specific-band commands.
|
|
|
54 |
*
|
|
|
55 |
* To maintain this invariant, whenever we are about to put an band-range
|
|
|
56 |
* command in the buffer, we check to see if the buffer already has any
|
|
|
57 |
* band-range commands in it, and if so, whether they are the last commands
|
|
|
58 |
* in the buffer and are for the same range; if the answer to any of these
|
|
|
59 |
* questions is negative, we flush the buffer.
|
|
|
60 |
*/
|
|
|
61 |
|
|
|
62 |
/* ---------------- Public structures ---------------- */
|
|
|
63 |
|
|
|
64 |
/*
|
|
|
65 |
* Define a saved page object. This consists of a snapshot of the device
|
|
|
66 |
* structure, information about the page per se, and the num_copies
|
|
|
67 |
* parameter of output_page.
|
|
|
68 |
*/
|
|
|
69 |
typedef struct gx_saved_page_s {
|
|
|
70 |
gx_device device;
|
|
|
71 |
char dname[8 + 1]; /* device name for checking */
|
|
|
72 |
gx_band_page_info_t info;
|
|
|
73 |
int num_copies;
|
|
|
74 |
} gx_saved_page;
|
|
|
75 |
|
|
|
76 |
/*
|
|
|
77 |
* Define a saved page placed at a particular (X,Y) offset for rendering.
|
|
|
78 |
*/
|
|
|
79 |
typedef struct gx_placed_page_s {
|
|
|
80 |
gx_saved_page *page;
|
|
|
81 |
gs_int_point offset;
|
|
|
82 |
} gx_placed_page;
|
|
|
83 |
|
|
|
84 |
/*
|
|
|
85 |
* Define a procedure to cause some bandlist memory to be freed up,
|
|
|
86 |
* probably by rendering current bandlist contents.
|
|
|
87 |
*/
|
|
|
88 |
#define proc_free_up_bandlist_memory(proc)\
|
|
|
89 |
int proc(gx_device *dev, bool flush_current)
|
|
|
90 |
|
|
|
91 |
/* ---------------- Internal structures ---------------- */
|
|
|
92 |
|
|
|
93 |
/*
|
|
|
94 |
* Currently, halftoning occurs during the first phase, producing calls
|
|
|
95 |
* to tile_rectangle. Both phases keep a cache of recently seen bitmaps
|
|
|
96 |
* (halftone cells and characters), which allows writing only a short cache
|
|
|
97 |
* index in the command list rather than the entire bitmap.
|
|
|
98 |
*
|
|
|
99 |
* We keep only a single cache for all bands, but since the second phase
|
|
|
100 |
* reads the command lists for each band separately, we have to keep track
|
|
|
101 |
* for each cache entry E and band B whether the definition of E has been
|
|
|
102 |
* written into B's list. We do this with a bit mask in each entry.
|
|
|
103 |
*
|
|
|
104 |
* Eventually, we will replace this entire arrangement with one in which
|
|
|
105 |
* we pass the actual halftone screen (whitening order) to all bands
|
|
|
106 |
* through the command list, and halftoning occurs on the second phase.
|
|
|
107 |
* This not only will shrink the command list, but will allow us to apply
|
|
|
108 |
* other rendering algorithms such as error diffusion in the second phase.
|
|
|
109 |
*/
|
|
|
110 |
typedef struct {
|
|
|
111 |
ulong offset; /* writing: offset from cdev->data, */
|
|
|
112 |
/* 0 means unused */
|
|
|
113 |
/* reading: offset from cdev->chunk.data */
|
|
|
114 |
} tile_hash;
|
|
|
115 |
typedef struct {
|
|
|
116 |
gx_cached_bits_common;
|
|
|
117 |
/* To save space, instead of storing rep_width and rep_height, */
|
|
|
118 |
/* we store width / rep_width and height / rep_height. */
|
|
|
119 |
byte x_reps, y_reps;
|
|
|
120 |
ushort rep_shift;
|
|
|
121 |
ushort index; /* index in table (hash table when writing) */
|
|
|
122 |
ushort num_bands; /* # of 1-bits in the band mask */
|
|
|
123 |
/* byte band_mask[]; */
|
|
|
124 |
#define ts_mask(pts) (byte *)((pts) + 1)
|
|
|
125 |
/* byte bits[]; */
|
|
|
126 |
#define ts_bits(cldev,pts) (ts_mask(pts) + (cldev)->tile_band_mask_size)
|
|
|
127 |
} tile_slot;
|
|
|
128 |
|
|
|
129 |
/* Define the prefix on each command run in the writing buffer. */
|
|
|
130 |
typedef struct cmd_prefix_s cmd_prefix;
|
|
|
131 |
struct cmd_prefix_s {
|
|
|
132 |
cmd_prefix *next;
|
|
|
133 |
uint size;
|
|
|
134 |
};
|
|
|
135 |
|
|
|
136 |
/* Define the pointers for managing a list of command runs in the buffer. */
|
|
|
137 |
/* There is one of these for each band, plus one for band-range commands. */
|
|
|
138 |
typedef struct cmd_list_s {
|
|
|
139 |
cmd_prefix *head, *tail; /* list of commands for band */
|
|
|
140 |
} cmd_list;
|
|
|
141 |
|
|
|
142 |
/*
|
|
|
143 |
* In order to keep the per-band state down to a reasonable size,
|
|
|
144 |
* we store only a single set of the imager state parameters;
|
|
|
145 |
* for each parameter, each band has a flag that says whether that band
|
|
|
146 |
* 'knows' the current value of the parameters.
|
|
|
147 |
*/
|
|
|
148 |
extern const gs_imager_state clist_imager_state_initial;
|
|
|
149 |
|
|
|
150 |
/*
|
|
|
151 |
* Define the main structure for holding command list state.
|
|
|
152 |
* Unless otherwise noted, all elements are used in both the writing (first)
|
|
|
153 |
* and reading (second) phase.
|
|
|
154 |
*/
|
|
|
155 |
typedef struct gx_clist_state_s gx_clist_state;
|
|
|
156 |
|
|
|
157 |
#define gx_device_clist_common_members\
|
|
|
158 |
gx_device_forward_common; /* (see gxdevice.h) */\
|
|
|
159 |
/* Following must be set before writing or reading. */\
|
|
|
160 |
/* See gx_device_clist_writer, below, for more that must be init'd */\
|
|
|
161 |
/* gx_device *target; */ /* device for which commands */\
|
|
|
162 |
/* are being buffered */\
|
|
|
163 |
gx_device_buf_procs_t buf_procs;\
|
|
|
164 |
gs_memory_t *bandlist_memory; /* allocator for in-memory bandlist files */\
|
|
|
165 |
byte *data; /* buffer area */\
|
|
|
166 |
uint data_size; /* size of buffer */\
|
|
|
167 |
gx_band_params_t band_params; /* band buffering parameters */\
|
|
|
168 |
bool do_not_open_or_close_bandfiles; /* if true, do not open/close bandfiles */\
|
|
|
169 |
bool page_uses_transparency; /* if true then page uses PDF 1.4 transparency */\
|
|
|
170 |
/* Following are used for both writing and reading. */\
|
|
|
171 |
gx_bits_cache_chunk chunk; /* the only chunk of bits */\
|
|
|
172 |
gx_bits_cache bits;\
|
|
|
173 |
uint tile_hash_mask; /* size of tile hash table -1 */\
|
|
|
174 |
uint tile_band_mask_size; /* size of band mask preceding */\
|
|
|
175 |
/* each tile in the cache */\
|
|
|
176 |
tile_hash *tile_table; /* table for tile cache: */\
|
|
|
177 |
/* see tile_hash above */\
|
|
|
178 |
/* (a hash table when writing) */\
|
|
|
179 |
int ymin, ymax; /* current band, <0 when writing */\
|
|
|
180 |
/* Following are set when writing, read when reading. */\
|
|
|
181 |
gx_band_page_info_t page_info; /* page information */\
|
|
|
182 |
int nbands /* # of bands */
|
|
|
183 |
|
|
|
184 |
typedef struct gx_device_clist_common_s {
|
|
|
185 |
gx_device_clist_common_members;
|
|
|
186 |
} gx_device_clist_common;
|
|
|
187 |
|
|
|
188 |
#define clist_band_height(cldev) ((cldev)->page_info.band_height)
|
|
|
189 |
#define clist_cfname(cldev) ((cldev)->page_info.cfname)
|
|
|
190 |
#define clist_cfile(cldev) ((cldev)->page_info.cfile)
|
|
|
191 |
#define clist_bfname(cldev) ((cldev)->page_info.bfname)
|
|
|
192 |
#define clist_bfile(cldev) ((cldev)->page_info.bfile)
|
|
|
193 |
|
|
|
194 |
/* Define the length of the longest dash pattern we are willing to store. */
|
|
|
195 |
/* (Strokes with longer patterns are converted to fills.) */
|
|
|
196 |
#define cmd_max_dash 11
|
|
|
197 |
|
|
|
198 |
/* Define the state of a band list when writing. */
|
|
|
199 |
typedef struct clist_color_space_s {
|
|
|
200 |
byte byte1; /* see cmd_opv_set_color_space in gxclpath.h */
|
|
|
201 |
gs_id id; /* space->id for comparisons */
|
|
|
202 |
const gs_color_space *space;
|
|
|
203 |
} clist_color_space_t;
|
|
|
204 |
typedef struct gx_device_clist_writer_s {
|
|
|
205 |
gx_device_clist_common_members; /* (must be first) */
|
|
|
206 |
int error_code; /* error returned by cmd_put_op */
|
|
|
207 |
gx_clist_state *states; /* current state of each band */
|
|
|
208 |
byte *cbuf; /* start of command buffer */
|
|
|
209 |
byte *cnext; /* next slot in command buffer */
|
|
|
210 |
byte *cend; /* end of command buffer */
|
|
|
211 |
cmd_list *ccl; /* &clist_state.list of last command */
|
|
|
212 |
cmd_list band_range_list; /* list of band-range commands */
|
|
|
213 |
int band_range_min, band_range_max; /* range for list */
|
|
|
214 |
uint tile_max_size; /* max size of a single tile (bytes) */
|
|
|
215 |
uint tile_max_count; /* max # of hash table entries */
|
|
|
216 |
gx_strip_bitmap tile_params; /* current tile parameters */
|
|
|
217 |
int tile_depth; /* current tile depth */
|
|
|
218 |
int tile_known_min, tile_known_max; /* range of bands that knows the */
|
|
|
219 |
/* current tile parameters */
|
|
|
220 |
/*
|
|
|
221 |
* NOTE: we must not set the line_params.dash.pattern member of the
|
|
|
222 |
* imager state to point to the dash_pattern member of the writer
|
|
|
223 |
* state (except transiently), since this would confuse the
|
|
|
224 |
* garbage collector.
|
|
|
225 |
*/
|
|
|
226 |
gs_imager_state imager_state; /* current values of imager params */
|
|
|
227 |
float dash_pattern[cmd_max_dash]; /* current dash pattern */
|
|
|
228 |
const gx_clip_path *clip_path; /* current clip path, */
|
|
|
229 |
/* only non-transient for images */
|
|
|
230 |
gs_id clip_path_id; /* id of current clip path */
|
|
|
231 |
clist_color_space_t color_space; /* current color space, */
|
|
|
232 |
/* only used for non-mask images */
|
|
|
233 |
gs_id transfer_ids[4]; /* ids of transfer maps */
|
|
|
234 |
gs_id black_generation_id; /* id of black generation map */
|
|
|
235 |
gs_id undercolor_removal_id; /* id of u.c.r. map */
|
|
|
236 |
gs_id device_halftone_id; /* id of device halftone */
|
|
|
237 |
gs_id image_enum_id; /* non-0 if we are inside an image */
|
|
|
238 |
/* that we are passing through */
|
|
|
239 |
int error_is_retryable; /* Extra status used to distinguish hard VMerrors */
|
|
|
240 |
/* from warnings upgraded to VMerrors. */
|
|
|
241 |
/* T if err ret'd by cmd_put_op et al can be retried */
|
|
|
242 |
int permanent_error; /* if < 0, error only cleared by clist_reset() */
|
|
|
243 |
int driver_call_nesting; /* nesting level of non-retryable driver calls */
|
|
|
244 |
int ignore_lo_mem_warnings; /* ignore warnings from clist file/mem */
|
|
|
245 |
/* Following must be set before writing */
|
|
|
246 |
proc_free_up_bandlist_memory((*free_up_bandlist_memory)); /* if nz, proc to free some bandlist memory */
|
|
|
247 |
int disable_mask; /* mask of routines to disable clist_disable_xxx */
|
|
|
248 |
} gx_device_clist_writer;
|
|
|
249 |
|
|
|
250 |
/* Bits for gx_device_clist_writer.disable_mask. Bit set disables behavior */
|
|
|
251 |
#define clist_disable_fill_path (1 << 0)
|
|
|
252 |
#define clist_disable_stroke_path (1 << 1)
|
|
|
253 |
#define clist_disable_hl_image (1 << 2)
|
|
|
254 |
#define clist_disable_complex_clip (1 << 3)
|
|
|
255 |
#define clist_disable_nonrect_hl_image (1 << 4)
|
|
|
256 |
#define clist_disable_pass_thru_params (1 << 5) /* disable EXCEPT at top of page */
|
|
|
257 |
#define clist_disable_copy_alpha (1 << 6) /* target does not support copy_alpha */
|
|
|
258 |
|
|
|
259 |
/* Define the state of a band list when reading. */
|
|
|
260 |
/* For normal rasterizing, pages and num_pages are both 0. */
|
|
|
261 |
typedef struct gx_device_clist_reader_s {
|
|
|
262 |
gx_device_clist_common_members; /* (must be first) */
|
|
|
263 |
gx_render_plane_t yplane; /* current plane, index = -1 */
|
|
|
264 |
/* means all planes */
|
|
|
265 |
const gx_placed_page *pages;
|
|
|
266 |
int num_pages;
|
|
|
267 |
} gx_device_clist_reader;
|
|
|
268 |
|
|
|
269 |
typedef union gx_device_clist_s {
|
|
|
270 |
gx_device_clist_common common;
|
|
|
271 |
gx_device_clist_reader reader;
|
|
|
272 |
gx_device_clist_writer writer;
|
|
|
273 |
} gx_device_clist;
|
|
|
274 |
|
|
|
275 |
extern_st(st_device_clist);
|
|
|
276 |
#define public_st_device_clist() /* in gxclist.c */\
|
|
|
277 |
gs_public_st_complex_only(st_device_clist, gx_device_clist,\
|
|
|
278 |
"gx_device_clist", 0, device_clist_enum_ptrs, device_clist_reloc_ptrs,\
|
|
|
279 |
gx_device_finalize)
|
|
|
280 |
#define st_device_clist_max_ptrs\
|
|
|
281 |
(st_device_forward_max_ptrs + st_imager_state_num_ptrs + 1)
|
|
|
282 |
|
|
|
283 |
/* setup before opening clist device */
|
|
|
284 |
#define clist_init_params(xclist, xdata, xdata_size, xtarget, xbuf_procs, xband_params, xexternal, xmemory, xfree_bandlist, xdisable, pageusestransparency)\
|
|
|
285 |
BEGIN\
|
|
|
286 |
(xclist)->common.data = (xdata);\
|
|
|
287 |
(xclist)->common.data_size = (xdata_size);\
|
|
|
288 |
(xclist)->common.target = (xtarget);\
|
|
|
289 |
(xclist)->common.buf_procs = (xbuf_procs);\
|
|
|
290 |
(xclist)->common.band_params = (xband_params);\
|
|
|
291 |
(xclist)->common.do_not_open_or_close_bandfiles = (xexternal);\
|
|
|
292 |
(xclist)->common.bandlist_memory = (xmemory);\
|
|
|
293 |
(xclist)->writer.free_up_bandlist_memory = (xfree_bandlist);\
|
|
|
294 |
(xclist)->writer.disable_mask = (xdisable);\
|
|
|
295 |
(xclist)->writer.page_uses_transparency = (pageusestransparency);\
|
|
|
296 |
END
|
|
|
297 |
|
|
|
298 |
/* Determine whether this clist device is able to recover VMerrors */
|
|
|
299 |
#define clist_test_VMerror_recoverable(cldev)\
|
|
|
300 |
((cldev)->free_up_bandlist_memory != 0)
|
|
|
301 |
|
|
|
302 |
/* The device template itself is never used, only the procedures. */
|
|
|
303 |
extern const gx_device_procs gs_clist_device_procs;
|
|
|
304 |
|
|
|
305 |
/* Reset (or prepare to append to) the command list after printing a page. */
|
|
|
306 |
int clist_finish_page(gx_device * dev, bool flush);
|
|
|
307 |
|
|
|
308 |
/* Close the band files and delete their contents. */
|
|
|
309 |
int clist_close_output_file(gx_device *dev);
|
|
|
310 |
|
|
|
311 |
/*
|
|
|
312 |
* Close and delete the contents of the band files associated with a
|
|
|
313 |
* page_info structure (a page that has been separated from the device).
|
|
|
314 |
*/
|
|
|
315 |
int clist_close_page_info(gx_band_page_info_t *ppi);
|
|
|
316 |
|
|
|
317 |
/*
|
|
|
318 |
* Compute the colors-used information in the page_info structure from the
|
|
|
319 |
* information in the individual writer bands. This is only useful at the
|
|
|
320 |
* end of a page. gdev_prn_colors_used calls this procedure if it hasn't
|
|
|
321 |
* been called since the page was started. clist_end_page also calls it.
|
|
|
322 |
*/
|
|
|
323 |
void clist_compute_colors_used(gx_device_clist_writer *cldev);
|
|
|
324 |
|
|
|
325 |
/* Define the abstract type for a printer device. */
|
|
|
326 |
#ifndef gx_device_printer_DEFINED
|
|
|
327 |
# define gx_device_printer_DEFINED
|
|
|
328 |
typedef struct gx_device_printer_s gx_device_printer;
|
|
|
329 |
#endif
|
|
|
330 |
|
|
|
331 |
/* Do device setup from params passed in the command list. */
|
|
|
332 |
int clist_setup_params(gx_device *dev);
|
|
|
333 |
|
|
|
334 |
/*
|
|
|
335 |
* Render a rectangle to a client-supplied image. This implements
|
|
|
336 |
* gdev_prn_render_rectangle for devices that are using banding.
|
|
|
337 |
*
|
|
|
338 |
* Note that clist_render_rectangle only guarantees to render *at least* the
|
|
|
339 |
* requested rectangle to bdev, offset by (-prect->p.x, -prect->p.y):
|
|
|
340 |
* anything it does to avoid rendering regions outside the rectangle is
|
|
|
341 |
* merely an optimization. If the client really wants the output clipped to
|
|
|
342 |
* some rectangle smaller than ((0, 0), (bdev->width, bdev->height)), it
|
|
|
343 |
* must set up a clipping device.
|
|
|
344 |
*/
|
|
|
345 |
int clist_render_rectangle(gx_device_clist *cdev,
|
|
|
346 |
const gs_int_rect *prect, gx_device *bdev,
|
|
|
347 |
const gx_render_plane_t *render_plane,
|
|
|
348 |
bool clear);
|
|
|
349 |
|
|
|
350 |
#endif /* gxclist_INCLUDED */
|