diff options
author | Adrian Johnson <ajohnson@redneon.com> | 2016-10-01 22:46:49 +0930 |
---|---|---|
committer | Adrian Johnson <ajohnson@redneon.com> | 2016-10-01 22:46:49 +0930 |
commit | 2d6a0f5d16d61c8f4236760c71061a0c4c3a199c (patch) | |
tree | 4b98a5cde00839c8b8c2b3f5578a21566270630e /src | |
parent | 26b3f83ff652a284b79557ec1555b398c566a7eb (diff) |
pdf: thumbnail API
Diffstat (limited to 'src')
-rw-r--r-- | src/cairo-paginated-private.h | 18 | ||||
-rw-r--r-- | src/cairo-paginated-surface.c | 64 | ||||
-rw-r--r-- | src/cairo-pdf-surface-private.h | 4 | ||||
-rw-r--r-- | src/cairo-pdf-surface.c | 79 | ||||
-rw-r--r-- | src/cairo-pdf.h | 5 |
5 files changed, 168 insertions, 2 deletions
diff --git a/src/cairo-paginated-private.h b/src/cairo-paginated-private.h index 29eefc76a..b85a5db6b 100644 --- a/src/cairo-paginated-private.h +++ b/src/cairo-paginated-private.h @@ -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 diff --git a/src/cairo-paginated-surface.c b/src/cairo-paginated-surface.c index 749f0de73..e9454d416 100644 --- a/src/cairo-paginated-surface.c +++ b/src/cairo-paginated-surface.c @@ -291,6 +291,63 @@ _cairo_paginated_surface_release_source_image (void *abstract_surface, } 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); diff --git a/src/cairo-pdf-surface-private.h b/src/cairo-pdf-surface-private.h index 960e07cd9..c1fd11a91 100644 --- a/src/cairo-pdf-surface-private.h +++ b/src/cairo-pdf-surface-private.h @@ -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; }; diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c index 900055431..e60d0b9a6 100644 --- a/src/cairo-pdf-surface.c +++ b/src/cairo-pdf-surface.c @@ -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, }; diff --git a/src/cairo-pdf.h b/src/cairo-pdf.h index 9bf69fedd..62bf41fca 100644 --- a/src/cairo-pdf.h +++ b/src/cairo-pdf.h @@ -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 */ |