diff --git a/render-wasm/src/main.rs b/render-wasm/src/main.rs index 259fdd8c0..3e09e3d7d 100644 --- a/render-wasm/src/main.rs +++ b/render-wasm/src/main.rs @@ -16,10 +16,7 @@ mod wapi; mod wasm; use crate::mem::SerializableResult; -use crate::shapes::{ - BoolType, ConstraintH, ConstraintV, StructureEntry, TransformEntry, Type, RAW_FILL_DATA_SIZE, - RAW_STOP_DATA_SIZE, -}; +use crate::shapes::{BoolType, ConstraintH, ConstraintV, StructureEntry, TransformEntry, Type}; use crate::utils::uuid_from_u32_quartet; use crate::uuid::Uuid; use indexmap::IndexSet; @@ -261,23 +258,8 @@ pub extern "C" fn add_shape_solid_fill(raw_color: u32) { pub extern "C" fn add_shape_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.add_fill(shapes::Fill::new_linear_gradient_with_stops( - raw_gradient.start(), - raw_gradient.end(), - raw_gradient.opacity(), - stops, - )); + let gradient = shapes::Gradient::try_from(&bytes[..]).expect("Invalid gradient data"); + shape.add_fill(shapes::Fill::LinearGradient(gradient)); }); } @@ -285,48 +267,11 @@ pub extern "C" fn add_shape_linear_fill() { pub extern "C" fn add_shape_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.add_fill(shapes::Fill::new_radial_gradient_with_stops( - raw_gradient.start(), - raw_gradient.end(), - raw_gradient.opacity(), - raw_gradient.width(), - stops, - )); + let gradient = shapes::Gradient::try_from(&bytes[..]).expect("Invalid gradient data"); + shape.add_fill(shapes::Fill::RadialGradient(gradient)); }); } -#[no_mangle] -pub extern "C" fn add_shape_fill_stops() { - let bytes = mem::bytes(); - - let entries: Vec<_> = bytes - .chunks(size_of::()) - .map(|data| { - let raw_stop_bytes: [u8; RAW_STOP_DATA_SIZE] = data.try_into().unwrap(); - shapes::RawStopData::from(raw_stop_bytes) - }) - .collect(); - - 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_image(a: u32, b: u32, c: u32, d: u32) { with_state!(state, { @@ -490,24 +435,10 @@ pub extern "C" fn add_shape_stroke_solid_fill(raw_color: u32) { 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(); + let gradient = shapes::Gradient::try_from(&bytes[..]).expect("Invalid gradient data"); shape - .set_stroke_fill(shapes::Fill::new_linear_gradient_with_stops( - raw_gradient.start(), - raw_gradient.end(), - raw_gradient.opacity(), - stops, - )) + .set_stroke_fill(shapes::Fill::LinearGradient(gradient)) .expect("could not add stroke linear gradient fill"); }); } @@ -516,50 +447,14 @@ pub extern "C" fn add_shape_stroke_linear_fill() { 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(); + let gradient = shapes::Gradient::try_from(&bytes[..]).expect("Invalid gradient data"); shape - .set_stroke_fill(shapes::Fill::new_radial_gradient_with_stops( - raw_gradient.start(), - raw_gradient.end(), - raw_gradient.opacity(), - raw_gradient.width(), - stops, - )) + .set_stroke_fill(shapes::Fill::RadialGradient(gradient)) .expect("could not add stroke radial gradient fill"); }); } -#[no_mangle] -pub extern "C" fn add_shape_stroke_stops() { - let bytes = mem::bytes(); - - let entries: Vec<_> = bytes - .chunks(size_of::()) - .map(|data| { - let raw_stop_bytes: [u8; RAW_STOP_DATA_SIZE] = data.try_into().unwrap(); - shapes::RawStopData::from(raw_stop_bytes) - }) - .collect(); - - with_current_shape!(state, |shape: &mut Shape| { - shape - .add_stroke_gradient_stops(entries) - .expect("could not add gradient stops"); - }); - - mem::free_bytes(); -} - // Extracts a string from the bytes slice until the next null byte (0) and returns the result as a `String`. // Updates the `start` index to the end of the extracted string. fn extract_string(start: &mut usize, bytes: &[u8]) -> String { diff --git a/render-wasm/src/shapes.rs b/render-wasm/src/shapes.rs index ac13d7f37..5b44806b8 100644 --- a/render-wasm/src/shapes.rs +++ b/render-wasm/src/shapes.rs @@ -456,21 +456,6 @@ impl Shape { self.fills.clear(); } - pub fn add_fill_gradient_stops(&mut self, buffer: Vec) -> Result<(), String> { - let fill = self.fills.last_mut().ok_or("Shape has no fills")?; - let gradient = match fill { - Fill::LinearGradient(g) => Ok(g), - Fill::RadialGradient(g) => Ok(g), - _ => Err("Active fill is not a gradient"), - }?; - - for stop in buffer.into_iter() { - gradient.add_stop(stop.color(), stop.offset()); - } - - Ok(()) - } - pub fn strokes(&self) -> std::slice::Iter { self.strokes.iter() } @@ -485,22 +470,6 @@ impl Shape { Ok(()) } - pub fn add_stroke_gradient_stops(&mut self, buffer: Vec) -> Result<(), String> { - let stroke = self.strokes.last_mut().ok_or("Shape has no strokes")?; - let fill = &mut stroke.fill; - let gradient = match fill { - Fill::LinearGradient(g) => Ok(g), - Fill::RadialGradient(g) => Ok(g), - _ => Err("Active stroke is not a gradient"), - }?; - - for stop in buffer.into_iter() { - gradient.add_stop(stop.color(), stop.offset()); - } - - Ok(()) - } - pub fn clear_strokes(&mut self) { self.strokes.clear(); } diff --git a/render-wasm/src/shapes/fills.rs b/render-wasm/src/shapes/fills.rs index 3fb126e4d..78bbff701 100644 --- a/render-wasm/src/shapes/fills.rs +++ b/render-wasm/src/shapes/fills.rs @@ -144,6 +144,42 @@ impl Gradient { } } +impl TryFrom<&[u8]> for Gradient { + type Error = String; + + fn try_from(bytes: &[u8]) -> Result { + let raw_gradient_bytes: [u8; RAW_FILL_DATA_SIZE] = bytes[0..RAW_FILL_DATA_SIZE] + .try_into() + .map_err(|_| "Invalid gradient data".to_string())?; + + let raw_gradient = 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() + .map_err(|_| "Invalid stop data".to_string())?; + Ok(RawStopData::from(data)) + }) + .collect::, Self::Error>>()?; + + let mut gradient = Gradient { + start: raw_gradient.start(), + end: raw_gradient.end(), + opacity: raw_gradient.opacity(), + colors: vec![], + offsets: vec![], + width: raw_gradient.width(), + }; + + for stop in stops { + gradient.add_stop(stop.color(), stop.offset()); + } + + Ok(gradient) + } +} + #[derive(Debug, Clone, PartialEq)] pub struct ImageFill { id: Uuid, @@ -171,51 +207,6 @@ pub enum Fill { } impl Fill { - pub fn new_linear_gradient_with_stops( - start: (f32, f32), - end: (f32, f32), - opacity: f32, - stops: Vec, - ) -> Self { - let mut gradient = Gradient { - start, - end, - opacity, - colors: vec![], - offsets: vec![], - width: 0., - }; - - for stop in stops { - gradient.add_stop(stop.color(), stop.offset()); - } - - Self::LinearGradient(gradient) - } - - 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 { Self::Image(ImageFill { id,