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

leonardo at ghostscript.com leonardo at ghostscript.com
Thu May 31 10:25:53 PDT 2007


Author: leonardo
Date: 2007-05-31 10:25:52 -0700 (Thu, 31 May 2007)
New Revision: 8017

Modified:
   trunk/gs/src/gdevdflt.c
   trunk/gs/src/gdevnfwd.c
   trunk/gs/src/gdevpdfb.c
   trunk/gs/src/gscolor3.c
   trunk/gs/src/gsptype2.c
   trunk/gs/src/gsptype2.h
   trunk/gs/src/gsshade.c
   trunk/gs/src/gsshade.h
   trunk/gs/src/gxcpath.c
   trunk/gs/src/gxdevcli.h
   trunk/gs/src/gxfill.c
   trunk/gs/src/gximask.c
   trunk/gs/src/gxpath.h
   trunk/gs/src/lib.mak
Log:
Fix (shadings) : Optimize path manipulations for shading fill.

DETAILS :

This partially improves performance for the test case of 
the bug 689189 "PDF fails with /unregistered in --shfill--".

While filling a shading, the old code 
converts the clipping path into a path, then 
converts it to a clipping path for intersecting it
with the filling path and with the shading BBox.
These manipulations are neccessary due to the
interface restrictions for gs_shading_fill_path,
which doesn't pass a clipping path.
It causes (1) a bad performance and (2)
a wrong fill adjustment, because the conversion 
of a path to a clipping path and back to path 
is not identity due to fill adjustment.

The new code is a 1st step for the elimination of gs_shading_fill_path.
This patch excludes this function for raster devices.
Excluding it for higth level devices will be a next step.

The new code moves path manipulation outside the
shading color painting. Now all 3 pathes
(the filling path, the clipping patrh, and the shading BBox)
are processed in gxfill.c . The painting 
is done with gs_shading_do_fill_rectangle,
which does not manipulate with pathes.

The patch modifies gx_image_fill_masked_end
to comply with the new inplementation of
gs_shading_do_fill_rectangle when a mask
is converted into a clipping path. 

Another optimization avoids the generation
of a filling path for 'shfill'.
Accorgong to PLRM, shfill deals with clipping path,
but it was converted into a path due to 
internal Ghostscript constraint for the device interface.
When the device implements fill_path with
the default method gx_default_fill_path,
the conversion to a path is not necessary.

To make use of this fact for optimization, the graphics library
needs to know, whether the output device uses the default
function gx_default_fill_path. This patch introduces a new response
for pattern_manage, which is named 'pattern_manage__shfill_doesnt_need_path'.
The device must respond with 1 if it does not need a path.
The patch provides implementations for raster devices and
for forwarding devices. If some device provides an instandard
fill_path method, the optimization won't work for it
(i.e. it will work as before - will recieve a path for shfill)
unless it provides a proper response to pattern_manage__shfill_doesnt_need_path . 

A minor change to gdevpdfb.c fixes a paranoid compiler warning
about a possible use of unubnitialized data.

EXPECTED DIFFERENCES :

The old code erroneusely applied fill adjustment two times
when filling a path with a shading color. 
Also fill adjustment was erroneusely applied when
painting a characxter with a shading color.
With new code shadings paint fewer pixels at a shading boundary,
causing a minor difference in rasters :

72dpi :

"442-01.ps" 
"446-01-fixed.ps" 
"470-01.ps" 
"Bug687546.ps" 
"Bug689189.pdf" 
"chilis_black.pdf" 
"chilis_red.pdf" 
"Clarke Tate Manns Chinese.ai" 
"gradmesh.ai" 
"muur.eps" 
"S2_Digitalproof-Forum_x3k.pdf" 
"shading_prob_800.ps" 
"SmoothShading.pdf" 
"Testform.v1.0.2.pdf" 


300dpi :

"470-01.ps" 
"Bug687546.ps" 
"Bug689189.pdf" 
"chilis_black.pdf" 
"chilis_red.pdf" 
"Clarke Tate Manns Chinese.ai" 
"muur.eps" 
"S2_Digitalproof-Forum_x3k.pdf" 
"SmoothShading.pdf" 


