static cairo_int_status_t
_paint_page (cairo_paginated_surface_t *surface)
{
    cairo_surface_t *analysis;
    cairo_surface_t *image;
    cairo_pattern_t *pattern;
    cairo_status_t status;

    analysis = _cairo_analysis_surface_create (surface->target,
					       surface->width, surface->height);
    if (analysis == NULL)
	return CAIRO_STATUS_NO_MEMORY;

    surface->backend->set_paginated_mode (surface->target, CAIRO_PAGINATED_MODE_ANALYZE);
    status = _cairo_meta_surface_replay (surface->meta, analysis);
    surface->backend->set_paginated_mode (surface->target, CAIRO_PAGINATED_MODE_RENDER);

    if (status || analysis->status) {
	if (status == CAIRO_STATUS_SUCCESS)
	    status = analysis->status;
	cairo_surface_destroy (analysis);
	return status;
    }

    if (_cairo_analysis_surface_has_unsupported (analysis))
    {
	double x_scale = surface->base.x_fallback_resolution / 72.0;
	double y_scale = surface->base.y_fallback_resolution / 72.0;
	cairo_matrix_t matrix;

	image = _cairo_paginated_surface_create_image_surface (surface,
							       surface->width  * x_scale,
							       surface->height * y_scale);
	_cairo_surface_set_device_scale (image, x_scale, y_scale);

	status = _cairo_meta_surface_replay (surface->meta, image);
	if (status)
	    goto CLEANUP_IMAGE;

	pattern = cairo_pattern_create_for_surface (image);
	cairo_matrix_init_scale (&matrix, x_scale, y_scale);
	cairo_pattern_set_matrix (pattern, &matrix);

	status = _cairo_surface_paint (surface->target, CAIRO_OPERATOR_SOURCE, pattern);

	cairo_pattern_destroy (pattern);

     CLEANUP_IMAGE:
	cairo_surface_destroy (image);
    }
    else
    {
	status = _cairo_meta_surface_replay (surface->meta, surface->target);
    }

    cairo_surface_destroy (analysis);

    return status;
}
static cairo_int_status_t
_paint_fallback_image (cairo_paginated_surface_t *surface,
		       cairo_rectangle_int_t     *rect)
{
    double x_scale = surface->base.x_fallback_resolution / surface->target->x_resolution;
    double y_scale = surface->base.y_fallback_resolution / surface->target->y_resolution;
    int x, y, width, height;
    cairo_status_t status;
    cairo_surface_t *image;
    cairo_surface_pattern_t pattern;
    cairo_clip_t *clip;

    x = rect->x;
    y = rect->y;
    width = rect->width;
    height = rect->height;
    image = _cairo_paginated_surface_create_image_surface (surface,
							   ceil (width  * x_scale),
							   ceil (height * y_scale));
    _cairo_surface_set_device_scale (image, x_scale, y_scale);
    /* set_device_offset just sets the x0/y0 components of the matrix;
     * so we have to do the scaling manually. */
    cairo_surface_set_device_offset (image, -x*x_scale, -y*y_scale);

    status = _cairo_recording_surface_replay (surface->recording_surface, image);
    if (unlikely (status))
	goto CLEANUP_IMAGE;

    _cairo_pattern_init_for_surface (&pattern, image);
    cairo_matrix_init (&pattern.base.matrix,
		       x_scale, 0, 0, y_scale, -x*x_scale, -y*y_scale);
    /* the fallback should be rendered at native resolution, so disable
     * filtering (if possible) to avoid introducing potential artifacts. */
    pattern.base.filter = CAIRO_FILTER_NEAREST;

    clip = _cairo_clip_intersect_rectangle (NULL, rect);
    status = _cairo_surface_paint (surface->target,
				   CAIRO_OPERATOR_SOURCE,
				   &pattern.base, clip);
    _cairo_clip_destroy (clip);
    _cairo_pattern_fini (&pattern.base);

CLEANUP_IMAGE:
    cairo_surface_destroy (image);

    return (cairo_int_status_t)status;
}
static cairo_int_status_t
_paint_fallback_image (cairo_paginated_surface_t *surface,
		       cairo_box_int_t           *box)
{
    double x_scale = surface->base.x_fallback_resolution / surface->target->x_resolution;
    double y_scale = surface->base.y_fallback_resolution / surface->target->y_resolution;
    cairo_matrix_t matrix;
    int x, y, width, height;
    cairo_status_t status;
    cairo_surface_t *image;
    cairo_pattern_t *pattern;

    x = box->p1.x;
    y = box->p1.y;
    width = box->p2.x - x;
    height = box->p2.y - y;
    image = _cairo_paginated_surface_create_image_surface (surface,
							   ceil (width  * x_scale),
							   ceil (height * y_scale));
    _cairo_surface_set_device_scale (image, x_scale, y_scale);
    /* set_device_offset just sets the x0/y0 components of the matrix;
     * so we have to do the scaling manually. */
    cairo_surface_set_device_offset (image, -x*x_scale, -y*y_scale);

    status = _cairo_meta_surface_replay (surface->meta, image);
    if (status)
	goto CLEANUP_IMAGE;

    pattern = cairo_pattern_create_for_surface (image);
    cairo_matrix_init (&matrix, x_scale, 0, 0, y_scale, -x*x_scale, -y*y_scale);
    cairo_pattern_set_matrix (pattern, &matrix);

    status = _cairo_surface_paint (surface->target,
				   CAIRO_OPERATOR_SOURCE,
				   pattern);

    cairo_pattern_destroy (pattern);
CLEANUP_IMAGE:
    cairo_surface_destroy (image);

    return status;
}