[cairo-commit] 11 commits - src/cairo-path-stroke.c test/dash-caps-joins-ref.png test/dash-scale-ref.png test/dash-state.c test/dash-state-ps-argb32-ref.png test/dash-state-ref.png test/degenerate-path.c test/degenerate-path-ps-argb32-ref.png test/degenerate-path-ref.png test/degenerate-path-rgb24-ref.png test/leaky-dash-ps-argb32-ref.png test/leaky-dash-ref.png test/Makefile.am

Jeff Muizelaar jrmuizel at kemper.freedesktop.org
Mon Feb 19 13:09:07 PST 2007


 src/cairo-path-stroke.c                |  167 ++++++++++++++++-----------------
 test/Makefile.am                       |    3 
 test/dash-caps-joins-ref.png           |binary
 test/dash-scale-ref.png                |binary
 test/dash-state-ps-argb32-ref.png      |binary
 test/dash-state-ref.png                |binary
 test/dash-state.c                      |   72 ++++++++++++++
 test/degenerate-path-ps-argb32-ref.png |binary
 test/degenerate-path-ref.png           |binary
 test/degenerate-path-rgb24-ref.png     |binary
 test/degenerate-path.c                 |   23 ++++
 test/leaky-dash-ps-argb32-ref.png      |binary
 test/leaky-dash-ref.png                |binary
 13 files changed, 177 insertions(+), 88 deletions(-)

New commits:
diff-tree 0fcd6cfe0edff25ad3d11af056ba611bd8d9d8c8 (from 89010db3ad3ce0a9afaf28fd313da86ebc864c7c)
Author: Jeff Smith <whydoubt at yahoo.com>
Date:   Mon Feb 19 16:06:57 2007 -0500

    Clean up some inconsistent spacing in the stroking code

