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