summaryrefslogtreecommitdiff
path: root/src/cairo-surface-fallback.c
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2009-08-28 10:06:04 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2009-08-29 08:08:38 +0100
commitab035ab2c7bec254fc94d6391398905b5039e777 (patch)
tree49312efc13ca5778e7c09c1e17de987b74ca89c1 /src/cairo-surface-fallback.c
parentd7b0c3b784faba756b10b66b9757e6e4c3fce38c (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.c95
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;
}