LCOV - code coverage report
Current view: top level - layout/generic - BlockReflowInput.h (source / functions) Hit Total Coverage
Test: output.info Lines: 25 46 54.3 %
Date: 2017-07-14 16:53:18 Functions: 10 17 58.8 %
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             : /* state used in reflow of block frames */
       7             : 
       8             : #ifndef BlockReflowInput_h
       9             : #define BlockReflowInput_h
      10             : 
      11             : #include "nsFloatManager.h"
      12             : #include "nsLineBox.h"
      13             : #include "mozilla/ReflowInput.h"
      14             : 
      15             : class nsBlockFrame;
      16             : class nsFrameList;
      17             : class nsOverflowContinuationTracker;
      18             : 
      19             : namespace mozilla {
      20             : 
      21             : // BlockReflowInput contains additional reflow input information that the
      22             : // block frame uses along with ReflowInput. Like ReflowInput, this
      23             : // is read-only data that is passed down from a parent frame to its children.
      24         162 : class BlockReflowInput {
      25             :   using BandInfoType = nsFloatManager::BandInfoType;
      26             :   using ShapeType = nsFloatManager::ShapeType;
      27             : 
      28             :   // Block reflow input flags.
      29             :   struct Flags {
      30         162 :     Flags()
      31         162 :       : mHasUnconstrainedBSize(false)
      32             :       , mIsBStartMarginRoot(false)
      33             :       , mIsBEndMarginRoot(false)
      34             :       , mShouldApplyBStartMargin(false)
      35             :       , mIsFirstInflow(false)
      36             :       , mHasLineAdjacentToTop(false)
      37             :       , mBlockNeedsFloatManager(false)
      38             :       , mIsLineLayoutEmpty(false)
      39             :       , mIsOverflowContainer(false)
      40             :       , mIsFloatListInBlockPropertyTable(false)
      41         162 :       , mFloatFragmentsInsideColumnEnabled(false)
      42         162 :     {}
      43             : 
      44             :     // Set in the BlockReflowInput constructor when the frame being reflowed has
      45             :     // been given NS_UNCONSTRAINEDSIZE as its available BSize in the
      46             :     // ReflowInput. If set, NS_UNCONSTRAINEDSIZE is passed to nsLineLayout as
      47             :     // the available BSize.
      48             :     bool mHasUnconstrainedBSize : 1;
      49             : 
      50             :     // Set in the BlockReflowInput constructor when reflowing a "block margin
      51             :     // root" frame (i.e. a frame with the NS_BLOCK_MARGIN_ROOT flag set, for
      52             :     // which margins apply by default).
      53             :     //
      54             :     // The flag is also set when reflowing a frame whose computed BStart border
      55             :     // padding is non-zero.
      56             :     bool mIsBStartMarginRoot : 1;
      57             : 
      58             :     // Set in the BlockReflowInput constructor when reflowing a "block margin
      59             :     // root" frame (i.e. a frame with the NS_BLOCK_MARGIN_ROOT flag set, for
      60             :     // which margins apply by default).
      61             :     //
      62             :     // The flag is also set when reflowing a frame whose computed BEnd border
      63             :     // padding is non-zero.
      64             :     bool mIsBEndMarginRoot : 1;
      65             : 
      66             :     // Set if the BStart margin should be considered when placing a linebox that
      67             :     // contains a block frame. It may be set as a side-effect of calling
      68             :     // nsBlockFrame::ShouldApplyBStartMargin(); once set,
      69             :     // ShouldApplyBStartMargin() uses it as a fast-path way to return whether
      70             :     // the BStart margin should apply.
      71             :     //
      72             :     // If the flag hasn't been set in the block reflow input, then
      73             :     // ShouldApplyBStartMargin() will crawl the line list to see if a block frame
      74             :     // precedes the specified frame. If so, the BStart margin should be applied, and
      75             :     // the flag is set to cache the result. (If not, the BStart margin will be
      76             :     // applied as a result of the generational margin collapsing logic in
      77             :     // nsBlockReflowContext::ComputeCollapsedBStartMargin(). In this case, the flag
      78             :     // won't be set, so subsequent calls to ShouldApplyBStartMargin() will continue
      79             :     // crawl the line list.)
      80             :     //
      81             :     // This flag is also set in the BlockReflowInput constructor if
      82             :     // mIsBStartMarginRoot is set; that is, the frame being reflowed is a margin
      83             :     // root by default.
      84             :     bool mShouldApplyBStartMargin : 1;
      85             : 
      86             :     bool mIsFirstInflow : 1;
      87             : 
      88             :     // Set when mLineAdjacentToTop is valid.
      89             :     bool mHasLineAdjacentToTop : 1;
      90             : 
      91             :     // Set when the block has the equivalent of NS_BLOCK_FLOAT_MGR.
      92             :     bool mBlockNeedsFloatManager : 1;
      93             : 
      94             :     // Set when nsLineLayout::LineIsEmpty was true at the end of reflowing
      95             :     // the current line.
      96             :     bool mIsLineLayoutEmpty : 1;
      97             : 
      98             :     bool mIsOverflowContainer : 1;
      99             : 
     100             :     // Set when our mPushedFloats list is stored on the block's property table.
     101             :     bool mIsFloatListInBlockPropertyTable : 1;
     102             : 
     103             :     // Set when the pref layout.float-fragments-inside-column.enabled is true.
     104             :     bool mFloatFragmentsInsideColumnEnabled : 1;
     105             : 
     106             :     // Set when we need text-overflow processing.
     107             :     bool mCanHaveTextOverflow : 1;
     108             :   };
     109             : 
     110             : public:
     111             :   BlockReflowInput(const ReflowInput& aReflowInput,
     112             :                      nsPresContext* aPresContext,
     113             :                      nsBlockFrame* aFrame,
     114             :                      bool aBStartMarginRoot, bool aBEndMarginRoot,
     115             :                      bool aBlockNeedsFloatManager,
     116             :                      nscoord aConsumedBSize = NS_INTRINSICSIZE);
     117             : 
     118             :   /**
     119             :    * Get the available reflow space (the area not occupied by floats)
     120             :    * for the current y coordinate. The available space is relative to
     121             :    * our coordinate system, which is the content box, with (0, 0) in the
     122             :    * upper left.
     123             :    *
     124             :    * Returns whether there are floats present at the given block-direction
     125             :    * coordinate and within the inline size of the content rect.
     126             :    */
     127          85 :   nsFlowAreaRect GetFloatAvailableSpace() const
     128          85 :     { return GetFloatAvailableSpace(mBCoord); }
     129           0 :   nsFlowAreaRect GetFloatAvailableSpaceForPlacingFloat(nscoord aBCoord) const
     130             :     { return GetFloatAvailableSpaceWithState(
     131           0 :         aBCoord, ShapeType::Margin, nullptr); }
     132         160 :   nsFlowAreaRect GetFloatAvailableSpace(nscoord aBCoord) const
     133             :     { return GetFloatAvailableSpaceWithState(
     134         160 :         aBCoord, ShapeType::ShapeOutside, nullptr); }
     135             :   nsFlowAreaRect
     136             :     GetFloatAvailableSpaceWithState(nscoord aBCoord, ShapeType aShapeType,
     137             :                                     nsFloatManager::SavedState *aState) const;
     138             :   nsFlowAreaRect
     139             :     GetFloatAvailableSpaceForBSize(nscoord aBCoord, nscoord aBSize,
     140             :                                    nsFloatManager::SavedState *aState) const;
     141             : 
     142             :   /*
     143             :    * The following functions all return true if they were able to
     144             :    * place the float, false if the float did not fit in available
     145             :    * space.
     146             :    * aLineLayout is null when we are reflowing pushed floats (because
     147             :    * they are not associated with a line box).
     148             :    */
     149             :   bool AddFloat(nsLineLayout*       aLineLayout,
     150             :                 nsIFrame*           aFloat,
     151             :                 nscoord             aAvailableISize);
     152             : 
     153             :   bool FlowAndPlaceFloat(nsIFrame* aFloat);
     154             : 
     155             :   void PlaceBelowCurrentLineFloats(nsFloatCacheFreeList& aFloats,
     156             :                                    nsLineBox* aLine);
     157             : 
     158             :   // Returns the first coordinate >= aBCoord that clears the
     159             :   // floats indicated by aBreakType and has enough inline size between floats
     160             :   // (or no floats remaining) to accomodate aReplacedBlock.
     161             :   nscoord ClearFloats(nscoord aBCoord, mozilla::StyleClear aBreakType,
     162             :                       nsIFrame *aReplacedBlock = nullptr,
     163             :                       uint32_t aFlags = 0);
     164             : 
     165        1486 :   nsFloatManager* FloatManager() const {
     166        1486 :     MOZ_ASSERT(mReflowInput.mFloatManager,
     167             :                "Float manager should be valid during the lifetime of "
     168             :                "BlockReflowInput!");
     169        1486 :     return mReflowInput.mFloatManager;
     170             :   }
     171             : 
     172             :   // Advances to the next band, i.e., the next horizontal stripe in
     173             :   // which there is a different set of floats.
     174             :   // Return false if it did not advance, which only happens for
     175             :   // constrained heights (and means that we should get pushed to the
     176             :   // next column/page).
     177           0 :   bool AdvanceToNextBand(const mozilla::LogicalRect& aFloatAvailableSpace,
     178             :                          nscoord *aBCoord) const {
     179           0 :     mozilla::WritingMode wm = mReflowInput.GetWritingMode();
     180           0 :     if (aFloatAvailableSpace.BSize(wm) > 0) {
     181             :       // See if there's room in the next band.
     182           0 :       *aBCoord += aFloatAvailableSpace.BSize(wm);
     183             :     } else {
     184           0 :       if (mReflowInput.AvailableHeight() != NS_UNCONSTRAINEDSIZE) {
     185             :         // Stop trying to clear here; we'll just get pushed to the
     186             :         // next column or page and try again there.
     187           0 :         return false;
     188             :       }
     189           0 :       NS_NOTREACHED("avail space rect with zero height!");
     190           0 :       *aBCoord += 1;
     191             :     }
     192           0 :     return true;
     193             :   }
     194             : 
     195             :   bool ReplacedBlockFitsInAvailSpace(nsIFrame* aReplacedBlock,
     196             :                             const nsFlowAreaRect& aFloatAvailableSpace) const;
     197             : 
     198          21 :   bool IsAdjacentWithTop() const {
     199          21 :     return mBCoord == mBorderPadding.BStart(mReflowInput.GetWritingMode());
     200             :   }
     201             : 
     202             :   /**
     203             :    * Return mBlock's computed physical border+padding with GetSkipSides applied.
     204             :    */
     205         162 :   const mozilla::LogicalMargin& BorderPadding() const {
     206         162 :     return mBorderPadding;
     207             :   }
     208             : 
     209             :   /**
     210             :    * Retrieve the block-axis content size "consumed" by any prev-in-flows.
     211             :    * @note the value is cached so subsequent calls will return the same value
     212             :    */
     213             :   nscoord ConsumedBSize();
     214             : 
     215             :   // Reconstruct the previous block-end margin that goes before |aLine|.
     216             :   void ReconstructMarginBefore(nsLineList::iterator aLine);
     217             : 
     218             :   // Caller must have called GetAvailableSpace for the correct position
     219             :   // (which need not be the current mBCoord).
     220             :   void ComputeReplacedBlockOffsetsForFloats(nsIFrame* aFrame,
     221             :                           const mozilla::LogicalRect& aFloatAvailableSpace,
     222             :                                             nscoord&  aIStartResult,
     223             :                                             nscoord&  aIEndResult) const;
     224             : 
     225             :   // Caller must have called GetAvailableSpace for the current mBCoord
     226             :   void ComputeBlockAvailSpace(nsIFrame* aFrame,
     227             :                               const nsFlowAreaRect& aFloatAvailableSpace,
     228             :                               bool aBlockAvoidsFloats,
     229             :                               mozilla::LogicalRect& aResult);
     230             : 
     231             :   void RecoverStateFrom(nsLineList::iterator aLine, nscoord aDeltaBCoord);
     232             : 
     233         151 :   void AdvanceToNextLine() {
     234         151 :     if (mFlags.mIsLineLayoutEmpty) {
     235          24 :       mFlags.mIsLineLayoutEmpty = false;
     236             :     } else {
     237         127 :       mLineNumber++;
     238             :     }
     239         151 :   }
     240             : 
     241             :   //----------------------------------------
     242             : 
     243             :   // This state is the "global" state computed once for the reflow of
     244             :   // the block.
     245             : 
     246             :   // The block frame that is using this object
     247             :   nsBlockFrame* mBlock;
     248             : 
     249             :   nsPresContext* mPresContext;
     250             : 
     251             :   const ReflowInput& mReflowInput;
     252             : 
     253             :   // The coordinates within the float manager where the block is being
     254             :   // placed <b>after</b> taking into account the blocks border and
     255             :   // padding. This, therefore, represents the inner "content area" (in
     256             :   // spacemanager coordinates) where child frames will be placed,
     257             :   // including child blocks and floats.
     258             :   nscoord mFloatManagerI, mFloatManagerB;
     259             : 
     260             :   // XXX get rid of this
     261             :   nsReflowStatus mReflowStatus;
     262             : 
     263             :   // The float manager state as it was before the contents of this
     264             :   // block.  This is needed for positioning bullets, since we only want
     265             :   // to move the bullet to flow around floats that were before this
     266             :   // block, not floats inside of it.
     267             :   nsFloatManager::SavedState mFloatManagerStateBefore;
     268             : 
     269             :   nscoord mBEndEdge;
     270             : 
     271             :   // The content area to reflow child frames within.  This is within
     272             :   // this frame's coordinate system and writing mode, which means
     273             :   // mContentArea.IStart == BorderPadding().IStart and
     274             :   // mContentArea.BStart == BorderPadding().BStart.
     275             :   // The block size may be NS_UNCONSTRAINEDSIZE, which indicates that there
     276             :   // is no page/column boundary below (the common case).
     277             :   // mContentArea.BEnd() should only be called after checking that
     278             :   // mContentArea.BSize is not NS_UNCONSTRAINEDSIZE; otherwise
     279             :   // coordinate overflow may occur.
     280             :   mozilla::LogicalRect mContentArea;
     281           0 :   nscoord ContentIStart() const {
     282           0 :     return mContentArea.IStart(mReflowInput.GetWritingMode());
     283             :   }
     284           0 :   nscoord ContentISize() const {
     285           0 :     return mContentArea.ISize(mReflowInput.GetWritingMode());
     286             :   }
     287             :   nscoord ContentIEnd() const {
     288             :     return mContentArea.IEnd(mReflowInput.GetWritingMode());
     289             :   }
     290           0 :   nscoord ContentBStart() const {
     291           0 :     return mContentArea.BStart(mReflowInput.GetWritingMode());
     292             :   }
     293           0 :   nscoord ContentBSize() const {
     294           0 :     return mContentArea.BSize(mReflowInput.GetWritingMode());
     295             :   }
     296           0 :   nscoord ContentBEnd() const {
     297           0 :     return mContentArea.BEnd(mReflowInput.GetWritingMode());
     298             :   }
     299          10 :   mozilla::LogicalSize ContentSize(mozilla::WritingMode aWM) const {
     300          10 :     mozilla::WritingMode wm = mReflowInput.GetWritingMode();
     301          10 :     return mContentArea.Size(wm).ConvertTo(aWM, wm);
     302             :   }
     303             : 
     304             :   // Physical size. Use only for physical <-> logical coordinate conversion.
     305             :   nsSize mContainerSize;
     306         534 :   const nsSize& ContainerSize() const { return mContainerSize; }
     307             : 
     308             :   // Continuation out-of-flow float frames that need to move to our
     309             :   // next in flow are placed here during reflow.  It's a pointer to
     310             :   // a frame list stored in the block's property table.
     311             :   nsFrameList *mPushedFloats;
     312             :   // This method makes sure pushed floats are accessible to
     313             :   // StealFrame. Call it before adding any frames to mPushedFloats.
     314             :   void SetupPushedFloatList();
     315             :   /**
     316             :    * Append aFloatCont and its next-in-flows within the same block to
     317             :    * mPushedFloats.  aFloatCont should not be on any child list when
     318             :    * making this call.  Its next-in-flows will be removed from
     319             :    * mBlock using StealFrame() before being added to mPushedFloats.
     320             :    * All appended frames will be marked NS_FRAME_IS_PUSHED_FLOAT.
     321             :    */
     322             :   void AppendPushedFloatChain(nsIFrame* aFloatCont);
     323             : 
     324             :   // Track child overflow continuations.
     325             :   nsOverflowContinuationTracker* mOverflowTracker;
     326             : 
     327             :   //----------------------------------------
     328             : 
     329             :   // This state is "running" state updated by the reflow of each line
     330             :   // in the block. This same state is "recovered" when a line is not
     331             :   // dirty and is passed over during incremental reflow.
     332             : 
     333             :   // The current line being reflowed
     334             :   // If it is mBlock->end_lines(), then it is invalid.
     335             :   nsLineList::iterator mCurrentLine;
     336             : 
     337             :   // When mHasLineAdjacentToTop is set, this refers to a line
     338             :   // which we know is adjacent to the top of the block (in other words,
     339             :   // all lines before it are empty and do not have clearance. This line is
     340             :   // always before the current line.
     341             :   nsLineList::iterator mLineAdjacentToTop;
     342             : 
     343             :   // The current block-direction coordinate in the block
     344             :   nscoord mBCoord;
     345             : 
     346             :   // mBlock's computed physical border+padding with GetSkipSides applied.
     347             :   mozilla::LogicalMargin mBorderPadding;
     348             : 
     349             :   // The overflow areas of all floats placed so far
     350             :   nsOverflowAreas mFloatOverflowAreas;
     351             : 
     352             :   nsFloatCacheFreeList mFloatCacheFreeList;
     353             : 
     354             :   // Previous child. This is used when pulling up a frame to update
     355             :   // the sibling list.
     356             :   nsIFrame* mPrevChild;
     357             : 
     358             :   // The previous child frames collapsed bottom margin value.
     359             :   nsCollapsingMargin mPrevBEndMargin;
     360             : 
     361             :   // The current next-in-flow for the block. When lines are pulled
     362             :   // from a next-in-flow, this is used to know which next-in-flow to
     363             :   // pull from. When a next-in-flow is emptied of lines, we advance
     364             :   // this to the next next-in-flow.
     365             :   nsBlockFrame* mNextInFlow;
     366             : 
     367             :   //----------------------------------------
     368             : 
     369             :   // Temporary line-reflow state. This state is used during the reflow
     370             :   // of a given line, but doesn't have meaning before or after.
     371             : 
     372             :   // The list of floats that are "current-line" floats. These are
     373             :   // added to the line after the line has been reflowed, to keep the
     374             :   // list fiddling from being N^2.
     375             :   nsFloatCacheFreeList mCurrentLineFloats;
     376             : 
     377             :   // The list of floats which are "below current-line"
     378             :   // floats. These are reflowed/placed after the line is reflowed
     379             :   // and placed. Again, this is done to keep the list fiddling from
     380             :   // being N^2.
     381             :   nsFloatCacheFreeList mBelowCurrentLineFloats;
     382             : 
     383             :   nscoord mMinLineHeight;
     384             : 
     385             :   int32_t mLineNumber;
     386             : 
     387             :   Flags mFlags;
     388             : 
     389             :   StyleClear mFloatBreakType;
     390             : 
     391             :   // The amount of computed block-direction size "consumed" by previous-in-flows.
     392             :   nscoord mConsumedBSize;
     393             : 
     394             :   // Cache the current line's BSize if nsBlockFrame::PlaceLine() fails to
     395             :   // place the line. When redoing the line, it will be used to query the
     396             :   // accurate float available space in AddFloat() and
     397             :   // nsBlockFrame::PlaceLine().
     398             :   mozilla::Maybe<nscoord> mLineBSize;
     399             : 
     400             : private:
     401             :   bool CanPlaceFloat(nscoord aFloatISize,
     402             :                      const nsFlowAreaRect& aFloatAvailableSpace);
     403             : 
     404             :   void PushFloatPastBreak(nsIFrame* aFloat);
     405             : 
     406             :   void RecoverFloats(nsLineList::iterator aLine, nscoord aDeltaBCoord);
     407             : };
     408             : 
     409             : }; // namespace mozilla
     410             : 
     411             : #endif // BlockReflowInput_h

Generated by: LCOV version 1.13