[gs-cvs] rev 8636 - branches/mtrender/src

ray at ghostscript.com ray at ghostscript.com
Sun Apr 13 19:28:13 PDT 2008


Author: ray
Date: 2008-04-13 19:28:08 -0700 (Sun, 13 Apr 2008)
New Revision: 8636

Modified:
   branches/mtrender/src/dwtrace.c
   branches/mtrender/src/dwtrace.h
   branches/mtrender/src/gdevbbox.c
   branches/mtrender/src/gdevdbit.c
   branches/mtrender/src/gdevddrw.c
   branches/mtrender/src/gdevdflt.c
   branches/mtrender/src/gdevdjet.c
   branches/mtrender/src/gdevdljm.c
   branches/mtrender/src/gdevmr8n.c
   branches/mtrender/src/gdevp14.c
   branches/mtrender/src/gdevp14.h
   branches/mtrender/src/gdevpdfb.h
   branches/mtrender/src/gdevpdfd.c
   branches/mtrender/src/gdevpdfi.c
   branches/mtrender/src/gdevpdfx.h
   branches/mtrender/src/gdevpdtf.c
   branches/mtrender/src/gdevpdti.c
   branches/mtrender/src/gdevpdtt.c
   branches/mtrender/src/gdevpsft.c
   branches/mtrender/src/gdevpx.c
   branches/mtrender/src/gdevvec.c
   branches/mtrender/src/gsalphac.c
   branches/mtrender/src/gscdef.c
   branches/mtrender/src/gsdevice.c
   branches/mtrender/src/gsovrc.c
   branches/mtrender/src/gsptype1.c
   branches/mtrender/src/gstparam.h
   branches/mtrender/src/gstrans.c
   branches/mtrender/src/gstrans.h
   branches/mtrender/src/gstype42.c
   branches/mtrender/src/gxcldev.h
   branches/mtrender/src/gxclimag.c
   branches/mtrender/src/gxclist.c
   branches/mtrender/src/gxclist.h
   branches/mtrender/src/gxclpath.c
   branches/mtrender/src/gxclrast.c
   branches/mtrender/src/gxclrect.c
   branches/mtrender/src/gxcomp.h
   branches/mtrender/src/gxfill.c
   branches/mtrender/src/gxfont.h
   branches/mtrender/src/gxfont42.h
   branches/mtrender/src/gxpcmap.c
   branches/mtrender/src/siscale.c
   branches/mtrender/src/sjbig2_luratech.c
   branches/mtrender/src/zchar1.c
   branches/mtrender/src/zfont.c
Log:
Update to rev 8609 (the intent). This rev _may_ be clean, but testing was based
on additional changes which will be in subsequent commits (with separate reasons
in the log messages for those commits).


Modified: branches/mtrender/src/dwtrace.c
===================================================================
--- branches/mtrender/src/dwtrace.c	2008-04-10 23:43:36 UTC (rev 8635)
+++ branches/mtrender/src/dwtrace.c	2008-04-14 02:28:08 UTC (rev 8636)
@@ -332,7 +332,7 @@
 #    define SET_CALLBACK(I,a) I.a = 0
 #endif
 
-void visual_tracer_init(void)
+vd_trace_interface *visual_tracer_init(void)
 {   SET_CALLBACK(visual_tracer, get_dc);
     SET_CALLBACK(visual_tracer, release_dc);
     SET_CALLBACK(visual_tracer, erase);
@@ -357,6 +357,7 @@
     SET_CALLBACK(visual_tracer, set_scale);
     SET_CALLBACK(visual_tracer, set_shift);
     SET_CALLBACK(visual_tracer, set_origin);
+    return &visual_tracer;
 }
         
 void visual_tracer_close(void)

Modified: branches/mtrender/src/dwtrace.h
===================================================================
--- branches/mtrender/src/dwtrace.h	2008-04-10 23:43:36 UTC (rev 8635)
+++ branches/mtrender/src/dwtrace.h	2008-04-14 02:28:08 UTC (rev 8636)
@@ -18,7 +18,7 @@
 #  define dwtrace_INCLUDED
 
 extern struct vd_trace_interface_s visual_tracer;
-void visual_tracer_init(void);
+struct vd_trace_interface_s *visual_tracer_init(void);
 void visual_tracer_close(void);
 
 #endif /* dwtrace_INCLUDED */

Modified: branches/mtrender/src/gdevbbox.c
===================================================================
--- branches/mtrender/src/gdevbbox.c	2008-04-10 23:43:36 UTC (rev 8635)
+++ branches/mtrender/src/gdevbbox.c	2008-04-14 02:28:08 UTC (rev 8636)
@@ -755,10 +755,24 @@
 	 dev_proc(tdev, fill_path));
     int code;
 
-    if (!GX_DC_IS_TRANSPARENT(pdevc, bdev) && !gx_path_is_void(ppath)) {
+    if (ppath == NULL) {
+	/* A special handling of shfill with no path. */
 	gs_fixed_rect ibox;
 	gs_fixed_point adjust;
 
+	if (pcpath == NULL)
+	    return 0;
+	gx_cpath_inner_box(pcpath, &ibox);
+	adjust = params->adjust;
+	if (params->fill_zero_width)
+	    gx_adjust_if_empty(&ibox, &adjust);
+	adjust_box(&ibox, adjust);
+	BBOX_ADD_RECT(bdev, ibox.p.x, ibox.p.y, ibox.q.x, ibox.q.y);
+	return 0;
+    } else if (!GX_DC_IS_TRANSPARENT(pdevc, bdev) && !gx_path_is_void(ppath)) {
+	gs_fixed_rect ibox;
+	gs_fixed_point adjust;
+
 	if (gx_path_bbox(ppath, &ibox) < 0)
 	    return 0;
 	adjust = params->adjust;

Modified: branches/mtrender/src/gdevdbit.c
===================================================================
--- branches/mtrender/src/gdevdbit.c	2008-04-10 23:43:36 UTC (rev 8635)
+++ branches/mtrender/src/gdevdbit.c	2008-04-14 02:28:08 UTC (rev 8636)
@@ -347,6 +347,8 @@
     int shift = tiles->shift;
     gs_id tile_id = tiles->id;
 
+    if (rwidth == 0 || rheight == 0)
+	return_error(gs_error_unregistered); /* Must not happen. */
     fit_fill_xy(dev, x, y, w, h);
 
 #ifdef DEBUG

Modified: branches/mtrender/src/gdevddrw.c
===================================================================
--- branches/mtrender/src/gdevddrw.c	2008-04-10 23:43:36 UTC (rev 8635)
+++ branches/mtrender/src/gdevddrw.c	2008-04-14 02:28:08 UTC (rev 8636)
@@ -928,7 +928,16 @@
 		      const byte ** plane_data,
 		      int data_x, uint raster, int height)
 {
-    return gx_image_data(info, plane_data, data_x, raster, height);
+    int code;
+
+    vd_get_dc('i');
+    vd_set_shift(0, 0);
+    vd_set_scale(0.01);
+    vd_set_origin(0, 0);
+    /* vd_erase(RGB(192, 192, 192)); */
+    code = gx_image_data(info, plane_data, data_x, raster, height);
+    vd_release_dc;
+    return code;
 }
 
 int

Modified: branches/mtrender/src/gdevdflt.c
===================================================================
--- branches/mtrender/src/gdevdflt.c	2008-04-10 23:43:36 UTC (rev 8635)
+++ branches/mtrender/src/gdevdflt.c	2008-04-14 02:28:08 UTC (rev 8636)
@@ -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: branches/mtrender/src/gdevdjet.c
===================================================================
--- branches/mtrender/src/gdevdjet.c	2008-04-10 23:43:36 UTC (rev 8635)
+++ branches/mtrender/src/gdevdjet.c	2008-04-14 02:28:08 UTC (rev 8636)
@@ -425,7 +425,7 @@
     bool tumble=dev->Tumble;
 
     hpjet_make_init(pdev, init, "\033&l-180u36Z\033*r0F");
-    hpjet_make_init(pdev, even_init, "\033&l180u36Z\033*r0F");
+    sprintf(even_init, "\033&l180u36Z\033*r0F");
     return dljet_mono_print_page_copies(pdev, prn_stream, num_copies,
 					300, PCL_LJ3D_FEATURES, init, even_init, tumble);
 }
@@ -460,10 +460,22 @@
     gx_device_hpjet *dev = (gx_device_hpjet *)pdev;
     bool tumble=dev->Tumble;
 
+    /* Put out per-page initialization. */
+    /*
+       Modified by karsten at sengebusch.de
+       in duplex mode the sheet is alread in process, so there are some
+       commands which must not be sent to the printer for the 2nd page,
+       as this commands will cause the printer to eject the sheet with
+       only the 1st page printed. This commands are:
+       \033&l%dA (setting paper size)
+       \033&l%dH (setting paper tray)
+       in simplex mode we set this parameters for each page,
+       in duplex mode we set this parameters for each odd page
+       (paper tray is set by "hpjet_make_init")
+    */
     sprintf(base_init, "\033&l-180u36Z\033*r0F\033&u%dD", dots_per_inch);
     hpjet_make_init(pdev, init, base_init);
-    sprintf(even_base_init, "\033&l180u36Z\033*r0F\033&u%dD", dots_per_inch);
-    hpjet_make_init(pdev, even_init, even_base_init);
+    sprintf(even_init, "\033&l180u36Z\033*r0F\033&u%dD", dots_per_inch);
     return dljet_mono_print_page_copies(pdev, prn_stream, num_copies,
 					dots_per_inch, PCL_LJ4D_FEATURES,
 					init,even_init,tumble);
@@ -565,7 +577,10 @@
 	}
     }
     if (code>=0)
+    {
        code=param_read_bool(plist,"Tumble",&Tumble);
+       if (code != 0) Tumble = false; // default: no tumble
+    }
 
     if (code >= 0)
 	code = gdev_prn_put_params(pdev, plist);

Modified: branches/mtrender/src/gdevdljm.c
===================================================================
--- branches/mtrender/src/gdevdljm.c	2008-04-10 23:43:36 UTC (rev 8635)
+++ branches/mtrender/src/gdevdljm.c	2008-04-14 02:28:08 UTC (rev 8636)
@@ -123,20 +123,36 @@
 	}
     }
     /* Put out per-page initialization. */
-    if (features & PCL_CAN_SET_PAPER_SIZE){ 
-        fprintf(prn_stream, "\033&l%dA", paper_size); 
-    } 
-    fputs("\033&l0o0l0E", prn_stream);
-    if ((features & PCL_HAS_DUPLEX) && dupset && dup)
-    {
+    /*
+       Modified by karsten at sengebusch.de
+       in duplex mode the sheet is alread in process, so there are some
+       commands which must not be sent to the printer for the 2nd page,
+       as this commands will cause the printer to eject the sheet with
+       only the 1st page printed. This commands are:
+       \033&l%dA (setting paper size)
+       \033&l%dH (setting paper tray)
+       in simplex mode we set this parameters for each page,
+       in duplex mode we set this parameters for each odd page
+    */
+    
+    if ((features & PCL_HAS_DUPLEX) && dupset && dup) {
        /* We are printing duplex, so change margins as needed */
-       if ((pdev->PageCount%2)==0)
+       if ((pdev->PageCount%2)==0) {
+          if (features & PCL_CAN_SET_PAPER_SIZE) { 
+              fprintf(prn_stream, "\033&l%dA", paper_size); 
+          } 
+          fputs("\033&l0o0l0E", prn_stream);
           fputs(odd_page_init, prn_stream);
-       else
+       } else
           fputs(even_page_init, prn_stream);
+    } else {
+        if (features & PCL_CAN_SET_PAPER_SIZE){  
+            fprintf(prn_stream, "\033&l%dA", paper_size); 
+        } 
+        fputs("\033&l0o0l0E", prn_stream);
+        fputs(odd_page_init, prn_stream);
     }
-    else
-        fputs(odd_page_init, prn_stream);
+    
     fprintf(prn_stream, "\033&l%dX", num_copies);	/* # of copies */
 
     /* End raster graphics, position cursor at top. */

Modified: branches/mtrender/src/gdevmr8n.c
===================================================================
--- branches/mtrender/src/gdevmr8n.c	2008-04-10 23:43:36 UTC (rev 8635)
+++ branches/mtrender/src/gdevmr8n.c	2008-04-14 02:28:08 UTC (rev 8636)
@@ -24,6 +24,7 @@
 #include "gxdevrop.h"
 #include "gdevmem.h"
 #include "gdevmrop.h"
+#include "vdtrace.h"
 
 /*
  * NOTE: The 16- and 32-bit cases aren't implemented: they just fall back to
@@ -54,7 +55,7 @@
     gx_color_index const_texture = gx_no_color_index;
     uint draster = mdev->raster;
     int line_count;
-    byte *drow;
+    byte *drow, *base;
     int depth = dev->color_info.depth;
     int bpp = depth >> 3;	/* bytes per pixel, 1 or 3 */
     gx_color_index all_ones = ((gx_color_index) 1 << depth) - 1;
@@ -140,7 +141,8 @@
 
     /* Set up transfer parameters. */
     line_count = height;
-    drow = scan_line_base(mdev, y) + x * bpp;
+    base = scan_line_base(mdev, y);
+    drow = base + x * bpp;
 
     /*
      * There are 18 cases depending on whether each of the source and
@@ -192,11 +194,15 @@
 		if (bpp == 1)
 /**** 8-bit destination ****/
 		    for (; left > 0; ++dptr, --left) {
+			vd_pixel(int2fixed((dptr - base) % draster), 
+				 int2fixed((dptr - base) / draster + y), const_texture);
 			rop_body_8((byte)const_source, (byte)const_texture);
 		    }
 		else
 /**** 24-bit destination ****/
 		    for (; left > 0; dptr += 3, --left) {
+			vd_pixel(int2fixed((dptr - base) % draster / 3), 
+				 int2fixed((dptr - base) / draster + y), const_texture);
 			rop_body_24(const_source, const_texture);
 		    }
 	    }
@@ -217,6 +223,8 @@
 			for (; left > 0; ++dptr, ++sx, --left) {
 			    byte s_pixel = cbit8(srow, sx, scolors);
 
+			    vd_pixel(int2fixed((dptr - base) % draster), 
+				 int2fixed((dptr - base) / draster + y), const_texture);
 			    rop_body_8(s_pixel, (byte)const_texture);
 			}
 		    else
@@ -224,6 +232,8 @@
 			for (; left > 0; dptr += 3, ++sx, --left) {
 			    bits32 s_pixel = cbit24(srow, sx, scolors);
 
+			    vd_pixel(int2fixed((dptr - base) % draster / 3), 
+				 int2fixed((dptr - base) / draster + y), const_texture);
 			    rop_body_24(s_pixel, const_texture);
 			}
 		} else if (bpp == 1) {
@@ -233,6 +243,8 @@
 		    for (; left > 0; ++dptr, ++sptr, --left) {
 			byte s_pixel = *sptr;
 
+			vd_pixel(int2fixed((dptr - base) % draster), 
+				 int2fixed((dptr - base) / draster + y), const_texture);
 			rop_body_8(s_pixel, (byte)const_texture);
 		    }
 		} else {
@@ -242,6 +254,8 @@
 		    for (; left > 0; dptr += 3, sptr += 3, --left) {
 			bits32 s_pixel = get24(sptr);
 
+			vd_pixel(int2fixed((dptr - base) % draster / 3), 
+				 int2fixed((dptr - base) / draster + y), const_texture);
 			rop_body_24(s_pixel, const_texture);
 		    }
 		}
@@ -271,6 +285,8 @@
 			for (; left > 0; ++dptr, ++tx, --left) {
 			    byte t_pixel = cbit8(tptr, tx, tcolors);
 
+			    vd_pixel(int2fixed((dptr - base) % draster), 
+				 int2fixed((dptr - base) / draster + y), t_pixel);
 			    rop_body_8((byte)const_source, t_pixel);
 			}
 		    else
@@ -278,6 +294,8 @@
 			for (; left > 0; dptr += 3, ++tx, --left) {
 			    bits32 t_pixel = cbit24(tptr, tx, tcolors);
 
+			    vd_pixel(int2fixed((dptr - base) % draster / 3), 
+				 int2fixed((dptr - base) / draster + y), t_pixel);
 			    rop_body_24(const_source, t_pixel);
 			}
 		} else if (bpp == 1) {
@@ -286,6 +304,8 @@
 		    for (; left > 0; ++dptr, ++tptr, --left) {
 			byte t_pixel = *tptr;
 
+			vd_pixel(int2fixed((dptr - base) % draster), 
+				 int2fixed((dptr - base) / draster + y), t_pixel);
 			rop_body_8((byte)const_source, t_pixel);
 		    }
 		} else {
@@ -294,6 +314,8 @@
 		    for (; left > 0; dptr += 3, tptr += 3, --left) {
 			bits32 t_pixel = get24(tptr);
 
+			vd_pixel(int2fixed((dptr - base) % draster / 3), 
+				 int2fixed((dptr - base) / draster + y), t_pixel);
 			rop_body_24(const_source, t_pixel);
 		    }
 		}
@@ -340,6 +362,8 @@
 			byte t_pixel =
 			    (tcolors ? cbit8(tptr, tx, tcolors) : *tptr);
 
+			vd_pixel(int2fixed((dptr - base) % draster), 
+				 int2fixed((dptr - base) / draster + y), t_pixel);
 			rop_body_8(s_pixel, t_pixel);
 		    }
 		} else {
@@ -355,6 +379,8 @@
 			    (tcolors ? cbit24(tptr, tx, tcolors) :
 			     get24(tptr));
 
+			vd_pixel(int2fixed((dptr - base) % draster / 3), 
+				 int2fixed((dptr - base) / draster + y), t_pixel);
 			rop_body_24(s_pixel, t_pixel);
 		    }
 		}

Modified: branches/mtrender/src/gdevp14.c
===================================================================
--- branches/mtrender/src/gdevp14.c	2008-04-10 23:43:36 UTC (rev 8635)
+++ branches/mtrender/src/gdevp14.c	2008-04-14 02:28:08 UTC (rev 8636)
@@ -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;
     }
@@ -753,6 +766,12 @@
 	goto exit;
     if (maskbuf != NULL && maskbuf->data == NULL)
 	goto exit;
+    if (maskbuf != NULL) {
+	y0 = max(y0, maskbuf->rect.p.y);
+	y1 = min(y1, maskbuf->rect.q.y);
+	x0 = max(x0, maskbuf->rect.p.x);
+	x1 = min(x1, maskbuf->rect.q.x);
+    }
     if (x0 < x1 && y0 < y1) {
 	int n_chan = ctx->n_chan;
 	int num_comp = n_chan - 1;
@@ -895,7 +914,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 +960,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 +992,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 +1872,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;
@@ -2012,12 +2034,13 @@
 		   		 &temp_dev_proto, pis, pdf14pct);
     if (code < 0)
 	return code;
-    pdev->color_info = temp_dev_proto.color_info;
+    pdev->color_info = dev_proto->color_info;
     pdev->procs = dev_proto->procs;
+    dev->static_procs = dev_proto->static_procs;
+    gx_device_set_procs(dev);
     gx_device_fill_in_procs(dev);
