Bug 449474, Fx3.0.2 updates should force modules/distribution.js, and use the version...
[mozilla-1.9.git] / gfx / src / nsRect.cpp
blobe7ba395672ca523e06fceb4acef72d6ececcc006
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
13 * License.
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.
22 * Contributor(s):
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 ***** */
38 #include "nsRect.h"
39 #include "nsString.h"
40 #include "nsIDeviceContext.h"
42 // Containment
43 PRBool nsRect::Contains(nscoord aX, nscoord aY) const
45 return (PRBool) ((aX >= x) && (aY >= y) &&
46 (aX < XMost()) && (aY < YMost()));
49 //Also Returns true if aRect is Empty
50 PRBool nsRect::Contains(const nsRect &aRect) const
52 return aRect.IsEmpty() ||
53 ((PRBool) ((aRect.x >= x) && (aRect.y >= y) &&
54 (aRect.XMost() <= XMost()) && (aRect.YMost() <= YMost())));
57 // Intersection. Returns TRUE if the receiver overlaps aRect and
58 // FALSE otherwise
59 PRBool nsRect::Intersects(const nsRect &aRect) const
61 return (PRBool) ((x < aRect.XMost()) && (y < aRect.YMost()) &&
62 (aRect.x < XMost()) && (aRect.y < YMost()));
65 // Computes the area in which aRect1 and aRect2 overlap and fills 'this' with
66 // the result. Returns FALSE if the rectangles don't intersect.
67 PRBool nsRect::IntersectRect(const nsRect &aRect1, const nsRect &aRect2)
69 nscoord xmost1 = aRect1.XMost();
70 nscoord ymost1 = aRect1.YMost();
71 nscoord xmost2 = aRect2.XMost();
72 nscoord ymost2 = aRect2.YMost();
73 nscoord temp;
75 x = PR_MAX(aRect1.x, aRect2.x);
76 y = PR_MAX(aRect1.y, aRect2.y);
78 // Compute the destination width
79 temp = PR_MIN(xmost1, xmost2);
80 if (temp <= x) {
81 Empty();
82 return PR_FALSE;
84 width = temp - x;
86 // Compute the destination height
87 temp = PR_MIN(ymost1, ymost2);
88 if (temp <= y) {
89 Empty();
90 return PR_FALSE;
92 height = temp - y;
94 return PR_TRUE;
97 // Computes the smallest rectangle that contains both aRect1 and aRect2 and
98 // fills 'this' with the result. Returns FALSE if both aRect1 and aRect2 are
99 // empty and TRUE otherwise
100 PRBool nsRect::UnionRect(const nsRect &aRect1, const nsRect &aRect2)
102 PRBool result = PR_TRUE;
104 // Is aRect1 empty?
105 if (aRect1.IsEmpty()) {
106 if (aRect2.IsEmpty()) {
107 // Both rectangles are empty which is an error
108 Empty();
109 result = PR_FALSE;
110 } else {
111 // aRect1 is empty so set the result to aRect2
112 *this = aRect2;
114 } else if (aRect2.IsEmpty()) {
115 // aRect2 is empty so set the result to aRect1
116 *this = aRect1;
117 } else {
118 UnionRectIncludeEmpty(aRect1, aRect2);
121 return result;
124 void nsRect::UnionRectIncludeEmpty(const nsRect &aRect1, const nsRect &aRect2)
126 nscoord xmost1 = aRect1.XMost();
127 nscoord xmost2 = aRect2.XMost();
128 nscoord ymost1 = aRect1.YMost();
129 nscoord ymost2 = aRect2.YMost();
131 // Compute the origin
132 x = PR_MIN(aRect1.x, aRect2.x);
133 y = PR_MIN(aRect1.y, aRect2.y);
135 // Compute the size
136 width = PR_MAX(xmost1, xmost2) - x;
137 height = PR_MAX(ymost1, ymost2) - y;
140 // Inflate the rect by the specified width and height
141 void nsRect::Inflate(nscoord aDx, nscoord aDy)
143 x -= aDx;
144 y -= aDy;
145 width += 2 * aDx;
146 height += 2 * aDy;
149 // Inflate the rect by the specified margin
150 void nsRect::Inflate(const nsMargin &aMargin)
152 x -= aMargin.left;
153 y -= aMargin.top;
154 width += aMargin.left + aMargin.right;
155 height += aMargin.top + aMargin.bottom;
158 // Deflate the rect by the specified width and height
159 void nsRect::Deflate(nscoord aDx, nscoord aDy)
161 x += aDx;
162 y += aDy;
163 width = PR_MAX(0, width - 2 * aDx);
164 height = PR_MAX(0, height - 2 * aDy);
167 // Deflate the rect by the specified margin
168 void nsRect::Deflate(const nsMargin &aMargin)
170 x += aMargin.left;
171 y += aMargin.top;
172 width = PR_MAX(0, width - aMargin.LeftRight());
173 height = PR_MAX(0, height - aMargin.TopBottom());
176 // scale the rect but round to smallest containing rect
177 nsRect& nsRect::ScaleRoundOut(float aScale)
179 nscoord right = NSToCoordCeil(float(XMost()) * aScale);
180 nscoord bottom = NSToCoordCeil(float(YMost()) * aScale);
181 x = NSToCoordFloor(float(x) * aScale);
182 y = NSToCoordFloor(float(y) * aScale);
183 width = (right - x);
184 height = (bottom - y);
185 return *this;
188 nsRect& nsRect::ScaleRoundOutInverse(float aScale)
190 nscoord right = NSToCoordCeil(float(XMost()) / aScale);
191 nscoord bottom = NSToCoordCeil(float(YMost()) / aScale);
192 x = NSToCoordFloor(float(x) / aScale);
193 y = NSToCoordFloor(float(y) / aScale);
194 width = (right - x);
195 height = (bottom - y);
196 return *this;
199 // scale the rect but round to largest contained rect
200 nsRect& nsRect::ScaleRoundIn(float aScale)
202 nscoord right = NSToCoordFloor(float(XMost()) * aScale);
203 nscoord bottom = NSToCoordFloor(float(YMost()) * aScale);
204 x = NSToCoordCeil(float(x) * aScale);
205 y = NSToCoordCeil(float(y) * aScale);
206 width = (right - x);
207 height = (bottom - y);
208 return *this;
211 nsRect& nsRect::ScaleRoundPreservingCentersInverse(float aScale)
213 nscoord right = NSToCoordRound(float(XMost()) / aScale);
214 nscoord bottom = NSToCoordRound(float(YMost()) / aScale);
215 x = NSToCoordRound(float(x) / aScale);
216 y = NSToCoordRound(float(y) / aScale);
217 width = (right - x);
218 height = (bottom - y);
219 return *this;
222 #ifdef DEBUG
223 // Diagnostics
225 FILE* operator<<(FILE* out, const nsRect& rect)
227 nsAutoString tmp;
229 // Output the coordinates in fractional pixels so they're easier to read
230 tmp.AppendLiteral("{");
231 tmp.AppendFloat(NSAppUnitsToFloatPixels(rect.x,
232 nsIDeviceContext::AppUnitsPerCSSPixel()));
233 tmp.AppendLiteral(", ");
234 tmp.AppendFloat(NSAppUnitsToFloatPixels(rect.y,
235 nsIDeviceContext::AppUnitsPerCSSPixel()));
236 tmp.AppendLiteral(", ");
237 tmp.AppendFloat(NSAppUnitsToFloatPixels(rect.width,
238 nsIDeviceContext::AppUnitsPerCSSPixel()));
239 tmp.AppendLiteral(", ");
240 tmp.AppendFloat(NSAppUnitsToFloatPixels(rect.height,
241 nsIDeviceContext::AppUnitsPerCSSPixel()));
242 tmp.AppendLiteral("}");
243 fputs(NS_LossyConvertUTF16toASCII(tmp).get(), out);
244 return out;
247 #ifdef NS_COORD_IS_FLOAT
248 // Computes the area in which aRect1 and aRect2 overlap and fills 'this' with
249 // the result. Returns FALSE if the rectangles don't intersect.
250 PRBool nsIntRect::IntersectRect(const nsIntRect &aRect1, const nsIntRect &aRect2)
252 PRInt32 xmost1 = aRect1.XMost();
253 PRInt32 ymost1 = aRect1.YMost();
254 PRInt32 xmost2 = aRect2.XMost();
255 PRInt32 ymost2 = aRect2.YMost();
256 PRInt32 temp;
258 x = PR_MAX(aRect1.x, aRect2.x);
259 y = PR_MAX(aRect1.y, aRect2.y);
261 // Compute the destination width
262 temp = PR_MIN(xmost1, xmost2);
263 if (temp <= x) {
264 Empty();
265 return PR_FALSE;
267 width = temp - x;
269 // Compute the destination height
270 temp = PR_MIN(ymost1, ymost2);
271 if (temp <= y) {
272 Empty();
273 return PR_FALSE;
275 height = temp - y;
277 return PR_TRUE;
280 // Computes the smallest rectangle that contains both aRect1 and aRect2 and
281 // fills 'this' with the result. Returns FALSE if both aRect1 and aRect2 are
282 // empty and TRUE otherwise
283 PRBool nsIntRect::UnionRect(const nsIntRect &aRect1, const nsIntRect &aRect2)
285 PRBool result = PR_TRUE;
287 // Is aRect1 empty?
288 if (aRect1.IsEmpty()) {
289 if (aRect2.IsEmpty()) {
290 // Both rectangles are empty which is an error
291 Empty();
292 result = PR_FALSE;
293 } else {
294 // aRect1 is empty so set the result to aRect2
295 *this = aRect2;
297 } else if (aRect2.IsEmpty()) {
298 // aRect2 is empty so set the result to aRect1
299 *this = aRect1;
300 } else {
301 PRInt32 xmost1 = aRect1.XMost();
302 PRInt32 xmost2 = aRect2.XMost();
303 PRInt32 ymost1 = aRect1.YMost();
304 PRInt32 ymost2 = aRect2.YMost();
306 // Compute the origin
307 x = PR_MIN(aRect1.x, aRect2.x);
308 y = PR_MIN(aRect1.y, aRect2.y);
310 // Compute the size
311 width = PR_MAX(xmost1, xmost2) - x;
312 height = PR_MAX(ymost1, ymost2) - y;
315 return result;
317 #endif
319 #endif // DEBUG