mirror of
https://github.com/servo/servo.git
synced 2025-08-10 07:55:33 +01:00
Auto merge of #17032 - jryans:stylo-visited, r=emilio
Stylo: visited pseudo-class support Reviewed in https://bugzilla.mozilla.org/show_bug.cgi?id=1328509 <!-- 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/17032) <!-- Reviewable:end -->
This commit is contained in:
commit
1f323f8848
18 changed files with 1016 additions and 236 deletions
|
@ -100,6 +100,11 @@ pub struct ComputedValues {
|
|||
pub font_size_keyword: Option<(longhands::font_size::KeywordSize, f32)>,
|
||||
/// The cached system font. See longhand/font.mako.rs
|
||||
pub cached_system_font: Option<longhands::system_font::ComputedSystemFont>,
|
||||
|
||||
/// The element's computed values if visited, only computed if there's a
|
||||
/// relevant link for this element. A element's "relevant link" is the
|
||||
/// element being matched if it is a link or the nearest ancestor link.
|
||||
visited_style: Option<Arc<ComputedValues>>,
|
||||
}
|
||||
|
||||
impl ComputedValues {
|
||||
|
@ -107,6 +112,7 @@ impl ComputedValues {
|
|||
writing_mode: WritingMode,
|
||||
root_font_size: Au,
|
||||
font_size_keyword: Option<(longhands::font_size::KeywordSize, f32)>,
|
||||
visited_style: Option<Arc<ComputedValues>>,
|
||||
% for style_struct in data.style_structs:
|
||||
${style_struct.ident}: Arc<style_structs::${style_struct.name}>,
|
||||
% endfor
|
||||
|
@ -117,6 +123,7 @@ impl ComputedValues {
|
|||
root_font_size: root_font_size,
|
||||
cached_system_font: None,
|
||||
font_size_keyword: font_size_keyword,
|
||||
visited_style: visited_style,
|
||||
% for style_struct in data.style_structs:
|
||||
${style_struct.ident}: ${style_struct.ident},
|
||||
% endfor
|
||||
|
@ -130,6 +137,7 @@ impl ComputedValues {
|
|||
root_font_size: longhands::font_size::get_initial_value(), // FIXME(bz): Also seems dubious?
|
||||
font_size_keyword: Some((Default::default(), 1.)),
|
||||
cached_system_font: None,
|
||||
visited_style: None,
|
||||
% for style_struct in data.style_structs:
|
||||
${style_struct.ident}: style_structs::${style_struct.name}::default(pres_context),
|
||||
% endfor
|
||||
|
@ -168,6 +176,23 @@ impl ComputedValues {
|
|||
}
|
||||
% endfor
|
||||
|
||||
/// Gets a reference to the visited computed values, if any.
|
||||
pub fn get_visited_style(&self) -> Option<<&Arc<ComputedValues>> {
|
||||
self.visited_style.as_ref()
|
||||
}
|
||||
|
||||
/// Gets a reference to the visited computed values. Panic if the element
|
||||
/// does not have visited computed values.
|
||||
pub fn visited_style(&self) -> &Arc<ComputedValues> {
|
||||
self.get_visited_style().unwrap()
|
||||
}
|
||||
|
||||
/// Clone the visited computed values Arc. Used for inheriting parent styles
|
||||
/// in StyleBuilder::for_inheritance.
|
||||
pub fn clone_visited_style(&self) -> Option<Arc<ComputedValues>> {
|
||||
self.visited_style.clone()
|
||||
}
|
||||
|
||||
pub fn custom_properties(&self) -> Option<Arc<ComputedValuesMap>> {
|
||||
self.custom_properties.clone()
|
||||
}
|
||||
|
|
|
@ -576,6 +576,57 @@ impl LonghandId {
|
|||
% endfor
|
||||
}
|
||||
}
|
||||
|
||||
/// Only a few properties are allowed to depend on the visited state of
|
||||
/// links. When cascading visited styles, we can save time by only
|
||||
/// processing these properties.
|
||||
fn is_visited_dependent(&self) -> bool {
|
||||
matches!(*self,
|
||||
% if product == "gecko":
|
||||
LonghandId::ColumnRuleColor |
|
||||
LonghandId::TextEmphasisColor |
|
||||
LonghandId::WebkitTextFillColor |
|
||||
LonghandId::WebkitTextStrokeColor |
|
||||
LonghandId::TextDecorationColor |
|
||||
LonghandId::Fill |
|
||||
LonghandId::Stroke |
|
||||
LonghandId::CaretColor |
|
||||
% endif
|
||||
LonghandId::Color |
|
||||
LonghandId::BackgroundColor |
|
||||
LonghandId::BorderTopColor |
|
||||
LonghandId::BorderRightColor |
|
||||
LonghandId::BorderBottomColor |
|
||||
LonghandId::BorderLeftColor |
|
||||
LonghandId::OutlineColor
|
||||
)
|
||||
}
|
||||
|
||||
/// The computed value of some properties depends on the (sometimes
|
||||
/// computed) value of *other* properties.
|
||||
///
|
||||
/// So we classify properties into "early" and "other", such that the only
|
||||
/// dependencies can be from "other" to "early".
|
||||
///
|
||||
/// Unfortunately, it’s not easy to check that this classification is
|
||||
/// correct.
|
||||
fn is_early_property(&self) -> bool {
|
||||
matches!(*self,
|
||||
% if product == 'gecko':
|
||||
LonghandId::TextOrientation |
|
||||
LonghandId::AnimationName |
|
||||
LonghandId::TransitionProperty |
|
||||
LonghandId::XLang |
|
||||
LonghandId::MozScriptLevel |
|
||||
% endif
|
||||
LonghandId::FontSize |
|
||||
LonghandId::FontFamily |
|
||||
LonghandId::Color |
|
||||
LonghandId::TextDecorationLine |
|
||||
LonghandId::WritingMode |
|
||||
LonghandId::Direction
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// An identifier for a given shorthand property.
|
||||
|
@ -1743,6 +1794,11 @@ pub struct ComputedValues {
|
|||
pub root_font_size: Au,
|
||||
/// The keyword behind the current font-size property, if any
|
||||
pub font_size_keyword: Option<(longhands::font_size::KeywordSize, f32)>,
|
||||
|
||||
/// The element's computed values if visited, only computed if there's a
|
||||
/// relevant link for this element. A element's "relevant link" is the
|
||||
/// element being matched if it is a link or the nearest ancestor link.
|
||||
visited_style: Option<Arc<ComputedValues>>,
|
||||
}
|
||||
|
||||
#[cfg(feature = "servo")]
|
||||
|
@ -1752,6 +1808,7 @@ impl ComputedValues {
|
|||
writing_mode: WritingMode,
|
||||
root_font_size: Au,
|
||||
font_size_keyword: Option<(longhands::font_size::KeywordSize, f32)>,
|
||||
visited_style: Option<Arc<ComputedValues>>,
|
||||
% for style_struct in data.active_style_structs():
|
||||
${style_struct.ident}: Arc<style_structs::${style_struct.name}>,
|
||||
% endfor
|
||||
|
@ -1761,6 +1818,7 @@ impl ComputedValues {
|
|||
writing_mode: writing_mode,
|
||||
root_font_size: root_font_size,
|
||||
font_size_keyword: font_size_keyword,
|
||||
visited_style: visited_style,
|
||||
% for style_struct in data.active_style_structs():
|
||||
${style_struct.ident}: ${style_struct.ident},
|
||||
% endfor
|
||||
|
@ -1796,6 +1854,23 @@ impl ComputedValues {
|
|||
}
|
||||
% endfor
|
||||
|
||||
/// Gets a reference to the visited computed values, if any.
|
||||
pub fn get_visited_style(&self) -> Option<<&Arc<ComputedValues>> {
|
||||
self.visited_style.as_ref()
|
||||
}
|
||||
|
||||
/// Gets a reference to the visited computed values. Panic if the element
|
||||
/// does not have visited computed values.
|
||||
pub fn visited_style(&self) -> &Arc<ComputedValues> {
|
||||
self.get_visited_style().unwrap()
|
||||
}
|
||||
|
||||
/// Clone the visited computed values Arc. Used for inheriting parent styles
|
||||
/// in StyleBuilder::for_inheritance.
|
||||
pub fn clone_visited_style(&self) -> Option<Arc<ComputedValues>> {
|
||||
self.visited_style.clone()
|
||||
}
|
||||
|
||||
/// Get the custom properties map if necessary.
|
||||
///
|
||||
/// Cloning the Arc here is fine because it only happens in the case where
|
||||
|
@ -2183,6 +2258,10 @@ pub struct StyleBuilder<'a> {
|
|||
pub root_font_size: Au,
|
||||
/// The keyword behind the current font-size property, if any.
|
||||
pub font_size_keyword: Option<(longhands::font_size::KeywordSize, f32)>,
|
||||
/// The element's style if visited, only computed if there's a relevant link
|
||||
/// for this element. A element's "relevant link" is the element being
|
||||
/// matched if it is a link or the nearest ancestor link.
|
||||
visited_style: Option<Arc<ComputedValues>>,
|
||||
% for style_struct in data.active_style_structs():
|
||||
${style_struct.ident}: StyleStructRef<'a, style_structs::${style_struct.name}>,
|
||||
% endfor
|
||||
|
@ -2195,6 +2274,7 @@ impl<'a> StyleBuilder<'a> {
|
|||
writing_mode: WritingMode,
|
||||
root_font_size: Au,
|
||||
font_size_keyword: Option<(longhands::font_size::KeywordSize, f32)>,
|
||||
visited_style: Option<Arc<ComputedValues>>,
|
||||
% for style_struct in data.active_style_structs():
|
||||
${style_struct.ident}: &'a Arc<style_structs::${style_struct.name}>,
|
||||
% endfor
|
||||
|
@ -2204,6 +2284,7 @@ impl<'a> StyleBuilder<'a> {
|
|||
writing_mode: writing_mode,
|
||||
root_font_size: root_font_size,
|
||||
font_size_keyword: font_size_keyword,
|
||||
visited_style: visited_style,
|
||||
% for style_struct in data.active_style_structs():
|
||||
${style_struct.ident}: StyleStructRef::Borrowed(${style_struct.ident}),
|
||||
% endfor
|
||||
|
@ -2223,6 +2304,7 @@ impl<'a> StyleBuilder<'a> {
|
|||
parent.writing_mode,
|
||||
parent.root_font_size,
|
||||
parent.font_size_keyword,
|
||||
parent.clone_visited_style(),
|
||||
% for style_struct in data.active_style_structs():
|
||||
% if style_struct.inherited:
|
||||
parent.${style_struct.name_lower}_arc(),
|
||||
|
@ -2296,6 +2378,7 @@ impl<'a> StyleBuilder<'a> {
|
|||
self.writing_mode,
|
||||
self.root_font_size,
|
||||
self.font_size_keyword,
|
||||
self.visited_style,
|
||||
% for style_struct in data.active_style_structs():
|
||||
self.${style_struct.ident}.build(),
|
||||
% endfor
|
||||
|
@ -2339,6 +2422,7 @@ mod lazy_static_module {
|
|||
writing_mode: WritingMode::empty(),
|
||||
root_font_size: longhands::font_size::get_initial_value(),
|
||||
font_size_keyword: Some((Default::default(), 1.)),
|
||||
visited_style: None,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -2370,6 +2454,8 @@ bitflags! {
|
|||
/// Whether to skip any root element and flex/grid item display style
|
||||
/// fixup.
|
||||
const SKIP_ROOT_AND_ITEM_BASED_DISPLAY_FIXUP = 0x02,
|
||||
/// Whether to only cascade properties that are visited dependent.
|
||||
const VISITED_DEPENDENT_ONLY = 0x04,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2392,6 +2478,7 @@ pub fn cascade(device: &Device,
|
|||
guards: &StylesheetGuards,
|
||||
parent_style: Option<<&ComputedValues>,
|
||||
layout_parent_style: Option<<&ComputedValues>,
|
||||
visited_style: Option<Arc<ComputedValues>>,
|
||||
cascade_info: Option<<&mut CascadeInfo>,
|
||||
error_reporter: &ParseErrorReporter,
|
||||
font_metrics_provider: &FontMetricsProvider,
|
||||
|
@ -2438,6 +2525,7 @@ pub fn cascade(device: &Device,
|
|||
iter_declarations,
|
||||
inherited_style,
|
||||
layout_parent_style,
|
||||
visited_style,
|
||||
cascade_info,
|
||||
error_reporter,
|
||||
font_metrics_provider,
|
||||
|
@ -2453,6 +2541,7 @@ pub fn apply_declarations<'a, F, I>(device: &Device,
|
|||
iter_declarations: F,
|
||||
inherited_style: &ComputedValues,
|
||||
layout_parent_style: &ComputedValues,
|
||||
visited_style: Option<Arc<ComputedValues>>,
|
||||
mut cascade_info: Option<<&mut CascadeInfo>,
|
||||
error_reporter: &ParseErrorReporter,
|
||||
font_metrics_provider: &FontMetricsProvider,
|
||||
|
@ -2483,6 +2572,7 @@ pub fn apply_declarations<'a, F, I>(device: &Device,
|
|||
WritingMode::empty(),
|
||||
inherited_style.root_font_size,
|
||||
inherited_style.font_size_keyword,
|
||||
visited_style,
|
||||
% for style_struct in data.active_style_structs():
|
||||
% if style_struct.inherited:
|
||||
inherited_style.${style_struct.name_lower}_arc(),
|
||||
|
@ -2496,6 +2586,7 @@ pub fn apply_declarations<'a, F, I>(device: &Device,
|
|||
WritingMode::empty(),
|
||||
inherited_style.root_font_size,
|
||||
inherited_style.font_size_keyword,
|
||||
visited_style,
|
||||
% for style_struct in data.active_style_structs():
|
||||
inherited_style.${style_struct.name_lower}_arc(),
|
||||
% endfor
|
||||
|
@ -2544,6 +2635,14 @@ pub fn apply_declarations<'a, F, I>(device: &Device,
|
|||
PropertyDeclarationId::Custom(..) => continue,
|
||||
};
|
||||
|
||||
// Only a few properties are allowed to depend on the visited state
|
||||
// of links. When cascading visited styles, we can save time by
|
||||
// only processing these properties.
|
||||
if flags.contains(VISITED_DEPENDENT_ONLY) &&
|
||||
!longhand_id.is_visited_dependent() {
|
||||
continue
|
||||
}
|
||||
|
||||
// The computed value of some properties depends on the
|
||||
// (sometimes computed) value of *other* properties.
|
||||
//
|
||||
|
@ -2555,26 +2654,11 @@ pub fn apply_declarations<'a, F, I>(device: &Device,
|
|||
//
|
||||
// Unfortunately, it’s not easy to check that this
|
||||
// classification is correct.
|
||||
let is_early_property = matches!(longhand_id,
|
||||
LonghandId::FontSize |
|
||||
LonghandId::FontFamily |
|
||||
LonghandId::Color |
|
||||
LonghandId::TextDecorationLine |
|
||||
LonghandId::WritingMode |
|
||||
LonghandId::Direction
|
||||
% if product == 'gecko':
|
||||
| LonghandId::TextOrientation
|
||||
| LonghandId::AnimationName
|
||||
| LonghandId::TransitionProperty
|
||||
| LonghandId::XLang
|
||||
| LonghandId::MozScriptLevel
|
||||
% endif
|
||||
);
|
||||
if
|
||||
% if category_to_cascade_now == "early":
|
||||
!
|
||||
% endif
|
||||
is_early_property
|
||||
longhand_id.is_early_property()
|
||||
{
|
||||
continue
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue