コード例 #1
0
static cairo_int_status_t
_cairo_analysis_surface_stroke (void			*abstract_surface,
				cairo_operator_t	 op,
				const cairo_pattern_t	*source,
				cairo_path_fixed_t	*path,
				cairo_stroke_style_t	*style,
				cairo_matrix_t		*ctm,
				cairo_matrix_t		*ctm_inverse,
				double			 tolerance,
				cairo_antialias_t	 antialias,
				cairo_rectangle_int_t   *stroke_extents)
{
    cairo_analysis_surface_t *surface = abstract_surface;
    cairo_status_t	     status, backend_status;
    cairo_rectangle_int_t    extents;
    cairo_bool_t             is_empty;

    if (!surface->target->backend->stroke)
	backend_status = CAIRO_INT_STATUS_UNSUPPORTED;
    else
	backend_status = (*surface->target->backend->stroke) (surface->target, op,
							      source, path, style,
							      ctm, ctm_inverse,
							      tolerance, antialias, NULL);

    if (backend_status == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN)
	backend_status = _analyze_meta_surface_pattern (surface, source);

    status = _cairo_surface_get_extents (&surface->base, &extents);
    if (_cairo_status_is_error (status))
	return status;

    if (_cairo_operator_bounded_by_source (op)) {
	cairo_rectangle_int_t source_extents;

	status = _cairo_pattern_get_extents (source, &source_extents);
	if (unlikely (status))
	    return status;

	is_empty = _cairo_rectangle_intersect (&extents, &source_extents);
    }

    is_empty = _cairo_rectangle_intersect (&extents, &surface->current_clip);

    if (_cairo_operator_bounded_by_mask (op)) {
	cairo_rectangle_int_t mask_extents;

	_cairo_path_fixed_approximate_stroke_extents (path,
						      style, ctm,
						      &mask_extents);

	is_empty = _cairo_rectangle_intersect (&extents, &mask_extents);
    }
    if (stroke_extents)
	*stroke_extents = extents;

    status = _add_operation (surface, &extents, backend_status);

    return status;
}
コード例 #2
0
cairo_int_status_t
_cairo_composite_rectangles_lazy_init_for_stroke (cairo_composite_rectangles_t *extents,
						  cairo_surface_t *surface,
						  cairo_operator_t op,
						  const cairo_pattern_t *source,
						  const cairo_path_fixed_t *path,
						  const cairo_stroke_style_t *style,
						  const cairo_matrix_t *ctm,
						  const cairo_clip_t *clip)
{
    cairo_bool_t should_be_lazy = TRUE;

    if (! _cairo_composite_rectangles_init (extents,
					    surface, op, source, clip,
					    &should_be_lazy))
    {
	return CAIRO_INT_STATUS_NOTHING_TO_DO;
    }

    if (! should_be_lazy) {
	_cairo_path_fixed_approximate_stroke_extents (path, style, ctm,
						      &extents->mask);
	return _cairo_composite_rectangles_intersect (extents, clip);
    }

    extents->clip = _cairo_clip_copy (clip);
    return CAIRO_INT_STATUS_SUCCESS;
}
コード例 #3
0
static cairo_int_status_t
_prevent_overlapping_drawing (cairo_gl_context_t 		*ctx,
			      cairo_gl_composite_t 		*setup,
			      cairo_composite_rectangles_t 	*composite,
			      const cairo_path_fixed_t		*path,
			      const cairo_stroke_style_t	*style,
			      const cairo_matrix_t		*ctm)
{
    cairo_rectangle_int_t stroke_extents;
    const cairo_pattern_t *pattern = composite->original_source_pattern;
    cairo_pattern_type_t type = cairo_pattern_get_type ((cairo_pattern_t *) pattern);

    if (! _cairo_gl_ensure_stencil (ctx, setup->dst))
	return CAIRO_INT_STATUS_UNSUPPORTED;


    /* XXX: improve me - since we have lazy init, we cannot use sample
       area */
    if (type == CAIRO_PATTERN_TYPE_SOLID &&
	_cairo_pattern_is_opaque_solid (pattern))
	return CAIRO_INT_STATUS_SUCCESS;

   if (glIsEnabled (GL_STENCIL_TEST) == FALSE) {
       /* In case we have pending operations we have to flush before
	  adding the stencil buffer. */
       _cairo_gl_composite_flush (ctx);

	/* Enable the stencil buffer, even if we are not using it for clipping,
	   so we can use it below to prevent overlapping shapes. We initialize
	   it all to one here which represents infinite clip. */
	if (! ctx->states_cache.depth_mask) {
	    glDepthMask (GL_TRUE);
	    ctx->states_cache.depth_mask = TRUE;
	}
	glEnable (GL_STENCIL_TEST);

	/* If we don't have clip, then we will setup clip extents based on
	   approximate stroke extent. */
	if (! setup->clip) {
	    _cairo_path_fixed_approximate_stroke_extents (path, style, ctm,
							  &stroke_extents);
	    _cairo_gl_scissor_to_extents (setup->dst, &stroke_extents);
	}

	glClearStencil (1);
	glClear (GL_STENCIL_BUFFER_BIT);
	glStencilFunc (GL_EQUAL, 1, 1);
    }

    /* This means that once we draw to a particular pixel nothing else can
       be drawn there until the stencil buffer is reset or the stencil test
       is disabled. */
    glStencilOp (GL_ZERO, GL_ZERO, GL_ZERO);

    /* we need to clean up clip cache */
    _cairo_clip_destroy (ctx->clip);
    ctx->clip = NULL;

    return CAIRO_INT_STATUS_SUCCESS;
}
コード例 #4
0
static cairo_int_status_t
_prevent_overlapping_strokes (cairo_gl_context_t 		*ctx,
			      cairo_gl_composite_t 		*setup,
			      cairo_composite_rectangles_t 	*composite,
			      const cairo_path_fixed_t		*path,
			      const cairo_stroke_style_t	*style,
			      const cairo_matrix_t		*ctm)
{
    cairo_rectangle_int_t stroke_extents;

    if (! _cairo_gl_ensure_stencil (ctx, setup->dst))
	return CAIRO_INT_STATUS_UNSUPPORTED;

    if (_cairo_pattern_is_opaque (&composite->source_pattern.base,
				  &composite->source_sample_area))
	return CAIRO_INT_STATUS_SUCCESS;

   if (glIsEnabled (GL_STENCIL_TEST) == FALSE) {
	cairo_bool_t scissor_was_enabled;

       /* In case we have pending operations we have to flush before
	  adding the stencil buffer. */
       _cairo_gl_composite_flush (ctx);

	/* Enable the stencil buffer, even if we are not using it for clipping,
	   so we can use it below to prevent overlapping shapes. We initialize
	   it all to one here which represents infinite clip. */
	glDepthMask (GL_TRUE);
	glEnable (GL_STENCIL_TEST);

	/* We scissor here so that we don't have to clear the entire stencil
	 * buffer. If the scissor test is already enabled, it was enabled
	 * for clipping. In that case, instead of calculating an intersection,
	 * we just reuse it, and risk clearing too much. */
	scissor_was_enabled = glIsEnabled (GL_SCISSOR_TEST);
	if (! scissor_was_enabled) {
	    _cairo_path_fixed_approximate_stroke_extents (path, style, ctm,
							  FALSE, /* is_vector */
							  &stroke_extents);
	    _cairo_gl_scissor_to_rectangle (setup->dst, &stroke_extents);
	}
	glClearStencil (1);
	glClear (GL_STENCIL_BUFFER_BIT);
	if (! scissor_was_enabled)
	    glDisable (GL_SCISSOR_TEST);

	glStencilFunc (GL_EQUAL, 1, 1);
    }

    /* This means that once we draw to a particular pixel nothing else can
       be drawn there until the stencil buffer is reset or the stencil test
       is disabled. */
    glStencilOp (GL_ZERO, GL_ZERO, GL_ZERO);

    _cairo_clip_destroy (setup->dst->clip_on_stencil_buffer);
    setup->dst->clip_on_stencil_buffer = NULL;

    return CAIRO_INT_STATUS_SUCCESS;
}
コード例 #5
0
cairo_int_status_t
_cairo_composite_rectangles_init_for_stroke (cairo_composite_rectangles_t *extents,
					     cairo_surface_t *surface,
					     cairo_operator_t		 op,
					     const cairo_pattern_t	*source,
					     const cairo_path_fixed_t		*path,
					     const cairo_stroke_style_t	*style,
					     const cairo_matrix_t	*ctm,
					     const cairo_clip_t		*clip)
{
    if (! _cairo_composite_rectangles_init (extents,
					    surface, op, source, clip))
    {
	return CAIRO_INT_STATUS_NOTHING_TO_DO;
    }

    _cairo_path_fixed_approximate_stroke_extents (path, style, ctm, &extents->mask);

    return _cairo_composite_rectangles_intersect (extents, clip);
}