mirror of
https://github.com/servo/servo.git
synced 2025-08-06 22:15:33 +01:00
layout: Add initial support for the ::marker
pseudo-element (#36317)
This change adds support for the `::marker` pseudo-element and ensure that markers are cached into the box tree. This is only initial support, there are a few things missing such as animations, transitions, and support the `content` CSS property. Testing: There are WPT tests for this change. Signed-off-by: Martin Robinson <mrobinson@igalia.com> Signed-off-by: Martin Robinson <mrobinson@igalia.com>
This commit is contained in:
parent
a5c547259f
commit
2b63e60e8f
27 changed files with 282 additions and 276 deletions
|
@ -34,6 +34,7 @@ pub struct InnerDOMLayoutData {
|
|||
pub(super) self_box: ArcRefCell<Option<LayoutBox>>,
|
||||
pub(super) pseudo_before_box: ArcRefCell<Option<LayoutBox>>,
|
||||
pub(super) pseudo_after_box: ArcRefCell<Option<LayoutBox>>,
|
||||
pub(super) pseudo_marker_box: ArcRefCell<Option<LayoutBox>>,
|
||||
}
|
||||
|
||||
/// A box that is stored in one of the `DOMLayoutData` slots.
|
||||
|
@ -222,6 +223,7 @@ where
|
|||
let cell = match pseudo_element_type {
|
||||
PseudoElement::Before => &data.pseudo_before_box,
|
||||
PseudoElement::After => &data.pseudo_after_box,
|
||||
PseudoElement::Marker => &data.pseudo_marker_box,
|
||||
_ => unreachable!(
|
||||
"Asked for box slot for unsupported pseudo-element: {:?}",
|
||||
pseudo_element_type
|
||||
|
@ -235,6 +237,7 @@ where
|
|||
let cell = match pseudo_element_type {
|
||||
PseudoElement::Before => &data.pseudo_before_box,
|
||||
PseudoElement::After => &data.pseudo_after_box,
|
||||
PseudoElement::Marker => &data.pseudo_marker_box,
|
||||
_ => unreachable!(
|
||||
"Asked for box slot for unsupported pseudo-element: {:?}",
|
||||
pseudo_element_type
|
||||
|
@ -248,6 +251,7 @@ where
|
|||
*data.self_box.borrow_mut() = None;
|
||||
*data.pseudo_before_box.borrow_mut() = None;
|
||||
*data.pseudo_after_box.borrow_mut() = None;
|
||||
*data.pseudo_marker_box.borrow_mut() = None;
|
||||
// Stylo already takes care of removing all layout data
|
||||
// for DOM descendants of elements with `display: none`.
|
||||
}
|
||||
|
|
|
@ -236,6 +236,10 @@ fn traverse_element<'dom, Node>(
|
|||
) where
|
||||
Node: NodeExt<'dom>,
|
||||
{
|
||||
// Clear any existing pseudo-element box slot, because markers are not handled like
|
||||
// `::before`` and `::after`. They are processed during box tree creation.
|
||||
element.unset_pseudo_element_box(PseudoElement::Marker);
|
||||
|
||||
let replaced = ReplacedContents::for_element(element, context);
|
||||
let style = element.style(context);
|
||||
match Display::from(style.get_box().display) {
|
||||
|
|
|
@ -393,7 +393,7 @@ where
|
|||
is_list_item: false,
|
||||
},
|
||||
NonReplacedContents::OfPseudoElement(contents).into(),
|
||||
BoxSlot::dummy(),
|
||||
info.node.pseudo_element_box_slot(PseudoElement::Marker),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -405,7 +405,7 @@ where
|
|||
) {
|
||||
self.block_level_boxes.push(BlockLevelJob {
|
||||
info: info.clone(),
|
||||
box_slot: BoxSlot::dummy(),
|
||||
box_slot: info.node.pseudo_element_box_slot(PseudoElement::Marker),
|
||||
kind: BlockLevelCreator::OutsideMarker {
|
||||
contents,
|
||||
list_item_style,
|
||||
|
|
|
@ -19,11 +19,7 @@ pub(crate) fn make_marker<'dom, Node>(
|
|||
where
|
||||
Node: NodeExt<'dom>,
|
||||
{
|
||||
// TODO: use `PseudoElement::Marker` when we add it.
|
||||
let marker_info = info.pseudo(
|
||||
context,
|
||||
style::selector_parser::PseudoElement::ServoLegacyText,
|
||||
)?;
|
||||
let marker_info = info.pseudo(context, style::selector_parser::PseudoElement::Marker)?;
|
||||
let style = &marker_info.style;
|
||||
let list_style = style.get_list();
|
||||
|
||||
|
|
|
@ -131,7 +131,7 @@ pub fn process_resolved_style_request<'dom>(
|
|||
None => layout_element,
|
||||
};
|
||||
|
||||
let style = &*layout_element.resolved_style();
|
||||
let style = &*layout_element.style(context);
|
||||
let longhand_id = match *property {
|
||||
PropertyId::NonCustom(id) => match id.longhand_or_shorthand() {
|
||||
Ok(longhand_id) => longhand_id,
|
||||
|
@ -1122,7 +1122,7 @@ where
|
|||
let element = node.as_element().unwrap();
|
||||
let parent_style = if node.is_connected() {
|
||||
if element.has_data() {
|
||||
node.to_threadsafe().as_element().unwrap().resolved_style()
|
||||
node.to_threadsafe().as_element().unwrap().style(context)
|
||||
} else {
|
||||
let mut tlc = ThreadLocalStyleContext::new();
|
||||
let mut context = StyleContext {
|
||||
|
|
|
@ -1262,6 +1262,7 @@ impl WindowMethods<crate::DomTypeHolder> for Window {
|
|||
Some(PseudoElement::After)
|
||||
},
|
||||
Some(ref pseudo) if pseudo == "::selection" => Some(PseudoElement::Selection),
|
||||
Some(ref pseudo) if pseudo == "::marker" => Some(PseudoElement::Marker),
|
||||
Some(ref pseudo) if pseudo.starts_with(':') => {
|
||||
// Step 3.2: If type is failure, or is a ::slotted() or ::part()
|
||||
// pseudo-element, let obj be null.
|
||||
|
|
|
@ -363,22 +363,6 @@ pub trait ThreadSafeLayoutElement<'dom>:
|
|||
.clone()
|
||||
}
|
||||
|
||||
/// Returns the already resolved style of the node.
|
||||
///
|
||||
/// This differs from `style(ctx)` in that if the pseudo-element has not yet
|
||||
/// been computed it would panic.
|
||||
///
|
||||
/// This should be used just for querying layout, or when we know the
|
||||
/// element style is precomputed, not from general layout itself.
|
||||
#[inline]
|
||||
fn resolved_style(&self) -> Arc<ComputedValues> {
|
||||
let data = self.style_data();
|
||||
match self.pseudo_element() {
|
||||
None => data.styles.primary().clone(),
|
||||
Some(pseudo_element) => data.styles.pseudos.get(&pseudo_element).unwrap().clone(),
|
||||
}
|
||||
}
|
||||
|
||||
fn is_shadow_host(&self) -> bool;
|
||||
|
||||
/// Returns whether this node is a body element of an html element root
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue