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