Author: leonardo
Date: 2008-03-03 08:01:12 -0800 (Mon, 03 Mar 2008)
New Revision: 8585

Modified:
   trunk/gs/src/gdevdflt.c
   trunk/gs/src/gdevp14.c
   trunk/gs/src/gdevp14.h
   trunk/gs/src/gsalphac.c
   trunk/gs/src/gsovrc.c
   trunk/gs/src/gstparam.h
   trunk/gs/src/gstrans.c
   trunk/gs/src/gstrans.h
   trunk/gs/src/gxclimag.c
   trunk/gs/src/gxclist.c
   trunk/gs/src/gxclist.h
   trunk/gs/src/gxclpath.c
   trunk/gs/src/gxclrast.c
   trunk/gs/src/gxcomp.h
Log:
Fix (clist) : Crop transparencsy commands while clist writing, step 2.

DETAILS :

This is a preparation to the next step.

The patch introduces a transparency stack for clist writer,
which saves cropping when entering a transparency group,
and restores when exiting it. The cropping is being narrowed
with transparency group's bounding box.

EXPECTED DIFFERENCES :

None.      


Modified: trunk/gs/src/gdevdflt.c
===================================================================
--- trunk/gs/src/gdevdflt.c	2008-03-03 11:57:42 UTC (rev 8584)
+++ trunk/gs/src/gdevdflt.c	2008-03-03 16:01:12 UTC (rev 8585)
@@ -881,7 +881,16 @@
     return 0;			/* Do nothing */
 }
 
+/*
+ * Default handler for get_cropping returns no cropping.
+ */
 int
+gx_default_composite_get_cropping(const gs_composite_t *pxcte, int *ry, int *rheight)
+{
+    return 0;			/* No cropping. */
+}
+
+int
 gx_default_finish_copydevice(gx_device *dev, const gx_device *from_dev)
 {
     /* Only allow copying the prototype. */

Modified: trunk/gs/src/gdevp14.c
===================================================================
--- trunk/gs/src/gdevp14.c	2008-03-03 11:57:42 UTC (rev 8584)
+++ trunk/gs/src/gdevp14.c	2008-03-03 16:01:12 UTC (rev 8585)
@@ -545,6 +545,7 @@
     result->transfer_fn = NULL;
     result->maskbuf = NULL;
     result->idle = idle;
+    result->mask_id = 0;
 
     if (height <= 0 || idle) {
 	/* Empty clipping - will skip all drawings. */
@@ -647,7 +648,8 @@
 pdf14_push_transparency_group(pdf14_ctx	*ctx, gs_int_rect *rect,
 			      bool isolated, bool knockout,
 			      byte alpha, byte shape,
-			      gs_blend_mode_t blend_mode, bool idle)
+			      gs_blend_mode_t blend_mode, bool idle,
+			      uint mask_id)
 {
     pdf14_buf *tos = ctx->stack;
     pdf14_buf *buf, *backdrop;
@@ -674,6 +676,7 @@
     buf->alpha = alpha;
     buf->shape = shape;
     buf->blend_mode = blend_mode;
+    buf->mask_id = mask_id;
 
     buf->maskbuf = ctx->maskbuf; /* Save becasuse the group rendering may set up 
 				    another (nested) mask. */
@@ -739,11 +742,21 @@
     int x1 = min(tos->rect.q.x, nos->rect.q.x);
     pdf14_buf *maskbuf = tos->maskbuf;
 
+    if (maskbuf != NULL && maskbuf->mask_id != tos->mask_id) {
+	/* We're under clist reader, and it skipped a group,
+	   which is resetting maskbuf. Force freeing the mask.
+	 */
+	ctx->maskbuf = maskbuf;
+	maskbuf = NULL;
+    }
     if (ctx->maskbuf) {
 	/* Happens with the test case of bug 689492 with no banding
 	   while rendering the group of an image with a mask.
 	   Not sure why gs/lib processes a mask inside the image droup,
-	   anyway we need to release it safely. */
+	   anyway we need to release it safely. 
+	   
+	   See also the comment above.
+	   */
 	pdf14_buf_free(ctx->maskbuf, ctx->memory);
 	ctx->maskbuf = NULL;
     }
@@ -895,7 +908,7 @@
 #		if VD_PAINT_COLORS
 		    vd_pixel(int2fixed(x), int2fixed(y), n_chan == 1 ? 
 			(nos_pixel[0] << 16) + (nos_pixel[0] << 8) + nos_pixel[0] :
-			(nos_pixel[0] << 16) + (nos_pixel[1] << 8) + nos_pixel[2]);*/
+			(nos_pixel[0] << 16) + (nos_pixel[1] << 8) + nos_pixel[2]);
 #		endif
 #		if VD_PAINT_ALPHA
 		    vd_pixel(int2fixed(x), int2fixed(y),
@@ -941,7 +954,8 @@
  */
 static	int
 pdf14_push_transparency_mask(pdf14_ctx *ctx, gs_int_rect *rect,	byte bg_alpha,
-			     byte *transfer_fn, bool idle, bool replacing)
+			     byte *transfer_fn, bool idle, bool replacing,
+			     uint mask_id)
 {
     pdf14_buf *buf;
 
@@ -972,6 +986,7 @@
     buf->shape = 0xff;
     buf->blend_mode = BLEND_MODE_Normal;
     buf->transfer_fn = transfer_fn;
+    buf->mask_id = mask_id;
     {	/* 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. 
@@ -1851,6 +1866,7 @@
 pdf14_disable_device(gx_device * dev)
 {
     gx_device_forward * pdev = (gx_device_forward *)dev;
+    pdf14_device *cdev = (pdf14_device *)dev;
 
     if_debug0('v', "[v]pdf14_disable_device\n");
     dev->color_info = pdev->target->color_info;
@@ -2242,7 +2258,8 @@
 }
 
 static int 
-pdf14_compute_group_device_int_rect(const gs_matrix *ctm, const gs_rect *pbbox, gs_int_rect *rect)
+pdf14_compute_group_device_int_rect(const gs_matrix *ctm, 
+				    const gs_rect *pbbox, gs_int_rect *rect)
 {
     gs_rect dev_bbox;
     int code;
@@ -2285,7 +2302,8 @@
 					 ptgp->Isolated, ptgp->Knockout,
 					 (byte)floor (255 * alpha + 0.5),
 					 (byte)floor (255 * pis->shape.alpha + 0.5),
-					 pis->blend_mode, ptgp->idle);
+					 pis->blend_mode, ptgp->idle,
+					 ptgp->mask_id);
     return code;
 }
 
@@ -2326,7 +2344,8 @@
     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, ptmp->replacing);
+					transfer_fn, ptmp->idle, ptmp->replacing,
+					ptmp->mask_id);
 }
 
 static	int
@@ -2844,25 +2863,29 @@
 #endif
 
 #define	put_value(dp, value)\
-    memcpy(dp, &value, sizeof(value));\
-    dp += sizeof(value)
+    BEGIN\
+	memcpy(dp, &value, sizeof(value));\
+	dp += sizeof(value);\
+    END
 
 /*
  * Convert a PDF 1.4 transparency compositor to string form for use by the command
  * list device.
  */
 static	int
-c_pdf14trans_write(const gs_composite_t	* pct, byte * data, uint * psize)
+c_pdf14trans_write(const gs_composite_t	* pct, byte * data, uint * psize, gx_device_clist_writer *cdev)
 {
     const gs_pdf14trans_params_t * pparams = &((const gs_pdf14trans_t *)pct)->params;
     int need, avail = *psize;
 	/* Must be large enough for largest data struct */
     byte buf[25 /* See sput_matrix. */ +
 	     21 + sizeof(pparams->Background)
-		+ sizeof(pparams->GrayBackground) + sizeof(pparams->bbox)];
+		+ sizeof(pparams->GrayBackground) + sizeof(pparams->bbox)
+		+ sizeof(cdev->mask_id)];
     byte * pbuf = buf;
     int opcode = pparams->pdf14_op;
     int mask_size = 0;
+    uint mask_id = 0;
     int len, code;
 
     /* Write PDF 1.4 compositor data into the clist */
@@ -2881,8 +2904,9 @@
 	    put_value(pbuf, pparams->num_spot_colors);	    
 	    break;
 	case PDF14_POP_DEVICE:
+	    code = 0;
+	    break;
 	case PDF14_END_TRANS_GROUP:
-	case PDF14_END_TRANS_MASK:
 	    break;			/* No data */
 	case PDF14_BEGIN_TRANS_GROUP:
 	    /*
@@ -2894,13 +2918,17 @@
 	    *pbuf++ = pparams->blend_mode;
 	    put_value(pbuf, pparams->opacity.alpha);
 	    put_value(pbuf, pparams->shape.alpha);
-	    put_value(pbuf, pparams->bbox);	    
+	    put_value(pbuf, pparams->bbox);
+	    mask_id = pparams->mask_id;
+	    put_value(pbuf, pparams->mask_id);
 	    break;
 	case PDF14_BEGIN_TRANS_MASK:
 	    put_value(pbuf, pparams->subtype);
 	    *pbuf++ = pparams->replacing;
 	    *pbuf++ = pparams->function_is_identity;
 	    *pbuf++ = pparams->Background_components;
+	    mask_id = pparams->mask_id;
+	    put_value(pbuf, pparams->mask_id);
 	    if (pparams->Background_components) {
 		const int l = sizeof(pparams->Background[0]) * pparams->Background_components;
 
@@ -2912,6 +2940,8 @@
 	    if (!pparams->function_is_identity)
 		mask_size = sizeof(pparams->transfer_fn);
 	    break;
+	case PDF14_END_TRANS_MASK:
+	    break;
 	case PDF14_SET_BLEND_PARAMS:
 	    *pbuf++ = pparams->changed;
 	    if (pparams->changed & PDF14_SET_BLEND_MODE)
@@ -2924,7 +2954,6 @@
 		put_value(pbuf, pparams->shape.alpha);
 	    break;
     }
-#undef put_value
 
     /* check for fit */
     need = (pbuf - buf) + mask_size;
@@ -2939,26 +2968,31 @@
     /* If we are writing more than the maximum ever expected,
      * return a rangecheck error.
      */
-    if ( need > MAX_CLIST_COMPOSITOR_SIZE )
+    if ( need + 3 > MAX_CLIST_COMPOSITOR_SIZE )
 	return_error(gs_error_rangecheck);
 
     /* Copy our serialzed data into the output buffer */
     memcpy(data, buf, need - mask_size);
     if (mask_size)	/* Include the transfer mask data if present */
 	memcpy(data + need - mask_size, pparams->transfer_fn, mask_size);
-    if_debug2('v', "[v] c_pdf14trans_write: opcode = %s need = %d\n",
-				pdf14_opcode_names[opcode], need);
+    if_debug3('v', "[v] c_pdf14trans_write: opcode = %s mask_id=%d need = %d\n",
+				pdf14_opcode_names[opcode], mask_id, need);
     return 0;
 }
 
+#undef put_value
+
+
 /* Function prototypes */
 static int gs_create_pdf14trans( gs_composite_t ** ppct,
 		const gs_pdf14trans_params_t * pparams,
 		gs_memory_t * mem );
 
 #define	read_value(dp, value)\
-    memcpy(&value, dp, sizeof(value));\
-    dp += sizeof(value)
+    BEGIN\
+	memcpy(&value, dp, sizeof(value));\
+	dp += sizeof(value);\
+    END
 
 /*
  * Convert the string representation of the PDF 1.4 transparency parameter
@@ -3003,6 +3037,7 @@
 	    read_value(data, params.opacity.alpha);
 	    read_value(data, params.shape.alpha);
 	    read_value(data, params.bbox);
+	    read_value(data, params.mask_id);
 	    break;
 	case PDF14_BEGIN_TRANS_MASK:
 		/* This is the largest transparency parameter at this time (potentially
@@ -3021,6 +3056,7 @@
 	    params.replacing = *data++;
 	    params.function_is_identity = *data++;
 	    params.Background_components = *data++;
+	    read_value(data, params.mask_id);
 	    if (params.Background_components) {
 		const int l = sizeof(params.Background[0]) * params.Background_components;
 
@@ -3041,8 +3077,7 @@
 	    }
 	    break;
 	case PDF14_END_TRANS_MASK:
-	    code += 0; /* A good place for a breakpoint. */
-	    break;			/* No data */
+	    break;
 	case PDF14_SET_BLEND_PARAMS:
 	    params.changed = *data++;
 	    if (params.changed & PDF14_SET_BLEND_MODE)
@@ -3059,11 +3094,11 @@
     if (code < 0)
 	return code;
     used = data - start;
-    if_debug1('v', "  used = %d\n", used);
+    if_debug2('v', " mask_id=%d used = %d\n", params.mask_id, used);
     
     /* If we read more than the maximum expected, return a rangecheck error */
-    if ( used > MAX_CLIST_COMPOSITOR_SIZE )
- 		return_error(gs_error_rangecheck);
+    if ( used + 3 > MAX_CLIST_COMPOSITOR_SIZE )
+ 	return_error(gs_error_rangecheck);
     else
     	return used;
 }
@@ -3256,6 +3291,7 @@
 static composite_is_friendly_proc(c_pdf14trans_is_friendly);
 static composite_clist_write_update(c_pdf14trans_clist_write_update);
 static composite_clist_read_update(c_pdf14trans_clist_read_update);
+static composite_get_cropping_proc(c_pdf14trans_get_cropping);
 
 
 /*
@@ -3278,7 +3314,8 @@
 	c_pdf14trans_is_friendly,                /* procs.is_friendly */
 		/* Create a PDF 1.4 clist write device */
 	c_pdf14trans_clist_write_update,   /* procs.composite_clist_write_update */
-	c_pdf14trans_clist_read_update	   /* procs.composite_clist_reade_update */
+	c_pdf14trans_clist_read_update,	   /* procs.composite_clist_reade_update */
+	c_pdf14trans_get_cropping	   /* procs.composite_get_cropping */
     }                                            /* procs */
 };
 
@@ -3294,7 +3331,8 @@
 	c_pdf14trans_is_friendly,                /* procs.is_friendly */
 		/* The PDF 1.4 clist writer already exists, Do not create it. */
 	gx_default_composite_clist_write_update, /* procs.composite_clist_write_update */
-	c_pdf14trans_clist_read_update	   /* procs.composite_clist_reade_update */
+	c_pdf14trans_clist_read_update,	   /* procs.composite_clist_reade_update */
+	c_pdf14trans_get_cropping	   /* procs.composite_get_cropping */
     }                                            /* procs */
 };
 
@@ -4159,13 +4197,9 @@
 		pdev->blend_mode = pdf14pct->params.blend_mode;
 		pdev->opacity = pdf14pct->params.opacity.alpha;
 		pdev->shape = pdf14pct->params.shape.alpha;
-		{
-		    const gs_pdf14trans_params_t * pparams = &((const gs_pdf14trans_t *)pct)->params;
-
-		    if (pparams->Background_components != 0 && 
-			pparams->Background_components != pdev->color_info.num_components)
-			return_error(gs_error_rangecheck);
-		}
+		if (pdf14pct->params.Background_components != 0 && 
+		    pdf14pct->params.Background_components != pdev->color_info.num_components)
+		    return_error(gs_error_rangecheck);
 		break;
 	    default:
 		break;		/* Pass remaining ops to target */
@@ -4418,8 +4452,6 @@
     pdf14_clist_device * p14dev;
     int code = 0;
 
