1use crate::render::Context;
6
7pub fn apply(
8 clip: &usvg::ClipPath,
9 transform: tiny_skia::Transform,
10 pixmap: &mut tiny_skia::Pixmap,
11) {
12 let mut clip_pixmap = tiny_skia::Pixmap::new(pixmap.width(), pixmap.height()).unwrap();
13 clip_pixmap.fill(tiny_skia::Color::BLACK);
14
15 draw_children(
16 clip.root(),
17 tiny_skia::BlendMode::Clear,
18 transform.pre_concat(clip.transform()),
19 &mut clip_pixmap.as_mut(),
20 );
21
22 if let Some(clip) = clip.clip_path() {
23 apply(clip, transform, pixmap);
24 }
25
26 let mut mask = tiny_skia::Mask::from_pixmap(clip_pixmap.as_ref(), tiny_skia::MaskType::Alpha);
27 mask.invert();
28 pixmap.apply_mask(&mask);
29}
30
31fn draw_children(
32 parent: &usvg::Group,
33 mode: tiny_skia::BlendMode,
34 transform: tiny_skia::Transform,
35 pixmap: &mut tiny_skia::PixmapMut,
36) {
37 for child in parent.children() {
38 match child {
39 usvg::Node::Path(ref path) => {
40 if !path.is_visible() {
41 continue;
42 }
43
44 let ctx = Context {
46 max_bbox: tiny_skia::IntRect::from_xywh(0, 0, 1, 1).unwrap(),
47 };
48
49 crate::path::fill_path(path, mode, &ctx, transform, pixmap);
50 }
51 usvg::Node::Text(ref text) => {
52 draw_children(text.flattened(), mode, transform, pixmap);
53 }
54 usvg::Node::Group(ref group) => {
55 let transform = transform.pre_concat(group.transform());
56
57 if let Some(clip) = group.clip_path() {
58 clip_group(group, clip, transform, pixmap);
62 } else {
63 draw_children(group, mode, transform, pixmap);
64 }
65 }
66 _ => {}
67 }
68 }
69}
70
71fn clip_group(
72 children: &usvg::Group,
73 clip: &usvg::ClipPath,
74 transform: tiny_skia::Transform,
75 pixmap: &mut tiny_skia::PixmapMut,
76) -> Option<()> {
77 let mut clip_pixmap = tiny_skia::Pixmap::new(pixmap.width(), pixmap.height()).unwrap();
78
79 draw_children(
80 children,
81 tiny_skia::BlendMode::SourceOver,
82 transform,
83 &mut clip_pixmap.as_mut(),
84 );
85 apply(clip, transform, &mut clip_pixmap);
86
87 let mut paint = tiny_skia::PixmapPaint::default();
88 paint.blend_mode = tiny_skia::BlendMode::Xor;
89 pixmap.draw_pixmap(
90 0,
91 0,
92 clip_pixmap.as_ref(),
93 &paint,
94 tiny_skia::Transform::identity(),
95 None,
96 );
97
98 Some(())
99}