Coverage Report

Created: 2018-09-25 14:53

/work/obj-fuzz/dist/include/mozilla/ReflowOutput.h
Line
Count
Source (jump to first uncovered line)
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
0
  for (nsOverflowType var_ = nsOverflowType(0); var_ < 2;                     \
35
0
       var_ = nsOverflowType(var_ + 1))
36
37
struct nsOverflowAreas {
38
private:
39
  nsRect mRects[2];
40
public:
41
0
  nsRect& Overflow(size_t aIndex) {
42
0
    NS_ASSERTION(aIndex < 2, "index out of range");
43
0
    return mRects[aIndex];
44
0
  }
45
0
  const nsRect& Overflow(size_t aIndex) const {
46
0
    NS_ASSERTION(aIndex < 2, "index out of range");
47
0
    return mRects[aIndex];
48
0
  }
49
50
0
  nsRect& VisualOverflow() { return mRects[eVisualOverflow]; }
51
0
  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
0
    // default-initializes to zero due to nsRect's default constructor
58
0
  }
59
60
  nsOverflowAreas(const nsRect& aVisualOverflow,
61
                  const nsRect& aScrollableOverflow)
62
0
  {
63
0
    mRects[eVisualOverflow] = aVisualOverflow;
64
0
    mRects[eScrollableOverflow] = aScrollableOverflow;
65
0
  }
66
67
0
  nsOverflowAreas(const nsOverflowAreas& aOther) {
68
0
    *this = aOther;
69
0
  }
70
71
0
  nsOverflowAreas& operator=(const nsOverflowAreas& aOther) {
72
0
    mRects[0] = aOther.mRects[0];
73
0
    mRects[1] = aOther.mRects[1];
74
0
    return *this;
75
0
  }
76
77
0
  bool operator==(const nsOverflowAreas& aOther) const {
78
0
    // Scrollable overflow is a point-set rectangle and visual overflow
79
0
    // is a pixel-set rectangle.
80
0
    return VisualOverflow().IsEqualInterior(aOther.VisualOverflow()) &&
81
0
           ScrollableOverflow().IsEqualEdges(aOther.ScrollableOverflow());
82
0
  }
83
84
0
  bool operator!=(const nsOverflowAreas& aOther) const {
85
0
    return !(*this == aOther);
86
0
  }
87
88
0
  nsOverflowAreas operator+(const nsPoint& aPoint) const {
89
0
    nsOverflowAreas result(*this);
90
0
    result += aPoint;
91
0
    return result;
92
0
  }
93
94
0
  nsOverflowAreas& operator+=(const nsPoint& aPoint) {
95
0
    mRects[0] += aPoint;
96
0
    mRects[1] += aPoint;
97
0
    return *this;
98
0
  }
99
100
0
  void Clear() {
101
0
    mRects[0].SetRect(0, 0, 0, 0);
102
0
    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
        : mMostPos(0),
132
          mMostNeg(0)
133
0
      {
134
0
      }
135
136
    nsCollapsingMargin(const nsCollapsingMargin& aOther)
137
        : mMostPos(aOther.mMostPos),
138
          mMostNeg(aOther.mMostNeg)
139
0
      {
140
0
      }
141
142
    bool operator==(const nsCollapsingMargin& aOther)
143
0
      {
144
0
        return mMostPos == aOther.mMostPos &&
145
0
          mMostNeg == aOther.mMostNeg;
146
0
      }
147
148
    bool operator!=(const nsCollapsingMargin& aOther)
149
0
      {
150
0
        return !(*this == aOther);
151
0
      }
152
153
    nsCollapsingMargin& operator=(const nsCollapsingMargin& aOther)
154
0
      {
155
0
        mMostPos = aOther.mMostPos;
156
0
        mMostNeg = aOther.mMostNeg;
157
0
        return *this;
158
0
      }
159
160
    void Include(nscoord aCoord)
161
0
      {
162
0
        if (aCoord > mMostPos)
163
0
          mMostPos = aCoord;
164
0
        else if (aCoord < mMostNeg)
165
0
          mMostNeg = aCoord;
166
0
      }
167
168
    void Include(const nsCollapsingMargin& aOther)
169
0
      {
170
0
        if (aOther.mMostPos > mMostPos)
171
0
          mMostPos = aOther.mMostPos;
172
0
        if (aOther.mMostNeg < mMostNeg)
173
0
          mMostNeg = aOther.mMostNeg;
174
0
      }
175
176
    void Zero()
177
0
      {
178
0
        mMostPos = 0;
179
0
        mMostNeg = 0;
180
0
      }
181
182
    bool IsZero() const
183
0
      {
184
0
        return (mMostPos == 0) && (mMostNeg == 0);
185
0
      }
186
187
    nscoord get() const
188
0
      {
189
0
        return mMostPos + mMostNeg;
190
0
      }
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
class ReflowOutput {
202
public:
203
  explicit ReflowOutput(mozilla::WritingMode aWritingMode)
204
    : mISize(0)
205
    , mBSize(0)
206
    , mBlockStartAscent(ASK_FOR_BASELINE)
207
    , mWritingMode(aWritingMode)
208
0
  {
209
0
  }
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
0
  nscoord ISize(mozilla::WritingMode aWritingMode) const {
218
0
    NS_ASSERTION(!aWritingMode.IsOrthogonalTo(mWritingMode),
219
0
                 "mismatched writing mode");
220
0
    return mISize;
221
0
  }
222
0
  nscoord BSize(mozilla::WritingMode aWritingMode) const {
223
0
    NS_ASSERTION(!aWritingMode.IsOrthogonalTo(mWritingMode),
224
0
                 "mismatched writing mode");
225
0
    return mBSize;
226
0
  }
227
0
  mozilla::LogicalSize Size(mozilla::WritingMode aWritingMode) const {
228
0
    NS_ASSERTION(!aWritingMode.IsOrthogonalTo(mWritingMode),
229
0
                 "mismatched writing mode");
230
0
    return mozilla::LogicalSize(aWritingMode, mISize, mBSize);
231
0
  }
232
233
0
  nscoord& ISize(mozilla::WritingMode aWritingMode) {
234
0
    NS_ASSERTION(!aWritingMode.IsOrthogonalTo(mWritingMode),
235
0
                 "mismatched writing mode");
236
0
    return mISize;
237
0
  }
238
0
  nscoord& BSize(mozilla::WritingMode aWritingMode) {
239
0
    NS_ASSERTION(!aWritingMode.IsOrthogonalTo(mWritingMode),
240
0
                 "mismatched writing mode");
241
0
    return mBSize;
242
0
  }
243
244
  // Set inline and block size from a LogicalSize, converting to our
245
  // writing mode as necessary.
246
  void SetSize(mozilla::WritingMode aWM, mozilla::LogicalSize aSize)
247
0
  {
248
0
    mozilla::LogicalSize convertedSize = aSize.ConvertTo(mWritingMode, aWM);
249
0
    mBSize = convertedSize.BSize(mWritingMode);
250
0
    mISize = convertedSize.ISize(mWritingMode);
251
0
  }
252
253
  // Set both inline and block size to zero -- no need for a writing mode!
254
  void ClearSize()
255
0
  {
256
0
    mISize = mBSize = 0;
257
0
  }
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
0
  nscoord Width() const { return mWritingMode.IsVertical() ? mBSize : mISize; }
264
0
  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
0
  {
270
0
    return mBlockStartAscent;
271
0
  }
272
273
0
  nscoord& Width() { return mWritingMode.IsVertical() ? mBSize : mISize; }
274
0
  nscoord& Height() { return mWritingMode.IsVertical() ? mISize : mBSize; }
275
276
  nsSize PhysicalSize()
277
0
  {
278
0
    return Size(mWritingMode).GetPhysicalSize(mWritingMode);
279
0
  }
280
281
  void SetBlockStartAscent(nscoord aAscent)
282
0
  {
283
0
    mBlockStartAscent = aAscent;
284
0
  }
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
0
    { return mOverflowAreas.VisualOverflow(); }
307
  const nsRect& VisualOverflow() const
308
0
    { return mOverflowAreas.VisualOverflow(); }
309
  nsRect& ScrollableOverflow()
310
0
    { return mOverflowAreas.ScrollableOverflow(); }
311
  const nsRect& ScrollableOverflow() const
312
0
    { 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
0
  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