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 : /* struct containing the output from nsIFrame::Reflow */
7 :
8 : #ifndef mozilla_ReflowOutput_h
9 : #define mozilla_ReflowOutput_h
10 :
11 : #include "mozilla/WritingModes.h"
12 : #include "nsBoundingMetrics.h"
13 : #include "nsRect.h"
14 :
15 : //----------------------------------------------------------------------
16 :
17 : namespace mozilla {
18 : struct ReflowInput;
19 : } // namespace mozilla
20 :
21 : // Option flags
22 : #define NS_REFLOW_CALC_BOUNDING_METRICS 0x0001
23 :
24 : /**
25 : * When we store overflow areas as an array of scrollable and visual
26 : * overflow, we use these indices.
27 : *
28 : * eOverflowType_LENGTH is needed (for gcc 4.5.*, at least) to ensure
29 : * that 2 is a valid value of nsOverflowType for use in
30 : * NS_FOR_FRAME_OVERFLOW_TYPES.
31 : */
32 : enum nsOverflowType { eVisualOverflow, eScrollableOverflow,
33 : eOverflowType_LENGTH };
34 :
35 : #define NS_FOR_FRAME_OVERFLOW_TYPES(var_) \
36 : for (nsOverflowType var_ = nsOverflowType(0); var_ < 2; \
37 : var_ = nsOverflowType(var_ + 1))
38 :
39 7776 : struct nsOverflowAreas {
40 : private:
41 : nsRect mRects[2];
42 : public:
43 9149 : nsRect& Overflow(size_t aIndex) {
44 9149 : NS_ASSERTION(aIndex < 2, "index out of range");
45 9149 : return mRects[aIndex];
46 : }
47 340 : const nsRect& Overflow(size_t aIndex) const {
48 340 : NS_ASSERTION(aIndex < 2, "index out of range");
49 340 : return mRects[aIndex];
50 : }
51 :
52 4720 : nsRect& VisualOverflow() { return mRects[eVisualOverflow]; }
53 4073 : const nsRect& VisualOverflow() const { return mRects[eVisualOverflow]; }
54 :
55 683 : nsRect& ScrollableOverflow() { return mRects[eScrollableOverflow]; }
56 3460 : const nsRect& ScrollableOverflow() const { return mRects[eScrollableOverflow]; }
57 :
58 1609 : nsOverflowAreas() {
59 : // default-initializes to zero due to nsRect's default constructor
60 1609 : }
61 :
62 4269 : nsOverflowAreas(const nsRect& aVisualOverflow,
63 : const nsRect& aScrollableOverflow)
64 4269 : {
65 4269 : mRects[eVisualOverflow] = aVisualOverflow;
66 4269 : mRects[eScrollableOverflow] = aScrollableOverflow;
67 4269 : }
68 :
69 2028 : nsOverflowAreas(const nsOverflowAreas& aOther) {
70 2028 : *this = aOther;
71 2028 : }
72 :
73 2860 : nsOverflowAreas& operator=(const nsOverflowAreas& aOther) {
74 2860 : mRects[0] = aOther.mRects[0];
75 2860 : mRects[1] = aOther.mRects[1];
76 2860 : return *this;
77 : }
78 :
79 1938 : bool operator==(const nsOverflowAreas& aOther) const {
80 : // Scrollable overflow is a point-set rectangle and visual overflow
81 : // is a pixel-set rectangle.
82 3534 : return VisualOverflow().IsEqualInterior(aOther.VisualOverflow()) &&
83 3534 : ScrollableOverflow().IsEqualEdges(aOther.ScrollableOverflow());
84 : }
85 :
86 1926 : bool operator!=(const nsOverflowAreas& aOther) const {
87 1926 : return !(*this == aOther);
88 : }
89 :
90 1598 : nsOverflowAreas operator+(const nsPoint& aPoint) const {
91 1598 : nsOverflowAreas result(*this);
92 1598 : result += aPoint;
93 1598 : return result;
94 : }
95 :
96 1598 : nsOverflowAreas& operator+=(const nsPoint& aPoint) {
97 1598 : mRects[0] += aPoint;
98 1598 : mRects[1] += aPoint;
99 1598 : return *this;
100 : }
101 :
102 227 : void Clear() {
103 227 : mRects[0].SetRect(0, 0, 0, 0);
104 227 : mRects[1].SetRect(0, 0, 0, 0);
105 227 : }
106 :
107 : // Mutates |this| by unioning both overflow areas with |aOther|.
108 : void UnionWith(const nsOverflowAreas& aOther);
109 :
110 : // Mutates |this| by unioning both overflow areas with |aRect|.
111 : void UnionAllWith(const nsRect& aRect);
112 :
113 : // Mutates |this| by setting both overflow areas to |aRect|.
114 : void SetAllTo(const nsRect& aRect);
115 : };
116 :
117 : /**
118 : * An nsCollapsingMargin represents a vertical collapsing margin between
119 : * blocks as described in section 8.3.1 of CSS2,
120 : * <URL: http://www.w3.org/TR/REC-CSS2/box.html#collapsing-margins >.
121 : *
122 : * All adjacent vertical margins collapse, and the resulting margin is
123 : * the sum of the largest positive margin included and the smallest (most
124 : * negative) negative margin included.
125 : */
126 : struct nsCollapsingMargin {
127 : private:
128 : nscoord mMostPos; // the largest positive margin included
129 : nscoord mMostNeg; // the smallest negative margin included
130 :
131 : public:
132 817 : nsCollapsingMargin()
133 817 : : mMostPos(0),
134 817 : mMostNeg(0)
135 : {
136 817 : }
137 :
138 20 : nsCollapsingMargin(const nsCollapsingMargin& aOther)
139 20 : : mMostPos(aOther.mMostPos),
140 20 : mMostNeg(aOther.mMostNeg)
141 : {
142 20 : }
143 :
144 6 : bool operator==(const nsCollapsingMargin& aOther)
145 : {
146 10 : return mMostPos == aOther.mMostPos &&
147 10 : mMostNeg == aOther.mMostNeg;
148 : }
149 :
150 6 : bool operator!=(const nsCollapsingMargin& aOther)
151 : {
152 6 : return !(*this == aOther);
153 : }
154 :
155 46 : nsCollapsingMargin& operator=(const nsCollapsingMargin& aOther)
156 : {
157 46 : mMostPos = aOther.mMostPos;
158 46 : mMostNeg = aOther.mMostNeg;
159 46 : return *this;
160 : }
161 :
162 20 : void Include(nscoord aCoord)
163 : {
164 20 : if (aCoord > mMostPos)
165 12 : mMostPos = aCoord;
166 8 : else if (aCoord < mMostNeg)
167 0 : mMostNeg = aCoord;
168 20 : }
169 :
170 5 : void Include(const nsCollapsingMargin& aOther)
171 : {
172 5 : if (aOther.mMostPos > mMostPos)
173 0 : mMostPos = aOther.mMostPos;
174 5 : if (aOther.mMostNeg < mMostNeg)
175 0 : mMostNeg = aOther.mMostNeg;
176 5 : }
177 :
178 367 : void Zero()
179 : {
180 367 : mMostPos = 0;
181 367 : mMostNeg = 0;
182 367 : }
183 :
184 11 : bool IsZero() const
185 : {
186 11 : return (mMostPos == 0) && (mMostNeg == 0);
187 : }
188 :
189 271 : nscoord get() const
190 : {
191 271 : return mMostPos + mMostNeg;
192 : }
193 : };
194 :
195 : namespace mozilla {
196 :
197 : /**
198 : * Reflow metrics used to return the frame's desired size and alignment
199 : * information.
200 : *
201 : * @see #Reflow()
202 : */
203 633 : class ReflowOutput {
204 : public:
205 : // XXXldb Should |aFlags| generally be passed from parent to child?
206 : // Some places do it, and some don't. |aFlags| should perhaps go away
207 : // entirely.
208 : // XXX width/height/ascent are OUT parameters and so they shouldn't
209 : // have to be initialized, but there are some bad frame classes that
210 : // aren't properly setting them when returning from Reflow()...
211 326 : explicit ReflowOutput(mozilla::WritingMode aWritingMode, uint32_t aFlags = 0)
212 326 : : mISize(0)
213 : , mBSize(0)
214 : , mBlockStartAscent(ASK_FOR_BASELINE)
215 : , mFlags(aFlags)
216 326 : , mWritingMode(aWritingMode)
217 326 : {}
218 :
219 : explicit ReflowOutput(const ReflowInput& aState, uint32_t aFlags = 0);
220 :
221 : // ISize and BSize are logical-coordinate dimensions:
222 : // ISize is the size in the writing mode's inline direction (which equates to
223 : // width in horizontal writing modes, height in vertical ones), and BSize is
224 : // the size in the block-progression direction.
225 : nscoord ISize(mozilla::WritingMode aWritingMode) const {
226 : NS_ASSERTION(!aWritingMode.IsOrthogonalTo(mWritingMode),
227 : "mismatched writing mode");
228 : return mISize;
229 : }
230 0 : nscoord BSize(mozilla::WritingMode aWritingMode) const {
231 0 : NS_ASSERTION(!aWritingMode.IsOrthogonalTo(mWritingMode),
232 : "mismatched writing mode");
233 0 : return mBSize;
234 : }
235 404 : mozilla::LogicalSize Size(mozilla::WritingMode aWritingMode) const {
236 404 : NS_ASSERTION(!aWritingMode.IsOrthogonalTo(mWritingMode),
237 : "mismatched writing mode");
238 404 : return mozilla::LogicalSize(aWritingMode, mISize, mBSize);
239 : }
240 :
241 718 : nscoord& ISize(mozilla::WritingMode aWritingMode) {
242 718 : NS_ASSERTION(!aWritingMode.IsOrthogonalTo(mWritingMode),
243 : "mismatched writing mode");
244 718 : return mISize;
245 : }
246 817 : nscoord& BSize(mozilla::WritingMode aWritingMode) {
247 817 : NS_ASSERTION(!aWritingMode.IsOrthogonalTo(mWritingMode),
248 : "mismatched writing mode");
249 817 : return mBSize;
250 : }
251 :
252 : // Set inline and block size from a LogicalSize, converting to our
253 : // writing mode as necessary.
254 360 : void SetSize(mozilla::WritingMode aWM, mozilla::LogicalSize aSize)
255 : {
256 360 : mozilla::LogicalSize convertedSize = aSize.ConvertTo(mWritingMode, aWM);
257 360 : mBSize = convertedSize.BSize(mWritingMode);
258 360 : mISize = convertedSize.ISize(mWritingMode);
259 360 : }
260 :
261 : // Set both inline and block size to zero -- no need for a writing mode!
262 221 : void ClearSize()
263 : {
264 221 : mISize = mBSize = 0;
265 221 : }
266 :
267 : // Width and Height are physical dimensions, independent of writing mode.
268 : // Accessing these is slightly more expensive than accessing the logical
269 : // dimensions (once vertical writing mode support is enabled); as far as
270 : // possible, client code should work purely with logical dimensions.
271 231 : nscoord Width() const { return mWritingMode.IsVertical() ? mBSize : mISize; }
272 231 : nscoord Height() const { return mWritingMode.IsVertical() ? mISize : mBSize; }
273 :
274 : // It's only meaningful to consider "ascent" on the block-start side of the
275 : // frame, so no need to pass a writing mode argument
276 446 : nscoord BlockStartAscent() const
277 : {
278 446 : return mBlockStartAscent;
279 : }
280 :
281 2105 : nscoord& Width() { return mWritingMode.IsVertical() ? mBSize : mISize; }
282 2189 : nscoord& Height() { return mWritingMode.IsVertical() ? mISize : mBSize; }
283 :
284 10 : nsSize PhysicalSize()
285 : {
286 10 : return Size(mWritingMode).GetPhysicalSize(mWritingMode);
287 : }
288 :
289 128 : void SetBlockStartAscent(nscoord aAscent)
290 : {
291 128 : mBlockStartAscent = aAscent;
292 128 : }
293 :
294 : enum { ASK_FOR_BASELINE = nscoord_MAX };
295 :
296 : // Metrics that _exactly_ enclose the text to allow precise MathML placements.
297 : // If the NS_REFLOW_CALC_BOUNDING_METRICS flag is set, then the caller is
298 : // requesting that you also compute additional details about your inner
299 : // bounding box and italic correction. For example, the bounding box of
300 : // msup is the smallest rectangle that _exactly_ encloses both the text
301 : // of the base and the text of the superscript.
302 : nsBoundingMetrics mBoundingMetrics; // [OUT]
303 :
304 : // Carried out block-end margin values. This is the collapsed
305 : // (generational) block-end margin value.
306 : nsCollapsingMargin mCarriedOutBEndMargin;
307 :
308 : // For frames that have content that overflow their content area
309 : // (HasOverflowAreas() is true) these rectangles represent the total
310 : // area of the frame including visible overflow, i.e., don't include
311 : // overflowing content that is hidden. The rects are in the local
312 : // coordinate space of the frame, and should be at least as big as the
313 : // desired size. If there is no content that overflows, then the
314 : // overflow area is identical to the desired size and should be {0, 0,
315 : // width, height}.
316 : nsOverflowAreas mOverflowAreas;
317 :
318 248 : nsRect& VisualOverflow()
319 248 : { return mOverflowAreas.VisualOverflow(); }
320 4 : const nsRect& VisualOverflow() const
321 4 : { return mOverflowAreas.VisualOverflow(); }
322 178 : nsRect& ScrollableOverflow()
323 178 : { return mOverflowAreas.ScrollableOverflow(); }
324 : const nsRect& ScrollableOverflow() const
325 : { return mOverflowAreas.ScrollableOverflow(); }
326 :
327 : // Set all of mOverflowAreas to (0, 0, width, height).
328 : void SetOverflowAreasToDesiredBounds();
329 :
330 : // Union all of mOverflowAreas with (0, 0, width, height).
331 : void UnionOverflowAreasWithDesiredBounds();
332 :
333 1464 : mozilla::WritingMode GetWritingMode() const { return mWritingMode; }
334 :
335 : private:
336 : nscoord mISize, mBSize; // [OUT] desired width and height (border-box)
337 : nscoord mBlockStartAscent; // [OUT] baseline (in Block direction), or ASK_FOR_BASELINE
338 :
339 : public:
340 : uint32_t mFlags;
341 :
342 : private:
343 : mozilla::WritingMode mWritingMode;
344 : };
345 :
346 : } // mozilla namespace
347 :
348 : #endif // mozilla_ReflowOutput_h
|