Back to index

lightning-sunbird  0.9+nobinonly
nsRect.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is mozilla.org code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either of the GNU General Public License Version 2 or later (the "GPL"),
00026  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 #include "nsRect.h"
00039 #include "nsString.h"
00040 #include "nsUnitConversion.h"
00041 
00042 #ifdef MIN
00043 #undef MIN
00044 #endif
00045 
00046 #ifdef MAX
00047 #undef MAX
00048 #endif
00049 
00050 #define MIN(a,b)\
00051   ((a) < (b) ? (a) : (b))
00052 #define MAX(a,b)\
00053   ((a) > (b) ? (a) : (b))
00054 
00055 // Containment
00056 PRBool nsRect::Contains(nscoord aX, nscoord aY) const
00057 {
00058   return (PRBool) ((aX >= x) && (aY >= y) &&
00059                    (aX < XMost()) && (aY < YMost()));
00060 }
00061 
00062 PRBool nsRect::Contains(const nsRect &aRect) const
00063 {
00064   return (PRBool) ((aRect.x >= x) && (aRect.y >= y) &&
00065                    (aRect.XMost() <= XMost()) && (aRect.YMost() <= YMost()));
00066 }
00067 
00068 // Intersection. Returns TRUE if the receiver overlaps aRect and
00069 // FALSE otherwise
00070 PRBool nsRect::Intersects(const nsRect &aRect) const
00071 {
00072   return (PRBool) ((x < aRect.XMost()) && (y < aRect.YMost()) &&
00073                    (aRect.x < XMost()) && (aRect.y < YMost()));
00074 }
00075 
00076 // Computes the area in which aRect1 and aRect2 overlap and fills 'this' with
00077 // the result. Returns FALSE if the rectangles don't intersect.
00078 PRBool nsRect::IntersectRect(const nsRect &aRect1, const nsRect &aRect2)
00079 {
00080   nscoord  xmost1 = aRect1.XMost();
00081   nscoord  ymost1 = aRect1.YMost();
00082   nscoord  xmost2 = aRect2.XMost();
00083   nscoord  ymost2 = aRect2.YMost();
00084   nscoord  temp;
00085 
00086   x = MAX(aRect1.x, aRect2.x);
00087   y = MAX(aRect1.y, aRect2.y);
00088 
00089   // Compute the destination width
00090   temp = MIN(xmost1, xmost2);
00091   if (temp <= x) {
00092     Empty();
00093     return PR_FALSE;
00094   }
00095   width = temp - x;
00096 
00097   // Compute the destination height
00098   temp = MIN(ymost1, ymost2);
00099   if (temp <= y) {
00100     Empty();
00101     return PR_FALSE;
00102   }
00103   height = temp - y;
00104 
00105   return PR_TRUE;
00106 }
00107 
00108 // Computes the smallest rectangle that contains both aRect1 and aRect2 and
00109 // fills 'this' with the result. Returns FALSE if both aRect1 and aRect2 are
00110 // empty and TRUE otherwise
00111 PRBool nsRect::UnionRect(const nsRect &aRect1, const nsRect &aRect2)
00112 {
00113   PRBool  result = PR_TRUE;
00114 
00115   // Is aRect1 empty?
00116   if (aRect1.IsEmpty()) {
00117     if (aRect2.IsEmpty()) {
00118       // Both rectangles are empty which is an error
00119       Empty();
00120       result = PR_FALSE;
00121     } else {
00122       // aRect1 is empty so set the result to aRect2
00123       *this = aRect2;
00124     }
00125   } else if (aRect2.IsEmpty()) {
00126     // aRect2 is empty so set the result to aRect1
00127     *this = aRect1;
00128   } else {
00129     nscoord xmost1 = aRect1.XMost();
00130     nscoord xmost2 = aRect2.XMost();
00131     nscoord ymost1 = aRect1.YMost();
00132     nscoord ymost2 = aRect2.YMost();
00133 
00134     // Compute the origin
00135     x = MIN(aRect1.x, aRect2.x);
00136     y = MIN(aRect1.y, aRect2.y);
00137 
00138     // Compute the size
00139     width = MAX(xmost1, xmost2) - x;
00140     height = MAX(ymost1, ymost2) - y;
00141   }
00142 
00143   return result;
00144 }
00145 
00146 // Inflate the rect by the specified width and height
00147 void nsRect::Inflate(nscoord aDx, nscoord aDy)
00148 {
00149   x -= aDx;
00150   y -= aDy;
00151   width += 2 * aDx;
00152   height += 2 * aDy;
00153 }
00154 
00155 // Inflate the rect by the specified margin
00156 void nsRect::Inflate(const nsMargin &aMargin)
00157 {
00158   x -= aMargin.left;
00159   y -= aMargin.top;
00160   width += aMargin.left + aMargin.right;
00161   height += aMargin.top + aMargin.bottom;
00162 }
00163 
00164 // Deflate the rect by the specified width and height
00165 void nsRect::Deflate(nscoord aDx, nscoord aDy)
00166 {
00167   x += aDx;
00168   y += aDy;
00169   width -= 2 * aDx;
00170   height -= 2 * aDy;
00171 }
00172 
00173 // Deflate the rect by the specified margin
00174 void nsRect::Deflate(const nsMargin &aMargin)
00175 {
00176   x += aMargin.left;
00177   y += aMargin.top;
00178   width -= aMargin.left + aMargin.right;
00179   height -= aMargin.top + aMargin.bottom;
00180 }
00181 
00182 // scale the rect but round to smallest containing rect
00183 nsRect& nsRect::ScaleRoundOut(const float aScale) 
00184 {
00185   nscoord right = NSToCoordCeil(float(x + width) * aScale);
00186   nscoord bottom = NSToCoordCeil(float(y + height) * aScale);
00187   x = NSToCoordFloor(float(x) * aScale);
00188   y = NSToCoordFloor(float(y) * aScale);
00189   width = (right - x);
00190   height = (bottom - y);
00191   return *this;
00192 }
00193 
00194 // scale the rect but round to largest contained rect
00195 nsRect& nsRect::ScaleRoundIn(const float aScale) 
00196 {
00197   nscoord right = NSToCoordFloor(float(x + width) * aScale);
00198   nscoord bottom = NSToCoordFloor(float(y + height) * aScale);
00199   x = NSToCoordCeil(float(x) * aScale);
00200   y = NSToCoordCeil(float(y) * aScale);
00201   width = (right - x);
00202   height = (bottom - y);
00203   return *this;
00204 }
00205 
00206 #ifdef DEBUG
00207 // Diagnostics
00208 
00209 FILE* operator<<(FILE* out, const nsRect& rect)
00210 {
00211   nsAutoString tmp;
00212 
00213   // Output the coordinates in fractional points so they're easier to read
00214   tmp.AppendLiteral("{");
00215   tmp.AppendFloat(NSTwipsToFloatPoints(rect.x));
00216   tmp.AppendLiteral(", ");
00217   tmp.AppendFloat(NSTwipsToFloatPoints(rect.y));
00218   tmp.AppendLiteral(", ");
00219   tmp.AppendFloat(NSTwipsToFloatPoints(rect.width));
00220   tmp.AppendLiteral(", ");
00221   tmp.AppendFloat(NSTwipsToFloatPoints(rect.height));
00222   tmp.AppendLiteral("}");
00223   fputs(NS_LossyConvertUCS2toASCII(tmp).get(), out);
00224   return out;
00225 }
00226 
00227 #ifdef NS_COORD_IS_FLOAT
00228 // Computes the area in which aRect1 and aRect2 overlap and fills 'this' with
00229 // the result. Returns FALSE if the rectangles don't intersect.
00230 PRBool nsIntRect::IntersectRect(const nsIntRect &aRect1, const nsIntRect &aRect2)
00231 {
00232   PRInt32  xmost1 = aRect1.XMost();
00233   PRInt32  ymost1 = aRect1.YMost();
00234   PRInt32  xmost2 = aRect2.XMost();
00235   PRInt32  ymost2 = aRect2.YMost();
00236   PRInt32  temp;
00237 
00238   x = MAX(aRect1.x, aRect2.x);
00239   y = MAX(aRect1.y, aRect2.y);
00240 
00241   // Compute the destination width
00242   temp = MIN(xmost1, xmost2);
00243   if (temp <= x) {
00244     Empty();
00245     return PR_FALSE;
00246   }
00247   width = temp - x;
00248 
00249   // Compute the destination height
00250   temp = MIN(ymost1, ymost2);
00251   if (temp <= y) {
00252     Empty();
00253     return PR_FALSE;
00254   }
00255   height = temp - y;
00256 
00257   return PR_TRUE;
00258 }
00259 
00260 // Computes the smallest rectangle that contains both aRect1 and aRect2 and
00261 // fills 'this' with the result. Returns FALSE if both aRect1 and aRect2 are
00262 // empty and TRUE otherwise
00263 PRBool nsIntRect::UnionRect(const nsIntRect &aRect1, const nsIntRect &aRect2)
00264 {
00265   PRBool  result = PR_TRUE;
00266 
00267   // Is aRect1 empty?
00268   if (aRect1.IsEmpty()) {
00269     if (aRect2.IsEmpty()) {
00270       // Both rectangles are empty which is an error
00271       Empty();
00272       result = PR_FALSE;
00273     } else {
00274       // aRect1 is empty so set the result to aRect2
00275       *this = aRect2;
00276     }
00277   } else if (aRect2.IsEmpty()) {
00278     // aRect2 is empty so set the result to aRect1
00279     *this = aRect1;
00280   } else {
00281     PRInt32 xmost1 = aRect1.XMost();
00282     PRInt32 xmost2 = aRect2.XMost();
00283     PRInt32 ymost1 = aRect1.YMost();
00284     PRInt32 ymost2 = aRect2.YMost();
00285 
00286     // Compute the origin
00287     x = MIN(aRect1.x, aRect2.x);
00288     y = MIN(aRect1.y, aRect2.y);
00289 
00290     // Compute the size
00291     width = MAX(xmost1, xmost2) - x;
00292     height = MAX(ymost1, ymost2) - y;
00293   }
00294 
00295   return result;
00296 }
00297 #endif
00298 
00299 #endif // DEBUG