Modified: trunk/gs/src/gdevdflt.c
===================================================================
--- trunk/gs/src/gdevdflt.c	2007-05-30 06:05:43 UTC (rev 8016)
+++ trunk/gs/src/gdevdflt.c	2007-05-31 17:25:52 UTC (rev 8017)
@@ -870,6 +870,10 @@
 gx_default_pattern_manage(gx_device *pdev, gx_bitmap_id id,
 		gs_pattern1_instance_t *pinst, pattern_manage_t function)
 {
+    if (function == pattern_manage__shfill_doesnt_need_path) {
+	if (pdev->procs.fill_path == gx_default_fill_path)
+	    return 1;
+    }
     return 0;
 }
 

Modified: trunk/gs/src/gdevnfwd.c
===================================================================
--- trunk/gs/src/gdevnfwd.c	2007-05-30 06:05:43 UTC (rev 8016)
+++ trunk/gs/src/gdevnfwd.c	2007-05-31 17:25:52 UTC (rev 8017)
@@ -751,9 +751,13 @@
 
     /* Note that clist sets fdev->target == fdev, 
        so this function is unapplicable to clist. */
-    if (tdev == 0)
+    if (tdev == 0) {
+	if (function == pattern_manage__shfill_doesnt_need_path) {
+	    if (dev->procs.fill_path == gx_default_fill_path)
+		return 1;
+	}
 	return 0;
-    else
+    } else
 	return dev_proc(tdev, pattern_manage)(tdev, id, pinst, function);
 }
 

Modified: trunk/gs/src/gdevpdfb.c
===================================================================
--- trunk/gs/src/gdevpdfb.c	2007-05-30 06:05:43 UTC (rev 8016)
+++ trunk/gs/src/gdevpdfb.c	2007-05-31 17:25:52 UTC (rev 8017)
@@ -123,7 +123,7 @@
 	      gx_color_index one, const gx_clip_path *pcpath)
 {
     int code;
-    gs_color_space *pcs;
+    gs_color_space *pcs = NULL;
     cos_value_t cs_value;
     cos_value_t *pcsvalue;
     byte palette[arch_sizeof_color_index * 2];

Modified: trunk/gs/src/gscolor3.c
===================================================================
--- trunk/gs/src/gscolor3.c	2007-05-30 06:05:43 UTC (rev 8016)
+++ trunk/gs/src/gscolor3.c	2007-05-31 17:25:52 UTC (rev 8017)
@@ -58,7 +58,6 @@
      * shading with Background removed.
      */
     gs_pattern2_template_t pat;
-    gx_path cpath;
     gs_matrix imat;
     gs_client_color cc;
     gs_color_space *pcs;
@@ -98,12 +97,22 @@
     code = pcs->type->remap_color(&cc, pcs, &devc, (gs_imager_state *)pgs,
 				  pgs->device, gs_color_select_texture);
     if (code >= 0) {
-	gx_path_init_local(&cpath, pgs->memory);
-	code = gx_cpath_to_path(pgs->clip_path, &cpath);
-	if (code >= 0)
-	    code = gx_fill_path(&cpath, &devc, pgs, gx_rule_winding_number,
+	gx_device *dev = pgs->device;
+	bool need_path = !dev_proc(dev, pattern_manage)(dev, gs_no_id, NULL,
+		pattern_manage__shfill_doesnt_need_path);
+
+	if (need_path) {
+    	    gx_path cpath;
+
+	    gx_path_init_local(&cpath, pgs->memory);
+	    code = gx_cpath_to_path(pgs->clip_path, &cpath);
+	    if (code >= 0)
+		code = gx_fill_path(&cpath, &devc, pgs, gx_rule_winding_number,
+				    pgs->fill_adjust.x, pgs->fill_adjust.y);
+	    gx_path_free(&cpath, "gs_shfill");
+	} else 
+	    code = gx_fill_path(NULL, &devc, pgs, gx_rule_winding_number,
 				pgs->fill_adjust.x, pgs->fill_adjust.y);
-	gx_path_free(&cpath, "gs_shfill");
     }
     rc_decrement(pcs, "gs_shfill");
     gs_pattern_reference(&cc, -1);

Modified: trunk/gs/src/gsptype2.c
===================================================================
--- trunk/gs/src/gsptype2.c	2007-05-30 06:05:43 UTC (rev 8016)
+++ trunk/gs/src/gsptype2.c	2007-05-31 17:25:52 UTC (rev 8017)
@@ -218,6 +218,10 @@
 }
 
 /* Fill a rectangle with a PatternType 2 color. */
+/* WARNING: This function doesn't account the shading BBox
+   to allow the clipent to optimize the clipping 
+   with changing the order of clip patrhs and rects.
+   The client must clip with the shading BBOx before calling this function. */
 private int
 gx_dc_pattern2_fill_rectangle(const gx_device_color * pdevc, int x, int y,
                               int w, int h, gx_device * dev,
@@ -230,12 +234,15 @@
 	return dev_proc(dev, fill_rectangle)(dev, x, y, w, h, (gx_color_index)0/*any*/);
     } else {
 	gs_fixed_rect rect;
+	gs_pattern2_instance_t *pinst =
+	    (gs_pattern2_instance_t *)pdevc->ccolor.pattern;
 
 	rect.p.x = int2fixed(x);
 	rect.p.y = int2fixed(y);
 	rect.q.x = int2fixed(x + w);
 	rect.q.y = int2fixed(y + h);
-	return gx_dc_pattern2_fill_path(pdevc, NULL, &rect,  dev);
+	return gs_shading_do_fill_rectangle(pinst->template.Shading, &rect, dev,
+				    (gs_imager_state *)pinst->saved, !pinst->shfill);
     }
 }
 
