diff options
author | Martin Robinson <mrobinson@igalia.com> | 2023-06-01 15:18:36 +0200 |
---|---|---|
committer | Martin Robinson <mrobinson@igalia.com> | 2023-06-04 18:12:11 +0200 |
commit | e563927718cc0df65e0ad4eab7d59203ede79b1a (patch) | |
tree | 7f8817f6d171021068cc8b9c85d641f36c809df1 /components/layout_2020/fragment_tree/base_fragment.rs | |
parent | f26d17096d86a2119f879d4ff60c288051a97510 (diff) | |
download | servo-e563927718cc0df65e0ad4eab7d59203ede79b1a.tar.gz servo-e563927718cc0df65e0ad4eab7d59203ede79b1a.zip |
Layout 2020: Move all Fragment code to the `fragment_tree` directory
This is a simple code organization change with no behavior change with
the idea of making Layout 2020 easier to understand by new folks to the
project. The idea is that we will have a cleaner separation between the
different parts of layout ie one directory for the fragment tree and one
(currently multiple) directory for the box tree.
Diffstat (limited to 'components/layout_2020/fragment_tree/base_fragment.rs')
-rw-r--r-- | components/layout_2020/fragment_tree/base_fragment.rs | 117 |
1 files changed, 117 insertions, 0 deletions
diff --git a/components/layout_2020/fragment_tree/base_fragment.rs b/components/layout_2020/fragment_tree/base_fragment.rs new file mode 100644 index 00000000000..d9271a7a0f6 --- /dev/null +++ b/components/layout_2020/fragment_tree/base_fragment.rs @@ -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 + } +} |