Example #1
0
static cairo_int_status_t
_cairo_gl_surface_fill_alpha_channel (cairo_gl_surface_t *dst,
				      cairo_gl_context_t *ctx,
				      int x, int y,
				      int width, int height)
{
    cairo_gl_composite_t setup;
    cairo_status_t status;

    _cairo_gl_composite_flush (ctx);
    glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE);

    status = _cairo_gl_composite_init (&setup, CAIRO_OPERATOR_SOURCE, dst,
                                       FALSE, NULL);
    if (unlikely (status))
        goto CLEANUP;

    _cairo_gl_composite_set_solid_source (&setup, CAIRO_COLOR_BLACK);

    status = _cairo_gl_composite_begin (&setup, &ctx);
    if (unlikely (status))
        goto CLEANUP;

    _cairo_gl_composite_emit_rect (ctx, x, y, x + width, y + height, 0);

    status = _cairo_gl_context_release (ctx, status);

  CLEANUP:
    _cairo_gl_composite_fini (&setup);

    _cairo_gl_composite_flush (ctx);
    glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);

    return status;
}
void
_cairo_gl_context_emit_rect (cairo_gl_context_t *ctx,
			     GLfloat x1, GLfloat y1,
			     GLfloat x2, GLfloat y2)
{
    _cairo_gl_composite_emit_rect (ctx, x1, y1, x2, y2);
}
cairo_int_status_t
_cairo_gl_surface_fill_rectangles (void			   *abstract_dst,
				   cairo_operator_t	    op,
				   const cairo_color_t     *color,
				   cairo_rectangle_int_t   *rects,
				   int			    num_rects)
{
    cairo_gl_surface_t *dst = abstract_dst;
    cairo_solid_pattern_t solid;
    cairo_gl_context_t *ctx;
    cairo_status_t status;
    cairo_gl_composite_t setup;
    int i;

    status = _cairo_gl_surface_deferred_clear (dst);
    if (unlikely (status))
	    return status;

    status = _cairo_gl_composite_init (&setup, op, dst,
                                       FALSE,
                                       /* XXX */ NULL);
    if (unlikely (status))
        goto CLEANUP;

    _cairo_pattern_init_solid (&solid, color);
    status = _cairo_gl_composite_set_source (&setup, &solid.base,
                                             0, 0,
                                             0, 0,
                                             0, 0,
                                             FALSE);
    if (unlikely (status))
        goto CLEANUP;

    status = _cairo_gl_composite_set_mask (&setup, NULL,
                                           0, 0,
                                           0, 0,
                                           0, 0);
    if (unlikely (status))
        goto CLEANUP;

    status = _cairo_gl_composite_begin (&setup, &ctx);
    if (unlikely (status))
        goto CLEANUP;

    for (i = 0; i < num_rects; i++) {
        _cairo_gl_composite_emit_rect (ctx,
                                       rects[i].x,
                                       rects[i].y,
                                       rects[i].x + rects[i].width,
                                       rects[i].y + rects[i].height,
                                       0);
    }

    status = _cairo_gl_context_release (ctx, status);

  CLEANUP:
    _cairo_gl_composite_fini (&setup);

    return status;
}
static cairo_status_t
_cairo_gl_render_unbounded_spans (void *abstract_renderer,
				  int y, int height,
				  const cairo_half_open_span_t *spans,
				  unsigned num_spans)
{
    cairo_gl_surface_span_renderer_t *renderer = abstract_renderer;

    if (y > renderer->ymin) {
        _cairo_gl_composite_emit_rect (renderer->ctx,
                                       renderer->xmin, renderer->ymin,
                                       renderer->xmax, y,
                                       0);
    }

    if (num_spans == 0) {
        _cairo_gl_composite_emit_rect (renderer->ctx,
                                       renderer->xmin, y,
                                       renderer->xmax, y + height,
                                       0);
    } else {
        if (spans[0].x != renderer->xmin) {
            _cairo_gl_composite_emit_rect (renderer->ctx,
                                           renderer->xmin, y,
                                           spans[0].x,     y + height,
                                           0);
        }

        do {
            _cairo_gl_composite_emit_rect (renderer->ctx,
                                           spans[0].x, y,
                                           spans[1].x, y + height,
                                           spans[0].coverage);
            spans++;
        } while (--num_spans > 1);

        if (spans[0].x != renderer->xmax) {
            _cairo_gl_composite_emit_rect (renderer->ctx,
                                           spans[0].x,     y,
                                           renderer->xmax, y + height,
                                           0);
        }
    }

    renderer->ymin = y + height;
    return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
_cairo_gl_finish_unbounded_spans (void *abstract_renderer)
{
    cairo_gl_surface_span_renderer_t *renderer = abstract_renderer;

    if (renderer->ymax > renderer->ymin) {
        _cairo_gl_composite_emit_rect (renderer->ctx,
                                       renderer->xmin, renderer->ymin,
                                       renderer->xmax, renderer->ymax,
                                       0);
    }

    return _cairo_gl_context_release (renderer->ctx, CAIRO_STATUS_SUCCESS);
}
static cairo_status_t
_cairo_gl_render_bounded_spans (void *abstract_renderer,
				int y, int height,
				const cairo_half_open_span_t *spans,
				unsigned num_spans)
{
    cairo_gl_surface_span_renderer_t *renderer = abstract_renderer;

    if (num_spans == 0)
	return CAIRO_STATUS_SUCCESS;

    do {
	if (spans[0].coverage) {
            _cairo_gl_composite_emit_rect (renderer->ctx,
                                           spans[0].x, y,
                                           spans[1].x, y + height,
                                           spans[0].coverage);
	}

	spans++;
    } while (--num_spans > 1);

    return CAIRO_STATUS_SUCCESS;
}
cairo_int_status_t
_cairo_gl_surface_composite (cairo_operator_t		  op,
			     const cairo_pattern_t	 *src,
			     const cairo_pattern_t	 *mask,
			     void			 *abstract_dst,
			     int			  src_x,
			     int			  src_y,
			     int			  mask_x,
			     int			  mask_y,
			     int			  dst_x,
			     int			  dst_y,
			     unsigned int		  width,
			     unsigned int		  height,
			     cairo_region_t		 *clip_region)
{
    cairo_gl_surface_t *dst = abstract_dst;
    cairo_gl_context_t *ctx;
    cairo_status_t status;
    cairo_gl_composite_t setup;
    cairo_rectangle_int_t rect = { dst_x, dst_y, width, height };
    int dx, dy;

    status = _cairo_gl_surface_deferred_clear (dst);
    if (unlikely (status))
	    return status;

    if (op == CAIRO_OPERATOR_SOURCE &&
        mask == NULL &&
        src->type == CAIRO_PATTERN_TYPE_SURFACE &&
        _cairo_surface_is_image (((cairo_surface_pattern_t *) src)->surface) &&
        _cairo_matrix_is_integer_translation (&src->matrix, &dx, &dy)) {
        cairo_image_surface_t *image = (cairo_image_surface_t *)
            ((cairo_surface_pattern_t *) src)->surface;
        dx += src_x;
        dy += src_y;
        if (dx >= 0 &&
            dy >= 0 &&
            dx + width <= (unsigned int) image->width &&
            dy + height <= (unsigned int) image->height) {
            status = _cairo_gl_surface_draw_image (dst, image,
                                                   dx, dy,
                                                   width, height,
                                                   dst_x, dst_y);
            if (status != CAIRO_INT_STATUS_UNSUPPORTED)
                return status;
        }
    }

    status = _cairo_gl_composite_init (&setup, op, dst,
                                       mask && mask->has_component_alpha,
                                       &rect);
    if (unlikely (status))
        goto CLEANUP;

    status = _cairo_gl_composite_set_source (&setup, src,
                                             src_x, src_y,
                                             dst_x, dst_y,
                                             width, height);
    if (unlikely (status))
        goto CLEANUP;

    status = _cairo_gl_composite_set_mask (&setup, mask,
                                           mask_x, mask_y,
                                           dst_x, dst_y,
                                           width, height);
    if (unlikely (status))
        goto CLEANUP;

    status = _cairo_gl_composite_begin (&setup, &ctx);
    if (unlikely (status))
	goto CLEANUP;

    if (clip_region != NULL) {
        int i, num_rectangles;

        num_rectangles = cairo_region_num_rectangles (clip_region);

	for (i = 0; i < num_rectangles; i++) {
	    cairo_rectangle_int_t rect;

	    cairo_region_get_rectangle (clip_region, i, &rect);
            _cairo_gl_composite_emit_rect (ctx,
                                           rect.x,              rect.y,
                                           rect.x + rect.width, rect.y + rect.height,
                                           0);
	}
    } else {
        _cairo_gl_composite_emit_rect (ctx,
                                       dst_x,         dst_y,
                                       dst_x + width, dst_y + height,
                                       0);
    }

    status = _cairo_gl_context_release (ctx, status);

  CLEANUP:
    _cairo_gl_composite_fini (&setup);

    return status;
}