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

leonardo at ghostscript.com leonardo at ghostscript.com
Wed Jul 11 14:17:42 PDT 2007


Author: leonardo
Date: 2007-07-11 14:17:39 -0700 (Wed, 11 Jul 2007)
New Revision: 8118

Modified:
   trunk/gs/src/gdevnfwd.c
   trunk/gs/src/gxcldev.h
   trunk/gs/src/gxclist.c
   trunk/gs/src/gxclist.h
   trunk/gs/src/gxclpath.c
   trunk/gs/src/gxclrast.c
   trunk/gs/src/gxclread.c
   trunk/gs/src/gxclrect.c
   trunk/gs/src/gxdevcli.h
   trunk/gs/src/gxfill.c
   trunk/gs/src/gxshade1.c
   trunk/gs/src/gxshade4.h
   trunk/gs/src/gxshade6.c
   trunk/gs/src/lib.mak
Log:
Banding : Exten\d clist language with trapezoids, linear color trapezoids and linear color triangles.

DETAILS :

This fixes the clist expansion problem for shadings.

1. New functions clist_fill_linear_color_trapezoid, clist_fill_linear_color_triangle
   provide the writing of shading parts into clist
   without a further decomposition into rectangles.

2. gxclrast.c is enhanced with reading the data from 1.

3. gxfill.c needs a special interaction with the clipper device
   for passing the clipping path as a high level object.
   The new request pattern_manage__handles_clip_path
   checks whether the target device can handle a clipping path.
   The clist writer can, so the graphics library first sends the
   clipping path, and then decomposes the shading into
   trapezoids without installing a clipper device.
   Doing so because clipper device can't handle trapezoids.
   See comments in gxclpath.c, gxfill.c .

4. The clist reader installs a clipper device when processes
   trapezoids and linear color triangles. 
   The new flag clipper_dev_open controls that.

5. A new flag gx_device_clist_writer_s::cropping_by_path 
   controls an additional cropping of shading components,
   which fall outside the shading path's bands.
   See comment in gxclpath.c .

6. R_fill_rect_with_const_color is rewritten with linear color functions,
   because the old implementation creates a rectangle, which is not clipped with
   4,5. It gives an invisible slowdown for unbanded rasters.

There are few things, which need further improvements :

1. A better compression for frac31 values in clist. 
   Such values usually have many zeros in ending bits.

2. Crop bands with ybot, ytop, fa->ystart, fa->yend in
   clist_write_fill_trapezoid.

3. The clist reader must handle cases when linear color functions return 0.
   It must perform a decomposition of areas with calling
   appropriate parts of gxshade6.c . The current code returns error,
   which does not happen in practice.
  
EXPECTED DIFFERENCES :

There is a problem with pkmraw -r300 Bug689189.pdf
which has to be fixed separately.

This patch causes a minor raster difference with shadings :
with a banded rendering the shading area becomes some smaller
than the old banded rendering. It needs a further analyzis.
Here is a list of files with this problem :

"442-01.ps" 
"446-01-fixed.ps" 
"464-01-fixed.ps" 
"470-01.ps" 
"478-01.ps" 
"483-01.ps" 
"483-05-fixed.ps" 
"Altona-Testsuite_p2_S_x3.pdf" 
"Altona_Visual_bb_1v1_x3.pdf" 
"Altona_Visual_sb_1v1_x3.pdf" 
"BEST8-99-Path.fh7.pdf" 
"Bug689189.pdf" 
"chilis_black.pdf" 
"chilis_red.pdf" 
"Clarke Tate Manns Chinese.ai" 
"gradmesh.ai" 
"Openhuis_pdf_zw.pdf" 
"S2_Digitalproof-Forum_x3k.pdf" 
"self-intersect2.ps" 
"shading_prob_800.ps" 
"SmoothShading.pdf" 
"STEUER-RollingMesh 1(linear).ai" 
"STEUER-RollingMesh 2(radial).ai" 
"STEUER-RollingMesh 3(Final).ai" 
"Testform.v1.0.2.pdf" 

This list may be related to bug 689338.


Modified: trunk/gs/src/gdevnfwd.c
===================================================================
--- trunk/gs/src/gdevnfwd.c	2007-07-11 00:26:24 UTC (rev 8117)
+++ trunk/gs/src/gdevnfwd.c	2007-07-11 21:17:39 UTC (rev 8118)
@@ -757,8 +757,13 @@
 		return 1;
 	}
 	return 0;
-    } else
+    } else {
+	if (function == pattern_manage__handles_clip_path) {
+	    if (dev->procs.fill_path == gx_default_fill_path)
+		return 0;
+	}
 	return dev_proc(tdev, pattern_manage)(tdev, id, pinst, function);
+    }
 }
 
 int

Modified: trunk/gs/src/gxcldev.h
===================================================================
--- trunk/gs/src/gxcldev.h	2007-07-11 00:26:24 UTC (rev 8117)
+++ trunk/gs/src/gxcldev.h	2007-07-11 21:17:39 UTC (rev 8118)
@@ -283,6 +283,9 @@
 dev_proc_strip_tile_rectangle(clist_strip_tile_rectangle);
 dev_proc_strip_copy_rop(clist_strip_copy_rop);
 dev_proc_fill_trapezoid(clist_fill_trapezoid);
