Line data Source code
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/. */
6 :
7 : /* struct containing the output from nsIFrame::Reflow */
8 :
9 : #ifndef mozilla_ReflowOutput_h
10 : #define mozilla_ReflowOutput_h
11 :
12 : #include "mozilla/WritingModes.h"
13 : #include "nsBoundingMetrics.h"
14 : #include "nsRect.h"
15 :
16 : //----------------------------------------------------------------------
17 :
18 : namespace mozilla {
19 : struct ReflowInput;
20 : } // namespace mozilla
21 :
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 };
32 :
33 : #define NS_FOR_FRAME_OVERFLOW_TYPES(var_) \
34 : for (nsOverflowType var_ = nsOverflowType(0); var_ < 2; \
35 : var_ = nsOverflowType(var_ + 1))
36 :
37 2941 : struct nsOverflowAreas {
38 : private:
39 : nsRect mRects[2];
40 : public:
41 3623 : nsRect& Overflow(size_t aIndex) {
42 3623 : NS_ASSERTION(aIndex < 2, "index out of range");
43 3623 : return mRects[aIndex];
44 : }
45 0 : const nsRect& Overflow(size_t aIndex) const {
46 0 : NS_ASSERTION(aIndex < 2, "index out of range");
47 112 : return mRects[aIndex];
48 : }
49 :
50 0 : nsRect& VisualOverflow() { return mRects[eVisualOverflow]; }
51 753 : const nsRect& VisualOverflow() const { return mRects[eVisualOverflow]; }
52 :
53 0 : nsRect& ScrollableOverflow() { return mRects[eScrollableOverflow]; }
54 0 : const nsRect& ScrollableOverflow() const { return mRects[eScrollableOverflow]; }
55 :
56 0 : nsOverflowAreas() {
57 : // default-initializes to zero due to nsRect's default constructor
58 586 : }
59 :
60 1744 : nsOverflowAreas(const nsRect& aVisualOverflow,
61 : const nsRect& aScrollableOverflow)
62 1744 : {
63 0 : mRects[eVisualOverflow] = aVisualOverflow;
64 1744 : mRects[eScrollableOverflow] = aScrollableOverflow;
65 0 : }
66 :
67 0 : nsOverflowAreas(const nsOverflowAreas& aOther) {
68 0 : *this = aOther;
69 667 : }
70 :
71 0 : nsOverflowAreas& operator=(const nsOverflowAreas& aOther) {
72 0 : mRects[0] = aOther.mRects[0];
73 920 : mRects[1] = aOther.mRects[1];
74 0 : return *this;
75 : }
76 :
77 0 : bool operator==(const nsOverflowAreas& aOther) const {
78 : // Scrollable overflow is a point-set rectangle and visual overflow
79 : // is a pixel-set rectangle.
80 0 : return VisualOverflow().IsEqualInterior(aOther.VisualOverflow()) &&
81 1457 : ScrollableOverflow().IsEqualEdges(aOther.ScrollableOverflow());
82 : }
83 :
84 0 : bool operator!=(const nsOverflowAreas& aOther) const {
85 746 : return !(*this == aOther);
86 : }
87 :
88 : nsOverflowAreas operator+(const nsPoint& aPoint) const {
89 558 : nsOverflowAreas result(*this);
90 558 : result += aPoint;
91 : return result;
92 : }
93 :
94 558 : nsOverflowAreas& operator+=(const nsPoint& aPoint) {
95 1116 : mRects[0] += aPoint;
96 1116 : mRects[1] += aPoint;
97 0 : return *this;
98 : }
99 :
100 0 : void Clear() {
101 148 : mRects[0].SetRect(0, 0, 0, 0);
102 148 : mRects[1].SetRect(0, 0, 0, 0);
103 0 : }
104 :
105 : // Mutates |this| by unioning both overflow areas with |aOther|.
106 : void UnionWith(const nsOverflowAreas& aOther);
107 :
108 : // Mutates |this| by unioning both overflow areas with |aRect|.
109 : void UnionAllWith(const nsRect& aRect);
110 :
111 : // Mutates |this| by setting both overflow areas to |aRect|.
112 : void SetAllTo(const nsRect& aRect);
113 : };
114 :
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
128 :
129 : public:
130 : nsCollapsingMargin()
131 355 : : mMostPos(0),
132 355 : mMostNeg(0)
133 : {
134 : }
135 :
136 : nsCollapsingMargin(const nsCollapsingMargin& aOther)
137 12 : : mMostPos(aOther.mMostPos),
138 12 : mMostNeg(aOther.mMostNeg)
139 : {
140 : }
141 :
142 5 : bool operator==(const nsCollapsingMargin& aOther)
143 : {
144 7 : return mMostPos == aOther.mMostPos &&
145 0 : mMostNeg == aOther.mMostNeg;
146 : }
147 :
148 0 : bool operator!=(const nsCollapsingMargin& aOther)
149 : {
150 5 : return !(*this == aOther);
151 : }
152 :
153 : nsCollapsingMargin& operator=(const nsCollapsingMargin& aOther)
154 : {
155 27 : mMostPos = aOther.mMostPos;
156 27 : mMostNeg = aOther.mMostNeg;
157 : return *this;
158 : }
159 :
160 10 : void Include(nscoord aCoord)
161 : {
162 10 : if (aCoord > mMostPos)
163 0 : mMostPos = aCoord;
164 0 : else if (aCoord < mMostNeg)
165 0 : mMostNeg = aCoord;
166 0 : }
167 :
168 0 : void Include(const nsCollapsingMargin& aOther)
169 : {
170 5 : if (aOther.mMostPos > mMostPos)
171 0 : mMostPos = aOther.mMostPos;
172 5 : if (aOther.mMostNeg < mMostNeg)
173 0 : mMostNeg = aOther.mMostNeg;
174 0 : }
175 :
176 : void Zero()
177 : {
178 82 : mMostPos = 0;
179 82 : mMostNeg = 0;
180 : }
181 :
182 0 : bool IsZero() const
183 : {
184 5 : return (mMostPos == 0) && (mMostNeg == 0);
185 : }
186 :
187 : nscoord get() const
188 : {
189 86 : return mMostPos + mMostNeg;
190 : }
191 : };
192 :
193 : namespace mozilla {
194 :
195 : /**
196 : * Reflow metrics used to return the frame's desired size and alignment
197 : * information.
198 : *
199 : * @see #Reflow()
200 : */
201 293 : class ReflowOutput {
202 : public:
203 293 : explicit ReflowOutput(mozilla::WritingMode aWritingMode)
204 0 : : mISize(0)
205 : , mBSize(0)
206 : , mBlockStartAscent(ASK_FOR_BASELINE)
207 586 : , mWritingMode(aWritingMode)
208 : {
209 293 : }
210 :
211 : explicit ReflowOutput(const ReflowInput& aReflowInput);
212 :
213 : // ISize and BSize are logical-coordinate dimensions:
214 : // ISize is the size in the writing mode's inline direction (which equates to
215 : // width in horizontal writing modes, height in vertical ones), and BSize is
216 : // the size in the block-progression direction.
217 : nscoord ISize(mozilla::WritingMode aWritingMode) const {
218 : NS_ASSERTION(!aWritingMode.IsOrthogonalTo(mWritingMode),
219 : "mismatched writing mode");
220 : return mISize;
221 : }
222 0 : nscoord BSize(mozilla::WritingMode aWritingMode) const {
223 0 : NS_ASSERTION(!aWritingMode.IsOrthogonalTo(mWritingMode),
224 : "mismatched writing mode");
225 0 : return mBSize;
226 : }
227 157 : mozilla::LogicalSize Size(mozilla::WritingMode aWritingMode) const {
228 157 : NS_ASSERTION(!aWritingMode.IsOrthogonalTo(mWritingMode),
229 : "mismatched writing mode");
230 314 : return mozilla::LogicalSize(aWritingMode, mISize, mBSize);
231 : }
232 :
233 286 : nscoord& ISize(mozilla::WritingMode aWritingMode) {
234 0 : NS_ASSERTION(!aWritingMode.IsOrthogonalTo(mWritingMode),
235 : "mismatched writing mode");
236 0 : return mISize;
237 : }
238 337 : nscoord& BSize(mozilla::WritingMode aWritingMode) {
239 0 : NS_ASSERTION(!aWritingMode.IsOrthogonalTo(mWritingMode),
240 : "mismatched writing mode");
241 337 : return mBSize;
242 : }
243 :
244 : // Set inline and block size from a LogicalSize, converting to our
245 : // writing mode as necessary.
246 161 : void SetSize(mozilla::WritingMode aWM, mozilla::LogicalSize aSize)
247 : {
248 0 : mozilla::LogicalSize convertedSize = aSize.ConvertTo(mWritingMode, aWM);
249 161 : mBSize = convertedSize.BSize(mWritingMode);
250 0 : mISize = convertedSize.ISize(mWritingMode);
251 161 : }
252 :
253 : // Set both inline and block size to zero -- no need for a writing mode!
254 : void ClearSize()
255 : {
256 123 : mISize = mBSize = 0;
257 : }
258 :
259 : // Width and Height are physical dimensions, independent of writing mode.
260 : // Accessing these is slightly more expensive than accessing the logical
261 : // dimensions (once vertical writing mode support is enabled); as far as
262 : // possible, client code should work purely with logical dimensions.
263 224 : nscoord Width() const { return mWritingMode.IsVertical() ? mBSize : mISize; }
264 224 : nscoord Height() const { return mWritingMode.IsVertical() ? mISize : mBSize; }
265 :
266 : // It's only meaningful to consider "ascent" on the block-start side of the
267 : // frame, so no need to pass a writing mode argument
268 : nscoord BlockStartAscent() const
269 : {
270 : return mBlockStartAscent;
271 : }
272 :
273 0 : nscoord& Width() { return mWritingMode.IsVertical() ? mBSize : mISize; }
274 1930 : nscoord& Height() { return mWritingMode.IsVertical() ? mISize : mBSize; }
275 :
276 5 : nsSize PhysicalSize()
277 : {
278 5 : return Size(mWritingMode).GetPhysicalSize(mWritingMode);
279 : }
280 :
281 : void SetBlockStartAscent(nscoord aAscent)
282 : {
283 0 : mBlockStartAscent = aAscent;
284 : }
285 :
286 : enum { ASK_FOR_BASELINE = nscoord_MAX };
287 :
288 : // Metrics that _exactly_ enclose the text to allow precise MathML placements.
289 : nsBoundingMetrics mBoundingMetrics; // [OUT]
290 :
291 : // Carried out block-end margin values. This is the collapsed
292 : // (generational) block-end margin value.
293 : nsCollapsingMargin mCarriedOutBEndMargin;
294 :
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;
304 :
305 : nsRect& VisualOverflow()
306 114 : { return mOverflowAreas.VisualOverflow(); }
307 : const nsRect& VisualOverflow() const
308 6 : { return mOverflowAreas.VisualOverflow(); }
309 : nsRect& ScrollableOverflow()
310 99 : { return mOverflowAreas.ScrollableOverflow(); }
311 : const nsRect& ScrollableOverflow() const
312 : { return mOverflowAreas.ScrollableOverflow(); }
313 :
314 : // Set all of mOverflowAreas to (0, 0, width, height).
315 : void SetOverflowAreasToDesiredBounds();
316 :
317 : // Union all of mOverflowAreas with (0, 0, width, height).
318 : void UnionOverflowAreasWithDesiredBounds();
319 :
320 : mozilla::WritingMode GetWritingMode() const { return mWritingMode; }
321 :
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
325 : mozilla::WritingMode mWritingMode;
326 : };
327 :
328 : } // mozilla namespace
329 :
330 : #endif // mozilla_ReflowOutput_h
|