summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2009-08-11 15:37:35 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2009-08-29 08:08:33 +0100
commit4bf96bad9697cbe67907df69d40f46d8d7f24325 (patch)
tree5b188989e7850aa66278399827200df4f0178be2
parent30e5fa0ce06b2572f09f3d47ee10b692f18ba0ae (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.c74
-rw-r--r--src/cairo-surface-fallback.c14
-rw-r--r--src/cairoint.h5
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,