-    state_update(ctm); /* See c_pdf14trans_write. */
-
     /* We only handle the push/pop operations */
     switch (pdf14pct->params.pdf14_op) {
 	case PDF14_PUSH_DEVICE:
@@ -4463,23 +4495,69 @@
 	    code = clist_writer_check_empty_cropping_stack(cdev);
 	    break;
 	case PDF14_BEGIN_TRANS_GROUP:
-	    {	pdf14_device *pdev = (pdf14_device *)*pcdev;
-		gs_int_rect rect;
+	    {	/* HACK: store mask_id into pparams for subsequent calls of c_pdf14trans_write. */
+		gs_pdf14trans_t * pdf14pct_nolconst = (gs_pdf14trans_t *) pcte; /* Break 'const'. */
 
-		code = pdf14_compute_group_device_int_rect(&ctm_only(pis),
-			&pdf14pct->params.bbox, &rect);
+		pdf14pct_nolconst->params.mask_id = (cdev->temp_mask_id != 0 ? cdev->temp_mask_id : cdev->mask_id);
+		if_debug2('v', "[v]c_pdf14trans_clist_write_update group mask_id=%d temp_mask_id=%d\n", 
+			    cdev->mask_id, cdev->temp_mask_id);
+	    }
+	    if (cdev->temp_mask_id)
+		cdev->temp_mask_id = 0;
+	    else
+		cdev->mask_id = 0;
+	    break;
+	case PDF14_END_TRANS_GROUP:
+	    code = 0; /* A place for breakpoint. */
+	    break;
+	case PDF14_BEGIN_TRANS_MASK:
+	    {   int save_mask_id = cdev->mask_id;
+		int save_temp_mask_id = cdev->temp_mask_id;
 
-		if (code >= 0)
-		    code = clist_writer_push_cropping(cdev, rect.p.y, rect.q.y - rect.p.y);
+		if (!cdev->mask_id || pdf14pct->params.replacing)
+		    cdev->mask_id = ++cdev->mask_id_count;
+		else
+		    cdev->temp_mask_id = ++cdev->mask_id_count;
+		{	/* HACK: store mask_id into pparams for subsequent calls of c_pdf14trans_write. */
+		    gs_pdf14trans_t * pdf14pct_nolconst = (gs_pdf14trans_t *) pcte; /* Break 'const'. */
+
+		    pdf14pct_nolconst->params.mask_id = (cdev->temp_mask_id != 0 ? cdev->temp_mask_id : cdev->mask_id);
+		    if_debug2('v', "[v]c_pdf14trans_clist_write_update mask mask_id=%d temp_mask_id=%d\n", 
+				cdev->mask_id, cdev->temp_mask_id);
+		}
+		code = clist_writer_push_no_cropping(cdev);
+		/* Delay updating current mask id until the mask is completed,
+		   because the mask may have internal groups and masks. 
+		   clist_writer_pop_cropping will set up the currnt mask id. */
+		cdev->mask_id = save_mask_id;
+		cdev->temp_mask_id = save_temp_mask_id;
 	    }
 	    break;
-	case PDF14_END_TRANS_GROUP:
+	case PDF14_END_TRANS_MASK:
 	    code = clist_writer_pop_cropping(cdev);
 	    break;
 	default:
 	    break;		/* do nothing for remaining ops */
     }
     *pcdev = dev;
+#if 0
+    state_update(ctm); /* See c_pdf14trans_write, c_pdf14trans_adjust_ctm, apply_create_compositor. */
+#elif 0
+    if (code < 0)
+	return code;
+    code = gs_setmatrix(&cdev->imager_state, &pdf14pct->params.ctm); /* See
+		c_pdf14trans_write, c_pdf14trans_adjust_ctm, apply_create_compositor. */
+#else
+    cdev->imager_state.ctm.xx = pdf14pct->params.ctm.xx;
+    cdev->imager_state.ctm.xy = pdf14pct->params.ctm.xy;
+    cdev->imager_state.ctm.yx = pdf14pct->params.ctm.yx;
+    cdev->imager_state.ctm.yy = pdf14pct->params.ctm.yy;
+    cdev->imager_state.ctm.tx = pdf14pct->params.ctm.tx;
+    cdev->imager_state.ctm.ty = pdf14pct->params.ctm.ty;
+    cdev->imager_state.ctm.tx_fixed = float2fixed(cdev->imager_state.ctm.tx);
+    cdev->imager_state.ctm.ty_fixed = float2fixed(cdev->imager_state.ctm.ty);
+#endif
+    cmd_clear_known(cdev, ctm_known); /* Wrote another ctm than from imager state. */
     return code;
 }
 
@@ -4565,6 +4643,33 @@
 }
 
 /*
+ * Get cropping for the compositor command.
+ */
+static	int
+c_pdf14trans_get_cropping(const gs_composite_t *pcte, int *ry, int *rheight)
+{
+    gs_pdf14trans_t * pdf14pct = (gs_pdf14trans_t *) pcte;
+    switch (pdf14pct->params.pdf14_op) {
+	case PDF14_PUSH_DEVICE: return 0; /* Applies to all bands. */
+	case PDF14_POP_DEVICE:  return 0; /* Applies to all bands. */
+	case PDF14_BEGIN_TRANS_GROUP:
+	    {	gs_int_rect rect;
+		int code;
+
+		code = pdf14_compute_group_device_int_rect(&pdf14pct->params.ctm, &pdf14pct->params.bbox, &rect);
+		*ry = rect.p.y;
+		*rheight = rect.q.y - rect.p.y;
+		return 1; /* Push croping. */
+	    }
+	case PDF14_END_TRANS_GROUP: return 2; /* Pop cropping. */
+	case PDF14_BEGIN_TRANS_MASK: return 3; /* Same cropping as before. */
+	case PDF14_END_TRANS_MASK: return 3;
+	case PDF14_SET_BLEND_PARAMS: return 3;
+    }
+    return 0;
+}
+
+/*
  * This routine will check to see if the color component name matches those
  * that are available amoung the current device's color components.  If the
  * color name is known to the output device then we add it to the list of

Modified: trunk/gs/src/gdevp14.h
===================================================================
--- trunk/gs/src/gdevp14.h	2008-03-03 11:57:42 UTC (rev 8584)
+++ trunk/gs/src/gdevp14.h	2008-03-03 16:01:12 UTC (rev 8585)
@@ -56,6 +56,7 @@
     gs_int_rect bbox;
     pdf14_buf *maskbuf; /* Save pdf14_ctx_s::maksbuf. */
     bool idle;
+    uint mask_id;
 };
 
 struct pdf14_ctx_s {

Modified: trunk/gs/src/gsalphac.c
===================================================================
--- trunk/gs/src/gsalphac.c	2008-03-03 11:57:42 UTC (rev 8584)
+++ trunk/gs/src/gsalphac.c	2008-03-03 16:01:12 UTC (rev 8585)
@@ -104,7 +104,8 @@
 	gx_default_composite_is_closing,
 	gx_default_composite_is_friendly,
 	gx_default_composite_clist_write_update,
-	gx_default_composite_clist_read_update
+	gx_default_composite_clist_read_update,
+	gx_default_composite_get_cropping
     }
 };
 typedef struct gs_composite_alpha_s {
@@ -150,7 +151,7 @@
 }
 
 static int
-c_alpha_write(const gs_composite_t * pcte, byte * data, uint * psize)
+c_alpha_write(const gs_composite_t * pcte, byte * data, uint * psize, gx_device_clist_writer *cdev)
 {
     uint size = *psize;
     uint used;

Modified: trunk/gs/src/gsovrc.c
===================================================================
--- trunk/gs/src/gsovrc.c	2008-03-03 11:57:42 UTC (rev 8584)
+++ trunk/gs/src/gsovrc.c	2008-03-03 16:01:12 UTC (rev 8585)
@@ -129,7 +129,7 @@
  * list device.
  */
 static int
-c_overprint_write(const gs_composite_t * pct, byte * data, uint * psize)
+c_overprint_write(const gs_composite_t * pct, byte * data, uint * psize, gx_device_clist_writer *cdev)
 {
     const gs_overprint_params_t *   pparams = &((const gs_overprint_t *)pct)->params;
     byte                            flags = 0;
@@ -230,7 +230,8 @@
 	c_overprint_is_closing,
 	gx_default_composite_is_friendly,
 	gx_default_composite_clist_write_update,/* procs.composite_clist_write_update */
-	gx_default_composite_clist_read_update	/* procs.composite_clist_reade_update */
+	gx_default_composite_clist_read_update,	/* procs.composite_clist_reade_update */
+	gx_default_composite_get_cropping	/* procs.composite_get_cropping */
     }                                           /* procs */
 };
 

Modified: trunk/gs/src/gstparam.h
===================================================================
--- trunk/gs/src/gstparam.h	2008-03-03 11:57:42 UTC (rev 8584)
+++ trunk/gs/src/gstparam.h	2008-03-03 16:01:12 UTC (rev 8585)
@@ -84,6 +84,7 @@
     bool Knockout;
     bool image_with_SMask;
     bool idle;
+    uint mask_id;
 } gs_transparency_group_params_t;
 
 /* Define the parameter structure for a transparency mask. */
@@ -118,6 +119,7 @@
     bool function_is_identity;
     bool idle;
     bool replacing;
+    uint mask_id;
     byte transfer_fn[MASK_TRANSFER_FUNCTION_SIZE];
 } gx_transparency_mask_params_t;
 

Modified: trunk/gs/src/gstrans.c
===================================================================
--- trunk/gs/src/gstrans.c	2008-03-03 11:57:42 UTC (rev 8584)
+++ trunk/gs/src/gstrans.c	2008-03-03 16:01:12 UTC (rev 8585)
@@ -150,7 +150,7 @@
 {
     gs_imager_state * pis = (gs_imager_state *)pgs;
     gx_device * dev = pgs->device;
-    gx_device * pdf14dev;
+    gx_device *pdf14dev = NULL;
     int code;
 
     /*
@@ -174,6 +174,7 @@
     ptgp->Isolated = false;
     ptgp->Knockout = false;
     ptgp->image_with_SMask = false;
+    ptgp->mask_id = 0;
 }
 
 int
@@ -234,6 +235,7 @@
     tgp.Isolated = pparams->Isolated;
     tgp.Knockout = pparams->Knockout;
     tgp.idle = pparams->idle;
+    tgp.mask_id = pparams->mask_id;
     pis->opacity.alpha = pparams->opacity.alpha;
     pis->shape.alpha = pparams->shape.alpha;
     pis->blend_mode = pparams->blend_mode;
@@ -354,6 +356,7 @@
     tmp.function_is_identity = pparams->function_is_identity;
     tmp.idle = pparams->idle;
     tmp.replacing = pparams->replacing;
+    tmp.mask_id = pparams->mask_id;
     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-03-03 11:57:42 UTC (rev 8584)
+++ trunk/gs/src/gstrans.h	2008-03-03 16:01:12 UTC (rev 8585)
@@ -88,8 +88,9 @@
     gs_transparency_source_t shape;
     bool mask_is_image;
     gs_matrix ctm;
-    bool idle;
     bool replacing;
+    bool idle; /* For clist reader.*/
+    uint mask_id; /* For clist reader.*/
 };
 
 #ifndef gs_pdf14trans_params_DEFINED

