static cairo_int_status_t
base_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)
{
    composite_traps_info_t info;
    cairo_int_status_t status;

    info.antialias = antialias;
    _cairo_traps_init_with_clip (&info.traps, extents->clip);
    status = _cairo_path_fixed_stroke_to_traps (path, style,
						ctm, ctm_inverse,
						tolerance,
						&info.traps);
    if (likely (status == CAIRO_INT_STATUS_SUCCESS))
	status = trim_extents_to_traps (extents, &info.traps);
    if (likely (status == CAIRO_INT_STATUS_SUCCESS))
	status = clip_and_composite (extents, composite_traps, &info);
    _cairo_traps_fini (&info.traps);

    return status;
}
cairo_status_t
_cairo_path_fixed_stroke_extents (const cairo_path_fixed_t *path,
				  cairo_stroke_style_t *stroke_style,
				  const cairo_matrix_t *ctm,
				  const cairo_matrix_t *ctm_inverse,
				  double tolerance,
				  cairo_rectangle_int_t *extents)
{
    cairo_traps_t traps;
    cairo_box_t bbox;
    cairo_status_t status;

    _cairo_traps_init (&traps);

    status = _cairo_path_fixed_stroke_to_traps (path,
						stroke_style,
						ctm,
						ctm_inverse,
						tolerance,
						&traps);

    _cairo_traps_extents (&traps, &bbox);
    _cairo_traps_fini (&traps);

    _cairo_box_round_to_rectangle (&bbox, extents);

    return status;
}
cairo_status_t
_cairo_surface_fallback_stroke (cairo_surface_t		*surface,
				cairo_operator_t	 op,
				cairo_pattern_t		*source,
				cairo_path_fixed_t	*path,
				cairo_stroke_style_t	*stroke_style,
				cairo_matrix_t		*ctm,
				cairo_matrix_t		*ctm_inverse,
				double			 tolerance,
				cairo_antialias_t	 antialias)
{
    cairo_status_t status;
    cairo_traps_t traps;

    _cairo_traps_init (&traps);

    status = _cairo_path_fixed_stroke_to_traps (path,
						stroke_style,
						ctm, ctm_inverse,
						tolerance,
						&traps);
    if (status) {
	_cairo_traps_fini (&traps);
	return status;
    }

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

    _cairo_traps_fini (&traps);

    return CAIRO_STATUS_SUCCESS;
}
Exemplo n.º 4
0
static cairo_int_status_t
_cairo_gl_msaa_compositor_stroke (const cairo_compositor_t	*compositor,
				  cairo_composite_rectangles_t	*composite,
				  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_int_status_t status;
    cairo_gl_surface_t *dst = (cairo_gl_surface_t *) composite->surface;
    struct _tristrip_composite_info info;
    cairo_bool_t use_color_attribute;

    if (! can_use_msaa_compositor (dst, antialias))
	return CAIRO_INT_STATUS_UNSUPPORTED;

    if (composite->is_bounded == FALSE) {
	cairo_surface_t* surface = _prepare_unbounded_surface (dst);

	if (unlikely (surface == NULL))
	    return CAIRO_INT_STATUS_UNSUPPORTED;

	status = _cairo_compositor_stroke (compositor, surface,
					   CAIRO_OPERATOR_SOURCE,
					   &composite->source_pattern.base,
					   path, style, ctm, ctm_inverse,
					   tolerance, antialias, NULL);
	if (unlikely (status)) {
	    cairo_surface_destroy (surface);
	    return status;
	}

	return _paint_back_unbounded_surface (compositor, composite, surface);
    }

    status = _cairo_gl_composite_init (&info.setup,
				       composite->op,
				       dst,
				       FALSE /* assume_component_alpha */);
    if (unlikely (status))
	return status;

    info.ctx = NULL;
    use_color_attribute = _cairo_path_fixed_stroke_is_rectilinear (path) ||
			  _cairo_gl_hairline_style_is_hairline (style, ctm);

    status = _cairo_gl_composite_set_source (&info.setup,
					     composite->original_source_pattern,
					     &composite->source_sample_area,
					     &composite->bounded,
					     use_color_attribute);
    if (unlikely (status))
	goto finish;

    _cairo_gl_msaa_compositor_set_clip (composite, &info.setup);

    status = _cairo_gl_composite_begin_multisample (&info.setup, &info.ctx,
	antialias != CAIRO_ANTIALIAS_NONE);
    if (unlikely (status))
	goto finish;

    if (_cairo_gl_hairline_style_is_hairline (style, ctm)) {
	cairo_gl_hairline_closure_t closure;

	if (! (_is_continuous_arc (path, style) ||
	       _is_continuous_single_line (path, style))) {
	    status = _prevent_overlapping_drawing (info.ctx, &info.setup,
					           composite, path,
						   style, ctm);
	    if (unlikely (status))
		goto finish;
	}

	closure.ctx = info.ctx;

	closure.tolerance = tolerance;

	status = _cairo_gl_path_fixed_stroke_to_hairline (path, &closure,
							  style, ctm,
							  ctm_inverse,
							  _cairo_gl_hairline_move_to,
							  style->dash ?
							  _cairo_gl_hairline_line_to_dashed :
							  _cairo_gl_hairline_line_to,
							  _cairo_gl_hairline_curve_to,
							  _cairo_gl_hairline_close_path);
	goto finish;
    }

    if (use_color_attribute) {
	cairo_traps_t traps;

	_cairo_traps_init (&traps);

	status = _cairo_path_fixed_stroke_to_traps (path, style,
						    ctm, ctm_inverse,
						    tolerance, &traps);
	if (unlikely (status)) {
	    _cairo_traps_fini (&traps);
	    goto finish;
	}

	status = _draw_traps (info.ctx, &info.setup, &traps);
	_cairo_traps_fini (&traps);
    } else {
	if (!_is_continuous_single_line (path, style)) {
	    status = _prevent_overlapping_drawing (info.ctx, &info.setup,
						   composite, path,
						   style, ctm);
	    if (unlikely (status))
		goto finish;
	}

	status =
	    _cairo_path_fixed_stroke_to_shaper ((cairo_path_fixed_t *) path,
						style,
						ctm,
						ctm_inverse,
						tolerance,
						_stroke_shaper_add_triangle,
						_stroke_shaper_add_triangle_fan,
						_stroke_shaper_add_quad,
						&info);
	if (unlikely (status))
	    goto finish;
    }
finish:
    _cairo_gl_composite_fini (&info.setup);

    if (info.ctx)
	status = _cairo_gl_context_release (info.ctx, status);

    return status;
}
Exemplo n.º 5
0
cairo_status_t
_cairo_surface_fallback_stroke (cairo_surface_t		*surface,
				cairo_operator_t	 op,
				cairo_pattern_t		*source,
				cairo_path_fixed_t	*path,
				cairo_stroke_style_t	*stroke_style,
				cairo_matrix_t		*ctm,
				cairo_matrix_t		*ctm_inverse,
				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_stroke_to_traps (path,
						stroke_style,
						ctm, ctm_inverse,
						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;
}
cairo_int_status_t
_cairo_recording_surface_get_path (cairo_surface_t    *surface,
				   cairo_path_fixed_t *path)
{
    cairo_recording_surface_t *recording_surface;
    cairo_command_t **elements;
    int i, num_elements;
    cairo_int_status_t status;

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

    recording_surface = (cairo_recording_surface_t *) surface;
    status = CAIRO_STATUS_SUCCESS;

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

	switch (command->header.type) {
	case CAIRO_COMMAND_PAINT:
	case CAIRO_COMMAND_MASK:
	    status = CAIRO_INT_STATUS_UNSUPPORTED;
	    break;

	case CAIRO_COMMAND_STROKE:
	{
	    cairo_traps_t traps;

	    _cairo_traps_init (&traps);

	    /* XXX call cairo_stroke_to_path() when that is implemented */
	    status = _cairo_path_fixed_stroke_to_traps (&command->stroke.path,
							&command->stroke.style,
							&command->stroke.ctm,
							&command->stroke.ctm_inverse,
							command->stroke.tolerance,
							&traps);

	    if (status == CAIRO_STATUS_SUCCESS)
		status = _cairo_traps_path (&traps, path);

	    _cairo_traps_fini (&traps);
	    break;
	}
	case CAIRO_COMMAND_FILL:
	{
	    status = _cairo_path_fixed_append (path,
					       &command->fill.path, CAIRO_DIRECTION_FORWARD,
					       0, 0);
	    break;
	}
	case CAIRO_COMMAND_SHOW_TEXT_GLYPHS:
	{
	    status = _cairo_scaled_font_glyph_path (command->show_text_glyphs.scaled_font,
						    command->show_text_glyphs.glyphs,
						    command->show_text_glyphs.num_glyphs,
						    path);
	    break;
	}

	default:
	    ASSERT_NOT_REACHED;
	}

	if (unlikely (status))
	    break;
    }

    return _cairo_surface_set_error (surface, status);
}
Exemplo n.º 7
0
cairo_status_t
_cairo_surface_fallback_stroke (cairo_surface_t		*surface,
				cairo_operator_t	 op,
				const cairo_pattern_t	*source,
				cairo_path_fixed_t	*path,
				cairo_stroke_style_t	*stroke_style,
				cairo_matrix_t		*ctm,
				cairo_matrix_t		*ctm_inverse,
				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 (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;

    if (extents.width == 0 || extents.height == 0)
	return CAIRO_STATUS_SUCCESS;

    _cairo_box_from_rectangle (&box, &extents);

    _cairo_traps_init (&traps);
    _cairo_traps_limit (&traps, &box);

    status = _cairo_path_fixed_stroke_to_traps (path,
						stroke_style,
						ctm, ctm_inverse,
						tolerance,
						&traps);
    if (unlikely (status))
	goto FAIL;

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

FAIL:
    _cairo_traps_fini (&traps);

    return status;
}
Exemplo n.º 8
0
static cairo_int_status_t
_cairo_analysis_surface_stroke (void			*abstract_surface,
				cairo_operator_t	 op,
				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_analysis_surface_t *surface = abstract_surface;
    cairo_status_t	     status, backend_status;
    cairo_traps_t            traps;
    cairo_rectangle_int_t  extents;

    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);

    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 (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
	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);
    }

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

    if (_cairo_operator_bounded_by_mask (op)) {
	cairo_box_t box;

	_cairo_box_from_rectangle (&box, &extents);

	_cairo_traps_init (&traps);
	_cairo_traps_limit (&traps, &box);
	status = _cairo_path_fixed_stroke_to_traps (path,
						    style,
						    ctm, ctm_inverse,
						    tolerance,
						    &traps);
	if (status) {
	    _cairo_traps_fini (&traps);
	    return status;
	}

	_cairo_traps_extents (&traps, &box);
	_cairo_traps_fini (&traps);

        _cairo_box_round_to_rectangle (&box, &extents);
    }

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

    return status;
}