Bug 216682 - Eliminate DrawToImage p=Alfred Kayser <alfredkayser@nl.ibm.com> r=tor, sr=pavlov, a=pavlov
--- 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;