зеркало из https://github.com/mozilla/gecko-dev.git
servo: Merge #16784 - Bug 1349651 - stylo: Implement HasAuthorSpecifiedRules (from mbrubeck:has_author); r=bholley
https://bugzilla.mozilla.org/show_bug.cgi?id=1349651 Source-Repo: https://github.com/servo/servo Source-Revision: 66cfea6728135d18be253c6f97f4a65ef561ba55 --HG-- extra : subtree_source : https%3A//hg.mozilla.org/projects/converted-servo-linear extra : subtree_revision : 24fa015b67008ac43f9f54a5ed4da6b616b6c0fe
This commit is contained in:
Родитель
7b7195de55
Коммит
964d3bb34e
|
@ -326,6 +326,7 @@ mod bindings {
|
|||
.constified_enum("UpdateAnimationsTasks")
|
||||
.parse_callbacks(Box::new(Callbacks));
|
||||
let whitelist_vars = [
|
||||
"NS_AUTHOR_SPECIFIED_.*",
|
||||
"NS_THEME_.*",
|
||||
"NODE_.*",
|
||||
"NS_FONT_.*",
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#![allow(non_snake_case, missing_docs)]
|
||||
|
||||
use gecko_bindings::bindings::{RawServoMediaList, RawServoMediaRule, RawServoNamespaceRule, RawServoPageRule};
|
||||
use gecko_bindings::bindings::{RawServoRuleNode, RawServoRuleNodeStrong};
|
||||
use gecko_bindings::bindings::{RawServoStyleSheet, RawServoImportRule, RawServoSupportsRule};
|
||||
use gecko_bindings::bindings::{ServoComputedValues, ServoCssRules};
|
||||
use gecko_bindings::structs::{RawServoDeclarationBlock, RawServoStyleRule};
|
||||
|
@ -17,7 +18,9 @@ use gecko_bindings::sugar::ownership::{HasArcFFI, HasFFI};
|
|||
use media_queries::MediaList;
|
||||
use properties::{ComputedValues, PropertyDeclarationBlock};
|
||||
use properties::animated_properties::AnimationValue;
|
||||
use rule_tree::StrongRuleNode;
|
||||
use shared_lock::Locked;
|
||||
use std::{mem, ptr};
|
||||
use stylesheets::{CssRules, Stylesheet, StyleRule, ImportRule, MediaRule};
|
||||
use stylesheets::{NamespaceRule, PageRule, SupportsRule};
|
||||
|
||||
|
@ -75,3 +78,28 @@ impl_arc_ffi!(Locked<PageRule> => RawServoPageRule
|
|||
|
||||
impl_arc_ffi!(Locked<SupportsRule> => RawServoSupportsRule
|
||||
[Servo_SupportsRule_AddRef, Servo_SupportsRule_Release]);
|
||||
|
||||
// RuleNode is a Arc-like type but it does not use Arc.
|
||||
|
||||
impl StrongRuleNode {
|
||||
pub fn into_strong(self) -> RawServoRuleNodeStrong {
|
||||
let ptr = self.ptr();
|
||||
mem::forget(self);
|
||||
unsafe { mem::transmute(ptr) }
|
||||
}
|
||||
|
||||
pub fn from_ffi<'a>(ffi: &'a &RawServoRuleNode) -> &'a Self {
|
||||
unsafe { &*(ffi as *const &RawServoRuleNode as *const StrongRuleNode) }
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn Servo_RuleNode_AddRef(obj: &RawServoRuleNode) {
|
||||
mem::forget(StrongRuleNode::from_ffi(&obj).clone());
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn Servo_RuleNode_Release(obj: &RawServoRuleNode) {
|
||||
let ptr = StrongRuleNode::from_ffi(&obj);
|
||||
ptr::read(ptr as *const StrongRuleNode);
|
||||
}
|
||||
|
|
|
@ -250,6 +250,11 @@ pub type RawServoSupportsRuleBorrowed<'a> = &'a RawServoSupportsRule;
|
|||
pub type RawServoSupportsRuleBorrowedOrNull<'a> = Option<&'a RawServoSupportsRule>;
|
||||
enum RawServoSupportsRuleVoid { }
|
||||
pub struct RawServoSupportsRule(RawServoSupportsRuleVoid);
|
||||
pub type RawServoRuleNodeStrong = ::gecko_bindings::sugar::ownership::Strong<RawServoRuleNode>;
|
||||
pub type RawServoRuleNodeBorrowed<'a> = &'a RawServoRuleNode;
|
||||
pub type RawServoRuleNodeBorrowedOrNull<'a> = Option<&'a RawServoRuleNode>;
|
||||
enum RawServoRuleNodeVoid { }
|
||||
pub struct RawServoRuleNode(RawServoRuleNodeVoid);
|
||||
pub type RawServoStyleSetOwned = ::gecko_bindings::sugar::ownership::Owned<RawServoStyleSet>;
|
||||
pub type RawServoStyleSetOwnedOrNull = ::gecko_bindings::sugar::ownership::OwnedOrNull<RawServoStyleSet>;
|
||||
pub type RawServoStyleSetBorrowed<'a> = &'a RawServoStyleSet;
|
||||
|
@ -411,6 +416,12 @@ extern "C" {
|
|||
extern "C" {
|
||||
pub fn Servo_SupportsRule_Release(ptr: RawServoSupportsRuleBorrowed);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn Servo_RuleNode_AddRef(ptr: RawServoRuleNodeBorrowed);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn Servo_RuleNode_Release(ptr: RawServoRuleNodeBorrowed);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn Servo_StyleSet_Drop(ptr: RawServoStyleSetOwned);
|
||||
}
|
||||
|
@ -2183,6 +2194,18 @@ extern "C" {
|
|||
set: RawServoStyleSetBorrowed)
|
||||
-> ServoComputedValuesStrong;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn Servo_ResolveRuleNode(element: RawGeckoElementBorrowed,
|
||||
pseudo_tag: *mut nsIAtom,
|
||||
set: RawServoStyleSetBorrowed)
|
||||
-> RawServoRuleNodeStrong;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn Servo_HasAuthorSpecifiedRules(rule_node: RawServoRuleNodeBorrowed,
|
||||
element: RawGeckoElementBorrowed,
|
||||
rule_type_mask: u32,
|
||||
author_colors_allowed: bool) -> bool;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn Servo_ResolveStyleLazily(element: RawGeckoElementBorrowed,
|
||||
pseudo_tag: *mut nsIAtom,
|
||||
|
|
|
@ -1126,6 +1126,10 @@ pub mod root {
|
|||
pub const kNameSpaceID_disabled_SVG: ::std::os::raw::c_uint = 12;
|
||||
pub const kNameSpaceID_LastBuiltin: ::std::os::raw::c_uint = 12;
|
||||
pub const kNameSpaceID_Wildcard: ::std::os::raw::c_int = -2147483648;
|
||||
pub const NS_AUTHOR_SPECIFIED_BACKGROUND: ::std::os::raw::c_uint = 1;
|
||||
pub const NS_AUTHOR_SPECIFIED_BORDER: ::std::os::raw::c_uint = 2;
|
||||
pub const NS_AUTHOR_SPECIFIED_PADDING: ::std::os::raw::c_uint = 4;
|
||||
pub const NS_AUTHOR_SPECIFIED_TEXT_SHADOW: ::std::os::raw::c_uint = 8;
|
||||
pub const NS_STYLE_INHERIT_MASK: ::std::os::raw::c_uint = 16777215;
|
||||
pub const NS_STYLE_HAS_TEXT_DECORATION_LINES: ::std::os::raw::c_uint =
|
||||
16777216;
|
||||
|
|
|
@ -1126,6 +1126,10 @@ pub mod root {
|
|||
pub const kNameSpaceID_disabled_SVG: ::std::os::raw::c_uint = 12;
|
||||
pub const kNameSpaceID_LastBuiltin: ::std::os::raw::c_uint = 12;
|
||||
pub const kNameSpaceID_Wildcard: ::std::os::raw::c_int = -2147483648;
|
||||
pub const NS_AUTHOR_SPECIFIED_BACKGROUND: ::std::os::raw::c_uint = 1;
|
||||
pub const NS_AUTHOR_SPECIFIED_BORDER: ::std::os::raw::c_uint = 2;
|
||||
pub const NS_AUTHOR_SPECIFIED_PADDING: ::std::os::raw::c_uint = 4;
|
||||
pub const NS_AUTHOR_SPECIFIED_TEXT_SHADOW: ::std::os::raw::c_uint = 8;
|
||||
pub const NS_STYLE_INHERIT_MASK: ::std::os::raw::c_uint = 16777215;
|
||||
pub const NS_STYLE_HAS_TEXT_DECORATION_LINES: ::std::os::raw::c_uint =
|
||||
16777216;
|
||||
|
|
|
@ -377,7 +377,8 @@ impl CascadeLevel {
|
|||
}
|
||||
}
|
||||
|
||||
struct RuleNode {
|
||||
/// A node in the rule tree.
|
||||
pub struct RuleNode {
|
||||
/// The root node. Only the root has no root pointer, for obvious reasons.
|
||||
root: Option<WeakRuleNode>,
|
||||
|
||||
|
@ -648,7 +649,8 @@ impl StrongRuleNode {
|
|||
}
|
||||
}
|
||||
|
||||
fn ptr(&self) -> *mut RuleNode {
|
||||
/// Raw pointer to the RuleNode
|
||||
pub fn ptr(&self) -> *mut RuleNode {
|
||||
self.ptr
|
||||
}
|
||||
|
||||
|
@ -790,6 +792,208 @@ impl StrongRuleNode {
|
|||
}
|
||||
}
|
||||
|
||||
/// Implementation of `nsRuleNode::HasAuthorSpecifiedRules` for Servo rule nodes.
|
||||
///
|
||||
/// Returns true if any properties specified by `rule_type_mask` was set by an author rule.
|
||||
#[cfg(feature = "gecko")]
|
||||
pub fn has_author_specified_rules<E>(&self,
|
||||
mut element: E,
|
||||
guards: &StylesheetGuards,
|
||||
rule_type_mask: u32,
|
||||
author_colors_allowed: bool)
|
||||
-> bool
|
||||
where E: ::dom::TElement
|
||||
{
|
||||
use cssparser::RGBA;
|
||||
use gecko_bindings::structs::{NS_AUTHOR_SPECIFIED_BACKGROUND, NS_AUTHOR_SPECIFIED_BORDER};
|
||||
use gecko_bindings::structs::{NS_AUTHOR_SPECIFIED_PADDING, NS_AUTHOR_SPECIFIED_TEXT_SHADOW};
|
||||
use properties::{CSSWideKeyword, LonghandId, LonghandIdSet};
|
||||
use properties::{PropertyDeclaration, PropertyDeclarationId};
|
||||
use std::borrow::Cow;
|
||||
use values::specified::Color;
|
||||
|
||||
// Reset properties:
|
||||
const BACKGROUND_PROPS: &'static [LonghandId] = &[
|
||||
LonghandId::BackgroundColor,
|
||||
LonghandId::BackgroundImage,
|
||||
];
|
||||
|
||||
const BORDER_PROPS: &'static [LonghandId] = &[
|
||||
LonghandId::BorderTopColor,
|
||||
LonghandId::BorderTopStyle,
|
||||
LonghandId::BorderTopWidth,
|
||||
LonghandId::BorderRightColor,
|
||||
LonghandId::BorderRightStyle,
|
||||
LonghandId::BorderRightWidth,
|
||||
LonghandId::BorderBottomColor,
|
||||
LonghandId::BorderBottomStyle,
|
||||
LonghandId::BorderBottomWidth,
|
||||
LonghandId::BorderLeftColor,
|
||||
LonghandId::BorderLeftStyle,
|
||||
LonghandId::BorderLeftWidth,
|
||||
LonghandId::BorderTopLeftRadius,
|
||||
LonghandId::BorderTopRightRadius,
|
||||
LonghandId::BorderBottomRightRadius,
|
||||
LonghandId::BorderBottomLeftRadius,
|
||||
];
|
||||
|
||||
const PADDING_PROPS: &'static [LonghandId] = &[
|
||||
LonghandId::PaddingTop,
|
||||
LonghandId::PaddingRight,
|
||||
LonghandId::PaddingBottom,
|
||||
LonghandId::PaddingLeft,
|
||||
];
|
||||
|
||||
// Inherited properties:
|
||||
const TEXT_SHADOW_PROPS: &'static [LonghandId] = &[
|
||||
LonghandId::TextShadow,
|
||||
];
|
||||
|
||||
fn inherited(id: LonghandId) -> bool {
|
||||
id == LonghandId::TextShadow
|
||||
}
|
||||
|
||||
// Set of properties that we are currently interested in.
|
||||
let mut properties = LonghandIdSet::new();
|
||||
|
||||
if rule_type_mask & NS_AUTHOR_SPECIFIED_BACKGROUND != 0 {
|
||||
for id in BACKGROUND_PROPS {
|
||||
properties.insert(*id);
|
||||
}
|
||||
}
|
||||
if rule_type_mask & NS_AUTHOR_SPECIFIED_BORDER != 0 {
|
||||
for id in BORDER_PROPS {
|
||||
properties.insert(*id);
|
||||
}
|
||||
}
|
||||
if rule_type_mask & NS_AUTHOR_SPECIFIED_PADDING != 0 {
|
||||
for id in PADDING_PROPS {
|
||||
properties.insert(*id);
|
||||
}
|
||||
}
|
||||
if rule_type_mask & NS_AUTHOR_SPECIFIED_TEXT_SHADOW != 0 {
|
||||
for id in TEXT_SHADOW_PROPS {
|
||||
properties.insert(*id);
|
||||
}
|
||||
}
|
||||
|
||||
// If author colors are not allowed, only claim to have author-specified rules if we're
|
||||
// looking at a non-color property or if we're looking at the background color and it's
|
||||
// set to transparent.
|
||||
const IGNORED_WHEN_COLORS_DISABLED: &'static [LonghandId] = &[
|
||||
LonghandId::BackgroundImage,
|
||||
LonghandId::BorderTopColor,
|
||||
LonghandId::BorderRightColor,
|
||||
LonghandId::BorderBottomColor,
|
||||
LonghandId::BorderLeftColor,
|
||||
LonghandId::TextShadow,
|
||||
];
|
||||
|
||||
if !author_colors_allowed {
|
||||
for id in IGNORED_WHEN_COLORS_DISABLED {
|
||||
properties.remove(*id);
|
||||
}
|
||||
}
|
||||
|
||||
let mut element_rule_node = Cow::Borrowed(self);
|
||||
|
||||
loop {
|
||||
// We need to be careful not to count styles covered up by user-important or
|
||||
// UA-important declarations. But we do want to catch explicit inherit styling in
|
||||
// those and check our parent element to see whether we have user styling for
|
||||
// those properties. Note that we don't care here about inheritance due to lack of
|
||||
// a specified value, since all the properties we care about are reset properties.
|
||||
//
|
||||
// FIXME: The above comment is copied from Gecko, but the last sentence is no longer
|
||||
// correct since 'text-shadow' support was added. This is a bug in Gecko, replicated
|
||||
// in Stylo for now: https://bugzilla.mozilla.org/show_bug.cgi?id=1363088
|
||||
|
||||
let mut inherited_properties = LonghandIdSet::new();
|
||||
let mut have_explicit_ua_inherit = false;
|
||||
|
||||
for node in element_rule_node.self_and_ancestors() {
|
||||
let declarations = match node.style_source() {
|
||||
Some(source) => source.read(node.cascade_level().guard(guards)).declarations(),
|
||||
None => continue
|
||||
};
|
||||
|
||||
// Iterate over declarations of the longhands we care about.
|
||||
let node_importance = node.importance();
|
||||
let longhands = declarations.iter().rev()
|
||||
.filter_map(|&(ref declaration, importance)| {
|
||||
if importance != node_importance { return None }
|
||||
match declaration.id() {
|
||||
PropertyDeclarationId::Longhand(id) => {
|
||||
Some((id, declaration))
|
||||
}
|
||||
_ => None
|
||||
}
|
||||
});
|
||||
|
||||
match node.cascade_level() {
|
||||
// Non-author rules:
|
||||
CascadeLevel::UANormal |
|
||||
CascadeLevel::UAImportant |
|
||||
CascadeLevel::UserNormal |
|
||||
CascadeLevel::UserImportant => {
|
||||
for (id, declaration) in longhands {
|
||||
if properties.contains(id) {
|
||||
// This property was set by a non-author rule. Stop looking for it in
|
||||
// this element's rule nodes.
|
||||
properties.remove(id);
|
||||
|
||||
// However, if it is inherited, then it might be inherited from an
|
||||
// author rule from an ancestor element's rule nodes.
|
||||
if declaration.get_css_wide_keyword() == Some(CSSWideKeyword::Inherit) ||
|
||||
(declaration.get_css_wide_keyword() == Some(CSSWideKeyword::Unset) &&
|
||||
inherited(id))
|
||||
{
|
||||
have_explicit_ua_inherit = true;
|
||||
inherited_properties.insert(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Author rules:
|
||||
CascadeLevel::PresHints |
|
||||
CascadeLevel::AuthorNormal |
|
||||
CascadeLevel::StyleAttributeNormal |
|
||||
CascadeLevel::SMILOverride |
|
||||
CascadeLevel::Animations |
|
||||
CascadeLevel::AuthorImportant |
|
||||
CascadeLevel::StyleAttributeImportant |
|
||||
CascadeLevel::Transitions => {
|
||||
for (id, declaration) in longhands {
|
||||
if properties.contains(id) {
|
||||
if !author_colors_allowed {
|
||||
if let PropertyDeclaration::BackgroundColor(ref color) = *declaration {
|
||||
return color.parsed == Color::RGBA(RGBA::transparent())
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !have_explicit_ua_inherit { break }
|
||||
|
||||
// Continue to the parent element and search for the inherited properties.
|
||||
element = match element.parent_element() {
|
||||
Some(parent) => parent,
|
||||
None => break
|
||||
};
|
||||
let parent_data = element.mutate_data().unwrap();
|
||||
let parent_rule_node = parent_data.styles().primary.rules.clone();
|
||||
element_rule_node = Cow::Owned(parent_rule_node);
|
||||
|
||||
properties = inherited_properties;
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
/// Returns true if there is either animation or transition level rule.
|
||||
pub fn has_animation_or_transition_rules(&self) -> bool {
|
||||
self.self_and_ancestors()
|
||||
|
|
|
@ -491,14 +491,47 @@ impl Stylist {
|
|||
where E: TElement +
|
||||
fmt::Debug +
|
||||
PresentationalHintsSynthetizer
|
||||
{
|
||||
let rule_node = match self.lazy_pseudo_rules(guards, element, pseudo) {
|
||||
Some(rule_node) => rule_node,
|
||||
None => return None
|
||||
};
|
||||
|
||||
// Read the comment on `precomputed_values_for_pseudo` to see why it's
|
||||
// difficult to assert that display: contents nodes never arrive here
|
||||
// (tl;dr: It doesn't apply for replaced elements and such, but the
|
||||
// computed value is still "contents").
|
||||
let computed =
|
||||
properties::cascade(&self.device,
|
||||
&rule_node,
|
||||
guards,
|
||||
Some(&**parent),
|
||||
Some(&**parent),
|
||||
None,
|
||||
&RustLogReporter,
|
||||
font_metrics,
|
||||
CascadeFlags::empty(),
|
||||
self.quirks_mode);
|
||||
|
||||
Some(ComputedStyle::new(rule_node, Arc::new(computed)))
|
||||
}
|
||||
|
||||
/// Computes the rule node for a lazily-cascaded pseudo-element.
|
||||
///
|
||||
/// See the documentation on lazy pseudo-elements in
|
||||
/// docs/components/style.md
|
||||
pub fn lazy_pseudo_rules<E>(&self,
|
||||
guards: &StylesheetGuards,
|
||||
element: &E,
|
||||
pseudo: &PseudoElement)
|
||||
-> Option<StrongRuleNode>
|
||||
where E: TElement + fmt::Debug + PresentationalHintsSynthetizer
|
||||
{
|
||||
debug_assert!(pseudo.is_lazy());
|
||||
if self.pseudos_map.get(pseudo).is_none() {
|
||||
return None;
|
||||
return None
|
||||
}
|
||||
|
||||
let mut declarations = vec![];
|
||||
|
||||
// Apply the selector flags. We should be in sequential mode
|
||||
// already, so we can directly apply the parent flags.
|
||||
let mut set_selector_flags = |element: &E, flags: ElementSelectorFlags| {
|
||||
|
@ -524,6 +557,7 @@ impl Stylist {
|
|||
};
|
||||
|
||||
|
||||
let mut declarations = vec![];
|
||||
self.push_applicable_declarations(element,
|
||||
None,
|
||||
None,
|
||||
|
@ -533,32 +567,14 @@ impl Stylist {
|
|||
guards,
|
||||
&mut declarations,
|
||||
&mut set_selector_flags);
|
||||
|
||||
if declarations.is_empty() {
|
||||
return None
|
||||
}
|
||||
|
||||
let rule_node =
|
||||
self.rule_tree.insert_ordered_rules(
|
||||
declarations.into_iter().map(|a| (a.source, a.level)));
|
||||
|
||||
// Read the comment on `precomputed_values_for_pseudo` to see why it's
|
||||
// difficult to assert that display: contents nodes never arrive here
|
||||
// (tl;dr: It doesn't apply for replaced elements and such, but the
|
||||
// computed value is still "contents").
|
||||
let computed =
|
||||
properties::cascade(&self.device,
|
||||
&rule_node,
|
||||
guards,
|
||||
Some(&**parent),
|
||||
Some(&**parent),
|
||||
None,
|
||||
&RustLogReporter,
|
||||
font_metrics,
|
||||
CascadeFlags::empty(),
|
||||
self.quirks_mode);
|
||||
|
||||
Some(ComputedStyle::new(rule_node, Arc::new(computed)))
|
||||
let rule_node = self.rule_tree.insert_ordered_rules(declarations.into_iter().map(|a| {
|
||||
(a.source, a.level)
|
||||
}));
|
||||
Some(rule_node)
|
||||
}
|
||||
|
||||
/// Set a given device, which may change the styles that apply to the
|
||||
|
|
|
@ -32,6 +32,7 @@ use style::gecko_bindings::bindings::{RawServoMediaList, RawServoMediaListBorrow
|
|||
use style::gecko_bindings::bindings::{RawServoMediaRule, RawServoMediaRuleBorrowed};
|
||||
use style::gecko_bindings::bindings::{RawServoNamespaceRule, RawServoNamespaceRuleBorrowed};
|
||||
use style::gecko_bindings::bindings::{RawServoPageRule, RawServoPageRuleBorrowed};
|
||||
use style::gecko_bindings::bindings::{RawServoRuleNodeBorrowed, RawServoRuleNodeStrong};
|
||||
use style::gecko_bindings::bindings::{RawServoStyleSetBorrowed, RawServoStyleSetOwned};
|
||||
use style::gecko_bindings::bindings::{RawServoStyleSheetBorrowed, ServoComputedValuesBorrowed};
|
||||
use style::gecko_bindings::bindings::{RawServoStyleSheetStrong, ServoComputedValuesStrong};
|
||||
|
@ -77,7 +78,7 @@ use style::properties::SKIP_ROOT_AND_ITEM_BASED_DISPLAY_FIXUP;
|
|||
use style::properties::animated_properties::{AnimationValue, ComputeDistance, Interpolate, TransitionProperty};
|
||||
use style::properties::parse_one_declaration;
|
||||
use style::restyle_hints::{self, RestyleHint};
|
||||
use style::rule_tree::StyleSource;
|
||||
use style::rule_tree::{StrongRuleNode, StyleSource};
|
||||
use style::selector_parser::PseudoElementCascadeType;
|
||||
use style::sequential;
|
||||
use style::shared_lock::{SharedRwLock, SharedRwLockReadGuard, StylesheetGuards, ToCssWithGuard, Locked};
|
||||
|
@ -938,6 +939,37 @@ pub extern "C" fn Servo_ComputedValues_GetForAnonymousBox(parent_style_or_null:
|
|||
.into_strong()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn Servo_ResolveRuleNode(element: RawGeckoElementBorrowed,
|
||||
pseudo_tag: *mut nsIAtom,
|
||||
raw_data: RawServoStyleSetBorrowed)
|
||||
-> RawServoRuleNodeStrong
|
||||
{
|
||||
let element = GeckoElement(element);
|
||||
let doc_data = PerDocumentStyleData::from_ffi(raw_data);
|
||||
let guard = (*GLOBAL_STYLE_DATA).shared_lock.read();
|
||||
|
||||
let data = element.mutate_data().unwrap();
|
||||
let styles = match data.get_styles() {
|
||||
Some(styles) => styles,
|
||||
None => {
|
||||
warn!("Calling Servo_ResolveRuleNode on unstyled element");
|
||||
return Strong::null()
|
||||
}
|
||||
};
|
||||
|
||||
let maybe_rules = if pseudo_tag.is_null() {
|
||||
Some(styles.primary.rules.clone())
|
||||
} else {
|
||||
get_pseudo_rule_node(&guard, element, pseudo_tag, styles, doc_data)
|
||||
};
|
||||
|
||||
match maybe_rules {
|
||||
Some(rule_node) => rule_node.into_strong(),
|
||||
None => Strong::null(),
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn Servo_ResolvePseudoStyle(element: RawGeckoElementBorrowed,
|
||||
pseudo_tag: *mut nsIAtom, is_probe: bool,
|
||||
|
@ -967,6 +999,42 @@ pub extern "C" fn Servo_ResolvePseudoStyle(element: RawGeckoElementBorrowed,
|
|||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn Servo_HasAuthorSpecifiedRules(rule_node: RawServoRuleNodeBorrowed,
|
||||
element: RawGeckoElementBorrowed,
|
||||
rule_type_mask: u32,
|
||||
author_colors_allowed: bool)
|
||||
-> bool
|
||||
{
|
||||
let element = GeckoElement(element);
|
||||
let guard = (*GLOBAL_STYLE_DATA).shared_lock.read();
|
||||
let guards = StylesheetGuards::same(&guard);
|
||||
|
||||
StrongRuleNode::from_ffi(&rule_node).has_author_specified_rules(element,
|
||||
&guards,
|
||||
rule_type_mask,
|
||||
author_colors_allowed)
|
||||
}
|
||||
|
||||
fn get_pseudo_rule_node(guard: &SharedRwLockReadGuard,
|
||||
element: GeckoElement,
|
||||
pseudo_tag: *mut nsIAtom,
|
||||
styles: &ElementStyles,
|
||||
doc_data: &PerDocumentStyleData)
|
||||
-> Option<StrongRuleNode>
|
||||
{
|
||||
let pseudo = PseudoElement::from_atom_unchecked(Atom::from(pseudo_tag), false);
|
||||
match pseudo.cascade_type() {
|
||||
PseudoElementCascadeType::Eager => styles.pseudos.get(&pseudo).map(|s| s.rules.clone()),
|
||||
PseudoElementCascadeType::Precomputed => unreachable!("No anonymous boxes"),
|
||||
PseudoElementCascadeType::Lazy => {
|
||||
let d = doc_data.borrow_mut();
|
||||
let guards = StylesheetGuards::same(guard);
|
||||
d.stylist.lazy_pseudo_rules(&guards, &element, &pseudo)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn get_pseudo_style(guard: &SharedRwLockReadGuard,
|
||||
element: GeckoElement,
|
||||
pseudo_tag: *mut nsIAtom,
|
||||
|
|
Загрузка…
Ссылка в новой задаче