@@ -303,6 +310,59 @@
     return 1;
 }
 
+int
+gx_dc_pattern2_color_has_bbox(const gx_device_color * pdevc)
+{
+    gs_pattern2_instance_t *pinst = (gs_pattern2_instance_t *)pdevc->ccolor.pattern;
+    const gs_shading_t *psh = pinst->template.Shading;
+
+    return psh->params.have_BBox;
+}
+
+/* Create a path from a PatternType 2 shading BBox to a path. */
+int
+gx_dc_shading_path_add_box(gx_path *ppath, const gx_device_color * pdevc)
+{
+    gs_pattern2_instance_t *pinst = (gs_pattern2_instance_t *)pdevc->ccolor.pattern;
+    const gs_shading_t *psh = pinst->template.Shading;
+
+    if (!psh->params.have_BBox)
+	return_error(gs_error_unregistered); /* Do not call in this case. */
+    else {
+	gs_state *pis = pinst->saved;
+
+	return shading_path_add_box(ppath, &psh->params.BBox, &pis->ctm);
+    }
+}
+
+/* Intersect a clipping path a shading BBox. */
+int
+gx_dc_pattern2_clip_with_bbox(const gx_device_color * pdevc, gx_device * pdev, 
+			      gx_clip_path *cpath_local, const gx_clip_path **ppcpath1)
+{
+    if (gx_dc_is_pattern2_color(pdevc) && gx_dc_pattern2_color_has_bbox(pdevc) &&
+	    (*dev_proc(pdev, pattern_manage))(pdev, gs_no_id, NULL, pattern_manage__shading_area) == 0) {
+	gs_pattern2_instance_t *pinst = (gs_pattern2_instance_t *)pdevc->ccolor.pattern;
+	gx_path box_path;
+	int code;
+
+	gx_path_init_local(&box_path, pdev->memory);
+	code = gx_dc_shading_path_add_box(&box_path, pdevc);
+	if (code == gs_error_limitcheck) {
+	    /* Ignore huge BBox - bug 689027. */
+	    code = 0;
+	} else {
+	    if (code >= 0) {
+		gx_cpath_init_local_shared(cpath_local, *ppcpath1, pdev->memory);
+		code = gx_cpath_intersect(cpath_local, &box_path, gx_rule_winding_number, (gs_imager_state *)pinst->saved);
+		*ppcpath1 = cpath_local;
+	    }
+	}
+	gx_path_free(&box_path, "gx_default_fill_path(path_bbox)");
+    }
+    return 0;
+}
+
 /* Get a shading color space. */
 const gs_color_space *
 gx_dc_pattern2_get_color_space(const gx_device_color * pdevc)

Modified: trunk/gs/src/gsptype2.h
===================================================================
--- trunk/gs/src/gsptype2.h	2007-05-30 06:05:43 UTC (rev 8016)
+++ trunk/gs/src/gsptype2.h	2007-05-31 17:25:52 UTC (rev 8017)
@@ -75,6 +75,11 @@
 typedef struct gs_color_space_s gs_color_space;
 #endif
 