+dev_proc_fill_linear_color_trapezoid(clist_fill_linear_color_trapezoid);
+dev_proc_fill_linear_color_triangle(clist_fill_linear_color_triangle);
+dev_proc_pattern_manage(clist_pattern_manage);
 
 /* In gxclimag.c */
 dev_proc_fill_mask(clist_fill_mask);

Modified: trunk/gs/src/gxclist.c
===================================================================
--- trunk/gs/src/gxclist.c	2007-07-11 00:26:24 UTC (rev 8117)
+++ trunk/gs/src/gxclist.c	2007-07-11 21:17:39 UTC (rev 8118)
@@ -150,12 +150,12 @@
     gx_forward_get_color_comp_index,
     gx_forward_encode_color,
     gx_forward_decode_color,
-    gx_default_pattern_manage,
+    clist_pattern_manage,
     gx_default_fill_rectangle_hl_color,
     gx_default_include_color_space,
     gx_default_fill_linear_color_scanline,
-    gx_default_fill_linear_color_trapezoid, /* fixme : write to clist. */
-    gx_default_fill_linear_color_triangle,
+    clist_fill_linear_color_trapezoid,
+    clist_fill_linear_color_triangle,
     gx_forward_update_spot_equivalent_colors,
     gx_forward_ret_devn_params
 };
@@ -457,6 +457,7 @@
     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;
     return 0;
 }
 /*

Modified: trunk/gs/src/gxclist.h
===================================================================
--- trunk/gs/src/gxclist.h	2007-07-11 00:26:24 UTC (rev 8117)
+++ trunk/gs/src/gxclist.h	2007-07-11 21:17:39 UTC (rev 8118)
@@ -248,6 +248,8 @@
 	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;
 } gx_device_clist_writer;
 
 /* Bits for gx_device_clist_writer.disable_mask. Bit set disables behavior */

Modified: trunk/gs/src/gxclpath.c
===================================================================
--- trunk/gs/src/gxclpath.c	2007-07-11 00:26:24 UTC (rev 8117)
+++ trunk/gs/src/gxclpath.c	2007-07-11 21:17:39 UTC (rev 8118)
@@ -577,7 +577,21 @@
     gs_fixed_point adjust;
     bool slow_rop = cmd_slow_rop(dev, lop_know_S_0(lop), pdcolor);
     cmd_rects_enum_t re;
+    int code;
 
+    if (pdcolor != NULL && gx_dc_is_pattern2_color(pdcolor)) {
+	/* Here we need to intersect *ppath, *pcpath and shading bbox.
+	   Call the default implementation, which has a special
+	   branch for processing a shading fill with the clip writer device.
+	   It will call us back with pdcolor=NULL for passing
+	   the intersected clipping path, 
+	   and then will decompose the shading into trapezoids.
+	   See comment below about pdcolor == NULL.
+	 */
+	code = gx_default_fill_path(dev, pis, ppath, params, pdcolor, pcpath);
+	cdev->cropping_by_path = false;
+	return code;
+    }
     if ( (cdev->disable_mask & clist_disable_fill_path) ||
 	 gs_debug_c(',')
 	 ) {
@@ -604,35 +618,57 @@
     if (unknown)
 	cmd_clear_known(cdev, unknown);
     if (cdev->permanent_error < 0)
-      return (cdev->permanent_error);
-    RECT_ENUM_INIT(re, ry, rheight);
-    do {
-	int code;
-
-	RECT_STEP_INIT(re);
-	code = cmd_do_write_unknown(cdev, re.pcls, FILL_KNOWN);
-	if (code < 0)
-	    return code;
-	if ((code = cmd_do_enable_clip(cdev, re.pcls, pcpath != NULL)) < 0 ||
-	    (code = cmd_update_lop(cdev, re.pcls, lop)) < 0
-	    )
-	    return code;
-	code = cmd_put_drawing_color(cdev, re.pcls, pdcolor);
-	if (code < 0) {
-	    /* Something went wrong, use the default implementation. */
-	    return gx_default_fill_path(dev, pis, ppath, params, pdcolor,
-					pcpath);
-	}
-	re.pcls->colors_used.slow_rop |= slow_rop;
-	code = cmd_put_path(cdev, re.pcls, ppath,
-			    int2fixed(max(re.y - 1, y0)),
-			    int2fixed(min(re.y + re.height + 1, y1)),
-			    op,
-			    true, sn_none /* fill doesn't need the notes */ );
-	if (code < 0)
-	    return code;
-	re.y += re.height;
-    } while (re.y < re.yend);
+	return (cdev->permanent_error);
+    if (pdcolor == NULL) {
+	/* See comment above about pattern2_color.
+	   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;
+	RECT_ENUM_INIT(re, ry, rheight);
+	do {
+	    RECT_STEP_INIT(re);
+	    if (pcpath != NULL) {
+		code = cmd_do_write_unknown(cdev, re.pcls, clip_path_known);
+		if (code < 0)
+		    return code;
+	    }
+	    code = cmd_do_enable_clip(cdev, re.pcls, pcpath != NULL);
+	    if (code  < 0)
+		return code;
+	    re.y += re.height;
+	} while (re.y < re.yend);
+    } else {
+	RECT_ENUM_INIT(re, ry, rheight);
+	do {
+	    RECT_STEP_INIT(re);
+	    code = cmd_do_write_unknown(cdev, re.pcls, FILL_KNOWN);
+	    if (code < 0)
+		return code;
+	    if ((code = cmd_do_enable_clip(cdev, re.pcls, pcpath != NULL)) < 0 ||
+		(code = cmd_update_lop(cdev, re.pcls, lop)) < 0
+		)
+		return code;
+	    code = cmd_put_drawing_color(cdev, re.pcls, pdcolor);
+	    if (code < 0) {
+		/* Something went wrong, use the default implementation. */
+		return gx_default_fill_path(dev, pis, ppath, params, pdcolor,
+					    pcpath);
+	    }
+	    re.pcls->colors_used.slow_rop |= slow_rop;
+	    code = cmd_put_path(cdev, re.pcls, ppath,
+				int2fixed(max(re.y - 1, y0)),
+				int2fixed(min(re.y + re.height + 1, y1)),
+				op,
+				true, sn_none /* fill doesn't need the notes */ );
+	    if (code < 0)
+		return code;
+	    re.y += re.height;
+	} while (re.y < re.yend);
+    }
     return 0;
 }
 

