summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdrian Johnson <ajohnson@redneon.com>2009-09-25 23:07:56 +0930
committerAdrian Johnson <ajohnson@redneon.com>2009-09-25 23:24:36 +0930
commitdb5e3db0a9b218bebad6921a95d5244047050348 (patch)
tree8cfcbedd28ea2112eed39e695329c475e011fea8
parentcaa9eed4646e78a62ffb49d9c4f48c0b351c7a7f (diff)
PS: Add DocumentMedia/PageMedia DSC comments
Provide default DocumentMedia and PageMedia DSC comments if the user does not specify them using cairo_ps_surface_dsc_comment(). This is required so that PostScript viewers such as gv use the correct page size.
-rw-r--r--src/cairo-ps-surface-private.h1
-rw-r--r--src/cairo-ps-surface.c88
2 files changed, 89 insertions, 0 deletions
diff --git a/src/cairo-ps-surface-private.h b/src/cairo-ps-surface-private.h
index e892103b..3dc00080 100644
--- a/src/cairo-ps-surface-private.h
+++ b/src/cairo-ps-surface-private.h
@@ -90,6 +90,7 @@ typedef struct cairo_ps_surface {
cairo_scaled_font_subsets_t *font_subsets;
+ cairo_list_t document_media;
cairo_array_t dsc_header_comments;
cairo_array_t dsc_setup_comments;
cairo_array_t dsc_page_setup_comments;
diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c
index 26bba176..a523d5e3 100644
--- a/src/cairo-ps-surface.c
+++ b/src/cairo-ps-surface.c
@@ -106,6 +106,13 @@ static const char * _cairo_ps_level_strings[CAIRO_PS_LEVEL_LAST] =
"PS Level 3"
};
+typedef struct _cairo_page_media {
+ char *name;
+ int width;
+ int height;
+ cairo_list_t link;
+} cairo_page_media_t;
+
static void
_cairo_ps_surface_emit_header (cairo_ps_surface_t *surface)
{
@@ -149,6 +156,27 @@ _cairo_ps_surface_emit_header (cairo_ps_surface_t *surface)
"%%%%LanguageLevel: %d\n",
level);
+ if (!cairo_list_is_empty (&surface->document_media)) {
+ cairo_page_media_t *page;
+ cairo_bool_t first = TRUE;
+
+ cairo_list_foreach_entry (page, cairo_page_media_t, &surface->document_media, link) {
+ if (first) {
+ _cairo_output_stream_printf (surface->final_stream,
+ "%%%%DocumentMedia: ");
+ first = FALSE;
+ } else {
+ _cairo_output_stream_printf (surface->final_stream,
+ "%%%%+ ");
+ }
+ _cairo_output_stream_printf (surface->final_stream,
+ "%s %d %d 0 () ()\n",
+ page->name,
+ page->width,
+ page->height);
+ }
+ }
+
num_comments = _cairo_array_num_elements (&surface->dsc_header_comments);
comments = _cairo_array_index (&surface->dsc_header_comments, 0);
for (i = 0; i < num_comments; i++) {
@@ -775,6 +803,39 @@ _cairo_ps_surface_clipper_intersect_clip_path (cairo_surface_clipper_t *clipper,
fill_rule);
}
+static const char *
+_cairo_ps_surface_get_page_media (cairo_ps_surface_t *surface)
+{
+ int width, height;
+ char buf[50];
+ cairo_page_media_t *page;
+
+ width = _cairo_lround (surface->width);
+ height = _cairo_lround (surface->height);
+ cairo_list_foreach_entry (page, cairo_page_media_t, &surface->document_media, link) {
+ if (page->width == width && page->height == height)
+ return page->name;
+ }
+
+ page = malloc (sizeof (cairo_page_media_t));
+ if (unlikely (page == NULL)) {
+ _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
+ return NULL;
+ }
+
+ snprintf (buf, sizeof (buf), "p%dx%d", width , height);
+ page->name = strdup (buf);
+ if (unlikely (page->name == NULL)) {
+ _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
+ return NULL;
+ }
+
+ page->width = width;
+ page->height = height;
+ cairo_list_add_tail (&page->link, &surface->document_media);
+
+ return page->name;
+}
static cairo_surface_t *
_cairo_ps_surface_create_for_stream_internal (cairo_output_stream_t *stream,
@@ -841,6 +902,7 @@ _cairo_ps_surface_create_for_stream_internal (cairo_output_stream_t *stream,
surface->font_subsets);
surface->num_pages = 0;
+ cairo_list_init (&surface->document_media);
_cairo_array_init (&surface->dsc_header_comments, sizeof (char *));
_cairo_array_init (&surface->dsc_setup_comments, sizeof (char *));
_cairo_array_init (&surface->dsc_page_setup_comments, sizeof (char *));
@@ -1392,6 +1454,17 @@ CLEANUP:
if (status == CAIRO_STATUS_SUCCESS)
status = status2;
+ while (! cairo_list_is_empty (&surface->document_media)) {
+ cairo_page_media_t *page;
+
+ page = cairo_list_first_entry (&surface->document_media,
+ cairo_page_media_t,
+ link);
+ cairo_list_del (&page->link);
+ free (page->name);
+ free (page);
+ }
+
num_comments = _cairo_array_num_elements (&surface->dsc_header_comments);
comments = _cairo_array_index (&surface->dsc_header_comments, 0);
for (i = 0; i < num_comments; i++)
@@ -3563,6 +3636,8 @@ _cairo_ps_surface_set_bounding_box (void *abstract_surface,
int i, num_comments;
char **comments;
int x1, y1, x2, y2;
+ cairo_bool_t has_page_media;
+ const char *page_media;
if (surface->eps) {
x1 = floor (_cairo_fixed_to_double (bbox->p1.x));
@@ -3589,16 +3664,29 @@ _cairo_ps_surface_set_bounding_box (void *abstract_surface,
_cairo_output_stream_printf (surface->stream,
"%%%%BeginPageSetup\n");
+ has_page_media = FALSE;
num_comments = _cairo_array_num_elements (&surface->dsc_page_setup_comments);
comments = _cairo_array_index (&surface->dsc_page_setup_comments, 0);
for (i = 0; i < num_comments; i++) {
_cairo_output_stream_printf (surface->stream,
"%s\n", comments[i]);
+ if (strncmp (comments[i], "%%PageMedia:", 11) == 0)
+ has_page_media = TRUE;
free (comments[i]);
comments[i] = NULL;
}
_cairo_array_truncate (&surface->dsc_page_setup_comments, 0);
+ if (!has_page_media && !surface->eps) {
+ page_media = _cairo_ps_surface_get_page_media (surface);
+ if (unlikely (page_media == NULL))
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
+ _cairo_output_stream_printf (surface->stream,
+ "%%%%PageMedia: %s\n",
+ page_media);
+ }
+
_cairo_output_stream_printf (surface->stream,
"%%%%PageBoundingBox: %d %d %d %d\n",
x1, y1, x2, y2);