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

leonardo at ghostscript.com leonardo at ghostscript.com
Thu Jul 5 23:00:18 PDT 2007


Author: leonardo
Date: 2007-07-05 23:00:17 -0700 (Thu, 05 Jul 2007)
New Revision: 8108

Modified:
   trunk/gs/src/gxpcopy.c
Log:
Fix : A wrong path filling.

DETAILS :

Bug 689317 "A wrong rendering of a path".

gx_path_merge_contacting_contours didn't account implicit closepath
with non-zero length. Due to that the filling algorithm could
recieve a path with a missed segment. It caused some areas
are missed while filling.

This fix is important for restoring high level clist objects,
which were disabled with rev 5056 change to gdevprn.c .

This fix inserts a line segments at the place of implicit closepath
before merging contours.

Minor change : improving documentation about
gx_path_merge_contacting_contours. 

EXPECTED DIFFERENCES :

None.


Modified: trunk/gs/src/gxpcopy.c
===================================================================
--- trunk/gs/src/gxpcopy.c	2007-07-05 19:04:29 UTC (rev 8107)
+++ trunk/gs/src/gxpcopy.c	2007-07-06 06:00:17 UTC (rev 8108)
@@ -724,6 +724,8 @@
 {
     /* Now this is a simplified algorithm,
        which merge only contours by a common quazi-vertical line. */
+    /* Note the merged contour is not equivalent to sum of original contours,
+       because we ignore small coordinate differences within fixed_epsilon. */
     int window = 5/* max spot holes */ * 6/* segments per subpath */;
     subpath *sp0 = ppath->segments->contents.subpath_first;
 
@@ -735,7 +737,7 @@
 	
 	for (count = 0; sp1 != NULL && count < window; sp1 = spnext, count++) {
 	    segment *sp1last = sp1->last;
-	    segment *sc0, *sc1;
+	    segment *sc0, *sc1, *old_first;
 		
 	    spnext = (subpath *)sp1last->next;
 	    if (find_contacting_segments(sp0, sp0last, sp1, sp1last, &sc0, &sc1)) {
@@ -745,13 +747,33 @@
 		    sp1last->next->prev = sp1->prev;
 		sp1->prev = 0;
 		sp1last->next = 0;
-		/* Change 'closepath' of the subpath 1 to a line (maybe degenerate) : */
-		if (sp1last->type == s_line_close)
+		old_first = sp1->next;
+		/* sp1 is not longer in use. Move subpath_current from it for safe removing : */
+		if (ppath->segments->contents.subpath_current == sp1) {
+		    ppath->segments->contents.subpath_current = sp1p;
+		}
+		if (sp1last->type == s_line_close) {
+		    /* Change 'closepath' of the subpath 1 to a line (maybe degenerate) : */
 		    sp1last->type = s_line;
+		    /* sp1 is not longer in use. Free it : */
+		    gs_free_object(gs_memory_stable(ppath->memory), sp1, "gx_path_merge_contacting_contours");
+		} else if (sp1last->pt.x == sp1->pt.x && sp1last->pt.y == sp1->pt.y) {
+		    /* Implicit closepath with zero length. Don't need a new segment. */
+		    /* sp1 is not longer in use. Free it : */
+		    gs_free_object(gs_memory_stable(ppath->memory), sp1, "gx_path_merge_contacting_contours");
+		} else {
+		    /* Insert the closing line segment. */
+		    /* sp1 is not longer in use. Convert it to the line segment : */
+		    sp1->type = s_line;
+		    sp1last->next = (segment *)sp1;
+		    sp1->next = NULL;
+		    sp1->prev = sp1last;
+		    sp1->last = NULL; /* Safety for garbager. */
+		    sp1last = (segment *)sp1;
+		}
+		sp1 = 0; /* Safety. */
 		/* Rotate the subpath 1 to sc1 : */
-		{   segment *old_first = sp1->next;
-
-		    /* Detach s_start and make a loop : */
+		{   /* Detach s_start and make a loop : */
 		    sp1last->next = old_first;
 		    old_first->prev = sp1last;
 		    /* Unlink before sc1 : */



More information about the gs-cvs mailing list