summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Vrhel <michael.vrhel@artifex.com>2011-10-22 23:51:42 -0700
committerMichael Vrhel <michael.vrhel@artifex.com>2011-10-27 11:19:50 -0700
commit2b91a85069d421465220a83c82ea491733d15017 (patch)
treeb3be7f7b09d2a803c1b4b31fe95754c82761a303
parent58722d520578050aad3d81c0f5fb477bc701a944 (diff)
Fix for Bug 692505 XPS patterns with transparency.
There were essentially three issues two in the xps interpreter and one in the graphics library. First in the xps interpreter we need to know if the pattern object has transparency and to set up the pattern object for the graphics library so that the graphics library will know to push the pdf14 device on the pattern accumulator object. We also had the issue that we were not undoing the pre-multiplied alpha in the tiff image in the interpreter. Second issue is that in ghostscript, we call pattern_paint_finish from the pdf interpreter when we are all done setting things up for the pattern. This is now handled prior to the call before gx_pattern_cache_add_entry which is where it is done in pattern_paint_finish. Also, some debugging of the mask stack was added in gdevp14.c. This was needed to track down a bug that become visible when I added in the pattern transparency support. The issue was that the parent PDF14 device may often have a valid soft mask in its mask stack if there had been a previous soft mask push. Since we made the soft mask state be part of the q Q operations in the PDF interpreter (the soft mask is actually part of the extended graphics state in PDF), we have to make sure to pop the soft mask we we are all done using it in the XPS interpreter. I added the appropriate commands for that. There was also an issue that cropped up with the pdf14 device and the interaction of the image interpolation code. We always interpolate image in XPS and it turned out that if we had an opacity mask pattern created with an image we installed a gray pdf14 device for the pattern. The interpolation code was incorrectly using halftoning for the pdf14 gray device due to the color info settings in that device. This commit results in many progressions in PDF and XPS (450 differences). In PDF, if the target was a gray devices and the content had interpolated images with transparency we see progressions due to the fact that we were improperly halftoning the images when the trans device is a contone device. In XPS, several missing figures now are visible and we correctly handle tiling with objects that have transparency.
-rw-r--r--gs/base/gdevp14.c79
-rw-r--r--gs/base/gxpcmap.c22
-rw-r--r--gs/base/lib.mak2
-rw-r--r--xps/xpsgradient.c3
-rw-r--r--xps/xpsimage.c4
-rw-r--r--xps/xpsopacity.c3
-rw-r--r--xps/xpstile.c20
7 files changed, 126 insertions, 7 deletions
diff --git a/gs/base/gdevp14.c b/gs/base/gdevp14.c
index 17a47b3f3..ec4d9b1c6 100644
--- a/gs/base/gdevp14.c
+++ b/gs/base/gdevp14.c
@@ -63,6 +63,8 @@ unsigned int global_index = 0;
unsigned int clist_band_count = 0;
#endif
+#define DUMP_MASK_STACK 0
+
/* Static prototypes */
/* Used for filling rects when we are doing a fill with a pattern that
has transparency */
@@ -106,6 +108,9 @@ static int pdf14_tile_pattern_fill(gx_device * pdev,
const gx_fill_params * params,
const gx_device_color * pdevc, const gx_clip_path * pcpath);
static pdf14_mask_t * pdf14_mask_element_new(gs_memory_t * memory);
+#ifdef DEBUG
+static void pdf14_debug_mask_stack_state(pdf14_ctx *ctx);
+#endif
/* Buffer stack data structure */
gs_private_st_ptrs5(st_pdf14_buf, pdf14_buf, "pdf14_buf",
@@ -778,11 +783,14 @@ pdf14_pop_transparency_group(gs_imager_state *pis, pdf14_ctx *ctx,
int num_noncolor_planes, new_num_planes;
int num_cols, num_rows, num_newcolor_planes;
bool icc_match;
-
gsicc_rendering_param_t rendering_params;
gsicc_link_t *icc_link;
gsicc_bufferdesc_t input_buff_desc;
gsicc_bufferdesc_t output_buff_desc;
+
+#ifdef DEBUG
+ pdf14_debug_mask_stack_state(ctx);
+#endif
if ( mask_stack == NULL) {
maskbuf = NULL;
} else {
@@ -1282,7 +1290,10 @@ pdf14_push_transparency_state(gx_device *dev, gs_imager_state *pis)
rc_increment(new_mask->rc_mask);
ctx->mask_stack->previous = new_mask;
}
- return(0);
+#ifdef DEBUG
+ pdf14_debug_mask_stack_state(pdev->ctx);
+#endif
+ return(0);
}
static int
@@ -1315,7 +1326,10 @@ pdf14_pop_transparency_state(gx_device *dev, gs_imager_state *pis)
}
}
}
- return(0);
+#ifdef DEBUG
+ pdf14_debug_mask_stack_state(pdev->ctx);
+#endif
+ return 0;
}
static int
@@ -1366,6 +1380,9 @@ pdf14_get_buffer_information(const gx_device * dev,
if ( pdev->ctx == NULL){
return 0; /* this can occur if the pattern is a clist */
}
+#ifdef DEBUG
+ pdf14_debug_mask_stack_state(pdev->ctx);
+#endif
buf = pdev->ctx->stack;
rect = buf->rect;
transbuff->dirty = &buf->dirty;
@@ -2801,6 +2818,8 @@ get_pdf14_device_proto(gx_device * dev, pdf14_device ** pdevproto,
ptempdevproto->color_info.max_components = 1;
ptempdevproto->color_info.num_components =
ptempdevproto->color_info.max_components;
+ ptempdevproto->color_info.max_gray = 255;
+ ptempdevproto->color_info.gray_index = 0; /* Avoid halftoning */
*pdevproto = ptempdevproto;
break;
case PDF14_DeviceRGB:
@@ -3329,6 +3348,9 @@ pdf14_end_transparency_group(gx_device *dev,
code = pdf14_pop_transparency_group(pis, pdev->ctx, pdev->blend_procs,
pdev->color_info.num_components, group_profile,
(gx_device *) pdev);
+#ifdef DEBUG
+ pdf14_debug_mask_stack_state(pdev->ctx);
+#endif
/* May need to reset some color stuff related
* to a mismatch between the parents color space
* and the group blending space */
@@ -4004,6 +4026,9 @@ pdf14_end_transparency_mask(gx_device *dev, gs_imager_state *pis,
if_debug0('v', "pdf14_end_transparency_mask\n");
ok = pdf14_pop_transparency_mask(pdev->ctx, pis, dev);
+#ifdef DEBUG
+ pdf14_debug_mask_stack_state(pdev->ctx);
+#endif
/* May need to reset some color stuff related
* to a mismatch between the Smask color space
* and the Smask blending space */
@@ -5735,6 +5760,8 @@ get_pdf14_clist_device_proto(gx_device * dev, pdf14_clist_device ** pdevproto,
ptempdevproto->color_info.max_components = 1;
ptempdevproto->color_info.num_components =
ptempdevproto->color_info.max_components;
+ ptempdevproto->color_info.max_gray = 255;
+ ptempdevproto->color_info.gray_index = 0; /* Avoid halftoning */
*pdevproto = ptempdevproto;
break;
case PDF14_DeviceRGB:
@@ -7437,3 +7464,49 @@ pdf14_free_smask_color(pdf14_device * pdev)
pdev->smaskcolor = NULL;
}
}
+
+#if DUMP_MASK_STACK
+
+static void
+dump_mask_stack(pdf14_mask_t *mask_stack)
+{
+ pdf14_mask_t *curr_mask = mask_stack;
+ int level = 0;
+
+ while (curr_mask != NULL) {
+ if_debug1('v', "[v]mask_level, %d\n", level);
+ if_debug1('v', "[v]mask_buf, %x\n", curr_mask->rc_mask->mask_buf);
+ if_debug1('v', "[v]rc_count, %d\n", curr_mask->rc_mask->rc);
+ level++;
+ curr_mask = curr_mask->previous;
+ }
+}
+
+/* A function to display the current state of the mask stack */
+static void
+pdf14_debug_mask_stack_state(pdf14_ctx *ctx)
+{
+ if_debug1('v', "[v]ctx_maskstack, %x\n", ctx->mask_stack);
+ if (ctx->mask_stack != NULL) {
+ dump_mask_stack(ctx->mask_stack);
+ }
+ if_debug1('v', "[v]ctx_stack, %x\n", ctx->stack);
+ if (ctx->stack != NULL) {
+ if_debug1('v', "[v]ctx_stack_maskstack, %x\n", ctx->stack->mask_stack);
+ if (ctx->stack->mask_stack != NULL) {
+ dump_mask_stack(ctx->stack->mask_stack);
+ }
+ }
+}
+
+#else
+
+#ifdef DEBUG
+static void
+pdf14_debug_mask_stack_state(pdf14_ctx *ctx)
+{
+ return;
+}
+#endif
+
+#endif
diff --git a/gs/base/gxpcmap.c b/gs/base/gxpcmap.c
index d9fa1d602..3fe4936e0 100644
--- a/gs/base/gxpcmap.c
+++ b/gs/base/gxpcmap.c
@@ -34,6 +34,7 @@
#include "gzstate.h"
#include "gxdevsop.h"
#include "gdevmpla.h"
+#include "gdevp14.h"
#if RAW_PATTERN_DUMP
unsigned int global_pat_index = 0;
@@ -1330,9 +1331,26 @@ gx_pattern_load(gx_device_color * pdc, const gs_imager_state * pis,
return code;
}
if (pinst->template.uses_transparency) {
- if_debug0('v', "gx_pattern_load: popping the pdf14 compositor device from this graphics state\n");
+ /* if_debug0('v', "gx_pattern_load: popping the pdf14 compositor device from this graphics state\n");
if ((code = gs_pop_pdf14trans_device(saved, true)) < 0)
- return code;
+ return code; */
+ if (pinst->is_clist) {
+ /* Send the compositor command to close the PDF14 device */
+ code = (gs_pop_pdf14trans_device(saved, true) < 0);
+ if (code < 0)
+ return code;
+ } else {
+ /* Not a clist, get PDF14 buffer information */
+ code =
+ pdf14_get_buffer_information(saved->device,
+ ((gx_device_pattern_accum*)adev)->transbuff,
+ saved->memory,
+ true);
+ /* PDF14 device (and buffer) is destroyed when pattern cache
+ entry is removed */
+ if (code < 0)
+ return code;
+ }
}
/* We REALLY don't like the following cast.... */
code = gx_pattern_cache_add_entry((gs_imager_state *)pis,
diff --git a/gs/base/lib.mak b/gs/base/lib.mak
index 53b11646a..f7f12378b 100644
--- a/gs/base/lib.mak
+++ b/gs/base/lib.mak
@@ -2366,7 +2366,7 @@ $(GLOBJ)gxpcmap.$(OBJ) : $(GLSRC)gxpcmap.c $(AK) $(gx_h) $(gserrors_h)\
$(gsstruct_h) $(gsutil_h)\
$(gxcolor2_h) $(gxcspace_h) $(gxdcolor_h) $(gxdevice_h) $(gxdevmem_h)\
$(gxfixed_h) $(gxmatrix_h) $(gxpcolor_h) $(gxclist_h) $(gxcldev_h)\
- $(gzstate_h) $(MAKEDIRS)
+ $(gzstate_h) $(gdevp14_h) $(MAKEDIRS)
$(GLCC) $(GLO_)gxpcmap.$(OBJ) $(C_) $(GLSRC)gxpcmap.c
# ---------------- PostScript Type 1 (and Type 4) fonts ---------------- #
diff --git a/xps/xpsgradient.c b/xps/xpsgradient.c
index 8628f46c5..0a0afb9f2 100644
--- a/xps/xpsgradient.c
+++ b/xps/xpsgradient.c
@@ -935,6 +935,9 @@ xps_parse_gradient_brush(xps_context_t *ctx, char *base_uri, xps_resource_t *dic
return gs_rethrow(code, "cannot draw gradient color");
}
gs_end_transparency_group(ctx->pgs);
+ /* Need to remove the soft mask from the graphic state. Otherwise
+ we may end up using it in subsequent drawings */
+ gs_pop_transparency_state(ctx->pgs);
}
else
{
diff --git a/xps/xpsimage.c b/xps/xpsimage.c
index 10a1d52c6..2da749e40 100644
--- a/xps/xpsimage.c
+++ b/xps/xpsimage.c
@@ -318,7 +318,9 @@ xps_paint_image_brush(xps_context_t *ctx, char *base_uri, xps_resource_t *dict,
return gs_rethrow(code, "cannot draw color channel image");
}
gs_end_transparency_group(ctx->pgs);
-
+ /* Need to remove the soft mask from the graphic state. Otherwise
+ we may end up using it in subsequent drawings */
+ gs_pop_transparency_state(ctx->pgs);
code = gs_grestore(ctx->pgs);
if (code < 0)
return gs_rethrow(code, "cannot grestore after transparency group");
diff --git a/xps/xpsopacity.c b/xps/xpsopacity.c
index cafb87664..9545a610b 100644
--- a/xps/xpsopacity.c
+++ b/xps/xpsopacity.c
@@ -99,4 +99,7 @@ xps_end_opacity(xps_context_t *ctx, char *base_uri, xps_resource_t *dict,
if (!opacity_att && !opacity_mask_tag)
return;
gs_end_transparency_group(ctx->pgs);
+ /* Need to remove the soft mask from the graphic state. Otherwise
+ we may end up using it in subsequent drawings */
+ gs_pop_transparency_state(ctx->pgs);
}
diff --git a/xps/xpstile.c b/xps/xpstile.c
index 315bfcfd5..9844b1431 100644
--- a/xps/xpstile.c
+++ b/xps/xpstile.c
@@ -307,6 +307,7 @@ xps_parse_tiling_brush(xps_context_t *ctx, char *base_uri, xps_resource_t *dict,
gs_client_pattern gspat;
gs_client_color gscolor;
gs_color_space *cs;
+ bool has_transparency = false;
closure.ctx = ctx;
closure.base_uri = base_uri;
@@ -321,6 +322,20 @@ xps_parse_tiling_brush(xps_context_t *ctx, char *base_uri, xps_resource_t *dict,
closure.viewbox.q.x = viewbox.q.x;
closure.viewbox.q.y = viewbox.q.y;
+ /* We need to know if this tiling brush includes transparency. */
+ for (node = xps_down(root); node; node = xps_next(node))
+ {
+ if (!strcmp(xps_tag(node), "VisualBrush.Visual"))
+ {
+ if (xps_element_has_transparency(ctx, base_uri, xps_down(node)))
+ has_transparency = true;
+ }
+ }
+ if (!strcmp(xps_tag(root), "ImageBrush"))
+ {
+ if (xps_image_brush_has_transparency(ctx, base_uri, root))
+ has_transparency = true;
+ }
gs_pattern1_init(&gspat);
uid_set_UniqueID(&gspat.uid, gs_next_ids(ctx->memory, 1));
gspat.PaintType = 1;
@@ -328,6 +343,8 @@ xps_parse_tiling_brush(xps_context_t *ctx, char *base_uri, xps_resource_t *dict,
gspat.PaintProc = xps_remap_pattern;
gspat.client_data = &closure;
+ gspat.uses_transparency = has_transparency;
+
gspat.XStep = viewbox.q.x - viewbox.p.x;
gspat.YStep = viewbox.q.y - viewbox.p.y;
gspat.BBox.p.x = viewbox.p.x;
@@ -353,10 +370,13 @@ xps_parse_tiling_brush(xps_context_t *ctx, char *base_uri, xps_resource_t *dict,
cs = ctx->srgb;
gs_setcolorspace(ctx->pgs, cs);
+ gsicc_profile_reference(cs->cmm_icc_profile_data, 1);
+
gs_makepattern(&gscolor, &gspat, &transform, ctx->pgs, NULL);
gs_setpattern(ctx->pgs, &gscolor);
xps_fill(ctx);
+ gsicc_profile_reference(cs->cmm_icc_profile_data, -1);
/* gs_makepattern increments the pattern count stored in the color
* structure. We will discard the color struct (its on the stack)