Modified: trunk/gs/src/gxclrast.c
===================================================================
--- trunk/gs/src/gxclrast.c	2007-07-11 00:26:24 UTC (rev 8117)
+++ trunk/gs/src/gxclrast.c	2007-07-11 21:17:39 UTC (rev 8118)
@@ -90,7 +90,7 @@
     long val = *p++ & 0x7f;
     int shift = 7;
 
-    for (; val += (long)(*p & 0x7f) << shift, *p++ > 0x7f; shift += 7);
+    for (; val |= (long)(*p & 0x7f) << shift, *p++ > 0x7f; shift += 7);
     *rp = p;
     return val;
 }
@@ -291,6 +291,8 @@
     int code = 0;
     ht_buff_t  ht_buff;
     gx_device *const orig_target = target;
+    gx_device_clip clipper_dev;
+    bool clipper_dev_open;
 
     cbuf.data = (byte *)cbuf_storage;
     cbuf.size = cbuf_size;
@@ -306,6 +308,7 @@
     set_colors = state.colors;
     use_clip = false;
     pcpath = NULL;
+    clipper_dev_open = false;
     notes = sn_none;
     data_x = 0;
     {
@@ -944,14 +947,17 @@
 			break;
 		    case cmd_opv_enable_clip:
 			pcpath = (use_clip ? &clip_path : NULL);
+			clipper_dev_open = false;
 			if_debug0('L', "\n");
 			break;
 		    case cmd_opv_disable_clip:
 			pcpath = NULL;
+			clipper_dev_open = false;
 			if_debug0('L', "\n");
 			break;
 		    case cmd_opv_begin_clip:
 			pcpath = NULL;
+			clipper_dev_open = false;
 			in_clip = true;
 			if_debug0('L', "\n");
 			code = gx_cpath_reset(&clip_path);
@@ -991,6 +997,7 @@
 				  cbox.q.y >= target_box.q.y);
 			}
 			pcpath = (use_clip ? &clip_path : NULL);
+			clipper_dev_open = false;
 			state.lop_enabled = clip_save.lop_enabled;
 			imager_state.log_op =
 			    (state.lop_enabled ? state.lop :
@@ -1389,10 +1396,19 @@
 				gx_cmd_rect rl, rr;
 				gs_fixed_edge left, right;
 				fixed ybot, ytop;
-				int swap_axes, wh;
+				int options, swap_axes, wh;
 				fixed x0f;
 				fixed y0f;
+				gx_device *ttdev = tdev;
 
+				if (pcpath != NULL && !clipper_dev_open) {
+				    gx_make_clip_device(&clipper_dev, gx_cpath_list(pcpath)); /* fixme : create a global instance */
+				    clipper_dev.target = tdev;
+				    (*dev_proc(&clipper_dev, open_device))((gx_device *)&clipper_dev);
+				    clipper_dev_open = true;
+				}
+				if (clipper_dev_open)
+				    ttdev = (gx_device *)&clipper_dev;
 				cmd_getw(left.start.x, cbp);
 				cmd_getw(left.start.y, cbp);
 				cmd_getw(left.end.x, cbp);
@@ -1403,7 +1419,8 @@
 				cmd_getw(right.end.y, cbp);
 				cmd_getw(ybot, cbp);
 				cmd_getw(ytop, cbp);
-				cmd_getw(swap_axes, cbp);
+				cmd_getw(options, cbp);
+				swap_axes = options & 1;
 				wh = swap_axes ? tdev->width : tdev->height;
 				x0f = int2fixed(swap_axes ? y0 : x0);
 				y0f = int2fixed(swap_axes ? x0 : y0);
@@ -1415,10 +1432,58 @@
 				right.start.y -= y0f;
 				right.end.x -= x0f;
 				right.end.y -= y0f;
-				code = gx_default_fill_trapezoid(tdev, &left, &right,
-				    max(ybot - y0f, fixed_half), 
-				    min(ytop - y0f, int2fixed(wh)), swap_axes,
-				    &dev_color, imager_state.log_op);
+				if (options & 2) {
+				    int num_components = tdev->color_info.num_components;
+				    frac31 c[4][GX_DEVICE_COLOR_MAX_COMPONENTS], *cc[4];
+				    byte colors_mask, i, j, m = 1;
+				    gs_fill_attributes fa;
+				    gs_fixed_rect clip;
+
+				    if (cbuf.end - cbp < 5 * cmd_max_intsize(sizeof(frac31)))
+					cbp = top_up_cbuf(&cbuf, cbp);
+				    cmd_getw(clip.p.x, cbp);
+				    cmd_getw(clip.p.y, cbp);
+				    cmd_getw(clip.q.x, cbp);
+				    cmd_getw(clip.q.y, cbp);
+				    clip.p.x -= x0f;
+				    clip.p.y -= y0f;
+				    clip.q.x -= x0f;
+				    clip.q.y -= y0f;
+				    fa.clip = &clip;
+				    fa.swap_axes = swap_axes;
+				    fa.ht = NULL;
+				    fa.lop = lop_default; /* fgixme: imager_state.log_op; */
+				    fa.ystart = ybot - y0f;
+				    fa.yend = ytop - y0f;
+				    cmd_getw(colors_mask, cbp);
+				    for (i = 0; i < 4; i++, m <<= 1) {
+					if (colors_mask & m) {
+					    if (cbuf.end - cbp < num_components * cmd_max_intsize(sizeof(frac31)))
+						cbp = top_up_cbuf(&cbuf, cbp);
+					    cc[i] = c[i];
+					    for (j = 0; j < num_components; j++)
+						cmd_getw(c[i][j], cbp);
+					} else
+					    cc[i] = NULL;
+				    }
+				    if (options & 4)
+					code = 1 | dev_proc(ttdev, fill_linear_color_triangle)(ttdev, &fa,
+							&left.start, &left.end, &right.start,
+							cc[0], cc[1], cc[2]);
+				    else
+					code = 1 || dev_proc(ttdev, fill_linear_color_trapezoid)(ttdev, &fa,
+							&left.start, &left.end, &right.start, &right.end,
+							cc[0], cc[1], cc[2], cc[3]);
+				    if (code == 0) {
+					/* Fixme : The target device didn't fill the trapezoid and
+					   requests a decomposition. Call a code from gxshade6.c . */
+					code = gs_note_error(gs_error_unregistered);
+				    }
+				} else
+				    code = gx_default_fill_trapezoid(ttdev, &left, &right,
+					max(ybot - y0f, fixed_half), 
+					min(ytop - y0f, int2fixed(wh)), swap_axes,
+					&dev_color, imager_state.log_op);
 			    }
 			   break;
 			default:
