resvg/
mask.rs

1// Copyright 2019 the Resvg Authors
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3
4use crate::render::Context;
5
6pub fn apply(
7    mask: &usvg::Mask,
8    ctx: &Context,
9    transform: tiny_skia::Transform,
10    pixmap: &mut tiny_skia::Pixmap,
11) {
12    if mask.root().children().is_empty() {
13        pixmap.fill(tiny_skia::Color::TRANSPARENT);
14        return;
15    }
16
17    let mut mask_pixmap = tiny_skia::Pixmap::new(pixmap.width(), pixmap.height()).unwrap();
18
19    {
20        // TODO: only when needed
21        // Mask has to be clipped by mask.region
22        let mut alpha_mask = tiny_skia::Mask::new(pixmap.width(), pixmap.height()).unwrap();
23        alpha_mask.fill_path(
24            &tiny_skia::PathBuilder::from_rect(mask.rect().to_rect()),
25            tiny_skia::FillRule::Winding,
26            true,
27            transform,
28        );
29
30        crate::render::render_nodes(mask.root(), ctx, transform, &mut mask_pixmap.as_mut());
31
32        mask_pixmap.apply_mask(&alpha_mask);
33    }
34
35    if let Some(mask) = mask.mask() {
36        self::apply(mask, ctx, transform, pixmap);
37    }
38
39    let mask_type = match mask.kind() {
40        usvg::MaskType::Luminance => tiny_skia::MaskType::Luminance,
41        usvg::MaskType::Alpha => tiny_skia::MaskType::Alpha,
42    };
43
44    let mask = tiny_skia::Mask::from_pixmap(mask_pixmap.as_ref(), mask_type);
45    pixmap.apply_mask(&mask);
46}