[cairo-commit] src/cairo-ps-surface.c

Adrian Johnson ajohnson at kemper.freedesktop.org
Sun Aug 14 02:51:57 PDT 2011


 src/cairo-ps-surface.c |  109 +++++++++++++++++++++++++++++++++----------------
 1 file changed, 74 insertions(+), 35 deletions(-)

New commits:
commit 79aa04fd50463629b3ab2e2efbcd8084038f6c09
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Sun Aug 14 19:19:34 2011 +0930

    ps: use deflate compression for ps level 3

diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c
index a9961fe..02909b2 100644
--- a/src/cairo-ps-surface.c
+++ b/src/cairo-ps-surface.c
@@ -108,6 +108,12 @@
  * This macro can be used to conditionally compile backend-specific code.
  */
 
+typedef enum {
+    CAIRO_PS_COMPRESS_NONE,
+    CAIRO_PS_COMPRESS_LZW,
+    CAIRO_PS_COMPRESS_DEFLATE
+ } cairo_ps_compress_t;
+
 static const cairo_surface_backend_t cairo_ps_surface_backend;
 static const cairo_paginated_surface_backend_t cairo_ps_surface_paginated_backend;
 
@@ -2044,9 +2050,12 @@ static cairo_status_t
 _cairo_ps_surface_emit_base85_string (cairo_ps_surface_t    *surface,
 				      const unsigned char   *data,
 				      unsigned long	     length,
+				      cairo_ps_compress_t    compress,
 				      cairo_bool_t           use_strings)
 {
-    cairo_output_stream_t *base85_stream, *string_array_stream;
+    cairo_output_stream_t *base85_stream, *string_array_stream, *deflate_stream;
+    unsigned char *data_compressed;
+    unsigned long data_compressed_size;
     cairo_status_t status, status2;
 
     if (use_strings)
@@ -2065,8 +2074,39 @@ _cairo_ps_surface_emit_base85_string (cairo_ps_surface_t    *surface,
 	return _cairo_output_stream_destroy (base85_stream);
     }
 
-    _cairo_output_stream_write (base85_stream, data, length);
+    switch (compress) {
+	case CAIRO_PS_COMPRESS_NONE:
+	    _cairo_output_stream_write (base85_stream, data, length);
+	    break;
+
+	case CAIRO_PS_COMPRESS_LZW:
+	    /* XXX: Should fix cairo-lzw to provide a stream-based interface
+	     * instead. */
+	    data_compressed_size = length;
+	    data_compressed = _cairo_lzw_compress ((unsigned char*)data, &data_compressed_size);
+	    if (unlikely (data_compressed == NULL)) {
+		status = _cairo_output_stream_destroy (string_array_stream);
+		status = _cairo_output_stream_destroy (base85_stream);
+		return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+	    }
+	    _cairo_output_stream_write (base85_stream, data_compressed, data_compressed_size);
+	    free (data_compressed);
+	    break;
 
+	case CAIRO_PS_COMPRESS_DEFLATE:
+	    deflate_stream = _cairo_deflate_stream_create (base85_stream);
+	    if (_cairo_output_stream_get_status (deflate_stream)) {
+		return _cairo_output_stream_destroy (deflate_stream);
+	    }
+	    _cairo_output_stream_write (deflate_stream, data, length);
+	    status = _cairo_output_stream_destroy (deflate_stream);
+	    if (unlikely (status)) {
+		status2 = _cairo_output_stream_destroy (string_array_stream);
+		status2 = _cairo_output_stream_destroy (base85_stream);
+		return _cairo_output_stream_destroy (deflate_stream);
+	    }
+	    break;
+    }
     status = _cairo_output_stream_destroy (base85_stream);
 
     /* Mark end of base85 data */
@@ -2075,7 +2115,6 @@ _cairo_ps_surface_emit_base85_string (cairo_ps_surface_t    *surface,
     if (status == CAIRO_STATUS_SUCCESS)
 	status = status2;
 
-
     return status;
 }
 
@@ -2086,8 +2125,8 @@ _cairo_ps_surface_emit_image (cairo_ps_surface_t    *surface,
 			      cairo_filter_t         filter)
 {
     cairo_status_t status;
-    unsigned char *data, *data_compressed;
-    unsigned long data_size, data_compressed_size;
+    unsigned char *data;
+    unsigned long data_size;
     cairo_image_surface_t *ps_image = image;
     int x, y, i;
     cairo_image_transparency_t transparency;
@@ -2096,6 +2135,8 @@ _cairo_ps_surface_emit_image (cairo_ps_surface_t    *surface,
     int bit;
     cairo_image_color_t color;
     const char *interpolate;
+    cairo_ps_compress_t compress;
+    const char *compress_filter;
 
     if (image->base.status)
 	return image->base.status;
@@ -2244,13 +2285,13 @@ _cairo_ps_surface_emit_image (cairo_ps_surface_t    *surface,
 	}
     }
 
-    /* XXX: Should fix cairo-lzw to provide a stream-based interface
-     * instead. */
-    data_compressed_size = data_size;
-    data_compressed = _cairo_lzw_compress (data, &data_compressed_size);
-    if (unlikely (data_compressed == NULL)) {
-	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
-	goto bail2;
+    if (surface->ps_level == CAIRO_PS_LEVEL_2) {
+	compress = CAIRO_PS_COMPRESS_LZW;
+	compress_filter = "LZWDecode";
+    } else {
+	compress = CAIRO_PS_COMPRESS_DEFLATE;
+	compress_filter = "FlateDecode";
+	surface->ps_level_used = CAIRO_PS_LEVEL_3;
     }
 
     if (surface->use_string_datasource) {
@@ -2260,11 +2301,12 @@ _cairo_ps_surface_emit_image (cairo_ps_surface_t    *surface,
 				     "/CairoImageData [\n");
 
 	status = _cairo_ps_surface_emit_base85_string (surface,
-						       data_compressed,
-						       data_compressed_size,
+						       data,
+						       data_size,
+						       compress,
 						       TRUE);
 	if (unlikely (status))
-	    goto bail3;
+	    goto bail2;
 
 	_cairo_output_stream_printf (surface->stream,
 				     "] def\n");
@@ -2300,10 +2342,12 @@ _cairo_ps_surface_emit_image (cairo_ps_surface_t    *surface,
 					 "	/CairoImageDataIndex CairoImageDataIndex 1 add def\n"
 					 "	CairoImageDataIndex CairoImageData length 1 sub gt\n"
 					 "       { /CairoImageDataIndex 0 def } if\n"
-					 "    } /ASCII85Decode filter /LZWDecode filter def\n");
+					 "    } /ASCII85Decode filter /%s filter def\n",
+					 compress_filter);
 	} else {
 	    _cairo_output_stream_printf (surface->stream,
-					 "    /DataSource currentfile /ASCII85Decode filter /LZWDecode filter def\n");
+					 "    /DataSource currentfile /ASCII85Decode filter /%s filter def\n",
+					 compress_filter);
 	}
 
 	_cairo_output_stream_printf (surface->stream,
@@ -2349,10 +2393,12 @@ _cairo_ps_surface_emit_image (cairo_ps_surface_t    *surface,
 					 "    /CairoImageDataIndex CairoImageDataIndex 1 add def\n"
 					 "    CairoImageDataIndex CairoImageData length 1 sub gt\n"
 					 "     { /CairoImageDataIndex 0 def } if\n"
-					 "  } /ASCII85Decode filter /LZWDecode filter def\n");
+					 "  } /ASCII85Decode filter /%s filter def\n",
+					 compress_filter);
 	} else {
 	    _cairo_output_stream_printf (surface->stream,
-					 "  /DataSource currentfile /ASCII85Decode filter /LZWDecode filter def\n");
+					 "  /DataSource currentfile /ASCII85Decode filter /%s filter def\n",
+					 compress_filter);
 	}
 
 	_cairo_output_stream_printf (surface->stream,
@@ -2368,17 +2414,15 @@ _cairo_ps_surface_emit_image (cairo_ps_surface_t    *surface,
 	/* Emit the image data as a base85-encoded string which will
 	 * be used as the data source for the image operator. */
 	status = _cairo_ps_surface_emit_base85_string (surface,
-						       data_compressed,
-						       data_compressed_size,
+						       data,
+						       data_size,
+						       compress,
 						       FALSE);
 	_cairo_output_stream_printf (surface->stream, "\n");
     } else {
 	status = CAIRO_STATUS_SUCCESS;
     }
 
-bail3:
-    free (data_compressed);
-
 bail2:
     free (data);
 
@@ -2423,6 +2467,7 @@ _cairo_ps_surface_emit_jpeg_image (cairo_ps_surface_t    *surface,
 	status = _cairo_ps_surface_emit_base85_string (surface,
 						       mime_data,
 						       mime_data_length,
+						       CAIRO_PS_COMPRESS_NONE,
 						       TRUE);
 	if (unlikely (status))
 	    return status;
@@ -2472,6 +2517,7 @@ _cairo_ps_surface_emit_jpeg_image (cairo_ps_surface_t    *surface,
 	status = _cairo_ps_surface_emit_base85_string (surface,
 						       mime_data,
 						       mime_data_length,
+						       CAIRO_PS_COMPRESS_NONE,
 						       FALSE);
     }
 
@@ -3446,8 +3492,6 @@ _cairo_ps_surface_emit_mesh_pattern (cairo_ps_surface_t     *surface,
     cairo_matrix_t pat_to_ps;
     cairo_status_t status;
     cairo_pdf_shading_t shading;
-    unsigned char *data_compressed;
-    unsigned long data_compressed_size;
     int i;
 
     if (_cairo_array_num_elements (&pattern->patches) == 0)
@@ -3469,7 +3513,7 @@ _cairo_ps_surface_emit_mesh_pattern (cairo_ps_surface_t     *surface,
 				 "   /Shading\n"
 				 "   << /ShadingType %d\n"
 				 "      /ColorSpace /DeviceRGB\n"
-				 "      /DataSource currentfile /ASCII85Decode filter /LZWDecode filter\n"
+				 "      /DataSource currentfile /ASCII85Decode filter /FlateDecode filter\n"
 				 "      /BitsPerCoordinate %d\n"
 				 "      /BitsPerComponent %d\n"
 				 "      /BitsPerFlag %d\n"
@@ -3495,20 +3539,15 @@ _cairo_ps_surface_emit_mesh_pattern (cairo_ps_surface_t     *surface,
     _cairo_output_stream_printf (surface->stream,
 				 "makepattern\n");
 
-    data_compressed_size = shading.data_length;
-    data_compressed = _cairo_lzw_compress (shading.data, &data_compressed_size);
-    if (unlikely (data_compressed == NULL))
-	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
     status = _cairo_ps_surface_emit_base85_string (surface,
-						   data_compressed,
-						   data_compressed_size,
+						   shading.data,
+						   shading.data_length,
+						   CAIRO_PS_COMPRESS_DEFLATE,
 						   FALSE);
     _cairo_output_stream_printf (surface->stream,
 				 "\n"
 				 "setpattern\n");
 
-    free (data_compressed);
     _cairo_pdf_shading_fini (&shading);
 
     return status;


More information about the cairo-commit mailing list