Modified: trunk/gs/src/gxclimag.c
===================================================================
--- trunk/gs/src/gxclimag.c	2008-03-03 11:57:42 UTC (rev 8584)
+++ trunk/gs/src/gxclimag.c	2008-03-03 16:01:12 UTC (rev 8585)
@@ -856,8 +856,14 @@
 			gs_imager_state * pis, gs_memory_t * mem)
 {
     byte * dp;
-    uint size = 0;
-    int code = pcte->type->procs.write(pcte, 0, &size);
+    uint size = 0, size_dummy;
+    gx_device_clist_writer * const cdev =
+		    &((gx_device_clist *)dev)->writer;
+    int ry, rheight, cropping_op;
+    int band_height = cdev->page_info.band_params.BandHeight;
+    int last_band = (cdev->height + band_height - 1) / band_height;
+    int first_band = 0, no_of_bands = last_band + 1;
+    int code = pcte->type->procs.write(pcte, 0, &size, cdev);
 
     /* determine the amount of space required */
     if (code < 0 && code != gs_error_rangecheck)
@@ -870,41 +876,78 @@
     if (code < 0)
         return code;
 
-#if 0 /* Disabled sinse c_pdf14trans_write includes CTM into the pdf14 compositor parameters. */
-    if (pcte->type->comp_id == GX_COMPOSITOR_PDF14_TRANS) {
-	gx_device_clist_writer * const cdev =
-			&((gx_device_clist *)dev)->writer;
-	int len = cmd_write_ctm_return_length(cdev, &ctm_only(pis));
+    code = pcte->type->procs.get_cropping(pcte, &ry, &rheight);
+    if (code < 0)
+	return code;
+    cropping_op = code;
+    if (cropping_op == 1) {
+	first_band = ry / band_height;
+	last_band = (ry + rheight + band_height - 1) / band_height;
+    } else if (cropping_op > 1) {
+	first_band = cdev->cropping_min / band_height;
+	last_band = (cdev->cropping_max + band_height - 1) / band_height;
+    }
+    if (last_band - first_band > no_of_bands * 2 / 3) {
+	/* Covering many bands, so write "all bands" command for shorter clist. */
+	cropping_op = 0;
+    }
+    if (cropping_op == 0) {
+	/* overprint applies to all bands */
+	size_dummy = size;
+	code = set_cmd_put_all_op( dp,
+				   (gx_device_clist_writer *)dev,
+				   cmd_opv_extend,
+				   size );
+	if (code < 0)
+	    return code;
 
-	code = set_cmd_put_all_op(dp, (gx_device_clist_writer *)dev,
-                           cmd_opv_set_ctm, len + 1);
+	/* insert the command and compositor identifier */
+	dp[1] = cmd_opv_ext_create_compositor;
+	dp[2] = pcte->type->comp_id;
+
+	/* serialize the remainder of the compositor */
+	if ((code = pcte->type->procs.write(pcte, dp + 3, &size_dummy, cdev)) < 0)
+	    ((gx_device_clist_writer *)dev)->cnext = dp;
+	return code;
+    } 
+    if (cropping_op == 1) {
+	code = clist_writer_push_cropping(cdev, ry, rheight);
 	if (code < 0)
 	    return code;
-	/* fixme: would like to set pcls->known for covered bands. */
-	code = cmd_write_ctm(&ctm_only(pis), dp, len);
+    }
+    {
+	/* The pdf14 compositor could be applied 
+	   only to bands covered by the pcte->params.bbox. */
+	cmd_rects_enum_t re;
+
+	RECT_ENUM_INIT(re, cdev->cropping_min, cdev->cropping_max - cdev->cropping_min);
+	do {
+	    RECT_STEP_INIT(re);
+	    re.pcls->band_complexity.nontrivial_rops = true;
+	    do {
+		code = set_cmd_put_op(dp, cdev, re.pcls, cmd_opv_extend, size);
+		if (code >= 0) {
+		    size_dummy = size;
+		    dp[1] = cmd_opv_ext_create_compositor;
+		    dp[2] = pcte->type->comp_id;
+		    code = pcte->type->procs.write(pcte, dp + 3, &size_dummy, cdev);
+		}
+	    } while (RECT_RECOVER(code));
+	    if (code < 0 && SET_BAND_CODE(code))
+		goto error_in_rect;
+	    re.y += re.height;
+	    continue;
+    error_in_rect:
+	    if (!(cdev->error_is_retryable && cdev->driver_call_nesting == 0 &&
+		    SET_BAND_CODE(clist_VMerror_recover_flush(cdev, re.band_code)) >= 0))
+		return re.band_code;
+	} while (re.y < re.yend);
+    }
+    if (cropping_op == 2) {
+	code = clist_writer_pop_cropping(cdev);
 	if (code < 0)
 	    return code;
-	state_update(ctm);
     }
-#endif
-
-    /* overprint applies to all bands */
-    /* fixme: optimize: the pdf14 compositor could be applied 
-       only to bands covered by the pcte->params.bbox. */
-    code = set_cmd_put_all_op( dp,
-                               (gx_device_clist_writer *)dev,
-                               cmd_opv_extend,
-                               size );
-    if (code < 0)
-        return code;
-
-    /* insert the command and compositor identifier */
-    dp[1] = cmd_opv_ext_create_compositor;
-    dp[2] = pcte->type->comp_id;
-
-    /* serialize the remainder of the compositor */
-    if ((code = pcte->type->procs.write(pcte, dp + 3, &size)) < 0)
-        ((gx_device_clist_writer *)dev)->cnext = dp;
     return code;
 }
 

Modified: trunk/gs/src/gxclist.c
===================================================================
--- trunk/gs/src/gxclist.c	2008-03-03 11:57:42 UTC (rev 8584)
+++ trunk/gs/src/gxclist.c	2008-03-03 16:01:12 UTC (rev 8585)
@@ -470,6 +470,8 @@
     cdev->cropping_min = cdev->save_cropping_min = 0;
     cdev->cropping_max = cdev->save_cropping_max = cdev->height;
     cdev->cropping_stack = NULL;
+    cdev->cropping_level = 0;
+    cdev->mask_id_count = cdev->mask_id = cdev->temp_mask_id = 0;
     return 0;
 }
 /*
@@ -883,9 +885,6 @@
     return min(dev->height - start, band_height);
 }
 
-
-
-
 /* copy constructor if from != NULL
  * default constructor if from == NULL
  */
