Skip to main content

layout/
lib.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
5#![deny(unsafe_code)]
6
7//! Layout. Performs layout on the DOM, builds display lists and sends them to be
8//! painted.
9
10mod accessibility;
11mod cell;
12mod context;
13mod display_list;
14mod dom;
15mod dom_traversal;
16mod flexbox;
17pub mod flow;
18mod formatting_contexts;
19mod fragment_tree;
20pub mod geom;
21mod layout_box_base;
22mod layout_impl;
23mod taffy;
24#[macro_use]
25mod construct_modern;
26mod layout_root;
27mod lists;
28mod positioned;
29mod query;
30mod quotes;
31mod replaced;
32mod selection;
33mod sizing;
34mod style_ext;
35pub mod table;
36mod traversal;
37
38use app_units::Au;
39pub use cell::ArcRefCell;
40pub(crate) use flow::BoxTree;
41pub(crate) use fragment_tree::FragmentTree;
42pub use layout_impl::LayoutFactoryImpl;
43use malloc_size_of_derive::MallocSizeOf;
44use servo_arc::Arc as ServoArc;
45use style::logical_geometry::WritingMode;
46use style::properties::ComputedValues;
47
48use crate::geom::LogicalVec2;
49use crate::sizing::SizeConstraint;
50use crate::style_ext::AspectRatio;
51
52/// At times, a style is "owned" by more than one layout object. For example, text
53/// fragments need a handle on their parent inline box's style. In order to make
54/// incremental layout easier to implement, another layer of shared ownership is added via
55/// [`SharedStyle`]. This allows updating the style in originating layout object and
56/// having all "depdendent" objects update automatically.
57///
58///  Note that this is not a cost-free data structure, so should only be
59/// used when necessary.
60pub(crate) type SharedStyle = ArcRefCell<ServoArc<ComputedValues>>;
61
62/// Represents the set of constraints that we use when computing the min-content
63/// and max-content inline sizes of an element.
64pub(crate) struct ConstraintSpace<'a> {
65    pub block_size: SizeConstraint,
66    pub style: &'a ComputedValues,
67    pub preferred_aspect_ratio: Option<AspectRatio>,
68}
69
70impl<'a> ConstraintSpace<'a> {
71    fn new(
72        block_size: SizeConstraint,
73        style: &'a ComputedValues,
74        preferred_aspect_ratio: Option<AspectRatio>,
75    ) -> Self {
76        Self {
77            block_size,
78            style,
79            preferred_aspect_ratio,
80        }
81    }
82}
83
84#[inline]
85fn stretch_size(size: Option<Au>, pbm_sum: Au) -> Option<Au> {
86    size.map(|size| Au(0).max(size - pbm_sum))
87}
88
89/// A variant of [`ContainingBlock`] that allows an indefinite inline size.
90/// Useful for code that is shared for both layout (where we know the inline size
91/// of the containing block) and intrinsic sizing (where we don't know it).
92pub(crate) struct IndefiniteContainingBlock<'a> {
93    pub size: LogicalVec2<Option<Au>>,
94    pub style: &'a ComputedValues,
95}
96
97impl IndefiniteContainingBlock<'_> {
98    #[inline]
99    fn block_stretch_size(&self, block_pbm_sum: Au) -> Option<Au> {
100        stretch_size(self.size.block, block_pbm_sum)
101    }
102}
103
104impl<'a> From<&ConstraintSpace<'a>> for IndefiniteContainingBlock<'a> {
105    fn from(constraint_space: &ConstraintSpace<'a>) -> Self {
106        Self {
107            size: LogicalVec2 {
108                inline: None,
109                block: constraint_space.block_size.to_definite(),
110            },
111            style: constraint_space.style,
112        }
113    }
114}
115
116impl<'a> From<&'_ ContainingBlock<'a>> for IndefiniteContainingBlock<'a> {
117    fn from(containing_block: &ContainingBlock<'a>) -> Self {
118        Self {
119            size: LogicalVec2 {
120                inline: Some(containing_block.size.inline),
121                block: containing_block.size.block.to_definite(),
122            },
123            style: containing_block.style,
124        }
125    }
126}
127
128impl<'a> From<&'_ DefiniteContainingBlock<'a>> for IndefiniteContainingBlock<'a> {
129    fn from(containing_block: &DefiniteContainingBlock<'a>) -> Self {
130        Self {
131            size: containing_block.size.map(|v| Some(*v)),
132            style: containing_block.style,
133        }
134    }
135}
136
137#[derive(Clone, Debug, MallocSizeOf, PartialEq)]
138pub(crate) struct ContainingBlockSize {
139    inline: Au,
140    block: SizeConstraint,
141}
142
143pub(crate) struct ContainingBlock<'a> {
144    size: ContainingBlockSize,
145    style: &'a ComputedValues,
146}
147
148impl ContainingBlock<'_> {
149    #[inline]
150    fn inline_stretch_size(&self, inline_pbm_sum: Au) -> Option<Au> {
151        stretch_size(Some(self.size.inline), inline_pbm_sum)
152    }
153
154    #[inline]
155    fn block_stretch_size(&self, block_pbm_sum: Au) -> Option<Au> {
156        stretch_size(self.size.block.to_definite(), block_pbm_sum)
157    }
158}
159
160struct DefiniteContainingBlock<'a> {
161    size: LogicalVec2<Au>,
162    style: &'a ServoArc<ComputedValues>,
163}
164
165impl<'a> From<&'_ DefiniteContainingBlock<'a>> for ContainingBlock<'a> {
166    fn from(definite: &DefiniteContainingBlock<'a>) -> Self {
167        ContainingBlock {
168            size: ContainingBlockSize {
169                inline: definite.size.inline,
170                block: SizeConstraint::Definite(definite.size.block),
171            },
172            style: definite.style,
173        }
174    }
175}
176
177/// Data that is propagated from ancestors to descendants during [`crate::flow::BoxTree`]
178/// construction.  This allows data to flow in the reverse direction of the typical layout
179/// propoagation, but only during `BoxTree` construction.
180#[derive(Clone, Copy, Debug, MallocSizeOf)]
181struct PropagatedBoxTreeData {
182    allow_percentage_column_in_tables: bool,
183}
184
185impl Default for PropagatedBoxTreeData {
186    fn default() -> Self {
187        Self {
188            allow_percentage_column_in_tables: true,
189        }
190    }
191}
192
193impl PropagatedBoxTreeData {
194    fn disallowing_percentage_table_columns(&self) -> PropagatedBoxTreeData {
195        Self {
196            allow_percentage_column_in_tables: false,
197        }
198    }
199}