[cairo-commit] 3 commits - src/cairo.c src/cairo-path-stroke.c test/get-path-extents.c test/.gitignore test/Makefile.am test/rectilinear-miter-limit.c test/rectilinear-miter-limit-ref.png
Carl Worth
cworth at kemper.freedesktop.org
Mon Jan 21 16:47:23 PST 2008
src/cairo-path-stroke.c | 6 ++
src/cairo.c | 4 -
test/.gitignore | 1
test/Makefile.am | 2
test/get-path-extents.c | 49 +++++++++++++++++++++
test/rectilinear-miter-limit-ref.png |binary
test/rectilinear-miter-limit.c | 80 +++++++++++++++++++++++++++++++++++
7 files changed, 140 insertions(+), 2 deletions(-)
New commits:
commit 47cf7ed769891b00abf96d14de6e79c0fa893cf9
Author: Carl Worth <cworth at cworth.org>
Date: Mon Jan 21 16:45:41 2008 -0800
Test and document that fill rule has no effect on cairo_path_extents
diff --git a/src/cairo.c b/src/cairo.c
index 3011125..9535174 100644
--- a/src/cairo.c
+++ b/src/cairo.c
@@ -1879,8 +1879,8 @@ slim_hidden_def(cairo_close_path);
*
* Computes a bounding box in user-space coordinates covering the
* points on the current path. If the current path is empty, returns
- * an empty rectangle ((0,0), (0,0)). Stroke parameters, surface
- * dimensions and clipping are not taken into account.
+ * an empty rectangle ((0,0), (0,0)). Stroke parameters, fill rule,
+ * surface dimensions and clipping are not taken into account.
*
* Contrast with cairo_fill_extents() and cairo_stroke_extents() which
* return the extents of only the area that would be "inked" by
diff --git a/test/get-path-extents.c b/test/get-path-extents.c
index 5e82c1e..12901fd 100644
--- a/test/get-path-extents.c
+++ b/test/get-path-extents.c
@@ -244,6 +244,55 @@ draw (cairo_t *cr, int width, int height)
cairo_new_path (cr2);
cairo_restore (cr2);
+ cairo_save (cr2);
+
+ cairo_set_line_width (cr2, 4);
+
+ cairo_rectangle (cr2, 10, 10, 30, 30);
+ cairo_rectangle (cr2, 25, 10, 15, 30);
+
+ cairo_set_fill_rule (cr2, CAIRO_FILL_RULE_EVEN_ODD);
+ phase = "EVEN_ODD overlapping rectangles";
+ if (!check_extents (phase, cr2, FILL, EQUALS, 10, 10, 15, 30) ||
+ !check_extents (phase, cr2, STROKE, EQUALS, 8, 8, 34, 34) ||
+ !check_extents (phase, cr2, PATH, EQUALS, 10, 10, 30, 30))
+ ret = CAIRO_TEST_FAILURE;
+
+ /* Test other fill rule with the same path. */
+
+ cairo_set_fill_rule (cr2, CAIRO_FILL_RULE_WINDING);
+ phase = "WINDING overlapping rectangles";
+ if (!check_extents (phase, cr2, FILL, EQUALS, 10, 10, 30, 30) ||
+ !check_extents (phase, cr2, STROKE, EQUALS, 8, 8, 34, 34) ||
+ !check_extents (phase, cr2, PATH, EQUALS, 10, 10, 30, 30))
+ ret = CAIRO_TEST_FAILURE;
+
+ /* Now, change the direction of the second rectangle and test both
+ * fill rules again. */
+ cairo_new_path (cr2);
+ cairo_rectangle (cr2, 10, 10, 30, 30);
+ cairo_rectangle (cr2, 25, 40, 15, -30);
+
+ cairo_set_fill_rule (cr2, CAIRO_FILL_RULE_EVEN_ODD);
+ phase = "EVEN_ODD overlapping rectangles";
+ if (!check_extents (phase, cr2, FILL, EQUALS, 10, 10, 15, 30) ||
+ !check_extents (phase, cr2, STROKE, EQUALS, 8, 8, 34, 34) ||
+ !check_extents (phase, cr2, PATH, EQUALS, 10, 10, 30, 30))
+ ret = CAIRO_TEST_FAILURE;
+
+ /* Test other fill rule with the same path. */
+
+ cairo_set_fill_rule (cr2, CAIRO_FILL_RULE_WINDING);
+ phase = "WINDING overlapping rectangles";
+ if (!check_extents (phase, cr2, FILL, EQUALS, 10, 10, 15, 30) ||
+ !check_extents (phase, cr2, STROKE, EQUALS, 8, 8, 34, 34) ||
+ !check_extents (phase, cr2, PATH, EQUALS, 10, 10, 30, 30))
+ ret = CAIRO_TEST_FAILURE;
+
+ cairo_new_path (cr2);
+
+ cairo_restore (cr2);
+
/* http://bugs.freedesktop.org/show_bug.cgi?id=7245 */
phase = "Arc";
cairo_save (cr2);
commit 1ca186f51134e7d5969937760b068caba0070d31
Author: Carl Worth <cworth at cworth.org>
Date: Mon Jan 21 16:34:24 2008 -0800
Disable rectilinear stroke optimization for small miter limit values
This fixes the bug that was causing the recently added
rectilinear-miter-limit test case to fail. It passes
quite happily now.
diff --git a/src/cairo-path-stroke.c b/src/cairo-path-stroke.c
index 6464e3d..9ebfce3 100644
--- a/src/cairo-path-stroke.c
+++ b/src/cairo-path-stroke.c
@@ -1358,6 +1358,12 @@ _cairo_path_fixed_stroke_rectilinear (cairo_path_fixed_t *path,
return CAIRO_INT_STATUS_UNSUPPORTED;
if (stroke_style->line_join != CAIRO_LINE_JOIN_MITER)
return CAIRO_INT_STATUS_UNSUPPORTED;
+ /* If the miter limit turns right angles into bevels, then we
+ * can't usethis optimization. Remember, the ratio is
+ * 1/sin(ɸ/2). So the cutoff is 1/sin(Ï/4.0) or â·2 or
+ * approximately 1.414213562373095, which we round for safety. */
+ if (stroke_style->miter_limit < 1.415)
+ return CAIRO_INT_STATUS_UNSUPPORTED;
if (stroke_style->dash)
return CAIRO_INT_STATUS_UNSUPPORTED;
if (! (stroke_style->line_cap == CAIRO_LINE_CAP_BUTT ||
commit 32efcc94627e8890969c4b36a78c831ced6f8d62
Author: Carl Worth <cworth at cworth.org>
Date: Mon Jan 21 16:32:48 2008 -0800
Add new rectilinear-miter-limit test to demonstrate bug
We're failing to respect the miter limit in the rectilinear
stroke optimization code.
diff --git a/test/.gitignore b/test/.gitignore
index a02b29d..15e66c2 100644
--- a/test/.gitignore
+++ b/test/.gitignore
@@ -131,6 +131,7 @@ svg-surface.svg
pixman-rotate
pthread-show-text
rectangle-rounding-error
+rectilinear-miter-limit
rectilinear-stroke
rel-path
rotate-image-surface-paint
diff --git a/test/Makefile.am b/test/Makefile.am
index 14bafc3..79a5b2c 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -98,6 +98,7 @@ push-group$(EXEEXT) \
radial-gradient$(EXEEXT) \
random-intersections$(EXEEXT) \
rectangle-rounding-error$(EXEEXT) \
+rectilinear-miter-limit$(EXEEXT) \
rectilinear-stroke$(EXEEXT) \
rel-path$(EXEEXT) \
rgb24-ignore-alpha$(EXEEXT) \
@@ -427,6 +428,7 @@ REFERENCE_IMAGES = \
random-intersections-ref.png \
rgb24-ignore-alpha-ref.png \
rectangle-rounding-error-ref.png \
+ rectilinear-miter-limit-ref.png \
rectilinear-stroke-ref.png \
rel-path-quartz-ref.png \
rel-path-quartz-rgb24-ref.png \
diff --git a/test/rectilinear-miter-limit-ref.png b/test/rectilinear-miter-limit-ref.png
new file mode 100644
index 0000000..53bfee0
Binary files /dev/null and b/test/rectilinear-miter-limit-ref.png differ
diff --git a/test/rectilinear-miter-limit.c b/test/rectilinear-miter-limit.c
new file mode 100644
index 0000000..78d0512
--- /dev/null
+++ b/test/rectilinear-miter-limit.c
@@ -0,0 +1,80 @@
+/*
+ * Copyright © 2009 Red Hat, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Author: Carl D. Worth <cworth at cworth.org>
+ */
+
+#include "cairo-test.h"
+
+#define LINE_WIDTH 10
+#define PAD 2
+#define WIDTH (PAD + LINE_WIDTH + PAD)
+#define HEIGHT (WIDTH)
+
+static cairo_test_draw_function_t draw;
+
+cairo_test_t test = {
+ "rectilinear-miter-limit",
+ "Test that the rectilinear stroke optimization doesn't break cairo_set_miter_limit",
+ WIDTH, HEIGHT,
+ draw
+};
+
+static cairo_test_status_t
+draw (cairo_t *cr, int width, int height)
+{
+ cairo_translate (cr, PAD, PAD);
+
+ /* Paint background white, then draw in black. */
+ cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); /* white */
+ cairo_paint (cr);
+ cairo_set_source_rgb (cr, 0.0, 0.0, 0.0); /* black */
+
+ cairo_set_line_cap (cr, CAIRO_LINE_CAP_BUTT);
+ cairo_set_line_width (cr, LINE_WIDTH);
+
+ /* The default miter limit value of 10.0 guarantees that
+ * right-angle turns, (in fact, any angle greater than 11
+ * degrees), gets a miter rather than a bevel join. The
+ * rectilinear stroke optimization was originally written in a
+ * buggy way that did not respect the miter limit, (that is,
+ * inappropriately drawing miter joins when the miter limit would
+ * turn them into bevels). So we draw here with a miter limit of
+ * 1.0 to force all miter joins into bevels. */
+ cairo_set_line_join (cr, CAIRO_LINE_JOIN_MITER);
+ cairo_set_miter_limit (cr, 1.0);
+
+ cairo_move_to (cr, LINE_WIDTH / 2.0, LINE_WIDTH);
+ cairo_rel_line_to (cr, 0, - LINE_WIDTH / 2.0);
+ cairo_rel_line_to (cr, LINE_WIDTH / 2.0, 0);
+
+ cairo_stroke (cr);
+
+ return CAIRO_TEST_SUCCESS;
+}
+
+int
+main (void)
+{
+ return cairo_test (&test);
+}
More information about the cairo-commit
mailing list