Break out cairo color matrix recoloring to gdk_cairo_image_surface_recolor()
authorAlexander Larsson <alexl@redhat.com>
Tue, 28 Jan 2020 10:42:24 +0000 (11:42 +0100)
committerAlexander Larsson <alexl@redhat.com>
Wed, 29 Jan 2020 18:06:16 +0000 (19:06 +0100)
This is useful in some parts of the icon theme APIs.

gdk/gdkcairo.c
gdk/gdkcairo.h
gsk/gskrendernodeimpl.c

index c5917cfeb9e76876fe0268979a411fae855713f1..94accf847be3402e55ca832807b657d27dd2eb55 100644 (file)
@@ -456,3 +456,62 @@ gdk_cairo_region_from_clip (cairo_t *cr)
 
   return region;
 }
+
+void
+gdk_cairo_image_surface_recolor (cairo_surface_t *image_surface,
+                                 const graphene_matrix_t *color_matrix,
+                                 const graphene_vec4_t *color_offset)
+{
+  graphene_vec4_t pixel;
+  guint32* pixel_data;
+  guchar *data;
+  gsize x, y, width, height, stride;
+  float alpha;
+
+  data = cairo_image_surface_get_data (image_surface);
+  width = cairo_image_surface_get_width (image_surface);
+  height = cairo_image_surface_get_height (image_surface);
+  stride = cairo_image_surface_get_stride (image_surface);
+
+  for (y = 0; y < height; y++)
+    {
+      pixel_data = (guint32 *) data;
+      for (x = 0; x < width; x++)
+        {
+          alpha = ((pixel_data[x] >> 24) & 0xFF) / 255.0;
+
+          if (alpha == 0)
+            {
+              graphene_vec4_init (&pixel, 0.0, 0.0, 0.0, 0.0);
+            }
+          else
+            {
+              graphene_vec4_init (&pixel,
+                                  ((pixel_data[x] >> 16) & 0xFF) / (255.0 * alpha),
+                                  ((pixel_data[x] >>  8) & 0xFF) / (255.0 * alpha),
+                                  ( pixel_data[x]        & 0xFF) / (255.0 * alpha),
+                                  alpha);
+              graphene_matrix_transform_vec4 (color_matrix, &pixel, &pixel);
+            }
+
+          graphene_vec4_add (&pixel, color_offset, &pixel);
+
+          alpha = graphene_vec4_get_w (&pixel);
+          if (alpha > 0.0)
+            {
+              alpha = MIN (alpha, 1.0);
+              pixel_data[x] = (((guint32) roundf (alpha * 255)) << 24) |
+                              (((guint32) roundf (CLAMP (graphene_vec4_get_x (&pixel), 0, 1) * alpha * 255)) << 16) |
+                              (((guint32) roundf (CLAMP (graphene_vec4_get_y (&pixel), 0, 1) * alpha * 255)) <<  8) |
+                               ((guint32) roundf (CLAMP (graphene_vec4_get_z (&pixel), 0, 1) * alpha * 255));
+            }
+          else
+            {
+              pixel_data[x] = 0;
+            }
+        }
+      data += stride;
+    }
+
+  cairo_surface_mark_dirty (image_surface);
+}
index c4e2d3836c4bcf823a7f02b543af1e3261450af8..52a6abdef3f409a4a7e4a36abf31375606400146 100644 (file)
@@ -26,6 +26,7 @@
 #include <gdk/gdkrgba.h>
 #include <gdk/gdkpixbuf.h>
 #include <pango/pangocairo.h>
+#include <graphene.h>
 
 G_BEGIN_DECLS
 
@@ -72,6 +73,11 @@ void      gdk_cairo_surface_upload_to_gl (cairo_surface_t *surface,
                                           int              height,
                                           GdkGLContext    *context);
 
+GDK_AVAILABLE_IN_ALL
+void      gdk_cairo_image_surface_recolor (cairo_surface_t *image_surface,
+                                           const graphene_matrix_t *color_matrix,
+                                           const graphene_vec4_t *color_offset);
+
 G_END_DECLS
 
 #endif /* __GDK_CAIRO_H__ */
index 2434c5d40e2b7ace235d803143f632628ff9a53d..f82343054b773b6996952a292f5408a2f93dacf5 100644 (file)
@@ -2339,11 +2339,6 @@ gsk_color_matrix_node_draw (GskRenderNode *node,
   GskColorMatrixNode *self = (GskColorMatrixNode *) node;
   cairo_pattern_t *pattern;
   cairo_surface_t *surface, *image_surface;
-  graphene_vec4_t pixel;
-  guint32* pixel_data;
-  guchar *data;
-  gsize x, y, width, height, stride;
-  float alpha;
 
   cairo_save (cr);
 
@@ -2360,52 +2355,10 @@ gsk_color_matrix_node_draw (GskRenderNode *node,
   cairo_pattern_get_surface (pattern, &surface);
   image_surface = cairo_surface_map_to_image (surface, NULL);
 
-  data = cairo_image_surface_get_data (image_surface);
-  width = cairo_image_surface_get_width (image_surface);
-  height = cairo_image_surface_get_height (image_surface);
-  stride = cairo_image_surface_get_stride (image_surface);
+  gdk_cairo_image_surface_recolor (image_surface,
+                                   &self->color_matrix,
+                                   &self->color_offset);
 
-  for (y = 0; y < height; y++)
-    {
-      pixel_data = (guint32 *) data;
-      for (x = 0; x < width; x++)
-        {
-          alpha = ((pixel_data[x] >> 24) & 0xFF) / 255.0;
-
-          if (alpha == 0)
-            {
-              graphene_vec4_init (&pixel, 0.0, 0.0, 0.0, 0.0);
-            }
-          else
-            {
-              graphene_vec4_init (&pixel,
-                                  ((pixel_data[x] >> 16) & 0xFF) / (255.0 * alpha),
-                                  ((pixel_data[x] >>  8) & 0xFF) / (255.0 * alpha),
-                                  ( pixel_data[x]        & 0xFF) / (255.0 * alpha),
-                                  alpha);
-              graphene_matrix_transform_vec4 (&self->color_matrix, &pixel, &pixel);
-            }
-
-          graphene_vec4_add (&pixel, &self->color_offset, &pixel);
-
-          alpha = graphene_vec4_get_w (&pixel);
-          if (alpha > 0.0)
-            {
-              alpha = MIN (alpha, 1.0);
-              pixel_data[x] = (((guint32) roundf (alpha * 255)) << 24) |
-                              (((guint32) roundf (CLAMP (graphene_vec4_get_x (&pixel), 0, 1) * alpha * 255)) << 16) |
-                              (((guint32) roundf (CLAMP (graphene_vec4_get_y (&pixel), 0, 1) * alpha * 255)) <<  8) |
-                               ((guint32) roundf (CLAMP (graphene_vec4_get_z (&pixel), 0, 1) * alpha * 255));
-            }
-          else
-            {
-              pixel_data[x] = 0;
-            }
-        }
-      data += stride;
-    }
-
-  cairo_surface_mark_dirty (image_surface);
   cairo_surface_unmap_image (surface, image_surface);
 
   cairo_set_source (cr, pattern);