diff options
-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> |