예제 #1
0
static inline cairo_bool_t
_cairo_composite_rectangles_init (cairo_composite_rectangles_t *extents,
				  int width, int height,
				  cairo_operator_t op,
				  const cairo_pattern_t *source,
				  cairo_clip_t *clip)
{
    extents->unbounded.x = extents->unbounded.y = 0;
    extents->unbounded.width  = width;
    extents->unbounded.height = height;

    if (clip != NULL) {
	const cairo_rectangle_int_t *clip_extents;

	clip_extents = _cairo_clip_get_extents (clip);
	if (clip_extents == NULL)
	    return FALSE;

	if (! _cairo_rectangle_intersect (&extents->unbounded, clip_extents))
	    return FALSE;
    }

    extents->bounded = extents->unbounded;
    extents->is_bounded = _cairo_operator_bounded_by_either (op);

    _cairo_pattern_get_extents (source, &extents->source);
    if (extents->is_bounded & CAIRO_OPERATOR_BOUND_BY_SOURCE) {
	if (! _cairo_rectangle_intersect (&extents->bounded, &extents->source))
	    return FALSE;
    }

    return TRUE;
}
예제 #2
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;
}
예제 #3
0
cairo_bool_t
_cairo_surface_wrapper_get_target_extents (cairo_surface_wrapper_t *wrapper,
					   cairo_bool_t surface_is_unbounded,
					   cairo_rectangle_int_t *extents)
{
    cairo_rectangle_int_t clip;
    cairo_bool_t has_clip = FALSE;

    if (!surface_is_unbounded)
	has_clip = _cairo_surface_get_extents (wrapper->target, &clip);

    if (wrapper->clip) {
	if (has_clip) {
	    if (! _cairo_rectangle_intersect (&clip,
					      _cairo_clip_get_extents (wrapper->clip)))
		return FALSE;
	} else {
	    has_clip = TRUE;
	    clip = *_cairo_clip_get_extents (wrapper->clip);
	}
    }

    if (has_clip && wrapper->needs_transform) {
	cairo_matrix_t m;
	double x1, y1, x2, y2;

	_cairo_surface_wrapper_get_inverse_transform (wrapper, &m);

	x1 = clip.x;
	y1 = clip.y;
	x2 = clip.x + clip.width;
	y2 = clip.y + clip.height;

	_cairo_matrix_transform_bounding_box (&m, &x1, &y1, &x2, &y2, NULL);

	clip.x = floor (x1);
	clip.y = floor (y1);
	clip.width  = ceil (x2) - clip.x;
	clip.height = ceil (y2) - clip.y;
    }

    if (has_clip) {
	if (wrapper->has_extents) {
	    *extents = wrapper->extents;
	    return _cairo_rectangle_intersect (extents, &clip);
	} else {
	    *extents = clip;
	    return TRUE;
	}
    } else if (wrapper->has_extents) {
	*extents = wrapper->extents;
	return TRUE;
    } else {
	_cairo_unbounded_rectangle_init (extents);
	return TRUE;
    }
}
예제 #4
0
static inline cairo_bool_t
_cairo_composite_rectangles_init (cairo_composite_rectangles_t *extents,
				  cairo_surface_t *surface,
				  cairo_operator_t op,
				  const cairo_pattern_t *source,
				  const cairo_clip_t *clip,
				  cairo_bool_t *should_be_lazy)
{
    if (_cairo_clip_is_all_clipped (clip))
	return FALSE;

    extents->surface = surface;
    extents->op = op;

    _cairo_surface_get_extents (surface, &extents->destination);
    extents->clip = NULL;

    extents->unbounded = extents->destination;
    extents->is_bounded = _cairo_operator_bounded_by_either (op);

    if (*should_be_lazy)
        *should_be_lazy = _cairo_composite_rectangles_check_lazy_init (extents,
                                                                       surface,
                                                                       source);

    if ((! *should_be_lazy) &&
        (clip && ! _cairo_rectangle_intersect (&extents->unbounded,
                                               _cairo_clip_get_extents (clip))))
        return FALSE;

    extents->bounded = extents->unbounded;

	extents->original_source_pattern = source;
	if (! *should_be_lazy) {
		_cairo_composite_reduce_pattern (source, &extents->source_pattern);

		_cairo_pattern_get_extents (&extents->source_pattern.base,
                                    &extents->source);
	} else
        _cairo_pattern_get_extents (extents->original_source_pattern,
                                    &extents->source);

    if (extents->is_bounded & CAIRO_OPERATOR_BOUND_BY_SOURCE) {
	if (! _cairo_rectangle_intersect (&extents->bounded, &extents->source))
	    return FALSE;
    }

    extents->original_mask_pattern = NULL;
    extents->mask_pattern.base.type = CAIRO_PATTERN_TYPE_SOLID;
    extents->mask_pattern.solid.color.alpha = 1.; /* XXX full initialisation? */
    extents->mask_pattern.solid.color.alpha_short = 0xffff;

    return TRUE;
}
예제 #5
0
static cairo_int_status_t
_cairo_analysis_surface_stroke (void			   *abstract_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_matrix_t	   *ctm_inverse,
				double			    tolerance,
				cairo_antialias_t	    antialias,
				const cairo_clip_t	   *clip)
{
    cairo_analysis_surface_t *surface = abstract_surface;
    cairo_int_status_t	     backend_status;
    cairo_rectangle_int_t    extents;

    if (surface->target->backend->stroke == NULL) {
	backend_status = CAIRO_INT_STATUS_UNSUPPORTED;
    } else {
	backend_status =
	    surface->target->backend->stroke (surface->target, op,
					      source, path, style,
					      ctm, ctm_inverse,
					      tolerance, antialias,
					      clip);
	if (_cairo_int_status_is_error (backend_status))
	    return backend_status;
    }

    _cairo_analysis_surface_operation_extents (surface,
					       op, source, clip,
					       &extents);
    if (backend_status == CAIRO_INT_STATUS_ANALYZE_RECORDING_SURFACE_PATTERN) {
	cairo_rectangle_int_t rec_extents;
	backend_status = _analyze_recording_surface_pattern (surface, source, &rec_extents);
	_cairo_rectangle_intersect (&extents, &rec_extents);
    }

    if (_cairo_operator_bounded_by_mask (op)) {
	cairo_rectangle_int_t mask_extents;
	cairo_int_status_t status;

	status = _cairo_path_fixed_stroke_extents (path, style,
						   ctm, ctm_inverse,
						   tolerance,
						   &mask_extents);
	if (unlikely (status))
	    return status;

	_cairo_rectangle_intersect (&extents, &mask_extents);
    }

    return _add_operation (surface, &extents, backend_status);
}
예제 #6
0
static cairo_int_status_t
_cairo_analysis_surface_intersect_clip_path (void		*abstract_surface,
					     cairo_path_fixed_t *path,
					     cairo_fill_rule_t   fill_rule,
					     double		 tolerance,
					     cairo_antialias_t   antialias)
{
    cairo_analysis_surface_t *surface = abstract_surface;

    if (path == NULL) {
	surface->current_clip.x = 0;
	surface->current_clip.y = 0;
	surface->current_clip.width  = surface->width;
	surface->current_clip.height = surface->height;
    } else {
	cairo_rectangle_int_t extents;
	cairo_bool_t is_empty;

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

    return CAIRO_STATUS_SUCCESS;
}
예제 #7
0
static cairo_int_status_t
_cairo_analysis_surface_paint (void			*abstract_surface,
			       cairo_operator_t		op,
			       const cairo_pattern_t	*source,
			       const cairo_clip_t	*clip)
{
    cairo_analysis_surface_t *surface = abstract_surface;
    cairo_int_status_t	     backend_status;
    cairo_rectangle_int_t  extents;

    if (surface->target->backend->paint == NULL) {
	backend_status = CAIRO_INT_STATUS_UNSUPPORTED;
    } else {
	backend_status =
	    surface->target->backend->paint (surface->target,
					     op, source, clip);
	if (_cairo_int_status_is_error (backend_status))
	    return backend_status;
    }

    _cairo_analysis_surface_operation_extents (surface,
					       op, source, clip,
					       &extents);
    if (backend_status == CAIRO_INT_STATUS_ANALYZE_RECORDING_SURFACE_PATTERN) {
	cairo_rectangle_int_t rec_extents;
	backend_status = _analyze_recording_surface_pattern (surface, source, &rec_extents);
	_cairo_rectangle_intersect (&extents, &rec_extents);
    }

    return _add_operation (surface, &extents, backend_status);
}
예제 #8
0
cairo_int_status_t
_cairo_composite_rectangles_init_for_paint (cairo_composite_rectangles_t *extents,
					    cairo_surface_t *surface,
					    cairo_operator_t		 op,
					    const cairo_pattern_t	*source,
					    const cairo_clip_t		*clip)
{
    if (! _cairo_composite_rectangles_init (extents,
					    surface, op, source, clip))
    {
	return CAIRO_INT_STATUS_NOTHING_TO_DO;
    }

    extents->mask = extents->destination;

    extents->clip = _cairo_clip_reduce_for_composite (clip, extents);
    if (_cairo_clip_is_all_clipped (extents->clip))
	return CAIRO_INT_STATUS_NOTHING_TO_DO;

    if (! _cairo_rectangle_intersect (&extents->unbounded,
				      _cairo_clip_get_extents (extents->clip)))
	return CAIRO_INT_STATUS_NOTHING_TO_DO;

    if (extents->source_pattern.base.type != CAIRO_PATTERN_TYPE_SOLID)
	_cairo_pattern_sampled_area (&extents->source_pattern.base,
				     &extents->bounded,
				     &extents->source_sample_area);

    return CAIRO_STATUS_SUCCESS;
}
예제 #9
0
static cairo_int_status_t
_cairo_analysis_surface_intersect_clip_path (void		*abstract_surface,
					     cairo_path_fixed_t *path,
					     cairo_fill_rule_t   fill_rule,
					     double		 tolerance,
					     cairo_antialias_t   antialias)
{
    cairo_analysis_surface_t *surface = abstract_surface;
    double                    x1, y1, x2, y2;
    cairo_rectangle_int_t   extent;

    if (path == NULL) {
	surface->current_clip.x = 0;
	surface->current_clip.y = 0;
	surface->current_clip.width  = surface->width;
	surface->current_clip.height = surface->height;
    } else {
	cairo_status_t status;

	status = _cairo_path_fixed_bounds (path, &x1, &y1, &x2, &y2, tolerance);
	if (status)
	    return status;

	extent.x = floor (x1);
	extent.y = floor (y1);
	extent.width  = ceil (x2) - extent.x;
	extent.height = ceil (y2) - extent.y;

	_cairo_rectangle_intersect (&surface->current_clip, &extent);
    }

    return CAIRO_STATUS_SUCCESS;
}
예제 #10
0
static cairo_status_t
_cairo_clip_path_intersect_to_rectangle (cairo_clip_path_t       *clip_path,
				         cairo_rectangle_int_t   *rectangle)
{
    while (clip_path) {
        cairo_status_t status;
        cairo_traps_t traps;
        cairo_box_t extents;
        cairo_rectangle_int_t extents_rect;

        _cairo_traps_init (&traps);

        status = _cairo_path_fixed_fill_to_traps (&clip_path->path,
                                                  clip_path->fill_rule,
                                                  clip_path->tolerance,
                                                  &traps);
        if (status) {
            _cairo_traps_fini (&traps);
            return status;
        }

        _cairo_traps_extents (&traps, &extents);
        _cairo_box_round_to_rectangle (&extents, &extents_rect);
        _cairo_rectangle_intersect (rectangle, &extents_rect);

        _cairo_traps_fini (&traps);

        clip_path = clip_path->prev;
    }

    return CAIRO_STATUS_SUCCESS;
}
예제 #11
0
cairo_status_t
_cairo_surface_fallback_fill (cairo_surface_t		*surface,
			      cairo_operator_t		 op,
			      cairo_pattern_t		*source,
			      cairo_path_fixed_t	*path,
			      cairo_fill_rule_t		 fill_rule,
			      double			 tolerance,
			      cairo_antialias_t		 antialias)
{
    cairo_status_t status;
    cairo_traps_t traps;
    cairo_box_t box;
    cairo_rectangle_int_t extents;

    status = _cairo_surface_get_extents (surface, &extents);
    if (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 (status)
	    return status;

	_cairo_rectangle_intersect (&extents, &source_extents);
    }

    status = _cairo_clip_intersect_to_rectangle (surface->clip, &extents);
    if (status)
        return status;

    box.p1.x = _cairo_fixed_from_int (extents.x);
    box.p1.y = _cairo_fixed_from_int (extents.y);
    box.p2.x = _cairo_fixed_from_int (extents.x + extents.width);
    box.p2.y = _cairo_fixed_from_int (extents.y + extents.height);

    _cairo_traps_init (&traps);

    _cairo_traps_limit (&traps, &box);

    status = _cairo_path_fixed_fill_to_traps (path,
					      fill_rule,
					      tolerance,
					      &traps);
    if (status) {
	_cairo_traps_fini (&traps);
	return status;
    }

    status = _clip_and_composite_trapezoids (source,
					     op,
					     surface,
					     &traps,
					     surface->clip,
					     antialias);

    _cairo_traps_fini (&traps);

    return status;
}
예제 #12
0
static cairo_status_t
_cairo_surface_subsurface_mark_dirty (void *abstract_surface,
				      int x, int y,
				      int width, int height)
{
    cairo_surface_subsurface_t *surface = abstract_surface;
    cairo_status_t status;

    status = CAIRO_STATUS_SUCCESS;
    if (surface->target->backend->mark_dirty_rectangle != NULL) {
	cairo_rectangle_int_t rect, extents;

	rect.x = x;
	rect.y = y;
	rect.width  = width;
	rect.height = height;

	extents.x = extents.y = 0;
	extents.width  = surface->extents.width;
	extents.height = surface->extents.height;

	if (_cairo_rectangle_intersect (&rect, &extents)) {
	    status = surface->target->backend->mark_dirty_rectangle (surface->target,
								     rect.x + surface->extents.x,
								     rect.y + surface->extents.y,
								     rect.width, rect.height);
	}
    }

    return status;
}
예제 #13
0
static cairo_int_status_t
_cairo_composite_rectangles_intersect (cairo_composite_rectangles_t *extents,
				       const cairo_clip_t *clip)
{
    if ((!_cairo_rectangle_intersect (&extents->bounded, &extents->mask)) &&
        (extents->is_bounded & CAIRO_OPERATOR_BOUND_BY_MASK))
	return CAIRO_INT_STATUS_NOTHING_TO_DO;

    if (extents->is_bounded == (CAIRO_OPERATOR_BOUND_BY_MASK | CAIRO_OPERATOR_BOUND_BY_SOURCE)) {
	extents->unbounded = extents->bounded;
    } else if (extents->is_bounded & CAIRO_OPERATOR_BOUND_BY_MASK) {
	if (!_cairo_rectangle_intersect (&extents->unbounded, &extents->mask))
	    return CAIRO_INT_STATUS_NOTHING_TO_DO;
    }

    extents->clip = _cairo_clip_reduce_for_composite (clip, extents);
    if (_cairo_clip_is_all_clipped (extents->clip))
	return CAIRO_INT_STATUS_NOTHING_TO_DO;

    if (! _cairo_rectangle_intersect (&extents->unbounded,
				      _cairo_clip_get_extents (extents->clip)))
	return CAIRO_INT_STATUS_NOTHING_TO_DO;

    if (! _cairo_rectangle_intersect (&extents->bounded,
				      _cairo_clip_get_extents (extents->clip)) &&
	extents->is_bounded & CAIRO_OPERATOR_BOUND_BY_MASK)
    {
	return CAIRO_INT_STATUS_NOTHING_TO_DO;
    }

    if (extents->source_pattern.base.type != CAIRO_PATTERN_TYPE_SOLID)
	_cairo_pattern_sampled_area (&extents->source_pattern.base,
				     &extents->bounded,
				     &extents->source_sample_area);
    if (extents->mask_pattern.base.type != CAIRO_PATTERN_TYPE_SOLID) {
	_cairo_pattern_sampled_area (&extents->mask_pattern.base,
				     &extents->bounded,
				     &extents->mask_sample_area);
	if (extents->mask_sample_area.width == 0 ||
	    extents->mask_sample_area.height == 0) {
	    _cairo_composite_rectangles_fini (extents);
	    return CAIRO_INT_STATUS_NOTHING_TO_DO;
	}
    }

    return CAIRO_STATUS_SUCCESS;
}
예제 #14
0
cairo_int_status_t
_cairo_composite_rectangles_lazy_init_for_mask (cairo_composite_rectangles_t *extents,
						cairo_surface_t *surface,
						cairo_operator_t op,
						const cairo_pattern_t *source,
						const cairo_pattern_t *mask,
						const cairo_clip_t *clip)
{
	cairo_bool_t ret;
	cairo_bool_t should_be_lazy = (op == CAIRO_OPERATOR_SOURCE) ? FALSE : TRUE;


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

	extents->original_mask_pattern = mask;

	if (! should_be_lazy) {
		_cairo_composite_reduce_pattern (mask, &extents->mask_pattern);
		_cairo_pattern_get_extents (&extents->mask_pattern.base,
					&extents->mask);
		return _cairo_composite_rectangles_intersect (extents, clip);
	}

	_cairo_pattern_get_extents (extents->original_mask_pattern,
				&extents->mask);

	ret = _cairo_rectangle_intersect (&extents->bounded, &extents->mask);
	if (! ret && extents->is_bounded & CAIRO_OPERATOR_BOUND_BY_MASK)
		return CAIRO_INT_STATUS_NOTHING_TO_DO;

	if (extents->is_bounded == (CAIRO_OPERATOR_BOUND_BY_MASK | CAIRO_OPERATOR_BOUND_BY_SOURCE))
		extents->unbounded = extents->bounded;
	else if ((extents->is_bounded & CAIRO_OPERATOR_BOUND_BY_MASK) &&
			 (!_cairo_rectangle_intersect (&extents->unbounded, &extents->mask)))
			 return CAIRO_INT_STATUS_NOTHING_TO_DO;

	extents->clip = _cairo_clip_copy (clip);
	return CAIRO_INT_STATUS_SUCCESS;
}
예제 #15
0
cairo_status_t
_cairo_surface_fallback_mask (cairo_surface_t		*surface,
			      cairo_operator_t		 op,
			      const cairo_pattern_t	*source,
			      const cairo_pattern_t	*mask)
{
    cairo_status_t status;
    cairo_rectangle_int_t extents, source_extents, mask_extents;

    status = _cairo_surface_get_extents (surface, &extents);
    if (unlikely (status))
	return status;

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

	if (! _cairo_rectangle_intersect (&extents, &source_extents))
	    return CAIRO_STATUS_SUCCESS;
    }

    if (_cairo_operator_bounded_by_mask (op)) {
	status = _cairo_pattern_get_extents (mask, &mask_extents);
	if (unlikely (status))
	    return status;

	if (! _cairo_rectangle_intersect (&extents, &mask_extents))
	    return CAIRO_STATUS_SUCCESS;
    }

    status = _cairo_clip_intersect_to_rectangle (surface->clip, &extents);
    if (unlikely (status))
	return status;

    status = _clip_and_composite (surface->clip, op,
				  source,
				  _cairo_surface_mask_draw_func,
				  (void *) mask,
				  surface,
				  &extents);

    return status;
}
예제 #16
0
cairo_bool_t
_cairo_composite_rectangles_can_reduce_clip (cairo_composite_rectangles_t *composite,
					     cairo_clip_t *clip)
{
    cairo_rectangle_int_t extents;
    cairo_box_t box;

    if (clip == NULL)
	return TRUE;

    extents = composite->destination;
    if (composite->is_bounded & CAIRO_OPERATOR_BOUND_BY_SOURCE)
	_cairo_rectangle_intersect (&extents, &composite->source);
    if (composite->is_bounded & CAIRO_OPERATOR_BOUND_BY_MASK)
	_cairo_rectangle_intersect (&extents, &composite->mask);

    _cairo_box_from_rectangle (&box, &extents);
    return _cairo_clip_contains_box (clip, &box);
}
cairo_status_t
_cairo_surface_fallback_mask (cairo_surface_t		*surface,
			      cairo_operator_t		 op,
			      cairo_pattern_t		*source,
			      cairo_pattern_t		*mask)
{
    cairo_status_t status;
    cairo_rectangle_int16_t extents, source_extents, mask_extents;

    status = _cairo_surface_get_extents (surface, &extents);
    if (status)
	return status;

    if (_cairo_operator_bounded_by_source (op)) {
	status = _cairo_pattern_get_extents (source, &source_extents);
	if (status)
	    return status;

	_cairo_rectangle_intersect (&extents, &source_extents);
    }

    if (_cairo_operator_bounded_by_mask (op)) {
	status = _cairo_pattern_get_extents (mask, &mask_extents);
	if (status)
	    return status;

	_cairo_rectangle_intersect (&extents, &mask_extents);
    }

    status = _cairo_clip_intersect_to_rectangle (surface->clip, &extents);
    if (status)
	return status;

    status = _clip_and_composite (surface->clip, op,
				  source,
				  _cairo_surface_mask_draw_func,
				  mask,
				  surface,
				  &extents);

    return status;
}
예제 #18
0
static cairo_int_status_t
_cairo_analysis_surface_paint (void			*abstract_surface,
			       cairo_operator_t		op,
			       const cairo_pattern_t	*source,
			       cairo_rectangle_int_t    *paint_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->paint)
	backend_status = CAIRO_INT_STATUS_UNSUPPORTED;
    else
	backend_status = (*surface->target->backend->paint) (surface->target, op,
                                                             source, 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 (paint_extents)
	*paint_extents = extents;

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

    return status;
}
예제 #19
0
static cairo_int_status_t
_cairo_composite_rectangles_intersect (cairo_composite_rectangles_t *extents)
{
    cairo_bool_t ret;

    ret = _cairo_rectangle_intersect (&extents->bounded, &extents->mask);
    if (! ret && extents->is_bounded & CAIRO_OPERATOR_BOUND_BY_MASK)
	return CAIRO_INT_STATUS_NOTHING_TO_DO;

    return CAIRO_STATUS_SUCCESS;
}
예제 #20
0
void
_cairo_surface_wrapper_intersect_extents (cairo_surface_wrapper_t *wrapper,
					  const cairo_rectangle_int_t *extents)
{
    if (! wrapper->has_extents) {
	wrapper->extents = *extents;
	wrapper->has_extents = TRUE;
    } else
	_cairo_rectangle_intersect (&wrapper->extents, extents);

    wrapper->needs_transform =
	_cairo_surface_wrapper_needs_device_transform (wrapper);
}
예제 #21
0
cairo_status_t
_cairo_clip_intersect_to_rectangle (cairo_clip_t            *clip,
				    cairo_rectangle_int_t *rectangle)
{
    cairo_status_t status;
    cairo_bool_t is_empty;

    if (!clip)
	return CAIRO_STATUS_SUCCESS;

    if (clip->all_clipped) {
	*rectangle = clip->surface_rect;
	return CAIRO_STATUS_SUCCESS;
    }

    if (clip->path) {
        status = _cairo_clip_path_intersect_to_rectangle (clip->path,
                                                          rectangle);
        if (unlikely (status))
            return status;
    }

    if (clip->has_region) {
	cairo_rectangle_int_t extents;

	_cairo_region_get_extents (&clip->region, &extents);
	is_empty = _cairo_rectangle_intersect (rectangle, &extents);
	if (is_empty)
	    return CAIRO_STATUS_SUCCESS;
    }

    if (clip->surface)
	is_empty = _cairo_rectangle_intersect (rectangle, &clip->surface_rect);

    return CAIRO_STATUS_SUCCESS;
}
예제 #22
0
cairo_bool_t
_cairo_surface_wrapper_get_extents (cairo_surface_wrapper_t *wrapper,
				    cairo_rectangle_int_t   *extents)
{
    if (wrapper->has_extents) {
	if (_cairo_surface_get_extents (wrapper->target, extents))
	    _cairo_rectangle_intersect (extents, &wrapper->extents);
	else
	    *extents = wrapper->extents;

	return TRUE;
    } else {
	return _cairo_surface_get_extents (wrapper->target, extents);
    }
}
예제 #23
0
cairo_status_t
_cairo_surface_fallback_show_glyphs (cairo_surface_t		*surface,
				     cairo_operator_t		 op,
				     const cairo_pattern_t	*source,
				     cairo_glyph_t		*glyphs,
				     int			 num_glyphs,
				     cairo_scaled_font_t	*scaled_font)
{
    cairo_status_t status;
    cairo_rectangle_int_t extents;
    cairo_show_glyphs_info_t glyph_info;

    status = _cairo_surface_get_extents (surface, &extents);
    if (unlikely (status))
	return status;

    if (_cairo_operator_bounded_by_mask (op)) {
        cairo_rectangle_int_t glyph_extents;

	status = _cairo_scaled_font_glyph_device_extents (scaled_font,
							  glyphs,
							  num_glyphs,
							  &glyph_extents);
	if (unlikely (status))
	    return status;

	if (! _cairo_rectangle_intersect (&extents, &glyph_extents))
	    return CAIRO_STATUS_SUCCESS;
    }

    status = _cairo_clip_intersect_to_rectangle (surface->clip, &extents);
    if (unlikely (status))
	return status;

    glyph_info.font = scaled_font;
    glyph_info.glyphs = glyphs;
    glyph_info.num_glyphs = num_glyphs;

    status = _clip_and_composite (surface->clip,
				  op,
				  source,
				  _cairo_surface_old_show_glyphs_draw_func,
				  &glyph_info,
				  surface,
				  &extents);

    return status;
}
예제 #24
0
cairo_status_t
_cairo_surface_fallback_paint (cairo_surface_t	*surface,
			       cairo_operator_t	 op,
			       cairo_pattern_t	*source)
{
    cairo_status_t status;
    cairo_rectangle_int_t extents;
    cairo_box_t box;
    cairo_traps_t traps;

    status = _cairo_surface_get_extents (surface, &extents);
    if (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 (status)
	    return status;

	_cairo_rectangle_intersect (&extents, &source_extents);
    }

    status = _cairo_clip_intersect_to_rectangle (surface->clip, &extents);
    if (status)
	return status;

    box.p1.x = _cairo_fixed_from_int (extents.x);
    box.p1.y = _cairo_fixed_from_int (extents.y);
    box.p2.x = _cairo_fixed_from_int (extents.x + extents.width);
    box.p2.y = _cairo_fixed_from_int (extents.y + extents.height);

    status = _cairo_traps_init_box (&traps, &box);
    if (status)
	return status;

    status = _clip_and_composite_trapezoids (source,
				             op,
					     surface,
					     &traps,
					     surface->clip,
					     CAIRO_ANTIALIAS_NONE);

    _cairo_traps_fini (&traps);

    return status;
}
예제 #25
0
static cairo_status_t
_cairo_clip_path_intersect_to_rectangle (cairo_clip_path_t       *clip_path,
				         cairo_rectangle_int_t   *rectangle)
{
    while (clip_path) {
        cairo_rectangle_int_t extents;

	_cairo_path_fixed_approximate_clip_extents (&clip_path->path, &extents);

        if (! _cairo_rectangle_intersect (rectangle, &extents))
	    return CAIRO_STATUS_SUCCESS;

        clip_path = clip_path->prev;
    }

    return CAIRO_STATUS_SUCCESS;
}
예제 #26
0
cairo_status_t
_cairo_surface_fallback_paint (cairo_surface_t		*surface,
			       cairo_operator_t		 op,
			       const cairo_pattern_t	*source)
{
    cairo_status_t status;
    cairo_rectangle_int_t extents;
    cairo_box_t box;
    cairo_traps_t traps;

    status = _cairo_surface_get_extents (surface, &extents);
    if (unlikely (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;

	if (! _cairo_rectangle_intersect (&extents, &source_extents))
	    return CAIRO_STATUS_SUCCESS;
    }

    status = _cairo_clip_intersect_to_rectangle (surface->clip, &extents);
    if (unlikely (status))
	return status;

    _cairo_box_from_rectangle (&box, &extents);

    _cairo_traps_init_box (&traps, &box);

    status = _clip_and_composite_trapezoids (source,
				             op,
					     surface,
					     &traps,
					     surface->clip,
					     CAIRO_ANTIALIAS_NONE);

    _cairo_traps_fini (&traps);

    return status;
}
예제 #27
0
cairo_int_status_t
_cairo_composite_rectangles_init_for_glyphs (cairo_composite_rectangles_t *extents,
					     cairo_surface_t *surface,
					     cairo_operator_t		 op,
					     const cairo_pattern_t	*source,
					     cairo_scaled_font_t	*scaled_font,
					     cairo_glyph_t		*glyphs,
					     int			 num_glyphs,
					     const cairo_clip_t		*clip,
					     cairo_bool_t		*overlap)
{
    cairo_status_t status;

    if (! _cairo_composite_rectangles_init (extents, surface, op, source, clip))
	return CAIRO_INT_STATUS_NOTHING_TO_DO;

    /* Computing the exact bbox and the overlap is expensive.
     * First perform a cheap test to see if the glyphs are all clipped out.
     */
    if (extents->is_bounded & CAIRO_OPERATOR_BOUND_BY_MASK &&
	_cairo_scaled_font_glyph_approximate_extents (scaled_font,
						      glyphs, num_glyphs,
						      &extents->mask))
    {
	if (! _cairo_rectangle_intersect (&extents->bounded, &extents->mask))
	    return CAIRO_INT_STATUS_NOTHING_TO_DO;
    }

    status = _cairo_scaled_font_glyph_device_extents (scaled_font,
						      glyphs, num_glyphs,
						      &extents->mask,
						      overlap);
    if (unlikely (status))
	return status;

    if (overlap && *overlap &&
	scaled_font->options.antialias == CAIRO_ANTIALIAS_NONE &&
	_cairo_pattern_is_opaque_solid (&extents->source_pattern.base))
    {
	*overlap = FALSE;
    }

    return _cairo_composite_rectangles_intersect (extents, clip);
}
예제 #28
0
cairo_status_t
_cairo_clip_intersect_to_rectangle (cairo_clip_t            *clip,
				    cairo_rectangle_int_t *rectangle)
{
    if (!clip)
	return CAIRO_STATUS_SUCCESS;

    if (clip->all_clipped) {
	*rectangle = clip->surface_rect;
	return CAIRO_STATUS_SUCCESS;
    }

    if (clip->path) {
        cairo_status_t status;

        status = _cairo_clip_path_intersect_to_rectangle (clip->path,
                                                          rectangle);
        if (status)
            return status;
    }

    if (clip->has_region) {
	cairo_status_t status = CAIRO_STATUS_SUCCESS;
	cairo_region_t intersection;

	_cairo_region_init_rect (&intersection, rectangle);

	status = _cairo_region_intersect (&intersection, &clip->region,
					  &intersection);

	if (!status)
	    _cairo_region_get_extents (&intersection, rectangle);

        _cairo_region_fini (&intersection);

        if (status)
            return status;
    }

    if (clip->surface)
	_cairo_rectangle_intersect (rectangle, &clip->surface_rect);

    return CAIRO_STATUS_SUCCESS;
}
예제 #29
0
static cairo_status_t
_cairo_clip_path_reapply_clip_path_transform (cairo_clip_t      *clip,
					      cairo_clip_path_t *other_path,
					      const cairo_matrix_t *matrix)
{
    cairo_status_t status;
    cairo_clip_path_t *clip_path;
    cairo_bool_t is_empty;

    if (other_path->prev != NULL) {
        status = _cairo_clip_path_reapply_clip_path_transform (clip,
							       other_path->prev,
							       matrix);
	if (unlikely (status))
	    return status;
    }

    clip_path = _cairo_clip_path_create (clip);
    if (unlikely (clip_path == NULL))
	return _cairo_error (CAIRO_STATUS_NO_MEMORY);

    status = _cairo_path_fixed_init_copy (&clip_path->path,
					  &other_path->path);
    if (unlikely (status)) {
	_cairo_clip_path_destroy (clip_path);
	return status;
    }

    _cairo_path_fixed_transform (&clip_path->path, matrix);
    _cairo_path_fixed_approximate_clip_extents (&clip_path->path,
						&clip_path->extents);
    if (clip_path->prev != NULL) {
	is_empty = _cairo_rectangle_intersect (&clip_path->extents,
					       &clip_path->prev->extents);
    }

    clip_path->fill_rule = other_path->fill_rule;
    clip_path->tolerance = other_path->tolerance;
    clip_path->antialias = other_path->antialias;

    return CAIRO_STATUS_SUCCESS;
}
예제 #30
0
static void
_cairo_analysis_surface_operation_extents (cairo_analysis_surface_t *surface,
					   cairo_operator_t op,
					   const cairo_pattern_t *source,
					   const cairo_clip_t *clip,
					   cairo_rectangle_int_t *extents)
{
    cairo_bool_t is_empty;

    is_empty = _cairo_surface_get_extents (&surface->base, extents);

    if (_cairo_operator_bounded_by_source (op)) {
	cairo_rectangle_int_t source_extents;

	_cairo_pattern_get_extents (source, &source_extents);
	_cairo_rectangle_intersect (extents, &source_extents);
    }

    _rectangle_intersect_clip (extents, clip);
}