OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 } |
OLD | NEW |