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

leonardo at ghostscript.com leonardo at ghostscript.com
Tue Jun 5 14:10:17 PDT 2007


Author: leonardo
Date: 2007-06-05 14:10:17 -0700 (Tue, 05 Jun 2007)
New Revision: 8020

Modified:
   trunk/gs/src/devs.mak
   trunk/gs/src/gdevpdfd.c
   trunk/gs/src/gdevpdfi.c
   trunk/gs/src/gsptype2.c
   trunk/gs/src/gsshade.c
   trunk/gs/src/gsshade.h
   trunk/gs/src/gxcpath.c
   trunk/gs/src/gxfill.c
   trunk/gs/src/gxpath.h
Log:
Fix (shadings) : Optimize path manipulations for shading fill (continued 2).

DETAILS :

This is the 2nd step for the elimination of gs_shading_fill_path.
It excludes that function from high level devices.

After the last patch, ps2write is only device that calls gs_shading_fill_path
while converting a shading into an image.
This patch replaces that call with a call to gs_shading_do_fill_rectangle.

This patch also fixes the revision 8017 regression
with the change to gdevpdfi.c .

Minor changes :

1. lcvd_fill_rectangle_shifted_from_mdev appears to be same as lcvd_fill_rectangle_shifted.
   Removing the 1st one.

2. path_scale appears almost same as gx_path_scale_exp2_shared.
   Removing the 1st one.

3. In gdevpdfd.c, when the scale isn't dividing by 4,
   the old code chooses a smaller scale by X.
   The new code dies by Y for a better view.
   It may cause minor differences in raster.
   
4. We're not sure why lcvd_get_clipping_box_from_target was used sometimes.
   It looks incorrect. Replaced with lcvd_get_clipping_box_shifted_from_mdev. 

5. gx_cpath_scale_exp2_shared didn't scale list->xmin, list->xmax.

6. gx_cpath_copy is defined and not used.
   Saving it from a dead branch, because it may be useful in future.

EXPECTED DIFFERENCES :

Should fix pdfwrite rev 8017 regressions.


Modified: trunk/gs/src/devs.mak
===================================================================
--- trunk/gs/src/devs.mak	2007-06-05 15:53:48 UTC (rev 8019)
+++ trunk/gs/src/devs.mak	2007-06-05 21:10:17 UTC (rev 8020)
@@ -857,7 +857,7 @@
 $(GLOBJ)gdevpdfd.$(OBJ) : $(GLSRC)gdevpdfd.c $(math__h) $(memory__h)\
  $(gx_h) $(gxdevice_h) $(gxfixed_h) $(gxistate_h) $(gxpaint_h)\
  $(gxcoord_h) $(gxdevmem_h) $(gxcolor2_h) $(gxhldevc_h)\
- $(gsstate_h) $(gserrors_h) $(gsptype2_h)\
+ $(gsstate_h) $(gserrors_h) $(gsptype2_h) $(gsshade_h)\
  $(gzpath_h) $(gzcpath_h) $(gdevpdfx_h) $(gdevpdfg_h) $(gdevpdfo_h) $(gsutil_h)
 	$(GLCC) $(GLO_)gdevpdfd.$(OBJ) $(C_) $(GLSRC)gdevpdfd.c
 

Modified: trunk/gs/src/gdevpdfd.c
===================================================================
--- trunk/gs/src/gdevpdfd.c	2007-06-05 15:53:48 UTC (rev 8019)
+++ trunk/gs/src/gdevpdfd.c	2007-06-05 21:10:17 UTC (rev 8020)
@@ -27,6 +27,7 @@
 #include "gsstate.h"
 #include "gserrors.h"
 #include "gsptype2.h"
+#include "gsshade.h"
 #include "gzpath.h"
 #include "gzcpath.h"
 #include "gdevpdfx.h"
@@ -520,21 +521,6 @@
     return cvd->std_fill_rectangle((gx_device *)&cvd->mdev, 
 	x - cvd->mdev.mapped_x, y - cvd->mdev.mapped_y, width, height, color);
 }
-private int 
-lcvd_fill_rectangle_shifted_from_mdev(gx_device *dev, int x, int y, int width, int height, gx_color_index color)
-{
-    pdf_lcvd_t *cvd = (pdf_lcvd_t *)dev;
-
-    return cvd->std_fill_rectangle((gx_device *)&cvd->mdev, 
-	x - cvd->mdev.mapped_x, y - cvd->mdev.mapped_y, width, height, color);
-}
-private void 
-lcvd_get_clipping_box_from_target(gx_device *dev, gs_fixed_rect *pbox)
-{
-    gx_device_memory *mdev = (gx_device_memory *)dev;
-
-    (*dev_proc(mdev->target, get_clipping_box))(mdev->target, pbox);
-}
 private void
 lcvd_get_clipping_box_shifted_from_mdev(gx_device *dev, gs_fixed_rect *pbox)
 {
@@ -998,9 +984,9 @@
 	/* Type 3 images will write to the mask directly. */
 	dev_proc(&cvd->mdev, fill_rectangle) = (need_mask ? lcvd_fill_rectangle_shifted2 
 							  : lcvd_fill_rectangle_shifted);
-	dev_proc(&cvd->mdev, get_clipping_box) = lcvd_get_clipping_box_from_target;
+	dev_proc(&cvd->mdev, get_clipping_box) = lcvd_get_clipping_box_shifted_from_mdev;
     } else {
-	dev_proc(&cvd->mdev, fill_rectangle) = lcvd_fill_rectangle_shifted_from_mdev;
+	dev_proc(&cvd->mdev, fill_rectangle) = lcvd_fill_rectangle_shifted;
 	dev_proc(&cvd->mdev, get_clipping_box) = lcvd_get_clipping_box_shifted_from_mdev;
     }
     dev_proc(&cvd->mdev, pattern_manage) = lcvd_pattern_manage;
@@ -1024,28 +1010,6 @@
     }
 }
 
-private int
-path_scale(gx_path *path, double scalex, double scaley)
-{
-    segment *pseg = (segment *)path->first_subpath;
-
-    for (;pseg != NULL; pseg = pseg->next) {
-	pseg->pt.x = (fixed)floor(pseg->pt.x * scalex + 0.5);
-	pseg->pt.y = (fixed)floor(pseg->pt.y * scaley + 0.5);
-	if (pseg->type == s_curve) {
-	    curve_segment *s = (curve_segment *)pseg;
-
-	    s->p1.x = (fixed)floor(s->p1.x * scalex + 0.5);
-	    s->p1.y = (fixed)floor(s->p1.y * scaley + 0.5);
-	    s->p2.x = (fixed)floor(s->p2.x * scalex + 0.5);
-	    s->p2.y = (fixed)floor(s->p2.y * scaley + 0.5);
-	}
-    }
-    path->position.x = (fixed)floor(path->position.x * scalex + 0.5);
-    path->position.y = (fixed)floor(path->position.y * scaley + 0.5);
-    return 0;
-}
-
 /* ------ Driver procedures ------ */
 
 /* Fill a path. */
@@ -1110,7 +1074,8 @@
 	    gs_matrix m, save_ctm = ctm_only(pis), ms, msi, mm;
 	    gs_int_point rect_size;
 	    /* double scalex = 1.9, scaley = 1.4; debug purpose only. */
-	    double scale, scalex = 1.0, scaley = 1.0;
+	    double scale, scalex, scaley;
+	    int log2_scale_x = 0, log2_scale_y = 0;
 	    gx_drawing_color dc = *pdcolor;
 	    gs_pattern2_instance_t pi = *(gs_pattern2_instance_t *)dc.ccolor.pattern;
 	    gs_state *pgs = gs_state_copy(pi.saved, gs_state_memory(pi.saved));
@@ -1150,12 +1115,13 @@
 		   we prefer to deal only with integers being powers of 2
 		   in order to avoid possible distorsions when scaling paths.
 		*/
-		scalex = ceil(sqrt(scale));
-		scalex = scaley = 1 << ilog2((int)scalex);
-		if (scalex * scaley < scale)
-		    scalex *= 2;
-		if (scalex * scaley < scale)
-		    scaley *= 2;
+		log2_scale_x = log2_scale_y = ilog2((int)ceil(sqrt(scale)));
+		if ((double)(1 << log2_scale_x) * (1 << log2_scale_y) < scale)
+		    log2_scale_y++;
+		if ((double)(1 << log2_scale_x) * (1 << log2_scale_y) < scale)
+		    log2_scale_x++;
+		scalex = (double)(1 << log2_scale_x);
+		scaley = (double)(1 << log2_scale_y);
 		rect_size.x = (int)floor(rect_size.x / scalex + 0.5);
 		rect_size.y = (int)floor(rect_size.y / scaley + 0.5);
 		gs_make_scaling(1.0 / scalex, 1.0 / scaley, &ms);
@@ -1182,32 +1148,11 @@
 	    }
 	    pdf_put_matrix(pdev, NULL, &cvd.m, " cm q\n");
 	    cvd.write_matrix = false;