@@ -2508,8 +2573,6 @@
 
 /*
  * Execute a polyfill -- either a fill_parallelogram or a fill_triangle.
- * If we ever implement fill_trapezoid in the band list, that will be
- * detected here too.
  *
  * Note that degenerate parallelograms or triangles may collapse into
  * a single line or point.  We must check for this so we don't try to

Modified: trunk/gs/src/gxclread.c
===================================================================
--- trunk/gs/src/gxclread.c	2007-07-11 00:26:24 UTC (rev 8117)
+++ trunk/gs/src/gxclread.c	2007-07-11 21:17:39 UTC (rev 8118)
@@ -27,6 +27,7 @@
 #include "gxhttile.h"
 #include "gdevplnx.h"
 #include "gsmemory.h"
+#include "vdtrace.h"
 /*
  * We really don't like the fact that gdevprn.h is included here, since
  * command lists are supposed to be usable for purposes other than printer
@@ -546,7 +547,15 @@
 	s_std_init(&s, sbuf, cbuf_size, &no_procs, s_mode_read);
 	s.foreign = 1;
 	s.state = (stream_state *)&rs;
+
+
+	vd_get_dc('s');
+	vd_set_shift(0, 0);
+	vd_set_scale(0.01);
+	vd_set_origin(0, 0);
+	vd_erase(RGB(192, 192, 192));
 	code = clist_playback_band(action, crdev, &s, target, x0, y0, mem);
+	vd_release_dc;
     }
 
     /* Close the files if we just opened them. */

Modified: trunk/gs/src/gxclrect.c
===================================================================
--- trunk/gs/src/gxclrect.c	2007-07-11 00:26:24 UTC (rev 8117)
+++ trunk/gs/src/gxclrect.c	2007-07-11 21:17:39 UTC (rev 8118)
@@ -134,20 +134,68 @@
     return 0;
 }
 
+private inline byte * 
+cmd_put_frac31_color(gx_device_clist_writer * cldev, const frac31 *c, byte *dp)
+{
+    int num_components = cldev->color_info.num_components;
+    int j;
+
+    for (j = 0; j < num_components; j++)
+	cmd_putw(c[j], dp);
+    return dp;
+}
+
+private inline int
+cmd_size_frac31_color(gx_device_clist_writer * cldev, const frac31 *c)
+{
+    int j, s = 0;
+    int num_components = cldev->color_info.num_components;
+
+    for (j = 0; j < num_components; j++)
+	s += cmd_sizew(c[j]);
+    return s;
+}
+
 private int
 cmd_write_trapezoid_cmd(gx_device_clist_writer * cldev, gx_clist_state * pcls,
 		    int op,  const gs_fixed_edge *left, const gs_fixed_edge *right,
-		    fixed ybot, fixed ytop, bool swap_axes)
+		    fixed ybot, fixed ytop, int options, 
+		    const gs_fill_attributes *fa, 
+		    const frac31 *c0, const frac31 *c1,
+		    const frac31 *c2, const frac31 *c3)
 {
     byte *dp;
     int rcsize;
     int code;
+    int colors_mask = 0;
 
     rcsize = 1 + cmd_sizew(left->start.x) + cmd_sizew(left->start.y)
 	       + cmd_sizew(left->end.x) + cmd_sizew(left->end.y)
 	       + cmd_sizew(right->start.x) + cmd_sizew(right->start.y)
 	       + cmd_sizew(right->end.x) + cmd_sizew(right->end.y)
-	       + cmd_sizew(ybot) + cmd_sizew(ytop) + cmd_sizew(swap_axes);
+	       + cmd_sizew(ybot) + cmd_sizew(ytop) + cmd_sizew(options);
+
+    if (options & 2) {
+	rcsize += cmd_sizew(fa->clip->p.x) + cmd_sizew(fa->clip->p.y) 
+		+ cmd_sizew(fa->clip->q.x) + cmd_sizew(fa->clip->q.y);
+	if (c0 != NULL) {
+	    colors_mask += 1;
+	    rcsize += cmd_size_frac31_color(cldev, c0);
+	}
+	if (c1 != NULL) {
+	    colors_mask += 2;
+	    rcsize += cmd_size_frac31_color(cldev, c1);
+	}
+	if (c2 != NULL) {
+	    colors_mask += 4;
+	    rcsize += cmd_size_frac31_color(cldev, c2);
+	}
+	if (c3 != NULL) {
+	    colors_mask += 8;
+	    rcsize += cmd_size_frac31_color(cldev, c3);
+	}
+	rcsize += cmd_sizew(colors_mask);
+    }
     code = set_cmd_put_op(dp, cldev, pcls, op, rcsize);
     if (code < 0)
 	return code;
@@ -162,11 +210,26 @@
     cmd_putw(right->end.y, dp);
     cmd_putw(ybot, dp);
     cmd_putw(ytop, dp);
-    cmd_putw(swap_axes, dp);
+    cmd_putw(options, dp);
     if_debug6('L', "    t%d:%d,%d,%d,%d   %d\n",
 	      rcsize - 1, left->start.x, left->start.y, left->end.x, left->end.y, ybot);
-    if_debug5('L', "    t%d,%d,%d,%d   %d\n",
-	      right->start.x, right->start.y, right->end.x, right->end.y, ytop);
+    if_debug6('L', "    t%d,%d,%d,%d   %d   o=%d\n",
+	      right->start.x, right->start.y, right->end.x, right->end.y, ytop, options);
+    if (options & 2) {
+	cmd_putw(fa->clip->p.x, dp);
+	cmd_putw(fa->clip->p.y, dp);
+	cmd_putw(fa->clip->q.x, dp);
+	cmd_putw(fa->clip->q.y, dp);
+	cmd_putw(colors_mask, dp);
+	if (c0 != NULL)
+	    dp = cmd_put_frac31_color(cldev, c0, dp);
+	if (c1 != NULL)
+	    dp = cmd_put_frac31_color(cldev, c1, dp);
+	if (c2 != NULL)
+	    dp = cmd_put_frac31_color(cldev, c2, dp);
+	if (c3 != NULL)
+	    cmd_put_frac31_color(cldev, c3, dp);
+    }
     return 0;
 }
 
@@ -210,43 +273,78 @@
     return 0;
 }
 
-int 
-clist_fill_trapezoid(gx_device * dev,
+private inline int 
+clist_write_fill_trapezoid(gx_device * dev,
     const gs_fixed_edge *left, const gs_fixed_edge *right,
-    fixed ybot, fixed ytop, bool swap_axes,
-    const gx_drawing_color *pdcolor, gs_logical_operation_t lop)
+    fixed ybot, fixed ytop, int options,
+    const gx_drawing_color *pdcolor, gs_logical_operation_t lop,
+    const gs_fill_attributes *fa,
+    const frac31 *c0, const frac31 *c1,
+    const frac31 *c2, const frac31 *c3)
 {
     gx_device_clist_writer * const cdev =
 	&((gx_device_clist *)dev)->writer;
     int code;
     cmd_rects_enum_t re;
     int ry, rheight;
+    bool swap_axes = (options & 1);
 
-    if (swap_axes) {
-	ry = fixed2int(min(left->start.x, left->end.x));
-	rheight = fixed2int_ceiling(max(right->start.x, right->end.x)) - ry;
+    if (options & 4) {
+	if (swap_axes) {
+	    ry = fixed2int(min(min(left->start.x, left->end.x), right->start.x));
+	    rheight = fixed2int_ceiling(max(max(left->start.x, left->end.x), right->start.x)) - ry;
+	} else {
+	    ry = fixed2int(min(min(left->start.y, left->end.y), right->start.y));
+	    rheight = fixed2int_ceiling(max(max(left->start.y, left->end.y), right->start.y)) - ry;
+	}
     } else {
-	ry = fixed2int(ybot);
-	rheight = fixed2int_ceiling(ytop) - ry;
+	if (swap_axes) {
+	    ry = fixed2int(min(left->start.x, left->end.x));
+	    rheight = fixed2int_ceiling(max(right->start.x, right->end.x)) - ry;
+	} else {
+	    ry = fixed2int(ybot);
+	    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)
+	return 0;
     if (cdev->permanent_error < 0)
 	return (cdev->permanent_error);
     RECT_ENUM_INIT(re, ry, rheight);
     do {
 	RECT_STEP_INIT(re);
 	do {
-	    code = cmd_put_drawing_color(cdev, re.pcls, pdcolor);
-	    if (code < 0) {
-		/* Something went wrong, use the default implementation. */
-		return gx_default_fill_trapezoid(dev, left, right, ybot, ytop, swap_axes, pdcolor, lop);
-	    }
-	    code = cmd_update_lop(cdev, re.pcls, lop);
+	    if (pdcolor != NULL) {
+		code = cmd_put_drawing_color(cdev, re.pcls, pdcolor);
+		if (code < 0) {
+		    /* Something went wrong, use the default implementation. */
+		    return gx_default_fill_trapezoid(dev, left, right, ybot, ytop, swap_axes, pdcolor, lop);
+		}
+		code = cmd_update_lop(cdev, re.pcls, lop);
+	    } else
+		code = 0;
 	    if (code >= 0) {
+		byte *dp;
+
 		/* Dont't want to shorten the trapezoid by the band boundary,
 		   keeping in mind a further optimization with writing same data to all bands. */
 		code = cmd_write_trapezoid_cmd(cdev, re.pcls, cmd_opv_fill_trapezoid, left, right,
-					  ybot, ytop, swap_axes);
+					  ybot, ytop, options, fa, c0, c1, c2, c3);
 	    }
 	} while (RECT_RECOVER(code));
 	if (code < 0 && SET_BAND_CODE(code))
@@ -262,6 +360,88 @@
 }
 
 int
+clist_fill_trapezoid(gx_device * dev,
+    const gs_fixed_edge *left, const gs_fixed_edge *right,
+    fixed ybot, fixed ytop, bool swap_axes,
+    const gx_drawing_color *pdcolor, gs_logical_operation_t lop)
+{
+    return clist_write_fill_trapezoid(dev, left, right,
+	ybot, ytop, swap_axes, pdcolor, lop, NULL, NULL, NULL, NULL, NULL);
+}
+
+int
+clist_fill_linear_color_trapezoid(gx_device * dev, const gs_fill_attributes *fa,
+	const gs_fixed_point *p0, const gs_fixed_point *p1,
+	const gs_fixed_point *p2, const gs_fixed_point *p3,
+	const frac31 *c0, const frac31 *c1,
+	const frac31 *c2, const frac31 *c3)
+{
+    gs_fixed_edge left, right;
+    int code;
+
+    left.start = *p0;
+    left.end = *p1;
+    right.start = *p2;
+    right.end = *p3;
+    code = clist_write_fill_trapezoid(dev, &left, &right,
+	fa->ystart, fa->yend, fa->swap_axes | 2, NULL, lop_default, fa, c0, c1, c2, c3);
+    if (code < 0)
+	return code;
+    /* NOTE : The return value 0 for the fill_linear_color_trapezoid method means
+       that the device requests a further decomposition of the trapezoid.
+       Currently we have no interface for checking whether the target device
+       can handle a trapezoid without an attempt to fill it.
+       Therefore the clist writer device must always return 1,
+       and the clist reader must perform a further decomposition
+       if the target device requests it.
+     */
+    return 1;
+}
+
+int 
+clist_fill_linear_color_triangle(gx_device * dev, const gs_fill_attributes *fa,
+	const gs_fixed_point *p0, const gs_fixed_point *p1,
+	const gs_fixed_point *p2,
+	const frac31 *c0, const frac31 *c1, const frac31 *c2)
+{
+    gs_fixed_edge left, right;
+    int code;
+
+    left.start = *p0;
+    left.end = *p1;
+    right.start = *p2;
+    right.end.x = right.end.y = 0; /* unused. */
+
+    code = clist_write_fill_trapezoid(dev, &left, &right,
+	fa->ystart, fa->yend, fa->swap_axes | 2 | 4, NULL, lop_default, fa, c0, c1, c2, NULL);
+    if (code < 0)
+	return code;
+    /* NOTE : The return value 0 for the fill_linear_color_triangle method means
+       that the device requests a further decomposition of the trapezoid.
+       Currently we have no interface for checking whether the target device
+       can handle a trapezoid without an attempt to fill it.
+       Therefore the clist writer device must always return 1,
+       and the clist reader must perform a further decomposition
+       if the target device requests it.
+     */
+    return 1;
+}
+
+
+int 
+clist_pattern_manage(gx_device *pdev, gx_bitmap_id id,
+		gs_pattern1_instance_t *pinst, pattern_manage_t function)
+{
+    if (function == pattern_manage__handles_clip_path)
+	return 1;
+    return gx_default_pattern_manage(pdev, id, pinst, function);
+}
+
+#define dev_proc_pattern_manage(proc)\
+  dev_t_proc_pattern_manage(proc, gx_device)
+
+
+int
 clist_strip_tile_rectangle(gx_device * dev, const gx_strip_bitmap * tile,
 			   int rx, int ry, int rwidth, int rheight,
 	       gx_color_index color0, gx_color_index color1, int px, int py)

Modified: trunk/gs/src/gxdevcli.h
===================================================================
--- trunk/gs/src/gxdevcli.h	2007-07-11 00:26:24 UTC (rev 8117)
+++ trunk/gs/src/gxdevcli.h	2007-07-11 21:17:39 UTC (rev 8118)
@@ -1225,7 +1225,8 @@
     pattern_manage__load,
     pattern_manage__shading_area,
     pattern_manage__is_cpath_accum,
-    pattern_manage__shfill_doesnt_need_path
+    pattern_manage__shfill_doesnt_need_path,
+    pattern_manage__handles_clip_path
 } pattern_manage_t;
 
 #define dev_t_proc_pattern_manage(proc, dev_t)\
@@ -1294,12 +1295,12 @@
 /* [p0 : p1] - left edge, from bottom to top.
    [p2 : p3] - right edge, from bottom to top.
    The filled area is within Y-spans of both edges. */
-/* If either (c0 and c1) or (c2 and c3) may be NULL.
+/* Either (c0 and c1) or (c2 and c3) may be NULL.
    In this case the color doesn't depend on X (on Y if fa->swap_axes).
    In this case the base coordinates for the color gradient
    may be unequal to p0, p1, p2, p3, and must be provided/taken
    in/from fa->ystart, fa->yend. 
-   The rerurn value 0 is not allowed in this case. */
+   The return value 0 is not allowed in this case. */
 /* Return values : 
   1 - success;
   0 - Too big. The area isn't filled. The client must decompose the area.

Modified: trunk/gs/src/gxfill.c
===================================================================
--- trunk/gs/src/gxfill.c	2007-07-11 00:26:24 UTC (rev 8117)
+++ trunk/gs/src/gxfill.c	2007-07-11 21:17:39 UTC (rev 8118)
@@ -618,27 +618,38 @@
 	    code = gx_dc_pattern2_clip_with_bbox(pdevc, pdev, &cpath_with_shading_bbox, &pcpath1);
 	/* Do fill : */
 	if (code >= 0) {
+	    gs_fixed_rect clip_box;
+	    gs_int_rect cb;
 	    const gx_rop_source_t *rs = NULL;
 	    gx_device *dev;
 	    gx_device_clip cdev;
-	    gs_fixed_rect clip_box;
-	    gs_int_rect cb;
 
 	    gx_cpath_outer_box(pcpath1, &clip_box);
-	    gx_make_clip_path_device(&cdev, pcpath1);
-	    cdev.HWResolution[0] = pdev->HWResolution[0];
-	    cdev.HWResolution[1] = pdev->HWResolution[1];
-	    cdev.target = pdev;
-	    dev = (gx_device *)&cdev;
-	    if ((*dev_proc(pdev, pattern_manage))(pdev, 
-		    gs_no_id, NULL, pattern_manage__shading_area) > 0)
-		set_dev_proc(&cdev, fill_path, pass_shading_area_through_clip_path_device);
-	    (*dev_proc(dev, open_device))(dev);
 	    cb.p.x = fixed2int_pixround(clip_box.p.x);
 	    cb.p.y = fixed2int_pixround(clip_box.p.y);
 	    cb.q.x = fixed2int_pixround(clip_box.q.x);
 	    cb.q.y = fixed2int_pixround(clip_box.q.y);
-	    code = pdevc->type->fill_rectangle(pdevc,
+	    if (gx_dc_is_pattern2_color(pdevc) && 
+		    (*dev_proc(pdev, pattern_manage))(pdev, gs_no_id, NULL, pattern_manage__handles_clip_path) > 0) {
+		/* A special interaction with clist writer device : 
+		   pass the intersected clipping path. It uses an unusual call to
+		   fill_path with NULL device color. */
+		code = (*dev_proc(pdev, fill_path))(pdev, pis, ppath, params, NULL, pcpath1);
+		dev = pdev;
+	    } else {
+		gx_make_clip_path_device(&cdev, pcpath1);
+		cdev.HWResolution[0] = pdev->HWResolution[0];
+		cdev.HWResolution[1] = pdev->HWResolution[1];
+		cdev.target = pdev;
+		dev = (gx_device *)&cdev;
+		if ((*dev_proc(pdev, pattern_manage))(pdev, 
+			gs_no_id, NULL, pattern_manage__shading_area) > 0)
+		    set_dev_proc(&cdev, fill_path, pass_shading_area_through_clip_path_device);
+		(*dev_proc(dev, open_device))(dev);
+		code = 0;
+	    }
+	    if (code >= 0)
+		code = pdevc->type->fill_rectangle(pdevc,
 			cb.p.x, cb.p.y, cb.q.x - cb.p.x, cb.q.y - cb.p.y,
 			dev, pis->log_op, rs);
 	}

Modified: trunk/gs/src/gxshade1.c
===================================================================
--- trunk/gs/src/gxshade1.c	2007-07-11 00:26:24 UTC (rev 8117)
+++ trunk/gs/src/gxshade1.c	2007-07-11 21:17:39 UTC (rev 8118)
@@ -640,8 +640,10 @@
 }
 
 private int
-R_fill_rect_with_const_color(const patch_fill_state_t *pfs, const gs_fixed_rect *clip_rect, float t)
+R_fill_rect_with_const_color(patch_fill_state_t *pfs, const gs_fixed_rect *clip_rect, float t)
 {
+#if 0 /* Disabled because the clist writer device doesn't pass 
+         the clipping path with fill_recatangle. */
     patch_color_t pc;
     const gs_color_space *pcs = pfs->direct_space;
     gx_device_color dc;
@@ -658,6 +660,34 @@
 					fixed2int_pixround(clip_rect->q.x) - fixed2int_pixround(clip_rect->p.x),
 					fixed2int_pixround(clip_rect->q.y) - fixed2int_pixround(clip_rect->p.y), 
 					&dc, pfs->dev, pfs->pis->log_op);
+#else
+    /* Can't apply fill_rectangle, because the clist writer device doesn't pass 
+       the clipping path with fill_recatangle. Convert into trapezoids instead.
+    */
+    quadrangle_patch p;
+    shading_vertex_t pp[2][2];
+    const gs_color_space *pcs = pfs->direct_space;
+    patch_color_t pc;
+    int code;
+
+    code = gs_function_evaluate(pfs->Function, &t, pc.cc.paint.values);
+    if (code < 0)
+	return code;
+    pcs->type->restrict_color(&pc.cc, pcs);
+    pc.t[0] = pc.t[1] = t;
+    pp[0][0].p = clip_rect->p;
+    pp[0][1].p.x = clip_rect->q.x;
+    pp[0][1].p.y = clip_rect->p.y;
+    pp[1][0].p.x = clip_rect->p.x;
+    pp[1][0].p.y = clip_rect->q.y;
+    pp[1][1].p = clip_rect->q;
+    pp[0][0].c = pp[0][1].c = pp[1][0].c = pp[1][1].c = &pc;
+    p.p[0][0] = &pp[0][0];
+    p.p[0][1] = &pp[0][1];
+    p.p[1][0] = &pp[1][0];
+    p.p[1][1] = &pp[1][1];
+    return constant_color_quadrangle(pfs, &p, false);
+#endif
 }
 
 typedef struct radial_shading_attrs_s {

Modified: trunk/gs/src/gxshade4.h
===================================================================
--- trunk/gs/src/gxshade4.h	2007-07-11 00:26:24 UTC (rev 8117)
+++ trunk/gs/src/gxshade4.h	2007-07-11 21:17:39 UTC (rev 8118)
@@ -160,6 +160,11 @@
     bool straight;
 } patch_curve_t;
 
+typedef struct {
+    const shading_vertex_t *p[2][2]; /* [v][u] */
+    wedge_vertex_list_t *l0001, *l0111, *l1110, *l1000;
+} quadrangle_patch;
+
 /* Initialize the fill state for triangle shading. */
 int mesh_init_fill_state(mesh_fill_state_t * pfs,
 			  const gs_shading_mesh_t * psh,
@@ -180,6 +185,8 @@
 	   void (*transform) (gs_fixed_point *, const patch_curve_t[4],
 			      const gs_fixed_point[4], floatp, floatp));
 
+int constant_color_quadrangle(patch_fill_state_t *pfs, const quadrangle_patch *p, bool self_intersecting);
+
 int wedge_vertex_list_elem_buffer_alloc(patch_fill_state_t *pfs);
 void wedge_vertex_list_elem_buffer_free(patch_fill_state_t *pfs);
 

Modified: trunk/gs/src/gxshade6.c
===================================================================
--- trunk/gs/src/gxshade6.c	2007-07-11 00:26:24 UTC (rev 8117)
+++ trunk/gs/src/gxshade6.c	2007-07-11 21:17:39 UTC (rev 8118)
@@ -618,11 +618,6 @@
     patch_color_t *c[2][2];     /* [v][u] */
 } tensor_patch;
 
-typedef struct {
-    const shading_vertex_t *p[2][2]; /* [v][u] */
-    wedge_vertex_list_t *l0001, *l0111, *l1110, *l1000;
-} quadrangle_patch;
-
 typedef enum {
     interpatch_padding = 1, /* A Padding between patches for poorly designed documents. */
     inpatch_wedge = 2  /* Wedges while a patch decomposition. */
@@ -1195,6 +1190,11 @@
 	    code = patch_color_to_device_color_inline(pfs, c1, NULL, fc[1]);
 	    if (code < 0)
 		goto out;
+	    if (fa.swap_axes) {
+		vd_quad(le->start.y, le->start.x, le->end.y, le->end.x, re->end.y, re->end.x, re->start.y, re->start.x, 0, RGB(0,255,0));
+	    } else {
+		vd_quad(le->start.x, le->start.y, le->end.x, le->end.y, re->end.x, re->end.y, re->start.x, re->start.y, 0, RGB(0,255,0));
+	    }
 	    code = dev_proc(pdev, fill_linear_color_trapezoid)(pdev, &fa, 
 			    &le->start, &le->end, &re->start, &re->end, 
 			    fc[0], fc[1], NULL, NULL);
@@ -2337,7 +2337,7 @@
     }
 }
 
-private int
+int
 constant_color_quadrangle(patch_fill_state_t *pfs, const quadrangle_patch *p, bool self_intersecting)
 {
     patch_color_t *c[3];

Modified: trunk/gs/src/lib.mak
===================================================================
--- trunk/gs/src/lib.mak	2007-07-11 00:26:24 UTC (rev 8117)
+++ trunk/gs/src/lib.mak	2007-07-11 21:17:39 UTC (rev 8118)
@@ -1687,7 +1687,7 @@
  $(gscoord_h) $(gsdevice_h)\
  $(gxcldev_h) $(gxdevice_h) $(gxdevmem_h) $(gxgetbit_h) $(gxhttile_h)\
  $(gsmemory_h) \
- $(stream_h) $(strimpl_h)
+ $(stream_h) $(strimpl_h) $(vdtrace_h)
 	$(GLCC) $(GLO_)gxclread.$(OBJ) $(C_) $(GLSRC)gxclread.c
 
 $(GLOBJ)gxclrect.$(OBJ) : $(GLSRC)gxclrect.c $(GXERR)\



More information about the gs-cvs mailing list