[cairo-commit] 5 commits - perf/cairo-perf.c perf/Makefile.am src/cairo-clip.c src/cairo-clip-private.h src/cairo-xlib-surface.c test/cairo-test.c test/Makefile.am

Chris Wilson ickle at kemper.freedesktop.org
Fri Oct 19 16:34:44 PDT 2007


 perf/Makefile.am         |    4 -
 perf/cairo-perf.c        |  121 ++++++++++++++++++++------------
 src/cairo-clip-private.h |    2 
 src/cairo-clip.c         |   86 ++++++++++++++++++++---
 src/cairo-xlib-surface.c |   17 ++--
 test/Makefile.am         |    2 
 test/cairo-test.c        |  173 ++++++++++++++++++++++++++++++-----------------
 7 files changed, 279 insertions(+), 126 deletions(-)

New commits:
commit ae2535e4cb7c09eda1be13079d7a23b262aaef7b
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Fri Oct 19 23:25:57 2007 +0100

    [cairo-perf] Run performance tests over similar surfaces as well.
    
    Immediately repeat the performance test against a similar surface to
    ensure that they introduce no regressions. Primarily introduced to
    sanity check the change to use XShmPixmaps instead of XPixmaps in the
    xlib backend, but it should be generally useful.

diff --git a/perf/cairo-perf.c b/perf/cairo-perf.c
index 388bfa7..de88a87 100644
--- a/perf/cairo-perf.c
+++ b/perf/cairo-perf.c
@@ -105,27 +105,45 @@ target_is_measurable (cairo_boilerplate_target_t *target)
 }
 
 static const char *
