aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbors-servo <metajack+bors@gmail.com>2015-08-04 12:53:26 -0600
committerbors-servo <metajack+bors@gmail.com>2015-08-04 12:53:26 -0600
commit56d3426431d98a6f43698f33bb7ce4d3ad67adeb (patch)
treeacf8f93b9e6c3341a6b95bc527d8b95d393bde9b
parent220557008318350b444ba1917a3b07e03d30bec5 (diff)
parent0a589d413d03b11198033e34b28cb24bed99c0fb (diff)
downloadservo-56d3426431d98a6f43698f33bb7ce4d3ad67adeb.tar.gz
servo-56d3426431d98a6f43698f33bb7ce4d3ad67adeb.zip
Auto merge of #6940 - pcwalton:inline-pseudo-repair-jumpiness, r=mbrubeck
layout: When repairing styles for incremental reflow, only repair styles of nodes that represent the dirty node, *including its pseudo-element*. r? @mbrubeck <!-- Reviewable:start --> [<img src="https://reviewable.io/review_button.png" height=40 alt="Review on Reviewable"/>](https://reviewable.io/reviews/servo/servo/6940) <!-- Reviewable:end -->
-rw-r--r--components/layout/construct.rs19
-rw-r--r--components/layout/fragment.rs10
-rw-r--r--components/layout/generated_content.rs11
-rw-r--r--components/layout/inline.rs5
-rw-r--r--components/layout/wrapper.rs22
-rw-r--r--tests/html/inline-pseudo-repair-jumpiness.html1
6 files changed, 55 insertions, 13 deletions
diff --git a/components/layout/construct.rs b/components/layout/construct.rs
index 9ab1dfc6675..5060eaa3bbd 100644
--- a/components/layout/construct.rs
+++ b/components/layout/construct.rs
@@ -105,7 +105,7 @@ pub enum ConstructionItem {
/// Inline fragments and associated {ib} splits that have not yet found flows.
InlineFragments(InlineFragmentsConstructionResult),
/// Potentially ignorable whitespace.
- Whitespace(OpaqueNode, Arc<ComputedValues>, RestyleDamage),
+ Whitespace(OpaqueNode, PseudoElementType<()>, Arc<ComputedValues>, RestyleDamage),
/// TableColumn Fragment
TableColumnFragment(Fragment),
}
@@ -217,6 +217,7 @@ impl InlineFragmentsAccumulator {
fragments: IntermediateInlineFragments::new(),
enclosing_node: Some(InlineFragmentNodeInfo {
address: node.opaque(),
+ pseudo: node.get_pseudo_element_type().strip(),
style: node.style().clone(),
}),
bidi_control_chars: None,
@@ -573,6 +574,7 @@ impl<'a> FlowConstructor<'a> {
}
ConstructionResult::ConstructionItem(ConstructionItem::Whitespace(
whitespace_node,
+ whitespace_pseudo,
mut whitespace_style,
whitespace_damage)) => {
// Add whitespace results. They will be stripped out later on when
@@ -581,6 +583,7 @@ impl<'a> FlowConstructor<'a> {
UnscannedTextFragmentInfo::from_text(" ".to_owned()));
properties::modify_style_for_replaced_content(&mut whitespace_style);
let fragment = Fragment::from_opaque_node_and_style(whitespace_node,
+ whitespace_pseudo,
whitespace_style,
whitespace_damage,
fragment_info);
@@ -712,6 +715,8 @@ impl<'a> FlowConstructor<'a> {
fragments.fragments
.push_back(Fragment::from_opaque_node_and_style(node.opaque(),
+ node.get_pseudo_element_type()
+ .strip(),
style.clone(),
node.restyle_damage(),
specific))
@@ -793,12 +798,14 @@ impl<'a> FlowConstructor<'a> {
} else {
// Push the absolutely-positioned kid as an inline containing block.
let kid_node = flow.as_block().fragment.node;
+ let kid_pseudo = flow.as_block().fragment.pseudo.clone();
let kid_style = flow.as_block().fragment.style.clone();
let kid_restyle_damage = flow.as_block().fragment.restyle_damage;
let fragment_info = SpecificFragmentInfo::InlineAbsolute(
InlineAbsoluteFragmentInfo::new(flow));
fragment_accumulator.push(Fragment::from_opaque_node_and_style(
kid_node,
+ kid_pseudo,
kid_style,
kid_restyle_damage,
fragment_info));
@@ -826,6 +833,7 @@ impl<'a> FlowConstructor<'a> {
}
ConstructionResult::ConstructionItem(ConstructionItem::Whitespace(
whitespace_node,
+ whitespace_pseudo,
mut whitespace_style,
whitespace_damage)) => {
// Instantiate the whitespace fragment.
@@ -833,6 +841,7 @@ impl<'a> FlowConstructor<'a> {
UnscannedTextFragmentInfo::from_text(" ".to_owned()));
properties::modify_style_for_replaced_content(&mut whitespace_style);
let fragment = Fragment::from_opaque_node_and_style(whitespace_node,
+ whitespace_pseudo,
whitespace_style,
whitespace_damage,
fragment_info);
@@ -875,6 +884,7 @@ impl<'a> FlowConstructor<'a> {
if node.is_ignorable_whitespace() {
return ConstructionResult::ConstructionItem(ConstructionItem::Whitespace(
node.opaque(),
+ node.get_pseudo_element_type().strip(),
node.style().clone(),
node.restyle_damage()))
}
@@ -1295,10 +1305,14 @@ impl<'a> FlowConstructor<'a> {
for fragment in inline_fragments_construction_result.fragments
.fragments
.iter_mut() {
- // Only mutate the styles of fragments that represent the dirty node.
+ // 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 fragment.specific {
SpecificFragmentInfo::InlineBlock(ref mut inline_block_fragment) => {
@@ -1689,6 +1703,7 @@ fn control_chars_to_fragment(node: &InlineFragmentNodeInfo, text: &str,
let info = SpecificFragmentInfo::UnscannedText(
UnscannedTextFragmentInfo::from_text(String::from(text)));
Fragment::from_opaque_node_and_style(node.address,
+ node.pseudo,
node.style.clone(),
restyle_damage,
info)
diff --git a/components/layout/fragment.rs b/components/layout/fragment.rs
index 61a6042b6df..1f7ecce5fe9 100644
--- a/components/layout/fragment.rs
+++ b/components/layout/fragment.rs
@@ -17,7 +17,7 @@ use inline::{InlineFragmentContext, InlineFragmentNodeInfo, InlineMetrics};
use layout_debug;
use model::{self, IntrinsicISizes, IntrinsicISizesContribution, MaybeAuto, specified};
use text;
-use wrapper::ThreadSafeLayoutNode;
+use wrapper::{PseudoElementType, ThreadSafeLayoutNode};
use euclid::{Point2D, Rect, Size2D};
use gfx::display_list::{BLUR_INFLATION_FACTOR, OpaqueNode};
@@ -107,6 +107,9 @@ pub struct Fragment {
/// How damaged this fragment is since last reflow.
pub restyle_damage: RestyleDamage,
+ /// The pseudo-element that this fragment represents.
+ pub pseudo: PseudoElementType<()>,
+
/// A debug ID that is consistent for the life of this fragment (via transform etc).
pub debug_id: u16,
}
@@ -752,6 +755,7 @@ impl Fragment {
margin: LogicalMargin::zero(writing_mode),
specific: specific,
inline_context: None,
+ pseudo: node.get_pseudo_element_type().strip(),
debug_id: layout_debug::generate_unique_debug_id(),
}
}
@@ -782,12 +786,14 @@ impl Fragment {
margin: LogicalMargin::zero(writing_mode),
specific: specific,
inline_context: None,
+ pseudo: node.get_pseudo_element_type().strip(),
debug_id: layout_debug::generate_unique_debug_id(),
}
}
/// Constructs a new `Fragment` instance from an opaque node.
pub fn from_opaque_node_and_style(node: OpaqueNode,
+ pseudo: PseudoElementType<()>,
style: Arc<ComputedValues>,
restyle_damage: RestyleDamage,
specific: SpecificFragmentInfo)
@@ -802,6 +808,7 @@ impl Fragment {
margin: LogicalMargin::zero(writing_mode),
specific: specific,
inline_context: None,
+ pseudo: pseudo,
debug_id: layout_debug::generate_unique_debug_id(),
}
}
@@ -834,6 +841,7 @@ impl Fragment {
margin: self.margin,
specific: info,
inline_context: self.inline_context.clone(),
+ pseudo: self.pseudo.clone(),
debug_id: self.debug_id,
}
}
diff --git a/components/layout/generated_content.rs b/components/layout/generated_content.rs
index a5803d2484c..6e9f5da9918 100644
--- a/components/layout/generated_content.rs
+++ b/components/layout/generated_content.rs
@@ -15,6 +15,7 @@ use fragment::{Fragment, GeneratedContentInfo, SpecificFragmentInfo, UnscannedTe
use incremental::{self, RESOLVE_GENERATED_CONTENT};
use smallvec::SmallVec;
use text::TextRunScanner;
+use wrapper::PseudoElementType;
use gfx::display_list::OpaqueNode;
use std::collections::{LinkedList, HashMap};
@@ -174,6 +175,7 @@ impl<'a,'b> ResolveGeneratedContentFragmentMutator<'a,'b> {
GeneratedContentInfo::ListItem => {
new_info = self.traversal.list_item.render(self.traversal.layout_context,
fragment.node,
+ fragment.pseudo.clone(),
fragment.style.clone(),
list_style_type,
RenderingMode::Suffix(".\u{00a0}"))
@@ -190,6 +192,7 @@ impl<'a,'b> ResolveGeneratedContentFragmentMutator<'a,'b> {
.unwrap_or(&mut temporary_counter);
new_info = counter.render(self.traversal.layout_context,
fragment.node,
+ fragment.pseudo.clone(),
fragment.style.clone(),
counter_style,
RenderingMode::Plain)
@@ -204,6 +207,7 @@ impl<'a,'b> ResolveGeneratedContentFragmentMutator<'a,'b> {
.unwrap_or(&mut temporary_counter);
new_info = counter.render(self.traversal.layout_context,
fragment.node,
+ fragment.pseudo,
fragment.style.clone(),
counter_style,
RenderingMode::All(&separator));
@@ -211,6 +215,7 @@ impl<'a,'b> ResolveGeneratedContentFragmentMutator<'a,'b> {
GeneratedContentInfo::ContentItem(ContentItem::OpenQuote) => {
new_info = Some(render_text(self.traversal.layout_context,
fragment.node,
+ fragment.pseudo,
fragment.style.clone(),
self.quote(&*fragment.style, false)));
self.traversal.quote += 1
@@ -222,6 +227,7 @@ impl<'a,'b> ResolveGeneratedContentFragmentMutator<'a,'b> {
new_info = Some(render_text(self.traversal.layout_context,
fragment.node,
+ fragment.pseudo,
fragment.style.clone(),
self.quote(&*fragment.style, true)));
}
@@ -356,6 +362,7 @@ impl Counter {
fn render(&self,
layout_context: &LayoutContext,
node: OpaqueNode,
+ pseudo: PseudoElementType<()>,
style: Arc<ComputedValues>,
list_style_type: list_style_type::T,
mode: RenderingMode)
@@ -392,7 +399,7 @@ impl Counter {
if string.is_empty() {
None
} else {
- Some(render_text(layout_context, node, style, string))
+ Some(render_text(layout_context, node, pseudo, style, string))
}
}
}
@@ -418,12 +425,14 @@ struct CounterValue {
/// Creates fragment info for a literal string.
fn render_text(layout_context: &LayoutContext,
node: OpaqueNode,
+ pseudo: PseudoElementType<()>,
style: Arc<ComputedValues>,
string: String)
-> SpecificFragmentInfo {
let mut fragments = LinkedList::new();
let info = SpecificFragmentInfo::UnscannedText(UnscannedTextFragmentInfo::from_text(string));
fragments.push_back(Fragment::from_opaque_node_and_style(node,
+ pseudo,
style,
incremental::rebuild_and_reflow(),
info));
diff --git a/components/layout/inline.rs b/components/layout/inline.rs
index 6d4d67e6bbb..78363d0451c 100644
--- a/components/layout/inline.rs
+++ b/components/layout/inline.rs
@@ -15,6 +15,7 @@ use incremental::{REFLOW, REFLOW_OUT_OF_FLOW, RESOLVE_GENERATED_CONTENT};
use layout_debug;
use model::IntrinsicISizesContribution;
use text;
+use wrapper::PseudoElementType;
use euclid::{Point2D, Rect, Size2D};
use gfx::display_list::OpaqueNode;
@@ -1349,8 +1350,7 @@ impl Flow for InlineFlow {
self.base.block_container_explicit_block_size;
for fragment in self.fragments.fragments.iter_mut() {
fragment.update_late_computed_replaced_inline_size_if_necessary();
- fragment.assign_replaced_block_size_if_necessary(
- containing_block_block_size);
+ fragment.assign_replaced_block_size_if_necessary(containing_block_block_size);
}
// Reset our state, so that we handle incremental reflow correctly.
@@ -1687,6 +1687,7 @@ impl fmt::Debug for InlineFlow {
pub struct InlineFragmentNodeInfo {
pub address: OpaqueNode,
pub style: Arc<ComputedValues>,
+ pub pseudo: PseudoElementType<()>,
}
#[derive(Clone)]
diff --git a/components/layout/wrapper.rs b/components/layout/wrapper.rs
index 26378daf40c..93e52192d64 100644
--- a/components/layout/wrapper.rs
+++ b/components/layout/wrapper.rs
@@ -588,13 +588,13 @@ impl<'le> TElementAttributes for LayoutElement<'le> {
}
#[derive(Copy, PartialEq, Clone)]
-pub enum PseudoElementType {
+pub enum PseudoElementType<T> {
Normal,
- Before(display::T),
- After(display::T),
+ Before(T),
+ After(T),
}
-impl PseudoElementType {
+impl<T> PseudoElementType<T> {
pub fn is_before(&self) -> bool {
match *self {
PseudoElementType::Before(_) => true,
@@ -608,6 +608,14 @@ impl PseudoElementType {
_ => false,
}
}
+
+ pub fn strip(&self) -> PseudoElementType<()> {
+ match *self {
+ PseudoElementType::Normal => PseudoElementType::Normal,
+ PseudoElementType::Before(_) => PseudoElementType::Before(()),
+ PseudoElementType::After(_) => PseudoElementType::After(()),
+ }
+ }
}
/// A thread-safe version of `LayoutNode`, used during flow construction. This type of layout
@@ -617,7 +625,7 @@ pub struct ThreadSafeLayoutNode<'ln> {
/// The wrapped node.
node: LayoutNode<'ln>,
- pseudo: PseudoElementType,
+ pseudo: PseudoElementType<display::T>,
}
impl<'ln> ThreadSafeLayoutNode<'ln> {
@@ -639,7 +647,7 @@ impl<'ln> ThreadSafeLayoutNode<'ln> {
/// Creates a new `ThreadSafeLayoutNode` for the same `LayoutNode`
/// with a different pseudo-element type.
- fn with_pseudo(&self, pseudo: PseudoElementType) -> ThreadSafeLayoutNode<'ln> {
+ fn with_pseudo(&self, pseudo: PseudoElementType<display::T>) -> ThreadSafeLayoutNode<'ln> {
ThreadSafeLayoutNode {
node: self.node.clone(),
pseudo: pseudo,
@@ -697,7 +705,7 @@ impl<'ln> ThreadSafeLayoutNode<'ln> {
}
#[inline]
- pub fn get_pseudo_element_type(&self) -> PseudoElementType {
+ pub fn get_pseudo_element_type(&self) -> PseudoElementType<display::T> {
self.pseudo
}
diff --git a/tests/html/inline-pseudo-repair-jumpiness.html b/tests/html/inline-pseudo-repair-jumpiness.html
new file mode 100644
index 00000000000..d95c12f939c
--- /dev/null
+++ b/tests/html/inline-pseudo-repair-jumpiness.html
@@ -0,0 +1 @@
+<body>a<br>b</body>