2 |
- |
1 |
/* Copyright (C) 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: gdevmr8n.c,v 1.4 2002/02/21 22:24:51 giles Exp $ */
|
|
|
18 |
/* RasterOp implementation for 8N-bit memory devices */
|
|
|
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 "gdevmem.h"
|
|
|
30 |
#include "gdevmrop.h"
|
|
|
31 |
|
|
|
32 |
/*
|
|
|
33 |
* NOTE: The 16- and 32-bit cases aren't implemented: they just fall back to
|
|
|
34 |
* the default implementation. This is very slow and will be fixed someday.
|
|
|
35 |
*/
|
|
|
36 |
|
|
|
37 |
#define chunk byte
|
|
|
38 |
|
|
|
39 |
/* Calculate the X offset for a given Y value, */
|
|
|
40 |
/* taking shift into account if necessary. */
|
|
|
41 |
#define x_offset(px, ty, textures)\
|
|
|
42 |
((textures)->shift == 0 ? (px) :\
|
|
|
43 |
(px) + (ty) / (textures)->rep_height * (textures)->rep_shift)
|
|
|
44 |
|
|
|
45 |
/* ---------------- RasterOp with 8-bit gray / 24-bit RGB ---------------- */
|
|
|
46 |
|
|
|
47 |
int
|
|
|
48 |
mem_gray8_rgb24_strip_copy_rop(gx_device * dev,
|
|
|
49 |
const byte * sdata, int sourcex, uint sraster, gx_bitmap_id id,
|
|
|
50 |
const gx_color_index * scolors,
|
|
|
51 |
const gx_strip_bitmap * textures, const gx_color_index * tcolors,
|
|
|
52 |
int x, int y, int width, int height,
|
|
|
53 |
int phase_x, int phase_y, gs_logical_operation_t lop)
|
|
|
54 |
{
|
|
|
55 |
gx_device_memory *mdev = (gx_device_memory *) dev;
|
|
|
56 |
gs_rop3_t rop = lop_rop(lop);
|
|
|
57 |
gx_color_index const_source = gx_no_color_index;
|
|
|
58 |
gx_color_index const_texture = gx_no_color_index;
|
|
|
59 |
uint draster = mdev->raster;
|
|
|
60 |
int line_count;
|
|
|
61 |
byte *drow;
|
|
|
62 |
int depth = dev->color_info.depth;
|
|
|
63 |
int bpp = depth >> 3; /* bytes per pixel, 1 or 3 */
|
|
|
64 |
gx_color_index all_ones = ((gx_color_index) 1 << depth) - 1;
|
|
|
65 |
gx_color_index strans =
|
|
|
66 |
(lop & lop_S_transparent ? all_ones : gx_no_color_index);
|
|
|
67 |
gx_color_index ttrans =
|
|
|
68 |
(lop & lop_T_transparent ? all_ones : gx_no_color_index);
|
|
|
69 |
|
|
|
70 |
/* Check for constant source. */
|
|
|
71 |
if (!rop3_uses_S(rop))
|
|
|
72 |
const_source = 0; /* arbitrary */
|
|
|
73 |
else if (scolors != 0 && scolors[0] == scolors[1]) {
|
|
|
74 |
/* Constant source */
|
|
|
75 |
const_source = scolors[0];
|
|
|
76 |
if (const_source == gx_device_black(dev))
|
|
|
77 |
rop = rop3_know_S_0(rop);
|
|
|
78 |
else if (const_source == gx_device_white(dev))
|
|
|
79 |
rop = rop3_know_S_1(rop);
|
|
|
80 |
}
|
|
|
81 |
|
|
|
82 |
/* Check for constant texture. */
|
|
|
83 |
if (!rop3_uses_T(rop))
|
|
|
84 |
const_texture = 0; /* arbitrary */
|
|
|
85 |
else if (tcolors != 0 && tcolors[0] == tcolors[1]) {
|
|
|
86 |
/* Constant texture */
|
|
|
87 |
const_texture = tcolors[0];
|
|
|
88 |
if (const_texture == gx_device_black(dev))
|
|
|
89 |
rop = rop3_know_T_0(rop);
|
|
|
90 |
else if (const_texture == gx_device_white(dev))
|
|
|
91 |
rop = rop3_know_T_1(rop);
|
|
|
92 |
}
|
|
|
93 |
|
|
|
94 |
if (bpp == 1 &&
|
|
|
95 |
(gx_device_has_color(dev) ||
|
|
|
96 |
(gx_device_black(dev) != 0 || gx_device_white(dev) != all_ones))
|
|
|
97 |
) {
|
|
|
98 |
/*
|
|
|
99 |
* This is an 8-bit device but not gray-scale. Except in a few
|
|
|
100 |
* simple cases, we have to use the slow algorithm that converts
|
|
|
101 |
* values to and from RGB.
|
|
|
102 |
*/
|
|
|
103 |
gx_color_index bw_pixel;
|
|
|
104 |
|
|
|
105 |
switch (rop) {
|
|
|
106 |
case rop3_0:
|
|
|
107 |
bw_pixel = gx_device_black(dev);
|
|
|
108 |
goto bw;
|
|
|
109 |
case rop3_1:
|
|
|
110 |
bw_pixel = gx_device_white(dev);
|
|
|
111 |
bw: if (bw_pixel == 0x00)
|
|
|
112 |
rop = rop3_0;
|
|
|
113 |
else if (bw_pixel == 0xff)
|
|
|
114 |
rop = rop3_1;
|
|
|
115 |
else
|
|
|
116 |
goto df;
|
|
|
117 |
break;
|
|
|
118 |
case rop3_D:
|
|
|
119 |
break;
|
|
|
120 |
case rop3_S:
|
|
|
121 |
if (lop & lop_S_transparent)
|
|
|
122 |
goto df;
|
|
|
123 |
break;
|
|
|
124 |
case rop3_T:
|
|
|
125 |
if (lop & lop_T_transparent)
|
|
|
126 |
goto df;
|
|
|
127 |
break;
|
|
|
128 |
default:
|
|
|
129 |
df: return mem_default_strip_copy_rop(dev,
|
|
|
130 |
sdata, sourcex, sraster, id,
|
|
|
131 |
scolors, textures, tcolors,
|
|
|
132 |
x, y, width, height,
|
|
|
133 |
phase_x, phase_y, lop);
|
|
|
134 |
}
|
|
|
135 |
}
|
|
|
136 |
|
|
|
137 |
/* Adjust coordinates to be in bounds. */
|
|
|
138 |
if (const_source == gx_no_color_index) {
|
|
|
139 |
fit_copy(dev, sdata, sourcex, sraster, id,
|
|
|
140 |
x, y, width, height);
|
|
|
141 |
} else {
|
|
|
142 |
fit_fill(dev, x, y, width, height);
|
|
|
143 |
}
|
|
|
144 |
|
|
|
145 |
/* Set up transfer parameters. */
|
|
|
146 |
line_count = height;
|
|
|
147 |
drow = scan_line_base(mdev, y) + x * bpp;
|
|
|
148 |
|
|
|
149 |
/*
|
|
|
150 |
* There are 18 cases depending on whether each of the source and
|
|
|
151 |
* texture is constant, 1-bit, or multi-bit, and on whether the
|
|
|
152 |
* depth is 8 or 24 bits. We divide first according to constant
|
|
|
153 |
* vs. non-constant, and then according to 1- vs. multi-bit, and
|
|
|
154 |
* finally according to pixel depth. This minimizes source code,
|
|
|
155 |
* but not necessarily time, since we do some of the divisions
|
|
|
156 |
* within 1 or 2 levels of loop.
|
|
|
157 |
*/
|
|
|
158 |
|
|
|
159 |
#define dbit(base, i) ((base)[(i) >> 3] & (0x80 >> ((i) & 7)))
|
|
|
160 |
/* 8-bit */
|
|
|
161 |
#define cbit8(base, i, colors)\
|
|
|
162 |
(dbit(base, i) ? (byte)colors[1] : (byte)colors[0])
|
|
|
163 |
#define rop_body_8(s_pixel, t_pixel)\
|
|
|
164 |
if ( (s_pixel) == strans || /* So = 0, s_tr = 1 */\
|
|
|
165 |
(t_pixel) == ttrans /* Po = 0, p_tr = 1 */\
|
|
|
166 |
)\
|
|
|
167 |
continue;\
|
|
|
168 |
*dptr = (*rop_proc_table[rop])(*dptr, s_pixel, t_pixel)
|
|
|
169 |
/* 24-bit */
|
|
|
170 |
#define get24(ptr)\
|
|
|
171 |
(((gx_color_index)(ptr)[0] << 16) | ((gx_color_index)(ptr)[1] << 8) | (ptr)[2])
|
|
|
172 |
#define put24(ptr, pixel)\
|
|
|
173 |
(ptr)[0] = (byte)((pixel) >> 16),\
|
|
|
174 |
(ptr)[1] = (byte)((uint)(pixel) >> 8),\
|
|
|
175 |
(ptr)[2] = (byte)(pixel)
|
|
|
176 |
#define cbit24(base, i, colors)\
|
|
|
177 |
(dbit(base, i) ? colors[1] : colors[0])
|
|
|
178 |
#define rop_body_24(s_pixel, t_pixel)\
|
|
|
179 |
if ( (s_pixel) == strans || /* So = 0, s_tr = 1 */\
|
|
|
180 |
(t_pixel) == ttrans /* Po = 0, p_tr = 1 */\
|
|
|
181 |
)\
|
|
|
182 |
continue;\
|
|
|
183 |
{ gx_color_index d_pixel = get24(dptr);\
|
|
|
184 |
d_pixel = (*rop_proc_table[rop])(d_pixel, s_pixel, t_pixel);\
|
|
|
185 |
put24(dptr, d_pixel);\
|
|
|
186 |
}
|
|
|
187 |
|
|
|
188 |
if (const_texture != gx_no_color_index) {
|
|
|
189 |
/**** Constant texture ****/
|
|
|
190 |
if (const_source != gx_no_color_index) {
|
|
|
191 |
/**** Constant source & texture ****/
|
|
|
192 |
for (; line_count-- > 0; drow += draster) {
|
|
|
193 |
byte *dptr = drow;
|
|
|
194 |
int left = width;
|
|
|
195 |
|
|
|
196 |
if (bpp == 1)
|
|
|
197 |
/**** 8-bit destination ****/
|
|
|
198 |
for (; left > 0; ++dptr, --left) {
|
|
|
199 |
rop_body_8((byte)const_source, (byte)const_texture);
|
|
|
200 |
}
|
|
|
201 |
else
|
|
|
202 |
/**** 24-bit destination ****/
|
|
|
203 |
for (; left > 0; dptr += 3, --left) {
|
|
|
204 |
rop_body_24(const_source, const_texture);
|
|
|
205 |
}
|
|
|
206 |
}
|
|
|
207 |
} else {
|
|
|
208 |
/**** Data source, const texture ****/
|
|
|
209 |
const byte *srow = sdata;
|
|
|
210 |
|
|
|
211 |
for (; line_count-- > 0; drow += draster, srow += sraster) {
|
|
|
212 |
byte *dptr = drow;
|
|
|
213 |
int left = width;
|
|
|
214 |
|
|
|
215 |
if (scolors) {
|
|
|
216 |
/**** 1-bit source ****/
|
|
|
217 |
int sx = sourcex;
|
|
|
218 |
|
|
|
219 |
if (bpp == 1)
|
|
|
220 |
/**** 8-bit destination ****/
|
|
|
221 |
for (; left > 0; ++dptr, ++sx, --left) {
|
|
|
222 |
byte s_pixel = cbit8(srow, sx, scolors);
|
|
|
223 |
|
|
|
224 |
rop_body_8(s_pixel, (byte)const_texture);
|
|
|
225 |
}
|
|
|
226 |
else
|
|
|
227 |
/**** 24-bit destination ****/
|
|
|
228 |
for (; left > 0; dptr += 3, ++sx, --left) {
|
|
|
229 |
bits32 s_pixel = cbit24(srow, sx, scolors);
|
|
|
230 |
|
|
|
231 |
rop_body_24(s_pixel, const_texture);
|
|
|
232 |
}
|
|
|
233 |
} else if (bpp == 1) {
|
|
|
234 |
/**** 8-bit source & dest ****/
|
|
|
235 |
const byte *sptr = srow + sourcex;
|
|
|
236 |
|
|
|
237 |
for (; left > 0; ++dptr, ++sptr, --left) {
|
|
|
238 |
byte s_pixel = *sptr;
|
|
|
239 |
|
|
|
240 |
rop_body_8(s_pixel, (byte)const_texture);
|
|
|
241 |
}
|
|
|
242 |
} else {
|
|
|
243 |
/**** 24-bit source & dest ****/
|
|
|
244 |
const byte *sptr = srow + sourcex * 3;
|
|
|
245 |
|
|
|
246 |
for (; left > 0; dptr += 3, sptr += 3, --left) {
|
|
|
247 |
bits32 s_pixel = get24(sptr);
|
|
|
248 |
|
|
|
249 |
rop_body_24(s_pixel, const_texture);
|
|
|
250 |
}
|
|
|
251 |
}
|
|
|
252 |
}
|
|
|
253 |
}
|
|
|
254 |
} else if (const_source != gx_no_color_index) {
|
|
|
255 |
/**** Const source, data texture ****/
|
|
|
256 |
uint traster = textures->raster;
|
|
|
257 |
int ty = y + phase_y;
|
|
|
258 |
|
|
|
259 |
for (; line_count-- > 0; drow += draster, ++ty) { /* Loop over copies of the tile. */
|
|
|
260 |
int dx = x, w = width, nw;
|
|
|
261 |
byte *dptr = drow;
|
|
|
262 |
const byte *trow =
|
|
|
263 |
textures->data + (ty % textures->size.y) * traster;
|
|
|
264 |
int xoff = x_offset(phase_x, ty, textures);
|
|
|
265 |
|
|
|
266 |
for (; w > 0; dx += nw, w -= nw) {
|
|
|
267 |
int tx = (dx + xoff) % textures->rep_width;
|
|
|
268 |
int left = nw = min(w, textures->size.x - tx);
|
|
|
269 |
const byte *tptr = trow;
|
|
|
270 |
|
|
|
271 |
if (tcolors) {
|
|
|
272 |
/**** 1-bit texture ****/
|
|
|
273 |
if (bpp == 1)
|
|
|
274 |
/**** 8-bit dest ****/
|
|
|
275 |
for (; left > 0; ++dptr, ++tx, --left) {
|
|
|
276 |
byte t_pixel = cbit8(tptr, tx, tcolors);
|
|
|
277 |
|
|
|
278 |
rop_body_8((byte)const_source, t_pixel);
|
|
|
279 |
}
|
|
|
280 |
else
|
|
|
281 |
/**** 24-bit dest ****/
|
|
|
282 |
for (; left > 0; dptr += 3, ++tx, --left) {
|
|
|
283 |
bits32 t_pixel = cbit24(tptr, tx, tcolors);
|
|
|
284 |
|
|
|
285 |
rop_body_24(const_source, t_pixel);
|
|
|
286 |
}
|
|
|
287 |
} else if (bpp == 1) {
|
|
|
288 |
/**** 8-bit T & D ****/
|
|
|
289 |
tptr += tx;
|
|
|
290 |
for (; left > 0; ++dptr, ++tptr, --left) {
|
|
|
291 |
byte t_pixel = *tptr;
|
|
|
292 |
|
|
|
293 |
rop_body_8((byte)const_source, t_pixel);
|
|
|
294 |
}
|
|
|
295 |
} else {
|
|
|
296 |
/**** 24-bit T & D ****/
|
|
|
297 |
tptr += tx * 3;
|
|
|
298 |
for (; left > 0; dptr += 3, tptr += 3, --left) {
|
|
|
299 |
bits32 t_pixel = get24(tptr);
|
|
|
300 |
|
|
|
301 |
rop_body_24(const_source, t_pixel);
|
|
|
302 |
}
|
|
|
303 |
}
|
|
|
304 |
}
|
|
|
305 |
}
|
|
|
306 |
} else {
|
|
|
307 |
/**** Data source & texture ****/
|
|
|
308 |
uint traster = textures->raster;
|
|
|
309 |
int ty = y + phase_y;
|
|
|
310 |
const byte *srow = sdata;
|
|
|
311 |
|
|
|
312 |
/* Loop over scan lines. */
|
|
|
313 |
for (; line_count-- > 0; drow += draster, srow += sraster, ++ty) { /* Loop over copies of the tile. */
|
|
|
314 |
int sx = sourcex;
|
|
|
315 |
int dx = x;
|
|
|
316 |
int w = width;
|
|
|
317 |
int nw;
|
|
|
318 |
byte *dptr = drow;
|
|
|
319 |
const byte *trow =
|
|
|
320 |
textures->data + (ty % textures->size.y) * traster;
|
|
|
321 |
int xoff = x_offset(phase_x, ty, textures);
|
|
|
322 |
|
|
|
323 |
for (; w > 0; dx += nw, w -= nw) { /* Loop over individual pixels. */
|
|
|
324 |
int tx = (dx + xoff) % textures->rep_width;
|
|
|
325 |
int left = nw = min(w, textures->size.x - tx);
|
|
|
326 |
const byte *tptr = trow;
|
|
|
327 |
|
|
|
328 |
/*
|
|
|
329 |
* For maximum speed, we should split this loop
|
|
|
330 |
* into 7 cases depending on source & texture
|
|
|
331 |
* depth: (1,1), (1,8), (1,24), (8,1), (8,8),
|
|
|
332 |
* (24,1), (24,24). But since we expect these
|
|
|
333 |
* cases to be relatively uncommon, we just
|
|
|
334 |
* divide on the destination depth.
|
|
|
335 |
*/
|
|
|
336 |
if (bpp == 1) {
|
|
|
337 |
/**** 8-bit destination ****/
|
|
|
338 |
const byte *sptr = srow + sx;
|
|
|
339 |
|
|
|
340 |
tptr += tx;
|
|
|
341 |
for (; left > 0; ++dptr, ++sptr, ++tptr, ++sx, ++tx, --left) {
|
|
|
342 |
byte s_pixel =
|
|
|
343 |
(scolors ? cbit8(srow, sx, scolors) : *sptr);
|
|
|
344 |
byte t_pixel =
|
|
|
345 |
(tcolors ? cbit8(tptr, tx, tcolors) : *tptr);
|
|
|
346 |
|
|
|
347 |
rop_body_8(s_pixel, t_pixel);
|
|
|
348 |
}
|
|
|
349 |
} else {
|
|
|
350 |
/**** 24-bit destination ****/
|
|
|
351 |
const byte *sptr = srow + sx * 3;
|
|
|
352 |
|
|
|
353 |
tptr += tx * 3;
|
|
|
354 |
for (; left > 0; dptr += 3, sptr += 3, tptr += 3, ++sx, ++tx, --left) {
|
|
|
355 |
bits32 s_pixel =
|
|
|
356 |
(scolors ? cbit24(srow, sx, scolors) :
|
|
|
357 |
get24(sptr));
|
|
|
358 |
bits32 t_pixel =
|
|
|
359 |
(tcolors ? cbit24(tptr, tx, tcolors) :
|
|
|
360 |
get24(tptr));
|
|
|
361 |
|
|
|
362 |
rop_body_24(s_pixel, t_pixel);
|
|
|
363 |
}
|
|
|
364 |
}
|
|
|
365 |
}
|
|
|
366 |
}
|
|
|
367 |
}
|
|
|
368 |
#undef rop_body_8
|
|
|
369 |
#undef rop_body_24
|
|
|
370 |
#undef dbit
|
|
|
371 |
#undef cbit8
|
|
|
372 |
#undef cbit24
|
|
|
373 |
return 0;
|
|
|
374 |
}
|