summaryrefslogtreecommitdiff
path: root/base/gxclip.c
diff options
context:
space:
mode:
authorRobin Watts <robin.watts@artifex.com>2017-10-26 12:53:29 +0100
committerRobin Watts <robin.watts@artifex.com>2017-10-26 17:42:51 +0100
commit81561e6e04f49a4b3b9599cc09ba2cde4407e936 (patch)
treefd1afcdb1cfef1a365e1da45fd9dc445552ff273 /base/gxclip.c
parent0d2177ac781235aa67cde3b6fc9d85030c50a8a9 (diff)
downloadghostpdl-81561e6e04f49a4b3b9599cc09ba2cde4407e936.tar.gz
Optimise clip_fill_rectangle and family.
Avoid testing for transpose each time, and cope with the common single rectangle case more efficiently. This gives a 20% speedup in testing with my cutdown Advertising-Powerpoint-A4.pdf file going to 1200dpi, 1bpc cmyk. The only one called here is clip_fill_rectangle, but push the same optimisations through clip_fill_rectangle_hl_color, clip_copy_mono, clip_copy_planes etc to help other devices.
Diffstat (limited to 'base/gxclip.c')
-rw-r--r--base/gxclip.c648
1 files changed, 577 insertions, 71 deletions
diff --git a/base/gxclip.c b/base/gxclip.c
index dd85712f9..9a312061f 100644
--- a/base/gxclip.c
+++ b/base/gxclip.c
@@ -409,8 +409,8 @@ clip_call_fill_rectangle(clip_callback_data_t * pccd, int xc, int yc, int xec, i
(pccd->tdev, xc, yc, xec - xc, yec - yc, pccd->color[0]);
}
static int
-clip_fill_rectangle(gx_device * dev, int x, int y, int w, int h,
- gx_color_index color)
+clip_fill_rectangle_t0(gx_device * dev, int x, int y, int w, int h,
+ gx_color_index color)
{
gx_device_clip *rdev = (gx_device_clip *) dev;
clip_callback_data_t ccdata;
@@ -428,13 +428,57 @@ clip_fill_rectangle(gx_device * dev, int x, int y, int w, int h,
/* ccdata is non-transposed */
ccdata.x = x, ccdata.y = y;
ccdata.w = w, ccdata.h = h;
- /* transpose x, y, xe, ye for clip checking */
- if (rdev->list.transpose) {
- x = ccdata.y;
- y = ccdata.x;
- xe = x + h;
- ye = y + w;
+ /* We open-code the most common cases here. */
+ if ((y >= rptr->ymin && ye <= rptr->ymax) ||
+ ((rptr = rptr->next) != 0 &&
+ y >= rptr->ymin && ye <= rptr->ymax)
+ ) {
+ rdev->current = rptr; /* may be redundant, but awkward to avoid */
+ INCR(in_y);
+ if (x >= rptr->xmin && xe <= rptr->xmax) {
+ INCR(in);
+ return dev_proc(tdev, fill_rectangle)(tdev, x, y, w, h, color);
+ }
+ else if ((rptr->prev == 0 || rptr->prev->ymax != rptr->ymax) &&
+ (rptr->next == 0 || rptr->next->ymax != rptr->ymax)
+ ) {
+ INCR(in1);
+ if (x < rptr->xmin)
+ x = rptr->xmin;
+ if (xe > rptr->xmax)
+ xe = rptr->xmax;
+ if (x >= xe)
+ return 0;
+ return dev_proc(tdev, fill_rectangle)(tdev, x, y, xe - x, h, color);
+ }
}
+ ccdata.tdev = tdev;
+ ccdata.color[0] = color;
+ return clip_enumerate_rest(rdev, x, y, xe, ye, clip_call_fill_rectangle, &ccdata);
+}
+
+static int
+clip_fill_rectangle_t1(gx_device * dev, int x, int y, int w, int h,
+ gx_color_index color)
+{
+ gx_device_clip *rdev = (gx_device_clip *) dev;
+ clip_callback_data_t ccdata;
+ /* We handle the fastest cases in-line here. */
+ gx_device *tdev = rdev->target;
+ /*const*/ gx_clip_rect *rptr = rdev->current;
+ int xe, ye;
+
+ if (w <= 0 || h <= 0)
+ return 0;
+ x += rdev->translation.x;
+ y += rdev->translation.y;
+ /* ccdata is non-transposed */
+ ccdata.x = x, ccdata.y = y;
+ ccdata.w = w, ccdata.h = h;
+ x = ccdata.y;
+ y = ccdata.x;
+ xe = x + h;
+ ye = y + w;
/* We open-code the most common cases here. */
if ((y >= rptr->ymin && ye <= rptr->ymax) ||
((rptr = rptr->next) != 0 &&
@@ -444,10 +488,7 @@ clip_fill_rectangle(gx_device * dev, int x, int y, int w, int h,
INCR(in_y);
if (x >= rptr->xmin && xe <= rptr->xmax) {
INCR(in);
- if (rdev->list.transpose)
- return dev_proc(tdev, fill_rectangle)(tdev, x, y, w, h, color);
- else
- return dev_proc(tdev, fill_rectangle)(tdev, x, y, w, h, color);
+ return dev_proc(tdev, fill_rectangle)(tdev, x, y, w, h, color);
}
else if ((rptr->prev == 0 || rptr->prev->ymax != rptr->ymax) &&
(rptr->next == 0 || rptr->next->ymax != rptr->ymax)
@@ -459,10 +500,7 @@ clip_fill_rectangle(gx_device * dev, int x, int y, int w, int h,
xe = rptr->xmax;
if (x >= xe)
return 0;
- if (rdev->list.transpose)
- return dev_proc(tdev, fill_rectangle)(tdev, y, x, h, xe - x, color);
- else
- return dev_proc(tdev, fill_rectangle)(tdev, x, y, xe - x, h, color);
+ return dev_proc(tdev, fill_rectangle)(tdev, y, x, h, xe - x, color);
}
}
ccdata.tdev = tdev;
@@ -470,6 +508,82 @@ clip_fill_rectangle(gx_device * dev, int x, int y, int w, int h,
return clip_enumerate_rest(rdev, x, y, xe, ye, clip_call_fill_rectangle, &ccdata);
}
+static int
+clip_fill_rectangle_s0(gx_device * dev, int x, int y, int w, int h,
+ gx_color_index color)
+{
+ gx_device_clip *rdev = (gx_device_clip *) dev;
+ gx_device *tdev = rdev->target;
+
+ if (w <= 0 || h <= 0)
+ return 0;
+ x += rdev->translation.x;
+ w += x;
+ y += rdev->translation.y;
+ h += y;
+ if (x < rdev->list.single.xmin)
+ x = rdev->list.single.xmin;
+ if (w > rdev->list.single.xmax)
+ w = rdev->list.single.xmax;
+ if (y < rdev->list.single.ymin)
+ y = rdev->list.single.ymin;
+ if (h > rdev->list.single.ymax)
+ h = rdev->list.single.ymax;
+ w -= x;
+ h -= y;
+ if (w <= 0 || h <= 0)
+ return 0;
+ return dev_proc(tdev, fill_rectangle)(tdev, x, y, w, h, color);
+}
+
+static int
+clip_fill_rectangle_s1(gx_device * dev, int x, int y, int w, int h,
+ gx_color_index color)
+{
+ gx_device_clip *rdev = (gx_device_clip *) dev;
+ gx_device *tdev = rdev->target;
+
+ if (w <= 0 || h <= 0)
+ return 0;
+ x += rdev->translation.x;
+ w += x;
+ y += rdev->translation.y;
+ h += y;
+ /* Now, treat x/w as y/h and vice versa as transposed. */
+ if (x < rdev->list.single.ymin)
+ x = rdev->list.single.ymin;
+ if (w > rdev->list.single.ymax)
+ w = rdev->list.single.ymax;
+ if (y < rdev->list.single.xmin)
+ y = rdev->list.single.xmin;
+ if (h > rdev->list.single.xmax)
+ h = rdev->list.single.xmax;
+ w -= x;
+ h -= y;
+ if (w <= 0 || h <= 0)
+ return 0;
+ return dev_proc(tdev, fill_rectangle)(tdev, y, x, h, w, color);
+}
+static int
+clip_fill_rectangle(gx_device * dev, int x, int y, int w, int h,
+ gx_color_index color)
+{
+ gx_device_clip *rdev = (gx_device_clip *) dev;
+
+ if (rdev->list.transpose) {
+ if (rdev->list.count == 1)
+ dev_proc(rdev, fill_rectangle) = clip_fill_rectangle_s1;
+ else
+ dev_proc(rdev, fill_rectangle) = clip_fill_rectangle_t1;
+ } else {
+ if (rdev->list.count == 1)
+ dev_proc(rdev, fill_rectangle) = clip_fill_rectangle_s0;
+ else
+ dev_proc(rdev, fill_rectangle) = clip_fill_rectangle_t0;
+ }
+ return dev_proc(rdev, fill_rectangle)(dev, x, y, w, h, color);
+}
+
int
clip_call_fill_rectangle_hl_color(clip_callback_data_t * pccd, int xc, int yc,
int xec, int yec)
@@ -485,7 +599,7 @@ clip_call_fill_rectangle_hl_color(clip_callback_data_t * pccd, int xc, int yc,
}
static int
-clip_fill_rectangle_hl_color(gx_device *dev, const gs_fixed_rect *rect,
+clip_fill_rectangle_hl_color_t0(gx_device *dev, const gs_fixed_rect *rect,
const gs_gstate *pgs, const gx_drawing_color *pdcolor,
const gx_clip_path *pcpath)
{
@@ -511,13 +625,6 @@ clip_fill_rectangle_hl_color(gx_device *dev, const gs_fixed_rect *rect,
/* ccdata is non-transposed */
ccdata.x = x, ccdata.y = y;
ccdata.w = w, ccdata.h = h;
- /* transpose x, y, xe, ye for clip checking */
- if (rdev->list.transpose) {
- x = ccdata.y;
- y = ccdata.x;
- xe = x + h;
- ye = y + w;
- }
/* We open-code the most common cases here. */
if ((y >= rptr->ymin && ye <= rptr->ymax) ||
((rptr = rptr->next) != 0 &&
@@ -527,17 +634,84 @@ clip_fill_rectangle_hl_color(gx_device *dev, const gs_fixed_rect *rect,
INCR(in_y);
if (x >= rptr->xmin && xe <= rptr->xmax) {
INCR(in);
- if (rdev->list.transpose) {
- newrect.p.x = int2fixed(y);
- newrect.p.y = int2fixed(x);
- newrect.q.x = int2fixed(y + h);
- newrect.q.y = int2fixed(x + w);
- } else {
+ newrect.p.x = int2fixed(x);
+ newrect.p.y = int2fixed(y);
+ newrect.q.x = int2fixed(x + w);
+ newrect.q.y = int2fixed(y + h);
+ return dev_proc(tdev, fill_rectangle_hl_color)(tdev, &newrect, pgs,
+ pdcolor, pcpath);
+ }
+ else if ((rptr->prev == 0 || rptr->prev->ymax != rptr->ymax) &&
+ (rptr->next == 0 || rptr->next->ymax != rptr->ymax)
+ ) {
+ INCR(in1);
+ if (x < rptr->xmin)
+ x = rptr->xmin;
+ if (xe > rptr->xmax)
+ xe = rptr->xmax;
+ if (x >= xe)
+ return 0;
+ else {
newrect.p.x = int2fixed(x);
newrect.p.y = int2fixed(y);
- newrect.q.x = int2fixed(x + w);
+ newrect.q.x = int2fixed(xe);
newrect.q.y = int2fixed(y + h);
+ return dev_proc(tdev, fill_rectangle_hl_color)(tdev, &newrect, pgs,
+ pdcolor, pcpath);
}
+ }
+ }
+ ccdata.tdev = tdev;
+ ccdata.pdcolor = pdcolor;
+ ccdata.pgs = pgs;
+ ccdata.pcpath = pcpath;
+ return clip_enumerate_rest(rdev, x, y, xe, ye,
+ clip_call_fill_rectangle_hl_color, &ccdata);
+}
+
+static int
+clip_fill_rectangle_hl_color_t1(gx_device *dev, const gs_fixed_rect *rect,
+ const gs_gstate *pgs, const gx_drawing_color *pdcolor,
+ const gx_clip_path *pcpath)
+{
+ gx_device_clip *rdev = (gx_device_clip *) dev;
+ clip_callback_data_t ccdata;
+ gx_device *tdev = rdev->target;
+ gx_clip_rect *rptr = rdev->current;
+ int xe, ye;
+ int w, h, x, y;
+ gs_fixed_rect newrect;
+
+ x = fixed2int(rect->p.x);
+ y = fixed2int(rect->p.y);
+ w = fixed2int(rect->q.x) - x;
+ h = fixed2int(rect->q.y) - y;
+
+ if (w <= 0 || h <= 0)
+ return 0;
+ x += rdev->translation.x;
+ y += rdev->translation.y;
+ /* ccdata is non-transposed */
+ ccdata.x = x, ccdata.y = y;
+ ccdata.w = w, ccdata.h = h;
+ /* transpose x, y, xe, ye for clip checking */
+ x = ccdata.y;
+ y = ccdata.x;
+ xe = x + h;
+ ye = y + w;
+ /* We open-code the most common cases here. */
+ if ((y >= rptr->ymin && ye <= rptr->ymax) ||
+ ((rptr = rptr->next) != 0 &&
+ y >= rptr->ymin && ye <= rptr->ymax)
+ ) {
+ rdev->current = rptr; /* may be redundant, but awkward to avoid */
+ INCR(in_y);
+ if (x >= rptr->xmin && xe <= rptr->xmax) {
+ INCR(in);
+ newrect.p.x = int2fixed(y);
+ newrect.p.y = int2fixed(x);
+ newrect.q.x = int2fixed(y + h);
+ newrect.q.y = int2fixed(x + w);
return dev_proc(tdev, fill_rectangle_hl_color)(tdev, &newrect, pgs,
pdcolor, pcpath);
}
@@ -552,17 +726,10 @@ clip_fill_rectangle_hl_color(gx_device *dev, const gs_fixed_rect *rect,
if (x >= xe)
return 0;
else {
- if (rdev->list.transpose) {
- newrect.p.x = int2fixed(y);
- newrect.p.y = int2fixed(x);
- newrect.q.x = int2fixed(y+h);
- newrect.q.y = int2fixed(xe);
- } else {
- newrect.p.x = int2fixed(x);
- newrect.p.y = int2fixed(y);
- newrect.q.x = int2fixed(xe);
- newrect.q.y = int2fixed(y + h);
- }
+ newrect.p.x = int2fixed(y);
+ newrect.p.y = int2fixed(x);
+ newrect.q.x = int2fixed(y+h);
+ newrect.q.y = int2fixed(xe);
return dev_proc(tdev, fill_rectangle_hl_color)(tdev, &newrect, pgs,
pdcolor, pcpath);
}
@@ -576,6 +743,110 @@ clip_fill_rectangle_hl_color(gx_device *dev, const gs_fixed_rect *rect,
clip_call_fill_rectangle_hl_color, &ccdata);
}
+static int
+clip_fill_rectangle_hl_color_s0(gx_device *dev, const gs_fixed_rect *rect,
+ const gs_gstate *pgs, const gx_drawing_color *pdcolor,
+ const gx_clip_path *pcpath)
+{
+ gx_device_clip *rdev = (gx_device_clip *) dev;
+ gx_device *tdev = rdev->target;
+ int w, h, x, y;
+ gs_fixed_rect newrect;
+
+ x = fixed2int(rect->p.x);
+ y = fixed2int(rect->p.y);
+ w = fixed2int(rect->q.x) - x;
+ h = fixed2int(rect->q.y) - y;
+
+ if (w <= 0 || h <= 0)
+ return 0;
+ x += rdev->translation.x;
+ w += x;
+ y += rdev->translation.y;
+ h += y;
+ if (x < rdev->list.single.xmin)
+ x = rdev->list.single.xmin;
+ if (w > rdev->list.single.xmax)
+ w = rdev->list.single.xmax;
+ if (y < rdev->list.single.ymin)
+ y = rdev->list.single.ymin;
+ if (h > rdev->list.single.ymax)
+ h = rdev->list.single.ymax;
+ w -= x;
+ h -= y;
+ if (w <= 0 || h <= 0)
+ return 0;
+ newrect.p.x = int2fixed(x);
+ newrect.p.y = int2fixed(y);
+ newrect.q.x = int2fixed(x + w);
+ newrect.q.y = int2fixed(y + h);
+ return dev_proc(tdev, fill_rectangle_hl_color)(tdev, &newrect, pgs,
+ pdcolor, pcpath);
+}
+
+static int
+clip_fill_rectangle_hl_color_s1(gx_device *dev, const gs_fixed_rect *rect,
+ const gs_gstate *pgs, const gx_drawing_color *pdcolor,
+ const gx_clip_path *pcpath)
+{
+ gx_device_clip *rdev = (gx_device_clip *) dev;
+ gx_device *tdev = rdev->target;
+ int w, h, x, y;
+ gs_fixed_rect newrect;
+
+ x = fixed2int(rect->p.x);
+ y = fixed2int(rect->p.y);
+ w = fixed2int(rect->q.x) - x;
+ h = fixed2int(rect->q.y) - y;
+
+ if (w <= 0 || h <= 0)
+ return 0;
+ x += rdev->translation.x;
+ w += x;
+ y += rdev->translation.y;
+ h += y;
+ /* Now, treat x/w as y/h and vice versa as transposed. */
+ if (x < rdev->list.single.ymin)
+ x = rdev->list.single.ymin;
+ if (w > rdev->list.single.ymax)
+ w = rdev->list.single.ymax;
+ if (y < rdev->list.single.xmin)
+ y = rdev->list.single.xmin;
+ if (h > rdev->list.single.xmax)
+ h = rdev->list.single.xmax;
+ w -= x;
+ h -= y;
+ if (w <= 0 || h <= 0)
+ return 0;
+ newrect.p.x = int2fixed(y);
+ newrect.p.y = int2fixed(x);
+ newrect.q.x = int2fixed(y + h);
+ newrect.q.y = int2fixed(x + w);
+ return dev_proc(tdev, fill_rectangle_hl_color)(tdev, &newrect, pgs,
+ pdcolor, pcpath);
+}
+
+static int
+clip_fill_rectangle_hl_color(gx_device *dev, const gs_fixed_rect *rect,
+ const gs_gstate *pgs, const gx_drawing_color *pdcolor,
+ const gx_clip_path *pcpath)
+{
+ gx_device_clip *rdev = (gx_device_clip *) dev;
+
+ if (rdev->list.transpose) {
+ if (rdev->list.count == 1)
+ dev_proc(rdev, fill_rectangle_hl_color) = clip_fill_rectangle_hl_color_s1;
+ else
+ dev_proc(rdev, fill_rectangle_hl_color) = clip_fill_rectangle_hl_color_t1;
+ } else {
+ if (rdev->list.count == 1)
+ dev_proc(rdev, fill_rectangle_hl_color) = clip_fill_rectangle_hl_color_s0;
+ else
+ dev_proc(rdev, fill_rectangle_hl_color) = clip_fill_rectangle_hl_color_t0;
+ }
+ return dev_proc(rdev, fill_rectangle_hl_color)(dev, rect, pgs, pdcolor, pcpath);
+}
+
/* Copy a monochrome rectangle */
int
clip_call_copy_mono(clip_callback_data_t * pccd, int xc, int yc, int xec, int yec)
@@ -586,10 +857,10 @@ clip_call_copy_mono(clip_callback_data_t * pccd, int xc, int yc, int xec, int ye
xc, yc, xec - xc, yec - yc, pccd->color[0], pccd->color[1]);
}
static int
-clip_copy_mono(gx_device * dev,
- const byte * data, int sourcex, int raster, gx_bitmap_id id,
- int x, int y, int w, int h,
- gx_color_index color0, gx_color_index color1)
+clip_copy_mono_t0(gx_device * dev,
+ const byte * data, int sourcex, int raster, gx_bitmap_id id,
+ int x, int y, int w, int h,
+ gx_color_index color0, gx_color_index color1)
{
gx_device_clip *rdev = (gx_device_clip *) dev;
clip_callback_data_t ccdata;
@@ -607,23 +878,50 @@ clip_copy_mono(gx_device * dev,
/* ccdata is non-transposed */
ccdata.x = x, ccdata.y = y;
ccdata.w = w, ccdata.h = h;
- /* transpose x, y, xe, ye for clip checking */
- if (rdev->list.transpose) {
- x = ccdata.y;
- y = ccdata.x;
- xe = x + h;
- ye = y + w;
+ if (y >= rptr->ymin && ye <= rptr->ymax) {
+ INCR(in_y);
+ if (x >= rptr->xmin && xe <= rptr->xmax) {
+ INCR(in);
+ return dev_proc(tdev, copy_mono)
+ (tdev, data, sourcex, raster, id, x, y, w, h, color0, color1);
+ }
}
+ ccdata.tdev = tdev;
+ ccdata.data = data, ccdata.sourcex = sourcex, ccdata.raster = raster;
+ ccdata.color[0] = color0, ccdata.color[1] = color1;
+ return clip_enumerate_rest(rdev, x, y, xe, ye,
+ clip_call_copy_mono, &ccdata);
+}
+static int
+clip_copy_mono_t1(gx_device * dev,
+ const byte * data, int sourcex, int raster, gx_bitmap_id id,
+ int x, int y, int w, int h,
+ gx_color_index color0, gx_color_index color1)
+{
+ gx_device_clip *rdev = (gx_device_clip *) dev;
+ clip_callback_data_t ccdata;
+ /* We handle the fastest case in-line here. */
+ gx_device *tdev = rdev->target;
+ const gx_clip_rect *rptr = rdev->current;
+ int xe, ye;
+
+ if (w <= 0 || h <= 0)
+ return 0;
+ x += rdev->translation.x;
+ y += rdev->translation.y;
+ /* ccdata is non-transposed */
+ ccdata.x = x, ccdata.y = y;
+ ccdata.w = w, ccdata.h = h;
+ x = ccdata.y;
+ y = ccdata.x;
+ xe = x + h;
+ ye = y + w;
if (y >= rptr->ymin && ye <= rptr->ymax) {
INCR(in_y);
if (x >= rptr->xmin && xe <= rptr->xmax) {
INCR(in);
- if (rdev->list.transpose)
- return dev_proc(tdev, copy_mono)
+ return dev_proc(tdev, copy_mono)
(tdev, data, sourcex, raster, id, y, x, h, w, color0, color1);
- else
- return dev_proc(tdev, copy_mono)
- (tdev, data, sourcex, raster, id, x, y, w, h, color0, color1);
}
}
ccdata.tdev = tdev;
@@ -632,6 +930,100 @@ clip_copy_mono(gx_device * dev,
return clip_enumerate_rest(rdev, x, y, xe, ye,
clip_call_copy_mono, &ccdata);
}
+static int
+clip_copy_mono_s0(gx_device * dev,
+ const byte * data, int sourcex, int raster, gx_bitmap_id id,
+ int x, int y, int w, int h,
+ gx_color_index color0, gx_color_index color1)
+{
+ gx_device_clip *rdev = (gx_device_clip *) dev;
+ gx_device *tdev = rdev->target;
+
+ if (w <= 0 || h <= 0)
+ return 0;
+ x += rdev->translation.x;
+ w += x;
+ y += rdev->translation.y;
+ h += y;
+ if (x < rdev->list.single.xmin)
+ {
+ sourcex += (rdev->list.single.xmin - x);
+ x = rdev->list.single.xmin;
+ }
+ if (w > rdev->list.single.xmax)
+ w = rdev->list.single.xmax;
+ if (y < rdev->list.single.ymin)
+ {
+ data += (rdev->list.single.ymin - y) * raster;
+ y = rdev->list.single.ymin;
+ }
+ if (h > rdev->list.single.ymax)
+ h = rdev->list.single.ymax;
+ w -= x;
+ h -= y;
+ if (w <= 0 || h <= 0)
+ return 0;
+ return dev_proc(tdev, copy_mono)
+ (tdev, data, sourcex, raster, id, x, y, w, h, color0, color1);
+}
+static int
+clip_copy_mono_s1(gx_device * dev,
+ const byte * data, int sourcex, int raster, gx_bitmap_id id,
+ int x, int y, int w, int h,
+ gx_color_index color0, gx_color_index color1)
+{
+ gx_device_clip *rdev = (gx_device_clip *) dev;
+ gx_device *tdev = rdev->target;
+
+ if (w <= 0 || h <= 0)
+ return 0;
+ x += rdev->translation.x;
+ w += x;
+ y += rdev->translation.y;
+ h += y;
+ /* Now, treat x/w as y/h and vice versa as transposed. */
+ if (x < rdev->list.single.ymin)
+ {
+ data += (rdev->list.single.ymin - x) * raster;
+ x = rdev->list.single.ymin;
+ }
+ if (w > rdev->list.single.ymax)
+ w = rdev->list.single.ymax;
+ if (y < rdev->list.single.xmin)
+ {
+ sourcex += (rdev->list.single.xmin - y);
+ y = rdev->list.single.xmin;
+ }
+ if (h > rdev->list.single.xmax)
+ h = rdev->list.single.xmax;
+ w -= x;
+ h -= y;
+ if (w <= 0 || h <= 0)
+ return 0;
+ return dev_proc(tdev, copy_mono)
+ (tdev, data, sourcex, raster, id, y, x, h, w, color0, color1);
+}
+static int
+clip_copy_mono(gx_device * dev,
+ const byte * data, int sourcex, int raster, gx_bitmap_id id,
+ int x, int y, int w, int h,
+ gx_color_index color0, gx_color_index color1)
+{
+ gx_device_clip *rdev = (gx_device_clip *) dev;
+
+ if (rdev->list.transpose) {
+ if (rdev->list.count == 1)
+ dev_proc(rdev, copy_mono) = clip_copy_mono_s1;
+ else
+ dev_proc(rdev, copy_mono) = clip_copy_mono_t1;
+ } else {
+ if (rdev->list.count == 1)
+ dev_proc(rdev, copy_mono) = clip_copy_mono_s0;
+ else
+ dev_proc(rdev, copy_mono) = clip_copy_mono_t0;
+ }
+ return dev_proc(rdev, copy_mono)(dev, data, sourcex, raster, id, x, y, w, h, color0, color1);
+}
/* Copy a plane */
int
@@ -643,9 +1035,9 @@ clip_call_copy_planes(clip_callback_data_t * pccd, int xc, int yc, int xec, int
xc, yc, xec - xc, yec - yc, pccd->plane_height);
}
static int
-clip_copy_planes(gx_device * dev,
- const byte * data, int sourcex, int raster, gx_bitmap_id id,
- int x, int y, int w, int h, int plane_height)
+clip_copy_planes_t0(gx_device * dev,
+ const byte * data, int sourcex, int raster, gx_bitmap_id id,
+ int x, int y, int w, int h, int plane_height)
{
gx_device_clip *rdev = (gx_device_clip *) dev;
clip_callback_data_t ccdata;
@@ -663,23 +1055,50 @@ clip_copy_planes(gx_device * dev,
/* ccdata is non-transposed */
ccdata.x = x, ccdata.y = y;
ccdata.w = w, ccdata.h = h;
- /* transpose x, y, xe, ye for clip checking */
- if (rdev->list.transpose) {
- x = ccdata.y;
- y = ccdata.x;
- xe = x + h;
- ye = y + w;
+ if (y >= rptr->ymin && ye <= rptr->ymax) {
+ INCR(in_y);
+ if (x >= rptr->xmin && xe <= rptr->xmax) {
+ INCR(in);
+ return dev_proc(tdev, copy_planes)
+ (tdev, data, sourcex, raster, id, x, y, w, h, plane_height);
+ }
}
+ ccdata.tdev = tdev;
+ ccdata.data = data, ccdata.sourcex = sourcex, ccdata.raster = raster;
+ ccdata.plane_height = plane_height;
+ return clip_enumerate_rest(rdev, x, y, xe, ye,
+ clip_call_copy_planes, &ccdata);
+}
+static int
+clip_copy_planes_t1(gx_device * dev,
+ const byte * data, int sourcex, int raster, gx_bitmap_id id,
+ int x, int y, int w, int h, int plane_height)
+{
+ gx_device_clip *rdev = (gx_device_clip *) dev;
+ clip_callback_data_t ccdata;
+ /* We handle the fastest case in-line here. */
+ gx_device *tdev = rdev->target;
+ const gx_clip_rect *rptr = rdev->current;
+ int xe, ye;
+
+ if (w <= 0 || h <= 0)
+ return 0;
+ x += rdev->translation.x;
+ y += rdev->translation.y;
+ /* ccdata is non-transposed */
+ ccdata.x = x, ccdata.y = y;
+ ccdata.w = w, ccdata.h = h;
+ /* transpose x, y, xe, ye for clip checking */
+ x = ccdata.y;
+ y = ccdata.x;
+ xe = x + h;
+ ye = y + w;
if (y >= rptr->ymin && ye <= rptr->ymax) {
INCR(in_y);
if (x >= rptr->xmin && xe <= rptr->xmax) {
INCR(in);
- if (rdev->list.transpose)
- return dev_proc(tdev, copy_planes)
+ return dev_proc(tdev, copy_planes)
(tdev, data, sourcex, raster, id, y, x, h, w, plane_height);
- else
- return dev_proc(tdev, copy_planes)
- (tdev, data, sourcex, raster, id, x, y, w, h, plane_height);
}
}
ccdata.tdev = tdev;
@@ -688,6 +1107,93 @@ clip_copy_planes(gx_device * dev,
return clip_enumerate_rest(rdev, x, y, xe, ye,
clip_call_copy_planes, &ccdata);
}
+static int
+clip_copy_planes_s0(gx_device * dev,
+ const byte * data, int sourcex, int raster, gx_bitmap_id id,
+ int x, int y, int w, int h, int plane_height)
+{
+ gx_device_clip *rdev = (gx_device_clip *) dev;
+ gx_device *tdev = rdev->target;
+
+ x += rdev->translation.x;
+ w += x;
+ y += rdev->translation.y;
+ h += y;
+ if (x < rdev->list.single.xmin)
+ {
+ sourcex += rdev->list.single.xmin - x;
+ x = rdev->list.single.xmin;
+ }
+ if (w > rdev->list.single.xmax)
+ w = rdev->list.single.xmax;
+ if (y < rdev->list.single.ymin)
+ {
+ data += (rdev->list.single.ymin - y) * raster;
+ y = rdev->list.single.ymin;
+ }
+ if (h > rdev->list.single.ymax)
+ h = rdev->list.single.ymax;
+ w -= x;
+ h -= y;
+ if (w <= 0 || h <= 0)
+ return 0;
+ return dev_proc(tdev, copy_planes)
+ (tdev, data, sourcex, raster, id, x, y, w, h, plane_height);
+}
+static int
+clip_copy_planes_s1(gx_device * dev,
+ const byte * data, int sourcex, int raster, gx_bitmap_id id,
+ int x, int y, int w, int h, int plane_height)
+{
+ gx_device_clip *rdev = (gx_device_clip *) dev;
+ gx_device *tdev = rdev->target;
+
+ x += rdev->translation.x;
+ w += x;
+ y += rdev->translation.y;
+ h += y;
+ /* Now, treat x/w as y/h and vice versa as transposed. */
+ if (x < rdev->list.single.ymin)
+ {
+ data += (rdev->list.single.ymin - x) * raster;
+ x = rdev->list.single.ymin;
+ }
+ if (w > rdev->list.single.ymax)
+ w = rdev->list.single.ymax;
+ if (y < rdev->list.single.xmin)
+ {
+ sourcex += rdev->list.single.xmin - y;
+ y = rdev->list.single.xmin;
+ }
+ if (h > rdev->list.single.xmax)
+ h = rdev->list.single.xmax;
+ w -= x;
+ h -= y;
+ if (w <= 0 || h <= 0)
+ return 0;
+ return dev_proc(tdev, copy_planes)
+ (tdev, data, sourcex, raster, id, y, x, h, w, plane_height);
+}
+static int
+clip_copy_planes(gx_device * dev,
+ const byte * data, int sourcex, int raster, gx_bitmap_id id,
+ int x, int y, int w, int h, int plane_height)
+{
+ gx_device_clip *rdev = (gx_device_clip *) dev;
+
+ if (rdev->list.transpose) {
+ if (rdev->list.count == 1)
+ dev_proc(rdev, copy_planes) = clip_copy_planes_s1;
+ else
+ dev_proc(rdev, copy_planes) = clip_copy_planes_t1;
+ } else {
+ if (rdev->list.count == 1)
+ dev_proc(rdev, copy_planes) = clip_copy_planes_s0;
+ else
+ dev_proc(rdev, copy_planes) = clip_copy_planes_t0;
+ }
+ return dev_proc(rdev, copy_planes)(dev, data, sourcex, raster, id, x, y, w, h, plane_height);
+}
/* Copy a color rectangle */
int