assets.rs

 1use crate::{DevicePixels, Result, SharedString, Size, size};
 2use smallvec::SmallVec;
 3
 4use image::{Delay, Frame};
 5use std::{
 6    borrow::Cow,
 7    fmt,
 8    hash::Hash,
 9    sync::atomic::{AtomicUsize, Ordering::SeqCst},
10};
11
12/// A source of assets for this app to use.
13pub trait AssetSource: 'static + Send + Sync {
14    /// Load the given asset from the source path.
15    fn load(&self, path: &str) -> Result<Option<Cow<'static, [u8]>>>;
16
17    /// List the assets at the given path.
18    fn list(&self, path: &str) -> Result<Vec<SharedString>>;
19}
20
21impl AssetSource for () {
22    fn load(&self, _path: &str) -> Result<Option<Cow<'static, [u8]>>> {
23        Ok(None)
24    }
25
26    fn list(&self, _path: &str) -> Result<Vec<SharedString>> {
27        Ok(vec![])
28    }
29}
30
31/// A unique identifier for the image cache
32#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
33pub struct ImageId(pub usize);
34
35#[derive(PartialEq, Eq, Hash, Clone)]
36pub(crate) struct RenderImageParams {
37    pub(crate) image_id: ImageId,
38    pub(crate) frame_index: usize,
39}
40
41/// A cached and processed image, in BGRA format
42pub struct RenderImage {
43    /// The ID associated with this image
44    pub id: ImageId,
45    data: SmallVec<[Frame; 1]>,
46}
47
48impl PartialEq for RenderImage {
49    fn eq(&self, other: &Self) -> bool {
50        self.id == other.id
51    }
52}
53
54impl Eq for RenderImage {}
55
56impl RenderImage {
57    /// Create a new image from the given data.
58    pub fn new(data: impl Into<SmallVec<[Frame; 1]>>) -> Self {
59        static NEXT_ID: AtomicUsize = AtomicUsize::new(0);
60
61        Self {
62            id: ImageId(NEXT_ID.fetch_add(1, SeqCst)),
63            data: data.into(),
64        }
65    }
66
67    /// Convert this image into a byte slice.
68    pub fn as_bytes(&self, frame_index: usize) -> Option<&[u8]> {
69        self.data
70            .get(frame_index)
71            .map(|frame| frame.buffer().as_raw().as_slice())
72    }
73
74    /// Get the size of this image, in pixels.
75    pub fn size(&self, frame_index: usize) -> Size<DevicePixels> {
76        let (width, height) = self.data[frame_index].buffer().dimensions();
77        size(width.into(), height.into())
78    }
79
80    /// Get the delay of this frame from the previous
81    pub fn delay(&self, frame_index: usize) -> Delay {
82        self.data[frame_index].delay()
83    }
84
85    /// Get the number of frames for this image.
86    pub fn frame_count(&self) -> usize {
87        self.data.len()
88    }
89}
90
91impl fmt::Debug for RenderImage {
92    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
93        f.debug_struct("ImageData")
94            .field("id", &self.id)
95            .field("size", &self.size(0))
96            .finish()
97    }
98}