diff --git a/frontend/src/app/render_wasm/api.cljs b/frontend/src/app/render_wasm/api.cljs index 3fc36ccce..9e37c4322 100644 --- a/frontend/src/app/render_wasm/api.cljs +++ b/frontend/src/app/render_wasm/api.cljs @@ -242,24 +242,11 @@ (sr-fills/serialize-linear-fill gradient opacity heap offset) (h/call wasm/internal-module "_add_shape_linear_fill")) :radial - (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) - mem (js/Uint8Array. (.-buffer heap) offset size)] - (h/call wasm/internal-module "_add_shape_radial_fill" - (:start-x gradient) - (:start-y gradient) - (:end-x gradient) - (:end-y gradient) - opacity - (:width gradient)) - (.set mem (js/Uint8Array. (clj->js (flatten (map (fn [stop] - (let [[r g b a] (sr-clr/rgba-bytes-from-hex (:color stop) (:opacity stop)) - offset (:offset stop)] - [r g b a (* 100 offset)])) - stops))))) - (h/call wasm/internal-module "_add_shape_fill_stops"))) + heap (mem/get-heap-u32)] + (sr-fills/serialize-radial-fill gradient opacity heap offset) + (h/call wasm/internal-module "_add_shape_radial_fill"))) (some? image) (let [id (dm/get-prop image :id) @@ -301,13 +288,15 @@ size (gradient-stop-get-entries-size stops) offset (mem/alloc-bytes size) heap (mem/get-heap-u8)] - (if (= (:type gradient) :linear) + (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) + :radial (h/call wasm/internal-module "_add_shape_stroke_radial_fill" (:start-x gradient) (:start-y gradient) diff --git a/frontend/src/app/render_wasm/serializers/fills.cljs b/frontend/src/app/render_wasm/serializers/fills.cljs index d92079459..cada7416a 100644 --- a/frontend/src/app/render_wasm/serializers/fills.cljs +++ b/frontend/src/app/render_wasm/serializers/fills.cljs @@ -35,4 +35,21 @@ (.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 diff --git a/render-wasm/src/main.rs b/render-wasm/src/main.rs index d37088b10..66e5961ec 100644 --- a/render-wasm/src/main.rs +++ b/render-wasm/src/main.rs @@ -282,20 +282,26 @@ pub extern "C" fn add_shape_linear_fill() { } #[no_mangle] -pub extern "C" fn add_shape_radial_fill( - start_x: f32, - start_y: f32, - end_x: f32, - end_y: f32, - opacity: f32, - width: f32, -) { +pub extern "C" fn add_shape_radial_fill() { 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, + 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.add_fill(shapes::Fill::new_radial_gradient_with_stops( + raw_gradient.start(), + raw_gradient.end(), + raw_gradient.opacity(), + raw_gradient.width(), + stops, )); }); } diff --git a/render-wasm/src/shapes/fills.rs b/render-wasm/src/shapes/fills.rs index 370d049fa..f19cd107a 100644 --- a/render-wasm/src/shapes/fills.rs +++ b/render-wasm/src/shapes/fills.rs @@ -41,6 +41,10 @@ impl RawGradientData { pub fn opacity(&self) -> f32 { self.opacity } + + pub fn width(&self) -> f32 { + self.width + } } pub const RAW_STOP_DATA_SIZE: usize = 8; @@ -199,14 +203,30 @@ impl Fill { opacity: f32, width: f32, ) -> Self { - Self::RadialGradient(Gradient { + Self::new_radial_gradient_with_stops(start, end, opacity, width, vec![]) + } + + pub fn new_radial_gradient_with_stops( + start: (f32, f32), + end: (f32, f32), + opacity: f32, + width: f32, + stops: Vec, + ) -> Self { + let mut gradient = Gradient { start, end, opacity, colors: vec![], offsets: vec![], width, - }) + }; + + for stop in stops { + gradient.add_stop(stop.color(), stop.offset()); + } + + Self::RadialGradient(gradient) } pub fn new_image_fill(id: Uuid, opacity: u8, (width, height): (i32, i32)) -> Self {