1use azul_core::{
4 geom::{LogicalPosition, LogicalRect, LogicalSize},
5 ui_solver::ResolvedOffsets,
6};
7use azul_css::props::{
8 basic::{pixel::PixelValue, PhysicalSize, PropertyContext, ResolutionContext, SizeMetric},
9 layout::LayoutWritingMode,
10};
11
12#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
14pub enum BoxSizing {
15 #[default]
16 ContentBox,
17 BorderBox,
18}
19
20#[derive(Debug, Clone, PartialEq, PartialOrd)]
21pub struct PositionedRectangle {
22 pub bounds: LogicalRect,
24 pub margin: ResolvedOffsets,
26 pub border: ResolvedOffsets,
28 pub padding: ResolvedOffsets,
30}
31
32#[derive(Debug, Clone, Copy, Default)]
34pub struct EdgeSizes {
35 pub top: f32,
36 pub right: f32,
37 pub bottom: f32,
38 pub left: f32,
39}
40
41impl EdgeSizes {
42 pub fn main_start(&self, wm: LayoutWritingMode) -> f32 {
44 match wm {
45 LayoutWritingMode::HorizontalTb => self.top,
46 LayoutWritingMode::VerticalRl | LayoutWritingMode::VerticalLr => self.left,
47 }
48 }
49
50 pub fn main_end(&self, wm: LayoutWritingMode) -> f32 {
52 match wm {
53 LayoutWritingMode::HorizontalTb => self.bottom,
54 LayoutWritingMode::VerticalRl | LayoutWritingMode::VerticalLr => self.right,
55 }
56 }
57
58 pub fn main_sum(&self, wm: LayoutWritingMode) -> f32 {
60 self.main_start(wm) + self.main_end(wm)
61 }
62
63 pub fn cross_start(&self, wm: LayoutWritingMode) -> f32 {
65 match wm {
66 LayoutWritingMode::HorizontalTb => self.left,
67 LayoutWritingMode::VerticalRl | LayoutWritingMode::VerticalLr => self.top,
68 }
69 }
70
71 pub fn cross_end(&self, wm: LayoutWritingMode) -> f32 {
73 match wm {
74 LayoutWritingMode::HorizontalTb => self.right,
75 LayoutWritingMode::VerticalRl | LayoutWritingMode::VerticalLr => self.bottom,
76 }
77 }
78
79 pub fn cross_sum(&self, wm: LayoutWritingMode) -> f32 {
81 self.cross_start(wm) + self.cross_end(wm)
82 }
83}
84
85#[derive(Debug, Clone, Copy, Default, PartialEq)]
94pub enum UnresolvedMargin {
95 #[default]
97 Zero,
98 Auto,
100 Length(PixelValue),
102}
103
104impl UnresolvedMargin {
105 pub fn is_auto(&self) -> bool {
107 matches!(self, UnresolvedMargin::Auto)
108 }
109
110 pub fn resolve(&self, ctx: &ResolutionContext) -> f32 {
116 match self {
117 UnresolvedMargin::Zero => 0.0,
118 UnresolvedMargin::Auto => 0.0, UnresolvedMargin::Length(pv) => pv.resolve_with_context(ctx, PropertyContext::Margin),
120 }
121 }
122}
123
124#[derive(Debug, Clone, Copy, Default)]
129pub struct UnresolvedEdge<T> {
130 pub top: T,
131 pub right: T,
132 pub bottom: T,
133 pub left: T,
134}
135
136impl<T> UnresolvedEdge<T> {
137 pub fn new(top: T, right: T, bottom: T, left: T) -> Self {
138 Self { top, right, bottom, left }
139 }
140}
141
142impl UnresolvedEdge<UnresolvedMargin> {
143 pub fn resolve(&self, ctx: &ResolutionContext) -> EdgeSizes {
145 EdgeSizes {
146 top: self.top.resolve(ctx),
147 right: self.right.resolve(ctx),
148 bottom: self.bottom.resolve(ctx),
149 left: self.left.resolve(ctx),
150 }
151 }
152
153 pub fn get_margin_auto(&self) -> MarginAuto {
155 MarginAuto {
156 top: self.top.is_auto(),
157 right: self.right.is_auto(),
158 bottom: self.bottom.is_auto(),
159 left: self.left.is_auto(),
160 }
161 }
162}
163
164impl UnresolvedEdge<PixelValue> {
165 pub fn resolve(&self, ctx: &ResolutionContext, prop_ctx: PropertyContext) -> EdgeSizes {
167 EdgeSizes {
168 top: self.top.resolve_with_context(ctx, prop_ctx),
169 right: self.right.resolve_with_context(ctx, prop_ctx),
170 bottom: self.bottom.resolve_with_context(ctx, prop_ctx),
171 left: self.left.resolve_with_context(ctx, prop_ctx),
172 }
173 }
174}
175
176#[derive(Debug, Clone, Copy)]
178pub struct ResolutionParams {
179 pub containing_block: LogicalSize,
181 pub viewport_size: LogicalSize,
183 pub element_font_size: f32,
185 pub root_font_size: f32,
187}
188
189impl ResolutionParams {
190 pub fn to_resolution_context(&self) -> ResolutionContext {
192 ResolutionContext {
193 element_font_size: self.element_font_size,
194 parent_font_size: self.element_font_size, root_font_size: self.root_font_size,
196 element_size: None,
197 containing_block_size: PhysicalSize::new(
198 self.containing_block.width,
199 self.containing_block.height,
200 ),
201 viewport_size: PhysicalSize::new(
202 self.viewport_size.width,
203 self.viewport_size.height,
204 ),
205 }
206 }
207}
208
209#[derive(Debug, Clone, Copy, Default)]
218pub struct UnresolvedBoxProps {
219 pub margin: UnresolvedEdge<UnresolvedMargin>,
220 pub padding: UnresolvedEdge<PixelValue>,
221 pub border: UnresolvedEdge<PixelValue>,
222}
223
224impl UnresolvedBoxProps {
225 pub fn resolve(&self, params: &ResolutionParams) -> ResolvedBoxProps {
227 let ctx = params.to_resolution_context();
228 ResolvedBoxProps {
229 margin: self.margin.resolve(&ctx),
230 padding: self.padding.resolve(&ctx, PropertyContext::Padding),
231 border: self.border.resolve(&ctx, PropertyContext::BorderWidth),
232 margin_auto: self.margin.get_margin_auto(),
233 }
234 }
235}
236
237#[derive(Debug, Clone, Copy, Default)]
243pub struct MarginAuto {
244 pub left: bool,
245 pub right: bool,
246 pub top: bool,
247 pub bottom: bool,
248}
249
250#[derive(Debug, Clone, Copy, Default)]
255pub struct ResolvedBoxProps {
256 pub margin: EdgeSizes,
257 pub padding: EdgeSizes,
258 pub border: EdgeSizes,
259 pub margin_auto: MarginAuto,
263}
264
265impl ResolvedBoxProps {
266 pub fn inner_size(&self, outer_size: LogicalSize, wm: LayoutWritingMode) -> LogicalSize {
269 let outer_main = outer_size.main(wm);
270 let outer_cross = outer_size.cross(wm);
271
272 let cross_axis_spacing = self.padding.cross_sum(wm) + self.border.cross_sum(wm);
274
275 let main_axis_spacing = self.padding.main_sum(wm) + self.border.main_sum(wm);
277
278 let inner_main = (outer_main - main_axis_spacing).max(0.0);
279 let inner_cross = (outer_cross - cross_axis_spacing).max(0.0);
280
281 LogicalSize::from_main_cross(inner_main, inner_cross, wm)
282 }
283}
284
285pub type BoxProps = ResolvedBoxProps;
288
289pub use azul_css::props::layout::{LayoutClear, LayoutFloat};
291
292#[derive(Debug, Clone, Copy, Default)]
295pub struct IntrinsicSizes {
296 pub min_content_width: f32,
298 pub max_content_width: f32,
300 pub preferred_width: Option<f32>,
302 pub min_content_height: f32,
304 pub max_content_height: f32,
306 pub preferred_height: Option<f32>,
308}
309
310impl IntrinsicSizes {
311 pub fn zero() -> Self {
313 Self::default()
314 }
315}