use std::{
ops::{Deref, DerefMut},
sync::Arc,
};
use crate::{rect::Rect, Library};
pub struct PixelsGuard<'a> {
lock: &'a mut Surface,
pixels: &'a mut [u8],
}
impl<'a> PixelsGuard<'a> {
unsafe fn new(lock: &'a mut Surface, pixels: &'a mut [u8]) -> PixelsGuard<'a> {
PixelsGuard { lock, pixels }
}
}
impl Deref for PixelsGuard<'_> {
type Target = [u8];
fn deref(&self) -> &[u8] {
self.pixels
}
}
impl DerefMut for PixelsGuard<'_> {
fn deref_mut(&mut self) -> &mut [u8] {
self.pixels
}
}
impl Drop for PixelsGuard<'_> {
fn drop(&mut self) {
unsafe {
self.lock.raw_unlock_pixels();
}
}
}
pub struct Surface {
lib: Arc<Library>,
internal: ul_sys::ULSurface,
}
impl Surface {
pub(crate) unsafe fn from_raw(lib: Arc<Library>, raw: ul_sys::ULSurface) -> Self {
Self { lib, internal: raw }
}
}
impl Surface {
pub fn width(&self) -> u32 {
unsafe { self.lib.ultralight().ulSurfaceGetWidth(self.internal) }
}
pub fn height(&self) -> u32 {
unsafe { self.lib.ultralight().ulSurfaceGetHeight(self.internal) }
}
pub fn row_bytes(&self) -> u32 {
unsafe { self.lib.ultralight().ulSurfaceGetRowBytes(self.internal) }
}
pub fn bytes_size(&self) -> usize {
unsafe { self.lib.ultralight().ulSurfaceGetSize(self.internal) }
}
pub fn lock_pixels(&mut self) -> Option<PixelsGuard> {
let raw_locked_pixels = unsafe { self.lib.ultralight().ulSurfaceLockPixels(self.internal) };
if raw_locked_pixels.is_null() {
return None;
}
let size = self.bytes_size();
unsafe {
let data = std::slice::from_raw_parts_mut(raw_locked_pixels as _, size);
Some(PixelsGuard::new(self, data))
}
}
pub(crate) unsafe fn raw_unlock_pixels(&self) {
self.lib.ultralight().ulSurfaceUnlockPixels(self.internal)
}
pub fn resize(&self, width: u32, height: u32) {
unsafe {
self.lib
.ultralight()
.ulSurfaceResize(self.internal, width, height)
}
}
pub fn set_dirty_bounds(&self, bounds: Rect<i32>) {
unsafe {
self.lib
.ultralight()
.ulSurfaceSetDirtyBounds(self.internal, bounds.into())
}
}
pub fn dirty_bounds(&self) -> Rect<i32> {
unsafe {
self.lib
.ultralight()
.ulSurfaceGetDirtyBounds(self.internal)
.into()
}
}
pub fn clear_dirty_bounds(&self) {
unsafe {
self.lib
.ultralight()
.ulSurfaceClearDirtyBounds(self.internal)
}
}
}