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
1 change: 1 addition & 0 deletions benches/src/yoga_helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,7 @@ fn apply_taffy_style(node: &mut yg::Node, style: &tf::Style) {

// position
node.set_position_type(match style.position {
tf::Position::Static => yg::PositionType::Static,
tf::Position::Relative => yg::PositionType::Relative,
tf::Position::Absolute => yg::PositionType::Absolute,
});
Expand Down
27 changes: 16 additions & 11 deletions src/compute/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -174,21 +174,21 @@ fn compute_inner(tree: &mut impl LayoutBlockContainer, node_id: NodeId, inputs:
start: vertical_margins_are_collapsible.start
&& !style.overflow().x.is_scroll_container()
&& !style.overflow().y.is_scroll_container()
&& style.position() == Position::Relative
&& style.position().is_in_flow()
&& padding.top == 0.0
&& border.top == 0.0,
end: vertical_margins_are_collapsible.end
&& !style.overflow().x.is_scroll_container()
&& !style.overflow().y.is_scroll_container()
&& style.position() == Position::Relative
&& style.position().is_in_flow()
&& padding.bottom == 0.0
&& border.bottom == 0.0
&& size.height.is_none(),
};
let has_styles_preventing_being_collapsed_through = !style.is_block()
|| style.overflow().x.is_scroll_container()
|| style.overflow().y.is_scroll_container()
|| style.position() == Position::Absolute
|| style.position().is_out_of_flow()
|| padding.top > 0.0
|| padding.bottom > 0.0
|| border.top > 0.0
Expand Down Expand Up @@ -267,7 +267,7 @@ fn compute_inner(tree: &mut impl LayoutBlockContainer, node_id: NodeId, inputs:

// 7. Determine whether this node can be collapsed through
let all_in_flow_children_can_be_collapsed_through =
items.iter().all(|item| item.position == Position::Absolute || item.can_be_collapsed_through);
items.iter().all(|item| item.position.is_out_of_flow() || item.can_be_collapsed_through);
let can_be_collapsed_through =
!has_styles_preventing_being_collapsed_through && all_in_flow_children_can_be_collapsed_through;

Expand Down Expand Up @@ -361,7 +361,7 @@ fn determine_content_based_container_width(
let available_space = Size { width: available_width, height: AvailableSpace::MinContent };

let mut max_child_width = 0.0;
for item in items.iter().filter(|item| item.position != Position::Absolute) {
for item in items.iter().filter(|item| item.position.is_in_flow()) {
let known_dimensions = item.size.maybe_clamp(item.min_size, item.max_size);

let width = known_dimensions.width.unwrap_or_else(|| {
Expand Down Expand Up @@ -413,7 +413,7 @@ fn perform_final_layout_on_in_flow_children(
let mut active_collapsible_margin_set = CollapsibleMarginSet::ZERO;
let mut is_collapsing_with_first_margin_set = true;
for item in items.iter_mut() {
if item.position == Position::Absolute {
if item.position.is_out_of_flow() {
item.static_position = Point { x: resolved_content_box_inset.left, y: y_offset_for_absolute }
} else {
let item_margin = item
Expand Down Expand Up @@ -490,11 +490,17 @@ fn perform_final_layout_on_in_flow_children(
x: resolved_content_box_inset.left,
y: committed_y_offset + active_collapsible_margin_set.resolve(),
};

let mut location = Point {
x: resolved_content_box_inset.left + inset_offset.x + resolved_margin.left,
y: committed_y_offset + inset_offset.y + y_margin_offset,
x: resolved_content_box_inset.left + resolved_margin.left,
y: committed_y_offset + y_margin_offset,
};

if item.position == Position::Relative {
location.x += inset_offset.x;
location.y += inset_offset.y;
}

// Apply alignment
let item_outer_width = item_layout.size.width + resolved_margin.horizontal_axis_sum();
if item_outer_width < container_inner_width {
Expand Down Expand Up @@ -589,12 +595,11 @@ fn perform_absolute_layout_on_absolute_children(
#[cfg_attr(not(feature = "content_size"), allow(unused_mut))]
let mut absolute_content_size = Size::ZERO;

for item in items.iter().filter(|item| item.position == Position::Absolute) {
for item in items.iter().filter(|item| item.position.is_out_of_flow()) {
let child_style = tree.get_block_child_style(item.node_id);

// Skip items that are display:none or are not position:absolute
if child_style.box_generation_mode() == BoxGenerationMode::None || child_style.position() != Position::Absolute
{
if child_style.box_generation_mode() == BoxGenerationMode::None {
continue;
}

Expand Down
31 changes: 17 additions & 14 deletions src/compute/flexbox.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ use crate::compute::common::alignment::compute_alignment_offset;
use crate::geometry::{Line, Point, Rect, Size};
use crate::style::{
AlignContent, AlignItems, AlignSelf, AvailableSpace, FlexWrap, JustifyContent, LengthPercentageAuto, Overflow,
Position,
};
use crate::style::{CoreStyle, FlexDirection, FlexboxContainerStyle, FlexboxItemStyle};
use crate::style_helpers::{TaffyMaxContent, TaffyMinContent};
Expand All @@ -13,7 +12,7 @@ use crate::util::debug::debug_log;
use crate::util::sys::{f32_max, new_vec_with_capacity, Vec};
use crate::util::MaybeMath;
use crate::util::{MaybeResolve, ResolveOrZero};
use crate::{BoxGenerationMode, BoxSizing};
use crate::{BoxGenerationMode, BoxSizing, Position};

use super::common::alignment::apply_alignment_fallback;
#[cfg(feature = "content_size")]
Expand All @@ -36,6 +35,9 @@ struct FlexItem {
/// The cross-alignment of this item
align_self: AlignSelf,

/// The position style of the item
position: Position,

/// The overflow style of the item
overflow: Point<Overflow>,
/// The width of the scrollbars (if it has any)
Expand Down Expand Up @@ -502,7 +504,7 @@ fn generate_anonymous_flex_items(
tree.child_ids(node)
.enumerate()
.map(|(index, child)| (index, child, tree.get_flexbox_child_style(child)))
.filter(|(_, _, style)| style.position() != Position::Absolute)
.filter(|(_, _, style)| style.position().is_in_flow())
.filter(|(_, _, style)| style.box_generation_mode() != BoxGenerationMode::None)
.map(|(index, child, child_style)| {
let aspect_ratio = child_style.aspect_ratio();
Expand All @@ -518,6 +520,7 @@ fn generate_anonymous_flex_items(
FlexItem {
node: child,
order: index as u32,
position: child_style.position(),
size: child_style
.size()
.maybe_resolve(constants.node_inner_size, |val, basis| tree.calc(val, basis))
Expand Down Expand Up @@ -1903,16 +1906,17 @@ fn calculate_flex_item(
..
} = layout_output;

let offset_main = *total_offset_main
+ item.offset_main
+ item.margin.main_start(direction)
+ (item.inset.main_start(direction).or(item.inset.main_end(direction).map(|pos| -pos)).unwrap_or(0.0));
let mut offset_main = *total_offset_main + item.offset_main + item.margin.main_start(direction);

let mut offset_cross =
total_offset_cross + item.offset_cross + line_offset_cross + item.margin.cross_start(direction);

let offset_cross = total_offset_cross
+ item.offset_cross
+ line_offset_cross
+ item.margin.cross_start(direction)
+ (item.inset.cross_start(direction).or(item.inset.cross_end(direction).map(|pos| -pos)).unwrap_or(0.0));
if item.position == Position::Relative {
offset_main +=
item.inset.main_start(direction).or(item.inset.main_end(direction).map(|pos| -pos)).unwrap_or(0.0);
offset_cross +=
item.inset.cross_start(direction).or(item.inset.cross_end(direction).map(|pos| -pos)).unwrap_or(0.0);
}

if direction.is_row() {
let baseline_offset_cross = total_offset_cross + item.offset_cross + item.margin.cross_start(direction);
Expand Down Expand Up @@ -2075,8 +2079,7 @@ fn perform_absolute_layout_on_absolute_children(
let child_style = tree.get_flexbox_child_style(child);

// Skip items that are display:none or are not position:absolute
if child_style.box_generation_mode() == BoxGenerationMode::None || child_style.position() != Position::Absolute
{
if child_style.box_generation_mode() == BoxGenerationMode::None || child_style.position().is_in_flow() {
continue;
}

Expand Down
10 changes: 5 additions & 5 deletions src/compute/grid/alignment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ pub(super) fn align_and_position_item(
let width = inherent_size.width.or_else(|| {
// Apply width derived from both the left and right properties of an absolutely
// positioned element being set
if position == Position::Absolute {
if position.is_out_of_flow() {
if let (Some(left), Some(right)) = (inset_horizontal.start, inset_horizontal.end) {
return Some(f32_max(grid_area_minus_item_margins_size.width - left - right, 0.0));
}
Expand All @@ -159,7 +159,7 @@ pub(super) fn align_and_position_item(
if margin.left.is_some()
&& margin.right.is_some()
&& alignment_styles.horizontal == AlignSelf::Stretch
&& position != Position::Absolute
&& position.is_in_flow()
{
return Some(grid_area_minus_item_margins_size.width);
}
Expand All @@ -171,7 +171,7 @@ pub(super) fn align_and_position_item(
let Size { width, height } = Size { width, height: inherent_size.height }.maybe_apply_aspect_ratio(aspect_ratio);

let height = height.or_else(|| {
if position == Position::Absolute {
if position.is_out_of_flow() {
if let (Some(top), Some(bottom)) = (inset_vertical.start, inset_vertical.end) {
return Some(f32_max(grid_area_minus_item_margins_size.height - top - bottom, 0.0));
}
Expand All @@ -184,7 +184,7 @@ pub(super) fn align_and_position_item(
if margin.top.is_some()
&& margin.bottom.is_some()
&& alignment_styles.vertical == AlignSelf::Stretch
&& position != Position::Absolute
&& position.is_in_flow()
{
return Some(grid_area_minus_item_margins_size.height);
}
Expand Down Expand Up @@ -309,7 +309,7 @@ pub(super) fn align_item_within_area(
AlignSelf::Stretch => resolved_margin.start,
};

let offset_within_area = if position == Position::Absolute {
let offset_within_area = if position.is_out_of_flow() {
if let Some(start) = inset.start {
start + non_auto_margin.start
} else if let Some(end) = inset.end {
Expand Down
6 changes: 3 additions & 3 deletions src/compute/grid/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
//! <https://www.w3.org/TR/css-grid-1>
use crate::geometry::{AbsoluteAxis, AbstractAxis, InBothAbsAxis};
use crate::geometry::{Line, Point, Rect, Size};
use crate::style::{AlignItems, AlignSelf, AvailableSpace, Overflow, Position};
use crate::style::{AlignItems, AlignSelf, AvailableSpace, Overflow};
use crate::tree::{Layout, LayoutInput, LayoutOutput, LayoutPartialTreeExt, NodeId, RunMode, SizingMode};
use crate::util::debug::debug_log;
use crate::util::sys::{f32_max, GridTrackVec, Vec};
Expand Down Expand Up @@ -202,7 +202,7 @@ pub fn compute_grid_layout<Tree: LayoutGridContainer>(
.enumerate()
.map(|(index, child_node)| (index, child_node, tree.get_grid_child_style(child_node)))
.filter(|(_, _, style)| {
style.box_generation_mode() != BoxGenerationMode::None && style.position() != Position::Absolute
style.box_generation_mode() != BoxGenerationMode::None && style.position().is_in_flow()
})
};
place_grid_items(
Expand Down Expand Up @@ -548,7 +548,7 @@ pub fn compute_grid_layout<Tree: LayoutGridContainer>(
}

// Position absolutely positioned child
if child_style.position() == Position::Absolute {
if child_style.position().is_out_of_flow() {
// Convert grid-col-{start/end} into Option's of indexes into the columns vector
// The Option is None if the style property is Auto and an unresolvable Span
let maybe_col_indexes = name_resolver
Expand Down
4 changes: 2 additions & 2 deletions src/compute/leaf.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! Computes size using styles and measure functions

use crate::geometry::{Point, Size};
use crate::style::{AvailableSpace, Overflow, Position};
use crate::style::{AvailableSpace, Overflow};
use crate::tree::{CollapsibleMarginSet, RunMode};
use crate::tree::{LayoutInput, LayoutOutput, SizingMode};
use crate::util::debug::debug_log;
Expand Down Expand Up @@ -76,7 +76,7 @@ where
let has_styles_preventing_being_collapsed_through = !style.is_block()
|| style.overflow().x.is_scroll_container()
|| style.overflow().y.is_scroll_container()
|| style.position() == Position::Absolute
|| style.position().is_out_of_flow()
|| padding.top > 0.0
|| padding.bottom > 0.0
|| border.top > 0.0
Expand Down
22 changes: 22 additions & 0 deletions src/style/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,8 @@ impl Default for BoxGenerationMode {
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum Position {
/// Offets are not applied
Static,
/// The offset is computed relative to the final position given by the layout algorithm.
/// Offsets do not affect the position of any other items; they are effectively a correction factor applied at the end.
Relative,
Expand All @@ -271,6 +273,26 @@ impl Default for Position {
}
}

impl Position {
/// Whether the element has a non-static position
#[inline(always)]
pub fn is_positioned(self) -> bool {
!matches!(self, Self::Static)
}

/// Whether the element is positioned out-of-flow (absolute or fixed position)
#[inline(always)]
pub fn is_out_of_flow(self) -> bool {
matches!(self, Self::Absolute)
}

/// Whether the element is positioned in-flow (NOT absolute or fixed position)
#[inline(always)]
pub fn is_in_flow(self) -> bool {
!self.is_out_of_flow()
}
}

/// Specifies whether size styles for this node are assigned to the node's "content box" or "border box"
///
/// - The "content box" is the node's inner size excluding padding, border and margin
Expand Down