mirror of
https://github.com/servo/servo.git
synced 2025-06-06 16:45:39 +00:00
While <https://drafts.csswg.org/css-lists/#list-style-position-property> says: > The size or contents of the marker box may affect the height of the > principal block box and/or the height of its first line box, and in some > cases may cause the creation of a new line box; this interaction is also > not defined. All other browsers ensure that the first line of list item content is the same block size as the marker. Doing this is complicated, but we can ensure that the entire list item is at least as tall as the marker. This should handle the majority of cases and we can make refinements later for stranger situations, such as when the marker is very tall. Co-authored-by: Oriol Brufau <obrufau@igalia.com>
134 lines
4.5 KiB
Rust
134 lines
4.5 KiB
Rust
/* 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 bitflags::bitflags;
|
|
use gfx_traits::{combine_id_with_fragment_type, FragmentType};
|
|
use serde::Serialize;
|
|
use style::dom::OpaqueNode;
|
|
use style::selector_parser::PseudoElement;
|
|
|
|
use crate::layout_debug::DebugId;
|
|
|
|
/// 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, if it is not an anonymous Fragment.
|
|
pub tag: Option<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: Some(Tag::new(node)),
|
|
flags: FragmentFlags::empty(),
|
|
}
|
|
}
|
|
|
|
pub(crate) fn anonymous() -> Self {
|
|
Self {
|
|
tag: None,
|
|
flags: FragmentFlags::empty(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl From<BaseFragmentInfo> for BaseFragment {
|
|
fn from(info: BaseFragmentInfo) -> Self {
|
|
Self {
|
|
tag: info.tag,
|
|
debug_id: DebugId::new(),
|
|
flags: info.flags,
|
|
}
|
|
}
|
|
}
|
|
|
|
bitflags! {
|
|
/// Flags used to track various information about a DOM node during layout.
|
|
#[derive(Clone, Copy, Debug, Serialize)]
|
|
pub(crate) struct FragmentFlags: u8 {
|
|
/// Whether or not the node that created this fragment is a `<body>` element on an HTML document.
|
|
const IS_BODY_ELEMENT_OF_HTML_ELEMENT_ROOT = 0b00000001;
|
|
/// Whether or not the node that created this Fragment is a `<br>` element.
|
|
const IS_BR_ELEMENT = 0b00000010;
|
|
/// Whether or not this Fragment was created to contain a replaced element or is
|
|
/// a replaced element.
|
|
const IS_REPLACED = 0b00000100;
|
|
/// Whether or not this Fragment was created to contain a list item marker
|
|
/// with a used value of `list-style-position: outside`.
|
|
const IS_OUTSIDE_LIST_ITEM_MARKER = 0b00001000;
|
|
}
|
|
}
|
|
|
|
/// 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(), fragment_type)
|
|
}
|
|
}
|