diff --git a/ports/geckolib/bindings.rs b/ports/geckolib/bindings.rs index 16724678a80..234f309378d 100644 --- a/ports/geckolib/bindings.rs +++ b/ports/geckolib/bindings.rs @@ -78,11 +78,11 @@ extern "C" { set: *mut RawServoStyleSet); pub fn Servo_PrependStyleSheet(sheet: *mut RawServoStyleSheet, set: *mut RawServoStyleSet); + pub fn Servo_RemoveStyleSheet(sheet: *mut RawServoStyleSheet, + set: *mut RawServoStyleSet); pub fn Servo_InsertStyleSheetBefore(sheet: *mut RawServoStyleSheet, reference: *mut RawServoStyleSheet, set: *mut RawServoStyleSet); - pub fn Servo_RemoveStyleSheet(sheet: *mut RawServoStyleSheet, - set: *mut RawServoStyleSet); pub fn Servo_StyleSheetHasRules(sheet: *mut RawServoStyleSheet) -> bool; pub fn Servo_InitStyleSet() -> *mut RawServoStyleSet; pub fn Servo_DropStyleSet(set: *mut RawServoStyleSet); @@ -93,6 +93,14 @@ extern "C" { pseudoTag: *mut nsIAtom, set: *mut RawServoStyleSet) -> *mut ServoComputedValues; + pub fn Servo_GetComputedValuesForPseudoElement(parent_style: + *mut ServoComputedValues, + match_element: + *mut RawGeckoElement, + pseudo_tag: *mut nsIAtom, + set: *mut RawServoStyleSet, + is_probe: bool) + -> *mut ServoComputedValues; pub fn Servo_AddRefComputedValues(arg1: *mut ServoComputedValues); pub fn Servo_ReleaseComputedValues(arg1: *mut ServoComputedValues); pub fn Gecko_GetAttrAsUTF8(element: *mut RawGeckoElement, ns: *const u8, diff --git a/ports/geckolib/glue.rs b/ports/geckolib/glue.rs index ac5e1b74b2b..96939a3f76f 100644 --- a/ports/geckolib/glue.rs +++ b/ports/geckolib/glue.rs @@ -5,7 +5,7 @@ #![allow(unsafe_code)] use app_units::Au; -use bindings::{RawGeckoDocument, RawGeckoNode}; +use bindings::{RawGeckoDocument, RawGeckoElement, RawGeckoNode}; use bindings::{RawServoStyleSet, RawServoStyleSheet, ServoComputedValues, ServoNodeData}; use bindings::{nsIAtom}; use data::PerDocumentStyleData; @@ -20,15 +20,16 @@ use std::slice; use std::str::from_utf8_unchecked; use std::sync::{Arc, Mutex}; use style::context::{ReflowGoal}; -use style::dom::{TDocument, TNode}; +use style::dom::{TDocument, TElement, TNode}; use style::error_reporting::StdoutErrorReporter; use style::parallel; use style::properties::ComputedValues; +use style::selector_impl::{SelectorImplExt, PseudoElementCascadeType}; use style::stylesheets::Origin; use traversal::RecalcStyleOnly; use url::Url; use util::arc_ptr_eq; -use wrapper::{GeckoDocument, GeckoNode, NonOpaqueStyleData}; +use wrapper::{GeckoDocument, GeckoElement, GeckoNode, NonOpaqueStyleData}; // TODO: This is ugly and should go away once we get an atom back-end. pub fn pseudo_element_from_atom(pseudo: *mut nsIAtom, @@ -256,7 +257,7 @@ pub extern "C" fn Servo_GetComputedValuesForAnonymousBox(parent_style_or_null: * -> *mut ServoComputedValues { let data = PerDocumentStyleData::borrow_mut_from_raw(raw_data); - let pseudo = match pseudo_element_from_atom(pseudo_tag, true) { + let pseudo = match pseudo_element_from_atom(pseudo_tag, /* ua_stylesheet = */ true) { Ok(pseudo) => pseudo, Err(pseudo) => { warn!("stylo: Unable to parse anonymous-box pseudo-element: {}", pseudo); @@ -272,6 +273,62 @@ pub extern "C" fn Servo_GetComputedValuesForAnonymousBox(parent_style_or_null: * }) } +#[no_mangle] +pub extern "C" fn Servo_GetComputedValuesForPseudoElement(parent_style: *mut ServoComputedValues, + match_element: *mut RawGeckoElement, + pseudo_tag: *mut nsIAtom, + raw_data: *mut RawServoStyleSet, + is_probe: bool) + -> *mut ServoComputedValues { + debug_assert!(!match_element.is_null()); + + let parent_or_null = || { + if is_probe { + ptr::null_mut() + } else { + Servo_AddRefComputedValues(parent_style); + parent_style + } + }; + + let pseudo = match pseudo_element_from_atom(pseudo_tag, /* ua_stylesheet = */ true) { + Ok(pseudo) => pseudo, + Err(pseudo) => { + warn!("stylo: Unable to parse anonymous-box pseudo-element: {}", pseudo); + return parent_or_null(); + } + }; + + + let data = PerDocumentStyleData::borrow_mut_from_raw(raw_data); + + let element = unsafe { GeckoElement::from_raw(match_element) }; + + type Helpers = ArcHelpers; + + match GeckoSelectorImpl::pseudo_element_cascade_type(&pseudo) { + PseudoElementCascadeType::Eager => { + let node = element.as_node(); + let maybe_computed = node.borrow_data() + .and_then(|data| { + data.per_pseudo.get(&pseudo).map(|c| c.clone()) + }); + maybe_computed.map_or_else(parent_or_null, Helpers::from) + } + PseudoElementCascadeType::Lazy => { + Helpers::with(parent_style, |parent| { + data.stylist + .lazily_compute_pseudo_element_style(&element, &pseudo, parent) + .map_or_else(parent_or_null, Helpers::from) + }) + } + PseudoElementCascadeType::Precomputed => { + unreachable!("Anonymous pseudo found in \ + Servo_GetComputedValuesForPseudoElement"); + } + } +} + #[no_mangle] pub extern "C" fn Servo_AddRefComputedValues(ptr: *mut ServoComputedValues) -> () { type Helpers = ArcHelpers;