summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKristian Høgsberg <krh@redhat.com>2005-03-16 12:08:41 +0000
committerKristian Høgsberg <krh@redhat.com>2005-03-16 12:08:41 +0000
commit6993c086ebaa9a98b1794f2c483013ec51cc41ec (patch)
treefcfc4cff8c0fb6197198587b453e92ebba5fa35e
parent5fecf69e2c41ed1957fdde8b0208e7a4aa031466 (diff)
Add cairo_output_stream.c
Add new errors, CAIRO_STATUS_WRITE_ERROR and CAIRO_STATUS_SURFACE_FINISHED, add cairo_surface_finish() prototype, add cairo_write_func_t. Add strings for new errors, documentation fix. Rename surface destroy functions to finish and change them to not free the surface. Change PDF surface constructors to take a write function in the general case and add stdio convenience constructors. Change destroy function to finish for cairo_pdf_surface. Change implementation to use cairo_output_stream_t functions for output. Use _cairo_surface_show_glyphs instead of calling function pointer directly. Add prototypes for cairo output stream functions, rename destroy to finish in cairo_surface_backend_t and add finished flag to cairo_surface_t. Add cairo_surface_finish() and call it from cairo_surface_destroy(). Check the finished flag in cairo_surface_t in functions that change the surface.
-rw-r--r--ChangeLog38
-rw-r--r--src/Makefile.am1
-rw-r--r--src/cairo-font.c19
-rw-r--r--src/cairo-glitz-surface.c11
-rw-r--r--src/cairo-image-surface.c8
-rw-r--r--src/cairo-pdf-surface.c849
-rw-r--r--src/cairo-pdf.h40
-rw-r--r--src/cairo-ps-surface.c8
-rw-r--r--src/cairo-surface.c116
-rw-r--r--src/cairo-win32-surface.c6
-rw-r--r--src/cairo-xcb-surface.c6
-rw-r--r--src/cairo-xlib-surface.c8
-rw-r--r--src/cairo.c6
-rw-r--r--src/cairo.h22
-rw-r--r--src/cairo_font.c19
-rw-r--r--src/cairo_glitz_surface.c11
-rw-r--r--src/cairo_image_surface.c8
-rw-r--r--src/cairo_pdf_surface.c849
-rw-r--r--src/cairo_png_surface.c8
-rw-r--r--src/cairo_ps_surface.c8
-rw-r--r--src/cairo_surface.c116
-rw-r--r--src/cairo_win32_surface.c6
-rw-r--r--src/cairo_xcb_surface.c6
-rw-r--r--src/cairo_xlib_surface.c8
-rw-r--r--src/cairoint.h49
25 files changed, 1415 insertions, 811 deletions
diff --git a/ChangeLog b/ChangeLog
index 99919cb0..198c7101 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,41 @@
+2005-03-16 Kristian Høgsberg <set EMAIL_ADDRESS environment variable>
+
+ * src/Makefile.am: Add cairo_output_stream.c
+
+ * src/cairo.h: Add new errors, CAIRO_STATUS_WRITE_ERROR and
+ CAIRO_STATUS_SURFACE_FINISHED, add cairo_surface_finish()
+ prototype, add cairo_write_func_t.
+
+ * src/cairo.c: Add strings for new errors, documentation fix.
+
+ * src/cairo_win32_surface.c:
+ * src/cairo_xcb_surface.c:
+ * src/cairo_xlib_surface.c:
+ * src/cairo_glitz_surface.c:
+ * src/cairo_image_surface.c:
+ * src/cairo_png_surface.c:
+ * src/cairo_ps_surface.c: Rename surface destroy functions to
+ finish and change them to not free the surface.
+
+ * src/cairo-pdf.h:
+ * src/cairo_pdf_surface.c: Change PDF surface constructors to take
+ a write function in the general case and add stdio convenience
+ constructors. Change destroy function to finish for
+ cairo_pdf_surface. Change implementation to use
+ cairo_output_stream_t functions for output.
+
+ * src/cairo_font.c: (_cairo_font_show_glyphs): Use
+ _cairo_surface_show_glyphs instead of calling function pointer
+ directly.
+
+ * src/cairoint.h: Add prototypes for cairo output stream
+ functions, rename destroy to finish in cairo_surface_backend_t and
+ add finished flag to cairo_surface_t.
+
+ * src/cairo_surface.c: Add cairo_surface_finish() and call it from
+ cairo_surface_destroy(). Check the finished flag in
+ cairo_surface_t in functions that change the surface.
+
2005-03-15 Owen Taylor <otaylor@redhat.com>
* src/cairo-xlib.h src/cairo_xlib_surface.c: Rework set
diff --git a/src/Makefile.am b/src/Makefile.am
index c60025a0..2bdf2d36 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -103,6 +103,7 @@ libcairo_la_SOURCES = \
cairo_traps.c \
cairo_pattern.c \
cairo_unicode.c \
+ cairo_output_stream.c \
cairo_wideint.c \
cairo-wideint.h \
$(libcairo_atsui_sources)\
diff --git a/src/cairo-font.c b/src/cairo-font.c
index 529c1c7c..f168e6f2 100644
--- a/src/cairo-font.c
+++ b/src/cairo-font.c
@@ -114,16 +114,15 @@ _cairo_font_show_glyphs (cairo_font_t *font,
int num_glyphs)
{
cairo_status_t status;
- if (surface->backend->show_glyphs != NULL) {
- status = surface->backend->show_glyphs (font, operator, pattern,
- surface,
- source_x, source_y,
- dest_x, dest_y,
- width, height,
- glyphs, num_glyphs);
- if (status == CAIRO_STATUS_SUCCESS)
- return status;
- }
+
+ status = _cairo_surface_show_glyphs (font, operator, pattern,
+ surface,
+ source_x, source_y,
+ dest_x, dest_y,
+ width, height,
+ glyphs, num_glyphs);
+ if (status != CAIRO_INT_STATUS_UNSUPPORTED)
+ return status;
/* Surface display routine either does not exist or failed. */
return font->backend->show_glyphs (font, operator, pattern,
diff --git a/src/cairo-glitz-surface.c b/src/cairo-glitz-surface.c
index ee664e1c..acdee9a0 100644
--- a/src/cairo-glitz-surface.c
+++ b/src/cairo-glitz-surface.c
@@ -54,8 +54,8 @@ typedef struct _cairo_glitz_surface {
pixman_region16_t *clip;
} cairo_glitz_surface_t;
-static void
-_cairo_glitz_surface_destroy (void *abstract_surface)
+static cairo_status_t
+_cairo_glitz_surface_finish (void *abstract_surface)
{
cairo_glitz_surface_t *surface = abstract_surface;
@@ -66,7 +66,8 @@ _cairo_glitz_surface_destroy (void *abstract_surface)
}
glitz_surface_destroy (surface->surface);
- free (surface);
+
+ return CAIRO_STATUS_SUCCESS;
}
static glitz_format_name_t
@@ -733,7 +734,7 @@ _cairo_glitz_pattern_release_surface (cairo_glitz_surface_t *dst,
_cairo_pattern_release_surface (&dst->base, &surface->base,
&attr->base);
else
- _cairo_glitz_surface_destroy (surface);
+ cairo_surface_destroy (&surface->base);
}
static cairo_int_status_t
@@ -1277,7 +1278,7 @@ _cairo_glitz_surface_set_clip_region (void *abstract_surface,
static const cairo_surface_backend_t cairo_glitz_surface_backend = {
_cairo_glitz_surface_create_similar,
- _cairo_glitz_surface_destroy,
+ _cairo_glitz_surface_finish,
_cairo_glitz_surface_pixels_per_inch,
_cairo_glitz_surface_acquire_source_image,
_cairo_glitz_surface_release_source_image,
diff --git a/src/cairo-image-surface.c b/src/cairo-image-surface.c
index 9745b315..106fcf0e 100644
--- a/src/cairo-image-surface.c
+++ b/src/cairo-image-surface.c
@@ -234,8 +234,8 @@ _cairo_image_surface_create_similar (void *abstract_src,
return cairo_image_surface_create (format, width, height);
}
-static void
-_cairo_image_abstract_surface_destroy (void *abstract_surface)
+static cairo_status_t
+_cairo_image_abstract_surface_finish (void *abstract_surface)
{
cairo_image_surface_t *surface = abstract_surface;
@@ -247,7 +247,7 @@ _cairo_image_abstract_surface_destroy (void *abstract_surface)
surface->data = NULL;
}
- free (surface);
+ return CAIRO_STATUS_SUCCESS;
}
void
@@ -658,7 +658,7 @@ _cairo_surface_is_image (cairo_surface_t *surface)
static const cairo_surface_backend_t cairo_image_surface_backend = {
_cairo_image_surface_create_similar,
- _cairo_image_abstract_surface_destroy,
+ _cairo_image_abstract_surface_finish,
_cairo_image_surface_pixels_per_inch,
_cairo_image_surface_acquire_source_image,
_cairo_image_surface_release_source_image,
diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index fee91835..5a73e7e8 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -153,8 +153,10 @@ struct cairo_pdf_stream {
};
struct cairo_pdf_document {
- FILE *file;
+ cairo_output_stream_t *output_stream;
unsigned long refcount;
+ cairo_surface_t *owner;
+ cairo_bool_t finished;
double width_inches;
double height_inches;
@@ -190,15 +192,18 @@ struct cairo_pdf_surface {
static cairo_pdf_document_t *
-_cairo_pdf_document_create (FILE *file,
- double width_inches,
- double height_inches,
- double x_pixels_per_inch,
- double y_pixels_per_inch);
+_cairo_pdf_document_create (cairo_output_stream_t *stream,
+ double width_inches,
+ double height_inches,
+ double x_pixels_per_inch,
+ double y_pixels_per_inch);
static void
_cairo_pdf_document_destroy (cairo_pdf_document_t *document);
+static cairo_status_t
+_cairo_pdf_document_finish (cairo_pdf_document_t *document);
+
static void
_cairo_pdf_document_reference (cairo_pdf_document_t *document);
@@ -814,7 +819,7 @@ _cairo_pdf_document_new_object (cairo_pdf_document_t *document)
{
cairo_pdf_object_t object;
- object.offset = ftell (document->file);
+ object.offset = _cairo_output_stream_get_position (document->output_stream);
if (_cairo_array_append (&document->objects, &object, 1) == NULL)
return 0;
@@ -828,7 +833,7 @@ _cairo_pdf_document_update_object (cairo_pdf_document_t *document,
cairo_pdf_object_t *object;
object = _cairo_array_index (&document->objects, id - 1);
- object->offset = ftell (document->file);
+ object->offset = _cairo_output_stream_get_position (document->output_stream);
}
static void
@@ -899,17 +904,17 @@ _cairo_pdf_surface_add_font (cairo_pdf_surface_t *surface, unsigned int id)
_cairo_array_append (&surface->fonts, &resource, 1);
}
-cairo_surface_t *
-cairo_pdf_surface_create (FILE *file,
- double width_inches,
- double height_inches,
- double x_pixels_per_inch,
- double y_pixels_per_inch)
+static cairo_surface_t *
+_cairo_pdf_surface_create_for_stream (cairo_output_stream_t *stream,
+ double width_inches,
+ double height_inches,
+ double x_pixels_per_inch,
+ double y_pixels_per_inch)
{
cairo_pdf_document_t *document;
cairo_surface_t *surface;
- document = _cairo_pdf_document_create (file,
+ document = _cairo_pdf_document_create (stream,
width_inches,
height_inches,
x_pixels_per_inch,
@@ -921,11 +926,54 @@ cairo_pdf_surface_create (FILE *file,
width_inches,
height_inches);
+ document->owner = surface;
_cairo_pdf_document_destroy (document);
return surface;
}
+cairo_surface_t *
+cairo_pdf_surface_create (cairo_write_func_t write,
+ cairo_destroy_func_t destroy_closure,
+ void *closure,
+ double width_inches,
+ double height_inches,
+ double x_pixels_per_inch,
+ double y_pixels_per_inch)
+{
+ cairo_output_stream_t *stream;
+
+ stream = _cairo_output_stream_create (write, destroy_closure, closure);
+ if (stream == NULL)
+ return NULL;
+
+ return _cairo_pdf_surface_create_for_stream (stream,
+ width_inches,
+ height_inches,
+ x_pixels_per_inch,
+ y_pixels_per_inch);
+}
+
+cairo_surface_t *
+cairo_pdf_surface_create_for_file (FILE *fp,
+ double width_inches,
+ double height_inches,
+ double x_pixels_per_inch,
+ double y_pixels_per_inch)
+{
+ cairo_output_stream_t *stream;
+
+ stream = _cairo_output_stream_create_for_file (fp);
+ if (stream == NULL)
+ return NULL;
+
+ return _cairo_pdf_surface_create_for_stream (stream,
+ width_inches,
+ height_inches,
+ x_pixels_per_inch,
+ y_pixels_per_inch);
+}
+
static cairo_surface_t *
_cairo_pdf_surface_create_for_document (cairo_pdf_document_t *document,
double width_inches,
@@ -989,7 +1037,7 @@ static cairo_pdf_stream_t *
_cairo_pdf_document_open_stream (cairo_pdf_document_t *document,
const char *extra_entries)
{
- FILE *file = document->file;
+ cairo_output_stream_t *output_stream = document->output_stream;
cairo_pdf_stream_t *stream;
stream = malloc (sizeof (cairo_pdf_stream_t));
@@ -1000,17 +1048,17 @@ _cairo_pdf_document_open_stream (cairo_pdf_document_t *document,
stream->id = _cairo_pdf_document_new_object (document);
stream->length_id = _cairo_pdf_document_new_object (document);
- fprintf (file,
- "%d 0 obj\r\n"
- "<< /Length %d 0 R\r\n"
- "%s"
- ">>\r\n"
- "stream\r\n",
- stream->id,
- stream->length_id,
- extra_entries);
+ _cairo_output_stream_printf (output_stream,
+ "%d 0 obj\r\n"
+ "<< /Length %d 0 R\r\n"
+ "%s"
+ ">>\r\n"
+ "stream\r\n",
+ stream->id,
+ stream->length_id,
+ extra_entries);
- stream->start_offset = ftell (file);
+ stream->start_offset = _cairo_output_stream_get_position (output_stream);
document->current_stream = stream;
@@ -1020,7 +1068,7 @@ _cairo_pdf_document_open_stream (cairo_pdf_document_t *document,
static void
_cairo_pdf_document_close_stream (cairo_pdf_document_t *document)
{
- FILE *file = document->file;
+ cairo_output_stream_t *output_stream = document->output_stream;
long length;
cairo_pdf_stream_t *stream;
@@ -1028,35 +1076,42 @@ _cairo_pdf_document_close_stream (cairo_pdf_document_t *document)
if (stream == NULL)
return;
- length = ftell(file) - stream->start_offset;
- fprintf (file,
- "\r\n"
- "endstream\r\n"
- "endobj\r\n");
+ length = _cairo_output_stream_get_position (output_stream) -
+ stream->start_offset;
+ _cairo_output_stream_printf (output_stream,
+ "\r\n"
+ "endstream\r\n"
+ "endobj\r\n");
_cairo_pdf_document_update_object (document, stream->length_id);
- fprintf (file,
- "%d 0 obj\r\n"
- " %ld\r\n"
- "endobj\r\n",
- stream->length_id,
- length);
+ _cairo_output_stream_printf (output_stream,
+ "%d 0 obj\r\n"
+ " %ld\r\n"
+ "endobj\r\n",
+ stream->length_id,
+ length);
document->current_stream = NULL;
}
-static void
-_cairo_pdf_surface_destroy (void *abstract_surface)
+static cairo_status_t
+_cairo_pdf_surface_finish (void *abstract_surface)
{
+ cairo_status_t status;
cairo_pdf_surface_t *surface = abstract_surface;
cairo_pdf_document_t *document = surface->document;
if (surface->current_stream == document->current_stream)
_cairo_pdf_document_close_stream (document);
+ if (document->owner == &surface->base)
+ status = _cairo_pdf_document_finish (document);
+ else
+ status = CAIRO_STATUS_SUCCESS;
+
_cairo_pdf_document_destroy (document);
- free (surface);
+ return status;
}
/* XXX: We should re-work this interface to return both X/Y ppi values. */
@@ -1073,7 +1128,7 @@ _cairo_pdf_surface_ensure_stream (cairo_pdf_surface_t *surface)
{
cairo_pdf_document_t *document = surface->document;
cairo_pdf_stream_t *stream;
- FILE *file = document->file;
+ cairo_output_stream_t *output = document->output_stream;
char extra[200];
if (document->current_stream == NULL ||
@@ -1091,8 +1146,9 @@ _cairo_pdf_surface_ensure_stream (cairo_pdf_surface_t *surface)
/* If this is the first stream we open for this surface,
* output the cairo to PDF transformation matrix. */
if (_cairo_array_num_elements (&surface->streams) == 1)
- fprintf (file, "1 0 0 -1 0 %f cm\r\n",
- document->height_inches * document->y_ppi);
+ _cairo_output_stream_printf (output,
+ "1 0 0 -1 0 %f cm\r\n",
+ document->height_inches * document->y_ppi);
}
}
@@ -1159,7 +1215,7 @@ static unsigned int
emit_image_data (cairo_pdf_document_t *document,
cairo_image_surface_t *image)
{
- FILE *file = document->file;
+ cairo_output_stream_t *output = document->output_stream;
cairo_pdf_stream_t *stream;
char entries[200];
char *rgb, *compressed;
@@ -1202,7 +1258,7 @@ emit_image_data (cairo_pdf_document_t *document,
image->width, image->height);
stream = _cairo_pdf_document_open_stream (document, entries);
- fwrite (compressed, 1, compressed_size, file);
+ _cairo_output_stream_write (output, compressed, compressed_size);
_cairo_pdf_document_close_stream (document);
free (rgb);
@@ -1216,7 +1272,7 @@ _cairo_pdf_surface_composite_image (cairo_pdf_surface_t *dst,
cairo_surface_pattern_t *pattern)
{
cairo_pdf_document_t *document = dst->document;
- FILE *file = document->file;
+ cairo_output_stream_t *output = document->output_stream;
unsigned id;
cairo_matrix_t i2u;
cairo_status_t status;
@@ -1244,12 +1300,12 @@ _cairo_pdf_surface_composite_image (cairo_pdf_surface_t *dst,
cairo_matrix_translate (&i2u, 0, image->height);
cairo_matrix_scale (&i2u, image->width, -image->height);
- fprintf (file,
- "q %f %f %f %f %f %f cm /res%d Do Q\r\n",
- i2u.m[0][0], i2u.m[0][1],
- i2u.m[1][0], i2u.m[1][1],
- i2u.m[2][0], i2u.m[2][1],
- id);
+ _cairo_output_stream_printf (output,
+ "q %f %f %f %f %f %f cm /res%d Do Q\r\n",
+ i2u.m[0][0], i2u.m[0][1],
+ i2u.m[1][0], i2u.m[1][1],
+ i2u.m[2][0], i2u.m[2][1],
+ id);
bail:
_cairo_surface_release_source_image (src, image, image_extra);
@@ -1272,7 +1328,7 @@ _cairo_pdf_surface_composite_pdf (cairo_pdf_surface_t *dst,
cairo_surface_pattern_t *pattern)
{
cairo_pdf_document_t *document = dst->document;
- FILE *file = document->file;
+ cairo_output_stream_t *output = document->output_stream;
cairo_matrix_t i2u;
cairo_pdf_stream_t *stream;
int num_streams, i;
@@ -1288,24 +1344,24 @@ _cairo_pdf_surface_composite_pdf (cairo_pdf_surface_t *dst,
1.0 / (src->width_inches * document->x_ppi),
1.0 / (src->height_inches * document->y_ppi));
- fprintf (file,
- "q %f %f %f %f %f %f cm",
- i2u.m[0][0], i2u.m[0][1],
- i2u.m[1][0], i2u.m[1][1],
- i2u.m[2][0], i2u.m[2][1]);
+ _cairo_output_stream_printf (output,
+ "q %f %f %f %f %f %f cm",
+ i2u.m[0][0], i2u.m[0][1],
+ i2u.m[1][0], i2u.m[1][1],
+ i2u.m[2][0], i2u.m[2][1]);
num_streams = _cairo_array_num_elements (&src->streams);
for (i = 0; i < num_streams; i++) {
_cairo_array_copy_element (&src->streams, i, &stream);
- fprintf (file,
- " /res%d Do",
- stream->id);
+ _cairo_output_stream_printf (output,
+ " /res%d Do",
+ stream->id);
_cairo_pdf_surface_add_xobject (dst, stream->id);
}
- fprintf (file, " Q\r\n");
+ _cairo_output_stream_printf (output, " Q\r\n");
return CAIRO_STATUS_SUCCESS;
}
@@ -1348,20 +1404,20 @@ _cairo_pdf_surface_fill_rectangles (void *abstract_surface,
{
cairo_pdf_surface_t *surface = abstract_surface;
cairo_pdf_document_t *document = surface->document;
- FILE *file = document->file;
+ cairo_output_stream_t *output = document->output_stream;
int i;
_cairo_pdf_surface_ensure_stream (surface);
- fprintf (file,
- "%f %f %f rg\r\n",
- color->red, color->green, color->blue);
+ _cairo_output_stream_printf (output,
+ "%f %f %f rg\r\n",
+ color->red, color->green, color->blue);
for (i = 0; i < num_rects; i++) {
- fprintf (file,
- "%d %d %d %d re f\r\n",
- rects[i].x, rects[i].y,
- rects[i].width, rects[i].height);
+ _cairo_output_stream_printf (output,
+ "%d %d %d %d re f\r\n",
+ rects[i].x, rects[i].y,
+ rects[i].width, rects[i].height);
}
return CAIRO_STATUS_SUCCESS;
@@ -1372,17 +1428,17 @@ emit_solid_pattern (cairo_pdf_surface_t *surface,
cairo_solid_pattern_t *pattern)
{
cairo_pdf_document_t *document = surface->document;
- FILE *file = document->file;
+ cairo_output_stream_t *output = document->output_stream;
unsigned int alpha;
alpha = _cairo_pdf_surface_add_alpha (surface, pattern->base.alpha);
_cairo_pdf_surface_ensure_stream (surface);
- fprintf (file,
- "%f %f %f rg /a%d gs\r\n",
- pattern->red,
- pattern->green,
- pattern->blue,
- alpha);
+ _cairo_output_stream_printf (output,
+ "%f %f %f rg /a%d gs\r\n",
+ pattern->red,
+ pattern->green,
+ pattern->blue,
+ alpha);
}
static void
@@ -1390,7 +1446,7 @@ emit_surface_pattern (cairo_pdf_surface_t *dst,
cairo_surface_pattern_t *pattern)
{
cairo_pdf_document_t *document = dst->document;
- FILE *file = document->file;
+ cairo_output_stream_t *output = document->output_stream;
cairo_pdf_stream_t *stream;
cairo_image_surface_t *image;
void *image_extra;
@@ -1441,9 +1497,9 @@ emit_surface_pattern (cairo_pdf_surface_t *dst,
_cairo_pdf_surface_ensure_stream (dst);
alpha = _cairo_pdf_surface_add_alpha (dst, 1.0);
- fprintf (file,
- "/Pattern cs /res%d scn /a%d gs\r\n",
- stream->id, alpha);
+ _cairo_output_stream_printf (output,
+ "/Pattern cs /res%d scn /a%d gs\r\n",
+ stream->id, alpha);
_cairo_surface_release_source_image (pattern->surface, image, image_extra);
}
@@ -1452,33 +1508,37 @@ static unsigned int
emit_pattern_stops (cairo_pdf_surface_t *surface, cairo_gradient_pattern_t *pattern)
{
cairo_pdf_document_t *document = surface->document;
- FILE *file = document->file;
+ cairo_output_stream_t *output = document->output_stream;
unsigned int function_id;
+ char stops[2][3];
function_id = _cairo_pdf_document_new_object (document);
- fprintf (file,
- "%d 0 obj\r\n"
- "<< /FunctionType 0\r\n"
- " /Domain [ 0.0 1.0 ]\r\n"
- " /Size [ 2 ]\r\n"
- " /BitsPerSample 8\r\n"
- " /Range [ 0.0 1.0 0.0 1.0 0.0 1.0 ]\r\n"
- " /Length 6\r\n"
- ">>\r\n"
- "stream\r\n",
- function_id);
-
- fputc (pattern->stops[0].color.red * 0xff, file);
- fputc (pattern->stops[0].color.green * 0xff, file);
- fputc (pattern->stops[0].color.blue * 0xff, file);
- fputc (pattern->stops[1].color.red * 0xff, file);
- fputc (pattern->stops[1].color.green * 0xff, file);
- fputc (pattern->stops[1].color.blue * 0xff, file);
-
- fprintf (file,
- "\r\n"
- "endstream\r\n"
- "endobj\r\n");
+
+ _cairo_output_stream_printf (output,
+ "%d 0 obj\r\n"
+ "<< /FunctionType 0\r\n"
+ " /Domain [ 0.0 1.0 ]\r\n"
+ " /Size [ 2 ]\r\n"
+ " /BitsPerSample 8\r\n"
+ " /Range [ 0.0 1.0 0.0 1.0 0.0 1.0 ]\r\n"
+ " /Length 6\r\n"
+ ">>\r\n"
+ "stream\r\n",
+ function_id);
+
+ stops[0][0] = pattern->stops[0].color.red * 0xff + 0.5;
+ stops[0][1] = pattern->stops[0].color.green * 0xff + 0.5;
+ stops[0][2] = pattern->stops[0].color.blue * 0xff + 0.5;
+ stops[1][0] = pattern->stops[1].color.red * 0xff + 0.5;
+ stops[1][1] = pattern->stops[1].color.green * 0xff + 0.5;
+ stops[1][2] = pattern->stops[1].color.blue * 0xff + 0.5;
+
+ _cairo_output_stream_write (output, stops, sizeof (stops));
+
+ _cairo_output_stream_printf (output,
+ "\r\n"
+ "endstream\r\n"
+ "endobj\r\n");
return function_id;
}
@@ -1487,7 +1547,7 @@ static void
emit_linear_pattern (cairo_pdf_surface_t *surface, cairo_linear_pattern_t *pattern)
{
cairo_pdf_document_t *document = surface->document;
- FILE *file = document->file;
+ cairo_output_stream_t *output = document->output_stream;
unsigned int function_id, pattern_id, alpha;
double x0, y0, x1, y1;
cairo_matrix_t p2u;
@@ -1507,24 +1567,24 @@ emit_linear_pattern (cairo_pdf_surface_t *surface, cairo_linear_pattern_t *patte
cairo_matrix_transform_point (&p2u, &x1, &y1);
pattern_id = _cairo_pdf_document_new_object (document);
- fprintf (file,
- "%d 0 obj\r\n"
- "<< /Type /Pattern\r\n"
- " /PatternType 2\r\n"
- " /Matrix [ 1 0 0 -1 0 %f ]\r\n"
- " /Shading\r\n"
- " << /ShadingType 2\r\n"
- " /ColorSpace /DeviceRGB\r\n"
- " /Coords [ %f %f %f %f ]\r\n"
- " /Function %d 0 R\r\n"
- " /Extend [ true true ]\r\n"
- " >>\r\n"
- ">>\r\n"
- "endobj\r\n",
- pattern_id,
- document->height_inches * document->y_ppi,
- x0, y0, x1, y1,
- function_id);
+ _cairo_output_stream_printf (output,
+ "%d 0 obj\r\n"
+ "<< /Type /Pattern\r\n"
+ " /PatternType 2\r\n"
+ " /Matrix [ 1 0 0 -1 0 %f ]\r\n"
+ " /Shading\r\n"
+ " << /ShadingType 2\r\n"
+ " /ColorSpace /DeviceRGB\r\n"
+ " /Coords [ %f %f %f %f ]\r\n"
+ " /Function %d 0 R\r\n"
+ " /Extend [ true true ]\r\n"
+ " >>\r\n"
+ ">>\r\n"
+ "endobj\r\n",
+ pattern_id,
+ document->height_inches * document->y_ppi,
+ x0, y0, x1, y1,
+ function_id);
_cairo_pdf_surface_add_pattern (surface, pattern_id);
@@ -1532,16 +1592,16 @@ emit_linear_pattern (cairo_pdf_surface_t *surface, cairo_linear_pattern_t *patte
alpha = _cairo_pdf_surface_add_alpha (surface, 1.0);
/* Use pattern */
- fprintf (file,
- "/Pattern cs /res%d scn /a%d gs\r\n",
- pattern_id, alpha);
+ _cairo_output_stream_printf (output,
+ "/Pattern cs /res%d scn /a%d gs\r\n",
+ pattern_id, alpha);
}
static void
emit_radial_pattern (cairo_pdf_surface_t *surface, cairo_radial_pattern_t *pattern)
{
cairo_pdf_document_t *document = surface->document;
- FILE *file = document->file;
+ cairo_output_stream_t *output = document->output_stream;
unsigned int function_id, pattern_id, alpha;
double x0, y0, x1, y1, r0, r1;
cairo_matrix_t p2u;
@@ -1574,24 +1634,24 @@ emit_radial_pattern (cairo_pdf_surface_t *surface, cairo_radial_pattern_t *patte
* behavoir, not yet sure how to implement the cairo mirror and
* repeat behaviour. */
pattern_id = _cairo_pdf_document_new_object (document);
- fprintf (file,
- "%d 0 obj\r\n"
- "<< /Type /Pattern\r\n"
- " /PatternType 2\r\n"
- " /Matrix [ 1 0 0 -1 0 %f ]\r\n"
- " /Shading\r\n"
- " << /ShadingType 3\r\n"
- " /ColorSpace /DeviceRGB\r\n"
- " /Coords [ %f %f %f %f %f %f ]\r\n"
- " /Function %d 0 R\r\n"
- " /Extend [ true true ]\r\n"
- " >>\r\n"
- ">>\r\n"
- "endobj\r\n",
- pattern_id,
- document->height_inches * document->y_ppi,
- x0, y0, r0, x1, y1, r1,
- function_id);
+ _cairo_output_stream_printf (output,
+ "%d 0 obj\r\n"
+ "<< /Type /Pattern\r\n"
+ " /PatternType 2\r\n"
+ " /Matrix [ 1 0 0 -1 0 %f ]\r\n"
+ " /Shading\r\n"
+ " << /ShadingType 3\r\n"
+ " /ColorSpace /DeviceRGB\r\n"
+ " /Coords [ %f %f %f %f %f %f ]\r\n"
+ " /Function %d 0 R\r\n"
+ " /Extend [ true true ]\r\n"
+ " >>\r\n"
+ ">>\r\n"
+ "endobj\r\n",
+ pattern_id,
+ document->height_inches * document->y_ppi,
+ x0, y0, r0, x1, y1, r1,
+ function_id);
_cairo_pdf_surface_add_pattern (surface, pattern_id);
@@ -1599,9 +1659,9 @@ emit_radial_pattern (cairo_pdf_surface_t *surface, cairo_radial_pattern_t *patte
alpha = _cairo_pdf_surface_add_alpha (surface, 1.0);
/* Use pattern */
- fprintf (file,
- "/Pattern cs /res%d scn /a%d gs\r\n",
- pattern_id, alpha);
+ _cairo_output_stream_printf (output,
+ "/Pattern cs /res%d scn /a%d gs\r\n",
+ pattern_id, alpha);
}
static void
@@ -1650,7 +1710,7 @@ _cairo_pdf_surface_composite_trapezoids (cairo_operator_t operator,
{
cairo_pdf_surface_t *surface = abstract_dst;
cairo_pdf_document_t *document = surface->document;
- FILE *file = document->file;
+ cairo_output_stream_t *output = document->output_stream;
int i;
emit_pattern (surface, pattern);
@@ -1668,16 +1728,16 @@ _cairo_pdf_surface_composite_trapezoids (cairo_operator_t operator,
right_x1 = intersect (&traps[i].right, traps[i].top);
right_x2 = intersect (&traps[i].right, traps[i].bottom);
- fprintf (file,
- "%f %f m %f %f l %f %f l %f %f l h\r\n",
- left_x1, _cairo_fixed_to_double (traps[i].top),
- left_x2, _cairo_fixed_to_double (traps[i].bottom),
- right_x2, _cairo_fixed_to_double (traps[i].bottom),
- right_x1, _cairo_fixed_to_double (traps[i].top));
+ _cairo_output_stream_printf (output,
+ "%f %f m %f %f l %f %f l %f %f l h\r\n",
+ left_x1, _cairo_fixed_to_double (traps[i].top),
+ left_x2, _cairo_fixed_to_double (traps[i].bottom),
+ right_x2, _cairo_fixed_to_double (traps[i].bottom),
+ right_x1, _cairo_fixed_to_double (traps[i].top));
}
- fprintf (file,
- "f\r\n");
+ _cairo_output_stream_printf (output,
+ "f\r\n");
return CAIRO_STATUS_SUCCESS;
}
@@ -1759,7 +1819,7 @@ _cairo_pdf_surface_show_glyphs (cairo_font_t *font,
{
cairo_pdf_surface_t *surface = abstract_surface;
cairo_pdf_document_t *document = surface->document;
- FILE *file = document->file;
+ cairo_output_stream_t *output = document->output_stream;
cairo_pdf_font_t *pdf_font;
int i, index;
@@ -1769,22 +1829,24 @@ _cairo_pdf_surface_show_glyphs (cairo_font_t *font,
emit_pattern (surface, pattern);
- fprintf (file, "BT /res%u 1 Tf", pdf_font->font_id);
+ _cairo_output_stream_printf (output,
+ "BT /res%u 1 Tf", pdf_font->font_id);
for (i = 0; i < num_glyphs; i++) {
index = cairo_pdf_font_use_glyph (pdf_font, glyphs[i].index);
- fprintf (file,
- " %f %f %f %f %f %f Tm (\\%o) Tj",
- font->scale.matrix[0][0],
- font->scale.matrix[0][1],
- font->scale.matrix[1][0],
- -font->scale.matrix[1][1],
- glyphs[i].x,
- glyphs[i].y,
- index);
+ _cairo_output_stream_printf (output,
+ " %f %f %f %f %f %f Tm (\\%o) Tj",
+ font->scale.matrix[0][0],
+ font->scale.matrix[0][1],
+ font->scale.matrix[1][0],
+ -font->scale.matrix[1][1],
+ glyphs[i].x,
+ glyphs[i].y,
+ index);
}
- fprintf (file, " ET\r\n");
+ _cairo_output_stream_printf (output,
+ " ET\r\n");
_cairo_pdf_surface_add_font (surface, pdf_font->font_id);
@@ -1793,7 +1855,7 @@ _cairo_pdf_surface_show_glyphs (cairo_font_t *font,
static const cairo_surface_backend_t cairo_pdf_surface_backend = {
_cairo_pdf_surface_create_similar,
- _cairo_pdf_surface_destroy,
+ _cairo_pdf_surface_finish,
_cairo_pdf_surface_pixels_per_inch,
_cairo_pdf_surface_acquire_source_image,
_cairo_pdf_surface_release_source_image,
@@ -1810,11 +1872,11 @@ static const cairo_surface_backend_t cairo_pdf_surface_backend = {
};
static cairo_pdf_document_t *
-_cairo_pdf_document_create (FILE *file,
- double width_inches,
- double height_inches,
- double x_pixels_per_inch,
- double y_pixels_per_inch)
+_cairo_pdf_document_create (cairo_output_stream_t *output_stream,
+ double width_inches,
+ double height_inches,
+ double x_pixels_per_inch,
+ double y_pixels_per_inch)
{
cairo_pdf_document_t *document;
@@ -1822,8 +1884,10 @@ _cairo_pdf_document_create (FILE *file,
if (document == NULL)
return NULL;
- document->file = file;
+ document->output_stream = output_stream;
document->refcount = 1;
+ document->owner = NULL;
+ document->finished = FALSE;
document->width_inches = width_inches;
document->height_inches = height_inches;
document->x_ppi = x_pixels_per_inch;
@@ -1840,7 +1904,8 @@ _cairo_pdf_document_create (FILE *file,
_cairo_array_init (&document->fonts, sizeof (cairo_pdf_font_t *));
/* Document header */
- fprintf (file, "%%PDF-1.4\r\n");
+ _cairo_output_stream_printf (output_stream,
+ "%%PDF-1.4\r\n");
return document;
}
@@ -1848,17 +1913,17 @@ _cairo_pdf_document_create (FILE *file,
static unsigned int
_cairo_pdf_document_write_info (cairo_pdf_document_t *document)
{
- FILE *file = document->file;
+ cairo_output_stream_t *output = document->output_stream;
unsigned int id;
id = _cairo_pdf_document_new_object (document);
- fprintf (file,
- "%d 0 obj\r\n"
- "<< /Creator (cairographics.org)\r\n"
- " /Producer (cairographics.org)\r\n"
- ">>\r\n"
- "endobj\r\n",
- id);
+ _cairo_output_stream_printf (output,
+ "%d 0 obj\r\n"
+ "<< /Creator (cairographics.org)\r\n"
+ " /Producer (cairographics.org)\r\n"
+ ">>\r\n"
+ "endobj\r\n",
+ id);
return id;
}
@@ -1866,40 +1931,40 @@ _cairo_pdf_document_write_info (cairo_pdf_document_t *document)
static void
_cairo_pdf_document_write_pages (cairo_pdf_document_t *document)
{
- FILE *file = document->file;
+ cairo_output_stream_t *stream = document->output_stream;
unsigned int page_id;
int num_pages, i;
_cairo_pdf_document_update_object (document, document->pages_id);
- fprintf (file,
- "%d 0 obj\r\n"
- "<< /Type /Pages\r\n"
- " /Kids [ ",
- document->pages_id);
+ _cairo_output_stream_printf (stream,
+ "%d 0 obj\r\n"
+ "<< /Type /Pages\r\n"
+ " /Kids [ ",
+ document->pages_id);
num_pages = _cairo_array_num_elements (&document->pages);
for (i = 0; i < num_pages; i++) {
_cairo_array_copy_element (&document->pages, i, &page_id);
- fprintf (file, "%d 0 R ", page_id);
+ _cairo_output_stream_printf (stream, "%d 0 R ", page_id);
}
- fprintf (file, "]\r\n");
- fprintf (file, " /Count %d\r\n", num_pages);
+ _cairo_output_stream_printf (stream, "]\r\n");
+ _cairo_output_stream_printf (stream, " /Count %d\r\n", num_pages);
/* TODO: Figure out wich other defaults to be inherited by /Page
* objects. */
- fprintf (file,
- " /MediaBox [ 0 0 %f %f ]\r\n"
- ">>\r\n"
- "endobj\r\n",
- document->width_inches * document->x_ppi,
- document->height_inches * document->y_ppi);
+ _cairo_output_stream_printf (stream,
+ " /MediaBox [ 0 0 %f %f ]\r\n"
+ ">>\r\n"
+ "endobj\r\n",
+ document->width_inches * document->x_ppi,
+ document->height_inches * document->y_ppi);
}
static cairo_status_t
_cairo_pdf_document_write_fonts (cairo_pdf_document_t *document)
{
- FILE *file = document->file;
+ cairo_output_stream_t *output = document->output_stream;
cairo_pdf_font_t *font;
int num_fonts, i, j;
const char *data;
@@ -1923,76 +1988,76 @@ _cairo_pdf_document_write_fonts (cairo_pdf_document_t *document)
}
stream_id = _cairo_pdf_document_new_object (document);
- fprintf (file,
- "%d 0 obj\r\n"
- "<< /Filter /FlateDecode\r\n"
- " /Length %lu\r\n"
- " /Length1 %lu\r\n"
- ">>\r\n"
- "stream\r\n",
- stream_id,
- compressed_size,
- data_size);
- fwrite (compressed, 1, compressed_size, file);
- fprintf (file,
- "\r\n"
- "endstream\r\n"
- "endobj\r\n");
+ _cairo_output_stream_printf (output,
+ "%d 0 obj\r\n"
+ "<< /Filter /FlateDecode\r\n"
+ " /Length %lu\r\n"
+ " /Length1 %lu\r\n"
+ ">>\r\n"
+ "stream\r\n",
+ stream_id,
+ compressed_size,
+ data_size);
+ _cairo_output_stream_write (output, compressed, compressed_size);
+ _cairo_output_stream_printf (output,
+ "\r\n"
+ "endstream\r\n"
+ "endobj\r\n");
free (compressed);
descriptor_id = _cairo_pdf_document_new_object (document);
- fprintf (file,
- "%d 0 obj\r\n"
- "<< /Type /FontDescriptor\r\n"
- " /FontName /7%s\r\n"
- " /Flags 4\r\n"
- " /FontBBox [ %ld %ld %ld %ld ]\r\n"
- " /ItalicAngle 0\r\n"
- " /Ascent %ld\r\n"
- " /Descent %ld\r\n"
- " /CapHeight 500\r\n"
- " /StemV 80\r\n"
- " /StemH 80\r\n"
- " /FontFile2 %u 0 R\r\n"
- ">>\r\n"
- "endobj\r\n",
- descriptor_id,
- font->base_font,
- font->x_min,
- font->y_min,
- font->x_max,
- font->y_max,
- font->ascent,
- font->descent,
- stream_id);
+ _cairo_output_stream_printf (output,
+ "%d 0 obj\r\n"
+ "<< /Type /FontDescriptor\r\n"
+ " /FontName /7%s\r\n"
+ " /Flags 4\r\n"
+ " /FontBBox [ %ld %ld %ld %ld ]\r\n"
+ " /ItalicAngle 0\r\n"
+ " /Ascent %ld\r\n"
+ " /Descent %ld\r\n"
+ " /CapHeight 500\r\n"
+ " /StemV 80\r\n"
+ " /StemH 80\r\n"
+ " /FontFile2 %u 0 R\r\n"
+ ">>\r\n"
+ "endobj\r\n",
+ descriptor_id,
+ font->base_font,
+ font->x_min,
+ font->y_min,
+ font->x_max,
+ font->y_max,
+ font->ascent,
+ font->descent,
+ stream_id);
_cairo_pdf_document_update_object (document, font->font_id);
- fprintf (file,
- "%d 0 obj\r\n"
- "<< /Type /Font\r\n"
- " /Subtype /TrueType\r\n"
- " /BaseFont /%s\r\n"
- " /FirstChar 0\r\n"
- " /LastChar %d\r\n"
- " /FontDescriptor %d 0 R\r\n"
- " /Widths ",
- font->font_id,
- font->base_font,
- font->num_glyphs,
- descriptor_id);
-
- fprintf (file,
- "[");
+ _cairo_output_stream_printf (output,
+ "%d 0 obj\r\n"
+ "<< /Type /Font\r\n"
+ " /Subtype /TrueType\r\n"
+ " /BaseFont /%s\r\n"
+ " /FirstChar 0\r\n"
+ " /LastChar %d\r\n"
+ " /FontDescriptor %d 0 R\r\n"
+ " /Widths ",
+ font->font_id,
+ font->base_font,
+ font->num_glyphs,
+ descriptor_id);
+
+ _cairo_output_stream_printf (output,
+ "[");
for (j = 0; j < font->num_glyphs; j++)
- fprintf (file,
- " %d",
- font->widths[j]);
+ _cairo_output_stream_printf (output,
+ " %d",
+ font->widths[j]);
- fprintf (file,
- " ]\r\n"
- ">>\r\n"
- "endobj\r\n");
+ _cairo_output_stream_printf (output,
+ " ]\r\n"
+ ">>\r\n"
+ "endobj\r\n");
fail:
cairo_pdf_ft_font_destroy (font);
@@ -2004,17 +2069,17 @@ _cairo_pdf_document_write_fonts (cairo_pdf_document_t *document)
static unsigned int
_cairo_pdf_document_write_catalog (cairo_pdf_document_t *document)
{
- FILE *file = document->file;
+ cairo_output_stream_t *output = document->output_stream;
unsigned int id;
id = _cairo_pdf_document_new_object (document);
- fprintf (file,
- "%d 0 obj\r\n"
- "<< /Type /Catalog\r\n"
- " /Pages %d 0 R\r\n"
- ">>\r\n"
- "endobj\r\n",
- id, document->pages_id);
+ _cairo_output_stream_printf (output,
+ "%d 0 obj\r\n"
+ "<< /Type /Catalog\r\n"
+ " /Pages %d 0 R\r\n"
+ ">>\r\n"
+ "endobj\r\n",
+ id, document->pages_id);
return id;
}
@@ -2022,23 +2087,25 @@ _cairo_pdf_document_write_catalog (cairo_pdf_document_t *document)
static long
_cairo_pdf_document_write_xref (cairo_pdf_document_t *document)
{
- FILE *file = document->file;
+ cairo_output_stream_t *output = document->output_stream;
cairo_pdf_object_t *object;
int num_objects, i;
long offset;
num_objects = _cairo_array_num_elements (&document->objects);
- offset = ftell(file);
- fprintf (document->file,
- "xref\r\n"
- "%d %d\r\n",
- 0, num_objects + 1);
+ offset = _cairo_output_stream_get_position (output);
+ _cairo_output_stream_printf (output,
+ "xref\r\n"
+ "%d %d\r\n",
+ 0, num_objects + 1);
- fprintf (file, "0000000000 65535 f\r\n");
+ _cairo_output_stream_printf (output,
+ "0000000000 65535 f\r\n");
for (i = 0; i < num_objects; i++) {
object = _cairo_array_index (&document->objects, i);
- fprintf (file, "%010ld 00000 n\r\n", object->offset);
+ _cairo_output_stream_printf (output,
+ "%010ld 00000 n\r\n", object->offset);
}
return offset;
@@ -2053,14 +2120,25 @@ _cairo_pdf_document_reference (cairo_pdf_document_t *document)
static void
_cairo_pdf_document_destroy (cairo_pdf_document_t *document)
{
- FILE *file = document->file;
- long offset;
- unsigned int info_id, catalog_id;
-
document->refcount--;
if (document->refcount > 0)
return;
+ _cairo_pdf_document_finish (document);
+
+ free (document);
+}
+
+static cairo_status_t
+_cairo_pdf_document_finish (cairo_pdf_document_t *document)
+{
+ cairo_output_stream_t *output = document->output_stream;
+ long offset;
+ unsigned int info_id, catalog_id;
+
+ if (document->finished)
+ return CAIRO_STATUS_SUCCESS;
+
_cairo_pdf_document_close_stream (document);
_cairo_pdf_document_write_pages (document);
_cairo_pdf_document_write_fonts (document);
@@ -2068,23 +2146,26 @@ _cairo_pdf_document_destroy (cairo_pdf_document_t *document)
catalog_id = _cairo_pdf_document_write_catalog (document);
offset = _cairo_pdf_document_write_xref (document);
- fprintf (file,
- "trailer\r\n"
- "<< /Size %d\r\n"
- " /Root %d 0 R\r\n"
- " /Info %d 0 R\r\n"
- ">>\r\n",
- document->next_available_id,
- catalog_id,
- info_id);
-
- fprintf (file,
- "startxref\r\n"
- "%ld\r\n"
- "%%%%EOF\r\n",
- offset);
+ _cairo_output_stream_printf (output,
+ "trailer\r\n"
+ "<< /Size %d\r\n"
+ " /Root %d 0 R\r\n"
+ " /Info %d 0 R\r\n"
+ ">>\r\n",
+ document->next_available_id,
+ catalog_id,
+ info_id);
- free (document);
+ _cairo_output_stream_printf (output,
+ "startxref\r\n"
+ "%ld\r\n"
+ "%%%%EOF\r\n",
+ offset);
+
+ _cairo_output_stream_destroy (output);
+ document->finished = TRUE;
+
+ return _cairo_output_stream_get_status (output);
}
static cairo_status_t
@@ -2093,122 +2174,124 @@ _cairo_pdf_document_add_page (cairo_pdf_document_t *document,
{
cairo_pdf_stream_t *stream;
cairo_pdf_resource_t *res;
- FILE *file = document->file;
+ cairo_output_stream_t *output = document->output_stream;
unsigned int page_id;
double alpha;
int num_streams, num_alphas, num_resources, i;
+ assert (!document->finished);
+
_cairo_pdf_document_close_stream (document);
page_id = _cairo_pdf_document_new_object (document);
- fprintf (file,
- "%d 0 obj\r\n"
- "<< /Type /Page\r\n"
- " /Parent %d 0 R\r\n"
- " /Contents [",
- page_id,
- document->pages_id);
+ _cairo_output_stream_printf (output,
+ "%d 0 obj\r\n"
+ "<< /Type /Page\r\n"
+ " /Parent %d 0 R\r\n"
+ " /Contents [",
+ page_id,
+ document->pages_id);
num_streams = _cairo_array_num_elements (&surface->streams);
for (i = 0; i < num_streams; i++) {
_cairo_array_copy_element (&surface->streams, i, &stream);
- fprintf (file,
- " %d 0 R",
- stream->id);
+ _cairo_output_stream_printf (output,
+ " %d 0 R",
+ stream->id);
}
- fprintf (file,
- " ]\r\n"
- " /Resources <<\r\n");
+ _cairo_output_stream_printf (output,
+ " ]\r\n"
+ " /Resources <<\r\n");
num_resources = _cairo_array_num_elements (&surface->fonts);
if (num_resources > 0) {
- fprintf (file,
- " /Font <<");
+ _cairo_output_stream_printf (output,
+ " /Font <<");
for (i = 0; i < num_resources; i++) {
res = _cairo_array_index (&surface->fonts, i);
- fprintf (file,
- " /res%d %d 0 R",
- res->id, res->id);
+ _cairo_output_stream_printf (output,
+ " /res%d %d 0 R",
+ res->id, res->id);
}
- fprintf (file,
- " >>\r\n");
+ _cairo_output_stream_printf (output,
+ " >>\r\n");
}
num_alphas = _cairo_array_num_elements (&surface->alphas);
if (num_alphas > 0) {
- fprintf (file,
- " /ExtGState <<\r\n");
+ _cairo_output_stream_printf (output,
+ " /ExtGState <<\r\n");
for (i = 0; i < num_alphas; i++) {
_cairo_array_copy_element (&surface->alphas, i, &alpha);
- fprintf (file,
- " /a%d << /ca %f >>\r\n",
- i, alpha);
+ _cairo_output_stream_printf (output,
+ " /a%d << /ca %f >>\r\n",
+ i, alpha);
}
- fprintf (file,
- " >>\r\n");
+ _cairo_output_stream_printf (output,
+ " >>\r\n");
}
num_resources = _cairo_array_num_elements (&surface->patterns);
if (num_resources > 0) {
- fprintf (file,
- " /Pattern <<");
+ _cairo_output_stream_printf (output,
+ " /Pattern <<");
for (i = 0; i < num_resources; i++) {
res = _cairo_array_index (&surface->patterns, i);
- fprintf (file,
- " /res%d %d 0 R",
- res->id, res->id);
+ _cairo_output_stream_printf (output,
+ " /res%d %d 0 R",
+ res->id, res->id);
}
- fprintf (file,
- " >>\r\n");
+ _cairo_output_stream_printf (output,
+ " >>\r\n");
}
num_resources = _cairo_array_num_elements (&surface->xobjects);
if (num_resources > 0) {
- fprintf (file,
- " /XObject <<");
+ _cairo_output_stream_printf (output,
+ " /XObject <<");
for (i = 0; i < num_resources; i++) {
res = _cairo_array_index (&surface->xobjects, i);
- fprintf (file,
- " /res%d %d 0 R",
- res->id, res->id);
+ _cairo_output_stream_printf (output,
+ " /res%d %d 0 R",
+ res->id, res->id);
}
- fprintf (file,
- " >>\r\n");
+ _cairo_output_stream_printf (output,
+ " >>\r\n");
}
- fprintf (file,
- " >>\r\n"
- ">>\r\n"
- "endobj\r\n");
+ _cairo_output_stream_printf (output,
+ " >>\r\n"
+ ">>\r\n"
+ "endobj\r\n");
_cairo_array_append (&document->pages, &page_id, 1);
return CAIRO_STATUS_SUCCESS;
}
-void
-cairo_set_target_pdf (cairo_t *cr,
- FILE *file,
- double width_inches,
- double height_inches,
- double x_pixels_per_inch,
- double y_pixels_per_inch)
+static void
+_cairo_set_target_pdf_as_stream (cairo_t *cr,
+ cairo_output_stream_t *stream,
+ double width_inches,
+ double height_inches,
+ double x_pixels_per_inch,
+ double y_pixels_per_inch)
{
cairo_surface_t *surface;
- surface = cairo_pdf_surface_create (file,
- width_inches,
- height_inches,
- x_pixels_per_inch,
- y_pixels_per_inch);
+ surface = _cairo_pdf_surface_create_for_stream (stream,
+ width_inches,
+ height_inches,
+ x_pixels_per_inch,
+ y_pixels_per_inch);
if (surface == NULL) {
cr->status = CAIRO_STATUS_NO_MEMORY;
@@ -2220,3 +2303,51 @@ cairo_set_target_pdf (cairo_t *cr,
/* cairo_set_target_surface takes a reference, so we must destroy ours */
cairo_surface_destroy (surface);
}
+
+void
+cairo_set_target_pdf (cairo_t *cr,
+ cairo_write_func_t write,
+ cairo_destroy_func_t destroy_closure,
+ void *closure,
+ double width_inches,
+ double height_inches,
+ double x_pixels_per_inch,
+ double y_pixels_per_inch)
+{
+ cairo_output_stream_t *stream;
+
+ stream = _cairo_output_stream_create (write, destroy_closure, closure);
+ if (stream == NULL) {
+ cr->status = CAIRO_STATUS_NO_MEMORY;
+ return;
+ }
+
+ return _cairo_set_target_pdf_as_stream (cr, stream,
+ width_inches,
+ height_inches,
+ x_pixels_per_inch,
+ y_pixels_per_inch);
+}
+
+void
+cairo_set_target_pdf_as_file (cairo_t *cr,
+ FILE *fp,
+ double width_inches,
+ double height_inches,
+ double x_pixels_per_inch,
+ double y_pixels_per_inch)
+{
+ cairo_output_stream_t *stream;
+
+ stream = _cairo_output_stream_create_for_file (fp);
+ if (stream == NULL) {
+ cr->status = CAIRO_STATUS_NO_MEMORY;
+ return;
+ }
+
+ return _cairo_set_target_pdf_as_stream (cr, stream,
+ width_inches,
+ height_inches,
+ x_pixels_per_inch,
+ y_pixels_per_inch);
+}
diff --git a/src/cairo-pdf.h b/src/cairo-pdf.h
index 701a7b4a..99d53a8c 100644
--- a/src/cairo-pdf.h
+++ b/src/cairo-pdf.h
@@ -46,20 +46,38 @@
CAIRO_BEGIN_DECLS
void
-cairo_set_target_pdf (cairo_t *cr,
- FILE *file,
- double width_inches,
- double height_inches,
- double x_pixels_per_inch,
- double y_pixels_per_inch);
+cairo_set_target_pdf (cairo_t *cr,
+ cairo_write_func_t write_func,
+ cairo_destroy_func_t destroy_closure_func,
+ void *closure,
+ double width_inches,
+ double height_inches,
+ double x_pixels_per_inch,
+ double y_pixels_per_inch);
+void
+cairo_set_target_pdf_as_file (cairo_t *cr,
+ FILE *fp,
+ double width_inches,
+ double height_inches,
+ double x_pixels_per_inch,
+ double y_pixels_per_inch);
+
+cairo_surface_t *
+cairo_pdf_surface_create (cairo_write_func_t write_func,
+ cairo_destroy_func_t destroy_closure_func,
+ void *closure,
+ double width_inches,
+ double height_inches,
+ double x_pixels_per_inch,
+ double y_pixels_per_inch);
cairo_surface_t *
-cairo_pdf_surface_create (FILE *file,
- double width_inches,
- double height_inches,
- double x_pixels_per_inch,
- double y_pixels_per_inch);
+cairo_pdf_surface_create_for_file (FILE *fp,
+ double width_inches,
+ double height_inches,
+ double x_pixels_per_inch,
+ double y_pixels_per_inch);
CAIRO_END_DECLS
diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c
index 4a45fc67..a0a92dc2 100644
--- a/src/cairo-ps-surface.c
+++ b/src/cairo-ps-surface.c
@@ -170,8 +170,8 @@ _cairo_ps_surface_create_similar (void *abstract_src,
return NULL;
}
-static void
-_cairo_ps_surface_destroy (void *abstract_surface)
+static cairo_status_t
+_cairo_ps_surface_finish (void *abstract_surface)
{
cairo_ps_surface_t *surface = abstract_surface;
@@ -180,7 +180,7 @@ _cairo_ps_surface_destroy (void *abstract_surface)
cairo_surface_destroy (&surface->image->base);
- free (surface);
+ return CAIRO_STATUS_SUCCESS;
}
static void
@@ -426,7 +426,7 @@ _cairo_ps_surface_set_clip_region (void *abstract_surface,
static const cairo_surface_backend_t cairo_ps_surface_backend = {
_cairo_ps_surface_create_similar,
- _cairo_ps_surface_destroy,
+ _cairo_ps_surface_finish,
_cairo_ps_surface_pixels_per_inch,
_cairo_ps_surface_acquire_source_image,
_cairo_ps_surface_release_source_image,
diff --git a/src/cairo-surface.c b/src/cairo-surface.c
index 2afedc2c..18b4eb07 100644
--- a/src/cairo-surface.c
+++ b/src/cairo-surface.c
@@ -51,6 +51,8 @@ _cairo_surface_init (cairo_surface_t *surface,
surface->backend = backend;
surface->ref_count = 1;
+ surface->finished = FALSE;
+
_cairo_array_init (&surface->user_data_slots,
sizeof (cairo_user_data_slot_t));
@@ -164,14 +166,49 @@ cairo_surface_destroy (cairo_surface_t *surface)
if (surface->ref_count)
return;
- if (surface->backend->destroy)
- surface->backend->destroy (surface);
+ cairo_surface_finish (surface);
_destroy_user_data (surface);
+
+ free (surface);
}
slim_hidden_def(cairo_surface_destroy);
/**
+ * cairo_surface_finish:
+ * @surface: the #cairo_surface_t to finish
+ *
+ * This function finishes the surface and drops all references to
+ * external resources. For example, for the Xlib backend it means
+ * that cairo will no longer access the drawable, which can be freed.
+ * After calling cairo_surface_finish() the only valid operations on a
+ * surface are getting and setting user data and referencing and
+ * destroying it. Further drawing the the surface will not affect the
+ * surface but set the surface status to
+ * CAIRO_STATUS_SURFACE_FINISHED.
+ *
+ * When the last call to cairo_surface_destroy() decreases the
+ * reference count to zero, cairo will call cairo_surface_finish() if
+ * it hasn't been called already, before freeing the resources
+ * associated with the surface.
+ *
+ * Return value: CAIRO_STATUS_SUCCESS if the surface was finished
+ * successfully, otherwise CAIRO_STATUS_NO_MEMORY or
+ * CAIRO_STATUS_WRITE_ERROR.
+ **/
+cairo_status_t
+cairo_surface_finish (cairo_surface_t *surface)
+{
+ if (surface->finished)
+ return CAIRO_STATUS_SURFACE_FINISHED;
+
+ if (surface->backend->finish)
+ return surface->backend->finish (surface);
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
+/**
* cairo_surface_get_user_data:
* @surface: a #cairo_surface_t
* @key: the address of the #cairo_user_data_key_t the user data was
@@ -281,6 +318,8 @@ _cairo_surface_acquire_source_image (cairo_surface_t *surface,
cairo_image_surface_t **image_out,
void **image_extra)
{
+ assert (!surface->finished);
+
return surface->backend->acquire_source_image (surface, image_out, image_extra);
}
@@ -296,6 +335,8 @@ _cairo_surface_release_source_image (cairo_surface_t *surface,
cairo_image_surface_t *image,
void *image_extra)
{
+ assert (!surface->finished);
+
surface->backend->release_source_image (surface, image, image_extra);
}
@@ -334,6 +375,8 @@ _cairo_surface_acquire_dest_image (cairo_surface_t *surface,
cairo_rectangle_t *image_rect,
void **image_extra)
{
+ assert (!surface->finished);
+
return surface->backend->acquire_dest_image (surface, interest_rect,
image_out, image_rect, image_extra);
}
@@ -357,6 +400,8 @@ _cairo_surface_release_dest_image (cairo_surface_t *surface,
cairo_rectangle_t *image_rect,
void *image_extra)
{
+ assert (!surface->finished);
+
surface->backend->release_dest_image (surface, interest_rect,
image, image_rect, image_extra);
}
@@ -386,6 +431,9 @@ _cairo_surface_clone_similar (cairo_surface_t *surface,
cairo_image_surface_t *image;
void *image_extra;
+ if (surface->finished)
+ return CAIRO_STATUS_SURFACE_FINISHED;
+
status = surface->backend->clone_similar (surface, src, clone_out);
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
return status;
@@ -409,6 +457,9 @@ _cairo_surface_clone_similar (cairo_surface_t *surface,
cairo_status_t
cairo_surface_set_matrix (cairo_surface_t *surface, cairo_matrix_t *matrix)
{
+ if (surface->finished)
+ return CAIRO_STATUS_SURFACE_FINISHED;
+
if (surface == NULL)
return CAIRO_STATUS_NULL_POINTER;
@@ -419,6 +470,9 @@ slim_hidden_def(cairo_surface_set_matrix);
cairo_status_t
cairo_surface_get_matrix (cairo_surface_t *surface, cairo_matrix_t *matrix)
{
+ if (surface->finished)
+ return CAIRO_STATUS_SURFACE_FINISHED;
+
if (surface == NULL)
return CAIRO_STATUS_NULL_POINTER;
@@ -429,6 +483,9 @@ slim_hidden_def(cairo_surface_get_matrix);
cairo_status_t
cairo_surface_set_filter (cairo_surface_t *surface, cairo_filter_t filter)
{
+ if (surface->finished)
+ return CAIRO_STATUS_SURFACE_FINISHED;
+
if (surface == NULL)
return CAIRO_STATUS_NULL_POINTER;
@@ -460,6 +517,9 @@ cairo_surface_clip_restore (cairo_surface_t *surface);
cairo_status_t
cairo_surface_set_repeat (cairo_surface_t *surface, int repeat)
{
+ if (surface->finished)
+ return CAIRO_STATUS_SURFACE_FINISHED;
+
if (surface == NULL)
return CAIRO_STATUS_NULL_POINTER;
@@ -552,6 +612,9 @@ _cairo_surface_composite (cairo_operator_t operator,
{
cairo_int_status_t status;
+ if (dst->finished)
+ return CAIRO_STATUS_SURFACE_FINISHED;
+
status = dst->backend->composite (operator,
src, mask, dst,
src_x, src_y,
@@ -580,6 +643,9 @@ _cairo_surface_fill_rectangle (cairo_surface_t *surface,
{
cairo_rectangle_t rect;
+ if (surface->finished)
+ return CAIRO_STATUS_SURFACE_FINISHED;
+
rect.x = x;
rect.y = y;
rect.width = width;
@@ -668,6 +734,9 @@ _cairo_surface_fill_rectangles (cairo_surface_t *surface,
{
cairo_int_status_t status;
+ if (surface->finished)
+ return CAIRO_STATUS_SURFACE_FINISHED;
+
if (num_rects == 0)
return CAIRO_STATUS_SUCCESS;
@@ -763,6 +832,9 @@ _cairo_surface_composite_trapezoids (cairo_operator_t operator,
{
cairo_int_status_t status;
+ if (dst->finished)
+ return CAIRO_STATUS_SURFACE_FINISHED;
+
status = dst->backend->composite_trapezoids (operator,
pattern, dst,
src_x, src_y,
@@ -784,6 +856,9 @@ _cairo_surface_copy_page (cairo_surface_t *surface)
{
cairo_int_status_t status;
+ if (surface->finished)
+ return CAIRO_STATUS_SURFACE_FINISHED;
+
status = surface->backend->copy_page (surface);
/* It's fine if some backends just don't support this. */
if (status == CAIRO_INT_STATUS_UNSUPPORTED)
@@ -799,6 +874,9 @@ _cairo_surface_show_page (cairo_surface_t *surface)
{
cairo_int_status_t status;
+ if (surface->finished)
+ return CAIRO_STATUS_SURFACE_FINISHED;
+
status = surface->backend->show_page (surface);
/* It's fine if some backends just don't support this. */
if (status == CAIRO_INT_STATUS_UNSUPPORTED)
@@ -812,5 +890,39 @@ _cairo_surface_show_page (cairo_surface_t *surface)
cairo_status_t
_cairo_surface_set_clip_region (cairo_surface_t *surface, pixman_region16_t *region)
{
+ if (surface->finished)
+ return CAIRO_STATUS_SURFACE_FINISHED;
+
return surface->backend->set_clip_region (surface, region);
}
+
+cairo_status_t
+_cairo_surface_show_glyphs (cairo_font_t *font,
+ cairo_operator_t operator,
+ cairo_pattern_t *pattern,
+ cairo_surface_t *dst,
+ int source_x,
+ int source_y,
+ int dest_x,
+ int dest_y,
+ unsigned int width,
+ unsigned int height,
+ const cairo_glyph_t *glyphs,
+ int num_glyphs)
+{
+ cairo_status_t status;
+
+ if (dst->finished)
+ return CAIRO_STATUS_SURFACE_FINISHED;
+
+ if (dst->backend->show_glyphs != NULL)
+ status = dst->backend->show_glyphs (font, operator, pattern, dst,
+ source_x, source_y,
+ dest_x, dest_y,
+ width, height,
+ glyphs, num_glyphs);
+ else
+ status = CAIRO_INT_STATUS_UNSUPPORTED;
+
+ return status;
+}
diff --git a/src/cairo-win32-surface.c b/src/cairo-win32-surface.c
index dcfe6d04..e5a27b0e 100644
--- a/src/cairo-win32-surface.c
+++ b/src/cairo-win32-surface.c
@@ -346,7 +346,7 @@ _cairo_win32_surface_create_dib (cairo_format_t format,
}
static void
-_cairo_win32_surface_destroy (void *abstract_surface)
+_cairo_win32_surface_finish (void *abstract_surface)
{
cairo_win32_surface_t *surface = abstract_surface;
@@ -362,8 +362,6 @@ _cairo_win32_surface_destroy (void *abstract_surface)
DeleteObject (surface->bitmap);
DeleteDC (surface->dc);
}
-
- free (surface);
}
static double
@@ -914,7 +912,7 @@ _cairo_surface_is_win32 (cairo_surface_t *surface)
static const cairo_surface_backend_t cairo_win32_surface_backend = {
_cairo_win32_surface_create_similar,
- _cairo_win32_surface_destroy,
+ _cairo_win32_surface_finish,
_cairo_win32_surface_pixels_per_inch,
_cairo_win32_surface_acquire_source_image,
_cairo_win32_surface_release_source_image,
diff --git a/src/cairo-xcb-surface.c b/src/cairo-xcb-surface.c
index 0694b77a..aef8368f 100644
--- a/src/cairo-xcb-surface.c
+++ b/src/cairo-xcb-surface.c
@@ -278,7 +278,7 @@ _cairo_xcb_surface_create_similar (void *abstract_src,
}
static void
-_cairo_xcb_surface_destroy (void *abstract_surface)
+_cairo_xcb_surface_finish (void *abstract_surface)
{
cairo_xcb_surface_t *surface = abstract_surface;
if (surface->picture.xid)
@@ -291,8 +291,6 @@ _cairo_xcb_surface_destroy (void *abstract_surface)
XCBFreeGC (surface->dpy, surface->gc);
surface->dpy = 0;
-
- free (surface);
}
static double
@@ -901,7 +899,7 @@ _cairo_xcb_surface_set_clip_region (void *abstract_surface,
static const cairo_surface_backend_t cairo_xcb_surface_backend = {
_cairo_xcb_surface_create_similar,
- _cairo_xcb_surface_destroy,
+ _cairo_xcb_surface_finish,
_cairo_xcb_surface_pixels_per_inch,
_cairo_xcb_surface_acquire_source_image,
_cairo_xcb_surface_release_source_image,
diff --git a/src/cairo-xlib-surface.c b/src/cairo-xlib-surface.c
index 8e05a320..3aaa94d6 100644
--- a/src/cairo-xlib-surface.c
+++ b/src/cairo-xlib-surface.c
@@ -185,8 +185,8 @@ _cairo_xlib_surface_create_similar (void *abstract_src,
return &surface->base;
}
-static void
-_cairo_xlib_surface_destroy (void *abstract_surface)
+static cairo_status_t
+_cairo_xlib_surface_finish (void *abstract_surface)
{
cairo_xlib_surface_t *surface = abstract_surface;
if (surface->picture)
@@ -200,7 +200,7 @@ _cairo_xlib_surface_destroy (void *abstract_surface)
surface->dpy = NULL;
- free (surface);
+ return CAIRO_STATUS_SUCCESS;
}
static double
@@ -959,7 +959,7 @@ _cairo_xlib_surface_show_glyphs (cairo_font_t *font,
static const cairo_surface_backend_t cairo_xlib_surface_backend = {
_cairo_xlib_surface_create_similar,
- _cairo_xlib_surface_destroy,
+ _cairo_xlib_surface_finish,
_cairo_xlib_surface_pixels_per_inch,
_cairo_xlib_surface_acquire_source_image,
_cairo_xlib_surface_release_source_image,
diff --git a/src/cairo.c b/src/cairo.c
index 622c88a3..9f9d1b4b 100644
--- a/src/cairo.c
+++ b/src/cairo.c
@@ -127,7 +127,7 @@ cairo_reference (cairo_t *cr)
*
* Decreases the reference count on @cr by one. If the result
* is zero, then @cr and all associated resources are freed.
- * See cairo_destroy().
+ * See cairo_reference().
**/
void
cairo_destroy (cairo_t *cr)
@@ -1821,6 +1821,10 @@ cairo_status_string (cairo_t *cr)
return "input string not valid UTF-8";
case CAIRO_STATUS_INVALID_PATH_DATA:
return "input path data not valid";
+ case CAIRO_STATUS_WRITE_ERROR:
+ return "error while writing to output stream";
+ case CAIRO_STATUS_SURFACE_FINISHED:
+ return "the target surface has been finished";
}
return "<unknown error status>";
diff --git a/src/cairo.h b/src/cairo.h
index bac76bbd..e6c27ca8 100644
--- a/src/cairo.h
+++ b/src/cairo.h
@@ -107,7 +107,9 @@ typedef enum cairo_status {
CAIRO_STATUS_NO_TARGET_SURFACE,
CAIRO_STATUS_NULL_POINTER,
CAIRO_STATUS_INVALID_STRING,
- CAIRO_STATUS_INVALID_PATH_DATA
+ CAIRO_STATUS_INVALID_PATH_DATA,
+ CAIRO_STATUS_WRITE_ERROR,
+ CAIRO_STATUS_SURFACE_FINISHED
} cairo_status_t;
/* Functions for manipulating state objects */
@@ -824,6 +826,9 @@ cairo_surface_reference (cairo_surface_t *surface);
void
cairo_surface_destroy (cairo_surface_t *surface);
+cairo_status_t
+cairo_surface_finish (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 */
@@ -989,6 +994,21 @@ cairo_matrix_transform_distance (cairo_matrix_t *matrix, double *dx, double *dy)
cairo_status_t
cairo_matrix_transform_point (cairo_matrix_t *matrix, double *x, double *y);
+/**
+ * cairo_write_func_t
+ *
+ * #cairo_write_func_t is the type of function which is called when a
+ * backend needs to write data to an output stream. It is passed the
+ * closure which was specified by the user at the time the write
+ * function was registered, the data to write and the length of the
+ * data in bytes. The write function should return
+ * CAIRO_STATUS_SUCCESS if all the data was successfully written,
+ * CAIRO_STATUS_WRITE_ERROR otherwise.
+ */
+typedef cairo_status_t (*cairo_write_func_t) (void *closure,
+ const char *data,
+ unsigned int length);
+
#define CAIRO_API_SHAKEUP_FLAG_DAY 0
#ifndef _CAIROINT_H_
diff --git a/src/cairo_font.c b/src/cairo_font.c
index 529c1c7c..f168e6f2 100644
--- a/src/cairo_font.c
+++ b/src/cairo_font.c
@@ -114,16 +114,15 @@ _cairo_font_show_glyphs (cairo_font_t *font,
int num_glyphs)
{
cairo_status_t status;
- if (surface->backend->show_glyphs != NULL) {
- status = surface->backend->show_glyphs (font, operator, pattern,
- surface,
- source_x, source_y,
- dest_x, dest_y,
- width, height,
- glyphs, num_glyphs);
- if (status == CAIRO_STATUS_SUCCESS)
- return status;
- }
+
+ status = _cairo_surface_show_glyphs (font, operator, pattern,
+ surface,
+ source_x, source_y,
+ dest_x, dest_y,
+ width, height,
+ glyphs, num_glyphs);
+ if (status != CAIRO_INT_STATUS_UNSUPPORTED)
+ return status;
/* Surface display routine either does not exist or failed. */
return font->backend->show_glyphs (font, operator, pattern,
diff --git a/src/cairo_glitz_surface.c b/src/cairo_glitz_surface.c
index ee664e1c..acdee9a0 100644
--- a/src/cairo_glitz_surface.c
+++ b/src/cairo_glitz_surface.c
@@ -54,8 +54,8 @@ typedef struct _cairo_glitz_surface {
pixman_region16_t *clip;
} cairo_glitz_surface_t;
-static void
-_cairo_glitz_surface_destroy (void *abstract_surface)
+static cairo_status_t
+_cairo_glitz_surface_finish (void *abstract_surface)
{
cairo_glitz_surface_t *surface = abstract_surface;
@@ -66,7 +66,8 @@ _cairo_glitz_surface_destroy (void *abstract_surface)
}
glitz_surface_destroy (surface->surface);
- free (surface);
+
+ return CAIRO_STATUS_SUCCESS;
}
static glitz_format_name_t
@@ -733,7 +734,7 @@ _cairo_glitz_pattern_release_surface (cairo_glitz_surface_t *dst,
_cairo_pattern_release_surface (&dst->base, &surface->base,
&attr->base);
else
- _cairo_glitz_surface_destroy (surface);
+ cairo_surface_destroy (&surface->base);
}
static cairo_int_status_t
@@ -1277,7 +1278,7 @@ _cairo_glitz_surface_set_clip_region (void *abstract_surface,
static const cairo_surface_backend_t cairo_glitz_surface_backend = {
_cairo_glitz_surface_create_similar,
- _cairo_glitz_surface_destroy,
+ _cairo_glitz_surface_finish,
_cairo_glitz_surface_pixels_per_inch,
_cairo_glitz_surface_acquire_source_image,
_cairo_glitz_surface_release_source_image,
diff --git a/src/cairo_image_surface.c b/src/cairo_image_surface.c
index 9745b315..106fcf0e 100644
--- a/src/cairo_image_surface.c
+++ b/src/cairo_image_surface.c
@@ -234,8 +234,8 @@ _cairo_image_surface_create_similar (void *abstract_src,
return cairo_image_surface_create (format, width, height);
}
-static void
-_cairo_image_abstract_surface_destroy (void *abstract_surface)
+static cairo_status_t
+_cairo_image_abstract_surface_finish (void *abstract_surface)
{
cairo_image_surface_t *surface = abstract_surface;
@@ -247,7 +247,7 @@ _cairo_image_abstract_surface_destroy (void *abstract_surface)
surface->data = NULL;
}
- free (surface);
+ return CAIRO_STATUS_SUCCESS;
}
void
@@ -658,7 +658,7 @@ _cairo_surface_is_image (cairo_surface_t *surface)
static const cairo_surface_backend_t cairo_image_surface_backend = {
_cairo_image_surface_create_similar,
- _cairo_image_abstract_surface_destroy,
+ _cairo_image_abstract_surface_finish,
_cairo_image_surface_pixels_per_inch,
_cairo_image_surface_acquire_source_image,
_cairo_image_surface_release_source_image,
diff --git a/src/cairo_pdf_surface.c b/src/cairo_pdf_surface.c
index fee91835..5a73e7e8 100644
--- a/src/cairo_pdf_surface.c
+++ b/src/cairo_pdf_surface.c
@@ -153,8 +153,10 @@ struct cairo_pdf_stream {
};
struct cairo_pdf_document {
- FILE *file;
+ cairo_output_stream_t *output_stream;
unsigned long refcount;
+ cairo_surface_t *owner;
+ cairo_bool_t finished;
double width_inches;
double height_inches;
@@ -190,15 +192,18 @@ struct cairo_pdf_surface {
static cairo_pdf_document_t *
-_cairo_pdf_document_create (FILE *file,
- double width_inches,
- double height_inches,
- double x_pixels_per_inch,
- double y_pixels_per_inch);
+_cairo_pdf_document_create (cairo_output_stream_t *stream,
+ double width_inches,
+ double height_inches,
+ double x_pixels_per_inch,
+ double y_pixels_per_inch);
static void
_cairo_pdf_document_destroy (cairo_pdf_document_t *document);
+static cairo_status_t
+_cairo_pdf_document_finish (cairo_pdf_document_t *document);
+
static void
_cairo_pdf_document_reference (cairo_pdf_document_t *document);
@@ -814,7 +819,7 @@ _cairo_pdf_document_new_object (cairo_pdf_document_t *document)
{
cairo_pdf_object_t object;
- object.offset = ftell (document->file);
+ object.offset = _cairo_output_stream_get_position (document->output_stream);
if (_cairo_array_append (&document->objects, &object, 1) == NULL)
return 0;
@@ -828,7 +833,7 @@ _cairo_pdf_document_update_object (cairo_pdf_document_t *document,
cairo_pdf_object_t *object;
object = _cairo_array_index (&document->objects, id - 1);
- object->offset = ftell (document->file);
+ object->offset = _cairo_output_stream_get_position (document->output_stream);
}
static void
@@ -899,17 +904,17 @@ _cairo_pdf_surface_add_font (cairo_pdf_surface_t *surface, unsigned int id)
_cairo_array_append (&surface->fonts, &resource, 1);
}
-cairo_surface_t *
-cairo_pdf_surface_create (FILE *file,
- double width_inches,
- double height_inches,
- double x_pixels_per_inch,
- double y_pixels_per_inch)
+static cairo_surface_t *
+_cairo_pdf_surface_create_for_stream (cairo_output_stream_t *stream,
+ double width_inches,
+ double height_inches,
+ double x_pixels_per_inch,
+ double y_pixels_per_inch)
{
cairo_pdf_document_t *document;
cairo_surface_t *surface;
- document = _cairo_pdf_document_create (file,
+ document = _cairo_pdf_document_create (stream,
width_inches,
height_inches,
x_pixels_per_inch,
@@ -921,11 +926,54 @@ cairo_pdf_surface_create (FILE *file,
width_inches,
height_inches);
+ document->owner = surface;
_cairo_pdf_document_destroy (document);
return surface;
}
+cairo_surface_t *
+cairo_pdf_surface_create (cairo_write_func_t write,
+ cairo_destroy_func_t destroy_closure,
+ void *closure,
+ double width_inches,
+ double height_inches,
+ double x_pixels_per_inch,
+ double y_pixels_per_inch)
+{
+ cairo_output_stream_t *stream;
+
+ stream = _cairo_output_stream_create (write, destroy_closure, closure);
+ if (stream == NULL)
+ return NULL;
+
+ return _cairo_pdf_surface_create_for_stream (stream,
+ width_inches,
+ height_inches,
+ x_pixels_per_inch,
+ y_pixels_per_inch);
+}
+
+cairo_surface_t *
+cairo_pdf_surface_create_for_file (FILE *fp,
+ double width_inches,
+ double height_inches,
+ double x_pixels_per_inch,
+ double y_pixels_per_inch)
+{
+ cairo_output_stream_t *stream;
+
+ stream = _cairo_output_stream_create_for_file (fp);
+ if (stream == NULL)
+ return NULL;
+
+ return _cairo_pdf_surface_create_for_stream (stream,
+ width_inches,
+ height_inches,
+ x_pixels_per_inch,
+ y_pixels_per_inch);
+}
+
static cairo_surface_t *
_cairo_pdf_surface_create_for_document (cairo_pdf_document_t *document,
double width_inches,
@@ -989,7 +1037,7 @@ static cairo_pdf_stream_t *
_cairo_pdf_document_open_stream (cairo_pdf_document_t *document,
const char *extra_entries)
{
- FILE *file = document->file;
+ cairo_output_stream_t *output_stream = document->output_stream;
cairo_pdf_stream_t *stream;
stream = malloc (sizeof (cairo_pdf_stream_t));
@@ -1000,17 +1048,17 @@ _cairo_pdf_document_open_stream (cairo_pdf_document_t *document,
stream->id = _cairo_pdf_document_new_object (document);
stream->length_id = _cairo_pdf_document_new_object (document);
- fprintf (file,
- "%d 0 obj\r\n"
- "<< /Length %d 0 R\r\n"
- "%s"
- ">>\r\n"
- "stream\r\n",
- stream->id,
- stream->length_id,
- extra_entries);
+ _cairo_output_stream_printf (output_stream,
+ "%d 0 obj\r\n"
+ "<< /Length %d 0 R\r\n"
+ "%s"
+ ">>\r\n"
+ "stream\r\n",
+ stream->id,
+ stream->length_id,
+ extra_entries);
- stream->start_offset = ftell (file);
+ stream->start_offset = _cairo_output_stream_get_position (output_stream);
document->current_stream = stream;
@@ -1020,7 +1068,7 @@ _cairo_pdf_document_open_stream (cairo_pdf_document_t *document,
static void
_cairo_pdf_document_close_stream (cairo_pdf_document_t *document)
{
- FILE *file = document->file;
+ cairo_output_stream_t *output_stream = document->output_stream;
long length;
cairo_pdf_stream_t *stream;
@@ -1028,35 +1076,42 @@ _cairo_pdf_document_close_stream (cairo_pdf_document_t *document)
if (stream == NULL)
return;
- length = ftell(file) - stream->start_offset;
- fprintf (file,
- "\r\n"
- "endstream\r\n"
- "endobj\r\n");
+ length = _cairo_output_stream_get_position (output_stream) -
+ stream->start_offset;
+ _cairo_output_stream_printf (output_stream,
+ "\r\n"
+ "endstream\r\n"
+ "endobj\r\n");
_cairo_pdf_document_update_object (document, stream->length_id);
- fprintf (file,
- "%d 0 obj\r\n"
- " %ld\r\n"
- "endobj\r\n",
- stream->length_id,
- length);
+ _cairo_output_stream_printf (output_stream,
+ "%d 0 obj\r\n"
+ " %ld\r\n"
+ "endobj\r\n",
+ stream->length_id,
+ length);
document->current_stream = NULL;
}
-static void
-_cairo_pdf_surface_destroy (void *abstract_surface)
+static cairo_status_t
+_cairo_pdf_surface_finish (void *abstract_surface)
{
+ cairo_status_t status;
cairo_pdf_surface_t *surface = abstract_surface;
cairo_pdf_document_t *document = surface->document;
if (surface->current_stream == document->current_stream)
_cairo_pdf_document_close_stream (document);
+ if (document->owner == &surface->base)
+ status = _cairo_pdf_document_finish (document);
+ else
+ status = CAIRO_STATUS_SUCCESS;
+
_cairo_pdf_document_destroy (document);
- free (surface);
+ return status;
}
/* XXX: We should re-work this interface to return both X/Y ppi values. */
@@ -1073,7 +1128,7 @@ _cairo_pdf_surface_ensure_stream (cairo_pdf_surface_t *surface)
{
cairo_pdf_document_t *document = surface->document;
cairo_pdf_stream_t *stream;
- FILE *file = document->file;
+ cairo_output_stream_t *output = document->output_stream;
char extra[200];
if (document->current_stream == NULL ||
@@ -1091,8 +1146,9 @@ _cairo_pdf_surface_ensure_stream (cairo_pdf_surface_t *surface)
/* If this is the first stream we open for this surface,
* output the cairo to PDF transformation matrix. */
if (_cairo_array_num_elements (&surface->streams) == 1)
- fprintf (file, "1 0 0 -1 0 %f cm\r\n",
- document->height_inches * document->y_ppi);
+ _cairo_output_stream_printf (output,
+ "1 0 0 -1 0 %f cm\r\n",
+ document->height_inches * document->y_ppi);
}
}
@@ -1159,7 +1215,7 @@ static unsigned int
emit_image_data (cairo_pdf_document_t *document,
cairo_image_surface_t *image)
{
- FILE *file = document->file;
+ cairo_output_stream_t *output = document->output_stream;
cairo_pdf_stream_t *stream;
char entries[200];
char *rgb, *compressed;
@@ -1202,7 +1258,7 @@ emit_image_data (cairo_pdf_document_t *document,
image->width, image->height);
stream = _cairo_pdf_document_open_stream (document, entries);
- fwrite (compressed, 1, compressed_size, file);
+ _cairo_output_stream_write (output, compressed, compressed_size);
_cairo_pdf_document_close_stream (document);
free (rgb);
@@ -1216,7 +1272,7 @@ _cairo_pdf_surface_composite_image (cairo_pdf_surface_t *dst,
cairo_surface_pattern_t *pattern)
{
cairo_pdf_document_t *document = dst->document;
- FILE *file = document->file;
+ cairo_output_stream_t *output = document->output_stream;
unsigned id;
cairo_matrix_t i2u;
cairo_status_t status;
@@ -1244,12 +1300,12 @@ _cairo_pdf_surface_composite_image (cairo_pdf_surface_t *dst,
cairo_matrix_translate (&i2u, 0, image->height);
cairo_matrix_scale (&i2u, image->width, -image->height);
- fprintf (file,
- "q %f %f %f %f %f %f cm /res%d Do Q\r\n",
- i2u.m[0][0], i2u.m[0][1],
- i2u.m[1][0], i2u.m[1][1],
- i2u.m[2][0], i2u.m[2][1],
- id);
+ _cairo_output_stream_printf (output,
+ "q %f %f %f %f %f %f cm /res%d Do Q\r\n",
+ i2u.m[0][0], i2u.m[0][1],
+ i2u.m[1][0], i2u.m[1][1],
+ i2u.m[2][0], i2u.m[2][1],
+ id);
bail:
_cairo_surface_release_source_image (src, image, image_extra);
@@ -1272,7 +1328,7 @@ _cairo_pdf_surface_composite_pdf (cairo_pdf_surface_t *dst,
cairo_surface_pattern_t *pattern)
{
cairo_pdf_document_t *document = dst->document;
- FILE *file = document->file;
+ cairo_output_stream_t *output = document->output_stream;
cairo_matrix_t i2u;
cairo_pdf_stream_t *stream;
int num_streams, i;
@@ -1288,24 +1344,24 @@ _cairo_pdf_surface_composite_pdf (cairo_pdf_surface_t *dst,
1.0 / (src->width_inches * document->x_ppi),
1.0 / (src->height_inches * document->y_ppi));
- fprintf (file,
- "q %f %f %f %f %f %f cm",
- i2u.m[0][0], i2u.m[0][1],
- i2u.m[1][0], i2u.m[1][1],
- i2u.m[2][0], i2u.m[2][1]);
+ _cairo_output_stream_printf (output,
+ "q %f %f %f %f %f %f cm",
+ i2u.m[0][0], i2u.m[0][1],
+ i2u.m[1][0], i2u.m[1][1],
+ i2u.m[2][0], i2u.m[2][1]);
num_streams = _cairo_array_num_elements (&src->streams);
for (i = 0; i < num_streams; i++) {
_cairo_array_copy_element (&src->streams, i, &stream);
- fprintf (file,
- " /res%d Do",
- stream->id);
+ _cairo_output_stream_printf (output,
+ " /res%d Do",
+ stream->id);
_cairo_pdf_surface_add_xobject (dst, stream->id);
}
- fprintf (file, " Q\r\n");
+ _cairo_output_stream_printf (output, " Q\r\n");
return CAIRO_STATUS_SUCCESS;
}
@@ -1348,20 +1404,20 @@ _cairo_pdf_surface_fill_rectangles (void *abstract_surface,
{
cairo_pdf_surface_t *surface = abstract_surface;
cairo_pdf_document_t *document = surface->document;
- FILE *file = document->file;
+ cairo_output_stream_t *output = document->output_stream;
int i;
_cairo_pdf_surface_ensure_stream (surface);
- fprintf (file,
- "%f %f %f rg\r\n",
- color->red, color->green, color->blue);
+ _cairo_output_stream_printf (output,
+ "%f %f %f rg\r\n",
+ color->red, color->green, color->blue);
for (i = 0; i < num_rects; i++) {
- fprintf (file,
- "%d %d %d %d re f\r\n",
- rects[i].x, rects[i].y,
- rects[i].width, rects[i].height);
+ _cairo_output_stream_printf (output,
+ "%d %d %d %d re f\r\n",
+ rects[i].x, rects[i].y,
+ rects[i].width, rects[i].height);
}
return CAIRO_STATUS_SUCCESS;
@@ -1372,17 +1428,17 @@ emit_solid_pattern (cairo_pdf_surface_t *surface,
cairo_solid_pattern_t *pattern)
{
cairo_pdf_document_t *document = surface->document;
- FILE *file = document->file;
+ cairo_output_stream_t *output = document->output_stream;
unsigned int alpha;
alpha = _cairo_pdf_surface_add_alpha (surface, pattern->base.alpha);
_cairo_pdf_surface_ensure_stream (surface);
- fprintf (file,
- "%f %f %f rg /a%d gs\r\n",
- pattern->red,
- pattern->green,
- pattern->blue,
- alpha);
+ _cairo_output_stream_printf (output,
+ "%f %f %f rg /a%d gs\r\n",
+ pattern->red,
+ pattern->green,
+ pattern->blue,
+ alpha);
}
static void
@@ -1390,7 +1446,7 @@ emit_surface_pattern (cairo_pdf_surface_t *dst,
cairo_surface_pattern_t *pattern)
{
cairo_pdf_document_t *document = dst->document;
- FILE *file = document->file;
+ cairo_output_stream_t *output = document->output_stream;
cairo_pdf_stream_t *stream;
cairo_image_surface_t *image;
void *image_extra;
@@ -1441,9 +1497,9 @@ emit_surface_pattern (cairo_pdf_surface_t *dst,
_cairo_pdf_surface_ensure_stream (dst);
alpha = _cairo_pdf_surface_add_alpha (dst, 1.0);
- fprintf (file,
- "/Pattern cs /res%d scn /a%d gs\r\n",
- stream->id, alpha);
+ _cairo_output_stream_printf (output,
+ "/Pattern cs /res%d scn /a%d gs\r\n",
+ stream->id, alpha);
_cairo_surface_release_source_image (pattern->surface, image, image_extra);
}
@@ -1452,33 +1508,37 @@ static unsigned int
emit_pattern_stops (cairo_pdf_surface_t *surface, cairo_gradient_pattern_t *pattern)
{
cairo_pdf_document_t *document = surface->document;
- FILE *file = document->file;
+ cairo_output_stream_t *output = document->output_stream;
unsigned int function_id;
+ char stops[2][3];
function_id = _cairo_pdf_document_new_object (document);
- fprintf (file,
- "%d 0 obj\r\n"
- "<< /FunctionType 0\r\n"
- " /Domain [ 0.0 1.0 ]\r\n"
- " /Size [ 2 ]\r\n"
- " /BitsPerSample 8\r\n"
- " /Range [ 0.0 1.0 0.0 1.0 0.0 1.0 ]\r\n"
- " /Length 6\r\n"
- ">>\r\n"
- "stream\r\n",
- function_id);
-
- fputc (pattern->stops[0].color.red * 0xff, file);
- fputc (pattern->stops[0].color.green * 0xff, file);
- fputc (pattern->stops[0].color.blue * 0xff, file);
- fputc (pattern->stops[1].color.red * 0xff, file);
- fputc (pattern->stops[1].color.green * 0xff, file);
- fputc (pattern->stops[1].color.blue * 0xff, file);
-
- fprintf (file,
- "\r\n"
- "endstream\r\n"
- "endobj\r\n");
+
+ _cairo_output_stream_printf (output,
+ "%d 0 obj\r\n"
+ "<< /FunctionType 0\r\n"
+ " /Domain [ 0.0 1.0 ]\r\n"
+ " /Size [ 2 ]\r\n"
+ " /BitsPerSample 8\r\n"
+ " /Range [ 0.0 1.0 0.0 1.0 0.0 1.0 ]\r\n"
+ " /Length 6\r\n"
+ ">>\r\n"
+ "stream\r\n",
+ function_id);
+
+ stops[0][0] = pattern->stops[0].color.red * 0xff + 0.5;
+ stops[0][1] = pattern->stops[0].color.green * 0xff + 0.5;
+ stops[0][2] = pattern->stops[0].color.blue * 0xff + 0.5;
+ stops[1][0] = pattern->stops[1].color.red * 0xff + 0.5;
+ stops[1][1] = pattern->stops[1].color.green * 0xff + 0.5;
+ stops[1][2] = pattern->stops[1].color.blue * 0xff + 0.5;
+
+ _cairo_output_stream_write (output, stops, sizeof (stops));
+
+ _cairo_output_stream_printf (output,
+ "\r\n"
+ "endstream\r\n"
+ "endobj\r\n");
return function_id;
}
@@ -1487,7 +1547,7 @@ static void
emit_linear_pattern (cairo_pdf_surface_t *surface, cairo_linear_pattern_t *pattern)
{
cairo_pdf_document_t *document = surface->document;
- FILE *file = document->file;
+ cairo_output_stream_t *output = document->output_stream;
unsigned int function_id, pattern_id, alpha;
double x0, y0, x1, y1;
cairo_matrix_t p2u;
@@ -1507,24 +1567,24 @@ emit_linear_pattern (cairo_pdf_surface_t *surface, cairo_linear_pattern_t *patte
cairo_matrix_transform_point (&p2u, &x1, &y1);
pattern_id = _cairo_pdf_document_new_object (document);
- fprintf (file,
- "%d 0 obj\r\n"
- "<< /Type /Pattern\r\n"
- " /PatternType 2\r\n"
- " /Matrix [ 1 0 0 -1 0 %f ]\r\n"
- " /Shading\r\n"
- " << /ShadingType 2\r\n"
- " /ColorSpace /DeviceRGB\r\n"
- " /Coords [ %f %f %f %f ]\r\n"
- " /Function %d 0 R\r\n"
- " /Extend [ true true ]\r\n"
- " >>\r\n"
- ">>\r\n"
- "endobj\r\n",
- pattern_id,
- document->height_inches * document->y_ppi,
- x0, y0, x1, y1,
- function_id);
+ _cairo_output_stream_printf (output,
+ "%d 0 obj\r\n"
+ "<< /Type /Pattern\r\n"
+ " /PatternType 2\r\n"
+ " /Matrix [ 1 0 0 -1 0 %f ]\r\n"
+ " /Shading\r\n"
+ " << /ShadingType 2\r\n"
+ " /ColorSpace /DeviceRGB\r\n"
+ " /Coords [ %f %f %f %f ]\r\n"
+ " /Function %d 0 R\r\n"
+ " /Extend [ true true ]\r\n"
+ " >>\r\n"
+ ">>\r\n"
+ "endobj\r\n",
+ pattern_id,
+ document->height_inches * document->y_ppi,
+ x0, y0, x1, y1,
+ function_id);
_cairo_pdf_surface_add_pattern (surface, pattern_id);
@@ -1532,16 +1592,16 @@ emit_linear_pattern (cairo_pdf_surface_t *surface, cairo_linear_pattern_t *patte
alpha = _cairo_pdf_surface_add_alpha (surface, 1.0);
/* Use pattern */
- fprintf (file,
- "/Pattern cs /res%d scn /a%d gs\r\n",
- pattern_id, alpha);
+ _cairo_output_stream_printf (output,
+ "/Pattern cs /res%d scn /a%d gs\r\n",
+ pattern_id, alpha);
}
static void
emit_radial_pattern (cairo_pdf_surface_t *surface, cairo_radial_pattern_t *pattern)
{
cairo_pdf_document_t *document = surface->document;
- FILE *file = document->file;
+ cairo_output_stream_t *output = document->output_stream;
unsigned int function_id, pattern_id, alpha;
double x0, y0, x1, y1, r0, r1;
cairo_matrix_t p2u;
@@ -1574,24 +1634,24 @@ emit_radial_pattern (cairo_pdf_surface_t *surface, cairo_radial_pattern_t *patte
* behavoir, not yet sure how to implement the cairo mirror and
* repeat behaviour. */
pattern_id = _cairo_pdf_document_new_object (document);
- fprintf (file,
- "%d 0 obj\r\n"
- "<< /Type /Pattern\r\n"
- " /PatternType 2\r\n"
- " /Matrix [ 1 0 0 -1 0 %f ]\r\n"
- " /Shading\r\n"
- " << /ShadingType 3\r\n"
- " /ColorSpace /DeviceRGB\r\n"
- " /Coords [ %f %f %f %f %f %f ]\r\n"
- " /Function %d 0 R\r\n"
- " /Extend [ true true ]\r\n"
- " >>\r\n"
- ">>\r\n"
- "endobj\r\n",
- pattern_id,
- document->height_inches * document->y_ppi,
- x0, y0, r0, x1, y1, r1,
- function_id);
+ _cairo_output_stream_printf (output,
+ "%d 0 obj\r\n"
+ "<< /Type /Pattern\r\n"
+ " /PatternType 2\r\n"
+ " /Matrix [ 1 0 0 -1 0 %f ]\r\n"
+ " /Shading\r\n"
+ " << /ShadingType 3\r\n"
+ " /ColorSpace /DeviceRGB\r\n"
+ " /Coords [ %f %f %f %f %f %f ]\r\n"
+ " /Function %d 0 R\r\n"
+ " /Extend [ true true ]\r\n"
+ " >>\r\n"
+ ">>\r\n"
+ "endobj\r\n",
+ pattern_id,
+ document->height_inches * document->y_ppi,
+ x0, y0, r0, x1, y1, r1,
+ function_id);
_cairo_pdf_surface_add_pattern (surface, pattern_id);
@@ -1599,9 +1659,9 @@ emit_radial_pattern (cairo_pdf_surface_t *surface, cairo_radial_pattern_t *patte
alpha = _cairo_pdf_surface_add_alpha (surface, 1.0);
/* Use pattern */
- fprintf (file,
- "/Pattern cs /res%d scn /a%d gs\r\n",
- pattern_id, alpha);
+ _cairo_output_stream_printf (output,
+ "/Pattern cs /res%d scn /a%d gs\r\n",
+ pattern_id, alpha);
}
static void
@@ -1650,7 +1710,7 @@ _cairo_pdf_surface_composite_trapezoids (cairo_operator_t operator,
{
cairo_pdf_surface_t *surface = abstract_dst;
cairo_pdf_document_t *document = surface->document;
- FILE *file = document->file;
+ cairo_output_stream_t *output = document->output_stream;
int i;
emit_pattern (surface, pattern);
@@ -1668,16 +1728,16 @@ _cairo_pdf_surface_composite_trapezoids (cairo_operator_t operator,
right_x1 = intersect (&traps[i].right, traps[i].top);
right_x2 = intersect (&traps[i].right, traps[i].bottom);
- fprintf (file,
- "%f %f m %f %f l %f %f l %f %f l h\r\n",
- left_x1, _cairo_fixed_to_double (traps[i].top),
- left_x2, _cairo_fixed_to_double (traps[i].bottom),
- right_x2, _cairo_fixed_to_double (traps[i].bottom),
- right_x1, _cairo_fixed_to_double (traps[i].top));
+ _cairo_output_stream_printf (output,
+ "%f %f m %f %f l %f %f l %f %f l h\r\n",
+ left_x1, _cairo_fixed_to_double (traps[i].top),
+ left_x2, _cairo_fixed_to_double (traps[i].bottom),
+ right_x2, _cairo_fixed_to_double (traps[i].bottom),
+ right_x1, _cairo_fixed_to_double (traps[i].top));
}
- fprintf (file,
- "f\r\n");
+ _cairo_output_stream_printf (output,
+ "f\r\n");
return CAIRO_STATUS_SUCCESS;
}
@@ -1759,7 +1819,7 @@ _cairo_pdf_surface_show_glyphs (cairo_font_t *font,
{
cairo_pdf_surface_t *surface = abstract_surface;
cairo_pdf_document_t *document = surface->document;
- FILE *file = document->file;
+ cairo_output_stream_t *output = document->output_stream;
cairo_pdf_font_t *pdf_font;
int i, index;
@@ -1769,22 +1829,24 @@ _cairo_pdf_surface_show_glyphs (cairo_font_t *font,
emit_pattern (surface, pattern);
- fprintf (file, "BT /res%u 1 Tf", pdf_font->font_id);
+ _cairo_output_stream_printf (output,
+ "BT /res%u 1 Tf", pdf_font->font_id);
for (i = 0; i < num_glyphs; i++) {
index = cairo_pdf_font_use_glyph (pdf_font, glyphs[i].index);
- fprintf (file,
- " %f %f %f %f %f %f Tm (\\%o) Tj",
- font->scale.matrix[0][0],
- font->scale.matrix[0][1],
- font->scale.matrix[1][0],
- -font->scale.matrix[1][1],
- glyphs[i].x,
- glyphs[i].y,
- index);
+ _cairo_output_stream_printf (output,
+ " %f %f %f %f %f %f Tm (\\%o) Tj",
+ font->scale.matrix[0][0],
+ font->scale.matrix[0][1],
+ font->scale.matrix[1][0],
+ -font->scale.matrix[1][1],
+ glyphs[i].x,
+ glyphs[i].y,
+ index);
}
- fprintf (file, " ET\r\n");
+ _cairo_output_stream_printf (output,
+ " ET\r\n");
_cairo_pdf_surface_add_font (surface, pdf_font->font_id);
@@ -1793,7 +1855,7 @@ _cairo_pdf_surface_show_glyphs (cairo_font_t *font,
static const cairo_surface_backend_t cairo_pdf_surface_backend = {
_cairo_pdf_surface_create_similar,
- _cairo_pdf_surface_destroy,
+ _cairo_pdf_surface_finish,
_cairo_pdf_surface_pixels_per_inch,
_cairo_pdf_surface_acquire_source_image,
_cairo_pdf_surface_release_source_image,
@@ -1810,11 +1872,11 @@ static const cairo_surface_backend_t cairo_pdf_surface_backend = {
};
static cairo_pdf_document_t *
-_cairo_pdf_document_create (FILE *file,
- double width_inches,
- double height_inches,
- double x_pixels_per_inch,
- double y_pixels_per_inch)
+_cairo_pdf_document_create (cairo_output_stream_t *output_stream,
+ double width_inches,
+ double height_inches,
+ double x_pixels_per_inch,
+ double y_pixels_per_inch)
{
cairo_pdf_document_t *document;
@@ -1822,8 +1884,10 @@ _cairo_pdf_document_create (FILE *file,
if (document == NULL)
return NULL;
- document->file = file;
+ document->output_stream = output_stream;
document->refcount = 1;
+ document->owner = NULL;
+ document->finished = FALSE;
document->width_inches = width_inches;
document->height_inches = height_inches;
document->x_ppi = x_pixels_per_inch;
@@ -1840,7 +1904,8 @@ _cairo_pdf_document_create (FILE *file,
_cairo_array_init (&document->fonts, sizeof (cairo_pdf_font_t *));
/* Document header */
- fprintf (file, "%%PDF-1.4\r\n");
+ _cairo_output_stream_printf (output_stream,
+ "%%PDF-1.4\r\n");
return document;
}
@@ -1848,17 +1913,17 @@ _cairo_pdf_document_create (FILE *file,
static unsigned int
_cairo_pdf_document_write_info (cairo_pdf_document_t *document)
{
- FILE *file = document->file;
+ cairo_output_stream_t *output = document->output_stream;
unsigned int id;
id = _cairo_pdf_document_new_object (document);
- fprintf (file,
- "%d 0 obj\r\n"
- "<< /Creator (cairographics.org)\r\n"
- " /Producer (cairographics.org)\r\n"
- ">>\r\n"
- "endobj\r\n",
- id);
+ _cairo_output_stream_printf (output,
+ "%d 0 obj\r\n"
+ "<< /Creator (cairographics.org)\r\n"
+ " /Producer (cairographics.org)\r\n"
+ ">>\r\n"
+ "endobj\r\n",
+ id);
return id;
}
@@ -1866,40 +1931,40 @@ _cairo_pdf_document_write_info (cairo_pdf_document_t *document)
static void
_cairo_pdf_document_write_pages (cairo_pdf_document_t *document)
{
- FILE *file = document->file;
+ cairo_output_stream_t *stream = document->output_stream;
unsigned int page_id;
int num_pages, i;
_cairo_pdf_document_update_object (document, document->pages_id);
- fprintf (file,
- "%d 0 obj\r\n"
- "<< /Type /Pages\r\n"
- " /Kids [ ",
- document->pages_id);
+ _cairo_output_stream_printf (stream,
+ "%d 0 obj\r\n"
+ "<< /Type /Pages\r\n"
+ " /Kids [ ",
+ document->pages_id);
num_pages = _cairo_array_num_elements (&document->pages);
for (i = 0; i < num_pages; i++) {
_cairo_array_copy_element (&document->pages, i, &page_id);
- fprintf (file, "%d 0 R ", page_id);
+ _cairo_output_stream_printf (stream, "%d 0 R ", page_id);
}
- fprintf (file, "]\r\n");
- fprintf (file, " /Count %d\r\n", num_pages);
+ _cairo_output_stream_printf (stream, "]\r\n");
+ _cairo_output_stream_printf (stream, " /Count %d\r\n", num_pages);
/* TODO: Figure out wich other defaults to be inherited by /Page
* objects. */
- fprintf (file,
- " /MediaBox [ 0 0 %f %f ]\r\n"
- ">>\r\n"
- "endobj\r\n",
- document->width_inches * document->x_ppi,
- document->height_inches * document->y_ppi);
+ _cairo_output_stream_printf (stream,
+ " /MediaBox [ 0 0 %f %f ]\r\n"
+ ">>\r\n"
+ "endobj\r\n",
+ document->width_inches * document->x_ppi,
+ document->height_inches * document->y_ppi);
}
static cairo_status_t
_cairo_pdf_document_write_fonts (cairo_pdf_document_t *document)
{
- FILE *file = document->file;
+ cairo_output_stream_t *output = document->output_stream;
cairo_pdf_font_t *font;
int num_fonts, i, j;
const char *data;
@@ -1923,76 +1988,76 @@ _cairo_pdf_document_write_fonts (cairo_pdf_document_t *document)
}
stream_id = _cairo_pdf_document_new_object (document);
- fprintf (file,
- "%d 0 obj\r\n"
- "<< /Filter /FlateDecode\r\n"
- " /Length %lu\r\n"
- " /Length1 %lu\r\n"
- ">>\r\n"
- "stream\r\n",
- stream_id,
- compressed_size,
- data_size);
- fwrite (compressed, 1, compressed_size, file);
- fprintf (file,
- "\r\n"
- "endstream\r\n"
- "endobj\r\n");
+ _cairo_output_stream_printf (output,
+ "%d 0 obj\r\n"
+ "<< /Filter /FlateDecode\r\n"
+ " /Length %lu\r\n"
+ " /Length1 %lu\r\n"
+ ">>\r\n"
+ "stream\r\n",
+ stream_id,
+ compressed_size,
+ data_size);
+ _cairo_output_stream_write (output, compressed, compressed_size);
+ _cairo_output_stream_printf (output,
+ "\r\n"
+ "endstream\r\n"
+ "endobj\r\n");
free (compressed);
descriptor_id = _cairo_pdf_document_new_object (document);
- fprintf (file,
- "%d 0 obj\r\n"
- "<< /Type /FontDescriptor\r\n"
- " /FontName /7%s\r\n"
- " /Flags 4\r\n"
- " /FontBBox [ %ld %ld %ld %ld ]\r\n"
- " /ItalicAngle 0\r\n"
- " /Ascent %ld\r\n"
- " /Descent %ld\r\n"
- " /CapHeight 500\r\n"
- " /StemV 80\r\n"
- " /StemH 80\r\n"
- " /FontFile2 %u 0 R\r\n"
- ">>\r\n"
- "endobj\r\n",
- descriptor_id,
- font->base_font,
- font->x_min,
- font->y_min,
- font->x_max,
- font->y_max,
- font->ascent,
- font->descent,
- stream_id);
+ _cairo_output_stream_printf (output,
+ "%d 0 obj\r\n"
+ "<< /Type /FontDescriptor\r\n"
+ " /FontName /7%s\r\n"
+ " /Flags 4\r\n"
+ " /FontBBox [ %ld %ld %ld %ld ]\r\n"
+ " /ItalicAngle 0\r\n"
+ " /Ascent %ld\r\n"
+ " /Descent %ld\r\n"
+ " /CapHeight 500\r\n"
+ " /StemV 80\r\n"
+ " /StemH 80\r\n"
+ " /FontFile2 %u 0 R\r\n"
+ ">>\r\n"
+ "endobj\r\n",
+ descriptor_id,
+ font->base_font,
+ font->x_min,
+ font->y_min,
+ font->x_max,
+ font->y_max,
+ font->ascent,
+ font->descent,
+ stream_id);
_cairo_pdf_document_update_object (document, font->font_id);
- fprintf (file,
- "%d 0 obj\r\n"
- "<< /Type /Font\r\n"
- " /Subtype /TrueType\r\n"
- " /BaseFont /%s\r\n"
- " /FirstChar 0\r\n"
- " /LastChar %d\r\n"
- " /FontDescriptor %d 0 R\r\n"
- " /Widths ",
- font->font_id,
- font->base_font,
- font->num_glyphs,
- descriptor_id);
-
- fprintf (file,
- "[");
+ _cairo_output_stream_printf (output,
+ "%d 0 obj\r\n"
+ "<< /Type /Font\r\n"
+ " /Subtype /TrueType\r\n"
+ " /BaseFont /%s\r\n"
+ " /FirstChar 0\r\n"
+ " /LastChar %d\r\n"
+ " /FontDescriptor %d 0 R\r\n"
+ " /Widths ",
+ font->font_id,
+ font->base_font,
+ font->num_glyphs,
+ descriptor_id);
+
+ _cairo_output_stream_printf (output,
+ "[");
for (j = 0; j < font->num_glyphs; j++)
- fprintf (file,
- " %d",
- font->widths[j]);
+ _cairo_output_stream_printf (output,
+ " %d",
+ font->widths[j]);
- fprintf (file,
- " ]\r\n"
- ">>\r\n"
- "endobj\r\n");
+ _cairo_output_stream_printf (output,
+ " ]\r\n"
+ ">>\r\n"
+ "endobj\r\n");
fail:
cairo_pdf_ft_font_destroy (font);
@@ -2004,17 +2069,17 @@ _cairo_pdf_document_write_fonts (cairo_pdf_document_t *document)
static unsigned int
_cairo_pdf_document_write_catalog (cairo_pdf_document_t *document)
{
- FILE *file = document->file;
+ cairo_output_stream_t *output = document->output_stream;
unsigned int id;
id = _cairo_pdf_document_new_object (document);
- fprintf (file,
- "%d 0 obj\r\n"
- "<< /Type /Catalog\r\n"
- " /Pages %d 0 R\r\n"
- ">>\r\n"
- "endobj\r\n",
- id, document->pages_id);
+ _cairo_output_stream_printf (output,
+ "%d 0 obj\r\n"
+ "<< /Type /Catalog\r\n"
+ " /Pages %d 0 R\r\n"
+ ">>\r\n"
+ "endobj\r\n",
+ id, document->pages_id);
return id;
}
@@ -2022,23 +2087,25 @@ _cairo_pdf_document_write_catalog (cairo_pdf_document_t *document)
static long
_cairo_pdf_document_write_xref (cairo_pdf_document_t *document)
{
- FILE *file = document->file;
+ cairo_output_stream_t *output = document->output_stream;
cairo_pdf_object_t *object;
int num_objects, i;
long offset;
num_objects = _cairo_array_num_elements (&document->objects);
- offset = ftell(file);
- fprintf (document->file,
- "xref\r\n"
- "%d %d\r\n",
- 0, num_objects + 1);
+ offset = _cairo_output_stream_get_position (output);
+ _cairo_output_stream_printf (output,
+ "xref\r\n"
+ "%d %d\r\n",
+ 0, num_objects + 1);
- fprintf (file, "0000000000 65535 f\r\n");
+ _cairo_output_stream_printf (output,
+ "0000000000 65535 f\r\n");
for (i = 0; i < num_objects; i++) {
object = _cairo_array_index (&document->objects, i);
- fprintf (file, "%010ld 00000 n\r\n", object->offset);
+ _cairo_output_stream_printf (output,
+ "%010ld 00000 n\r\n", object->offset);
}
return offset;
@@ -2053,14 +2120,25 @@ _cairo_pdf_document_reference (cairo_pdf_document_t *document)
static void
_cairo_pdf_document_destroy (cairo_pdf_document_t *document)
{
- FILE *file = document->file;
- long offset;
- unsigned int info_id, catalog_id;
-
document->refcount--;
if (document->refcount > 0)
return;
+ _cairo_pdf_document_finish (document);
+
+ free (document);
+}
+
+static cairo_status_t
+_cairo_pdf_document_finish (cairo_pdf_document_t *document)
+{
+ cairo_output_stream_t *output = document->output_stream;
+ long offset;
+ unsigned int info_id, catalog_id;
+
+ if (document->finished)
+ return CAIRO_STATUS_SUCCESS;
+
_cairo_pdf_document_close_stream (document);
_cairo_pdf_document_write_pages (document);
_cairo_pdf_document_write_fonts (document);
@@ -2068,23 +2146,26 @@ _cairo_pdf_document_destroy (cairo_pdf_document_t *document)
catalog_id = _cairo_pdf_document_write_catalog (document);
offset = _cairo_pdf_document_write_xref (document);
- fprintf (file,
- "trailer\r\n"
- "<< /Size %d\r\n"
- " /Root %d 0 R\r\n"
- " /Info %d 0 R\r\n"
- ">>\r\n",
- document->next_available_id,
- catalog_id,
- info_id);
-
- fprintf (file,
- "startxref\r\n"
- "%ld\r\n"
- "%%%%EOF\r\n",
- offset);
+ _cairo_output_stream_printf (output,
+ "trailer\r\n"
+ "<< /Size %d\r\n"
+ " /Root %d 0 R\r\n"
+ " /Info %d 0 R\r\n"
+ ">>\r\n",
+ document->next_available_id,
+ catalog_id,
+ info_id);
- free (document);
+ _cairo_output_stream_printf (output,
+ "startxref\r\n"
+ "%ld\r\n"
+ "%%%%EOF\r\n",
+ offset);
+
+ _cairo_output_stream_destroy (output);
+ document->finished = TRUE;
+
+ return _cairo_output_stream_get_status (output);
}
static cairo_status_t
@@ -2093,122 +2174,124 @@ _cairo_pdf_document_add_page (cairo_pdf_document_t *document,
{
cairo_pdf_stream_t *stream;
cairo_pdf_resource_t *res;
- FILE *file = document->file;
+ cairo_output_stream_t *output = document->output_stream;
unsigned int page_id;
double alpha;
int num_streams, num_alphas, num_resources, i;
+ assert (!document->finished);
+
_cairo_pdf_document_close_stream (document);
page_id = _cairo_pdf_document_new_object (document);
- fprintf (file,
- "%d 0 obj\r\n"
- "<< /Type /Page\r\n"
- " /Parent %d 0 R\r\n"
- " /Contents [",
- page_id,
- document->pages_id);
+ _cairo_output_stream_printf (output,
+ "%d 0 obj\r\n"
+ "<< /Type /Page\r\n"
+ " /Parent %d 0 R\r\n"
+ " /Contents [",
+ page_id,
+ document->pages_id);
num_streams = _cairo_array_num_elements (&surface->streams);
for (i = 0; i < num_streams; i++) {
_cairo_array_copy_element (&surface->streams, i, &stream);
- fprintf (file,
- " %d 0 R",
- stream->id);
+ _cairo_output_stream_printf (output,
+ " %d 0 R",
+ stream->id);
}
- fprintf (file,
- " ]\r\n"
- " /Resources <<\r\n");
+ _cairo_output_stream_printf (output,
+ " ]\r\n"
+ " /Resources <<\r\n");
num_resources = _cairo_array_num_elements (&surface->fonts);
if (num_resources > 0) {
- fprintf (file,
- " /Font <<");
+ _cairo_output_stream_printf (output,
+ " /Font <<");
for (i = 0; i < num_resources; i++) {
res = _cairo_array_index (&surface->fonts, i);
- fprintf (file,
- " /res%d %d 0 R",
- res->id, res->id);
+ _cairo_output_stream_printf (output,
+ " /res%d %d 0 R",
+ res->id, res->id);
}
- fprintf (file,
- " >>\r\n");
+ _cairo_output_stream_printf (output,
+ " >>\r\n");
}
num_alphas = _cairo_array_num_elements (&surface->alphas);
if (num_alphas > 0) {
- fprintf (file,
- " /ExtGState <<\r\n");
+ _cairo_output_stream_printf (output,
+ " /ExtGState <<\r\n");
for (i = 0; i < num_alphas; i++) {
_cairo_array_copy_element (&surface->alphas, i, &alpha);
- fprintf (file,
- " /a%d << /ca %f >>\r\n",
- i, alpha);
+ _cairo_output_stream_printf (output,
+ " /a%d << /ca %f >>\r\n",
+ i, alpha);
}
- fprintf (file,
- " >>\r\n");
+ _cairo_output_stream_printf (output,
+ " >>\r\n");
}
num_resources = _cairo_array_num_elements (&surface->patterns);
if (num_resources > 0) {
- fprintf (file,
- " /Pattern <<");
+ _cairo_output_stream_printf (output,
+ " /Pattern <<");
for (i = 0; i < num_resources; i++) {
res = _cairo_array_index (&surface->patterns, i);
- fprintf (file,
- " /res%d %d 0 R",
- res->id, res->id);
+ _cairo_output_stream_printf (output,
+ " /res%d %d 0 R",
+ res->id, res->id);
}
- fprintf (file,
- " >>\r\n");
+ _cairo_output_stream_printf (output,
+ " >>\r\n");
}
num_resources = _cairo_array_num_elements (&surface->xobjects);
if (num_resources > 0) {
- fprintf (file,
- " /XObject <<");
+ _cairo_output_stream_printf (output,
+ " /XObject <<");
for (i = 0; i < num_resources; i++) {
res = _cairo_array_index (&surface->xobjects, i);
- fprintf (file,
- " /res%d %d 0 R",
- res->id, res->id);
+ _cairo_output_stream_printf (output,
+ " /res%d %d 0 R",
+ res->id, res->id);
}
- fprintf (file,
- " >>\r\n");
+ _cairo_output_stream_printf (output,
+ " >>\r\n");
}
- fprintf (file,
- " >>\r\n"
- ">>\r\n"
- "endobj\r\n");
+ _cairo_output_stream_printf (output,
+ " >>\r\n"
+ ">>\r\n"
+ "endobj\r\n");
_cairo_array_append (&document->pages, &page_id, 1);
return CAIRO_STATUS_SUCCESS;
}
-void
-cairo_set_target_pdf (cairo_t *cr,
- FILE *file,
- double width_inches,
- double height_inches,
- double x_pixels_per_inch,
- double y_pixels_per_inch)
+static void
+_cairo_set_target_pdf_as_stream (cairo_t *cr,
+ cairo_output_stream_t *stream,
+ double width_inches,
+ double height_inches,
+ double x_pixels_per_inch,
+ double y_pixels_per_inch)
{
cairo_surface_t *surface;
- surface = cairo_pdf_surface_create (file,
- width_inches,
- height_inches,
- x_pixels_per_inch,
- y_pixels_per_inch);
+ surface = _cairo_pdf_surface_create_for_stream (stream,
+ width_inches,
+ height_inches,
+ x_pixels_per_inch,
+ y_pixels_per_inch);
if (surface == NULL) {
cr->status = CAIRO_STATUS_NO_MEMORY;
@@ -2220,3 +2303,51 @@ cairo_set_target_pdf (cairo_t *cr,
/* cairo_set_target_surface takes a reference, so we must destroy ours */
cairo_surface_destroy (surface);
}
+
+void
+cairo_set_target_pdf (cairo_t *cr,
+ cairo_write_func_t write,
+ cairo_destroy_func_t destroy_closure,
+ void *closure,
+ double width_inches,
+ double height_inches,
+ double x_pixels_per_inch,
+ double y_pixels_per_inch)
+{
+ cairo_output_stream_t *stream;
+
+ stream = _cairo_output_stream_create (write, destroy_closure, closure);
+ if (stream == NULL) {
+ cr->status = CAIRO_STATUS_NO_MEMORY;
+ return;
+ }
+
+ return _cairo_set_target_pdf_as_stream (cr, stream,
+ width_inches,
+ height_inches,
+ x_pixels_per_inch,
+ y_pixels_per_inch);
+}
+
+void
+cairo_set_target_pdf_as_file (cairo_t *cr,
+ FILE *fp,
+ double width_inches,
+ double height_inches,
+ double x_pixels_per_inch,
+ double y_pixels_per_inch)
+{
+ cairo_output_stream_t *stream;
+
+ stream = _cairo_output_stream_create_for_file (fp);
+ if (stream == NULL) {
+ cr->status = CAIRO_STATUS_NO_MEMORY;
+ return;
+ }
+
+ return _cairo_set_target_pdf_as_stream (cr, stream,
+ width_inches,
+ height_inches,
+ x_pixels_per_inch,
+ y_pixels_per_inch);
+}
diff --git a/src/cairo_png_surface.c b/src/cairo_png_surface.c
index 1ae745cb..b016cea4 100644
--- a/src/cairo_png_surface.c
+++ b/src/cairo_png_surface.c
@@ -150,8 +150,8 @@ unpremultiply_data (png_structp png, png_row_infop row_info, png_bytep data)
}
}
-static void
-_cairo_png_surface_destroy (void *abstract_surface)
+static cairo_status_t
+_cairo_png_surface_finish (void *abstract_surface)
{
cairo_png_surface_t *surface = abstract_surface;
@@ -160,7 +160,7 @@ _cairo_png_surface_destroy (void *abstract_surface)
cairo_surface_destroy (&surface->image->base);
- free (surface);
+ return CAIRO_STATUS_SUCCESS;
}
static void
@@ -408,7 +408,7 @@ _cairo_png_surface_set_clip_region (void *abstract_surface,
static const cairo_surface_backend_t cairo_png_surface_backend = {
_cairo_png_surface_create_similar,
- _cairo_png_surface_destroy,
+ _cairo_png_surface_finish,
_cairo_png_surface_pixels_per_inch,
_cairo_png_surface_acquire_source_image,
_cairo_png_surface_release_source_image,
diff --git a/src/cairo_ps_surface.c b/src/cairo_ps_surface.c
index 4a45fc67..a0a92dc2 100644
--- a/src/cairo_ps_surface.c
+++ b/src/cairo_ps_surface.c
@@ -170,8 +170,8 @@ _cairo_ps_surface_create_similar (void *abstract_src,
return NULL;
}
-static void
-_cairo_ps_surface_destroy (void *abstract_surface)
+static cairo_status_t
+_cairo_ps_surface_finish (void *abstract_surface)
{
cairo_ps_surface_t *surface = abstract_surface;
@@ -180,7 +180,7 @@ _cairo_ps_surface_destroy (void *abstract_surface)
cairo_surface_destroy (&surface->image->base);
- free (surface);
+ return CAIRO_STATUS_SUCCESS;
}
static void
@@ -426,7 +426,7 @@ _cairo_ps_surface_set_clip_region (void *abstract_surface,
static const cairo_surface_backend_t cairo_ps_surface_backend = {
_cairo_ps_surface_create_similar,
- _cairo_ps_surface_destroy,
+ _cairo_ps_surface_finish,
_cairo_ps_surface_pixels_per_inch,
_cairo_ps_surface_acquire_source_image,
_cairo_ps_surface_release_source_image,
diff --git a/src/cairo_surface.c b/src/cairo_surface.c
index 2afedc2c..18b4eb07 100644
--- a/src/cairo_surface.c
+++ b/src/cairo_surface.c
@@ -51,6 +51,8 @@ _cairo_surface_init (cairo_surface_t *surface,
surface->backend = backend;
surface->ref_count = 1;
+ surface->finished = FALSE;
+
_cairo_array_init (&surface->user_data_slots,
sizeof (cairo_user_data_slot_t));
@@ -164,14 +166,49 @@ cairo_surface_destroy (cairo_surface_t *surface)
if (surface->ref_count)
return;
- if (surface->backend->destroy)
- surface->backend->destroy (surface);
+ cairo_surface_finish (surface);
_destroy_user_data (surface);
+
+ free (surface);
}
slim_hidden_def(cairo_surface_destroy);
/**
+ * cairo_surface_finish:
+ * @surface: the #cairo_surface_t to finish
+ *
+ * This function finishes the surface and drops all references to
+ * external resources. For example, for the Xlib backend it means
+ * that cairo will no longer access the drawable, which can be freed.
+ * After calling cairo_surface_finish() the only valid operations on a
+ * surface are getting and setting user data and referencing and
+ * destroying it. Further drawing the the surface will not affect the
+ * surface but set the surface status to
+ * CAIRO_STATUS_SURFACE_FINISHED.
+ *
+ * When the last call to cairo_surface_destroy() decreases the
+ * reference count to zero, cairo will call cairo_surface_finish() if
+ * it hasn't been called already, before freeing the resources
+ * associated with the surface.
+ *
+ * Return value: CAIRO_STATUS_SUCCESS if the surface was finished
+ * successfully, otherwise CAIRO_STATUS_NO_MEMORY or
+ * CAIRO_STATUS_WRITE_ERROR.
+ **/
+cairo_status_t
+cairo_surface_finish (cairo_surface_t *surface)
+{
+ if (surface->finished)
+ return CAIRO_STATUS_SURFACE_FINISHED;
+
+ if (surface->backend->finish)
+ return surface->backend->finish (surface);
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
+/**
* cairo_surface_get_user_data:
* @surface: a #cairo_surface_t
* @key: the address of the #cairo_user_data_key_t the user data was
@@ -281,6 +318,8 @@ _cairo_surface_acquire_source_image (cairo_surface_t *surface,
cairo_image_surface_t **image_out,
void **image_extra)
{
+ assert (!surface->finished);
+
return surface->backend->acquire_source_image (surface, image_out, image_extra);
}
@@ -296,6 +335,8 @@ _cairo_surface_release_source_image (cairo_surface_t *surface,
cairo_image_surface_t *image,
void *image_extra)
{
+ assert (!surface->finished);
+
surface->backend->release_source_image (surface, image, image_extra);
}
@@ -334,6 +375,8 @@ _cairo_surface_acquire_dest_image (cairo_surface_t *surface,
cairo_rectangle_t *image_rect,
void **image_extra)
{
+ assert (!surface->finished);
+
return surface->backend->acquire_dest_image (surface, interest_rect,
image_out, image_rect, image_extra);
}
@@ -357,6 +400,8 @@ _cairo_surface_release_dest_image (cairo_surface_t *surface,
cairo_rectangle_t *image_rect,
void *image_extra)
{
+ assert (!surface->finished);
+
surface->backend->release_dest_image (surface, interest_rect,
image, image_rect, image_extra);
}
@@ -386,6 +431,9 @@ _cairo_surface_clone_similar (cairo_surface_t *surface,
cairo_image_surface_t *image;
void *image_extra;
+ if (surface->finished)
+ return CAIRO_STATUS_SURFACE_FINISHED;
+
status = surface->backend->clone_similar (surface, src, clone_out);
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
return status;
@@ -409,6 +457,9 @@ _cairo_surface_clone_similar (cairo_surface_t *surface,
cairo_status_t
cairo_surface_set_matrix (cairo_surface_t *surface, cairo_matrix_t *matrix)
{
+ if (surface->finished)
+ return CAIRO_STATUS_SURFACE_FINISHED;
+
if (surface == NULL)
return CAIRO_STATUS_NULL_POINTER;
@@ -419,6 +470,9 @@ slim_hidden_def(cairo_surface_set_matrix);
cairo_status_t
cairo_surface_get_matrix (cairo_surface_t *surface, cairo_matrix_t *matrix)
{
+ if (surface->finished)
+ return CAIRO_STATUS_SURFACE_FINISHED;
+
if (surface == NULL)
return CAIRO_STATUS_NULL_POINTER;
@@ -429,6 +483,9 @@ slim_hidden_def(cairo_surface_get_matrix);
cairo_status_t
cairo_surface_set_filter (cairo_surface_t *surface, cairo_filter_t filter)
{
+ if (surface->finished)
+ return CAIRO_STATUS_SURFACE_FINISHED;
+
if (surface == NULL)
return CAIRO_STATUS_NULL_POINTER;
@@ -460,6 +517,9 @@ cairo_surface_clip_restore (cairo_surface_t *surface);
cairo_status_t
cairo_surface_set_repeat (cairo_surface_t *surface, int repeat)
{
+ if (surface->finished)
+ return CAIRO_STATUS_SURFACE_FINISHED;
+
if (surface == NULL)
return CAIRO_STATUS_NULL_POINTER;
@@ -552,6 +612,9 @@ _cairo_surface_composite (cairo_operator_t operator,
{
cairo_int_status_t status;
+ if (dst->finished)
+ return CAIRO_STATUS_SURFACE_FINISHED;
+
status = dst->backend->composite (operator,
src, mask, dst,
src_x, src_y,
@@ -580,6 +643,9 @@ _cairo_surface_fill_rectangle (cairo_surface_t *surface,
{
cairo_rectangle_t rect;
+ if (surface->finished)
+ return CAIRO_STATUS_SURFACE_FINISHED;
+
rect.x = x;
rect.y = y;
rect.width = width;
@@ -668,6 +734,9 @@ _cairo_surface_fill_rectangles (cairo_surface_t *surface,
{
cairo_int_status_t status;
+ if (surface->finished)
+ return CAIRO_STATUS_SURFACE_FINISHED;
+
if (num_rects == 0)
return CAIRO_STATUS_SUCCESS;
@@ -763,6 +832,9 @@ _cairo_surface_composite_trapezoids (cairo_operator_t operator,
{
cairo_int_status_t status;
+ if (dst->finished)
+ return CAIRO_STATUS_SURFACE_FINISHED;
+
status = dst->backend->composite_trapezoids (operator,
pattern, dst,
src_x, src_y,
@@ -784,6 +856,9 @@ _cairo_surface_copy_page (cairo_surface_t *surface)
{
cairo_int_status_t status;
+ if (surface->finished)
+ return CAIRO_STATUS_SURFACE_FINISHED;
+
status = surface->backend->copy_page (surface);
/* It's fine if some backends just don't support this. */
if (status == CAIRO_INT_STATUS_UNSUPPORTED)
@@ -799,6 +874,9 @@ _cairo_surface_show_page (cairo_surface_t *surface)
{
cairo_int_status_t status;
+ if (surface->finished)
+ return CAIRO_STATUS_SURFACE_FINISHED;
+
status = surface->backend->show_page (surface);
/* It's fine if some backends just don't support this. */
if (status == CAIRO_INT_STATUS_UNSUPPORTED)
@@ -812,5 +890,39 @@ _cairo_surface_show_page (cairo_surface_t *surface)
cairo_status_t
_cairo_surface_set_clip_region (cairo_surface_t *surface, pixman_region16_t *region)
{
+ if (surface->finished)
+ return CAIRO_STATUS_SURFACE_FINISHED;
+
return surface->backend->set_clip_region (surface, region);
}
+
+cairo_status_t
+_cairo_surface_show_glyphs (cairo_font_t *font,
+ cairo_operator_t operator,
+ cairo_pattern_t *pattern,
+ cairo_surface_t *dst,
+ int source_x,
+ int source_y,
+ int dest_x,
+ int dest_y,
+ unsigned int width,
+ unsigned int height,
+ const cairo_glyph_t *glyphs,
+ int num_glyphs)
+{
+ cairo_status_t status;
+
+ if (dst->finished)
+ return CAIRO_STATUS_SURFACE_FINISHED;
+
+ if (dst->backend->show_glyphs != NULL)
+ status = dst->backend->show_glyphs (font, operator, pattern, dst,
+ source_x, source_y,
+ dest_x, dest_y,
+ width, height,
+ glyphs, num_glyphs);
+ else
+ status = CAIRO_INT_STATUS_UNSUPPORTED;
+
+ return status;
+}
diff --git a/src/cairo_win32_surface.c b/src/cairo_win32_surface.c
index dcfe6d04..e5a27b0e 100644
--- a/src/cairo_win32_surface.c
+++ b/src/cairo_win32_surface.c
@@ -346,7 +346,7 @@ _cairo_win32_surface_create_dib (cairo_format_t format,
}
static void
-_cairo_win32_surface_destroy (void *abstract_surface)
+_cairo_win32_surface_finish (void *abstract_surface)
{
cairo_win32_surface_t *surface = abstract_surface;
@@ -362,8 +362,6 @@ _cairo_win32_surface_destroy (void *abstract_surface)
DeleteObject (surface->bitmap);
DeleteDC (surface->dc);
}
-
- free (surface);
}
static double
@@ -914,7 +912,7 @@ _cairo_surface_is_win32 (cairo_surface_t *surface)
static const cairo_surface_backend_t cairo_win32_surface_backend = {
_cairo_win32_surface_create_similar,
- _cairo_win32_surface_destroy,
+ _cairo_win32_surface_finish,
_cairo_win32_surface_pixels_per_inch,
_cairo_win32_surface_acquire_source_image,
_cairo_win32_surface_release_source_image,
diff --git a/src/cairo_xcb_surface.c b/src/cairo_xcb_surface.c
index 0694b77a..aef8368f 100644
--- a/src/cairo_xcb_surface.c
+++ b/src/cairo_xcb_surface.c
@@ -278,7 +278,7 @@ _cairo_xcb_surface_create_similar (void *abstract_src,
}
static void
-_cairo_xcb_surface_destroy (void *abstract_surface)
+_cairo_xcb_surface_finish (void *abstract_surface)
{
cairo_xcb_surface_t *surface = abstract_surface;
if (surface->picture.xid)
@@ -291,8 +291,6 @@ _cairo_xcb_surface_destroy (void *abstract_surface)
XCBFreeGC (surface->dpy, surface->gc);
surface->dpy = 0;
-
- free (surface);
}
static double
@@ -901,7 +899,7 @@ _cairo_xcb_surface_set_clip_region (void *abstract_surface,
static const cairo_surface_backend_t cairo_xcb_surface_backend = {
_cairo_xcb_surface_create_similar,
- _cairo_xcb_surface_destroy,
+ _cairo_xcb_surface_finish,
_cairo_xcb_surface_pixels_per_inch,
_cairo_xcb_surface_acquire_source_image,
_cairo_xcb_surface_release_source_image,
diff --git a/src/cairo_xlib_surface.c b/src/cairo_xlib_surface.c
index 8e05a320..3aaa94d6 100644
--- a/src/cairo_xlib_surface.c
+++ b/src/cairo_xlib_surface.c
@@ -185,8 +185,8 @@ _cairo_xlib_surface_create_similar (void *abstract_src,
return &surface->base;
}
-static void
-_cairo_xlib_surface_destroy (void *abstract_surface)
+static cairo_status_t
+_cairo_xlib_surface_finish (void *abstract_surface)
{
cairo_xlib_surface_t *surface = abstract_surface;
if (surface->picture)
@@ -200,7 +200,7 @@ _cairo_xlib_surface_destroy (void *abstract_surface)
surface->dpy = NULL;
- free (surface);
+ return CAIRO_STATUS_SUCCESS;
}
static double
@@ -959,7 +959,7 @@ _cairo_xlib_surface_show_glyphs (cairo_font_t *font,
static const cairo_surface_backend_t cairo_xlib_surface_backend = {
_cairo_xlib_surface_create_similar,
- _cairo_xlib_surface_destroy,
+ _cairo_xlib_surface_finish,
_cairo_xlib_surface_pixels_per_inch,
_cairo_xlib_surface_acquire_source_image,
_cairo_xlib_surface_release_source_image,
diff --git a/src/cairoint.h b/src/cairoint.h
index 6afaece0..1c3ad6e6 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -55,6 +55,7 @@
#include <math.h>
#include <limits.h>
#include <stdint.h>
+#include <stdio.h>
#include "cairo.h"
@@ -550,8 +551,8 @@ typedef struct _cairo_surface_backend {
int width,
int height);
- void
- (*destroy) (void *surface);
+ cairo_status_t
+ (*finish) (void *surface);
double
(*pixels_per_inch) (void *surface);
@@ -666,6 +667,7 @@ struct _cairo_surface {
const cairo_surface_backend_t *backend;
unsigned int ref_count;
+ cairo_bool_t finished;
cairo_array_t user_data_slots;
cairo_matrix_t matrix;
@@ -1501,6 +1503,20 @@ _cairo_surface_clone_similar (cairo_surface_t *surface,
cairo_private cairo_status_t
_cairo_surface_set_clip_region (cairo_surface_t *surface, pixman_region16_t *region);
+cairo_private cairo_status_t
+_cairo_surface_show_glyphs (cairo_font_t *font,
+ cairo_operator_t operator,
+ cairo_pattern_t *pattern,
+ cairo_surface_t *surface,
+ int source_x,
+ int source_y,
+ int dest_x,
+ int dest_y,
+ unsigned int width,
+ unsigned int height,
+ const cairo_glyph_t *glyphs,
+ int num_glyphs);
+
/* cairo_image_surface.c */
cairo_private cairo_image_surface_t *
@@ -1764,6 +1780,35 @@ _cairo_utf8_to_utf16 (const char *str,
uint16_t **result,
int *items_written);
+/* cairo_output_stream.c */
+
+typedef struct _cairo_output_stream cairo_output_stream_t;
+
+cairo_private cairo_output_stream_t *
+_cairo_output_stream_create (cairo_write_func_t write_func,
+ cairo_destroy_func_t destroy_closure_func,
+ void *closure);
+
+cairo_private void
+_cairo_output_stream_destroy (cairo_output_stream_t *stream);
+
+cairo_private cairo_status_t
+_cairo_output_stream_write (cairo_output_stream_t *stream,
+ const void *data, size_t length);
+
+cairo_private cairo_status_t
+_cairo_output_stream_printf (cairo_output_stream_t *stream,
+ const char *fmt, ...);
+
+cairo_private long
+_cairo_output_stream_get_position (cairo_output_stream_t *status);
+
+cairo_private cairo_status_t
+_cairo_output_stream_get_status (cairo_output_stream_t *stream);
+
+cairo_output_stream_t *
+_cairo_output_stream_create_for_file (FILE *fp);
+
/* Avoid unnecessary PLT entries. */
slim_hidden_proto(cairo_close_path)