summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarl Worth <cworth@cworth.org>2003-10-31 21:30:35 +0000
committerCarl Worth <cworth@cworth.org>2003-10-31 21:30:35 +0000
commitc6255f9c295dc2b273b8aa4c5ce558d6d2a05887 (patch)
treed416e4cbe2ea52da4377ca0e1a1466a6edd99a33
parent9736375a7a106b9fd6745dcea26572a63f1334f5 (diff)
Implemented preliminary PostScript output support. Added cairo_show_page. Bumped version number to 0.1.10
-rw-r--r--ChangeLog29
-rw-r--r--configure.in2
-rw-r--r--src/Makefile.am1
-rw-r--r--src/cairo-gstate.c9
-rw-r--r--src/cairo-image-surface.c18
-rw-r--r--src/cairo-ps-surface.c377
-rw-r--r--src/cairo-surface.c15
-rw-r--r--src/cairo-xlib-surface.c7
-rw-r--r--src/cairo.c9
-rw-r--r--src/cairo.h49
-rw-r--r--src/cairo_gstate.c9
-rw-r--r--src/cairo_image_surface.c18
-rw-r--r--src/cairo_ps_surface.c377
-rw-r--r--src/cairo_surface.c15
-rw-r--r--src/cairo_xlib_surface.c7
-rw-r--r--src/cairoint.h16
16 files changed, 942 insertions, 16 deletions
diff --git a/ChangeLog b/ChangeLog
index 186aa03e..f5e49b53 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,32 @@
+2003-11-01 Carl Worth <cworth@isi.edu>
+
+ * configure.in (CAIRO_VERSION): Bumped version to 0.1.10 for new
+ functions cairo_set_target_ps, cairo_ps_surface_create, and
+ cairo_show_page.
+
+ * src/cairo_ps_surface.c: New file with preliminary support for
+ drawing to a PostScript file. Most of the ps_surface backend
+ functions are just tiny wrappers, deferring to image_surface
+ functions to do the real work. Then, in show_page, the image is
+ compressed and spit out into the file. Crude and effective.
+
+ * src/cairo.c (cairo_show_page):
+ * src/cairo_gstate.c (_cairo_gstate_show_page):
+ * src/cairo_image_surface (_cairo_image_surface_show_page):
+ * src/cairo_xlib_surface.c (_cairo_xlib_surface_show_page):
+ * src/cairo_surface.c (_cairo_surface_show_page): Implement new
+ support for cairo_show_page -- just a stub in the non-PS surfaces.
+
+ * src/cairo_image_surface.c (_cairo_image_surface_set_filter):
+ Export this function for internal use.
+
+ * src/cairo.h: Added cairo_set_target_ps, cairo_ps_surface_create,
+ and cairo_show_page. Noted plans for new cairo_surface_clip_begin,
+ perhaps moving some cairo_surface functions to cairo_set_pattern,
+ and possibly renaming cairo_matrix_t to cairo_transform_t.
+
+ * src/Makefile.am (libcairo_la_SOURCES): Added cairo_ps_surface.c.
+
2003-10-31 Carl Worth <cworth@isi.edu>
* src/cairo_gstate.c (_cairo_gstate_arc):
diff --git a/configure.in b/configure.in
index 4c950021..57c89556 100644
--- a/configure.in
+++ b/configure.in
@@ -3,7 +3,7 @@ AC_INIT(src/cairo.h)
dnl ===========================================================================
# Package version number, (as distinct from shared library version)
-CAIRO_VERSION=0.1.9
+CAIRO_VERSION=0.1.10
# libtool shared library version
diff --git a/src/Makefile.am b/src/Makefile.am
index e90b0fa3..8ff927be 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -18,6 +18,7 @@ libcairo_la_SOURCES = \
cairo_path_stroke.c \
cairo_pen.c \
cairo_polygon.c \
+ cairo_ps_surface.c \
cairo_slope.c \
cairo_spline.c \
cairo_surface.c \
diff --git a/src/cairo-gstate.c b/src/cairo-gstate.c
index 7b9fdd59..8405c32c 100644
--- a/src/cairo-gstate.c
+++ b/src/cairo-gstate.c
@@ -1345,6 +1345,15 @@ _cairo_gstate_fill (cairo_gstate_t *gstate)
}
cairo_status_t
+_cairo_gstate_show_page (cairo_gstate_t *gstate)
+{
+ if (gstate->surface == NULL)
+ return CAIRO_STATUS_NO_TARGET_SURFACE;
+
+ return _cairo_surface_show_page (gstate->surface);
+}
+
+cairo_status_t
_cairo_gstate_clip (cairo_gstate_t *gstate)
{
cairo_status_t status;
diff --git a/src/cairo-image-surface.c b/src/cairo-image-surface.c
index 908e4342..ffd03d0b 100644
--- a/src/cairo-image-surface.c
+++ b/src/cairo-image-surface.c
@@ -251,9 +251,16 @@ _cairo_image_surface_set_matrix (cairo_image_surface_t *surface,
}
static cairo_status_t
-_cairo_image_surface_set_filter (void *abstract_surface, cairo_filter_t filter)
+_cairo_image_abstract_surface_set_filter (void *abstract_surface, cairo_filter_t filter)
{
cairo_image_surface_t *surface = abstract_surface;
+
+ return _cairo_image_surface_set_filter (surface, filter);
+}
+
+cairo_status_t
+_cairo_image_surface_set_filter (cairo_image_surface_t *surface, cairo_filter_t filter)
+{
IcFilter ic_filter;
switch (filter) {
@@ -414,6 +421,12 @@ _cairo_image_surface_composite_trapezoids (cairo_operator_t operator,
return CAIRO_STATUS_SUCCESS;
}
+static cairo_int_status_t
+_cairo_image_surface_show_page (void *abstract_surface)
+{
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+}
+
static const cairo_surface_backend_t cairo_image_surface_backend = {
_cairo_image_surface_create_similar,
_cairo_image_abstract_surface_destroy,
@@ -421,9 +434,10 @@ static const cairo_surface_backend_t cairo_image_surface_backend = {
_cairo_image_surface_get_image,
_cairo_image_surface_set_image,
_cairo_image_abstract_surface_set_matrix,
- _cairo_image_surface_set_filter,
+ _cairo_image_abstract_surface_set_filter,
_cairo_image_abstract_surface_set_repeat,
_cairo_image_surface_composite,
_cairo_image_surface_fill_rectangles,
_cairo_image_surface_composite_trapezoids,
+ _cairo_image_surface_show_page
};
diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c
new file mode 100644
index 00000000..f78c0ff3
--- /dev/null
+++ b/src/cairo-ps-surface.c
@@ -0,0 +1,377 @@
+/*
+ * Copyright © 2003 University of Southern California
+ *
+ * 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 the
+ * University of Southern California not be used in advertising or
+ * publicity pertaining to distribution of the software without
+ * specific, written prior permission. The University of Southern
+ * California makes no representations about the suitability of this
+ * software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ *
+ * THE UNIVERSITY OF SOUTHERN CALIFORNIA DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF
+ * SOUTHERN CALIFORNIA 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@isi.edu>
+ */
+
+#include "cairoint.h"
+
+#include <time.h>
+#include <zlib.h>
+
+static const cairo_surface_backend_t cairo_ps_surface_backend;
+
+void
+cairo_set_target_ps (cairo_t *cr,
+ FILE *file,
+ double width_inches,
+ double height_inches,
+ double x_pixels_per_inch,
+ double y_pixels_per_inch)
+{
+ cairo_surface_t *surface;
+
+ surface = cairo_ps_surface_create (file,
+ width_inches, height_inches,
+ x_pixels_per_inch, y_pixels_per_inch);
+
+ cairo_set_target_surface (cr, surface);
+
+ /* cairo_set_target_surface takes a reference, so we must destroy ours */
+ cairo_surface_destroy (surface);
+}
+
+typedef struct cairo_ps_surface {
+ cairo_surface_t base;
+
+ /* PS-specific fields */
+ FILE *file;
+
+ double width_inches;
+ double height_inches;
+ double x_ppi;
+ double y_ppi;
+
+ cairo_image_surface_t *image;
+} cairo_ps_surface_t;
+
+cairo_surface_t *
+cairo_ps_surface_create (FILE *file,
+ double width_inches,
+ double height_inches,
+ double x_pixels_per_inch,
+ double y_pixels_per_inch)
+{
+ cairo_ps_surface_t *surface;
+ int width, height;
+ cairo_color_t transparent;
+
+ surface = malloc (sizeof (cairo_ps_surface_t));
+ if (surface == NULL)
+ return NULL;
+
+ _cairo_surface_init (&surface->base, &cairo_ps_surface_backend);
+
+ surface->file = file;
+
+ surface->width_inches = width_inches;
+ surface->height_inches = height_inches;
+ surface->x_ppi = x_pixels_per_inch;
+ surface->y_ppi = x_pixels_per_inch;
+
+ width = (int) (x_pixels_per_inch * width_inches + 1.0);
+ height = (int) (y_pixels_per_inch * height_inches + 1.0);
+
+ surface->image = (cairo_image_surface_t *)
+ cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
+ if (surface->image == NULL) {
+ free (surface);
+ return NULL;
+ }
+
+ _cairo_color_init (&transparent);
+ _cairo_color_set_rgb (&transparent, 0., 0., 0.);
+ _cairo_color_set_alpha (&transparent, 0.);
+ _cairo_surface_fill_rectangle (&surface->image->base,
+ CAIRO_OPERATOR_SRC,
+ &transparent, 0, 0, width, height);
+
+ return &surface->base;
+}
+
+static cairo_surface_t *
+_cairo_ps_surface_create_similar (void *abstract_src,
+ cairo_format_t format,
+ int width,
+ int height)
+{
+ return NULL;
+}
+
+static void
+_cairo_ps_surface_destroy (void *abstract_surface)
+{
+ cairo_ps_surface_t *surface = abstract_surface;
+
+ cairo_surface_destroy (&surface->image->base);
+
+ free (surface);
+}
+
+/* XXX: We should re-work this interface to return both X/Y ppi values. */
+static double
+_cairo_ps_surface_pixels_per_inch (void *abstract_surface)
+{
+ cairo_ps_surface_t *surface = abstract_surface;
+
+ return surface->y_ppi;
+}
+
+static cairo_image_surface_t *
+_cairo_ps_surface_get_image (void *abstract_surface)
+{
+ cairo_ps_surface_t *surface = abstract_surface;
+
+ cairo_surface_reference (&surface->image->base);
+
+ return surface->image;
+}
+
+static cairo_status_t
+_cairo_ps_surface_set_image (void *abstract_surface,
+ cairo_image_surface_t *image)
+{
+ cairo_ps_surface_t *surface = abstract_surface;
+
+ if (image == surface->image)
+ return CAIRO_STATUS_SUCCESS;
+
+ /* XXX: Need to call _cairo_image_surface_set_image here, but it's
+ not implemented yet. */
+
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+}
+
+static cairo_status_t
+_cairo_ps_surface_set_matrix (void *abstract_surface,
+ cairo_matrix_t *matrix)
+{
+ cairo_ps_surface_t *surface = abstract_surface;
+
+ return _cairo_image_surface_set_matrix (surface->image, matrix);
+}
+
+static cairo_status_t
+_cairo_ps_surface_set_filter (void *abstract_surface,
+ cairo_filter_t filter)
+{
+ cairo_ps_surface_t *surface = abstract_surface;
+
+ return _cairo_image_surface_set_filter (surface->image, filter);
+}
+
+static cairo_status_t
+_cairo_ps_surface_set_repeat (void *abstract_surface,
+ int repeat)
+{
+ cairo_ps_surface_t *surface = abstract_surface;
+
+ return _cairo_image_surface_set_repeat (surface->image, repeat);
+}
+
+static cairo_int_status_t
+_cairo_ps_surface_composite (cairo_operator_t operator,
+ cairo_surface_t *generic_src,
+ cairo_surface_t *generic_mask,
+ void *abstract_dst,
+ int src_x,
+ int src_y,
+ int mask_x,
+ int mask_y,
+ int dst_x,
+ int dst_y,
+ unsigned int width,
+ unsigned int height)
+{
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+}
+
+static cairo_int_status_t
+_cairo_ps_surface_fill_rectangles (void *abstract_surface,
+ cairo_operator_t operator,
+ const cairo_color_t *color,
+ cairo_rectangle_t *rects,
+ int num_rects)
+{
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+}
+
+static cairo_int_status_t
+_cairo_ps_surface_composite_trapezoids (cairo_operator_t operator,
+ cairo_surface_t *generic_src,
+ void *abstract_dst,
+ int x_src,
+ int y_src,
+ cairo_trapezoid_t *traps,
+ int num_traps)
+{
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+}
+
+static cairo_int_status_t
+_cairo_ps_surface_show_page (void *abstract_surface)
+{
+ cairo_status_t status = CAIRO_STATUS_SUCCESS;
+ cairo_ps_surface_t *surface = abstract_surface;
+ int width = surface->image->width;
+ int height = surface->image->height;
+ FILE *file = surface->file;
+
+ int i, x, y;
+ time_t now = time (0);
+
+ cairo_surface_t *white_surface;
+ char *bgr, *compressed;
+ long bgr_size, compressed_size;
+
+ cairo_color_t white;
+
+ bgr_size = 3 * width * height;
+ bgr = malloc (bgr_size);
+ if (bgr == NULL) {
+ status = CAIRO_STATUS_NO_MEMORY;
+ goto BAIL0;
+ }
+
+ compressed_size = (int) (1.0 + 1.1 * bgr_size);
+ compressed = malloc (compressed_size);
+ if (compressed == NULL) {
+ status = CAIRO_STATUS_NO_MEMORY;
+ goto BAIL1;
+ }
+
+ /* PostScript can not represent the alpha channel, so we blend the
+ current image over a white RGB surface to eliminate it. */
+ white_surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24, 1, 1);
+ if (white_surface == NULL) {
+ status = CAIRO_STATUS_NO_MEMORY;
+ goto BAIL2;
+ }
+
+ _cairo_color_init (&white);
+ _cairo_surface_fill_rectangle (white_surface,
+ CAIRO_OPERATOR_SRC,
+ &white,
+ 0, 0, 1, 1);
+ cairo_surface_set_repeat (white_surface, 1);
+ _cairo_surface_composite (CAIRO_OPERATOR_OVER_REVERSE,
+ white_surface,
+ NULL,
+ &surface->image->base,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ width, height);
+
+ i = 0;
+ for (y = 0; y < height; y++) {
+ char *line = surface->image->data + y * surface->image->stride;
+ for (x = 0; x < width; x++) {
+ unsigned char *pixel = (unsigned char *) line + x * 4;
+ bgr[i++] = *(pixel+2);
+ bgr[i++] = *(pixel+1);
+ bgr[i++] = *(pixel);
+ }
+ }
+
+ compress (compressed, &compressed_size, bgr, bgr_size);
+
+ /* Document header */
+ fprintf (file,
+ "%%!PS-Adobe-3.0\n"
+ "%%%%Creator: Cairo (http://cairographics.org)\n");
+ fprintf (file,
+ "%%%%CreationDate: %s",
+ ctime (&now));
+ fprintf (file,
+ "%%%%Copyright: 2003 Carl Worth and Keith Packard\n");
+ fprintf (file,
+ "%%%%BoundingBox: %d %d %d %d\n",
+ 0, 0, (int) (surface->width_inches * 72.0), (int) (surface->height_inches * 72.0));
+ fprintf (file,
+ "%%%%DocumentData: Clean7Bit\n"
+ "%%%%LanguageLevel: 3\n");
+ fprintf (file,
+ "%%%%Pages: %d\n",
+ 1);
+ fprintf (file,
+ "%%%%Orientation: Portrait\n"
+ "%%%%EndComments\n");
+
+ /* Page header */
+ fprintf (file, "%%%%Page: %d\n", 1);
+
+ fprintf (file, "gsave\n");
+
+ /* Image header goop */
+ fprintf (file, "%g %g translate\n", 0.0, surface->width_inches * 72.0);
+ fprintf (file, "%g %g scale\n", 72.0 / surface->x_ppi, 72.0 / surface->y_ppi);
+ fprintf (file, "/DeviceRGB setcolorspace\n");
+ fprintf (file, "<<\n");
+ fprintf (file, " /ImageType 1\n");
+ fprintf (file, " /Width %d\n", width);
+ fprintf (file, " /Height %d\n", height);
+ fprintf (file, " /BitsPerComponent 8\n");
+ fprintf (file, " /Decode [ 0 1 0 1 0 1 ]\n");
+ fprintf (file, " /DataSource currentfile /FlateDecode filter\n");
+ fprintf (file, " /ImageMatrix [ 1 0 0 -1 0 1 ]\n");
+ fprintf (file, ">>\n");
+ fprintf (file, "image\n");
+
+ /* Compressed image data */
+ fwrite (compressed, 1, compressed_size, file);
+
+ fprintf (file, "showpage\n");
+
+ fprintf (file, "grestore\n");
+
+ /* Page footer */
+ fprintf (file, "%%%%EndPage\n");
+
+ /* Document footer */
+ fprintf (file, "%%%%EOF\n");
+
+ cairo_surface_destroy (white_surface);
+ BAIL2:
+ free (compressed);
+ BAIL1:
+ free (bgr);
+ BAIL0:
+ return status;
+}
+
+static const cairo_surface_backend_t cairo_ps_surface_backend = {
+ _cairo_ps_surface_create_similar,
+ _cairo_ps_surface_destroy,
+ _cairo_ps_surface_pixels_per_inch,
+ _cairo_ps_surface_get_image,
+ _cairo_ps_surface_set_image,
+ _cairo_ps_surface_set_matrix,
+ _cairo_ps_surface_set_filter,
+ _cairo_ps_surface_set_repeat,
+ _cairo_ps_surface_composite,
+ _cairo_ps_surface_fill_rectangles,
+ _cairo_ps_surface_composite_trapezoids,
+ _cairo_ps_surface_show_page
+};
diff --git a/src/cairo-surface.c b/src/cairo-surface.c
index 41baabec..0e847eae 100644
--- a/src/cairo-surface.c
+++ b/src/cairo-surface.c
@@ -334,3 +334,18 @@ _cairo_surface_composite_trapezoids (cairo_operator_t operator,
return status;
}
+cairo_status_t
+_cairo_surface_show_page (cairo_surface_t *surface)
+{
+ cairo_int_status_t status;
+
+ status = surface->backend->show_page (surface);
+ /* It's fine if some backends just don't support this. */
+ if (status == CAIRO_INT_STATUS_UNSUPPORTED)
+ return CAIRO_STATUS_SUCCESS;
+ if (status)
+ return status;
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
diff --git a/src/cairo-xlib-surface.c b/src/cairo-xlib-surface.c
index 41ab48bd..9d705150 100644
--- a/src/cairo-xlib-surface.c
+++ b/src/cairo-xlib-surface.c
@@ -556,7 +556,11 @@ _cairo_xlib_surface_composite_trapezoids (cairo_operator_t operator,
return CAIRO_STATUS_SUCCESS;
}
-
+static cairo_int_status_t
+_cairo_xlib_surface_show_page (void *abstract_surface)
+{
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+}
static const struct cairo_surface_backend cairo_xlib_surface_backend = {
_cairo_xlib_surface_create_similar,
@@ -570,6 +574,7 @@ static const struct cairo_surface_backend cairo_xlib_surface_backend = {
_cairo_xlib_surface_composite,
_cairo_xlib_surface_fill_rectangles,
_cairo_xlib_surface_composite_trapezoids,
+ _cairo_xlib_surface_show_page
};
cairo_surface_t *
diff --git a/src/cairo.c b/src/cairo.c
index 77220cbf..e80fd6cd 100644
--- a/src/cairo.c
+++ b/src/cairo.c
@@ -584,6 +584,15 @@ cairo_fill (cairo_t *cr)
}
void
+cairo_show_page (cairo_t *cr)
+{
+ if (cr->status)
+ return;
+
+ cr->status = _cairo_gstate_show_page (cr->gstate);
+}
+
+void
cairo_clip (cairo_t *cr)
{
if (cr->status)
diff --git a/src/cairo.h b/src/cairo.h
index 8a64d3fb..1944aaa7 100644
--- a/src/cairo.h
+++ b/src/cairo.h
@@ -29,6 +29,7 @@
#define _CAIRO_H_
#include <ic.h>
+#include <stdio.h>
#ifdef _CAIROINT_H_
#include <slim_export.h>
@@ -90,6 +91,14 @@ cairo_set_target_image (cairo_t *cr,
int height,
int stride);
+void
+cairo_set_target_ps (cairo_t *cr,
+ FILE *file,
+ double width_inches,
+ double height_inches,
+ double x_pixels_per_inch,
+ double y_pixels_per_inch);
+
typedef enum cairo_operator {
CAIRO_OPERATOR_CLEAR,
CAIRO_OPERATOR_SRC,
@@ -286,6 +295,9 @@ cairo_stroke (cairo_t *cr);
extern void __external_linkage
cairo_fill (cairo_t *cr);
+void
+cairo_show_page (cairo_t *cr);
+
/* Clipping */
extern void __external_linkage
cairo_clip (cairo_t *cr);
@@ -497,15 +509,18 @@ cairo_status (cairo_t *cr);
extern const char * __external_linkage
cairo_status_string (cairo_t *cr);
-/* Surface mainpulation */
-
+/* Surface manipulation */
+/* XXX: We may want to rename this function in light of the new
+ virtualized surface backends... */
extern cairo_surface_t * __external_linkage
-cairo_surface_create_for_image (char *data,
- cairo_format_t format,
- int width,
- int height,
- int stride);
-
+cairo_surface_create_for_image (char *data,
+ cairo_format_t format,
+ int width,
+ int height,
+ int stride);
+
+/* XXX: I want to remove this function, (replace with
+ cairo_set_target_scratch or similar). */
extern cairo_surface_t * __external_linkage
cairo_surface_create_similar (cairo_surface_t *other,
cairo_format_t format,
@@ -523,6 +538,9 @@ extern cairo_status_t __external_linkage
cairo_surface_clip_restore (cairo_surface_t *surface);
extern cairo_status_t __external_linkage
+cairo_surface_clip_begin (cairo_surface_t *surface);
+
+extern cairo_status_t __external_linkage
cairo_surface_clip_rectangle (cairo_surface_t *surface,
int x, int y,
int width, int height);
@@ -530,12 +548,15 @@ cairo_surface_clip_rectangle (cairo_surface_t *surface,
/* XXX: Note: The current Render/Ic implementations don't do the right
thing with repeat when the surface has a non-identity matrix. */
+/* XXX: Rework this as a cairo function with an enum: cairo_set_pattern_extend */
extern cairo_status_t __external_linkage
cairo_surface_set_repeat (cairo_surface_t *surface, int repeat);
+/* XXX: Rework this as a cairo function: cairo_set_pattern_transform */
extern cairo_status_t __external_linkage
cairo_surface_set_matrix (cairo_surface_t *surface, cairo_matrix_t *matrix);
+/* XXX: Rework this as a cairo function: cairo_current_pattern_transform */
extern cairo_status_t __external_linkage
cairo_surface_get_matrix (cairo_surface_t *surface, cairo_matrix_t *matrix);
@@ -547,6 +568,7 @@ typedef enum cairo_filter {
CAIRO_FILTER_BILINEAR,
} cairo_filter_t;
+/* XXX: Rework this as a cairo function: cairo_set_pattern_filter */
extern cairo_status_t __external_linkage
cairo_surface_set_filter (cairo_surface_t *surface, cairo_filter_t filter);
@@ -564,8 +586,19 @@ cairo_image_surface_create_for_data (char *data,
int height,
int stride);
+/* PS-surface functions */
+
+cairo_surface_t *
+cairo_ps_surface_create (FILE *file,
+ double width_inches,
+ double height_inches,
+ double x_pixels_per_inch,
+ double y_pixels_per_inch);
+
/* Matrix functions */
+/* XXX: Rename all of these to cairo_transform_t */
+
extern cairo_matrix_t * __external_linkage
cairo_matrix_create (void);
diff --git a/src/cairo_gstate.c b/src/cairo_gstate.c
index 7b9fdd59..8405c32c 100644
--- a/src/cairo_gstate.c
+++ b/src/cairo_gstate.c
@@ -1345,6 +1345,15 @@ _cairo_gstate_fill (cairo_gstate_t *gstate)
}
cairo_status_t
+_cairo_gstate_show_page (cairo_gstate_t *gstate)
+{
+ if (gstate->surface == NULL)
+ return CAIRO_STATUS_NO_TARGET_SURFACE;
+
+ return _cairo_surface_show_page (gstate->surface);
+}
+
+cairo_status_t
_cairo_gstate_clip (cairo_gstate_t *gstate)
{
cairo_status_t status;
diff --git a/src/cairo_image_surface.c b/src/cairo_image_surface.c
index 908e4342..ffd03d0b 100644
--- a/src/cairo_image_surface.c
+++ b/src/cairo_image_surface.c
@@ -251,9 +251,16 @@ _cairo_image_surface_set_matrix (cairo_image_surface_t *surface,
}
static cairo_status_t
-_cairo_image_surface_set_filter (void *abstract_surface, cairo_filter_t filter)
+_cairo_image_abstract_surface_set_filter (void *abstract_surface, cairo_filter_t filter)
{
cairo_image_surface_t *surface = abstract_surface;
+
+ return _cairo_image_surface_set_filter (surface, filter);
+}
+
+cairo_status_t
+_cairo_image_surface_set_filter (cairo_image_surface_t *surface, cairo_filter_t filter)
+{
IcFilter ic_filter;
switch (filter) {
@@ -414,6 +421,12 @@ _cairo_image_surface_composite_trapezoids (cairo_operator_t operator,
return CAIRO_STATUS_SUCCESS;
}
+static cairo_int_status_t
+_cairo_image_surface_show_page (void *abstract_surface)
+{
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+}
+
static const cairo_surface_backend_t cairo_image_surface_backend = {
_cairo_image_surface_create_similar,
_cairo_image_abstract_surface_destroy,
@@ -421,9 +434,10 @@ static const cairo_surface_backend_t cairo_image_surface_backend = {
_cairo_image_surface_get_image,
_cairo_image_surface_set_image,
_cairo_image_abstract_surface_set_matrix,
- _cairo_image_surface_set_filter,
+ _cairo_image_abstract_surface_set_filter,
_cairo_image_abstract_surface_set_repeat,
_cairo_image_surface_composite,
_cairo_image_surface_fill_rectangles,
_cairo_image_surface_composite_trapezoids,
+ _cairo_image_surface_show_page
};
diff --git a/src/cairo_ps_surface.c b/src/cairo_ps_surface.c
new file mode 100644
index 00000000..f78c0ff3
--- /dev/null
+++ b/src/cairo_ps_surface.c
@@ -0,0 +1,377 @@
+/*
+ * Copyright © 2003 University of Southern California
+ *
+ * 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 the
+ * University of Southern California not be used in advertising or
+ * publicity pertaining to distribution of the software without
+ * specific, written prior permission. The University of Southern
+ * California makes no representations about the suitability of this
+ * software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ *
+ * THE UNIVERSITY OF SOUTHERN CALIFORNIA DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF
+ * SOUTHERN CALIFORNIA 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@isi.edu>
+ */
+
+#include "cairoint.h"
+
+#include <time.h>
+#include <zlib.h>
+
+static const cairo_surface_backend_t cairo_ps_surface_backend;
+
+void
+cairo_set_target_ps (cairo_t *cr,
+ FILE *file,
+ double width_inches,
+ double height_inches,
+ double x_pixels_per_inch,
+ double y_pixels_per_inch)
+{
+ cairo_surface_t *surface;
+
+ surface = cairo_ps_surface_create (file,
+ width_inches, height_inches,
+ x_pixels_per_inch, y_pixels_per_inch);
+
+ cairo_set_target_surface (cr, surface);
+
+ /* cairo_set_target_surface takes a reference, so we must destroy ours */
+ cairo_surface_destroy (surface);
+}
+
+typedef struct cairo_ps_surface {
+ cairo_surface_t base;
+
+ /* PS-specific fields */
+ FILE *file;
+
+ double width_inches;
+ double height_inches;
+ double x_ppi;
+ double y_ppi;
+
+ cairo_image_surface_t *image;
+} cairo_ps_surface_t;
+
+cairo_surface_t *
+cairo_ps_surface_create (FILE *file,
+ double width_inches,
+ double height_inches,
+ double x_pixels_per_inch,
+ double y_pixels_per_inch)
+{
+ cairo_ps_surface_t *surface;
+ int width, height;
+ cairo_color_t transparent;
+
+ surface = malloc (sizeof (cairo_ps_surface_t));
+ if (surface == NULL)
+ return NULL;
+
+ _cairo_surface_init (&surface->base, &cairo_ps_surface_backend);
+
+ surface->file = file;
+
+ surface->width_inches = width_inches;
+ surface->height_inches = height_inches;
+ surface->x_ppi = x_pixels_per_inch;
+ surface->y_ppi = x_pixels_per_inch;
+
+ width = (int) (x_pixels_per_inch * width_inches + 1.0);
+ height = (int) (y_pixels_per_inch * height_inches + 1.0);
+
+ surface->image = (cairo_image_surface_t *)
+ cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
+ if (surface->image == NULL) {
+ free (surface);
+ return NULL;
+ }
+
+ _cairo_color_init (&transparent);
+ _cairo_color_set_rgb (&transparent, 0., 0., 0.);
+ _cairo_color_set_alpha (&transparent, 0.);
+ _cairo_surface_fill_rectangle (&surface->image->base,
+ CAIRO_OPERATOR_SRC,
+ &transparent, 0, 0, width, height);
+
+ return &surface->base;
+}
+
+static cairo_surface_t *
+_cairo_ps_surface_create_similar (void *abstract_src,
+ cairo_format_t format,
+ int width,
+ int height)
+{
+ return NULL;
+}
+
+static void
+_cairo_ps_surface_destroy (void *abstract_surface)
+{
+ cairo_ps_surface_t *surface = abstract_surface;
+
+ cairo_surface_destroy (&surface->image->base);
+
+ free (surface);
+}
+
+/* XXX: We should re-work this interface to return both X/Y ppi values. */
+static double
+_cairo_ps_surface_pixels_per_inch (void *abstract_surface)
+{
+ cairo_ps_surface_t *surface = abstract_surface;
+
+ return surface->y_ppi;
+}
+
+static cairo_image_surface_t *
+_cairo_ps_surface_get_image (void *abstract_surface)
+{
+ cairo_ps_surface_t *surface = abstract_surface;
+
+ cairo_surface_reference (&surface->image->base);
+
+ return surface->image;
+}
+
+static cairo_status_t
+_cairo_ps_surface_set_image (void *abstract_surface,
+ cairo_image_surface_t *image)
+{
+ cairo_ps_surface_t *surface = abstract_surface;
+
+ if (image == surface->image)
+ return CAIRO_STATUS_SUCCESS;
+
+ /* XXX: Need to call _cairo_image_surface_set_image here, but it's
+ not implemented yet. */
+
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+}
+
+static cairo_status_t
+_cairo_ps_surface_set_matrix (void *abstract_surface,
+ cairo_matrix_t *matrix)
+{
+ cairo_ps_surface_t *surface = abstract_surface;
+
+ return _cairo_image_surface_set_matrix (surface->image, matrix);
+}
+
+static cairo_status_t
+_cairo_ps_surface_set_filter (void *abstract_surface,
+ cairo_filter_t filter)
+{
+ cairo_ps_surface_t *surface = abstract_surface;
+
+ return _cairo_image_surface_set_filter (surface->image, filter);
+}
+
+static cairo_status_t
+_cairo_ps_surface_set_repeat (void *abstract_surface,
+ int repeat)
+{
+ cairo_ps_surface_t *surface = abstract_surface;
+
+ return _cairo_image_surface_set_repeat (surface->image, repeat);
+}
+
+static cairo_int_status_t
+_cairo_ps_surface_composite (cairo_operator_t operator,
+ cairo_surface_t *generic_src,
+ cairo_surface_t *generic_mask,
+ void *abstract_dst,
+ int src_x,
+ int src_y,
+ int mask_x,
+ int mask_y,
+ int dst_x,
+ int dst_y,
+ unsigned int width,
+ unsigned int height)
+{
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+}
+
+static cairo_int_status_t
+_cairo_ps_surface_fill_rectangles (void *abstract_surface,
+ cairo_operator_t operator,
+ const cairo_color_t *color,
+ cairo_rectangle_t *rects,
+ int num_rects)
+{
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+}
+
+static cairo_int_status_t
+_cairo_ps_surface_composite_trapezoids (cairo_operator_t operator,
+ cairo_surface_t *generic_src,
+ void *abstract_dst,
+ int x_src,
+ int y_src,
+ cairo_trapezoid_t *traps,
+ int num_traps)
+{
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+}
+
+static cairo_int_status_t
+_cairo_ps_surface_show_page (void *abstract_surface)
+{
+ cairo_status_t status = CAIRO_STATUS_SUCCESS;
+ cairo_ps_surface_t *surface = abstract_surface;
+ int width = surface->image->width;
+ int height = surface->image->height;
+ FILE *file = surface->file;
+
+ int i, x, y;
+ time_t now = time (0);
+
+ cairo_surface_t *white_surface;
+ char *bgr, *compressed;
+ long bgr_size, compressed_size;
+
+ cairo_color_t white;
+
+ bgr_size = 3 * width * height;
+ bgr = malloc (bgr_size);
+ if (bgr == NULL) {
+ status = CAIRO_STATUS_NO_MEMORY;
+ goto BAIL0;
+ }
+
+ compressed_size = (int) (1.0 + 1.1 * bgr_size);
+ compressed = malloc (compressed_size);
+ if (compressed == NULL) {
+ status = CAIRO_STATUS_NO_MEMORY;
+ goto BAIL1;
+ }
+
+ /* PostScript can not represent the alpha channel, so we blend the
+ current image over a white RGB surface to eliminate it. */
+ white_surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24, 1, 1);
+ if (white_surface == NULL) {
+ status = CAIRO_STATUS_NO_MEMORY;
+ goto BAIL2;
+ }
+
+ _cairo_color_init (&white);
+ _cairo_surface_fill_rectangle (white_surface,
+ CAIRO_OPERATOR_SRC,
+ &white,
+ 0, 0, 1, 1);
+ cairo_surface_set_repeat (white_surface, 1);
+ _cairo_surface_composite (CAIRO_OPERATOR_OVER_REVERSE,
+ white_surface,
+ NULL,
+ &surface->image->base,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ width, height);
+
+ i = 0;
+ for (y = 0; y < height; y++) {
+ char *line = surface->image->data + y * surface->image->stride;
+ for (x = 0; x < width; x++) {
+ unsigned char *pixel = (unsigned char *) line + x * 4;
+ bgr[i++] = *(pixel+2);
+ bgr[i++] = *(pixel+1);
+ bgr[i++] = *(pixel);
+ }
+ }
+
+ compress (compressed, &compressed_size, bgr, bgr_size);
+
+ /* Document header */
+ fprintf (file,
+ "%%!PS-Adobe-3.0\n"
+ "%%%%Creator: Cairo (http://cairographics.org)\n");
+ fprintf (file,
+ "%%%%CreationDate: %s",
+ ctime (&now));
+ fprintf (file,
+ "%%%%Copyright: 2003 Carl Worth and Keith Packard\n");
+ fprintf (file,
+ "%%%%BoundingBox: %d %d %d %d\n",
+ 0, 0, (int) (surface->width_inches * 72.0), (int) (surface->height_inches * 72.0));
+ fprintf (file,
+ "%%%%DocumentData: Clean7Bit\n"
+ "%%%%LanguageLevel: 3\n");
+ fprintf (file,
+ "%%%%Pages: %d\n",
+ 1);
+ fprintf (file,
+ "%%%%Orientation: Portrait\n"
+ "%%%%EndComments\n");
+
+ /* Page header */
+ fprintf (file, "%%%%Page: %d\n", 1);
+
+ fprintf (file, "gsave\n");
+
+ /* Image header goop */
+ fprintf (file, "%g %g translate\n", 0.0, surface->width_inches * 72.0);
+ fprintf (file, "%g %g scale\n", 72.0 / surface->x_ppi, 72.0 / surface->y_ppi);
+ fprintf (file, "/DeviceRGB setcolorspace\n");
+ fprintf (file, "<<\n");
+ fprintf (file, " /ImageType 1\n");
+ fprintf (file, " /Width %d\n", width);
+ fprintf (file, " /Height %d\n", height);
+ fprintf (file, " /BitsPerComponent 8\n");
+ fprintf (file, " /Decode [ 0 1 0 1 0 1 ]\n");
+ fprintf (file, " /DataSource currentfile /FlateDecode filter\n");
+ fprintf (file, " /ImageMatrix [ 1 0 0 -1 0 1 ]\n");
+ fprintf (file, ">>\n");
+ fprintf (file, "image\n");
+
+ /* Compressed image data */
+ fwrite (compressed, 1, compressed_size, file);
+
+ fprintf (file, "showpage\n");
+
+ fprintf (file, "grestore\n");
+
+ /* Page footer */
+ fprintf (file, "%%%%EndPage\n");
+
+ /* Document footer */
+ fprintf (file, "%%%%EOF\n");
+
+ cairo_surface_destroy (white_surface);
+ BAIL2:
+ free (compressed);
+ BAIL1:
+ free (bgr);
+ BAIL0:
+ return status;
+}
+
+static const cairo_surface_backend_t cairo_ps_surface_backend = {
+ _cairo_ps_surface_create_similar,
+ _cairo_ps_surface_destroy,
+ _cairo_ps_surface_pixels_per_inch,
+ _cairo_ps_surface_get_image,
+ _cairo_ps_surface_set_image,
+ _cairo_ps_surface_set_matrix,
+ _cairo_ps_surface_set_filter,
+ _cairo_ps_surface_set_repeat,
+ _cairo_ps_surface_composite,
+ _cairo_ps_surface_fill_rectangles,
+ _cairo_ps_surface_composite_trapezoids,
+ _cairo_ps_surface_show_page
+};
diff --git a/src/cairo_surface.c b/src/cairo_surface.c
index 41baabec..0e847eae 100644
--- a/src/cairo_surface.c
+++ b/src/cairo_surface.c
@@ -334,3 +334,18 @@ _cairo_surface_composite_trapezoids (cairo_operator_t operator,
return status;
}
+cairo_status_t
+_cairo_surface_show_page (cairo_surface_t *surface)
+{
+ cairo_int_status_t status;
+
+ status = surface->backend->show_page (surface);
+ /* It's fine if some backends just don't support this. */
+ if (status == CAIRO_INT_STATUS_UNSUPPORTED)
+ return CAIRO_STATUS_SUCCESS;
+ if (status)
+ return status;
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
diff --git a/src/cairo_xlib_surface.c b/src/cairo_xlib_surface.c
index 41ab48bd..9d705150 100644
--- a/src/cairo_xlib_surface.c
+++ b/src/cairo_xlib_surface.c
@@ -556,7 +556,11 @@ _cairo_xlib_surface_composite_trapezoids (cairo_operator_t operator,
return CAIRO_STATUS_SUCCESS;
}
-
+static cairo_int_status_t
+_cairo_xlib_surface_show_page (void *abstract_surface)
+{
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+}
static const struct cairo_surface_backend cairo_xlib_surface_backend = {
_cairo_xlib_surface_create_similar,
@@ -570,6 +574,7 @@ static const struct cairo_surface_backend cairo_xlib_surface_backend = {
_cairo_xlib_surface_composite,
_cairo_xlib_surface_fill_rectangles,
_cairo_xlib_surface_composite_trapezoids,
+ _cairo_xlib_surface_show_page
};
cairo_surface_t *
diff --git a/src/cairoint.h b/src/cairoint.h
index b672e2eb..d100a067 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -353,6 +353,9 @@ typedef struct cairo_surface_backend {
int ySrc,
cairo_trapezoid_t *traps,
int num_traps);
+
+ cairo_int_status_t
+ (*show_page) (void *surface);
} cairo_surface_backend_t;
struct cairo_matrix {
@@ -709,6 +712,9 @@ _cairo_gstate_stroke (cairo_gstate_t *gstate);
extern cairo_status_t __internal_linkage
_cairo_gstate_fill (cairo_gstate_t *gstate);
+cairo_status_t
+_cairo_gstate_show_page (cairo_gstate_t *gstate);
+
extern cairo_status_t __internal_linkage
_cairo_gstate_clip (cairo_gstate_t *gstate);
@@ -956,6 +962,9 @@ _cairo_surface_composite_trapezoids (cairo_operator_t operator,
cairo_trapezoid_t *traps,
int ntraps);
+cairo_status_t
+_cairo_surface_show_page (cairo_surface_t *surface);
+
extern double __internal_linkage
_cairo_surface_pixels_per_inch (cairo_surface_t *surface);
@@ -982,8 +991,13 @@ extern cairo_status_t __internal_linkage
_cairo_image_surface_set_matrix (cairo_image_surface_t *surface,
cairo_matrix_t *matrix);
+cairo_status_t
+_cairo_image_surface_set_filter (cairo_image_surface_t *surface,
+ cairo_filter_t filter);
+
extern cairo_status_t __internal_linkage
-_cairo_image_surface_set_repeat (cairo_image_surface_t *surface, int repeat);
+_cairo_image_surface_set_repeat (cairo_image_surface_t *surface,
+ int repeat);
/* cairo_pen.c */
extern cairo_status_t __internal_linkage