Back to index

lightning-sunbird  0.9+nobinonly
nsRegionXlib.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  *   Stuart Parmenter <pavlov@netscape.com>
00024  *
00025  * Alternatively, the contents of this file may be used under the terms of
00026  * either of the GNU General Public License Version 2 or later (the "GPL"),
00027  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00028  * in which case the provisions of the GPL or the LGPL are applicable instead
00029  * of those above. If you wish to allow use of your version of this file only
00030  * under the terms of either the GPL or the LGPL, and not to allow others to
00031  * use your version of this file under the terms of the MPL, indicate your
00032  * decision by deleting the provisions above and replace them with the notice
00033  * and other provisions required by the GPL or the LGPL. If you do not delete
00034  * the provisions above, a recipient may use your version of this file under
00035  * the terms of any one of the MPL, the GPL or the LGPL.
00036  *
00037  * ***** END LICENSE BLOCK ***** */
00038 
00039 #include "prmem.h"
00040 #include "nsRegionXlib.h"
00041 #include "xregion.h"
00042 
00043 // #define DEBUG_REGIONS 1
00044 
00045 #ifdef DEBUG_REGIONS
00046 static int nRegions;
00047 #endif
00048 
00049 Region nsRegionXlib::copyRegion = 0;
00050 
00051 
00052 nsRegionXlib::nsRegionXlib()
00053 {
00054 #ifdef DEBUG_REGIONS
00055     ++nRegions;
00056       printf("REGIONS+ = %i\n", nRegions);
00057 #endif
00058 
00059   mRegion = nsnull;
00060 }
00061 
00062 nsRegionXlib::~nsRegionXlib()
00063 {
00064 #ifdef DEBUG_REGIONS
00065   --nRegions;
00066   printf("REGIONS- = %i\n", nRegions);
00067 #endif
00068   
00069   if (mRegion)
00070     ::XDestroyRegion(mRegion);
00071   mRegion = nsnull;
00072 }
00073 
00074 NS_IMPL_ISUPPORTS1(nsRegionXlib, nsIRegion)
00075 
00076 Region
00077 nsRegionXlib::GetCopyRegion()
00078 {
00079   if (!copyRegion)
00080     copyRegion = ::XCreateRegion();
00081   return copyRegion;
00082 }
00083 
00084 Region
00085 nsRegionXlib::xlib_region_copy(Region region)
00086 {
00087   Region nRegion;
00088   nRegion = XCreateRegion();
00089 
00090   XUnionRegion(region, GetCopyRegion(), nRegion);
00091 
00092   return nRegion;
00093 }
00094 
00095 Region nsRegionXlib::xlib_region_from_rect(PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight)
00096 {
00097   XRectangle rect;
00098   Region nRegion;
00099 
00100   rect.x = aX;
00101   rect.y = aY;
00102   rect.width = aWidth;
00103   rect.height = aHeight;
00104 
00105   nRegion = XCreateRegion();
00106 
00107   XUnionRectWithRegion(&rect, GetCopyRegion(), nRegion);
00108 
00109   return nRegion;
00110 }
00111 
00112 nsresult
00113 nsRegionXlib::Init()
00114 {
00115   if (mRegion) {
00116     ::XDestroyRegion(mRegion);
00117     mRegion = nsnull;
00118   }
00119 
00120   return NS_OK;
00121 }
00122 
00123 void
00124 nsRegionXlib::SetTo(const nsIRegion &aRegion)
00125 {
00126   Init();
00127   nsRegionXlib * pRegion = (nsRegionXlib *)&aRegion;
00128 
00129   mRegion = xlib_region_copy(pRegion->mRegion);
00130 }
00131 
00132 void
00133 nsRegionXlib::SetTo(PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight)
00134 {
00135   Init();
00136   mRegion = xlib_region_from_rect(aX, aY, aWidth, aHeight);
00137 }
00138 
00139 void
00140 nsRegionXlib::Intersect(const nsIRegion &aRegion)
00141 {
00142   nsRegionXlib * pRegion = (nsRegionXlib *)&aRegion;
00143   
00144   Region nRegion = XCreateRegion();
00145   ::XIntersectRegion(mRegion, pRegion->mRegion, nRegion);
00146   ::XDestroyRegion(mRegion);
00147   mRegion = nRegion;
00148 }
00149 
00150 void
00151 nsRegionXlib::Intersect(PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight)
00152 {
00153   Region tRegion = xlib_region_from_rect(aX, aY, aWidth, aHeight);
00154   
00155   Region nRegion = XCreateRegion();
00156 
00157   ::XIntersectRegion(mRegion, tRegion, nRegion);
00158   ::XDestroyRegion(tRegion);
00159   ::XDestroyRegion(mRegion);
00160   mRegion = nRegion;
00161 }
00162 
00163 void
00164 nsRegionXlib::Union(const nsIRegion &aRegion)
00165 {
00166   nsRegionXlib * pRegion = (nsRegionXlib *)&aRegion;
00167 
00168   if (pRegion->mRegion && !::XEmptyRegion(pRegion->mRegion)) {
00169     if (mRegion) {
00170       if (::XEmptyRegion(mRegion)) {
00171         ::XDestroyRegion(mRegion);
00172         mRegion = xlib_region_copy(pRegion->mRegion);
00173       } else {
00174         Region nRegion = ::XCreateRegion();
00175         ::XUnionRegion(mRegion, pRegion->mRegion, nRegion);
00176         ::XDestroyRegion(mRegion);
00177         mRegion = nRegion;
00178       }
00179     } else
00180       mRegion = xlib_region_copy(pRegion->mRegion);
00181   }
00182 }
00183 
00184 void
00185 nsRegionXlib::Union(PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight)
00186 {
00187   if (mRegion) {
00188     XRectangle rect;
00189     
00190     rect.x = aX;
00191     rect.y = aY;
00192     rect.width = aWidth;
00193     rect.height = aHeight;
00194 
00195     if (rect.width > 0 && rect.height > 0) {
00196       if (::XEmptyRegion(mRegion)) {
00197         ::XDestroyRegion(mRegion);
00198         mRegion = xlib_region_from_rect(aX, aY, aWidth, aHeight);
00199       } else {
00200         Region nRegion = ::XCreateRegion();
00201         ::XUnionRectWithRegion(&rect, mRegion, nRegion);
00202         ::XDestroyRegion(mRegion);
00203         mRegion = nRegion;
00204       }
00205     }
00206   } else {
00207     mRegion = xlib_region_from_rect(aX, aY, aWidth, aHeight);
00208   }
00209 }
00210 
00211 void
00212 nsRegionXlib::Subtract(const nsIRegion &aRegion)
00213 {
00214 #ifdef DEBUG_REGIONS
00215   printf("nsRegionXlib::Subtract ");
00216 #endif
00217   nsRegionXlib * pRegion = (nsRegionXlib *)&aRegion;
00218 
00219   if (pRegion->mRegion) {
00220     if (mRegion) {
00221 #ifdef DEBUG_REGIONS
00222     printf("-");
00223 #endif
00224       Region nRegion = ::XCreateRegion();
00225       ::XSubtractRegion(mRegion, pRegion->mRegion, nRegion);
00226       ::XDestroyRegion(mRegion);
00227       mRegion = nRegion;
00228     } else {
00229 #ifdef DEBUG_REGIONS
00230     printf("+");
00231 #endif
00232       mRegion = ::XCreateRegion();
00233       ::XSubtractRegion(GetCopyRegion(), pRegion->mRegion, mRegion);
00234     }
00235   }
00236 #ifdef DEBUG_REGIONS
00237     printf("\n");
00238 #endif
00239 }
00240 
00241 void
00242 nsRegionXlib::Subtract(PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight)
00243 {
00244   if (mRegion) {
00245     Region tRegion = xlib_region_from_rect(aX, aY, aWidth, aHeight);
00246 
00247     Region nRegion = ::XCreateRegion();
00248     ::XSubtractRegion(mRegion, tRegion, nRegion);
00249     ::XDestroyRegion(mRegion);
00250     ::XDestroyRegion(tRegion);
00251     mRegion = nRegion;
00252   } else {
00253     Region tRegion = xlib_region_from_rect(aX, aY, aWidth, aHeight);
00254     mRegion = XCreateRegion();
00255     ::XSubtractRegion(GetCopyRegion(), tRegion, mRegion);
00256     ::XDestroyRegion(tRegion);
00257   }
00258 }
00259 
00260 PRBool
00261 nsRegionXlib::IsEmpty(void)
00262 {
00263   if (!mRegion)
00264     return PR_TRUE;
00265   return ::XEmptyRegion(mRegion);
00266 }
00267 
00268 PRBool
00269 nsRegionXlib::IsEqual(const nsIRegion &aRegion)
00270 {
00271   nsRegionXlib *pRegion = (nsRegionXlib *)&aRegion;
00272 
00273   if (mRegion && pRegion->mRegion) {
00274     return ::XEqualRegion(mRegion, pRegion->mRegion);
00275   } else if (!mRegion && !pRegion->mRegion) {
00276     return PR_TRUE;
00277   } else if ((mRegion && !pRegion->mRegion) ||
00278       (!mRegion && pRegion->mRegion)) {
00279     return PR_FALSE;
00280   }
00281 
00282   return PR_FALSE;
00283 }
00284 
00285 void
00286 nsRegionXlib::GetBoundingBox(PRInt32 *aX, PRInt32 *aY,
00287                              PRInt32 *aWidth, PRInt32 *aHeight)
00288 {
00289   if (mRegion) {
00290     XRectangle r;
00291 
00292     ::XClipBox(mRegion, &r);
00293 
00294     *aX = r.x;
00295     *aY = r.y;
00296     *aWidth = r.width;
00297     *aHeight = r.height;
00298   } else {
00299     *aX = 0;
00300     *aY = 0;
00301     *aWidth = 0;
00302     *aHeight = 0;
00303   }
00304 }
00305 
00306 void
00307 nsRegionXlib::Offset(PRInt32 aXOffset, PRInt32 aYOffset)
00308 {
00309   if (mRegion) {
00310     ::XOffsetRegion(mRegion, aXOffset, aYOffset);
00311   }
00312 }
00313 
00314 PRBool
00315 nsRegionXlib::ContainsRect(PRInt32 aX, PRInt32 aY,
00316                            PRInt32 aWidth, PRInt32 aHeight)
00317 {
00318   return (::XRectInRegion(mRegion, aX, aY, aWidth, aHeight) == RectangleIn) ?
00319     PR_TRUE : PR_FALSE;
00320 }
00321 
00322 NS_IMETHODIMP
00323 nsRegionXlib::GetRects(nsRegionRectSet **aRects)
00324 {
00325   *aRects = nsnull;
00326 
00327   if (!mRegion)
00328     return NS_OK;
00329 
00330   nsRegionRectSet   *rects;
00331   int               nbox;
00332   BOX               *pbox;
00333   nsRegionRect      *rect;
00334 
00335   NS_ASSERTION(!(nsnull == aRects), "bad ptr");
00336  
00337   //code lifted from old xfe. MMP
00338 
00339   pbox = mRegion->rects;
00340   nbox = mRegion->numRects;
00341  
00342   rects = *aRects;
00343 
00344   if ((nsnull == rects) || (rects->mRectsLen < (PRUint32)nbox)) {
00345     void *buf = PR_Realloc(rects, sizeof(nsRegionRectSet) +
00346                            (sizeof(nsRegionRect) * (nbox - 1)));
00347 
00348     if (nsnull == buf) {
00349       if (nsnull != rects)
00350         rects->mNumRects = 0;
00351  
00352       return NS_OK;
00353     }
00354 
00355     rects = (nsRegionRectSet *)buf;
00356     rects->mRectsLen = nbox;
00357   }
00358 
00359   rects->mNumRects = nbox;
00360   rects->mArea = 0;
00361   rect = &rects->mRects[0];
00362 
00363   while (nbox--) {
00364     rect->x = pbox->x1;
00365     rect->width = (pbox->x2 - pbox->x1);
00366     rect->y = pbox->y1;
00367     rect->height = (pbox->y2 - pbox->y1);
00368 
00369     rects->mArea += rect->width * rect->height;
00370 
00371     pbox++;
00372     rect++;
00373   }
00374 
00375   *aRects = rects;
00376 
00377   return NS_OK;
00378 }
00379 
00380 NS_IMETHODIMP
00381 nsRegionXlib::FreeRects(nsRegionRectSet *aRects)
00382 {
00383   if (nsnull != aRects)
00384     PR_Free((void *)aRects);
00385 
00386   return NS_OK;
00387 }
00388 
00389 NS_IMETHODIMP
00390 nsRegionXlib::GetNativeRegion(void *&aRegion) const
00391 {
00392   aRegion = (void *)mRegion;
00393   return NS_OK;
00394 }
00395 
00396 NS_IMETHODIMP
00397 nsRegionXlib::GetRegionComplexity(nsRegionComplexity &aComplexity) const
00398 {
00399   // cast to avoid const-ness problems on some compilers
00400   if (((nsRegionXlib*)this)->IsEmpty())
00401     aComplexity = eRegionComplexity_empty;
00402   else 
00403     aComplexity = eRegionComplexity_rect;
00404       
00405   return NS_OK;
00406 }
00407 
00408 void nsRegionXlib::SetRegionEmpty()
00409 {
00410   if (!IsEmpty()) { 
00411     ::XDestroyRegion(mRegion);
00412   }
00413 }
00414 
00415 NS_IMETHODIMP
00416 nsRegionXlib::GetNumRects(PRUint32 *aRects) const
00417 {
00418   if (!mRegion)
00419     *aRects = 0;
00420 
00421   *aRects = mRegion->numRects;
00422 
00423   return NS_OK;
00424 }