[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