diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2011-08-13 15:20:03 +0100 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2011-08-13 16:41:28 +0100 |
commit | ba406866be320c3a344b4e4a8d4bd19f48fa158d (patch) | |
tree | cc926299a6ee910db208e8228ce3fedcb4d7d485 /src/cairo-path-fill.c | |
parent | 54c8e8ccfc242fd17144c64202f628c87edbb6f4 (diff) | |
download | cairo-ba406866be320c3a344b4e4a8d4bd19f48fa158d.tar.gz |
stroke: Rely on the tessellator to remove self-intersections
As handling joins/caps between line segments shorter than
half_line_width is tricky.
Rather than also fixing the bug in traps, remove that code. The plan is
to avoiding hitting the traps code, short-circuiting several steps along
the fast rectangular paths.
Fixes line-width-overlap.
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Diffstat (limited to 'src/cairo-path-fill.c')
-rw-r--r-- | src/cairo-path-fill.c | 245 |
1 files changed, 0 insertions, 245 deletions
diff --git a/src/cairo-path-fill.c b/src/cairo-path-fill.c index b15b1a4a0..ce4c86a45 100644 --- a/src/cairo-path-fill.c +++ b/src/cairo-path-fill.c @@ -235,251 +235,6 @@ _cairo_path_fixed_fill_to_traps (const cairo_path_fixed_t *path, return status; } -static cairo_region_t * -_cairo_path_fixed_fill_rectilinear_tessellate_to_region (const cairo_path_fixed_t *path, - cairo_fill_rule_t fill_rule, - const cairo_rectangle_int_t *extents) -{ - cairo_box_t box; - cairo_polygon_t polygon; - cairo_traps_t traps; - cairo_status_t status; - cairo_region_t *region; - - /* first try to bypass fill-to-polygon */ - _cairo_traps_init (&traps); - status = _cairo_path_fixed_fill_rectilinear_to_traps (path, - fill_rule, - CAIRO_ANTIALIAS_NONE, - &traps); - if (_cairo_status_is_error (status)) - goto CLEANUP_TRAPS; - - if (status == CAIRO_STATUS_SUCCESS) { - status = _cairo_traps_extract_region (&traps, - CAIRO_ANTIALIAS_NONE, - ®ion); - goto CLEANUP_TRAPS; - } - - /* path is not rectangular, try extracting clipped rectilinear edges */ - if (extents != NULL) { - _cairo_box_from_rectangle (&box, extents); - _cairo_polygon_init (&polygon, &box, 1); - } else { - _cairo_polygon_init (&polygon, NULL, 0); - } - - /* tolerance will be ignored as the path is rectilinear */ - status = _cairo_path_fixed_fill_to_polygon (path, 0., &polygon); - if (unlikely (status)) - goto CLEANUP_POLYGON; - - if (polygon.num_edges == 0) { - region = cairo_region_create (); - } else { - status = - _cairo_bentley_ottmann_tessellate_rectilinear_polygon (&traps, - &polygon, - fill_rule); - if (likely (status == CAIRO_STATUS_SUCCESS)) - status = _cairo_traps_extract_region (&traps, - CAIRO_ANTIALIAS_NONE, - ®ion); - } - - CLEANUP_POLYGON: - _cairo_polygon_fini (&polygon); - - CLEANUP_TRAPS: - _cairo_traps_fini (&traps); - - if (unlikely (status)) - region = _cairo_region_create_in_error (status); - - return region; -} - -/* This special-case filler supports only a path that describes a - * device-axis aligned rectangle. It exists to avoid the overhead of - * the general tessellator when drawing very common rectangles. - * - * If the path described anything but a device-axis aligned rectangle, - * this function will abort. - */ -cairo_region_t * -_cairo_path_fixed_fill_rectilinear_to_region (const cairo_path_fixed_t *path, - cairo_fill_rule_t fill_rule, - const cairo_rectangle_int_t *extents) -{ - cairo_rectangle_int_t rectangle_stack[CAIRO_STACK_ARRAY_LENGTH (cairo_rectangle_int_t)]; - cairo_box_t box; - cairo_region_t *region = NULL; - - assert (_cairo_path_fixed_fill_maybe_region (path)); - assert (! _cairo_path_fixed_fill_is_empty (path)); - - if (_cairo_path_fixed_is_box (path, &box)) { - rectangle_stack[0].x = _cairo_fixed_integer_part (box.p1.x); - rectangle_stack[0].y = _cairo_fixed_integer_part (box.p1.y); - rectangle_stack[0].width = _cairo_fixed_integer_part (box.p2.x) - - rectangle_stack[0].x; - rectangle_stack[0].height = _cairo_fixed_integer_part (box.p2.y) - - rectangle_stack[0].y; - if (! _cairo_rectangle_intersect (&rectangle_stack[0], extents)) - region = cairo_region_create (); - else - region = cairo_region_create_rectangle (&rectangle_stack[0]); - } else if (fill_rule == CAIRO_FILL_RULE_WINDING) { - cairo_rectangle_int_t *rects = rectangle_stack; - cairo_path_fixed_iter_t iter; - int last_cw = -1; - int size = ARRAY_LENGTH (rectangle_stack); - int count = 0; - - /* 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_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 TESSELLATE; - - if (count == size) { - cairo_rectangle_int_t *new_rects; - - size *= 4; - if (rects == rectangle_stack) { - new_rects = _cairo_malloc_ab (size, - sizeof (cairo_rectangle_int_t)); - if (unlikely (new_rects == NULL)) { - /* XXX _cairo_region_nil */ - break; - } - memcpy (new_rects, rects, sizeof (rectangle_stack)); - } else { - new_rects = _cairo_realloc_ab (rects, size, - sizeof (cairo_rectangle_int_t)); - if (unlikely (new_rects == NULL)) { - /* XXX _cairo_region_nil */ - break; - } - } - rects = new_rects; - } - - rects[count].x = _cairo_fixed_integer_part (box.p1.x); - rects[count].y = _cairo_fixed_integer_part (box.p1.y); - rects[count].width = _cairo_fixed_integer_part (box.p2.x) - rects[count].x; - rects[count].height = _cairo_fixed_integer_part (box.p2.y) - rects[count].y; - if (_cairo_rectangle_intersect (&rects[count], extents)) - count++; - } - - if (_cairo_path_fixed_iter_at_end (&iter)) - region = cairo_region_create_rectangles (rects, count); - -TESSELLATE: - if (rects != rectangle_stack) - free (rects); - } - - if (region == NULL) { - /* Hmm, complex polygon */ - region = _cairo_path_fixed_fill_rectilinear_tessellate_to_region (path, - fill_rule, - extents); - - - } - - 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_antialias_t antialias, - cairo_traps_t *traps) -{ - cairo_box_t box; - cairo_status_t status; - - traps->is_rectilinear = TRUE; - traps->is_rectangular = TRUE; - - if (_cairo_path_fixed_is_box (path, &box)) { - if (antialias == CAIRO_ANTIALIAS_NONE) { - box.p1.x = _cairo_fixed_round_down (box.p1.x); - box.p1.y = _cairo_fixed_round_down (box.p1.y); - box.p2.x = _cairo_fixed_round_down (box.p2.x); - box.p2.y = _cairo_fixed_round_down (box.p2.y); - } - return _cairo_traps_tessellate_rectangle (traps, &box.p1, &box.p2); - } else { - cairo_path_fixed_iter_t iter; - - _cairo_path_fixed_iter_init (&iter, path); - while (_cairo_path_fixed_iter_is_fill_box (&iter, &box)) { - 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; - - t = box.p1.x; - box.p1.x = box.p2.x; - box.p2.x = t; - } - - if (antialias == CAIRO_ANTIALIAS_NONE) { - box.p1.x = _cairo_fixed_round_down (box.p1.x); - box.p1.y = _cairo_fixed_round_down (box.p1.y); - box.p2.x = _cairo_fixed_round_down (box.p2.x); - box.p2.y = _cairo_fixed_round_down (box.p2.y); - } - - status = _cairo_traps_tessellate_rectangle (traps, - &box.p1, &box.p2); - if (unlikely (status)) { - _cairo_traps_clear (traps); - return status; - } - } - - if (_cairo_path_fixed_iter_at_end (&iter)) - return _cairo_bentley_ottmann_tessellate_rectangular_traps (traps, fill_rule); - - _cairo_traps_clear (traps); - return CAIRO_INT_STATUS_UNSUPPORTED; - } -} - static cairo_status_t _cairo_path_fixed_fill_rectilinear_tessellate_to_boxes (const cairo_path_fixed_t *path, cairo_fill_rule_t fill_rule, |