static cairo_status_t _cairo_paginated_surface_acquire_source_image (void *abstract_surface, cairo_image_surface_t **image_out, void **image_extra) { cairo_paginated_surface_t *surface = abstract_surface; cairo_surface_t *image; cairo_status_t status; cairo_rectangle_int_t extents; status = _cairo_surface_get_extents (surface->target, &extents); if (status) return status; image = _cairo_paginated_surface_create_image_surface (surface, extents.width, extents.height); status = _cairo_meta_surface_replay (surface->meta, image); if (status) { cairo_surface_destroy (image); return status; } *image_out = (cairo_image_surface_t*) image; *image_extra = NULL; return CAIRO_STATUS_SUCCESS; }
static cairo_status_t _cairo_paginated_surface_acquire_source_image (void *abstract_surface, cairo_image_surface_t **image_out, void **image_extra) { cairo_paginated_surface_t *surface = abstract_surface; cairo_bool_t is_bounded; cairo_surface_t *image; cairo_status_t status; cairo_rectangle_int_t extents; is_bounded = _cairo_surface_get_extents (surface->target, &extents); if (! is_bounded) return (cairo_status_t)CAIRO_INT_STATUS_UNSUPPORTED; image = _cairo_paginated_surface_create_image_surface (surface, extents.width, extents.height); status = _cairo_recording_surface_replay (surface->recording_surface, image); if (unlikely (status)) { cairo_surface_destroy (image); return status; } *image_out = (cairo_image_surface_t*) image; *image_extra = NULL; return CAIRO_STATUS_SUCCESS; }
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; }
static cairo_surface_t * _cairo_paginated_surface_snapshot (void *abstract_other) { cairo_status_t status; cairo_paginated_surface_t *other = abstract_other; /* XXX: Just making a snapshot of other->meta is what we really * want. But this currently triggers a bug somewhere (the "mask" * test from the test suite segfaults). * * For now, we'll create a new image surface and replay onto * that. It would be tempting to replay into other->image and then * return a snapshot of that, but that will cause the self-copy * test to fail, (since our replay will be affected by a clip that * should not have any effect on the use of the resulting snapshot * as a source). */ #if 0 return _cairo_surface_snapshot (other->meta); #else cairo_rectangle_int16_t extents; cairo_surface_t *surface; status = _cairo_surface_get_extents (other->target, &extents); if (status) return (cairo_surface_t*) &_cairo_surface_nil; surface = _cairo_paginated_surface_create_image_surface (other, extents.width, extents.height); status = _cairo_meta_surface_replay (other->meta, surface); if (status) { cairo_surface_destroy (surface); surface = (cairo_surface_t*) &_cairo_surface_nil; } return surface; #endif }