mirror of
https://github.com/servo/servo.git
synced 2025-09-27 23:30:08 +01:00
layout: Always build Tag
and BaseFragmentInfo
with ServoThreadSafeLayoutNode
(#38680)
This cleanup makes the interface a bit simpler and prevents problems where the pseudo-element information is not passed by accident. Testing: This should not change behavior, so is covered by existing tests. --------- Signed-off-by: Martin Robinson <mrobinson@igalia.com> Signed-off-by: Oriol Brufau <obrufau@igalia.com> Co-authored-by: Oriol Brufau <obrufau@igalia.com>
This commit is contained in:
parent
8743a11ba4
commit
6fdf40dce7
7 changed files with 117 additions and 116 deletions
|
@ -3,11 +3,18 @@
|
|||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use bitflags::bitflags;
|
||||
use layout_api::combine_id_with_fragment_type;
|
||||
use layout_api::wrapper_traits::PseudoElementChain;
|
||||
use html5ever::local_name;
|
||||
use layout_api::wrapper_traits::{
|
||||
PseudoElementChain, ThreadSafeLayoutElement, ThreadSafeLayoutNode,
|
||||
};
|
||||
use layout_api::{LayoutElementType, LayoutNodeType, combine_id_with_fragment_type};
|
||||
use malloc_size_of::malloc_size_of_is_0;
|
||||
use malloc_size_of_derive::MallocSizeOf;
|
||||
use script::layout_dom::ServoThreadSafeLayoutNode;
|
||||
use style::dom::OpaqueNode;
|
||||
use style::selector_parser::PseudoElement;
|
||||
|
||||
use crate::dom_traversal::NodeAndStyleInfo;
|
||||
|
||||
/// This data structure stores fields that are common to all non-base
|
||||
/// Fragment types and should generally be the first member of all
|
||||
|
@ -48,19 +55,84 @@ pub(crate) struct BaseFragmentInfo {
|
|||
}
|
||||
|
||||
impl BaseFragmentInfo {
|
||||
pub(crate) fn new_for_node(node: OpaqueNode) -> Self {
|
||||
Self {
|
||||
tag: Some(Tag::new(node)),
|
||||
flags: FragmentFlags::empty(),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn anonymous() -> Self {
|
||||
Self {
|
||||
tag: None,
|
||||
flags: FragmentFlags::empty(),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn new_for_testing(id: usize) -> Self {
|
||||
Self {
|
||||
tag: Some(Tag {
|
||||
node: OpaqueNode(id),
|
||||
pseudo_element_chain: Default::default(),
|
||||
}),
|
||||
flags: FragmentFlags::empty(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&NodeAndStyleInfo<'_>> for BaseFragmentInfo {
|
||||
fn from(info: &NodeAndStyleInfo) -> Self {
|
||||
info.node.into()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ServoThreadSafeLayoutNode<'_>> for BaseFragmentInfo {
|
||||
fn from(node: ServoThreadSafeLayoutNode) -> Self {
|
||||
let pseudo_element_chain = node.pseudo_element_chain();
|
||||
let mut flags = FragmentFlags::empty();
|
||||
|
||||
// Anonymous boxes should not have a tag, because they should not take part in hit testing.
|
||||
//
|
||||
// TODO(mrobinson): It seems that anonymous boxes should take part in hit testing in some
|
||||
// cases, but currently this means that the order of hit test results isn't as expected for
|
||||
// some WPT tests. This needs more investigation.
|
||||
if matches!(
|
||||
pseudo_element_chain.innermost(),
|
||||
Some(PseudoElement::ServoAnonymousBox) |
|
||||
Some(PseudoElement::ServoAnonymousTable) |
|
||||
Some(PseudoElement::ServoAnonymousTableCell) |
|
||||
Some(PseudoElement::ServoAnonymousTableRow)
|
||||
) {
|
||||
return Self::anonymous();
|
||||
}
|
||||
|
||||
if let Some(element) = node.as_html_element() {
|
||||
if element.is_body_element_of_html_element_root() {
|
||||
flags.insert(FragmentFlags::IS_BODY_ELEMENT_OF_HTML_ELEMENT_ROOT);
|
||||
}
|
||||
|
||||
match element.get_local_name() {
|
||||
&local_name!("br") => {
|
||||
flags.insert(FragmentFlags::IS_BR_ELEMENT);
|
||||
},
|
||||
&local_name!("table") | &local_name!("th") | &local_name!("td") => {
|
||||
flags.insert(FragmentFlags::IS_TABLE_TH_OR_TD_ELEMENT);
|
||||
},
|
||||
_ => {},
|
||||
}
|
||||
|
||||
if matches!(
|
||||
element.type_id(),
|
||||
Some(LayoutNodeType::Element(
|
||||
LayoutElementType::HTMLInputElement | LayoutElementType::HTMLTextAreaElement
|
||||
))
|
||||
) {
|
||||
flags.insert(FragmentFlags::IS_TEXT_CONTROL);
|
||||
}
|
||||
|
||||
if ThreadSafeLayoutElement::is_root(&element) {
|
||||
flags.insert(FragmentFlags::IS_ROOT_ELEMENT);
|
||||
}
|
||||
};
|
||||
|
||||
Self {
|
||||
tag: Some(node.into()),
|
||||
flags,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<BaseFragmentInfo> for BaseFragment {
|
||||
|
@ -118,25 +190,16 @@ pub(crate) struct Tag {
|
|||
}
|
||||
|
||||
impl Tag {
|
||||
/// Create a new Tag for a non-pseudo element. This is mainly used for
|
||||
/// matching existing tags, since it does not accept an `info` argument.
|
||||
pub(crate) fn new(node: OpaqueNode) -> Self {
|
||||
Tag {
|
||||
node,
|
||||
pseudo_element_chain: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a new Tag for a pseudo element. This is mainly used for
|
||||
/// matching existing tags, since it does not accept an `info` argument.
|
||||
pub(crate) fn new_pseudo(node: OpaqueNode, pseudo_element_chain: PseudoElementChain) -> Self {
|
||||
Tag {
|
||||
node,
|
||||
pseudo_element_chain,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn to_display_list_fragment_id(self) -> u64 {
|
||||
combine_id_with_fragment_type(self.node.id(), self.pseudo_element_chain.primary.into())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ServoThreadSafeLayoutNode<'_>> for Tag {
|
||||
fn from(node: ServoThreadSafeLayoutNode<'_>) -> Self {
|
||||
Self {
|
||||
node: node.opaque(),
|
||||
pseudo_element_chain: node.pseudo_element_chain(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue