[cairo-commit] 4 commits - src/cairo-ps-surface.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/leaky-dash.c test/Makefile.am test/text-pattern-pdf-argb32-ref.png test/text-pattern-ps-argb32-ref.png

Carl Worth cworth at kemper.freedesktop.org
Wed Jun 28 21:30:46 PDT 2006


 src/cairo-ps-surface.c                  |   79 ++++++++++++++++++++++++++++-
 test/Makefile.am                        |    1 
 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                 |   85 +++++++++++++++++++++-----------
 test/leaky-dash.c                       |    3 -
 test/text-pattern-pdf-argb32-ref.png    |binary
 test/text-pattern-ps-argb32-ref.png     |binary
 9 files changed, 134 insertions(+), 34 deletions(-)

New commits:
diff-tree 8effd25c1b05607ff6501821f1d80745677d8e72 (from a64b946ee0512d85d3c790c67aad8a882c5c3533)
Author: Carl Worth <cworth at cworth.org>
Date:   Thu Jun 29 06:25:24 2006 +0200

    Update PDF and PS reference images for test/text-pattern.

diff --git a/test/text-pattern-pdf-argb32-ref.png b/test/text-pattern-pdf-argb32-ref.png
new file mode 100644
index 0000000..17afd64
Binary files /dev/null and b/test/text-pattern-pdf-argb32-ref.png differ
diff --git a/test/text-pattern-ps-argb32-ref.png b/test/text-pattern-ps-argb32-ref.png
new file mode 100644
index 0000000..1bc8dd4
Binary files /dev/null and b/test/text-pattern-ps-argb32-ref.png differ
diff-tree a64b946ee0512d85d3c790c67aad8a882c5c3533 (from 734e10709f5c62c0b64e51a03df8e109e7eebe0d)
Author: Carl Worth <cworth at cworth.org>
Date:   Thu Jun 29 06:24:44 2006 +0200

    Mark test/leaky-dash as an expected failure.

diff --git a/test/Makefile.am b/test/Makefile.am
index 4da7ed4..bd2e9a6 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -292,6 +292,7 @@ XFAIL_TESTS =			\
 a8-mask				\
 extend-reflect			\
 filter-nearest-offset		\
+leaky-dash			\
 pixman-rotate			\
 self-intersecting		\
 text-rotate
