feat: implement nested border-box layout and alignment

This commit is contained in:
2026-11-10 22:17:19 +08:00
parent 525097a0b2
commit 32d7ada3ab
21 changed files with 1368 additions and 74 deletions
+21 -9
View File
@@ -165,7 +165,11 @@ impl NativeCallable for Step {
Some(
plan.runtime
.measure_node(&node, children.clone(), constraints)
.map_err(|_| invalid("native measurement exceeds layout limits"))?,
.map_err(|error| {
error.downcast_ref::<VmError>().cloned().unwrap_or_else(|| {
invalid("native measurement exceeds layout limits")
})
})?,
)
} else {
if !intrinsic {
@@ -211,8 +215,7 @@ impl NativeCallable for Step {
if matches!(self.phase, Phase::Arrange) {
plan.runtime.arranged += 1;
plan.native_arrange[self.index] = intrinsic;
plan.custom_arrange[self.index] =
!intrinsic || node.children().iter().any(|child| child.has_flex());
plan.custom_arrange[self.index] = !intrinsic || node.allocates_children();
}
(node, children, preferred, bounds, native_size)
};
@@ -532,7 +535,13 @@ impl NativeCallable for Settle {
Size { width, height },
);
for child in children {
let mut constraints = base;
let natural = layout::occurrence_constraints(
&plan.nodes[index],
&plan.nodes[child],
base,
Size { width, height },
);
let mut constraints = natural;
if let Some(width) = plan.allocations[child][0] {
constraints[0] = width;
constraints[2] = width;
@@ -554,8 +563,8 @@ impl NativeCallable for Settle {
// own replacement measurement. Source arrange
// allocations remain authoritative.
plan.allocations[child][main] = None;
constraints[main] = base[main];
constraints[main + 2] = base[main + 2];
constraints[main] = natural[main];
constraints[main + 2] = natural[main + 2];
}
}
}
@@ -844,7 +853,7 @@ pub fn start(
let mut nodes = Vec::new();
let mut work = vec![root.clone()];
while let Some(node) = work.pop() {
custom |= node.has_flex();
custom |= node.has_flex() || node.allocates_children();
work.extend(node.children().iter().rev().cloned());
nodes.push(node);
}
@@ -878,9 +887,12 @@ pub fn start(
}
let mut constraints = vec![runtime.root_constraints(); nodes.len()];
for index in 0..nodes.len() {
let next = layout::child_constraints(&nodes[index], constraints[index]);
for child in &children[index] {
constraints[*child] = next;
constraints[*child] = layout::initial_child_constraints(
&nodes[index],
&nodes[*child],
constraints[index],
);
}
}
let count = nodes.len();