mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2026-05-05 00:38:06 +02:00
pdf: thumbnail API
This commit is contained in:
parent
26b3f83ff6
commit
2d6a0f5d16
6 changed files with 169 additions and 2 deletions
|
|
@ -81,6 +81,7 @@ cairo_pdf_surface_set_size
|
|||
cairo_pdf_surface_add_outline
|
||||
cairo_pdf_surface_set_metadata
|
||||
cairo_pdf_surface_set_page_label
|
||||
cairo_pdf_surface_set_thumbnail_size
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
|
|
|
|||
|
|
@ -77,7 +77,23 @@ struct _cairo_paginated_surface_backend {
|
|||
cairo_bool_t fallbacks_required);
|
||||
|
||||
cairo_bool_t
|
||||
(*supports_fine_grained_fallbacks) (void *surface);
|
||||
(*supports_fine_grained_fallbacks) (void *surface);
|
||||
|
||||
/* Optional. Indicates whether the page requires a thumbnail image to be
|
||||
* supplied. If a thumbnail is required, set width, heigh to size required
|
||||
* and return TRUE.
|
||||
*/
|
||||
cairo_bool_t
|
||||
(*requires_thumbnail_image) (void *surface,
|
||||
int *width,
|
||||
int *height);
|
||||
|
||||
/* If thumbbail image requested, this function will be called before
|
||||
* _show_page().
|
||||
*/
|
||||
cairo_warn cairo_int_status_t
|
||||
(*set_thumbnail_image) (void *surface,
|
||||
cairo_image_surface_t *image);
|
||||
};
|
||||
|
||||
/* A #cairo_paginated_surface_t provides a very convenient wrapper that
|
||||
|
|
|
|||
|
|
@ -290,6 +290,63 @@ _cairo_paginated_surface_release_source_image (void *abstract_surface,
|
|||
cairo_surface_destroy (&image->base);
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_paint_thumbnail_image (cairo_paginated_surface_t *surface,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
cairo_surface_pattern_t pattern;
|
||||
cairo_rectangle_int_t extents;
|
||||
double x_scale;
|
||||
double y_scale;
|
||||
cairo_surface_t *image = NULL;
|
||||
cairo_surface_t *opaque = NULL;
|
||||
cairo_status_t status = CAIRO_STATUS_SUCCESS;
|
||||
|
||||
_cairo_surface_get_extents (surface->target, &extents);
|
||||
x_scale = (double)width / extents.width;
|
||||
y_scale = (double)height / extents.height;
|
||||
|
||||
image = _cairo_paginated_surface_create_image_surface (surface, width, height);
|
||||
cairo_surface_set_device_scale (image, x_scale, y_scale);
|
||||
cairo_surface_set_device_offset (image, -extents.x*x_scale, -extents.y*y_scale);
|
||||
status = _cairo_recording_surface_replay (surface->recording_surface, image);
|
||||
if (unlikely (status))
|
||||
goto cleanup;
|
||||
|
||||
/* flatten transparency */
|
||||
|
||||
opaque = cairo_image_surface_create (CAIRO_FORMAT_RGB24, width, height);
|
||||
if (unlikely (opaque->status)) {
|
||||
status = opaque->status;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
status = _cairo_surface_paint (opaque,
|
||||
CAIRO_OPERATOR_SOURCE,
|
||||
&_cairo_pattern_white.base,
|
||||
NULL);
|
||||
if (unlikely (status))
|
||||
goto cleanup;
|
||||
|
||||
_cairo_pattern_init_for_surface (&pattern, image);
|
||||
pattern.base.filter = CAIRO_FILTER_NEAREST;
|
||||
status = _cairo_surface_paint (opaque, CAIRO_OPERATOR_OVER, &pattern.base, NULL);
|
||||
_cairo_pattern_fini (&pattern.base);
|
||||
if (unlikely (status))
|
||||
goto cleanup;
|
||||
|
||||
status = surface->backend->set_thumbnail_image (surface->target, (cairo_image_surface_t *)opaque);
|
||||
|
||||
cleanup:
|
||||
if (image)
|
||||
cairo_surface_destroy (image);
|
||||
if (opaque)
|
||||
cairo_surface_destroy (opaque);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_paint_fallback_image (cairo_paginated_surface_t *surface,
|
||||
cairo_rectangle_int_t *rect)
|
||||
|
|
@ -460,6 +517,13 @@ _paint_page (cairo_paginated_surface_t *surface)
|
|||
}
|
||||
}
|
||||
|
||||
if (surface->backend->requires_thumbnail_image) {
|
||||
int width, height;
|
||||
|
||||
if (surface->backend->requires_thumbnail_image (surface->target, &width, &height))
|
||||
_paint_thumbnail_image (surface, width, height);
|
||||
}
|
||||
|
||||
FAIL:
|
||||
cairo_surface_destroy (analysis);
|
||||
|
||||
|
|
|
|||
|
|
@ -330,6 +330,10 @@ struct _cairo_pdf_surface {
|
|||
cairo_pdf_resource_t docinfo_res;
|
||||
cairo_pdf_resource_t page_labels_res;
|
||||
|
||||
int thumbnail_width;
|
||||
int thumbnail_height;
|
||||
cairo_image_surface_t *thumbnail_image;
|
||||
|
||||
cairo_surface_t *paginated_surface;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -453,6 +453,9 @@ _cairo_pdf_surface_create_for_stream_internal (cairo_output_stream_t *output,
|
|||
surface->names_dict_res.id = 0;
|
||||
surface->docinfo_res.id = 0;
|
||||
surface->page_labels_res.id = 0;
|
||||
surface->thumbnail_width = 0;
|
||||
surface->thumbnail_height = 0;
|
||||
surface->thumbnail_image = NULL;
|
||||
|
||||
surface->paginated_surface = _cairo_paginated_surface_create (
|
||||
&surface->base,
|
||||
|
|
@ -832,6 +835,32 @@ cairo_pdf_surface_set_page_label (cairo_surface_t *surface,
|
|||
pdf_surface->current_page_label = utf8 ? strdup (utf8) : NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* cairo_pdf_surface_set_thumbnail_size:
|
||||
* @surface: a PDF #cairo_surface_t
|
||||
* @width: Thumbnail width.
|
||||
* @height: Thumbnail height
|
||||
*
|
||||
* Set the thumbnail image size for the current and all subsequent
|
||||
* pages. Setting a width or height of 0 disables thumbnails for the
|
||||
* current and subsequent pages.
|
||||
*
|
||||
* Since: 1.16
|
||||
**/
|
||||
void
|
||||
cairo_pdf_surface_set_thumbnail_size (cairo_surface_t *surface,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
cairo_pdf_surface_t *pdf_surface = NULL; /* hide compiler warning */
|
||||
|
||||
if (! _extract_pdf_surface (surface, &pdf_surface))
|
||||
return;
|
||||
|
||||
pdf_surface->thumbnail_width = width;
|
||||
pdf_surface->thumbnail_height = height;
|
||||
}
|
||||
|
||||
static void
|
||||
_cairo_pdf_surface_clear (cairo_pdf_surface_t *surface)
|
||||
{
|
||||
|
|
@ -862,6 +891,9 @@ _cairo_pdf_surface_clear (cairo_pdf_surface_t *surface)
|
|||
_cairo_array_truncate (&surface->smask_groups, 0);
|
||||
_cairo_array_truncate (&surface->knockout_group, 0);
|
||||
_cairo_array_truncate (&surface->page_annots, 0);
|
||||
|
||||
cairo_surface_destroy (&surface->thumbnail_image->base);
|
||||
surface->thumbnail_image = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -2365,6 +2397,33 @@ _cairo_pdf_surface_supports_fine_grained_fallbacks (void *abstract_surface)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static cairo_bool_t
|
||||
_cairo_pdf_surface_requires_thumbnail_image (void *abstract_surface,
|
||||
int *width,
|
||||
int *height)
|
||||
{
|
||||
cairo_pdf_surface_t *surface = abstract_surface;
|
||||
|
||||
if (surface->thumbnail_width > 0 && surface->thumbnail_height > 0) {
|
||||
*width = surface->thumbnail_width;
|
||||
*height = surface->thumbnail_height;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_pdf_surface_set_thumbnail_image (void *abstract_surface,
|
||||
cairo_image_surface_t *image)
|
||||
{
|
||||
cairo_pdf_surface_t *surface = abstract_surface;
|
||||
|
||||
surface->thumbnail_image = (cairo_image_surface_t *)cairo_surface_reference(&image->base);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_pdf_surface_add_padded_image_surface (cairo_pdf_surface_t *surface,
|
||||
const cairo_pattern_t *source,
|
||||
|
|
@ -6590,7 +6649,7 @@ _cairo_pdf_surface_write_patterns_and_smask_groups (cairo_pdf_surface_t *surface
|
|||
static cairo_int_status_t
|
||||
_cairo_pdf_surface_write_page (cairo_pdf_surface_t *surface)
|
||||
{
|
||||
cairo_pdf_resource_t knockout, res;
|
||||
cairo_pdf_resource_t knockout, res, thumbnail_res;
|
||||
cairo_pdf_resource_t *page;
|
||||
cairo_int_status_t status;
|
||||
unsigned int i, len, page_num, num_annots;
|
||||
|
|
@ -6651,6 +6710,16 @@ _cairo_pdf_surface_write_page (cairo_pdf_surface_t *surface)
|
|||
return status;
|
||||
}
|
||||
|
||||
thumbnail_res.id = 0;
|
||||
if (surface->thumbnail_image) {
|
||||
cairo_pdf_source_surface_entry_t entry;
|
||||
|
||||
memset (&entry, 0, sizeof (entry));
|
||||
thumbnail_res = _cairo_pdf_surface_new_object (surface);
|
||||
entry.surface_res = thumbnail_res;
|
||||
_cairo_pdf_surface_emit_image (surface, surface->thumbnail_image, &entry);
|
||||
}
|
||||
|
||||
page_num = _cairo_array_num_elements (&surface->pages);
|
||||
page = _cairo_array_index (&surface->pages, page_num - 1);
|
||||
_cairo_pdf_surface_update_object (surface, *page);
|
||||
|
|
@ -6693,6 +6762,12 @@ _cairo_pdf_surface_write_page (cairo_pdf_surface_t *surface)
|
|||
_cairo_output_stream_printf (surface->output, "]\n");
|
||||
}
|
||||
|
||||
if (thumbnail_res.id) {
|
||||
_cairo_output_stream_printf (surface->output,
|
||||
" /Thumb %d 0 R\n",
|
||||
thumbnail_res.id);
|
||||
}
|
||||
|
||||
_cairo_output_stream_printf (surface->output,
|
||||
">>\n"
|
||||
"endobj\n");
|
||||
|
|
@ -8209,4 +8284,6 @@ cairo_pdf_surface_paginated_backend = {
|
|||
NULL, /* set_bounding_box */
|
||||
_cairo_pdf_surface_has_fallback_images,
|
||||
_cairo_pdf_surface_supports_fine_grained_fallbacks,
|
||||
_cairo_pdf_surface_requires_thumbnail_image,
|
||||
_cairo_pdf_surface_set_thumbnail_image,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -148,6 +148,11 @@ void
|
|||
cairo_pdf_surface_set_page_label (cairo_surface_t *surface,
|
||||
const char *utf8);
|
||||
|
||||
void
|
||||
cairo_pdf_surface_set_thumbnail_size (cairo_surface_t *surface,
|
||||
int width,
|
||||
int height);
|
||||
|
||||
CAIRO_END_DECLS
|
||||
|
||||
#else /* CAIRO_HAS_PDF_SURFACE */
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue