mirror of
https://github.com/servo/servo.git
synced 2025-08-05 13:40:08 +01:00
Auto merge of #18398 - canaltinova:at-page-rule, r=emilio
stylo: Pass the @page values to precomputed pseudo element declarations 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. Reviewed by emilio on Bugzilla. --- - [X] `./mach build -d` does not report any errors - [X] `./mach test-tidy` does not report any errors - [X] These changes fix [Bug 1394035](https://bugzilla.mozilla.org/show_bug.cgi?id=1394035) <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/18398) <!-- Reviewable:end -->
This commit is contained in:
commit
094502e55f
2 changed files with 119 additions and 16 deletions
|
@ -21,7 +21,7 @@ use properties::{AnimationRules, PropertyDeclarationBlock};
|
||||||
#[cfg(feature = "servo")]
|
#[cfg(feature = "servo")]
|
||||||
use properties::INHERIT_ALL;
|
use properties::INHERIT_ALL;
|
||||||
use properties::IS_LINK;
|
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_map::{PrecomputedHashMap, SelectorMap, SelectorMapEntry};
|
||||||
use selector_parser::{SelectorImpl, PerPseudoElementMap, PseudoElement};
|
use selector_parser::{SelectorImpl, PerPseudoElementMap, PseudoElement};
|
||||||
use selectors::attr::NamespaceConstraint;
|
use selectors::attr::NamespaceConstraint;
|
||||||
|
@ -40,7 +40,7 @@ use std::ops;
|
||||||
use style_traits::viewport::ViewportConstraints;
|
use style_traits::viewport::ViewportConstraints;
|
||||||
use stylesheet_set::{OriginValidity, SheetRebuildKind, StylesheetSet, StylesheetIterator, StylesheetFlusher};
|
use stylesheet_set::{OriginValidity, SheetRebuildKind, StylesheetSet, StylesheetIterator, StylesheetFlusher};
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
use stylesheets::{CounterStyleRule, FontFaceRule, FontFeatureValuesRule};
|
use stylesheets::{CounterStyleRule, FontFaceRule, FontFeatureValuesRule, PageRule};
|
||||||
use stylesheets::{CssRule, Origin, OriginSet, PerOrigin, PerOriginIter};
|
use stylesheets::{CssRule, Origin, OriginSet, PerOrigin, PerOriginIter};
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
use stylesheets::{MallocEnclosingSizeOfFn, MallocSizeOf, MallocSizeOfBox, MallocSizeOfFn};
|
use stylesheets::{MallocEnclosingSizeOfFn, MallocSizeOf, MallocSizeOfBox, MallocSizeOfFn};
|
||||||
|
@ -357,6 +357,12 @@ impl DocumentCascadeData {
|
||||||
.borrow_mut_for_origin(&origin)
|
.borrow_mut_for_origin(&origin)
|
||||||
.add_counter_style(guard, rule);
|
.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.
|
// We don't care about any other rule.
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
@ -711,17 +717,33 @@ impl Stylist {
|
||||||
) -> Arc<ComputedValues> {
|
) -> Arc<ComputedValues> {
|
||||||
debug_assert!(pseudo.is_precomputed());
|
debug_assert!(pseudo.is_precomputed());
|
||||||
|
|
||||||
let rule_node =
|
let rule_node = self.rule_node_for_precomputed_pseudo(
|
||||||
match self.cascade_data.precomputed_pseudo_element_decls.get(pseudo) {
|
guards,
|
||||||
Some(declarations) => {
|
pseudo,
|
||||||
self.rule_tree.insert_ordered_rules_with_important(
|
None,
|
||||||
declarations.into_iter().map(|a| (a.source.clone(), a.level())),
|
);
|
||||||
guards
|
|
||||||
)
|
|
||||||
}
|
|
||||||
None => self.rule_tree.root().clone(),
|
|
||||||
};
|
|
||||||
|
|
||||||
|
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
|
// NOTE(emilio): We skip calculating the proper layout parent style
|
||||||
// here.
|
// here.
|
||||||
//
|
//
|
||||||
|
@ -739,7 +761,7 @@ impl Stylist {
|
||||||
properties::cascade(
|
properties::cascade(
|
||||||
&self.device,
|
&self.device,
|
||||||
Some(pseudo),
|
Some(pseudo),
|
||||||
&rule_node,
|
rule_node,
|
||||||
guards,
|
guards,
|
||||||
parent,
|
parent,
|
||||||
parent,
|
parent,
|
||||||
|
@ -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.
|
/// Returns the style for an anonymous box of the given type.
|
||||||
#[cfg(feature = "servo")]
|
#[cfg(feature = "servo")]
|
||||||
pub fn style_for_anonymous(
|
pub fn style_for_anonymous(
|
||||||
|
@ -1611,6 +1670,10 @@ pub struct ExtraStyleData {
|
||||||
/// A map of effective counter-style rules.
|
/// A map of effective counter-style rules.
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
pub counter_styles: PrecomputedHashMap<Atom, Arc<Locked<CounterStyleRule>>>,
|
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")]
|
#[cfg(feature = "gecko")]
|
||||||
|
@ -1634,6 +1697,11 @@ impl ExtraStyleData {
|
||||||
let name = rule.read_with(guard).mName.raw::<nsIAtom>().into();
|
let name = rule.read_with(guard).mName.raw::<nsIAtom>().into();
|
||||||
self.counter_styles.insert(name, rule.clone());
|
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 {
|
impl ExtraStyleData {
|
||||||
|
@ -1643,6 +1711,7 @@ impl ExtraStyleData {
|
||||||
self.font_faces.clear();
|
self.font_faces.clear();
|
||||||
self.font_feature_values.clear();
|
self.font_feature_values.clear();
|
||||||
self.counter_styles.clear();
|
self.counter_styles.clear();
|
||||||
|
self.pages.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,7 @@ use std::env;
|
||||||
use std::fmt::Write;
|
use std::fmt::Write;
|
||||||
use std::iter;
|
use std::iter;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
|
use style::applicable_declarations::ApplicableDeclarationBlock;
|
||||||
use style::context::{CascadeInputs, QuirksMode, SharedStyleContext, StyleContext};
|
use style::context::{CascadeInputs, QuirksMode, SharedStyleContext, StyleContext};
|
||||||
use style::context::ThreadLocalStyleContext;
|
use style::context::ThreadLocalStyleContext;
|
||||||
use style::data::ElementStyles;
|
use style::data::ElementStyles;
|
||||||
|
@ -113,7 +114,7 @@ use style::properties::PROHIBIT_DISPLAY_CONTENTS;
|
||||||
use style::properties::animated_properties::{AnimatableLonghand, AnimationValue};
|
use style::properties::animated_properties::{AnimatableLonghand, AnimationValue};
|
||||||
use style::properties::animated_properties::compare_property_priority;
|
use style::properties::animated_properties::compare_property_priority;
|
||||||
use style::properties::parse_one_declaration_into;
|
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::selector_parser::PseudoElementCascadeType;
|
||||||
use style::shared_lock::{SharedRwLockReadGuard, StylesheetGuards, ToCssWithGuard, Locked};
|
use style::shared_lock::{SharedRwLockReadGuard, StylesheetGuards, ToCssWithGuard, Locked};
|
||||||
use style::string_cache::Atom;
|
use style::string_cache::Atom;
|
||||||
|
@ -1679,11 +1680,44 @@ pub extern "C" fn Servo_ComputedValues_GetForAnonymousBox(parent_style_or_null:
|
||||||
cascade_flags.insert(IS_FIELDSET_CONTENT);
|
cascade_flags.insert(IS_FIELDSET_CONTENT);
|
||||||
}
|
}
|
||||||
let metrics = get_metrics_provider_for_product();
|
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,
|
&guards,
|
||||||
&pseudo,
|
&pseudo,
|
||||||
parent_style_or_null.map(|x| &*x),
|
parent_style_or_null.map(|x| &*x),
|
||||||
cascade_flags, &metrics
|
cascade_flags,
|
||||||
|
&metrics,
|
||||||
|
&rule_node
|
||||||
).into()
|
).into()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue