style: Move the RELEVANT_LINK_VISITED flag to servo.

And kill one GetParentAllowServo call while at it, and some other dumbness...

Bug: 1383307
Reviewed-by: Manishearth
This commit is contained in:
Emilio Cobos Álvarez 2017-07-23 04:50:08 +02:00
parent d0561e76df
commit 4e0492c5d1
No known key found for this signature in database
GPG key ID: 056B727BB9C1027C
7 changed files with 64 additions and 8 deletions

View file

@ -550,6 +550,11 @@ pub trait TElement : Eq + PartialEq + Debug + Hash + Sized + Copy + Clone +
unsafe fn unset_animation_only_dirty_descendants(&self) { unsafe fn unset_animation_only_dirty_descendants(&self) {
} }
/// Returns true if this element is a visited link.
///
/// Servo doesn't support visited styles yet.
fn is_visited_link(&self) -> bool { false }
/// Returns true if this element is native anonymous (only Gecko has native /// Returns true if this element is native anonymous (only Gecko has native
/// anonymous content). /// anonymous content).
fn is_native_anonymous(&self) -> bool { false } fn is_native_anonymous(&self) -> bool { false }

View file

@ -1011,6 +1011,11 @@ impl<'le> TElement for GeckoElement<'le> {
self.unset_flags(ELEMENT_HAS_ANIMATION_ONLY_DIRTY_DESCENDANTS_FOR_SERVO as u32) self.unset_flags(ELEMENT_HAS_ANIMATION_ONLY_DIRTY_DESCENDANTS_FOR_SERVO as u32)
} }
fn is_visited_link(&self) -> bool {
use element_state::IN_VISITED_STATE;
self.get_state().intersects(IN_VISITED_STATE)
}
fn is_native_anonymous(&self) -> bool { fn is_native_anonymous(&self) -> bool {
self.flags() & (NODE_IS_NATIVE_ANONYMOUS as u32) != 0 self.flags() & (NODE_IS_NATIVE_ANONYMOUS as u32) != 0
} }

View file

@ -33,5 +33,9 @@ bitflags! {
/// ///
/// This is used from Gecko's layout engine. /// This is used from Gecko's layout engine.
const IS_TEXT_COMBINED = 1 << 2, const IS_TEXT_COMBINED = 1 << 2,
/// A flag used to mark styles under a relevant link that is also
/// visited.
const IS_RELEVANT_LINK_VISITED = 1 << 3,
} }
} }

View file

@ -2650,6 +2650,11 @@ impl<'a> StyleBuilder<'a> {
) )
} }
/// Returns whether we have a visited style.
pub fn has_visited_style(&self) -> bool {
self.visited_style.is_some()
}
/// Returns the style we're inheriting from. /// Returns the style we're inheriting from.
pub fn inherited_style(&self) -> &'a ComputedValues { pub fn inherited_style(&self) -> &'a ComputedValues {
self.inherited_style self.inherited_style
@ -2805,14 +2810,14 @@ bitflags! {
pub flags CascadeFlags: u8 { pub flags CascadeFlags: u8 {
/// Whether to inherit all styles from the parent. If this flag is not /// Whether to inherit all styles from the parent. If this flag is not
/// present, non-inherited styles are reset to their initial values. /// present, non-inherited styles are reset to their initial values.
const INHERIT_ALL = 0x01, const INHERIT_ALL = 1,
/// Whether to skip any display style fixup for root element, flex/grid /// Whether to skip any display style fixup for root element, flex/grid
/// item, and ruby descendants. /// item, and ruby descendants.
const SKIP_ROOT_AND_ITEM_BASED_DISPLAY_FIXUP = 0x02, const SKIP_ROOT_AND_ITEM_BASED_DISPLAY_FIXUP = 1 << 1,
/// Whether to only cascade properties that are visited dependent. /// Whether to only cascade properties that are visited dependent.
const VISITED_DEPENDENT_ONLY = 0x04, const VISITED_DEPENDENT_ONLY = 1 << 2,
/// Whether the given element we're styling is the document element, /// Whether the given element we're styling is the document element,
/// that is, matches :root. /// that is, matches :root.
@ -2822,15 +2827,19 @@ bitflags! {
/// ///
/// This affects some style adjustments, like blockification, and means /// This affects some style adjustments, like blockification, and means
/// that it may affect global state, like the Device's root font-size. /// that it may affect global state, like the Device's root font-size.
const IS_ROOT_ELEMENT = 0x08, const IS_ROOT_ELEMENT = 1 << 3,
/// Whether to convert display:contents into display:inline. This /// Whether to convert display:contents into display:inline. This
/// is used by Gecko to prevent display:contents on generated /// is used by Gecko to prevent display:contents on generated
/// content. /// content.
const PROHIBIT_DISPLAY_CONTENTS = 0x10, const PROHIBIT_DISPLAY_CONTENTS = 1 << 4,
/// Whether we're styling the ::-moz-fieldset-content anonymous box. /// Whether we're styling the ::-moz-fieldset-content anonymous box.
const IS_FIELDSET_CONTENT = 0x20, const IS_FIELDSET_CONTENT = 1 << 5,
/// Whether we're computing the style of a link element that happens to
/// be visited.
const IS_VISITED_LINK = 1 << 6,
} }
} }

View file

@ -426,14 +426,39 @@ impl<'a, 'b: 'a> StyleAdjuster<'a, 'b> {
} }
} }
/// Computes the RELEVANT_LINK_VISITED flag based on the parent style and on
/// whether we're a relevant link.
///
/// NOTE(emilio): We don't do this for text styles, which is... dubious, but
/// Gecko doesn't seem to do it either. It's extremely easy to do if needed
/// though.
///
/// FIXME(emilio): This isn't technically a style adjustment thingie, could
/// it move somewhere else?
fn adjust_for_visited(&mut self, flags: CascadeFlags) {
use properties::IS_VISITED_LINK;
use properties::computed_value_flags::IS_RELEVANT_LINK_VISITED;
if !self.style.has_visited_style() {
return;
}
if flags.contains(IS_VISITED_LINK) ||
self.style.inherited_style().flags.contains(IS_RELEVANT_LINK_VISITED) {
self.style.flags.insert(IS_RELEVANT_LINK_VISITED);
}
}
/// Adjusts the style to account for various fixups that don't fit naturally /// Adjusts the style to account for various fixups that don't fit naturally
/// into the cascade. /// into the cascade.
/// ///
/// When comparing to Gecko, this is similar to the work done by /// When comparing to Gecko, this is similar to the work done by
/// `nsStyleContext::ApplyStyleFixups`. /// `nsStyleContext::ApplyStyleFixups`, plus some parts of
/// `nsStyleSet::GetContext`.
pub fn adjust(&mut self, pub fn adjust(&mut self,
layout_parent_style: &ComputedValues, layout_parent_style: &ComputedValues,
flags: CascadeFlags) { flags: CascadeFlags) {
self.adjust_for_visited(flags);
#[cfg(feature = "gecko")] #[cfg(feature = "gecko")]
{ {
self.adjust_for_prohibited_display_contents(flags); self.adjust_for_prohibited_display_contents(flags);

View file

@ -12,7 +12,7 @@ use dom::TElement;
use log::LogLevel::Trace; use log::LogLevel::Trace;
use matching::{CascadeVisitedMode, MatchMethods}; use matching::{CascadeVisitedMode, MatchMethods};
use properties::{AnimationRules, CascadeFlags, ComputedValues}; use properties::{AnimationRules, CascadeFlags, ComputedValues};
use properties::{IS_ROOT_ELEMENT, PROHIBIT_DISPLAY_CONTENTS, SKIP_ROOT_AND_ITEM_BASED_DISPLAY_FIXUP}; use properties::{IS_ROOT_ELEMENT, IS_VISITED_LINK, PROHIBIT_DISPLAY_CONTENTS, SKIP_ROOT_AND_ITEM_BASED_DISPLAY_FIXUP};
use properties::{VISITED_DEPENDENT_ONLY, cascade}; use properties::{VISITED_DEPENDENT_ONLY, cascade};
use rule_tree::StrongRuleNode; use rule_tree::StrongRuleNode;
use selector_parser::{PseudoElement, SelectorImpl}; use selector_parser::{PseudoElement, SelectorImpl};
@ -473,6 +473,11 @@ where
if self.element.skip_root_and_item_based_display_fixup() { if self.element.skip_root_and_item_based_display_fixup() {
cascade_flags.insert(SKIP_ROOT_AND_ITEM_BASED_DISPLAY_FIXUP); cascade_flags.insert(SKIP_ROOT_AND_ITEM_BASED_DISPLAY_FIXUP);
} }
if pseudo.is_none() && self.element.is_visited_link() {
cascade_flags.insert(IS_VISITED_LINK);
}
if cascade_visited.visited_dependent_only() { if cascade_visited.visited_dependent_only() {
// If this element is a link, we want its visited style to inherit // If this element is a link, we want its visited style to inherit
// from the regular style of its parent, because only the // from the regular style of its parent, because only the

View file

@ -1736,6 +1736,9 @@ pub extern "C" fn Servo_ComputedValues_GetStyleBits(values: ServoStyleContextBor
use style::properties::computed_value_flags::*; use style::properties::computed_value_flags::*;
let flags = values.flags; let flags = values.flags;
let mut result = 0; let mut result = 0;
if flags.contains(IS_RELEVANT_LINK_VISITED) {
result |= structs::NS_STYLE_RELEVANT_LINK_VISITED as u64;
}
if flags.contains(HAS_TEXT_DECORATION_LINES) { if flags.contains(HAS_TEXT_DECORATION_LINES) {
result |= structs::NS_STYLE_HAS_TEXT_DECORATION_LINES as u64; result |= structs::NS_STYLE_HAS_TEXT_DECORATION_LINES as u64;
} }