🔧 Avoid using global static mut variables when possible

This commit is contained in:
elenatorro 2025-03-05 16:26:34 +01:00
parent 0279e75c4b
commit 3a8ba4cbee
6 changed files with 270 additions and 218 deletions

View file

@ -24,6 +24,22 @@ extern "C" {
) -> *const ::std::os::raw::c_void;
}
macro_rules! with_state {
($state:ident, $block:block) => {
let $state = unsafe { STATE.as_mut() }.expect("Got an invalid state pointer");
$block
};
}
macro_rules! with_current_shape {
($state:ident, |$shape:ident: &mut Shape| $block:block) => {
let $state = unsafe { STATE.as_mut() }.expect("Got an invalid state pointer");
if let Some($shape) = $state.current_shape() {
$block
}
};
}
fn init_gl() {
unsafe {
gl::load_with(|addr| {
@ -50,167 +66,167 @@ pub extern "C" fn clean_up() {
#[no_mangle]
pub extern "C" fn clear_cache() {
let state = unsafe { STATE.as_mut() }.expect("Got an invalid state pointer");
let render_state = state.render_state();
render_state.clear_cache();
with_state!(state, {
let render_state = state.render_state();
render_state.clear_cache();
});
}
#[no_mangle]
pub extern "C" fn set_render_options(debug: u32, dpr: f32) {
let state = unsafe { STATE.as_mut() }.expect("Got an invalid state pointer");
let render_state = state.render_state();
render_state.set_debug_flags(debug);
render_state.set_dpr(dpr);
with_state!(state, {
let render_state = state.render_state();
render_state.set_debug_flags(debug);
render_state.set_dpr(dpr);
});
}
#[no_mangle]
pub extern "C" fn set_canvas_background(raw_color: u32) {
let state = unsafe { STATE.as_mut() }.expect("got an invalid state pointer");
let color = skia::Color::new(raw_color);
state.set_background_color(color);
with_state!(state, {
let color = skia::Color::new(raw_color);
state.set_background_color(color);
});
}
#[no_mangle]
pub extern "C" fn render(timestamp: i32) {
let state = unsafe { STATE.as_mut() }.expect("Got an invalid state pointer");
state.start_render_loop(timestamp).expect("Error rendering");
with_state!(state, {
state.start_render_loop(timestamp).expect("Error rendering");
});
}
#[no_mangle]
pub extern "C" fn render_from_cache() {
let state = unsafe { STATE.as_mut() }.expect("Got an invalid state pointer");
state.render_from_cache();
with_state!(state, {
state.render_from_cache();
});
}
#[no_mangle]
pub extern "C" fn process_animation_frame(timestamp: i32) {
let state = unsafe { STATE.as_mut() }.expect("Got an invalid state pointer");
state
.process_animation_frame(timestamp)
.expect("Error processing animation frame");
with_state!(state, {
state
.process_animation_frame(timestamp)
.expect("Error processing animation frame");
});
}
#[no_mangle]
pub extern "C" fn reset_canvas() {
let state = unsafe { STATE.as_mut() }.expect("Got an invalid state pointer");
state.render_state().reset_canvas();
with_state!(state, {
state.render_state().reset_canvas();
});
}
#[no_mangle]
pub extern "C" fn resize_viewbox(width: i32, height: i32) {
let state = unsafe { STATE.as_mut() }.expect("Got an invalid state pointer");
state.resize(width, height);
with_state!(state, {
state.resize(width, height);
});
}
#[no_mangle]
pub extern "C" fn set_view(zoom: f32, x: f32, y: f32) {
let state = unsafe { STATE.as_mut() }.expect("Got an invalid state pointer");
let render_state = state.render_state();
render_state.invalidate_cache_if_needed();
render_state.viewbox.set_all(zoom, x, y);
with_state!(state, {
let render_state = state.render_state();
render_state.invalidate_cache_if_needed();
render_state.viewbox.set_all(zoom, x, y);
});
}
#[no_mangle]
pub extern "C" fn set_view_zoom(zoom: f32) {
let state = unsafe { STATE.as_mut() }.expect("Got an invalid state pointer");
state.render_state().viewbox.set_zoom(zoom);
with_state!(state, {
state.render_state().viewbox.set_zoom(zoom);
});
}
#[no_mangle]
pub extern "C" fn set_view_xy(x: f32, y: f32) {
let state = unsafe { STATE.as_mut() }.expect("Got an invalid state pointer");
state.render_state().viewbox.set_pan_xy(x, y);
with_state!(state, {
state.render_state().viewbox.set_pan_xy(x, y);
});
}
#[no_mangle]
pub extern "C" fn use_shape(a: u32, b: u32, c: u32, d: u32) {
let state = unsafe { STATE.as_mut() }.expect("Got an invalid state pointer");
let id = uuid_from_u32_quartet(a, b, c, d);
state.use_shape(id);
with_state!(state, {
let id = uuid_from_u32_quartet(a, b, c, d);
state.use_shape(id);
});
}
#[no_mangle]
pub extern "C" fn set_shape_masked_group(masked: bool) {
let state = unsafe { STATE.as_mut() }.expect("Got an invalid state pointer");
if let Some(shape) = state.current_shape() {
with_current_shape!(state, |shape: &mut Shape| {
shape.set_masked(masked);
}
});
}
#[no_mangle]
pub extern "C" fn set_shape_bool_type(raw_bool_type: u8) {
let state = unsafe { STATE.as_mut() }.expect("got an invalid state pointer");
if let Some(shape) = state.current_shape() {
shape.set_bool_type(BoolType::from(raw_bool_type))
}
with_current_shape!(state, |shape: &mut Shape| {
shape.set_bool_type(BoolType::from(raw_bool_type));
});
}
#[no_mangle]
pub unsafe extern "C" fn set_shape_type(shape_type: u8) {
let state = unsafe { STATE.as_mut() }.expect("Got an invalid state pointer");
if let Some(shape) = state.current_shape() {
with_current_shape!(state, |shape: &mut Shape| {
shape.set_shape_type(Type::from(shape_type));
}
});
}
#[no_mangle]
pub extern "C" fn set_shape_selrect(left: f32, top: f32, right: f32, bottom: f32) {
let state = unsafe { STATE.as_mut() }.expect("Got an invalid state pointer");
if let Some(shape) = state.current_shape() {
with_current_shape!(state, |shape: &mut Shape| {
shape.set_selrect(left, top, right, bottom);
}
});
}
#[no_mangle]
pub extern "C" fn set_shape_clip_content(clip_content: bool) {
let state = unsafe { STATE.as_mut() }.expect("Got an invalid state pointer");
if let Some(shape) = state.current_shape() {
with_current_shape!(state, |shape: &mut Shape| {
shape.set_clip(clip_content);
}
});
}
#[no_mangle]
pub extern "C" fn set_shape_rotation(rotation: f32) {
let state = unsafe { STATE.as_mut() }.expect("Got an invalid state pointer");
if let Some(shape) = state.current_shape() {
with_current_shape!(state, |shape: &mut Shape| {
shape.set_rotation(rotation);
}
});
}
#[no_mangle]
pub extern "C" fn set_shape_transform(a: f32, b: f32, c: f32, d: f32, e: f32, f: f32) {
let state = unsafe { STATE.as_mut() }.expect("Got an invalid state pointer");
if let Some(shape) = state.current_shape() {
with_current_shape!(state, |shape: &mut Shape| {
shape.set_transform(a, b, c, d, e, f);
}
});
}
#[no_mangle]
pub extern "C" fn add_shape_child(a: u32, b: u32, c: u32, d: u32) {
let state = unsafe { STATE.as_mut() }.expect("Got an invalid state pointer");
let id = uuid_from_u32_quartet(a, b, c, d);
if let Some(shape) = state.current_shape() {
with_current_shape!(state, |shape: &mut Shape| {
let id = uuid_from_u32_quartet(a, b, c, d);
shape.add_child(id);
}
});
}
#[no_mangle]
pub extern "C" fn clear_shape_children() {
let state = unsafe { STATE.as_mut() }.expect("Got an invalid state pointer");
if let Some(shape) = state.current_shape() {
with_current_shape!(state, |shape: &mut Shape| {
shape.clear_children();
}
});
}
#[no_mangle]
pub extern "C" fn add_shape_solid_fill(raw_color: u32) {
let state = unsafe { STATE.as_mut() }.expect("Got an invalid state pointer");
if let Some(shape) = state.current_shape() {
with_current_shape!(state, |shape: &mut Shape| {
let color = skia::Color::new(raw_color);
shape.add_fill(shapes::Fill::Solid(color));
}
});
}
#[no_mangle]
@ -221,14 +237,13 @@ pub extern "C" fn add_shape_linear_fill(
end_y: f32,
opacity: f32,
) {
let state = unsafe { STATE.as_mut() }.expect("Got an invalid state pointer");
if let Some(shape) = state.current_shape() {
with_current_shape!(state, |shape: &mut Shape| {
shape.add_fill(shapes::Fill::new_linear_gradient(
(start_x, start_y),
(end_x, end_y),
opacity,
))
}
));
});
}
#[no_mangle]
@ -240,15 +255,14 @@ pub extern "C" fn add_shape_radial_fill(
opacity: f32,
width: f32,
) {
let state = unsafe { STATE.as_mut() }.expect("Got an invalid state pointer");
if let Some(shape) = state.current_shape() {
with_current_shape!(state, |shape: &mut Shape| {
shape.add_fill(shapes::Fill::new_radial_gradient(
(start_x, start_y),
(end_x, end_y),
opacity,
width,
))
}
));
});
}
#[no_mangle]
@ -260,58 +274,63 @@ pub extern "C" fn add_shape_fill_stops() {
.map(|data| shapes::RawStopData::from_bytes(data.try_into().unwrap()))
.collect();
let state = unsafe { STATE.as_mut() }.expect("Got an invalid state pointer");
if let Some(shape) = state.current_shape() {
with_current_shape!(state, |shape: &mut Shape| {
shape
.add_fill_gradient_stops(entries)
.expect("could not add gradient stops");
}
});
mem::free_bytes();
}
#[no_mangle]
pub extern "C" fn store_font(family_name_size: u32, font_size: u32) {
let state = unsafe { STATE.as_mut() }.expect("Got an invalid state pointer");
unsafe {
let font_bytes =
Vec::<u8>::from_raw_parts(mem::buffer_ptr(), font_size as usize, font_size as usize);
let family_name = String::from_raw_parts(
mem::buffer_ptr().add(font_size as usize),
family_name_size as usize,
family_name_size as usize,
);
match state.render_state().add_font(family_name, &font_bytes) {
with_state!(state, {
unsafe {
let font_bytes = Vec::<u8>::from_raw_parts(
mem::buffer_ptr(),
font_size as usize,
font_size as usize,
);
let family_name = String::from_raw_parts(
mem::buffer_ptr().add(font_size as usize),
family_name_size as usize,
family_name_size as usize,
);
match state.render_state().add_font(family_name, &font_bytes) {
Err(msg) => {
eprintln!("{}", msg);
}
_ => {}
}
mem::free_bytes();
}
});
}
#[no_mangle]
pub extern "C" fn store_image(a: u32, b: u32, c: u32, d: u32) {
with_state!(state, {
let id = uuid_from_u32_quartet(a, b, c, d);
let image_bytes = mem::bytes();
match state.render_state().add_image(id, &image_bytes) {
Err(msg) => {
eprintln!("{}", msg);
}
_ => {}
}
mem::free_bytes();
}
}
#[no_mangle]
pub extern "C" fn store_image(a: u32, b: u32, c: u32, d: u32) {
let state = unsafe { STATE.as_mut() }.expect("Got an invalid state pointer");
let id = uuid_from_u32_quartet(a, b, c, d);
let image_bytes = mem::bytes();
match state.render_state().add_image(id, &image_bytes) {
Err(msg) => {
eprintln!("{}", msg);
}
_ => {}
}
mem::free_bytes();
});
}
#[no_mangle]
pub extern "C" fn is_image_cached(a: u32, b: u32, c: u32, d: u32) -> bool {
let state = unsafe { STATE.as_mut() }.expect("Got an invalid state pointer");
let id = uuid_from_u32_quartet(a, b, c, d);
state.render_state().has_image(&id)
with_state!(state, {
let id = uuid_from_u32_quartet(a, b, c, d);
return state.render_state().has_image(&id);
});
}
#[no_mangle]
@ -324,29 +343,26 @@ pub extern "C" fn add_shape_image_fill(
width: i32,
height: i32,
) {
let state = unsafe { STATE.as_mut() }.expect("Got an invalid state pointer");
let id = uuid_from_u32_quartet(a, b, c, d);
if let Some(shape) = state.current_shape() {
with_current_shape!(state, |shape: &mut Shape| {
let id = uuid_from_u32_quartet(a, b, c, d);
shape.add_fill(shapes::Fill::new_image_fill(
id,
(alpha * 0xff as f32).floor() as u8,
(width, height),
));
}
});
}
#[no_mangle]
pub extern "C" fn clear_shape_fills() {
let state = unsafe { STATE.as_mut() }.expect("Got an invalid state pointer");
if let Some(shape) = state.current_shape() {
with_current_shape!(state, |shape: &mut Shape| {
shape.clear_fills();
}
});
}
#[no_mangle]
pub extern "C" fn set_shape_svg_raw_content() {
let state = unsafe { STATE.as_mut() }.expect("Got an invalid state pointer");
if let Some(shape) = state.current_shape() {
with_current_shape!(state, |shape: &mut Shape| {
let bytes = mem::bytes();
let svg_raw_content = String::from_utf8(bytes)
.unwrap()
@ -355,62 +371,54 @@ pub extern "C" fn set_shape_svg_raw_content() {
shape
.set_svg_raw_content(svg_raw_content)
.expect("Failed to set svg raw content");
}
});
}
#[no_mangle]
pub extern "C" fn set_shape_blend_mode(mode: i32) {
let state = unsafe { STATE.as_mut() }.expect("Got an invalid state pointer");
if let Some(shape) = state.current_shape() {
with_current_shape!(state, |shape: &mut Shape| {
shape.set_blend_mode(render::BlendMode::from(mode));
}
});
}
#[no_mangle]
pub extern "C" fn set_shape_opacity(opacity: f32) {
let state = unsafe { STATE.as_mut() }.expect("Got an invalid state pointer");
if let Some(shape) = state.current_shape() {
with_current_shape!(state, |shape: &mut Shape| {
shape.set_opacity(opacity);
}
});
}
#[no_mangle]
pub extern "C" fn set_shape_constraint_h(constraint: u8) {
let state = unsafe { STATE.as_mut() }.expect("Got an invalid state pointer");
if let Some(shape) = state.current_shape() {
shape.set_constraint_h(ConstraintH::from(constraint))
}
with_current_shape!(state, |shape: &mut Shape| {
shape.set_constraint_h(ConstraintH::from(constraint));
});
}
#[no_mangle]
pub extern "C" fn set_shape_constraint_v(constraint: u8) {
let state = unsafe { STATE.as_mut() }.expect("Got an invalid state pointer");
if let Some(shape) = state.current_shape() {
shape.set_constraint_v(ConstraintV::from(constraint))
}
with_current_shape!(state, |shape: &mut Shape| {
shape.set_constraint_v(ConstraintV::from(constraint));
});
}
#[no_mangle]
pub extern "C" fn set_shape_hidden(hidden: bool) {
let state = unsafe { STATE.as_mut() }.expect("Got an invalid state pointer");
if let Some(shape) = state.current_shape() {
with_current_shape!(state, |shape: &mut Shape| {
shape.set_hidden(hidden);
}
});
}
#[no_mangle]
pub extern "C" fn set_shape_blur(blur_type: u8, hidden: bool, value: f32) {
let state = unsafe { STATE.as_mut() }.expect("got an invalid state pointer");
if let Some(shape) = state.current_shape() {
with_current_shape!(state, |shape: &mut Shape| {
shape.set_blur(blur_type, hidden, value);
}
});
}
#[no_mangle]
pub extern "C" fn set_shape_path_content() {
let state = unsafe { STATE.as_mut() }.expect("Got an invalid state pointer");
if let Some(shape) = state.current_shape() {
with_current_shape!(state, |shape: &mut Shape| {
let bytes = mem::bytes();
let raw_segments = bytes
.chunks(size_of::<shapes::RawPathData>())
@ -419,48 +427,44 @@ pub extern "C" fn set_shape_path_content() {
})
.collect();
shape.set_path_segments(raw_segments).unwrap();
}
});
}
#[no_mangle]
pub extern "C" fn add_shape_center_stroke(width: f32, style: u8, cap_start: u8, cap_end: u8) {
let state = unsafe { STATE.as_mut() }.expect("got an invalid state pointer");
if let Some(shape) = state.current_shape() {
with_current_shape!(state, |shape: &mut Shape| {
shape.add_stroke(shapes::Stroke::new_center_stroke(
width, style, cap_start, cap_end,
));
}
});
}
#[no_mangle]
pub extern "C" fn add_shape_inner_stroke(width: f32, style: u8, cap_start: u8, cap_end: u8) {
let state = unsafe { STATE.as_mut() }.expect("got an invalid state pointer");
if let Some(shape) = state.current_shape() {
with_current_shape!(state, |shape: &mut Shape| {
shape.add_stroke(shapes::Stroke::new_inner_stroke(
width, style, cap_start, cap_end,
))
}
));
});
}
#[no_mangle]
pub extern "C" fn add_shape_outer_stroke(width: f32, style: u8, cap_start: u8, cap_end: u8) {
let state = unsafe { STATE.as_mut() }.expect("got an invalid state pointer");
if let Some(shape) = state.current_shape() {
with_current_shape!(state, |shape: &mut Shape| {
shape.add_stroke(shapes::Stroke::new_outer_stroke(
width, style, cap_start, cap_end,
))
}
));
});
}
#[no_mangle]
pub extern "C" fn add_shape_stroke_solid_fill(raw_color: u32) {
let state = unsafe { STATE.as_mut() }.expect("got an invalid state pointer");
if let Some(shape) = state.current_shape() {
with_current_shape!(state, |shape: &mut Shape| {
let color = skia::Color::new(raw_color);
shape
.set_stroke_fill(shapes::Fill::Solid(color))
.expect("could not add stroke solid fill");
}
});
}
#[no_mangle]
@ -471,8 +475,7 @@ pub extern "C" fn add_shape_stroke_linear_fill(
end_y: f32,
opacity: f32,
) {
let state = unsafe { STATE.as_mut() }.expect("got an invalid state pointer");
if let Some(shape) = state.current_shape() {
with_current_shape!(state, |shape: &mut Shape| {
shape
.set_stroke_fill(shapes::Fill::new_linear_gradient(
(start_x, start_y),
@ -480,7 +483,7 @@ pub extern "C" fn add_shape_stroke_linear_fill(
opacity,
))
.expect("could not add stroke linear fill");
}
});
}
#[no_mangle]
@ -492,8 +495,7 @@ pub extern "C" fn add_shape_stroke_radial_fill(
opacity: f32,
width: f32,
) {
let state = unsafe { STATE.as_mut() }.expect("got an invalid state pointer");
if let Some(shape) = state.current_shape() {
with_current_shape!(state, |shape: &mut Shape| {
shape
.set_stroke_fill(shapes::Fill::new_radial_gradient(
(start_x, start_y),
@ -502,7 +504,7 @@ pub extern "C" fn add_shape_stroke_radial_fill(
width,
))
.expect("could not add stroke radial fill");
}
});
}
#[no_mangle]
@ -514,13 +516,12 @@ pub extern "C" fn add_shape_stroke_stops() {
.map(|data| shapes::RawStopData::from_bytes(data.try_into().unwrap()))
.collect();
let state = unsafe { STATE.as_mut() }.expect("Got an invalid state pointer");
if let Some(shape) = state.current_shape() {
with_current_shape!(state, |shape: &mut Shape| {
shape
.add_stroke_gradient_stops(entries)
.expect("could not add gradient stops");
}
});
mem::free_bytes();
}
@ -552,9 +553,8 @@ pub extern "C" fn add_shape_image_stroke(
width: i32,
height: i32,
) {
let state = unsafe { STATE.as_mut() }.expect("got an invalid state pointer");
let id = uuid_from_u32_quartet(a, b, c, d);
if let Some(shape) = state.current_shape() {
with_current_shape!(state, |shape: &mut Shape| {
let id = uuid_from_u32_quartet(a, b, c, d);
shape
.set_stroke_fill(shapes::Fill::new_image_fill(
id,
@ -562,30 +562,26 @@ pub extern "C" fn add_shape_image_stroke(
(width, height),
))
.expect("could not add stroke image fill");
}
});
}
#[no_mangle]
pub extern "C" fn clear_shape_strokes() {
let state = unsafe { STATE.as_mut() }.expect("got an invalid state pointer");
if let Some(shape) = state.current_shape() {
with_current_shape!(state, |shape: &mut Shape| {
shape.clear_strokes();
}
});
}
#[no_mangle]
pub extern "C" fn set_shape_corners(r1: f32, r2: f32, r3: f32, r4: f32) {
let state = unsafe { STATE.as_mut() }.expect("got an invalid state pointer");
if let Some(shape) = state.current_shape() {
with_current_shape!(state, |shape: &mut Shape| {
shape.set_corners((r1, r2, r3, r4));
}
});
}
#[no_mangle]
pub extern "C" fn set_shape_path_attrs(num_attrs: u32) {
let state = unsafe { STATE.as_mut() }.expect("Got an invalid state pointer");
if let Some(shape) = state.current_shape() {
with_current_shape!(state, |shape: &mut Shape| {
let bytes = mem::bytes();
let mut start = 0;
for _ in 0..num_attrs {
@ -593,7 +589,7 @@ pub extern "C" fn set_shape_path_attrs(num_attrs: u32) {
let value = extract_string(&mut start, &bytes);
shape.set_path_attr(name, value);
}
}
});
}
#[no_mangle]
@ -632,7 +628,7 @@ pub extern "C" fn set_modifiers() {
for entry in entries {
state.modifiers.insert(entry.id, entry.transform);
}
state.render_state.clear_cache();
state.render_state().clear_cache();
}
#[no_mangle]
@ -645,21 +641,19 @@ pub extern "C" fn add_shape_shadow(
raw_style: u8,
hidden: bool,
) {
let state = unsafe { STATE.as_mut() }.expect("got an invalid state pointer");
if let Some(shape) = state.current_shape() {
with_current_shape!(state, |shape: &mut Shape| {
let color = skia::Color::new(raw_color);
let style = shapes::ShadowStyle::from(raw_style);
let shadow = shapes::Shadow::new(color, blur, spread, (x, y), style, hidden);
shape.add_shadow(shadow);
}
});
}
#[no_mangle]
pub extern "C" fn clear_shape_shadows() {
let state = unsafe { STATE.as_mut() }.expect("got an invalid state pointer");
if let Some(shape) = state.current_shape() {
with_current_shape!(state, |shape: &mut Shape| {
shape.clear_shadows();
}
});
}
#[no_mangle]
@ -684,8 +678,7 @@ pub extern "C" fn set_flex_layout_data(
let justify_content = shapes::JustifyContent::from_u8(justify_content);
let wrap_type = shapes::WrapType::from_u8(wrap_type);
let state = unsafe { STATE.as_mut() }.expect("got an invalid state pointer");
if let Some(shape) = state.current_shape() {
with_current_shape!(state, |shape: &mut Shape| {
shape.set_flex_layout_data(
dir,
row_gap,
@ -700,7 +693,7 @@ pub extern "C" fn set_flex_layout_data(
padding_bottom,
padding_left,
);
}
});
}
#[no_mangle]
@ -729,8 +722,7 @@ pub extern "C" fn set_layout_child_data(
let max_w = if has_max_w { Some(max_w) } else { None };
let min_w = if has_min_w { Some(min_w) } else { None };
let state = unsafe { STATE.as_mut() }.expect("got an invalid state pointer");
if let Some(shape) = state.current_shape() {
with_current_shape!(state, |shape: &mut Shape| {
shape.set_flex_layout_child_data(
margin_top,
margin_right,
@ -745,7 +737,7 @@ pub extern "C" fn set_layout_child_data(
is_absolute,
z_index,
);
}
});
}
#[no_mangle]