1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
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/. */
7 /* struct containing the output from nsIFrame::Reflow */
9 #ifndef mozilla_ReflowOutput_h
10 #define mozilla_ReflowOutput_h
12 #include "mozilla/EnumeratedRange.h"
13 #include "mozilla/WritingModes.h"
14 #include "nsBoundingMetrics.h"
17 //----------------------------------------------------------------------
22 enum class OverflowType
: uint8_t { Ink
, Scrollable
};
23 constexpr auto AllOverflowTypes() {
24 return mozilla::MakeInclusiveEnumeratedRange(OverflowType::Ink
,
25 OverflowType::Scrollable
);
28 struct OverflowAreas
{
30 nsRect
& InkOverflow() { return mInk
; }
31 const nsRect
& InkOverflow() const { return mInk
; }
33 nsRect
& ScrollableOverflow() { return mScrollable
; }
34 const nsRect
& ScrollableOverflow() const { return mScrollable
; }
36 nsRect
& Overflow(OverflowType aType
) {
37 return aType
== OverflowType::Ink
? InkOverflow() : ScrollableOverflow();
39 const nsRect
& Overflow(OverflowType aType
) const {
40 return aType
== OverflowType::Ink
? InkOverflow() : ScrollableOverflow();
43 OverflowAreas() = default;
45 OverflowAreas(const nsRect
& aInkOverflow
, const nsRect
& aScrollableOverflow
)
46 : mInk(aInkOverflow
), mScrollable(aScrollableOverflow
) {}
48 bool operator==(const OverflowAreas
& aOther
) const {
49 // Scrollable overflow is a point-set rectangle and ink overflow
50 // is a pixel-set rectangle.
51 return InkOverflow().IsEqualInterior(aOther
.InkOverflow()) &&
52 ScrollableOverflow().IsEqualEdges(aOther
.ScrollableOverflow());
55 bool operator!=(const OverflowAreas
& aOther
) const {
56 return !(*this == aOther
);
59 OverflowAreas
operator+(const nsPoint
& aPoint
) const {
60 OverflowAreas
result(*this);
65 OverflowAreas
& operator+=(const nsPoint
& aPoint
) {
67 mScrollable
+= aPoint
;
71 void Clear() { SetAllTo(nsRect()); }
73 // Mutates |this| by unioning both overflow areas with |aOther|.
74 void UnionWith(const OverflowAreas
& aOther
);
76 // Mutates |this| by unioning both overflow areas with |aRect|.
77 void UnionAllWith(const nsRect
& aRect
);
79 // Mutates |this| by setting both overflow areas to |aRect|.
80 void SetAllTo(const nsRect
& aRect
);
82 // Applies overflow clipping (for e.g. overflow: clip) as needed to both our
84 void ApplyClipping(const nsRect
& aBounds
, PhysicalAxes aClipAxes
,
85 const nsSize
& aOverflowMargin
) {
86 ApplyOverflowClippingOnRect(InkOverflow(), aBounds
, aClipAxes
,
88 ApplyOverflowClippingOnRect(ScrollableOverflow(), aBounds
, aClipAxes
,
92 // Gets the overflow clipping rect for a given element given a rect to clip,
93 // the frame bounds, a set of axes, and the overflow margin.
94 static nsRect
GetOverflowClipRect(const nsRect
& aRectToClip
,
95 const nsRect
& aBounds
,
96 PhysicalAxes aClipAxes
,
97 const nsSize
& aOverflowMargin
);
99 // Applies the overflow clipping to a given overflow rect, given the frame
100 // bounds, and the physical axes on which to apply the overflow clip.
101 static void ApplyOverflowClippingOnRect(nsRect
& aOverflowRect
,
102 const nsRect
& aBounds
,
103 PhysicalAxes aClipAxes
,
104 const nsSize
& aOverflowMargin
);
112 * CollapsingMargin represents a vertical collapsing margin between
113 * blocks as described in section 8.3.1 of CSS2.
114 * <https://www.w3.org/TR/CSS22/box.html#collapsing-margins>
116 * All adjacent vertical margins collapse, and the resulting margin is
117 * the sum of the largest positive margin included and the smallest (most
118 * negative) negative margin included.
120 class CollapsingMargin final
{
122 bool operator==(const CollapsingMargin
& aOther
) const {
123 return mMostPos
== aOther
.mMostPos
&& mMostNeg
== aOther
.mMostNeg
;
126 bool operator!=(const CollapsingMargin
& aOther
) const {
127 return !(*this == aOther
);
130 void Include(nscoord aCoord
) {
131 if (aCoord
> mMostPos
) {
133 } else if (aCoord
< mMostNeg
) {
138 void Include(const CollapsingMargin
& aOther
) {
139 if (aOther
.mMostPos
> mMostPos
) {
140 mMostPos
= aOther
.mMostPos
;
142 if (aOther
.mMostNeg
< mMostNeg
) {
143 mMostNeg
= aOther
.mMostNeg
;
152 bool IsZero() const { return mMostPos
== 0 && mMostNeg
== 0; }
154 nscoord
Get() const { return mMostPos
+ mMostNeg
; }
157 // The largest positive margin included.
158 nscoord mMostPos
= 0;
160 // The smallest negative margin included.
161 nscoord mMostNeg
= 0;
165 * ReflowOutput is initialized by a parent frame as a parameter passing to
166 * Reflow() to allow a child frame to return its desired size and alignment
169 * ReflowOutput's constructor usually takes a parent frame's WritingMode (or
170 * ReflowInput) because it is more convenient for the parent frame to use the
171 * stored Size() after reflowing the child frame. However, it can actually
172 * accept any WritingMode (or ReflowInput) because SetSize() knows how to
173 * convert a size in any writing mode to the stored writing mode.
175 * @see nsIFrame::Reflow() for more information.
179 explicit ReflowOutput(mozilla::WritingMode aWritingMode
)
180 : mSize(aWritingMode
), mWritingMode(aWritingMode
) {}
182 // A convenient constructor to get WritingMode in ReflowInput.
183 explicit ReflowOutput(const ReflowInput
& aReflowInput
);
185 nscoord
ISize(mozilla::WritingMode aWritingMode
) const {
186 return mSize
.ISize(aWritingMode
);
188 nscoord
BSize(mozilla::WritingMode aWritingMode
) const {
189 return mSize
.BSize(aWritingMode
);
191 mozilla::LogicalSize
Size(mozilla::WritingMode aWritingMode
) const {
192 return mSize
.ConvertTo(aWritingMode
, mWritingMode
);
195 nscoord
& ISize(mozilla::WritingMode aWritingMode
) {
196 return mSize
.ISize(aWritingMode
);
198 nscoord
& BSize(mozilla::WritingMode aWritingMode
) {
199 return mSize
.BSize(aWritingMode
);
202 // Set inline and block size from a LogicalSize, converting to our
203 // writing mode as necessary.
204 void SetSize(mozilla::WritingMode aWM
, mozilla::LogicalSize aSize
) {
205 mSize
= aSize
.ConvertTo(mWritingMode
, aWM
);
208 // Set both inline and block size to zero -- no need for a writing mode!
209 void ClearSize() { mSize
.SizeTo(mWritingMode
, 0, 0); }
211 // Width and Height are physical dimensions, independent of writing mode.
212 // Accessing these is slightly more expensive than accessing the logical
213 // dimensions; as far as possible, client code should work purely with logical
215 nscoord
Width() const { return mSize
.Width(mWritingMode
); }
216 nscoord
Height() const { return mSize
.Height(mWritingMode
); }
218 return mWritingMode
.IsVertical() ? mSize
.BSize(mWritingMode
)
219 : mSize
.ISize(mWritingMode
);
222 return mWritingMode
.IsVertical() ? mSize
.ISize(mWritingMode
)
223 : mSize
.BSize(mWritingMode
);
226 nsSize
PhysicalSize() const { return mSize
.GetPhysicalSize(mWritingMode
); }
228 // It's only meaningful to consider "ascent" on the block-start side of the
229 // frame, so no need to pass a writing mode argument
230 enum { ASK_FOR_BASELINE
= nscoord_MAX
};
231 nscoord
BlockStartAscent() const { return mBlockStartAscent
; }
232 void SetBlockStartAscent(nscoord aAscent
) { mBlockStartAscent
= aAscent
; }
234 // Metrics that _exactly_ enclose the text to allow precise MathML placements.
235 nsBoundingMetrics mBoundingMetrics
; // [OUT]
237 // Carried out block-end margin values. This is the collapsed
238 // (generational) block-end margin value.
239 CollapsingMargin mCarriedOutBEndMargin
;
241 // For frames that have content that overflow their content area
242 // (HasOverflowAreas() is true) these rectangles represent the total
243 // area of the frame including visible overflow, i.e., don't include
244 // overflowing content that is hidden. The rects are in the local
245 // coordinate space of the frame, and should be at least as big as the
246 // desired size. If there is no content that overflows, then the
247 // overflow area is identical to the desired size and should be {0, 0,
249 OverflowAreas mOverflowAreas
;
251 nsRect
& InkOverflow() { return mOverflowAreas
.InkOverflow(); }
252 const nsRect
& InkOverflow() const { return mOverflowAreas
.InkOverflow(); }
253 nsRect
& ScrollableOverflow() { return mOverflowAreas
.ScrollableOverflow(); }
254 const nsRect
& ScrollableOverflow() const {
255 return mOverflowAreas
.ScrollableOverflow();
258 // Set all of mOverflowAreas to (0, 0, width, height).
259 void SetOverflowAreasToDesiredBounds();
261 // Union all of mOverflowAreas with (0, 0, width, height).
262 void UnionOverflowAreasWithDesiredBounds();
264 mozilla::WritingMode
GetWritingMode() const { return mWritingMode
; }
267 // Desired size of a frame's border-box.
270 // Baseline (in block direction), or the default value ASK_FOR_BASELINE.
271 nscoord mBlockStartAscent
= ASK_FOR_BASELINE
;
273 mozilla::WritingMode mWritingMode
;
276 } // namespace mozilla
278 #endif // mozilla_ReflowOutput_h