[gtk/wip/otte/color-profiles: 20/30] cairo: Add color profile get/set




commit 2a64b3d6e59c081d72858bf5df7f76de64629ff2
Author: Benjamin Otte <otte redhat com>
Date:   Sat Sep 25 22:56:34 2021 +0200

    cairo: Add color profile get/set
    
    Add a centralized place to attach color profiles to.
    
    Nothing uses that information yet, but all the backends do set it.

 gdk/broadway/gdkcairocontext-broadway.c | 17 ++----
 gdk/gdkcairo.c                          | 96 +++++++++++++++++++++++++++++++++
 gdk/gdkcairo.h                          | 12 +++--
 gdk/gdksurface.c                        |  4 +-
 gdk/gdktexture.c                        | 12 +++--
 gdk/wayland/gdkcairocontext-wayland.c   |  3 ++
 gdk/win32/gdkcairocontext-win32.c       |  1 +
 gdk/x11/gdkcairocontext-x11.c           |  2 +
 8 files changed, 126 insertions(+), 21 deletions(-)
---
diff --git a/gdk/broadway/gdkcairocontext-broadway.c b/gdk/broadway/gdkcairocontext-broadway.c
index bc45b5094a..24e7d61e13 100644
--- a/gdk/broadway/gdkcairocontext-broadway.c
+++ b/gdk/broadway/gdkcairocontext-broadway.c
@@ -38,26 +38,19 @@ gdk_broadway_cairo_context_begin_frame (GdkDrawContext *draw_context,
 {
   GdkBroadwayCairoContext *self = GDK_BROADWAY_CAIRO_CONTEXT (draw_context);
   GdkSurface *surface = gdk_draw_context_get_surface (GDK_DRAW_CONTEXT (self));
-  cairo_t *cr;
   cairo_region_t *repaint_region;
-  int width, height, scale;
+  int width, height;
 
   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,
+                                                            height);
 
   repaint_region = cairo_region_create_rectangle (&(cairo_rectangle_int_t) { 0, 0, width, height });
   cairo_region_union (region, repaint_region);
   cairo_region_destroy (repaint_region);
-
-  /* clear the repaint area */
-  cr = cairo_create (self->paint_surface);
-  cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR);
-  cairo_fill (cr);
-  cairo_destroy (cr);
 }
 
 static void
diff --git a/gdk/gdkcairo.c b/gdk/gdkcairo.c
index ef8f5d2fb5..1f1eb58a61 100644
--- a/gdk/gdkcairo.c
+++ b/gdk/gdkcairo.c
@@ -19,6 +19,8 @@
 
 #include "gdkcairoprivate.h"
 
