LCOV - code coverage report
Current view: top level - layout/generic - ReflowInput.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 694 1325 52.4 %
Date: 2017-07-14 16:53:18 Functions: 36 45 80.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       5             : 
       6             : /* struct containing the input to nsIFrame::Reflow */
       7             : 
       8             : #include "mozilla/ReflowInput.h"
       9             : 
      10             : #include "LayoutLogging.h"
      11             : #include "nsStyleConsts.h"
      12             : #include "nsCSSAnonBoxes.h"
      13             : #include "nsFrame.h"
      14             : #include "nsIContent.h"
      15             : #include "nsGkAtoms.h"
      16             : #include "nsPresContext.h"
      17             : #include "nsIPresShell.h"
      18             : #include "nsFontMetrics.h"
      19             : #include "nsBlockFrame.h"
      20             : #include "nsLineBox.h"
      21             : #include "nsImageFrame.h"
      22             : #include "nsTableFrame.h"
      23             : #include "nsTableCellFrame.h"
      24             : #include "nsIPercentBSizeObserver.h"
      25             : #include "nsLayoutUtils.h"
      26             : #include "mozilla/Preferences.h"
      27             : #include "nsFontInflationData.h"
      28             : #include "StickyScrollContainer.h"
      29             : #include "nsIFrameInlines.h"
      30             : #include "CounterStyleManager.h"
      31             : #include <algorithm>
      32             : #include "mozilla/dom/HTMLInputElement.h"
      33             : 
      34             : #ifdef DEBUG
      35             : #undef NOISY_VERTICAL_ALIGN
      36             : #else
      37             : #undef NOISY_VERTICAL_ALIGN
      38             : #endif
      39             : 
      40             : using namespace mozilla;
      41             : using namespace mozilla::css;
      42             : using namespace mozilla::dom;
      43             : using namespace mozilla::layout;
      44             : 
      45             : enum eNormalLineHeightControl {
      46             :   eUninitialized = -1,
      47             :   eNoExternalLeading = 0,   // does not include external leading
      48             :   eIncludeExternalLeading,  // use whatever value font vendor provides
      49             :   eCompensateLeading        // compensate leading if leading provided by font vendor is not enough
      50             : };
      51             : 
      52             : static eNormalLineHeightControl sNormalLineHeightControl = eUninitialized;
      53             : 
      54             : // Initialize a <b>root</b> reflow state with a rendering context to
      55             : // use for measuring things.
      56         200 : ReflowInput::ReflowInput(nsPresContext*       aPresContext,
      57             :                                      nsIFrame*            aFrame,
      58             :                                      gfxContext*          aRenderingContext,
      59             :                                      const LogicalSize&   aAvailableSpace,
      60         200 :                                      uint32_t             aFlags)
      61             :   : SizeComputationInput(aFrame, aRenderingContext)
      62             :   , mBlockDelta(0)
      63             :   , mOrthogonalLimit(NS_UNCONSTRAINEDSIZE)
      64             :   , mContainingBlockSize(mWritingMode)
      65         200 :   , mReflowDepth(0)
      66             : {
      67         200 :   NS_PRECONDITION(aRenderingContext, "no rendering context");
      68         200 :   MOZ_ASSERT(aPresContext, "no pres context");
      69         200 :   MOZ_ASSERT(aFrame, "no frame");
      70         200 :   MOZ_ASSERT(aPresContext == aFrame->PresContext(), "wrong pres context");
      71         200 :   mParentReflowInput = nullptr;
      72         200 :   AvailableISize() = aAvailableSpace.ISize(mWritingMode);
      73         200 :   AvailableBSize() = aAvailableSpace.BSize(mWritingMode);
      74         200 :   mFloatManager = nullptr;
      75         200 :   mLineLayout = nullptr;
      76         200 :   mDiscoveredClearance = nullptr;
      77         200 :   mPercentBSizeObserver = nullptr;
      78             : 
      79         200 :   if (aFlags & DUMMY_PARENT_REFLOW_STATE) {
      80         126 :     mFlags.mDummyParentReflowInput = true;
      81             :   }
      82         200 :   if (aFlags & COMPUTE_SIZE_SHRINK_WRAP) {
      83           0 :     mFlags.mShrinkWrap = true;
      84             :   }
      85         200 :   if (aFlags & COMPUTE_SIZE_USE_AUTO_BSIZE) {
      86           0 :     mFlags.mUseAutoBSize = true;
      87             :   }
      88         200 :   if (aFlags & STATIC_POS_IS_CB_ORIGIN) {
      89           0 :     mFlags.mStaticPosIsCBOrigin = true;
      90             :   }
      91         200 :   if (aFlags & I_CLAMP_MARGIN_BOX_MIN_SIZE) {
      92           0 :     mFlags.mIClampMarginBoxMinSize = true;
      93             :   }
      94         200 :   if (aFlags & B_CLAMP_MARGIN_BOX_MIN_SIZE) {
      95           0 :     mFlags.mBClampMarginBoxMinSize = true;
      96             :   }
      97         200 :   if (aFlags & I_APPLY_AUTO_MIN_SIZE) {
      98           0 :     mFlags.mApplyAutoMinSize = true;
      99             :   }
     100             : 
     101         200 :   if (!(aFlags & CALLER_WILL_INIT)) {
     102         130 :     Init(aPresContext);
     103             :   }
     104         200 : }
     105             : 
     106           0 : static bool CheckNextInFlowParenthood(nsIFrame* aFrame, nsIFrame* aParent)
     107             : {
     108           0 :   nsIFrame* frameNext = aFrame->GetNextInFlow();
     109           0 :   nsIFrame* parentNext = aParent->GetNextInFlow();
     110           0 :   return frameNext && parentNext && frameNext->GetParent() == parentNext;
     111             : }
     112             : 
     113             : /**
     114             :  * Adjusts the margin for a list (ol, ul), if necessary, depending on
     115             :  * font inflation settings. Unfortunately, because bullets from a list are
     116             :  * placed in the margin area, we only have ~40px in which to place the
     117             :  * bullets. When they are inflated, however, this causes problems, since
     118             :  * the text takes up more space than is available in the margin.
     119             :  *
     120             :  * This method will return a small amount (in app units) by which the
     121             :  * margin can be adjusted, so that the space is available for list
     122             :  * bullets to be rendered with font inflation enabled.
     123             :  */
     124             : static  nscoord
     125         652 : FontSizeInflationListMarginAdjustment(const nsIFrame* aFrame)
     126             : {
     127         652 :   float inflation = nsLayoutUtils::FontSizeInflationFor(aFrame);
     128         652 :   if (aFrame->IsFrameOfType(nsIFrame::eBlockFrame)) {
     129         172 :     const nsBlockFrame* blockFrame = static_cast<const nsBlockFrame*>(aFrame);
     130             : 
     131             :     // We only want to adjust the margins if we're dealing with an ordered
     132             :     // list.
     133         172 :     if (inflation > 1.0f &&
     134         172 :         blockFrame->HasBullet() &&
     135             :         inflation > 1.0f) {
     136             : 
     137           0 :       auto listStyleType = aFrame->StyleList()->mCounterStyle->GetStyle();
     138           0 :       if (listStyleType != NS_STYLE_LIST_STYLE_NONE &&
     139           0 :           listStyleType != NS_STYLE_LIST_STYLE_DISC &&
     140           0 :           listStyleType != NS_STYLE_LIST_STYLE_CIRCLE &&
     141           0 :           listStyleType != NS_STYLE_LIST_STYLE_SQUARE &&
     142           0 :           listStyleType != NS_STYLE_LIST_STYLE_DISCLOSURE_CLOSED &&
     143             :           listStyleType != NS_STYLE_LIST_STYLE_DISCLOSURE_OPEN) {
     144             :         // The HTML spec states that the default padding for ordered lists
     145             :         // begins at 40px, indicating that we have 40px of space to place a
     146             :         // bullet. When performing font inflation calculations, we add space
     147             :         // equivalent to this, but simply inflated at the same amount as the
     148             :         // text, in app units.
     149           0 :         return nsPresContext::CSSPixelsToAppUnits(40) * (inflation - 1);
     150             :       }
     151             : 
     152             :     }
     153             :   }
     154             : 
     155         652 :   return 0;
     156             : }
     157             : 
     158             : // NOTE: If we ever want to use SizeComputationInput for a flex item or a
     159             : // grid item, we need to make it take the containing-block block-size as
     160             : // well as the inline-size, since flex items and grid items resolve
     161             : // block-direction percent margins and padding against the
     162             : // containing-block block-size, rather than its inline-size.
     163           0 : SizeComputationInput::SizeComputationInput(nsIFrame *aFrame,
     164             :                                    gfxContext *aRenderingContext,
     165             :                                    WritingMode aContainingBlockWritingMode,
     166           0 :                                    nscoord aContainingBlockISize)
     167             :   : mFrame(aFrame)
     168             :   , mRenderingContext(aRenderingContext)
     169           0 :   , mWritingMode(aFrame->GetWritingMode())
     170             : {
     171           0 :   MOZ_ASSERT(!aFrame->IsFlexOrGridItem(),
     172             :              "We're about to resolve percent margin & padding "
     173             :              "values against CB inline size, which is incorrect for "
     174             :              "flex/grid items. "
     175             :              "Additionally for grid items, this path doesn't handle baseline "
     176             :              "padding contribution - see SizeComputationInput::InitOffsets");
     177             :   LogicalSize cbSize(aContainingBlockWritingMode, aContainingBlockISize,
     178           0 :                      aContainingBlockISize);
     179           0 :   ReflowInputFlags flags;
     180           0 :   InitOffsets(aContainingBlockWritingMode, cbSize, mFrame->Type(), flags);
     181           0 : }
     182             : 
     183             : // Initialize a reflow state for a child frame's reflow. Some state
     184             : // is copied from the parent reflow state; the remaining state is
     185             : // computed.
     186         523 : ReflowInput::ReflowInput(
     187             :                      nsPresContext*           aPresContext,
     188             :                      const ReflowInput& aParentReflowInput,
     189             :                      nsIFrame*                aFrame,
     190             :                      const LogicalSize&       aAvailableSpace,
     191             :                      const LogicalSize*       aContainingBlockSize,
     192         523 :                      uint32_t                 aFlags)
     193         523 :   : SizeComputationInput(aFrame, aParentReflowInput.mRenderingContext)
     194             :   , mBlockDelta(0)
     195             :   , mOrthogonalLimit(NS_UNCONSTRAINEDSIZE)
     196             :   , mContainingBlockSize(mWritingMode)
     197             :   , mFlags(aParentReflowInput.mFlags)
     198         523 :   , mReflowDepth(aParentReflowInput.mReflowDepth + 1)
     199             : {
     200         523 :   MOZ_ASSERT(aPresContext, "no pres context");
     201         523 :   MOZ_ASSERT(aFrame, "no frame");
     202         523 :   MOZ_ASSERT(aPresContext == aFrame->PresContext(), "wrong pres context");
     203         523 :   NS_PRECONDITION(!mFlags.mSpecialBSizeReflow ||
     204             :                   !NS_SUBTREE_DIRTY(aFrame),
     205             :                   "frame should be clean when getting special bsize reflow");
     206             : 
     207         523 :   mParentReflowInput = &aParentReflowInput;
     208             : 
     209         523 :   AvailableISize() = aAvailableSpace.ISize(mWritingMode);
     210         523 :   AvailableBSize() = aAvailableSpace.BSize(mWritingMode);
     211             : 
     212         523 :   if (mWritingMode.IsOrthogonalTo(aParentReflowInput.GetWritingMode())) {
     213             :     // If we're setting up for an orthogonal flow, and the parent reflow state
     214             :     // had a constrained ComputedBSize, we can use that as our AvailableISize
     215             :     // in preference to leaving it unconstrained.
     216           0 :     if (AvailableISize() == NS_UNCONSTRAINEDSIZE &&
     217           0 :         aParentReflowInput.ComputedBSize() != NS_UNCONSTRAINEDSIZE) {
     218           0 :       AvailableISize() = aParentReflowInput.ComputedBSize();
     219             :     }
     220             :   }
     221             : 
     222         523 :   mFloatManager = aParentReflowInput.mFloatManager;
     223         523 :   if (mFrame->IsFrameOfType(nsIFrame::eLineParticipant))
     224           9 :     mLineLayout = aParentReflowInput.mLineLayout;
     225             :   else
     226         514 :     mLineLayout = nullptr;
     227             : 
     228             :   // Note: mFlags was initialized as a copy of aParentReflowInput.mFlags up in
     229             :   // this constructor's init list, so the only flags that we need to explicitly
     230             :   // initialize here are those that may need a value other than our parent's.
     231         523 :   mFlags.mNextInFlowUntouched = aParentReflowInput.mFlags.mNextInFlowUntouched &&
     232           0 :     CheckNextInFlowParenthood(aFrame, aParentReflowInput.mFrame);
     233         523 :   mFlags.mAssumingHScrollbar = mFlags.mAssumingVScrollbar = false;
     234         523 :   mFlags.mIsColumnBalancing = false;
     235         523 :   mFlags.mIsFlexContainerMeasuringHeight = false;
     236         523 :   mFlags.mDummyParentReflowInput = false;
     237         523 :   mFlags.mShrinkWrap = !!(aFlags & COMPUTE_SIZE_SHRINK_WRAP);
     238         523 :   mFlags.mUseAutoBSize = !!(aFlags & COMPUTE_SIZE_USE_AUTO_BSIZE);
     239         523 :   mFlags.mStaticPosIsCBOrigin = !!(aFlags & STATIC_POS_IS_CB_ORIGIN);
     240         523 :   mFlags.mIOffsetsNeedCSSAlign = mFlags.mBOffsetsNeedCSSAlign = false;
     241         523 :   mFlags.mIClampMarginBoxMinSize = !!(aFlags & I_CLAMP_MARGIN_BOX_MIN_SIZE);
     242         523 :   mFlags.mBClampMarginBoxMinSize = !!(aFlags & B_CLAMP_MARGIN_BOX_MIN_SIZE);
     243         523 :   mFlags.mApplyAutoMinSize = !!(aFlags & I_APPLY_AUTO_MIN_SIZE);
     244             : 
     245         523 :   mDiscoveredClearance = nullptr;
     246        1046 :   mPercentBSizeObserver = (aParentReflowInput.mPercentBSizeObserver &&
     247           0 :                             aParentReflowInput.mPercentBSizeObserver->NeedsToObserve(*this))
     248         523 :                            ? aParentReflowInput.mPercentBSizeObserver : nullptr;
     249             : 
     250        1046 :   if ((aFlags & DUMMY_PARENT_REFLOW_STATE) ||
     251         435 :       (mParentReflowInput->mFlags.mDummyParentReflowInput &&
     252          38 :        mFrame->IsTableFrame())) {
     253         126 :     mFlags.mDummyParentReflowInput = true;
     254             :   }
     255             : 
     256         523 :   if (!(aFlags & CALLER_WILL_INIT)) {
     257         360 :     Init(aPresContext, aContainingBlockSize);
     258             :   }
     259         523 : }
     260             : 
     261             : inline nscoord
     262         106 : SizeComputationInput::ComputeISizeValue(nscoord aContainingBlockISize,
     263             :                                     nscoord aContentEdgeToBoxSizing,
     264             :                                     nscoord aBoxSizingToMarginEdge,
     265             :                                     const nsStyleCoord& aCoord) const
     266             : {
     267         106 :   return mFrame->ComputeISizeValue(mRenderingContext,
     268             :                                    aContainingBlockISize,
     269             :                                    aContentEdgeToBoxSizing,
     270             :                                    aBoxSizingToMarginEdge,
     271         106 :                                    aCoord);
     272             : }
     273             : 
     274             : nscoord
     275         106 : SizeComputationInput::ComputeISizeValue(nscoord aContainingBlockISize,
     276             :                                     StyleBoxSizing aBoxSizing,
     277             :                                     const nsStyleCoord& aCoord) const
     278             : {
     279         106 :   WritingMode wm = GetWritingMode();
     280         212 :   nscoord inside = 0, outside = ComputedLogicalBorderPadding().IStartEnd(wm) +
     281         106 :                                 ComputedLogicalMargin().IStartEnd(wm);
     282         106 :   if (aBoxSizing == StyleBoxSizing::Border) {
     283         106 :     inside = ComputedLogicalBorderPadding().IStartEnd(wm);
     284             :   }
     285         106 :   outside -= inside;
     286             : 
     287             :   return ComputeISizeValue(aContainingBlockISize, inside,
     288         106 :                            outside, aCoord);
     289             : }
     290             : 
     291             : nscoord
     292          92 : SizeComputationInput::ComputeBSizeValue(nscoord aContainingBlockBSize,
     293             :                                     StyleBoxSizing aBoxSizing,
     294             :                                     const nsStyleCoord& aCoord) const
     295             : {
     296          92 :   WritingMode wm = GetWritingMode();
     297          92 :   nscoord inside = 0;
     298          92 :   if (aBoxSizing == StyleBoxSizing::Border) {
     299          92 :     inside = ComputedLogicalBorderPadding().BStartEnd(wm);
     300             :   }
     301             :   return nsLayoutUtils::ComputeBSizeValue(aContainingBlockBSize,
     302          92 :                                           inside, aCoord);
     303             : }
     304             : 
     305             : void
     306         288 : ReflowInput::SetComputedWidth(nscoord aComputedWidth)
     307             : {
     308         288 :   NS_ASSERTION(mFrame, "Must have a frame!");
     309             :   // It'd be nice to assert that |frame| is not in reflow, but this fails for
     310             :   // two reasons:
     311             :   //
     312             :   // 1) Viewport frames reset the computed width on a copy of their reflow
     313             :   //    state when reflowing fixed-pos kids.  In that case we actually don't
     314             :   //    want to mess with the resize flags, because comparing the frame's rect
     315             :   //    to the munged computed width is pointless.
     316             :   // 2) nsFrame::BoxReflow creates a reflow state for its parent.  This reflow
     317             :   //    state is not used to reflow the parent, but just as a parent for the
     318             :   //    frame's own reflow state.  So given a nsBoxFrame inside some non-XUL
     319             :   //    (like a text control, for example), we'll end up creating a reflow
     320             :   //    state for the parent while the parent is reflowing.
     321             : 
     322         288 :   NS_PRECONDITION(aComputedWidth >= 0, "Invalid computed width");
     323         288 :   if (ComputedWidth() != aComputedWidth) {
     324          40 :     ComputedWidth() = aComputedWidth;
     325          40 :     LayoutFrameType frameType = mFrame->Type();
     326          40 :     if (frameType != LayoutFrameType::Viewport || // Or check GetParent()?
     327           0 :         mWritingMode.IsVertical()) {
     328          40 :       InitResizeFlags(mFrame->PresContext(), frameType);
     329             :     }
     330             :   }
     331         288 : }
     332             : 
     333             : void
     334         499 : ReflowInput::SetComputedHeight(nscoord aComputedHeight)
     335             : {
     336         499 :   NS_ASSERTION(mFrame, "Must have a frame!");
     337             :   // It'd be nice to assert that |frame| is not in reflow, but this fails
     338             :   // because:
     339             :   //
     340             :   //    nsFrame::BoxReflow creates a reflow state for its parent.  This reflow
     341             :   //    state is not used to reflow the parent, but just as a parent for the
     342             :   //    frame's own reflow state.  So given a nsBoxFrame inside some non-XUL
     343             :   //    (like a text control, for example), we'll end up creating a reflow
     344             :   //    state for the parent while the parent is reflowing.
     345             : 
     346         499 :   NS_PRECONDITION(aComputedHeight >= 0, "Invalid computed height");
     347         499 :   if (ComputedHeight() != aComputedHeight) {
     348         317 :     ComputedHeight() = aComputedHeight;
     349         317 :     LayoutFrameType frameType = mFrame->Type();
     350         317 :     if (frameType != LayoutFrameType::Viewport || !mWritingMode.IsVertical()) {
     351         317 :       InitResizeFlags(mFrame->PresContext(), frameType);
     352             :     }
     353             :   }
     354         499 : }
     355             : 
     356             : void
     357         723 : ReflowInput::Init(nsPresContext*     aPresContext,
     358             :                         const LogicalSize* aContainingBlockSize,
     359             :                         const nsMargin*    aBorder,
     360             :                         const nsMargin*    aPadding)
     361             : {
     362        1099 :   if ((mFrame->GetStateBits() & NS_FRAME_IS_DIRTY) &&
     363         376 :       !mFrame->IsXULBoxFrame()) {
     364             :     // Mark all child frames as dirty.
     365             :     //
     366             :     // We don't do this for XUL boxes because they handle their child
     367             :     // reflow separately.
     368             :     //
     369             :     // FIXME (bug 1376530): It would be better for memory locality if we
     370             :     // did this as we went.  However, we need to be careful not to do
     371             :     // this twice for any particular child if we reflow it twice.  The
     372             :     // easiest way to accomplish that is to do it at the start.
     373         894 :     for (nsIFrame::ChildListIterator childLists(mFrame);
     374         629 :          !childLists.IsDone(); childLists.Next()) {
     375         383 :       for (nsIFrame* childFrame : childLists.CurrentList()) {
     376         201 :         if (!childFrame->IsTableColGroupFrame()) {
     377         201 :           childFrame->AddStateBits(NS_FRAME_IS_DIRTY);
     378             :         }
     379             :       }
     380             :     }
     381             :   }
     382             : 
     383         723 :   if (AvailableISize() == NS_UNCONSTRAINEDSIZE) {
     384             :     // Look up the parent chain for an orthogonal inline limit,
     385             :     // and reset AvailableISize() if found.
     386           0 :     for (const ReflowInput *parent = mParentReflowInput;
     387           0 :          parent != nullptr; parent = parent->mParentReflowInput) {
     388           0 :       if (parent->GetWritingMode().IsOrthogonalTo(mWritingMode) &&
     389           0 :           parent->mOrthogonalLimit != NS_UNCONSTRAINEDSIZE) {
     390           0 :         AvailableISize() = parent->mOrthogonalLimit;
     391           0 :         break;
     392             :       }
     393             :     }
     394             :   }
     395             : 
     396         723 :   LAYOUT_WARN_IF_FALSE(AvailableISize() != NS_UNCONSTRAINEDSIZE,
     397             :                        "have unconstrained inline-size; this should only "
     398             :                        "result from very large sizes, not attempts at "
     399             :                        "intrinsic inline-size calculation");
     400             : 
     401         723 :   mStylePosition = mFrame->StylePosition();
     402         723 :   mStyleDisplay = mFrame->StyleDisplay();
     403         723 :   mStyleVisibility = mFrame->StyleVisibility();
     404         723 :   mStyleBorder = mFrame->StyleBorder();
     405         723 :   mStyleMargin = mFrame->StyleMargin();
     406         723 :   mStylePadding = mFrame->StylePadding();
     407         723 :   mStyleText = mFrame->StyleText();
     408             : 
     409         723 :   LayoutFrameType type = mFrame->Type();
     410         723 :   if (type == mozilla::LayoutFrameType::Placeholder) {
     411             :     // Placeholders have a no-op Reflow method that doesn't need the rest of
     412             :     // this initialization, so we bail out early.
     413          71 :     ComputedBSize() = ComputedISize() = 0;
     414          71 :     return;
     415             :   }
     416             : 
     417         652 :   InitFrameType(type);
     418         652 :   InitCBReflowInput();
     419             : 
     420         652 :   LogicalSize cbSize(mWritingMode, -1, -1);
     421         652 :   if (aContainingBlockSize) {
     422          77 :     cbSize = *aContainingBlockSize;
     423             :   }
     424             : 
     425         652 :   InitConstraints(aPresContext, cbSize, aBorder, aPadding, type);
     426             : 
     427         652 :   InitResizeFlags(aPresContext, type);
     428             : 
     429         652 :   nsIFrame *parent = mFrame->GetParent();
     430        1238 :   if (parent &&
     431         764 :       (parent->GetStateBits() & NS_FRAME_IN_CONSTRAINED_BSIZE) &&
     432         102 :       !(parent->IsScrollFrame() &&
     433          46 :         parent->StyleDisplay()->mOverflowY != NS_STYLE_OVERFLOW_HIDDEN)) {
     434          56 :     mFrame->AddStateBits(NS_FRAME_IN_CONSTRAINED_BSIZE);
     435         596 :   } else if (type == LayoutFrameType::SVGForeignObject) {
     436             :     // An SVG foreignObject frame is inherently constrained block-size.
     437           0 :     mFrame->AddStateBits(NS_FRAME_IN_CONSTRAINED_BSIZE);
     438             :   } else {
     439         596 :     const nsStyleCoord& bSizeCoord = mStylePosition->BSize(mWritingMode);
     440         596 :     const nsStyleCoord& maxBSizeCoord = mStylePosition->MaxBSize(mWritingMode);
     441        1734 :     if ((bSizeCoord.GetUnit() != eStyleUnit_Auto ||
     442         796 :          maxBSizeCoord.GetUnit() != eStyleUnit_None) &&
     443             :          // Don't set NS_FRAME_IN_CONSTRAINED_BSIZE on body or html elements.
     444         200 :          (mFrame->GetContent() &&
     445         100 :         !(mFrame->GetContent()->IsAnyOfHTMLElements(nsGkAtoms::body,
     446             :                                                    nsGkAtoms::html)))) {
     447             : 
     448             :       // If our block-size was specified as a percentage, then this could
     449             :       // actually resolve to 'auto', based on:
     450             :       // http://www.w3.org/TR/CSS21/visudet.html#the-height-property
     451         100 :       nsIFrame* containingBlk = mFrame;
     452         116 :       while (containingBlk) {
     453         108 :         const nsStylePosition* stylePos = containingBlk->StylePosition();
     454         108 :         const nsStyleCoord& bSizeCoord = stylePos->BSize(mWritingMode);
     455         108 :         const nsStyleCoord& maxBSizeCoord = stylePos->MaxBSize(mWritingMode);
     456         270 :         if ((bSizeCoord.IsCoordPercentCalcUnit() &&
     457         262 :              !bSizeCoord.HasPercent()) ||
     458         108 :             (maxBSizeCoord.IsCoordPercentCalcUnit() &&
     459          46 :              !maxBSizeCoord.HasPercent())) {
     460          92 :           mFrame->AddStateBits(NS_FRAME_IN_CONSTRAINED_BSIZE);
     461          92 :           break;
     462          40 :         } else if ((bSizeCoord.IsCoordPercentCalcUnit() &&
     463          32 :                     bSizeCoord.HasPercent()) ||
     464           8 :                    (maxBSizeCoord.IsCoordPercentCalcUnit() &&
     465           0 :                     maxBSizeCoord.HasPercent())) {
     466           8 :           if (!(containingBlk = containingBlk->GetContainingBlock())) {
     467             :             // If we've reached the top of the tree, then we don't have
     468             :             // a constrained block-size.
     469           0 :             mFrame->RemoveStateBits(NS_FRAME_IN_CONSTRAINED_BSIZE);
     470           0 :             break;
     471             :           }
     472             : 
     473           8 :           continue;
     474             :         } else {
     475           8 :           mFrame->RemoveStateBits(NS_FRAME_IN_CONSTRAINED_BSIZE);
     476           8 :           break;
     477             :         }
     478             :       }
     479             :     } else {
     480         496 :       mFrame->RemoveStateBits(NS_FRAME_IN_CONSTRAINED_BSIZE);
     481             :     }
     482             :   }
     483             : 
     484        2408 :   if (mParentReflowInput &&
     485        2008 :       mParentReflowInput->GetWritingMode().IsOrthogonalTo(mWritingMode)) {
     486             :     // Orthogonal frames are always reflowed with an unconstrained
     487             :     // dimension to avoid incomplete reflow across an orthogonal
     488             :     // boundary. Normally this is the block-size, but for column sets
     489             :     // with auto-height it's the inline-size, so that they can add
     490             :     // columns in the container's block direction
     491           0 :     if (type == LayoutFrameType::ColumnSet &&
     492           0 :         eStyleUnit_Auto == mStylePosition->ISize(mWritingMode).GetUnit()) {
     493           0 :       ComputedISize() = NS_UNCONSTRAINEDSIZE;
     494             :     } else {
     495           0 :       AvailableBSize() = NS_UNCONSTRAINEDSIZE;
     496             :     }
     497             :   }
     498             : 
     499         652 :   LAYOUT_WARN_IF_FALSE((mFrameType == NS_CSS_FRAME_TYPE_INLINE &&
     500             :                         !mFrame->IsFrameOfType(nsIFrame::eReplaced)) ||
     501             :                        type == LayoutFrameType::Text ||
     502             :                        ComputedISize() != NS_UNCONSTRAINEDSIZE,
     503             :                        "have unconstrained inline-size; this should only "
     504             :                        "result from very large sizes, not attempts at "
     505             :                        "intrinsic inline-size calculation");
     506             : }
     507             : 
     508         652 : void ReflowInput::InitCBReflowInput()
     509             : {
     510         652 :   if (!mParentReflowInput) {
     511         200 :     mCBReflowInput = nullptr;
     512         200 :     return;
     513             :   }
     514         452 :   if (mParentReflowInput->mFlags.mDummyParentReflowInput) {
     515          93 :     mCBReflowInput = mParentReflowInput;
     516          93 :     return;
     517             :   }
     518             : 
     519         359 :   if (mParentReflowInput->mFrame == mFrame->GetContainingBlock(0, mStyleDisplay)) {
     520             :     // Inner table frames need to use the containing block of the outer
     521             :     // table frame.
     522         359 :     if (mFrame->IsTableFrame()) {
     523           0 :       mCBReflowInput = mParentReflowInput->mCBReflowInput;
     524             :     } else {
     525         359 :       mCBReflowInput = mParentReflowInput;
     526             :     }
     527             :   } else {
     528           0 :     mCBReflowInput = mParentReflowInput->mCBReflowInput;
     529             :   }
     530             : }
     531             : 
     532             : /* Check whether CalcQuirkContainingBlockHeight would stop on the
     533             :  * given reflow state, using its block as a height.  (essentially
     534             :  * returns false for any case in which CalcQuirkContainingBlockHeight
     535             :  * has a "continue" in its main loop.)
     536             :  *
     537             :  * XXX Maybe refactor CalcQuirkContainingBlockHeight so it uses
     538             :  * this function as well
     539             :  */
     540             : static bool
     541           0 : IsQuirkContainingBlockHeight(const ReflowInput* rs, LayoutFrameType aFrameType)
     542             : {
     543           0 :   if (LayoutFrameType::Block == aFrameType ||
     544             : #ifdef MOZ_XUL
     545           0 :       LayoutFrameType::XULLabel == aFrameType ||
     546             : #endif
     547             :       LayoutFrameType::Scroll == aFrameType) {
     548             :     // Note: This next condition could change due to a style change,
     549             :     // but that would cause a style reflow anyway, which means we're ok.
     550           0 :     if (NS_AUTOHEIGHT == rs->ComputedHeight()) {
     551           0 :       if (!rs->mFrame->IsAbsolutelyPositioned(rs->mStyleDisplay)) {
     552           0 :         return false;
     553             :       }
     554             :     }
     555             :   }
     556           0 :   return true;
     557             : }
     558             : 
     559             : void
     560        1009 : ReflowInput::InitResizeFlags(nsPresContext* aPresContext,
     561             :                              LayoutFrameType aFrameType)
     562             : {
     563        1009 :   SetBResize(false);
     564        1009 :   SetIResize(false);
     565             : 
     566        1009 :   const WritingMode wm = mWritingMode; // just a shorthand
     567             :   // We should report that we have a resize in the inline dimension if
     568             :   // *either* the border-box size or the content-box size in that
     569             :   // dimension has changed.  It might not actually be necessary to do
     570             :   // this if the border-box size has changed and the content-box size
     571             :   // has not changed, but since we've historically used the flag to mean
     572             :   // border-box size change, continue to do that.  (It's possible for
     573             :   // the content-box size to change without a border-box size change or
     574             :   // a style change given (1) a fixed width (possibly fixed by max-width
     575             :   // or min-width), (2) box-sizing:border-box or padding-box, and
     576             :   // (3) percentage padding.)
     577             :   //
     578             :   // However, we don't actually have the information at this point to
     579             :   // tell whether the content-box size has changed, since both style
     580             :   // data and the UsedPaddingProperty() have already been updated.  So,
     581             :   // instead, we explicitly check for the case where it's possible for
     582             :   // the content-box size to have changed without either (a) a change in
     583             :   // the border-box size or (b) an nsChangeHint_NeedDirtyReflow change
     584             :   // hint due to change in border or padding.  Thus we test using the
     585             :   // conditions from the previous paragraph, except without testing (1)
     586             :   // since it's complicated to test properly and less likely to help
     587             :   // with optimizing cases away.
     588             :   bool isIResize =
     589             :     // is the border-box resizing?
     590        1009 :     mFrame->ISize(wm) !=
     591        5045 :       ComputedISize() + ComputedLogicalBorderPadding().IStartEnd(wm) ||
     592             :     // or is the content-box resizing?  (see comment above)
     593         741 :     (mStylePosition->mBoxSizing != StyleBoxSizing::Content &&
     594        1196 :      mStylePadding->IsWidthDependent());
     595             : 
     596        1461 :   if ((mFrame->GetStateBits() & NS_FRAME_FONT_INFLATION_FLOW_ROOT) &&
     597         452 :       nsLayoutUtils::FontSizeInflationEnabled(aPresContext)) {
     598             :     // Create our font inflation data if we don't have it already, and
     599             :     // give it our current width information.
     600           0 :     bool dirty = nsFontInflationData::UpdateFontInflationDataISizeFor(*this) &&
     601             :                  // Avoid running this at the box-to-block interface
     602             :                  // (where we shouldn't be inflating anyway, and where
     603             :                  // reflow state construction is probably to construct a
     604             :                  // dummy parent reflow state anyway).
     605           0 :                  !mFlags.mDummyParentReflowInput;
     606             : 
     607           0 :     if (dirty || (!mFrame->GetParent() && isIResize)) {
     608             :       // When font size inflation is enabled, a change in either:
     609             :       //  * the effective width of a font inflation flow root
     610             :       //  * the width of the frame
     611             :       // needs to cause a dirty reflow since they change the font size
     612             :       // inflation calculations, which in turn change the size of text,
     613             :       // line-heights, etc.  This is relatively similar to a classic
     614             :       // case of style change reflow, except that because inflation
     615             :       // doesn't affect the intrinsic sizing codepath, there's no need
     616             :       // to invalidate intrinsic sizes.
     617             :       //
     618             :       // Note that this makes horizontal resizing a good bit more
     619             :       // expensive.  However, font size inflation is targeted at a set of
     620             :       // devices (zoom-and-pan devices) where the main use case for
     621             :       // horizontal resizing needing to be efficient (window resizing) is
     622             :       // not present.  It does still increase the cost of dynamic changes
     623             :       // caused by script where a style or content change in one place
     624             :       // causes a resize in another (e.g., rebalancing a table).
     625             : 
     626             :       // FIXME: This isn't so great for the cases where
     627             :       // ReflowInput::SetComputedWidth is called, if the first time
     628             :       // we go through InitResizeFlags we set IsHResize() to true, and then
     629             :       // the second time we'd set it to false even without the
     630             :       // NS_FRAME_IS_DIRTY bit already set.
     631           0 :       if (mFrame->IsSVGForeignObjectFrame()) {
     632             :         // Foreign object frames use dirty bits in a special way.
     633           0 :         mFrame->AddStateBits(NS_FRAME_HAS_DIRTY_CHILDREN);
     634           0 :         nsIFrame *kid = mFrame->PrincipalChildList().FirstChild();
     635           0 :         if (kid) {
     636           0 :           kid->AddStateBits(NS_FRAME_IS_DIRTY);
     637             :         }
     638             :       } else {
     639           0 :         mFrame->AddStateBits(NS_FRAME_IS_DIRTY);
     640             :       }
     641             : 
     642             :       // Mark intrinsic widths on all descendants dirty.  We need to do
     643             :       // this (1) since we're changing the size of text and need to
     644             :       // clear text runs on text frames and (2) since we actually are
     645             :       // changing some intrinsic widths, but only those that live inside
     646             :       // of containers.
     647             : 
     648             :       // It makes sense to do this for descendants but not ancestors
     649             :       // (which is unusual) because we're only changing the unusual
     650             :       // inflation-dependent intrinsic widths (i.e., ones computed with
     651             :       // nsPresContext::mInflationDisabledForShrinkWrap set to false),
     652             :       // which should never affect anything outside of their inflation
     653             :       // flow root (or, for that matter, even their inflation
     654             :       // container).
     655             : 
     656             :       // This is also different from what PresShell::FrameNeedsReflow
     657             :       // does because it doesn't go through placeholders.  It doesn't
     658             :       // need to because we're actually doing something that cares about
     659             :       // frame tree geometry (the width on an ancestor) rather than
     660             :       // style.
     661             : 
     662           0 :       AutoTArray<nsIFrame*, 32> stack;
     663           0 :       stack.AppendElement(mFrame);
     664             : 
     665           0 :       do {
     666           0 :         nsIFrame *f = stack.ElementAt(stack.Length() - 1);
     667           0 :         stack.RemoveElementAt(stack.Length() - 1);
     668             : 
     669           0 :         nsIFrame::ChildListIterator lists(f);
     670           0 :         for (; !lists.IsDone(); lists.Next()) {
     671           0 :           nsFrameList::Enumerator childFrames(lists.CurrentList());
     672           0 :           for (; !childFrames.AtEnd(); childFrames.Next()) {
     673           0 :             nsIFrame* kid = childFrames.get();
     674           0 :             kid->MarkIntrinsicISizesDirty();
     675           0 :             stack.AppendElement(kid);
     676             :           }
     677             :         }
     678           0 :       } while (stack.Length() != 0);
     679             :     }
     680             :   }
     681             : 
     682        1009 :   SetIResize(!(mFrame->GetStateBits() & NS_FRAME_IS_DIRTY) &&
     683        1009 :              isIResize);
     684             : 
     685             :   // XXX Should we really need to null check mCBReflowInput?  (We do for
     686             :   // at least nsBoxFrame).
     687        2018 :   if (IS_TABLE_CELL(aFrameType) &&
     688           0 :       (mFlags.mSpecialBSizeReflow ||
     689           0 :        (mFrame->FirstInFlow()->GetStateBits() &
     690        1009 :          NS_TABLE_CELL_HAD_SPECIAL_REFLOW)) &&
     691           0 :       (mFrame->GetStateBits() & NS_FRAME_CONTAINS_RELATIVE_BSIZE)) {
     692             :     // Need to set the bit on the cell so that
     693             :     // mCBReflowInput->IsBResize() is set correctly below when
     694             :     // reflowing descendant.
     695           0 :     SetBResize(true);
     696        1009 :   } else if (mCBReflowInput && mFrame->IsBlockWrapper()) {
     697             :     // XXX Is this problematic for relatively positioned inlines acting
     698             :     // as containing block for absolutely positioned elements?
     699             :     // Possibly; in that case we should at least be checking
     700             :     // NS_SUBTREE_DIRTY, I'd think.
     701           0 :     SetBResize(mCBReflowInput->IsBResizeForWM(wm));
     702        1009 :   } else if (mCBReflowInput && !nsLayoutUtils::GetAsBlock(mFrame)) {
     703             :     // Some non-block frames (e.g. table frames) aggressively optimize out their
     704             :     // BSize recomputation when they don't have the BResize flag set.  This
     705             :     // means that if they go from having a computed non-auto height to having an
     706             :     // auto height and don't have that flag set, they will not actually compute
     707             :     // their auto height and will just remain at whatever size they already
     708             :     // were.  We can end up in that situation if the child has a percentage
     709             :     // specified height and the parent changes from non-auto height to auto
     710             :     // height.  When that happens, the parent will typically have the BResize
     711             :     // flag set, and we want to propagate that flag to the kid.
     712             :     //
     713             :     // Ideally it seems like we'd do this for blocks too, of course... but we'd
     714             :     // really want to restrict it to the percentage height case or something, to
     715             :     // avoid extra reflows in common cases.  Maybe we should be examining
     716             :     // mStylePosition->BSize(wm).GetUnit() for that purpose?
     717             :     //
     718             :     // Note that we _also_ need to set the BResize flag if we have auto
     719             :     // ComputedBSize() and a dirty subtree, since that might require us to
     720             :     // change BSize due to kids having been added or removed.
     721         531 :     SetBResize(mCBReflowInput->IsBResizeForWM(wm));
     722         531 :     if (ComputedBSize() == NS_AUTOHEIGHT) {
     723         298 :       SetBResize(IsBResize() || NS_SUBTREE_DIRTY(mFrame));
     724             :     }
     725         478 :   } else if (ComputedBSize() == NS_AUTOHEIGHT) {
     726         309 :     if (eCompatibility_NavQuirks == aPresContext->CompatibilityMode() &&
     727          26 :         mCBReflowInput) {
     728          18 :       SetBResize(mCBReflowInput->IsBResizeForWM(wm));
     729             :     } else {
     730         265 :       SetBResize(IsIResize());
     731             :     }
     732         283 :     SetBResize(IsBResize() || NS_SUBTREE_DIRTY(mFrame));
     733             :   } else {
     734             :     // not 'auto' block-size
     735         390 :     SetBResize(mFrame->BSize(wm) !=
     736         390 :                ComputedBSize() + ComputedLogicalBorderPadding().BStartEnd(wm));
     737             :   }
     738             : 
     739             :   bool dependsOnCBBSize =
     740        1958 :     (mStylePosition->BSizeDependsOnContainer(wm) &&
     741             :      // FIXME: condition this on not-abspos?
     742        1950 :      mStylePosition->BSize(wm).GetUnit() != eStyleUnit_Auto) ||
     743        2002 :     mStylePosition->MinBSizeDependsOnContainer(wm) ||
     744        2002 :     mStylePosition->MaxBSizeDependsOnContainer(wm) ||
     745        2000 :     mStylePosition->OffsetHasPercent(wm.PhysicalSide(eLogicalSideBStart)) ||
     746        3007 :     mStylePosition->mOffset.GetBEndUnit(wm) != eStyleUnit_Auto ||
     747        2008 :     mFrame->IsXULBoxFrame();
     748             : 
     749        1009 :   if (mStyleText->mLineHeight.GetUnit() == eStyleUnit_Enumerated) {
     750         189 :     NS_ASSERTION(mStyleText->mLineHeight.GetIntValue() ==
     751             :                  NS_STYLE_LINE_HEIGHT_BLOCK_HEIGHT,
     752             :                  "bad line-height value");
     753             : 
     754             :     // line-height depends on block bsize
     755         189 :     mFrame->AddStateBits(NS_FRAME_CONTAINS_RELATIVE_BSIZE);
     756             :     // but only on containing blocks if this frame is not a suitable block
     757         189 :     dependsOnCBBSize |= !nsLayoutUtils::IsNonWrapperBlock(mFrame);
     758             :   }
     759             : 
     760             :   // If we're the descendant of a table cell that performs special bsize
     761             :   // reflows and we could be the child that requires them, always set
     762             :   // the block-axis resize in case this is the first pass before the
     763             :   // special bsize reflow.  However, don't do this if it actually is
     764             :   // the special bsize reflow, since in that case it will already be
     765             :   // set correctly above if we need it set.
     766        2573 :   if (!IsBResize() && mCBReflowInput &&
     767         460 :       (IS_TABLE_CELL(mCBReflowInput->mFrame->Type()) ||
     768         230 :        mCBReflowInput->mFlags.mHeightDependsOnAncestorCell) &&
     769        1009 :       !mCBReflowInput->mFlags.mSpecialBSizeReflow &&
     770             :       dependsOnCBBSize) {
     771           0 :     SetBResize(true);
     772           0 :     mFlags.mHeightDependsOnAncestorCell = true;
     773             :   }
     774             : 
     775             :   // Set NS_FRAME_CONTAINS_RELATIVE_BSIZE if it's needed.
     776             : 
     777             :   // It would be nice to check that |ComputedBSize != NS_AUTOHEIGHT|
     778             :   // &&ed with the percentage bsize check.  However, this doesn't get
     779             :   // along with table special bsize reflows, since a special bsize
     780             :   // reflow (a quirk that makes such percentage height work on children
     781             :   // of table cells) can cause not just a single percentage height to
     782             :   // become fixed, but an entire descendant chain of percentage height
     783             :   // to become fixed.
     784        1009 :   if (dependsOnCBBSize && mCBReflowInput) {
     785         189 :     const ReflowInput *rs = this;
     786         189 :     bool hitCBReflowInput = false;
     787          29 :     do {
     788         189 :       rs = rs->mParentReflowInput;
     789         189 :       if (!rs) {
     790           0 :         break;
     791             :       }
     792             : 
     793         189 :       if (rs->mFrame->GetStateBits() & NS_FRAME_CONTAINS_RELATIVE_BSIZE)
     794         160 :         break; // no need to go further
     795          29 :       rs->mFrame->AddStateBits(NS_FRAME_CONTAINS_RELATIVE_BSIZE);
     796             : 
     797             :       // Keep track of whether we've hit the containing block, because
     798             :       // we need to go at least that far.
     799          29 :       if (rs == mCBReflowInput) {
     800          29 :         hitCBReflowInput = true;
     801             :       }
     802             : 
     803             :       // XXX What about orthogonal flows? It doesn't make sense to
     804             :       // keep propagating this bit across an orthogonal boundary,
     805             :       // where the meaning of BSize changes. Bug 1175517.
     806          58 :     } while (!hitCBReflowInput ||
     807          29 :              (eCompatibility_NavQuirks == aPresContext->CompatibilityMode() &&
     808           0 :               !IsQuirkContainingBlockHeight(rs, rs->mFrame->Type())));
     809             :     // Note: We actually don't need to set the
     810             :     // NS_FRAME_CONTAINS_RELATIVE_BSIZE bit for the cases
     811             :     // where we hit the early break statements in
     812             :     // CalcQuirkContainingBlockHeight. But it doesn't hurt
     813             :     // us to set the bit in these cases.
     814             : 
     815             :   }
     816        1009 :   if (mFrame->GetStateBits() & NS_FRAME_IS_DIRTY) {
     817             :     // If we're reflowing everything, then we'll find out if we need
     818             :     // to re-set this.
     819         482 :     mFrame->RemoveStateBits(NS_FRAME_CONTAINS_RELATIVE_BSIZE);
     820             :   }
     821        1009 : }
     822             : 
     823             : nscoord
     824           0 : ReflowInput::GetContainingBlockContentISize(WritingMode aWritingMode) const
     825             : {
     826           0 :   if (!mCBReflowInput) {
     827           0 :     return 0;
     828             :   }
     829           0 :   return mCBReflowInput->GetWritingMode().IsOrthogonalTo(aWritingMode)
     830           0 :     ? mCBReflowInput->ComputedBSize()
     831           0 :     : mCBReflowInput->ComputedISize();
     832             : }
     833             : 
     834             : void
     835         652 : ReflowInput::InitFrameType(LayoutFrameType aFrameType)
     836             : {
     837         652 :   const nsStyleDisplay *disp = mStyleDisplay;
     838             :   nsCSSFrameType frameType;
     839             : 
     840             :   // Section 9.7 of the CSS2 spec indicates that absolute position
     841             :   // takes precedence over float which takes precedence over display.
     842             :   // XXXldb nsRuleNode::ComputeDisplayData should take care of this, right?
     843             :   // Make sure the frame was actually moved out of the flow, and don't
     844             :   // just assume what the style says, because we might not have had a
     845             :   // useful float/absolute containing block
     846             : 
     847        1304 :   DISPLAY_INIT_TYPE(mFrame, this);
     848             : 
     849         652 :   if (aFrameType == LayoutFrameType::Table) {
     850           0 :     mFrameType = NS_CSS_FRAME_TYPE_BLOCK;
     851           0 :     return;
     852             :   }
     853             : 
     854         652 :   NS_ASSERTION(mFrame->StyleDisplay()->IsAbsolutelyPositionedStyle() ==
     855             :                  disp->IsAbsolutelyPositionedStyle(),
     856             :                "Unexpected position style");
     857         652 :   NS_ASSERTION(mFrame->StyleDisplay()->IsFloatingStyle() ==
     858             :                  disp->IsFloatingStyle(), "Unexpected float style");
     859         652 :   if (mFrame->GetStateBits() & NS_FRAME_OUT_OF_FLOW) {
     860          77 :     if (disp->IsAbsolutelyPositioned(mFrame)) {
     861          77 :       frameType = NS_CSS_FRAME_TYPE_ABSOLUTE;
     862             :       //XXXfr hack for making frames behave properly when in overflow container lists
     863             :       //      see bug 154892; need to revisit later
     864          77 :       if (mFrame->GetPrevInFlow())
     865           0 :         frameType = NS_CSS_FRAME_TYPE_BLOCK;
     866             :     }
     867           0 :     else if (disp->IsFloating(mFrame)) {
     868           0 :       frameType = NS_CSS_FRAME_TYPE_FLOATING;
     869             :     } else {
     870           0 :       NS_ASSERTION(disp->mDisplay == StyleDisplay::MozPopup,
     871             :                    "unknown out of flow frame type");
     872           0 :       frameType = NS_CSS_FRAME_TYPE_UNKNOWN;
     873             :     }
     874             :   }
     875             :   else {
     876         575 :     switch (GetDisplay()) {
     877             :     case StyleDisplay::Block:
     878             :     case StyleDisplay::ListItem:
     879             :     case StyleDisplay::Table:
     880             :     case StyleDisplay::TableCaption:
     881             :     case StyleDisplay::Flex:
     882             :     case StyleDisplay::WebkitBox:
     883             :     case StyleDisplay::Grid:
     884             :     case StyleDisplay::FlowRoot:
     885             :     case StyleDisplay::RubyTextContainer:
     886         358 :       frameType = NS_CSS_FRAME_TYPE_BLOCK;
     887         358 :       break;
     888             : 
     889             :     case StyleDisplay::Inline:
     890             :     case StyleDisplay::InlineBlock:
     891             :     case StyleDisplay::InlineTable:
     892             :     case StyleDisplay::MozInlineBox:
     893             :     case StyleDisplay::MozInlineGrid:
     894             :     case StyleDisplay::MozInlineStack:
     895             :     case StyleDisplay::InlineFlex:
     896             :     case StyleDisplay::WebkitInlineBox:
     897             :     case StyleDisplay::InlineGrid:
     898             :     case StyleDisplay::Ruby:
     899             :     case StyleDisplay::RubyBase:
     900             :     case StyleDisplay::RubyText:
     901             :     case StyleDisplay::RubyBaseContainer:
     902          71 :       frameType = NS_CSS_FRAME_TYPE_INLINE;
     903          71 :       break;
     904             : 
     905             :     case StyleDisplay::TableCell:
     906             :     case StyleDisplay::TableRowGroup:
     907             :     case StyleDisplay::TableColumn:
     908             :     case StyleDisplay::TableColumnGroup:
     909             :     case StyleDisplay::TableHeaderGroup:
     910             :     case StyleDisplay::TableFooterGroup:
     911             :     case StyleDisplay::TableRow:
     912           0 :       frameType = NS_CSS_FRAME_TYPE_INTERNAL_TABLE;
     913           0 :       break;
     914             : 
     915             :     case StyleDisplay::None:
     916             :     default:
     917         146 :       frameType = NS_CSS_FRAME_TYPE_UNKNOWN;
     918         146 :       break;
     919             :     }
     920             :   }
     921             : 
     922             :   // See if the frame is replaced
     923         652 :   if (mFrame->IsFrameOfType(nsIFrame::eReplacedContainsBlock)) {
     924         166 :     frameType = NS_FRAME_REPLACED_CONTAINS_BLOCK(frameType);
     925         486 :   } else if (mFrame->IsFrameOfType(nsIFrame::eReplaced)) {
     926           9 :     frameType = NS_FRAME_REPLACED(frameType);
     927             :   }
     928             : 
     929         652 :   mFrameType = frameType;
     930             : }
     931             : 
     932             : /* static */ void
     933           0 : ReflowInput::ComputeRelativeOffsets(WritingMode aWM,
     934             :                                           nsIFrame* aFrame,
     935             :                                           const LogicalSize& aCBSize,
     936             :                                           nsMargin& aComputedOffsets)
     937             : {
     938           0 :   LogicalMargin offsets(aWM);
     939           0 :   mozilla::Side inlineStart = aWM.PhysicalSide(eLogicalSideIStart);
     940           0 :   mozilla::Side inlineEnd   = aWM.PhysicalSide(eLogicalSideIEnd);
     941           0 :   mozilla::Side blockStart  = aWM.PhysicalSide(eLogicalSideBStart);
     942           0 :   mozilla::Side blockEnd    = aWM.PhysicalSide(eLogicalSideBEnd);
     943             : 
     944           0 :   const nsStylePosition* position = aFrame->StylePosition();
     945             : 
     946             :   // Compute the 'inlineStart' and 'inlineEnd' values. 'inlineStart'
     947             :   // moves the boxes to the end of the line, and 'inlineEnd' moves the
     948             :   // boxes to the start of the line. The computed values are always:
     949             :   // inlineStart=-inlineEnd
     950             :   bool inlineStartIsAuto =
     951           0 :     eStyleUnit_Auto == position->mOffset.GetUnit(inlineStart);
     952             :   bool inlineEndIsAuto =
     953           0 :     eStyleUnit_Auto == position->mOffset.GetUnit(inlineEnd);
     954             : 
     955             :   // If neither 'inlineStart' nor 'inlineEnd' is auto, then we're
     956             :   // over-constrained and we ignore one of them
     957           0 :   if (!inlineStartIsAuto && !inlineEndIsAuto) {
     958           0 :     inlineEndIsAuto = true;
     959             :   }
     960             : 
     961           0 :   if (inlineStartIsAuto) {
     962           0 :     if (inlineEndIsAuto) {
     963             :       // If both are 'auto' (their initial values), the computed values are 0
     964           0 :       offsets.IStart(aWM) = offsets.IEnd(aWM) = 0;
     965             :     } else {
     966             :       // 'inlineEnd' isn't 'auto' so compute its value
     967           0 :       offsets.IEnd(aWM) = nsLayoutUtils::
     968           0 :         ComputeCBDependentValue(aCBSize.ISize(aWM),
     969           0 :                                 position->mOffset.Get(inlineEnd));
     970             : 
     971             :       // Computed value for 'inlineStart' is minus the value of 'inlineEnd'
     972           0 :       offsets.IStart(aWM) = -offsets.IEnd(aWM);
     973             :     }
     974             : 
     975             :   } else {
     976           0 :     NS_ASSERTION(inlineEndIsAuto, "unexpected specified constraint");
     977             : 
     978             :     // 'InlineStart' isn't 'auto' so compute its value
     979           0 :     offsets.IStart(aWM) = nsLayoutUtils::
     980           0 :       ComputeCBDependentValue(aCBSize.ISize(aWM),
     981           0 :                               position->mOffset.Get(inlineStart));
     982             : 
     983             :     // Computed value for 'inlineEnd' is minus the value of 'inlineStart'
     984           0 :     offsets.IEnd(aWM) = -offsets.IStart(aWM);
     985             :   }
     986             : 
     987             :   // Compute the 'blockStart' and 'blockEnd' values. The 'blockStart'
     988             :   // and 'blockEnd' properties move relatively positioned elements in
     989             :   // the block progression direction. They also must be each other's
     990             :   // negative
     991             :   bool blockStartIsAuto =
     992           0 :     eStyleUnit_Auto == position->mOffset.GetUnit(blockStart);
     993             :   bool blockEndIsAuto =
     994           0 :     eStyleUnit_Auto == position->mOffset.GetUnit(blockEnd);
     995             : 
     996             :   // Check for percentage based values and a containing block block-size
     997             :   // that depends on the content block-size. Treat them like 'auto'
     998           0 :   if (NS_AUTOHEIGHT == aCBSize.BSize(aWM)) {
     999           0 :     if (position->OffsetHasPercent(blockStart)) {
    1000           0 :       blockStartIsAuto = true;
    1001             :     }
    1002           0 :     if (position->OffsetHasPercent(blockEnd)) {
    1003           0 :       blockEndIsAuto = true;
    1004             :     }
    1005             :   }
    1006             : 
    1007             :   // If neither is 'auto', 'block-end' is ignored
    1008           0 :   if (!blockStartIsAuto && !blockEndIsAuto) {
    1009           0 :     blockEndIsAuto = true;
    1010             :   }
    1011             : 
    1012           0 :   if (blockStartIsAuto) {
    1013           0 :     if (blockEndIsAuto) {
    1014             :       // If both are 'auto' (their initial values), the computed values are 0
    1015           0 :       offsets.BStart(aWM) = offsets.BEnd(aWM) = 0;
    1016             :     } else {
    1017             :       // 'blockEnd' isn't 'auto' so compute its value
    1018           0 :       offsets.BEnd(aWM) = nsLayoutUtils::
    1019           0 :         ComputeBSizeDependentValue(aCBSize.BSize(aWM),
    1020           0 :                                    position->mOffset.Get(blockEnd));
    1021             : 
    1022             :       // Computed value for 'blockStart' is minus the value of 'blockEnd'
    1023           0 :       offsets.BStart(aWM) = -offsets.BEnd(aWM);
    1024             :     }
    1025             : 
    1026             :   } else {
    1027           0 :     NS_ASSERTION(blockEndIsAuto, "unexpected specified constraint");
    1028             : 
    1029             :     // 'blockStart' isn't 'auto' so compute its value
    1030           0 :     offsets.BStart(aWM) = nsLayoutUtils::
    1031           0 :       ComputeBSizeDependentValue(aCBSize.BSize(aWM),
    1032           0 :                                  position->mOffset.Get(blockStart));
    1033             : 
    1034             :     // Computed value for 'blockEnd' is minus the value of 'blockStart'
    1035           0 :     offsets.BEnd(aWM) = -offsets.BStart(aWM);
    1036             :   }
    1037             : 
    1038             :   // Convert the offsets to physical coordinates and store them on the frame
    1039           0 :   aComputedOffsets = offsets.GetPhysicalMargin(aWM);
    1040             :   nsMargin* physicalOffsets =
    1041           0 :     aFrame->GetProperty(nsIFrame::ComputedOffsetProperty());
    1042           0 :   if (physicalOffsets) {
    1043           0 :     *physicalOffsets = aComputedOffsets;
    1044             :   } else {
    1045           0 :     aFrame->AddProperty(nsIFrame::ComputedOffsetProperty(),
    1046           0 :                         new nsMargin(aComputedOffsets));
    1047             :   }
    1048           0 : }
    1049             : 
    1050             : /* static */ void
    1051          55 : ReflowInput::ApplyRelativePositioning(nsIFrame* aFrame,
    1052             :                                             const nsMargin& aComputedOffsets,
    1053             :                                             nsPoint* aPosition)
    1054             : {
    1055          55 :   if (!aFrame->IsRelativelyPositioned()) {
    1056          55 :     NS_ASSERTION(!aFrame->GetProperty(nsIFrame::NormalPositionProperty()),
    1057             :                  "We assume that changing the 'position' property causes "
    1058             :                  "frame reconstruction.  If that ever changes, this code "
    1059             :                  "should call "
    1060             :                  "aFrame->DeleteProperty(nsIFrame::NormalPositionProperty())");
    1061          55 :     return;
    1062             :   }
    1063             : 
    1064             :   // Store the normal position
    1065             :   nsPoint* normalPosition =
    1066           0 :     aFrame->GetProperty(nsIFrame::NormalPositionProperty());
    1067           0 :   if (normalPosition) {
    1068           0 :     *normalPosition = *aPosition;
    1069             :   } else {
    1070           0 :     aFrame->AddProperty(nsIFrame::NormalPositionProperty(),
    1071           0 :                         new nsPoint(*aPosition));
    1072             :   }
    1073             : 
    1074           0 :   const nsStyleDisplay* display = aFrame->StyleDisplay();
    1075           0 :   if (NS_STYLE_POSITION_RELATIVE == display->mPosition) {
    1076           0 :     *aPosition += nsPoint(aComputedOffsets.left, aComputedOffsets.top);
    1077           0 :   } else if (NS_STYLE_POSITION_STICKY == display->mPosition &&
    1078           0 :              !aFrame->GetNextContinuation() &&
    1079           0 :              !aFrame->GetPrevContinuation() &&
    1080           0 :              !(aFrame->GetStateBits() & NS_FRAME_PART_OF_IBSPLIT)) {
    1081             :     // Sticky positioning for elements with multiple frames needs to be
    1082             :     // computed all at once. We can't safely do that here because we might be
    1083             :     // partway through (re)positioning the frames, so leave it until the scroll
    1084             :     // container reflows and calls StickyScrollContainer::UpdatePositions.
    1085             :     // For single-frame sticky positioned elements, though, go ahead and apply
    1086             :     // it now to avoid unnecessary overflow updates later.
    1087             :     StickyScrollContainer* ssc =
    1088           0 :       StickyScrollContainer::GetStickyScrollContainerForFrame(aFrame);
    1089           0 :     if (ssc) {
    1090           0 :       *aPosition = ssc->ComputePosition(aFrame);
    1091             :     }
    1092             :   }
    1093             : }
    1094             : 
    1095             : nsIFrame*
    1096          77 : ReflowInput::GetHypotheticalBoxContainer(nsIFrame*    aFrame,
    1097             :                                                nscoord&     aCBIStartEdge,
    1098             :                                                LogicalSize& aCBSize) const
    1099             : {
    1100          77 :   aFrame = aFrame->GetContainingBlock();
    1101          77 :   NS_ASSERTION(aFrame != mFrame, "How did that happen?");
    1102             : 
    1103             :   /* Now aFrame is the containing block we want */
    1104             : 
    1105             :   /* Check whether the containing block is currently being reflowed.
    1106             :      If so, use the info from the reflow state. */
    1107             :   const ReflowInput* state;
    1108          77 :   if (aFrame->GetStateBits() & NS_FRAME_IN_REFLOW) {
    1109           0 :     for (state = mParentReflowInput; state && state->mFrame != aFrame;
    1110           0 :          state = state->mParentReflowInput) {
    1111             :       /* do nothing */
    1112             :     }
    1113             :   } else {
    1114          77 :     state = nullptr;
    1115             :   }
    1116             : 
    1117          77 :   if (state) {
    1118           0 :     WritingMode wm = state->GetWritingMode();
    1119           0 :     NS_ASSERTION(wm == aFrame->GetWritingMode(), "unexpected writing mode");
    1120           0 :     aCBIStartEdge = state->ComputedLogicalBorderPadding().IStart(wm);
    1121           0 :     aCBSize = state->ComputedSize(wm);
    1122             :   } else {
    1123             :     /* Didn't find a reflow state for aFrame.  Just compute the information we
    1124             :        want, on the assumption that aFrame already knows its size.  This really
    1125             :        ought to be true by now. */
    1126          77 :     NS_ASSERTION(!(aFrame->GetStateBits() & NS_FRAME_IN_REFLOW),
    1127             :                  "aFrame shouldn't be in reflow; we'll lie if it is");
    1128          77 :     WritingMode wm = aFrame->GetWritingMode();
    1129          77 :     LogicalMargin borderPadding = aFrame->GetLogicalUsedBorderAndPadding(wm);
    1130          77 :     aCBIStartEdge = borderPadding.IStart(wm);
    1131          77 :     aCBSize = aFrame->GetLogicalSize(wm) - borderPadding.Size(wm);
    1132             :   }
    1133             : 
    1134          77 :   return aFrame;
    1135             : }
    1136             : 
    1137          77 : struct nsHypotheticalPosition {
    1138             :   // offset from inline-start edge of containing block (which is a padding edge)
    1139             :   nscoord       mIStart;
    1140             :   // offset from block-start edge of containing block (which is a padding edge)
    1141             :   nscoord       mBStart;
    1142             :   WritingMode   mWritingMode;
    1143             : };
    1144             : 
    1145             : static bool
    1146           0 : GetIntrinsicSizeFor(nsIFrame* aFrame,
    1147             :                     nsSize& aIntrinsicSize,
    1148             :                     LayoutFrameType aFrameType)
    1149             : {
    1150             :   // See if it is an image frame
    1151           0 :   bool success = false;
    1152             : 
    1153             :   // Currently the only type of replaced frame that we can get the intrinsic
    1154             :   // size for is an image frame
    1155             :   // XXX We should add back the GetReflowOutput() function and one of the
    1156             :   // things should be the intrinsic size...
    1157           0 :   if (aFrameType == LayoutFrameType::Image) {
    1158           0 :     nsImageFrame* imageFrame = (nsImageFrame*)aFrame;
    1159             : 
    1160           0 :     if (NS_SUCCEEDED(imageFrame->GetIntrinsicImageSize(aIntrinsicSize))) {
    1161           0 :       success = (aIntrinsicSize != nsSize(0, 0));
    1162             :     }
    1163             :   }
    1164           0 :   return success;
    1165             : }
    1166             : 
    1167             : /**
    1168             :  * aInsideBoxSizing returns the part of the padding, border, and margin
    1169             :  * in the aAxis dimension that goes inside the edge given by box-sizing;
    1170             :  * aOutsideBoxSizing returns the rest.
    1171             :  */
    1172             : void
    1173          77 : ReflowInput::CalculateBorderPaddingMargin(
    1174             :                        LogicalAxis aAxis,
    1175             :                        nscoord aContainingBlockSize,
    1176             :                        nscoord* aInsideBoxSizing,
    1177             :                        nscoord* aOutsideBoxSizing) const
    1178             : {
    1179          77 :   WritingMode wm = GetWritingMode();
    1180             :   mozilla::Side startSide =
    1181          77 :     wm.PhysicalSide(MakeLogicalSide(aAxis, eLogicalEdgeStart));
    1182             :   mozilla::Side endSide =
    1183          77 :     wm.PhysicalSide(MakeLogicalSide(aAxis, eLogicalEdgeEnd));
    1184             : 
    1185          77 :   nsMargin styleBorder = mStyleBorder->GetComputedBorder();
    1186             :   nscoord borderStartEnd =
    1187          77 :     styleBorder.Side(startSide) + styleBorder.Side(endSide);
    1188             : 
    1189             :   nscoord paddingStartEnd, marginStartEnd;
    1190             : 
    1191             :   // See if the style system can provide us the padding directly
    1192          77 :   nsMargin stylePadding;
    1193          77 :   if (mStylePadding->GetPadding(stylePadding)) {
    1194          77 :     paddingStartEnd =
    1195          77 :       stylePadding.Side(startSide) + stylePadding.Side(endSide);
    1196             :   } else {
    1197             :     // We have to compute the start and end values
    1198             :     nscoord start, end;
    1199             :     start = nsLayoutUtils::
    1200             :       ComputeCBDependentValue(aContainingBlockSize,
    1201           0 :                               mStylePadding->mPadding.Get(startSide));
    1202             :     end = nsLayoutUtils::
    1203             :       ComputeCBDependentValue(aContainingBlockSize,
    1204           0 :                               mStylePadding->mPadding.Get(endSide));
    1205           0 :     paddingStartEnd = start + end;
    1206             :   }
    1207             : 
    1208             :   // See if the style system can provide us the margin directly
    1209          77 :   nsMargin styleMargin;
    1210          77 :   if (mStyleMargin->GetMargin(styleMargin)) {
    1211          77 :     marginStartEnd =
    1212          77 :       styleMargin.Side(startSide) + styleMargin.Side(endSide);
    1213             :   } else {
    1214             :     nscoord start, end;
    1215             :     // We have to compute the start and end values
    1216           0 :     if (eStyleUnit_Auto == mStyleMargin->mMargin.GetUnit(startSide)) {
    1217             :       // XXX FIXME (or does CalculateBlockSideMargins do this?)
    1218           0 :       start = 0;  // just ignore
    1219             :     } else {
    1220             :       start = nsLayoutUtils::
    1221             :         ComputeCBDependentValue(aContainingBlockSize,
    1222           0 :                                 mStyleMargin->mMargin.Get(startSide));
    1223             :     }
    1224           0 :     if (eStyleUnit_Auto == mStyleMargin->mMargin.GetUnit(endSide)) {
    1225             :       // XXX FIXME (or does CalculateBlockSideMargins do this?)
    1226           0 :       end = 0;  // just ignore
    1227             :     } else {
    1228             :       end = nsLayoutUtils::
    1229             :         ComputeCBDependentValue(aContainingBlockSize,
    1230           0 :                                 mStyleMargin->mMargin.Get(endSide));
    1231             :     }
    1232           0 :     marginStartEnd = start + end;
    1233             :   }
    1234             : 
    1235          77 :   nscoord outside = paddingStartEnd + borderStartEnd + marginStartEnd;
    1236          77 :   nscoord inside = 0;
    1237          77 :   if (mStylePosition->mBoxSizing == StyleBoxSizing::Border) {
    1238          77 :     inside = borderStartEnd + paddingStartEnd;
    1239             :   }
    1240          77 :   outside -= inside;
    1241          77 :   *aInsideBoxSizing = inside;
    1242          77 :   *aOutsideBoxSizing = outside;
    1243          77 :   return;
    1244             : }
    1245             : 
    1246             : /**
    1247             :  * Returns true iff a pre-order traversal of the normal child
    1248             :  * frames rooted at aFrame finds no non-empty frame before aDescendant.
    1249             :  */
    1250             : static bool
    1251           0 : AreAllEarlierInFlowFramesEmpty(nsIFrame* aFrame,
    1252             :                                nsIFrame* aDescendant,
    1253             :                                bool* aFound)
    1254             : {
    1255           0 :   if (aFrame == aDescendant) {
    1256           0 :     *aFound = true;
    1257           0 :     return true;
    1258             :   }
    1259           0 :   if (aFrame->IsPlaceholderFrame()) {
    1260           0 :     auto ph = static_cast<nsPlaceholderFrame*>(aFrame);
    1261           0 :     MOZ_ASSERT(ph->IsSelfEmpty() && ph->PrincipalChildList().IsEmpty());
    1262           0 :     ph->SetLineIsEmptySoFar(true);
    1263             :   } else {
    1264           0 :     if (!aFrame->IsSelfEmpty()) {
    1265           0 :       *aFound = false;
    1266           0 :       return false;
    1267             :     }
    1268           0 :     for (nsIFrame* f : aFrame->PrincipalChildList()) {
    1269           0 :       bool allEmpty = AreAllEarlierInFlowFramesEmpty(f, aDescendant, aFound);
    1270           0 :       if (*aFound || !allEmpty) {
    1271           0 :         return allEmpty;
    1272             :       }
    1273             :     }
    1274             :   }
    1275           0 :   *aFound = false;
    1276           0 :   return true;
    1277             : }
    1278             : 
    1279             : // Calculate the position of the hypothetical box that the element would have
    1280             : // if it were in the flow.
    1281             : // The values returned are relative to the padding edge of the absolute
    1282             : // containing block. The writing-mode of the hypothetical box position will
    1283             : // have the same block direction as the absolute containing block, but may
    1284             : // differ in inline-bidi direction.
    1285             : // In the code below, |cbrs->frame| is the absolute containing block, while
    1286             : // |containingBlock| is the nearest block container of the placeholder frame,
    1287             : // which may be different from the absolute containing block.
    1288             : void
    1289          77 : ReflowInput::CalculateHypotheticalPosition(
    1290             :   nsPresContext* aPresContext,
    1291             :   nsPlaceholderFrame* aPlaceholderFrame,
    1292             :   const ReflowInput* cbrs,
    1293             :   nsHypotheticalPosition& aHypotheticalPos,
    1294             :   LayoutFrameType aFrameType) const
    1295             : {
    1296          77 :   NS_ASSERTION(mStyleDisplay->mOriginalDisplay != StyleDisplay::None,
    1297             :                "mOriginalDisplay has not been properly initialized");
    1298             : 
    1299             :   // Find the nearest containing block frame to the placeholder frame,
    1300             :   // and its inline-start edge and width.
    1301             :   nscoord blockIStartContentEdge;
    1302             :   // Dummy writing mode for blockContentSize, will be changed as needed by
    1303             :   // GetHypotheticalBoxContainer.
    1304          77 :   WritingMode cbwm = cbrs->GetWritingMode();
    1305          77 :   LogicalSize blockContentSize(cbwm);
    1306             :   nsIFrame* containingBlock =
    1307             :     GetHypotheticalBoxContainer(aPlaceholderFrame, blockIStartContentEdge,
    1308          77 :                                 blockContentSize);
    1309             :   // Now blockContentSize is in containingBlock's writing mode.
    1310             : 
    1311             :   // If it's a replaced element and it has a 'auto' value for
    1312             :   //'inline size', see if we can get the intrinsic size. This will allow
    1313             :   // us to exactly determine both the inline edges
    1314          77 :   WritingMode wm = containingBlock->GetWritingMode();
    1315             : 
    1316         154 :   nsStyleCoord styleISize = mStylePosition->ISize(wm);
    1317          77 :   bool isAutoISize = styleISize.GetUnit() == eStyleUnit_Auto;
    1318          77 :   nsSize      intrinsicSize;
    1319          77 :   bool        knowIntrinsicSize = false;
    1320          77 :   if (NS_FRAME_IS_REPLACED(mFrameType) && isAutoISize) {
    1321             :     // See if we can get the intrinsic size of the element
    1322           0 :     knowIntrinsicSize = GetIntrinsicSizeFor(mFrame, intrinsicSize, aFrameType);
    1323             :   }
    1324             : 
    1325             :   // See if we can calculate what the box inline size would have been if
    1326             :   // the element had been in the flow
    1327             :   nscoord boxISize;
    1328          77 :   bool    knowBoxISize = false;
    1329          77 :   if ((StyleDisplay::Inline == mStyleDisplay->mOriginalDisplay) &&
    1330           0 :       !NS_FRAME_IS_REPLACED(mFrameType)) {
    1331             :     // For non-replaced inline-level elements the 'inline size' property
    1332             :     // doesn't apply, so we don't know what the inline size would have
    1333             :     // been without reflowing it
    1334             : 
    1335             :   } else {
    1336             :     // It's either a replaced inline-level element or a block-level element
    1337             : 
    1338             :     // Determine the total amount of inline direction
    1339             :     // border/padding/margin that the element would have had if it had
    1340             :     // been in the flow. Note that we ignore any 'auto' and 'inherit'
    1341             :     // values
    1342             :     nscoord insideBoxSizing, outsideBoxSizing;
    1343          77 :     CalculateBorderPaddingMargin(eLogicalAxisInline,
    1344          77 :                                  blockContentSize.ISize(wm),
    1345          77 :                                  &insideBoxSizing, &outsideBoxSizing);
    1346             : 
    1347          77 :     if (NS_FRAME_IS_REPLACED(mFrameType) && isAutoISize) {
    1348             :       // It's a replaced element with an 'auto' inline size so the box
    1349             :       // inline size is its intrinsic size plus any border/padding/margin
    1350           0 :       if (knowIntrinsicSize) {
    1351           0 :         boxISize = LogicalSize(wm, intrinsicSize).ISize(wm) +
    1352           0 :                    outsideBoxSizing + insideBoxSizing;
    1353           0 :         knowBoxISize = true;
    1354             :       }
    1355             : 
    1356          77 :     } else if (isAutoISize) {
    1357             :       // The box inline size is the containing block inline size
    1358          77 :       boxISize = blockContentSize.ISize(wm);
    1359          77 :       knowBoxISize = true;
    1360             : 
    1361             :     } else {
    1362             :       // We need to compute it. It's important we do this, because if it's
    1363             :       // percentage based this computed value may be different from the computed
    1364             :       // value calculated using the absolute containing block width
    1365           0 :       boxISize = ComputeISizeValue(blockContentSize.ISize(wm),
    1366             :                                    insideBoxSizing, outsideBoxSizing,
    1367           0 :                                    styleISize) +
    1368           0 :                  insideBoxSizing + outsideBoxSizing;
    1369           0 :       knowBoxISize = true;
    1370             :     }
    1371             :   }
    1372             : 
    1373             :   // Get the placeholder x-offset and y-offset in the coordinate
    1374             :   // space of its containing block
    1375             :   // XXXbz the placeholder is not fully reflowed yet if our containing block is
    1376             :   // relatively positioned...
    1377          77 :   nsSize containerSize = containingBlock->GetStateBits() & NS_FRAME_IN_REFLOW
    1378             :     ? cbrs->ComputedSizeAsContainerIfConstrained()
    1379          77 :     : containingBlock->GetSize();
    1380             :   LogicalPoint
    1381         154 :     placeholderOffset(wm, aPlaceholderFrame->GetOffsetTo(containingBlock),
    1382          77 :                       containerSize);
    1383             : 
    1384             :   // First, determine the hypothetical box's mBStart.  We want to check the
    1385             :   // content insertion frame of containingBlock for block-ness, but make
    1386             :   // sure to compute all coordinates in the coordinate system of
    1387             :   // containingBlock.
    1388             :   nsBlockFrame* blockFrame =
    1389          77 :     nsLayoutUtils::GetAsBlock(containingBlock->GetContentInsertionFrame());
    1390          77 :   if (blockFrame) {
    1391             :     // Use a null containerSize to convert a LogicalPoint functioning as a
    1392             :     // vector into a physical nsPoint vector.
    1393           0 :     const nsSize nullContainerSize;
    1394           0 :     LogicalPoint blockOffset(wm, blockFrame->GetOffsetTo(containingBlock),
    1395           0 :                              nullContainerSize);
    1396             :     bool isValid;
    1397           0 :     nsBlockInFlowLineIterator iter(blockFrame, aPlaceholderFrame, &isValid);
    1398           0 :     if (!isValid) {
    1399             :       // Give up.  We're probably dealing with somebody using
    1400             :       // position:absolute inside native-anonymous content anyway.
    1401           0 :       aHypotheticalPos.mBStart = placeholderOffset.B(wm);
    1402             :     } else {
    1403           0 :       NS_ASSERTION(iter.GetContainer() == blockFrame,
    1404             :                    "Found placeholder in wrong block!");
    1405           0 :       nsBlockFrame::LineIterator lineBox = iter.GetLine();
    1406             : 
    1407             :       // How we determine the hypothetical box depends on whether the element
    1408             :       // would have been inline-level or block-level
    1409             :       LogicalRect lineBounds =
    1410           0 :         lineBox->GetBounds().ConvertTo(wm, lineBox->mWritingMode,
    1411           0 :                                        lineBox->mContainerSize);
    1412           0 :       if (mStyleDisplay->IsOriginalDisplayInlineOutsideStyle()) {
    1413             :         // Use the block-start of the inline box which the placeholder lives in
    1414             :         // as the hypothetical box's block-start.
    1415           0 :         aHypotheticalPos.mBStart = lineBounds.BStart(wm) + blockOffset.B(wm);
    1416             :       } else {
    1417             :         // The element would have been block-level which means it would
    1418             :         // be below the line containing the placeholder frame, unless
    1419             :         // all the frames before it are empty.  In that case, it would
    1420             :         // have been just before this line.
    1421             :         // XXXbz the line box is not fully reflowed yet if our
    1422             :         // containing block is relatively positioned...
    1423           0 :         if (lineBox != iter.End()) {
    1424           0 :           nsIFrame* firstFrame = lineBox->mFirstChild;
    1425           0 :           bool allEmpty = false;
    1426           0 :           if (firstFrame == aPlaceholderFrame) {
    1427           0 :             aPlaceholderFrame->SetLineIsEmptySoFar(true);
    1428           0 :             allEmpty = true;
    1429             :           } else {
    1430           0 :             auto prev = aPlaceholderFrame->GetPrevSibling();
    1431           0 :             if (prev && prev->IsPlaceholderFrame()) {
    1432           0 :               auto ph = static_cast<nsPlaceholderFrame*>(prev);
    1433           0 :               if (ph->GetLineIsEmptySoFar(&allEmpty)) {
    1434           0 :                 aPlaceholderFrame->SetLineIsEmptySoFar(allEmpty);
    1435             :               }
    1436             :             }
    1437             :           }
    1438           0 :           if (!allEmpty) {
    1439           0 :             bool found = false;
    1440           0 :             while (firstFrame) { // See bug 223064
    1441           0 :               allEmpty = AreAllEarlierInFlowFramesEmpty(firstFrame,
    1442             :                 aPlaceholderFrame, &found);
    1443           0 :               if (found || !allEmpty) {
    1444             :                 break;
    1445             :               }
    1446           0 :               firstFrame = firstFrame->GetNextSibling();
    1447             :             }
    1448           0 :             aPlaceholderFrame->SetLineIsEmptySoFar(allEmpty);
    1449             :           }
    1450           0 :           NS_ASSERTION(firstFrame, "Couldn't find placeholder!");
    1451             : 
    1452           0 :           if (allEmpty) {
    1453             :             // The top of the hypothetical box is the top of the line
    1454             :             // containing the placeholder, since there is nothing in the
    1455             :             // line before our placeholder except empty frames.
    1456           0 :             aHypotheticalPos.mBStart =
    1457           0 :               lineBounds.BStart(wm) + blockOffset.B(wm);
    1458             :           } else {
    1459             :             // The top of the hypothetical box is just below the line
    1460             :             // containing the placeholder.
    1461           0 :             aHypotheticalPos.mBStart =
    1462           0 :               lineBounds.BEnd(wm) + blockOffset.B(wm);
    1463             :           }
    1464             :         } else {
    1465             :           // Just use the placeholder's block-offset wrt the containing block
    1466           0 :           aHypotheticalPos.mBStart = placeholderOffset.B(wm);
    1467             :         }
    1468             :       }
    1469             :     }
    1470             :   } else {
    1471             :     // The containing block is not a block, so it's probably something
    1472             :     // like a XUL box, etc.
    1473             :     // Just use the placeholder's block-offset
    1474          77 :     aHypotheticalPos.mBStart = placeholderOffset.B(wm);
    1475             :   }
    1476             : 
    1477             :   // Second, determine the hypothetical box's mIStart.
    1478             :   // How we determine the hypothetical box depends on whether the element
    1479             :   // would have been inline-level or block-level
    1480         154 :   if (mStyleDisplay->IsOriginalDisplayInlineOutsideStyle() ||
    1481          77 :       mFlags.mIOffsetsNeedCSSAlign) {
    1482             :     // The placeholder represents the IStart edge of the hypothetical box.
    1483             :     // (Or if mFlags.mIOffsetsNeedCSSAlign is set, it represents the IStart
    1484             :     // edge of the Alignment Container.)
    1485           0 :     aHypotheticalPos.mIStart = placeholderOffset.I(wm);
    1486             :   } else {
    1487          77 :     aHypotheticalPos.mIStart = blockIStartContentEdge;
    1488             :   }
    1489             : 
    1490             :   // The current coordinate space is that of the nearest block to the placeholder.
    1491             :   // Convert to the coordinate space of the absolute containing block
    1492             :   // One weird thing here is that for fixed-positioned elements we want to do
    1493             :   // the conversion incorrectly; specifically we want to ignore any scrolling
    1494             :   // that may have happened;
    1495          77 :   nsPoint cbOffset;
    1496         154 :   if (mStyleDisplay->mPosition == NS_STYLE_POSITION_FIXED &&
    1497             :       // Exclude cases inside -moz-transform where fixed is like absolute.
    1498          77 :       nsLayoutUtils::IsReallyFixedPos(mFrame)) {
    1499             :     // In this case, cbrs->frame will likely be an ancestor of
    1500             :     // containingBlock, so can just walk our way up the frame tree.
    1501             :     // Make sure to not add positions of frames whose parent is a
    1502             :     // scrollFrame, since we're doing fixed positioning, which assumes
    1503             :     // everything is scrolled to (0,0).
    1504          77 :     cbOffset.MoveTo(0, 0);
    1505         776 :     do {
    1506         853 :       cbOffset += containingBlock->GetPositionIgnoringScrolling();
    1507         853 :       nsContainerFrame* parent = containingBlock->GetParent();
    1508         853 :       if (!parent) {
    1509             :         // Oops, our absolute containing block isn't an ancestor of the
    1510             :         // placeholder's containing block. This can happen if the placeholder
    1511             :         // is pushed to a different page in a printing context.  'cbOffset' is
    1512             :         // currently relative to the root frame (containingBlock) - so just
    1513             :         // subtract the offset to the absolute containing block to make it
    1514             :         // relative to that.
    1515           0 :         cbOffset -= containingBlock->GetOffsetTo(cbrs->mFrame);
    1516           0 :         break;
    1517             :       }
    1518         853 :       containingBlock = parent;
    1519         853 :     } while (containingBlock != cbrs->mFrame);
    1520             :   } else {
    1521             :     // XXXldb We need to either ignore scrolling for the absolute
    1522             :     // positioning case too (and take the incompatibility) or figure out
    1523             :     // how to make these positioned elements actually *move* when we
    1524             :     // scroll, and thus avoid the resulting incremental reflow bugs.
    1525           0 :     cbOffset = containingBlock->GetOffsetTo(cbrs->mFrame);
    1526             :   }
    1527          77 :   nsSize cbrsSize = cbrs->ComputedSizeAsContainerIfConstrained();
    1528          77 :   LogicalPoint logCBOffs(wm, cbOffset, cbrsSize - containerSize);
    1529          77 :   aHypotheticalPos.mIStart += logCBOffs.I(wm);
    1530          77 :   aHypotheticalPos.mBStart += logCBOffs.B(wm);
    1531             : 
    1532             :   // The specified offsets are relative to the absolute containing block's
    1533             :   // padding edge and our current values are relative to the border edge, so
    1534             :   // translate.
    1535             :   LogicalMargin border =
    1536          77 :     cbrs->ComputedLogicalBorderPadding() - cbrs->ComputedLogicalPadding();
    1537          77 :   border = border.ConvertTo(wm, cbrs->GetWritingMode());
    1538          77 :   aHypotheticalPos.mIStart -= border.IStart(wm);
    1539          77 :   aHypotheticalPos.mBStart -= border.BStart(wm);
    1540             : 
    1541             :   // At this point, we have computed aHypotheticalPos using the writing mode
    1542             :   // of the placeholder's containing block.
    1543             : 
    1544          77 :   if (cbwm.GetBlockDir() != wm.GetBlockDir()) {
    1545             :     // If the block direction we used in calculating aHypotheticalPos does not
    1546             :     // match the absolute containing block's, we need to convert here so that
    1547             :     // aHypotheticalPos is usable in relation to the absolute containing block.
    1548             :     // This requires computing or measuring the abspos frame's block-size,
    1549             :     // which is not otherwise required/used here (as aHypotheticalPos
    1550             :     // records only the block-start coordinate).
    1551             : 
    1552             :     // This is similar to the inline-size calculation for a replaced
    1553             :     // inline-level element or a block-level element (above), except that
    1554             :     // 'auto' sizing is handled differently in the block direction for non-
    1555             :     // replaced elements and replaced elements lacking an intrinsic size.
    1556             : 
    1557             :     // Determine the total amount of block direction
    1558             :     // border/padding/margin that the element would have had if it had
    1559             :     // been in the flow. Note that we ignore any 'auto' and 'inherit'
    1560             :     // values.
    1561             :     nscoord insideBoxSizing, outsideBoxSizing;
    1562           0 :     CalculateBorderPaddingMargin(eLogicalAxisBlock,
    1563           0 :                                  blockContentSize.BSize(wm),
    1564           0 :                                  &insideBoxSizing, &outsideBoxSizing);
    1565             : 
    1566             :     nscoord boxBSize;
    1567           0 :     nsStyleCoord styleBSize = mStylePosition->BSize(wm);
    1568           0 :     bool isAutoBSize = styleBSize.GetUnit() == eStyleUnit_Auto;
    1569           0 :     if (isAutoBSize) {
    1570           0 :       if (NS_FRAME_IS_REPLACED(mFrameType) && knowIntrinsicSize) {
    1571             :         // It's a replaced element with an 'auto' block size so the box
    1572             :         // block size is its intrinsic size plus any border/padding/margin
    1573           0 :         boxBSize = LogicalSize(wm, intrinsicSize).BSize(wm) +
    1574           0 :                    outsideBoxSizing + insideBoxSizing;
    1575             :       } else {
    1576             :         // XXX Bug 1191801
    1577             :         // Figure out how to get the correct boxBSize here (need to reflow the
    1578             :         // positioned frame?)
    1579           0 :         boxBSize = 0;
    1580             :       }
    1581             :     } else {
    1582             :       // We need to compute it. It's important we do this, because if it's
    1583             :       // percentage-based this computed value may be different from the
    1584             :       // computed value calculated using the absolute containing block height.
    1585           0 :       boxBSize = nsLayoutUtils::ComputeBSizeValue(blockContentSize.BSize(wm),
    1586           0 :                                                   insideBoxSizing, styleBSize) +
    1587           0 :                  insideBoxSizing + outsideBoxSizing;
    1588             :     }
    1589             : 
    1590           0 :     LogicalSize boxSize(wm, knowBoxISize ? boxISize : 0, boxBSize);
    1591             : 
    1592             :     LogicalPoint origin(wm, aHypotheticalPos.mIStart,
    1593           0 :                         aHypotheticalPos.mBStart);
    1594           0 :     origin = origin.ConvertTo(cbwm, wm, cbrsSize -
    1595           0 :                               boxSize.GetPhysicalSize(wm));
    1596             : 
    1597           0 :     aHypotheticalPos.mIStart = origin.I(cbwm);
    1598           0 :     aHypotheticalPos.mBStart = origin.B(cbwm);
    1599           0 :     aHypotheticalPos.mWritingMode = cbwm;
    1600             :   } else {
    1601          77 :     aHypotheticalPos.mWritingMode = wm;
    1602             :   }
    1603          77 : }
    1604             : 
    1605             : void
    1606          77 : ReflowInput::InitAbsoluteConstraints(nsPresContext* aPresContext,
    1607             :                                      const ReflowInput* cbrs,
    1608             :                                      const LogicalSize& aCBSize,
    1609             :                                      LayoutFrameType aFrameType)
    1610             : {
    1611          77 :   WritingMode wm = GetWritingMode();
    1612          77 :   WritingMode cbwm = cbrs->GetWritingMode();
    1613          77 :   NS_PRECONDITION(aCBSize.BSize(cbwm) != NS_AUTOHEIGHT,
    1614             :                   "containing block bsize must be constrained");
    1615             : 
    1616          77 :   NS_ASSERTION(aFrameType != LayoutFrameType::Table,
    1617             :                "InitAbsoluteConstraints should not be called on table frames");
    1618          77 :   NS_ASSERTION(mFrame->GetStateBits() & NS_FRAME_OUT_OF_FLOW,
    1619             :                "Why are we here?");
    1620             : 
    1621          77 :   const auto& styleOffset = mStylePosition->mOffset;
    1622          77 :   bool iStartIsAuto = styleOffset.GetIStartUnit(cbwm) == eStyleUnit_Auto;
    1623          77 :   bool iEndIsAuto   = styleOffset.GetIEndUnit(cbwm) == eStyleUnit_Auto;
    1624          77 :   bool bStartIsAuto = styleOffset.GetBStartUnit(cbwm) == eStyleUnit_Auto;
    1625          77 :   bool bEndIsAuto   = styleOffset.GetBEndUnit(cbwm) == eStyleUnit_Auto;
    1626             : 
    1627             :   // If both 'left' and 'right' are 'auto' or both 'top' and 'bottom' are
    1628             :   // 'auto', then compute the hypothetical box position where the element would
    1629             :   // have been if it had been in the flow
    1630          77 :   nsHypotheticalPosition hypotheticalPos;
    1631          77 :   if ((iStartIsAuto && iEndIsAuto) || (bStartIsAuto && bEndIsAuto)) {
    1632          77 :     nsPlaceholderFrame* placeholderFrame = mFrame->GetPlaceholderFrame();
    1633          77 :     MOZ_ASSERT(placeholderFrame, "no placeholder frame");
    1634             : 
    1635          77 :     if (placeholderFrame->HasAnyStateBits(
    1636             :           PLACEHOLDER_STATICPOS_NEEDS_CSSALIGN)) {
    1637           0 :       DebugOnly<nsIFrame*> placeholderParent = placeholderFrame->GetParent();
    1638           0 :       MOZ_ASSERT(placeholderParent, "shouldn't have unparented placeholders");
    1639           0 :       MOZ_ASSERT(placeholderParent->IsFlexOrGridContainer(),
    1640             :                  "This flag should only be set on grid/flex children");
    1641             : 
    1642             :       // If the (as-yet unknown) static position will determine the inline
    1643             :       // and/or block offsets, set flags to note those offsets aren't valid
    1644             :       // until we can do CSS Box Alignment on the OOF frame.
    1645           0 :       mFlags.mIOffsetsNeedCSSAlign = (iStartIsAuto && iEndIsAuto);
    1646           0 :       mFlags.mBOffsetsNeedCSSAlign = (bStartIsAuto && bEndIsAuto);
    1647             :     }
    1648             : 
    1649          77 :     if (mFlags.mStaticPosIsCBOrigin) {
    1650           0 :       hypotheticalPos.mWritingMode = cbwm;
    1651           0 :       hypotheticalPos.mIStart = nscoord(0);
    1652           0 :       hypotheticalPos.mBStart = nscoord(0);
    1653             :     } else {
    1654             :       CalculateHypotheticalPosition(aPresContext, placeholderFrame, cbrs,
    1655          77 :                                     hypotheticalPos, aFrameType);
    1656             :     }
    1657             :   }
    1658             : 
    1659             :   // Initialize the 'left' and 'right' computed offsets
    1660             :   // XXX Handle new 'static-position' value...
    1661             : 
    1662             :   // Size of the containing block in its writing mode
    1663          77 :   LogicalSize cbSize = aCBSize;
    1664          77 :   LogicalMargin offsets = ComputedLogicalOffsets().ConvertTo(cbwm, wm);
    1665             : 
    1666          77 :   if (iStartIsAuto) {
    1667          77 :     offsets.IStart(cbwm) = 0;
    1668             :   } else {
    1669           0 :     offsets.IStart(cbwm) = nsLayoutUtils::
    1670           0 :       ComputeCBDependentValue(cbSize.ISize(cbwm), styleOffset.GetIStart(cbwm));
    1671             :   }
    1672          77 :   if (iEndIsAuto) {
    1673          77 :     offsets.IEnd(cbwm) = 0;
    1674             :   } else {
    1675           0 :     offsets.IEnd(cbwm) = nsLayoutUtils::
    1676           0 :       ComputeCBDependentValue(cbSize.ISize(cbwm), styleOffset.GetIEnd(cbwm));
    1677             :   }
    1678             : 
    1679          77 :   if (iStartIsAuto && iEndIsAuto) {
    1680          77 :     if (cbwm.IsBidiLTR() != hypotheticalPos.mWritingMode.IsBidiLTR()) {
    1681           0 :       offsets.IEnd(cbwm) = hypotheticalPos.mIStart;
    1682           0 :       iEndIsAuto = false;
    1683             :     } else {
    1684          77 :       offsets.IStart(cbwm) = hypotheticalPos.mIStart;
    1685          77 :       iStartIsAuto = false;
    1686             :     }
    1687             :   }
    1688             : 
    1689          77 :   if (bStartIsAuto) {
    1690          77 :     offsets.BStart(cbwm) = 0;
    1691             :   } else {
    1692           0 :     offsets.BStart(cbwm) = nsLayoutUtils::
    1693           0 :       ComputeBSizeDependentValue(cbSize.BSize(cbwm),
    1694           0 :                                  styleOffset.GetBStart(cbwm));
    1695             :   }
    1696          77 :   if (bEndIsAuto) {
    1697          77 :     offsets.BEnd(cbwm) = 0;
    1698             :   } else {
    1699           0 :     offsets.BEnd(cbwm) = nsLayoutUtils::
    1700           0 :       ComputeBSizeDependentValue(cbSize.BSize(cbwm),
    1701           0 :                                  styleOffset.GetBEnd(cbwm));
    1702             :   }
    1703             : 
    1704          77 :   if (bStartIsAuto && bEndIsAuto) {
    1705             :     // Treat 'top' like 'static-position'
    1706          77 :     offsets.BStart(cbwm) = hypotheticalPos.mBStart;
    1707          77 :     bStartIsAuto = false;
    1708             :   }
    1709             : 
    1710          77 :   SetComputedLogicalOffsets(offsets.ConvertTo(wm, cbwm));
    1711             : 
    1712             :   typedef nsIFrame::ComputeSizeFlags ComputeSizeFlags;
    1713          77 :   ComputeSizeFlags computeSizeFlags = ComputeSizeFlags::eDefault;
    1714          77 :   if (mFlags.mIClampMarginBoxMinSize) {
    1715           0 :     computeSizeFlags = ComputeSizeFlags(computeSizeFlags |
    1716             :                          ComputeSizeFlags::eIClampMarginBoxMinSize);
    1717             :   }
    1718          77 :   if (mFlags.mBClampMarginBoxMinSize) {
    1719           0 :     computeSizeFlags = ComputeSizeFlags(computeSizeFlags |
    1720             :                          ComputeSizeFlags::eBClampMarginBoxMinSize);
    1721             :   }
    1722          77 :   if (mFlags.mApplyAutoMinSize) {
    1723           0 :     computeSizeFlags = ComputeSizeFlags(computeSizeFlags |
    1724             :                          ComputeSizeFlags::eIApplyAutoMinSize);
    1725             :   }
    1726          77 :   if (mFlags.mShrinkWrap) {
    1727           0 :     computeSizeFlags =
    1728           0 :       ComputeSizeFlags(computeSizeFlags | ComputeSizeFlags::eShrinkWrap);
    1729             :   }
    1730          77 :   if (mFlags.mUseAutoBSize) {
    1731           0 :     computeSizeFlags =
    1732           0 :       ComputeSizeFlags(computeSizeFlags | ComputeSizeFlags::eUseAutoBSize);
    1733             :   }
    1734          77 :   if (wm.IsOrthogonalTo(cbwm)) {
    1735           0 :     if (bStartIsAuto || bEndIsAuto) {
    1736           0 :       computeSizeFlags =
    1737           0 :         ComputeSizeFlags(computeSizeFlags | ComputeSizeFlags::eShrinkWrap);
    1738             :     }
    1739             :   } else {
    1740          77 :     if (iStartIsAuto || iEndIsAuto) {
    1741          77 :       computeSizeFlags =
    1742          77 :         ComputeSizeFlags(computeSizeFlags | ComputeSizeFlags::eShrinkWrap);
    1743             :     }
    1744             :   }
    1745             : 
    1746          77 :   LogicalSize computedSize(wm);
    1747             :   {
    1748         154 :     AutoMaybeDisableFontInflation an(mFrame);
    1749             : 
    1750             :     computedSize =
    1751         308 :       mFrame->ComputeSize(mRenderingContext, wm, cbSize.ConvertTo(wm, cbwm),
    1752         154 :                          cbSize.ConvertTo(wm, cbwm).ISize(wm), // XXX or AvailableISize()?
    1753         154 :                          ComputedLogicalMargin().Size(wm) +
    1754         154 :                            ComputedLogicalOffsets().Size(wm),
    1755         154 :                          ComputedLogicalBorderPadding().Size(wm) -
    1756         154 :                            ComputedLogicalPadding().Size(wm),
    1757         154 :                          ComputedLogicalPadding().Size(wm),
    1758         308 :                          computeSizeFlags);
    1759          77 :     ComputedISize() = computedSize.ISize(wm);
    1760          77 :     ComputedBSize() = computedSize.BSize(wm);
    1761          77 :     NS_ASSERTION(ComputedISize() >= 0, "Bogus inline-size");
    1762          77 :     NS_ASSERTION(ComputedBSize() == NS_UNCONSTRAINEDSIZE ||
    1763             :                  ComputedBSize() >= 0, "Bogus block-size");
    1764             :   }
    1765          77 :   computedSize = computedSize.ConvertTo(cbwm, wm);
    1766             : 
    1767             :   // XXX Now that we have ComputeSize, can we condense many of the
    1768             :   // branches off of widthIsAuto?
    1769             : 
    1770          77 :   LogicalMargin margin = ComputedLogicalMargin().ConvertTo(cbwm, wm);
    1771             :   const LogicalMargin borderPadding =
    1772          77 :     ComputedLogicalBorderPadding().ConvertTo(cbwm, wm);
    1773             : 
    1774          77 :   bool iSizeIsAuto = eStyleUnit_Auto == mStylePosition->ISize(cbwm).GetUnit();
    1775          77 :   if (iStartIsAuto) {
    1776             :     // We know 'right' is not 'auto' anymore thanks to the hypothetical
    1777             :     // box code above.
    1778             :     // Solve for 'left'.
    1779           0 :     if (iSizeIsAuto) {
    1780             :       // XXXldb This, and the corresponding code in
    1781             :       // nsAbsoluteContainingBlock.cpp, could probably go away now that
    1782             :       // we always compute widths.
    1783           0 :       offsets.IStart(cbwm) = NS_AUTOOFFSET;
    1784             :     } else {
    1785           0 :       offsets.IStart(cbwm) =
    1786           0 :         cbSize.ISize(cbwm) - offsets.IEnd(cbwm) -
    1787           0 :         computedSize.ISize(cbwm) - margin.IStartEnd(cbwm) -
    1788           0 :         borderPadding.IStartEnd(cbwm);
    1789             :     }
    1790          77 :   } else if (iEndIsAuto) {
    1791             :     // We know 'left' is not 'auto' anymore thanks to the hypothetical
    1792             :     // box code above.
    1793             :     // Solve for 'right'.
    1794          77 :     if (iSizeIsAuto) {
    1795             :       // XXXldb This, and the corresponding code in
    1796             :       // nsAbsoluteContainingBlock.cpp, could probably go away now that
    1797             :       // we always compute widths.
    1798          77 :       offsets.IEnd(cbwm) = NS_AUTOOFFSET;
    1799             :     } else {
    1800           0 :       offsets.IEnd(cbwm) =
    1801           0 :         cbSize.ISize(cbwm) - offsets.IStart(cbwm) -
    1802           0 :         computedSize.ISize(cbwm) - margin.IStartEnd(cbwm) -
    1803           0 :         borderPadding.IStartEnd(cbwm);
    1804             :     }
    1805             :   } else {
    1806             :     // Neither 'inline-start' nor 'inline-end' is 'auto'.
    1807             : 
    1808           0 :     if (wm.IsOrthogonalTo(cbwm)) {
    1809             :       // For orthogonal blocks, we need to handle the case where the block had
    1810             :       // unconstrained block-size, which mapped to unconstrained inline-size
    1811             :       // in the containing block's writing mode.
    1812           0 :       nscoord autoISize = cbSize.ISize(cbwm) - margin.IStartEnd(cbwm) -
    1813           0 :         borderPadding.IStartEnd(cbwm) - offsets.IStartEnd(cbwm);
    1814           0 :       if (autoISize < 0) {
    1815           0 :         autoISize = 0;
    1816             :       }
    1817             : 
    1818           0 :       if (computedSize.ISize(cbwm) == NS_UNCONSTRAINEDSIZE) {
    1819             :         // For non-replaced elements with block-size auto, the block-size
    1820             :         // fills the remaining space.
    1821           0 :         computedSize.ISize(cbwm) = autoISize;
    1822             : 
    1823             :         // XXX Do these need box-sizing adjustments?
    1824           0 :         LogicalSize maxSize = ComputedMaxSize(cbwm);
    1825           0 :         LogicalSize minSize = ComputedMinSize(cbwm);
    1826           0 :         if (computedSize.ISize(cbwm) > maxSize.ISize(cbwm)) {
    1827           0 :           computedSize.ISize(cbwm) = maxSize.ISize(cbwm);
    1828             :         }
    1829           0 :         if (computedSize.ISize(cbwm) < minSize.ISize(cbwm)) {
    1830           0 :           computedSize.ISize(cbwm) = minSize.ISize(cbwm);
    1831             :         }
    1832             :       }
    1833             :     }
    1834             : 
    1835             :     // However, the inline-size might
    1836             :     // still not fill all the available space (even though we didn't
    1837             :     // shrink-wrap) in case:
    1838             :     //  * inline-size was specified
    1839             :     //  * we're dealing with a replaced element
    1840             :     //  * width was constrained by min- or max-inline-size.
    1841             : 
    1842             :     nscoord availMarginSpace =
    1843           0 :       aCBSize.ISize(cbwm) - offsets.IStartEnd(cbwm) - margin.IStartEnd(cbwm) -
    1844           0 :       borderPadding.IStartEnd(cbwm) - computedSize.ISize(cbwm);
    1845             :     bool marginIStartIsAuto =
    1846           0 :       eStyleUnit_Auto == mStyleMargin->mMargin.GetIStartUnit(cbwm);
    1847             :     bool marginIEndIsAuto =
    1848           0 :       eStyleUnit_Auto == mStyleMargin->mMargin.GetIEndUnit(cbwm);
    1849             : 
    1850           0 :     if (marginIStartIsAuto) {
    1851           0 :       if (marginIEndIsAuto) {
    1852           0 :         if (availMarginSpace < 0) {
    1853             :           // Note that this case is different from the neither-'auto'
    1854             :           // case below, where the spec says to ignore 'left'/'right'.
    1855             :           // Ignore the specified value for 'margin-right'.
    1856           0 :           margin.IEnd(cbwm) = availMarginSpace;
    1857             :         } else {
    1858             :           // Both 'margin-left' and 'margin-right' are 'auto', so they get
    1859             :           // equal values
    1860           0 :           margin.IStart(cbwm) = availMarginSpace / 2;
    1861           0 :           margin.IEnd(cbwm) = availMarginSpace - margin.IStart(cbwm);
    1862             :         }
    1863             :       } else {
    1864             :         // Just 'margin-left' is 'auto'
    1865           0 :         margin.IStart(cbwm) = availMarginSpace;
    1866             :       }
    1867             :     } else {
    1868           0 :       if (marginIEndIsAuto) {
    1869             :         // Just 'margin-right' is 'auto'
    1870           0 :         margin.IEnd(cbwm) = availMarginSpace;
    1871             :       } else {
    1872             :         // We're over-constrained so use the direction of the containing
    1873             :         // block to dictate which value to ignore.  (And note that the
    1874             :         // spec says to ignore 'left' or 'right' rather than
    1875             :         // 'margin-left' or 'margin-right'.)
    1876             :         // Note that this case is different from the both-'auto' case
    1877             :         // above, where the spec says to ignore
    1878             :         // 'margin-left'/'margin-right'.
    1879             :         // Ignore the specified value for 'right'.
    1880           0 :         offsets.IEnd(cbwm) += availMarginSpace;
    1881             :       }
    1882             :     }
    1883             :   }
    1884             : 
    1885          77 :   bool bSizeIsAuto = eStyleUnit_Auto == mStylePosition->BSize(cbwm).GetUnit();
    1886          77 :   if (bStartIsAuto) {
    1887             :     // solve for block-start
    1888           0 :     if (bSizeIsAuto) {
    1889           0 :       offsets.BStart(cbwm) = NS_AUTOOFFSET;
    1890             :     } else {
    1891           0 :       offsets.BStart(cbwm) = cbSize.BSize(cbwm) - margin.BStartEnd(cbwm) -
    1892           0 :         borderPadding.BStartEnd(cbwm) - computedSize.BSize(cbwm) -
    1893           0 :         offsets.BEnd(cbwm);
    1894             :     }
    1895          77 :   } else if (bEndIsAuto) {
    1896             :     // solve for block-end
    1897          77 :     if (bSizeIsAuto) {
    1898          77 :       offsets.BEnd(cbwm) = NS_AUTOOFFSET;
    1899             :     } else {
    1900           0 :       offsets.BEnd(cbwm) = cbSize.BSize(cbwm) - margin.BStartEnd(cbwm) -
    1901           0 :         borderPadding.BStartEnd(cbwm) - computedSize.BSize(cbwm) -
    1902           0 :         offsets.BStart(cbwm);
    1903             :     }
    1904             :   } else {
    1905             :     // Neither block-start nor -end is 'auto'.
    1906           0 :     nscoord autoBSize = cbSize.BSize(cbwm) - margin.BStartEnd(cbwm) -
    1907           0 :       borderPadding.BStartEnd(cbwm) - offsets.BStartEnd(cbwm);
    1908           0 :     if (autoBSize < 0) {
    1909           0 :       autoBSize = 0;
    1910             :     }
    1911             : 
    1912           0 :     if (computedSize.BSize(cbwm) == NS_UNCONSTRAINEDSIZE) {
    1913             :       // For non-replaced elements with block-size auto, the block-size
    1914             :       // fills the remaining space.
    1915           0 :       computedSize.BSize(cbwm) = autoBSize;
    1916             : 
    1917             :       // XXX Do these need box-sizing adjustments?
    1918           0 :       LogicalSize maxSize = ComputedMaxSize(cbwm);
    1919           0 :       LogicalSize minSize = ComputedMinSize(cbwm);
    1920           0 :       if (computedSize.BSize(cbwm) > maxSize.BSize(cbwm)) {
    1921           0 :         computedSize.BSize(cbwm) = maxSize.BSize(cbwm);
    1922             :       }
    1923           0 :       if (computedSize.BSize(cbwm) < minSize.BSize(cbwm)) {
    1924           0 :         computedSize.BSize(cbwm) = minSize.BSize(cbwm);
    1925             :       }
    1926             :     }
    1927             : 
    1928             :     // The block-size might still not fill all the available space in case:
    1929             :     //  * bsize was specified
    1930             :     //  * we're dealing with a replaced element
    1931             :     //  * bsize was constrained by min- or max-bsize.
    1932           0 :     nscoord availMarginSpace = autoBSize - computedSize.BSize(cbwm);
    1933             :     bool marginBStartIsAuto =
    1934           0 :       eStyleUnit_Auto == mStyleMargin->mMargin.GetBStartUnit(cbwm);
    1935             :     bool marginBEndIsAuto =
    1936           0 :       eStyleUnit_Auto == mStyleMargin->mMargin.GetBEndUnit(cbwm);
    1937             : 
    1938           0 :     if (marginBStartIsAuto) {
    1939           0 :       if (marginBEndIsAuto) {
    1940             :         // Both 'margin-top' and 'margin-bottom' are 'auto', so they get
    1941             :         // equal values
    1942           0 :         margin.BStart(cbwm) = availMarginSpace / 2;
    1943           0 :         margin.BEnd(cbwm) = availMarginSpace - margin.BStart(cbwm);
    1944             :       } else {
    1945             :         // Just margin-block-start is 'auto'
    1946           0 :         margin.BStart(cbwm) = availMarginSpace;
    1947             :       }
    1948             :     } else {
    1949           0 :       if (marginBEndIsAuto) {
    1950             :         // Just margin-block-end is 'auto'
    1951           0 :         margin.BEnd(cbwm) = availMarginSpace;
    1952             :       } else {
    1953             :         // We're over-constrained so ignore the specified value for
    1954             :         // block-end.  (And note that the spec says to ignore 'bottom'
    1955             :         // rather than 'margin-bottom'.)
    1956           0 :         offsets.BEnd(cbwm) += availMarginSpace;
    1957             :       }
    1958             :     }
    1959             :   }
    1960          77 :   ComputedBSize() = computedSize.ConvertTo(wm, cbwm).BSize(wm);
    1961          77 :   ComputedISize() = computedSize.ConvertTo(wm, cbwm).ISize(wm);
    1962             : 
    1963          77 :   SetComputedLogicalOffsets(offsets.ConvertTo(wm, cbwm));
    1964          77 :   SetComputedLogicalMargin(margin.ConvertTo(wm, cbwm));
    1965          77 : }
    1966             : 
    1967             : // This will not be converted to abstract coordinates because it's only
    1968             : // used in CalcQuirkContainingBlockHeight
    1969             : nscoord
    1970           0 : GetBlockMarginBorderPadding(const ReflowInput* aReflowInput)
    1971             : {
    1972           0 :   nscoord result = 0;
    1973           0 :   if (!aReflowInput) return result;
    1974             : 
    1975             :   // zero auto margins
    1976           0 :   nsMargin margin = aReflowInput->ComputedPhysicalMargin();
    1977           0 :   if (NS_AUTOMARGIN == margin.top)
    1978           0 :     margin.top = 0;
    1979           0 :   if (NS_AUTOMARGIN == margin.bottom)
    1980           0 :     margin.bottom = 0;
    1981             : 
    1982           0 :   result += margin.top + margin.bottom;
    1983           0 :   result += aReflowInput->ComputedPhysicalBorderPadding().top +
    1984           0 :             aReflowInput->ComputedPhysicalBorderPadding().bottom;
    1985             : 
    1986           0 :   return result;
    1987             : }
    1988             : 
    1989             : /* Get the height based on the viewport of the containing block specified
    1990             :  * in aReflowInput when the containing block has mComputedHeight == NS_AUTOHEIGHT
    1991             :  * This will walk up the chain of containing blocks looking for a computed height
    1992             :  * until it finds the canvas frame, or it encounters a frame that is not a block,
    1993             :  * area, or scroll frame. This handles compatibility with IE (see bug 85016 and bug 219693)
    1994             :  *
    1995             :  * When we encounter scrolledContent block frames, we skip over them,
    1996             :  * since they are guaranteed to not be useful for computing the containing block.
    1997             :  *
    1998             :  * See also IsQuirkContainingBlockHeight.
    1999             :  */
    2000             : static nscoord
    2001           0 : CalcQuirkContainingBlockHeight(const ReflowInput* aCBReflowInput)
    2002             : {
    2003           0 :   const ReflowInput* firstAncestorRI = nullptr; // a candidate for html frame
    2004           0 :   const ReflowInput* secondAncestorRI = nullptr; // a candidate for body frame
    2005             : 
    2006             :   // initialize the default to NS_AUTOHEIGHT as this is the containings block
    2007             :   // computed height when this function is called. It is possible that we
    2008             :   // don't alter this height especially if we are restricted to one level
    2009           0 :   nscoord result = NS_AUTOHEIGHT;
    2010             : 
    2011           0 :   const ReflowInput* rs = aCBReflowInput;
    2012           0 :   for (; rs; rs = rs->mParentReflowInput) {
    2013           0 :     LayoutFrameType frameType = rs->mFrame->Type();
    2014             :     // if the ancestor is auto height then skip it and continue up if it
    2015             :     // is the first block frame and possibly the body/html
    2016           0 :     if (LayoutFrameType::Block == frameType ||
    2017             : #ifdef MOZ_XUL
    2018           0 :         LayoutFrameType::XULLabel == frameType ||
    2019             : #endif
    2020             :         LayoutFrameType::Scroll == frameType) {
    2021             : 
    2022           0 :       secondAncestorRI = firstAncestorRI;
    2023           0 :       firstAncestorRI = rs;
    2024             : 
    2025             :       // If the current frame we're looking at is positioned, we don't want to
    2026             :       // go any further (see bug 221784).  The behavior we want here is: 1) If
    2027             :       // not auto-height, use this as the percentage base.  2) If auto-height,
    2028             :       // keep looking, unless the frame is positioned.
    2029           0 :       if (NS_AUTOHEIGHT == rs->ComputedHeight()) {
    2030           0 :         if (rs->mFrame->IsAbsolutelyPositioned(rs->mStyleDisplay)) {
    2031           0 :           break;
    2032             :         } else {
    2033           0 :           continue;
    2034             :         }
    2035             :       }
    2036           0 :     } else if (LayoutFrameType::Canvas == frameType) {
    2037             :       // Always continue on to the height calculation
    2038           0 :     } else if (LayoutFrameType::PageContent == frameType) {
    2039           0 :       nsIFrame* prevInFlow = rs->mFrame->GetPrevInFlow();
    2040             :       // only use the page content frame for a height basis if it is the first in flow
    2041           0 :       if (prevInFlow)
    2042           0 :         break;
    2043             :     }
    2044             :     else {
    2045           0 :       break;
    2046             :     }
    2047             : 
    2048             :     // if the ancestor is the page content frame then the percent base is
    2049             :     // the avail height, otherwise it is the computed height
    2050           0 :     result = (LayoutFrameType::PageContent == frameType) ? rs->AvailableHeight()
    2051             :                                                          : rs->ComputedHeight();
    2052             :     // if unconstrained - don't sutract borders - would result in huge height
    2053           0 :     if (NS_AUTOHEIGHT == result) return result;
    2054             : 
    2055             :     // if we got to the canvas or page content frame, then subtract out
    2056             :     // margin/border/padding for the BODY and HTML elements
    2057           0 :     if ((LayoutFrameType::Canvas == frameType) ||
    2058             :         (LayoutFrameType::PageContent == frameType)) {
    2059             : 
    2060           0 :       result -= GetBlockMarginBorderPadding(firstAncestorRI);
    2061           0 :       result -= GetBlockMarginBorderPadding(secondAncestorRI);
    2062             : 
    2063             : #ifdef DEBUG
    2064             :       // make sure the first ancestor is the HTML and the second is the BODY
    2065           0 :       if (firstAncestorRI) {
    2066           0 :         nsIContent* frameContent = firstAncestorRI->mFrame->GetContent();
    2067           0 :         if (frameContent) {
    2068           0 :           NS_ASSERTION(frameContent->IsHTMLElement(nsGkAtoms::html),
    2069             :                        "First ancestor is not HTML");
    2070             :         }
    2071             :       }
    2072           0 :       if (secondAncestorRI) {
    2073           0 :         nsIContent* frameContent = secondAncestorRI->mFrame->GetContent();
    2074           0 :         if (frameContent) {
    2075           0 :           NS_ASSERTION(frameContent->IsHTMLElement(nsGkAtoms::body),
    2076             :                        "Second ancestor is not BODY");
    2077             :         }
    2078           0 :       }
    2079             : #endif
    2080             : 
    2081             :     }
    2082             :     // if we got to the html frame (a block child of the canvas) ...
    2083           0 :     else if (LayoutFrameType::Block == frameType && rs->mParentReflowInput &&
    2084           0 :              rs->mParentReflowInput->mFrame->IsCanvasFrame()) {
    2085             :       // ... then subtract out margin/border/padding for the BODY element
    2086           0 :       result -= GetBlockMarginBorderPadding(secondAncestorRI);
    2087             :     }
    2088           0 :     break;
    2089             :   }
    2090             : 
    2091             :   // Make sure not to return a negative height here!
    2092           0 :   return std::max(result, 0);
    2093             : }
    2094             : 
    2095             : // Called by InitConstraints() to compute the containing block rectangle for
    2096             : // the element. Handles the special logic for absolutely positioned elements
    2097             : LogicalSize
    2098         320 : ReflowInput::ComputeContainingBlockRectangle(
    2099             :                      nsPresContext*           aPresContext,
    2100             :                      const ReflowInput* aContainingBlockRI) const
    2101             : {
    2102             :   // Unless the element is absolutely positioned, the containing block is
    2103             :   // formed by the content edge of the nearest block-level ancestor
    2104         320 :   LogicalSize cbSize = aContainingBlockRI->ComputedSize();
    2105             : 
    2106         320 :   WritingMode wm = aContainingBlockRI->GetWritingMode();
    2107             : 
    2108             :   // mFrameType for abs-pos tables is NS_CSS_FRAME_TYPE_BLOCK, so we need to
    2109             :   // special case them here.
    2110         640 :   if (NS_FRAME_GET_TYPE(mFrameType) == NS_CSS_FRAME_TYPE_ABSOLUTE ||
    2111         320 :       (mFrame->IsTableFrame() && mFrame->IsAbsolutelyPositioned(mStyleDisplay) &&
    2112           0 :        (mFrame->GetParent()->GetStateBits() & NS_FRAME_OUT_OF_FLOW))) {
    2113             :     // See if the ancestor is block-level or inline-level
    2114           0 :     if (NS_FRAME_GET_TYPE(aContainingBlockRI->mFrameType) == NS_CSS_FRAME_TYPE_INLINE) {
    2115             :       // Base our size on the actual size of the frame.  In cases when this is
    2116             :       // completely bogus (eg initial reflow), this code shouldn't even be
    2117             :       // called, since the code in nsInlineFrame::Reflow will pass in
    2118             :       // the containing block dimensions to our constructor.
    2119             :       // XXXbz we should be taking the in-flows into account too, but
    2120             :       // that's very hard.
    2121             : 
    2122             :       LogicalMargin computedBorder =
    2123           0 :         aContainingBlockRI->ComputedLogicalBorderPadding() -
    2124           0 :         aContainingBlockRI->ComputedLogicalPadding();
    2125           0 :       cbSize.ISize(wm) = aContainingBlockRI->mFrame->ISize(wm) -
    2126           0 :                          computedBorder.IStartEnd(wm);
    2127           0 :       NS_ASSERTION(cbSize.ISize(wm) >= 0,
    2128             :                    "Negative containing block isize!");
    2129           0 :       cbSize.BSize(wm) = aContainingBlockRI->mFrame->BSize(wm) -
    2130           0 :                          computedBorder.BStartEnd(wm);
    2131           0 :       NS_ASSERTION(cbSize.BSize(wm) >= 0,
    2132             :                    "Negative containing block bsize!");
    2133             :     } else {
    2134             :       // If the ancestor is block-level, the containing block is formed by the
    2135             :       // padding edge of the ancestor
    2136           0 :       cbSize.ISize(wm) +=
    2137           0 :         aContainingBlockRI->ComputedLogicalPadding().IStartEnd(wm);
    2138           0 :       cbSize.BSize(wm) +=
    2139           0 :         aContainingBlockRI->ComputedLogicalPadding().BStartEnd(wm);
    2140             :     }
    2141             :   } else {
    2142             :     // an element in quirks mode gets a containing block based on looking for a
    2143             :     // parent with a non-auto height if the element has a percent height
    2144             :     // Note: We don't emulate this quirk for percents in calc() or in
    2145             :     // vertical writing modes.
    2146         640 :     if (!wm.IsVertical() &&
    2147         320 :         NS_AUTOHEIGHT == cbSize.BSize(wm)) {
    2148          88 :       if (eCompatibility_NavQuirks == aPresContext->CompatibilityMode() &&
    2149          24 :           (mStylePosition->mHeight.GetUnit() == eStyleUnit_Percent ||
    2150          12 :            (mFrame->IsTableWrapperFrame() &&
    2151           0 :             mFrame->PrincipalChildList().FirstChild()->StylePosition()->
    2152           0 :               mHeight.GetUnit() == eStyleUnit_Percent))) {
    2153           0 :         cbSize.BSize(wm) = CalcQuirkContainingBlockHeight(aContainingBlockRI);
    2154             :       }
    2155             :     }
    2156             :   }
    2157             : 
    2158         320 :   return cbSize.ConvertTo(GetWritingMode(), wm);
    2159             : }
    2160             : 
    2161         147 : static eNormalLineHeightControl GetNormalLineHeightCalcControl(void)
    2162             : {
    2163         147 :   if (sNormalLineHeightControl == eUninitialized) {
    2164             :     // browser.display.normal_lineheight_calc_control is not user
    2165             :     // changeable, so no need to register callback for it.
    2166             :     int32_t val =
    2167             :       Preferences::GetInt("browser.display.normal_lineheight_calc_control",
    2168           2 :                           eNoExternalLeading);
    2169           2 :     sNormalLineHeightControl = static_cast<eNormalLineHeightControl>(val);
    2170             :   }
    2171         147 :   return sNormalLineHeightControl;
    2172             : }
    2173             : 
    2174             : static inline bool
    2175         257 : IsSideCaption(nsIFrame* aFrame, const nsStyleDisplay* aStyleDisplay,
    2176             :               WritingMode aWM)
    2177             : {
    2178         257 :   if (aStyleDisplay->mDisplay != StyleDisplay::TableCaption) {
    2179         257 :     return false;
    2180             :   }
    2181           0 :   uint8_t captionSide = aFrame->StyleTableBorder()->mCaptionSide;
    2182           0 :   return captionSide == NS_STYLE_CAPTION_SIDE_LEFT ||
    2183           0 :          captionSide == NS_STYLE_CAPTION_SIDE_RIGHT;
    2184             : }
    2185             : 
    2186             : // Flex/grid items resolve block-axis percentage margin & padding against the
    2187             : // containing block block-size (also for abs/fixed-pos child frames).
    2188             : // For everything else: the CSS21 spec requires that margin and padding
    2189             : // percentage values are calculated with respect to the inline-size of the
    2190             : // containing block, even for margin & padding in the block axis.
    2191             : static LogicalSize
    2192         652 : OffsetPercentBasis(const nsIFrame*    aFrame,
    2193             :                    WritingMode        aWM,
    2194             :                    const LogicalSize& aContainingBlockSize)
    2195             : {
    2196         652 :   LogicalSize offsetPercentBasis = aContainingBlockSize;
    2197         652 :   if (MOZ_LIKELY(!aFrame->GetParent() ||
    2198             :                  !aFrame->GetParent()->IsFlexOrGridContainer())) {
    2199         652 :     offsetPercentBasis.BSize(aWM) = offsetPercentBasis.ISize(aWM);
    2200           0 :   } else if (offsetPercentBasis.BSize(aWM) == NS_AUTOHEIGHT) {
    2201           0 :     offsetPercentBasis.BSize(aWM) = 0;
    2202             :   }
    2203             : 
    2204         652 :   return offsetPercentBasis;
    2205             : }
    2206             : 
    2207             : // XXX refactor this code to have methods for each set of properties
    2208             : // we are computing: width,height,line-height; margin; offsets
    2209             : 
    2210             : void
    2211         652 : ReflowInput::InitConstraints(nsPresContext* aPresContext,
    2212             :                              const LogicalSize& aContainingBlockSize,
    2213             :                              const nsMargin* aBorder,
    2214             :                              const nsMargin* aPadding,
    2215             :                              LayoutFrameType aFrameType)
    2216             : {
    2217         652 :   WritingMode wm = GetWritingMode();
    2218        1304 :   DISPLAY_INIT_CONSTRAINTS(mFrame, this,
    2219             :                            aContainingBlockSize.ISize(wm),
    2220             :                            aContainingBlockSize.BSize(wm),
    2221             :                            aBorder, aPadding);
    2222             : 
    2223             :   // If this is a reflow root, then set the computed width and
    2224             :   // height equal to the available space
    2225         652 :   if (nullptr == mParentReflowInput || mFlags.mDummyParentReflowInput) {
    2226             :     // XXXldb This doesn't mean what it used to!
    2227         510 :     InitOffsets(wm, OffsetPercentBasis(mFrame, wm, aContainingBlockSize),
    2228         255 :                 aFrameType, mFlags, aBorder, aPadding, mStyleDisplay);
    2229             :     // Override mComputedMargin since reflow roots start from the
    2230             :     // frame's boundary, which is inside the margin.
    2231         255 :     ComputedPhysicalMargin().SizeTo(0, 0, 0, 0);
    2232         255 :     ComputedPhysicalOffsets().SizeTo(0, 0, 0, 0);
    2233             : 
    2234         510 :     ComputedISize() =
    2235         510 :       AvailableISize() - ComputedLogicalBorderPadding().IStartEnd(wm);
    2236         255 :     if (ComputedISize() < 0) {
    2237          14 :       ComputedISize() = 0;
    2238             :     }
    2239         255 :     if (AvailableBSize() != NS_UNCONSTRAINEDSIZE) {
    2240         154 :       ComputedBSize() =
    2241         154 :         AvailableBSize() - ComputedLogicalBorderPadding().BStartEnd(wm);
    2242          77 :       if (ComputedBSize() < 0) {
    2243           1 :         ComputedBSize() = 0;
    2244             :       }
    2245             :     } else {
    2246         178 :       ComputedBSize() = NS_UNCONSTRAINEDSIZE;
    2247             :     }
    2248             : 
    2249         255 :     ComputedMinWidth() = ComputedMinHeight() = 0;
    2250         255 :     ComputedMaxWidth() = ComputedMaxHeight() = NS_UNCONSTRAINEDSIZE;
    2251             :   } else {
    2252             :     // Get the containing block reflow state
    2253         397 :     const ReflowInput* cbrs = mCBReflowInput;
    2254         397 :     MOZ_ASSERT(cbrs, "no containing block");
    2255         397 :     MOZ_ASSERT(mFrame->GetParent());
    2256             : 
    2257             :     // If we weren't given a containing block width and height, then
    2258             :     // compute one
    2259         794 :     LogicalSize cbSize = (aContainingBlockSize == LogicalSize(wm, -1, -1))
    2260             :       ? ComputeContainingBlockRectangle(aPresContext, cbrs)
    2261         397 :       : aContainingBlockSize;
    2262             : 
    2263             :     // See if the containing block height is based on the size of its
    2264             :     // content
    2265             :     LayoutFrameType fType;
    2266         397 :     if (NS_AUTOHEIGHT == cbSize.BSize(wm)) {
    2267             :       // See if the containing block is a cell frame which needs
    2268             :       // to use the mComputedHeight of the cell instead of what the cell block passed in.
    2269             :       // XXX It seems like this could lead to bugs with min-height and friends
    2270          76 :       if (cbrs->mParentReflowInput) {
    2271          76 :         fType = cbrs->mFrame->Type();
    2272          76 :         if (IS_TABLE_CELL(fType)) {
    2273             :           // use the cell's computed block size
    2274           0 :           cbSize.BSize(wm) = cbrs->ComputedSize(wm).BSize(wm);
    2275             :         }
    2276             :       }
    2277             :     }
    2278             : 
    2279             :     // XXX Might need to also pass the CB height (not width) for page boxes,
    2280             :     // too, if we implement them.
    2281             : 
    2282             :     // For calculating positioning offsets, margins, borders and
    2283             :     // padding, we use the writing mode of the containing block
    2284         397 :     WritingMode cbwm = cbrs->GetWritingMode();
    2285        1191 :     InitOffsets(cbwm, OffsetPercentBasis(mFrame, cbwm,
    2286         794 :                                          cbSize.ConvertTo(cbwm, wm)),
    2287         397 :                 aFrameType, mFlags, aBorder, aPadding, mStyleDisplay);
    2288             : 
    2289             :     // For calculating the size of this box, we use its own writing mode
    2290         397 :     const nsStyleCoord &blockSize = mStylePosition->BSize(wm);
    2291         397 :     nsStyleUnit blockSizeUnit = blockSize.GetUnit();
    2292             : 
    2293             :     // Check for a percentage based block size and a containing block
    2294             :     // block size that depends on the content block size
    2295             :     // XXX twiddling blockSizeUnit doesn't help anymore
    2296             :     // FIXME Shouldn't we fix that?
    2297         397 :     if (blockSize.HasPercent()) {
    2298           8 :       if (NS_AUTOHEIGHT == cbSize.BSize(wm)) {
    2299             :         // this if clause enables %-blockSize on replaced inline frames,
    2300             :         // such as images.  See bug 54119.  The else clause "blockSizeUnit = eStyleUnit_Auto;"
    2301             :         // used to be called exclusively.
    2302           0 :         if (NS_FRAME_REPLACED(NS_CSS_FRAME_TYPE_INLINE) == mFrameType ||
    2303             :             NS_FRAME_REPLACED_CONTAINS_BLOCK(
    2304           0 :                 NS_CSS_FRAME_TYPE_INLINE) == mFrameType) {
    2305             :           // Get the containing block reflow state
    2306           0 :           NS_ASSERTION(nullptr != cbrs, "no containing block");
    2307             :           // in quirks mode, get the cb height using the special quirk method
    2308           0 :           if (!wm.IsVertical() &&
    2309           0 :               eCompatibility_NavQuirks == aPresContext->CompatibilityMode()) {
    2310           0 :             if (!IS_TABLE_CELL(fType)) {
    2311           0 :               cbSize.BSize(wm) = CalcQuirkContainingBlockHeight(cbrs);
    2312           0 :               if (cbSize.BSize(wm) == NS_AUTOHEIGHT) {
    2313           0 :                 blockSizeUnit = eStyleUnit_Auto;
    2314             :               }
    2315             :             }
    2316             :             else {
    2317           0 :               blockSizeUnit = eStyleUnit_Auto;
    2318             :             }
    2319             :           }
    2320             :           // in standard mode, use the cb block size.  if it's "auto",
    2321             :           // as will be the case by default in BODY, use auto block size
    2322             :           // as per CSS2 spec.
    2323             :           else
    2324             :           {
    2325           0 :             nscoord computedBSize = cbrs->ComputedSize(wm).BSize(wm);
    2326           0 :             if (NS_AUTOHEIGHT != computedBSize) {
    2327           0 :               cbSize.BSize(wm) = computedBSize;
    2328             :             }
    2329             :             else {
    2330           0 :               blockSizeUnit = eStyleUnit_Auto;
    2331             :             }
    2332           0 :           }
    2333             :         }
    2334             :         else {
    2335             :           // default to interpreting the blockSize like 'auto'
    2336           0 :           blockSizeUnit = eStyleUnit_Auto;
    2337             :         }
    2338             :       }
    2339             :     }
    2340             : 
    2341             :     // Compute our offsets if the element is relatively positioned.  We
    2342             :     // need the correct containing block inline-size and block-size
    2343             :     // here, which is why we need to do it after all the quirks-n-such
    2344             :     // above. (If the element is sticky positioned, we need to wait
    2345             :     // until the scroll container knows its size, so we compute offsets
    2346             :     // from StickyScrollContainer::UpdatePositions.)
    2347         397 :     if (mStyleDisplay->IsRelativelyPositioned(mFrame) &&
    2348           0 :         NS_STYLE_POSITION_RELATIVE == mStyleDisplay->mPosition) {
    2349           0 :       ComputeRelativeOffsets(cbwm, mFrame, cbSize.ConvertTo(cbwm, wm),
    2350           0 :                              ComputedPhysicalOffsets());
    2351             :     } else {
    2352             :       // Initialize offsets to 0
    2353         397 :       ComputedPhysicalOffsets().SizeTo(0, 0, 0, 0);
    2354             :     }
    2355             : 
    2356             :     // Calculate the computed values for min and max properties.  Note that
    2357             :     // this MUST come after we've computed our border and padding.
    2358         397 :     ComputeMinMaxValues(cbSize);
    2359             : 
    2360             :     // Calculate the computed inlineSize and blockSize.
    2361             :     // This varies by frame type.
    2362             : 
    2363         397 :     if (NS_CSS_FRAME_TYPE_INTERNAL_TABLE == mFrameType) {
    2364             :       // Internal table elements. The rules vary depending on the type.
    2365             :       // Calculate the computed isize
    2366           0 :       bool rowOrRowGroup = false;
    2367           0 :       const nsStyleCoord &inlineSize = mStylePosition->ISize(wm);
    2368           0 :       nsStyleUnit inlineSizeUnit = inlineSize.GetUnit();
    2369           0 :       if ((StyleDisplay::TableRow == mStyleDisplay->mDisplay) ||
    2370           0 :           (StyleDisplay::TableRowGroup == mStyleDisplay->mDisplay)) {
    2371             :         // 'inlineSize' property doesn't apply to table rows and row groups
    2372           0 :         inlineSizeUnit = eStyleUnit_Auto;
    2373           0 :         rowOrRowGroup = true;
    2374             :       }
    2375             : 
    2376             :       // calc() with percentages acts like auto on internal table elements
    2377           0 :       if (eStyleUnit_Auto == inlineSizeUnit ||
    2378           0 :           (inlineSize.IsCalcUnit() && inlineSize.CalcHasPercent())) {
    2379           0 :         ComputedISize() = AvailableISize();
    2380             : 
    2381           0 :         if ((ComputedISize() != NS_UNCONSTRAINEDSIZE) && !rowOrRowGroup){
    2382             :           // Internal table elements don't have margins. Only tables and
    2383             :           // cells have border and padding
    2384           0 :           ComputedISize() -= ComputedLogicalBorderPadding().IStartEnd(wm);
    2385           0 :           if (ComputedISize() < 0)
    2386           0 :             ComputedISize() = 0;
    2387             :         }
    2388           0 :         NS_ASSERTION(ComputedISize() >= 0, "Bogus computed isize");
    2389             : 
    2390             :       } else {
    2391           0 :         NS_ASSERTION(inlineSizeUnit == inlineSize.GetUnit(),
    2392             :                      "unexpected inline size unit change");
    2393           0 :         ComputedISize() = ComputeISizeValue(cbSize.ISize(wm),
    2394           0 :                                             mStylePosition->mBoxSizing,
    2395             :                                             inlineSize);
    2396             :       }
    2397             : 
    2398             :       // Calculate the computed block size
    2399           0 :       if ((StyleDisplay::TableColumn == mStyleDisplay->mDisplay) ||
    2400           0 :           (StyleDisplay::TableColumnGroup == mStyleDisplay->mDisplay)) {
    2401             :         // 'blockSize' property doesn't apply to table columns and column groups
    2402           0 :         blockSizeUnit = eStyleUnit_Auto;
    2403             :       }
    2404             :       // calc() with percentages acts like 'auto' on internal table elements
    2405           0 :       if (eStyleUnit_Auto == blockSizeUnit ||
    2406           0 :           (blockSize.IsCalcUnit() && blockSize.CalcHasPercent())) {
    2407           0 :         ComputedBSize() = NS_AUTOHEIGHT;
    2408             :       } else {
    2409           0 :         NS_ASSERTION(blockSizeUnit == blockSize.GetUnit(),
    2410             :                      "unexpected block size unit change");
    2411           0 :         ComputedBSize() = ComputeBSizeValue(cbSize.BSize(wm),
    2412           0 :                                             mStylePosition->mBoxSizing,
    2413             :                                             blockSize);
    2414             :       }
    2415             : 
    2416             :       // Doesn't apply to table elements
    2417           0 :       ComputedMinWidth() = ComputedMinHeight() = 0;
    2418           0 :       ComputedMaxWidth() = ComputedMaxHeight() = NS_UNCONSTRAINEDSIZE;
    2419             : 
    2420         397 :     } else if (NS_FRAME_GET_TYPE(mFrameType) == NS_CSS_FRAME_TYPE_ABSOLUTE) {
    2421             :       // XXX not sure if this belongs here or somewhere else - cwk
    2422          77 :       InitAbsoluteConstraints(aPresContext, cbrs, cbSize.ConvertTo(cbrs->GetWritingMode(), wm), aFrameType);
    2423             :     } else {
    2424         640 :       AutoMaybeDisableFontInflation an(mFrame);
    2425             : 
    2426         320 :       bool isBlock = NS_CSS_FRAME_TYPE_BLOCK == NS_FRAME_GET_TYPE(mFrameType);
    2427             :       typedef nsIFrame::ComputeSizeFlags ComputeSizeFlags;
    2428             :       ComputeSizeFlags computeSizeFlags =
    2429         320 :         isBlock ? ComputeSizeFlags::eDefault : ComputeSizeFlags::eShrinkWrap;
    2430         320 :       if (mFlags.mIClampMarginBoxMinSize) {
    2431           0 :         computeSizeFlags = ComputeSizeFlags(computeSizeFlags |
    2432             :                              ComputeSizeFlags::eIClampMarginBoxMinSize);
    2433             :       }
    2434         320 :       if (mFlags.mBClampMarginBoxMinSize) {
    2435           0 :         computeSizeFlags = ComputeSizeFlags(computeSizeFlags |
    2436             :                              ComputeSizeFlags::eBClampMarginBoxMinSize);
    2437             :       }
    2438         320 :       if (mFlags.mApplyAutoMinSize) {
    2439           0 :         computeSizeFlags = ComputeSizeFlags(computeSizeFlags |
    2440             :                              ComputeSizeFlags::eIApplyAutoMinSize);
    2441             :       }
    2442         320 :       if (mFlags.mShrinkWrap) {
    2443           0 :         computeSizeFlags =
    2444           0 :           ComputeSizeFlags(computeSizeFlags | ComputeSizeFlags::eShrinkWrap);
    2445             :       }
    2446         320 :       if (mFlags.mUseAutoBSize) {
    2447           0 :         computeSizeFlags =
    2448           0 :           ComputeSizeFlags(computeSizeFlags | ComputeSizeFlags::eUseAutoBSize);
    2449             :       }
    2450             : 
    2451         320 :       nsIFrame* alignCB = mFrame->GetParent();
    2452         320 :       if (alignCB->IsTableWrapperFrame() && alignCB->GetParent()) {
    2453             :         // XXX grid-specific for now; maybe remove this check after we address bug 799725
    2454           0 :         if (alignCB->GetParent()->IsGridContainerFrame()) {
    2455           0 :           alignCB = alignCB->GetParent();
    2456             :         }
    2457             :       }
    2458         320 :       if (alignCB->IsGridContainerFrame()) {
    2459             :         // Shrink-wrap grid items that will be aligned (rather than stretched)
    2460             :         // in its inline axis.
    2461             :         auto inlineAxisAlignment =
    2462           0 :           wm.IsOrthogonalTo(cbwm)
    2463           0 :             ? mStylePosition->UsedAlignSelf(alignCB->StyleContext())
    2464           0 :             : mStylePosition->UsedJustifySelf(alignCB->StyleContext());
    2465           0 :         if ((inlineAxisAlignment != NS_STYLE_ALIGN_STRETCH &&
    2466           0 :              inlineAxisAlignment != NS_STYLE_ALIGN_NORMAL) ||
    2467           0 :             mStyleMargin->mMargin.GetIStartUnit(wm) == eStyleUnit_Auto ||
    2468           0 :             mStyleMargin->mMargin.GetIEndUnit(wm) == eStyleUnit_Auto) {
    2469           0 :           computeSizeFlags =
    2470           0 :             ComputeSizeFlags(computeSizeFlags | ComputeSizeFlags::eShrinkWrap);
    2471             :         }
    2472             :       } else {
    2473             :         // Make sure legend frames with display:block and width:auto still
    2474             :         // shrink-wrap.
    2475             :         // Also shrink-wrap blocks that are orthogonal to their container.
    2476         703 :         if (isBlock &&
    2477           0 :             ((aFrameType == LayoutFrameType::Legend &&
    2478         257 :               mFrame->StyleContext()->GetPseudo() != nsCSSAnonBoxes::scrolledContent) ||
    2479          43 :              (aFrameType == LayoutFrameType::Scroll &&
    2480         300 :               mFrame->GetContentInsertionFrame()->IsLegendFrame()) ||
    2481         771 :              (mCBReflowInput &&
    2482        1091 :               mCBReflowInput->GetWritingMode().IsOrthogonalTo(mWritingMode)))) {
    2483           0 :           computeSizeFlags =
    2484           0 :             ComputeSizeFlags(computeSizeFlags | ComputeSizeFlags::eShrinkWrap);
    2485             :         }
    2486             : 
    2487         320 :         if (alignCB->IsFlexContainerFrame()) {
    2488           0 :           computeSizeFlags =
    2489           0 :             ComputeSizeFlags(computeSizeFlags | ComputeSizeFlags::eShrinkWrap);
    2490             : 
    2491             :           // If we're inside of a flex container that needs to measure our
    2492             :           // auto height, pass that information along to ComputeSize().
    2493           0 :           if (mFlags.mIsFlexContainerMeasuringHeight) {
    2494           0 :             computeSizeFlags =
    2495           0 :               ComputeSizeFlags(computeSizeFlags | ComputeSizeFlags::eUseAutoBSize);
    2496             :           }
    2497             :         } else {
    2498         320 :           MOZ_ASSERT(!mFlags.mIsFlexContainerMeasuringHeight,
    2499             :                      "We're not in a flex container, so the flag "
    2500             :                      "'mIsFlexContainerMeasuringHeight' shouldn't be set");
    2501             :         }
    2502             :       }
    2503             : 
    2504         320 :       if (cbSize.ISize(wm) == NS_UNCONSTRAINEDSIZE) {
    2505             :         // For orthogonal flows, where we found a parent orthogonal-limit
    2506             :         // for AvailableISize() in Init(), we'll use the same here as well.
    2507           0 :         cbSize.ISize(wm) = AvailableISize();
    2508             :       }
    2509             : 
    2510             :       LogicalSize size =
    2511         960 :         mFrame->ComputeSize(mRenderingContext, wm, cbSize, AvailableISize(),
    2512         640 :                            ComputedLogicalMargin().Size(wm),
    2513         640 :                            ComputedLogicalBorderPadding().Size(wm) -
    2514         640 :                              ComputedLogicalPadding().Size(wm),
    2515         640 :                            ComputedLogicalPadding().Size(wm),
    2516         960 :                            computeSizeFlags);
    2517             : 
    2518         320 :       ComputedISize() = size.ISize(wm);
    2519         320 :       ComputedBSize() = size.BSize(wm);
    2520         320 :       NS_ASSERTION(ComputedISize() >= 0, "Bogus inline-size");
    2521         320 :       NS_ASSERTION(ComputedBSize() == NS_UNCONSTRAINEDSIZE ||
    2522             :                    ComputedBSize() >= 0, "Bogus block-size");
    2523             : 
    2524             :       // Exclude inline tables, side captions, flex and grid items from block
    2525             :       // margin calculations.
    2526         834 :       if (isBlock && !IsSideCaption(mFrame, mStyleDisplay, cbwm) &&
    2527         834 :           mStyleDisplay->mDisplay != StyleDisplay::InlineTable &&
    2528         257 :           !alignCB->IsFlexOrGridContainer()) {
    2529         257 :         CalculateBlockSideMargins(aFrameType);
    2530             :       }
    2531             :     }
    2532             :   }
    2533             : 
    2534             :   // Save our containing block dimensions
    2535         652 :   mContainingBlockSize = aContainingBlockSize;
    2536         652 : }
    2537             : 
    2538             : static void
    2539        1304 : UpdateProp(nsIFrame* aFrame,
    2540             :            const FramePropertyDescriptor<nsMargin>* aProperty,
    2541             :            bool aNeeded,
    2542             :            nsMargin& aNewValue)
    2543             : {
    2544        1304 :   if (aNeeded) {
    2545          22 :     nsMargin* propValue = aFrame->GetProperty(aProperty);
    2546          22 :     if (propValue) {
    2547          14 :       *propValue = aNewValue;
    2548             :     } else {
    2549           8 :       aFrame->AddProperty(aProperty, new nsMargin(aNewValue));
    2550             :     }
    2551             :   } else {
    2552        1282 :     aFrame->DeleteProperty(aProperty);
    2553             :   }
    2554        1304 : }
    2555             : 
    2556             : void
    2557         652 : SizeComputationInput::InitOffsets(WritingMode aWM,
    2558             :                                   const LogicalSize& aPercentBasis,
    2559             :                                   LayoutFrameType aFrameType,
    2560             :                                   ReflowInputFlags aFlags,
    2561             :                                   const nsMargin* aBorder,
    2562             :                                   const nsMargin* aPadding,
    2563             :                                   const nsStyleDisplay* aDisplay)
    2564             : {
    2565        1304 :   DISPLAY_INIT_OFFSETS(mFrame, this, aPercentBasis, aWM, aBorder, aPadding);
    2566             : 
    2567             :   // Since we are in reflow, we don't need to store these properties anymore
    2568             :   // unless they are dependent on width, in which case we store the new value.
    2569         652 :   nsPresContext *presContext = mFrame->PresContext();
    2570         652 :   mFrame->DeleteProperty(nsIFrame::UsedBorderProperty());
    2571             : 
    2572             :   // Compute margins from the specified margin style information. These
    2573             :   // become the default computed values, and may be adjusted below
    2574             :   // XXX fix to provide 0,0 for the top&bottom margins for
    2575             :   // inline-non-replaced elements
    2576         652 :   bool needMarginProp = ComputeMargin(aWM, aPercentBasis);
    2577             :   // XXX We need to include 'auto' horizontal margins in this too!
    2578             :   // ... but if we did that, we'd need to fix nsFrame::GetUsedMargin
    2579             :   // to use it even when the margins are all zero (since sometimes
    2580             :   // they get treated as auto)
    2581         652 :   ::UpdateProp(mFrame, nsIFrame::UsedMarginProperty(), needMarginProp,
    2582         652 :                ComputedPhysicalMargin());
    2583             : 
    2584             : 
    2585         652 :   const nsStyleDisplay* disp = mFrame->StyleDisplayWithOptionalParam(aDisplay);
    2586         652 :   bool isThemed = mFrame->IsThemed(disp);
    2587             :   bool needPaddingProp;
    2588         652 :   nsIntMargin widget;
    2589         660 :   if (isThemed &&
    2590          16 :       presContext->GetTheme()->GetWidgetPadding(presContext->DeviceContext(),
    2591           8 :                                                 mFrame, disp->mAppearance,
    2592           8 :                                                 &widget)) {
    2593           0 :     ComputedPhysicalPadding().top = presContext->DevPixelsToAppUnits(widget.top);
    2594           0 :     ComputedPhysicalPadding().right = presContext->DevPixelsToAppUnits(widget.right);
    2595           0 :     ComputedPhysicalPadding().bottom = presContext->DevPixelsToAppUnits(widget.bottom);
    2596           0 :     ComputedPhysicalPadding().left = presContext->DevPixelsToAppUnits(widget.left);
    2597           0 :     needPaddingProp = false;
    2598             :   }
    2599         652 :   else if (nsSVGUtils::IsInSVGTextSubtree(mFrame)) {
    2600           0 :     ComputedPhysicalPadding().SizeTo(0, 0, 0, 0);
    2601           0 :     needPaddingProp = false;
    2602             :   }
    2603         652 :   else if (aPadding) { // padding is an input arg
    2604         167 :     ComputedPhysicalPadding() = *aPadding;
    2605         334 :     needPaddingProp = mFrame->StylePadding()->IsWidthDependent() ||
    2606         167 :           (mFrame->GetStateBits() & NS_FRAME_REFLOW_ROOT);
    2607             :   }
    2608             :   else {
    2609         485 :     needPaddingProp = ComputePadding(aWM, aPercentBasis, aFrameType);
    2610             :   }
    2611             : 
    2612             :   // Add [align|justify]-content:baseline padding contribution.
    2613             :   typedef const FramePropertyDescriptor<SmallValueHolder<nscoord>>* Prop;
    2614             :   auto ApplyBaselinePadding = [this, &needPaddingProp]
    2615        1304 :          (LogicalAxis aAxis, Prop aProp) {
    2616             :     bool found;
    2617        1304 :     nscoord val = mFrame->GetProperty(aProp, &found);
    2618        1304 :     if (found) {
    2619           0 :       NS_ASSERTION(val != nscoord(0), "zero in this property is useless");
    2620           0 :       WritingMode wm = GetWritingMode();
    2621             :       LogicalSide side;
    2622           0 :       if (val > 0) {
    2623           0 :         side = MakeLogicalSide(aAxis, eLogicalEdgeStart);
    2624             :       } else {
    2625           0 :         side = MakeLogicalSide(aAxis, eLogicalEdgeEnd);
    2626           0 :         val = -val;
    2627             :       }
    2628           0 :       mComputedPadding.Side(wm.PhysicalSide(side)) += val;
    2629           0 :       needPaddingProp = true;
    2630             :     }
    2631        1956 :   };
    2632         652 :   if (!aFlags.mUseAutoBSize) {
    2633         652 :     ApplyBaselinePadding(eLogicalAxisBlock, nsIFrame::BBaselinePadProperty());
    2634             :   }
    2635         652 :   if (!aFlags.mShrinkWrap) {
    2636         652 :     ApplyBaselinePadding(eLogicalAxisInline, nsIFrame::IBaselinePadProperty());
    2637             :   }
    2638             : 
    2639         652 :   if (isThemed) {
    2640           8 :     nsIntMargin widget;
    2641          16 :     presContext->GetTheme()->GetWidgetBorder(presContext->DeviceContext(),
    2642           8 :                                              mFrame, disp->mAppearance,
    2643          16 :                                              &widget);
    2644          16 :     ComputedPhysicalBorderPadding().top =
    2645           8 :       presContext->DevPixelsToAppUnits(widget.top);
    2646          16 :     ComputedPhysicalBorderPadding().right =
    2647           8 :       presContext->DevPixelsToAppUnits(widget.right);
    2648          16 :     ComputedPhysicalBorderPadding().bottom =
    2649           8 :       presContext->DevPixelsToAppUnits(widget.bottom);
    2650          16 :     ComputedPhysicalBorderPadding().left =
    2651           8 :       presContext->DevPixelsToAppUnits(widget.left);
    2652             :   }
    2653         644 :   else if (nsSVGUtils::IsInSVGTextSubtree(mFrame)) {
    2654           0 :     ComputedPhysicalBorderPadding().SizeTo(0, 0, 0, 0);
    2655             :   }
    2656         644 :   else if (aBorder) {  // border is an input arg
    2657           0 :     ComputedPhysicalBorderPadding() = *aBorder;
    2658             :   }
    2659             :   else {
    2660         644 :     ComputedPhysicalBorderPadding() = mFrame->StyleBorder()->GetComputedBorder();
    2661             :   }
    2662         652 :   ComputedPhysicalBorderPadding() += ComputedPhysicalPadding();
    2663             : 
    2664         652 :   if (aFrameType == LayoutFrameType::Table) {
    2665           0 :     nsTableFrame *tableFrame = static_cast<nsTableFrame*>(mFrame);
    2666             : 
    2667           0 :     if (tableFrame->IsBorderCollapse()) {
    2668             :       // border-collapsed tables don't use any of their padding, and
    2669             :       // only part of their border.  We need to do this here before we
    2670             :       // try to do anything like handling 'auto' widths,
    2671             :       // 'box-sizing', or 'auto' margins.
    2672           0 :       ComputedPhysicalPadding().SizeTo(0,0,0,0);
    2673             :       SetComputedLogicalBorderPadding(
    2674           0 :         tableFrame->GetIncludedOuterBCBorder(mWritingMode));
    2675             :     }
    2676             : 
    2677             :     // The margin is inherited to the table wrapper frame via
    2678             :     // the ::-moz-table-wrapper rule in ua.css.
    2679           0 :     ComputedPhysicalMargin().SizeTo(0, 0, 0, 0);
    2680         652 :   } else if (aFrameType == LayoutFrameType::Scrollbar) {
    2681             :     // scrollbars may have had their width or height smashed to zero
    2682             :     // by the associated scrollframe, in which case we must not report
    2683             :     // any padding or border.
    2684           4 :     nsSize size(mFrame->GetSize());
    2685           4 :     if (size.width == 0 || size.height == 0) {
    2686           4 :       ComputedPhysicalPadding().SizeTo(0,0,0,0);
    2687           4 :       ComputedPhysicalBorderPadding().SizeTo(0,0,0,0);
    2688             :     }
    2689             :   }
    2690         652 :   ::UpdateProp(mFrame, nsIFrame::UsedPaddingProperty(), needPaddingProp,
    2691         652 :                ComputedPhysicalPadding());
    2692         652 : }
    2693             : 
    2694             : // This code enforces section 10.3.3 of the CSS2 spec for this formula:
    2695             : //
    2696             : // 'margin-left' + 'border-left-width' + 'padding-left' + 'width' +
    2697             : //   'padding-right' + 'border-right-width' + 'margin-right'
    2698             : //   = width of containing block
    2699             : //
    2700             : // Note: the width unit is not auto when this is called
    2701             : void
    2702         257 : ReflowInput::CalculateBlockSideMargins(LayoutFrameType aFrameType)
    2703             : {
    2704             :   // Calculations here are done in the containing block's writing mode,
    2705             :   // which is where margins will eventually be applied: we're calculating
    2706             :   // margins that will be used by the container in its inline direction,
    2707             :   // which in the case of an orthogonal contained block will correspond to
    2708             :   // the block direction of this reflow state. So in the orthogonal-flow
    2709             :   // case, "CalculateBlock*Side*Margins" will actually end up adjusting
    2710             :   // the BStart/BEnd margins; those are the "sides" of the block from its
    2711             :   // container's point of view.
    2712             :   WritingMode cbWM =
    2713         257 :     mCBReflowInput ? mCBReflowInput->GetWritingMode(): GetWritingMode();
    2714             : 
    2715         257 :   nscoord availISizeCBWM = AvailableSize(cbWM).ISize(cbWM);
    2716         257 :   nscoord computedISizeCBWM = ComputedSize(cbWM).ISize(cbWM);
    2717         257 :   if (computedISizeCBWM == NS_UNCONSTRAINEDSIZE) {
    2718             :     // For orthogonal flows, where we found a parent orthogonal-limit
    2719             :     // for AvailableISize() in Init(), we'll use the same here as well.
    2720           0 :     computedISizeCBWM = availISizeCBWM;
    2721             :   }
    2722             : 
    2723         257 :   LAYOUT_WARN_IF_FALSE(NS_UNCONSTRAINEDSIZE != computedISizeCBWM &&
    2724             :                        NS_UNCONSTRAINEDSIZE != availISizeCBWM,
    2725             :                        "have unconstrained inline-size; this should only "
    2726             :                        "result from very large sizes, not attempts at "
    2727             :                        "intrinsic inline-size calculation");
    2728             : 
    2729             :   LogicalMargin margin =
    2730         257 :     ComputedLogicalMargin().ConvertTo(cbWM, mWritingMode);
    2731             :   LogicalMargin borderPadding =
    2732         257 :     ComputedLogicalBorderPadding().ConvertTo(cbWM, mWritingMode);
    2733         514 :   nscoord sum = margin.IStartEnd(cbWM) +
    2734         514 :     borderPadding.IStartEnd(cbWM) + computedISizeCBWM;
    2735         257 :   if (sum == availISizeCBWM) {
    2736             :     // The sum is already correct
    2737         514 :     return;
    2738             :   }
    2739             : 
    2740             :   // Determine the start and end margin values. The isize value
    2741             :   // remains constant while we do this.
    2742             : 
    2743             :   // Calculate how much space is available for margins
    2744           0 :   nscoord availMarginSpace = availISizeCBWM - sum;
    2745             : 
    2746             :   // If the available margin space is negative, then don't follow the
    2747             :   // usual overconstraint rules.
    2748           0 :   if (availMarginSpace < 0) {
    2749           0 :     margin.IEnd(cbWM) += availMarginSpace;
    2750           0 :     SetComputedLogicalMargin(margin.ConvertTo(mWritingMode, cbWM));
    2751           0 :     return;
    2752             :   }
    2753             : 
    2754             :   // The css2 spec clearly defines how block elements should behave
    2755             :   // in section 10.3.3.
    2756           0 :   const nsStyleSides& styleSides = mStyleMargin->mMargin;
    2757           0 :   bool isAutoStartMargin = eStyleUnit_Auto == styleSides.GetIStartUnit(cbWM);
    2758           0 :   bool isAutoEndMargin = eStyleUnit_Auto == styleSides.GetIEndUnit(cbWM);
    2759           0 :   if (!isAutoStartMargin && !isAutoEndMargin) {
    2760             :     // Neither margin is 'auto' so we're over constrained. Use the
    2761             :     // 'direction' property of the parent to tell which margin to
    2762             :     // ignore
    2763             :     // First check if there is an HTML alignment that we should honor
    2764           0 :     const ReflowInput* prs = mParentReflowInput;
    2765           0 :     if (aFrameType == LayoutFrameType::Table) {
    2766           0 :       NS_ASSERTION(prs->mFrame->IsTableWrapperFrame(),
    2767             :                    "table not inside table wrapper");
    2768             :       // Center the table within the table wrapper based on the alignment
    2769             :       // of the table wrapper's parent.
    2770           0 :       prs = prs->mParentReflowInput;
    2771             :     }
    2772           0 :     if (prs &&
    2773           0 :         (prs->mStyleText->mTextAlign == NS_STYLE_TEXT_ALIGN_MOZ_LEFT ||
    2774           0 :          prs->mStyleText->mTextAlign == NS_STYLE_TEXT_ALIGN_MOZ_CENTER ||
    2775           0 :          prs->mStyleText->mTextAlign == NS_STYLE_TEXT_ALIGN_MOZ_RIGHT)) {
    2776           0 :       if (prs->mWritingMode.IsBidiLTR()) {
    2777           0 :         isAutoStartMargin =
    2778           0 :           prs->mStyleText->mTextAlign != NS_STYLE_TEXT_ALIGN_MOZ_LEFT;
    2779           0 :         isAutoEndMargin =
    2780           0 :           prs->mStyleText->mTextAlign != NS_STYLE_TEXT_ALIGN_MOZ_RIGHT;
    2781             :       } else {
    2782           0 :         isAutoStartMargin =
    2783           0 :           prs->mStyleText->mTextAlign != NS_STYLE_TEXT_ALIGN_MOZ_RIGHT;
    2784           0 :         isAutoEndMargin =
    2785           0 :           prs->mStyleText->mTextAlign != NS_STYLE_TEXT_ALIGN_MOZ_LEFT;
    2786             :       }
    2787             :     }
    2788             :     // Otherwise apply the CSS rules, and ignore one margin by forcing
    2789             :     // it to 'auto', depending on 'direction'.
    2790             :     else {
    2791           0 :       isAutoEndMargin = true;
    2792             :     }
    2793             :   }
    2794             : 
    2795             :   // Logic which is common to blocks and tables
    2796             :   // The computed margins need not be zero because the 'auto' could come from
    2797             :   // overconstraint or from HTML alignment so values need to be accumulated
    2798             : 
    2799           0 :   if (isAutoStartMargin) {
    2800           0 :     if (isAutoEndMargin) {
    2801             :       // Both margins are 'auto' so the computed addition should be equal
    2802           0 :       nscoord forStart = availMarginSpace / 2;
    2803           0 :       margin.IStart(cbWM) += forStart;
    2804           0 :       margin.IEnd(cbWM) += availMarginSpace - forStart;
    2805             :     } else {
    2806           0 :       margin.IStart(cbWM) += availMarginSpace;
    2807             :     }
    2808           0 :   } else if (isAutoEndMargin) {
    2809           0 :     margin.IEnd(cbWM) += availMarginSpace;
    2810             :   }
    2811           0 :   SetComputedLogicalMargin(margin.ConvertTo(mWritingMode, cbWM));
    2812             : }
    2813             : 
    2814             : #define NORMAL_LINE_HEIGHT_FACTOR 1.2f    // in term of emHeight
    2815             : // For "normal" we use the font's normal line height (em height + leading).
    2816             : // If both internal leading and  external leading specified by font itself
    2817             : // are zeros, we should compensate this by creating extra (external) leading
    2818             : // in eCompensateLeading mode. This is necessary because without this
    2819             : // compensation, normal line height might looks too tight.
    2820             : 
    2821             : // For risk management, we use preference to control the behavior, and
    2822             : // eNoExternalLeading is the old behavior.
    2823             : static nscoord
    2824         147 : GetNormalLineHeight(nsFontMetrics* aFontMetrics)
    2825             : {
    2826         147 :   NS_PRECONDITION(nullptr != aFontMetrics, "no font metrics");
    2827             : 
    2828             :   nscoord normalLineHeight;
    2829             : 
    2830         147 :   nscoord externalLeading = aFontMetrics->ExternalLeading();
    2831         147 :   nscoord internalLeading = aFontMetrics->InternalLeading();
    2832         147 :   nscoord emHeight = aFontMetrics->EmHeight();
    2833         147 :   switch (GetNormalLineHeightCalcControl()) {
    2834             :   case eIncludeExternalLeading:
    2835           0 :     normalLineHeight = emHeight+ internalLeading + externalLeading;
    2836           0 :     break;
    2837             :   case eCompensateLeading:
    2838         147 :     if (!internalLeading && !externalLeading)
    2839           0 :       normalLineHeight = NSToCoordRound(emHeight * NORMAL_LINE_HEIGHT_FACTOR);
    2840             :     else
    2841         147 :       normalLineHeight = emHeight+ internalLeading + externalLeading;
    2842         147 :     break;
    2843             :   default:
    2844             :     //case eNoExternalLeading:
    2845           0 :     normalLineHeight = emHeight + internalLeading;
    2846             :   }
    2847         147 :   return normalLineHeight;
    2848             : }
    2849             : 
    2850             : static inline nscoord
    2851         192 : ComputeLineHeight(nsStyleContext* aStyleContext,
    2852             :                   nscoord aBlockBSize,
    2853             :                   float aFontSizeInflation)
    2854             : {
    2855         192 :   const nsStyleCoord& lhCoord = aStyleContext->StyleText()->mLineHeight;
    2856             : 
    2857         192 :   if (lhCoord.GetUnit() == eStyleUnit_Coord) {
    2858           0 :     nscoord result = lhCoord.GetCoordValue();
    2859           0 :     if (aFontSizeInflation != 1.0f) {
    2860           0 :       result = NSToCoordRound(result * aFontSizeInflation);
    2861             :     }
    2862           0 :     return result;
    2863             :   }
    2864             : 
    2865         192 :   if (lhCoord.GetUnit() == eStyleUnit_Factor)
    2866             :     // For factor units the computed value of the line-height property
    2867             :     // is found by multiplying the factor by the font's computed size
    2868             :     // (adjusted for min-size prefs and text zoom).
    2869           0 :     return NSToCoordRound(lhCoord.GetFactorValue() * aFontSizeInflation *
    2870           0 :                           aStyleContext->StyleFont()->mFont.size);
    2871             : 
    2872         192 :   NS_ASSERTION(lhCoord.GetUnit() == eStyleUnit_Normal ||
    2873             :                lhCoord.GetUnit() == eStyleUnit_Enumerated,
    2874             :                "bad line-height unit");
    2875             : 
    2876         192 :   if (lhCoord.GetUnit() == eStyleUnit_Enumerated) {
    2877          46 :     NS_ASSERTION(lhCoord.GetIntValue() == NS_STYLE_LINE_HEIGHT_BLOCK_HEIGHT,
    2878             :                  "bad line-height value");
    2879          46 :     if (aBlockBSize != NS_AUTOHEIGHT) {
    2880          45 :       return aBlockBSize;
    2881             :     }
    2882             :   }
    2883             : 
    2884             :   RefPtr<nsFontMetrics> fm = nsLayoutUtils::
    2885         294 :     GetFontMetricsForStyleContext(aStyleContext, aFontSizeInflation);
    2886         147 :   return GetNormalLineHeight(fm);
    2887             : }
    2888             : 
    2889             : nscoord
    2890         171 : ReflowInput::CalcLineHeight() const
    2891             : {
    2892             :   nscoord blockBSize =
    2893         180 :     nsLayoutUtils::IsNonWrapperBlock(mFrame) ? ComputedBSize() :
    2894         180 :     (mCBReflowInput ? mCBReflowInput->ComputedBSize() : NS_AUTOHEIGHT);
    2895             : 
    2896         171 :   return CalcLineHeight(mFrame->GetContent(), mFrame->StyleContext(), blockBSize,
    2897         342 :                         nsLayoutUtils::FontSizeInflationFor(mFrame));
    2898             : }
    2899             : 
    2900             : /* static */ nscoord
    2901         192 : ReflowInput::CalcLineHeight(nsIContent* aContent,
    2902             :                                   nsStyleContext* aStyleContext,
    2903             :                                   nscoord aBlockBSize,
    2904             :                                   float aFontSizeInflation)
    2905             : {
    2906         192 :   NS_PRECONDITION(aStyleContext, "Must have a style context");
    2907             : 
    2908             :   nscoord lineHeight =
    2909         192 :     ComputeLineHeight(aStyleContext, aBlockBSize, aFontSizeInflation);
    2910             : 
    2911         192 :   NS_ASSERTION(lineHeight >= 0, "ComputeLineHeight screwed up");
    2912             : 
    2913         192 :   HTMLInputElement* input = HTMLInputElement::FromContentOrNull(aContent);
    2914         192 :   if (input && input->IsSingleLineTextControl()) {
    2915             :     // For Web-compatibility, single-line text input elements cannot
    2916             :     // have a line-height smaller than one.
    2917             :     nscoord lineHeightOne =
    2918          20 :       aFontSizeInflation * aStyleContext->StyleFont()->mFont.size;
    2919          20 :     if (lineHeight < lineHeightOne) {
    2920           0 :       lineHeight = lineHeightOne;
    2921             :     }
    2922             :   }
    2923             : 
    2924         192 :   return lineHeight;
    2925             : }
    2926             : 
    2927             : bool
    2928         652 : SizeComputationInput::ComputeMargin(WritingMode aWM,
    2929             :                                 const LogicalSize& aPercentBasis)
    2930             : {
    2931             :   // SVG text frames have no margin.
    2932         652 :   if (nsSVGUtils::IsInSVGTextSubtree(mFrame)) {
    2933           0 :     return false;
    2934             :   }
    2935             : 
    2936             :   // If style style can provide us the margin directly, then use it.
    2937         652 :   const nsStyleMargin *styleMargin = mFrame->StyleMargin();
    2938             : 
    2939         652 :   bool isCBDependent = !styleMargin->GetMargin(ComputedPhysicalMargin());
    2940         652 :   if (isCBDependent) {
    2941             :     // We have to compute the value. Note that this calculation is
    2942             :     // performed according to the writing mode of the containing block
    2943             :     // (http://dev.w3.org/csswg/css-writing-modes-3/#orthogonal-flows)
    2944           0 :     LogicalMargin m(aWM);
    2945           0 :     m.IStart(aWM) = nsLayoutUtils::
    2946           0 :       ComputeCBDependentValue(aPercentBasis.ISize(aWM),
    2947           0 :                               styleMargin->mMargin.GetIStart(aWM));
    2948           0 :     m.IEnd(aWM) = nsLayoutUtils::
    2949           0 :       ComputeCBDependentValue(aPercentBasis.ISize(aWM),
    2950           0 :                               styleMargin->mMargin.GetIEnd(aWM));
    2951             : 
    2952           0 :     m.BStart(aWM) = nsLayoutUtils::
    2953           0 :       ComputeCBDependentValue(aPercentBasis.BSize(aWM),
    2954           0 :                               styleMargin->mMargin.GetBStart(aWM));
    2955           0 :     m.BEnd(aWM) = nsLayoutUtils::
    2956           0 :       ComputeCBDependentValue(aPercentBasis.BSize(aWM),
    2957           0 :                               styleMargin->mMargin.GetBEnd(aWM));
    2958             : 
    2959           0 :     SetComputedLogicalMargin(aWM, m);
    2960             :   }
    2961             : 
    2962             :   // ... but font-size-inflation-based margin adjustment uses the
    2963             :   // frame's writing mode
    2964         652 :   nscoord marginAdjustment = FontSizeInflationListMarginAdjustment(mFrame);
    2965             : 
    2966         652 :   if (marginAdjustment > 0) {
    2967           0 :     LogicalMargin m = ComputedLogicalMargin();
    2968           0 :     m.IStart(mWritingMode) += marginAdjustment;
    2969           0 :     SetComputedLogicalMargin(m);
    2970             :   }
    2971             : 
    2972         652 :   return isCBDependent;
    2973             : }
    2974             : 
    2975             : bool
    2976         485 : SizeComputationInput::ComputePadding(WritingMode aWM,
    2977             :                                      const LogicalSize& aPercentBasis,
    2978             :                                      LayoutFrameType aFrameType)
    2979             : {
    2980             :   // If style can provide us the padding directly, then use it.
    2981         485 :   const nsStylePadding *stylePadding = mFrame->StylePadding();
    2982         485 :   bool isCBDependent = !stylePadding->GetPadding(ComputedPhysicalPadding());
    2983             :   // a table row/col group, row/col doesn't have padding
    2984             :   // XXXldb Neither do border-collapse tables.
    2985         485 :   if (LayoutFrameType::TableRowGroup == aFrameType ||
    2986         485 :       LayoutFrameType::TableColGroup == aFrameType ||
    2987         485 :       LayoutFrameType::TableRow      == aFrameType ||
    2988             :       LayoutFrameType::TableCol      == aFrameType) {
    2989           0 :     ComputedPhysicalPadding().SizeTo(0,0,0,0);
    2990             :   }
    2991         485 :   else if (isCBDependent) {
    2992             :     // We have to compute the value. This calculation is performed
    2993             :     // according to the writing mode of the containing block
    2994             :     // (http://dev.w3.org/csswg/css-writing-modes-3/#orthogonal-flows)
    2995             :     // clamp negative calc() results to 0
    2996           0 :     LogicalMargin p(aWM);
    2997           0 :     p.IStart(aWM) = std::max(0, nsLayoutUtils::
    2998           0 :       ComputeCBDependentValue(aPercentBasis.ISize(aWM),
    2999           0 :                               stylePadding->mPadding.GetIStart(aWM)));
    3000           0 :     p.IEnd(aWM) = std::max(0, nsLayoutUtils::
    3001           0 :       ComputeCBDependentValue(aPercentBasis.ISize(aWM),
    3002           0 :                               stylePadding->mPadding.GetIEnd(aWM)));
    3003             : 
    3004           0 :     p.BStart(aWM) = std::max(0, nsLayoutUtils::
    3005           0 :       ComputeCBDependentValue(aPercentBasis.BSize(aWM),
    3006           0 :                               stylePadding->mPadding.GetBStart(aWM)));
    3007           0 :     p.BEnd(aWM) = std::max(0, nsLayoutUtils::
    3008           0 :       ComputeCBDependentValue(aPercentBasis.BSize(aWM),
    3009           0 :                               stylePadding->mPadding.GetBEnd(aWM)));
    3010             : 
    3011           0 :     SetComputedLogicalPadding(aWM, p);
    3012             :   }
    3013         485 :   return isCBDependent;
    3014             : }
    3015             : 
    3016             : void
    3017         397 : ReflowInput::ComputeMinMaxValues(const LogicalSize&aCBSize)
    3018             : {
    3019         397 :   WritingMode wm = GetWritingMode();
    3020             : 
    3021         397 :   const nsStyleCoord& minISize = mStylePosition->MinISize(wm);
    3022         397 :   const nsStyleCoord& maxISize = mStylePosition->MaxISize(wm);
    3023         397 :   const nsStyleCoord& minBSize = mStylePosition->MinBSize(wm);
    3024         397 :   const nsStyleCoord& maxBSize = mStylePosition->MaxBSize(wm);
    3025             : 
    3026             :   // NOTE: min-width:auto resolves to 0, except on a flex item. (But
    3027             :   // even there, it's supposed to be ignored (i.e. treated as 0) until
    3028             :   // the flex container explicitly resolves & considers it.)
    3029         397 :   if (eStyleUnit_Auto == minISize.GetUnit()) {
    3030         345 :     ComputedMinISize() = 0;
    3031             :   } else {
    3032         104 :     ComputedMinISize() = ComputeISizeValue(aCBSize.ISize(wm),
    3033          52 :                                            mStylePosition->mBoxSizing,
    3034             :                                            minISize);
    3035             :   }
    3036             : 
    3037         397 :   if (eStyleUnit_None == maxISize.GetUnit()) {
    3038             :     // Specified value of 'none'
    3039         343 :     ComputedMaxISize() = NS_UNCONSTRAINEDSIZE;  // no limit
    3040             :   } else {
    3041         108 :     ComputedMaxISize() = ComputeISizeValue(aCBSize.ISize(wm),
    3042          54 :                                            mStylePosition->mBoxSizing,
    3043             :                                            maxISize);
    3044             :   }
    3045             : 
    3046             :   // If the computed value of 'min-width' is greater than the value of
    3047             :   // 'max-width', 'max-width' is set to the value of 'min-width'
    3048         397 :   if (ComputedMinISize() > ComputedMaxISize()) {
    3049           0 :     ComputedMaxISize() = ComputedMinISize();
    3050             :   }
    3051             : 
    3052             :   // Check for percentage based values and a containing block height that
    3053             :   // depends on the content height. Treat them like 'auto'
    3054             :   // Likewise, check for calc() with percentages on internal table elements;
    3055             :   // that's treated as 'auto' too.
    3056             :   // Likewise, if we're a child of a flex container who's measuring our
    3057             :   // intrinsic height, then we want to disregard our min-height.
    3058             : 
    3059             :   // NOTE: min-height:auto resolves to 0, except on a flex item. (But
    3060             :   // even there, it's supposed to be ignored (i.e. treated as 0) until
    3061             :   // the flex container explicitly resolves & considers it.)
    3062         840 :   if (eStyleUnit_Auto == minBSize.GetUnit() ||
    3063          46 :       (NS_AUTOHEIGHT == aCBSize.BSize(wm) &&
    3064          46 :        minBSize.HasPercent()) ||
    3065          46 :       (mFrameType == NS_CSS_FRAME_TYPE_INTERNAL_TABLE &&
    3066         443 :        minBSize.IsCalcUnit() && minBSize.CalcHasPercent()) ||
    3067          46 :       mFlags.mIsFlexContainerMeasuringHeight) {
    3068         351 :     ComputedMinBSize() = 0;
    3069             :   } else {
    3070          92 :     ComputedMinBSize() = ComputeBSizeValue(aCBSize.BSize(wm),
    3071          46 :                                            mStylePosition->mBoxSizing,
    3072             :                                            minBSize);
    3073             :   }
    3074         397 :   nsStyleUnit maxBSizeUnit = maxBSize.GetUnit();
    3075         397 :   if (eStyleUnit_None == maxBSizeUnit) {
    3076             :     // Specified value of 'none'
    3077         351 :     ComputedMaxBSize() = NS_UNCONSTRAINEDSIZE;  // no limit
    3078             :   } else {
    3079             :     // Check for percentage based values and a containing block height that
    3080             :     // depends on the content height. Treat them like 'none'
    3081             :     // Likewise, check for calc() with percentages on internal table elements;
    3082             :     // that's treated as 'auto' too.
    3083             :     // Likewise, if we're a child of a flex container who's measuring our
    3084             :     // intrinsic height, then we want to disregard our max-height.
    3085          92 :     if ((NS_AUTOHEIGHT == aCBSize.BSize(wm) &&
    3086          46 :          maxBSize.HasPercent()) ||
    3087          46 :         (mFrameType == NS_CSS_FRAME_TYPE_INTERNAL_TABLE &&
    3088          92 :          maxBSize.IsCalcUnit() && maxBSize.CalcHasPercent()) ||
    3089          46 :         mFlags.mIsFlexContainerMeasuringHeight) {
    3090           0 :       ComputedMaxBSize() = NS_UNCONSTRAINEDSIZE;
    3091             :     } else {
    3092          92 :       ComputedMaxBSize() = ComputeBSizeValue(aCBSize.BSize(wm),
    3093          46 :                                              mStylePosition->mBoxSizing,
    3094             :                                              maxBSize);
    3095             :     }
    3096             :   }
    3097             : 
    3098             :   // If the computed value of 'min-height' is greater than the value of
    3099             :   // 'max-height', 'max-height' is set to the value of 'min-height'
    3100         397 :   if (ComputedMinBSize() > ComputedMaxBSize()) {
    3101           0 :     ComputedMaxBSize() = ComputedMinBSize();
    3102             :   }
    3103         397 : }
    3104             : 
    3105             : bool
    3106          54 : ReflowInput::IsFloating() const
    3107             : {
    3108          54 :   return mStyleDisplay->IsFloating(mFrame);
    3109             : }
    3110             : 
    3111             : mozilla::StyleDisplay
    3112         575 : ReflowInput::GetDisplay() const
    3113             : {
    3114         575 :   return mStyleDisplay->GetDisplay(mFrame);
    3115             : }

Generated by: LCOV version 1.13