summaryrefslogtreecommitdiff
path: root/base
diff options
context:
space:
mode:
authorRobin Watts <Robin.Watts@artifex.com>2023-01-27 16:07:06 +0000
committerRobin Watts <Robin.Watts@artifex.com>2023-02-08 15:37:03 +0000
commit2ff71f81b69a02de76b8f0090c76d85f397895df (patch)
treefdcf1ed8aab7a3526af954c1b75c99edcafcc05a /base
parenteecd33392f90b77853a0d2ba64d115eec34890a3 (diff)
downloadghostpdl-2ff71f81b69a02de76b8f0090c76d85f397895df.tar.gz
Bug 706373: Improve detection of image clipping.
When we set out to render an image, we calculate the target rectangle. We attempt to reduce this according to the clip path as much as we can so as to limit the amount of excess work we do - particularly for interpolated images. Unfortunately, in some cases (including some clist cases) this code is called without a clip path in place, and so we were failing to clip the target at all. This meant that for images that spanned the whole page, we could end up interpolating the whole image for every single band. Here, we adapt the code so that in the absence of a clip path we use the bbox of the target device as bounds.
Diffstat (limited to 'base')
-rw-r--r--base/gxipixel.c27
1 files changed, 19 insertions, 8 deletions
diff --git a/base/gxipixel.c b/base/gxipixel.c
index 26b4d7667..672c935fd 100644
--- a/base/gxipixel.c
+++ b/base/gxipixel.c
@@ -432,23 +432,33 @@ gx_image_enum_begin(gx_device * dev, const gs_gstate * pgs,
}
/* Can we restrict the amount of image we need? */
- while (pcpath && !pim->imagematrices_are_untrustworthy) /* So we can break out of it */
+ while (!pim->imagematrices_are_untrustworthy) /* So we can break out of it */
{
gs_rect rect, rect_src;
gs_matrix mi;
const gs_matrix *m = pgs != NULL ? &ctm_only(pgs) : NULL;
- gs_fixed_rect obox;
gs_int_rect irect;
if (m == NULL || (code = gs_matrix_invert(m, &mi)) < 0 ||
(code = gs_matrix_multiply(&mi, &pic->ImageMatrix, &mi)) < 0) {
/* Give up trying to shrink the render box, but continue processing */
break;
}
- gx_cpath_outer_box(pcpath, &obox);
- rect.p.x = fixed2float(obox.p.x);
- rect.p.y = fixed2float(obox.p.y);
- rect.q.x = fixed2float(obox.q.x);
- rect.q.y = fixed2float(obox.q.y);
+ if (pcpath)
+ {
+ gs_fixed_rect obox;
+ gx_cpath_outer_box(pcpath, &obox);
+ rect.p.x = fixed2float(obox.p.x);
+ rect.p.y = fixed2float(obox.p.y);
+ rect.q.x = fixed2float(obox.q.x);
+ rect.q.y = fixed2float(obox.q.y);
+ }
+ else
+ {
+ rect.p.x = 0;
+ rect.p.y = 0;
+ rect.q.x = dev->width;
+ rect.q.y = dev->height;
+ }
/* rect is in destination space. Calculate rect_src, in source space. */
code = gs_bbox_transform(&rect, &mi, &rect_src);
if (code < 0) {
@@ -460,6 +470,7 @@ gx_image_enum_begin(gx_device * dev, const gs_gstate * pgs,
/* If mi.{xx,yy} > 1 then we are downscaling. During downscaling,
* the support increases to ensure that we don't lose pixels contributions
* entirely. */
+ if (pim->Interpolate)
{
float support = any_abs(mi.xx);
int isupport;
@@ -479,7 +490,7 @@ gx_image_enum_begin(gx_device * dev, const gs_gstate * pgs,
rect_src.p.x -= isupport;
rect_src.p.y -= isupport;
rect_src.q.x += isupport;
- rect_src.q.y += isupport;
+ rect_src.q.y += isupport+1; /* +1 is a fudge! */
}
irect.p.x = (int)floor(rect_src.p.x);
irect.p.y = (int)floor(rect_src.p.y);