playdate_graphics/bitmap/
table.rs1use alloc::boxed::Box;
4use core::ffi::c_char;
5use core::ffi::c_int;
6
7use sys::ffi::CString;
8use sys::ffi::LCDBitmapTable;
9use fs::Path;
10
11use crate::error::ApiError;
12use crate::error::Error;
13use super::Bitmap;
14use super::api::Api as BitmapApi;
15
16
17#[cfg_attr(feature = "bindings-derive-debug", derive(Debug))]
18pub struct BitmapTable<Api: api::Api = api::Default, const FREE_ON_DROP: bool = true>(*mut LCDBitmapTable, Api);
19
20impl<Api: api::Api, const FOD: bool> Drop for BitmapTable<Api, FOD> {
21 fn drop(&mut self) {
22 if FOD && !self.0.is_null() {
23 let f = self.1.free_bitmap_table();
24 unsafe { f(self.0) };
25 self.0 = core::ptr::null_mut();
26 }
27 }
28}
29
30
31impl<Api: api::Api> BitmapTable<Api, true> {
32 #[doc(alias = "sys::ffi::playdate_graphics::newBitmapTable")]
36 pub fn new(count: c_int, width: c_int, height: c_int) -> Result<Self, Error>
37 where Api: Default {
38 let api = Api::default();
39 Self::new_with(api, count, width, height)
40 }
41
42 #[doc(alias = "sys::ffi::playdate_graphics::newBitmapTable")]
47 pub fn new_with(api: Api, count: c_int, width: c_int, height: c_int) -> Result<Self, Error> {
48 let f = api.new_bitmap_table();
49 let ptr = unsafe { f(count, width, height) };
50 if ptr.is_null() {
51 Err(Error::Alloc)
52 } else {
53 Ok(Self(ptr, api))
54 }
55 }
56
57
58 #[doc(alias = "sys::ffi::playdate_graphics::loadBitmapTable")]
64 pub fn load<P: AsRef<Path>>(path: P) -> Result<Self, ApiError>
65 where Api: Default {
66 let api = Api::default();
67 Self::load_with(api, path)
68 }
69
70 #[doc(alias = "sys::ffi::playdate_graphics::loadBitmapTable")]
76 pub fn load_with<P: AsRef<Path>>(api: Api, path: P) -> Result<Self, ApiError> {
77 let mut err = Box::new(core::ptr::null() as *const c_char);
78 let out_err = Box::into_raw(err);
79
80 let path = CString::new(path.as_ref())?;
81
82 let f = api.load_bitmap_table();
83 let ptr = unsafe { f(path.as_ptr() as *mut c_char, out_err as _) };
84 if ptr.is_null() {
85 err = unsafe { Box::from_raw(out_err) };
86 if let Some(err) = fs::error::Error::from_ptr(*err) {
87 Err(Error::Fs(err).into())
88 } else {
89 Err(Error::Alloc.into())
90 }
91 } else {
92 Ok(Self(ptr, api))
93 }
94 }
95}
96
97impl<Api: api::Api, const FOD: bool> BitmapTable<Api, FOD> {
98 #[doc(alias = "sys::ffi::playdate_graphics::loadIntoBitmapTable")]
102 pub fn load_into<P: AsRef<Path>>(&mut self, path: P) -> Result<(), ApiError> {
103 let mut err = Box::new(core::ptr::null() as *const c_char);
104 let out_err = Box::into_raw(err);
105
106 let path = CString::new(path.as_ref())?;
107
108 let f = self.1.load_into_bitmap_table();
109 unsafe { f(path.as_ptr() as *mut c_char, self.0, out_err as _) };
110 err = unsafe { Box::from_raw(out_err) };
111 if let Some(err) = fs::error::Error::from_ptr(*err) {
112 Err(Error::Fs(err).into())
113 } else {
114 Ok(())
115 }
116 }
117
118
119 #[doc(alias = "sys::ffi::playdate_graphics::getTableBitmap")]
126 pub fn get<'table, BitApi: BitmapApi>(&'table self, index: c_int) -> Option<Bitmap<BitApi, true>>
127 where Bitmap<BitApi, true>: 'table,
128 BitApi: Default {
129 self.get_with(BitApi::default(), index)
130 }
131
132 #[doc(alias = "sys::ffi::playdate_graphics::getTableBitmap")]
139 pub fn get_with<'table, BitApi: BitmapApi>(&'table self,
140 api: BitApi,
141 index: c_int)
142 -> Option<Bitmap<BitApi, true>>
143 where Bitmap<BitApi, true>: 'table
144 {
145 let f = self.1.get_table_bitmap();
146 let ptr = unsafe { f(self.0, index) };
147 if ptr.is_null() {
148 None
149 } else {
150 Some(Bitmap(ptr, api))
151 }
152 }
153
154 #[doc(alias = "sys::ffi::playdate_graphics::getTableBitmap")]
159 pub fn info<'table, BitApi: BitmapApi>(&'table self, count: Option<&mut c_int>, width: Option<&mut c_int>) {
160 let f = self.1.get_bitmap_table_info();
161 unsafe {
162 use core::ptr::null_mut;
163 f(
164 self.0,
165 count.map_or(null_mut() as _, |v| v as *mut _),
166 width.map_or(null_mut() as _, |v| v as *mut _),
167 )
168 }
169 }
170}
171
172
173pub mod api {
174 use core::ffi::c_char;
175 use core::ffi::c_int;
176 use sys::ffi::LCDBitmap;
177 use sys::ffi::LCDBitmapTable;
178
179
180 pub type Default = crate::api::Default;
184
185 pub type Cache = crate::api::Cache;
191
192
193 pub trait Api {
195 #[doc(alias = "sys::ffi::playdate_graphics::newBitmapTable")]
197 fn new_bitmap_table(
198 &self)
199 -> unsafe extern "C" fn(count: c_int, width: c_int, height: c_int) -> *mut LCDBitmapTable {
200 *sys::api!(graphics.newBitmapTable)
201 }
202
203
204 #[doc(alias = "sys::ffi::playdate_graphics::freeBitmapTable")]
206 fn free_bitmap_table(&self) -> unsafe extern "C" fn(table: *mut LCDBitmapTable) {
207 *sys::api!(graphics.freeBitmapTable)
208 }
209
210
211 #[doc(alias = "sys::ffi::playdate_graphics::loadBitmapTable")]
213 fn load_bitmap_table(
214 &self)
215 -> unsafe extern "C" fn(path: *const c_char, out_err: *mut *const c_char) -> *mut LCDBitmapTable {
216 *sys::api!(graphics.loadBitmapTable)
217 }
218
219 #[doc(alias = "sys::ffi::playdate_graphics::loadIntoBitmapTable")]
221 fn load_into_bitmap_table(
222 &self)
223 -> unsafe extern "C" fn(path: *const c_char, table: *mut LCDBitmapTable, out_err: *mut *const c_char) {
224 *sys::api!(graphics.loadIntoBitmapTable)
225 }
226
227 #[doc(alias = "sys::ffi::playdate_graphics::getTableBitmap")]
229 fn get_table_bitmap(&self)
230 -> unsafe extern "C" fn(table: *mut LCDBitmapTable, idx: c_int) -> *mut LCDBitmap {
231 *sys::api!(graphics.getTableBitmap)
232 }
233
234 #[doc(alias = "sys::ffi::playdate_graphics::getBitmapTableInfo")]
236 fn get_bitmap_table_info(
237 &self)
238 -> unsafe extern "C" fn(table: *mut LCDBitmapTable, count: *mut c_int, width: *mut c_int) {
239 *sys::api!(graphics.getBitmapTableInfo)
240 }
241 }
242}