[gtk/wip/otte/color-profiles: 8/8] FIXME: Add a crude way to color-correct GdkRGBAs




commit e0e0c6d3ef3a6ec2eb436da302f6e2aedc5c4742
Author: Benjamin Otte <otte redhat com>
Date:   Mon Sep 27 06:03:14 2021 +0200

    FIXME: Add a crude way to color-correct GdkRGBAs
    
    Only used in gdk_cairo_set_source_rgba() for now, but works as a proof
    of concept.

 gdk/gdkcairo.c         |  30 +++++++++++++--
 gsk/gskcairorenderer.c | 101 +++++++++++++++++++++++++++++++------------------
 2 files changed, 91 insertions(+), 40 deletions(-)
---
diff --git a/gdk/gdkcairo.c b/gdk/gdkcairo.c
index 1f1eb58a61..3a60999871 100644
--- a/gdk/gdkcairo.c
+++ b/gdk/gdkcairo.c
@@ -20,9 +20,28 @@
 #include "gdkcairoprivate.h"
 
 #include "gdkcolorprofile.h"
+#include "gdkmemoryformatprivate.h"
 
 #include <math.h>
 
+static void
+gdk_rgba_convert (GdkRGBA         *dest,
+                  const GdkRGBA   *src,
+                  GdkColorProfile *profile)
+{
+  gdk_memory_convert ((guchar *) dest,
+                      sizeof (float) * 4,
+                      GDK_MEMORY_R32G32B32_FLOAT,
+                      profile,
+                      (guchar *) src,
+                      sizeof (float) * 4,
+                      GDK_MEMORY_R32G32B32_FLOAT,
+                      gdk_color_profile_get_srgb (),
+                      1,
+                      1);
+  dest->alpha = src->alpha;
+}
+
 /**
  * gdk_cairo_set_source_rgba:
  * @cr: a cairo context
@@ -34,14 +53,17 @@ void
 gdk_cairo_set_source_rgba (cairo_t       *cr,
                            const GdkRGBA *rgba)
 {
+  GdkRGBA tmp;
+
   g_return_if_fail (cr != NULL);
   g_return_if_fail (rgba != NULL);
 
+  gdk_rgba_convert (&tmp, rgba, gdk_cairo_get_color_profile (cr));
   cairo_set_source_rgba (cr,
-                         rgba->red,
-                         rgba->green,
-                         rgba->blue,
-                         rgba->alpha);
+                         tmp.red,
+                         tmp.green,
+                         tmp.blue,
+                         tmp.alpha);
 }
 
 /**
diff --git a/gsk/gskcairorenderer.c b/gsk/gskcairorenderer.c
index 34625c66a8..e0e24ad5be 100644
--- a/gsk/gskcairorenderer.c
+++ b/gsk/gskcairorenderer.c
@@ -27,6 +27,7 @@
 #include "gskrendernodeprivate.h"
 
 #include "gdk/gdkcolorprofileprivate.h"
+#include "gdk/gdkmemorytextureprivate.h"
 #include "gdk/gdktextureprivate.h"
 
 #ifdef G_ENABLE_DEBUG
@@ -91,41 +92,7 @@ gsk_cairo_renderer_do_render (GskRenderer   *renderer,
   gsk_profiler_timer_begin (profiler, self->profile_timers.cpu_time);
 #endif
 
-  if (!self->color_managed ||
-      gdk_color_profile_is_linear (gdk_cairo_get_color_profile (cr)))
-    {
-      gsk_render_node_draw (root, cr);
-    }
-  else
-    {
-      GdkSurface *surface = gsk_renderer_get_surface (renderer);
-      cairo_surface_t *cairo_surface;
-      cairo_t *cr2;
-      GdkTexture *color_correct;
-
-      /* We can't use cairo_push_group() here, because we'd lose the
-       * color profile information. */
-      cairo_surface = gdk_surface_create_similar_surface (surface,
-                                                          CAIRO_CONTENT_COLOR_ALPHA,
-                                                          gdk_surface_get_width (surface),
-                                                          gdk_surface_get_height (surface));
-      gdk_cairo_surface_set_color_profile (cairo_surface,
-                                           gdk_color_profile_get_srgb_linear ());
-
-      cr2 = cairo_create (cairo_surface);
-      gsk_render_node_draw (root, cr2);
-      cairo_destroy (cr2);
-
-      color_correct = gdk_texture_new_for_surface (cairo_surface);
-      cairo_surface_destroy (cairo_surface);
-      cairo_surface = gdk_texture_download_surface (color_correct,
-                                                    gdk_cairo_get_color_profile (cr));
-      g_object_unref (color_correct);
-
-      cairo_set_source_surface (cr, cairo_surface, 0, 0);
-      cairo_paint (cr);
-      cairo_surface_destroy (cairo_surface);
-    }
+  gsk_render_node_draw (root, cr);
 
 #ifdef G_ENABLE_DEBUG
   cpu_time = gsk_profiler_timer_end (profiler, self->profile_timers.cpu_time);
@@ -140,11 +107,15 @@ gsk_cairo_renderer_render_texture (GskRenderer           *renderer,
                                    GskRenderNode         *root,
                                    const graphene_rect_t *viewport)
 {
+  GskCairoRenderer *self = GSK_CAIRO_RENDERER (renderer);
   GdkTexture *texture;
   cairo_surface_t *surface;
   cairo_t *cr;
 
   surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, ceil (viewport->size.width), ceil 
(viewport->size.height));
+  if (self->color_managed)
+      gdk_cairo_surface_set_color_profile (surface, gdk_color_profile_get_srgb_linear ());
+
   cr = cairo_create (surface);
 
   cairo_translate (cr, - viewport->origin.x, - viewport->origin.y);
@@ -189,7 +160,65 @@ gsk_cairo_renderer_render (GskRenderer          *renderer,
     }
 #endif
 
-  gsk_cairo_renderer_do_render (renderer, cr, root);
+  if (!self->color_managed ||
+      gdk_color_profile_is_linear (gdk_cairo_get_color_profile (cr)))
+    {
+      gsk_cairo_renderer_do_render (renderer, cr, root);
+    }
+  else
+    {
+      GdkSurface *surface = gsk_renderer_get_surface (renderer);
+      GdkColorProfile *target_profile = gdk_cairo_get_color_profile (cr);
+      cairo_surface_t *cairo_surface;
+      cairo_t *cr2;
+      GdkTexture *color_correct;
+      const cairo_region_t *frame_region;
+      cairo_rectangle_int_t extents;
+      guint i, n;
+
+      frame_region = gdk_draw_context_get_frame_region (GDK_DRAW_CONTEXT (self->cairo_context));
+      cairo_region_get_extents (frame_region, &extents);
+      /* We can't use cairo_push_group() here, because we'd lose the
+       * color profile information. */
+      cairo_surface = gdk_surface_create_similar_surface (surface,
+                                                          CAIRO_CONTENT_COLOR_ALPHA,
+                                                          extents.width,
+                                                          extents.height);
+      gdk_cairo_surface_set_color_profile (cairo_surface,
+                                           gdk_color_profile_get_srgb_linear ());
+
+      cr2 = cairo_create (cairo_surface);
+      cairo_translate (cr2, -extents.x, -extents.y);
+      gdk_cairo_region (cr2, frame_region);
+      cairo_clip (cr2);
+      gsk_cairo_renderer_do_render (renderer, cr2, root);
+      cairo_destroy (cr2);
+
+      color_correct = gdk_texture_new_for_surface (cairo_surface);
+      cairo_surface_destroy (cairo_surface);
+      n = cairo_region_num_rectangles (frame_region);
+      for (i = 0; i < n; i++)
+        {
+          cairo_rectangle_int_t rect;
+          GdkMemoryTexture *sub;
+
+          cairo_region_get_rectangle (frame_region, i, &rect);
+          rect.x -= extents.x;
+          rect.y -= extents.y;
+
+          sub = gdk_memory_texture_convert (g_object_ref (GDK_MEMORY_TEXTURE (color_correct)),
+                                            GDK_MEMORY_DEFAULT,
+                                            target_profile,
+                                            &rect);
+          cairo_surface = gdk_texture_download_surface (GDK_TEXTURE (sub), target_profile);
+          cairo_set_source_surface (cr, cairo_surface, rect.x + extents.x, rect.y + extents.y);
+          cairo_paint (cr);
+          cairo_surface_destroy (cairo_surface);
+          g_object_unref (sub);
+        }
+      g_object_unref (color_correct);
+
+    }
 
   cairo_destroy (cr);
 


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