b=562574 fixes for cairo_copy_clip_rectangle_list and empty cairo_clip_extents r=jrmuizel

--HG--
extra : rebase_source : 7559cb07311c0328d62a625c631a6ab822934b0d
This commit is contained in:
Karl Tomlinson 2010-07-23 10:22:51 +12:00
Родитель 72e4ce62b7
Коммит 44ee4169cd
6 изменённых файлов: 305 добавлений и 49 удалений

Просмотреть файл

@ -128,6 +128,12 @@ win32-transparent-surface.patch: add API so we can create a win32 surface for an
cairo_qt_glyphs.patch: Drop X surface from Qt surface, add support for new qt glyphs api
empty-clip-rectangles.patch: f2fa15680ec3ac95cb68d4957557f06561a7dc55
empty-clip-extents.patch: b79ea8a6cab8bd28aebecf6e1e8229d5ac017264
clip-rects-surface-extents.patch: 108b1c7825116ed3f93aa57384bbd3290cdc9181
==== pixman patches ====
pixman-android-cpu-detect.patch: Add CPU detection support for Android, where we can't reliably access /proc/self/auxv.

Просмотреть файл

@ -1311,9 +1311,14 @@ _cairo_clip_combine_with_surface (cairo_clip_t *clip,
return CAIRO_STATUS_SUCCESS;
}
static const cairo_rectangle_int_t _cairo_empty_rectangle_int = { 0, 0, 0, 0 };
const cairo_rectangle_int_t *
_cairo_clip_get_extents (const cairo_clip_t *clip)
{
if (clip->all_clipped)
return &_cairo_empty_rectangle_int;
if (clip->path == NULL)
return NULL;
@ -1453,7 +1458,7 @@ _cairo_rectangle_list_create_in_error (cairo_status_t status)
cairo_rectangle_list_t *
_cairo_clip_copy_rectangle_list (cairo_clip_t *clip, cairo_gstate_t *gstate)
{
#define ERROR_LIST(S) _cairo_rectangle_list_create_in_error (_cairo_error (S));
#define ERROR_LIST(S) _cairo_rectangle_list_create_in_error (_cairo_error (S))
cairo_rectangle_list_t *list;
cairo_rectangle_t *rectangles = NULL;
@ -1462,57 +1467,40 @@ _cairo_clip_copy_rectangle_list (cairo_clip_t *clip, cairo_gstate_t *gstate)
int n_rects = 0;
int i;
if (clip != NULL && clip->path != NULL) {
status = _cairo_clip_get_region (clip, &region);
if (status == CAIRO_INT_STATUS_NOTHING_TO_DO) {
goto DONE;
} else if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
return ERROR_LIST (CAIRO_STATUS_CLIP_NOT_REPRESENTABLE)
} else if (unlikely (status)) {
return ERROR_LIST (status);
}
if (clip->all_clipped)
goto DONE;
if (!clip->path)
return ERROR_LIST (CAIRO_STATUS_CLIP_NOT_REPRESENTABLE);
status = _cairo_clip_get_region (clip, &region);
if (status == CAIRO_INT_STATUS_NOTHING_TO_DO) {
goto DONE;
} else if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
return ERROR_LIST (CAIRO_STATUS_CLIP_NOT_REPRESENTABLE);
} else if (unlikely (status)) {
return ERROR_LIST (status);
}
if (region != NULL) {
n_rects = cairo_region_num_rectangles (region);
if (n_rects) {
rectangles = _cairo_malloc_ab (n_rects, sizeof (cairo_rectangle_t));
if (unlikely (rectangles == NULL)) {
return ERROR_LIST (CAIRO_STATUS_NO_MEMORY);
}
for (i = 0; i < n_rects; ++i) {
cairo_rectangle_int_t clip_rect;
cairo_region_get_rectangle (region, i, &clip_rect);
if (! _cairo_clip_int_rect_to_user (gstate,
&clip_rect,
&rectangles[i]))
{
free (rectangles);
return ERROR_LIST (CAIRO_STATUS_CLIP_NOT_REPRESENTABLE);
}
}
}
} else {
cairo_rectangle_int_t extents;
if (! _cairo_surface_get_extents (_cairo_gstate_get_target (gstate),
&extents))
{
/* unbounded surface -> unclipped */
goto DONE;
}
n_rects = 1;
rectangles = malloc(sizeof (cairo_rectangle_t));
if (unlikely (rectangles == NULL))
n_rects = cairo_region_num_rectangles (region);
if (n_rects) {
rectangles = _cairo_malloc_ab (n_rects, sizeof (cairo_rectangle_t));
if (unlikely (rectangles == NULL)) {
return ERROR_LIST (CAIRO_STATUS_NO_MEMORY);
}
if (! _cairo_clip_int_rect_to_user (gstate, &extents, rectangles)) {
free (rectangles);
return ERROR_LIST (CAIRO_STATUS_CLIP_NOT_REPRESENTABLE);
for (i = 0; i < n_rects; ++i) {
cairo_rectangle_int_t clip_rect;
cairo_region_get_rectangle (region, i, &clip_rect);
if (! _cairo_clip_int_rect_to_user (gstate,
&clip_rect,
&rectangles[i]))
{
free (rectangles);
return ERROR_LIST (CAIRO_STATUS_CLIP_NOT_REPRESENTABLE);
}
}
}

Просмотреть файл

@ -1443,7 +1443,19 @@ _cairo_gstate_clip_extents (cairo_gstate_t *gstate,
cairo_rectangle_list_t*
_cairo_gstate_copy_clip_rectangle_list (cairo_gstate_t *gstate)
{
return _cairo_clip_copy_rectangle_list (&gstate->clip, gstate);
cairo_clip_t clip;
cairo_rectangle_int_t extents;
cairo_rectangle_list_t *list;
_cairo_clip_init_copy (&clip, &gstate->clip);
if (_cairo_surface_get_extents (gstate->target, &extents))
_cairo_clip_rectangle (&clip, &extents);
list = _cairo_clip_copy_rectangle_list (&clip, gstate);
_cairo_clip_fini (&clip);
return list;
}
static void

Просмотреть файл

@ -0,0 +1,163 @@
From 108b1c7825116ed3f93aa57384bbd3290cdc9181 Mon Sep 17 00:00:00 2001
From: Karl Tomlinson <karlt+@karlt.net>
Date: Sat, 17 Jul 2010 01:08:53 +0000
Subject: clip: consider gstate target extents in _cairo_gstate_copy_clip_rectangle_list
Fixes https://bugs.freedesktop.org/show_bug.cgi?id=29125
To be consistent with _cairo_gstate_clip_extents, the context's clip
should be intersected with the target surface extents (instead of only
using them when there is no clip).
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
---
diff --git a/src/cairo-clip.c b/src/cairo-clip.c
index 77d8214..d5a2fab 100644
--- a/src/cairo-clip.c
+++ b/src/cairo-clip.c
@@ -1495,7 +1495,7 @@ _cairo_rectangle_list_create_in_error (cairo_status_t status)
cairo_rectangle_list_t *
_cairo_clip_copy_rectangle_list (cairo_clip_t *clip, cairo_gstate_t *gstate)
{
-#define ERROR_LIST(S) _cairo_rectangle_list_create_in_error (_cairo_error (S));
+#define ERROR_LIST(S) _cairo_rectangle_list_create_in_error (_cairo_error (S))
cairo_rectangle_list_t *list;
cairo_rectangle_t *rectangles = NULL;
@@ -1507,57 +1507,37 @@ _cairo_clip_copy_rectangle_list (cairo_clip_t *clip, cairo_gstate_t *gstate)
if (clip->all_clipped)
goto DONE;
- if (clip->path != NULL) {
- status = _cairo_clip_get_region (clip, &region);
- if (status == CAIRO_INT_STATUS_NOTHING_TO_DO) {
- goto DONE;
- } else if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
- return ERROR_LIST (CAIRO_STATUS_CLIP_NOT_REPRESENTABLE)
- } else if (unlikely (status)) {
- return ERROR_LIST (status);
- }
- }
-
- if (region != NULL) {
- n_rects = cairo_region_num_rectangles (region);
- if (n_rects) {
- rectangles = _cairo_malloc_ab (n_rects, sizeof (cairo_rectangle_t));
- if (unlikely (rectangles == NULL)) {
- return ERROR_LIST (CAIRO_STATUS_NO_MEMORY);
- }
+ if (!clip->path)
+ return ERROR_LIST (CAIRO_STATUS_CLIP_NOT_REPRESENTABLE);
- for (i = 0; i < n_rects; ++i) {
- cairo_rectangle_int_t clip_rect;
-
- cairo_region_get_rectangle (region, i, &clip_rect);
+ status = _cairo_clip_get_region (clip, &region);
+ if (status == CAIRO_INT_STATUS_NOTHING_TO_DO) {
+ goto DONE;
+ } else if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
+ return ERROR_LIST (CAIRO_STATUS_CLIP_NOT_REPRESENTABLE);
+ } else if (unlikely (status)) {
+ return ERROR_LIST (status);
+ }
- if (! _cairo_clip_int_rect_to_user (gstate,
- &clip_rect,
- &rectangles[i]))
- {
- free (rectangles);
- return ERROR_LIST (CAIRO_STATUS_CLIP_NOT_REPRESENTABLE);
- }
- }
+ n_rects = cairo_region_num_rectangles (region);
+ if (n_rects) {
+ rectangles = _cairo_malloc_ab (n_rects, sizeof (cairo_rectangle_t));
+ if (unlikely (rectangles == NULL)) {
+ return ERROR_LIST (CAIRO_STATUS_NO_MEMORY);
}
- } else {
- cairo_rectangle_int_t extents;
- if (! _cairo_surface_get_extents (_cairo_gstate_get_target (gstate),
- &extents))
- {
- /* unbounded surface -> unclipped */
- goto DONE;
- }
+ for (i = 0; i < n_rects; ++i) {
+ cairo_rectangle_int_t clip_rect;
- n_rects = 1;
- rectangles = malloc(sizeof (cairo_rectangle_t));
- if (unlikely (rectangles == NULL))
- return ERROR_LIST (CAIRO_STATUS_NO_MEMORY);
+ cairo_region_get_rectangle (region, i, &clip_rect);
- if (! _cairo_clip_int_rect_to_user (gstate, &extents, rectangles)) {
- free (rectangles);
- return ERROR_LIST (CAIRO_STATUS_CLIP_NOT_REPRESENTABLE);
+ if (! _cairo_clip_int_rect_to_user (gstate,
+ &clip_rect,
+ &rectangles[i]))
+ {
+ free (rectangles);
+ return ERROR_LIST (CAIRO_STATUS_CLIP_NOT_REPRESENTABLE);
+ }
}
}
diff --git a/src/cairo-gstate.c b/src/cairo-gstate.c
index baf6145..7caf624 100644
--- a/src/cairo-gstate.c
+++ b/src/cairo-gstate.c
@@ -1555,7 +1555,19 @@ _cairo_gstate_clip_extents (cairo_gstate_t *gstate,
cairo_rectangle_list_t*
_cairo_gstate_copy_clip_rectangle_list (cairo_gstate_t *gstate)
{
- return _cairo_clip_copy_rectangle_list (&gstate->clip, gstate);
+ cairo_clip_t clip;
+ cairo_rectangle_int_t extents;
+ cairo_rectangle_list_t *list;
+
+ _cairo_clip_init_copy (&clip, &gstate->clip);
+
+ if (_cairo_surface_get_extents (gstate->target, &extents))
+ _cairo_clip_rectangle (&clip, &extents);
+
+ list = _cairo_clip_copy_rectangle_list (&clip, gstate);
+ _cairo_clip_fini (&clip);
+
+ return list;
}
static void
diff --git a/test/get-clip.c b/test/get-clip.c
index f0477a1..f97db3f 100644
--- a/test/get-clip.c
+++ b/test/get-clip.c
@@ -120,6 +120,22 @@ preamble (cairo_test_context_t *ctx)
}
cairo_rectangle_list_destroy (rectangle_list);
+ /* We should get the same results after applying a clip that contains the
+ existing clip. */
+ phase = "Clip beyond surface extents";
+ cairo_save (cr);
+ cairo_rectangle (cr, -10, -10, SIZE + 20 , SIZE + 20);
+ cairo_clip (cr);
+ rectangle_list = cairo_copy_clip_rectangle_list (cr);
+ if (! check_count (ctx, phase, rectangle_list, 1) ||
+ ! check_clip_extents (ctx, phase, cr, 0, 0, SIZE, SIZE) ||
+ ! check_rectangles_contain (ctx, phase, rectangle_list, 0, 0, SIZE, SIZE))
+ {
+ goto FAIL;
+ }
+ cairo_rectangle_list_destroy (rectangle_list);
+ cairo_restore (cr);
+
/* Test simple clip rect. */
phase = "Simple clip rect";
cairo_save (cr);
--
cgit v0.8.3-6-g21f6

Просмотреть файл

@ -0,0 +1,59 @@
From b79ea8a6cab8bd28aebecf6e1e8229d5ac017264 Mon Sep 17 00:00:00 2001
From: Karl Tomlinson <karlt+@karlt.net>
Date: Fri, 16 Jul 2010 23:46:25 +0000
Subject: clip: consider all_clipped in _cairo_clip_get_extents
If the gstate clip in _cairo_gstate_int_clip_extents() has all_clipped
set (and path NULL), then it returns the gstate target extents instead of
an empty rectangle. If the target is infinite, then it says the clip is
unbounded.
Fixes https://bugs.freedesktop.org/show_bug.cgi?id=29124
Tested-by test/get-clip
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
---
diff --git a/src/cairo-clip.c b/src/cairo-clip.c
index f6173c6..77d8214 100644
--- a/src/cairo-clip.c
+++ b/src/cairo-clip.c
@@ -1264,9 +1264,14 @@ _cairo_clip_combine_with_surface (cairo_clip_t *clip,
return CAIRO_STATUS_SUCCESS;
}
+static const cairo_rectangle_int_t _cairo_empty_rectangle_int = { 0, 0, 0, 0 };
+
const cairo_rectangle_int_t *
_cairo_clip_get_extents (const cairo_clip_t *clip)
{
+ if (clip->all_clipped)
+ return &_cairo_empty_rectangle_int;
+
if (clip->path == NULL)
return NULL;
diff --git a/test/get-clip.c b/test/get-clip.c
index 9d6e796..f0477a1 100644
--- a/test/get-clip.c
+++ b/test/get-clip.c
@@ -83,6 +83,8 @@ check_clip_extents (const cairo_test_context_t *ctx,
cairo_clip_extents (cr, &ext_x1, &ext_y1, &ext_x2, &ext_y2);
if (ext_x1 == x && ext_y1 == y && ext_x2 == x + width && ext_y2 == y + height)
return 1;
+ if (width == 0.0 && height == 0.0 && ext_x1 == ext_x2 && ext_y1 == ext_y2)
+ return 1;
cairo_test_log (ctx, "Error: %s; clip extents %f,%f,%f,%f should be %f,%f,%f,%f\n",
message, ext_x1, ext_y1, ext_x2 - ext_x1, ext_y2 - ext_y1,
x, y, width, height);
@@ -138,7 +140,8 @@ preamble (cairo_test_context_t *ctx)
cairo_save (cr);
cairo_clip (cr);
rectangle_list = cairo_copy_clip_rectangle_list (cr);
- if (! check_count (ctx, phase, rectangle_list, 0))
+ if (! check_count (ctx, phase, rectangle_list, 0) ||
+ ! check_clip_extents (ctx, phase, cr, 0, 0, 0, 0))
{
goto FAIL;
}
--
cgit v0.8.3-6-g21f6

Просмотреть файл

@ -0,0 +1,28 @@
From f2fa15680ec3ac95cb68d4957557f06561a7dc55 Mon Sep 17 00:00:00 2001
From: Karl Tomlinson <karlt+@karlt.net>
Date: Fri, 16 Jul 2010 22:39:50 +0000
Subject: clip: return empty clip from _cairo_clip_copy_rectangle_list when all_clipped
Fixes https://bugs.freedesktop.org/show_bug.cgi?id=29122
Tested by test/get-clip
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
---
diff --git a/src/cairo-clip.c b/src/cairo-clip.c
index 12dc04d..f6173c6 100644
--- a/src/cairo-clip.c
+++ b/src/cairo-clip.c
@@ -1499,7 +1499,10 @@ _cairo_clip_copy_rectangle_list (cairo_clip_t *clip, cairo_gstate_t *gstate)
int n_rects = 0;
int i;
- if (clip != NULL && clip->path != NULL) {
+ if (clip->all_clipped)
+ goto DONE;
+
+ if (clip->path != NULL) {
status = _cairo_clip_get_region (clip, &region);
if (status == CAIRO_INT_STATUS_NOTHING_TO_DO) {
goto DONE;
--
cgit v0.8.3-6-g21f6