use crate::{size, DevicePixels, Result, SharedString, Size}; use smallvec::SmallVec; use image::{Delay, Frame}; use std::{ borrow::Cow, fmt, hash::Hash, sync::atomic::{AtomicUsize, Ordering::SeqCst}, }; /// A source of assets for this app to use. pub trait AssetSource: 'static + Send + Sync { /// Load the given asset from the source path. fn load(&self, path: &str) -> Result>>; /// List the assets at the given path. fn list(&self, path: &str) -> Result>; } impl AssetSource for () { fn load(&self, _path: &str) -> Result>> { Ok(None) } fn list(&self, _path: &str) -> Result> { Ok(vec![]) } } /// A unique identifier for the image cache #[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] pub struct ImageId(pub usize); #[derive(PartialEq, Eq, Hash, Clone)] pub(crate) struct RenderImageParams { pub(crate) image_id: ImageId, pub(crate) frame_index: usize, } /// A cached and processed image, in BGRA format pub struct RenderImage { /// The ID associated with this image pub id: ImageId, data: SmallVec<[Frame; 1]>, } impl PartialEq for RenderImage { fn eq(&self, other: &Self) -> bool { self.id == other.id } } impl Eq for RenderImage {} impl RenderImage { /// Create a new image from the given data. pub fn new(data: impl Into>) -> Self { static NEXT_ID: AtomicUsize = AtomicUsize::new(0); Self { id: ImageId(NEXT_ID.fetch_add(1, SeqCst)), data: data.into(), } } /// Convert this image into a byte slice. pub fn as_bytes(&self, frame_index: usize) -> Option<&[u8]> { self.data .get(frame_index) .map(|frame| frame.buffer().as_raw().as_slice()) } /// Get the size of this image, in pixels. pub fn size(&self, frame_index: usize) -> Size { let (width, height) = self.data[frame_index].buffer().dimensions(); size(width.into(), height.into()) } /// Get the delay of this frame from the previous pub fn delay(&self, frame_index: usize) -> Delay { self.data[frame_index].delay() } /// Get the number of frames for this image. pub fn frame_count(&self) -> usize { self.data.len() } } impl fmt::Debug for RenderImage { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("ImageData") .field("id", &self.id) .field("size", &self.size(0)) .finish() } }