summaryrefslogtreecommitdiff
path: root/src/cairo-base85-stream.c
diff options
context:
space:
mode:
authorCarl Worth <cworth@raht.cworth.org>2006-04-03 23:44:51 -0700
committerCarl Worth <cworth@raht.cworth.org>2006-04-03 23:44:51 -0700
commit5a06133eb2e13a4c0354dad7f7da414c85733c4e (patch)
treedd1859e55c27f62e775bf9983c298d6bb60a163c /src/cairo-base85-stream.c
parent57fe9b17b0a1a36acf0d8d524df05215ea48361f (diff)
downloadcairo-5a06133eb2e13a4c0354dad7f7da414c85733c4e.tar.gz
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.
Diffstat (limited to 'src/cairo-base85-stream.c')
-rw-r--r--src/cairo-base85-stream.c142
1 files changed, 102 insertions, 40 deletions
diff --git a/src/cairo-base85-stream.c b/src/cairo-base85-stream.c
index 0bb6f320f..6adfa1668 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);
+}
+