Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Call measure function on leaf nodes even if the node does not have context #598

Merged
merged 1 commit into from
Jan 2, 2024
Merged
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
30 changes: 11 additions & 19 deletions examples/custom_tree_owned_partial.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,25 +146,17 @@ impl taffy::LayoutPartialTree for Node {
match node.kind {
NodeKind::Flexbox => compute_flexbox_layout(node, node_id, inputs),
NodeKind::Grid => compute_grid_layout(node, node_id, inputs),
NodeKind::Text => compute_leaf_layout(
inputs,
&node.style,
Some(|known_dimensions, available_space| {
text_measure_function(
known_dimensions,
available_space,
node.text_data.as_ref().unwrap(),
&font_metrics,
)
}),
),
NodeKind::Image => compute_leaf_layout(
inputs,
&node.style,
Some(|known_dimensions, _available_space| {
image_measure_function(known_dimensions, node.image_data.as_ref().unwrap())
}),
),
NodeKind::Text => compute_leaf_layout(inputs, &node.style, |known_dimensions, available_space| {
text_measure_function(
known_dimensions,
available_space,
node.text_data.as_ref().unwrap(),
&font_metrics,
)
}),
NodeKind::Image => compute_leaf_layout(inputs, &node.style, |known_dimensions, _available_space| {
image_measure_function(known_dimensions, node.image_data.as_ref().unwrap())
}),
}
})
}
Expand Down
30 changes: 11 additions & 19 deletions examples/custom_tree_owned_unsafe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,25 +150,17 @@ impl LayoutPartialTree for StatelessLayoutTree {
match node.kind {
NodeKind::Flexbox => compute_flexbox_layout(tree, node_id, inputs),
NodeKind::Grid => compute_grid_layout(tree, node_id, inputs),
NodeKind::Text => compute_leaf_layout(
inputs,
&node.style,
Some(|known_dimensions, available_space| {
text_measure_function(
known_dimensions,
available_space,
node.text_data.as_ref().unwrap(),
&font_metrics,
)
}),
),
NodeKind::Image => compute_leaf_layout(
inputs,
&node.style,
Some(|known_dimensions, _available_space| {
image_measure_function(known_dimensions, node.image_data.as_ref().unwrap())
}),
),
NodeKind::Text => compute_leaf_layout(inputs, &node.style, |known_dimensions, available_space| {
text_measure_function(
known_dimensions,
available_space,
node.text_data.as_ref().unwrap(),
&font_metrics,
)
}),
NodeKind::Image => compute_leaf_layout(inputs, &node.style, |known_dimensions, _available_space| {
image_measure_function(known_dimensions, node.image_data.as_ref().unwrap())
}),
}
})
}
Expand Down
30 changes: 11 additions & 19 deletions examples/custom_tree_vec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -159,25 +159,17 @@ impl taffy::LayoutPartialTree for Tree {
match node.kind {
NodeKind::Flexbox => compute_flexbox_layout(tree, node_id, inputs),
NodeKind::Grid => compute_grid_layout(tree, node_id, inputs),
NodeKind::Text => compute_leaf_layout(
inputs,
&node.style,
Some(|known_dimensions, available_space| {
text_measure_function(
known_dimensions,
available_space,
node.text_data.as_ref().unwrap(),
&font_metrics,
)
}),
),
NodeKind::Image => compute_leaf_layout(
inputs,
&node.style,
Some(|known_dimensions, _available_space| {
image_measure_function(known_dimensions, node.image_data.as_ref().unwrap())
}),
),
NodeKind::Text => compute_leaf_layout(inputs, &node.style, |known_dimensions, available_space| {
text_measure_function(
known_dimensions,
available_space,
node.text_data.as_ref().unwrap(),
&font_metrics,
)
}),
NodeKind::Image => compute_leaf_layout(inputs, &node.style, |known_dimensions, _available_space| {
image_measure_function(known_dimensions, node.image_data.as_ref().unwrap())
}),
}
})
}
Expand Down
124 changes: 45 additions & 79 deletions src/compute/leaf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use core::unreachable;
pub fn compute_leaf_layout<MeasureFunction>(
inputs: LayoutInput,
style: &Style,
measure_function: Option<MeasureFunction>,
measure_function: MeasureFunction,
) -> LayoutOutput
where
MeasureFunction: FnOnce(Size<Option<f32>>, Size<AvailableSpace>) -> Size<f32>,
Expand Down Expand Up @@ -80,7 +80,7 @@ where
debug_log!("max_size ", dbg:node_max_size);

// Return early if both width and height are known
if run_mode == RunMode::ComputeSize {
if run_mode == RunMode::ComputeSize && has_styles_preventing_being_collapsed_through {
if let Size { width: Some(width), height: Some(height) } = node_size {
let size = Size { width, height }
.maybe_clamp(node_min_size, node_max_size)
Expand All @@ -92,99 +92,65 @@ where
first_baselines: Point::NONE,
top_margin: CollapsibleMarginSet::ZERO,
bottom_margin: CollapsibleMarginSet::ZERO,
margins_can_collapse_through: !has_styles_preventing_being_collapsed_through
&& size.height == 0.0
&& measure_function.is_none(),
margins_can_collapse_through: false,
};
};
}

if let Some(measure_function) = measure_function {
// Compute available space
let available_space = Size {
width: known_dimensions
.width
.map(AvailableSpace::from)
.unwrap_or(available_space.width)
.maybe_sub(margin.horizontal_axis_sum())
.maybe_set(known_dimensions.width)
.maybe_set(node_size.width)
.maybe_set(node_max_size.width)
.map_definite_value(|size| {
size.maybe_clamp(node_min_size.width, node_max_size.width) - content_box_inset.horizontal_axis_sum()
}),
height: known_dimensions
.height
.map(AvailableSpace::from)
.unwrap_or(available_space.height)
.maybe_sub(margin.vertical_axis_sum())
.maybe_set(known_dimensions.height)
.maybe_set(node_size.height)
.maybe_set(node_max_size.height)
.map_definite_value(|size| {
size.maybe_clamp(node_min_size.height, node_max_size.height) - content_box_inset.vertical_axis_sum()
}),
};

// Measure node
let measured_size = measure_function(
match run_mode {
RunMode::ComputeSize => known_dimensions,
RunMode::PerformLayout => Size::NONE,
RunMode::PerformHiddenLayout => unreachable!(),
},
available_space,
);
let clamped_size = known_dimensions
.or(node_size)
.unwrap_or(measured_size + content_box_inset.sum_axes())
.maybe_clamp(node_min_size, node_max_size);
let size = Size {
width: clamped_size.width,
height: f32_max(clamped_size.height, aspect_ratio.map(|ratio| clamped_size.width / ratio).unwrap_or(0.0)),
};
let size = size.maybe_max(padding_border.sum_axes().map(Some));

return LayoutOutput {
size,
#[cfg(feature = "content_size")]
content_size: measured_size + padding.sum_axes(),
first_baselines: Point::NONE,
top_margin: CollapsibleMarginSet::ZERO,
bottom_margin: CollapsibleMarginSet::ZERO,
margins_can_collapse_through: !has_styles_preventing_being_collapsed_through
&& size.height == 0.0
&& measured_size.height == 0.0,
};
}

let size = Size {
width: node_size
// Compute available space
let available_space = Size {
width: known_dimensions
.width
// .unwrap_or(0.0) + padding.horizontal_axis_sum() + border.horizontal_axis_sum(), // content-box
.unwrap_or(content_box_inset.horizontal_axis_sum()) // border-box
.maybe_clamp(node_min_size.width, node_max_size.width)
.maybe_max(padding_border.horizontal_axis_sum().into()),
height: node_size
.map(AvailableSpace::from)
.unwrap_or(available_space.width)
.maybe_sub(margin.horizontal_axis_sum())
.maybe_set(known_dimensions.width)
.maybe_set(node_size.width)
.maybe_set(node_max_size.width)
.map_definite_value(|size| {
size.maybe_clamp(node_min_size.width, node_max_size.width) - content_box_inset.horizontal_axis_sum()
}),
height: known_dimensions
.height
// .unwrap_or(0.0) + padding.vertical_axis_sum() + border.vertical_axis_sum(), // content-box
.unwrap_or(content_box_inset.vertical_axis_sum()) // border-box
.maybe_clamp(node_min_size.height, node_max_size.height)
.maybe_max(padding_border.vertical_axis_sum().into()),
.map(AvailableSpace::from)
.unwrap_or(available_space.height)
.maybe_sub(margin.vertical_axis_sum())
.maybe_set(known_dimensions.height)
.maybe_set(node_size.height)
.maybe_set(node_max_size.height)
.map_definite_value(|size| {
size.maybe_clamp(node_min_size.height, node_max_size.height) - content_box_inset.vertical_axis_sum()
}),
};

// Measure node
let measured_size = measure_function(
match run_mode {
RunMode::ComputeSize => known_dimensions,
RunMode::PerformLayout => Size::NONE,
RunMode::PerformHiddenLayout => unreachable!(),
},
available_space,
);
let clamped_size = known_dimensions
.or(node_size)
.unwrap_or(measured_size + content_box_inset.sum_axes())
.maybe_clamp(node_min_size, node_max_size);
let size = Size {
width: f32_max(size.width, aspect_ratio.map(|ratio| size.height * ratio).unwrap_or(0.0)),
height: f32_max(size.height, aspect_ratio.map(|ratio| size.width / ratio).unwrap_or(0.0)),
width: clamped_size.width,
height: f32_max(clamped_size.height, aspect_ratio.map(|ratio| clamped_size.width / ratio).unwrap_or(0.0)),
};
let size = size.maybe_max(padding_border.sum_axes().map(Some));

LayoutOutput {
size,
#[cfg(feature = "content_size")]
content_size: padding.sum_axes(),
content_size: measured_size + padding.sum_axes(),
first_baselines: Point::NONE,
top_margin: CollapsibleMarginSet::ZERO,
bottom_margin: CollapsibleMarginSet::ZERO,
margins_can_collapse_through: !has_styles_preventing_being_collapsed_through && size.height == 0.0,
margins_can_collapse_through: !has_styles_preventing_being_collapsed_through
&& size.height == 0.0
&& measured_size.height == 0.0,
}
}
20 changes: 10 additions & 10 deletions src/tree/taffy_tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,8 @@ struct NodeData {
/// These may be rounded or unrounded depending on what the `use_rounding` config setting is set to.
pub(crate) final_layout: Layout,

/// Should we try and measure this node?
pub(crate) needs_measure: bool,
/// Whether the node has context data associated with it or not
pub(crate) has_context: bool,

/// The cached results of the layout computation
pub(crate) cache: Cache,
Expand All @@ -108,7 +108,7 @@ impl NodeData {
cache: Cache::new(),
unrounded_layout: Layout::new(),
final_layout: Layout::new(),
needs_measure: false,
has_context: false,
}
}

Expand Down Expand Up @@ -317,11 +317,11 @@ where
(_, false) => {
let node_key = node.into();
let style = &tree.taffy.nodes[node_key].style;
let needs_measure = tree.taffy.nodes[node_key].needs_measure;
let measure_function = needs_measure.then_some(|known_dimensions, available_space| {
let node_context = tree.taffy.node_context_data.get_mut(node_key);
let has_context = tree.taffy.nodes[node_key].has_context;
let node_context = has_context.then(|| tree.taffy.node_context_data.get_mut(node_key)).flatten();
let measure_function = |known_dimensions, available_space| {
(tree.measure_function)(known_dimensions, available_space, node, node_context)
});
};
compute_leaf_layout(inputs, style, measure_function)
}
}
Expand Down Expand Up @@ -393,7 +393,7 @@ impl<NodeContext> TaffyTree<NodeContext> {
/// Creates and adds a new leaf node with a supplied context
pub fn new_leaf_with_context(&mut self, layout: Style, context: NodeContext) -> TaffyResult<NodeId> {
let mut data = NodeData::new(layout);
data.needs_measure = true;
data.has_context = true;

let id = self.nodes.insert(data);
self.node_context_data.insert(id, context);
Expand Down Expand Up @@ -454,10 +454,10 @@ impl<NodeContext> TaffyTree<NodeContext> {
pub fn set_node_context(&mut self, node: NodeId, measure: Option<NodeContext>) -> TaffyResult<()> {
let key = node.into();
if let Some(measure) = measure {
self.nodes[key].needs_measure = true;
self.nodes[key].has_context = true;
self.node_context_data.insert(key, measure);
} else {
self.nodes[key].needs_measure = false;
self.nodes[key].has_context = false;
self.node_context_data.remove(key);
}

Expand Down
2 changes: 1 addition & 1 deletion tests/measure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ mod measure {
_node_id: NodeId,
node_context: Option<&mut AspectRatioMeasure>,
) -> taffy::geometry::Size<f32> {
let node_context = node_context.unwrap();
let Some(node_context) = node_context else { return Size::ZERO };
let width = known_dimensions.width.unwrap_or(node_context.width);
let height = known_dimensions.height.unwrap_or(width * node_context.height_ratio);
Size { width, height }
Expand Down