Bug 691754. Change the decoder constructor to use a c++ reference instead of a pointer. r=joe
authorJeff Muizelaar <jmuizelaar@mozilla.com>
Thu, 29 Sep 2011 09:17:13 -0400
changeset 80396 7eefb2f21c4c60a14c2e89a33024a199ce6eeab5
parent 80394 095174dc1a95fc394057ae8764f8f4c5e899f9c1
child 80397 344e0e0cabe451fd8d99f0b5729d8cd3b7121fa9
push id434
push userclegnitto@mozilla.com
push dateWed, 21 Dec 2011 12:10:54 +0000
treeherdermozilla-beta@bddb6ed8dd47 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjoe
bugs691754
milestone10.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 691754. Change the decoder constructor to use a c++ reference instead of a pointer. r=joe A raster image always outlives it's decoder so we can refer to it using a reference instead of a pointer.
image/decoders/nsBMPDecoder.cpp
image/decoders/nsBMPDecoder.h
image/decoders/nsGIFDecoder2.cpp
image/decoders/nsGIFDecoder2.h
image/decoders/nsICODecoder.cpp
image/decoders/nsICODecoder.h
image/decoders/nsIconDecoder.cpp
image/decoders/nsIconDecoder.h
image/decoders/nsJPEGDecoder.cpp
image/decoders/nsJPEGDecoder.h
image/decoders/nsPNGDecoder.cpp
image/decoders/nsPNGDecoder.h
image/src/Decoder.cpp
image/src/Decoder.h
image/src/RasterImage.cpp
--- a/image/decoders/nsBMPDecoder.cpp
+++ b/image/decoders/nsBMPDecoder.cpp
@@ -58,17 +58,17 @@ namespace imagelib {
 #ifdef PR_LOGGING
 PRLogModuleInfo *gBMPLog = PR_NewLogModule("BMPDecoder");
 #endif
 
 // Convert from row (1..height) to absolute line (0..height-1)
 #define LINE(row) ((mBIH.height < 0) ? (-mBIH.height - (row)) : ((row) - 1))
 #define PIXEL_OFFSET(row, col) (LINE(row) * mBIH.width + col)
 
-nsBMPDecoder::nsBMPDecoder(RasterImage *aImage, imgIDecoderObserver* aObserver)
+nsBMPDecoder::nsBMPDecoder(RasterImage &aImage, imgIDecoderObserver* aObserver)
  : Decoder(aImage, aObserver)
 {
   mColors = nsnull;
   mRow = nsnull;
   mImageData = nsnull;
   mCurPos = mPos = mNumColors = mRowBytes = 0;
   mOldLine = mCurLine = 1; // Otherwise decoder will never start
   mState = eRLEStateInitial;
@@ -336,38 +336,38 @@ nsBMPDecoder::WriteInternal(const char* 
                  ("BMP ALPHABITFIELDS only supports 16 or 32 bits per pixel\n"));
           PostDataError();
           return;
         }
 
         PRUint32 imageLength;
         if (mBIH.compression == BI_RLE8 || mBIH.compression == BI_RLE4 || 
             mBIH.compression == BI_ALPHABITFIELDS) {
-            rv = mImage->EnsureFrame(0, 0, 0, mBIH.width, real_height, 
-                                     gfxASurface::ImageFormatARGB32,
-                                     (PRUint8**)&mImageData, &imageLength);
+            rv = mImage.EnsureFrame(0, 0, 0, mBIH.width, real_height, 
+                                    gfxASurface::ImageFormatARGB32,
+                                    (PRUint8**)&mImageData, &imageLength);
         } else {
             // mRow is not used for RLE encoded images
             mRow = (PRUint8*)moz_malloc((mBIH.width * mBIH.bpp) / 8 + 4);
             // + 4 because the line is padded to a 4 bit boundary, but I don't want
             // to make exact calculations here, that's unnecessary.
             // Also, it compensates rounding error.
             if (!mRow) {
                 PostDecoderError(NS_ERROR_OUT_OF_MEMORY);
                 return;
             }
 
             if (mUseAlphaData) {
-              rv = mImage->EnsureFrame(0, 0, 0, mBIH.width, real_height, 
-                                       gfxASurface::ImageFormatARGB32,
-                                       (PRUint8**)&mImageData, &imageLength);
+              rv = mImage.EnsureFrame(0, 0, 0, mBIH.width, real_height, 
+                                      gfxASurface::ImageFormatARGB32,
+                                      (PRUint8**)&mImageData, &imageLength);
             } else {
-              rv = mImage->EnsureFrame(0, 0, 0, mBIH.width, real_height, 
-                                       gfxASurface::ImageFormatRGB24,
-                                       (PRUint8**)&mImageData, &imageLength);
+              rv = mImage.EnsureFrame(0, 0, 0, mBIH.width, real_height, 
+                                      gfxASurface::ImageFormatRGB24,
+                                      (PRUint8**)&mImageData, &imageLength);
             }
         }
         if (NS_FAILED(rv) || !mImageData) {
             PostDecoderError(NS_ERROR_FAILURE);
             return;
         }
 
         // Prepare for transparency
--- a/image/decoders/nsBMPDecoder.h
+++ b/image/decoders/nsBMPDecoder.h
@@ -54,17 +54,17 @@ class RasterImage;
 
 /**
  * Decoder for BMP-Files, as used by Windows and OS/2
  */
 class nsBMPDecoder : public Decoder
 {
 public:
 
-    nsBMPDecoder(RasterImage *aImage, imgIDecoderObserver* aObserver);
+    nsBMPDecoder(RasterImage &aImage, imgIDecoderObserver* aObserver);
     ~nsBMPDecoder();
 
     // Specifies whether or not the BMP file will contain alpha data
     // If set to true and the BMP is 32BPP, the alpha data will be
     // retrieved from the 4th byte of image data per pixel 
     void SetUseAlphaData(bool useAlphaData);
     // Obtains the bits per pixel from the internal BIH header
     PRInt32 GetBitsPerPixel() const;
--- a/image/decoders/nsGIFDecoder2.cpp
+++ b/image/decoders/nsGIFDecoder2.cpp
@@ -102,17 +102,17 @@ namespace imagelib {
     mGIFStruct.state = (s);            \
   PR_END_MACRO
 
 /* Get a 16-bit value stored in little-endian format */
 #define GETINT16(p)   ((p)[1]<<8|(p)[0])
 //////////////////////////////////////////////////////////////////////
 // GIF Decoder Implementation
 
-nsGIFDecoder2::nsGIFDecoder2(RasterImage *aImage, imgIDecoderObserver* aObserver)
+nsGIFDecoder2::nsGIFDecoder2(RasterImage &aImage, imgIDecoderObserver* aObserver)
   : Decoder(aImage, aObserver)
   , mCurrentRow(-1)
   , mLastFlushedRow(-1)
   , mImageData(nsnull)
   , mOldColor(0)
   , mCurrentFrame(-1)
   , mCurrentPass(0)
   , mLastFlushedPass(0)
@@ -145,17 +145,17 @@ nsGIFDecoder2::FinishInternal()
   // If the GIF got cut off, handle it anyway
   if (!IsSizeDecode() && mGIFOpen) {
     if (mCurrentFrame == mGIFStruct.images_decoded)
       EndImageFrame();
     PostDecodeDone();
     mGIFOpen = false;
   }
 
-  mImage->SetLoopCount(mGIFStruct.loop_count - 1);
+  mImage.SetLoopCount(mGIFStruct.loop_count - 1);
 }
 
 // Push any new rows according to mCurrentPass/mLastFlushedPass and
 // mCurrentRow/mLastFlushedRow.  Note: caller is responsible for
 // updating mlastFlushed{Row,Pass}.
 void
 nsGIFDecoder2::FlushImageData(PRUint32 fromRow, PRUint32 rows)
 {
@@ -211,45 +211,45 @@ nsresult nsGIFDecoder2::BeginImageFrame(
     format = gfxASurface::ImageFormatARGB32;
   else
     format = gfxASurface::ImageFormatRGB24;
 
   // Use correct format, RGB for first frame, PAL for following frames
   // and include transparency to allow for optimization of opaque images
   if (mGIFStruct.images_decoded) {
     // Image data is stored with original depth and palette
-    rv = mImage->EnsureFrame(mGIFStruct.images_decoded,
-                             mGIFStruct.x_offset, mGIFStruct.y_offset,
-                             mGIFStruct.width, mGIFStruct.height,
-                             format, aDepth, &mImageData, &imageDataLength,
-                             &mColormap, &mColormapSize);
+    rv = mImage.EnsureFrame(mGIFStruct.images_decoded,
+                            mGIFStruct.x_offset, mGIFStruct.y_offset,
+                            mGIFStruct.width, mGIFStruct.height,
+                            format, aDepth, &mImageData, &imageDataLength,
+                            &mColormap, &mColormapSize);
   } else {
     // Regardless of depth of input, image is decoded into 24bit RGB
-    rv = mImage->EnsureFrame(mGIFStruct.images_decoded,
-                             mGIFStruct.x_offset, mGIFStruct.y_offset,
-                             mGIFStruct.width, mGIFStruct.height,
-                             format, &mImageData, &imageDataLength);
+    rv = mImage.EnsureFrame(mGIFStruct.images_decoded,
+                            mGIFStruct.x_offset, mGIFStruct.y_offset,
+                            mGIFStruct.width, mGIFStruct.height,
+                            format, &mImageData, &imageDataLength);
   }
 
   if (NS_FAILED(rv))
     return rv;
 
-  mImage->SetFrameDisposalMethod(mGIFStruct.images_decoded,
-                                 mGIFStruct.disposal_method);
+  mImage.SetFrameDisposalMethod(mGIFStruct.images_decoded,
+                                mGIFStruct.disposal_method);
 
   // Tell the superclass we're starting a frame
   PostFrameStart();
 
   if (!mGIFStruct.images_decoded) {
     // Send a onetime invalidation for the first frame if it has a y-axis offset. 
     // Otherwise, the area may never be refreshed and the placeholder will remain
     // on the screen. (Bug 37589)
     if (mGIFStruct.y_offset > 0) {
       PRInt32 imgWidth;
-      mImage->GetWidth(&imgWidth);
+      mImage.GetWidth(&imgWidth);
       nsIntRect r(0, 0, imgWidth, mGIFStruct.y_offset);
       PostInvalidation(r);
     }
   }
 
   mCurrentFrame = mGIFStruct.images_decoded;
   return NS_OK;
 }
@@ -270,17 +270,17 @@ void nsGIFDecoder2::EndImageFrame()
     if (realFrameHeight < mGIFStruct.screen_height) {
       nsIntRect r(0, realFrameHeight,
                   mGIFStruct.screen_width,
                   mGIFStruct.screen_height - realFrameHeight);
       PostInvalidation(r);
     }
     // This transparency check is only valid for first frame
     if (mGIFStruct.is_transparent && !mSawTransparency) {
-      mImage->SetFrameHasNoAlpha(mGIFStruct.images_decoded);
+      mImage.SetFrameHasNoAlpha(mGIFStruct.images_decoded);
     }
   }
   mCurrentRow = mLastFlushedRow = -1;
   mCurrentPass = mLastFlushedPass = 0;
 
   // Only add frame if we have any rows at all
   if (mGIFStruct.rows_remaining != mGIFStruct.height) {
     if (mGIFStruct.rows_remaining && mGIFStruct.images_decoded) {
@@ -288,17 +288,17 @@ void nsGIFDecoder2::EndImageFrame()
       PRUint8 *rowp = mImageData + ((mGIFStruct.height - mGIFStruct.rows_remaining) * mGIFStruct.width);
       memset(rowp, 0, mGIFStruct.rows_remaining * mGIFStruct.width);
     }
 
     // We actually have the timeout information before we get the lzw encoded 
     // image data, at least according to the spec, but we delay in setting the 
     // timeout for the image until here to help ensure that we have the whole 
     // image frame decoded before we go off and try to display another frame.
-    mImage->SetFrameTimeout(mGIFStruct.images_decoded, mGIFStruct.delay_time);
+    mImage.SetFrameTimeout(mGIFStruct.images_decoded, mGIFStruct.delay_time);
   }
 
   // Unconditionally increment images_decoded, because we unconditionally
   // append frames in BeginImageFrame(). This ensures that images_decoded
   // always refers to the frame in mImage we're currently decoding,
   // even if some of them weren't decoded properly and thus are blank.
   mGIFStruct.images_decoded++;
 
--- a/image/decoders/nsGIFDecoder2.h
+++ b/image/decoders/nsGIFDecoder2.h
@@ -53,17 +53,17 @@ class RasterImage;
 
 //////////////////////////////////////////////////////////////////////
 // nsGIFDecoder2 Definition
 
 class nsGIFDecoder2 : public Decoder
 {
 public:
 
-  nsGIFDecoder2(RasterImage *aImage, imgIDecoderObserver* aObserver);
+  nsGIFDecoder2(RasterImage &aImage, imgIDecoderObserver* aObserver);
   ~nsGIFDecoder2();
 
   virtual void WriteInternal(const char* aBuffer, PRUint32 aCount);
   virtual void FinishInternal();
   virtual Telemetry::ID SpeedHistogram();
 
 private:
   /* These functions will be called when the decoder has a decoded row,
--- a/image/decoders/nsICODecoder.cpp
+++ b/image/decoders/nsICODecoder.cpp
@@ -94,17 +94,17 @@ nsICODecoder::GetNumColors()
     default:
       numColors = (PRUint16)-1;
     }
   }
   return numColors;
 }
 
 
-nsICODecoder::nsICODecoder(RasterImage *aImage, imgIDecoderObserver* aObserver)
+nsICODecoder::nsICODecoder(RasterImage &aImage, imgIDecoderObserver* aObserver)
  : Decoder(aImage, aObserver)
 {
   mPos = mImageOffset = mCurrIcon = mNumIcons = mBPP = mRowBytes = 0;
   mIsPNG = false;
   mRow = nsnull;
   mOldLine = mCurLine = 1; // Otherwise decoder will never start
 }
 
@@ -204,18 +204,18 @@ nsICODecoder::SetHotSpotIfCursor() {
     do_CreateInstance("@mozilla.org/supports-PRUint32;1");
   nsCOMPtr<nsISupportsPRUint32> intwrapy = 
     do_CreateInstance("@mozilla.org/supports-PRUint32;1");
 
   if (intwrapx && intwrapy) {
     intwrapx->SetData(mDirEntry.mXHotspot);
     intwrapy->SetData(mDirEntry.mYHotspot);
 
-    mImage->Set("hotspotX", intwrapx);
-    mImage->Set("hotspotY", intwrapy);
+    mImage.Set("hotspotX", intwrapx);
+    mImage.Set("hotspotY", intwrapy);
   }
 }
 
 void
 nsICODecoder::WriteInternal(const char* aBuffer, PRUint32 aCount)
 {
   NS_ABORT_IF_FALSE(!HasError(), "Shouldn't call WriteInternal after error!");
 
@@ -490,18 +490,17 @@ nsICODecoder::WriteInternal(const char* 
           if (!mRow) {
             PostDecoderError(NS_ERROR_OUT_OF_MEMORY);
             return;
           }
         }
 
         // Ensure memory has been allocated before decoding.
         NS_ABORT_IF_FALSE(mRow, "mRow is null");
-        NS_ABORT_IF_FALSE(mImage, "mImage is null");
-        if (!mRow || !mImage) {
+        if (!mRow) {
           PostDataError();
           return;
         }
 
         while (mCurLine > 0 && aCount > 0) {
           PRUint32 toCopy = NS_MIN(rowSize - mRowBytes, aCount);
           if (toCopy) {
             memcpy(mRow + mRowBytes, aBuffer, toCopy);
--- a/image/decoders/nsICODecoder.h
+++ b/image/decoders/nsICODecoder.h
@@ -53,17 +53,17 @@ namespace mozilla {
 namespace imagelib {
 
 class RasterImage;
 
 class nsICODecoder : public Decoder
 {
 public:
 
-  nsICODecoder(RasterImage *aImage, imgIDecoderObserver* aObserver);
+  nsICODecoder(RasterImage &aImage, imgIDecoderObserver* aObserver);
   virtual ~nsICODecoder();
 
   // Obtains the width of the icon directory entry
   PRUint32 GetRealWidth() const
   {
     return mDirEntry.mWidth == 0 ? 256 : mDirEntry.mWidth; 
   }
 
--- a/image/decoders/nsIconDecoder.cpp
+++ b/image/decoders/nsIconDecoder.cpp
@@ -45,17 +45,17 @@
 #include "nspr.h"
 #include "nsRect.h"
 
 #include "ImageErrors.h"
 
 namespace mozilla {
 namespace imagelib {
 
-nsIconDecoder::nsIconDecoder(RasterImage *aImage, imgIDecoderObserver* aObserver)
+nsIconDecoder::nsIconDecoder(RasterImage &aImage, imgIDecoderObserver* aObserver)
  : Decoder(aImage, aObserver),
    mWidth(-1),
    mHeight(-1),
    mPixBytesRead(0),
    mPixBytesTotal(0),
    mImageData(nsnull),
    mState(iconStateStart)
 {
@@ -109,19 +109,19 @@ nsIconDecoder::WriteInternal(const char 
 
         // If We're doing a size decode, we're done
         if (IsSizeDecode()) {
           mState = iconStateFinished;
           break;
         }
 
         // Add the frame and signal
-        rv = mImage->EnsureFrame(0, 0, 0, mWidth, mHeight,
-                                 gfxASurface::ImageFormatARGB32,
-                                 &mImageData, &mPixBytesTotal);
+        rv = mImage.EnsureFrame(0, 0, 0, mWidth, mHeight,
+                                gfxASurface::ImageFormatARGB32,
+                                &mImageData, &mPixBytesTotal);
         if (NS_FAILED(rv)) {
           PostDecoderError(rv);
           return;
         }
 
         // Tell the superclass we're starting a frame
         PostFrameStart();
 
--- a/image/decoders/nsIconDecoder.h
+++ b/image/decoders/nsIconDecoder.h
@@ -69,17 +69,17 @@ class RasterImage;
 //
 //
 //////////////////////////////////////////////////////////////////////////////////////////////
 
 class nsIconDecoder : public Decoder
 {
 public:
 
-  nsIconDecoder(RasterImage *aImage, imgIDecoderObserver* aObserver);
+  nsIconDecoder(RasterImage &aImage, imgIDecoderObserver* aObserver);
   virtual ~nsIconDecoder();
 
   virtual void WriteInternal(const char* aBuffer, PRUint32 aCount);
 
   PRUint8 mWidth;
   PRUint8 mHeight;
   PRUint32 mPixBytesRead;
   PRUint32 mPixBytesTotal;
--- a/image/decoders/nsJPEGDecoder.cpp
+++ b/image/decoders/nsJPEGDecoder.cpp
@@ -104,17 +104,17 @@ METHODDEF(boolean) fill_input_buffer (j_
 METHODDEF(void) skip_input_data (j_decompress_ptr jd, long num_bytes);
 METHODDEF(void) term_source (j_decompress_ptr jd);
 METHODDEF(void) my_error_exit (j_common_ptr cinfo);
 
 /* Normal JFIF markers can't have more bytes than this. */
 #define MAX_JPEG_MARKER_LENGTH  (((PRUint32)1 << 16) - 1)
 
 
-nsJPEGDecoder::nsJPEGDecoder(RasterImage *aImage, imgIDecoderObserver* aObserver)
+nsJPEGDecoder::nsJPEGDecoder(RasterImage &aImage, imgIDecoderObserver* aObserver)
  : Decoder(aImage, aObserver)
 {
   mState = JPEG_HEADER;
   mReading = true;
   mImageData = nsnull;
 
   mBytesToSkip = 0;
   memset(&mInfo, 0, sizeof(jpeg_decompress_struct));
@@ -387,19 +387,19 @@ nsJPEGDecoder::WriteInternal(const char 
      * when the image is a sequential JPEG.
      */
     mInfo.buffered_image = jpeg_has_multiple_scans(&mInfo);
 
     /* Used to set up image size so arrays can be allocated */
     jpeg_calc_output_dimensions(&mInfo);
 
     PRUint32 imagelength;
-    if (NS_FAILED(mImage->EnsureFrame(0, 0, 0, mInfo.image_width, mInfo.image_height,
-                                      gfxASurface::ImageFormatRGB24,
-                                      &mImageData, &imagelength))) {
+    if (NS_FAILED(mImage.EnsureFrame(0, 0, 0, mInfo.image_width, mInfo.image_height,
+                                     gfxASurface::ImageFormatRGB24,
+                                     &mImageData, &imagelength))) {
       mState = JPEG_ERROR;
       PostDecoderError(NS_ERROR_OUT_OF_MEMORY);
       PR_LOG(gJPEGDecoderAccountingLog, PR_LOG_DEBUG,
              ("} (could not initialize image frame)"));
       return;
     }
 
     PR_LOG(gJPEGDecoderAccountingLog, PR_LOG_DEBUG,
--- a/image/decoders/nsJPEGDecoder.h
+++ b/image/decoders/nsJPEGDecoder.h
@@ -81,17 +81,17 @@ typedef enum {
     JPEG_ERROR    
 } jstate;
 
 class RasterImage;
 
 class nsJPEGDecoder : public Decoder
 {
 public:
-  nsJPEGDecoder(RasterImage *aImage, imgIDecoderObserver* aObserver);
+  nsJPEGDecoder(RasterImage &aImage, imgIDecoderObserver* aObserver);
   virtual ~nsJPEGDecoder();
 
   virtual void InitInternal();
   virtual void WriteInternal(const char* aBuffer, PRUint32 aCount);
   virtual void FinishInternal();
 
   virtual Telemetry::ID SpeedHistogram();
   void NotifyDone();
--- a/image/decoders/nsPNGDecoder.cpp
+++ b/image/decoders/nsPNGDecoder.cpp
@@ -76,17 +76,17 @@ static PRLogModuleInfo *gPNGDecoderAccou
 #define WIDTH_OFFSET 16
 #define HEIGHT_OFFSET (WIDTH_OFFSET + 4)
 #define BYTES_NEEDED_FOR_DIMENSIONS (HEIGHT_OFFSET + 4)
 
 // First 8 bytes of a PNG file
 const PRUint8 
 nsPNGDecoder::pngSignatureBytes[] = { 137, 80, 78, 71, 13, 10, 26, 10 };
 
-nsPNGDecoder::nsPNGDecoder(RasterImage *aImage, imgIDecoderObserver* aObserver)
+nsPNGDecoder::nsPNGDecoder(RasterImage &aImage, imgIDecoderObserver* aObserver)
  : Decoder(aImage, aObserver),
    mPNG(nsnull), mInfo(nsnull),
    mCMSLine(nsnull), interlacebuf(nsnull),
    mInProfile(nsnull), mTransform(nsnull),
    mHeaderBuf(nsnull), mHeaderBytesRead(0),
    mChannels(0), mFrameIsHidden(false),
    mCMSMode(0), mDisablePremultipliedAlpha(false)
 {
@@ -112,19 +112,19 @@ nsPNGDecoder::~nsPNGDecoder()
 }
 
 // CreateFrame() is used for both simple and animated images
 void nsPNGDecoder::CreateFrame(png_uint_32 x_offset, png_uint_32 y_offset,
                                PRInt32 width, PRInt32 height,
                                gfxASurface::gfxImageFormat format)
 {
   PRUint32 imageDataLength;
-  nsresult rv = mImage->EnsureFrame(GetFrameCount(), x_offset, y_offset,
-                                    width, height, format,
-                                    &mImageData, &imageDataLength);
+  nsresult rv = mImage.EnsureFrame(GetFrameCount(), x_offset, y_offset,
+                                   width, height, format,
+                                   &mImageData, &imageDataLength);
   if (NS_FAILED(rv))
     longjmp(png_jmpbuf(mPNG), 5); // NS_ERROR_OUT_OF_MEMORY
 
   mFrameRect.x = x_offset;
   mFrameRect.y = y_offset;
   mFrameRect.width = width;
   mFrameRect.height = height;
 
@@ -135,17 +135,17 @@ void nsPNGDecoder::CreateFrame(png_uint_
 
   // Tell the superclass we're starting a frame
   PostFrameStart();
 
   PR_LOG(gPNGDecoderAccountingLog, PR_LOG_DEBUG,
          ("PNGDecoderAccounting: nsPNGDecoder::CreateFrame -- created "
           "image frame with %dx%d pixels in container %p",
           width, height,
-          mImage.get ()));
+          &mImage));
 
   mFrameHasNoAlpha = true;
 }
 
 #ifdef PNG_APNG_SUPPORTED
 // set timeout and frame disposal method for the current frame
 void nsPNGDecoder::SetAnimFrameInfo()
 {
@@ -167,52 +167,52 @@ void nsPNGDecoder::SetAnimFrameInfo()
       delay_den = 100; // so says the APNG spec
 
     // Need to cast delay_num to float to have a proper division and
     // the result to int to avoid compiler warning
     timeout = static_cast<PRInt32>
               (static_cast<PRFloat64>(delay_num) * 1000 / delay_den);
   }
 
-  PRUint32 numFrames = mImage->GetNumFrames();
+  PRUint32 numFrames = mImage.GetNumFrames();
 
-  mImage->SetFrameTimeout(numFrames - 1, timeout);
+  mImage.SetFrameTimeout(numFrames - 1, timeout);
 
   if (dispose_op == PNG_DISPOSE_OP_PREVIOUS)
-      mImage->SetFrameDisposalMethod(numFrames - 1,
-                                     RasterImage::kDisposeRestorePrevious);
+      mImage.SetFrameDisposalMethod(numFrames - 1,
+                                    RasterImage::kDisposeRestorePrevious);
   else if (dispose_op == PNG_DISPOSE_OP_BACKGROUND)
-      mImage->SetFrameDisposalMethod(numFrames - 1,
-                                     RasterImage::kDisposeClear);
+      mImage.SetFrameDisposalMethod(numFrames - 1,
+                                    RasterImage::kDisposeClear);
   else
-      mImage->SetFrameDisposalMethod(numFrames - 1,
-                                     RasterImage::kDisposeKeep);
+      mImage.SetFrameDisposalMethod(numFrames - 1,
+                                    RasterImage::kDisposeKeep);
 
   if (blend_op == PNG_BLEND_OP_SOURCE)
-      mImage->SetFrameBlendMethod(numFrames - 1, RasterImage::kBlendSource);
+      mImage.SetFrameBlendMethod(numFrames - 1, RasterImage::kBlendSource);
   /*else // 'over' is the default
-      mImage->SetFrameBlendMethod(numFrames - 1, RasterImage::kBlendOver); */
+      mImage.SetFrameBlendMethod(numFrames - 1, RasterImage::kBlendOver); */
 }
 #endif
 
 // set timeout and frame disposal method for the current frame
 void nsPNGDecoder::EndImageFrame()
 {
   if (mFrameIsHidden)
     return;
 
   PRUint32 numFrames = 1;
 #ifdef PNG_APNG_SUPPORTED
-  numFrames = mImage->GetNumFrames();
+  numFrames = mImage.GetNumFrames();
 
   // We can't use mPNG->num_frames_read as it may be one ahead.
   if (numFrames > 1) {
     // Tell the image renderer that the frame is complete
     if (mFrameHasNoAlpha)
-      mImage->SetFrameHasNoAlpha(numFrames - 1);
+      mImage.SetFrameHasNoAlpha(numFrames - 1);
 
     PostInvalidation(mFrameRect);
   }
 #endif
 
   PostFrameStop();
 }
 
@@ -791,17 +791,17 @@ nsPNGDecoder::row_callback(png_structp p
       break;
       default:
         longjmp(png_jmpbuf(decoder->mPNG), 1);
     }
 
     if (!rowHasNoAlpha)
       decoder->mFrameHasNoAlpha = false;
 
-    PRUint32 numFrames = decoder->mImage->GetNumFrames();
+    PRUint32 numFrames = decoder->mImage.GetNumFrames();
     if (numFrames <= 1) {
       // Only do incremental image display for the first frame
       // XXXbholley - this check should be handled in the superclass
       nsIntRect r(0, row_num, width, 1);
       decoder->PostInvalidation(r);
     }
   }
 }
@@ -851,17 +851,17 @@ nsPNGDecoder::end_callback(png_structp p
                static_cast<nsPNGDecoder*>(png_get_progressive_ptr(png_ptr));
 
   // We shouldn't get here if we've hit an error
   NS_ABORT_IF_FALSE(!decoder->HasError(), "Finishing up PNG but hit error!");
 
 #ifdef PNG_APNG_SUPPORTED
   if (png_get_valid(png_ptr, info_ptr, PNG_INFO_acTL)) {
     PRInt32 num_plays = png_get_num_plays(png_ptr, info_ptr);
-    decoder->mImage->SetLoopCount(num_plays - 1);
+    decoder->mImage.SetLoopCount(num_plays - 1);
   }
 #endif
 
   // Send final notifications
   decoder->EndImageFrame();
   decoder->PostDecodeDone();
 }
 
--- a/image/decoders/nsPNGDecoder.h
+++ b/image/decoders/nsPNGDecoder.h
@@ -54,17 +54,17 @@
 
 namespace mozilla {
 namespace imagelib {
 class RasterImage;
 
 class nsPNGDecoder : public Decoder
 {
 public:
-  nsPNGDecoder(RasterImage *aImage, imgIDecoderObserver* aObserver);
+  nsPNGDecoder(RasterImage &aImage, imgIDecoderObserver* aObserver);
   virtual ~nsPNGDecoder();
 
   virtual void InitInternal();
   virtual void WriteInternal(const char* aBuffer, PRUint32 aCount);
   virtual Telemetry::ID SpeedHistogram();
 
   void CreateFrame(png_uint_32 x_offset, png_uint_32 y_offset,
                    PRInt32 width, PRInt32 height,
--- a/image/src/Decoder.cpp
+++ b/image/src/Decoder.cpp
@@ -39,32 +39,28 @@
 #include "Decoder.h"
 #include "nsIServiceManager.h"
 #include "nsIConsoleService.h"
 #include "nsIScriptError.h"
 
 namespace mozilla {
 namespace imagelib {
 
-Decoder::Decoder(RasterImage *aImage, imgIDecoderObserver* aObserver)
-  : mDecodeFlags(0)
+Decoder::Decoder(RasterImage &aImage, imgIDecoderObserver* aObserver)
+  : mImage(aImage)
+  , mObserver(aObserver)
+  , mDecodeFlags(0)
   , mFrameCount(0)
   , mFailCode(NS_OK)
   , mInitialized(false)
   , mSizeDecode(false)
   , mInFrame(false)
   , mDecodeDone(false)
   , mDataError(false)
 {
-  // We should always have an image
-  NS_ABORT_IF_FALSE(aImage, "Can't initialize decoder without an image!");
-
-  // Save our paremeters
-  mImage = aImage;
-  mObserver = aObserver;
 }
 
 Decoder::~Decoder()
 {
   NS_WARN_IF_FALSE(!mInFrame, "Shutting down decoder mid-frame!");
   mInitialized = false;
 }
 
@@ -133,40 +129,40 @@ Decoder::Finish()
     // Log data errors to the error console
     nsCOMPtr<nsIConsoleService> consoleService =
       do_GetService(NS_CONSOLESERVICE_CONTRACTID);
     nsCOMPtr<nsIScriptError2> errorObject =
       do_CreateInstance(NS_SCRIPTERROR_CONTRACTID);
 
     if (consoleService && errorObject && !HasDecoderError()) {
       nsAutoString msg(NS_LITERAL_STRING("Image corrupt or truncated: ") +
-                       NS_ConvertASCIItoUTF16(mImage->GetURIString()));
+                       NS_ConvertASCIItoUTF16(mImage.GetURIString()));
 
       errorObject->InitWithWindowID
         (msg.get(),
-         NS_ConvertUTF8toUTF16(mImage->GetURIString()).get(),
+         NS_ConvertUTF8toUTF16(mImage.GetURIString()).get(),
          nsnull,
          0, 0, nsIScriptError::errorFlag,
-         "Image", mImage->InnerWindowID()
+         "Image", mImage.InnerWindowID()
          );
   
       nsCOMPtr<nsIScriptError> error = do_QueryInterface(errorObject);
       consoleService->LogMessage(error);
     }
 
     // If we only have a data error, see if things are worth salvaging
-    bool salvage = !HasDecoderError() && mImage->GetNumFrames();
+    bool salvage = !HasDecoderError() && mImage.GetNumFrames();
 
     // If we're salvaging, say we finished decoding
     if (salvage)
-      mImage->DecodingComplete();
+      mImage.DecodingComplete();
 
     // Fire teardown notifications
     if (mObserver) {
-      mObserver->OnStopContainer(nsnull, mImage);
+      mObserver->OnStopContainer(nsnull, &mImage);
       mObserver->OnStopDecode(nsnull, salvage ? NS_OK : NS_ERROR_FAILURE, nsnull);
     }
   }
 }
 
 void
 Decoder::FinishSharedDecoder()
 {
@@ -181,21 +177,21 @@ Decoder::FlushInvalidations()
   NS_ABORT_IF_FALSE(!HasDecoderError(),
                     "Not allowed to make more decoder calls after error!");
 
   // If we've got an empty invalidation rect, we have nothing to do
   if (mInvalidRect.IsEmpty())
     return;
 
   // Tell the image that it's been updated
-  mImage->FrameUpdated(mFrameCount - 1, mInvalidRect);
+  mImage.FrameUpdated(mFrameCount - 1, mInvalidRect);
 
   // Fire OnDataAvailable
   if (mObserver) {
-    bool isCurrentFrame = mImage->GetCurrentFrameIndex() == (mFrameCount - 1);
+    bool isCurrentFrame = mImage.GetCurrentFrameIndex() == (mFrameCount - 1);
     mObserver->OnDataAvailable(nsnull, isCurrentFrame, &mInvalidRect);
   }
 
   // Clear the invalidation rectangle
   mInvalidRect.SetEmpty();
 }
 
 /*
@@ -213,21 +209,21 @@ void Decoder::FinishInternal() { }
 void
 Decoder::PostSize(PRInt32 aWidth, PRInt32 aHeight)
 {
   // Validate
   NS_ABORT_IF_FALSE(aWidth >= 0, "Width can't be negative!");
   NS_ABORT_IF_FALSE(aHeight >= 0, "Height can't be negative!");
 
   // Tell the image
-  mImage->SetSize(aWidth, aHeight);
+  mImage.SetSize(aWidth, aHeight);
 
   // Notify the observer
   if (mObserver)
-    mObserver->OnStartContainer(nsnull, mImage);
+    mObserver->OnStartContainer(nsnull, &mImage);
 }
 
 void
 Decoder::PostFrameStart()
 {
   // We shouldn't already be mid-frame
   NS_ABORT_IF_FALSE(!mInFrame, "Starting new frame but not done with old one!");
 
@@ -238,17 +234,17 @@ Decoder::PostFrameStart()
 
   // Update our state to reflect the new frame
   mFrameCount++;
   mInFrame = true;
 
   // Decoder implementations should only call this method if they successfully
   // appended the frame to the image. So mFrameCount should always match that
   // reported by the Image.
-  NS_ABORT_IF_FALSE(mFrameCount == mImage->GetNumFrames(),
+  NS_ABORT_IF_FALSE(mFrameCount == mImage.GetNumFrames(),
                     "Decoder frame count doesn't match image's!");
 
   // Fire notification
   if (mObserver)
     mObserver->OnStartFrame(nsnull, mFrameCount - 1); // frame # is zero-indexed
 }
 
 void
@@ -282,19 +278,19 @@ void
 Decoder::PostDecodeDone()
 {
   NS_ABORT_IF_FALSE(!IsSizeDecode(), "Can't be done with decoding with size decode!");
   NS_ABORT_IF_FALSE(!mInFrame, "Can't be done decoding if we're mid-frame!");
   NS_ABORT_IF_FALSE(!mDecodeDone, "Decode already done!");
   mDecodeDone = true;
 
   // Notify
-  mImage->DecodingComplete();
+  mImage.DecodingComplete();
   if (mObserver) {
-    mObserver->OnStopContainer(nsnull, mImage);
+    mObserver->OnStopContainer(nsnull, &mImage);
     mObserver->OnStopDecode(nsnull, NS_OK, nsnull);
   }
 }
 
 void
 Decoder::PostDataError()
 {
   mDataError = true;
--- a/image/src/Decoder.h
+++ b/image/src/Decoder.h
@@ -45,17 +45,17 @@
 
 namespace mozilla {
 namespace imagelib {
 
 class Decoder
 {
 public:
 
-  Decoder(RasterImage* aImage, imgIDecoderObserver* aObserver);
+  Decoder(RasterImage& aImage, imgIDecoderObserver* aObserver);
   virtual ~Decoder();
 
   /**
    * Initialize an image decoder. Decoders may not be re-initialized.
    *
    * @param aContainer The image container to decode to.
    * @param aObserver The observer for decode notification events.
    *
@@ -196,17 +196,17 @@ protected:
   // Data errors are the fault of the source data, decoder errors are our fault
   void PostDataError();
   void PostDecoderError(nsresult aFailCode);
 
   /*
    * Member variables.
    *
    */
-  nsRefPtr<RasterImage> mImage;
+  RasterImage &mImage;
   nsCOMPtr<imgIDecoderObserver> mObserver;
 
   PRUint32 mDecodeFlags;
   bool mDecodeDone;
   bool mDataError;
 
 private:
   PRUint32 mFrameCount; // Number of frames, including anything in-progress
--- a/image/src/RasterImage.cpp
+++ b/image/src/RasterImage.cpp
@@ -2157,32 +2157,32 @@ RasterImage::InitDecoder(bool aDoSizeDec
   // Figure out which decoder we want
   eDecoderType type = GetDecoderType(mSourceDataMimeType.get());
   CONTAINER_ENSURE_TRUE(type != eDecoderType_unknown, NS_IMAGELIB_ERROR_NO_DECODER);
 
   nsCOMPtr<imgIDecoderObserver> observer(do_QueryReferent(mObserver));
   // Instantiate the appropriate decoder
   switch (type) {
     case eDecoderType_png:
-      mDecoder = new nsPNGDecoder(this, observer);
+      mDecoder = new nsPNGDecoder(*this, observer);
       break;
     case eDecoderType_gif:
-      mDecoder = new nsGIFDecoder2(this, observer);
+      mDecoder = new nsGIFDecoder2(*this, observer);
       break;
     case eDecoderType_jpeg:
-      mDecoder = new nsJPEGDecoder(this, observer);
+      mDecoder = new nsJPEGDecoder(*this, observer);
       break;
     case eDecoderType_bmp:
-      mDecoder = new nsBMPDecoder(this, observer);
+      mDecoder = new nsBMPDecoder(*this, observer);
       break;
     case eDecoderType_ico:
-      mDecoder = new nsICODecoder(this, observer);
+      mDecoder = new nsICODecoder(*this, observer);
       break;
     case eDecoderType_icon:
-      mDecoder = new nsIconDecoder(this, observer);
+      mDecoder = new nsIconDecoder(*this, observer);
       break;
     default:
       NS_ABORT_IF_FALSE(0, "Shouldn't get here!");
   }
 
   // Initialize the decoder
   mDecoder->SetSizeDecode(aDoSizeDecode);
   mDecoder->SetDecodeFlags(mFrameDecodeFlags);