use crate::draw::command::DrawCommand;
use crate::draw::renderer::Renderer;
use crate::draw::sw::blur::{alpha_for_radius, iir_blur_inplace};
use crate::ecs::{Entity, World};
use crate::types::{Fixed, Point, Rect};
use crate::widget::view::{View, ViewCtx};
pub struct BackgroundBlur {
pub radius: Fixed,
}
impl BackgroundBlur {
pub fn new(radius: impl Into<Fixed>) -> Self {
Self {
radius: radius.into(),
}
}
}
fn background_blur_render(
renderer: &mut dyn Renderer,
world: &World,
entity: Entity,
rect: &Rect,
ctx: &mut ViewCtx,
) {
let Some(bg) = world.get::<BackgroundBlur>(entity) else {
return;
};
if bg.radius <= Fixed::ZERO {
return;
}
let sample_rect = ctx.transform.apply_rect_bbox(*rect);
let alpha = alpha_for_radius(bg.radius);
use crate::types::TransformClass;
let class = ctx.transform.classify();
if matches!(class, TransformClass::Identity | TransformClass::Translate) && ctx.quad.is_none() {
renderer.modify_target_region(&sample_rect, &mut |tex| {
iir_blur_inplace(tex, alpha);
});
return;
}
let Some(mut tmp) = renderer.sample_target_region(&sample_rect) else {
return;
};
iir_blur_inplace(&mut tmp, alpha);
renderer.draw(
&DrawCommand::Blit {
pos: Point::new(rect.x, rect.y),
size: Point::new(rect.w, rect.h),
transform: ctx.transform,
quad: ctx.quad,
texture: &tmp,
},
ctx.clip,
);
}
pub fn view() -> View {
View::new("BackgroundBlur", 60, background_blur_render).with_filter::<BackgroundBlur>()
}