Bug 1144096 part 13 - [css-grid] Refactor ReflowChildren() by separating out the code that reflows normal flow children (grid items and placeholders) into a new method ReflowInFlowChild(). r=dholbert

This commit is contained in:
Mats Palmgren 2016-03-11 17:39:26 +01:00
parent 7b283c23f7
commit 1dbca39b11
2 changed files with 119 additions and 81 deletions

View File

@ -4057,6 +4057,94 @@ nsGridContainerFrame::GetNearestFragmentainer(const GridReflowState& aState) con
return data;
}
void
nsGridContainerFrame::ReflowInFlowChild(nsIFrame* aChild,
const GridItemInfo* aGridItemInfo,
nsSize aContainerSize,
const Fragmentainer* aFragmentainer,
const GridReflowState& aState,
const LogicalRect& aContentArea,
nsHTMLReflowMetrics& aDesiredSize,
nsReflowStatus& aStatus)
{
nsPresContext* pc = PresContext();
nsStyleContext* containerSC = StyleContext();
WritingMode wm = aState.mReflowState->GetWritingMode();
LogicalMargin pad(aState.mReflowState->ComputedLogicalPadding());
const LogicalPoint padStart(wm, pad.IStart(wm), pad.BStart(wm));
const bool isGridItem = !!aGridItemInfo;
MOZ_ASSERT(isGridItem == (aChild->GetType() != nsGkAtoms::placeholderFrame));
LogicalRect cb(wm);
WritingMode childWM = aChild->GetWritingMode();
if (MOZ_LIKELY(isGridItem)) {
MOZ_ASSERT(aGridItemInfo->mFrame == aChild);
const GridArea& area = aGridItemInfo->mArea;
MOZ_ASSERT(area.IsDefinite());
cb = aState.ContainingBlockFor(area);
cb += aContentArea.Origin(wm);
} else {
cb = aContentArea;
}
LogicalSize childCBSize = cb.Size(wm).ConvertTo(childWM, wm);
LogicalSize percentBasis(childCBSize);
// XXX temporary workaround to avoid being INCOMPLETE until we have
// support for fragmentation (bug 1144096)
childCBSize.BSize(childWM) = NS_UNCONSTRAINEDSIZE;
Maybe<nsHTMLReflowState> childRS; // Maybe<> so we can reuse the space
childRS.emplace(pc, *aState.mReflowState, aChild, childCBSize, &percentBasis);
// 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.
Maybe<nsHTMLReflowMetrics> childSize; // Maybe<> so we can reuse the space
childSize.emplace(*childRS);
const nsSize dummyContainerSize;
ReflowChild(aChild, pc, *childSize, *childRS, childWM, LogicalPoint(childWM),
dummyContainerSize, 0, aStatus);
LogicalPoint childPos =
cb.Origin(wm).ConvertTo(childWM, wm,
aContainerSize - childSize->PhysicalSize());
// Apply align/justify-self and reflow again if that affects the size.
if (isGridItem) {
LogicalSize oldSize = childSize->Size(childWM); // from the ReflowChild()
LogicalSize newContentSize(childWM);
auto align = childRS->mStylePosition->ComputedAlignSelf(containerSC);
Maybe<LogicalAxis> alignResize =
AlignSelf(align, cb, wm, *childRS, oldSize, &newContentSize, &childPos);
auto justify = childRS->mStylePosition->ComputedJustifySelf(containerSC);
Maybe<LogicalAxis> justifyResize =
JustifySelf(justify, cb, wm, *childRS, oldSize, &newContentSize, &childPos);
if (alignResize || justifyResize) {
FinishReflowChild(aChild, pc, *childSize, childRS.ptr(), childWM,
LogicalPoint(childWM), aContainerSize,
NS_FRAME_NO_MOVE_FRAME | NS_FRAME_NO_SIZE_VIEW);
childSize.reset(); // In reverse declaration order since it runs
childRS.reset(); // destructors.
childRS.emplace(pc, *aState.mReflowState, aChild, childCBSize, &percentBasis);
if ((alignResize && alignResize.value() == eLogicalAxisBlock) ||
(justifyResize && justifyResize.value() == eLogicalAxisBlock)) {
childRS->SetComputedBSize(newContentSize.BSize(childWM));
childRS->SetBResize(true);
}
if ((alignResize && alignResize.value() == eLogicalAxisInline) ||
(justifyResize && justifyResize.value() == eLogicalAxisInline)) {
childRS->SetComputedISize(newContentSize.ISize(childWM));
childRS->SetIResize(true);
}
childSize.emplace(*childRS);
ReflowChild(aChild, pc, *childSize, *childRS, childWM,
LogicalPoint(childWM), dummyContainerSize, 0, aStatus);
}
} else {
// Put a placeholder at the padding edge, in case an ancestor is its CB.
childPos -= padStart;
}
childRS->ApplyRelativePositioning(&childPos, aContainerSize);
FinishReflowChild(aChild, pc, *childSize, childRS.ptr(), childWM, childPos,
aContainerSize, 0);
ConsiderChildOverflow(aDesiredSize.mOverflowAreas, aChild);
}
void
nsGridContainerFrame::ReflowChildren(GridReflowState& aState,
const LogicalRect& aContentArea,
@ -4074,89 +4162,26 @@ nsGridContainerFrame::ReflowChildren(GridReflowState& aState,
}
WritingMode wm = aState.mReflowState->GetWritingMode();
const LogicalPoint gridOrigin(aContentArea.Origin(wm));
const nsSize containerSize =
(aContentArea.Size(wm) +
aState.mReflowState->ComputedLogicalBorderPadding().Size(wm)).GetPhysicalSize(wm);
nsPresContext* pc = PresContext();
nsStyleContext* containerSC = StyleContext();
LogicalMargin pad(aState.mReflowState->ComputedLogicalPadding());
const LogicalPoint padStart(wm, pad.IStart(wm), pad.BStart(wm));
for (; !aState.mIter.AtEnd(); aState.mIter.Next()) {
nsIFrame* child = *aState.mIter;
const bool isGridItem = child->GetType() != nsGkAtoms::placeholderFrame;
LogicalRect cb(wm);
if (MOZ_LIKELY(isGridItem)) {
MOZ_ASSERT(aState.mGridItems[aState.mIter.GridItemIndex()].mFrame == child,
"iterator out of sync with mGridItems");
GridArea& area = aState.mGridItems[aState.mIter.GridItemIndex()].mArea;
MOZ_ASSERT(area.IsDefinite());
cb = aState.ContainingBlockFor(area);
cb += gridOrigin;
} else {
cb = aContentArea;
}
WritingMode childWM = child->GetWritingMode();
LogicalSize childCBSize = cb.Size(wm).ConvertTo(childWM, wm);
LogicalSize percentBasis(childCBSize);
// XXX temporary workaround to avoid being INCOMPLETE until we have
// support for fragmentation (bug 1144096)
childCBSize.BSize(childWM) = NS_UNCONSTRAINEDSIZE;
Maybe<nsHTMLReflowState> childRS; // Maybe<> so we can reuse the space
childRS.emplace(pc, *aState.mReflowState, child, childCBSize, &percentBasis);
// 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
// containerSize, and then pass the correct position to FinishReflowChild.
Maybe<nsHTMLReflowMetrics> childSize; // Maybe<> so we can reuse the space
childSize.emplace(*childRS);
nsReflowStatus childStatus;
const nsSize dummyContainerSize;
ReflowChild(child, pc, *childSize, *childRS, childWM, LogicalPoint(childWM),
dummyContainerSize, 0, childStatus);
LogicalPoint childPos =
cb.Origin(wm).ConvertTo(childWM, wm,
containerSize - childSize->PhysicalSize());
// Apply align/justify-self and reflow again if that affects the size.
if (isGridItem) {
LogicalSize oldSize = childSize->Size(childWM); // from the ReflowChild()
LogicalSize newContentSize(childWM);
auto align = childRS->mStylePosition->ComputedAlignSelf(containerSC);
Maybe<LogicalAxis> alignResize =
AlignSelf(align, cb, wm, *childRS, oldSize, &newContentSize, &childPos);
auto justify = childRS->mStylePosition->ComputedJustifySelf(containerSC);
Maybe<LogicalAxis> justifyResize =
JustifySelf(justify, cb, wm, *childRS, oldSize, &newContentSize, &childPos);
if (alignResize || justifyResize) {
FinishReflowChild(child, pc, *childSize, childRS.ptr(), childWM,
LogicalPoint(childWM), containerSize,
NS_FRAME_NO_MOVE_FRAME | NS_FRAME_NO_SIZE_VIEW);
childSize.reset(); // In reverse declaration order since it runs
childRS.reset(); // destructors.
childRS.emplace(pc, *aState.mReflowState, child, childCBSize, &percentBasis);
if ((alignResize && alignResize.value() == eLogicalAxisBlock) ||
(justifyResize && justifyResize.value() == eLogicalAxisBlock)) {
childRS->SetComputedBSize(newContentSize.BSize(childWM));
childRS->SetBResize(true);
}
if ((alignResize && alignResize.value() == eLogicalAxisInline) ||
(justifyResize && justifyResize.value() == eLogicalAxisInline)) {
childRS->SetComputedISize(newContentSize.ISize(childWM));
childRS->SetIResize(true);
}
childSize.emplace(*childRS);
ReflowChild(child, pc, *childSize, *childRS, childWM,
LogicalPoint(childWM), dummyContainerSize, 0, childStatus);
nscoord bSize = aContentArea.BSize(wm);
if (false) {
// XXX TBD: a later patch will add the fragmented reflow here...
} else {
aState.mIter.Reset(GridItemCSSOrderIterator::eIncludeAll);
for (; !aState.mIter.AtEnd(); aState.mIter.Next()) {
nsIFrame* child = *aState.mIter;
const GridItemInfo* info = nullptr;
if (child->GetType() != nsGkAtoms::placeholderFrame) {
info = &aState.mGridItems[aState.mIter.GridItemIndex()];
}
} else {
// Put a placeholder at the padding edge, in case an ancestor is its CB.
childPos -= padStart;
ReflowInFlowChild(*aState.mIter, info, containerSize, nullptr,
aState, aContentArea, aDesiredSize, aStatus);
MOZ_ASSERT(NS_FRAME_IS_COMPLETE(aStatus), "child should be complete "
"in unconstrained reflow");
}
childRS->ApplyRelativePositioning(&childPos, containerSize);
FinishReflowChild(child, pc, *childSize, childRS.ptr(), childWM, childPos,
containerSize, 0);
ConsiderChildOverflow(aDesiredSize.mOverflowAreas, child);
// XXX deal with 'childStatus' not being COMPLETE (bug 1144096)
}
// Merge overflow container bounds and status.
@ -4166,11 +4191,13 @@ nsGridContainerFrame::ReflowChildren(GridReflowState& aState,
if (IsAbsoluteContainer()) {
nsFrameList children(GetChildList(GetAbsoluteListID()));
if (!children.IsEmpty()) {
// 'padStart' is the origin of the grid (the start of the first track),
// 'gridOrigin' is the origin of the grid (the start of the first track),
// with respect to the grid container's padding-box (CB).
LogicalMargin pad(aState.mReflowState->ComputedLogicalPadding());
const LogicalPoint gridOrigin(wm, pad.IStart(wm), pad.BStart(wm));
const LogicalRect gridCB(wm, 0, 0,
aContentArea.ISize(wm) + pad.IStartEnd(wm),
aContentArea.BSize(wm) + pad.BStartEnd(wm));
bSize + pad.BStartEnd(wm));
const nsSize gridCBPhysicalSize = gridCB.Size(wm).GetPhysicalSize(wm);
size_t i = 0;
for (nsFrameList::Enumerator e(children); !e.AtEnd(); e.Next(), ++i) {
@ -4179,7 +4206,7 @@ nsGridContainerFrame::ReflowChildren(GridReflowState& aState,
MOZ_ASSERT(aState.mAbsPosItems[i].mFrame == child);
GridArea& area = aState.mAbsPosItems[i].mArea;
LogicalRect itemCB =
aState.ContainingBlockForAbsPos(area, padStart, gridCB);
aState.ContainingBlockForAbsPos(area, gridOrigin, gridCB);
// nsAbsoluteContainingBlock::Reflow uses physical coordinates.
nsRect* cb = static_cast<nsRect*>(child->Properties().Get(
GridItemContainingBlockRect()));
@ -4197,7 +4224,8 @@ nsGridContainerFrame::ReflowChildren(GridReflowState& aState,
AbsPosReflowFlags::eCBWidthAndHeightChanged; // XXX could be optimized
flags |= AbsPosReflowFlags::eConstrainHeight;
flags |= AbsPosReflowFlags::eIsGridContainerCB;
GetAbsoluteContainingBlock()->Reflow(this, pc, *aState.mReflowState,
GetAbsoluteContainingBlock()->Reflow(this, PresContext(),
*aState.mReflowState,
aStatus, dummyRect, flags,
&aDesiredSize.mOverflowAreas);
}

View File

@ -183,6 +183,16 @@ private:
Maybe<nsGridContainerFrame::Fragmentainer>
GetNearestFragmentainer(const GridReflowState& aState) const;
// Helper for ReflowChildren / ReflowInFragmentainer
void ReflowInFlowChild(nsIFrame* aChild,
const GridItemInfo* aGridItemInfo,
nsSize aContainerSize,
const Fragmentainer* aFragmentainer,
const GridReflowState& aState,
const LogicalRect& aContentArea,
nsHTMLReflowMetrics& aDesiredSize,
nsReflowStatus& aStatus);
/**
* Cached values to optimize GetMinISize/GetPrefISize.
*/