[PATCH] Make _cairo_slope_compare return a non-zero result for slopes that differ by pi
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
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
@@ -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
- 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)
+ /* 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. */
More information about the cairo