/* 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/. */ //! The `Fragment` type, which represents the leaves of the layout tree. use crate::context::LayoutContext; use crate::display_list::items::OpaqueNode; use crate::ServoArc; use app_units::Au; use euclid::default::Rect; use script_layout_interface::wrapper_traits::{PseudoElementType, ThreadSafeLayoutNode}; use serde::ser::{Serialize, SerializeStruct, Serializer}; use style::logical_geometry::{LogicalMargin, LogicalRect}; use style::properties::ComputedValues; use style::selector_parser::RestyleDamage; use style::servo::restyle_damage::ServoRestyleDamage; #[derive(Clone)] pub struct Fragment { pub node: OpaqueNode, pub style: ServoArc, pub border_box: LogicalRect, pub border_padding: LogicalMargin, pub margin: LogicalMargin, pub specific: SpecificFragmentInfo, pub restyle_damage: RestyleDamage, pub pseudo: PseudoElementType, } impl Serialize for Fragment { fn serialize(&self, serializer: S) -> Result { let mut serializer = serializer.serialize_struct("fragment", 3)?; serializer.serialize_field("border_box", &self.border_box)?; serializer.serialize_field("margin", &self.margin)?; serializer.end() } } #[derive(Clone)] pub enum SpecificFragmentInfo { Generic, } impl SpecificFragmentInfo { fn restyle_damage(&self) -> RestyleDamage { RestyleDamage::empty() } } impl Fragment { /// Constructs a new `Fragment` instance. pub fn new( node: &N, specific: SpecificFragmentInfo, ctx: &LayoutContext, ) -> Fragment { let shared_context = ctx.shared_context(); let style = node.style(shared_context); let writing_mode = style.writing_mode; let mut restyle_damage = RestyleDamage::rebuild_and_reflow(); restyle_damage.remove(ServoRestyleDamage::RECONSTRUCT_FLOW); Fragment { node: node.opaque(), style: style, restyle_damage: restyle_damage, border_box: LogicalRect::zero(writing_mode), border_padding: LogicalMargin::zero(writing_mode), margin: LogicalMargin::zero(writing_mode), specific: specific, pseudo: node.get_pseudo_element_type(), } } pub fn restyle_damage(&self) -> RestyleDamage { self.restyle_damage | self.specific.restyle_damage() } pub fn contains_node(&self, node_address: OpaqueNode) -> bool { node_address == self.node } /// Returns the sum of the inline-sizes of all the borders of this fragment. Note that this /// can be expensive to compute, so if possible use the `border_padding` field instead. #[inline] pub fn border_width(&self) -> LogicalMargin { self.style().logical_border_width() } #[inline(always)] pub fn style(&self) -> &ComputedValues { &*self.style } pub fn is_primary_fragment(&self) -> bool { true } } /// A top-down fragment border box iteration handler. pub trait FragmentBorderBoxIterator { /// The operation to perform. fn process(&mut self, fragment: &Fragment, level: i32, overflow: &Rect); /// Returns true if this fragment must be processed in-order. If this returns false, /// we skip the operation for this fragment, but continue processing siblings. fn should_process(&mut self, fragment: &Fragment) -> bool; }