From dacc380dd9ea23fe060d0397104ecd4b2a6d0eae Mon Sep 17 00:00:00 2001 From: M Joonas Pihlaja Date: Sat, 11 Jul 2009 02:59:12 +0300 Subject: [test] Test extremely small dash lengths. The stroker code is liable to wedge when passed dash patterns which don't advance the dash offset due to limited precision arithmetic. This test attempts to hit all the places in the stroker where that can happen. Reported on the cairo mailing list by Hans Breuer: http://lists.cairographics.org/archives/cairo/2009-June/017506.html --- test/Makefile.am | 1 + test/Makefile.sources | 1 + test/dash-infinite-loop.c | 83 ++++++++++++++++++++++++++++++++++++++++ test/dash-infinite-loop.ref.png | Bin 0 -> 642 bytes 4 files changed, 85 insertions(+) create mode 100644 test/dash-infinite-loop.c create mode 100644 test/dash-infinite-loop.ref.png (limited to 'test') diff --git a/test/Makefile.am b/test/Makefile.am index 7e42789f4..7a04e5e1e 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -269,6 +269,7 @@ REFERENCE_IMAGES = \ dash-curve.ps3.ref.png \ dash-curve.quartz.ref.png \ dash-curve.ref.png \ + dash-infinite-loop.ref.png \ dash-no-dash.ref.png \ dash-offset-negative.ref.png \ dash-scale.ps2.argb32.ref.png \ diff --git a/test/Makefile.sources b/test/Makefile.sources index 3acc25599..ec7be36e8 100644 --- a/test/Makefile.sources +++ b/test/Makefile.sources @@ -38,6 +38,7 @@ test_sources = \ curve-to-as-line-to.c \ dash-caps-joins.c \ dash-curve.c \ + dash-infinite-loop.c \ dash-no-dash.c \ dash-offset-negative.c \ dash-scale.c \ diff --git a/test/dash-infinite-loop.c b/test/dash-infinite-loop.c new file mode 100644 index 000000000..a3d75442c --- /dev/null +++ b/test/dash-infinite-loop.c @@ -0,0 +1,83 @@ +/* + * Copyright © 2009 M Joonas Pihlaja + * + * 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: M Joonas Pihlaja + */ + +#include "cairo-test.h" + +/* When faced with very small dash lengths the stroker is liable to + * get stuck in an infinite loop when advancing the dash offset. This + * test attempts to hit each of the locations in the stroker code + * where the dash offset is advanced in a loop. + * + * Reported to the cairo mailing list by Hans Breuer. + * http://lists.cairographics.org/archives/cairo/2009-June/017506.html + */ + +#define EPS 1e-30 +/* This should be comfortably smaller than the unit epsilon of the + * floating point type used to advance the dashing, yet not small + * enough that it underflows to zero. 1e-30 works to foil up to 80 + * bit extended precision arithmetic. We want to avoid zero dash + * lengths because those trigger special processing in the stroker. */ + +static void +do_dash (cairo_t *cr, double dx, double dy, double offset) +{ + /* Set the dash pattern to be predominantly ON so that we can + * create a reference image by just ignoring the dashing. */ + static double dash[] = { EPS, EPS/512 }; + cairo_set_dash (cr, dash, 2, offset); + cairo_move_to (cr, 10, 10); + cairo_rel_line_to (cr, dx, dy); + cairo_stroke (cr); + cairo_translate (cr, dx, dy); +} + +static cairo_test_status_t +draw (cairo_t *cr, int width, int height) +{ + (void)width; (void)height; + + cairo_set_source_rgb (cr, 1,1,1); + cairo_paint (cr); + cairo_set_source_rgb (cr, 0,0,0); + + cairo_set_line_width (cr, 10); + + /* The following calls will wedge in various places that try + * to advance the dashing in a loop inside the stroker. */ + do_dash (cr, 30, 30, 0); /* _cairo_stroker_line_to_dashed */ + do_dash (cr, 30, 0, 0); /* _cairo_rectilinear_stroker_line_to_dashed */ + do_dash (cr, 30, 30, 1); /* _cairo_stroker_dash_start */ + + return CAIRO_TEST_SUCCESS; +} + +CAIRO_TEST (dash_infinite_loop, + "Test dashing with extremely small dash lengths.", + "dash", + NULL, + 100, 100, + NULL, draw); diff --git a/test/dash-infinite-loop.ref.png b/test/dash-infinite-loop.ref.png new file mode 100644 index 000000000..c0cc7391e Binary files /dev/null and b/test/dash-infinite-loop.ref.png differ -- cgit v1.2.3