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/. */
7 #ifndef DISPLAYITEMCLIP_H_
8 #define DISPLAYITEMCLIP_H_
10 #include "mozilla/RefPtr.h"
13 #include "nsStyleConsts.h"
25 class StackingContextHelper
;
28 struct ComplexClipRegion
;
30 } // namespace mozilla
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.
40 class DisplayItemClip
{
41 typedef mozilla::gfx::Color Color
;
42 typedef mozilla::gfx::DrawTarget DrawTarget
;
43 typedef mozilla::gfx::Path Path
;
48 // Indices into mRadii are the HalfCorner values in gfx/2d/Types.h
51 RoundedRect
operator+(const nsPoint
& aOffset
) const {
52 RoundedRect r
= *this;
56 bool operator==(const RoundedRect
& aOther
) const {
57 if (!mRect
.IsEqualInterior(aOther
.mRect
)) {
61 NS_FOR_CSS_HALF_CORNERS(corner
) {
62 if (mRadii
[corner
] != aOther
.mRadii
[corner
]) {
68 bool operator!=(const RoundedRect
& aOther
) const {
69 return !(*this == aOther
);
73 // Constructs a DisplayItemClip that does no clipping at all.
74 DisplayItemClip() : mHaveClipRect(false) {}
76 void SetTo(const nsRect
& aRect
);
77 void SetTo(const nsRect
& aRect
, const nscoord
* aRadii
);
78 void SetTo(const nsRect
& aRect
, const nsRect
& aRoundedRect
,
79 const nscoord
* aRadii
);
80 void IntersectWith(const DisplayItemClip
& aOther
);
82 // Apply this |DisplayItemClip| to the given gfxContext. Any saving of state
83 // or clearing of other clips must be done by the caller.
84 // See aBegin/aEnd note on ApplyRoundedRectsTo.
85 void ApplyTo(gfxContext
* aContext
, int32_t A2D
) const;
87 void ApplyRectTo(gfxContext
* aContext
, int32_t A2D
) const;
88 // Applies the rounded rects in this Clip to aContext
89 // Will only apply rounded rects from aBegin (inclusive) to aEnd
90 // (exclusive) or the number of rounded rects, whichever is smaller.
91 void ApplyRoundedRectClipsTo(gfxContext
* aContext
, int32_t A2DPRInt32
,
92 uint32_t aBegin
, uint32_t aEnd
) const;
94 // Draw (fill) the rounded rects in this clip to aContext
95 void FillIntersectionOfRoundedRectClips(gfxContext
* aContext
,
97 int32_t aAppUnitsPerDevPixel
) const;
98 // 'Draw' (create as a path, does not stroke or fill) aRoundRect to aContext
99 already_AddRefed
<Path
> MakeRoundedRectPath(
100 DrawTarget
& aDrawTarget
, int32_t A2D
,
101 const RoundedRect
& aRoundRect
) const;
103 // Returns true if the intersection of aRect and this clip region is
104 // non-empty. This is precise for DisplayItemClips with at most one
105 // rounded rectangle. When multiple rounded rectangles are present, we just
106 // check that the rectangle intersects all of them (but possibly in different
107 // places). So it may return true when the correct answer is false.
108 bool MayIntersect(const nsRect
& aRect
) const;
110 // Return a rectangle contained in the intersection of aRect with this
111 // clip region. Tries to return the largest possible rectangle, but may
113 nsRect
ApproximateIntersectInward(const nsRect
& aRect
) const;
116 * Computes a region which contains the clipped area of this DisplayItemClip,
117 * or if aOldClip is non-null, the union of the clipped area of this
118 * DisplayItemClip with the clipped area of aOldClip translated by aShift.
119 * The result is stored in aCombined. If the result would be infinite
120 * (because one or both of the clips does no clipping), returns false.
122 bool ComputeRegionInClips(const DisplayItemClip
* aOldClip
,
123 const nsPoint
& aShift
, nsRegion
* aCombined
) const;
125 // Returns false if aRect is definitely not clipped by a rounded corner in
126 // this clip. Returns true if aRect is clipped by a rounded corner in this
127 // clip or it can not be quickly determined that it is not clipped by a
128 // rounded corner in this clip.
129 bool IsRectClippedByRoundedCorner(const nsRect
& aRect
) const;
131 // Returns false if aRect is definitely not clipped by anything in this clip.
132 // Fast but not necessarily accurate.
133 bool IsRectAffectedByClip(const nsRect
& aRect
) const;
134 bool IsRectAffectedByClip(const nsIntRect
& aRect
, float aXScale
,
135 float aYScale
, int32_t A2D
) const;
137 // Intersection of all rects in this clip ignoring any rounded corners.
138 nsRect
NonRoundedIntersection() const;
140 // Intersect the given rects with all rects in this clip, ignoring any
142 nsRect
ApplyNonRoundedIntersection(const nsRect
& aRect
) const;
144 // Gets rid of any rounded corners in this clip.
145 void RemoveRoundedCorners();
147 // Adds the difference between Intersect(*this + aPoint, aBounds) and
148 // Intersect(aOther, aOtherBounds) to aDifference (or a bounding-box thereof).
149 void AddOffsetAndComputeDifference(const nsPoint
& aPoint
,
150 const nsRect
& aBounds
,
151 const DisplayItemClip
& aOther
,
152 const nsRect
& aOtherBounds
,
153 nsRegion
* aDifference
);
155 bool operator==(const DisplayItemClip
& aOther
) const {
156 return mHaveClipRect
== aOther
.mHaveClipRect
&&
157 (!mHaveClipRect
|| mClipRect
.IsEqualInterior(aOther
.mClipRect
)) &&
158 mRoundedClipRects
== aOther
.mRoundedClipRects
;
160 bool operator!=(const DisplayItemClip
& aOther
) const {
161 return !(*this == aOther
);
164 bool HasClip() const { return mHaveClipRect
; }
165 const nsRect
& GetClipRect() const {
166 NS_ASSERTION(HasClip(), "No clip rect!");
170 void MoveBy(const nsPoint
& aPoint
);
172 nsCString
ToString() const;
174 uint32_t GetRoundedRectCount() const { return mRoundedClipRects
.Length(); }
175 void AppendRoundedRects(nsTArray
<RoundedRect
>* aArray
) const;
177 void ToComplexClipRegions(int32_t aAppUnitsPerDevPixel
,
178 nsTArray
<wr::ComplexClipRegion
>& aOutArray
) const;
180 static const DisplayItemClip
& NoClip();
182 static void Shutdown();
186 nsTArray
<RoundedRect
> mRoundedClipRects
;
187 // If mHaveClipRect is false then this object represents no clipping at all
188 // and mRoundedClipRects must be empty.
192 } // namespace mozilla
194 #endif /* DISPLAYITEMCLIP_H_ */