xref: /plan9/sys/src/cmd/gs/src/gdevmr8n.c (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
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
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)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 }
375