diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2009-08-28 10:06:04 +0100 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2009-08-29 08:08:38 +0100 |
commit | ab035ab2c7bec254fc94d6391398905b5039e777 (patch) | |
tree | 49312efc13ca5778e7c09c1e17de987b74ca89c1 /src/cairo-surface-fallback.c | |
parent | d7b0c3b784faba756b10b66b9757e6e4c3fce38c (diff) |
[tessellate] Rectangular special case
Add an even simpler sweep-line tessellator for rectangular trapezoids (as
produced by the rectilinear stoker and box filler).
This is so simple it even outperforms pixman's region validation code for the
purposes of path-to-region conversion.
Diffstat (limited to 'src/cairo-surface-fallback.c')
-rw-r--r-- | src/cairo-surface-fallback.c | 95 |
1 files changed, 90 insertions, 5 deletions
diff --git a/src/cairo-surface-fallback.c b/src/cairo-surface-fallback.c index 4dc8ebbc..2755e16c 100644 --- a/src/cairo-surface-fallback.c +++ b/src/cairo-surface-fallback.c @@ -634,6 +634,87 @@ _clip_and_composite_region (const cairo_pattern_t *src, return status; } +/* avoid using region code to re-validate boxes */ +static cairo_status_t +_fill_rectangles (cairo_surface_t *dst, + cairo_operator_t op, + const cairo_pattern_t *src, + cairo_traps_t *traps, + cairo_clip_t *clip) +{ + const cairo_color_t *color; + cairo_rectangle_int_t stack_rects[CAIRO_STACK_ARRAY_LENGTH (cairo_rectangle_int_t)]; + cairo_rectangle_int_t *rects = stack_rects; + cairo_status_t status; + int i; + + if (! traps->is_rectilinear || ! traps->maybe_region) + return CAIRO_INT_STATUS_UNSUPPORTED; + + /* XXX: convert clip region to geometric boxes? */ + if (clip != NULL) + return CAIRO_INT_STATUS_UNSUPPORTED; + + /* XXX: fallback for the region_subtract() operation */ + if (! _cairo_operator_bounded_by_mask (op)) + return CAIRO_INT_STATUS_UNSUPPORTED; + + if (! (src->type == CAIRO_PATTERN_TYPE_SOLID || op == CAIRO_OPERATOR_CLEAR)) + return CAIRO_INT_STATUS_UNSUPPORTED; + + if (traps->has_intersections) { + if (traps->is_rectangular) { + status = _cairo_bentley_ottmann_tessellate_rectangular_traps (traps, CAIRO_FILL_RULE_WINDING); + } else { + status = _cairo_bentley_ottmann_tessellate_rectilinear_traps (traps, CAIRO_FILL_RULE_WINDING); + } + if (unlikely (status)) + return status; + } + + for (i = 0; i < traps->num_traps; i++) { + if (! _cairo_fixed_is_integer (traps->traps[i].top) || + ! _cairo_fixed_is_integer (traps->traps[i].bottom) || + ! _cairo_fixed_is_integer (traps->traps[i].left.p1.x) || + ! _cairo_fixed_is_integer (traps->traps[i].right.p1.x)) + { + traps->maybe_region = FALSE; + return CAIRO_INT_STATUS_UNSUPPORTED; + } + } + + if (traps->num_traps > ARRAY_LENGTH (stack_rects)) { + rects = _cairo_malloc_ab (traps->num_traps, + sizeof (cairo_rectangle_int_t)); + if (unlikely (rects == NULL)) + return _cairo_error (CAIRO_STATUS_NO_MEMORY); + } + + for (i = 0; i < traps->num_traps; i++) { + int x1 = _cairo_fixed_integer_part (traps->traps[i].left.p1.x); + int y1 = _cairo_fixed_integer_part (traps->traps[i].top); + int x2 = _cairo_fixed_integer_part (traps->traps[i].right.p1.x); + int y2 = _cairo_fixed_integer_part (traps->traps[i].bottom); + + rects[i].x = x1; + rects[i].y = y1; + rects[i].width = x2 - x1; + rects[i].height = y2 - y1; + } + + if (op == CAIRO_OPERATOR_CLEAR) + color = CAIRO_COLOR_TRANSPARENT; + else + color = &((cairo_solid_pattern_t *)src)->color; + + status = _cairo_surface_fill_rectangles (dst, op, color, rects, i); + + if (rects != stack_rects) + free (rects); + + return status; +} + /* Warning: This call modifies the coordinates of traps */ static cairo_status_t _clip_and_composite_trapezoids (const cairo_pattern_t *src, @@ -671,6 +752,10 @@ _clip_and_composite_trapezoids (const cairo_pattern_t *src, { cairo_region_t *trap_region = NULL; + status = _fill_rectangles (dst, op, src, traps, clip); + if (status != CAIRO_INT_STATUS_UNSUPPORTED) + return status; + status = _cairo_traps_extract_region (traps, &trap_region); if (unlikely (_cairo_status_is_error (status))) return status; @@ -713,12 +798,12 @@ _clip_and_composite_trapezoids (const cairo_pattern_t *src, /* No fast path, exclude self-intersections and clip trapezoids. */ if (traps->has_intersections) { - if (traps->is_rectilinear) - status = _cairo_bentley_ottmann_tessellate_rectilinear_traps (traps, - CAIRO_FILL_RULE_WINDING); + if (traps->is_rectangular) + status = _cairo_bentley_ottmann_tessellate_rectangular_traps (traps, CAIRO_FILL_RULE_WINDING); + else if (traps->is_rectilinear) + status = _cairo_bentley_ottmann_tessellate_rectilinear_traps (traps, CAIRO_FILL_RULE_WINDING); else - status = _cairo_bentley_ottmann_tessellate_traps (traps, - CAIRO_FILL_RULE_WINDING); + status = _cairo_bentley_ottmann_tessellate_traps (traps, CAIRO_FILL_RULE_WINDING); if (unlikely (status)) return status; } |