[PATCH] Make _cairo_slope_compare return a non-zero result for slopes that differ by pi

Carl Worth cworth at cworth.org
Thu Feb 14 11:50:26 PST 2008


This prevents infinite looping while trying to advance along
a spline while trying to stroke it with a pen compressed to
a line as described here:

	Infinite loop when scaling very small values using 24.8
	http://bugs.freedesktop.org/show_bug.cgi?id=14280

Note that that particular test case only exposes the infinite
loop when using 24.8 instead of 16.16 fixed-point values by
setting CAIRO_FIXED_FRAC_BITS to 8.
---
 src/cairo-slope.c |   22 ++++++++++++++++++++--
 1 files changed, 20 insertions(+), 2 deletions(-)

diff --git a/src/cairo-slope.c b/src/cairo-slope.c
index e8421fc..6ec4759 100644
--- a/src/cairo-slope.c
+++ b/src/cairo-slope.c
@@ -47,8 +47,10 @@ _cairo_slope_init (cairo_slope_t *slope, cairo_point_t *a, cairo_point_t *b)
    positive X axis and increase in the direction of the positive Y
    axis.

-   WARNING: This function only gives correct results if the angular
-   difference between a and b is less than PI.
+   NOTE: This function should only be called if the angular difference
+   between a and b is less than or equal to pi. And in the case of pi,
+   this function will always return a value less than 0, (a will
+   always be considered less positive than b in that case).

    <  0 => a less positive than b
    == 0 => a equal to b
@@ -78,6 +80,22 @@ _cairo_slope_compare (cairo_slope_t *a, cairo_slope_t *b)
     if (b->dx == 0 && b->dy ==0)
 	return -1;

+    /* Finally, we're looking at two vectors that are either equal or
+     * that differ by exactly pi. We can identify the "differ by pi"
+     * case by looking for a change in sign in either dx or dy between
+     * a and b.
+     *
+     * And in these cases, we eliminate the ambiguity by reducing the angle
+     * of b by an infinitesimally small amount, (that is, 'a' will
+     * always be considered less than 'b').
+     */
+    if (((a->dx > 0) != (b->dx > 0)) ||
+	((a->dy > 0) != (b->dy > 0)))
+    {
+	return -1;
+    }
+
+    /* Finally, for identical slopes, we obviously return 0. */
     return 0;
 }

--
1.5.3.2




More information about the cairo mailing list