forked from mirrors/gecko-dev
		
	 fb32f0a2c2
			
		
	
	
		fb32f0a2c2
		
	
	
	
	
		
			
			I realized my fix in bug 1769512 (using IsEmpty()) wasn't quite correct in this case, because IntersectionObserver preserves edge-inclusive intersections. Differential Revision: https://phabricator.services.mozilla.com/D147078
		
			
				
	
	
		
			280 lines
		
	
	
	
		
			9.8 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			280 lines
		
	
	
	
		
			9.8 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 | |
| /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 | |
| /* This Source Code Form is subject to the terms of the Mozilla Public
 | |
|  * License, v. 2.0. If a copy of the MPL was not distributed with this
 | |
|  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 | |
| 
 | |
| /* struct containing the output from nsIFrame::Reflow */
 | |
| 
 | |
| #ifndef mozilla_ReflowOutput_h
 | |
| #define mozilla_ReflowOutput_h
 | |
| 
 | |
| #include "mozilla/EnumeratedRange.h"
 | |
| #include "mozilla/WritingModes.h"
 | |
| #include "nsBoundingMetrics.h"
 | |
| #include "nsRect.h"
 | |
| 
 | |
| //----------------------------------------------------------------------
 | |
| 
 | |
| namespace mozilla {
 | |
| struct ReflowInput;
 | |
| 
 | |
| enum class OverflowType : uint8_t { Ink, Scrollable };
 | |
| constexpr auto AllOverflowTypes() {
 | |
|   return mozilla::MakeInclusiveEnumeratedRange(OverflowType::Ink,
 | |
|                                                OverflowType::Scrollable);
 | |
| }
 | |
| 
 | |
| struct OverflowAreas {
 | |
|  public:
 | |
|   nsRect& InkOverflow() { return mInk; }
 | |
|   const nsRect& InkOverflow() const { return mInk; }
 | |
| 
 | |
|   nsRect& ScrollableOverflow() { return mScrollable; }
 | |
|   const nsRect& ScrollableOverflow() const { return mScrollable; }
 | |
| 
 | |
|   nsRect& Overflow(OverflowType aType) {
 | |
|     return aType == OverflowType::Ink ? InkOverflow() : ScrollableOverflow();
 | |
|   }
 | |
|   const nsRect& Overflow(OverflowType aType) const {
 | |
|     return aType == OverflowType::Ink ? InkOverflow() : ScrollableOverflow();
 | |
|   }
 | |
| 
 | |
|   OverflowAreas() = default;
 | |
| 
 | |
|   OverflowAreas(const nsRect& aInkOverflow, const nsRect& aScrollableOverflow)
 | |
|       : mInk(aInkOverflow), mScrollable(aScrollableOverflow) {}
 | |
| 
 | |
|   bool operator==(const OverflowAreas& aOther) const {
 | |
|     // Scrollable overflow is a point-set rectangle and ink overflow
 | |
|     // is a pixel-set rectangle.
 | |
|     return InkOverflow().IsEqualInterior(aOther.InkOverflow()) &&
 | |
|            ScrollableOverflow().IsEqualEdges(aOther.ScrollableOverflow());
 | |
|   }
 | |
| 
 | |
|   bool operator!=(const OverflowAreas& aOther) const {
 | |
|     return !(*this == aOther);
 | |
|   }
 | |
| 
 | |
|   OverflowAreas operator+(const nsPoint& aPoint) const {
 | |
|     OverflowAreas result(*this);
 | |
|     result += aPoint;
 | |
|     return result;
 | |
|   }
 | |
| 
 | |
|   OverflowAreas& operator+=(const nsPoint& aPoint) {
 | |
|     mInk += aPoint;
 | |
|     mScrollable += aPoint;
 | |
|     return *this;
 | |
|   }
 | |
| 
 | |
|   void Clear() { SetAllTo(nsRect()); }
 | |
| 
 | |
|   // Mutates |this| by unioning both overflow areas with |aOther|.
 | |
|   void UnionWith(const OverflowAreas& aOther);
 | |
| 
 | |
|   // Mutates |this| by unioning both overflow areas with |aRect|.
 | |
|   void UnionAllWith(const nsRect& aRect);
 | |
| 
 | |
|   // Mutates |this| by setting both overflow areas to |aRect|.
 | |
|   void SetAllTo(const nsRect& aRect);
 | |
| 
 | |
|   // Applies overflow clipping (for e.g. overflow: clip) as needed to both our
 | |
|   // overflow rects.
 | |
|   void ApplyClipping(const nsRect& aBounds, PhysicalAxes aClipAxes,
 | |
|                      const nsSize& aOverflowMargin) {
 | |
|     ApplyOverflowClippingOnRect(InkOverflow(), aBounds, aClipAxes,
 | |
|                                 aOverflowMargin);
 | |
|     ApplyOverflowClippingOnRect(ScrollableOverflow(), aBounds, aClipAxes,
 | |
|                                 aOverflowMargin);
 | |
|   }
 | |
| 
 | |
|   // Gets the overflow clipping rect for a given element given a rect to clip,
 | |
|   // the frame bounds, a set of axes, and the overflow margin.
 | |
|   static nsRect GetOverflowClipRect(const nsRect& aRectToClip,
 | |
|                                     const nsRect& aBounds,
 | |
|                                     PhysicalAxes aClipAxes,
 | |
|                                     const nsSize& aOverflowMargin);
 | |
| 
 | |
|   // Applies the overflow clipping to a given overflow rect, given the frame
 | |
|   // bounds, and the physical axes on which to apply the overflow clip.
 | |
|   static void ApplyOverflowClippingOnRect(nsRect& aOverflowRect,
 | |
|                                           const nsRect& aBounds,
 | |
|                                           PhysicalAxes aClipAxes,
 | |
|                                           const nsSize& aOverflowMargin);
 | |
| 
 | |
|  private:
 | |
|   nsRect mInk;
 | |
|   nsRect mScrollable;
 | |
| };
 | |
| 
 | |
| }  // namespace mozilla
 | |
| 
 | |
| /**
 | |
|  * An nsCollapsingMargin represents a vertical collapsing margin between
 | |
|  * blocks as described in section 8.3.1 of CSS2,
 | |
|  * <URL: http://www.w3.org/TR/REC-CSS2/box.html#collapsing-margins >.
 | |
|  *
 | |
|  * All adjacent vertical margins collapse, and the resulting margin is
 | |
|  * the sum of the largest positive margin included and the smallest (most
 | |
|  * negative) negative margin included.
 | |
|  */
 | |
| struct nsCollapsingMargin {
 | |
|  private:
 | |
|   nscoord mMostPos;  // the largest positive margin included
 | |
|   nscoord mMostNeg;  // the smallest negative margin included
 | |
| 
 | |
|  public:
 | |
|   nsCollapsingMargin() : mMostPos(0), mMostNeg(0) {}
 | |
| 
 | |
|   nsCollapsingMargin(const nsCollapsingMargin& aOther) = default;
 | |
| 
 | |
|   bool operator==(const nsCollapsingMargin& aOther) {
 | |
|     return mMostPos == aOther.mMostPos && mMostNeg == aOther.mMostNeg;
 | |
|   }
 | |
| 
 | |
|   bool operator!=(const nsCollapsingMargin& aOther) {
 | |
|     return !(*this == aOther);
 | |
|   }
 | |
| 
 | |
|   nsCollapsingMargin& operator=(const nsCollapsingMargin& aOther) = default;
 | |
| 
 | |
|   void Include(nscoord aCoord) {
 | |
|     if (aCoord > mMostPos)
 | |
|       mMostPos = aCoord;
 | |
|     else if (aCoord < mMostNeg)
 | |
|       mMostNeg = aCoord;
 | |
|   }
 | |
| 
 | |
|   void Include(const nsCollapsingMargin& aOther) {
 | |
|     if (aOther.mMostPos > mMostPos) mMostPos = aOther.mMostPos;
 | |
|     if (aOther.mMostNeg < mMostNeg) mMostNeg = aOther.mMostNeg;
 | |
|   }
 | |
| 
 | |
|   void Zero() {
 | |
|     mMostPos = 0;
 | |
|     mMostNeg = 0;
 | |
|   }
 | |
| 
 | |
|   bool IsZero() const { return (mMostPos == 0) && (mMostNeg == 0); }
 | |
| 
 | |
|   nscoord get() const { return mMostPos + mMostNeg; }
 | |
| };
 | |
| 
 | |
| namespace mozilla {
 | |
| 
 | |
| /**
 | |
|  * ReflowOutput is initialized by a parent frame as a parameter passing to
 | |
|  * Reflow() to allow a child frame to return its desired size and alignment
 | |
|  * information.
 | |
|  *
 | |
|  * ReflowOutput's constructor usually takes a parent frame's WritingMode (or
 | |
|  * ReflowInput) because it is more convenient for the parent frame to use the
 | |
|  * stored Size() after reflowing the child frame. However, it can actually
 | |
|  * accept any WritingMode (or ReflowInput) because SetSize() knows how to
 | |
|  * convert a size in any writing mode to the stored writing mode.
 | |
|  *
 | |
|  * @see nsIFrame::Reflow() for more information.
 | |
|  */
 | |
| class ReflowOutput {
 | |
|  public:
 | |
|   explicit ReflowOutput(mozilla::WritingMode aWritingMode)
 | |
|       : mSize(aWritingMode), mWritingMode(aWritingMode) {}
 | |
| 
 | |
|   // A convenient constructor to get WritingMode in ReflowInput.
 | |
|   explicit ReflowOutput(const ReflowInput& aReflowInput);
 | |
| 
 | |
|   nscoord ISize(mozilla::WritingMode aWritingMode) const {
 | |
|     return mSize.ISize(aWritingMode);
 | |
|   }
 | |
|   nscoord BSize(mozilla::WritingMode aWritingMode) const {
 | |
|     return mSize.BSize(aWritingMode);
 | |
|   }
 | |
|   mozilla::LogicalSize Size(mozilla::WritingMode aWritingMode) const {
 | |
|     return mSize.ConvertTo(aWritingMode, mWritingMode);
 | |
|   }
 | |
| 
 | |
|   nscoord& ISize(mozilla::WritingMode aWritingMode) {
 | |
|     return mSize.ISize(aWritingMode);
 | |
|   }
 | |
|   nscoord& BSize(mozilla::WritingMode aWritingMode) {
 | |
|     return mSize.BSize(aWritingMode);
 | |
|   }
 | |
| 
 | |
|   // Set inline and block size from a LogicalSize, converting to our
 | |
|   // writing mode as necessary.
 | |
|   void SetSize(mozilla::WritingMode aWM, mozilla::LogicalSize aSize) {
 | |
|     mSize = aSize.ConvertTo(mWritingMode, aWM);
 | |
|   }
 | |
| 
 | |
|   // Set both inline and block size to zero -- no need for a writing mode!
 | |
|   void ClearSize() { mSize.SizeTo(mWritingMode, 0, 0); }
 | |
| 
 | |
|   // Width and Height are physical dimensions, independent of writing mode.
 | |
|   // Accessing these is slightly more expensive than accessing the logical
 | |
|   // dimensions; as far as possible, client code should work purely with logical
 | |
|   // dimensions.
 | |
|   nscoord Width() const { return mSize.Width(mWritingMode); }
 | |
|   nscoord Height() const { return mSize.Height(mWritingMode); }
 | |
|   nscoord& Width() {
 | |
|     return mWritingMode.IsVertical() ? mSize.BSize(mWritingMode)
 | |
|                                      : mSize.ISize(mWritingMode);
 | |
|   }
 | |
|   nscoord& Height() {
 | |
|     return mWritingMode.IsVertical() ? mSize.ISize(mWritingMode)
 | |
|                                      : mSize.BSize(mWritingMode);
 | |
|   }
 | |
| 
 | |
|   nsSize PhysicalSize() const { return mSize.GetPhysicalSize(mWritingMode); }
 | |
| 
 | |
|   // It's only meaningful to consider "ascent" on the block-start side of the
 | |
|   // frame, so no need to pass a writing mode argument
 | |
|   enum { ASK_FOR_BASELINE = nscoord_MAX };
 | |
|   nscoord BlockStartAscent() const { return mBlockStartAscent; }
 | |
|   void SetBlockStartAscent(nscoord aAscent) { mBlockStartAscent = aAscent; }
 | |
| 
 | |
|   // Metrics that _exactly_ enclose the text to allow precise MathML placements.
 | |
|   nsBoundingMetrics mBoundingMetrics;  // [OUT]
 | |
| 
 | |
|   // Carried out block-end margin values. This is the collapsed
 | |
|   // (generational) block-end margin value.
 | |
|   nsCollapsingMargin mCarriedOutBEndMargin;
 | |
| 
 | |
|   // For frames that have content that overflow their content area
 | |
|   // (HasOverflowAreas() is true) these rectangles represent the total
 | |
|   // area of the frame including visible overflow, i.e., don't include
 | |
|   // overflowing content that is hidden.  The rects are in the local
 | |
|   // coordinate space of the frame, and should be at least as big as the
 | |
|   // desired size. If there is no content that overflows, then the
 | |
|   // overflow area is identical to the desired size and should be {0, 0,
 | |
|   // width, height}.
 | |
|   OverflowAreas mOverflowAreas;
 | |
| 
 | |
|   nsRect& InkOverflow() { return mOverflowAreas.InkOverflow(); }
 | |
|   const nsRect& InkOverflow() const { return mOverflowAreas.InkOverflow(); }
 | |
|   nsRect& ScrollableOverflow() { return mOverflowAreas.ScrollableOverflow(); }
 | |
|   const nsRect& ScrollableOverflow() const {
 | |
|     return mOverflowAreas.ScrollableOverflow();
 | |
|   }
 | |
| 
 | |
|   // Set all of mOverflowAreas to (0, 0, width, height).
 | |
|   void SetOverflowAreasToDesiredBounds();
 | |
| 
 | |
|   // Union all of mOverflowAreas with (0, 0, width, height).
 | |
|   void UnionOverflowAreasWithDesiredBounds();
 | |
| 
 | |
|   mozilla::WritingMode GetWritingMode() const { return mWritingMode; }
 | |
| 
 | |
|  private:
 | |
|   // Desired size of a frame's border-box.
 | |
|   LogicalSize mSize;
 | |
| 
 | |
|   // Baseline (in block direction), or the default value ASK_FOR_BASELINE.
 | |
|   nscoord mBlockStartAscent = ASK_FOR_BASELINE;
 | |
| 
 | |
|   mozilla::WritingMode mWritingMode;
 | |
| };
 | |
| 
 | |
| }  // namespace mozilla
 | |
| 
 | |
| #endif  // mozilla_ReflowOutput_h
 |