[cairo-commit] src/cairo-ps-surface.c src/cairo-ps-surface-private.h

Adrian Johnson ajohnson at kemper.freedesktop.org
Fri Sep 25 06:55:44 PDT 2009


 src/cairo-ps-surface-private.h |    1 
 src/cairo-ps-surface.c         |   88 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 89 insertions(+)

New commits:
commit db5e3db0a9b218bebad6921a95d5244047050348
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Fri Sep 25 23:07:56 2009 +0930

    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.

diff --git a/src/cairo-ps-surface-private.h b/src/cairo-ps-surface-private.h
index e892103..3dc0008 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 26bba17..a523d5e 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);


More information about the cairo-commit mailing list