Back to index

lightning-sunbird  0.9+nobinonly
nsGfxUtils.h
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 #ifndef nsGfxUtils_h_
00039 #define nsGfxUtils_h_
00040 
00041 #ifndef CarbonHelpers_h__
00042 #include "nsCarbonHelpers.h"
00043 #endif // CarbonHelpers_h__
00044 
00045 #if DEBUG && !defined(XP_MACOSX)
00046 #include "macstdlibextras.h"
00047 #endif
00048 
00049 #include <LowMem.h>
00050 
00051 
00055 inline PRBool CurrentPortIsWMPort()
00056 {
00057   return PR_FALSE;
00058 }
00059 
00060 
00061 //------------------------------------------------------------------------
00062 // ValidateDrawingState
00063 // 
00064 // Test that the current drawing environment is good, which means that
00065 // we have a valid port (as far as we can tell)
00066 //------------------------------------------------------------------------
00067 inline PRBool ValidateDrawingState()
00068 {
00069   CGrafPtr    curPort;
00070   GDHandle    curDevice;
00071   
00072   GetGWorld(&curPort, &curDevice);
00073   
00074   // if we have a window, but we're set to the WM port, things are bad
00075   if (CurrentPortIsWMPort() && (FrontWindow() != nil))
00076     return false;
00077 
00078 
00079   // see if the device is in the device list. If not, it probably means that
00080   // it's the device for an offscreen GWorld. In that case, the current port
00081   // should be set to that GWorld too.
00082   {
00083     GDHandle    thisDevice = GetDeviceList();
00084     while (thisDevice)
00085     {
00086       if (thisDevice == curDevice)
00087          break;
00088     
00089       thisDevice = GetNextDevice(thisDevice);
00090     }
00091 
00092     if ((thisDevice == nil) && !IsPortOffscreen(curPort))    // nil device is OK only with GWorld
00093       return false;
00094   }
00095 
00096   return true;
00097 }
00098 
00099 
00100 //------------------------------------------------------------------------
00101 // static graphics utility methods
00102 //------------------------------------------------------------------------
00103 class nsGraphicsUtils
00104 {
00105 public:
00106 
00107   //------------------------------------------------------------------------
00108   // SafeSetPort
00109   //
00110   // Set the port, being sure to set the GDevice to a valid device, since
00111   // the current GDevice may belong to a GWorld.
00112   //------------------------------------------------------------------------
00113   static void SafeSetPort(CGrafPtr newPort)
00114   {
00115     ::SetGWorld(newPort, ::IsPortOffscreen(newPort) ? nsnull : ::GetMainDevice());
00116   }
00117   
00118   //------------------------------------------------------------------------
00119   // SafeSetPortWindowPort
00120   //
00121   // Set the port, being sure to set the GDevice to a valid device, since
00122   // the current GDevice may belong to a GWorld.
00123   //------------------------------------------------------------------------
00124   static void SafeSetPortWindowPort(WindowPtr window)
00125   {
00126     SafeSetPort(::GetWindowPort(window));
00127   }
00128 
00129   //------------------------------------------------------------------------
00130   // SetPortToKnownGoodPort
00131   //
00132   // Set the port to a known good port, if possible.
00133   //------------------------------------------------------------------------
00134   static void SetPortToKnownGoodPort()
00135   {
00136     WindowPtr firstWindow = GetTheWindowList();
00137     if (firstWindow)
00138       ::SetGWorld(::GetWindowPort(firstWindow), ::GetMainDevice());
00139   }
00140 
00141 };
00142 
00143 
00144 //------------------------------------------------------------------------
00145 // utility port setting class
00146 //
00147 // This code has to deal with the situation where the current port
00148 // is a GWorld, and the current devices that GWorld's device. So
00149 // when setting the port to an onscreen part, we always reset the
00150 // current device to the main device.
00151 //------------------------------------------------------------------------
00152 class StPortSetter
00153 {
00154 public:
00155        StPortSetter(CGrafPtr newPort)
00156        {
00157               InitSetter(newPort);
00158        }
00159 
00160        StPortSetter(WindowPtr window)
00161        {
00162               InitSetter(GetWindowPort(window));
00163        }
00164        
00165        ~StPortSetter()
00166        {
00167          if (mPortChanged)
00168               ::SetGWorld(mOldPort, mOldDevice);
00169          NS_ASSERTION(ValidateDrawingState(), "Bad drawing state");
00170        }
00171 
00172 protected:
00173   void InitSetter(CGrafPtr newPort)
00174        {
00175          NS_ASSERTION(ValidateDrawingState(), "Bad drawing state");
00176          // we assume that if the port has been set, then the port/GDevice are
00177          // valid, and do nothing (for speed)
00178          mPortChanged = (newPort != CGrafPtr(GetQDGlobalsThePort()));
00179          if (mPortChanged)
00180          {
00181               ::GetGWorld(&mOldPort, &mOldDevice);
00182               ::SetGWorld(newPort, ::IsPortOffscreen(newPort) ? nsnull : ::GetMainDevice());
00183               }
00184        }
00185 
00186 protected:
00187   Boolean     mPortChanged;
00188        CGrafPtr             mOldPort;
00189        GDHandle    mOldDevice;
00190 };
00191 
00192 
00193 //------------------------------------------------------------------------
00194 // utility class to temporarily set and restore the origin.
00195 // Assumes that the port has already been set up.
00196 //------------------------------------------------------------------------
00197 class StOriginSetter
00198 {
00199 public:
00200 
00201   StOriginSetter(WindowRef wind, const Point* newOrigin = nsnull)
00202   {
00203     ::GetWindowPortBounds(wind, &mSavePortRect);
00204     if (newOrigin)
00205       ::SetOrigin(newOrigin->h, newOrigin->v);
00206     else
00207       ::SetOrigin(0, 0);
00208   }
00209   
00210   StOriginSetter(CGrafPtr grafPort, const Point* newOrigin = nsnull)
00211   {
00212     ::GetPortBounds(grafPort, &mSavePortRect);
00213     if (newOrigin)
00214       ::SetOrigin(newOrigin->h, newOrigin->v);
00215     else
00216       ::SetOrigin(0, 0);
00217   }
00218   
00219   ~StOriginSetter()
00220   {
00221     ::SetOrigin(mSavePortRect.left, mSavePortRect.top);
00222   }
00223 
00224 protected:
00225   
00226   Rect    mSavePortRect;
00227 
00228 };
00229 
00230 //------------------------------------------------------------------------
00231 // utility GWorld port setting class
00232 //
00233 // This should *only* be used to set the port temporarily to the
00234 // GWorld, and then restore it.
00235 //------------------------------------------------------------------------
00236 
00237 class StGWorldPortSetter
00238 {
00239 public:
00240        StGWorldPortSetter(GWorldPtr destGWorld)
00241        {
00242          NS_ASSERTION(::IsPortOffscreen(destGWorld), "StGWorldPortSetter should only be used for GWorlds");
00243          ::GetGWorld(&mOldPort, &mOldDevice);
00244               ::SetGWorld(destGWorld, nsnull);
00245        }
00246        
00247        ~StGWorldPortSetter()
00248        {
00249     ::SetGWorld(mOldPort, mOldDevice);
00250          NS_ASSERTION(ValidateDrawingState(), "Bad drawing state");
00251        }
00252 
00253 protected:
00254        GWorldPtr            mOldPort;
00255   GDHandle    mOldDevice;
00256 };
00257 
00258 //------------------------------------------------------------------------
00259 // utility text state save/restore class
00260 //------------------------------------------------------------------------
00261 
00262 class StTextStyleSetter
00263 {
00264 public:
00265        StTextStyleSetter(SInt16 fontID, SInt16 fontSize, SInt16 fontFace)
00266        {
00267          SetPortFontStyle(fontID, fontSize, fontFace);
00268        }
00269        
00270        StTextStyleSetter(TextStyle& theStyle)
00271        {
00272          SetPortFontStyle(theStyle.tsFont, theStyle.tsSize, theStyle.tsFace);
00273        }
00274        
00275        ~StTextStyleSetter()
00276        {
00277        ::TextFont(mFontID);
00278        ::TextSize(mFontSize);
00279        ::TextFace(mFontFace);
00280        }
00281 
00282 protected:
00283 
00284   void SetPortFontStyle(SInt16 fontID, SInt16 fontSize, SInt16 fontFace)
00285        {
00286          CGrafPtr curPort;
00287          ::GetPort((GrafPtr*)&curPort);
00288          
00289          NS_ASSERTION(ValidateDrawingState(), "Bad drawing state");
00290 
00291     mFontID = ::GetPortTextFont(curPort);
00292     mFontSize = ::GetPortTextSize(curPort);
00293     mFontFace = ::GetPortTextFace(curPort);
00294          
00295        ::TextFont(fontID);
00296        ::TextSize(fontSize);
00297        ::TextFace(fontFace);
00298 
00299        }
00300 
00301 protected:
00302        SInt16        mFontID;
00303        SInt16        mFontSize;
00304        SInt16    mFontFace;
00305 };
00306 
00307 
00308 
00309 
00310 
00315 class StPixelLocker
00316 {
00317 public:
00318                             
00319                                                                       StPixelLocker(PixMapHandle thePixMap)
00320                                                                       :      mPixMap(thePixMap)
00321                                                                       ,      mPixelState(0)
00322                                                                       {
00323                                                                              if (mPixMap) {
00324                                                                              mPixelState = ::GetPixelsState(mPixMap);
00325                                                                              ::LockPixels(mPixMap);
00326                                                                       }
00327                                                                       }
00328                                                                       
00329                                                                       ~StPixelLocker()
00330                                                                       {
00331                                                                              if (mPixMap)
00332                                                                              ::SetPixelsState(mPixMap, mPixelState);
00333                                                                       }
00334 
00335 protected:
00336 
00337 
00338               PixMapHandle         mPixMap;
00339               GWorldFlags                 mPixelState;
00340 
00341 };
00342 
00343 
00344 
00349 class StHandleOwner
00350 {
00351 public:
00352                     StHandleOwner(Handle inHandle)
00353                     : mHandle(inHandle)
00354                     {
00355                     }
00356 
00357                     ~StHandleOwner()
00358                     {
00359                       if (mHandle)
00360                         ::DisposeHandle(mHandle);
00361                     }
00362 
00363   Handle            GetHandle() { return mHandle; }
00364 
00365   void              ClearHandle(Boolean disposeIt = false)
00366                     {
00367                       if (disposeIt)
00368                         ::DisposeHandle(mHandle);
00369                       
00370                       mHandle = nsnull;
00371                     }
00372 
00373 protected:
00374 
00375   Handle            mHandle;
00376 
00377 };
00378 
00384 class StHandleLocker
00385 {
00386 public:
00387 
00388                     StHandleLocker(Handle theHandle)
00389                     :       mHandle(theHandle)
00390                     {
00391                       if (mHandle)
00392                       {
00393                        mOldHandleState = ::HGetState(mHandle);
00394                        ::HLock(mHandle);
00395                       }                                                                      
00396                     }
00397 
00398                     ~StHandleLocker()
00399                     {
00400                       if (mHandle)
00401                         ::HSetState(mHandle, mOldHandleState);
00402                     }
00403 
00404 protected:
00405 
00406     Handle          mHandle;
00407     SInt8           mOldHandleState;
00408 };
00409 
00410 
00417 class StColorSpaceReleaser
00418 {
00419 public:
00420   StColorSpaceReleaser(CGColorSpaceRef inColorSpace)
00421   : mColorSpace(inColorSpace)
00422   {
00423   }
00424 
00425   ~StColorSpaceReleaser()
00426   {
00427     // No need to check for NULL, since CGColorSpaceCreateDeviceRGB(NULL)
00428     // is a noop.
00429     ::CGColorSpaceRelease(mColorSpace);
00430   }
00431 
00432 private:
00433   CGColorSpaceRef mColorSpace;
00434 };
00435 
00436 #endif // nsGfxUtils_h_