Bug 1030952 part 1: Save each flex item's intrinsic ratio during reflow, for easy reuse. r=mats a=lizzard
authorDaniel Holbert <dholbert@cs.stanford.edu>
Thu, 28 Apr 2016 20:16:58 -0700
changeset 332674 39e8e0eebc51d0fefbe103958912851fc41313b6
parent 332673 2312ffc9586602df777c20b1ed1ede61e65c4100
child 332675 76e3ffd2a6d6cfabe73e8d02462e4052611257ba
push id6048
push userkmoir@mozilla.com
push dateMon, 06 Jun 2016 19:02:08 +0000
treeherdermozilla-beta@46d72a56c57d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmats, lizzard
bugs1030952
milestone48.0a2
Bug 1030952 part 1: Save each flex item's intrinsic ratio during reflow, for easy reuse. r=mats a=lizzard MozReview-Commit-ID: 84dtBQUJZP7
layout/generic/nsFlexContainerFrame.cpp
--- a/layout/generic/nsFlexContainerFrame.cpp
+++ b/layout/generic/nsFlexContainerFrame.cpp
@@ -549,16 +549,19 @@ public:
       // regardless of mFlexShrink, we should just return 0.
       // (This is really a special-case for when mFlexShrink is infinity, to
       // avoid performing mFlexShrink * mFlexBaseSize = inf * 0 = undefined.)
       return 0.0f;
     }
     return mFlexShrink * mFlexBaseSize;
   }
 
+  const nsSize& IntrinsicRatio() const { return mIntrinsicRatio; }
+  bool HasIntrinsicRatio() const { return mIntrinsicRatio != nsSize(); }
+
   // Getters for margin:
   // ===================
   const nsMargin& GetMargin() const { return mMargin; }
 
   // Returns the margin component for a given mozilla::Side
   nscoord GetMarginComponentForSide(mozilla::Side aSide) const
   { return mMargin.Side(aSide); }
 
@@ -745,16 +748,18 @@ protected:
 
   // Our frame:
   nsIFrame* const mFrame;
 
   // Values that we already know in constructor: (and are hence mostly 'const')
   const float mFlexGrow;
   const float mFlexShrink;
 
+  const nsSize mIntrinsicRatio;
+
   const nsMargin mBorderPadding;
   nsMargin mMargin; // non-const because we need to resolve auto margins
 
   // These are non-const so that we can lazily update them with the item's
   // intrinsic size (obtained via a "measuring" reflow), when necessary.
   // (e.g. for "flex-basis:auto;height:auto" & "min-height:auto")
   nscoord mFlexBaseSize;
   nscoord mMainMinSize;
@@ -1388,17 +1393,16 @@ MainSizeFromAspectRatio(nscoord aCrossSi
 // consider flex-basis, main max-size, and the intrinsic aspect ratio).
 // The caller is responsible for computing & considering the min-content size
 // in combination with the partially-resolved value that this function returns.
 //
 // Spec reference: http://dev.w3.org/csswg/css-flexbox/#min-size-auto
 static nscoord
 PartiallyResolveAutoMinSize(const FlexItem& aFlexItem,
                             const nsHTMLReflowState& aItemReflowState,
-                            const nsSize& aIntrinsicRatio,
                             const FlexboxAxisTracker& aAxisTracker)
 {
   MOZ_ASSERT(aFlexItem.NeedsMinSizeAutoResolution(),
              "only call for FlexItems that need min-size auto resolution");
 
   nscoord minMainSize = nscoord_MAX; // Intentionally huge; we'll shrink it
                                      // from here, w/ std::min().
 
@@ -1425,62 +1429,61 @@ PartiallyResolveAutoMinSize(const FlexIt
   }
 
   // * if the item has no intrinsic aspect ratio, its min-content size:
   //  --- SKIPPING THIS IN THIS FUNCTION --- caller's responsibility.
 
   // * if the item has an intrinsic aspect ratio, the width (height) calculated
   //   from the aspect ratio and any definite size constraints in the opposite
   //   dimension.
-  if (aAxisTracker.GetCrossComponent(aIntrinsicRatio) != 0) {
+  if (aAxisTracker.GetCrossComponent(aFlexItem.IntrinsicRatio()) != 0) {
     // We have a usable aspect ratio. (not going to divide by 0)
     const bool useMinSizeIfCrossSizeIsIndefinite = true;
     nscoord crossSizeToUseWithRatio =
       CrossSizeToUseWithRatio(aFlexItem, aItemReflowState,
                               useMinSizeIfCrossSizeIsIndefinite,
                               aAxisTracker);
     nscoord minMainSizeFromRatio =
       MainSizeFromAspectRatio(crossSizeToUseWithRatio,
-                              aIntrinsicRatio, aAxisTracker);
+                              aFlexItem.IntrinsicRatio(), aAxisTracker);
     minMainSize = std::min(minMainSize, minMainSizeFromRatio);
   }
 
   return minMainSize;
 }
 
 // Resolves flex-basis:auto, using the given intrinsic ratio and the flex
 // item's cross size.  On success, updates the flex item with its resolved
 // flex-basis and returns true. On failure (e.g. if the ratio is invalid or
 // the cross-size is indefinite), returns false.
 static bool
 ResolveAutoFlexBasisFromRatio(FlexItem& aFlexItem,
                               const nsHTMLReflowState& aItemReflowState,
-                              const nsSize& aIntrinsicRatio,
                               const FlexboxAxisTracker& aAxisTracker)
 {
   MOZ_ASSERT(NS_AUTOHEIGHT == aFlexItem.GetFlexBaseSize(),
              "Should only be called to resolve an 'auto' flex-basis");
   // If the flex item has ...
   //  - an intrinsic aspect ratio,
   //  - a [used] flex-basis of 'main-size' [auto?] [We have this, if we're here.]
   //  - a definite cross size
   // then the flex base size is calculated from its inner cross size and the
   // flex item’s intrinsic aspect ratio.
-  if (aAxisTracker.GetCrossComponent(aIntrinsicRatio) != 0) {
+  if (aAxisTracker.GetCrossComponent(aFlexItem.IntrinsicRatio()) != 0) {
     // We have a usable aspect ratio. (not going to divide by 0)
     const bool useMinSizeIfCrossSizeIsIndefinite = false;
     nscoord crossSizeToUseWithRatio =
       CrossSizeToUseWithRatio(aFlexItem, aItemReflowState,
                               useMinSizeIfCrossSizeIsIndefinite,
                               aAxisTracker);
     if (crossSizeToUseWithRatio != NS_AUTOHEIGHT) {
       // We have a definite cross-size
       nscoord mainSizeFromRatio =
         MainSizeFromAspectRatio(crossSizeToUseWithRatio,
-                                aIntrinsicRatio, aAxisTracker);
+                                aFlexItem.IntrinsicRatio(), aAxisTracker);
       aFlexItem.SetFlexBaseSizeAndMainSize(mainSizeFromRatio);
       return true;
     }
   }
   return false;
 }
 
 // Note: If & when we handle "min-height: min-content" for flex items,
@@ -1528,42 +1531,38 @@ nsFlexContainerFrame::
     // (Container's cross size is definite if cross-axis is horizontal, or if
     // cross-axis is vertical and the cross-size is not NS_AUTOHEIGHT.)
     if (aAxisTracker.IsCrossAxisHorizontal() ||
         containerCrossSize != NS_AUTOHEIGHT) {
       aFlexItem.ResolveStretchedCrossSize(containerCrossSize, aAxisTracker);
     }
   }
 
-  // We'll need the intrinsic ratio (if there is one), regardless of whether
-  // we're resolving min-[width|height]:auto or flex-basis:auto.
-  const nsSize ratio = aFlexItem.Frame()->GetIntrinsicRatio();
-
   nscoord resolvedMinSize; // (only set/used if isMainMinSizeAuto==true)
   bool minSizeNeedsToMeasureContent = false; // assume the best
   if (isMainMinSizeAuto) {
     // Resolve the min-size, except for considering the min-content size.
     // (We'll consider that later, if we need to.)
     resolvedMinSize = PartiallyResolveAutoMinSize(aFlexItem, aItemReflowState,
-                                                  ratio, aAxisTracker);
+                                                  aAxisTracker);
     if (resolvedMinSize > 0 &&
-        aAxisTracker.GetCrossComponent(ratio) == 0) {
+        aAxisTracker.GetCrossComponent(aFlexItem.IntrinsicRatio()) == 0) {
       // We don't have a usable aspect ratio, so we need to consider our
       // min-content size as another candidate min-size, which we'll have to
       // min() with the current resolvedMinSize.
       // (If resolvedMinSize were already at 0, we could skip this measurement
       // because it can't go any lower. But it's not 0, so we need it.)
       minSizeNeedsToMeasureContent = true;
     }
   }
 
   bool flexBasisNeedsToMeasureContent = false; // assume the best
   if (isMainSizeAuto) {
     if (!ResolveAutoFlexBasisFromRatio(aFlexItem, aItemReflowState,
-                                       ratio, aAxisTracker)) {
+                                       aAxisTracker)) {
       flexBasisNeedsToMeasureContent = true;
     }
   }
 
   // Measure content, if needed (w/ intrinsic-width method or a reflow)
   if (minSizeNeedsToMeasureContent || flexBasisNeedsToMeasureContent) {
     if (aAxisTracker.IsMainAxisHorizontal()) {
       if (minSizeNeedsToMeasureContent) {
@@ -1673,16 +1672,17 @@ FlexItem::FlexItem(nsHTMLReflowState& aF
                    float aFlexGrow, float aFlexShrink, nscoord aFlexBaseSize,
                    nscoord aMainMinSize,  nscoord aMainMaxSize,
                    nscoord aTentativeCrossSize,
                    nscoord aCrossMinSize, nscoord aCrossMaxSize,
                    const FlexboxAxisTracker& aAxisTracker)
   : mFrame(aFlexItemReflowState.frame),
     mFlexGrow(aFlexGrow),
     mFlexShrink(aFlexShrink),
+    mIntrinsicRatio(mFrame->GetIntrinsicRatio()),
     mBorderPadding(aFlexItemReflowState.ComputedPhysicalBorderPadding()),
     mMargin(aFlexItemReflowState.ComputedPhysicalMargin()),
     mMainMinSize(aMainMinSize),
     mMainMaxSize(aMainMaxSize),
     mCrossMinSize(aCrossMinSize),
     mCrossMaxSize(aCrossMaxSize),
     mMainPosn(0),
     mCrossSize(aTentativeCrossSize),
@@ -1765,16 +1765,17 @@ FlexItem::FlexItem(nsHTMLReflowState& aF
 // Simplified constructor for creating a special "strut" FlexItem, for a child
 // with visibility:collapse. The strut has 0 main-size, and it only exists to
 // impose a minimum cross size on whichever FlexLine it ends up in.
 FlexItem::FlexItem(nsIFrame* aChildFrame, nscoord aCrossSize,
                    WritingMode aContainerWM)
   : mFrame(aChildFrame),
     mFlexGrow(0.0f),
     mFlexShrink(0.0f),
+    mIntrinsicRatio(),
     // mBorderPadding uses default constructor,
     // mMargin uses default constructor,
     mFlexBaseSize(0),
     mMainMinSize(0),
     mMainMaxSize(0),
     mCrossMinSize(0),
     mCrossMaxSize(0),
     mMainSize(0),