diff options
| author | Micha White <botahamec@outlook.com> | 2022-10-25 11:13:37 -0400 |
|---|---|---|
| committer | Micha White <botahamec@outlook.com> | 2022-10-25 11:13:37 -0400 |
| commit | 323c6ca03bc1d560b02114445764dab5e753049e (patch) | |
| tree | 68b60475d670dfcab27ec5eab0de61c32f8b81ca /alligator_resources/src/texture.rs | |
| parent | 578fc0aa670067991135921ab9a03d223036a598 (diff) | |
Started the alligator_resources project
Diffstat (limited to 'alligator_resources/src/texture.rs')
| -rw-r--r-- | alligator_resources/src/texture.rs | 92 |
1 files changed, 92 insertions, 0 deletions
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) + } +} |