-	    if (code >= 0) {
-		/* See gx_default_fill_path. */
-		gx_clip_path cpath_intersection;
-		gx_path path_intersection, path1, *p = &path_intersection;
-
-		gx_path_init_local(&path_intersection, pdev->memory);
-		gx_path_init_local(&path1, pdev->memory);
-		gx_cpath_init_local_shared(&cpath_intersection, pcpath, pdev->memory);
-		if ((code = gx_cpath_intersect(&cpath_intersection, ppath, params->rule, (gs_imager_state *)pis)) >= 0)
-		    code = gx_cpath_to_path(&cpath_intersection, &path_intersection);
-		if (code >= 0 && scale > 1) {
-		    code = gx_path_copy(&path_intersection, &path1);	
-		    if (code > 0) {
-			p = &path1;
-			code = path_scale(&path1, scalex, scaley);
-		    }
-		}
-		if (code >= 0)
-		    code = gx_dc_pattern2_fill_path(&dc, p, NULL, (gx_device *)&cvd.mdev);
-		gx_path_free(&path_intersection, "gdev_pdf_fill_path");
-		gx_path_free(&path1, "gdev_pdf_fill_path");
-		gx_cpath_free(&cpath_intersection, "gdev_pdf_fill_path");
-	    }
-	    if (code >= 0) {
+	    if (code >= 0)
+		code = gs_shading_do_fill_rectangle(pi.template.Shading,
+		     NULL, (gx_device *)&cvd.mdev, (gs_imager_state *)pgs, !pi.shfill);
+	    if (code >= 0)
 		code = pdf_dump_converted_image(pdev, &cvd);
-	    }
 	    stream_puts(pdev->strm, "Q Q\n");
 	    pdf_remove_masked_image_converter(pdev, &cvd, need_mask);
 	    gs_setmatrix((gs_state *)pis, &save_ctm);

Modified: trunk/gs/src/gdevpdfi.c
===================================================================
--- trunk/gs/src/gdevpdfi.c	2007-06-05 15:53:48 UTC (rev 8019)
+++ trunk/gs/src/gdevpdfi.c	2007-06-05 21:10:17 UTC (rev 8020)
@@ -1390,6 +1390,8 @@
 	    return 0;
 	case pattern_manage__is_cpath_accum:
 	    return 0;
+	case pattern_manage__shfill_doesnt_need_path:
+	    return 0; /* gdev_pdf_fill_path still does need a path. */
     }
     return_error(gs_error_unregistered);
 }

Modified: trunk/gs/src/gsptype2.c
===================================================================
--- trunk/gs/src/gsptype2.c	2007-06-05 15:53:48 UTC (rev 8019)
+++ trunk/gs/src/gsptype2.c	2007-06-05 21:10:17 UTC (rev 8020)
@@ -331,7 +331,7 @@
     else {
 	gs_state *pis = pinst->saved;
 
-	return shading_path_add_box(ppath, &psh->params.BBox, &pis->ctm);
+	return gs_shading_path_add_box(ppath, &psh->params.BBox, &pis->ctm);
     }
 }
 

Modified: trunk/gs/src/gsshade.c
===================================================================
--- trunk/gs/src/gsshade.c	2007-06-05 15:53:48 UTC (rev 8019)
+++ trunk/gs/src/gsshade.c	2007-06-05 21:10:17 UTC (rev 8020)
@@ -418,7 +418,7 @@
 
 /* Add a user-space rectangle to a path. */
 int
-shading_path_add_box(gx_path *ppath, const gs_rect *pbox,
+gs_shading_path_add_box(gx_path *ppath, const gs_rect *pbox,
 		     const gs_matrix_fixed *pmat)
 {
     gs_fixed_point pt;
@@ -527,7 +527,7 @@
 		}
 		code = gx_cpath_from_rectangle(path_clip, &path_box);
 		if (code >= 0) {
-		    code = shading_path_add_box(box_path, &psh->params.BBox, pmat);
+		    code = gs_shading_path_add_box(box_path, &psh->params.BBox, pmat);
 		    if (code == gs_error_limitcheck) {
 			/* Ignore huge BBox - bug 689027. */
 			code = 0;

Modified: trunk/gs/src/gsshade.h
===================================================================
--- trunk/gs/src/gsshade.h	2007-06-05 15:53:48 UTC (rev 8019)
+++ trunk/gs/src/gsshade.h	2007-06-05 21:10:17 UTC (rev 8020)
@@ -253,6 +253,10 @@
 #  define gx_path_DEFINED
 typedef struct gx_path_s gx_path;
 #endif
+#ifndef gs_matrix_fixed_DEFINED
+#define gs_matrix_fixed_DEFINED
+typedef struct gs_matrix_fixed_s gs_matrix_fixed;
+#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,
@@ -263,4 +267,8 @@
 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);
+
+int gs_shading_path_add_box(gx_path *ppath, const gs_rect *pbox,
+		     const gs_matrix_fixed *pmat);
+
 #endif /* gsshade_INCLUDED */

Modified: trunk/gs/src/gxcpath.c
===================================================================
--- trunk/gs/src/gxcpath.c	2007-06-05 15:53:48 UTC (rev 8019)
+++ trunk/gs/src/gxcpath.c	2007-06-05 21:10:17 UTC (rev 8020)
@@ -722,6 +722,8 @@
 		SCALE_V(ymax, log2_scale_y);
 #undef SCALE_V
 	    }
+	list->xmin = arith_rshift(list->xmin, -log2_scale_x);
+	list->xmax = arith_rshift(list->xmax, -log2_scale_x);
     }
     pcpath->id = gs_next_ids(pcpath->path.memory, 1);	/* path changed => change id */
     return 0;
