[cairo-commit] 4 commits - src/cairo-clip.c src/cairo-pdf-surface.c src/cairo-surface.c test/clip-all.c test/clip-empty.c test/clip-empty-ref.png test/Makefile.am

Chris Wilson ickle at kemper.freedesktop.org
Tue Nov 6 07:31:43 PST 2007


 src/cairo-clip.c        |    6 ++++
 src/cairo-pdf-surface.c |   36 ++++++++++++++----------
 src/cairo-surface.c     |   61 ++++++++++++++++++++++++++++++++++------
 test/Makefile.am        |    2 +
 test/clip-all.c         |   10 ++++++
 test/clip-empty-ref.png |binary
 test/clip-empty.c       |   72 ++++++++++++++++++++++++++++++++++++++++++++++++
 7 files changed, 164 insertions(+), 23 deletions(-)

New commits:
commit 62d64e12aa9264a17c9bb7d6ae154a1778f0c7e1
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Nov 6 14:24:52 2007 +0000

    [cairo-pdf-surface] Create a new path for an empty clip.
    
    If the clip path is empty, then we need to start a new path otherwise
    the clip is ineffective.

diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index 6db1018..695e6e9 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -3995,26 +3995,34 @@ _cairo_pdf_surface_emit_clip (cairo_pdf_surface_t  *surface,
 			      cairo_path_fixed_t   *path,
 			      cairo_fill_rule_t	    fill_rule)
 {
-    cairo_status_t status;
     const char *pdf_operator;
-    pdf_path_info_t info;
 
     if (path == NULL) {
 	_cairo_output_stream_printf (surface->output, "Q q\r\n");
 	return CAIRO_STATUS_SUCCESS;
     }
 
-    info.output = surface->output;
-    info.cairo_to_pdf = &surface->cairo_to_pdf;
-    info.ctm_inverse = NULL;
-
-    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 (! path->has_current_point) {
+	/* construct an empty path */
+	_cairo_output_stream_printf (surface->output, "0 0 m ");
+    } else {
+	pdf_path_info_t info;
+	cairo_status_t status;
+
+	info.output = surface->output;
+	info.cairo_to_pdf = &surface->cairo_to_pdf;
+	info.ctm_inverse = NULL;
+
+	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 (status)
+	    return status;
+    }
 
     switch (fill_rule) {
     case CAIRO_FILL_RULE_WINDING:
@@ -4031,7 +4039,7 @@ _cairo_pdf_surface_emit_clip (cairo_pdf_surface_t  *surface,
 				 "%s n\r\n",
 				 pdf_operator);
 
-    return status;
+    return CAIRO_STATUS_SUCCESS;
 }
 
 static cairo_status_t
commit b4057b8643cf02439b6033d7443d0d4c42220a62
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Nov 6 09:45:54 2007 +0000

    [cairo-clip] Special case using an empty clip path.
    
    Detect when the user calls cairo_clip() with an empty clip path and
    mark the clip as all_clipped.

diff --git a/src/cairo-clip.c b/src/cairo-clip.c
index 8254105..0fed3f6 100644
--- a/src/cairo-clip.c
+++ b/src/cairo-clip.c
@@ -537,6 +537,12 @@ _cairo_clip_clip (cairo_clip_t       *clip,
     if (clip->all_clipped)
 	return CAIRO_STATUS_SUCCESS;
 
+    /* catch the empty clip path */
+    if (! path->has_current_point) {
+	_cairo_clip_set_all_clipped (clip, target);
+	return CAIRO_STATUS_SUCCESS;
+    }
+
     status = _cairo_clip_intersect_path (clip,
 					 path, fill_rule, tolerance,
 					 antialias);
commit 2f0867b43fbc9a385a32a2a39895f4c3559f6ddf
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Nov 6 09:44:03 2007 +0000

    [cairo-surface] Handle the all clipped out case.
    
    Explicitly handle a clip which represents that the entire surface is
    clipped out.
    
    Fixes https://bugs.freedesktop.org/show_bug.cgi?id=13084.

diff --git a/src/cairo-surface.c b/src/cairo-surface.c
index 97a8b9e..ed332f5 100644
--- a/src/cairo-surface.c
+++ b/src/cairo-surface.c
@@ -1903,6 +1903,38 @@ _cairo_surface_set_clip_path (cairo_surface_t	*surface,
     return CAIRO_STATUS_SUCCESS;
 }
 
+
+/**
+ * _cairo_surface_set_empty_clip_path:
+ * @surface: the #cairo_surface_t to set the clip on
+ * @serial: the clip serial number associated with the clip path
+ *
+ * Create an empty clip path, one that represents the entire surface clipped
+ * out, and assigns the given clipping serial to the surface.
+ **/
+static cairo_status_t
+_cairo_surface_set_empty_clip_path (cairo_surface_t *surface,
+	                            unsigned int serial)
+{
+    cairo_path_fixed_t path;
+    cairo_status_t status;
+
+    _cairo_path_fixed_init (&path);
+
+    status = surface->backend->intersect_clip_path (surface,
+						    &path,
+						    CAIRO_FILL_RULE_WINDING,
+						    0,
+						    CAIRO_ANTIALIAS_DEFAULT);
+
+    if (status == CAIRO_STATUS_SUCCESS)
+	surface->current_clip_serial = serial;
+
+    _cairo_path_fixed_fini (&path);
+
+    return _cairo_surface_set_error (surface, status);
+}
+
 cairo_status_t
 _cairo_surface_set_clip (cairo_surface_t *surface, cairo_clip_t *clip)
 {
@@ -1926,15 +1958,26 @@ _cairo_surface_set_clip (cairo_surface_t *surface, cairo_clip_t *clip)
 	return CAIRO_STATUS_SUCCESS;
 
     if (clip) {
-	if (clip->path)
-	    return _cairo_surface_set_clip_path (surface,
-						 clip->path,
-						 clip->serial);
-
-	if (clip->has_region)
-	    return _cairo_surface_set_clip_region (surface,
-						   &clip->region,
-						   clip->serial);
+	if (clip->all_clipped) {
+	    if (surface->backend->intersect_clip_path != NULL)
+		return _cairo_surface_set_empty_clip_path (surface,
+						           clip->serial);
+
+	    if (surface->backend->set_clip_region != NULL)
+		return _cairo_surface_set_clip_region (surface,
+						       &clip->region,
+						       clip->serial);
+	} else {
+	    if (clip->path)
+		return _cairo_surface_set_clip_path (surface,
+						     clip->path,
+						     clip->serial);
+
+	    if (clip->has_region)
+		return _cairo_surface_set_clip_region (surface,
+						       &clip->region,
+						       clip->serial);
+	}
     }
 
     return _cairo_surface_reset_clip (surface);
commit 641215b2b018e98b298db5042360e2e22ab5a0aa
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Mon Nov 5 22:22:42 2007 +0000

    [test/clip-all] Combine text and everything clipped out.
    
    https://bugs.freedesktop.org/show_bug.cgi?id=13084 demonstrates a
    regression where the clip is ignored by the xlib backend whilst
    rendering text. Therefore we extend the current test cases to combine
    a clip that represents everything clipped out with the rendering of
    text. For completeness, we add a new test case that exactly mimics the
    sequence of cairo operations that lead to the discovery of this bug -
    namely the rendering of text with an empty clip path.

diff --git a/test/Makefile.am b/test/Makefile.am
index bf10ba9..3975bd0 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -8,6 +8,7 @@ caps-joins			\
 caps-joins-alpha		\
 caps-sub-paths			\
 clip-all			\
+clip-empty			\
 clip-fill-rule			\
 clip-fill-rule-pixel-aligned	\
 clip-nesting			\
@@ -221,6 +222,7 @@ REFERENCE_IMAGES = \
 	caps-joins-ref.png	\
 	caps-sub-paths-ref.png	\
 	clip-all-ref.png	\
+	clip-empty-ref.png	\
 	clip-fill-rule-pixel-aligned-ref.png	\
 	clip-fill-rule-pixel-aligned-rgb24-ref.png	\
 	clip-fill-rule-ps-argb32-ref.png	\
diff --git a/test/clip-all.c b/test/clip-all.c
index 2ff883d..b38e7b9 100644
--- a/test/clip-all.c
+++ b/test/clip-all.c
@@ -62,6 +62,16 @@ draw (cairo_t *cr, int width, int height)
     cairo_set_source_rgb (cr, 1, 1, 0);
     cairo_fill (cr);
 
+    /* https://bugs.freedesktop.org/show_bug.cgi?id=13084 */
+    cairo_select_font_face (cr,
+	                    "Bitstream Vera Sans",
+			    CAIRO_FONT_SLANT_NORMAL,
+			    CAIRO_FONT_WEIGHT_NORMAL);
+
+    cairo_move_to (cr, 0., SIZE);
+    cairo_show_text (cr, "cairo");
+
+
     return CAIRO_TEST_SUCCESS;
 }
 
diff --git a/test/clip-empty-ref.png b/test/clip-empty-ref.png
new file mode 100644
index 0000000..6c14df5
Binary files /dev/null and b/test/clip-empty-ref.png differ
diff --git a/test/clip-empty.c b/test/clip-empty.c
new file mode 100644
index 0000000..9049153
--- /dev/null
+++ b/test/clip-empty.c
@@ -0,0 +1,72 @@
+/*
+ * Copyright © 2007 Chris Wilson
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without
+ * fee, provided that the above copyright notice appear in all copies
+ * and that both that copyright notice and this permission notice
+ * appear in supporting documentation, and that the name of
+ * Chris Wilson not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior
+ * permission. Chris Wilson makes no representations about the
+ * suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * CHRIS WILSON DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL CHRIS WILSON BE LIABLE FOR ANY SPECIAL,
+ * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
+ * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Author: Chris Wilson <chris at chris-wilson.co.uk>
+ */
+
+#include "cairo-test.h"
+
+#define SIZE 10
+
+static cairo_test_draw_function_t draw;
+
+cairo_test_t test = {
+    "clip-empty",
+    "Test clipping with an empty clip path",
+    SIZE, SIZE,
+    draw
+};
+
+static cairo_test_status_t
+draw (cairo_t *cr, int width, int height)
+{
+    cairo_set_source_rgb (cr, 0, 0, 1);
+    cairo_paint (cr);
+
+    cairo_reset_clip (cr);
+    cairo_clip (cr);
+
+    cairo_translate (cr, .5, .5);
+
+    cairo_set_source_rgb (cr, 0, 1, 0);
+    cairo_rectangle (cr, 0, 0, SIZE, SIZE);
+    cairo_fill_preserve (cr);
+    cairo_set_source_rgb (cr, 1, 0, 0);
+    cairo_stroke (cr);
+
+    /* https://bugs.freedesktop.org/show_bug.cgi?id=13084 */
+    cairo_select_font_face (cr,
+	                    "Bitstream Vera Sans",
+			    CAIRO_FONT_SLANT_NORMAL,
+			    CAIRO_FONT_WEIGHT_NORMAL);
+
+    cairo_move_to (cr, 0., SIZE);
+    cairo_show_text (cr, "cairo");
+
+    return CAIRO_TEST_SUCCESS;
+}
+
+int
+main (void)
+{
+    return cairo_test (&test);
+}


More information about the cairo-commit mailing list