[stroke] Optimise rectilinear strokes.

Avoid the overhead of sorting the rectangle in
_cairo_traps_tessellate_convex_quad() by constructing the trap directly
from the line segment. This also has secondary effects in only passing
 the non-degenerate trap to _cairo_traps_add_trap().

For rectilinear Hilbert curves this makes the rectilinear stoker over 4x
faster.
This commit is contained in:
Chris Wilson 2008-09-19 13:22:51 +01:00
parent 9930eefbbd
commit d5cd7ee74f
3 changed files with 48 additions and 17 deletions

View file

@ -1257,12 +1257,12 @@ _cairo_rectilinear_stroker_emit_segments (cairo_rectilinear_stroker_t *stroker)
cairo_status_t status;
cairo_line_cap_t line_cap = stroker->stroke_style->line_cap;
cairo_fixed_t half_line_width = stroker->half_line_width;
cairo_bool_t lengthen_initial, shorten_final, lengthen_final;
cairo_point_t *a, *b;
cairo_point_t r[4];
int i;
for (i = 0; i < stroker->num_segments; i++) {
cairo_point_t *a, *b;
cairo_bool_t lengthen_initial, shorten_final, lengthen_final;
a = &stroker->segments[i].p1;
b = &stroker->segments[i].p2;
@ -1315,6 +1315,14 @@ _cairo_rectilinear_stroker_emit_segments (cairo_rectilinear_stroker_t *stroker)
else if (lengthen_final)
b->x -= half_line_width;
}
if (a->x > b->x) {
cairo_point_t *t;
t = a;
a = b;
b = t;
}
} else {
if (a->y < b->y) {
if (lengthen_initial)
@ -1331,27 +1339,27 @@ _cairo_rectilinear_stroker_emit_segments (cairo_rectilinear_stroker_t *stroker)
else if (lengthen_final)
b->y -= half_line_width;
}
if (a->y > b->y) {
cairo_point_t *t;
t = a;
a = b;
b = t;
}
}
/* Form the rectangle by expanding by half the line width in
* either perpendicular direction. */
r[0] = *a;
r[1] = *b;
r[2] = *b;
r[3] = *a;
if (a->y == b->y) {
r[0].y -= half_line_width;
r[1].y -= half_line_width;
r[2].y += half_line_width;
r[3].y += half_line_width;
a->y -= half_line_width;
b->y += half_line_width;
} else {
r[0].x -= half_line_width;
r[1].x -= half_line_width;
r[2].x += half_line_width;
r[3].x += half_line_width;
a->x -= half_line_width;
b->x += half_line_width;
}
status = _cairo_traps_tessellate_convex_quad (stroker->traps, r);
status = _cairo_traps_tessellate_rectangle (stroker->traps, a, b);
if (status)
return status;
}
@ -1439,7 +1447,7 @@ _cairo_path_fixed_stroke_rectilinear (cairo_path_fixed_t *path,
/* This special-case rectilinear stroker only supports
* miter-joined lines (not curves) and no dashing and a
* translation-only matrix (though it could probably be extended
* to support a matrix with uniform, integer sacling).
* to support a matrix with uniform, integer scaling).
*
* It also only supports horizontal and vertical line_to
* elements. But we don't catch that here, but instead return

View file

@ -351,6 +351,24 @@ _cairo_traps_tessellate_triangle (cairo_traps_t *traps,
return _cairo_traps_tessellate_convex_quad (traps, quad);
}
cairo_status_t
_cairo_traps_tessellate_rectangle (cairo_traps_t *traps,
const cairo_point_t *top_left,
const cairo_point_t *bottom_right)
{
cairo_line_t left;
cairo_line_t right;
left.p1.x = left.p2.x = top_left->x;
left.p1.y = right.p1.y = top_left->y;
right.p1.x = right.p2.x = bottom_right->x;
left.p2.y = right.p2.y = bottom_right->y;
_cairo_traps_add_trap (traps, top_left->y, bottom_right->y, &left, &right);
return traps->status;
}
cairo_status_t
_cairo_traps_tessellate_convex_quad (cairo_traps_t *traps,
const cairo_point_t q[4])

View file

@ -2191,6 +2191,11 @@ cairo_private cairo_status_t
_cairo_traps_tessellate_convex_quad (cairo_traps_t *traps,
const cairo_point_t q[4]);
cairo_private cairo_status_t
_cairo_traps_tessellate_rectangle (cairo_traps_t *traps,
const cairo_point_t *top_left,
const cairo_point_t *bottom_right);
cairo_private void
_cairo_traps_add_trap (cairo_traps_t *traps,
cairo_fixed_t top, cairo_fixed_t bottom,