[cairo-commit] 5 commits - src/cairo-path-stroke.c test/dash-zero-length.c test/dash-zero-length-ps-argb32-ref.png test/dash-zero-length-ref.png test/dash-zero-length-rgb24-ref.png test/Makefile.am

Jeff Muizelaar jrmuizel at kemper.freedesktop.org
Thu Apr 13 22:57:52 PDT 2006


 src/cairo-path-stroke.c                 |   45 +++++++++++-----
 test/Makefile.am                        |    4 +
 test/dash-zero-length-ps-argb32-ref.png |binary
 test/dash-zero-length-ref.png           |binary
 test/dash-zero-length-rgb24-ref.png     |binary
 test/dash-zero-length.c                 |   88 ++++++++++++++++++++++++++++++++
 6 files changed, 123 insertions(+), 14 deletions(-)

New commits:
diff-tree 2078557c5c9e10cf8ae16fb3fa8a225f908ab528 (from 5eaf71e77bd975f5865cc059b4aa4d57c096688e)
Author: Jeff Muizelaar <jeff at infidigm.net>
Date:   Sun Apr 9 23:11:27 2006 -0400

    Fix skipping zero length dash segments in dash_start.
    
    The extra check makes sure zero length segments are not skipped when computing
    the dash start state. This is needed so that we get proper line capping if, for
    example, the first dash segment has zero length and we have a dash offset of
    zero.

diff --git a/src/cairo-path-stroke.c b/src/cairo-path-stroke.c
index 870dc50..d6044a3 100644
--- a/src/cairo-path-stroke.c
+++ b/src/cairo-path-stroke.c
@@ -116,7 +116,11 @@ _cairo_stroker_start_dash (cairo_stroker
     int	i = 0;
 
     offset = stroker->style->dash_offset;
-    while (offset >= stroker->style->dash[i]) {
+
+    /* We stop searching for a starting point as soon as the
+       offset reaches zero.  Otherwise when an initial dash
+       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;
 	if (++i == stroker->style->num_dashes)
diff-tree 5eaf71e77bd975f5865cc059b4aa4d57c096688e (from 20fca01a2cc539df017e442be0cc6ad35353571f)
Author: Jeff Muizelaar <jeff at infidigm.net>
Date:   Sun Apr 9 23:11:11 2006 -0400

    Move the test for zero length sub edges below the computation of faces.
    
    Face computation still works if a line has zero length, all that is needed is a
    slope and a point. This patch fixes bug #5561 because the faces are initialized
    even if the segment has zero length as expected by
    _cairo_stroker_line_to_dashed.

diff --git a/src/cairo-path-stroke.c b/src/cairo-path-stroke.c
index 4fe7e31..870dc50 100644
--- a/src/cairo-path-stroke.c
+++ b/src/cairo-path-stroke.c
@@ -554,13 +554,6 @@ _cairo_stroker_add_sub_edge (cairo_strok
     cairo_status_t status;
     cairo_polygon_t polygon;
 
-    if (p1->x == p2->x && p1->y == p2->y) {
-	/* XXX: Need to rethink how this case should be handled, (both
-           here and in _compute_face). The key behavior is that
-           degenerate paths should draw as much as possible. */
-	return CAIRO_STATUS_SUCCESS;
-    }
-
     _compute_face (p1, slope, stroker, start);
 
     /* XXX: This could be optimized slightly by not calling
@@ -568,6 +561,13 @@ _cairo_stroker_add_sub_edge (cairo_strok
        fields from start. */
     _compute_face (p2, slope, stroker, end);
 
+    if (p1->x == p2->x && p1->y == p2->y) {
+	/* XXX: Need to rethink how this case should be handled, (both
+           here and in _compute_face). The key behavior is that
+           degenerate paths should draw as much as possible. */
+	return CAIRO_STATUS_SUCCESS;
+    }
+
     /* XXX: I should really check the return value of the
        move_to/line_to functions here to catch out of memory
        conditions. But since that would be ugly, I'd prefer to add a
diff-tree 20fca01a2cc539df017e442be0cc6ad35353571f (from 8a2ea660fb59beb4eacaf73978368c8db7a6b584)
Author: Jeff Muizelaar <jeff at infidigm.net>
Date:   Sun Apr 9 23:10:59 2006 -0400

    Move calculation of slope outside of _cairo_stroker_add_sub_edge.
    
    This makes the slope calculation more accurate for dashed lines by computing it
    once for the entire line instead for each individual dash segment. It also
    adjusts stroker_line_to() to match the new convention for
    stroker_add_sub_edge().

diff --git a/src/cairo-path-stroke.c b/src/cairo-path-stroke.c
index ff09f30..4fe7e31 100644
--- a/src/cairo-path-stroke.c
+++ b/src/cairo-path-stroke.c
@@ -548,11 +548,11 @@ _compute_face (cairo_point_t *point, cai
 
 static cairo_status_t
 _cairo_stroker_add_sub_edge (cairo_stroker_t *stroker, cairo_point_t *p1, cairo_point_t *p2,
-			     cairo_stroke_face_t *start, cairo_stroke_face_t *end)
+			     cairo_slope_t *slope, cairo_stroke_face_t *start,
+			     cairo_stroke_face_t *end)
 {
     cairo_status_t status;
     cairo_polygon_t polygon;
-    cairo_slope_t slope;
 
     if (p1->x == p2->x && p1->y == p2->y) {
 	/* XXX: Need to rethink how this case should be handled, (both
@@ -561,13 +561,12 @@ _cairo_stroker_add_sub_edge (cairo_strok
 	return CAIRO_STATUS_SUCCESS;
     }
 
-    _cairo_slope_init (&slope, p1, p2);
-    _compute_face (p1, &slope, stroker, start);
+    _compute_face (p1, slope, stroker, start);
 
     /* XXX: This could be optimized slightly by not calling
        _compute_face again but rather  translating the relevant
        fields from start. */
-    _compute_face (p2, &slope, stroker, end);
+    _compute_face (p2, slope, stroker, end);
 
     /* XXX: I should really check the return value of the
        move_to/line_to functions here to catch out of memory
@@ -633,6 +632,7 @@ _cairo_stroker_line_to (void *closure, c
     cairo_stroke_face_t start, end;
     cairo_point_t *p1 = &stroker->current_point;
     cairo_point_t *p2 = point;
+    cairo_slope_t slope;
 
     if (!stroker->has_current_point)
 	return _cairo_stroker_move_to (stroker, point);
@@ -644,8 +644,10 @@ _cairo_stroker_line_to (void *closure, c
            as possible. */
 	return CAIRO_STATUS_SUCCESS;
     }
+
+    _cairo_slope_init (&slope, p1, p2);
     
-    status = _cairo_stroker_add_sub_edge (stroker, p1, p2, &start, &end);
+    status = _cairo_stroker_add_sub_edge (stroker, p1, p2, &slope, &start, &end);
     if (status)
 	return status;
 
@@ -683,6 +685,7 @@ _cairo_stroker_line_to_dashed (void *clo
     cairo_stroke_face_t sub_start, sub_end;
     cairo_point_t *p1 = &stroker->current_point;
     cairo_point_t *p2 = point;
+    cairo_slope_t slope;
 
     if (!stroker->has_current_point)
 	return _cairo_stroker_move_to (stroker, point);
@@ -695,6 +698,8 @@ _cairo_stroker_line_to_dashed (void *clo
 	return CAIRO_STATUS_SUCCESS;
     }
 
+    _cairo_slope_init (&slope, p1, p2);
+
     dx = _cairo_fixed_to_double (p2->x - p1->x);
     dy = _cairo_fixed_to_double (p2->y - p1->y);
 
@@ -719,7 +724,7 @@ _cairo_stroker_line_to_dashed (void *clo
 	 * XXX simplify this case analysis
 	 */
 	if (stroker->dash_on) {
-	    status = _cairo_stroker_add_sub_edge (stroker, &fd1, &fd2, &sub_start, &sub_end);
+	    status = _cairo_stroker_add_sub_edge (stroker, &fd1, &fd2, &slope, &sub_start, &sub_end);
 	    if (status)
 		return status;
 	    if (!first) {
diff-tree 8a2ea660fb59beb4eacaf73978368c8db7a6b584 (from 584109d5e6160c1e74da0e79b6e024701a354293)
Author: Jeff Muizelaar <jeff at infidigm.net>
Date:   Sun Apr 9 23:10:46 2006 -0400

    Check for zero length dashed lines.
    
    This makes line_to_dashed more like line_to by returning immediately on
    degenerate paths. This is needed so that we can do the slope calculation for
    the entire line.

diff --git a/src/cairo-path-stroke.c b/src/cairo-path-stroke.c
index a02a3aa..ff09f30 100644
--- a/src/cairo-path-stroke.c
+++ b/src/cairo-path-stroke.c
@@ -686,7 +686,15 @@ _cairo_stroker_line_to_dashed (void *clo
 
     if (!stroker->has_current_point)
 	return _cairo_stroker_move_to (stroker, point);
-    
+
+    if (p1->x == p2->x && p1->y == p2->y) {
+	/* XXX: Need to rethink how this case should be handled, (both
+           here and in cairo_stroker_add_sub_edge and in _compute_face). The
+           key behavior is that degenerate paths should draw as much
+           as possible. */
+	return CAIRO_STATUS_SUCCESS;
+    }
+
     dx = _cairo_fixed_to_double (p2->x - p1->x);
     dy = _cairo_fixed_to_double (p2->y - p1->y);
 
diff-tree 584109d5e6160c1e74da0e79b6e024701a354293 (from f17b347ab443fcc12f9098f9b601334f85d20a30)
Author: Jeff Muizelaar <jeff at infidigm.net>
Date:   Sun Apr 9 23:11:47 2006 -0400

    Add test case for dashed lines.
    
    The new test case tests a variety of circumstances involved with zero length dashing.

diff --git a/test/Makefile.am b/test/Makefile.am
index b951b43..1eecbe2 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -16,6 +16,7 @@ create-from-png			\
 create-from-png-stream		\
 dash-caps-joins			\
 dash-offset-negative		\
+dash-zero-length		\
 extend-reflect			\
 fill-and-stroke			\
 fill-rule			\
@@ -140,6 +141,8 @@ dash-caps-joins-rgb24-ref.png				\
 dash-offset-negative-ref.png				\
 dash-offset-negative-rgb24-ref.png			\
 dash-offset-negative-ps-rgb24-ref.png			\
+dash-zero-length-ref.png				\
+dash-zero-length-rgb24-ref.png				\
 extend-reflect-ref.png					\
 extend-reflect-rgb24-ref.png				\
 fill-and-stroke-ref.png					\
@@ -317,6 +320,7 @@ create_from_png_LDADD = $(LDADDS)
 create_from_png_stream_LDADD = $(LDADDS)
 dash_caps_joins_LDADD = $(LDADDS)
 dash_offset_negative_LDADD = $(LDADDS)
+dash_zero_length_LDADD = $(LDADDS)
 extend_reflect_LDADD = $(LDADDS)
 fill_and_stroke_LDADD = $(LDADDS)
 fill_rule_LDADD = $(LDADDS)
diff --git a/test/dash-zero-length-ps-argb32-ref.png b/test/dash-zero-length-ps-argb32-ref.png
new file mode 100644
index 0000000..0f66648
Binary files /dev/null and b/test/dash-zero-length-ps-argb32-ref.png differ
diff --git a/test/dash-zero-length-ref.png b/test/dash-zero-length-ref.png
new file mode 100644
index 0000000..aca856f
Binary files /dev/null and b/test/dash-zero-length-ref.png differ
diff --git a/test/dash-zero-length-rgb24-ref.png b/test/dash-zero-length-rgb24-ref.png
new file mode 100644
index 0000000..f5e40e8
Binary files /dev/null and b/test/dash-zero-length-rgb24-ref.png differ
diff --git a/test/dash-zero-length.c b/test/dash-zero-length.c
new file mode 100644
index 0000000..a5d0047
--- /dev/null
+++ b/test/dash-zero-length.c
@@ -0,0 +1,88 @@
+/*
+ * Copyright © 2006 Jeff Muizelaar
+ *
+ * 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 Muizelaar. not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior
+ * permission. Jeff Muizelaar. makes no representations about the
+ * suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * JEFF MUIZELAAR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL JEFF MUIZELAAR 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 Muizelaar <jeff at infidigm.net>
+ */
+
+#include "cairo-test.h"
+
+#define IMAGE_WIDTH 19
+#define IMAGE_HEIGHT 25
+
+/* A test of the two extremes of dashing: a solid line
+ * and an invisible one. Also test that capping works
+ * on invisible lines.
+ */
+
+cairo_test_t test = {
+    "dash-zero-length",
+    "Tests cairo_set_dash with zero length",
+    IMAGE_WIDTH, IMAGE_HEIGHT
+};
+
+static cairo_test_status_t
+draw (cairo_t *cr, int width, int height)
+{
+    double solid_line[] = { 4, 0 };
+    double invisible_line[] = { 0, 4 };
+    double dotted_line[] = { 0, 6 };
+    double rounded_line[] = { 2, 6 };
+
+    cairo_set_source_rgb (cr, 1, 0, 0);
+    cairo_set_line_width (cr, 2);
+
+    /* draw a solid line */
+    cairo_set_dash (cr, solid_line, 2, 0);
+    cairo_move_to (cr,  1, 2);
+    cairo_line_to (cr, 18, 2);
+    cairo_stroke (cr);
+
+    /* draw an invisible line */
+    cairo_set_dash (cr, invisible_line, 2, 0);
+    cairo_move_to (cr,  1, 8);
+    cairo_line_to (cr, 18, 8);
+    cairo_stroke (cr);
+
+    /* draw a dotted line */
+    cairo_set_line_width (cr, 5);
+    cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
+    cairo_set_dash (cr, dotted_line, 2, 0);
+    cairo_move_to (cr, 5, 13);
+    cairo_line_to (cr, 18, 13);
+    cairo_stroke (cr);
+
+    /* draw a rounded line */
+    cairo_set_line_width (cr, 5);
+    cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
+    cairo_set_dash (cr, rounded_line, 2, 2);
+    cairo_move_to (cr, 5, 20);
+    cairo_line_to (cr, 18, 20);
+    cairo_stroke (cr);
+
+    return CAIRO_TEST_SUCCESS;
+}
+
+int
+main (void)
+{
+    return cairo_test (&test, draw);
+}


More information about the cairo-commit mailing list