diff options
author | 2019-12-15 06:19:07 +0100 | |
---|---|---|
committer | 2019-12-15 06:19:07 +0100 | |
commit | 09707f29fcf7fbd71570a43db214921043427c3f (patch) | |
tree | b3e045a64e81f58910c976b0478e6f7f91780ad0 /native/src/widget/svg.rs | |
parent | 27717bc70c3947f553a8b75da9789fe967994a31 (diff) | |
download | iced-09707f29fcf7fbd71570a43db214921043427c3f.tar.gz iced-09707f29fcf7fbd71570a43db214921043427c3f.tar.bz2 iced-09707f29fcf7fbd71570a43db214921043427c3f.zip |
Rerasterize SVGs when resized and refactor a bit
Diffstat (limited to 'native/src/widget/svg.rs')
-rw-r--r-- | native/src/widget/svg.rs | 101 |
1 files changed, 89 insertions, 12 deletions
diff --git a/native/src/widget/svg.rs b/native/src/widget/svg.rs index 097c1d86..42f2ebdf 100644 --- a/native/src/widget/svg.rs +++ b/native/src/widget/svg.rs @@ -1,28 +1,27 @@ //! Display an icon. -use crate::{ - image, layout, Element, Hasher, Layout, Length, Point, Size, Widget, -}; +use crate::{layout, Element, Hasher, Layout, Length, Point, Size, Widget}; use std::{ hash::Hash, - path::PathBuf, + path::{Path, PathBuf}, }; /// A simple icon_loader widget. #[derive(Debug, Clone)] pub struct Svg { - handle: image::Handle, + handle: Handle, width: Length, height: Length, } impl Svg { - /// Create a new [`Svg`] from the file at `path`. + /// Creates a new [`Svg`] from the given [`Handle`]. /// /// [`Svg`]: struct.Svg.html - pub fn new(path: impl Into<PathBuf>) -> Self { + /// [`Handle`]: struct.Handle.html + pub fn new(handle: impl Into<Handle>) -> Self { Svg { - handle: image::Handle::from_path(path), + handle: handle.into(), width: Length::Fill, height: Length::Fill, } @@ -47,7 +46,7 @@ impl Svg { impl<Message, Renderer> Widget<Message, Renderer> for Svg where - Renderer: image::Renderer, + Renderer: self::Renderer, { fn width(&self) -> Length { self.width @@ -57,7 +56,11 @@ where self.height } - fn layout(&self, renderer: &Renderer, limits: &layout::Limits) -> layout::Node { + fn layout( + &self, + renderer: &Renderer, + limits: &layout::Limits, + ) -> layout::Node { let (width, height) = renderer.dimensions(&self.handle); let aspect_ratio = width as f32 / height as f32; @@ -65,7 +68,7 @@ where let mut size = limits .width(self.width) .height(self.height) - .max(); + .resolve(Size::new(width as f32, height as f32)); let viewport_aspect_ratio = size.width / size.height; @@ -93,9 +96,83 @@ where } } +/// An [`Svg`] handle. +/// +/// [`Svg`]: struct.Svg.html +#[derive(Debug, Clone)] +pub struct Handle { + id: u64, + path: PathBuf, +} + +impl Handle { + /// Creates an SVG [`Handle`] pointing to the vector image of the given + /// path. + /// + /// [`Handle`]: struct.Handle.html + pub fn from_path<T: Into<PathBuf>>(path: T) -> Handle { + use std::hash::Hasher as _; + + let path = path.into(); + + let mut hasher = Hasher::default(); + path.hash(&mut hasher); + + Handle { + id: hasher.finish(), + path, + } + } + + /// Returns the unique identifier of the [`Handle`]. + /// + /// [`Handle`]: struct.Handle.html + pub fn id(&self) -> u64 { + self.id + } + + /// Returns a reference to the path of the [`Handle`]. + /// + /// [`Handle`]: enum.Handle.html + pub fn path(&self) -> &Path { + &self.path + } +} + +impl From<String> for Handle { + fn from(path: String) -> Handle { + Handle::from_path(path) + } +} + +impl From<&str> for Handle { + fn from(path: &str) -> Handle { + Handle::from_path(path) + } +} + +/// The renderer of an [`Svg`]. +/// +/// Your [renderer] will need to implement this trait before being able to use +/// an [`Svg`] in your user interface. +/// +/// [`Svg`]: struct.Svg.html +/// [renderer]: ../../renderer/index.html +pub trait Renderer: crate::Renderer { + /// Returns the default dimensions of an [`Svg`] located on the given path. + /// + /// [`Svg`]: struct.Svg.html + fn dimensions(&self, handle: &Handle) -> (u32, u32); + + /// Draws an [`Svg`]. + /// + /// [`Svg`]: struct.Svg.html + fn draw(&mut self, handle: Handle, layout: Layout<'_>) -> Self::Output; +} + impl<'a, Message, Renderer> From<Svg> for Element<'a, Message, Renderer> where - Renderer: image::Renderer, + Renderer: self::Renderer, { fn from(icon: Svg) -> Element<'a, Message, Renderer> { Element::new(icon) |