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: gdevmr1.c,v 1.5 2002/08/22 07:12:28 henrys Exp $ */
18 /* RasterOp implementation for monobit 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 "gdevmrop.h"
30
31 /* Calculate the X offset for a given Y value, */
32 /* taking shift into account if necessary. */
33 #define x_offset(px, ty, textures)\
34 ((textures)->shift == 0 ? (px) :\
35 (px) + (ty) / (textures)->rep_height * (textures)->rep_shift)
36
37 /* ---------------- Monobit RasterOp ---------------- */
38
39 int
mem_mono_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)40 mem_mono_strip_copy_rop(gx_device * dev,
41 const byte * sdata, int sourcex, uint sraster, gx_bitmap_id id,
42 const gx_color_index * scolors,
43 const gx_strip_bitmap * textures, const gx_color_index * tcolors,
44 int x, int y, int width, int height,
45 int phase_x, int phase_y, gs_logical_operation_t lop)
46 {
47 gx_device_memory *mdev = (gx_device_memory *) dev;
48 gs_rop3_t rop = gs_transparent_rop(lop); /* handle transparency */
49 gx_strip_bitmap no_texture;
50 bool invert;
51 uint draster = mdev->raster;
52 uint traster;
53 int line_count;
54 byte *drow;
55 const byte *srow;
56 int ty;
57
58 /* If map_rgb_color isn't the default one for monobit memory */
59 /* devices, palette might not be set; set it now if needed. */
60 if (mdev->palette.data == 0) {
61 gx_color_value cv[3];
62 cv[0] = cv[1] = cv[2] = 0;
63 gdev_mem_mono_set_inverted(mdev,
64 (*dev_proc(dev, map_rgb_color))
65 (dev, cv) != 0);
66 }
67 invert = mdev->palette.data[0] != 0;
68
69 #ifdef DEBUG
70 if (gs_debug_c('b'))
71 trace_copy_rop("mem_mono_strip_copy_rop",
72 dev, sdata, sourcex, sraster,
73 id, scolors, textures, tcolors,
74 x, y, width, height, phase_x, phase_y, lop);
75 if (gs_debug_c('B'))
76 debug_dump_bitmap(scan_line_base(mdev, y), mdev->raster,
77 height, "initial dest bits");
78 #endif
79
80 /*
81 * RasterOp is defined as operating in RGB space; in the monobit
82 * case, this means black = 0, white = 1. However, most monobit
83 * devices use the opposite convention. To make this work,
84 * we must precondition the Boolean operation by swapping the
85 * order of bits end-for-end and then inverting.
86 */
87
88 if (invert)
89 rop = byte_reverse_bits[rop] ^ 0xff;
90
91 /*
92 * From this point on, rop works in terms of device pixel values,
93 * not RGB-space values.
94 */
95
96 /* Modify the raster operation according to the source palette. */
97 if (scolors != 0) { /* Source with palette. */
98 switch ((int)((scolors[1] << 1) + scolors[0])) {
99 case 0:
100 rop = rop3_know_S_0(rop);
101 break;
102 case 1:
103 rop = rop3_invert_S(rop);
104 break;
105 case 2:
106 break;
107 case 3:
108 rop = rop3_know_S_1(rop);
109 break;
110 }
111 }
112 /* Modify the raster operation according to the texture palette. */
113 if (tcolors != 0) { /* Texture with palette. */
114 switch ((int)((tcolors[1] << 1) + tcolors[0])) {
115 case 0:
116 rop = rop3_know_T_0(rop);
117 break;
118 case 1:
119 rop = rop3_invert_T(rop);
120 break;
121 case 2:
122 break;
123 case 3:
124 rop = rop3_know_T_1(rop);
125 break;
126 }
127 }
128 /* Handle constant source and/or texture, and other special cases. */
129 {
130 gx_color_index color0, color1;
131
132 switch (rop_usage_table[rop]) {
133 case rop_usage_none:
134 /* We're just filling with a constant. */
135 return (*dev_proc(dev, fill_rectangle))
136 (dev, x, y, width, height, (gx_color_index) (rop & 1));
137 case rop_usage_D:
138 /* This is either D (no-op) or ~D. */
139 if (rop == rop3_D)
140 return 0;
141 /* Code no_S inline, then finish with no_T. */
142 fit_fill(dev, x, y, width, height);
143 sdata = scan_line_base(mdev, 0);
144 sourcex = x;
145 sraster = 0;
146 goto no_T;
147 case rop_usage_S:
148 /* This is either S or ~S, which copy_mono can handle. */
149 if (rop == rop3_S)
150 color0 = 0, color1 = 1;
151 else
152 color0 = 1, color1 = 0;
153 do_copy:return (*dev_proc(dev, copy_mono))
154 (dev, sdata, sourcex, sraster, id, x, y, width, height,
155 color0, color1);
156 case rop_usage_DS:
157 /* This might be a case that copy_mono can handle. */
158 #define copy_case(c0, c1) color0 = c0, color1 = c1; goto do_copy;
159 switch ((uint) rop) { /* cast shuts up picky compilers */
160 case rop3_D & rop3_not(rop3_S):
161 copy_case(gx_no_color_index, 0);
162 case rop3_D | rop3_S:
163 copy_case(gx_no_color_index, 1);
164 case rop3_D & rop3_S:
165 copy_case(0, gx_no_color_index);
166 case rop3_D | rop3_not(rop3_S):
167 copy_case(1, gx_no_color_index);
168 default:;
169 }
170 #undef copy_case
171 fit_copy(dev, sdata, sourcex, sraster, id, x, y, width, height);
172 no_T: /* Texture is not used; textures may be garbage. */
173 no_texture.data = scan_line_base(mdev, 0); /* arbitrary */
174 no_texture.raster = 0;
175 no_texture.size.x = width;
176 no_texture.size.y = height;
177 no_texture.rep_width = no_texture.rep_height = 1;
178 no_texture.rep_shift = no_texture.shift = 0;
179 textures = &no_texture;
180 break;
181 case rop_usage_T:
182 /* This is either T or ~T, which tile_rectangle can handle. */
183 if (rop == rop3_T)
184 color0 = 0, color1 = 1;
185 else
186 color0 = 1, color1 = 0;
187 do_tile:return (*dev_proc(dev, strip_tile_rectangle))
188 (dev, textures, x, y, width, height, color0, color1,
189 phase_x, phase_y);
190 case rop_usage_DT:
191 /* This might be a case that tile_rectangle can handle. */
192 #define tile_case(c0, c1) color0 = c0, color1 = c1; goto do_tile;
193 switch ((uint) rop) { /* cast shuts up picky compilers */
194 case rop3_D & rop3_not(rop3_T):
195 tile_case(gx_no_color_index, 0);
196 case rop3_D | rop3_T:
197 tile_case(gx_no_color_index, 1);
198 case rop3_D & rop3_T:
199 tile_case(0, gx_no_color_index);
200 case rop3_D | rop3_not(rop3_T):
201 tile_case(1, gx_no_color_index);
202 default:;
203 }
204 #undef tile_case
205 fit_fill(dev, x, y, width, height);
206 /* Source is not used; sdata et al may be garbage. */
207 sdata = mdev->base; /* arbitrary, as long as all */
208 /* accesses are valid */
209 sourcex = x; /* guarantee no source skew */
210 sraster = 0;
211 break;
212 default: /* rop_usage_[D]ST */
213 fit_copy(dev, sdata, sourcex, sraster, id, x, y, width, height);
214 }
215 }
216
217 #ifdef DEBUG
218 if_debug1('b', "final rop=0x%x\n", rop);
219 #endif
220
221 /* Set up transfer parameters. */
222 line_count = height;
223 srow = sdata;
224 drow = scan_line_base(mdev, y);
225 traster = textures->raster;
226 ty = y + phase_y;
227
228 /* Loop over scan lines. */
229 for (; line_count-- > 0; drow += draster, srow += sraster, ++ty) {
230 int sx = sourcex;
231 int dx = x;
232 int w = width;
233 const byte *trow =
234 textures->data + (ty % textures->rep_height) * traster;
235 int xoff = x_offset(phase_x, ty, textures);
236 int nw;
237
238 /* Loop over (horizontal) copies of the tile. */
239 for (; w > 0; sx += nw, dx += nw, w -= nw) {
240 int dbit = dx & 7;
241 int sbit = sx & 7;
242 int sskew = sbit - dbit;
243 int tx = (dx + xoff) % textures->rep_width;
244 int tbit = tx & 7;
245 int tskew = tbit - dbit;
246 int left = nw = min(w, textures->size.x - tx);
247 byte lmask = 0xff >> dbit;
248 byte rmask = 0xff << (~(dbit + nw - 1) & 7);
249 byte mask = lmask;
250 int nx = 8 - dbit;
251 byte *dptr = drow + (dx >> 3);
252 const byte *sptr = srow + (sx >> 3);
253 const byte *tptr = trow + (tx >> 3);
254
255 if (sskew < 0)
256 --sptr, sskew += 8;
257 if (tskew < 0)
258 --tptr, tskew += 8;
259 for (; left > 0;
260 left -= nx, mask = 0xff, nx = 8,
261 ++dptr, ++sptr, ++tptr
262 ) {
263 byte dbyte = *dptr;
264
265 #define fetch1(ptr, skew)\
266 (skew ? (ptr[0] << skew) + (ptr[1] >> (8 - skew)) : *ptr)
267 byte sbyte = fetch1(sptr, sskew);
268 byte tbyte = fetch1(tptr, tskew);
269
270 #undef fetch1
271 byte result =
272 (*rop_proc_table[rop]) (dbyte, sbyte, tbyte);
273
274 if (left <= nx)
275 mask &= rmask;
276 *dptr = (mask == 0xff ? result :
277 (result & mask) | (dbyte & ~mask));
278 }
279 }
280 }
281 #ifdef DEBUG
282 if (gs_debug_c('B'))
283 debug_dump_bitmap(scan_line_base(mdev, y), mdev->raster,
284 height, "final dest bits");
285 #endif
286 return 0;
287 }
288