[fractal] widgets/image.rs: Round images in chat view



commit 09e6fc573614e1d90319681f2506fbb3160f16b7
Author: Christopher Davis <brainblasted disroot org>
Date:   Fri Oct 2 15:44:01 2020 -0700

    widgets/image.rs: Round images in chat view
    
    Adds a bit of polish by rounding images in our chat view.
    Applications like Telegram and element do this, and it
    matches well with the new rounder styling for Adwaita.

 fractal-gtk/res/app.css          |  4 +++
 fractal-gtk/src/util/mod.rs      |  8 +++++
 fractal-gtk/src/widgets/image.rs | 64 +++++++++++++++++++++++++++++-----------
 3 files changed, 59 insertions(+), 17 deletions(-)
---
diff --git a/fractal-gtk/res/app.css b/fractal-gtk/res/app.css
index 1e60f24a..f101e12b 100644
--- a/fractal-gtk/res/app.css
+++ b/fractal-gtk/res/app.css
@@ -315,6 +315,10 @@ stack.titlebar:not(headerbar) > box > separator {
   animation: spin 1s linear infinite;
 }
 
+.image-widget {
+  border-radius: 6px;
+}
+
 .spinner-background {
   background: alpha(@theme_fg_color, 0.8);
   margin: 25px;
diff --git a/fractal-gtk/src/util/mod.rs b/fractal-gtk/src/util/mod.rs
index a621bd09..05dfdf57 100644
--- a/fractal-gtk/src/util/mod.rs
+++ b/fractal-gtk/src/util/mod.rs
@@ -6,6 +6,7 @@ use anyhow::Error as AnyhowError;
 use gdk::prelude::*;
 use gdk_pixbuf::Pixbuf;
 use gio::{Settings, SettingsExt, SettingsSchemaSource};
+use gtk::StyleContextExt;
 use html2pango::{html_escape, markup_links};
 use log::error;
 use std::fs::create_dir_all;
@@ -64,6 +65,13 @@ pub fn set_markdown_schema(md: bool) {
     }
 }
 
+pub fn get_border_radius(ctx: &gtk::StyleContext) -> i32 {
+    let state = ctx.get_state();
+    gtk::StyleContextExt::get_property(ctx, "border-radius", state)
+        .get_some()
+        .unwrap_or(0)
+}
+
 macro_rules! unwrap_or_unit_return {
     ($x:expr) => {
         match $x {
diff --git a/fractal-gtk/src/widgets/image.rs b/fractal-gtk/src/widgets/image.rs
index 35252573..91b311e2 100644
--- a/fractal-gtk/src/widgets/image.rs
+++ b/fractal-gtk/src/widgets/image.rs
@@ -1,4 +1,5 @@
 use crate::backend::{media, ThreadPool};
+use crate::util::get_border_radius;
 use either::Either;
 use fractal_api::url::Url;
 use gdk::prelude::GdkContextExt;
@@ -29,7 +30,6 @@ pub struct Image {
     pub zoom_level: Arc<Mutex<Option<f64>>>,
     pub shrink_to_fit: bool,
     pub thumb: bool,
-    pub circle: bool,
     pub fixed_size: bool,
     pub centered: bool,
 }
@@ -42,7 +42,7 @@ impl Image {
     ///
     /// ```
     /// let img = Image::new("mxc://matrix.org/HASDH")
-    ///           .circle(true)
+    ///           .rounded(true)
     ///           .fixed(true)
     ///           .size(Some((50, 50)))
     ///           .build();
@@ -73,7 +73,6 @@ impl Image {
             scaled: Arc::new(Mutex::new(None)),
             zoom_level: Arc::new(Mutex::new(None)),
             thumb: false,
-            circle: false,
             fixed_size: false,
             centered: false,
             shrink_to_fit: false,
@@ -109,6 +108,7 @@ impl Image {
 
     pub fn draw(&self) {
         let da = &self.widget;
+        let ctx = da.get_style_context();
 
         match self.max_size {
             Some(size) => {
@@ -141,7 +141,6 @@ impl Image {
         let pix = self.pixbuf.clone();
         let scaled = self.scaled.clone();
         let zoom_level = self.zoom_level.clone();
-        let is_circle = self.circle;
         let fixed_size = self.fixed_size;
         let centered = self.centered;
         let shrink_to_fit = self.shrink_to_fit;
@@ -159,6 +158,16 @@ impl Image {
                 rh = i32::min(size.1, widget_h);
             }
 
+            let arc_1 = 0.0;
+            let arc_2 = std::f64::consts::PI * 0.5;
+            let arc_3 = std::f64::consts::PI;
+            let arc_4 = std::f64::consts::PI * 1.5;
+
+            let border_radius = get_border_radius(&ctx) as f64;
+
+            let widget_x = 0.0;
+            let widget_y = 0.0;
+
             let context = da.get_style_context();
             gtk::render_background(&context, g, 0.0, 0.0, width, height);
 
@@ -173,6 +182,40 @@ impl Image {
                     adjust_to(pb.get_width(), pb.get_height(), rw, rh)
                 };
 
+                if border_radius > 0.0 {
+                    g.new_sub_path();
+                    g.arc(
+                        widget_x + pw as f64 - border_radius,
+                        widget_y + border_radius,
+                        border_radius,
+                        arc_4,
+                        arc_1,
+                    );
+                    g.arc(
+                        widget_x + pw as f64 - border_radius,
+                        widget_y + ph as f64 - border_radius,
+                        border_radius,
+                        arc_1,
+                        arc_2,
+                    );
+                    g.arc(
+                        widget_x + border_radius,
+                        widget_y + ph as f64 - border_radius,
+                        border_radius,
+                        arc_2,
+                        arc_3,
+                    );
+                    g.arc(
+                        widget_x + border_radius,
+                        widget_y + border_radius,
+                        border_radius,
+                        arc_3,
+                        arc_4,
+                    );
+                    g.close_path();
+                    g.clip();
+                }
+
                 if let Ok(zoom_level_guard) = zoom_level.lock() {
                     if let Some(zl) = *zoom_level_guard {
                         pw = (pb.get_width() as f64 * zl) as i32;
@@ -199,19 +242,6 @@ impl Image {
                 }
 
                 if let Some(sc) = scaled_pix {
-                    if is_circle {
-                        use std::f64::consts::PI;
-
-                        g.arc(
-                            pw as f64 / 2.0,
-                            ph as f64 / 2.0,
-                            pw.min(ph) as f64 / 2.0,
-                            0.0,
-                            2.0 * PI,
-                        );
-                        g.clip();
-                    }
-
                     let x = if centered {
                         ((width / 2.0) - (pw as f64 / 2.0)).round()
                     } else {


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