LCOV - code coverage report
Current view: top level - layout/generic - nsFloatManager.h (source / functions) Hit Total Coverage
Test: output.info Lines: 18 75 24.0 %
Date: 2017-07-14 16:53:18 Functions: 7 45 15.6 %
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 manages rules for positioning floats */
       8             : 
       9             : #ifndef nsFloatManager_h_
      10             : #define nsFloatManager_h_
      11             : 
      12             : #include "mozilla/Attributes.h"
      13             : #include "mozilla/UniquePtr.h"
      14             : #include "mozilla/WritingModes.h"
      15             : #include "nsCoord.h"
      16             : #include "nsFrameList.h" // for DEBUG_FRAME_DUMP
      17             : #include "nsIntervalSet.h"
      18             : #include "nsPoint.h"
      19             : #include "nsTArray.h"
      20             : 
      21             : class nsIPresShell;
      22             : class nsIFrame;
      23             : class nsPresContext;
      24             : namespace mozilla {
      25             : struct ReflowInput;
      26             : class StyleBasicShape;
      27             : } // namespace mozilla
      28             : 
      29             : /**
      30             :  * The available space for content not occupied by floats is divided
      31             :  * into a sequence of rectangles in the block direction.  However, we
      32             :  * need to know not only the rectangle, but also whether it was reduced
      33             :  * (from the content rectangle) by floats that actually intruded into
      34             :  * the content rectangle.
      35             :  */
      36         235 : struct nsFlowAreaRect {
      37             :   mozilla::LogicalRect mRect;
      38             :   bool mHasFloats;
      39             : 
      40         235 :   nsFlowAreaRect(mozilla::WritingMode aWritingMode,
      41             :                  nscoord aICoord, nscoord aBCoord,
      42             :                  nscoord aISize, nscoord aBSize,
      43             :                  bool aHasFloats)
      44         235 :     : mRect(aWritingMode, aICoord, aBCoord, aISize, aBSize)
      45         235 :     , mHasFloats(aHasFloats) {}
      46             : };
      47             : 
      48             : #define NS_FLOAT_MANAGER_CACHE_SIZE 64
      49             : 
      50             : /**
      51             :  * nsFloatManager is responsible for implementing CSS's rules for
      52             :  * positioning floats. An nsFloatManager object is created during reflow for
      53             :  * any block with NS_BLOCK_FLOAT_MGR. During reflow, the float manager for
      54             :  * the nearest such ancestor block is found in ReflowInput::mFloatManager.
      55             :  *
      56             :  * According to the line-relative mappings in CSS Writing Modes spec [1],
      57             :  * line-right and line-left are calculated with respect to the writing mode
      58             :  * of the containing block of the floats. All the writing modes passed to
      59             :  * nsFloatManager methods should be the containing block's writing mode.
      60             :  *
      61             :  * However, according to the abstract-to-physical mappings table [2], the
      62             :  * 'direction' property of the containing block doesn't affect the
      63             :  * interpretation of line-right and line-left. We actually implement this by
      64             :  * passing in the writing mode of the block formatting context (BFC), i.e.
      65             :  * the of BlockReflowInput's writing mode.
      66             :  *
      67             :  * nsFloatManager uses a special logical coordinate space with inline
      68             :  * coordinates on the line-axis and block coordinates on the block-axis
      69             :  * based on the writing mode of the block formatting context. All the
      70             :  * physical types like nsRect, nsPoint, etc. use this coordinate space. See
      71             :  * FloatInfo::mRect for an example.
      72             :  *
      73             :  * [1] https://drafts.csswg.org/css-writing-modes/#line-mappings
      74             :  * [2] https://drafts.csswg.org/css-writing-modes/#logical-to-physical
      75             :  */
      76             : class nsFloatManager {
      77             : public:
      78             :   explicit nsFloatManager(nsIPresShell* aPresShell, mozilla::WritingMode aWM);
      79             :   ~nsFloatManager();
      80             : 
      81             :   void* operator new(size_t aSize) CPP_THROW_NEW;
      82             :   void operator delete(void* aPtr, size_t aSize);
      83             : 
      84             :   static void Shutdown();
      85             : 
      86             :   /**
      87             :    * Get float region stored on the frame. (Defaults to mRect if it's
      88             :    * not there.) The float region is the area impacted by this float;
      89             :    * the coordinates are relative to the containing block frame.
      90             :    */
      91             :   static mozilla::LogicalRect GetRegionFor(mozilla::WritingMode aWM,
      92             :                                            nsIFrame* aFloatFrame,
      93             :                                            const nsSize& aContainerSize);
      94             :   /**
      95             :    * Calculate the float region for this frame using aMargin and the
      96             :    * frame's mRect. The region includes the margins around the float,
      97             :    * but doesn't include the relative offsets.
      98             :    * Note that if the frame is or has a continuation, aMargin's top
      99             :    * and/or bottom must be zeroed by the caller.
     100             :    */
     101             :   static mozilla::LogicalRect CalculateRegionFor(
     102             :                                 mozilla::WritingMode aWM,
     103             :                                 nsIFrame* aFloatFrame,
     104             :                                 const mozilla::LogicalMargin& aMargin,
     105             :                                 const nsSize& aContainerSize);
     106             :   /**
     107             :    * Store the float region on the frame. The region is stored
     108             :    * as a delta against the mRect, so repositioning the frame will
     109             :    * also reposition the float region.
     110             :    */
     111             :   static void StoreRegionFor(mozilla::WritingMode aWM,
     112             :                              nsIFrame* aFloat,
     113             :                              const mozilla::LogicalRect& aRegion,
     114             :                              const nsSize& aContainerSize);
     115             : 
     116             :   // Structure that stores the current state of a float manager for
     117             :   // Save/Restore purposes.
     118             :   struct SavedState {
     119         247 :     explicit SavedState() {}
     120             :   private:
     121             :     uint32_t mFloatInfoCount;
     122             :     nscoord mLineLeft, mBlockStart;
     123             :     bool mPushedLeftFloatPastBreak;
     124             :     bool mPushedRightFloatPastBreak;
     125             :     bool mSplitLeftFloatAcrossBreak;
     126             :     bool mSplitRightFloatAcrossBreak;
     127             : 
     128             :     friend class nsFloatManager;
     129             :   };
     130             : 
     131             :   /**
     132             :    * Translate the current origin by the specified offsets. This
     133             :    * creates a new local coordinate space relative to the current
     134             :    * coordinate space.
     135             :    */
     136         170 :   void Translate(nscoord aLineLeft, nscoord aBlockStart)
     137             :   {
     138         170 :     mLineLeft += aLineLeft;
     139         170 :     mBlockStart += aBlockStart;
     140         170 :   }
     141             : 
     142             :   /**
     143             :    * Returns the current translation from local coordinate space to
     144             :    * world coordinate space. This represents the accumulated calls to
     145             :    * Translate().
     146             :    */
     147         397 :   void GetTranslation(nscoord& aLineLeft, nscoord& aBlockStart) const
     148             :   {
     149         397 :     aLineLeft = mLineLeft;
     150         397 :     aBlockStart = mBlockStart;
     151         397 :   }
     152             : 
     153             :   /**
     154             :    * Get information about the area available to content that flows
     155             :    * around floats.  Two different types of space can be requested:
     156             :    *   BandFromPoint: returns the band containing block-dir coordinate
     157             :    *     |aBCoord| (though actually with the top truncated to begin at
     158             :    *     aBCoord), but up to at most |aBSize| (which may be nscoord_MAX).
     159             :    *     This will return the tallest rectangle whose block start is
     160             :    *     |aBCoord| and in which there are no changes in what floats are
     161             :    *     on the sides of that rectangle, but will limit the block size
     162             :    *     of the rectangle to |aBSize|.  The inline start and end edges
     163             :    *     of the rectangle give the area available for line boxes in that
     164             :    *     space. The inline size of this resulting rectangle will not be
     165             :    *     negative.
     166             :    *   WidthWithinHeight: This returns a rectangle whose block start
     167             :    *     is aBCoord and whose block size is exactly aBSize.  Its inline
     168             :    *     start and end edges give the corresponding edges of the space
     169             :    *     that can be used for line boxes *throughout* that space.  (It
     170             :    *     is possible that more inline space could be used in part of the
     171             :    *     space if a float begins or ends in it.)  The inline size of the
     172             :    *     resulting rectangle can be negative.
     173             :    *
     174             :    * ShapeType can be used to request two different types of flow areas.
     175             :    * (This is the float area defined in CSS Shapes Module Level 1 ยง1.4):
     176             :    *    Margin: uses the float element's margin-box to request the flow area.
     177             :    *    ShapeOutside: uses the float element's shape-outside value to request
     178             :    *      the float area.
     179             :    *
     180             :    * @param aBCoord [in] block-dir coordinate for block start of available space
     181             :    *          desired, which are positioned relative to the current translation.
     182             :    * @param aBSize [in] see above
     183             :    * @param aContentArea [in] an nsRect representing the content area
     184             :    * @param aState [in] If null, use the current state, otherwise, do
     185             :    *                    computation based only on floats present in the given
     186             :    *                    saved state.
     187             :    * @return An nsFlowAreaRect whose:
     188             :    *           mRect is the resulting rectangle for line boxes.  It will not
     189             :    *             extend beyond aContentArea's inline bounds, but may be
     190             :    *             narrower when floats are present.
     191             :    *           mHasFloats is whether there are floats at the sides of the
     192             :    *             return value including those that do not reduce the line box
     193             :    *             inline size at all (because they are entirely in the margins)
     194             :    */
     195             :   enum class BandInfoType { BandFromPoint, WidthWithinHeight };
     196             :   enum class ShapeType { Margin, ShapeOutside };
     197             :   nsFlowAreaRect GetFlowArea(mozilla::WritingMode aWM,
     198             :                              nscoord aBCoord, nscoord aBSize,
     199             :                              BandInfoType aBandInfoType, ShapeType aShapeType,
     200             :                              mozilla::LogicalRect aContentArea,
     201             :                              SavedState* aState,
     202             :                              const nsSize& aContainerSize) const;
     203             : 
     204             :   /**
     205             :    * Add a float that comes after all floats previously added.  Its
     206             :    * block start must be even with or below the top of all previous
     207             :    * floats.
     208             :    *
     209             :    * aMarginRect is relative to the current translation.  The caller
     210             :    * must ensure aMarginRect.height >= 0 and aMarginRect.width >= 0.
     211             :    */
     212             :   void AddFloat(nsIFrame* aFloatFrame,
     213             :                 const mozilla::LogicalRect& aMarginRect,
     214             :                 mozilla::WritingMode aWM, const nsSize& aContainerSize);
     215             : 
     216             :   /**
     217             :    * Notify that we tried to place a float that could not fit at all and
     218             :    * had to be pushed to the next page/column?  (If so, we can't place
     219             :    * any more floats in this page/column because of the rule that the
     220             :    * top of a float cannot be above the top of an earlier float.  It
     221             :    * also means that any clear needs to continue to the next column.)
     222             :    */
     223           0 :   void SetPushedLeftFloatPastBreak()
     224           0 :     { mPushedLeftFloatPastBreak = true; }
     225           0 :   void SetPushedRightFloatPastBreak()
     226           0 :     { mPushedRightFloatPastBreak = true; }
     227             : 
     228             :   /**
     229             :    * Notify that we split a float, with part of it needing to be pushed
     230             :    * to the next page/column.  (This means that any 'clear' needs to
     231             :    * continue to the next page/column.)
     232             :    */
     233           0 :   void SetSplitLeftFloatAcrossBreak()
     234           0 :     { mSplitLeftFloatAcrossBreak = true; }
     235           0 :   void SetSplitRightFloatAcrossBreak()
     236           0 :     { mSplitRightFloatAcrossBreak = true; }
     237             : 
     238             :   /**
     239             :    * Remove the regions associated with this floating frame and its
     240             :    * next-sibling list.  Some of the frames may never have been added;
     241             :    * we just skip those. This is not fully general; it only works as
     242             :    * long as the N frames to be removed are the last N frames to have
     243             :    * been added; if there's a frame in the middle of them that should
     244             :    * not be removed, YOU LOSE.
     245             :    */
     246             :   nsresult RemoveTrailingRegions(nsIFrame* aFrameList);
     247             : 
     248         380 :   bool HasAnyFloats() const { return !mFloats.IsEmpty(); }
     249             : 
     250             :   /**
     251             :    * Methods for dealing with the propagation of float damage during
     252             :    * reflow.
     253             :    */
     254           0 :   bool HasFloatDamage() const
     255             :   {
     256           0 :     return !mFloatDamage.IsEmpty();
     257             :   }
     258             : 
     259           0 :   void IncludeInDamage(nscoord aIntervalBegin, nscoord aIntervalEnd)
     260             :   {
     261           0 :     mFloatDamage.IncludeInterval(aIntervalBegin + mBlockStart,
     262           0 :                                  aIntervalEnd + mBlockStart);
     263           0 :   }
     264             : 
     265           0 :   bool IntersectsDamage(nscoord aIntervalBegin, nscoord aIntervalEnd) const
     266             :   {
     267           0 :     return mFloatDamage.Intersects(aIntervalBegin + mBlockStart,
     268           0 :                                    aIntervalEnd + mBlockStart);
     269             :   }
     270             : 
     271             :   /**
     272             :    * Saves the current state of the float manager into aState.
     273             :    */
     274             :   void PushState(SavedState* aState);
     275             : 
     276             :   /**
     277             :    * Restores the float manager to the saved state.
     278             :    *
     279             :    * These states must be managed using stack discipline. PopState can only
     280             :    * be used after PushState has been used to save the state, and it can only
     281             :    * be used once --- although it can be omitted; saved states can be ignored.
     282             :    * States must be popped in the reverse order they were pushed.  A
     283             :    * call to PopState invalidates any saved states Pushed after the
     284             :    * state passed to PopState was pushed.
     285             :    */
     286             :   void PopState(SavedState* aState);
     287             : 
     288             :   /**
     289             :    * Get the block start of the last float placed into the float
     290             :    * manager, to enforce the rule that a float can't be above an earlier
     291             :    * float. Returns the minimum nscoord value if there are no floats.
     292             :    *
     293             :    * The result is relative to the current translation.
     294             :    */
     295             :   nscoord GetLowestFloatTop() const;
     296             : 
     297             :   /**
     298             :    * Return the coordinate of the lowest float matching aBreakType in
     299             :    * this float manager. Returns aBCoord if there are no matching
     300             :    * floats.
     301             :    *
     302             :    * Both aBCoord and the result are relative to the current translation.
     303             :    */
     304             :   enum {
     305             :     // Tell ClearFloats not to push to nscoord_MAX when floats have been
     306             :     // pushed to the next page/column.
     307             :     DONT_CLEAR_PUSHED_FLOATS = (1<<0)
     308             :   };
     309             :   nscoord ClearFloats(nscoord aBCoord, mozilla::StyleClear aBreakType,
     310             :                       uint32_t aFlags = 0) const;
     311             : 
     312             :   /**
     313             :    * Checks if clear would pass into the floats' BFC's next-in-flow,
     314             :    * i.e. whether floats affecting this clear have continuations.
     315             :    */
     316             :   bool ClearContinues(mozilla::StyleClear aBreakType) const;
     317             : 
     318           0 :   void AssertStateMatches(SavedState *aState) const
     319             :   {
     320           0 :     NS_ASSERTION(aState->mLineLeft == mLineLeft &&
     321             :                  aState->mBlockStart == mBlockStart &&
     322             :                  aState->mPushedLeftFloatPastBreak ==
     323             :                    mPushedLeftFloatPastBreak &&
     324             :                  aState->mPushedRightFloatPastBreak ==
     325             :                    mPushedRightFloatPastBreak &&
     326             :                  aState->mSplitLeftFloatAcrossBreak ==
     327             :                    mSplitLeftFloatAcrossBreak &&
     328             :                  aState->mSplitRightFloatAcrossBreak ==
     329             :                    mSplitRightFloatAcrossBreak &&
     330             :                  aState->mFloatInfoCount == mFloats.Length(),
     331             :                  "float manager state should match saved state");
     332           0 :   }
     333             : 
     334             : #ifdef DEBUG_FRAME_DUMP
     335             :   /**
     336             :    * Dump the state of the float manager out to a file.
     337             :    */
     338             :   nsresult List(FILE* out) const;
     339             : #endif
     340             : 
     341             : private:
     342             : 
     343             :   // ShapeInfo is an abstract class for implementing all the shapes in CSS
     344             :   // Shapes Module. A subclass needs to override all the methods to adjust
     345             :   // the flow area with respect to its shape.
     346           0 :   class ShapeInfo
     347             :   {
     348             :   public:
     349           0 :     virtual ~ShapeInfo() {}
     350             : 
     351             :     virtual nscoord LineLeft(const nscoord aBStart,
     352             :                              const nscoord aBEnd) const = 0;
     353             :     virtual nscoord LineRight(const nscoord aBStart,
     354             :                               const nscoord aBEnd) const = 0;
     355             :     virtual nscoord BStart() const = 0;
     356             :     virtual nscoord BEnd() const = 0;
     357             :     virtual bool IsEmpty() const = 0;
     358             : 
     359             :     // Translate the current origin by the specified offsets.
     360             :     virtual void Translate(nscoord aLineLeft, nscoord aBlockStart) = 0;
     361             : 
     362             :     static mozilla::LogicalRect ComputeShapeBoxRect(
     363             :       const mozilla::StyleShapeSource& aShapeOutside,
     364             :       nsIFrame* const aFrame,
     365             :       const mozilla::LogicalRect& aMarginRect,
     366             :       mozilla::WritingMode aWM);
     367             : 
     368             :     // Convert the LogicalRect to the special logical coordinate space used
     369             :     // in float manager.
     370           0 :     static nsRect ConvertToFloatLogical(const mozilla::LogicalRect& aRect,
     371             :                                         mozilla::WritingMode aWM,
     372             :                                         const nsSize& aContainerSize)
     373             :     {
     374             :       return nsRect(aRect.LineLeft(aWM, aContainerSize), aRect.BStart(aWM),
     375           0 :                     aRect.ISize(aWM), aRect.BSize(aWM));
     376             :     }
     377             : 
     378             :     static mozilla::UniquePtr<ShapeInfo> CreateShapeBox(
     379             :       nsIFrame* const aFrame,
     380             :       const mozilla::LogicalRect& aShapeBoxRect,
     381             :       mozilla::WritingMode aWM,
     382             :       const nsSize& aContainerSize);
     383             : 
     384             :     static mozilla::UniquePtr<ShapeInfo> CreateInset(
     385             :       const mozilla::StyleBasicShape* aBasicShape,
     386             :       const mozilla::LogicalRect& aShapeBoxRect,
     387             :       mozilla::WritingMode aWM,
     388             :       const nsSize& aContainerSize);
     389             : 
     390             :     static mozilla::UniquePtr<ShapeInfo> CreateCircleOrEllipse(
     391             :       const mozilla::StyleBasicShape* aBasicShape,
     392             :       const mozilla::LogicalRect& aShapeBoxRect,
     393             :       mozilla::WritingMode aWM,
     394             :       const nsSize& aContainerSize);
     395             : 
     396             :     static mozilla::UniquePtr<ShapeInfo> CreatePolygon(
     397             :       const mozilla::StyleBasicShape* aBasicShape,
     398             :       const mozilla::LogicalRect& aShapeBoxRect,
     399             :       mozilla::WritingMode aWM,
     400             :       const nsSize& aContainerSize);
     401             : 
     402             :   protected:
     403             :     // Compute the minimum line-axis difference between the bounding shape
     404             :     // box and its rounded corner within the given band (block-axis region).
     405             :     // This is used as a helper function to compute the LineRight() and
     406             :     // LineLeft(). See the picture in the implementation for an example.
     407             :     // RadiusL and RadiusB stand for radius on the line-axis and block-axis.
     408             :     //
     409             :     // Returns radius-x diff on the line-axis, or 0 if there's no rounded
     410             :     // corner within the given band.
     411             :     static nscoord ComputeEllipseLineInterceptDiff(
     412             :       const nscoord aShapeBoxBStart, const nscoord aShapeBoxBEnd,
     413             :       const nscoord aBStartCornerRadiusL, const nscoord aBStartCornerRadiusB,
     414             :       const nscoord aBEndCornerRadiusL, const nscoord aBEndCornerRadiusB,
     415             :       const nscoord aBandBStart, const nscoord aBandBEnd);
     416             : 
     417             :     static nscoord XInterceptAtY(const nscoord aY, const nscoord aRadiusX,
     418             :                                  const nscoord aRadiusY);
     419             : 
     420             :     // Convert the physical point to the special logical coordinate space
     421             :     // used in float manager.
     422             :     static nsPoint ConvertToFloatLogical(const nsPoint& aPoint,
     423             :                                          mozilla::WritingMode aWM,
     424             :                                          const nsSize& aContainerSize);
     425             : 
     426             :     // Convert the half corner radii (nscoord[8]) to the special logical
     427             :     // coordinate space used in float manager.
     428             :     static mozilla::UniquePtr<nscoord[]> ConvertToFloatLogical(
     429             :       const nscoord aRadii[8],
     430             :       mozilla::WritingMode aWM);
     431             :   };
     432             : 
     433             :   // Implements shape-outside: <shape-box> and shape-outside: inset().
     434           0 :   class RoundedBoxShapeInfo final : public ShapeInfo
     435             :   {
     436             :   public:
     437           0 :     RoundedBoxShapeInfo(const nsRect& aRect,
     438             :                         mozilla::UniquePtr<nscoord[]> aRadii)
     439           0 :       : mRect(aRect)
     440           0 :       , mRadii(Move(aRadii))
     441           0 :     {}
     442             : 
     443             :     nscoord LineLeft(const nscoord aBStart,
     444             :                      const nscoord aBEnd) const override;
     445             :     nscoord LineRight(const nscoord aBStart,
     446             :                       const nscoord aBEnd) const override;
     447           0 :     nscoord BStart() const override { return mRect.y; }
     448           0 :     nscoord BEnd() const override { return mRect.YMost(); }
     449           0 :     bool IsEmpty() const override { return mRect.IsEmpty(); };
     450             : 
     451           0 :     void Translate(nscoord aLineLeft, nscoord aBlockStart) override
     452             :     {
     453           0 :       mRect.MoveBy(aLineLeft, aBlockStart);
     454           0 :     }
     455             : 
     456             :   private:
     457             :     // The rect of the rounded box shape in the float manager's coordinate
     458             :     // space.
     459             :     nsRect mRect;
     460             :     // The half corner radii of the reference box. It's an nscoord[8] array
     461             :     // in the float manager's coordinate space. If there are no radii, it's
     462             :     // nullptr.
     463             :     mozilla::UniquePtr<nscoord[]> mRadii;
     464             :   };
     465             : 
     466             :   // Implements shape-outside: circle() and shape-outside: ellipse().
     467           0 :   class EllipseShapeInfo final : public ShapeInfo
     468             :   {
     469             :   public:
     470           0 :     EllipseShapeInfo(const nsPoint& aCenter,
     471             :                      const nsSize& aRadii)
     472           0 :       : mCenter(aCenter)
     473           0 :       , mRadii(aRadii)
     474           0 :     {}
     475             : 
     476             :     nscoord LineLeft(const nscoord aBStart,
     477             :                      const nscoord aBEnd) const override;
     478             :     nscoord LineRight(const nscoord aBStart,
     479             :                       const nscoord aBEnd) const override;
     480           0 :     nscoord BStart() const override { return mCenter.y - mRadii.height; }
     481           0 :     nscoord BEnd() const override { return mCenter.y + mRadii.height; }
     482           0 :     bool IsEmpty() const override { return mRadii.IsEmpty(); };
     483             : 
     484           0 :     void Translate(nscoord aLineLeft, nscoord aBlockStart) override
     485             :     {
     486           0 :       mCenter.MoveBy(aLineLeft, aBlockStart);
     487           0 :     }
     488             : 
     489             :   private:
     490             :     // The position of the center of the ellipse. The coordinate space is the
     491             :     // same as FloatInfo::mRect.
     492             :     nsPoint mCenter;
     493             :     // The radii of the ellipse in app units. The width and height represent
     494             :     // the line-axis and block-axis radii of the ellipse.
     495             :     nsSize mRadii;
     496             :   };
     497             : 
     498             :   // Implements shape-outside: polygon().
     499           0 :   class PolygonShapeInfo final : public ShapeInfo
     500             :   {
     501             :   public:
     502             :     explicit PolygonShapeInfo(nsTArray<nsPoint>&& aVertices);
     503             : 
     504             :     nscoord LineLeft(const nscoord aBStart,
     505             :                      const nscoord aBEnd) const override;
     506             :     nscoord LineRight(const nscoord aBStart,
     507             :                       const nscoord aBEnd) const override;
     508           0 :     nscoord BStart() const override { return mBStart; }
     509           0 :     nscoord BEnd() const override { return mBEnd; }
     510           0 :     bool IsEmpty() const override { return mEmpty; }
     511             : 
     512             :     void Translate(nscoord aLineLeft, nscoord aBlockStart) override;
     513             : 
     514             :   private:
     515             :     // Helper method for implementing LineLeft() and LineRight().
     516             :     nscoord ComputeLineIntercept(
     517             :       const nscoord aBStart,
     518             :       const nscoord aBEnd,
     519             :       nscoord (*aCompareOp) (std::initializer_list<nscoord>),
     520             :       const nscoord aLineInterceptInitialValue) const;
     521             : 
     522             :     // Given a horizontal line y, and two points p1 and p2 forming a line
     523             :     // segment L. Solve x for the intersection of y and L. This method
     524             :     // assumes y and L do intersect, and L is *not* horizontal.
     525             :     static nscoord XInterceptAtY(const nscoord aY,
     526             :                                  const nsPoint& aP1,
     527             :                                  const nsPoint& aP2);
     528             : 
     529             :     // The vertices of the polygon in the float manager's coordinate space.
     530             :     nsTArray<nsPoint> mVertices;
     531             : 
     532             :     // If mEmpty is true, that means the polygon encloses no area.
     533             :     bool mEmpty = false;
     534             : 
     535             :     // Computed block start and block end value of the polygon shape.
     536             :     //
     537             :     // If mEmpty is false, their initial values nscoord_MAX and nscoord_MIN
     538             :     // are used as sentinels for computing min() and max() in the
     539             :     // constructor, and mBStart is guaranteed to be less than or equal to
     540             :     // mBEnd. If mEmpty is true, their values do not matter.
     541             :     nscoord mBStart = nscoord_MAX;
     542             :     nscoord mBEnd = nscoord_MIN;
     543             :   };
     544             : 
     545             :   struct FloatInfo {
     546             :     nsIFrame *const mFrame;
     547             :     // The lowest block-ends of left/right floats up to and including
     548             :     // this one.
     549             :     nscoord mLeftBEnd, mRightBEnd;
     550             : 
     551             :     FloatInfo(nsIFrame* aFrame, nscoord aLineLeft, nscoord aBlockStart,
     552             :               const mozilla::LogicalRect& aMarginRect,
     553             :               mozilla::WritingMode aWM, const nsSize& aContainerSize);
     554             : 
     555           0 :     nscoord LineLeft() const { return mRect.x; }
     556           0 :     nscoord LineRight() const { return mRect.XMost(); }
     557           0 :     nscoord ISize() const { return mRect.width; }
     558           0 :     nscoord BStart() const { return mRect.y; }
     559           0 :     nscoord BEnd() const { return mRect.YMost(); }
     560           0 :     nscoord BSize() const { return mRect.height; }
     561           0 :     bool IsEmpty() const { return mRect.IsEmpty(); }
     562             : 
     563             :     // aBStart and aBEnd are the starting and ending coordinate of a band.
     564             :     // LineLeft() and LineRight() return the innermost line-left extent and
     565             :     // line-right extent within the given band, respectively.
     566             :     nscoord LineLeft(ShapeType aShapeType,
     567             :                      const nscoord aBStart, const nscoord aBEnd) const;
     568             :     nscoord LineRight(ShapeType aShapeType,
     569             :                       const nscoord aBStart, const nscoord aBEnd) const;
     570             :     nscoord BStart(ShapeType aShapeType) const;
     571             :     nscoord BEnd(ShapeType aShapeType) const;
     572             :     bool IsEmpty(ShapeType aShapeType) const;
     573             : 
     574             : #ifdef NS_BUILD_REFCNT_LOGGING
     575             :     FloatInfo(FloatInfo&& aOther);
     576             :     ~FloatInfo();
     577             : #endif
     578             : 
     579             :     // NB! This is really a logical rect in a writing mode suitable for
     580             :     // placing floats, which is not necessarily the actual writing mode
     581             :     // either of the block which created the float manager or the block
     582             :     // that is calling the float manager. The inline coordinates are in
     583             :     // the line-relative axis of the float manager and its block
     584             :     // coordinates are in the float manager's block direction.
     585             :     nsRect mRect;
     586             :     // Pointer to a concrete subclass of ShapeInfo or null, which means that
     587             :     // there is no shape-outside.
     588             :     mozilla::UniquePtr<ShapeInfo> mShapeInfo;
     589             :   };
     590             : 
     591             : #ifdef DEBUG
     592             :   // Store the writing mode from the block frame which establishes the block
     593             :   // formatting context (BFC) when the nsFloatManager is created.
     594             :   mozilla::WritingMode mWritingMode;
     595             : #endif
     596             : 
     597             :   // Translation from local to global coordinate space.
     598             :   nscoord mLineLeft, mBlockStart;
     599             :   // We use 11 here in order to fill up the jemalloc allocatoed chunk nicely,
     600             :   // see https://bugzilla.mozilla.org/show_bug.cgi?id=1362876#c6.
     601             :   AutoTArray<FloatInfo, 11> mFloats;
     602             :   nsIntervalSet   mFloatDamage;
     603             : 
     604             :   // Did we try to place a float that could not fit at all and had to be
     605             :   // pushed to the next page/column?  If so, we can't place any more
     606             :   // floats in this page/column because of the rule that the top of a
     607             :   // float cannot be above the top of an earlier float.  And we also
     608             :   // need to apply this information to 'clear', and thus need to
     609             :   // separate left and right floats.
     610             :   bool mPushedLeftFloatPastBreak;
     611             :   bool mPushedRightFloatPastBreak;
     612             : 
     613             :   // Did we split a float, with part of it needing to be pushed to the
     614             :   // next page/column.  This means that any 'clear' needs to continue to
     615             :   // the next page/column.
     616             :   bool mSplitLeftFloatAcrossBreak;
     617             :   bool mSplitRightFloatAcrossBreak;
     618             : 
     619             :   static int32_t sCachedFloatManagerCount;
     620             :   static void* sCachedFloatManagers[NS_FLOAT_MANAGER_CACHE_SIZE];
     621             : 
     622             :   nsFloatManager(const nsFloatManager&) = delete;
     623             :   void operator=(const nsFloatManager&) = delete;
     624             : };
     625             : 
     626             : /**
     627             :  * A helper class to manage maintenance of the float manager during
     628             :  * nsBlockFrame::Reflow. It automatically restores the old float
     629             :  * manager in the reflow input when the object goes out of scope.
     630             :  */
     631             : class nsAutoFloatManager {
     632             :   using ReflowInput = mozilla::ReflowInput;
     633             : 
     634             : public:
     635         162 :   explicit nsAutoFloatManager(ReflowInput& aReflowInput)
     636         162 :     : mReflowInput(aReflowInput)
     637         162 :     , mOld(nullptr)
     638         162 :   {}
     639             : 
     640             :   ~nsAutoFloatManager();
     641             : 
     642             :   /**
     643             :    * Create a new float manager for the specified frame. This will
     644             :    * `remember' the old float manager, and install the new float
     645             :    * manager in the reflow input.
     646             :    */
     647             :   void
     648             :   CreateFloatManager(nsPresContext *aPresContext);
     649             : 
     650             : protected:
     651             :   ReflowInput &mReflowInput;
     652             :   mozilla::UniquePtr<nsFloatManager> mNew;
     653             : 
     654             :   // A non-owning pointer, which points to the object owned by
     655             :   // nsAutoFloatManager::mNew.
     656             :   nsFloatManager* mOld;
     657             : };
     658             : 
     659             : #endif /* !defined(nsFloatManager_h_) */

Generated by: LCOV version 1.13