mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2026-05-09 07:18:04 +02:00
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.
This commit is contained in:
parent
3023330706
commit
2457c4bede
3 changed files with 127 additions and 1 deletions
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
@ -98,6 +163,22 @@ _cairo_nil_scan_converter_add_polygon (void *abstract_converter,
|
|||
return _cairo_scan_converter_status (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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
@ -1914,6 +1914,30 @@ _cairo_tor_scan_converter_destroy (void *converter)
|
|||
free(self);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue