diff --git a/render-wasm/src/render.rs b/render-wasm/src/render.rs index 35d017d49..94d848eb6 100644 --- a/render-wasm/src/render.rs +++ b/render-wasm/src/render.rs @@ -210,43 +210,35 @@ impl RenderState { } pub fn apply_drawing_to_render_canvas(&mut self, shape: Option<&Shape>) { - self.surfaces - .flush_and_submit(&mut self.gpu_state, SurfaceId::Fills); - self.surfaces .flush_and_submit(&mut self.gpu_state, SurfaceId::DropShadows); - self.surfaces - .flush_and_submit(&mut self.gpu_state, SurfaceId::InnerShadows); - self.surfaces.draw_into( SurfaceId::DropShadows, SurfaceId::Current, Some(&skia::Paint::default()), ); + self.surfaces + .flush_and_submit(&mut self.gpu_state, SurfaceId::Fills); + self.surfaces.draw_into( SurfaceId::Fills, SurfaceId::Current, Some(&skia::Paint::default()), ); - self.surfaces.draw_into( - SurfaceId::InnerShadows, - SurfaceId::Current, - Some(&skia::Paint::default()), - ); - let mut render_overlay_below_strokes = false; if let Some(shape) = shape { - render_overlay_below_strokes = shape.fills().len() > 0; + render_overlay_below_strokes = shape.has_fills(); } if render_overlay_below_strokes { self.surfaces - .flush_and_submit(&mut self.gpu_state, SurfaceId::Overlay); + .flush_and_submit(&mut self.gpu_state, SurfaceId::InnerShadows); + self.surfaces.draw_into( - SurfaceId::Overlay, + SurfaceId::InnerShadows, SurfaceId::Current, Some(&skia::Paint::default()), ); @@ -254,6 +246,7 @@ impl RenderState { self.surfaces .flush_and_submit(&mut self.gpu_state, SurfaceId::Strokes); + self.surfaces.draw_into( SurfaceId::Strokes, SurfaceId::Current, @@ -262,25 +255,22 @@ impl RenderState { if !render_overlay_below_strokes { self.surfaces - .flush_and_submit(&mut self.gpu_state, SurfaceId::Overlay); + .flush_and_submit(&mut self.gpu_state, SurfaceId::InnerShadows); + self.surfaces.draw_into( - SurfaceId::Overlay, + SurfaceId::InnerShadows, SurfaceId::Current, Some(&skia::Paint::default()), ); } - self.surfaces - .draw_into(SurfaceId::Overlay, SurfaceId::Current, None); self.surfaces .flush_and_submit(&mut self.gpu_state, SurfaceId::Current); self.surfaces.apply_mut( &[ - SurfaceId::Shadow, - SurfaceId::InnerShadows, SurfaceId::DropShadows, - SurfaceId::Overlay, + SurfaceId::InnerShadows, SurfaceId::Fills, SurfaceId::Strokes, ], @@ -400,11 +390,13 @@ impl RenderState { } for stroke in shape.strokes().rev() { - strokes::render(self, &shape, stroke, antialias); + shadows::render_stroke_drop_shadows(self, &shape, stroke, antialias); + strokes::render(self, &shape, stroke, None, None, antialias); + shadows::render_stroke_inner_shadows(self, &shape, stroke, antialias); } - shadows::render_inner_shadows(self, &shape, antialias); - shadows::render_drop_shadows(self, &shape, antialias); + shadows::render_fill_inner_shadows(self, &shape, antialias); + shadows::render_fill_drop_shadows(self, &shape, antialias); } }; diff --git a/render-wasm/src/render/shadows.rs b/render-wasm/src/render/shadows.rs index 4b9ab2ed4..b61dea596 100644 --- a/render-wasm/src/render/shadows.rs +++ b/render-wasm/src/render/shadows.rs @@ -1,18 +1,14 @@ use super::{RenderState, SurfaceId}; -use crate::shapes::{Shadow, Shape, Type}; -use skia_safe::{self as skia, Paint}; +use crate::render::strokes; +use crate::shapes::{Shadow, Shape, Stroke, Type}; +use skia_safe::Paint; -// Drop Shadows -pub fn render_drop_shadows(render_state: &mut RenderState, shape: &Shape, antialias: bool) { +// Fill Shadows +pub fn render_fill_drop_shadows(render_state: &mut RenderState, shape: &Shape, antialias: bool) { if shape.has_fills() { for shadow in shape.drop_shadows().rev().filter(|s| !s.hidden()) { render_fill_drop_shadow(render_state, &shape, &shadow, antialias); } - } else { - let scale = render_state.get_scale(); - for shadow in shape.drop_shadows().rev().filter(|s| !s.hidden()) { - render_stroke_drop_shadow(render_state, &shadow, scale, antialias); - } } } @@ -26,42 +22,11 @@ fn render_fill_drop_shadow( render_shadow_paint(render_state, shape, paint, SurfaceId::DropShadows); } -// TODO: Stroke shadows -fn render_stroke_drop_shadow( - render_state: &mut RenderState, - shadow: &Shadow, - scale: f32, - antialias: bool, -) { - let shadow_paint = &shadow.to_paint(scale, antialias); - - render_state - .surfaces - .draw_into(SurfaceId::Strokes, SurfaceId::Shadow, Some(shadow_paint)); - - render_state.surfaces.draw_into( - SurfaceId::Shadow, - SurfaceId::Current, - Some(&skia::Paint::default()), - ); - - render_state - .surfaces - .canvas(SurfaceId::Shadow) - .clear(skia::Color::TRANSPARENT); -} - -// Inner Shadows -pub fn render_inner_shadows(render_state: &mut RenderState, shape: &Shape, antialias: bool) { +pub fn render_fill_inner_shadows(render_state: &mut RenderState, shape: &Shape, antialias: bool) { if shape.has_fills() { for shadow in shape.inner_shadows().rev().filter(|s| !s.hidden()) { render_fill_inner_shadow(render_state, &shape, &shadow, antialias); } - } else { - let scale = render_state.get_scale(); - for shadow in shape.inner_shadows().rev().filter(|s| !s.hidden()) { - render_stroke_inner_shadow(render_state, &shadow, scale, antialias); - } } } @@ -75,29 +40,46 @@ fn render_fill_inner_shadow( render_shadow_paint(render_state, shape, paint, SurfaceId::InnerShadows); } -// TODO: Stroke shadows -fn render_stroke_inner_shadow( +pub fn render_stroke_drop_shadows( render_state: &mut RenderState, - shadow: &Shadow, - scale: f32, + shape: &Shape, + stroke: &Stroke, antialias: bool, ) { - let shadow_paint = &shadow.to_paint(scale, antialias); + if !shape.has_fills() { + for shadow in shape.drop_shadows().rev().filter(|s| !s.hidden()) { + let filter = shadow.get_drop_shadow_filter(); + strokes::render( + render_state, + &shape, + stroke, + Some(SurfaceId::Strokes), // FIXME + filter.as_ref(), + antialias, + ) + } + } +} - render_state - .surfaces - .draw_into(SurfaceId::Strokes, SurfaceId::Shadow, Some(shadow_paint)); - - render_state.surfaces.draw_into( - SurfaceId::Shadow, - SurfaceId::Overlay, - Some(&skia::Paint::default()), - ); - - render_state - .surfaces - .canvas(SurfaceId::Shadow) - .clear(skia::Color::TRANSPARENT); +pub fn render_stroke_inner_shadows( + render_state: &mut RenderState, + shape: &Shape, + stroke: &Stroke, + antialias: bool, +) { + if !shape.has_fills() { + for shadow in shape.inner_shadows().rev().filter(|s| !s.hidden()) { + let filter = shadow.get_inner_shadow_filter(); + strokes::render( + render_state, + &shape, + stroke, + Some(SurfaceId::Strokes), // FIXME + filter.as_ref(), + antialias, + ) + } + } } fn render_shadow_paint( diff --git a/render-wasm/src/render/strokes.rs b/render-wasm/src/render/strokes.rs index 08c47b2f7..13f130b33 100644 --- a/render-wasm/src/render/strokes.rs +++ b/render-wasm/src/render/strokes.rs @@ -3,7 +3,7 @@ use std::collections::HashMap; use crate::math::{Matrix, Point, Rect}; use crate::shapes::{Corners, Fill, ImageFill, Path, Shape, Stroke, StrokeCap, StrokeKind, Type}; -use skia_safe::{self as skia, RRect}; +use skia_safe::{self as skia, ImageFilter, RRect}; use super::{RenderState, SurfaceId}; @@ -15,6 +15,7 @@ fn draw_stroke_on_rect( corners: &Option, svg_attrs: &HashMap, scale: f32, + shadow: Option<&ImageFilter>, antialias: bool, ) { // Draw the different kind of strokes for a rect is straightforward, we just need apply a stroke to: @@ -22,7 +23,11 @@ fn draw_stroke_on_rect( // - A bigger rect if it's an outer stroke // - A smaller rect if it's an outer stroke let stroke_rect = stroke.outer_rect(rect); - let paint = stroke.to_paint(selrect, svg_attrs, scale, antialias); + let mut paint = stroke.to_paint(selrect, svg_attrs, scale, antialias); + + if let Some(filter) = shadow { + paint.set_image_filter(filter.clone()); + } match corners { Some(radii) => { @@ -43,6 +48,7 @@ fn draw_stroke_on_circle( selrect: &Rect, svg_attrs: &HashMap, scale: f32, + shadow: Option<&ImageFilter>, antialias: bool, ) { // Draw the different kind of strokes for an oval is straightforward, we just need apply a stroke to: @@ -50,13 +56,16 @@ fn draw_stroke_on_circle( // - A bigger oval if it's an outer stroke // - A smaller oval if it's an outer stroke let stroke_rect = stroke.outer_rect(rect); - canvas.draw_oval( - &stroke_rect, - &stroke.to_paint(selrect, svg_attrs, scale, antialias), - ); + let mut paint = stroke.to_paint(selrect, svg_attrs, scale, antialias); + + if let Some(filter) = shadow { + paint.set_image_filter(filter.clone()); + } + + canvas.draw_oval(&stroke_rect, &paint); } -fn draw_stroke_on_path( +pub fn draw_stroke_on_path( canvas: &skia::Canvas, stroke: &Stroke, path: &Path, @@ -64,13 +73,19 @@ fn draw_stroke_on_path( path_transform: Option<&Matrix>, svg_attrs: &HashMap, scale: f32, + shadow: Option<&ImageFilter>, antialias: bool, ) { let mut skia_path = path.to_skia_path(); skia_path.transform(path_transform.unwrap()); let is_open = path.is_open(); - let paint_stroke = stroke.to_stroked_paint(is_open, selrect, svg_attrs, scale, antialias); + let mut paint: skia_safe::Handle<_> = + stroke.to_stroked_paint(path.is_open(), selrect, svg_attrs, scale, antialias); + + if let Some(filter) = shadow { + paint.set_image_filter(filter.clone()); + } // Draw the different kind of strokes for a path requires different strategies: match stroke.render_kind(is_open) { @@ -78,22 +93,21 @@ fn draw_stroke_on_path( StrokeKind::InnerStroke => { canvas.save(); // As we are using clear for surfaces we use save and restore here to still be able to clean the full surface canvas.clip_path(&skia_path, skia::ClipOp::Intersect, antialias); - canvas.draw_path(&skia_path, &paint_stroke); + canvas.draw_path(&skia_path, &paint); canvas.restore(); } // For center stroke we don't need to do anything extra StrokeKind::CenterStroke => { - canvas.draw_path(&skia_path, &paint_stroke); + canvas.draw_path(&skia_path, &paint); } // For outer stroke we draw a center stroke (with double width) and use another path with blend mode clear to remove the inner stroke added StrokeKind::OuterStroke => { - let mut paint = skia::Paint::default(); - paint.set_blend_mode(skia::BlendMode::SrcOver); - paint.set_anti_alias(antialias); - let layer_rec = skia::canvas::SaveLayerRec::default().paint(&paint); + let mut outer_paint = skia::Paint::default(); + outer_paint.set_blend_mode(skia::BlendMode::SrcOver); + outer_paint.set_anti_alias(antialias); + let layer_rec = skia::canvas::SaveLayerRec::default().paint(&outer_paint); canvas.save_layer(&layer_rec); - - canvas.draw_path(&skia_path, &paint_stroke); + canvas.draw_path(&skia_path, &paint); let mut clear_paint = skia::Paint::default(); clear_paint.set_blend_mode(skia::BlendMode::Clear); @@ -344,7 +358,7 @@ fn draw_image_stroke_in_container( let size = image_fill.size(); let scale = render_state.get_scale(); - let canvas = render_state.surfaces.canvas(SurfaceId::Fills); + let canvas = render_state.surfaces.canvas(SurfaceId::Strokes); let container = &shape.selrect; let path_transform = shape.to_path_transform(); let svg_attrs = &shape.svg_attrs; @@ -370,6 +384,7 @@ fn draw_image_stroke_in_container( &shape_type.corners(), svg_attrs, scale, + None, antialias, ); } @@ -380,6 +395,7 @@ fn draw_image_stroke_in_container( &outer_rect, svg_attrs, scale, + None, antialias, ), @@ -456,15 +472,26 @@ fn draw_image_stroke_in_container( /** * This SHOULD be the only public function in this module. */ -pub fn render(render_state: &mut RenderState, shape: &Shape, stroke: &Stroke, antialias: bool) { +pub fn render( + render_state: &mut RenderState, + shape: &Shape, + stroke: &Stroke, + surface_id: Option, + shadow: Option<&ImageFilter>, + antialias: bool, +) { let scale = render_state.get_scale(); - let canvas = render_state.surfaces.canvas(SurfaceId::Strokes); + let canvas = render_state + .surfaces + .canvas(surface_id.unwrap_or(SurfaceId::Strokes)); let selrect = shape.selrect; let path_transform = shape.to_path_transform(); let svg_attrs = &shape.svg_attrs; - if let Fill::Image(image_fill) = &stroke.fill { - draw_image_stroke_in_container(render_state, shape, stroke, image_fill, antialias); + if !shadow.is_some() && matches!(stroke.fill, Fill::Image(_)) { + if let Fill::Image(image_fill) = &stroke.fill { + draw_image_stroke_in_container(render_state, shape, stroke, image_fill, antialias); + } } else { match &shape.shape_type { shape_type @ (Type::Rect(_) | Type::Frame(_)) => { @@ -476,11 +503,12 @@ pub fn render(render_state: &mut RenderState, shape: &Shape, stroke: &Stroke, an &shape_type.corners(), svg_attrs, scale, + shadow, antialias, ); } Type::Circle => draw_stroke_on_circle( - canvas, stroke, &selrect, &selrect, svg_attrs, scale, antialias, + canvas, stroke, &selrect, &selrect, svg_attrs, scale, shadow, antialias, ), shape_type @ (Type::Path(_) | Type::Bool(_)) => { if let Some(path) = shape_type.path() { @@ -492,6 +520,7 @@ pub fn render(render_state: &mut RenderState, shape: &Shape, stroke: &Stroke, an path_transform.as_ref(), svg_attrs, scale, + shadow, antialias, ); } diff --git a/render-wasm/src/render/surfaces.rs b/render-wasm/src/render/surfaces.rs index 154f0f0e7..69564fc9d 100644 --- a/render-wasm/src/render/surfaces.rs +++ b/render-wasm/src/render/surfaces.rs @@ -13,10 +13,8 @@ pub enum SurfaceId { Current, Fills, Strokes, - Shadow, DropShadows, InnerShadows, - Overlay, Debug, } @@ -30,12 +28,9 @@ pub struct Surfaces { // keeps the current shape's strokes shape_strokes: skia::Surface, // used for rendering shadows - shadow: skia::Surface, - // used for new shadow rendering drop_shadows: skia::Surface, + // used fo rendering over shadows. inner_shadows: skia::Surface, - // for drawing the things that are over shadows. - overlay: skia::Surface, // for drawing debug info. debug: skia::Surface, // for drawing tiles. @@ -63,10 +58,8 @@ impl Surfaces { let mut target = gpu_state.create_target_surface(width, height); let current = target.new_surface_with_dimensions(extra_tile_dims).unwrap(); - let shadow = target.new_surface_with_dimensions(extra_tile_dims).unwrap(); let drop_shadows = target.new_surface_with_dimensions(extra_tile_dims).unwrap(); let inner_shadows = target.new_surface_with_dimensions(extra_tile_dims).unwrap(); - let overlay = target.new_surface_with_dimensions(extra_tile_dims).unwrap(); let shape_fills = target.new_surface_with_dimensions(extra_tile_dims).unwrap(); let shape_strokes = target.new_surface_with_dimensions(extra_tile_dims).unwrap(); let debug = target.new_surface_with_dimensions((width, height)).unwrap(); @@ -79,10 +72,8 @@ impl Surfaces { Surfaces { target, current, - shadow, drop_shadows, inner_shadows, - overlay, shape_fills, shape_strokes, debug, @@ -176,10 +167,8 @@ impl Surfaces { match id { SurfaceId::Target => &mut self.target, SurfaceId::Current => &mut self.current, - SurfaceId::Shadow => &mut self.shadow, SurfaceId::DropShadows => &mut self.drop_shadows, SurfaceId::InnerShadows => &mut self.inner_shadows, - SurfaceId::Overlay => &mut self.overlay, SurfaceId::Fills => &mut self.shape_fills, SurfaceId::Strokes => &mut self.shape_strokes, SurfaceId::Debug => &mut self.debug, @@ -225,8 +214,6 @@ impl Surfaces { SurfaceId::Current, SurfaceId::DropShadows, SurfaceId::InnerShadows, - SurfaceId::Shadow, - SurfaceId::Overlay, ], |s| { s.canvas().clear(color).reset_matrix(); diff --git a/render-wasm/src/shapes/shadows.rs b/render-wasm/src/shapes/shadows.rs index 999f1221c..a8f226c41 100644 --- a/render-wasm/src/shapes/shadows.rs +++ b/render-wasm/src/shapes/shadows.rs @@ -1,4 +1,4 @@ -use skia_safe::{self as skia, image_filters, ImageFilter}; +use skia_safe::{self as skia, image_filters, ImageFilter, Paint}; use super::Color; @@ -62,75 +62,8 @@ impl Shadow { self.hidden } - pub fn to_paint(&self, scale: f32, antialias: bool) -> skia::Paint { - let mut paint = skia::Paint::default(); - - let image_filter = match self.style { - ShadowStyle::Drop => self.drop_shadow_filters(scale), - ShadowStyle::Inner => self.inner_shadow_filters(scale), - }; - - paint.set_image_filter(image_filter); - paint.set_anti_alias(antialias); - - paint - } - - // To be removed: Old methods for Drop Shadows and Inner Shadows (now used opnly for stroke shadows) - - fn drop_shadow_filters(&self, scale: f32) -> Option { - let mut filter = image_filters::drop_shadow_only( - (self.offset.0 * scale, self.offset.1 * scale), - (self.blur * scale, self.blur * scale), - self.color, - None, - None, - None, - ); - - if self.spread > 0. { - filter = - image_filters::dilate((self.spread * scale, self.spread * scale), filter, None); - } - - filter - } - - fn inner_shadow_filters(&self, scale: f32) -> Option { - let sigma = self.blur * 0.5; - let mut filter = skia::image_filters::drop_shadow_only( - (self.offset.0 * scale, self.offset.1 * scale), // DPR? - (sigma * scale, sigma * scale), - skia::Color::BLACK, - None, - None, - None, - ); - - filter = skia::image_filters::color_filter( - skia::color_filters::blend(self.color, skia::BlendMode::SrcOut).unwrap(), - filter, - None, - ); - - if self.spread > 0. { - filter = skia::image_filters::dilate( - (self.spread * scale, self.spread * scale), - filter, - None, - ); - } - - filter = skia::image_filters::blend(skia::BlendMode::SrcIn, None, filter, None); - - filter - } - - // New methods for Drop Shadows - - pub fn get_drop_shadow_paint(&self, antialias: bool) -> skia::Paint { - let mut paint = skia::Paint::default(); - + pub fn get_drop_shadow_paint(&self, antialias: bool) -> Paint { + let mut paint = Paint::default(); let image_filter = self.get_drop_shadow_filter(); paint.set_image_filter(image_filter); @@ -139,7 +72,7 @@ impl Shadow { paint } - fn get_drop_shadow_filter(&self) -> Option { + pub fn get_drop_shadow_filter(&self) -> Option { let mut filter = image_filters::drop_shadow_only( (self.offset.0, self.offset.1), (self.blur, self.blur), @@ -156,10 +89,8 @@ impl Shadow { filter } - // New methods for Inner Shadows - - pub fn get_inner_shadow_paint(&self, antialias: bool) -> skia::Paint { - let mut paint = skia::Paint::default(); + pub fn get_inner_shadow_paint(&self, antialias: bool) -> Paint { + let mut paint = Paint::default(); let image_filter = self.get_inner_shadow_filter(); @@ -169,12 +100,12 @@ impl Shadow { paint } - fn get_inner_shadow_filter(&self) -> Option { + pub fn get_inner_shadow_filter(&self) -> Option { let sigma = self.blur * 0.5; let mut filter = skia::image_filters::drop_shadow_only( (self.offset.0, self.offset.1), // DPR? (sigma, sigma), - skia::Color::BLACK, + skia::Color::WHITE, None, None, None, diff --git a/render-wasm/src/shapes/strokes.rs b/render-wasm/src/shapes/strokes.rs index 7f0fa692c..6c1af2d7d 100644 --- a/render-wasm/src/shapes/strokes.rs +++ b/render-wasm/src/shapes/strokes.rs @@ -232,13 +232,13 @@ impl Stroke { match self.render_kind(is_open) { StrokeKind::InnerStroke => { paint.set_stroke_width(2. * paint.stroke_width()); - paint } - StrokeKind::CenterStroke => paint, + StrokeKind::CenterStroke => {} StrokeKind::OuterStroke => { paint.set_stroke_width(2. * paint.stroke_width()); - paint } } + + paint } }