diff options
Diffstat (limited to '')
| -rw-r--r-- | native/src/widget/image.rs | 66 | 
1 files changed, 50 insertions, 16 deletions
diff --git a/native/src/widget/image.rs b/native/src/widget/image.rs index b8fb662e..5ddc3642 100644 --- a/native/src/widget/image.rs +++ b/native/src/widget/image.rs @@ -5,7 +5,9 @@ pub use viewer::Viewer;  use crate::image;  use crate::layout;  use crate::renderer; -use crate::{Element, Hasher, Layout, Length, Point, Rectangle, Size, Widget}; +use crate::{ +    ContentFit, Element, Hasher, Layout, Length, Point, Rectangle, Size, Widget, +};  use std::hash::Hash; @@ -26,6 +28,7 @@ pub struct Image<Handle> {      handle: Handle,      width: Length,      height: Length, +    fit: ContentFit,  }  impl<Handle> Image<Handle> { @@ -35,6 +38,7 @@ impl<Handle> Image<Handle> {              handle: handle.into(),              width: Length::Shrink,              height: Length::Shrink, +            fit: ContentFit::Contain,          }      } @@ -49,6 +53,13 @@ impl<Handle> Image<Handle> {          self.height = height;          self      } + +    /// Sets the image fit +    /// +    /// Defaults to [`ContentFit::Contain`] +    pub fn fit(self, fit: ContentFit) -> Self { +        Self { fit, ..self } +    }  }  impl<Message, Renderer, Handle> Widget<Message, Renderer> for Image<Handle> @@ -69,24 +80,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.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( @@ -97,7 +116,22 @@ where          _cursor_position: Point,          _viewport: &Rectangle,      ) { -        renderer.draw(self.handle.clone(), layout.bounds()); +        // 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 adjusted_fit = self.fit.fit(image_size, layout.bounds().size()); + +        renderer.with_layer(layout.bounds(), |renderer| { +            renderer.draw( +                self.handle.clone(), +                Rectangle { +                    width: adjusted_fit.width, +                    height: adjusted_fit.height, +                    ..layout.bounds() +                }, +            ) +        })      }      fn hash_layout(&self, state: &mut Hasher) {  | 
