mirror of
https://github.com/servo/servo.git
synced 2025-08-06 14:10:11 +01:00
Detect body elements during layout
During layout it is often useful, for various specification reasons, to know if an element is the `<body>` element of an `<html>` element root. There are a couple places where a brittle heuristic is used to detect `<body>` elements. This information is going to be even more important to properly handle `<html>` elements that inherit their overflow property from their `<body>` children. Implementing this properly requires updating the DOM wrapper interface. This check does reach up to the parent of thread-safe nodes, but this is essentially the same kind of operation that `parent_style()` does, so is ostensibly safe. This change should not change any behavior and is just a preparation step for properly handle `<body>` overflow.
This commit is contained in:
parent
77a184a0e7
commit
72302e2dae
26 changed files with 487 additions and 277 deletions
117
components/layout_2020/fragment_tree/base.rs
Normal file
117
components/layout_2020/fragment_tree/base.rs
Normal file
|
@ -0,0 +1,117 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use crate::layout_debug::DebugId;
|
||||
use bitflags::bitflags;
|
||||
use gfx_traits::{combine_id_with_fragment_type, FragmentType};
|
||||
use style::dom::OpaqueNode;
|
||||
use style::selector_parser::PseudoElement;
|
||||
|
||||
/// This data structure stores fields that are common to all non-base
|
||||
/// Fragment types and should generally be the first member of all
|
||||
/// concrete fragments.
|
||||
#[derive(Debug, Serialize)]
|
||||
pub(crate) struct BaseFragment {
|
||||
/// A tag which identifies the DOM node and pseudo element of this
|
||||
/// Fragment's content. If this fragment isn't related to any DOM
|
||||
/// node at all, the tag will be None.
|
||||
pub tag: Option<Tag>,
|
||||
|
||||
/// An id used to uniquely identify this Fragment in debug builds.
|
||||
pub debug_id: DebugId,
|
||||
|
||||
/// Flags which various information about this fragment used during
|
||||
/// layout.
|
||||
pub flags: FragmentFlags,
|
||||
}
|
||||
|
||||
impl BaseFragment {
|
||||
pub(crate) fn anonymous() -> Self {
|
||||
BaseFragment {
|
||||
tag: None,
|
||||
debug_id: DebugId::new(),
|
||||
flags: FragmentFlags::empty(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns true if this fragment is non-anonymous and it is for the given
|
||||
/// OpaqueNode, regardless of the pseudo element.
|
||||
pub(crate) fn is_for_node(&self, node: OpaqueNode) -> bool {
|
||||
self.tag.map(|tag| tag.node == node).unwrap_or(false)
|
||||
}
|
||||
}
|
||||
|
||||
/// Information necessary to construct a new BaseFragment.
|
||||
#[derive(Clone, Copy, Debug, Serialize)]
|
||||
pub(crate) struct BaseFragmentInfo {
|
||||
/// The tag to use for the new BaseFragment.
|
||||
pub tag: Tag,
|
||||
|
||||
/// The flags to use for the new BaseFragment.
|
||||
pub flags: FragmentFlags,
|
||||
}
|
||||
|
||||
impl BaseFragmentInfo {
|
||||
pub(crate) fn new_for_node(node: OpaqueNode) -> Self {
|
||||
Self {
|
||||
tag: Tag::new(node),
|
||||
flags: FragmentFlags::empty(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<BaseFragmentInfo> for BaseFragment {
|
||||
fn from(info: BaseFragmentInfo) -> Self {
|
||||
Self {
|
||||
tag: Some(info.tag),
|
||||
debug_id: DebugId::new(),
|
||||
flags: info.flags,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
#[doc = "Flags used to track various information about a DOM node during layout."]
|
||||
#[derive(Serialize)]
|
||||
pub(crate) struct FragmentFlags: u8 {
|
||||
#[doc = "Whether or not this node is a body element on an HTML document."]
|
||||
const IS_BODY_ELEMENT_OF_HTML_ELEMENT_ROOT = 0b00000001;
|
||||
}
|
||||
}
|
||||
|
||||
/// A data structure used to hold DOM and pseudo-element information about
|
||||
/// a particular layout object.
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize)]
|
||||
pub(crate) struct Tag {
|
||||
pub(crate) node: OpaqueNode,
|
||||
pub(crate) pseudo: Option<PseudoElement>,
|
||||
}
|
||||
|
||||
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: None }
|
||||
}
|
||||
|
||||
/// 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: Option<PseudoElement>) -> Self {
|
||||
Tag { node, pseudo }
|
||||
}
|
||||
|
||||
/// Returns true if this tag is for a pseudo element.
|
||||
pub(crate) fn is_pseudo(&self) -> bool {
|
||||
self.pseudo.is_some()
|
||||
}
|
||||
|
||||
pub(crate) fn to_display_list_fragment_id(&self) -> u64 {
|
||||
let fragment_type = match self.pseudo {
|
||||
Some(PseudoElement::Before) => FragmentType::BeforePseudoContent,
|
||||
Some(PseudoElement::After) => FragmentType::AfterPseudoContent,
|
||||
_ => FragmentType::FragmentBody,
|
||||
};
|
||||
combine_id_with_fragment_type(self.node.id() as usize, fragment_type) as u64
|
||||
}
|
||||
}
|
7
components/layout_2020/fragment_tree/mod.rs
Normal file
7
components/layout_2020/fragment_tree/mod.rs
Normal file
|
@ -0,0 +1,7 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
mod base;
|
||||
|
||||
pub(crate) use base::*;
|
Loading…
Add table
Add a link
Reference in a new issue