use core::{cell::Cell, slice};
extern crate alloc;
use crate::{
resource::{ImageKey, PdcKey, PdcSeqKey},
sys,
ui::graphics::Colour,
};
#[repr(transparent)]
pub struct SharedPalette {
inner: [Cell<Colour>; 16],
}
unsafe impl Sync for SharedPalette {}
impl SharedPalette {
pub const fn new(val: [Colour; 16]) -> Self {
Self {
inner: val.map(Cell::new),
}
}
pub fn new_leak(val: [Colour; 16]) -> &'static Self {
use alloc::boxed::Box;
Box::leak(Box::new_in(Self::new(val), crate::alloc::PebbleAlloc))
}
pub fn as_sys_ptr(&'static self) -> *mut sys::GColor {
core::ptr::from_ref(self).cast_mut().cast()
}
pub fn set(&self, i: usize, val: Colour) {
if let Some(v) = self.inner.get(i) {
v.set(val);
}
}
pub fn get(&self, i: usize) -> Option<Colour> {
self.inner.get(i).map(Cell::get)
}
}
pub struct GBitMap {
inner: *mut sys::GBitmap,
shared_palette: bool,
}
impl GBitMap {
pub fn load(key: ImageKey) -> Option<Self> {
let inner = unsafe { sys::gbitmap_create_with_resource(key.0.get()) };
(!inner.is_null()).then_some(GBitMap {
inner,
shared_palette: false,
})
}
pub fn palette(&mut self) -> Option<&mut [Colour]> {
let format = unsafe { sys::gbitmap_get_format(self.inner) };
let mut palette_len = match format {
sys::GBitmapFormat_GBitmapFormat1BitPalette => Some(2),
sys::GBitmapFormat_GBitmapFormat2BitPalette => Some(4),
sys::GBitmapFormat_GBitmapFormat4BitPalette => Some(16),
_ => None,
};
palette_len
.take_if(|_| !self.shared_palette)
.map(|len| unsafe {
slice::from_raw_parts_mut(sys::gbitmap_get_palette(self.inner).cast(), len)
})
}
pub fn origin(&self) -> sys::GPoint {
self.bounds().origin
}
pub fn size(&self) -> sys::GSize {
self.bounds().size
}
pub fn bounds(&self) -> sys::GRect {
unsafe { sys::gbitmap_get_bounds(self.inner) }
}
pub fn as_ptr(&self) -> *mut sys::GBitmap {
self.inner
}
pub fn set_shared_palette(&mut self, shared: &'static SharedPalette) {
self.shared_palette = true;
unsafe {
sys::gbitmap_set_palette(self.inner, shared.as_sys_ptr(), false);
}
}
}
impl Drop for GBitMap {
fn drop(&mut self) {
unsafe { sys::gbitmap_destroy(self.inner) }
}
}
pub struct DrawCommand {
inner: *mut sys::GDrawCommandImage,
}
impl DrawCommand {
pub fn load(key: PdcKey) -> Option<Self> {
let inner = unsafe { sys::gdraw_command_image_create_with_resource(key.0.get()) };
if inner.is_null() {
None
} else {
Some(DrawCommand { inner })
}
}
pub fn as_ptr(&self) -> *mut sys::GDrawCommandImage {
self.inner
}
}
impl Drop for DrawCommand {
fn drop(&mut self) {
unsafe { sys::gdraw_command_image_destroy(self.inner) }
}
}
pub struct DrawCommandSequence {
inner: *mut sys::GDrawCommandSequence,
}
impl DrawCommandSequence {
pub fn load(key: PdcSeqKey) -> Option<Self> {
let inner = unsafe { sys::gdraw_command_sequence_create_with_resource(key.0.get()) };
if inner.is_null() {
None
} else {
Some(DrawCommandSequence { inner })
}
}
pub fn as_ptr(&self) -> *mut sys::GDrawCommandSequence {
self.inner
}
}
impl Drop for DrawCommandSequence {
fn drop(&mut self) {
unsafe { sys::gdraw_command_sequence_destroy(self.inner) }
}
}