use anyrender::PaintScene;
use kurbo::{Affine, Shape};
use peniko::Mix;
use std::cell::Cell;
const LAYER_LIMIT: u32 = 1024;
#[derive(Default)]
pub(crate) struct LayerManager {
layers_used: Cell<u32>,
layer_depth: Cell<u32>,
layers_wanted: Cell<u32>,
#[allow(unused)] layer_depth_used: Cell<u32>,
}
impl LayerManager {
pub(crate) fn maybe_with_layer<S: PaintScene, F: FnOnce(&mut S)>(
&self,
scene: &mut S,
condition: bool,
opacity: f32,
transform: Affine,
shape: &impl Shape,
paint_layer: F,
) {
let layer_used = self.maybe_push_layer(scene, condition, opacity, transform, shape);
paint_layer(scene);
self.maybe_pop_layer(scene, layer_used);
}
pub(crate) fn maybe_push_layer(
&self,
scene: &mut impl PaintScene,
condition: bool,
opacity: f32,
transform: Affine,
shape: &impl Shape,
) -> bool {
if !condition {
return false;
}
self.layers_wanted.update(|x| x + 1);
let layers_available = self.layers_used.get() <= LAYER_LIMIT;
if !layers_available {
return false;
}
if opacity == 1.0 {
scene.push_clip_layer(transform, shape);
} else {
scene.push_layer(Mix::Normal, opacity, transform, shape);
};
self.layers_used.update(|x| x + 1);
self.layer_depth.update(|x| x + 1);
self.layer_depth.update(|x| x.max(self.layer_depth.get()));
true
}
pub(crate) fn maybe_pop_layer(&self, scene: &mut impl PaintScene, condition: bool) {
if condition {
scene.pop_layer();
self.layer_depth.update(|x| x - 1);
}
}
}