⎇ df9799325a1a368cc36b5dd85d6ad830fd1c0b85
src/compute/leaf.rs
Ñawpa willay
Pi imata llamkarqan
ch'uya
1//! Computes size using styles and measure functions
2
3use crate::geometry::Size;
4use crate::layout::{AvailableSpace, RunMode, SizingMode};
5use crate::math::MaybeMath;
6use crate::node::Node;
7use crate::resolve::{MaybeResolve, ResolveOrDefault};
8use crate::tree::LayoutTree;
9
10#[cfg(feature = "debug")]
11use crate::debug::NODE_LOGGER;
12
13/// Compute the size of a leaf node (node with no children)
14pub(crate) fn compute(
15 tree: &mut impl LayoutTree,
16 node: Node,
17 known_dimensions: Size<Option<f32>>,
18 available_space: Size<AvailableSpace>,
19 _run_mode: RunMode,
20 sizing_mode: SizingMode,
21) -> Size<f32> {
22 let style = tree.style(node);
23
24 // Resolve node's preferred/min/max sizes (width/heights) against the available space (percentages resolve to pixel values)
25 // For ContentSize mode, we pretend that the node has no size styles as these should be ignored.
26 let (node_size, node_min_size, node_max_size) = match sizing_mode {
27 SizingMode::ContentSize => {
28 let node_size = known_dimensions;
29 let node_min_size = Size::NONE;
30 let node_max_size = Size::NONE;
31 (node_size, node_min_size, node_max_size)
32 }
33 SizingMode::InherentSize => {
34 let style_size = style.size.maybe_resolve(available_space.as_options());
35 let node_size = known_dimensions.or(style_size);
36 let node_min_size = style.min_size.maybe_resolve(available_space.as_options());
37 let node_max_size = style.max_size.maybe_resolve(available_space.as_options());
38 (node_size, node_min_size, node_max_size)
39 }
40 };
41
42 #[cfg(feature = "debug")]
43 NODE_LOGGER.log("LEAF");
44 #[cfg(feature = "debug")]
45 NODE_LOGGER.labelled_debug_log("node_size", node_size);
46 #[cfg(feature = "debug")]
47 NODE_LOGGER.labelled_debug_log("min_size ", node_min_size);
48 #[cfg(feature = "debug")]
49 NODE_LOGGER.labelled_debug_log("max_size ", node_max_size);
50
51 // Return early if both width and height are known
52 if let Size { width: Some(width), height: Some(height) } = node_size {
53 return Size { width, height }.maybe_clamp(node_min_size, node_max_size);
54 };
55
56 if tree.needs_measure(node) {
57 // Compute available space
58 let available_space = Size {
59 width: available_space.width.maybe_set(node_size.width),
60 height: available_space.height.maybe_set(node_size.height),
61 };
62
63 // Measure node
64 let measured_size = tree.measure_node(node, known_dimensions, available_space);
65
66 return node_size.unwrap_or(measured_size).maybe_clamp(node_min_size, node_max_size);
67 }
68
69 // Note: both horizontal and vertical percentage padding/borders are resolved against the container's inline size (i.e. width).
70 // This is not a bug, but is how CSS is specified (see: https://developer.mozilla.org/en-US/docs/Web/CSS/padding#values)
71 let padding = style.padding.resolve_or_default(available_space.width.into_option());
72 let border = style.border.resolve_or_default(available_space.width.into_option());
73
74 Size {
75 width: node_size
76 .width
77 // .unwrap_or(0.0) + padding.horizontal_axis_sum() + border.horizontal_axis_sum(), // content-box
78 .unwrap_or(0.0 + padding.horizontal_axis_sum() + border.horizontal_axis_sum()) // border-box
79 .maybe_clamp(node_min_size.width, node_max_size.width),
80 height: node_size
81 .height
82 // .unwrap_or(0.0) + padding.vertical_axis_sum() + border.vertical_axis_sum(), // content-box
83 .unwrap_or(0.0 + padding.vertical_axis_sum() + border.vertical_axis_sum()) // border-box
84 .maybe_clamp(node_min_size.height, node_max_size.height),
85 }
86}