--- a/layout/generic/nsFlexContainerFrame.cpp
+++ b/layout/generic/nsFlexContainerFrame.cpp
@@ -882,27 +882,33 @@ protected:
/**
* Represents a single flex line in a flex container.
* Manages a linked list of the FlexItems that are in the line.
*/
class nsFlexContainerFrame::FlexLine : public LinkedListElement<FlexLine>
{
public:
- FlexLine()
+ explicit FlexLine(nscoord aMainGapSize)
: mNumItems(0),
mNumFrozenItems(0),
mTotalItemMBP(0),
mTotalOuterHypotheticalMainSize(0),
mLineCrossSize(0),
mFirstBaselineOffset(nscoord_MIN),
- mLastBaselineOffset(nscoord_MIN)
+ mLastBaselineOffset(nscoord_MIN),
+ mMainGapSize(aMainGapSize)
{}
- // Returns the sum of our FlexItems' outer hypothetical main sizes.
+ nscoord GetSumOfGaps() const {
+ return mNumItems > 0 ? (mNumItems - 1) * mMainGapSize : 0;
+ }
+
+ // Returns the sum of our FlexItems' outer hypothetical main sizes plus the
+ // sum of main axis {row,column}-gaps between items.
// ("outer" = margin-box, and "hypothetical" = before flexing)
nscoord GetTotalOuterHypotheticalMainSize() const {
return mTotalOuterHypotheticalMainSize;
}
// Accessors for our FlexItems & information about them:
FlexItem* GetFirstItem()
{
@@ -978,17 +984,25 @@ public:
// don't want that to make mTotalOuterHypotheticalMainSize overflow to a
// negative value), because that'd make us incorrectly think that we should
// grow our flex items rather than shrink them when it comes time to
// resolve flexible items. Hence, we sum up the hypothetical sizes using a
// helper function AddChecked() to avoid overflow.
mTotalItemMBP = AddChecked(mTotalItemMBP, itemMBP);
mTotalOuterHypotheticalMainSize =
- AddChecked(mTotalOuterHypotheticalMainSize, aItemOuterHypotheticalMainSize);
+ AddChecked(mTotalOuterHypotheticalMainSize,
+ aItemOuterHypotheticalMainSize);
+
+ // If the item added was not the first item in the line, we add in any gap
+ // space as needed.
+ if (mNumItems >= 2) {
+ mTotalOuterHypotheticalMainSize =
+ AddChecked(mTotalOuterHypotheticalMainSize, mMainGapSize);
+ }
}
// Computes the cross-size and baseline position of this FlexLine, based on
// its FlexItems.
void ComputeCrossSizeAndBaseline(const FlexboxAxisTracker& aAxisTracker);
// Returns the cross-size of this line.
nscoord GetLineCrossSize() const { return mLineCrossSize; }
@@ -1022,16 +1036,32 @@ public:
* distance from the line's cross-start edge.
*
* If there are no last baseline-aligned FlexItems, returns nscoord_MIN.
*/
nscoord GetLastBaselineOffset() const {
return mLastBaselineOffset;
}
+ /**
+ * Returns the number of items held in this line. Used for total gap
+ * calculations.
+ */
+ uint32_t GetNumItems() const {
+ return mNumItems;
+ }
+
+ /**
+ * Returns the gap size in the main axis for this line. Used for gap
+ * calculations.
+ */
+ nscoord GetMainGapSize() const {
+ return mMainGapSize;
+ }
+
// Runs the "Resolving Flexible Lengths" algorithm from section 9.7 of the
// CSS flexbox spec to distribute aFlexContainerMainSize among our flex items.
void ResolveFlexibleLengths(nscoord aFlexContainerMainSize,
ComputedFlexLineInfo* aLineInfo);
void PositionItemsInMainAxis(uint8_t aJustifyContent,
nscoord aContentBoxMainSize,
const FlexboxAxisTracker& aAxisTracker);
@@ -1059,24 +1089,28 @@ private:
// Number of *frozen* FlexItems in this line, based on FlexItem::IsFrozen().
// Mostly used for optimization purposes, e.g. to bail out early from loops
// when we can tell they have nothing left to do.
uint32_t mNumFrozenItems;
// Sum of margin/border/padding for the FlexItems in this FlexLine.
nscoord mTotalItemMBP;
- // Sum of FlexItems' outer hypothetical main sizes.
+ // Sum of FlexItems' outer hypothetical main sizes and all main-axis
+ // {row,columnm}-gaps between items.
// (i.e. their flex base sizes, clamped via their min/max-size properties,
- // plus their main-axis margin/border/padding.)
+ // plus their main-axis margin/border/padding, plus the sum of the gaps.)
nscoord mTotalOuterHypotheticalMainSize;
nscoord mLineCrossSize;
nscoord mFirstBaselineOffset;
nscoord mLastBaselineOffset;
+
+ // Maintain size of each {row,column}-gap in the main axis
+ const nscoord mMainGapSize;
};
// Information about a strut left behind by a FlexItem that's been collapsed
// using "visibility:collapse".
struct nsFlexContainerFrame::StrutInfo {
StrutInfo(uint32_t aItemIdx, nscoord aStrutCrossSize)
: mItemIdx(aItemIdx),
mStrutCrossSize(aStrutCrossSize)
@@ -2227,16 +2261,19 @@ public:
~MainAxisPositionTracker() {
MOZ_ASSERT(mNumPackingSpacesRemaining == 0,
"miscounted the number of packing spaces");
MOZ_ASSERT(mNumAutoMarginsInMainAxis == 0,
"miscounted the number of auto margins");
}
+ // Advances past the gap space (if any) between two flex items
+ void TraverseGap(nscoord aGapSize) { mPosition += aGapSize; }
+
// Advances past the packing space (if any) between two flex items
void TraversePackingSpace();
// If aItem has any 'auto' margins in the main axis, this method updates the
// corresponding values in its margin.
void ResolveAutoMarginsInMainAxis(FlexItem& aItem);
private:
@@ -2252,17 +2289,21 @@ private:
// The "0" position represents the cross-start edge of the flex container's
// content-box.
class MOZ_STACK_CLASS CrossAxisPositionTracker : public PositionTracker {
public:
CrossAxisPositionTracker(FlexLine* aFirstLine,
const ReflowInput& aReflowInput,
nscoord aContentBoxCrossSize,
bool aIsCrossSizeDefinite,
- const FlexboxAxisTracker& aAxisTracker);
+ const FlexboxAxisTracker& aAxisTracker,
+ const nscoord aCrossGapSize);
+
+ // Advances past the gap (if any) between two flex lines
+ void TraverseGap() { mPosition += mCrossGapSize; }
// Advances past the packing space (if any) between two flex lines
void TraversePackingSpace();
// Advances past the given FlexLine
void TraverseLine(FlexLine& aLine) { mPosition += aLine.GetLineCrossSize(); }
private:
@@ -2274,16 +2315,18 @@ private:
void ExitMargin(const nsMargin& aMargin) = delete;
void EnterChildFrame(nscoord aChildFrameSize) = delete;
void ExitChildFrame(nscoord aChildFrameSize) = delete;
nscoord mPackingSpaceRemaining;
uint32_t mNumPackingSpacesRemaining;
// XXX this should be uint16_t when we add explicit fallback handling
uint8_t mAlignContent;
+
+ nscoord mCrossGapSize = 0;
};
// Utility class for managing our position along the cross axis, *within* a
// single flex line.
class MOZ_STACK_CLASS SingleLineCrossAxisPositionTracker : public PositionTracker {
public:
explicit SingleLineCrossAxisPositionTracker(const FlexboxAxisTracker& aAxisTracker);
@@ -2554,21 +2597,21 @@ FlexLine::ResolveFlexibleLengths(nscoord
if ((mNumFrozenItems == mNumItems) && !aLineInfo) {
// All our items are frozen, so we have no flexible lengths to resolve,
// and we aren't being asked to generate computed line info.
return;
}
MOZ_ASSERT(!IsEmpty() || aLineInfo,
"empty lines should take the early-return above");
- // Subtract space occupied by our items' margins/borders/padding, so we can
- // just be dealing with the space available for our flex items' content
+ // Subtract space occupied by our items' margins/borders/padding/gaps, so
+ // we can just be dealing with the space available for our flex items' content
// boxes.
nscoord spaceAvailableForFlexItemsContentBoxes =
- aFlexContainerMainSize - mTotalItemMBP;
+ aFlexContainerMainSize - (mTotalItemMBP + GetSumOfGaps());
nscoord origAvailableFreeSpace;
bool isOrigAvailFreeSpaceInitialized = false;
// NOTE: I claim that this chunk of the algorithm (the looping part) needs to
// run the loop at MOST mNumItems times. This claim should hold up
// because we'll freeze at least one item on each loop iteration, and once
// we've run out of items to freeze, there's nothing left to do. However,
@@ -2895,16 +2938,19 @@ MainAxisPositionTracker::
// we'll subtract out the main sizes of our flex items, so that it ends up
// with the *actual* amount of packing space.
for (const FlexItem* item = aLine->GetFirstItem(); item;
item = item->getNext()) {
mPackingSpaceRemaining -= item->GetOuterMainSize(mAxis);
mNumAutoMarginsInMainAxis += item->GetNumAutoMarginsInAxis(mAxis);
}
+ // Subtract space required for row/col gap from the remaining packing space
+ mPackingSpaceRemaining -= aLine->GetSumOfGaps();
+
if (mPackingSpaceRemaining <= 0) {
// No available packing space to use for resolving auto margins.
mNumAutoMarginsInMainAxis = 0;
}
// If packing space is negative or we only have one item, 'space-between'
// falls back to 'flex-start', and 'space-around' & 'space-evenly' fall back
// to 'center'. In those cases, it's simplest to just pretend we have a
@@ -3042,22 +3088,24 @@ MainAxisPositionTracker::TraversePacking
}
}
CrossAxisPositionTracker::
CrossAxisPositionTracker(FlexLine* aFirstLine,
const ReflowInput& aReflowInput,
nscoord aContentBoxCrossSize,
bool aIsCrossSizeDefinite,
- const FlexboxAxisTracker& aAxisTracker)
+ const FlexboxAxisTracker& aAxisTracker,
+ const nscoord aCrossGapSize)
: PositionTracker(aAxisTracker.GetCrossAxis(),
aAxisTracker.IsCrossAxisReversed()),
mPackingSpaceRemaining(0),
mNumPackingSpacesRemaining(0),
- mAlignContent(aReflowInput.mStylePosition->mAlignContent)
+ mAlignContent(aReflowInput.mStylePosition->mAlignContent),
+ mCrossGapSize(aCrossGapSize)
{
MOZ_ASSERT(aFirstLine, "null first line pointer");
// 'normal' behaves as 'stretch'
if (mAlignContent == NS_STYLE_ALIGN_NORMAL) {
mAlignContent = NS_STYLE_ALIGN_STRETCH;
}
@@ -3100,16 +3148,21 @@ CrossAxisPositionTracker::
// lines we have. (We need that count in some cases below.)
mPackingSpaceRemaining = aContentBoxCrossSize;
uint32_t numLines = 0;
for (FlexLine* line = aFirstLine; line; line = line->getNext()) {
mPackingSpaceRemaining -= line->GetLineCrossSize();
numLines++;
}
+ // Subtract space required for row/col gap from the remaining packing space
+ MOZ_ASSERT(numLines >= 1,
+ "GenerateFlexLines should've produced at least 1 line");
+ mPackingSpaceRemaining -= aCrossGapSize * (numLines - 1);
+
// If packing space is negative, 'space-between' and 'stretch' behave like
// 'flex-start', and 'space-around' and 'space-evenly' behave like 'center'.
// In those cases, it's simplest to just pretend we have a different
// 'align-content' value and share code. (If we only have one line, all of
// the 'space-*' keywords fall back as well, but 'stretch' doesn't because
// even a single line can still stretch.)
if (mPackingSpaceRemaining < 0 && mAlignContent == NS_STYLE_ALIGN_STRETCH) {
mAlignContent = NS_STYLE_ALIGN_FLEX_START;
@@ -3704,19 +3757,20 @@ FlexboxAxisTracker::InitAxesFromModernPr
mIsCrossAxisReversed = false;
}
}
// Allocates a new FlexLine, adds it to the given LinkedList (at the front or
// back depending on aShouldInsertAtFront), and returns a pointer to it.
static FlexLine*
AddNewFlexLineToList(LinkedList<FlexLine>& aLines,
- bool aShouldInsertAtFront)
+ bool aShouldInsertAtFront,
+ nscoord aMainGapSize)
{
- FlexLine* newLine = new FlexLine();
+ FlexLine* newLine = new FlexLine(aMainGapSize);
if (aShouldInsertAtFront) {
aLines.insertFront(newLine);
} else {
aLines.insertBack(newLine);
}
return newLine;
}
@@ -3756,16 +3810,17 @@ nsFlexContainerFrame::ShouldUseMozBoxCol
void
nsFlexContainerFrame::GenerateFlexLines(
nsPresContext* aPresContext,
const ReflowInput& aReflowInput,
nscoord aContentBoxMainSize,
nscoord aAvailableBSizeForContent,
const nsTArray<StrutInfo>& aStruts,
const FlexboxAxisTracker& aAxisTracker,
+ nscoord aMainGapSize,
nsTArray<nsIFrame*>& aPlaceholders, /* out */
LinkedList<FlexLine>& aLines /* out */)
{
MOZ_ASSERT(aLines.isEmpty(), "Expecting outparam to start out empty");
const bool isSingleLine =
NS_STYLE_FLEX_WRAP_NOWRAP == aReflowInput.mStylePosition->mFlexWrap;
@@ -3774,17 +3829,18 @@ nsFlexContainerFrame::GenerateFlexLines(
// layout (with flipped axes) will still produce the correct result.
// Here, we declare a convenience bool that we'll pass when adding a new
// FlexLine or FlexItem, to make us insert it at the beginning of its list
// (so the list ends up reversed).
const bool shouldInsertAtFront = aAxisTracker.AreAxesInternallyReversed();
// We have at least one FlexLine. Even an empty flex container has a single
// (empty) flex line.
- FlexLine* curLine = AddNewFlexLineToList(aLines, shouldInsertAtFront);
+ FlexLine* curLine = AddNewFlexLineToList(aLines, shouldInsertAtFront,
+ aMainGapSize);
nscoord wrapThreshold;
if (isSingleLine) {
// Not wrapping. Set threshold to sentinel value that tells us not to wrap.
wrapThreshold = NS_UNCONSTRAINEDSIZE;
} else {
// Wrapping! Set wrap threshold to flex container's content-box main-size.
wrapThreshold = aContentBoxMainSize;
@@ -3838,17 +3894,17 @@ nsFlexContainerFrame::GenerateFlexLines(
if (childFrame->IsPlaceholderFrame()) {
aPlaceholders.AppendElement(childFrame);
continue;
}
// Honor "page-break-before", if we're multi-line and this line isn't empty:
if (!isSingleLine && !curLine->IsEmpty() &&
childFrame->StyleDisplay()->mBreakBefore) {
- curLine = AddNewFlexLineToList(aLines, shouldInsertAtFront);
+ curLine = AddNewFlexLineToList(aLines, shouldInsertAtFront, aMainGapSize);
}
UniquePtr<FlexItem> item;
if (useMozBoxCollapseBehavior &&
(NS_STYLE_VISIBILITY_COLLAPSE ==
childFrame->StyleVisibility()->mVisible)) {
// Legacy visibility:collapse behavior: make a 0-sized strut. (No need to
// bother with aStruts and remembering cross size.)
@@ -3878,31 +3934,35 @@ nsFlexContainerFrame::GenerateFlexLines(
// NOTE: We have to account for the fact that
// itemOuterHypotheticalMainSize might be huge, if our item is (or
// contains) a table with "table-layout:fixed". So we use AddChecked()
// rather than (possibly-overflowing) normal addition, to be sure we don't
// make the wrong judgement about whether the item fits on this line.
nscoord newOuterSize =
AddChecked(curLine->GetTotalOuterHypotheticalMainSize(),
itemOuterHypotheticalMainSize);
+ // Account for gap between this line's previous item and this item
+ newOuterSize = AddChecked(newOuterSize, aMainGapSize);
if (newOuterSize == nscoord_MAX || newOuterSize > wrapThreshold) {
- curLine = AddNewFlexLineToList(aLines, shouldInsertAtFront);
+ curLine = AddNewFlexLineToList(aLines, shouldInsertAtFront,
+ aMainGapSize);
}
}
// Add item to current flex line (and update the line's bookkeeping about
// how large its items collectively are).
- curLine->AddItem(item.release(), shouldInsertAtFront,
+ curLine->AddItem(item.release(),
+ shouldInsertAtFront,
itemInnerHypotheticalMainSize,
itemOuterHypotheticalMainSize);
// Honor "page-break-after", if we're multi-line and have more children:
if (!isSingleLine && childFrame->GetNextSibling() &&
childFrame->StyleDisplay()->mBreakAfter) {
- curLine = AddNewFlexLineToList(aLines, shouldInsertAtFront);
+ curLine = AddNewFlexLineToList(aLines, shouldInsertAtFront, aMainGapSize);
}
itemIdxInContainer++;
}
}
// Retrieves the content-box main-size of our flex container from the
// reflow state (specifically, the main-size of *this continuation* of the
// flex container).
@@ -4084,16 +4144,19 @@ FlexLine::PositionItemsInMainAxis(uint8_
mainAxisPosnTracker.EnterMargin(item->GetMargin());
mainAxisPosnTracker.EnterChildFrame(itemMainBorderBoxSize);
item->SetMainPosition(mainAxisPosnTracker.GetPosition());
mainAxisPosnTracker.ExitChildFrame(itemMainBorderBoxSize);
mainAxisPosnTracker.ExitMargin(item->GetMargin());
mainAxisPosnTracker.TraversePackingSpace();
+ if (item->getNext()) {
+ mainAxisPosnTracker.TraverseGap(mMainGapSize);
+ }
}
}
/**
* Given the flex container's "flex-relative ascent" (i.e. distance from the
* flex container's content-box cross-start edge to its baseline), returns
* its actual physical ascent value (the distance from the *border-box* top
* edge to its baseline).
@@ -4265,28 +4328,48 @@ nsFlexContainerFrame::Reflow(nsPresConte
availableBSizeForContent -=
aReflowInput.ComputedLogicalBorderPadding().BStart(wm);
// (Don't let that push availableBSizeForContent below zero, though):
availableBSizeForContent = std::max(availableBSizeForContent, 0);
}
nscoord contentBoxMainSize = GetMainSizeFromReflowInput(aReflowInput,
axisTracker);
+ // Calculate gap size for main and cross axis
+ nscoord mainGapSize;
+ nscoord crossGapSize;
+ if (axisTracker.IsRowOriented()) {
+ mainGapSize = nsLayoutUtils::ResolveGapToLength(stylePos->mColumnGap,
+ contentBoxMainSize);
+ crossGapSize =
+ nsLayoutUtils::ResolveGapToLength(stylePos->mRowGap,
+ GetEffectiveComputedBSize(aReflowInput));
+ } else {
+ mainGapSize = nsLayoutUtils::ResolveGapToLength(stylePos->mRowGap,
+ contentBoxMainSize);
+ NS_WARNING_ASSERTION(aReflowInput.ComputedISize() != NS_UNCONSTRAINEDSIZE,
+ "Unconstrained inline size; this should only result "
+ "from huge sizes (not intrinsic sizing w/ orthogonal "
+ "flows)");
+ crossGapSize =
+ nsLayoutUtils::ResolveGapToLength(stylePos->mColumnGap,
+ aReflowInput.ComputedISize());
+ }
AutoTArray<StrutInfo, 1> struts;
DoFlexLayout(aPresContext, aDesiredSize, aReflowInput, aStatus,
contentBoxMainSize, availableBSizeForContent,
- struts, axisTracker);
+ struts, axisTracker, mainGapSize, crossGapSize);
if (!struts.IsEmpty()) {
// We're restarting flex layout, with new knowledge of collapsed items.
aStatus.Reset();
DoFlexLayout(aPresContext, aDesiredSize, aReflowInput, aStatus,
contentBoxMainSize, availableBSizeForContent,
- struts, axisTracker);
+ struts, axisTracker, mainGapSize, crossGapSize);
}
}
// RAII class to clean up a list of FlexLines.
// Specifically, this removes each line from the list, deletes all the
// FlexItems in its list, and deletes the FlexLine.
class MOZ_RAII AutoFlexLineListClearer
{
@@ -4510,28 +4593,31 @@ nsFlexContainerFrame::IsUsedFlexBasisCon
void
nsFlexContainerFrame::DoFlexLayout(nsPresContext* aPresContext,
ReflowOutput& aDesiredSize,
const ReflowInput& aReflowInput,
nsReflowStatus& aStatus,
nscoord aContentBoxMainSize,
nscoord aAvailableBSizeForContent,
nsTArray<StrutInfo>& aStruts,
- const FlexboxAxisTracker& aAxisTracker)
+ const FlexboxAxisTracker& aAxisTracker,
+ nscoord aMainGapSize,
+ nscoord aCrossGapSize)
{
MOZ_ASSERT(aStatus.IsEmpty(), "Caller should pass a fresh reflow status!");
LinkedList<FlexLine> lines;
nsTArray<nsIFrame*> placeholderKids;
AutoFlexLineListClearer cleanupLines(lines);
GenerateFlexLines(aPresContext, aReflowInput,
aContentBoxMainSize,
aAvailableBSizeForContent,
aStruts, aAxisTracker,
+ aMainGapSize,
placeholderKids, lines);
if (lines.getFirst()->IsEmpty() &&
!lines.getFirst()->getNext()) {
// We have no flex items, our parent should synthesize a baseline if needed.
AddStateBits(NS_STATE_FLEX_SYNTHESIZE_BASELINE);
} else {
RemoveStateBits(NS_STATE_FLEX_SYNTHESIZE_BASELINE);
@@ -4674,17 +4760,18 @@ nsFlexContainerFrame::DoFlexLayout(nsPre
ComputeCrossSize(aReflowInput, aAxisTracker, sumLineCrossSizes,
aAvailableBSizeForContent, &isCrossSizeDefinite, aStatus);
// Set up state for cross-axis alignment, at a high level (outside the
// scope of a particular flex line)
CrossAxisPositionTracker
crossAxisPosnTracker(lines.getFirst(),
aReflowInput, contentBoxCrossSize,
- isCrossSizeDefinite, aAxisTracker);
+ isCrossSizeDefinite, aAxisTracker,
+ aCrossGapSize);
// Now that we know the cross size of each line (including
// "align-content:stretch" adjustments, from the CrossAxisPositionTracker
// constructor), we can create struts for any flex items with
// "visibility: collapse" (and restart flex layout).
if (aStruts.IsEmpty() && // (Don't make struts if we already did)
!ShouldUseMozBoxCollapseBehavior(aReflowInput.mStyleDisplay)) {
BuildStrutInfoFromCollapsedItems(lines.getFirst(), aStruts);
@@ -4712,16 +4799,17 @@ nsFlexContainerFrame::DoFlexLayout(nsPre
contentBoxCrossSize, aReflowInput, aAxisTracker);
}
}
const auto justifyContent = IsLegacyBox(aReflowInput.mFrame) ?
ConvertLegacyStyleToJustifyContent(StyleXUL()) :
aReflowInput.mStylePosition->mJustifyContent;
+
lineIndex = 0;
for (FlexLine* line = lines.getFirst(); line; line = line->getNext(),
++lineIndex) {
// Main-Axis Alignment - Flexbox spec section 9.5
// ==============================================
line->PositionItemsInMainAxis(justifyContent,
aContentBoxMainSize,
aAxisTracker);
@@ -4733,16 +4821,20 @@ nsFlexContainerFrame::DoFlexLayout(nsPre
}
// Cross-Axis Alignment - Flexbox spec section 9.6
// ===============================================
line->PositionItemsInCrossAxis(crossAxisPosnTracker.GetPosition(),
aAxisTracker);
crossAxisPosnTracker.TraverseLine(*line);
crossAxisPosnTracker.TraversePackingSpace();
+
+ if (line->getNext()) {
+ crossAxisPosnTracker.TraverseGap();
+ }
}
// If the container should derive its baseline from the last FlexLine,
// do that here (while crossAxisPosnTracker is conveniently pointing
// at the cross-end edge of that line, which the line's baseline offset is
// measured from):
if (aAxisTracker.AreAxesInternallyReversed()) {
nscoord lastLineBaselineOffset = lines.getLast()->GetFirstBaselineOffset();
@@ -5140,38 +5232,56 @@ nsFlexContainerFrame::IntrinsicISize(gfx
IntrinsicISizeType aType)
{
nscoord containerISize = 0;
RenumberList();
const nsStylePosition* stylePos = StylePosition();
const FlexboxAxisTracker axisTracker(this, GetWritingMode());
+ nscoord mainGapSize;
+ if (axisTracker.IsRowOriented()) {
+ mainGapSize = nsLayoutUtils::ResolveGapToLength(stylePos->mColumnGap,
+ NS_UNCONSTRAINEDSIZE);
+ } else {
+ mainGapSize = nsLayoutUtils::ResolveGapToLength(stylePos->mRowGap,
+ NS_UNCONSTRAINEDSIZE);
+ }
+
const bool useMozBoxCollapseBehavior =
ShouldUseMozBoxCollapseBehavior(StyleDisplay());
+ // The loop below sets aside space for a gap before each item besides the
+ // first. This bool helps us handle that special-case.
+ bool onFirstChild = true;
+
for (nsIFrame* childFrame : mFrames) {
// If we're using legacy "visibility:collapse" behavior, then we don't
// care about the sizes of any collapsed children.
if (!useMozBoxCollapseBehavior ||
(NS_STYLE_VISIBILITY_COLLAPSE !=
childFrame->StyleVisibility()->mVisible)) {
nscoord childISize =
nsLayoutUtils::IntrinsicForContainer(aRenderingContext, childFrame,
aType);
// * For a row-oriented single-line flex container, the intrinsic
- // {min/pref}-isize is the sum of its items' {min/pref}-isizes.
+ // {min/pref}-isize is the sum of its items' {min/pref}-isizes and
+ // (n-1) column gaps.
// * For a column-oriented flex container, the intrinsic min isize
// is the max of its items' min isizes.
// * For a row-oriented multi-line flex container, the intrinsic
// pref isize is former (sum), and its min isize is the latter (max).
bool isSingleLine = (NS_STYLE_FLEX_WRAP_NOWRAP == stylePos->mFlexWrap);
if (axisTracker.IsRowOriented() &&
(isSingleLine || aType == nsLayoutUtils::PREF_ISIZE)) {
containerISize += childISize;
+ if (!onFirstChild) {
+ containerISize += mainGapSize;
+ }
+ onFirstChild = false;
} else { // (col-oriented, or MIN_ISIZE for multi-line row flex container)
containerISize = std::max(containerISize, childISize);
}
}
}
return containerISize;
}