freya_core/
layout.rs

1use freya_engine::prelude::*;
2use freya_native_core::prelude::NodeImmutable;
3use itertools::Itertools;
4use torin::geometry::Area;
5
6use crate::{
7    accessibility::NodeAccessibility,
8    dom::*,
9    render::{
10        Compositor,
11        SkiaMeasurer,
12    },
13};
14
15/// Process the layout of the DOM
16pub fn process_layout(
17    fdom: &FreyaDOM,
18    area: Area,
19    font_collection: &mut FontCollection,
20    scale_factor: f32,
21    default_fonts: &[String],
22) {
23    {
24        let rdom = fdom.rdom();
25        let mut images_cache = fdom.images_cache();
26        let mut dom_adapter = DioxusDOMAdapter::new(rdom, scale_factor);
27        let skia_measurer = SkiaMeasurer::new(
28            rdom,
29            font_collection,
30            default_fonts,
31            scale_factor,
32            &mut images_cache,
33        );
34
35        let mut layout = fdom.layout();
36
37        // Finds the best Node from where to start measuring
38        layout.find_best_root(&mut dom_adapter);
39
40        let mut dirty_accessibility_tree = fdom.accessibility_dirty_nodes();
41        let mut compositor_dirty_nodes = fdom.compositor_dirty_nodes();
42        let mut compositor_dirty_area = fdom.compositor_dirty_area();
43        let mut buffer = layout.dirty.keys().copied().collect_vec();
44        while let Some(node_id) = buffer.pop() {
45            if let Some(node) = rdom.get(node_id) {
46                if let Some(area) =
47                    Compositor::get_drawing_area(node_id, &layout, rdom, scale_factor)
48                {
49                    // Unite the invalidated area with the dirty area
50                    compositor_dirty_area.unite_or_insert(&area);
51
52                    // Mark these elements as dirty for the compositor
53                    compositor_dirty_nodes.insert(node_id);
54
55                    // Mark as invalidated this node as its layout has changed
56                    if node.get_accessibility_id().is_some() {
57                        dirty_accessibility_tree.add_or_update(node_id);
58                    }
59                }
60                // Continue iterating in the children of this node
61                buffer.extend(node.child_ids());
62            }
63        }
64        let root_id = fdom.rdom().root_id();
65
66        // Measure the layout
67        layout.measure(root_id, area, &mut Some(skia_measurer), &mut dom_adapter);
68    }
69}