[cairo-commit] src/cairo-ps.h src/cairo-ps-surface.c src/.gitignore test/.gitignore test/Makefile.am test/ps-features.c

Carl Worth cworth at kemper.freedesktop.org
Tue May 2 12:51:43 PDT 2006


 src/.gitignore         |    1 
 src/cairo-ps-surface.c |  113 ++++++++++++++++++++++++++++++++++-------
 src/cairo-ps.h         |    5 +
 test/.gitignore        |    2 
 test/Makefile.am       |    5 +
 test/ps-features.c     |  135 +++++++++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 243 insertions(+), 18 deletions(-)

New commits:
diff-tree 8488aaee1a8f25d3cc9bf2af986b32710cea91f0 (from e59f35291fa5f97acfe408b7bce8652ec20566c8)
Author: Carl Worth <cworth at cworth.org>
Date:   Tue May 2 12:36:23 2006 -0700

    PS: Add cairo_ps_surface_set_size along with ps-features test
    
    Add a new cairo_ps_surface_set_size which can be used to produce a
    PostScript file consisting of pages of various different sizes (or
    orientations).
    
    Also add a new test (ps-features.c) for testing this and subsequent
    ps-specific function calls.

diff --git a/src/.gitignore b/src/.gitignore
index eac847c..abf1f37 100644
--- a/src/.gitignore
+++ b/src/.gitignore
@@ -11,3 +11,4 @@ cairo-features.h
 cairo.def
 *.o
 *~
