Bug 1144096 part 14 - [css-grid] Make ReflowInFlowChild() deal with a constrained available block-size. r=dholbert
authorMats Palmgren <mats@mozilla.com>
Fri, 11 Mar 2016 17:39:26 +0100
changeset 288306 77d251bd9afe14d6b024c6622e03d244289e0da8
parent 288305 33b3bfd3d4160439d6da2694841841f9fc02e3cc
child 288307 c5fd95723f2e70d51a3638534d7039f353b45435
push id30079
push userryanvm@gmail.com
push dateSat, 12 Mar 2016 20:24:19 +0000
treeherdermozilla-central@d1d47ba19ce9 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdholbert
bugs1144096
milestone48.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1144096 part 14 - [css-grid] Make ReflowInFlowChild() deal with a constrained available block-size. r=dholbert
layout/generic/nsGridContainerFrame.cpp
layout/generic/nsIFrame.h
--- a/layout/generic/nsGridContainerFrame.cpp
+++ b/layout/generic/nsGridContainerFrame.cpp
@@ -4071,64 +4071,95 @@ nsGridContainerFrame::ReflowInFlowChild(
   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();
+  bool isConstrainedBSize = false;
+  nscoord toFragmentainerEnd;
   if (MOZ_LIKELY(isGridItem)) {
     MOZ_ASSERT(aGridItemInfo->mFrame == aChild);
     const GridArea& area = aGridItemInfo->mArea;
     MOZ_ASSERT(area.IsDefinite());
     cb = aState.ContainingBlockFor(area);
+    isConstrainedBSize = aFragmentainer && !wm.IsOrthogonalTo(childWM);
+    if (isConstrainedBSize) {
+      nscoord fragCBOffset = cb.BStart(wm) - aState.mFragBStart;
+      if (fragCBOffset < 0) {
+        // Subtract the "consumed" part of the grid area.
+        cb.BSize(wm) = std::max(fragCBOffset + cb.BSize(wm), 0);
+      }
+      cb.BStart(wm) = std::max(fragCBOffset, 0);
+      toFragmentainerEnd = aFragmentainer->mToFragmentainerEnd -
+        aState.mFragBStart - cb.BStart(wm);
+      toFragmentainerEnd = std::max(toFragmentainerEnd, 0);
+    }
     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;
-
+
+  LogicalSize reflowSize(cb.Size(wm));
+  if (isConstrainedBSize) {
+    reflowSize.BSize(wm) = toFragmentainerEnd;
+  }
+  LogicalSize childCBSize = reflowSize.ConvertTo(childWM, wm);
+  if (!isConstrainedBSize) {
+    childCBSize.BSize(childWM) = NS_UNCONSTRAINEDSIZE;
+  }
+
+  LogicalSize percentBasis(cb.Size(wm).ConvertTo(childWM, wm));
   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;
   // 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) {
+  if (MOZ_LIKELY(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);
+    Maybe<LogicalAxis> alignResize;
+    if (NS_FRAME_IS_COMPLETE(aStatus)) {
+      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);
+      childRS->mFlags.mIsTopOfPage = aFragmentainer ? aFragmentainer->mIsTopOfPage : false;
       if ((alignResize && alignResize.value() == eLogicalAxisBlock) ||
           (justifyResize && justifyResize.value() == eLogicalAxisBlock)) {
-        childRS->SetComputedBSize(newContentSize.BSize(childWM));
+        nscoord childConsumedBSize = 0;
+        if (isConstrainedBSize) {
+          // XXX use aChild->GetConsumedBSize() instead after bug 1232194 is fixed
+          for (auto prev = aChild->GetPrevInFlow(); prev; prev = prev->GetPrevInFlow()) {
+            childConsumedBSize += prev->ContentBSize(childWM);
+          }
+        }
+        childRS->SetComputedBSize(childConsumedBSize + 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);
--- a/layout/generic/nsIFrame.h
+++ b/layout/generic/nsIFrame.h
@@ -708,16 +708,22 @@ public:
   nscoord ISize() const { return ISize(GetWritingMode()); }
   nscoord ISize(mozilla::WritingMode aWritingMode) const {
     return GetLogicalSize(aWritingMode).ISize(aWritingMode);
   }
   nscoord BSize() const { return BSize(GetWritingMode()); }
   nscoord BSize(mozilla::WritingMode aWritingMode) const {
     return GetLogicalSize(aWritingMode).BSize(aWritingMode);
   }
+  nscoord ContentBSize() const { return ContentBSize(GetWritingMode()); }
+  nscoord ContentBSize(mozilla::WritingMode aWritingMode) const {
+    auto bp = GetLogicalUsedBorderAndPadding(aWritingMode);
+    bp.ApplySkipSides(GetLogicalSkipSides());
+    return std::max(0, BSize(aWritingMode) - bp.BStartEnd(aWritingMode));
+  }
 
   /**
    * When we change the size of the frame's border-box rect, we may need to
    * reset the overflow rect if it was previously stored as deltas.
    * (If it is currently a "large" overflow and could be re-packed as deltas,
    * we don't bother as the cost of the allocation has already been paid.)
    */
   void SetRect(const nsRect& aRect) {