use crate::RasterCause;
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
pub enum Seed {
#[default]
Clear,
Backdrop,
}
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
pub struct Drew {
pub fills: bool,
pub strokes: bool,
pub images: bool,
}
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
pub struct Fingerprint {
pub seed: Seed,
pub full_cover_fill: bool,
pub drew: Drew,
pub draws: usize,
}
impl Fingerprint {
fn is_lone_image(self) -> bool {
self.draws == 1
&& self.drew
== Drew {
images: true,
..Drew::default()
}
}
fn is_fill_only(self) -> bool {
self.drew.fills && !self.drew.strokes
}
fn is_stroke_only(self) -> bool {
self.drew.strokes && !self.drew.fills
}
}
pub type Witness = Fingerprint;
#[must_use]
pub fn classify(witnesses: &[Witness]) -> RasterCause {
let Some(last) = witnesses.last() else {
return RasterCause::SampledSource;
};
if witnesses.iter().any(|w| matches!(w.seed, Seed::Backdrop)) {
return RasterCause::NonIsolatedGroup;
}
if witnesses.iter().any(|w| w.full_cover_fill) {
return RasterCause::MeshShading;
}
if witnesses.len() == 2
&& witnesses.first().is_some_and(|f| f.is_fill_only())
&& last.is_stroke_only()
{
return RasterCause::Knockout;
}
if last.is_lone_image() {
return RasterCause::SoftMask;
}
RasterCause::CompositedGroup
}
#[cfg(test)]
mod tests {
use super::*;
fn drew(n: usize) -> Fingerprint {
Fingerprint {
drew: Drew {
fills: true,
..Drew::default()
},
draws: n,
..Fingerprint::default()
}
}
#[test]
fn no_offscreen_work_is_a_sampled_source() {
assert_eq!(classify(&[]), RasterCause::SampledSource);
}
#[test]
fn a_backdrop_seeded_target_is_a_non_isolated_group() {
let w = Fingerprint {
seed: Seed::Backdrop,
..drew(3)
};
assert_eq!(classify(&[w]), RasterCause::NonIsolatedGroup);
}
#[test]
fn full_cover_fills_are_a_mesh_shading() {
let w = Fingerprint {
full_cover_fill: true,
..drew(900)
};
assert_eq!(classify(&[w]), RasterCause::MeshShading);
}
#[test]
fn a_fill_target_then_a_stroke_target_is_a_knockout() {
let fill = drew(1);
let stroke = Fingerprint {
drew: Drew {
strokes: true,
..Drew::default()
},
draws: 1,
..Fingerprint::default()
};
assert_eq!(classify(&[fill, stroke]), RasterCause::Knockout);
}
#[test]
fn a_lone_image_target_is_a_mask_pass() {
let content = drew(5);
let mask = Fingerprint {
drew: Drew {
images: true,
..Drew::default()
},
draws: 1,
..Fingerprint::default()
};
assert_eq!(classify(&[content, mask]), RasterCause::SoftMask);
}
#[test]
fn an_ordinary_subtree_is_a_composited_group() {
assert_eq!(classify(&[drew(7)]), RasterCause::CompositedGroup);
}
#[test]
fn the_backdrop_wins_over_every_other_signal() {
let mesh = Fingerprint {
full_cover_fill: true,
..drew(2)
};
let group = Fingerprint {
seed: Seed::Backdrop,
..drew(1)
};
assert_eq!(classify(&[mesh, group]), RasterCause::NonIsolatedGroup);
}
}