use std::fmt;
use std::marker::PhantomData;
use std::ptr::NonNull;
use jawt_sys::*;
use jni::sys::jint;
use crate::dsi::DrawingSurfaceInfo;
type DrawingSurfaceFree = unsafe extern "C" fn(ds: *mut JAWT_DrawingSurface);
pub struct DrawingSurface {
pub(crate) inner: NonNull<JAWT_DrawingSurface>,
pub(crate) free: DrawingSurfaceFree,
}
impl fmt::Debug for DrawingSurface {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("DrawingSurface")
.field("env", &self.as_ref().env)
.field("target", &self.as_ref().target)
.field("Lock", &self.as_ref().Lock)
.field(
"GetDrawingSurfaceInfo",
&self.as_ref().GetDrawingSurfaceInfo,
)
.field(
"FreeDrawingSurfaceInfo",
&self.as_ref().FreeDrawingSurfaceInfo,
)
.field("Unlock", &self.as_ref().Unlock)
.field("JAWT.FreeDrawingSurface", &self.free)
.finish()
}
}
impl DrawingSurface {
pub const unsafe fn from_raw_parts(
inner: NonNull<JAWT_DrawingSurface>,
free: DrawingSurfaceFree,
) -> Self {
Self { inner, free }
}
pub const fn as_ref(&self) -> &JAWT_DrawingSurface {
unsafe { self.inner.as_ref() }
}
pub unsafe fn as_mut(&mut self) -> &mut JAWT_DrawingSurface {
self.inner.as_mut()
}
pub fn into_raw_parts(self) -> (NonNull<JAWT_DrawingSurface>, DrawingSurfaceFree) {
(self.inner, self.free)
}
pub fn lock(&mut self) -> Option<(DrawingSurfaceLockResult, DrawingSurfaceGuard<'_>)> {
let lock_result = unsafe {
crate::utils::unwrap_fn!(self.as_ref(), JAWT_DrawingSurface.Lock)(self.inner.as_ptr())
};
if lock_result & JAWT_LOCK_ERROR != 0 {
return None;
}
Some((
DrawingSurfaceLockResult::from_bits_truncate(lock_result),
DrawingSurfaceGuard {
drawing_surface: self,
},
))
}
}
impl AsRef<JAWT_DrawingSurface> for DrawingSurface {
fn as_ref(&self) -> &JAWT_DrawingSurface {
self.as_ref()
}
}
impl Drop for DrawingSurface {
fn drop(&mut self) {
unsafe { (self.free)(self.inner.as_mut()) };
}
}
bitflags::bitflags! {
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct DrawingSurfaceLockResult: jint {
const CLIP_CHANGED = JAWT_LOCK_CLIP_CHANGED;
const BOUNDS_CHANGED = JAWT_LOCK_BOUNDS_CHANGED;
const SURFACE_CHANGED = JAWT_LOCK_SURFACE_CHANGED;
}
}
pub struct DrawingSurfaceGuard<'a> {
drawing_surface: &'a mut DrawingSurface,
}
impl DrawingSurfaceGuard<'_> {
pub fn drawing_surface_info(&mut self) -> Option<DrawingSurfaceInfo<'_>> {
let get_drawing_surface_info = crate::utils::unwrap_fn!(
self.drawing_surface.as_ref(),
JAWT_DrawingSurface.GetDrawingSurfaceInfo,
);
let free_drawing_surface_info = crate::utils::unwrap_fn!(
self.drawing_surface.as_ref(),
JAWT_DrawingSurface.FreeDrawingSurfaceInfo,
);
let drawing_surface_info =
NonNull::new(unsafe { get_drawing_surface_info(self.drawing_surface.inner.as_ptr()) })?;
Some(DrawingSurfaceInfo {
inner: drawing_surface_info,
free: free_drawing_surface_info,
_drawing_surface: PhantomData,
})
}
}
impl Drop for DrawingSurfaceGuard<'_> {
fn drop(&mut self) {
unsafe {
crate::utils::unwrap_fn!(self.drawing_surface.as_ref(), JAWT_DrawingSurface.Unlock)(
self.drawing_surface.inner.as_ptr(),
)
};
}
}