+#include "gdkcolorprofile.h"
+
 #include <math.h>
 
 /**
@@ -399,3 +401,97 @@ gdk_cairo_region_from_clip (cairo_t *cr)
 
   return region;
 }
+
+static cairo_user_data_key_t color_profile_key;
+
+/**
+ * gdk_cairo_surface_set_color_profile:
+ * @surface: a surface
+ * @profile: the profile to attach to the surface
+ *
+ * Attaches a `GdkColorProfile` 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 space, so if you want to use the surface
+ * as a target for rendering in a color managed way, you should use
+ * such a color profile.
+ *
+ * The default color profile is assumed to be sRGB, which is not
+ * linear.
+ *
+ * Since: 4.6
+ **/
+void
+gdk_cairo_surface_set_color_profile (cairo_surface_t *surface,
+                                     GdkColorProfile *profile)
+{
+  g_return_if_fail (surface != NULL);
+  g_return_if_fail (GDK_IS_COLOR_PROFILE (profile));
+
+  cairo_surface_set_user_data (surface,
+                               &color_profile_key,
+                               g_object_ref (profile),
+                               g_object_unref);
+}
+
+/**
+ * gdk_cairo_surface_get_color_profile:
+ * @surface: a surface
+ *
+ * Gets the color profile GTK assumes for the surface. See
+ * gdk_cairo_surface_set_color_profile() for details.
+ *
+ * Returns: (transfer none): the assumed profile
+ *
+ * Since: 4.6
+ **/
+GdkColorProfile *
+gdk_cairo_surface_get_color_profile (cairo_surface_t *surface)
+{
+  GdkColorProfile *profile;
+
+  g_return_val_if_fail (surface != NULL, gdk_color_profile_get_srgb ());
+
+  profile = cairo_surface_get_user_data (surface, &color_profile_key);
+  if (profile == NULL)
+    profile = gdk_color_profile_get_srgb ();
+  
+  return profile;
+}
+
+/**
+ * gdk_cairo_get_color_profile:
+ * @cr: a cairo context
+ *
+ * Gets the color profile GTK assumes for the cairo context.
+ *
+ * Returns: (transfer none): the assumed profile
+ *
+ * Since: 4.6
+ **/
+GdkColorProfile *
+gdk_cairo_get_color_profile (cairo_t *cr)
+{
+  GdkColorProfile *profile;
+  cairo_surface_t *surface;
+
+  g_return_val_if_fail (cr != NULL, gdk_color_profile_get_srgb ());
+
+  surface = cairo_get_group_target (cr);
+  profile = cairo_surface_get_user_data (surface, &color_profile_key);
+  if (profile != NULL)
+    return profile;
+
+  /* theoretically, we should walk the whole group stack, but I don't
+   * think Cairo lets us do that
+   */
+  surface = cairo_get_target (cr);
+  profile = cairo_surface_get_user_data (surface, &color_profile_key);
+  if (profile != NULL)
+    return profile;
+
+  return gdk_color_profile_get_srgb ();
+}
diff --git a/gdk/gdkcairo.h b/gdk/gdkcairo.h
index f2dfa3177e..eea08975b0 100644
--- a/gdk/gdkcairo.h
+++ b/gdk/gdkcairo.h
@@ -46,9 +46,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_6
+void                    gdk_cairo_surface_set_color_profile     (cairo_surface_t        *surface,
+                                                                 GdkColorProfile        *profile);
+GDK_AVAILABLE_IN_4_6
+GdkColorProfile *       gdk_cairo_surface_get_color_profile     (cairo_surface_t        *surface);
+GDK_AVAILABLE_IN_4_6
+GdkColorProfile *       gdk_cairo_get_color_profile             (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 c53ed89fe1..e1abb68e58 100644
--- a/gdk/gdksurface.c
+++ b/gdk/gdksurface.c
@@ -30,6 +30,7 @@
 #include "gdksurface.h"
 
 #include "gdk-private.h"
+#include "gdkcairo.h"
 #include "gdkcolorprofile.h"
 #include "gdkcontentprovider.h"
 #include "gdkdeviceprivate.h"
@@ -2334,7 +2335,7 @@ _gdk_windowing_got_event (GdkDisplay *display,
  *   with it.
  */
 cairo_surface_t *
-gdk_surface_create_similar_surface (GdkSurface *     surface,
+gdk_surface_create_similar_surface (GdkSurface *    surface,
                                     cairo_content_t content,
                                     int             width,
                                     int             height)
@@ -2350,6 +2351,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_profile (similar_surface, gdk_surface_get_color_profile (surface));
 
   return similar_surface;
 }
diff --git a/gdk/gdktexture.c b/gdk/gdktexture.c
index 975e6c5f9a..b062667b54 100644
--- a/gdk/gdktexture.c
+++ b/gdk/gdktexture.c
@@ -40,6 +40,7 @@
 
 #include "gdktextureprivate.h"
 
+#include "gdkcairo.h"
 #include "gdkcolorprofile.h"
 #include "gdkintl.h"
 #include "gdkmemorytextureprivate.h"
@@ -421,11 +422,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_profile (cairo_image_surface_get_width (surface),
+                                                       cairo_image_surface_get_height (surface),
+                                                       GDK_MEMORY_DEFAULT,
+                                                       gdk_cairo_surface_get_color_profile (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 4ce7134327..1996c963d0 100644
--- a/gdk/wayland/gdkcairocontext-wayland.c
+++ b/gdk/wayland/gdkcairocontext-wayland.c
@@ -156,6 +156,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_profile (self->paint_surface,
+                                       gdk_surface_get_color_profile (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 9eb115ffcd..b1a6391133 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_profile (cairo_surface, gdk_surface_get_color_profile (surface));
 
   return cairo_surface;
 }
diff --git a/gdk/x11/gdkcairocontext-x11.c b/gdk/x11/gdkcairocontext-x11.c
index 36bf1ae0ba..a6275f969a 100644
--- a/gdk/x11/gdkcairocontext-x11.c
+++ b/gdk/x11/gdkcairocontext-x11.c
@@ -49,6 +49,8 @@ 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_profile (cairo_surface,
+                                       gdk_surface_get_color_profile (surface));
 
   return cairo_surface;
 }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]