Bug 1146051 part 4 - [css-grid] Translate the grid so that the top-/left-most implicit line becomes 1,1. r=dholbert
authorMats Palmgren <mats@mozilla.com>
Thu, 30 Apr 2015 18:42:50 +0000
changeset 273268 e2be01a8ae2cf9f5fb2e88540f5dee41ddf6aafe
parent 273267 32b9547b85212d1f94912b9c129e4c32696388c9
child 273269 a5d65e0edabcc307b854d53db8ade0f5e68dc02a
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 4 - [css-grid] Translate the grid so that the top-/left-most implicit line becomes 1,1. r=dholbert
layout/generic/nsGridContainerFrame.cpp
layout/generic/nsGridContainerFrame.h
--- a/layout/generic/nsGridContainerFrame.cpp
+++ b/layout/generic/nsGridContainerFrame.cpp
@@ -809,28 +809,64 @@ void
 nsGridContainerFrame::PlaceGridItems(GridItemCSSOrderIterator& aIter,
                                      const nsStylePosition*    aStyle)
 {
   mCellMap.ClearOccupied();
   InitializeGridBounds(aStyle);
 
   // http://dev.w3.org/csswg/css-grid/#line-placement
   // Resolve definite positions per spec chap 9.2.
-  for (; !aIter.AtEnd(); aIter.Next()) {
-    nsIFrame* child = *aIter;
-    const GridArea& area = PlaceDefinite(child, aStyle);
-    GridArea* prop = GetGridAreaForChild(child);
-    if (prop) {
-      *prop = area;
-    } else {
-      child->Properties().Set(GridAreaProperty(), new GridArea(area));
+  {
+    nsAutoTArray<GridArea*, 100> areasToAdjust;
+    int32_t minCol = 1;
+    int32_t minRow = 1;
+    for (; !aIter.AtEnd(); aIter.Next()) {
+      nsIFrame* child = *aIter;
+      const GridArea& area = PlaceDefinite(child, aStyle);
+      bool adjust = false;
+      if (area.mCols.IsDefinite()) {
+        minCol = std::min(minCol, area.mCols.mStart);
+        adjust = true;
+      }
+      if (area.mRows.IsDefinite()) {
+        minRow = std::min(minRow, area.mRows.mStart);
+        adjust = true;
+      }
+      GridArea* prop = GetGridAreaForChild(child);
+      if (prop) {
+        *prop = area;
+      } else {
+        prop = new GridArea(area);
+        child->Properties().Set(GridAreaProperty(), prop);
+      }
+      if (adjust) {
+        areasToAdjust.AppendElement(prop);
+      }
     }
-    if (area.IsDefinite()) {
-      mCellMap.Fill(area);
-      InflateGridFor(area);
+
+    // 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;
+    for (GridArea* area : areasToAdjust) {
+      if (explicitGridOffsetCol != 0 && area->mCols.IsDefinite()) {
+        area->mCols.mStart += explicitGridOffsetCol;
+        area->mCols.mEnd += explicitGridOffsetCol;
+      }
+      if (explicitGridOffsetRow != 0 && area->mRows.IsDefinite()) {
+        area->mRows.mStart += explicitGridOffsetRow;
+        area->mRows.mEnd += explicitGridOffsetRow;
+      }
+      if (area->IsDefinite()) {
+        mCellMap.Fill(*area);
+        InflateGridFor(*area);
+      }
     }
   }
 
   // http://dev.w3.org/csswg/css-grid/#auto-placement-algo
   // Step 1, place 'auto' items that have one definite position -
   // definite row (column) for grid-auto-flow:row (column).
   auto flowStyle = aStyle->mGridAutoFlow;
   const bool isRowOrder = (flowStyle & NS_STYLE_GRID_AUTO_FLOW_ROW);
@@ -924,19 +960,38 @@ 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;
+    // Untranslate the grid again temporarily while resolving abs.pos. lines.
+    AutoRestore<uint32_t> save1(mGridColEnd);
+    AutoRestore<uint32_t> save2(mGridRowEnd);
+    mGridColEnd -= explicitGridOffsetCol;
+    mGridRowEnd -= explicitGridOffsetRow;
     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;
+      }
+      if (area.mCols.mEnd != kAutoLine) {
+        area.mCols.mEnd += explicitGridOffsetCol;
+      }
+      if (area.mRows.mStart != kAutoLine) {
+        area.mRows.mStart += explicitGridOffsetRow;
+      }
+      if (area.mRows.mEnd != kAutoLine) {
+        area.mRows.mEnd += explicitGridOffsetRow;
+      }
       GridArea* prop = GetGridAreaForChild(child);
       if (prop) {
         *prop = area;
       } else {
         child->Properties().Set(GridAreaProperty(), new GridArea(area));
       }
     }
   }
@@ -975,27 +1030,34 @@ InitializeTrackSize(nscoord aPercentageB
 }
 
 static void
 InitializeTrackSizes(nscoord aPercentageBasis,
                      const nsTArray<nsStyleCoord>& aMinSizingFunctions,
                      const nsTArray<nsStyleCoord>& aMaxSizingFunctions,
                      const nsStyleCoord& aAutoMinFunction,
                      const nsStyleCoord& aAutoMaxFunction,
+                     uint32_t aExplicitGridOffset,
                      nsTArray<TrackSize>& aResults)
 {
-  MOZ_ASSERT(aResults.Length() >= aMinSizingFunctions.Length());
+  MOZ_ASSERT(aResults.Length() >= aExplicitGridOffset + aMinSizingFunctions.Length());
   MOZ_ASSERT(aMinSizingFunctions.Length() == aMaxSizingFunctions.Length());
-  const size_t len = aMinSizingFunctions.Length();
   size_t i = 0;
-  for (; i < len; ++i) {
+  for (; i < aExplicitGridOffset; ++i) {
     InitializeTrackSize(aPercentageBasis,
-                        aMinSizingFunctions[i], aMaxSizingFunctions[i],
+                        aAutoMinFunction, aAutoMaxFunction,
                         &aResults[i]);
   }
+  size_t j = 0;
+  for (const size_t len = aMinSizingFunctions.Length(); j < len; ++j) {
+    InitializeTrackSize(aPercentageBasis,
+                        aMinSizingFunctions[j], aMaxSizingFunctions[j],
+                        &aResults[i + j]);
+  }
+  i += j;
   for (; i < aResults.Length(); ++i) {
     InitializeTrackSize(aPercentageBasis,
                         aAutoMinFunction, aAutoMaxFunction,
                         &aResults[i]);
   }
 }
 
 void
@@ -1007,22 +1069,24 @@ nsGridContainerFrame::CalculateTrackSize
   aColSizes.SetLength(mGridColEnd - 1);
   aRowSizes.SetLength(mGridRowEnd - 1);
   WritingMode wm = GetWritingMode();
   InitializeTrackSizes(aPercentageBasis.ISize(wm),
                        aStyle->mGridTemplateColumns.mMinTrackSizingFunctions,
                        aStyle->mGridTemplateColumns.mMaxTrackSizingFunctions,
                        aStyle->mGridAutoColumnsMin,
                        aStyle->mGridAutoColumnsMax,
+                       mExplicitGridOffsetCol,
                        aColSizes);
   InitializeTrackSizes(aPercentageBasis.BSize(wm),
                        aStyle->mGridTemplateRows.mMinTrackSizingFunctions,
                        aStyle->mGridTemplateRows.mMaxTrackSizingFunctions,
                        aStyle->mGridAutoRowsMin,
                        aStyle->mGridAutoRowsMax,
+                       mExplicitGridOffsetRow,
                        aRowSizes);
 }
 
 void
 nsGridContainerFrame::LineRange::ToPositionAndLength(
   const nsTArray<TrackSize>& aTrackSizes, nscoord* aPos, nscoord* aLength) const
 {
   MOZ_ASSERT(mStart != kAutoLine && mEnd != kAutoLine,
--- a/layout/generic/nsGridContainerFrame.h
+++ b/layout/generic/nsGridContainerFrame.h
@@ -348,16 +348,20 @@ 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) &&
+               mGridRowEnd <= uint32_t(nsStyleGridLine::kMaxLine -
+                                       nsStyleGridLine::kMinLine));
   }
 
   /**
    * Calculate track sizes.
    */
   void CalculateTrackSizes(const mozilla::LogicalSize& aPercentageBasis,
                            const nsStylePosition*      aStyle,
                            nsTArray<TrackSize>&        aColSizes,
@@ -460,16 +464,26 @@ private:
   /**
    * 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
+
+  /**
+   * 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.
+   */
+  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.
    */
   bool mIsNormalFlowInCSSOrder : 1;
 };
 
 #endif /* nsGridContainerFrame_h___ */