[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