[gnome-games/wip/exalm/gtk4: 237/238] game-thumbnail: Port to textures and render nodes



commit 2048f8221dc40484128f6328a14c714949c761b1
Author: Alexander Mikhaylenko <exalm7659 gmail com>
Date:   Tue Aug 20 01:15:14 2019 +0500

    game-thumbnail: Port to textures and render nodes
    
    This allows them to be drawn on GPU together with other widgets.

 src/ui/game-thumbnail.vala | 153 +++++++++++++++++++++------------------------
 1 file changed, 73 insertions(+), 80 deletions(-)
---
diff --git a/src/ui/game-thumbnail.vala b/src/ui/game-thumbnail.vala
index 2c1bb335..7ce41d24 100644
--- a/src/ui/game-thumbnail.vala
+++ b/src/ui/game-thumbnail.vala
@@ -1,6 +1,6 @@
 // This file is part of GNOME Games. License: GPL-3.0+.
 
-private class Games.GameThumbnail : Gtk.DrawingArea {
+private class Games.GameThumbnail : Gtk.Widget {
        private const Gtk.CornerType[] right_corners = { Gtk.CornerType.TOP_RIGHT, 
Gtk.CornerType.BOTTOM_RIGHT };
        private const Gtk.CornerType[] bottom_corners = { Gtk.CornerType.BOTTOM_LEFT, 
Gtk.CornerType.BOTTOM_RIGHT };
 
@@ -54,12 +54,12 @@ private class Games.GameThumbnail : Gtk.DrawingArea {
        }
 
        private bool tried_loading_cover;
-       private Gdk.Pixbuf? cover_cache;
+       private Gdk.Texture? cover_cache;
        private int previous_cover_width;
        private int previous_cover_height;
 
        public struct DrawingContext {
-               Cairo.Context cr;
+               Gtk.Snapshot snapshot;
                Gtk.StyleContext style;
                int width;
                int height;
@@ -78,15 +78,13 @@ private class Games.GameThumbnail : Gtk.DrawingArea {
                minimum_baseline = natural_baseline = -1;
        }
 
-       construct {
-               set_draw_func (draw);
-       }
-
-       public void draw (Gtk.DrawingArea area, Cairo.Context cr, int width, int height) {
+       public override void snapshot (Gtk.Snapshot snapshot) {
                var style = get_style_context ();
+               var width = get_width ();
+               var height = get_height ();
 
                DrawingContext context = {
-                       cr, style, width, height
+                       snapshot, style, width, height
                };
 
                if (icon == null)
@@ -97,6 +95,9 @@ private class Games.GameThumbnail : Gtk.DrawingArea {
 
                var drawn = false;
 
+               var mask = get_mask (context);
+               context.snapshot.push_rounded_clip (mask);
+
                drawn = draw_cover (context);
 
                if (!drawn)
@@ -105,6 +106,8 @@ private class Games.GameThumbnail : Gtk.DrawingArea {
                // Draw the default thumbnail if no thumbnail have been drawn
                if (!drawn)
                        draw_default (context);
+
+               context.snapshot.pop ();
        }
 
        public bool draw_icon (DrawingContext context) {
@@ -112,36 +115,35 @@ private class Games.GameThumbnail : Gtk.DrawingArea {
                if (g_icon == null)
                        return false;
 
-               var pixbuf = get_scaled_icon (context, g_icon, ICON_SCALE);
-               if (pixbuf == null)
+               var texture = get_scaled_icon (context, g_icon, ICON_SCALE);
+               if (texture == null)
                        return false;
 
-               draw_pixbuf (context, pixbuf);
+               draw_texture (context, texture);
 
                return true;
        }
 
        public bool draw_cover (DrawingContext context) {
-               var pixbuf = get_scaled_cover (context);
-               if (pixbuf == null)
+               var texture = get_scaled_cover (context);
+               if (texture == null)
                        return false;
 
-               var border_radius = (int) context.style.get_property (Gtk.STYLE_PROPERTY_BORDER_RADIUS);
-               border_radius = border_radius.clamp (0, int.max (context.width / 2, context.height / 2));
-
-               context.cr.set_source_rgb (0, 0, 0);
-               rounded_rectangle (context.cr, 0.5, 0.5, context.width - 1, context.height - 1, 
border_radius);
-               context.cr.fill ();
-               draw_pixbuf (context, pixbuf);
+               draw_background (context);
+               draw_texture (context, texture);
 
                return true;
        }
 
        public void draw_default (DrawingContext context) {
-               draw_emblem_icon (context, Config.APPLICATION_ID + "-symbolic", EMBLEM_SCALE);
+               var texture = get_emblem_icon (context, Config.APPLICATION_ID + "-symbolic", EMBLEM_SCALE);
+               if (texture == null)
+                       return;
+
+               draw_texture (context, texture);
        }
 
-       private void draw_emblem_icon (DrawingContext context, string icon_name, double scale) {
+       private Gdk.Texture? get_emblem_icon (DrawingContext context, string icon_name, double scale) {
                Gdk.Pixbuf? emblem = null;
 
                var color = context.style.get_color ();
@@ -153,25 +155,16 @@ private class Games.GameThumbnail : Gtk.DrawingArea {
                        emblem = icon_info.load_symbolic (color);
                } catch (GLib.Error error) {
                        warning (@"Unable to get icon “$icon_name”: $(error.message)");
-                       return;
+                       return null;
                }
 
                if (emblem == null)
-                       return;
-
-               double offset_x = context.width * scale_factor / 2.0 - emblem.width / 2.0;
-               double offset_y = context.height * scale_factor / 2.0 - emblem.height / 2.0;
-
-               context.cr.save ();
-               context.cr.scale (1.0 / scale_factor, 1.0 / scale_factor);
-
-               Gdk.cairo_set_source_pixbuf (context.cr, emblem, offset_x, offset_y);
-               context.cr.paint ();
+                       return null;
 
-               context.cr.restore ();
+               return Gdk.Texture.for_pixbuf (emblem);
        }
 
-       private Gdk.Pixbuf? get_scaled_icon (DrawingContext context, GLib.Icon? icon, double scale) {
+       private Gdk.Texture? get_scaled_icon (DrawingContext context, GLib.Icon? icon, double scale) {
                if (icon == null)
                        return null;
 
@@ -183,16 +176,22 @@ private class Games.GameThumbnail : Gtk.DrawingArea {
                if (icon_info == null)
                        return null;
 
+               Gdk.Pixbuf? pixbuf = null;
                try {
-                       return icon_info.load_icon ();
+                       pixbuf = icon_info.load_icon ();
                }
                catch (Error e) {
                        warning (@"Couldn’t load the icon: $(e.message)\n");
                        return null;
                }
+
+               if (pixbuf == null)
+                       return null;
+
+               return Gdk.Texture.for_pixbuf (pixbuf);
        }
 
-       private Gdk.Pixbuf? get_scaled_cover (DrawingContext context) {
+       private Gdk.Texture? get_scaled_cover (DrawingContext context) {
                if (previous_cover_width != context.width * scale_factor) {
                        previous_cover_width = context.width * scale_factor;
                        cover_cache = null;
@@ -222,14 +221,20 @@ private class Games.GameThumbnail : Gtk.DrawingArea {
                var lookup_flags = Gtk.IconLookupFlags.FORCE_SIZE | Gtk.IconLookupFlags.FORCE_REGULAR;
                var icon_info = theme.lookup_by_gicon (g_icon, (int) size, lookup_flags);
 
+               Gdk.Pixbuf? pixbuf = null;
                try {
-                       cover_cache = icon_info.load_icon ();
-                       save_cover_cache_to_disk (size);
+                       pixbuf = icon_info.load_icon ();
+                       save_cover_cache_to_disk (pixbuf, size);
                }
                catch (Error e) {
                        warning (@"Couldn’t load the icon: $(e.message)\n");
                }
 
+               if (pixbuf == null)
+                       return null;
+
+               cover_cache = Gdk.Texture.for_pixbuf (pixbuf);
+
                return cover_cache;
        }
 
@@ -250,17 +255,15 @@ private class Games.GameThumbnail : Gtk.DrawingArea {
                }
 
                try {
-                       cover_cache = new Gdk.Pixbuf.from_file_at_scale (cover_cache_path,
-                                                                        context.width * scale_factor,
-                                                                        context.height * scale_factor,
-                                                                        true);
+                       var file = File.new_for_path (cover_cache_path);
+                       cover_cache = Gdk.Texture.from_file (file);
                }
                catch (Error e) {
                        debug (e.message);
                }
        }
 
-       private void save_cover_cache_to_disk (int size) {
+       private void save_cover_cache_to_disk (Gdk.Pixbuf? pixbuf, int size) {
                if (cover_cache == null)
                        return;
 
@@ -270,10 +273,10 @@ private class Games.GameThumbnail : Gtk.DrawingArea {
 
                try {
                        var cover_cache_path = get_cover_cache_path (size);
-                       cover_cache.save (cover_cache_path, "png",
-                                         "tEXt::Software", "GNOME Games",
-                                         "tEXt::Creation Time", creation_time.to_string (),
-                                         null);
+                       pixbuf.save (cover_cache_path, "png",
+                                    "tEXt::Software", "GNOME Games",
+                                    "tEXt::Creation Time", creation_time.to_string (),
+                                    null);
                }
                catch (Error e) {
                        critical (e.message);
@@ -296,47 +299,37 @@ private class Games.GameThumbnail : Gtk.DrawingArea {
                queue_draw ();
        }
 
-       private void draw_pixbuf (DrawingContext context, Gdk.Pixbuf pixbuf) {
-               context.cr.save ();
-               context.cr.scale (1.0 / scale_factor, 1.0 / scale_factor);
-
-               var mask = get_mask (context);
-
-               var x_offset = (context.width * scale_factor - pixbuf.width) / 2;
-               var y_offset = (context.height * scale_factor - pixbuf.height) / 2;
+       private void draw_texture (DrawingContext context, Gdk.Texture texture) {
+               var x_offset = (context.width * scale_factor - texture.width) / 2;
+               var y_offset = (context.height * scale_factor - texture.height) / 2;
 
-               Gdk.cairo_set_source_pixbuf (context.cr, pixbuf, x_offset, y_offset);
-               context.cr.mask_surface (mask, 0, 0);
+               Graphene.Rect bounds = {};
+               bounds.init (x_offset, y_offset, texture.width, texture.height);
 
-               context.cr.restore ();
+               context.snapshot.scale (1.0f / scale_factor, 1.0f / scale_factor);
+               context.snapshot.append_texture (texture, bounds);
+               context.snapshot.scale (scale_factor, scale_factor);
        }
 
-       private Cairo.Surface get_mask (DrawingContext context) {
-               var mask = new Cairo.ImageSurface (Cairo.Format.A8, context.width * scale_factor, 
context.height * scale_factor);
+       private Gsk.RoundedRect get_mask (DrawingContext context) {
+               Graphene.Rect bounds = {};
+               bounds.init (0, 0, context.width, context.height);
 
                var border_radius = (int) context.style.get_property (Gtk.STYLE_PROPERTY_BORDER_RADIUS);
                border_radius = border_radius.clamp (0, int.max (context.width / 2, context.height / 2));
 
-               var cr = new Cairo.Context (mask);
-               cr.scale (scale_factor, scale_factor);
-               cr.set_source_rgb (0, 0, 0);
-               rounded_rectangle (cr, 0.5, 0.5, context.width - 1, context.height - 1, border_radius);
-               cr.fill ();
+               Gsk.RoundedRect rect = {};
+               rect.init_from_rect (bounds, border_radius);
 
-               return mask;
+               return rect;
        }
 
-       private void rounded_rectangle (Cairo.Context cr, double x, double y, double width, double height, 
double radius) {
-               const double ARC_0 = 0;
-               const double ARC_1 = Math.PI * 0.5;
-               const double ARC_2 = Math.PI;
-               const double ARC_3 = Math.PI * 1.5;
-
-               cr.new_sub_path ();
-               cr.arc (x + width - radius, y + radius,          radius, ARC_3, ARC_0);
-               cr.arc (x + width - radius, y + height - radius, radius, ARC_0, ARC_1);
-               cr.arc (x + radius,         y + height - radius, radius, ARC_1, ARC_2);
-               cr.arc (x + radius,         y + radius,          radius, ARC_2, ARC_3);
-               cr.close_path ();
+       private void draw_background (DrawingContext context) {
+               Graphene.Rect bounds = {};
+               bounds.init (0, 0, context.width, context.height);
+
+               Gdk.RGBA rgba = {0, 0, 0, 1};
+
+               context.snapshot.append_color (rgba, bounds);
        }
 }


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