[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