diff --git a/src/cairo-path-stroke.c b/src/cairo-path-stroke.c
index 7743086..958b95a 100644
--- a/src/cairo-path-stroke.c
+++ b/src/cairo-path-stroke.c
@@ -696,13 +696,13 @@ _cairo_stroker_line_to_dashed (void *clo
 
     cairo_matrix_transform_distance (stroker->ctm_inverse, &dx, &dy);
 
-    mag = sqrt (dx *dx + dy * dy);
+    mag = sqrt (dx * dx + dy * dy);
     remain = mag;
     fd1 = *p1;
     while (remain) {
 	step_length = MIN (stroker->dash_remain, remain);
 	remain -= step_length;
-        dx2 = dx * (mag - remain)/mag;
+	dx2 = dx * (mag - remain)/mag;
 	dy2 = dy * (mag - remain)/mag;
 	cairo_matrix_transform_distance (stroker->ctm, &dx2, &dy2);
 	fd2.x = _cairo_fixed_from_double (dx2) + p1->x;
diff-tree 89010db3ad3ce0a9afaf28fd313da86ebc864c7c (from adb573d0bafd7b555bda0effcbd94b9144981ad6)
Author: Jeff Smith <whydoubt at yahoo.com>
Date:   Mon Feb 19 16:06:57 2007 -0500

    Add or reword several comments in the stroking code

diff --git a/src/cairo-path-stroke.c b/src/cairo-path-stroke.c
index abdf2bf..7743086 100644
--- a/src/cairo-path-stroke.c
+++ b/src/cairo-path-stroke.c
@@ -603,6 +603,7 @@ _cairo_stroker_move_to (void *closure, c
     cairo_status_t status;
     cairo_stroker_t *stroker = closure;
 
+    /* Cap the start and end of the previous sub path as needed */
     status = _cairo_stroker_add_caps (stroker);
     if (status)
 	return status;
@@ -649,10 +650,12 @@ _cairo_stroker_line_to (void *closure, c
 	return status;
 
     if (stroker->has_current_face) {
+	/* Join with final face from previous segment */
 	status = _cairo_stroker_join (stroker, &stroker->current_face, &start);
 	if (status)
 	    return status;
     } else if (!stroker->has_first_face) {
+	/* Save sub path's first face in case needed for closing join */
 	stroker->first_face = start;
 	stroker->has_first_face = TRUE;
     }
@@ -704,9 +707,7 @@ _cairo_stroker_line_to_dashed (void *clo
 	cairo_matrix_transform_distance (stroker->ctm, &dx2, &dy2);
 	fd2.x = _cairo_fixed_from_double (dx2) + p1->x;
 	fd2.y = _cairo_fixed_from_double (dy2) + p1->y;
-	/*
-	 * XXX simplify this case analysis
-	 */
+
 	if (stroker->dash_on) {
 	    status = _cairo_stroker_add_sub_edge (stroker, &fd1, &fd2, &slope, &sub_start, &sub_end);
 	    if (status)
@@ -730,9 +731,7 @@ _cairo_stroker_line_to_dashed (void *clo
 	    }
 
 	    if (remain) {
-		/*
-		 * Cap if not at end of segment
-		 */
+		/* Cap dash end if not at end of segment */
 		status = _cairo_stroker_add_trailing_cap (stroker, &sub_end);
 		if (status)
 		    return status;
@@ -921,10 +920,12 @@ _cairo_stroker_close_path (void *closure
 	return status;
 
     if (stroker->has_first_face && stroker->has_current_face) {
+	/* Join first and final faces of sub path */
 	status = _cairo_stroker_join (stroker, &stroker->current_face, &stroker->first_face);
 	if (status)
 	    return status;
     } else {
+	/* Cap the start and end of the sub path as needed */
 	status = _cairo_stroker_add_caps (stroker);
 	if (status)
 	    return status;
@@ -989,6 +990,7 @@ _cairo_path_fixed_stroke_to_traps (cairo
     if (status)
 	goto BAIL;
 
+    /* Cap the start and end of the final sub path as needed */
     status = _cairo_stroker_add_caps (&stroker);
 
 BAIL:
diff-tree adb573d0bafd7b555bda0effcbd94b9144981ad6 (from fb29fddd40aeb4c2f1a42f88eddec5c06adf0583)
Author: Jeff Smith <whydoubt at yahoo.com>
Date:   Mon Feb 19 16:06:57 2007 -0500

    Minor changes to shorten the stroking code

diff --git a/src/cairo-path-stroke.c b/src/cairo-path-stroke.c
index e830649..abdf2bf 100644
--- a/src/cairo-path-stroke.c
+++ b/src/cairo-path-stroke.c
@@ -652,11 +652,9 @@ _cairo_stroker_line_to (void *closure, c
 	status = _cairo_stroker_join (stroker, &stroker->current_face, &start);
 	if (status)
 	    return status;
-    } else {
-	if (!stroker->has_first_face) {
-	    stroker->first_face = start;
-	    stroker->has_first_face = TRUE;
-	}
+    } else if (!stroker->has_first_face) {
+	stroker->first_face = start;
+	stroker->has_first_face = TRUE;
     }
     stroker->current_face = end;
     stroker->has_current_face = TRUE;
@@ -699,17 +697,13 @@ _cairo_stroker_line_to_dashed (void *clo
     remain = mag;
     fd1 = *p1;
     while (remain) {
-	step_length = stroker->dash_remain;
-	if (step_length > remain)
-	    step_length = remain;
+	step_length = MIN (stroker->dash_remain, remain);
 	remain -= step_length;
         dx2 = dx * (mag - remain)/mag;
 	dy2 = dy * (mag - remain)/mag;
 	cairo_matrix_transform_distance (stroker->ctm, &dx2, &dy2);
-	fd2.x = _cairo_fixed_from_double (dx2);
-	fd2.y = _cairo_fixed_from_double (dy2);
-	fd2.x += p1->x;
-	fd2.y += p1->y;
+	fd2.x = _cairo_fixed_from_double (dx2) + p1->x;
+	fd2.y = _cairo_fixed_from_double (dy2) + p1->y;
 	/*
 	 * XXX simplify this case analysis
 	 */
@@ -808,11 +802,9 @@ _cairo_stroker_curve_to (void *closure,
 	status = _cairo_stroker_join (stroker, &stroker->current_face, &start);
 	if (status)
 	    return status;
-    } else {
-	if (!stroker->has_first_face) {
-	    stroker->first_face = start;
-	    stroker->has_first_face = TRUE;
-	}
+    } else if (!stroker->has_first_face) {
+	stroker->first_face = start;
+	stroker->has_first_face = TRUE;
     }
     stroker->current_face = end;
     stroker->has_current_face = TRUE;
diff-tree fb29fddd40aeb4c2f1a42f88eddec5c06adf0583 (from afd5f92195335a88d7c1ff181a1bd03ca01b424f)
Author: Jeff Muizelaar <jrmuizel at uwaterloo.ca>
Date:   Mon Feb 19 16:06:57 2007 -0500

    Rename tmp to step_length because that is what it actually is.

diff --git a/src/cairo-path-stroke.c b/src/cairo-path-stroke.c
index 1c835b9..e830649 100644
--- a/src/cairo-path-stroke.c
+++ b/src/cairo-path-stroke.c
@@ -674,7 +674,7 @@ _cairo_stroker_line_to_dashed (void *clo
 {
     cairo_status_t status = CAIRO_STATUS_SUCCESS;
     cairo_stroker_t *stroker = closure;
-    double mag, remain, tmp = 0;
+    double mag, remain, step_length = 0;
     double dx, dy;
     double dx2, dy2;
     cairo_point_t fd1, fd2;
@@ -699,10 +699,10 @@ _cairo_stroker_line_to_dashed (void *clo
     remain = mag;
     fd1 = *p1;
     while (remain) {
-	tmp = stroker->dash_remain;
-	if (tmp > remain)
-	    tmp = remain;
-	remain -= tmp;
+	step_length = stroker->dash_remain;
+	if (step_length > remain)
+	    step_length = remain;
+	remain -= step_length;
         dx2 = dx * (mag - remain)/mag;
 	dy2 = dy * (mag - remain)/mag;
 	cairo_matrix_transform_distance (stroker->ctm, &dx2, &dy2);
@@ -755,7 +755,7 @@ _cairo_stroker_line_to_dashed (void *clo
 		stroker->has_current_face = FALSE;
 	    }
 	}
-	_cairo_stroker_step_dash (stroker, tmp);
+	_cairo_stroker_step_dash (stroker, step_length);
 	fd1 = fd2;
     }
 
diff-tree afd5f92195335a88d7c1ff181a1bd03ca01b424f (from 78ae474d96b48ccba3d18dc26c416ebd6daab502)
Author: Jeff Muizelaar <jrmuizel at uwaterloo.ca>
Date:   Mon Feb 19 16:06:57 2007 -0500

    Fix several issues with dashed stroking code, particularly 'leaky-dash'
    
    Adds some state, 'dash_starts_on', to keep track of whether a dashed path
    starts with dash_on or not. This fixes the 'leaky-dash' bug (#4863) and
    some other degenerate cases. The new version is, in my opinion,
    considerably cleaner and more understandable than the old code.
    
    Finally, the rewrite changes the behaviour of dashing to add degenerate
    caps around corners that start at the same place as a dash begins. This
    matches the behaviour seen in acroread.
    
    This rewrite is based on an initial rewrite done by Jeff Smith.

diff --git a/src/cairo-path-stroke.c b/src/cairo-path-stroke.c
index acf733b..1c835b9 100644
--- a/src/cairo-path-stroke.c
+++ b/src/cairo-path-stroke.c
@@ -62,6 +62,7 @@ typedef struct cairo_stroker {
     cairo_bool_t dashed;
     unsigned int dash_index;
     cairo_bool_t dash_on;
+    cairo_bool_t dash_starts_on;
     double dash_remain;
 } cairo_stroker_t;
 
@@ -130,7 +131,7 @@ _cairo_stroker_start_dash (cairo_stroker
     }
     stroker->dashed = TRUE;
     stroker->dash_index = i;
-    stroker->dash_on = on;
+    stroker->dash_on = stroker->dash_starts_on = on;
     stroker->dash_remain = stroker->style->dash[i] - offset;
 }
 
@@ -673,17 +674,16 @@ _cairo_stroker_line_to_dashed (void *clo
 {
     cairo_status_t status = CAIRO_STATUS_SUCCESS;
     cairo_stroker_t *stroker = closure;
-    double mag, remain, tmp;
+    double mag, remain, tmp = 0;
     double dx, dy;
     double dx2, dy2;
     cairo_point_t fd1, fd2;
-    cairo_bool_t first = TRUE;
     cairo_stroke_face_t sub_start, sub_end;
     cairo_point_t *p1 = &stroker->current_point;
     cairo_point_t *p2 = point;
     cairo_slope_t slope;
 
-    stroker->has_initial_sub_path = stroker->dash_on;
+    stroker->has_initial_sub_path = stroker->dash_starts_on;
 
     if (p1->x == p2->x && p1->y == p2->y)
 	return CAIRO_STATUS_SUCCESS;
@@ -717,35 +717,24 @@ _cairo_stroker_line_to_dashed (void *clo
 	    status = _cairo_stroker_add_sub_edge (stroker, &fd1, &fd2, &slope, &sub_start, &sub_end);
 	    if (status)
 		return status;
-	    if (!first) {
-		/*
-		 * Not first dash in this segment, cap start
-		 */
-		status = _cairo_stroker_add_leading_cap (stroker, &sub_start);
+
+	    if (stroker->has_current_face) {
+		/* Join with final face from previous segment */
+		status = _cairo_stroker_join (stroker, &stroker->current_face, &sub_start);
+		stroker->has_current_face = FALSE;
 		if (status)
 		    return status;
+	    } else if (!stroker->has_first_face && stroker->dash_starts_on) {
+		/* Save sub path's first face in case needed for closing join */
+		stroker->first_face = sub_start;
+		stroker->has_first_face = TRUE;
 	    } else {
-		/*
-		 * First in this segment, join to any current_face, else
-		 * if at start of sub-path, mark position, else
-		 * cap
-		 */
-		if (stroker->has_current_face) {
-		    status = _cairo_stroker_join (stroker, &stroker->current_face, &sub_start);
-		    if (status)
-			return status;
-		} else {
-		    if (!stroker->has_first_face) {
-			stroker->first_face = sub_start;
-			stroker->has_first_face = TRUE;
-		    } else {
-			status = _cairo_stroker_add_leading_cap (stroker, &sub_start);
-			if (status)
-			    return status;
-		    }
-		}
-		stroker->has_initial_sub_path = TRUE;
+		/* Cap dash start if not connecting to a previous segment */
+		status = _cairo_stroker_add_leading_cap (stroker, &sub_start);
+		if (status)
+		    return status;
 	    }
+
 	    if (remain) {
 		/*
 		 * Cap if not at end of segment
@@ -754,31 +743,35 @@ _cairo_stroker_line_to_dashed (void *clo
 		if (status)
 		    return status;
 	    } else {
-		/*
-		 * Mark previous line face and fix up next time
-		 * through
-		 */
 		stroker->current_face = sub_end;
 		stroker->has_current_face = TRUE;
 	    }
 	} else {
-	    /*
-	     * If starting with off dash, check previous face
-	     * and cap if necessary
-	     */
-	    if (first) {
-		if (stroker->has_current_face) {
-		    status = _cairo_stroker_add_trailing_cap (stroker, &stroker->current_face);
-		    if (status)
-			return status;
-		}
-	    }
-	    if (!remain)
+	    if (stroker->has_current_face) {
+		/* Cap final face from previous segment */
+		status = _cairo_stroker_add_trailing_cap (stroker, &stroker->current_face);
+		if (status)
+		    return status;
 		stroker->has_current_face = FALSE;
+	    }
 	}
 	_cairo_stroker_step_dash (stroker, tmp);
 	fd1 = fd2;
-	first = FALSE;
+    }
+
+    if (stroker->dash_on && !stroker->has_current_face) {
+	/* This segment ends on a transition to dash_on, compute a new face
+	 * and add cap for the begining of the next dash_on step.
+	 *
+	 * Note: this will create a degenerate cap if this is not the last line
+	 * in the path. Whether this behaviour is desirable or not is debatable.
+	 * On one side these degnerate caps can not be reproduced with regular path stroking.
+	 * On the other side Acroread 7 also produces the degenerate caps. */
+	_compute_face (point, &slope, stroker, &stroker->current_face);
+	stroker->has_current_face = TRUE;
+	status = _cairo_stroker_add_leading_cap (stroker, &stroker->current_face);
+	if (status)
+	    return status;
     }
 
     stroker->current_point = *point;
diff --git a/test/Makefile.am b/test/Makefile.am
index 18ba2ac..7eefc32 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -360,7 +360,6 @@ big-trap			\
 extend-reflect			\
 filter-nearest-offset		\
 ft-text-vertical-layout-type1	\
-leaky-dash			\
 long-lines			\
 rotate-image-surface-paint	\
 self-intersecting		\
diff --git a/test/dash-caps-joins-ref.png b/test/dash-caps-joins-ref.png
index ec1f2f7..15a0679 100644
Binary files a/test/dash-caps-joins-ref.png and b/test/dash-caps-joins-ref.png differ
diff --git a/test/dash-scale-ref.png b/test/dash-scale-ref.png
index cba93aa..60aab2f 100644
Binary files a/test/dash-scale-ref.png and b/test/dash-scale-ref.png differ
diff --git a/test/leaky-dash-ps-argb32-ref.png b/test/leaky-dash-ps-argb32-ref.png
new file mode 100644
index 0000000..93b8640
Binary files /dev/null and b/test/leaky-dash-ps-argb32-ref.png differ
diff --git a/test/leaky-dash-ref.png b/test/leaky-dash-ref.png
index e030f6c..87facc5 100644
Binary files a/test/leaky-dash-ref.png and b/test/leaky-dash-ref.png differ
diff-tree 78ae474d96b48ccba3d18dc26c416ebd6daab502 (from 9f3fb4f753eabc84f19d808df64a718991269670)
Author: Jeff Muizelaar <jrmuizel at uwaterloo.ca>
Date:   Mon Feb 19 16:06:56 2007 -0500

    Rename has_sub_path to has_initial_sub_path
    
    has_initial_sub_path more accurately describes the condition we want to
    track. This flag is used to indicate when an initial sub_path needs capping
    but has no associated slope and thus no associated faces.

diff --git a/src/cairo-path-stroke.c b/src/cairo-path-stroke.c
index cb15f5a..acf733b 100644
--- a/src/cairo-path-stroke.c
+++ b/src/cairo-path-stroke.c
@@ -51,7 +51,7 @@ typedef struct cairo_stroker {
     cairo_point_t current_point;
     cairo_point_t first_point;
 
-    cairo_bool_t has_sub_path;
+    cairo_bool_t has_initial_sub_path;
 
     cairo_bool_t has_current_face;
     cairo_stroke_face_t current_face;
@@ -167,7 +167,7 @@ _cairo_stroker_init (cairo_stroker_t		*s
 
     stroker->has_current_face = FALSE;
     stroker->has_first_face = FALSE;
-    stroker->has_sub_path = FALSE;
+    stroker->has_initial_sub_path = FALSE;
 
     if (stroker->style->dash)
 	_cairo_stroker_start_dash (stroker);
@@ -466,7 +466,7 @@ _cairo_stroker_add_caps (cairo_stroker_t
 {
     cairo_status_t status;
     /* check for a degenerative sub_path */
-    if (stroker->has_sub_path
+    if (stroker->has_initial_sub_path
 	&& !stroker->has_first_face
 	&& !stroker->has_current_face
 	&& stroker->style->line_cap == CAIRO_LINE_JOIN_ROUND)
@@ -611,7 +611,7 @@ _cairo_stroker_move_to (void *closure, c
 
     stroker->has_first_face = FALSE;
     stroker->has_current_face = FALSE;
-    stroker->has_sub_path = FALSE;
+    stroker->has_initial_sub_path = FALSE;
 
     return CAIRO_STATUS_SUCCESS;
 }
@@ -636,7 +636,7 @@ _cairo_stroker_line_to (void *closure, c
     cairo_point_t *p2 = point;
     cairo_slope_t slope;
 
-    stroker->has_sub_path = TRUE;
+    stroker->has_initial_sub_path = TRUE;
 
     if (p1->x == p2->x && p1->y == p2->y)
 	return CAIRO_STATUS_SUCCESS;
@@ -683,7 +683,7 @@ _cairo_stroker_line_to_dashed (void *clo
     cairo_point_t *p2 = point;
     cairo_slope_t slope;
 
-    stroker->has_sub_path = stroker->dash_on;
+    stroker->has_initial_sub_path = stroker->dash_on;
 
     if (p1->x == p2->x && p1->y == p2->y)
 	return CAIRO_STATUS_SUCCESS;
@@ -744,7 +744,7 @@ _cairo_stroker_line_to_dashed (void *clo
 			    return status;
 		    }
 		}
-		stroker->has_sub_path = TRUE;
+		stroker->has_initial_sub_path = TRUE;
 	    }
 	    if (remain) {
 		/*
@@ -945,7 +945,7 @@ _cairo_stroker_close_path (void *closure
 	    return status;
     }
 
-    stroker->has_sub_path = FALSE;
+    stroker->has_initial_sub_path = FALSE;
     stroker->has_first_face = FALSE;
     stroker->has_current_face = FALSE;
 
diff-tree 9f3fb4f753eabc84f19d808df64a718991269670 (from a1a4d6966e1d9c8ccf84c9972a4f9560553948f6)
Author: Jeff Muizelaar <jrmuizel at uwaterloo.ca>
Date:   Mon Feb 19 16:06:56 2007 -0500

    Add a comment about the point choice when capping degenerate paths

diff --git a/src/cairo-path-stroke.c b/src/cairo-path-stroke.c
index 4827ab0..cb15f5a 100644
--- a/src/cairo-path-stroke.c
+++ b/src/cairo-path-stroke.c
@@ -474,6 +474,9 @@ _cairo_stroker_add_caps (cairo_stroker_t
 	/* pick an arbitrary slope to use */
 	cairo_slope_t slope = {1, 0};
 	cairo_stroke_face_t face;
+
+	/* arbitrarily choose first_point
+	 * first_point and current_point should be the same */
 	_compute_face (&stroker->first_point, &slope, stroker, &face);
 
 	status = _cairo_stroker_add_leading_cap (stroker, &face);
diff-tree a1a4d6966e1d9c8ccf84c9972a4f9560553948f6 (from 849a9ef81b99d05d8f3ceb4f73bf5e52c90b24af)
Author: Jeff Smith <whydoubt at yahoo.com>
Date:   Mon Feb 19 16:06:56 2007 -0500

    Modify how _cairo_stroker_add_caps handles zero-length sub-paths
    
    For zero-length sub-paths, _cairo_stroker_add_caps sets up a dummy face,
    then lets later parts of the function add the caps.

diff --git a/src/cairo-path-stroke.c b/src/cairo-path-stroke.c
index 55eee68..4827ab0 100644
--- a/src/cairo-path-stroke.c
+++ b/src/cairo-path-stroke.c
@@ -473,10 +473,15 @@ _cairo_stroker_add_caps (cairo_stroker_t
     {
 	/* pick an arbitrary slope to use */
 	cairo_slope_t slope = {1, 0};
-	_compute_face (&stroker->first_point, &slope, stroker, &stroker->first_face);
+	cairo_stroke_face_t face;
+	_compute_face (&stroker->first_point, &slope, stroker, &face);
 
-	stroker->has_first_face = stroker->has_current_face = TRUE;
-	stroker->current_face = stroker->first_face;
+	status = _cairo_stroker_add_leading_cap (stroker, &face);
+	if (status)
+	    return status;
+	status = _cairo_stroker_add_trailing_cap (stroker, &face);
+	if (status)
+	    return status;
     }
 
     if (stroker->has_first_face) {
diff-tree 849a9ef81b99d05d8f3ceb4f73bf5e52c90b24af (from 74ded42327e87b40de434a28620d0a3fc8e4d249)
Author: Jeff Smith <whydoubt at yahoo.com>
Date:   Mon Feb 19 16:06:56 2007 -0500

    Change type of cairo_stroker_t's dash_on from int to cairo_bool_t

diff --git a/src/cairo-path-stroke.c b/src/cairo-path-stroke.c
index 519434c..55eee68 100644
--- a/src/cairo-path-stroke.c
+++ b/src/cairo-path-stroke.c
@@ -61,7 +61,7 @@ typedef struct cairo_stroker {
 
     cairo_bool_t dashed;
     unsigned int dash_index;
-    int dash_on;
+    cairo_bool_t dash_on;
     double dash_remain;
 } cairo_stroker_t;
 
@@ -114,7 +114,7 @@ static void
 _cairo_stroker_start_dash (cairo_stroker_t *stroker)
 {
     double offset;
-    int	on = 1;
+    cairo_bool_t on = TRUE;
     unsigned int i = 0;
 
     offset = stroker->style->dash_offset;
@@ -124,7 +124,7 @@ _cairo_stroker_start_dash (cairo_stroker
        segment shrinks to zero it will be skipped over. */
     while (offset > 0.0 && offset >= stroker->style->dash[i]) {
 	offset -= stroker->style->dash[i];
-	on = 1-on;
+	on = !on;
 	if (++i == stroker->style->num_dashes)
 	    i = 0;
     }
@@ -142,7 +142,7 @@ _cairo_stroker_step_dash (cairo_stroker_
 	stroker->dash_index++;
 	if (stroker->dash_index == stroker->style->num_dashes)
 	    stroker->dash_index = 0;
-	stroker->dash_on = 1-stroker->dash_on;
+	stroker->dash_on = !stroker->dash_on;
 	stroker->dash_remain = stroker->style->dash[stroker->dash_index];
     }
 }
diff-tree 74ded42327e87b40de434a28620d0a3fc8e4d249 (from 1c1697398c5ef17e38bc031e8c067113a6c10287)
Author: Jeff Muizelaar <jrmuizel at uwaterloo.ca>
Date:   Mon Feb 19 16:06:56 2007 -0500

    Add a new dashing test
    
    This new dashing test, based on some code from Jeff Smith, does a pretty
    good job exploring all the cases that the dashing code needs to deal with.

diff --git a/test/Makefile.am b/test/Makefile.am
index ca82b87..18ba2ac 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -27,6 +27,7 @@ dash-no-dash			\
 dash-offset-negative		\
 dash-scale			\
 dash-zero-length		\
+dash-state			\
 degenerate-path			\
 device-offset			\
 device-offset-positive		\
@@ -208,6 +209,7 @@ dash-no-dash-ref.png					\
 dash-offset-negative-ref.png				\
 dash-scale-ref.png					\
 dash-scale-ps-argb32-ref.png				\
+dash-state-ref.png					\
 dash-zero-length-ref.png				\
 dash-zero-length-rgb24-ref.png				\
 dash-zero-length-ps-argb32-ref.png			\
diff --git a/test/dash-state-ps-argb32-ref.png b/test/dash-state-ps-argb32-ref.png
new file mode 100644
index 0000000..01d32fa
Binary files /dev/null and b/test/dash-state-ps-argb32-ref.png differ
diff --git a/test/dash-state-ref.png b/test/dash-state-ref.png
new file mode 100644
index 0000000..d195ab0
Binary files /dev/null and b/test/dash-state-ref.png differ
diff --git a/test/dash-state.c b/test/dash-state.c
new file mode 100644
index 0000000..a59a3e8
--- /dev/null
+++ b/test/dash-state.c
@@ -0,0 +1,72 @@
+/*
+ * Copyright © 2007 Jeff Smith
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without
+ * fee, provided that the above copyright notice appear in all copies
+ * and that both that copyright notice and this permission notice
+ * appear in supporting documentation, and that the name of
+ * Jeff Smith not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior
+ * permission. Jeff Smith makes no representations about the
+ * suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * JEFF SMITH DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL JEFF SMITH BE LIABLE FOR ANY SPECIAL,
+ * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
+ * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Author: Jeff Smith <whydoubt at yahoo.com>
+ */
+
+#include "cairo-test.h"
+
+static cairo_test_draw_function_t draw;
+
+cairo_test_t test = {
+    "dash-state",
+    "Tries to explore the state space of the dashing code",
+    25*60, 4*60,
+    draw
+};
+
+static cairo_test_status_t
+draw (cairo_t *cr, int width, int height)
+{
+    double dashes[2] = {20, 20};
+    int a=0, b=0, c=0;
+    
+    cairo_set_source_rgb (cr, 0, 0, 0);
+    cairo_paint (cr);
+
+    for (a=0; a<4; a++)
+    for (b=0; b<5; b++)
+    for (c=0; c<5; c++) {
+	cairo_move_to (cr, ((b*5)+c)*60+10, a*60+10);
+	cairo_rel_line_to (cr, 0, b*10);
+	cairo_rel_line_to (cr, c*10, 0);
+
+	cairo_set_source_rgb (cr, 1, 1, 1);
+	cairo_set_line_width (cr, 8);
+	cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
+	cairo_set_dash (cr, dashes, 2, a*10);
+	cairo_stroke_preserve (cr);
+
+	cairo_set_source_rgb (cr, 0, 0.5, 1);
+	cairo_set_line_width (cr, 2);
+	cairo_set_line_cap (cr, CAIRO_LINE_CAP_BUTT);
+	cairo_set_dash (cr, 0, 0, 0);
+	cairo_stroke (cr);
+    }
+    return CAIRO_TEST_SUCCESS;
+}
+
+int
+main (void)
+{
+    return cairo_test (&test);
+}
diff-tree 1c1697398c5ef17e38bc031e8c067113a6c10287 (from 9927dde5334322c97942982f9bf632e74502d628)
Author: Jeff Muizelaar <jrmuizel at uwaterloo.ca>
Date:   Mon Feb 19 16:06:56 2007 -0500

    Add two new test cases to degenerate-path test
    
    These new cases deal with degenerate paths at the end of dashed paths. They
    currently fail.

diff --git a/test/degenerate-path-ps-argb32-ref.png b/test/degenerate-path-ps-argb32-ref.png
index bd3c8c6..85b9d4b 100644
Binary files a/test/degenerate-path-ps-argb32-ref.png and b/test/degenerate-path-ps-argb32-ref.png differ
diff --git a/test/degenerate-path-ref.png b/test/degenerate-path-ref.png
index 82095fd..102e890 100644
Binary files a/test/degenerate-path-ref.png and b/test/degenerate-path-ref.png differ
diff --git a/test/degenerate-path-rgb24-ref.png b/test/degenerate-path-rgb24-ref.png
index 54fff7f..881c019 100644
Binary files a/test/degenerate-path-rgb24-ref.png and b/test/degenerate-path-rgb24-ref.png differ
diff --git a/test/degenerate-path.c b/test/degenerate-path.c
index 2c1e4c2..c861cd2 100644
--- a/test/degenerate-path.c
+++ b/test/degenerate-path.c
@@ -35,7 +35,7 @@ static cairo_test_draw_function_t draw;
 cairo_test_t test = {
     "degenerate-path",
     "Tests the behaviour of degenerate paths with different cap types",
-    3*(PAD+LINE_WIDTH+PAD), 6*(LINE_WIDTH+PAD) + PAD,
+    3*(PAD+LINE_WIDTH+PAD), 8*(LINE_WIDTH+PAD) + PAD,
     draw
 };
 
@@ -45,6 +45,7 @@ draw (cairo_t *cr, int width, int height
     const cairo_line_cap_t cap[] = { CAIRO_LINE_CAP_ROUND, CAIRO_LINE_CAP_SQUARE, CAIRO_LINE_CAP_BUTT };
     size_t i;
     double dash[] = {2, 2};
+    double dash_long[] = {6, 6};
 
     cairo_set_source_rgb (cr, 1, 0, 0);
 
@@ -91,6 +92,26 @@ draw (cairo_t *cr, int width, int height
 	cairo_close_path (cr);
 	cairo_stroke (cr);
 
+	/* this should draw a single degenerate sub-path
+	 * at the end of the path */
+	cairo_set_dash (cr, dash_long, 2, 6.);
+
+	cairo_translate (cr, 0, 3*PAD);
+	cairo_move_to (cr, LINE_WIDTH + 6.0, LINE_WIDTH);
+	cairo_line_to (cr, LINE_WIDTH, LINE_WIDTH);
+	cairo_stroke (cr);
+
+	/* this should draw a single degenerate sub-path
+	 * at the end of the path. The difference between this
+	 * and the above is that this ends with a degenerate sub-path*/
+	cairo_set_dash (cr, dash_long, 2, 6.);
+
+	cairo_translate (cr, 0, 3*PAD);
+	cairo_move_to (cr, LINE_WIDTH + 6.0, LINE_WIDTH);
+	cairo_line_to (cr, LINE_WIDTH, LINE_WIDTH);
+	cairo_line_to (cr, LINE_WIDTH, LINE_WIDTH);
+	cairo_stroke (cr);
+
 	cairo_restore (cr);
 
 	cairo_translate (cr, PAD+LINE_WIDTH+PAD, 0);


More information about the cairo-commit mailing list