From 9d56bc38a9037d63ae15cb9aa31e173b0b68e0fe Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Mon, 3 Jul 2023 05:55:21 +0200 Subject: [PATCH] Clear is_clear flag on unmap_image() When a clear image surface gets mapped and the mapped image is modified, the image surface needs to be marked as not clear. Fixes early no-op exits from cairo_mask() etc when such an image was then used as source or mask. A new test map-clear-to-image is included. --- src/cairo-image-surface.c | 4 +++ test/map-to-image.c | 38 ++++++++++++++++++++++ test/reference/map-clear-to-image.ref.png | Bin 0 -> 100 bytes 3 files changed, 42 insertions(+) create mode 100644 test/reference/map-clear-to-image.ref.png diff --git a/src/cairo-image-surface.c b/src/cairo-image-surface.c index 3b11eb981..0b5b8a88b 100644 --- a/src/cairo-image-surface.c +++ b/src/cairo-image-surface.c @@ -847,6 +847,10 @@ cairo_int_status_t _cairo_image_surface_unmap_image (void *abstract_surface, cairo_image_surface_t *image) { + cairo_image_surface_t *surface = abstract_surface; + + surface->base.is_clear &= image->base.is_clear; + cairo_surface_finish (&image->base); cairo_surface_destroy (&image->base); diff --git a/test/map-to-image.c b/test/map-to-image.c index 7fac9aa8a..0d18cbdd8 100644 --- a/test/map-to-image.c +++ b/test/map-to-image.c @@ -115,6 +115,38 @@ bit (cairo_t *cr, int width, int height) return CAIRO_TEST_SUCCESS; } +static cairo_test_status_t +clear (cairo_t *cr, int width, int height) +{ + cairo_surface_t *surface; + cairo_pattern_t *pattern; + cairo_rectangle_int_t extents; + cairo_t *cr2; + + extents.x = extents.y = extents.width = extents.height = 1; + + /* Fill background red */ + cairo_set_source_rgb (cr, 1, 0, 0); + cairo_paint (cr); + + /* Get clear image */ + cairo_push_group (cr); + + surface = cairo_surface_map_to_image (cairo_get_group_target (cr), &extents); + cr2 = cairo_create (surface); + cairo_set_source_rgb (cr2, 0, 0, 1); + cairo_paint (cr2); + cairo_destroy (cr2); + cairo_surface_unmap_image (cairo_get_group_target (cr), surface); + + pattern = cairo_pop_group (cr); + /* all green */ + cairo_set_source_rgb (cr, 0, 1, 0); + cairo_mask (cr, pattern); + + return CAIRO_TEST_SUCCESS; +} + static cairo_test_status_t fill (cairo_t *cr, int width, int height) { @@ -150,6 +182,12 @@ CAIRO_TEST (map_bit_to_image, "target=raster", /* requirements */ WIDTH, HEIGHT, NULL, bit) +CAIRO_TEST (map_clear_to_image, + "Test mapping a clear surface to an image and modifying it externally marks it as not clear", + "image", /* keywords */ + "target=raster", /* requirements */ + WIDTH, HEIGHT, + NULL, clear) CAIRO_TEST (map_to_image_fill, "Test mapping a surface to an image and modifying it externally", "image", /* keywords */ diff --git a/test/reference/map-clear-to-image.ref.png b/test/reference/map-clear-to-image.ref.png new file mode 100644 index 0000000000000000000000000000000000000000..846dbe28e55c5f078315a7c9b794c14391c8fb0a GIT binary patch literal 100 zcmeAS@N?(olHy`uVBq!ia0vp^%plCc1SD^IDZKzvY)RhkE)4%caKYZ?lYt_Vo-U3d s95a*uoM&M5;o;%w`7ilEg&7DKOg)*IRqOTU02MKKy85}Sb4q9e07!cn1ONa4 literal 0 HcmV?d00001