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) 1993, 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: gxclip2.c,v 1.11 2004/06/24 05:03:36 dan Exp $ */
18
/* Mask clipping for patterns */
19
#include "memory_.h"
20
#include "gx.h"
21
#include "gserrors.h"
22
#include "gsstruct.h"
23
#include "gxdevice.h"
24
#include "gxdevmem.h"
25
#include "gxclip2.h"
26
 
27
private_st_device_tile_clip();
28
 
29
/* Device procedures */
30
private dev_proc_fill_rectangle(tile_clip_fill_rectangle);
31
private dev_proc_copy_mono(tile_clip_copy_mono);
32
private dev_proc_copy_color(tile_clip_copy_color);
33
private dev_proc_copy_alpha(tile_clip_copy_alpha);
34
private dev_proc_strip_copy_rop(tile_clip_strip_copy_rop);
35
 
36
/* The device descriptor. */
37
private const gx_device_tile_clip gs_tile_clip_device =
38
{std_device_std_body_open(gx_device_tile_clip, 0, "tile clipper",
39
			  0, 0, 1, 1),
40
 {gx_default_open_device,
41
  gx_forward_get_initial_matrix,
42
  gx_default_sync_output,
43
  gx_default_output_page,
44
  gx_default_close_device,
45
  gx_forward_map_rgb_color,
46
  gx_forward_map_color_rgb,
47
  tile_clip_fill_rectangle,
48
  gx_default_tile_rectangle,
49
  tile_clip_copy_mono,
50
  tile_clip_copy_color,
51
  gx_default_draw_line,
52
  gx_forward_get_bits,
53
  gx_forward_get_params,
54
  gx_forward_put_params,
55
  gx_forward_map_cmyk_color,
56
  gx_forward_get_xfont_procs,
57
  gx_forward_get_xfont_device,
58
  gx_forward_map_rgb_alpha_color,
59
  gx_forward_get_page_device,
60
  gx_forward_get_alpha_bits,
61
  tile_clip_copy_alpha,
62
  gx_forward_get_band,
63
  gx_default_copy_rop,
64
  gx_default_fill_path,
65
  gx_default_stroke_path,
66
  gx_default_fill_mask,
67
  gx_default_fill_trapezoid,
68
  gx_default_fill_parallelogram,
69
  gx_default_fill_triangle,
70
  gx_default_draw_thin_line,
71
  gx_default_begin_image,
72
  gx_default_image_data,
73
  gx_default_end_image,
74
  gx_default_strip_tile_rectangle,
75
  tile_clip_strip_copy_rop,
76
  gx_forward_get_clipping_box,
77
  gx_default_begin_typed_image,
78
  gx_forward_get_bits_rectangle,
79
  gx_forward_map_color_rgb_alpha,
80
  gx_no_create_compositor,
81
  gx_forward_get_hardware_params,
82
  gx_default_text_begin,
83
  gx_default_finish_copydevice,
84
  NULL,			/* begin_transparency_group */
85
  NULL,			/* end_transparency_group */
86
  NULL,			/* begin_transparency_mask */
87
  NULL,			/* end_transparency_mask */
88
  NULL,			/* discard_transparency_layer */
89
  gx_forward_get_color_mapping_procs,
90
  gx_forward_get_color_comp_index,
91
  gx_forward_encode_color,
92
  gx_forward_decode_color,
93
  gx_forward_pattern_manage,
94
  gx_forward_fill_rectangle_hl_color,
95
  gx_forward_include_color_space,
96
  gx_forward_fill_linear_color_scanline,
97
  gx_forward_fill_linear_color_trapezoid,
98
  gx_forward_fill_linear_color_triangle,
99
  gx_forward_update_spot_equivalent_colors
100
 }
101
};
102
 
103
/* Initialize a tile clipping device from a mask. */
104
int
105
tile_clip_initialize(gx_device_tile_clip * cdev, const gx_strip_bitmap * tiles,
106
		     gx_device * tdev, int px, int py, gs_memory_t *mem)
107
{
108
    int code =
109
    gx_mask_clip_initialize(cdev, &gs_tile_clip_device,
110
			    (const gx_bitmap *)tiles,
111
			    tdev, 0, 0, mem);	/* phase will be reset */
112
 
113
    if (code >= 0) {
114
	cdev->tiles = *tiles;
115
	tile_clip_set_phase(cdev, px, py);
116
    }
117
    return code;
118
}
119
 
