use crate::core::animation::Tweenable;
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum MaskMode {
Alpha,
Subtract,
Xor,
Intersect,
Union,
Exclude,
Difference,
}
impl Tweenable for MaskMode {
fn interpolate(a: &Self, b: &Self, t: f32) -> Self {
if t >= 1.0 {
*b
} else {
*a
}
}
fn state_hash(&self) -> u64 {
*self as u64
}
}
#[cfg(feature = "runtime")]
pub fn apply_mask(
scene: &mut vello::Scene,
mode: MaskMode,
combined_opacity: f32,
combined_transform: kurbo::Affine,
mask_render: impl FnOnce(&mut vello::Scene, kurbo::Affine),
source_render: impl FnOnce(&mut vello::Scene, kurbo::Affine),
) {
if combined_opacity <= 0.0 {
return;
}
scene.push_layer(
peniko::Mix::Normal,
combined_opacity,
kurbo::Affine::IDENTITY,
&kurbo::Rect::new(-10000.0, -10000.0, 10000.0, 10000.0),
);
mask_render(scene, combined_transform);
let compose_mode = match mode {
MaskMode::Alpha | MaskMode::Intersect => peniko::Compose::SrcIn,
MaskMode::Subtract => peniko::Compose::SrcOut,
MaskMode::Xor | MaskMode::Exclude | MaskMode::Difference => peniko::Compose::Xor,
MaskMode::Union => peniko::Compose::SrcOver,
};
scene.push_layer(
peniko::BlendMode {
mix: peniko::Mix::Normal,
compose: compose_mode,
},
1.0,
kurbo::Affine::IDENTITY,
&kurbo::Rect::new(-10000.0, -10000.0, 10000.0, 10000.0),
);
source_render(scene, combined_transform);
scene.pop_layer();
scene.pop_layer();
}