LCOV - code coverage report
Current view: top level - layout/generic - nsBlockReflowContext.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 114 181 63.0 %
Date: 2017-07-14 16:53:18 Functions: 5 5 100.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             : // vim:cindent:ts=2:et:sw=2:
       3             : /* This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : /* class that a parent frame uses to reflow a block frame */
       8             : 
       9             : #include "nsBlockReflowContext.h"
      10             : #include "BlockReflowInput.h"
      11             : #include "nsFloatManager.h"
      12             : #include "nsColumnSetFrame.h"
      13             : #include "nsContainerFrame.h"
      14             : #include "nsBlockFrame.h"
      15             : #include "nsLineBox.h"
      16             : #include "nsLayoutUtils.h"
      17             : 
      18             : using namespace mozilla;
      19             : 
      20             : #ifdef DEBUG
      21             : #undef  NOISY_MAX_ELEMENT_SIZE
      22             : #undef   REALLY_NOISY_MAX_ELEMENT_SIZE
      23             : #undef  NOISY_BLOCK_DIR_MARGINS
      24             : #else
      25             : #undef  NOISY_MAX_ELEMENT_SIZE
      26             : #undef   REALLY_NOISY_MAX_ELEMENT_SIZE
      27             : #undef  NOISY_BLOCK_DIR_MARGINS
      28             : #endif
      29             : 
      30          10 : nsBlockReflowContext::nsBlockReflowContext(nsPresContext* aPresContext,
      31          10 :                                            const ReflowInput& aParentRS)
      32             :   : mPresContext(aPresContext),
      33             :     mOuterReflowInput(aParentRS),
      34             :     mSpace(aParentRS.GetWritingMode()),
      35          10 :     mMetrics(aParentRS)
      36             : {
      37          10 : }
      38             : 
      39          10 : static nsIFrame* DescendIntoBlockLevelFrame(nsIFrame* aFrame)
      40             : {
      41          10 :   LayoutFrameType type = aFrame->Type();
      42          10 :   if (type == LayoutFrameType::ColumnSet) {
      43           0 :     static_cast<nsColumnSetFrame*>(aFrame)->DrainOverflowColumns();
      44           0 :     nsIFrame* child = aFrame->PrincipalChildList().FirstChild();
      45           0 :     if (child) {
      46           0 :       return DescendIntoBlockLevelFrame(child);
      47             :     }
      48             :   }
      49          10 :   return aFrame;
      50             : }
      51             : 
      52             : bool
      53          10 : nsBlockReflowContext::ComputeCollapsedBStartMargin(const ReflowInput& aRI,
      54             :                                                    nsCollapsingMargin* aMargin,
      55             :                                                    nsIFrame* aClearanceFrame,
      56             :                                                    bool* aMayNeedRetry,
      57             :                                                    bool* aBlockIsEmpty)
      58             : {
      59          10 :   WritingMode wm = aRI.GetWritingMode();
      60          10 :   WritingMode parentWM = mMetrics.GetWritingMode();
      61             : 
      62             :   // Include block-start element of frame's margin
      63          10 :   aMargin->Include(aRI.ComputedLogicalMargin().ConvertTo(parentWM, wm).BStart(parentWM));
      64             : 
      65             :   // The inclusion of the block-end margin when empty is done by the caller
      66             :   // since it doesn't need to be done by the top-level (non-recursive)
      67             :   // caller.
      68             : 
      69             : #ifdef NOISY_BLOCKDIR_MARGINS
      70             :   nsFrame::ListTag(stdout, aRI.mFrame);
      71             :   printf(": %d => %d\n", aRI.ComputedLogicalMargin().BStart(wm), aMargin->get());
      72             : #endif
      73             : 
      74          10 :   bool dirtiedLine = false;
      75          10 :   bool setBlockIsEmpty = false;
      76             : 
      77             :   // Calculate the frame's generational block-start-margin from its child
      78             :   // blocks. Note that if the frame has a non-zero block-start-border or
      79             :   // block-start-padding then this step is skipped because it will be a margin
      80             :   // root.  It is also skipped if the frame is a margin root for other
      81             :   // reasons.
      82          10 :   nsIFrame* frame = DescendIntoBlockLevelFrame(aRI.mFrame);
      83          10 :   nsPresContext* prescontext = frame->PresContext();
      84          10 :   nsBlockFrame* block = nullptr;
      85          10 :   if (0 == aRI.ComputedLogicalBorderPadding().BStart(wm)) {
      86          10 :     block = nsLayoutUtils::GetAsBlock(frame);
      87          10 :     if (block) {
      88             :       bool bStartMarginRoot, unused;
      89          10 :       block->IsMarginRoot(&bStartMarginRoot, &unused);
      90          10 :       if (bStartMarginRoot) {
      91           0 :         block = nullptr;
      92             :       }
      93             :     }
      94             :   }
      95             : 
      96             :   // iterate not just through the lines of 'block' but also its
      97             :   // overflow lines and the normal and overflow lines of its next in
      98             :   // flows. Note that this will traverse some frames more than once:
      99             :   // for example, if A contains B and A->nextinflow contains
     100             :   // B->nextinflow, we'll traverse B->nextinflow twice. But this is
     101             :   // OK because our traversal is idempotent.
     102          28 :   for ( ;block; block = static_cast<nsBlockFrame*>(block->GetNextInFlow())) {
     103          28 :     for (int overflowLines = 0; overflowLines <= 1; ++overflowLines) {
     104          19 :       nsBlockFrame::LineIterator line;
     105          19 :       nsBlockFrame::LineIterator line_end;
     106          19 :       bool anyLines = true;
     107          19 :       if (overflowLines) {
     108           9 :         nsBlockFrame::FrameLines* frames = block->GetOverflowLines();
     109           9 :         nsLineList* lines = frames ? &frames->mLines : nullptr;
     110           9 :         if (!lines) {
     111           9 :           anyLines = false;
     112             :         } else {
     113           0 :           line = lines->begin();
     114           0 :           line_end = lines->end();
     115             :         }
     116             :       } else {
     117          10 :         line = block->LinesBegin();
     118          10 :         line_end = block->LinesEnd();
     119             :       }
     120          19 :       for (; anyLines && line != line_end; ++line) {
     121           1 :         if (!aClearanceFrame && line->HasClearance()) {
     122             :           // If we don't have a clearance frame, then we're computing
     123             :           // the collapsed margin in the first pass, assuming that all
     124             :           // lines have no clearance. So clear their clearance flags.
     125           0 :           line->ClearHasClearance();
     126           0 :           line->MarkDirty();
     127           0 :           dirtiedLine = true;
     128             :         }
     129             : 
     130             :         bool isEmpty;
     131           1 :         if (line->IsInline()) {
     132           1 :           isEmpty = line->IsEmpty();
     133             :         } else {
     134           0 :           nsIFrame* kid = line->mFirstChild;
     135           0 :           if (kid == aClearanceFrame) {
     136           0 :             line->SetHasClearance();
     137           0 :             line->MarkDirty();
     138           0 :             dirtiedLine = true;
     139           0 :             if (!setBlockIsEmpty && aBlockIsEmpty) {
     140           0 :               setBlockIsEmpty = true;
     141           0 :               *aBlockIsEmpty = false;
     142             :             }
     143           1 :             goto done;
     144             :           }
     145             :           // Here is where we recur. Now that we have determined that a
     146             :           // generational collapse is required we need to compute the
     147             :           // child blocks margin and so in so that we can look into
     148             :           // it. For its margins to be computed we need to have a reflow
     149             :           // state for it.
     150             : 
     151             :           // We may have to construct an extra reflow state here if
     152             :           // we drilled down through a block wrapper. At the moment
     153             :           // we can only drill down one level so we only have to support
     154             :           // one extra reflow state.
     155           0 :           const ReflowInput* outerReflowInput = &aRI;
     156           0 :           if (frame != aRI.mFrame) {
     157           0 :             NS_ASSERTION(frame->GetParent() == aRI.mFrame,
     158             :                          "Can only drill through one level of block wrapper");
     159           0 :             LogicalSize availSpace = aRI.ComputedSize(frame->GetWritingMode());
     160           0 :             outerReflowInput = new ReflowInput(prescontext,
     161           0 :                                                      aRI, frame, availSpace);
     162             :           }
     163             :           {
     164             :             LogicalSize availSpace =
     165           0 :               outerReflowInput->ComputedSize(kid->GetWritingMode());
     166             :             ReflowInput innerReflowInput(prescontext,
     167             :                                                *outerReflowInput, kid,
     168           0 :                                                availSpace);
     169             :             // Record that we're being optimistic by assuming the kid
     170             :             // has no clearance
     171           0 :             if (kid->StyleDisplay()->mBreakType != StyleClear::None ||
     172           0 :                 !nsBlockFrame::BlockCanIntersectFloats(kid)) {
     173           0 :               *aMayNeedRetry = true;
     174             :             }
     175           0 :             if (ComputeCollapsedBStartMargin(innerReflowInput, aMargin,
     176             :                                              aClearanceFrame, aMayNeedRetry,
     177             :                                              &isEmpty)) {
     178           0 :               line->MarkDirty();
     179           0 :               dirtiedLine = true;
     180             :             }
     181           0 :             if (isEmpty) {
     182           0 :               WritingMode innerWM = innerReflowInput.GetWritingMode();
     183             :               LogicalMargin innerMargin =
     184           0 :                 innerReflowInput.ComputedLogicalMargin().ConvertTo(parentWM, innerWM);
     185           0 :               aMargin->Include(innerMargin.BEnd(parentWM));
     186             :             }
     187             :           }
     188           0 :           if (outerReflowInput != &aRI) {
     189             :             delete const_cast<ReflowInput*>(outerReflowInput);
     190             :           }
     191             :         }
     192           1 :         if (!isEmpty) {
     193           1 :           if (!setBlockIsEmpty && aBlockIsEmpty) {
     194           0 :             setBlockIsEmpty = true;
     195           0 :             *aBlockIsEmpty = false;
     196             :           }
     197           1 :           goto done;
     198             :         }
     199             :       }
     200          18 :       if (!setBlockIsEmpty && aBlockIsEmpty) {
     201             :         // The first time we reach here is when this is the first block
     202             :         // and we have processed all its normal lines.
     203           0 :         setBlockIsEmpty = true;
     204             :         // All lines are empty, or we wouldn't be here!
     205           0 :         *aBlockIsEmpty = aRI.mFrame->IsSelfEmpty();
     206             :       }
     207             :     }
     208             :   }
     209             :   done:
     210             : 
     211          10 :   if (!setBlockIsEmpty && aBlockIsEmpty) {
     212           0 :     *aBlockIsEmpty = aRI.mFrame->IsEmpty();
     213             :   }
     214             : 
     215             : #ifdef NOISY_BLOCKDIR_MARGINS
     216             :   nsFrame::ListTag(stdout, aRI.mFrame);
     217             :   printf(": => %d\n", aMargin->get());
     218             : #endif
     219             : 
     220          10 :   return dirtiedLine;
     221             : }
     222             : 
     223             : void
     224          10 : nsBlockReflowContext::ReflowBlock(const LogicalRect&  aSpace,
     225             :                                   bool                aApplyBStartMargin,
     226             :                                   nsCollapsingMargin& aPrevMargin,
     227             :                                   nscoord             aClearance,
     228             :                                   bool                aIsAdjacentWithBStart,
     229             :                                   nsLineBox*          aLine,
     230             :                                   ReflowInput&  aFrameRI,
     231             :                                   nsReflowStatus&     aFrameReflowStatus,
     232             :                                   BlockReflowInput& aState)
     233             : {
     234          10 :   mFrame = aFrameRI.mFrame;
     235          10 :   mWritingMode = aState.mReflowInput.GetWritingMode();
     236          10 :   mContainerSize = aState.ContainerSize();
     237          10 :   mSpace = aSpace;
     238             : 
     239          10 :   if (!aIsAdjacentWithBStart) {
     240           0 :     aFrameRI.mFlags.mIsTopOfPage = false;  // make sure this is cleared
     241             :   }
     242             : 
     243          10 :   if (aApplyBStartMargin) {
     244          10 :     mBStartMargin = aPrevMargin;
     245             : 
     246             : #ifdef NOISY_BLOCKDIR_MARGINS
     247             :     nsFrame::ListTag(stdout, mOuterReflowInput.mFrame);
     248             :     printf(": reflowing ");
     249             :     nsFrame::ListTag(stdout, mFrame);
     250             :     printf(" margin => %d, clearance => %d\n", mBStartMargin.get(), aClearance);
     251             : #endif
     252             : 
     253             :     // Adjust the available size if it's constrained so that the
     254             :     // child frame doesn't think it can reflow into its margin area.
     255          10 :     if (mWritingMode.IsOrthogonalTo(mFrame->GetWritingMode())) {
     256           0 :       if (NS_UNCONSTRAINEDSIZE != aFrameRI.AvailableISize()) {
     257           0 :         aFrameRI.AvailableISize() -= mBStartMargin.get() + aClearance;
     258             :       }
     259             :     } else {
     260          10 :       if (NS_UNCONSTRAINEDSIZE != aFrameRI.AvailableBSize()) {
     261           0 :         aFrameRI.AvailableBSize() -= mBStartMargin.get() + aClearance;
     262             :       }
     263             :     }
     264             :   } else {
     265             :     // nsBlockFrame::ReflowBlock might call us multiple times with
     266             :     // *different* values of aApplyBStartMargin.
     267           0 :     mBStartMargin.Zero();
     268             :   }
     269             : 
     270          10 :   nscoord tI = 0, tB = 0;
     271             :   // The values of x and y do not matter for floats, so don't bother
     272             :   // calculating them. Floats are guaranteed to have their own float
     273             :   // manager, so tI and tB don't matter.  mICoord and mBCoord don't
     274             :   // matter becacuse they are only used in PlaceBlock, which is not used
     275             :   // for floats.
     276          10 :   if (aLine) {
     277             :     // Compute inline/block coordinate where reflow will begin. Use the
     278             :     // rules from 10.3.3 to determine what to apply. At this point in the
     279             :     // reflow auto inline-start/end margins will have a zero value.
     280             : 
     281          10 :     WritingMode frameWM = aFrameRI.GetWritingMode();
     282             :     LogicalMargin usedMargin =
     283          10 :       aFrameRI.ComputedLogicalMargin().ConvertTo(mWritingMode, frameWM);
     284          10 :     mICoord = mSpace.IStart(mWritingMode) + usedMargin.IStart(mWritingMode);
     285          10 :     mBCoord = mSpace.BStart(mWritingMode) + mBStartMargin.get() + aClearance;
     286             : 
     287             :     LogicalRect space(mWritingMode, mICoord, mBCoord,
     288          10 :                       mSpace.ISize(mWritingMode) -
     289          10 :                       usedMargin.IStartEnd(mWritingMode),
     290          10 :                       mSpace.BSize(mWritingMode) -
     291          30 :                       usedMargin.BStartEnd(mWritingMode));
     292          10 :     tI = space.LineLeft(mWritingMode, mContainerSize);
     293          10 :     tB = mBCoord;
     294             : 
     295          10 :     if ((mFrame->GetStateBits() & NS_BLOCK_FLOAT_MGR) == 0)
     296          10 :       aFrameRI.mBlockDelta =
     297          10 :         mOuterReflowInput.mBlockDelta + mBCoord - aLine->BStart();
     298             :   }
     299             : 
     300             : #ifdef DEBUG
     301          10 :   mMetrics.ISize(mWritingMode) = nscoord(0xdeadbeef);
     302          10 :   mMetrics.BSize(mWritingMode) = nscoord(0xdeadbeef);
     303             : #endif
     304             : 
     305          10 :   mOuterReflowInput.mFloatManager->Translate(tI, tB);
     306          10 :   mFrame->Reflow(mPresContext, mMetrics, aFrameRI, aFrameReflowStatus);
     307          10 :   mOuterReflowInput.mFloatManager->Translate(-tI, -tB);
     308             : 
     309             : #ifdef DEBUG
     310          10 :   if (!aFrameReflowStatus.IsInlineBreakBefore()) {
     311          40 :     if ((CRAZY_SIZE(mMetrics.ISize(mWritingMode)) ||
     312          30 :          CRAZY_SIZE(mMetrics.BSize(mWritingMode))) &&
     313           0 :         !mFrame->GetParent()->IsCrazySizeAssertSuppressed()) {
     314           0 :       printf("nsBlockReflowContext: ");
     315           0 :       nsFrame::ListTag(stdout, mFrame);
     316           0 :       printf(" metrics=%d,%d!\n",
     317           0 :              mMetrics.ISize(mWritingMode), mMetrics.BSize(mWritingMode));
     318             :     }
     319          20 :     if ((mMetrics.ISize(mWritingMode) == nscoord(0xdeadbeef)) ||
     320          10 :         (mMetrics.BSize(mWritingMode) == nscoord(0xdeadbeef))) {
     321           0 :       printf("nsBlockReflowContext: ");
     322           0 :       nsFrame::ListTag(stdout, mFrame);
     323           0 :       printf(" didn't set i/b %d,%d!\n",
     324           0 :              mMetrics.ISize(mWritingMode), mMetrics.BSize(mWritingMode));
     325             :     }
     326             :   }
     327             : #endif
     328             : 
     329          10 :   if (!mFrame->HasOverflowAreas()) {
     330          10 :     mMetrics.SetOverflowAreasToDesiredBounds();
     331             :   }
     332             : 
     333          10 :   if (!aFrameReflowStatus.IsInlineBreakBefore() ||
     334           0 :       (mFrame->GetStateBits() & NS_FRAME_OUT_OF_FLOW)) {
     335             :     // If frame is complete and has a next-in-flow, we need to delete
     336             :     // them now. Do not do this when a break-before is signaled because
     337             :     // the frame is going to get reflowed again (and may end up wanting
     338             :     // a next-in-flow where it ends up), unless it is an out of flow frame.
     339          10 :     if (aFrameReflowStatus.IsFullyComplete()) {
     340          10 :       nsIFrame* kidNextInFlow = mFrame->GetNextInFlow();
     341          10 :       if (nullptr != kidNextInFlow) {
     342             :         // Remove all of the childs next-in-flows. Make sure that we ask
     343             :         // the right parent to do the removal (it's possible that the
     344             :         // parent is not this because we are executing pullup code).
     345             :         // Floats will eventually be removed via nsBlockFrame::RemoveFloat
     346             :         // which detaches the placeholder from the float.
     347           0 :         nsOverflowContinuationTracker::AutoFinish fini(aState.mOverflowTracker, mFrame);
     348           0 :         kidNextInFlow->GetParent()->DeleteNextInFlowChild(kidNextInFlow, true);
     349             :       }
     350             :     }
     351             :   }
     352          10 : }
     353             : 
     354             : /**
     355             :  * Attempt to place the block frame within the available space.  If
     356             :  * it fits, apply inline-dir ("horizontal") positioning (CSS 10.3.3),
     357             :  * collapse margins (CSS2 8.3.1). Also apply relative positioning.
     358             :  */
     359             : bool
     360          10 : nsBlockReflowContext::PlaceBlock(const ReflowInput&  aReflowInput,
     361             :                                  bool                      aForceFit,
     362             :                                  nsLineBox*                aLine,
     363             :                                  nsCollapsingMargin&       aBEndMarginResult,
     364             :                                  nsOverflowAreas&          aOverflowAreas,
     365             :                                  nsReflowStatus            aReflowStatus)
     366             : {
     367             :   // Compute collapsed block-end margin value.
     368          10 :   WritingMode wm = aReflowInput.GetWritingMode();
     369          10 :   WritingMode parentWM = mMetrics.GetWritingMode();
     370          10 :   if (aReflowStatus.IsComplete()) {
     371          10 :     aBEndMarginResult = mMetrics.mCarriedOutBEndMargin;
     372          30 :     aBEndMarginResult.Include(aReflowInput.ComputedLogicalMargin().
     373          20 :       ConvertTo(parentWM, wm).BEnd(parentWM));
     374             :   } else {
     375             :     // The used block-end-margin is set to zero before a break.
     376           0 :     aBEndMarginResult.Zero();
     377             :   }
     378             : 
     379          10 :   nscoord backupContainingBlockAdvance = 0;
     380             : 
     381             :   // Check whether the block's block-end margin collapses with its block-start
     382             :   // margin. See CSS 2.1 section 8.3.1; those rules seem to match
     383             :   // nsBlockFrame::IsEmpty(). Any such block must have zero block-size so
     384             :   // check that first. Note that a block can have clearance and still
     385             :   // have adjoining block-start/end margins, because the clearance goes
     386             :   // above the block-start margin.
     387             :   // Mark the frame as non-dirty; it has been reflowed (or we wouldn't
     388             :   // be here), and we don't want to assert in CachedIsEmpty()
     389          10 :   mFrame->RemoveStateBits(NS_FRAME_IS_DIRTY);
     390          10 :   bool empty = 0 == mMetrics.BSize(parentWM) && aLine->CachedIsEmpty();
     391          10 :   if (empty) {
     392             :     // Collapse the block-end margin with the block-start margin that was
     393             :     // already applied.
     394           5 :     aBEndMarginResult.Include(mBStartMargin);
     395             : 
     396             : #ifdef NOISY_BLOCKDIR_MARGINS
     397             :     printf("  ");
     398             :     nsFrame::ListTag(stdout, mOuterReflowInput.mFrame);
     399             :     printf(": ");
     400             :     nsFrame::ListTag(stdout, mFrame);
     401             :     printf(" -- collapsing block start & end margin together; BStart=%d spaceBStart=%d\n",
     402             :            mBCoord, mSpace.BStart(mWritingMode));
     403             : #endif
     404             :     // Section 8.3.1 of CSS 2.1 says that blocks with adjoining
     405             :     // "top/bottom" (i.e. block-start/end) margins whose top margin collapses
     406             :     // with their parent's top margin should have their top border-edge at the
     407             :     // top border-edge of their parent. We actually don't have to do
     408             :     // anything special to make this happen. In that situation,
     409             :     // nsBlockFrame::ShouldApplyBStartMargin will have returned false,
     410             :     // and mBStartMargin and aClearance will have been zero in
     411             :     // ReflowBlock.
     412             : 
     413             :     // If we did apply our block-start margin, but now we're collapsing it
     414             :     // into the block-end margin, we need to back up the containing
     415             :     // block's bCoord-advance by our block-start margin so that it doesn't get
     416             :     // counted twice. Note that here we're allowing the line's bounds
     417             :     // to become different from the block's position; we do this
     418             :     // because the containing block will place the next line at the
     419             :     // line's BEnd, and it must place the next line at a different
     420             :     // point from where this empty block will be.
     421           5 :     backupContainingBlockAdvance = mBStartMargin.get();
     422             :   }
     423             : 
     424             :   // See if the frame fit. If it's the first frame or empty then it
     425             :   // always fits. If the block-size is unconstrained then it always fits,
     426             :   // even if there's some sort of integer overflow that makes bCoord +
     427             :   // mMetrics.BSize() appear to go beyond the available block size.
     428          10 :   if (!empty && !aForceFit &&
     429           0 :       mSpace.BSize(mWritingMode) != NS_UNCONSTRAINEDSIZE) {
     430           0 :     nscoord bEnd = mBCoord -
     431           0 :                    backupContainingBlockAdvance + mMetrics.BSize(mWritingMode);
     432           0 :     if (bEnd > mSpace.BEnd(mWritingMode)) {
     433             :       // didn't fit, we must acquit.
     434           0 :       mFrame->DidReflow(mPresContext, &aReflowInput,
     435           0 :                         nsDidReflowStatus::FINISHED);
     436           0 :       return false;
     437             :     }
     438             :   }
     439             : 
     440          40 :   aLine->SetBounds(mWritingMode,
     441          10 :                    mICoord, mBCoord - backupContainingBlockAdvance,
     442          20 :                    mMetrics.ISize(mWritingMode), mMetrics.BSize(mWritingMode),
     443          10 :                    mContainerSize);
     444             : 
     445          10 :   WritingMode frameWM = mFrame->GetWritingMode();
     446             :   LogicalPoint logPos =
     447          20 :     LogicalPoint(mWritingMode, mICoord, mBCoord).
     448             :       ConvertTo(frameWM, mWritingMode,
     449          30 :                 mContainerSize - mMetrics.PhysicalSize());
     450             : 
     451             :   // ApplyRelativePositioning in right-to-left writing modes needs to
     452             :   // know the updated frame width
     453          10 :   mFrame->SetSize(mWritingMode, mMetrics.Size(mWritingMode));
     454          10 :   aReflowInput.ApplyRelativePositioning(&logPos, mContainerSize);
     455             : 
     456             :   // Now place the frame and complete the reflow process
     457          10 :   nsContainerFrame::FinishReflowChild(mFrame, mPresContext, mMetrics,
     458             :                                       &aReflowInput, frameWM, logPos,
     459          10 :                                       mContainerSize, 0);
     460             : 
     461          10 :   aOverflowAreas = mMetrics.mOverflowAreas + mFrame->GetPosition();
     462             : 
     463          10 :   return true;
     464             : }

Generated by: LCOV version 1.13