mirror of
https://github.com/penpot/penpot.git
synced 2026-05-30 20:28:07 +00:00
139 lines
3.6 KiB
Rust
139 lines
3.6 KiB
Rust
use macros::wasm_error;
|
|
|
|
use crate::mem;
|
|
use crate::render::{gpu_state::GpuState, RenderState};
|
|
use crate::state::{State, TextEditorState};
|
|
|
|
static mut DESIGN_STATE: *mut State = std::ptr::null_mut();
|
|
|
|
/// Design State.
|
|
pub(crate) fn get_design_state() -> &'static mut State {
|
|
unsafe {
|
|
debug_assert!(!DESIGN_STATE.is_null(), "Design State is null");
|
|
&mut *DESIGN_STATE
|
|
}
|
|
}
|
|
|
|
/// GPU State.
|
|
static mut GPU_STATE: *mut GpuState = std::ptr::null_mut();
|
|
|
|
#[inline(always)]
|
|
pub(crate) fn get_gpu_state() -> &'static mut GpuState {
|
|
unsafe {
|
|
debug_assert!(!GPU_STATE.is_null(), "GPU State is null");
|
|
&mut *GPU_STATE
|
|
}
|
|
}
|
|
|
|
/// Render State.
|
|
static mut RENDER_STATE: *mut RenderState = std::ptr::null_mut();
|
|
|
|
#[inline(always)]
|
|
pub(crate) fn get_render_state() -> &'static mut RenderState {
|
|
unsafe {
|
|
debug_assert!(!RENDER_STATE.is_null(), "Render State is null");
|
|
&mut *RENDER_STATE
|
|
}
|
|
}
|
|
|
|
/// Text Editor State
|
|
static mut TEXT_EDITOR_STATE: *mut TextEditorState = std::ptr::null_mut();
|
|
|
|
#[inline(always)]
|
|
pub(crate) fn get_text_editor_state() -> &'static mut TextEditorState {
|
|
unsafe {
|
|
debug_assert!(!TEXT_EDITOR_STATE.is_null(), "Text Editor state is null");
|
|
&mut *TEXT_EDITOR_STATE
|
|
}
|
|
}
|
|
|
|
// FIXME: These with_state* macros should be using our CriticalError instead of expect.
|
|
// But to do that, we need to not use them at domain-level (i.e. in business logic), just
|
|
// in the context of the wasm call.
|
|
#[macro_export]
|
|
macro_rules! with_state {
|
|
($state:ident, $block:block) => {{
|
|
use $crate::globals::get_design_state;
|
|
let $state = get_design_state();
|
|
$block
|
|
}};
|
|
}
|
|
|
|
#[macro_export]
|
|
macro_rules! with_current_shape_mut {
|
|
($state:ident, |$shape:ident: &mut Shape| $block:block) => {
|
|
use $crate::globals::get_design_state;
|
|
let $state = get_design_state();
|
|
$state.touch_current();
|
|
if let Some($shape) = $state.current_shape_mut() {
|
|
$block
|
|
}
|
|
};
|
|
}
|
|
|
|
#[macro_export]
|
|
macro_rules! with_current_shape {
|
|
($state:ident, |$shape:ident: &Shape| $block:block) => {
|
|
use $crate::globals::get_design_state;
|
|
let $state = get_design_state();
|
|
if let Some($shape) = $state.current_shape() {
|
|
$block
|
|
}
|
|
};
|
|
}
|
|
|
|
/// Initializes GPUState.
|
|
fn gpu_init() {
|
|
unsafe {
|
|
let gpu_state = GpuState::try_new().expect("Cannot initialize GPU State");
|
|
GPU_STATE = Box::into_raw(Box::new(gpu_state));
|
|
}
|
|
}
|
|
|
|
/// Initializes RenderState.
|
|
fn render_init(width: i32, height: i32) {
|
|
unsafe {
|
|
let render_state =
|
|
RenderState::try_new(width, height).expect("Cannot intialize RenderState");
|
|
RENDER_STATE = Box::into_raw(Box::new(render_state));
|
|
}
|
|
}
|
|
|
|
/// Initializes DesignState.
|
|
fn design_init() {
|
|
unsafe {
|
|
let design_state = State::new();
|
|
DESIGN_STATE = Box::into_raw(Box::new(design_state));
|
|
}
|
|
}
|
|
|
|
fn text_editor_init() {
|
|
unsafe {
|
|
let text_editor_state = TextEditorState::new();
|
|
TEXT_EDITOR_STATE = Box::into_raw(Box::new(text_editor_state));
|
|
}
|
|
}
|
|
|
|
#[no_mangle]
|
|
#[wasm_error]
|
|
pub extern "C" fn init(width: i32, height: i32) -> Result<()> {
|
|
gpu_init();
|
|
render_init(width, height);
|
|
text_editor_init();
|
|
design_init();
|
|
Ok(())
|
|
}
|
|
|
|
#[no_mangle]
|
|
#[wasm_error]
|
|
pub extern "C" fn clean_up() -> Result<()> {
|
|
// Cancel the current animation frame if it exists so
|
|
// it won't try to render without context
|
|
let render_state = get_render_state();
|
|
render_state.cancel_animation_frame();
|
|
render_state.prepare_context_loss_cleanup();
|
|
unsafe { DESIGN_STATE = std::ptr::null_mut() }
|
|
mem::free_bytes()?;
|
|
Ok(())
|
|
}
|