[gnome-music/wip/mschraal/core-thumb-property: 3/18] artcache: Unify DefaultIcon and _make_icon_frame



commit af0ce453773c3758e4fb8f6f631a4727a121b5dc
Author: Marinus Schraal <mschraal gnome org>
Date:   Sun Apr 5 20:15:02 2020 +0200

    artcache: Unify DefaultIcon and _make_icon_frame
    
    These were split up during the initial implementation of ArtistArt to
    speed up implementation. This is a partial cleanup.

 gnomemusic/albumartcache.py          | 99 +-----------------------------------
 gnomemusic/artcache.py               | 87 +++++++++++++++++++++++--------
 gnomemusic/widgets/artistartstack.py |  3 +-
 gnomemusic/widgets/coverstack.py     |  3 +-
 4 files changed, 71 insertions(+), 121 deletions(-)
---
diff --git a/gnomemusic/albumartcache.py b/gnomemusic/albumartcache.py
index 6c388711..c4f18289 100644
--- a/gnomemusic/albumartcache.py
+++ b/gnomemusic/albumartcache.py
@@ -34,6 +34,7 @@ gi.require_version("Soup", "2.4")
 from gi.repository import (Gdk, GdkPixbuf, Gio, GLib, GObject, Gtk, MediaArt,
                            Gst, GstTag, GstPbutils, Soup)
 
+from gnomemusic.artcache import DefaultIcon, _make_icon_frame
 from gnomemusic.musiclogger import MusicLogger
 
 
@@ -58,104 +59,6 @@ def lookup_art_file_from_cache(coresong):
     return thumb_file
 
 
