xref: /plan9/sys/src/cmd/gs/src/gxp1fill.c (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
17dd7cddfSDavid du Colombier /* Copyright (C) 1998, 1999 Aladdin Enterprises.  All rights reserved.
27dd7cddfSDavid du Colombier 
3*593dc095SDavid du Colombier   This software is provided AS-IS with no warranty, either express or
4*593dc095SDavid du Colombier   implied.
57dd7cddfSDavid du Colombier 
6*593dc095SDavid du Colombier   This software is distributed under license and may not be copied,
7*593dc095SDavid du Colombier   modified or distributed except as expressly authorized under the terms
8*593dc095SDavid du Colombier   of the license contained in the file LICENSE in this distribution.
97dd7cddfSDavid du Colombier 
10*593dc095SDavid du Colombier   For more information about licensing, please refer to
11*593dc095SDavid du Colombier   http://www.ghostscript.com/licensing/. For information on
12*593dc095SDavid du Colombier   commercial licensing, go to http://www.artifex.com/licensing/ or
13*593dc095SDavid du Colombier   contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14*593dc095SDavid du Colombier   San Rafael, CA  94903, U.S.A., +1(415)492-9861.
157dd7cddfSDavid du Colombier */
167dd7cddfSDavid du Colombier 
17*593dc095SDavid du Colombier /* $Id: gxp1fill.c,v 1.6 2004/08/05 20:15:09 stefan Exp $ */
187dd7cddfSDavid du Colombier /* PatternType 1 filling algorithms */
197dd7cddfSDavid du Colombier #include "math_.h"
207dd7cddfSDavid du Colombier #include "gx.h"
217dd7cddfSDavid du Colombier #include "gserrors.h"
227dd7cddfSDavid du Colombier #include "gsrop.h"
237dd7cddfSDavid du Colombier #include "gsmatrix.h"
247dd7cddfSDavid du Colombier #include "gxcspace.h"		/* for gscolor2.h */
257dd7cddfSDavid du Colombier #include "gxcolor2.h"
267dd7cddfSDavid du Colombier #include "gxdcolor.h"
277dd7cddfSDavid du Colombier #include "gxdevcli.h"
287dd7cddfSDavid du Colombier #include "gxdevmem.h"
297dd7cddfSDavid du Colombier #include "gxclip2.h"
307dd7cddfSDavid du Colombier #include "gxpcolor.h"
317dd7cddfSDavid du Colombier #include "gxp1impl.h"
327dd7cddfSDavid du Colombier 
337dd7cddfSDavid du Colombier /* Define the state for tile filling. */
347dd7cddfSDavid du Colombier typedef struct tile_fill_state_s {
357dd7cddfSDavid du Colombier 
367dd7cddfSDavid du Colombier     /* Original arguments */
377dd7cddfSDavid du Colombier 
387dd7cddfSDavid du Colombier     const gx_device_color *pdevc;	/* pattern color */
397dd7cddfSDavid du Colombier     int x0, y0, w0, h0;
407dd7cddfSDavid du Colombier     gs_logical_operation_t lop;
417dd7cddfSDavid du Colombier     const gx_rop_source_t *source;
427dd7cddfSDavid du Colombier 
437dd7cddfSDavid du Colombier     /* Variables set at initialization */
447dd7cddfSDavid du Colombier 
457dd7cddfSDavid du Colombier     gx_device_tile_clip cdev;
467dd7cddfSDavid du Colombier     gx_device *pcdev;		/* original device or &cdev */
477dd7cddfSDavid du Colombier     const gx_strip_bitmap *tmask;
487dd7cddfSDavid du Colombier     gs_int_point phase;
497dd7cddfSDavid du Colombier 
507dd7cddfSDavid du Colombier     /* Following are only for uncolored patterns */
517dd7cddfSDavid du Colombier 
527dd7cddfSDavid du Colombier     dev_color_proc_fill_rectangle((*fill_rectangle));
537dd7cddfSDavid du Colombier 
547dd7cddfSDavid du Colombier     /* Following are only for colored patterns */
557dd7cddfSDavid du Colombier 
567dd7cddfSDavid du Colombier     const gx_rop_source_t *rop_source;
577dd7cddfSDavid du Colombier     gx_device *orig_dev;
587dd7cddfSDavid du Colombier     int xoff, yoff;		/* set dynamically */
597dd7cddfSDavid du Colombier 
607dd7cddfSDavid du Colombier } tile_fill_state_t;
617dd7cddfSDavid du Colombier 
627dd7cddfSDavid du Colombier /* Initialize the filling state. */
637dd7cddfSDavid du Colombier private int
tile_fill_init(tile_fill_state_t * ptfs,const gx_device_color * pdevc,gx_device * dev,bool set_mask_phase)647dd7cddfSDavid du Colombier tile_fill_init(tile_fill_state_t * ptfs, const gx_device_color * pdevc,
657dd7cddfSDavid du Colombier 	       gx_device * dev, bool set_mask_phase)
667dd7cddfSDavid du Colombier {
677dd7cddfSDavid du Colombier     gx_color_tile *m_tile = pdevc->mask.m_tile;
687dd7cddfSDavid du Colombier     int px, py;
697dd7cddfSDavid du Colombier 
707dd7cddfSDavid du Colombier     ptfs->pdevc = pdevc;
717dd7cddfSDavid du Colombier     if (m_tile == 0) {		/* no clipping */
727dd7cddfSDavid du Colombier 	ptfs->pcdev = dev;
737dd7cddfSDavid du Colombier 	ptfs->phase = pdevc->phase;
747dd7cddfSDavid du Colombier 	return 0;
757dd7cddfSDavid du Colombier     }
767dd7cddfSDavid du Colombier     ptfs->pcdev = (gx_device *) & ptfs->cdev;
777dd7cddfSDavid du Colombier     ptfs->tmask = &m_tile->tmask;
787dd7cddfSDavid du Colombier     ptfs->phase.x = pdevc->mask.m_phase.x;
797dd7cddfSDavid du Colombier     ptfs->phase.y = pdevc->mask.m_phase.y;
807dd7cddfSDavid du Colombier     /*
817dd7cddfSDavid du Colombier      * For non-simple tiles, the phase will be reset on each pass of the
827dd7cddfSDavid du Colombier      * tile_by_steps loop, but for simple tiles, we must set it now.
837dd7cddfSDavid du Colombier      */
847dd7cddfSDavid du Colombier     if (set_mask_phase && m_tile->is_simple) {
857dd7cddfSDavid du Colombier 	px = imod(-(int)(m_tile->step_matrix.tx - ptfs->phase.x + 0.5),
867dd7cddfSDavid du Colombier 		  m_tile->tmask.rep_width);
877dd7cddfSDavid du Colombier 	py = imod(-(int)(m_tile->step_matrix.ty - ptfs->phase.y + 0.5),
887dd7cddfSDavid du Colombier 		  m_tile->tmask.rep_height);
897dd7cddfSDavid du Colombier     } else
907dd7cddfSDavid du Colombier 	px = py = 0;
91*593dc095SDavid du Colombier     return tile_clip_initialize(&ptfs->cdev, ptfs->tmask, dev, px, py, dev->memory);
92*593dc095SDavid du Colombier     /* leak ? was NULL memoryptr */
937dd7cddfSDavid du Colombier }
947dd7cddfSDavid du Colombier 
957dd7cddfSDavid du Colombier /*
967dd7cddfSDavid du Colombier  * Fill with non-standard X and Y stepping.
977dd7cddfSDavid du Colombier  * ptile is pdevc->colors.pattern.{m,p}_tile.
987dd7cddfSDavid du Colombier  * tbits_or_tmask is whichever of tbits and tmask is supplying
997dd7cddfSDavid du Colombier  * the tile size.
1007dd7cddfSDavid du Colombier  * This implementation could be sped up considerably!
1017dd7cddfSDavid du Colombier  */
1027dd7cddfSDavid du Colombier private int
tile_by_steps(tile_fill_state_t * ptfs,int x0,int y0,int w0,int h0,const gx_color_tile * ptile,const gx_strip_bitmap * tbits_or_tmask,int (* fill_proc)(const tile_fill_state_t * ptfs,int x,int y,int w,int h))1037dd7cddfSDavid du Colombier tile_by_steps(tile_fill_state_t * ptfs, int x0, int y0, int w0, int h0,
1047dd7cddfSDavid du Colombier 	      const gx_color_tile * ptile,
1057dd7cddfSDavid du Colombier 	      const gx_strip_bitmap * tbits_or_tmask,
106*593dc095SDavid du Colombier 	      int (*fill_proc) (const tile_fill_state_t * ptfs,
107*593dc095SDavid du Colombier 				int x, int y, int w, int h))
1087dd7cddfSDavid du Colombier {
1097dd7cddfSDavid du Colombier     int x1 = x0 + w0, y1 = y0 + h0;
1107dd7cddfSDavid du Colombier     int i0, i1, j0, j1, i, j;
1117dd7cddfSDavid du Colombier     gs_matrix step_matrix;	/* translated by phase */
1127dd7cddfSDavid du Colombier     int code;
1137dd7cddfSDavid du Colombier 
1147dd7cddfSDavid du Colombier     ptfs->x0 = x0, ptfs->w0 = w0;
1157dd7cddfSDavid du Colombier     ptfs->y0 = y0, ptfs->h0 = h0;
1167dd7cddfSDavid du Colombier     step_matrix = ptile->step_matrix;
1177dd7cddfSDavid du Colombier     step_matrix.tx -= ptfs->phase.x;
1187dd7cddfSDavid du Colombier     step_matrix.ty -= ptfs->phase.y;
1197dd7cddfSDavid du Colombier     {
1207dd7cddfSDavid du Colombier 	gs_rect bbox;		/* bounding box in device space */
1217dd7cddfSDavid du Colombier 	gs_rect ibbox;		/* bounding box in stepping space */
1227dd7cddfSDavid du Colombier 	double bbw = ptile->bbox.q.x - ptile->bbox.p.x;
1237dd7cddfSDavid du Colombier 	double bbh = ptile->bbox.q.y - ptile->bbox.p.y;
1247dd7cddfSDavid du Colombier 	double u0, v0, u1, v1;
1257dd7cddfSDavid du Colombier 
1267dd7cddfSDavid du Colombier 	bbox.p.x = x0, bbox.p.y = y0;
1277dd7cddfSDavid du Colombier 	bbox.q.x = x1, bbox.q.y = y1;
1287dd7cddfSDavid du Colombier 	gs_bbox_transform_inverse(&bbox, &step_matrix, &ibbox);
1297dd7cddfSDavid du Colombier 	if_debug10('T',
1307dd7cddfSDavid du Colombier 	  "[T]x,y=(%d,%d) w,h=(%d,%d) => (%g,%g),(%g,%g), offset=(%g,%g)\n",
1317dd7cddfSDavid du Colombier 		   x0, y0, w0, h0,
1327dd7cddfSDavid du Colombier 		   ibbox.p.x, ibbox.p.y, ibbox.q.x, ibbox.q.y,
1337dd7cddfSDavid du Colombier 		   step_matrix.tx, step_matrix.ty);
1347dd7cddfSDavid du Colombier 	/*
1357dd7cddfSDavid du Colombier 	 * If the pattern is partly transparent and XStep/YStep is smaller
1367dd7cddfSDavid du Colombier 	 * than the device space BBox, we need to ensure that we cover
1377dd7cddfSDavid du Colombier 	 * each pixel of the rectangle being filled with *every* pattern
1387dd7cddfSDavid du Colombier 	 * that overlaps it, not just *some* pattern copy.
1397dd7cddfSDavid du Colombier 	 */
1407dd7cddfSDavid du Colombier 	u0 = ibbox.p.x - max(ptile->bbox.p.x, 0) - 0.000001;
1417dd7cddfSDavid du Colombier 	v0 = ibbox.p.y - max(ptile->bbox.p.y, 0) - 0.000001;
1427dd7cddfSDavid du Colombier 	u1 = ibbox.q.x - min(ptile->bbox.q.x, 0) + 0.000001;
1437dd7cddfSDavid du Colombier 	v1 = ibbox.q.y - min(ptile->bbox.q.y, 0) + 0.000001;
1447dd7cddfSDavid du Colombier 	if (!ptile->is_simple)
1457dd7cddfSDavid du Colombier 	    u0 -= bbw, v0 -= bbh, u1 += bbw, v1 += bbh;
1467dd7cddfSDavid du Colombier 	i0 = (int)floor(u0);
1477dd7cddfSDavid du Colombier 	j0 = (int)floor(v0);
1487dd7cddfSDavid du Colombier 	i1 = (int)ceil(u1);
1497dd7cddfSDavid du Colombier 	j1 = (int)ceil(v1);
1507dd7cddfSDavid du Colombier     }
1517dd7cddfSDavid du Colombier     if_debug4('T', "[T]i=(%d,%d) j=(%d,%d)\n", i0, i1, j0, j1);
1527dd7cddfSDavid du Colombier     for (i = i0; i < i1; i++)
1537dd7cddfSDavid du Colombier 	for (j = j0; j < j1; j++) {
1547dd7cddfSDavid du Colombier 	    int x = (int)(step_matrix.xx * i +
1557dd7cddfSDavid du Colombier 			  step_matrix.yx * j + step_matrix.tx);
1567dd7cddfSDavid du Colombier 	    int y = (int)(step_matrix.xy * i +
1577dd7cddfSDavid du Colombier 			  step_matrix.yy * j + step_matrix.ty);
1587dd7cddfSDavid du Colombier 	    int w = tbits_or_tmask->size.x;
1597dd7cddfSDavid du Colombier 	    int h = tbits_or_tmask->size.y;
1607dd7cddfSDavid du Colombier 	    int xoff, yoff;
1617dd7cddfSDavid du Colombier 
1627dd7cddfSDavid du Colombier 	    if_debug4('T', "[T]i=%d j=%d x,y=(%d,%d)", i, j, x, y);
1637dd7cddfSDavid du Colombier 	    if (x < x0)
1647dd7cddfSDavid du Colombier 		xoff = x0 - x, x = x0, w -= xoff;
1657dd7cddfSDavid du Colombier 	    else
1667dd7cddfSDavid du Colombier 		xoff = 0;
1677dd7cddfSDavid du Colombier 	    if (y < y0)
1687dd7cddfSDavid du Colombier 		yoff = y0 - y, y = y0, h -= yoff;
1697dd7cddfSDavid du Colombier 	    else
1707dd7cddfSDavid du Colombier 		yoff = 0;
1717dd7cddfSDavid du Colombier 	    if (x + w > x1)
1727dd7cddfSDavid du Colombier 		w = x1 - x;
1737dd7cddfSDavid du Colombier 	    if (y + h > y1)
1747dd7cddfSDavid du Colombier 		h = y1 - y;
1757dd7cddfSDavid du Colombier 	    if_debug6('T', "=>(%d,%d) w,h=(%d,%d) x/yoff=(%d,%d)\n",
1767dd7cddfSDavid du Colombier 		      x, y, w, h, xoff, yoff);
1777dd7cddfSDavid du Colombier 	    if (w > 0 && h > 0) {
1787dd7cddfSDavid du Colombier 		if (ptfs->pcdev == (gx_device *) & ptfs->cdev)
1797dd7cddfSDavid du Colombier 		    tile_clip_set_phase(&ptfs->cdev,
1807dd7cddfSDavid du Colombier 				imod(xoff - x, ptfs->tmask->rep_width),
1817dd7cddfSDavid du Colombier 				imod(yoff - y, ptfs->tmask->rep_height));
1827dd7cddfSDavid du Colombier 		/* Set the offsets for colored pattern fills */
1837dd7cddfSDavid du Colombier 		ptfs->xoff = xoff;
1847dd7cddfSDavid du Colombier 		ptfs->yoff = yoff;
1857dd7cddfSDavid du Colombier 		code = (*fill_proc) (ptfs, x, y, w, h);
1867dd7cddfSDavid du Colombier 		if (code < 0)
1877dd7cddfSDavid du Colombier 		    return code;
1887dd7cddfSDavid du Colombier 	    }
1897dd7cddfSDavid du Colombier 	}
1907dd7cddfSDavid du Colombier     return 0;
1917dd7cddfSDavid du Colombier }
1927dd7cddfSDavid du Colombier 
1937dd7cddfSDavid du Colombier /* Fill a rectangle with a colored Pattern. */
1947dd7cddfSDavid du Colombier /* Note that we treat this as "texture" for RasterOp. */
1957dd7cddfSDavid du Colombier private int
tile_colored_fill(const tile_fill_state_t * ptfs,int x,int y,int w,int h)1967dd7cddfSDavid du Colombier tile_colored_fill(const tile_fill_state_t * ptfs,
1977dd7cddfSDavid du Colombier 		  int x, int y, int w, int h)
1987dd7cddfSDavid du Colombier {
1997dd7cddfSDavid du Colombier     gx_color_tile *ptile = ptfs->pdevc->colors.pattern.p_tile;
2007dd7cddfSDavid du Colombier     gs_logical_operation_t lop = ptfs->lop;
2017dd7cddfSDavid du Colombier     const gx_rop_source_t *source = ptfs->source;
2027dd7cddfSDavid du Colombier     const gx_rop_source_t *rop_source = ptfs->rop_source;
2037dd7cddfSDavid du Colombier     gx_device *dev = ptfs->orig_dev;
2047dd7cddfSDavid du Colombier     int xoff = ptfs->xoff, yoff = ptfs->yoff;
2057dd7cddfSDavid du Colombier     gx_strip_bitmap *bits = &ptile->tbits;
2067dd7cddfSDavid du Colombier     const byte *data = bits->data;
2077dd7cddfSDavid du Colombier     bool full_transfer = (w == ptfs->w0 && h == ptfs->h0);
2087dd7cddfSDavid du Colombier     gx_bitmap_id source_id =
2097dd7cddfSDavid du Colombier     (full_transfer ? rop_source->id : gx_no_bitmap_id);
2107dd7cddfSDavid du Colombier     int code;
2117dd7cddfSDavid du Colombier 
2127dd7cddfSDavid du Colombier     if (source == NULL && lop_no_S_is_T(lop))
2137dd7cddfSDavid du Colombier 	code = (*dev_proc(ptfs->pcdev, copy_color))
2147dd7cddfSDavid du Colombier 	    (ptfs->pcdev, data + bits->raster * yoff, xoff,
2157dd7cddfSDavid du Colombier 	     bits->raster,
2167dd7cddfSDavid du Colombier 	     (full_transfer ? bits->id : gx_no_bitmap_id),
2177dd7cddfSDavid du Colombier 	     x, y, w, h);
2187dd7cddfSDavid du Colombier     else {
2197dd7cddfSDavid du Colombier 	gx_strip_bitmap data_tile;
2207dd7cddfSDavid du Colombier 
2217dd7cddfSDavid du Colombier 	data_tile.data = (byte *) data;		/* actually const */
2227dd7cddfSDavid du Colombier 	data_tile.raster = bits->raster;
2237dd7cddfSDavid du Colombier 	data_tile.size.x = data_tile.rep_width = ptile->tbits.size.x;
2247dd7cddfSDavid du Colombier 	data_tile.size.y = data_tile.rep_height = ptile->tbits.size.y;
2257dd7cddfSDavid du Colombier 	data_tile.id = bits->id;
2267dd7cddfSDavid du Colombier 	data_tile.shift = data_tile.rep_shift = 0;
2277dd7cddfSDavid du Colombier 	code = (*dev_proc(dev, strip_copy_rop))
2287dd7cddfSDavid du Colombier 	    (dev,
2297dd7cddfSDavid du Colombier 	     rop_source->sdata + (y - ptfs->y0) * rop_source->sraster,
2307dd7cddfSDavid du Colombier 	     rop_source->sourcex + (x - ptfs->x0),
2317dd7cddfSDavid du Colombier 	     rop_source->sraster, source_id,
2327dd7cddfSDavid du Colombier 	     (rop_source->use_scolors ? rop_source->scolors : NULL),
2337dd7cddfSDavid du Colombier 	     &data_tile, NULL,
2347dd7cddfSDavid du Colombier 	     x, y, w, h,
2357dd7cddfSDavid du Colombier 	     imod(xoff - x, data_tile.rep_width),
2367dd7cddfSDavid du Colombier 	     imod(yoff - y, data_tile.rep_height),
2377dd7cddfSDavid du Colombier 	     lop);
2387dd7cddfSDavid du Colombier     }
2397dd7cddfSDavid du Colombier     return code;
2407dd7cddfSDavid du Colombier }
2417dd7cddfSDavid du Colombier int
gx_dc_pattern_fill_rectangle(const gx_device_color * pdevc,int x,int y,int w,int h,gx_device * dev,gs_logical_operation_t lop,const gx_rop_source_t * source)2427dd7cddfSDavid du Colombier gx_dc_pattern_fill_rectangle(const gx_device_color * pdevc, int x, int y,
2437dd7cddfSDavid du Colombier 			     int w, int h, gx_device * dev,
2447dd7cddfSDavid du Colombier 			     gs_logical_operation_t lop,
2457dd7cddfSDavid du Colombier 			     const gx_rop_source_t * source)
2467dd7cddfSDavid du Colombier {
2477dd7cddfSDavid du Colombier     gx_color_tile *ptile = pdevc->colors.pattern.p_tile;
2487dd7cddfSDavid du Colombier     const gx_rop_source_t *rop_source = source;
2497dd7cddfSDavid du Colombier     gx_rop_source_t no_source;
2507dd7cddfSDavid du Colombier     gx_strip_bitmap *bits;
2517dd7cddfSDavid du Colombier     tile_fill_state_t state;
2527dd7cddfSDavid du Colombier     int code;
2537dd7cddfSDavid du Colombier 
2547dd7cddfSDavid du Colombier     if (ptile == 0)		/* null pattern */
2557dd7cddfSDavid du Colombier 	return 0;
2567dd7cddfSDavid du Colombier     if (rop_source == NULL)
2577dd7cddfSDavid du Colombier 	set_rop_no_source(rop_source, no_source, dev);
2587dd7cddfSDavid du Colombier     bits = &ptile->tbits;
2597dd7cddfSDavid du Colombier     code = tile_fill_init(&state, pdevc, dev, false);
2607dd7cddfSDavid du Colombier     if (code < 0)
2617dd7cddfSDavid du Colombier 	return code;
2627dd7cddfSDavid du Colombier     if (ptile->is_simple) {
2637dd7cddfSDavid du Colombier 	int px =
2647dd7cddfSDavid du Colombier 	    imod(-(int)(ptile->step_matrix.tx - state.phase.x + 0.5),
2657dd7cddfSDavid du Colombier 		 bits->rep_width);
2667dd7cddfSDavid du Colombier 	int py =
2677dd7cddfSDavid du Colombier 	    imod(-(int)(ptile->step_matrix.ty - state.phase.y + 0.5),
2687dd7cddfSDavid du Colombier 		 bits->rep_height);
2697dd7cddfSDavid du Colombier 
2707dd7cddfSDavid du Colombier 	if (state.pcdev != dev)
2717dd7cddfSDavid du Colombier 	    tile_clip_set_phase(&state.cdev, px, py);
2727dd7cddfSDavid du Colombier 	if (source == NULL && lop_no_S_is_T(lop))
2737dd7cddfSDavid du Colombier 	    code = (*dev_proc(state.pcdev, strip_tile_rectangle))
2747dd7cddfSDavid du Colombier 		(state.pcdev, bits, x, y, w, h,
2757dd7cddfSDavid du Colombier 		 gx_no_color_index, gx_no_color_index, px, py);
2767dd7cddfSDavid du Colombier 	else
2777dd7cddfSDavid du Colombier 	    code = (*dev_proc(state.pcdev, strip_copy_rop))
2787dd7cddfSDavid du Colombier 		(state.pcdev,
2797dd7cddfSDavid du Colombier 		 rop_source->sdata, rop_source->sourcex,
2807dd7cddfSDavid du Colombier 		 rop_source->sraster, rop_source->id,
2817dd7cddfSDavid du Colombier 		 (rop_source->use_scolors ? rop_source->scolors : NULL),
2827dd7cddfSDavid du Colombier 		 bits, NULL, x, y, w, h, px, py, lop);
2837dd7cddfSDavid du Colombier     } else {
2847dd7cddfSDavid du Colombier 	state.lop = lop;
2857dd7cddfSDavid du Colombier 	state.source = source;
2867dd7cddfSDavid du Colombier 	state.rop_source = rop_source;
2877dd7cddfSDavid du Colombier 	state.orig_dev = dev;
2887dd7cddfSDavid du Colombier 	code = tile_by_steps(&state, x, y, w, h, ptile,
2897dd7cddfSDavid du Colombier 			     &ptile->tbits, tile_colored_fill);
2907dd7cddfSDavid du Colombier     }
2917dd7cddfSDavid du Colombier     return code;
2927dd7cddfSDavid du Colombier }
2937dd7cddfSDavid du Colombier 
2947dd7cddfSDavid du Colombier /* Fill a rectangle with an uncolored Pattern. */
2957dd7cddfSDavid du Colombier /* Note that we treat this as "texture" for RasterOp. */
2967dd7cddfSDavid du Colombier private int
tile_masked_fill(const tile_fill_state_t * ptfs,int x,int y,int w,int h)2977dd7cddfSDavid du Colombier tile_masked_fill(const tile_fill_state_t * ptfs,
2987dd7cddfSDavid du Colombier 		 int x, int y, int w, int h)
2997dd7cddfSDavid du Colombier {
3007dd7cddfSDavid du Colombier     if (ptfs->source == NULL)
3017dd7cddfSDavid du Colombier 	return (*ptfs->fill_rectangle)
3027dd7cddfSDavid du Colombier 	    (ptfs->pdevc, x, y, w, h, ptfs->pcdev, ptfs->lop, NULL);
3037dd7cddfSDavid du Colombier     else {
3047dd7cddfSDavid du Colombier 	const gx_rop_source_t *source = ptfs->source;
3057dd7cddfSDavid du Colombier 	gx_rop_source_t step_source;
3067dd7cddfSDavid du Colombier 
3077dd7cddfSDavid du Colombier 	step_source.sdata = source->sdata + (y - ptfs->y0) * source->sraster;
3087dd7cddfSDavid du Colombier 	step_source.sourcex = source->sourcex + (x - ptfs->x0);
3097dd7cddfSDavid du Colombier 	step_source.sraster = source->sraster;
3107dd7cddfSDavid du Colombier 	step_source.id = (w == ptfs->w0 && h == ptfs->h0 ?
3117dd7cddfSDavid du Colombier 			  source->id : gx_no_bitmap_id);
3127dd7cddfSDavid du Colombier 	step_source.scolors[0] = source->scolors[0];
3137dd7cddfSDavid du Colombier 	step_source.scolors[1] = source->scolors[1];
3147dd7cddfSDavid du Colombier 	step_source.use_scolors = source->use_scolors;
3157dd7cddfSDavid du Colombier 	return (*ptfs->fill_rectangle)
3167dd7cddfSDavid du Colombier 	    (ptfs->pdevc, x, y, w, h, ptfs->pcdev, ptfs->lop, &step_source);
3177dd7cddfSDavid du Colombier     }
3187dd7cddfSDavid du Colombier }
3197dd7cddfSDavid du Colombier int
gx_dc_pure_masked_fill_rect(const gx_device_color * pdevc,int x,int y,int w,int h,gx_device * dev,gs_logical_operation_t lop,const gx_rop_source_t * source)3207dd7cddfSDavid du Colombier gx_dc_pure_masked_fill_rect(const gx_device_color * pdevc,
3217dd7cddfSDavid du Colombier 			    int x, int y, int w, int h, gx_device * dev,
3227dd7cddfSDavid du Colombier 			    gs_logical_operation_t lop,
3237dd7cddfSDavid du Colombier 			    const gx_rop_source_t * source)
3247dd7cddfSDavid du Colombier {
3257dd7cddfSDavid du Colombier     gx_color_tile *ptile = pdevc->mask.m_tile;
3267dd7cddfSDavid du Colombier     tile_fill_state_t state;
3277dd7cddfSDavid du Colombier     int code;
3287dd7cddfSDavid du Colombier 
3297dd7cddfSDavid du Colombier     /*
3307dd7cddfSDavid du Colombier      * This routine should never be called if there is no masking,
3317dd7cddfSDavid du Colombier      * but we leave the checks below just in case.
3327dd7cddfSDavid du Colombier      */
3337dd7cddfSDavid du Colombier     code = tile_fill_init(&state, pdevc, dev, true);
3347dd7cddfSDavid du Colombier     if (code < 0)
3357dd7cddfSDavid du Colombier 	return code;
3367dd7cddfSDavid du Colombier     if (state.pcdev == dev || ptile->is_simple)
3377dd7cddfSDavid du Colombier 	return (*gx_dc_type_data_pure.fill_rectangle)
3387dd7cddfSDavid du Colombier 	    (pdevc, x, y, w, h, state.pcdev, lop, source);
3397dd7cddfSDavid du Colombier     else {
3407dd7cddfSDavid du Colombier 	state.lop = lop;
3417dd7cddfSDavid du Colombier 	state.source = source;
3427dd7cddfSDavid du Colombier 	state.fill_rectangle = gx_dc_type_data_pure.fill_rectangle;
3437dd7cddfSDavid du Colombier 	return tile_by_steps(&state, x, y, w, h, ptile, &ptile->tmask,
3447dd7cddfSDavid du Colombier 			     tile_masked_fill);
3457dd7cddfSDavid du Colombier     }
3467dd7cddfSDavid du Colombier }
3477dd7cddfSDavid du Colombier int
gx_dc_binary_masked_fill_rect(const gx_device_color * pdevc,int x,int y,int w,int h,gx_device * dev,gs_logical_operation_t lop,const gx_rop_source_t * source)3487dd7cddfSDavid du Colombier gx_dc_binary_masked_fill_rect(const gx_device_color * pdevc,
3497dd7cddfSDavid du Colombier 			      int x, int y, int w, int h, gx_device * dev,
3507dd7cddfSDavid du Colombier 			      gs_logical_operation_t lop,
3517dd7cddfSDavid du Colombier 			      const gx_rop_source_t * source)
3527dd7cddfSDavid du Colombier {
3537dd7cddfSDavid du Colombier     gx_color_tile *ptile = pdevc->mask.m_tile;
3547dd7cddfSDavid du Colombier     tile_fill_state_t state;
3557dd7cddfSDavid du Colombier     int code;
3567dd7cddfSDavid du Colombier 
3577dd7cddfSDavid du Colombier     code = tile_fill_init(&state, pdevc, dev, true);
3587dd7cddfSDavid du Colombier     if (code < 0)
3597dd7cddfSDavid du Colombier 	return code;
3607dd7cddfSDavid du Colombier     if (state.pcdev == dev || ptile->is_simple)
3617dd7cddfSDavid du Colombier 	return (*gx_dc_type_data_ht_binary.fill_rectangle)
3627dd7cddfSDavid du Colombier 	    (pdevc, x, y, w, h, state.pcdev, lop, source);
3637dd7cddfSDavid du Colombier     else {
3647dd7cddfSDavid du Colombier 	state.lop = lop;
3657dd7cddfSDavid du Colombier 	state.source = source;
3667dd7cddfSDavid du Colombier 	state.fill_rectangle = gx_dc_type_data_ht_binary.fill_rectangle;
3677dd7cddfSDavid du Colombier 	return tile_by_steps(&state, x, y, w, h, ptile, &ptile->tmask,
3687dd7cddfSDavid du Colombier 			     tile_masked_fill);
3697dd7cddfSDavid du Colombier     }
3707dd7cddfSDavid du Colombier }
3717dd7cddfSDavid du Colombier int
gx_dc_colored_masked_fill_rect(const gx_device_color * pdevc,int x,int y,int w,int h,gx_device * dev,gs_logical_operation_t lop,const gx_rop_source_t * source)3727dd7cddfSDavid du Colombier gx_dc_colored_masked_fill_rect(const gx_device_color * pdevc,
3737dd7cddfSDavid du Colombier 			       int x, int y, int w, int h, gx_device * dev,
3747dd7cddfSDavid du Colombier 			       gs_logical_operation_t lop,
3757dd7cddfSDavid du Colombier 			       const gx_rop_source_t * source)
3767dd7cddfSDavid du Colombier {
3777dd7cddfSDavid du Colombier     gx_color_tile *ptile = pdevc->mask.m_tile;
3787dd7cddfSDavid du Colombier     tile_fill_state_t state;
3797dd7cddfSDavid du Colombier     int code;
3807dd7cddfSDavid du Colombier 
3817dd7cddfSDavid du Colombier     code = tile_fill_init(&state, pdevc, dev, true);
3827dd7cddfSDavid du Colombier     if (code < 0)
3837dd7cddfSDavid du Colombier 	return code;
3847dd7cddfSDavid du Colombier     if (state.pcdev == dev || ptile->is_simple)
3857dd7cddfSDavid du Colombier 	return (*gx_dc_type_data_ht_colored.fill_rectangle)
3867dd7cddfSDavid du Colombier 	    (pdevc, x, y, w, h, state.pcdev, lop, source);
3877dd7cddfSDavid du Colombier     else {
3887dd7cddfSDavid du Colombier 	state.lop = lop;
3897dd7cddfSDavid du Colombier 	state.source = source;
3907dd7cddfSDavid du Colombier 	state.fill_rectangle = gx_dc_type_data_ht_colored.fill_rectangle;
3917dd7cddfSDavid du Colombier 	return tile_by_steps(&state, x, y, w, h, ptile, &ptile->tmask,
3927dd7cddfSDavid du Colombier 			     tile_masked_fill);
3937dd7cddfSDavid du Colombier     }
3947dd7cddfSDavid du Colombier }
395