[gnome-games] cover-loader: Cache icons



commit 40c87d7ad31e4d279ac6c4213d78fbc019228d08
Author: Adwait Rawat <adwait rawat gmail com>
Date:   Sun Feb 23 04:41:11 2020 +0900

    cover-loader: Cache icons
    
    Fixes #247

 src/core/cover-loader.vala | 105 ++++++++++++++++++++++++++--------------
 src/ui/application.vala    |   6 +--
 src/ui/game-thumbnail.vala | 116 +++++++++++++++++++--------------------------
 3 files changed, 122 insertions(+), 105 deletions(-)
---
diff --git a/src/core/cover-loader.vala b/src/core/cover-loader.vala
index e8e0bb00..7b697814 100644
--- a/src/core/cover-loader.vala
+++ b/src/core/cover-loader.vala
@@ -1,11 +1,12 @@
 // This file is part of GNOME Games. License: GPL-3.0+.
 
 public class Games.CoverLoader : Object {
-       public delegate void CoverReadyCallback (int size, Gdk.Pixbuf? pixbuf);
+       public delegate void CoverReadyCallback (int cover_size, Gdk.Pixbuf? cover_pixbuf, int icon_size, 
Gdk.Pixbuf? icon_pixbuf);
 
        private struct CoverRequest {
                Game game;
-               int size;
+               int cover_size;
+               int icon_size;
                unowned CoverReadyCallback cb;
        }
 
@@ -17,9 +18,9 @@ public class Games.CoverLoader : Object {
                thread = new Thread<void> (null, run_loader_thread);
        }
 
-       private void run_callback (CoverRequest request, int size, Gdk.Pixbuf? pixbuf) {
+       private void run_callback (CoverRequest request, int cover_size, Gdk.Pixbuf? cover_pixbuf, int 
icon_size, Gdk.Pixbuf? icon_pixbuf) {
                Idle.add (() => {
-                       request.cb (size, pixbuf);
+                       request.cb (cover_size, cover_pixbuf, icon_size, icon_pixbuf);
                        return Source.REMOVE;
                });
        }
@@ -43,52 +44,86 @@ public class Games.CoverLoader : Object {
                }
        }
 
-       private void run_loader_thread () {
-               while (true) {
-                       var request = request_queue.pop ();
-                       var game = request.game;
-                       var size = request.size;
+       private Gdk.Pixbuf? try_load_cover (Game game, int size) {
+               var pixbuf = load_cache_from_disk (game, size, "covers");
+               if (pixbuf != null)
+                       return pixbuf;
 
-                       var pixbuf = load_cover_cache_from_disk (game, size);
-                       if (pixbuf != null) {
-                               run_callback (request, size, pixbuf);
-                               continue;
-                       }
-
-                       var file = game.get_cover ().get_cover ();
-                       if (file == null) {
-                               run_callback (request, size, null);
-                               continue;
-                       }
+               var file = game.get_cover ().get_cover ();
 
+               if (file != null) {
                        int width, height;
                        get_dimensions (file, size, out width, out height);
 
                        try {
                                pixbuf = new Gdk.Pixbuf.from_file_at_scale (file.get_path (), width, height, 
false);
-                               save_cover_cache_to_disk (game, pixbuf, size);
+                               save_cache_to_disk (game, pixbuf, size, "covers");
                        }
                        catch (Error e) {
-                               run_callback (request, size, null);
-                               continue;
+                               return null;
                        }
+               }
+
+               return pixbuf;
+       }
+
+       private Gdk.Pixbuf? try_load_icon (Game game, int size) {
+               var pixbuf = load_cache_from_disk (game, size, "icons");
+               if (pixbuf != null)
+                       return pixbuf;
+
+               var icon = game.get_icon ().get_icon ();
+               if (icon == null)
+                       return null;
+
+               var theme = Gtk.IconTheme.get_default ();
+               var lookup_flags = Gtk.IconLookupFlags.FORCE_SIZE | Gtk.IconLookupFlags.FORCE_REGULAR;
+               var icon_info = theme.lookup_by_gicon (icon, (int) size, lookup_flags);
+
+               if (icon_info == null)
+                       return null;
+
+               try {
+                       pixbuf = icon_info.load_icon ();
+                       save_cache_to_disk (game, pixbuf, size, "icons");
+               }
+               catch (Error e) {
+                       critical ("Couldn’t load the icon: %s", e.message);
+                       return null;
+               }
+
+               return pixbuf;
+       }
+
+       private void run_loader_thread () {
+               while (true) {
+                       var request = request_queue.pop ();
+                       var game = request.game;
+                       var cover_size = request.cover_size;
+                       var icon_size = request.icon_size;
+
+                       var cover_pixbuf = try_load_cover (game, cover_size);
+                       if (cover_pixbuf != null)
+                               run_callback (request, cover_size, cover_pixbuf, icon_size, null);
+
+                       var icon_pixbuf = try_load_icon (game, icon_size);
 
-                       run_callback (request, size, pixbuf);
+                       run_callback (request, cover_size, cover_pixbuf, icon_size, icon_pixbuf);
                }
        }
 
-       private string get_cover_cache_path (Game game, int size) throws Error {
-               var dir = Application.get_covers_cache_dir (size);
+       private string get_cache_path (Game game, int size, string dir_name) throws Error {
+               var dir = Application.get_image_cache_dir (dir_name, size);
 
                var uid = game.get_uid ().get_uid ();
 
                return @"$dir/$uid.png";
        }
 
-       private Gdk.Pixbuf? load_cover_cache_from_disk (Game game, int size) {
-               string cover_cache_path;
+       private Gdk.Pixbuf? load_cache_from_disk (Game game, int size, string dir) {
+               string cache_path;
                try {
-                       cover_cache_path = get_cover_cache_path (game, size);
+                       cache_path = get_cache_path (game, size, dir);
                }
                catch (Error e) {
                        critical (e.message);
@@ -96,20 +131,20 @@ public class Games.CoverLoader : Object {
                }
 
                try {
-                       return new Gdk.Pixbuf.from_file (cover_cache_path);
+                       return new Gdk.Pixbuf.from_file (cache_path);
                }
                catch (Error e) {
                        return null;
                }
        }
 
-       private void save_cover_cache_to_disk (Game game, Gdk.Pixbuf pixbuf, int size) {
-               Application.try_make_dir (Application.get_covers_cache_dir (size));
+       private void save_cache_to_disk (Game game, Gdk.Pixbuf pixbuf, int size, string dir_name) {
+               Application.try_make_dir (Application.get_image_cache_dir (dir_name, size));
                var now = new GLib.DateTime.now_local ();
                var creation_time = now.to_string ();
 
                try {
-                       var cover_cache_path = get_cover_cache_path (game, size);
+                       var cover_cache_path = get_cache_path (game, size, dir_name);
                        pixbuf.save (cover_cache_path, "png",
                                    "tEXt::Software", "GNOME Games",
                                    "tEXt::Creation Time", creation_time.to_string (),
@@ -120,7 +155,7 @@ public class Games.CoverLoader : Object {
                }
        }
 
-       public void fetch_cover (Game game, int size, CoverReadyCallback cb) {
-               request_queue.push ({ game, size, cb });
+       public void fetch_cover (Game game, int cover_size, int icon_size, CoverReadyCallback cb) {
+               request_queue.push ({ game, cover_size, icon_size, cb });
        }
 }
diff --git a/src/ui/application.vala b/src/ui/application.vala
index 38d1459d..5bf626d5 100644
--- a/src/ui/application.vala
+++ b/src/ui/application.vala
@@ -119,10 +119,10 @@ public class Games.Application : Gtk.Application {
                return @"$cache_dir/covers";
        }
 
-       public static string get_covers_cache_dir (int size) {
-               var covers_dir = get_covers_dir ();
+       public static string get_image_cache_dir (string dir_name, int size) {
+               var cache_dir = get_cache_dir ();
 
-               return @"$covers_dir/$size";
+               return @"$cache_dir/$dir_name/$size";
        }
 
        public static void try_make_dir (string path) {
diff --git a/src/ui/game-thumbnail.vala b/src/ui/game-thumbnail.vala
index 8b5ef689..bab5c53e 100644
--- a/src/ui/game-thumbnail.vala
+++ b/src/ui/game-thumbnail.vala
@@ -37,9 +37,9 @@ private class Games.GameThumbnail : Gtk.DrawingArea {
        }
 
        private Gdk.Pixbuf? cover_pixbuf;
-       private bool loading_cover;
+       private Gdk.Pixbuf? icon_pixbuf;
        private bool try_load_cover;
-       private int last_size;
+       private int last_cover_size;
 
        public struct DrawingContext {
                Cairo.Context cr;
@@ -83,10 +83,7 @@ private class Games.GameThumbnail : Gtk.DrawingArea {
 
                var drawn = false;
 
-               drawn = draw_cover (context);
-
-               if (!drawn)
-                       drawn = draw_icon (context);
+               drawn = draw_image (context);
 
                // Draw the default thumbnail if no thumbnail have been drawn
                if (!drawn)
@@ -95,37 +92,32 @@ private class Games.GameThumbnail : Gtk.DrawingArea {
                return true;
        }
 
-       public bool draw_icon (DrawingContext context) {
-               var g_icon = icon.get_icon ();
-               if (g_icon == null)
-                       return false;
-
-               var pixbuf = get_scaled_icon (context, g_icon, ICON_SCALE);
-               if (pixbuf == null)
-                       return false;
+       public bool draw_image (DrawingContext context) {
+               Gdk.Pixbuf cover, icon;
+               get_icon_and_cover (context, out cover, out icon);
 
-               draw_background (context);
-               draw_pixbuf (context, pixbuf);
-               draw_border (context);
+               if (cover != null) {
+                       var border_radius = (int) context.style.get_property 
(Gtk.STYLE_PROPERTY_BORDER_RADIUS, context.state);
+                       border_radius = border_radius.clamp (0, int.max (context.width / 2, context.height / 
2));
 
-               return true;
-       }
+                       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, cover);
+                       draw_border (context);
 
-       public bool draw_cover (DrawingContext context) {
-               var pixbuf = get_scaled_cover (context);
-               if (pixbuf == null)
-                       return false;
+                       return true;
+               }
 
-               var border_radius = (int) context.style.get_property (Gtk.STYLE_PROPERTY_BORDER_RADIUS, 
context.state);
-               border_radius = border_radius.clamp (0, int.max (context.width / 2, context.height / 2));
+               if (icon != null) {
+                       draw_background (context);
+                       draw_pixbuf (context, icon);
+                       draw_border (context);
 
-               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_border (context);
+                       return true;
+               }
 
-               return true;
+               return false;
        }
 
        public void draw_default (DrawingContext context) {
@@ -164,57 +156,47 @@ private class Games.GameThumbnail : Gtk.DrawingArea {
                context.cr.restore ();
        }
 
-       private Gdk.Pixbuf? get_scaled_icon (DrawingContext context, GLib.Icon? icon, double scale) {
-               if (icon == null)
-                       return null;
-
-               var theme = Gtk.IconTheme.get_default ();
-               var lookup_flags = Gtk.IconLookupFlags.FORCE_SIZE | Gtk.IconLookupFlags.FORCE_REGULAR;
-               var size = int.min (context.width, context.height) * scale * scale_factor;
-               var icon_info = theme.lookup_by_gicon (icon, (int) size, lookup_flags);
+       private void get_icon_and_cover (DrawingContext context, out Gdk.Pixbuf cover, out Gdk.Pixbuf icon) {
+               var cover_size = int.min (context.width, context.height) * scale_factor;
+               var icon_size = (int) (cover_size * ICON_SCALE);
 
-               if (icon_info == null)
-                       return null;
-
-               try {
-                       return icon_info.load_icon ();
-               }
-               catch (Error e) {
-                       warning (@"Couldn’t load the icon: $(e.message)\n");
-                       return null;
-               }
-       }
-
-       private Gdk.Pixbuf? get_scaled_cover (DrawingContext context) {
-               var size = int.min (context.width, context.height) * scale_factor;
-
-               if (size != last_size) {
+               if (cover_size != last_cover_size) {
                        cover_pixbuf = null;
+                       icon_pixbuf = null;
                        try_load_cover = true;
                }
 
-               if (!try_load_cover)
-                       return cover_pixbuf;
+               if (!try_load_cover) {
+                       cover = cover_pixbuf;
+                       icon = icon_pixbuf;
+                       return;
+               }
 
                var loader = Application.get_default ().get_cover_loader ();
 
-               last_size = size;
+               last_cover_size = cover_size;
 
                try_load_cover = false;
-               loading_cover = true;
-               loader.fetch_cover (game, size, (s, pixbuf) => {
-                       if (s != last_size) {
-                               cover_pixbuf = null;
+               loader.fetch_cover (game, cover_size, icon_size, (cover_size, cover_pixbuf, icon_size, 
icon_pixbuf) => {
+                       if (cover_size != last_cover_size) {
+                               this.cover_pixbuf = null;
+                               this.icon_pixbuf = null;
+
                                try_load_cover = true;
-                       } else
-                       if (pixbuf != null)
-                               cover_pixbuf = pixbuf;
+                       }
+                       else {
+                               if (cover_pixbuf != null)
+                                       this.cover_pixbuf = cover_pixbuf;
+
+                               if (icon_pixbuf != null)
+                                       this.icon_pixbuf = icon_pixbuf;
+                       }
 
-                       loading_cover = false;
                        queue_draw ();
                });
 
-               return cover_pixbuf;
+               cover = cover_pixbuf;
+               icon = icon_pixbuf;
        }
 
        private void draw_pixbuf (DrawingContext context, Gdk.Pixbuf pixbuf) {


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