зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
10bcc61257
Коммит
4ecaa5ce11
|
@ -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>
|
Загрузка…
Ссылка в новой задаче