diff options
Diffstat (limited to 'native/src/widget/svg.rs')
-rw-r--r-- | native/src/widget/svg.rs | 98 |
1 files changed, 56 insertions, 42 deletions
diff --git a/native/src/widget/svg.rs b/native/src/widget/svg.rs index 063730bb..9cd61918 100644 --- a/native/src/widget/svg.rs +++ b/native/src/widget/svg.rs @@ -1,9 +1,11 @@ //! Display vector graphics in your application. -use crate::{layout, Element, Hasher, Layout, Length, Point, Size, Widget}; +use crate::layout; +use crate::{Element, Hasher, Layout, Length, Point, Rectangle, Size, Widget}; use std::{ - hash::Hash, - path::{Path, PathBuf}, + hash::{Hash, Hasher as _}, + path::PathBuf, + sync::Arc, }; /// A vector graphics image. @@ -12,8 +14,6 @@ use std::{ /// /// [`Svg`] images can have a considerable rendering cost when resized, /// specially when they are complex. -/// -/// [`Svg`]: struct.Svg.html #[derive(Debug, Clone)] pub struct Svg { handle: Handle, @@ -23,9 +23,6 @@ pub struct Svg { impl Svg { /// Creates a new [`Svg`] from the given [`Handle`]. - /// - /// [`Svg`]: struct.Svg.html - /// [`Handle`]: struct.Handle.html pub fn new(handle: impl Into<Handle>) -> Self { Svg { handle: handle.into(), @@ -34,17 +31,19 @@ impl Svg { } } + /// Creates a new [`Svg`] that will display the contents of the file at the + /// provided path. + pub fn from_path(path: impl Into<PathBuf>) -> Self { + Self::new(Handle::from_path(path)) + } + /// Sets the width of the [`Svg`]. - /// - /// [`Svg`]: struct.Svg.html pub fn width(mut self, width: Length) -> Self { self.width = width; self } /// Sets the height of the [`Svg`]. - /// - /// [`Svg`]: struct.Svg.html pub fn height(mut self, height: Length) -> Self { self.height = height; self @@ -94,68 +93,88 @@ where _defaults: &Renderer::Defaults, layout: Layout<'_>, _cursor_position: Point, + _viewport: &Rectangle, ) -> Renderer::Output { renderer.draw(self.handle.clone(), layout) } fn hash_layout(&self, state: &mut Hasher) { + std::any::TypeId::of::<Svg>().hash(state); + + self.handle.hash(state); self.width.hash(state); self.height.hash(state); } } /// An [`Svg`] handle. -/// -/// [`Svg`]: struct.Svg.html #[derive(Debug, Clone)] pub struct Handle { id: u64, - path: PathBuf, + data: Arc<Data>, } 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 _; + pub fn from_path(path: impl Into<PathBuf>) -> Handle { + Self::from_data(Data::Path(path.into())) + } - let path = path.into(); + /// Creates an SVG [`Handle`] from raw bytes containing either an SVG string + /// or gzip compressed data. + /// + /// This is useful if you already have your SVG data in-memory, maybe + /// because you downloaded or generated it procedurally. + pub fn from_memory(bytes: impl Into<Vec<u8>>) -> Handle { + Self::from_data(Data::Bytes(bytes.into())) + } + fn from_data(data: Data) -> Handle { let mut hasher = Hasher::default(); - path.hash(&mut hasher); + data.hash(&mut hasher); Handle { id: hasher.finish(), - path, + data: Arc::new(data), } } /// 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 + /// Returns a reference to the SVG [`Data`]. + pub fn data(&self) -> &Data { + &self.data } } -impl From<String> for Handle { - fn from(path: String) -> Handle { - Handle::from_path(path) +impl Hash for Handle { + fn hash<H: std::hash::Hasher>(&self, state: &mut H) { + self.id.hash(state); } } -impl From<&str> for Handle { - fn from(path: &str) -> Handle { - Handle::from_path(path) +/// The data of an [`Svg`]. +#[derive(Clone, Hash)] +pub enum Data { + /// File data + Path(PathBuf), + + /// In-memory data + /// + /// Can contain an SVG string or a gzip compressed data. + Bytes(Vec<u8>), +} + +impl std::fmt::Debug for Data { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Data::Path(path) => write!(f, "Path({:?})", path), + Data::Bytes(_) => write!(f, "Bytes(...)"), + } } } @@ -164,17 +183,12 @@ impl From<&str> for Handle { /// 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 +/// [renderer]: crate::renderer pub trait Renderer: crate::Renderer { - /// Returns the default dimensions of an [`Svg`] located on the given path. - /// - /// [`Svg`]: struct.Svg.html + /// Returns the default dimensions of an [`Svg`] for the given [`Handle`]. fn dimensions(&self, handle: &Handle) -> (u32, u32); /// Draws an [`Svg`]. - /// - /// [`Svg`]: struct.Svg.html fn draw(&mut self, handle: Handle, layout: Layout<'_>) -> Self::Output; } |