Bug 1146051 part 6 - [css-grid] Make the grid zero-based after resolving definite lines. r=dholbert
authorMats Palmgren <mats@mozilla.com>
Thu, 30 Apr 2015 18:42:50 +0000
changeset 273271 3e1c6c1d1a350a7ead65ad30a4a2d8bc6a287383
parent 273270 224b82a7ed131e731ef621c0a85d7cde962ab159
child 273272 cd838a901830defba07d859b8ea282a6968d18a5
push id863
push userraliiev@mozilla.com
push dateMon, 03 Aug 2015 13:22:43 +0000
treeherdermozilla-release@f6321b14228d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdholbert
bugs1146051
milestone40.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 1146051 part 6 - [css-grid] Make the grid zero-based after resolving definite lines. r=dholbert
layout/generic/nsGridContainerFrame.cpp
layout/generic/nsGridContainerFrame.h
--- a/layout/generic/nsGridContainerFrame.cpp
+++ b/layout/generic/nsGridContainerFrame.cpp
@@ -258,18 +258,17 @@ static bool
 IsNameWithStartSuffix(const nsString& aString, uint32_t* aIndex)
 {
   return IsNameWithSuffix(aString, NS_LITERAL_STRING("-start"), aIndex);
 }
 
 static nscoord
 GridLinePosition(uint32_t aLine, const nsTArray<TrackSize>& aTrackSizes)
 {
-  MOZ_ASSERT(aLine != 0, "expected a 1-based line number");
-  const uint32_t endIndex = aLine - 1;
+  const uint32_t endIndex = aLine;
   MOZ_ASSERT(endIndex <= aTrackSizes.Length(), "aTrackSizes is too small");
   nscoord pos = 0;
   for (uint32_t i = 0; i < endIndex; ++i) {
     pos += aTrackSizes[i].mBase;
   }
   return pos;
 }
 
@@ -654,22 +653,20 @@ nsGridContainerFrame::ResolveAbsPosLineR
   MOZ_ASSERT(r.mStart <= r.mEnd);
   return r;
 }
 
 uint32_t
 nsGridContainerFrame::FindAutoCol(uint32_t aStartCol, uint32_t aLockedRow,
                                   const GridArea* aArea) const
 {
-  MOZ_ASSERT(aStartCol > 0, "expected a 1-based track number");
-  MOZ_ASSERT(aLockedRow > 0, "expected a 1-based track number");
   const uint32_t extent = aArea->mCols.Extent();
-  const uint32_t iStart = aLockedRow - 1;
+  const uint32_t iStart = aLockedRow;
   const uint32_t iEnd = iStart + aArea->mRows.Extent();
-  uint32_t candidate = aStartCol - 1;
+  uint32_t candidate = aStartCol;
   for (uint32_t i = iStart; i < iEnd; ) {
     if (i >= mCellMap.mCells.Length()) {
       break;
     }
     const nsTArray<CellMap::Cell>& cellsInRow = mCellMap.mCells[i];
     const uint32_t len = cellsInRow.Length();
     const uint32_t lastCandidate = candidate;
     // Find the first gap in the current row that's at least 'extent' wide.
@@ -688,17 +685,17 @@ nsGridContainerFrame::FindAutoCol(uint32
     if (lastCandidate < candidate && i != iStart) {
       // Couldn't fit 'extent' tracks at 'lastCandidate' here so we must
       // restart from the beginning with the new 'candidate'.
       i = iStart;
     } else {
       ++i;
     }
   }
-  return candidate + 1; // return a 1-based column number
+  return candidate;
 }
 
 nsGridContainerFrame::GridArea
 nsGridContainerFrame::PlaceAbsPos(nsIFrame* aChild,
                                   const nsStylePosition* aStyle)
 {
   const nsStylePosition* itemStyle = aChild->StylePosition();
   int32_t gridColStart = 1 - mExplicitGridOffsetCol;
@@ -728,23 +725,21 @@ nsGridContainerFrame::PlaceAutoCol(uint3
   aArea->mCols.ResolveAutoPosition(col);
   MOZ_ASSERT(aArea->IsDefinite());
 }
 
 uint32_t
 nsGridContainerFrame::FindAutoRow(uint32_t aLockedCol, uint32_t aStartRow,
                                   const GridArea* aArea) const
 {
-  MOZ_ASSERT(aLockedCol > 0, "expected a 1-based track number");
-  MOZ_ASSERT(aStartRow > 0, "expected a 1-based track number");
   const uint32_t extent = aArea->mRows.Extent();
-  const uint32_t jStart = aLockedCol - 1;
+  const uint32_t jStart = aLockedCol;
   const uint32_t jEnd = jStart + aArea->mCols.Extent();
   const uint32_t iEnd = mCellMap.mCells.Length();
-  uint32_t candidate = aStartRow - 1;
+  uint32_t candidate = aStartRow;
   // Find the first gap in the rows that's at least 'extent' tall.
   // ('gap' tracks how tall the current row gap is.)
   for (uint32_t i = candidate, gap = 0; i < iEnd && gap < extent; ++i) {
     ++gap; // tentative, but we may reset it below if a column is occupied
     const nsTArray<CellMap::Cell>& cellsInRow = mCellMap.mCells[i];
     const uint32_t clampedJEnd = std::min<uint32_t>(jEnd, cellsInRow.Length());
     // Check if the current row is unoccupied from jStart to jEnd.
     for (uint32_t j = jStart; j < clampedJEnd; ++j) {
@@ -752,17 +747,17 @@ nsGridContainerFrame::FindAutoRow(uint32
         // Couldn't fit 'extent' rows at 'candidate' here; we hit something
         // at row 'i'.  So, try the row after 'i' as our next candidate.
         candidate = i + 1;
         gap = 0;
         break;
       }
     }
   }
-  return candidate + 1; // return a 1-based row number
+  return candidate;
 }
 
 void
 nsGridContainerFrame::PlaceAutoRow(uint32_t aStartRow, GridArea* aArea) const
 {
   MOZ_ASSERT(aArea->mCols.IsDefinite() && aArea->mRows.IsAuto());
   uint32_t row = FindAutoRow(aArea->mCols.mStart, aStartRow, aArea);
   aArea->mRows.ResolveAutoPosition(row);
@@ -780,20 +775,20 @@ nsGridContainerFrame::PlaceAutoAutoInRow
   const uint32_t gridColEnd = mGridColEnd;
   uint32_t col = aStartCol;
   uint32_t row = aStartRow;
   for (; row < gridRowEnd; ++row) {
     col = FindAutoCol(col, row, aArea);
     if (col + colExtent <= gridColEnd) {
       break;
     }
-    col = 1;
+    col = 0;
   }
-  MOZ_ASSERT(row < gridRowEnd || col == 1,
-             "expected column 1 for placing in a new row");
+  MOZ_ASSERT(row < gridRowEnd || col == 0,
+             "expected column 0 for placing in a new row");
   aArea->mCols.ResolveAutoPosition(col);
   aArea->mRows.ResolveAutoPosition(row);
   MOZ_ASSERT(aArea->IsDefinite());
 }
 
 void
 nsGridContainerFrame::PlaceAutoAutoInColOrder(uint32_t aStartCol,
                                               uint32_t aStartRow,
@@ -805,29 +800,31 @@ nsGridContainerFrame::PlaceAutoAutoInCol
   const uint32_t gridColEnd = mGridColEnd;
   uint32_t col = aStartCol;
   uint32_t row = aStartRow;
   for (; col < gridColEnd; ++col) {
     row = FindAutoRow(col, row, aArea);
     if (row + rowExtent <= gridRowEnd) {
       break;
     }
-    row = 1;
+    row = 0;
   }
-  MOZ_ASSERT(col < gridColEnd || row == 1,
-             "expected row 1 for placing in a new column");
+  MOZ_ASSERT(col < gridColEnd || row == 0,
+             "expected row 0 for placing in a new column");
   aArea->mCols.ResolveAutoPosition(col);
   aArea->mRows.ResolveAutoPosition(row);
   MOZ_ASSERT(aArea->IsDefinite());
 }
 
 void
 nsGridContainerFrame::InitializeGridBounds(const nsStylePosition* aStyle)
 {
   // http://dev.w3.org/csswg/css-grid/#grid-definition
+  // Note that this is for a grid with a 1,1 origin.  We'll change that
+  // to a 0,0 based grid after placing definite lines.
   uint32_t colEnd = aStyle->mGridTemplateColumns.mLineNameLists.Length();
   uint32_t rowEnd = aStyle->mGridTemplateRows.mLineNameLists.Length();
   auto areas = aStyle->mGridTemplateAreas.get();
   mExplicitGridColEnd = std::max(colEnd, areas ? areas->mNColumns + 1 : 1);
   mExplicitGridRowEnd = std::max(rowEnd, areas ? areas->NRows() + 1 : 1);
   mExplicitGridColEnd =
     std::min(mExplicitGridColEnd, uint32_t(nsStyleGridLine::kMaxLine));
   mExplicitGridRowEnd =
@@ -868,31 +865,31 @@ nsGridContainerFrame::PlaceGridItems(Gri
         prop = new GridArea(area);
         child->Properties().Set(GridAreaProperty(), prop);
       }
       if (adjust) {
         areasToAdjust.AppendElement(prop);
       }
     }
 
-    // Translate the whole grid so that the top-/left-most area is at 1,1.
-    const uint32_t explicitGridOffsetCol = 1 - minCol;
-    const uint32_t explicitGridOffsetRow = 1 - minRow;
-    mGridColEnd += explicitGridOffsetCol;
-    mGridRowEnd += explicitGridOffsetRow;
-    mExplicitGridOffsetCol = explicitGridOffsetCol;
-    mExplicitGridOffsetRow = explicitGridOffsetRow;
+    // Translate the whole grid so that the top-/left-most area is at 0,0.
+    mExplicitGridOffsetCol = 1 - minCol;
+    mExplicitGridOffsetRow = 1 - minRow;
+    const int32_t offsetToColZero = int32_t(mExplicitGridOffsetCol) - 1;
+    const int32_t offsetToRowZero = int32_t(mExplicitGridOffsetRow) - 1;
+    mGridColEnd += offsetToColZero;
+    mGridRowEnd += offsetToRowZero;
     for (GridArea* area : areasToAdjust) {
-      if (explicitGridOffsetCol != 0 && area->mCols.IsDefinite()) {
-        area->mCols.mStart += explicitGridOffsetCol;
-        area->mCols.mEnd += explicitGridOffsetCol;
+      if (area->mCols.IsDefinite()) {
+        area->mCols.mStart += offsetToColZero;
+        area->mCols.mEnd += offsetToColZero;
       }
-      if (explicitGridOffsetRow != 0 && area->mRows.IsDefinite()) {
-        area->mRows.mStart += explicitGridOffsetRow;
-        area->mRows.mEnd += explicitGridOffsetRow;
+      if (area->mRows.IsDefinite()) {
+        area->mRows.mStart += offsetToRowZero;
+        area->mRows.mEnd += offsetToRowZero;
       }
       if (area->IsDefinite()) {
         mCellMap.Fill(*area);
         InflateGridFor(*area);
       }
     }
   }
 
@@ -913,17 +910,17 @@ nsGridContainerFrame::PlaceGridItems(Gri
     aIter.Reset();
     for (; !aIter.AtEnd(); aIter.Next()) {
       nsIFrame* child = *aIter;
       GridArea* area = GetGridAreaForChild(child);
       LineRange& major = isRowOrder ? area->mRows : area->mCols;
       LineRange& minor = isRowOrder ? area->mCols : area->mRows;
       if (major.IsDefinite() && minor.IsAuto()) {
         // Items with 'auto' in the minor dimension only.
-        uint32_t cursor = 1;
+        uint32_t cursor = 0;
         if (isSparse) {
           cursors->Get(major.mStart, &cursor);
         }
         (this->*placeAutoMinorFunc)(cursor, area);
         mCellMap.Fill(*area);
         if (isSparse) {
           cursors->Put(major.mStart, minor.mEnd);
         }
@@ -936,18 +933,18 @@ nsGridContainerFrame::PlaceGridItems(Gri
   // XXX It's unclear if the remaining major-dimension auto and
   // XXX auto in both dimensions should use the same cursor or not,
   // XXX https://www.w3.org/Bugs/Public/show_bug.cgi?id=16044
   // XXX seems to indicate it shouldn't.
   // XXX http://dev.w3.org/csswg/css-grid/#auto-placement-cursor
   // XXX now says it should (but didn't in earlier versions)
 
   // Step 3, place the remaining grid items
-  uint32_t cursorMajor = 1; // for 'dense' these two cursors will stay at 1,1
-  uint32_t cursorMinor = 1;
+  uint32_t cursorMajor = 0; // for 'dense' these two cursors will stay at 0,0
+  uint32_t cursorMinor = 0;
   auto placeAutoMajorFunc = isRowOrder ? &nsGridContainerFrame::PlaceAutoRow
                                        : &nsGridContainerFrame::PlaceAutoCol;
   aIter.Reset();
   for (; !aIter.AtEnd(); aIter.Next()) {
     nsIFrame* child = *aIter;
     GridArea* area = GetGridAreaForChild(child);
     LineRange& major = isRowOrder ? area->mRows : area->mCols;
     LineRange& minor = isRowOrder ? area->mCols : area->mRows;
@@ -991,37 +988,37 @@ nsGridContainerFrame::PlaceGridItems(Gri
   }
 
   if (IsAbsoluteContainer()) {
     // 9.4 Absolutely-positioned Grid Items
     // http://dev.w3.org/csswg/css-grid/#abspos-items
     // We only resolve definite lines here; we'll align auto positions to the
     // grid container later during reflow.
     nsFrameList children(GetChildList(GetAbsoluteListID()));
-    const uint32_t explicitGridOffsetCol = mExplicitGridOffsetCol;
-    const uint32_t explicitGridOffsetRow = mExplicitGridOffsetRow;
+    const int32_t offsetToColZero = int32_t(mExplicitGridOffsetCol) - 1;
+    const int32_t offsetToRowZero = int32_t(mExplicitGridOffsetRow) - 1;
     // Untranslate the grid again temporarily while resolving abs.pos. lines.
     AutoRestore<uint32_t> save1(mGridColEnd);
     AutoRestore<uint32_t> save2(mGridRowEnd);
-    mGridColEnd -= explicitGridOffsetCol;
-    mGridRowEnd -= explicitGridOffsetRow;
+    mGridColEnd -= offsetToColZero;
+    mGridRowEnd -= offsetToRowZero;
     for (nsFrameList::Enumerator e(children); !e.AtEnd(); e.Next()) {
       nsIFrame* child = e.get();
       GridArea area(PlaceAbsPos(child, aStyle));
       if (area.mCols.mStart != kAutoLine) {
-        area.mCols.mStart += explicitGridOffsetCol;
+        area.mCols.mStart += offsetToColZero;
       }
       if (area.mCols.mEnd != kAutoLine) {
-        area.mCols.mEnd += explicitGridOffsetCol;
+        area.mCols.mEnd += offsetToColZero;
       }
       if (area.mRows.mStart != kAutoLine) {
-        area.mRows.mStart += explicitGridOffsetRow;
+        area.mRows.mStart += offsetToRowZero;
       }
       if (area.mRows.mEnd != kAutoLine) {
-        area.mRows.mEnd += explicitGridOffsetRow;
+        area.mRows.mEnd += offsetToRowZero;
       }
       GridArea* prop = GetGridAreaForChild(child);
       if (prop) {
         *prop = area;
       } else {
         child->Properties().Set(GridAreaProperty(), new GridArea(area));
       }
     }
@@ -1092,18 +1089,18 @@ InitializeTrackSizes(nscoord aPercentage
 }
 
 void
 nsGridContainerFrame::CalculateTrackSizes(const LogicalSize& aPercentageBasis,
                                           const nsStylePosition* aStyle,
                                           nsTArray<TrackSize>& aColSizes,
                                           nsTArray<TrackSize>& aRowSizes)
 {
-  aColSizes.SetLength(mGridColEnd - 1);
-  aRowSizes.SetLength(mGridRowEnd - 1);
+  aColSizes.SetLength(mGridColEnd);
+  aRowSizes.SetLength(mGridRowEnd);
   WritingMode wm = GetWritingMode();
   InitializeTrackSizes(aPercentageBasis.ISize(wm),
                        aStyle->mGridTemplateColumns.mMinTrackSizingFunctions,
                        aStyle->mGridTemplateColumns.mMaxTrackSizingFunctions,
                        aStyle->mGridAutoColumnsMin,
                        aStyle->mGridAutoColumnsMax,
                        mExplicitGridOffsetCol,
                        aColSizes);
@@ -1118,25 +1115,25 @@ nsGridContainerFrame::CalculateTrackSize
 
 void
 nsGridContainerFrame::LineRange::ToPositionAndLength(
   const nsTArray<TrackSize>& aTrackSizes, nscoord* aPos, nscoord* aLength) const
 {
   MOZ_ASSERT(mStart != kAutoLine && mEnd != kAutoLine,
              "expected a definite LineRange");
   nscoord pos = 0;
-  const uint32_t start = mStart - 1;
+  const uint32_t start = mStart;
   uint32_t i = 0;
   for (; i < start; ++i) {
     pos += aTrackSizes[i].mBase;
   }
   *aPos = pos;
 
   nscoord length = 0;
-  const uint32_t end = mEnd - 1;
+  const uint32_t end = mEnd;
   MOZ_ASSERT(end <= aTrackSizes.Length(), "aTrackSizes isn't large enough");
   for (; i < end; ++i) {
     length += aTrackSizes[i].mBase;
   }
   *aLength = length;
 }
 
 void
@@ -1316,17 +1313,17 @@ nsGridContainerFrame::Reflow(nsPresConte
   const nscoord computedBSize = aReflowState.ComputedBSize();
   const nscoord computedISize = aReflowState.ComputedISize();
   LogicalSize percentageBasis(wm, computedISize,
       computedBSize == NS_AUTOHEIGHT ? 0 : computedBSize);
   CalculateTrackSizes(percentageBasis, stylePos, colSizes, rowSizes);
 
   nscoord bSize = 0;
   if (computedBSize == NS_AUTOHEIGHT) {
-    for (uint32_t i = 0; i < mGridRowEnd - 1; ++i) {
+    for (uint32_t i = 0; i < mGridRowEnd; ++i) {
       bSize += rowSizes[i].mBase;
     }
   } else {
     bSize = computedBSize;
   }
   bSize = std::max(bSize - GetConsumedBSize(), 0);
   LogicalSize desiredSize(wm, computedISize + bp.IStartEnd(wm),
                           bSize + bp.BStartEnd(wm));
@@ -1390,27 +1387,26 @@ nsGridContainerFrame::GetFrameName(nsASt
 }
 #endif
 
 void
 nsGridContainerFrame::CellMap::Fill(const GridArea& aGridArea)
 {
   MOZ_ASSERT(aGridArea.IsDefinite());
   MOZ_ASSERT(aGridArea.mRows.mStart < aGridArea.mRows.mEnd);
-  MOZ_ASSERT(aGridArea.mRows.mStart > 0);
+  MOZ_ASSERT(aGridArea.mRows.mStart >= 0);
   MOZ_ASSERT(aGridArea.mCols.mStart < aGridArea.mCols.mEnd);
-  MOZ_ASSERT(aGridArea.mCols.mStart > 0);
-  // Line numbers are 1-based so convert them to a zero-based index.
-  const auto numRows = aGridArea.mRows.mEnd - 1;
-  const auto numCols = aGridArea.mCols.mEnd - 1;
+  MOZ_ASSERT(aGridArea.mCols.mStart >= 0);
+  const auto numRows = aGridArea.mRows.mEnd;
+  const auto numCols = aGridArea.mCols.mEnd;
   mCells.EnsureLengthAtLeast(numRows);
-  for (auto i = aGridArea.mRows.mStart - 1; i < numRows; ++i) {
+  for (auto i = aGridArea.mRows.mStart; i < numRows; ++i) {
     nsTArray<Cell>& cellsInRow = mCells[i];
     cellsInRow.EnsureLengthAtLeast(numCols);
-    for (auto j = aGridArea.mCols.mStart - 1; j < numCols; ++j) {
+    for (auto j = aGridArea.mCols.mStart; j < numCols; ++j) {
       cellsInRow[j].mIsOccupied = true;
     }
   }
 }
 
 void
 nsGridContainerFrame::CellMap::ClearOccupied()
 {
--- a/layout/generic/nsGridContainerFrame.h
+++ b/layout/generic/nsGridContainerFrame.h
@@ -117,25 +117,25 @@ protected:
     }
     /**
      * Resolve this auto range to start at aStart, making it definite.
      * Precondition: this range IsAuto()
      */
     void ResolveAutoPosition(int32_t aStart)
     {
       MOZ_ASSERT(IsAuto(), "Why call me?");
-      MOZ_ASSERT(aStart > 0, "expected a 1-based line number");
+      MOZ_ASSERT(aStart >= 0, "expected a zero-based line number");
       mStart = aStart;
       mEnd += aStart;
     }
     /**
      * Return the contribution of this line range for step 2 in
      * http://dev.w3.org/csswg/css-grid/#auto-placement-algo
      */
-    uint32_t HypotheticalEnd() const { return IsAuto() ? mEnd + 1 : mEnd; }
+    uint32_t HypotheticalEnd() const { return mEnd; }
     /**
      * Given an array of track sizes, return the starting position and length
      * of the tracks in this line range.
      */
     void ToPositionAndLength(const nsTArray<TrackSize>& aTrackSizes,
                              nscoord* aPos, nscoord* aLength) const;
     /**
      * Given an array of track sizes and a grid origin coordinate, adjust the
@@ -351,19 +351,19 @@ protected:
    * Inflate the implicit grid to include aArea.
    * @param aArea may be definite or auto
    */
   void InflateGridFor(const GridArea& aArea)
   {
     mGridColEnd = std::max(mGridColEnd, aArea.mCols.HypotheticalEnd());
     mGridRowEnd = std::max(mGridRowEnd, aArea.mRows.HypotheticalEnd());
     MOZ_ASSERT(mGridColEnd <= uint32_t(nsStyleGridLine::kMaxLine -
-                                       nsStyleGridLine::kMinLine) &&
+                                       nsStyleGridLine::kMinLine - 1) &&
                mGridRowEnd <= uint32_t(nsStyleGridLine::kMaxLine -
-                                       nsStyleGridLine::kMinLine));
+                                       nsStyleGridLine::kMinLine - 1));
   }
 
   /**
    * Calculate track sizes.
    */
   void CalculateTrackSizes(const mozilla::LogicalSize& aPercentageBasis,
                            const nsStylePosition*      aStyle,
                            nsTArray<TrackSize>&        aColSizes,
@@ -463,25 +463,27 @@ private:
    * (i.e. the number of explicit columns + 1)
    */
   uint32_t mExplicitGridColEnd;
   /**
    * The last row grid line (1-based) in the explicit grid.
    * (i.e. the number of explicit rows + 1)
    */
   uint32_t mExplicitGridRowEnd;
-  // Same for the implicit grid
-  uint32_t mGridColEnd; // always >= mExplicitGridColEnd
-  uint32_t mGridRowEnd; // always >= mExplicitGridRowEnd
+  // Same for the implicit grid, except these become zero-based after
+  // resolving definite lines.
+  uint32_t mGridColEnd;
+  uint32_t mGridRowEnd;
 
   /**
    * Offsets from the start of the implicit grid to the start of the translated
    * explicit grid.  They are zero if there are no implicit lines before 1,1.
    * e.g. "grid-column: span 3 / 1" makes mExplicitGridOffsetCol = 3 and the
-   * corresponding GridArea::mCols will be 1 / 4 in the translated grid.
+   * corresponding GridArea::mCols will be 0 / 3 in the zero-based translated
+   * grid.
    */
   uint32_t mExplicitGridOffsetCol;
   uint32_t mExplicitGridOffsetRow;
 
   /**
    * True iff the normal flow children are already in CSS 'order' in the
    * order they occur in the child frame list.
    */