120
/* Set the phase of the tile. */
121
void
122
tile_clip_set_phase(gx_device_tile_clip * cdev, int px, int py)
123
{
124
    cdev->phase.x = px;
125
    cdev->phase.y = py;
126
}
127
 
128
/* Fill a rectangle by tiling with the mask. */
129
private int
130
tile_clip_fill_rectangle(gx_device * dev, int x, int y, int w, int h,
131
			 gx_color_index color)
132
{
133
    gx_device_tile_clip *cdev = (gx_device_tile_clip *) dev;
134
    gx_device *tdev = cdev->target;
135
 
136
    return (*dev_proc(tdev, strip_tile_rectangle)) (tdev, &cdev->tiles,
137
						    x, y, w, h,
138
		    gx_no_color_index, color, cdev->phase.x, cdev->phase.y);
139
}
140
 
141
/* Calculate the X offset corresponding to a given Y, taking the phase */
142
/* and shift into account. */
143
#define x_offset(ty, cdev)\
144
  ((cdev)->phase.x + (((ty) + (cdev)->phase.y) / (cdev)->tiles.rep_height) *\
145
   (cdev)->tiles.rep_shift)
146
 
147
/* Copy a monochrome bitmap.  We divide it up into maximal chunks */
148
/* that line up with a single tile, and then do the obvious Boolean */
149
/* combination of the tile mask and the source. */
150
private int
151
tile_clip_copy_mono(gx_device * dev,
152
		const byte * data, int sourcex, int raster, gx_bitmap_id id,
153
		    int x, int y, int w, int h,
154
		    gx_color_index color0, gx_color_index color1)
155
{
156
    gx_device_tile_clip *cdev = (gx_device_tile_clip *) dev;
157
    gx_color_index color, mcolor0, mcolor1;
158
    int ty, ny;
159
    int code;
160
 
161
    setup_mask_copy_mono(cdev, color, mcolor0, mcolor1);
162
    for (ty = y; ty < y + h; ty += ny) {
163
	int tx, nx;
164
	int cy = (ty + cdev->phase.y) % cdev->tiles.rep_height;
165
	int xoff = x_offset(ty, cdev);
166
 
167
	ny = min(y + h - ty, cdev->tiles.size.y - cy);
168
	if (ny > cdev->mdev.height)
169
	    ny = cdev->mdev.height;
170
	for (tx = x; tx < x + w; tx += nx) {
171
	    int cx = (tx + xoff) % cdev->tiles.rep_width;
172
 
173
	    nx = min(x + w - tx, cdev->tiles.size.x - cx);
174
	    /* Copy a tile slice to the memory device buffer. */
175
	    memcpy(cdev->buffer.bytes,
176
		   cdev->tiles.data + cy * cdev->tiles.raster,
177
		   cdev->tiles.raster * ny);
178
	    /* Intersect the tile with the source data. */
179
	    /* mcolor0 and mcolor1 invert the data if needed. */
180
	    /* This call can't fail. */
181
	    (*dev_proc(&cdev->mdev, copy_mono)) ((gx_device *) & cdev->mdev,
182
				 data + (ty - y) * raster, sourcex + tx - x,
183
						 raster, gx_no_bitmap_id,
184
					   cx, 0, nx, ny, mcolor0, mcolor1);
185
	    /* Now copy the color through the double mask. */
186
	    code = (*dev_proc(cdev->target, copy_mono)) (cdev->target,
187
				 cdev->buffer.bytes, cx, cdev->tiles.raster,
188
							 gx_no_bitmap_id,
189
				  tx, ty, nx, ny, gx_no_color_index, color);
190
	    if (code < 0)
191
		return code;
192
	}
193
    }
194
    return 0;
195
}
196
 
197
/*
198
 * Define the skeleton for the other copying operations.  We can't use the
199
 * BitBlt tricks: we have to scan for runs of 1s.  There are many obvious
200
 * ways to speed this up; we'll implement some if we need to.  The schema
201
 * is:
202
 *      FOR_RUNS(data_row, tx1, tx, ty) {
203
 *        ... process the run ([tx1,tx),ty) ...
204
 *      } END_FOR_RUNS();
205
 * Free variables: cdev, data, sourcex, raster, x, y, w, h.
206
 */
207
#define t_next(tx)\
208
  BEGIN {\
209
    if ( ++cx == cdev->tiles.size.x )\
210
      cx = 0, tp = tile_row, tbit = 0x80;\
211
    else if ( (tbit >>= 1) == 0 )\
212
      tp++, tbit = 0x80;\
213
    tx++;\
214
  } END
