diff --git a/common/src/app/common/types/path.cljc b/common/src/app/common/types/path.cljc index 7007d08cb2..b47eca63c0 100644 --- a/common/src/app/common/types/path.cljc +++ b/common/src/app/common/types/path.cljc @@ -234,16 +234,15 @@ "Calculate the boolean content from shape and objects. Returns a packed PathData instance" [shape objects] - (let [content (if (fn? wasm:calc-bool-content) - (wasm:calc-bool-content (get shape :bool-type) - (get shape :shapes)) - (calc-bool-content* shape objects))] + (let [content (calc-bool-content* shape objects)] (impl/path-data content))) (defn update-bool-shape "Calculates the selrect+points for the boolean shape" [shape objects] - (let [content (calc-bool-content shape objects) + (let [content (if (fn? wasm:calc-bool-content) + (wasm:calc-bool-content shape objects) + (calc-bool-content shape objects)) shape (assoc shape :content content)] (update-geometry shape))) diff --git a/frontend/src/app/render_wasm/api.cljs b/frontend/src/app/render_wasm/api.cljs index fe5bf50b85..7c4c533aaa 100644 --- a/frontend/src/app/render_wasm/api.cljs +++ b/frontend/src/app/render_wasm/api.cljs @@ -1297,12 +1297,7 @@ (mem/free) content)) -(defn- calculate-bool* - [bool-type] - (-> (h/call wasm/internal-module "_calculate_bool" (sr/translate-bool-type bool-type)) - (mem/->offset-32))) - -(defn calculate-bool +(defn calculate-bool* [bool-type ids] (let [size (mem/get-alloc-size ids UUID-U8-SIZE) heap (mem/get-heap-u32) @@ -1313,7 +1308,10 @@ offset (rseq ids)) - (let [offset (calculate-bool* bool-type) + (let [offset + (-> (h/call wasm/internal-module "_calculate_bool" (sr/translate-bool-type bool-type)) + (mem/->offset-32)) + length (aget heap offset) data (mem/slice heap (+ offset 1) @@ -1322,6 +1320,29 @@ (mem/free) content))) +(defn calculate-bool + [shape objects] + + ;; We need to be able to calculate the boolean data but we cannot + ;; depend on the serialization flow. + ;; start_temp_object / end_temp_object create a new shapes_pool + ;; temporary and then we serialize the objects needed to calculate the + ;; boolean object. + ;; After the content is returned we discard that temporary context + (h/call wasm/internal-module "_start_temp_objects") + + (let [bool-type (get shape :bool-type) + ids (get shape :shapes) + all-children + (->> ids + (mapcat #(cfh/get-children-with-self objects %)))] + (h/call wasm/internal-module "_init_shapes_pool" (count all-children)) + (run! (partial set-object objects) all-children) + + (let [content (-> (calculate-bool* bool-type ids) + (path.impl/path-data))] + (h/call wasm/internal-module "_end_temp_objects") + content))) (defn init-wasm-module [module] diff --git a/render-wasm/src/main.rs b/render-wasm/src/main.rs index a5d0bb0822..38b7413817 100644 --- a/render-wasm/src/main.rs +++ b/render-wasm/src/main.rs @@ -655,6 +655,26 @@ pub extern "C" fn set_modifiers() { }); } +#[no_mangle] +pub extern "C" fn start_temp_objects() { + unsafe { + #[allow(static_mut_refs)] + let mut state = STATE.take().expect("Got an invalid state pointer"); + state = Box::new(state.start_temp_objects()); + STATE = Some(state); + } +} + +#[no_mangle] +pub extern "C" fn end_temp_objects() { + unsafe { + #[allow(static_mut_refs)] + let mut state = STATE.take().expect("Got an invalid state pointer"); + state = Box::new(state.end_temp_objects()); + STATE = Some(state); + } +} + fn main() { #[cfg(target_arch = "wasm32")] init_gl!(); diff --git a/render-wasm/src/state.rs b/render-wasm/src/state.rs index 4257ab6da8..5e48cea05e 100644 --- a/render-wasm/src/state.rs +++ b/render-wasm/src/state.rs @@ -24,6 +24,7 @@ pub(crate) struct State<'a> { pub current_id: Option, pub current_browser: u8, pub shapes: ShapesPool<'a>, + pub saved_shapes: Option>, } impl<'a> State<'a> { @@ -34,9 +35,32 @@ impl<'a> State<'a> { current_id: None, current_browser: 0, shapes: ShapesPool::new(), + // TODO: Maybe this can be moved to a different object + saved_shapes: None, } } + // Creates a new temporary shapes pool. + // Will panic if a previous temporary pool exists. + pub fn start_temp_objects(mut self) -> Self { + if self.saved_shapes.is_some() { + panic!("Tried to start a temp objects while the previous have not been restored"); + } + self.saved_shapes = Some(self.shapes); + self.shapes = ShapesPool::new(); + self + } + + // Disposes of the temporary shapes pool restoring the normal pool + // Will panic if a there is no temporary pool. + pub fn end_temp_objects(mut self) -> Self { + self.shapes = self + .saved_shapes + .expect("Tried to end temp objects but not content to be restored is present"); + self.saved_shapes = None; + self + } + pub fn resize(&mut self, width: i32, height: i32) { self.render_state.resize(width, height); }