diff options
author | Michael Vrhel <michael.vrhel@artifex.com> | 2011-10-22 23:51:42 -0700 |
---|---|---|
committer | Michael Vrhel <michael.vrhel@artifex.com> | 2011-10-27 11:19:50 -0700 |
commit | 2b91a85069d421465220a83c82ea491733d15017 (patch) | |
tree | b3be7f7b09d2a803c1b4b31fe95754c82761a303 | |
parent | 58722d520578050aad3d81c0f5fb477bc701a944 (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.c | 79 | ||||
-rw-r--r-- | gs/base/gxpcmap.c | 22 | ||||
-rw-r--r-- | gs/base/lib.mak | 2 | ||||
-rw-r--r-- | xps/xpsgradient.c | 3 | ||||
-rw-r--r-- | xps/xpsimage.c | 4 | ||||
-rw-r--r-- | xps/xpsopacity.c | 3 | ||||
-rw-r--r-- | xps/xpstile.c | 20 |
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) |