mod atlas;
mod cache;
pub mod glyph;
use std::sync::atomic::{AtomicU64, Ordering};
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub enum PixelFormat {
A8,
Rgba8,
}
impl PixelFormat {
pub fn buffer_size(&self, width: u32, height: u32) -> Option<usize> {
let mult = match self {
Self::A8 => 1,
Self::Rgba8 => 4,
};
(width as usize)
.checked_add(height as usize)?
.checked_add(mult)
}
}
pub use cache::ImageCache;
pub use glyph::GlyphCache;
#[derive(Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Hash, Debug)]
pub struct TextureId(pub u64);
impl TextureId {
fn allocate() -> Self {
static COUNTER: AtomicU64 = AtomicU64::new(1);
Self(COUNTER.fetch_add(1, Ordering::Relaxed))
}
}
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub struct ImageId(u32);
impl ImageId {
fn new(generation: u8, index: u32, alpha: bool) -> Option<Self> {
if index & ID_INDEX_MASK != index {
return None;
}
let mut handle = index & ID_INDEX_MASK;
handle |= (generation as u32) << 24;
if alpha {
handle |= ID_ALPHA_BIT
}
Some(Self(handle))
}
fn generation(self) -> u8 {
(self.0 >> 24) as u8
}
fn index(self) -> usize {
(self.0 & ID_INDEX_MASK) as usize
}
pub fn has_alpha(self) -> bool {
self.0 & ID_ALPHA_BIT != 0
}
}
#[derive(Copy, Clone)]
pub struct ImageLocation {
pub texture_id: TextureId,
pub min: (f32, f32),
pub max: (f32, f32),
}
#[derive(Clone, Copy)]
pub struct AddImage<'a> {
pub format: PixelFormat,
pub width: u16,
pub height: u16,
pub has_alpha: bool,
pub evictable: bool,
pub data: ImageData<'a>,
}
impl<'a> AddImage<'a> {
fn data(&'a self) -> Option<&'a [u8]> {
self.data.data()
}
}
#[derive(Clone, Copy)]
pub enum ImageData<'a> {
Borrowed(&'a [u8]),
}
impl<'a> ImageData<'a> {
fn data(&'a self) -> Option<&'a [u8]> {
Some(match self {
Self::Borrowed(data) => data,
})
}
}
#[derive(Copy, Clone)]
#[allow(clippy::enum_variant_names)]
pub enum TextureEvent<'a> {
CreateTexture {
id: TextureId,
format: PixelFormat,
width: u16,
height: u16,
data: Option<&'a [u8]>,
},
UpdateTexture {
id: TextureId,
format: PixelFormat,
x: u16,
y: u16,
width: u16,
height: u16,
data: &'a [u8],
},
DestroyTexture(TextureId),
}
const MAX_ATLASES: u16 = 256;
const MAX_ENTRIES: u32 = 0x007FFFFF;
const END_OF_LIST: u32 = !0;
const ID_INDEX_MASK: u32 = MAX_ENTRIES;
const ID_ALPHA_BIT: u32 = 0x00800000;
const ENTRY_ALLOCATED: u8 = 1;
const ENTRY_STANDALONE: u8 = 2;
const ENTRY_EVICTABLE: u8 = 4;