[gtk/gamma-shenanigans] Use our png loader for content (de)serialization




commit 6798fcdafcd2cffdc4663ef986e985bd65d437b8
Author: Matthias Clasen <mclasen redhat com>
Date:   Thu Sep 9 22:23:37 2021 -0400

    Use our png loader for content (de)serialization
    
    We still fall back to gdk-pixbuf for handling all
    the other image formats. But with this in place,
    we no longer need to tweak the pixbuf formats to
    ensure that png comes first.

 gdk/gdkcontentdeserializer.c | 64 ++++++++++++++++++++---------
 gdk/gdkcontentserializer.c   | 96 +++++++++++++++++++++++++++++++++++---------
 2 files changed, 120 insertions(+), 40 deletions(-)
---
diff --git a/gdk/gdkcontentdeserializer.c b/gdk/gdkcontentdeserializer.c
index 4959b5af4d..68c6ae2553 100644
--- a/gdk/gdkcontentdeserializer.c
+++ b/gdk/gdkcontentdeserializer.c
@@ -25,6 +25,7 @@
 #include "filetransferportalprivate.h"
 #include "gdktexture.h"
 #include "gdkrgbaprivate.h"
+#include "gdkpng.h"
 
 #include <gdk-pixbuf/gdk-pixbuf.h>
 
@@ -655,6 +656,43 @@ pixbuf_deserializer (GdkContentDeserializer *deserializer)
                                     deserializer);
 }
 
+static void
+png_deserializer_finish (GObject      *source,
+                         GAsyncResult *res,
+                         gpointer      deserializer)
+{
+  GdkTexture *texture;
+  GValue *value;
+  GError *error = NULL;
+
+  texture = gdk_load_png_finish (res, &error);
+  if (texture == NULL)
+    {
+      gdk_content_deserializer_return_error (deserializer, error);
+      return;
+    }
+
+  value = gdk_content_deserializer_get_value (deserializer);
+  if (G_VALUE_HOLDS (value, GDK_TYPE_TEXTURE))
+    {
+      g_value_take_object (value, texture);
+    }
+  else
+    {
+      g_assert_not_reached ();
+    }
+  gdk_content_deserializer_return_success (deserializer);
+}
+
+static void
+png_deserializer (GdkContentDeserializer *deserializer)
+{
+  gdk_load_png_async (gdk_content_deserializer_get_input_stream (deserializer),
+                      gdk_content_deserializer_get_cancellable (deserializer),
+                      png_deserializer_finish,
+                      deserializer);
+}
+
 static void
 string_deserializer_finish (GObject      *source,
                             GAsyncResult *result,
@@ -863,27 +901,13 @@ init (void)
 
   initialized = TRUE;
 
-  formats = gdk_pixbuf_get_formats ();
-
-  /* Make sure png comes first */
-  for (f = formats; f; f = f->next)
-    {
-      GdkPixbufFormat *fmt = f->data;
-      char *name; 
- 
-      name = gdk_pixbuf_format_get_name (fmt);
-      if (g_str_equal (name, "png"))
-       {
-         formats = g_slist_delete_link (formats, f);
-         formats = g_slist_prepend (formats, fmt);
-
-         g_free (name);
-
-         break;
-       }
+  gdk_content_register_deserializer ("image/png",
+                                     GDK_TYPE_TEXTURE,
+                                     png_deserializer,
+                                     NULL,
+                                     NULL);
 
-      g_free (name);
-    }  
+  formats = gdk_pixbuf_get_formats ();
 
   for (f = formats; f; f = f->next)
     {
diff --git a/gdk/gdkcontentserializer.c b/gdk/gdkcontentserializer.c
index bc9deeb8d5..bf29c5cf0b 100644
--- a/gdk/gdkcontentserializer.c
+++ b/gdk/gdkcontentserializer.c
@@ -26,6 +26,7 @@
 #include "filetransferportalprivate.h"
 #include "gdktextureprivate.h"
 #include "gdkrgba.h"
+#include "gdkpng.h"
 
 #include <gdk-pixbuf/gdk-pixbuf.h>
 #include <string.h>
@@ -606,6 +607,7 @@ gdk_content_serialize_finish (GAsyncResult  *result,
 
 /*** SERIALIZERS ***/
 
+
 static void
 pixbuf_serializer_finish (GObject      *source,
                           GAsyncResult *res,
@@ -658,6 +660,75 @@ pixbuf_serializer (GdkContentSerializer *serializer)
   g_object_unref (pixbuf);
 }
 
+typedef struct {
+  GdkContentSerializer *serializer;
+  GBytes *bytes;
+} PngSerializerData;
+
+static void
+png_serializer_finish (GObject      *source,
+                       GAsyncResult *res,
+                       gpointer      user_data)
+{
+  PngSerializerData *data = user_data;
+  GError *error = NULL;
+
+  if (!gdk_save_png_finish (res, &error))
+    gdk_content_serializer_return_error (data->serializer, error);
+  else
+    gdk_content_serializer_return_success (data->serializer);
+
+  g_bytes_unref (data->bytes);
+  g_free (data);
+}
+
+static void
+png_serializer (GdkContentSerializer *serializer)
+{
+  const GValue *value;
+  GdkTexture *texture;
+  GdkMemoryFormat format;
+  GBytes *bytes = NULL;
+  PngSerializerData *data;
+
+  value = gdk_content_serializer_get_value (serializer);
+
+  if (G_VALUE_HOLDS (value, GDK_TYPE_TEXTURE))
+    {
+      texture = g_value_get_object (value);
+    }
+  else
+    {
+      g_assert_not_reached ();
+    }
+
+  for (int i = 0; i < GDK_MEMORY_N_FORMATS; i++)
+    {
+      bytes = gdk_texture_download_format (texture, i);
+      if (bytes)
+        {
+          format = i;
+          break;
+        }
+    }
+
+  g_assert (bytes != NULL);
+
+  data = g_new0 (PngSerializerData, 1);
+  data->serializer = serializer;
+  data->bytes = bytes;
+
+  gdk_save_png_async (gdk_content_serializer_get_output_stream (serializer),
+                      g_bytes_get_data (bytes, NULL),
+                      gdk_texture_get_width (texture),
+                      gdk_texture_get_height (texture),
+                      format,
+                      gdk_content_serializer_get_cancellable (serializer),
+                      png_serializer_finish,
+                      data);
+  g_object_unref (texture);
+}
+
 static void
 string_serializer_finish (GObject      *source,
                           GAsyncResult *result,
@@ -877,27 +948,12 @@ init (void)
 
   initialized = TRUE;
 
-  formats = gdk_pixbuf_get_formats ();
-
-  /* Make sure png comes first */
-  for (f = formats; f; f = f->next)
-    {
-      GdkPixbufFormat *fmt = f->data;
-      char *name; 
- 
-      name = gdk_pixbuf_format_get_name (fmt);
-      if (g_str_equal (name, "png"))
-       {
-         formats = g_slist_delete_link (formats, f);
-         formats = g_slist_prepend (formats, fmt);
-
-         g_free (name);
+  gdk_content_register_serializer (GDK_TYPE_TEXTURE,
+                                   "image/png",
+                                   png_serializer,
+                                   NULL, NULL);
 
-         break;
-       }
-
-      g_free (name);
-    }  
+  formats = gdk_pixbuf_get_formats ();
 
   for (f = formats; f; f = f->next)
     {


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