Index: src/cairo-path-stroke.c =================================================================== RCS file: /mirrors/freedesktop/cairo/cairo/src/cairo-path-stroke.c,v retrieving revision 1.25 diff -u -p -r1.25 cairo-path-stroke.c --- src/cairo-path-stroke.c 23 Aug 2005 14:44:14 -0000 1.25 +++ src/cairo-path-stroke.c 10 Sep 2005 00:04:57 -0000 @@ -81,6 +81,12 @@ _cairo_stroker_curve_to (void *closure, cairo_point_t *d); static cairo_status_t +_cairo_stroker_curve_to_dashed (void *closure, + cairo_point_t *b, + cairo_point_t *c, + cairo_point_t *d); + +static cairo_status_t _cairo_stroker_close_path (void *closure); static void @@ -801,6 +807,74 @@ _cairo_stroker_curve_to (void *closure, return status; } +/* We're using two different algorithms here for dashed and un-dashed + * splines. The dashed alogorithm uses the existing line dashing + * code. It's linear in path length, but gets subtly wrong results for + * self-intersecting paths (an outstanding but for self-intersecting + * non-curved paths as well). The non-dashed algorithm tessellates a + * single polygon for the whole curve. It handles the + * self-intersecting problem, but it's (unsurprisingly) not O(n) and + * more significantly, it doesn't yet handle dashes. + * + * The only reason we're doing split algortihms here is to + * minimize the impact of fixing the splines-aren't-dashed bug for + * 1.0.2. Long-term the right answer is to rewrite the whole pile + * of stroking code so that the entire result is computed as a + * single polygon that is tessellated, (that is, stroking can be + * built on top of filling). That will solve the self-intersecting + * problem. It will also increase the importance of implementing + * an efficient and more robust tessellator. + */ +static cairo_status_t +_cairo_stroker_curve_to_dashed (void *closure, + cairo_point_t *b, + cairo_point_t *c, + cairo_point_t *d) +{ + cairo_status_t status = CAIRO_STATUS_SUCCESS; + cairo_stroker_t *stroker = closure; + cairo_gstate_t *gstate = stroker->gstate; + cairo_spline_t spline; + cairo_point_t *a = &stroker->current_point; + cairo_line_join_t line_join_save; + int i; + + status = _cairo_spline_init (&spline, a, b, c, d); + if (status == CAIRO_INT_STATUS_DEGENERATE) + return CAIRO_STATUS_SUCCESS; + + /* If the line width is so small that the pen is reduced to a + single point, then we have nothing to do. */ + if (gstate->pen_regular.num_vertices <= 1) + goto CLEANUP_SPLINE; + + /* Temporarily modify the gstate to use round joins to guarantee + * smooth stroked curves. */ + line_join_save = gstate->line_join; + gstate->line_join = CAIRO_LINE_JOIN_ROUND; + + status = _cairo_spline_decompose (&spline, gstate->tolerance); + if (status) + goto CLEANUP_GSTATE; + + for (i = 1; i < spline.num_points; i++) { + if (stroker->dashed) + status = _cairo_stroker_line_to_dashed (stroker, &spline.points[i]); + else + status = _cairo_stroker_line_to (stroker, &spline.points[i]); + if (status) + break; + } + + CLEANUP_GSTATE: + gstate->line_join = line_join_save; + + CLEANUP_SPLINE: + _cairo_spline_fini (&spline); + + return status; +} + static cairo_status_t _cairo_stroker_close_path (void *closure) { @@ -844,7 +918,7 @@ _cairo_path_fixed_stroke_to_traps (cairo CAIRO_DIRECTION_FORWARD, _cairo_stroker_move_to, _cairo_stroker_line_to_dashed, - _cairo_stroker_curve_to, + _cairo_stroker_curve_to_dashed, _cairo_stroker_close_path, &stroker); else