diff options
Diffstat (limited to 'alligator_resources')
| -rw-r--r-- | alligator_resources/Cargo.toml | 11 | ||||
| -rw-r--r-- | alligator_resources/src/lib.rs | 7 | ||||
| -rw-r--r-- | alligator_resources/src/texture.rs | 92 |
3 files changed, 110 insertions, 0 deletions
diff --git a/alligator_resources/Cargo.toml b/alligator_resources/Cargo.toml new file mode 100644 index 0000000..7d09857 --- /dev/null +++ b/alligator_resources/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "alligator_resources" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +image = "0.24" +thiserror = "1" +exun = "0.1" diff --git a/alligator_resources/src/lib.rs b/alligator_resources/src/lib.rs new file mode 100644 index 0000000..5ea8ad1 --- /dev/null +++ b/alligator_resources/src/lib.rs @@ -0,0 +1,7 @@ +#![warn(clippy::nursery)] +#![warn(clippy::pedantic)] +#![allow(clippy::module_name_repetitions)] + +pub mod texture; + +struct ResourceManager {} diff --git a/alligator_resources/src/texture.rs b/alligator_resources/src/texture.rs new file mode 100644 index 0000000..ba0ff47 --- /dev/null +++ b/alligator_resources/src/texture.rs @@ -0,0 +1,92 @@ +use std::collections::HashMap; +use std::sync::atomic::{AtomicUsize, Ordering}; + +use exun::{Expect, Expected, Unexpected}; +use thiserror::Error; + +static NEXT_TEXTURE_ID: AtomicUsize = AtomicUsize::new(0); + +type Rgba16Texture = image::ImageBuffer<image::Rgba<u16>, Box<[u16]>>; + +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] +pub struct TextureId(usize); + +impl TextureId { + fn new() -> Self { + Self(NEXT_TEXTURE_ID.fetch_add(1, Ordering::Relaxed)) + } +} + +/// These are the formats supported by the renderer. +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] +#[non_exhaustive] +pub enum ImageFormat { + Bmp, + Ico, + Farbfeld, +} + +impl From<ImageFormat> for image::ImageFormat { + fn from(format: ImageFormat) -> Self { + match format { + ImageFormat::Bmp => Self::Bmp, + ImageFormat::Ico => Self::Ico, + ImageFormat::Farbfeld => Self::Farbfeld, + } + } +} + +#[derive(Debug, Error)] +#[error("{}", .0)] +pub struct DecodingError(#[from] image::error::DecodingError); + +type LoadError = Expect<DecodingError>; + +pub struct TextureManager { + textures: HashMap<TextureId, Rgba16Texture>, +} + +#[allow(clippy::missing_const_for_fn)] +fn convert_image_decoding(e: image::ImageError) -> Expect<DecodingError> { + if let image::ImageError::Decoding(de) = e { + Expected(de.into()) + } else { + Unexpected(e.into()) + } +} + +impl TextureManager { + #[must_use] + pub fn new() -> Self { + Self { + textures: HashMap::new(), + } + } + + /// Loads a texture from memory in the given format. + /// + /// # Errors + /// + /// This returns `Expected(DecodingError)` if the given buffer was invalid + /// for the given format. + #[allow(clippy::missing_panics_doc)] + pub fn load_from_memory( + &mut self, + buf: &[u8], + format: ImageFormat, + ) -> Result<TextureId, LoadError> { + let id = TextureId::new(); + let texture = image::load_from_memory_with_format(buf, format.into()) + .map_err(convert_image_decoding)?; + + let texture = texture.into_rgb16(); + + let width = texture.width(); + let height = texture.height(); + let buf = texture.into_raw().into_boxed_slice(); + let texture = image::ImageBuffer::from_raw(width, height, buf).unwrap(); + self.textures.insert(id, texture); + + Ok(id) + } +} |
