summaryrefslogtreecommitdiff
path: root/src/cairo-path-fill.c
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2008-11-25 11:52:01 +0000
committerChris Wilson <chris@chris-wilson.co.uk>2008-11-25 12:54:58 +0000
commit4ac38f7c2bde67cab37805cab8a2effb2a8617e4 (patch)
treec3667748223f869416610285eaab04421b7038db /src/cairo-path-fill.c
parent23df74e5ffd6be876f3c19ee9d71683f5a0ed6f4 (diff)
downloadcairo-4ac38f7c2bde67cab37805cab8a2effb2a8617e4.tar.gz
[fill] Emit rectangles for GdkRegion
Scan the path for a series of consistently wound rectangles.
Diffstat (limited to 'src/cairo-path-fill.c')
-rw-r--r--src/cairo-path-fill.c85
1 files changed, 68 insertions, 17 deletions
diff --git a/src/cairo-path-fill.c b/src/cairo-path-fill.c
index 46046bb9b..a6dea0832 100644
--- a/src/cairo-path-fill.c
+++ b/src/cairo-path-fill.c
@@ -150,6 +150,7 @@ _cairo_filler_close_path (void *closure)
static cairo_int_status_t
_cairo_path_fixed_fill_rectangle (cairo_path_fixed_t *path,
+ cairo_fill_rule_t fill_rule,
cairo_traps_t *traps);
cairo_status_t
@@ -163,7 +164,7 @@ _cairo_path_fixed_fill_to_traps (cairo_path_fixed_t *path,
/* Before we do anything else, we use a special-case filler for
* a device-axis aligned rectangle if possible. */
- status = _cairo_path_fixed_fill_rectangle (path, traps);
+ status = _cairo_path_fixed_fill_rectangle (path, fill_rule, traps);
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
return status;
@@ -205,27 +206,77 @@ BAIL:
*/
static cairo_int_status_t
_cairo_path_fixed_fill_rectangle (cairo_path_fixed_t *path,
+ cairo_fill_rule_t fill_rule,
cairo_traps_t *traps)
{
- if (_cairo_path_fixed_is_box (path, NULL)) {
- cairo_point_t *p = path->buf_head.base.points;
- cairo_point_t *top_left, *bot_right;
-
- top_left = &p[0];
- bot_right = &p[2];
- if (top_left->x > bot_right->x || top_left->y > bot_right->y) {
- int n;
-
- /* not a simple cairo_rectangle() */
- for (n = 0; n < 4; n++) {
- if (p[n].x <= top_left->x && p[n].y <= top_left->y)
- top_left = &p[n];
- if (p[n].x >= bot_right->x && p[n].y >= bot_right->y)
- bot_right = &p[n];
+ cairo_box_t box;
+
+ 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;
+
+ /* Support a series of rectangles as can be expected to describe a
+ * GdkRegion clip region during exposes.
+ */
+ _cairo_path_fixed_iter_init (&iter, path);
+ while (_cairo_path_fixed_iter_is_box (&iter, &box)) {
+ cairo_status_t status;
+ 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) {
+ _cairo_traps_clear (traps);
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+ }
+
+ 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;
- return _cairo_traps_tessellate_rectangle (traps, top_left, bot_right);
+ _cairo_traps_clear (traps);
}
return CAIRO_INT_STATUS_UNSUPPORTED;