--- cairo-1.0.2/src/cairo-path-stroke.c 2005-10-03 16:44:43.000000000 -0400 +++ cairo-1.0.2-0width/src/cairo-path-stroke.c 2006-03-25 00:29:24.000000000 -0500 @@ -529,6 +529,61 @@ } static cairo_status_t +_cairo_stroker_add_sub_edge_slope (cairo_stroker_t *stroker, cairo_point_t *p1, cairo_point_t *p2, + cairo_slope_t *slope, + cairo_stroke_face_t *start, cairo_stroke_face_t *end) +{ + cairo_status_t status; + cairo_gstate_t *gstate = stroker->gstate; + cairo_polygon_t polygon; + cairo_slope_t slope_check; + + if (p1->x != p2->x || p1->y != p2->y) { + /* XXX: Need to rethink how this case should be handled, (both + here and in _compute_face). The key behavior is that + degenerate paths should draw as much as possible. */ + _cairo_slope_init (&slope_check, p1, p2); + if (_cairo_slope_compare (slope, &slope_check)) + printf("slopes don't match\n"); +// return CAIRO_STATUS_SUCCESS; + } + _compute_face (p1, slope, gstate, start); + + /* XXX: This could be optimized slightly by not calling + _compute_face again but rather translating the relevant + fields from start. */ + _compute_face (p2, slope, gstate, end); + + if (p1->x == p2->x && p1->y == p2->y) + return CAIRO_STATUS_SUCCESS; + /* XXX: I should really check the return value of the + move_to/line_to functions here to catch out of memory + conditions. But since that would be ugly, I'd prefer to add a + status flag to the polygon object that I could check only once + at then end of this sequence, (like we do with cairo_t + already). */ + _cairo_polygon_init (&polygon); + _cairo_polygon_move_to (&polygon, &start->cw); + _cairo_polygon_line_to (&polygon, &start->ccw); + _cairo_polygon_line_to (&polygon, &end->ccw); + _cairo_polygon_line_to (&polygon, &end->cw); + _cairo_polygon_close (&polygon); + + /* XXX: We can't use tessellate_rectangle as the matrix may have + skewed this into a non-rectangular shape. Perhaps it would be + worth checking the matrix for skew so that the common case + could use the faster tessellate_rectangle rather than + tessellate_polygon? */ + status = _cairo_traps_tessellate_polygon (stroker->traps, + &polygon, CAIRO_FILL_RULE_WINDING); + + _cairo_polygon_fini (&polygon); + + return status; +} + + +static cairo_status_t _cairo_stroker_add_sub_edge (cairo_stroker_t *stroker, cairo_point_t *p1, cairo_point_t *p2, cairo_stroke_face_t *start, cairo_stroke_face_t *end) { @@ -649,6 +704,7 @@ cairo_status_t status = CAIRO_STATUS_SUCCESS; cairo_stroker_t *stroker = closure; cairo_gstate_t *gstate = stroker->gstate; + cairo_slope_t slope; double mag, remain, tmp; double dx, dy; double dx2, dy2; @@ -658,6 +714,8 @@ cairo_point_t *p1 = &stroker->current_point; cairo_point_t *p2 = point; + /* compute the slope once for the entire line */ + _cairo_slope_init (&slope, p1, p2); if (!stroker->has_current_point) return _cairo_stroker_move_to (stroker, point); @@ -684,8 +742,9 @@ /* * XXX simplify this case analysis */ + if (stroker->dash_on) { - status = _cairo_stroker_add_sub_edge (stroker, &fd1, &fd2, &sub_start, &sub_end); + status = _cairo_stroker_add_sub_edge_slope (stroker, &fd1, &fd2, &slope, &sub_start, &sub_end); if (status) return status; if (!first) {