summaryrefslogtreecommitdiff
path: root/src/cairo-path-fill.c
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2011-08-13 15:20:03 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2011-08-13 16:41:28 +0100
commitba406866be320c3a344b4e4a8d4bd19f48fa158d (patch)
treecc926299a6ee910db208e8228ce3fedcb4d7d485 /src/cairo-path-fill.c
parent54c8e8ccfc242fd17144c64202f628c87edbb6f4 (diff)
downloadcairo-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.c245
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,
- &region);
- 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,
- &region);
- }
-
- 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,