aboutsummaryrefslogtreecommitdiffstats
path: root/components/layout
diff options
context:
space:
mode:
Diffstat (limited to 'components/layout')
-rw-r--r--components/layout/display_list/mod.rs22
-rw-r--r--components/layout/dom.rs71
-rw-r--r--components/layout/dom_traversal.rs9
-rw-r--r--components/layout/flexbox/mod.rs22
-rw-r--r--components/layout/flow/inline/construct.rs6
-rw-r--r--components/layout/flow/inline/inline_box.rs14
-rw-r--r--components/layout/flow/inline/mod.rs55
-rw-r--r--components/layout/flow/mod.rs57
-rw-r--r--components/layout/flow/root.rs6
-rw-r--r--components/layout/formatting_contexts.rs28
-rw-r--r--components/layout/fragment_tree/fragment.rs19
-rw-r--r--components/layout/fragment_tree/positioning_fragment.rs16
-rw-r--r--components/layout/layout_box_base.rs7
-rw-r--r--components/layout/layout_impl.rs10
-rw-r--r--components/layout/positioned.rs287
-rw-r--r--components/layout/table/layout.rs1
-rw-r--r--components/layout/table/mod.rs50
-rw-r--r--components/layout/taffy/mod.rs22
-rw-r--r--components/layout/traversal.rs82
19 files changed, 568 insertions, 216 deletions
diff --git a/components/layout/display_list/mod.rs b/components/layout/display_list/mod.rs
index 9990528911c..f017642908d 100644
--- a/components/layout/display_list/mod.rs
+++ b/components/layout/display_list/mod.rs
@@ -471,18 +471,16 @@ impl Fragment {
Fragment::AbsoluteOrFixedPositioned(_) => {},
Fragment::Positioning(positioning_fragment) => {
let positioning_fragment = positioning_fragment.borrow();
- if let Some(style) = positioning_fragment.style.as_ref() {
- let rect = positioning_fragment
- .rect
- .translate(containing_block.origin.to_vector());
- self.maybe_push_hit_test_for_style_and_tag(
- builder,
- style,
- positioning_fragment.base.tag,
- rect,
- Cursor::Default,
- );
- }
+ let rect = positioning_fragment
+ .rect
+ .translate(containing_block.origin.to_vector());
+ self.maybe_push_hit_test_for_style_and_tag(
+ builder,
+ &positioning_fragment.style,
+ positioning_fragment.base.tag,
+ rect,
+ Cursor::Default,
+ );
},
Fragment::Image(image) => {
let image = image.borrow();
diff --git a/components/layout/dom.rs b/components/layout/dom.rs
index faedf608749..e3a22eb5197 100644
--- a/components/layout/dom.rs
+++ b/components/layout/dom.rs
@@ -19,11 +19,11 @@ use script_layout_interface::{
GenericLayoutDataTrait, LayoutElementType, LayoutNodeType as ScriptLayoutNodeType,
};
use servo_arc::Arc as ServoArc;
+use style::context::SharedStyleContext;
use style::properties::ComputedValues;
use style::selector_parser::PseudoElement;
use crate::cell::ArcRefCell;
-use crate::context::LayoutContext;
use crate::flexbox::FlexLevelBox;
use crate::flow::BlockLevelBox;
use crate::flow::inline::{InlineItem, SharedInlineStyles};
@@ -102,6 +102,41 @@ impl LayoutBox {
LayoutBox::TableLevelBox(table_box) => table_box.fragments(),
}
}
+
+ fn repair_style(
+ &self,
+ context: &SharedStyleContext,
+ node: &ServoLayoutNode,
+ new_style: &ServoArc<ComputedValues>,
+ ) {
+ match self {
+ LayoutBox::DisplayContents(inline_shared_styles) => {
+ *inline_shared_styles.style.borrow_mut() = new_style.clone();
+ *inline_shared_styles.selected.borrow_mut() = node.to_threadsafe().selected_style();
+ },
+ LayoutBox::BlockLevel(block_level_box) => {
+ block_level_box
+ .borrow_mut()
+ .repair_style(context, node, new_style);
+ },
+ LayoutBox::InlineLevel(inline_items) => {
+ for inline_item in inline_items {
+ inline_item
+ .borrow_mut()
+ .repair_style(context, node, new_style);
+ }
+ },
+ LayoutBox::FlexLevel(flex_level_box) => {
+ flex_level_box.borrow_mut().repair_style(context, new_style)
+ },
+ LayoutBox::TableLevelBox(table_level_box) => {
+ table_level_box.repair_style(context, new_style)
+ },
+ LayoutBox::TaffyItemBox(taffy_item_box) => {
+ taffy_item_box.borrow_mut().repair_style(context, new_style)
+ },
+ }
+ }
}
/// A wrapper for [`InnerDOMLayoutData`]. This is necessary to give the entire data
@@ -167,7 +202,7 @@ pub(crate) trait NodeExt<'dom> {
fn as_iframe(&self) -> Option<(PipelineId, BrowsingContextId)>;
fn as_video(&self) -> Option<(Option<webrender_api::ImageKey>, Option<PhysicalSize<f64>>)>;
fn as_typeless_object_with_data_attribute(&self) -> Option<String>;
- fn style(&self, context: &LayoutContext) -> ServoArc<ComputedValues>;
+ fn style(&self, context: &SharedStyleContext) -> ServoArc<ComputedValues>;
fn layout_data_mut(&self) -> AtomicRefMut<'dom, InnerDOMLayoutData>;
fn layout_data(&self) -> Option<AtomicRef<'dom, InnerDOMLayoutData>>;
@@ -180,6 +215,8 @@ pub(crate) trait NodeExt<'dom> {
fn fragments_for_pseudo(&self, pseudo_element: Option<PseudoElement>) -> Vec<Fragment>;
fn invalidate_cached_fragment(&self);
+
+ fn repair_style(&self, context: &SharedStyleContext);
}
impl<'dom> NodeExt<'dom> for ServoLayoutNode<'dom> {
@@ -253,8 +290,8 @@ impl<'dom> NodeExt<'dom> for ServoLayoutNode<'dom> {
.map(|string| string.to_owned())
}
- fn style(&self, context: &LayoutContext) -> ServoArc<ComputedValues> {
- self.to_threadsafe().style(context.shared_context())
+ fn style(&self, context: &SharedStyleContext) -> ServoArc<ComputedValues> {
+ self.to_threadsafe().style(context)
}
fn layout_data_mut(&self) -> AtomicRefMut<'dom, InnerDOMLayoutData> {
@@ -339,4 +376,30 @@ impl<'dom> NodeExt<'dom> for ServoLayoutNode<'dom> {
})
.unwrap_or_default()
}
+
+ fn repair_style(&self, context: &SharedStyleContext) {
+ let data = self.layout_data_mut();
+ if let Some(layout_object) = &*data.self_box.borrow() {
+ let style = self.to_threadsafe().style(context);
+ layout_object.repair_style(context, self, &style);
+ }
+
+ if let Some(layout_object) = &*data.pseudo_before_box.borrow() {
+ if let Some(node) = self.to_threadsafe().with_pseudo(PseudoElement::Before) {
+ layout_object.repair_style(context, self, &node.style(context));
+ }
+ }
+
+ if let Some(layout_object) = &*data.pseudo_after_box.borrow() {
+ if let Some(node) = self.to_threadsafe().with_pseudo(PseudoElement::After) {
+ layout_object.repair_style(context, self, &node.style(context));
+ }
+ }
+
+ if let Some(layout_object) = &*data.pseudo_marker_box.borrow() {
+ if let Some(node) = self.to_threadsafe().with_pseudo(PseudoElement::Marker) {
+ layout_object.repair_style(context, self, &node.style(context));
+ }
+ }
+ }
}
diff --git a/components/layout/dom_traversal.rs b/components/layout/dom_traversal.rs
index d9019bbf8e0..0201d72dbe2 100644
--- a/components/layout/dom_traversal.rs
+++ b/components/layout/dom_traversal.rs
@@ -212,7 +212,10 @@ fn traverse_children_of<'dom>(
);
if is_text_input_element || is_textarea_element {
- let info = NodeAndStyleInfo::new(parent_element, parent_element.style(context));
+ let info = NodeAndStyleInfo::new(
+ parent_element,
+ parent_element.style(context.shared_context()),
+ );
let node_text_content = parent_element.to_threadsafe().node_text_content();
if node_text_content.is_empty() {
// The addition of zero-width space here forces the text input to have an inline formatting
@@ -231,7 +234,7 @@ fn traverse_children_of<'dom>(
if !is_text_input_element && !is_textarea_element {
for child in iter_child_nodes(parent_element) {
if child.is_text_node() {
- let info = NodeAndStyleInfo::new(child, child.style(context));
+ let info = NodeAndStyleInfo::new(child, child.style(context.shared_context()));
handler.handle_text(&info, child.to_threadsafe().node_text_content());
} else if child.is_element() {
traverse_element(child, context, handler);
@@ -252,7 +255,7 @@ fn traverse_element<'dom>(
element.unset_pseudo_element_box(PseudoElement::Marker);
let replaced = ReplacedContents::for_element(element, context);
- let style = element.style(context);
+ let style = element.style(context.shared_context());
match Display::from(style.get_box().display) {
Display::None => element.unset_all_boxes(),
Display::Contents => {
diff --git a/components/layout/flexbox/mod.rs b/components/layout/flexbox/mod.rs
index 737b15de25b..91a12b31812 100644
--- a/components/layout/flexbox/mod.rs
+++ b/components/layout/flexbox/mod.rs
@@ -5,6 +5,7 @@
use geom::{FlexAxis, MainStartCrossStart};
use malloc_size_of_derive::MallocSizeOf;
use servo_arc::Arc as ServoArc;
+use style::context::SharedStyleContext;
use style::logical_geometry::WritingMode;
use style::properties::ComputedValues;
use style::properties::longhands::align_items::computed_value::T as AlignItems;
@@ -136,6 +137,11 @@ impl FlexContainer {
config: FlexContainerConfig::new(&info.style),
}
}
+
+ pub(crate) fn repair_style(&mut self, new_style: &ServoArc<ComputedValues>) {
+ self.config = FlexContainerConfig::new(new_style);
+ self.style = new_style.clone();
+ }
}
#[derive(Debug, MallocSizeOf)]
@@ -145,6 +151,22 @@ pub(crate) enum FlexLevelBox {
}
impl FlexLevelBox {
+ pub(crate) fn repair_style(
+ &mut self,
+ context: &SharedStyleContext,
+ new_style: &ServoArc<ComputedValues>,
+ ) {
+ match self {
+ FlexLevelBox::FlexItem(flex_item_box) => flex_item_box
+ .independent_formatting_context
+ .repair_style(context, new_style),
+ FlexLevelBox::OutOfFlowAbsolutelyPositionedBox(positioned_box) => positioned_box
+ .borrow_mut()
+ .context
+ .repair_style(context, new_style),
+ }
+ }
+
pub(crate) fn invalidate_cached_fragment(&self) {
match self {
FlexLevelBox::FlexItem(flex_item_box) => flex_item_box
diff --git a/components/layout/flow/inline/construct.rs b/components/layout/flow/inline/construct.rs
index 42d80059ab2..a99de1679a4 100644
--- a/components/layout/flow/inline/construct.rs
+++ b/components/layout/flow/inline/construct.rs
@@ -7,7 +7,6 @@ use std::char::{ToLowercase, ToUppercase};
use icu_segmenter::WordSegmenter;
use itertools::izip;
-use servo_arc::Arc;
use style::computed_values::white_space_collapse::T as WhiteSpaceCollapse;
use style::values::specified::text::TextTransformCase;
use unicode_bidi::Level;
@@ -158,7 +157,7 @@ impl InlineFormattingContextBuilder {
independent_formatting_context: IndependentFormattingContext,
) -> ArcRefCell<InlineItem> {
let inline_level_box = ArcRefCell::new(InlineItem::Atomic(
- Arc::new(independent_formatting_context),
+ ArcRefCell::new(independent_formatting_context),
self.current_text_offset,
Level::ltr(), /* This will be assigned later if necessary. */
));
@@ -189,7 +188,8 @@ impl InlineFormattingContextBuilder {
}
pub(crate) fn push_float_box(&mut self, float_box: FloatBox) -> ArcRefCell<InlineItem> {
- let inline_level_box = ArcRefCell::new(InlineItem::OutOfFlowFloatBox(Arc::new(float_box)));
+ let inline_level_box =
+ ArcRefCell::new(InlineItem::OutOfFlowFloatBox(ArcRefCell::new(float_box)));
self.inline_items.push(inline_level_box.clone());
self.contains_floats = true;
inline_level_box
diff --git a/components/layout/flow/inline/inline_box.rs b/components/layout/flow/inline/inline_box.rs
index 0ff58b6a6f3..b547f3b5935 100644
--- a/components/layout/flow/inline/inline_box.rs
+++ b/components/layout/flow/inline/inline_box.rs
@@ -7,6 +7,10 @@ use std::vec::IntoIter;
use app_units::Au;
use fonts::FontMetrics;
use malloc_size_of_derive::MallocSizeOf;
+use script::layout_dom::ServoLayoutNode;
+use script_layout_interface::wrapper_traits::{LayoutNode, ThreadSafeLayoutNode};
+use servo_arc::Arc as ServoArc;
+use style::properties::ComputedValues;
use super::{
InlineContainerState, InlineContainerStateFlags, SharedInlineStyles,
@@ -66,6 +70,16 @@ impl InlineBox {
pub(crate) fn layout_style(&self) -> LayoutStyle {
LayoutStyle::Default(&self.base.style)
}
+
+ pub(crate) fn repair_style(
+ &mut self,
+ node: &ServoLayoutNode,
+ new_style: &ServoArc<ComputedValues>,
+ ) {
+ self.base.repair_style(new_style);
+ *self.shared_inline_styles.style.borrow_mut() = new_style.clone();
+ *self.shared_inline_styles.selected.borrow_mut() = node.to_threadsafe().selected_style();
+ }
}
#[derive(Debug, Default, MallocSizeOf)]
diff --git a/components/layout/flow/inline/mod.rs b/components/layout/flow/inline/mod.rs
index d623eb4a3d8..7e69aa1aaae 100644
--- a/components/layout/flow/inline/mod.rs
+++ b/components/layout/flow/inline/mod.rs
@@ -90,12 +90,13 @@ use line::{
use line_breaker::LineBreaker;
use malloc_size_of_derive::MallocSizeOf;
use range::Range;
+use script::layout_dom::ServoLayoutNode;
use servo_arc::Arc;
use style::Zero;
use style::computed_values::text_wrap_mode::T as TextWrapMode;
use style::computed_values::vertical_align::T as VerticalAlign;
use style::computed_values::white_space_collapse::T as WhiteSpaceCollapse;
-use style::context::QuirksMode;
+use style::context::{QuirksMode, SharedStyleContext};
use style::properties::ComputedValues;
use style::properties::style_structs::InheritedText;
use style::values::generics::box_::VerticalAlignKeyword;
@@ -210,15 +211,41 @@ pub(crate) enum InlineItem {
ArcRefCell<AbsolutelyPositionedBox>,
usize, /* offset_in_text */
),
- OutOfFlowFloatBox(#[conditional_malloc_size_of] Arc<FloatBox>),
+ OutOfFlowFloatBox(ArcRefCell<FloatBox>),
Atomic(
- #[conditional_malloc_size_of] Arc<IndependentFormattingContext>,
+ ArcRefCell<IndependentFormattingContext>,
usize, /* offset_in_text */
Level, /* bidi_level */
),
}
impl InlineItem {
+ pub(crate) fn repair_style(
+ &self,
+ context: &SharedStyleContext,
+ node: &ServoLayoutNode,
+ new_style: &Arc<ComputedValues>,
+ ) {
+ match self {
+ InlineItem::StartInlineBox(inline_box) => {
+ inline_box.borrow_mut().repair_style(node, new_style);
+ },
+ InlineItem::EndInlineBox => {},
+ // TextRun holds a handle the `InlineSharedStyles` which is updated when repairing inline box
+ // and `display: contents` styles.
+ InlineItem::TextRun(..) => {},
+ InlineItem::OutOfFlowAbsolutelyPositionedBox(positioned_box, ..) => positioned_box
+ .borrow_mut()
+ .context
+ .repair_style(context, new_style),
+ InlineItem::OutOfFlowFloatBox(float_box) => float_box
+ .borrow_mut()
+ .contents
+ .repair_style(context, new_style),
+ InlineItem::Atomic(atomic, ..) => atomic.borrow_mut().repair_style(context, new_style),
+ }
+ }
+
pub(crate) fn invalidate_cached_fragment(&self) {
match self {
InlineItem::StartInlineBox(inline_box) => {
@@ -232,11 +259,14 @@ impl InlineItem {
.base
.invalidate_cached_fragment();
},
- InlineItem::OutOfFlowFloatBox(float_box) => {
- float_box.contents.base.invalidate_cached_fragment()
- },
+ InlineItem::OutOfFlowFloatBox(float_box) => float_box
+ .borrow()
+ .contents
+ .base
+ .invalidate_cached_fragment(),
InlineItem::Atomic(independent_formatting_context, ..) => {
independent_formatting_context
+ .borrow()
.base
.invalidate_cached_fragment();
},
@@ -252,9 +282,11 @@ impl InlineItem {
InlineItem::OutOfFlowAbsolutelyPositionedBox(positioned_box, ..) => {
positioned_box.borrow().context.base.fragments()
},
- InlineItem::OutOfFlowFloatBox(float_box) => float_box.contents.base.fragments(),
+ InlineItem::OutOfFlowFloatBox(float_box) => {
+ float_box.borrow().contents.base.fragments()
+ },
InlineItem::Atomic(independent_formatting_context, ..) => {
- independent_formatting_context.base.fragments()
+ independent_formatting_context.borrow().base.fragments()
},
}
}
@@ -978,6 +1010,7 @@ impl InlineFormattingContextLayout<'_> {
.as_physical(Some(self.containing_block));
self.fragments
.push(Fragment::Positioning(PositioningFragment::new_anonymous(
+ self.root_nesting_level.style.clone(),
physical_line_rect,
fragments,
)));
@@ -1770,7 +1803,7 @@ impl InlineFormattingContext {
InlineItem::EndInlineBox => layout.finish_inline_box(),
InlineItem::TextRun(run) => run.borrow().layout_into_line_items(&mut layout),
InlineItem::Atomic(atomic_formatting_context, offset_in_text, bidi_level) => {
- atomic_formatting_context.layout_into_line_items(
+ atomic_formatting_context.borrow().layout_into_line_items(
&mut layout,
*offset_in_text,
*bidi_level,
@@ -1785,7 +1818,7 @@ impl InlineFormattingContext {
));
},
InlineItem::OutOfFlowFloatBox(float_box) => {
- float_box.layout_into_line_items(&mut layout);
+ float_box.borrow().layout_into_line_items(&mut layout);
},
}
}
@@ -2448,7 +2481,7 @@ impl<'layout_data> ContentSizesComputation<'layout_data> {
let InlineContentSizesResult {
sizes: outer,
depends_on_block_constraints,
- } = atomic.outer_inline_content_sizes(
+ } = atomic.borrow().outer_inline_content_sizes(
self.layout_context,
&self.constraint_space.into(),
&LogicalVec2::zero(),
diff --git a/components/layout/flow/mod.rs b/components/layout/flow/mod.rs
index 17a952d24cb..6adb63153d6 100644
--- a/components/layout/flow/mod.rs
+++ b/components/layout/flow/mod.rs
@@ -9,9 +9,11 @@ use app_units::{Au, MAX_AU};
use inline::InlineFormattingContext;
use malloc_size_of_derive::MallocSizeOf;
use rayon::iter::{IndexedParallelIterator, IntoParallelRefIterator, ParallelIterator};
+use script::layout_dom::ServoLayoutNode;
use servo_arc::Arc;
use style::Zero;
use style::computed_values::clear::T as StyleClear;
+use style::context::SharedStyleContext;
use style::logical_geometry::Direction;
use style::properties::ComputedValues;
use style::servo::selector_parser::PseudoElement;
@@ -21,6 +23,7 @@ use style::values::specified::{Display, TextAlignKeyword};
use crate::cell::ArcRefCell;
use crate::context::LayoutContext;
+use crate::dom::NodeExt;
use crate::flow::float::{
Clear, ContainingBlockPositionInfo, FloatBox, FloatSide, PlacementAmongFloats,
SequentialLayoutState,
@@ -91,6 +94,36 @@ pub(crate) enum BlockLevelBox {
}
impl BlockLevelBox {
+ pub(crate) fn repair_style(
+ &mut self,
+ context: &SharedStyleContext,
+ node: &ServoLayoutNode,
+ new_style: &Arc<ComputedValues>,
+ ) {
+ self.with_base_mut(|base| {
+ base.repair_style(new_style);
+ });
+
+ match self {
+ BlockLevelBox::Independent(independent_formatting_context) => {
+ independent_formatting_context.repair_style(context, new_style)
+ },
+ BlockLevelBox::OutOfFlowAbsolutelyPositionedBox(positioned_box) => positioned_box
+ .borrow_mut()
+ .context
+ .repair_style(context, new_style),
+ BlockLevelBox::OutOfFlowFloatBox(float_box) => {
+ float_box.contents.repair_style(context, new_style)
+ },
+ BlockLevelBox::OutsideMarker(outside_marker) => {
+ outside_marker.repair_style(context, node, new_style)
+ },
+ BlockLevelBox::SameFormattingContextBlock { base, .. } => {
+ base.repair_style(new_style);
+ },
+ }
+ }
+
pub(crate) fn invalidate_cached_fragment(&self) {
self.with_base(LayoutBoxBase::invalidate_cached_fragment);
}
@@ -113,6 +146,20 @@ impl BlockLevelBox {
}
}
+ pub(crate) fn with_base_mut<T>(&mut self, callback: impl Fn(&mut LayoutBoxBase) -> T) -> T {
+ match self {
+ BlockLevelBox::Independent(independent_formatting_context) => {
+ callback(&mut independent_formatting_context.base)
+ },
+ BlockLevelBox::OutOfFlowAbsolutelyPositionedBox(positioned_box) => {
+ callback(&mut positioned_box.borrow_mut().context.base)
+ },
+ BlockLevelBox::OutOfFlowFloatBox(float_box) => callback(&mut float_box.contents.base),
+ BlockLevelBox::OutsideMarker(outside_marker) => callback(&mut outside_marker.base),
+ BlockLevelBox::SameFormattingContextBlock { base, .. } => callback(base),
+ }
+ }
+
fn contains_floats(&self) -> bool {
match self {
BlockLevelBox::SameFormattingContextBlock {
@@ -360,6 +407,16 @@ impl OutsideMarker {
None,
)))
}
+
+ fn repair_style(
+ &mut self,
+ context: &SharedStyleContext,
+ node: &ServoLayoutNode,
+ new_style: &Arc<ComputedValues>,
+ ) {
+ self.list_item_style = node.style(context);
+ self.base.repair_style(new_style);
+ }
}
impl BlockFormattingContext {
diff --git a/components/layout/flow/root.rs b/components/layout/flow/root.rs
index b367b20c881..a37db54065d 100644
--- a/components/layout/flow/root.rs
+++ b/components/layout/flow/root.rs
@@ -59,7 +59,7 @@ impl BoxTree {
// > none, user agents must instead apply the overflow-* values of the first such child
// > element to the viewport. The element from which the value is propagated must then have a
// > used overflow value of visible.
- let root_style = root_element.style(context);
+ let root_style = root_element.style(context.shared_context());
let mut viewport_overflow_x = root_style.clone_overflow_x();
let mut viewport_overflow_y = root_style.clone_overflow_y();
@@ -76,7 +76,7 @@ impl BoxTree {
continue;
}
- let style = child.style(context);
+ let style = child.style(context.shared_context());
if !style.get_box().display.is_none() {
viewport_overflow_x = style.clone_overflow_x();
viewport_overflow_y = style.clone_overflow_y();
@@ -293,7 +293,7 @@ fn construct_for_root_element(
context: &LayoutContext,
root_element: ServoLayoutNode<'_>,
) -> Vec<ArcRefCell<BlockLevelBox>> {
- let info = NodeAndStyleInfo::new(root_element, root_element.style(context));
+ let info = NodeAndStyleInfo::new(root_element, root_element.style(context.shared_context()));
let box_style = info.style.get_box();
let display_inside = match Display::from(box_style.display) {
diff --git a/components/layout/formatting_contexts.rs b/components/layout/formatting_contexts.rs
index 04a8c60f692..d704011d0e7 100644
--- a/components/layout/formatting_contexts.rs
+++ b/components/layout/formatting_contexts.rs
@@ -6,6 +6,7 @@ use app_units::Au;
use malloc_size_of_derive::MallocSizeOf;
use script::layout_dom::ServoLayoutElement;
use servo_arc::Arc;
+use style::context::SharedStyleContext;
use style::properties::ComputedValues;
use style::selector_parser::PseudoElement;
@@ -217,6 +218,20 @@ impl IndependentFormattingContext {
},
}
}
+
+ pub(crate) fn repair_style(
+ &mut self,
+ context: &SharedStyleContext,
+ new_style: &Arc<ComputedValues>,
+ ) {
+ self.base.repair_style(new_style);
+ match &mut self.contents {
+ IndependentFormattingContextContents::NonReplaced(content) => {
+ content.repair_style(context, new_style);
+ },
+ IndependentFormattingContextContents::Replaced(..) => {},
+ }
+ }
}
impl IndependentNonReplacedContents {
@@ -334,6 +349,19 @@ impl IndependentNonReplacedContents {
pub(crate) fn is_table(&self) -> bool {
matches!(self, Self::Table(_))
}
+
+ fn repair_style(&mut self, context: &SharedStyleContext, new_style: &Arc<ComputedValues>) {
+ match self {
+ IndependentNonReplacedContents::Flow(..) => {},
+ IndependentNonReplacedContents::Flex(flex_container) => {
+ flex_container.repair_style(new_style)
+ },
+ IndependentNonReplacedContents::Grid(taffy_container) => {
+ taffy_container.repair_style(new_style)
+ },
+ IndependentNonReplacedContents::Table(table) => table.repair_style(context, new_style),
+ }
+ }
}
impl ComputeInlineContentSizes for IndependentNonReplacedContents {
diff --git a/components/layout/fragment_tree/fragment.rs b/components/layout/fragment_tree/fragment.rs
index f67da133031..1ebc7b3c989 100644
--- a/components/layout/fragment_tree/fragment.rs
+++ b/components/layout/fragment_tree/fragment.rs
@@ -304,6 +304,25 @@ impl Fragment {
_ => None,
}
}
+
+ pub(crate) fn repair_style(&self, style: &ServoArc<ComputedValues>) {
+ match self {
+ Fragment::Box(box_fragment) | Fragment::Float(box_fragment) => {
+ box_fragment.borrow_mut().style = style.clone()
+ },
+ Fragment::Positioning(positioning_fragment) => {
+ positioning_fragment.borrow_mut().style = style.clone();
+ },
+ Fragment::AbsoluteOrFixedPositioned(positioned_fragment) => {
+ if let Some(ref fragment) = positioned_fragment.borrow().fragment {
+ fragment.repair_style(style);
+ }
+ },
+ Fragment::Text(..) => unreachable!("Should never try to repair style of TextFragment"),
+ Fragment::Image(image_fragment) => image_fragment.borrow_mut().style = style.clone(),
+ Fragment::IFrame(iframe_fragment) => iframe_fragment.borrow_mut().style = style.clone(),
+ }
+ }
}
impl TextFragment {
diff --git a/components/layout/fragment_tree/positioning_fragment.rs b/components/layout/fragment_tree/positioning_fragment.rs
index 803a154ba83..e45a6137bff 100644
--- a/components/layout/fragment_tree/positioning_fragment.rs
+++ b/components/layout/fragment_tree/positioning_fragment.rs
@@ -24,8 +24,8 @@ pub(crate) struct PositioningFragment {
/// The scrollable overflow of this anonymous fragment's children.
pub scrollable_overflow: PhysicalRect<Au>,
- /// If this fragment was created with a style, the style of the fragment.
- pub style: Option<ServoArc<ComputedValues>>,
+ /// The style of the fragment.
+ pub style: ServoArc<ComputedValues>,
/// This [`PositioningFragment`]'s containing block rectangle in coordinates relative to
/// the initial containing block, but not taking into account any transforms.
@@ -33,8 +33,12 @@ pub(crate) struct PositioningFragment {
}
impl PositioningFragment {
- pub fn new_anonymous(rect: PhysicalRect<Au>, children: Vec<Fragment>) -> ArcRefCell<Self> {
- Self::new_with_base_fragment(BaseFragment::anonymous(), None, rect, children)
+ pub fn new_anonymous(
+ style: ServoArc<ComputedValues>,
+ rect: PhysicalRect<Au>,
+ children: Vec<Fragment>,
+ ) -> ArcRefCell<Self> {
+ Self::new_with_base_fragment(BaseFragment::anonymous(), style, rect, children)
}
pub fn new_empty(
@@ -42,12 +46,12 @@ impl PositioningFragment {
rect: PhysicalRect<Au>,
style: ServoArc<ComputedValues>,
) -> ArcRefCell<Self> {
- Self::new_with_base_fragment(base_fragment_info.into(), Some(style), rect, Vec::new())
+ Self::new_with_base_fragment(base_fragment_info.into(), style, rect, Vec::new())
}
fn new_with_base_fragment(
base: BaseFragment,
- style: Option<ServoArc<ComputedValues>>,
+ style: ServoArc<ComputedValues>,
rect: PhysicalRect<Au>,
children: Vec<Fragment>,
) -> ArcRefCell<Self> {
diff --git a/components/layout/layout_box_base.rs b/components/layout/layout_box_base.rs
index d025a627aef..161aee0f9bb 100644
--- a/components/layout/layout_box_base.rs
+++ b/components/layout/layout_box_base.rs
@@ -89,6 +89,13 @@ impl LayoutBoxBase {
pub(crate) fn clear_fragments(&self) {
self.fragments.borrow_mut().clear();
}
+
+ pub(crate) fn repair_style(&mut self, new_style: &Arc<ComputedValues>) {
+ self.style = new_style.clone();
+ for fragment in self.fragments.borrow_mut().iter_mut() {
+ fragment.repair_style(new_style);
+ }
+ }
}
impl Debug for LayoutBoxBase {
diff --git a/components/layout/layout_impl.rs b/components/layout/layout_impl.rs
index cdf76d3fed0..fcf658036b2 100644
--- a/components/layout/layout_impl.rs
+++ b/components/layout/layout_impl.rs
@@ -56,7 +56,7 @@ use style::media_queries::{Device, MediaList, MediaType};
use style::properties::style_structs::Font;
use style::properties::{ComputedValues, PropertyId};
use style::queries::values::PrefersColorScheme;
-use style::selector_parser::{PseudoElement, SnapshotMap};
+use style::selector_parser::{PseudoElement, RestyleDamage, SnapshotMap};
use style::servo::media_queries::FontMetricsProvider;
use style::shared_lock::{SharedRwLock, SharedRwLockReadGuard, StylesheetGuards};
use style::stylesheets::{
@@ -83,7 +83,7 @@ use crate::query::{
process_content_boxes_request, process_node_scroll_area_request, process_offset_parent_query,
process_resolved_font_style_query, process_resolved_style_request, process_text_index_request,
};
-use crate::traversal::RecalcStyle;
+use crate::traversal::{RecalcStyle, compute_damage_and_repair_style};
use crate::{BoxTree, FragmentTree};
// This mutex is necessary due to syncronisation issues between two different types of thread-local storage
@@ -765,6 +765,12 @@ 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 damage == RestyleDamage::REPAINT {
+ layout_context.style_context.stylist.rule_tree().maybe_gc();
+ return;
+ }
+
let mut box_tree = self.box_tree.borrow_mut();
let box_tree = &mut *box_tree;
let mut build_box_tree = || {
diff --git a/components/layout/positioned.rs b/components/layout/positioned.rs
index bb5386dc696..b607462d6eb 100644
--- a/components/layout/positioned.rs
+++ b/components/layout/positioned.rs
@@ -473,7 +473,7 @@ impl HoistedAbsolutelyPositionedBox {
false => shared_fragment.resolved_alignment.inline,
};
- let mut inline_axis_solver = AbsoluteAxisSolver {
+ let inline_axis_solver = AbsoluteAxisSolver {
axis: Direction::Inline,
containing_size: cbis,
padding_border_sum: pbm.padding_border_sums.inline,
@@ -496,7 +496,7 @@ impl HoistedAbsolutelyPositionedBox {
true => style.clone_align_self().0.0,
false => shared_fragment.resolved_alignment.block,
};
- let mut block_axis_solver = AbsoluteAxisSolver {
+ let block_axis_solver = AbsoluteAxisSolver {
axis: Direction::Block,
containing_size: cbbs,
padding_border_sum: pbm.padding_border_sums.block,
@@ -511,52 +511,6 @@ impl HoistedAbsolutelyPositionedBox {
is_table,
};
- if let IndependentFormattingContextContents::Replaced(replaced) = &context.contents {
- // https://drafts.csswg.org/css2/visudet.html#abs-replaced-width
- // https://drafts.csswg.org/css2/visudet.html#abs-replaced-height
- let inset_sums = LogicalVec2 {
- inline: inline_axis_solver.inset_sum(),
- block: block_axis_solver.inset_sum(),
- };
- let automatic_size = |alignment: AlignFlags, offsets: &LogicalSides1D<_>| {
- if alignment.value() == AlignFlags::STRETCH && !offsets.either_auto() {
- Size::Stretch
- } else {
- Size::FitContent
- }
- };
- let used_size = replaced.used_size_as_if_inline_element_from_content_box_sizes(
- containing_block,
- &style,
- context.preferred_aspect_ratio(&pbm.padding_border_sums),
- LogicalVec2 {
- inline: &inline_axis_solver.computed_sizes,
- block: &block_axis_solver.computed_sizes,
- },
- LogicalVec2 {
- inline: automatic_size(inline_alignment, &inline_axis_solver.box_offsets),
- block: automatic_size(block_alignment, &block_axis_solver.box_offsets),
- },
- pbm.padding_border_sums + pbm.margin.auto_is(Au::zero).sum() + inset_sums,
- );
- inline_axis_solver.override_size(used_size.inline);
- block_axis_solver.override_size(used_size.block);
- }
-
- // The block axis can depend on layout results, so we only solve it tentatively,
- // we may have to resolve it properly later on.
- let mut block_axis = block_axis_solver.solve_tentatively();
-
- // The inline axis can be fully resolved, computing intrinsic sizes using the
- // tentative block size.
- let mut inline_axis = inline_axis_solver.solve(Some(|| {
- let ratio = context.preferred_aspect_ratio(&pbm.padding_border_sums);
- let constraint_space = ConstraintSpace::new(block_axis.size, style.writing_mode, ratio);
- context
- .inline_content_sizes(layout_context, &constraint_space)
- .sizes
- }));
-
let mut positioning_context = PositioningContext::default();
let mut new_fragment = {
let content_size: LogicalVec2<Au>;
@@ -566,10 +520,34 @@ impl HoistedAbsolutelyPositionedBox {
IndependentFormattingContextContents::Replaced(replaced) => {
// https://drafts.csswg.org/css2/visudet.html#abs-replaced-width
// https://drafts.csswg.org/css2/visudet.html#abs-replaced-height
- content_size = LogicalVec2 {
- inline: inline_axis.size.to_definite().unwrap(),
- block: block_axis.size.to_definite().unwrap(),
+ let inset_sums = LogicalVec2 {
+ inline: inline_axis_solver.inset_sum(),
+ block: block_axis_solver.inset_sum(),
+ };
+ let automatic_size = |alignment: AlignFlags, offsets: &LogicalSides1D<_>| {
+ if alignment.value() == AlignFlags::STRETCH && !offsets.either_auto() {
+ Size::Stretch
+ } else {
+ Size::FitContent
+ }
};
+ content_size = replaced.used_size_as_if_inline_element_from_content_box_sizes(
+ containing_block,
+ &style,
+ context.preferred_aspect_ratio(&pbm.padding_border_sums),
+ LogicalVec2 {
+ inline: &inline_axis_solver.computed_sizes,
+ block: &block_axis_solver.computed_sizes,
+ },
+ LogicalVec2 {
+ inline: automatic_size(
+ inline_alignment,
+ &inline_axis_solver.box_offsets,
+ ),
+ block: automatic_size(block_alignment, &block_axis_solver.box_offsets),
+ },
+ pbm.padding_border_sums + pbm.margin.auto_is(Au::zero).sum() + inset_sums,
+ );
fragments = replaced.make_fragments(
layout_context,
&style,
@@ -579,11 +557,26 @@ impl HoistedAbsolutelyPositionedBox {
IndependentFormattingContextContents::NonReplaced(non_replaced) => {
// https://drafts.csswg.org/css2/visudet.html#abs-non-replaced-width
// https://drafts.csswg.org/css2/visudet.html#abs-non-replaced-height
- let inline_size = inline_axis.size.to_definite().unwrap();
+
+ // The block size can depend on layout results, so we only solve it extrinsically,
+ // we may have to resolve it properly later on.
+ let extrinsic_block_size = block_axis_solver.solve_size_extrinsically();
+
+ // The inline axis can be fully resolved, computing intrinsic sizes using the
+ // extrinsic block size.
+ let inline_size = inline_axis_solver.solve_size(|| {
+ let ratio = context.preferred_aspect_ratio(&pbm.padding_border_sums);
+ let constraint_space =
+ ConstraintSpace::new(extrinsic_block_size, style.writing_mode, ratio);
+ context
+ .inline_content_sizes(layout_context, &constraint_space)
+ .sizes
+ });
+
let containing_block_for_children = ContainingBlock {
size: ContainingBlockSize {
inline: inline_size,
- block: block_axis.size,
+ block: extrinsic_block_size,
},
style: &style,
};
@@ -603,22 +596,14 @@ impl HoistedAbsolutelyPositionedBox {
false, /* depends_on_block_constraints */
);
- let inline_size = if let Some(inline_size) =
- independent_layout.content_inline_size_for_table
- {
- // Tables can become narrower than predicted due to collapsed columns,
- // so we need to solve again to update margins.
- inline_axis_solver.override_size(inline_size);
- inline_axis = inline_axis_solver.solve_tentatively();
- inline_size
- } else {
- inline_size
- };
+ // Tables can become narrower than predicted due to collapsed columns
+ let inline_size = independent_layout
+ .content_inline_size_for_table
+ .unwrap_or(inline_size);
// Now we can properly solve the block size.
- block_axis = block_axis_solver
- .solve(Some(|| independent_layout.content_block_size.into()));
- let block_size = block_axis.size.to_definite().unwrap();
+ let block_size = block_axis_solver
+ .solve_size(|| independent_layout.content_block_size.into());
content_size = LogicalVec2 {
inline: inline_size,
@@ -629,11 +614,13 @@ impl HoistedAbsolutelyPositionedBox {
},
};
+ let inline_margins = inline_axis_solver.solve_margins(content_size.inline);
+ let block_margins = block_axis_solver.solve_margins(content_size.block);
let margin = LogicalSides {
- inline_start: inline_axis.margin_start,
- inline_end: inline_axis.margin_end,
- block_start: block_axis.margin_start,
- block_end: block_axis.margin_end,
+ inline_start: inline_margins.start,
+ inline_end: inline_margins.end,
+ block_start: block_margins.start,
+ block_end: block_margins.end,
};
let pb = pbm.padding + pbm.border;
@@ -715,12 +702,6 @@ impl LogicalRect<Au> {
}
}
-struct AxisResult {
- size: SizeConstraint,
- margin_start: Au,
- margin_end: Au,
-}
-
struct AbsoluteAxisSolver<'a> {
axis: Direction,
containing_size: Au,
@@ -763,101 +744,77 @@ impl AbsoluteAxisSolver<'_> {
}
}
- /// This unifies some of the parts in common in:
- ///
- /// * <https://drafts.csswg.org/css2/visudet.html#abs-non-replaced-width>
- /// * <https://drafts.csswg.org/css2/visudet.html#abs-non-replaced-height>
- ///
- /// … and:
- ///
- /// * <https://drafts.csswg.org/css2/visudet.html#abs-replaced-width>
- /// * <https://drafts.csswg.org/css2/visudet.html#abs-replaced-height>
- ///
- /// In the replaced case, `size` is never `Auto`.
- fn solve(&self, get_content_size: Option<impl FnOnce() -> ContentSizes>) -> AxisResult {
- let solve_size = |initial_behavior, stretch_size: Au| -> SizeConstraint {
- let stretch_size = stretch_size.max(Au::zero());
- if let Some(get_content_size) = get_content_size {
- SizeConstraint::Definite(self.computed_sizes.resolve(
- self.axis,
- initial_behavior,
- Au::zero,
- Some(stretch_size),
- get_content_size,
- self.is_table,
- ))
- } else {
- self.computed_sizes.resolve_extrinsic(
- initial_behavior,
- Au::zero(),
- Some(stretch_size),
- )
- }
- };
- if self.box_offsets.either_auto() {
- let margin_start = self.computed_margin_start.auto_is(Au::zero);
- let margin_end = self.computed_margin_end.auto_is(Au::zero);
- let stretch_size = self.containing_size -
+ #[inline]
+ fn automatic_size(&self) -> Size<Au> {
+ match self.alignment.value() {
+ _ if self.box_offsets.either_auto() => Size::FitContent,
+ AlignFlags::NORMAL | AlignFlags::AUTO if !self.is_table => Size::Stretch,
+ AlignFlags::STRETCH => Size::Stretch,
+ _ => Size::FitContent,
+ }
+ }
+
+ #[inline]
+ fn stretch_size(&self) -> Au {
+ Au::zero().max(
+ self.containing_size -
self.inset_sum() -
self.padding_border_sum -
- margin_start -
- margin_end;
- let size = solve_size(Size::FitContent, stretch_size);
- AxisResult {
- size,
- margin_start,
- margin_end,
- }
- } else {
- let mut free_space = self.containing_size - self.inset_sum() - self.padding_border_sum;
- let stretch_size = free_space -
self.computed_margin_start.auto_is(Au::zero) -
- self.computed_margin_end.auto_is(Au::zero);
- let initial_behavior = match self.alignment.value() {
- AlignFlags::NORMAL | AlignFlags::AUTO if !self.is_table => Size::Stretch,
- AlignFlags::STRETCH => Size::Stretch,
- _ => Size::FitContent,
- };
- let size = solve_size(initial_behavior, stretch_size);
- if let Some(used_size) = size.to_definite() {
- free_space -= used_size;
- } else {
- free_space = Au::zero();
- }
- let (margin_start, margin_end) =
- match (self.computed_margin_start, self.computed_margin_end) {
- (AuOrAuto::Auto, AuOrAuto::Auto) => {
- if self.avoid_negative_margin_start && free_space < Au::zero() {
- (Au::zero(), free_space)
- } else {
- let margin_start = free_space / 2;
- (margin_start, free_space - margin_start)
- }
- },
- (AuOrAuto::Auto, AuOrAuto::LengthPercentage(end)) => (free_space - end, end),
- (AuOrAuto::LengthPercentage(start), AuOrAuto::Auto) => {
- (start, free_space - start)
- },
- (AuOrAuto::LengthPercentage(start), AuOrAuto::LengthPercentage(end)) => {
- (start, end)
- },
- };
- AxisResult {
- size,
- margin_start,
- margin_end,
- }
- }
+ self.computed_margin_end.auto_is(Au::zero),
+ )
}
- fn solve_tentatively(&mut self) -> AxisResult {
- self.solve(None::<fn() -> ContentSizes>)
+ #[inline]
+ fn solve_size_extrinsically(&self) -> SizeConstraint {
+ self.computed_sizes.resolve_extrinsic(
+ self.automatic_size(),
+ Au::zero(),
+ Some(self.stretch_size()),
+ )
+ }
+
+ #[inline]
+ fn solve_size(&self, get_content_size: impl FnOnce() -> ContentSizes) -> Au {
+ self.computed_sizes.resolve(
+ self.axis,
+ self.automatic_size(),
+ Au::zero,
+ Some(self.stretch_size()),
+ get_content_size,
+ self.is_table,
+ )
}
- fn override_size(&mut self, size: Au) {
- self.computed_sizes.preferred = Size::Numeric(size);
- self.computed_sizes.min = Size::default();
- self.computed_sizes.max = Size::default();
+ fn solve_margins(&self, size: Au) -> LogicalSides1D<Au> {
+ if self.box_offsets.either_auto() {
+ LogicalSides1D::new(
+ self.computed_margin_start.auto_is(Au::zero),
+ self.computed_margin_end.auto_is(Au::zero),
+ )
+ } else {
+ let free_space =
+ self.containing_size - self.inset_sum() - self.padding_border_sum - size;
+ match (self.computed_margin_start, self.computed_margin_end) {
+ (AuOrAuto::Auto, AuOrAuto::Auto) => {
+ if self.avoid_negative_margin_start && free_space < Au::zero() {
+ LogicalSides1D::new(Au::zero(), free_space)
+ } else {
+ let margin_start = free_space / 2;
+ LogicalSides1D::new(margin_start, free_space - margin_start)
+ }
+ },
+ (AuOrAuto::Auto, AuOrAuto::LengthPercentage(end)) => {
+ LogicalSides1D::new(free_space - end, end)
+ },
+ (AuOrAuto::LengthPercentage(start), AuOrAuto::Auto) => {
+ LogicalSides1D::new(start, free_space - start)
+ },
+ (AuOrAuto::LengthPercentage(start), AuOrAuto::LengthPercentage(end)) => {
+ LogicalSides1D::new(start, end)
+ },
+ }
+ }
}
fn origin_for_margin_box(
diff --git a/components/layout/table/layout.rs b/components/layout/table/layout.rs
index 00dac210625..5b7e79d7fb0 100644
--- a/components/layout/table/layout.rs
+++ b/components/layout/table/layout.rs
@@ -2867,6 +2867,7 @@ impl TableSlotCell {
block: vertical_align_offset,
};
let vertical_align_fragment = PositioningFragment::new_anonymous(
+ self.base.style.clone(),
vertical_align_fragment_rect.as_physical(None),
layout.layout.fragments,
);
diff --git a/components/layout/table/mod.rs b/components/layout/table/mod.rs
index 08fc89d927e..72b67863e7d 100644
--- a/components/layout/table/mod.rs
+++ b/components/layout/table/mod.rs
@@ -76,9 +76,12 @@ pub(crate) use construct::AnonymousTableContent;
pub use construct::TableBuilder;
use euclid::{Point2D, Size2D, UnknownUnit, Vector2D};
use malloc_size_of_derive::MallocSizeOf;
+use script::layout_dom::ServoLayoutElement;
use servo_arc::Arc;
+use style::context::SharedStyleContext;
use style::properties::ComputedValues;
use style::properties::style_structs::Font;
+use style::selector_parser::PseudoElement;
use style_traits::dom::OpaqueNode;
use super::flow::BlockFormattingContext;
@@ -191,6 +194,19 @@ impl Table {
),
}
}
+
+ pub(crate) fn repair_style(
+ &mut self,
+ context: &SharedStyleContext,
+ new_style: &Arc<ComputedValues>,
+ ) {
+ self.style = new_style.clone();
+ self.grid_style = context.stylist.style_for_anonymous::<ServoLayoutElement>(
+ &context.guards,
+ &PseudoElement::ServoTableGrid,
+ new_style,
+ );
+ }
}
type TableSlotCoordinates = Point2D<usize, UnknownUnit>;
@@ -232,6 +248,10 @@ impl TableSlotCell {
pub fn node_id(&self) -> usize {
self.base.base_fragment_info.tag.map_or(0, |tag| tag.node.0)
}
+
+ fn repair_style(&mut self, new_style: &Arc<ComputedValues>) {
+ self.base.repair_style(new_style);
+ }
}
/// A single table slot. It may be an actual cell, or a reference
@@ -294,6 +314,13 @@ pub struct TableTrack {
shared_background_style: SharedStyle,
}
+impl TableTrack {
+ fn repair_style(&mut self, new_style: &Arc<ComputedValues>) {
+ self.base.repair_style(new_style);
+ self.shared_background_style = SharedStyle::new(new_style.clone());
+ }
+}
+
#[derive(Debug, MallocSizeOf, PartialEq)]
pub enum TableTrackGroupType {
HeaderGroup,
@@ -323,6 +350,11 @@ impl TableTrackGroup {
pub(super) fn is_empty(&self) -> bool {
self.track_range.is_empty()
}
+
+ fn repair_style(&mut self, new_style: &Arc<ComputedValues>) {
+ self.base.repair_style(new_style);
+ self.shared_background_style = SharedStyle::new(new_style.clone());
+ }
}
#[derive(Debug, MallocSizeOf)]
@@ -389,4 +421,22 @@ impl TableLevelBox {
TableLevelBox::Track(track) => track.borrow().base.fragments(),
}
}
+
+ pub(crate) fn repair_style(
+ &self,
+ context: &SharedStyleContext<'_>,
+ new_style: &Arc<ComputedValues>,
+ ) {
+ match self {
+ TableLevelBox::Caption(caption) => caption
+ .borrow_mut()
+ .context
+ .repair_style(context, new_style),
+ TableLevelBox::Cell(cell) => cell.borrow_mut().repair_style(new_style),
+ TableLevelBox::TrackGroup(track_group) => {
+ track_group.borrow_mut().repair_style(new_style);
+ },
+ TableLevelBox::Track(track) => track.borrow_mut().repair_style(new_style),
+ }
+ }
}
diff --git a/components/layout/taffy/mod.rs b/components/layout/taffy/mod.rs
index fc13e6c52ae..ba80824fa99 100644
--- a/components/layout/taffy/mod.rs
+++ b/components/layout/taffy/mod.rs
@@ -8,6 +8,7 @@ use std::fmt;
use app_units::Au;
use malloc_size_of_derive::MallocSizeOf;
use servo_arc::Arc;
+use style::context::SharedStyleContext;
use style::properties::ComputedValues;
use stylo_taffy::TaffyStyloStyle;
@@ -68,6 +69,10 @@ impl TaffyContainer {
style: info.style.clone(),
}
}
+
+ pub(crate) fn repair_style(&mut self, new_style: &Arc<ComputedValues>) {
+ self.style = new_style.clone();
+ }
}
#[derive(MallocSizeOf)]
@@ -143,6 +148,23 @@ impl TaffyItemBox {
},
}
}
+
+ pub(crate) fn repair_style(
+ &mut self,
+ context: &SharedStyleContext,
+ new_style: &Arc<ComputedValues>,
+ ) {
+ self.style = new_style.clone();
+ match &mut self.taffy_level_box {
+ TaffyItemBoxInner::InFlowBox(independent_formatting_context) => {
+ independent_formatting_context.repair_style(context, new_style)
+ },
+ TaffyItemBoxInner::OutOfFlowAbsolutelyPositionedBox(positioned_box) => positioned_box
+ .borrow_mut()
+ .context
+ .repair_style(context, new_style),
+ }
+ }
}
/// Details from Taffy grid layout that will be stored
diff --git a/components/layout/traversal.rs b/components/layout/traversal.rs
index bf60c41d6ba..17c3d0b1c20 100644
--- a/components/layout/traversal.rs
+++ b/components/layout/traversal.rs
@@ -2,14 +2,18 @@
* 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 script::layout_dom::ServoLayoutNode;
use script_layout_interface::wrapper_traits::LayoutNode;
use style::context::{SharedStyleContext, StyleContext};
use style::data::ElementData;
use style::dom::{NodeInfo, TElement, TNode};
+use style::selector_parser::RestyleDamage;
use style::traversal::{DomTraversal, PerLevelTraversalData, recalc_style_at};
+use style::values::computed::Display;
use crate::context::LayoutContext;
-use crate::dom::DOMLayoutData;
+use crate::dom::{DOMLayoutData, NodeExt};
+use crate::dom_traversal::iter_child_nodes;
pub struct RecalcStyle<'a> {
context: &'a LayoutContext<'a>,
@@ -40,14 +44,33 @@ where
) where
F: FnMut(E::ConcreteNode),
{
+ if node.is_text_node() {
+ return;
+ }
+
+ let had_style_data = node.style_data().is_some();
unsafe {
node.initialize_style_and_layout_data::<DOMLayoutData>();
- if !node.is_text_node() {
- let el = node.as_element().unwrap();
- let mut data = el.mutate_data().unwrap();
- recalc_style_at(self, traversal_data, context, el, &mut data, note_child);
- el.unset_dirty_descendants();
- }
+ }
+
+ let element = node.as_element().unwrap();
+ let mut element_data = element.mutate_data().unwrap();
+
+ if !had_style_data {
+ element_data.damage = RestyleDamage::reconstruct();
+ }
+
+ recalc_style_at(
+ self,
+ traversal_data,
+ context,
+ element,
+ &mut element_data,
+ note_child,
+ );
+
+ unsafe {
+ element.unset_dirty_descendants();
}
}
@@ -68,3 +91,48 @@ where
&self.context.style_context
}
}
+
+pub(crate) fn compute_damage_and_repair_style(
+ context: &SharedStyleContext,
+ node: ServoLayoutNode<'_>,
+) -> RestyleDamage {
+ compute_damage_and_repair_style_inner(context, node, RestyleDamage::empty())
+}
+
+pub(crate) fn compute_damage_and_repair_style_inner(
+ context: &SharedStyleContext,
+ node: ServoLayoutNode<'_>,
+ parent_restyle_damage: RestyleDamage,
+) -> RestyleDamage {
+ let original_damage;
+ let damage = {
+ let mut element_data = node
+ .style_data()
+ .expect("Should not run `compute_damage` before styling.")
+ .element_data
+ .borrow_mut();
+
+ if let Some(ref style) = element_data.styles.primary {
+ if style.get_box().display == Display::None {
+ return parent_restyle_damage;
+ }
+ }
+
+ original_damage = std::mem::take(&mut element_data.damage);
+ element_data.damage |= parent_restyle_damage;
+ element_data.damage
+ };
+
+ let mut propagated_damage = damage;
+ for child in iter_child_nodes(node) {
+ if child.is_element() {
+ propagated_damage |= compute_damage_and_repair_style_inner(context, child, damage);
+ }
+ }
+
+ if propagated_damage == RestyleDamage::REPAINT && original_damage == RestyleDamage::REPAINT {
+ node.repair_style(context);
+ }
+
+ propagated_damage
+}