Back to index

lightning-sunbird  0.9+nobinonly
nsDrawingSurfaceXlib.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  *   David Smith <david@igelaus.com.au>
00024  *   Roland Mainz <roland.mainz@informatik.med.uni-giessen.de>
00025  *
00026  * Alternatively, the contents of this file may be used under the terms of
00027  * either of the GNU General Public License Version 2 or later (the "GPL"),
00028  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00029  * in which case the provisions of the GPL or the LGPL are applicable instead
00030  * of those above. If you wish to allow use of your version of this file only
00031  * under the terms of either the GPL or the LGPL, and not to allow others to
00032  * use your version of this file under the terms of the MPL, indicate your
00033  * decision by deleting the provisions above and replace them with the notice
00034  * and other provisions required by the GPL or the LGPL. If you do not delete
00035  * the provisions above, a recipient may use your version of this file under
00036  * the terms of any one of the MPL, the GPL or the LGPL.
00037  *
00038  * ***** END LICENSE BLOCK ***** */
00039 
00040 #include "nsDrawingSurfaceXlib.h"
00041 #include "prlog.h"
00042 #include "nsGCCache.h"
00043 
00044 #include "xlibrgb.h"      // for xxlib_rgb_get_visual_info
00045 
00046 #ifdef PR_LOGGING 
00047 static PRLogModuleInfo *DrawingSurfaceXlibLM = PR_NewLogModule("DrawingSurfaceXlib");
00048 #endif /* PR_LOGGING */ 
00049 
00050 nsDrawingSurfaceXlibImpl::nsDrawingSurfaceXlibImpl() :
00051   nsIDrawingSurfaceXlib(),
00052   mXlibRgbHandle(nsnull),
00053   mDisplay(nsnull),
00054   mScreen(nsnull),
00055   mVisual(nsnull),
00056   mDepth(0),
00057   mGC(nsnull),
00058   mDrawable(None),
00059   mImage(nsnull),
00060   // set up lock info
00061   mLockX(0),
00062   mLockY(0),
00063   mLockWidth(0),
00064   mLockHeight(0),
00065   mLockFlags(0),
00066   mLocked(PR_FALSE),
00067   // dimensions...
00068   mWidth(0),
00069   mHeight(0),
00070   mIsOffscreen(PR_FALSE)
00071 {
00072   PR_LOG(DrawingSurfaceXlibLM, PR_LOG_DEBUG, ("nsDrawingSurfaceXlibImpl::nsDrawingSurfaceXlibImpl()\n"));
00073 
00074 }
00075 
00076 nsDrawingSurfaceXlibImpl::~nsDrawingSurfaceXlibImpl()
00077 {
00078   PR_LOG(DrawingSurfaceXlibLM, PR_LOG_DEBUG, ("nsDrawingSurfaceXlibImpl::~nsDrawingSurfaceXlibImpl()\n"));
00079   // if it's been labeled as destroy, it's a pixmap.
00080   if (mDrawable!=None && mIsOffscreen) {
00081     XFreePixmap(mDisplay, mDrawable);
00082   }
00083   if (mImage) {
00084     XDestroyImage(mImage);
00085   }
00086 
00087   // We are freeing the GC here now [See nsWidget::CreateGC()]
00088   if(mGC) {
00089     mGC->Release();
00090     mGC = nsnull;
00091   }
00092 }
00093 
00094 NS_IMPL_ISUPPORTS1(nsDrawingSurfaceXlibImpl, nsIDrawingSurfaceXlib)
00095 
00096 NS_IMETHODIMP
00097 nsDrawingSurfaceXlibImpl::Init(XlibRgbHandle *aXlibRgbHandle,
00098                                Drawable       aDrawable, 
00099                                xGC           *aGC) 
00100 {
00101   PR_LOG(DrawingSurfaceXlibLM, PR_LOG_DEBUG, ("nsDrawingSurfaceXlibImpl::Init()\n"));
00102 
00103   mXlibRgbHandle = aXlibRgbHandle;
00104   mDrawable      = aDrawable;
00105 
00106   CommonInit();
00107   
00108   if (mGC)
00109     mGC->Release();
00110   mGC = aGC;
00111   mGC->AddRef();
00112   
00113   mIsOffscreen = PR_FALSE;
00114   return NS_OK;
00115 }
00116 
00117 NS_IMETHODIMP
00118 nsDrawingSurfaceXlibImpl::Init(XlibRgbHandle *aXlibRgbHandle,
00119                                xGC     * aGC,
00120                                PRUint32  aWidth, 
00121                                PRUint32  aHeight, 
00122                                PRUint32  aFlags) 
00123 {
00124   mXlibRgbHandle = aXlibRgbHandle;
00125   mWidth = aWidth;
00126   mHeight = aHeight;
00127   mLockFlags = aFlags;
00128 
00129   CommonInit();
00130   
00131   if (mGC)
00132     mGC->Release();
00133   mGC = aGC;
00134   mGC->AddRef();
00135   
00136   mIsOffscreen = PR_TRUE;
00137 
00138   mDrawable = XCreatePixmap(mDisplay, 
00139                             XRootWindow(mDisplay, XScreenNumberOfScreen(mScreen)),
00140                             mWidth, 
00141                             mHeight, 
00142                             mDepth);
00143 
00144   return (mDrawable!=None)?(NS_OK):(NS_ERROR_FAILURE);
00145 }
00146 
00147 void 
00148 nsDrawingSurfaceXlibImpl::CommonInit()
00149 {
00150   mDisplay = xxlib_rgb_get_display(mXlibRgbHandle);
00151   mScreen  = xxlib_rgb_get_screen(mXlibRgbHandle);
00152   mVisual  = xxlib_rgb_get_visual(mXlibRgbHandle);
00153   mDepth   = xxlib_rgb_get_depth(mXlibRgbHandle);
00154 
00155   XVisualInfo *x_visual_info = xxlib_rgb_get_visual_info(mXlibRgbHandle);
00156   NS_ASSERTION(nsnull != x_visual_info, "Visual info from xlibrgb is null.");
00157 
00158   if (x_visual_info)
00159   {
00160     mPixFormat.mRedMask = x_visual_info->red_mask;
00161     mPixFormat.mGreenMask = x_visual_info->green_mask;;
00162     mPixFormat.mBlueMask = x_visual_info->blue_mask;;
00163     mPixFormat.mAlphaMask = 0;
00164 
00165     mPixFormat.mRedCount = ConvertMaskToCount(x_visual_info->red_mask);
00166     mPixFormat.mGreenCount = ConvertMaskToCount(x_visual_info->green_mask);
00167     mPixFormat.mBlueCount = ConvertMaskToCount(x_visual_info->blue_mask);;
00168     mPixFormat.mAlphaCount = 0;
00169 
00170     mPixFormat.mRedShift = GetShiftForMask(x_visual_info->red_mask);
00171     mPixFormat.mGreenShift = GetShiftForMask(x_visual_info->green_mask);
00172     mPixFormat.mBlueShift = GetShiftForMask(x_visual_info->blue_mask);
00173     mPixFormat.mAlphaShift = 0;
00174   }
00175 }
00176 
00177 NS_IMETHODIMP
00178 nsDrawingSurfaceXlibImpl::Lock(PRInt32 aX, PRInt32 aY,
00179                                PRUint32 aWidth, PRUint32 aHeight,
00180                                void **aBits, PRInt32 *aStride,
00181                                PRInt32 *aWidthBytes, PRUint32 aFlags)
00182 {
00183   PR_LOG(DrawingSurfaceXlibLM, PR_LOG_DEBUG, ("nsDrawingSurfaceXlibImpl::Lock()\n"));
00184   if (mLocked)
00185   {
00186     NS_ASSERTION(0, "nested lock attempt");
00187     return NS_ERROR_FAILURE;
00188   }
00189   if (aWidth == 0 || aHeight == 0)
00190   {
00191     NS_ASSERTION(0, "Width or Height is 0");
00192     return NS_ERROR_FAILURE;
00193   }
00194 
00195   mLocked = PR_TRUE;
00196 
00197   mLockX = aX;
00198   mLockY = aY;
00199   mLockWidth = aWidth;
00200   mLockHeight = aHeight;
00201   mLockFlags = aFlags;
00202 
00203   mImage = XGetImage(mDisplay, mDrawable,
00204                      mLockX, mLockY,
00205                      mLockWidth, mLockHeight,
00206                      0xFFFFFFFF,
00207                      ZPixmap);
00208 
00209   if (!mImage) {
00210     mLocked = PR_FALSE;
00211     return NS_ERROR_FAILURE;
00212   }
00213   
00214   *aBits = mImage->data;
00215   
00216   *aWidthBytes = mImage->bytes_per_line;
00217   *aStride = mImage->bytes_per_line;
00218 
00219   return NS_OK;
00220 }
00221 
00222 NS_IMETHODIMP
00223 nsDrawingSurfaceXlibImpl::Unlock(void)
00224 {
00225   PR_LOG(DrawingSurfaceXlibLM, PR_LOG_DEBUG, ("nsDrawingSurfaceXlibImpl::UnLock()\n"));
00226   if (!mLocked) {
00227     NS_ASSERTION(0, "attempting to unlock an DS that isn't locked");
00228     return NS_ERROR_FAILURE;
00229   }
00230   
00231   // If the lock was not read only, put the bits back on the pixmap
00232   if (!(mLockFlags & NS_LOCK_SURFACE_READ_ONLY)) {
00233     XPutImage(mDisplay, mDrawable, *mGC, mImage,
00234               0, 0, mLockX, mLockY,
00235               mLockWidth, mLockHeight);
00236   }
00237   if (mImage) {
00238     XDestroyImage(mImage);
00239     mImage = nsnull;
00240   }
00241   mLocked = PR_FALSE;
00242   return NS_OK;
00243 }
00244 
00245 NS_IMETHODIMP
00246 nsDrawingSurfaceXlibImpl::GetDimensions(PRUint32 *aWidth, PRUint32 *aHeight)
00247 {
00248   *aWidth = mWidth;
00249   *aHeight = mHeight;
00250   return NS_OK;
00251 }
00252 
00253 NS_IMETHODIMP
00254 nsDrawingSurfaceXlibImpl::IsOffscreen(PRBool *aOffScreen)
00255 {
00256   *aOffScreen = mIsOffscreen;
00257   return NS_OK;
00258 }
00259 
00260 NS_IMETHODIMP
00261 nsDrawingSurfaceXlibImpl::IsPixelAddressable(PRBool *aAddressable)
00262 {
00263   *aAddressable = PR_FALSE;
00264   return NS_OK;
00265 }
00266 
00267 NS_IMETHODIMP
00268 nsDrawingSurfaceXlibImpl::GetPixelFormat(nsPixelFormat *aFormat)
00269 {
00270   *aFormat = mPixFormat;
00271   return NS_OK;
00272 }
00273 
00274 PRUint8 
00275 nsDrawingSurfaceXlibImpl::ConvertMaskToCount(unsigned long val)
00276 {
00277   PRUint8 retval = 0;
00278   PRUint8 cur_bit = 0;
00279   // walk through the number, incrementing the value if
00280   // the bit in question is set.
00281   while (cur_bit < (sizeof(unsigned long) * 8)) {
00282     if ((val >> cur_bit) & 0x1) {
00283       retval++;
00284     }
00285     cur_bit++;
00286   }
00287   return retval;
00288 }
00289 
00290 PRUint8 
00291 nsDrawingSurfaceXlibImpl::GetShiftForMask(unsigned long val)
00292 {
00293   PRUint8 cur_bit = 0;
00294   // walk through the number, looking for the first 1
00295   while (cur_bit < (sizeof(unsigned long) * 8)) {
00296     if ((val >> cur_bit) & 0x1) {
00297       return cur_bit;
00298     }
00299     cur_bit++;
00300   }
00301   return cur_bit;
00302 }