/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_ */ |