From 44ee4169cdabcad0e6aecca2ccb56fdaf7bd83ff Mon Sep 17 00:00:00 2001 From: Karl Tomlinson Date: Fri, 23 Jul 2010 10:22:51 +1200 Subject: [PATCH] b=562574 fixes for cairo_copy_clip_rectangle_list and empty cairo_clip_extents r=jrmuizel --HG-- extra : rebase_source : 7559cb07311c0328d62a625c631a6ab822934b0d --- gfx/cairo/README | 6 + gfx/cairo/cairo/src/cairo-clip.c | 84 +++++------ gfx/cairo/cairo/src/cairo-gstate.c | 14 +- gfx/cairo/clip-rects-surface-extents.patch | 163 +++++++++++++++++++++ gfx/cairo/empty-clip-extents.patch | 59 ++++++++ gfx/cairo/empty-clip-rectangles.patch | 28 ++++ 6 files changed, 305 insertions(+), 49 deletions(-) create mode 100644 gfx/cairo/clip-rects-surface-extents.patch create mode 100644 gfx/cairo/empty-clip-extents.patch create mode 100644 gfx/cairo/empty-clip-rectangles.patch diff --git a/gfx/cairo/README b/gfx/cairo/README index 12d15b98d141..9afcb488812a 100644 --- a/gfx/cairo/README +++ b/gfx/cairo/README @@ -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. diff --git a/gfx/cairo/cairo/src/cairo-clip.c b/gfx/cairo/cairo/src/cairo-clip.c index 6acbcff2716f..ca56d0473ce8 100644 --- a/gfx/cairo/cairo/src/cairo-clip.c +++ b/gfx/cairo/cairo/src/cairo-clip.c @@ -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, ®ion); - 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, ®ion); + 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); + } } } diff --git a/gfx/cairo/cairo/src/cairo-gstate.c b/gfx/cairo/cairo/src/cairo-gstate.c index fd16bb9def0e..af1afedd5341 100644 --- a/gfx/cairo/cairo/src/cairo-gstate.c +++ b/gfx/cairo/cairo/src/cairo-gstate.c @@ -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 diff --git a/gfx/cairo/clip-rects-surface-extents.patch b/gfx/cairo/clip-rects-surface-extents.patch new file mode 100644 index 000000000000..1a9972aa75fd --- /dev/null +++ b/gfx/cairo/clip-rects-surface-extents.patch @@ -0,0 +1,163 @@ +From 108b1c7825116ed3f93aa57384bbd3290cdc9181 Mon Sep 17 00:00:00 2001 +From: Karl Tomlinson +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 +--- +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, ®ion); +- 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, ®ion); ++ 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 diff --git a/gfx/cairo/empty-clip-extents.patch b/gfx/cairo/empty-clip-extents.patch new file mode 100644 index 000000000000..306a61ad6037 --- /dev/null +++ b/gfx/cairo/empty-clip-extents.patch @@ -0,0 +1,59 @@ +From b79ea8a6cab8bd28aebecf6e1e8229d5ac017264 Mon Sep 17 00:00:00 2001 +From: Karl Tomlinson +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 +--- +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 diff --git a/gfx/cairo/empty-clip-rectangles.patch b/gfx/cairo/empty-clip-rectangles.patch new file mode 100644 index 000000000000..c9aa558a275b --- /dev/null +++ b/gfx/cairo/empty-clip-rectangles.patch @@ -0,0 +1,28 @@ +From f2fa15680ec3ac95cb68d4957557f06561a7dc55 Mon Sep 17 00:00:00 2001 +From: Karl Tomlinson +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 +--- +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, ®ion); + if (status == CAIRO_INT_STATUS_NOTHING_TO_DO) { + goto DONE; +-- +cgit v0.8.3-6-g21f6