[cairo] Initial tests of cairo's PostScript backend with firefox

Carl Worth cworth at cworth.org
Wed Apr 12 16:42:24 PDT 2006


On Tue, 11 Apr 2006 21:41:27 -0400, Michael Sweet wrote:
> 
> For fun, I ran these files through the (new) CUPS cupstestdsc program.
> The original firefox 1.5 output passed the tests, but the new cairo-
> based output had a couple issues:
> 
>      - %%Page: needs a page label and ordinal page number; typically
>        you will just use the page number twice, e.g.:
...
>      - You have a lot of lines longer than 255 characters;

Thanks so much! I really appreciate your attention to detail. Thanks
to feedback like this I'm hoping cairo will start generating fairly
reasonable PostScript output soon. I've made changes for both of the
above and the new output for the minefield page is here:

	http://cairographics.org/~cworth/images/minefield-wrapped.ps

How does that look?

>                                                           probably
>        the simplest fix is to use a LF instead of space as the
>        separator.

That probably would have been the right thing to do, but instead I
went ahead and wrote some stupid line wrapping code to keep things
near 80 columns or so. I probably botched it pretty bad, so I've
attached the patch below for review. In any case, it seems to work on
the test cases we have in the test suite as well as the minefield page
from firefox. But that's not saying much of course.

> Also, you can optimize the output size significantly just by defining
> procedures like "M" for moveto, etc.  The following document prolog
> with the corresponding substitutions in the merges-ps-type3 file
> reduced the size of the output by 37k (273936 bytes total):

I went ahead and did that too, just for kicks. (It's perhaps a
pre-mature optimization, since there are still more wasteful things
than this in the output---and it does make the code a bit harder to
read---but it's also a simple change to revert as desired).

The output from this one is here:

	http://cairographics.org/~cworth/images/minefield-wrapped-shorter.ps

The changes for both of these are merged into the master branch on the
central cairo tree. This means that keithp's type3 changes also got
merged in.

Similarly, for mozilla testing the mozilla-merged branch in my
personal tree is all that's needed now, (the mozilla-merged-ps-type3
branch no longer exists). And I hope to get mozilla's patched merged
into master soon so that we won't even need any mozilla branches at
all. Vlad, where do we stand on this?

Oh, and I should have mentioned this before: My mozilla-merged branch
might make for some useful spot testing, but it's definitely *not*
anything that anyone should use as a base for development. There were
some conflicts in the merge that weren't relevant to what I was doing,
(such as in cairo-atsui-font.c), so the result of that merge has a
bunch of garbage in places like that. You have been warned.

-Carl

diff-tree d60eaab222fb1ce19ef7bbbf496ad444f07aa703 (from 6a5d8fc7ffb5f425ceffd313b8a875f38126b324)
Author: Carl Worth <cworth at cworth.org>
Date:   Wed Apr 12 15:48:59 2006 -0700

    Add simple word wrapping to keep PostScript output within 80 columns or less.

diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c
index 93a3e93..e19182d 100644
--- a/src/cairo-ps-surface.c
+++ b/src/cairo-ps-surface.c
@@ -696,12 +696,117 @@ cairo_ps_surface_set_dpi (cairo_surface_
 
 }
 
+/* A word wrap stream can be used as a filter to do word wrapping on
+ * top of an existing output stream. The word wrapping is quite
+ * simple, using isspace to determine characters that separate
+ * words. Any word that will cause the column count exceeed the given
+ * max_column will have a '\n' character emitted before it.
+ *
+ * The stream is careful to maintain integrity for words that cross
+ * the boundary from one call to write to the next.
+ *
+ * Note: This stream does not guarantee that the output will never
+ * exceed max_column. In particular, if a single word is larger than
+ * max_column it will not be broken up.
+ */
+typedef struct _word_wrap_stream {
+    cairo_output_stream_t *output;
+    int max_column;
+    int column;
+    cairo_bool_t last_write_was_space;
+} word_wrap_stream_t;
+
+static int
+_count_word_up_to (const unsigned char *s, int length)
+{
+    int word = 0;
+
+    while (length--) {
+	if (! isspace (*s++))
+	    word++;
+	else
+	    return word;
+    }
+
+    return word;
+}
+
+static cairo_status_t
+_word_wrap_stream_write (void			*closure,
+			 const unsigned char	*data,
+			 unsigned int		 length)
+{
+    word_wrap_stream_t *stream = closure;
+    cairo_bool_t newline;
+    int word;
+
+    while (length) {
+	if (isspace (*data)) {
+	    newline =  (*data == '\n' || *data == '\r');
+	    if (! newline && stream->column >= stream->max_column) {
+		_cairo_output_stream_printf (stream->output, "\n");
+		stream->column = 0;
+	    }
+	    _cairo_output_stream_write (stream->output, data, 1);
+	    data++;
+	    length--;
+	    if (newline)
+		stream->column = 0;
+	    else
+		stream->column++;
+	    stream->last_write_was_space = TRUE;
+	} else {
+	    word = _count_word_up_to (data, length);
+	    /* Don't wrap if this word is a continuation of a word
+	     * from a previous call to write. */
+	    if (stream->column + word >= stream->max_column &&
+		stream->last_write_was_space)
+	    {
+		_cairo_output_stream_printf (stream->output, "\n");
+		stream->column = 0;
+	    }
+	    _cairo_output_stream_write (stream->output, data, word);
+	    data += word;
+	    length -= word;
+	    stream->column += word;
+	    stream->last_write_was_space = FALSE;
+	}
+    }
+
+    return _cairo_output_stream_get_status (stream->output);
+}
+
+static cairo_output_stream_t *
+_word_wrap_stream_create (cairo_output_stream_t *output, int max_column)
+{
+    word_wrap_stream_t *stream;
+
+    stream = malloc (sizeof (word_wrap_stream_t));
+    if (stream == NULL)
+	return (cairo_output_stream_t *) &cairo_output_stream_nil;
+
+    stream->output = output;
+    stream->max_column = max_column;
+    stream->column = 0;
+    stream->last_write_was_space = FALSE;
+
+    return _cairo_output_stream_create (_word_wrap_stream_write,
+					NULL, stream);
+}
+
 static cairo_status_t
 _cairo_ps_surface_finish (void *abstract_surface)
 {
     cairo_status_t status;
     cairo_ps_surface_t *surface = abstract_surface;
+    cairo_output_stream_t *final_stream, *word_wrap;
 
+    /* Save final_stream to be restored later. */
+    final_stream = surface->final_stream;
+
+    word_wrap = _word_wrap_stream_create (final_stream, 79);
+    surface->final_stream = word_wrap;
+   
     _cairo_ps_surface_emit_header (surface);
     
     _cairo_ps_surface_emit_fonts (surface);
@@ -715,6 +820,10 @@ _cairo_ps_surface_finish (void *abstract
     _cairo_output_stream_destroy (surface->stream);
 
     fclose (surface->tmpfile);
+
+    /* Restore final stream before final cleanup. */
+    _cairo_output_stream_destroy (word_wrap);
+    surface->final_stream = final_stream;
 
     _cairo_output_stream_close (surface->final_stream);
     if (status == CAIRO_STATUS_SUCCESS)
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 191 bytes
Desc: not available
Url : http://lists.freedesktop.org/archives/cairo/attachments/20060412/c0abf67e/attachment.pgp


More information about the cairo mailing list