Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ dioxus-cli-config = { version = "0.7.3" }
dioxus-core-macro = { version = "0.7.3" }

# Taffy + Parley + Fontations
taffy = { version = "0.14.0", default-features = false, features = [
taffy = { git = "https://github.com/DioxusLabs/taffy", rev = "76a2869514ddbedb75e76e07f03afa18aa8fbaba", default-features = false, features = [
"std",
"flexbox",
"grid",
Expand Down
13 changes: 10 additions & 3 deletions packages/blitz-dom/src/document.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1785,9 +1785,16 @@ impl BaseDocument {
return (None, None);
}
let mut scrollbar = None;
let hit = self
.root_element()
.hit_inner(x, y, self.viewport().scale_f64(), &mut scrollbar);
let hit = self.root_element().hit_inner(
x,
y,
self.viewport().scale_f64(),
&mut scrollbar,
taffy::Point {
x: self.viewport_scroll.x as f32,
y: self.viewport_scroll.y as f32,
},
);
(hit, scrollbar)
}

Expand Down
30 changes: 29 additions & 1 deletion packages/blitz-dom/src/layout/damage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -611,6 +611,34 @@ impl BaseDocument {
let position = style.clone_position();
let z_index = style.clone_z_index().integer_or(0);

// Out-of-flow boxes are hoisted to their containing block by Taffy's
// out-of-flow positioning pass and their layout location is relative to
// the containing block's border box. When this node is the child's
// containing block (it claims the child's position type), the child
// stays in this node's paint list, preserving tree order among
// positioned siblings. Otherwise it is painted (and hit-tested) via
// the containing block's `hoisted_children` list (see
// `attach_hoisted_children`), not via its DOM parent.
if matches!(position, Position::Absolute | Position::Fixed) {
let parent = &self.nodes[node_id];
// The root element is the initial containing block: it claims
// every candidate not claimed by a closer containing block.
let is_root = self.try_root_element().is_some_and(|el| el.id == node_id);
let parent_claims = is_root
|| parent
.containing_block_claims()
.for_position(stylo_taffy::convert::position(position));
if !parent_claims {
continue;
}
// Z-indexed out-of-flow boxes are routed to their stacking
// context by `attach_hoisted_children` after layout, when
// their containing-block-relative location is known.
if z_index != 0 {
continue;
}
}

// TODO: more complete hoisting detection
// z-index applies to static flex/grid items too
// (css-flexbox-1 §painting, css-grid-1 §z-order).
Expand Down Expand Up @@ -678,7 +706,7 @@ fn float_to_order(pos: Float) -> i32 {
/// Appendix E step 8); within a level the stable sort preserves
/// (order-modified) document order.
#[inline(always)]
fn node_to_paint_order(node: &Node, is_flex_or_grid: bool) -> (i32, i32) {
pub(crate) fn node_to_paint_order(node: &Node, is_flex_or_grid: bool) -> (i32, i32) {
let Some(style) = node.primary_styles() else {
return (0, 0);
};
Expand Down
636 changes: 196 additions & 440 deletions packages/blitz-dom/src/layout/inline.rs

Large diffs are not rendered by default.

82 changes: 76 additions & 6 deletions packages/blitz-dom/src/layout/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,10 @@ use style::values::computed::CSSPixelLength;
use style::values::computed::length_percentage::CalcLengthPercentage;
use stylo_taffy::TaffyStyloStyle;
use taffy::{
BlockContext, CoreStyle as _, FlexDirection, LayoutPartialTree, NodeId, ResolveOrZero,
RoundTree, TraversePartialTree, TraverseTree, compute_block_layout, compute_cached_layout,
compute_flexbox_layout, compute_grid_layout, compute_leaf_layout, prelude::*,
BlockContext, CoreStyle as _, DetailedLayoutInfo, FlexDirection, LayoutContainingBlock,
LayoutPartialTree, NodeId, ResolveOrZero, RoundTree, TraversePartialTree, TraverseTree,
compute_block_layout, compute_cached_layout, compute_flexbox_layout, compute_grid_layout,
compute_leaf_layout, compute_oof_layout, prelude::*,
};

pub(crate) mod construct;
Expand Down Expand Up @@ -430,11 +431,64 @@ impl LayoutPartialTree for BaseDocument {
inputs: taffy::LayoutInput,
) -> taffy::LayoutOutput {
compute_cached_layout(self, node_id, inputs, |tree, node_id, inputs| {
tree.compute_child_layout_internal(node_id, inputs, None)
let mut output = tree.compute_child_layout_internal(node_id, inputs, None);
if inputs.run_mode == taffy::RunMode::PerformLayout {
compute_oof_layout(tree, node_id, &mut output);
}
output
})
}
}

impl LayoutContainingBlock for BaseDocument {
type OofItemStyle<'a>
= TaffyStyloStyle<ComputedStyleRef<'a>>
where
Self: 'a;

fn get_oof_item_style(&self, node_id: NodeId) -> Self::OofItemStyle<'_> {
self.node_from_id(node_id).layout_style()
}

fn set_hoisted_children(&mut self, node_id: NodeId, hoisted: &[NodeId]) {
let containing_block = dom_node_id(node_id);
let node = self.node_from_id(node_id);
let mut vec = node.hoisted_children.borrow_mut();
vec.clear();
vec.extend(hoisted.iter().copied().map(dom_node_id));
drop(vec);
for &hoisted_id in hoisted {
self.node_from_id(hoisted_id)
.layout_parent
.set(Some(containing_block));
}
}

fn add_hoisted_children(&mut self, node_id: NodeId, hoisted: &[NodeId]) {
let containing_block = dom_node_id(node_id);
let node = self.node_from_id(node_id);
let mut vec = node.hoisted_children.borrow_mut();
for id in hoisted.iter().copied().map(dom_node_id) {
if !vec.contains(&id) {
vec.push(id);
}
}
drop(vec);
for &hoisted_id in hoisted {
self.node_from_id(hoisted_id)
.layout_parent
.set(Some(containing_block));
}
}

fn get_detailed_layout_info(&self, node_id: NodeId) -> &DetailedLayoutInfo<Atom> {
self.node_from_id(node_id)
.element_data()
.map(|element| &element.detailed_layout_info)
.unwrap_or(&DetailedLayoutInfo::None)
}
}

impl taffy::CacheTree for BaseDocument {
#[inline]
fn cache_get(
Expand Down Expand Up @@ -493,7 +547,11 @@ impl taffy::LayoutBlockContainer for BaseDocument {
block_ctx: Option<&mut BlockContext<'_>>,
) -> taffy::LayoutOutput {
compute_cached_layout(self, node_id, inputs, |tree, node_id, inputs| {
tree.compute_child_layout_internal(node_id, inputs, block_ctx)
let mut output = tree.compute_child_layout_internal(node_id, inputs, block_ctx);
if inputs.run_mode == taffy::RunMode::PerformLayout {
compute_oof_layout(tree, node_id, &mut output);
}
output
})
}
}
Expand Down Expand Up @@ -544,7 +602,7 @@ impl taffy::LayoutGridContainer for BaseDocument {
) {
let node = self.node_from_id_mut(node_id);
if let Some(element) = node.element_data_mut() {
element.detailed_grid_info = Some(Box::new(detailed_grid_info));
element.detailed_layout_info = DetailedLayoutInfo::Grid(Box::new(detailed_grid_info));
}
}
}
Expand All @@ -557,6 +615,18 @@ impl RoundTree for BaseDocument {
fn set_final_layout(&mut self, node_id: NodeId, layout: &Layout) {
*self.node_from_id_mut(node_id).final_layout_mut() = *layout;
}

fn is_hoisted(&self, node_id: NodeId) -> bool {
self.node_from_id(node_id).is_hoisted()
}

fn hoisted_child_count(&self, node_id: NodeId) -> usize {
self.node_from_id(node_id).hoisted_children.borrow().len()
}

fn get_hoisted_child_id(&self, node_id: NodeId, index: usize) -> NodeId {
taffy_node_id(self.node_from_id(node_id).hoisted_children.borrow()[index])
}
}

impl PrintTree for BaseDocument {
Expand Down
11 changes: 6 additions & 5 deletions packages/blitz-dom/src/node/element.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,9 +105,10 @@ pub struct ElementData {
pub before: Option<NodeId>,
pub after: Option<NodeId>,

/// Detailed grid track sizing information from the most recent layout
/// (grid containers only). Used by devtools grid inspection.
pub detailed_grid_info: Option<Box<taffy::DetailedGridInfo<Atom>>>,
/// Detailed layout information from the most recent layout (currently
/// grid track sizing information for grid containers only). Used by
/// devtools grid inspection and out-of-flow grid-area positioning.
pub detailed_layout_info: taffy::DetailedLayoutInfo<Atom>,

// Taffy layout data:
pub display_constructed_as: StyloDisplay,
Expand Down Expand Up @@ -314,7 +315,7 @@ impl Clone for ElementData {
damaged_descendants: AtomicBool::new(true),
before: None,
after: None,
detailed_grid_info: None,
detailed_layout_info: taffy::DetailedLayoutInfo::None,
display_constructed_as: StyloDisplay::Block,
layout_data: None,
transform: None,
Expand Down Expand Up @@ -421,7 +422,7 @@ impl ElementData {
damaged_descendants: AtomicBool::new(true),
before: None,
after: None,
detailed_grid_info: None,
detailed_layout_info: taffy::DetailedLayoutInfo::None,
display_constructed_as: StyloDisplay::Block,
layout_data: None,
transform: None,
Expand Down
Loading
Loading