+#ifndef gx_clip_path_DEFINED
+#  define gx_clip_path_DEFINED
+typedef struct gx_clip_path_s gx_clip_path;
+#endif
+
 extern const gx_device_color_type_t gx_dc_pattern2;
 
 #define gx_dc_type_pattern2 (&gx_dc_pattern2)
@@ -107,6 +112,18 @@
 /* Get a shading bbox. Returns 1 on success. */
 int gx_dc_pattern2_get_bbox(const gx_device_color * pdevc, gs_fixed_rect *bbox);
 
+/* Checks whether a PatternType 2 has a shading BBox. */
+int gx_dc_pattern2_color_has_bbox(const gx_device_color * pdevc);
+
+/* Intersect a clipping path a shading BBox. */
+int gx_dc_pattern2_clip_with_bbox(const gx_device_color * pdevc, gx_device * pdev, 
+				  gx_clip_path *cpath_local, const gx_clip_path **cpath1);
+
+
+/* Create a path from a PatternType 2 shading BBox to a path. */
+int gx_dc_shading_path_add_box(gx_path *ppath, const gx_device_color * pdevc);
+
+
 /* Get a shading color space. */
 const gs_color_space *gx_dc_pattern2_get_color_space(const gx_device_color * pdevc);
 

Modified: trunk/gs/src/gsshade.c
===================================================================
--- trunk/gs/src/gsshade.c	2007-05-30 06:05:43 UTC (rev 8016)
+++ trunk/gs/src/gsshade.c	2007-05-31 17:25:52 UTC (rev 8017)
@@ -417,7 +417,7 @@
 /* ================ Shading rendering ================ */
 
 /* Add a user-space rectangle to a path. */
-private int
+int
 shading_path_add_box(gx_path *ppath, const gs_rect *pbox,
 		     const gs_matrix_fixed *pmat)
 {
@@ -441,12 +441,51 @@
 }
 
 /* Fill a path with a shading. */
+int
+gs_shading_do_fill_rectangle(const gs_shading_t *psh,
+		     const gs_fixed_rect *prect, gx_device *dev,
+		     gs_imager_state *pis, bool fill_background)
+{   /* If you need to fill a path, clip the output device before calling this function. */
+    const gs_matrix_fixed *pmat = &pis->ctm;
+    gs_fixed_rect path_box;
+    gs_rect path_rect;
+    gs_rect rect;
+    int code = 0;
+
+    dev_proc(dev, get_clipping_box)(dev, &path_box);
+    if (prect)
+	rect_intersect(path_box, *prect);
+    if (psh->params.Background && fill_background) {
+	const gs_color_space *pcs = psh->params.ColorSpace;
+	gs_client_color cc;
+	gx_device_color dev_color;
+
+	cc = *psh->params.Background;
+	(*pcs->type->restrict_color)(&cc, pcs);
+	(*pcs->type->remap_color)(&cc, pcs, &dev_color, pis,
+				  dev, gs_color_select_texture);
+
+	/****** WRONG IF NON-IDEMPOTENT RasterOp ******/
+	code = gx_shade_background(dev, &path_box, &dev_color, pis->log_op);
+    }
+    if (code >= 0) {
+	path_rect.p.x = fixed2float(path_box.p.x);
+	path_rect.p.y = fixed2float(path_box.p.y);
+	path_rect.q.x = fixed2float(path_box.q.x);
+	path_rect.q.y = fixed2float(path_box.q.y);
+	gs_bbox_transform_inverse(&path_rect, (const gs_matrix *)pmat, &rect);
+	code = gs_shading_fill_rectangle(psh, &rect, &path_box, dev, pis);
+    }
+    return code;
+}
+
+/* Fill a path with a shading. */
+/* Depricated. To be removed soon. */
 private int
 gs_shading_fill_path(const gs_shading_t *psh, /*const*/ gx_path *ppath,
 		     const gs_fixed_rect *prect, gx_device *orig_dev,
 		     gs_imager_state *pis, bool fill_background)
