servo: Merge #6940 - layout: When repairing styles for incremental reflow, only repair styles of nodes that represent the dirty node, *including its pseudo-element* (from pcwalton:inline-pseudo-repair-jumpiness); r=mbrubeck

r? @mbrubeck

Source-Repo: https://github.com/servo/servo
Source-Revision: 56d3426431d98a6f43698f33bb7ce4d3ad67adeb
This commit is contained in:
Patrick Walton 2015-08-04 12:53:26 -06:00
Родитель 10bcc61257
Коммит 4ecaa5ce11
6 изменённых файлов: 55 добавлений и 13 удалений

Просмотреть файл

@ -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)

Просмотреть файл

@ -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,
}
}

Просмотреть файл

@ -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));

Просмотреть файл

@ -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)]

Просмотреть файл

@ -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
}

Просмотреть файл

@ -0,0 +1 @@
<body>a<br>b</body>