Bug 216682 - Eliminate DrawToImage p=Alfred Kayser <alfredkayser@nl.ibm.com> r=tor, sr=pavlov, a=pavlov
authorasqueella@gmail.com
Sat, 25 Aug 2007 12:18:44 -0700
changeset 5275 b4cda3a9b6183709e74466fae26400676e54624e
parent 5274 d7d1cc3bceb6797601cc60a28c65976aba992744
child 5276 10e1f8f89aa9f9d53aa31a775d5f690b0cc919bf
push idunknown
push userunknown
push dateunknown
reviewerstor, pavlov, pavlov
bugs216682
milestone1.9a8pre
Bug 216682 - Eliminate DrawToImage p=Alfred Kayser <alfredkayser@nl.ibm.com> r=tor, sr=pavlov, a=pavlov
gfx/idl/gfxIImageFrame.idl
gfx/public/nsIImage.h
gfx/src/shared/gfxImageFrame.cpp
gfx/src/thebes/nsThebesImage.cpp
gfx/src/thebes/nsThebesImage.h
modules/libpr0n/src/imgContainer.cpp
modules/libpr0n/src/imgContainer.h
--- a/gfx/idl/gfxIImageFrame.idl
+++ b/gfx/idl/gfxIImageFrame.idl
@@ -52,17 +52,17 @@ native nsRectRef(nsIntRect &);
  * gfxIImageFrame interface
  *
  * All x, y, width, height values are in pixels.
  *
  * @author Tim Rowley <tor@cs.brown.edu>
  * @author Stuart Parmenter <pavlov@netscape.com>
  * @version 0.1
  */
-[scriptable, uuid(f6d00ee7-defc-4101-b2dc-e72cf4c37c3c)]
+[scriptable, uuid(2502c898-73bd-4da5-8fae-21cf7a492f64)]
 interface gfxIImageFrame : nsISupports
 {
   /**
    * Create a new \a aWidth x \a aHeight sized image.
    *
    * @param aX The x-offset from the origin of the gfxIImageContainer parent.
    * @param aY The y-offset from the origin of the gfxIImageContainer parent.
    * @param aWidth The width of the image to create.
@@ -184,25 +184,16 @@ interface gfxIImageFrame : nsISupports
    */
   void unlockAlphaData();
 
 
 
   /* GIF Specific methods.  These should be in a different class or interface. */
 
   /**
-   * Blit this frame into another frame. Used for GIF animation compositing
-   */
-  void drawTo(in gfxIImageFrame aDst,
-              in PRInt32 aDX,
-              in PRInt32 aDY,
-              in PRInt32 aDWidth,
-              in PRInt32 aDHeight);
-
-  /**
    * Represents the number of milliseconds until the next frame should be displayed.
    * @note -1 means that this frame should be displayed forever.
    */
   attribute long timeout;
 
   /* frame disposal method, used only by GIFs. Should probably subclass image frame
    * and image container for GIFs special needs, but for simplicity it is here for the
    * moment
--- a/gfx/public/nsIImage.h
+++ b/gfx/public/nsIImage.h
@@ -200,28 +200,16 @@ public:
    * @param aSourceRect  source rectangle, in image pixels
    * @param aDestRect  destination rectangle, in device pixels
    */
   NS_IMETHOD Draw(nsIRenderingContext &aContext,
                   const gfxRect &aSourceRect,
                   const gfxRect &aDestRect) = 0;
 
   /**
-   * BitBlit the entire (no cropping) nsIImage to another nsImage, the source and dest can be scaled
-   * @update - saari 03/08/01
-   * @param aDstImage  the nsImage to blit to
-   * @param aDX The destination horizontal location
-   * @param aDY The destination vertical location
-   * @param aDWidth The destination width of the pixelmap
-   * @param aDHeight The destination height of the pixelmap
-   * @return if TRUE, no errors
-   */
-  NS_IMETHOD DrawToImage(nsIImage* aDstImage, PRInt32 aDX, PRInt32 aDY, PRInt32 aDWidth, PRInt32 aDHeight) = 0;
-
-  /**
    * Get the alpha depth for the image mask
    * @update - lordpixel 2001/05/16
    * @return  the alpha mask depth for the image, ie, 0, 1 or 8
    */
   virtual PRInt8 GetAlphaDepth() = 0;
 
   /**
    * Return information about the bits for this structure
--- a/gfx/src/shared/gfxImageFrame.cpp
+++ b/gfx/src/shared/gfxImageFrame.cpp
@@ -441,31 +441,16 @@ NS_IMETHODIMP gfxImageFrame::LockAlphaDa
 NS_IMETHODIMP gfxImageFrame::UnlockAlphaData()
 {
   if (!mInitialized || !mImage->GetHasAlphaMask())
     return NS_ERROR_NOT_INITIALIZED;
 
   return mImage->UnlockImagePixels(PR_TRUE);
 }
 
-
-
-
-
-/* void drawTo */
-NS_IMETHODIMP gfxImageFrame::DrawTo(gfxIImageFrame* aDst, PRInt32 aDX, PRInt32 aDY, PRInt32 aDWidth, PRInt32 aDHeight)
-{
-  if (!mInitialized)
-    return NS_ERROR_NOT_INITIALIZED;
-
-  nsCOMPtr<nsIImage> img(do_GetInterface(aDst));
-  return mImage->DrawToImage(img, aDX, aDY, aDWidth, aDHeight);
-}
-
-
 /* attribute long timeout; */
 NS_IMETHODIMP gfxImageFrame::GetTimeout(PRInt32 *aTimeout)
 {
   if (!mInitialized)
     return NS_ERROR_NOT_INITIALIZED;
 
   // Ensure a minimal time between updates so we don't throttle the UI thread.
   // consider 0 == unspecified and make it fast but not too fast.  See bug
--- a/gfx/src/thebes/nsThebesImage.cpp
+++ b/gfx/src/thebes/nsThebesImage.cpp
@@ -557,38 +557,16 @@ nsThebesImage::ThebesDrawTile(gfxContext
     thebesContext->Rectangle(targetRect, doSnap);
     thebesContext->Fill();
 
     thebesContext->SetColor(gfxRGBA(0,0,0,0));
 
     return NS_OK;
 }
 
-/* This is only used by the GIF decoder, via gfxImageFrame::DrawTo */
-NS_IMETHODIMP
-nsThebesImage::DrawToImage(nsIImage* aDstImage, PRInt32 aDX, PRInt32 aDY, PRInt32 aDWidth, PRInt32 aDHeight)
-{
-    nsThebesImage *dstThebesImage = static_cast<nsThebesImage*>(aDstImage);
-
-    nsRefPtr<gfxContext> dst = new gfxContext(dstThebesImage->ThebesSurface());
-
-    dst->NewPath();
-    // We don't use PixelSnappedRectangleAndSetPattern because if
-    // these coords aren't already pixel aligned, we've lost
-    // before we've even begun.
-    dst->Translate(gfxPoint(aDX, aDY));
-    dst->Rectangle(gfxRect(0, 0, aDWidth, aDHeight), PR_TRUE);
-    dst->Scale(double(aDWidth)/mWidth, double(aDHeight)/mHeight);
-
-    dst->SetSource(ThebesSurface());
-    dst->Paint();
-
-    return NS_OK;
-}
-
 PRBool
 nsThebesImage::ShouldUseImageSurfaces()
 {
 #ifdef XP_WIN
     static const DWORD kGDIObjectsHighWaterMark = 7000;
 
     // at 7000 GDI objects, stop allocating normal images to make sure
     // we never hit the 10k hard limit.
--- a/gfx/src/thebes/nsThebesImage.h
+++ b/gfx/src/thebes/nsThebesImage.h
@@ -70,18 +70,16 @@ public:
     virtual PRBool GetIsImageComplete();
     virtual void ImageUpdated(nsIDeviceContext *aContext, PRUint8 aFlags, nsRect *aUpdateRect);
     virtual nsresult Optimize(nsIDeviceContext* aContext);
     virtual nsColorMap *GetColorMap();
 
     NS_IMETHOD Draw(nsIRenderingContext &aContext,
                     const gfxRect &aSourceRect,
                     const gfxRect &aDestRect);
-    NS_IMETHOD DrawToImage(nsIImage* aDstImage,
-                           PRInt32 aDX, PRInt32 aDY, PRInt32 aDWidth, PRInt32 aDHeight);
 
     nsresult ThebesDrawTile(gfxContext *thebesContext,
                             nsIDeviceContext* dx,
                             const gfxPoint& aOffset,
                             const gfxRect& aTileRect,
                             const PRInt32 aXPadding,
                             const PRInt32 aYPadding);
 
--- a/modules/libpr0n/src/imgContainer.cpp
+++ b/modules/libpr0n/src/imgContainer.cpp
@@ -658,18 +658,17 @@ nsresult imgContainer::DoComposite(gfxII
     // XXX If we had a method of drawing a section of a frame into another, we
     //     could optimize further:
     //     if aPrevFrameIndex == 1 && lastCompositedFrameIndex <> -1,
     //     only firstFrameRefreshArea needs to be drawn back to composite
     if (isFullPrevFrame) {
       CopyFrameImage(aPrevFrame, mAnim->compositingFrame);
     } else {
       ClearFrame(mAnim->compositingFrame);
-      aPrevFrame->DrawTo(mAnim->compositingFrame, prevFrameRect.x, prevFrameRect.y,
-                         prevFrameRect.width, prevFrameRect.height);
+      DrawFrameTo(aPrevFrame, mAnim->compositingFrame, prevFrameRect);
       needToBlankComposite = PR_FALSE;
     }
   }
 
   // Dispose of previous
   switch (prevFrameDisposalMethod) {
     case imgIContainer::kDisposeClear:
       if (needToBlankComposite) {
@@ -716,18 +715,17 @@ nsresult imgContainer::DoComposite(gfxII
                                               gfxIFormats::RGB_A1, 24);
       if (NS_FAILED(rv))
         return rv;
     }
     CopyFrameImage(mAnim->compositingFrame, mAnim->compositingPrevFrame);
   }
 
   // blit next frame into it's correct spot
-  aNextFrame->DrawTo(mAnim->compositingFrame, nextFrameRect.x, nextFrameRect.y,
-                     nextFrameRect.width, nextFrameRect.height);
+  DrawFrameTo(aNextFrame, mAnim->compositingFrame, nextFrameRect);
   // Set timeout of CompositeFrame to timeout of frame we just composed
   // Bug 177948
   PRInt32 timeout;
   aNextFrame->GetTimeout(&timeout);
   mAnim->compositingFrame->SetTimeout(timeout);
 
   if (isFullNextFrame && mAnimationMode == kNormalAnimMode && mLoopCount != 0) {
     // We have a composited full frame
@@ -790,17 +788,17 @@ void imgContainer::ClearFrame(gfxIImageF
   img->ImageUpdated(nsnull, nsImageUpdateFlags_kBitsChanged, &aRect);
 }
 
 
 //******************************************************************************
 // Whether we succeed or fail will not cause a crash, and there's not much
 // we can do about a failure, so there we don't return a nsresult
 PRBool imgContainer::CopyFrameImage(gfxIImageFrame *aSrcFrame,
-                                       gfxIImageFrame *aDstFrame)
+                                    gfxIImageFrame *aDstFrame)
 {
   PRUint8* aDataSrc;
   PRUint8* aDataDest;
   PRUint32 aDataLengthSrc;
   PRUint32 aDataLengthDest;
 
   if (!aSrcFrame || !aDstFrame)
     return PR_FALSE;
@@ -814,29 +812,61 @@ PRBool imgContainer::CopyFrameImage(gfxI
   if (!aDataDest || !aDataSrc || aDataLengthDest != aDataLengthSrc) {
     aDstFrame->UnlockImageData();
     return PR_FALSE;
   }
   memcpy(aDataDest, aDataSrc, aDataLengthSrc);
   aDstFrame->UnlockImageData();
 
   // Tell the image that it's data has been updated
-  nsCOMPtr<nsIInterfaceRequestor> ireq(do_QueryInterface(aDstFrame));
-  if (!ireq)
-    return PR_FALSE;
-  nsCOMPtr<nsIImage> img(do_GetInterface(ireq));
+  nsCOMPtr<nsIImage> img(do_GetInterface(aDstFrame));
   if (!img)
     return PR_FALSE;
   nsIntRect r;
   aDstFrame->GetRect(r);
   img->ImageUpdated(nsnull, nsImageUpdateFlags_kBitsChanged, &r);
 
   return PR_TRUE;
 }
 
+//******************************************************************************
+nsresult imgContainer::DrawFrameTo(gfxIImageFrame *aSrc,
+                                   gfxIImageFrame *aDst, 
+                                   nsIntRect& aDstRect)
+{
+  if (!aSrc || !aDst)
+    return NS_ERROR_NOT_INITIALIZED;
+
+  nsCOMPtr<nsIImage> srcImg(do_GetInterface(aSrc));
+  nsRefPtr<gfxASurface> srcSurf;
+  srcImg->GetSurface(getter_AddRefs(srcSurf));
+
+  nsCOMPtr<nsIImage> dstImg(do_GetInterface(aDst));
+  nsRefPtr<gfxASurface> dstSurf;
+  dstImg->GetSurface(getter_AddRefs(dstSurf));
+
+  gfxContext dst(dstSurf);
+  dst.NewPath();
+  // We don't use PixelSnappedRectangleAndSetPattern because if
+  // these coords aren't already pixel aligned, we've lost
+  // before we've even begun.
+  dst.Translate(gfxPoint(aDstRect.x, aDstRect.y));
+  dst.Rectangle(gfxRect(0, 0, aDstRect.width, aDstRect.height), PR_TRUE);
+
+  nsIntRect srcRect;
+  aSrc->GetRect(srcRect);
+  dst.Scale(double(aDstRect.width) / srcRect.width, 
+            double(aDstRect.height) / srcRect.height);
+  dst.SetSource(srcSurf);
+  dst.Paint();
+
+  return NS_OK;
+}
+
+
 /********* Methods to implement lazy allocation of nsIProperties object *************/
 NS_IMETHODIMP imgContainer::Get(const char *prop, const nsIID & iid, void * *result)
 {
   if (!mProperties)
     return NS_ERROR_FAILURE;
   return mProperties->Get(prop, iid, result);
 }
 
--- a/modules/libpr0n/src/imgContainer.h
+++ b/modules/libpr0n/src/imgContainer.h
@@ -266,16 +266,27 @@ private:
   
   //! @overload
   static void ClearFrame(gfxIImageFrame* aFrame, nsIntRect &aRect);
   
   //! Copy one gfxIImageFrame's image and mask into another
   static PRBool CopyFrameImage(gfxIImageFrame *aSrcFrame,
                                gfxIImageFrame *aDstFrame);
   
+  /** Draws one gfxIImageFrame's image to into another,
+   * at the position specified by aRect
+   *
+   * @param aSrcFrame  Frame providing the source image
+   * @param aDstFrame  Frame where the image is drawn into
+   * @param aRect      The position and size to draw the image
+   */
+  static nsresult DrawFrameTo(gfxIImageFrame *aSrcFrame,
+                              gfxIImageFrame *aDstFrame,
+                              nsIntRect& aRect);
+
   nsIntSize                  mSize;
   
   //! All the <gfxIImageFrame>s of the PNG
   nsCOMArray<gfxIImageFrame> mFrames;
   
   nsCOMPtr<nsIProperties>    mProperties;
   
   imgContainer::Anim*        mAnim;