-    check_device_separable((gx_device *)pdev);
-
-    return code;
+    check_device_separable(dev);
+    return dev_proc(pdev, open_device)(dev);
 }
 
 /*
@@ -2242,7 +2265,40 @@
 	return pdf14_mark_fill_rectangle(dev, x, y, w, h, color);
 }
 
+static int 
+pdf14_compute_group_device_int_rect(const gs_matrix *ctm, 
+				    const gs_rect *pbbox, gs_int_rect *rect)
+{
+    gs_rect dev_bbox;
+    int code;
+
+    code = gs_bbox_transform(pbbox, ctm, &dev_bbox);
+    if (code < 0)
+	return code;
+    rect->p.x = (int)floor(dev_bbox.p.x);
+    rect->p.y = (int)floor(dev_bbox.p.y);
+    rect->q.x = (int)ceil(dev_bbox.q.x);
+    rect->q.y = (int)ceil(dev_bbox.q.y);
+    return 0;
+}
+
 static	int
+compute_group_device_int_rect(pdf14_device *pdev, gs_int_rect *rect, const gs_rect *pbbox, gs_imager_state *pis)
+{
+    int code = pdf14_compute_group_device_int_rect(&ctm_only(pis), pbbox, rect);
+
+    if (code < 0)
+	return code;
+    rect_intersect(*rect, pdev->ctx->rect);
+    /* Make sure the rectangle is not anomalous (q < p) -- see gsrect.h */
+    if (rect->q.x < rect->p.x)
+	rect->q.x = rect->p.x;
+    if (rect->q.y < rect->p.y)
+	rect->q.y = rect->p.y;
+    return 0;
+}
+
+static	int
 pdf14_begin_transparency_group(gx_device *dev,
 			      const gs_transparency_group_params_t *ptgp,
 			      const gs_rect *pbbox,
@@ -2252,30 +2308,20 @@
 {
     pdf14_device *pdev = (pdf14_device *)dev;
     double alpha = pis->opacity.alpha * pis->shape.alpha;
-    gs_rect dev_bbox;
     gs_int_rect rect;
     int code;
 
-    code = gs_bbox_transform(pbbox, &ctm_only(pis), &dev_bbox);
+    code = compute_group_device_int_rect(pdev, &rect, pbbox, pis);
     if (code < 0)
 	return code;
-    rect.p.x = (int)floor(dev_bbox.p.x);
-    rect.p.y = (int)floor(dev_bbox.p.y);
-    rect.q.x = (int)ceil(dev_bbox.q.x);
-    rect.q.y = (int)ceil(dev_bbox.q.y);
-    rect_intersect(rect, pdev->ctx->rect);
-    /* Make sure the rectangle is not anomalous (q < p) -- see gsrect.h */
-    if (rect.q.x < rect.p.x)
-	rect.q.x = rect.p.x;
-    if (rect.q.y < rect.p.y)
-	rect.q.y = rect.p.y;
     if_debug4('v', "[v]pdf14_begin_transparency_group, I = %d, K = %d, alpha = %g, bm = %d\n",
 	      ptgp->Isolated, ptgp->Knockout, alpha, pis->blend_mode);
     code = pdf14_push_transparency_group(pdev->ctx, &rect,
 					 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;
 }
 
@@ -2310,13 +2356,21 @@
     byte bg_alpha = 0;
     byte *transfer_fn = (byte *)gs_alloc_bytes(pdev->ctx->memory, 256,
 					       "pdf14_begin_transparency_mask");
+    gs_int_rect rect;
+    int code;
 
+    if (transfer_fn == NULL)
+	return_error(gs_error_VMerror);
+    code = compute_group_device_int_rect(pdev, &rect, pbbox, pis);
+    if (code < 0)
+	return code;
     if (ptmp->Background_components)
 	bg_alpha = (int)(255 * ptmp->GrayBackground + 0.5);
     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);
+    return pdf14_push_transparency_mask(pdev->ctx, &rect, bg_alpha,
+					transfer_fn, ptmp->idle, ptmp->replacing,
+					ptmp->mask_id);
 }
 
 static	int
@@ -2834,36 +2888,55 @@
 #endif
 
 #define	put_value(dp, value)\
-    memcpy(dp, &value, sizeof(value));\
-    dp += sizeof(value)
+    BEGIN\
+	memcpy(dp, &value, sizeof(value));\
+	dp += sizeof(value);\
+    END
 
+static inline int
+c_pdf14trans_write_ctm(byte **ppbuf, const gs_pdf14trans_params_t *pparams)
+{
+    /* Note: We can't skip writing CTM if it is equal to pis->ctm,
+       because clist writer may skip this command for some bands.
+       For a better result we need individual CTM for each band.
+     */
+    byte *pbuf = *ppbuf;
+    int len, code;
+
+    len = cmd_write_ctm_return_length_nodevice(&pparams->ctm);
+    pbuf--; /* For cmd_write_ctm. */
+    code = cmd_write_ctm(&pparams->ctm, pbuf, len);
+    if (code < 0)
+	return code;
+    pbuf += len + 1;
+    *ppbuf = pbuf;
+    return 0;
+}
+
+
 /*
  * 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;
-    int len, code;
+    uint mask_id = 0;
+    int code;
 
     /* Write PDF 1.4 compositor data into the clist */
 
     *pbuf++ = opcode;			/* 1 byte */
-    len = cmd_write_ctm_return_length_nodevice(&pparams->ctm);
-    pbuf--; /* For cmd_write_ctm. */
-    code = cmd_write_ctm(&pparams->ctm, pbuf, len);
-    if (code < 0)
-	return code;
-    pbuf += len + 1;
     switch (opcode) {
 	default:			/* Should not occur. */
 	    break;
@@ -2871,26 +2944,33 @@
 	    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:
-	    /*
-	     * The bbox data is floating point.  We are not currently using it.
-	     * So we are not currently putting it into the clist.  We are also
-	     * not using the color space.
-	     */
+	    code = c_pdf14trans_write_ctm(&pbuf, pparams);
+	    if (code < 0)
+		return code;
 	    *pbuf++ = (pparams->Isolated & 1) + ((pparams->Knockout & 1) << 1);
 	    *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:
+	    code = c_pdf14trans_write_ctm(&pbuf, pparams);
+	    if (code < 0)
+		return code;
 	    put_value(pbuf, pparams->subtype);
 	    *pbuf++ = pparams->replacing;
 	    *pbuf++ = pparams->function_is_identity;
 	    *pbuf++ = pparams->Background_components;
+	    put_value(pbuf, pparams->bbox);
+	    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;
 
@@ -2902,6 +2982,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)
@@ -2914,7 +2996,6 @@
 		put_value(pbuf, pparams->shape.alpha);
 	    break;
     }
-#undef put_value
 
     /* check for fit */
     need = (pbuf - buf) + mask_size;
@@ -2929,26 +3010,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
@@ -2969,7 +3055,7 @@
     params.pdf14_op = *data++;
     if_debug2('v', "[v] c_pdf14trans_read: opcode = %s  avail = %d",
 				pdf14_opcode_names[params.pdf14_op], size);
-    data = cmd_read_matrix(&params.ctm, data);
+    memset(&params.ctm, 0, sizeof(params.ctm));
     switch (params.pdf14_op) {
 	default:			/* Should not occur. */
 	    break;
@@ -2987,12 +3073,14 @@
 	     * We are currently not using the bbox or the colorspace so they were
 	     * not placed in the clist
 	     */
+	    data = cmd_read_matrix(&params.ctm, data);
 	    params.Isolated = (*data) & 1;
 	    params.Knockout = (*data++ >> 1) & 1;
 	    params.blend_mode = *data++;
 	    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
@@ -3007,10 +3095,13 @@
 		 * Also... if another compositor param should exceed this size, this
 		 * same condition applies.
 		 */
+	    data = cmd_read_matrix(&params.ctm, data);
 	    read_value(data, params.subtype);
 	    params.replacing = *data++;
 	    params.function_is_identity = *data++;
 	    params.Background_components = *data++;
+	    read_value(data, params.bbox);
+	    read_value(data, params.mask_id);
 	    if (params.Background_components) {
 		const int l = sizeof(params.Background[0]) * params.Background_components;
 
@@ -3031,8 +3122,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)
@@ -3049,11 +3139,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;
 }
@@ -3065,8 +3155,8 @@
 c_pdf14trans_adjust_ctm(gs_composite_t * pct0, int x0, int y0, gs_imager_state *pis)
 {
     gs_pdf14trans_t *pct = (gs_pdf14trans_t *)pct0;
+    gs_matrix mat = pct->params.ctm;
 
-    gs_matrix mat = pct->params.ctm;
     if_debug6('L', " [%g %g %g %g %g %g]\n",
 	      mat.xx, mat.xy, mat.yx, mat.yy,
 	      mat.tx, mat.ty);
@@ -3244,8 +3334,9 @@
 static composite_adjust_ctm_proc(c_pdf14trans_adjust_ctm);
 static composite_is_closing_proc(c_pdf14trans_is_closing);
 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_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);
 
 
 /*
@@ -3268,7 +3359,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 */
 };
 
@@ -3284,7 +3376,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 */
 };
 
@@ -4149,13 +4242,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 */
@@ -4403,16 +4492,11 @@
 c_pdf14trans_clist_write_update(const gs_composite_t * pcte, gx_device * dev,
 		gx_device ** pcdev, gs_imager_state * pis, gs_memory_t * mem)
 {
+    gx_device_clist_writer * const cdev = &((gx_device_clist *)dev)->writer;
     const gs_pdf14trans_t * pdf14pct = (const gs_pdf14trans_t *) pcte;
     pdf14_clist_device * p14dev;
     int code = 0;
 
-    {	gx_device_clist_writer * const cdev =
-			&((gx_device_clist *)dev)->writer;
-
-	state_update(ctm); /* See c_pdf14trans_write. */
-    }
-
     /* We only handle the push/pop operations */
     switch (pdf14pct->params.pdf14_op) {
 	case PDF14_PUSH_DEVICE:
@@ -4453,11 +4537,59 @@
 #	    else 
 	    code = 0;
 #	    endif
+	    code = clist_writer_check_empty_cropping_stack(cdev);
 	    break;
+	case PDF14_BEGIN_TRANS_GROUP:
+	    {	/* 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 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 (!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_MASK:
+	    code = clist_writer_pop_cropping(cdev);
+	    break;
 	default:
 	    break;		/* do nothing for remaining ops */
     }
     *pcdev = dev;
+    if (code < 0)
+	return code;
+    code = gs_imager_setmatrix(&cdev->imager_state, &pdf14pct->params.ctm); /* See
+		c_pdf14trans_write, c_pdf14trans_adjust_ctm, apply_create_compositor. */
+    cmd_clear_known(cdev, ctm_known); /* Wrote another ctm than from imager state. */
     return code;
 }
 
@@ -4543,6 +4675,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: branches/mtrender/src/gdevp14.h
===================================================================
--- branches/mtrender/src/gdevp14.h	2008-04-10 23:43:36 UTC (rev 8635)
+++ branches/mtrender/src/gdevp14.h	2008-04-14 02:28:08 UTC (rev 8636)
@@ -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: branches/mtrender/src/gdevpdfb.h
===================================================================
--- branches/mtrender/src/gdevpdfb.h	2008-04-10 23:43:36 UTC (rev 8635)
+++ branches/mtrender/src/gdevpdfb.h	2008-04-14 02:28:08 UTC (rev 8636)
@@ -234,6 +234,8 @@
  NULL,				/* pres_soft_mask_dict */
  {0, 0},			/* objname */
  0,				/* OPDFRead_procset_length */
- 0				/* find_resource_param */
+ 0,				/* find_resource_param */
+ 0,				/* last_charpath_op */
+ 0				/* type3charpath */
 };
 

Modified: branches/mtrender/src/gdevpdfd.c
===================================================================
--- branches/mtrender/src/gdevpdfd.c	2008-04-10 23:43:36 UTC (rev 8635)
+++ branches/mtrender/src/gdevpdfd.c	2008-04-14 02:28:08 UTC (rev 8636)
@@ -1224,13 +1224,29 @@
 	    /* Set the colour for the stroke */
 	    code = pdf_reset_color(pdev, pis_for_hl_color, pdcolor, &pdev->saved_stroke_color, 
 			&pdev->stroke_used_process_color, &psdf_set_stroke_color_commands);
-	    if(code == 0) {
+	    if (code == 0) {
 		s = pdev->strm;
 		/* Text is emitted scaled so that the CTM is an identity matrix, the line width 
 		 * needs to be scaled to match otherwise we will get the default, or the current
 		 * width scaled by the CTM before the text, either of which would be wrong.
 		 */
-		pprintg1(s, "%g w\n", (pis->line_params.half_width * 2));
+		if (pdev->font3 != 0) {
+		    double det, scale;
+
+		    /* Since font matrix may have different scaling effect by
+		       different directions, we need to average them into
+		       a single scaling factor. A right way is to use
+		       the geometric average of the 2 eigenvalues of the 2x2 matrix,
+		       which appears equal to sqrt(abs(det(M)) where M
+		       is the font matrix with no translation.  */
+		    det = ((double)fixed2float(pdev->charproc_ctm.xx) * fixed2float(pdev->charproc_ctm.yy)) - 
+			((double)fixed2float(pdev->charproc_ctm.xy) * fixed2float(pdev->charproc_ctm.yx));
+		    scale = fabs(sqrt(det));
+		    scale *= 72 / pdev->HWResolution[0];
+		    pprintg1(s, "%g w\n", (pis->line_params.half_width * 2) * (float)scale);
+		} else {
+		    pprintg1(s, "%g w\n", (pis->line_params.half_width * 2));
+		}
 		/* Some trickery here. We have altered the colour, text render mode and linewidth,
 		 * we don't want those to persist. By switching to a stream context we will flush the 
 		 * pending text. This has the beneficial side effect of executing a grestore. So

Modified: branches/mtrender/src/gdevpdfi.c
===================================================================
--- branches/mtrender/src/gdevpdfi.c	2008-04-10 23:43:36 UTC (rev 8635)
+++ branches/mtrender/src/gdevpdfi.c	2008-04-14 02:28:08 UTC (rev 8636)
@@ -1380,7 +1380,7 @@
 	    if (code < 0)
 		return code;
 	    /* Scale the coordinate system, because object handlers assume so. See none_to_stream. */
-	    pprintg2(pdev->strm, "q %g 0 0 %g 0 0 cm\n",
+	    pprintg2(pdev->strm, "%g 0 0 %g 0 0 cm\n",
 		     72.0 / pdev->HWResolution[0], 72.0 / pdev->HWResolution[1]);
 	    return 1;
 	case pattern_manage__finish_accum:

Modified: branches/mtrender/src/gdevpdfx.h
===================================================================
--- branches/mtrender/src/gdevpdfx.h	2008-04-10 23:43:36 UTC (rev 8635)
+++ branches/mtrender/src/gdevpdfx.h	2008-04-14 02:28:08 UTC (rev 8636)
@@ -652,6 +652,7 @@
     int OPDFRead_procset_length;      /* PS2WRITE only. */
     void *find_resource_param; /* WARNING : not visible for garbager. */
     int last_charpath_op; /* true or false state of last charpath */
+    bool type3charpath;
 };
 
 #define is_in_page(pdev)\

Modified: branches/mtrender/src/gdevpdtf.c
===================================================================
--- branches/mtrender/src/gdevpdtf.c	2008-04-10 23:43:36 UTC (rev 8635)
+++ branches/mtrender/src/gdevpdtf.c	2008-04-14 02:28:08 UTC (rev 8636)
@@ -662,7 +662,33 @@
     int index = pdf_find_standard_font_name(chars, size);
     bool embed_as_standard_called = false;
     bool do_embed_as_standard = false; /* Quiet compiler. */
+    int code;
+    gs_font_info_t info;
 
+    memset(&info, 0x00, sizeof(gs_font_info_t));
+    code = font->procs.font_info(font, NULL, FONT_INFO_EMBEDDING_RIGHTS, &info);
+    if (code == 0 && (info.members & FONT_INFO_EMBEDDING_RIGHTS)) {
+	if ((info.EmbeddingRights == 0x0002) || (info.EmbeddingRights & 0x0200)) {
+	    /* See the OpenType specification, "The 'OS/2' and Windows Metrics Table" for details
+	       of the fstype parameter. This is a bitfield, currently we forbid embedding of fonts
+	       with these bits set:
+	       bit 1	0x0002	Fonts that have only this bit set must not be modified, embedded or
+				exchanged in any manner.
+	       bit 9	0x0200	Bitmap embedding only.
+
+	       Note for Restricted License embedding (bit 1), this must be the only level of embedding 
+	       selected (see the OpenType spec).
+             */
+	    char name[gs_font_name_max + 1];
+	    int len;
+
+	    len = min(gs_font_name_max, font->font_name.size);
+	    memcpy(name, font->font_name.chars, len);
+	    name[len] = 0;
+	    eprintf1("\nWarning: %s cannot be embedded because of licensing restrictions\n", name);
+	    return FONT_EMBED_NO;
+	}
+    }
     /*
      * The behavior of Acrobat Distiller changed between 3.0 (PDF 1.2),
      * which will never embed the base 14 fonts, and 4.0 (PDF 1.3), which

Modified: branches/mtrender/src/gdevpdti.c
===================================================================
--- branches/mtrender/src/gdevpdti.c	2008-04-10 23:43:36 UTC (rev 8635)
+++ branches/mtrender/src/gdevpdti.c	2008-04-14 02:28:08 UTC (rev 8636)
@@ -614,6 +614,9 @@
     pdev->context = PDF_IN_STREAM;
     pdev->accumulating_substream_resource = pres;
     pdev->last_charpath_op = 0;
+    /* Do not alter type3charpath, inherit the current value. We need to know if */
+    /* we are inside a charpath operation, and only reset this when the charpath */
+    /* is complete */
     pdf_reset_graphics(pdev);
     *ppres = pres;
     return 0;

Modified: branches/mtrender/src/gdevpdtt.c
===================================================================
--- branches/mtrender/src/gdevpdtt.c	2008-04-10 23:43:36 UTC (rev 8635)
+++ branches/mtrender/src/gdevpdtt.c	2008-04-14 02:28:08 UTC (rev 8636)
@@ -96,6 +96,9 @@
     pdf_text_enum_t *const penum = (pdf_text_enum_t *)pte;
     gx_device_pdf *pdev = (gx_device_pdf *)pte->dev;
 
+    if (pdev->type3charpath)
+	return gs_text_set_cache(penum->pte_default, pw, control);
+
     switch (control) {
     case TEXT_SET_CHAR_WIDTH:
     case TEXT_SET_CACHE_DEVICE:
@@ -339,28 +342,31 @@
 
     pdev->last_charpath_op = 0;
     if ((text->operation & TEXT_DO_ANY_CHARPATH) && !path0->first_subpath) {
-	if(pdf_compare_text_state_for_charpath(pdev->text->text_state, pdev, pis, font, text))
+	if (pdf_compare_text_state_for_charpath(pdev->text->text_state, pdev, pis, font, text))
 	    pdev->last_charpath_op = text->operation & TEXT_DO_ANY_CHARPATH;
     }
 
-    if (font->FontType == ft_user_defined &&
-	(text->operation & TEXT_DO_NONE) && (text->operation & TEXT_RETURN_WIDTH)) {
-	/* This is stringwidth, see gx_default_text_begin.
-	 * We need to prevent writing characters to PS cache,
-	 * otherwise the font converts to bitmaps.
-	 * So pass through even with stringwidth.
-	 */
-	code = gx_hld_stringwidth_begin(pis, &path);
-	if (code < 0)
-	    return code;
-    } else if ((!(text->operation & TEXT_DO_DRAW) && pis->text_rendering_mode != 3) 
-		|| path == 0 || gx_path_current_point(path, &cpt) < 0
-	    )
-	return gx_default_text_begin(dev, pis, text, font, path, pdcolor,
+    if (font->FontType != ft_user_defined || !(text->operation & TEXT_DO_ANY_CHARPATH)) {
+        if (font->FontType == ft_user_defined &&
+	    (text->operation & TEXT_DO_NONE) && (text->operation & TEXT_RETURN_WIDTH)) {
+	    /* This is stringwidth, see gx_default_text_begin.
+	     * We need to prevent writing characters to PS cache,
+	     * otherwise the font converts to bitmaps.
+	     * So pass through even with stringwidth.
+	     */
+	    code = gx_hld_stringwidth_begin(pis, &path);
+	    if (code < 0)
+		return code;
+	} else if ((!(text->operation & TEXT_DO_DRAW) && pis->text_rendering_mode != 3) 
+/*		    || path == 0 || gx_path_current_point(path, &cpt) < 0 */
+		    || path == 0 || path_position_valid(path) < 0
+		    || pdev->type3charpath) 
+	    return gx_default_text_begin(dev, pis, text, font, path, pdcolor,
 					 pcpath, mem, ppte);
-    else if (text->operation & TEXT_DO_ANY_CHARPATH)
-	return gx_default_text_begin(dev, pis, text, font, path, pdcolor,
+	else if (text->operation & TEXT_DO_ANY_CHARPATH)
+	    return gx_default_text_begin(dev, pis, text, font, path, pdcolor,
 					 pcpath, mem, ppte);
+    }
 
     /* Allocate and initialize the enumerator. */
 
@@ -2408,6 +2414,12 @@
 	    penum->current_font = penum->orig_font;
 	}
     }
+    if (penum->current_font->FontType == ft_user_defined && (penum->text.operation & TEXT_DO_ANY_CHARPATH)
+	&& !pdev->type3charpath) {
+	pdev->type3charpath = true;
+	goto default_impl;
+    }
+
     code = -1;		/* to force default implementation */
 
     /*
@@ -2431,7 +2443,7 @@
 		len = min(gs_font_name_max, gnstr.size);
 		memcpy(glyph, gnstr.data, len);
 		glyph[len] = 0x00;
-		len = min(255, penum->current_font->font_name.size);
+		len = min(gs_font_name_max, penum->current_font->font_name.size);
 		memcpy(FontName, penum->current_font->font_name.chars, len);
 		FontName[len] = 0x00;
 		len = min(255, penum->current_font->key_name.size);
@@ -2459,7 +2471,7 @@
 	code = gs_text_process(pte_default);
 	pdev->pte = NULL;	 /* CAUTION: See comment in gdevpdfx.h . */
 	pdev->charproc_just_accumulated = false;
-	if (code == TEXT_PROCESS_RENDER) {
+	if (code == TEXT_PROCESS_RENDER && !pdev->type3charpath) {
 	    penum->returned.current_char = pte_default->returned.current_char;
 	    penum->returned.current_glyph = pte_default->returned.current_glyph;
 	    pdev->charproc_ctm = penum->pis->ctm;
@@ -2511,6 +2523,8 @@
 	    return code;
 	gs_text_release(pte_default, "pdf_text_process");
 	penum->pte_default = 0;
+	if (pdev->type3charpath)
+	    pdev->type3charpath = false;
 	return 0;
     }
     {

Modified: branches/mtrender/src/gdevpsft.c
===================================================================
--- branches/mtrender/src/gdevpsft.c	2008-04-10 23:43:36 UTC (rev 8635)
+++ branches/mtrender/src/gdevpsft.c	2008-04-14 02:28:08 UTC (rev 8636)
@@ -494,6 +494,8 @@
 write_OS_2(stream *s, gs_font *font, uint first_glyph, int num_glyphs)
 {
     ttf_OS_2_t os2;
+    gs_font_info_t info;
+    int code;
 
     /*
      * We don't bother to set most of the fields.  The really important
@@ -507,6 +509,17 @@
     put_u16(os2.usWeightClass, 400); /* Normal */
     put_u16(os2.usWidthClass, 5); /* Normal */
     update_OS_2(&os2, first_glyph, num_glyphs);
+
+    /*
+     * We should also preserve the licensed embedding rights, to prevent
+     * 'laundering' a TrueType font. These can be non-zero even when embedding is permitted.
+     */
+    memset(&info, 0x00, sizeof(gs_font_info_t));
+    code = font->procs.font_info(font, NULL, FONT_INFO_EMBEDDING_RIGHTS, &info);
+    if (code == 0 && (info.members & FONT_INFO_EMBEDDING_RIGHTS)) {
+	put_u16(os2.fsType, info.EmbeddingRights);
+    }
+
     stream_write(s, &os2, offset_of(ttf_OS_2_t, sxHeight[0]));
     put_pad(s, offset_of(ttf_OS_2_t, sxHeight[0]));
 }

Modified: branches/mtrender/src/gdevpx.c
===================================================================
--- branches/mtrender/src/gdevpx.c	2008-04-10 23:43:36 UTC (rev 8635)
+++ branches/mtrender/src/gdevpx.c	2008-04-14 02:28:08 UTC (rev 8636)
@@ -514,14 +514,14 @@
 	    r.ptr = data + i * raster - 1;
 	    r.limit = r.ptr + width_bytes;
 	    if ((*s_RLE_template.process)
-		((stream_state *) & rlstate, &r, &w, false) != 0 ||
+		((stream_state *) & rlstate, &r, &w, true) != 0 ||
 		r.ptr != r.limit
 		)
 		goto ncfree;
 	    r.ptr = (const byte *)"\000\000\000\000\000";
 	    r.limit = r.ptr + (-(int)width_bytes & 3);
 	    if ((*s_RLE_template.process)
-		((stream_state *) & rlstate, &r, &w, false) != 0 ||
+		((stream_state *) & rlstate, &r, &w, true) != 0 ||
 		r.ptr != r.limit
 		)
 		goto ncfree;
@@ -1218,6 +1218,11 @@
     code = gdev_vector_update_clip_path(vdev, NULL);
     if (code < 0)
 	return code;
+
+    if (data_x !=0 )
+        return gx_default_copy_mono(dev, data, data_x, raster, id, 
+  				    x, y, w, h, zero, one);
+
     pclxl_set_cursor(xdev, x, y);
     if (id != gs_no_id && zero == gx_no_color_index &&
 	one != gx_no_color_index && data_x == 0
@@ -1296,6 +1301,8 @@
     code = gdev_vector_update_clip_path(vdev, NULL);
     if (code < 0)
 	return code;
+
+
     source_bit = sourcex * dev->color_info.depth;
     if ((source_bit & 7) != 0)
 	return gx_default_copy_color(dev, base, sourcex, raster, id,

Modified: branches/mtrender/src/gdevvec.c
===================================================================
--- branches/mtrender/src/gdevvec.c	2008-04-10 23:43:36 UTC (rev 8635)
+++ branches/mtrender/src/gdevvec.c	2008-04-14 02:28:08 UTC (rev 8636)
@@ -300,7 +300,7 @@
 	    gs_free_object(vdev->v_memory, vdev->strmbuf,
 			   "vector_open(strmbuf)");
 	vdev->strmbuf = 0;
-	fclose(vdev->file);
+	gx_device_close_output_file((gx_device *)vdev, vdev->fname, vdev->file);
 	vdev->file = 0;
 	return_error(gs_error_VMerror);
     }

Modified: branches/mtrender/src/gsalphac.c
===================================================================
--- branches/mtrender/src/gsalphac.c	2008-04-10 23:43:36 UTC (rev 8635)
+++ branches/mtrender/src/gsalphac.c	2008-04-14 02:28:08 UTC (rev 8636)
@@ -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: branches/mtrender/src/gscdef.c
===================================================================
--- branches/mtrender/src/gscdef.c	2008-04-10 23:43:36 UTC (rev 8635)
+++ branches/mtrender/src/gscdef.c	2008-04-14 02:28:08 UTC (rev 8636)
@@ -43,7 +43,7 @@
 
 #ifndef GS_PRODUCT
 #  define GS_PRODUCT\
-	GS_PRODUCTFAMILY
+	GS_PRODUCTFAMILY " SVN PRE-RELEASE"
 #endif
 const char *const gs_product = GS_PRODUCT;
 

Modified: branches/mtrender/src/gsdevice.c
===================================================================
--- branches/mtrender/src/gsdevice.c	2008-04-10 23:43:36 UTC (rev 8635)
+++ branches/mtrender/src/gsdevice.c	2008-04-14 02:28:08 UTC (rev 8636)
@@ -895,6 +895,8 @@
 	*pfile = dev->memory->gs_lib_ctx->fstdout;
 	/* Force stdout to binary. */
 	return gp_setmode_binary(*pfile, true);
+    } else if (parsed.iodev && !strcmp(parsed.iodev->dname, "%pipe%")) {
+	positionable = false;
     }
     if (fmt) {						/* filename includes "%nnd" */
 	long count1 = dev->PageCount + 1;

Modified: branches/mtrender/src/gsovrc.c
===================================================================
--- branches/mtrender/src/gsovrc.c	2008-04-10 23:43:36 UTC (rev 8635)
+++ branches/mtrender/src/gsovrc.c	2008-04-14 02:28:08 UTC (rev 8636)
@@ -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: branches/mtrender/src/gsptype1.c
===================================================================
--- branches/mtrender/src/gsptype1.c	2008-04-10 23:43:36 UTC (rev 8635)
+++ branches/mtrender/src/gsptype1.c	2008-04-14 02:28:08 UTC (rev 8636)
@@ -1032,7 +1032,7 @@
     if (pdevc->ccolor_valid) {
 	psdc->colors.pattern.id = pdevc->ccolor.pattern->pattern_id;
 	psdc->colors.pattern.phase = pdevc->phase;
-    } {
+    } else {
 	/* The client color has been changed to a non-pattern color,
 	   but device color has not been created yet. 
 	 */

Modified: branches/mtrender/src/gstparam.h
===================================================================
--- branches/mtrender/src/gstparam.h	2008-04-10 23:43:36 UTC (rev 8635)
+++ branches/mtrender/src/gstparam.h	2008-04-14 02:28:08 UTC (rev 8636)
@@ -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: branches/mtrender/src/gstrans.c
===================================================================
--- branches/mtrender/src/gstrans.c	2008-04-10 23:43:36 UTC (rev 8635)
+++ branches/mtrender/src/gstrans.c	2008-04-14 02:28:08 UTC (rev 8636)
@@ -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: branches/mtrender/src/gstrans.h
===================================================================
--- branches/mtrender/src/gstrans.h	2008-04-10 23:43:36 UTC (rev 8635)
+++ branches/mtrender/src/gstrans.h	2008-04-14 02:28:08 UTC (rev 8636)
@@ -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: branches/mtrender/src/gstype42.c
===================================================================
--- branches/mtrender/src/gstype42.c	2008-04-10 23:43:36 UTC (rev 8635)
+++ branches/mtrender/src/gstype42.c	2008-04-14 02:28:08 UTC (rev 8636)
@@ -223,6 +223,8 @@
 	} else if (!memcmp(tab, "vmtx", 4)) {
 	    pfont->data.metrics[1].offset = offset;
 	    pfont->data.metrics[1].length = (uint)u32(tab + 12);
+	} else if (!memcmp(tab, "OS/2", 4)) {
+	    pfont->data.os2_offset = offset;
 	}
     }
     loca_size >>= pfont->data.indexToLocFormat + 1;
@@ -1294,6 +1296,16 @@
     gs_font_type42 *pfont = (gs_font_type42 *)font;
     int code;
 
+    if (!(info->members & FONT_INFO_EMBEDDING_RIGHTS) && (members & FONT_INFO_EMBEDDING_RIGHTS)) {
+	if(pfont->data.os2_offset != 0) {
+	    int (*string_proc)(gs_font_type42 *, ulong, uint, const byte **) = pfont->data.string_proc;
+	    unsigned char fstype[2];
+
+	    READ_SFNTS(pfont, pfont->data.os2_offset + 8, 2, fstype);
+    	    info->EmbeddingRights = U16(fstype);
+    	    info->members |= FONT_INFO_EMBEDDING_RIGHTS;
+	}
+    }
     if (pfont->data.name_offset == 0)
 	return 0;
     if (!(info->members & FONT_INFO_COPYRIGHT) && (members & FONT_INFO_COPYRIGHT)) {
@@ -1311,6 +1323,7 @@
 	if (code < 0)
 	    return code;
     }
+
     return 0;
 }
 

Modified: branches/mtrender/src/gxcldev.h
===================================================================
--- branches/mtrender/src/gxcldev.h	2008-04-10 23:43:36 UTC (rev 8635)
+++ branches/mtrender/src/gxcldev.h	2008-04-14 02:28:08 UTC (rev 8636)
@@ -722,4 +722,9 @@
 int top_up_offset_map(stream_state * st, const byte *buf, const byte *ptr, const byte *end);
 #endif
 
+int clist_writer_push_no_cropping(gx_device_clist_writer *cdev);
+int clist_writer_push_cropping(gx_device_clist_writer *cdev, int ry, int rheight);
+int clist_writer_pop_cropping(gx_device_clist_writer *cdev);
+int clist_writer_check_empty_cropping_stack(gx_device_clist_writer *cdev);
+
 #endif /* gxcldev_INCLUDED */

Modified: branches/mtrender/src/gxclimag.c
===================================================================
--- branches/mtrender/src/gxclimag.c	2008-04-10 23:43:36 UTC (rev 8635)
+++ branches/mtrender/src/gxclimag.c	2008-04-14 02:28:08 UTC (rev 8636)
@@ -81,7 +81,9 @@
     if (depth > 1 && (cdev->disable_mask & clist_disable_copy_alpha) != 0)
 	return_error(gs_error_unknownerror);
 
-    fit_copy(dev, data, data_x, raster, id, rx, ry, rwidth, rheight);
+    crop_copy(cdev, data, data_x, raster, id, rx, ry, rwidth, rheight);
+    if (rwidth <= 0 || rheight <= 0)
+	return 0;
     y0 = ry;			/* must do after fit_copy */
 
     /* If non-trivial clipping & complex clipping disabled, default */
@@ -854,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)
@@ -868,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: branches/mtrender/src/gxclist.c
===================================================================
--- branches/mtrender/src/gxclist.c	2008-04-10 23:43:36 UTC (rev 8635)
+++ branches/mtrender/src/gxclist.c	2008-04-14 02:28:08 UTC (rev 8636)
@@ -45,6 +45,7 @@
         case 1: return ENUM_OBJ((cdev->writer.image_enum_id != gs_no_id ?
                      cdev->writer.color_space.space : 0));
 	case 2: return ENUM_OBJ(cdev->writer.pinst);
+ 	case 3: return ENUM_OBJ(cdev->writer.cropping_stack);
         default:
         return ENUM_USING(st_imager_state, &cdev->writer.imager_state,
                   sizeof(gs_imager_state), index - 3);
@@ -75,6 +76,7 @@
 	    RELOC_VAR(cdev->writer.color_space.space);
         }
 	RELOC_VAR(cdev->writer.pinst);
+ 	RELOC_VAR(cdev->writer.cropping_stack);
         RELOC_USING(st_imager_state, &cdev->writer.imager_state,
             sizeof(gs_imager_state));
     } else {
@@ -87,9 +89,10 @@
     }
 } RELOC_PTRS_END
 public_st_device_clist();
+private_st_clist_writer_cropping_buffer();
 
 /* Forward declarations of driver procedures */
-static dev_proc_open_device(clist_open);
+dev_proc_open_device(clist_open);
 static dev_proc_output_page(clist_output_page);
 static dev_proc_close_device(clist_close);
 static dev_proc_get_band(clist_get_band);
@@ -464,7 +467,12 @@
     cdev->undercolor_removal_id = gs_no_id;
     cdev->device_halftone_id = gs_no_id;
     cdev->image_enum_id = gs_no_id;
-    cdev->cropping_by_path = false;
+    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;
 }
 /*
@@ -613,7 +621,7 @@
 
 /* Open the device by initializing the device state and opening the */
 /* scratch files. */
-static int
+int
 clist_open(gx_device *dev)
 {
     gx_device_clist_writer * const cdev =
@@ -904,3 +912,63 @@
 #endif
     }
 }
+
+int 
+clist_writer_push_no_cropping(gx_device_clist_writer *cdev)
+{
+    clist_writer_cropping_buffer_t *buf = gs_alloc_struct(cdev->memory, 
+		clist_writer_cropping_buffer_t,
+		&st_clist_writer_cropping_buffer, "clist_writer_transparency_push");
+
+    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;
+}
+
+int 
+clist_writer_push_cropping(gx_device_clist_writer *cdev, int ry, int rheight)
+{
+    int code = clist_writer_push_no_cropping(cdev);
+    
+    if (code < 0)
+	return 0;
+    cdev->cropping_min = max(cdev->cropping_min, ry);
+    cdev->cropping_max = min(cdev->cropping_max, ry + rheight);
+    return 0;
+}
+
+int 
+clist_writer_pop_cropping(gx_device_clist_writer *cdev)
+{
+    clist_writer_cropping_buffer_t *buf = cdev->cropping_stack;
+
+    if (buf == NULL)
+	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;
+}
+
+int 
+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: branches/mtrender/src/gxclist.h
===================================================================
--- branches/mtrender/src/gxclist.h	2008-04-10 23:43:36 UTC (rev 8635)
+++ branches/mtrender/src/gxclist.h	2008-04-14 02:28:08 UTC (rev 8636)
@@ -198,13 +198,29 @@
 /* (Strokes with longer patterns are converted to fills.) */
 #define cmd_max_dash 11
 
+/* Define a clist cropping buffer, 
+   which represents a cropping stack element while clist writing. */
+typedef struct clist_writer_cropping_buffer_s clist_writer_cropping_buffer_t;
+
+struct clist_writer_cropping_buffer_s {
+    int cropping_min, cropping_max;
+    uint mask_id, temp_mask_id;
+    clist_writer_cropping_buffer_t *next;
+};
+
+#define private_st_clist_writer_cropping_buffer()\
+  gs_private_st_ptrs1(st_clist_writer_cropping_buffer,\
+		clist_writer_cropping_buffer_t, "clist_writer_transparency_buffer",\
+		clist_writer_cropping_buffer_enum_ptrs, clist_writer_cropping_buffer_reloc_ptrs, next)
+
+
 /* Define the state of a band list when writing. */
 typedef struct clist_color_space_s {
     byte byte1;			/* see cmd_opv_set_color_space in gxclpath.h */
     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 */
@@ -249,10 +265,19 @@
     proc_free_up_bandlist_memory((*free_up_bandlist_memory)); /* if nz, proc to free some bandlist memory */
     int disable_mask;		/* mask of routines to disable clist_disable_xxx */
     gs_pattern1_instance_t *pinst; /* Used when it is a pattern clist. */
-    bool cropping_by_path;
     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;
-} 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)
@@ -302,7 +327,7 @@
     "gx_device_clist", 0, device_clist_enum_ptrs, device_clist_reloc_ptrs,\
     gx_device_finalize)
 #define st_device_clist_max_ptrs\
-  (st_device_forward_max_ptrs + st_imager_state_num_ptrs + 3)
+  (st_device_forward_max_ptrs + st_imager_state_num_ptrs + 4)
 
 #define CLIST_IS_WRITER(cdev) ((cdev)->common.ymin < 0)
 
@@ -429,4 +454,53 @@
 #define clist_debug_set_ctm (void)
 #endif
 
+/* Cropping by Y is necessary when the shading path is smaller than shading.
+   In this case the clipping path is written into the path's bands only.
+   Thus bands outside the shading path are not clipped,
+   but the shading may paint into them, so use this macro to crop them.
+
+   Besides that, cropping by Y is necessary when a transparency compositor
+   is installed over clist writer. Transparency compositors change the number
+   of device color components, so transparency group's elements
+   must not paint to bands that are not covered by the transparency bbox
+   to prevent a failure when clist reader recieves a wrong number of color components.
+ */
+#define crop_fill_y(cdev, ry, rheight)\
+    BEGIN\
+	if (ry < cdev->cropping_min) {\
+	    rheight = ry + rheight - cdev->cropping_min;\
+	    ry = cdev->cropping_min;\
+	}\
+	if (ry + rheight > cdev->cropping_max)\
+	    rheight = cdev->cropping_max - ry;\
+    END
+
+#define crop_fill(dev, x, y, w, h)\
+    BEGIN\
+	if ( x < 0 )\
+	    w += x, x = 0;\
+	fit_fill_w(dev, x, w);\
+	crop_fill_y(dev, y, h);\
+    END
+
+#define crop_copy_y(cdev, data, data_x, raster, id, ry, rheight)\
+    BEGIN\
+	if (ry < cdev->cropping_min) {\
+	    rheight = ry + rheight - cdev->cropping_min;\
+	    data += (cdev->cropping_min - ry) * raster;\
+	    id = gx_no_bitmap_id;\
+	    ry = cdev->cropping_min;\
+	}\
+	if (ry + rheight > cdev->cropping_max)\
+	    rheight = cdev->cropping_max - ry;\
+    END
+
+#define crop_copy(dev, data, data_x, raster, id, x, y, w, h)\
+    BEGIN\
+	if ( x < 0 )\
+	    w += x, data_x -= x, x = 0;\
+	fit_fill_w(dev, x, w);\
+	crop_copy_y(dev, data, data_x, raster, id, y, h);\
+    END
+
 #endif /* gxclist_INCLUDED */

Modified: branches/mtrender/src/gxclpath.c
===================================================================
--- branches/mtrender/src/gxclpath.c	2008-04-10 23:43:36 UTC (rev 8635)
+++ branches/mtrender/src/gxclpath.c	2008-04-14 02:28:08 UTC (rev 8636)
@@ -602,7 +602,10 @@
 	   See comment below about pdcolor == NULL.
 	 */
 	code = gx_default_fill_path(dev, pis, ppath, params, pdcolor, pcpath);
-	cdev->cropping_by_path = false;
+	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) ||
@@ -624,8 +627,7 @@
 	}
 	ry = fixed2int(bbox.p.y) - 1;
 	rheight = fixed2int_ceiling(bbox.q.y) - ry + 1;
-	fit_fill_y(dev, ry, rheight);
-	fit_fill_h(dev, ry, rheight);
+	crop_fill_y(cdev, ry, rheight);
 	if (rheight <= 0)
 	    return 0;
     }
@@ -642,10 +644,13 @@
 	   Put the clipping path only.
 	   The graphics library will call us again with subdividing 
 	   the shading into trapezoids and rectangles. 
-	   Note cropping_by_path is true during such calls. */
-	cdev->cropping_by_path = true;
-	cdev->cropping_min = ry;
-	cdev->cropping_max = ry + rheight;
+	   Narrow cropping_min, croping_max for such calls. */
+	cdev->save_cropping_min = cdev->cropping_min;
+	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: branches/mtrender/src/gxclrast.c
===================================================================
--- branches/mtrender/src/gxclrast.c	2008-04-10 23:43:36 UTC (rev 8635)
+++ branches/mtrender/src/gxclrast.c	2008-04-14 02:28:08 UTC (rev 8636)
@@ -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: branches/mtrender/src/gxclrect.c
===================================================================
--- branches/mtrender/src/gxclrect.c	2008-04-10 23:43:36 UTC (rev 8635)
+++ branches/mtrender/src/gxclrect.c	2008-04-14 02:28:08 UTC (rev 8636)
@@ -244,7 +244,9 @@
     int code;
     cmd_rects_enum_t re;
 
-    fit_fill(dev, rx, ry, rwidth, rheight);
+    crop_fill(cdev, rx, ry, rwidth, rheight);
+    if (rwidth <= 0 || rheight <= 0)
+	return 0;
     if (cdev->permanent_error < 0)
       return (cdev->permanent_error);
     RECT_ENUM_INIT(re, ry, rheight);
@@ -310,22 +312,8 @@
 	    rheight = fixed2int_ceiling(ytop) - ry;
 	}
     }
-    if (cdev->cropping_by_path) {
-	/* Cropping by Y is necessary when the shading path is smaller than shading.
-	   In this case the clipping path is written into the path's bands only.
-	   Thus bands outside the shading path are not clipped,
-	   but the shading may paint into them, so crop them here.
-	 */
-	if (ry < cdev->cropping_min) {
-	    rheight = ry + rheight - cdev->cropping_min;
-	    ry = cdev->cropping_min;
-	}
-	if (ry + rheight > cdev->cropping_max)
-	    rheight = cdev->cropping_max - ry;
-    }
-    fit_fill_y(dev, ry, rheight);
-    fit_fill_h(dev, ry, rheight);
-    if (rheight < 0)
+    crop_fill_y(cdev, ry, rheight);
+    if (rheight <= 0)
 	return 0;
     if (cdev->permanent_error < 0)
 	return (cdev->permanent_error);
@@ -464,7 +452,9 @@
     int code;
     cmd_rects_enum_t re;
 
-    fit_fill(dev, rx, ry, rwidth, rheight);
+    crop_fill(cdev, rx, ry, rwidth, rheight);
+    if (rwidth <= 0 || rheight <= 0)
+	return 0;
     if (cdev->permanent_error < 0)
       return (cdev->permanent_error);
     RECT_ENUM_INIT(re, ry, rheight);
@@ -916,10 +906,12 @@
     cmd_rects_enum_t re;
 
     if (scolors != 0 && scolors[0] != scolors[1]) {
-	fit_fill(dev, rx, ry, rwidth, rheight);
+	crop_fill(cdev, rx, ry, rwidth, rheight);
     } else {
-	fit_copy(dev, sdata, sourcex, sraster, id, rx, ry, rwidth, rheight);
+	crop_copy(cdev, sdata, sourcex, sraster, id, rx, ry, rwidth, rheight);
     }
+    if (rwidth <= 0 || rheight <= 0)
+	return 0;
     /*
      * On CMYK devices, RasterOps must be executed with complete pixels
      * if the operation involves the destination.
@@ -989,6 +981,9 @@
 			uint rep_height = tiles->rep_height;
 			gs_id ids;
 			gx_strip_bitmap line_tile;
+			int data_shift = 0, phase_shift = 0, raster;
+			int new_phase = phase_x;
+			int tile_space_phase;
 			int iy;
 
 			if (rep_height == 1 ||
@@ -1004,16 +999,45 @@
 			line_tile = *tiles;
 			line_tile.size.y = 1;
 			line_tile.rep_height = 1;
+			raster = line_tile.raster;
+			/* The rasterizer assumes tile phase relatively to the rectangle origin,
+			   (see x_offset in gdevmr8n.c), so compute "the tile phase in the tile space" 
+			   with same expression : */
+			tile_space_phase = (rx + phase_x) % tiles->rep_width;
+			if (tile_space_phase + rwidth <= tiles->rep_width) {
+			    /* Narrow the tile to prevent buffer overflow - bug 689588.
+			       Note currently we don't narrow "wrapped" tiles (because bug 689588 doesn't need) :
+			       when tile_space_phase < rep_width && tile_space_phase + rwidth > rep_width, 
+			       each line to be converted into 2 ones.
+			    */
+			    int depth = dev->color_info.depth;
+
+#			    if 0
+			    /* Align bitmap data : */
+   			    data_shift = ((tile_space_phase * depth) >> (log2_align_bitmap_mod + 3)) << log2_align_bitmap_mod;
+#			    else
+   			    data_shift = tile_space_phase * depth / 8; /* No bitmap data alignment because we'll only write it to clist.  */
+#			    endif
+			    phase_shift = data_shift * 8 / depth;
+			    line_tile.rep_width = rwidth + (tile_space_phase - phase_shift);
+			    /* Normally line_tile.raster must account trailing row alignment bytes and 
+			       to be computed as bitmap_raster(line_tile.rep_width * depth); 
+			       but we can't apply it here because the trailing alignment bytes may be absent
+			       due to data_shift. We believe it is not harmful because we just write the data to clist,
+			       and because the bitmap height is 1.
+			       The clist reader must provide the trailing bytes if the rasterizer needs them.
+			     */
+			    line_tile.raster = (line_tile.rep_width * depth + 7) / 8; 
+			    line_tile.size.x = line_tile.rep_width;
+			    line_tile.shift = 0;
+			    new_phase = (tile_space_phase - phase_shift - rx % line_tile.rep_width);
+			    /* Provide a positive phase for clist reader : */
+			    new_phase = (new_phase + line_tile.rep_width) % line_tile.rep_width;
+			}
 			for (iy = 0; iy < re.height; ++iy) {
-			    line_tile.data = tiles->data + line_tile.raster *
-				((re.y + iy + phase_y) % rep_height);
+			    line_tile.data = tiles->data + raster *
+				((re.y + iy + phase_y) % rep_height) + data_shift;
 			    line_tile.id = ids + (iy % rep_height);
-			    /*
-			     * Note that since we're only transferring
-			     * a single scan line, phase_y is irrelevant;
-			     * we may as well use the current tile phase
-			     * so we don't have to write extra commands.
-			     */
 			    ++cdev->driver_call_nesting;
 			    {
 				code = clist_strip_copy_rop(dev,
@@ -1022,7 +1046,7 @@
 					gx_no_bitmap_id, scolors,
 					&line_tile, tcolors,
 					rx, re.y + iy, rwidth, 1,
-					phase_x, re.pcls->tile_phase.y, lop);
+					new_phase, 0, lop);
 			    } 
 			    --cdev->driver_call_nesting;
 			    if (code < 0 && SET_BAND_CODE(code))
