/layout/svg/renderer/src/libart/nsSVGLibartBitmapDefault.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
00006  * Version 1.1 (the "License"); you may not use this file except in
00007  * compliance with 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 Alex Fritze.
00018  * 
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 the GNU General Public License Version 2 or later (the "GPL"), or 
00027  * 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 NPL, 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 "nsISVGLibartBitmap.h"
00042 #include "nsIRenderingContext.h"
00043 #include "nsIDeviceContext.h"
00044 #include "nsIPresContext.h"
00045 #include "nsRect.h"
00046 #include "nsIImage.h"
00047 #include "nsIComponentManager.h"
00048 #include "imgIContainer.h"
00049 #include "gfxIImageFrame.h"
00050 #include "nsIInterfaceRequestor.h"
00051 #include "nsIInterfaceRequestorUtils.h"
00052 
00057 
00058 
00064 class nsSVGLibartBitmapDefault : public nsISVGLibartBitmap
00065 {
00066 public:
00067   nsSVGLibartBitmapDefault();
00068   ~nsSVGLibartBitmapDefault();
00069   nsresult Init(nsIRenderingContext *ctx,
00070                 nsIPresContext* presContext,
00071                 const nsRect & rect);
00072 
00073   // nsISupports interface:
00074   NS_DECL_ISUPPORTS
00075 
00076   // nsISVGLibartBitmap interface:
00077   NS_IMETHOD_(PRUint8 *) GetBits();
00078   NS_IMETHOD_(nsISVGLibartBitmap::PixelFormat) GetPixelFormat();
00079   NS_IMETHOD_(int) GetLineStride();
00080   NS_IMETHOD_(int) GetWidth();
00081   NS_IMETHOD_(int) GetHeight();
00082   NS_IMETHOD_(void) LockRenderingContext(const nsRect& rect, nsIRenderingContext**ctx);
00083   NS_IMETHOD_(void) UnlockRenderingContext();
00084   NS_IMETHOD_(void) Flush();
00085   
00086 private:
00087   void LockBuffer();
00088   void UnlockBuffer();
00089 
00090   PRBool mLocked;
00091   nsCOMPtr<nsIRenderingContext> mRenderingContext;
00092   nsCOMPtr<imgIContainer> mContainer;
00093   nsCOMPtr<gfxIImageFrame> mBuffer;
00094   nsRect mRectTwips;
00095   nsRect mRect;
00096 };
00097 
00100 //----------------------------------------------------------------------
00101 // implementation:
00102 
00103 nsSVGLibartBitmapDefault::nsSVGLibartBitmapDefault()
00104     : mLocked(PR_FALSE)
00105 {
00106 }
00107 
00108 nsSVGLibartBitmapDefault::~nsSVGLibartBitmapDefault()
00109 {
00110 
00111 }
00112 
00113 nsresult
00114 nsSVGLibartBitmapDefault::Init(nsIRenderingContext* ctx,
00115                                nsIPresContext* presContext,
00116                                const nsRect & rect)
00117 {
00118   mRenderingContext = ctx;
00119 
00120   float twipsPerPx;
00121   presContext->GetPixelsToTwips(&twipsPerPx);
00122   mRectTwips.x = (nscoord)(rect.x*twipsPerPx);
00123   mRectTwips.y = (nscoord)(rect.y*twipsPerPx);
00124   mRectTwips.width = (nscoord)(rect.width*twipsPerPx);
00125   mRectTwips.height = (nscoord)(rect.height*twipsPerPx);
00126   mRect = rect;
00127   
00128   mContainer = do_CreateInstance("@mozilla.org/image/container;1");
00129   mContainer->Init(rect.width, rect.height, nsnull);
00130     
00131   mBuffer = do_CreateInstance("@mozilla.org/gfx/image/frame;2");
00132   mBuffer->Init(0, 0, rect.width, rect.height, gfxIFormats::RGB, 24);
00133   mContainer->AppendFrame(mBuffer);
00134   
00135   return NS_OK;
00136 }
00137 
00138 nsresult
00139 NS_NewSVGLibartBitmap(nsISVGLibartBitmap **result,
00140                       nsIRenderingContext *ctx,
00141                       nsIPresContext* presContext,
00142                       const nsRect & rect)
00143 {
00144   nsSVGLibartBitmapDefault* bm = new nsSVGLibartBitmapDefault();
00145   if (!bm) return NS_ERROR_OUT_OF_MEMORY;
00146 
00147   NS_ADDREF(bm);
00148 
00149   nsresult rv = bm->Init(ctx, presContext, rect);
00150 
00151   if (NS_FAILED(rv)) {
00152     NS_RELEASE(bm);
00153     return rv;
00154   }
00155   
00156   *result = bm;
00157   return rv;
00158 }
00159 
00160 //----------------------------------------------------------------------
00161 // nsISupports methods:
00162 
00163 NS_IMPL_ADDREF(nsSVGLibartBitmapDefault)
00164 NS_IMPL_RELEASE(nsSVGLibartBitmapDefault)
00165 
00166 NS_INTERFACE_MAP_BEGIN(nsSVGLibartBitmapDefault)
00167   NS_INTERFACE_MAP_ENTRY(nsISVGLibartBitmap)
00168   NS_INTERFACE_MAP_ENTRY(nsISupports)
00169 NS_INTERFACE_MAP_END
00170 
00171 //----------------------------------------------------------------------
00172 // Implementation helpers:
00173 void
00174 nsSVGLibartBitmapDefault::LockBuffer()
00175 {
00176   if (mLocked) return;
00177 
00178   mBuffer->LockImageData();    
00179   mLocked = PR_TRUE;
00180 }
00181 
00182 void
00183 nsSVGLibartBitmapDefault::UnlockBuffer()
00184 {
00185   if (!mLocked) return;
00186 
00187   mBuffer->UnlockImageData();
00188   mLocked = PR_FALSE;
00189 }
00190 
00191 
00192 //----------------------------------------------------------------------
00193 // nsISVGLibartBitmap methods:
00194 
00195 NS_IMETHODIMP_(PRUint8 *)
00196 nsSVGLibartBitmapDefault::GetBits()
00197 {
00198   LockBuffer();
00199   PRUint8* bits=nsnull;
00200   PRUint32 length;
00201   mBuffer->GetImageData(&bits, &length);
00202   return bits;
00203 }
00204 
00205 NS_IMETHODIMP_(nsISVGLibartBitmap::PixelFormat)
00206 nsSVGLibartBitmapDefault::GetPixelFormat()
00207 {
00208   return PIXEL_FORMAT_24_RGB;
00209 }
00210 
00211 NS_IMETHODIMP_(int)
00212 nsSVGLibartBitmapDefault::GetLineStride()
00213 {
00214   PRUint32 bytesPerRow=0;
00215   mBuffer->GetImageBytesPerRow(&bytesPerRow);
00216   return (int) bytesPerRow;
00217 }
00218 
00219 NS_IMETHODIMP_(int)
00220 nsSVGLibartBitmapDefault::GetWidth()
00221 {
00222   return mRect.width; 
00223 }
00224 
00225 NS_IMETHODIMP_(int)
00226 nsSVGLibartBitmapDefault::GetHeight()
00227 {
00228   return mRect.height;
00229 }
00230 
00231 NS_IMETHODIMP_(void)
00232 nsSVGLibartBitmapDefault::LockRenderingContext(const nsRect& rect, nsIRenderingContext** ctx)
00233 {
00234   // doesn't work on default bitmap!
00235   *ctx = nsnull;
00236 }
00237 
00238 NS_IMETHODIMP_(void)
00239 nsSVGLibartBitmapDefault::UnlockRenderingContext()
00240 {
00241   // doesn't work on default bitmap!
00242 }
00243 
00244 NS_IMETHODIMP_(void)
00245 nsSVGLibartBitmapDefault::Flush()
00246 {
00247   UnlockBuffer();
00248 
00249   nsCOMPtr<nsIDeviceContext> ctx;
00250   mRenderingContext->GetDeviceContext(*getter_AddRefs(ctx));
00251 
00252   nsCOMPtr<nsIInterfaceRequestor> ireq(do_QueryInterface(mBuffer));
00253   if (ireq) {
00254     nsCOMPtr<nsIImage> img(do_GetInterface(ireq));
00255 
00256     if (!img->GetIsRowOrderTopToBottom()) {
00257       // XXX we need to flip the image. This is silly. Blt should take
00258       // care of it
00259       int stride = img->GetLineStride();
00260       int height = GetHeight();
00261       PRUint8* bits = img->GetBits();
00262       PRUint8* rowbuf = new PRUint8[stride];
00263       for (int row=0; row<height/2; ++row) {
00264         memcpy(rowbuf, bits+row*stride, stride);
00265         memcpy(bits+row*stride, bits+(height-1-row)*stride, stride);
00266         memcpy(bits+(height-1-row)*stride, rowbuf, stride);
00267       }
00268       delete[] rowbuf;
00269     }
00270     
00271     nsRect r(0, 0, GetWidth(), GetHeight());
00272     img->ImageUpdated(ctx, nsImageUpdateFlags_kBitsChanged, &r);
00273   }
00274   
00275   mContainer->DecodingComplete();
00276   mRenderingContext->DrawTile(mContainer, mRectTwips.x, mRectTwips.y, &mRectTwips);
00277 }

Generated on Wed Sep 10 22:25:24 2003 for Mozilla SVG Project Rendering Backend by doxygen1.3