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

Carl Worth cworth at kemper.freedesktop.org
Wed Apr 12 16:22:08 PDT 2006


 src/cairo-ps-surface.c |  151 ++++++++++++++++++++++++++++++++++++++++++++-----
 1 files changed, 136 insertions(+), 15 deletions(-)

New commits:
diff-tree 6beababd47aabfb4896a878de09d729f287aa714 (from d60eaab222fb1ce19ef7bbbf496ad444f07aa703)
Author: Carl Worth <cworth at cworth.org>
Date:   Wed Apr 12 16:19:08 2006 -0700

    Optimize PostScript file size with procedures instead of builtin operators.
    
    This is based on a suggestion by Michael Sweet.

diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c
index e19182d..d02eacf 100644
--- a/src/cairo-ps-surface.c
+++ b/src/cairo-ps-surface.c
@@ -123,7 +123,7 @@ _cairo_ps_surface_path_move_to (void *cl
     cairo_ps_surface_path_info_t *info = closure;
 
     _cairo_output_stream_printf (info->output_stream,
-				 "%f %f moveto ",
+				 "%f %f M ",
 				 _cairo_fixed_to_double (point->x),
 				 _cairo_fixed_to_double (point->y));
     info->has_current_point = TRUE;
@@ -138,9 +138,9 @@ _cairo_ps_surface_path_line_to (void *cl
     const char *ps_operator;
 
     if (info->has_current_point)
-	ps_operator = "lineto";
+	ps_operator = "L";
     else
-	ps_operator = "moveto";
+	ps_operator = "M";
     
     _cairo_output_stream_printf (info->output_stream,
 				 "%f %f %s ",
@@ -161,7 +161,7 @@ _cairo_ps_surface_path_curve_to (void   
     cairo_ps_surface_path_info_t *info = closure;
 
     _cairo_output_stream_printf (info->output_stream,
-				 "%f %f %f %f %f %f curveto ",
+				 "%f %f %f %f %f %f C ",
 				 _cairo_fixed_to_double (b->x),
 				 _cairo_fixed_to_double (b->y),
 				 _cairo_fixed_to_double (c->x),
@@ -179,7 +179,7 @@ _cairo_ps_surface_path_close_path (void 
     
     if (info->has_current_point)
         _cairo_output_stream_printf (info->output_stream,
-				     "closepath\n");
+				     "P\n");
     info->has_current_point = FALSE;
 
     return CAIRO_STATUS_SUCCESS;
@@ -209,6 +209,18 @@ _cairo_ps_surface_emit_header (cairo_ps_
 				 "%%%%LanguageLevel: 2\n"
 				 "%%%%Orientation: Portrait\n"
 				 "%%%%EndComments\n");
+
+    _cairo_output_stream_printf (surface->final_stream,
+				 "%%%%BeginProlog\n"
+				 "/C{curveto}bind def\n"
+				 "/F{fill}bind def\n"
+				 "/G{setgray}bind def\n"
+				 "/L{lineto}bind def\n"
+				 "/M{moveto}bind def\n"
+				 "/P{closepath}bind def\n"
+				 "/R{setrgbcolor}bind def\n"
+				 "/S{show}bind def\n"
+				 "%%%%EndProlog\n");
 }
 
 static cairo_bool_t
@@ -429,7 +441,7 @@ _cairo_ps_surface_emit_glyph (cairo_ps_s
 					  &info);
     
     _cairo_output_stream_printf (surface->final_stream,
-				 "fill\n");
+				 "F\n");
     
     _cairo_output_stream_printf (surface->final_stream,
 				 "\t\t}\n");
@@ -1343,11 +1355,11 @@ emit_solid_pattern (cairo_ps_surface_t *
 {
     if (color_is_gray (&pattern->color))
 	_cairo_output_stream_printf (surface->stream,
-				     "%f setgray\n",
+				     "%f G\n",
 				     pattern->color.red);
     else
 	_cairo_output_stream_printf (surface->stream,
-				     "%f %f %f setrgbcolor\n",
+				     "%f %f %f R\n",
 				     pattern->color.red,
 				     pattern->color.green,
 				     pattern->color.blue);
@@ -1546,12 +1558,12 @@ _cairo_ps_surface_paint (void			*abstrac
     info.output_stream = stream;
     info.has_current_point = FALSE;
 
-    _cairo_output_stream_printf (stream, "0 0 moveto\n");
-    _cairo_output_stream_printf (stream, "%f 0 lineto\n", surface->width);
-    _cairo_output_stream_printf (stream, "%f %f lineto\n",
+    _cairo_output_stream_printf (stream, "0 0 M\n");
+    _cairo_output_stream_printf (stream, "%f 0 L\n", surface->width);
+    _cairo_output_stream_printf (stream, "%f %f L\n",
 				 surface->width, surface->height);
-    _cairo_output_stream_printf (stream, "0 %f lineto\n", surface->height);
-    _cairo_output_stream_printf (stream, "closepath fill\n");
+    _cairo_output_stream_printf (stream, "0 %f L\n", surface->height);
+    _cairo_output_stream_printf (stream, "P F\n");
     return CAIRO_STATUS_SUCCESS;
 }
 
@@ -1713,7 +1725,7 @@ _cairo_ps_surface_fill (void		*abstract_
 
     switch (fill_rule) {
     case CAIRO_FILL_RULE_WINDING:
-	ps_operator = "fill";
+	ps_operator = "F";
 	break;
     case CAIRO_FILL_RULE_EVEN_ODD:
 	ps_operator = "eofill";
@@ -1791,7 +1803,7 @@ _cairo_ps_surface_show_glyphs (void		   
 	    cur_subfont = subfont;
 	}
 	_cairo_output_stream_printf (surface->stream,
-				     "%f %f moveto <%c%c> show\n",
+				     "%f %f M <%c%c> S\n",
 				     glyphs[i].x, glyphs[i].y,
 				     hex_digit (ps_glyph->output_glyph >> 4),
 				     hex_digit (ps_glyph->output_glyph));
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);
@@ -716,6 +821,10 @@ _cairo_ps_surface_finish (void *abstract
 
     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)
 	status = _cairo_output_stream_get_status (surface->final_stream);


More information about the cairo-commit mailing list