assets.rs

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