[gs-cvs] rev 8505 - trunk/gs/src
leonardo at ghostscript.com
leonardo at ghostscript.com
Sat Jan 26 05:21:28 PST 2008
Author: leonardo
Date: 2008-01-26 05:21:27 -0800 (Sat, 26 Jan 2008)
New Revision: 8505
Modified:
trunk/gs/src/gdevp14.c
trunk/gs/src/gstparam.h
trunk/gs/src/gstrans.c
trunk/gs/src/gstrans.h
trunk/gs/src/ztrans.c
Log:
Fix (transparency) : Memory leak after an image with soft mask.
DETAILS :
Bug 689492 "Ghostscript uses a large amount of memory".
When a PDF command stream executes "/d1 gs /d2 gs" where d1 and d2 both define an
untrivial SMask (not important whether they are same mask or different masks),
the second mask replaces the first one, and the first one to be released.
When a transparent group includes an image with a soft mask
(this case happens in the test document for the bug), the image's soft mask must
*temporary* replace the groups soft mask, and the first mask must not
be released.
The old code does not distinguish these cases, assuming that
a mask buffer is being released after rendering a group with it.
Due to that some mask buffers were never released,
causing a memory leak with banded rendering,
because the clist interpreter doesn't run the garbager.
A simpler case for demonstrating the leak could be created with
"/d1 gs /d2 gs" as explained above.
The patch defines a new bool gs_transparency_mask_params_s::replacing,
gx_transparency_mask_params_s::replacing and gs_pdf14trans_params_s::replacing
for passing the necessary information through old interfaces.
Note that as usual we cannot change the device interface for
an easier passing of this info, because we need to maintain
the compatibility with 3d party devices.
Using the 'replacing' flag, pdf14_push_transparency_mask either replaces
the old mask buffer, or creates a new one as a temporary substitution for
an image with a soft mask. In the second case the group mask is
saved in the last transparency stack element in the field
buf->maskbuf. After rendering the image's group
the function pdf14_pop_transparency_group restores
the saved mask buffer, as it was set in the transparency context
before starting the image's mask. For more details see
comments added into gdevp14.c .
EXPECTED DIFFERENCES :
None.
Modified: trunk/gs/src/gdevp14.c
===================================================================
--- trunk/gs/src/gdevp14.c 2008-01-25 08:17:16 UTC (rev 8504)
+++ trunk/gs/src/gdevp14.c 2008-01-26 13:21:27 UTC (rev 8505)
@@ -647,7 +647,7 @@
pdf14_buf *buf, *backdrop;
bool has_shape;
- if_debug0('v', "[v]pdf14_push_transparency_group\n");
+ if_debug1('v', "[v]pdf14_push_transparency_group, idle = %d\n", idle);
/* todo: fix this hack, which makes all knockout groups isolated.
For the vast majority of files, there won't be any visible
@@ -893,6 +893,14 @@
exit:
ctx->stack = nos;
+ { /* If this group is one for an image with soft mask,
+ the containing group's mask was saved in maskbuf->maskbuf.
+ Set up it now to the transparensy context as undiong
+ the save action done in pdf14_push_transparency_mask
+ when replacing==false;
+ */
+ ctx->maskbuf = (maskbuf != NULL ? maskbuf->maskbuf : NULL);
+ }
if_debug1('v', "[v]pop buf, idle=%d\n", tos->idle);
pdf14_buf_free(tos, ctx->memory);
if (maskbuf != NULL) {
@@ -910,11 +918,27 @@
*/
static int
pdf14_push_transparency_mask(pdf14_ctx *ctx, gs_int_rect *rect, byte bg_alpha,
- byte *transfer_fn, bool idle)
+ byte *transfer_fn, bool idle, bool replacing)
{
pdf14_buf *buf;
- if_debug0('v', "[v]pdf14_push_transparency_mask\n");
+ if_debug2('v', "[v]pdf14_push_transparency_mask, idle=%d, replacing=%d\n", idle, replacing);
+ if (replacing && ctx->maskbuf != NULL) {
+ if (ctx->maskbuf->maskbuf != NULL) {
+ /* fixme: We pass here when a mask of an image
+ is being replaced with the containing group's mask.
+ It looks as the image's mask covers some band,
+ but the image itself does not.
+ This situation looks strange, but it does happen
+ with the test case of the bug 689492.
+ Will need further investigation.
+ For now just release the containing group's mask.
+ */
+ pdf14_buf_free(ctx->maskbuf->maskbuf, ctx->memory);
+ }
+ pdf14_buf_free(ctx->maskbuf, ctx->memory);
+ ctx->maskbuf = NULL;
+ }
buf = pdf14_buf_new(rect, false, false, idle, ctx->n_chan, ctx->memory);
if (buf == NULL)
return_error(gs_error_VMerror);
@@ -927,6 +951,12 @@
buf->shape = 0xff;
buf->blend_mode = BLEND_MODE_Normal;
buf->transfer_fn = transfer_fn;
+ { /* If replacing=false, we start the mask for an image with SMask.
+ In this case the image's SMask temporary replaces the
+ mask of the containing group.
+ Save the containing droup's mask in buf->maskbuf : */
+ buf->maskbuf = ctx->maskbuf;
+ }
buf->saved = ctx->stack;
ctx->stack = buf;
@@ -2268,7 +2298,7 @@
if_debug1('v', "pdf14_begin_transparency_mask, bg_alpha = %d\n", bg_alpha);
memcpy(transfer_fn, ptmp->transfer_fn, size_of(ptmp->transfer_fn));
return pdf14_push_transparency_mask(pdev->ctx, &pdev->ctx->rect, bg_alpha,
- transfer_fn, ptmp->idle);
+ transfer_fn, ptmp->idle, ptmp->replacing);
}
static int
@@ -2843,6 +2873,7 @@
break;
case PDF14_BEGIN_TRANS_MASK:
put_value(pbuf, pparams->subtype);
+ *pbuf++ = pparams->replacing;
*pbuf++ = pparams->function_is_identity;
*pbuf++ = pparams->Background_components;
if (pparams->Background_components) {
@@ -2964,6 +2995,7 @@
* same condition applies.
*/
read_value(data, params.subtype);
+ params.replacing = *data++;
params.function_is_identity = *data++;
params.Background_components = *data++;
if (params.Background_components) {
Modified: trunk/gs/src/gstparam.h
===================================================================
--- trunk/gs/src/gstparam.h 2008-01-25 08:17:16 UTC (rev 8504)
+++ trunk/gs/src/gstparam.h 2008-01-26 13:21:27 UTC (rev 8505)
@@ -104,6 +104,7 @@
float GrayBackground;
int (*TransferFunction)(floatp in, float *out, void *proc_data);
gs_function_t *TransferFunction_data;
+ bool replacing;
} gs_transparency_mask_params_t;
#define MASK_TRANSFER_FUNCTION_SIZE 256
@@ -116,6 +117,7 @@
float GrayBackground;
bool function_is_identity;
bool idle;
+ bool replacing;
byte transfer_fn[MASK_TRANSFER_FUNCTION_SIZE];
} gx_transparency_mask_params_t;
Modified: trunk/gs/src/gstrans.c
===================================================================
--- trunk/gs/src/gstrans.c 2008-01-25 08:17:16 UTC (rev 8504)
+++ trunk/gs/src/gstrans.c 2008-01-26 13:21:27 UTC (rev 8505)
@@ -300,6 +300,7 @@
ptmp->Background_components = 0;
ptmp->TransferFunction = mask_transfer_identity;
ptmp->TransferFunction_data = 0;
+ ptmp->replacing = false;
}
int
@@ -327,6 +328,7 @@
params.function_is_identity =
(ptmp->TransferFunction == mask_transfer_identity);
params.mask_is_image = mask_is_image;
+ params.replacing = ptmp->replacing;
/* Sample the transfer function */
for (i = 0; i < MASK_TRANSFER_FUNCTION_SIZE; i++) {
float in = (float)(i * (1.0 / (MASK_TRANSFER_FUNCTION_SIZE - 1)));
@@ -351,6 +353,7 @@
tmp.GrayBackground = pparams->GrayBackground;
tmp.function_is_identity = pparams->function_is_identity;
tmp.idle = pparams->idle;
+ tmp.replacing = pparams->replacing;
memcpy(tmp.transfer_fn, pparams->transfer_fn, size_of(tmp.transfer_fn));
if_debug8('v', "[v](0x%lx)gx_begin_transparency_mask [%g %g %g %g]\n\
subtype = %d Background_components = %d %s\n",
Modified: trunk/gs/src/gstrans.h
===================================================================
--- trunk/gs/src/gstrans.h 2008-01-25 08:17:16 UTC (rev 8504)
+++ trunk/gs/src/gstrans.h 2008-01-26 13:21:27 UTC (rev 8505)
@@ -92,6 +92,7 @@
bool mask_is_image;
gs_matrix ctm;
bool idle;
+ bool replacing;
};
#ifndef gs_pdf14trans_params_DEFINED
Modified: trunk/gs/src/ztrans.c
===================================================================
--- trunk/gs/src/ztrans.c 2008-01-25 08:17:16 UTC (rev 8504)
+++ trunk/gs/src/ztrans.c 2008-01-26 13:21:27 UTC (rev 8505)
@@ -266,6 +266,7 @@
if ((code = enum_param(imemory, pparam, subtype_names)) < 0)
return code;
gs_trans_mask_params_init(¶ms, code);
+ params.replacing = true;
if ((code = dict_floats_param(imemory, dop, "Background",
cs_num_components(gs_currentcolorspace(i_ctx_p->pgs)),
params.Background, NULL)) < 0
More information about the gs-cvs
mailing list