add: masking to vector data

This commit is contained in:
mtvare6
2025-07-09 19:20:10 +05:30
parent b1620c41c0
commit 9c0847f3fd

View File

@@ -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();