Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
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/. */
6 /* struct containing the output from nsIFrame::Reflow */
8 #ifndef nsHTMLReflowMetrics_h___
9 #define nsHTMLReflowMetrics_h___
11 #include "nsRect.h"
12 #include "nsBoundingMetrics.h"
13 #include "WritingModes.h"
15 //----------------------------------------------------------------------
17 class nsHTMLReflowState;
19 // Option flags
20 #define NS_REFLOW_CALC_BOUNDING_METRICS 0x0001
22 /**
23 * When we store overflow areas as an array of scrollable and visual
24 * overflow, we use these indices.
25 *
26 * eOverflowType_LENGTH is needed (for gcc 4.5.*, at least) to ensure
27 * that 2 is a valid value of nsOverflowType for use in
28 * NS_FOR_FRAME_OVERFLOW_TYPES.
29 */
30 enum nsOverflowType { eVisualOverflow, eScrollableOverflow,
31 eOverflowType_LENGTH };
33 #define NS_FOR_FRAME_OVERFLOW_TYPES(var_) \
34 for (nsOverflowType var_ = nsOverflowType(0); var_ < 2; \
35 var_ = nsOverflowType(var_ + 1))
37 struct nsOverflowAreas {
38 private:
39 nsRect mRects[2];
40 public:
41 nsRect& Overflow(size_t aIndex) {
42 NS_ASSERTION(aIndex < 2, "index out of range");
43 return mRects[aIndex];
44 }
45 const nsRect& Overflow(size_t aIndex) const {
46 NS_ASSERTION(aIndex < 2, "index out of range");
47 return mRects[aIndex];
48 }
50 nsRect& VisualOverflow() { return mRects[eVisualOverflow]; }
51 const nsRect& VisualOverflow() const { return mRects[eVisualOverflow]; }
53 nsRect& ScrollableOverflow() { return mRects[eScrollableOverflow]; }
54 const nsRect& ScrollableOverflow() const { return mRects[eScrollableOverflow]; }
56 nsOverflowAreas() {
57 // default-initializes to zero due to nsRect's default constructor
58 }
60 nsOverflowAreas(const nsRect& aVisualOverflow,
61 const nsRect& aScrollableOverflow)
62 {
63 mRects[eVisualOverflow] = aVisualOverflow;
64 mRects[eScrollableOverflow] = aScrollableOverflow;
65 }
67 nsOverflowAreas(const nsOverflowAreas& aOther) {
68 *this = aOther;
69 }
71 nsOverflowAreas& operator=(const nsOverflowAreas& aOther) {
72 mRects[0] = aOther.mRects[0];
73 mRects[1] = aOther.mRects[1];
74 return *this;
75 }
77 bool operator==(const nsOverflowAreas& aOther) const {
78 // Scrollable overflow is a point-set rectangle and visual overflow
79 // is a pixel-set rectangle.
80 return VisualOverflow().IsEqualInterior(aOther.VisualOverflow()) &&
81 ScrollableOverflow().IsEqualEdges(aOther.ScrollableOverflow());
82 }
84 bool operator!=(const nsOverflowAreas& aOther) const {
85 return !(*this == aOther);
86 }
88 nsOverflowAreas operator+(const nsPoint& aPoint) const {
89 nsOverflowAreas result(*this);
90 result += aPoint;
91 return result;
92 }
94 nsOverflowAreas& operator+=(const nsPoint& aPoint) {
95 mRects[0] += aPoint;
96 mRects[1] += aPoint;
97 return *this;
98 }
100 void Clear() {
101 mRects[0].SetRect(0, 0, 0, 0);
102 mRects[1].SetRect(0, 0, 0, 0);
103 }
105 // Mutates |this| by unioning both overflow areas with |aOther|.
106 void UnionWith(const nsOverflowAreas& aOther);
108 // Mutates |this| by unioning both overflow areas with |aRect|.
109 void UnionAllWith(const nsRect& aRect);
111 // Mutates |this| by setting both overflow areas to |aRect|.
112 void SetAllTo(const nsRect& aRect);
113 };
115 /**
116 * An nsCollapsingMargin represents a vertical collapsing margin between
117 * blocks as described in section 8.3.1 of CSS2,
118 * <URL: http://www.w3.org/TR/REC-CSS2/box.html#collapsing-margins >.
119 *
120 * All adjacent vertical margins collapse, and the resulting margin is
121 * the sum of the largest positive margin included and the smallest (most
122 * negative) negative margin included.
123 */
124 struct nsCollapsingMargin {
125 private:
126 nscoord mMostPos; // the largest positive margin included
127 nscoord mMostNeg; // the smallest negative margin included
129 public:
130 nsCollapsingMargin()
131 : mMostPos(0),
132 mMostNeg(0)
133 {
134 }
136 nsCollapsingMargin(const nsCollapsingMargin& aOther)
137 : mMostPos(aOther.mMostPos),
138 mMostNeg(aOther.mMostNeg)
139 {
140 }
142 bool operator==(const nsCollapsingMargin& aOther)
143 {
144 return mMostPos == aOther.mMostPos &&
145 mMostNeg == aOther.mMostNeg;
146 }
148 bool operator!=(const nsCollapsingMargin& aOther)
149 {
150 return !(*this == aOther);
151 }
153 nsCollapsingMargin& operator=(const nsCollapsingMargin& aOther)
154 {
155 mMostPos = aOther.mMostPos;
156 mMostNeg = aOther.mMostNeg;
157 return *this;
158 }
160 void Include(nscoord aCoord)
161 {
162 if (aCoord > mMostPos)
163 mMostPos = aCoord;
164 else if (aCoord < mMostNeg)
165 mMostNeg = aCoord;
166 }
168 void Include(const nsCollapsingMargin& aOther)
169 {
170 if (aOther.mMostPos > mMostPos)
171 mMostPos = aOther.mMostPos;
172 if (aOther.mMostNeg < mMostNeg)
173 mMostNeg = aOther.mMostNeg;
174 }
176 void Zero()
177 {
178 mMostPos = 0;
179 mMostNeg = 0;
180 }
182 bool IsZero() const
183 {
184 return (mMostPos == 0) && (mMostNeg == 0);
185 }
187 nscoord get() const
188 {
189 return mMostPos + mMostNeg;
190 }
191 };
193 /**
194 * Reflow metrics used to return the frame's desired size and alignment
195 * information.
196 *
197 * @see #Reflow()
198 */
199 class nsHTMLReflowMetrics {
200 public:
201 // XXXldb Should |aFlags| generally be passed from parent to child?
202 // Some places do it, and some don't. |aFlags| should perhaps go away
203 // entirely.
204 // XXX width/height/ascent are OUT parameters and so they shouldn't
205 // have to be initialized, but there are some bad frame classes that
206 // aren't properly setting them when returning from Reflow()...
207 nsHTMLReflowMetrics(mozilla::WritingMode aWritingMode, uint32_t aFlags = 0)
208 : mISize(0)
209 , mBSize(0)
210 , mBlockStartAscent(ASK_FOR_BASELINE)
211 , mFlags(aFlags)
212 , mWritingMode(aWritingMode)
213 {}
215 nsHTMLReflowMetrics(const nsHTMLReflowState& aState, uint32_t aFlags = 0);
217 // ISize and BSize are logical-coordinate dimensions:
218 // ISize is the size in the writing mode's inline direction (which equates to
219 // width in horizontal writing modes, height in vertical ones), and BSize is
220 // the size in the block-progression direction.
221 nscoord ISize() const { return mISize; }
222 nscoord BSize() const { return mBSize; }
224 nscoord& ISize() { return mISize; }
225 nscoord& BSize() { return mBSize; }
227 // Width and Height are physical dimensions, independent of writing mode.
228 // Accessing these is slightly more expensive than accessing the logical
229 // dimensions (once vertical writing mode support is enabled); as far as
230 // possible, client code should work purely with logical dimensions.
231 nscoord Width() const { return mWritingMode.IsVertical() ? mBSize : mISize; }
232 nscoord Height() const { return mWritingMode.IsVertical() ? mISize : mBSize; }
234 // It's only meaningful to consider "ascent" on the block-start side of the
235 // frame; asking for the "ascent" on any other side will just return zero.
236 nscoord TopAscent() const
237 {
238 return mWritingMode.IsVertical() ? 0 : mBlockStartAscent;
239 }
240 nscoord LeftAscent() const
241 {
242 return mWritingMode.IsVertical() && mWritingMode.IsVerticalLR() ?
243 mBlockStartAscent : 0;
244 }
245 nscoord RightAscent() const
246 {
247 return mWritingMode.IsVertical() && !mWritingMode.IsVerticalLR() ?
248 mBlockStartAscent : 0;
249 }
251 nscoord& Width() { return mWritingMode.IsVertical() ? mBSize : mISize; }
252 nscoord& Height() { return mWritingMode.IsVertical() ? mISize : mBSize; }
254 // To set the ascent value, we must be sure we're working with the correct
255 // writing mode, so either pass it to the logical setter...
256 void SetBlockStartAscent(mozilla::WritingMode aWritingMode, nscoord aAscent)
257 {
258 NS_ASSERTION(aWritingMode == mWritingMode, "writing mode mismatch");
259 mBlockStartAscent = aAscent;
260 }
261 // ...or call the appropriate physical setter (these will probably be removed
262 // eventually).
263 void SetTopAscent(nscoord aAscent)
264 {
265 NS_ASSERTION(!mWritingMode.IsVertical(), "writing mode mismatch");
266 mBlockStartAscent = aAscent;
267 }
268 void SetLeftAscent(nscoord aAscent)
269 {
270 NS_ASSERTION(mWritingMode.IsVertical() && mWritingMode.IsVerticalLR(),
271 "writing mode mismatch");
272 mBlockStartAscent = aAscent;
273 }
274 void SetRightAscent(nscoord aAscent)
275 {
276 NS_ASSERTION(mWritingMode.IsVertical() && !mWritingMode.IsVerticalLR(),
277 "writing mode mismatch");
278 mBlockStartAscent = aAscent;
279 }
281 enum { ASK_FOR_BASELINE = nscoord_MAX };
283 // Metrics that _exactly_ enclose the text to allow precise MathML placements.
284 // If the NS_REFLOW_CALC_BOUNDING_METRICS flag is set, then the caller is
285 // requesting that you also compute additional details about your inner
286 // bounding box and italic correction. For example, the bounding box of
287 // msup is the smallest rectangle that _exactly_ encloses both the text
288 // of the base and the text of the superscript.
289 nsBoundingMetrics mBoundingMetrics; // [OUT]
291 // Carried out bottom margin values. This is the collapsed
292 // (generational) bottom margin value.
293 nsCollapsingMargin mCarriedOutBottomMargin;
295 // For frames that have content that overflow their content area
296 // (HasOverflowAreas() is true) these rectangles represent the total
297 // area of the frame including visible overflow, i.e., don't include
298 // overflowing content that is hidden. The rects are in the local
299 // coordinate space of the frame, and should be at least as big as the
300 // desired size. If there is no content that overflows, then the
301 // overflow area is identical to the desired size and should be {0, 0,
302 // width, height}.
303 nsOverflowAreas mOverflowAreas;
305 nsRect& VisualOverflow()
306 { return mOverflowAreas.VisualOverflow(); }
307 const nsRect& VisualOverflow() const
308 { return mOverflowAreas.VisualOverflow(); }
309 nsRect& ScrollableOverflow()
310 { return mOverflowAreas.ScrollableOverflow(); }
311 const nsRect& ScrollableOverflow() const
312 { return mOverflowAreas.ScrollableOverflow(); }
314 // Set all of mOverflowAreas to (0, 0, width, height).
315 void SetOverflowAreasToDesiredBounds();
317 // Union all of mOverflowAreas with (0, 0, width, height).
318 void UnionOverflowAreasWithDesiredBounds();
320 mozilla::WritingMode GetWritingMode() const { return mWritingMode; }
322 private:
323 nscoord mISize, mBSize; // [OUT] desired width and height (border-box)
324 nscoord mBlockStartAscent; // [OUT] baseline (in Block direction), or ASK_FOR_BASELINE
326 public:
327 uint32_t mFlags;
329 private:
330 mozilla::WritingMode mWritingMode;
331 };
333 #endif /* nsHTMLReflowMetrics_h___ */