mirror of
https://github.com/servo/servo.git
synced 2025-07-23 15:23:42 +01:00
Record effective @font-face rules when updating stylist.
This commit is contained in:
parent
0d96c7997f
commit
01e986f2e6
3 changed files with 71 additions and 17 deletions
|
@ -98,6 +98,7 @@ use servo_url::ServoUrl;
|
||||||
use std::borrow::ToOwned;
|
use std::borrow::ToOwned;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::hash::BuildHasherDefault;
|
use std::hash::BuildHasherDefault;
|
||||||
|
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;
|
||||||
|
@ -116,7 +117,7 @@ use style::parser::ParserContextExtraData;
|
||||||
use style::servo::restyle_damage::{REFLOW, REFLOW_OUT_OF_FLOW, REPAINT, REPOSITION, STORE_OVERFLOW};
|
use style::servo::restyle_damage::{REFLOW, REFLOW_OUT_OF_FLOW, REPAINT, REPOSITION, STORE_OVERFLOW};
|
||||||
use style::shared_lock::{SharedRwLock, SharedRwLockReadGuard, StylesheetGuards};
|
use style::shared_lock::{SharedRwLock, SharedRwLockReadGuard, StylesheetGuards};
|
||||||
use style::stylesheets::{Origin, Stylesheet, UserAgentStylesheets};
|
use style::stylesheets::{Origin, Stylesheet, UserAgentStylesheets};
|
||||||
use style::stylist::Stylist;
|
use style::stylist::{ExtraStyleData, Stylist};
|
||||||
use style::thread_state;
|
use style::thread_state;
|
||||||
use style::timer::Timer;
|
use style::timer::Timer;
|
||||||
use style::traversal::{DomTraversal, TraversalDriver, TraversalFlags};
|
use style::traversal::{DomTraversal, TraversalDriver, TraversalFlags};
|
||||||
|
@ -1078,11 +1079,15 @@ 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 {
|
||||||
|
marker: PhantomData,
|
||||||
|
};
|
||||||
let needs_dirtying = Arc::get_mut(&mut rw_data.stylist).unwrap().update(
|
let needs_dirtying = Arc::get_mut(&mut rw_data.stylist).unwrap().update(
|
||||||
&data.document_stylesheets,
|
&data.document_stylesheets,
|
||||||
&guards,
|
&guards,
|
||||||
Some(ua_stylesheets),
|
Some(ua_stylesheets),
|
||||||
data.stylesheets_changed);
|
data.stylesheets_changed,
|
||||||
|
&mut extra_data);
|
||||||
let needs_reflow = viewport_size_changed && !needs_dirtying;
|
let needs_reflow = viewport_size_changed && !needs_dirtying;
|
||||||
if needs_dirtying {
|
if needs_dirtying {
|
||||||
if let Some(mut d) = element.mutate_data() {
|
if let Some(mut d) = element.mutate_data() {
|
||||||
|
|
|
@ -13,12 +13,12 @@ use gecko_bindings::sugar::ownership::{HasBoxFFI, HasFFI, HasSimpleFFI};
|
||||||
use media_queries::Device;
|
use media_queries::Device;
|
||||||
use parking_lot::RwLock;
|
use parking_lot::RwLock;
|
||||||
use properties::ComputedValues;
|
use properties::ComputedValues;
|
||||||
use shared_lock::{StylesheetGuards, SharedRwLockReadGuard};
|
use shared_lock::{Locked, StylesheetGuards, SharedRwLockReadGuard};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::sync::mpsc::{Receiver, Sender, channel};
|
use std::sync::mpsc::{Receiver, Sender, channel};
|
||||||
use stylesheets::Stylesheet;
|
use stylesheets::{FontFaceRule, Origin, Stylesheet};
|
||||||
use stylist::Stylist;
|
use stylist::{ExtraStyleData, Stylist};
|
||||||
|
|
||||||
/// The container for data that a Servo-backed Gecko document needs to style
|
/// The container for data that a Servo-backed Gecko document needs to style
|
||||||
/// itself.
|
/// itself.
|
||||||
|
@ -45,6 +45,9 @@ pub struct PerDocumentStyleDataImpl {
|
||||||
/// Unused. Will go away when we actually implement transitions and
|
/// Unused. Will go away when we actually implement transitions and
|
||||||
/// animations properly.
|
/// animations properly.
|
||||||
pub expired_animations: Arc<RwLock<HashMap<OpaqueNode, Vec<Animation>>>>,
|
pub expired_animations: Arc<RwLock<HashMap<OpaqueNode, Vec<Animation>>>>,
|
||||||
|
|
||||||
|
/// List of effective font face rules.
|
||||||
|
pub font_faces: Vec<(Arc<Locked<FontFaceRule>>, Origin)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The data itself is an `AtomicRefCell`, which guarantees the proper semantics
|
/// The data itself is an `AtomicRefCell`, which guarantees the proper semantics
|
||||||
|
@ -66,6 +69,7 @@ impl PerDocumentStyleData {
|
||||||
new_animations_receiver: new_anims_receiver,
|
new_animations_receiver: new_anims_receiver,
|
||||||
running_animations: Arc::new(RwLock::new(HashMap::new())),
|
running_animations: Arc::new(RwLock::new(HashMap::new())),
|
||||||
expired_animations: Arc::new(RwLock::new(HashMap::new())),
|
expired_animations: Arc::new(RwLock::new(HashMap::new())),
|
||||||
|
font_faces: vec![],
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -97,7 +101,11 @@ impl PerDocumentStyleDataImpl {
|
||||||
pub fn flush_stylesheets(&mut self, guard: &SharedRwLockReadGuard) {
|
pub fn flush_stylesheets(&mut self, guard: &SharedRwLockReadGuard) {
|
||||||
if self.stylesheets_changed {
|
if self.stylesheets_changed {
|
||||||
let mut stylist = Arc::get_mut(&mut self.stylist).unwrap();
|
let mut stylist = Arc::get_mut(&mut self.stylist).unwrap();
|
||||||
stylist.update(&self.stylesheets, &StylesheetGuards::same(guard), None, true);
|
let mut extra_data = ExtraStyleData {
|
||||||
|
font_faces: &mut self.font_faces,
|
||||||
|
};
|
||||||
|
stylist.update(&self.stylesheets, &StylesheetGuards::same(guard),
|
||||||
|
None, true, &mut extra_data);
|
||||||
self.stylesheets_changed = false;
|
self.stylesheets_changed = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,9 +34,11 @@ use std::borrow::Borrow;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::hash::Hash;
|
use std::hash::Hash;
|
||||||
|
#[cfg(feature = "servo")]
|
||||||
|
use std::marker::PhantomData;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use style_traits::viewport::ViewportConstraints;
|
use style_traits::viewport::ViewportConstraints;
|
||||||
use stylesheets::{CssRule, Origin, StyleRule, Stylesheet, UserAgentStylesheets};
|
use stylesheets::{CssRule, FontFaceRule, Origin, StyleRule, Stylesheet, UserAgentStylesheets};
|
||||||
use thread_state;
|
use thread_state;
|
||||||
use viewport::{self, MaybeNew, ViewportRule};
|
use viewport::{self, MaybeNew, ViewportRule};
|
||||||
|
|
||||||
|
@ -118,6 +120,37 @@ pub struct Stylist {
|
||||||
non_common_style_affecting_attributes_selectors: Vec<Selector<SelectorImpl>>,
|
non_common_style_affecting_attributes_selectors: Vec<Selector<SelectorImpl>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// This struct holds data which user of Stylist may want to extract
|
||||||
|
/// from stylesheets which can be done at the same time as updating.
|
||||||
|
pub struct ExtraStyleData<'a> {
|
||||||
|
/// A list of effective font-face rules and their origin.
|
||||||
|
#[cfg(feature = "gecko")]
|
||||||
|
pub font_faces: &'a mut Vec<(Arc<Locked<FontFaceRule>>, Origin)>,
|
||||||
|
|
||||||
|
#[allow(missing_docs)]
|
||||||
|
#[cfg(feature = "servo")]
|
||||||
|
pub marker: PhantomData<&'a usize>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "gecko")]
|
||||||
|
impl<'a> ExtraStyleData<'a> {
|
||||||
|
/// Clear the internal @font-face rule list.
|
||||||
|
fn clear_font_faces(&mut self) {
|
||||||
|
self.font_faces.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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "servo")]
|
||||||
|
impl<'a> ExtraStyleData<'a> {
|
||||||
|
fn clear_font_faces(&mut self) {}
|
||||||
|
fn add_font_face(&mut self, _: &Arc<Locked<FontFaceRule>>, _: Origin) {}
|
||||||
|
}
|
||||||
|
|
||||||
impl Stylist {
|
impl Stylist {
|
||||||
/// Construct a new `Stylist`, using a given `Device`.
|
/// Construct a new `Stylist`, using a given `Device`.
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -156,11 +189,12 @@ 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 update(&mut self,
|
pub fn update<'a>(&mut self,
|
||||||
doc_stylesheets: &[Arc<Stylesheet>],
|
doc_stylesheets: &[Arc<Stylesheet>],
|
||||||
guards: &StylesheetGuards,
|
guards: &StylesheetGuards,
|
||||||
ua_stylesheets: Option<&UserAgentStylesheets>,
|
ua_stylesheets: Option<&UserAgentStylesheets>,
|
||||||
stylesheets_changed: bool) -> bool {
|
stylesheets_changed: bool,
|
||||||
|
extra_data: &mut ExtraStyleData<'a>) -> bool {
|
||||||
if !(self.is_device_dirty || stylesheets_changed) {
|
if !(self.is_device_dirty || stylesheets_changed) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -194,18 +228,21 @@ impl Stylist {
|
||||||
self.sibling_affecting_selectors.clear();
|
self.sibling_affecting_selectors.clear();
|
||||||
self.non_common_style_affecting_attributes_selectors.clear();
|
self.non_common_style_affecting_attributes_selectors.clear();
|
||||||
|
|
||||||
|
extra_data.clear_font_faces();
|
||||||
|
|
||||||
if let Some(ua_stylesheets) = ua_stylesheets {
|
if let Some(ua_stylesheets) = ua_stylesheets {
|
||||||
for stylesheet in &ua_stylesheets.user_or_user_agent_stylesheets {
|
for stylesheet in &ua_stylesheets.user_or_user_agent_stylesheets {
|
||||||
self.add_stylesheet(&stylesheet, guards.ua_or_user);
|
self.add_stylesheet(&stylesheet, guards.ua_or_user, extra_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.quirks_mode {
|
if self.quirks_mode {
|
||||||
self.add_stylesheet(&ua_stylesheets.quirks_mode_stylesheet, guards.ua_or_user);
|
self.add_stylesheet(&ua_stylesheets.quirks_mode_stylesheet,
|
||||||
|
guards.ua_or_user, extra_data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for ref stylesheet in doc_stylesheets.iter() {
|
for ref stylesheet in doc_stylesheets.iter() {
|
||||||
self.add_stylesheet(stylesheet, guards.author);
|
self.add_stylesheet(stylesheet, guards.author, extra_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
debug!("Stylist stats:");
|
debug!("Stylist stats:");
|
||||||
|
@ -230,7 +267,8 @@ impl Stylist {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_stylesheet(&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) {
|
if stylesheet.disabled() || !stylesheet.is_effective_for_device(&self.device, guard) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -274,7 +312,7 @@ impl Stylist {
|
||||||
}
|
}
|
||||||
CssRule::Import(ref import) => {
|
CssRule::Import(ref import) => {
|
||||||
let import = import.read_with(guard);
|
let import = import.read_with(guard);
|
||||||
self.add_stylesheet(&import.stylesheet, guard)
|
self.add_stylesheet(&import.stylesheet, guard, extra_data)
|
||||||
}
|
}
|
||||||
CssRule::Keyframes(ref keyframes_rule) => {
|
CssRule::Keyframes(ref keyframes_rule) => {
|
||||||
let keyframes_rule = keyframes_rule.read_with(guard);
|
let keyframes_rule = keyframes_rule.read_with(guard);
|
||||||
|
@ -284,6 +322,9 @@ impl Stylist {
|
||||||
debug!("Found valid keyframe animation: {:?}", animation);
|
debug!("Found valid keyframe animation: {:?}", animation);
|
||||||
self.animations.insert(keyframes_rule.name.clone(), animation);
|
self.animations.insert(keyframes_rule.name.clone(), animation);
|
||||||
}
|
}
|
||||||
|
CssRule::FontFace(ref rule) => {
|
||||||
|
extra_data.add_font_face(&rule, stylesheet.origin);
|
||||||
|
}
|
||||||
// We don't care about any other rule.
|
// We don't care about any other rule.
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue