[cairo-commit] 2 commits - src/cairo-base85-stream.c src/cairoint.h src/cairo-output-stream.c src/cairo-pdf-surface.c src/cairo-ps-surface.c src/cairo-svg-surface.c src/Makefile.am

Carl Worth cworth at kemper.freedesktop.org
Tue Apr 4 09:14:08 PDT 2006


 src/Makefile.am           |    1 
 src/cairo-base85-stream.c |  160 ++++++++++++++++++++++++++++++++++++++++++++++
 src/cairo-output-stream.c |  115 +++++++++------------------------
 src/cairo-pdf-surface.c   |    2 
 src/cairo-ps-surface.c    |   22 ++++--
 src/cairo-svg-surface.c   |    2 
 src/cairoint.h            |   23 ++++--
 7 files changed, 228 insertions(+), 97 deletions(-)

New commits:
diff-tree 5a06133eb2e13a4c0354dad7f7da414c85733c4e (from 57fe9b17b0a1a36acf0d8d524df05215ea48361f)
Author: Carl Worth <cworth at raht.cworth.org>
Date:   Mon Apr 3 23:44:51 2006 -0700

    Implement cairo-base85-stream as a filtering output stream not just a write function.
    
    Now _cairo_output_stream_create accepts a new close callback, (which
    the base85 stream uses to write its trailer). This eliminates the
    former kludge used to fclose the stdio output streams, and required a
    bit of touchup to the pdf, ps, and svg-surface usage of streams.

diff --git a/src/cairo-base85-stream.c b/src/cairo-base85-stream.c
index 0bb6f32..6adfa16 100644
--- a/src/cairo-base85-stream.c
+++ b/src/cairo-base85-stream.c
@@ -36,63 +36,125 @@
 
 #include "cairoint.h"
 
-static cairo_bool_t
-_convert_four_tuple (const unsigned char *four_tuple, char five_tuple[5])
+typedef struct _cairo_base85_stream {
+    cairo_output_stream_t *output;
+    unsigned char four_tuple[4];
+    int pending;
+    int column;
+} cairo_base85_stream_t;
+
+static void
+_expand_four_tuple_to_five (unsigned char four_tuple[4],
+			    unsigned char five_tuple[5],
+			    cairo_bool_t *all_zero)
 {
-    cairo_bool_t all_zero;
     uint32_t value;
     int digit, i;
     
     value = four_tuple[0] << 24 | four_tuple[1] << 16 | four_tuple[2] << 8 | four_tuple[3];
-    all_zero = TRUE;
+    if (all_zero)
+	*all_zero = TRUE;
     for (i = 0; i < 5; i++) {
 	digit = value % 85;
-	if (digit != 0)
-	    all_zero = FALSE;
+	if (digit != 0 && all_zero)
+	    *all_zero = FALSE;
 	five_tuple[4-i] = digit + 33;
 	value = value / 85;
     }
-    return all_zero;
 }
 
-void
-_cairo_output_stream_write_base85_string (cairo_output_stream_t *stream,
-					  const char *data,
-					  size_t length)
+static cairo_status_t
+_cairo_base85_wrap_perhaps (cairo_base85_stream_t *stream)
 {
-    unsigned char *ptr;
-    unsigned char four_tuple[4];
-    char five_tuple[5];
-    int column;
-    
-    ptr = (unsigned char *)data;
-    column = 0;
-    while (length > 0) {
-	if (length >= 4) {
-	    if (_convert_four_tuple (ptr, five_tuple)) {
-		column += 1;
-		_cairo_output_stream_write (stream, "z", 1);
+    cairo_status_t status;
+
+    if (stream->column >= 72) {
+	status = _cairo_output_stream_write (stream->output, "\n", 1);
+	if (status)
+	    return status;
+	stream->column = 0;
+    }
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+_cairo_base85_stream_write_data (void			*closure,
+				 const unsigned char	*data,
+				 unsigned int		 length)
+{
+    cairo_status_t status;
+    cairo_base85_stream_t *stream = closure;
+    const unsigned char *ptr = data;
+    unsigned char five_tuple[5];
+    cairo_bool_t is_zero;
+
+    while (length) {
+	stream->four_tuple[stream->pending++] = *ptr++;
+	length--;
+	if (stream->pending == 4) {
+	    _expand_four_tuple_to_five (stream->four_tuple, five_tuple, &is_zero);
+	    if (is_zero) {
+		status = _cairo_output_stream_write (stream->output, "z", 1);
+		stream->column += 1;
 	    } else {
-		column += 5;
-		_cairo_output_stream_write (stream, five_tuple, 5);
+		status = _cairo_output_stream_write (stream->output, five_tuple, 5);
+		stream->column += 5;
 	    }
-	    length -= 4;
-	    ptr += 4;
-	} else { /* length < 4 */
-	    memset (four_tuple, 0, 4);
-	    memcpy (four_tuple, ptr, length);
-	    _convert_four_tuple (four_tuple, five_tuple);
-	    column += length + 1;
-	    _cairo_output_stream_write (stream, five_tuple, length + 1);
-	    length = 0;
-	}
-	if (column >= 72) {
-	    _cairo_output_stream_write (stream, "\n", 1);
-	    column = 0;
+	    if (status)
+		return status;
+	    status = _cairo_base85_wrap_perhaps (stream);
+	    if (status)
+		return status;
+	    stream->pending = 0;
 	}
     }
 
-    if (column > 0) {
-	_cairo_output_stream_write (stream, "\n", 1);
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+_cairo_base85_stream_close (void *closure)
+{
+    cairo_status_t status;
+    cairo_base85_stream_t *stream = closure;
+    unsigned char five_tuple[5];
+
+    if (stream->pending) {
+	memset (stream->four_tuple + stream->pending, 0, 4 - stream->pending);
+	_expand_four_tuple_to_five (stream->four_tuple, five_tuple, NULL);
+	status = _cairo_output_stream_write (stream->output, five_tuple, stream->pending + 1);
+	if (status)
+	    return status;
+	stream->column += stream->pending + 1;
+	status = _cairo_base85_wrap_perhaps (stream);
+	if (status)
+	    return status;
     }
+
+    /* Mark end of base85 data */
+    status = _cairo_output_stream_printf (stream->output, "~>\n");
+    if (status)
+	return status;
+
+    return CAIRO_STATUS_SUCCESS;
 }
+
+cairo_output_stream_t *
+_cairo_base85_stream_create (cairo_output_stream_t *output)
+{
+    cairo_base85_stream_t *stream;
+
+    stream = malloc (sizeof (cairo_base85_stream_t));
+    if (stream == NULL)
+	return NULL;
+
+    stream->output = output;
+    stream->pending = 0;
+    stream->column = 0;
+
+    return _cairo_output_stream_create (_cairo_base85_stream_write_data,
+					_cairo_base85_stream_close,
+					stream);
+}
+
diff --git a/src/cairo-output-stream.c b/src/cairo-output-stream.c
index b07423c..1ed569c 100644
--- a/src/cairo-output-stream.c
+++ b/src/cairo-output-stream.c
@@ -45,14 +45,15 @@
 
 struct _cairo_output_stream {
     cairo_write_func_t		write_data;
+    cairo_close_func_t		close_func;
     void			*closure;
-    cairo_bool_t		owns_closure_is_file;
     unsigned long		position;
     cairo_status_t		status;
 };
 
 cairo_output_stream_t *
 _cairo_output_stream_create (cairo_write_func_t		write_data,
+			     cairo_close_func_t		close_func,
 			     void			*closure)
 {
     cairo_output_stream_t *stream;
@@ -62,23 +63,25 @@ _cairo_output_stream_create (cairo_write
 	return NULL;
 
     stream->write_data = write_data;
+    stream->close_func = close_func;
     stream->closure = closure;
-    stream->owns_closure_is_file = FALSE;
     stream->position = 0;
     stream->status = CAIRO_STATUS_SUCCESS;
 
     return stream;
 }
 
-void
+cairo_status_t
 _cairo_output_stream_destroy (cairo_output_stream_t *stream)
 {
-    if (stream->owns_closure_is_file) {
-	FILE *file = stream->closure;
-	fflush (file);
-	fclose (file);
-    }
+    cairo_status_t status = CAIRO_STATUS_SUCCESS;
+
+    if (stream->close_func)
+	status = stream->close_func (stream->closure);
+
     free (stream);
+
+    return status;
 }
 
 cairo_status_t
@@ -286,30 +289,39 @@ _cairo_output_stream_get_status (cairo_o
 static cairo_status_t
 stdio_write (void *closure, const unsigned char *data, unsigned int length)
 {
-    FILE *fp = closure;
+    FILE *file = closure;
 
-    if (fwrite (data, 1, length, fp) == length)
-	return CAIRO_STATUS_SUCCESS;
+    if (fwrite (data, 1, length, file) != length)
+	return CAIRO_STATUS_WRITE_ERROR;
 
-    return CAIRO_STATUS_WRITE_ERROR;
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+stdio_close (void *closure)
+{
+    FILE *file = closure;
+
+    fflush (file);
+    fclose (file);
+
+    return CAIRO_STATUS_SUCCESS;
 }
 
 cairo_output_stream_t *
 _cairo_output_stream_create_for_file (const char *filename)
 {
-    FILE *fp;
+    FILE *file;
     cairo_output_stream_t *stream;
 
-    fp = fopen (filename, "wb");
-    if (fp == NULL)
+    file = fopen (filename, "wb");
+    if (file == NULL)
 	return NULL;
     
-    stream = _cairo_output_stream_create (stdio_write, fp);
+    stream = _cairo_output_stream_create (stdio_write, stdio_close, file);
 
-    if (stream)
-	stream->owns_closure_is_file = TRUE;
-    else
-	fclose (fp);
+    if (stream == NULL)
+	fclose (file);
 
     return stream;
 }
diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index 6d18196..4a783b5 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -335,7 +335,7 @@ cairo_pdf_surface_create_for_stream (cai
 {
     cairo_output_stream_t *stream;
 
-    stream = _cairo_output_stream_create (write, closure);
+    stream = _cairo_output_stream_create (write, NULL, closure);
     if (stream == NULL) {
 	_cairo_error (CAIRO_STATUS_NO_MEMORY);
 	return (cairo_surface_t*) &_cairo_surface_nil;
diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c
index a646d45..4242a1e 100644
--- a/src/cairo-ps-surface.c
+++ b/src/cairo-ps-surface.c
@@ -218,7 +218,7 @@ cairo_ps_surface_create_for_stream (cair
 {
     cairo_output_stream_t *stream;
 
-    stream = _cairo_output_stream_create (write_func, closure);
+    stream = _cairo_output_stream_create (write_func, NULL, closure);
     if (stream == NULL) {
 	_cairo_error (CAIRO_STATUS_NO_MEMORY);
 	return (cairo_surface_t*) &_cairo_surface_nil;
@@ -667,6 +667,7 @@ emit_image (cairo_ps_surface_t    *surfa
     cairo_pattern_union_t pattern;
     cairo_matrix_t d2i;
     int x, y, i;
+    cairo_output_stream_t *base85_stream;
 
     /* PostScript can not represent the alpha channel, so we blend the
        current image over a white RGB surface to eliminate it. */
@@ -756,12 +757,21 @@ emit_image (cairo_ps_surface_t    *surfa
 				 d2i.x0, d2i.y0);
 
     /* Compressed image data (Base85 encoded) */
-    _cairo_output_stream_write_base85_string (surface->stream, (char *)compressed, compressed_size);
-    status = CAIRO_STATUS_SUCCESS;
+    base85_stream = _cairo_base85_stream_create (surface->stream);
+    if (base85_stream == NULL) {
+	status = CAIRO_STATUS_NO_MEMORY;
+	goto bail3;
+    }
 
-    /* Mark end of base85 data */
-    _cairo_output_stream_printf (surface->stream,
-				 "~>\n");
+    status = _cairo_output_stream_write (base85_stream, compressed, compressed_size);
+    if (status) {
+	_cairo_output_stream_destroy (base85_stream);
+	goto bail3;
+    }
+
+    status = _cairo_output_stream_destroy (base85_stream);
+
+ bail3:
     free (compressed);
  bail2:
     free (rgb);
diff --git a/src/cairo-svg-surface.c b/src/cairo-svg-surface.c
index d413408..7c38464 100644
--- a/src/cairo-svg-surface.c
+++ b/src/cairo-svg-surface.c
@@ -145,7 +145,7 @@ cairo_svg_surface_create_for_stream (cai
 {
     cairo_output_stream_t *stream;
 
-    stream = _cairo_output_stream_create (write, closure);
+    stream = _cairo_output_stream_create (write, NULL, closure);
     if (stream == NULL)
 	return NULL;
 
diff --git a/src/cairoint.h b/src/cairoint.h
index 3dc0f7e..4203599 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -2124,11 +2124,23 @@ _cairo_utf8_to_utf16 (const unsigned cha
 
 typedef struct _cairo_output_stream cairo_output_stream_t;
 
+/* We already have the following declared in cairo.h:
+
+typedef cairo_status_t (*cairo_write_func_t) (void		  *closure,
+					      const unsigned char *data,
+					      unsigned int	   length);
+*/
+typedef cairo_status_t (*cairo_close_func_t) (void *closure);
+
 cairo_private cairo_output_stream_t *
 _cairo_output_stream_create (cairo_write_func_t		write_func,
+			     cairo_close_func_t		close_func,
 			     void			*closure);
 
-cairo_private void
+/* Most cairo destroy functions don't return a status, but we do here
+ * to allow the return status from the close_func callback to be
+ * captured. */
+cairo_private cairo_status_t
 _cairo_output_stream_destroy (cairo_output_stream_t *stream);
 
 cairo_private cairo_status_t
@@ -2140,11 +2152,6 @@ _cairo_output_stream_write_hex_string (c
 				       const char *data,
 				       size_t length);
 
-cairo_private void
-_cairo_output_stream_write_base85_string (cairo_output_stream_t *stream,
-					  const char *data,
-					  size_t length);
-
 unsigned char *
 _cairo_lzw_compress (unsigned char *data, unsigned long *data_size_in_out);
 
@@ -2165,6 +2172,10 @@ _cairo_output_stream_get_status (cairo_o
 cairo_private cairo_output_stream_t *
 _cairo_output_stream_create_for_file (const char *filename);
 
+/* cairo_base85_stream.c */
+cairo_output_stream_t *
+_cairo_base85_stream_create (cairo_output_stream_t *output);
+
 cairo_private void
 _cairo_error (cairo_status_t status);
 
diff-tree 57fe9b17b0a1a36acf0d8d524df05215ea48361f (from 9bdb4f6ff713db0d101a0c0735dbb27e54fd7846)
Author: Carl Worth <cworth at raht.cworth.org>
Date:   Mon Apr 3 15:26:17 2006 -0700

    Move base85 code out of cairo-output-stream.c into new cairo-base85-stream.c

diff --git a/src/Makefile.am b/src/Makefile.am
index ad18568..5b3d75f 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -134,6 +134,7 @@ libcairo_la_SOURCES =				\
 	cairo-arc.c				\
 	cairo-arc-private.h			\
 	cairo-array.c				\
+	cairo-base85-stream.c			\
 	cairo-cache.c				\
 	cairo-cache-private.h			\
 	cairo-clip.c				\
diff --git a/src/cairo-base85-stream.c b/src/cairo-base85-stream.c
new file mode 100644
index 0000000..0bb6f32
--- /dev/null
+++ b/src/cairo-base85-stream.c
@@ -0,0 +1,98 @@
+/* cairo_output_stream.c: Output stream abstraction
+ * 
+ * Copyright © 2005 Red Hat, Inc
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ * The Original Code is cairo_output_stream.c as distributed with the
+ *   cairo graphics library.
+ *
+ * The Initial Developer of the Original Code is Red Hat, Inc.
+ *
+ * Author(s):
+ *	Kristian Høgsberg <krh at redhat.com>
+ */
+
+#include "cairoint.h"
+
+static cairo_bool_t
+_convert_four_tuple (const unsigned char *four_tuple, char five_tuple[5])
+{
+    cairo_bool_t all_zero;
+    uint32_t value;
+    int digit, i;
+    
+    value = four_tuple[0] << 24 | four_tuple[1] << 16 | four_tuple[2] << 8 | four_tuple[3];
+    all_zero = TRUE;
+    for (i = 0; i < 5; i++) {
+	digit = value % 85;
+	if (digit != 0)
+	    all_zero = FALSE;
+	five_tuple[4-i] = digit + 33;
+	value = value / 85;
+    }
+    return all_zero;
+}
+
+void
+_cairo_output_stream_write_base85_string (cairo_output_stream_t *stream,
+					  const char *data,
+					  size_t length)
+{
+    unsigned char *ptr;
+    unsigned char four_tuple[4];
+    char five_tuple[5];
+    int column;
+    
+    ptr = (unsigned char *)data;
+    column = 0;
+    while (length > 0) {
+	if (length >= 4) {
+	    if (_convert_four_tuple (ptr, five_tuple)) {
+		column += 1;
+		_cairo_output_stream_write (stream, "z", 1);
+	    } else {
+		column += 5;
+		_cairo_output_stream_write (stream, five_tuple, 5);
+	    }
+	    length -= 4;
+	    ptr += 4;
+	} else { /* length < 4 */
+	    memset (four_tuple, 0, 4);
+	    memcpy (four_tuple, ptr, length);
+	    _convert_four_tuple (four_tuple, five_tuple);
+	    column += length + 1;
+	    _cairo_output_stream_write (stream, five_tuple, length + 1);
+	    length = 0;
+	}
+	if (column >= 72) {
+	    _cairo_output_stream_write (stream, "\n", 1);
+	    column = 0;
+	}
+    }
+
+    if (column > 0) {
+	_cairo_output_stream_write (stream, "\n", 1);
+    }
+}
diff --git a/src/cairo-output-stream.c b/src/cairo-output-stream.c
index 6fd6181..b07423c 100644
--- a/src/cairo-output-stream.c
+++ b/src/cairo-output-stream.c
@@ -114,69 +114,6 @@ _cairo_output_stream_write_hex_string (c
     }
 }
 
-static cairo_bool_t
-convert_four_tuple (const unsigned char *four_tuple, char five_tuple[5])
-{
-    cairo_bool_t all_zero;
-    uint32_t value;
-    int digit, i;
-    
-    value = four_tuple[0] << 24 | four_tuple[1] << 16 | four_tuple[2] << 8 | four_tuple[3];
-    all_zero = TRUE;
-    for (i = 0; i < 5; i++) {
-	digit = value % 85;
-	if (digit != 0)
-	    all_zero = FALSE;
-	five_tuple[4-i] = digit + 33;
-	value = value / 85;
-    }
-    return all_zero;
-}
-
-void
-_cairo_output_stream_write_base85_string (cairo_output_stream_t *stream,
-					  const char *data,
-					  size_t length)
-{
-    unsigned char *ptr;
-    unsigned char four_tuple[4];
-    char five_tuple[5];
-    int column;
-    
-    ptr = (unsigned char *)data;
-    column = 0;
-    while (length > 0) {
-	if (length >= 4) {
-	    if (convert_four_tuple (ptr, five_tuple)) {
-		column += 1;
-		_cairo_output_stream_write (stream, "z", 1);
-	    } else {
-		column += 5;
-		_cairo_output_stream_write (stream, five_tuple, 5);
-	    }
-	    length -= 4;
-	    ptr += 4;
-	} else { /* length < 4 */
-	    memset (four_tuple, 0, 4);
-	    memcpy (four_tuple, ptr, length);
-	    convert_four_tuple (four_tuple, five_tuple);
-	    column += length + 1;
-	    _cairo_output_stream_write (stream, five_tuple, length + 1);
-	    length = 0;
-	}
-	if (column >= 72) {
-	    _cairo_output_stream_write (stream, "\n", 1);
-	    column = 0;
-	}
-    }
-
-    if (column > 0) {
-	_cairo_output_stream_write (stream, "\n", 1);
-    }
-}
-
-
-
 /* Format a double in a locale independent way and trim trailing
  * zeros.  Based on code from Alex Larson <alexl at redhat.com>.
  * http://mail.gnome.org/archives/gtk-devel-list/2001-October/msg00087.html


More information about the cairo-commit mailing list