OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "core/layout/ng/ng_absolute_utils.h" | 5 #include "core/layout/ng/ng_absolute_utils.h" |
6 | 6 |
7 #include "core/layout/ng/ng_constraint_space.h" | 7 #include "core/layout/ng/ng_constraint_space.h" |
8 #include "core/layout/ng/ng_length_utils.h" | 8 #include "core/layout/ng/ng_length_utils.h" |
9 #include "core/style/ComputedStyle.h" | 9 #include "core/style/ComputedStyle.h" |
10 #include "platform/LengthFunctions.h" | 10 #include "platform/LengthFunctions.h" |
11 | 11 |
12 namespace blink { | 12 namespace blink { |
13 | 13 |
14 namespace { | 14 namespace { |
15 | 15 |
16 // Extends Length::valueForLength with default value if length type is auto. | |
17 LayoutUnit CustomValueForLength(const Length& length, | |
18 LayoutUnit max_value, | |
19 LayoutUnit default_value = NGSizeIndefinite) { | |
20 if (length.isAuto()) | |
21 return default_value; | |
22 DCHECK(!length.isPercentOrCalc() || max_value != NGSizeIndefinite); | |
23 return valueForLength(length, max_value); | |
24 } | |
25 | |
26 bool AbsoluteHorizontalNeedsEstimate(const ComputedStyle& style) { | 16 bool AbsoluteHorizontalNeedsEstimate(const ComputedStyle& style) { |
27 return style.width().isAuto() && | 17 Length width = style.width(); |
28 (style.left().isAuto() || style.right().isAuto()); | 18 return width.isIntrinsic() || |
| 19 (width.isAuto() && (style.left().isAuto() || style.right().isAuto())); |
29 } | 20 } |
30 | 21 |
31 bool AbsoluteVerticalNeedsEstimate(const ComputedStyle& style) { | 22 bool AbsoluteVerticalNeedsEstimate(const ComputedStyle& style) { |
32 return style.height().isAuto() && | 23 Length height = style.height(); |
33 (style.top().isAuto() || style.bottom().isAuto()); | 24 return height.isIntrinsic() || |
| 25 (height.isAuto() && (style.top().isAuto() || style.bottom().isAuto())); |
34 } | 26 } |
35 | 27 |
36 // Implement absolute horizontal size resolution algorithm. | 28 // Implement absolute horizontal size resolution algorithm. |
37 // https://www.w3.org/TR/css-position-3/#abs-non-replaced-width | 29 // https://www.w3.org/TR/css-position-3/#abs-non-replaced-width |
38 void ComputeAbsoluteHorizontal(const NGConstraintSpace& space, | 30 void ComputeAbsoluteHorizontal( |
39 const ComputedStyle& style, | 31 const NGConstraintSpace& space, |
40 const NGStaticPosition& static_position, | 32 const ComputedStyle& style, |
41 const Optional<LayoutUnit>& child_auto_width, | 33 const NGStaticPosition& static_position, |
42 NGAbsolutePhysicalPosition* position) { | 34 const Optional<MinAndMaxContentSizes>& child_minmax, |
43 // Always use inline_size for percent resolution. | 35 NGAbsolutePhysicalPosition* position) { |
44 // TODO(atotic) test whether inline_size is correct in vertical modes. | 36 NGLogicalSize percentage_logical = space.PercentageResolutionSize(); |
45 LayoutUnit percentage_resolution_size = | 37 NGPhysicalSize percentage_physical = |
46 space.PercentageResolutionSize().inline_size; | 38 percentage_logical.ConvertToPhysical(space.WritingMode()); |
47 LayoutUnit border_left(style.borderLeftWidth()); | 39 LayoutUnit border_left(style.borderLeftWidth()); |
48 LayoutUnit border_right(style.borderRightWidth()); | 40 LayoutUnit border_right(style.borderRightWidth()); |
49 LayoutUnit padding_left = CustomValueForLength( | 41 LayoutUnit padding_left = |
50 style.paddingLeft(), percentage_resolution_size, LayoutUnit()); | 42 valueForLength(style.paddingLeft(), percentage_logical.inline_size); |
51 LayoutUnit padding_right = CustomValueForLength( | 43 LayoutUnit padding_right = |
52 style.paddingRight(), percentage_resolution_size, LayoutUnit()); | 44 valueForLength(style.paddingRight(), percentage_logical.inline_size); |
53 LayoutUnit margin_left = | 45 Optional<LayoutUnit> margin_left; |
54 CustomValueForLength(style.marginLeft(), percentage_resolution_size); | 46 if (!style.marginLeft().isAuto()) |
55 LayoutUnit margin_right = | 47 margin_left = |
56 CustomValueForLength(style.marginRight(), percentage_resolution_size); | 48 valueForLength(style.marginLeft(), percentage_logical.inline_size); |
57 LayoutUnit left = | 49 Optional<LayoutUnit> margin_right; |
58 CustomValueForLength(style.left(), percentage_resolution_size); | 50 if (!style.marginRight().isAuto()) |
59 LayoutUnit right = | 51 margin_right = |
60 CustomValueForLength(style.right(), percentage_resolution_size); | 52 valueForLength(style.marginRight(), percentage_logical.inline_size); |
| 53 Optional<LayoutUnit> left; |
| 54 if (!style.left().isAuto()) |
| 55 left = valueForLength(style.left(), percentage_physical.width); |
| 56 Optional<LayoutUnit> right; |
| 57 if (!style.right().isAuto()) |
| 58 right = valueForLength(style.right(), percentage_physical.width); |
61 LayoutUnit border_padding = | 59 LayoutUnit border_padding = |
62 border_left + border_right + padding_left + padding_right; | 60 border_left + border_right + padding_left + padding_right; |
63 // TODO(atotic): This should use Resolve{Inline,Block}Length | 61 Optional<LayoutUnit> width; |
64 LayoutUnit width = | 62 if (!style.width().isAuto()) { |
65 CustomValueForLength(style.width(), percentage_resolution_size); | 63 if (space.WritingMode() == kHorizontalTopBottom) { |
66 | 64 width = ResolveInlineLength(space, style, child_minmax, style.width(), |
67 // Normalize width to border-box sizing. | 65 LengthResolveType::kContentSize); |
68 if (style.boxSizing() == EBoxSizing::BoxSizingContentBox && | 66 } else { |
69 width != NGSizeIndefinite) | 67 LayoutUnit computed_width = |
70 width += border_padding; | 68 child_minmax.has_value() ? child_minmax->max_content : LayoutUnit(); |
| 69 width = ResolveBlockLength(space, style, style.width(), computed_width, |
| 70 LengthResolveType::kContentSize); |
| 71 } |
| 72 } |
71 | 73 |
72 NGPhysicalSize container_size = | 74 NGPhysicalSize container_size = |
73 space.AvailableSize().ConvertToPhysical(space.WritingMode()); | 75 space.AvailableSize().ConvertToPhysical(space.WritingMode()); |
74 DCHECK(container_size.width != NGSizeIndefinite); | 76 DCHECK(container_size.width != NGSizeIndefinite); |
75 | 77 |
76 // Solving the equation: | 78 // Solving the equation: |
77 // left + marginLeft + width + marginRight + right = container width | 79 // left + marginLeft + width + marginRight + right = container width |
78 if (left == NGSizeIndefinite && right == NGSizeIndefinite && | 80 if (!left && !right && !width) { |
79 width == NGSizeIndefinite) { | |
80 // Standard: "If all three of left, width, and right are auto:" | 81 // Standard: "If all three of left, width, and right are auto:" |
81 if (margin_left == NGSizeIndefinite) | 82 if (!margin_left) |
82 margin_left = LayoutUnit(); | 83 margin_left = LayoutUnit(); |
83 if (margin_right == NGSizeIndefinite) | 84 if (!margin_right) |
84 margin_right = LayoutUnit(); | 85 margin_right = LayoutUnit(); |
85 DCHECK(child_auto_width.has_value()); | 86 DCHECK(child_minmax.has_value()); |
86 width = *child_auto_width; | 87 width = child_minmax->ShrinkToFit(container_size.width); |
87 if (space.Direction() == TextDirection::Ltr) { | 88 if (space.Direction() == TextDirection::Ltr) { |
88 left = static_position.LeftPosition(container_size.width, width, | 89 left = static_position.LeftPosition(container_size.width, *width, |
89 margin_left, margin_right); | 90 *margin_left, *margin_right); |
90 } else { | 91 } else { |
91 right = static_position.RightPosition(container_size.width, width, | 92 right = static_position.RightPosition(container_size.width, *width, |
92 margin_left, margin_right); | 93 *margin_left, *margin_right); |
93 } | 94 } |
94 } else if (left != NGSizeIndefinite && right != NGSizeIndefinite && | 95 } else if (left && right && width) { |
95 width != NGSizeIndefinite) { | |
96 // Standard: "If left, right, and width are not auto:" | 96 // Standard: "If left, right, and width are not auto:" |
97 // Compute margins. | 97 // Compute margins. |
98 LayoutUnit margin_space = container_size.width - left - right - width; | 98 LayoutUnit margin_space = container_size.width - *left - *right - *width; |
99 // When both margins are auto. | 99 // When both margins are auto. |
100 if (margin_left == NGSizeIndefinite && margin_right == NGSizeIndefinite) { | 100 if (!margin_left && !margin_right) { |
101 if (margin_space > 0) { | 101 if (margin_space > 0) { |
102 margin_left = margin_space / 2; | 102 margin_left = margin_space / 2; |
103 margin_right = margin_space / 2; | 103 margin_right = margin_space / 2; |
104 } else { | 104 } else { |
105 // Margins are negative. | 105 // Margins are negative. |
106 if (space.Direction() == TextDirection::Ltr) { | 106 if (space.Direction() == TextDirection::Ltr) { |
107 margin_left = LayoutUnit(); | 107 margin_left = LayoutUnit(); |
108 margin_right = margin_space; | 108 margin_right = margin_space; |
109 } else { | 109 } else { |
110 margin_right = LayoutUnit(); | 110 margin_right = LayoutUnit(); |
111 margin_left = margin_space; | 111 margin_left = margin_space; |
112 } | 112 } |
113 } | 113 } |
114 } else if (margin_left == NGSizeIndefinite) { | 114 } else if (!margin_left) { |
115 margin_left = margin_space; | 115 margin_left = margin_space; |
116 } else if (margin_right == NGSizeIndefinite) { | 116 } else if (!margin_right) { |
117 margin_right = margin_space; | 117 margin_right = margin_space; |
118 } else { | 118 } else { |
119 // Are values overconstrained? | 119 // Are values overconstrained? |
120 if (margin_left + margin_right != margin_space) { | 120 if (*margin_left + *margin_right != margin_space) { |
121 // Relax the end. | 121 // Relax the end. |
122 if (space.Direction() == TextDirection::Ltr) | 122 if (space.Direction() == TextDirection::Ltr) |
123 right -= margin_left + margin_right - margin_space; | 123 right = *right - *margin_left + *margin_right - margin_space; |
124 else | 124 else |
125 left -= margin_left + margin_right - margin_space; | 125 left = *left - *margin_left + *margin_right - margin_space; |
126 } | 126 } |
127 } | 127 } |
128 } | 128 } |
129 | 129 |
130 // Set unknown margins. | 130 // Set unknown margins. |
131 if (margin_left == NGSizeIndefinite) | 131 if (!margin_left) |
132 margin_left = LayoutUnit(); | 132 margin_left = LayoutUnit(); |
133 if (margin_right == NGSizeIndefinite) | 133 if (!margin_right) |
134 margin_right = LayoutUnit(); | 134 margin_right = LayoutUnit(); |
135 | 135 |
136 // Rules 1 through 3, 2 out of 3 are unknown. | 136 // Rules 1 through 3, 2 out of 3 are unknown. |
137 if (left == NGSizeIndefinite && width == NGSizeIndefinite) { | 137 if (!left && !width) { |
138 // Rule 1: left/width are unknown. | 138 // Rule 1: left/width are unknown. |
139 DCHECK_NE(right, NGSizeIndefinite); | 139 DCHECK(right.has_value()); |
140 DCHECK(child_auto_width.has_value()); | 140 DCHECK(child_minmax.has_value()); |
141 width = *child_auto_width; | 141 width = child_minmax->ShrinkToFit(container_size.width); |
142 } else if (left == NGSizeIndefinite && right == NGSizeIndefinite) { | 142 } else if (!left && !right) { |
143 // Rule 2. | 143 // Rule 2. |
144 DCHECK_NE(width, NGSizeIndefinite); | 144 DCHECK(width.has_value()); |
145 if (space.Direction() == TextDirection::Ltr) | 145 if (space.Direction() == TextDirection::Ltr) |
146 left = static_position.LeftPosition(container_size.width, width, | 146 left = static_position.LeftPosition(container_size.width, *width, |
147 margin_left, margin_right); | 147 *margin_left, *margin_right); |
148 else | 148 else |
149 right = static_position.RightPosition(container_size.width, width, | 149 right = static_position.RightPosition(container_size.width, *width, |
150 margin_left, margin_right); | 150 *margin_left, *margin_right); |
151 } else if (width == NGSizeIndefinite && right == NGSizeIndefinite) { | 151 } else if (!width && !right) { |
152 // Rule 3. | 152 // Rule 3. |
153 DCHECK(child_auto_width.has_value()); | 153 DCHECK(child_minmax.has_value()); |
154 width = *child_auto_width; | 154 width = child_minmax->ShrinkToFit(container_size.width); |
155 } | 155 } |
156 | 156 |
157 // Rules 4 through 6, 1 out of 3 are unknown. | 157 // Rules 4 through 6, 1 out of 3 are unknown. |
158 if (left == NGSizeIndefinite) { | 158 if (!left) { |
159 left = container_size.width - right - width - margin_left - margin_right; | 159 left = |
160 } else if (right == NGSizeIndefinite) { | 160 container_size.width - *right - *width - *margin_left - *margin_right; |
161 right = container_size.width - left - width - margin_left - margin_right; | 161 } else if (!right) { |
162 } else if (width == NGSizeIndefinite) { | 162 right = |
163 width = container_size.width - left - right - margin_left - margin_right; | 163 container_size.width - *left - *width - *margin_left - *margin_right; |
| 164 } else if (!width) { |
| 165 width = |
| 166 container_size.width - *left - *right - *margin_left - *margin_right; |
164 } | 167 } |
165 DCHECK_EQ(container_size.width, | 168 DCHECK_EQ(container_size.width, |
166 left + right + margin_left + margin_right + width); | 169 *left + *right + *margin_left + *margin_right + *width); |
167 | 170 |
168 // Negative widths are not allowed. | 171 // Negative widths are not allowed. |
169 width = std::max(width, border_padding); | 172 width = std::max(*width, border_padding); |
170 | 173 |
171 position->inset.left = left + margin_left; | 174 position->inset.left = *left + *margin_left; |
172 position->inset.right = right + margin_right; | 175 position->inset.right = *right + *margin_right; |
173 position->size.width = width; | 176 position->size.width = *width; |
174 } | 177 } |
175 | 178 |
176 // Implements absolute vertical size resolution algorithm. | 179 // Implements absolute vertical size resolution algorithm. |
177 // https://www.w3.org/TR/css-position-3/#abs-non-replaced-height | 180 // https://www.w3.org/TR/css-position-3/#abs-non-replaced-height |
178 void ComputeAbsoluteVertical(const NGConstraintSpace& space, | 181 void ComputeAbsoluteVertical( |
179 const ComputedStyle& style, | 182 const NGConstraintSpace& space, |
180 const NGStaticPosition& static_position, | 183 const ComputedStyle& style, |
181 const Optional<LayoutUnit>& child_auto_height, | 184 const NGStaticPosition& static_position, |
182 NGAbsolutePhysicalPosition* position) { | 185 const Optional<MinAndMaxContentSizes>& child_minmax, |
183 // TODO(atotic) check percentage resolution for vertical writing modes. | 186 NGAbsolutePhysicalPosition* position) { |
184 LayoutUnit percentage_inline_size = | 187 NGLogicalSize percentage_logical = space.PercentageResolutionSize(); |
185 space.PercentageResolutionSize().inline_size; | 188 NGPhysicalSize percentage_physical = |
186 LayoutUnit percentage_block_size = | 189 percentage_logical.ConvertToPhysical(space.WritingMode()); |
187 space.PercentageResolutionSize().block_size; | 190 |
188 LayoutUnit border_top(style.borderTopWidth()); | 191 LayoutUnit border_top(style.borderTopWidth()); |
189 LayoutUnit border_bottom(style.borderBottomWidth()); | 192 LayoutUnit border_bottom(style.borderBottomWidth()); |
190 LayoutUnit padding_top = CustomValueForLength( | 193 LayoutUnit padding_top = |
191 style.paddingTop(), percentage_inline_size, LayoutUnit()); | 194 valueForLength(style.paddingTop(), percentage_logical.inline_size); |
192 LayoutUnit padding_bottom = CustomValueForLength( | 195 LayoutUnit padding_bottom = |
193 style.paddingBottom(), percentage_inline_size, LayoutUnit()); | 196 valueForLength(style.paddingBottom(), percentage_logical.inline_size); |
194 LayoutUnit margin_top = | 197 Optional<LayoutUnit> margin_top; |
195 CustomValueForLength(style.marginTop(), percentage_inline_size); | 198 if (!style.marginTop().isAuto()) |
196 LayoutUnit margin_bottom = | 199 margin_top = |
197 CustomValueForLength(style.marginBottom(), percentage_inline_size); | 200 valueForLength(style.marginTop(), percentage_logical.inline_size); |
198 LayoutUnit top = CustomValueForLength(style.top(), percentage_block_size); | 201 Optional<LayoutUnit> margin_bottom; |
199 LayoutUnit bottom = | 202 if (!style.marginBottom().isAuto()) |
200 CustomValueForLength(style.bottom(), percentage_block_size); | 203 margin_bottom = |
| 204 valueForLength(style.marginBottom(), percentage_logical.inline_size); |
| 205 Optional<LayoutUnit> top; |
| 206 if (!style.top().isAuto()) |
| 207 top = valueForLength(style.top(), percentage_physical.height); |
| 208 Optional<LayoutUnit> bottom; |
| 209 if (!style.bottom().isAuto()) |
| 210 bottom = valueForLength(style.bottom(), percentage_physical.height); |
201 LayoutUnit border_padding = | 211 LayoutUnit border_padding = |
202 border_top + border_bottom + padding_top + padding_bottom; | 212 border_top + border_bottom + padding_top + padding_bottom; |
203 // TODO(atotic): This should use Resolve{Inline,Block}Length. | |
204 LayoutUnit height = | |
205 CustomValueForLength(style.height(), percentage_block_size); | |
206 | 213 |
207 if (style.boxSizing() == EBoxSizing::BoxSizingContentBox && | 214 Optional<LayoutUnit> height; |
208 height != NGSizeIndefinite) | 215 if (!style.height().isAuto()) { |
209 height += border_padding; | 216 if (space.WritingMode() == kHorizontalTopBottom) { |
| 217 LayoutUnit computed_height = |
| 218 child_minmax.has_value() ? child_minmax->max_content : LayoutUnit(); |
| 219 height = ResolveBlockLength(space, style, style.height(), computed_height, |
| 220 LengthResolveType::kContentSize); |
| 221 } else { |
| 222 height = ResolveInlineLength(space, style, child_minmax, style.height(), |
| 223 LengthResolveType::kContentSize); |
| 224 } |
| 225 } |
210 | 226 |
211 NGPhysicalSize container_size = | 227 NGPhysicalSize container_size = |
212 space.AvailableSize().ConvertToPhysical(space.WritingMode()); | 228 space.AvailableSize().ConvertToPhysical(space.WritingMode()); |
213 DCHECK(container_size.height != NGSizeIndefinite); | 229 DCHECK(container_size.height != NGSizeIndefinite); |
214 | 230 |
215 // Solving the equation: | 231 // Solving the equation: |
216 // top + marginTop + height + marginBottom + bottom | 232 // top + marginTop + height + marginBottom + bottom |
217 // + border_padding = container height | 233 // + border_padding = container height |
218 if (top == NGSizeIndefinite && bottom == NGSizeIndefinite && | 234 if (!top && !bottom && !height) { |
219 height == NGSizeIndefinite) { | |
220 // Standard: "If all three of top, height, and bottom are auto:" | 235 // Standard: "If all three of top, height, and bottom are auto:" |
221 if (margin_top == NGSizeIndefinite) | 236 if (!margin_top) |
222 margin_top = LayoutUnit(); | 237 margin_top = LayoutUnit(); |
223 if (margin_bottom == NGSizeIndefinite) | 238 if (!margin_bottom) |
224 margin_bottom = LayoutUnit(); | 239 margin_bottom = LayoutUnit(); |
225 DCHECK(child_auto_height.has_value()); | 240 DCHECK(child_minmax.has_value()); |
226 height = *child_auto_height; | 241 height = child_minmax->ShrinkToFit(container_size.height); |
227 top = static_position.TopPosition(container_size.height, height, margin_top, | 242 top = static_position.TopPosition(container_size.height, *height, |
228 margin_bottom); | 243 *margin_top, *margin_bottom); |
229 } else if (top != NGSizeIndefinite && bottom != NGSizeIndefinite && | 244 } else if (top && bottom && height) { |
230 height != NGSizeIndefinite) { | |
231 // Standard: "If top, bottom, and height are not auto:" | 245 // Standard: "If top, bottom, and height are not auto:" |
232 // Compute margins. | 246 // Compute margins. |
233 LayoutUnit margin_space = container_size.height - top - bottom - height; | 247 LayoutUnit margin_space = container_size.height - *top - *bottom - *height; |
234 // When both margins are auto. | 248 // When both margins are auto. |
235 if (margin_top == NGSizeIndefinite && margin_bottom == NGSizeIndefinite) { | 249 if (!margin_top && !margin_bottom) { |
236 if (margin_space > 0) { | 250 if (margin_space > 0) { |
237 margin_top = margin_space / 2; | 251 margin_top = margin_space / 2; |
238 margin_bottom = margin_space / 2; | 252 margin_bottom = margin_space / 2; |
239 } else { | 253 } else { |
240 // Margin space is over-constrained. | 254 // Margin space is over-constrained. |
241 margin_top = LayoutUnit(); | 255 margin_top = LayoutUnit(); |
242 margin_bottom = margin_space; | 256 margin_bottom = margin_space; |
243 } | 257 } |
244 } else if (margin_top == NGSizeIndefinite) { | 258 } else if (!margin_top) { |
245 margin_top = margin_space; | 259 margin_top = margin_space; |
246 } else if (margin_bottom == NGSizeIndefinite) { | 260 } else if (!margin_bottom) { |
247 margin_bottom = margin_space; | 261 margin_bottom = margin_space; |
248 } else { | 262 } else { |
249 // Are values overconstrained? | 263 // Are values overconstrained? |
250 if (margin_top + margin_bottom != margin_space) { | 264 if (*margin_top + *margin_bottom != margin_space) { |
251 // Relax the end. | 265 // Relax the end. |
252 bottom -= margin_top + margin_bottom - margin_space; | 266 bottom = *bottom - *margin_top + *margin_bottom - margin_space; |
253 } | 267 } |
254 } | 268 } |
255 } | 269 } |
256 | 270 |
257 // Set unknown margins. | 271 // Set unknown margins. |
258 if (margin_top == NGSizeIndefinite) | 272 if (!margin_top) |
259 margin_top = LayoutUnit(); | 273 margin_top = LayoutUnit(); |
260 if (margin_bottom == NGSizeIndefinite) | 274 if (!margin_bottom) |
261 margin_bottom = LayoutUnit(); | 275 margin_bottom = LayoutUnit(); |
262 | 276 |
263 // Rules 1 through 3, 2 out of 3 are unknown, fix 1. | 277 // Rules 1 through 3, 2 out of 3 are unknown, fix 1. |
264 if (top == NGSizeIndefinite && height == NGSizeIndefinite) { | 278 if (!top && !height) { |
265 // Rule 1. | 279 // Rule 1. |
266 DCHECK_NE(bottom, NGSizeIndefinite); | 280 DCHECK(bottom.has_value()); |
267 DCHECK(child_auto_height.has_value()); | 281 DCHECK(child_minmax.has_value()); |
268 height = *child_auto_height; | 282 height = child_minmax->ShrinkToFit(container_size.height); |
269 } else if (top == NGSizeIndefinite && bottom == NGSizeIndefinite) { | 283 } else if (!top && !bottom) { |
270 // Rule 2. | 284 // Rule 2. |
271 DCHECK_NE(height, NGSizeIndefinite); | 285 DCHECK(height.has_value()); |
272 top = static_position.TopPosition(container_size.height, height, margin_top, | 286 top = static_position.TopPosition(container_size.height, *height, |
273 margin_bottom); | 287 *margin_top, *margin_bottom); |
274 } else if (height == NGSizeIndefinite && bottom == NGSizeIndefinite) { | 288 } else if (!height && !bottom) { |
275 // Rule 3. | 289 // Rule 3. |
276 DCHECK(child_auto_height.has_value()); | 290 DCHECK(child_minmax.has_value()); |
277 height = *child_auto_height; | 291 height = child_minmax->ShrinkToFit(container_size.height); |
278 } | 292 } |
279 | 293 |
280 // Rules 4 through 6, 1 out of 3 are unknown. | 294 // Rules 4 through 6, 1 out of 3 are unknown. |
281 if (top == NGSizeIndefinite) { | 295 if (!top) { |
282 top = container_size.height - bottom - height - margin_top - margin_bottom; | 296 top = container_size.height - *bottom - *height - *margin_top - |
283 } else if (bottom == NGSizeIndefinite) { | 297 *margin_bottom; |
284 bottom = container_size.height - top - height - margin_top - margin_bottom; | 298 } else if (!bottom) { |
285 } else if (height == NGSizeIndefinite) { | 299 bottom = |
286 height = container_size.height - top - bottom - margin_top - margin_bottom; | 300 container_size.height - *top - *height - *margin_top - *margin_bottom; |
| 301 } else if (!height) { |
| 302 height = |
| 303 container_size.height - *top - *bottom - *margin_top - *margin_bottom; |
287 } | 304 } |
288 DCHECK_EQ(container_size.height, | 305 DCHECK_EQ(container_size.height, |
289 top + bottom + margin_top + margin_bottom + height); | 306 *top + *bottom + *margin_top + *margin_bottom + *height); |
290 | 307 |
291 // Negative heights are not allowed. | 308 // Negative heights are not allowed. |
292 height = std::max(height, border_padding); | 309 height = std::max(*height, border_padding); |
293 | 310 |
294 position->inset.top = top + margin_top; | 311 position->inset.top = *top + *margin_top; |
295 position->inset.bottom = bottom + margin_bottom; | 312 position->inset.bottom = *bottom + *margin_bottom; |
296 position->size.height = height; | 313 position->size.height = *height; |
297 } | 314 } |
298 | 315 |
299 } // namespace | 316 } // namespace |
300 | 317 |
301 String NGAbsolutePhysicalPosition::ToString() const { | 318 String NGAbsolutePhysicalPosition::ToString() const { |
302 return String::format("INSET(LRTB):%d,%d,%d,%d SIZE:%dx%d", | 319 return String::format("INSET(LRTB):%d,%d,%d,%d SIZE:%dx%d", |
303 inset.left.toInt(), inset.right.toInt(), | 320 inset.left.toInt(), inset.right.toInt(), |
304 inset.top.toInt(), inset.bottom.toInt(), | 321 inset.top.toInt(), inset.bottom.toInt(), |
305 size.width.toInt(), size.height.toInt()); | 322 size.width.toInt(), size.height.toInt()); |
306 } | 323 } |
307 | 324 |
308 bool AbsoluteNeedsChildBlockSize(const ComputedStyle& style) { | 325 bool AbsoluteNeedsChildBlockSize(const ComputedStyle& style) { |
309 if (style.isHorizontalWritingMode()) | 326 if (style.isHorizontalWritingMode()) |
310 return AbsoluteVerticalNeedsEstimate(style); | 327 return AbsoluteVerticalNeedsEstimate(style); |
311 else | 328 else |
312 return AbsoluteHorizontalNeedsEstimate(style); | 329 return AbsoluteHorizontalNeedsEstimate(style); |
313 } | 330 } |
314 | 331 |
315 bool AbsoluteNeedsChildInlineSize(const ComputedStyle& style) { | 332 bool AbsoluteNeedsChildInlineSize(const ComputedStyle& style) { |
316 if (style.isHorizontalWritingMode()) | 333 if (style.isHorizontalWritingMode()) |
317 return AbsoluteHorizontalNeedsEstimate(style); | 334 return AbsoluteHorizontalNeedsEstimate(style); |
318 else | 335 else |
319 return AbsoluteVerticalNeedsEstimate(style); | 336 return AbsoluteVerticalNeedsEstimate(style); |
320 } | 337 } |
321 | 338 |
322 NGAbsolutePhysicalPosition ComputePartialAbsoluteWithChildInlineSize( | 339 NGAbsolutePhysicalPosition ComputePartialAbsoluteWithChildInlineSize( |
323 const NGConstraintSpace& space, | 340 const NGConstraintSpace& space, |
324 const ComputedStyle& style, | 341 const ComputedStyle& style, |
325 const NGStaticPosition& static_position, | 342 const NGStaticPosition& static_position, |
326 const Optional<LayoutUnit>& child_inline_size) { | 343 const Optional<MinAndMaxContentSizes>& child_minmax) { |
327 NGAbsolutePhysicalPosition position; | 344 NGAbsolutePhysicalPosition position; |
328 if (style.isHorizontalWritingMode()) | 345 if (style.isHorizontalWritingMode()) |
329 ComputeAbsoluteHorizontal(space, style, static_position, child_inline_size, | 346 ComputeAbsoluteHorizontal(space, style, static_position, child_minmax, |
330 &position); | 347 &position); |
331 else | 348 else { |
332 ComputeAbsoluteVertical(space, style, static_position, child_inline_size, | 349 ComputeAbsoluteVertical(space, style, static_position, child_minmax, |
333 &position); | 350 &position); |
| 351 } |
334 return position; | 352 return position; |
335 } | 353 } |
336 | 354 |
337 void ComputeFullAbsoluteWithChildBlockSize( | 355 void ComputeFullAbsoluteWithChildBlockSize( |
338 const NGConstraintSpace& space, | 356 const NGConstraintSpace& space, |
339 const ComputedStyle& style, | 357 const ComputedStyle& style, |
340 const NGStaticPosition& static_position, | 358 const NGStaticPosition& static_position, |
341 const Optional<LayoutUnit>& child_block_size, | 359 const Optional<LayoutUnit>& child_block_size, |
342 NGAbsolutePhysicalPosition* position) { | 360 NGAbsolutePhysicalPosition* position) { |
| 361 // After partial size has been computed, child block size is either |
| 362 // unknown, or fully computed, there is no minmax. |
| 363 // To express this, a 'fixed' minmax is created where |
| 364 // min and max are the same. |
| 365 Optional<MinAndMaxContentSizes> child_minmax; |
| 366 if (child_block_size.has_value()) { |
| 367 child_minmax = MinAndMaxContentSizes{*child_block_size, *child_block_size}; |
| 368 } |
343 if (style.isHorizontalWritingMode()) | 369 if (style.isHorizontalWritingMode()) |
344 ComputeAbsoluteVertical(space, style, static_position, child_block_size, | 370 ComputeAbsoluteVertical(space, style, static_position, child_minmax, |
345 position); | 371 position); |
346 else | 372 else { |
347 ComputeAbsoluteHorizontal(space, style, static_position, child_block_size, | 373 ComputeAbsoluteHorizontal(space, style, static_position, child_minmax, |
348 position); | 374 position); |
| 375 } |
349 } | 376 } |
350 | 377 |
351 } // namespace blink | 378 } // namespace blink |
OLD | NEW |