Back to index

lightning-sunbird  0.9+nobinonly
nsRegionMac.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 "nsRegionMac.h"
00039 #include "prmem.h"
00040 #include "nsCarbonHelpers.h"
00041 
00042 #include "nsRegionPool.h"
00043 
00044 static RegionToRectsUPP sAddRectToArrayProc;
00045 static RegionToRectsUPP sCountRectProc;
00046 
00047 static OSStatus
00048 AddRectToArrayProc(UInt16 message, RgnHandle rgn, const Rect *inRect, void *inArray)
00049 {
00050   if (message == kQDRegionToRectsMsgParse) {
00051     nsRegionRectSet* rects = NS_REINTERPRET_CAST(nsRegionRectSet*, inArray);
00052     nsRegionRect* rect = &rects->mRects[rects->mNumRects++];
00053     rect->x = inRect->left;
00054     rect->y = inRect->top;
00055     rect->width = inRect->right - inRect->left;
00056     rect->height = inRect->bottom - inRect->top;
00057     rects->mArea += rect->width * rect->height;
00058   }
00059 
00060   return noErr;
00061 }
00062 
00063 static OSStatus
00064 CountRectProc(UInt16 message, RgnHandle rgn, const Rect* inRect, void* rectCount)
00065 {
00066   if (message == kQDRegionToRectsMsgParse)
00067     ++(*NS_REINTERPRET_CAST(long*, rectCount));
00068 
00069   return noErr;
00070 }
00071 
00072 //---------------------------------------------------------------------
00073 
00074 nsRegionMac::nsRegionMac()
00075 {
00076        mRegion = nsnull;
00077        mRegionType = eRegionComplexity_empty;
00078   if (!sAddRectToArrayProc) {
00079     sAddRectToArrayProc = NewRegionToRectsUPP(AddRectToArrayProc);
00080     sCountRectProc = NewRegionToRectsUPP(CountRectProc);
00081   }
00082 }
00083 
00084 //---------------------------------------------------------------------
00085 
00086 nsRegionMac::~nsRegionMac()
00087 {
00088        if (mRegion != nsnull) {
00089               sNativeRegionPool.ReleaseRegion(mRegion);
00090               mRegion = nsnull;
00091        }
00092 }
00093 
00094 NS_IMPL_ISUPPORTS1(nsRegionMac, nsIRegion)
00095 
00096 //---------------------------------------------------------------------
00097 
00098 nsresult nsRegionMac::Init(void)
00099 {
00100        if (mRegion != nsnull)
00101               ::SetEmptyRgn(mRegion);
00102        else
00103               mRegion = sNativeRegionPool.GetNewRegion();
00104        if (mRegion != nsnull) {
00105               mRegionType = eRegionComplexity_empty;
00106               return NS_OK;
00107        }
00108        return NS_ERROR_OUT_OF_MEMORY;
00109 }
00110 
00111 //---------------------------------------------------------------------
00112 
00113 void nsRegionMac::SetTo(const nsIRegion &aRegion)
00114 {
00115        nsRegionMac* pRegion = (nsRegionMac*)&aRegion;
00116        ::CopyRgn(pRegion->mRegion, mRegion);
00117        SetRegionType();
00118 }
00119 
00120 //---------------------------------------------------------------------
00121 
00122 void nsRegionMac::SetTo(PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight)
00123 {
00124        ::SetRectRgn(mRegion, aX, aY, aX + aWidth, aY + aHeight);
00125        SetRegionType();
00126 }
00127 
00128 //---------------------------------------------------------------------
00129 
00130 void nsRegionMac::Intersect(const nsIRegion &aRegion)
00131 {
00132        nsRegionMac* pRegion = (nsRegionMac*)&aRegion;
00133        ::SectRgn(mRegion, pRegion->mRegion, mRegion);
00134        SetRegionType();
00135 }
00136 
00137 //---------------------------------------------------------------------
00138 
00139 void nsRegionMac::Intersect(PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight)
00140 {
00141        RgnHandle rectRgn = sNativeRegionPool.GetNewRegion();
00142        if (rectRgn != nsnull) {
00143               ::SetRectRgn(rectRgn, aX, aY, aX + aWidth, aY + aHeight);
00144               ::SectRgn(mRegion, rectRgn, mRegion);
00145               sNativeRegionPool.ReleaseRegion(rectRgn);
00146               SetRegionType();
00147        }
00148 }
00149 
00150 //---------------------------------------------------------------------
00151 
00152 void nsRegionMac::Union(const nsIRegion &aRegion)
00153 {
00154        nsRegionMac* pRegion = (nsRegionMac*)&aRegion;
00155        ::UnionRgn(mRegion, pRegion->mRegion, mRegion);
00156        SetRegionType();
00157 }
00158 
00159 //---------------------------------------------------------------------
00160 
00161 void nsRegionMac::Union(PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight)
00162 {
00163        RgnHandle rectRgn = sNativeRegionPool.GetNewRegion();
00164        if (rectRgn != nsnull) {
00165               ::SetRectRgn(rectRgn, aX, aY, aX + aWidth, aY + aHeight);
00166               ::UnionRgn(mRegion, rectRgn, mRegion);
00167               sNativeRegionPool.ReleaseRegion(rectRgn);
00168               SetRegionType();
00169        }
00170 }
00171 
00172 //---------------------------------------------------------------------
00173 
00174 void nsRegionMac::Subtract(const nsIRegion &aRegion)
00175 {
00176        nsRegionMac* pRegion = (nsRegionMac*)&aRegion;
00177        ::DiffRgn(mRegion, pRegion->mRegion, mRegion);
00178        SetRegionType();
00179 }
00180 
00181 //---------------------------------------------------------------------
00182 
00183 void nsRegionMac::Subtract(PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight)
00184 {
00185        RgnHandle rectRgn = sNativeRegionPool.GetNewRegion();
00186        if (rectRgn != nsnull) {
00187               ::SetRectRgn(rectRgn, aX, aY, aX + aWidth, aY + aHeight);
00188               ::DiffRgn(mRegion, rectRgn, mRegion);
00189               sNativeRegionPool.ReleaseRegion(rectRgn);
00190               SetRegionType();
00191        }
00192 }
00193 
00194 //---------------------------------------------------------------------
00195 
00196 PRBool nsRegionMac::IsEmpty(void)
00197 {
00198        if (mRegionType == eRegionComplexity_empty)
00199        return PR_TRUE;
00200        else
00201               return PR_FALSE;
00202 }
00203 
00204 //---------------------------------------------------------------------
00205 
00206 PRBool nsRegionMac::IsEqual(const nsIRegion &aRegion)
00207 {
00208        nsRegionMac* pRegion = (nsRegionMac*)&aRegion;
00209        return(::EqualRgn(mRegion, pRegion->mRegion));
00210 }
00211 
00212 //---------------------------------------------------------------------
00213 
00214 void nsRegionMac::GetBoundingBox(PRInt32 *aX, PRInt32 *aY, PRInt32 *aWidth, PRInt32 *aHeight)
00215 {
00216        Rect macRect;
00217        ::GetRegionBounds (mRegion, &macRect);
00218 
00219        *aX = macRect.left;
00220        *aY = macRect.top;
00221        *aWidth  = macRect.right - macRect.left;
00222        *aHeight = macRect.bottom - macRect.top;
00223 }
00224 
00225 //---------------------------------------------------------------------
00226 
00227 void nsRegionMac::Offset(PRInt32 aXOffset, PRInt32 aYOffset)
00228 {
00229        ::OffsetRgn(mRegion, aXOffset, aYOffset);
00230 }
00231 
00232 //---------------------------------------------------------------------
00233 
00234 PRBool nsRegionMac::ContainsRect(PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight)
00235 {
00236        Rect macRect;
00237        ::SetRect(&macRect, aX, aY, aX + aWidth, aY + aHeight);
00238        return(::RectInRgn(&macRect, mRegion));
00239 }
00240 
00241 //---------------------------------------------------------------------
00242 
00243 NS_IMETHODIMP nsRegionMac::GetRects(nsRegionRectSet **aRects)
00244 {
00245   NS_ASSERTION(aRects, "bad ptr");
00246 
00247   nsRegionRectSet* rects = *aRects;
00248   long numrects = 0;
00249   QDRegionToRects(mRegion, kQDParseRegionFromTopLeft, sCountRectProc, &numrects);
00250 
00251   if (!rects || rects->mRectsLen < (PRUint32) numrects) {
00252     void* buf = PR_Realloc(rects, sizeof(nsRegionRectSet) + sizeof(nsRegionRect) * (numrects - 1));
00253 
00254     if (!buf) {
00255       if (rects)
00256         rects->mNumRects = 0;
00257 
00258       return NS_ERROR_OUT_OF_MEMORY;
00259     }
00260 
00261     rects = (nsRegionRectSet*) buf;
00262     rects->mRectsLen = numrects;
00263   }
00264 
00265   rects->mNumRects = 0;
00266   rects->mArea = 0;
00267   QDRegionToRects(mRegion, kQDParseRegionFromTopLeft, sAddRectToArrayProc, rects);
00268 
00269   *aRects = rects;
00270 
00271   return NS_OK;
00272 }
00273 
00274 //---------------------------------------------------------------------
00275 
00276 NS_IMETHODIMP nsRegionMac::FreeRects(nsRegionRectSet *aRects)
00277 {
00278        if (nsnull != aRects)
00279               PR_Free((void *)aRects);
00280 
00281        return NS_OK;
00282 }
00283 
00284 //---------------------------------------------------------------------
00285 
00286 
00287 NS_IMETHODIMP nsRegionMac::GetNativeRegion(void *&aRegion) const
00288 {
00289        aRegion = (void *)mRegion;
00290        return NS_OK;
00291 }
00292 
00293 
00294 nsresult nsRegionMac::SetNativeRegion(void *aRegion)
00295 {
00296        if (aRegion) {
00297               ::CopyRgn((RgnHandle)aRegion, mRegion);
00298        SetRegionType();
00299        } else {
00300               Init();
00301        }
00302        return NS_OK;
00303 }
00304 
00305 //---------------------------------------------------------------------
00306 
00307 NS_IMETHODIMP nsRegionMac::GetRegionComplexity(nsRegionComplexity &aComplexity) const
00308 {
00309        aComplexity = mRegionType;
00310        return NS_OK;
00311 }
00312 
00313 //---------------------------------------------------------------------
00314 
00315 
00316 void nsRegionMac::SetRegionType()
00317 {
00318        if (::EmptyRgn(mRegion) == PR_TRUE)
00319        mRegionType = eRegionComplexity_empty;
00320        else
00321        if ( ::IsRegionRectangular(mRegion) )
00322               mRegionType = eRegionComplexity_rect;
00323        else
00324               mRegionType = eRegionComplexity_complex;
00325 }
00326 
00327 
00328 //---------------------------------------------------------------------
00329 
00330 
00331 void nsRegionMac::SetRegionEmpty()
00332 {
00333        ::SetEmptyRgn(mRegion);
00334        SetRegionType();
00335 }
00336 
00337 //---------------------------------------------------------------------
00338 
00339 RgnHandle nsRegionMac::CreateRectRegion(PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight)
00340 {
00341        RgnHandle rectRgn = sNativeRegionPool.GetNewRegion();
00342        if (rectRgn != nsnull)
00343               ::SetRectRgn(rectRgn, aX, aY, aX + aWidth, aY + aHeight);
00344        return rectRgn;
00345 }