Bug 1174574 part 2 - [css-grid] Implement intrinsic sizing for grid containers (aka GetMinISize/GetPrefISize). r=dholbert
☠☠ backed out by 2b4eff0977f2 ☠ ☠
authorMats Palmgren <mats@mozilla.com>
Fri, 04 Sep 2015 22:06:58 +0200
changeset 293632 fd3a53075e540d98ff49d092697503fc3445f4ff
parent 293631 16cf05b1664c04e73ae9a4a4fb297cf1311136c3
child 293633 332af3c9e3667ee4c106fc5e647f6b13d7bb2041
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
bugs1174574
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 1174574 part 2 - [css-grid] Implement intrinsic sizing for grid containers (aka GetMinISize/GetPrefISize). r=dholbert
layout/generic/nsGridContainerFrame.cpp
layout/generic/nsGridContainerFrame.h
--- a/layout/generic/nsGridContainerFrame.cpp
+++ b/layout/generic/nsGridContainerFrame.cpp
@@ -2277,16 +2277,31 @@ nsGridContainerFrame::LineRange::ToPosit
   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;
 }
 
+nscoord
+nsGridContainerFrame::LineRange::ToLength(
+  const nsTArray<TrackSize>& aTrackSizes) const
+{
+  MOZ_ASSERT(mStart != kAutoLine && mEnd != kAutoLine,
+             "expected a definite LineRange");
+  nscoord length = 0;
+  const uint32_t end = mEnd;
+  MOZ_ASSERT(end <= aTrackSizes.Length(), "aTrackSizes isn't large enough");
+  for (uint32_t i = mStart; i < end; ++i) {
+    length += aTrackSizes[i].mBase;
+  }
+  return length;
+}
+
 void
 nsGridContainerFrame::LineRange::ToPositionAndLengthForAbsPos(
   const nsTArray<TrackSize>& aTrackSizes, nscoord aGridOrigin,
   nscoord* aPos, nscoord* aLength) const
 {
   // kAutoLine for abspos children contributes the corresponding edge
   // of the grid container's padding-box.
   if (mEnd == kAutoLine) {
@@ -2497,16 +2512,66 @@ nsGridContainerFrame::Reflow(nsPresConte
   gridReflowState.mIter.Reset(GridItemCSSOrderIterator::eIncludeAll);
   ReflowChildren(gridReflowState, contentArea, aDesiredSize, aStatus);
 
   FinishAndStoreOverflow(&aDesiredSize);
   aStatus = NS_FRAME_COMPLETE;
   NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize);
 }
 
+nscoord
+nsGridContainerFrame::IntrinsicISize(nsRenderingContext* aRenderingContext,
+                                     IntrinsicISizeType  aConstraint)
+{
+  // Calculate the sum of column sizes under aConstraint.
+  // http://dev.w3.org/csswg/css-grid/#intrinsic-sizes
+  GridReflowState state(this, *aRenderingContext);
+  InitImplicitNamedAreas(state.mGridStyle); // XXX optimize
+  PlaceGridItems(state);                    // XXX optimize
+  if (mGridColEnd == 0) {
+    return 0;
+  }
+  state.mCols.Initialize(state.mColFunctions, mGridColEnd,
+                         NS_UNCONSTRAINEDSIZE);
+  state.mIter.Reset();
+  state.mCols.CalculateSizes(state, mGridItems, state.mColFunctions,
+                             NS_UNCONSTRAINEDSIZE, &GridArea::mCols,
+                             aConstraint);
+  TranslatedLineRange allTracks(0, mGridColEnd);
+  return allTracks.ToLength(state.mCols.mSizes);
+}
+
+nscoord
+nsGridContainerFrame::GetMinISize(nsRenderingContext* aRC)
+{
+  DISPLAY_MIN_WIDTH(this, mCachedMinISize);
+  if (mCachedMinISize == NS_INTRINSIC_WIDTH_UNKNOWN) {
+    mCachedMinISize = IntrinsicISize(aRC, nsLayoutUtils::MIN_ISIZE);
+  }
+  return mCachedMinISize;
+}
+
+nscoord
+nsGridContainerFrame::GetPrefISize(nsRenderingContext* aRC)
+{
+  DISPLAY_PREF_WIDTH(this, mCachedPrefISize);
+  if (mCachedPrefISize == NS_INTRINSIC_WIDTH_UNKNOWN) {
+    mCachedPrefISize = IntrinsicISize(aRC, nsLayoutUtils::PREF_ISIZE);
+  }
+  return mCachedPrefISize;
+}
+
+void
+nsGridContainerFrame::MarkIntrinsicISizesDirty()
+{
+  mCachedMinISize = NS_INTRINSIC_WIDTH_UNKNOWN;
+  mCachedPrefISize = NS_INTRINSIC_WIDTH_UNKNOWN;
+  nsContainerFrame::MarkIntrinsicISizesDirty();
+}
+
 nsIAtom*
 nsGridContainerFrame::GetType() const
 {
   return nsGkAtoms::gridContainerFrame;
 }
 
 void
 nsGridContainerFrame::BuildDisplayList(nsDisplayListBuilder*   aBuilder,
--- a/layout/generic/nsGridContainerFrame.h
+++ b/layout/generic/nsGridContainerFrame.h
@@ -28,16 +28,19 @@ public:
   NS_DECL_QUERYFRAME_TARGET(nsGridContainerFrame)
   NS_DECL_QUERYFRAME
 
   // nsIFrame overrides
   void Reflow(nsPresContext*           aPresContext,
               nsHTMLReflowMetrics&     aDesiredSize,
               const nsHTMLReflowState& aReflowState,
               nsReflowStatus&          aStatus) override;
+  nscoord GetMinISize(nsRenderingContext* aRenderingContext) override;
+  nscoord GetPrefISize(nsRenderingContext* aRenderingContext) override;
+  void MarkIntrinsicISizesDirty() override;
   virtual nsIAtom* GetType() const override;
 
   void BuildDisplayList(nsDisplayListBuilder*   aBuilder,
                         const nsRect&           aDirtyRect,
                         const nsDisplayListSet& aLists) override;
 
 #ifdef DEBUG_FRAME_DUMP
   virtual nsresult GetFrameName(nsAString& aResult) const override;
@@ -102,17 +105,21 @@ protected:
   typedef mozilla::css::GridNamedArea GridNamedArea;
   typedef nsLayoutUtils::IntrinsicISizeType IntrinsicISizeType;
   class GridItemCSSOrderIterator;
   struct TrackSizingFunctions;
   struct Tracks;
   struct GridReflowState;
   friend nsContainerFrame* NS_NewGridContainerFrame(nsIPresShell* aPresShell,
                                                     nsStyleContext* aContext);
-  explicit nsGridContainerFrame(nsStyleContext* aContext) : nsContainerFrame(aContext) {}
+  explicit nsGridContainerFrame(nsStyleContext* aContext)
+    : nsContainerFrame(aContext)
+    , mCachedMinISize(NS_INTRINSIC_WIDTH_UNKNOWN)
+    , mCachedPrefISize(NS_INTRINSIC_WIDTH_UNKNOWN)
+  {}
 
   /**
    * A LineRange can be definite or auto - when it's definite it represents
    * a consecutive set of tracks between a starting line and an ending line.
    * Before it's definite it can also represent an auto position with a span,
    * where mStart == kAutoLine and mEnd is the (non-zero positive) span.
    * For normal-flow items, the invariant mStart < mEnd holds when both
    * lines are definite.
@@ -178,16 +185,21 @@ protected:
     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, return the length of the tracks in this
+     * line range.
+     */
+    nscoord ToLength(const nsTArray<TrackSize>& aTrackSizes) const;
+    /**
      * Given an array of track sizes and a grid origin coordinate, adjust the
      * abs.pos. containing block along an axis given by aPos and aLength.
      * aPos and aLength should already be initialized to the grid container
      * containing block for this axis before calling this method.
      */
     void ToPositionAndLengthForAbsPos(const nsTArray<TrackSize>& aTrackSizes,
                                       nscoord aGridOrigin,
                                       nscoord* aPos, nscoord* aLength) const;
@@ -518,16 +530,22 @@ protected:
   /**
    * Reflow and place our children.
    */
   void ReflowChildren(GridReflowState&     aState,
                       const LogicalRect&   aContentArea,
                       nsHTMLReflowMetrics& aDesiredSize,
                       nsReflowStatus&      aStatus);
 
+  /**
+   * Helper for GetMinISize / GetPrefISize.
+   */
+  nscoord IntrinsicISize(nsRenderingContext* aRenderingContext,
+                         IntrinsicISizeType  aConstraint);
+
 #ifdef DEBUG
   void SanityCheckAnonymousGridItems() const;
 #endif // DEBUG
 
 private:
   /**
    * Info about each (normal flow) grid item.
    */
@@ -564,16 +582,22 @@ private:
    * e.g. "grid-column: span 3 / 1" makes mExplicitGridOffsetCol = 3 and the
    * corresponding GridArea::mCols will be 0 / 3 in the zero-based translated
    * grid.
    */
   uint32_t mExplicitGridOffsetCol;
   uint32_t mExplicitGridOffsetRow;
 
   /**
+   * Cached values to optimize GetMinISize/GetPrefISize.
+   */
+  nscoord mCachedMinISize;
+  nscoord mCachedPrefISize;
+
+  /**
    * True iff the normal flow children are already in CSS 'order' in the
    * order they occur in the child frame list.
    */
   bool mIsNormalFlowInCSSOrder : 1;
 };
 
 namespace mozilla {
 template <>