[cairo-commit] src/cairoint.h src/cairo-path-fixed.c src/cairo-pdf-operators.c src/cairo-ps-surface.c

Adrian Johnson ajohnson at kemper.freedesktop.org
Tue Feb 26 04:48:53 PST 2008


 src/cairo-path-fixed.c    |   24 ++++++++++++++++++++++++
 src/cairo-pdf-operators.c |   36 +++++++++++++++++++++++++++++-------
 src/cairo-ps-surface.c    |    2 ++
 src/cairoint.h            |    4 ++++
 4 files changed, 59 insertions(+), 7 deletions(-)

New commits:
commit 40f4750f5ec53ca9ca6e3d621fefb2bd1687909e
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Tue Feb 26 23:17:04 2008 +1030

    Use PDF 're' operator for rectangle paths
    
    Modify cairo-pdf-operators.c to emit to 're' path operator when the
    path contains only a rectangle. This can only be done when the path is
    logically equivilent to the the path drawn by the 're'
    operator. Otherwise dashed strokes may start on the wrong line.
    
    ie the path must be equivalent to:
    
      cairo_move_to (cr, x, y);
      cairo_rel_line_to (cr, width, 0);
      cairo_rel_line_to (cr, 0, height);
      cairo_rel_line_to (cr, -width, 0);
      cairo_close_path (cr);
    
    which is also equivilent to cairo_rectangle().

diff --git a/src/cairo-path-fixed.c b/src/cairo-path-fixed.c
index 5c10d65..55229da 100644
--- a/src/cairo-path-fixed.c
+++ b/src/cairo-path-fixed.c
@@ -802,3 +802,27 @@ _cairo_path_fixed_is_box (cairo_path_fixed_t *path,
 
     return FALSE;
 }
+
+/**
+ * Check whether the given path contains a single rectangle
+ * that is logically equivalent to:
+ *   cairo_move_to (cr, x, y);
+ *   cairo_rel_line_to (cr, width, 0);
+ *   cairo_rel_line_to (cr, 0, height);
+ *   cairo_rel_line_to (cr, -width, 0);
+ *   cairo_close_path (cr);
+ */
+cairo_bool_t
+_cairo_path_fixed_is_rectangle (cairo_path_fixed_t *path,
+				cairo_box_t        *box)
+{
+    cairo_path_buf_t *buf = &path->buf_head.base;
+
+    if (!_cairo_path_fixed_is_box (path, box))
+	return FALSE;
+
+    if (buf->points[0].y == buf->points[1].y)
+	return TRUE;
+
+    return FALSE;
+}
diff --git a/src/cairo-pdf-operators.c b/src/cairo-pdf-operators.c
index fb685b5..066a73f 100644
--- a/src/cairo-pdf-operators.c
+++ b/src/cairo-pdf-operators.c
@@ -328,6 +328,23 @@ _cairo_pdf_path_close_path (void *closure)
     return _cairo_output_stream_get_status (info->output);
 }
 
+static cairo_status_t
+_cairo_pdf_path_rectangle (pdf_path_info_t *info, cairo_box_t *box)
+{
+    double x1 = _cairo_fixed_to_double (box->p1.x);
+    double y1 = _cairo_fixed_to_double (box->p1.y);
+    double x2 = _cairo_fixed_to_double (box->p2.x);
+    double y2 = _cairo_fixed_to_double (box->p2.y);
+
+    cairo_matrix_transform_point (info->path_transform, &x1, &y1);
+    cairo_matrix_transform_point (info->path_transform, &x2, &y2);
+    _cairo_output_stream_printf (info->output,
+				 "%f %f %f %f re ",
+				 x1, y1, x2 - x1, y2 - y1);
+
+    return _cairo_output_stream_get_status (info->output);
+}
+
 /* The line cap value is needed to workaround the fact that PostScript
  * and PDF semantics for stroking degenerate sub-paths do not match
  * cairo semantics. (PostScript draws something for any line cap
@@ -346,6 +363,7 @@ _cairo_pdf_operators_emit_path (cairo_pdf_operators_t 	*pdf_operators,
     cairo_output_stream_t *word_wrap;
     cairo_status_t status, status2;
     pdf_path_info_t info;
+    cairo_box_t box;
 
     word_wrap = _word_wrap_stream_create (pdf_operators->stream, 79);
     status = _cairo_output_stream_get_status (word_wrap);
@@ -355,13 +373,17 @@ _cairo_pdf_operators_emit_path (cairo_pdf_operators_t 	*pdf_operators,
     info.output = word_wrap;
     info.path_transform = path_transform;
     info.line_cap = line_cap;
-    status = _cairo_path_fixed_interpret (path,
-					  CAIRO_DIRECTION_FORWARD,
-					  _cairo_pdf_path_move_to,
-					  _cairo_pdf_path_line_to,
-					  _cairo_pdf_path_curve_to,
-					  _cairo_pdf_path_close_path,
-					  &info);
+    if (_cairo_path_fixed_is_rectangle (path, &box)) {
+	status = _cairo_pdf_path_rectangle (&info, &box);
+    } else {
+	status = _cairo_path_fixed_interpret (path,
+					      CAIRO_DIRECTION_FORWARD,
+					      _cairo_pdf_path_move_to,
+					      _cairo_pdf_path_line_to,
+					      _cairo_pdf_path_curve_to,
+					      _cairo_pdf_path_close_path,
+					      &info);
+    }
 
     status2 = _cairo_output_stream_destroy (word_wrap);
     if (status == CAIRO_STATUS_SUCCESS)
diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c
index f8e1901..86d632c 100644
--- a/src/cairo-ps-surface.c
+++ b/src/cairo-ps-surface.c
@@ -169,6 +169,8 @@ _cairo_ps_surface_emit_header (cairo_ps_surface_t *surface)
 				 "/l { lineto } bind def\n"
 				 "/c { curveto } bind def\n"
 				 "/h { closepath } bind def\n"
+				 "/re { exch dup neg 3 1 roll 5 3 roll moveto 0 rlineto\n"
+				 "      0 exch rlineto 0 rlineto closepath } bind def\n"
 				 "/S { stroke } bind def\n"
 				 "/f { fill } bind def\n"
 				 "/f* { eofill } bind def\n"
diff --git a/src/cairoint.h b/src/cairoint.h
index 099d0d5..5f68e0d 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -1399,6 +1399,10 @@ cairo_private cairo_bool_t
 _cairo_path_fixed_is_box (cairo_path_fixed_t *path,
                           cairo_box_t *box);
 
+cairo_private cairo_bool_t
+_cairo_path_fixed_is_rectangle (cairo_path_fixed_t *path,
+				cairo_box_t        *box);
+
 /* cairo_path_fill.c */
 cairo_private cairo_status_t
 _cairo_path_fixed_fill_to_traps (cairo_path_fixed_t *path,


More information about the cairo-commit mailing list