diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2009-08-10 14:48:03 +0100 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2009-08-29 08:08:32 +0100 |
commit | 2457c4bedef0447f7bff9b54dba96126010917ac (patch) | |
tree | 4d840c838a92f8493b9a71bdfc3eea0164c5de4c | |
parent | 3023330706b1237b0fbd697d015cad9a23c250b7 (diff) |
traps-as-spans
Add an interface to spans that accepts trapezoids. This allows backends
that have an efficient span-line interface but lack efficient handling
of boxes (partly due to the current poor compositor interface) to
redirect composite_trapezoids() to composite_polygon() and the
span-renderer.
-rw-r--r-- | src/cairo-spans-private.h | 19 | ||||
-rw-r--r-- | src/cairo-spans.c | 82 | ||||
-rw-r--r-- | src/cairo-tor-scan-converter.c | 27 |
3 files changed, 127 insertions, 1 deletions
diff --git a/src/cairo-spans-private.h b/src/cairo-spans-private.h index 9f6f1169..e29a567a 100644 --- a/src/cairo-spans-private.h +++ b/src/cairo-spans-private.h @@ -75,6 +75,13 @@ struct _cairo_scan_converter { /* Destroy this scan converter. */ cairo_destroy_func_t destroy; + /* Add a single edge to the converter. */ + cairo_status_t (*add_edge) (void *abstract_converter, + const cairo_point_t *p1, + const cairo_point_t *p2, + int top, int bottom, + int dir); + /* Add a polygon (set of edges) to the converter. */ cairo_status_t (*add_polygon) (void *abstract_converter, const cairo_polygon_t *polygon); @@ -133,4 +140,16 @@ _cairo_surface_composite_polygon (cairo_surface_t *surface, cairo_polygon_t *polygon, cairo_region_t *clip_region); +cairo_private cairo_status_t +_cairo_surface_composite_trapezoids_as_polygon (cairo_surface_t *surface, + cairo_operator_t op, + const cairo_pattern_t *pattern, + cairo_antialias_t antialias, + int src_x, int src_y, + int dst_x, int dst_y, + int width, int height, + cairo_trapezoid_t *traps, + int num_traps, + cairo_region_t *clip_region); + #endif /* CAIRO_SPANS_PRIVATE_H */ diff --git a/src/cairo-spans.c b/src/cairo-spans.c index 369cd582..1a516347 100644 --- a/src/cairo-spans.c +++ b/src/cairo-spans.c @@ -83,6 +83,71 @@ _cairo_surface_composite_polygon (cairo_surface_t *surface, return status; } +cairo_status_t +_cairo_surface_composite_trapezoids_as_polygon (cairo_surface_t *surface, + cairo_operator_t op, + const cairo_pattern_t *pattern, + cairo_antialias_t antialias, + int src_x, int src_y, + int dst_x, int dst_y, + int width, int height, + cairo_trapezoid_t *traps, + int num_traps, + cairo_region_t *clip_region) +{ + cairo_span_renderer_t *renderer; + cairo_scan_converter_t *converter; + cairo_composite_rectangles_t rects; + cairo_status_t status; + + rects.src.x = src_x; + rects.src.y = src_y; + rects.dst.x = 0; + rects.dst.y = 0; + rects.mask.x = dst_x; + rects.mask.y = dst_y; + rects.width = width; + rects.height = height; + + converter = _create_scan_converter (CAIRO_FILL_RULE_WINDING, + antialias, + &rects); + status = converter->status; + if (unlikely (status)) + goto CLEANUP_CONVERTER; + + while (num_traps--) { + status = converter->add_edge (converter, + &traps->left.p1, &traps->left.p2, + traps->top, traps->bottom, 1); + if (unlikely (status)) + goto CLEANUP_CONVERTER; + + status = converter->add_edge (converter, + &traps->right.p1, &traps->right.p2, + traps->top, traps->bottom, -1); + if (unlikely (status)) + goto CLEANUP_CONVERTER; + + traps++; + } + + renderer = _cairo_surface_create_span_renderer (op, pattern, surface, + antialias, &rects, + clip_region); + status = converter->generate (converter, renderer); + if (unlikely (status)) + goto CLEANUP_RENDERER; + + status = renderer->finish (renderer); + + CLEANUP_RENDERER: + renderer->destroy (renderer); + CLEANUP_CONVERTER: + converter->destroy (converter); + return status; +} + static void _cairo_nil_destroy (void *abstract) { @@ -99,6 +164,22 @@ _cairo_nil_scan_converter_add_polygon (void *abstract_converter, } static cairo_status_t +_cairo_nil_scan_converter_add_edge (void *abstract_converter, + const cairo_point_t *p1, + const cairo_point_t *p2, + int top, int bottom, + int dir) +{ + (void) abstract_converter; + (void) p1; + (void) p2; + (void) top; + (void) bottom; + (void) dir; + return _cairo_scan_converter_status (abstract_converter); +} + +static cairo_status_t _cairo_nil_scan_converter_generate (void *abstract_converter, cairo_span_renderer_t *renderer) { @@ -123,6 +204,7 @@ _cairo_scan_converter_set_error (void *abstract_converter, ASSERT_NOT_REACHED; if (converter->status == CAIRO_STATUS_SUCCESS) { converter->add_polygon = _cairo_nil_scan_converter_add_polygon; + converter->add_edge = _cairo_nil_scan_converter_add_edge; converter->generate = _cairo_nil_scan_converter_generate; converter->status = error; } diff --git a/src/cairo-tor-scan-converter.c b/src/cairo-tor-scan-converter.c index 75cda4fe..29262c2d 100644 --- a/src/cairo-tor-scan-converter.c +++ b/src/cairo-tor-scan-converter.c @@ -1685,7 +1685,7 @@ glitter_scan_converter_add_edge (glitter_scan_converter_t *converter, INPUT_TO_GRID_Y (edge->top, e.top); INPUT_TO_GRID_Y (edge->bottom, e.bottom); - if (e.top == e.bottom) + if (e.top >= e.bottom) return GLITTER_STATUS_SUCCESS; /* XXX: possible overflows if GRID_X/Y > 2**GLITTER_INPUT_BITS */ @@ -1915,6 +1915,30 @@ _cairo_tor_scan_converter_destroy (void *converter) } static cairo_status_t +_cairo_tor_scan_converter_add_edge (void *converter, + const cairo_point_t *p1, + const cairo_point_t *p2, + int top, int bottom, + int dir) +{ + cairo_tor_scan_converter_t *self = converter; + cairo_status_t status; + cairo_edge_t edge; + + edge.line.p1 = *p1; + edge.line.p2 = *p2; + edge.top = top; + edge.bottom = bottom; + edge.dir = dir; + + status = glitter_scan_converter_add_edge (self->converter, &edge); + if (unlikely (status)) + return _cairo_scan_converter_set_error (self, _cairo_error (status)); + + return CAIRO_STATUS_SUCCESS; +} + +static cairo_status_t _cairo_tor_scan_converter_add_polygon (void *converter, const cairo_polygon_t *polygon) { @@ -1968,6 +1992,7 @@ _cairo_tor_scan_converter_create (int xmin, } self->base.destroy = _cairo_tor_scan_converter_destroy; + self->base.add_edge = _cairo_tor_scan_converter_add_edge; self->base.add_polygon = _cairo_tor_scan_converter_add_polygon; self->base.generate = _cairo_tor_scan_converter_generate; |