2 |
- |
1 |
/* Copyright (C) 1998, 1999 Aladdin Enterprises. All rights reserved.
|
|
|
2 |
|
|
|
3 |
This software is provided AS-IS with no warranty, either express or
|
|
|
4 |
implied.
|
|
|
5 |
|
|
|
6 |
This software is distributed under license and may not be copied,
|
|
|
7 |
modified or distributed except as expressly authorized under the terms
|
|
|
8 |
of the license contained in the file LICENSE in this distribution.
|
|
|
9 |
|
|
|
10 |
For more information about licensing, please refer to
|
|
|
11 |
http://www.ghostscript.com/licensing/. For information on
|
|
|
12 |
commercial licensing, go to http://www.artifex.com/licensing/ or
|
|
|
13 |
contact Artifex Software, Inc., 101 Lucas Valley Road #110,
|
|
|
14 |
San Rafael, CA 94903, U.S.A., +1(415)492-9861.
|
|
|
15 |
*/
|
|
|
16 |
|
|
|
17 |
/* $Id: gdevplnx.c,v 1.10 2004/08/04 19:36:12 stefan Exp $*/
|
|
|
18 |
/* Plane extraction device */
|
|
|
19 |
#include "gx.h"
|
|
|
20 |
#include "gserrors.h"
|
|
|
21 |
#include "gsbitops.h"
|
|
|
22 |
#include "gsrop.h" /* for logical op access */
|
|
|
23 |
#include "gsstruct.h"
|
|
|
24 |
#include "gsutil.h"
|
|
|
25 |
#include "gxdcolor.h"
|
|
|
26 |
#include "gxcmap.h" /* requires gxdcolor.h */
|
|
|
27 |
#include "gxdevice.h"
|
|
|
28 |
#include "gxdevmem.h"
|
|
|
29 |
#include "gxdither.h"
|
|
|
30 |
#include "gxgetbit.h"
|
|
|
31 |
#include "gxiparam.h"
|
|
|
32 |
#include "gxistate.h"
|
|
|
33 |
#include "gdevplnx.h"
|
|
|
34 |
|
|
|
35 |
/* Define the size of the locally allocated bitmap buffers. */
|
|
|
36 |
#define COPY_COLOR_BUF_SIZE 100
|
|
|
37 |
#define TILE_RECTANGLE_BUF_SIZE 100
|
|
|
38 |
#define COPY_ROP_SOURCE_BUF_SIZE 100
|
|
|
39 |
#define COPY_ROP_TEXTURE_BUF_SIZE 100
|
|
|
40 |
|
|
|
41 |
/* GC procedures */
|
|
|
42 |
private
|
|
|
43 |
ENUM_PTRS_WITH(device_plane_extract_enum_ptrs, gx_device_plane_extract *edev)
|
|
|
44 |
ENUM_PREFIX(st_device_forward, 1);
|
|
|
45 |
case 0: ENUM_RETURN(gx_device_enum_ptr(edev->target));
|
|
|
46 |
ENUM_PTRS_END
|
|
|
47 |
private RELOC_PTRS_WITH(device_plane_extract_reloc_ptrs, gx_device_plane_extract *edev)
|
|
|
48 |
{
|
|
|
49 |
RELOC_PREFIX(st_device_forward);
|
|
|
50 |
edev->plane_dev = gx_device_reloc_ptr(edev->plane_dev, gcst);
|
|
|
51 |
}
|
|
|
52 |
RELOC_PTRS_END
|
|
|
53 |
public_st_device_plane_extract();
|
|
|
54 |
|
|
|
55 |
/* Driver procedures */
|
|
|
56 |
private dev_proc_open_device(plane_open_device);
|
|
|
57 |
private dev_proc_fill_rectangle(plane_fill_rectangle);
|
|
|
58 |
private dev_proc_copy_mono(plane_copy_mono);
|
|
|
59 |
private dev_proc_copy_color(plane_copy_color);
|
|
|
60 |
private dev_proc_copy_alpha(plane_copy_alpha);
|
|
|
61 |
private dev_proc_fill_path(plane_fill_path);
|
|
|
62 |
private dev_proc_stroke_path(plane_stroke_path);
|
|
|
63 |
private dev_proc_fill_mask(plane_fill_mask);
|
|
|
64 |
private dev_proc_fill_parallelogram(plane_fill_parallelogram);
|
|
|
65 |
private dev_proc_fill_triangle(plane_fill_triangle);
|
|
|
66 |
private dev_proc_strip_tile_rectangle(plane_strip_tile_rectangle);
|
|
|
67 |
private dev_proc_strip_copy_rop(plane_strip_copy_rop);
|
|
|
68 |
private dev_proc_begin_typed_image(plane_begin_typed_image);
|
|
|
69 |
private dev_proc_get_bits_rectangle(plane_get_bits_rectangle);
|
|
|
70 |
|
|
|
71 |
/* Device prototype */
|
|
|
72 |
private const gx_device_plane_extract gs_plane_extract_device = {
|
|
|
73 |
std_device_std_body(gx_device_plane_extract, 0, "plane_extract",
|
|
|
74 |
0, 0, 72, 72),
|
|
|
75 |
{
|
|
|
76 |
plane_open_device,
|
|
|
77 |
NULL,
|
|
|
78 |
NULL,
|
|
|
79 |
NULL,
|
|
|
80 |
gx_default_close_device,
|
|
|
81 |
NULL,
|
|
|
82 |
NULL,
|
|
|
83 |
plane_fill_rectangle,
|
|
|
84 |
gx_default_tile_rectangle,
|
|
|
85 |
plane_copy_mono,
|
|
|
86 |
plane_copy_color,
|
|
|
87 |
gx_default_draw_line,
|
|
|
88 |
gx_default_get_bits,
|
|
|
89 |
NULL,
|
|
|
90 |
NULL,
|
|
|
91 |
NULL,
|
|
|
92 |
NULL,
|
|
|
93 |
NULL,
|
|
|
94 |
NULL,
|
|
|
95 |
NULL,
|
|
|
96 |
NULL,
|
|
|
97 |
plane_copy_alpha,
|
|
|
98 |
NULL,
|
|
|
99 |
gx_default_copy_rop,
|
|
|
100 |
plane_fill_path,
|
|
|
101 |
plane_stroke_path,
|
|
|
102 |
plane_fill_mask,
|
|
|
103 |
gx_default_fill_trapezoid,
|
|
|
104 |
plane_fill_parallelogram,
|
|
|
105 |
plane_fill_triangle,
|
|
|
106 |
gx_default_draw_thin_line,
|
|
|
107 |
gx_default_begin_image,
|
|
|
108 |
gx_default_image_data,
|
|
|
109 |
gx_default_end_image,
|
|
|
110 |
plane_strip_tile_rectangle,
|
|
|
111 |
plane_strip_copy_rop,
|
|
|
112 |
NULL,
|
|
|
113 |
plane_begin_typed_image,
|
|
|
114 |
plane_get_bits_rectangle,
|
|
|
115 |
NULL,
|
|
|
116 |
gx_no_create_compositor, /* WRONG */
|
|
|
117 |
NULL,
|
|
|
118 |
gx_default_text_begin
|
|
|
119 |
},
|
|
|
120 |
/* device-specific members */
|
|
|
121 |
NULL, /* target */
|
|
|
122 |
NULL, /* plane_dev */
|
|
|
123 |
{ 0 }, /* plane */
|
|
|
124 |
0, /* plane_white */
|
|
|
125 |
0, /* plane_mask */
|
|
|
126 |
0, /* plane_dev_is_memory */
|
|
|
127 |
1 /*true*/ /* any_marks */
|
|
|
128 |
};
|
|
|
129 |
|
|
|
130 |
/* ---------------- Utilities ---------------- */
|
|
|
131 |
|
|
|
132 |
/* Extract the selected plane from a color (gx_color_index). */
|
|
|
133 |
#define COLOR_PIXEL(edev, color)\
|
|
|
134 |
( ((color) >> (edev)->plane.shift) & (edev)->plane_mask )
|
|
|
135 |
/* Do the same if the color might be transparent. */
|
|
|
136 |
#define TRANS_COLOR_PIXEL(edev, color)\
|
|
|
137 |
((color) == gx_no_color_index ? gx_no_color_index : COLOR_PIXEL(edev, color))
|
|
|
138 |
|
|
|
139 |
/*
|
|
|
140 |
* Reduce the drawing color to one for the selected plane.
|
|
|
141 |
* All we care about is whether the drawing operation should be skipped.
|
|
|
142 |
*/
|
|
|
143 |
typedef enum {
|
|
|
144 |
REDUCE_SKIP,
|
|
|
145 |
REDUCE_DRAW,
|
|
|
146 |
REDUCE_FAILED /* couldn't reduce */
|
|
|
147 |
} reduced_color_t;
|
|
|
148 |
#define REDUCE_PURE(edev, pixel)\
|
|
|
149 |
((pixel) == (edev)->plane_white && !(edev)->any_marks ? REDUCE_SKIP :\
|
|
|
150 |
((edev)->any_marks = true, REDUCE_DRAW))
|
|
|
151 |
private reduced_color_t
|
|
|
152 |
reduce_drawing_color(gx_device_color *ppdc, gx_device_plane_extract *edev,
|
|
|
153 |
const gx_drawing_color *pdevc,
|
|
|
154 |
gs_logical_operation_t *plop)
|
|
|
155 |
{
|
|
|
156 |
reduced_color_t reduced;
|
|
|
157 |
|
|
|
158 |
if (gx_dc_is_pure(pdevc)) {
|
|
|
159 |
gx_color_index pixel = COLOR_PIXEL(edev, gx_dc_pure_color(pdevc));
|
|
|
160 |
|
|
|
161 |
set_nonclient_dev_color(ppdc, pixel);
|
|
|
162 |
reduced = REDUCE_PURE(edev, pixel);
|
|
|
163 |
} else if (gx_dc_is_binary_halftone(pdevc)) {
|
|
|
164 |
gx_color_index pixel0 =
|
|
|
165 |
TRANS_COLOR_PIXEL(edev, gx_dc_binary_color0(pdevc));
|
|
|
166 |
gx_color_index pixel1 =
|
|
|
167 |
TRANS_COLOR_PIXEL(edev, gx_dc_binary_color1(pdevc));
|
|
|
168 |
|
|
|
169 |
if (pixel0 == pixel1) {
|
|
|
170 |
set_nonclient_dev_color(ppdc, pixel0);
|
|
|
171 |
reduced = REDUCE_PURE(edev, pixel0);
|
|
|
172 |
} else {
|
|
|
173 |
*ppdc = *pdevc;
|
|
|
174 |
ppdc->colors.binary.color[0] = pixel0;
|
|
|
175 |
ppdc->colors.binary.color[1] = pixel1;
|
|
|
176 |
edev->any_marks = true;
|
|
|
177 |
reduced = REDUCE_DRAW;
|
|
|
178 |
}
|
|
|
179 |
} else if (color_is_colored_halftone(pdevc)) {
|
|
|
180 |
int plane = edev->plane.index;
|
|
|
181 |
int i;
|
|
|
182 |
|
|
|
183 |
*ppdc = *pdevc;
|
|
|
184 |
for (i = 0; i < countof(ppdc->colors.colored.c_base); ++i)
|
|
|
185 |
if (i != edev->plane.index) {
|
|
|
186 |
ppdc->colors.colored.c_base[i] = 0;
|
|
|
187 |
ppdc->colors.colored.c_level[i] = 0;
|
|
|
188 |
}
|
|
|
189 |
ppdc->colors.colored.plane_mask &= 1 << plane;
|
|
|
190 |
if (ppdc->colors.colored.c_level[plane] == 0) {
|
|
|
191 |
gx_devn_reduce_colored_halftone(ppdc, (gx_device *)edev);
|
|
|
192 |
ppdc->colors.pure = COLOR_PIXEL(edev, ppdc->colors.pure);
|
|
|
193 |
reduced = REDUCE_PURE(edev, gx_dc_pure_color(ppdc));
|
|
|
194 |
} else if (ppdc->colors.colored.alpha != gx_max_color_value)
|
|
|
195 |
return REDUCE_FAILED; /* can't reduce */
|
|
|
196 |
else {
|
|
|
197 |
gx_devn_reduce_colored_halftone(ppdc, (gx_device *)edev);
|
|
|
198 |
ppdc->colors.binary.color[0] =
|
|
|
199 |
COLOR_PIXEL(edev, ppdc->colors.binary.color[0]);
|
|
|
200 |
ppdc->colors.binary.color[1] =
|
|
|
201 |
COLOR_PIXEL(edev, ppdc->colors.binary.color[1]);
|
|
|
202 |
gx_color_load(ppdc, NULL, (gx_device *)edev);
|
|
|
203 |
edev->any_marks = true;
|
|
|
204 |
reduced = REDUCE_DRAW;
|
|
|
205 |
}
|
|
|
206 |
} else
|
|
|
207 |
return REDUCE_FAILED; /* can't handle it */
|
|
|
208 |
if (*plop & lop_T_transparent) {
|
|
|
209 |
/*
|
|
|
210 |
* If the logical operation invokes transparency for the texture, we
|
|
|
211 |
* must do some extra work, since a color that was originally opaque
|
|
|
212 |
* may become transparent (white) if reduced to a single plane. If
|
|
|
213 |
* RasterOp transparency were calculated before halftoning, life
|
|
|
214 |
* would be easy: we would simply turn off texture transparency in
|
|
|
215 |
* the logical operation iff the original (not reduced) color was
|
|
|
216 |
* not white. Unfortunately, RasterOp transparency is calculated
|
|
|
217 |
* after halftoning. (This is arguably wrong, but it's how we've
|
|
|
218 |
* defined it.) Therefore, if transparency is involved with a
|
|
|
219 |
* white color or a halftone that can include white, we must keep
|
|
|
220 |
* the entire pixel together for the RasterOp.
|
|
|
221 |
*/
|
|
|
222 |
gx_color_index white = gx_device_white((gx_device *)edev);
|
|
|
223 |
|
|
|
224 |
/*
|
|
|
225 |
* Given that we haven't failed, the only possible colors at this
|
|
|
226 |
* point are pure or binary halftone.
|
|
|
227 |
*/
|
|
|
228 |
if (gx_dc_is_pure(ppdc)) {
|
|
|
229 |
if (gx_dc_pure_color(pdevc) != white)
|
|
|
230 |
*plop &= ~lop_T_transparent;
|
|
|
231 |
else if (!gx_dc_is_pure(pdevc))
|
|
|
232 |
return REDUCE_FAILED;
|
|
|
233 |
} else {
|
|
|
234 |
if (gx_dc_binary_color0(pdevc) != white &&
|
|
|
235 |
gx_dc_binary_color1(pdevc) != white) {
|
|
|
236 |
*plop &= ~lop_T_transparent;
|
|
|
237 |
} else
|
|
|
238 |
return REDUCE_FAILED;
|
|
|
239 |
}
|
|
|
240 |
}
|
|
|
241 |
return reduced;
|
|
|
242 |
}
|
|
|
243 |
|
|
|
244 |
/*
|
|
|
245 |
* Set up to create the plane-extracted bitmap corresponding to a
|
|
|
246 |
* source or halftone pixmap. If the bitmap doesn't fit in the locally
|
|
|
247 |
* allocated buffer, we may either do the operation in pieces, or allocate
|
|
|
248 |
* a buffer on the heap. The control structure is:
|
|
|
249 |
* begin_tiling(&state, ...);
|
|
|
250 |
* do {
|
|
|
251 |
* extract_partial_tile(&state);
|
|
|
252 |
* ... process tile in buffer ...
|
|
|
253 |
* } while (next_tile(&state));
|
|
|
254 |
* end_tiling(&state);
|
|
|
255 |
* If partial_ok is false, there is only a single tile, so the do ... while
|
|
|
256 |
* is not used.
|
|
|
257 |
*/
|
|
|
258 |
typedef struct tiling_state_s {
|
|
|
259 |
/* Save the original operands. */
|
|
|
260 |
const gx_device_plane_extract *edev;
|
|
|
261 |
const byte *data;
|
|
|
262 |
int data_x;
|
|
|
263 |
uint raster;
|
|
|
264 |
int width, height;
|
|
|
265 |
int dest_x; /* only for copy_color, defaults to 0 */
|
|
|
266 |
/* Define the (aligned) buffer for doing the operation. */
|
|
|
267 |
struct tsb_ {
|
|
|
268 |
byte *data;
|
|
|
269 |
uint size;
|
|
|
270 |
uint raster;
|
|
|
271 |
bool on_heap;
|
|
|
272 |
} buffer;
|
|
|
273 |
/* Record the current tile available for processing. */
|
|
|
274 |
/* The client may read these out. */
|
|
|
275 |
gs_int_point offset;
|
|
|
276 |
gs_int_point size;
|
|
|
277 |
/* Record private tiling parameters. */
|
|
|
278 |
int per_tile_width;
|
|
|
279 |
} tiling_state_t;
|
|
|
280 |
|
|
|
281 |
/*
|
|
|
282 |
* Extract the plane's data from one subrectangle of a source tile.
|
|
|
283 |
*/
|
|
|
284 |
inline private int /* ignore the return value */
|
|
|
285 |
extract_partial_tile(const tiling_state_t *pts)
|
|
|
286 |
{
|
|
|
287 |
const gx_device_plane_extract * const edev = pts->edev;
|
|
|
288 |
bits_plane_t dest, source;
|
|
|
289 |
|
|
|
290 |
dest.data.write = pts->buffer.data + pts->offset.y * pts->buffer.raster;
|
|
|
291 |
dest.raster = pts->buffer.raster;
|
|
|
292 |
dest.depth = edev->plane.depth;
|
|
|
293 |
dest.x = pts->dest_x;
|
|
|
294 |
|
|
|
295 |
source.data.read = pts->data + pts->offset.y * pts->raster;
|
|
|
296 |
source.raster = pts->raster;
|
|
|
297 |
source.depth = edev->color_info.depth;
|
|
|
298 |
source.x = pts->data_x + pts->offset.x;
|
|
|
299 |
|
|
|
300 |
bits_extract_plane(&dest, &source, edev->plane.shift,
|
|
|
301 |
pts->size.x, pts->size.y);
|
|
|
302 |
return 0;
|
|
|
303 |
}
|
|
|
304 |
|
|
|
305 |
/*
|
|
|
306 |
* Set up to start (possibly) tiling. Return 0 if the entire tile fit,
|
|
|
307 |
* 1 if a partial tile fit, or a negative error code.
|
|
|
308 |
*/
|
|
|
309 |
private int
|
|
|
310 |
begin_tiling(tiling_state_t *pts, gx_device_plane_extract *edev,
|
|
|
311 |
const byte *data, int data_x, uint raster, int width, int height,
|
|
|
312 |
byte *local_buffer, uint buffer_size, bool partial_ok)
|
|
|
313 |
{
|
|
|
314 |
uint width_raster =
|
|
|
315 |
bitmap_raster(width * edev->plane_dev->color_info.depth);
|
|
|
316 |
uint full_size = width_raster * height;
|
|
|
317 |
|
|
|
318 |
pts->edev = edev;
|
|
|
319 |
pts->data = data, pts->data_x = data_x, pts->raster = raster;
|
|
|
320 |
pts->width = width, pts->height = height;
|
|
|
321 |
pts->dest_x = 0;
|
|
|
322 |
if (full_size <= buffer_size) {
|
|
|
323 |
pts->buffer.data = local_buffer;
|
|
|
324 |
pts->buffer.size = buffer_size;
|
|
|
325 |
pts->buffer.raster = width_raster;
|
|
|
326 |
pts->buffer.on_heap = false;
|
|
|
327 |
pts->size.x = width, pts->size.y = height;
|
|
|
328 |
} else if (partial_ok) {
|
|
|
329 |
pts->buffer.data = local_buffer;
|
|
|
330 |
pts->buffer.size = buffer_size;
|
|
|
331 |
pts->buffer.on_heap = false;
|
|
|
332 |
if (buffer_size >= width_raster) {
|
|
|
333 |
pts->buffer.raster = width_raster;
|
|
|
334 |
pts->size.x = width;
|
|
|
335 |
pts->size.y = buffer_size / width_raster;
|
|
|
336 |
} else {
|
|
|
337 |
pts->buffer.raster = buffer_size & -align_bitmap_mod;
|
|
|
338 |
pts->size.x =
|
|
|
339 |
pts->buffer.raster * (8 / edev->plane_dev->color_info.depth);
|
|
|
340 |
pts->size.y = 1;
|
|
|
341 |
}
|
|
|
342 |
} else {
|
|
|
343 |
pts->buffer.data =
|
|
|
344 |
gs_alloc_bytes(edev->memory, full_size, "begin_tiling");
|
|
|
345 |
if (!pts->buffer.data)
|
|
|
346 |
return_error(gs_error_VMerror);
|
|
|
347 |
pts->buffer.size = full_size;
|
|
|
348 |
pts->buffer.raster = width_raster;
|
|
|
349 |
pts->buffer.on_heap = true;
|
|
|
350 |
pts->size.x = width, pts->size.y = height;
|
|
|
351 |
}
|
|
|
352 |
pts->buffer.raster = width_raster;
|
|
|
353 |
pts->offset.x = pts->offset.y = 0;
|
|
|
354 |
pts->per_tile_width = pts->size.x;
|
|
|
355 |
return pts->buffer.size < full_size;
|
|
|
356 |
}
|
|
|
357 |
|
|
|
358 |
/*
|
|
|
359 |
* Advance to the next tile. Return true if there are more tiles to do.
|
|
|
360 |
*/
|
|
|
361 |
private bool
|
|
|
362 |
next_tile(tiling_state_t *pts)
|
|
|
363 |
{
|
|
|
364 |
if ((pts->offset.x += pts->size.x) >= pts->width) {
|
|
|
365 |
if ((pts->offset.y += pts->size.y) >= pts->height)
|
|
|
366 |
return false;
|
|
|
367 |
pts->offset.x = 0;
|
|
|
368 |
pts->size.x = pts->per_tile_width;
|
|
|
369 |
if (pts->offset.y + pts->size.y >= pts->height)
|
|
|
370 |
pts->size.y = pts->height - pts->offset.y;
|
|
|
371 |
} else if (pts->offset.x + pts->size.x >= pts->width)
|
|
|
372 |
pts->size.x = pts->width - pts->offset.x;
|
|
|
373 |
return true;
|
|
|
374 |
}
|
|
|
375 |
|
|
|
376 |
/*
|
|
|
377 |
* Finish tiling by freeing the buffer if necessary.
|
|
|
378 |
*/
|
|
|
379 |
private void
|
|
|
380 |
end_tiling(tiling_state_t *pts)
|
|
|
381 |
{
|
|
|
382 |
if (pts->buffer.on_heap)
|
|
|
383 |
gs_free_object(pts->edev->memory, pts->buffer.data, "end_tiling");
|
|
|
384 |
}
|
|
|
385 |
|
|
|
386 |
/* ---------------- Initialization ---------------- */
|
|
|
387 |
|
|
|
388 |
int
|
|
|
389 |
plane_device_init(gx_device_plane_extract *edev, gx_device *target,
|
|
|
390 |
gx_device *plane_dev, const gx_render_plane_t *render_plane, bool clear)
|
|
|
391 |
{
|
|
|
392 |
/* Check for compatibility of the plane specification. */
|
|
|
393 |
if (render_plane->depth > plane_dev->color_info.depth)
|
|
|
394 |
return_error(gs_error_rangecheck);
|
|
|
395 |
gx_device_init((gx_device *)edev,
|
|
|
396 |
(const gx_device *)&gs_plane_extract_device,
|
|
|
397 |
edev->memory, true);
|
|
|
398 |
check_device_separable((gx_device *)edev);
|
|
|
399 |
gx_device_forward_fill_in_procs((gx_device_forward *)edev);
|
|
|
400 |
gx_device_set_target((gx_device_forward *)edev, target);
|
|
|
401 |
gx_device_copy_params((gx_device *)edev, target);
|
|
|
402 |
edev->plane_dev = plane_dev;
|
|
|
403 |
edev->plane = *render_plane;
|
|
|
404 |
plane_open_device((gx_device *)edev);
|
|
|
405 |
if (clear) {
|
|
|
406 |
dev_proc(plane_dev, fill_rectangle)
|
|
|
407 |
(plane_dev, 0, 0, plane_dev->width, plane_dev->height,
|
|
|
408 |
edev->plane_white);
|
|
|
409 |
edev->any_marks = false;
|
|
|
410 |
}
|
|
|
411 |
return 0;
|
|
|
412 |
}
|
|
|
413 |
|
|
|
414 |
/* ---------------- Driver procedures ---------------- */
|
|
|
415 |
|
|
|
416 |
private int
|
|
|
417 |
plane_open_device(gx_device *dev)
|
|
|
418 |
{
|
|
|
419 |
gx_device_plane_extract * const edev = (gx_device_plane_extract *)dev;
|
|
|
420 |
gx_device * const plane_dev = edev->plane_dev;
|
|
|
421 |
int plane_depth = plane_dev->color_info.depth;
|
|
|
422 |
const gx_device_memory * const mdproto =
|
|
|
423 |
gdev_mem_device_for_bits(plane_depth);
|
|
|
424 |
|
|
|
425 |
edev->plane_white = gx_device_white(plane_dev);
|
|
|
426 |
edev->plane_mask = (1 << plane_depth) - 1;
|
|
|
427 |
edev->plane_dev_is_memory = mdproto != 0 &&
|
|
|
428 |
dev_proc(plane_dev, copy_color) == dev_proc(mdproto, copy_color);
|
|
|
429 |
/* We don't set or clear any_marks here: see ...init above. */
|
|
|
430 |
return 0;
|
|
|
431 |
}
|
|
|
432 |
|
|
|
433 |
private int
|
|
|
434 |
plane_fill_rectangle(gx_device *dev,
|
|
|
435 |
int x, int y, int w, int h, gx_color_index color)
|
|
|
436 |
{
|
|
|
437 |
gx_device_plane_extract * const edev = (gx_device_plane_extract *)dev;
|
|
|
438 |
gx_device * const plane_dev = edev->plane_dev;
|
|
|
439 |
gx_color_index pixel = COLOR_PIXEL(edev, color);
|
|
|
440 |
|
|
|
441 |
if (pixel != edev->plane_white)
|
|
|
442 |
edev->any_marks = true;
|
|
|
443 |
else if (!edev->any_marks)
|
|
|
444 |
return 0;
|
|
|
445 |
return dev_proc(plane_dev, fill_rectangle)
|
|
|
446 |
(plane_dev, x, y, w, h, pixel);
|
|
|
447 |
}
|
|
|
448 |
|
|
|
449 |
private int
|
|
|
450 |
plane_copy_mono(gx_device *dev,
|
|
|
451 |
const byte *data, int data_x, int raster, gx_bitmap_id id,
|
|
|
452 |
int x, int y, int w, int h,
|
|
|
453 |
gx_color_index color0, gx_color_index color1)
|
|
|
454 |
{
|
|
|
455 |
gx_device_plane_extract * const edev = (gx_device_plane_extract *)dev;
|
|
|
456 |
gx_device * const plane_dev = edev->plane_dev;
|
|
|
457 |
gx_color_index pixel0 = TRANS_COLOR_PIXEL(edev, color0);
|
|
|
458 |
gx_color_index pixel1 = TRANS_COLOR_PIXEL(edev, color1);
|
|
|
459 |
|
|
|
460 |
if (pixel0 == pixel1)
|
|
|
461 |
return plane_fill_rectangle(dev, x, y, w, h, color0);
|
|
|
462 |
if ((pixel0 == edev->plane_white || pixel0 == gx_no_color_index) &&
|
|
|
463 |
(pixel1 == edev->plane_white || pixel1 == gx_no_color_index)) {
|
|
|
464 |
/* This operation will only write white. */
|
|
|
465 |
if (!edev->any_marks)
|
|
|
466 |
return 0;
|
|
|
467 |
} else
|
|
|
468 |
edev->any_marks = true;
|
|
|
469 |
return dev_proc(plane_dev, copy_mono)
|
|
|
470 |
(plane_dev, data, data_x, raster, id, x, y, w, h, pixel0, pixel1);
|
|
|
471 |
}
|
|
|
472 |
|
|
|
473 |
private int
|
|
|
474 |
plane_copy_color(gx_device *dev,
|
|
|
475 |
const byte *data, int data_x, int raster, gx_bitmap_id id,
|
|
|
476 |
int x, int y, int w, int h)
|
|
|
477 |
{
|
|
|
478 |
gx_device_plane_extract * const edev = (gx_device_plane_extract *)dev;
|
|
|
479 |
gx_device * const plane_dev = edev->plane_dev;
|
|
|
480 |
tiling_state_t state;
|
|
|
481 |
long buf[COPY_COLOR_BUF_SIZE / sizeof(long)];
|
|
|
482 |
int code;
|
|
|
483 |
|
|
|
484 |
if (edev->plane_dev_is_memory) {
|
|
|
485 |
/* Reduce the source directly into the plane device. */
|
|
|
486 |
gx_device_memory * const mdev = (gx_device_memory *)plane_dev;
|
|
|
487 |
|
|
|
488 |
fit_copy(edev, data, data_x, raster, id, x, y, w, h);
|
|
|
489 |
code = begin_tiling(&state, edev, data, data_x, raster, w, h,
|
|
|
490 |
scan_line_base(mdev, y), max_uint, false);
|
|
|
491 |
if (code < 0)
|
|
|
492 |
return code;
|
|
|
493 |
state.dest_x = x;
|
|
|
494 |
state.buffer.raster = mdev->raster;
|
|
|
495 |
extract_partial_tile(&state);
|
|
|
496 |
end_tiling(&state);
|
|
|
497 |
edev->any_marks = true;
|
|
|
498 |
return 0;
|
|
|
499 |
}
|
|
|
500 |
code = begin_tiling(&state, edev, data, data_x, raster,
|
|
|
501 |
w, h, (byte *)buf, sizeof(buf), true);
|
|
|
502 |
if (code < 0)
|
|
|
503 |
return code;
|
|
|
504 |
do {
|
|
|
505 |
extract_partial_tile(&state);
|
|
|
506 |
code = dev_proc(plane_dev, copy_color)
|
|
|
507 |
(plane_dev, state.buffer.data, 0, state.buffer.raster,
|
|
|
508 |
gx_no_bitmap_id, x + state.offset.x, y + state.offset.y,
|
|
|
509 |
state.size.x, state.size.y);
|
|
|
510 |
} while (code >= 0 && next_tile(&state));
|
|
|
511 |
end_tiling(&state);
|
|
|
512 |
edev->any_marks = true;
|
|
|
513 |
return code;
|
|
|
514 |
}
|
|
|
515 |
|
|
|
516 |
private int
|
|
|
517 |
plane_copy_alpha(gx_device *dev, const byte *data, int data_x,
|
|
|
518 |
int raster, gx_bitmap_id id, int x, int y, int w, int h,
|
|
|
519 |
gx_color_index color, int depth)
|
|
|
520 |
{
|
|
|
521 |
gx_device_plane_extract * const edev = (gx_device_plane_extract *)dev;
|
|
|
522 |
gx_device * const plane_dev = edev->plane_dev;
|
|
|
523 |
gx_color_index pixel = COLOR_PIXEL(edev, color);
|
|
|
524 |
|
|
|
525 |
if (pixel != edev->plane_white)
|
|
|
526 |
edev->any_marks = true;
|
|
|
527 |
else if (!edev->any_marks)
|
|
|
528 |
return 0;
|
|
|
529 |
return dev_proc(plane_dev, copy_alpha)
|
|
|
530 |
(plane_dev, data, data_x, raster, id, x, y, w, h, pixel, depth);
|
|
|
531 |
}
|
|
|
532 |
|
|
|
533 |
private int
|
|
|
534 |
plane_fill_path(gx_device *dev,
|
|
|
535 |
const gs_imager_state *pis, gx_path *ppath,
|
|
|
536 |
const gx_fill_params *params,
|
|
|
537 |
const gx_drawing_color *pdevc, const gx_clip_path *pcpath)
|
|
|
538 |
{
|
|
|
539 |
gx_device_plane_extract * const edev = (gx_device_plane_extract *)dev;
|
|
|
540 |
gx_device * const plane_dev = edev->plane_dev;
|
|
|
541 |
gs_logical_operation_t lop_orig =
|
|
|
542 |
gs_current_logical_op((const gs_state *)pis);
|
|
|
543 |
gs_logical_operation_t lop = lop_orig;
|
|
|
544 |
gx_device_color dcolor;
|
|
|
545 |
|
|
|
546 |
switch (reduce_drawing_color(&dcolor, edev, pdevc, &lop)) {
|
|
|
547 |
case REDUCE_SKIP:
|
|
|
548 |
return 0;
|
|
|
549 |
case REDUCE_DRAW: {
|
|
|
550 |
gs_imager_state lopis;
|
|
|
551 |
const gs_imager_state *pis_draw = pis;
|
|
|
552 |
|
|
|
553 |
if (lop != lop_orig) {
|
|
|
554 |
lopis = *pis;
|
|
|
555 |
gs_set_logical_op((gs_state *)&lopis, lop);
|
|
|
556 |
pis_draw = &lopis;
|
|
|
557 |
}
|
|
|
558 |
return dev_proc(plane_dev, fill_path)
|
|
|
559 |
(plane_dev, pis_draw, ppath, params, &dcolor, pcpath);
|
|
|
560 |
}
|
|
|
561 |
default /*REDUCE_FAILED*/:
|
|
|
562 |
return gx_default_fill_path(dev, pis, ppath, params, pdevc, pcpath);
|
|
|
563 |
}
|
|
|
564 |
}
|
|
|
565 |
|
|
|
566 |
private int
|
|
|
567 |
plane_stroke_path(gx_device *dev,
|
|
|
568 |
const gs_imager_state *pis, gx_path *ppath,
|
|
|
569 |
const gx_stroke_params *params,
|
|
|
570 |
const gx_drawing_color *pdevc, const gx_clip_path *pcpath)
|
|
|
571 |
{
|
|
|
572 |
gx_device_plane_extract * const edev = (gx_device_plane_extract *)dev;
|
|
|
573 |
gx_device * const plane_dev = edev->plane_dev;
|
|
|
574 |
gs_logical_operation_t lop_orig =
|
|
|
575 |
gs_current_logical_op((const gs_state *)pis);
|
|
|
576 |
gs_logical_operation_t lop = lop_orig;
|
|
|
577 |
gx_device_color dcolor;
|
|
|
578 |
|
|
|
579 |
switch (reduce_drawing_color(&dcolor, edev, pdevc, &lop)) {
|
|
|
580 |
case REDUCE_SKIP:
|
|
|
581 |
return 0;
|
|
|
582 |
case REDUCE_DRAW: {
|
|
|
583 |
gs_imager_state lopis;
|
|
|
584 |
const gs_imager_state *pis_draw = pis;
|
|
|
585 |
|
|
|
586 |
if (lop != lop_orig) {
|
|
|
587 |
lopis = *pis;
|
|
|
588 |
gs_set_logical_op((gs_state *)&lopis, lop);
|
|
|
589 |
pis_draw = &lopis;
|
|
|
590 |
}
|
|
|
591 |
return dev_proc(plane_dev, stroke_path)
|
|
|
592 |
(plane_dev, pis_draw, ppath, params, &dcolor, pcpath);
|
|
|
593 |
}
|
|
|
594 |
default /*REDUCE_FAILED*/:
|
|
|
595 |
return gx_default_stroke_path(dev, pis, ppath, params, pdevc, pcpath);
|
|
|
596 |
}
|
|
|
597 |
}
|
|
|
598 |
|
|
|
599 |
private int
|
|
|
600 |
plane_fill_mask(gx_device *dev,
|
|
|
601 |
const byte *data, int data_x, int raster, gx_bitmap_id id,
|
|
|
602 |
int x, int y, int w, int h,
|
|
|
603 |
const gx_drawing_color *pdcolor, int depth,
|
|
|
604 |
gs_logical_operation_t lop, const gx_clip_path *pcpath)
|
|
|
605 |
{
|
|
|
606 |
gx_device_plane_extract * const edev = (gx_device_plane_extract *)dev;
|
|
|
607 |
gx_device * const plane_dev = edev->plane_dev;
|
|
|
608 |
gx_device_color dcolor;
|
|
|
609 |
|
|
|
610 |
switch (reduce_drawing_color(&dcolor, edev, pdcolor, &lop)) {
|
|
|
611 |
case REDUCE_SKIP:
|
|
|
612 |
return 0;
|
|
|
613 |
case REDUCE_DRAW:
|
|
|
614 |
return dev_proc(plane_dev, fill_mask)
|
|
|
615 |
(plane_dev, data, data_x, raster, gx_no_bitmap_id, x, y, w, h,
|
|
|
616 |
&dcolor, depth, lop, pcpath);
|
|
|
617 |
default /*REDUCE_FAILED*/:
|
|
|
618 |
return gx_default_fill_mask(dev, data, data_x, raster, gx_no_bitmap_id,
|
|
|
619 |
x, y, w, h, &dcolor, depth, lop, pcpath);
|
|
|
620 |
}
|
|
|
621 |
}
|
|
|
622 |
|
|
|
623 |
private int
|
|
|
624 |
plane_fill_parallelogram(gx_device * dev,
|
|
|
625 |
fixed px, fixed py, fixed ax, fixed ay, fixed bx, fixed by,
|
|
|
626 |
const gx_drawing_color * pdcolor, gs_logical_operation_t lop)
|
|
|
627 |
{
|
|
|
628 |
gx_device_plane_extract * const edev = (gx_device_plane_extract *)dev;
|
|
|
629 |
gx_device * const plane_dev = edev->plane_dev;
|
|
|
630 |
gx_device_color dcolor;
|
|
|
631 |
|
|
|
632 |
switch (reduce_drawing_color(&dcolor, edev, pdcolor, &lop)) {
|
|
|
633 |
case REDUCE_SKIP:
|
|
|
634 |
return 0;
|
|
|
635 |
case REDUCE_DRAW:
|
|
|
636 |
return dev_proc(plane_dev, fill_parallelogram)
|
|
|
637 |
(plane_dev, px, py, ax, ay, bx, by, &dcolor, lop);
|
|
|
638 |
default /*REDUCE_FAILED*/:
|
|
|
639 |
return gx_default_fill_parallelogram(dev, px, py, ax, ay, bx, by,
|
|
|
640 |
pdcolor, lop);
|
|
|
641 |
}
|
|
|
642 |
}
|
|
|
643 |
|
|
|
644 |
private int
|
|
|
645 |
plane_fill_triangle(gx_device * dev,
|
|
|
646 |
fixed px, fixed py, fixed ax, fixed ay, fixed bx, fixed by,
|
|
|
647 |
const gx_drawing_color * pdcolor, gs_logical_operation_t lop)
|
|
|
648 |
{
|
|
|
649 |
gx_device_plane_extract * const edev = (gx_device_plane_extract *)dev;
|
|
|
650 |
gx_device * const plane_dev = edev->plane_dev;
|
|
|
651 |
gx_device_color dcolor;
|
|
|
652 |
|
|
|
653 |
switch (reduce_drawing_color(&dcolor, edev, pdcolor, &lop)) {
|
|
|
654 |
case REDUCE_SKIP:
|
|
|
655 |
return 0;
|
|
|
656 |
case REDUCE_DRAW:
|
|
|
657 |
return dev_proc(plane_dev, fill_triangle)
|
|
|
658 |
(plane_dev, px, py, ax, ay, bx, by, &dcolor, lop);
|
|
|
659 |
default /*REDUCE_FAILED*/:
|
|
|
660 |
return gx_default_fill_triangle(dev, px, py, ax, ay, bx, by,
|
|
|
661 |
pdcolor, lop);
|
|
|
662 |
}
|
|
|
663 |
}
|
|
|
664 |
|
|
|
665 |
private int
|
|
|
666 |
plane_strip_tile_rectangle(gx_device *dev,
|
|
|
667 |
const gx_strip_bitmap *tiles, int x, int y, int w, int h,
|
|
|
668 |
gx_color_index color0, gx_color_index color1,
|
|
|
669 |
int phase_x, int phase_y)
|
|
|
670 |
{
|
|
|
671 |
gx_device_plane_extract * const edev = (gx_device_plane_extract *)dev;
|
|
|
672 |
gx_device * const plane_dev = edev->plane_dev;
|
|
|
673 |
gx_color_index pixel0 = TRANS_COLOR_PIXEL(edev, color0);
|
|
|
674 |
gx_color_index pixel1 = TRANS_COLOR_PIXEL(edev, color1);
|
|
|
675 |
|
|
|
676 |
if (pixel0 == pixel1) {
|
|
|
677 |
if (pixel0 != gx_no_color_index)
|
|
|
678 |
return plane_fill_rectangle(dev, x, y, w, h, color0);
|
|
|
679 |
/* The tile is a pixmap rather than a bitmap. */
|
|
|
680 |
/* We should use the default implementation if it is small.... */
|
|
|
681 |
{
|
|
|
682 |
gx_strip_bitmap plane_tile;
|
|
|
683 |
tiling_state_t state;
|
|
|
684 |
long buf[TILE_RECTANGLE_BUF_SIZE / sizeof(long)];
|
|
|
685 |
int code = begin_tiling(&state, edev, tiles->data, 0, tiles->raster,
|
|
|
686 |
tiles->size.x, tiles->size.y,
|
|
|
687 |
(byte *)buf, sizeof(buf), false);
|
|
|
688 |
|
|
|
689 |
if (code < 0)
|
|
|
690 |
return gx_default_strip_tile_rectangle(dev, tiles, x, y, w, h,
|
|
|
691 |
color0, color1, phase_x, phase_y);
|
|
|
692 |
extract_partial_tile(&state);
|
|
|
693 |
plane_tile = *tiles;
|
|
|
694 |
plane_tile.data = state.buffer.data;
|
|
|
695 |
plane_tile.raster = state.buffer.raster;
|
|
|
696 |
plane_tile.id = gx_no_bitmap_id;
|
|
|
697 |
code = dev_proc(plane_dev, strip_tile_rectangle)
|
|
|
698 |
(plane_dev, &plane_tile, x, y, w, h, pixel0, pixel1,
|
|
|
699 |
phase_x, phase_y);
|
|
|
700 |
end_tiling(&state);
|
|
|
701 |
edev->any_marks = true;
|
|
|
702 |
return code;
|
|
|
703 |
}
|
|
|
704 |
}
|
|
|
705 |
if ((pixel0 == edev->plane_white || pixel0 == gx_no_color_index) &&
|
|
|
706 |
(pixel1 == edev->plane_white || pixel1 == gx_no_color_index)) {
|
|
|
707 |
/* This operation will only write white. */
|
|
|
708 |
if (!edev->any_marks)
|
|
|
709 |
return 0;
|
|
|
710 |
} else
|
|
|
711 |
edev->any_marks = true;
|
|
|
712 |
return dev_proc(plane_dev, strip_tile_rectangle)
|
|
|
713 |
(plane_dev, tiles, x, y, w, h, pixel0, pixel1, phase_x, phase_y);
|
|
|
714 |
}
|
|
|
715 |
|
|
|
716 |
private int
|
|
|
717 |
plane_strip_copy_rop(gx_device *dev,
|
|
|
718 |
const byte *sdata, int sourcex, uint sraster, gx_bitmap_id id,
|
|
|
719 |
const gx_color_index *scolors,
|
|
|
720 |
const gx_strip_bitmap *textures, const gx_color_index *tcolors,
|
|
|
721 |
int x, int y, int w, int h,
|
|
|
722 |
int phase_x, int phase_y, gs_logical_operation_t lop)
|
|
|
723 |
{
|
|
|
724 |
gx_device_plane_extract * const edev = (gx_device_plane_extract *)dev;
|
|
|
725 |
gx_device * const plane_dev = edev->plane_dev;
|
|
|
726 |
gs_rop3_t rop = lop_rop(lop);
|
|
|
727 |
struct crp_ {
|
|
|
728 |
gx_color_index pixels[2];
|
|
|
729 |
gx_color_index *colors;
|
|
|
730 |
tiling_state_t state;
|
|
|
731 |
} source, texture;
|
|
|
732 |
long sbuf[COPY_ROP_SOURCE_BUF_SIZE / sizeof(long)];
|
|
|
733 |
long tbuf[COPY_ROP_TEXTURE_BUF_SIZE / sizeof(long)];
|
|
|
734 |
const byte *plane_source;
|
|
|
735 |
uint plane_raster = 0xbaadf00d; /* Initialize against indeterminizm. */
|
|
|
736 |
gx_strip_bitmap plane_texture;
|
|
|
737 |
const gx_strip_bitmap *plane_textures = NULL;
|
|
|
738 |
int code;
|
|
|
739 |
|
|
|
740 |
/* We should do better than this on transparency.... */
|
|
|
741 |
if (lop & (lop_S_transparent | lop_T_transparent))
|
|
|
742 |
return gx_default_strip_copy_rop(dev, sdata, sourcex, sraster, id,
|
|
|
743 |
scolors, textures, tcolors,
|
|
|
744 |
x, y, w, h, phase_x, phase_y, lop);
|
|
|
745 |
if (!rop3_uses_S(rop)) {
|
|
|
746 |
sdata = 0;
|
|
|
747 |
source.colors = 0;
|
|
|
748 |
} else if (scolors) {
|
|
|
749 |
source.pixels[0] = COLOR_PIXEL(edev, scolors[0]);
|
|
|
750 |
source.pixels[1] = COLOR_PIXEL(edev, scolors[1]);
|
|
|
751 |
if (source.pixels[0] == source.pixels[1])
|
|
|
752 |
sdata = 0;
|
|
|
753 |
source.colors = source.pixels;
|
|
|
754 |
}
|
|
|
755 |
else
|
|
|
756 |
source.colors = 0;
|
|
|
757 |
if (!rop3_uses_T(rop)) {
|
|
|
758 |
textures = 0;
|
|
|
759 |
texture.colors = 0;
|
|
|
760 |
} else if (tcolors) {
|
|
|
761 |
texture.pixels[0] = COLOR_PIXEL(edev, tcolors[0]);
|
|
|
762 |
texture.pixels[1] = COLOR_PIXEL(edev, tcolors[1]);
|
|
|
763 |
if (texture.pixels[0] == texture.pixels[1])
|
|
|
764 |
textures = 0;
|
|
|
765 |
texture.colors = texture.pixels;
|
|
|
766 |
}
|
|
|
767 |
else
|
|
|
768 |
texture.colors = 0;
|
|
|
769 |
if (sdata) {
|
|
|
770 |
code = begin_tiling(&source.state, edev, sdata, sourcex, sraster, w, y,
|
|
|
771 |
(byte *)sbuf, sizeof(sbuf), true);
|
|
|
772 |
if (code < 0)
|
|
|
773 |
return gx_default_strip_copy_rop(dev, sdata, sourcex, sraster, id,
|
|
|
774 |
scolors, textures, tcolors,
|
|
|
775 |
x, y, w, h, phase_x, phase_y, lop);
|
|
|
776 |
plane_source = source.state.buffer.data;
|
|
|
777 |
plane_raster = source.state.buffer.raster;
|
|
|
778 |
} else
|
|
|
779 |
plane_source = 0;
|
|
|
780 |
if (textures) {
|
|
|
781 |
code = begin_tiling(&texture.state, edev, textures->data, 0,
|
|
|
782 |
textures->raster, textures->size.x,
|
|
|
783 |
textures->size.y, (byte *)tbuf, sizeof(tbuf),
|
|
|
784 |
false);
|
|
|
785 |
if (code < 0) {
|
|
|
786 |
if (plane_source)
|
|
|
787 |
end_tiling(&source.state);
|
|
|
788 |
return code;
|
|
|
789 |
}
|
|
|
790 |
plane_texture = *textures;
|
|
|
791 |
plane_texture.data = texture.state.buffer.data;
|
|
|
792 |
plane_texture.raster = texture.state.buffer.raster;
|
|
|
793 |
plane_textures = &plane_texture;
|
|
|
794 |
}
|
|
|
795 |
if (textures)
|
|
|
796 |
extract_partial_tile(&texture.state);
|
|
|
797 |
do {
|
|
|
798 |
if (sdata)
|
|
|
799 |
extract_partial_tile(&source.state);
|
|
|
800 |
code = dev_proc(plane_dev, strip_copy_rop)
|
|
|
801 |
(plane_dev, plane_source, sourcex, plane_raster, gx_no_bitmap_id,
|
|
|
802 |
source.colors, plane_textures, texture.colors,
|
|
|
803 |
x, y, w, h, phase_x, phase_y, lop);
|
|
|
804 |
} while (code >= 0 && sdata && next_tile(&source.state));
|
|
|
805 |
if (textures)
|
|
|
806 |
end_tiling(&texture.state);
|
|
|
807 |
if (sdata)
|
|
|
808 |
end_tiling(&source.state);
|
|
|
809 |
return code;
|
|
|
810 |
}
|
|
|
811 |
|
|
|
812 |
/* ---------------- Images ---------------- */
|
|
|
813 |
|
|
|
814 |
/* Define the state for image rendering. */
|
|
|
815 |
typedef struct plane_image_enum_s {
|
|
|
816 |
gx_image_enum_common;
|
|
|
817 |
gs_memory_t *memory;
|
|
|
818 |
gx_image_enum_common_t *info; /* plane device enumerator */
|
|
|
819 |
const gs_imager_state *pis; /* original imager state */
|
|
|
820 |
gs_imager_state *pis_image; /* modified imager state */
|
|
|
821 |
} plane_image_enum_t;
|
|
|
822 |
gs_private_st_suffix_add3(st_plane_image_enum, plane_image_enum_t,
|
|
|
823 |
"plane_image_enum_t", plane_image_enum_enum_ptrs,
|
|
|
824 |
plane_image_enum_reloc_ptrs, st_gx_image_enum_common, info, pis, pis_image);
|
|
|
825 |
|
|
|
826 |
/*
|
|
|
827 |
* Reduce drawing colors returned by color mapping. Note that these
|
|
|
828 |
* assume that the call of reduce_drawing_color will not fail:
|
|
|
829 |
* plane_begin_typed_image must ensure this.
|
|
|
830 |
*
|
|
|
831 |
* In the imager state passed to these procedures, the client data is
|
|
|
832 |
* the plane_image_enum_t.
|
|
|
833 |
*/
|
|
|
834 |
|
|
|
835 |
private void
|
|
|
836 |
plane_cmap_gray(frac gray, gx_device_color * pdc,
|
|
|
837 |
const gs_imager_state *pis_image, gx_device *dev, gs_color_select_t select)
|
|
|
838 |
{
|
|
|
839 |
const plane_image_enum_t *ppie =
|
|
|
840 |
(const plane_image_enum_t *)pis_image->client_data;
|
|
|
841 |
gx_device_plane_extract * const edev =
|
|
|
842 |
(gx_device_plane_extract *)ppie->dev;
|
|
|
843 |
gs_logical_operation_t lop = gs_current_logical_op_inline(pis_image);
|
|
|
844 |
gx_device_color dcolor;
|
|
|
845 |
|
|
|
846 |
gx_remap_concrete_gray(gray, &dcolor, ppie->pis,
|
|
|
847 |
(gx_device *)edev, select);
|
|
|
848 |
reduce_drawing_color(pdc, edev, &dcolor, &lop);
|
|
|
849 |
}
|
|
|
850 |
private void
|
|
|
851 |
plane_cmap_rgb(frac r, frac g, frac b, gx_device_color * pdc,
|
|
|
852 |
const gs_imager_state *pis_image, gx_device *dev, gs_color_select_t select)
|
|
|
853 |
{
|
|
|
854 |
const plane_image_enum_t *ppie =
|
|
|
855 |
(const plane_image_enum_t *)pis_image->client_data;
|
|
|
856 |
gx_device_plane_extract * const edev =
|
|
|
857 |
(gx_device_plane_extract *)ppie->dev;
|
|
|
858 |
gs_logical_operation_t lop = gs_current_logical_op_inline(pis_image);
|
|
|
859 |
gx_device_color dcolor;
|
|
|
860 |
|
|
|
861 |
gx_remap_concrete_rgb(r, g, b, &dcolor, ppie->pis,
|
|
|
862 |
(gx_device *)edev, select);
|
|
|
863 |
reduce_drawing_color(pdc, edev, &dcolor, &lop);
|
|
|
864 |
}
|
|
|
865 |
private void
|
|
|
866 |
plane_cmap_cmyk(frac c, frac m, frac y, frac k, gx_device_color * pdc,
|
|
|
867 |
const gs_imager_state *pis_image, gx_device *dev, gs_color_select_t select)
|
|
|
868 |
{
|
|
|
869 |
const plane_image_enum_t *ppie =
|
|
|
870 |
(const plane_image_enum_t *)pis_image->client_data;
|
|
|
871 |
gx_device_plane_extract * const edev =
|
|
|
872 |
(gx_device_plane_extract *)ppie->dev;
|
|
|
873 |
gs_logical_operation_t lop = gs_current_logical_op_inline(pis_image);
|
|
|
874 |
gx_device_color dcolor;
|
|
|
875 |
|
|
|
876 |
gx_remap_concrete_cmyk(c, m, y, k, &dcolor, ppie->pis,
|
|
|
877 |
(gx_device *)edev, select);
|
|
|
878 |
reduce_drawing_color(pdc, edev, &dcolor, &lop);
|
|
|
879 |
}
|
|
|
880 |
private void
|
|
|
881 |
plane_cmap_rgb_alpha(frac r, frac g, frac b, frac alpha, gx_device_color * pdc,
|
|
|
882 |
const gs_imager_state *pis_image, gx_device *dev, gs_color_select_t select)
|
|
|
883 |
{
|
|
|
884 |
const plane_image_enum_t *ppie =
|
|
|
885 |
(const plane_image_enum_t *)pis_image->client_data;
|
|
|
886 |
gx_device_plane_extract * const edev =
|
|
|
887 |
(gx_device_plane_extract *)ppie->dev;
|
|
|
888 |
gs_logical_operation_t lop = gs_current_logical_op_inline(pis_image);
|
|
|
889 |
gx_device_color dcolor;
|
|
|
890 |
|
|
|
891 |
gx_remap_concrete_rgb_alpha(r, g, b, alpha, &dcolor, ppie->pis,
|
|
|
892 |
(gx_device *)edev, select);
|
|
|
893 |
reduce_drawing_color(pdc, edev, &dcolor, &lop);
|
|
|
894 |
}
|
|
|
895 |
private bool
|
|
|
896 |
plane_cmap_is_halftoned(const gs_imager_state *pis_image, gx_device *dev)
|
|
|
897 |
{
|
|
|
898 |
return false;
|
|
|
899 |
}
|
|
|
900 |
|
|
|
901 |
private const gx_color_map_procs plane_color_map_procs = {
|
|
|
902 |
plane_cmap_gray, plane_cmap_rgb, plane_cmap_cmyk, plane_cmap_rgb_alpha,
|
|
|
903 |
NULL, NULL, plane_cmap_is_halftoned
|
|
|
904 |
};
|
|
|
905 |
private const gx_color_map_procs *
|
|
|
906 |
plane_get_cmap_procs(const gs_imager_state *pis, const gx_device *dev)
|
|
|
907 |
{
|
|
|
908 |
return &plane_color_map_procs;
|
|
|
909 |
}
|
|
|
910 |
|
|
|
911 |
/* Define the image processing procedures. */
|
|
|
912 |
private image_enum_proc_plane_data(plane_image_plane_data);
|
|
|
913 |
private image_enum_proc_end_image(plane_image_end_image);
|
|
|
914 |
private const gx_image_enum_procs_t plane_image_enum_procs = {
|
|
|
915 |
plane_image_plane_data, plane_image_end_image
|
|
|
916 |
};
|
|
|
917 |
|
|
|
918 |
private int
|
|
|
919 |
plane_begin_typed_image(gx_device * dev,
|
|
|
920 |
const gs_imager_state * pis, const gs_matrix * pmat,
|
|
|
921 |
const gs_image_common_t * pic, const gs_int_rect * prect,
|
|
|
922 |
const gx_drawing_color * pdcolor, const gx_clip_path * pcpath,
|
|
|
923 |
gs_memory_t * memory, gx_image_enum_common_t ** pinfo)
|
|
|
924 |
{
|
|
|
925 |
/*
|
|
|
926 |
* For images, we intercept the imager state's cmap_procs and apply
|
|
|
927 |
* reduce_drawing_color to the colors as they are returned to the image
|
|
|
928 |
* processing code. For reasons explained above, we can't do this in
|
|
|
929 |
* some cases of RasterOp that include transparency.
|
|
|
930 |
*/
|
|
|
931 |
gx_device_plane_extract * const edev = (gx_device_plane_extract *)dev;
|
|
|
932 |
gs_logical_operation_t lop = gs_current_logical_op((const gs_state *)pis);
|
|
|
933 |
const gs_pixel_image_t *pim;
|
|
|
934 |
plane_image_enum_t *info = 0;
|
|
|
935 |
gs_imager_state *pis_image = 0;
|
|
|
936 |
gx_device_color dcolor;
|
|
|
937 |
bool uses_color = false;
|
|
|
938 |
int code;
|
|
|
939 |
|
|
|
940 |
/* We can only handle a limited set of image types. */
|
|
|
941 |
switch (pic->type->index) {
|
|
|
942 |
case 1: {
|
|
|
943 |
const gs_image1_t * const pim1 = (const gs_image1_t *)pic;
|
|
|
944 |
|
|
|
945 |
if (pim1->Alpha != gs_image_alpha_none)
|
|
|
946 |
goto fail;
|
|
|
947 |
uses_color = pim1->ImageMask;
|
|
|
948 |
break;
|
|
|
949 |
}
|
|
|
950 |
case 3:
|
|
|
951 |
case 4:
|
|
|
952 |
break;
|
|
|
953 |
default:
|
|
|
954 |
goto fail;
|
|
|
955 |
}
|
|
|
956 |
pim = (const gs_pixel_image_t *)pic;
|
|
|
957 |
if ((lop & lop_S_transparent) ||
|
|
|
958 |
((uses_color || pim->CombineWithColor) && (lop & lop_T_transparent))
|
|
|
959 |
)
|
|
|
960 |
goto fail;
|
|
|
961 |
if (uses_color || (pim->CombineWithColor && lop_uses_T(lop))) {
|
|
|
962 |
if (reduce_drawing_color(&dcolor, edev, pdcolor, &lop) ==
|
|
|
963 |
REDUCE_FAILED)
|
|
|
964 |
goto fail;
|
|
|
965 |
} else {
|
|
|
966 |
/*
|
|
|
967 |
* The drawing color won't be used, but if RasterOp is involved,
|
|
|
968 |
* it may still be accessed in some anomalous cases.
|
|
|
969 |
*/
|
|
|
970 |
set_nonclient_dev_color(&dcolor, (gx_color_index)0);
|
|
|
971 |
}
|
|
|
972 |
info = gs_alloc_struct(memory, plane_image_enum_t, &st_plane_image_enum,
|
|
|
973 |
"plane_image_begin_typed(info)");
|
|
|
974 |
pis_image = gs_imager_state_copy(pis, memory);
|
|
|
975 |
if (pis_image == 0 || info == 0)
|
|
|
976 |
goto fail;
|
|
|
977 |
*pis_image = *pis;
|
|
|
978 |
pis_image->client_data = info;
|
|
|
979 |
pis_image->get_cmap_procs = plane_get_cmap_procs;
|
|
|
980 |
code = dev_proc(edev->plane_dev, begin_typed_image)
|
|
|
981 |
(edev->plane_dev, pis_image, pmat, pic, prect,
|
|
|
982 |
&dcolor, pcpath, memory, &info->info);
|
|
|
983 |
if (code < 0)
|
|
|
984 |
goto fail;
|
|
|
985 |
*((gx_image_enum_common_t *)info) = *info->info;
|
|
|
986 |
info->procs = &plane_image_enum_procs;
|
|
|
987 |
info->dev = (gx_device *)edev;
|
|
|
988 |
info->id = gs_next_ids(memory, 1);
|
|
|
989 |
info->memory = memory;
|
|
|
990 |
info->pis = pis;
|
|
|
991 |
info->pis_image = pis_image;
|
|
|
992 |
*pinfo = (gx_image_enum_common_t *)info;
|
|
|
993 |
return code;
|
|
|
994 |
fail:
|
|
|
995 |
gs_free_object(memory, pis_image, "plane_image_begin_typed(pis_image)");
|
|
|
996 |
gs_free_object(memory, info, "plane_image_begin_typed(info)");
|
|
|
997 |
return gx_default_begin_typed_image(dev, pis, pmat, pic, prect,
|
|
|
998 |
pdcolor, pcpath, memory, pinfo);
|
|
|
999 |
}
|
|
|
1000 |
|
|
|
1001 |
private int
|
|
|
1002 |
plane_image_plane_data(gx_image_enum_common_t * info,
|
|
|
1003 |
const gx_image_plane_t * planes, int height,
|
|
|
1004 |
int *rows_used)
|
|
|
1005 |
{
|
|
|
1006 |
plane_image_enum_t * const ppie = (plane_image_enum_t *)info;
|
|
|
1007 |
|
|
|
1008 |
return gx_image_plane_data_rows(ppie->info, planes, height, rows_used);
|
|
|
1009 |
}
|
|
|
1010 |
|
|
|
1011 |
private int
|
|
|
1012 |
plane_image_end_image(gx_image_enum_common_t * info, bool draw_last)
|
|
|
1013 |
{
|
|
|
1014 |
plane_image_enum_t * const ppie = (plane_image_enum_t *)info;
|
|
|
1015 |
int code = gx_image_end(ppie->info, draw_last);
|
|
|
1016 |
|
|
|
1017 |
gs_free_object(ppie->memory, ppie->pis_image,
|
|
|
1018 |
"plane_image_end_image(pis_image)");
|
|
|
1019 |
gs_free_object(ppie->memory, info, "plane_image_end_image(info)");
|
|
|
1020 |
return code;
|
|
|
1021 |
}
|
|
|
1022 |
|
|
|
1023 |
/* ---------------- Reading back bits ---------------- */
|
|
|
1024 |
|
|
|
1025 |
private int
|
|
|
1026 |
plane_get_bits_rectangle(gx_device * dev, const gs_int_rect * prect,
|
|
|
1027 |
gs_get_bits_params_t * params, gs_int_rect ** unread)
|
|
|
1028 |
{
|
|
|
1029 |
gx_device_plane_extract * const edev = (gx_device_plane_extract *)dev;
|
|
|
1030 |
gx_device * const plane_dev = edev->plane_dev;
|
|
|
1031 |
int plane_index = edev->plane.index;
|
|
|
1032 |
gs_get_bits_options_t options = params->options;
|
|
|
1033 |
gs_get_bits_params_t plane_params;
|
|
|
1034 |
int plane;
|
|
|
1035 |
int code;
|
|
|
1036 |
|
|
|
1037 |
/*
|
|
|
1038 |
* The only real option that this device supports is single-plane
|
|
|
1039 |
* retrieval. However, for the default case of RasterOp, it must be
|
|
|
1040 |
* able to return chunky pixels in which the other components are
|
|
|
1041 |
* arbitrary (but might as well be zero).
|
|
|
1042 |
*/
|
|
|
1043 |
if ((options & GB_PACKING_PLANAR) && (options & GB_SELECT_PLANES)) {
|
|
|
1044 |
if (params->data[plane_index] == 0)
|
|
|
1045 |
return gx_default_get_bits_rectangle(dev, prect, params, unread);
|
|
|
1046 |
/* If the caller wants any other plane(s), punt. */
|
|
|
1047 |
for (plane = 0; plane < dev->color_info.num_components; ++plane)
|
|
|
1048 |
if (plane != plane_index && params->data[plane] != 0)
|
|
|
1049 |
return gx_default_get_bits_rectangle(dev, prect, params, unread);
|
|
|
1050 |
/* Pass the request on to the plane device. */
|
|
|
1051 |
plane_params = *params;
|
|
|
1052 |
plane_params.options =
|
|
|
1053 |
(options & ~(GB_PACKING_ALL | GB_SELECT_PLANES)) |
|
|
|
1054 |
GB_PACKING_CHUNKY;
|
|
|
1055 |
plane_params.data[0] = params->data[plane_index];
|
|
|
1056 |
code = dev_proc(plane_dev, get_bits_rectangle)
|
|
|
1057 |
(plane_dev, prect, &plane_params, unread);
|
|
|
1058 |
if (code >= 0) {
|
|
|
1059 |
*params = plane_params;
|
|
|
1060 |
params->options = (params->options & ~GB_PACKING_ALL) |
|
|
|
1061 |
(GB_PACKING_PLANAR | GB_SELECT_PLANES);
|
|
|
1062 |
params->data[plane_index] = params->data[0];
|
|
|
1063 |
for (plane = 0; plane < dev->color_info.num_components; ++plane)
|
|
|
1064 |
if (plane != plane_index)
|
|
|
1065 |
params->data[plane] = 0;
|
|
|
1066 |
}
|
|
|
1067 |
} else if (!(~options & (GB_COLORS_NATIVE | GB_ALPHA_NONE |
|
|
|
1068 |
GB_PACKING_CHUNKY | GB_RETURN_COPY |
|
|
|
1069 |
GB_ALIGN_STANDARD | GB_OFFSET_0 |
|
|
|
1070 |
GB_RASTER_STANDARD))) {
|
|
|
1071 |
/* Expand the plane into chunky pixels. */
|
|
|
1072 |
bits_plane_t dest, source;
|
|
|
1073 |
|
|
|
1074 |
dest.data.write = params->data[0];
|
|
|
1075 |
dest.raster =
|
|
|
1076 |
bitmap_raster((prect->q.x - prect->p.x) * dev->color_info.depth);
|
|
|
1077 |
dest.depth = edev->color_info.depth;
|
|
|
1078 |
dest.x = 0;
|
|
|
1079 |
|
|
|
1080 |
/* not source.data, source.raster, source.x */
|
|
|
1081 |
source.depth = plane_dev->color_info.depth;
|
|
|
1082 |
|
|
|
1083 |
plane_params = *params;
|
|
|
1084 |
plane_params.options = options &=
|
|
|
1085 |
(~(GB_COLORS_ALL | GB_ALPHA_ALL | GB_PACKING_ALL |
|
|
|
1086 |
GB_RETURN_ALL | GB_ALIGN_ALL | GB_OFFSET_ALL | GB_RASTER_ALL) |
|
|
|
1087 |
GB_COLORS_NATIVE | GB_ALPHA_NONE | GB_PACKING_CHUNKY |
|
|
|
1088 |
/* Try for a pointer return the first time. */
|
|
|
1089 |
GB_RETURN_POINTER |
|
|
|
1090 |
GB_ALIGN_STANDARD |
|
|
|
1091 |
(GB_OFFSET_0 | GB_OFFSET_ANY) |
|
|
|
1092 |
(GB_RASTER_STANDARD | GB_RASTER_ANY));
|
|
|
1093 |
plane_params.raster = gx_device_raster(plane_dev, true);
|
|
|
1094 |
code = dev_proc(plane_dev, get_bits_rectangle)
|
|
|
1095 |
(plane_dev, prect, &plane_params, unread);
|
|
|
1096 |
if (code >= 0) {
|
|
|
1097 |
/* Success, expand the plane into pixels. */
|
|
|
1098 |
source.data.read = plane_params.data[0];
|
|
|
1099 |
source.raster = plane_params.raster;
|
|
|
1100 |
source.x = params->x_offset;
|
|
|
1101 |
code = bits_expand_plane(&dest, &source, edev->plane.shift,
|
|
|
1102 |
prect->q.x - prect->p.x,
|
|
|
1103 |
prect->q.y - prect->p.y);
|
|
|
1104 |
}
|
|
|
1105 |
params->options = (options & ~GB_RETURN_POINTER) | GB_RETURN_COPY;
|
|
|
1106 |
} else
|
|
|
1107 |
return gx_default_get_bits_rectangle(dev, prect, params, unread);
|
|
|
1108 |
return code;
|
|
|
1109 |
}
|