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

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

Issue 1470373003: [css-flexbox] Correctly implement flex factors < 1 (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: add a comment Created 5 years 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 673 matching lines...) Expand 10 before | Expand all | Expand 10 after
684 } 684 }
685 return std::max(LayoutUnit(), computeMainAxisExtentForChild(child, MainOrPre ferredSize, flexBasis)); 685 return std::max(LayoutUnit(), computeMainAxisExtentForChild(child, MainOrPre ferredSize, flexBasis));
686 } 686 }
687 687
688 void LayoutFlexibleBox::layoutFlexItems(bool relayoutChildren, SubtreeLayoutScop e& layoutScope) 688 void LayoutFlexibleBox::layoutFlexItems(bool relayoutChildren, SubtreeLayoutScop e& layoutScope)
689 { 689 {
690 Vector<LineContext> lineContexts; 690 Vector<LineContext> lineContexts;
691 OrderedFlexItemList orderedChildren; 691 OrderedFlexItemList orderedChildren;
692 LayoutUnit sumFlexBaseSize; 692 LayoutUnit sumFlexBaseSize;
693 double totalFlexGrow; 693 double totalFlexGrow;
694 double totalFlexShrink;
694 double totalWeightedFlexShrink; 695 double totalWeightedFlexShrink;
695 LayoutUnit sumHypotheticalMainSize; 696 LayoutUnit sumHypotheticalMainSize;
696 697
697 Vector<LayoutUnit, 16> childSizes; 698 Vector<LayoutUnit, 16> childSizes;
698 699
699 m_orderIterator.first(); 700 m_orderIterator.first();
700 LayoutUnit crossAxisOffset = flowAwareBorderBefore() + flowAwarePaddingBefor e(); 701 LayoutUnit crossAxisOffset = flowAwareBorderBefore() + flowAwarePaddingBefor e();
701 while (computeNextFlexLine(orderedChildren, sumFlexBaseSize, totalFlexGrow, totalWeightedFlexShrink, sumHypotheticalMainSize, relayoutChildren)) { 702 while (computeNextFlexLine(orderedChildren, sumFlexBaseSize, totalFlexGrow, totalFlexShrink, totalWeightedFlexShrink, sumHypotheticalMainSize, relayoutChild ren)) {
702 LayoutUnit containerMainInnerSize = mainAxisContentExtent(sumHypothetica lMainSize); 703 LayoutUnit containerMainInnerSize = mainAxisContentExtent(sumHypothetica lMainSize);
704 // availableFreeSpace is the initial amount of free space in this flexbo x.
705 // remainingFreeSpace starts out at the same value but as we place and l ay out
706 // flex items we subtract from it. Note that both values can be negative .
703 LayoutUnit availableFreeSpace = containerMainInnerSize - sumFlexBaseSize ; 707 LayoutUnit availableFreeSpace = containerMainInnerSize - sumFlexBaseSize ;
708 LayoutUnit remainingFreeSpace = availableFreeSpace;
704 FlexSign flexSign = (sumHypotheticalMainSize < containerMainInnerSize) ? PositiveFlexibility : NegativeFlexibility; 709 FlexSign flexSign = (sumHypotheticalMainSize < containerMainInnerSize) ? PositiveFlexibility : NegativeFlexibility;
705 InflexibleFlexItemSize inflexibleItems; 710 InflexibleFlexItemSize inflexibleItems;
706 childSizes.reserveCapacity(orderedChildren.size()); 711 childSizes.reserveCapacity(orderedChildren.size());
707 while (!resolveFlexibleLengths(flexSign, orderedChildren, availableFreeS pace, totalFlexGrow, totalWeightedFlexShrink, inflexibleItems, childSizes)) { 712 while (!resolveFlexibleLengths(flexSign, orderedChildren, availableFreeS pace, remainingFreeSpace, totalFlexGrow, totalFlexShrink, totalWeightedFlexShrin k, inflexibleItems, childSizes)) {
708 ASSERT(totalFlexGrow >= 0 && totalWeightedFlexShrink >= 0); 713 ASSERT(totalFlexGrow >= 0 && totalWeightedFlexShrink >= 0);
709 ASSERT(inflexibleItems.size() > 0); 714 ASSERT(inflexibleItems.size() > 0);
710 } 715 }
711 716
712 layoutAndPlaceChildren(crossAxisOffset, orderedChildren, childSizes, ava ilableFreeSpace, relayoutChildren, layoutScope, lineContexts); 717 layoutAndPlaceChildren(crossAxisOffset, orderedChildren, childSizes, rem ainingFreeSpace, relayoutChildren, layoutScope, lineContexts);
713 } 718 }
714 if (hasLineIfEmpty()) { 719 if (hasLineIfEmpty()) {
715 // Even if computeNextFlexLine returns true, the flexbox might not have 720 // Even if computeNextFlexLine returns true, the flexbox might not have
716 // a line because all our children might be out of flow positioned. 721 // a line because all our children might be out of flow positioned.
717 // Instead of just checking if we have a line, make sure the flexbox 722 // Instead of just checking if we have a line, make sure the flexbox
718 // has at least a line's worth of height to cover this case. 723 // has at least a line's worth of height to cover this case.
719 LayoutUnit minHeight = minimumLogicalHeightForEmptyLine(); 724 LayoutUnit minHeight = minimumLogicalHeightForEmptyLine();
720 if (size().height() < minHeight) 725 if (size().height() < minHeight)
721 setLogicalHeight(minHeight); 726 setLogicalHeight(minHeight);
722 } 727 }
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after
920 minExtent = std::min(specifiedSize, contentSize); 925 minExtent = std::min(specifiedSize, contentSize);
921 } else { 926 } else {
922 minExtent = contentSize; 927 minExtent = contentSize;
923 } 928 }
924 // TODO(cbiesinger): Implement aspect ratio handling (here, transferred size) - crbug.com/249112 929 // TODO(cbiesinger): Implement aspect ratio handling (here, transferred size) - crbug.com/249112
925 } 930 }
926 ASSERT(minExtent >= 0); 931 ASSERT(minExtent >= 0);
927 return std::max(childSize, minExtent); 932 return std::max(childSize, minExtent);
928 } 933 }
929 934
930 bool LayoutFlexibleBox::computeNextFlexLine(OrderedFlexItemList& orderedChildren , LayoutUnit& sumFlexBaseSize, double& totalFlexGrow, double& totalWeightedFlexS hrink, LayoutUnit& sumHypotheticalMainSize, bool relayoutChildren) 935 bool LayoutFlexibleBox::computeNextFlexLine(OrderedFlexItemList& orderedChildren , LayoutUnit& sumFlexBaseSize, double& totalFlexGrow, double& totalFlexShrink, d ouble& totalWeightedFlexShrink, LayoutUnit& sumHypotheticalMainSize, bool relayo utChildren)
931 { 936 {
932 orderedChildren.clear(); 937 orderedChildren.clear();
933 sumFlexBaseSize = 0; 938 sumFlexBaseSize = 0;
934 totalFlexGrow = totalWeightedFlexShrink = 0; 939 totalFlexGrow = totalFlexShrink = totalWeightedFlexShrink = 0;
935 sumHypotheticalMainSize = 0; 940 sumHypotheticalMainSize = 0;
936 941
937 if (!m_orderIterator.currentChild()) 942 if (!m_orderIterator.currentChild())
938 return false; 943 return false;
939 944
940 LayoutUnit lineBreakLength = mainAxisContentExtent(LayoutUnit::max()); 945 LayoutUnit lineBreakLength = mainAxisContentExtent(LayoutUnit::max());
941 946
942 bool lineHasInFlowItem = false; 947 bool lineHasInFlowItem = false;
943 948
944 for (LayoutBox* child = m_orderIterator.currentChild(); child; child = m_ord erIterator.next()) { 949 for (LayoutBox* child = m_orderIterator.currentChild(); child; child = m_ord erIterator.next()) {
(...skipping 19 matching lines...) Expand all
964 969
965 LayoutUnit childMinMaxAppliedMainAxisExtent = adjustChildSizeForMinAndMa x(*child, childInnerFlexBaseSize); 970 LayoutUnit childMinMaxAppliedMainAxisExtent = adjustChildSizeForMinAndMa x(*child, childInnerFlexBaseSize);
966 LayoutUnit childHypotheticalMainSize = childMinMaxAppliedMainAxisExtent + childMainAxisMarginBorderPadding; 971 LayoutUnit childHypotheticalMainSize = childMinMaxAppliedMainAxisExtent + childMainAxisMarginBorderPadding;
967 972
968 if (isMultiline() && sumHypotheticalMainSize + childHypotheticalMainSize > lineBreakLength && lineHasInFlowItem) 973 if (isMultiline() && sumHypotheticalMainSize + childHypotheticalMainSize > lineBreakLength && lineHasInFlowItem)
969 break; 974 break;
970 orderedChildren.append(child); 975 orderedChildren.append(child);
971 lineHasInFlowItem = true; 976 lineHasInFlowItem = true;
972 sumFlexBaseSize += childOuterFlexBaseSize; 977 sumFlexBaseSize += childOuterFlexBaseSize;
973 totalFlexGrow += child->style()->flexGrow(); 978 totalFlexGrow += child->style()->flexGrow();
979 totalFlexShrink += child->style()->flexShrink();
974 totalWeightedFlexShrink += child->style()->flexShrink() * childInnerFlex BaseSize; 980 totalWeightedFlexShrink += child->style()->flexShrink() * childInnerFlex BaseSize;
975 sumHypotheticalMainSize += childHypotheticalMainSize; 981 sumHypotheticalMainSize += childHypotheticalMainSize;
976 } 982 }
977 return true; 983 return true;
978 } 984 }
979 985
980 void LayoutFlexibleBox::freezeViolations(const Vector<Violation>& violations, La youtUnit& availableFreeSpace, double& totalFlexGrow, double& totalWeightedFlexSh rink, InflexibleFlexItemSize& inflexibleItems) 986 void LayoutFlexibleBox::freezeViolations(const Vector<Violation>& violations, La youtUnit& availableFreeSpace, double& totalFlexGrow, double& totalFlexShrink, do uble& totalWeightedFlexShrink, InflexibleFlexItemSize& inflexibleItems)
981 { 987 {
982 for (size_t i = 0; i < violations.size(); ++i) { 988 for (size_t i = 0; i < violations.size(); ++i) {
983 LayoutBox* child = violations[i].child; 989 LayoutBox* child = violations[i].child;
984 LayoutUnit childSize = violations[i].childSize; 990 LayoutUnit childSize = violations[i].childSize;
985 availableFreeSpace -= childSize - violations[i].childInnerFlexBaseSize; 991 availableFreeSpace -= childSize - violations[i].childInnerFlexBaseSize;
986 totalFlexGrow -= child->style()->flexGrow(); 992 totalFlexGrow -= child->style()->flexGrow();
993 totalFlexShrink -= child->style()->flexShrink();
987 totalWeightedFlexShrink -= child->style()->flexShrink() * violations[i]. childInnerFlexBaseSize; 994 totalWeightedFlexShrink -= child->style()->flexShrink() * violations[i]. childInnerFlexBaseSize;
988 // totalWeightedFlexShrink can be negative when we exceed the precision of a double when we initially 995 // totalWeightedFlexShrink can be negative when we exceed the precision of a double when we initially
989 // calcuate totalWeightedFlexShrink. We then subtract each child's weigh ted flex shrink with full precision, 996 // calcuate totalWeightedFlexShrink. We then subtract each child's weigh ted flex shrink with full precision,
990 // now leading to a negative result. See css3/flexbox/large-flex-shrink- assert.html 997 // now leading to a negative result. See css3/flexbox/large-flex-shrink- assert.html
991 totalWeightedFlexShrink = std::max(totalWeightedFlexShrink, 0.0); 998 totalWeightedFlexShrink = std::max(totalWeightedFlexShrink, 0.0);
992 inflexibleItems.set(child, childSize); 999 inflexibleItems.set(child, childSize);
993 } 1000 }
994 } 1001 }
995 1002
996 // Returns true if we successfully ran the algorithm and sized the flex items. 1003 // Returns true if we successfully ran the algorithm and sized the flex items.
997 bool LayoutFlexibleBox::resolveFlexibleLengths(FlexSign flexSign, const OrderedF lexItemList& children, LayoutUnit& availableFreeSpace, double& totalFlexGrow, do uble& totalWeightedFlexShrink, InflexibleFlexItemSize& inflexibleItems, Vector<L ayoutUnit, 16>& childSizes) 1004 bool LayoutFlexibleBox::resolveFlexibleLengths(FlexSign flexSign, const OrderedF lexItemList& children, LayoutUnit availableFreeSpace, LayoutUnit& remainingFreeS pace, double& totalFlexGrow, double& totalFlexShrink, double& totalWeightedFlexS hrink, InflexibleFlexItemSize& inflexibleItems, Vector<LayoutUnit, 16>& childSiz es)
998 { 1005 {
999 childSizes.resize(0); 1006 childSizes.resize(0);
1000 LayoutUnit totalViolation = 0; 1007 LayoutUnit totalViolation = 0;
1001 LayoutUnit usedFreeSpace = 0; 1008 LayoutUnit usedFreeSpace = 0;
1002 Vector<Violation> minViolations; 1009 Vector<Violation> minViolations;
1003 Vector<Violation> maxViolations; 1010 Vector<Violation> maxViolations;
1011
1012 double sumFlexFactors = (flexSign == PositiveFlexibility) ? totalFlexGrow : totalFlexShrink;
1013 if (sumFlexFactors > 0 && sumFlexFactors < 1) {
1014 LayoutUnit fractional = availableFreeSpace * sumFlexFactors;
1015 if (fractional.abs() < remainingFreeSpace.abs())
1016 remainingFreeSpace = fractional;
1017 }
1018
1004 for (size_t i = 0; i < children.size(); ++i) { 1019 for (size_t i = 0; i < children.size(); ++i) {
1005 LayoutBox* child = children[i]; 1020 LayoutBox* child = children[i];
1006 if (child->isOutOfFlowPositioned()) { 1021 if (child->isOutOfFlowPositioned()) {
1007 childSizes.append(0); 1022 childSizes.append(0);
1008 continue; 1023 continue;
1009 } 1024 }
1010 1025
1011 if (inflexibleItems.contains(child)) { 1026 if (inflexibleItems.contains(child)) {
1012 childSizes.append(inflexibleItems.get(child)); 1027 childSizes.append(inflexibleItems.get(child));
1013 } else { 1028 } else {
1014 LayoutUnit childInnerFlexBaseSize = computeInnerFlexBaseSizeForChild (*child); 1029 LayoutUnit childInnerFlexBaseSize = computeInnerFlexBaseSizeForChild (*child);
1015 LayoutUnit childSize = childInnerFlexBaseSize; 1030 LayoutUnit childSize = childInnerFlexBaseSize;
1016 double extraSpace = 0; 1031 double extraSpace = 0;
1017 if (availableFreeSpace > 0 && totalFlexGrow > 0 && flexSign == Posit iveFlexibility && std::isfinite(totalFlexGrow)) { 1032 if (remainingFreeSpace > 0 && totalFlexGrow > 0 && flexSign == Posit iveFlexibility && std::isfinite(totalFlexGrow)) {
1018 if (totalFlexGrow < 1) 1033 extraSpace = remainingFreeSpace * child->style()->flexGrow() / t otalFlexGrow;
1019 extraSpace = availableFreeSpace * child->style()->flexGrow() ; 1034 } else if (remainingFreeSpace < 0 && totalWeightedFlexShrink > 0 && flexSign == NegativeFlexibility && std::isfinite(totalWeightedFlexShrink) && chi ld->style()->flexShrink()) {
1020 else 1035 extraSpace = remainingFreeSpace * child->style()->flexShrink() * childInnerFlexBaseSize / totalWeightedFlexShrink;
1021 extraSpace = availableFreeSpace * child->style()->flexGrow() / totalFlexGrow;
1022 } else if (availableFreeSpace < 0 && totalWeightedFlexShrink > 0 && flexSign == NegativeFlexibility && std::isfinite(totalWeightedFlexShrink) && chi ld->style()->flexShrink()) {
1023 extraSpace = availableFreeSpace * child->style()->flexShrink() * childInnerFlexBaseSize / totalWeightedFlexShrink;
1024 } 1036 }
1025 if (std::isfinite(extraSpace)) 1037 if (std::isfinite(extraSpace))
1026 childSize += LayoutUnit::fromFloatRound(extraSpace); 1038 childSize += LayoutUnit::fromFloatRound(extraSpace);
1027 1039
1028 LayoutUnit adjustedChildSize = adjustChildSizeForMinAndMax(*child, c hildSize); 1040 LayoutUnit adjustedChildSize = adjustChildSizeForMinAndMax(*child, c hildSize);
1029 ASSERT(adjustedChildSize >= 0); 1041 ASSERT(adjustedChildSize >= 0);
1030 childSizes.append(adjustedChildSize); 1042 childSizes.append(adjustedChildSize);
1031 usedFreeSpace += adjustedChildSize - childInnerFlexBaseSize; 1043 usedFreeSpace += adjustedChildSize - childInnerFlexBaseSize;
1032 1044
1033 LayoutUnit violation = adjustedChildSize - childSize; 1045 LayoutUnit violation = adjustedChildSize - childSize;
1034 if (violation > 0) 1046 if (violation > 0)
1035 minViolations.append(Violation(child, adjustedChildSize, childIn nerFlexBaseSize)); 1047 minViolations.append(Violation(child, adjustedChildSize, childIn nerFlexBaseSize));
1036 else if (violation < 0) 1048 else if (violation < 0)
1037 maxViolations.append(Violation(child, adjustedChildSize, childIn nerFlexBaseSize)); 1049 maxViolations.append(Violation(child, adjustedChildSize, childIn nerFlexBaseSize));
1038 totalViolation += violation; 1050 totalViolation += violation;
1039 } 1051 }
1040 } 1052 }
1041 1053
1042 if (totalViolation) 1054 if (totalViolation)
1043 freezeViolations(totalViolation < 0 ? maxViolations : minViolations, ava ilableFreeSpace, totalFlexGrow, totalWeightedFlexShrink, inflexibleItems); 1055 freezeViolations(totalViolation < 0 ? maxViolations : minViolations, rem ainingFreeSpace, totalFlexGrow, totalFlexShrink, totalWeightedFlexShrink, inflex ibleItems);
1044 else 1056 else
1045 availableFreeSpace -= usedFreeSpace; 1057 remainingFreeSpace -= usedFreeSpace;
1046 1058
1047 return !totalViolation; 1059 return !totalViolation;
1048 } 1060 }
1049 1061
1050 static LayoutUnit initialJustifyContentOffset(LayoutUnit availableFreeSpace, Con tentPosition justifyContent, ContentDistributionType justifyContentDistribution, unsigned numberOfChildren) 1062 static LayoutUnit initialJustifyContentOffset(LayoutUnit availableFreeSpace, Con tentPosition justifyContent, ContentDistributionType justifyContentDistribution, unsigned numberOfChildren)
1051 { 1063 {
1052 if (justifyContent == ContentPositionFlexEnd) 1064 if (justifyContent == ContentPositionFlexEnd)
1053 return availableFreeSpace; 1065 return availableFreeSpace;
1054 if (justifyContent == ContentPositionCenter) 1066 if (justifyContent == ContentPositionCenter)
1055 return availableFreeSpace / 2; 1067 return availableFreeSpace / 2;
(...skipping 471 matching lines...) Expand 10 before | Expand all | Expand 10 after
1527 ASSERT(child); 1539 ASSERT(child);
1528 LayoutUnit lineCrossAxisExtent = lineContexts[lineNumber].crossAxisE xtent; 1540 LayoutUnit lineCrossAxisExtent = lineContexts[lineNumber].crossAxisE xtent;
1529 LayoutUnit originalOffset = lineContexts[lineNumber].crossAxisOffset - crossAxisStartEdge; 1541 LayoutUnit originalOffset = lineContexts[lineNumber].crossAxisOffset - crossAxisStartEdge;
1530 LayoutUnit newOffset = contentExtent - originalOffset - lineCrossAxi sExtent; 1542 LayoutUnit newOffset = contentExtent - originalOffset - lineCrossAxi sExtent;
1531 adjustAlignmentForChild(*child, newOffset - originalOffset); 1543 adjustAlignmentForChild(*child, newOffset - originalOffset);
1532 } 1544 }
1533 } 1545 }
1534 } 1546 }
1535 1547
1536 } 1548 }
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