diff options
| author | 2022-02-16 17:59:39 +0700 | |
|---|---|---|
| committer | 2022-02-16 18:19:37 +0700 | |
| commit | 83c0e0f7a862ddcefedfb4ef11a11f9bd5245605 (patch) | |
| tree | 2b26af858450971dc6688adb7e09762628dc4e45 /native/src | |
| parent | c910e239196655f3d5ba146aa3dc8da2b578ef8e (diff) | |
| download | iced-83c0e0f7a862ddcefedfb4ef11a11f9bd5245605.tar.gz iced-83c0e0f7a862ddcefedfb4ef11a11f9bd5245605.tar.bz2 iced-83c0e0f7a862ddcefedfb4ef11a11f9bd5245605.zip  | |
Add `ContentFit` support to `Svg` widget
Diffstat (limited to '')
| -rw-r--r-- | native/src/widget/image.rs | 1 | ||||
| -rw-r--r-- | native/src/widget/svg.rs | 83 | 
2 files changed, 67 insertions, 17 deletions
diff --git a/native/src/widget/image.rs b/native/src/widget/image.rs index a2e7f765..8ccc7856 100644 --- a/native/src/widget/image.rs +++ b/native/src/widget/image.rs @@ -120,7 +120,6 @@ where          _cursor_position: Point,          _viewport: &Rectangle,      ) { -        // The raw w/h of the underlying image          let (width, height) = renderer.dimensions(&self.handle);          let image_size = Size::new(width as f32, height as f32); diff --git a/native/src/widget/svg.rs b/native/src/widget/svg.rs index f212dfcb..9e3639db 100644 --- a/native/src/widget/svg.rs +++ b/native/src/widget/svg.rs @@ -2,7 +2,10 @@  use crate::layout;  use crate::renderer;  use crate::svg::{self, Handle}; -use crate::{Element, Hasher, Layout, Length, Point, Rectangle, Size, Widget}; +use crate::{ +    ContentFit, Element, Hasher, Layout, Length, Point, Rectangle, Size, +    Vector, Widget, +};  use std::hash::Hash;  use std::path::PathBuf; @@ -18,6 +21,7 @@ pub struct Svg {      handle: Handle,      width: Length,      height: Length, +    content_fit: ContentFit,  }  impl Svg { @@ -27,6 +31,7 @@ impl Svg {              handle: handle.into(),              width: Length::Fill,              height: Length::Shrink, +            content_fit: ContentFit::Contain,          }      } @@ -47,6 +52,16 @@ impl Svg {          self.height = height;          self      } + +    /// Sets the [`ContentFit`] of the [`Svg`]. +    /// +    /// Defaults to [`ContentFit::Contain`] +    pub fn content_fit(self, content_fit: ContentFit) -> Self { +        Self { +            content_fit, +            ..self +        } +    }  }  impl<Message, Renderer> Widget<Message, Renderer> for Svg @@ -66,24 +81,32 @@ where          renderer: &Renderer,          limits: &layout::Limits,      ) -> layout::Node { +        // The raw w/h of the underlying image          let (width, height) = renderer.dimensions(&self.handle); +        let image_size = Size::new(width as f32, height as f32); -        let aspect_ratio = width as f32 / height as f32; - -        let mut size = limits +        // The size to be available to the widget prior to `Shrink`ing +        let raw_size = limits              .width(self.width)              .height(self.height) -            .resolve(Size::new(width as f32, height as f32)); - -        let viewport_aspect_ratio = size.width / size.height; - -        if viewport_aspect_ratio > aspect_ratio { -            size.width = width as f32 * size.height / height as f32; -        } else { -            size.height = height as f32 * size.width / width as f32; -        } - -        layout::Node::new(size) +            .resolve(image_size); + +        // The uncropped size of the image when fit to the bounds above +        let full_size = self.content_fit.fit(image_size, raw_size); + +        // Shrink the widget to fit the resized image, if requested +        let final_size = Size { +            width: match self.width { +                Length::Shrink => f32::min(raw_size.width, full_size.width), +                _ => raw_size.width, +            }, +            height: match self.height { +                Length::Shrink => f32::min(raw_size.height, full_size.height), +                _ => raw_size.height, +            }, +        }; + +        layout::Node::new(final_size)      }      fn draw( @@ -94,7 +117,35 @@ where          _cursor_position: Point,          _viewport: &Rectangle,      ) { -        renderer.draw(self.handle.clone(), layout.bounds()) +        let (width, height) = renderer.dimensions(&self.handle); +        let image_size = Size::new(width as f32, height as f32); + +        let adjusted_fit = +            self.content_fit.fit(image_size, layout.bounds().size()); +        let bounds = layout.bounds(); + +        let render = |renderer: &mut Renderer| { +            let offset = Vector::new( +                (bounds.width - adjusted_fit.width).max(0.0) / 2.0, +                (bounds.height - adjusted_fit.height).max(0.0) / 2.0, +            ); + +            let bounds = Rectangle { +                width: adjusted_fit.width, +                height: adjusted_fit.height, +                ..layout.bounds() +            }; + +            renderer.draw(self.handle.clone(), bounds + offset) +        }; + +        if adjusted_fit.width > bounds.width +            || adjusted_fit.height > bounds.height +        { +            renderer.with_layer(layout.bounds(), render); +        } else { +            render(renderer) +        }      }      fn hash_layout(&self, state: &mut Hasher) {  | 
