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