Back to index

lightning-sunbird  0.9+nobinonly
nsSVGLibartCanvas.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) 2002
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 
00040 #include "nsCOMPtr.h"
00041 #include "nsSVGLibartCanvas.h"
00042 #include "nsISVGLibartCanvas.h"
00043 #include "nsISVGLibartBitmap.h"
00044 #include "nsIRenderingContext.h"
00045 #include "nsIDeviceContext.h"
00046 #include "nsTransform2D.h"
00047 #include "nsPresContext.h"
00048 #include "nsRect.h"
00049 #include "libart-incs.h"
00050 
00055 
00056 
00059 class nsSVGLibartCanvas : public nsISVGLibartCanvas
00060 {
00061 public:
00062   nsSVGLibartCanvas();
00063   ~nsSVGLibartCanvas();
00064   nsresult Init(nsIRenderingContext* ctx, nsPresContext* presContext,
00065                 const nsRect & dirtyRect);
00066 
00067   // nsISupports interface:
00068   NS_DECL_ISUPPORTS
00069 
00070   // nsISVGRendererCanvas interface:
00071   NS_DECL_NSISVGRENDERERCANVAS
00072 
00073   // nsISVGLibartCanvas interface:
00074   NS_IMETHOD_(ArtRender*) NewRender();
00075   NS_IMETHOD_(ArtRender*) NewRender(int x0, int y0, int x1, int y1);
00076   NS_IMETHOD_(void) InvokeRender(ArtRender* render);  
00077   NS_IMETHOD_(void) GetArtColor(nscolor rgb, ArtColor& artColor);
00078   
00079 private:
00080   nsCOMPtr<nsIRenderingContext> mRenderingContext;
00081   nsCOMPtr<nsPresContext> mPresContext;
00082   nsCOMPtr<nsISVGLibartBitmap> mBitmap;
00083   nsRect mDirtyRect;
00084 
00085 };
00086 
00089 //----------------------------------------------------------------------
00090 // implementation:
00091 
00092 nsSVGLibartCanvas::nsSVGLibartCanvas()
00093 {
00094 }
00095 
00096 nsSVGLibartCanvas::~nsSVGLibartCanvas()
00097 {
00098 }
00099 
00100 nsresult
00101 nsSVGLibartCanvas::Init(nsIRenderingContext* ctx,
00102                         nsPresContext* presContext,
00103                         const nsRect & dirtyRect)
00104 {
00105   mPresContext = presContext;
00106   NS_ASSERTION(mPresContext, "empty prescontext");
00107   mRenderingContext = ctx;
00108   NS_ASSERTION(mRenderingContext, "empty rendering context");
00109 
00110   mDirtyRect = dirtyRect;
00111   NS_NewSVGLibartBitmap(getter_AddRefs(mBitmap), ctx, presContext,
00112                         dirtyRect);
00113   if (!mBitmap) {
00114     NS_ERROR("could not construct bitmap");
00115     return NS_ERROR_FAILURE;
00116   }
00117   
00118   return NS_OK;
00119 }
00120 
00121 nsresult
00122 NS_NewSVGLibartCanvas(nsISVGRendererCanvas **result,
00123                       nsIRenderingContext *ctx,
00124                       nsPresContext *presContext,
00125                       const nsRect & dirtyRect)
00126 {
00127   nsSVGLibartCanvas* pg = new nsSVGLibartCanvas();
00128   if (!pg) return NS_ERROR_OUT_OF_MEMORY;
00129 
00130   NS_ADDREF(pg);
00131 
00132   nsresult rv = pg->Init(ctx, presContext, dirtyRect);
00133 
00134   if (NS_FAILED(rv)) {
00135     NS_RELEASE(pg);
00136     return rv;
00137   }
00138   
00139   *result = pg;
00140   return rv;
00141 }
00142 
00143 //----------------------------------------------------------------------
00144 // nsISupports methods:
00145 
00146 NS_IMPL_ADDREF(nsSVGLibartCanvas)
00147 NS_IMPL_RELEASE(nsSVGLibartCanvas)
00148 
00149 NS_INTERFACE_MAP_BEGIN(nsSVGLibartCanvas)
00150   NS_INTERFACE_MAP_ENTRY(nsISVGRendererCanvas)
00151   NS_INTERFACE_MAP_ENTRY(nsISVGLibartCanvas)
00152   NS_INTERFACE_MAP_ENTRY(nsISupports)
00153 //  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsISVGRendererCanvas)
00154 NS_INTERFACE_MAP_END
00155 
00156 //----------------------------------------------------------------------
00157 // nsISVGRendererCanvas methods:
00158 
00160 NS_IMETHODIMP
00161 nsSVGLibartCanvas::LockRenderingContext(const nsRect & rect,
00162                                         nsIRenderingContext **_retval)
00163 {
00164   *_retval = nsnull;
00165   mBitmap->LockRenderingContext(rect, _retval);
00166   if (!*_retval) return NS_ERROR_FAILURE;
00167   return NS_OK;
00168 }
00169 
00171 NS_IMETHODIMP 
00172 nsSVGLibartCanvas::UnlockRenderingContext()
00173 {
00174   mBitmap->UnlockRenderingContext();
00175   return NS_OK;
00176 }
00177 
00179 NS_IMETHODIMP
00180 nsSVGLibartCanvas::GetPresContext(nsPresContext **_retval)
00181 {
00182   *_retval = mPresContext;
00183   NS_IF_ADDREF(*_retval);
00184   return NS_OK;
00185 }
00186 
00188 NS_IMETHODIMP
00189 nsSVGLibartCanvas::Clear(nscolor color)
00190 {
00191   PRUint8 red   = NS_GET_R(color);
00192   PRUint8 green = NS_GET_G(color);
00193   PRUint8 blue  = NS_GET_B(color);
00194 
00195   switch (mBitmap->GetPixelFormat()) {
00196     case nsISVGLibartBitmap::PIXEL_FORMAT_24_RGB:
00197     {
00198       PRInt32 stride = mBitmap->GetLineStride();
00199       PRInt32 width  = mBitmap->GetWidth();
00200       PRUint8* buf = mBitmap->GetBits();
00201       PRUint8* end = buf + stride*mBitmap->GetHeight();
00202       for ( ; buf<end; buf += stride) {
00203         art_rgb_fill_run(buf, red, green, blue, width);
00204       }
00205       break;
00206     }
00207     case nsISVGLibartBitmap::PIXEL_FORMAT_24_BGR:
00208     {
00209       PRInt32 stride = mBitmap->GetLineStride();
00210       PRInt32 width  = mBitmap->GetWidth();
00211       PRUint8* buf = mBitmap->GetBits();
00212       PRUint8* end = buf + stride*mBitmap->GetHeight();
00213       for ( ; buf<end; buf += stride) {
00214         art_rgb_fill_run(buf, blue, green, red, width);
00215       }
00216       break;
00217     }
00218     case nsISVGLibartBitmap::PIXEL_FORMAT_32_ABGR:
00219     {
00220       NS_ASSERTION(mBitmap->GetLineStride() == 4*mBitmap->GetWidth(), "strange pixel format");
00221       PRUint32 pixel = (blue<<24)+(green<<16)+(red<<8)+0xff;
00222       PRUint32 *dest = (PRUint32*)mBitmap->GetBits();
00223       PRUint32 *end  = dest+mBitmap->GetWidth()*mBitmap->GetHeight();
00224       while (dest!=end)
00225         *dest++ = pixel;
00226       break;
00227     }
00228     case nsISVGLibartBitmap::PIXEL_FORMAT_32_RGBA:
00229     {
00230       PRInt32 stride = mBitmap->GetLineStride();
00231       PRInt32 width  = mBitmap->GetWidth();
00232       PRUint8* buf = mBitmap->GetBits();
00233       PRUint8* end = buf + stride*mBitmap->GetHeight();
00234       for ( ; buf<end; buf += stride) {
00235         art_rgb_run_alpha(buf, red, green, blue, 0x100, width);
00236       }
00237       break;
00238     }
00239     case nsISVGLibartBitmap::PIXEL_FORMAT_32_BGRA:
00240     {
00241       PRInt32 stride = mBitmap->GetLineStride();
00242       PRInt32 width  = mBitmap->GetWidth();
00243       PRUint8* buf = mBitmap->GetBits();
00244       PRUint8* end = buf + stride*mBitmap->GetHeight();
00245       for ( ; buf<end; buf += stride) {
00246         art_rgb_run_alpha(buf, blue, green, red, 0x100, width);
00247       }
00248       break;
00249     }
00250     default:
00251       NS_ERROR("Unknown pixel format");
00252       break;
00253   }
00254   
00255   return NS_OK;
00256 }
00257 
00259 NS_IMETHODIMP
00260 nsSVGLibartCanvas::Flush()
00261 {
00262   mBitmap->Flush();
00263   return NS_OK;
00264 }
00265 
00266 //----------------------------------------------------------------------
00267 // nsISVGLibartCanvas methods:
00268 NS_IMETHODIMP_(ArtRender*)
00269 nsSVGLibartCanvas::NewRender()
00270 {
00271   ArtAlphaType alphaType = ART_ALPHA_NONE;
00272 
00273   if (mBitmap->GetPixelFormat()==nsISVGLibartBitmap::PIXEL_FORMAT_32_ABGR ||
00274       mBitmap->GetPixelFormat()==nsISVGLibartBitmap::PIXEL_FORMAT_32_RGBA ||
00275       mBitmap->GetPixelFormat()==nsISVGLibartBitmap::PIXEL_FORMAT_32_BGRA)
00276   {
00277       alphaType = ART_ALPHA_SEPARATE;
00278   }
00279 
00280   return art_render_new(mDirtyRect.x, mDirtyRect.y, // x0,y0
00281                         mDirtyRect.x+mDirtyRect.width, // x1
00282                         mDirtyRect.y+mDirtyRect.height, // y1
00283                         mBitmap->GetBits(), // pixels
00284                         mBitmap->GetLineStride(), // rowstride
00285                         3, // n_chan
00286                         8, // depth
00287                         alphaType, // alpha_type
00288                         NULL //alphagamma
00289                         );
00290 }
00291 
00292 NS_IMETHODIMP_(ArtRender*)
00293 nsSVGLibartCanvas::NewRender(int x0, int y0, int x1, int y1)
00294 {
00295   NS_ASSERTION(x0<x1 && y0<y1, "empty rect passed to NewRender()");
00296   if (x0>=x1 || y0>=y1) return nsnull;
00297 
00298   // only construct a render object if there is overlap with the dirty rect:
00299   if (x1<mDirtyRect.x || x0>mDirtyRect.x+mDirtyRect.width ||
00300       y1<mDirtyRect.y || y0>mDirtyRect.y+mDirtyRect.height)
00301     return nsnull;
00302 
00303   int rx0 = (x0>mDirtyRect.x ? x0 : mDirtyRect.x);
00304   int rx1 = (x1<mDirtyRect.x+mDirtyRect.width ? x1 : mDirtyRect.x+mDirtyRect.width);
00305   int ry0 = (y0>mDirtyRect.y ? y0 : mDirtyRect.y);
00306   int ry1 = (y1<mDirtyRect.y+mDirtyRect.height ? y1 : mDirtyRect.y+mDirtyRect.height);
00307 
00308   int offset = 3*(rx0-mDirtyRect.x) + mBitmap->GetLineStride()*(ry0-mDirtyRect.y);
00309   
00310   ArtAlphaType alphaType = ART_ALPHA_NONE;
00311 
00312   if (mBitmap->GetPixelFormat()==nsISVGLibartBitmap::PIXEL_FORMAT_32_ABGR ||
00313       mBitmap->GetPixelFormat()==nsISVGLibartBitmap::PIXEL_FORMAT_32_RGBA ||
00314       mBitmap->GetPixelFormat()==nsISVGLibartBitmap::PIXEL_FORMAT_32_BGRA)
00315   {
00316       alphaType = ART_ALPHA_SEPARATE;
00317   }
00318 
00319   return art_render_new(rx0, ry0, rx1, ry1,
00320                         mBitmap->GetBits()+offset, // pixels
00321                         mBitmap->GetLineStride(),  // rowstride
00322                         3, // n_chan
00323                         8, // depth
00324                         alphaType, // alpha_type
00325                         NULL //alphagamma
00326                         );
00327 }
00328 
00329 NS_IMETHODIMP_(void)
00330 nsSVGLibartCanvas::InvokeRender(ArtRender* render)
00331 {
00332   art_render_invoke(render);
00333 }
00334 
00335 NS_IMETHODIMP_(void)
00336 nsSVGLibartCanvas::GetArtColor(nscolor rgb, ArtColor& artColor)
00337 {
00338   switch (mBitmap->GetPixelFormat()) {
00339     case nsISVGLibartBitmap::PIXEL_FORMAT_24_RGB:
00340     case nsISVGLibartBitmap::PIXEL_FORMAT_32_RGBA:
00341       artColor[0] = ART_PIX_MAX_FROM_8(NS_GET_R(rgb));
00342       artColor[1] = ART_PIX_MAX_FROM_8(NS_GET_G(rgb));
00343       artColor[2] = ART_PIX_MAX_FROM_8(NS_GET_B(rgb));
00344       break;
00345     case nsISVGLibartBitmap::PIXEL_FORMAT_24_BGR:
00346     case nsISVGLibartBitmap::PIXEL_FORMAT_32_ABGR:
00347     case nsISVGLibartBitmap::PIXEL_FORMAT_32_BGRA:
00348       artColor[0] = ART_PIX_MAX_FROM_8(NS_GET_B(rgb));
00349       artColor[1] = ART_PIX_MAX_FROM_8(NS_GET_G(rgb));
00350       artColor[2] = ART_PIX_MAX_FROM_8(NS_GET_R(rgb));
00351       break;
00352     default:
00353       NS_ERROR("unknown pixel format");
00354       break;
00355   }
00356 }
00357 
00358 NS_IMETHODIMP
00359 nsSVGLibartCanvas::GetRenderMode(PRUint16 *aMode)
00360 {
00361   return NS_ERROR_NOT_IMPLEMENTED;
00362 }
00363 
00364 NS_IMETHODIMP
00365 nsSVGLibartCanvas::SetRenderMode(PRUint16 mode)
00366 {
00367   return NS_ERROR_NOT_IMPLEMENTED;
00368 }
00369 
00371 NS_IMETHODIMP
00372 nsSVGLibartCanvas::PushClip()
00373 {
00374   // XXX
00375   return NS_ERROR_NOT_IMPLEMENTED;
00376 }
00377 
00379 NS_IMETHODIMP
00380 nsSVGLibartCanvas::PopClip()
00381 {
00382   // XXX
00383   return NS_ERROR_NOT_IMPLEMENTED;
00384 }
00385 
00388 NS_IMETHODIMP
00389 nsSVGLibartCanvas::SetClipRect(nsIDOMSVGMatrix *aCTM, float aX, float aY,
00390                                float aWidth, float aHeight)
00391 {
00392   // XXX
00393   return NS_ERROR_NOT_IMPLEMENTED;
00394 }
00395 
00396 
00398 NS_IMETHODIMP
00399 nsSVGLibartCanvas::PushSurface(nsISVGRendererSurface *aSurface)
00400 {
00401   // XXX
00402   return NS_ERROR_NOT_IMPLEMENTED;
00403 }
00404 
00406 NS_IMETHODIMP
00407 nsSVGLibartCanvas::PopSurface()
00408 {
00409   // XXX
00410   return NS_ERROR_NOT_IMPLEMENTED;
00411 }
00412 
00416 NS_IMETHODIMP
00417 nsSVGLibartCanvas::CompositeSurface(nsISVGRendererSurface *aSurface,
00418                                     PRUint32 aX, PRUint32 aY, float aOpacity)
00419 {
00420   // XXX
00421   return NS_ERROR_NOT_IMPLEMENTED;
00422 }
00423 
00427 NS_IMETHODIMP
00428 nsSVGLibartCanvas::CompositeSurfaceMatrix(nsISVGRendererSurface *aSurface,
00429                                           nsIDOMSVGMatrix *aCTM, float aOpacity)
00430 {
00431   // XXX
00432   return NS_ERROR_NOT_IMPLEMENTED;
00433 }
00434