mirror of
https://github.com/servo/servo.git
synced 2025-08-12 00:45:33 +01:00
Make Restyle tracking more granular.
The primary idea of this patch is to ditch the rigid enum of Previous/Current styles, and replace it with a series of indicators for the various types of work that needs to be performed (expanding snapshots, rematching, recascading, and damage processing). This loses us a little bit of sanity checking (since the up-to-date-ness of our style is no longer baked into the type system), but gives us a lot more flexibility that we'll need going forward (especially when we separate matching from cascading). We also eliminate get_styling_mode in favor of a method on the traversal. This patch does a few other things as ridealongs: * Temporarily eliminates the handling for transfering ownership of styles to the frame. We'll need this again at some point, but for now it's causing too much complexity for a half-implemented feature. * Ditches TRestyleDamage, which is no longer necessary post-crate-merge, and is a constant source of compilation failures from either needing to be imported or being unnecessarily imported (which varies between gecko and servo). * Expands Snapshots for the traversal root, which was missing before. * Fixes up the skip_root stuff to avoid visiting the skipped root. * Unifies parallel traversal and avoids spawning for a single work item. * Adds an explicit pre_traverse step do any pre-processing and determine whether we need to traverse at all. MozReview-Commit-ID: IKhLAkAigXE
This commit is contained in:
parent
4cb3404c09
commit
80460cc549
27 changed files with 502 additions and 474 deletions
|
@ -8,17 +8,15 @@
|
|||
|
||||
use {Atom, Namespace, LocalName};
|
||||
use atomic_refcell::{AtomicRef, AtomicRefCell, AtomicRefMut};
|
||||
use data::{ElementStyles, ElementData};
|
||||
use data::ElementData;
|
||||
use element_state::ElementState;
|
||||
use parking_lot::RwLock;
|
||||
use properties::{ComputedValues, PropertyDeclarationBlock};
|
||||
use selector_parser::{ElementExt, PseudoElement, RestyleDamage};
|
||||
use selector_parser::{ElementExt, PreExistingComputedValues, PseudoElement};
|
||||
use sink::Push;
|
||||
use std::fmt::Debug;
|
||||
use std::ops::{BitOr, BitOrAssign};
|
||||
use std::sync::Arc;
|
||||
use stylist::ApplicableDeclarationBlock;
|
||||
use util::opts;
|
||||
|
||||
pub use style_traits::UnsafeNode;
|
||||
|
||||
|
@ -43,42 +41,6 @@ impl OpaqueNode {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
pub enum StylingMode {
|
||||
/// The node has never been styled before, and needs a full style computation.
|
||||
Initial,
|
||||
/// The node has been styled before, but needs some amount of recomputation.
|
||||
Restyle,
|
||||
/// The node does not need any style processing, but one or more of its
|
||||
/// descendants do.
|
||||
Traverse,
|
||||
/// No nodes in this subtree require style processing.
|
||||
Stop,
|
||||
}
|
||||
|
||||
pub trait TRestyleDamage : BitOr<Output=Self> + BitOrAssign + Copy + Debug + PartialEq {
|
||||
/// The source for our current computed values in the cascade. This is a
|
||||
/// ComputedValues in Servo and a StyleContext in Gecko.
|
||||
///
|
||||
/// This is needed because Gecko has a few optimisations for the calculation
|
||||
/// of the difference depending on which values have been used during
|
||||
/// layout.
|
||||
///
|
||||
/// This should be obtained via TNode::existing_style_for_restyle_damage
|
||||
type PreExistingComputedValues;
|
||||
|
||||
fn compute(old: &Self::PreExistingComputedValues,
|
||||
new: &Arc<ComputedValues>) -> Self;
|
||||
|
||||
fn empty() -> Self;
|
||||
|
||||
fn rebuild_and_reflow() -> Self;
|
||||
|
||||
fn is_empty(&self) -> bool {
|
||||
*self == Self::empty()
|
||||
}
|
||||
}
|
||||
|
||||
/// Simple trait to provide basic information about the type of an element.
|
||||
///
|
||||
/// We avoid exposing the full type id, since computing it in the general case
|
||||
|
@ -174,7 +136,7 @@ pub trait TElement : PartialEq + Debug + Sized + Copy + Clone + ElementExt + Pre
|
|||
fn existing_style_for_restyle_damage<'a>(&'a self,
|
||||
current_computed_values: Option<&'a Arc<ComputedValues>>,
|
||||
pseudo: Option<&PseudoElement>)
|
||||
-> Option<&'a <RestyleDamage as TRestyleDamage>::PreExistingComputedValues>;
|
||||
-> Option<&'a PreExistingComputedValues>;
|
||||
|
||||
/// Returns true if this element may have a descendant needing style processing.
|
||||
///
|
||||
|
@ -201,60 +163,11 @@ pub trait TElement : PartialEq + Debug + Sized + Copy + Clone + ElementExt + Pre
|
|||
/// traversal. Returns the number of children left to process.
|
||||
fn did_process_child(&self) -> isize;
|
||||
|
||||
/// Returns true if this element's current style is display:none. Only valid
|
||||
/// to call after styling.
|
||||
/// Returns true if this element's style is display:none.
|
||||
fn is_display_none(&self) -> bool {
|
||||
self.borrow_data().unwrap().current_styles().is_display_none()
|
||||
}
|
||||
|
||||
/// Returns true if this node has a styled layout frame that owns the style.
|
||||
fn frame_has_style(&self) -> bool { false }
|
||||
|
||||
/// Returns the styles from the layout frame that owns them, if any.
|
||||
///
|
||||
/// FIXME(bholley): Once we start dropping ElementData from nodes when
|
||||
/// creating frames, we'll want to teach this method to actually get
|
||||
/// style data from the frame.
|
||||
fn get_styles_from_frame(&self) -> Option<ElementStyles> { None }
|
||||
|
||||
/// Returns the styling mode for this node. This is only valid to call before
|
||||
/// and during restyling, before finish_styling is invoked.
|
||||
///
|
||||
/// See the comments around StylingMode.
|
||||
fn styling_mode(&self) -> StylingMode {
|
||||
use self::StylingMode::*;
|
||||
|
||||
// Non-incremental layout impersonates Initial.
|
||||
if opts::get().nonincremental_layout {
|
||||
return Initial;
|
||||
}
|
||||
|
||||
// Compute the default result if this node doesn't require processing.
|
||||
let mode_for_descendants = if self.has_dirty_descendants() {
|
||||
Traverse
|
||||
} else {
|
||||
Stop
|
||||
};
|
||||
|
||||
match self.borrow_data() {
|
||||
// No element data, no style on the frame.
|
||||
None if !self.frame_has_style() => Initial,
|
||||
// No element data, style on the frame.
|
||||
None => mode_for_descendants,
|
||||
// We have element data. Decide below.
|
||||
Some(d) => match *d {
|
||||
ElementData::Restyle(_) => Restyle,
|
||||
ElementData::Persistent(_) => mode_for_descendants,
|
||||
ElementData::Initial(None) => Initial,
|
||||
// We previously computed the initial style for this element
|
||||
// and then never consumed it. This is arguably a bug, since
|
||||
// it means we either styled an element unnecessarily, or missed
|
||||
// an opportunity to coalesce style traversals. However, this
|
||||
// happens now for various reasons, so we just let it slide and
|
||||
// treat it as persistent for now.
|
||||
ElementData::Initial(Some(_)) => mode_for_descendants,
|
||||
},
|
||||
}
|
||||
let data = self.borrow_data().unwrap();
|
||||
debug_assert!(data.has_current_styles());
|
||||
data.styles().is_display_none()
|
||||
}
|
||||
|
||||
/// Gets a reference to the ElementData container.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue