Back to index

lightning-sunbird  0.9+nobinonly
nsSVGLibartBitmapMac.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 
00063 class nsSVGLibartBitmapMac : public nsISVGLibartBitmap
00064 {
00065 public:
00066   nsSVGLibartBitmapMac();
00067   ~nsSVGLibartBitmapMac();
00068   nsresult Init(nsIRenderingContext *ctx,
00069                 nsPresContext* presContext,
00070                 const nsRect & rect);
00071 
00072   // nsISupports interface:
00073   NS_DECL_ISUPPORTS
00074 
00075   // nsISVGLibartBitmap interface:
00076   NS_IMETHOD_(PRUint8 *) GetBits();
00077   NS_IMETHOD_(nsISVGLibartBitmap::PixelFormat) GetPixelFormat();
00078   NS_IMETHOD_(int) GetLineStride();
00079   NS_IMETHOD_(int) GetWidth();
00080   NS_IMETHOD_(int) GetHeight();
00081   NS_IMETHOD_(void) LockRenderingContext(const nsRect& rect, nsIRenderingContext**ctx);
00082   NS_IMETHOD_(void) UnlockRenderingContext();
00083   NS_IMETHOD_(void) Flush();
00084   
00085 private:
00086   void LockBuffer();
00087   void UnlockBuffer();
00088 
00089   PRBool mLocked;
00090   nsCOMPtr<nsIRenderingContext> mRenderingContext;
00091   nsCOMPtr<imgIContainer> mContainer;
00092   nsCOMPtr<gfxIImageFrame> mBuffer;
00093   nsRect mRectTwips;
00094   nsRect mRect;
00095 };
00096 
00099 //----------------------------------------------------------------------
00100 // implementation:
00101 
00102 nsSVGLibartBitmapMac::nsSVGLibartBitmapMac()
00103     : mLocked(PR_FALSE)
00104 {
00105 }
00106 
00107 nsSVGLibartBitmapMac::~nsSVGLibartBitmapMac()
00108 {
00109 
00110 }
00111 
00112 nsresult
00113 nsSVGLibartBitmapMac::Init(nsIRenderingContext* ctx,
00114                                nsPresContext* presContext,
00115                                const nsRect & rect)
00116 {
00117   mRenderingContext = ctx;
00118 
00119   float twipsPerPx;
00120   twipsPerPx = presContext->PixelsToTwips();
00121   mRectTwips.x = (nscoord)(rect.x*twipsPerPx);
00122   mRectTwips.y = (nscoord)(rect.y*twipsPerPx);
00123   mRectTwips.width = (nscoord)(rect.width*twipsPerPx);
00124   mRectTwips.height = (nscoord)(rect.height*twipsPerPx);
00125   mRect = rect;
00126   
00127   mContainer = do_CreateInstance("@mozilla.org/image/container;1");
00128   mContainer->Init(rect.width, rect.height, nsnull);
00129     
00130   mBuffer = do_CreateInstance("@mozilla.org/gfx/image/frame;2");
00131   // even though we request a 24bpp buffer, on the mac we get a 32bpp one...
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   nsSVGLibartBitmapMac* bm = new nsSVGLibartBitmapMac();
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(nsSVGLibartBitmapMac)
00164 NS_IMPL_RELEASE(nsSVGLibartBitmapMac)
00165 
00166 NS_INTERFACE_MAP_BEGIN(nsSVGLibartBitmapMac)
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 nsSVGLibartBitmapMac::LockBuffer()
00175 {
00176   if (mLocked) return;
00177 
00178   mBuffer->LockImageData();    
00179   mLocked = PR_TRUE;
00180 }
00181 
00182 void
00183 nsSVGLibartBitmapMac::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 nsSVGLibartBitmapMac::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 nsSVGLibartBitmapMac::GetPixelFormat()
00207 {
00208   return PIXEL_FORMAT_32_ABGR;
00209 }
00210 
00211 NS_IMETHODIMP_(int)
00212 nsSVGLibartBitmapMac::GetLineStride()
00213 {
00214   PRUint32 bytesPerRow=0;
00215   mBuffer->GetImageBytesPerRow(&bytesPerRow);
00216   return (int) bytesPerRow;
00217 }
00218 
00219 NS_IMETHODIMP_(int)
00220 nsSVGLibartBitmapMac::GetWidth()
00221 {
00222   return mRect.width; 
00223 }
00224 
00225 NS_IMETHODIMP_(int)
00226 nsSVGLibartBitmapMac::GetHeight()
00227 {
00228   return mRect.height;
00229 }
00230 
00231 NS_IMETHODIMP_(void)
00232 nsSVGLibartBitmapMac::LockRenderingContext(const nsRect& rect, nsIRenderingContext** ctx)
00233 {
00234   // doesn't work on default bitmap!
00235   *ctx = nsnull;
00236 }
00237 
00238 NS_IMETHODIMP_(void)
00239 nsSVGLibartBitmapMac::UnlockRenderingContext()
00240 {
00241   // doesn't work on default bitmap!
00242 }
00243 
00244 NS_IMETHODIMP_(void)
00245 nsSVGLibartBitmapMac::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     // need to flip the words
00257     int stride = img->GetLineStride();
00258     int height = GetHeight();
00259     int width = GetWidth();
00260     PRUint8* bits = img->GetBits();
00261     PRUint8* rowbuf = new PRUint8[stride];
00262     for (int row = 0; row < height; row++) {
00263       PRUint8 *src = bits + row * stride;
00264       PRUint8 *dst = rowbuf + 3;
00265       for (int x = 0; x < width; x++) {
00266         *dst-- = *src++;
00267         *dst-- = *src++;
00268         *dst-- = *src++;
00269         *dst   = *src++;
00270         dst += 7;
00271       }
00272       memcpy(bits + row * stride, rowbuf, stride);
00273     }
00274     delete[] rowbuf;
00275 
00276     nsRect r(0, 0, GetWidth(), GetHeight());
00277     img->ImageUpdated(ctx, nsImageUpdateFlags_kBitsChanged, &r);
00278   }
00279   
00280   mContainer->DecodingComplete();
00281   mRenderingContext->DrawTile(mContainer, mRectTwips.x, mRectTwips.y, &mRectTwips);
00282 }