Back to index

lightning-sunbird  0.9+nobinonly
nsSVGLibartBitmapGdk.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 the Mozilla SVG project.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Alex Fritze.
00019  * Portions created by the Initial Developer are Copyright (C) 2003
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *   Alex Fritze <alex@croczilla.com> (original author)
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"gdk-pixbuf/gdk-pixbuf.h"
00040 #include "nsCOMPtr.h"
00041 #include "nsISVGLibartBitmap.h"
00042 #include "nsIRenderingContext.h"
00043 #include "nsIDeviceContext.h"
00044 #include "nsPresContext.h"
00045 #include "nsRect.h"
00046 #include "nsIComponentManager.h"
00047 #include "nsDrawingSurfaceGTK.h"
00048 #include "nsRenderingContextGTK.h"
00049 
00054 
00055 
00058 class nsSVGLibartBitmapGdk : public nsISVGLibartBitmap
00059 {
00060 public:
00061   nsSVGLibartBitmapGdk();
00062   ~nsSVGLibartBitmapGdk();
00063   nsresult Init(nsIRenderingContext *ctx,
00064                 nsPresContext* presContext,
00065                 const nsRect & rect);
00066 
00067   // nsISupports interface:
00068   NS_DECL_ISUPPORTS
00069 
00070   // nsISVGLibartBitmap interface:
00071   NS_IMETHOD_(PRUint8 *) GetBits();
00072   NS_IMETHOD_(nsISVGLibartBitmap::PixelFormat) GetPixelFormat();
00073   NS_IMETHOD_(int) GetLineStride();
00074   NS_IMETHOD_(int) GetWidth();
00075   NS_IMETHOD_(int) GetHeight();
00076   NS_IMETHOD_(void) LockRenderingContext(const nsRect& rect, nsIRenderingContext**ctx);
00077   NS_IMETHOD_(void) UnlockRenderingContext();
00078   NS_IMETHOD_(void) Flush();
00079   
00080 private:
00081   nsCOMPtr<nsIRenderingContext> mRenderingContext;
00082   nsRect mBufferRect;
00083   GdkPixbuf *mBuffer;
00084   nsRect mLockRect;
00085   nsIDrawingSurface* mTempSurface;
00086 };
00087 
00090 //----------------------------------------------------------------------
00091 // implementation:
00092 
00093 nsSVGLibartBitmapGdk::nsSVGLibartBitmapGdk()
00094     : mBuffer(nsnull),
00095       mTempSurface(nsnull)
00096 {
00097 }
00098 
00099 nsSVGLibartBitmapGdk::~nsSVGLibartBitmapGdk()
00100 {
00101   if (mBuffer) {
00102     gdk_pixbuf_unref(mBuffer);
00103   }
00104 }
00105 
00106 nsresult
00107 nsSVGLibartBitmapGdk::Init(nsIRenderingContext* ctx,
00108                            nsPresContext* presContext,
00109                            const nsRect & rect)
00110 {
00111   mRenderingContext = ctx;
00112   mBufferRect = rect;
00113   
00114   mBuffer = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, rect.width, rect.height);
00115 
00116   return NS_OK;
00117 }
00118 
00119 nsresult
00120 NS_NewSVGLibartBitmap(nsISVGLibartBitmap **result,
00121                       nsIRenderingContext *ctx,
00122                       nsPresContext* presContext,
00123                       const nsRect & rect)
00124 {
00125   nsSVGLibartBitmapGdk* bm = new nsSVGLibartBitmapGdk();
00126   if (!bm) return NS_ERROR_OUT_OF_MEMORY;
00127 
00128   NS_ADDREF(bm);
00129 
00130   nsresult rv = bm->Init(ctx, presContext, rect);
00131 
00132   if (NS_FAILED(rv)) {
00133     NS_RELEASE(bm);
00134     return rv;
00135   }
00136   
00137   *result = bm;
00138   return rv;
00139 }
00140 
00141 //----------------------------------------------------------------------
00142 // nsISupports methods:
00143 
00144 NS_IMPL_ADDREF(nsSVGLibartBitmapGdk)
00145 NS_IMPL_RELEASE(nsSVGLibartBitmapGdk)
00146 
00147 NS_INTERFACE_MAP_BEGIN(nsSVGLibartBitmapGdk)
00148   NS_INTERFACE_MAP_ENTRY(nsISVGLibartBitmap)
00149   NS_INTERFACE_MAP_ENTRY(nsISupports)
00150 NS_INTERFACE_MAP_END
00151 
00152 //----------------------------------------------------------------------
00153 // Implementation helpers:
00154 
00155 //----------------------------------------------------------------------
00156 // nsISVGLibartBitmap methods:
00157 
00158 NS_IMETHODIMP_(PRUint8 *)
00159 nsSVGLibartBitmapGdk::GetBits()
00160 {
00161   PRUint8* bits=gdk_pixbuf_get_pixels(mBuffer);
00162   return bits;
00163 }
00164 
00165 NS_IMETHODIMP_(nsISVGLibartBitmap::PixelFormat)
00166 nsSVGLibartBitmapGdk::GetPixelFormat()
00167 {
00168   return PIXEL_FORMAT_24_RGB;
00169 }
00170 
00171 NS_IMETHODIMP_(int)
00172 nsSVGLibartBitmapGdk::GetLineStride()
00173 {
00174   return gdk_pixbuf_get_rowstride(mBuffer);
00175 }
00176 
00177 NS_IMETHODIMP_(int)
00178 nsSVGLibartBitmapGdk::GetWidth()
00179 {
00180   return mBufferRect.width; 
00181 }
00182 
00183 NS_IMETHODIMP_(int)
00184 nsSVGLibartBitmapGdk::GetHeight()
00185 {
00186   return mBufferRect.height;
00187 }
00188 
00189 NS_IMETHODIMP_(void)
00190 nsSVGLibartBitmapGdk::LockRenderingContext(const nsRect& rect, nsIRenderingContext**ctx)
00191 { 
00192   NS_ASSERTION(mTempSurface==nsnull, "nested locking?");
00193   mLockRect = rect;
00194   
00195   nsDrawingSurfaceGTK *surface=nsnull;
00196   mRenderingContext->CreateDrawingSurface(rect, NS_CREATEDRAWINGSURFACE_FOR_PIXEL_ACCESS,
00197                                           (nsIDrawingSurface*&)surface);
00198   NS_ASSERTION(surface, "could not create drawing surface");
00199 
00200   // copy from pixbuf to surface
00201   GdkDrawable *drawable = surface->GetDrawable();
00202   NS_ASSERTION(drawable, "null gdkdrawable");
00203 
00204   gdk_draw_pixbuf(drawable, 0, mBuffer,
00205                   mLockRect.x-mBufferRect.x,
00206                   mLockRect.y-mBufferRect.y,
00207                   0, 0,
00208                   mLockRect.width, mLockRect.height,
00209                   GDK_RGB_DITHER_NONE, 0, 0);
00210 
00211   mRenderingContext->GetDrawingSurface(&mTempSurface);
00212   mRenderingContext->SelectOffScreenDrawingSurface(surface);
00213   mRenderingContext->PushState();
00214 
00215   nsTransform2D* transform;
00216   mRenderingContext->GetCurrentTransform(transform);
00217   transform->SetTranslation(-mLockRect.x, -mLockRect.y);
00218   
00219   *ctx = mRenderingContext;
00220   NS_ADDREF(*ctx);
00221 }
00222 
00223 NS_IMETHODIMP_(void)
00224 nsSVGLibartBitmapGdk::UnlockRenderingContext()
00225 { 
00226   NS_ASSERTION(mTempSurface, "no temporary surface. multiple unlock calls?");
00227   nsDrawingSurfaceGTK *surface=nsnull;
00228   mRenderingContext->GetDrawingSurface((nsIDrawingSurface**)&surface);
00229   NS_ASSERTION(surface, "null surface");
00230 
00231   mRenderingContext->PopState();
00232   mRenderingContext->SelectOffScreenDrawingSurface(mTempSurface);
00233   mTempSurface = nsnull;
00234   
00235   // copy from surface to pixbuf
00236   GdkPixbuf * pb = gdk_pixbuf_get_from_drawable(mBuffer, surface->GetDrawable(),
00237                                                 0,
00238                                                 0,0,
00239                                                 mLockRect.x-mBufferRect.x,mLockRect.y-mBufferRect.y,
00240                                                 mLockRect.width,mLockRect.height);
00241   NS_ASSERTION(pb, "gdk_pixbuf_get_from_drawable failed");
00242   mRenderingContext->DestroyDrawingSurface(surface);
00243 }
00244 
00245 NS_IMETHODIMP_(void)
00246 nsSVGLibartBitmapGdk::Flush()
00247 {
00248 
00249   nsDrawingSurfaceGTK *surface=nsnull;
00250   mRenderingContext->GetDrawingSurface((nsIDrawingSurface**)&surface);
00251   NS_ASSERTION(surface, "null drawing surface");
00252 
00253   GdkDrawable *drawable = surface->GetDrawable();
00254   NS_ASSERTION(drawable, "null gdkdrawable");
00255 
00256   nsTransform2D* transform;
00257   mRenderingContext->GetCurrentTransform(transform);
00258 
00259   gdk_draw_pixbuf(drawable, 0, mBuffer,
00260                   0, 0,
00261                   mBufferRect.x + transform->GetXTranslation(),
00262                   mBufferRect.y + transform->GetYTranslation(),
00263                   mBufferRect.width, mBufferRect.height,
00264                   GDK_RGB_DITHER_NONE, 0, 0);
00265 }