Skip to content

Commit

Permalink
stylo: Pass the @page values to precomputed pseudo element declarations
Browse files Browse the repository at this point in the history
We were parsing @page rules correctly and serializing for cssom when we
we need. But we weren't actually including them to the pseudo element
declarations when we need to print a page.
  • Loading branch information
canova committed Sep 6, 2017
1 parent af587e5 commit c533e23
Show file tree
Hide file tree
Showing 2 changed files with 119 additions and 16 deletions.
95 changes: 82 additions & 13 deletions components/style/stylist.rs
Expand Up @@ -21,7 +21,7 @@ use properties::{AnimationRules, PropertyDeclarationBlock};
#[cfg(feature = "servo")]
use properties::INHERIT_ALL;
use properties::IS_LINK;
use rule_tree::{CascadeLevel, RuleTree, StyleSource};
use rule_tree::{CascadeLevel, RuleTree, StrongRuleNode, StyleSource};
use selector_map::{PrecomputedHashMap, SelectorMap, SelectorMapEntry};
use selector_parser::{SelectorImpl, PerPseudoElementMap, PseudoElement};
use selectors::attr::NamespaceConstraint;
Expand All @@ -40,7 +40,7 @@ use std::ops;
use style_traits::viewport::ViewportConstraints;
use stylesheet_set::{OriginValidity, SheetRebuildKind, StylesheetSet, StylesheetIterator, StylesheetFlusher};
#[cfg(feature = "gecko")]
use stylesheets::{CounterStyleRule, FontFaceRule, FontFeatureValuesRule};
use stylesheets::{CounterStyleRule, FontFaceRule, FontFeatureValuesRule, PageRule};
use stylesheets::{CssRule, Origin, OriginSet, PerOrigin, PerOriginIter};
#[cfg(feature = "gecko")]
use stylesheets::{MallocEnclosingSizeOfFn, MallocSizeOf, MallocSizeOfBox, MallocSizeOfFn};
Expand Down Expand Up @@ -357,6 +357,12 @@ impl DocumentCascadeData {
.borrow_mut_for_origin(&origin)
.add_counter_style(guard, rule);
}
#[cfg(feature = "gecko")]
CssRule::Page(ref rule) => {
_extra_data
.borrow_mut_for_origin(&origin)
.add_page(rule);
}
// We don't care about any other rule.
_ => {}
}
Expand Down Expand Up @@ -711,17 +717,33 @@ impl Stylist {
) -> Arc<ComputedValues> {
debug_assert!(pseudo.is_precomputed());

let rule_node =
match self.cascade_data.precomputed_pseudo_element_decls.get(pseudo) {
Some(declarations) => {
self.rule_tree.insert_ordered_rules_with_important(
declarations.into_iter().map(|a| (a.source.clone(), a.level())),
guards
)
}
None => self.rule_tree.root().clone(),
};
let rule_node = self.rule_node_for_precomputed_pseudo(
guards,
pseudo,
None,
);

self.precomputed_values_for_pseudo_with_rule_node(
guards,
pseudo,
parent,
cascade_flags,
font_metrics,
&rule_node
)
}

/// Computes the style for a given "precomputed" pseudo-element with
/// given rule node.
pub fn precomputed_values_for_pseudo_with_rule_node(
&self,
guards: &StylesheetGuards,
pseudo: &PseudoElement,
parent: Option<&ComputedValues>,
cascade_flags: CascadeFlags,
font_metrics: &FontMetricsProvider,
rule_node: &StrongRuleNode
) -> Arc<ComputedValues> {
// NOTE(emilio): We skip calculating the proper layout parent style
// here.
//
Expand All @@ -739,7 +761,7 @@ impl Stylist {
properties::cascade(
&self.device,
Some(pseudo),
&rule_node,
rule_node,
guards,
parent,
parent,
Expand All @@ -751,6 +773,43 @@ impl Stylist {
)
}

/// Returns the rule node for given precomputed pseudo-element.
///
/// If we want to include extra declarations to this precomputed pseudo-element,
/// we can provide a vector of ApplicableDeclarationBlock to extra_declarations
/// argument. This is useful for providing extra @page rules.
pub fn rule_node_for_precomputed_pseudo(
&self,
guards: &StylesheetGuards,
pseudo: &PseudoElement,
extra_declarations: Option<Vec<ApplicableDeclarationBlock>>,
) -> StrongRuleNode {
let mut decl;
let declarations = match self.cascade_data.precomputed_pseudo_element_decls.get(pseudo) {
Some(declarations) => {
match extra_declarations {
Some(mut extra_decls) => {
decl = declarations.clone();
decl.append(&mut extra_decls);
Some(&decl)
},
None => Some(declarations),
}
}
None => extra_declarations.as_ref(),
};

match declarations {
Some(decls) => {
self.rule_tree.insert_ordered_rules_with_important(
decls.into_iter().map(|a| (a.source.clone(), a.level())),
guards
)
},
None => self.rule_tree.root().clone(),
}
}

/// Returns the style for an anonymous box of the given type.
#[cfg(feature = "servo")]
pub fn style_for_anonymous(
Expand Down Expand Up @@ -1611,6 +1670,10 @@ pub struct ExtraStyleData {
/// A map of effective counter-style rules.
#[cfg(feature = "gecko")]
pub counter_styles: PrecomputedHashMap<Atom, Arc<Locked<CounterStyleRule>>>,

/// A map of effective page rules.
#[cfg(feature = "gecko")]
pub pages: Vec<Arc<Locked<PageRule>>>,
}

#[cfg(feature = "gecko")]
Expand All @@ -1634,6 +1697,11 @@ impl ExtraStyleData {
let name = rule.read_with(guard).mName.raw::<nsIAtom>().into();
self.counter_styles.insert(name, rule.clone());
}

/// Add the given @page rule.
fn add_page(&mut self, rule: &Arc<Locked<PageRule>>) {
self.pages.push(rule.clone());
}
}

impl ExtraStyleData {
Expand All @@ -1643,6 +1711,7 @@ impl ExtraStyleData {
self.font_faces.clear();
self.font_feature_values.clear();
self.counter_styles.clear();
self.pages.clear();
}
}

Expand Down
40 changes: 37 additions & 3 deletions ports/geckolib/glue.rs
Expand Up @@ -12,6 +12,7 @@ use std::env;
use std::fmt::Write;
use std::iter;
use std::ptr;
use style::applicable_declarations::ApplicableDeclarationBlock;
use style::context::{CascadeInputs, QuirksMode, SharedStyleContext, StyleContext};
use style::context::ThreadLocalStyleContext;
use style::data::ElementStyles;
Expand Down Expand Up @@ -113,7 +114,7 @@ use style::properties::PROHIBIT_DISPLAY_CONTENTS;
use style::properties::animated_properties::{AnimatableLonghand, AnimationValue};
use style::properties::animated_properties::compare_property_priority;
use style::properties::parse_one_declaration_into;
use style::rule_tree::StyleSource;
use style::rule_tree::{CascadeLevel, StyleSource};
use style::selector_parser::PseudoElementCascadeType;
use style::shared_lock::{SharedRwLockReadGuard, StylesheetGuards, ToCssWithGuard, Locked};
use style::string_cache::Atom;
Expand Down Expand Up @@ -1679,11 +1680,44 @@ pub extern "C" fn Servo_ComputedValues_GetForAnonymousBox(parent_style_or_null:
cascade_flags.insert(IS_FIELDSET_CONTENT);
}
let metrics = get_metrics_provider_for_product();
data.stylist.precomputed_values_for_pseudo(

// If the pseudo element is PageContent, we should append the precomputed
// pseudo element declerations with specified page rules.
let page_decls = match pseudo {
PseudoElement::PageContent => {
let mut declarations = vec![];
let iter = data.extra_style_data.iter_origins_rev();
for (data, origin) in iter {
let level = match origin {
Origin::UserAgent => CascadeLevel::UANormal,
Origin::User => CascadeLevel::UserNormal,
Origin::Author => CascadeLevel::AuthorNormal,
};
for rule in data.pages.iter() {
declarations.push(ApplicableDeclarationBlock::from_declarations(
rule.read_with(level.guard(&guards)).block.clone(),
level
));
}
}
Some(declarations)
},
_ => None,
};

let rule_node = data.stylist.rule_node_for_precomputed_pseudo(
&guards,
&pseudo,
page_decls,
);

data.stylist.precomputed_values_for_pseudo_with_rule_node(
&guards,
&pseudo,
parent_style_or_null.map(|x| &*x),
cascade_flags, &metrics
cascade_flags,
&metrics,
&rule_node
).into()
}

Expand Down

0 comments on commit c533e23

Please sign in to comment.