style: Implement the body text color quirk in a more straight-forward way.

This avoids grabbing the document when values that inherit from the body,
whatever that means, aren't under the body.

In that case we'll get a semi-random value, but that's also mishandled by Gecko
anyways (and probably Blink, though haven't tested), and doesn't really make
much sense.
This commit is contained in:
Emilio Cobos Álvarez 2017-09-15 10:09:19 +02:00
parent 920585bd74
commit bd314747da
No known key found for this signature in database
GPG key ID: 056B727BB9C1027C
8 changed files with 76 additions and 22 deletions

View file

@ -547,6 +547,14 @@ impl<'le> TElement for ServoLayoutElement<'le> {
}; };
extended_filtering(&element_lang, &*value) extended_filtering(&element_lang, &*value)
} }
fn is_html_document_body_element(&self) -> bool {
// This is only used for the "tables inherit from body" quirk, which we
// don't implement.
//
// FIXME(emilio): We should be able to give the right answer though!
false
}
} }
impl<'le> PartialEq for ServoLayoutElement<'le> { impl<'le> PartialEq for ServoLayoutElement<'le> {

View file

@ -727,6 +727,10 @@ pub trait TElement : Eq + PartialEq + Debug + Hash + Sized + Copy + Clone +
override_lang: Option<Option<AttrValue>>, override_lang: Option<Option<AttrValue>>,
value: &PseudoClassStringArg value: &PseudoClassStringArg
) -> bool; ) -> bool;
/// Returns whether this element is the main body element of the HTML
/// document it is on.
fn is_html_document_body_element(&self) -> bool;
} }
/// TNode and TElement aren't Send because we want to be careful and explicit /// TNode and TElement aren't Send because we want to be careful and explicit

View file

