resvg/
mask.rs

1// This Source Code Form is subject to the terms of the Mozilla Public
2// License, v. 2.0. If a copy of the MPL was not distributed with this
3// file, You can obtain one at http://mozilla.org/MPL/2.0/.
4
5use crate::render::Context;
6
7pub fn apply(
8    mask: &usvg::Mask,
9    ctx: &Context,
10    transform: tiny_skia::Transform,
11    pixmap: &mut tiny_skia::Pixmap,
12) {
13    if mask.root().children().is_empty() {
14        pixmap.fill(tiny_skia::Color::TRANSPARENT);
15        return;
16    }
17
18    let mut mask_pixmap = tiny_skia::Pixmap::new(pixmap.width(), pixmap.height()).unwrap();
19
20    {
21        // TODO: only when needed
22        // Mask has to be clipped by mask.region
23        let mut alpha_mask = tiny_skia::Mask::new(pixmap.width(), pixmap.height()).unwrap();
24        alpha_mask.fill_path(
25            &tiny_skia::PathBuilder::from_rect(mask.rect().to_rect()),
26            tiny_skia::FillRule::Winding,
27            true,
28            transform,
29        );
30
31        crate::render::render_nodes(mask.root(), ctx, transform, &mut mask_pixmap.as_mut());
32
33        mask_pixmap.apply_mask(&alpha_mask);
34    }
35
36    if let Some(mask) = mask.mask() {
37        self::apply(mask, ctx, transform, pixmap);
38    }
39
40    let mask_type = match mask.kind() {
41        usvg::MaskType::Luminance => tiny_skia::MaskType::Luminance,
42        usvg::MaskType::Alpha => tiny_skia::MaskType::Alpha,
43    };
44
45    let mask = tiny_skia::Mask::from_pixmap(mask_pixmap.as_ref(), mask_type);
46    pixmap.apply_mask(&mask);
47}