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,27 +4466,52 @@ static nscoord ContentContribution(
nscoord aMinSizeClamp = NS_MAXSIZE, uint32_t aFlags = 0) { nscoord aMinSizeClamp = NS_MAXSIZE, uint32_t aFlags = 0) {
nsIFrame* child = aGridItem.mFrame; 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; nscoord extraMargin = 0;
nsGridContainerFrame::Subgrid* subgrid = nullptr; nsGridContainerFrame::Subgrid* subgrid = nullptr;
if (child->GetParent() != aState.mFrame && if (child->GetParent() != aState.mFrame) {
(aGridItem.mState[aAxis] & ItemState::eEdgeBits)) { // |child| is a subgrid descendant, so it contributes its subgrids'
// margin+border+padding for any edge tracks that it spans.
auto* subgridFrame = child->GetParent(); auto* subgridFrame = child->GetParent();
subgrid = subgridFrame->GetProperty(Subgrid::Prop()); subgrid = subgridFrame->GetProperty(Subgrid::Prop());
LogicalMargin mbp = SubgridAccumulatedMarginBorderPadding( const auto itemEdgeBits = aGridItem.mState[aAxis] & ItemState::eEdgeBits;
subgridFrame, subgrid, aCBWM, aAxis); if (itemEdgeBits) {
auto state = aGridItem.mState[aAxis]; LogicalMargin mbp = SubgridAccumulatedMarginBorderPadding(
if (state & ItemState::eStartEdge) { subgridFrame, subgrid, aCBWM, aAxis);
extraMargin += mbp.Start(aAxis, aCBWM); if (itemEdgeBits & ItemState::eStartEdge) {
extraMargin += mbp.Start(aAxis, aCBWM);
}
if (itemEdgeBits & ItemState::eEndEdge) {
extraMargin += mbp.End(aAxis, aCBWM);
}
} }
if (state & ItemState::eEndEdge) { // It also contributes (half of) the subgrid's gap on its edges (if any)
extraMargin += mbp.End(aAxis, aCBWM); // 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;
}
}
}
} }
} }
// XXX add in subgrid gap contribution here... (bug 1547560)
PhysicalAxis axis(aCBWM.PhysicalAxis(aAxis)); PhysicalAxis axis(aCBWM.PhysicalAxis(aAxis));
nscoord size = nsLayoutUtils::IntrinsicForAxis( nscoord size = nsLayoutUtils::IntrinsicForAxis(
axis, aRC, child, aConstraint, aPercentageBasis, axis, aRC, child, aConstraint, aPercentageBasis,
@ -5588,23 +5613,73 @@ void nsGridContainerFrame::Tracks::StretchFlexibleTracks(
void nsGridContainerFrame::Tracks::AlignJustifyContent( void nsGridContainerFrame::Tracks::AlignJustifyContent(
const nsStylePosition* aStyle, WritingMode aWM, nscoord aContentSize, const nsStylePosition* aStyle, WritingMode aWM, nscoord aContentSize,
bool aIsSubgriddedAxis) { 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()) { if (mSizes.IsEmpty()) {
return; return;
} }
const bool isAlign = mAxis == eLogicalAxisBlock;
auto valueAndFallback = auto valueAndFallback =
isAlign ? aStyle->mAlignContent : aStyle->mJustifyContent; isAlign ? aStyle->mAlignContent : aStyle->mJustifyContent;
bool overflowSafe; bool overflowSafe;
auto alignment = auto alignment =
::GetAlignJustifyValue(valueAndFallback, aWM, isAlign, &overflowSafe); ::GetAlignJustifyValue(valueAndFallback, aWM, isAlign, &overflowSafe);
if (alignment == NS_STYLE_ALIGN_NORMAL) { 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, MOZ_ASSERT(valueAndFallback == NS_STYLE_ALIGN_NORMAL,
"*-content:normal cannot be specified with explicit fallback"); "*-content:normal cannot be specified with explicit fallback");
alignment = NS_STYLE_ALIGN_STRETCH; alignment = NS_STYLE_ALIGN_STRETCH;
@ -5616,10 +5691,14 @@ void nsGridContainerFrame::Tracks::AlignJustifyContent(
nscoord space; nscoord space;
if (alignment != NS_STYLE_ALIGN_START) { if (alignment != NS_STYLE_ALIGN_START) {
nscoord trackSizeSum = 0; nscoord trackSizeSum = 0;
for (const TrackSize& sz : mSizes) { if (aIsSubgriddedAxis) {
trackSizeSum += sz.mBase; numAutoTracks = mSizes.Length();
if (sz.mState & TrackSize::eAutoMaxSizing) { } else {
++numAutoTracks; for (const TrackSize& sz : mSizes) {
trackSizeSum += sz.mBase;
if (sz.mState & TrackSize::eAutoMaxSizing) {
++numAutoTracks;
}
} }
} }
space = aContentSize - trackSizeSum - SumOfGridGaps(); space = aContentSize - trackSizeSum - SumOfGridGaps();
@ -7032,20 +7111,17 @@ void nsGridContainerFrame::Reflow(nsPresContext* aPresContext,
if (!prevInFlow) { if (!prevInFlow) {
const auto& rowSizes = gridReflowInput.mRows.mSizes; const auto& rowSizes = gridReflowInput.mRows.mSizes;
if (computedBSize == NS_AUTOHEIGHT &&
stylePos->mRowGap.IsLengthPercentage() &&
stylePos->mRowGap.AsLengthPercentage().HasPercent()) {
// Re-resolve the row-gap now that we know our intrinsic block-size.
gridReflowInput.mRows.mGridGap =
nsLayoutUtils::ResolveGapToLength(stylePos->mRowGap, bSize);
}
if (!IsRowSubgrid()) { if (!IsRowSubgrid()) {
// Apply 'align-content' to the grid. // Apply 'align-content' to the grid.
if (computedBSize == NS_AUTOHEIGHT &&
stylePos->mRowGap.IsLengthPercentage() &&
stylePos->mRowGap.AsLengthPercentage().HasPercent()) {
// Re-resolve the row-gap now that we know our intrinsic block-size.
gridReflowInput.mRows.mGridGap =
nsLayoutUtils::ResolveGapToLength(stylePos->mRowGap, bSize);
}
gridReflowInput.mRows.AlignJustifyContent(stylePos, wm, bSize, false); gridReflowInput.mRows.AlignJustifyContent(stylePos, wm, bSize, false);
} else if (!rowSizes.IsEmpty()) { } else {
gridReflowInput.mRows.mGridGap =
nsLayoutUtils::ResolveGapToLength(stylePos->mRowGap, bSize);
gridReflowInput.mRows.AlignJustifyContent(stylePos, wm, bSize, true);
if (computedBSize == NS_AUTOHEIGHT) { if (computedBSize == NS_AUTOHEIGHT) {
bSize = gridReflowInput.mRows.GridLineEdge(rowSizes.Length(), bSize = gridReflowInput.mRows.GridLineEdge(rowSizes.Length(),
GridLineSide::BeforeGridGap); GridLineSide::BeforeGridGap);