use super::color::Rgba;
use super::{DrawImpl, PassId};
use crate::cast::Cast;
use crate::geom::{Quad, Rect, Size};
use crate::text::{Effect, TextDisplay};
use std::any::Any;
use std::num::NonZeroU32;
use std::rc::Rc;
use thiserror::Error;
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub struct ImageId(NonZeroU32);
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub struct ImageHandle(ImageId, Rc<()>);
impl ImageHandle {
#[inline]
pub fn id(&self) -> ImageId {
self.0
}
}
impl ImageId {
#[cfg_attr(not(feature = "internal_doc"), doc(hidden))]
#[cfg_attr(doc_cfg, doc(cfg(internal_doc)))]
#[inline]
pub const fn try_new(n: u32) -> Option<Self> {
if let Some(nz) = NonZeroU32::new(n) {
Some(ImageId(nz))
} else {
None
}
}
}
#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub enum ImageFormat {
Rgba8,
}
#[derive(Error, Debug)]
#[error("failed to allocate: size too large or zero-sized")]
pub struct AllocError;
pub struct SharedState<DS: DrawSharedImpl> {
pub draw: DS,
}
#[cfg_attr(not(feature = "internal_doc"), doc(hidden))]
#[cfg_attr(doc_cfg, doc(cfg(internal_doc)))]
impl<DS: DrawSharedImpl> SharedState<DS> {
pub fn new(draw: DS) -> Self {
SharedState { draw }
}
}
pub trait DrawShared {
fn image_alloc(&mut self, size: (u32, u32)) -> Result<ImageHandle, AllocError>;
fn image_upload(&mut self, handle: &ImageHandle, data: &[u8], format: ImageFormat);
fn image_free(&mut self, handle: ImageHandle);
fn image_size(&self, handle: &ImageHandle) -> Option<Size>;
}
impl<DS: DrawSharedImpl> DrawShared for SharedState<DS> {
#[inline]
fn image_alloc(&mut self, size: (u32, u32)) -> Result<ImageHandle, AllocError> {
self.draw
.image_alloc(size)
.map(|id| ImageHandle(id, Rc::new(())))
}
#[inline]
fn image_upload(&mut self, handle: &ImageHandle, data: &[u8], format: ImageFormat) {
self.draw.image_upload(handle.0, data, format);
}
#[inline]
fn image_free(&mut self, handle: ImageHandle) {
if let Ok(()) = Rc::try_unwrap(handle.1) {
self.draw.image_free(handle.0);
}
}
#[inline]
fn image_size(&self, handle: &ImageHandle) -> Option<Size> {
self.draw.image_size(handle.0).map(|size| size.cast())
}
}
#[cfg_attr(not(feature = "internal_doc"), doc(hidden))]
#[cfg_attr(doc_cfg, doc(cfg(internal_doc)))]
pub trait DrawSharedImpl: Any {
type Draw: DrawImpl;
fn image_alloc(&mut self, size: (u32, u32)) -> Result<ImageId, AllocError>;
fn image_upload(&mut self, id: ImageId, data: &[u8], format: ImageFormat);
fn image_free(&mut self, id: ImageId);
fn image_size(&self, id: ImageId) -> Option<(u32, u32)>;
fn draw_image(&self, draw: &mut Self::Draw, pass: PassId, id: ImageId, rect: Quad);
fn draw_text(
&mut self,
draw: &mut Self::Draw,
pass: PassId,
rect: Rect,
text: &TextDisplay,
col: Rgba,
);
fn draw_text_effects(
&mut self,
draw: &mut Self::Draw,
pass: PassId,
rect: Rect,
text: &TextDisplay,
col: Rgba,
effects: &[Effect<()>],
);
fn draw_text_effects_rgba(
&mut self,
draw: &mut Self::Draw,
pass: PassId,
rect: Rect,
text: &TextDisplay,
effects: &[Effect<Rgba>],
);
}