[gnome-games/wip/exalm/hidpi: 5/7] savestate-listbox-row: Draw thumbnails manually
- From: Alexander Mikhaylenko <alexm src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-games/wip/exalm/hidpi: 5/7] savestate-listbox-row: Draw thumbnails manually
- Date: Fri, 16 Aug 2019 21:10:05 +0000 (UTC)
commit aecb6ad5681d4e95e21339d077ef264da32d8b7e
Author: Alexander Mikhaylenko <exalm7659 gmail com>
Date: Sat Aug 17 00:11:10 2019 +0500
savestate-listbox-row: Draw thumbnails manually
This allows to handle border-radius nicely and will be used in the next
commit to draw larger images on hidpi.
data/ui/savestate-listbox-row.ui | 3 +-
src/ui/savestate-listbox-row.vala | 69 +++++++++++++++++++++++++++++++++++----
2 files changed, 65 insertions(+), 7 deletions(-)
---
diff --git a/data/ui/savestate-listbox-row.ui b/data/ui/savestate-listbox-row.ui
index 306dc617..77cf7d30 100644
--- a/data/ui/savestate-listbox-row.ui
+++ b/data/ui/savestate-listbox-row.ui
@@ -15,12 +15,13 @@
<property name="visible">true</property>
<property name="margin">2</property>
<child>
- <object class="GtkImage" id="image">
+ <object class="GtkDrawingArea" id="image">
<property name="visible">true</property>
<property name="valign">start</property>
<property name="width-request">66</property>
<property name="height-request">66</property>
<property name="margin">6</property>
+ <signal name="draw" handler="on_draw_image"/>
<style>
<class name="savestate-thumbnail"/>
</style>
diff --git a/src/ui/savestate-listbox-row.vala b/src/ui/savestate-listbox-row.vala
index ac65be9f..16fc057c 100644
--- a/src/ui/savestate-listbox-row.vala
+++ b/src/ui/savestate-listbox-row.vala
@@ -5,7 +5,7 @@ private class Games.SavestateListBoxRow : Gtk.ListBoxRow {
public const int THUMBNAIL_SIZE = 64;
[GtkChild]
- private Gtk.Image image;
+ private Gtk.DrawingArea image;
[GtkChild]
private Gtk.Label name_label;
[GtkChild]
@@ -59,11 +59,10 @@ private class Games.SavestateListBoxRow : Gtk.ListBoxRow {
}
try {
- var thumbnail = new Gdk.Pixbuf.from_file_at_scale (screenshot_path,
- thumbnail_width,
- thumbnail_height,
- false);
- image.set_from_pixbuf (thumbnail);
+ pixbuf = new Gdk.Pixbuf.from_file_at_scale (screenshot_path,
+ thumbnail_width,
+ thumbnail_height,
+ false);
}
catch (Error e) {
warning ("Failed to load savestate thumbnail: %s", e.message);
@@ -71,6 +70,8 @@ private class Games.SavestateListBoxRow : Gtk.ListBoxRow {
}
}
+ private Gdk.Pixbuf pixbuf;
+
public SavestateListBoxRow (Savestate savestate) {
Object (savestate: savestate);
}
@@ -91,5 +92,61 @@ private class Games.SavestateListBoxRow : Gtk.ListBoxRow {
});
revealer.reveal_child = false;
}
+
+ [GtkCallback]
+ private bool on_draw_image (Cairo.Context cr) {
+ var width = image.get_allocated_width ();
+ var height = image.get_allocated_height ();
+
+ var style = image.get_style_context ();
+ style.render_background (cr, 0.0, 0.0, width, height);
+ style.render_frame (cr, 0.0, 0.0, width, height);
+
+ var mask = get_mask ();
+
+ var surface = Gdk.cairo_surface_create_from_pixbuf (pixbuf, 1, image.get_window ());
+ var x_offset = (width - pixbuf.width) / 2;
+ var y_offset = (height - pixbuf.height) / 2;
+
+ cr.set_source_surface (surface, x_offset, y_offset);
+ cr.mask_surface (mask, 0, 0);
+
+ return Gdk.EVENT_PROPAGATE;
+ }
+
+ // TODO: Share this with GameThumbnail
+ private Cairo.Surface get_mask () {
+ var width = image.get_allocated_width ();
+ var height = image.get_allocated_height ();
+
+ var mask = new Cairo.ImageSurface (Cairo.Format.A8, width, height);
+
+ var style = image.get_style_context ();
+ var flags = image.get_state_flags ();
+ var border_radius = (int) style.get_property (Gtk.STYLE_PROPERTY_BORDER_RADIUS, flags);
+ border_radius = border_radius.clamp (0, int.max (width / 2, height / 2));
+
+ var cr = new Cairo.Context (mask);
+ cr.set_source_rgb (0, 0, 0);
+ rounded_rectangle (cr, 0.5, 0.5, width - 1, height - 1, border_radius);
+ cr.fill ();
+
+ return mask;
+ }
+
+ // TODO: Share this with GameThumbnail
+ 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 ();
+ }
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]