[gtk/delayed-loading: 4/5] Add delayed loading for textures




commit 429132b40b272a6840af56d77ad43aff7b3a6aae
Author: Matthias Clasen <mclasen redhat com>
Date:   Sat Sep 18 13:25:47 2021 -0400

    Add delayed loading for textures

 gtk/gdkpixbufutils.c   |  14 ++--
 gtk/gtkloader.c        | 198 +++++++++++++++++++++++++++++++++++++++++++++++++
 gtk/gtkloaderprivate.h |  35 +++++++++
 gtk/meson.build        |   1 +
 4 files changed, 241 insertions(+), 7 deletions(-)
---
diff --git a/gtk/gdkpixbufutils.c b/gtk/gdkpixbufutils.c
index df8c542deb..59c87a97e9 100644
--- a/gtk/gdkpixbufutils.c
+++ b/gtk/gdkpixbufutils.c
@@ -580,7 +580,7 @@ gdk_paintable_new_from_bytes_scaled (GBytes *bytes,
                                      int     scale_factor)
 {
   LoaderData loader_data;
-  GdkTexture *texture;
+  GdkPaintable *inner;
   GdkPaintable *paintable;
 
   loader_data.scale_factor = scale_factor;
@@ -588,8 +588,8 @@ gdk_paintable_new_from_bytes_scaled (GBytes *bytes,
   if (gdk_texture_can_load (bytes))
     {
       /* We know these formats can't be scaled */
-      texture = gdk_texture_new_from_bytes (bytes, NULL);
-      if (texture == NULL)
+      inner = GDK_PAINTABLE (gdk_texture_new_from_bytes (bytes, NULL));
+      if (inner == NULL)
         return NULL;
     }
   else
@@ -608,16 +608,16 @@ gdk_paintable_new_from_bytes_scaled (GBytes *bytes,
       if (!success)
         return NULL;
 
-      texture = gdk_texture_new_for_pixbuf (gdk_pixbuf_loader_get_pixbuf (loader));
+      inner = GDK_PAINTABLE (gdk_texture_new_for_pixbuf (gdk_pixbuf_loader_get_pixbuf (loader)));
       g_object_unref (loader);
     }
 
   if (loader_data.scale_factor != 1)
-    paintable = gtk_scaler_new (GDK_PAINTABLE (texture), loader_data.scale_factor);
+    paintable = gtk_scaler_new (inner, loader_data.scale_factor);
   else
-    paintable = g_object_ref ((GdkPaintable *)texture);
+    paintable = g_object_ref ((GdkPaintable *)inner);
 
-  g_object_unref (texture);
+  g_object_unref (inner);
 
   return paintable;
 }
diff --git a/gtk/gtkloader.c b/gtk/gtkloader.c
new file mode 100644
index 0000000000..35ec8bbada
--- /dev/null
+++ b/gtk/gtkloader.c
@@ -0,0 +1,198 @@
+/*
+ * Copyright © 2018 Benjamin Otte
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Benjamin Otte <otte gnome org>
+ */
+
+#include "config.h"
+
+#include "gtkloaderprivate.h"
+
+#include "gtksnapshot.h"
+
+struct _GtkLoader
+{
+  GObject parent_instance;
+
+  GdkTexture *texture;
+};
+
+struct _GtkLoaderClass
+{
+  GObjectClass parent_class;
+};
+
+static void
+gtk_loader_paintable_snapshot (GdkPaintable *paintable,
+                               GdkSnapshot  *snapshot,
+                               double        width,
+                               double        height)
+{
+  GtkLoader *self = GTK_LOADER (paintable);
+
+  if (self->texture)
+    gdk_paintable_snapshot (GDK_PAINTABLE (self->texture), snapshot, width, height);
+}
+
+static GdkPaintable *
+gtk_loader_paintable_get_current_image (GdkPaintable *paintable)
+{
+  GtkLoader *self = GTK_LOADER (paintable);
+
+  if (self->texture)
+    return gdk_paintable_get_current_image (GDK_PAINTABLE (self->texture));
+
+  // FIXME: return a loading image
+  return NULL;
+}
+
+static GdkPaintableFlags
+gtk_loader_paintable_get_flags (GdkPaintable *paintable)
+{
+  GtkLoader *self = GTK_LOADER (paintable);
+
+  if (self->texture)
+    return gdk_paintable_get_flags (GDK_PAINTABLE (self->texture));
+
+  return 0;
+}
+
+static int
+gtk_loader_paintable_get_intrinsic_width (GdkPaintable *paintable)
+{
+  GtkLoader *self = GTK_LOADER (paintable);
+
+  if (self->texture)
+    return gdk_paintable_get_intrinsic_width (GDK_PAINTABLE (self->texture));
+
+  return 16;
+}
+
+static int
+gtk_loader_paintable_get_intrinsic_height (GdkPaintable *paintable)
+{
+  GtkLoader *self = GTK_LOADER (paintable);
+
+  if (self->texture)
+    return gdk_paintable_get_intrinsic_height (GDK_PAINTABLE (self->texture));
+
+  return 16;
+}
+
+static double
+gtk_loader_paintable_get_intrinsic_aspect_ratio (GdkPaintable *paintable)
+{
+  GtkLoader *self = GTK_LOADER (paintable);
+
+  if (self->texture)
+    return gdk_paintable_get_intrinsic_aspect_ratio (GDK_PAINTABLE (self->texture));
+
+  return 0;
+};
+
+static void
+gtk_loader_paintable_init (GdkPaintableInterface *iface)
+{
+  iface->snapshot = gtk_loader_paintable_snapshot;
+  iface->get_current_image = gtk_loader_paintable_get_current_image;
+  iface->get_flags = gtk_loader_paintable_get_flags;
+  iface->get_intrinsic_width = gtk_loader_paintable_get_intrinsic_width;
+  iface->get_intrinsic_height = gtk_loader_paintable_get_intrinsic_height;
+  iface->get_intrinsic_aspect_ratio = gtk_loader_paintable_get_intrinsic_aspect_ratio;
+}
+
+G_DEFINE_TYPE_EXTENDED (GtkLoader, gtk_loader, G_TYPE_OBJECT, 0,
+                        G_IMPLEMENT_INTERFACE (GDK_TYPE_PAINTABLE,
+                                               gtk_loader_paintable_init))
+
+static void
+gtk_loader_dispose (GObject *object)
+{
+  GtkLoader *self = GTK_LOADER (object);
+
+  g_clear_object (&self->texture);
+
+  G_OBJECT_CLASS (gtk_loader_parent_class)->dispose (object);
+}
+
+static void
+gtk_loader_class_init (GtkLoaderClass *klass)
+{
+  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+  gobject_class->dispose = gtk_loader_dispose;
+}
+
+static void
+gtk_loader_init (GtkLoader *self)
+{
+}
+
+static void
+load_texture_in_thread (GTask        *task,
+                        gpointer      source_object,
+                        gpointer      task_data,
+                        GCancellable *cancellable)
+{
+  GBytes *bytes = task_data;
+  GdkTexture *texture;
+  GError *error = NULL;
+
+  texture = gdk_texture_new_from_bytes (bytes, &error);
+
+  if (texture)
+    g_task_return_pointer (task, texture, g_object_unref);
+  else
+    g_task_return_error (task, error);
+}
+
+static void
+texture_finished (GObject      *source,
+                  GAsyncResult *result,
+                  gpointer      data)
+{
+  GtkLoader *self = GTK_LOADER (source);
+  GdkTexture *texture;
+  GError *error = NULL;
+
+  texture = g_task_propagate_pointer (G_TASK (result), &error);
+
+  if (texture)
+    {
+      self->texture = g_object_ref (texture);
+
+      gdk_paintable_invalidate_size (GDK_PAINTABLE (self));
+      gdk_paintable_invalidate_contents (GDK_PAINTABLE (self));
+    }
+}
+
+GdkPaintable *
+gtk_loader_new (GBytes *bytes)
+{
+  GtkLoader *self;
+  GTask *task;
+
+  g_return_val_if_fail (bytes != NULL, NULL);
+
+  self = g_object_new (GTK_TYPE_LOADER, NULL);
+
+  task = g_task_new (self, NULL, texture_finished, NULL);
+  g_task_set_task_data (task, g_bytes_ref (bytes), (GDestroyNotify)g_bytes_unref);
+  g_task_run_in_thread (task, load_texture_in_thread);
+  g_object_unref (task);
+
+  return GDK_PAINTABLE (self);
+}
diff --git a/gtk/gtkloaderprivate.h b/gtk/gtkloaderprivate.h
new file mode 100644
index 0000000000..4ae56eef5e
--- /dev/null
+++ b/gtk/gtkloaderprivate.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright © 2021 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Matthias Clasen <mclasen redhat com>
+ */
+
+#ifndef __GTK_LOADER_H__
+#define __GTK_LOADER_H__
+
+#include <gdk/gdk.h>
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_LOADER (gtk_loader_get_type ())
+
+G_DECLARE_FINAL_TYPE (GtkLoader, gtk_loader, GTK, LOADER, GObject)
+
+GdkPaintable *  gtk_loader_new          (GBytes *bytes);
+
+G_END_DECLS
+
+#endif /* __GTK_SCALER_H__ */
diff --git a/gtk/meson.build b/gtk/meson.build
index bc097fdd6f..747096a7d4 100644
--- a/gtk/meson.build
+++ b/gtk/meson.build
@@ -116,6 +116,7 @@ gtk_private_sources = files([
   'gtkiconhelper.c',
   'gtkjoinedmenu.c',
   'gtkkineticscrolling.c',
+  'gtkloader.c',
   'gtkmagnifier.c',
   'gtkmenusectionbox.c',
   'gtkmenutracker.c',


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