diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2009-08-11 15:37:35 +0100 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2009-08-29 08:08:33 +0100 |
commit | 4bf96bad9697cbe67907df69d40f46d8d7f24325 (patch) | |
tree | 5b188989e7850aa66278399827200df4f0178be2 | |
parent | 30e5fa0ce06b2572f09f3d47ee10b692f18ba0ae (diff) |
[fill] Use trivial rectilinear_to_traps
Avoid a small amount of unnecessary overhead by performing a simple
conversion of the path to traps when it consists solely of simple boxes.
-rw-r--r-- | src/cairo-path-fill.c | 74 | ||||
-rw-r--r-- | src/cairo-surface-fallback.c | 14 | ||||
-rw-r--r-- | src/cairoint.h | 5 |
3 files changed, 93 insertions, 0 deletions
diff --git a/src/cairo-path-fill.c b/src/cairo-path-fill.c index f9679443..3daf2461 100644 --- a/src/cairo-path-fill.c +++ b/src/cairo-path-fill.c @@ -347,3 +347,77 @@ TESSELLATE: return region; } + +cairo_int_status_t +_cairo_path_fixed_fill_rectilinear_to_traps (const cairo_path_fixed_t *path, + cairo_fill_rule_t fill_rule, + cairo_traps_t *traps) +{ + cairo_box_t box; + cairo_status_t status; + + if (_cairo_path_fixed_is_box (path, &box)) { + if (box.p1.x > box.p2.x) { + cairo_fixed_t t; + + t = box.p1.x; + box.p1.x = box.p2.x; + box.p2.x = t; + } + + if (box.p1.y > box.p2.y) { + cairo_fixed_t t; + + t = box.p1.y; + box.p1.y = box.p2.y; + box.p2.y = t; + } + + return _cairo_traps_tessellate_rectangle (traps, &box.p1, &box.p2); + } else if (fill_rule == CAIRO_FILL_RULE_WINDING) { + cairo_path_fixed_iter_t iter; + int last_cw = -1; + + _cairo_path_fixed_iter_init (&iter, path); + while (_cairo_path_fixed_iter_is_fill_box (&iter, &box)) { + int cw = 0; + + if (box.p1.x > box.p2.x) { + cairo_fixed_t t; + + t = box.p1.x; + box.p1.x = box.p2.x; + box.p2.x = t; + + cw = ! cw; + } + + if (box.p1.y > box.p2.y) { + cairo_fixed_t t; + + t = box.p1.y; + box.p1.y = box.p2.y; + box.p2.y = t; + + cw = ! cw; + } + + if (last_cw < 0) + last_cw = cw; + else if (last_cw != cw) + goto out; + + status = _cairo_traps_tessellate_rectangle (traps, + &box.p1, &box.p2); + if (unlikely (status)) + return status; + } + + if (_cairo_path_fixed_iter_at_end (&iter)) + return CAIRO_STATUS_SUCCESS; + } + + out: + _cairo_traps_clear (traps); + return CAIRO_INT_STATUS_UNSUPPORTED; +} diff --git a/src/cairo-surface-fallback.c b/src/cairo-surface-fallback.c index 32db7fbd..4dc8ebbc 100644 --- a/src/cairo-surface-fallback.c +++ b/src/cairo-surface-fallback.c @@ -1193,6 +1193,20 @@ _cairo_surface_fallback_fill (cairo_surface_t *surface, _cairo_polygon_init (&polygon); _cairo_polygon_limit (&polygon, boxes, num_boxes); + if (path->is_empty_fill) + goto DO_TRAPS; + + if (path->is_rectilinear) { + status = _cairo_path_fixed_fill_rectilinear_to_traps (path, + fill_rule, + &traps); + if (likely (status == CAIRO_STATUS_SUCCESS)) + goto DO_TRAPS; + + if (_cairo_status_is_error (status)) + goto CLEANUP; + } + status = _cairo_path_fixed_fill_to_polygon (path, tolerance, &polygon); if (unlikely (status)) goto CLEANUP; diff --git a/src/cairoint.h b/src/cairoint.h index 2afb6904..5ac8b6a2 100644 --- a/src/cairoint.h +++ b/src/cairoint.h @@ -1617,6 +1617,11 @@ _cairo_path_fixed_fill_to_polygon (const cairo_path_fixed_t *path, double tolerance, cairo_polygon_t *polygon); +cairo_private cairo_int_status_t +_cairo_path_fixed_fill_rectilinear_to_traps (const cairo_path_fixed_t *path, + cairo_fill_rule_t fill_rule, + cairo_traps_t *traps); + cairo_private cairo_region_t * _cairo_path_fixed_fill_rectilinear_to_region (const cairo_path_fixed_t *path, cairo_fill_rule_t fill_rule, |