From 9c0847f3fda48e47ca8b85a3f79107f0bf38ea8c Mon Sep 17 00:00:00 2001 From: mtvare6 Date: Wed, 9 Jul 2025 19:20:10 +0530 Subject: [PATCH] add: masking to vector data --- node-graph/gsvg-renderer/src/renderer.rs | 36 ++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/node-graph/gsvg-renderer/src/renderer.rs b/node-graph/gsvg-renderer/src/renderer.rs index 43d7acaed9..fc26fe3c1a 100644 --- a/node-graph/gsvg-renderer/src/renderer.rs +++ b/node-graph/gsvg-renderer/src/renderer.rs @@ -531,6 +531,21 @@ impl GraphicElementRendered for VectorDataTable { let selector = format!("url(#{id})"); attributes.push(mask_type.to_attribute(), selector); } + + if let Some(mask) = instance.mask { + let uuid = generate_uuid(); + let mask_type = if mask.can_reduce_to_clip_path() { MaskType::Clip } else { MaskType::Mask }; + let mut svg = SvgRender::new(); + mask.render_svg(&mut svg, &render_params.for_clipper()); + + write!(&mut attributes.0.svg_defs, r##"{}"##, svg.svg_defs).unwrap(); + mask_type.write_to_defs(&mut attributes.0.svg_defs, uuid, svg.svg.to_svg_string()); + let id = format!("mask-{}", uuid); + let selector = format!("url(#{id})"); + + attributes.push(mask_type.to_attribute(), selector); + } + attributes.push_val(fill_and_stroke); let factor = if render_params.for_mask { 1. } else { instance.alpha_blending.fill }; @@ -587,6 +602,22 @@ impl GraphicElementRendered for VectorDataTable { ); } + + let mut masked = false; + if let Some(mask) = instance.mask { + let transform = applied_stroke_transform; + let bounds = mask.bounding_box(transform, true); + + if let Some(bounds) = bounds { + masked = true; + let rect = vello::kurbo::Rect::new(bounds[0].x, bounds[0].y, bounds[1].x, bounds[1].y); + + scene.push_layer(peniko::Mix::Normal, 1., kurbo::Affine::IDENTITY, &rect); + mask.render_to_vello(scene, transform, _context, &render_params.for_clipper()); + scene.push_layer(peniko::BlendMode::new(peniko::Mix::Clip, peniko::Compose::SrcIn), 1., kurbo::Affine::IDENTITY, &rect); + } + } + let can_draw_aligned_stroke = instance.instance.style.stroke().is_some_and(|stroke| stroke.has_renderable_stroke() && stroke.align.is_not_centered()) && instance.instance.stroke_bezier_paths().all(|path| path.closed()); @@ -748,6 +779,11 @@ impl GraphicElementRendered for VectorDataTable { scene.pop_layer(); } + if masked { + scene.pop_layer(); + scene.pop_layer(); + } + // If we pushed a layer for opacity or a blend mode, we need to pop it if layer { scene.pop_layer();