diff --git a/test/leaky-dash.c b/test/leaky-dash.c
index 95c5ca7..44f04f0 100644
--- a/test/leaky-dash.c
+++ b/test/leaky-dash.c
@@ -64,5 +64,6 @@ draw (cairo_t *cr, int width, int height
 int
 main (void)
 {
-    return cairo_test (&test, draw);
+    return cairo_test_expect_failure (&test, draw,
+				      "known bug (#4863) which has existed since the 1.0 release");
 }
diff-tree 734e10709f5c62c0b64e51a03df8e109e7eebe0d (from 8aa306caac99ebe074a6cde8b424b1780cafefee)
Author: Carl Worth <cworth at cworth.org>
Date:   Thu Jun 29 06:12:48 2006 +0200

    Add several more stress tests to test/dash-zero-length

diff --git a/test/dash-zero-length-ps-argb32-ref.png b/test/dash-zero-length-ps-argb32-ref.png
index 5c7fab5..897f25f 100644
Binary files a/test/dash-zero-length-ps-argb32-ref.png 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
index aca856f..16024f4 100644
Binary files a/test/dash-zero-length-ref.png 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
index f5e40e8..41b595c 100644
Binary files a/test/dash-zero-length-rgb24-ref.png and b/test/dash-zero-length-rgb24-ref.png differ
diff --git a/test/dash-zero-length.c b/test/dash-zero-length.c
index a5d0047..2014c07 100644
--- a/test/dash-zero-length.c
+++ b/test/dash-zero-length.c
@@ -26,7 +26,7 @@
 #include "cairo-test.h"
 
 #define IMAGE_WIDTH 19
-#define IMAGE_HEIGHT 25
+#define IMAGE_HEIGHT 61
 
 /* A test of the two extremes of dashing: a solid line
  * and an invisible one. Also test that capping works
@@ -39,44 +39,71 @@ cairo_test_t test = {
     IMAGE_WIDTH, IMAGE_HEIGHT
 };
 
+static void
+draw_dash (cairo_t *cr, double *dash, int num_dashes)
+{
+    cairo_set_dash (cr, dash, num_dashes, 0.0);
+    cairo_move_to (cr,  1, 2);
+    cairo_line_to (cr, 18, 2);
+    cairo_stroke (cr);
+    cairo_translate (cr, 0, 3);
+}
 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 };
+    static double solid_line[] = { 4, 0 };
+    static double invisible_line[] = { 0, 4 };
+    static double dotted_line[] = { 0, 6 };
+    static double zero_1_of_3[] = { 0, 2, 3 };
+    static double zero_2_of_3[] = { 1, 0, 3 };
+    static double zero_3_of_3[] = { 1, 2, 0 };
+    static double zero_1_of_4[] = { 0, 2, 3, 4 };
+    static double zero_2_of_4[] = { 1, 0, 3, 4 };
+    static double zero_3_of_4[] = { 1, 2, 0, 4 };
+    static double zero_4_of_4[] = { 1, 2, 3, 0 };
+    static double zero_1_2_of_4[] = { 0, 0, 3, 4 };
+    static double zero_1_3_of_4[] = { 0, 2, 0, 4 };
+/* Clearly it would be nice to draw this one as well, but it seems to trigger a bug in ghostscript. */
+#if BUG_FIXED_IN_GHOSTSCRIPT
+    static double zero_1_4_of_4[] = { 0, 2, 3, 0 };
+#endif
+    static double zero_2_3_of_4[] = { 1, 0, 0, 4 };
+    static double zero_2_4_of_4[] = { 1, 0, 3, 0 };
+    static double zero_3_4_of_4[] = { 1, 2, 0, 0 };
+    static double zero_1_2_3_of_4[] = { 0, 0, 0, 4 };
+    static double zero_1_2_4_of_4[] = { 0, 0, 3, 0 };
+    static double zero_1_3_4_of_4[] = { 0, 2, 0, 0 };
+    static double zero_2_3_4_of_4[] = { 1, 0, 0, 0 };
 
     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_dash (cr, solid_line, 2);
+    draw_dash (cr, invisible_line, 2);
 
-    /* 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_dash (cr, dotted_line, 2);
+    cairo_set_line_cap (cr, CAIRO_LINE_CAP_BUTT);
 
-    /* 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);
+    draw_dash (cr, zero_1_of_3, 3);
+    draw_dash (cr, zero_2_of_3, 3);
+    draw_dash (cr, zero_3_of_3, 3);
+    draw_dash (cr, zero_1_of_4, 4);
+    draw_dash (cr, zero_2_of_4, 4);
+    draw_dash (cr, zero_3_of_4, 4);
+    draw_dash (cr, zero_4_of_4, 4);
+    draw_dash (cr, zero_1_2_of_4, 4);
+    draw_dash (cr, zero_1_3_of_4, 4);
+#if BUG_FIXED_IN_GHOSTSCRIPT
+    draw_dash (cr, zero_1_4_of_4, 4);
+#endif
+    draw_dash (cr, zero_2_3_of_4, 4);
+    draw_dash (cr, zero_2_4_of_4, 4);
+    draw_dash (cr, zero_3_4_of_4, 4);
+    draw_dash (cr, zero_1_2_3_of_4, 4);
+    draw_dash (cr, zero_1_2_4_of_4, 4);
+    draw_dash (cr, zero_1_3_4_of_4, 4);
+    draw_dash (cr, zero_2_3_4_of_4, 4);
 
     return CAIRO_TEST_SUCCESS;
 }
diff-tree 8aa306caac99ebe074a6cde8b424b1780cafefee (from 7285499700a4f0f4bb95f003d0c730246bf3eabd)
Author: Carl Worth <cworth at cworth.org>
Date:   Thu Jun 29 05:13:37 2006 +0200

    PS: Fix for dash-zero-length

diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c
index d72c3c0..b45e6f9 100644
--- a/src/cairo-ps-surface.c
+++ b/src/cairo-ps-surface.c
@@ -1805,15 +1805,82 @@ _cairo_ps_surface_stroke (void			*abstra
     cairo_ps_surface_t *surface = abstract_surface;
     cairo_output_stream_t *stream = surface->stream;
     cairo_int_status_t status;
+    double *dash = style->dash;
+    int num_dashes = style->num_dashes;
+    double dash_offset = style->dash_offset;
 
     if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
 	return _analyze_operation (surface, op, source);
 
     assert (operation_supported (surface, op, source));
 
+
     _cairo_output_stream_printf (stream,
 				 "%% _cairo_ps_surface_stroke\n");
 
+    /* PostScript has "special needs" when it comes to zero-length
+     * dash segments with butt caps. It apparently (at least
+     * according to ghostscript) draws hairlines for this
+     * case. That's not what the cairo semantics want, so we first
+     * touch up the array to eliminate any 0.0 values that will
+     * result in "on" segments.
+     */
+    if (num_dashes && style->line_cap == CAIRO_LINE_CAP_BUTT) {
+	int i;
+
+	/* If there's an odd number of dash values they will each get
+	 * interpreted as both on and off. So we first explicitly
+	 * expand the array to remove the duplicate usage so that we
+	 * can modify some of the values.
+	 */
+	if (num_dashes % 2) {
+	    dash = malloc (2 * num_dashes * sizeof (double));
+	    if (dash == NULL)
+		return CAIRO_STATUS_NO_MEMORY;
+
+	    memcpy (dash, style->dash, num_dashes * sizeof (double));
+	    memcpy (dash + num_dashes, style->dash, num_dashes * sizeof (double));
+
+	    num_dashes *= 2;
+	}
+
+	for (i = 0; i < num_dashes; i += 2) {
+	    if (dash[i] == 0.0) {
+		/* If we're at the front of the list, we first rotate
+		 * two elements from the end of the list to the front
+		 * of the list before folding away the 0.0. Or, if
+		 * there are only two dash elements, then there is
+		 * nothing at all to draw.
+		 */
+		if (i == 0) {
+		    double last_two[2];
+
+		    if (num_dashes == 2) {
+			if (dash != style->dash)
+			    free (dash);
+			return CAIRO_STATUS_SUCCESS;
+		    }
+		    /* The cases of num_dashes == 0, 1, or 3 elements
+		     * cannot exist, so the rotation of 2 elements
+		     * will always be safe */
+		    memcpy (last_two, dash + num_dashes - 2, sizeof (last_two));
+		    memmove (dash + 2, dash, (num_dashes - 2) * sizeof (double));
+		    memcpy (dash, last_two, sizeof (last_two));
+		    dash_offset += dash[0] + dash[1];
+		    i = 2;
+		}
+		dash[i-1] += dash[i+1];
+		num_dashes -= 2;
+		memmove (dash + i, dash + i + 2, (num_dashes - i) * sizeof (double));
+		/* If we might have just rotated, it's possible that
+		 * we rotated a 0.0 value to the front of the list.
+		 * Set i to -2 so it will get incremented to 0. */
+		if (i == 2)
+		    i = -2;
+	    }
+	}
+    }
+
     emit_pattern (surface, source);
 
     _cairo_output_stream_printf (stream,
@@ -1836,14 +1903,18 @@ _cairo_ps_surface_stroke (void			*abstra
     _cairo_output_stream_printf (stream, "%d setlinejoin\n",
 				 _cairo_ps_line_join (style->line_join));
     /* dashes */
-    if (style->num_dashes) {
+    if (num_dashes) {
 	int d;
+
 	_cairo_output_stream_printf (stream, "[");
-	for (d = 0; d < style->num_dashes; d++)
-	    _cairo_output_stream_printf (stream, " %f", style->dash[d]);
+	for (d = 0; d < num_dashes; d++)
+	    _cairo_output_stream_printf (stream, " %f", dash[d]);
 	_cairo_output_stream_printf (stream, "] %f setdash\n",
-				     style->dash_offset);
+				     dash_offset);
     }
+    if (dash != style->dash)
+	free (dash);
+
     /* miter limit */
     _cairo_output_stream_printf (stream, "%f setmiterlimit\n",
 				 style->miter_limit);


More information about the cairo-commit mailing list