Subversion Repositories planix.SVN

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
/* Copyright (C) 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: gxp1fill.c,v 1.6 2004/08/05 20:15:09 stefan Exp $ */
18
/* PatternType 1 filling algorithms */
19
#include "math_.h"
20
#include "gx.h"
21
#include "gserrors.h"
22
#include "gsrop.h"
23
#include "gsmatrix.h"
24
#include "gxcspace.h"		/* for gscolor2.h */
25
#include "gxcolor2.h"
26
#include "gxdcolor.h"
27
#include "gxdevcli.h"
28
#include "gxdevmem.h"
29
#include "gxclip2.h"
30
#include "gxpcolor.h"
31
#include "gxp1impl.h"
32
 
33
/* Define the state for tile filling. */
34
typedef struct tile_fill_state_s {
35
 
36
    /* Original arguments */
37
 
38
    const gx_device_color *pdevc;	/* pattern color */
39
    int x0, y0, w0, h0;
40
    gs_logical_operation_t lop;
41
    const gx_rop_source_t *source;
42
 
43
    /* Variables set at initialization */
44
 
45
    gx_device_tile_clip cdev;
46
    gx_device *pcdev;		/* original device or &cdev */
47
    const gx_strip_bitmap *tmask;
48
    gs_int_point phase;
49
 
50
    /* Following are only for uncolored patterns */
51
 
52
    dev_color_proc_fill_rectangle((*fill_rectangle));
53
 
54
    /* Following are only for colored patterns */
55
 
56
    const gx_rop_source_t *rop_source;
57
    gx_device *orig_dev;
58
    int xoff, yoff;		/* set dynamically */
59
 
60
} tile_fill_state_t;
61
 
62
/* Initialize the filling state. */
63
private int
64
tile_fill_init(tile_fill_state_t * ptfs, const gx_device_color * pdevc,
65
	       gx_device * dev, bool set_mask_phase)
66
{
67
    gx_color_tile *m_tile = pdevc->mask.m_tile;
68
    int px, py;
69
 
70
    ptfs->pdevc = pdevc;
71
    if (m_tile == 0) {		/* no clipping */
72
	ptfs->pcdev = dev;
73
	ptfs->phase = pdevc->phase;
74
	return 0;
75
    }
76
    ptfs->pcdev = (gx_device *) & ptfs->cdev;
77
    ptfs->tmask = &m_tile->tmask;
78
    ptfs->phase.x = pdevc->mask.m_phase.x;
79
    ptfs->phase.y = pdevc->mask.m_phase.y;
80
    /*
81
     * For non-simple tiles, the phase will be reset on each pass of the
82
     * tile_by_steps loop, but for simple tiles, we must set it now.
83
     */
84
    if (set_mask_phase && m_tile->is_simple) {
85
	px = imod(-(int)(m_tile->step_matrix.tx - ptfs->phase.x + 0.5),
86
		  m_tile->tmask.rep_width);
87
	py = imod(-(int)(m_tile->step_matrix.ty - ptfs->phase.y + 0.5),
88
		  m_tile->tmask.rep_height);
89
    } else
90
	px = py = 0;
91
    return tile_clip_initialize(&ptfs->cdev, ptfs->tmask, dev, px, py, dev->memory); 
92
    /* leak ? was NULL memoryptr */
93
}
94
 
95
/*
96
 * Fill with non-standard X and Y stepping.
97
 * ptile is pdevc->colors.pattern.{m,p}_tile.
98
 * tbits_or_tmask is whichever of tbits and tmask is supplying
99
 * the tile size.
100
 * This implementation could be sped up considerably!
101
 */
102
private int
103
tile_by_steps(tile_fill_state_t * ptfs, int x0, int y0, int w0, int h0,
104
	      const gx_color_tile * ptile,
105
	      const gx_strip_bitmap * tbits_or_tmask,
106
	      int (*fill_proc) (const tile_fill_state_t * ptfs,
107
				int x, int y, int w, int h))
108
{
109
    int x1 = x0 + w0, y1 = y0 + h0;
110
    int i0, i1, j0, j1, i, j;
111
    gs_matrix step_matrix;	/* translated by phase */
112
    int code;
113
 
114
    ptfs->x0 = x0, ptfs->w0 = w0;
115
    ptfs->y0 = y0, ptfs->h0 = h0;
116
    step_matrix = ptile->step_matrix;
117
    step_matrix.tx -= ptfs->phase.x;
118
    step_matrix.ty -= ptfs->phase.y;
119
    {
120
	gs_rect bbox;		/* bounding box in device space */
121
	gs_rect ibbox;		/* bounding box in stepping space */
122
	double bbw = ptile->bbox.q.x - ptile->bbox.p.x;
123
	double bbh = ptile->bbox.q.y - ptile->bbox.p.y;
124
	double u0, v0, u1, v1;
125
 
126
	bbox.p.x = x0, bbox.p.y = y0;
127
	bbox.q.x = x1, bbox.q.y = y1;
128
	gs_bbox_transform_inverse(&bbox, &step_matrix, &ibbox);
129
	if_debug10('T',
130
	  "[T]x,y=(%d,%d) w,h=(%d,%d) => (%g,%g),(%g,%g), offset=(%g,%g)\n",
131
		   x0, y0, w0, h0,
132
		   ibbox.p.x, ibbox.p.y, ibbox.q.x, ibbox.q.y,
133
		   step_matrix.tx, step_matrix.ty);
134
	/*
135
	 * If the pattern is partly transparent and XStep/YStep is smaller
136
	 * than the device space BBox, we need to ensure that we cover
137
	 * each pixel of the rectangle being filled with *every* pattern
138
	 * that overlaps it, not just *some* pattern copy.
139
	 */
140
	u0 = ibbox.p.x - max(ptile->bbox.p.x, 0) - 0.000001;
141
	v0 = ibbox.p.y - max(ptile->bbox.p.y, 0) - 0.000001;
142
	u1 = ibbox.q.x - min(ptile->bbox.q.x, 0) + 0.000001;
143
	v1 = ibbox.q.y - min(ptile->bbox.q.y, 0) + 0.000001;
144
	if (!ptile->is_simple)
145
	    u0 -= bbw, v0 -= bbh, u1 += bbw, v1 += bbh;
146
	i0 = (int)floor(u0);
147
	j0 = (int)floor(v0);
148
	i1 = (int)ceil(u1);
149
	j1 = (int)ceil(v1);
150
    }
151
    if_debug4('T', "[T]i=(%d,%d) j=(%d,%d)\n", i0, i1, j0, j1);
152
    for (i = i0; i < i1; i++)
153
	for (j = j0; j < j1; j++) {
154
	    int x = (int)(step_matrix.xx * i +
155
			  step_matrix.yx * j + step_matrix.tx);
156
	    int y = (int)(step_matrix.xy * i +
157
			  step_matrix.yy * j + step_matrix.ty);
158
	    int w = tbits_or_tmask->size.x;
159
	    int h = tbits_or_tmask->size.y;
160
	    int xoff, yoff;
161
 
162
	    if_debug4('T', "[T]i=%d j=%d x,y=(%d,%d)", i, j, x, y);
163
	    if (x < x0)
164
		xoff = x0 - x, x = x0, w -= xoff;
165
	    else
166
		xoff = 0;
167
	    if (y < y0)
168
		yoff = y0 - y, y = y0, h -= yoff;
169
	    else
170
		yoff = 0;
171
	    if (x + w > x1)
172
		w = x1 - x;
173
	    if (y + h > y1)
174
		h = y1 - y;
175
	    if_debug6('T', "=>(%d,%d) w,h=(%d,%d) x/yoff=(%d,%d)\n",
176
		      x, y, w, h, xoff, yoff);
177
	    if (w > 0 && h > 0) {
178
		if (ptfs->pcdev == (gx_device *) & ptfs->cdev)
179
		    tile_clip_set_phase(&ptfs->cdev,
180
				imod(xoff - x, ptfs->tmask->rep_width),
181
				imod(yoff - y, ptfs->tmask->rep_height));
182
		/* Set the offsets for colored pattern fills */
183
		ptfs->xoff = xoff;
184
		ptfs->yoff = yoff;
185
		code = (*fill_proc) (ptfs, x, y, w, h);
186
		if (code < 0)
187
		    return code;
188
	    }
189
	}
190
    return 0;
191
}
192
 
193
/* Fill a rectangle with a colored Pattern. */
194
/* Note that we treat this as "texture" for RasterOp. */
195
private int
196
tile_colored_fill(const tile_fill_state_t * ptfs,
197
		  int x, int y, int w, int h)
198
{
199
    gx_color_tile *ptile = ptfs->pdevc->colors.pattern.p_tile;
200
    gs_logical_operation_t lop = ptfs->lop;
201
    const gx_rop_source_t *source = ptfs->source;
202
    const gx_rop_source_t *rop_source = ptfs->rop_source;
203
    gx_device *dev = ptfs->orig_dev;
204
    int xoff = ptfs->xoff, yoff = ptfs->yoff;
205
    gx_strip_bitmap *bits = &ptile->tbits;
206
    const byte *data = bits->data;
207
    bool full_transfer = (w == ptfs->w0 && h == ptfs->h0);
208
    gx_bitmap_id source_id =
209
    (full_transfer ? rop_source->id : gx_no_bitmap_id);
210
    int code;
211
 
212
    if (source == NULL && lop_no_S_is_T(lop))
213
	code = (*dev_proc(ptfs->pcdev, copy_color))
214
	    (ptfs->pcdev, data + bits->raster * yoff, xoff,
215
	     bits->raster,
216
	     (full_transfer ? bits->id : gx_no_bitmap_id),
217
	     x, y, w, h);
218
    else {
219
	gx_strip_bitmap data_tile;
220
 
221
	data_tile.data = (byte *) data;		/* actually const */
222
	data_tile.raster = bits->raster;
223
	data_tile.size.x = data_tile.rep_width = ptile->tbits.size.x;
224
	data_tile.size.y = data_tile.rep_height = ptile->tbits.size.y;
225
	data_tile.id = bits->id;
226
	data_tile.shift = data_tile.rep_shift = 0;
227
	code = (*dev_proc(dev, strip_copy_rop))
228
	    (dev,
229
	     rop_source->sdata + (y - ptfs->y0) * rop_source->sraster,
230
	     rop_source->sourcex + (x - ptfs->x0),
231
	     rop_source->sraster, source_id,
232
	     (rop_source->use_scolors ? rop_source->scolors : NULL),
233
	     &data_tile, NULL,
234
	     x, y, w, h,
235
	     imod(xoff - x, data_tile.rep_width),
236
	     imod(yoff - y, data_tile.rep_height),
237
	     lop);
238
    }
239
    return code;
240
}
241
int
242
gx_dc_pattern_fill_rectangle(const gx_device_color * pdevc, int x, int y,
243
			     int w, int h, gx_device * dev,
244
			     gs_logical_operation_t lop,
245
			     const gx_rop_source_t * source)
246
{
247
    gx_color_tile *ptile = pdevc->colors.pattern.p_tile;
248
    const gx_rop_source_t *rop_source = source;
249
    gx_rop_source_t no_source;
250
    gx_strip_bitmap *bits;
251
    tile_fill_state_t state;
252
    int code;
253
 
254
    if (ptile == 0)		/* null pattern */
255
	return 0;
256
    if (rop_source == NULL)
257
	set_rop_no_source(rop_source, no_source, dev);
258
    bits = &ptile->tbits;
259
    code = tile_fill_init(&state, pdevc, dev, false);
260
    if (code < 0)
261
	return code;
262
    if (ptile->is_simple) {
263
	int px =
264
	    imod(-(int)(ptile->step_matrix.tx - state.phase.x + 0.5),
265
		 bits->rep_width);
266
	int py =
267
	    imod(-(int)(ptile->step_matrix.ty - state.phase.y + 0.5),
268
		 bits->rep_height);
269
 
270
	if (state.pcdev != dev)
271
	    tile_clip_set_phase(&state.cdev, px, py);
272
	if (source == NULL && lop_no_S_is_T(lop))
273
	    code = (*dev_proc(state.pcdev, strip_tile_rectangle))
274
		(state.pcdev, bits, x, y, w, h,
275
		 gx_no_color_index, gx_no_color_index, px, py);
276
	else
277
	    code = (*dev_proc(state.pcdev, strip_copy_rop))
278
		(state.pcdev,
279
		 rop_source->sdata, rop_source->sourcex,
280
		 rop_source->sraster, rop_source->id,
281
		 (rop_source->use_scolors ? rop_source->scolors : NULL),
282
		 bits, NULL, x, y, w, h, px, py, lop);
283
    } else {
284
	state.lop = lop;
285
	state.source = source;
286
	state.rop_source = rop_source;
287
	state.orig_dev = dev;
288
	code = tile_by_steps(&state, x, y, w, h, ptile,
289
			     &ptile->tbits, tile_colored_fill);
290
    }
291
    return code;
292
}
293
 
