use krilla::geom::Size;
use krilla::image::Image;
use krilla::surface::Surface;
use usvg::tiny_skia_path::Transform;
use super::ProcessContext;
use super::util::KrillaTransformExt;
pub(super) fn render(
group: &usvg::Group,
surface: &mut Surface,
process_context: &ProcessContext,
) -> Option<()> {
let layer_bbox = group.layer_bounding_box().transform(group.transform())?;
let raster_scale = {
let actual_bbox = group
.layer_bounding_box()
.transform(surface.cur_transform().to_usvg())?
.transform(group.transform())?;
let scale = {
let (x_scale, y_scale) = (
(actual_bbox.width() / layer_bbox.width()),
(actual_bbox.height() / layer_bbox.height()),
);
x_scale.max(y_scale) * process_context.svg_settings.filter_scale
};
let max_scale = {
const PIXEL_THRESHOLD: f32 = 5000.0;
let (x_scale, y_scale) = (
(PIXEL_THRESHOLD / layer_bbox.width()),
(PIXEL_THRESHOLD / layer_bbox.height()),
);
x_scale.min(y_scale)
};
scale.min(max_scale)
};
let pixmap_size = Size::from_wh(
layer_bbox.width() * raster_scale,
layer_bbox.height() * raster_scale,
)?;
let width = pixmap_size.width().round() as u32;
let height = pixmap_size.height().round() as u32;
let mut pixmap = tiny_skia::Pixmap::new(width, height)?;
let initial_transform = Transform::from_scale(raster_scale, raster_scale)
.pre_concat(Transform::from_translate(-layer_bbox.x(), -layer_bbox.y()))
.pre_concat(Transform::from_translate(
group.abs_layer_bounding_box().x(),
group.abs_layer_bounding_box().y(),
));
resvg::render_node(
&usvg::Node::Group(Box::new(group.clone())),
initial_transform,
&mut pixmap.as_mut(),
);
let demultiplied = pixmap
.pixels()
.iter()
.flat_map(|p| {
let c = p.demultiply();
[c.red(), c.green(), c.blue(), c.alpha()]
})
.collect::<Vec<_>>();
let image = Image::from_rgba8(demultiplied, width, height);
let size = Size::from_wh(layer_bbox.width(), layer_bbox.height())?;
surface.push_transform(&krilla::geom::Transform::from_translate(
layer_bbox.x(),
layer_bbox.y(),
));
surface.draw_image(image, size);
surface.pop();
Some(())
}