-def _make_icon_frame(icon_surface, art_size=None, scale=1, default_icon=False):
-    border = 3
-    degrees = pi / 180
-    radius = 3
-
-    icon_w = icon_surface.get_width()
-    icon_h = icon_surface.get_height()
-    ratio = icon_h / icon_w
-
-    # Scale down the image according to the biggest axis
-    if ratio > 1:
-        w = int(art_size.width / ratio)
-        h = art_size.height
-    else:
-        w = art_size.width
-        h = int(art_size.height * ratio)
-
-    surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, w * scale, h * scale)
-    surface.set_device_scale(scale, scale)
-    ctx = cairo.Context(surface)
-
-    # draw outline
-    ctx.new_sub_path()
-    ctx.arc(w - radius, radius, radius - 0.5, -90 * degrees, 0 * degrees)
-    ctx.arc(w - radius, h - radius, radius - 0.5, 0 * degrees, 90 * degrees)
-    ctx.arc(radius, h - radius, radius - 0.5, 90 * degrees, 180 * degrees)
-    ctx.arc(radius, radius, radius - 0.5, 180 * degrees, 270 * degrees)
-    ctx.close_path()
-    ctx.set_line_width(0.6)
-    ctx.set_source_rgba(0, 0, 0, 0.7)
-    ctx.stroke_preserve()
-
-    matrix = cairo.Matrix()
-
-    if default_icon:
-        ctx.set_source_rgb(1, 1, 1)
-        ctx.fill()
-        ctx.set_source_rgba(0, 0, 0, 0.3)
-        ctx.mask_surface(icon_surface, w / 3, h / 3)
-        ctx.fill()
-    else:
-        matrix.scale(
-            icon_w / ((w - border * 2) * scale),
-            icon_h / ((h - border * 2) * scale))
-        matrix.translate(-border, -border)
-        ctx.set_source_surface(icon_surface, 0, 0)
-
-        pattern = ctx.get_source()
-        pattern.set_matrix(matrix)
-        ctx.fill()
-
-    ctx.rectangle(border, border, w - border * 2, h - border * 2)
-    ctx.clip()
-
-    return surface
-
-
-class DefaultIcon(GObject.GObject):
-    """Provides the symbolic fallback and loading icons."""
-
-    class Type(Enum):
-        LOADING = 'content-loading-symbolic'
-        MUSIC = 'folder-music-symbolic'
-
-    _cache = {}
-    _default_theme = Gtk.IconTheme.get_default()
-
-    def __init__(self):
-        super().__init__()
-
-    def _make_default_icon(self, icon_type, art_size, scale):
-        icon_info = self._default_theme.lookup_icon_for_scale(
-            icon_type.value, art_size.width / 3, scale, 0)
-        icon = icon_info.load_surface()
-
-        icon_surface = _make_icon_frame(icon, art_size, scale, True)
-
-        return icon_surface
-
-    def get(self, icon_type, art_size, scale=1):
-        """Returns the requested symbolic icon
-
-        Returns a cairo surface of the requested symbolic icon in the
-        given size.
-
-        :param enum icon_type: The DefaultIcon.Type of the icon
-        :param enum art_size: The Art.Size requested
-
-        :return: The symbolic icon
-        :rtype: cairo.Surface
-        """
-        if (icon_type, art_size, scale) not in self._cache.keys():
-            new_icon = self._make_default_icon(icon_type, art_size, scale)
-            self._cache[(icon_type, art_size, scale)] = new_icon
-
-        return self._cache[(icon_type, art_size, scale)]
-
-
 class Art(GObject.GObject):
     """Retrieves art for an album or song
 
diff --git a/gnomemusic/artcache.py b/gnomemusic/artcache.py
index 4dcb5c53..e20dcaa4 100644
--- a/gnomemusic/artcache.py
+++ b/gnomemusic/artcache.py
@@ -30,7 +30,23 @@ from gi.repository import Gdk, GdkPixbuf, Gio, Gtk, GLib, GObject
 from gnomemusic.musiclogger import MusicLogger
 
 
-def _make_icon_frame(icon_surface, art_size=None, scale=1, default_icon=False):
+def _make_icon_frame(
+        icon_surface, art_size=None, scale=1, default_icon=False,
+        round_shape=False):
+    """Create an Art frame, square or round.
+
+    :param cairo.Surface icon_surface: The surface to use
+    :param art_size: The size of the art
+    :param int scale: The scale of the art
+    :param bool default_icon: Indicates of this is a default icon
+    :param bool round_shape: Square or round indicator
+
+    :return: The framed surface
+    :rtype: cairo.Surface
+    """
+    border = 3
+    degrees = pi / 180
+    radius = 3
     icon_w = icon_surface.get_width()
     icon_h = icon_surface.get_height()
     ratio = icon_h / icon_w
@@ -46,15 +62,27 @@ def _make_icon_frame(icon_surface, art_size=None, scale=1, default_icon=False):
     surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, w * scale, h * scale)
     surface.set_device_scale(scale, scale)
     ctx = cairo.Context(surface)
-
     matrix = cairo.Matrix()
 
-    line_width = 0.6
-    ctx.new_sub_path()
-    ctx.arc(w / 2, h / 2, (w / 2) - line_width, 0, 2 * pi)
-    ctx.set_source_rgba(0, 0, 0, 0.7)
-    ctx.set_line_width(line_width)
-    ctx.stroke_preserve()
+    if round_shape:
+        line_width = 0.6
+        ctx.new_sub_path()
+        ctx.arc(w / 2, h / 2, (w / 2) - line_width, 0, 2 * pi)
+        ctx.set_source_rgba(0, 0, 0, 0.7)
+        ctx.set_line_width(line_width)
+        ctx.stroke_preserve()
+    else:
+        # draw outline
+        ctx.new_sub_path()
+        ctx.arc(w - radius, radius, radius - 0.5, -90 * degrees, 0 * degrees)
+        ctx.arc(
+            w - radius, h - radius, radius - 0.5, 0 * degrees, 90 * degrees)
+        ctx.arc(radius, h - radius, radius - 0.5, 90 * degrees, 180 * degrees)
+        ctx.arc(radius, radius, radius - 0.5, 180 * degrees, 270 * degrees)
+        ctx.close_path()
+        ctx.set_line_width(0.6)
+        ctx.set_source_rgba(0, 0, 0, 0.7)
+        ctx.stroke_preserve()
 
     if default_icon:
         ctx.set_source_rgb(1, 1, 1)
@@ -63,14 +91,25 @@ def _make_icon_frame(icon_surface, art_size=None, scale=1, default_icon=False):
         ctx.mask_surface(icon_surface, w / 3, h / 3)
         ctx.fill()
     else:
-        matrix.scale(icon_w / (w * scale), icon_h / (h * scale))
+        if round_shape:
+            matrix.scale(icon_w / (w * scale), icon_h / (h * scale))
+        else:
+            matrix.scale(
+                icon_w / ((w - border * 2) * scale),
+                icon_h / ((h - border * 2) * scale))
+            matrix.translate(-border, -border)
+
         ctx.set_source_surface(icon_surface, 0, 0)
 
         pattern = ctx.get_source()
         pattern.set_matrix(matrix)
         ctx.fill()
 
-    ctx.arc(w / 2, h / 2, w / 2, 0, 2 * pi)
+    if round_shape:
+        ctx.arc(w / 2, h / 2, w / 2, 0, 2 * pi)
+    else:
+        ctx.rectangle(border, border, w - border * 2, h - border * 2)
+
     ctx.clip()
 
     return surface
@@ -80,8 +119,9 @@ class DefaultIcon(GObject.GObject):
     """Provides the symbolic fallback and loading icons."""
 
     class Type(Enum):
-        LOADING = "content-loading-symbolic"
         ARTIST = "avatar-default-symbolic"
+        LOADING = "content-loading-symbolic"
+        MUSIC = "folder-music-symbolic"
 
     _cache = {}
     _default_theme = Gtk.IconTheme.get_default()
@@ -89,32 +129,36 @@ class DefaultIcon(GObject.GObject):
     def __init__(self):
         super().__init__()
 
-    def _make_default_icon(self, icon_type, art_size, scale):
+    def _make_default_icon(self, icon_type, art_size, scale, round_shape):
         icon_info = self._default_theme.lookup_icon_for_scale(
             icon_type.value, art_size.width / 3, scale, 0)
         icon = icon_info.load_surface()
 
-        icon_surface = _make_icon_frame(icon, art_size, scale, True)
+        icon_surface = _make_icon_frame(
+            icon, art_size, scale, True, round_shape=round_shape)
 
         return icon_surface
 
-    def get(self, icon_type, art_size, scale=1):
+    def get(self, icon_type, art_size, scale=1, round_shape=False):
         """Returns the requested symbolic icon
 
         Returns a cairo surface of the requested symbolic icon in the
-        given size.
+        given size and shape.
 
         :param enum icon_type: The DefaultIcon.Type of the icon
         :param enum art_size: The Art.Size requested
+        :param int scale: The scale
+        :param bool round_shape: Indicates square or round icon shape
 
         :return: The symbolic icon
         :rtype: cairo.Surface
         """
         if (icon_type, art_size, scale) not in self._cache.keys():
-            new_icon = self._make_default_icon(icon_type, art_size, scale)
-            self._cache[(icon_type, art_size, scale)] = new_icon
+            new_icon = self._make_default_icon(
+                icon_type, art_size, scale, round_shape)
+            self._cache[(icon_type, art_size, scale, round_shape)] = new_icon
 
-        return self._cache[(icon_type, art_size, scale)]
+        return self._cache[(icon_type, art_size, scale, round_shape)]
 
 
 class ArtCache(GObject.GObject):
@@ -139,9 +183,9 @@ class ArtCache(GObject.GObject):
         self._scale = scale
 
         self._loading_icon = DefaultIcon().get(
-            DefaultIcon.Type.LOADING, self._size, self._scale)
+            DefaultIcon.Type.LOADING, self._size, self._scale, True)
         self._default_icon = DefaultIcon().get(
-            DefaultIcon.Type.ARTIST, self._size, self._scale)
+            DefaultIcon.Type.ARTIST, self._size, self._scale, True)
 
     def query(self, coreartist):
         """Start the cache query
@@ -189,7 +233,8 @@ class ArtCache(GObject.GObject):
 
         surface = Gdk.cairo_surface_create_from_pixbuf(
             pixbuf, self._scale, None)
-        surface = _make_icon_frame(surface, self._size, self._scale)
+        surface = _make_icon_frame(
+            surface, self._size, self._scale, round_shape=True)
 
         self.emit("result", surface)
 
diff --git a/gnomemusic/widgets/artistartstack.py b/gnomemusic/widgets/artistartstack.py
index d33cc9da..1323cf30 100644
--- a/gnomemusic/widgets/artistartstack.py
+++ b/gnomemusic/widgets/artistartstack.py
@@ -89,7 +89,8 @@ class ArtistArtStack(Gtk.Stack):
         self._size = value
 
         icon = self._default_icon.get(
-            DefaultIcon.Type.LOADING, self.props.size, self.props.scale_factor)
+            DefaultIcon.Type.LOADING, self.props.size,
+            self.props.scale_factor, round_shape=True)
         self._loading_cover.props.surface = icon
 
     @GObject.Property(type=CoreArtist, default=None)
diff --git a/gnomemusic/widgets/coverstack.py b/gnomemusic/widgets/coverstack.py
index 1e97e489..661dbc8f 100644
--- a/gnomemusic/widgets/coverstack.py
+++ b/gnomemusic/widgets/coverstack.py
@@ -24,7 +24,8 @@
 
 from gi.repository import GLib, GObject, Gtk
 
-from gnomemusic.albumartcache import Art, DefaultIcon
+from gnomemusic.albumartcache import Art
+from gnomemusic.artcache import DefaultIcon
 
 
 class CoverStack(Gtk.Stack):


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