static cairo_int_status_t
check_composite (const cairo_composite_rectangles_t *extents)
{
    if (! _cairo_gl_operator_is_supported (extents->op))
	return UNSUPPORTED ("unsupported operator");

    return CAIRO_STATUS_SUCCESS;
}
Exemplo n.º 2
0
cairo_int_status_t
_cairo_gl_check_composite_glyphs (const cairo_composite_rectangles_t *extents,
				  cairo_scaled_font_t *scaled_font,
				  cairo_glyph_t *glyphs,
				  int *num_glyphs)
{
    if (! _cairo_gl_operator_is_supported (extents->op))
	return UNSUPPORTED ("unsupported operator");

    /* XXX use individual masks for large glyphs? */
    if (ceil (scaled_font->max_scale) >= GLYPH_CACHE_MAX_SIZE)
	return UNSUPPORTED ("glyphs too large");

    return CAIRO_STATUS_SUCCESS;
}
Exemplo n.º 3
0
cairo_bool_t
_cairo_gl_surface_check_span_renderer (cairo_operator_t	       op,
				       const cairo_pattern_t  *pattern,
				       void		      *abstract_dst,
				       cairo_antialias_t       antialias)
{
    if (! _cairo_gl_operator_is_supported (op))
	return FALSE;

    return TRUE;

    (void) pattern;
    (void) abstract_dst;
    (void) antialias;
}
Exemplo n.º 4
0
cairo_status_t
_cairo_gl_composite_set_operator (cairo_gl_composite_t *setup,
				  cairo_operator_t op,
				  cairo_bool_t assume_component_alpha)
{
    if (assume_component_alpha) {
        if (op != CAIRO_OPERATOR_CLEAR &&
            op != CAIRO_OPERATOR_OVER &&
            op != CAIRO_OPERATOR_ADD)
            return UNSUPPORTED ("unsupported component alpha operator");
    } else {
        if (! _cairo_gl_operator_is_supported (op))
            return UNSUPPORTED ("unsupported operator");
    }

    setup->op = op;
    return CAIRO_STATUS_SUCCESS;
}
Exemplo n.º 5
0
cairo_int_status_t
_cairo_gl_surface_composite_trapezoids (cairo_operator_t op,
					const cairo_pattern_t *pattern,
					void *abstract_dst,
					cairo_antialias_t antialias,
					int src_x, int src_y,
					int dst_x, int dst_y,
					unsigned int width,
					unsigned int height,
					cairo_trapezoid_t *traps,
					int num_traps,
					cairo_region_t *clip_region)
{
    cairo_gl_surface_t *dst = abstract_dst;
    cairo_surface_pattern_t traps_pattern;
    cairo_int_status_t status;

    if (! _cairo_gl_operator_is_supported (op))
	return UNSUPPORTED ("unsupported operator");

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

    status = _cairo_gl_get_traps_pattern (dst,
					  dst_x, dst_y, width, height,
					  traps, num_traps, antialias,
					  &traps_pattern);
    if (unlikely (status))
	return status;

    status = _cairo_gl_surface_composite (op,
					  pattern, &traps_pattern.base, dst,
					  src_x, src_y,
					  0, 0,
					  dst_x, dst_y,
					  width, height,
					  clip_region);

    _cairo_pattern_fini (&traps_pattern.base);

    assert (status != CAIRO_INT_STATUS_UNSUPPORTED);
    return status;
}
Exemplo n.º 6
0
cairo_status_t
_cairo_gl_composite_init (cairo_gl_composite_t *setup,
                          cairo_operator_t op,
                          cairo_gl_surface_t *dst,
                          cairo_bool_t assume_component_alpha)
{
    memset (setup, 0, sizeof (cairo_gl_composite_t));

    if (assume_component_alpha) {
        if (op != CAIRO_OPERATOR_CLEAR &&
            op != CAIRO_OPERATOR_OVER &&
            op != CAIRO_OPERATOR_ADD)
            return (cairo_status_t)UNSUPPORTED ("unsupported component alpha operator");
    } else {
        if (! _cairo_gl_operator_is_supported (op))
            return (cairo_status_t)UNSUPPORTED ("unsupported operator");
    }

    setup->dst = dst;
    setup->op = op;
    setup->clip_region = dst->clip_region;

    return CAIRO_STATUS_SUCCESS;
}
cairo_int_status_t
_cairo_gl_surface_show_glyphs (void			*abstract_dst,
			       cairo_operator_t		 op,
			       const cairo_pattern_t	*source,
			       cairo_glyph_t		*glyphs,
			       int			 num_glyphs,
			       cairo_scaled_font_t	*scaled_font,
			       cairo_clip_t		*clip,
			       int			*remaining_glyphs)
{
    cairo_gl_surface_t *dst = abstract_dst;
    cairo_rectangle_int_t surface_extents;
    cairo_rectangle_int_t extents;
    cairo_region_t *clip_region = NULL;
    cairo_solid_pattern_t solid_pattern;
    cairo_bool_t overlap, use_mask = FALSE;
    cairo_status_t status;

    if (! GLEW_ARB_vertex_buffer_object)
	return UNSUPPORTED ("requires ARB_vertex_buffer_object");

    if (! _cairo_gl_operator_is_supported (op))
	return UNSUPPORTED ("unsupported operator");

    if (! _cairo_operator_bounded_by_mask (op))
	use_mask |= TRUE;

    /* For CLEAR, cairo's rendering equation (quoting Owen's description in:
     * http://lists.cairographics.org/archives/cairo/2005-August/004992.html)
     * is:
     *     mask IN clip ? src OP dest : dest
     * or more simply:
     *     mask IN CLIP ? 0 : dest
     *
     * where the ternary operator A ? B : C is (A * B) + ((1 - A) * C).
     *
     * The model we use in _cairo_gl_set_operator() is Render's:
     *     src IN mask IN clip OP dest
     * which would boil down to:
     *     0 (bounded by the extents of the drawing).
     *
     * However, we can do a Render operation using an opaque source
     * and DEST_OUT to produce:
     *    1 IN mask IN clip DEST_OUT dest
     * which is
     *    mask IN clip ? 0 : dest
     */
    if (op == CAIRO_OPERATOR_CLEAR) {
	_cairo_pattern_init_solid (&solid_pattern, CAIRO_COLOR_WHITE,
				   CAIRO_CONTENT_COLOR);
	source = &solid_pattern.base;
	op = CAIRO_OPERATOR_DEST_OUT;
    }

    /* For SOURCE, cairo's rendering equation is:
     *     (mask IN clip) ? src OP dest : dest
     * or more simply:
     *     (mask IN clip) ? src : dest.
     *
     * If we just used the Render equation, we would get:
     *     (src IN mask IN clip) OP dest
     * or:
     *     (src IN mask IN clip) bounded by extents of the drawing.
     *
     * The trick is that for GL blending, we only get our 4 source values
     * into the blender, and since we need all 4 components of source, we
     * can't also get the mask IN clip into the blender.  But if we did
     * two passes we could make it work:
     *     dest = (mask IN clip) DEST_OUT dest
     *     dest = src IN mask IN clip ADD dest
     *
     * But for now, composite via an intermediate mask.
     */
    if (op == CAIRO_OPERATOR_SOURCE)
	use_mask |= TRUE;

    /* XXX we don't need ownership of the font as we use a global
     * glyph cache -- but we do need scaled_glyph eviction notification. :-(
     */
    if (! _cairo_gl_surface_owns_font (dst, scaled_font))
	return UNSUPPORTED ("do not control font");

    /* If the glyphs overlap, we need to build an intermediate mask rather
     * then perform the compositing directly.
     */
    status = _cairo_scaled_font_glyph_device_extents (scaled_font,
						      glyphs, num_glyphs,
						      &extents,
						      &overlap);
    if (unlikely (status))
	return status;

    use_mask |= overlap;

    if (clip != NULL) {
	status = _cairo_clip_get_region (clip, &clip_region);
	/* the empty clip should never be propagated this far */
	assert (status != CAIRO_INT_STATUS_NOTHING_TO_DO);
	if (unlikely (_cairo_status_is_error (status)))
	    return status;

	use_mask |= status == CAIRO_INT_STATUS_UNSUPPORTED;

	if (! _cairo_rectangle_intersect (&extents,
		                          _cairo_clip_get_extents (clip)))
	    goto EMPTY;
    }

    surface_extents.x = surface_extents.y = 0;
    surface_extents.width = dst->width;
    surface_extents.height = dst->height;
    if (! _cairo_rectangle_intersect (&extents, &surface_extents))
	goto EMPTY;

    if (use_mask) {
	return _cairo_gl_surface_show_glyphs_via_mask (dst, op,
			                               source,
			                               glyphs, num_glyphs,
						       &extents,
						       scaled_font,
						       clip,
						       remaining_glyphs);
    }

    return _render_glyphs (dst, extents.x, extents.y,
	                   op, source,
			   glyphs, num_glyphs, &extents,
			   scaled_font, clip_region, remaining_glyphs);

EMPTY:
    *remaining_glyphs = 0;
    if (! _cairo_operator_bounded_by_mask (op))
	return _cairo_surface_paint (&dst->base, op, source, clip);
    else
	return CAIRO_STATUS_SUCCESS;
}