mirror of
https://github.com/servo/servo.git
synced 2025-08-02 04:00:32 +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::cell::{Cell, RefCell};
|
||||
use std::collections::HashMap;
|
||||
use std::marker::PhantomData;
|
||||
use std::mem as std_mem;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
use std::process;
|
||||
|
@ -1207,9 +1206,7 @@ impl LayoutThread {
|
|||
author: &author_guard,
|
||||
ua_or_user: &ua_or_user_guard,
|
||||
};
|
||||
let mut extra_data = ExtraStyleData {
|
||||
marker: PhantomData,
|
||||
};
|
||||
let mut extra_data = ExtraStyleData;
|
||||
let needs_dirtying = self.stylist.update(
|
||||
StylesheetIterator(data.document_stylesheets.iter()),
|
||||
&guards,
|
||||
|
|
|
@ -4,10 +4,8 @@
|
|||
|
||||
//! Data needed to style a Gecko document.
|
||||
|
||||
use Atom;
|
||||
use atomic_refcell::{AtomicRef, AtomicRefCell, AtomicRefMut};
|
||||
use dom::TElement;
|
||||
use gecko::rules::{CounterStyleRule, FontFaceRule};
|
||||
use gecko_bindings::bindings::{self, RawServoStyleSet};
|
||||
use gecko_bindings::structs::{ServoStyleSheet, StyleSheetInfo, ServoStyleSheetInner};
|
||||
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 media_queries::{Device, MediaList};
|
||||
use properties::ComputedValues;
|
||||
use selector_map::PrecomputedHashMap;
|
||||
use servo_arc::Arc;
|
||||
use shared_lock::{Locked, StylesheetGuards, SharedRwLockReadGuard};
|
||||
use stylesheet_set::StylesheetSet;
|
||||
use stylesheets::{Origin, StylesheetContents, StylesheetInDocument};
|
||||
use stylesheets::{StylesheetContents, StylesheetInDocument};
|
||||
use stylist::{ExtraStyleData, Stylist};
|
||||
|
||||
/// Little wrapper to a Gecko style sheet.
|
||||
|
@ -120,11 +117,8 @@ pub struct PerDocumentStyleDataImpl {
|
|||
/// List of stylesheets, mirrored from Gecko.
|
||||
pub stylesheets: StylesheetSet<GeckoStyleSheet>,
|
||||
|
||||
/// List of effective font face rules.
|
||||
pub font_faces: Vec<(Arc<Locked<FontFaceRule>>, Origin)>,
|
||||
|
||||
/// Map for effective counter style rules.
|
||||
pub counter_styles: PrecomputedHashMap<Atom, Arc<Locked<CounterStyleRule>>>,
|
||||
/// List of effective @font-face and @counter-style rules.
|
||||
pub extra_style_data: ExtraStyleData,
|
||||
}
|
||||
|
||||
/// The data itself is an `AtomicRefCell`, which guarantees the proper semantics
|
||||
|
@ -142,8 +136,7 @@ impl PerDocumentStyleData {
|
|||
PerDocumentStyleData(AtomicRefCell::new(PerDocumentStyleDataImpl {
|
||||
stylist: Stylist::new(device, quirks_mode.into()),
|
||||
stylesheets: StylesheetSet::new(),
|
||||
font_faces: vec![],
|
||||
counter_styles: PrecomputedHashMap::default(),
|
||||
extra_style_data: Default::default(),
|
||||
}))
|
||||
}
|
||||
|
||||
|
@ -169,11 +162,6 @@ impl PerDocumentStyleDataImpl {
|
|||
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();
|
||||
self.stylist.clear();
|
||||
let iter = self.stylesheets.flush(document_element);
|
||||
|
@ -183,7 +171,7 @@ impl PerDocumentStyleDataImpl {
|
|||
/* ua_sheets = */ None,
|
||||
/* stylesheets_changed = */ true,
|
||||
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 smallvec::VecLike;
|
||||
use std::fmt::Debug;
|
||||
#[cfg(feature = "servo")]
|
||||
use std::marker::PhantomData;
|
||||
use style_traits::viewport::ViewportConstraints;
|
||||
#[cfg(feature = "gecko")]
|
||||
use stylesheets::{CounterStyleRule, FontFaceRule};
|
||||
|
@ -112,27 +110,71 @@ pub struct Stylist {
|
|||
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.
|
||||
#[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.
|
||||
pub font_faces: &'a mut Vec<(Arc<Locked<FontFaceRule>>, Origin)>,
|
||||
pub font_faces: Vec<Arc<Locked<FontFaceRule>>>,
|
||||
/// 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")]
|
||||
impl<'a> ExtraStyleData<'a> {
|
||||
impl ExtraStyleData {
|
||||
/// 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) {
|
||||
self.font_faces.clear();
|
||||
self.counter_styles.clear();
|
||||
}
|
||||
|
||||
/// Add the given @font-face rule.
|
||||
fn add_font_face(&mut self, rule: &Arc<Locked<FontFaceRule>>, origin: Origin) {
|
||||
self.font_faces.push((rule.clone(), origin));
|
||||
fn add_font_face(&mut self, rule: &Arc<Locked<FontFaceRule>>) {
|
||||
self.font_faces.push(rule.clone());
|
||||
}
|
||||
|
||||
/// Add the given @counter-style rule.
|
||||
|
@ -145,12 +187,10 @@ impl<'a> ExtraStyleData<'a> {
|
|||
|
||||
#[allow(missing_docs)]
|
||||
#[cfg(feature = "servo")]
|
||||
pub struct ExtraStyleData<'a> {
|
||||
pub marker: PhantomData<&'a usize>,
|
||||
}
|
||||
pub struct ExtraStyleData;
|
||||
|
||||
#[cfg(feature = "servo")]
|
||||
impl<'a> ExtraStyleData<'a> {
|
||||
impl ExtraStyleData {
|
||||
fn clear(&mut self) {}
|
||||
}
|
||||
|
||||
|
@ -277,17 +317,17 @@ 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, 'b, I, S>(
|
||||
pub fn rebuild<'a, I, S>(
|
||||
&mut self,
|
||||
doc_stylesheets: I,
|
||||
guards: &StylesheetGuards,
|
||||
ua_stylesheets: Option<&UserAgentStylesheets>,
|
||||
stylesheets_changed: bool,
|
||||
author_style_disabled: bool,
|
||||
extra_data: &mut ExtraStyleData<'a>
|
||||
extra_data: &mut ExtraStyleData
|
||||
) -> bool
|
||||
where
|
||||
I: Iterator<Item = &'b S> + Clone,
|
||||
I: Iterator<Item = &'a S> + Clone,
|
||||
S: StylesheetInDocument + ToMediaListKey + 'static,
|
||||
{
|
||||
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
|
||||
/// 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,
|
||||
doc_stylesheets: I,
|
||||
guards: &StylesheetGuards,
|
||||
ua_stylesheets: Option<&UserAgentStylesheets>,
|
||||
stylesheets_changed: bool,
|
||||
author_style_disabled: bool,
|
||||
extra_data: &mut ExtraStyleData<'a>
|
||||
extra_data: &mut ExtraStyleData
|
||||
) -> bool
|
||||
where
|
||||
I: Iterator<Item = &'b S> + Clone,
|
||||
I: Iterator<Item = &'a S> + Clone,
|
||||
S: StylesheetInDocument + ToMediaListKey + 'static,
|
||||
{
|
||||
debug_assert!(!self.is_cleared || self.is_device_dirty);
|
||||
|
@ -382,11 +422,11 @@ impl Stylist {
|
|||
author_style_disabled, extra_data)
|
||||
}
|
||||
|
||||
fn add_stylesheet<'a, S>(
|
||||
fn add_stylesheet<S>(
|
||||
&mut self,
|
||||
stylesheet: &S,
|
||||
guard: &SharedRwLockReadGuard,
|
||||
_extra_data: &mut ExtraStyleData<'a>
|
||||
_extra_data: &mut ExtraStyleData
|
||||
)
|
||||
where
|
||||
S: StylesheetInDocument + ToMediaListKey + 'static,
|
||||
|
@ -506,11 +546,15 @@ impl Stylist {
|
|||
}
|
||||
#[cfg(feature = "gecko")]
|
||||
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")]
|
||||
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.
|
||||
_ => {}
|
||||
|
@ -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
|
||||
/// origin.
|
||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||
|
|
|
@ -10,6 +10,7 @@ use selectors::matching::{MatchingContext, MatchingMode, matches_selector};
|
|||
use servo_arc::{Arc, ArcBorrow, RawOffsetArc};
|
||||
use std::env;
|
||||
use std::fmt::Write;
|
||||
use std::iter;
|
||||
use std::ptr;
|
||||
use style::context::{CascadeInputs, QuirksMode, SharedStyleContext, StyleContext};
|
||||
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 guard = global_style_data.shared_lock.read();
|
||||
|
||||
unsafe { rules.set_len(data.font_faces.len() as u32) };
|
||||
for (src, dest) in data.font_faces.iter().zip(rules.iter_mut()) {
|
||||
let len: u32 = data.extra_style_data
|
||||
.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.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,
|
||||
name: *mut nsIAtom) -> *mut nsCSSCounterStyleRule {
|
||||
let data = PerDocumentStyleData::from_ffi(raw_data).borrow();
|
||||
let extra_data = &data.extra_style_data;
|
||||
|
||||
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| {
|
||||
let global_style_data = &*GLOBAL_STYLE_DATA;
|
||||
let guard = global_style_data.shared_lock.read();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue