Bug 1176619 - [css-grid] Implement the "Maximize Tracks" algorithm. r=dholbert
authorMats Palmgren <mats@mozilla.com>
Fri, 04 Sep 2015 22:06:57 +0200
changeset 293719 ed39340ecfc9e142a9dc38f3dd0350daa338f14a
parent 293718 390aba3006bcfa823c5bcc6d8431f7472d0f3de9
child 293720 71aea85370eb0e201273883b71755851e604751b
push id5245
push userraliiev@mozilla.com
push dateThu, 29 Oct 2015 11:30:51 +0000
treeherdermozilla-beta@dac831dc1bd0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdholbert
bugs1176619
milestone43.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 1176619 - [css-grid] Implement the "Maximize Tracks" algorithm. r=dholbert
layout/generic/nsGridContainerFrame.cpp
layout/reftests/css-grid/grid-whitespace-handling-2-ref.xhtml
--- a/layout/generic/nsGridContainerFrame.cpp
+++ b/layout/generic/nsGridContainerFrame.cpp
@@ -489,16 +489,65 @@ struct MOZ_STACK_CLASS nsGridContainerFr
     nscoord space = GrowTracksToLimit(aAvailableSpace, aPlan, aGrowableTracks);
     if (space > 0) {
       GrowSelectedTracksUnlimited(aAvailableSpace, aPlan, aGrowableTracks,
                                   TrackSize::StateBits(0));
     }
     CopyPlanToLimit(aPlan, aGrowableTracks);
   }
 
+  /**
+   * Distribute aAvailableSize to the tracks.  This implements 12.6 at:
+   * http://dev.w3.org/csswg/css-grid/#algo-grow-tracks
+   */
+  void DistributeFreeSpace(nscoord aAvailableSize)
+  {
+    const uint32_t numTracks = mSizes.Length();
+    if (MOZ_UNLIKELY(numTracks == 0 || aAvailableSize <= 0)) {
+      return;
+    }
+    if (aAvailableSize == NS_UNCONSTRAINEDSIZE) {
+      for (TrackSize& sz : mSizes) {
+        sz.mBase = sz.mLimit;
+      }
+    } else {
+      // Compute free space and count growable tracks.
+      nscoord space = aAvailableSize;
+      uint32_t numGrowable = numTracks;
+      for (const TrackSize& sz : mSizes) {
+        space -= sz.mBase;
+        MOZ_ASSERT(sz.mBase <= sz.mLimit);
+        if (sz.mBase == sz.mLimit) {
+          --numGrowable;
+        }
+      }
+      // Distribute the free space evenly to the growable tracks. If not exactly
+      // divisable the remainder is added to the leading tracks.
+      while (space > 0 && numGrowable) {
+        nscoord spacePerTrack =
+          std::max<nscoord>(space / numGrowable, 1);
+        for (uint32_t i = 0; i < numTracks && space > 0; ++i) {
+          TrackSize& sz = mSizes[i];
+          if (sz.mBase == sz.mLimit) {
+            continue;
+          }
+          nscoord newBase = sz.mBase + spacePerTrack;
+          if (newBase >= sz.mLimit) {
+            space -= sz.mLimit - sz.mBase;
+            sz.mBase = sz.mLimit;
+            --numGrowable;
+          } else {
+            space -= spacePerTrack;
+            sz.mBase = newBase;
+          }
+        }
+      }
+    }
+  }
+
 #ifdef DEBUG
   void Dump() const
   {
     for (uint32_t i = 0, len = mSizes.Length(); i < len; ++i) {
       printf("  %d: ", i);
       mSizes[i].Dump();
       printf("\n");
     }
@@ -1645,29 +1694,35 @@ nsGridContainerFrame::CalculateTrackSize
   PodZero(aState.mCols.mSizes.Elements(), aState.mCols.mSizes.Length());
   const WritingMode& wm = aState.mWM;
   nscoord colPercentageBasis = aContentBox.ISize(wm);
   auto& colFunctions = aState.mColFunctions;
   aState.mCols.Initialize(colFunctions, colPercentageBasis);
   aState.mCols.ResolveIntrinsicSize(aState, mGridItems, colFunctions,
                                     &GridArea::mCols, colPercentageBasis,
                                     aConstraint);
+  if (aConstraint != nsLayoutUtils::MIN_ISIZE) {
+    aState.mCols.DistributeFreeSpace(aContentBox.ISize(wm));
+  }
 
   aState.mRows.mSizes.SetLength(mGridRowEnd);
   PodZero(aState.mRows.mSizes.Elements(), aState.mRows.mSizes.Length());
   nscoord rowPercentageBasis = aContentBox.BSize(wm);
   if (rowPercentageBasis == NS_AUTOHEIGHT) {
     rowPercentageBasis = 0;
   }
   auto& rowFunctions = aState.mRowFunctions;
   aState.mRows.Initialize(rowFunctions, rowPercentageBasis);
   aState.mIter.Reset(); // XXX cleanup this Reset mess!
   aState.mRows.ResolveIntrinsicSize(aState, mGridItems, rowFunctions,
                                     &GridArea::mRows, rowPercentageBasis,
                                     aConstraint);
+  if (aConstraint != nsLayoutUtils::MIN_ISIZE) {
+    aState.mRows.DistributeFreeSpace(aContentBox.BSize(wm));
+  }
 }
 
 bool
 nsGridContainerFrame::Tracks::HasIntrinsicButNoFlexSizingInRange(
   const LineRange&      aRange,
   IntrinsicISizeType    aConstraint,
   TrackSize::StateBits* aState) const
 {
--- a/layout/reftests/css-grid/grid-whitespace-handling-2-ref.xhtml
+++ b/layout/reftests/css-grid/grid-whitespace-handling-2-ref.xhtml
@@ -9,17 +9,17 @@
      grid item (to ensure that the whitespace is included).
 -->
 <html xmlns="http://www.w3.org/1999/xhtml">
   <head>
     <title>CSS Reftest Reference</title>
     <link rel="author" title="Daniel Holbert" href="mailto:dholbert@mozilla.com"/>
     <link rel="stylesheet" type="text/css" href="support/ahem.css" />
     <style>
-      div { height: 100px; }
+      div.a, div.b, div.grid { height: 100px; }
       div.grid {
         white-space: pre;
         border: 1px dashed blue;
         width: 200px;
         display: grid;
         justify-content: space-around;
       }
       div.a {