Bug 1271392 part 4 - [css-grid] Make sure a grid item's last fragment fills its grid area. r=dholbert

This commit is contained in:
Mats Palmgren 2016-05-18 13:49:33 +02:00
parent 88e4ba9cfe
commit 4d19f2a6ef
4 changed files with 61 additions and 10 deletions

View File

@ -1616,13 +1616,29 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
}
}
if (IS_TRUE_OVERFLOW_CONTAINER(this) &&
NS_FRAME_IS_NOT_COMPLETE(aState.mReflowStatus)) {
// Overflow containers can only be overflow complete.
// Note that auto height overflow containers have no normal children
NS_ASSERTION(finalSize.BSize(wm) == 0,
"overflow containers must be zero-block-size");
NS_FRAME_SET_OVERFLOW_INCOMPLETE(aState.mReflowStatus);
if (IS_TRUE_OVERFLOW_CONTAINER(this)) {
if (NS_FRAME_IS_NOT_COMPLETE(aState.mReflowStatus)) {
// Overflow containers can only be overflow complete.
// Note that auto height overflow containers have no normal children
NS_ASSERTION(finalSize.BSize(wm) == 0,
"overflow containers must be zero-block-size");
NS_FRAME_SET_OVERFLOW_INCOMPLETE(aState.mReflowStatus);
}
} else if (aReflowState.AvailableBSize() != NS_UNCONSTRAINEDSIZE &&
!NS_INLINE_IS_BREAK_BEFORE(aState.mReflowStatus) &&
NS_FRAME_IS_COMPLETE(aState.mReflowStatus)) {
// Currently only used for grid items, but could be used in other contexts.
// The FragStretchBSizeProperty is our expected non-fragmented block-size
// we should stretch to (for align-self:stretch etc). In some fragmentation
// cases though, the last fragment (this frame since we're complete), needs
// to have extra size applied because earlier fragments consumed to much of
// our computed size due to overflowing their containing block. (E.g. this
// ensures we fill the last row when a multi-row grid item is fragmented).
bool found;
nscoord bSize = Properties().Get(FragStretchBSizeProperty(), &found);
if (found) {
finalSize.BSize(wm) = std::max(bSize, finalSize.BSize(wm));
}
}
// Screen out negative block sizes --- can happen due to integer overflows :-(

View File

@ -4130,6 +4130,7 @@ void
nsGridContainerFrame::ReflowInFlowChild(nsIFrame* aChild,
const GridItemInfo* aGridItemInfo,
nsSize aContainerSize,
Maybe<nscoord> aStretchBSize,
const Fragmentainer* aFragmentainer,
const GridReflowState& aState,
const LogicalRect& aContentArea,
@ -4177,6 +4178,28 @@ nsGridContainerFrame::ReflowInFlowChild(nsIFrame* aChild,
Maybe<nsHTMLReflowState> childRS; // Maybe<> so we can reuse the space
childRS.emplace(pc, *aState.mReflowState, aChild, childCBSize, &percentBasis);
childRS->mFlags.mIsTopOfPage = aFragmentainer ? aFragmentainer->mIsTopOfPage : false;
// If the child is stretching in its block axis, and we might be fragmenting
// it in that axis, then setup a frame property to tell
// nsBlockFrame::ComputeFinalSize the size.
if (isConstrainedBSize && !wm.IsOrthogonalTo(childWM)) {
bool stretch = false;
if (!childRS->mStyleMargin->HasBlockAxisAuto(childWM) &&
childRS->mStylePosition->BSize(childWM).GetUnit() == eStyleUnit_Auto) {
auto blockAxisAlignment =
childRS->mStylePosition->ComputedAlignSelf(StyleContext());
if (blockAxisAlignment == NS_STYLE_ALIGN_NORMAL ||
blockAxisAlignment == NS_STYLE_ALIGN_STRETCH) {
stretch = true;
}
}
if (stretch) {
aChild->Properties().Set(FragStretchBSizeProperty(), *aStretchBSize);
} else {
aChild->Properties().Delete(FragStretchBSizeProperty());
}
}
// We need the width of the child before we can correctly convert
// the writing-mode of its origin, so we reflow at (0, 0) using a dummy
// aContainerSize, and then pass the correct position to FinishReflowChild.
@ -4273,7 +4296,8 @@ nsGridContainerFrame::ReflowInFragmentainer(GridReflowState& aState,
// Reflow our placeholder children; they must all be complete.
for (auto child : placeholders) {
nsReflowStatus childStatus;
ReflowInFlowChild(child, nullptr, aContainerSize, &aFragmentainer,
Maybe<nscoord> nothing;
ReflowInFlowChild(child, nullptr, aContainerSize, nothing, &aFragmentainer,
aState, aContentArea, aDesiredSize, childStatus);
MOZ_ASSERT(NS_FRAME_IS_COMPLETE(childStatus),
"nsPlaceholderFrame should never need to be fragmented");
@ -4544,7 +4568,14 @@ nsGridContainerFrame::ReflowRowsInFragmentainer(
// We only restart the loop once.
aFragmentainer.mIsTopOfPage = isRowTopOfPage && !rowCanGrow;
nsReflowStatus childStatus;
ReflowInFlowChild(child, info, aContainerSize, &aFragmentainer,
// Pass along how much to stretch this fragment, in case it's needed.
Maybe<nscoord> bSize;
bSize.emplace(
aState.mRows.GridLineEdge(std::min(aEndRow, info->mArea.mRows.mEnd),
GridLineSide::eBeforeGridGap) -
aState.mRows.GridLineEdge(std::max(aStartRow, row),
GridLineSide::eAfterGridGap));
ReflowInFlowChild(child, info, aContainerSize, bSize, &aFragmentainer,
aState, aContentArea, aDesiredSize, childStatus);
MOZ_ASSERT(NS_INLINE_IS_BREAK_BEFORE(childStatus) ||
!NS_FRAME_IS_FULLY_COMPLETE(childStatus) ||
@ -4764,7 +4795,8 @@ nsGridContainerFrame::ReflowChildren(GridReflowState& aState,
if (child->GetType() != nsGkAtoms::placeholderFrame) {
info = &aState.mGridItems[aState.mIter.GridItemIndex()];
}
ReflowInFlowChild(*aState.mIter, info, containerSize, nullptr,
Maybe<nscoord> nothing;
ReflowInFlowChild(*aState.mIter, info, containerSize, nothing, nullptr,
aState, aContentArea, aDesiredSize, aStatus);
MOZ_ASSERT(NS_FRAME_IS_COMPLETE(aStatus), "child should be complete "
"in unconstrained reflow");

View File

@ -234,6 +234,7 @@ private:
void ReflowInFlowChild(nsIFrame* aChild,
const GridItemInfo* aGridItemInfo,
nsSize aContainerSize,
mozilla::Maybe<nscoord>aStretchBSize,
const Fragmentainer* aFragmentainer,
const GridReflowState& aState,
const LogicalRect& aContentArea,

View File

@ -943,6 +943,8 @@ public:
NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(RefusedAsyncAnimationProperty, bool)
NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(FragStretchBSizeProperty, nscoord)
NS_DECLARE_FRAME_PROPERTY_WITH_DTOR(GenConProperty, ContentArray,
DestroyContentArray)