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

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: Clamp width/height to minmax values 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 LengthResolveType resolve_type) {
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 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
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
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
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
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
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
OLDNEW
« no previous file with comments | « third_party/WebKit/LayoutTests/TestExpectations ('k') | third_party/WebKit/Source/core/layout/ng/ng_absolute_utils_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698