215
#define FOR_RUNS(data_row, tx1, tx, ty)\
216
	const byte *data_row = data;\
217
	int cy = (y + cdev->phase.y) % cdev->tiles.rep_height;\
218
	const byte *tile_row = cdev->tiles.data + cy * cdev->tiles.raster;\
219
	int ty;\
220
\
221
	for ( ty = y; ty < y + h; ty++, data_row += raster ) {\
222
	  int cx = (x + x_offset(ty, cdev)) % cdev->tiles.rep_width;\
223
	  const byte *tp = tile_row + (cx >> 3);\
224
	  byte tbit = 0x80 >> (cx & 7);\
225
	  int tx;\
226
\
227
	  for ( tx = x; tx < x + w; ) {\
228
	    int tx1;\
229
\
230
	    /* Skip a run of 0s. */\
231
	    while ( tx < x + w && (*tp & tbit) == 0 )\
232
	      t_next(tx);\
233
	    if ( tx == x + w )\
234
	      break;\
235
	    /* Scan a run of 1s. */\
236
	    tx1 = tx;\
237
	    do {\
238
	      t_next(tx);\
239
	    } while ( tx < x + w && (*tp & tbit) != 0 );\
240
	    if_debug3('T', "[T]run x=(%d,%d), y=%d\n", tx1, tx, ty);
241
/* (body goes here) */
242
#define END_FOR_RUNS()\
243
	  }\
244
	  if ( ++cy == cdev->tiles.size.y )\
245
	    cy = 0, tile_row = cdev->tiles.data;\
246
	  else\
247
	    tile_row += cdev->tiles.raster;\
248
	}
249
 
250
/* Copy a color rectangle. */
251
private int
252
tile_clip_copy_color(gx_device * dev,
253
		const byte * data, int sourcex, int raster, gx_bitmap_id id,
254
		     int x, int y, int w, int h)
255
{
256
    gx_device_tile_clip *cdev = (gx_device_tile_clip *) dev;
257
 
258
    FOR_RUNS(data_row, txrun, tx, ty) {
259
	/* Copy the run. */
260
	int code = (*dev_proc(cdev->target, copy_color))
261
	(cdev->target, data_row, sourcex + txrun - x, raster,
262
	 gx_no_bitmap_id, txrun, ty, tx - txrun, 1);
263
 
264
	if (code < 0)
265
	    return code;
266
    }
267
    END_FOR_RUNS();
268
    return 0;
269
}
270
 
271
/* Copy an alpha rectangle similarly. */
272
private int
273
tile_clip_copy_alpha(gx_device * dev,
274
		const byte * data, int sourcex, int raster, gx_bitmap_id id,
275
		int x, int y, int w, int h, gx_color_index color, int depth)
276
{
277
    gx_device_tile_clip *cdev = (gx_device_tile_clip *) dev;
278
 
279
    FOR_RUNS(data_row, txrun, tx, ty) {
280
	/* Copy the run. */
281
	int code = (*dev_proc(cdev->target, copy_alpha))
282
	(cdev->target, data_row, sourcex + txrun - x, raster,
283
	 gx_no_bitmap_id, txrun, ty, tx - txrun, 1, color, depth);
284
 
285
	if (code < 0)
286
	    return code;
287
    }
288
    END_FOR_RUNS();
289
    return 0;
290
}
291
 
292
/* Copy a RasterOp rectangle similarly. */
293
private int
294
tile_clip_strip_copy_rop(gx_device * dev,
295
	       const byte * data, int sourcex, uint raster, gx_bitmap_id id,
296
			 const gx_color_index * scolors,
297
	   const gx_strip_bitmap * textures, const gx_color_index * tcolors,
298
			 int x, int y, int w, int h,
299
		       int phase_x, int phase_y, gs_logical_operation_t lop)
300
{
301
    gx_device_tile_clip *cdev = (gx_device_tile_clip *) dev;
302
 
303
    FOR_RUNS(data_row, txrun, tx, ty) {
304
	/* Copy the run. */
305
	int code = (*dev_proc(cdev->target, strip_copy_rop))
306
	(cdev->target, data_row, sourcex + txrun - x, raster,
307
	 gx_no_bitmap_id, scolors, textures, tcolors,
308
	 txrun, ty, tx - txrun, 1, phase_x, phase_y, lop);
309
 
310
	if (code < 0)
311
	    return code;
312
    }
313
    END_FOR_RUNS();
314
    return 0;
315
}