[gs-cvs] rev 8430 - trunk/gs/src

tor at ghostscript.com tor at ghostscript.com
Mon Dec 10 08:13:27 PST 2007


Author: tor
Date: 2007-12-10 08:13:26 -0800 (Mon, 10 Dec 2007)
New Revision: 8430

Modified:
   trunk/gs/src/gdevp14.c
   trunk/gs/src/gdevp14.h
Log:
Pick up the transparency mask buffer when a new transparency group is pushed rather than when it is popped. Solves memory leaks and incorrect rendering when transparency groups are nested.

Modified: trunk/gs/src/gdevp14.c
===================================================================
--- trunk/gs/src/gdevp14.c	2007-12-10 09:45:03 UTC (rev 8429)
+++ trunk/gs/src/gdevp14.c	2007-12-10 16:13:26 UTC (rev 8430)
@@ -553,7 +553,8 @@
     result->n_planes = n_planes;
     result->rowstride = rowstride;
     result->transfer_fn = NULL;
-    
+    result->maskbuf = NULL;
+
     if (height <= 0) {
 	/* Empty clipping - will skip all drawings. */
 	result->planestride = 0;
@@ -583,6 +584,10 @@
 static	void
 pdf14_buf_free(pdf14_buf *buf, gs_memory_t *memory)
 {
+    if (buf->maskbuf) {
+	errprintf("forgot to free transparency maskbuf\n");
+	pdf14_buf_free(buf->maskbuf, memory);
+    }
     gs_free_object(memory, buf->transfer_fn, "pdf14_buf_free");
     gs_free_object(memory, buf->data, "pdf14_buf_free");
     gs_free_object(memory, buf, "pdf14_buf_free");
@@ -684,6 +689,14 @@
     buf->saved = tos;
     ctx->stack = buf;
 
+    /* If a transparency mask is used for this group, this function call will have
+       been preceded by pdf14_push_transparency_mask ... pdf14_pop_transparency_mask
+       calls to create the mask buffer. This mask is stored in ctx->maskbuf.
+       We pick it up here when pushing the group (instead of when popping)
+       so that nested transparency groups and masks will work. */
+    buf->maskbuf = ctx->maskbuf;
+    ctx->maskbuf = NULL;
+
     if (buf->data == NULL)
 	return 0;
 
@@ -732,7 +745,7 @@
 {
     pdf14_buf *tos = ctx->stack;
     pdf14_buf *nos = tos->saved;
-    pdf14_buf *maskbuf = ctx->maskbuf;
+    pdf14_buf *maskbuf = tos->maskbuf;
     int y0 = max(tos->rect.p.y, nos->rect.p.y);
     int y1 = min(tos->rect.q.y, nos->rect.q.y);
     int x0 = max(tos->rect.p.x, nos->rect.p.x);
@@ -887,14 +900,20 @@
 
     ctx->stack = nos;
     if_debug0('v', "[v]pop buf\n");
-    pdf14_buf_free(tos, ctx->memory);
     if (maskbuf != NULL) {
 	pdf14_buf_free(maskbuf, ctx->memory);
-	ctx->maskbuf = NULL;
+	tos->maskbuf = NULL;
     }
+    pdf14_buf_free(tos, ctx->memory);
     return 0;
 }
 
+/*
+ * Create a transparency mask that will be used as the mask for
+ * the next transparency group that is created afterwards.
+ * The sequence of calls is:
+ * push_mask, draw the mask, pop_mask, push_group, draw the group, pop_group
+ */
 static	int
 pdf14_push_transparency_mask(pdf14_ctx *ctx, gs_int_rect *rect,	byte bg_alpha,
 			     byte *transfer_fn)
@@ -928,7 +947,14 @@
     pdf14_buf *tos = ctx->stack;
 
     ctx->stack = tos->saved;
+
+    /* After creating the mask buffer we're storing it in ctx->maskbuf so
+       that the next pdf14_push_transparency_group call can pick
+       it up. */
+    if (ctx->maskbuf != NULL)
+	errprintf("programmer error. we lost a transparency mask.\n");
     ctx->maskbuf = tos;
+
     return 0;
 }
 

Modified: trunk/gs/src/gdevp14.h
===================================================================
--- trunk/gs/src/gdevp14.h	2007-12-10 09:45:03 UTC (rev 8429)
+++ trunk/gs/src/gdevp14.h	2007-12-10 16:13:26 UTC (rev 8430)
@@ -56,6 +56,9 @@
     byte *transfer_fn;
 
     gs_int_rect bbox;
+
+    /* the associated transparency mask */
+    pdf14_buf *maskbuf;
 };
 
 struct pdf14_ctx_s {



More information about the gs-cvs mailing list