@ -1551,8 +1551,7 @@ extern "C" {
*mut nsCSSCounterStyleRule); *mut nsCSSCounterStyleRule);
} }
extern "C" { extern "C" {
pub fn Gecko_GetBody(pres_context: RawGeckoPresContextBorrowed) pub fn Gecko_IsDocumentBody(element: RawGeckoElementBorrowed) -> bool;
-> RawGeckoElementBorrowedOrNull;
} }
extern "C" { extern "C" {
pub fn Gecko_GetLookAndFeelSystemColor(color_id: i32, pub fn Gecko_GetLookAndFeelSystemColor(color_id: i32,

View file

@ -11,7 +11,7 @@ use cssparser::{CssStringWriter, Parser, RGBA, Token, BasicParseError};
use euclid::ScaleFactor; use euclid::ScaleFactor;
use euclid::Size2D; use euclid::Size2D;
use font_metrics::get_metrics_provider_for_product; use font_metrics::get_metrics_provider_for_product;
use gecko::values::convert_nscolor_to_rgba; use gecko::values::{convert_nscolor_to_rgba, convert_rgba_to_nscolor};
use gecko_bindings::bindings; use gecko_bindings::bindings;
use gecko_bindings::structs; use gecko_bindings::structs;
use gecko_bindings::structs::{nsCSSKeyword, nsCSSProps_KTableEntry, nsCSSValue, nsCSSUnit}; use gecko_bindings::structs::{nsCSSKeyword, nsCSSProps_KTableEntry, nsCSSValue, nsCSSUnit};
@ -27,7 +27,7 @@ use rule_cache::RuleCacheConditions;
use servo_arc::Arc; use servo_arc::Arc;
use std::cell::RefCell; use std::cell::RefCell;
use std::fmt::{self, Write}; use std::fmt::{self, Write};
use std::sync::atomic::{AtomicBool, AtomicIsize, Ordering}; use std::sync::atomic::{AtomicBool, AtomicIsize, AtomicUsize, Ordering};
use str::starts_with_ignore_ascii_case; use str::starts_with_ignore_ascii_case;
use string_cache::Atom; use string_cache::Atom;
use style_traits::{CSSPixel, DevicePixel}; use style_traits::{CSSPixel, DevicePixel};
@ -54,6 +54,11 @@ pub struct Device {
/// the parent to compute everything else. So it is correct to just use /// the parent to compute everything else. So it is correct to just use
/// a relaxed atomic here. /// a relaxed atomic here.
root_font_size: AtomicIsize, root_font_size: AtomicIsize,
/// The body text color, stored as an `nscolor`, used for the "tables
/// inherit from body" quirk.
///
/// https://quirks.spec.whatwg.org/#the-tables-inherit-color-from-body-quirk
body_text_color: AtomicUsize,
/// Whether any styles computed in the document relied on the root font-size /// Whether any styles computed in the document relied on the root font-size
/// by using rem units. /// by using rem units.
used_root_font_size: AtomicBool, used_root_font_size: AtomicBool,
@ -74,6 +79,7 @@ impl Device {
default_values: ComputedValues::default_values(unsafe { &*pres_context }), default_values: ComputedValues::default_values(unsafe { &*pres_context }),
// FIXME(bz): Seems dubious? // FIXME(bz): Seems dubious?
root_font_size: AtomicIsize::new(font_size::get_initial_value().0.to_i32_au() as isize), root_font_size: AtomicIsize::new(font_size::get_initial_value().0.to_i32_au() as isize),
body_text_color: AtomicUsize::new(unsafe { &*pres_context }.mDefaultColor as usize),
used_root_font_size: AtomicBool::new(false), used_root_font_size: AtomicBool::new(false),
used_viewport_size: AtomicBool::new(false), used_viewport_size: AtomicBool::new(false),
} }
@ -110,6 +116,18 @@ impl Device {
self.root_font_size.store(size.0 as isize, Ordering::Relaxed) self.root_font_size.store(size.0 as isize, Ordering::Relaxed)
} }
/// Sets the body text color for the "inherit color from body" quirk.
///
/// https://quirks.spec.whatwg.org/#the-tables-inherit-color-from-body-quirk
pub fn set_body_text_color(&self, color: RGBA) {
self.body_text_color.store(convert_rgba_to_nscolor(&color) as usize, Ordering::Relaxed)
}
/// Returns the body text color.
pub fn body_text_color(&self) -> RGBA {
convert_nscolor_to_rgba(self.body_text_color.load(Ordering::Relaxed) as u32)
}
/// Gets the pres context associated with this document. /// Gets the pres context associated with this document.
pub fn pres_context(&self) -> &nsPresContext { pub fn pres_context(&self) -> &nsPresContext {
unsafe { &*self.pres_context } unsafe { &*self.pres_context }

View file

@ -593,6 +593,10 @@ impl<'le> GeckoElement<'le> {
self.as_node().node_info().mInner.mNamespaceID self.as_node().node_info().mInner.mNamespaceID
} }
fn is_html_element(&self) -> bool {
self.namespace_id() == (structs::root::kNameSpaceID_XHTML as i32)
}
fn is_xul_element(&self) -> bool { fn is_xul_element(&self) -> bool {
self.namespace_id() == (structs::root::kNameSpaceID_XUL as i32) self.namespace_id() == (structs::root::kNameSpaceID_XUL as i32)
} }
@ -1502,6 +1506,18 @@ impl<'le> TElement for GeckoElement<'le> {
Gecko_MatchLang(self.0, override_lang_ptr, override_lang.is_some(), value.as_ptr()) Gecko_MatchLang(self.0, override_lang_ptr, override_lang.is_some(), value.as_ptr())
} }
} }
fn is_html_document_body_element(&self) -> bool {
if self.get_local_name() != &*local_name!("body") {
return false;
}
if !self.is_html_element() {
return false;
}
unsafe { bindings::Gecko_IsDocumentBody(self.0) }
}
} }
impl<'le> PartialEq for GeckoElement<'le> { impl<'le> PartialEq for GeckoElement<'le> {
@ -2011,10 +2027,8 @@ impl<'le> ::selectors::Element for GeckoElement<'le> {
} }
fn is_html_element_in_html_document(&self) -> bool { fn is_html_element_in_html_document(&self) -> bool {
let node = self.as_node(); self.is_html_element() &&
let node_info = node.node_info(); self.as_node().owner_doc().mType == structs::root::nsIDocument_Type::eHTML
node_info.mInner.mNamespaceID == (structs::root::kNameSpaceID_XHTML as i32) &&
node.owner_doc().mType == structs::root::nsIDocument_Type::eHTML
} }
fn ignores_nth_child_selectors(&self) -> bool { fn ignores_nth_child_selectors(&self) -> bool {

View file

@ -7,7 +7,8 @@
#![allow(unsafe_code)] #![allow(unsafe_code)]
#![deny(missing_docs)] #![deny(missing_docs)]
use context::{ElementCascadeInputs, SelectorFlagsMap, SharedStyleContext, StyleContext}; use context::{ElementCascadeInputs, QuirksMode, SelectorFlagsMap};
use context::{SharedStyleContext, StyleContext};
use data::ElementData; use data::ElementData;
use dom::TElement; use dom::TElement;
use invalidation::element::restyle_hints::{RESTYLE_CSS_ANIMATIONS, RESTYLE_CSS_TRANSITIONS}; use invalidation::element::restyle_hints::{RESTYLE_CSS_ANIMATIONS, RESTYLE_CSS_TRANSITIONS};
@ -586,6 +587,21 @@ pub trait MatchMethods : TElement {
} }
} }
if context.shared.stylist.quirks_mode() == QuirksMode::Quirks {
if self.is_html_document_body_element() {
// NOTE(emilio): We _could_ handle dynamic changes to it if it
// changes and before we reach our children the cascade stops,
// but we don't track right now whether we use the document body
// color, and nobody else handles that properly anyway.
let device = context.shared.stylist.device();
// Needed for the "inherit from body" quirk.
let text_color = new_primary_style.get_color().clone_color();
device.set_body_text_color(text_color);
}
}
// Don't accumulate damage if we're in a forgetful traversal. // Don't accumulate damage if we're in a forgetful traversal.
if context.shared.traversal_flags.contains(traversal_flags::Forgetful) { if context.shared.traversal_flags.contains(traversal_flags::Forgetful) {
return ChildCascadeRequirement::MustCascadeChildren; return ChildCascadeRequirement::MustCascadeChildren;

View file

@ -92,6 +92,13 @@ impl Device {
self.root_font_size.store(size.0 as isize, Ordering::Relaxed) self.root_font_size.store(size.0 as isize, Ordering::Relaxed)
} }
/// Sets the body text color for the "inherit color from body" quirk.
///
/// https://quirks.spec.whatwg.org/#the-tables-inherit-color-from-body-quirk
pub fn set_body_text_color(&self, _color: RGBA) {
// Servo doesn't implement this quirk (yet)
}
/// Returns whether we ever looked up the root font size of the Device. /// Returns whether we ever looked up the root font size of the Device.
pub fn used_root_font_size(&self) -> bool { pub fn used_root_font_size(&self) -> bool {
self.used_root_font_size.load(Ordering::Relaxed) self.used_root_font_size.load(Ordering::Relaxed)

View file

@ -289,19 +289,7 @@ impl ToComputedValue for Color {
} }
#[cfg(feature = "gecko")] #[cfg(feature = "gecko")]
Color::InheritFromBodyQuirk => { Color::InheritFromBodyQuirk => {
use dom::TElement; ComputedColor::rgba(context.device().body_text_color())
use gecko::wrapper::GeckoElement;
use gecko_bindings::bindings::Gecko_GetBody;
let pres_context = context.device().pres_context();
let body = unsafe { Gecko_GetBody(pres_context) }.map(GeckoElement);
let data = body.as_ref().and_then(|wrap| wrap.borrow_data());
if let Some(data) = data {
ComputedColor::rgba(data.styles.primary()
.get_color()
.clone_color())
} else {
convert_nscolor_to_computedcolor(pres_context.mDefaultColor)
}
}, },
} }
} }