diff --git a/frontend/src/app/render_wasm/api.cljs b/frontend/src/app/render_wasm/api.cljs index 3882dc245..f6b895b55 100644 --- a/frontend/src/app/render_wasm/api.cljs +++ b/frontend/src/app/render_wasm/api.cljs @@ -211,6 +211,14 @@ (store-image id)))))) fills)) +(defn- translate-stroke-style + [stroke-style] + (case stroke-style + :dotted 1 + :dashed 2 + :mixed 3 + 0)) + (defn set-shape-strokes [strokes] (h/call internal-module "_clear_shape_strokes") @@ -220,11 +228,12 @@ gradient (:stroke-color-gradient stroke) image (:stroke-image stroke) width (:stroke-width stroke) - align (:stroke-alignment stroke)] + align (:stroke-alignment stroke) + style (-> stroke :stroke-style translate-stroke-style)] (case align - :inner (h/call internal-module "_add_shape_inner_stroke" width) - :outer (h/call internal-module "_add_shape_outer_stroke" width) - (h/call internal-module "_add_shape_center_stroke" width)) + :inner (h/call internal-module "_add_shape_inner_stroke" width style) + :outer (h/call internal-module "_add_shape_outer_stroke" width style) + (h/call internal-module "_add_shape_center_stroke" width style)) (cond (some? gradient) diff --git a/render-wasm/src/main.rs b/render-wasm/src/main.rs index fbf52c665..4911dff18 100644 --- a/render-wasm/src/main.rs +++ b/render-wasm/src/main.rs @@ -347,26 +347,26 @@ pub extern "C" fn set_shape_path_content() { } #[no_mangle] -pub extern "C" fn add_shape_center_stroke(width: f32) { +pub extern "C" fn add_shape_center_stroke(width: f32, style: i32) { let state = unsafe { STATE.as_mut() }.expect("got an invalid state pointer"); if let Some(shape) = state.current_shape() { - shape.add_stroke(shapes::Stroke::new_center_stroke(width)) + shape.add_stroke(shapes::Stroke::new_center_stroke(width, style)); } } #[no_mangle] -pub extern "C" fn add_shape_inner_stroke(width: f32) { +pub extern "C" fn add_shape_inner_stroke(width: f32, style: i32) { let state = unsafe { STATE.as_mut() }.expect("got an invalid state pointer"); if let Some(shape) = state.current_shape() { - shape.add_stroke(shapes::Stroke::new_inner_stroke(width)) + shape.add_stroke(shapes::Stroke::new_inner_stroke(width, style)) } } #[no_mangle] -pub extern "C" fn add_shape_outer_stroke(width: f32) { +pub extern "C" fn add_shape_outer_stroke(width: f32, style: i32) { let state = unsafe { STATE.as_mut() }.expect("got an invalid state pointer"); if let Some(shape) = state.current_shape() { - shape.add_stroke(shapes::Stroke::new_outer_stroke(width)) + shape.add_stroke(shapes::Stroke::new_outer_stroke(width, style)) } } diff --git a/render-wasm/src/shapes/strokes.rs b/render-wasm/src/shapes/strokes.rs index a4bef5a72..2eec2293b 100644 --- a/render-wasm/src/shapes/strokes.rs +++ b/render-wasm/src/shapes/strokes.rs @@ -5,9 +5,20 @@ use skia_safe as skia; #[derive(Debug, Clone, PartialEq)] pub enum StrokeStyle { Solid, - // Dotted, - // Dashed, - // Mixed, + Dotted, + Dashed, + Mixed, +} + +impl From for StrokeStyle { + fn from(value: i32) -> Self { + match value { + 1 => StrokeStyle::Dotted, + 2 => StrokeStyle::Dashed, + 3 => StrokeStyle::Mixed, + _ => StrokeStyle::Solid, + } + } } #[derive(Debug, Clone, PartialEq)] @@ -39,36 +50,36 @@ pub struct Stroke { } impl Stroke { - pub fn new_center_stroke(width: f32) -> Self { + pub fn new_center_stroke(width: f32, style: i32) -> Self { let transparent = skia::Color::from_argb(0, 0, 0, 0); Stroke { fill: Fill::Solid(transparent), width: width, - style: StrokeStyle::Solid, + style: StrokeStyle::from(style), cap_end: StrokeCap::None, cap_start: StrokeCap::None, kind: StrokeKind::CenterStroke, } } - pub fn new_inner_stroke(width: f32) -> Self { + pub fn new_inner_stroke(width: f32, style: i32) -> Self { let transparent = skia::Color::from_argb(0, 0, 0, 0); Stroke { fill: Fill::Solid(transparent), width: width, - style: StrokeStyle::Solid, + style: StrokeStyle::from(style), cap_end: StrokeCap::None, cap_start: StrokeCap::None, kind: StrokeKind::InnerStroke, } } - pub fn new_outer_stroke(width: f32) -> Self { + pub fn new_outer_stroke(width: f32, style: i32) -> Self { let transparent = skia::Color::from_argb(0, 0, 0, 0); Stroke { fill: Fill::Solid(transparent), width: width, - style: StrokeStyle::Solid, + style: StrokeStyle::from(style), cap_end: StrokeCap::None, cap_start: StrokeCap::None, kind: StrokeKind::OuterStroke, @@ -108,6 +119,37 @@ impl Stroke { paint.set_style(skia::PaintStyle::Stroke); paint.set_stroke_width(self.width); paint.set_anti_alias(true); + + if self.style != StrokeStyle::Solid { + let path_effect = match self.style { + StrokeStyle::Dotted => { + let mut circle_path = skia::Path::new(); + circle_path.add_circle((0.0, 0.0), self.width / 2.0, None); + let advance = self.width + 5.0; + skia::PathEffect::path_1d( + &circle_path, + advance, + 0.0, + skia::path_1d_path_effect::Style::Translate, + ) + } + StrokeStyle::Dashed => { + skia::PathEffect::dash(&[self.width + 10., self.width + 10.], 0.) + } + StrokeStyle::Mixed => skia::PathEffect::dash( + &[ + self.width + 5., + self.width + 5., + self.width + 1., + self.width + 5., + ], + 0., + ), + _ => None, + }; + paint.set_path_effect(path_effect); + } + paint }