-_content_to_string (cairo_content_t content)
+_content_to_string (cairo_content_t content, cairo_bool_t similar)
 {
-    switch (content) {
+    switch (content|similar) {
     case CAIRO_CONTENT_COLOR:
 	return "rgb";
+    case CAIRO_CONTENT_COLOR|1:
+	return "rgb&";
     case CAIRO_CONTENT_ALPHA:
 	return "a";
+    case CAIRO_CONTENT_ALPHA|1:
+	return "a&";
     case CAIRO_CONTENT_COLOR_ALPHA:
 	return "rgba";
+    case CAIRO_CONTENT_COLOR_ALPHA|1:
+	return "rgba&";
     default:
 	return "<unknown_content>";
     }
 }
 
+static cairo_bool_t
+cairo_perf_has_similar (cairo_perf_t *perf)
+{
+    cairo_surface_t *target = cairo_get_target (perf->cr);
+
+    /* exclude the image backend */
+    if (cairo_surface_get_type (target) == CAIRO_SURFACE_TYPE_IMAGE)
+	return FALSE;
+
+    return TRUE;
+}
+
 void
 cairo_perf_run (cairo_perf_t		*perf,
 		const char		*name,
 		cairo_perf_func_t	 perf_func)
 {
     static cairo_bool_t first_run = TRUE;
-    unsigned int i;
+    unsigned int i, similar, has_similar;
     cairo_perf_ticks_t *times;
     cairo_stats_t stats = {0.0, 0.0};
     int low_std_dev_count;
@@ -156,56 +174,67 @@ cairo_perf_run (cairo_perf_t		*perf,
 
     times = xmalloc (perf->iterations * sizeof (cairo_perf_ticks_t));
 
-    /* We run one iteration in advance to warm caches, etc. */
-    cairo_perf_yield ();
-    (perf_func) (perf->cr, perf->size, perf->size);
-
-    low_std_dev_count = 0;
-    for (i =0; i < perf->iterations; i++) {
+    has_similar = cairo_perf_has_similar (perf);
+    for (similar = 0; similar <= has_similar; similar++) {
+	/* We run one iteration in advance to warm caches, etc. */
 	cairo_perf_yield ();
-	times[i] = (perf_func) (perf->cr, perf->size, perf->size);
+	if (similar)
+	    cairo_push_group_with_content (perf->cr, perf->target->content);
+	(perf_func) (perf->cr, perf->size, perf->size);
+	if (similar)
+	    cairo_pattern_destroy (cairo_pop_group (perf->cr));
+
+	low_std_dev_count = 0;
+	for (i =0; i < perf->iterations; i++) {
+	    cairo_perf_yield ();
+	    if (similar)
+		cairo_push_group_with_content (perf->cr, perf->target->content);
+	    times[i] = (perf_func) (perf->cr, perf->size, perf->size);
+	    if (similar)
+		cairo_pattern_destroy (cairo_pop_group (perf->cr));
+
+	    if (perf->raw) {
+		if (i == 0)
+		    printf ("[*] %s-%s %s-%d %g",
+			    perf->target->name,
+			    _content_to_string (perf->target->content, similar),
+			    name, perf->size,
+			    cairo_perf_ticks_per_second () / 1000.0);
+		printf (" %lld", times[i]);
+	    } else if (! perf->exact_iterations) {
+		if (i > 0) {
+		    _cairo_stats_compute (&stats, times, i+1);
+
+		    if (stats.std_dev <= CAIRO_PERF_LOW_STD_DEV)
+		    {
+			low_std_dev_count++;
+			if (low_std_dev_count >= CAIRO_PERF_STABLE_STD_DEV_COUNT)
+			    break;
+		    } else {
+			low_std_dev_count = 0;
+		    }
+		}
+	    }
+	}
 
 	if (perf->raw) {
-	    if (i == 0)
-		printf ("[*] %s-%s %s-%d %g",
-			perf->target->name,
-			_content_to_string (perf->target->content),
-			name, perf->size,
-			cairo_perf_ticks_per_second () / 1000.0);
-	    printf (" %lld", times[i]);
+	    printf ("\n");
 	} else {
-	    if (i > 0) {
-		_cairo_stats_compute (&stats, times, i+1);
-
-		if (stats.std_dev <= CAIRO_PERF_LOW_STD_DEV &&
-		    ! perf->exact_iterations)
-		{
-		    low_std_dev_count++;
-		    if (low_std_dev_count >= CAIRO_PERF_STABLE_STD_DEV_COUNT)
-			break;
-		} else {
-		    low_std_dev_count = 0;
-		}
-	    }
+	    _cairo_stats_compute (&stats, times, i);
+	    printf ("[%3d] %8s-%-5s %26s-%-3d ",
+		    perf->test_number, perf->target->name,
+		    _content_to_string (perf->target->content, similar),
+		    name, perf->size);
+
+	    printf ("%10lld %#8.3f %#8.3f %#5.2f%% %3d\n",
+		    stats.min_ticks,
+		    (stats.min_ticks * 1000.0) / cairo_perf_ticks_per_second (),
+		    (stats.median_ticks * 1000.0) / cairo_perf_ticks_per_second (),
+		    stats.std_dev * 100.0, stats.iterations);
 	}
-    }
 
-    if (perf->raw) {
-	printf ("\n");
-    } else {
-	printf ("[%3d] %8s-%-4s %26s-%-3d ",
-		perf->test_number, perf->target->name,
-		_content_to_string (perf->target->content),
-		name, perf->size);
-
-	printf ("%10lld %#8.3f %#8.3f %#5.2f%% %3d\n",
-		stats.min_ticks,
-		(stats.min_ticks * 1000.0) / cairo_perf_ticks_per_second (),
-		(stats.median_ticks * 1000.0) / cairo_perf_ticks_per_second (),
-		stats.std_dev * 100.0, stats.iterations);
+	perf->test_number++;
     }
-
-    perf->test_number++;
     free (times);
 }
 
commit 081507a09e61e1e4a048e40f8ba67a76aa76bbef
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Fri Oct 19 22:26:28 2007 +0100

    [cairo-test] Repeat tests for similar surfaces.
    
    Having noticed strange discrepancies creeping into similar surfaces
    whilst working on the xlib backend, I thought it wise to also run
    the test harness against similar targets. For consistency, only
    targets whose similar surface use the same backend are included.
    
    This can be disabled by exporting CAIRO_TEST_IGNORE_SIMILAR=1.

diff --git a/test/cairo-test.c b/test/cairo-test.c
index 500bb16..de8ed1b 100755
--- a/test/cairo-test.c
+++ b/test/cairo-test.c
@@ -204,10 +204,47 @@ done:
     return ref_name;
 }
 
+static cairo_bool_t
+cairo_test_target_has_similar (const cairo_test_t *test, cairo_boilerplate_target_t *target)
+{
+    cairo_surface_t *surface;
+    cairo_bool_t has_similar = FALSE;
+
+    /* ignore image intermediate targets */
+    if (target->expected_type == CAIRO_SURFACE_TYPE_IMAGE)
+	return FALSE;
+
+    if (getenv ("CAIRO_TEST_IGNORE_SIMILAR"))
+	return FALSE;
+
+    surface = (target->create_surface) (test->name,
+					target->content,
+					test->width,
+					test->height,
+					CAIRO_BOILERPLATE_MODE_TEST,
+					&target->closure);
+    if (surface != NULL) {
+	cairo_t * cr = cairo_create (surface);
+	cairo_surface_t *similar;
+	cairo_push_group_with_content (cr, target->content);
+	similar = cairo_get_target (cr);
+	has_similar = cairo_surface_get_type (similar) == cairo_surface_get_type (surface);
+
+	cairo_destroy (cr);
+	cairo_surface_destroy (surface);
+
+	if (target->cleanup)
+	    target->cleanup (target->closure);
+    }
+
+    return has_similar;
+}
+
 static cairo_test_status_t
 cairo_test_for_target (cairo_test_t			 *test,
 		       cairo_boilerplate_target_t	 *target,
-		       int				  dev_offset)
+		       int				  dev_offset,
+		       cairo_bool_t                       similar)
 {
     cairo_test_status_t status;
     cairo_surface_t *surface = NULL;
@@ -225,16 +262,18 @@ cairo_test_for_target (cairo_test_t			 *test,
     else
 	offset_str = strdup("");
 
-    xasprintf (&png_name, "%s-%s-%s%s%s",
+    xasprintf (&png_name, "%s-%s-%s%s%s%s",
 	       test->name,
 	       target->name,
 	       format,
+	       similar ? "-similar" : "",
 	       offset_str, CAIRO_TEST_PNG_SUFFIX);
     ref_name = cairo_ref_name_for_test_target_format (test->name, target->name, format);
-    xasprintf (&diff_name, "%s-%s-%s%s%s",
+    xasprintf (&diff_name, "%s-%s-%s%s%s%s",
 	       test->name,
 	       target->name,
 	       format,
+	       similar ? "-similar" : "",
 	       offset_str, CAIRO_TEST_DIFF_SUFFIX);
 
     if (target->is_vector) {
@@ -301,6 +340,8 @@ cairo_test_for_target (cairo_test_t			 *test,
     cairo_surface_set_device_offset (surface, dev_offset, dev_offset);
 
     cr = cairo_create (surface);
+    if (similar)
+	cairo_push_group_with_content (cr, target->content);
 
     /* Clear to transparent (or black) depending on whether the target
      * surface supports alpha. */
@@ -327,6 +368,11 @@ cairo_test_for_target (cairo_test_t			 *test,
 	goto UNWIND_CAIRO;
     }
 
+    if (similar) {
+	cairo_pop_group_to_source (cr);
+	cairo_paint (cr);
+    }
+
     if (cairo_status (cr) != CAIRO_STATUS_SUCCESS) {
 	cairo_test_log ("Error: Function under test left cairo status in an error state: %s\n",
 			cairo_status_to_string (cairo_status (cr)));
@@ -409,7 +455,7 @@ cairo_test_expecting (cairo_test_t *test,
 {
     /* we use volatile here to make sure values are not clobbered
      * by longjmp */
-    volatile size_t i, j, num_targets;
+    volatile size_t i, j, num_targets, similar, has_similar;
     volatile cairo_bool_t limited_targets = FALSE, print_fail_on_stdout = TRUE;
 #ifdef HAVE_SIGNAL_H
     void (*old_segfault_handler)(int);
@@ -462,83 +508,90 @@ cairo_test_expecting (cairo_test_t *test,
      * Also, on a crash, run no further tests.
      */
     status = ret = CAIRO_TEST_UNTESTED;
-    for (i = 0; i < num_targets && status != CAIRO_TEST_CRASHED; i++) {
+    for (i = 0; i < num_targets; i++) {
 	for (j = 0; j < NUM_DEVICE_OFFSETS; j++) {
 	    cairo_boilerplate_target_t * volatile target = targets_to_test[i];
 	    volatile int dev_offset = j * 25;
-
-	    cairo_test_log ("Testing %s with %s target (dev offset %d)\n", test->name, target->name, dev_offset);
-	    printf ("%s-%s-%s [%d]:\t", test->name, target->name,
-		    cairo_boilerplate_content_name (target->content),
-		    dev_offset);
+	    has_similar = cairo_test_target_has_similar (test, target);
+	    for (similar = 0; similar <= has_similar ; similar++) {
+		cairo_test_log ("Testing %s with %s%s target (dev offset %d)\n", test->name, similar ? " (similar)" : "", target->name, dev_offset);
+		printf ("%s-%s-%s [%d]%s:\t", test->name, target->name,
+			cairo_boilerplate_content_name (target->content),
+			dev_offset,
+			similar ? " (similar)": "");
 
 #ifdef HAVE_SIGNAL_H
-	    /* Set up a checkpoint to get back to in case of segfaults. */
-	    old_segfault_handler = signal (SIGSEGV, segfault_handler);
-	    if (0 == setjmp (jmpbuf))
+		/* Set up a checkpoint to get back to in case of segfaults. */
+		old_segfault_handler = signal (SIGSEGV, segfault_handler);
+		if (0 == setjmp (jmpbuf))
 #endif
-		status = cairo_test_for_target (test, target, dev_offset);
+		    status = cairo_test_for_target (test, target, dev_offset, similar);
 #ifdef HAVE_SIGNAL_H
-	    else
-	        status = CAIRO_TEST_CRASHED;
-	    signal (SIGSEGV, old_segfault_handler);
+		else
+		    status = CAIRO_TEST_CRASHED;
+		signal (SIGSEGV, old_segfault_handler);
 #endif
 
-	    cairo_test_log ("TEST: %s TARGET: %s FORMAT: %s OFFSET: %d RESULT: ",
-			    test->name, target->name,
-			    cairo_boilerplate_content_name (target->content),
-			    dev_offset);
-
-	    switch (status) {
-	    case CAIRO_TEST_SUCCESS:
-		printf ("PASS\n");
-		cairo_test_log ("PASS\n");
-		if (ret == CAIRO_TEST_UNTESTED)
-		    ret = CAIRO_TEST_SUCCESS;
-		break;
-	    case CAIRO_TEST_UNTESTED:
-		printf ("UNTESTED\n");
-		cairo_test_log ("UNTESTED\n");
-		break;
-	    case CAIRO_TEST_CRASHED:
-		if (print_fail_on_stdout) {
-		    printf ("!!!CRASHED!!!\n");
-		} else {
-		    /* eat the test name */
-		    printf ("\r");
-		    fflush (stdout);
-		}
-		cairo_test_log ("CRASHED\n");
-		fprintf (stderr, "%s-%s-%s [%d]:\t%s!!!CRASHED!!!%s\n",
-			 test->name, target->name,
-			 cairo_boilerplate_content_name (target->content), dev_offset,
-			 fail_face, normal_face);
-		ret = CAIRO_TEST_FAILURE;
-		break;
-	    default:
-	    case CAIRO_TEST_FAILURE:
-		if (expectation == CAIRO_TEST_FAILURE) {
-		    printf ("XFAIL\n");
-		    cairo_test_log ("XFAIL\n");
-		} else {
+		cairo_test_log ("TEST: %s TARGET: %s FORMAT: %s OFFSET: %d SIMILAR: %d RESULT: ",
+				test->name, target->name,
+				cairo_boilerplate_content_name (target->content),
+				dev_offset, similar);
+
+		switch (status) {
+		case CAIRO_TEST_SUCCESS:
+		    printf ("PASS\n");
+		    cairo_test_log ("PASS\n");
+		    if (ret == CAIRO_TEST_UNTESTED)
+			ret = CAIRO_TEST_SUCCESS;
+		    break;
+		case CAIRO_TEST_UNTESTED:
+		    printf ("UNTESTED\n");
+		    cairo_test_log ("UNTESTED\n");
+		    break;
+		case CAIRO_TEST_CRASHED:
 		    if (print_fail_on_stdout) {
-			printf ("FAIL\n");
+			printf ("!!!CRASHED!!!\n");
 		    } else {
 			/* eat the test name */
 			printf ("\r");
 			fflush (stdout);
 		    }
-		    fprintf (stderr, "%s-%s-%s [%d]:\t%sFAIL%s\n",
+		    cairo_test_log ("CRASHED\n");
+		    fprintf (stderr, "%s-%s-%s [%d]%s:\t%s!!!CRASHED!!!%s\n",
 			     test->name, target->name,
-			     cairo_boilerplate_content_name (target->content), dev_offset,
+			     cairo_boilerplate_content_name (target->content), dev_offset, similar ? " (similar)" : "",
 			     fail_face, normal_face);
-		    cairo_test_log ("FAIL\n");
+		    ret = CAIRO_TEST_FAILURE;
+		    break;
+		default:
+		case CAIRO_TEST_FAILURE:
+		    if (expectation == CAIRO_TEST_FAILURE) {
+			printf ("XFAIL\n");
+			cairo_test_log ("XFAIL\n");
+		    } else {
+			if (print_fail_on_stdout) {
+			    printf ("FAIL\n");
+			} else {
+			    /* eat the test name */
+			    printf ("\r");
+			    fflush (stdout);
+			}
+			fprintf (stderr, "%s-%s-%s [%d]%s:\t%sFAIL%s\n",
+				 test->name, target->name,
+				 cairo_boilerplate_content_name (target->content), dev_offset, similar ? " (similar)" : "",
+				 fail_face, normal_face);
+			cairo_test_log ("FAIL\n");
+		    }
+		    ret = status;
+		    break;
 		}
-		ret = status;
-		break;
+
+		if (status == CAIRO_TEST_CRASHED)
+		    goto out;
 	    }
 	}
     }
+out:
 
     if (ret != CAIRO_TEST_SUCCESS)
         printf ("Check %s%s out for more information.\n", test->name, CAIRO_TEST_LOG_SUFFIX);
commit 3211d810d31a6607c8d78a50f577a8ca8eb705e6
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Fri Oct 19 22:45:15 2007 +0100

    [cairo-xlib] Check source for XRender support.
    
    Do not rely on the assumption that if the destination has render support
    then the source has it as well - breaks when the boilerplate disables
    render support for a surface.
    
    Similarly do not set the XRender attributes on the source surface
    unless it actually has a xrender_format.

diff --git a/src/cairo-xlib-surface.c b/src/cairo-xlib-surface.c
index c8126af..f5267e1 100644
--- a/src/cairo-xlib-surface.c
+++ b/src/cairo-xlib-surface.c
@@ -1198,10 +1198,8 @@ _recategorize_composite_operation (cairo_xlib_surface_t	      *dst,
 	return DO_XCOPYAREA;
     }
 
-    if (!dst->buggy_repeat)
-	return DO_RENDER;
-
-    if (is_integer_translation &&
+    if (dst->buggy_repeat &&
+	is_integer_translation &&
 	src_attr->extend == CAIRO_EXTEND_REPEAT &&
 	(src->width != 1 || src->height != 1))
     {
@@ -1215,6 +1213,9 @@ _recategorize_composite_operation (cairo_xlib_surface_t	      *dst,
 	return DO_UNSUPPORTED;
     }
 
+    if (!CAIRO_SURFACE_RENDER_HAS_COMPOSITE (src))
+	return DO_UNSUPPORTED;
+
     return DO_RENDER;
 }
 
@@ -1319,13 +1320,13 @@ _cairo_xlib_surface_composite (cairo_operator_t		op,
 	goto BAIL;
     }
 
-    status = _cairo_xlib_surface_set_attributes (src, &src_attr);
-    if (status)
-	goto BAIL;
-
     switch (operation)
     {
     case DO_RENDER:
+	status = _cairo_xlib_surface_set_attributes (src, &src_attr);
+	if (status)
+	    goto BAIL;
+
 	_cairo_xlib_surface_ensure_dst_picture (dst);
 	if (mask) {
 	    status = _cairo_xlib_surface_set_attributes (mask, &mask_attr);
commit 5c08226a0f7bc373a96fe75d15ad854910eb3265
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Fri Oct 19 16:04:33 2007 +0100

    [cairo-clip] Avoid work when all clipped out.
    
    When the clip mask is empty we perform actions like composite 0x0
    surfaces, which results in a lot of unnecessary work and allocations.
    Avoid doing work when we know everything is clip out and take the
    liberty of freeing any memory associated with the clop state.

diff --git a/src/cairo-clip-private.h b/src/cairo-clip-private.h
index c2fe494..2e1eabd 100644
--- a/src/cairo-clip-private.h
+++ b/src/cairo-clip-private.h
@@ -53,6 +53,8 @@ struct _cairo_clip_path {
 struct _cairo_clip {
     cairo_clip_mode_t mode;
 
+    cairo_bool_t all_clipped;
+
     /*
      * Mask-based clipping for cases where the backend
      * clipping isn't sufficiently able.
diff --git a/src/cairo-clip.c b/src/cairo-clip.c
index 387e26e..8254105 100644
--- a/src/cairo-clip.c
+++ b/src/cairo-clip.c
@@ -54,6 +54,8 @@ _cairo_clip_init (cairo_clip_t *clip, cairo_surface_t *target)
     else
 	clip->mode = CAIRO_CLIP_MODE_MASK;
 
+    clip->all_clipped = FALSE;
+
     clip->surface = NULL;
     clip->surface_rect.x = 0;
     clip->surface_rect.y = 0;
@@ -73,6 +75,8 @@ _cairo_clip_init_copy (cairo_clip_t *clip, cairo_clip_t *other)
 {
     clip->mode = other->mode;
 
+    clip->all_clipped = other->all_clipped;
+
     clip->surface = cairo_surface_reference (other->surface);
     clip->surface_rect = other->surface_rect;
 
@@ -81,12 +85,12 @@ _cairo_clip_init_copy (cairo_clip_t *clip, cairo_clip_t *other)
     _cairo_region_init (&clip->region);
 
     if (other->has_region) {
-	if (_cairo_region_copy (&clip->region, &other->region) !=
-            CAIRO_STATUS_SUCCESS)
-        {
+	cairo_status_t status;
+	status = _cairo_region_copy (&clip->region, &other->region);
+	if (status) {
 	    _cairo_region_fini (&clip->region);
 	    cairo_surface_destroy (clip->surface);
-	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+	    return status;
 	}
         clip->has_region = TRUE;
     } else {
@@ -94,13 +98,15 @@ _cairo_clip_init_copy (cairo_clip_t *clip, cairo_clip_t *other)
     }
 
     clip->path = _cairo_clip_path_reference (other->path);
-    
+
     return CAIRO_STATUS_SUCCESS;
 }
 
 void
 _cairo_clip_reset (cairo_clip_t *clip)
 {
+    clip->all_clipped = FALSE;
+
     /* destroy any existing clip-region artifacts */
     cairo_surface_destroy (clip->surface);
     clip->surface = NULL;
@@ -121,9 +127,19 @@ _cairo_clip_reset (cairo_clip_t *clip)
     clip->path = NULL;
 }
 
+static void
+_cairo_clip_set_all_clipped (cairo_clip_t *clip, cairo_surface_t *target)
+{
+    _cairo_clip_reset (clip);
+
+    clip->all_clipped = TRUE;
+    clip->serial = _cairo_surface_allocate_clip_serial (target);
+}
+
+
 static cairo_status_t
 _cairo_clip_path_intersect_to_rectangle (cairo_clip_path_t       *clip_path,
-   				         cairo_rectangle_int_t   *rectangle)
+				         cairo_rectangle_int_t   *rectangle)
 {
     while (clip_path) {
         cairo_status_t status;
@@ -161,9 +177,14 @@ _cairo_clip_intersect_to_rectangle (cairo_clip_t            *clip,
     if (!clip)
 	return CAIRO_STATUS_SUCCESS;
 
+    if (clip->all_clipped) {
+	*rectangle = clip->surface_rect;
+	return CAIRO_STATUS_SUCCESS;
+    }
+
     if (clip->path) {
         cairo_status_t status;
-        
+
         status = _cairo_clip_path_intersect_to_rectangle (clip->path,
                                                           rectangle);
         if (status)
@@ -203,6 +224,18 @@ _cairo_clip_intersect_to_region (cairo_clip_t      *clip,
     if (!clip)
 	return CAIRO_STATUS_SUCCESS;
 
+    if (clip->all_clipped) {
+	cairo_region_t clip_rect;
+
+	_cairo_region_init_rect (&clip_rect, &clip->surface_rect);
+
+	status = _cairo_region_intersect (region, &clip_rect, region);
+
+	_cairo_region_fini (&clip_rect);
+
+	return status;
+    }
+
     if (clip->path) {
 	/* Intersect clip path into region. */
     }
@@ -244,6 +277,9 @@ _cairo_clip_combine_to_surface (cairo_clip_t                  *clip,
     cairo_pattern_union_t pattern;
     cairo_status_t status;
 
+    if (clip->all_clipped)
+	return CAIRO_STATUS_SUCCESS;
+
     _cairo_pattern_init_for_surface (&pattern.surface, clip->surface);
 
     status = _cairo_surface_composite (op,
@@ -324,6 +360,7 @@ _cairo_clip_path_destroy (cairo_clip_path_t *clip_path)
     free (clip_path);
 }
 
+
 static cairo_int_status_t
 _cairo_clip_intersect_region (cairo_clip_t    *clip,
 			      cairo_traps_t   *traps,
@@ -332,6 +369,9 @@ _cairo_clip_intersect_region (cairo_clip_t    *clip,
     cairo_region_t region;
     cairo_int_status_t status;
 
+    if (clip->all_clipped)
+	return CAIRO_STATUS_SUCCESS;
+
     if (clip->mode != CAIRO_CLIP_MODE_REGION)
 	return CAIRO_INT_STATUS_UNSUPPORTED;
 
@@ -363,6 +403,9 @@ _cairo_clip_intersect_region (cairo_clip_t    *clip,
     clip->serial = _cairo_surface_allocate_clip_serial (target);
     _cairo_region_fini (&region);
 
+    if (! _cairo_region_not_empty (&clip->region))
+	_cairo_clip_set_all_clipped (clip, target);
+
     return status;
 }
 
@@ -378,6 +421,9 @@ _cairo_clip_intersect_mask (cairo_clip_t      *clip,
     cairo_surface_t *surface;
     cairo_status_t status;
 
+    if (clip->all_clipped)
+	return CAIRO_STATUS_SUCCESS;
+
     /* Represent the clip as a mask surface.  We create a new surface
      * the size of the intersection of the old mask surface and the
      * extents of the new clip path. */
@@ -395,6 +441,14 @@ _cairo_clip_intersect_mask (cairo_clip_t      *clip,
     if (!status)
 	_cairo_rectangle_intersect (&surface_rect, &target_rect);
 
+    if (surface_rect.width == 0 || surface_rect.height == 0) {
+	surface = NULL;
+	status = CAIRO_STATUS_SUCCESS;
+	if (clip->surface != NULL)
+	    cairo_surface_destroy (clip->surface);
+	goto DONE;
+    }
+
     _cairo_pattern_init_solid (&pattern.solid, CAIRO_COLOR_WHITE,
 			       CAIRO_CONTENT_COLOR);
     surface = _cairo_surface_create_similar_solid (target,
@@ -458,10 +512,14 @@ _cairo_clip_intersect_mask (cairo_clip_t      *clip,
 	cairo_surface_destroy (clip->surface);
     }
 
+ DONE:
     clip->surface = surface;
     clip->surface_rect = surface_rect;
     clip->serial = _cairo_surface_allocate_clip_serial (target);
 
+    if (surface_rect.width == 0 || surface_rect.height == 0)
+	_cairo_clip_set_all_clipped (clip, target);
+
     return status;
 }
 
@@ -476,6 +534,9 @@ _cairo_clip_clip (cairo_clip_t       *clip,
     cairo_status_t status;
     cairo_traps_t traps;
 
+    if (clip->all_clipped)
+	return CAIRO_STATUS_SUCCESS;
+
     status = _cairo_clip_intersect_path (clip,
 					 path, fill_rule, tolerance,
 					 antialias);
@@ -510,6 +571,9 @@ _cairo_clip_translate (cairo_clip_t  *clip,
                        cairo_fixed_t  tx,
                        cairo_fixed_t  ty)
 {
+    if (clip->all_clipped)
+	return;
+
     if (clip->has_region) {
         _cairo_region_translate (&clip->region,
                                  _cairo_fixed_integer_part (tx),
@@ -639,7 +703,10 @@ _cairo_clip_copy_rectangle_list (cairo_clip_t *clip, cairo_gstate_t *gstate)
 {
     cairo_rectangle_list_t *list;
     cairo_rectangle_t *rectangles = NULL;
-    int n_boxes;
+    int n_boxes = 0;
+
+    if (clip->all_clipped)
+	goto DONE;
 
     if (clip->path || clip->surface)
 	return (cairo_rectangle_list_t*) &_cairo_rectangles_not_representable;
@@ -692,13 +759,14 @@ _cairo_clip_copy_rectangle_list (cairo_clip_t *clip, cairo_gstate_t *gstate)
 	}
     }
 
+ DONE:
     list = malloc (sizeof (cairo_rectangle_list_t));
     if (list == NULL) {
         free (rectangles);
 	_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
         return (cairo_rectangle_list_t*) &_cairo_rectangles_nil;
     }
-    
+
     list->status = CAIRO_STATUS_SUCCESS;
     list->rectangles = rectangles;
     list->num_rectangles = n_boxes;
commit c70c2cf6d6a71df54515175af0cb1651b67bdb86
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Fri Oct 19 23:31:36 2007 +0100

    [Makefile.am] Fix ${top_srcdir}/libtool
    
    libtool exists in the top level build directory, but in a couple of
    places we refer to the top level source directory.

diff --git a/perf/Makefile.am b/perf/Makefile.am
index 7814be5..4701abf 100644
--- a/perf/Makefile.am
+++ b/perf/Makefile.am
@@ -104,14 +104,14 @@ CLEANFILES = \
 check-valgrind perf-valgrind:
 	$(MAKE) $(AM_MAKEFLAGS) check \
 	    TESTS_ENVIRONMENT='$(TESTS_ENVIRONMENT) \
-	    $(top_srcdir)/libtool --mode=execute \
+	    $(top_builddir)/libtool --mode=execute \
 	    valgrind $(VALGRIND_MEMCHECK_FLAGS) $(EXTRA_VALGRIND_FLAGS)' \
 	    | tee valgrind-log
 
 perf-callgrind:
 	$(MAKE) $(AM_MAKEFLAGS) check \
 	    TESTS_ENVIRONMENT='$(TESTS_ENVIRONMENT) \
-	    $(top_srcdir)/libtool --mode=execute \
+	    $(top_builddir)/libtool --mode=execute \
 	    valgrind $(VALGRIND_CALLGRIND_FLAGS) $(EXTRA_VALGRIND_FLAGS)'
 
 .PHONY: perf html check-valgrind perf-valgrind perf-callgrind
diff --git a/test/Makefile.am b/test/Makefile.am
index 3785568..114ae78 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -578,7 +578,7 @@ clean-local:
 # Check tests under valgrind
 # Saves log to valgrind-log
 check-valgrind:
-	$(MAKE) $(AM_MAKEFLAGS) check TESTS_ENVIRONMENT='$(TESTS_ENVIRONMENT) $(top_srcdir)/libtool --mode=execute valgrind $(VALGRIND_FLAGS)' 2>&1 | tee valgrind-log
+	$(MAKE) $(AM_MAKEFLAGS) check TESTS_ENVIRONMENT='$(TESTS_ENVIRONMENT) $(top_builddir)/libtool --mode=execute valgrind $(VALGRIND_FLAGS)' 2>&1 | tee valgrind-log
 
 # The following definitions both should work.
 #FAILED_TESTS = `grep -l '\<FAIL\>' $(TESTS:=.log) 2>/dev/null | sed -e 's/[.]log$$//' | xargs echo`


More information about the cairo-commit mailing list