Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2)

Side by Side Diff: third_party/WebKit/Source/core/layout/ng/ng_absolute_utils.cc

Issue 2643043003: Constrain width/height to minmax values (Closed)
Patch Set: Fix copypaste error: ResolveWidth->ResolveHeight Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698