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 {
62    pub block_size: SizeConstraint,
63    pub writing_mode: WritingMode,
64    pub preferred_aspect_ratio: Option<AspectRatio>,
65}
66
67impl ConstraintSpace {
68    fn new(
69        block_size: SizeConstraint,
70        writing_mode: WritingMode,
71        preferred_aspect_ratio: Option<AspectRatio>,
72    ) -> Self {
73        Self {
74            block_size,
75            writing_mode,
76            preferred_aspect_ratio,
77        }
78    }
79
80    fn new_for_style_and_ratio(
81        style: &ComputedValues,
82        preferred_aspect_ratio: Option<AspectRatio>,
83    ) -> Self {
84        Self::new(
85            SizeConstraint::default(),
86            style.writing_mode,
87            preferred_aspect_ratio,
88        )
89    }
90}
91
92/// A variant of [`ContainingBlock`] that allows an indefinite inline size.
93/// Useful for code that is shared for both layout (where we know the inline size
94/// of the containing block) and intrinsic sizing (where we don't know it).
95pub(crate) struct IndefiniteContainingBlock {
96    pub size: LogicalVec2<Option<Au>>,
97    pub writing_mode: WritingMode,
98}
99
100impl From<&ConstraintSpace> for IndefiniteContainingBlock {
101    fn from(constraint_space: &ConstraintSpace) -> Self {
102        Self {
103            size: LogicalVec2 {
104                inline: None,
105                block: constraint_space.block_size.to_definite(),
106            },
107            writing_mode: constraint_space.writing_mode,
108        }
109    }
110}
111
112impl<'a> From<&'_ ContainingBlock<'a>> for IndefiniteContainingBlock {
113    fn from(containing_block: &ContainingBlock<'a>) -> Self {
114        Self {
115            size: LogicalVec2 {
116                inline: Some(containing_block.size.inline),
117                block: containing_block.size.block.to_definite(),
118            },
119            writing_mode: containing_block.style.writing_mode,
120        }
121    }
122}
123
124impl<'a> From<&'_ DefiniteContainingBlock<'a>> for IndefiniteContainingBlock {
125    fn from(containing_block: &DefiniteContainingBlock<'a>) -> Self {
126        Self {
127            size: containing_block.size.map(|v| Some(*v)),
128            writing_mode: containing_block.style.writing_mode,
129        }
130    }
131}
132
133#[derive(Clone, Debug, MallocSizeOf)]
134pub(crate) struct ContainingBlockSize {
135    inline: Au,
136    block: SizeConstraint,
137}
138
139pub(crate) struct ContainingBlock<'a> {
140    size: ContainingBlockSize,
141    style: &'a ComputedValues,
142}
143
144struct DefiniteContainingBlock<'a> {
145    size: LogicalVec2<Au>,
146    style: &'a ComputedValues,
147}
148
149impl<'a> From<&'_ DefiniteContainingBlock<'a>> for ContainingBlock<'a> {
150    fn from(definite: &DefiniteContainingBlock<'a>) -> Self {
151        ContainingBlock {
152            size: ContainingBlockSize {
153                inline: definite.size.inline,
154                block: SizeConstraint::Definite(definite.size.block),
155            },
156            style: definite.style,
157        }
158    }
159}
160
161/// Data that is propagated from ancestors to descendants during [`crate::flow::BoxTree`]
162/// construction.  This allows data to flow in the reverse direction of the typical layout
163/// propoagation, but only during `BoxTree` construction.
164#[derive(Clone, Copy, Debug)]
165struct PropagatedBoxTreeData {
166    allow_percentage_column_in_tables: bool,
167}
168
169impl Default for PropagatedBoxTreeData {
170    fn default() -> Self {
171        Self {
172            allow_percentage_column_in_tables: true,
173        }
174    }
175}
176
177impl PropagatedBoxTreeData {
178    fn disallowing_percentage_table_columns(&self) -> PropagatedBoxTreeData {
179        Self {
180            allow_percentage_column_in_tables: false,
181        }
182    }
183}