1 /* ***** BEGIN LICENSE BLOCK *****
2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 * The contents of this file are subject to the Mozilla Public License Version
5 * 1.1 (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 * http://www.mozilla.org/MPL/
9 * Software distributed under the License is distributed on an "AS IS" basis,
10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 * for the specific language governing rights and limitations under the
14 * The Original Code is mozilla.org code.
16 * The Initial Developer of the Original Code is
17 * Dainis Jonitis, <Dainis_Jonitis@swh-t.lv>.
18 * Portions created by the Initial Developer are Copyright (C) 2001
19 * the Initial Developer. All Rights Reserved.
23 * Alternatively, the contents of this file may be used under the terms of
24 * either of the GNU General Public License Version 2 or later (the "GPL"),
25 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
26 * in which case the provisions of the GPL or the LGPL are applicable instead
27 * of those above. If you wish to allow use of your version of this file only
28 * under the terms of either the GPL or the LGPL, and not to allow others to
29 * use your version of this file under the terms of the MPL, indicate your
30 * decision by deleting the provisions above and replace them with the notice
31 * and other provisions required by the GPL or the LGPL. If you do not delete
32 * the provisions above, a recipient may use your version of this file under
33 * the terms of any one of the MPL, the GPL or the LGPL.
35 * ***** END LICENSE BLOCK ***** */
42 // Implementation of region.
43 // Region is represented as circular double-linked list of nsRegion::RgnRect structures.
44 // Rectangles in this list do not overlap and are sorted by (y, x) coordinates.
51 friend class nsRegionRectIterator
;
52 friend class RgnRectMemoryAllocator
;
55 // Special version of nsRect structure for speed optimizations in nsRegion code.
56 // Most important functions could be made inline and be sure that passed rectangles
57 // will always be non-empty.
59 // Do not add any new member variables to this structure!
60 // Otherwise it will break casts from nsRect to nsRectFast, which expect data parts to be identical.
61 struct nsRectFast
: public nsRect
63 nsRectFast () {} // No need to call parent constructor to set default values
64 nsRectFast (PRInt32 aX
, PRInt32 aY
, PRInt32 aWidth
, PRInt32 aHeight
) : nsRect (aX
, aY
, aWidth
, aHeight
) {}
65 nsRectFast (const nsRect
& aRect
) : nsRect (aRect
) {}
67 // Override nsRect methods to make them inline. Do not check for emptiness.
68 inline PRBool
Contains (const nsRect
& aRect
) const;
69 inline PRBool
Intersects (const nsRect
& aRect
) const;
70 inline PRBool
IntersectRect (const nsRect
& aRect1
, const nsRect
& aRect2
);
71 inline void UnionRect (const nsRect
& aRect1
, const nsRect
& aRect2
);
75 struct RgnRect
: public nsRectFast
80 RgnRect () {} // No need to call parent constructor to set default values
81 RgnRect (PRInt32 aX
, PRInt32 aY
, PRInt32 aWidth
, PRInt32 aHeight
) : nsRectFast (aX
, aY
, aWidth
, aHeight
) {}
82 RgnRect (const nsRectFast
& aRect
) : nsRectFast (aRect
) {}
84 void* operator new (size_t) CPP_THROW_NEW
;
85 void operator delete (void* aRect
, size_t);
87 RgnRect
& operator = (const RgnRect
& aRect
) // Do not overwrite prev/next pointers
92 height
= aRect
.height
;
99 nsRegion () { Init (); }
100 nsRegion (const nsRect
& aRect
) { Init (); Copy (aRect
); }
101 nsRegion (const nsRegion
& aRegion
) { Init (); Copy (aRegion
); }
102 ~nsRegion () { SetToElements (0); }
103 nsRegion
& operator = (const nsRect
& aRect
) { Copy (aRect
); return *this; }
104 nsRegion
& operator = (const nsRegion
& aRegion
) { Copy (aRegion
); return *this; }
107 nsRegion
& And (const nsRegion
& aRgn1
, const nsRegion
& aRgn2
);
108 nsRegion
& And (const nsRegion
& aRegion
, const nsRect
& aRect
);
109 nsRegion
& And (const nsRect
& aRect
, const nsRegion
& aRegion
)
111 return And (aRegion
, aRect
);
113 nsRegion
& And (const nsRect
& aRect1
, const nsRect
& aRect2
)
117 TmpRect
.IntersectRect (aRect1
, aRect2
);
118 return Copy (TmpRect
);
121 nsRegion
& Or (const nsRegion
& aRgn1
, const nsRegion
& aRgn2
);
122 nsRegion
& Or (const nsRegion
& aRegion
, const nsRect
& aRect
);
123 nsRegion
& Or (const nsRect
& aRect
, const nsRegion
& aRegion
)
125 return Or (aRegion
, aRect
);
127 nsRegion
& Or (const nsRect
& aRect1
, const nsRect
& aRect2
)
130 return Or (*this, aRect2
);
133 nsRegion
& Xor (const nsRegion
& aRgn1
, const nsRegion
& aRgn2
);
134 nsRegion
& Xor (const nsRegion
& aRegion
, const nsRect
& aRect
);
135 nsRegion
& Xor (const nsRect
& aRect
, const nsRegion
& aRegion
)
137 return Xor (aRegion
, aRect
);
139 nsRegion
& Xor (const nsRect
& aRect1
, const nsRect
& aRect2
)
142 return Xor (*this, aRect2
);
145 nsRegion
& Sub (const nsRegion
& aRgn1
, const nsRegion
& aRgn2
);
146 nsRegion
& Sub (const nsRegion
& aRegion
, const nsRect
& aRect
);
147 nsRegion
& Sub (const nsRect
& aRect
, const nsRegion
& aRegion
)
149 return Sub (nsRegion (aRect
), aRegion
);
151 nsRegion
& Sub (const nsRect
& aRect1
, const nsRect
& aRect2
)
154 return Sub (*this, aRect2
);
157 PRBool
Contains (const nsRect
& aRect
) const;
158 PRBool
Intersects (const nsRect
& aRect
) const;
160 void MoveBy (PRInt32 aXOffset
, PRInt32 aYOffset
)
162 MoveBy (nsPoint (aXOffset
, aYOffset
));
164 void MoveBy (nsPoint aPt
);
168 mBoundRect
.SetRect (0, 0, 0, 0);
171 PRBool
IsEmpty () const { return mRectCount
== 0; }
172 PRBool
IsComplex () const { return mRectCount
> 1; }
173 PRBool
IsEqual (const nsRegion
& aRegion
) const;
174 PRUint32
GetNumRects () const { return mRectCount
; }
175 const nsRect
& GetBounds () const { return mBoundRect
; }
178 * Make sure the region has at most aMaxRects by adding area to it
179 * if necessary. The simplified region will be a superset of the
180 * original region. The simplified region's bounding box will be
181 * the same as for the current region.
183 void SimplifyOutward (PRUint32 aMaxRects
);
185 * Make sure the region has at most aMaxRects by removing area from
186 * it if necessary. The simplified region will be a subset of the
189 void SimplifyInward (PRUint32 aMaxRects
);
191 * Efficiently try to remove a rectangle from this region. The actual
192 * area removed could be some sub-area contained by the rectangle
193 * (even possibly nothing at all).
195 * We remove all rectangles that are contained by aRect.
197 void SimpleSubtract (const nsRect
& aRect
);
199 * Efficiently try to remove a region from this region. The actual
200 * area removed could be some sub-area contained by aRegion
201 * (even possibly nothing at all).
203 * We remove all rectangles of this region that are contained by
204 * a rectangle of aRegion.
206 void SimpleSubtract (const nsRegion
& aRegion
);
211 RgnRect mRectListHead
;
212 nsRectFast mBoundRect
;
215 nsRegion
& Copy (const nsRegion
& aRegion
);
216 nsRegion
& Copy (const nsRect
& aRect
);
217 void InsertBefore (RgnRect
* aNewRect
, RgnRect
* aRelativeRect
);
218 void InsertAfter (RgnRect
* aNewRect
, RgnRect
* aRelativeRect
);
219 void SetToElements (PRUint32 aCount
);
220 RgnRect
* Remove (RgnRect
* aRect
);
221 void InsertInPlace (RgnRect
* aRect
, PRBool aOptimizeOnFly
= PR_FALSE
);
222 inline void SaveLinkChain ();
223 inline void RestoreLinkChain ();
225 void SubRegion (const nsRegion
& aRegion
, nsRegion
& aResult
) const;
226 void SubRect (const nsRectFast
& aRect
, nsRegion
& aResult
, nsRegion
& aCompleted
) const;
227 void SubRect (const nsRectFast
& aRect
, nsRegion
& aResult
) const
228 { SubRect (aRect
, aResult
, aResult
); }
229 void Merge (const nsRegion
& aRgn1
, const nsRegion
& aRgn2
);
230 void MoveInto (nsRegion
& aDestRegion
, const RgnRect
* aStartRect
);
231 void MoveInto (nsRegion
& aDestRegion
)
232 { MoveInto (aDestRegion
, mRectListHead
.next
); }
237 // Allow read-only access to region rectangles by iterating the list
239 class NS_GFX nsRegionRectIterator
241 const nsRegion
* mRegion
;
242 const nsRegion::RgnRect
* mCurPtr
;
245 nsRegionRectIterator (const nsRegion
& aRegion
)
248 mCurPtr
= &aRegion
.mRectListHead
;
251 const nsRect
* Next ()
253 mCurPtr
= mCurPtr
->next
;
254 return (mCurPtr
!= &mRegion
->mRectListHead
) ? mCurPtr
: nsnull
;
257 const nsRect
* Prev ()
259 mCurPtr
= mCurPtr
->prev
;
260 return (mCurPtr
!= &mRegion
->mRectListHead
) ? mCurPtr
: nsnull
;
265 mCurPtr
= &mRegion
->mRectListHead
;