[cairo-commit] src/cairo-ps-surface.c
Carl Worth
cworth at kemper.freedesktop.org
Fri Jun 30 07:59:21 PDT 2006
src/cairo-ps-surface.c | 84 +++++++++++++++++++++++++++++++++++++++----------
1 files changed, 68 insertions(+), 16 deletions(-)
New commits:
diff-tree e0db22c6bc40d4576d9c1131d3192f1df3b942ca (from 057c0abeea1ee80c7156be5a1c15594765d88fe0)
Author: Carl Worth <cworth at cworth.org>
Date: Fri Jun 30 16:54:16 2006 +0200
ps: Fix degenerate-path test failure.
This is as simple as simply not emitting any degenerate sub-paths when the cap
style is CAIRO_LINE_CAP_SQUARE or CAIRO_LINE_CAP_BUTT.
diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c
index a4e52f8..f9a80f4 100644
--- a/src/cairo-ps-surface.c
+++ b/src/cairo-ps-surface.c
@@ -195,12 +195,23 @@ _word_wrap_stream_create (cairo_output_s
return &stream->base;
}
+typedef struct _ps_path_info {
+ cairo_ps_surface_t *surface;
+ cairo_output_stream_t *stream;
+ cairo_line_cap_t line_cap;
+ cairo_point_t last_move_to_point;
+ cairo_bool_t has_sub_path;
+} ps_path_info_t;
+
static cairo_status_t
_cairo_ps_surface_path_move_to (void *closure, cairo_point_t *point)
{
- cairo_output_stream_t *output_stream = closure;
+ ps_path_info_t *path_info = closure;
- _cairo_output_stream_printf (output_stream,
+ path_info->last_move_to_point = *point;
+ path_info->has_sub_path = FALSE;
+
+ _cairo_output_stream_printf (path_info->stream,
"%f %f moveto ",
_cairo_fixed_to_double (point->x),
_cairo_fixed_to_double (point->y));
@@ -211,9 +222,19 @@ _cairo_ps_surface_path_move_to (void *cl
static cairo_status_t
_cairo_ps_surface_path_line_to (void *closure, cairo_point_t *point)
{
- cairo_output_stream_t *output_stream = closure;
+ ps_path_info_t *path_info = closure;
+
+ if (path_info->line_cap != CAIRO_LINE_CAP_ROUND &&
+ ! path_info->has_sub_path &&
+ point->x == path_info->last_move_to_point.x &&
+ point->y == path_info->last_move_to_point.y)
+ {
+ return CAIRO_STATUS_SUCCESS;
+ }
- _cairo_output_stream_printf (output_stream,
+ path_info->has_sub_path = TRUE;
+
+ _cairo_output_stream_printf (path_info->stream,
"%f %f lineto ",
_cairo_fixed_to_double (point->x),
_cairo_fixed_to_double (point->y));
@@ -227,9 +248,11 @@ _cairo_ps_surface_path_curve_to (void
cairo_point_t *c,
cairo_point_t *d)
{
- cairo_output_stream_t *output_stream = closure;
+ ps_path_info_t *path_info = closure;
+
+ path_info->has_sub_path = TRUE;
- _cairo_output_stream_printf (output_stream,
+ _cairo_output_stream_printf (path_info->stream,
"%f %f %f %f %f %f curveto ",
_cairo_fixed_to_double (b->x),
_cairo_fixed_to_double (b->y),
@@ -244,30 +267,51 @@ _cairo_ps_surface_path_curve_to (void
static cairo_status_t
_cairo_ps_surface_path_close_path (void *closure)
{
- cairo_output_stream_t *output_stream = closure;
+ ps_path_info_t *path_info = closure;
- _cairo_output_stream_printf (output_stream,
+ if (path_info->line_cap != CAIRO_LINE_CAP_ROUND &&
+ ! path_info->has_sub_path)
+ {
+ return CAIRO_STATUS_SUCCESS;
+ }
+
+ _cairo_output_stream_printf (path_info->stream,
"closepath\n");
return CAIRO_STATUS_SUCCESS;
}
+/* The line cap value is needed to workaround the fact that PostScript
+ * semnatics for stroking degenerate sub-paths do not match cairo
+ * semantics. (PostScript draws something for any line cap value,
+ * while cairo draws something only for round caps).
+ *
+ * When using this function to emit a path to be filled, rather than
+ * stroked, simply pass CAIRO_LINE_CAP_ROUND which will guarantee that
+ * the stroke workaround will not modify the path being emitted.
+ */
static cairo_status_t
-_cairo_ps_surface_emit_path (cairo_output_stream_t *stream,
- cairo_path_fixed_t *path)
+_cairo_ps_surface_emit_path (cairo_ps_surface_t *surface,
+ cairo_output_stream_t *stream,
+ cairo_path_fixed_t *path,
+ cairo_line_cap_t line_cap)
{
cairo_output_stream_t *word_wrap;
cairo_status_t status;
+ ps_path_info_t path_info;
word_wrap = _word_wrap_stream_create (stream, 79);
+ path_info.surface = surface;
+ path_info.stream = word_wrap;
+ path_info.line_cap = line_cap;
status = _cairo_path_fixed_interpret (path,
CAIRO_DIRECTION_FORWARD,
_cairo_ps_surface_path_move_to,
_cairo_ps_surface_path_line_to,
_cairo_ps_surface_path_curve_to,
_cairo_ps_surface_path_close_path,
- word_wrap);
+ &path_info);
_cairo_output_stream_destroy (word_wrap);
@@ -461,8 +505,11 @@ _cairo_ps_surface_emit_outline_glyph_dat
_cairo_fixed_to_double (scaled_glyph->bbox.p2.x),
-_cairo_fixed_to_double (scaled_glyph->bbox.p1.y));
- status = _cairo_ps_surface_emit_path (surface->final_stream,
- scaled_glyph->path);
+ /* We're filling not stroking, so we pass CAIRO_LINE_CAP_ROUND. */
+ status = _cairo_ps_surface_emit_path (surface,
+ surface->final_stream,
+ scaled_glyph->path,
+ CAIRO_LINE_CAP_ROUND);
_cairo_output_stream_printf (surface->final_stream,
"F\n");
@@ -1691,7 +1738,9 @@ _cairo_ps_surface_intersect_clip_path (v
return CAIRO_STATUS_SUCCESS;
}
- status = _cairo_ps_surface_emit_path (stream, path);
+ /* We're "filling" not stroking, so we pass CAIRO_LINE_CAP_ROUND. */
+ status = _cairo_ps_surface_emit_path (surface, stream, path,
+ CAIRO_LINE_CAP_ROUND);
switch (fill_rule) {
case CAIRO_FILL_RULE_WINDING:
@@ -1910,7 +1959,8 @@ _cairo_ps_surface_stroke (void *abstra
_cairo_output_stream_printf (stream,
"gsave\n");
- status = _cairo_ps_surface_emit_path (stream, path);
+ status = _cairo_ps_surface_emit_path (surface, stream, path,
+ style->line_cap);
/*
* Switch to user space to set line parameters
@@ -1974,7 +2024,9 @@ _cairo_ps_surface_fill (void *abstract_
emit_pattern (surface, source, 0, 0);
- status = _cairo_ps_surface_emit_path (stream, path);
+ /* We're filling not stroking, so we pass CAIRO_LINE_CAP_ROUND. */
+ status = _cairo_ps_surface_emit_path (surface, stream, path,
+ CAIRO_LINE_CAP_ROUND);
switch (fill_rule) {
case CAIRO_FILL_RULE_WINDING:
More information about the cairo-commit
mailing list