diff options
author | bors-servo <lbergstrom+bors@mozilla.com> | 2016-08-23 15:43:56 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2016-08-23 15:43:56 -0500 |
commit | d5913035ecef35350897c5fad9960615bbb4cec1 (patch) | |
tree | 88cb1d0ffa5f3eaefaea0ceaf93955055660f5c4 | |
parent | 6f22251e6599aa529ce024d8618595be765c9a18 (diff) | |
parent | 4bb9de4ea5b74bfabf95431c28006d8831d3277d (diff) | |
download | servo-d5913035ecef35350897c5fad9960615bbb4cec1.tar.gz servo-d5913035ecef35350897c5fad9960615bbb4cec1.zip |
Auto merge of #12981 - splav:inline_reconstruct#12602, r=notriddle
Inline reconstruct#12602
<!-- Please describe your changes on the following line: -->
This PR fixes two different issues:
1) In non-incremental layout mode if the inline node hasn't changes - the style pass was skipped, that leads to the corresponding ConstructionResult was not produced. When the parent was rebuilt, the child without the ConstructionResult was omited.
2) When the opacity was changed (or other style change, causing only repaint) for image (and others, producing only ConstructionItem) the damage is calculated only from children's flows, not from individual fragments. So for now, let's pretend we've newly constructed the ConstructionItem and thus need to rebuild the parent's flow.
---
<!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: -->
- [X] `./mach build -d` does not report any errors
- [X] `./mach test-tidy` does not report any errors
- [X] These changes fix #12602 (github issue number if applicable).
<!-- Either: -->
- [x] There are tests for these changes OR
- [ ] These changes do not require tests because _____
<!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. -->
<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/12981)
<!-- Reviewable:end -->
-rw-r--r-- | components/layout/construct.rs | 152 | ||||
-rw-r--r-- | components/script_layout_interface/restyle_damage.rs | 2 | ||||
-rw-r--r-- | components/style/traversal.rs | 2 | ||||
-rw-r--r-- | tests/wpt/mozilla/meta/MANIFEST.json | 24 | ||||
-rw-r--r-- | tests/wpt/mozilla/tests/css/inline_block_opacity_change.html | 26 | ||||
-rw-r--r-- | tests/wpt/mozilla/tests/css/inline_block_opacity_change_ref.html | 17 |
6 files changed, 150 insertions, 73 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 - } - - 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 + 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; + + 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 } - if fragment.pseudo != node.get_pseudo_element_type().strip() { - continue + + 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 } - 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); + 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::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); + if fragment.pseudo != node.get_pseudo_element_type().strip() { + continue } - 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; } } 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 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<N: TNode> { /// 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. diff --git a/tests/wpt/mozilla/meta/MANIFEST.json b/tests/wpt/mozilla/meta/MANIFEST.json index 0546548d847..322e742d7a1 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", @@ -11788,6 +11800,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 @@ +<!DOCTYPE html> +<html> +<head> + <link rel="match" href="inline_block_opacity_change_ref.html"> + <style> + #a { + background-color: green; + display: inline-block; + width: 1em; + opacity: 0.2; + } + + #a.go { + opacity: 1; + } + </style> +</head> + +<body> + <span style="transition: opacity .1s ease-out;" id="a">a</span> + <script> + document.body.offsetWidth; // force layout + document.querySelector('#a').classList.add('go'); + </script> +</body> +</html> 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 @@ +<!DOCTYPE html> +<html> +<head> + <style> + #a { + background-color: green; + display: inline-block; + width: 1em; + opacity: 1; + } + </style> +</head> + +<body> + <span id="a">a</span> +</body> +</html> |