[cairo-commit] 3 commits - src/cairo-clip.c src/cairo-clip-private.h src/cairo-gl-surface.c src/cairo-image-surface.c src/cairo-surface-fallback.c src/cairo-xcb-surface-render.c src/drm test/Makefile.am test/Makefile.sources test/partial-clip-text.c test/partial-clip-text.ps.ref.png test/partial-clip-text.ref.png test/partial-clip-text.svg.ref.png

Chris Wilson ickle at kemper.freedesktop.org
Mon Jul 12 08:41:20 PDT 2010


 src/cairo-clip-private.h           |    4 ++
 src/cairo-clip.c                   |   22 +++++++++++-----
 src/cairo-gl-surface.c             |    4 +-
 src/cairo-image-surface.c          |   33 +++++++++++++++++-------
 src/cairo-surface-fallback.c       |   10 +++----
 src/cairo-xcb-surface-render.c     |   10 +++----
 src/drm/cairo-drm-i915-glyphs.c    |    2 -
 src/drm/cairo-drm-i915-surface.c   |    8 ++---
 src/drm/cairo-drm-i965-glyphs.c    |    2 -
 src/drm/cairo-drm-i965-surface.c   |    8 ++---
 test/Makefile.am                   |    3 ++
 test/Makefile.sources              |    1 
 test/partial-clip-text.c           |   50 +++++++++++++++++++++++++++++++++++++
 test/partial-clip-text.ps.ref.png  |binary
 test/partial-clip-text.ref.png     |binary
 test/partial-clip-text.svg.ref.png |binary
 16 files changed, 119 insertions(+), 38 deletions(-)

New commits:
commit ef0679333da881bd83b0bb4db546ea9c68f81f89
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Mon Jul 12 16:07:27 2010 +0100

    image: Manually clip against bounds when rendering directly
    
    This is path is slightly peculiar in that it explicitly avoid the
    intermediate mask and the geometry is not pre-clipped.
    
    This in conjunction with the previous commit fixes:
    
      Clip doesn't work for text
      https://bugs.freedesktop.org/show_bug.cgi?id=29008
    
    which is captured in test/partial-clip-text.

