mirror of
https://github.com/servo/servo.git
synced 2025-08-03 04:30:10 +01:00
layout: Correct damage propagation and style repair for repaint-only layout (#37004)
When making last-minute changes to the repaint-only layout pass, damage propagation was broken, meaning that full layout was always done. This change fixes that, meaning that times in the `blaster.html` test case now reflect those described in the original commit message from #36978. In addition, some style repair is now fixed: - `InlineFormattingContext`s now keep a `SharedInlineStyles` for the root of the IFC which is updated during style repair. - `BlockFormattingContext`s now properly update their style. These changes are verified by turning on repaint only layout for more properties in Stylo via servo/stylo#183. Testing: Manual performance testing via `blaster.html`. Signed-off-by: Martin Robinson <mrobinson@igalia.com>
This commit is contained in:
parent
89f7026cc8
commit
573663d502
10 changed files with 91 additions and 48 deletions
|
@ -126,15 +126,15 @@ impl LayoutBox {
|
|||
.repair_style(context, node, new_style);
|
||||
}
|
||||
},
|
||||
LayoutBox::FlexLevel(flex_level_box) => {
|
||||
flex_level_box.borrow_mut().repair_style(context, new_style)
|
||||
},
|
||||
LayoutBox::FlexLevel(flex_level_box) => flex_level_box
|
||||
.borrow_mut()
|
||||
.repair_style(context, node, 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)
|
||||
table_level_box.repair_style(context, node, new_style)
|
||||
},
|
||||
LayoutBox::TaffyItemBox(taffy_item_box) => taffy_item_box
|
||||
.borrow_mut()
|
||||
.repair_style(context, node, new_style),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
use geom::{FlexAxis, MainStartCrossStart};
|
||||
use malloc_size_of_derive::MallocSizeOf;
|
||||
use script::layout_dom::ServoLayoutNode;
|
||||
use servo_arc::Arc as ServoArc;
|
||||
use style::context::SharedStyleContext;
|
||||
use style::logical_geometry::WritingMode;
|
||||
|
@ -154,16 +155,17 @@ impl FlexLevelBox {
|
|||
pub(crate) fn repair_style(
|
||||
&mut self,
|
||||
context: &SharedStyleContext,
|
||||
node: &ServoLayoutNode,
|
||||
new_style: &ServoArc<ComputedValues>,
|
||||
) {
|
||||
match self {
|
||||
FlexLevelBox::FlexItem(flex_item_box) => flex_item_box
|
||||
.independent_formatting_context
|
||||
.repair_style(context, new_style),
|
||||
.repair_style(context, node, new_style),
|
||||
FlexLevelBox::OutOfFlowAbsolutelyPositionedBox(positioned_box) => positioned_box
|
||||
.borrow_mut()
|
||||
.context
|
||||
.repair_style(context, new_style),
|
||||
.repair_style(context, node, new_style),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ pub(crate) struct InlineFormattingContextBuilder {
|
|||
/// inline box stack, and importantly, one for every `display: contents` element that we are
|
||||
/// currently processing. Normally `display: contents` elements don't affect the structure of
|
||||
/// the [`InlineFormattingContext`], but the styles they provide do style their children.
|
||||
shared_inline_styles_stack: Vec<SharedInlineStyles>,
|
||||
pub shared_inline_styles_stack: Vec<SharedInlineStyles>,
|
||||
|
||||
/// The collection of text strings that make up this [`InlineFormattingContext`] under
|
||||
/// construction.
|
||||
|
|
|
@ -91,6 +91,7 @@ use line_breaker::LineBreaker;
|
|||
use malloc_size_of_derive::MallocSizeOf;
|
||||
use range::Range;
|
||||
use script::layout_dom::ServoLayoutNode;
|
||||
use script_layout_interface::wrapper_traits::{LayoutNode, ThreadSafeLayoutNode};
|
||||
use servo_arc::Arc;
|
||||
use style::Zero;
|
||||
use style::computed_values::text_wrap_mode::T as TextWrapMode;
|
||||
|
@ -158,6 +159,10 @@ pub(crate) struct InlineFormattingContext {
|
|||
/// context in order to avoid duplicating this information.
|
||||
pub font_metrics: Vec<FontKeyAndMetrics>,
|
||||
|
||||
/// The [`SharedInlineStyles`] for the root of this [`InlineFormattingContext`] that are used to
|
||||
/// share styles with all [`TextRun`] children.
|
||||
pub(super) shared_inline_styles: SharedInlineStyles,
|
||||
|
||||
pub(super) text_decoration_line: TextDecorationLine,
|
||||
|
||||
/// Whether this IFC contains the 1st formatted line of an element:
|
||||
|
@ -237,12 +242,14 @@ impl InlineItem {
|
|||
InlineItem::OutOfFlowAbsolutelyPositionedBox(positioned_box, ..) => positioned_box
|
||||
.borrow_mut()
|
||||
.context
|
||||
.repair_style(context, new_style),
|
||||
.repair_style(context, node, 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),
|
||||
.repair_style(context, node, new_style),
|
||||
InlineItem::Atomic(atomic, ..) => {
|
||||
atomic.borrow_mut().repair_style(context, node, new_style)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1699,6 +1706,11 @@ impl InlineFormattingContext {
|
|||
inline_items: builder.inline_items,
|
||||
inline_boxes: builder.inline_boxes,
|
||||
font_metrics,
|
||||
shared_inline_styles: builder
|
||||
.shared_inline_styles_stack
|
||||
.last()
|
||||
.expect("Should have at least one SharedInlineStyle for the root of an IFC")
|
||||
.clone(),
|
||||
text_decoration_line: propagated_data.text_decoration,
|
||||
has_first_formatted_line,
|
||||
contains_floats: builder.contains_floats,
|
||||
|
@ -1707,6 +1719,11 @@ impl InlineFormattingContext {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn repair_style(&self, node: &ServoLayoutNode, new_style: &Arc<ComputedValues>) {
|
||||
*self.shared_inline_styles.style.borrow_mut() = new_style.clone();
|
||||
*self.shared_inline_styles.selected.borrow_mut() = node.to_threadsafe().selected_style();
|
||||
}
|
||||
|
||||
pub(super) fn layout(
|
||||
&self,
|
||||
layout_context: &LayoutContext,
|
||||
|
|
|
@ -78,6 +78,15 @@ impl BlockContainer {
|
|||
BlockContainer::InlineFormattingContext(context) => context.contains_floats,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn repair_style(&mut self, node: &ServoLayoutNode, new_style: &Arc<ComputedValues>) {
|
||||
match self {
|
||||
BlockContainer::BlockLevelBoxes(..) => {},
|
||||
BlockContainer::InlineFormattingContext(inline_formatting_context) => {
|
||||
inline_formatting_context.repair_style(node, new_style)
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, MallocSizeOf)]
|
||||
|
@ -106,20 +115,21 @@ impl BlockLevelBox {
|
|||
|
||||
match self {
|
||||
BlockLevelBox::Independent(independent_formatting_context) => {
|
||||
independent_formatting_context.repair_style(context, new_style)
|
||||
independent_formatting_context.repair_style(context, node, new_style)
|
||||
},
|
||||
BlockLevelBox::OutOfFlowAbsolutelyPositionedBox(positioned_box) => positioned_box
|
||||
.borrow_mut()
|
||||
.context
|
||||
.repair_style(context, new_style),
|
||||
.repair_style(context, node, new_style),
|
||||
BlockLevelBox::OutOfFlowFloatBox(float_box) => {
|
||||
float_box.contents.repair_style(context, new_style)
|
||||
float_box.contents.repair_style(context, node, new_style)
|
||||
},
|
||||
BlockLevelBox::OutsideMarker(outside_marker) => {
|
||||
outside_marker.repair_style(context, node, new_style)
|
||||
},
|
||||
BlockLevelBox::SameFormattingContextBlock { base, .. } => {
|
||||
BlockLevelBox::SameFormattingContextBlock { base, contents, .. } => {
|
||||
base.repair_style(new_style);
|
||||
contents.repair_style(node, new_style);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -477,6 +487,10 @@ impl BlockFormattingContext {
|
|||
pub(crate) fn layout_style<'a>(&self, base: &'a LayoutBoxBase) -> LayoutStyle<'a> {
|
||||
LayoutStyle::Default(&base.style)
|
||||
}
|
||||
|
||||
pub(crate) fn repair_style(&mut self, node: &ServoLayoutNode, new_style: &Arc<ComputedValues>) {
|
||||
self.contents.repair_style(node, new_style);
|
||||
}
|
||||
}
|
||||
|
||||
/// Finds the min/max-content inline size of the block-level children of a block container.
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
use app_units::Au;
|
||||
use malloc_size_of_derive::MallocSizeOf;
|
||||
use script::layout_dom::ServoLayoutElement;
|
||||
use script::layout_dom::{ServoLayoutElement, ServoLayoutNode};
|
||||
use servo_arc::Arc;
|
||||
use style::context::SharedStyleContext;
|
||||
use style::properties::ComputedValues;
|
||||
|
@ -223,12 +223,13 @@ impl IndependentFormattingContext {
|
|||
pub(crate) fn repair_style(
|
||||
&mut self,
|
||||
context: &SharedStyleContext,
|
||||
node: &ServoLayoutNode,
|
||||
new_style: &Arc<ComputedValues>,
|
||||
) {
|
||||
self.base.repair_style(new_style);
|
||||
match &mut self.contents {
|
||||
IndependentFormattingContextContents::NonReplaced(content) => {
|
||||
content.repair_style(context, new_style);
|
||||
content.repair_style(context, node, new_style);
|
||||
},
|
||||
IndependentFormattingContextContents::Replaced(..) => {},
|
||||
}
|
||||
|
@ -356,9 +357,16 @@ impl IndependentNonReplacedContents {
|
|||
matches!(self, Self::Table(_))
|
||||
}
|
||||
|
||||
fn repair_style(&mut self, context: &SharedStyleContext, new_style: &Arc<ComputedValues>) {
|
||||
fn repair_style(
|
||||
&mut self,
|
||||
context: &SharedStyleContext,
|
||||
node: &ServoLayoutNode,
|
||||
new_style: &Arc<ComputedValues>,
|
||||
) {
|
||||
match self {
|
||||
IndependentNonReplacedContents::Flow(..) => {},
|
||||
IndependentNonReplacedContents::Flow(block_formatting_context) => {
|
||||
block_formatting_context.repair_style(node, new_style);
|
||||
},
|
||||
IndependentNonReplacedContents::Flex(flex_container) => {
|
||||
flex_container.repair_style(new_style)
|
||||
},
|
||||
|
|
|
@ -76,7 +76,7 @@ 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 script::layout_dom::{ServoLayoutElement, ServoLayoutNode};
|
||||
use servo_arc::Arc;
|
||||
use style::context::SharedStyleContext;
|
||||
use style::properties::ComputedValues;
|
||||
|
@ -425,13 +425,14 @@ impl TableLevelBox {
|
|||
pub(crate) fn repair_style(
|
||||
&self,
|
||||
context: &SharedStyleContext<'_>,
|
||||
node: &ServoLayoutNode,
|
||||
new_style: &Arc<ComputedValues>,
|
||||
) {
|
||||
match self {
|
||||
TableLevelBox::Caption(caption) => caption
|
||||
.borrow_mut()
|
||||
.context
|
||||
.repair_style(context, new_style),
|
||||
.repair_style(context, node, new_style),
|
||||
TableLevelBox::Cell(cell) => cell.borrow_mut().repair_style(new_style),
|
||||
TableLevelBox::TrackGroup(track_group) => {
|
||||
track_group.borrow_mut().repair_style(new_style);
|
||||
|
|
|
@ -7,6 +7,7 @@ use std::fmt;
|
|||
|
||||
use app_units::Au;
|
||||
use malloc_size_of_derive::MallocSizeOf;
|
||||
use script::layout_dom::ServoLayoutNode;
|
||||
use servo_arc::Arc;
|
||||
use style::context::SharedStyleContext;
|
||||
use style::properties::ComputedValues;
|
||||
|
@ -152,17 +153,18 @@ impl TaffyItemBox {
|
|||
pub(crate) fn repair_style(
|
||||
&mut self,
|
||||
context: &SharedStyleContext,
|
||||
node: &ServoLayoutNode,
|
||||
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)
|
||||
independent_formatting_context.repair_style(context, node, new_style)
|
||||
},
|
||||
TaffyItemBoxInner::OutOfFlowAbsolutelyPositionedBox(positioned_box) => positioned_box
|
||||
.borrow_mut()
|
||||
.context
|
||||
.repair_style(context, new_style),
|
||||
.repair_style(context, node, new_style),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -112,15 +112,14 @@ pub(crate) fn compute_damage_and_repair_style_inner(
|
|||
.element_data
|
||||
.borrow_mut();
|
||||
|
||||
original_damage = std::mem::take(&mut element_data.damage);
|
||||
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
|
||||
original_damage | parent_restyle_damage
|
||||
};
|
||||
|
||||
let mut propagated_damage = damage;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue