use core::ptr::NonNull;
use std::ffi::{CStr, CString};
use std::os::raw::c_void;
use crate::ffi::{
TextureRenderCallback, noesis_base_component_release, noesis_bitmap_image_create,
noesis_bitmap_image_get_uri_source, noesis_bitmap_image_set_uri_source,
noesis_bitmap_source_get_dpi, noesis_bitmap_source_get_pixel_size,
noesis_cropped_bitmap_create, noesis_cropped_bitmap_get_source,
noesis_cropped_bitmap_get_source_rect, noesis_cropped_bitmap_set_source,
noesis_cropped_bitmap_set_source_rect, noesis_dynamic_texture_source_create,
noesis_dynamic_texture_source_get_pixel_size, noesis_dynamic_texture_source_resize,
noesis_texture_source_create, noesis_texture_source_get_texture,
noesis_texture_source_set_texture,
};
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
pub struct Int32Rect {
pub x: i32,
pub y: i32,
pub width: u32,
pub height: u32,
}
impl Int32Rect {
#[must_use]
pub fn new(x: i32, y: i32, width: u32, height: u32) -> Self {
Self {
x,
y,
width,
height,
}
}
}
pub trait BitmapSource {
fn bitmap_source_raw(&self) -> *mut c_void;
#[must_use]
fn pixel_size(&self) -> (i32, i32) {
let mut w = 0i32;
let mut h = 0i32;
unsafe {
noesis_bitmap_source_get_pixel_size(
self.bitmap_source_raw(),
&mut w as *mut i32,
&mut h as *mut i32,
);
}
(w, h)
}
#[must_use]
fn dpi(&self) -> (f32, f32) {
let mut x = 0f32;
let mut y = 0f32;
unsafe {
noesis_bitmap_source_get_dpi(
self.bitmap_source_raw(),
&mut x as *mut f32,
&mut y as *mut f32,
);
}
(x, y)
}
}
macro_rules! base_component_handle {
($name:ident) => {
unsafe impl Send for $name {}
impl $name {
#[must_use]
pub fn raw(&self) -> *mut c_void {
self.ptr.as_ptr()
}
}
impl Drop for $name {
fn drop(&mut self) {
unsafe { noesis_base_component_release(self.ptr.as_ptr()) }
}
}
};
}
pub struct CroppedBitmap {
ptr: NonNull<c_void>,
}
base_component_handle!(CroppedBitmap);
impl Default for CroppedBitmap {
fn default() -> Self {
Self::new()
}
}
impl CroppedBitmap {
#[must_use]
pub fn new() -> Self {
let ptr = unsafe { noesis_cropped_bitmap_create() };
Self {
ptr: NonNull::new(ptr).expect("noesis_cropped_bitmap_create returned null"),
}
}
pub fn set_source<S: BitmapSource>(&mut self, source: &S) -> bool {
unsafe { noesis_cropped_bitmap_set_source(self.ptr.as_ptr(), source.bitmap_source_raw()) }
}
#[must_use]
pub fn source(&self) -> Option<NonNull<c_void>> {
let p = unsafe { noesis_cropped_bitmap_get_source(self.ptr.as_ptr()) };
NonNull::new(p)
}
pub fn set_source_rect(&mut self, rect: Int32Rect) {
unsafe {
noesis_cropped_bitmap_set_source_rect(
self.ptr.as_ptr(),
rect.x,
rect.y,
rect.width,
rect.height,
);
}
}
#[must_use]
pub fn source_rect(&self) -> Int32Rect {
let mut r = Int32Rect::default();
unsafe {
noesis_cropped_bitmap_get_source_rect(
self.ptr.as_ptr(),
&mut r.x as *mut i32,
&mut r.y as *mut i32,
&mut r.width as *mut u32,
&mut r.height as *mut u32,
);
}
r
}
}
impl BitmapSource for CroppedBitmap {
fn bitmap_source_raw(&self) -> *mut c_void {
self.raw()
}
}
pub struct TextureSource {
ptr: NonNull<c_void>,
}
base_component_handle!(TextureSource);
impl Default for TextureSource {
fn default() -> Self {
Self::new()
}
}
impl TextureSource {
#[must_use]
pub fn new() -> Self {
let ptr = unsafe { noesis_texture_source_create(core::ptr::null_mut()) };
Self {
ptr: NonNull::new(ptr).expect("noesis_texture_source_create returned null"),
}
}
#[must_use]
pub unsafe fn with_texture(texture: *mut c_void) -> Option<Self> {
let ptr = unsafe { noesis_texture_source_create(texture) };
NonNull::new(ptr).map(|ptr| Self { ptr })
}
pub unsafe fn set_texture(&mut self, texture: *mut c_void) -> bool {
unsafe { noesis_texture_source_set_texture(self.ptr.as_ptr(), texture) }
}
#[must_use]
pub fn texture(&self) -> Option<NonNull<c_void>> {
let p = unsafe { noesis_texture_source_get_texture(self.ptr.as_ptr()) };
NonNull::new(p)
}
}
impl BitmapSource for TextureSource {
fn bitmap_source_raw(&self) -> *mut c_void {
self.raw()
}
}
pub struct BitmapImage {
ptr: NonNull<c_void>,
}
base_component_handle!(BitmapImage);
impl Default for BitmapImage {
fn default() -> Self {
Self::new()
}
}
impl BitmapImage {
#[must_use]
pub fn new() -> Self {
let ptr = unsafe { noesis_bitmap_image_create(core::ptr::null()) };
Self {
ptr: NonNull::new(ptr).expect("noesis_bitmap_image_create returned null"),
}
}
#[must_use]
pub fn from_uri(uri: &str) -> Self {
let c = CString::new(uri).expect("BitmapImage uri contains interior NUL");
let ptr = unsafe { noesis_bitmap_image_create(c.as_ptr()) };
Self {
ptr: NonNull::new(ptr).expect("noesis_bitmap_image_create returned null"),
}
}
#[must_use = "a false return means the property was not set (unknown name / type mismatch / read-only)"]
pub fn set_uri_source(&mut self, uri: &str) -> bool {
let c = CString::new(uri).expect("BitmapImage uri contains interior NUL");
unsafe { noesis_bitmap_image_set_uri_source(self.ptr.as_ptr(), c.as_ptr()) }
}
#[must_use]
pub fn uri_source(&self) -> String {
let p = unsafe { noesis_bitmap_image_get_uri_source(self.ptr.as_ptr()) };
if p.is_null() {
return String::new();
}
unsafe { CStr::from_ptr(p) }.to_string_lossy().into_owned()
}
}
impl BitmapSource for BitmapImage {
fn bitmap_source_raw(&self) -> *mut c_void {
self.raw()
}
}
pub struct DynamicTextureSource {
ptr: NonNull<c_void>,
}
base_component_handle!(DynamicTextureSource);
impl DynamicTextureSource {
#[must_use]
pub unsafe fn new(
width: u32,
height: u32,
callback: TextureRenderCallback,
user: *mut c_void,
) -> Self {
let ptr = unsafe { noesis_dynamic_texture_source_create(width, height, callback, user) };
Self {
ptr: NonNull::new(ptr).expect("noesis_dynamic_texture_source_create returned null"),
}
}
pub fn resize(&mut self, width: u32, height: u32) -> bool {
unsafe { noesis_dynamic_texture_source_resize(self.ptr.as_ptr(), width, height) }
}
#[must_use]
pub fn pixel_size(&self) -> (u32, u32) {
let mut w = 0u32;
let mut h = 0u32;
unsafe {
noesis_dynamic_texture_source_get_pixel_size(
self.ptr.as_ptr(),
&mut w as *mut u32,
&mut h as *mut u32,
);
}
(w, h)
}
}