mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2026-01-10 22:10:16 +01:00
[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:
parent
9930eefbbd
commit
d5cd7ee74f
3 changed files with 48 additions and 17 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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])
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue