1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
15 * The Original Code is mozilla.org code.
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 1998
20 * the Initial Developer. All Rights Reserved.
24 * Alternatively, the contents of this file may be used under the terms of
25 * either of the GNU General Public License Version 2 or later (the "GPL"),
26 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
36 * ***** END LICENSE BLOCK ***** */
48 #include "nsTraceRefcnt.h"
52 struct NS_GFX nsRect
{
54 nscoord width
, height
;
57 nsRect() : x(0), y(0), width(0), height(0) {
58 MOZ_COUNT_CTOR(nsRect
);
60 nsRect(const nsRect
& aRect
) {
61 MOZ_COUNT_CTOR(nsRect
);
64 nsRect(const nsPoint
& aOrigin
, const nsSize
&aSize
) {
65 MOZ_COUNT_CTOR(nsRect
);
66 x
= aOrigin
.x
; y
= aOrigin
.y
;
67 width
= aSize
.width
; height
= aSize
.height
;
69 nsRect(nscoord aX
, nscoord aY
, nscoord aWidth
, nscoord aHeight
) {
70 MOZ_COUNT_CTOR(nsRect
);
71 x
= aX
; y
= aY
; width
= aWidth
; height
= aHeight
;
72 VERIFY_COORD(x
); VERIFY_COORD(y
); VERIFY_COORD(width
); VERIFY_COORD(height
);
75 #ifdef NS_BUILD_REFCNT_LOGGING
77 MOZ_COUNT_DTOR(nsRect
);
81 // Emptiness. An empty rect is one that has no area, i.e. its height or width
83 PRBool
IsEmpty() const {
84 return (PRBool
) ((height
<= 0) || (width
<= 0));
86 void Empty() {width
= height
= 0;}
89 PRBool
Contains(const nsRect
& aRect
) const;
90 PRBool
Contains(nscoord aX
, nscoord aY
) const;
91 PRBool
Contains(const nsPoint
& aPoint
) const {return Contains(aPoint
.x
, aPoint
.y
);}
93 // Intersection. Returns TRUE if the receiver overlaps aRect and
95 PRBool
Intersects(const nsRect
& aRect
) const;
97 // Computes the area in which aRect1 and aRect2 overlap, and fills 'this' with
98 // the result. Returns FALSE if the rectangles don't intersect, and sets 'this'
99 // rect to be an empty rect.
101 // 'this' can be the same object as either aRect1 or aRect2
102 PRBool
IntersectRect(const nsRect
& aRect1
, const nsRect
& aRect2
);
104 // Computes the smallest rectangle that contains both aRect1 and aRect2 and
105 // fills 'this' with the result, ignoring empty input rectangles.
106 // Returns FALSE and sets 'this' rect to be an empty rect if both aRect1
107 // and aRect2 are empty.
109 // 'this' can be the same object as either aRect1 or aRect2
110 PRBool
UnionRect(const nsRect
& aRect1
, const nsRect
& aRect2
);
112 // Computes the smallest rectangle that contains both aRect1 and aRect2,
113 // where empty input rectangles are allowed to affect the result; the
114 // top-left of an empty input rectangle will be inside or on the edge of
117 // 'this' can be the same object as either aRect1 or aRect2
118 void UnionRectIncludeEmpty(const nsRect
& aRect1
, const nsRect
& aRect2
);
121 void SetRect(nscoord aX
, nscoord aY
, nscoord aWidth
, nscoord aHeight
) {
122 x
= aX
; y
= aY
; width
= aWidth
; height
= aHeight
;
124 void SetRect(const nsPoint
& aPt
, const nsSize
& aSize
) {
125 SetRect(aPt
.x
, aPt
.y
, aSize
.width
, aSize
.height
);
127 void MoveTo(nscoord aX
, nscoord aY
) {x
= aX
; y
= aY
;}
128 void MoveTo(const nsPoint
& aPoint
) {x
= aPoint
.x
; y
= aPoint
.y
;}
129 void MoveBy(nscoord aDx
, nscoord aDy
) {x
+= aDx
; y
+= aDy
;}
130 void MoveBy(const nsPoint
& aPoint
) {x
+= aPoint
.x
; y
+= aPoint
.y
;}
131 void SizeTo(nscoord aWidth
, nscoord aHeight
) {width
= aWidth
; height
= aHeight
;}
132 void SizeTo(const nsSize
& aSize
) {SizeTo(aSize
.width
, aSize
.height
);}
133 void SizeBy(nscoord aDeltaWidth
, nscoord aDeltaHeight
) {width
+= aDeltaWidth
;
134 height
+= aDeltaHeight
;}
136 // Inflate the rect by the specified width/height or margin
137 void Inflate(nscoord aDx
, nscoord aDy
);
138 void Inflate(const nsSize
& aSize
) {Inflate(aSize
.width
, aSize
.height
);}
139 void Inflate(const nsMargin
& aMargin
);
141 // Deflate the rect by the specified width/height or margin
142 void Deflate(nscoord aDx
, nscoord aDy
);
143 void Deflate(const nsSize
& aSize
) {Deflate(aSize
.width
, aSize
.height
);}
144 void Deflate(const nsMargin
& aMargin
);
146 // Overloaded operators. Note that '=' isn't defined so we'll get the
147 // compiler generated default assignment operator.
148 PRBool
operator==(const nsRect
& aRect
) const {
149 return (PRBool
) ((IsEmpty() && aRect
.IsEmpty()) ||
150 ((x
== aRect
.x
) && (y
== aRect
.y
) &&
151 (width
== aRect
.width
) && (height
== aRect
.height
)));
153 PRBool
operator!=(const nsRect
& aRect
) const {
154 return (PRBool
) !operator==(aRect
);
157 // Useful when we care about the exact x/y/width/height values being
158 // equal (i.e. we care about differences in empty rectangles)
159 PRBool
IsExactEqual(const nsRect
& aRect
) const {
160 return x
== aRect
.x
&& y
== aRect
.y
&&
161 width
== aRect
.width
&& height
== aRect
.height
;
164 // Arithmetic with nsPoints
165 nsRect
operator+(const nsPoint
& aPoint
) const {
166 return nsRect(x
+ aPoint
.x
, y
+ aPoint
.y
, width
, height
);
168 nsRect
operator-(const nsPoint
& aPoint
) const {
169 return nsRect(x
- aPoint
.x
, y
- aPoint
.y
, width
, height
);
171 nsRect
& operator+=(const nsPoint
& aPoint
) {x
+= aPoint
.x
; y
+= aPoint
.y
; return *this;}
172 nsRect
& operator-=(const nsPoint
& aPoint
) {x
-= aPoint
.x
; y
-= aPoint
.y
; return *this;}
174 // Arithmetic with nsMargins
175 nsMargin
operator-(const nsRect
& aRect
) const; // Find difference as nsMargin
176 nsRect
& operator+=(const nsMargin
& aMargin
) { Inflate(aMargin
); return *this; }
177 nsRect
& operator-=(const nsMargin
& aMargin
) { Deflate(aMargin
); return *this; }
178 nsRect
operator+(const nsMargin
& aMargin
) const { return nsRect(*this) += aMargin
; }
179 nsRect
operator-(const nsMargin
& aMargin
) const { return nsRect(*this) -= aMargin
; }
181 // Scale by aScale, converting coordinates to integers so that the result is
182 // the smallest integer-coordinate rectangle containing the unrounded result.
183 nsRect
& ScaleRoundOut(float aScale
) { return ScaleRoundOut(aScale
, aScale
); }
184 nsRect
& ScaleRoundOut(float aXScale
, float aYScale
);
186 // Converts this rect from aFromAPP, an appunits per pixel ratio, to aToAPP.
187 // In the RoundOut version we make the rect the smallest rect containing the
188 // unrounded result. In the RoundIn version we make the rect the largest rect
189 // contained in the unrounded result.
190 inline nsRect
ConvertAppUnitsRoundOut(PRInt32 aFromAPP
, PRInt32 aToAPP
) const;
191 inline nsRect
ConvertAppUnitsRoundIn(PRInt32 aFromAPP
, PRInt32 aToAPP
) const;
193 // Helpers for accessing the vertices
194 nsPoint
TopLeft() const { return nsPoint(x
, y
); }
195 nsPoint
TopRight() const { return nsPoint(XMost(), y
); }
196 nsPoint
BottomLeft() const { return nsPoint(x
, YMost()); }
197 nsPoint
BottomRight() const { return nsPoint(XMost(), YMost()); }
199 nsSize
Size() const { return nsSize(width
, height
); }
201 // Helper methods for computing the extents
202 nscoord
XMost() const {return x
+ width
;}
203 nscoord
YMost() const {return y
+ height
;}
205 inline nsIntRect
ToNearestPixels(nscoord aAppUnitsPerPixel
) const;
206 inline nsIntRect
ToOutsidePixels(nscoord aAppUnitsPerPixel
) const;
207 inline nsIntRect
ToInsidePixels(nscoord aAppUnitsPerPixel
) const;
210 struct NS_GFX nsIntRect
{
212 PRInt32 width
, height
;
215 nsIntRect() : x(0), y(0), width(0), height(0) {}
216 nsIntRect(const nsIntRect
& aRect
) {*this = aRect
;}
217 nsIntRect(const nsIntPoint
& aOrigin
, const nsIntSize
&aSize
) {
218 x
= aOrigin
.x
; y
= aOrigin
.y
;
219 width
= aSize
.width
; height
= aSize
.height
;
221 nsIntRect(PRInt32 aX
, PRInt32 aY
, PRInt32 aWidth
, PRInt32 aHeight
) {
222 x
= aX
; y
= aY
; width
= aWidth
; height
= aHeight
;
225 // Emptiness. An empty rect is one that has no area, i.e. its height or width
227 PRBool
IsEmpty() const {
228 return (PRBool
) ((height
<= 0) || (width
<= 0));
230 void Empty() {width
= height
= 0;}
232 // Inflate the rect by the specified width/height or margin
233 void Inflate(PRInt32 aDx
, PRInt32 aDy
) {
239 void Inflate(const nsIntMargin
&aMargin
) {
242 width
+= aMargin
.left
+ aMargin
.right
;
243 height
+= aMargin
.top
+ aMargin
.bottom
;
246 // Deflate the rect by the specified width/height or margin
247 void Deflate(PRInt32 aDx
, PRInt32 aDy
) {
253 void Deflate(const nsIntMargin
&aMargin
) {
256 width
-= (aMargin
.left
+ aMargin
.right
);
257 height
-= (aMargin
.top
+ aMargin
.bottom
);
260 // Overloaded operators. Note that '=' isn't defined so we'll get the
261 // compiler generated default assignment operator.
262 PRBool
operator==(const nsIntRect
& aRect
) const {
263 return (PRBool
) ((IsEmpty() && aRect
.IsEmpty()) ||
264 ((x
== aRect
.x
) && (y
== aRect
.y
) &&
265 (width
== aRect
.width
) && (height
== aRect
.height
)));
267 PRBool
operator!=(const nsIntRect
& aRect
) const {
268 return (PRBool
) !operator==(aRect
);
271 nsIntRect
operator+(const nsIntPoint
& aPoint
) const {
272 return nsIntRect(x
+ aPoint
.x
, y
+ aPoint
.y
, width
, height
);
274 nsIntRect
operator-(const nsIntPoint
& aPoint
) const {
275 return nsIntRect(x
- aPoint
.x
, y
- aPoint
.y
, width
, height
);
277 nsIntRect
& operator+=(const nsIntPoint
& aPoint
) {x
+= aPoint
.x
; y
+= aPoint
.y
; return *this;}
278 nsIntRect
& operator-=(const nsIntPoint
& aPoint
) {x
-= aPoint
.x
; y
-= aPoint
.y
; return *this;}
280 void SetRect(PRInt32 aX
, PRInt32 aY
, PRInt32 aWidth
, PRInt32 aHeight
) {
281 x
= aX
; y
= aY
; width
= aWidth
; height
= aHeight
;
284 void MoveTo(PRInt32 aX
, PRInt32 aY
) {x
= aX
; y
= aY
;}
285 void MoveTo(const nsIntPoint
& aPoint
) {x
= aPoint
.x
; y
= aPoint
.y
;}
286 void MoveBy(PRInt32 aDx
, PRInt32 aDy
) {x
+= aDx
; y
+= aDy
;}
287 void MoveBy(const nsIntPoint
& aPoint
) {x
+= aPoint
.x
; y
+= aPoint
.y
;}
288 void SizeTo(PRInt32 aWidth
, PRInt32 aHeight
) {width
= aWidth
; height
= aHeight
;}
289 void SizeTo(const nsIntSize
& aSize
) {SizeTo(aSize
.width
, aSize
.height
);}
290 void SizeBy(PRInt32 aDeltaWidth
, PRInt32 aDeltaHeight
) {width
+= aDeltaWidth
;
291 height
+= aDeltaHeight
;}
293 PRBool
Contains(const nsIntRect
& aRect
) const
295 return aRect
.IsEmpty() ||
296 (PRBool
) ((aRect
.x
>= x
) && (aRect
.y
>= y
) &&
297 (aRect
.XMost() <= XMost()) && (aRect
.YMost() <= YMost()));
299 PRBool
Contains(PRInt32 aX
, PRInt32 aY
) const
301 return (PRBool
) ((aX
>= x
) && (aY
>= y
) &&
302 (aX
< XMost()) && (aY
< YMost()));
304 PRBool
Contains(const nsIntPoint
& aPoint
) const { return Contains(aPoint
.x
, aPoint
.y
); }
306 // Intersection. Returns TRUE if the receiver overlaps aRect and
308 PRBool
Intersects(const nsIntRect
& aRect
) const {
309 return (PRBool
) ((x
< aRect
.XMost()) && (y
< aRect
.YMost()) &&
310 (aRect
.x
< XMost()) && (aRect
.y
< YMost()));
313 // Computes the area in which aRect1 and aRect2 overlap, and fills 'this' with
314 // the result. Returns FALSE if the rectangles don't intersect, and sets 'this'
315 // rect to be an empty rect.
317 // 'this' can be the same object as either aRect1 or aRect2
318 PRBool
IntersectRect(const nsIntRect
& aRect1
, const nsIntRect
& aRect2
);
320 // Computes the smallest rectangle that contains both aRect1 and aRect2 and
321 // fills 'this' with the result. Returns FALSE and sets 'this' rect to be an
322 // empty rect if both aRect1 and aRect2 are empty
324 // 'this' can be the same object as either aRect1 or aRect2
325 PRBool
UnionRect(const nsIntRect
& aRect1
, const nsIntRect
& aRect2
);
327 // Helpers for accessing the vertices
328 nsIntPoint
TopLeft() const { return nsIntPoint(x
, y
); }
329 nsIntPoint
TopRight() const { return nsIntPoint(XMost(), y
); }
330 nsIntPoint
BottomLeft() const { return nsIntPoint(x
, YMost()); }
331 nsIntPoint
BottomRight() const { return nsIntPoint(XMost(), YMost()); }
333 nsIntSize
Size() const { return nsIntSize(width
, height
); }
335 // Helper methods for computing the extents
336 PRInt32
XMost() const {return x
+ width
;}
337 PRInt32
YMost() const {return y
+ height
;}
339 inline nsRect
ToAppUnits(nscoord aAppUnitsPerPixel
) const;
341 // Returns a special nsIntRect that's used in some places to signify
342 // "all available space".
343 static const nsIntRect
& GetMaxSizedIntRect() { return kMaxSizedIntRect
; }
346 static const nsIntRect kMaxSizedIntRect
;
350 * App Unit/Pixel conversions
354 nsRect::ConvertAppUnitsRoundOut(PRInt32 aFromAPP
, PRInt32 aToAPP
) const
356 if (aFromAPP
== aToAPP
) {
361 nscoord right
= NSToCoordCeil(NSCoordScale(XMost(), aFromAPP
, aToAPP
));
362 nscoord bottom
= NSToCoordCeil(NSCoordScale(YMost(), aFromAPP
, aToAPP
));
363 rect
.x
= NSToCoordFloor(NSCoordScale(x
, aFromAPP
, aToAPP
));
364 rect
.y
= NSToCoordFloor(NSCoordScale(y
, aFromAPP
, aToAPP
));
365 rect
.width
= (right
- rect
.x
);
366 rect
.height
= (bottom
- rect
.y
);
372 nsRect::ConvertAppUnitsRoundIn(PRInt32 aFromAPP
, PRInt32 aToAPP
) const
374 if (aFromAPP
== aToAPP
) {
379 nscoord right
= NSToCoordFloor(NSCoordScale(XMost(), aFromAPP
, aToAPP
));
380 nscoord bottom
= NSToCoordFloor(NSCoordScale(YMost(), aFromAPP
, aToAPP
));
381 rect
.x
= NSToCoordCeil(NSCoordScale(x
, aFromAPP
, aToAPP
));
382 rect
.y
= NSToCoordCeil(NSCoordScale(y
, aFromAPP
, aToAPP
));
383 rect
.width
= (right
- rect
.x
);
384 rect
.height
= (bottom
- rect
.y
);
389 // scale the rect but round to preserve centers
391 nsRect::ToNearestPixels(nscoord aAppUnitsPerPixel
) const
394 rect
.x
= NSToIntRoundUp(NSAppUnitsToFloatPixels(x
, float(aAppUnitsPerPixel
)));
395 rect
.y
= NSToIntRoundUp(NSAppUnitsToFloatPixels(y
, float(aAppUnitsPerPixel
)));
396 rect
.width
= NSToIntRoundUp(NSAppUnitsToFloatPixels(XMost(),
397 float(aAppUnitsPerPixel
))) - rect
.x
;
398 rect
.height
= NSToIntRoundUp(NSAppUnitsToFloatPixels(YMost(),
399 float(aAppUnitsPerPixel
))) - rect
.y
;
403 // scale the rect but round to smallest containing rect
405 nsRect::ToOutsidePixels(nscoord aAppUnitsPerPixel
) const
408 rect
.x
= NSToIntFloor(NSAppUnitsToFloatPixels(x
, float(aAppUnitsPerPixel
)));
409 rect
.y
= NSToIntFloor(NSAppUnitsToFloatPixels(y
, float(aAppUnitsPerPixel
)));
410 rect
.width
= NSToIntCeil(NSAppUnitsToFloatPixels(XMost(),
411 float(aAppUnitsPerPixel
))) - rect
.x
;
412 rect
.height
= NSToIntCeil(NSAppUnitsToFloatPixels(YMost(),
413 float(aAppUnitsPerPixel
))) - rect
.y
;
417 // scale the rect but round to largest contained rect
419 nsRect::ToInsidePixels(nscoord aAppUnitsPerPixel
) const
422 rect
.x
= NSToIntCeil(NSAppUnitsToFloatPixels(x
, float(aAppUnitsPerPixel
)));
423 rect
.y
= NSToIntCeil(NSAppUnitsToFloatPixels(y
, float(aAppUnitsPerPixel
)));
424 rect
.width
= NSToIntFloor(NSAppUnitsToFloatPixels(XMost(),
425 float(aAppUnitsPerPixel
))) - rect
.x
;
426 rect
.height
= NSToIntFloor(NSAppUnitsToFloatPixels(YMost(),
427 float(aAppUnitsPerPixel
))) - rect
.y
;
431 // app units are integer multiples of pixels, so no rounding needed
433 nsIntRect::ToAppUnits(nscoord aAppUnitsPerPixel
) const
435 return nsRect(NSIntPixelsToAppUnits(x
, aAppUnitsPerPixel
),
436 NSIntPixelsToAppUnits(y
, aAppUnitsPerPixel
),
437 NSIntPixelsToAppUnits(width
, aAppUnitsPerPixel
),
438 NSIntPixelsToAppUnits(height
, aAppUnitsPerPixel
));
443 extern NS_GFX
FILE* operator<<(FILE* out
, const nsRect
& rect
);
446 #endif /* NSRECT_H */