static cairo_int_status_t
_cairo_tee_surface_fill (void				*abstract_surface,
			 cairo_operator_t		 op,
			 const cairo_pattern_t		*source,
			 const cairo_path_fixed_t	*path,
			 cairo_fill_rule_t		 fill_rule,
			 double				 tolerance,
			 cairo_antialias_t		 antialias,
			 const cairo_clip_t		*clip)
{
    cairo_tee_surface_t *surface = abstract_surface;
    cairo_surface_wrapper_t *slaves;
    cairo_int_status_t status;
    int n, num_slaves;

    num_slaves = _cairo_array_num_elements (&surface->slaves);
    slaves = _cairo_array_index (&surface->slaves, 0);
    for (n = 0; n < num_slaves; n++) {
	status = _cairo_surface_wrapper_fill (&slaves[n],
					      op, source,
					      path, fill_rule,
					      tolerance, antialias,
					      clip);
	if (unlikely (status))
	    return status;
    }

    return _cairo_surface_wrapper_fill (&surface->master,
					op, source,
					path, fill_rule,
					tolerance, antialias,
					clip);
}
static cairo_int_status_t
_cairo_tee_surface_fill (void				*abstract_surface,
			 cairo_operator_t		 op,
			 const cairo_pattern_t		*source,
			 cairo_path_fixed_t		*path,
			 cairo_fill_rule_t		 fill_rule,
			 double				 tolerance,
			 cairo_antialias_t		 antialias,
			 cairo_clip_t			*clip)
{
    cairo_tee_surface_t *surface = abstract_surface;
    cairo_surface_wrapper_t *slaves;
    int n, num_slaves;
    cairo_status_t status;
    const cairo_pattern_t *matched_source;
    cairo_surface_pattern_t temp;

    matched_source = _cairo_tee_surface_match_source (surface, source, 0, &surface->master, &temp);
    status = _cairo_surface_wrapper_fill (&surface->master,
					  op, matched_source,
					  path, fill_rule,
					  tolerance, antialias,
					  clip);
    if (matched_source == &temp.base) {
        _cairo_pattern_fini (&temp.base);
    }
    if (unlikely (status))
	return status;

    num_slaves = _cairo_array_num_elements (&surface->slaves);
    slaves = _cairo_array_index (&surface->slaves, 0);
    for (n = 0; n < num_slaves; n++) {
        matched_source = _cairo_tee_surface_match_source (surface, source, n + 1, &slaves[n], &temp);
	status = _cairo_surface_wrapper_fill (&slaves[n],
					      op, matched_source,
					      path, fill_rule,
					      tolerance, antialias,
					      clip);
        if (matched_source == &temp.base) {
            _cairo_pattern_fini (&temp.base);
        }
	if (unlikely (status))
	    return status;
    }

    return CAIRO_STATUS_SUCCESS;
}
Exemple #3
0
static cairo_int_status_t
_test_wrapping_surface_fill (void				*abstract_surface,
			      cairo_operator_t			 op,
			      const cairo_pattern_t		*source,
			      cairo_path_fixed_t		*path,
			      cairo_fill_rule_t			 fill_rule,
			      double				 tolerance,
			      cairo_antialias_t			 antialias,
			      cairo_clip_t			*clip)
{
    test_wrapping_surface_t *surface = abstract_surface;

    return _cairo_surface_wrapper_fill (&surface->wrapper,
					op, source,
					path, fill_rule,
					tolerance, antialias,
					clip);
}
static cairo_status_t
_cairo_recording_surface_replay_internal (cairo_surface_t	     *surface,
					  const cairo_rectangle_int_t *surface_extents,
					  cairo_surface_t	     *target,
					  cairo_recording_replay_type_t type,
					  cairo_recording_region_type_t region)
{
    cairo_recording_surface_t *recording_surface;
    cairo_command_t **elements;
    int i, num_elements;
    cairo_int_status_t status;
    cairo_surface_wrapper_t wrapper;

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

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

    if (unlikely (surface->finished))
	return _cairo_error (CAIRO_STATUS_SURFACE_FINISHED);

    if (surface->is_clear)
	return CAIRO_STATUS_SUCCESS;

    assert (_cairo_surface_is_recording (surface));

    _cairo_surface_wrapper_init (&wrapper, target);
    _cairo_surface_wrapper_set_extents (&wrapper, surface_extents);

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

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

	switch (command->header.type) {
	case CAIRO_COMMAND_PAINT:
	    status = _cairo_surface_wrapper_paint (&wrapper,
						   command->header.op,
						   &command->paint.source.base,
						   _clip (command));
	    break;

	case CAIRO_COMMAND_MASK:
	    status = _cairo_surface_wrapper_mask (&wrapper,
						  command->header.op,
						  &command->mask.source.base,
						  &command->mask.mask.base,
						  _clip (command));
	    break;

	case CAIRO_COMMAND_STROKE:
	{
	    status = _cairo_surface_wrapper_stroke (&wrapper,
						    command->header.op,
						    &command->stroke.source.base,
						    &command->stroke.path,
						    &command->stroke.style,
						    &command->stroke.ctm,
						    &command->stroke.ctm_inverse,
						    command->stroke.tolerance,
						    command->stroke.antialias,
						    _clip (command));
	    break;
	}
	case CAIRO_COMMAND_FILL:
	{
	    cairo_command_t *stroke_command;

	    stroke_command = NULL;
	    if (type != CAIRO_RECORDING_CREATE_REGIONS && i < num_elements - 1)
		stroke_command = elements[i + 1];

	    if (stroke_command != NULL &&
		type == CAIRO_RECORDING_REPLAY &&
		region != CAIRO_RECORDING_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 (&command->fill.path,
					    &stroke_command->stroke.path))
	    {
		status = _cairo_surface_wrapper_fill_stroke (&wrapper,
							     command->header.op,
							     &command->fill.source.base,
							     command->fill.fill_rule,
							     command->fill.tolerance,
							     command->fill.antialias,
							     &command->fill.path,
							     stroke_command->header.op,
							     &stroke_command->stroke.source.base,
							     &stroke_command->stroke.style,
							     &stroke_command->stroke.ctm,
							     &stroke_command->stroke.ctm_inverse,
							     stroke_command->stroke.tolerance,
							     stroke_command->stroke.antialias,
							     _clip (command));
		i++;
	    }
	    else
	    {
		status = _cairo_surface_wrapper_fill (&wrapper,
						      command->header.op,
						      &command->fill.source.base,
						      &command->fill.path,
						      command->fill.fill_rule,
						      command->fill.tolerance,
						      command->fill.antialias,
						      _clip (command));
	    }
	    break;
	}
	case CAIRO_COMMAND_SHOW_TEXT_GLYPHS:
	{
	    cairo_glyph_t *glyphs = command->show_text_glyphs.glyphs;
	    cairo_glyph_t *glyphs_copy;
	    int 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.
	     */
	    glyphs_copy = _cairo_malloc_ab (num_glyphs, sizeof (cairo_glyph_t));
	    if (unlikely (glyphs_copy == NULL)) {
		status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
		break;
	    }

	    memcpy (glyphs_copy, glyphs, sizeof (cairo_glyph_t) * num_glyphs);

	    status = _cairo_surface_wrapper_show_text_glyphs (&wrapper,
							      command->header.op,
							      &command->show_text_glyphs.source.base,
							      command->show_text_glyphs.utf8, command->show_text_glyphs.utf8_len,
							      glyphs_copy, 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,
							      _clip (command));
	    free (glyphs_copy);
	    break;
	}
	default:
	    ASSERT_NOT_REACHED;
	}

	if (type == CAIRO_RECORDING_CREATE_REGIONS) {
	    if (status == CAIRO_STATUS_SUCCESS) {
		command->header.region = CAIRO_RECORDING_REGION_NATIVE;
	    } else if (status == CAIRO_INT_STATUS_IMAGE_FALLBACK) {
		command->header.region = CAIRO_RECORDING_REGION_IMAGE_FALLBACK;
		status = CAIRO_STATUS_SUCCESS;
	    } else {
		assert (_cairo_status_is_error (status));
	    }
	}

	if (unlikely (status))
	    break;
    }

    /* free up any caches */
    for (i = recording_surface->replay_start_idx; i < num_elements; i++) {
	cairo_command_t *command = elements[i];

	_cairo_clip_drop_cache (&command->header.clip);
    }

    _cairo_surface_wrapper_fini (&wrapper);

    return _cairo_surface_set_error (surface, status);
}