diff --git a/src/cairo-image-surface.c b/src/cairo-image-surface.c
index 1f8e9b1..e111973 100644
--- a/src/cairo-image-surface.c
+++ b/src/cairo-image-surface.c
@@ -3939,6 +3939,8 @@ _composite_glyphs (void				*closure,
 
 	glyph_surface = scaled_glyph->surface;
 	if (glyph_surface->width && glyph_surface->height) {
+	    int x1, y1, x2, y2;
+
 	    /* round glyph locations to the nearest pixel */
 	    /* XXX: FRAGILE: We're ignoring device_transform scaling here. A bug? */
 	    x = _cairo_lround (info->glyphs[i].x -
@@ -3946,13 +3948,26 @@ _composite_glyphs (void				*closure,
 	    y = _cairo_lround (info->glyphs[i].y -
 			       glyph_surface->base.device_transform.y0);
 
+	    x1 = x;
+	    if (x1 < extents->x)
+		x1 = extents->x;
+	    x2 = x + glyph_surface->width;
+	    if (x2 > extents->x + extents->width)
+		x2 = extents->x + extents->width;
+
+	    y1 = y;
+	    if (y1 < extents->y)
+		y1 = extents->y;
+	    y2 = y + glyph_surface->height;
+	    if (y2 > extents->y + extents->height)
+		y2 = extents->y + extents->height;
+
 	    pixman_image_composite32 (pixman_op,
                                       src, glyph_surface->pixman_image, dst,
-                                      x + src_x,  y + src_y,
+                                      x1 + src_x,  y1 + src_y,
                                       0, 0,
-                                      x - dst_x, y - dst_y,
-                                      glyph_surface->width,
-                                      glyph_surface->height);
+                                      x1 - dst_x, y1 - dst_y,
+                                      x2 - x1, y2 - y1);
 	}
     }
     _cairo_scaled_font_thaw_cache (info->font);
commit 679e5a600bd7dae6cbde83070fb1f7355f8025a7
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Mon Jul 12 16:06:32 2010 +0100

    Differentiate between reducing clip to composite extents and a rectangle
    
    This is required for handling glyphs when rendering directly to the
    surface.

diff --git a/src/cairo-clip-private.h b/src/cairo-clip-private.h
index 7c7b84f..faf4864 100644
--- a/src/cairo-clip-private.h
+++ b/src/cairo-clip-private.h
@@ -136,6 +136,10 @@ _cairo_clip_to_boxes (cairo_clip_t **clip,
 
 cairo_private cairo_bool_t
 _cairo_clip_contains_rectangle (cairo_clip_t *clip,
+				const cairo_rectangle_int_t *rect);
+
+cairo_private cairo_bool_t
+_cairo_clip_contains_extents (cairo_clip_t *clip,
 				const cairo_composite_rectangles_t *extents);
 
 cairo_private void
diff --git a/src/cairo-clip.c b/src/cairo-clip.c
index 0c6cb74..3bd7edc 100644
--- a/src/cairo-clip.c
+++ b/src/cairo-clip.c
@@ -1106,18 +1106,13 @@ _cairo_clip_path_get_surface (cairo_clip_path_t *clip_path,
 
 cairo_bool_t
 _cairo_clip_contains_rectangle (cairo_clip_t *clip,
-				const cairo_composite_rectangles_t *extents)
+				const cairo_rectangle_int_t *rect)
 {
-    cairo_clip_path_t *clip_path;
-    const cairo_rectangle_int_t *rect;
+    cairo_clip_path_t *clip_path = clip->path;
 
     if (clip == NULL)
 	return FALSE;
 
-    rect = extents->is_bounded ? &extents->bounded : &extents->unbounded;
-
-    clip_path = clip->path;
-
     if (clip_path->extents.x > rect->x ||
 	clip_path->extents.y > rect->y ||
 	clip_path->extents.x + clip_path->extents.width  < rect->x + rect->width ||
@@ -1147,6 +1142,19 @@ _cairo_clip_contains_rectangle (cairo_clip_t *clip,
     return TRUE;
 }
 
+cairo_bool_t
+_cairo_clip_contains_extents (cairo_clip_t *clip,
+			      const cairo_composite_rectangles_t *extents)
+{
+    const cairo_rectangle_int_t *rect;
+
+    if (clip == NULL)
+	return FALSE;
+
+    rect = extents->is_bounded ? &extents->bounded : &extents->unbounded;
+    return _cairo_clip_contains_rectangle (clip, rect);
+}
+
 void
 _cairo_debug_print_clip (FILE *stream, cairo_clip_t *clip)
 {
diff --git a/src/cairo-gl-surface.c b/src/cairo-gl-surface.c
index e2ad7e4..e53506c 100644
--- a/src/cairo-gl-surface.c
+++ b/src/cairo-gl-surface.c
@@ -1487,7 +1487,7 @@ _cairo_gl_surface_stroke (void			        *abstract_surface,
     if (unlikely (status))
 	return status;
 
-    if (_cairo_clip_contains_rectangle (clip, &extents))
+    if (_cairo_clip_contains_extents (clip, &extents))
 	clip = NULL;
 
     if (clip != NULL) {
@@ -1552,7 +1552,7 @@ _cairo_gl_surface_fill (void			*abstract_surface,
     if (unlikely (status))
 	return status;
 
-    if (_cairo_clip_contains_rectangle (clip, &extents))
+    if (_cairo_clip_contains_extents (clip, &extents))
 	clip = NULL;
 
 #if 0
diff --git a/src/cairo-image-surface.c b/src/cairo-image-surface.c
index 383df99..1f8e9b1 100644
--- a/src/cairo-image-surface.c
+++ b/src/cairo-image-surface.c
@@ -3229,7 +3229,7 @@ _cairo_image_surface_paint (void			*abstract_surface,
     if (unlikely (status))
 	return status;
 
-    if (_cairo_clip_contains_rectangle (clip, &extents))
+    if (_cairo_clip_contains_extents (clip, &extents))
 	clip = NULL;
 
     if (clip != NULL) {
@@ -3347,7 +3347,7 @@ _cairo_image_surface_mask (void				*abstract_surface,
     if (unlikely (status))
 	return status;
 
-    if (_cairo_clip_contains_rectangle (clip, &extents))
+    if (_cairo_clip_contains_extents (clip, &extents))
 	clip = NULL;
 
     if (clip != NULL && extents.is_bounded) {
@@ -3581,7 +3581,7 @@ _cairo_image_surface_stroke (void			*abstract_surface,
     if (unlikely (status))
 	return status;
 
-    if (_cairo_clip_contains_rectangle (clip, &extents))
+    if (_cairo_clip_contains_extents (clip, &extents))
 	clip = NULL;
 
     if (clip != NULL) {
@@ -3672,7 +3672,7 @@ _cairo_image_surface_fill (void				*abstract_surface,
     if (unlikely (status))
 	return status;
 
-    if (_cairo_clip_contains_rectangle (clip, &extents))
+    if (_cairo_clip_contains_extents (clip, &extents))
 	clip = NULL;
 
     if (extents.is_bounded && clip != NULL) {
@@ -3991,7 +3991,7 @@ _cairo_image_surface_glyphs (void			*abstract_surface,
     if (unlikely (status))
 	return status;
 
-    if (_cairo_clip_contains_rectangle (clip, &extents))
+    if (_cairo_clip_contains_rectangle (clip, &extents.mask))
 	clip = NULL;
 
     if (clip != NULL && extents.is_bounded) {
diff --git a/src/cairo-surface-fallback.c b/src/cairo-surface-fallback.c
index 1edeac0..99ea07e 100644
--- a/src/cairo-surface-fallback.c
+++ b/src/cairo-surface-fallback.c
@@ -903,7 +903,7 @@ _cairo_surface_fallback_paint (cairo_surface_t		*surface,
     if (unlikely (status))
 	return status;
 
-    if (_cairo_clip_contains_rectangle (clip, &extents))
+    if (_cairo_clip_contains_extents (clip, &extents))
 	clip = NULL;
 
     status = _cairo_clip_to_boxes (&clip, &extents, &clip_boxes, &num_boxes);
@@ -1012,7 +1012,7 @@ _cairo_surface_fallback_mask (cairo_surface_t		*surface,
     if (unlikely (status))
 	return status;
 
-    if (_cairo_clip_contains_rectangle (clip, &extents))
+    if (_cairo_clip_contains_extents (clip, &extents))
 	clip = NULL;
 
     if (clip != NULL && extents.is_bounded) {
@@ -1060,7 +1060,7 @@ _cairo_surface_fallback_stroke (cairo_surface_t		*surface,
     if (unlikely (status))
 	return status;
 
-    if (_cairo_clip_contains_rectangle (clip, &extents))
+    if (_cairo_clip_contains_extents (clip, &extents))
 	clip = NULL;
 
     status = _cairo_clip_to_boxes (&clip, &extents, &clip_boxes, &num_boxes);
@@ -1153,7 +1153,7 @@ _cairo_surface_fallback_fill (cairo_surface_t		*surface,
     if (unlikely (status))
 	return status;
 
-    if (_cairo_clip_contains_rectangle (clip, &extents))
+    if (_cairo_clip_contains_extents (clip, &extents))
 	clip = NULL;
 
     status = _cairo_clip_to_boxes (&clip, &extents, &clip_boxes, &num_boxes);
@@ -1326,7 +1326,7 @@ _cairo_surface_fallback_show_glyphs (cairo_surface_t		*surface,
     if (unlikely (status))
 	return status;
 
-    if (_cairo_clip_contains_rectangle (clip, &extents))
+    if (_cairo_clip_contains_rectangle (clip, &extents.mask))
 	clip = NULL;
 
     if (clip != NULL && extents.is_bounded) {
diff --git a/src/cairo-xcb-surface-render.c b/src/cairo-xcb-surface-render.c
index fef12ec..6e6255e 100644
--- a/src/cairo-xcb-surface-render.c
+++ b/src/cairo-xcb-surface-render.c
@@ -3129,7 +3129,7 @@ _cairo_xcb_surface_render_paint (cairo_xcb_surface_t	*surface,
     if (unlikely (status))
 	return status;
 
-    if (_cairo_clip_contains_rectangle (clip, &extents))
+    if (_cairo_clip_contains_extents (clip, &extents))
 	clip = NULL;
 
     if (clip != NULL) {
@@ -3196,7 +3196,7 @@ _cairo_xcb_surface_render_mask (cairo_xcb_surface_t	*surface,
     if (unlikely (status))
 	return status;
 
-    if (_cairo_clip_contains_rectangle (clip, &extents))
+    if (_cairo_clip_contains_extents (clip, &extents))
 	clip = NULL;
 
     if (clip != NULL && extents.is_bounded) {
@@ -3483,7 +3483,7 @@ _cairo_xcb_surface_render_stroke (cairo_xcb_surface_t	*surface,
     if (unlikely (status))
 	return status;
 
-    if (_cairo_clip_contains_rectangle (clip, &extents))
+    if (_cairo_clip_contains_extents (clip, &extents))
 	clip = NULL;
 
     if (clip != NULL) {
@@ -3666,7 +3666,7 @@ _cairo_xcb_surface_render_fill (cairo_xcb_surface_t	*surface,
     if (unlikely (status))
 	return status;
 
-    if (_cairo_clip_contains_rectangle (clip, &extents))
+    if (_cairo_clip_contains_extents (clip, &extents))
 	clip = NULL;
 
     if (clip != NULL) {
@@ -4630,7 +4630,7 @@ _cairo_xcb_surface_render_glyphs (cairo_xcb_surface_t	*surface,
     if (unlikely (status))
 	return status;
 
-    if (_cairo_clip_contains_rectangle (clip, &extents))
+    if (_cairo_clip_contains_rectangle (clip, &extents.mask))
 	clip = NULL;
 
     if (clip != NULL) {
diff --git a/src/drm/cairo-drm-i915-glyphs.c b/src/drm/cairo-drm-i915-glyphs.c
index 40c8106..9944f15 100644
--- a/src/drm/cairo-drm-i915-glyphs.c
+++ b/src/drm/cairo-drm-i915-glyphs.c
@@ -310,7 +310,7 @@ i915_surface_glyphs (void			*abstract_surface,
     if (unlikely (status))
 	return status;
 
-    if (_cairo_clip_contains_rectangle (clip, &extents))
+    if (_cairo_clip_contains_rectangle (clip, &extents.mask))
 	clip = NULL;
 
     if (clip != NULL && extents.is_bounded) {
diff --git a/src/drm/cairo-drm-i915-surface.c b/src/drm/cairo-drm-i915-surface.c
index f80612c..8d365dd 100644
--- a/src/drm/cairo-drm-i915-surface.c
+++ b/src/drm/cairo-drm-i915-surface.c
@@ -1889,7 +1889,7 @@ i915_surface_fill_with_alpha (void			*abstract_dst,
     if (unlikely (status))
 	return status;
 
-    if (_cairo_clip_contains_rectangle (clip, &extents))
+    if (_cairo_clip_contains_extents (clip, &extents))
 	clip = NULL;
 
     if (extents.is_bounded && clip != NULL) {
@@ -2004,7 +2004,7 @@ i915_surface_paint_with_alpha (void			*abstract_dst,
     if (unlikely (status))
 	return status;
 
-    if (_cairo_clip_contains_rectangle (clip, &extents))
+    if (_cairo_clip_contains_extents (clip, &extents))
 	clip = NULL;
 
     if (clip != NULL) {
@@ -2099,7 +2099,7 @@ i915_surface_mask (void				*abstract_dst,
     if (unlikely (status))
 	return status;
 
-    if (_cairo_clip_contains_rectangle (clip, &extents))
+    if (_cairo_clip_contains_extents (clip, &extents))
 	clip = NULL;
 
     if (clip != NULL && extents.is_bounded) {
@@ -2243,7 +2243,7 @@ i915_surface_stroke (void			*abstract_dst,
     if (unlikely (status))
 	return status;
 
-    if (_cairo_clip_contains_rectangle (clip, &extents))
+    if (_cairo_clip_contains_extents (clip, &extents))
 	clip = NULL;
 
     if (clip != NULL) {
diff --git a/src/drm/cairo-drm-i965-glyphs.c b/src/drm/cairo-drm-i965-glyphs.c
index e1ec95d..c66a63d 100644
--- a/src/drm/cairo-drm-i965-glyphs.c
+++ b/src/drm/cairo-drm-i965-glyphs.c
@@ -252,7 +252,7 @@ i965_surface_glyphs (void			*abstract_surface,
     if (unlikely (status))
 	return status;
 
-    if (clip != NULL && _cairo_clip_contains_rectangle (clip, &extents))
+    if (clip != NULL && _cairo_clip_contains_rectangle (clip, &extents.mask))
 	clip = NULL;
 
     if (clip != NULL && extents.is_bounded) {
diff --git a/src/drm/cairo-drm-i965-surface.c b/src/drm/cairo-drm-i965-surface.c
index a944fb3..e578d6f 100644
--- a/src/drm/cairo-drm-i965-surface.c
+++ b/src/drm/cairo-drm-i965-surface.c
@@ -1110,7 +1110,7 @@ i965_surface_paint (void			*abstract_dst,
     if (unlikely (status))
 	return status;
 
-    if (clip != NULL && _cairo_clip_contains_rectangle (clip, &extents))
+    if (clip != NULL && _cairo_clip_contains_extents (clip, &extents))
 	clip = NULL;
 
     if (clip != NULL) {
@@ -1163,7 +1163,7 @@ i965_surface_mask (void				*abstract_dst,
     if (unlikely (status))
 	return status;
 
-    if (clip != NULL && _cairo_clip_contains_rectangle (clip, &extents))
+    if (clip != NULL && _cairo_clip_contains_extents (clip, &extents))
 	clip = NULL;
 
     if (clip != NULL && extents.is_bounded) {
@@ -1306,7 +1306,7 @@ i965_surface_stroke (void			*abstract_dst,
     if (unlikely (status))
 	return status;
 
-    if (clip != NULL && _cairo_clip_contains_rectangle (clip, &extents))
+    if (clip != NULL && _cairo_clip_contains_extents (clip, &extents))
 	clip = NULL;
 
     if (clip != NULL) {
@@ -1413,7 +1413,7 @@ i965_surface_fill (void			*abstract_dst,
     if (unlikely (status))
 	return status;
 
-    if (clip != NULL && _cairo_clip_contains_rectangle (clip, &extents))
+    if (clip != NULL && _cairo_clip_contains_extents (clip, &extents))
 	clip = NULL;
 
     if (clip != NULL) {
commit 8546a877889bfafc056c867bc9aea25e9fdcdef0
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Mon Jul 12 16:27:29 2010 +0100

    test: Add partial-clip-text
    
    This exercises a bug found by Igor Nikitin:
    
      https://bugs.freedesktop.org/show_bug.cgi?id=29008

diff --git a/test/Makefile.am b/test/Makefile.am
index cfb8104..99d015c 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -948,6 +948,9 @@ REFERENCE_IMAGES = \
 	paint-with-alpha.ref.png \
 	paint-with-alpha.svg.ref.png \
 	paint.ref.png \
+	partial-clip-text.ref.png \
+	partial-clip-text.ps.ref.png \
+	partial-clip-text.svg.ref.png \
 	partial-coverage-half-reference.ref.png \
 	partial-coverage-half-triangles.ref.png \
 	partial-coverage-intersecting-quads.ref.png \
diff --git a/test/Makefile.sources b/test/Makefile.sources
index 99aab70..42afafd 100644
--- a/test/Makefile.sources
+++ b/test/Makefile.sources
@@ -182,6 +182,7 @@ test_sources = \
 	paint-repeat.c					\
 	paint-source-alpha.c				\
 	paint-with-alpha.c				\
+	partial-clip-text.c				\
 	partial-coverage.c				\
 	path-append.c					\
 	path-stroke-twice.c				\
diff --git a/test/partial-clip-text.c b/test/partial-clip-text.c
new file mode 100644
index 0000000..f467a5f
--- /dev/null
+++ b/test/partial-clip-text.c
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2010 Igor Nikitin
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Author: Igor Nikitin <igor_nikitin at valentina-db.com>
+ */
+
+#include "cairo-test.h"
+
+static cairo_test_status_t
+draw (cairo_t *cr, int width, int height)
+{
+     cairo_set_source_rgb( cr, 0, 0, 0 );
+     cairo_paint (cr);
+
+     cairo_rectangle (cr, 0, 0, 40, 5);
+     cairo_clip (cr);
+
+     cairo_move_to (cr, 0, 12);
+     cairo_set_source_rgb (cr, 1, 1, 1);
+     cairo_show_text (cr, "CAIRO");
+
+     return CAIRO_TEST_SUCCESS;
+}
+
+CAIRO_TEST (partial_clip_text,
+	    "Tests drawing text through a single, partial clip.",
+	    "clip, text", /* keywords */
+	    NULL, /* requirements */
+	    40, 15,
+	    NULL, draw)
diff --git a/test/partial-clip-text.ps.ref.png b/test/partial-clip-text.ps.ref.png
new file mode 100644
index 0000000..049bba5
Binary files /dev/null and b/test/partial-clip-text.ps.ref.png differ
diff --git a/test/partial-clip-text.ref.png b/test/partial-clip-text.ref.png
new file mode 100644
index 0000000..6deaf75
Binary files /dev/null and b/test/partial-clip-text.ref.png differ
diff --git a/test/partial-clip-text.svg.ref.png b/test/partial-clip-text.svg.ref.png
new file mode 100644
index 0000000..dc3fc58
Binary files /dev/null and b/test/partial-clip-text.svg.ref.png differ


More information about the cairo-commit mailing list