Exemplo n.º 1
0
static cairo_int_status_t
_cairo_xcb_surface_mask (void			*abstract_surface,
			 cairo_operator_t	 op,
			 const cairo_pattern_t	*source,
			 const cairo_pattern_t	*mask,
			 cairo_clip_t		*clip)
{
    cairo_xcb_surface_t *surface = abstract_surface;
    cairo_status_t status;

    if (surface->drm != NULL && ! surface->marked_dirty)
	return _cairo_surface_mask (surface->drm, op, source, mask, clip);

    if (surface->fallback == NULL) {
	status =  _cairo_xcb_surface_cairo_mask (surface,
						 op, source, mask, clip);
	if (status != CAIRO_INT_STATUS_UNSUPPORTED)
	    return status;

	status =  _cairo_xcb_surface_render_mask (surface,
						  op, source, mask, clip);
	if (status != CAIRO_INT_STATUS_UNSUPPORTED)
	    return status;

	surface->fallback = _cairo_xcb_surface_map_to_image (surface);
    }

    return _cairo_surface_mask (surface->fallback,
				op, source, mask,
				clip);
}
Exemplo n.º 2
0
static cairo_int_status_t
radeon_surface_mask (void			*abstract_surface,
		    cairo_operator_t		 op,
		    const cairo_pattern_t	*source,
		    const cairo_pattern_t	*mask,
		    cairo_clip_t		*clip)
{
    return _cairo_surface_mask (radeon_surface_map_to_image (abstract_surface),
				op, source, mask, clip);
}
Exemplo n.º 3
0
static cairo_int_status_t
_cairo_paginated_surface_mask (void		*abstract_surface,
			       cairo_operator_t	 op,
			       cairo_pattern_t	*source,
			       cairo_pattern_t	*mask)
{
    cairo_paginated_surface_t *surface = abstract_surface;

    return _cairo_surface_mask (surface->meta, op, source, mask);
}
Exemplo n.º 4
0
static cairo_int_status_t
render_glyphs_via_mask (cairo_gl_surface_t *dst,
			int dst_x, int dst_y,
			cairo_operator_t  op,
			cairo_surface_t *source,
			cairo_composite_glyphs_info_t *info)
{
    cairo_surface_t *mask;
    cairo_status_t status;
    cairo_bool_t has_component_alpha;

    TRACE ((stderr, "%s\n", __FUNCTION__));

    /* XXX: For non-CA, this should be CAIRO_CONTENT_ALPHA to save memory */
    mask = cairo_gl_surface_create (dst->base.device,
                                    CAIRO_CONTENT_COLOR_ALPHA,
                                    info->extents.width,
                                    info->extents.height);
    if (unlikely (mask->status))
        return mask->status;

    status = render_glyphs ((cairo_gl_surface_t *) mask,
			    info->extents.x, info->extents.y,
			    CAIRO_OPERATOR_ADD, NULL,
			    info, &has_component_alpha);
    if (likely (status == CAIRO_STATUS_SUCCESS)) {
	cairo_surface_pattern_t mask_pattern;
	cairo_surface_pattern_t source_pattern;

	mask->is_clear = FALSE;
	_cairo_pattern_init_for_surface (&mask_pattern, mask);
	mask_pattern.base.has_component_alpha = has_component_alpha;
	mask_pattern.base.filter = CAIRO_FILTER_NEAREST;
	mask_pattern.base.extend = CAIRO_EXTEND_NONE;

	cairo_matrix_init_translate (&mask_pattern.base.matrix,
		                     dst_x-info->extents.x, dst_y-info->extents.y);

	_cairo_pattern_init_for_surface (&source_pattern, source);
	cairo_matrix_init_translate (&source_pattern.base.matrix,
		                     dst_x-info->extents.x, dst_y-info->extents.y);

	status = _cairo_surface_mask (&dst->base, op,
		                      &source_pattern.base,
				      &mask_pattern.base,
				      NULL);

	_cairo_pattern_fini (&mask_pattern.base);
	_cairo_pattern_fini (&source_pattern.base);
    }

    cairo_surface_destroy (mask);

    return status;
}
static cairo_int_status_t
_cairo_quartz_image_surface_mask (void				*abstract_surface,
				  cairo_operator_t		 op,
				  const cairo_pattern_t		*source,
				  const cairo_pattern_t		*mask,
				  const cairo_clip_t		*clip)
{
    cairo_quartz_image_surface_t *surface = abstract_surface;
    return _cairo_surface_mask (&surface->imageSurface->base,
				op, source, mask, clip);
}
static cairo_int_status_t
_cairo_paginated_surface_mask (void		*abstract_surface,
			       cairo_operator_t	 op,
			       const cairo_pattern_t	*source,
			       const cairo_pattern_t	*mask,
			       const cairo_clip_t		*clip)
{
    cairo_paginated_surface_t *surface = abstract_surface;

    return (cairo_int_status_t)_cairo_surface_mask (surface->recording_surface, op, source, mask, clip);
}
Exemplo n.º 7
0
static cairo_int_status_t
_cairo_xcb_fallback_compositor_mask (const cairo_compositor_t     *compositor,
				     cairo_composite_rectangles_t *extents)
{
    cairo_xcb_surface_t *surface = (cairo_xcb_surface_t *) extents->surface;
    cairo_surface_t *fallback = _cairo_xcb_surface_fallback (surface, extents);

    return _cairo_surface_mask (fallback, extents->op,
				 &extents->source_pattern.base,
				 &extents->mask_pattern.base,
				 extents->clip);
}
static cairo_int_status_t
_cairo_gl_surface_show_glyphs_via_mask (cairo_gl_surface_t	*dst,
			                cairo_operator_t	 op,
					const cairo_pattern_t	*source,
					cairo_glyph_t		*glyphs,
					int			 num_glyphs,
					const cairo_rectangle_int_t *glyph_extents,
					cairo_scaled_font_t	*scaled_font,
					cairo_clip_t		*clip,
					int			*remaining_glyphs)
{
    cairo_surface_t *mask;
    cairo_status_t status;
    cairo_solid_pattern_t solid;
    int i;

    mask = cairo_gl_surface_create (dst->ctx,
	                            CAIRO_CONTENT_ALPHA,
				    glyph_extents->width,
				    glyph_extents->height);
    if (unlikely (mask->status))
	return mask->status;

    for (i = 0; i < num_glyphs; i++) {
	glyphs[i].x -= glyph_extents->x;
	glyphs[i].y -= glyph_extents->y;
    }

    _cairo_pattern_init_solid (&solid, CAIRO_COLOR_WHITE, CAIRO_CONTENT_ALPHA);
    status = _render_glyphs ((cairo_gl_surface_t *) mask, 0, 0,
	                     CAIRO_OPERATOR_ADD, &solid.base,
	                     glyphs, num_glyphs, glyph_extents,
			     scaled_font, NULL, remaining_glyphs);
    if (likely (status == CAIRO_STATUS_SUCCESS)) {
	cairo_surface_pattern_t mask_pattern;

	_cairo_pattern_init_for_surface (&mask_pattern, mask);
	cairo_matrix_init_translate (&mask_pattern.base.matrix,
		                     -glyph_extents->x, -glyph_extents->y);
	status = _cairo_surface_mask (&dst->base, op,
		                      source, &mask_pattern.base, clip);
	_cairo_pattern_fini (&mask_pattern.base);
    } else {
	for (i = 0; i < num_glyphs; i++) {
	    glyphs[i].x += glyph_extents->x;
	    glyphs[i].y += glyph_extents->y;
	}
	*remaining_glyphs = num_glyphs;
    }

    cairo_surface_destroy (mask);
    return status;
}
Exemplo n.º 9
0
static cairo_int_status_t
_test_paginated_surface_mask (void		*abstract_surface,
			      cairo_operator_t	 op,
			      cairo_pattern_t	*source,
			      cairo_pattern_t	*mask)
{
    test_paginated_surface_t *surface = abstract_surface;

    if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
	return CAIRO_STATUS_SUCCESS;

    return _cairo_surface_mask (surface->target, op, source, mask);
}
Exemplo n.º 10
0
cairo_status_t
_cairo_surface_offset_mask (cairo_surface_t		*target,
			    int x, int y,
			    cairo_operator_t		 op,
			    const cairo_pattern_t	*source,
			    const cairo_pattern_t	*mask,
			    cairo_clip_t		*clip)
{
    cairo_status_t status;
    cairo_clip_t clip_copy, *dev_clip = clip;
    cairo_pattern_union_t source_copy;
    cairo_pattern_union_t mask_copy;

    if (unlikely (target->status))
	return target->status;

    if (clip && clip->all_clipped)
	return CAIRO_STATUS_SUCCESS;

    if (x | y) {
	cairo_matrix_t m;

	if (clip != NULL) {
	    cairo_matrix_init_translate (&m, -x, -y);
	    status = _cairo_clip_init_copy_transformed (&clip_copy, clip, &m);
	    if (unlikely (status))
		goto FINISH;

	    dev_clip = &clip_copy;
	}

	cairo_matrix_init_translate (&m, x, y);
	_copy_transformed_pattern (&source_copy.base, source, &m);
	_copy_transformed_pattern (&mask_copy.base, mask, &m);
	source = &source_copy.base;
	mask = &mask_copy.base;
    }

    status = _cairo_surface_mask (target, op,
				  &source_copy.base, &mask_copy.base,
				  dev_clip);

  FINISH:
    if (dev_clip != clip)
	_cairo_clip_reset (dev_clip);

    return status;
}
Exemplo n.º 11
0
static cairo_int_status_t
gallium_surface_mask (void			*abstract_surface,
                      cairo_operator_t	 op,
                      const cairo_pattern_t	*source,
                      const cairo_pattern_t	*mask,
                      cairo_clip_t		*clip)
{
    gallium_surface_t *surface = abstract_surface;

    if (surface->fallback == NULL) {
        /* XXX insert magic */
        surface->fallback = gallium_surface_map_to_image (surface);
    }

    return _cairo_surface_mask (surface->fallback,
                                op, source, mask,
                                clip);
}
cairo_status_t
_cairo_surface_wrapper_mask (cairo_surface_wrapper_t *wrapper,
			     cairo_operator_t	 op,
			     const cairo_pattern_t *source,
			     const cairo_pattern_t *mask,
			     cairo_clip_t	    *clip)
{
    cairo_status_t status;
    cairo_matrix_t device_transform;
    cairo_clip_t clip_copy, *dev_clip = clip;

    if (unlikely (wrapper->target->status))
	return wrapper->target->status;

    if (clip && clip->all_clipped)
	return CAIRO_STATUS_SUCCESS;

    if (clip != NULL) {
	if (_cairo_surface_wrapper_needs_device_transform (wrapper,
							   &device_transform))
	{
	    status = _cairo_clip_init_copy_transformed (&clip_copy, clip,
							&device_transform);
	    if (unlikely (status))
		goto FINISH;

	} else {
	    _cairo_clip_init_copy (&clip_copy, clip);
	}

	dev_clip = &clip_copy;
    }

    status = _cairo_surface_mask (wrapper->target, op, source, mask, dev_clip);

  FINISH:
    if (dev_clip != clip)
	_cairo_clip_reset (dev_clip);
    return status;
}
Exemplo n.º 13
0
cairo_status_t
_cairo_surface_offset_mask (cairo_surface_t		*target,
			    int x, int y,
			    cairo_operator_t		 op,
			    const cairo_pattern_t	*source,
			    const cairo_pattern_t	*mask,
			    const cairo_clip_t		*clip)
{
    cairo_status_t status;
    cairo_clip_t *dev_clip = (cairo_clip_t *) clip;
    cairo_pattern_union_t source_copy;
    cairo_pattern_union_t mask_copy;

    if (unlikely (target->status))
	return target->status;

    if (_cairo_clip_is_all_clipped (clip))
	return CAIRO_STATUS_SUCCESS;

    if (x | y) {
	cairo_matrix_t m;

	dev_clip = _cairo_clip_copy_with_translation (clip, -x, -y);

	cairo_matrix_init_translate (&m, x, y);
	_copy_transformed_pattern (&source_copy.base, source, &m);
	_copy_transformed_pattern (&mask_copy.base, mask, &m);
	source = &source_copy.base;
	mask = &mask_copy.base;
    }

    status = _cairo_surface_mask (target, op,
				  source, mask,
				  dev_clip);

    if (dev_clip != clip)
	_cairo_clip_destroy (dev_clip);

    return status;
}
Exemplo n.º 14
0
cairo_status_t
_cairo_surface_wrapper_mask (cairo_surface_wrapper_t *wrapper,
			     cairo_operator_t	 op,
			     const cairo_pattern_t *source,
			     const cairo_pattern_t *mask,
			     const cairo_clip_t	    *clip)
{
    cairo_status_t status;
    cairo_clip_t *dev_clip;
    cairo_pattern_union_t source_copy;
    cairo_pattern_union_t mask_copy;

    if (unlikely (wrapper->target->status))
	return wrapper->target->status;

    dev_clip = _cairo_surface_wrapper_get_clip (wrapper, clip);
    if (_cairo_clip_is_all_clipped (dev_clip))
	return (cairo_status_t)CAIRO_INT_STATUS_NOTHING_TO_DO;

    if (wrapper->needs_transform) {
	cairo_matrix_t m;

	_cairo_surface_wrapper_get_transform (wrapper, &m);

	status = cairo_matrix_invert (&m);
	assert (status == CAIRO_STATUS_SUCCESS);

	_copy_transformed_pattern (&source_copy.base, source, &m);
	source = &source_copy.base;

	_copy_transformed_pattern (&mask_copy.base, mask, &m);
	mask = &mask_copy.base;
    }

    status = _cairo_surface_mask (wrapper->target, op, source, mask, dev_clip);

    _cairo_clip_destroy (dev_clip);
    return status;
}
Exemplo n.º 15
0
static cairo_int_status_t
_cairo_xcb_surface_mask (void			*abstract_surface,
			 cairo_operator_t	 op,
			 const cairo_pattern_t	*source,
			 const cairo_pattern_t	*mask,
			 const cairo_clip_t	*clip)
{
    cairo_xcb_surface_t *surface = abstract_surface;
    cairo_composite_rectangles_t composite;
    cairo_int_status_t status;

    status = _cairo_composite_rectangles_init_for_mask (&composite,
							&surface->base,
							op, source, mask, clip);
    if (unlikely (status))
	return status;

    if (surface->fallback == NULL) {
	status =  _cairo_xcb_surface_cairo_mask (surface,
						 op, source, mask, clip);
	if (status != CAIRO_INT_STATUS_UNSUPPORTED)
	    goto done;

	status =  _cairo_xcb_surface_render_mask (surface,
						  op, source, mask, &composite);
	if (status != CAIRO_INT_STATUS_UNSUPPORTED)
	    goto done;
    }

    status = _cairo_surface_mask (_cairo_xcb_surface_fallback (surface,
							       &composite),
				  op, source, mask,
				  clip);
done:
    _cairo_composite_rectangles_fini (&composite);
    return status;
}
Exemplo n.º 16
0
static cairo_status_t
_cairo_meta_surface_replay_internal (cairo_surface_t	     *surface,
				     cairo_surface_t	     *target,
				     cairo_meta_replay_type_t type,
				     cairo_meta_region_type_t region)
{
    cairo_meta_surface_t *meta;
    cairo_command_t *command, **elements;
    int i, num_elements;
    cairo_int_status_t status, status2;
    cairo_clip_t clip, *old_clip;
    cairo_bool_t has_device_transform = _cairo_surface_has_device_transform (target);
    cairo_matrix_t *device_transform = &target->device_transform;
    cairo_path_fixed_t path_copy, *dev_path;

    if (surface->status)
	return surface->status;

    if (target->status)
	return _cairo_surface_set_error (surface, target->status);

    meta = (cairo_meta_surface_t *) surface;
    status = CAIRO_STATUS_SUCCESS;

    _cairo_clip_init (&clip, target);
    old_clip = _cairo_surface_get_clip (target);

    num_elements = meta->commands.num_elements;
    elements = _cairo_array_index (&meta->commands, 0);
    for (i = meta->replay_start_idx; i < num_elements; i++) {
	command = elements[i];

	if (type == CAIRO_META_REPLAY && region != CAIRO_META_REGION_ALL) {
	    if (command->header.region != region)
		continue;
        }

	/* For all commands except intersect_clip_path, we have to
	 * ensure the current clip gets set on the surface. */
	if (command->header.type != CAIRO_COMMAND_INTERSECT_CLIP_PATH) {
	    status = _cairo_surface_set_clip (target, &clip);
	    if (status)
		break;
	}

	dev_path = _cairo_command_get_path (command);
	if (dev_path && has_device_transform) {
	    status = _cairo_path_fixed_init_copy (&path_copy, dev_path);
	    if (status)
		break;
	    _cairo_path_fixed_transform (&path_copy, device_transform);
	    dev_path = &path_copy;
	}

	switch (command->header.type) {
	case CAIRO_COMMAND_PAINT:
	    status = _cairo_surface_paint (target,
					   command->paint.op,
					   &command->paint.source.base);
	    break;
	case CAIRO_COMMAND_MASK:
	    status = _cairo_surface_mask (target,
					  command->mask.op,
					  &command->mask.source.base,
					  &command->mask.mask.base);
	    break;
	case CAIRO_COMMAND_STROKE:
	{
	    cairo_matrix_t dev_ctm = command->stroke.ctm;
	    cairo_matrix_t dev_ctm_inverse = command->stroke.ctm_inverse;

	    if (has_device_transform) {
		cairo_matrix_multiply (&dev_ctm, &dev_ctm, device_transform);
		cairo_matrix_multiply (&dev_ctm_inverse,
				       &target->device_transform_inverse,
				       &dev_ctm_inverse);
	    }

	    status = _cairo_surface_stroke (target,
					    command->stroke.op,
					    &command->stroke.source.base,
					    dev_path,
					    &command->stroke.style,
					    &dev_ctm,
					    &dev_ctm_inverse,
					    command->stroke.tolerance,
					    command->stroke.antialias);
	    break;
	}
	case CAIRO_COMMAND_FILL:
	{
	    cairo_command_t *stroke_command;

	    if (type != CAIRO_META_CREATE_REGIONS)
		stroke_command = (i < num_elements - 1) ? elements[i + 1] : NULL;
	    else
		stroke_command = NULL;

	    if (stroke_command != NULL &&
		type == CAIRO_META_REPLAY && region != CAIRO_META_REGION_ALL)
	    {
		if (stroke_command->header.region != region)
		    stroke_command = NULL;
	    }
	    if (stroke_command != NULL &&
		stroke_command->header.type == CAIRO_COMMAND_STROKE &&
		_cairo_path_fixed_is_equal (dev_path, _cairo_command_get_path (stroke_command))) {
		cairo_matrix_t dev_ctm;
		cairo_matrix_t dev_ctm_inverse;

		dev_ctm = stroke_command->stroke.ctm;
		dev_ctm_inverse = stroke_command->stroke.ctm_inverse;

		if (has_device_transform) {
		    cairo_matrix_multiply (&dev_ctm, &dev_ctm, device_transform);
		    cairo_matrix_multiply (&dev_ctm_inverse,
					   &surface->device_transform_inverse,
					   &dev_ctm_inverse);
		}

		status = _cairo_surface_fill_stroke (target,
						     command->fill.op,
						     &command->fill.source.base,
						     command->fill.fill_rule,
						     command->fill.tolerance,
						     command->fill.antialias,
						     dev_path,
						     stroke_command->stroke.op,
						     &stroke_command->stroke.source.base,
						     &stroke_command->stroke.style,
						     &dev_ctm,
						     &dev_ctm_inverse,
						     stroke_command->stroke.tolerance,
						     stroke_command->stroke.antialias);
		i++;
	    } else
		status = _cairo_surface_fill (target,
					      command->fill.op,
					      &command->fill.source.base,
					      dev_path,
					      command->fill.fill_rule,
					      command->fill.tolerance,
					      command->fill.antialias);
	    break;
	}
	case CAIRO_COMMAND_SHOW_TEXT_GLYPHS:
	{
	    cairo_glyph_t *glyphs = command->show_text_glyphs.glyphs;
	    cairo_glyph_t *dev_glyphs;
	    int i, num_glyphs = command->show_text_glyphs.num_glyphs;

            /* show_text_glyphs is special because _cairo_surface_show_text_glyphs is allowed
	     * to modify the glyph array that's passed in.  We must always
	     * copy the array before handing it to the backend.
	     */
	    dev_glyphs = _cairo_malloc_ab (num_glyphs, sizeof (cairo_glyph_t));
	    if (dev_glyphs == NULL) {
		status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
		break;
	    }

	    if (has_device_transform) {
		for (i = 0; i < num_glyphs; i++) {
		    dev_glyphs[i] = glyphs[i];
		    cairo_matrix_transform_point (device_transform,
						  &dev_glyphs[i].x,
						  &dev_glyphs[i].y);
		}
	    } else {
		memcpy (dev_glyphs, glyphs, sizeof (cairo_glyph_t) * num_glyphs);
	    }

	    status = _cairo_surface_show_text_glyphs	(target,
							 command->show_text_glyphs.op,
							 &command->show_text_glyphs.source.base,
							 command->show_text_glyphs.utf8, command->show_text_glyphs.utf8_len,
							 dev_glyphs, num_glyphs,
							 command->show_text_glyphs.clusters, command->show_text_glyphs.num_clusters,
							 command->show_text_glyphs.cluster_flags,
							 command->show_text_glyphs.scaled_font);

	    free (dev_glyphs);
	    break;
	}
	case CAIRO_COMMAND_INTERSECT_CLIP_PATH:
	    /* XXX Meta surface clipping is broken and requires some
	     * cairo-gstate.c rewriting.  Work around it for now. */
	    if (dev_path == NULL)
		_cairo_clip_reset (&clip);
	    else
		status = _cairo_clip_clip (&clip, dev_path,
					   command->intersect_clip_path.fill_rule,
					   command->intersect_clip_path.tolerance,
					   command->intersect_clip_path.antialias,
					   target);
	    break;
	default:
	    ASSERT_NOT_REACHED;
	}

	if (dev_path == &path_copy)
	    _cairo_path_fixed_fini (&path_copy);

	if (type == CAIRO_META_CREATE_REGIONS) {
	    if (status == CAIRO_STATUS_SUCCESS) {
		command->header.region = CAIRO_META_REGION_NATIVE;
	    } else if (status == CAIRO_INT_STATUS_IMAGE_FALLBACK) {
		command->header.region = CAIRO_META_REGION_IMAGE_FALLBACK;
		status = CAIRO_STATUS_SUCCESS;
	    }
	}

	if (status)
	    break;
    }

    _cairo_clip_reset (&clip);
    status2 = _cairo_surface_set_clip (target, old_clip);
    if (status == CAIRO_STATUS_SUCCESS)
	status = status2;

    return _cairo_surface_set_error (surface, status);
}
Exemplo n.º 17
0
cairo_status_t
_cairo_surface_wrapper_mask (cairo_surface_wrapper_t *wrapper,
                             cairo_operator_t	 op,
                             const cairo_pattern_t *source,
                             const cairo_pattern_t *mask,
                             cairo_clip_t	    *clip)
{
    cairo_status_t status;
    cairo_clip_t clip_copy, *dev_clip = clip;
    cairo_pattern_union_t source_copy;
    cairo_pattern_union_t mask_copy;
    cairo_clip_t target_clip;

    if (unlikely (wrapper->target->status))
        return wrapper->target->status;

    if (wrapper->has_extents) {
        _cairo_clip_init_copy (&target_clip, clip);
        status = _cairo_clip_rectangle (&target_clip, &wrapper->extents);
        if (unlikely (status))
            goto FINISH;

        dev_clip = clip = &target_clip;
    }

    if (clip && clip->all_clipped) {
        status = CAIRO_STATUS_SUCCESS;
        goto FINISH;
    }

    if (_cairo_surface_wrapper_needs_device_transform (wrapper) ||
            _cairo_surface_wrapper_needs_extents_transform (wrapper))
    {
        cairo_matrix_t m;

        cairo_matrix_init_identity (&m);

        if (_cairo_surface_wrapper_needs_extents_transform (wrapper))
            cairo_matrix_translate (&m, -wrapper->extents.x, -wrapper->extents.y);

        if (_cairo_surface_wrapper_needs_device_transform (wrapper))
            cairo_matrix_multiply (&m, &wrapper->target->device_transform, &m);

        if (clip != NULL) {
            status = _cairo_clip_init_copy_transformed (&clip_copy, clip, &m);
            if (unlikely (status))
                goto FINISH;

            dev_clip = &clip_copy;
        }

        status = cairo_matrix_invert (&m);
        assert (status == CAIRO_STATUS_SUCCESS);

        _copy_transformed_pattern (&source_copy.base, source, &m);
        source = &source_copy.base;

        _copy_transformed_pattern (&mask_copy.base, mask, &m);
        mask = &mask_copy.base;
    }

    status = _cairo_surface_mask (wrapper->target, op, source, mask, dev_clip);

FINISH:
    if (wrapper->has_extents)
        _cairo_clip_reset (&target_clip);
    if (dev_clip != clip)
        _cairo_clip_reset (dev_clip);
    return status;
}
Exemplo n.º 18
0
static cairo_int_status_t
_cairo_shape_mask_compositor_stroke (const cairo_compositor_t *_compositor,
				     cairo_composite_rectangles_t *extents,
				     const cairo_path_fixed_t	*path,
				     const cairo_stroke_style_t	*style,
				     const cairo_matrix_t	*ctm,
				     const cairo_matrix_t	*ctm_inverse,
				     double		 tolerance,
				     cairo_antialias_t	 antialias)
{
    cairo_surface_t *mask;
    cairo_surface_pattern_t pattern;
    cairo_int_status_t status;
    cairo_clip_t *clip;

    if (! extents->is_bounded)
	return CAIRO_INT_STATUS_UNSUPPORTED;

    TRACE ((stderr, "%s\n", __FUNCTION__));
    mask = _cairo_surface_create_scratch (extents->surface,
					  CAIRO_CONTENT_ALPHA,
					  extents->bounded.width,
					  extents->bounded.height,
					  NULL);
    if (unlikely (mask->status))
	return mask->status;

    clip = extents->clip;
    if (! _cairo_clip_is_region (clip))
	clip = _cairo_clip_copy_region (clip);

    if (! mask->is_clear) {
	status = _cairo_surface_offset_paint (mask,
					      extents->bounded.x,
					      extents->bounded.y,
					      CAIRO_OPERATOR_CLEAR,
					      &_cairo_pattern_clear.base,
					      clip);
	if (unlikely (status))
	    goto error;
    }

    status = _cairo_surface_offset_stroke (mask,
					   extents->bounded.x,
					   extents->bounded.y,
					   CAIRO_OPERATOR_ADD,
					   &_cairo_pattern_white.base,
					   path, style, ctm, ctm_inverse,
					   tolerance, antialias,
					   clip);
    if (unlikely (status))
	goto error;

    if (clip != extents->clip) {
	status = _cairo_clip_combine_with_surface (extents->clip, mask,
						   extents->bounded.x,
						   extents->bounded.y);
	if (unlikely (status))
	    goto error;
    }

    _cairo_pattern_init_for_surface (&pattern, mask);
    cairo_matrix_init_translate (&pattern.base.matrix,
				 -extents->bounded.x,
				 -extents->bounded.y);
    pattern.base.filter = CAIRO_FILTER_NEAREST;
    pattern.base.extend = CAIRO_EXTEND_NONE;
    if (extents->op == CAIRO_OPERATOR_SOURCE) {
	status = _cairo_surface_mask (extents->surface,
				      CAIRO_OPERATOR_DEST_OUT,
				      &_cairo_pattern_white.base,
				      &pattern.base,
				      clip);
	if ((status == CAIRO_INT_STATUS_SUCCESS)) {
	    status = _cairo_surface_mask (extents->surface,
					  CAIRO_OPERATOR_ADD,
					  &extents->source_pattern.base,
					  &pattern.base,
					  clip);
	}
    } else {
	status = _cairo_surface_mask (extents->surface,
				      extents->op,
				      &extents->source_pattern.base,
				      &pattern.base,
				      clip);
    }
    _cairo_pattern_fini (&pattern.base);

error:
    cairo_surface_destroy (mask);
    if (clip != extents->clip)
	_cairo_clip_destroy (clip);
    return status;
}