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 bool AbsoluteHorizontalNeedsEstimate(const ComputedStyle& style) { | 16 bool AbsoluteHorizontalNeedsEstimate(const ComputedStyle& style) { |
17 Length width = style.width(); | 17 Length width = style.width(); |
18 return width.isIntrinsic() || | 18 return width.isIntrinsic() || |
19 (width.isAuto() && (style.left().isAuto() || style.right().isAuto())); | 19 (width.isAuto() && (style.left().isAuto() || style.right().isAuto())); |
20 } | 20 } |
21 | 21 |
22 bool AbsoluteVerticalNeedsEstimate(const ComputedStyle& style) { | 22 bool AbsoluteVerticalNeedsEstimate(const ComputedStyle& style) { |
23 Length height = style.height(); | 23 Length height = style.height(); |
24 return height.isIntrinsic() || | 24 return height.isIntrinsic() || |
25 (height.isAuto() && (style.top().isAuto() || style.bottom().isAuto())); | 25 (height.isAuto() && (style.top().isAuto() || style.bottom().isAuto())); |
26 } | 26 } |
27 | 27 |
28 LayoutUnit ResolveWidth(const Length& width, | |
29 const NGConstraintSpace& space, | |
30 const ComputedStyle& style, | |
31 const Optional<MinAndMaxContentSizes>& child_minmax) { | |
32 if (space.WritingMode() == kHorizontalTopBottom) | |
33 return ResolveInlineLength(space, style, child_minmax, width, | |
34 LengthResolveType::kContentSize); | |
cbiesinger
2017/01/19 22:49:13
So, you really need to pass in the LengthResolveTy
atotic
2017/01/19 23:47:43
done. The usage of Resolve.. methods keeps trippin
| |
35 LayoutUnit computed_width = | |
36 child_minmax.has_value() ? child_minmax->max_content : LayoutUnit(); | |
37 return ResolveBlockLength(space, style, style.width(), computed_width, | |
38 LengthResolveType::kContentSize); | |
39 } | |
40 | |
28 // Implement absolute horizontal size resolution algorithm. | 41 // Implement absolute horizontal size resolution algorithm. |
29 // https://www.w3.org/TR/css-position-3/#abs-non-replaced-width | 42 // https://www.w3.org/TR/css-position-3/#abs-non-replaced-width |
30 void ComputeAbsoluteHorizontal( | 43 void ComputeAbsoluteHorizontal( |
31 const NGConstraintSpace& space, | 44 const NGConstraintSpace& space, |
32 const ComputedStyle& style, | 45 const ComputedStyle& style, |
33 const NGStaticPosition& static_position, | 46 const NGStaticPosition& static_position, |
34 const Optional<MinAndMaxContentSizes>& child_minmax, | 47 const Optional<MinAndMaxContentSizes>& child_minmax, |
35 NGAbsolutePhysicalPosition* position) { | 48 NGAbsolutePhysicalPosition* position) { |
36 NGLogicalSize percentage_logical = space.PercentageResolutionSize(); | 49 NGLogicalSize percentage_logical = space.PercentageResolutionSize(); |
37 NGPhysicalSize percentage_physical = | 50 NGPhysicalSize percentage_physical = |
(...skipping 13 matching lines...) Expand all Loading... | |
51 margin_right = | 64 margin_right = |
52 valueForLength(style.marginRight(), percentage_logical.inline_size); | 65 valueForLength(style.marginRight(), percentage_logical.inline_size); |
53 Optional<LayoutUnit> left; | 66 Optional<LayoutUnit> left; |
54 if (!style.left().isAuto()) | 67 if (!style.left().isAuto()) |
55 left = valueForLength(style.left(), percentage_physical.width); | 68 left = valueForLength(style.left(), percentage_physical.width); |
56 Optional<LayoutUnit> right; | 69 Optional<LayoutUnit> right; |
57 if (!style.right().isAuto()) | 70 if (!style.right().isAuto()) |
58 right = valueForLength(style.right(), percentage_physical.width); | 71 right = valueForLength(style.right(), percentage_physical.width); |
59 LayoutUnit border_padding = | 72 LayoutUnit border_padding = |
60 border_left + border_right + padding_left + padding_right; | 73 border_left + border_right + padding_left + padding_right; |
74 Optional<LayoutUnit> min_width; | |
75 if (!style.minWidth().isAuto()) | |
76 min_width = ResolveWidth(style.minWidth(), space, style, child_minmax); | |
77 Optional<LayoutUnit> max_width; | |
78 if (!style.maxWidth().isMaxSizeNone()) | |
79 max_width = ResolveWidth(style.maxWidth(), space, style, child_minmax); | |
61 Optional<LayoutUnit> width; | 80 Optional<LayoutUnit> width; |
62 if (!style.width().isAuto()) { | 81 if (!style.width().isAuto()) { |
63 if (space.WritingMode() == kHorizontalTopBottom) { | 82 width = ResolveWidth(style.width(), space, style, child_minmax); |
64 width = ResolveInlineLength(space, style, child_minmax, style.width(), | 83 width = ConstrainByMinMax(*width, min_width, max_width); |
65 LengthResolveType::kContentSize); | |
66 } else { | |
67 LayoutUnit computed_width = | |
68 child_minmax.has_value() ? child_minmax->max_content : LayoutUnit(); | |
69 width = ResolveBlockLength(space, style, style.width(), computed_width, | |
70 LengthResolveType::kContentSize); | |
71 } | |
72 } | 84 } |
73 | |
74 NGPhysicalSize container_size = | 85 NGPhysicalSize container_size = |
75 space.AvailableSize().ConvertToPhysical(space.WritingMode()); | 86 space.AvailableSize().ConvertToPhysical(space.WritingMode()); |
76 DCHECK(container_size.width != NGSizeIndefinite); | 87 DCHECK(container_size.width != NGSizeIndefinite); |
77 | 88 |
78 // Solving the equation: | 89 // Solving the equation: |
79 // left + marginLeft + width + marginRight + right = container width | 90 // left + marginLeft + width + marginRight + right = container width |
80 if (!left && !right && !width) { | 91 if (!left && !right && !width) { |
81 // Standard: "If all three of left, width, and right are auto:" | 92 // Standard: "If all three of left, width, and right are auto:" |
82 if (!margin_left) | 93 if (!margin_left) |
83 margin_left = LayoutUnit(); | 94 margin_left = LayoutUnit(); |
84 if (!margin_right) | 95 if (!margin_right) |
85 margin_right = LayoutUnit(); | 96 margin_right = LayoutUnit(); |
86 DCHECK(child_minmax.has_value()); | 97 DCHECK(child_minmax.has_value()); |
87 width = child_minmax->ShrinkToFit(container_size.width); | 98 width = child_minmax->ShrinkToFit(container_size.width); |
99 width = ConstrainByMinMax(*width, min_width, max_width); | |
88 if (space.Direction() == TextDirection::kLtr) { | 100 if (space.Direction() == TextDirection::kLtr) { |
89 left = static_position.LeftPosition(container_size.width, *width, | 101 left = static_position.LeftPosition(container_size.width, *width, |
90 *margin_left, *margin_right); | 102 *margin_left, *margin_right); |
91 } else { | 103 } else { |
92 right = static_position.RightPosition(container_size.width, *width, | 104 right = static_position.RightPosition(container_size.width, *width, |
93 *margin_left, *margin_right); | 105 *margin_left, *margin_right); |
94 } | 106 } |
95 } else if (left && right && width) { | 107 } else if (left && right && width) { |
96 // Standard: "If left, right, and width are not auto:" | 108 // Standard: "If left, right, and width are not auto:" |
97 // Compute margins. | 109 // Compute margins. |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
133 margin_left = LayoutUnit(); | 145 margin_left = LayoutUnit(); |
134 if (!margin_right) | 146 if (!margin_right) |
135 margin_right = LayoutUnit(); | 147 margin_right = LayoutUnit(); |
136 | 148 |
137 // Rules 1 through 3, 2 out of 3 are unknown. | 149 // Rules 1 through 3, 2 out of 3 are unknown. |
138 if (!left && !width) { | 150 if (!left && !width) { |
139 // Rule 1: left/width are unknown. | 151 // Rule 1: left/width are unknown. |
140 DCHECK(right.has_value()); | 152 DCHECK(right.has_value()); |
141 DCHECK(child_minmax.has_value()); | 153 DCHECK(child_minmax.has_value()); |
142 width = child_minmax->ShrinkToFit(container_size.width); | 154 width = child_minmax->ShrinkToFit(container_size.width); |
155 width = ConstrainByMinMax(*width, min_width, max_width); | |
143 } else if (!left && !right) { | 156 } else if (!left && !right) { |
144 // Rule 2. | 157 // Rule 2. |
145 DCHECK(width.has_value()); | 158 DCHECK(width.has_value()); |
146 if (space.Direction() == TextDirection::kLtr) | 159 if (space.Direction() == TextDirection::kLtr) |
147 left = static_position.LeftPosition(container_size.width, *width, | 160 left = static_position.LeftPosition(container_size.width, *width, |
148 *margin_left, *margin_right); | 161 *margin_left, *margin_right); |
149 else | 162 else |
150 right = static_position.RightPosition(container_size.width, *width, | 163 right = static_position.RightPosition(container_size.width, *width, |
151 *margin_left, *margin_right); | 164 *margin_left, *margin_right); |
152 } else if (!width && !right) { | 165 } else if (!width && !right) { |
153 // Rule 3. | 166 // Rule 3. |
154 DCHECK(child_minmax.has_value()); | 167 DCHECK(child_minmax.has_value()); |
155 width = child_minmax->ShrinkToFit(container_size.width); | 168 width = child_minmax->ShrinkToFit(container_size.width); |
169 width = ConstrainByMinMax(*width, min_width, max_width); | |
156 } | 170 } |
157 | 171 |
158 // Rules 4 through 6, 1 out of 3 are unknown. | 172 // Rules 4 through 6, 1 out of 3 are unknown. |
159 if (!left) { | 173 if (!left) { |
160 left = | 174 left = |
161 container_size.width - *right - *width - *margin_left - *margin_right; | 175 container_size.width - *right - *width - *margin_left - *margin_right; |
162 } else if (!right) { | 176 } else if (!right) { |
163 right = | 177 right = |
164 container_size.width - *left - *width - *margin_left - *margin_right; | 178 container_size.width - *left - *width - *margin_left - *margin_right; |
165 } else if (!width) { | 179 } else if (!width) { |
166 width = | 180 width = |
167 container_size.width - *left - *right - *margin_left - *margin_right; | 181 container_size.width - *left - *right - *margin_left - *margin_right; |
168 } | 182 } |
169 DCHECK_EQ(container_size.width, | 183 DCHECK_EQ(container_size.width, |
170 *left + *right + *margin_left + *margin_right + *width); | 184 *left + *right + *margin_left + *margin_right + *width); |
171 | 185 |
186 width = ConstrainByMinMax(*width, min_width, max_width); | |
172 // Negative widths are not allowed. | 187 // Negative widths are not allowed. |
173 width = std::max(*width, border_padding); | 188 width = std::max(*width, border_padding); |
174 | 189 |
175 position->inset.left = *left + *margin_left; | 190 position->inset.left = *left + *margin_left; |
176 position->inset.right = *right + *margin_right; | 191 position->inset.right = *right + *margin_right; |
177 position->size.width = *width; | 192 position->size.width = *width; |
178 } | 193 } |
179 | 194 |
195 LayoutUnit ResolveHeight(const Length& height, | |
cbiesinger
2017/01/19 22:49:13
I would move this function to the top, under Resol
atotic
2017/01/19 23:47:43
done.
| |
196 const NGConstraintSpace& space, | |
197 const ComputedStyle& style, | |
198 const Optional<MinAndMaxContentSizes>& child_minmax) { | |
199 if (space.WritingMode() != kHorizontalTopBottom) | |
200 return ResolveInlineLength(space, style, child_minmax, height, | |
201 LengthResolveType::kContentSize); | |
202 LayoutUnit computed_height = | |
203 child_minmax.has_value() ? child_minmax->max_content : LayoutUnit(); | |
204 return ResolveBlockLength(space, style, height, computed_height, | |
205 LengthResolveType::kContentSize); | |
206 } | |
180 // Implements absolute vertical size resolution algorithm. | 207 // Implements absolute vertical size resolution algorithm. |
181 // https://www.w3.org/TR/css-position-3/#abs-non-replaced-height | 208 // https://www.w3.org/TR/css-position-3/#abs-non-replaced-height |
182 void ComputeAbsoluteVertical( | 209 void ComputeAbsoluteVertical( |
183 const NGConstraintSpace& space, | 210 const NGConstraintSpace& space, |
184 const ComputedStyle& style, | 211 const ComputedStyle& style, |
185 const NGStaticPosition& static_position, | 212 const NGStaticPosition& static_position, |
186 const Optional<MinAndMaxContentSizes>& child_minmax, | 213 const Optional<MinAndMaxContentSizes>& child_minmax, |
187 NGAbsolutePhysicalPosition* position) { | 214 NGAbsolutePhysicalPosition* position) { |
188 NGLogicalSize percentage_logical = space.PercentageResolutionSize(); | 215 NGLogicalSize percentage_logical = space.PercentageResolutionSize(); |
189 NGPhysicalSize percentage_physical = | 216 NGPhysicalSize percentage_physical = |
(...skipping 15 matching lines...) Expand all Loading... | |
205 valueForLength(style.marginBottom(), percentage_logical.inline_size); | 232 valueForLength(style.marginBottom(), percentage_logical.inline_size); |
206 Optional<LayoutUnit> top; | 233 Optional<LayoutUnit> top; |
207 if (!style.top().isAuto()) | 234 if (!style.top().isAuto()) |
208 top = valueForLength(style.top(), percentage_physical.height); | 235 top = valueForLength(style.top(), percentage_physical.height); |
209 Optional<LayoutUnit> bottom; | 236 Optional<LayoutUnit> bottom; |
210 if (!style.bottom().isAuto()) | 237 if (!style.bottom().isAuto()) |
211 bottom = valueForLength(style.bottom(), percentage_physical.height); | 238 bottom = valueForLength(style.bottom(), percentage_physical.height); |
212 LayoutUnit border_padding = | 239 LayoutUnit border_padding = |
213 border_top + border_bottom + padding_top + padding_bottom; | 240 border_top + border_bottom + padding_top + padding_bottom; |
214 | 241 |
242 Optional<LayoutUnit> min_height; | |
243 if (!style.minHeight().isAuto()) | |
244 min_height = ResolveHeight(style.minHeight(), space, style, child_minmax); | |
245 Optional<LayoutUnit> max_height; | |
246 if (!style.maxHeight().isMaxSizeNone()) | |
247 max_height = ResolveHeight(style.maxHeight(), space, style, child_minmax); | |
215 Optional<LayoutUnit> height; | 248 Optional<LayoutUnit> height; |
216 if (!style.height().isAuto()) { | 249 if (!style.height().isAuto()) { |
217 if (space.WritingMode() == kHorizontalTopBottom) { | 250 height = ResolveHeight(style.height(), space, style, child_minmax); |
218 LayoutUnit computed_height = | 251 height = ConstrainByMinMax(*height, min_height, max_height); |
219 child_minmax.has_value() ? child_minmax->max_content : LayoutUnit(); | |
220 height = ResolveBlockLength(space, style, style.height(), computed_height, | |
221 LengthResolveType::kContentSize); | |
222 } else { | |
223 height = ResolveInlineLength(space, style, child_minmax, style.height(), | |
224 LengthResolveType::kContentSize); | |
225 } | |
226 } | 252 } |
227 | 253 |
228 NGPhysicalSize container_size = | 254 NGPhysicalSize container_size = |
229 space.AvailableSize().ConvertToPhysical(space.WritingMode()); | 255 space.AvailableSize().ConvertToPhysical(space.WritingMode()); |
230 DCHECK(container_size.height != NGSizeIndefinite); | 256 DCHECK(container_size.height != NGSizeIndefinite); |
231 | 257 |
232 // Solving the equation: | 258 // Solving the equation: |
233 // top + marginTop + height + marginBottom + bottom | 259 // top + marginTop + height + marginBottom + bottom |
234 // + border_padding = container height | 260 // + border_padding = container height |
235 if (!top && !bottom && !height) { | 261 if (!top && !bottom && !height) { |
236 // Standard: "If all three of top, height, and bottom are auto:" | 262 // Standard: "If all three of top, height, and bottom are auto:" |
237 if (!margin_top) | 263 if (!margin_top) |
238 margin_top = LayoutUnit(); | 264 margin_top = LayoutUnit(); |
239 if (!margin_bottom) | 265 if (!margin_bottom) |
240 margin_bottom = LayoutUnit(); | 266 margin_bottom = LayoutUnit(); |
241 DCHECK(child_minmax.has_value()); | 267 DCHECK(child_minmax.has_value()); |
242 height = child_minmax->ShrinkToFit(container_size.height); | 268 height = child_minmax->ShrinkToFit(container_size.height); |
269 height = ConstrainByMinMax(*height, min_height, max_height); | |
243 top = static_position.TopPosition(container_size.height, *height, | 270 top = static_position.TopPosition(container_size.height, *height, |
244 *margin_top, *margin_bottom); | 271 *margin_top, *margin_bottom); |
245 } else if (top && bottom && height) { | 272 } else if (top && bottom && height) { |
246 // Standard: "If top, bottom, and height are not auto:" | 273 // Standard: "If top, bottom, and height are not auto:" |
247 // Compute margins. | 274 // Compute margins. |
248 LayoutUnit margin_space = container_size.height - *top - *bottom - *height; | 275 LayoutUnit margin_space = container_size.height - *top - *bottom - *height; |
249 // When both margins are auto. | 276 // When both margins are auto. |
250 if (!margin_top && !margin_bottom) { | 277 if (!margin_top && !margin_bottom) { |
251 if (margin_space > 0) { | 278 if (margin_space > 0) { |
252 margin_top = margin_space / 2; | 279 margin_top = margin_space / 2; |
(...skipping 19 matching lines...) Expand all Loading... | |
272 margin_top = LayoutUnit(); | 299 margin_top = LayoutUnit(); |
273 if (!margin_bottom) | 300 if (!margin_bottom) |
274 margin_bottom = LayoutUnit(); | 301 margin_bottom = LayoutUnit(); |
275 | 302 |
276 // Rules 1 through 3, 2 out of 3 are unknown, fix 1. | 303 // Rules 1 through 3, 2 out of 3 are unknown, fix 1. |
277 if (!top && !height) { | 304 if (!top && !height) { |
278 // Rule 1. | 305 // Rule 1. |
279 DCHECK(bottom.has_value()); | 306 DCHECK(bottom.has_value()); |
280 DCHECK(child_minmax.has_value()); | 307 DCHECK(child_minmax.has_value()); |
281 height = child_minmax->ShrinkToFit(container_size.height); | 308 height = child_minmax->ShrinkToFit(container_size.height); |
309 height = ConstrainByMinMax(*height, min_height, max_height); | |
282 } else if (!top && !bottom) { | 310 } else if (!top && !bottom) { |
283 // Rule 2. | 311 // Rule 2. |
284 DCHECK(height.has_value()); | 312 DCHECK(height.has_value()); |
285 top = static_position.TopPosition(container_size.height, *height, | 313 top = static_position.TopPosition(container_size.height, *height, |
286 *margin_top, *margin_bottom); | 314 *margin_top, *margin_bottom); |
287 } else if (!height && !bottom) { | 315 } else if (!height && !bottom) { |
288 // Rule 3. | 316 // Rule 3. |
289 DCHECK(child_minmax.has_value()); | 317 DCHECK(child_minmax.has_value()); |
290 height = child_minmax->ShrinkToFit(container_size.height); | 318 height = child_minmax->ShrinkToFit(container_size.height); |
319 height = ConstrainByMinMax(*height, min_height, max_height); | |
291 } | 320 } |
292 | 321 |
293 // Rules 4 through 6, 1 out of 3 are unknown. | 322 // Rules 4 through 6, 1 out of 3 are unknown. |
294 if (!top) { | 323 if (!top) { |
295 top = container_size.height - *bottom - *height - *margin_top - | 324 top = container_size.height - *bottom - *height - *margin_top - |
296 *margin_bottom; | 325 *margin_bottom; |
297 } else if (!bottom) { | 326 } else if (!bottom) { |
298 bottom = | 327 bottom = |
299 container_size.height - *top - *height - *margin_top - *margin_bottom; | 328 container_size.height - *top - *height - *margin_top - *margin_bottom; |
300 } else if (!height) { | 329 } else if (!height) { |
301 height = | 330 height = |
302 container_size.height - *top - *bottom - *margin_top - *margin_bottom; | 331 container_size.height - *top - *bottom - *margin_top - *margin_bottom; |
303 } | 332 } |
304 DCHECK_EQ(container_size.height, | 333 DCHECK_EQ(container_size.height, |
305 *top + *bottom + *margin_top + *margin_bottom + *height); | 334 *top + *bottom + *margin_top + *margin_bottom + *height); |
306 | 335 |
336 height = ConstrainByMinMax(*height, min_height, max_height); | |
307 // Negative heights are not allowed. | 337 // Negative heights are not allowed. |
308 height = std::max(*height, border_padding); | 338 height = std::max(*height, border_padding); |
309 | 339 |
310 position->inset.top = *top + *margin_top; | 340 position->inset.top = *top + *margin_top; |
311 position->inset.bottom = *bottom + *margin_bottom; | 341 position->inset.bottom = *bottom + *margin_bottom; |
312 position->size.height = *height; | 342 position->size.height = *height; |
313 } | 343 } |
314 | 344 |
315 } // namespace | 345 } // namespace |
316 | 346 |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
379 if (style.isHorizontalWritingMode()) | 409 if (style.isHorizontalWritingMode()) |
380 ComputeAbsoluteVertical(space, style, static_position, child_minmax, | 410 ComputeAbsoluteVertical(space, style, static_position, child_minmax, |
381 position); | 411 position); |
382 else { | 412 else { |
383 ComputeAbsoluteHorizontal(space, style, static_position, child_minmax, | 413 ComputeAbsoluteHorizontal(space, style, static_position, child_minmax, |
384 position); | 414 position); |
385 } | 415 } |
386 } | 416 } |
387 | 417 |
388 } // namespace blink | 418 } // namespace blink |
OLD | NEW |