From 1f58f96e88a89f5417f958c3d168b6a3c0137d1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bel=C3=A9n=20Albeza?= Date: Tue, 15 Apr 2025 12:16:40 +0200 Subject: [PATCH] :recycle: Refactor serializing gradient fill --- frontend/src/app/render_wasm/api.cljs | 43 ++++-------- .../app/render_wasm/serializers/fills.cljs | 56 +++++----------- render-wasm/src/main.rs | 65 +++++++++++-------- render-wasm/src/shapes/fills.rs | 13 ---- 4 files changed, 69 insertions(+), 108 deletions(-) diff --git a/frontend/src/app/render_wasm/api.cljs b/frontend/src/app/render_wasm/api.cljs index 9e37c4322..44321c28e 100644 --- a/frontend/src/app/render_wasm/api.cljs +++ b/frontend/src/app/render_wasm/api.cljs @@ -234,18 +234,14 @@ (h/call wasm/internal-module "_add_shape_solid_fill" rgba)) (some? gradient) - (case (:type gradient) - :linear - (let [size (gradient-byte-size gradient) - offset (mem/alloc-bytes size) - heap (mem/get-heap-u32)] - (sr-fills/serialize-linear-fill gradient opacity heap offset) - (h/call wasm/internal-module "_add_shape_linear_fill")) - :radial - (let [size (gradient-byte-size gradient) - offset (mem/alloc-bytes size) - heap (mem/get-heap-u32)] - (sr-fills/serialize-radial-fill gradient opacity heap offset) + (let [size (gradient-byte-size gradient) + offset (mem/alloc-bytes size) + heap (mem/get-heap-u32)] + (sr-fills/serialize-gradient-fill gradient opacity heap offset) + (case (:type gradient) + :linear + (h/call wasm/internal-module "_add_shape_linear_fill") + :radial (h/call wasm/internal-module "_add_shape_radial_fill"))) (some? image) @@ -284,28 +280,15 @@ (cond (some? gradient) - (let [stops (:stops gradient) - size (gradient-stop-get-entries-size stops) + (let [size (gradient-byte-size gradient) offset (mem/alloc-bytes size) - heap (mem/get-heap-u8)] + heap (mem/get-heap-u32)] + (sr-fills/serialize-gradient-fill gradient opacity heap offset) (case (:type gradient) :linear - (h/call wasm/internal-module "_add_shape_stroke_linear_fill" - (:start-x gradient) - (:start-y gradient) - (:end-x gradient) - (:end-y gradient) - opacity) + (h/call wasm/internal-module "_add_shape_stroke_linear_fill") :radial - (h/call wasm/internal-module "_add_shape_stroke_radial_fill" - (:start-x gradient) - (:start-y gradient) - (:end-x gradient) - (:end-y gradient) - opacity - (:width gradient))) - (sr-fills/serialize-gradient-stops stops heap offset) - (h/call wasm/internal-module "_add_shape_stroke_stops")) + (h/call wasm/internal-module "_add_shape_stroke_radial_fill"))) (some? image) (let [id (dm/get-prop image :id) diff --git a/frontend/src/app/render_wasm/serializers/fills.cljs b/frontend/src/app/render_wasm/serializers/fills.cljs index cada7416a..cbcbb5b59 100644 --- a/frontend/src/app/render_wasm/serializers/fills.cljs +++ b/frontend/src/app/render_wasm/serializers/fills.cljs @@ -6,10 +6,22 @@ (def GRADIENT-STOP-SIZE 8) (def GRADIENT-BASE-SIZE 24) -(defn serialize-gradient-stops - [stops heap offset] - (let [dview (js/DataView. (.-buffer heap))] - (loop [stops (seq stops) offset offset] +(defn serialize-gradient-fill + [gradient opacity heap offset] + (let [dview (js/DataView. (.-buffer heap)) + start-x (dm/get-prop gradient :start-x) + start-y (dm/get-prop gradient :start-y) + end-x (dm/get-prop gradient :end-x) + end-y (dm/get-prop gradient :end-y) + width (or (dm/get-prop gradient :width) 0) + stops (dm/get-prop gradient :stops)] + (.setFloat32 dview offset start-x true) + (.setFloat32 dview (+ offset 4) start-y true) + (.setFloat32 dview (+ offset 8) end-x true) + (.setFloat32 dview (+ offset 12) end-y true) + (.setFloat32 dview (+ offset 16) opacity true) + (.setFloat32 dview (+ offset 20) width true) + (loop [stops (seq stops) offset (+ offset GRADIENT-BASE-SIZE)] (when-not (empty? stops) (let [stop (first stops) hex-color (dm/get-prop stop :color) @@ -18,38 +30,4 @@ stop-offset (dm/get-prop stop :offset)] (.setUint32 dview offset argb true) (.setFloat32 dview (+ offset 4) stop-offset true) - (recur (rest stops) (+ offset GRADIENT-STOP-SIZE))))))) - -(defn serialize-linear-fill - [gradient opacity heap offset] - (let [dview (js/DataView. (.-buffer heap)) - start-x (dm/get-prop gradient :start-x) - start-y (dm/get-prop gradient :start-y) - end-x (dm/get-prop gradient :end-x) - end-y (dm/get-prop gradient :end-y) - stops (dm/get-prop gradient :stops) - width 0] - (.setFloat32 dview offset start-x true) - (.setFloat32 dview (+ offset 4) start-y true) - (.setFloat32 dview (+ offset 8) end-x true) - (.setFloat32 dview (+ offset 12) end-y true) - (.setFloat32 dview (+ offset 16) opacity true) - (.setFloat32 dview (+ offset 20) width true) - (serialize-gradient-stops stops heap (+ offset GRADIENT-BASE-SIZE)))) - -(defn serialize-radial-fill - [gradient opacity heap offset] - (let [dview (js/DataView. (.-buffer heap)) - start-x (dm/get-prop gradient :start-x) - start-y (dm/get-prop gradient :start-y) - end-x (dm/get-prop gradient :end-x) - end-y (dm/get-prop gradient :end-y) - stops (dm/get-prop gradient :stops) - width (dm/get-prop gradient :width)] - (.setFloat32 dview offset start-x true) - (.setFloat32 dview (+ offset 4) start-y true) - (.setFloat32 dview (+ offset 8) end-x true) - (.setFloat32 dview (+ offset 12) end-y true) - (.setFloat32 dview (+ offset 16) opacity true) - (.setFloat32 dview (+ offset 20) width true) - (serialize-gradient-stops stops heap (+ offset GRADIENT-BASE-SIZE)))) \ No newline at end of file + (recur (rest stops) (+ offset GRADIENT-STOP-SIZE))))))) \ No newline at end of file diff --git a/render-wasm/src/main.rs b/render-wasm/src/main.rs index 66e5961ec..259fdd8c0 100644 --- a/render-wasm/src/main.rs +++ b/render-wasm/src/main.rs @@ -487,42 +487,55 @@ pub extern "C" fn add_shape_stroke_solid_fill(raw_color: u32) { } #[no_mangle] -pub extern "C" fn add_shape_stroke_linear_fill( - start_x: f32, - start_y: f32, - end_x: f32, - end_y: f32, - opacity: f32, -) { +pub extern "C" fn add_shape_stroke_linear_fill() { with_current_shape!(state, |shape: &mut Shape| { + let bytes = mem::bytes(); + let raw_gradient_bytes: [u8; RAW_FILL_DATA_SIZE] = + bytes[0..RAW_FILL_DATA_SIZE].try_into().unwrap(); + let raw_gradient = shapes::RawGradientData::from(raw_gradient_bytes); + let stops: Vec = bytes[RAW_FILL_DATA_SIZE..] + .chunks(RAW_STOP_DATA_SIZE) + .map(|chunk| { + let data: [u8; RAW_STOP_DATA_SIZE] = chunk.try_into().unwrap(); + shapes::RawStopData::from(data) + }) + .collect(); + shape - .set_stroke_fill(shapes::Fill::new_linear_gradient( - (start_x, start_y), - (end_x, end_y), - opacity, + .set_stroke_fill(shapes::Fill::new_linear_gradient_with_stops( + raw_gradient.start(), + raw_gradient.end(), + raw_gradient.opacity(), + stops, )) - .expect("could not add stroke linear fill"); + .expect("could not add stroke linear gradient fill"); }); } #[no_mangle] -pub extern "C" fn add_shape_stroke_radial_fill( - start_x: f32, - start_y: f32, - end_x: f32, - end_y: f32, - opacity: f32, - width: f32, -) { +pub extern "C" fn add_shape_stroke_radial_fill() { with_current_shape!(state, |shape: &mut Shape| { + let bytes = mem::bytes(); + let raw_gradient_bytes: [u8; RAW_FILL_DATA_SIZE] = + bytes[0..RAW_FILL_DATA_SIZE].try_into().unwrap(); + let raw_gradient = shapes::RawGradientData::from(raw_gradient_bytes); + let stops: Vec = bytes[RAW_FILL_DATA_SIZE..] + .chunks(RAW_STOP_DATA_SIZE) + .map(|chunk| { + let data: [u8; RAW_STOP_DATA_SIZE] = chunk.try_into().unwrap(); + shapes::RawStopData::from(data) + }) + .collect(); + shape - .set_stroke_fill(shapes::Fill::new_radial_gradient( - (start_x, start_y), - (end_x, end_y), - opacity, - width, + .set_stroke_fill(shapes::Fill::new_radial_gradient_with_stops( + raw_gradient.start(), + raw_gradient.end(), + raw_gradient.opacity(), + raw_gradient.width(), + stops, )) - .expect("could not add stroke radial fill"); + .expect("could not add stroke radial gradient fill"); }); } diff --git a/render-wasm/src/shapes/fills.rs b/render-wasm/src/shapes/fills.rs index f19cd107a..3fb126e4d 100644 --- a/render-wasm/src/shapes/fills.rs +++ b/render-wasm/src/shapes/fills.rs @@ -171,10 +171,6 @@ pub enum Fill { } impl Fill { - pub fn new_linear_gradient(start: (f32, f32), end: (f32, f32), opacity: f32) -> Self { - Self::new_linear_gradient_with_stops(start, end, opacity, vec![]) - } - pub fn new_linear_gradient_with_stops( start: (f32, f32), end: (f32, f32), @@ -197,15 +193,6 @@ impl Fill { Self::LinearGradient(gradient) } - pub fn new_radial_gradient( - start: (f32, f32), - end: (f32, f32), - opacity: f32, - width: f32, - ) -> Self { - Self::new_radial_gradient_with_stops(start, end, opacity, width, vec![]) - } - pub fn new_radial_gradient_with_stops( start: (f32, f32), end: (f32, f32),