From baefbc5259efc4b0a84b31d88a64edb2cd72efb7 Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Sat, 25 Sep 2021 22:56:34 +0200 Subject: [PATCH] Add color space get/set for cairo Add a centralized place to attach color space to. Nothing uses that information yet, but all the backends do set it. --- gdk/broadway/gdkcairocontext-broadway.c | 7 +- gdk/gdkcairo.c | 96 +++++++++++++++++++++++++ gdk/gdkcairo.h | 12 +++- gdk/gdksurface.c | 3 + gdk/gdktexture.c | 12 ++-- gdk/wayland/gdkcairocontext-wayland.c | 3 + gdk/win32/gdkcairocontext-win32.c | 1 + gdk/x11/gdkcairocontext-x11.c | 1 + 8 files changed, 124 insertions(+), 11 deletions(-) diff --git a/gdk/broadway/gdkcairocontext-broadway.c b/gdk/broadway/gdkcairocontext-broadway.c index 314ebf54a0..f8fa099674 100644 --- a/gdk/broadway/gdkcairocontext-broadway.c +++ b/gdk/broadway/gdkcairocontext-broadway.c @@ -46,9 +46,10 @@ gdk_broadway_cairo_context_begin_frame (GdkDrawContext *draw_context, width = gdk_surface_get_width (surface); height = gdk_surface_get_height (surface); scale = gdk_surface_get_scale_factor (surface); - self->paint_surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, - width * scale, height * scale); - cairo_surface_set_device_scale (self->paint_surface, scale, scale); + + self->paint_surface = gdk_surface_create_similar_surface (surface, + CAIRO_CONTENT_COLOR_ALPHA, + width * scale, height *scale); repaint_region = cairo_region_create_rectangle (&(cairo_rectangle_int_t) { 0, 0, width, height }); cairo_region_union (region, repaint_region); diff --git a/gdk/gdkcairo.c b/gdk/gdkcairo.c index a1236667dc..92209dc21b 100644 --- a/gdk/gdkcairo.c +++ b/gdk/gdkcairo.c @@ -21,6 +21,7 @@ #include "gdkrgba.h" #include "gdktexture.h" +#include "gdkcolorstate.h" #include @@ -303,3 +304,98 @@ gdk_cairo_region_create_from_surface (cairo_surface_t *surface) return region; } + +static cairo_user_data_key_t color_state_key; + +/** + * gdk_cairo_surface_set_color_state: + * @surface: a surface + * @color_state: the color state to attach to the surface + * + * Attaches a `GdkColorState` to the Cairo surface. + * + * This is just auxiliary data for use by GTK, no Cairo functions + * do interact with this information. + * + * Note that all Cairo compositing operations are assumed to happen + * in a linear RGB color state, so if you want to use the surface + * as a target for rendering in a color managed way, you should use + * such a color state. + * + * The default color state is assumed to be sRGB, which is not + * linear. + * + * Since: 4.16 + */ +void +gdk_cairo_surface_set_color_state (cairo_surface_t *surface, + GdkColorState *color_state) +{ + g_return_if_fail (surface != NULL); + g_return_if_fail (color_state != NULL); + + cairo_surface_set_user_data (surface, + &color_state_key, + gdk_color_state_ref (color_state), + (cairo_destroy_func_t) gdk_color_state_unref); +} + +/** + * gdk_cairo_surface_get_color_state: + * @surface: a surface + * + * Gets the color state GTK assumes for the surface. + * + * See [method@Gdk.CairoSurface.set_color_state] for details. + * + * Returns: (transfer none): the color state + * + * Since: 4.16 + */ +GdkColorState * +gdk_cairo_surface_get_color_state (cairo_surface_t *surface) +{ + GdkColorState *color_state; + + g_return_val_if_fail (surface != NULL, gdk_color_state_get_srgb ()); + + color_state = cairo_surface_get_user_data (surface, &color_state_key); + if (color_state == NULL) + color_state = gdk_color_state_get_srgb (); + + return color_state; +} + +/** + * gdk_cairo_get_color_state: + * @cr: a cairo context + * + * Gets the color state GTK assumes for the cairo context. + * + * Returns: (transfer none): the color state + * + * Since: 4.16 + */ +GdkColorState * +gdk_cairo_get_color_state (cairo_t *cr) +{ + GdkColorState *color_state; + cairo_surface_t *surface; + + g_return_val_if_fail (cr != NULL, gdk_color_state_get_srgb ()); + + surface = cairo_get_group_target (cr); + color_state = cairo_surface_get_user_data (surface, &color_state_key); + if (color_state != NULL) + return color_state; + + /* theoretically, we should walk the whole group stack, but I don't + * think Cairo lets us do that + */ + surface = cairo_get_target (cr); + color_state = cairo_surface_get_user_data (surface, &color_state_key); + if (color_state != NULL) + return color_state; + + return gdk_color_state_get_srgb (); +} diff --git a/gdk/gdkcairo.h b/gdk/gdkcairo.h index eafc4c29dc..137580d8f4 100644 --- a/gdk/gdkcairo.h +++ b/gdk/gdkcairo.h @@ -44,9 +44,15 @@ void gdk_cairo_region (cairo_t *cr, const cairo_region_t *region); GDK_AVAILABLE_IN_ALL -cairo_region_t * - gdk_cairo_region_create_from_surface - (cairo_surface_t *surface); +cairo_region_t * gdk_cairo_region_create_from_surface (cairo_surface_t *surface); + +GDK_AVAILABLE_IN_4_16 +void gdk_cairo_surface_set_color_state (cairo_surface_t *surface, + GdkColorState *color_state); +GDK_AVAILABLE_IN_4_16 +GdkColorState * gdk_cairo_surface_get_color_state (cairo_surface_t *surface); +GDK_AVAILABLE_IN_4_16 +GdkColorState * gdk_cairo_get_color_state (cairo_t *cr); GDK_DEPRECATED_IN_4_6_FOR(gdk_gl_texture_new) void gdk_cairo_draw_from_gl (cairo_t *cr, diff --git a/gdk/gdksurface.c b/gdk/gdksurface.c index c947ad9626..f625de5207 100644 --- a/gdk/gdksurface.c +++ b/gdk/gdksurface.c @@ -30,6 +30,8 @@ #include "gdksurface.h" #include "gdkprivate.h" +#include "gdkcolorstate.h" +#include "gdkcairo.h" #include "gdkcontentprovider.h" #include "gdkdeviceprivate.h" #include "gdkdisplayprivate.h" @@ -2361,6 +2363,7 @@ gdk_surface_create_similar_surface (GdkSurface *surface, content == CAIRO_CONTENT_ALPHA ? CAIRO_FORMAT_A8 : CAIRO_FORMAT_ARGB32, width * scale, height * scale); cairo_surface_set_device_scale (similar_surface, scale, scale); + gdk_cairo_surface_set_color_state (similar_surface, gdk_surface_get_color_state (surface)); return similar_surface; } diff --git a/gdk/gdktexture.c b/gdk/gdktexture.c index 6e63ef2386..b3f387cbff 100644 --- a/gdk/gdktexture.c +++ b/gdk/gdktexture.c @@ -45,6 +45,7 @@ #include "gdkpaintable.h" #include "gdksnapshot.h" #include "gdkcolorstate.h" +#include "gdkcairo.h" #include #include "loaders/gdkpngprivate.h" @@ -455,11 +456,12 @@ gdk_texture_new_for_surface (cairo_surface_t *surface) (GDestroyNotify) cairo_surface_destroy, cairo_surface_reference (surface)); - texture = gdk_memory_texture_new (cairo_image_surface_get_width (surface), - cairo_image_surface_get_height (surface), - GDK_MEMORY_DEFAULT, - bytes, - cairo_image_surface_get_stride (surface)); + texture = gdk_memory_texture_new_with_color_state (cairo_image_surface_get_width (surface), + cairo_image_surface_get_height (surface), + GDK_MEMORY_DEFAULT, + gdk_cairo_surface_get_color_state (surface), + bytes, + cairo_image_surface_get_stride (surface)); g_bytes_unref (bytes); diff --git a/gdk/wayland/gdkcairocontext-wayland.c b/gdk/wayland/gdkcairocontext-wayland.c index cc8419701b..6294df90c4 100644 --- a/gdk/wayland/gdkcairocontext-wayland.c +++ b/gdk/wayland/gdkcairocontext-wayland.c @@ -158,6 +158,9 @@ gdk_wayland_cairo_context_begin_frame (GdkDrawContext *draw_context, else self->paint_surface = gdk_wayland_cairo_context_create_surface (self); + gdk_cairo_surface_set_color_state (self->paint_surface, + gdk_surface_get_color_state (gdk_draw_context_get_surface (draw_context))); + surface_region = gdk_wayland_cairo_context_surface_get_region (self->paint_surface); if (surface_region) cairo_region_union (region, surface_region); diff --git a/gdk/win32/gdkcairocontext-win32.c b/gdk/win32/gdkcairocontext-win32.c index f75ded291c..a4e055da48 100644 --- a/gdk/win32/gdkcairocontext-win32.c +++ b/gdk/win32/gdkcairocontext-win32.c @@ -47,6 +47,7 @@ create_cairo_surface_for_surface (GdkSurface *surface, cairo_surface = cairo_win32_surface_create_with_format (hdc, CAIRO_FORMAT_ARGB32); cairo_surface_set_device_scale (cairo_surface, scale, scale); + gdk_cairo_surface_set_color_state (cairo_surface, gdk_surface_get_color_state (surface)); return cairo_surface; } diff --git a/gdk/x11/gdkcairocontext-x11.c b/gdk/x11/gdkcairocontext-x11.c index 9e99c89baa..42123a0427 100644 --- a/gdk/x11/gdkcairocontext-x11.c +++ b/gdk/x11/gdkcairocontext-x11.c @@ -49,6 +49,7 @@ create_cairo_surface_for_surface (GdkSurface *surface) gdk_surface_get_width (surface) * scale, gdk_surface_get_height (surface) * scale); cairo_surface_set_device_scale (cairo_surface, scale, scale); + gdk_cairo_surface_set_color_state (cairo_surface, gdk_surface_get_color_state (surface)); return cairo_surface; }