Bug 1547560 - [css-grid-2] Add subgrid gaps to its items contributions in track sizing and recompute the subgrid tracks size/position to center the subgrid gaps. r=dholbert

Differential Revision: https://phabricator.services.mozilla.com/D31630

--HG--
extra : rebase_source : 5357831ac1395ae8f8f9252bb5a75b4c08eab25d
This commit is contained in:
Mats Palmgren 2019-05-17 16:50:42 +02:00
parent a697823fed
commit 29ee64cea5

View File

@ -4466,26 +4466,51 @@ static nscoord ContentContribution(
nscoord aMinSizeClamp = NS_MAXSIZE, uint32_t aFlags = 0) {
nsIFrame* child = aGridItem.mFrame;
// If |child| is a subgrid descendant, then it contributes its subgrids'
// margin+border+padding for any edge tracks that it spans.
nscoord extraMargin = 0;
nsGridContainerFrame::Subgrid* subgrid = nullptr;
if (child->GetParent() != aState.mFrame &&
(aGridItem.mState[aAxis] & ItemState::eEdgeBits)) {
if (child->GetParent() != aState.mFrame) {
// |child| is a subgrid descendant, so it contributes its subgrids'
// margin+border+padding for any edge tracks that it spans.
auto* subgridFrame = child->GetParent();
subgrid = subgridFrame->GetProperty(Subgrid::Prop());
const auto itemEdgeBits = aGridItem.mState[aAxis] & ItemState::eEdgeBits;
if (itemEdgeBits) {
LogicalMargin mbp = SubgridAccumulatedMarginBorderPadding(
subgridFrame, subgrid, aCBWM, aAxis);
auto state = aGridItem.mState[aAxis];
if (state & ItemState::eStartEdge) {
if (itemEdgeBits & ItemState::eStartEdge) {
extraMargin += mbp.Start(aAxis, aCBWM);
}
if (state & ItemState::eEndEdge) {
if (itemEdgeBits & ItemState::eEndEdge) {
extraMargin += mbp.End(aAxis, aCBWM);
}
}
// XXX add in subgrid gap contribution here... (bug 1547560)
// It also contributes (half of) the subgrid's gap on its edges (if any)
// subtracted by the non-subgrid ancestor grid container's gap.
// Note that this can also be negative since it's considered a margin.
if (itemEdgeBits != ItemState::eEdgeBits) {
auto subgridAxis = aCBWM.IsOrthogonalTo(subgridFrame->GetWritingMode())
? GetOrthogonalAxis(aAxis) : aAxis;
auto& gapStyle = subgridAxis == eLogicalAxisBlock ?
subgridFrame->StylePosition()->mRowGap :
subgridFrame->StylePosition()->mColumnGap;
if (!gapStyle.IsNormal()) {
auto subgridExtent =
subgridAxis == eLogicalAxisBlock ? subgrid->mGridRowEnd
: subgrid->mGridColEnd;
if (subgridExtent > 1) {
nscoord subgridGap =
nsLayoutUtils::ResolveGapToLength(gapStyle, NS_UNCONSTRAINEDSIZE);
auto& tracks = aAxis == eLogicalAxisBlock ? aState.mRows : aState.mCols;
auto gapDelta = subgridGap - tracks.mGridGap;
if (!itemEdgeBits) {
extraMargin += gapDelta;
} else {
extraMargin += gapDelta / 2;
}
}
}
}
}
PhysicalAxis axis(aCBWM.PhysicalAxis(aAxis));
nscoord size = nsLayoutUtils::IntrinsicForAxis(
@ -5588,23 +5613,73 @@ void nsGridContainerFrame::Tracks::StretchFlexibleTracks(
void nsGridContainerFrame::Tracks::AlignJustifyContent(
const nsStylePosition* aStyle, WritingMode aWM, nscoord aContentSize,
bool aIsSubgriddedAxis) {
const bool isAlign = mAxis == eLogicalAxisBlock;
// Align-/justify-content doesn't apply in a subgridded axis.
// Gap properties do apply though so we need to stretch/position the tracks
// to center-align the gaps with the parent's gaps.
if (MOZ_UNLIKELY(aIsSubgriddedAxis)) {
auto& gap = isAlign ? aStyle->mRowGap : aStyle->mColumnGap;
if (gap.IsNormal()) {
return;
}
auto len = mSizes.Length();
if (len <= 1) {
return;
}
// This stores the gap deltas between the subgrid gap and the gaps in
// the used track sizes (as encoded in its tracks' mPosition):
nsTArray<nscoord> gapDeltas;
const size_t numGaps = len - 1;
gapDeltas.SetLength(numGaps);
for (size_t i = 0; i < numGaps; ++i) {
TrackSize& sz1 = mSizes[i];
TrackSize& sz2 = mSizes[i + 1];
nscoord currentGap = sz2.mPosition - (sz1.mPosition + sz1.mBase);
gapDeltas[i] = mGridGap - currentGap;
}
// Recompute the tracks' size/position so that they end up with
// a subgrid-gap centered on the original track gap.
nscoord currentPos = mSizes[0].mPosition;
nscoord lastHalfDelta(0);
for (size_t i = 0; i < numGaps; ++i) {
TrackSize& sz = mSizes[i];
nscoord delta = gapDeltas[i];
nscoord halfDelta;
nscoord roundingError = NSCoordDivRem(delta, 2, &halfDelta);
auto newSize = sz.mBase - (halfDelta + roundingError) - lastHalfDelta;
lastHalfDelta = halfDelta;
if (newSize >= 0) {
sz.mBase = newSize;
sz.mPosition = currentPos;
currentPos += newSize + mGridGap;
} else {
sz.mBase = nscoord(0);
sz.mPosition = currentPos + newSize;
currentPos = sz.mPosition + mGridGap;
}
}
auto& lastTrack = mSizes.LastElement();
auto newSize = lastTrack.mBase - lastHalfDelta;
if (newSize >= 0) {
lastTrack.mBase = newSize;
lastTrack.mPosition = currentPos;
} else {
lastTrack.mBase = nscoord(0);
lastTrack.mPosition = currentPos + newSize;
}
return;
}
if (mSizes.IsEmpty()) {
return;
}
const bool isAlign = mAxis == eLogicalAxisBlock;
auto valueAndFallback =
isAlign ? aStyle->mAlignContent : aStyle->mJustifyContent;
bool overflowSafe;
auto alignment =
::GetAlignJustifyValue(valueAndFallback, aWM, isAlign, &overflowSafe);
if (alignment == NS_STYLE_ALIGN_NORMAL) {
if (aIsSubgriddedAxis) {
auto& gap = isAlign ? aStyle->mRowGap : aStyle->mColumnGap;
if (gap.IsNormal()) {
return;
}
}
MOZ_ASSERT(valueAndFallback == NS_STYLE_ALIGN_NORMAL,
"*-content:normal cannot be specified with explicit fallback");
alignment = NS_STYLE_ALIGN_STRETCH;
@ -5616,12 +5691,16 @@ void nsGridContainerFrame::Tracks::AlignJustifyContent(
nscoord space;
if (alignment != NS_STYLE_ALIGN_START) {
nscoord trackSizeSum = 0;
if (aIsSubgriddedAxis) {
numAutoTracks = mSizes.Length();
} else {
for (const TrackSize& sz : mSizes) {
trackSizeSum += sz.mBase;
if (sz.mState & TrackSize::eAutoMaxSizing) {
++numAutoTracks;
}
}
}
space = aContentSize - trackSizeSum - SumOfGridGaps();
// Use the fallback value instead when applicable.
if (space < 0 ||
@ -7032,6 +7111,8 @@ void nsGridContainerFrame::Reflow(nsPresContext* aPresContext,
if (!prevInFlow) {
const auto& rowSizes = gridReflowInput.mRows.mSizes;
if (!IsRowSubgrid()) {
// Apply 'align-content' to the grid.
if (computedBSize == NS_AUTOHEIGHT &&
stylePos->mRowGap.IsLengthPercentage() &&
stylePos->mRowGap.AsLengthPercentage().HasPercent()) {
@ -7039,13 +7120,8 @@ void nsGridContainerFrame::Reflow(nsPresContext* aPresContext,
gridReflowInput.mRows.mGridGap =
nsLayoutUtils::ResolveGapToLength(stylePos->mRowGap, bSize);
}
if (!IsRowSubgrid()) {
// Apply 'align-content' to the grid.
gridReflowInput.mRows.AlignJustifyContent(stylePos, wm, bSize, false);
} else if (!rowSizes.IsEmpty()) {
gridReflowInput.mRows.mGridGap =
nsLayoutUtils::ResolveGapToLength(stylePos->mRowGap, bSize);
gridReflowInput.mRows.AlignJustifyContent(stylePos, wm, bSize, true);
} else {
if (computedBSize == NS_AUTOHEIGHT) {
bSize = gridReflowInput.mRows.GridLineEdge(rowSizes.Length(),
GridLineSide::BeforeGridGap);