+TAGS
diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c
index 31498a8..bb9a0ed 100644
--- a/src/cairo-ps-surface.c
+++ b/src/cairo-ps-surface.c
@@ -93,6 +93,8 @@ typedef struct cairo_ps_surface {
 
     double width;
     double height;
+    double max_width;
+    double max_height;
     double x_dpi;
     double y_dpi;
 
@@ -176,12 +178,12 @@ _cairo_ps_surface_emit_header (cairo_ps_
 				 "%%%%Creator: cairo (http://cairographics.org)\n"
 				 "%%%%CreationDate: %s"
 				 "%%%%Pages: %d\n"
-				 "%%%%BoundingBox: %f %f %f %f\n",
+				 "%%%%BoundingBox: %d %d %d %d\n",
 				 ctime (&now),
 				 surface->num_pages,
-				 0.0, 0.0, 
-				 surface->width,
-				 surface->height);
+				 0, 0,
+				 (int) (surface->max_width + 0.5),
+				 (int) (surface->max_height + 0.5));
 
     _cairo_output_stream_printf (surface->final_stream,
 				 "%%%%DocumentData: Clean7Bit\n"
@@ -548,6 +550,8 @@ _cairo_ps_surface_create_for_stream_inte
     
     surface->width  = width;
     surface->height = height;
+    surface->max_width = width;
+    surface->max_height = height;
     surface->x_dpi = PS_SURFACE_DPI_DEFAULT;
     surface->y_dpi = PS_SURFACE_DPI_DEFAULT;
     surface->paginated_mode = CAIRO_PAGINATED_MODE_ANALYZE;
@@ -567,7 +571,12 @@ _cairo_ps_surface_create_for_stream_inte
  * @height_in_points: height of the surface, in points (1 point == 1/72.0 inch)
  * 
  * Creates a PostScript surface of the specified size in points to be
- * written to @filename.
+ * written to @filename. See cairo_ps_surface_create_for_stream() for
+ * a more flexible mechanism for handling the PostScript output than
+ * simply writing it to a named file.
+ *
+ * Note that the size of individual pages of the PostScript output can
+ * vary. See cairo_ps_surface_set_size().
  *
  * Return value: a pointer to the newly created surface. The caller
  * owns the surface and should call cairo_surface_destroy when done
@@ -606,7 +615,11 @@ cairo_ps_surface_create (const char		*fi
  * 
  * Creates a PostScript surface of the specified size in points to be
  * written incrementally to the stream represented by @write and
- * @closure.
+ * @closure. See cairo_ps_surface_create() for a more convenient way
+ * to simply direct the PostScript output to a named file.
+ *
+ * Note that the size of individual pages of the PostScript
+ * output can vary. See cairo_ps_surface_set_size().
  *
  * Return value: a pointer to the newly created surface. The caller
  * owns the surface and should call cairo_surface_destroy when done
@@ -643,9 +656,32 @@ _cairo_surface_is_ps (cairo_surface_t *s
     return surface->backend == &cairo_ps_surface_backend;
 }
 
+/* If the abstract_surface is a paginated surface, and that paginated
+ * surface's target is a ps_surface, then set ps_surface to that
+ * target. Otherwise return CAIRO_STATUS_SURFACE_TYPE_MISMATCH.
+ */
+static cairo_status_t
+_extract_ps_surface (cairo_surface_t	 *surface,
+		     cairo_ps_surface_t **ps_surface)
+{
+    cairo_surface_t *target;
+
+    if (! _cairo_surface_is_paginated (surface))
+	return CAIRO_STATUS_SURFACE_TYPE_MISMATCH;
+
+    target = _cairo_paginated_surface_get_target (surface);
+
+    if (! _cairo_surface_is_ps (target))
+	return CAIRO_STATUS_SURFACE_TYPE_MISMATCH;
+
+    *ps_surface = (cairo_ps_surface_t *) target;
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
 /**
  * cairo_ps_surface_set_dpi:
- * @surface: a postscript cairo_surface_t
+ * @surface: a PostScript cairo_surface_t
  * @x_dpi: horizontal dpi
  * @y_dpi: vertical dpi
  * 
@@ -660,26 +696,50 @@ cairo_ps_surface_set_dpi (cairo_surface_
 			  double	   x_dpi,
 			  double	   y_dpi)
 {
-    cairo_surface_t *target;
     cairo_ps_surface_t *ps_surface;
+    cairo_status_t status;
 
-    if (! _cairo_surface_is_paginated (surface)) {
-	_cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
+    status = _extract_ps_surface (surface, &ps_surface);
+    if (status) {
+	_cairo_surface_set_error (surface, status);
 	return;
     }
 
-    target = _cairo_paginated_surface_get_target (surface);
+    ps_surface->x_dpi = x_dpi;    
+    ps_surface->y_dpi = y_dpi;
+}
 
-    if (! _cairo_surface_is_ps (target)) {
-	_cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
+/**
+ * cairo_ps_surface_set_size:
+ * @surface: a PostScript cairo_surface_t
+ * @width_in_points: new surface width, in points (1 point == 1/72.0 inch)
+ * @height_in_points: new surface height, in points (1 point == 1/72.0 inch)
+ * 
+ * Changes the size of a PostScript surface for the current (and
+ * subsequent) pages.
+ *
+ * This function should only be called before any drawing operations
+ * have been performed on the current page. The simplest way to do
+ * this is to call this function immediately after creating the
+ * surface or immediately after completing a page with either
+ * cairo_show_page() or cairo_copy_page().
+ **/
+void
+cairo_ps_surface_set_size (cairo_surface_t	*surface,
+			   double		 width_in_points,
+			   double		 height_in_points)
+{
+    cairo_ps_surface_t *ps_surface;
+    cairo_status_t status;
+
+    status = _extract_ps_surface (surface, &ps_surface);
+    if (status) {
+	_cairo_surface_set_error (surface, CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
 	return;
     }
 
-    ps_surface = (cairo_ps_surface_t *) target;
-
-    ps_surface->x_dpi = x_dpi;    
-    ps_surface->y_dpi = y_dpi;
-
+    ps_surface->width = width_in_points;
+    ps_surface->height = height_in_points;
 }
 
 /* A word wrap stream can be used as a filter to do word wrapping on
@@ -858,11 +918,28 @@ _cairo_ps_surface_start_page (void *abst
 				 surface->num_pages);
 
     _cairo_output_stream_printf (surface->stream,
+				 "%%%%BeginPageSetup\n");
+
+    _cairo_output_stream_printf (surface->stream,
+				 "%%%%PageBoundingBox: %d %d %d %d\n",
+				 0, 0,
+				 (int) (surface->width + 0.5),
+				 (int) (surface->height + 0.5));
+
+    _cairo_output_stream_printf (surface->stream,
 				 "gsave %f %f translate %f %f scale \n",
 				 0.0, surface->height,
 				 1.0/surface->base.device_x_scale,
 				 -1.0/surface->base.device_y_scale);
 
+    _cairo_output_stream_printf (surface->stream,
+				 "%%%%EndPageSetup\n");
+
+    if (surface->width > surface->max_width)
+	surface->max_width = surface->width;
+    if (surface->height > surface->max_height)
+	surface->max_height = surface->height;
+
     return _cairo_output_stream_get_status (surface->stream);
 }
 
diff --git a/src/cairo-ps.h b/src/cairo-ps.h
index 0db0c02..75c624e 100644
--- a/src/cairo-ps.h
+++ b/src/cairo-ps.h
@@ -59,6 +59,11 @@ cairo_ps_surface_create_for_stream (cair
 				    double		height_in_points);
 
 cairo_public void
+cairo_ps_surface_set_size (cairo_surface_t	*abstract_surface,
+			   double		 width_in_points,
+			   double		 height_in_points);
+
+cairo_public void
 cairo_ps_surface_set_dpi (cairo_surface_t      *surface,
 			  double		x_dpi,
 			  double		y_dpi);
diff --git a/test/.gitignore b/test/.gitignore
index b1704f6..bc4855c 100644
--- a/test/.gitignore
+++ b/test/.gitignore
@@ -53,6 +53,8 @@ path-data
 pattern-get-type
 pdf2png
 png-flatten
+ps-features
+ps-features.ps
 svg2png
 svg-clip
 svg-clip.svg
diff --git a/test/Makefile.am b/test/Makefile.am
index 3d459c4..9ff4d96 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -83,6 +83,10 @@ if CAIRO_HAS_SVG_SURFACE
 TESTS += svg-surface svg-clip
 endif
 
+if CAIRO_HAS_PS_SURFACE
+TESTS += ps-features
+endif
+
 if CAIRO_HAS_XLIB_SURFACE
 TESTS += xlib-surface
 endif
@@ -298,6 +302,7 @@ CLEANFILES =					\
 	*.log					\
 	multi-page.ps				\
 	multi-page.pdf				\
+	ps-features.ps				\
 	svg-surface.svg				\
 	svg-clip.svg
 
diff --git a/test/ps-features.c b/test/ps-features.c
new file mode 100644
index 0000000..501e412
--- /dev/null
+++ b/test/ps-features.c
@@ -0,0 +1,135 @@
+/*
+ * Copyright © 2006 Red Hat, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without
+ * fee, provided that the above copyright notice appear in all copies
+ * and that both that copyright notice and this permission notice
+ * appear in supporting documentation, and that the name of
+ * Red Hat, Inc. not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior
+ * permission. Red Hat, Inc. makes no representations about the
+ * suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * RED HAT, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL RED HAT, INC. BE LIABLE FOR ANY SPECIAL,
+ * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
+ * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Author: Carl D. Worth <cworth at cworth.org>
+ */
+
+#include <stdio.h>
+#include <cairo.h>
+#include <cairo-ps.h>
+
+#include "cairo-test.h"
+
+/* This test exists to test the various features of cairo-ps.h.
+ *
+ * Currently, this test exercises the following function calls:
+ *
+ *	cairo_ps_surface_set_size
+ */
+
+#define INCHES_TO_POINTS(in) ((in) * 72.0)
+#define MM_TO_POINTS(mm) ((mm) / 25.4 * 72.0)
+#define TEXT_SIZE 12
+
+#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(arr[0]))
+
+struct {
+    const char *page_size;
+    const char *orientation;
+    double width_in_points;
+    double height_in_points;
+} pages[] = {
+    {"na_letter_8.5x11in", "portrait",
+     INCHES_TO_POINTS(8.5), INCHES_TO_POINTS(11)},
+    {"na_letter_8.5x11in", "landscape",
+     INCHES_TO_POINTS(11), INCHES_TO_POINTS(8.5)},
+    {"iso_a4_210x297mm", "portrait",
+     MM_TO_POINTS(210), MM_TO_POINTS(297)},
+    {"iso_a4_210x297mm", "landscape",
+     MM_TO_POINTS(297), MM_TO_POINTS(210)},
+    {"iso_a5_148x210mm", "portrait",
+     MM_TO_POINTS(148), MM_TO_POINTS(210)},
+    {"iso_a5_148x210mm", "landscape",
+     MM_TO_POINTS(210), MM_TO_POINTS(148)},
+    {"iso_a6_105x148mm", "portrait",
+     MM_TO_POINTS(105), MM_TO_POINTS(148)},
+    {"iso_a6_105x148mm", "landscape",
+     MM_TO_POINTS(148), MM_TO_POINTS(105)},
+    {"iso_a7_74x105mm", "portrait",
+     MM_TO_POINTS(74), MM_TO_POINTS(105)},
+    {"iso_a7_74x105mm", "landscape",
+     MM_TO_POINTS(105), MM_TO_POINTS(74)},
+    {"iso_a8_52x74mm", "portrait",
+     MM_TO_POINTS(52), MM_TO_POINTS(74)},
+    {"iso_a8_52x74mm", "landscape",
+     MM_TO_POINTS(74), MM_TO_POINTS(52)},
+    {"iso_a9_37x52mm", "portrait",
+     MM_TO_POINTS(37), MM_TO_POINTS(52)},
+    {"iso_a9_37x52mm", "landscape",
+     MM_TO_POINTS(52), MM_TO_POINTS(37)},
+    {"iso_a10_26x37mm", "portrait",
+     MM_TO_POINTS(26), MM_TO_POINTS(37)},
+    {"iso_a10_26x37mm", "landscape",
+     MM_TO_POINTS(37), MM_TO_POINTS(26)}
+};
+
+int
+main (void)
+{
+    cairo_surface_t *surface;
+    cairo_t *cr;
+    cairo_status_t status;
+    char *filename;
+    int i;
+
+    printf("\n");
+
+    filename = "ps-features.ps";
+
+    /* We demonstrate that the initial size doesn't matter (we're
+     * passing 0,0), if we use cairo_ps_surface_set_size on the first
+     * page. */
+    surface = cairo_ps_surface_create (filename, 0, 0);
+
+    cr = cairo_create (surface);
+
+    cairo_select_font_face (cr, "Bitstream Vera Sans",
+			    CAIRO_FONT_SLANT_NORMAL,
+			    CAIRO_FONT_WEIGHT_NORMAL);
+    cairo_set_font_size (cr, TEXT_SIZE);
+
+    for (i=0; i < ARRAY_SIZE(pages); i++) {
+	cairo_ps_surface_set_size (surface,
+				   pages[i].width_in_points,
+				   pages[i].height_in_points);
+	cairo_move_to (cr, TEXT_SIZE, TEXT_SIZE);
+	cairo_show_text (cr, pages[i].page_size);
+	cairo_show_text (cr, " - ");
+	cairo_show_text (cr, pages[i].orientation);
+	cairo_show_page (cr);
+    }
+
+    status = cairo_status (cr);
+
+    cairo_destroy (cr);
+    cairo_surface_destroy (surface);
+
+    if (status) {
+	cairo_test_log ("Failed to create pdf surface for file %s: %s\n",
+			filename, cairo_status_to_string (status));
+	return CAIRO_TEST_FAILURE;
+    }
+
+    printf ("multi-page-size: Please check %s to ensure it looks/prints correctly.\n", filename);
+
+    return CAIRO_TEST_SUCCESS;
+}


More information about the cairo-commit mailing list