00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
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
00074 NS_DECL_ISUPPORTS
00075
00076
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
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
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
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
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
00235 *ctx = nsnull;
00236 }
00237
00238 NS_IMETHODIMP_(void)
00239 nsSVGLibartBitmapDefault::UnlockRenderingContext()
00240 {
00241
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
00258
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 }