Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 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
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
}