[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