@@ -916,10 +915,14 @@
 
     if (buf == NULL)
 	return_error(gs_error_VMerror);
+    if_debug1('v', "[v]push cropping[%d]\n", cdev->cropping_level);
     buf->next = cdev->cropping_stack;
     cdev->cropping_stack = buf;
     buf->cropping_min = cdev->cropping_min;
     buf->cropping_max = cdev->cropping_max;
+    buf->mask_id = cdev->mask_id;
+    buf->temp_mask_id = cdev->temp_mask_id;
+    cdev->cropping_level++;
     return 0;
 }
 
@@ -944,7 +947,11 @@
 	return_error(gs_error_unregistered); /*Must not happen. */
     cdev->cropping_min = buf->cropping_min;
     cdev->cropping_max = buf->cropping_max;
+    cdev->mask_id = buf->mask_id;
+    cdev->temp_mask_id = buf->temp_mask_id;
     cdev->cropping_stack = buf->next;
+    cdev->cropping_level--;
+    if_debug1('v', "[v]pop cropping[%d]\n", cdev->cropping_level);
     gs_free_object(cdev->memory, buf, "clist_writer_transparency_pop");
     return 0;
 }
@@ -953,6 +960,7 @@
 clist_writer_check_empty_cropping_stack(gx_device_clist_writer *cdev)
 {
     if (cdev->cropping_stack != NULL) {
+	if_debug1('v', "[v]Error: left %d cropping(s)\n", cdev->cropping_level);
 	return_error(gs_error_unregistered); /* Must not happen */
     }
     return 0;

Modified: trunk/gs/src/gxclist.h
===================================================================
--- trunk/gs/src/gxclist.h	2008-03-03 11:57:42 UTC (rev 8584)
+++ trunk/gs/src/gxclist.h	2008-03-03 16:01:12 UTC (rev 8585)
@@ -219,7 +219,7 @@
     gs_id id;			/* space->id for comparisons */
     const gs_color_space *space;
 } clist_color_space_t;
-typedef struct gx_device_clist_writer_s {
+struct gx_device_clist_writer_s {
     gx_device_clist_common_members;	/* (must be first) */
     int error_code;		/* error returned by cmd_put_op */
     gx_clist_state *states;	/* current state of each band */
@@ -266,9 +266,17 @@
     gs_pattern1_instance_t *pinst; /* Used when it is a pattern clist. */
     int cropping_min, cropping_max;
     int save_cropping_min, save_cropping_max;
+    int cropping_level;
+    clist_writer_cropping_buffer_t *cropping_stack;
     ulong ins_count;
-    clist_writer_cropping_buffer_t *cropping_stack;
-} gx_device_clist_writer;
+    uint mask_id_count;
+    uint mask_id;
+    uint temp_mask_id; /* Mask id of a mask of an image with SMask. */
+};
+#ifndef gx_device_clist_writer_DEFINED
+#define gx_device_clist_writer_DEFINED
+typedef struct gx_device_clist_writer_s gx_device_clist_writer;
+#endif
 
 /* Bits for gx_device_clist_writer.disable_mask. Bit set disables behavior */
 #define clist_disable_fill_path	(1 << 0)

Modified: trunk/gs/src/gxclpath.c
===================================================================
--- trunk/gs/src/gxclpath.c	2008-03-03 11:57:42 UTC (rev 8584)
+++ trunk/gs/src/gxclpath.c	2008-03-03 16:01:12 UTC (rev 8585)
@@ -604,6 +604,8 @@
 	code = gx_default_fill_path(dev, pis, ppath, params, pdcolor, pcpath);
 	cdev->cropping_min = cdev->save_cropping_min;
 	cdev->cropping_max = cdev->save_cropping_max;
+	if_debug2('v', "[v] clist_fill_path: restore cropping_min=%d croping_max=%d\n",
+				cdev->save_cropping_min, cdev->save_cropping_max);
 	return code;
     }
     if ( (cdev->disable_mask & clist_disable_fill_path) ||
@@ -647,6 +649,8 @@
 	cdev->save_cropping_max = cdev->cropping_max;
 	cdev->cropping_min = max(ry, cdev->cropping_min);
 	cdev->cropping_max = min(ry + rheight, cdev->cropping_max);
+	if_debug2('v', "[v] clist_fill_path: narrow cropping_min=%d croping_max=%d\n",
+				cdev->save_cropping_min, cdev->save_cropping_max);
 	RECT_ENUM_INIT(re, ry, rheight);
 	do {
 	    RECT_STEP_INIT(re);

Modified: trunk/gs/src/gxclrast.c
===================================================================
--- trunk/gs/src/gxclrast.c	2008-03-03 11:57:42 UTC (rev 8584)
+++ trunk/gs/src/gxclrast.c	2008-03-03 16:01:12 UTC (rev 8585)
@@ -388,17 +388,24 @@
     }
 }
 
