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