diff options
author | Jeff Muizelaar <jmuizelaar@mozilla.com> | 2010-01-24 21:47:20 -0500 |
---|---|---|
committer | Jeff Muizelaar <jmuizelaar@mozilla.com> | 2010-01-24 21:47:20 -0500 |
commit | 58aec6f0cc19a4ea681e1d1541cd05bac2bb40b4 (patch) | |
tree | 29db642434d35debeb497a2bf615ce9f753aa9d8 | |
parent | 1255c081bf30de4d082038e89c5ad4db32916596 (diff) |
Cleanup
-rw-r--r-- | src/cairo-spline-offset.c | 168 |
1 files changed, 85 insertions, 83 deletions
diff --git a/src/cairo-spline-offset.c b/src/cairo-spline-offset.c index 7a7e49f3..5969873a 100644 --- a/src/cairo-spline-offset.c +++ b/src/cairo-spline-offset.c @@ -602,31 +602,33 @@ Which simplifies to the following: *t = 0.5; return !is_curvy_t(bzprod, sizeof(bzprod)/sizeof(bzprod[0])-1, max_error, t); } -void print_knot(knots_t c) { + +void +print_knot (knots_t c) { //printf("(%.13a %.13a) (%.13a %.13a) (%.13a %.13a) (%.13a %.13a)\n", c.a.x, c.a.y, c.b.x, c.b.y, c.c.x, c.c.y, c.d.x, c.d.y); printf("(%.5f %.5f) (%.5f %.5f) (%.5f %.5f) (%.5f %.5f)\n", c.a.x, c.a.y, c.b.x, c.b.y, c.c.x, c.c.y, c.d.x, c.d.y); } static knots_t -convolve_with_circle (knots_t self, double dist) +convolve_with_circle (knots_t spline, double dist) { - vector_t in_normal = normalize(perp(begin_tangent(self))); - vector_t out_normal = normalize(perp(end_tangent(self))); + vector_t in_normal = normalize(perp(begin_tangent(spline))); + vector_t out_normal = normalize(perp(end_tangent(spline))); /* find an arc the goes from the input normal to the output_normal */ knots_t arc_spline = arc_segment_cart(in_normal, out_normal, 1, in_normal, out_normal); //printf("%f %f, %f %f\n", in_normal.x, in_normal.y, out_normal.x, out_normal.y); - /* approximate convolving 'self' with the arc spline */ - self.a.x += dist * arc_spline.a.x; - self.a.y += dist * arc_spline.a.y; - self.b.x += dist * arc_spline.b.x; - self.b.y += dist * arc_spline.b.y; - self.c.x += dist * arc_spline.c.x; - self.c.y += dist * arc_spline.c.y; - self.d.x += dist * arc_spline.d.x; - self.d.y += dist * arc_spline.d.y; - - return self; + /* approximate convolving 'spline' with the arc spline (XXX: is convolve the right word?) */ + spline.a.x += dist * arc_spline.a.x; + spline.a.y += dist * arc_spline.a.y; + spline.b.x += dist * arc_spline.b.x; + spline.b.y += dist * arc_spline.b.y; + spline.c.x += dist * arc_spline.c.x; + spline.c.y += dist * arc_spline.c.y; + spline.d.x += dist * arc_spline.d.x; + spline.d.y += dist * arc_spline.d.y; + + return spline; } /* This approach is inspired by "Approximation of circular arcs and offset curves by Bezier curves of high degree" @@ -649,11 +651,11 @@ approximate_offset_curve_with_shin (knots_t self, double dist, void (*curve_fn)( we want to ensure that we don't have any inflection points in our spline */ inflection_points_t t_inflect = inflection_points(self); + /* split the curve at the inflection points and convolve each with an approximation of + * a circle */ knots_t remaining = self; double adjusted_inflect = t_inflect.t2; - printf("WITH SHIN\n"); - /* check that the first inflection point is in range */ if (t_inflect.t1 > 0 && t_inflect.t1 < 1) { /* split at the inflection point */ @@ -845,74 +847,74 @@ knot_offset(knots_t self, double width, cairo_bool_t *is_parallel) * good offset approximation down to the resolution of a double. */ void -curve_offset(knots_t self, double dist, double tolerance, void (*curve_fn)(void *, knots_t), void *closure) +curve_offset (knots_t self, double dist, double tolerance, void (*curve_fn)(void *, knots_t), void *closure) { - cairo_bool_t recurse; - double break_point; - double max_error = 0.01;//500;//0.01;//tolerance; - knots_t offset = knot_offset(self, dist, &recurse); - - printf("curve result: "); - print_knot(offset); - //double max_error = 0.01;//tolerance; - //bool recurse = !error_within_bounds(self, offset, dist, max_error); - //bool recurse = !error_within_bounds_muiz(self, offset, dist, 1.5*max_error/2.4); - if (!recurse) { - // we need to make sure we have a finite offset before checking the error - ensure_finite(offset); - recurse = !error_within_bounds_elber(self, offset, dist, max_error, &break_point); - } else { - /* TODO: we could probably choose a better place to split than halfway - * for times when we know we're going to recurse */ - break_point = .5; + cairo_bool_t recurse; + double break_point; + double max_error = 0.01;//500;//0.01;//tolerance; + knots_t offset = knot_offset(self, dist, &recurse); + + printf("curve result: "); + print_knot(offset); + //double max_error = 0.01;//tolerance; + //bool recurse = !error_within_bounds(self, offset, dist, max_error); + //bool recurse = !error_within_bounds_muiz(self, offset, dist, 1.5*max_error/2.4); + if (!recurse) { + // we need to make sure we have a finite offset before checking the error + ensure_finite(offset); + recurse = !error_within_bounds_elber(self, offset, dist, max_error, &break_point); + } else { + /* TODO: we could probably choose a better place to split than halfway + * for times when we know we're going to recurse */ + break_point = .5; + } + printf("recurse?: %d\n", recurse); + if (recurse) { + // error is too large. subdivide on max t and try again. + knots_t left = self; + knots_t right; + + cairo_bool_t is_continuous; + + /* We need to do something to handle regions of high curvature + * + * skia uses the first and second derivitives at the points of 'max curvature' to check for + * pinchynes. + * qt tests whether the points are close and reverse direction. + * float l = (orig->x1 - orig->x2)*(orig->x1 - orig->x2) + (orig->y3 - orig->y4)*(orig->y3 - orig->y4); + * float dot = (orig->x1 - orig->x2)*(orig->x3 - orig->x4) + (orig->y1 - orig->y2)*(orig->y3 - orig->y4); + * + * we just check if the knot is flat and has large error. + */ + if (is_knot_flat(self)) { + /* we don't want to recurse anymore because we're pretty flat, + * instead approximate the offset curve with an arc. + * + * The previously generated offset curve can become really bad if the the intersections + * are far away from the original curve (self) */ + + approximate_offset_curve_with_shin (self, dist, curve_fn, closure); + return; } - printf("recurse?: %d\n", recurse); - if (recurse) { - // error is too large. subdivide on max t and try again. - knots_t left = self; - knots_t right; - - cairo_bool_t is_continuous; - - /* We need to do something to handle regions of high curvature - * - * skia uses the first and second derivitives at the points of 'max curvature' to check for - * pinchynes. - * qt tests whether the points are close and reverse direction. - * float l = (orig->x1 - orig->x2)*(orig->x1 - orig->x2) + (orig->y3 - orig->y4)*(orig->y3 - orig->y4); - * float dot = (orig->x1 - orig->x2)*(orig->x3 - orig->x4) + (orig->y1 - orig->y2)*(orig->y3 - orig->y4); - * - * we just check if the knot is flat and has large error. - */ - if (is_knot_flat(self)) { - /* we don't want to recurse anymore because we're pretty flat, - * instead approximate the offset curve with an arc. - * - * The previously generated offset curve can become really bad if the the intersections - * are far away from the original curve (self) */ - - approximate_offset_curve_with_shin (self, dist, curve_fn, closure); - return; - } - - is_continuous = _de_casteljau_t(&left, &right, break_point); - - //printf("offset left\n"); - //print_knot(left); - curve_offset(left, dist, tolerance, curve_fn, closure); - - if (!is_continuous) { - // add circle - /* we can use the exit the normal from the left side - as the begining normal of our cusp */ - vector_t normal = perp (end_tangent (left)); - printf("semi cusp\n"); - semi_circle (left.d.x, left.d.y, dist, normal, curve_fn, closure); - } - - curve_offset(right, dist, tolerance, curve_fn, closure); - } else { - curve_fn(closure, offset); + + is_continuous = _de_casteljau_t(&left, &right, break_point); + + //printf("offset left\n"); + //print_knot(left); + curve_offset(left, dist, tolerance, curve_fn, closure); + + if (!is_continuous) { + // add circle + /* we can use the exit the normal from the left side + as the begining normal of our cusp */ + vector_t normal = perp (end_tangent (left)); + printf("semi cusp\n"); + semi_circle (left.d.x, left.d.y, dist, normal, curve_fn, closure); } + + curve_offset(right, dist, tolerance, curve_fn, closure); + } else { + curve_fn(closure, offset); + } } |