aboutsummaryrefslogtreecommitdiffstats
path: root/components/layout
diff options
context:
space:
mode:
Diffstat (limited to 'components/layout')
-rw-r--r--components/layout/display_list/stacking_context.rs4
-rw-r--r--components/layout/flow/construct.rs7
-rw-r--r--components/layout/flow/mod.rs31
-rw-r--r--components/layout/flow/root.rs24
-rw-r--r--components/layout/fragment_tree/box_fragment.rs44
-rw-r--r--components/layout/fragment_tree/fragment.rs23
-rw-r--r--components/layout/fragment_tree/fragment_tree.rs43
-rw-r--r--components/layout/fragment_tree/positioning_fragment.rs31
-rw-r--r--components/layout/layout_impl.rs38
-rw-r--r--components/layout/positioned.rs7
-rw-r--r--components/layout/query.rs4
-rw-r--r--components/layout/stylesheets/servo.css4
-rw-r--r--components/layout/taffy/layout.rs9
-rw-r--r--components/layout/taffy/mod.rs14
-rw-r--r--components/layout/taffy/stylo_taffy/convert.rs78
-rw-r--r--components/layout/taffy/stylo_taffy/wrapper.rs81
16 files changed, 261 insertions, 181 deletions
diff --git a/components/layout/display_list/stacking_context.rs b/components/layout/display_list/stacking_context.rs
index 66d8421e5f7..17e8f2ef4fd 100644
--- a/components/layout/display_list/stacking_context.rs
+++ b/components/layout/display_list/stacking_context.rs
@@ -618,7 +618,7 @@ impl StackingContext {
// If it’s larger, we also want to paint areas reachable after scrolling.
let painting_area = fragment_tree
.initial_containing_block
- .union(&fragment_tree.scrollable_overflow)
+ .union(&fragment_tree.scrollable_overflow())
.to_webrender();
let background_color =
@@ -1346,7 +1346,7 @@ impl BoxFragment {
let position = self.style.get_box().position;
// https://drafts.csswg.org/css2/#clipping
// The clip property applies only to absolutely positioned elements
- if position != ComputedPosition::Absolute && position != ComputedPosition::Fixed {
+ if !position.is_absolutely_positioned() {
return None;
}
diff --git a/components/layout/flow/construct.rs b/components/layout/flow/construct.rs
index cc3fe0e6f44..d8d6cd5c6ab 100644
--- a/components/layout/flow/construct.rs
+++ b/components/layout/flow/construct.rs
@@ -744,9 +744,14 @@ impl BlockLevelJob<'_> {
self.propagated_data,
false, /* is_list_item */
);
+ // An outside ::marker must establish a BFC, and can't contain floats.
+ let block_formatting_context = BlockFormattingContext {
+ contents: block_container,
+ contains_floats: false,
+ };
ArcRefCell::new(BlockLevelBox::OutsideMarker(OutsideMarker {
base: LayoutBoxBase::new(info.into(), info.style.clone()),
- block_container,
+ block_formatting_context,
list_item_style,
}))
},
diff --git a/components/layout/flow/mod.rs b/components/layout/flow/mod.rs
index 4776b65771c..81343d81111 100644
--- a/components/layout/flow/mod.rs
+++ b/components/layout/flow/mod.rs
@@ -308,7 +308,7 @@ pub(crate) struct CollapsibleWithParentStartMargin(bool);
pub(crate) struct OutsideMarker {
pub list_item_style: Arc<ComputedValues>,
pub base: LayoutBoxBase,
- pub block_container: BlockContainer,
+ pub block_formatting_context: BlockFormattingContext,
}
impl OutsideMarker {
@@ -317,8 +317,11 @@ impl OutsideMarker {
layout_context: &LayoutContext,
constraint_space: &ConstraintSpace,
) -> InlineContentSizesResult {
- self.base
- .inline_content_sizes(layout_context, constraint_space, &self.block_container)
+ self.base.inline_content_sizes(
+ layout_context,
+ constraint_space,
+ &self.block_formatting_context.contents,
+ )
}
fn layout(
@@ -326,8 +329,6 @@ impl OutsideMarker {
layout_context: &LayoutContext<'_>,
containing_block: &ContainingBlock<'_>,
positioning_context: &mut PositioningContext,
- sequential_layout_state: Option<&mut SequentialLayoutState>,
- collapsible_with_parent_start_margin: Option<CollapsibleWithParentStartMargin>,
) -> Fragment {
let constraint_space = ConstraintSpace::new_for_style_and_ratio(
&self.base.style,
@@ -342,17 +343,11 @@ impl OutsideMarker {
style: &self.base.style,
};
- // A ::marker can't have a stretch size (must be auto), so this doesn't matter.
- // https://drafts.csswg.org/css-sizing-4/#stretch-fit-sizing
- let ignore_block_margins_for_stretch = LogicalSides1D::new(false, false);
-
- let flow_layout = self.block_container.layout(
+ let flow_layout = self.block_formatting_context.layout(
layout_context,
positioning_context,
&containing_block_for_children,
- sequential_layout_state,
- collapsible_with_parent_start_margin.unwrap_or(CollapsibleWithParentStartMargin(false)),
- ignore_block_margins_for_stretch,
+ false, /* depends_on_block_constraints */
);
let max_inline_size =
@@ -900,13 +895,9 @@ impl BlockLevelBox {
BlockLevelBox::OutOfFlowFloatBox(float_box) => Fragment::Float(ArcRefCell::new(
float_box.layout(layout_context, positioning_context, containing_block),
)),
- BlockLevelBox::OutsideMarker(outside_marker) => outside_marker.layout(
- layout_context,
- containing_block,
- positioning_context,
- sequential_layout_state,
- collapsible_with_parent_start_margin,
- ),
+ BlockLevelBox::OutsideMarker(outside_marker) => {
+ outside_marker.layout(layout_context, containing_block, positioning_context)
+ },
};
self.with_base(|base| base.set_fragment(fragment.clone()));
diff --git a/components/layout/flow/root.rs b/components/layout/flow/root.rs
index fb9884a4f01..fe98dbc3156 100644
--- a/components/layout/flow/root.rs
+++ b/components/layout/flow/root.rs
@@ -29,7 +29,7 @@ use crate::flow::inline::InlineItem;
use crate::flow::{BlockContainer, BlockFormattingContext, BlockLevelBox};
use crate::formatting_contexts::IndependentFormattingContext;
use crate::fragment_tree::FragmentTree;
-use crate::geom::{LogicalVec2, PhysicalRect, PhysicalSize};
+use crate::geom::{LogicalVec2, PhysicalSize};
use crate::positioned::{AbsolutelyPositionedBox, PositioningContext};
use crate::replaced::ReplacedContents;
use crate::style_ext::{Display, DisplayGeneratingBox, DisplayInside};
@@ -392,31 +392,9 @@ impl BoxTree {
&mut root_fragments,
);
- let scrollable_overflow = root_fragments
- .iter()
- .fold(PhysicalRect::zero(), |acc, child| {
- let child_overflow = child.scrollable_overflow_for_parent();
-
- // https://drafts.csswg.org/css-overflow/#scrolling-direction
- // We want to clip scrollable overflow on box-start and inline-start
- // sides of the scroll container.
- //
- // FIXME(mrobinson, bug 25564): This should take into account writing
- // mode.
- let child_overflow = PhysicalRect::new(
- euclid::Point2D::zero(),
- euclid::Size2D::new(
- child_overflow.size.width + child_overflow.origin.x,
- child_overflow.size.height + child_overflow.origin.y,
- ),
- );
- acc.union(&child_overflow)
- });
-
FragmentTree::new(
layout_context,
root_fragments,
- scrollable_overflow,
physical_containing_block,
self.viewport_scroll_sensitivity,
)
diff --git a/components/layout/fragment_tree/box_fragment.rs b/components/layout/fragment_tree/box_fragment.rs
index b7c3a2a3524..eb63038b7d7 100644
--- a/components/layout/fragment_tree/box_fragment.rs
+++ b/components/layout/fragment_tree/box_fragment.rs
@@ -89,7 +89,7 @@ pub(crate) struct BoxFragment {
block_margins_collapsed_with_children: Option<Box<CollapsedBlockMargins>>,
/// The scrollable overflow of this box fragment.
- pub scrollable_overflow_from_children: PhysicalRect<Au>,
+ scrollable_overflow: Option<PhysicalRect<Au>>,
/// The resolved box insets if this box is `position: sticky`. These are calculated
/// during `StackingContextTree` construction because they rely on the size of the
@@ -114,11 +114,6 @@ impl BoxFragment {
margin: PhysicalSides<Au>,
clearance: Option<Au>,
) -> BoxFragment {
- let scrollable_overflow_from_children =
- children.iter().fold(PhysicalRect::zero(), |acc, child| {
- acc.union(&child.scrollable_overflow_for_parent())
- });
-
BoxFragment {
base: base_fragment_info.into(),
style,
@@ -131,7 +126,7 @@ impl BoxFragment {
clearance,
baselines: Baselines::default(),
block_margins_collapsed_with_children: None,
- scrollable_overflow_from_children,
+ scrollable_overflow: None,
resolved_sticky_insets: AtomicRefCell::default(),
background_mode: BackgroundMode::Normal,
specific_layout_info: None,
@@ -203,13 +198,23 @@ impl BoxFragment {
/// Get the scrollable overflow for this [`BoxFragment`] relative to its
/// containing block.
pub fn scrollable_overflow(&self) -> PhysicalRect<Au> {
+ self.scrollable_overflow
+ .expect("Should only call `scrollable_overflow()` after calculating overflow")
+ }
+
+ pub(crate) fn calculate_scrollable_overflow(&mut self) {
+ let scrollable_overflow_from_children = self
+ .children
+ .iter()
+ .fold(PhysicalRect::zero(), |acc, child| {
+ acc.union(&child.calculate_scrollable_overflow_for_parent())
+ });
let physical_padding_rect = self.padding_rect();
let content_origin = self.content_rect.origin.to_vector();
- physical_padding_rect.union(
- &self
- .scrollable_overflow_from_children
- .translate(content_origin),
- )
+ self.scrollable_overflow = Some(
+ physical_padding_rect
+ .union(&scrollable_overflow_from_children.translate(content_origin)),
+ );
}
pub(crate) fn set_containing_block(&mut self, containing_block: &PhysicalRect<Au>) {
@@ -275,7 +280,12 @@ impl BoxFragment {
tree.end_level();
}
- pub fn scrollable_overflow_for_parent(&self) -> PhysicalRect<Au> {
+ pub(crate) fn scrollable_overflow_for_parent(&self) -> PhysicalRect<Au> {
+ // TODO: Properly handle absolutely positioned fragments.
+ if self.style.get_box().position.is_absolutely_positioned() {
+ return PhysicalRect::zero();
+ }
+
let mut overflow = self.border_rect();
if !self.style.establishes_scroll_container(self.base.flags) {
// https://www.w3.org/TR/css-overflow-3/#scrollable
@@ -328,7 +338,7 @@ impl BoxFragment {
///
/// Return the clipped the scrollable overflow based on its scroll origin, determined by overflow direction.
/// For an element, the clip rect is the padding rect and for viewport, it is the initial containing block.
- pub fn clip_unreachable_scrollable_overflow_region(
+ pub(crate) fn clip_unreachable_scrollable_overflow_region(
&self,
scrollable_overflow: PhysicalRect<Au>,
clipping_rect: PhysicalRect<Au>,
@@ -362,7 +372,7 @@ impl BoxFragment {
///
/// Return the clipped the scrollable overflow based on its scroll origin, determined by overflow direction.
/// This will coincides with the scrollport if the fragment is a scroll container.
- pub fn reachable_scrollable_overflow_region(&self) -> PhysicalRect<Au> {
+ pub(crate) fn reachable_scrollable_overflow_region(&self) -> PhysicalRect<Au> {
self.clip_unreachable_scrollable_overflow_region(
self.scrollable_overflow(),
self.padding_rect(),
@@ -421,9 +431,7 @@ impl BoxFragment {
return convert_to_au_or_auto(PhysicalSides::new(top, right, bottom, left));
}
- debug_assert!(
- position == ComputedPosition::Fixed || position == ComputedPosition::Absolute
- );
+ debug_assert!(position.is_absolutely_positioned());
let margin_rect = self.margin_rect();
let (top, bottom) = match (&insets.top, &insets.bottom) {
diff --git a/components/layout/fragment_tree/fragment.rs b/components/layout/fragment_tree/fragment.rs
index c81fd59e36b..10338c78743 100644
--- a/components/layout/fragment_tree/fragment.rs
+++ b/components/layout/fragment_tree/fragment.rs
@@ -183,19 +183,36 @@ impl Fragment {
}
}
- pub fn scrollable_overflow_for_parent(&self) -> PhysicalRect<Au> {
+ pub(crate) fn scrollable_overflow_for_parent(&self) -> PhysicalRect<Au> {
match self {
Fragment::Box(fragment) | Fragment::Float(fragment) => {
- fragment.borrow().scrollable_overflow_for_parent()
+ return fragment.borrow().scrollable_overflow_for_parent();
},
Fragment::AbsoluteOrFixedPositioned(_) => PhysicalRect::zero(),
- Fragment::Positioning(fragment) => fragment.borrow().scrollable_overflow,
+ Fragment::Positioning(fragment) => fragment.borrow().scrollable_overflow_for_parent(),
Fragment::Text(fragment) => fragment.borrow().rect,
Fragment::Image(fragment) => fragment.borrow().rect,
Fragment::IFrame(fragment) => fragment.borrow().rect,
}
}
+ pub(crate) fn calculate_scrollable_overflow_for_parent(&self) -> PhysicalRect<Au> {
+ self.calculate_scrollable_overflow();
+ self.scrollable_overflow_for_parent()
+ }
+
+ pub(crate) fn calculate_scrollable_overflow(&self) {
+ match self {
+ Fragment::Box(fragment) | Fragment::Float(fragment) => {
+ fragment.borrow_mut().calculate_scrollable_overflow()
+ },
+ Fragment::Positioning(fragment) => {
+ fragment.borrow_mut().calculate_scrollable_overflow()
+ },
+ _ => {},
+ }
+ }
+
pub(crate) fn cumulative_border_box_rect(&self) -> Option<PhysicalRect<Au>> {
match self {
Fragment::Box(fragment) | Fragment::Float(fragment) => {
diff --git a/components/layout/fragment_tree/fragment_tree.rs b/components/layout/fragment_tree/fragment_tree.rs
index ba03a72ac21..b59ace43aa6 100644
--- a/components/layout/fragment_tree/fragment_tree.rs
+++ b/components/layout/fragment_tree/fragment_tree.rs
@@ -2,14 +2,14 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
+use std::cell::Cell;
+
use app_units::Au;
use base::print_tree::PrintTree;
use compositing_traits::display_list::AxesScrollSensitivity;
-use euclid::default::Size2D;
use fxhash::FxHashSet;
use malloc_size_of_derive::MallocSizeOf;
use style::animation::AnimationSetKey;
-use webrender_api::units;
use super::{BoxFragment, ContainingBlockManager, Fragment};
use crate::ArcRefCell;
@@ -30,7 +30,7 @@ pub struct FragmentTree {
/// The scrollable overflow rectangle for the entire tree
/// <https://drafts.csswg.org/css-overflow/#scrollable>
- pub(crate) scrollable_overflow: PhysicalRect<Au>,
+ scrollable_overflow: Cell<Option<PhysicalRect<Au>>>,
/// The containing block used in the layout of this fragment tree.
pub(crate) initial_containing_block: PhysicalRect<Au>,
@@ -43,13 +43,12 @@ impl FragmentTree {
pub(crate) fn new(
layout_context: &LayoutContext,
root_fragments: Vec<Fragment>,
- scrollable_overflow: PhysicalRect<Au>,
initial_containing_block: PhysicalRect<Au>,
viewport_scroll_sensitivity: AxesScrollSensitivity,
) -> Self {
let fragment_tree = Self {
root_fragments,
- scrollable_overflow,
+ scrollable_overflow: Cell::default(),
initial_containing_block,
viewport_scroll_sensitivity,
};
@@ -97,11 +96,35 @@ impl FragmentTree {
}
}
- pub fn scrollable_overflow(&self) -> units::LayoutSize {
- units::LayoutSize::from_untyped(Size2D::new(
- self.scrollable_overflow.size.width.to_f32_px(),
- self.scrollable_overflow.size.height.to_f32_px(),
- ))
+ pub(crate) fn scrollable_overflow(&self) -> PhysicalRect<Au> {
+ self.scrollable_overflow
+ .get()
+ .expect("Should only call `scrollable_overflow()` after calculating overflow")
+ }
+
+ pub(crate) fn calculate_scrollable_overflow(&self) {
+ self.scrollable_overflow
+ .set(Some(self.root_fragments.iter().fold(
+ PhysicalRect::zero(),
+ |acc, child| {
+ let child_overflow = child.calculate_scrollable_overflow_for_parent();
+
+ // https://drafts.csswg.org/css-overflow/#scrolling-direction
+ // We want to clip scrollable overflow on box-start and inline-start
+ // sides of the scroll container.
+ //
+ // FIXME(mrobinson, bug 25564): This should take into account writing
+ // mode.
+ let child_overflow = PhysicalRect::new(
+ euclid::Point2D::zero(),
+ euclid::Size2D::new(
+ child_overflow.size.width + child_overflow.origin.x,
+ child_overflow.size.height + child_overflow.origin.y,
+ ),
+ );
+ acc.union(&child_overflow)
+ },
+ )));
}
pub(crate) fn find<T>(
diff --git a/components/layout/fragment_tree/positioning_fragment.rs b/components/layout/fragment_tree/positioning_fragment.rs
index e45a6137bff..5547a9d86a1 100644
--- a/components/layout/fragment_tree/positioning_fragment.rs
+++ b/components/layout/fragment_tree/positioning_fragment.rs
@@ -22,7 +22,7 @@ pub(crate) struct PositioningFragment {
pub children: Vec<Fragment>,
/// The scrollable overflow of this anonymous fragment's children.
- pub scrollable_overflow: PhysicalRect<Au>,
+ scrollable_overflow: Option<PhysicalRect<Au>>,
/// The style of the fragment.
pub style: ServoArc<ComputedValues>,
@@ -55,20 +55,12 @@ impl PositioningFragment {
rect: PhysicalRect<Au>,
children: Vec<Fragment>,
) -> ArcRefCell<Self> {
- let content_origin = rect.origin;
- let scrollable_overflow = children.iter().fold(PhysicalRect::zero(), |acc, child| {
- acc.union(
- &child
- .scrollable_overflow_for_parent()
- .translate(content_origin.to_vector()),
- )
- });
ArcRefCell::new(PositioningFragment {
base,
style,
rect,
children,
- scrollable_overflow,
+ scrollable_overflow: None,
cumulative_containing_block_rect: PhysicalRect::zero(),
})
}
@@ -81,6 +73,25 @@ impl PositioningFragment {
rect.translate(self.cumulative_containing_block_rect.origin.to_vector())
}
+ pub(crate) fn calculate_scrollable_overflow(&mut self) {
+ self.scrollable_overflow = Some(self.children.iter().fold(
+ PhysicalRect::zero(),
+ |acc, child| {
+ acc.union(
+ &child
+ .calculate_scrollable_overflow_for_parent()
+ .translate(self.rect.origin.to_vector()),
+ )
+ },
+ ));
+ }
+
+ pub(crate) fn scrollable_overflow_for_parent(&self) -> PhysicalRect<Au> {
+ self.scrollable_overflow.expect(
+ "Should only call `scrollable_overflow_for_parent()` after calculating overflow",
+ )
+ }
+
pub fn print(&self, tree: &mut PrintTree) {
tree.new_level(format!(
"PositioningFragment\
diff --git a/components/layout/layout_impl.rs b/components/layout/layout_impl.rs
index 54edc215389..0fbc8395c35 100644
--- a/components/layout/layout_impl.rs
+++ b/components/layout/layout_impl.rs
@@ -8,6 +8,7 @@ use std::cell::{Cell, RefCell};
use std::collections::HashMap;
use std::fmt::Debug;
use std::process;
+use std::rc::Rc;
use std::sync::{Arc, LazyLock};
use app_units::Au;
@@ -142,7 +143,7 @@ pub struct LayoutThread {
box_tree: RefCell<Option<Arc<BoxTree>>>,
/// The fragment tree.
- fragment_tree: RefCell<Option<Arc<FragmentTree>>>,
+ fragment_tree: RefCell<Option<Rc<FragmentTree>>>,
/// The [`StackingContextTree`] cached from previous layouts.
stacking_context_tree: RefCell<Option<StackingContextTree>>,
@@ -656,7 +657,7 @@ impl LayoutThread {
&mut layout_context,
viewport_changed,
);
-
+ self.calculate_overflow(damage);
self.build_stacking_context_tree(&reflow_request, damage);
self.build_display_list(&reflow_request, &mut layout_context);
@@ -773,8 +774,11 @@ impl LayoutThread {
driver::traverse_dom(&recalc_style_traversal, token, rayon_pool).as_node();
let root_node = root_element.as_node();
- let damage = compute_damage_and_repair_style(layout_context.shared_context(), root_node);
- if !viewport_changed && !damage.contains(RestyleDamage::REBUILD_BOX) {
+ let mut damage =
+ compute_damage_and_repair_style(layout_context.shared_context(), root_node);
+ if viewport_changed {
+ damage = RestyleDamage::REBUILD_BOX;
+ } else if !damage.contains(RestyleDamage::REBUILD_BOX) {
layout_context.style_context.stylist.rule_tree().maybe_gc();
return damage;
}
@@ -802,15 +806,12 @@ impl LayoutThread {
.unwrap()
.layout(recalc_style_traversal.context(), viewport_size)
};
- let fragment_tree = Arc::new(if let Some(pool) = rayon_pool {
+ let fragment_tree = Rc::new(if let Some(pool) = rayon_pool {
pool.install(run_layout)
} else {
run_layout()
});
- if self.debug.dump_flow_tree {
- fragment_tree.print();
- }
*self.fragment_tree.borrow_mut() = Some(fragment_tree);
// The FragmentTree has been updated, so any existing StackingContext tree that layout
@@ -837,6 +838,19 @@ impl LayoutThread {
damage
}
+ fn calculate_overflow(&self, damage: RestyleDamage) {
+ if !damage.contains(RestyleDamage::RECALCULATE_OVERFLOW) {
+ return;
+ }
+
+ if let Some(fragment_tree) = &*self.fragment_tree.borrow() {
+ fragment_tree.calculate_scrollable_overflow();
+ if self.debug.dump_flow_tree {
+ fragment_tree.print();
+ }
+ }
+ }
+
fn build_stacking_context_tree(&self, reflow_request: &ReflowRequest, damage: RestyleDamage) {
if !reflow_request.reflow_goal.needs_display_list() &&
!reflow_request.reflow_goal.needs_display()
@@ -858,13 +872,19 @@ impl LayoutThread {
viewport_size.height.to_f32_px(),
);
+ let scrollable_overflow = fragment_tree.scrollable_overflow();
+ let scrollable_overflow = LayoutSize::from_untyped(Size2D::new(
+ scrollable_overflow.size.width.to_f32_px(),
+ scrollable_overflow.size.height.to_f32_px(),
+ ));
+
// Build the StackingContextTree. This turns the `FragmentTree` into a
// tree of fragments in CSS painting order and also creates all
// applicable spatial and clip nodes.
*self.stacking_context_tree.borrow_mut() = Some(StackingContextTree::new(
fragment_tree,
viewport_size,
- fragment_tree.scrollable_overflow(),
+ scrollable_overflow,
self.id.into(),
fragment_tree.viewport_scroll_sensitivity,
self.first_reflow.get(),
diff --git a/components/layout/positioned.rs b/components/layout/positioned.rs
index 6280864d533..186fc78e3bf 100644
--- a/components/layout/positioned.rs
+++ b/components/layout/positioned.rs
@@ -305,10 +305,7 @@ impl PositioningContext {
}
pub(crate) fn push(&mut self, hoisted_box: HoistedAbsolutelyPositionedBox) {
- debug_assert!(matches!(
- hoisted_box.position(),
- Position::Absolute | Position::Fixed
- ));
+ debug_assert!(hoisted_box.position().is_absolutely_positioned());
self.absolutes.push(hoisted_box);
}
@@ -380,7 +377,7 @@ impl HoistedAbsolutelyPositionedBox {
.context
.style()
.clone_position();
- assert!(position == Position::Fixed || position == Position::Absolute);
+ assert!(position.is_absolutely_positioned());
position
}
diff --git a/components/layout/query.rs b/components/layout/query.rs
index ca9db9ceaf1..7f304ff2da1 100644
--- a/components/layout/query.rs
+++ b/components/layout/query.rs
@@ -3,7 +3,7 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
//! Utilities for querying the layout, as needed by layout.
-use std::sync::Arc;
+use std::rc::Rc;
use app_units::Au;
use euclid::default::{Point2D, Rect};
@@ -80,7 +80,7 @@ pub fn process_client_rect_request(node: ServoLayoutNode<'_>) -> Rect<i32> {
/// <https://drafts.csswg.org/cssom-view/#scrolling-area>
pub fn process_node_scroll_area_request(
requested_node: Option<ServoLayoutNode<'_>>,
- fragment_tree: Option<Arc<FragmentTree>>,
+ fragment_tree: Option<Rc<FragmentTree>>,
) -> Rect<i32> {
let Some(tree) = fragment_tree else {
return Rect::zero();
diff --git a/components/layout/stylesheets/servo.css b/components/layout/stylesheets/servo.css
index c025b19f364..cb206bbcd00 100644
--- a/components/layout/stylesheets/servo.css
+++ b/components/layout/stylesheets/servo.css
@@ -265,4 +265,8 @@ select {
padding: 0 0.25em;
/* Don't show a text cursor when hovering selected option */
cursor: default;
+}
+
+slot {
+ display: contents;
} \ No newline at end of file
diff --git a/components/layout/taffy/layout.rs b/components/layout/taffy/layout.rs
index 61c4a0508e9..c5f66eee6d2 100644
--- a/components/layout/taffy/layout.rs
+++ b/components/layout/taffy/layout.rs
@@ -107,7 +107,7 @@ impl taffy::LayoutPartialTree for TaffyContainerContext<'_> {
Self: 'a;
fn get_core_container_style(&self, _node_id: taffy::NodeId) -> Self::CoreContainerStyle<'_> {
- TaffyStyloStyle(self.style)
+ TaffyStyloStyle::new(self.style, false /* is_replaced */)
}
fn set_unrounded_layout(&mut self, node_id: taffy::NodeId, layout: &taffy::Layout) {
@@ -311,7 +311,7 @@ impl taffy::LayoutGridContainer for TaffyContainerContext<'_> {
&self,
_node_id: taffy::prelude::NodeId,
) -> Self::GridContainerStyle<'_> {
- TaffyStyloStyle(self.style)
+ TaffyStyloStyle::new(self.style, false /* is_replaced */)
}
fn get_grid_child_style(
@@ -320,7 +320,10 @@ impl taffy::LayoutGridContainer for TaffyContainerContext<'_> {
) -> Self::GridItemStyle<'_> {
let id = usize::from(child_node_id);
let child = (*self.source_child_nodes[id]).borrow();
- TaffyStyloStyle(AtomicRef::map(child, |c| &*c.style))
+ // TODO: account for non-replaced elements that are "compressible replaced"
+ let is_replaced = child.is_in_flow_replaced();
+ let stylo_style = AtomicRef::map(child, |c| &*c.style);
+ TaffyStyloStyle::new(stylo_style, is_replaced)
}
fn set_detailed_grid_info(
diff --git a/components/layout/taffy/mod.rs b/components/layout/taffy/mod.rs
index 05fc09c5511..d34f36f249a 100644
--- a/components/layout/taffy/mod.rs
+++ b/components/layout/taffy/mod.rs
@@ -19,7 +19,9 @@ use crate::construct_modern::{ModernContainerBuilder, ModernItemKind};
use crate::context::LayoutContext;
use crate::dom::LayoutBox;
use crate::dom_traversal::{NodeAndStyleInfo, NonReplacedContents};
-use crate::formatting_contexts::IndependentFormattingContext;
+use crate::formatting_contexts::{
+ IndependentFormattingContext, IndependentFormattingContextContents,
+};
use crate::fragment_tree::Fragment;
use crate::positioned::{AbsolutelyPositionedBox, PositioningContext};
@@ -166,6 +168,16 @@ impl TaffyItemBox {
.repair_style(context, node, new_style),
}
}
+
+ fn is_in_flow_replaced(&self) -> bool {
+ match &self.taffy_level_box {
+ TaffyItemBoxInner::InFlowBox(fc) => match fc.contents {
+ IndependentFormattingContextContents::NonReplaced(_) => false,
+ IndependentFormattingContextContents::Replaced(_) => true,
+ },
+ TaffyItemBoxInner::OutOfFlowAbsolutelyPositionedBox(_) => false,
+ }
+ }
}
/// Details from Taffy grid layout that will be stored
diff --git a/components/layout/taffy/stylo_taffy/convert.rs b/components/layout/taffy/stylo_taffy/convert.rs
index 5780be17c82..1b365cde6f6 100644
--- a/components/layout/taffy/stylo_taffy/convert.rs
+++ b/components/layout/taffy/stylo_taffy/convert.rs
@@ -7,6 +7,7 @@ mod stylo {
pub(crate) use style::properties::generated::longhands::box_sizing::computed_value::T as BoxSizing;
pub(crate) use style::properties::longhands::aspect_ratio::computed_value::T as AspectRatio;
pub(crate) use style::properties::longhands::position::computed_value::T as Position;
+ pub(crate) use style::values::computed::length_percentage::Unpacked as UnpackedLengthPercentage;
pub(crate) use style::values::computed::{LengthPercentage, Percentage};
pub(crate) use style::values::generics::NonNegative;
pub(crate) use style::values::generics::length::{
@@ -32,15 +33,16 @@ mod stylo {
pub(crate) use style::values::specified::GenericGridTemplateComponent;
}
+use taffy::MaxTrackSizingFunction;
+use taffy::style_helpers::*;
+
#[inline]
pub fn length_percentage(val: &stylo::LengthPercentage) -> taffy::LengthPercentage {
- if let Some(length) = val.to_length() {
- taffy::LengthPercentage::Length(length.px())
- } else if let Some(val) = val.to_percentage() {
- taffy::LengthPercentage::Percent(val.0)
- } else {
+ match val.unpack() {
+ stylo::UnpackedLengthPercentage::Length(len) => length(len.px()),
+ stylo::UnpackedLengthPercentage::Percentage(percentage) => percent(percentage.0),
// TODO: Support calc
- taffy::LengthPercentage::Percent(0.0)
+ stylo::UnpackedLengthPercentage::Calc(_) => percent(0.0),
}
}
@@ -48,14 +50,14 @@ pub fn length_percentage(val: &stylo::LengthPercentage) -> taffy::LengthPercenta
pub fn dimension(val: &stylo::Size) -> taffy::Dimension {
match val {
stylo::Size::LengthPercentage(val) => length_percentage(&val.0).into(),
- stylo::Size::Auto => taffy::Dimension::Auto,
+ stylo::Size::Auto => taffy::Dimension::AUTO,
// TODO: implement other values in Taffy
- stylo::Size::MaxContent => taffy::Dimension::Auto,
- stylo::Size::MinContent => taffy::Dimension::Auto,
- stylo::Size::FitContent => taffy::Dimension::Auto,
- stylo::Size::FitContentFunction(_) => taffy::Dimension::Auto,
- stylo::Size::Stretch => taffy::Dimension::Auto,
+ stylo::Size::MaxContent => taffy::Dimension::AUTO,
+ stylo::Size::MinContent => taffy::Dimension::AUTO,
+ stylo::Size::FitContent => taffy::Dimension::AUTO,
+ stylo::Size::FitContentFunction(_) => taffy::Dimension::AUTO,
+ stylo::Size::Stretch => taffy::Dimension::AUTO,
// Anchor positioning will be flagged off for time being
stylo::Size::AnchorSizeFunction(_) => unreachable!(),
@@ -67,14 +69,14 @@ pub fn dimension(val: &stylo::Size) -> taffy::Dimension {
pub fn max_size_dimension(val: &stylo::MaxSize) -> taffy::Dimension {
match val {
stylo::MaxSize::LengthPercentage(val) => length_percentage(&val.0).into(),
- stylo::MaxSize::None => taffy::Dimension::Auto,
+ stylo::MaxSize::None => taffy::Dimension::AUTO,
// TODO: implement other values in Taffy
- stylo::MaxSize::MaxContent => taffy::Dimension::Auto,
- stylo::MaxSize::MinContent => taffy::Dimension::Auto,
- stylo::MaxSize::FitContent => taffy::Dimension::Auto,
- stylo::MaxSize::FitContentFunction(_) => taffy::Dimension::Auto,
- stylo::MaxSize::Stretch => taffy::Dimension::Auto,
+ stylo::MaxSize::MaxContent => taffy::Dimension::AUTO,
+ stylo::MaxSize::MinContent => taffy::Dimension::AUTO,
+ stylo::MaxSize::FitContent => taffy::Dimension::AUTO,
+ stylo::MaxSize::FitContentFunction(_) => taffy::Dimension::AUTO,
+ stylo::MaxSize::Stretch => taffy::Dimension::AUTO,
// Anchor positioning will be flagged off for time being
stylo::MaxSize::AnchorSizeFunction(_) => unreachable!(),
@@ -85,7 +87,7 @@ pub fn max_size_dimension(val: &stylo::MaxSize) -> taffy::Dimension {
#[inline]
pub fn margin(val: &stylo::MarginVal) -> taffy::LengthPercentageAuto {
match val {
- stylo::MarginVal::Auto => taffy::LengthPercentageAuto::Auto,
+ stylo::MarginVal::Auto => taffy::LengthPercentageAuto::AUTO,
stylo::MarginVal::LengthPercentage(val) => length_percentage(val).into(),
// Anchor positioning will be flagged off for time being
@@ -97,7 +99,7 @@ pub fn margin(val: &stylo::MarginVal) -> taffy::LengthPercentageAuto {
#[inline]
pub fn inset(val: &stylo::InsetVal) -> taffy::LengthPercentageAuto {
match val {
- stylo::InsetVal::Auto => taffy::LengthPercentageAuto::Auto,
+ stylo::InsetVal::Auto => taffy::LengthPercentageAuto::AUTO,
stylo::InsetVal::LengthPercentage(val) => length_percentage(val).into(),
// Anchor positioning will be flagged off for time being
@@ -214,7 +216,7 @@ pub fn gap(input: &stylo::Gap) -> taffy::LengthPercentage {
match input {
// For Flexbox and CSS Grid the "normal" value is 0px. This may need to be updated
// if we ever implement multi-column layout.
- stylo::Gap::Normal => taffy::LengthPercentage::Length(0.0),
+ stylo::Gap::Normal => taffy::LengthPercentage::ZERO,
stylo::Gap::LengthPercentage(val) => length_percentage(&val.0),
}
}
@@ -306,16 +308,18 @@ pub fn track_size(
max: max_track(max),
},
stylo::TrackSize::FitContent(limit) => taffy::MinMax {
- min: taffy::MinTrackSizingFunction::Auto,
- max: taffy::MaxTrackSizingFunction::FitContent(match limit {
- stylo::TrackBreadth::Breadth(lp) => length_percentage(lp),
+ min: taffy::MinTrackSizingFunction::AUTO,
+ max: match limit {
+ stylo::TrackBreadth::Breadth(lp) => {
+ MaxTrackSizingFunction::fit_content(length_percentage(lp))
+ },
// Are these valid? Taffy doesn't support this in any case
stylo::TrackBreadth::Fr(_) => unreachable!(),
stylo::TrackBreadth::Auto => unreachable!(),
stylo::TrackBreadth::MinContent => unreachable!(),
stylo::TrackBreadth::MaxContent => unreachable!(),
- }),
+ },
},
}
}
@@ -325,13 +329,11 @@ pub fn min_track(
input: &stylo::TrackBreadth<stylo::LengthPercentage>,
) -> taffy::MinTrackSizingFunction {
match input {
- stylo::TrackBreadth::Breadth(lp) => {
- taffy::MinTrackSizingFunction::Fixed(length_percentage(lp))
- },
- stylo::TrackBreadth::Fr(_) => taffy::MinTrackSizingFunction::Auto,
- stylo::TrackBreadth::Auto => taffy::MinTrackSizingFunction::Auto,
- stylo::TrackBreadth::MinContent => taffy::MinTrackSizingFunction::MinContent,
- stylo::TrackBreadth::MaxContent => taffy::MinTrackSizingFunction::MaxContent,
+ stylo::TrackBreadth::Breadth(lp) => length_percentage(lp).into(),
+ stylo::TrackBreadth::Fr(_) => taffy::MinTrackSizingFunction::AUTO,
+ stylo::TrackBreadth::Auto => taffy::MinTrackSizingFunction::AUTO,
+ stylo::TrackBreadth::MinContent => taffy::MinTrackSizingFunction::MIN_CONTENT,
+ stylo::TrackBreadth::MaxContent => taffy::MinTrackSizingFunction::MAX_CONTENT,
}
}
@@ -340,12 +342,10 @@ pub fn max_track(
input: &stylo::TrackBreadth<stylo::LengthPercentage>,
) -> taffy::MaxTrackSizingFunction {
match input {
- stylo::TrackBreadth::Breadth(lp) => {
- taffy::MaxTrackSizingFunction::Fixed(length_percentage(lp))
- },
- stylo::TrackBreadth::Fr(val) => taffy::MaxTrackSizingFunction::Fraction(*val),
- stylo::TrackBreadth::Auto => taffy::MaxTrackSizingFunction::Auto,
- stylo::TrackBreadth::MinContent => taffy::MaxTrackSizingFunction::MinContent,
- stylo::TrackBreadth::MaxContent => taffy::MaxTrackSizingFunction::MaxContent,
+ stylo::TrackBreadth::Breadth(lp) => length_percentage(lp).into(),
+ stylo::TrackBreadth::Fr(val) => fr(*val),
+ stylo::TrackBreadth::Auto => taffy::MaxTrackSizingFunction::AUTO,
+ stylo::TrackBreadth::MinContent => taffy::MaxTrackSizingFunction::MIN_CONTENT,
+ stylo::TrackBreadth::MaxContent => taffy::MaxTrackSizingFunction::MAX_CONTENT,
}
}
diff --git a/components/layout/taffy/stylo_taffy/wrapper.rs b/components/layout/taffy/stylo_taffy/wrapper.rs
index 35b19aa7838..22d02ffeb08 100644
--- a/components/layout/taffy/stylo_taffy/wrapper.rs
+++ b/components/layout/taffy/stylo_taffy/wrapper.rs
@@ -10,33 +10,44 @@ use super::convert;
/// A wrapper struct for anything that Deref's to a [`ComputedValues`], which
/// implements Taffy's layout traits and can used with Taffy's layout algorithms.
-pub struct TaffyStyloStyle<T: Deref<Target = ComputedValues>>(pub T);
+pub struct TaffyStyloStyle<T: Deref<Target = ComputedValues>> {
+ pub style: T,
+ pub is_compressible_replaced: bool,
+}
-impl<T: Deref<Target = ComputedValues>> From<T> for TaffyStyloStyle<T> {
- fn from(value: T) -> Self {
- Self(value)
+impl<T: Deref<Target = ComputedValues>> TaffyStyloStyle<T> {
+ pub fn new(style: T, is_compressible_replaced: bool) -> Self {
+ Self {
+ style,
+ is_compressible_replaced,
+ }
}
}
impl<T: Deref<Target = ComputedValues>> taffy::CoreStyle for TaffyStyloStyle<T> {
#[inline]
fn box_generation_mode(&self) -> taffy::BoxGenerationMode {
- convert::box_generation_mode(self.0.get_box().display)
+ convert::box_generation_mode(self.style.get_box().display)
}
#[inline]
fn is_block(&self) -> bool {
- convert::is_block(self.0.get_box().display)
+ convert::is_block(self.style.get_box().display)
+ }
+
+ #[inline]
+ fn is_compressible_replaced(&self) -> bool {
+ self.is_compressible_replaced
}
#[inline]
fn box_sizing(&self) -> taffy::BoxSizing {
- convert::box_sizing(self.0.get_position().box_sizing)
+ convert::box_sizing(self.style.get_position().box_sizing)
}
#[inline]
fn overflow(&self) -> taffy::Point<taffy::Overflow> {
- let box_styles = self.0.get_box();
+ let box_styles = self.style.get_box();
taffy::Point {
x: convert::overflow(box_styles.overflow_x),
y: convert::overflow(box_styles.overflow_y),
@@ -50,12 +61,12 @@ impl<T: Deref<Target = ComputedValues>> taffy::CoreStyle for TaffyStyloStyle<T>
#[inline]
fn position(&self) -> taffy::Position {
- convert::position(self.0.get_box().position)
+ convert::position(self.style.get_box().position)
}
#[inline]
fn inset(&self) -> taffy::Rect<taffy::LengthPercentageAuto> {
- let position_styles = self.0.get_position();
+ let position_styles = self.style.get_position();
taffy::Rect {
left: convert::inset(&position_styles.left),
right: convert::inset(&position_styles.right),
@@ -66,7 +77,7 @@ impl<T: Deref<Target = ComputedValues>> taffy::CoreStyle for TaffyStyloStyle<T>
#[inline]
fn size(&self) -> taffy::Size<taffy::Dimension> {
- let position_styles = self.0.get_position();
+ let position_styles = self.style.get_position();
taffy::Size {
width: convert::dimension(&position_styles.width),
height: convert::dimension(&position_styles.height),
@@ -75,7 +86,7 @@ impl<T: Deref<Target = ComputedValues>> taffy::CoreStyle for TaffyStyloStyle<T>
#[inline]
fn min_size(&self) -> taffy::Size<taffy::Dimension> {
- let position_styles = self.0.get_position();
+ let position_styles = self.style.get_position();
taffy::Size {
width: convert::dimension(&position_styles.min_width),
height: convert::dimension(&position_styles.min_height),
@@ -84,7 +95,7 @@ impl<T: Deref<Target = ComputedValues>> taffy::CoreStyle for TaffyStyloStyle<T>
#[inline]
fn max_size(&self) -> taffy::Size<taffy::Dimension> {
- let position_styles = self.0.get_position();
+ let position_styles = self.style.get_position();
taffy::Size {
width: convert::max_size_dimension(&position_styles.max_width),
height: convert::max_size_dimension(&position_styles.max_height),
@@ -93,12 +104,12 @@ impl<T: Deref<Target = ComputedValues>> taffy::CoreStyle for TaffyStyloStyle<T>
#[inline]
fn aspect_ratio(&self) -> Option<f32> {
- convert::aspect_ratio(self.0.get_position().aspect_ratio)
+ convert::aspect_ratio(self.style.get_position().aspect_ratio)
}
#[inline]
fn margin(&self) -> taffy::Rect<taffy::LengthPercentageAuto> {
- let margin_styles = self.0.get_margin();
+ let margin_styles = self.style.get_margin();
taffy::Rect {
left: convert::margin(&margin_styles.margin_left),
right: convert::margin(&margin_styles.margin_right),
@@ -109,7 +120,7 @@ impl<T: Deref<Target = ComputedValues>> taffy::CoreStyle for TaffyStyloStyle<T>
#[inline]
fn padding(&self) -> taffy::Rect<taffy::LengthPercentage> {
- let padding_styles = self.0.get_padding();
+ let padding_styles = self.style.get_padding();
taffy::Rect {
left: convert::length_percentage(&padding_styles.padding_left.0),
right: convert::length_percentage(&padding_styles.padding_right.0),
@@ -120,12 +131,12 @@ impl<T: Deref<Target = ComputedValues>> taffy::CoreStyle for TaffyStyloStyle<T>
#[inline]
fn border(&self) -> taffy::Rect<taffy::LengthPercentage> {
- let border_styles = self.0.get_border();
+ let border_styles = self.style.get_border();
taffy::Rect {
- left: taffy::LengthPercentage::Length(border_styles.border_left_width.to_f32_px()),
- right: taffy::LengthPercentage::Length(border_styles.border_right_width.to_f32_px()),
- top: taffy::LengthPercentage::Length(border_styles.border_top_width.to_f32_px()),
- bottom: taffy::LengthPercentage::Length(border_styles.border_bottom_width.to_f32_px()),
+ left: taffy::LengthPercentage::length(border_styles.border_left_width.to_f32_px()),
+ right: taffy::LengthPercentage::length(border_styles.border_right_width.to_f32_px()),
+ top: taffy::LengthPercentage::length(border_styles.border_top_width.to_f32_px()),
+ bottom: taffy::LengthPercentage::length(border_styles.border_bottom_width.to_f32_px()),
}
}
}
@@ -142,32 +153,32 @@ impl<T: Deref<Target = ComputedValues>> taffy::GridContainerStyle for TaffyStylo
#[inline]
fn grid_template_rows(&self) -> Self::TemplateTrackList<'_> {
- convert::grid_template_tracks(&self.0.get_position().grid_template_rows)
+ convert::grid_template_tracks(&self.style.get_position().grid_template_rows)
}
#[inline]
fn grid_template_columns(&self) -> Self::TemplateTrackList<'_> {
- convert::grid_template_tracks(&self.0.get_position().grid_template_columns)
+ convert::grid_template_tracks(&self.style.get_position().grid_template_columns)
}
#[inline]
fn grid_auto_rows(&self) -> Self::AutoTrackList<'_> {
- convert::grid_auto_tracks(&self.0.get_position().grid_auto_rows)
+ convert::grid_auto_tracks(&self.style.get_position().grid_auto_rows)
}
#[inline]
fn grid_auto_columns(&self) -> Self::AutoTrackList<'_> {
- convert::grid_auto_tracks(&self.0.get_position().grid_auto_columns)
+ convert::grid_auto_tracks(&self.style.get_position().grid_auto_columns)
}
#[inline]
fn grid_auto_flow(&self) -> taffy::GridAutoFlow {
- convert::grid_auto_flow(self.0.get_position().grid_auto_flow)
+ convert::grid_auto_flow(self.style.get_position().grid_auto_flow)
}
#[inline]
fn gap(&self) -> taffy::Size<taffy::LengthPercentage> {
- let position_styles = self.0.get_position();
+ let position_styles = self.style.get_position();
taffy::Size {
width: convert::gap(&position_styles.column_gap),
height: convert::gap(&position_styles.row_gap),
@@ -176,29 +187,29 @@ impl<T: Deref<Target = ComputedValues>> taffy::GridContainerStyle for TaffyStylo
#[inline]
fn align_content(&self) -> Option<taffy::AlignContent> {
- convert::content_alignment(self.0.get_position().align_content.0)
+ convert::content_alignment(self.style.get_position().align_content.0)
}
#[inline]
fn justify_content(&self) -> Option<taffy::JustifyContent> {
- convert::content_alignment(self.0.get_position().justify_content.0)
+ convert::content_alignment(self.style.get_position().justify_content.0)
}
#[inline]
fn align_items(&self) -> Option<taffy::AlignItems> {
- convert::item_alignment(self.0.get_position().align_items.0)
+ convert::item_alignment(self.style.get_position().align_items.0)
}
#[inline]
fn justify_items(&self) -> Option<taffy::AlignItems> {
- convert::item_alignment(self.0.get_position().justify_items.computed.0)
+ convert::item_alignment(self.style.get_position().justify_items.computed.0)
}
}
impl<T: Deref<Target = ComputedValues>> taffy::GridItemStyle for TaffyStyloStyle<T> {
#[inline]
fn grid_row(&self) -> taffy::Line<taffy::GridPlacement> {
- let position_styles = self.0.get_position();
+ let position_styles = self.style.get_position();
taffy::Line {
start: convert::grid_line(&position_styles.grid_row_start),
end: convert::grid_line(&position_styles.grid_row_end),
@@ -207,7 +218,7 @@ impl<T: Deref<Target = ComputedValues>> taffy::GridItemStyle for TaffyStyloStyle
#[inline]
fn grid_column(&self) -> taffy::Line<taffy::GridPlacement> {
- let position_styles = self.0.get_position();
+ let position_styles = self.style.get_position();
taffy::Line {
start: convert::grid_line(&position_styles.grid_column_start),
end: convert::grid_line(&position_styles.grid_column_end),
@@ -216,11 +227,11 @@ impl<T: Deref<Target = ComputedValues>> taffy::GridItemStyle for TaffyStyloStyle
#[inline]
fn align_self(&self) -> Option<taffy::AlignSelf> {
- convert::item_alignment(self.0.get_position().align_self.0.0)
+ convert::item_alignment(self.style.get_position().align_self.0.0)
}
#[inline]
fn justify_self(&self) -> Option<taffy::AlignSelf> {
- convert::item_alignment(self.0.get_position().justify_self.0.0)
+ convert::item_alignment(self.style.get_position().justify_self.0.0)
}
}