mirror of
https://github.com/servo/servo.git
synced 2025-08-05 13:40:08 +01:00
Introduce a concept of restyle damage to the style system.
We can't hoist RestyleDamage itself, because it's very layout-dependent. But this should be enough to let us hoist the things we need.
This commit is contained in:
parent
947134949a
commit
27987c3bb4
7 changed files with 61 additions and 31 deletions
|
@ -35,7 +35,7 @@ use flow_ref::{self, FlowRef, WeakFlowRef};
|
||||||
use fragment::{Fragment, FragmentBorderBoxIterator, SpecificFragmentInfo};
|
use fragment::{Fragment, FragmentBorderBoxIterator, SpecificFragmentInfo};
|
||||||
use gfx::display_list::{ClippingRegion, DisplayList};
|
use gfx::display_list::{ClippingRegion, DisplayList};
|
||||||
use gfx_traits::LayerId;
|
use gfx_traits::LayerId;
|
||||||
use incremental::{self, RECONSTRUCT_FLOW, REFLOW, REFLOW_OUT_OF_FLOW, RestyleDamage};
|
use incremental::{RECONSTRUCT_FLOW, REFLOW, REFLOW_OUT_OF_FLOW, RestyleDamage};
|
||||||
use inline::InlineFlow;
|
use inline::InlineFlow;
|
||||||
use model::{CollapsibleMargins, IntrinsicISizes, MarginCollapseInfo};
|
use model::{CollapsibleMargins, IntrinsicISizes, MarginCollapseInfo};
|
||||||
use msg::compositor_msg::LayerType;
|
use msg::compositor_msg::LayerType;
|
||||||
|
@ -48,6 +48,7 @@ use std::sync::Arc;
|
||||||
use std::sync::atomic::Ordering;
|
use std::sync::atomic::Ordering;
|
||||||
use std::{fmt, mem, raw};
|
use std::{fmt, mem, raw};
|
||||||
use style::computed_values::{clear, display, empty_cells, float, position, text_align};
|
use style::computed_values::{clear, display, empty_cells, float, position, text_align};
|
||||||
|
use style::dom::TRestyleDamage;
|
||||||
use style::properties::{self, ComputedValues};
|
use style::properties::{self, ComputedValues};
|
||||||
use style::values::computed::LengthOrPercentageOrAuto;
|
use style::values::computed::LengthOrPercentageOrAuto;
|
||||||
use table::{ColumnComputedInlineSize, ColumnIntrinsicInlineSize, TableFlow};
|
use table::{ColumnComputedInlineSize, ColumnIntrinsicInlineSize, TableFlow};
|
||||||
|
@ -1046,7 +1047,7 @@ impl BaseFlow {
|
||||||
}
|
}
|
||||||
|
|
||||||
// New flows start out as fully damaged.
|
// New flows start out as fully damaged.
|
||||||
let mut damage = incremental::rebuild_and_reflow();
|
let mut damage = RestyleDamage::rebuild_and_reflow();
|
||||||
damage.remove(RECONSTRUCT_FLOW);
|
damage.remove(RECONSTRUCT_FLOW);
|
||||||
|
|
||||||
BaseFlow {
|
BaseFlow {
|
||||||
|
|
|
@ -18,7 +18,7 @@ use gfx::display_list::{BLUR_INFLATION_FACTOR, OpaqueNode};
|
||||||
use gfx::text::glyph::CharIndex;
|
use gfx::text::glyph::CharIndex;
|
||||||
use gfx::text::text_run::{TextRun, TextRunSlice};
|
use gfx::text::text_run::{TextRun, TextRunSlice};
|
||||||
use gfx_traits::LayerId;
|
use gfx_traits::LayerId;
|
||||||
use incremental::{self, RECONSTRUCT_FLOW, RestyleDamage};
|
use incremental::{RECONSTRUCT_FLOW, RestyleDamage};
|
||||||
use inline::{FIRST_FRAGMENT_OF_ELEMENT, InlineFragmentContext, InlineFragmentNodeInfo};
|
use inline::{FIRST_FRAGMENT_OF_ELEMENT, InlineFragmentContext, InlineFragmentNodeInfo};
|
||||||
use inline::{InlineMetrics, LAST_FRAGMENT_OF_ELEMENT};
|
use inline::{InlineMetrics, LAST_FRAGMENT_OF_ELEMENT};
|
||||||
use ipc_channel::ipc::IpcSender;
|
use ipc_channel::ipc::IpcSender;
|
||||||
|
@ -40,6 +40,7 @@ use style::computed_values::content::ContentItem;
|
||||||
use style::computed_values::{border_collapse, clear, display, mix_blend_mode, overflow_wrap};
|
use style::computed_values::{border_collapse, clear, display, mix_blend_mode, overflow_wrap};
|
||||||
use style::computed_values::{overflow_x, position, text_decoration, transform_style};
|
use style::computed_values::{overflow_x, position, text_decoration, transform_style};
|
||||||
use style::computed_values::{white_space, word_break, z_index};
|
use style::computed_values::{white_space, word_break, z_index};
|
||||||
|
use style::dom::TRestyleDamage;
|
||||||
use style::properties::ComputedValues;
|
use style::properties::ComputedValues;
|
||||||
use style::values::computed::{LengthOrPercentage, LengthOrPercentageOrAuto};
|
use style::values::computed::{LengthOrPercentage, LengthOrPercentageOrAuto};
|
||||||
use style::values::computed::{LengthOrPercentageOrNone};
|
use style::values::computed::{LengthOrPercentageOrNone};
|
||||||
|
@ -833,7 +834,7 @@ impl Fragment {
|
||||||
self.border_box.start,
|
self.border_box.start,
|
||||||
size);
|
size);
|
||||||
|
|
||||||
let mut restyle_damage = incremental::rebuild_and_reflow();
|
let mut restyle_damage = RestyleDamage::rebuild_and_reflow();
|
||||||
restyle_damage.remove(RECONSTRUCT_FLOW);
|
restyle_damage.remove(RECONSTRUCT_FLOW);
|
||||||
|
|
||||||
Fragment {
|
Fragment {
|
||||||
|
|
|
@ -13,12 +13,13 @@ use flow::{InorderFlowTraversal};
|
||||||
use flow::{self, AFFECTS_COUNTERS, Flow, HAS_COUNTER_AFFECTING_CHILDREN, ImmutableFlowUtils};
|
use flow::{self, AFFECTS_COUNTERS, Flow, HAS_COUNTER_AFFECTING_CHILDREN, ImmutableFlowUtils};
|
||||||
use fragment::{Fragment, GeneratedContentInfo, SpecificFragmentInfo, UnscannedTextFragmentInfo};
|
use fragment::{Fragment, GeneratedContentInfo, SpecificFragmentInfo, UnscannedTextFragmentInfo};
|
||||||
use gfx::display_list::OpaqueNode;
|
use gfx::display_list::OpaqueNode;
|
||||||
use incremental::{self, RESOLVE_GENERATED_CONTENT};
|
use incremental::{RESOLVE_GENERATED_CONTENT, RestyleDamage};
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
use std::collections::{HashMap, LinkedList};
|
use std::collections::{HashMap, LinkedList};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use style::computed_values::content::ContentItem;
|
use style::computed_values::content::ContentItem;
|
||||||
use style::computed_values::{display, list_style_type};
|
use style::computed_values::{display, list_style_type};
|
||||||
|
use style::dom::TRestyleDamage;
|
||||||
use style::properties::ComputedValues;
|
use style::properties::ComputedValues;
|
||||||
use text::TextRunScanner;
|
use text::TextRunScanner;
|
||||||
use wrapper::PseudoElementType;
|
use wrapper::PseudoElementType;
|
||||||
|
@ -431,7 +432,7 @@ fn render_text(layout_context: &LayoutContext,
|
||||||
fragments.push_back(Fragment::from_opaque_node_and_style(node,
|
fragments.push_back(Fragment::from_opaque_node_and_style(node,
|
||||||
pseudo,
|
pseudo,
|
||||||
style,
|
style,
|
||||||
incremental::rebuild_and_reflow(),
|
RestyleDamage::rebuild_and_reflow(),
|
||||||
info));
|
info));
|
||||||
// FIXME(pcwalton): This should properly handle multiple marker fragments. This could happen
|
// FIXME(pcwalton): This should properly handle multiple marker fragments. This could happen
|
||||||
// due to text run splitting.
|
// due to text run splitting.
|
||||||
|
|
|
@ -6,6 +6,7 @@ use flow::{self, AFFECTS_COUNTERS, Flow, HAS_COUNTER_AFFECTING_CHILDREN, IS_ABSO
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use style::computed_values::float;
|
use style::computed_values::float;
|
||||||
|
use style::dom::TRestyleDamage;
|
||||||
use style::properties::ComputedValues;
|
use style::properties::ComputedValues;
|
||||||
|
|
||||||
bitflags! {
|
bitflags! {
|
||||||
|
@ -47,6 +48,18 @@ bitflags! {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl TRestyleDamage for RestyleDamage {
|
||||||
|
fn compute(old: &Option<Arc<ComputedValues>>, new: &ComputedValues) -> RestyleDamage { compute_damage(old, new) }
|
||||||
|
|
||||||
|
/// Returns a bitmask that represents a flow that needs to be rebuilt and reflowed.
|
||||||
|
///
|
||||||
|
/// Use this instead of `RestyleDamage::all()` because `RestyleDamage::all()` will result in
|
||||||
|
/// unnecessary sequential resolution of generated content.
|
||||||
|
fn rebuild_and_reflow() -> RestyleDamage {
|
||||||
|
REPAINT | BUBBLE_ISIZES | REFLOW_OUT_OF_FLOW | REFLOW | RECONSTRUCT_FLOW
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
impl RestyleDamage {
|
impl RestyleDamage {
|
||||||
/// Supposing a flow has the given `position` property and this damage, returns the damage that
|
/// Supposing a flow has the given `position` property and this damage, returns the damage that
|
||||||
|
@ -130,18 +143,10 @@ macro_rules! add_if_not_equal(
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
/// Returns a bitmask that represents a flow that needs to be rebuilt and reflowed.
|
|
||||||
///
|
|
||||||
/// Use this instead of `RestyleDamage::all()` because `RestyleDamage::all()` will result in
|
|
||||||
/// unnecessary sequential resolution of generated content.
|
|
||||||
pub fn rebuild_and_reflow() -> RestyleDamage {
|
|
||||||
REPAINT | BUBBLE_ISIZES | REFLOW_OUT_OF_FLOW | REFLOW | RECONSTRUCT_FLOW
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn compute_damage(old: &Option<Arc<ComputedValues>>, new: &ComputedValues) -> RestyleDamage {
|
pub fn compute_damage(old: &Option<Arc<ComputedValues>>, new: &ComputedValues) -> RestyleDamage {
|
||||||
let old: &ComputedValues =
|
let old: &ComputedValues =
|
||||||
match old.as_ref() {
|
match old.as_ref() {
|
||||||
None => return rebuild_and_reflow(),
|
None => return RestyleDamage::rebuild_and_reflow(),
|
||||||
Some(cv) => &**cv,
|
Some(cv) => &**cv,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -195,7 +200,7 @@ pub fn compute_damage(old: &Option<Arc<ComputedValues>>, new: &ComputedValues) -
|
||||||
// If the layer requirements of this flow have changed due to the value
|
// If the layer requirements of this flow have changed due to the value
|
||||||
// of the transform, then reflow is required to rebuild the layers.
|
// of the transform, then reflow is required to rebuild the layers.
|
||||||
if old.transform_requires_layer() != new.transform_requires_layer() {
|
if old.transform_requires_layer() != new.transform_requires_layer() {
|
||||||
damage.insert(rebuild_and_reflow());
|
damage.insert(RestyleDamage::rebuild_and_reflow());
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: test somehow that we checked every CSS property
|
// FIXME: test somehow that we checked every CSS property
|
||||||
|
@ -256,7 +261,7 @@ impl<'a> LayoutDamageComputation for &'a mut Flow {
|
||||||
|
|
||||||
fn reflow_entire_document(self) {
|
fn reflow_entire_document(self) {
|
||||||
let self_base = flow::mut_base(self);
|
let self_base = flow::mut_base(self);
|
||||||
self_base.restyle_damage.insert(rebuild_and_reflow());
|
self_base.restyle_damage.insert(RestyleDamage::rebuild_and_reflow());
|
||||||
self_base.restyle_damage.remove(RECONSTRUCT_FLOW);
|
self_base.restyle_damage.remove(RECONSTRUCT_FLOW);
|
||||||
for kid in self_base.children.iter_mut() {
|
for kid in self_base.children.iter_mut() {
|
||||||
kid.reflow_entire_document();
|
kid.reflow_entire_document();
|
||||||
|
|
|
@ -10,13 +10,13 @@ use css::matching::{ElementMatchMethods, MatchMethods, StyleSharingResult};
|
||||||
use flow::{PostorderFlowTraversal, PreorderFlowTraversal};
|
use flow::{PostorderFlowTraversal, PreorderFlowTraversal};
|
||||||
use flow::{self, Flow};
|
use flow::{self, Flow};
|
||||||
use gfx::display_list::OpaqueNode;
|
use gfx::display_list::OpaqueNode;
|
||||||
use incremental::{self, BUBBLE_ISIZES, REFLOW, REFLOW_OUT_OF_FLOW, REPAINT, RestyleDamage};
|
use incremental::{BUBBLE_ISIZES, REFLOW, REFLOW_OUT_OF_FLOW, REPAINT, RestyleDamage};
|
||||||
use script::layout_interface::ReflowGoal;
|
use script::layout_interface::ReflowGoal;
|
||||||
use selectors::bloom::BloomFilter;
|
use selectors::bloom::BloomFilter;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use style::context::StyleContext;
|
use style::context::StyleContext;
|
||||||
use style::dom::UnsafeNode;
|
use style::dom::{TRestyleDamage, UnsafeNode};
|
||||||
use style::matching::ApplicableDeclarations;
|
use style::matching::ApplicableDeclarations;
|
||||||
use util::opts;
|
use util::opts;
|
||||||
use util::tid::tid;
|
use util::tid::tid;
|
||||||
|
@ -209,8 +209,7 @@ fn recalc_style_at<'a, 'ln, N: LayoutNode<'ln>> (context: &'a DomTraversalContex
|
||||||
},
|
},
|
||||||
None => {
|
None => {
|
||||||
if node.has_changed() {
|
if node.has_changed() {
|
||||||
node.to_threadsafe().set_restyle_damage(
|
node.set_restyle_damage(N::ConcreteRestyleDamage::rebuild_and_reflow())
|
||||||
incremental::rebuild_and_reflow())
|
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
},
|
},
|
||||||
|
|
|
@ -132,6 +132,7 @@ impl<'ln> ServoLayoutNode<'ln> {
|
||||||
impl<'ln> TNode<'ln> for ServoLayoutNode<'ln> {
|
impl<'ln> TNode<'ln> for ServoLayoutNode<'ln> {
|
||||||
type ConcreteElement = ServoLayoutElement<'ln>;
|
type ConcreteElement = ServoLayoutElement<'ln>;
|
||||||
type ConcreteDocument = ServoLayoutDocument<'ln>;
|
type ConcreteDocument = ServoLayoutDocument<'ln>;
|
||||||
|
type ConcreteRestyleDamage = RestyleDamage;
|
||||||
|
|
||||||
fn to_unsafe(&self) -> UnsafeNode {
|
fn to_unsafe(&self) -> UnsafeNode {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -237,6 +238,14 @@ impl<'ln> TNode<'ln> for ServoLayoutNode<'ln> {
|
||||||
unsafe { self.mutate_layout_data().map(|d| transmute(d)) }
|
unsafe { self.mutate_layout_data().map(|d| transmute(d)) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn restyle_damage(self) -> RestyleDamage {
|
||||||
|
self.borrow_layout_data().unwrap().restyle_damage
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_restyle_damage(self, damage: RestyleDamage) {
|
||||||
|
self.mutate_layout_data().unwrap().restyle_damage = damage;
|
||||||
|
}
|
||||||
|
|
||||||
fn parent_node(&self) -> Option<ServoLayoutNode<'ln>> {
|
fn parent_node(&self) -> Option<ServoLayoutNode<'ln>> {
|
||||||
unsafe {
|
unsafe {
|
||||||
self.node.parent_node_ref().map(|node| self.new_with_this_lifetime(&node))
|
self.node.parent_node_ref().map(|node| self.new_with_this_lifetime(&node))
|
||||||
|
@ -714,16 +723,9 @@ pub trait ThreadSafeLayoutNode<'ln> : Clone + Copy + Sized {
|
||||||
|
|
||||||
fn is_ignorable_whitespace(&self) -> bool;
|
fn is_ignorable_whitespace(&self) -> bool;
|
||||||
|
|
||||||
/// Get the description of how to account for recent style changes.
|
fn restyle_damage(self) -> RestyleDamage;
|
||||||
/// This is a simple bitfield and fine to copy by value.
|
|
||||||
fn restyle_damage(self) -> RestyleDamage {
|
|
||||||
self.borrow_layout_data().unwrap().restyle_damage
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Set the restyle damage field.
|
fn set_restyle_damage(self, damage: RestyleDamage);
|
||||||
fn set_restyle_damage(self, damage: RestyleDamage) {
|
|
||||||
self.mutate_layout_data().unwrap().restyle_damage = damage;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the layout data flags for this node.
|
/// Returns the layout data flags for this node.
|
||||||
fn flags(self) -> LayoutDataFlags;
|
fn flags(self) -> LayoutDataFlags;
|
||||||
|
@ -909,6 +911,14 @@ impl<'ln> ThreadSafeLayoutNode<'ln> for ServoThreadSafeLayoutNode<'ln> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn restyle_damage(self) -> RestyleDamage {
|
||||||
|
self.node.restyle_damage()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_restyle_damage(self, damage: RestyleDamage) {
|
||||||
|
self.node.set_restyle_damage(damage)
|
||||||
|
}
|
||||||
|
|
||||||
fn flags(self) -> LayoutDataFlags {
|
fn flags(self) -> LayoutDataFlags {
|
||||||
unsafe {
|
unsafe {
|
||||||
(*self.node.borrow_layout_data_unchecked().unwrap()).flags
|
(*self.node.borrow_layout_data_unchecked().unwrap()).flags
|
||||||
|
|
|
@ -5,13 +5,15 @@
|
||||||
#![allow(unsafe_code)]
|
#![allow(unsafe_code)]
|
||||||
|
|
||||||
use data::PrivateStyleData;
|
use data::PrivateStyleData;
|
||||||
use properties::{PropertyDeclaration, PropertyDeclarationBlock};
|
use properties::{ComputedValues, PropertyDeclaration, PropertyDeclarationBlock};
|
||||||
use restyle_hints::{ElementSnapshot, RESTYLE_DESCENDANTS, RESTYLE_LATER_SIBLINGS, RESTYLE_SELF, RestyleHint};
|
use restyle_hints::{ElementSnapshot, RESTYLE_DESCENDANTS, RESTYLE_LATER_SIBLINGS, RESTYLE_SELF, RestyleHint};
|
||||||
use selectors::matching::DeclarationBlock;
|
use selectors::matching::DeclarationBlock;
|
||||||
use selectors::states::ElementState;
|
use selectors::states::ElementState;
|
||||||
use smallvec::VecLike;
|
use smallvec::VecLike;
|
||||||
use std::cell::{Ref, RefMut};
|
use std::cell::{Ref, RefMut};
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
use std::ops::BitOr;
|
||||||
|
use std::sync::Arc;
|
||||||
use string_cache::{Atom, Namespace};
|
use string_cache::{Atom, Namespace};
|
||||||
|
|
||||||
/// Opaque type stored in type-unsafe work queues for parallel layout.
|
/// Opaque type stored in type-unsafe work queues for parallel layout.
|
||||||
|
@ -39,10 +41,15 @@ impl OpaqueNode {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait TRestyleDamage : BitOr<Output=Self> + Copy {
|
||||||
|
fn compute(old: &Option<Arc<ComputedValues>>, new: &ComputedValues) -> Self;
|
||||||
|
fn rebuild_and_reflow() -> Self;
|
||||||
|
}
|
||||||
|
|
||||||
pub trait TNode<'ln> : Sized + Copy + Clone {
|
pub trait TNode<'ln> : Sized + Copy + Clone {
|
||||||
type ConcreteElement: TElement<'ln, ConcreteNode = Self, ConcreteDocument = Self::ConcreteDocument>;
|
type ConcreteElement: TElement<'ln, ConcreteNode = Self, ConcreteDocument = Self::ConcreteDocument>;
|
||||||
type ConcreteDocument: TDocument<'ln, ConcreteNode = Self, ConcreteElement = Self::ConcreteElement>;
|
type ConcreteDocument: TDocument<'ln, ConcreteNode = Self, ConcreteElement = Self::ConcreteElement>;
|
||||||
|
type ConcreteRestyleDamage: TRestyleDamage;
|
||||||
|
|
||||||
fn to_unsafe(&self) -> UnsafeNode;
|
fn to_unsafe(&self) -> UnsafeNode;
|
||||||
unsafe fn from_unsafe(n: &UnsafeNode) -> Self;
|
unsafe fn from_unsafe(n: &UnsafeNode) -> Self;
|
||||||
|
@ -134,6 +141,12 @@ pub trait TNode<'ln> : Sized + Copy + Clone {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn mutate_data(&self) -> Option<RefMut<PrivateStyleData>>;
|
fn mutate_data(&self) -> Option<RefMut<PrivateStyleData>>;
|
||||||
|
|
||||||
|
/// Get the description of how to account for recent style changes.
|
||||||
|
fn restyle_damage(self) -> Self::ConcreteRestyleDamage;
|
||||||
|
|
||||||
|
/// Set the restyle damage field.
|
||||||
|
fn set_restyle_damage(self, damage: Self::ConcreteRestyleDamage);
|
||||||
|
|
||||||
fn parent_node(&self) -> Option<Self>;
|
fn parent_node(&self) -> Option<Self>;
|
||||||
|
|
||||||
fn first_child(&self) -> Option<Self>;
|
fn first_child(&self) -> Option<Self>;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue