Bug 1174574 part 2 - [css-grid] Implement intrinsic sizing for grid containers (aka GetMinISize/GetPrefISize). r=dholbert
authorMats Palmgren <mats@mozilla.com>
Fri, 04 Sep 2015 22:06:58 +0200
changeset 261123 bacad119cc26f53894d092bdd32f95a88ab70308
parent 261122 cf5ad7ef6a431e1dac70e0e3b0fb302708e69b3b
child 261124 56e29e6d877eab5f887cc93bfeff34a9a63144e9
push id29336
push usercbook@mozilla.com
push dateMon, 07 Sep 2015 10:01:38 +0000
treeherdermozilla-central@5fe9ed3edd68 [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 <>