Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/layout/painting/DisplayItemClip.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
#ifndef DISPLAYITEMCLIP_H_
8
#define DISPLAYITEMCLIP_H_
9
10
#include "mozilla/RefPtr.h"
11
#include "nsRect.h"
12
#include "nsTArray.h"
13
#include "nsStyleConsts.h"
14
15
class gfxContext;
16
class nsPresContext;
17
class nsRegion;
18
19
namespace mozilla {
20
namespace gfx {
21
class DrawTarget;
22
class Path;
23
} // namespace gfx
24
namespace layers {
25
class StackingContextHelper;
26
} // namespace layers
27
namespace wr {
28
struct ComplexClipRegion;
29
} // namepsace wr
30
} // namespace mozilla
31
32
namespace mozilla {
33
34
/**
35
 * An DisplayItemClip represents the intersection of an optional rectangle
36
 * with a list of rounded rectangles (which is often empty), all in appunits.
37
 * It can represent everything CSS clipping can do to an element (except for
38
 * SVG clip-path), including no clipping at all.
39
 */
40
class DisplayItemClip
41
{
42
  typedef mozilla::gfx::Color Color;
43
  typedef mozilla::gfx::DrawTarget DrawTarget;
44
  typedef mozilla::gfx::Path Path;
45
46
public:
47
  struct RoundedRect
48
  {
49
    nsRect mRect;
50
    // Indices into mRadii are the HalfCorner values in gfx/2d/Types.h
51
    nscoord mRadii[8];
52
53
    RoundedRect operator+(const nsPoint& aOffset) const
54
0
    {
55
0
      RoundedRect r = *this;
56
0
      r.mRect += aOffset;
57
0
      return r;
58
0
    }
59
    bool operator==(const RoundedRect& aOther) const
60
    {
61
      if (!mRect.IsEqualInterior(aOther.mRect)) {
62
        return false;
63
      }
64
65
      NS_FOR_CSS_HALF_CORNERS(corner)
66
      {
67
        if (mRadii[corner] != aOther.mRadii[corner]) {
68
          return false;
69
        }
70
      }
71
      return true;
72
    }
73
    bool operator!=(const RoundedRect& aOther) const
74
0
    {
75
0
      return !(*this == aOther);
76
0
    }
77
  };
78
79
  // Constructs a DisplayItemClip that does no clipping at all.
80
  DisplayItemClip()
81
    : mHaveClipRect(false)
82
  {
83
  }
84
85
  void SetTo(const nsRect& aRect);
86
  void SetTo(const nsRect& aRect, const nscoord* aRadii);
87
  void SetTo(const nsRect& aRect,
88
             const nsRect& aRoundedRect,
89
             const nscoord* aRadii);
90
  void IntersectWith(const DisplayItemClip& aOther);
91
92
  // Apply this |DisplayItemClip| to the given gfxContext.  Any saving of state
93
  // or clearing of other clips must be done by the caller.
94
  // See aBegin/aEnd note on ApplyRoundedRectsTo.
95
  void ApplyTo(gfxContext* aContext, int32_t A2D) const;
96
97
  void ApplyRectTo(gfxContext* aContext, int32_t A2D) const;
98
  // Applies the rounded rects in this Clip to aContext
99
  // Will only apply rounded rects from aBegin (inclusive) to aEnd
100
  // (exclusive) or the number of rounded rects, whichever is smaller.
101
  void ApplyRoundedRectClipsTo(gfxContext* aContext,
102
                               int32_t A2DPRInt32,
103
                               uint32_t aBegin,
104
                               uint32_t aEnd) const;
105
106
  // Draw (fill) the rounded rects in this clip to aContext
107
  void FillIntersectionOfRoundedRectClips(gfxContext* aContext,
108
                                          const Color& aColor,
109
                                          int32_t aAppUnitsPerDevPixel) const;
110
  // 'Draw' (create as a path, does not stroke or fill) aRoundRect to aContext
111
  already_AddRefed<Path> MakeRoundedRectPath(
112
    DrawTarget& aDrawTarget,
113
    int32_t A2D,
114
    const RoundedRect& aRoundRect) const;
115
116
  // Returns true if the intersection of aRect and this clip region is
117
  // non-empty. This is precise for DisplayItemClips with at most one
118
  // rounded rectangle. When multiple rounded rectangles are present, we just
119
  // check that the rectangle intersects all of them (but possibly in different
120
  // places). So it may return true when the correct answer is false.
121
  bool MayIntersect(const nsRect& aRect) const;
122
123
  // Return a rectangle contained in the intersection of aRect with this
124
  // clip region. Tries to return the largest possible rectangle, but may
125
  // not succeed.
126
  nsRect ApproximateIntersectInward(const nsRect& aRect) const;
127
128
  /*
129
   * Computes a region which contains the clipped area of this DisplayItemClip,
130
   * or if aOldClip is non-null, the union of the clipped area of this
131
   * DisplayItemClip with the clipped area of aOldClip translated by aShift.
132
   * The result is stored in aCombined. If the result would be infinite
133
   * (because one or both of the clips does no clipping), returns false.
134
   */
135
  bool ComputeRegionInClips(const DisplayItemClip* aOldClip,
136
                            const nsPoint& aShift,
137
                            nsRegion* aCombined) const;
138
139
  // Returns false if aRect is definitely not clipped by a rounded corner in
140
  // this clip. Returns true if aRect is clipped by a rounded corner in this
141
  // clip or it can not be quickly determined that it is not clipped by a
142
  // rounded corner in this clip.
143
  bool IsRectClippedByRoundedCorner(const nsRect& aRect) const;
144
145
  // Returns false if aRect is definitely not clipped by anything in this clip.
146
  // Fast but not necessarily accurate.
147
  bool IsRectAffectedByClip(const nsRect& aRect) const;
148
  bool IsRectAffectedByClip(const nsIntRect& aRect,
149
                            float aXScale,
150
                            float aYScale,
151
                            int32_t A2D) const;
152
153
  // Intersection of all rects in this clip ignoring any rounded corners.
154
  nsRect NonRoundedIntersection() const;
155
156
  // Intersect the given rects with all rects in this clip, ignoring any
157
  // rounded corners.
158
  nsRect ApplyNonRoundedIntersection(const nsRect& aRect) const;
159
160
  // Gets rid of any rounded corners in this clip.
161
  void RemoveRoundedCorners();
162
163
  // Adds the difference between Intersect(*this + aPoint, aBounds) and
164
  // Intersect(aOther, aOtherBounds) to aDifference (or a bounding-box thereof).
165
  void AddOffsetAndComputeDifference(const nsPoint& aPoint,
166
                                     const nsRect& aBounds,
167
                                     const DisplayItemClip& aOther,
168
                                     const nsRect& aOtherBounds,
169
                                     nsRegion* aDifference);
170
171
  bool operator==(const DisplayItemClip& aOther) const
172
  {
173
    return mHaveClipRect == aOther.mHaveClipRect &&
174
           (!mHaveClipRect || mClipRect.IsEqualInterior(aOther.mClipRect)) &&
175
           mRoundedClipRects == aOther.mRoundedClipRects;
176
  }
177
  bool operator!=(const DisplayItemClip& aOther) const
178
  {
179
    return !(*this == aOther);
180
  }
181
182
  bool HasClip() const { return mHaveClipRect; }
183
  const nsRect& GetClipRect() const
184
  {
185
    NS_ASSERTION(HasClip(), "No clip rect!");
186
    return mClipRect;
187
  }
188
189
  void MoveBy(const nsPoint& aPoint);
190
191
  nsCString ToString() const;
192
193
  uint32_t GetRoundedRectCount() const { return mRoundedClipRects.Length(); }
194
  void AppendRoundedRects(nsTArray<RoundedRect>* aArray) const;
195
196
  void ToComplexClipRegions(int32_t aAppUnitsPerDevPixel,
197
                            const layers::StackingContextHelper& aSc,
198
                            nsTArray<wr::ComplexClipRegion>& aOutArray) const;
199
200
  static const DisplayItemClip& NoClip();
201
202
  static void Shutdown();
203
204
private:
205
  nsRect mClipRect;
206
  nsTArray<RoundedRect> mRoundedClipRects;
207
  // If mHaveClipRect is false then this object represents no clipping at all
208
  // and mRoundedClipRects must be empty.
209
  bool mHaveClipRect;
210
};
211
212
} // namespace mozilla
213
214
#endif /* DISPLAYITEMCLIP_H_ */