1use crate::{size, DevicePixels, Result, SharedString, Size};
2use anyhow::anyhow;
3use image::{Bgra, ImageBuffer};
4use std::{
5 borrow::Cow,
6 fmt,
7 hash::Hash,
8 sync::atomic::{AtomicUsize, Ordering::SeqCst},
9};
10
11pub trait AssetSource: 'static + Send + Sync {
12 fn load(&self, path: &str) -> Result<Cow<[u8]>>;
13 fn list(&self, path: &str) -> Result<Vec<SharedString>>;
14}
15
16impl AssetSource for () {
17 fn load(&self, path: &str) -> Result<Cow<[u8]>> {
18 Err(anyhow!(
19 "get called on empty asset provider with \"{}\"",
20 path
21 ))
22 }
23
24 fn list(&self, _path: &str) -> Result<Vec<SharedString>> {
25 Ok(vec![])
26 }
27}
28
29#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
30pub struct ImageId(usize);
31
32pub struct ImageData {
33 pub id: ImageId,
34 data: ImageBuffer<Bgra<u8>, Vec<u8>>,
35}
36
37impl ImageData {
38 pub fn new(data: ImageBuffer<Bgra<u8>, Vec<u8>>) -> Self {
39 static NEXT_ID: AtomicUsize = AtomicUsize::new(0);
40
41 Self {
42 id: ImageId(NEXT_ID.fetch_add(1, SeqCst)),
43 data,
44 }
45 }
46
47 pub fn as_bytes(&self) -> &[u8] {
48 &self.data
49 }
50
51 pub fn size(&self) -> Size<DevicePixels> {
52 let (width, height) = self.data.dimensions();
53 size(width.into(), height.into())
54 }
55}
56
57impl fmt::Debug for ImageData {
58 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
59 f.debug_struct("ImageData")
60 .field("id", &self.id)
61 .field("size", &self.data.dimensions())
62 .finish()
63 }
64}