[cairo-commit] 2 commits - src/cairo-pdf-surface.c

Carl Worth cworth at kemper.freedesktop.org
Fri May 12 15:00:21 PDT 2006


 src/cairo-pdf-surface.c | 1215 ++++++++++++++++++++----------------------------
 1 files changed, 526 insertions(+), 689 deletions(-)

New commits:
diff-tree f500cef19f049a4a0ed296172618db2f26794932 (from d84a1cac1cc2da8a34fb6aa91c3c4f4058527207)
Author: Carl Worth <cworth at cworth.org>
Date:   Fri May 12 14:56:11 2006 -0700

    PDF: Fold (unused) cairo_pdf_document_t into cairo_pdf_surface_t

diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index d0e5ebb..2746cd0 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -88,7 +88,6 @@
 
 typedef struct cairo_pdf_object cairo_pdf_object_t;
 typedef struct cairo_pdf_resource cairo_pdf_resource_t;
-typedef struct cairo_pdf_document cairo_pdf_document_t;
 typedef struct cairo_pdf_surface cairo_pdf_surface_t;
 
 struct cairo_pdf_object {
@@ -99,17 +98,25 @@ struct cairo_pdf_resource {
     unsigned int id;
 };
 
-struct cairo_pdf_document {
-    cairo_output_stream_t *output_stream;
-    unsigned long ref_count;
-    cairo_surface_t *owner;
-    cairo_bool_t finished;
+struct cairo_pdf_surface {
+    cairo_surface_t base;
+
+    /* Prefer the name "output" here to avoid confusion over the
+     * structure within a PDF document known as a "stream". */
+    cairo_output_stream_t *output;
 
     double width;
     double height;
     double x_dpi;
     double y_dpi;
 
+    cairo_array_t objects;
+    cairo_array_t pages;
+    cairo_array_t patterns;
+    cairo_array_t xobjects;
+    cairo_array_t streams;
+    cairo_array_t alphas;
+
     cairo_pdf_resource_t next_available_resource;
     cairo_pdf_resource_t pages_resource;
 
@@ -120,25 +127,6 @@ struct cairo_pdf_document {
 	long start_offset;
     } current_stream;
 
-    cairo_array_t objects;
-    cairo_array_t pages;
-
-    cairo_array_t fonts;
-};
-
-struct cairo_pdf_surface {
-    cairo_surface_t base;
-
-    double width;
-    double height;
-
-    cairo_pdf_document_t *document;
-
-    cairo_array_t patterns;
-    cairo_array_t xobjects;
-    cairo_array_t streams;
-    cairo_array_t alphas;
-    cairo_array_t fonts;
     cairo_bool_t has_clip;
 
     cairo_paginated_mode_t paginated_mode;
@@ -146,77 +134,70 @@ struct cairo_pdf_surface {
 
 #define DEFAULT_DPI 300
 
-static cairo_pdf_document_t *
-_cairo_pdf_document_create (cairo_output_stream_t	*stream,
-			    double			width,
-			    double			height);
-
-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 cairo_pdf_document_t *
-_cairo_pdf_document_reference (cairo_pdf_document_t *document);
-
 static cairo_pdf_resource_t
-_cairo_pdf_document_new_object (cairo_pdf_document_t *document);
-
-static cairo_status_t
-_cairo_pdf_document_add_page (cairo_pdf_document_t *document,
-			      cairo_pdf_surface_t *surface);
+_cairo_pdf_surface_new_object (cairo_pdf_surface_t *surface);
 
 static void
 _cairo_pdf_surface_clear (cairo_pdf_surface_t *surface);
 
 static cairo_pdf_resource_t
-_cairo_pdf_document_open_stream (cairo_pdf_document_t	*document,
-				 const char		*fmt,
-				 ...) CAIRO_PRINTF_FORMAT(2, 3);
+_cairo_pdf_surface_open_stream (cairo_pdf_surface_t	*surface,
+				const char		*fmt,
+				...) CAIRO_PRINTF_FORMAT(2, 3);
 static void
-_cairo_pdf_document_close_stream (cairo_pdf_document_t	*document);
+_cairo_pdf_surface_close_stream (cairo_pdf_surface_t	*surface);
 
-static cairo_surface_t *
-_cairo_pdf_surface_create_for_document (cairo_pdf_document_t	*document,
-					double			width,
-					double			height);
 static void
 _cairo_pdf_surface_add_stream (cairo_pdf_surface_t	*surface,
 			       cairo_pdf_resource_t	 stream);
 
+static void
+_cairo_pdf_surface_write_pages (cairo_pdf_surface_t *surface);
+
+static cairo_pdf_resource_t
+_cairo_pdf_surface_write_info (cairo_pdf_surface_t *surface);
+
+static cairo_pdf_resource_t
+_cairo_pdf_surface_write_catalog (cairo_pdf_surface_t *surface);
+
+static long
+_cairo_pdf_surface_write_xref (cairo_pdf_surface_t *surface);
+
+static cairo_status_t
+_cairo_pdf_surface_write_page (cairo_pdf_surface_t *surface);
+
 static const cairo_surface_backend_t cairo_pdf_surface_backend;
 static const cairo_paginated_surface_backend_t cairo_pdf_surface_paginated_backend;
 
 static cairo_pdf_resource_t
-_cairo_pdf_document_new_object (cairo_pdf_document_t *document)
+_cairo_pdf_surface_new_object (cairo_pdf_surface_t *surface)
 {
     cairo_pdf_resource_t resource;
     cairo_status_t status;
     cairo_pdf_object_t object;
 
-    object.offset = _cairo_output_stream_get_position (document->output_stream);
+    object.offset = _cairo_output_stream_get_position (surface->output);
 
-    status = _cairo_array_append (&document->objects, &object);
+    status = _cairo_array_append (&surface->objects, &object);
     if (status) {
 	resource.id = 0;
 	return resource;
     }
 
-    resource = document->next_available_resource;
-    document->next_available_resource.id++;
+    resource = surface->next_available_resource;
+    surface->next_available_resource.id++;
 
     return resource;
 }
 
 static void
-_cairo_pdf_document_update_object (cairo_pdf_document_t *document,
-				   cairo_pdf_resource_t	 resource)
+_cairo_pdf_surface_update_object (cairo_pdf_surface_t	*surface,
+				  cairo_pdf_resource_t	 resource)
 {
     cairo_pdf_object_t *object;
 
-    object = _cairo_array_index (&document->objects, resource.id - 1);
-    object->offset = _cairo_output_stream_get_position (document->output_stream);
+    object = _cairo_array_index (&surface->objects, resource.id - 1);
+    object->offset = _cairo_output_stream_get_position (surface->output);
 }
 
 static void
@@ -259,25 +240,48 @@ _cairo_pdf_surface_add_alpha (cairo_pdf_
 }
 
 static cairo_surface_t *
-_cairo_pdf_surface_create_for_stream_internal (cairo_output_stream_t	*stream,
+_cairo_pdf_surface_create_for_stream_internal (cairo_output_stream_t	*output,
 					       double			 width,
 					       double			 height)
 {
-    cairo_pdf_document_t *document;
-    cairo_surface_t *target;
+    cairo_pdf_surface_t *surface;
 
-    document = _cairo_pdf_document_create (stream, width, height);
-    if (document == NULL) {
+    surface = malloc (sizeof (cairo_pdf_surface_t));
+    if (surface == NULL) {
 	_cairo_error (CAIRO_STATUS_NO_MEMORY);
 	return (cairo_surface_t*) &_cairo_surface_nil;
     }
 
-    target = _cairo_pdf_surface_create_for_document (document, width, height);
+    _cairo_surface_init (&surface->base, &cairo_pdf_surface_backend);
+
+    surface->output = output;
+
+    surface->width = width;
+    surface->height = height;
+    surface->x_dpi = DEFAULT_DPI;
+    surface->y_dpi = DEFAULT_DPI;
+
+    _cairo_array_init (&surface->objects, sizeof (cairo_pdf_object_t));
+    _cairo_array_init (&surface->pages, sizeof (cairo_pdf_resource_t));
+    _cairo_array_init (&surface->patterns, sizeof (cairo_pdf_resource_t));
+    _cairo_array_init (&surface->xobjects, sizeof (cairo_pdf_resource_t));
+    _cairo_array_init (&surface->streams, sizeof (cairo_pdf_resource_t));
+    _cairo_array_init (&surface->alphas, sizeof (double));
+
+    surface->next_available_resource.id = 1;
+    surface->pages_resource = _cairo_pdf_surface_new_object (surface);
+
+    surface->current_stream.active = FALSE;
 
-    document->owner = target;
-    _cairo_pdf_document_destroy (document);
+    surface->has_clip = FALSE;
+
+    surface->paginated_mode = CAIRO_PAGINATED_MODE_ANALYZE;
+
+    /* Document header */
+    _cairo_output_stream_printf (surface->output,
+				 "%%PDF-1.4\r\n");
 
-    return _cairo_paginated_surface_create (target,
+    return _cairo_paginated_surface_create (&surface->base,
 					    CAIRO_CONTENT_COLOR_ALPHA,
 					    width, height,
 					    &cairo_pdf_surface_paginated_backend);
@@ -289,7 +293,7 @@ _cairo_pdf_surface_create_for_stream_int
  * @closure: the closure argument for @write
  * @width_in_points: width of the surface, in points (1 point == 1/72.0 inch)
  * @height_in_points: height of the surface, in points (1 point == 1/72.0 inch)
- * 
+ *
  * Creates a PDF surface of the specified size in points to be written
  * incrementally to the stream represented by @write and @closure.
  *
@@ -308,16 +312,16 @@ cairo_pdf_surface_create_for_stream (cai
 				     double			 height_in_points)
 {
     cairo_status_t status;
-    cairo_output_stream_t *stream;
+    cairo_output_stream_t *output;
 
-    stream = _cairo_output_stream_create (write, NULL, closure);
-    status = _cairo_output_stream_get_status (stream);
+    output = _cairo_output_stream_create (write, NULL, closure);
+    status = _cairo_output_stream_get_status (output);
     if (status) {
 	_cairo_error (status);
 	return (cairo_surface_t*) &_cairo_surface_nil;
     }
 
-    return _cairo_pdf_surface_create_for_stream_internal (stream,
+    return _cairo_pdf_surface_create_for_stream_internal (output,
 							  width_in_points,
 							  height_in_points);
 }
@@ -327,10 +331,10 @@ cairo_pdf_surface_create_for_stream (cai
  * @filename: a filename for the PDF output (must be writable)
  * @width_in_points: width of the surface, in points (1 point == 1/72.0 inch)
  * @height_in_points: height of the surface, in points (1 point == 1/72.0 inch)
- * 
+ *
  * Creates a PDF surface of the specified size in points to be written
  * to @filename.
- * 
+ *
  * Return value: a pointer to the newly created surface. The caller
  * owns the surface and should call cairo_surface_destroy when done
  * with it.
@@ -345,16 +349,16 @@ cairo_pdf_surface_create (const char		*f
 			  double		 height_in_points)
 {
     cairo_status_t status;
-    cairo_output_stream_t *stream;
+    cairo_output_stream_t *output;
 
-    stream = _cairo_output_stream_create_for_filename (filename);
-    status = _cairo_output_stream_get_status (stream);
+    output = _cairo_output_stream_create_for_filename (filename);
+    status = _cairo_output_stream_get_status (output);
     if (status) {
 	_cairo_error (status);
 	return (cairo_surface_t*) &_cairo_surface_nil;
     }
 
-    return _cairo_pdf_surface_create_for_stream_internal (stream,
+    return _cairo_pdf_surface_create_for_stream_internal (output,
 							  width_in_points,
 							  height_in_points);
 }
@@ -393,7 +397,7 @@ _extract_pdf_surface (cairo_surface_t		 
  * @surface: a PDF cairo_surface_t
  * @x_dpi: horizontal dpi
  * @y_dpi: vertical dpi
- * 
+ *
  * Set the horizontal and vertical resolution for image fallbacks.
  * When the pdf backend needs to fall back to image overlays, it will
  * use this resolution. These DPI values are not used for any other
@@ -414,8 +418,8 @@ cairo_pdf_surface_set_dpi (cairo_surface
 	return;
     }
 
-    pdf_surface->document->x_dpi = x_dpi;    
-    pdf_surface->document->y_dpi = y_dpi;    
+    pdf_surface->x_dpi = x_dpi;
+    pdf_surface->y_dpi = y_dpi;
 }
 
 /**
@@ -423,7 +427,7 @@ cairo_pdf_surface_set_dpi (cairo_surface
  * @surface: a PDF cairo_surface_t
  * @width_in_points: new surface width, in points (1 point == 1/72.0 inch)
  * @height_in_points: new surface height, in points (1 point == 1/72.0 inch)
- * 
+ *
  * Changes the size of a PDF surface for the current (and
  * subsequent) pages.
  *
@@ -451,37 +455,6 @@ cairo_pdf_surface_set_size (cairo_surfac
     pdf_surface->height = height_in_points;
 }
 
-static cairo_surface_t *
-_cairo_pdf_surface_create_for_document (cairo_pdf_document_t	*document,
-					double			width,
-					double			height)
-{
-    cairo_pdf_surface_t *surface;
-
-    surface = malloc (sizeof (cairo_pdf_surface_t));
-    if (surface == NULL) {
-	_cairo_error (CAIRO_STATUS_NO_MEMORY);
-	return (cairo_surface_t*) &_cairo_surface_nil;
-    }
-
-    _cairo_surface_init (&surface->base, &cairo_pdf_surface_backend);
-
-    surface->width = width;
-    surface->height = height;
-
-    surface->document = _cairo_pdf_document_reference (document);
-    _cairo_array_init (&surface->streams, sizeof (cairo_pdf_resource_t));
-    _cairo_array_init (&surface->patterns, sizeof (cairo_pdf_resource_t));
-    _cairo_array_init (&surface->xobjects, sizeof (cairo_pdf_resource_t));
-    _cairo_array_init (&surface->alphas, sizeof (double));
-    _cairo_array_init (&surface->fonts, sizeof (cairo_pdf_resource_t));
-    surface->has_clip = FALSE;
-
-    surface->paginated_mode = CAIRO_PAGINATED_MODE_ANALYZE;
-
-    return &surface->base;
-}
-
 static void
 _cairo_pdf_surface_clear (cairo_pdf_surface_t *surface)
 {
@@ -489,7 +462,6 @@ _cairo_pdf_surface_clear (cairo_pdf_surf
     _cairo_array_truncate (&surface->patterns, 0);
     _cairo_array_truncate (&surface->xobjects, 0);
     _cairo_array_truncate (&surface->alphas, 0);
-    _cairo_array_truncate (&surface->fonts, 0);
 }
 
 static cairo_surface_t *
@@ -506,63 +478,61 @@ _cairo_pdf_surface_create_similar (void	
 }
 
 static cairo_pdf_resource_t
-_cairo_pdf_document_open_stream (cairo_pdf_document_t	*document,
-				 const char		*fmt,
-				 ...)
+_cairo_pdf_surface_open_stream (cairo_pdf_surface_t	*surface,
+				const char		*fmt,
+				...)
 {
-    cairo_output_stream_t *output_stream = document->output_stream;
     va_list ap;
 
-    document->current_stream.active = TRUE;
-    document->current_stream.self = _cairo_pdf_document_new_object (document);
-    document->current_stream.length = _cairo_pdf_document_new_object (document);
+    surface->current_stream.active = TRUE;
+    surface->current_stream.self = _cairo_pdf_surface_new_object (surface);
+    surface->current_stream.length = _cairo_pdf_surface_new_object (surface);
 
-    _cairo_output_stream_printf (output_stream,
+    _cairo_output_stream_printf (surface->output,
 				 "%d 0 obj\r\n"
 				 "<< /Length %d 0 R\r\n",
-				 document->current_stream.self.id,
-				 document->current_stream.length.id);
+				 surface->current_stream.self.id,
+				 surface->current_stream.length.id);
 
     if (fmt != NULL) {
 	va_start (ap, fmt);
-	_cairo_output_stream_vprintf (output_stream, fmt, ap);
+	_cairo_output_stream_vprintf (surface->output, fmt, ap);
 	va_end (ap);
     }
 
-    _cairo_output_stream_printf (output_stream,
+    _cairo_output_stream_printf (surface->output,
 				 ">>\r\n"
 				 "stream\r\n");
 
-    document->current_stream.start_offset = _cairo_output_stream_get_position (output_stream);
+    surface->current_stream.start_offset = _cairo_output_stream_get_position (surface->output);
 
-    return document->current_stream.self;
+    return surface->current_stream.self;
 }
 
 static void
-_cairo_pdf_document_close_stream (cairo_pdf_document_t	*document)
+_cairo_pdf_surface_close_stream (cairo_pdf_surface_t *surface)
 {
-    cairo_output_stream_t *output_stream = document->output_stream;
     long length;
 
-    if (! document->current_stream.active)
+    if (! surface->current_stream.active)
 	return;
 
-    length = _cairo_output_stream_get_position (output_stream) -
-	document->current_stream.start_offset;
-    _cairo_output_stream_printf (output_stream,
+    length = _cairo_output_stream_get_position (surface->output) -
+	surface->current_stream.start_offset;
+    _cairo_output_stream_printf (surface->output,
 				 "endstream\r\n"
 				 "endobj\r\n");
 
-    _cairo_pdf_document_update_object (document,
-				       document->current_stream.length);
-    _cairo_output_stream_printf (output_stream,
+    _cairo_pdf_surface_update_object (surface,
+				      surface->current_stream.length);
+    _cairo_output_stream_printf (surface->output,
 				 "%d 0 obj\r\n"
 				 "   %ld\r\n"
 				 "endobj\r\n",
-				 document->current_stream.length.id,
+				 surface->current_stream.length.id,
 				 length);
 
-    document->current_stream.active = FALSE;
+    surface->current_stream.active = FALSE;
 }
 
 static cairo_status_t
@@ -570,46 +540,63 @@ _cairo_pdf_surface_finish (void *abstrac
 {
     cairo_status_t status;
     cairo_pdf_surface_t *surface = abstract_surface;
-    cairo_pdf_document_t *document = surface->document;
+    long offset;
+    cairo_pdf_resource_t info, catalog;
 
-    _cairo_pdf_document_close_stream (document);
+    _cairo_pdf_surface_close_stream (surface);
 
-    if (document->owner == &surface->base)
-	status = _cairo_pdf_document_finish (document);
-    else
-	status = CAIRO_STATUS_SUCCESS;
+    _cairo_pdf_surface_write_pages (surface);
 
-    _cairo_pdf_document_destroy (document);
+    info = _cairo_pdf_surface_write_info (surface);
+    catalog = _cairo_pdf_surface_write_catalog (surface);
+    offset = _cairo_pdf_surface_write_xref (surface);
 
-    _cairo_array_fini (&surface->streams);
+    _cairo_output_stream_printf (surface->output,
+				 "trailer\r\n"
+				 "<< /Size %d\r\n"
+				 "   /Root %d 0 R\r\n"
+				 "   /Info %d 0 R\r\n"
+				 ">>\r\n",
+				 surface->next_available_resource.id,
+				 catalog.id,
+				 info.id);
+
+    _cairo_output_stream_printf (surface->output,
+				 "startxref\r\n"
+				 "%ld\r\n"
+				 "%%%%EOF\r\n",
+				 offset);
+
+    status = _cairo_output_stream_get_status (surface->output);
+    _cairo_output_stream_destroy (surface->output);
+
+    _cairo_array_fini (&surface->objects);
+    _cairo_array_fini (&surface->pages);
     _cairo_array_fini (&surface->patterns);
     _cairo_array_fini (&surface->xobjects);
+    _cairo_array_fini (&surface->streams);
     _cairo_array_fini (&surface->alphas);
-    _cairo_array_fini (&surface->fonts);
 
     return status;
 }
 
-static void 
+static void
 _cairo_pdf_surface_pause_content_stream (cairo_pdf_surface_t *surface)
 {
-    cairo_pdf_document_t *document = surface->document;
-
-    _cairo_pdf_document_close_stream (document);
+    _cairo_pdf_surface_close_stream (surface);
 }
 
 static void
 _cairo_pdf_surface_resume_content_stream (cairo_pdf_surface_t *surface)
 {
-    cairo_pdf_document_t *document = surface->document;
     cairo_pdf_resource_t stream;
 
-    stream = _cairo_pdf_document_open_stream (document,
-					      "   /Type /XObject\r\n"
-					      "   /Subtype /Form\r\n"
-					      "   /BBox [ 0 0 %f %f ]\r\n",
-					      surface->width,
-					      surface->height);
+    stream = _cairo_pdf_surface_open_stream (surface,
+					     "   /Type /XObject\r\n"
+					     "   /Subtype /Form\r\n"
+					     "   /BBox [ 0 0 %f %f ]\r\n",
+					     surface->width,
+					     surface->height);
 
     _cairo_pdf_surface_add_stream (surface, stream);
 }
@@ -618,20 +605,18 @@ static cairo_int_status_t
 _cairo_pdf_surface_start_page (void *abstract_surface)
 {
     cairo_pdf_surface_t *surface = abstract_surface;
-    cairo_pdf_document_t *document = surface->document;
-    cairo_output_stream_t *output = document->output_stream;
     cairo_pdf_resource_t stream;
 
-    stream = _cairo_pdf_document_open_stream (document,
-					      "   /Type /XObject\r\n"
-					      "   /Subtype /Form\r\n"
-					      "   /BBox [ 0 0 %f %f ]\r\n",
-					      surface->width,
-					      surface->height);
+    stream = _cairo_pdf_surface_open_stream (surface,
+					     "   /Type /XObject\r\n"
+					     "   /Subtype /Form\r\n"
+					     "   /BBox [ 0 0 %f %f ]\r\n",
+					     surface->width,
+					     surface->height);
 
     _cairo_pdf_surface_add_stream (surface, stream);
 
-    _cairo_output_stream_printf (output,
+    _cairo_output_stream_printf (surface->output,
 				 "1 0 0 -1 0 %f cm\r\n",
 				 surface->height);
 
@@ -662,12 +647,11 @@ compress_dup (const void *data, unsigned
  * no SMask object will be emitted and *id_ret will be set to 0.
  */
 static cairo_status_t
-emit_smask (cairo_pdf_document_t	*document,
+emit_smask (cairo_pdf_surface_t		*surface,
 	    cairo_image_surface_t	*image,
 	    cairo_pdf_resource_t	*stream_ret)
 {
     cairo_status_t status = CAIRO_STATUS_SUCCESS;
-    cairo_output_stream_t *output = document->output_stream;
     char *alpha, *alpha_compressed;
     unsigned long alpha_size, alpha_compressed_size;
     pixman_bits_t *pixel;
@@ -708,21 +692,20 @@ emit_smask (cairo_pdf_document_t	*docume
     if (alpha_compressed == NULL) {
 	status = CAIRO_STATUS_NO_MEMORY;
 	goto CLEANUP_ALPHA;
-	
     }
 
-    *stream_ret = _cairo_pdf_document_open_stream (document,
-						   "   /Type /XObject\r\n"
-						   "   /Subtype /Image\r\n"
-						   "   /Width %d\r\n"
-						   "   /Height %d\r\n"
-						   "   /ColorSpace /DeviceGray\r\n"
-						   "   /BitsPerComponent 8\r\n"
-						   "   /Filter /FlateDecode\r\n",
-						   image->width, image->height);
-    _cairo_output_stream_write (output, alpha_compressed, alpha_compressed_size);
-    _cairo_output_stream_printf (output, "\r\n");
-    _cairo_pdf_document_close_stream (document);
+    *stream_ret = _cairo_pdf_surface_open_stream (surface,
+						  "   /Type /XObject\r\n"
+						  "   /Subtype /Image\r\n"
+						  "   /Width %d\r\n"
+						  "   /Height %d\r\n"
+						  "   /ColorSpace /DeviceGray\r\n"
+						  "   /BitsPerComponent 8\r\n"
+						  "   /Filter /FlateDecode\r\n",
+						  image->width, image->height);
+    _cairo_output_stream_write (surface->output, alpha_compressed, alpha_compressed_size);
+    _cairo_output_stream_printf (surface->output, "\r\n");
+    _cairo_pdf_surface_close_stream (surface);
 
     free (alpha_compressed);
  CLEANUP_ALPHA:
@@ -732,15 +715,14 @@ emit_smask (cairo_pdf_document_t	*docume
 }
 
 
-/* Emit image data into the given document, providing an id that can
- * be used to reference the data in id_ret. */
+/* Emit image data into the given surface, providing a resource that
+ * can be used to reference the data in image_ret. */
 static cairo_status_t
-emit_image (cairo_pdf_document_t	*document,
+emit_image (cairo_pdf_surface_t		*surface,
 	    cairo_image_surface_t	*image,
 	    cairo_pdf_resource_t	*image_ret)
 {
     cairo_status_t status = CAIRO_STATUS_SUCCESS;
-    cairo_output_stream_t *output = document->output_stream;
     char *rgb, *compressed;
     unsigned long rgb_size, compressed_size;
     pixman_bits_t *pixel;
@@ -756,7 +738,7 @@ emit_image (cairo_pdf_document_t	*docume
     /* These are the only image formats we currently support, (which
      * makes things a lot simpler here). This is enforeced through
      * _analyze_operation which only accept source surfaces of
-     * CONTENT_COLOR or CONTENT_COLOR_ALPHA. 
+     * CONTENT_COLOR or CONTENT_COLOR_ALPHA.
      */
     assert (image->format == CAIRO_FORMAT_RGB24 || image->format == CAIRO_FORMAT_ARGB32);
 
@@ -805,7 +787,7 @@ emit_image (cairo_pdf_document_t	*docume
 
     need_smask = FALSE;
     if (image->format == CAIRO_FORMAT_ARGB32) {
-	status = emit_smask (document, image, &smask);
+	status = emit_smask (surface, image, &smask);
 	if (status)
 	    goto CLEANUP_COMPRESSED;
 
@@ -823,21 +805,21 @@ emit_image (cairo_pdf_document_t	*docume
 
 
     if (need_smask)
-	*image_ret = _cairo_pdf_document_open_stream (document,
-						      IMAGE_DICTIONARY
-						      "   /SMask %d 0 R\r\n",
-						      image->width, image->height,
-						      smask.id);
+	*image_ret = _cairo_pdf_surface_open_stream (surface,
+						     IMAGE_DICTIONARY
+						     "   /SMask %d 0 R\r\n",
+						     image->width, image->height,
+						     smask.id);
     else
-	*image_ret = _cairo_pdf_document_open_stream (document,
-						      IMAGE_DICTIONARY,
-						      image->width, image->height);
+	*image_ret = _cairo_pdf_surface_open_stream (surface,
+						     IMAGE_DICTIONARY,
+						     image->width, image->height);
 
 #undef IMAGE_DICTIONARY
 
-    _cairo_output_stream_write (output, compressed, compressed_size);
-    _cairo_output_stream_printf (output, "\r\n");
-    _cairo_pdf_document_close_stream (document);
+    _cairo_output_stream_write (surface->output, compressed, compressed_size);
+    _cairo_output_stream_printf (surface->output, "\r\n");
+    _cairo_pdf_surface_close_stream (surface);
 
  CLEANUP_COMPRESSED:
     free (compressed);
@@ -851,15 +833,13 @@ static cairo_status_t
 emit_solid_pattern (cairo_pdf_surface_t *surface,
 		    cairo_solid_pattern_t *pattern)
 {
-    cairo_pdf_document_t *document = surface->document;
-    cairo_output_stream_t *output = document->output_stream;
     cairo_pdf_resource_t alpha;
 
     alpha = _cairo_pdf_surface_add_alpha (surface, pattern->color.alpha);
 
     /* With some work, we could separate the stroking
      * or non-stroking color here as actually needed. */
-    _cairo_output_stream_printf (output,
+    _cairo_output_stream_printf (surface->output,
 				 "%f %f %f RG "
 				 "%f %f %f rg "
 				 "/a%d gs\r\n",
@@ -875,11 +855,9 @@ emit_solid_pattern (cairo_pdf_surface_t 
 }
 
 static cairo_status_t
-emit_surface_pattern (cairo_pdf_surface_t	*dst,
+emit_surface_pattern (cairo_pdf_surface_t	*surface,
 		      cairo_surface_pattern_t	*pattern)
 {
-    cairo_pdf_document_t *document = dst->document;
-    cairo_output_stream_t *output = document->output_stream;
     cairo_pdf_resource_t stream;
     cairo_image_surface_t *image;
     void *image_extra;
@@ -888,21 +866,21 @@ emit_surface_pattern (cairo_pdf_surface_
     cairo_matrix_t cairo_p2d, pdf_p2d;
     cairo_extend_t extend = cairo_pattern_get_extend (&pattern->base);
     int xstep, ystep;
-    cairo_rectangle_fixed_t dst_extents;
+    cairo_rectangle_fixed_t surface_extents;
 
     /* XXX: Should do something clever here for PDF source surfaces ? */
 
-    _cairo_pdf_surface_pause_content_stream (dst);
+    _cairo_pdf_surface_pause_content_stream (surface);
 
     status = _cairo_surface_acquire_source_image (pattern->surface, &image, &image_extra);
     if (status)
 	return status;
 
-    status = emit_image (dst->document, image, &image_resource);
+    status = emit_image (surface, image, &image_resource);
     if (status)
 	goto BAIL;
 
-    _cairo_surface_get_extents (&dst->base, &dst_extents);
+    _cairo_surface_get_extents (&surface->base, &surface_extents);
 
     /* In PDF, (as far as I can tell), all patterns are repeating. So
      * we support cairo's EXTEND_NONE semantics by setting the repeat
@@ -912,8 +890,8 @@ emit_surface_pattern (cairo_pdf_surface_
      */
     switch (extend) {
     case CAIRO_EXTEND_NONE:
-	xstep = MAX(image->width, dst_extents.width);
-	ystep = MAX(image->height, dst_extents.height);
+	xstep = MAX(image->width, surface_extents.width);
+	ystep = MAX(image->height, surface_extents.height);
 	break;
     case CAIRO_EXTEND_REPEAT:
 	xstep = image->width;
@@ -956,44 +934,44 @@ emit_surface_pattern (cairo_pdf_surface_
     cairo_matrix_invert (&cairo_p2d);
 
     cairo_matrix_init_identity (&pdf_p2d);
-    cairo_matrix_translate (&pdf_p2d, 0.0, dst_extents.height);
+    cairo_matrix_translate (&pdf_p2d, 0.0, surface_extents.height);
     cairo_matrix_scale (&pdf_p2d, 1.0, -1.0);
     cairo_matrix_multiply (&pdf_p2d, &cairo_p2d, &pdf_p2d);
     cairo_matrix_translate (&pdf_p2d, 0.0, image->height);
     cairo_matrix_scale (&pdf_p2d, 1.0, -1.0);
 
-    stream = _cairo_pdf_document_open_stream (document,
-					      "   /BBox [0 0 %d %d]\r\n"
-					      "   /XStep %d\r\n"
-					      "   /YStep %d\r\n"
-					      "   /PatternType 1\r\n"
-					      "   /TilingType 1\r\n"
-					      "   /PaintType 1\r\n"
-					      "   /Matrix [ %f %f %f %f %f %f ]\r\n"
-					      "   /Resources << /XObject << /res%d %d 0 R >> >>\r\n",
-					      image->width, image->height,
-					      xstep, ystep,
-					      pdf_p2d.xx, pdf_p2d.yx,
-					      pdf_p2d.xy, pdf_p2d.yy,
-					      pdf_p2d.x0, pdf_p2d.y0,
-					      image_resource.id,
-					      image_resource.id);
+    stream = _cairo_pdf_surface_open_stream (surface,
+					     "   /BBox [0 0 %d %d]\r\n"
+					     "   /XStep %d\r\n"
+					     "   /YStep %d\r\n"
+					     "   /PatternType 1\r\n"
+					     "   /TilingType 1\r\n"
+					     "   /PaintType 1\r\n"
+					     "   /Matrix [ %f %f %f %f %f %f ]\r\n"
+					     "   /Resources << /XObject << /res%d %d 0 R >> >>\r\n",
+					     image->width, image->height,
+					     xstep, ystep,
+					     pdf_p2d.xx, pdf_p2d.yx,
+					     pdf_p2d.xy, pdf_p2d.yy,
+					     pdf_p2d.x0, pdf_p2d.y0,
+					     image_resource.id,
+					     image_resource.id);
 
-    _cairo_output_stream_printf (output,
+    _cairo_output_stream_printf (surface->output,
 				 "q %d 0 0 %d 0 0 cm /res%d Do Q\r\n",
 				 image->width, image->height,
 				 image_resource.id);
 
-    _cairo_pdf_document_close_stream (document);
+    _cairo_pdf_surface_close_stream (surface);
 
-    _cairo_pdf_surface_resume_content_stream (dst);
+    _cairo_pdf_surface_resume_content_stream (surface);
 
-    _cairo_pdf_surface_add_pattern (dst, stream);
+    _cairo_pdf_surface_add_pattern (surface, stream);
 
-    alpha = _cairo_pdf_surface_add_alpha (dst, 1.0);
+    alpha = _cairo_pdf_surface_add_alpha (surface, 1.0);
     /* With some work, we could separate the stroking
      * or non-stroking pattern here as actually needed. */
-    _cairo_output_stream_printf (output,
+    _cairo_output_stream_printf (surface->output,
 				 "/Pattern CS /res%d SCN "
 				 "/Pattern cs /res%d scn "
 				 "/a%d gs\r\n",
@@ -1005,7 +983,6 @@ emit_surface_pattern (cairo_pdf_surface_
     return status;
 }
 
-
 typedef struct _cairo_pdf_color_stop {
     double	  		offset;
     cairo_pdf_resource_t	gradient;
@@ -1013,14 +990,13 @@ typedef struct _cairo_pdf_color_stop {
 } cairo_pdf_color_stop_t;
 
 static cairo_pdf_resource_t
-emit_linear_colorgradient (cairo_pdf_document_t   *document,
-			   cairo_pdf_color_stop_t *stop1, 
-			   cairo_pdf_color_stop_t *stop2)
-{
-    cairo_output_stream_t *output = document->output_stream;
-    cairo_pdf_resource_t function = _cairo_pdf_document_new_object (document);
-    
-    _cairo_output_stream_printf (output,
+emit_linear_colorgradient (cairo_pdf_surface_t		*surface,
+			   cairo_pdf_color_stop_t	*stop1,
+			   cairo_pdf_color_stop_t	*stop2)
+{
+    cairo_pdf_resource_t function = _cairo_pdf_surface_new_object (surface);
+
+    _cairo_output_stream_printf (surface->output,
 				 "%d 0 obj\r\n"
 				 "<< /FunctionType 0\r\n"
 				 "   /Domain [ 0 1 ]\r\n"
@@ -1032,54 +1008,70 @@ emit_linear_colorgradient (cairo_pdf_doc
 				 "stream\r\n",
 				 function.id);
 
-    _cairo_output_stream_write (output, stop1->color_char, 3);
-    _cairo_output_stream_write (output, stop2->color_char, 3);
-    _cairo_output_stream_printf (output,
+    _cairo_output_stream_write (surface->output, stop1->color_char, 3);
+    _cairo_output_stream_write (surface->output, stop2->color_char, 3);
+    _cairo_output_stream_printf (surface->output,
 				 "\r\n"
 				 "endstream\r\n"
 				 "endobj\r\n");
-    
+
     return function;
 }
 
 static cairo_pdf_resource_t
-emit_stiched_colorgradient (cairo_pdf_document_t   *document,
+emit_stiched_colorgradient (cairo_pdf_surface_t   *surface,
 			    unsigned int 	   n_stops,
 			    cairo_pdf_color_stop_t stops[])
 {
-    cairo_output_stream_t *output = document->output_stream;
     cairo_pdf_resource_t function;
     unsigned int i;
-    
+
     /* emit linear gradients between pairs of subsequent stops... */
     for (i = 0; i < n_stops-1; i++) {
-	stops[i].gradient = emit_linear_colorgradient (document, 
-						       &stops[i], 
+	stops[i].gradient = emit_linear_colorgradient (surface,
+						       &stops[i],
 						       &stops[i+1]);
     }
-    
+
     /* ... and stich them together */
-    function = _cairo_pdf_document_new_object (document);
-    _cairo_output_stream_printf (output,
+    function = _cairo_pdf_surface_new_object (surface);
+    _cairo_output_stream_printf (surface->output,
 				 "%d 0 obj\r\n"
 				 "<< /FunctionType 3\r\n"
-				 "   /Domain [ 0 1 ]\r\n"
-				 "   /Functions [ ",
+				 "   /Domain [ 0 1 ]\r\n",
 				 function.id);
+
+    _cairo_output_stream_printf (surface->output,
+				 "   /Functions [ ");
     for (i = 0; i < n_stops-1; i++)
-        _cairo_output_stream_printf (output, "%d 0 R ", stops[i].gradient.id);
-    _cairo_output_stream_printf (output,
-		    		 "]\r\n"
+    {
+        _cairo_output_stream_printf (surface->output,
+				     "%d 0 R ", stops[i].gradient.id);
+    }
+    _cairo_output_stream_printf (surface->output,
+		    		 "]\r\n");
+
+    _cairo_output_stream_printf (surface->output,
 				 "   /Bounds [ ");
     for (i = 1; i < n_stops-1; i++)
-        _cairo_output_stream_printf (output, "%f ", stops[i].offset);
-    _cairo_output_stream_printf (output,
-		    		 "]\r\n"
+    {
+        _cairo_output_stream_printf (surface->output,
+				     "%f ", stops[i].offset);
+    }
+    _cairo_output_stream_printf (surface->output,
+		    		 "]\r\n");
+
+    _cairo_output_stream_printf (surface->output,
 				 "   /Encode [ ");
     for (i = 1; i < n_stops; i++)
-        _cairo_output_stream_printf (output, "0 1 ");
-    _cairo_output_stream_printf (output, 
-	    			 "]\r\n"
+    {
+        _cairo_output_stream_printf (surface->output,
+				     "0 1 ");
+    }
+    _cairo_output_stream_printf (surface->output,
+	    			 "]\r\n");
+
+    _cairo_output_stream_printf (surface->output,
 	    			 ">>\r\n"
 				 "endobj\r\n");
 
@@ -1091,13 +1083,12 @@ emit_stiched_colorgradient (cairo_pdf_do
 static cairo_pdf_resource_t
 emit_pattern_stops (cairo_pdf_surface_t *surface, cairo_gradient_pattern_t *pattern)
 {
-    cairo_pdf_document_t   *document = surface->document;
     cairo_pdf_resource_t    function;
     cairo_pdf_color_stop_t *allstops, *stops;
     unsigned int 	   n_stops;
     unsigned int 	   i;
 
-    function = _cairo_pdf_document_new_object (document);
+    function = _cairo_pdf_surface_new_object (surface);
 
     allstops = malloc ((pattern->n_stops + 2) * sizeof (cairo_pdf_color_stop_t));
     if (allstops == NULL) {
@@ -1107,7 +1098,7 @@ emit_pattern_stops (cairo_pdf_surface_t 
     }
     stops = &allstops[1];
     n_stops = pattern->n_stops;
-    
+
     for (i = 0; i < pattern->n_stops; i++) {
 	stops[i].color_char[0] = pattern->stops[i].color.red   >> 8;
 	stops[i].color_char[1] = pattern->stops[i].color.green >> 8;
@@ -1125,21 +1116,21 @@ emit_pattern_stops (cairo_pdf_surface_t 
 	    n_stops++;
     }
     if (stops[n_stops-1].offset < 1.0 - COLOR_STOP_EPSILLON) {
-	    memcpy (&stops[n_stops], 
-		    &stops[n_stops - 1], 
+	    memcpy (&stops[n_stops],
+		    &stops[n_stops - 1],
 		    sizeof (cairo_pdf_color_stop_t));
 	    stops[n_stops].offset = 1.0;
 	    n_stops++;
     }
-    
+
     if (n_stops == 2) {
 	/* no need for stiched function */
-	function = emit_linear_colorgradient (document, &stops[0], &stops[1]);
+	function = emit_linear_colorgradient (surface, &stops[0], &stops[1]);
     } else {
 	/* multiple stops: stich. XXX possible optimization: regulary spaced
 	 * stops do not require stiching. XXX */
-	function = emit_stiched_colorgradient (document, 
-					       n_stops, 
+	function = emit_stiched_colorgradient (surface,
+					       n_stops,
 					       stops);
     }
 
@@ -1151,8 +1142,6 @@ emit_pattern_stops (cairo_pdf_surface_t 
 static cairo_status_t
 emit_linear_pattern (cairo_pdf_surface_t *surface, cairo_linear_pattern_t *pattern)
 {
-    cairo_pdf_document_t *document = surface->document;
-    cairo_output_stream_t *output = document->output_stream;
     cairo_pdf_resource_t function, pattern_resource, alpha;
     double x0, y0, x1, y1;
     cairo_matrix_t p2u;
@@ -1173,8 +1162,8 @@ emit_linear_pattern (cairo_pdf_surface_t
     y1 = _cairo_fixed_to_double (pattern->gradient.p2.y);
     cairo_matrix_transform_point (&p2u, &x1, &y1);
 
-    pattern_resource = _cairo_pdf_document_new_object (document);
-    _cairo_output_stream_printf (output,
+    pattern_resource = _cairo_pdf_surface_new_object (surface);
+    _cairo_output_stream_printf (surface->output,
 				 "%d 0 obj\r\n"
 				 "<< /Type /Pattern\r\n"
 				 "   /PatternType 2\r\n"
@@ -1189,10 +1178,10 @@ emit_linear_pattern (cairo_pdf_surface_t
 				 ">>\r\n"
 				 "endobj\r\n",
 				 pattern_resource.id,
-				 document->height,
+				 surface->height,
 				 x0, y0, x1, y1,
 				 function.id);
-    
+
     _cairo_pdf_surface_add_pattern (surface, pattern_resource);
 
     alpha = _cairo_pdf_surface_add_alpha (surface, 1.0);
@@ -1200,7 +1189,7 @@ emit_linear_pattern (cairo_pdf_surface_t
     /* Use pattern */
     /* With some work, we could separate the stroking
      * or non-stroking pattern here as actually needed. */
-    _cairo_output_stream_printf (output,
+    _cairo_output_stream_printf (surface->output,
 				 "/Pattern CS /res%d SCN "
 				 "/Pattern cs /res%d scn "
 				 "/a%d gs\r\n",
@@ -1212,12 +1201,10 @@ emit_linear_pattern (cairo_pdf_surface_t
 
     return CAIRO_STATUS_SUCCESS;
 }
-	
+
 static cairo_status_t
 emit_radial_pattern (cairo_pdf_surface_t *surface, cairo_radial_pattern_t *pattern)
 {
-    cairo_pdf_document_t *document = surface->document;
-    cairo_output_stream_t *output = document->output_stream;
     cairo_pdf_resource_t function, pattern_resource, alpha;
     double x0, y0, x1, y1, r0, r1;
     cairo_matrix_t p2u;
@@ -1251,8 +1238,8 @@ emit_radial_pattern (cairo_pdf_surface_t
      * to infinity. Setting extend=true in PDF gives the cairo default
      * behavoir, not yet sure how to implement the cairo mirror and
      * repeat behaviour. */
-    pattern_resource = _cairo_pdf_document_new_object (document);
-    _cairo_output_stream_printf (output,
+    pattern_resource = _cairo_pdf_surface_new_object (surface);
+    _cairo_output_stream_printf (surface->output,
 				 "%d 0 obj\r\n"
 				 "<< /Type /Pattern\r\n"
 				 "   /PatternType 2\r\n"
@@ -1267,10 +1254,10 @@ emit_radial_pattern (cairo_pdf_surface_t
 				 ">>\r\n"
 				 "endobj\r\n",
 				 pattern_resource.id,
-				 document->height,
+				 surface->height,
 				 x0, y0, r0, x1, y1, r1,
 				 function.id);
-    
+
     _cairo_pdf_surface_add_pattern (surface, pattern_resource);
 
     alpha = _cairo_pdf_surface_add_alpha (surface, 1.0);
@@ -1278,7 +1265,7 @@ emit_radial_pattern (cairo_pdf_surface_t
     /* Use pattern */
     /* With some work, we could separate the stroking
      * or non-stroking pattern here as actually needed. */
-    _cairo_output_stream_printf (output,
+    _cairo_output_stream_printf (surface->output,
 				 "/Pattern CS /res%d SCN "
 				 "/Pattern cs /res%d scn "
 				 "/a%d gs\r\n",
@@ -1316,22 +1303,22 @@ emit_pattern (cairo_pdf_surface_t *surfa
 static cairo_status_t
 _cairo_pdf_path_move_to (void *closure, cairo_point_t *point)
 {
-    cairo_output_stream_t *output_stream = closure;
+    cairo_output_stream_t *output = closure;
 
-    _cairo_output_stream_printf (output_stream,
+    _cairo_output_stream_printf (output,
 				 "%f %f m ",
 				 _cairo_fixed_to_double (point->x),
 				 _cairo_fixed_to_double (point->y));
-    
+
     return CAIRO_STATUS_SUCCESS;
 }
 
 static cairo_status_t
 _cairo_pdf_path_line_to (void *closure, cairo_point_t *point)
 {
-    cairo_output_stream_t *output_stream = closure;
-    
-    _cairo_output_stream_printf (output_stream,
+    cairo_output_stream_t *output = closure;
+
+    _cairo_output_stream_printf (output,
 				 "%f %f l ",
 				 _cairo_fixed_to_double (point->x),
 				 _cairo_fixed_to_double (point->y));
@@ -1345,9 +1332,9 @@ _cairo_pdf_path_curve_to (void          
 			  cairo_point_t *c,
 			  cairo_point_t *d)
 {
-    cairo_output_stream_t *output_stream = closure;
+    cairo_output_stream_t *output = closure;
 
-    _cairo_output_stream_printf (output_stream,
+    _cairo_output_stream_printf (output,
 				 "%f %f %f %f %f %f c ",
 				 _cairo_fixed_to_double (b->x),
 				 _cairo_fixed_to_double (b->y),
@@ -1355,16 +1342,16 @@ _cairo_pdf_path_curve_to (void          
 				 _cairo_fixed_to_double (c->y),
 				 _cairo_fixed_to_double (d->x),
 				 _cairo_fixed_to_double (d->y));
-    
+
     return CAIRO_STATUS_SUCCESS;
 }
 
 static cairo_status_t
 _cairo_pdf_path_close_path (void *closure)
 {
-    cairo_output_stream_t *output_stream = closure;
-    
-    _cairo_output_stream_printf (output_stream,
+    cairo_output_stream_t *output = closure;
+
+    _cairo_output_stream_printf (output,
 				 "h\r\n");
 
     return CAIRO_STATUS_SUCCESS;
@@ -1374,19 +1361,17 @@ static cairo_int_status_t
 _cairo_pdf_surface_copy_page (void *abstract_surface)
 {
     cairo_pdf_surface_t *surface = abstract_surface;
-    cairo_pdf_document_t *document = surface->document;
 
-    return _cairo_pdf_document_add_page (document, surface);
+    return _cairo_pdf_surface_write_page (surface);
 }
 
 static cairo_int_status_t
 _cairo_pdf_surface_show_page (void *abstract_surface)
 {
     cairo_pdf_surface_t *surface = abstract_surface;
-    cairo_pdf_document_t *document = surface->document;
     cairo_int_status_t status;
 
-    status = _cairo_pdf_document_add_page (document, surface);
+    status = _cairo_pdf_surface_write_page (surface);
     if (status)
 	return status;
 
@@ -1415,7 +1400,7 @@ _cairo_pdf_surface_get_extents (void		  
 }
 
 typedef struct _pdf_stroke {
-    cairo_output_stream_t   *output_stream;
+    cairo_output_stream_t   *output;
     cairo_matrix_t	    *ctm_inverse;
 } pdf_stroke_t;
 
@@ -1428,7 +1413,7 @@ _cairo_pdf_stroke_move_to (void *closure
 
     cairo_matrix_transform_point (stroke->ctm_inverse, &x, &y);
 
-    _cairo_output_stream_printf (stroke->output_stream,
+    _cairo_output_stream_printf (stroke->output,
 				 "%f %f m ", x, y);
 
     return CAIRO_STATUS_SUCCESS;
@@ -1443,7 +1428,7 @@ _cairo_pdf_stroke_line_to (void *closure
 
     cairo_matrix_transform_point (stroke->ctm_inverse, &x, &y);
 
-    _cairo_output_stream_printf (stroke->output_stream,
+    _cairo_output_stream_printf (stroke->output,
 				 "%f %f l ", x, y);
     return CAIRO_STATUS_SUCCESS;
 }
@@ -1466,7 +1451,7 @@ _cairo_pdf_stroke_curve_to (void        
     cairo_matrix_transform_point (stroke->ctm_inverse, &cx, &cy);
     cairo_matrix_transform_point (stroke->ctm_inverse, &dx, &dy);
 
-    _cairo_output_stream_printf (stroke->output_stream,
+    _cairo_output_stream_printf (stroke->output,
 				 "%f %f %f %f %f %f c ",
 				 bx, by, cx, cy, dx, dy);
     return CAIRO_STATUS_SUCCESS;
@@ -1477,34 +1462,32 @@ _cairo_pdf_stroke_close_path (void *clos
 {
     pdf_stroke_t *stroke = closure;
 
-    _cairo_output_stream_printf (stroke->output_stream,
+    _cairo_output_stream_printf (stroke->output,
 				 "h\r\n");
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 static cairo_int_status_t
-_cairo_pdf_surface_intersect_clip_path (void			*dst,
+_cairo_pdf_surface_intersect_clip_path (void			*abstract_surface,
 					cairo_path_fixed_t	*path,
 					cairo_fill_rule_t	fill_rule,
 					double			tolerance,
 					cairo_antialias_t	antialias)
 {
-    cairo_pdf_surface_t *surface = dst;
-    cairo_pdf_document_t *document = surface->document;
-    cairo_output_stream_t *output = document->output_stream;
+    cairo_pdf_surface_t *surface = abstract_surface;
     cairo_status_t status;
     const char *pdf_operator;
 
     if (path == NULL) {
 	if (surface->has_clip)
-	    _cairo_output_stream_printf (output, "Q\r\n");
+	    _cairo_output_stream_printf (surface->output, "Q\r\n");
 	surface->has_clip = FALSE;
 	return CAIRO_STATUS_SUCCESS;
     }
 
     if (!surface->has_clip) {
-	_cairo_output_stream_printf (output, "q ");
+	_cairo_output_stream_printf (surface->output, "q ");
 	surface->has_clip = TRUE;
     }
 
@@ -1514,7 +1497,7 @@ _cairo_pdf_surface_intersect_clip_path (
 					  _cairo_pdf_path_line_to,
 					  _cairo_pdf_path_curve_to,
 					  _cairo_pdf_path_close_path,
-					  document->output_stream);
+					  surface->output);
 
     switch (fill_rule) {
     case CAIRO_FILL_RULE_WINDING:
@@ -1527,7 +1510,7 @@ _cairo_pdf_surface_intersect_clip_path (
 	ASSERT_NOT_REACHED;
     }
 
-    _cairo_output_stream_printf (document->output_stream,
+    _cairo_output_stream_printf (surface->output,
 				 "%s n\r\n",
 				 pdf_operator);
 
@@ -1544,51 +1527,13 @@ _cairo_pdf_surface_get_font_options (voi
     cairo_font_options_set_hint_metrics (options, CAIRO_HINT_METRICS_OFF);
 }
 
-static cairo_pdf_document_t *
-_cairo_pdf_document_create (cairo_output_stream_t	*output_stream,
-			    double			width,
-			    double			height)
-{
-    cairo_pdf_document_t *document;
-
-    document = malloc (sizeof (cairo_pdf_document_t));
-    if (document == NULL)
-	return NULL;
-
-    document->output_stream = output_stream;
-    document->ref_count = 1;
-    document->owner = NULL;
-    document->finished = FALSE;
-    document->width = width;
-    document->height = height;
-    document->x_dpi = DEFAULT_DPI;
-    document->y_dpi = DEFAULT_DPI;
-
-    _cairo_array_init (&document->objects, sizeof (cairo_pdf_object_t));
-    _cairo_array_init (&document->pages, sizeof (cairo_pdf_resource_t));
-    document->next_available_resource.id = 1;
-
-    document->current_stream.active = FALSE;
-
-    document->pages_resource = _cairo_pdf_document_new_object (document);
-
-    _cairo_array_init (&document->fonts, sizeof (cairo_font_subset_t *));
-
-    /* Document header */
-    _cairo_output_stream_printf (output_stream,
-				 "%%PDF-1.4\r\n");
-
-    return document;
-}
-
 static cairo_pdf_resource_t
-_cairo_pdf_document_write_info (cairo_pdf_document_t *document)
+_cairo_pdf_surface_write_info (cairo_pdf_surface_t *surface)
 {
-    cairo_output_stream_t *output = document->output_stream;
     cairo_pdf_resource_t info;
 
-    info = _cairo_pdf_document_new_object (document);
-    _cairo_output_stream_printf (output,
+    info = _cairo_pdf_surface_new_object (surface);
+    _cairo_output_stream_printf (surface->output,
 				 "%d 0 obj\r\n"
 				 "<< /Creator (cairographics.org)\r\n"
 				 "   /Producer (cairographics.org)\r\n"
@@ -1600,42 +1545,41 @@ _cairo_pdf_document_write_info (cairo_pd
 }
 
 static void
-_cairo_pdf_document_write_pages (cairo_pdf_document_t *document)
+_cairo_pdf_surface_write_pages (cairo_pdf_surface_t *surface)
 {
-    cairo_output_stream_t *stream = document->output_stream;
     cairo_pdf_resource_t page;
     int num_pages, i;
 
-    _cairo_pdf_document_update_object (document, document->pages_resource);
-    _cairo_output_stream_printf (stream,
+    _cairo_pdf_surface_update_object (surface, surface->pages_resource);
+    _cairo_output_stream_printf (surface->output,
 				 "%d 0 obj\r\n"
 				 "<< /Type /Pages\r\n"
 				 "   /Kids [ ",
-				 document->pages_resource.id);
-    
-    num_pages = _cairo_array_num_elements (&document->pages);
+				 surface->pages_resource.id);
+
+    num_pages = _cairo_array_num_elements (&surface->pages);
     for (i = 0; i < num_pages; i++) {
-	_cairo_array_copy_element (&document->pages, i, &page);
-	_cairo_output_stream_printf (stream, "%d 0 R ", page.id);
+	_cairo_array_copy_element (&surface->pages, i, &page);
+	_cairo_output_stream_printf (surface->output, "%d 0 R ", page.id);
     }
 
-    _cairo_output_stream_printf (stream, "]\r\n"); 
-    _cairo_output_stream_printf (stream, "   /Count %d\r\n", num_pages);
+    _cairo_output_stream_printf (surface->output, "]\r\n");
+    _cairo_output_stream_printf (surface->output, "   /Count %d\r\n", num_pages);
 
     /* TODO: Figure out wich other defaults to be inherited by /Page
      * objects. */
-    _cairo_output_stream_printf (stream,
+    _cairo_output_stream_printf (surface->output,
 				 "   /MediaBox [ 0 0 %f %f ]\r\n"
 				 ">>\r\n"
 				 "endobj\r\n",
-				 document->width,
-				 document->height);
+				 surface->width,
+				 surface->height);
 }
 
+#if 0
 static cairo_status_t
-_cairo_pdf_document_write_fonts (cairo_pdf_document_t *document)
+_cairo_pdf_surface_write_fonts (cairo_pdf_surface_t *surface)
 {
-    cairo_output_stream_t *output = document->output_stream;
     cairo_font_subset_t *font;
     cairo_pdf_resource_t font_resource;
     int num_fonts, i, j;
@@ -1645,9 +1589,9 @@ _cairo_pdf_document_write_fonts (cairo_p
     cairo_pdf_resource_t stream, descriptor;
     cairo_status_t status = CAIRO_STATUS_SUCCESS;
 
-    num_fonts = _cairo_array_num_elements (&document->fonts);
+    num_fonts = _cairo_array_num_elements (&surface->fonts);
     for (i = 0; i < num_fonts; i++) {
-	_cairo_array_copy_element (&document->fonts, i, &font);
+	_cairo_array_copy_element (&surface->fonts, i, &font);
 
 	status = _cairo_font_subset_generate (font, &data, &data_size);
 	if (status)
@@ -1659,8 +1603,8 @@ _cairo_pdf_document_write_fonts (cairo_p
 	    goto fail;
 	}
 
-	stream = _cairo_pdf_document_new_object (document);
-	_cairo_output_stream_printf (output,
+	stream = _cairo_pdf_surface_new_object (surface);
+	_cairo_output_stream_printf (surface->output,
 				     "%d 0 obj\r\n"
 				     "<< /Filter /FlateDecode\r\n"
 				     "   /Length %lu\r\n"
@@ -1670,15 +1614,15 @@ _cairo_pdf_document_write_fonts (cairo_p
 				     stream.id,
 				     compressed_size,
 				     data_size);
-	_cairo_output_stream_write (output, compressed, compressed_size);
-	_cairo_output_stream_printf (output,
+	_cairo_output_stream_write (surface->output, compressed, compressed_size);
+	_cairo_output_stream_printf (surface->output,
 				     "\r\n"
 				     "endstream\r\n"
 				     "endobj\r\n");
 	free (compressed);
 
-	descriptor = _cairo_pdf_document_new_object (document);
-	_cairo_output_stream_printf (output,
+	descriptor = _cairo_pdf_surface_new_object (surface);
+	_cairo_output_stream_printf (surface->output,
 				     "%d 0 obj\r\n"
 				     "<< /Type /FontDescriptor\r\n"
 				     "   /FontName /7%s\r\n"
@@ -1704,8 +1648,8 @@ _cairo_pdf_document_write_fonts (cairo_p
 				     stream.id);
 
 	font_resource.id = font->font_id;
-	_cairo_pdf_document_update_object (document, font_resource);
-	_cairo_output_stream_printf (output,
+	_cairo_pdf_surface_update_object (surface, font_resource);
+	_cairo_output_stream_printf (surface->output,
 				     "%d 0 obj\r\n"
 				     "<< /Type /Font\r\n"
 				     "   /Subtype /TrueType\r\n"
@@ -1719,15 +1663,15 @@ _cairo_pdf_document_write_fonts (cairo_p
 				     font->num_glyphs,
 				     descriptor.id);
 
-	_cairo_output_stream_printf (output,
+	_cairo_output_stream_printf (surface->output,
 				     "[");
 
 	for (j = 0; j < font->num_glyphs; j++)
-	    _cairo_output_stream_printf (output,
+	    _cairo_output_stream_printf (surface->output,
 					 " %d",
 					 font->widths[j]);
 
-	_cairo_output_stream_printf (output,
+	_cairo_output_stream_printf (surface->output,
 				     " ]\r\n"
 				     ">>\r\n"
 				     "endobj\r\n");
@@ -1738,245 +1682,158 @@ _cairo_pdf_document_write_fonts (cairo_p
 
     return status;
 }
+#endif
 
 static cairo_pdf_resource_t
-_cairo_pdf_document_write_catalog (cairo_pdf_document_t *document)
+_cairo_pdf_surface_write_catalog (cairo_pdf_surface_t *surface)
 {
-    cairo_output_stream_t *output = document->output_stream;
     cairo_pdf_resource_t catalog;
 
-    catalog = _cairo_pdf_document_new_object (document);
-    _cairo_output_stream_printf (output,
+    catalog = _cairo_pdf_surface_new_object (surface);
+    _cairo_output_stream_printf (surface->output,
 				 "%d 0 obj\r\n"
 				 "<< /Type /Catalog\r\n"
-				 "   /Pages %d 0 R\r\n" 
+				 "   /Pages %d 0 R\r\n"
 				 ">>\r\n"
 				 "endobj\r\n",
 				 catalog.id,
-				 document->pages_resource.id);
+				 surface->pages_resource.id);
 
     return catalog;
 }
 
 static long
-_cairo_pdf_document_write_xref (cairo_pdf_document_t *document)
+_cairo_pdf_surface_write_xref (cairo_pdf_surface_t *surface)
 {
-    cairo_output_stream_t *output = document->output_stream;
     cairo_pdf_object_t *object;
     int num_objects, i;
     long offset;
     char buffer[11];
 
-    num_objects = _cairo_array_num_elements (&document->objects);
+    num_objects = _cairo_array_num_elements (&surface->objects);
 
-    offset = _cairo_output_stream_get_position (output);
-    _cairo_output_stream_printf (output,
+    offset = _cairo_output_stream_get_position (surface->output);
+    _cairo_output_stream_printf (surface->output,
 				 "xref\r\n"
 				 "%d %d\r\n",
 				 0, num_objects + 1);
 
-    _cairo_output_stream_printf (output,
+    _cairo_output_stream_printf (surface->output,
 				 "0000000000 65535 f\r\n");
     for (i = 0; i < num_objects; i++) {
-	object = _cairo_array_index (&document->objects, i);
+	object = _cairo_array_index (&surface->objects, i);
 	snprintf (buffer, sizeof buffer, "%010ld", object->offset);
-	_cairo_output_stream_printf (output,
+	_cairo_output_stream_printf (surface->output,
 				     "%s 00000 n\r\n", buffer);
     }
 
     return offset;
 }
 
-static cairo_pdf_document_t *
-_cairo_pdf_document_reference (cairo_pdf_document_t *document)
-{
-    document->ref_count++;
-
-    return document;
-}
-
-static void
-_cairo_pdf_document_destroy (cairo_pdf_document_t *document)
-{
-    document->ref_count--;
-    if (document->ref_count > 0)
-      return;
-
-    _cairo_pdf_document_finish (document);
-
-    free (document);
-}
-    
-static cairo_status_t
-_cairo_pdf_document_finish (cairo_pdf_document_t *document)
-{
-    cairo_status_t status;
-    cairo_output_stream_t *output = document->output_stream;
-    long offset;
-    cairo_pdf_resource_t info, catalog;
-
-    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);
-    info = _cairo_pdf_document_write_info (document);
-    catalog = _cairo_pdf_document_write_catalog (document);
-    offset = _cairo_pdf_document_write_xref (document);
-    
-    _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_resource.id,
-				 catalog.id,
-				 info.id);
-
-    _cairo_output_stream_printf (output,
-				 "startxref\r\n"
-				 "%ld\r\n"
-				 "%%%%EOF\r\n",
-				 offset);
-
-    status = _cairo_output_stream_get_status (output);
-    _cairo_output_stream_destroy (output);
-
-    _cairo_array_fini (&document->objects);
-    _cairo_array_fini (&document->pages);
-    _cairo_array_fini (&document->fonts);
-
-    document->finished = TRUE;
-
-    return status;
-}
-
 static cairo_status_t
-_cairo_pdf_document_add_page (cairo_pdf_document_t	*document,
-			      cairo_pdf_surface_t	*surface)
+_cairo_pdf_surface_write_page (cairo_pdf_surface_t *surface)
 {
     cairo_status_t status;
     cairo_pdf_resource_t *res;
-    cairo_output_stream_t *output = document->output_stream;
     cairo_pdf_resource_t page;
     double alpha;
     cairo_pdf_resource_t stream;
     int num_streams, num_alphas, num_resources, i;
 
-    assert (!document->finished);
-
     if (surface->has_clip) {
-	_cairo_output_stream_printf (output, "Q\r\n");
+	_cairo_output_stream_printf (surface->output, "Q\r\n");
 	surface->has_clip = FALSE;
     }
 
-    _cairo_pdf_document_close_stream (document);
+    _cairo_pdf_surface_close_stream (surface);
 
-    page = _cairo_pdf_document_new_object (document);
-    _cairo_output_stream_printf (output,
+    page = _cairo_pdf_surface_new_object (surface);
+    _cairo_output_stream_printf (surface->output,
 				 "%d 0 obj\r\n"
 				 "<< /Type /Page\r\n"
 				 "   /Parent %d 0 R\r\n",
 				 page.id,
-				 document->pages_resource.id);
+				 surface->pages_resource.id);
 
-    if (surface->width != document->width ||
-	surface->height != document->height)
+    if (surface->width != surface->width ||
+	surface->height != surface->height)
     {
-	_cairo_output_stream_printf (output,
+	_cairo_output_stream_printf (surface->output,
 				     "   /MediaBox [ 0 0 %f %f ]\r\n",
 				     surface->width,
 				     surface->height);
     }
 
-    _cairo_output_stream_printf (output,
+    _cairo_output_stream_printf (surface->output,
 				 "   /Contents [");
     num_streams = _cairo_array_num_elements (&surface->streams);
     for (i = 0; i < num_streams; i++) {
 	_cairo_array_copy_element (&surface->streams, i, &stream);
-	_cairo_output_stream_printf (output,
+	_cairo_output_stream_printf (surface->output,
 				     " %d 0 R",
 				     stream.id);
     }
-    _cairo_output_stream_printf (output,
+    _cairo_output_stream_printf (surface->output,
 				 " ]\r\n");
 
-    _cairo_output_stream_printf (output,
+    _cairo_output_stream_printf (surface->output,
 				 "   /Resources <<\r\n");
 
-    num_resources =  _cairo_array_num_elements (&surface->fonts);
-    if (num_resources > 0) {
-	_cairo_output_stream_printf (output,
-				     "      /Font <<");
-
-	for (i = 0; i < num_resources; i++) {
-	    res = _cairo_array_index (&surface->fonts, i);
-	    _cairo_output_stream_printf (output,
-					 " /res%d %d 0 R",
-					 res->id, res->id);
-	}
-
-	_cairo_output_stream_printf (output,
-				     " >>\r\n");
-    }
-    
     num_alphas =  _cairo_array_num_elements (&surface->alphas);
     if (num_alphas > 0) {
-	_cairo_output_stream_printf (output,
+	_cairo_output_stream_printf (surface->output,
 				     "      /ExtGState <<\r\n");
 
 	for (i = 0; i < num_alphas; i++) {
 	    /* With some work, we could separate the stroking
 	     * or non-stroking alpha here as actually needed. */
 	    _cairo_array_copy_element (&surface->alphas, i, &alpha);
-	    _cairo_output_stream_printf (output,
+	    _cairo_output_stream_printf (surface->output,
 					 "         /a%d << /CA %f /ca %f >>\r\n",
 					 i, alpha, alpha);
 	}
 
-	_cairo_output_stream_printf (output,
+	_cairo_output_stream_printf (surface->output,
 				     "      >>\r\n");
     }
-    
+
     num_resources = _cairo_array_num_elements (&surface->patterns);
     if (num_resources > 0) {
-	_cairo_output_stream_printf (output,
+	_cairo_output_stream_printf (surface->output,
 				     "      /Pattern <<");
 	for (i = 0; i < num_resources; i++) {
 	    res = _cairo_array_index (&surface->patterns, i);
-	    _cairo_output_stream_printf (output,
+	    _cairo_output_stream_printf (surface->output,
 					 " /res%d %d 0 R",
 					 res->id, res->id);
 	}
 
-	_cairo_output_stream_printf (output,
+	_cairo_output_stream_printf (surface->output,
 				     " >>\r\n");
     }
 
     num_resources = _cairo_array_num_elements (&surface->xobjects);
     if (num_resources > 0) {
-	_cairo_output_stream_printf (output,
+	_cairo_output_stream_printf (surface->output,
 				     "      /XObject <<");
 
 	for (i = 0; i < num_resources; i++) {
 	    res = _cairo_array_index (&surface->xobjects, i);
-	    _cairo_output_stream_printf (output,
+	    _cairo_output_stream_printf (surface->output,
 					 " /res%d %d 0 R",
 					 res->id, res->id);
 	}
 
-	_cairo_output_stream_printf (output,
+	_cairo_output_stream_printf (surface->output,
 				     " >>\r\n");
     }
 
-    _cairo_output_stream_printf (output,
+    _cairo_output_stream_printf (surface->output,
 				 "   >>\r\n"
 				 ">>\r\n"
 				 "endobj\r\n");
 
-    status = _cairo_array_append (&document->pages, &page);
+    status = _cairo_array_append (&surface->pages, &page);
     if (status)
 	return status;
 
@@ -2022,7 +1879,7 @@ _pattern_supported (cairo_pattern_t *pat
 
     if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE)
 	return _surface_pattern_supported ((cairo_surface_pattern_t *) pattern);
-	
+
     return FALSE;
 }
 
@@ -2059,7 +1916,6 @@ _cairo_pdf_surface_paint (void			*abstra
 			  cairo_pattern_t	*source)
 {
     cairo_pdf_surface_t *surface = abstract_surface;
-    cairo_pdf_document_t *document = surface->document;
     cairo_status_t status;
 
     if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
@@ -2079,11 +1935,11 @@ _cairo_pdf_surface_paint (void			*abstra
     if (status)
 	return status;
 
-    _cairo_output_stream_printf (document->output_stream,
+    _cairo_output_stream_printf (surface->output,
 				 "0 0 %f %f re f\r\n",
 				 surface->width, surface->height);
 
-    return _cairo_output_stream_get_status (document->output_stream);
+    return _cairo_output_stream_get_status (surface->output);
 }
 
 static cairo_int_status_t
@@ -2136,35 +1992,34 @@ _cairo_pdf_line_join (cairo_line_join_t 
 
 static cairo_status_t
 _cairo_pdf_surface_emit_stroke_style (cairo_pdf_surface_t	*surface,
-				      cairo_output_stream_t	*stream,
 				      cairo_stroke_style_t	*style)
 {
-    _cairo_output_stream_printf (stream,
+    _cairo_output_stream_printf (surface->output,
 				 "%f w\r\n",
 				 style->line_width);
 
-    _cairo_output_stream_printf (stream,
+    _cairo_output_stream_printf (surface->output,
 				 "%d J\r\n",
 				 _cairo_pdf_line_cap (style->line_cap));
 
-    _cairo_output_stream_printf (stream, 
+    _cairo_output_stream_printf (surface->output,
 				 "%d j\r\n",
 				 _cairo_pdf_line_join (style->line_join));
 
     if (style->num_dashes) {
 	int d;
-	_cairo_output_stream_printf (stream, "[");
+	_cairo_output_stream_printf (surface->output, "[");
 	for (d = 0; d < style->num_dashes; d++)
-	    _cairo_output_stream_printf (stream, " %f", style->dash[d]);
-	_cairo_output_stream_printf (stream, "] %f d\r\n",
+	    _cairo_output_stream_printf (surface->output, " %f", style->dash[d]);
+	_cairo_output_stream_printf (surface->output, "] %f d\r\n",
 				     style->dash_offset);
     }
 
-    _cairo_output_stream_printf (stream,
+    _cairo_output_stream_printf (surface->output,
 				 "%f M ",
 				 style->miter_limit);
 
-    return _cairo_output_stream_get_status (stream);
+    return _cairo_output_stream_get_status (surface->output);
 }
 
 static cairo_int_status_t
@@ -2179,7 +2034,6 @@ _cairo_pdf_surface_stroke (void			*abstr
 			   cairo_antialias_t	 antialias)
 {
     cairo_pdf_surface_t *surface = abstract_surface;
-    cairo_pdf_document_t *document = surface->document;
     pdf_stroke_t stroke;
     cairo_status_t status;
 
@@ -2198,7 +2052,7 @@ _cairo_pdf_surface_stroke (void			*abstr
     if (status)
 	return status;
 
-    stroke.output_stream = document->output_stream;
+    stroke.output = surface->output;
     stroke.ctm_inverse = ctm_inverse;
     status = _cairo_path_fixed_interpret (path,
 					  CAIRO_DIRECTION_FORWARD,
@@ -2207,19 +2061,18 @@ _cairo_pdf_surface_stroke (void			*abstr
 					  _cairo_pdf_stroke_curve_to,
 					  _cairo_pdf_stroke_close_path,
 					  &stroke);
-				 
-    _cairo_output_stream_printf (document->output_stream,
+
+    _cairo_output_stream_printf (surface->output,
 				 "q %f %f %f %f %f %f cm\r\n",
 				 ctm->xx, ctm->yx, ctm->xy, ctm->yy,
 				 ctm->x0, ctm->y0);
 
     status = _cairo_pdf_surface_emit_stroke_style (surface,
-						   document->output_stream,
 						   style);
     if (status)
 	return status;
 
-    _cairo_output_stream_printf (document->output_stream, "S Q\r\n");
+    _cairo_output_stream_printf (surface->output, "S Q\r\n");
 
     return status;
 }
@@ -2234,7 +2087,6 @@ _cairo_pdf_surface_fill (void			*abstrac
 			 cairo_antialias_t	 antialias)
 {
     cairo_pdf_surface_t *surface = abstract_surface;
-    cairo_pdf_document_t *document = surface->document;
     const char *pdf_operator;
     cairo_status_t status;
 
@@ -2259,7 +2111,7 @@ _cairo_pdf_surface_fill (void			*abstrac
 					  _cairo_pdf_path_line_to,
 					  _cairo_pdf_path_curve_to,
 					  _cairo_pdf_path_close_path,
-					  document->output_stream);
+					  surface->output);
 
     switch (fill_rule) {
     case CAIRO_FILL_RULE_WINDING:
@@ -2272,7 +2124,7 @@ _cairo_pdf_surface_fill (void			*abstrac
 	ASSERT_NOT_REACHED;
     }
 
-    _cairo_output_stream_printf (document->output_stream,
+    _cairo_output_stream_printf (surface->output,
 				 "%s\r\n",
 				 pdf_operator);
 
diff-tree d84a1cac1cc2da8a34fb6aa91c3c4f4058527207 (from b7e9506707878367493a8a45c74bb6eb048b7e88)
Author: Carl Worth <cworth at cworth.org>
Date:   Fri May 12 13:31:12 2006 -0700

    PDF: Use cairo_pdf_resource_t more consistently.
    
    Eliminate the named structure cairo_pdf_stream_t. This structure was
    being dynamically allocated, passed around, and leaked when only an ID
    was actually needed to be passed around.
    
    Similarly, many other uses of PDF resources were passing bare unsigned
    int types rather than the safer and more legible cairo_pdf_resource_t.

diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index 9bf1ea8..d0e5ebb 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -88,7 +88,6 @@
 
 typedef struct cairo_pdf_object cairo_pdf_object_t;
 typedef struct cairo_pdf_resource cairo_pdf_resource_t;
-typedef struct cairo_pdf_stream cairo_pdf_stream_t;
 typedef struct cairo_pdf_document cairo_pdf_document_t;
 typedef struct cairo_pdf_surface cairo_pdf_surface_t;
 
@@ -100,12 +99,6 @@ struct cairo_pdf_resource {
     unsigned int id;
 };
 
-struct cairo_pdf_stream {
-    unsigned int id;
-    unsigned int length_id;
-    long start_offset;
-};
-
 struct cairo_pdf_document {
     cairo_output_stream_t *output_stream;
     unsigned long ref_count;
@@ -117,10 +110,15 @@ struct cairo_pdf_document {
     double x_dpi;
     double y_dpi;
 
-    unsigned int next_available_id;
-    unsigned int pages_id;
+    cairo_pdf_resource_t next_available_resource;
+    cairo_pdf_resource_t pages_resource;
 
-    cairo_pdf_stream_t *current_stream;
+    struct {
+	cairo_bool_t active;
+	cairo_pdf_resource_t self;
+	cairo_pdf_resource_t length;
+	long start_offset;
+    } current_stream;
 
     cairo_array_t objects;
     cairo_array_t pages;
@@ -135,7 +133,6 @@ struct cairo_pdf_surface {
     double height;
 
     cairo_pdf_document_t *document;
-    cairo_pdf_stream_t *current_stream;
 
     cairo_array_t patterns;
     cairo_array_t xobjects;
@@ -163,7 +160,7 @@ _cairo_pdf_document_finish (cairo_pdf_do
 static cairo_pdf_document_t *
 _cairo_pdf_document_reference (cairo_pdf_document_t *document);
 
-static unsigned int
+static cairo_pdf_resource_t
 _cairo_pdf_document_new_object (cairo_pdf_document_t *document);
 
 static cairo_status_t
@@ -173,7 +170,7 @@ _cairo_pdf_document_add_page (cairo_pdf_
 static void
 _cairo_pdf_surface_clear (cairo_pdf_surface_t *surface);
 
-static cairo_pdf_stream_t *
+static cairo_pdf_resource_t
 _cairo_pdf_document_open_stream (cairo_pdf_document_t	*document,
 				 const char		*fmt,
 				 ...) CAIRO_PRINTF_FORMAT(2, 3);
@@ -186,73 +183,79 @@ _cairo_pdf_surface_create_for_document (
 					double			height);
 static void
 _cairo_pdf_surface_add_stream (cairo_pdf_surface_t	*surface,
-			       cairo_pdf_stream_t	*stream);
-static void
-_cairo_pdf_surface_ensure_stream (cairo_pdf_surface_t	*surface);
+			       cairo_pdf_resource_t	 stream);
 
 static const cairo_surface_backend_t cairo_pdf_surface_backend;
 static const cairo_paginated_surface_backend_t cairo_pdf_surface_paginated_backend;
 
-static unsigned int
+static cairo_pdf_resource_t
 _cairo_pdf_document_new_object (cairo_pdf_document_t *document)
 {
+    cairo_pdf_resource_t resource;
     cairo_status_t status;
     cairo_pdf_object_t object;
 
     object.offset = _cairo_output_stream_get_position (document->output_stream);
 
     status = _cairo_array_append (&document->objects, &object);
-    if (status)
-	return 0;
+    if (status) {
+	resource.id = 0;
+	return resource;
+    }
 
-    return document->next_available_id++;
+    resource = document->next_available_resource;
+    document->next_available_resource.id++;
+
+    return resource;
 }
 
 static void
 _cairo_pdf_document_update_object (cairo_pdf_document_t *document,
-				   unsigned int id)
+				   cairo_pdf_resource_t	 resource)
 {
     cairo_pdf_object_t *object;
 
-    object = _cairo_array_index (&document->objects, id - 1);
+    object = _cairo_array_index (&document->objects, resource.id - 1);
     object->offset = _cairo_output_stream_get_position (document->output_stream);
 }
 
 static void
 _cairo_pdf_surface_add_stream (cairo_pdf_surface_t	*surface,
-			       cairo_pdf_stream_t	*stream)
+			       cairo_pdf_resource_t	 stream)
 {
     /* XXX: Should be checking the return value here. */
     _cairo_array_append (&surface->streams, &stream);
-    surface->current_stream = stream;
 }
 
 static void
-_cairo_pdf_surface_add_pattern (cairo_pdf_surface_t *surface, unsigned int id)
+_cairo_pdf_surface_add_pattern (cairo_pdf_surface_t	*surface,
+				cairo_pdf_resource_t	 pattern)
 {
-    cairo_pdf_resource_t resource;
-
-    resource.id = id;
     /* XXX: Should be checking the return value here. */
-    _cairo_array_append (&surface->patterns, &resource);
+    _cairo_array_append (&surface->patterns, &pattern);
 }
 
-static unsigned int
+static cairo_pdf_resource_t
 _cairo_pdf_surface_add_alpha (cairo_pdf_surface_t *surface, double alpha)
 {
+    cairo_pdf_resource_t resource;
     int num_alphas, i;
     double other;
 
     num_alphas = _cairo_array_num_elements (&surface->alphas);
     for (i = 0; i < num_alphas; i++) {
 	_cairo_array_copy_element (&surface->alphas, i, &other);
-	if (alpha == other)
-	    return i;
+	if (alpha == other) {
+	    resource.id  = i;
+	    return resource;
+	}
     }
 
     /* XXX: Should be checking the return value here. */
     _cairo_array_append (&surface->alphas, &alpha);
-    return _cairo_array_num_elements (&surface->alphas) - 1;
+
+    resource.id = _cairo_array_num_elements (&surface->alphas) - 1;
+    return resource;
 }
 
 static cairo_surface_t *
@@ -467,7 +470,7 @@ _cairo_pdf_surface_create_for_document (
     surface->height = height;
 
     surface->document = _cairo_pdf_document_reference (document);
-    _cairo_array_init (&surface->streams, sizeof (cairo_pdf_stream_t *));
+    _cairo_array_init (&surface->streams, sizeof (cairo_pdf_resource_t));
     _cairo_array_init (&surface->patterns, sizeof (cairo_pdf_resource_t));
     _cairo_array_init (&surface->xobjects, sizeof (cairo_pdf_resource_t));
     _cairo_array_init (&surface->alphas, sizeof (double));
@@ -482,15 +485,6 @@ _cairo_pdf_surface_create_for_document (
 static void
 _cairo_pdf_surface_clear (cairo_pdf_surface_t *surface)
 {
-    int num_streams, i;
-    cairo_pdf_stream_t *stream;
-
-    num_streams = _cairo_array_num_elements (&surface->streams);
-    for (i = 0; i < num_streams; i++) {
-	_cairo_array_copy_element (&surface->streams, i, &stream);
-	free (stream);
-    }
-
     _cairo_array_truncate (&surface->streams, 0);
     _cairo_array_truncate (&surface->patterns, 0);
     _cairo_array_truncate (&surface->xobjects, 0);
@@ -511,28 +505,23 @@ _cairo_pdf_surface_create_similar (void	
     return cairo_image_surface_create (format, width, height);
 }
 
-static cairo_pdf_stream_t *
+static cairo_pdf_resource_t
 _cairo_pdf_document_open_stream (cairo_pdf_document_t	*document,
 				 const char		*fmt,
 				 ...)
 {
     cairo_output_stream_t *output_stream = document->output_stream;
-    cairo_pdf_stream_t *stream;
     va_list ap;
 
-    stream = malloc (sizeof (cairo_pdf_stream_t));
-    if (stream == NULL) {
-	return NULL;
-    }
-
-    stream->id = _cairo_pdf_document_new_object (document);
-    stream->length_id = _cairo_pdf_document_new_object (document);
+    document->current_stream.active = TRUE;
+    document->current_stream.self = _cairo_pdf_document_new_object (document);
+    document->current_stream.length = _cairo_pdf_document_new_object (document);
 
     _cairo_output_stream_printf (output_stream,
 				 "%d 0 obj\r\n"
 				 "<< /Length %d 0 R\r\n",
-				 stream->id,
-				 stream->length_id);
+				 document->current_stream.self.id,
+				 document->current_stream.length.id);
 
     if (fmt != NULL) {
 	va_start (ap, fmt);
@@ -544,11 +533,9 @@ _cairo_pdf_document_open_stream (cairo_p
 				 ">>\r\n"
 				 "stream\r\n");
 
-    stream->start_offset = _cairo_output_stream_get_position (output_stream);
+    document->current_stream.start_offset = _cairo_output_stream_get_position (output_stream);
 
-    document->current_stream = stream;
-
-    return stream;
+    return document->current_stream.self;
 }
 
 static void
@@ -556,27 +543,26 @@ _cairo_pdf_document_close_stream (cairo_
 {
     cairo_output_stream_t *output_stream = document->output_stream;
     long length;
-    cairo_pdf_stream_t *stream;
 
-    stream = document->current_stream;
-    if (stream == NULL)
+    if (! document->current_stream.active)
 	return;
 
     length = _cairo_output_stream_get_position (output_stream) -
-	stream->start_offset;
+	document->current_stream.start_offset;
     _cairo_output_stream_printf (output_stream,
 				 "endstream\r\n"
 				 "endobj\r\n");
 
-    _cairo_pdf_document_update_object (document, stream->length_id);
+    _cairo_pdf_document_update_object (document,
+				       document->current_stream.length);
     _cairo_output_stream_printf (output_stream,
 				 "%d 0 obj\r\n"
 				 "   %ld\r\n"
 				 "endobj\r\n",
-				 stream->length_id,
+				 document->current_stream.length.id,
 				 length);
 
-    document->current_stream = NULL;
+    document->current_stream.active = FALSE;
 }
 
 static cairo_status_t
@@ -586,8 +572,7 @@ _cairo_pdf_surface_finish (void *abstrac
     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);
+    _cairo_pdf_document_close_stream (document);
 
     if (document->owner == &surface->base)
 	status = _cairo_pdf_document_finish (document);
@@ -605,32 +590,52 @@ _cairo_pdf_surface_finish (void *abstrac
     return status;
 }
 
+static void 
+_cairo_pdf_surface_pause_content_stream (cairo_pdf_surface_t *surface)
+{
+    cairo_pdf_document_t *document = surface->document;
+
+    _cairo_pdf_document_close_stream (document);
+}
+
 static void
-_cairo_pdf_surface_ensure_stream (cairo_pdf_surface_t *surface)
+_cairo_pdf_surface_resume_content_stream (cairo_pdf_surface_t *surface)
 {
     cairo_pdf_document_t *document = surface->document;
-    cairo_pdf_stream_t *stream;
+    cairo_pdf_resource_t stream;
+
+    stream = _cairo_pdf_document_open_stream (document,
+					      "   /Type /XObject\r\n"
+					      "   /Subtype /Form\r\n"
+					      "   /BBox [ 0 0 %f %f ]\r\n",
+					      surface->width,
+					      surface->height);
+
+    _cairo_pdf_surface_add_stream (surface, stream);
+}
+
+static cairo_int_status_t
+_cairo_pdf_surface_start_page (void *abstract_surface)
+{
+    cairo_pdf_surface_t *surface = abstract_surface;
+    cairo_pdf_document_t *document = surface->document;
     cairo_output_stream_t *output = document->output_stream;
+    cairo_pdf_resource_t stream;
 
-    if (document->current_stream == NULL ||
-	document->current_stream != surface->current_stream) {
-	_cairo_pdf_document_close_stream (document);
-	stream = _cairo_pdf_document_open_stream (document,
-						  "   /Type /XObject\r\n"
-						  "   /Subtype /Form\r\n"
-						  "   /BBox [ 0 0 %f %f ]\r\n",
-						  surface->width,
-						  surface->height);
-
-	_cairo_pdf_surface_add_stream (surface, stream);
-
-	/* 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)
-	    _cairo_output_stream_printf (output,
-					 "1 0 0 -1 0 %f cm\r\n",
-					 surface->height);
-    }
+    stream = _cairo_pdf_document_open_stream (document,
+					      "   /Type /XObject\r\n"
+					      "   /Subtype /Form\r\n"
+					      "   /BBox [ 0 0 %f %f ]\r\n",
+					      surface->width,
+					      surface->height);
+
+    _cairo_pdf_surface_add_stream (surface, stream);
+
+    _cairo_output_stream_printf (output,
+				 "1 0 0 -1 0 %f cm\r\n",
+				 surface->height);
+
+    return CAIRO_STATUS_SUCCESS;
 }
 
 static void *
@@ -659,11 +664,10 @@ compress_dup (const void *data, unsigned
 static cairo_status_t
 emit_smask (cairo_pdf_document_t	*document,
 	    cairo_image_surface_t	*image,
-	    unsigned int		*id_ret)
+	    cairo_pdf_resource_t	*stream_ret)
 {
     cairo_status_t status = CAIRO_STATUS_SUCCESS;
     cairo_output_stream_t *output = document->output_stream;
-    cairo_pdf_stream_t *smask_stream;
     char *alpha, *alpha_compressed;
     unsigned long alpha_size, alpha_compressed_size;
     pixman_bits_t *pixel;
@@ -696,7 +700,7 @@ emit_smask (cairo_pdf_document_t	*docume
 
     /* Bail out without emitting smask if it's all opaque. */
     if (opaque) {
-	*id_ret = 0;
+	stream_ret->id = 0;
 	goto CLEANUP_ALPHA;
     }
 
@@ -707,21 +711,19 @@ emit_smask (cairo_pdf_document_t	*docume
 	
     }
 
-    smask_stream = _cairo_pdf_document_open_stream (document,
-						    "   /Type /XObject\r\n"
-						    "   /Subtype /Image\r\n"
-						    "   /Width %d\r\n"
-						    "   /Height %d\r\n"
-						    "   /ColorSpace /DeviceGray\r\n"
-						    "   /BitsPerComponent 8\r\n"
-						    "   /Filter /FlateDecode\r\n",
-						    image->width, image->height);
+    *stream_ret = _cairo_pdf_document_open_stream (document,
+						   "   /Type /XObject\r\n"
+						   "   /Subtype /Image\r\n"
+						   "   /Width %d\r\n"
+						   "   /Height %d\r\n"
+						   "   /ColorSpace /DeviceGray\r\n"
+						   "   /BitsPerComponent 8\r\n"
+						   "   /Filter /FlateDecode\r\n",
+						   image->width, image->height);
     _cairo_output_stream_write (output, alpha_compressed, alpha_compressed_size);
     _cairo_output_stream_printf (output, "\r\n");
     _cairo_pdf_document_close_stream (document);
 
-    *id_ret = smask_stream->id;
-
     free (alpha_compressed);
  CLEANUP_ALPHA:
     free (alpha);
@@ -735,18 +737,22 @@ emit_smask (cairo_pdf_document_t	*docume
 static cairo_status_t
 emit_image (cairo_pdf_document_t	*document,
 	    cairo_image_surface_t	*image,
-	    unsigned int		*id_ret)
+	    cairo_pdf_resource_t	*image_ret)
 {
     cairo_status_t status = CAIRO_STATUS_SUCCESS;
     cairo_output_stream_t *output = document->output_stream;
-    cairo_pdf_stream_t *image_stream;
     char *rgb, *compressed;
     unsigned long rgb_size, compressed_size;
     pixman_bits_t *pixel;
     int i, x, y;
-    unsigned int smask_id = 0; /* just to squelch a warning */
+    cairo_pdf_resource_t smask;
     cairo_bool_t need_smask;
 
+    /* XXX: Need to rewrite this as a pdf_surface function with
+     * pause/resume of content_stream, (currently the only caller does
+     * the pause/resume already, but that is expected to change in the
+     * future). */
+
     /* These are the only image formats we currently support, (which
      * makes things a lot simpler here). This is enforeced through
      * _analyze_operation which only accept source surfaces of
@@ -791,8 +797,6 @@ emit_image (cairo_pdf_document_t	*docume
 	}
     }
 
-    _cairo_pdf_document_close_stream (document);
-
     compressed = compress_dup (rgb, rgb_size, &compressed_size);
     if (compressed == NULL) {
 	status = CAIRO_STATUS_NO_MEMORY;
@@ -801,11 +805,11 @@ emit_image (cairo_pdf_document_t	*docume
 
     need_smask = FALSE;
     if (image->format == CAIRO_FORMAT_ARGB32) {
-	status = emit_smask (document, image, &smask_id);
+	status = emit_smask (document, image, &smask);
 	if (status)
 	    goto CLEANUP_COMPRESSED;
 
-	if (smask_id)
+	if (smask.id)
 	    need_smask = TRUE;
     }
 
@@ -819,15 +823,15 @@ emit_image (cairo_pdf_document_t	*docume
 
 
     if (need_smask)
-	image_stream = _cairo_pdf_document_open_stream (document,
-							IMAGE_DICTIONARY
-							"   /SMask %d 0 R\r\n",
-							image->width, image->height,
-							smask_id);
+	*image_ret = _cairo_pdf_document_open_stream (document,
+						      IMAGE_DICTIONARY
+						      "   /SMask %d 0 R\r\n",
+						      image->width, image->height,
+						      smask.id);
     else
-	image_stream = _cairo_pdf_document_open_stream (document,
-							IMAGE_DICTIONARY,
-							image->width, image->height);
+	*image_ret = _cairo_pdf_document_open_stream (document,
+						      IMAGE_DICTIONARY,
+						      image->width, image->height);
 
 #undef IMAGE_DICTIONARY
 
@@ -835,8 +839,6 @@ emit_image (cairo_pdf_document_t	*docume
     _cairo_output_stream_printf (output, "\r\n");
     _cairo_pdf_document_close_stream (document);
 
-    *id_ret = image_stream->id;
-
  CLEANUP_COMPRESSED:
     free (compressed);
  CLEANUP_RGB:
@@ -851,10 +853,10 @@ emit_solid_pattern (cairo_pdf_surface_t 
 {
     cairo_pdf_document_t *document = surface->document;
     cairo_output_stream_t *output = document->output_stream;
-    unsigned int alpha;
+    cairo_pdf_resource_t alpha;
 
     alpha = _cairo_pdf_surface_add_alpha (surface, pattern->color.alpha);
-    _cairo_pdf_surface_ensure_stream (surface);
+
     /* With some work, we could separate the stroking
      * or non-stroking color here as actually needed. */
     _cairo_output_stream_printf (output,
@@ -867,7 +869,7 @@ emit_solid_pattern (cairo_pdf_surface_t 
 				 pattern->color.red,
 				 pattern->color.green,
 				 pattern->color.blue,
-				 alpha);
+				 alpha.id);
 
     return CAIRO_STATUS_SUCCESS;
 }
@@ -878,11 +880,11 @@ emit_surface_pattern (cairo_pdf_surface_
 {
     cairo_pdf_document_t *document = dst->document;
     cairo_output_stream_t *output = document->output_stream;
-    cairo_pdf_stream_t *stream;
+    cairo_pdf_resource_t stream;
     cairo_image_surface_t *image;
     void *image_extra;
     cairo_status_t status = CAIRO_STATUS_SUCCESS;
-    unsigned int alpha, id = 0; /* just to squelch a warning */
+    cairo_pdf_resource_t alpha, image_resource;
     cairo_matrix_t cairo_p2d, pdf_p2d;
     cairo_extend_t extend = cairo_pattern_get_extend (&pattern->base);
     int xstep, ystep;
@@ -890,13 +892,13 @@ emit_surface_pattern (cairo_pdf_surface_
 
     /* XXX: Should do something clever here for PDF source surfaces ? */
 
+    _cairo_pdf_surface_pause_content_stream (dst);
+
     status = _cairo_surface_acquire_source_image (pattern->surface, &image, &image_extra);
     if (status)
 	return status;
 
-    _cairo_pdf_document_close_stream (document);
-
-    status = emit_image (dst->document, image, &id);
+    status = emit_image (dst->document, image, &image_resource);
     if (status)
 	goto BAIL;
 
@@ -974,16 +976,20 @@ emit_surface_pattern (cairo_pdf_surface_
 					      pdf_p2d.xx, pdf_p2d.yx,
 					      pdf_p2d.xy, pdf_p2d.yy,
 					      pdf_p2d.x0, pdf_p2d.y0,
-					      id, id);
+					      image_resource.id,
+					      image_resource.id);
 
     _cairo_output_stream_printf (output,
 				 "q %d 0 0 %d 0 0 cm /res%d Do Q\r\n",
 				 image->width, image->height,
-				 id);
+				 image_resource.id);
 
-    _cairo_pdf_surface_add_pattern (dst, stream->id);
+    _cairo_pdf_document_close_stream (document);
+
+    _cairo_pdf_surface_resume_content_stream (dst);
+
+    _cairo_pdf_surface_add_pattern (dst, stream);
 
-    _cairo_pdf_surface_ensure_stream (dst);
     alpha = _cairo_pdf_surface_add_alpha (dst, 1.0);
     /* With some work, we could separate the stroking
      * or non-stroking pattern here as actually needed. */
@@ -991,7 +997,7 @@ emit_surface_pattern (cairo_pdf_surface_
 				 "/Pattern CS /res%d SCN "
 				 "/Pattern cs /res%d scn "
 				 "/a%d gs\r\n",
-				 stream->id, stream->id, alpha);
+				 stream.id, stream.id, alpha.id);
 
  BAIL:
     _cairo_surface_release_source_image (pattern->surface, image, image_extra);
@@ -1001,19 +1007,18 @@ emit_surface_pattern (cairo_pdf_surface_
 
 
 typedef struct _cairo_pdf_color_stop {
-    double	  offset;
-    unsigned int  gradient_id;
-    unsigned char color_char[4];
+    double	  		offset;
+    cairo_pdf_resource_t	gradient;
+    unsigned char		color_char[4];
 } cairo_pdf_color_stop_t;
 
-
-static unsigned int
+static cairo_pdf_resource_t
 emit_linear_colorgradient (cairo_pdf_document_t   *document,
 			   cairo_pdf_color_stop_t *stop1, 
 			   cairo_pdf_color_stop_t *stop2)
 {
     cairo_output_stream_t *output = document->output_stream;
-    unsigned int function_id = _cairo_pdf_document_new_object (document);
+    cairo_pdf_resource_t function = _cairo_pdf_document_new_object (document);
     
     _cairo_output_stream_printf (output,
 				 "%d 0 obj\r\n"
@@ -1025,7 +1030,7 @@ emit_linear_colorgradient (cairo_pdf_doc
 				 "   /Length 6\r\n"
 				 ">>\r\n"
 				 "stream\r\n",
-				 function_id);
+				 function.id);
 
     _cairo_output_stream_write (output, stop1->color_char, 3);
     _cairo_output_stream_write (output, stop2->color_char, 3);
@@ -1034,36 +1039,35 @@ emit_linear_colorgradient (cairo_pdf_doc
 				 "endstream\r\n"
 				 "endobj\r\n");
     
-    return function_id;
+    return function;
 }
 
-
-static unsigned int
+static cairo_pdf_resource_t
 emit_stiched_colorgradient (cairo_pdf_document_t   *document,
 			    unsigned int 	   n_stops,
 			    cairo_pdf_color_stop_t stops[])
 {
     cairo_output_stream_t *output = document->output_stream;
-    unsigned int function_id;
+    cairo_pdf_resource_t function;
     unsigned int i;
     
     /* emit linear gradients between pairs of subsequent stops... */
     for (i = 0; i < n_stops-1; i++) {
-	stops[i].gradient_id = emit_linear_colorgradient (document, 
-		    					  &stops[i], 
-							  &stops[i+1]);
+	stops[i].gradient = emit_linear_colorgradient (document, 
+						       &stops[i], 
+						       &stops[i+1]);
     }
     
     /* ... and stich them together */
-    function_id = _cairo_pdf_document_new_object (document);
+    function = _cairo_pdf_document_new_object (document);
     _cairo_output_stream_printf (output,
 				 "%d 0 obj\r\n"
 				 "<< /FunctionType 3\r\n"
 				 "   /Domain [ 0 1 ]\r\n"
 				 "   /Functions [ ",
-				 function_id);
+				 function.id);
     for (i = 0; i < n_stops-1; i++)
-        _cairo_output_stream_printf (output, "%d 0 R ", stops[i].gradient_id);
+        _cairo_output_stream_printf (output, "%d 0 R ", stops[i].gradient.id);
     _cairo_output_stream_printf (output,
 		    		 "]\r\n"
 				 "   /Bounds [ ");
@@ -1079,26 +1083,27 @@ emit_stiched_colorgradient (cairo_pdf_do
 	    			 ">>\r\n"
 				 "endobj\r\n");
 
-    return function_id;
+    return function;
 }
 
 #define COLOR_STOP_EPSILLON 1e-6
 
-static unsigned int
+static cairo_pdf_resource_t
 emit_pattern_stops (cairo_pdf_surface_t *surface, cairo_gradient_pattern_t *pattern)
 {
     cairo_pdf_document_t   *document = surface->document;
-    unsigned int	   function_id;
+    cairo_pdf_resource_t    function;
     cairo_pdf_color_stop_t *allstops, *stops;
     unsigned int 	   n_stops;
     unsigned int 	   i;
 
-    function_id = _cairo_pdf_document_new_object (document);
+    function = _cairo_pdf_document_new_object (document);
 
     allstops = malloc ((pattern->n_stops + 2) * sizeof (cairo_pdf_color_stop_t));
     if (allstops == NULL) {
 	_cairo_error (CAIRO_STATUS_NO_MEMORY);
-	return 0;
+	function.id = 0;
+	return function;
     }
     stops = &allstops[1];
     n_stops = pattern->n_stops;
@@ -1129,18 +1134,18 @@ emit_pattern_stops (cairo_pdf_surface_t 
     
     if (n_stops == 2) {
 	/* no need for stiched function */
-	function_id = emit_linear_colorgradient (document, &stops[0], &stops[1]);
+	function = emit_linear_colorgradient (document, &stops[0], &stops[1]);
     } else {
 	/* multiple stops: stich. XXX possible optimization: regulary spaced
 	 * stops do not require stiching. XXX */
-	function_id = emit_stiched_colorgradient (document, 
-						  n_stops, 
-						  stops);
+	function = emit_stiched_colorgradient (document, 
+					       n_stops, 
+					       stops);
     }
 
     free (allstops);
 
-    return function_id;
+    return function;
 }
 
 static cairo_status_t
@@ -1148,14 +1153,14 @@ emit_linear_pattern (cairo_pdf_surface_t
 {
     cairo_pdf_document_t *document = surface->document;
     cairo_output_stream_t *output = document->output_stream;
-    unsigned int function_id, pattern_id, alpha;
+    cairo_pdf_resource_t function, pattern_resource, alpha;
     double x0, y0, x1, y1;
     cairo_matrix_t p2u;
 
-    _cairo_pdf_document_close_stream (document);
+    _cairo_pdf_surface_pause_content_stream (surface);
 
-    function_id = emit_pattern_stops (surface, &pattern->base);
-    if (function_id == 0)
+    function = emit_pattern_stops (surface, &pattern->base);
+    if (function.id == 0)
 	return CAIRO_STATUS_NO_MEMORY;
 
     p2u = pattern->base.base.matrix;
@@ -1168,7 +1173,7 @@ emit_linear_pattern (cairo_pdf_surface_t
     y1 = _cairo_fixed_to_double (pattern->gradient.p2.y);
     cairo_matrix_transform_point (&p2u, &x1, &y1);
 
-    pattern_id = _cairo_pdf_document_new_object (document);
+    pattern_resource = _cairo_pdf_document_new_object (document);
     _cairo_output_stream_printf (output,
 				 "%d 0 obj\r\n"
 				 "<< /Type /Pattern\r\n"
@@ -1183,14 +1188,13 @@ emit_linear_pattern (cairo_pdf_surface_t
 				 "      >>\r\n"
 				 ">>\r\n"
 				 "endobj\r\n",
-				 pattern_id,
+				 pattern_resource.id,
 				 document->height,
 				 x0, y0, x1, y1,
-				 function_id);
+				 function.id);
     
-    _cairo_pdf_surface_add_pattern (surface, pattern_id);
+    _cairo_pdf_surface_add_pattern (surface, pattern_resource);
 
-    _cairo_pdf_surface_ensure_stream (surface);
     alpha = _cairo_pdf_surface_add_alpha (surface, 1.0);
 
     /* Use pattern */
@@ -1200,7 +1204,11 @@ emit_linear_pattern (cairo_pdf_surface_t
 				 "/Pattern CS /res%d SCN "
 				 "/Pattern cs /res%d scn "
 				 "/a%d gs\r\n",
-				 pattern_id, pattern_id, alpha);
+				 pattern_resource.id,
+				 pattern_resource.id,
+				 alpha.id);
+
+    _cairo_pdf_surface_resume_content_stream (surface);
 
     return CAIRO_STATUS_SUCCESS;
 }
@@ -1210,14 +1218,14 @@ emit_radial_pattern (cairo_pdf_surface_t
 {
     cairo_pdf_document_t *document = surface->document;
     cairo_output_stream_t *output = document->output_stream;
-    unsigned int function_id, pattern_id, alpha;
+    cairo_pdf_resource_t function, pattern_resource, alpha;
     double x0, y0, x1, y1, r0, r1;
     cairo_matrix_t p2u;
 
-    _cairo_pdf_document_close_stream (document);
+    _cairo_pdf_surface_pause_content_stream (surface);
 
-    function_id = emit_pattern_stops (surface, &pattern->base);
-    if (function_id == 0)
+    function = emit_pattern_stops (surface, &pattern->base);
+    if (function.id == 0)
 	return CAIRO_STATUS_NO_MEMORY;
 
     p2u = pattern->base.base.matrix;
@@ -1243,7 +1251,7 @@ emit_radial_pattern (cairo_pdf_surface_t
      * to infinity. Setting extend=true in PDF gives the cairo default
      * behavoir, not yet sure how to implement the cairo mirror and
      * repeat behaviour. */
-    pattern_id = _cairo_pdf_document_new_object (document);
+    pattern_resource = _cairo_pdf_document_new_object (document);
     _cairo_output_stream_printf (output,
 				 "%d 0 obj\r\n"
 				 "<< /Type /Pattern\r\n"
@@ -1258,14 +1266,13 @@ emit_radial_pattern (cairo_pdf_surface_t
 				 "      >>\r\n"
 				 ">>\r\n"
 				 "endobj\r\n",
-				 pattern_id,
+				 pattern_resource.id,
 				 document->height,
 				 x0, y0, r0, x1, y1, r1,
-				 function_id);
+				 function.id);
     
-    _cairo_pdf_surface_add_pattern (surface, pattern_id);
+    _cairo_pdf_surface_add_pattern (surface, pattern_resource);
 
-    _cairo_pdf_surface_ensure_stream (surface);
     alpha = _cairo_pdf_surface_add_alpha (surface, 1.0);
 
     /* Use pattern */
@@ -1275,7 +1282,11 @@ emit_radial_pattern (cairo_pdf_surface_t
 				 "/Pattern CS /res%d SCN "
 				 "/Pattern cs /res%d scn "
 				 "/a%d gs\r\n",
-				 pattern_id, pattern_id, alpha);
+				 pattern_resource.id,
+				 pattern_resource.id,
+				 alpha.id);
+
+    _cairo_pdf_surface_resume_content_stream (surface);
 
     return CAIRO_STATUS_SUCCESS;
 }
@@ -1295,6 +1306,7 @@ emit_pattern (cairo_pdf_surface_t *surfa
 
     case CAIRO_PATTERN_TYPE_RADIAL:
 	return emit_radial_pattern (surface, (cairo_radial_pattern_t *) pattern);
+
     }
 
     ASSERT_NOT_REACHED;
@@ -1484,8 +1496,6 @@ _cairo_pdf_surface_intersect_clip_path (
     cairo_status_t status;
     const char *pdf_operator;
 
-    _cairo_pdf_surface_ensure_stream (surface);
-
     if (path == NULL) {
 	if (surface->has_clip)
 	    _cairo_output_stream_printf (output, "Q\r\n");
@@ -1555,12 +1565,12 @@ _cairo_pdf_document_create (cairo_output
     document->y_dpi = DEFAULT_DPI;
 
     _cairo_array_init (&document->objects, sizeof (cairo_pdf_object_t));
-    _cairo_array_init (&document->pages, sizeof (unsigned int));
-    document->next_available_id = 1;
+    _cairo_array_init (&document->pages, sizeof (cairo_pdf_resource_t));
+    document->next_available_resource.id = 1;
 
-    document->current_stream = NULL;
+    document->current_stream.active = FALSE;
 
-    document->pages_id = _cairo_pdf_document_new_object (document);
+    document->pages_resource = _cairo_pdf_document_new_object (document);
 
     _cairo_array_init (&document->fonts, sizeof (cairo_font_subset_t *));
 
@@ -1571,42 +1581,42 @@ _cairo_pdf_document_create (cairo_output
     return document;
 }
 
-static unsigned int
+static cairo_pdf_resource_t
 _cairo_pdf_document_write_info (cairo_pdf_document_t *document)
 {
     cairo_output_stream_t *output = document->output_stream;
-    unsigned int id;
+    cairo_pdf_resource_t info;
 
-    id = _cairo_pdf_document_new_object (document);
+    info = _cairo_pdf_document_new_object (document);
     _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);
+				 info.id);
 
-    return id;
+    return info;
 }
 
 static void
 _cairo_pdf_document_write_pages (cairo_pdf_document_t *document)
 {
     cairo_output_stream_t *stream = document->output_stream;
-    unsigned int page_id;
+    cairo_pdf_resource_t page;
     int num_pages, i;
 
-    _cairo_pdf_document_update_object (document, document->pages_id);
+    _cairo_pdf_document_update_object (document, document->pages_resource);
     _cairo_output_stream_printf (stream,
 				 "%d 0 obj\r\n"
 				 "<< /Type /Pages\r\n"
 				 "   /Kids [ ",
-				 document->pages_id);
+				 document->pages_resource.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);
-	_cairo_output_stream_printf (stream, "%d 0 R ", page_id);
+	_cairo_array_copy_element (&document->pages, i, &page);
+	_cairo_output_stream_printf (stream, "%d 0 R ", page.id);
     }
 
     _cairo_output_stream_printf (stream, "]\r\n"); 
@@ -1627,11 +1637,12 @@ _cairo_pdf_document_write_fonts (cairo_p
 {
     cairo_output_stream_t *output = document->output_stream;
     cairo_font_subset_t *font;
+    cairo_pdf_resource_t font_resource;
     int num_fonts, i, j;
     const char *data;
     char *compressed;
     unsigned long data_size, compressed_size;
-    unsigned int stream_id, descriptor_id;
+    cairo_pdf_resource_t stream, descriptor;
     cairo_status_t status = CAIRO_STATUS_SUCCESS;
 
     num_fonts = _cairo_array_num_elements (&document->fonts);
@@ -1648,7 +1659,7 @@ _cairo_pdf_document_write_fonts (cairo_p
 	    goto fail;
 	}
 
-	stream_id = _cairo_pdf_document_new_object (document);
+	stream = _cairo_pdf_document_new_object (document);
 	_cairo_output_stream_printf (output,
 				     "%d 0 obj\r\n"
 				     "<< /Filter /FlateDecode\r\n"
@@ -1656,7 +1667,7 @@ _cairo_pdf_document_write_fonts (cairo_p
 				     "   /Length1 %lu\r\n"
 				     ">>\r\n"
 				     "stream\r\n",
-				     stream_id,
+				     stream.id,
 				     compressed_size,
 				     data_size);
 	_cairo_output_stream_write (output, compressed, compressed_size);
@@ -1666,7 +1677,7 @@ _cairo_pdf_document_write_fonts (cairo_p
 				     "endobj\r\n");
 	free (compressed);
 
-	descriptor_id = _cairo_pdf_document_new_object (document);
+	descriptor = _cairo_pdf_document_new_object (document);
 	_cairo_output_stream_printf (output,
 				     "%d 0 obj\r\n"
 				     "<< /Type /FontDescriptor\r\n"
@@ -1682,7 +1693,7 @@ _cairo_pdf_document_write_fonts (cairo_p
 				     "   /FontFile2 %u 0 R\r\n"
 				     ">>\r\n"
 				     "endobj\r\n",
-				     descriptor_id,
+				     descriptor.id,
 				     font->base_font,
 				     font->x_min,
 				     font->y_min,
@@ -1690,9 +1701,10 @@ _cairo_pdf_document_write_fonts (cairo_p
 				     font->y_max,
 				     font->ascent,
 				     font->descent,
-				     stream_id);
+				     stream.id);
 
-	_cairo_pdf_document_update_object (document, font->font_id);
+	font_resource.id = font->font_id;
+	_cairo_pdf_document_update_object (document, font_resource);
 	_cairo_output_stream_printf (output,
 				     "%d 0 obj\r\n"
 				     "<< /Type /Font\r\n"
@@ -1705,7 +1717,7 @@ _cairo_pdf_document_write_fonts (cairo_p
 				     font->font_id,
 				     font->base_font,
 				     font->num_glyphs,
-				     descriptor_id);
+				     descriptor.id);
 
 	_cairo_output_stream_printf (output,
 				     "[");
@@ -1727,22 +1739,23 @@ _cairo_pdf_document_write_fonts (cairo_p
     return status;
 }
 
-static unsigned int
+static cairo_pdf_resource_t
 _cairo_pdf_document_write_catalog (cairo_pdf_document_t *document)
 {
     cairo_output_stream_t *output = document->output_stream;
-    unsigned int id;
+    cairo_pdf_resource_t catalog;
 
-    id = _cairo_pdf_document_new_object (document);
+    catalog = _cairo_pdf_document_new_object (document);
     _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);
+				 catalog.id,
+				 document->pages_resource.id);
 
-    return id;
+    return catalog;
 }
 
 static long
@@ -1800,7 +1813,7 @@ _cairo_pdf_document_finish (cairo_pdf_do
     cairo_status_t status;
     cairo_output_stream_t *output = document->output_stream;
     long offset;
-    unsigned int info_id, catalog_id;
+    cairo_pdf_resource_t info, catalog;
 
     if (document->finished)
 	return CAIRO_STATUS_SUCCESS;
@@ -1808,8 +1821,8 @@ _cairo_pdf_document_finish (cairo_pdf_do
     _cairo_pdf_document_close_stream (document);
     _cairo_pdf_document_write_pages (document);
     _cairo_pdf_document_write_fonts (document);
-    info_id = _cairo_pdf_document_write_info (document);
-    catalog_id = _cairo_pdf_document_write_catalog (document);
+    info = _cairo_pdf_document_write_info (document);
+    catalog = _cairo_pdf_document_write_catalog (document);
     offset = _cairo_pdf_document_write_xref (document);
     
     _cairo_output_stream_printf (output,
@@ -1818,9 +1831,9 @@ _cairo_pdf_document_finish (cairo_pdf_do
 				 "   /Root %d 0 R\r\n"
 				 "   /Info %d 0 R\r\n"
 				 ">>\r\n",
-				 document->next_available_id,
-				 catalog_id,
-				 info_id);
+				 document->next_available_resource.id,
+				 catalog.id,
+				 info.id);
 
     _cairo_output_stream_printf (output,
 				 "startxref\r\n"
@@ -1845,17 +1858,15 @@ _cairo_pdf_document_add_page (cairo_pdf_
 			      cairo_pdf_surface_t	*surface)
 {
     cairo_status_t status;
-    cairo_pdf_stream_t *stream;
     cairo_pdf_resource_t *res;
     cairo_output_stream_t *output = document->output_stream;
-    unsigned int page_id;
+    cairo_pdf_resource_t page;
     double alpha;
+    cairo_pdf_resource_t stream;
     int num_streams, num_alphas, num_resources, i;
 
     assert (!document->finished);
 
-    _cairo_pdf_surface_ensure_stream (surface);
-
     if (surface->has_clip) {
 	_cairo_output_stream_printf (output, "Q\r\n");
 	surface->has_clip = FALSE;
@@ -1863,13 +1874,13 @@ _cairo_pdf_document_add_page (cairo_pdf_
 
     _cairo_pdf_document_close_stream (document);
 
-    page_id = _cairo_pdf_document_new_object (document);
+    page = _cairo_pdf_document_new_object (document);
     _cairo_output_stream_printf (output,
 				 "%d 0 obj\r\n"
 				 "<< /Type /Page\r\n"
 				 "   /Parent %d 0 R\r\n",
-				 page_id,
-				 document->pages_id);
+				 page.id,
+				 document->pages_resource.id);
 
     if (surface->width != document->width ||
 	surface->height != document->height)
@@ -1884,15 +1895,14 @@ _cairo_pdf_document_add_page (cairo_pdf_
 				 "   /Contents [");
     num_streams = _cairo_array_num_elements (&surface->streams);
     for (i = 0; i < num_streams; i++) {
-	_cairo_array_copy_element (&surface->streams, i, &stream);	
+	_cairo_array_copy_element (&surface->streams, i, &stream);
 	_cairo_output_stream_printf (output,
 				     " %d 0 R",
-				     stream->id);
+				     stream.id);
     }
     _cairo_output_stream_printf (output,
 				 " ]\r\n");
 
-
     _cairo_output_stream_printf (output,
 				 "   /Resources <<\r\n");
 
@@ -1966,7 +1976,7 @@ _cairo_pdf_document_add_page (cairo_pdf_
 				 ">>\r\n"
 				 "endobj\r\n");
 
-    status = _cairo_array_append (&document->pages, &page_id);
+    status = _cairo_array_append (&document->pages, &page);
     if (status)
 	return status;
 
@@ -2069,12 +2079,6 @@ _cairo_pdf_surface_paint (void			*abstra
     if (status)
 	return status;
 
-    /* After emitting the pattern the current stream should belong to
-     * this surface, so no need to _cairo_pdf_surface_ensure_stream()
-     */
-    assert (document->current_stream != NULL &&
-	    document->current_stream == surface->current_stream);
-
     _cairo_output_stream_printf (document->output_stream,
 				 "0 0 %f %f re f\r\n",
 				 surface->width, surface->height);
@@ -2194,12 +2198,6 @@ _cairo_pdf_surface_stroke (void			*abstr
     if (status)
 	return status;
 
-    /* After emitting the pattern the current stream should belong to
-     * this surface, so no need to _cairo_pdf_surface_ensure_stream()
-     */
-    assert (document->current_stream != NULL &&
-	    document->current_stream == surface->current_stream);
-
     stroke.output_stream = document->output_stream;
     stroke.ctm_inverse = ctm_inverse;
     status = _cairo_path_fixed_interpret (path,
@@ -2255,12 +2253,6 @@ _cairo_pdf_surface_fill (void			*abstrac
     if (status)
 	return status;
 
-    /* After emitting the pattern the current stream should belong to
-     * this surface, so no need to _cairo_pdf_surface_ensure_stream()
-     */
-    assert (document->current_stream != NULL &&
-	    document->current_stream == surface->current_stream);
-
     status = _cairo_path_fixed_interpret (path,
 					  CAIRO_DIRECTION_FORWARD,
 					  _cairo_pdf_path_move_to,
@@ -2296,7 +2288,6 @@ _cairo_pdf_surface_show_glyphs (void			*
 				cairo_scaled_font_t	*scaled_font)
 {
     cairo_pdf_surface_t *surface = abstract_surface;
-    cairo_pdf_document_t *document = surface->document;
     cairo_path_fixed_t path;
     cairo_status_t status;
 
@@ -2309,12 +2300,6 @@ _cairo_pdf_surface_show_glyphs (void			*
     if (status)
 	return status;
 
-    /* After emitting the pattern the current stream should belong to
-     * this surface, so no need to _cairo_pdf_surface_ensure_stream()
-     */
-    assert (document->current_stream != NULL &&
-	    document->current_stream == surface->current_stream);
-
     _cairo_path_fixed_init (&path);
     _cairo_scaled_font_glyph_path (scaled_font, glyphs, num_glyphs, &path);
     status = _cairo_pdf_surface_fill (surface, op, source,
@@ -2369,6 +2354,6 @@ static const cairo_surface_backend_t cai
 };
 
 static const cairo_paginated_surface_backend_t cairo_pdf_surface_paginated_backend = {
-    NULL, /* start_page */
+    _cairo_pdf_surface_start_page,
     _cairo_pdf_surface_set_paginated_mode
 };


More information about the cairo-commit mailing list