Back to index

lightning-sunbird  0.9+nobinonly
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 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 "nsISVGLibartBitmap.h"
00042 #include "nsIRenderingContext.h"
00043 #include "nsIDeviceContext.h"
00044 #include "nsPresContext.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                 nsPresContext* 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                                nsPresContext* presContext,
00116                                const nsRect & rect)
00117 {
00118   mRenderingContext = ctx;
00119 
00120   float twipsPerPx;
00121   twipsPerPx = presContext->PixelsToTwips();
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                       nsPresContext* 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 #ifdef WIN32
00209   return PIXEL_FORMAT_24_BGR;
00210 #else
00211   return PIXEL_FORMAT_24_RGB;
00212 #endif
00213 }
00214 
00215 NS_IMETHODIMP_(int)
00216 nsSVGLibartBitmapDefault::GetLineStride()
00217 {
00218   PRUint32 bytesPerRow=0;
00219   mBuffer->GetImageBytesPerRow(&bytesPerRow);
00220   return (int) bytesPerRow;
00221 }
00222 
00223 NS_IMETHODIMP_(int)
00224 nsSVGLibartBitmapDefault::GetWidth()
00225 {
00226   return mRect.width; 
00227 }
00228 
00229 NS_IMETHODIMP_(int)
00230 nsSVGLibartBitmapDefault::GetHeight()
00231 {
00232   return mRect.height;
00233 }
00234 
00235 NS_IMETHODIMP_(void)
00236 nsSVGLibartBitmapDefault::LockRenderingContext(const nsRect& rect, nsIRenderingContext** ctx)
00237 {
00238   // doesn't work on default bitmap!
00239   *ctx = nsnull;
00240 }
00241 
00242 NS_IMETHODIMP_(void)
00243 nsSVGLibartBitmapDefault::UnlockRenderingContext()
00244 {
00245   // doesn't work on default bitmap!
00246 }
00247 
00248 NS_IMETHODIMP_(void)
00249 nsSVGLibartBitmapDefault::Flush()
00250 {
00251   UnlockBuffer();
00252 
00253   nsCOMPtr<nsIDeviceContext> ctx;
00254   mRenderingContext->GetDeviceContext(*getter_AddRefs(ctx));
00255 
00256   nsCOMPtr<nsIInterfaceRequestor> ireq(do_QueryInterface(mBuffer));
00257   if (ireq) {
00258     nsCOMPtr<nsIImage> img(do_GetInterface(ireq));
00259 
00260     if (!img->GetIsRowOrderTopToBottom()) {
00261       // XXX we need to flip the image. This is silly. Blt should take
00262       // care of it
00263       int stride = img->GetLineStride();
00264       int height = GetHeight();
00265       PRUint8* bits = img->GetBits();
00266       PRUint8* rowbuf = new PRUint8[stride];
00267       for (int row=0; row<height/2; ++row) {
00268         memcpy(rowbuf, bits+row*stride, stride);
00269         memcpy(bits+row*stride, bits+(height-1-row)*stride, stride);
00270         memcpy(bits+(height-1-row)*stride, rowbuf, stride);
00271       }
00272       delete[] rowbuf;
00273     }
00274     
00275     nsRect r(0, 0, GetWidth(), GetHeight());
00276     img->ImageUpdated(ctx, nsImageUpdateFlags_kBitsChanged, &r);
00277   }
00278   
00279   mContainer->DecodingComplete();
00280   mRenderingContext->DrawTile(mContainer, mRectTwips.x, mRectTwips.y, &mRectTwips);
00281 }