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