use dioxus_native_core::prelude::ElementNode;
use dioxus_native_core::real_dom::NodeImmutable;
use dioxus_native_core::NodeId;
use dioxus_native_core::{node::NodeType, tags::TagName};
use freya_dom::prelude::DioxusNode;
use freya_engine::prelude::*;
use freya_node_state::{Style, Transform, ViewportState};
use torin::{
geometry::Area,
prelude::{LayoutNode, Torin},
};
use crate::elements::{render_image, render_label, render_paragraph, render_rect, render_svg};
fn clip_viewport(canvas: &Canvas, viewport: &Area) {
canvas.clip_rect(
Rect::new(
viewport.min_x(),
viewport.min_y(),
viewport.max_x(),
viewport.max_y(),
),
ClipOp::Intersect,
true,
);
}
#[allow(clippy::too_many_arguments)]
pub fn render_skia(
canvas: &Canvas,
layout_node: &LayoutNode,
dioxus_node: &DioxusNode,
font_collection: &mut FontCollection,
font_manager: &FontMgr,
render_wireframe: bool,
matrices: &mut Vec<(Matrix, Vec<NodeId>)>,
opacities: &mut Vec<(f32, Vec<NodeId>)>,
default_fonts: &[String],
layout: &Torin<NodeId>,
) {
let area = layout_node.visible_area();
let data = &layout_node.data;
let node_type = &*dioxus_node.node_type();
if let NodeType::Element(ElementNode { tag, .. }) = node_type {
canvas.save();
let node_transform = &*dioxus_node.get::<Transform>().unwrap();
let node_style = &*dioxus_node.get::<Style>().unwrap();
if let Some(rotate_degs) = node_transform.rotate_degs {
let mut matrix = Matrix::new_identity();
matrix.set_rotate(
rotate_degs,
Some(Point {
x: area.min_x() + area.width() / 2.0,
y: area.min_y() + area.height() / 2.0,
}),
);
matrices.push((matrix, vec![dioxus_node.id()]));
}
if let Some(opacity) = node_style.opacity {
opacities.push((opacity, vec![dioxus_node.id()]));
}
for (matrix, nodes) in matrices.iter_mut() {
if nodes.contains(&dioxus_node.id()) {
canvas.concat(matrix);
nodes.extend(dioxus_node.child_ids());
}
}
for (opacity, nodes) in opacities.iter_mut() {
if nodes.contains(&dioxus_node.id()) {
canvas.save_layer_alpha_f(
Rect::new(area.min_x(), area.min_y(), area.max_x(), area.max_y()),
*opacity,
);
nodes.extend(dioxus_node.child_ids());
}
}
let node_viewports = dioxus_node.get::<ViewportState>().unwrap();
if !node_viewports.viewports.is_empty() && *tag == TagName::Paragraph {
clip_viewport(canvas, &layout_node.visible_area());
}
for viewport_id in &node_viewports.viewports {
let viewport = layout.get(*viewport_id).unwrap().visible_area();
clip_viewport(canvas, &viewport);
}
match tag {
TagName::Rect => {
render_rect(&area, dioxus_node, canvas, font_collection);
}
TagName::Label => {
render_label(&area, data, canvas);
}
TagName::Paragraph => {
render_paragraph(
&area,
data,
dioxus_node,
canvas,
font_collection,
default_fonts,
);
}
TagName::Svg => {
render_svg(&area, dioxus_node, canvas, font_manager);
}
TagName::Image => {
render_image(&area, dioxus_node, canvas);
}
_ => {}
}
if render_wireframe {
crate::wireframe::render_wireframe(canvas, &area);
}
canvas.restore();
}
}