use super::ElementCx;
use crate::color::{Color, ToColorColor as _};
use anyrender::PaintScene;
use kurbo::{Rect, Vec2};
use peniko::{Compose, Fill, Mix};
impl ElementCx<'_> {
pub(super) fn draw_outset_box_shadow(&self, scene: &mut impl PaintScene) {
let box_shadow = &self.style.get_effects().box_shadow.0;
let has_outset_shadow = box_shadow.iter().any(|s| !s.inset);
if !has_outset_shadow {
return;
}
let current_color = self.style.clone_color();
let max_shadow_rect = box_shadow.iter().fold(Rect::ZERO, |prev, shadow| {
let x = shadow.base.horizontal.px() as f64 * self.scale;
let y = shadow.base.vertical.px() as f64 * self.scale;
let blur = shadow.base.blur.px() as f64 * self.scale;
let spread = shadow.spread.px() as f64 * self.scale;
let offset = spread + blur * 2.5;
let rect = self.frame.border_box.inflate(offset, offset) + Vec2::new(x, y);
prev.union(rect)
});
self.context.layer_manager.maybe_with_layer(
scene,
has_outset_shadow,
1.0,
self.transform,
&self.frame.shadow_clip(max_shadow_rect),
|scene| {
for shadow in box_shadow.iter().filter(|s| !s.inset).rev() {
let shadow_color = shadow
.base
.color
.resolve_to_absolute(¤t_color)
.as_srgb_color();
let alpha = shadow_color.components[3];
if alpha != 0.0 {
let transform = self.transform.then_translate(Vec2 {
x: shadow.base.horizontal.px() as f64 * self.scale,
y: shadow.base.vertical.px() as f64 * self.scale,
});
let radius = self.frame.border_radii.average();
let spread = shadow.spread.px() as f64 * self.scale;
let rect = self.frame.border_box.inflate(spread, spread);
scene.draw_box_shadow(
transform,
rect,
shadow_color,
radius,
shadow.base.blur.px() as f64,
);
}
}
},
)
}
pub(super) fn draw_inset_box_shadow(&self, scene: &mut impl PaintScene) {
let current_color = self.style.clone_color();
let box_shadow = &self.style.get_effects().box_shadow.0;
let has_inset_shadow = box_shadow.iter().any(|s| s.inset);
if !has_inset_shadow {
return;
}
let padding_box = self.frame.padding_box_path();
for shadow in box_shadow.iter().filter(|s| s.inset) {
let shadow_color = shadow
.base
.color
.resolve_to_absolute(¤t_color)
.as_srgb_color();
if shadow_color == Color::TRANSPARENT {
return;
}
let radius = self.frame.border_radii.average();
let transform = self.transform.then_translate(Vec2 {
x: shadow.base.horizontal.px() as f64,
y: shadow.base.vertical.px() as f64,
});
scene.push_layer(Mix::Normal, 1.0, self.transform, &padding_box);
scene.fill(
Fill::NonZero,
self.transform,
shadow_color,
None,
&padding_box,
);
scene.push_layer(Compose::DestOut, 1.0, self.transform, &padding_box);
scene.draw_box_shadow(
transform,
self.frame.border_box,
Color::WHITE,
radius,
shadow.base.blur.px() as f64 * self.scale,
);
scene.pop_layer();
scene.pop_layer();
}
}
}