@@ -1024,6 +1026,40 @@
     return false;
 }
 
+int
+gx_cpath_copy(const gx_clip_path * from, gx_clip_path * pcpath)
+{   /* *pcpath must be initialized. */
+    gx_clip_rect *r, *s;
+    gx_clip_list *l = &pcpath->rect_list->list;
+
+    pcpath->path_valid = false;
+    /* NOTE: pcpath->path still contains the old path. */
+    if (pcpath->path_list)
+	rc_decrement(pcpath->path_list, "gx_cpath_copy");
+    pcpath->path_list = NULL;
+    pcpath->rule = from->rule;
+    pcpath->outer_box = from->outer_box;
+    pcpath->inner_box = from->inner_box;
+    l->single = from->rect_list->list.single;
+    for (r = from->rect_list->list.head; r != NULL; r = r->next) {
+	s = gs_alloc_struct(from->rect_list->rc.memory, gx_clip_rect, &st_clip_rect, "gx_cpath_copy");
+	if (s == NULL)
+	    return_error(gs_error_VMerror);
+	*s = *r;
+	s->next = NULL;
+	if (l->tail) {
+	    s->prev = l->tail;
+	    l->tail->next = s;
+	} else {
+	    l->head = s;
+	    s->prev = NULL;
+	}
+	l->tail = s;
+    }
+    l->count = from->rect_list->list.count;
+    return 0;
+}
+
 /* ------ Debugging printout ------ */
 
 #ifdef DEBUG

Modified: trunk/gs/src/gxfill.c
===================================================================
--- trunk/gs/src/gxfill.c	2007-06-05 15:53:48 UTC (rev 8019)
+++ trunk/gs/src/gxfill.c	2007-06-05 21:10:17 UTC (rev 8020)
@@ -557,6 +557,20 @@
     return code;
 }
 
+private int
+pass_shading_area_through_clip_path_device(gx_device * pdev, const gs_imager_state * pis,
+		     gx_path * ppath, const gx_fill_params * params,
+		 const gx_device_color * pdevc, const gx_clip_path * pcpath)
+{
+    if (pdevc == NULL) {
+	gx_device_clip *cdev = (gx_device_clip *)pdev;
+
+	return dev_proc(cdev->target, fill_path)(cdev->target, pis, ppath, params, pdevc, pcpath);
+    }
+    /* We know that tha clip path device implements fill_path with default proc. */
+    return gx_default_fill_path(pdev, pis, ppath, params, pdevc, pcpath);
+}
+
 /*
  * Fill a path.  This is the default implementation of the driver
  * fill_path procedure.
@@ -591,14 +605,14 @@
 	gs_imager_state *pis_noconst = (gs_imager_state *)pis; /* Break const. */
 
 	if (ppath != NULL) {
-	    gx_cpath_init_local_shared(&cpath_intersection, pcpath, pdev->memory);
+	    code = gx_cpath_init_local_shared(&cpath_intersection, pcpath, pdev->memory);
+	    if (code < 0)
+		return code;
 	    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);
@@ -616,6 +630,9 @@
 	    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);

Modified: trunk/gs/src/gxpath.h
===================================================================
--- trunk/gs/src/gxpath.h	2007-06-05 15:53:48 UTC (rev 8019)
+++ trunk/gs/src/gxpath.h	2007-06-05 21:10:17 UTC (rev 8020)
@@ -343,6 +343,7 @@
 				fixed, fixed);
 const gs_fixed_rect *cpath_is_rectangle(const gx_clip_path * pcpath);
 bool gx_cpath_rect_visible(gx_clip_path * pcpath, gs_int_rect *prect);
+int gx_cpath_copy(const gx_clip_path * from, gx_clip_path * pcpath);
 
 /* Enumerate a clipping path.  This interface does not copy the path. */
 /* However, it does write into the path's "visited" flags. */



More information about the gs-cvs mailing list