From c4a57385fa2e69020f43519bea21b98182bf5fd7 Mon Sep 17 00:00:00 2001 From: Adrian Johnson Date: Sun, 23 Nov 2008 21:12:08 +1030 Subject: PDF: Add cairo_pdf_surface_restrict_to_version API Now that we are using PDF 1.5 features, add an api to select between version 1.4 or 1.5. --- src/cairo-pdf-surface-private.h | 2 + src/cairo-pdf-surface.c | 116 +++++++++++++++++++++++++++++++++++++--- src/cairo-pdf.h | 24 +++++++++ 3 files changed, 136 insertions(+), 6 deletions(-) diff --git a/src/cairo-pdf-surface-private.h b/src/cairo-pdf-surface-private.h index 7f2764ff..d2fa43c4 100644 --- a/src/cairo-pdf-surface-private.h +++ b/src/cairo-pdf-surface-private.h @@ -128,12 +128,14 @@ struct _cairo_pdf_surface { cairo_pdf_resource_t next_available_resource; cairo_pdf_resource_t pages_resource; + cairo_pdf_version_t pdf_version; cairo_bool_t compress_content; cairo_pdf_resource_t content; cairo_pdf_resource_t content_resources; cairo_pdf_group_resources_t resources; cairo_bool_t has_fallback_images; + cairo_bool_t header_emitted; struct { cairo_bool_t active; diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c index 322c7737..bf80a944 100644 --- a/src/cairo-pdf-surface.c +++ b/src/cairo-pdf-surface.c @@ -111,6 +111,20 @@ * XObject instead of using an indirect object. */ +static const cairo_pdf_version_t _cairo_pdf_versions[] = +{ + CAIRO_PDF_VERSION_1_4, + CAIRO_PDF_VERSION_1_5 +}; + +#define CAIRO_PDF_VERSION_LAST ARRAY_LENGTH (_cairo_pdf_versions) + +static const char * _cairo_pdf_version_strings[CAIRO_PDF_VERSION_LAST] = +{ + "PDF 1.4", + "PDF 1.5" +}; + typedef struct _cairo_pdf_object { long offset; } cairo_pdf_object_t; @@ -273,6 +287,7 @@ _cairo_pdf_surface_create_for_stream_internal (cairo_output_stream_t *output, goto BAIL1; } + surface->pdf_version = CAIRO_PDF_VERSION_1_5; surface->compress_content = TRUE; surface->pdf_stream.active = FALSE; surface->pdf_stream.old_output = NULL; @@ -285,6 +300,7 @@ _cairo_pdf_surface_create_for_stream_internal (cairo_output_stream_t *output, surface->force_fallbacks = FALSE; surface->select_pattern_gstate_saved = FALSE; surface->current_pattern_is_solid_color = FALSE; + surface->header_emitted = FALSE; _cairo_pdf_operators_init (&surface->pdf_operators, surface->output, @@ -294,12 +310,6 @@ _cairo_pdf_surface_create_for_stream_internal (cairo_output_stream_t *output, _cairo_pdf_surface_add_font, surface); - /* Document header */ - _cairo_output_stream_printf (surface->output, - "%%PDF-1.5\n"); - _cairo_output_stream_printf (surface->output, - "%%%c%c%c%c\n", 181, 237, 174, 251); - surface->paginated_surface = _cairo_paginated_surface_create ( &surface->base, CAIRO_CONTENT_COLOR_ALPHA, @@ -437,6 +447,80 @@ _extract_pdf_surface (cairo_surface_t *surface, return CAIRO_STATUS_SUCCESS; } +/** + * cairo_pdf_surface_restrict_to_version: + * @surface: a PDF #cairo_surface_t + * @version: PDF version + * + * Restricts the generated PDF file to @version. See cairo_pdf_get_versions() + * for a list of available version values that can be used here. + * + * This function should only be called before any drawing operations + * have been performed on the given surface. The simplest way to do + * this is to call this function immediately after creating the + * surface. + * + * Since: 1.10 + **/ +void +cairo_pdf_surface_restrict_to_version (cairo_surface_t *abstract_surface, + cairo_pdf_version_t version) +{ + cairo_pdf_surface_t *surface = NULL; /* hide compiler warning */ + cairo_status_t status; + + status = _extract_pdf_surface (abstract_surface, &surface); + if (status) { + status = _cairo_surface_set_error (abstract_surface, status); + return; + } + + if (version < CAIRO_PDF_VERSION_LAST) + surface->pdf_version = version; +} + +/** + * cairo_pdf_get_versions: + * @versions: supported version list + * @num_versions: list length + * + * Used to retrieve the list of supported versions. See + * cairo_pdf_surface_restrict_to_version(). + * + * Since: 1.10 + **/ +void +cairo_pdf_get_versions (cairo_pdf_version_t const **versions, + int *num_versions) +{ + if (versions != NULL) + *versions = _cairo_pdf_versions; + + if (num_versions != NULL) + *num_versions = CAIRO_PDF_VERSION_LAST; +} + +/** + * cairo_pdf_version_to_string: + * @version: a version id + * + * Get the string representation of the given @version id. This function + * will return %NULL if @version isn't valid. See cairo_pdf_get_versions() + * for a way to get the list of valid version ids. + * + * Return value: the string associated to given version. + * + * Since: 1.10 + **/ +const char * +cairo_pdf_version_to_string (cairo_pdf_version_t version) +{ + if (version >= CAIRO_PDF_VERSION_LAST) + return NULL; + + return _cairo_pdf_version_strings[version]; +} + /** * cairo_pdf_surface_set_size: * @surface: a PDF #cairo_surface_t @@ -1291,6 +1375,26 @@ _cairo_pdf_surface_start_page (void *abstract_surface) { cairo_pdf_surface_t *surface = abstract_surface; + /* Document header */ + if (! surface->header_emitted) { + const char *version; + + switch (surface->pdf_version) { + case CAIRO_PDF_VERSION_1_4: + version = "1.4"; + break; + case CAIRO_PDF_VERSION_1_5: + version = "1.5"; + break; + } + + _cairo_output_stream_printf (surface->output, + "%%PDF-%s\n", version); + _cairo_output_stream_printf (surface->output, + "%%%c%c%c%c\n", 181, 237, 174, 251); + surface->header_emitted = TRUE; + } + _cairo_pdf_group_resources_clear (&surface->resources); return CAIRO_STATUS_SUCCESS; diff --git a/src/cairo-pdf.h b/src/cairo-pdf.h index 1a066b3a..294f36d2 100644 --- a/src/cairo-pdf.h +++ b/src/cairo-pdf.h @@ -43,6 +43,19 @@ CAIRO_BEGIN_DECLS +/** + * cairo_pdf_version_t: + * @CAIRO_PDF_VERSION_1_4: The version 1.4 of the PDF specification. + * @CAIRO_PDF_VERSION_1_5: The version 1.5 of the PDF specification. + * + * #cairo_pdf_version_t is used to describe the version number of the PDF + * specification that a generated PDF file will conform to. + */ +typedef enum _cairo_pdf_version { + CAIRO_PDF_VERSION_1_4, + CAIRO_PDF_VERSION_1_5 +} cairo_pdf_version_t; + cairo_public cairo_surface_t * cairo_pdf_surface_create (const char *filename, double width_in_points, @@ -54,6 +67,17 @@ cairo_pdf_surface_create_for_stream (cairo_write_func_t write_func, double width_in_points, double height_in_points); +cairo_public void +cairo_pdf_surface_restrict_to_version (cairo_surface_t *surface, + cairo_pdf_version_t version); + +cairo_public void +cairo_pdf_get_versions (cairo_pdf_version_t const **versions, + int *num_versions); + +cairo_public const char * +cairo_pdf_version_to_string (cairo_pdf_version_t version); + cairo_public void cairo_pdf_surface_set_size (cairo_surface_t *surface, double width_in_points, -- cgit v1.2.3