Bug 1498273 Part 3: Define and set ComputedFlexItemInfo::mClampState. r=dholbert
authorBrad Werth <bwerth@mozilla.com>
Wed, 24 Oct 2018 23:47:23 +0000
changeset 491246 a40344d98665905cd05f742e38cbe93f3bc7b5d4
parent 491245 28d81e5c33d8e04494ad4455a8d7cf5a0813083f
child 491247 1c2698dc96cb707f7979e5eadef311fc0f4c8c35
push id247
push userfmarier@mozilla.com
push dateSat, 27 Oct 2018 01:06:44 +0000
reviewersdholbert
bugs1498273
milestone65.0a1
Bug 1498273 Part 3: Define and set ComputedFlexItemInfo::mClampState. r=dholbert Depends on D9727 Differential Revision: https://phabricator.services.mozilla.com/D9728
dom/flex/FlexItemValues.cpp
layout/generic/nsFlexContainerFrame.cpp
layout/generic/nsFlexContainerFrame.h
--- a/dom/flex/FlexItemValues.cpp
+++ b/dom/flex/FlexItemValues.cpp
@@ -56,17 +56,17 @@ FlexItemValues::FlexItemValues(FlexLineV
     aItem->mMainDeltaSize);
   mMainMinSize = nsPresContext::AppUnitsToDoubleCSSPixels(
     aItem->mMainMinSize);
   mMainMaxSize = ToPossiblyUnconstrainedPixels(aItem->mMainMaxSize);
   mCrossMinSize = nsPresContext::AppUnitsToDoubleCSSPixels(
     aItem->mCrossMinSize);
   mCrossMaxSize = ToPossiblyUnconstrainedPixels(aItem->mCrossMaxSize);
 
-  mClampState = FlexItemClampState::Unclamped;
+  mClampState = aItem->mClampState;
 }
 
 JSObject*
 FlexItemValues::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
 {
   return FlexItemValues_Binding::Wrap(aCx, this, aGivenProto);
 }
 
--- a/layout/generic/nsFlexContainerFrame.cpp
+++ b/layout/generic/nsFlexContainerFrame.cpp
@@ -1452,16 +1452,21 @@ nsFlexContainerFrame::GenerateFlexItemFo
                                    crossMinSize, crossMaxSize,
                                    aAxisTracker);
 
   // If we're inflexible, we can just freeze to our hypothetical main-size
   // up-front. Similarly, if we're a fixed-size widget, we only have one
   // valid size, so we freeze to keep ourselves from flexing.
   if (isFixedSizeWidget || (flexGrow == 0.0f && flexShrink == 0.0f)) {
     item->Freeze();
+    if (flexBaseSize < mainMinSize) {
+      item->SetWasMinClamped();
+    } else if (flexBaseSize > mainMaxSize) {
+      item->SetWasMaxClamped();
+    }
   }
 
   // Resolve "flex-basis:auto" and/or "min-[width|height]:auto" (which might
   // require us to reflow the item to measure content height)
   ResolveAutoFlexBasisAndMinSize(aPresContext, *item,
                                  childRI, aAxisTracker);
   return item;
 }
@@ -2603,16 +2608,21 @@ FlexLine::FreezeItemsEarly(bool aIsUsing
           if (item->GetFlexBaseSize() < item->GetMainSize()) {
             shouldFreeze = true;
           }
         }
       }
       if (shouldFreeze) {
         // Freeze item! (at its hypothetical main size)
         item->Freeze();
+        if (item->GetFlexBaseSize() < item->GetMainSize()) {
+          item->SetWasMinClamped();
+        } else if (item->GetFlexBaseSize() > item->GetMainSize()) {
+          item->SetWasMaxClamped();
+        }
         mNumFrozenItems++;
       }
     }
   }
 }
 
 // Based on the sign of aTotalViolation, this function freezes a subset of our
 // flexible sizes, and restores the remaining ones to their initial pref sizes.
@@ -2642,26 +2652,33 @@ FlexLine::FreezeOrRestoreEachFlexibleSiz
        numUnfrozenItemsToBeSeen > 0; item = item->getNext()) {
     MOZ_ASSERT(item, "numUnfrozenItemsToBeSeen says items remain to be seen");
     if (!item->IsFrozen()) {
       numUnfrozenItemsToBeSeen--;
 
       MOZ_ASSERT(!item->HadMinViolation() || !item->HadMaxViolation(),
                  "Can have either min or max violation, but not both");
 
+      bool hadMinViolation = item->HadMinViolation();
+      bool hadMaxViolation = item->HadMaxViolation();
       if (eFreezeEverything == freezeType ||
-          (eFreezeMinViolations == freezeType && item->HadMinViolation()) ||
-          (eFreezeMaxViolations == freezeType && item->HadMaxViolation())) {
+          (eFreezeMinViolations == freezeType && hadMinViolation) ||
+          (eFreezeMaxViolations == freezeType && hadMaxViolation)) {
 
         MOZ_ASSERT(item->GetMainSize() >= item->GetMainMinSize(),
                    "Freezing item at a size below its minimum");
         MOZ_ASSERT(item->GetMainSize() <= item->GetMainMaxSize(),
                    "Freezing item at a size above its maximum");
 
         item->Freeze();
+        if (hadMinViolation) {
+          item->SetWasMinClamped();
+        } else if (hadMaxViolation) {
+          item->SetWasMaxClamped();
+        }
         mNumFrozenItems++;
       } else if (MOZ_UNLIKELY(aIsFinalIteration)) {
         // XXXdholbert If & when bug 765861 is fixed, we should upgrade this
         // assertion to be fatal except in documents with enormous lengths.
         NS_ERROR("Final iteration still has unfrozen items, this shouldn't"
                  " happen unless there was nscoord under/overflow.");
         item->Freeze();
         mNumFrozenItems++;
@@ -4862,16 +4879,38 @@ nsFlexContainerFrame::DoFlexLayout(nsPre
   for (FlexLine* line = lines.getFirst(); line; line = line->getNext(),
                                                 ++lineIndex) {
     ComputedFlexLineInfo* lineInfo = containerInfo ?
                                      &containerInfo->mLines[lineIndex] :
                                      nullptr;
     line->ResolveFlexibleLengths(aContentBoxMainSize, lineInfo);
   }
 
+  // If needed, capture the final clamp state from all the items.
+  if (containerInfo) {
+    uint32_t lineIndex = 0;
+    for (const FlexLine* line = lines.getFirst(); line;
+         line = line->getNext(), ++lineIndex) {
+      ComputedFlexLineInfo* lineInfo = &containerInfo->mLines[lineIndex];
+
+      uint32_t itemIndex = 0;
+      for (const FlexItem* item = line->GetFirstItem(); item;
+           item = item->getNext(), ++itemIndex) {
+        ComputedFlexItemInfo* itemInfo = &lineInfo->mItems[itemIndex];
+
+        itemInfo->mClampState =
+          item->WasMinClamped() ?
+          mozilla::dom::FlexItemClampState::Clamped_to_min :
+          (item->WasMaxClamped() ?
+           mozilla::dom::FlexItemClampState::Clamped_to_max :
+           mozilla::dom::FlexItemClampState::Unclamped);
+      }
+    }
+  }
+
   // Cross Size Determination - Flexbox spec section 9.4
   // ===================================================
   // Calculate the hypothetical cross size of each item:
 
   // 'sumLineCrossSizes' includes the size of all gaps between lines
   nscoord sumLineCrossSizes = 0;
   for (FlexLine* line = lines.getFirst(); line; line = line->getNext()) {
     for (FlexItem* item = line->GetFirstItem(); item; item = item->getNext()) {
--- a/layout/generic/nsFlexContainerFrame.h
+++ b/layout/generic/nsFlexContainerFrame.h
@@ -49,16 +49,17 @@ struct ComputedFlexItemInfo
    * algorithm proceeds linearly, the mMainDeltaSize for an item only
    * respects the resolved size of items already frozen.
    */
   nscoord mMainDeltaSize;
   nscoord mMainMinSize;
   nscoord mMainMaxSize;
   nscoord mCrossMinSize;
   nscoord mCrossMaxSize;
+  mozilla::dom::FlexItemClampState mClampState;
 };
 
 struct ComputedFlexLineInfo
 {
   nsTArray<ComputedFlexItemInfo> mItems;
   nscoord mCrossStart;
   nscoord mCrossSize;
   nscoord mFirstBaselineOffset;