-{
-    gs_memory_t *mem = pis->memory;
+{   gs_memory_t *mem = pis->memory;
     const gs_matrix_fixed *pmat = &pis->ctm;
     gx_device *dev = orig_dev;
     gs_fixed_rect path_box;

Modified: trunk/gs/src/gsshade.h
===================================================================
--- trunk/gs/src/gsshade.h	2007-05-30 06:05:43 UTC (rev 8016)
+++ trunk/gs/src/gsshade.h	2007-05-31 17:25:52 UTC (rev 8017)
@@ -253,8 +253,14 @@
 #  define gx_path_DEFINED
 typedef struct gx_path_s gx_path;
 #endif
+/* Fill a path with a shading. */
+/* Depricated. To be removed soon. */
 int gs_shading_fill_path_adjusted(const gs_shading_t *psh, /*const*/ gx_path *ppath,
 			 const gs_fixed_rect *prect, gx_device *dev,
 			 gs_imager_state *pis, bool fill_background);
 
+/* Fill a path with a shading. */
+int gs_shading_do_fill_rectangle(const gs_shading_t *psh, 
+			 const gs_fixed_rect *prect, gx_device *dev,
+			 gs_imager_state *pis, bool fill_background);
 #endif /* gsshade_INCLUDED */

Modified: trunk/gs/src/gxcpath.c
===================================================================
--- trunk/gs/src/gxcpath.c	2007-05-30 06:05:43 UTC (rev 8016)
+++ trunk/gs/src/gxcpath.c	2007-05-31 17:25:52 UTC (rev 8017)
@@ -375,56 +375,67 @@
 
 /* ------ Clipping path accessing ------ */
 
+/* Synthesize a path from a clipping path. */
+int
+gx_cpath_to_path_synthesize(const gx_clip_path * pcpath, gx_path * ppath)
+{
+    /* Synthesize a path. */
+    gs_cpath_enum cenum;
+    gs_fixed_point pts[3];
+    int code;
+
+    gx_cpath_enum_init(&cenum, pcpath);
+    while ((code = gx_cpath_enum_next(&cenum, pts)) != 0) {
+	switch (code) {
+	    case gs_pe_moveto:
+		code = gx_path_add_point(ppath, pts[0].x, pts[0].y);
+		break;
+	    case gs_pe_lineto:
+		code = gx_path_add_line_notes(ppath, pts[0].x, pts[0].y,
+					   gx_cpath_enum_notes(&cenum));
+		break;
+	    case gs_pe_curveto:
+		code = gx_path_add_curve_notes(ppath, pts[0].x, pts[0].y,
+					       pts[1].x, pts[1].y,
+					       pts[2].x, pts[2].y,
+					   gx_cpath_enum_notes(&cenum));
+		break;
+	    case gs_pe_closepath:
+		code = gx_path_close_subpath_notes(ppath,
+					   gx_cpath_enum_notes(&cenum));
+		break;
+	    default:
+		if (code >= 0)
+		    code = gs_note_error(gs_error_unregistered);
+	}
+	if (code < 0)
+	    break;
+    }
+    return 0;
+}
+
 /* Return the path of a clipping path. */
 int
 gx_cpath_to_path(gx_clip_path * pcpath, gx_path * ppath)
 {
     if (!pcpath->path_valid) {
-	/* Synthesize a path. */
-	gs_cpath_enum cenum;
-	gs_fixed_point pts[3];
 	gx_path rpath;
 	int code;
 
 	gx_path_init_local(&rpath, pcpath->path.memory);
-	gx_cpath_enum_init(&cenum, pcpath);
-	while ((code = gx_cpath_enum_next(&cenum, pts)) != 0) {
-	    switch (code) {
-		case gs_pe_moveto:
-		    code = gx_path_add_point(&rpath, pts[0].x, pts[0].y);
-		    break;
-		case gs_pe_lineto:
-		    code = gx_path_add_line_notes(&rpath, pts[0].x, pts[0].y,
-					       gx_cpath_enum_notes(&cenum));
-		    break;
-		case gs_pe_curveto:
-		    code = gx_path_add_curve_notes(&rpath, pts[0].x, pts[0].y,
-						   pts[1].x, pts[1].y,
-						   pts[2].x, pts[2].y,
-					       gx_cpath_enum_notes(&cenum));
-		    break;
-		case gs_pe_closepath:
-		    code = gx_path_close_subpath_notes(&rpath,
-					       gx_cpath_enum_notes(&cenum));
-		    break;
-		default:
-		    if (code >= 0)
-			code = gs_note_error(gs_error_unregistered);
-	    }
-	    if (code < 0)
-		break;
-	}
-	if (code >= 0)
-	    code = gx_path_assign_free(&pcpath->path, &rpath);
+	code = gx_cpath_to_path_synthesize(pcpath, ppath);
 	if (code < 0) {
 	    gx_path_free(&rpath, "gx_cpath_to_path error");
 	    return code;
 	}
+	code = gx_path_assign_free(&pcpath->path, &rpath);
+	if (code < 0)
+	    return code;
 	pcpath->path_valid = true;
+	return 0;
     }
     return gx_path_assign_preserve(ppath, &pcpath->path);
 }
-
 /* Return the inner and outer check rectangles for a clipping path. */
 /* Return true iff the path is a rectangle. */
 bool
@@ -474,7 +485,7 @@
 }
 /* Internal non-const version of the same accessor. */
 inline private gx_clip_list *
-gx_cpath_list_private(gx_clip_path *pcpath)
+gx_cpath_list_private(const gx_clip_path *pcpath)
 {
     return &pcpath->rect_list->list;
 }
@@ -760,7 +771,7 @@
 
 /* Start enumerating a clipping path. */
 int
-gx_cpath_enum_init(gs_cpath_enum * penum, gx_clip_path * pcpath)
+gx_cpath_enum_init(gs_cpath_enum * penum, const gx_clip_path * pcpath)
 {
     if ((penum->using_path = pcpath->path_valid)) {
 	gx_path_enum_init(&penum->path_enum, &pcpath->path);

Modified: trunk/gs/src/gxdevcli.h
===================================================================
--- trunk/gs/src/gxdevcli.h	2007-05-30 06:05:43 UTC (rev 8016)
+++ trunk/gs/src/gxdevcli.h	2007-05-31 17:25:52 UTC (rev 8017)
@@ -1224,7 +1224,8 @@
     pattern_manage__finish_accum,
     pattern_manage__load,
     pattern_manage__shading_area,
-    pattern_manage__is_cpath_accum
+    pattern_manage__is_cpath_accum,
+    pattern_manage__shfill_doesnt_need_path
 } pattern_manage_t;
 
 #define dev_t_proc_pattern_manage(proc, dev_t)\

Modified: trunk/gs/src/gxfill.c
===================================================================
--- trunk/gs/src/gxfill.c	2007-05-30 06:05:43 UTC (rev 8016)
+++ trunk/gs/src/gxfill.c	2007-05-31 17:25:52 UTC (rev 8017)
@@ -41,6 +41,7 @@
 #include "gxpaint.h"		/* for prototypes */
 #include "gxfdrop.h"
 #include "gxfill.h"
+#include "gxpath.h"
 #include "gsptype1.h"
 #include "gsptype2.h"
 #include "gxpcolor.h"
@@ -565,7 +566,7 @@
 		     gx_path * ppath, const gx_fill_params * params,
 		 const gx_device_color * pdevc, const gx_clip_path * pcpath)
 {
-    int code;
+    int code = 0;
 
     if (gx_dc_is_pattern2_color(pdevc) 
 	|| pdevc->type == &gx_dc_type_data_ht_colored
@@ -585,60 +586,49 @@
 	/*  We need a single clipping path here, because shadings and
 	    halftones don't take 2 paths. Compute the clipping path intersection.
 	*/
-	gx_clip_path cpath_intersection;
-	gx_path path_intersection;
+	gx_clip_path cpath_intersection, cpath_with_shading_bbox;
+	const gx_clip_path *pcpath1, *pcpath2;
+	gs_imager_state *pis_noconst = (gs_imager_state *)pis; /* Break const. */
 
-	gx_path_init_local(&path_intersection, pdev->memory);
-	gx_cpath_init_local_shared(&cpath_intersection, pcpath, pdev->memory);
-	code = gx_cpath_intersect_with_params(&cpath_intersection, ppath, params->rule, 
-		    (gs_imager_state *)pis, params);
+	if (ppath != NULL) {
+	    gx_cpath_init_local_shared(&cpath_intersection, pcpath, pdev->memory);
+	    code = gx_cpath_intersect_with_params(&cpath_intersection, ppath, params->rule, 
+			pis_noconst, params);
+	    pcpath1 = &cpath_intersection;
+	} else
+	    pcpath1 = pcpath;
+
+
+	pcpath2 = pcpath1;
+	if (code >= 0)
+	    code = gx_dc_pattern2_clip_with_bbox(pdevc, pdev, &cpath_with_shading_bbox, &pcpath1);
 	/* Do fill : */
 	if (code >= 0) {
-	    if (pdevc->type == &gx_dc_type_data_ht_colored || gx_dc_is_pattern1_color(pdevc)) {
-		const gx_rop_source_t *rs = NULL;
-		gx_device *dev;
-		gx_device_clip cdev;
-		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(&cpath_intersection, &clip_box);
-		gx_make_clip_path_device(&cdev, &cpath_intersection);
-		cdev.target = pdev;
-		dev = (gx_device *)&cdev;
-		(*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,
-			    cb.p.x, cb.p.y, cb.q.x - cb.p.x, cb.q.y - cb.p.y,
-			    dev, pis->log_op, rs);
-	    } else {
-		/* The shading fill algorithm fills an area restricted with a path,
-		   so we need to convert cpath into path.
-
-		   We can't set a clipping device here like we did for 
-		   gx_dc_type_data_ht_colored, because the shading itself
-		   may add another clipping with its BBox,
-		   which may be transformed into a parallelogram.
-		   We don't want two clipping devices chained consequently.
-		 */
-		if (params->rule != gx_rule_winding_number) {
-		    /* HACK : Rather cpath_intersection contains a valid path,
-		       it is not planarized to a simple winding path,
-		       so we can't use the contained path.
-		       Reset path_valid against using it.
-		    */
-		    cpath_intersection.path_valid = false;
-		}
-		code = gx_cpath_to_path(&cpath_intersection, &path_intersection);
-		if (code >= 0)
-		    code = gx_dc_pattern2_fill_path(pdevc, &path_intersection, NULL,  pdev);
-	    }
+	    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;
+	    (*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,
+			cb.p.x, cb.p.y, cb.q.x - cb.p.x, cb.q.y - cb.p.y,
+			dev, pis->log_op, rs);
 	}
-	/* Destruct local data and return :*/
-	gx_path_free(&path_intersection, "shading_fill_path_intersection");
-	gx_cpath_free(&cpath_intersection, "shading_fill_cpath_intersection");
+	if (ppath != NULL)
+	    gx_cpath_free(&cpath_intersection, "shading_fill_cpath_intersection");
+	if (pcpath1 != pcpath2)
+	    gx_cpath_free(&cpath_with_shading_bbox, "shading_fill_cpath_intersection");
     } else {
 	bool got_dc = false;
         vd_save;

Modified: trunk/gs/src/gximask.c
===================================================================
--- trunk/gs/src/gximask.c	2007-05-30 06:05:43 UTC (rev 8016)
+++ trunk/gs/src/gximask.c	2007-05-31 17:25:52 UTC (rev 8017)
@@ -60,23 +60,30 @@
 gx_image_fill_masked_end(gx_device *dev, gx_device *tdev, const gx_device_color *pdevc)
 {
     gx_device_cpath_accum *pcdev = (gx_device_cpath_accum *)dev;
-    gx_clip_path cpath;
+    gx_clip_path cpath, cpath_with_shading_bbox;
+    const gx_clip_path *pcpath1 = &cpath;
     gx_device_clip cdev;
     int code, code1;
 
     gx_cpath_init_local(&cpath, pcdev->memory);
     code = gx_cpath_accum_end(pcdev, &cpath);
-    gx_make_clip_path_device(&cdev, &cpath);
-    cdev.target = tdev;
-    (*dev_proc(&cdev, open_device)) ((gx_device *) & cdev);
-    code1 = gx_device_color_fill_rectangle(pdevc, 
-		pcdev->bbox.p.x, pcdev->bbox.p.y, 
-		pcdev->bbox.q.x - pcdev->bbox.p.x, 
-		pcdev->bbox.q.y - pcdev->bbox.p.y, 
-		(gx_device *)&cdev, lop_default, 0);
-    if (code == 0)
-	code = code1;
-    gx_device_retain((gx_device *)pcdev, false);
+    if (code >= 0)
+	code = gx_dc_pattern2_clip_with_bbox(pdevc, tdev, &cpath_with_shading_bbox, &pcpath1);
+    if (code >= 0) {
+	gx_make_clip_path_device(&cdev, pcpath1);
+	cdev.target = tdev;
+	(*dev_proc(&cdev, open_device)) ((gx_device *) & cdev);
+	code1 = gx_device_color_fill_rectangle(pdevc, 
+		    pcdev->bbox.p.x, pcdev->bbox.p.y, 
+		    pcdev->bbox.q.x - pcdev->bbox.p.x, 
+		    pcdev->bbox.q.y - pcdev->bbox.p.y, 
+		    (gx_device *)&cdev, lop_default, 0);
+	if (code == 0)
+	    code = code1;
+	gx_device_retain((gx_device *)pcdev, false);
+    }
+    if (pcpath1 == &cpath_with_shading_bbox)
+	gx_cpath_free(&cpath_with_shading_bbox, "s_image_cleanup");
     gx_cpath_free(&cpath, "s_image_cleanup");
     return code;
 }

Modified: trunk/gs/src/gxpath.h
===================================================================
--- trunk/gs/src/gxpath.h	2007-05-30 06:05:43 UTC (rev 8016)
+++ trunk/gs/src/gxpath.h	2007-05-31 17:25:52 UTC (rev 8017)
@@ -334,7 +334,8 @@
     gx_cpath_scale_exp2_shared(gx_clip_path *pcpath, int log2_scale_x,
 			       int log2_scale_y, bool list_shared,
 			       bool segments_shared),
-    gx_cpath_to_path(gx_clip_path *, gx_path *);
+    gx_cpath_to_path(gx_clip_path *, gx_path *),
+    gx_cpath_to_path_synthesize(const gx_clip_path * pcpath, gx_path * ppath);
 bool
     gx_cpath_inner_box(const gx_clip_path *, gs_fixed_rect *),
     gx_cpath_outer_box(const gx_clip_path *, gs_fixed_rect *),
@@ -345,7 +346,7 @@
 
 /* Enumerate a clipping path.  This interface does not copy the path. */
 /* However, it does write into the path's "visited" flags. */
-int gx_cpath_enum_init(gs_cpath_enum *, gx_clip_path *);
+int gx_cpath_enum_init(gs_cpath_enum *, const gx_clip_path *);
 int gx_cpath_enum_next(gs_cpath_enum *, gs_fixed_point[3]);		/* 0 when done */
 
 segment_notes

Modified: trunk/gs/src/lib.mak
===================================================================
--- trunk/gs/src/lib.mak	2007-05-30 06:05:43 UTC (rev 8016)
+++ trunk/gs/src/lib.mak	2007-05-31 17:25:52 UTC (rev 8017)
@@ -607,9 +607,10 @@
 	$(GLCC) $(GLO_)gxhldevc.$(OBJ) $(C_) $(GLSRC)gxhldevc.c
 
 $(GLOBJ)gxfill.$(OBJ) : $(GLSRC)gxfill.c $(GXERR)\
- $(gsstruct_h)\
+ $(gsstruct_h) $(gsfixed_h)\
  $(gxdcolor_h) $(gxdevice_h) $(gxfixed_h) $(gxhttile_h)\
- $(gxistate_h) $(gxpaint_h) $(gxfill_h) $(gxfdrop_h) $(gsptype1_h) $(gsptype2_h) $(gxpcolor_h)\
+ $(gxistate_h) $(gxpaint_h) $(gxfdrop_h) $(gxfill_h) $(gxpath_h)\
+ $(gsptype1_h) $(gsptype2_h) $(gxpcolor_h)\
  $(gzcpath_h) $(gzpath_h) $(gzspotan_h) $(gdevddrw_h) $(memory__h) $(stdint_) $(vdtrace_h)\
  $(gxfilltr_h) $(gxfillsl_h) $(gxfillts_h)
 	$(GLCC) $(GLO_)gxfill.$(OBJ) $(C_) $(GLSRC)gxfill.c



More information about the gs-cvs mailing list