aboutsummaryrefslogtreecommitdiffstats
path: root/community/gpodder/0002-gtkui-properly-scale-cover-pill-on-hires-displays.patch
blob: 3ac3ba67c22ee6f534d8199d52be9a25574c90d1 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
Backport from master:
https://github.com/gpodder/gpodder/pull/1106

From 2f542aa9c7bec7641343253a70d27283bf2222bf Mon Sep 17 00:00:00 2001
From: Oliver Smith <ollieparanoid@postmarketos.org>
Date: Sat, 17 Jul 2021 13:12:37 +0200
Subject: [PATCH 2/2] gtkui: properly scale cover/pill on hires displays

Fix the cover images and "pill" looking blurry on high resolution
displays. For example, when the adaptive version of gPodder is used with
Phosh on the PinePhone.

Get the scale parameter from the gtkTreeView object and pass it down to
the cover thumbnail size and to draw_text_pill. If the scaling is not 1,
then use the new draw_iconcell_scale() function to draw the pixbuf with
high resolution.
---
 src/gpodder/gtkui/draw.py  | 45 +++++++++++++++++++++++++++++++++-----
 src/gpodder/gtkui/main.py  |  9 ++++++--
 src/gpodder/gtkui/model.py | 11 +++++++---
 3 files changed, 55 insertions(+), 10 deletions(-)

diff --git a/src/gpodder/gtkui/draw.py b/src/gpodder/gtkui/draw.py
index 5beb97a4..ccedba36 100644
--- a/src/gpodder/gtkui/draw.py
+++ b/src/gpodder/gtkui/draw.py
@@ -169,7 +169,8 @@ def draw_cake(percentage, text=None, emblem=None, size=None):
     return surface
 
 
-def draw_text_pill(left_text, right_text, x=0, y=0, border=2, radius=14, widget=None):
+def draw_text_pill(left_text, right_text, x=0, y=0, border=2, radius=14,
+                   widget=None, scale=1):
 
     # Padding (in px) at the right edge of the image (for Ubuntu; bug 1533)
     padding_right = 7
@@ -200,10 +201,13 @@ def draw_text_pill(left_text, right_text, x=0, y=0, border=2, radius=14, widget=
     left_side_width = width_left + x_border * 2
     right_side_width = width_right + x_border * 2
 
-    image_height = int(y + text_height + border * 2)
-    image_width = int(x + left_side_width + right_side_width + padding_right)
+    image_height = int(scale * (y + text_height + border * 2))
+    image_width = int(scale * (x + left_side_width + right_side_width
+                               + padding_right))
 
     surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, image_width, image_height)
+    surface.set_device_scale(scale, scale)
+
     ctx = cairo.Context(surface)
 
     # Clip so as to not draw on the right padding (for Ubuntu; bug 1533)
@@ -288,8 +292,9 @@ def draw_cake_pixbuf(percentage, text=None, emblem=None, size=None):
     return cairo_surface_to_pixbuf(draw_cake(percentage, text, emblem, size=size))
 
 
-def draw_pill_pixbuf(left_text, right_text, widget=None):
-    return cairo_surface_to_pixbuf(draw_text_pill(left_text, right_text, widget=widget))
+def draw_pill_pixbuf(left_text, right_text, widget=None, scale=1):
+    return cairo_surface_to_pixbuf(draw_text_pill(left_text, right_text,
+                                                  widget=widget, scale=scale))
 
 
 def cake_size_from_widget(widget=None):
@@ -479,3 +484,33 @@ def investigate_widget_colors(type_classes_and_widgets):
 
         f.write("</dl></td></tr>\n")
         f.write("</table></html>\n")
+
+
+def draw_iconcell_scale(column, cell, model, iter, scale):
+    """
+    Draw cell's pixbuf to a surface with proper scaling for high resolution
+    displays. To be used as gtk.TreeViewColumn.set_cell_data_func.
+
+    :param column: gtk.TreeViewColumn (ignored)
+    :param cell: gtk.CellRenderer
+    :param model: gtk.TreeModel (ignored)
+    :param iter: gtk.TreeIter (ignored)
+    :param scale: factor of the target display (e.g. 1 or 2)
+    """
+    pixbuf = cell.props.pixbuf
+    if not pixbuf:
+        return
+
+    width = pixbuf.get_width()
+    height = pixbuf.get_height()
+    scale_inv = 1 / scale
+
+    surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height)
+    surface.set_device_scale(scale, scale)
+
+    cr = cairo.Context(surface)
+    cr.scale(scale_inv, scale_inv)
+    Gdk.cairo_set_source_pixbuf(cr, cell.props.pixbuf, 0, 0)
+    cr.paint()
+
+    cell.props.surface = surface
diff --git a/src/gpodder/gtkui/main.py b/src/gpodder/gtkui/main.py
index 62cb49a1..dc22efa9 100644
--- a/src/gpodder/gtkui/main.py
+++ b/src/gpodder/gtkui/main.py
@@ -48,7 +48,7 @@ from .desktop.welcome import gPodderWelcome
 from .desktopfile import UserAppsReader
 from .download import DownloadStatusModel
 from .draw import (cake_size_from_widget, draw_cake_pixbuf,
-                   draw_text_box_centered)
+                   draw_iconcell_scale, draw_text_box_centered)
 from .interface.addpodcast import gPodderAddPodcast
 from .interface.common import BuilderWidget, TreeViewHelper
 from .interface.progress import ProgressIndicator
@@ -677,7 +677,8 @@ class gPodder(BuilderWidget, dbus.service.Object):
 
     def init_podcast_list_treeview(self):
         size = cake_size_from_widget(self.treeChannels) * 2
-        self.podcast_list_model.set_max_image_size(size)
+        scale = self.treeChannels.get_scale_factor()
+        self.podcast_list_model.set_max_image_size(size, scale)
         # Set up podcast channel tree view widget
         column = Gtk.TreeViewColumn('')
         iconcell = Gtk.CellRendererPixbuf()
@@ -685,6 +686,8 @@ class gPodder(BuilderWidget, dbus.service.Object):
         column.pack_start(iconcell, False)
         column.add_attribute(iconcell, 'pixbuf', PodcastListModel.C_COVER)
         column.add_attribute(iconcell, 'visible', PodcastListModel.C_COVER_VISIBLE)
+        if scale != 1:
+            column.set_cell_data_func(iconcell, draw_iconcell_scale, scale)
 
         namecell = Gtk.CellRendererText()
         namecell.set_property('ellipsize', Pango.EllipsizeMode.END)
@@ -696,6 +699,8 @@ class gPodder(BuilderWidget, dbus.service.Object):
         column.pack_start(iconcell, False)
         column.add_attribute(iconcell, 'pixbuf', PodcastListModel.C_PILL)
         column.add_attribute(iconcell, 'visible', PodcastListModel.C_PILL_VISIBLE)
+        if scale != 1:
+            column.set_cell_data_func(iconcell, draw_iconcell_scale, scale)
 
         self.treeChannels.append_column(column)
 
diff --git a/src/gpodder/gtkui/model.py b/src/gpodder/gtkui/model.py
index 40eedf6c..186d683c 100644
--- a/src/gpodder/gtkui/model.py
+++ b/src/gpodder/gtkui/model.py
@@ -585,6 +585,7 @@ class PodcastListModel(Gtk.ListStore):
 
         self._cover_cache = {}
         self._max_image_side = 40
+        self._scale = 1
         self._cover_downloader = cover_downloader
 
         self.ICON_DISABLED = 'media-playback-pause'
@@ -653,8 +654,9 @@ class PodcastListModel(Gtk.ListStore):
     def get_search_term(self):
         return self._search_term
 
-    def set_max_image_size(self, size):
-        self._max_image_side = size
+    def set_max_image_size(self, size, scale):
+        self._max_image_side = size * scale
+        self._scale = scale
         self._cover_cache = {}
 
     def _resize_pixbuf_keep_ratio(self, url, pixbuf):
@@ -773,7 +775,10 @@ class PodcastListModel(Gtk.ListStore):
 
     def _get_pill_image(self, channel, count_downloaded, count_unplayed):
         if count_unplayed > 0 or count_downloaded > 0:
-            return draw.draw_pill_pixbuf('{:n}'.format(count_unplayed), '{:n}'.format(count_downloaded), widget=self.widget)
+            return draw.draw_pill_pixbuf('{:n}'.format(count_unplayed),
+                                         '{:n}'.format(count_downloaded),
+                                         widget=self.widget,
+                                         scale=self._scale)
         else:
             return None
 
-- 
2.20.1