-static inline void
+static inline int
 drop_compositor_queue(gs_composite_t **ppcomp_first, gs_composite_t **ppcomp_last, 
-		      gs_composite_t *pcomp_from, gs_memory_t *mem)
+		      gs_composite_t *pcomp_from, gs_memory_t *mem, int x0, int y0,
+		      gs_imager_state *pis)
 {
     gs_composite_t *pcomp;
 
     do {
+	int code;
+
 	pcomp = *ppcomp_last;
 	dequeue_compositor(ppcomp_first, ppcomp_last, *ppcomp_last);
+	code = pcomp->type->procs.adjust_ctm(pcomp, x0, y0, pis);
+	if (code < 0)
+	    return code;
 	free_compositor(pcomp, mem);
     } while (pcomp != pcomp_from);
+    return 0;
 }
 
 static int
@@ -1416,6 +1423,7 @@
 				    goto out;
 				break;
 			    case cmd_opv_ext_create_compositor:
+				if_debug0('L', " ext_create_compositor\n");
 				cbuf.ptr = cbp;
 				/*
 				 * The screen phase may have been changed during
@@ -1484,7 +1492,9 @@
 					} else if (code == 5) {
 					    /* Annihilate the last compositors. */
 					    enqueue_compositor(&pcomp_first, &pcomp_last, pcomp);
-					    drop_compositor_queue(&pcomp_first, &pcomp_last, pcomp_opening, mem);
+					    code = drop_compositor_queue(&pcomp_first, &pcomp_last, pcomp_opening, mem, x0, y0, &imager_state);
+					    if (code < 0)
+						goto out;
 					} else if (code == 6) {
 					    /* Mark as idle. */
 					    enqueue_compositor(&pcomp_first, &pcomp_last, pcomp);
@@ -1577,6 +1587,7 @@
                                 {
                                     uint    ht_size;
 
+				    if_debug0('L', " ext_put_halftone\n");
                                     enc_u_getw(ht_size, cbp);
                                     code = read_alloc_ht_buff(&ht_buff, ht_size, mem);
                                     if (code < 0)
@@ -1584,6 +1595,7 @@
                                 }
 				break;
 			    case cmd_opv_ext_put_ht_seg:
+				if_debug0('L', " ext_put_ht_seg\n");
                                 cbuf.ptr = cbp;
                                 code = read_ht_segment(&ht_buff, &cbuf,
 						       &imager_state, tdev,
@@ -2001,8 +2013,12 @@
     ht_buff.ht_size = 0;
     ht_buff.read_size = 0;
 
-    if (pcomp_last != NULL)
-	drop_compositor_queue(&pcomp_first, &pcomp_last, NULL, mem);
+    if (pcomp_last != NULL) {
+	int code1 = drop_compositor_queue(&pcomp_first, &pcomp_last, NULL, mem, x0, y0, &imager_state);
+
+	if (code == 0)
+	    code = code1;
+    }
     rc_decrement(pcs, "clist_playback_band");
     gx_cpath_free(&clip_path, "clist_render_band exit");
     gx_path_free(&path, "clist_render_band exit");

Modified: trunk/gs/src/gxcomp.h
===================================================================
--- trunk/gs/src/gxcomp.h	2008-03-03 11:57:42 UTC (rev 8584)
+++ trunk/gs/src/gxcomp.h	2008-03-03 16:01:12 UTC (rev 8585)
@@ -55,13 +55,16 @@
 #ifndef gs_imager_state_DEFINED
 #  define gs_imager_state_DEFINED
 typedef struct gs_imager_state_s gs_imager_state;
-
 #endif
 
 #ifndef gx_device_DEFINED
 #  define gx_device_DEFINED
 typedef struct gx_device_s gx_device;
+#endif
 
+#ifndef gx_device_clist_writer_DEFINED
+#define gx_device_clist_writer_DEFINED
+typedef struct gx_device_clist_writer_s gx_device_clist_writer;
 #endif
 
 typedef struct gs_composite_type_procs_s {
@@ -91,7 +94,7 @@
      * not changed.
      */
 #define composite_write_proc(proc)\
-  int proc(const gs_composite_t *pcte, byte *data, uint *psize)
+  int proc(const gs_composite_t *pcte, byte *data, uint *psize, gx_device_clist_writer *cdev)
     composite_write_proc((*write));
 
     /*
@@ -146,6 +149,13 @@
 			gs_imager_state * pis, gs_memory_t * mem)
     composite_clist_read_update((*clist_compositor_read_update));
 
+    /*
+     * Get compositor cropping.
+     */
+#define composite_get_cropping_proc(proc)\
+  int proc(const gs_composite_t * pcte, int *ry, int *rheight)
+    composite_get_cropping_proc((*get_cropping));
+
 } gs_composite_type_procs_t;
 
 typedef struct gs_composite_type_s {
@@ -175,6 +185,11 @@
 composite_clist_read_update(gx_default_composite_clist_read_update);
 
 /*
+ * Default implementation for get_cropping doesn't return a cropping.
+ */
+composite_get_cropping_proc(gx_default_composite_get_cropping);
+
+/*
  * Compositing objects are reference-counted, because graphics states will
  * eventually reference them.  Note that the common part has no
  * garbage-collectible pointers and is never actually instantiated, so no

_______________________________________________
gs-cvs mailing list
gs-cvs@ghostscript.com
http://www.ghostscript.com/mailman/listinfo/gs-cvs
