summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobin Watts <Robin.Watts@artifex.com>2020-07-28 17:52:11 +0100
committerRobin Watts <Robin.Watts@artifex.com>2020-07-28 17:58:58 +0100
commitc001ce438ef9fd0171104ac49afa110e39edb03e (patch)
treefbc67c53516a409926b8751b9e6629c725e3a026
parent45b122117e937bb36da2ef03ea590c90ebcd2de9 (diff)
downloadghostpdl-c001ce438ef9fd0171104ac49afa110e39edb03e.tar.gz
Bug 702587: Fix alpha buffer issue with fill/stroke operations.
The "alphabits" devices work by an alpha buffer being inserted into the device chain before graphical operations. This intercepts drawing device calls, 'saves' the color, and then converts the call into a fill of a monochrome mask. Only a small 'window' of mask is ever held in memory at once. When the drawing moves out of the range of that window, the window is flushed (conceptually the mask is scaled down, and then that scaled representation is filled with the saved color). Any "stragglers" (i.e. unwritten back bits of mask) are flushed at the end of the graphical operation. When using fill/stroke, the existing code fails to notice the color in use being changed. This means the last 'window' of fill can end up being written in the color intended for 'stroke'. We therefore update the fill/stroke logic to check for the color changing. (We check for 'unflushed data' and 'color has changed').
-rw-r--r--base/gdevabuf.c27
1 files changed, 24 insertions, 3 deletions
diff --git a/base/gdevabuf.c b/base/gdevabuf.c
index 7e27b941b..929baef7c 100644
--- a/base/gdevabuf.c
+++ b/base/gdevabuf.c
@@ -191,7 +191,7 @@ gs_make_mem_abuf_device(gx_device_memory * adev, gs_memory_t * mem,
adev->mapped_x = mapped_x;
set_dev_proc(adev, close_device, mem_abuf_close);
set_dev_proc(adev, get_clipping_box, mem_abuf_get_clipping_box);
- if (!devn)
+ if (!devn)
adev->save_hl_color = NULL; /* This is the test for when we flush the
the buffer as to what copy_alpha type
use */
@@ -235,7 +235,7 @@ abuf_flush_block(gx_device_memory * adev, int y)
* (see gsbitops.c), we can't expand the box only to pixel
* boundaries:
int alpha_mask = -1 << adev->log2_alpha_bits;
- * Instead, we must expand it to byte boundaries,
+ * Instead, we must expand it to byte boundaries,
*/
int alpha_mask = ~7;
gs_int_rect bbox;
@@ -249,7 +249,7 @@ abuf_flush_block(gx_device_memory * adev, int y)
adev->raster, bits, draster, &adev->log2_scale,
adev->log2_alpha_bits);
/* Set up with NULL when adev initialized */
- if (adev->save_hl_color == NULL) {
+ if (adev->save_hl_color == NULL) {
return (*dev_proc(target, copy_alpha)) (target,
bits, 0, draster, gx_no_bitmap_id,
(adev->mapped_x + bbox.p.x) >>
@@ -387,6 +387,13 @@ mem_abuf_copy_mono(gx_device * dev,
fit_copy_xyw(dev, base, sourcex, sraster, id, x, y, w, h); /* don't limit h */
if (w <= 0 || h <= 0)
return 0;
+ if (mdev->mapped_height != 0 && mdev->mapped_start != 0 &&
+ mdev->save_color != one) {
+ /* Color has changed. Better flush. */
+ int code = abuf_flush(mdev);
+ if (code < 0)
+ return code;
+ }
mdev->save_color = one;
y_transfer_init(&yt, dev, y, h);
while (yt.height_left > 0) {
@@ -415,6 +422,13 @@ mem_abuf_fill_rectangle(gx_device * dev, int x, int y, int w, int h,
fit_fill_xy(dev, x, y, w, h);
fit_fill_w(dev, x, w); /* don't limit h */
/* or check w <= 0, h <= 0 */
+ if (mdev->mapped_height != 0 && mdev->mapped_start != 0 &&
+ mdev->save_color != color) {
+ /* Color has changed. Better flush. */
+ int code = abuf_flush(mdev);
+ if (code < 0)
+ return code;
+ }
mdev->save_color = color;
y_transfer_init(&yt, dev, y, h);
while (yt.height_left > 0) {
@@ -448,6 +462,13 @@ mem_abuf_fill_rectangle_hl_color(gx_device * dev, const gs_fixed_rect *rect,
fit_fill_xy(dev, x, y, w, h);
fit_fill_w(dev, x, w); /* don't limit h */
/* or check w <= 0, h <= 0 */
+ if (mdev->mapped_height != 0 && mdev->mapped_start != 0 &&
+ memcmp(mdev->save_hl_color, pdcolor, sizeof(*pdcolor)) != 0) {
+ /* Color has changed. Better flush. */
+ int code = abuf_flush(mdev);
+ if (code < 0)
+ return code;
+ }
mdev->save_hl_color = pdcolor;
y_transfer_init(&yt, dev, y, h);
while (yt.height_left > 0) {