diff --git a/mozilla/content/html/content/src/nsHTMLImageElement.cpp b/mozilla/content/html/content/src/nsHTMLImageElement.cpp
index ac36c8207d9..285f49875f3 100644
--- a/mozilla/content/html/content/src/nsHTMLImageElement.cpp
+++ b/mozilla/content/html/content/src/nsHTMLImageElement.cpp
@@ -50,8 +50,10 @@
#include "nsIWebShell.h"
#include "nsIFrame.h"
#include "nsImageFrame.h"
+#include "nsFrameImageLoader.h"
#include "nsLayoutAtoms.h"
#include "nsNodeInfoManager.h"
+#include "nsIFrameImageLoader.h"
static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID);
@@ -137,6 +139,14 @@ public:
protected:
nsGenericHTMLLeafElement mInner;
nsIDocument* mOwnerDocument; // Only used if this is a script constructed image
+
+ static nsresult ImageLibCallBack(nsIPresContext* aPresContext,
+ nsIFrameImageLoader* aLoader,
+ nsIFrame* aFrame,
+ void* aClosure,
+ PRUint32 aStatus);
+
+ nsCOMPtr mLoader;
};
nsresult
@@ -181,6 +191,9 @@ nsHTMLImageElement::nsHTMLImageElement(nsINodeInfo *aNodeInfo)
nsHTMLImageElement::~nsHTMLImageElement()
{
NS_IF_RELEASE(mOwnerDocument);
+
+ if (mLoader)
+ mLoader->RemoveFrame(this);
}
NS_IMPL_ADDREF(nsHTMLImageElement)
@@ -309,8 +322,12 @@ nsHTMLImageElement::GetComplete(PRBool* aComplete)
nsImageFrame* imageFrame;
result = GetImageFrame(&imageFrame);
- if (NS_SUCCEEDED(result)) {
+ if (NS_SUCCEEDED(result) && imageFrame) {
result = imageFrame->IsImageComplete(aComplete);
+ } else {
+ result = NS_OK;
+
+ *aComplete = !mLoader;
}
return NS_OK;
@@ -849,13 +866,70 @@ nsHTMLImageElement::GetSrc(nsAWritableString& aSrc)
return rv;
}
+nsresult nsHTMLImageElement::ImageLibCallBack(nsIPresContext* aPresContext,
+ nsIFrameImageLoader* aLoader,
+ nsIFrame* aFrame,
+ void* aClosure,
+ PRUint32 aStatus)
+{
+ nsHTMLImageElement *img = (nsHTMLImageElement *)aClosure;
+
+ if (!img || !img->mLoader)
+ return NS_OK;
+
+ if ((aStatus & NS_IMAGE_LOAD_STATUS_SIZE_AVAILABLE) &&
+ !(aStatus & NS_IMAGE_LOAD_STATUS_ERROR)) {
+ nsCOMPtr cx;
+ aLoader->GetPresContext(getter_AddRefs(cx));
+
+ float t2p;
+ cx->GetTwipsToPixels(&t2p);
+
+ nsSize size;
+ aLoader->GetSize(size);
+
+ nsAutoString tmpStr;
+ tmpStr.AppendInt(NSTwipsToIntPixels(size.width, t2p));
+ img->SetAttribute(kNameSpaceID_None, nsHTMLAtoms::width, tmpStr,
+ PR_FALSE);
+
+ tmpStr.Truncate();
+ tmpStr.AppendInt(NSTwipsToIntPixels(size.height, t2p));
+ img->SetAttribute(kNameSpaceID_None, nsHTMLAtoms::height, tmpStr,
+ PR_FALSE);
+ }
+
+ if (aStatus & (NS_IMAGE_LOAD_STATUS_IMAGE_READY |
+ NS_IMAGE_LOAD_STATUS_ERROR)) {
+ // We set mLoader = nsnull to indicate that we're complete.
+ img->mLoader->RemoveFrame(img);
+ img->mLoader = nsnull;
+
+ // Fire the onload event.
+ nsEventStatus status = nsEventStatus_eIgnore;
+ nsEvent event;
+ event.eventStructType = NS_EVENT;
+
+ if (aStatus & NS_IMAGE_LOAD_STATUS_IMAGE_READY) {
+ event.message = NS_IMAGE_LOAD;
+ } else {
+ event.message = NS_IMAGE_ERROR;
+ }
+
+ img->HandleDOMEvent(aPresContext, &event, nsnull, NS_EVENT_FLAG_INIT,
+ &status);
+ }
+
+ return NS_OK;
+}
+
+
nsresult
nsHTMLImageElement::SetSrcInner(nsIURI* aBaseURL, const nsAReadableString& aSrc)
{
nsresult result = NS_OK;
if (nsnull != mOwnerDocument) {
-
PRInt32 i, count = mOwnerDocument->GetNumberOfShells();
nsIPresShell* shell;
@@ -902,11 +976,17 @@ nsHTMLImageElement::SetSrcInner(nsIURI* aBaseURL, const nsAReadableString& aSrc)
specifiedSize = &size;
}
- // Start the image loading. We don't care about notification
- // or holding on to the image loader.
+ // If we have a loader we're in the middle of loading a image,
+ // we'll cancel that load and start a new one.
+ if (mLoader) {
+ mLoader->RemoveFrame(this);
+ }
+
+ // Start the image loading. We don't care about holding on to
+ // the image loader.
result = context->StartLoadImage(url, nsnull, specifiedSize,
- nsnull, nsnull, nsnull,
- nsnull);
+ nsnull, ImageLibCallBack, this, this,
+ getter_AddRefs(mLoader));
NS_RELEASE(context);
}
diff --git a/mozilla/layout/base/nsCSSRendering.cpp b/mozilla/layout/base/nsCSSRendering.cpp
index f254f026602..63cfb71afed 100644
--- a/mozilla/layout/base/nsCSSRendering.cpp
+++ b/mozilla/layout/base/nsCSSRendering.cpp
@@ -2096,13 +2096,13 @@ nsCSSRendering::PaintBackground(nsIPresContext* aPresContext,
nsCOMPtr image;
nsIFrameImageLoader* loader = nsnull;
nsresult rv = aPresContext->StartLoadImage(aColor.mBackgroundImage,
- transparentBG
- ? nsnull
- : &aColor.mBackgroundColor,
- nsnull,
- pBGFrame,
- nsnull, nsnull,
- &loader);
+ transparentBG
+ ? nsnull
+ : &aColor.mBackgroundColor,
+ nsnull,
+ pBGFrame,
+ nsnull, nsnull,
+ pBGFrame, &loader);
if ((NS_OK != rv) || (nsnull == loader) ||
(loader->GetImage(getter_AddRefs(image)), (!image))) {
NS_IF_RELEASE(loader);
diff --git a/mozilla/layout/base/nsFrameManager.cpp b/mozilla/layout/base/nsFrameManager.cpp
index f93c09748d0..9fa1916d57b 100644
--- a/mozilla/layout/base/nsFrameManager.cpp
+++ b/mozilla/layout/base/nsFrameManager.cpp
@@ -1292,7 +1292,7 @@ FrameManager::ReResolveStyleContext(nsIPresContext* aPresContext,
if(oldColor.mBackgroundImage.Length() > 0 &&
oldColor.mBackgroundImage != newColor.mBackgroundImage ){
// stop the image loading for the frame, the image has changed
- aPresContext->StopAllLoadImagesFor(aFrame);
+ aPresContext->StopAllLoadImagesFor(aFrame, aFrame);
}
}
else {
diff --git a/mozilla/layout/base/nsPresContext.cpp b/mozilla/layout/base/nsPresContext.cpp
index 8ad9a0e0464..0b056a7e838 100644
--- a/mozilla/layout/base/nsPresContext.cpp
+++ b/mozilla/layout/base/nsPresContext.cpp
@@ -880,6 +880,7 @@ nsPresContext::StartLoadImage(const nsString& aURL,
nsIFrame* aTargetFrame,
nsIFrameImageLoaderCB aCallBack,
void* aClosure,
+ void* aKey,
nsIFrameImageLoader** aResult)
{
if (mStopped) {
@@ -916,7 +917,7 @@ nsPresContext::StartLoadImage(const nsString& aURL,
}
// Add frame to list of interested frames for this loader
- loader->AddFrame(aTargetFrame, aCallBack, aClosure);
+ loader->AddFrame(aTargetFrame, aCallBack, aClosure, aKey);
return NS_OK;
}
}
@@ -963,7 +964,8 @@ nsPresContext::StartLoadImage(const nsString& aURL,
}
rv = loader->Init(this, mImageGroup, aURL, aBackgroundColor, aDesiredSize,
- aTargetFrame, mImageAnimationMode, aCallBack, aClosure);
+ aTargetFrame, mImageAnimationMode, aCallBack, aClosure,
+ aKey);
if (NS_OK != rv) {
mImageLoaders.RemoveElement(loader);
loader->StopImageLoad();
@@ -995,8 +997,7 @@ nsPresContext::Stop(void)
}
NS_IMETHODIMP
-nsPresContext::StopLoadImage(nsIFrame* aTargetFrame,
- nsIFrameImageLoader* aLoader)
+nsPresContext::StopLoadImage(void* aKey, nsIFrameImageLoader* aLoader)
{
PRInt32 i, n = mImageLoaders.Count();
nsIFrameImageLoader* loader;
@@ -1004,7 +1005,7 @@ nsPresContext::StopLoadImage(nsIFrame* aTargetFrame,
loader = (nsIFrameImageLoader*) mImageLoaders.ElementAt(i);
if (loader == aLoader) {
// Remove frame from list of interested frames for this loader
- loader->RemoveFrame(aTargetFrame);
+ loader->RemoveFrame(aKey);
// If loader is no longer loading for anybody and its safe to
// nuke it, nuke it.
@@ -1023,7 +1024,7 @@ nsPresContext::StopLoadImage(nsIFrame* aTargetFrame,
}
NS_IMETHODIMP
-nsPresContext::StopAllLoadImagesFor(nsIFrame* aTargetFrame)
+nsPresContext::StopAllLoadImagesFor(nsIFrame* aTargetFrame, void *aKey)
{
nsFrameState state;
aTargetFrame->GetFrameState(&state);
@@ -1033,7 +1034,7 @@ nsPresContext::StopAllLoadImagesFor(nsIFrame* aTargetFrame)
for (i = 0; i < n; i++) {
PRBool safe;
loader = (nsIFrameImageLoader*) mImageLoaders.ElementAt(i);
- loader->RemoveFrame(aTargetFrame);
+ loader->RemoveFrame(aKey);
loader->SafeToDestroy(&safe);
if (safe) {
loader->StopImageLoad();
diff --git a/mozilla/layout/base/nsPresContext.h b/mozilla/layout/base/nsPresContext.h
index 92c0435bec8..cc8086a8b4c 100644
--- a/mozilla/layout/base/nsPresContext.h
+++ b/mozilla/layout/base/nsPresContext.h
@@ -251,18 +251,19 @@ public:
nsIFrame* aTargetFrame,
nsIFrameImageLoaderCB aCallBack,
void* aClosure,
+ void* aKey,
nsIFrameImageLoader** aResult) = 0;
/**
* Stop a specific image load being done on behalf of the argument frame.
*/
- NS_IMETHOD StopLoadImage(nsIFrame* aForFrame,
+ NS_IMETHOD StopLoadImage(void* aKey,
nsIFrameImageLoader* aLoader) = 0;
/**
* Stop any image loading being done on behalf of the argument frame.
*/
- NS_IMETHOD StopAllLoadImagesFor(nsIFrame* aForFrame) = 0;
+ NS_IMETHOD StopAllLoadImagesFor(nsIFrame* aTargetFrame, void* aKey) = 0;
NS_IMETHOD SetContainer(nsISupports* aContainer) = 0;
diff --git a/mozilla/layout/base/public/nsIFrameImageLoader.h b/mozilla/layout/base/public/nsIFrameImageLoader.h
index 9161cbda426..7a3e13cdb8c 100644
--- a/mozilla/layout/base/public/nsIFrameImageLoader.h
+++ b/mozilla/layout/base/public/nsIFrameImageLoader.h
@@ -71,7 +71,7 @@ public:
nsIFrame* aFrame,
nsImageAnimation aAnimationMode,
nsIFrameImageLoaderCB aCallBack,
- void* aClosure) = 0;
+ void* aClosure, void* aKey) = 0;
NS_IMETHOD StopImageLoad() = 0;
@@ -83,9 +83,9 @@ public:
PRBool* aResult) = 0;
NS_IMETHOD AddFrame(nsIFrame* aFrame, nsIFrameImageLoaderCB aCallBack,
- void* aClosure) = 0;
+ void* aClosure, void* aKey) = 0;
- NS_IMETHOD RemoveFrame(nsIFrame* aFrame) = 0;
+ NS_IMETHOD RemoveFrame(void* aKey) = 0;
NS_IMETHOD SafeToDestroy(PRBool* aResult) = 0;
diff --git a/mozilla/layout/base/public/nsIPresContext.h b/mozilla/layout/base/public/nsIPresContext.h
index 92c0435bec8..cc8086a8b4c 100644
--- a/mozilla/layout/base/public/nsIPresContext.h
+++ b/mozilla/layout/base/public/nsIPresContext.h
@@ -251,18 +251,19 @@ public:
nsIFrame* aTargetFrame,
nsIFrameImageLoaderCB aCallBack,
void* aClosure,
+ void* aKey,
nsIFrameImageLoader** aResult) = 0;
/**
* Stop a specific image load being done on behalf of the argument frame.
*/
- NS_IMETHOD StopLoadImage(nsIFrame* aForFrame,
+ NS_IMETHOD StopLoadImage(void* aKey,
nsIFrameImageLoader* aLoader) = 0;
/**
* Stop any image loading being done on behalf of the argument frame.
*/
- NS_IMETHOD StopAllLoadImagesFor(nsIFrame* aForFrame) = 0;
+ NS_IMETHOD StopAllLoadImagesFor(nsIFrame* aTargetFrame, void* aKey) = 0;
NS_IMETHOD SetContainer(nsISupports* aContainer) = 0;
diff --git a/mozilla/layout/base/public/nsPresContext.h b/mozilla/layout/base/public/nsPresContext.h
index 92c0435bec8..cc8086a8b4c 100644
--- a/mozilla/layout/base/public/nsPresContext.h
+++ b/mozilla/layout/base/public/nsPresContext.h
@@ -251,18 +251,19 @@ public:
nsIFrame* aTargetFrame,
nsIFrameImageLoaderCB aCallBack,
void* aClosure,
+ void* aKey,
nsIFrameImageLoader** aResult) = 0;
/**
* Stop a specific image load being done on behalf of the argument frame.
*/
- NS_IMETHOD StopLoadImage(nsIFrame* aForFrame,
+ NS_IMETHOD StopLoadImage(void* aKey,
nsIFrameImageLoader* aLoader) = 0;
/**
* Stop any image loading being done on behalf of the argument frame.
*/
- NS_IMETHOD StopAllLoadImagesFor(nsIFrame* aForFrame) = 0;
+ NS_IMETHOD StopAllLoadImagesFor(nsIFrame* aTargetFrame, void* aKey) = 0;
NS_IMETHOD SetContainer(nsISupports* aContainer) = 0;
diff --git a/mozilla/layout/base/src/nsFrameImageLoader.cpp b/mozilla/layout/base/src/nsFrameImageLoader.cpp
index eb2ed5a578f..8f1453b94b5 100644
--- a/mozilla/layout/base/src/nsFrameImageLoader.cpp
+++ b/mozilla/layout/base/src/nsFrameImageLoader.cpp
@@ -124,7 +124,8 @@ nsFrameImageLoader::Init(nsIPresContext* aPresContext,
nsIFrame* aTargetFrame,
nsImageAnimation aAnimationMode,
nsIFrameImageLoaderCB aCallBack,
- void* aClosure)
+ void* aClosure,
+ void* aKey)
{
NS_PRECONDITION(nsnull != aPresContext, "null ptr");
if (nsnull == aPresContext) {
@@ -162,16 +163,17 @@ nsFrameImageLoader::Init(nsIPresContext* aPresContext,
desiredHeight = NSToCoordRound((mDesiredSize.height * t2p)/devScale);
}
- if (nsnull != aTargetFrame) {
+ if (aTargetFrame || aCallBack) {
PerFrameData* pfd = new PerFrameData;
if (nsnull == pfd) {
return NS_ERROR_OUT_OF_MEMORY;
}
pfd->mFrame = aTargetFrame;
+ pfd->mKey = aKey;
pfd->mCallBack = aCallBack;
pfd->mClosure = aClosure;
pfd->mNext = mFrames;
- pfd->mNeedSizeUpdate = PR_TRUE;
+ pfd->mNeedSizeUpdate = aTargetFrame ? PR_TRUE : PR_FALSE;
mFrames = pfd;
}
@@ -187,11 +189,12 @@ nsFrameImageLoader::Init(nsIPresContext* aPresContext,
NS_IMETHODIMP
nsFrameImageLoader::AddFrame(nsIFrame* aFrame,
nsIFrameImageLoaderCB aCallBack,
- void* aClosure)
+ void* aClosure,
+ void* aKey)
{
PerFrameData* pfd = mFrames;
while (pfd) {
- if (pfd->mFrame == aFrame) {
+ if (pfd->mKey == aKey) {
pfd->mCallBack = aCallBack;
pfd->mClosure = aClosure;
return NS_OK;
@@ -199,42 +202,41 @@ nsFrameImageLoader::AddFrame(nsIFrame* aFrame,
pfd = pfd->mNext;
}
- if (nsnull != aFrame) {
- pfd = new PerFrameData;
- if (nsnull == pfd) {
- return NS_ERROR_OUT_OF_MEMORY;
- }
- pfd->mFrame = aFrame;
- pfd->mCallBack = aCallBack;
- pfd->mClosure = aClosure;
- pfd->mNext = mFrames;
- pfd->mNeedSizeUpdate = PR_TRUE;
- mFrames = pfd;
- if (aCallBack && mPresContext &&
- ((NS_IMAGE_LOAD_STATUS_SIZE_AVAILABLE |
- NS_IMAGE_LOAD_STATUS_ERROR) & mImageLoadStatus)) {
- // Fire notification callback right away so that caller doesn't
- // miss it...
+ pfd = new PerFrameData;
+ if (nsnull == pfd) {
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+ pfd->mFrame = aFrame;
+ pfd->mKey = aKey;
+ pfd->mCallBack = aCallBack;
+ pfd->mClosure = aClosure;
+ pfd->mNext = mFrames;
+ pfd->mNeedSizeUpdate = PR_TRUE;
+ mFrames = pfd;
+ if (aCallBack && mPresContext &&
+ ((NS_IMAGE_LOAD_STATUS_SIZE_AVAILABLE |
+ NS_IMAGE_LOAD_STATUS_ERROR) & mImageLoadStatus)) {
+ // Fire notification callback right away so that caller doesn't
+ // miss it...
#ifdef NOISY_IMAGE_LOADING
- printf("%p: AddFrame: notify frame=%p status=%x\n",
- this, pfd->mFrame, mImageLoadStatus);
+ printf("%p: AddFrame: notify frame=%p status=%x\n",
+ this, pfd->mFrame, mImageLoadStatus);
#endif
- (*aCallBack)(mPresContext, this, pfd->mFrame, pfd->mClosure,
- mImageLoadStatus);
- pfd->mNeedSizeUpdate = PR_FALSE;
- }
+ (*aCallBack)(mPresContext, this, pfd->mFrame, pfd->mClosure,
+ mImageLoadStatus);
+ pfd->mNeedSizeUpdate = PR_FALSE;
}
return NS_OK;
}
NS_IMETHODIMP
-nsFrameImageLoader::RemoveFrame(nsIFrame* aFrame)
+nsFrameImageLoader::RemoveFrame(void* aKey)
{
PerFrameData** pfdp = &mFrames;
PerFrameData* pfd;
while (nsnull != (pfd = *pfdp)) {
- if (pfd->mFrame == aFrame) {
+ if (pfd->mKey == aKey) {
*pfdp = pfd->mNext;
delete pfd;
return NS_OK;
@@ -494,9 +496,11 @@ nsFrameImageLoader::Notify(nsIImageRequest *aImageRequest,
// XXX this is pretty vile; change this so that we set another frame status bit and then pass on a notification *or* lets just start passing on the notifications directly to the frames and eliminate all of this code.
pfd = mFrames;
while (pfd) {
- pfd->mFrame->GetView(mPresContext, &view);
- if (view) {
- view->SetContentTransparency(PR_TRUE);
+ if (pfd->mFrame) {
+ pfd->mFrame->GetView(mPresContext, &view);
+ if (view) {
+ view->SetContentTransparency(PR_TRUE);
+ }
}
pfd = pfd->mNext;
}
@@ -567,52 +571,39 @@ nsFrameImageLoader::DamageRepairFrames(const nsRect* aDamageRect)
while (nsnull != pfd) {
nsIFrame* frame = pfd->mFrame;
- // NOTE: It is not sufficient to invalidate only the size of the image:
- // the image may be tiled!
- // The best option is to call into the frame, however lacking this
- // we have to at least invalidate the frame's bounds, hence
- // as long as we have a frame we'll use its size.
- //
- // XXX - Add a NotifyImageLoaded to nsIFrame and call that, passing the
- // damage rect (image size)
-
- NS_ASSERTION(frame, "Frame should not be null and be remembered");
if (frame) {
+ // NOTE: It is not sufficient to invalidate only the size of the image:
+ // the image may be tiled!
+ // The best option is to call into the frame, however lacking this
+ // we have to at least invalidate the frame's bounds, hence
+ // as long as we have a frame we'll use its size.
+ //
+ // XXX - Add a NotifyImageLoaded to nsIFrame and call that, passing the
+ // damage rect (image size)
+
// Invalidate the entire frame
// XXX We really only need to invalidate the client area of the frame...
frame->GetRect(bounds);
bounds.x = bounds.y = 0;
- }
- else {
- // aDamageRect represents the part of the content area that
- // needs updating.
- bounds = *aDamageRect;
- // Offset damage origin by border/padding
- // XXX This is pretty sleazy. See the XXX remark below...
- const nsStyleSpacing* space;
- nsMargin borderPadding;
- frame->GetStyleData(eStyleStruct_Spacing, (const nsStyleStruct*&)space);
- space->CalcBorderPaddingFor(frame, borderPadding);
- bounds.MoveBy(borderPadding.left, borderPadding.top);
+ // XXX We should tell the frame the damage area and let it invalidate
+ // itself. Add some API calls to nsIFrame to allow a caller to invalidate
+ // parts of the frame...
+ frame->GetView(mPresContext, &view);
+ if (nsnull == view) {
+ frame->GetOffsetFromView(mPresContext, offset, &view);
+ bounds.x += offset.x;
+ bounds.y += offset.y;
+ }
+
+ nsCOMPtr vm = nsnull;
+ nsresult rv = NS_OK;
+ rv = view->GetViewManager(*getter_AddRefs(vm));
+ if (NS_SUCCEEDED(rv) && nsnull != vm) {
+ vm->UpdateView(view, bounds, NS_VMREFRESH_NO_SYNC);
+ }
}
- // XXX We should tell the frame the damage area and let it invalidate
- // itself. Add some API calls to nsIFrame to allow a caller to invalidate
- // parts of the frame...
- frame->GetView(mPresContext, &view);
- if (nsnull == view) {
- frame->GetOffsetFromView(mPresContext, offset, &view);
- bounds.x += offset.x;
- bounds.y += offset.y;
- }
-
- nsCOMPtr vm = nsnull;
- nsresult rv = NS_OK;
- rv = view->GetViewManager(*getter_AddRefs(vm));
- if (NS_SUCCEEDED(rv) && nsnull != vm) {
- vm->UpdateView(view, bounds, NS_VMREFRESH_NO_SYNC);
- }
pfd = pfd->mNext;
}
}
diff --git a/mozilla/layout/base/src/nsFrameImageLoader.h b/mozilla/layout/base/src/nsFrameImageLoader.h
index 191de942c34..8e57fda9d1e 100644
--- a/mozilla/layout/base/src/nsFrameImageLoader.h
+++ b/mozilla/layout/base/src/nsFrameImageLoader.h
@@ -59,7 +59,7 @@ public:
nsIFrame* aTargetFrame,
nsImageAnimation aAnimationMode,
nsIFrameImageLoaderCB aCallBack,
- void* aClosure);
+ void* aClosure, void* aKey);
NS_IMETHOD StopImageLoad();
@@ -71,9 +71,9 @@ public:
PRBool* aResult);
NS_IMETHOD AddFrame(nsIFrame* aFrame, nsIFrameImageLoaderCB aCallBack,
- void* aClosure);
+ void* aClosure, void* aKey);
- NS_IMETHOD RemoveFrame(nsIFrame* aFrame);
+ NS_IMETHOD RemoveFrame(void* aKey);
// See if its safe to destroy this image loader. Its safe if there
// are no more frames using the loader and we aren't in the middle
@@ -122,6 +122,7 @@ protected:
nsIFrame* mFrame;
nsIFrameImageLoaderCB mCallBack;
void* mClosure;
+ void* mKey;
PRBool mNeedSizeUpdate;
};
PerFrameData* mFrames;
diff --git a/mozilla/layout/base/src/nsPresContext.cpp b/mozilla/layout/base/src/nsPresContext.cpp
index 8ad9a0e0464..0b056a7e838 100644
--- a/mozilla/layout/base/src/nsPresContext.cpp
+++ b/mozilla/layout/base/src/nsPresContext.cpp
@@ -880,6 +880,7 @@ nsPresContext::StartLoadImage(const nsString& aURL,
nsIFrame* aTargetFrame,
nsIFrameImageLoaderCB aCallBack,
void* aClosure,
+ void* aKey,
nsIFrameImageLoader** aResult)
{
if (mStopped) {
@@ -916,7 +917,7 @@ nsPresContext::StartLoadImage(const nsString& aURL,
}
// Add frame to list of interested frames for this loader
- loader->AddFrame(aTargetFrame, aCallBack, aClosure);
+ loader->AddFrame(aTargetFrame, aCallBack, aClosure, aKey);
return NS_OK;
}
}
@@ -963,7 +964,8 @@ nsPresContext::StartLoadImage(const nsString& aURL,
}
rv = loader->Init(this, mImageGroup, aURL, aBackgroundColor, aDesiredSize,
- aTargetFrame, mImageAnimationMode, aCallBack, aClosure);
+ aTargetFrame, mImageAnimationMode, aCallBack, aClosure,
+ aKey);
if (NS_OK != rv) {
mImageLoaders.RemoveElement(loader);
loader->StopImageLoad();
@@ -995,8 +997,7 @@ nsPresContext::Stop(void)
}
NS_IMETHODIMP
-nsPresContext::StopLoadImage(nsIFrame* aTargetFrame,
- nsIFrameImageLoader* aLoader)
+nsPresContext::StopLoadImage(void* aKey, nsIFrameImageLoader* aLoader)
{
PRInt32 i, n = mImageLoaders.Count();
nsIFrameImageLoader* loader;
@@ -1004,7 +1005,7 @@ nsPresContext::StopLoadImage(nsIFrame* aTargetFrame,
loader = (nsIFrameImageLoader*) mImageLoaders.ElementAt(i);
if (loader == aLoader) {
// Remove frame from list of interested frames for this loader
- loader->RemoveFrame(aTargetFrame);
+ loader->RemoveFrame(aKey);
// If loader is no longer loading for anybody and its safe to
// nuke it, nuke it.
@@ -1023,7 +1024,7 @@ nsPresContext::StopLoadImage(nsIFrame* aTargetFrame,
}
NS_IMETHODIMP
-nsPresContext::StopAllLoadImagesFor(nsIFrame* aTargetFrame)
+nsPresContext::StopAllLoadImagesFor(nsIFrame* aTargetFrame, void *aKey)
{
nsFrameState state;
aTargetFrame->GetFrameState(&state);
@@ -1033,7 +1034,7 @@ nsPresContext::StopAllLoadImagesFor(nsIFrame* aTargetFrame)
for (i = 0; i < n; i++) {
PRBool safe;
loader = (nsIFrameImageLoader*) mImageLoaders.ElementAt(i);
- loader->RemoveFrame(aTargetFrame);
+ loader->RemoveFrame(aKey);
loader->SafeToDestroy(&safe);
if (safe) {
loader->StopImageLoad();
diff --git a/mozilla/layout/base/src/nsPresContext.h b/mozilla/layout/base/src/nsPresContext.h
index 8a948eeb9ec..d2c26ea54d2 100644
--- a/mozilla/layout/base/src/nsPresContext.h
+++ b/mozilla/layout/base/src/nsPresContext.h
@@ -120,9 +120,10 @@ public:
nsIFrame* aTargetFrame,
nsIFrameImageLoaderCB aCallBack,
void* aClosure,
+ void* aKey,
nsIFrameImageLoader** aResult);
- NS_IMETHOD StopLoadImage(nsIFrame* aForFrame, nsIFrameImageLoader* aLoader);
- NS_IMETHOD StopAllLoadImagesFor(nsIFrame* aForFrame);
+ NS_IMETHOD StopLoadImage(void* aKey, nsIFrameImageLoader* aLoader);
+ NS_IMETHOD StopAllLoadImagesFor(nsIFrame* aTargetFrame, void* aKey);
NS_IMETHOD SetContainer(nsISupports* aContainer);
NS_IMETHOD GetContainer(nsISupports** aResult);
NS_IMETHOD SetLinkHandler(nsILinkHandler* aHandler);
diff --git a/mozilla/layout/generic/nsFrame.cpp b/mozilla/layout/generic/nsFrame.cpp
index 1ae32ea22ed..88eb6072289 100644
--- a/mozilla/layout/generic/nsFrame.cpp
+++ b/mozilla/layout/generic/nsFrame.cpp
@@ -409,7 +409,7 @@ nsFrame::Destroy(nsIPresContext* aPresContext)
//XXX Why is this done in nsFrame instead of some frame class
// that actually loads images?
- aPresContext->StopAllLoadImagesFor(this);
+ aPresContext->StopAllLoadImagesFor(this, this);
if (view) {
// Break association between view and frame
diff --git a/mozilla/layout/html/base/src/nsFrame.cpp b/mozilla/layout/html/base/src/nsFrame.cpp
index 1ae32ea22ed..88eb6072289 100644
--- a/mozilla/layout/html/base/src/nsFrame.cpp
+++ b/mozilla/layout/html/base/src/nsFrame.cpp
@@ -409,7 +409,7 @@ nsFrame::Destroy(nsIPresContext* aPresContext)
//XXX Why is this done in nsFrame instead of some frame class
// that actually loads images?
- aPresContext->StopAllLoadImagesFor(this);
+ aPresContext->StopAllLoadImagesFor(this, this);
if (view) {
// Break association between view and frame
diff --git a/mozilla/layout/html/base/src/nsFrameManager.cpp b/mozilla/layout/html/base/src/nsFrameManager.cpp
index f93c09748d0..9fa1916d57b 100644
--- a/mozilla/layout/html/base/src/nsFrameManager.cpp
+++ b/mozilla/layout/html/base/src/nsFrameManager.cpp
@@ -1292,7 +1292,7 @@ FrameManager::ReResolveStyleContext(nsIPresContext* aPresContext,
if(oldColor.mBackgroundImage.Length() > 0 &&
oldColor.mBackgroundImage != newColor.mBackgroundImage ){
// stop the image loading for the frame, the image has changed
- aPresContext->StopAllLoadImagesFor(aFrame);
+ aPresContext->StopAllLoadImagesFor(aFrame, aFrame);
}
}
else {
diff --git a/mozilla/layout/html/base/src/nsHTMLImageLoader.cpp b/mozilla/layout/html/base/src/nsHTMLImageLoader.cpp
index 32cd4485d78..c6250ecc456 100644
--- a/mozilla/layout/html/base/src/nsHTMLImageLoader.cpp
+++ b/mozilla/layout/html/base/src/nsHTMLImageLoader.cpp
@@ -107,7 +107,7 @@ nsHTMLImageLoader::StopLoadImage(nsIPresContext* aPresContext)
void
nsHTMLImageLoader::StopAllLoadImages(nsIPresContext* aPresContext)
{
- aPresContext->StopAllLoadImagesFor(mFrame);
+ aPresContext->StopAllLoadImagesFor(mFrame, mFrame);
}
nsresult
@@ -203,7 +203,7 @@ nsHTMLImageLoader::StartLoadImage(nsIPresContext* aPresContext)
nsresult rv = aPresContext->StartLoadImage(*urlSpec, nsnull,
sizeToLoadWidth,
mFrame, ImageLoadCB, (void*)this,
- &mImageLoader);
+ mFrame, &mImageLoader);
#ifdef NOISY_IMAGE_LOADING
nsFrame::ListTag(stdout, mFrame);
printf(": loading image '");
diff --git a/mozilla/layout/html/content/src/nsHTMLImageElement.cpp b/mozilla/layout/html/content/src/nsHTMLImageElement.cpp
index ac36c8207d9..285f49875f3 100644
--- a/mozilla/layout/html/content/src/nsHTMLImageElement.cpp
+++ b/mozilla/layout/html/content/src/nsHTMLImageElement.cpp
@@ -50,8 +50,10 @@
#include "nsIWebShell.h"
#include "nsIFrame.h"
#include "nsImageFrame.h"
+#include "nsFrameImageLoader.h"
#include "nsLayoutAtoms.h"
#include "nsNodeInfoManager.h"
+#include "nsIFrameImageLoader.h"
static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID);
@@ -137,6 +139,14 @@ public:
protected:
nsGenericHTMLLeafElement mInner;
nsIDocument* mOwnerDocument; // Only used if this is a script constructed image
+
+ static nsresult ImageLibCallBack(nsIPresContext* aPresContext,
+ nsIFrameImageLoader* aLoader,
+ nsIFrame* aFrame,
+ void* aClosure,
+ PRUint32 aStatus);
+
+ nsCOMPtr mLoader;
};
nsresult
@@ -181,6 +191,9 @@ nsHTMLImageElement::nsHTMLImageElement(nsINodeInfo *aNodeInfo)
nsHTMLImageElement::~nsHTMLImageElement()
{
NS_IF_RELEASE(mOwnerDocument);
+
+ if (mLoader)
+ mLoader->RemoveFrame(this);
}
NS_IMPL_ADDREF(nsHTMLImageElement)
@@ -309,8 +322,12 @@ nsHTMLImageElement::GetComplete(PRBool* aComplete)
nsImageFrame* imageFrame;
result = GetImageFrame(&imageFrame);
- if (NS_SUCCEEDED(result)) {
+ if (NS_SUCCEEDED(result) && imageFrame) {
result = imageFrame->IsImageComplete(aComplete);
+ } else {
+ result = NS_OK;
+
+ *aComplete = !mLoader;
}
return NS_OK;
@@ -849,13 +866,70 @@ nsHTMLImageElement::GetSrc(nsAWritableString& aSrc)
return rv;
}
+nsresult nsHTMLImageElement::ImageLibCallBack(nsIPresContext* aPresContext,
+ nsIFrameImageLoader* aLoader,
+ nsIFrame* aFrame,
+ void* aClosure,
+ PRUint32 aStatus)
+{
+ nsHTMLImageElement *img = (nsHTMLImageElement *)aClosure;
+
+ if (!img || !img->mLoader)
+ return NS_OK;
+
+ if ((aStatus & NS_IMAGE_LOAD_STATUS_SIZE_AVAILABLE) &&
+ !(aStatus & NS_IMAGE_LOAD_STATUS_ERROR)) {
+ nsCOMPtr cx;
+ aLoader->GetPresContext(getter_AddRefs(cx));
+
+ float t2p;
+ cx->GetTwipsToPixels(&t2p);
+
+ nsSize size;
+ aLoader->GetSize(size);
+
+ nsAutoString tmpStr;
+ tmpStr.AppendInt(NSTwipsToIntPixels(size.width, t2p));
+ img->SetAttribute(kNameSpaceID_None, nsHTMLAtoms::width, tmpStr,
+ PR_FALSE);
+
+ tmpStr.Truncate();
+ tmpStr.AppendInt(NSTwipsToIntPixels(size.height, t2p));
+ img->SetAttribute(kNameSpaceID_None, nsHTMLAtoms::height, tmpStr,
+ PR_FALSE);
+ }
+
+ if (aStatus & (NS_IMAGE_LOAD_STATUS_IMAGE_READY |
+ NS_IMAGE_LOAD_STATUS_ERROR)) {
+ // We set mLoader = nsnull to indicate that we're complete.
+ img->mLoader->RemoveFrame(img);
+ img->mLoader = nsnull;
+
+ // Fire the onload event.
+ nsEventStatus status = nsEventStatus_eIgnore;
+ nsEvent event;
+ event.eventStructType = NS_EVENT;
+
+ if (aStatus & NS_IMAGE_LOAD_STATUS_IMAGE_READY) {
+ event.message = NS_IMAGE_LOAD;
+ } else {
+ event.message = NS_IMAGE_ERROR;
+ }
+
+ img->HandleDOMEvent(aPresContext, &event, nsnull, NS_EVENT_FLAG_INIT,
+ &status);
+ }
+
+ return NS_OK;
+}
+
+
nsresult
nsHTMLImageElement::SetSrcInner(nsIURI* aBaseURL, const nsAReadableString& aSrc)
{
nsresult result = NS_OK;
if (nsnull != mOwnerDocument) {
-
PRInt32 i, count = mOwnerDocument->GetNumberOfShells();
nsIPresShell* shell;
@@ -902,11 +976,17 @@ nsHTMLImageElement::SetSrcInner(nsIURI* aBaseURL, const nsAReadableString& aSrc)
specifiedSize = &size;
}
- // Start the image loading. We don't care about notification
- // or holding on to the image loader.
+ // If we have a loader we're in the middle of loading a image,
+ // we'll cancel that load and start a new one.
+ if (mLoader) {
+ mLoader->RemoveFrame(this);
+ }
+
+ // Start the image loading. We don't care about holding on to
+ // the image loader.
result = context->StartLoadImage(url, nsnull, specifiedSize,
- nsnull, nsnull, nsnull,
- nsnull);
+ nsnull, ImageLibCallBack, this, this,
+ getter_AddRefs(mLoader));
NS_RELEASE(context);
}
diff --git a/mozilla/layout/html/style/src/nsCSSRendering.cpp b/mozilla/layout/html/style/src/nsCSSRendering.cpp
index f254f026602..63cfb71afed 100644
--- a/mozilla/layout/html/style/src/nsCSSRendering.cpp
+++ b/mozilla/layout/html/style/src/nsCSSRendering.cpp
@@ -2096,13 +2096,13 @@ nsCSSRendering::PaintBackground(nsIPresContext* aPresContext,
nsCOMPtr image;
nsIFrameImageLoader* loader = nsnull;
nsresult rv = aPresContext->StartLoadImage(aColor.mBackgroundImage,
- transparentBG
- ? nsnull
- : &aColor.mBackgroundColor,
- nsnull,
- pBGFrame,
- nsnull, nsnull,
- &loader);
+ transparentBG
+ ? nsnull
+ : &aColor.mBackgroundColor,
+ nsnull,
+ pBGFrame,
+ nsnull, nsnull,
+ pBGFrame, &loader);
if ((NS_OK != rv) || (nsnull == loader) ||
(loader->GetImage(getter_AddRefs(image)), (!image))) {
NS_IF_RELEASE(loader);