fix(renderer): honor explicitly authored absolute layouts
An authored layout:none whose children carry real x/y is deliberate overlay placement; the horizontal-layout inference pass flattened it (a pinned badge dot snapped into flow). Legacy frames with absent layout and stale 0,0 children still infer.
This commit is contained in:
parent
acfcb9f864
commit
ba497758cd
|
|
@ -321,7 +321,22 @@ fn layout_measure_backend() -> Rc<dyn MeasureBackend> {
|
|||
/// root at its own (0, 0), so a tap must subtract the containing root's
|
||||
/// authored origin before it reaches `Runtime::dispatch_pointer`.
|
||||
pub fn root_authored_origin(n: &PenNode) -> (f32, f32) {
|
||||
let base = match n {
|
||||
let base = pen_base(n);
|
||||
(base.x.unwrap_or(0.0) as f32, base.y.unwrap_or(0.0) as f32)
|
||||
}
|
||||
|
||||
/// `Some(_)` when the node authored an `x` or `y` — the explicit-absolute
|
||||
/// signal `layout_repair`'s flow inference must yield to.
|
||||
pub(crate) fn node_base_xy(n: &PenNode) -> Option<(f64, f64)> {
|
||||
let base = pen_base(n);
|
||||
match (base.x, base.y) {
|
||||
(None, None) => None,
|
||||
(x, y) => Some((x.unwrap_or(0.0), y.unwrap_or(0.0))),
|
||||
}
|
||||
}
|
||||
|
||||
fn pen_base(n: &PenNode) -> &jian_ops_schema::node::base::PenNodeBase {
|
||||
match n {
|
||||
PenNode::Frame(f) => &f.base,
|
||||
PenNode::Group(g) => &g.base,
|
||||
PenNode::Rectangle(r) => &r.base,
|
||||
|
|
@ -343,8 +358,7 @@ pub fn root_authored_origin(n: &PenNode) -> (f32, f32) {
|
|||
PenNode::Image(i) => &i.base,
|
||||
PenNode::IconFont(i) => &i.base,
|
||||
PenNode::Ref(r) => &r.base,
|
||||
};
|
||||
(base.x.unwrap_or(0.0) as f32, base.y.unwrap_or(0.0) as f32)
|
||||
}
|
||||
}
|
||||
|
||||
/// Choose the (available_width, available_height) the layout engine
|
||||
|
|
|
|||
|
|
@ -46,7 +46,9 @@ fn repair_node(node: &PenNode, rects: &mut BTreeMap<String, [f32; 4]>, is_root:
|
|||
repair_horizontal_container(node, props, kids, rects);
|
||||
}
|
||||
None | Some(LayoutMode::None)
|
||||
if is_frame(node) && should_infer_horizontal_layout(props, kids) =>
|
||||
if is_frame(node)
|
||||
&& should_infer_horizontal_layout(props, kids)
|
||||
&& !explicit_absolute_intent(props, kids) =>
|
||||
{
|
||||
repair_inferred_horizontal_container(node, props, kids, rects);
|
||||
}
|
||||
|
|
@ -437,6 +439,20 @@ fn should_infer_horizontal_layout(props: &ContainerProps, kids: &[PenNode]) -> b
|
|||
|| kids.iter().any(child_has_fill_container_axis)
|
||||
}
|
||||
|
||||
/// An EXPLICITLY authored `layout: "none"` whose children carry real x/y is
|
||||
/// absolute placement by spec — a badge dot pinned on a bell icon (x:28, y:8
|
||||
/// over a 20px icon at 12,12). Models belt-and-suspender these buttons with
|
||||
/// justifyContent+alignItems too, which used to trip the flow inference and
|
||||
/// stomp taffy's absolute positions (measured: the badge rendered BESIDE the
|
||||
/// bell). Legacy TS docs with an ABSENT layout field and stale x/y=0 children
|
||||
/// still get the inference — their coordinates are flow debris, not intent.
|
||||
fn explicit_absolute_intent(props: &ContainerProps, kids: &[PenNode]) -> bool {
|
||||
matches!(props.layout.as_ref(), Some(LayoutMode::None))
|
||||
&& kids
|
||||
.iter()
|
||||
.any(|k| crate::adapter::node_base_xy(k).is_some_and(|(x, y)| x != 0.0 || y != 0.0))
|
||||
}
|
||||
|
||||
fn inferred_horizontal_padding(node: &PenNode, props: &ContainerProps, kids: &[PenNode]) -> Sides {
|
||||
let mut padding = padding_sides(props.padding.as_ref());
|
||||
if legacy_zero_horizontal_inset_row(node, props, kids) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue