tawasuyu

tawasuyu/taffy

A high performance rust-powered UI layout library

Rust 1077HTML 1008Markdown 12TOML 83209 Definiciones

⎇ df46fcf3630e2e8f4ea2c99bbe261154383a4aab tests/hand_written/float_clearance.rs Rust · 204 líneas · 7.3 KB Historia Quién tocó qué crudo

Fix clearance calculation and its interaction with margin collapsing df46fcf36 · Nico Burns ·

1//! Regression tests for clearance calculation and its interaction with margin collapsing.
2//!
3//! Scenarios are reduced from WPT tests in css/CSS2/floats-clear and css/CSS2/floats.
4use taffy::prelude::*;
5use taffy::{Clear, Float, Overflow, Point};
6
7fn block(tree: &mut TaffyTree<()>, style: Style, children: &[NodeId]) -> NodeId {
8    tree.new_with_children(Style { display: Display::Block, ..style }, children).unwrap()
9}
10
11fn assert_layout(tree: &TaffyTree<()>, node: NodeId, x: f32, y: f32, width: f32, height: f32) {
12    let layout = tree.layout(node).unwrap();
13    assert_eq!(layout.location.x, x, "x of {node:?}");
14    assert_eq!(layout.location.y, y, "y of {node:?}");
15    assert_eq!(layout.size.width, width, "width of {node:?}");
16    assert_eq!(layout.size.height, height, "height of {node:?}");
17}
18
19/// Reduced from WPT css/CSS2/floats-clear/clear-002.xht
20///
21/// A cleared float should clear past prior floats, but `clear` on the first float
22/// (with no prior floats on the relevant side) should not move it down.
23#[test]
24fn clear_on_float_with_and_without_preceding_float() {
25    let t = &mut TaffyTree::new();
26    let f1 = block(
27        t,
28        Style { float: Float::Right, size: Size { width: length(96.0), height: length(96.0) }, ..Default::default() },
29        &[],
30    );
31    let f2 = block(
32        t,
33        Style {
34            float: Float::Right,
35            clear: Clear::Right,
36            size: Size { width: length(96.0), height: length(96.0) },
37            ..Default::default()
38        },
39        &[],
40    );
41    let container =
42        block(t, Style { size: Size { width: length(500.0), height: auto() }, ..Default::default() }, &[f1, f2]);
43    t.compute_layout(container, Size::MAX_CONTENT).unwrap();
44
45    assert_layout(t, f1, 404.0, 0.0, 96.0, 96.0);
46    assert_layout(t, f2, 404.0, 96.0, 96.0, 96.0);
47}
48
49/// Reduced from WPT css/CSS2/floats-clear/clear-clearance-calculation-004.xht
50///
51/// When the hypothetical position of a cleared block (with its top margin) is already
52/// past the bottom of the float, negative clearance keeps it at the float's bottom edge.
53#[test]
54fn negative_clearance_from_large_top_margin() {
55    let t = &mut TaffyTree::new();
56    let first = block(
57        t,
58        Style {
59            size: Size { width: auto(), height: length(25.0) },
60            margin: Rect { bottom: length(25.0), ..Rect::zero() },
61            ..Default::default()
62        },
63        &[],
64    );
65    let float = block(
66        t,
67        Style { float: Float::Left, size: Size { width: length(50.0), height: length(50.0) }, ..Default::default() },
68        &[],
69    );
70    let last = block(
71        t,
72        Style {
73            clear: Clear::Left,
74            margin: Rect { top: length(75.0), ..Rect::zero() },
75            size: Size { width: auto(), height: length(50.0) },
76            ..Default::default()
77        },
78        &[],
79    );
80    let container = block(
81        t,
82        Style { size: Size { width: length(300.0), height: auto() }, ..Default::default() },
83        &[first, float, last],
84    );
85    t.compute_layout(container, Size::MAX_CONTENT).unwrap();
86
87    assert_layout(t, float, 0.0, 50.0, 50.0, 50.0);
88    assert_layout(t, last, 0.0, 100.0, 300.0, 50.0);
89    assert_layout(t, container, 0.0, 0.0, 300.0, 150.0);
90}
91
92/// Reduced from WPT css/CSS2/floats-clear/clear-with-top-margin-after-cleared-empty-block.html
93///
94/// Clearance on a self-collapsing block suppresses margin collapsing with following
95/// siblings, and a following cleared sibling with a large top margin gets no clearance.
96#[test]
97fn clear_with_top_margin_after_cleared_empty_block() {
98    let t = &mut TaffyTree::new();
99    let float = block(
100        t,
101        Style { float: Float::Left, size: Size { width: length(100.0), height: length(20.0) }, ..Default::default() },
102        &[],
103    );
104    let c1 = block(t, Style { clear: Clear::Both, ..Default::default() }, &[]);
105    let c2 = block(
106        t,
107        Style {
108            clear: Clear::Both,
109            margin: Rect { top: length(100.0), ..Rect::zero() },
110            size: Size { width: auto(), height: length(20.0) },
111            ..Default::default()
112        },
113        &[],
114    );
115    let container = block(
116        t,
117        Style {
118            size: Size { width: length(100.0), height: auto() },
119            border: Rect { top: length(1.0), ..Rect::zero() },
120            ..Default::default()
121        },
122        &[float, c1, c2],
123    );
124    t.compute_layout(container, Size::MAX_CONTENT).unwrap();
125
126    assert_layout(t, c1, 0.0, 21.0, 100.0, 0.0);
127    assert_layout(t, c2, 0.0, 121.0, 100.0, 20.0);
128    assert_layout(t, container, 0.0, 0.0, 100.0, 141.0);
129}
130
131/// Reduced from WPT css/CSS2/floats/new-fc-separates-from-float.html
132///
133/// A block establishing a new formatting context that does not fit beside a float is
134/// pushed below it, and its top margin no longer collapses with preceding margins
135/// (so the float, which adjoins the unresolved margin strut, does not move down).
136#[test]
137fn new_fc_separates_from_float() {
138    let t = &mut TaffyTree::new();
139    let float = block(
140        t,
141        Style { float: Float::Left, size: Size { width: length(200.0), height: length(200.0) }, ..Default::default() },
142        &[],
143    );
144    let inner = block(t, Style::default(), &[float]);
145    let bfc = block(
146        t,
147        Style {
148            overflow: Point { x: Overflow::Hidden, y: Overflow::Hidden },
149            margin: Rect { top: length(200.0), ..Rect::zero() },
150            size: Size { width: length(200.0), height: length(1.0) },
151            ..Default::default()
152        },
153        &[],
154    );
155    let mid = block(t, Style::default(), &[inner, bfc]);
156    let container = block(
157        t,
158        Style {
159            overflow: Point { x: Overflow::Hidden, y: Overflow::Hidden },
160            size: Size { width: length(200.0), height: auto() },
161            ..Default::default()
162        },
163        &[mid],
164    );
165    t.compute_layout(container, Size::MAX_CONTENT).unwrap();
166
167    assert_layout(t, mid, 0.0, 0.0, 200.0, 201.0);
168    assert_layout(t, float, 0.0, 0.0, 200.0, 200.0);
169    assert_layout(t, bfc, 0.0, 200.0, 200.0, 1.0);
170    assert_layout(t, container, 0.0, 0.0, 200.0, 201.0);
171}
172
173/// Reduced from WPT css/CSS2/floats-clear/margin-collapse-clear-013.xht
174///
175/// The top and bottom margins of a self-collapsing block with clearance collapse with
176/// each other and are applied inside the parent (they do not collapse with the parent's
177/// bottom margin).
178#[test]
179fn self_collapsing_block_with_clearance_margins() {
180    let t = &mut TaffyTree::new();
181    let float = block(
182        t,
183        Style { float: Float::Left, size: Size { width: length(100.0), height: length(100.0) }, ..Default::default() },
184        &[],
185    );
186    let cleared = block(
187        t,
188        Style {
189            clear: Clear::Left,
190            margin: Rect { top: length(40.0), bottom: length(140.0), ..Rect::zero() },
191            ..Default::default()
192        },
193        &[],
194    );
195    let parent = block(t, Style::default(), &[float, cleared]);
196    let next = block(t, Style { size: Size { width: auto(), height: length(100.0) }, ..Default::default() }, &[]);
197    let root =
198        block(t, Style { size: Size { width: length(300.0), height: auto() }, ..Default::default() }, &[parent, next]);
199    t.compute_layout(root, Size::MAX_CONTENT).unwrap();
200
201    assert_layout(t, cleared, 0.0, 100.0, 300.0, 0.0);
202    assert_layout(t, parent, 0.0, 0.0, 300.0, 200.0);
203    assert_layout(t, next, 0.0, 200.0, 300.0, 100.0);
204}