mirror of
https://github.com/servo/servo.git
synced 2025-08-01 19:50:30 +01:00
style: Split collected @font-face / @counter-style rules per origin.
This commit is contained in:
parent
1877cac477
commit
57622004ce
4 changed files with 120 additions and 47 deletions
|
@ -114,7 +114,6 @@ use servo_url::ServoUrl;
|
||||||
use std::borrow::ToOwned;
|
use std::borrow::ToOwned;
|
||||||
use std::cell::{Cell, RefCell};
|
use std::cell::{Cell, RefCell};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::marker::PhantomData;
|
|
||||||
use std::mem as std_mem;
|
use std::mem as std_mem;
|
||||||
use std::ops::{Deref, DerefMut};
|
use std::ops::{Deref, DerefMut};
|
||||||
use std::process;
|
use std::process;
|
||||||
|
@ -1207,9 +1206,7 @@ impl LayoutThread {
|
||||||
author: &author_guard,
|
author: &author_guard,
|
||||||
ua_or_user: &ua_or_user_guard,
|
ua_or_user: &ua_or_user_guard,
|
||||||
};
|
};
|
||||||
let mut extra_data = ExtraStyleData {
|
let mut extra_data = ExtraStyleData;
|
||||||
marker: PhantomData,
|
|
||||||
};
|
|
||||||
let needs_dirtying = self.stylist.update(
|
let needs_dirtying = self.stylist.update(
|
||||||
StylesheetIterator(data.document_stylesheets.iter()),
|
StylesheetIterator(data.document_stylesheets.iter()),
|
||||||
&guards,
|
&guards,
|
||||||
|
|
|
@ -4,10 +4,8 @@
|
||||||
|
|
||||||
//! Data needed to style a Gecko document.
|
//! Data needed to style a Gecko document.
|
||||||
|
|
||||||
use Atom;
|
|
||||||
use atomic_refcell::{AtomicRef, AtomicRefCell, AtomicRefMut};
|
use atomic_refcell::{AtomicRef, AtomicRefCell, AtomicRefMut};
|
||||||
use dom::TElement;
|
use dom::TElement;
|
||||||
use gecko::rules::{CounterStyleRule, FontFaceRule};
|
|
||||||
use gecko_bindings::bindings::{self, RawServoStyleSet};
|
use gecko_bindings::bindings::{self, RawServoStyleSet};
|
||||||
use gecko_bindings::structs::{ServoStyleSheet, StyleSheetInfo, ServoStyleSheetInner};
|
use gecko_bindings::structs::{ServoStyleSheet, StyleSheetInfo, ServoStyleSheetInner};
|
||||||
use gecko_bindings::structs::RawGeckoPresContextOwned;
|
use gecko_bindings::structs::RawGeckoPresContextOwned;
|
||||||
|
@ -16,11 +14,10 @@ use gecko_bindings::sugar::ownership::{HasArcFFI, HasBoxFFI, HasFFI, HasSimpleFF
|
||||||
use invalidation::media_queries::{MediaListKey, ToMediaListKey};
|
use invalidation::media_queries::{MediaListKey, ToMediaListKey};
|
||||||
use media_queries::{Device, MediaList};
|
use media_queries::{Device, MediaList};
|
||||||
use properties::ComputedValues;
|
use properties::ComputedValues;
|
||||||
use selector_map::PrecomputedHashMap;
|
|
||||||
use servo_arc::Arc;
|
use servo_arc::Arc;
|
||||||
use shared_lock::{Locked, StylesheetGuards, SharedRwLockReadGuard};
|
use shared_lock::{Locked, StylesheetGuards, SharedRwLockReadGuard};
|
||||||
use stylesheet_set::StylesheetSet;
|
use stylesheet_set::StylesheetSet;
|
||||||
use stylesheets::{Origin, StylesheetContents, StylesheetInDocument};
|
use stylesheets::{StylesheetContents, StylesheetInDocument};
|
||||||
use stylist::{ExtraStyleData, Stylist};
|
use stylist::{ExtraStyleData, Stylist};
|
||||||
|
|
||||||
/// Little wrapper to a Gecko style sheet.
|
/// Little wrapper to a Gecko style sheet.
|
||||||
|
@ -120,11 +117,8 @@ pub struct PerDocumentStyleDataImpl {
|
||||||
/// List of stylesheets, mirrored from Gecko.
|
/// List of stylesheets, mirrored from Gecko.
|
||||||
pub stylesheets: StylesheetSet<GeckoStyleSheet>,
|
pub stylesheets: StylesheetSet<GeckoStyleSheet>,
|
||||||
|
|
||||||
/// List of effective font face rules.
|
/// List of effective @font-face and @counter-style rules.
|
||||||
pub font_faces: Vec<(Arc<Locked<FontFaceRule>>, Origin)>,
|
pub extra_style_data: ExtraStyleData,
|
||||||
|
|
||||||
/// Map for effective counter style rules.
|
|
||||||
pub counter_styles: PrecomputedHashMap<Atom, Arc<Locked<CounterStyleRule>>>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The data itself is an `AtomicRefCell`, which guarantees the proper semantics
|
/// The data itself is an `AtomicRefCell`, which guarantees the proper semantics
|
||||||
|
@ -142,8 +136,7 @@ impl PerDocumentStyleData {
|
||||||
PerDocumentStyleData(AtomicRefCell::new(PerDocumentStyleDataImpl {
|
PerDocumentStyleData(AtomicRefCell::new(PerDocumentStyleDataImpl {
|
||||||
stylist: Stylist::new(device, quirks_mode.into()),
|
stylist: Stylist::new(device, quirks_mode.into()),
|
||||||
stylesheets: StylesheetSet::new(),
|
stylesheets: StylesheetSet::new(),
|
||||||
font_faces: vec![],
|
extra_style_data: Default::default(),
|
||||||
counter_styles: PrecomputedHashMap::default(),
|
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -169,11 +162,6 @@ impl PerDocumentStyleDataImpl {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut extra_data = ExtraStyleData {
|
|
||||||
font_faces: &mut self.font_faces,
|
|
||||||
counter_styles: &mut self.counter_styles,
|
|
||||||
};
|
|
||||||
|
|
||||||
let author_style_disabled = self.stylesheets.author_style_disabled();
|
let author_style_disabled = self.stylesheets.author_style_disabled();
|
||||||
self.stylist.clear();
|
self.stylist.clear();
|
||||||
let iter = self.stylesheets.flush(document_element);
|
let iter = self.stylesheets.flush(document_element);
|
||||||
|
@ -183,7 +171,7 @@ impl PerDocumentStyleDataImpl {
|
||||||
/* ua_sheets = */ None,
|
/* ua_sheets = */ None,
|
||||||
/* stylesheets_changed = */ true,
|
/* stylesheets_changed = */ true,
|
||||||
author_style_disabled,
|
author_style_disabled,
|
||||||
&mut extra_data
|
&mut self.extra_style_data,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -36,8 +36,6 @@ use servo_arc::{Arc, ArcBorrow};
|
||||||
use shared_lock::{Locked, SharedRwLockReadGuard, StylesheetGuards};
|
use shared_lock::{Locked, SharedRwLockReadGuard, StylesheetGuards};
|
||||||
use smallvec::VecLike;
|
use smallvec::VecLike;
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
#[cfg(feature = "servo")]
|
|
||||||
use std::marker::PhantomData;
|
|
||||||
use style_traits::viewport::ViewportConstraints;
|
use style_traits::viewport::ViewportConstraints;
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
use stylesheets::{CounterStyleRule, FontFaceRule};
|
use stylesheets::{CounterStyleRule, FontFaceRule};
|
||||||
|
@ -112,27 +110,71 @@ pub struct Stylist {
|
||||||
num_rebuilds: usize,
|
num_rebuilds: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This struct holds data which user of Stylist may want to extract
|
/// This struct holds data which users of Stylist may want to extract
|
||||||
/// from stylesheets which can be done at the same time as updating.
|
/// from stylesheets which can be done at the same time as updating.
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
pub struct ExtraStyleData<'a> {
|
#[derive(Default)]
|
||||||
|
pub struct ExtraStyleData {
|
||||||
|
/// Extra data from user agent stylesheets
|
||||||
|
user_agent: PerOriginExtraStyleData,
|
||||||
|
/// Extra data from author stylesheets
|
||||||
|
author: PerOriginExtraStyleData,
|
||||||
|
/// Extra data from user stylesheets
|
||||||
|
user: PerOriginExtraStyleData,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// This struct holds data which users of Stylist may want to extract
|
||||||
|
/// from stylesheets which can be done at the same time as updating.
|
||||||
|
#[cfg(feature = "gecko")]
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct PerOriginExtraStyleData {
|
||||||
/// A list of effective font-face rules and their origin.
|
/// A list of effective font-face rules and their origin.
|
||||||
pub font_faces: &'a mut Vec<(Arc<Locked<FontFaceRule>>, Origin)>,
|
pub font_faces: Vec<Arc<Locked<FontFaceRule>>>,
|
||||||
/// A map of effective counter-style rules.
|
/// A map of effective counter-style rules.
|
||||||
pub counter_styles: &'a mut PrecomputedHashMap<Atom, Arc<Locked<CounterStyleRule>>>,
|
pub counter_styles: PrecomputedHashMap<Atom, Arc<Locked<CounterStyleRule>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
impl<'a> ExtraStyleData<'a> {
|
impl ExtraStyleData {
|
||||||
/// Clear the internal data.
|
/// Clear the internal data.
|
||||||
|
pub fn clear(&mut self) {
|
||||||
|
self.user_agent.clear();
|
||||||
|
self.author.clear();
|
||||||
|
self.user.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a reference to the per-origin extra style data for
|
||||||
|
/// the specified origin.
|
||||||
|
#[inline]
|
||||||
|
pub fn borrow_mut_for_origin(&mut self, origin: &Origin) -> &mut PerOriginExtraStyleData {
|
||||||
|
match *origin {
|
||||||
|
Origin::UserAgent => &mut self.user_agent,
|
||||||
|
Origin::Author => &mut self.author,
|
||||||
|
Origin::User => &mut self.user,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Iterates over the per-origin extra style data, from highest level (user)
|
||||||
|
/// to lowest (user agent).
|
||||||
|
pub fn iter_origins(&self) -> ExtraStyleDataIter {
|
||||||
|
ExtraStyleDataIter {
|
||||||
|
extra_style_data: &self,
|
||||||
|
cur: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "gecko")]
|
||||||
|
impl PerOriginExtraStyleData {
|
||||||
|
/// Clears the stored @font-face and @counter-style rules.
|
||||||
fn clear(&mut self) {
|
fn clear(&mut self) {
|
||||||
self.font_faces.clear();
|
self.font_faces.clear();
|
||||||
self.counter_styles.clear();
|
self.counter_styles.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add the given @font-face rule.
|
/// Add the given @font-face rule.
|
||||||
fn add_font_face(&mut self, rule: &Arc<Locked<FontFaceRule>>, origin: Origin) {
|
fn add_font_face(&mut self, rule: &Arc<Locked<FontFaceRule>>) {
|
||||||
self.font_faces.push((rule.clone(), origin));
|
self.font_faces.push(rule.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add the given @counter-style rule.
|
/// Add the given @counter-style rule.
|
||||||
|
@ -145,12 +187,10 @@ impl<'a> ExtraStyleData<'a> {
|
||||||
|
|
||||||
#[allow(missing_docs)]
|
#[allow(missing_docs)]
|
||||||
#[cfg(feature = "servo")]
|
#[cfg(feature = "servo")]
|
||||||
pub struct ExtraStyleData<'a> {
|
pub struct ExtraStyleData;
|
||||||
pub marker: PhantomData<&'a usize>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "servo")]
|
#[cfg(feature = "servo")]
|
||||||
impl<'a> ExtraStyleData<'a> {
|
impl ExtraStyleData {
|
||||||
fn clear(&mut self) {}
|
fn clear(&mut self) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -277,17 +317,17 @@ impl Stylist {
|
||||||
/// This method resets all the style data each time the stylesheets change
|
/// This method resets all the style data each time the stylesheets change
|
||||||
/// (which is indicated by the `stylesheets_changed` parameter), or the
|
/// (which is indicated by the `stylesheets_changed` parameter), or the
|
||||||
/// device is dirty, which means we need to re-evaluate media queries.
|
/// device is dirty, which means we need to re-evaluate media queries.
|
||||||
pub fn rebuild<'a, 'b, I, S>(
|
pub fn rebuild<'a, I, S>(
|
||||||
&mut self,
|
&mut self,
|
||||||
doc_stylesheets: I,
|
doc_stylesheets: I,
|
||||||
guards: &StylesheetGuards,
|
guards: &StylesheetGuards,
|
||||||
ua_stylesheets: Option<&UserAgentStylesheets>,
|
ua_stylesheets: Option<&UserAgentStylesheets>,
|
||||||
stylesheets_changed: bool,
|
stylesheets_changed: bool,
|
||||||
author_style_disabled: bool,
|
author_style_disabled: bool,
|
||||||
extra_data: &mut ExtraStyleData<'a>
|
extra_data: &mut ExtraStyleData
|
||||||
) -> bool
|
) -> bool
|
||||||
where
|
where
|
||||||
I: Iterator<Item = &'b S> + Clone,
|
I: Iterator<Item = &'a S> + Clone,
|
||||||
S: StylesheetInDocument + ToMediaListKey + 'static,
|
S: StylesheetInDocument + ToMediaListKey + 'static,
|
||||||
{
|
{
|
||||||
debug_assert!(!self.is_cleared || self.is_device_dirty);
|
debug_assert!(!self.is_cleared || self.is_device_dirty);
|
||||||
|
@ -357,17 +397,17 @@ impl Stylist {
|
||||||
|
|
||||||
/// clear the stylist and then rebuild it. Chances are, you want to use
|
/// clear the stylist and then rebuild it. Chances are, you want to use
|
||||||
/// either clear() or rebuild(), with the latter done lazily, instead.
|
/// either clear() or rebuild(), with the latter done lazily, instead.
|
||||||
pub fn update<'a, 'b, I, S>(
|
pub fn update<'a, I, S>(
|
||||||
&mut self,
|
&mut self,
|
||||||
doc_stylesheets: I,
|
doc_stylesheets: I,
|
||||||
guards: &StylesheetGuards,
|
guards: &StylesheetGuards,
|
||||||
ua_stylesheets: Option<&UserAgentStylesheets>,
|
ua_stylesheets: Option<&UserAgentStylesheets>,
|
||||||
stylesheets_changed: bool,
|
stylesheets_changed: bool,
|
||||||
author_style_disabled: bool,
|
author_style_disabled: bool,
|
||||||
extra_data: &mut ExtraStyleData<'a>
|
extra_data: &mut ExtraStyleData
|
||||||
) -> bool
|
) -> bool
|
||||||
where
|
where
|
||||||
I: Iterator<Item = &'b S> + Clone,
|
I: Iterator<Item = &'a S> + Clone,
|
||||||
S: StylesheetInDocument + ToMediaListKey + 'static,
|
S: StylesheetInDocument + ToMediaListKey + 'static,
|
||||||
{
|
{
|
||||||
debug_assert!(!self.is_cleared || self.is_device_dirty);
|
debug_assert!(!self.is_cleared || self.is_device_dirty);
|
||||||
|
@ -382,11 +422,11 @@ impl Stylist {
|
||||||
author_style_disabled, extra_data)
|
author_style_disabled, extra_data)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_stylesheet<'a, S>(
|
fn add_stylesheet<S>(
|
||||||
&mut self,
|
&mut self,
|
||||||
stylesheet: &S,
|
stylesheet: &S,
|
||||||
guard: &SharedRwLockReadGuard,
|
guard: &SharedRwLockReadGuard,
|
||||||
_extra_data: &mut ExtraStyleData<'a>
|
_extra_data: &mut ExtraStyleData
|
||||||
)
|
)
|
||||||
where
|
where
|
||||||
S: StylesheetInDocument + ToMediaListKey + 'static,
|
S: StylesheetInDocument + ToMediaListKey + 'static,
|
||||||
|
@ -506,11 +546,15 @@ impl Stylist {
|
||||||
}
|
}
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
CssRule::FontFace(ref rule) => {
|
CssRule::FontFace(ref rule) => {
|
||||||
_extra_data.add_font_face(&rule, origin);
|
_extra_data
|
||||||
|
.borrow_mut_for_origin(&origin)
|
||||||
|
.add_font_face(&rule);
|
||||||
}
|
}
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
CssRule::CounterStyle(ref rule) => {
|
CssRule::CounterStyle(ref rule) => {
|
||||||
_extra_data.add_counter_style(guard, &rule);
|
_extra_data
|
||||||
|
.borrow_mut_for_origin(&origin)
|
||||||
|
.add_counter_style(guard, &rule);
|
||||||
}
|
}
|
||||||
// We don't care about any other rule.
|
// We don't care about any other rule.
|
||||||
_ => {}
|
_ => {}
|
||||||
|
@ -1628,6 +1672,33 @@ impl<'a> Iterator for CascadeDataIter<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Iterator over `PerOriginExtraStyleData`, from highest level (user) to lowest
|
||||||
|
/// (user agent).
|
||||||
|
///
|
||||||
|
/// We rely on this specific order for correctly looking up the @font-face
|
||||||
|
/// and @counter-style rules.
|
||||||
|
#[cfg(feature = "gecko")]
|
||||||
|
pub struct ExtraStyleDataIter<'a> {
|
||||||
|
extra_style_data: &'a ExtraStyleData,
|
||||||
|
cur: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "gecko")]
|
||||||
|
impl<'a> Iterator for ExtraStyleDataIter<'a> {
|
||||||
|
type Item = (&'a PerOriginExtraStyleData, Origin);
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<(&'a PerOriginExtraStyleData, Origin)> {
|
||||||
|
let result = match self.cur {
|
||||||
|
0 => (&self.extra_style_data.user, Origin::User),
|
||||||
|
1 => (&self.extra_style_data.author, Origin::Author),
|
||||||
|
2 => (&self.extra_style_data.user_agent, Origin::UserAgent),
|
||||||
|
_ => return None,
|
||||||
|
};
|
||||||
|
self.cur += 1;
|
||||||
|
Some(result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Data resulting from performing the CSS cascade that is specific to a given
|
/// Data resulting from performing the CSS cascade that is specific to a given
|
||||||
/// origin.
|
/// origin.
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
|
|
|
@ -10,6 +10,7 @@ use selectors::matching::{MatchingContext, MatchingMode, matches_selector};
|
||||||
use servo_arc::{Arc, ArcBorrow, RawOffsetArc};
|
use servo_arc::{Arc, ArcBorrow, RawOffsetArc};
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::fmt::Write;
|
use std::fmt::Write;
|
||||||
|
use std::iter;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
use style::context::{CascadeInputs, QuirksMode, SharedStyleContext, StyleContext};
|
use style::context::{CascadeInputs, QuirksMode, SharedStyleContext, StyleContext};
|
||||||
use style::context::ThreadLocalStyleContext;
|
use style::context::ThreadLocalStyleContext;
|
||||||
|
@ -3422,8 +3423,17 @@ pub extern "C" fn Servo_StyleSet_GetFontFaceRules(raw_data: RawServoStyleSetBorr
|
||||||
let global_style_data = &*GLOBAL_STYLE_DATA;
|
let global_style_data = &*GLOBAL_STYLE_DATA;
|
||||||
let guard = global_style_data.shared_lock.read();
|
let guard = global_style_data.shared_lock.read();
|
||||||
|
|
||||||
unsafe { rules.set_len(data.font_faces.len() as u32) };
|
let len: u32 = data.extra_style_data
|
||||||
for (src, dest) in data.font_faces.iter().zip(rules.iter_mut()) {
|
.iter_origins()
|
||||||
|
.map(|(d, _)| d.font_faces.len() as u32)
|
||||||
|
.sum();
|
||||||
|
|
||||||
|
let font_face_iter = data.extra_style_data
|
||||||
|
.iter_origins()
|
||||||
|
.flat_map(|(d, o)| d.font_faces.iter().zip(iter::repeat(o)));
|
||||||
|
|
||||||
|
unsafe { rules.set_len(len) };
|
||||||
|
for (src, dest) in font_face_iter.zip(rules.iter_mut()) {
|
||||||
dest.mRule = src.0.read_with(&guard).clone().forget();
|
dest.mRule = src.0.read_with(&guard).clone().forget();
|
||||||
dest.mSheetType = src.1.into();
|
dest.mSheetType = src.1.into();
|
||||||
}
|
}
|
||||||
|
@ -3433,8 +3443,15 @@ pub extern "C" fn Servo_StyleSet_GetFontFaceRules(raw_data: RawServoStyleSetBorr
|
||||||
pub extern "C" fn Servo_StyleSet_GetCounterStyleRule(raw_data: RawServoStyleSetBorrowed,
|
pub extern "C" fn Servo_StyleSet_GetCounterStyleRule(raw_data: RawServoStyleSetBorrowed,
|
||||||
name: *mut nsIAtom) -> *mut nsCSSCounterStyleRule {
|
name: *mut nsIAtom) -> *mut nsCSSCounterStyleRule {
|
||||||
let data = PerDocumentStyleData::from_ffi(raw_data).borrow();
|
let data = PerDocumentStyleData::from_ffi(raw_data).borrow();
|
||||||
|
let extra_data = &data.extra_style_data;
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
Atom::with(name, |name| data.counter_styles.get(name))
|
Atom::with(name, |name| {
|
||||||
|
extra_data
|
||||||
|
.iter_origins()
|
||||||
|
.filter_map(|(d, _)| d.counter_styles.get(name))
|
||||||
|
.next()
|
||||||
|
})
|
||||||
}.map(|rule| {
|
}.map(|rule| {
|
||||||
let global_style_data = &*GLOBAL_STYLE_DATA;
|
let global_style_data = &*GLOBAL_STYLE_DATA;
|
||||||
let guard = global_style_data.shared_lock.read();
|
let guard = global_style_data.shared_lock.read();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue