[gtk/image-loading: 10/15] Use our own loaders for content (de)serialization
- From: Matthias Clasen <matthiasc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk/image-loading: 10/15] Use our own loaders for content (de)serialization
- Date: Mon, 13 Sep 2021 19:36:26 +0000 (UTC)
commit b66fa84161aa05c6b0d5ed1051eae3a61ddfea16
Author: Matthias Clasen <mclasen redhat com>
Date: Thu Sep 9 22:23:37 2021 -0400
Use our own loaders for content (de)serialization
Use our own loader to (de)serialiaze textures
to and from png and tiff.
We still fall back to gdk-pixbuf for handling all
the other image formats, and for pixbufs.
gdk/gdkcontentdeserializer.c | 135 +++++++++++++++++++++++++++++++++++++------
gdk/gdkcontentserializer.c | 131 +++++++++++++++++++++++++++++++++++------
2 files changed, 231 insertions(+), 35 deletions(-)
---
diff --git a/gdk/gdkcontentdeserializer.c b/gdk/gdkcontentdeserializer.c
index 4959b5af4d..6731b47e24 100644
--- a/gdk/gdkcontentdeserializer.c
+++ b/gdk/gdkcontentdeserializer.c
@@ -25,6 +25,8 @@
#include "filetransferportalprivate.h"
#include "gdktexture.h"
#include "gdkrgbaprivate.h"
+#include "loaders/gdkpngprivate.h"
+#include "loaders/gdktiffprivate.h"
#include <gdk-pixbuf/gdk-pixbuf.h>
@@ -655,6 +657,88 @@ pixbuf_deserializer (GdkContentDeserializer *deserializer)
deserializer);
}
+static void
+texture_deserializer_finish (GObject *source,
+ GAsyncResult *res,
+ gpointer data)
+{
+ GdkContentDeserializer *deserializer = GDK_CONTENT_DESERIALIZER (source);
+ GdkTexture *texture;
+ GValue *value;
+ GError *error = NULL;
+
+ texture = g_task_propagate_pointer (G_TASK (res), &error);
+ if (texture == NULL)
+ {
+ gdk_content_deserializer_return_error (deserializer, error);
+ return;
+ }
+
+ value = gdk_content_deserializer_get_value (deserializer);
+ g_value_take_object (value, texture);
+ gdk_content_deserializer_return_success (deserializer);
+}
+
+static GBytes *
+read_all_data (GInputStream *source,
+ GError **error)
+{
+ GOutputStream *output;
+ gssize size;
+ GBytes *bytes;
+
+ output = g_memory_output_stream_new (NULL, 0, g_realloc, g_free);
+ size = g_output_stream_splice (output, source, 0, NULL, error);
+ if (size == -1)
+ {
+ g_object_unref (output);
+ return NULL;
+ }
+
+ g_output_stream_close (output, NULL, NULL);
+ bytes = g_memory_output_stream_steal_as_bytes (G_MEMORY_OUTPUT_STREAM (output));
+ g_object_unref (output);
+
+ return bytes;
+}
+
+static void
+deserialize_texture_in_thread (GTask *task,
+ gpointer source_object,
+ gpointer task_data,
+ GCancellable *cancellable)
+{
+ GdkContentDeserializer *deserializer = source_object;
+ GBytes *bytes;
+ GError *error = NULL;
+ GdkTexture *texture = NULL;
+
+ bytes = read_all_data (gdk_content_deserializer_get_input_stream (deserializer), &error);
+ if (bytes)
+ {
+ texture = gdk_texture_new_from_bytes (bytes, &error);
+ g_bytes_unref (bytes);
+ }
+
+ if (texture)
+ g_task_return_pointer (task, texture, g_object_unref);
+ else
+ g_task_return_error (task, error);
+}
+
+static void
+texture_deserializer (GdkContentDeserializer *deserializer)
+{
+ GTask *task;
+
+ task = g_task_new (deserializer,
+ gdk_content_deserializer_get_cancellable (deserializer),
+ texture_deserializer_finish,
+ NULL);
+ g_task_run_in_thread (task, deserialize_texture_in_thread);
+ g_object_unref (task);
+}
+
static void
string_deserializer_finish (GObject *source,
GAsyncResult *result,
@@ -863,48 +947,65 @@ init (void)
initialized = TRUE;
+ gdk_content_register_deserializer ("image/png",
+ GDK_TYPE_TEXTURE,
+ texture_deserializer,
+ NULL,
+ NULL);
+
+ gdk_content_register_deserializer ("image/tiff",
+ GDK_TYPE_TEXTURE,
+ texture_deserializer,
+ NULL,
+ NULL);
+
formats = gdk_pixbuf_get_formats ();
/* Make sure png comes first */
for (f = formats; f; f = f->next)
{
GdkPixbufFormat *fmt = f->data;
- char *name;
-
+ 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);
+ {
+ formats = g_slist_delete_link (formats, f);
+ formats = g_slist_prepend (formats, fmt);
- break;
- }
+ g_free (name);
+ break;
+ }
g_free (name);
- }
+ }
for (f = formats; f; f = f->next)
{
GdkPixbufFormat *fmt = f->data;
char **mimes, **m;
+ char *name;
+ name = gdk_pixbuf_format_get_name (fmt);
mimes = gdk_pixbuf_format_get_mime_types (fmt);
for (m = mimes; *m; m++)
- {
- gdk_content_register_deserializer (*m,
- GDK_TYPE_TEXTURE,
- pixbuf_deserializer,
- NULL,
- NULL);
+ {
+ /* Turning pngs and tiffs into textures is handled above */
+ if (!g_str_equal (name, "png") &&
+ !g_str_equal (name, "tiff"))
+ gdk_content_register_deserializer (*m,
+ GDK_TYPE_TEXTURE,
+ pixbuf_deserializer,
+ NULL,
+ NULL);
gdk_content_register_deserializer (*m,
GDK_TYPE_PIXBUF,
pixbuf_deserializer,
NULL,
NULL);
- }
+ }
g_strfreev (mimes);
+ g_free (name);
}
g_slist_free (formats);
diff --git a/gdk/gdkcontentserializer.c b/gdk/gdkcontentserializer.c
index bc9deeb8d5..316f6ad9c0 100644
--- a/gdk/gdkcontentserializer.c
+++ b/gdk/gdkcontentserializer.c
@@ -26,6 +26,9 @@
#include "filetransferportalprivate.h"
#include "gdktextureprivate.h"
#include "gdkrgba.h"
+#include "loaders/gdkpngprivate.h"
+#include "loaders/gdktiffprivate.h"
+#include "gdkmemorytextureprivate.h"
#include <gdk-pixbuf/gdk-pixbuf.h>
#include <string.h>
@@ -606,6 +609,7 @@ gdk_content_serialize_finish (GAsyncResult *result,
/*** SERIALIZERS ***/
+
static void
pixbuf_serializer_finish (GObject *source,
GAsyncResult *res,
@@ -658,6 +662,82 @@ pixbuf_serializer (GdkContentSerializer *serializer)
g_object_unref (pixbuf);
}
+static void
+texture_serializer_finish (GObject *source,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ GdkContentSerializer *serializer = GDK_CONTENT_SERIALIZER (source);
+ GError *error = NULL;
+
+ if (!g_task_propagate_boolean (G_TASK (res), &error))
+ gdk_content_serializer_return_error (serializer, error);
+ else
+ gdk_content_serializer_return_success (serializer);
+}
+
+static void
+serialize_texture_in_thread (GTask *task,
+ gpointer source_object,
+ gpointer task_data,
+ GCancellable *cancellable)
+{
+ GdkContentSerializer *serializer = source_object;
+ const GValue *value;
+ GdkTexture *texture;
+ GBytes *bytes = NULL;
+ GError *error = NULL;
+ gboolean result = FALSE;
+
+ value = gdk_content_serializer_get_value (serializer);
+ texture = g_value_get_object (value);
+
+ if (strcmp (gdk_content_serializer_get_mime_type (serializer), "image/png") == 0)
+ bytes = gdk_save_png (texture);
+ else if (strcmp (gdk_content_serializer_get_mime_type (serializer), "image/tiff") == 0)
+ bytes = gdk_save_tiff (texture);
+ else
+ g_assert_not_reached ();
+
+ if (bytes)
+ {
+ GInputStream *input = g_memory_input_stream_new_from_bytes (bytes);
+ gssize spliced;
+
+ spliced = g_output_stream_splice (gdk_content_serializer_get_output_stream (serializer),
+ input,
+ G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE,
+ gdk_content_serializer_get_cancellable (serializer),
+ &error);
+ g_object_unref (input);
+ g_bytes_unref (bytes);
+
+ result = spliced != -1;
+ }
+ else
+ g_set_error_literal (&error,
+ G_IO_ERROR, G_IO_ERROR_FAILED,
+ "Saving png failed");
+
+ if (result)
+ g_task_return_boolean (task, result);
+ else
+ g_task_return_error (task, error);
+}
+
+static void
+texture_serializer (GdkContentSerializer *serializer)
+{
+ GTask *task;
+
+ task = g_task_new (serializer,
+ gdk_content_serializer_get_cancellable (serializer),
+ texture_serializer_finish,
+ NULL);
+ g_task_run_in_thread (task, serialize_texture_in_thread);
+ g_object_unref (task);
+}
+
static void
string_serializer_finish (GObject *source,
GAsyncResult *result,
@@ -877,51 +957,66 @@ init (void)
initialized = TRUE;
+ gdk_content_register_serializer (GDK_TYPE_TEXTURE,
+ "image/png",
+ texture_serializer,
+ NULL, NULL);
+
+ gdk_content_register_serializer (GDK_TYPE_TEXTURE,
+ "image/tiff",
+ texture_serializer,
+ NULL, NULL);
+
formats = gdk_pixbuf_get_formats ();
/* Make sure png comes first */
for (f = formats; f; f = f->next)
{
GdkPixbufFormat *fmt = f->data;
- char *name;
-
+ 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);
+ {
+ formats = g_slist_delete_link (formats, f);
+ formats = g_slist_prepend (formats, fmt);
- break;
- }
+ g_free (name);
+ break;
+ }
g_free (name);
- }
+ }
for (f = formats; f; f = f->next)
{
GdkPixbufFormat *fmt = f->data;
char **mimes, **m;
+ char *name;
if (!gdk_pixbuf_format_is_writable (fmt))
- continue;
+ continue;
+ name = gdk_pixbuf_format_get_name (fmt);
mimes = gdk_pixbuf_format_get_mime_types (fmt);
for (m = mimes; *m; m++)
- {
- gdk_content_register_serializer (GDK_TYPE_TEXTURE,
- *m,
- pixbuf_serializer,
- gdk_pixbuf_format_get_name (fmt),
- g_free);
+ {
+ /* Turning textures into pngs or tiffs is handled above */
+ if (!g_str_equal (name, "png") &&
+ !g_str_equal (name, "tiff"))
+ gdk_content_register_serializer (GDK_TYPE_TEXTURE,
+ *m,
+ pixbuf_serializer,
+ gdk_pixbuf_format_get_name (fmt),
+ g_free);
gdk_content_register_serializer (GDK_TYPE_PIXBUF,
*m,
pixbuf_serializer,
gdk_pixbuf_format_get_name (fmt),
g_free);
- }
+ }
g_strfreev (mimes);
+ g_free (name);
}
g_slist_free (formats);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]