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

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

Issue 1875263005: [css-flexbox] More correctly implement percentage sizing (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 8 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 251 matching lines...) Expand 10 before | Expand all | Expand 10 after
262 } 262 }
263 } 263 }
264 264
265 void LayoutFlexibleBox::layoutBlock(bool relayoutChildren) 265 void LayoutFlexibleBox::layoutBlock(bool relayoutChildren)
266 { 266 {
267 ASSERT(needsLayout()); 267 ASSERT(needsLayout());
268 268
269 if (!relayoutChildren && simplifiedLayout()) 269 if (!relayoutChildren && simplifiedLayout())
270 return; 270 return;
271 271
272 m_relaidOutChildren.clear();
273
272 if (updateLogicalWidthAndColumnWidth()) 274 if (updateLogicalWidthAndColumnWidth())
273 relayoutChildren = true; 275 relayoutChildren = true;
274 276
275 SubtreeLayoutScope layoutScope(*this); 277 SubtreeLayoutScope layoutScope(*this);
276 LayoutUnit previousHeight = logicalHeight(); 278 LayoutUnit previousHeight = logicalHeight();
277 setLogicalHeight(borderAndPaddingLogicalHeight() + scrollbarLogicalHeight()) ; 279 setLogicalHeight(borderAndPaddingLogicalHeight() + scrollbarLogicalHeight()) ;
278 280
279 { 281 {
280 TextAutosizer::LayoutScope textAutosizerLayoutScope(this); 282 TextAutosizer::LayoutScope textAutosizerLayoutScope(this);
281 LayoutState state(*this, locationOffset()); 283 LayoutState state(*this, locationOffset());
(...skipping 447 matching lines...) Expand 10 before | Expand all | Expand 10 after
729 LayoutUnit mainSize; 731 LayoutUnit mainSize;
730 if (hasOrthogonalFlow(child)) { 732 if (hasOrthogonalFlow(child)) {
731 mainSize = child.logicalHeight(); 733 mainSize = child.logicalHeight();
732 } else { 734 } else {
733 // The max preferred logical width includes the intrinsic scrollbar logi cal width, which is only set for 735 // The max preferred logical width includes the intrinsic scrollbar logi cal width, which is only set for
734 // overflow: scroll. To handle overflow: auto, we have to take scrollbar LogicalWidth() into account, and then 736 // overflow: scroll. To handle overflow: auto, we have to take scrollbar LogicalWidth() into account, and then
735 // subtract the intrinsic width again so as to not double-count overflow : scroll scrollbars. 737 // subtract the intrinsic width again so as to not double-count overflow : scroll scrollbars.
736 mainSize = child.maxPreferredLogicalWidth() + child.scrollbarLogicalWidt h() - child.intrinsicScrollbarLogicalWidth(); 738 mainSize = child.maxPreferredLogicalWidth() + child.scrollbarLogicalWidt h() - child.intrinsicScrollbarLogicalWidth();
737 } 739 }
738 m_intrinsicSizeAlongMainAxis.set(&child, mainSize); 740 m_intrinsicSizeAlongMainAxis.set(&child, mainSize);
741 m_relaidOutChildren.add(&child);
739 } 742 }
740 743
741 void LayoutFlexibleBox::clearCachedMainSizeForChild(const LayoutBox& child) 744 void LayoutFlexibleBox::clearCachedMainSizeForChild(const LayoutBox& child)
742 { 745 {
743 m_intrinsicSizeAlongMainAxis.remove(&child); 746 m_intrinsicSizeAlongMainAxis.remove(&child);
744 } 747 }
745 748
746 LayoutUnit LayoutFlexibleBox::computeInnerFlexBaseSizeForChild(LayoutBox& child, ChildLayoutType childLayoutType) 749 LayoutUnit LayoutFlexibleBox::computeInnerFlexBaseSizeForChild(LayoutBox& child, ChildLayoutType childLayoutType)
747 { 750 {
748 child.clearOverrideSize(); 751 child.clearOverrideSize();
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
780 Vector<LineContext> lineContexts; 783 Vector<LineContext> lineContexts;
781 OrderedFlexItemList orderedChildren; 784 OrderedFlexItemList orderedChildren;
782 LayoutUnit sumFlexBaseSize; 785 LayoutUnit sumFlexBaseSize;
783 double totalFlexGrow; 786 double totalFlexGrow;
784 double totalFlexShrink; 787 double totalFlexShrink;
785 double totalWeightedFlexShrink; 788 double totalWeightedFlexShrink;
786 LayoutUnit sumHypotheticalMainSize; 789 LayoutUnit sumHypotheticalMainSize;
787 790
788 Vector<LayoutUnit, 16> childSizes; 791 Vector<LayoutUnit, 16> childSizes;
789 792
793 dirtyForLayoutFromPercentageHeightDescendants(layoutScope);
leviw_travelin_and_unemployed 2016/04/13 20:10:22 Why this change? Is it necessary?
794
790 m_orderIterator.first(); 795 m_orderIterator.first();
791 LayoutUnit crossAxisOffset = flowAwareBorderBefore() + flowAwarePaddingBefor e(); 796 LayoutUnit crossAxisOffset = flowAwareBorderBefore() + flowAwarePaddingBefor e();
792 while (computeNextFlexLine(orderedChildren, sumFlexBaseSize, totalFlexGrow, totalFlexShrink, totalWeightedFlexShrink, sumHypotheticalMainSize, relayoutChild ren)) { 797 while (computeNextFlexLine(orderedChildren, sumFlexBaseSize, totalFlexGrow, totalFlexShrink, totalWeightedFlexShrink, sumHypotheticalMainSize, relayoutChild ren)) {
793 LayoutUnit containerMainInnerSize = mainAxisContentExtent(sumHypothetica lMainSize); 798 LayoutUnit containerMainInnerSize = mainAxisContentExtent(sumHypothetica lMainSize);
794 // availableFreeSpace is the initial amount of free space in this flexbo x. 799 // availableFreeSpace is the initial amount of free space in this flexbo x.
795 // remainingFreeSpace starts out at the same value but as we place and l ay out 800 // remainingFreeSpace starts out at the same value but as we place and l ay out
796 // flex items we subtract from it. Note that both values can be negative . 801 // flex items we subtract from it. Note that both values can be negative .
797 LayoutUnit availableFreeSpace = containerMainInnerSize - sumFlexBaseSize ; 802 LayoutUnit availableFreeSpace = containerMainInnerSize - sumFlexBaseSize ;
798 LayoutUnit remainingFreeSpace = availableFreeSpace; 803 LayoutUnit remainingFreeSpace = availableFreeSpace;
799 FlexSign flexSign = (sumHypotheticalMainSize < containerMainInnerSize) ? PositiveFlexibility : NegativeFlexibility; 804 FlexSign flexSign = (sumHypotheticalMainSize < containerMainInnerSize) ? PositiveFlexibility : NegativeFlexibility;
(...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after
1060 return LayoutUnit(-1); 1065 return LayoutUnit(-1);
1061 return toLayoutFlexibleBox(parent())->childLogicalHeightForPercentageRes olution(*this); 1066 return toLayoutFlexibleBox(parent())->childLogicalHeightForPercentageRes olution(*this);
1062 } 1067 }
1063 LogicalExtentComputedValues computedValues; 1068 LogicalExtentComputedValues computedValues;
1064 computeLogicalHeight(LayoutUnit(-1), LayoutUnit(), computedValues); 1069 computeLogicalHeight(LayoutUnit(-1), LayoutUnit(), computedValues);
1065 return computedValues.m_extent; 1070 return computedValues.m_extent;
1066 } 1071 }
1067 1072
1068 LayoutUnit LayoutFlexibleBox::crossSizeForPercentageResolution(const LayoutBox& child) 1073 LayoutUnit LayoutFlexibleBox::crossSizeForPercentageResolution(const LayoutBox& child)
1069 { 1074 {
1070 // This function implements section 9.8. Definite and Indefinite Sizes, case 1075 if (alignmentForChild(child) != ItemPositionStretch)
1071 // 1) of the flexbox spec.
1072 // We need to check for multiline and a definite cross size of the flexbox
1073 // per https://drafts.csswg.org/css-flexbox/#definite-sizes, and for
1074 // stretch, auto margins, and an indefinite cross size of the flex item per
1075 // https://drafts.csswg.org/css-flexbox/#stretched (linked from that
1076 // section)
1077 if (isMultiline() || alignmentForChild(child) != ItemPositionStretch || hasA utoMarginsInCrossAxis(child))
1078 return LayoutUnit(-1); 1076 return LayoutUnit(-1);
1079 1077
1080 const Length& childCrossLength = isHorizontalFlow() ? child.styleRef().heigh t() : child.styleRef().width(); 1078 // Here we implement https://drafts.csswg.org/css-flexbox/#algo-stretch
1081 if (crossAxisLengthIsDefinite(child, childCrossLength)) 1079 if (hasOrthogonalFlow(child) && child.hasOverrideLogicalContentWidth())
1082 return LayoutUnit(-1); 1080 return child.overrideLogicalContentWidth();
1081 if (!hasOrthogonalFlow(child) && child.hasOverrideLogicalContentHeight())
1082 return child.overrideLogicalContentHeight();
1083 1083
1084 LayoutUnit childCrossSize; 1084 // We don't currently implement the optimization from https://drafts.csswg.o rg/css-flexbox/#definite-sizes
1085 1085 // case 1. While that could speed up a specialized case, it requires determi ning if we have a definite
1086 if (isColumnFlow()) { 1086 // size, which itself is not cheap. We can consider implementing it at a lat er time.
1087 LayoutUnit definiteWidth = computeDefiniteLogicalWidth(); 1087 // (The correctness is ensured by redoing layout in applyStretchAlignmentToC hild)
1088 if (definiteWidth == LayoutUnit(-1)) 1088 return LayoutUnit(-1);
1089 return definiteWidth;
1090 childCrossSize = definiteWidth - borderAndPaddingLogicalWidth() - scroll barLogicalWidth();
1091 childCrossSize = child.constrainLogicalWidthByMinMax(childCrossSize, chi ldCrossSize, this) - child.scrollbarLogicalWidth() - child.borderAndPaddingLogic alWidth();
1092 } else {
1093 LayoutUnit definiteHeight = computeDefiniteLogicalHeight();
1094 if (definiteHeight == LayoutUnit(-1))
1095 return definiteHeight;
1096
1097 childCrossSize = definiteHeight - borderAndPaddingLogicalHeight() - scro llbarLogicalHeight();
1098 childCrossSize = child.constrainLogicalHeightByMinMax(childCrossSize, La youtUnit(-1)) - child.scrollbarLogicalHeight() - child.borderAndPaddingLogicalHe ight();
1099 }
1100 return childCrossSize;
1101 } 1089 }
1102 1090
1103 LayoutUnit LayoutFlexibleBox::mainSizeForPercentageResolution(const LayoutBox& c hild) 1091 LayoutUnit LayoutFlexibleBox::mainSizeForPercentageResolution(const LayoutBox& c hild)
1104 { 1092 {
1105 // This function implements section 9.8. Definite and Indefinite Sizes, case 1093 // This function implements section 9.8. Definite and Indefinite Sizes, case
1106 // 2) of the flexbox spec. 1094 // 2) of the flexbox spec.
1107 // We need to check for the flexbox to have a definite main size, and for th e 1095 // We need to check for the flexbox to have a definite main size, and for th e
1108 // flex item to have a definite flex basis. 1096 // flex item to have a definite flex basis.
1109 const Length& flexBasis = flexBasisForChild(child); 1097 const Length& flexBasis = flexBasisForChild(child);
1110 if (!mainAxisLengthIsDefinite(child, flexBasis)) 1098 if (!mainAxisLengthIsDefinite(child, flexBasis))
(...skipping 340 matching lines...) Expand 10 before | Expand all | Expand 10 after
1451 prepareChildForPositionedLayout(*child, mainAxisOffset, crossAxisOff set, FlipForRowReverse); 1439 prepareChildForPositionedLayout(*child, mainAxisOffset, crossAxisOff set, FlipForRowReverse);
1452 continue; 1440 continue;
1453 } 1441 }
1454 1442
1455 // FIXME Investigate if this can be removed based on other flags. crbug. com/370010 1443 // FIXME Investigate if this can be removed based on other flags. crbug. com/370010
1456 child->setMayNeedPaintInvalidation(); 1444 child->setMayNeedPaintInvalidation();
1457 1445
1458 LayoutUnit childPreferredSize = childSizes[i] + mainAxisBorderAndPadding ExtentForChild(*child); 1446 LayoutUnit childPreferredSize = childSizes[i] + mainAxisBorderAndPadding ExtentForChild(*child);
1459 setOverrideMainAxisSizeForChild(*child, childPreferredSize); 1447 setOverrideMainAxisSizeForChild(*child, childPreferredSize);
1460 if (childPreferredSize != mainAxisExtentForChild(*child)) { 1448 if (childPreferredSize != mainAxisExtentForChild(*child)) {
1461 // We will correctly handle percentage sizing even without re-laying out here, because
1462 // if our size was already correct, then percentage resolution was a lso correct due
1463 // to the way percentage sizing is defined by flexbox (ie. it requir es a definite flex basis)
1464 // TODO(cbiesinger): When flex-basis is used instead of width/height , this is not the case. That
1465 // problem is not limited to percentages. See http://crbug.com/53165 6#c11
1466 child->setChildNeedsLayout(MarkOnlyThis); 1449 child->setChildNeedsLayout(MarkOnlyThis);
1467 } else { 1450 } else {
1468 // To avoid double applying margin changes in updateAutoMarginsInCro ssAxis, we reset the margins here. 1451 // To avoid double applying margin changes in updateAutoMarginsInCro ssAxis, we reset the margins here.
1469 resetAutoMarginsAndLogicalTopInCrossAxis(*child); 1452 resetAutoMarginsAndLogicalTopInCrossAxis(*child);
1470 } 1453 }
1471 // We may have already forced relayout for orthogonal flowing children i n computeInnerFlexBaseSizeForChild. 1454 // We may have already forced relayout for orthogonal flowing children i n computeInnerFlexBaseSizeForChild.
1472 bool forceChildRelayout = relayoutChildren && !childFlexBaseSizeRequires Layout(*child); 1455 bool forceChildRelayout = relayoutChildren && !childFlexBaseSizeRequires Layout(*child);
1456 if (child->isLayoutBlock() && toLayoutBlock(*child).hasPercentHeightDesc endants() && m_relaidOutChildren.contains(child)) {
1457 // Have to force another relayout even though the child is sized cor rectly, because
1458 // its descendants are not sized correctly yet. Our previous layout of the child was
1459 // done without an override height set. So, redo it here.
1460 forceChildRelayout = true;
1461 }
1473 updateBlockChildDirtyBitsBeforeLayout(forceChildRelayout, *child); 1462 updateBlockChildDirtyBitsBeforeLayout(forceChildRelayout, *child);
1474 if (!child->needsLayout()) 1463 if (!child->needsLayout())
1475 child->markForPaginationRelayoutIfNeeded(layoutScope); 1464 child->markForPaginationRelayoutIfNeeded(layoutScope);
1465 if (child->needsLayout())
1466 m_relaidOutChildren.add(child);
1476 child->layoutIfNeeded(); 1467 child->layoutIfNeeded();
1477 1468
1478 updateAutoMarginsInMainAxis(*child, autoMarginOffset); 1469 updateAutoMarginsInMainAxis(*child, autoMarginOffset);
1479 1470
1480 LayoutUnit childCrossAxisMarginBoxExtent; 1471 LayoutUnit childCrossAxisMarginBoxExtent;
1481 if (alignmentForChild(*child) == ItemPositionBaseline && !hasAutoMargins InCrossAxis(*child)) { 1472 if (alignmentForChild(*child) == ItemPositionBaseline && !hasAutoMargins InCrossAxis(*child)) {
1482 LayoutUnit ascent = marginBoxAscentForChild(*child); 1473 LayoutUnit ascent = marginBoxAscentForChild(*child);
1483 LayoutUnit descent = (crossAxisMarginExtentForChild(*child) + crossA xisExtentForChild(*child)) - ascent; 1474 LayoutUnit descent = (crossAxisMarginExtentForChild(*child) + crossA xisExtentForChild(*child)) - ascent;
1484 1475
1485 maxAscent = std::max(maxAscent, ascent); 1476 maxAscent = std::max(maxAscent, ascent);
(...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after
1723 void LayoutFlexibleBox::applyStretchAlignmentToChild(LayoutBox& child, LayoutUni t lineCrossAxisExtent) 1714 void LayoutFlexibleBox::applyStretchAlignmentToChild(LayoutBox& child, LayoutUni t lineCrossAxisExtent)
1724 { 1715 {
1725 if (!hasOrthogonalFlow(child) && child.style()->logicalHeight().isAuto()) { 1716 if (!hasOrthogonalFlow(child) && child.style()->logicalHeight().isAuto()) {
1726 LayoutUnit heightBeforeStretching = needToStretchChildLogicalHeight(chil d) ? constrainedChildIntrinsicContentLogicalHeight(child) : child.logicalHeight( ); 1717 LayoutUnit heightBeforeStretching = needToStretchChildLogicalHeight(chil d) ? constrainedChildIntrinsicContentLogicalHeight(child) : child.logicalHeight( );
1727 LayoutUnit stretchedLogicalHeight = std::max(child.borderAndPaddingLogic alHeight(), heightBeforeStretching + availableAlignmentSpaceForChildBeforeStretc hing(lineCrossAxisExtent, child)); 1718 LayoutUnit stretchedLogicalHeight = std::max(child.borderAndPaddingLogic alHeight(), heightBeforeStretching + availableAlignmentSpaceForChildBeforeStretc hing(lineCrossAxisExtent, child));
1728 ASSERT(!child.needsLayout()); 1719 ASSERT(!child.needsLayout());
1729 LayoutUnit desiredLogicalHeight = child.constrainLogicalHeightByMinMax(s tretchedLogicalHeight, heightBeforeStretching - child.borderAndPaddingLogicalHei ght()); 1720 LayoutUnit desiredLogicalHeight = child.constrainLogicalHeightByMinMax(s tretchedLogicalHeight, heightBeforeStretching - child.borderAndPaddingLogicalHei ght());
1730 1721
1731 // FIXME: Can avoid laying out here in some cases. See https://webkit.or g/b/87905. 1722 // FIXME: Can avoid laying out here in some cases. See https://webkit.or g/b/87905.
1732 bool childNeedsRelayout = desiredLogicalHeight != child.logicalHeight(); 1723 bool childNeedsRelayout = desiredLogicalHeight != child.logicalHeight();
1724 if (child.isLayoutBlock() && toLayoutBlock(child).hasPercentHeightDescen dants() && m_relaidOutChildren.contains(&child)) {
1725 // Have to force another relayout even though the child is sized cor rectly, because
1726 // its descendants are not sized correctly yet. Our previous layout of the child was
1727 // done without an override height set. So, redo it here.
1728 childNeedsRelayout = true;
1729 }
1733 if (childNeedsRelayout || !child.hasOverrideLogicalContentHeight()) 1730 if (childNeedsRelayout || !child.hasOverrideLogicalContentHeight())
1734 child.setOverrideLogicalContentHeight(desiredLogicalHeight - child.b orderAndPaddingLogicalHeight()); 1731 child.setOverrideLogicalContentHeight(desiredLogicalHeight - child.b orderAndPaddingLogicalHeight());
1735 if (childNeedsRelayout) { 1732 if (childNeedsRelayout) {
1736 child.setLogicalHeight(LayoutUnit()); 1733 child.setLogicalHeight(LayoutUnit());
1737 // We cache the child's intrinsic content logical height to avoid it being reset to the stretched height. 1734 // We cache the child's intrinsic content logical height to avoid it being reset to the stretched height.
1738 // FIXME: This is fragile. LayoutBoxes should be smart enough to det ermine their intrinsic content logical 1735 // FIXME: This is fragile. LayoutBoxes should be smart enough to det ermine their intrinsic content logical
1739 // height correctly even when there's an overrideHeight. 1736 // height correctly even when there's an overrideHeight.
1740 LayoutUnit childIntrinsicContentLogicalHeight = child.intrinsicConte ntLogicalHeight(); 1737 LayoutUnit childIntrinsicContentLogicalHeight = child.intrinsicConte ntLogicalHeight();
1741 child.forceChildLayout(); 1738 child.forceChildLayout();
1742 child.setIntrinsicContentLogicalHeight(childIntrinsicContentLogicalH eight); 1739 child.setIntrinsicContentLogicalHeight(childIntrinsicContentLogicalH eight);
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
1778 ASSERT(child); 1775 ASSERT(child);
1779 LayoutUnit lineCrossAxisExtent = lineContexts[lineNumber].crossAxisE xtent; 1776 LayoutUnit lineCrossAxisExtent = lineContexts[lineNumber].crossAxisE xtent;
1780 LayoutUnit originalOffset = lineContexts[lineNumber].crossAxisOffset - crossAxisStartEdge; 1777 LayoutUnit originalOffset = lineContexts[lineNumber].crossAxisOffset - crossAxisStartEdge;
1781 LayoutUnit newOffset = contentExtent - originalOffset - lineCrossAxi sExtent; 1778 LayoutUnit newOffset = contentExtent - originalOffset - lineCrossAxi sExtent;
1782 adjustAlignmentForChild(*child, newOffset - originalOffset); 1779 adjustAlignmentForChild(*child, newOffset - originalOffset);
1783 } 1780 }
1784 } 1781 }
1785 } 1782 }
1786 1783
1787 } // namespace blink 1784 } // 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