mirror of
https://github.com/servo/servo.git
synced 2025-08-13 01:15:34 +01:00
Auto merge of #16802 - emilio:slim-down-slc, r=bholley
style: Slim down SharedStyleContext, and do various other cleanups around the style crate. This slims down SharedStyleContext, in preparation for a few things. First, I would like to eventually move the stylist to the document in Servo, in order for it to hold the StyleSheetSet. Also, this gets rid of a fair amount of overhead while creating it in stylo. Fixes bug 1363245. <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/16802) <!-- Reviewable:end -->
This commit is contained in:
commit
eeb1ee9723
11 changed files with 171 additions and 141 deletions
|
@ -399,6 +399,7 @@ impl PropertyAnimation {
|
|||
//
|
||||
// TODO(emilio): Take rid of this mutex splitting SharedLayoutContex into a
|
||||
// cloneable part and a non-cloneable part..
|
||||
#[cfg(feature = "servo")]
|
||||
pub fn start_transitions_if_applicable(new_animations_sender: &Sender<Animation>,
|
||||
opaque_node: OpaqueNode,
|
||||
unsafe_node: UnsafeNode,
|
||||
|
@ -755,6 +756,7 @@ pub fn update_style_for_animation(context: &SharedStyleContext,
|
|||
}
|
||||
|
||||
/// Update the style in the node when it finishes.
|
||||
#[cfg(feature = "servo")]
|
||||
pub fn complete_expired_transitions(node: OpaqueNode, style: &mut Arc<ComputedValues>,
|
||||
context: &SharedStyleContext) -> bool {
|
||||
let had_animations_to_expire;
|
||||
|
|
|
@ -4,7 +4,8 @@
|
|||
|
||||
//! The context within which style is calculated.
|
||||
|
||||
use animation::{Animation, PropertyAnimation};
|
||||
#[cfg(feature = "servo")] use animation::Animation;
|
||||
use animation::PropertyAnimation;
|
||||
use app_units::Au;
|
||||
use bit_vec::BitVec;
|
||||
use bloom::StyleBloom;
|
||||
|
@ -17,18 +18,18 @@ use fnv::FnvHashMap;
|
|||
use font_metrics::FontMetricsProvider;
|
||||
#[cfg(feature = "gecko")] use gecko_bindings::structs;
|
||||
use matching::StyleSharingCandidateCache;
|
||||
use parking_lot::RwLock;
|
||||
#[cfg(feature = "servo")] use parking_lot::RwLock;
|
||||
#[cfg(feature = "gecko")] use properties::ComputedValues;
|
||||
use selector_parser::SnapshotMap;
|
||||
use selectors::matching::ElementSelectorFlags;
|
||||
#[cfg(feature = "servo")] use servo_config::opts;
|
||||
use shared_lock::StylesheetGuards;
|
||||
use std::collections::HashMap;
|
||||
#[cfg(not(feature = "servo"))] use std::env;
|
||||
#[cfg(feature = "servo")] use std::collections::HashMap;
|
||||
#[cfg(feature = "gecko")] use std::env;
|
||||
use std::fmt;
|
||||
use std::ops::Add;
|
||||
use std::sync::Mutex;
|
||||
use std::sync::mpsc::Sender;
|
||||
#[cfg(feature = "servo")] use std::sync::Mutex;
|
||||
#[cfg(feature = "servo")] use std::sync::mpsc::Sender;
|
||||
use stylearc::Arc;
|
||||
use stylist::Stylist;
|
||||
use thread_state;
|
||||
|
@ -37,10 +38,12 @@ use timer::Timer;
|
|||
use traversal::{DomTraversal, TraversalFlags};
|
||||
|
||||
/// This structure is used to create a local style context from a shared one.
|
||||
#[cfg(feature = "servo")]
|
||||
pub struct ThreadLocalStyleContextCreationInfo {
|
||||
new_animations_sender: Sender<Animation>,
|
||||
}
|
||||
|
||||
#[cfg(feature = "servo")]
|
||||
impl ThreadLocalStyleContextCreationInfo {
|
||||
/// Trivially constructs a `ThreadLocalStyleContextCreationInfo`.
|
||||
pub fn new(animations_sender: Sender<Animation>) -> Self {
|
||||
|
@ -106,7 +109,7 @@ impl Default for StyleSystemOptions {
|
|||
/// shared among the worker threads.
|
||||
pub struct SharedStyleContext<'a> {
|
||||
/// The CSS selector stylist.
|
||||
pub stylist: Arc<Stylist>,
|
||||
pub stylist: &'a Stylist,
|
||||
|
||||
/// Configuration options.
|
||||
pub options: StyleSystemOptions,
|
||||
|
@ -114,17 +117,8 @@ pub struct SharedStyleContext<'a> {
|
|||
/// Guards for pre-acquired locks
|
||||
pub guards: StylesheetGuards<'a>,
|
||||
|
||||
/// The animations that are currently running.
|
||||
pub running_animations: Arc<RwLock<HashMap<OpaqueNode, Vec<Animation>>>>,
|
||||
|
||||
/// The list of animations that have expired since the last style recalculation.
|
||||
pub expired_animations: Arc<RwLock<HashMap<OpaqueNode, Vec<Animation>>>>,
|
||||
|
||||
///The CSS error reporter for all CSS loaded in this layout thread
|
||||
pub error_reporter: Box<ParseErrorReporter>,
|
||||
|
||||
/// Data needed to create the thread-local style context from the shared one.
|
||||
pub local_context_creation_data: Mutex<ThreadLocalStyleContextCreationInfo>,
|
||||
pub error_reporter: &'a ParseErrorReporter,
|
||||
|
||||
/// The current timer for transitions and animations. This is needed to test
|
||||
/// them.
|
||||
|
@ -138,6 +132,19 @@ pub struct SharedStyleContext<'a> {
|
|||
|
||||
/// A map with our snapshots in order to handle restyle hints.
|
||||
pub snapshot_map: &'a SnapshotMap,
|
||||
|
||||
/// The animations that are currently running.
|
||||
#[cfg(feature = "servo")]
|
||||
pub running_animations: Arc<RwLock<HashMap<OpaqueNode, Vec<Animation>>>>,
|
||||
|
||||
/// The list of animations that have expired since the last style recalculation.
|
||||
#[cfg(feature = "servo")]
|
||||
pub expired_animations: Arc<RwLock<HashMap<OpaqueNode, Vec<Animation>>>>,
|
||||
|
||||
/// Data needed to create the thread-local style context from the shared one.
|
||||
#[cfg(feature = "servo")]
|
||||
pub local_context_creation_data: Mutex<ThreadLocalStyleContextCreationInfo>,
|
||||
|
||||
}
|
||||
|
||||
impl<'a> SharedStyleContext<'a> {
|
||||
|
@ -400,6 +407,7 @@ pub struct ThreadLocalStyleContext<E: TElement> {
|
|||
pub bloom_filter: StyleBloom<E>,
|
||||
/// A channel on which new animations that have been triggered by style
|
||||
/// recalculation can be sent.
|
||||
#[cfg(feature = "servo")]
|
||||
pub new_animations_sender: Sender<Animation>,
|
||||
/// A set of tasks to be run (on the parent thread) in sequential mode after
|
||||
/// the rest of the styling is complete. This is useful for infrequently-needed
|
||||
|
@ -421,6 +429,7 @@ pub struct ThreadLocalStyleContext<E: TElement> {
|
|||
|
||||
impl<E: TElement> ThreadLocalStyleContext<E> {
|
||||
/// Creates a new `ThreadLocalStyleContext` from a shared one.
|
||||
#[cfg(feature = "servo")]
|
||||
pub fn new(shared: &SharedStyleContext) -> Self {
|
||||
ThreadLocalStyleContext {
|
||||
style_sharing_candidate_cache: StyleSharingCandidateCache::new(),
|
||||
|
@ -434,6 +443,20 @@ impl<E: TElement> ThreadLocalStyleContext<E> {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "gecko")]
|
||||
/// Creates a new `ThreadLocalStyleContext` from a shared one.
|
||||
pub fn new(shared: &SharedStyleContext) -> Self {
|
||||
ThreadLocalStyleContext {
|
||||
style_sharing_candidate_cache: StyleSharingCandidateCache::new(),
|
||||
bloom_filter: StyleBloom::new(),
|
||||
tasks: Vec::new(),
|
||||
selector_flags: SelectorFlagsMap::new(),
|
||||
statistics: TraversalStatistics::default(),
|
||||
current_element_info: None,
|
||||
font_metrics_provider: E::FontMetricsProvider::create_from(shared),
|
||||
}
|
||||
}
|
||||
|
||||
/// Notes when the style system starts traversing an element.
|
||||
pub fn begin_element(&mut self, element: E, data: &ElementData) {
|
||||
debug_assert!(self.current_element_info.is_none());
|
||||
|
|
|
@ -18,14 +18,14 @@ use std::collections::HashMap;
|
|||
use std::sync::mpsc::{Receiver, Sender, channel};
|
||||
use stylearc::Arc;
|
||||
use stylesheet_set::StylesheetSet;
|
||||
use stylesheets::{FontFaceRule, Origin, Stylesheet};
|
||||
use stylesheets::{FontFaceRule, Origin};
|
||||
use stylist::{ExtraStyleData, Stylist};
|
||||
|
||||
/// The container for data that a Servo-backed Gecko document needs to style
|
||||
/// itself.
|
||||
pub struct PerDocumentStyleDataImpl {
|
||||
/// Rule processor.
|
||||
pub stylist: Arc<Stylist>,
|
||||
pub stylist: Stylist,
|
||||
|
||||
/// List of stylesheets, mirrored from Gecko.
|
||||
pub stylesheets: StylesheetSet,
|
||||
|
@ -60,7 +60,7 @@ impl PerDocumentStyleData {
|
|||
let (new_anims_sender, new_anims_receiver) = channel();
|
||||
|
||||
PerDocumentStyleData(AtomicRefCell::new(PerDocumentStyleDataImpl {
|
||||
stylist: Arc::new(Stylist::new(device)),
|
||||
stylist: Stylist::new(device),
|
||||
stylesheets: StylesheetSet::new(),
|
||||
new_animations_sender: new_anims_sender,
|
||||
new_animations_receiver: new_anims_receiver,
|
||||
|
@ -86,10 +86,7 @@ impl PerDocumentStyleDataImpl {
|
|||
///
|
||||
/// Implies also a stylesheet flush.
|
||||
pub fn reset_device(&mut self, guard: &SharedRwLockReadGuard) {
|
||||
{
|
||||
let mut stylist = Arc::get_mut(&mut self.stylist).unwrap();
|
||||
Arc::get_mut(&mut stylist.device).unwrap().reset();
|
||||
}
|
||||
Arc::get_mut(&mut self.stylist.device).unwrap().reset();
|
||||
self.stylesheets.force_dirty();
|
||||
self.flush_stylesheets(guard);
|
||||
}
|
||||
|
@ -100,21 +97,18 @@ impl PerDocumentStyleDataImpl {
|
|||
return;
|
||||
}
|
||||
|
||||
let mut stylist = Arc::get_mut(&mut self.stylist).unwrap();
|
||||
let mut extra_data = ExtraStyleData {
|
||||
font_faces: &mut self.font_faces,
|
||||
};
|
||||
|
||||
let author_style_disabled = self.stylesheets.author_style_disabled();
|
||||
let mut stylesheets = Vec::<Arc<Stylesheet>>::new();
|
||||
self.stylesheets.flush(&mut stylesheets);
|
||||
stylist.clear();
|
||||
stylist.rebuild(stylesheets.as_slice(),
|
||||
&StylesheetGuards::same(guard),
|
||||
/* ua_sheets = */ None,
|
||||
/* stylesheets_changed = */ true,
|
||||
author_style_disabled,
|
||||
&mut extra_data);
|
||||
self.stylist.clear();
|
||||
self.stylist.rebuild(self.stylesheets.flush(),
|
||||
&StylesheetGuards::same(guard),
|
||||
/* ua_sheets = */ None,
|
||||
/* stylesheets_changed = */ true,
|
||||
author_style_disabled,
|
||||
&mut extra_data);
|
||||
}
|
||||
|
||||
/// Get the default computed values for this document.
|
||||
|
@ -125,8 +119,7 @@ impl PerDocumentStyleDataImpl {
|
|||
/// Clear the stylist. This will be a no-op if the stylist is
|
||||
/// already cleared; the stylist handles that.
|
||||
pub fn clear_stylist(&mut self) {
|
||||
let mut stylist = Arc::get_mut(&mut self.stylist).unwrap();
|
||||
stylist.clear();
|
||||
self.stylist.clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
#![deny(missing_docs)]
|
||||
|
||||
use Atom;
|
||||
use animation::{self, Animation, PropertyAnimation};
|
||||
use atomic_refcell::AtomicRefMut;
|
||||
use bit_vec::BitVec;
|
||||
use cache::{LRUCache, LRUCacheMutIterator};
|
||||
|
@ -721,6 +720,8 @@ trait PrivateMatchMethods: TElement {
|
|||
old_values: &mut Option<Arc<ComputedValues>>,
|
||||
new_values: &mut Arc<ComputedValues>,
|
||||
_primary_style: &ComputedStyle) {
|
||||
use animation;
|
||||
|
||||
let possibly_expired_animations =
|
||||
&mut context.thread_local.current_element_info.as_mut().unwrap()
|
||||
.possibly_expired_animations;
|
||||
|
@ -806,11 +807,14 @@ trait PrivateMatchMethods: TElement {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "servo")]
|
||||
fn update_animations_for_cascade(&self,
|
||||
context: &SharedStyleContext,
|
||||
style: &mut Arc<ComputedValues>,
|
||||
possibly_expired_animations: &mut Vec<PropertyAnimation>,
|
||||
possibly_expired_animations: &mut Vec<::animation::PropertyAnimation>,
|
||||
font_metrics: &FontMetricsProvider) {
|
||||
use animation::{self, Animation};
|
||||
|
||||
// Finish any expired transitions.
|
||||
let this_opaque = self.as_node().opaque();
|
||||
animation::complete_expired_transitions(this_opaque, style, context);
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
//! A centralized set of stylesheets for a document.
|
||||
|
||||
use std::slice;
|
||||
use stylearc::Arc;
|
||||
use stylesheets::Stylesheet;
|
||||
|
||||
|
@ -14,6 +15,17 @@ pub struct StylesheetSetEntry {
|
|||
sheet: Arc<Stylesheet>,
|
||||
}
|
||||
|
||||
/// A iterator over the stylesheets of a list of entries in the StylesheetSet.
|
||||
#[derive(Clone)]
|
||||
pub struct StylesheetIterator<'a>(slice::Iter<'a, StylesheetSetEntry>);
|
||||
|
||||
impl<'a> Iterator for StylesheetIterator<'a> {
|
||||
type Item = &'a Arc<Stylesheet>;
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
self.0.next().map(|entry| &entry.sheet)
|
||||
}
|
||||
}
|
||||
|
||||
/// The set of stylesheets effective for a given document.
|
||||
pub struct StylesheetSet {
|
||||
/// The actual list of all the stylesheets that apply to the given document,
|
||||
|
@ -108,12 +120,11 @@ impl StylesheetSet {
|
|||
self.dirty
|
||||
}
|
||||
|
||||
/// Flush the current set, unmarking it as dirty.
|
||||
pub fn flush(&mut self, sheets: &mut Vec<Arc<Stylesheet>>) {
|
||||
/// Flush the current set, unmarking it as dirty, and returns an iterator
|
||||
/// over the new stylesheet list.
|
||||
pub fn flush(&mut self) -> StylesheetIterator {
|
||||
self.dirty = false;
|
||||
for entry in &self.entries {
|
||||
sheets.push(entry.sheet.clone())
|
||||
}
|
||||
StylesheetIterator(self.entries.iter())
|
||||
}
|
||||
|
||||
/// Mark the stylesheets as dirty, because something external may have
|
||||
|
|
|
@ -296,13 +296,15 @@ impl Stylist {
|
|||
/// This method resets all the style data each time the stylesheets change
|
||||
/// (which is indicated by the `stylesheets_changed` parameter), or the
|
||||
/// device is dirty, which means we need to re-evaluate media queries.
|
||||
pub fn rebuild<'a>(&mut self,
|
||||
doc_stylesheets: &[Arc<Stylesheet>],
|
||||
guards: &StylesheetGuards,
|
||||
ua_stylesheets: Option<&UserAgentStylesheets>,
|
||||
stylesheets_changed: bool,
|
||||
author_style_disabled: bool,
|
||||
extra_data: &mut ExtraStyleData<'a>) -> bool {
|
||||
pub fn rebuild<'a, 'b, I>(&mut self,
|
||||
doc_stylesheets: I,
|
||||
guards: &StylesheetGuards,
|
||||
ua_stylesheets: Option<&UserAgentStylesheets>,
|
||||
stylesheets_changed: bool,
|
||||
author_style_disabled: bool,
|
||||
extra_data: &mut ExtraStyleData<'a>) -> bool
|
||||
where I: Iterator<Item = &'b Arc<Stylesheet>> + Clone,
|
||||
{
|
||||
debug_assert!(!self.is_cleared || self.is_device_dirty);
|
||||
|
||||
self.is_cleared = false;
|
||||
|
@ -315,7 +317,7 @@ impl Stylist {
|
|||
|
||||
let cascaded_rule = ViewportRule {
|
||||
declarations: viewport::Cascade::from_stylesheets(
|
||||
doc_stylesheets, guards.author, &self.device
|
||||
doc_stylesheets.clone(), guards.author, &self.device
|
||||
).finish(),
|
||||
};
|
||||
|
||||
|
@ -345,7 +347,7 @@ impl Stylist {
|
|||
}
|
||||
|
||||
// Only use author stylesheets if author styles are enabled.
|
||||
let sheets_to_add = doc_stylesheets.iter().filter(|s| {
|
||||
let sheets_to_add = doc_stylesheets.filter(|s| {
|
||||
!author_style_disabled || s.origin != Origin::Author
|
||||
});
|
||||
|
||||
|
@ -366,13 +368,15 @@ impl Stylist {
|
|||
|
||||
/// clear the stylist and then rebuild it. Chances are, you want to use
|
||||
/// either clear() or rebuild(), with the latter done lazily, instead.
|
||||
pub fn update<'a>(&mut self,
|
||||
doc_stylesheets: &[Arc<Stylesheet>],
|
||||
guards: &StylesheetGuards,
|
||||
ua_stylesheets: Option<&UserAgentStylesheets>,
|
||||
stylesheets_changed: bool,
|
||||
author_style_disabled: bool,
|
||||
extra_data: &mut ExtraStyleData<'a>) -> bool {
|
||||
pub fn update<'a, 'b, I>(&mut self,
|
||||
doc_stylesheets: I,
|
||||
guards: &StylesheetGuards,
|
||||
ua_stylesheets: Option<&UserAgentStylesheets>,
|
||||
stylesheets_changed: bool,
|
||||
author_style_disabled: bool,
|
||||
extra_data: &mut ExtraStyleData<'a>) -> bool
|
||||
where I: Iterator<Item = &'b Arc<Stylesheet>> + Clone,
|
||||
{
|
||||
debug_assert!(!self.is_cleared || self.is_device_dirty);
|
||||
|
||||
// We have to do a dirtiness check before clearing, because if
|
||||
|
@ -385,7 +389,9 @@ impl Stylist {
|
|||
author_style_disabled, extra_data)
|
||||
}
|
||||
|
||||
fn add_stylesheet<'a>(&mut self, stylesheet: &Stylesheet, guard: &SharedRwLockReadGuard,
|
||||
fn add_stylesheet<'a>(&mut self,
|
||||
stylesheet: &Stylesheet,
|
||||
guard: &SharedRwLockReadGuard,
|
||||
extra_data: &mut ExtraStyleData<'a>) {
|
||||
if stylesheet.disabled() || !stylesheet.is_effective_for_device(&self.device, guard) {
|
||||
return;
|
||||
|
@ -711,10 +717,12 @@ impl Stylist {
|
|||
/// FIXME(emilio): The semantics of the device for Servo and Gecko are
|
||||
/// different enough we may want to unify them.
|
||||
#[cfg(feature = "servo")]
|
||||
pub fn set_device(&mut self, mut device: Device, guard: &SharedRwLockReadGuard,
|
||||
pub fn set_device(&mut self,
|
||||
mut device: Device,
|
||||
guard: &SharedRwLockReadGuard,
|
||||
stylesheets: &[Arc<Stylesheet>]) {
|
||||
let cascaded_rule = ViewportRule {
|
||||
declarations: viewport::Cascade::from_stylesheets(stylesheets, guard, &device).finish(),
|
||||
declarations: viewport::Cascade::from_stylesheets(stylesheets.iter(), guard, &device).finish(),
|
||||
};
|
||||
|
||||
self.viewport_constraints =
|
||||
|
|
|
@ -26,6 +26,7 @@ use std::iter::Enumerate;
|
|||
use std::str::Chars;
|
||||
use style_traits::{PinchZoomFactor, ToCss};
|
||||
use style_traits::viewport::{Orientation, UserZoom, ViewportConstraints, Zoom};
|
||||
use stylearc::Arc;
|
||||
use stylesheets::{Stylesheet, Origin};
|
||||
use values::computed::{Context, ToComputedValue};
|
||||
use values::specified::{NoCalcLength, LengthOrPercentageOrAuto, ViewportPercentageLength};
|
||||
|
@ -329,7 +330,6 @@ fn is_whitespace_separator_or_equals(c: &char) -> bool {
|
|||
}
|
||||
|
||||
impl Parse for ViewportRule {
|
||||
#[allow(missing_docs)]
|
||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
let parser = ViewportRuleParser { context: context };
|
||||
|
||||
|
@ -545,14 +545,15 @@ impl Cascade {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn from_stylesheets<'a, I>(stylesheets: I, guard: &SharedRwLockReadGuard,
|
||||
device: &Device) -> Self
|
||||
where I: IntoIterator,
|
||||
I::Item: AsRef<Stylesheet>,
|
||||
pub fn from_stylesheets<'a, I>(stylesheets: I,
|
||||
guard: &SharedRwLockReadGuard,
|
||||
device: &Device)
|
||||
-> Self
|
||||
where I: Iterator<Item = &'a Arc<Stylesheet>>,
|
||||
{
|
||||
let mut cascade = Self::new();
|
||||
for stylesheet in stylesheets {
|
||||
stylesheet.as_ref().effective_viewport_rules(device, guard, |rule| {
|
||||
stylesheet.effective_viewport_rules(device, guard, |rule| {
|
||||
for declaration in &rule.declarations {
|
||||
cascade.add(Cow::Borrowed(declaration))
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue