1use crate::{size, DevicePixels, Result, SharedString, Size};
2use anyhow::anyhow;
3use image::{Bgra, ImageBuffer};
4use std::{
5 borrow::Cow,
6 fmt,
7 sync::atomic::{AtomicUsize, Ordering::SeqCst},
8};
9
10pub trait AssetSource: 'static + Send + Sync {
11 fn load(&self, path: &SharedString) -> Result<Cow<[u8]>>;
12 fn list(&self, path: &SharedString) -> Result<Vec<SharedString>>;
13}
14
15impl AssetSource for () {
16 fn load(&self, path: &SharedString) -> Result<Cow<[u8]>> {
17 Err(anyhow!(
18 "get called on empty asset provider with \"{}\"",
19 path
20 ))
21 }
22
23 fn list(&self, _path: &SharedString) -> Result<Vec<SharedString>> {
24 Ok(vec![])
25 }
26}
27
28pub struct ImageData {
29 pub id: usize,
30 data: ImageBuffer<Bgra<u8>, Vec<u8>>,
31}
32
33impl ImageData {
34 pub fn from_raw(size: Size<DevicePixels>, bytes: Vec<u8>) -> Self {
35 static NEXT_ID: AtomicUsize = AtomicUsize::new(0);
36
37 Self {
38 id: NEXT_ID.fetch_add(1, SeqCst),
39 data: ImageBuffer::from_raw(size.width.into(), size.height.into(), bytes).unwrap(),
40 }
41 }
42
43 pub fn as_bytes(&self) -> &[u8] {
44 &self.data
45 }
46
47 pub fn into_bytes(self) -> Vec<u8> {
48 self.data.into_raw()
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}