use std::{ffi::c_void, mem::MaybeUninit};
use crate::*;
use std::ffi::{CStr, CString};
use libc::{c_char, c_ulong};
pub struct BufroFont(Font);
#[derive(Clone, Copy)]
#[repr(C)]
pub struct BufroXlibWindow {
pub window: c_ulong,
pub display: *mut c_void,
}
impl Into<raw_window_handle::RawWindowHandle> for BufroXlibWindow {
fn into(self) -> raw_window_handle::RawWindowHandle {
raw_window_handle::RawWindowHandle::Xlib(raw_window_handle::unix::XlibHandle {
window: self.window,
display: self.display,
..raw_window_handle::unix::XlibHandle::empty()
})
}
}
unsafe impl raw_window_handle::HasRawWindowHandle for BufroXlibWindow {
fn raw_window_handle(&self) -> raw_window_handle::RawWindowHandle {
(*self).into()
}
}
#[no_mangle]
pub unsafe extern "C" fn bfr_painter_from_xlib_window(
handle: BufroXlibWindow,
width: u32,
height: u32,
backend: u32,
) -> *mut Painter {
let painter = Box::new(pollster::block_on(Painter::new_from_window(
&handle,
(width, height),
Backends::from_bits(backend).unwrap(),
)));
Box::into_raw(painter)
}
#[no_mangle]
pub unsafe extern "C" fn bfr_painter_free(painter: *mut Painter) {
Box::from_raw(painter);
}
#[no_mangle]
pub unsafe extern "C" fn bfr_font_from_buffer(
data: *const c_char,
len: usize,
ptr: *mut *mut BufroFont,
) -> u8 {
let data = data as *const u8;
let data = &*std::ptr::slice_from_raw_parts(data, len);
let boxed = Box::new({
match Font::new(data) {
Some(font) => BufroFont(font),
None => return 1,
}
});
*ptr = Box::into_raw(boxed);
0
}
#[no_mangle]
pub unsafe extern "C" fn bfr_font_free(font: *mut BufroFont) {
Box::from_raw(font);
}
#[no_mangle]
pub unsafe extern "C" fn bfr_painter_resize(painter: *mut Painter, width: u32, height: u32) {
(*painter).resize((width, height));
}
#[no_mangle]
pub unsafe extern "C" fn bfr_painter_rectangle(
painter: *mut Painter,
x: f32,
y: f32,
width: f32,
height: f32,
color: BufroColor,
) {
(*painter).rectangle(x, y, width, height, std::mem::transmute(color));
}
#[no_mangle]
pub unsafe extern "C" fn bfr_pathbuilder_new() -> *mut PathBuilder {
Box::into_raw(Box::new(PathBuilder::new()))
}
#[no_mangle]
pub unsafe extern "C" fn bfr_pathbuilder_free(pathbuilder: *mut PathBuilder) {
Box::from_raw(pathbuilder);
}
#[no_mangle]
pub unsafe extern "C" fn bfr_pathbuilder_build(
pathbuilder: *mut PathBuilder,
path: *mut *mut Path,
) {
let mut builder: MaybeUninit<PathBuilder> = MaybeUninit::uninit().assume_init();
std::ptr::copy(
pathbuilder,
&mut builder as *mut MaybeUninit<PathBuilder> as *mut PathBuilder,
1,
);
let builder = builder.assume_init();
let newpath = Box::new(builder.build());
*path = Box::into_raw(newpath);
}
#[no_mangle]
pub unsafe extern "C" fn bfr_pathbuilder_scale(pathbuilder: *mut PathBuilder, x: f32, y: f32) {
(*pathbuilder).scale(x, y);
}
#[no_mangle]
pub unsafe extern "C" fn bfr_pathbuilder_rotate(pathbuilder: *mut PathBuilder, angle: f32) {
(*pathbuilder).rotate(angle);
}
#[no_mangle]
pub unsafe extern "C" fn bfr_pathbuilder_translate(pathbuilder: *mut PathBuilder, x: f32, y: f32) {
(*pathbuilder).translate(x, y);
}
#[no_mangle]
pub unsafe extern "C" fn bfr_pathbuilder_save(pathbuilder: *mut PathBuilder) {
(*pathbuilder).save();
}
#[no_mangle]
pub unsafe extern "C" fn bfr_pathbuilder_restore(pathbuilder: *mut PathBuilder) {
(*pathbuilder).restore();
}
#[no_mangle]
pub unsafe extern "C" fn bfr_pathbuilder_close(pathbuilder: *mut PathBuilder) {
(*pathbuilder).close();
}
#[no_mangle]
pub unsafe extern "C" fn bfr_pathbuilder_move_to(pathbuilder: *mut PathBuilder, x: f32, y: f32) {
(*pathbuilder).move_to(x, y);
}
#[no_mangle]
pub unsafe extern "C" fn bfr_pathbuilder_line_to(pathbuilder: *mut PathBuilder, x: f32, y: f32) {
(*pathbuilder).line_to(x, y);
}
#[no_mangle]
pub unsafe extern "C" fn bfr_pathbuilder_quad_to(
pathbuilder: *mut PathBuilder,
x1: f32,
y1: f32,
x2: f32,
y2: f32,
) {
(*pathbuilder).quad_to(x1, y1, x2, y2);
}
#[no_mangle]
pub unsafe extern "C" fn bfr_pathbuilder_curve_to(
pathbuilder: *mut PathBuilder,
x1: f32,
y1: f32,
x2: f32,
y2: f32,
x3: f32,
y3: f32,
) {
(*pathbuilder).curve_to(x1, y1, x2, y2, x3, y3);
}
#[no_mangle]
pub unsafe extern "C" fn bfr_painter_scale(painter: *mut Painter, x: f32, y: f32) {
(*painter).scale(x, y);
}
#[no_mangle]
pub unsafe extern "C" fn bfr_painter_rotate(painter: *mut Painter, angle: f32) {
(*painter).rotate(angle);
}
#[no_mangle]
pub unsafe extern "C" fn bfr_painter_translate(painter: *mut Painter, x: f32, y: f32) {
(*painter).translate(x, y);
}
#[no_mangle]
pub unsafe extern "C" fn bfr_painter_save(painter: *mut Painter) {
(*painter).save();
}
#[no_mangle]
pub unsafe extern "C" fn bfr_painter_restore(painter: *mut Painter) {
(*painter).restore();
}
#[no_mangle]
pub unsafe extern "C" fn bfr_painter_fill_text(
painter: *mut Painter,
font: *const BufroFont,
text: *const c_char,
x: f32,
y: f32,
size: f32,
color: BufroColor,
wrap_limit: usize,
) {
let text = CStr::from_ptr(text);
let text = text.to_str().unwrap();
(*painter).fill_text(
&(*font).0,
text,
x,
y,
size,
std::mem::transmute(color),
match wrap_limit {
0 => None,
_ => Some(wrap_limit),
},
);
}
#[no_mangle]
pub unsafe extern "C" fn bfr_painter_stroke_text(
painter: *mut Painter,
font: *const BufroFont,
text: *const c_char,
x: f32,
y: f32,
size: f32,
color: BufroColor,
options: BufroStrokeOptions,
wrap_limit: usize,
) {
let text = CStr::from_ptr(text);
let text = text.to_str().unwrap();
(*painter).stroke_text(
&(*font).0,
text,
x,
y,
size,
std::mem::transmute(color),
std::mem::transmute(options),
match wrap_limit {
0 => None,
_ => Some(wrap_limit),
},
);
}
#[derive(Copy, Clone, Debug, PartialEq, Hash, Eq)]
#[repr(C)]
pub enum BufroLineCap {
BufroLineCapButt,
BufroLineCapSquare,
BufroLineCapRound,
}
#[derive(Copy, Clone, Debug, PartialEq, Hash, Eq)]
#[repr(C)]
pub enum BufroLineJoin {
BufroLineJoinMiter,
BufroLineJoinMiterClip,
BufroLineJoinRound,
BufroLineJoinBevel,
}
#[repr(C)]
pub struct BufroStrokeOptions {
pub start_cap: BufroLineCap,
pub end_cap: BufroLineCap,
pub line_join: BufroLineJoin,
pub line_width: f32,
pub miter_limit: f32,
}
#[no_mangle]
pub unsafe extern "C" fn bfr_painter_regen(painter: *mut Painter) {
(*painter).regen();
}
#[no_mangle]
pub unsafe extern "C" fn bfr_painter_stroke_path(
painter: *mut Painter,
path: *const Path,
color: BufroColor,
options: BufroStrokeOptions,
) {
(*painter).stroke_path(
&*path,
std::mem::transmute(color),
std::mem::transmute(options),
);
}
#[no_mangle]
pub unsafe extern "C" fn bfr_painter_fill_path(
painter: *mut Painter,
path: *const Path,
color: BufroColor,
) {
(*painter).fill_path(&*path, std::mem::transmute(color));
}
#[no_mangle]
pub unsafe extern "C" fn bfr_painter_circle(
painter: *mut Painter,
x: f32,
y: f32,
radius: f32,
color: BufroColor,
) {
(*painter).circle(x, y, radius, std::mem::transmute(color));
}
#[no_mangle]
pub unsafe extern "C" fn bfr_painter_get_buffer_info_string(
painter: *mut Painter,
) -> *const c_char {
let info = (*painter).get_buffer_info();
CString::new(info).unwrap().into_raw()
}
#[no_mangle]
pub unsafe extern "C" fn bfr_painter_clear(painter: *mut Painter) {
(*painter).clear();
}
#[no_mangle]
pub unsafe extern "C" fn bfr_painter_flush(painter: *mut Painter) -> BufroFlushResult {
match (*painter).flush() {
Ok(()) => BufroFlushResult::BufroFlushResultOk,
Err(e) => BufroFlushResult::from(e),
}
}
#[repr(C)]
pub enum BufroFlushResult {
BufroFlushResultTimeout,
BufroFlushResultOutdated,
BufroFlushResultLost,
BufroFlushResultOutOfMemory,
BufroFlushResultOk,
}
impl From<wgpu::SurfaceError> for BufroFlushResult {
fn from(err: wgpu::SurfaceError) -> Self {
match err {
wgpu::SurfaceError::Outdated => BufroFlushResult::BufroFlushResultOutdated,
wgpu::SurfaceError::Lost => BufroFlushResult::BufroFlushResultLost,
wgpu::SurfaceError::OutOfMemory => BufroFlushResult::BufroFlushResultOutOfMemory,
wgpu::SurfaceError::Timeout => BufroFlushResult::BufroFlushResultTimeout,
}
}
}
#[repr(C)]
pub struct BufroColor {
pub r: f32,
pub g: f32,
pub b: f32,
pub a: f32,
}
#[no_mangle]
pub unsafe extern "C" fn bfr_colorf(r: f32, g: f32, b: f32, a: f32) -> BufroColor {
BufroColor { r, g, b, a }
}
#[no_mangle]
pub unsafe extern "C" fn bfr_coloru8(r: u8, g: u8, b: u8, a: u8) -> BufroColor {
BufroColor {
r: r as f32 / 255.0,
g: g as f32 / 255.0,
b: b as f32 / 255.0,
a: a as f32 / 255.0,
}
}