2 |
- |
1 |
/* Copyright (C) 1995, 2000 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: gdevdrop.c,v 1.7 2002/08/22 07:12:28 henrys Exp $ */
|
|
|
18 |
/* Default and device-independent RasterOp algorithms */
|
|
|
19 |
#include "memory_.h"
|
|
|
20 |
#include "gx.h"
|
|
|
21 |
#include "gsbittab.h"
|
|
|
22 |
#include "gserrors.h"
|
|
|
23 |
#include "gsropt.h"
|
|
|
24 |
#include "gxcindex.h"
|
|
|
25 |
#include "gxdcolor.h"
|
|
|
26 |
#include "gxdevice.h"
|
|
|
27 |
#include "gxdevmem.h"
|
|
|
28 |
#include "gxdevrop.h"
|
|
|
29 |
#include "gxgetbit.h"
|
|
|
30 |
#include "gdevmem.h" /* for mem_default_strip_copy_rop prototype */
|
|
|
31 |
#include "gdevmrop.h"
|
|
|
32 |
|
|
|
33 |
/*
|
|
|
34 |
* Define the maximum amount of space we are willing to allocate for a
|
|
|
35 |
* multiple-row RasterOp buffer. (We are always willing to allocate
|
|
|
36 |
* one row, no matter how wide.)
|
|
|
37 |
*/
|
|
|
38 |
private const uint max_rop_bitmap = 1000;
|
|
|
39 |
|
|
|
40 |
/* ---------------- Debugging aids ---------------- */
|
|
|
41 |
|
|
|
42 |
#ifdef DEBUG
|
|
|
43 |
|
|
|
44 |
void
|
|
|
45 |
trace_copy_rop(const char *cname, gx_device * dev,
|
|
|
46 |
const byte * sdata, int sourcex, uint sraster, gx_bitmap_id id,
|
|
|
47 |
const gx_color_index * scolors,
|
|
|
48 |
const gx_strip_bitmap * textures,
|
|
|
49 |
const gx_color_index * tcolors,
|
|
|
50 |
int x, int y, int width, int height,
|
|
|
51 |
int phase_x, int phase_y, gs_logical_operation_t lop)
|
|
|
52 |
{
|
|
|
53 |
dlprintf4("%s: dev=0x%lx(%s) depth=%d\n",
|
|
|
54 |
cname, (ulong) dev, dev->dname, dev->color_info.depth);
|
|
|
55 |
dlprintf4(" source data=0x%lx x=%d raster=%u id=%lu colors=",
|
|
|
56 |
(ulong) sdata, sourcex, sraster, (ulong) id);
|
|
|
57 |
if (scolors)
|
|
|
58 |
dprintf2("(%lu,%lu);\n", scolors[0], scolors[1]);
|
|
|
59 |
else
|
|
|
60 |
dputs("none;\n");
|
|
|
61 |
if (textures)
|
|
|
62 |
dlprintf8(" textures=0x%lx size=%dx%d(%dx%d) raster=%u shift=%d(%d)",
|
|
|
63 |
(ulong) textures, textures->size.x, textures->size.y,
|
|
|
64 |
textures->rep_width, textures->rep_height,
|
|
|
65 |
textures->raster, textures->shift, textures->rep_shift);
|
|
|
66 |
else
|
|
|
67 |
dlputs(" textures=none");
|
|
|
68 |
if (tcolors)
|
|
|
69 |
dprintf2(" colors=(%lu,%lu)\n", tcolors[0], tcolors[1]);
|
|
|
70 |
else
|
|
|
71 |
dputs(" colors=none\n");
|
|
|
72 |
dlprintf7(" rect=(%d,%d),(%d,%d) phase=(%d,%d) op=0x%x\n",
|
|
|
73 |
x, y, x + width, y + height, phase_x, phase_y,
|
|
|
74 |
(uint) lop);
|
|
|
75 |
if (gs_debug_c('B')) {
|
|
|
76 |
if (sdata)
|
|
|
77 |
debug_dump_bitmap(sdata, sraster, height, "source bits");
|
|
|
78 |
if (textures && textures->data)
|
|
|
79 |
debug_dump_bitmap(textures->data, textures->raster,
|
|
|
80 |
textures->size.y, "textures bits");
|
|
|
81 |
}
|
|
|
82 |
}
|
|
|
83 |
|
|
|
84 |
#endif
|
|
|
85 |
|
|
|
86 |
/* ---------------- Default copy_rop implementations ---------------- */
|
|
|
87 |
|
|
|
88 |
/*
|
|
|
89 |
* The default implementation for non-memory devices uses get_bits_rectangle
|
|
|
90 |
* to read out the pixels, the memory device implementation to do the
|
|
|
91 |
* operation, and copy_color to write the pixels back.
|
|
|
92 |
*/
|
|
|
93 |
int
|
|
|
94 |
gx_default_strip_copy_rop(gx_device * dev,
|
|
|
95 |
const byte * sdata, int sourcex,
|
|
|
96 |
uint sraster, gx_bitmap_id id,
|
|
|
97 |
const gx_color_index * scolors,
|
|
|
98 |
const gx_strip_bitmap * textures,
|
|
|
99 |
const gx_color_index * tcolors,
|
|
|
100 |
int x, int y, int width, int height,
|
|
|
101 |
int phase_x, int phase_y,
|
|
|
102 |
gs_logical_operation_t lop)
|
|
|
103 |
{
|
|
|
104 |
int depth = dev->color_info.depth;
|
|
|
105 |
gs_memory_t *mem = dev->memory;
|
|
|
106 |
const gx_device_memory *mdproto = gdev_mem_device_for_bits(depth);
|
|
|
107 |
gx_device_memory mdev;
|
|
|
108 |
uint draster;
|
|
|
109 |
byte *row = 0;
|
|
|
110 |
gs_int_rect rect;
|
|
|
111 |
int max_height;
|
|
|
112 |
int block_height;
|
|
|
113 |
int code;
|
|
|
114 |
int py;
|
|
|
115 |
|
|
|
116 |
#ifdef DEBUG
|
|
|
117 |
if (gs_debug_c('b'))
|
|
|
118 |
trace_copy_rop("gx_default_strip_copy_rop",
|
|
|
119 |
dev, sdata, sourcex, sraster,
|
|
|
120 |
id, scolors, textures, tcolors,
|
|
|
121 |
x, y, width, height, phase_x, phase_y, lop);
|
|
|
122 |
#endif
|
|
|
123 |
if (mdproto == 0)
|
|
|
124 |
return_error(gs_error_rangecheck);
|
|
|
125 |
if (sdata == 0) {
|
|
|
126 |
fit_fill(dev, x, y, width, height);
|
|
|
127 |
} else {
|
|
|
128 |
fit_copy(dev, sdata, sourcex, sraster, id, x, y, width, height);
|
|
|
129 |
}
|
|
|
130 |
draster = bitmap_raster(width * depth);
|
|
|
131 |
max_height = max_rop_bitmap / draster;
|
|
|
132 |
if (max_height == 0)
|
|
|
133 |
max_height = 1;
|
|
|
134 |
block_height = min(height, max_height);
|
|
|
135 |
gs_make_mem_device(&mdev, mdproto, mem, -1, dev);
|
|
|
136 |
gx_device_retain((gx_device *)&mdev, true); /* prevent freeing */
|
|
|
137 |
mdev.width = width;
|
|
|
138 |
mdev.height = block_height;
|
|
|
139 |
mdev.bitmap_memory = mem;
|
|
|
140 |
mdev.color_info = dev->color_info;
|
|
|
141 |
code = (*dev_proc(&mdev, open_device))((gx_device *)&mdev);
|
|
|
142 |
if (code < 0)
|
|
|
143 |
return code;
|
|
|
144 |
if (rop3_uses_D(gs_transparent_rop(lop))) {
|
|
|
145 |
row = gs_alloc_bytes(mem, draster * block_height, "copy_rop row");
|
|
|
146 |
if (row == 0) {
|
|
|
147 |
code = gs_note_error(gs_error_VMerror);
|
|
|
148 |
goto out;
|
|
|
149 |
}
|
|
|
150 |
}
|
|
|
151 |
rect.p.x = x;
|
|
|
152 |
rect.q.x = x + width;
|
|
|
153 |
for (py = y; py < y + height; py += block_height) {
|
|
|
154 |
if (block_height > y + height - py)
|
|
|
155 |
block_height = y + height - py;
|
|
|
156 |
rect.p.y = py;
|
|
|
157 |
rect.q.y = py + block_height;
|
|
|
158 |
if (row /*uses_d*/) {
|
|
|
159 |
gs_get_bits_params_t bit_params;
|
|
|
160 |
|
|
|
161 |
bit_params.options =
|
|
|
162 |
GB_COLORS_NATIVE | GB_ALPHA_NONE | GB_DEPTH_ALL |
|
|
|
163 |
GB_PACKING_CHUNKY | GB_RETURN_ALL | GB_ALIGN_STANDARD |
|
|
|
164 |
GB_OFFSET_0 | GB_OFFSET_ANY | GB_RASTER_STANDARD;
|
|
|
165 |
bit_params.data[0] = row;
|
|
|
166 |
bit_params.x_offset = 0;
|
|
|
167 |
code = (*dev_proc(dev, get_bits_rectangle))
|
|
|
168 |
(dev, &rect, &bit_params, NULL);
|
|
|
169 |
if (code < 0)
|
|
|
170 |
break;
|
|
|
171 |
code = (*dev_proc(&mdev, copy_color))
|
|
|
172 |
((gx_device *)&mdev, bit_params.data[0], bit_params.x_offset,
|
|
|
173 |
draster, gx_no_bitmap_id, 0, 0, width,
|
|
|
174 |
block_height);
|
|
|
175 |
if (code < 0)
|
|
|
176 |
return code;
|
|
|
177 |
}
|
|
|
178 |
code = (*dev_proc(&mdev, strip_copy_rop))
|
|
|
179 |
((gx_device *)&mdev,
|
|
|
180 |
sdata + (py - y) * sraster, sourcex, sraster,
|
|
|
181 |
gx_no_bitmap_id, scolors, textures, tcolors,
|
|
|
182 |
0, 0, width, block_height, phase_x + x, phase_y + py, lop);
|
|
|
183 |
if (code < 0)
|
|
|
184 |
break;
|
|
|
185 |
code = (*dev_proc(dev, copy_color))
|
|
|
186 |
(dev, scan_line_base(&mdev, 0), 0, draster, gx_no_bitmap_id,
|
|
|
187 |
x, py, width, block_height);
|
|
|
188 |
if (code < 0)
|
|
|
189 |
break;
|
|
|
190 |
}
|
|
|
191 |
out:
|
|
|
192 |
gs_free_object(mem, row, "copy_rop row");
|
|
|
193 |
(*dev_proc(&mdev, close_device))((gx_device *)&mdev);
|
|
|
194 |
return code;
|
|
|
195 |
}
|
|
|
196 |
|
|
|
197 |
/* ---------------- Default memory device copy_rop ---------------- */
|
|
|
198 |
|
|
|
199 |
/* Convert color constants to standard RGB representation. */
|
|
|
200 |
private void
|
|
|
201 |
unpack_colors_to_standard(gx_device * dev, gx_color_index real_colors[2],
|
|
|
202 |
const gx_color_index * colors, int depth)
|
|
|
203 |
{
|
|
|
204 |
int i;
|
|
|
205 |
|
|
|
206 |
for (i = 0; i < 2; ++i) {
|
|
|
207 |
gx_color_value rgb[3];
|
|
|
208 |
gx_color_index pixel;
|
|
|
209 |
|
|
|
210 |
(*dev_proc(dev, map_color_rgb)) (dev, colors[i], rgb);
|
|
|
211 |
pixel = gx_color_value_to_byte(rgb[0]);
|
|
|
212 |
if (depth > 8) {
|
|
|
213 |
pixel = (pixel << 16) +
|
|
|
214 |
(gx_color_value_to_byte(rgb[1]) << 8) +
|
|
|
215 |
gx_color_value_to_byte(rgb[2]);
|
|
|
216 |
}
|
|
|
217 |
real_colors[i] = pixel;
|
|
|
218 |
}
|
|
|
219 |
}
|
|
|
220 |
|
|
|
221 |
/*
|
|
|
222 |
* Convert RGB to the device's native format. We special-case this for
|
|
|
223 |
* 1-bit CMYK devices.
|
|
|
224 |
*/
|
|
|
225 |
private void
|
|
|
226 |
pack_cmyk_1bit_from_standard(gx_device * dev, byte * dest, int destx,
|
|
|
227 |
const byte * src, int width, int depth,
|
|
|
228 |
int src_depth)
|
|
|
229 |
{
|
|
|
230 |
/*
|
|
|
231 |
* This routine is only called if dev_proc(dev, map_cmyk_color) ==
|
|
|
232 |
* cmyk_1bit_map_cmyk_color (implying depth == 4) and src_depth == 24.
|
|
|
233 |
*/
|
|
|
234 |
int bit_x = destx * 4;
|
|
|
235 |
byte *dp = dest + (bit_x >> 3);
|
|
|
236 |
bool hi = (bit_x & 4) != 0; /* true if last nibble filled was hi */
|
|
|
237 |
byte buf = (hi ? *dp & 0xf0 : 0);
|
|
|
238 |
const byte *sp = src;
|
|
|
239 |
int x;
|
|
|
240 |
|
|
|
241 |
for (x = width; --x >= 0; sp += 3) {
|
|
|
242 |
byte r = sp[0], g = sp[1], b = sp[2];
|
|
|
243 |
byte pixel =
|
|
|
244 |
(r | g | b ?
|
|
|
245 |
(((r >> 4) & 8) | ((g >> 5) & 4) | ((b >> 6) & 2)) ^ 0xe : 1);
|
|
|
246 |
|
|
|
247 |
if ((hi = !hi))
|
|
|
248 |
buf = pixel << 4;
|
|
|
249 |
else
|
|
|
250 |
*dp++ = buf | pixel;
|
|
|
251 |
}
|
|
|
252 |
if (hi && width > 0)
|
|
|
253 |
*dp = buf | (*dp & 0xf);
|
|
|
254 |
|
|
|
255 |
}
|
|
|
256 |
|
|
|
257 |
private gx_color_index
|
|
|
258 |
map_rgb_to_color_via_cmyk(gx_device * dev, const gx_color_value rgbcv[])
|
|
|
259 |
{
|
|
|
260 |
gx_color_value cmykcv[4];
|
|
|
261 |
|
|
|
262 |
cmykcv[0] = gx_max_color_value - rgbcv[0];
|
|
|
263 |
cmykcv[1] = gx_max_color_value - rgbcv[1];
|
|
|
264 |
cmykcv[2] = gx_max_color_value - rgbcv[2];
|
|
|
265 |
cmykcv[3] = (cmykcv[0] < cmykcv[1] ? min(cmykcv[0], cmykcv[2]) : min(cmykcv[1], cmykcv[2]));
|
|
|
266 |
|
|
|
267 |
cmykcv[0] -= cmykcv[3];
|
|
|
268 |
cmykcv[1] -= cmykcv[3];
|
|
|
269 |
cmykcv[2] -= cmykcv[3];
|
|
|
270 |
|
|
|
271 |
return (*dev_proc(dev, map_cmyk_color)) (dev, cmykcv);
|
|
|
272 |
}
|
|
|
273 |
private void
|
|
|
274 |
pack_from_standard(gx_device * dev, byte * dest, int destx, const byte * src,
|
|
|
275 |
int width, int depth, int src_depth)
|
|
|
276 |
{
|
|
|
277 |
dev_proc_map_rgb_color((*map)) =
|
|
|
278 |
(dev->color_info.num_components == 4 ?
|
|
|
279 |
map_rgb_to_color_via_cmyk : dev_proc(dev, map_rgb_color));
|
|
|
280 |
int bit_x = destx * depth;
|
|
|
281 |
byte *dp = dest + (bit_x >> 3);
|
|
|
282 |
int shift = (~bit_x & 7) + 1;
|
|
|
283 |
byte buf = (shift == 8 ? 0 : *dp & (0xff00 >> shift));
|
|
|
284 |
const byte *sp = src;
|
|
|
285 |
int x;
|
|
|
286 |
|
|
|
287 |
for (x = width; --x >= 0;) {
|
|
|
288 |
byte vr, vg, vb;
|
|
|
289 |
gx_color_index pixel;
|
|
|
290 |
byte chop = 0x1;
|
|
|
291 |
|
|
|
292 |
vr = *sp++;
|
|
|
293 |
if (src_depth > 8) {
|
|
|
294 |
vg = *sp++;
|
|
|
295 |
vb = *sp++;
|
|
|
296 |
} else
|
|
|
297 |
vb = vg = vr;
|
|
|
298 |
/*
|
|
|
299 |
* We have to map back to some pixel value, even if the color
|
|
|
300 |
* isn't accurate.
|
|
|
301 |
*/
|
|
|
302 |
for (;;) {
|
|
|
303 |
gx_color_value cv[3];
|
|
|
304 |
cv[0] = gx_color_value_from_byte(vr);
|
|
|
305 |
cv[1] = gx_color_value_from_byte(vg);
|
|
|
306 |
cv[2] = gx_color_value_from_byte(vb);
|
|
|
307 |
pixel = (*map) (dev, cv);
|
|
|
308 |
if (pixel != gx_no_color_index)
|
|
|
309 |
break;
|
|
|
310 |
/* Reduce the color accuracy and try again. */
|
|
|
311 |
vr = (vr >= 0x80 ? vr | chop : vr & ~chop);
|
|
|
312 |
vg = (vg >= 0x80 ? vg | chop : vg & ~chop);
|
|
|
313 |
vb = (vb >= 0x80 ? vb | chop : vb & ~chop);
|
|
|
314 |
chop <<= 1;
|
|
|
315 |
}
|
|
|
316 |
if ((shift -= depth) >= 0)
|
|
|
317 |
buf += (byte)(pixel << shift);
|
|
|
318 |
else {
|
|
|
319 |
switch (depth) {
|
|
|
320 |
default: /* 1, 2, 4, 8 */
|
|
|
321 |
*dp++ = buf;
|
|
|
322 |
shift += 8;
|
|
|
323 |
buf = (byte)(pixel << shift);
|
|
|
324 |
break;
|
|
|
325 |
case 32:
|
|
|
326 |
*dp++ = (byte)(pixel >> 24);
|
|
|
327 |
*dp++ = (byte)(pixel >> 16);
|
|
|
328 |
case 16:
|
|
|
329 |
*dp++ = (byte)(pixel >> 8);
|
|
|
330 |
*dp++ = (byte)pixel;
|
|
|
331 |
shift = 0;
|
|
|
332 |
}
|
|
|
333 |
}
|
|
|
334 |
}
|
|
|
335 |
if (width > 0 && depth <= 8)
|
|
|
336 |
*dp = (shift == 0 ? buf : buf + (*dp & ((1 << shift) - 1)));
|
|
|
337 |
}
|
|
|
338 |
|
|
|
339 |
/*
|
|
|
340 |
* The default implementation for memory devices uses get_bits_rectangle to
|
|
|
341 |
* read out the pixels and convert them to standard (8-bit gray or 24-bit
|
|
|
342 |
* RGB) representation, the standard memory device implementation to do the
|
|
|
343 |
* operation, pack_from_standard to convert them back to the device
|
|
|
344 |
* representation, and copy_color to write the pixels back.
|
|
|
345 |
*/
|
|
|
346 |
int
|
|
|
347 |
mem_default_strip_copy_rop(gx_device * dev,
|
|
|
348 |
const byte * sdata, int sourcex,
|
|
|
349 |
uint sraster, gx_bitmap_id id,
|
|
|
350 |
const gx_color_index * scolors,
|
|
|
351 |
const gx_strip_bitmap * textures,
|
|
|
352 |
const gx_color_index * tcolors,
|
|
|
353 |
int x, int y, int width, int height,
|
|
|
354 |
int phase_x, int phase_y,
|
|
|
355 |
gs_logical_operation_t lop)
|
|
|
356 |
{
|
|
|
357 |
int depth = dev->color_info.depth;
|
|
|
358 |
int rop_depth = (gx_device_has_color(dev) ? 24 : 8);
|
|
|
359 |
void (*pack)(gx_device *, byte *, int, const byte *, int, int, int) =
|
|
|
360 |
(dev_proc(dev, map_cmyk_color) == cmyk_1bit_map_cmyk_color &&
|
|
|
361 |
rop_depth == 24 ? pack_cmyk_1bit_from_standard : pack_from_standard);
|
|
|
362 |
const gx_bitmap_format_t no_expand_options =
|
|
|
363 |
GB_COLORS_NATIVE | GB_ALPHA_NONE | GB_DEPTH_ALL |
|
|
|
364 |
GB_PACKING_CHUNKY | GB_RETURN_ALL | GB_ALIGN_STANDARD |
|
|
|
365 |
GB_OFFSET_0 | GB_OFFSET_ANY | GB_RASTER_STANDARD;
|
|
|
366 |
const gx_bitmap_format_t expand_options =
|
|
|
367 |
(rop_depth > 8 ? GB_COLORS_RGB : GB_COLORS_GRAY) |
|
|
|
368 |
GB_ALPHA_NONE | GB_DEPTH_8 |
|
|
|
369 |
GB_PACKING_CHUNKY | GB_RETURN_COPY | GB_ALIGN_STANDARD |
|
|
|
370 |
GB_OFFSET_0 | GB_RASTER_STANDARD;
|
|
|
371 |
gs_memory_t *mem = dev->memory;
|
|
|
372 |
const gx_device_memory *mdproto = gdev_mem_device_for_bits(rop_depth);
|
|
|
373 |
gx_device_memory mdev;
|
|
|
374 |
union { long l; void *p; } mdev_storage[20];
|
|
|
375 |
uint row_raster = bitmap_raster(width * depth);
|
|
|
376 |
gs_rop3_t trans_rop = gs_transparent_rop(lop);
|
|
|
377 |
bool uses_d = rop3_uses_D(trans_rop);
|
|
|
378 |
bool uses_s = rop3_uses_S(trans_rop);
|
|
|
379 |
bool uses_t = rop3_uses_T(trans_rop);
|
|
|
380 |
bool expand_s, expand_t;
|
|
|
381 |
byte *row = 0;
|
|
|
382 |
union { long l; void *p; } dest_buffer[16];
|
|
|
383 |
byte *source_row = 0;
|
|
|
384 |
uint source_row_raster;
|
|
|
385 |
union { long l; void *p; } source_buffer[16];
|
|
|
386 |
byte *texture_row = 0;
|
|
|
387 |
uint texture_row_raster;
|
|
|
388 |
union { long l; void *p; } texture_buffer[16];
|
|
|
389 |
gx_color_index source_colors[2];
|
|
|
390 |
const gx_color_index *real_scolors = scolors;
|
|
|
391 |
gx_color_index texture_colors[2];
|
|
|
392 |
const gx_color_index *real_tcolors = tcolors;
|
|
|
393 |
gx_strip_bitmap rop_texture;
|
|
|
394 |
const gx_strip_bitmap *real_texture = textures;
|
|
|
395 |
gs_int_rect rect;
|
|
|
396 |
gs_get_bits_params_t bit_params;
|
|
|
397 |
gs_get_bits_params_t expand_params;
|
|
|
398 |
gs_get_bits_params_t no_expand_params;
|
|
|
399 |
int max_height;
|
|
|
400 |
int block_height, loop_height;
|
|
|
401 |
int code;
|
|
|
402 |
int py;
|
|
|
403 |
|
|
|
404 |
/*
|
|
|
405 |
* Allocate a temporary row buffer. Free variables: mem, block_height.
|
|
|
406 |
* Labels used: out.
|
|
|
407 |
*/
|
|
|
408 |
#define ALLOC_BUF(buf, prebuf, size, cname)\
|
|
|
409 |
BEGIN\
|
|
|
410 |
uint num_bytes = (size) * block_height;\
|
|
|
411 |
\
|
|
|
412 |
if (num_bytes <= sizeof(prebuf))\
|
|
|
413 |
buf = (byte *)prebuf;\
|
|
|
414 |
else {\
|
|
|
415 |
buf = gs_alloc_bytes(mem, num_bytes, cname);\
|
|
|
416 |
if (buf == 0) {\
|
|
|
417 |
code = gs_note_error(gs_error_VMerror);\
|
|
|
418 |
goto out;\
|
|
|
419 |
}\
|
|
|
420 |
}\
|
|
|
421 |
END
|
|
|
422 |
|
|
|
423 |
#ifdef DEBUG
|
|
|
424 |
if (gs_debug_c('b'))
|
|
|
425 |
trace_copy_rop("mem_default_strip_copy_rop",
|
|
|
426 |
dev, sdata, sourcex, sraster,
|
|
|
427 |
id, scolors, textures, tcolors,
|
|
|
428 |
x, y, width, height, phase_x, phase_y, lop);
|
|
|
429 |
#endif
|
|
|
430 |
if (mdproto == 0)
|
|
|
431 |
return_error(gs_error_rangecheck);
|
|
|
432 |
if (sdata == 0) {
|
|
|
433 |
fit_fill(dev, x, y, width, height);
|
|
|
434 |
} else {
|
|
|
435 |
fit_copy(dev, sdata, sourcex, sraster, id, x, y, width, height);
|
|
|
436 |
}
|
|
|
437 |
/* Compute max_height conservatively. */
|
|
|
438 |
max_height = max_rop_bitmap / (width * rop_depth);
|
|
|
439 |
if (max_height == 0)
|
|
|
440 |
max_height = 1;
|
|
|
441 |
block_height = min(height, max_height);
|
|
|
442 |
expand_s = scolors == 0 && uses_s;
|
|
|
443 |
expand_t = tcolors == 0 && uses_t;
|
|
|
444 |
no_expand_params.options = no_expand_options;
|
|
|
445 |
if (expand_t) {
|
|
|
446 |
/*
|
|
|
447 |
* We don't want to wrap around more than once in Y when
|
|
|
448 |
* copying the texture to the intermediate buffer.
|
|
|
449 |
*/
|
|
|
450 |
if (textures->size.y < block_height)
|
|
|
451 |
block_height = textures->size.y;
|
|
|
452 |
}
|
|
|
453 |
gs_make_mem_device(&mdev, mdproto, mem, -1, NULL);
|
|
|
454 |
gx_device_retain((gx_device *)&mdev, true); /* prevent freeing */
|
|
|
455 |
mdev.width = width;
|
|
|
456 |
mdev.height = block_height;
|
|
|
457 |
mdev.color_info.num_components = rop_depth >> 3;
|
|
|
458 |
if (gdev_mem_data_size(&mdev, width, block_height) <= sizeof(mdev_storage)) {
|
|
|
459 |
/* Use the locally allocated storage. */
|
|
|
460 |
mdev.base = (byte *)mdev_storage;
|
|
|
461 |
mdev.line_ptrs = (byte **)
|
|
|
462 |
(mdev.base + gdev_mem_bits_size(&mdev, mdev.width, mdev.height));
|
|
|
463 |
} else {
|
|
|
464 |
mdev.bitmap_memory = mem;
|
|
|
465 |
}
|
|
|
466 |
code = (*dev_proc(&mdev, open_device))((gx_device *)&mdev);
|
|
|
467 |
if (code < 0)
|
|
|
468 |
return code;
|
|
|
469 |
ALLOC_BUF(row, dest_buffer, row_raster, "copy_rop row");
|
|
|
470 |
/* We may need intermediate buffers for all 3 operands. */
|
|
|
471 |
if (expand_s) {
|
|
|
472 |
source_row_raster = bitmap_raster(width * rop_depth);
|
|
|
473 |
ALLOC_BUF(source_row, source_buffer, source_row_raster,
|
|
|
474 |
"copy_rop source_row");
|
|
|
475 |
}
|
|
|
476 |
if (scolors && uses_s) {
|
|
|
477 |
unpack_colors_to_standard(dev, source_colors, scolors, rop_depth);
|
|
|
478 |
real_scolors = source_colors;
|
|
|
479 |
}
|
|
|
480 |
if (expand_t) {
|
|
|
481 |
texture_row_raster = bitmap_raster(textures->rep_width * rop_depth);
|
|
|
482 |
ALLOC_BUF(texture_row, texture_buffer, texture_row_raster,
|
|
|
483 |
"copy_rop texture_row");
|
|
|
484 |
rop_texture = *textures;
|
|
|
485 |
rop_texture.data = texture_row;
|
|
|
486 |
rop_texture.raster = texture_row_raster;
|
|
|
487 |
rop_texture.size.x = rop_texture.rep_width;
|
|
|
488 |
rop_texture.id = gs_no_bitmap_id;
|
|
|
489 |
real_texture = &rop_texture;
|
|
|
490 |
}
|
|
|
491 |
if (tcolors && uses_t) {
|
|
|
492 |
unpack_colors_to_standard(dev, texture_colors, tcolors, rop_depth);
|
|
|
493 |
real_tcolors = texture_colors;
|
|
|
494 |
}
|
|
|
495 |
expand_params.options = expand_options;
|
|
|
496 |
expand_params.x_offset = 0;
|
|
|
497 |
rect.p.x = x;
|
|
|
498 |
rect.q.x = x + width;
|
|
|
499 |
for (py = y; py < y + height; py += loop_height) {
|
|
|
500 |
int sx = sourcex;
|
|
|
501 |
const byte *source_data = sdata + (py - y) * sraster;
|
|
|
502 |
uint source_raster = sraster;
|
|
|
503 |
|
|
|
504 |
if (block_height > y + height - py)
|
|
|
505 |
block_height = y + height - py;
|
|
|
506 |
rect.p.y = py;
|
|
|
507 |
if (expand_t) {
|
|
|
508 |
int rep_y = (phase_y + py) % rop_texture.rep_height;
|
|
|
509 |
|
|
|
510 |
loop_height = min(block_height, rop_texture.size.y - rep_y);
|
|
|
511 |
rect.q.y = py + loop_height;
|
|
|
512 |
expand_params.data[0] = texture_row;
|
|
|
513 |
gx_get_bits_copy(dev, 0, textures->rep_width, loop_height,
|
|
|
514 |
&expand_params, &no_expand_params,
|
|
|
515 |
textures->data + rep_y * textures->raster,
|
|
|
516 |
textures->raster);
|
|
|
517 |
/*
|
|
|
518 |
* Compensate for the addition of rep_y * raster
|
|
|
519 |
* in the subsidiary strip_copy_rop call.
|
|
|
520 |
*/
|
|
|
521 |
rop_texture.data = texture_row - rep_y * rop_texture.raster;
|
|
|
522 |
} else {
|
|
|
523 |
loop_height = block_height;
|
|
|
524 |
rect.q.y = py + block_height;
|
|
|
525 |
}
|
|
|
526 |
if (uses_d) {
|
|
|
527 |
bit_params.options = expand_options;
|
|
|
528 |
bit_params.data[0] = scan_line_base(&mdev, 0);
|
|
|
529 |
bit_params.x_offset = 0;
|
|
|
530 |
code = (*dev_proc(dev, get_bits_rectangle))
|
|
|
531 |
(dev, &rect, &bit_params, NULL);
|
|
|
532 |
if (code < 0)
|
|
|
533 |
break;
|
|
|
534 |
}
|
|
|
535 |
/* Convert the source and texture to standard format. */
|
|
|
536 |
if (expand_s) {
|
|
|
537 |
expand_params.data[0] = source_row;
|
|
|
538 |
gx_get_bits_copy(dev, sx, width, loop_height, &expand_params,
|
|
|
539 |
&no_expand_params, source_data, sraster);
|
|
|
540 |
sx = 0;
|
|
|
541 |
source_data = source_row;
|
|
|
542 |
source_raster = source_row_raster;
|
|
|
543 |
}
|
|
|
544 |
code = (*dev_proc(&mdev, strip_copy_rop))
|
|
|
545 |
((gx_device *)&mdev, source_data, sx, source_raster,
|
|
|
546 |
gx_no_bitmap_id, real_scolors, real_texture, real_tcolors,
|
|
|
547 |
0, 0, width, loop_height, phase_x + x, phase_y + py, lop);
|
|
|
548 |
if (code < 0)
|
|
|
549 |
break;
|
|
|
550 |
{
|
|
|
551 |
/*
|
|
|
552 |
* Convert the result back to the device's format. We know
|
|
|
553 |
* the device is a memory device, so we can store the result
|
|
|
554 |
* directly into its scan lines.
|
|
|
555 |
*/
|
|
|
556 |
int i;
|
|
|
557 |
const byte *unpacked = scan_line_base(&mdev, 0);
|
|
|
558 |
|
|
|
559 |
for (i = 0; i < loop_height; unpacked += mdev.raster, ++i) {
|
|
|
560 |
byte *packed = scan_line_base((gx_device_memory *)dev, py + i);
|
|
|
561 |
|
|
|
562 |
pack(dev, packed, x, unpacked, width, depth, rop_depth);
|
|
|
563 |
}
|
|
|
564 |
}
|
|
|
565 |
}
|
|
|
566 |
out:
|
|
|
567 |
if (texture_row != 0 && texture_row != (byte *)texture_buffer)
|
|
|
568 |
gs_free_object(mem, texture_row, "copy_rop texture_row");
|
|
|
569 |
if (source_row != 0 && source_row != (byte *)source_buffer)
|
|
|
570 |
gs_free_object(mem, source_row, "copy_rop source_row");
|
|
|
571 |
if (row != 0 && row != (byte *)dest_buffer)
|
|
|
572 |
gs_free_object(mem, row, "copy_rop row");
|
|
|
573 |
(*dev_proc(&mdev, close_device)) ((gx_device *) & mdev);
|
|
|
574 |
return code;
|
|
|
575 |
}
|
|
|
576 |
|
|
|
577 |
/* ------ Implementation of related functions ------ */
|
|
|
578 |
|
|
|
579 |
int
|
|
|
580 |
gx_default_copy_rop(gx_device * dev,
|
|
|
581 |
const byte * sdata, int sourcex, uint sraster, gx_bitmap_id id,
|
|
|
582 |
const gx_color_index * scolors,
|
|
|
583 |
const gx_tile_bitmap * texture, const gx_color_index * tcolors,
|
|
|
584 |
int x, int y, int width, int height,
|
|
|
585 |
int phase_x, int phase_y, gs_logical_operation_t lop)
|
|
|
586 |
{
|
|
|
587 |
const gx_strip_bitmap *textures;
|
|
|
588 |
gx_strip_bitmap tiles;
|
|
|
589 |
|
|
|
590 |
if (texture == 0)
|
|
|
591 |
textures = 0;
|
|
|
592 |
else {
|
|
|
593 |
*(gx_tile_bitmap *) & tiles = *texture;
|
|
|
594 |
tiles.rep_shift = tiles.shift = 0;
|
|
|
595 |
textures = &tiles;
|
|
|
596 |
}
|
|
|
597 |
return (*dev_proc(dev, strip_copy_rop))
|
|
|
598 |
(dev, sdata, sourcex, sraster, id, scolors, textures, tcolors,
|
|
|
599 |
x, y, width, height, phase_x, phase_y, lop);
|
|
|
600 |
}
|
|
|
601 |
|
|
|
602 |
int
|
|
|
603 |
gx_copy_rop_unaligned(gx_device * dev,
|
|
|
604 |
const byte * sdata, int sourcex, uint sraster, gx_bitmap_id id,
|
|
|
605 |
const gx_color_index * scolors,
|
|
|
606 |
const gx_tile_bitmap * texture, const gx_color_index * tcolors,
|
|
|
607 |
int x, int y, int width, int height,
|
|
|
608 |
int phase_x, int phase_y, gs_logical_operation_t lop)
|
|
|
609 |
{
|
|
|
610 |
const gx_strip_bitmap *textures;
|
|
|
611 |
gx_strip_bitmap tiles;
|
|
|
612 |
|
|
|
613 |
if (texture == 0)
|
|
|
614 |
textures = 0;
|
|
|
615 |
else {
|
|
|
616 |
*(gx_tile_bitmap *) & tiles = *texture;
|
|
|
617 |
tiles.rep_shift = tiles.shift = 0;
|
|
|
618 |
textures = &tiles;
|
|
|
619 |
}
|
|
|
620 |
return gx_strip_copy_rop_unaligned
|
|
|
621 |
(dev, sdata, sourcex, sraster, id, scolors, textures, tcolors,
|
|
|
622 |
x, y, width, height, phase_x, phase_y, lop);
|
|
|
623 |
}
|
|
|
624 |
|
|
|
625 |
int
|
|
|
626 |
gx_strip_copy_rop_unaligned(gx_device * dev,
|
|
|
627 |
const byte * sdata, int sourcex, uint sraster, gx_bitmap_id id,
|
|
|
628 |
const gx_color_index * scolors,
|
|
|
629 |
const gx_strip_bitmap * textures, const gx_color_index * tcolors,
|
|
|
630 |
int x, int y, int width, int height,
|
|
|
631 |
int phase_x, int phase_y, gs_logical_operation_t lop)
|
|
|
632 |
{
|
|
|
633 |
dev_proc_strip_copy_rop((*copy_rop)) = dev_proc(dev, strip_copy_rop);
|
|
|
634 |
int depth = (scolors == 0 ? dev->color_info.depth : 1);
|
|
|
635 |
int step = sraster & (align_bitmap_mod - 1);
|
|
|
636 |
|
|
|
637 |
/* Adjust the origin. */
|
|
|
638 |
if (sdata != 0) {
|
|
|
639 |
uint offset =
|
|
|
640 |
(uint) (sdata - (const byte *)0) & (align_bitmap_mod - 1);
|
|
|
641 |
|
|
|
642 |
/* See copy_color above re the following statement. */
|
|
|
643 |
if (depth == 24)
|
|
|
644 |
offset += (offset % 3) *
|
|
|
645 |
(align_bitmap_mod * (3 - (align_bitmap_mod % 3)));
|
|
|
646 |
sdata -= offset;
|
|
|
647 |
sourcex += (offset << 3) / depth;
|
|
|
648 |
}
|
|
|
649 |
/* Adjust the raster. */
|
|
|
650 |
if (!step || sdata == 0 ||
|
|
|
651 |
(scolors != 0 && scolors[0] == scolors[1])
|
|
|
652 |
) { /* No adjustment needed. */
|
|
|
653 |
return (*copy_rop) (dev, sdata, sourcex, sraster, id, scolors,
|
|
|
654 |
textures, tcolors, x, y, width, height,
|
|
|
655 |
phase_x, phase_y, lop);
|
|
|
656 |
}
|
|
|
657 |
/* Do the transfer one scan line at a time. */
|
|
|
658 |
{
|
|
|
659 |
const byte *p = sdata;
|
|
|
660 |
int d = sourcex;
|
|
|
661 |
int dstep = (step << 3) / depth;
|
|
|
662 |
int code = 0;
|
|
|
663 |
int i;
|
|
|
664 |
|
|
|
665 |
for (i = 0; i < height && code >= 0;
|
|
|
666 |
++i, p += sraster - step, d += dstep
|
|
|
667 |
)
|
|
|
668 |
code = (*copy_rop) (dev, p, d, sraster, gx_no_bitmap_id, scolors,
|
|
|
669 |
textures, tcolors, x, y + i, width, 1,
|
|
|
670 |
phase_x, phase_y, lop);
|
|
|
671 |
return code;
|
|
|
672 |
}
|
|
|
673 |
}
|
|
|
674 |
|
|
|
675 |
/* ---------------- Internal routines ---------------- */
|
|
|
676 |
|
|
|
677 |
/* Compute the effective RasterOp for the 1-bit case, */
|
|
|
678 |
/* taking transparency into account. */
|
|
|
679 |
gs_rop3_t
|
|
|
680 |
gs_transparent_rop(gs_logical_operation_t lop)
|
|
|
681 |
{
|
|
|
682 |
gs_rop3_t rop = lop_rop(lop);
|
|
|
683 |
|
|
|
684 |
/*
|
|
|
685 |
* The algorithm for computing an effective RasterOp is presented,
|
|
|
686 |
* albeit obfuscated, in the H-P PCL5 technical documentation.
|
|
|
687 |
* Define So ("source opaque") and Po ("pattern opaque") as masks
|
|
|
688 |
* that have 1-bits precisely where the source or pattern
|
|
|
689 |
* respectively are not white (transparent).
|
|
|
690 |
* One applies the original RasterOp to compute an intermediate
|
|
|
691 |
* result R, and then computes the final result as
|
|
|
692 |
* (R & M) | (D & ~M) where M depends on transparencies as follows:
|
|
|
693 |
* s_tr p_tr M
|
|
|
694 |
* 0 0 1
|
|
|
695 |
* 0 1 ~So | Po (? Po ?)
|
|
|
696 |
* 1 0 So
|
|
|
697 |
* 1 1 So & Po
|
|
|
698 |
* The s_tr = 0, p_tr = 1 case seems wrong, but it's clearly
|
|
|
699 |
* specified that way in the "PCL 5 Color Technical Reference
|
|
|
700 |
* Manual."
|
|
|
701 |
*
|
|
|
702 |
* In the 1-bit case, So = ~S and Po = ~P, so we can apply the
|
|
|
703 |
* above table directly.
|
|
|
704 |
*/
|
|
|
705 |
#define So rop3_not(rop3_S)
|
|
|
706 |
#define Po rop3_not(rop3_T)
|
|
|
707 |
#ifdef TRANSPARENCY_PER_H_P
|
|
|
708 |
/*
|
|
|
709 |
* Believe it or not, MPo depends on S in this case even if the original
|
|
|
710 |
* RasterOp didn't depend on S.
|
|
|
711 |
*/
|
|
|
712 |
# define MPo (rop3_not(So) | Po)
|
|
|
713 |
#else
|
|
|
714 |
# define MPo Po
|
|
|
715 |
#endif
|
|
|
716 |
/*
|
|
|
717 |
* If the operation doesn't use S or T, we must disregard the
|
|
|
718 |
* corresponding transparency flag.
|
|
|
719 |
*/
|
|
|
720 |
#define source_transparent ((lop & lop_S_transparent) && rop3_uses_S(rop))
|
|
|
721 |
#define pattern_transparent ((lop & lop_T_transparent) && rop3_uses_T(rop))
|
|
|
722 |
gs_rop3_t mask =
|
|
|
723 |
(source_transparent ?
|
|
|
724 |
(pattern_transparent ? So & Po : So) :
|
|
|
725 |
(pattern_transparent ? MPo : rop3_1));
|
|
|
726 |
|
|
|
727 |
#undef MPo
|
|
|
728 |
return (rop & mask) | (rop3_D & ~mask);
|
|
|
729 |
}
|