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

Side by Side Diff: third_party/WebKit/Source/core/layout/LayoutFlexibleBox.cpp

Issue 1639723003: [css-flexbox] Use correct aspect ratio for min-size: auto (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: more tests & a bugfix Created 4 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
« no previous file with comments | « third_party/WebKit/Source/core/layout/LayoutFlexibleBox.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2011 Google Inc. All rights reserved. 2 * Copyright (C) 2011 Google Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are 5 * modification, are permitted provided that the following conditions are
6 * met: 6 * met:
7 * 7 *
8 * * Redistributions of source code must retain the above copyright 8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above 10 * * Redistributions in binary form must reproduce the above
(...skipping 24 matching lines...) Expand all
35 #include "core/layout/TextAutosizer.h" 35 #include "core/layout/TextAutosizer.h"
36 #include "core/paint/BlockPainter.h" 36 #include "core/paint/BlockPainter.h"
37 #include "core/paint/PaintLayer.h" 37 #include "core/paint/PaintLayer.h"
38 #include "core/style/ComputedStyle.h" 38 #include "core/style/ComputedStyle.h"
39 #include "platform/LengthFunctions.h" 39 #include "platform/LengthFunctions.h"
40 #include "wtf/MathExtras.h" 40 #include "wtf/MathExtras.h"
41 #include <limits> 41 #include <limits>
42 42
43 namespace blink { 43 namespace blink {
44 44
45 static bool hasAspectRatio(const LayoutBox& child)
46 {
47 return child.isImage() || child.isCanvas() || child.isVideo();
48 }
49
45 struct LayoutFlexibleBox::LineContext { 50 struct LayoutFlexibleBox::LineContext {
46 LineContext(LayoutUnit crossAxisOffset, LayoutUnit crossAxisExtent, size_t n umberOfChildren, LayoutUnit maxAscent) 51 LineContext(LayoutUnit crossAxisOffset, LayoutUnit crossAxisExtent, size_t n umberOfChildren, LayoutUnit maxAscent)
47 : crossAxisOffset(crossAxisOffset) 52 : crossAxisOffset(crossAxisOffset)
48 , crossAxisExtent(crossAxisExtent) 53 , crossAxisExtent(crossAxisExtent)
49 , numberOfChildren(numberOfChildren) 54 , numberOfChildren(numberOfChildren)
50 , maxAscent(maxAscent) 55 , maxAscent(maxAscent)
51 { 56 {
52 } 57 }
53 58
54 LayoutUnit crossAxisOffset; 59 LayoutUnit crossAxisOffset;
(...skipping 390 matching lines...) Expand 10 before | Expand all | Expand 10 after
445 // Otherwise we need the logical height. 450 // Otherwise we need the logical height.
446 if (isHorizontalFlow() != child.styleRef().isHorizontalWritingMode()) { 451 if (isHorizontalFlow() != child.styleRef().isHorizontalWritingMode()) {
447 // We don't have to check for "auto" here - computeContentLogicalHeight will just return -1 for that case anyway. 452 // We don't have to check for "auto" here - computeContentLogicalHeight will just return -1 for that case anyway.
448 // It's safe to access scrollbarLogicalHeight here because computeNextFl exLine will have already 453 // It's safe to access scrollbarLogicalHeight here because computeNextFl exLine will have already
449 // forced layout on the child. 454 // forced layout on the child.
450 return child.computeContentLogicalHeight(sizeType, size, child.contentLo gicalHeight()) + child.scrollbarLogicalHeight(); 455 return child.computeContentLogicalHeight(sizeType, size, child.contentLo gicalHeight()) + child.scrollbarLogicalHeight();
451 } 456 }
452 // computeLogicalWidth always re-computes the intrinsic widths. However, whe n our logical width is auto, 457 // computeLogicalWidth always re-computes the intrinsic widths. However, whe n our logical width is auto,
453 // we can just use our cached value. So let's do that here. (Compare code in LayoutBlock::computePreferredLogicalWidths) 458 // we can just use our cached value. So let's do that here. (Compare code in LayoutBlock::computePreferredLogicalWidths)
454 LayoutUnit borderAndPadding = child.borderAndPaddingLogicalWidth(); 459 LayoutUnit borderAndPadding = child.borderAndPaddingLogicalWidth();
455 if (child.styleRef().logicalWidth().isAuto()) { 460 if (child.styleRef().logicalWidth().isAuto() && !hasAspectRatio(child)) {
456 if (size.type() == MinContent) 461 if (size.type() == MinContent)
457 return child.minPreferredLogicalWidth() - borderAndPadding; 462 return child.minPreferredLogicalWidth() - borderAndPadding;
458 if (size.type() == MaxContent) 463 if (size.type() == MaxContent)
459 return child.maxPreferredLogicalWidth() - borderAndPadding; 464 return child.maxPreferredLogicalWidth() - borderAndPadding;
460 } 465 }
461 return child.computeLogicalWidthUsing(sizeType, size, contentLogicalWidth(), this) - borderAndPadding; 466 return child.computeLogicalWidthUsing(sizeType, size, contentLogicalWidth(), this) - borderAndPadding;
462 } 467 }
463 468
464 LayoutFlexibleBox::TransformedWritingMode LayoutFlexibleBox::transformedWritingM ode() const 469 LayoutFlexibleBox::TransformedWritingMode LayoutFlexibleBox::transformedWritingM ode() const
465 { 470 {
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after
618 LayoutUnit LayoutFlexibleBox::crossAxisScrollbarExtentForChild(const LayoutBox& child) const 623 LayoutUnit LayoutFlexibleBox::crossAxisScrollbarExtentForChild(const LayoutBox& child) const
619 { 624 {
620 return isHorizontalFlow() ? child.horizontalScrollbarHeight() : child.vertic alScrollbarWidth(); 625 return isHorizontalFlow() ? child.horizontalScrollbarHeight() : child.vertic alScrollbarWidth();
621 } 626 }
622 627
623 LayoutPoint LayoutFlexibleBox::flowAwareLocationForChild(const LayoutBox& child) const 628 LayoutPoint LayoutFlexibleBox::flowAwareLocationForChild(const LayoutBox& child) const
624 { 629 {
625 return isHorizontalFlow() ? child.location() : child.location().transposedPo int(); 630 return isHorizontalFlow() ? child.location() : child.location().transposedPo int();
626 } 631 }
627 632
633 bool LayoutFlexibleBox::useChildAspectRatio(const LayoutBox& child) const
634 {
635 if (!hasAspectRatio(child))
636 return false;
637 if (child.intrinsicSize().height() == 0) {
638 // We can't compute a ratio in this case.
639 return false;
640 }
641 Length crossSize;
642 if (isHorizontalFlow())
643 crossSize = child.styleRef().height();
644 else
645 crossSize = child.styleRef().width();
646 return crossAxisLengthIsDefinite(child, crossSize);
647 }
648
649 LayoutUnit LayoutFlexibleBox::computeMainSizeFromAspectRatio(const LayoutBox& ch ild, Length crossSizeLength) const
650 {
651 ASSERT(useChildAspectRatio(child));
652
653 LayoutUnit crossSize;
654 if (crossSizeLength.isFixed()) {
655 crossSize = crossSizeLength.value();
656 } else {
657 ASSERT(crossSizeLength.hasPercent());
658 crossSize = hasOrthogonalFlow(child) ?
659 adjustBorderBoxLogicalWidthForBoxSizing(valueForLength(crossSizeLeng th, contentWidth())) :
660 child.computePercentageLogicalHeight(crossSizeLength);
661 }
662
663 const LayoutSize& childIntrinsicSize = child.intrinsicSize();
664 double ratio = childIntrinsicSize.width().toFloat() / childIntrinsicSize.hei ght().toFloat();
665 if (isHorizontalFlow())
666 return crossSize * ratio;
667 return crossSize / ratio;
668 }
669
628 void LayoutFlexibleBox::setFlowAwareLocationForChild(LayoutBox& child, const Lay outPoint& location) 670 void LayoutFlexibleBox::setFlowAwareLocationForChild(LayoutBox& child, const Lay outPoint& location)
629 { 671 {
630 if (isHorizontalFlow()) 672 if (isHorizontalFlow())
631 child.setLocationAndUpdateOverflowControlsIfNeeded(location); 673 child.setLocationAndUpdateOverflowControlsIfNeeded(location);
632 else 674 else
633 child.setLocationAndUpdateOverflowControlsIfNeeded(location.transposedPo int()); 675 child.setLocationAndUpdateOverflowControlsIfNeeded(location.transposedPo int());
634 } 676 }
635 677
636 LayoutUnit LayoutFlexibleBox::mainAxisBorderAndPaddingExtentForChild(const Layou tBox& child) const 678 LayoutUnit LayoutFlexibleBox::mainAxisBorderAndPaddingExtentForChild(const Layou tBox& child) const
637 { 679 {
638 return isHorizontalFlow() ? child.borderAndPaddingWidth() : child.borderAndP addingHeight(); 680 return isHorizontalFlow() ? child.borderAndPaddingWidth() : child.borderAndP addingHeight();
639 } 681 }
640 682
641 bool LayoutFlexibleBox::mainAxisLengthIsDefinite(const LayoutBox& child, const L ength& flexBasis) const 683 bool LayoutFlexibleBox::mainAxisLengthIsDefinite(const LayoutBox& child, const L ength& flexBasis) const
642 { 684 {
643 if (flexBasis.isAuto()) 685 if (flexBasis.isAuto())
644 return false; 686 return false;
645 if (flexBasis.hasPercent()) { 687 if (flexBasis.hasPercent()) {
646 return isColumnFlow() ? 688 return isColumnFlow() ?
647 child.computePercentageLogicalHeight(flexBasis) != -1 : 689 child.computePercentageLogicalHeight(flexBasis) != -1 :
648 hasDefiniteLogicalWidth(); 690 hasDefiniteLogicalWidth();
649 } 691 }
650 return true; 692 return true;
651 } 693 }
652 694
695 bool LayoutFlexibleBox::crossAxisLengthIsDefinite(const LayoutBox& child, const Length& length) const
696 {
697 if (length.isAuto())
698 return false;
699 if (length.hasPercent()) {
700 return hasOrthogonalFlow(child) ?
701 hasDefiniteLogicalWidth() :
702 child.computePercentageLogicalHeight(length) != -1;
703
leviw_travelin_and_unemployed 2016/01/27 23:18:45 This seems like a weird empty line </whitespace-je
cbiesinger 2016/01/27 23:25:25 Oh oops. Removed.
704 }
705 return true;
706 }
707
653 bool LayoutFlexibleBox::childFlexBaseSizeRequiresLayout(const LayoutBox& child) const 708 bool LayoutFlexibleBox::childFlexBaseSizeRequiresLayout(const LayoutBox& child) const
654 { 709 {
655 return !mainAxisLengthIsDefinite(child, flexBasisForChild(child)) && ( 710 return !mainAxisLengthIsDefinite(child, flexBasisForChild(child)) && (
656 hasOrthogonalFlow(child) || crossAxisOverflowForChild(child) == OAUTO); 711 hasOrthogonalFlow(child) || crossAxisOverflowForChild(child) == OAUTO);
657 } 712 }
658 713
659 LayoutUnit LayoutFlexibleBox::computeInnerFlexBaseSizeForChild(LayoutBox& child, ChildLayoutType childLayoutType) 714 LayoutUnit LayoutFlexibleBox::computeInnerFlexBaseSizeForChild(LayoutBox& child, ChildLayoutType childLayoutType)
660 { 715 {
661 child.clearOverrideSize(); 716 child.clearOverrideSize();
662 717
(...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after
919 // css-flexbox section 4.5 974 // css-flexbox section 4.5
920 LayoutUnit contentSize = computeMainAxisExtentForChild(child, MinSize, L ength(MinContent)); 975 LayoutUnit contentSize = computeMainAxisExtentForChild(child, MinSize, L ength(MinContent));
921 ASSERT(contentSize >= 0); 976 ASSERT(contentSize >= 0);
922 if (maxExtent != -1 && contentSize > maxExtent) 977 if (maxExtent != -1 && contentSize > maxExtent)
923 contentSize = maxExtent; 978 contentSize = maxExtent;
924 979
925 Length mainSize = isHorizontalFlow() ? child.styleRef().width() : child. styleRef().height(); 980 Length mainSize = isHorizontalFlow() ? child.styleRef().width() : child. styleRef().height();
926 if (mainAxisLengthIsDefinite(child, mainSize)) { 981 if (mainAxisLengthIsDefinite(child, mainSize)) {
927 LayoutUnit resolvedMainSize = computeMainAxisExtentForChild(child, M ainOrPreferredSize, mainSize); 982 LayoutUnit resolvedMainSize = computeMainAxisExtentForChild(child, M ainOrPreferredSize, mainSize);
928 ASSERT(resolvedMainSize >= 0); 983 ASSERT(resolvedMainSize >= 0);
984 // TODO(cbiesinger): For items with an aspect ratio, clamp this size through the converted cross-size min/max size. crbug.com/249112
929 LayoutUnit specifiedSize = maxExtent != -1 ? std::min(resolvedMainSi ze, maxExtent) : resolvedMainSize; 985 LayoutUnit specifiedSize = maxExtent != -1 ? std::min(resolvedMainSi ze, maxExtent) : resolvedMainSize;
930 986
931 minExtent = std::min(specifiedSize, contentSize); 987 minExtent = std::min(specifiedSize, contentSize);
988 } else if (useChildAspectRatio(child)) {
989 Length crossSizeLength = isHorizontalFlow() ? child.styleRef().heigh t() : child.styleRef().width();
990 LayoutUnit transferredSize = computeMainSizeFromAspectRatio(child, c rossSizeLength);
991 minExtent = std::min(transferredSize, contentSize);
932 } else { 992 } else {
933 minExtent = contentSize; 993 minExtent = contentSize;
934 } 994 }
935 // TODO(cbiesinger): Implement aspect ratio handling (here, transferred size) - crbug.com/249112
936 } 995 }
937 ASSERT(minExtent >= 0); 996 ASSERT(minExtent >= 0);
938 return std::max(childSize, minExtent); 997 return std::max(childSize, minExtent);
939 } 998 }
940 999
941 bool LayoutFlexibleBox::computeNextFlexLine(OrderedFlexItemList& orderedChildren , LayoutUnit& sumFlexBaseSize, double& totalFlexGrow, double& totalFlexShrink, d ouble& totalWeightedFlexShrink, LayoutUnit& sumHypotheticalMainSize, bool relayo utChildren) 1000 bool LayoutFlexibleBox::computeNextFlexLine(OrderedFlexItemList& orderedChildren , LayoutUnit& sumFlexBaseSize, double& totalFlexGrow, double& totalFlexShrink, d ouble& totalWeightedFlexShrink, LayoutUnit& sumHypotheticalMainSize, bool relayo utChildren)
942 { 1001 {
943 orderedChildren.clear(); 1002 orderedChildren.clear();
944 sumFlexBaseSize = 0; 1003 sumFlexBaseSize = 0;
945 totalFlexGrow = totalFlexShrink = totalWeightedFlexShrink = 0; 1004 totalFlexGrow = totalFlexShrink = totalWeightedFlexShrink = 0;
(...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after
1170 // So the child will automatically stretch if our cross axis is the child's inline axis. That's the case if: 1229 // So the child will automatically stretch if our cross axis is the child's inline axis. That's the case if:
1171 // - We are horizontal and the child is in vertical writing mode 1230 // - We are horizontal and the child is in vertical writing mode
1172 // - We are vertical and the child is in horizontal writing mode 1231 // - We are vertical and the child is in horizontal writing mode
1173 // Otherwise, we need to stretch if the cross axis size is auto. 1232 // Otherwise, we need to stretch if the cross axis size is auto.
1174 if (alignmentForChild(child) != ItemPositionStretch) 1233 if (alignmentForChild(child) != ItemPositionStretch)
1175 return false; 1234 return false;
1176 1235
1177 if (isHorizontalFlow() != child.styleRef().isHorizontalWritingMode()) 1236 if (isHorizontalFlow() != child.styleRef().isHorizontalWritingMode())
1178 return false; 1237 return false;
1179 1238
1239 // TODO(cbiesinger): what about indefinite percentage heights?
1180 return isHorizontalFlow() ? child.styleRef().height().isAuto() : child.style Ref().width().isAuto(); 1240 return isHorizontalFlow() ? child.styleRef().height().isAuto() : child.style Ref().width().isAuto();
1181 } 1241 }
1182 1242
1183 bool LayoutFlexibleBox::childHasIntrinsicMainAxisSize(const LayoutBox& child) co nst 1243 bool LayoutFlexibleBox::childHasIntrinsicMainAxisSize(const LayoutBox& child) co nst
1184 { 1244 {
1185 bool result = false; 1245 bool result = false;
1186 if (isHorizontalFlow() != child.styleRef().isHorizontalWritingMode()) { 1246 if (isHorizontalFlow() != child.styleRef().isHorizontalWritingMode()) {
1187 Length childFlexBasis = flexBasisForChild(child); 1247 Length childFlexBasis = flexBasisForChild(child);
1188 Length childMinSize = isHorizontalFlow() ? child.style()->minWidth() : c hild.style()->minHeight(); 1248 Length childMinSize = isHorizontalFlow() ? child.style()->minWidth() : c hild.style()->minHeight();
1189 Length childMaxSize = isHorizontalFlow() ? child.style()->maxWidth() : c hild.style()->maxHeight(); 1249 Length childMaxSize = isHorizontalFlow() ? child.style()->maxWidth() : c hild.style()->maxHeight();
1190 if (childFlexBasis.isIntrinsic() || childMinSize.isIntrinsicOrAuto() || childMaxSize.isIntrinsic()) 1250 if (childFlexBasis.isIntrinsic() || childMinSize.isIntrinsicOrAuto() || childMaxSize.isIntrinsic())
1191 result = true; 1251 result = true;
1192 } 1252 }
1193 return result; 1253 return result;
1194 } 1254 }
1195 1255
1196 EOverflow LayoutFlexibleBox::mainAxisOverflowForChild(const LayoutBox& child) co nst 1256 EOverflow LayoutFlexibleBox::mainAxisOverflowForChild(const LayoutBox& child) co nst
1197 { 1257 {
1198 if (isHorizontalFlow()) 1258 if (isHorizontalFlow())
1199 return child.styleRef().overflowX(); 1259 return child.styleRef().overflowX();
1200 return child.styleRef().overflowY(); 1260 return child.styleRef().overflowY();
1201 } 1261 }
1202 1262
1203 EOverflow LayoutFlexibleBox::crossAxisOverflowForChild(const LayoutBox& child) c onst 1263 EOverflow LayoutFlexibleBox::crossAxisOverflowForChild(const LayoutBox& child) c onst
1204 { 1264 {
1205 if (isHorizontalFlow()) 1265 if (isHorizontalFlow())
1206 return child.styleRef().overflowY(); 1266 return child.styleRef().overflowY();
1207 return child.styleRef().overflowX(); 1267 return child.styleRef().overflowX();
1208 } 1268 }
1269
1209 void LayoutFlexibleBox::layoutAndPlaceChildren(LayoutUnit& crossAxisOffset, cons t OrderedFlexItemList& children, const Vector<LayoutUnit, 16>& childSizes, Layou tUnit availableFreeSpace, bool relayoutChildren, SubtreeLayoutScope& layoutScope , Vector<LineContext>& lineContexts) 1270 void LayoutFlexibleBox::layoutAndPlaceChildren(LayoutUnit& crossAxisOffset, cons t OrderedFlexItemList& children, const Vector<LayoutUnit, 16>& childSizes, Layou tUnit availableFreeSpace, bool relayoutChildren, SubtreeLayoutScope& layoutScope , Vector<LineContext>& lineContexts)
1210 { 1271 {
1211 ASSERT(childSizes.size() == children.size()); 1272 ASSERT(childSizes.size() == children.size());
1212 1273
1213 size_t numberOfChildrenForJustifyContent = numberOfInFlowPositionedChildren( children); 1274 size_t numberOfChildrenForJustifyContent = numberOfInFlowPositionedChildren( children);
1214 LayoutUnit autoMarginOffset = autoMarginOffsetInMainAxis(children, available FreeSpace); 1275 LayoutUnit autoMarginOffset = autoMarginOffsetInMainAxis(children, available FreeSpace);
1215 LayoutUnit mainAxisOffset = flowAwareBorderStart() + flowAwarePaddingStart() ; 1276 LayoutUnit mainAxisOffset = flowAwareBorderStart() + flowAwarePaddingStart() ;
1216 mainAxisOffset += initialJustifyContentOffset(availableFreeSpace, style()->j ustifyContentPosition(), style()->justifyContentDistribution(), numberOfChildren ForJustifyContent); 1277 mainAxisOffset += initialJustifyContentOffset(availableFreeSpace, style()->j ustifyContentPosition(), style()->justifyContentDistribution(), numberOfChildren ForJustifyContent);
1217 if (style()->flexDirection() == FlowRowReverse) 1278 if (style()->flexDirection() == FlowRowReverse)
1218 mainAxisOffset += isHorizontalFlow() ? verticalScrollbarWidth() : horizo ntalScrollbarHeight(); 1279 mainAxisOffset += isHorizontalFlow() ? verticalScrollbarWidth() : horizo ntalScrollbarHeight();
(...skipping 326 matching lines...) Expand 10 before | Expand all | Expand 10 after
1545 ASSERT(child); 1606 ASSERT(child);
1546 LayoutUnit lineCrossAxisExtent = lineContexts[lineNumber].crossAxisE xtent; 1607 LayoutUnit lineCrossAxisExtent = lineContexts[lineNumber].crossAxisE xtent;
1547 LayoutUnit originalOffset = lineContexts[lineNumber].crossAxisOffset - crossAxisStartEdge; 1608 LayoutUnit originalOffset = lineContexts[lineNumber].crossAxisOffset - crossAxisStartEdge;
1548 LayoutUnit newOffset = contentExtent - originalOffset - lineCrossAxi sExtent; 1609 LayoutUnit newOffset = contentExtent - originalOffset - lineCrossAxi sExtent;
1549 adjustAlignmentForChild(*child, newOffset - originalOffset); 1610 adjustAlignmentForChild(*child, newOffset - originalOffset);
1550 } 1611 }
1551 } 1612 }
1552 } 1613 }
1553 1614
1554 } // namespace blink 1615 } // namespace blink
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/core/layout/LayoutFlexibleBox.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698