294
/* Fill a rectangle with an uncolored Pattern. */
295
/* Note that we treat this as "texture" for RasterOp. */
296
private int
297
tile_masked_fill(const tile_fill_state_t * ptfs,
298
		 int x, int y, int w, int h)
299
{
300
    if (ptfs->source == NULL)
301
	return (*ptfs->fill_rectangle)
302
	    (ptfs->pdevc, x, y, w, h, ptfs->pcdev, ptfs->lop, NULL);
303
    else {
304
	const gx_rop_source_t *source = ptfs->source;
305
	gx_rop_source_t step_source;
306
 
307
	step_source.sdata = source->sdata + (y - ptfs->y0) * source->sraster;
308
	step_source.sourcex = source->sourcex + (x - ptfs->x0);
309
	step_source.sraster = source->sraster;
310
	step_source.id = (w == ptfs->w0 && h == ptfs->h0 ?
311
			  source->id : gx_no_bitmap_id);
312
	step_source.scolors[0] = source->scolors[0];
313
	step_source.scolors[1] = source->scolors[1];
314
	step_source.use_scolors = source->use_scolors;
315
	return (*ptfs->fill_rectangle)
316
	    (ptfs->pdevc, x, y, w, h, ptfs->pcdev, ptfs->lop, &step_source);
317
    }
318
}
319
int
320
gx_dc_pure_masked_fill_rect(const gx_device_color * pdevc,
321
			    int x, int y, int w, int h, gx_device * dev,
322
			    gs_logical_operation_t lop,
323
			    const gx_rop_source_t * source)
324
{
325
    gx_color_tile *ptile = pdevc->mask.m_tile;
326
    tile_fill_state_t state;
327
    int code;
328
 
329
    /*
330
     * This routine should never be called if there is no masking,
331
     * but we leave the checks below just in case.
332
     */
333
    code = tile_fill_init(&state, pdevc, dev, true);
334
    if (code < 0)
335
	return code;
336
    if (state.pcdev == dev || ptile->is_simple)
337
	return (*gx_dc_type_data_pure.fill_rectangle)
338
	    (pdevc, x, y, w, h, state.pcdev, lop, source);
339
    else {
340
	state.lop = lop;
341
	state.source = source;
342
	state.fill_rectangle = gx_dc_type_data_pure.fill_rectangle;
343
	return tile_by_steps(&state, x, y, w, h, ptile, &ptile->tmask,
344
			     tile_masked_fill);
345
    }
346
}
347
int
348
gx_dc_binary_masked_fill_rect(const gx_device_color * pdevc,
349
			      int x, int y, int w, int h, gx_device * dev,
350
			      gs_logical_operation_t lop,
351
			      const gx_rop_source_t * source)
352
{
353
    gx_color_tile *ptile = pdevc->mask.m_tile;
354
    tile_fill_state_t state;
355
    int code;
356
 
357
    code = tile_fill_init(&state, pdevc, dev, true);
358
    if (code < 0)
359
	return code;
360
    if (state.pcdev == dev || ptile->is_simple)
361
	return (*gx_dc_type_data_ht_binary.fill_rectangle)
362
	    (pdevc, x, y, w, h, state.pcdev, lop, source);
363
    else {
364
	state.lop = lop;
365
	state.source = source;
366
	state.fill_rectangle = gx_dc_type_data_ht_binary.fill_rectangle;
367
	return tile_by_steps(&state, x, y, w, h, ptile, &ptile->tmask,
368
			     tile_masked_fill);
369
    }
370
}
371
int
372
gx_dc_colored_masked_fill_rect(const gx_device_color * pdevc,
373
			       int x, int y, int w, int h, gx_device * dev,
374
			       gs_logical_operation_t lop,
375
			       const gx_rop_source_t * source)
376
{
377
    gx_color_tile *ptile = pdevc->mask.m_tile;
378
    tile_fill_state_t state;
379
    int code;
380
 
381
    code = tile_fill_init(&state, pdevc, dev, true);
382
    if (code < 0)
383
	return code;
384
    if (state.pcdev == dev || ptile->is_simple)
385
	return (*gx_dc_type_data_ht_colored.fill_rectangle)
386
	    (pdevc, x, y, w, h, state.pcdev, lop, source);
387
    else {
388
	state.lop = lop;
389
	state.source = source;
390
	state.fill_rectangle = gx_dc_type_data_ht_colored.fill_rectangle;
391
	return tile_by_steps(&state, x, y, w, h, ptile, &ptile->tmask,
392
			     tile_masked_fill);
393
    }
394
}