static cairo_int_status_t
_cairo_meta_surface_composite (cairo_operator_t	operator,
			       cairo_pattern_t	*src_pattern,
			       cairo_pattern_t	*mask_pattern,
			       void		*abstract_surface,
			       int		src_x,
			       int		src_y,
			       int		mask_x,
			       int		mask_y,
			       int		dst_x,
			       int		dst_y,
			       unsigned int	width,
			       unsigned int	height)
{
    cairo_meta_surface_t *meta = abstract_surface;
    cairo_command_composite_t *command;

    command = malloc (sizeof (cairo_command_composite_t));
    if (command == NULL)
	return CAIRO_STATUS_NO_MEMORY;

    command->type = CAIRO_COMMAND_COMPOSITE;
    command->operator = operator;
    _cairo_pattern_init_copy (&command->src_pattern.base, src_pattern);
    if (mask_pattern) {
	_cairo_pattern_init_copy (&command->mask_pattern.base, mask_pattern);
	command->mask_pattern_pointer = &command->mask_pattern.base;
    } else {
	command->mask_pattern_pointer = NULL;
    }
	
    command->src_x = src_x;
    command->src_y = src_y;
    command->mask_x = mask_x;
    command->mask_y = mask_y;
    command->dst_x = dst_x;
    command->dst_y = dst_y;
    command->width = width;
    command->height = height;

    if (_cairo_array_append (&meta->commands, &command, 1) == NULL) {
	_cairo_pattern_fini (&command->src_pattern.base);
	_cairo_pattern_fini (command->mask_pattern_pointer);
	free (command);
	return CAIRO_STATUS_NO_MEMORY;
    }

    return CAIRO_STATUS_SUCCESS;
}
static const cairo_pattern_t *
_cairo_tee_surface_match_source (cairo_tee_surface_t *surface,
                                 const cairo_pattern_t *source,
                                 int index,
                                 cairo_surface_wrapper_t *dest,
                                 cairo_surface_pattern_t *temp)
{
    cairo_surface_t *s;
    cairo_status_t status = cairo_pattern_get_surface ((cairo_pattern_t *)source, &s);
    if (status == CAIRO_STATUS_SUCCESS &&
        cairo_surface_get_type (s) == CAIRO_SURFACE_TYPE_TEE) {
        cairo_surface_t *tee_surf = cairo_tee_surface_index (s, index);
        if (tee_surf->status == CAIRO_STATUS_SUCCESS &&
            tee_surf->backend == dest->target->backend) {
            status = _cairo_pattern_init_copy (&temp->base, source);
            if (status == CAIRO_STATUS_SUCCESS) {
                cairo_surface_destroy (temp->surface);
                temp->surface = tee_surf;
                cairo_surface_reference (temp->surface);
                return &temp->base;
            }
        }
    }

    return source;
}
static cairo_int_status_t
_cairo_meta_surface_show_glyphs (cairo_scaled_font_t	*scaled_font,
				 cairo_operator_t	operator,
				 cairo_pattern_t	*pattern,
				 void			*abstract_surface,
				 int			source_x,
				 int			source_y,
				 int			dest_x,
				 int			dest_y,
				 unsigned int		width,
				 unsigned int		height,
				 const cairo_glyph_t	*glyphs,
				 int			num_glyphs)
{
    cairo_meta_surface_t *meta = abstract_surface;
    cairo_command_show_glyphs_t *command;

    command = malloc (sizeof (cairo_command_show_glyphs_t));
    if (command == NULL)
	return CAIRO_STATUS_NO_MEMORY;

    command->type = CAIRO_COMMAND_SHOW_GLYPHS;
    command->scaled_font = cairo_scaled_font_reference (scaled_font);
    command->operator = operator;
    _cairo_pattern_init_copy (&command->pattern.base, pattern);
    command->source_x = source_x;
    command->source_y = source_y;
    command->dest_x = dest_x;
    command->dest_y = dest_y;
    command->width = width;
    command->height = height;

    command->glyphs = malloc (sizeof (cairo_glyph_t) * num_glyphs);
    if (command->glyphs == NULL) {
	_cairo_pattern_fini (&command->pattern.base);
	free (command);
        return CAIRO_STATUS_NO_MEMORY;
    }
    memcpy (command->glyphs, glyphs, sizeof (cairo_glyph_t) * num_glyphs);

    command->num_glyphs = num_glyphs;

    if (_cairo_array_append (&meta->commands, &command, 1) == NULL) {
	_cairo_pattern_fini (&command->pattern.base);
	free (command->glyphs);
	free (command);
	return CAIRO_STATUS_NO_MEMORY;
    }

    return CAIRO_STATUS_SUCCESS;
}
static cairo_int_status_t
_cairo_meta_surface_composite_trapezoids (cairo_operator_t	operator,
					  cairo_pattern_t	*pattern,
					  void			*abstract_surface,
					  cairo_antialias_t	antialias,
					  int			x_src,
					  int			y_src,
					  int			x_dst,
					  int			y_dst,
					  unsigned int		width,
					  unsigned int		height,
					  cairo_trapezoid_t	*traps,
					  int			num_traps)
{
    cairo_meta_surface_t *meta = abstract_surface;
    cairo_command_composite_trapezoids_t *command;

    command = malloc (sizeof (cairo_command_composite_trapezoids_t));
    if (command == NULL)
	return CAIRO_STATUS_NO_MEMORY;

    command->type = CAIRO_COMMAND_COMPOSITE_TRAPEZOIDS;
    command->operator = operator;
    _cairo_pattern_init_copy (&command->pattern.base, pattern);
    command->antialias = antialias;
    command->x_src = x_src;
    command->y_src = y_src;
    command->x_dst = x_dst;
    command->y_dst = y_dst;
    command->width = width;
    command->height = height;

    command->traps = malloc (sizeof (cairo_trapezoid_t) * num_traps);
    if (command->traps == NULL) {
	_cairo_pattern_fini (&command->pattern.base);
	free (command);
        return CAIRO_STATUS_NO_MEMORY;
    }
    memcpy (command->traps, traps, sizeof (cairo_trapezoid_t) * num_traps);

    command->num_traps = num_traps;

    if (_cairo_array_append (&meta->commands, &command, 1) == NULL) {
	_cairo_pattern_fini (&command->pattern.base);
	free (command->traps);
	free (command);
	return CAIRO_STATUS_NO_MEMORY;
    }

    return CAIRO_STATUS_SUCCESS;
}
static cairo_int_status_t
_cairo_meta_surface_fill_path (cairo_operator_t	   operator,
			       cairo_pattern_t	  *pattern,
			       void		  *abstract_surface,
			       cairo_path_fixed_t *path,
			       cairo_fill_rule_t   fill_rule,
			       double		   tolerance)
{
    cairo_meta_surface_t *meta = abstract_surface;
    cairo_command_fill_path_t *command;
    cairo_status_t status;

    command = malloc (sizeof (cairo_command_fill_path_t));
    if (command == NULL)
	return CAIRO_STATUS_NO_MEMORY;

    command->type = CAIRO_COMMAND_FILL_PATH;
    command->operator = operator;
    _cairo_pattern_init_copy (&command->pattern.base, pattern);
    status = _cairo_path_fixed_init_copy (&command->path, path);
    if (status) {
	_cairo_pattern_fini (&command->pattern.base);
	free (command);
	return CAIRO_STATUS_NO_MEMORY;
    }	
    command->fill_rule = fill_rule;
    command->tolerance = tolerance;

    if (_cairo_array_append (&meta->commands, &command, 1) == NULL) {
	_cairo_path_fixed_fini (&command->path);
	_cairo_pattern_fini (&command->pattern.base);
	free (command);
	return CAIRO_STATUS_NO_MEMORY;
    }

    return CAIRO_STATUS_SUCCESS;
}