Skip to content

Commit

Permalink
style: Introduce OriginSet.
Browse files Browse the repository at this point in the history
  • Loading branch information
emilio committed Aug 14, 2017
1 parent b0422b8 commit f7eb46f
Show file tree
Hide file tree
Showing 5 changed files with 119 additions and 56 deletions.
2 changes: 1 addition & 1 deletion components/style/gecko_bindings/sugar/mod.rs
Expand Up @@ -13,7 +13,7 @@ mod ns_style_auto_array;
pub mod ns_style_coord;
mod ns_t_array;
mod ns_timing_function;
mod origin_flags;
pub mod origin_flags;
pub mod ownership;
pub mod refptr;
mod style_complex_color;
49 changes: 15 additions & 34 deletions components/style/gecko_bindings/sugar/origin_flags.rs
Expand Up @@ -8,43 +8,24 @@ use gecko_bindings::structs::OriginFlags;
use gecko_bindings::structs::OriginFlags_Author;
use gecko_bindings::structs::OriginFlags_User;
use gecko_bindings::structs::OriginFlags_UserAgent;
use stylesheets::Origin;

impl OriginFlags {
/// Returns an iterator over the origins present in the `OriginFlags`,
/// in order from highest priority (author) to lower (user agent).
pub fn iter(self) -> OriginFlagsIter {
OriginFlagsIter {
origin_flags: self,
cur: 0,
}
}
use stylesheets::OriginSet;

/// Checks that the values for OriginFlags are the ones we expect.
pub fn assert_flags_match() {
use stylesheets::origin::*;
debug_assert_eq!(OriginFlags_UserAgent.0, ORIGIN_USER_AGENT.bits());
debug_assert_eq!(OriginFlags_Author.0, ORIGIN_AUTHOR.bits());
debug_assert_eq!(OriginFlags_User.0, ORIGIN_USER.bits());
}

/// Iterates over the origins present in an `OriginFlags`, in order from
/// highest priority (author) to lower (user agent).
pub struct OriginFlagsIter {
origin_flags: OriginFlags,
cur: usize,
impl From<OriginFlags> for OriginSet {
fn from(flags: OriginFlags) -> Self {
Self::from_bits_truncate(flags.0)
}
}

impl Iterator for OriginFlagsIter {
type Item = Origin;

fn next(&mut self) -> Option<Origin> {
loop {
let (bit, origin) = match self.cur {
0 => (OriginFlags_Author, Origin::Author),
1 => (OriginFlags_User, Origin::User),
2 => (OriginFlags_UserAgent, Origin::UserAgent),
_ => return None,
};

self.cur += 1;

if (self.origin_flags & bit).0 != 0 {
return Some(origin);
}
}
impl From<OriginSet> for OriginFlags {
fn from(set: OriginSet) -> Self {
OriginFlags(set.bits())
}
}
4 changes: 2 additions & 2 deletions components/style/stylesheets/mod.rs
Expand Up @@ -14,7 +14,7 @@ mod loader;
mod media_rule;
mod memory;
mod namespace_rule;
mod origin;
pub mod origin;
mod page_rule;
mod rule_list;
mod rule_parser;
Expand Down Expand Up @@ -44,7 +44,7 @@ pub use self::memory::{MallocSizeOf, MallocSizeOfFn, MallocSizeOfWithGuard};
#[cfg(feature = "gecko")]
pub use self::memory::{MallocSizeOfWithRepeats, SizeOfState};
pub use self::namespace_rule::NamespaceRule;
pub use self::origin::{Origin, PerOrigin, PerOriginClear};
pub use self::origin::{Origin, OriginSet, PerOrigin, PerOriginClear};
pub use self::page_rule::PageRule;
pub use self::rule_parser::{State, TopLevelRuleParser};
pub use self::rule_list::{CssRules, CssRulesHelpers};
Expand Down
113 changes: 96 additions & 17 deletions components/style/stylesheets/origin.rs
Expand Up @@ -2,24 +2,103 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

///! [CSS cascade origins](https://drafts.csswg.org/css-cascade/#cascading-origins).
//! [CSS cascade origins](https://drafts.csswg.org/css-cascade/#cascading-origins).

use std::marker::PhantomData;
use std::ops::BitOrAssign;

/// Each style rule has an origin, which determines where it enters the cascade.
///
/// https://drafts.csswg.org/css-cascade/#cascading-origins
#[derive(Clone, PartialEq, Eq, Copy, Debug)]
#[repr(u8)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub enum Origin {
/// https://drafts.csswg.org/css-cascade/#cascade-origin-us
UserAgent,
/// https://drafts.csswg.org/css-cascade/#cascade-origin-user-agent
UserAgent = 1 << 0,

/// https://drafts.csswg.org/css-cascade/#cascade-origin-user
User,
User = 1 << 1,

/// https://drafts.csswg.org/css-cascade/#cascade-origin-author
Author,
Author = 1 << 2,
}

impl Origin {
/// Returns an origin that goes in order for `index`.
///
/// This is used for iterating across origins.
fn from_index(index: i8) -> Option<Self> {
Some(match index {
0 => Origin::Author,
1 => Origin::User,
2 => Origin::UserAgent,
_ => return None,
})
}
}

bitflags! {
/// A set of origins. This is equivalent to Gecko's OriginFlags.
pub flags OriginSet: u8 {
/// https://drafts.csswg.org/css-cascade/#cascade-origin-user-agent
const ORIGIN_USER_AGENT = Origin::UserAgent as u8,
/// https://drafts.csswg.org/css-cascade/#cascade-origin-user
const ORIGIN_USER = Origin::User as u8,
/// https://drafts.csswg.org/css-cascade/#cascade-origin-author
const ORIGIN_AUTHOR = Origin::Author as u8,
}
}

impl OriginSet {
/// Returns an iterator over the origins present in this `OriginSet`.
///
/// See the `OriginSet` documentation for information about the order
/// origins are iterated.
pub fn iter(&self) -> OriginSetIterator {
OriginSetIterator {
set: *self,
cur: 0,
}
}
}

impl From<Origin> for OriginSet {
fn from(origin: Origin) -> Self {
Self::from_bits_truncate(origin as u8)
}
}

impl BitOrAssign<Origin> for OriginSet {
fn bitor_assign(&mut self, origin: Origin) {
*self |= OriginSet::from(origin);
}
}

/// Iterates over the origins present in an `OriginSet`, in order from
/// highest priority (author) to lower (user agent).
pub struct OriginSetIterator {
set: OriginSet,
cur: i8,
}

impl Iterator for OriginSetIterator {
type Item = Origin;

fn next(&mut self) -> Option<Origin> {
loop {
let origin = match Origin::from_index(self.cur) {
Some(origin) => origin,
None => return None,
};

self.cur += 1;

if self.set.contains(origin.into()) {
return Some(origin)
}
}
}
}

/// An object that stores a `T` for each origin of the CSS cascade.
Expand Down Expand Up @@ -118,14 +197,14 @@ impl<'a, T> Iterator for PerOriginIter<'a, T> where T: 'a {
type Item = (&'a T, Origin);

fn next(&mut self) -> Option<Self::Item> {
let result = match self.cur {
0 => (&self.data.author, Origin::Author),
1 => (&self.data.user, Origin::User),
2 => (&self.data.user_agent, Origin::UserAgent),
_ => return None,
let origin = match Origin::from_index(self.cur) {
Some(origin) => origin,
None => return None,
};

self.cur += if self.rev { -1 } else { 1 };
Some(result)

Some((self.data.borrow_for_origin(&origin), origin))
}
}

Expand All @@ -145,13 +224,13 @@ impl<'a, T> Iterator for PerOriginIterMut<'a, T> where T: 'a {
type Item = (&'a mut T, Origin);

fn next(&mut self) -> Option<Self::Item> {
let result = match self.cur {
0 => (unsafe { &mut (*self.data).author }, Origin::Author),
1 => (unsafe { &mut (*self.data).user }, Origin::User),
2 => (unsafe { &mut (*self.data).user_agent }, Origin::UserAgent),
_ => return None,
let origin = match Origin::from_index(self.cur) {
Some(origin) => origin,
None => return None,
};

self.cur += 1;
Some(result)

Some((unsafe { (*self.data).borrow_mut_for_origin(&origin) }, origin))
}
}
7 changes: 5 additions & 2 deletions ports/geckolib/glue.rs
Expand Up @@ -115,7 +115,7 @@ use style::string_cache::Atom;
use style::style_adjuster::StyleAdjuster;
use style::stylesheets::{CssRule, CssRules, CssRuleType, CssRulesHelpers, DocumentRule};
use style::stylesheets::{FontFeatureValuesRule, ImportRule, KeyframesRule, MallocSizeOfWithGuard};
use style::stylesheets::{MediaRule, NamespaceRule, Origin, PageRule, SizeOfState, StyleRule};
use style::stylesheets::{MediaRule, NamespaceRule, Origin, OriginSet, PageRule, SizeOfState, StyleRule};
use style::stylesheets::{StylesheetContents, StylesheetInDocument, SupportsRule};
use style::stylesheets::StylesheetLoader as StyleStylesheetLoader;
use style::stylesheets::keyframes_rule::{Keyframe, KeyframeSelector, KeyframesStepValue};
Expand Down Expand Up @@ -148,6 +148,8 @@ static mut DUMMY_URL_DATA: *mut URLExtraData = 0 as *mut URLExtraData;

#[no_mangle]
pub extern "C" fn Servo_Initialize(dummy_url_data: *mut URLExtraData) {
use style::gecko_bindings::sugar::origin_flags;

// Initialize logging.
let mut builder = LogBuilder::new();
let default_level = if cfg!(debug_assertions) { "warn" } else { "error" };
Expand All @@ -161,6 +163,7 @@ pub extern "C" fn Servo_Initialize(dummy_url_data: *mut URLExtraData) {

// Perform some debug-only runtime assertions.
restyle_hints::assert_restyle_hints_match();
origin_flags::assert_flags_match();
parser::assert_parsing_mode_match();
traversal_flags::assert_traversal_flags_match();

Expand Down Expand Up @@ -994,7 +997,7 @@ pub extern "C" fn Servo_StyleSet_NoteStyleSheetsChanged(
changed_origins: OriginFlags,
) {
let mut data = PerDocumentStyleData::from_ffi(raw_data).borrow_mut();
for origin in changed_origins.iter() {
for origin in OriginSet::from(changed_origins).iter() {
data.stylesheets.force_dirty_origin(&origin);
data.clear_stylist_origin(&origin);
}
Expand Down

0 comments on commit f7eb46f

Please sign in to comment.