From fc549fcd2f2b63f7b62474938141979362ea8208 Mon Sep 17 00:00:00 2001 From: Alexandrov Sergey Date: Tue, 23 Aug 2016 00:22:36 +0300 Subject: [PATCH 1/4] calculate damage for opacity change --- components/script_layout_interface/restyle_damage.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/script_layout_interface/restyle_damage.rs b/components/script_layout_interface/restyle_damage.rs index 9e2cd1db514..ef33370e064 100644 --- a/components/script_layout_interface/restyle_damage.rs +++ b/components/script_layout_interface/restyle_damage.rs @@ -247,7 +247,7 @@ fn compute_damage(old: &ServoComputedValues, new: &ServoComputedValues) -> Resty get_effects.box_shadow, get_effects.clip, get_inheritedtext.text_shadow, get_effects.filter, get_effects.transform, get_effects.backface_visibility, get_effects.transform_style, get_effects.transform_origin, get_effects.perspective, get_effects.perspective_origin, - get_effects.mix_blend_mode, get_inheritedbox.image_rendering, + get_effects.mix_blend_mode, get_effects.opacity, get_inheritedbox.image_rendering, // Note: May require REFLOW et al. if `visibility: collapse` is implemented. get_inheritedbox.visibility From 3e73475d5bb5673321e1cb7d8f15ff5f2fdb6b38 Mon Sep 17 00:00:00 2001 From: Alexandrov Sergey Date: Tue, 23 Aug 2016 00:24:20 +0300 Subject: [PATCH 2/4] set HAS_NEWLY_CONSTRUCTED_FLOW flag for reconstructed flow'less inline element --- components/layout/construct.rs | 152 ++++++++++++++++++--------------- 1 file changed, 81 insertions(+), 71 deletions(-) diff --git a/components/layout/construct.rs b/components/layout/construct.rs index bb7f0372189..b6e21f6d219 100644 --- a/components/layout/construct.rs +++ b/components/layout/construct.rs @@ -1408,88 +1408,98 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode> return false } - let mut style = node.style(self.style_context()).clone(); - let mut data = node.mutate_layout_data().unwrap(); - let damage = data.restyle_damage; - match *node.construction_result_mut(&mut *data) { - ConstructionResult::None => true, - ConstructionResult::Flow(ref mut flow, _) => { - // The node's flow is of the same type and has the same set of children and can - // therefore be repaired by simply propagating damage and style to the flow. - if !flow.is_block_flow() { - return false - } - let flow = flow_ref::deref_mut(flow); - flow::mut_base(flow).restyle_damage.insert(damage); - flow.repair_style_and_bubble_inline_sizes(&style); - true - } - ConstructionResult::ConstructionItem(ConstructionItem::InlineFragments( - ref mut inline_fragments_construction_result)) => { - if !inline_fragments_construction_result.splits.is_empty() { - return false - } + let mut set_has_newly_constructed_flow_flag = false; + let result = { + let mut style = node.style(self.style_context()).clone(); + let mut data = node.mutate_layout_data().unwrap(); + let damage = data.restyle_damage; - for fragment in inline_fragments_construction_result.fragments - .fragments - .iter_mut() { - // Only mutate the styles of fragments that represent the dirty node (including - // pseudo-element). - if fragment.node != node.opaque() { - continue - } - if fragment.pseudo != node.get_pseudo_element_type().strip() { - continue + match *node.construction_result_mut(&mut *data) { + ConstructionResult::None => true, + ConstructionResult::Flow(ref mut flow, _) => { + // The node's flow is of the same type and has the same set of children and can + // therefore be repaired by simply propagating damage and style to the flow. + if !flow.is_block_flow() { + return false } - match fragment.specific { - SpecificFragmentInfo::InlineBlock(ref mut inline_block_fragment) => { - let flow_ref = flow_ref::deref_mut(&mut inline_block_fragment.flow_ref); - flow::mut_base(flow_ref).restyle_damage.insert(damage); - // FIXME(pcwalton): Fragment restyle damage too? - flow_ref.repair_style_and_bubble_inline_sizes(&style); + let flow = flow_ref::deref_mut(flow); + flow::mut_base(flow).restyle_damage.insert(damage); + flow.repair_style_and_bubble_inline_sizes(&style); + true + } + ConstructionResult::ConstructionItem(ConstructionItem::InlineFragments( + ref mut inline_fragments_construction_result)) => { + if !inline_fragments_construction_result.splits.is_empty() { + return false + } + + for fragment in inline_fragments_construction_result.fragments + .fragments + .iter_mut() { + // Only mutate the styles of fragments that represent the dirty node (including + // pseudo-element). + if fragment.node != node.opaque() { + continue } - SpecificFragmentInfo::InlineAbsoluteHypothetical( - ref mut inline_absolute_hypothetical_fragment) => { - let flow_ref = flow_ref::deref_mut( - &mut inline_absolute_hypothetical_fragment.flow_ref); - flow::mut_base(flow_ref).restyle_damage.insert(damage); - // FIXME(pcwalton): Fragment restyle damage too? - flow_ref.repair_style_and_bubble_inline_sizes(&style); + if fragment.pseudo != node.get_pseudo_element_type().strip() { + continue } - SpecificFragmentInfo::InlineAbsolute(ref mut inline_absolute_fragment) => { - let flow_ref = flow_ref::deref_mut( - &mut inline_absolute_fragment.flow_ref); - flow::mut_base(flow_ref).restyle_damage.insert(damage); - // FIXME(pcwalton): Fragment restyle damage too? - flow_ref.repair_style_and_bubble_inline_sizes(&style); - } - SpecificFragmentInfo::ScannedText(_) => { - // Text fragments in ConstructionResult haven't been scanned yet - unreachable!() - } - SpecificFragmentInfo::GeneratedContent(_) | - SpecificFragmentInfo::UnscannedText(_) => { - // We can't repair this unscanned text; we need to update the - // scanned text fragments. - // - // TODO: Add code to find and repair the ScannedText fragments? - return false - } - _ => { - if node.is_replaced_content() { - properties::modify_style_for_replaced_content(&mut style); + + match fragment.specific { + SpecificFragmentInfo::InlineBlock(ref mut inline_block_fragment) => { + let flow_ref = flow_ref::deref_mut(&mut inline_block_fragment.flow_ref); + flow::mut_base(flow_ref).restyle_damage.insert(damage); + // FIXME(pcwalton): Fragment restyle damage too? + flow_ref.repair_style_and_bubble_inline_sizes(&style); + } + SpecificFragmentInfo::InlineAbsoluteHypothetical( + ref mut inline_absolute_hypothetical_fragment) => { + let flow_ref = flow_ref::deref_mut( + &mut inline_absolute_hypothetical_fragment.flow_ref); + flow::mut_base(flow_ref).restyle_damage.insert(damage); + // FIXME(pcwalton): Fragment restyle damage too? + flow_ref.repair_style_and_bubble_inline_sizes(&style); + } + SpecificFragmentInfo::InlineAbsolute(ref mut inline_absolute_fragment) => { + let flow_ref = flow_ref::deref_mut( + &mut inline_absolute_fragment.flow_ref); + flow::mut_base(flow_ref).restyle_damage.insert(damage); + // FIXME(pcwalton): Fragment restyle damage too? + flow_ref.repair_style_and_bubble_inline_sizes(&style); + } + SpecificFragmentInfo::ScannedText(_) => { + // Text fragments in ConstructionResult haven't been scanned yet + unreachable!() + } + SpecificFragmentInfo::GeneratedContent(_) | + SpecificFragmentInfo::UnscannedText(_) => { + // We can't repair this unscanned text; we need to update the + // scanned text fragments. + // + // TODO: Add code to find and repair the ScannedText fragments? + return false + } + _ => { + if node.is_replaced_content() { + properties::modify_style_for_replaced_content(&mut style); + } + fragment.repair_style(&style); + set_has_newly_constructed_flow_flag = true; } - fragment.repair_style(&style); } } + true + } + ConstructionResult::ConstructionItem(_) => { + false } - true - } - ConstructionResult::ConstructionItem(_) => { - false } + }; + if set_has_newly_constructed_flow_flag { + node.insert_flags(HAS_NEWLY_CONSTRUCTED_FLOW); } + return result; } } From 512764b7dadd4a975f861b89dcffce3936ffbe00 Mon Sep 17 00:00:00 2001 From: Alexandrov Sergey Date: Tue, 23 Aug 2016 00:25:30 +0300 Subject: [PATCH 3/4] force style calculation/element construction for non-incremental mode --- components/style/traversal.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/style/traversal.rs b/components/style/traversal.rs index ed84fafa345..5f041919596 100644 --- a/components/style/traversal.rs +++ b/components/style/traversal.rs @@ -179,7 +179,7 @@ pub trait DomTraversalContext { /// Note that this is true unconditionally for servo, since it requires to /// bubble the widths bottom-up for all the DOM. fn should_process(&self, node: N) -> bool { - node.is_dirty() || node.has_dirty_descendants() + opts::get().nonincremental_layout || node.is_dirty() || node.has_dirty_descendants() } /// Do an action over the child before pushing him to the work queue. From 4bb9de4ea5b74bfabf95431c28006d8831d3277d Mon Sep 17 00:00:00 2001 From: Alexandrov Sergey Date: Tue, 23 Aug 2016 23:08:53 +0300 Subject: [PATCH 4/4] add tests for inline-block element opacity only change incremental reflow --- tests/wpt/mozilla/meta/MANIFEST.json | 24 +++++++++++++++++ .../css/inline_block_opacity_change.html | 26 +++++++++++++++++++ .../css/inline_block_opacity_change_ref.html | 17 ++++++++++++ 3 files changed, 67 insertions(+) create mode 100644 tests/wpt/mozilla/tests/css/inline_block_opacity_change.html create mode 100644 tests/wpt/mozilla/tests/css/inline_block_opacity_change_ref.html diff --git a/tests/wpt/mozilla/meta/MANIFEST.json b/tests/wpt/mozilla/meta/MANIFEST.json index ee90a1be5d4..81cf142111f 100644 --- a/tests/wpt/mozilla/meta/MANIFEST.json +++ b/tests/wpt/mozilla/meta/MANIFEST.json @@ -2496,6 +2496,18 @@ "url": "/_mozilla/css/inline_block_min_width.html" } ], + "css/inline_block_opacity_change.html": [ + { + "path": "css/inline_block_opacity_change.html", + "references": [ + [ + "/_mozilla/css/inline_block_opacity_change_ref.html", + "==" + ] + ], + "url": "/_mozilla/css/inline_block_opacity_change.html" + } + ], "css/inline_block_overflow.html": [ { "path": "css/inline_block_overflow.html", @@ -11764,6 +11776,18 @@ "url": "/_mozilla/css/inline_block_min_width.html" } ], + "css/inline_block_opacity_change.html": [ + { + "path": "css/inline_block_opacity_change.html", + "references": [ + [ + "/_mozilla/css/inline_block_opacity_change_ref.html", + "==" + ] + ], + "url": "/_mozilla/css/inline_block_opacity_change.html" + } + ], "css/inline_block_overflow.html": [ { "path": "css/inline_block_overflow.html", diff --git a/tests/wpt/mozilla/tests/css/inline_block_opacity_change.html b/tests/wpt/mozilla/tests/css/inline_block_opacity_change.html new file mode 100644 index 00000000000..aa51ab444cd --- /dev/null +++ b/tests/wpt/mozilla/tests/css/inline_block_opacity_change.html @@ -0,0 +1,26 @@ + + + + + + + + + a + + + diff --git a/tests/wpt/mozilla/tests/css/inline_block_opacity_change_ref.html b/tests/wpt/mozilla/tests/css/inline_block_opacity_change_ref.html new file mode 100644 index 00000000000..d047a3a8517 --- /dev/null +++ b/tests/wpt/mozilla/tests/css/inline_block_opacity_change_ref.html @@ -0,0 +1,17 @@ + + + + + + + + a + +