blob: 2b51a58489ce7608e4a10622eb652b422772e4b1 [file] [log] [blame]
use std::{
ffi::CString, fs::File, io::Read, os::unix::prelude::OsStrExt, path::Path, ptr::NonNull,
};
use vello::kurbo::Vec2;
use crate::VelloRenderer;
#[derive(Debug)]
enum RawViewerContent {}
extern "C" {
fn viewer_content_new(raw_path: *const i8) -> Option<NonNull<RawViewerContent>>;
fn viewer_content_release(raw_viewer_content: Option<NonNull<RawViewerContent>>);
fn viewer_content_handle_resize(
raw_viewer_content: Option<NonNull<RawViewerContent>>,
width: i32,
height: i32,
);
// We're simply propagating the `VelloRender` pointer opaquely through the FFI.
#[allow(improper_ctypes)]
fn viewer_content_handle_draw(
raw_viewer_content: Option<NonNull<RawViewerContent>>,
raw_vello_renderer: Option<NonNull<VelloRenderer>>,
elapsed: f64,
);
fn viewer_content_handle_pointer_move(
raw_viewer_content: Option<NonNull<RawViewerContent>>,
x: f32,
y: f32,
);
fn viewer_content_handle_pointer_down(
raw_viewer_content: Option<NonNull<RawViewerContent>>,
x: f32,
y: f32,
);
fn viewer_content_handle_pointer_up(
raw_viewer_content: Option<NonNull<RawViewerContent>>,
x: f32,
y: f32,
);
}
#[derive(Debug)]
pub struct ViewerContent {
raw_viewer_content: Option<NonNull<RawViewerContent>>,
}
impl ViewerContent {
pub fn new<P: AsRef<Path>>(path: P) -> Option<Self> {
let path = path.as_ref();
let header = {
let mut file = File::open(path).ok()?;
let mut buffer = [0; 4];
file.read_exact(&mut buffer).ok()?;
buffer
};
if &header != b"RIVE" {
return None;
}
let c_str = CString::new(path.as_os_str().as_bytes()).unwrap();
let raw_viewer_content = Some(unsafe { viewer_content_new(c_str.as_ptr())? });
Some(Self { raw_viewer_content })
}
pub fn handle_resize(&self, width: u32, height: u32) {
unsafe {
viewer_content_handle_resize(self.raw_viewer_content, width as i32, height as i32);
}
}
pub fn handle_draw(&mut self, renderer: &mut VelloRenderer, elapsed: f64) {
unsafe {
viewer_content_handle_draw(
self.raw_viewer_content,
NonNull::new(renderer as *mut VelloRenderer),
elapsed,
)
}
}
pub fn handle_pointer_move(&self, pos: Vec2) {
unsafe {
viewer_content_handle_pointer_move(self.raw_viewer_content, pos.x as f32, pos.y as f32);
}
}
pub fn handle_pointer_down(&self, pos: Vec2) {
unsafe {
viewer_content_handle_pointer_down(self.raw_viewer_content, pos.x as f32, pos.y as f32);
}
}
pub fn handle_pointer_up(&self, pos: Vec2) {
unsafe {
viewer_content_handle_pointer_up(self.raw_viewer_content, pos.x as f32, pos.y as f32);
}
}
}
impl Drop for ViewerContent {
fn drop(&mut self) {
unsafe {
viewer_content_release(self.raw_viewer_content);
}
}
}