@@ -1030,9 +1054,8 @@
 			}
 			continue;
 		    }
-		    if (phase_x != re.pcls->tile_phase.x ||
-			phase_y != re.pcls->tile_phase.y
-			) {
+		    if (((phase_x != re.pcls->tile_phase.x) && (tiles->rep_width > 1)) ||
+			((phase_y != re.pcls->tile_phase.y) && (tiles->rep_height > 1))) {
 			do {
 			    code = cmd_set_tile_phase(cdev, re.pcls, phase_x,
 						      phase_y);

Modified: branches/mtrender/src/gxcomp.h
===================================================================
--- branches/mtrender/src/gxcomp.h	2008-04-10 23:43:36 UTC (rev 8635)
+++ branches/mtrender/src/gxcomp.h	2008-04-14 02:28:08 UTC (rev 8636)
@@ -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

Modified: branches/mtrender/src/gxfill.c
===================================================================
--- branches/mtrender/src/gxfill.c	2008-04-10 23:43:36 UTC (rev 8635)
+++ branches/mtrender/src/gxfill.c	2008-04-14 02:28:08 UTC (rev 8636)
@@ -614,6 +614,7 @@
 	    else
 		(*dev_proc(pdev, get_clipping_box)) (pdev, &clip_box);
 	    rect_intersect(clip_box, shading_rect);
+	    gx_cpath_init_local(&cpath_intersection, pdev->memory);
 	    code = gx_cpath_from_rectangle(&cpath_intersection, &clip_box);
 	} else if (pcpath != NULL) {
 	    /* either *pcpath is not a rectangle, or shading cell is not a rectangle.  */

Modified: branches/mtrender/src/gxfont.h
===================================================================
--- branches/mtrender/src/gxfont.h	2008-04-10 23:43:36 UTC (rev 8635)
+++ branches/mtrender/src/gxfont.h	2008-04-14 02:28:08 UTC (rev 8636)
@@ -108,7 +108,8 @@
     gs_const_string FamilyName;
 #define FONT_INFO_FULL_NAME 0x2000
     gs_const_string FullName;
-
+#define FONT_INFO_EMBEDDING_RIGHTS 0x4000
+    int EmbeddingRights;
 } gs_font_info_t;
 
 #define public_st_gs_font_info() /* in gsfont.c */\

Modified: branches/mtrender/src/gxfont42.h
===================================================================
--- branches/mtrender/src/gxfont42.h	2008-04-10 23:43:36 UTC (rev 8635)
+++ branches/mtrender/src/gxfont42.h	2008-04-14 02:28:08 UTC (rev 8636)
@@ -85,6 +85,7 @@
     gs_type42_mtx_t metrics[2];	/* hhea/hmtx, vhea/vmtx (indexed by WMode) */
     ulong loca;			/* offset to loca table */
     ulong name_offset;		/* offset to name table */		
+    ulong os2_offset;		/* offset to OS/2 table */		
     /*
      * TrueType fonts specify the number of glyphs in two different ways:
      * the size of the loca table, and an explicit value in maxp.  Currently

Modified: branches/mtrender/src/gxpcmap.c
===================================================================
--- branches/mtrender/src/gxpcmap.c	2008-04-10 23:43:36 UTC (rev 8635)
+++ branches/mtrender/src/gxpcmap.c	2008-04-14 02:28:08 UTC (rev 8636)
@@ -173,7 +173,7 @@
 {
 }
 
-#define MAX_BITMAP_PATTERN_SIZE (1024*1024)
+#define MAX_BITMAP_PATTERN_SIZE (20*1024*1024)
 
 /* Allocate a pattern accumulator, with an initial refct of 0. */
 gx_device_forward *

Modified: branches/mtrender/src/siscale.c
===================================================================
--- branches/mtrender/src/siscale.c	2008-04-10 23:43:36 UTC (rev 8635)
+++ branches/mtrender/src/siscale.c	2008-04-14 02:28:08 UTC (rev 8636)
@@ -376,21 +376,7 @@
     if (sizeofPixelOut == 1) {
 	zoom_y_loop(byte)
     } else {			/* sizeofPixelOut == 2 */
-	/* zoom_y_loop(bits16) */
-	for ( kc = 0; kc < kn; ++kc ) {
-		AccumTmp weight = 0;
-		{ const PixelTmp *pp = &tmp[kc + first_pixel];
-		  int j = cn;
-		  const CONTRIB *cp = cbp;
-		  for ( ; j > 0; pp += kn, ++cp, --j )
-		    weight += *pp * cp->weight;
-		}
-		{ PixelTmp2 pixel = unscale_AccumTmp(weight, fraction_bits);
-		  if_debug1('W', " %lx", (long)pixel);
-		  ((bits16 *)dst)[kc] =
-		    (bits16)CLAMP(pixel, 0, max_weight);
-		}
-	}
+	zoom_y_loop(bits16)
     }
     if_debug0('W', "\n");
 }

Modified: branches/mtrender/src/sjbig2_luratech.c
===================================================================
--- branches/mtrender/src/sjbig2_luratech.c	2008-04-10 23:43:36 UTC (rev 8635)
+++ branches/mtrender/src/sjbig2_luratech.c	2008-04-14 02:28:08 UTC (rev 8636)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2006 Artifex Software, Inc.
+/* Copyright (C) 2001-2008 Artifex Software, Inc.
    All Rights Reserved.
   
    This software is provided AS-IS with no warranty, either express or
@@ -94,23 +94,22 @@
 
 /* store a global ctx pointer in our state structure */
 int
-s_jbig2decode_set_global_data(stream_state *ss, s_jbig2_global_data_t *gs)
+s_jbig2decode_set_global_data(stream_state *ss, s_jbig2_global_data_t *gd)
 {
     stream_jbig2decode_state *state = (stream_jbig2decode_state*)ss;
     if (state == NULL)
         return gs_error_VMerror;
     
-    state->global_struct = gs;
-    if (gs != NULL) {
-        s_jbig2decode_global_data *global = (s_jbig2decode_global_data*)(gs->data);
-
+    state->global_struct = gd;
+    if (gd != NULL) {
+        s_jbig2decode_global_data *global = (s_jbig2decode_global_data*)(gd->data);
         state->global_data = global->data;
         state->global_size = global->size;
     } else {
         state->global_data = NULL;
         state->global_size = 0;
     }
-    return gs_error_VMerror;
+    return 0;
 }
 
 /* invert the bits in a buffer */

Modified: branches/mtrender/src/zchar1.c
===================================================================
--- branches/mtrender/src/zchar1.c	2008-04-10 23:43:36 UTC (rev 8635)
+++ branches/mtrender/src/zchar1.c	2008-04-14 02:28:08 UTC (rev 8636)
@@ -289,12 +289,22 @@
 	 * create the path twice, since we can't know the
 	 * oversampling factor until after setcachedevice.
 	 */
-	if (cxs.present == metricsSideBearingAndWidth) {
-	    gs_point sbpt;
+	switch (cxs.present) {
+            case metricsSideBearingAndWidth: { 
+                gs_point pt;
 
-	    sbpt.x = cxs.sbw[0], sbpt.y = cxs.sbw[1];
-	    gs_type1_set_lsb(pcis, &sbpt);
-	}
+	        pt.x = cxs.sbw[0], pt.y = cxs.sbw[1];
+	        gs_type1_set_lsb(pcis, &pt);
+            }
+            /* fall through */
+            case metricsWidthOnly: {
+                gs_point pt;
+
+	        pt.x = cxs.sbw[2], pt.y = cxs.sbw[3];
+                gs_type1_set_width(pcis, &pt);
+            }
+        }
+
 	/* Continue interpreting. */
       icont:
 	code = type1_continue_dispatch(i_ctx_p, &cxs, opstr, &other_subr, 4);
@@ -308,9 +318,16 @@
 		return type1_call_OtherSubr(i_ctx_p, &cxs, nobbox_continue,
 					    &other_subr);
 	    case type1_result_sbw:	/* [h]sbw, just continue */
-		if (cxs.present != metricsSideBearingAndWidth)
-		    type1_cis_get_metrics(pcis, cxs.sbw);
-		opstr = 0;
+                switch (cxs.present) {
+                    case metricsNone:
+                        cxs.sbw[0] = fixed2float(pcis->lsb.x);
+                        cxs.sbw[1] = fixed2float(pcis->lsb.y);
+                    /* fall through */
+                    case metricsWidthOnly:
+                        cxs.sbw[2] = fixed2float(pcis->width.x);
+                        cxs.sbw[3] = fixed2float(pcis->width.y);
+                }
+                opstr = 0;
 		goto icont;
 	}
     }

Modified: branches/mtrender/src/zfont.c
===================================================================
--- branches/mtrender/src/zfont.c	2008-04-10 23:43:36 UTC (rev 8635)
+++ branches/mtrender/src/zfont.c	2008-04-14 02:28:08 UTC (rev 8636)
@@ -589,7 +589,7 @@
 		      FONT_INFO_FAMILY_NAME | FONT_INFO_FULL_NAME),
 				    info);
     const ref *pfdict;
-    ref *pfontinfo;
+    ref *pfontinfo, *pvalue;
 
     if (code < 0)
 	return code;
@@ -609,6 +609,11 @@
     if ((members & FONT_INFO_FULL_NAME) &&
 	zfont_info_has(pfontinfo, "FullName", &info->FullName))
 	info->members |= FONT_INFO_FULL_NAME;
+    if ((members & FONT_INFO_EMBEDDING_RIGHTS) 
+	&& (dict_find_string(pfontinfo, "FSType", &pvalue) > 0)) {
+	info->EmbeddingRights = pvalue->value.intval;
+	info->members |= FONT_INFO_EMBEDDING_RIGHTS;
+    }
     return code;
 }
 



More information about the gs-cvs mailing list