fix for bug 92248 r=bryner sr=jst

This commit is contained in:
pavlov%netscape.com 2001-10-06 05:08:16 +00:00
Родитель f284bf6dda
Коммит e15f4f6c5d
22 изменённых файлов: 394 добавлений и 185 удалений

Просмотреть файл

@ -941,7 +941,7 @@ nsHTMLImageElement::SetSrcInner(nsIURI* aBaseURL,
doc->GetDocumentLoadGroup(getter_AddRefs(loadGroup)); doc->GetDocumentLoadGroup(getter_AddRefs(loadGroup));
} }
il->LoadImage(uri, loadGroup, this, sup, nsIRequest::LOAD_NORMAL, nsnull, getter_AddRefs(mRequest)); il->LoadImage(uri, loadGroup, this, sup, nsIRequest::LOAD_NORMAL, nsnull, nsnull, getter_AddRefs(mRequest));
} }
} }

Просмотреть файл

@ -535,7 +535,7 @@ nsXBLPrototypeBinding::LoadResources(PRBool* aResult)
// Now kick off the image load // Now kick off the image load
nsCOMPtr<imgIRequest> req; nsCOMPtr<imgIRequest> req;
il->LoadImage(url, nsnull, nsnull, nsnull, nsIRequest::LOAD_BACKGROUND, nsnull, getter_AddRefs(req)); il->LoadImage(url, nsnull, nsnull, nsnull, nsIRequest::LOAD_BACKGROUND, nsnull, nsnull, getter_AddRefs(req));
} }
else else
#endif #endif

Просмотреть файл

@ -119,7 +119,7 @@ nsImageLoader::Load(const nsAReadableString &aURI)
if (NS_FAILED(rv)) return rv; if (NS_FAILED(rv)) return rv;
return il->LoadImage(uri, loadGroup, NS_STATIC_CAST(imgIDecoderObserver *, this), return il->LoadImage(uri, loadGroup, NS_STATIC_CAST(imgIDecoderObserver *, this),
nsnull, nsIRequest::LOAD_BACKGROUND, nsnull, getter_AddRefs(mRequest)); nsnull, nsIRequest::LOAD_BACKGROUND, nsnull, nsnull, getter_AddRefs(mRequest));
} }

Просмотреть файл

@ -119,7 +119,7 @@ nsImageLoader::Load(const nsAReadableString &aURI)
if (NS_FAILED(rv)) return rv; if (NS_FAILED(rv)) return rv;
return il->LoadImage(uri, loadGroup, NS_STATIC_CAST(imgIDecoderObserver *, this), return il->LoadImage(uri, loadGroup, NS_STATIC_CAST(imgIDecoderObserver *, this),
nsnull, nsIRequest::LOAD_BACKGROUND, nsnull, getter_AddRefs(mRequest)); nsnull, nsIRequest::LOAD_BACKGROUND, nsnull, nsnull, getter_AddRefs(mRequest));
} }

Просмотреть файл

@ -145,7 +145,7 @@ nsBulletFrame::Init(nsIPresContext* aPresContext,
NS_RELEASE(listener); NS_RELEASE(listener);
} }
il->LoadImage(imgURI, loadGroup, mListener, aPresContext, nsIRequest::LOAD_NORMAL, nsnull, getter_AddRefs(mImageRequest)); il->LoadImage(imgURI, loadGroup, mListener, aPresContext, nsIRequest::LOAD_NORMAL, nsnull, nsnull, getter_AddRefs(mImageRequest));
} }
return NS_OK; return NS_OK;
@ -1383,7 +1383,7 @@ nsBulletFrame::Reflow(nsIPresContext* aPresContext,
nsCOMPtr<nsILoadGroup> loadGroup; nsCOMPtr<nsILoadGroup> loadGroup;
GetLoadGroup(aPresContext, getter_AddRefs(loadGroup)); GetLoadGroup(aPresContext, getter_AddRefs(loadGroup));
il->LoadImage(newURI, loadGroup, mListener, aPresContext, nsIRequest::LOAD_NORMAL, nsnull, getter_AddRefs(mImageRequest)); il->LoadImage(newURI, loadGroup, mListener, aPresContext, nsIRequest::LOAD_NORMAL, nsnull, nsnull, getter_AddRefs(mImageRequest));
} }
} }
} }

Просмотреть файл

@ -131,6 +131,24 @@ NS_NewImageFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame)
return NS_OK; return NS_OK;
} }
int
nsImageFrame::GetImageLoad(imgIRequest *aRequest)
{
if (aRequest == mLoads[0].mRequest)
return 0;
else if (aRequest == mLoads[1].mRequest)
return 1;
else if (aRequest == mLoads[2].mRequest)
return 2;
NS_ASSERTION((aRequest == mLoads[0].mRequest &&
aRequest == mLoads[1].mRequest &&
aRequest == mLoads[2].mRequest), "Failure to figure out which imgIRequest this is!");
return -1;
}
nsImageFrame::nsImageFrame() : nsImageFrame::nsImageFrame() :
mIntrinsicSize(0, 0), mIntrinsicSize(0, 0),
mGotInitialReflow(PR_FALSE), mGotInitialReflow(PR_FALSE),
@ -208,17 +226,17 @@ nsImageFrame::Destroy(nsIPresContext* aPresContext)
NS_RELEASE(mImageMap); NS_RELEASE(mImageMap);
} }
if (mImageRequest) for (int i=0; i != 3; ++i) {
mImageRequest->Cancel(NS_ERROR_FAILURE); // NS_BINDING_ABORT ? if (mLoads[i].mRequest) {
if (mLowImageRequest) mLoads[i].mRequest->Cancel(NS_ERROR_FAILURE);
mLowImageRequest->Cancel(NS_ERROR_FAILURE); // NS_BINDING_ABORT ? mLoads[i].mRequest = nsnull;
}
}
// set the frame to null so we don't send messages to a dead object. // set the frame to null so we don't send messages to a dead object.
if (mListener) if (mListener)
NS_REINTERPRET_CAST(nsImageListener*, mListener.get())->SetFrame(nsnull); NS_REINTERPRET_CAST(nsImageListener*, mListener.get())->SetFrame(nsnull);
mImageRequest = nsnull;
mLowImageRequest = nsnull;
mListener = nsnull; mListener = nsnull;
return nsLeafFrame::Destroy(aPresContext); return nsLeafFrame::Destroy(aPresContext);
@ -258,15 +276,17 @@ nsImageFrame::Init(nsIPresContext* aPresContext,
// Set the image loader's source URL and base URL // Set the image loader's source URL and base URL
if (NS_CONTENT_ATTR_HAS_VALUE == lowSrcResult && !lowSrc.IsEmpty()) { if (NS_CONTENT_ATTR_HAS_VALUE == lowSrcResult && !lowSrc.IsEmpty()) {
LoadImage(lowSrc, aPresContext, getter_AddRefs(mLowImageRequest)); mLoads[1].mRequest = do_CreateInstance("@mozilla.org/image/request;1");
LoadImage(lowSrc, aPresContext, mLoads[1].mRequest);
} }
mInitialLoadCompleted = PR_FALSE; mInitialLoadCompleted = PR_FALSE;
mCanSendLoadEvent = PR_TRUE; mCanSendLoadEvent = PR_TRUE;
rv = LoadImage(src, aPresContext, getter_AddRefs(mImageRequest)); // if the image was found in the cache, mLoads[0].mRequest = do_CreateInstance("@mozilla.org/image/request;1");
// it is possible that LoadImage will result in rv = LoadImage(src, aPresContext, mLoads[0].mRequest); // if the image was found in the cache,
// a call to OnStartContainer() // it is possible that LoadImage will result in
// a call to OnStartContainer()
return rv; return rv;
} }
@ -279,8 +299,14 @@ NS_IMETHODIMP nsImageFrame::OnStartDecode(imgIRequest *aRequest, nsIPresContext
NS_IMETHODIMP nsImageFrame::OnStartContainer(imgIRequest *aRequest, nsIPresContext *aPresContext, imgIContainer *aImage) NS_IMETHODIMP nsImageFrame::OnStartContainer(imgIRequest *aRequest, nsIPresContext *aPresContext, imgIContainer *aImage)
{ {
if (!aImage) return NS_ERROR_INVALID_ARG;
mInitialLoadCompleted = PR_TRUE; mInitialLoadCompleted = PR_TRUE;
int whichLoad = GetImageLoad(aRequest);
if (whichLoad == -1) return NS_ERROR_FAILURE;
struct ImageLoad *load= &mLoads[whichLoad];
if (aImage) if (aImage)
{ {
/* Get requested animation policy from the pres context: /* Get requested animation policy from the pres context:
@ -295,11 +321,6 @@ NS_IMETHODIMP nsImageFrame::OnStartContainer(imgIRequest *aRequest, nsIPresConte
} }
nscoord w, h; nscoord w, h;
#ifdef DEBUG_pavlov
NS_ENSURE_ARG_POINTER(aImage);
#else
if (!aImage) return NS_ERROR_INVALID_ARG;
#endif
aImage->GetWidth(&w); aImage->GetWidth(&w);
aImage->GetHeight(&h); aImage->GetHeight(&h);
@ -308,19 +329,19 @@ NS_IMETHODIMP nsImageFrame::OnStartContainer(imgIRequest *aRequest, nsIPresConte
nsSize newsize(NSIntPixelsToTwips(w, p2t), NSIntPixelsToTwips(h, p2t)); nsSize newsize(NSIntPixelsToTwips(w, p2t), NSIntPixelsToTwips(h, p2t));
if (mIntrinsicSize != newsize) { if (load->mIntrinsicSize != newsize) {
mIntrinsicSize = newsize; load->mIntrinsicSize = newsize;
if (mIntrinsicSize.width != 0 && mIntrinsicSize.height != 0) if (load->mIntrinsicSize.width != 0 && load->mIntrinsicSize.height != 0)
mTransform.SetToScale((float(mComputedSize.width) / float(mIntrinsicSize.width)), load->mTransform.SetToScale((float(mComputedSize.width) / float(load->mIntrinsicSize.width)),
(float(mComputedSize.height) / float(mIntrinsicSize.height))); (float(mComputedSize.height) / float(load->mIntrinsicSize.height)));
if (!mSizeConstrained) { if (!mSizeConstrained) {
nsCOMPtr<nsIPresShell> presShell; nsCOMPtr<nsIPresShell> presShell;
aPresContext->GetShell(getter_AddRefs(presShell)); aPresContext->GetShell(getter_AddRefs(presShell));
NS_ASSERTION(mParent, "No parent to pass the reflow request up to."); NS_ASSERTION(mParent, "No parent to pass the reflow request up to.");
NS_ASSERTION(presShell, "No PresShell."); NS_ASSERTION(presShell, "No PresShell.");
if (mParent && presShell && mGotInitialReflow) { // don't reflow if we havn't gotten the inital reflow yet if (mParent && presShell && mGotInitialReflow && whichLoad == 0) { // don't reflow if we havn't gotten the inital reflow yet
mState |= NS_FRAME_IS_DIRTY; mState |= NS_FRAME_IS_DIRTY;
mParent->ReflowDirtyChild(presShell, NS_STATIC_CAST(nsIFrame*, this)); mParent->ReflowDirtyChild(presShell, NS_STATIC_CAST(nsIFrame*, this));
} }
@ -343,6 +364,12 @@ NS_IMETHODIMP nsImageFrame::OnDataAvailable(imgIRequest *aRequest, nsIPresContex
if (!aRect) if (!aRect)
return NS_ERROR_NULL_POINTER; return NS_ERROR_NULL_POINTER;
int whichLoad = GetImageLoad(aRequest);
if (whichLoad == -1) return NS_ERROR_FAILURE;
if (whichLoad != 0) return NS_OK;
struct ImageLoad *load= &mLoads[whichLoad];
nsRect r(aRect->x, aRect->y, aRect->width, aRect->height); nsRect r(aRect->x, aRect->y, aRect->width, aRect->height);
float p2t; float p2t;
@ -352,12 +379,13 @@ NS_IMETHODIMP nsImageFrame::OnDataAvailable(imgIRequest *aRequest, nsIPresContex
r.width = NSIntPixelsToTwips(r.width, p2t); r.width = NSIntPixelsToTwips(r.width, p2t);
r.height = NSIntPixelsToTwips(r.height, p2t); r.height = NSIntPixelsToTwips(r.height, p2t);
mTransform.TransformCoord(&r.x, &r.y, &r.width, &r.height); load->mTransform.TransformCoord(&r.x, &r.y, &r.width, &r.height);
r.x += mBorderPadding.left; r.x += mBorderPadding.left;
r.y += mBorderPadding.top; r.y += mBorderPadding.top;
Invalidate(aPresContext, r, PR_FALSE); if (whichLoad == 0)
Invalidate(aPresContext, r, PR_FALSE);
return NS_OK; return NS_OK;
} }
@ -519,18 +547,57 @@ NS_IMETHODIMP nsImageFrame::OnStopDecode(imgIRequest *aRequest, nsIPresContext *
// check to see if an image error occurred // check to see if an image error occurred
PRBool imageFailedToLoad = PR_FALSE; PRBool imageFailedToLoad = PR_FALSE;
if (NS_FAILED(aStatus)) { // We failed to load the image. Notify the pres shell int whichLoad = GetImageLoad(aRequest);
if (whichLoad == -1) return NS_ERROR_FAILURE;
if (whichLoad == 2) {
if (NS_SUCCEEDED(aStatus)) {
if (mLoads[0].mRequest) {
mLoads[0].mRequest->Cancel(NS_ERROR_FAILURE);
}
mLoads[0].mRequest = mLoads[2].mRequest;
mLoads[0].mIntrinsicSize = mLoads[2].mIntrinsicSize;
// XXX i don't think we always want to set this.
mLoads[0].mTransform = mLoads[2].mTransform;
struct ImageLoad *load= &mLoads[0];
mLoads[2].mRequest = nsnull;
if (!mSizeConstrained && (mLoads[0].mIntrinsicSize != mIntrinsicSize)) {
nsCOMPtr<nsIPresShell> presShell;
aPresContext->GetShell(getter_AddRefs(presShell));
NS_ASSERTION(mParent, "No parent to pass the reflow request up to.");
NS_ASSERTION(presShell, "No PresShell.");
if (mParent && presShell && mGotInitialReflow) { // don't reflow if we havn't gotten the inital reflow yet
mState |= NS_FRAME_IS_DIRTY;
mParent->ReflowDirtyChild(presShell, NS_STATIC_CAST(nsIFrame*, this));
}
} else {
nsSize s;
GetSize(s);
nsRect r(0,0, s.width, s.height);
Invalidate(aPresContext, r, PR_FALSE);
}
} else {
mLoads[2].mRequest = nsnull;
}
} else if (NS_FAILED(aStatus)) {
PRBool lowFailed = PR_FALSE; PRBool lowFailed = PR_FALSE;
PRBool imageFailed = PR_FALSE; PRBool imageFailed = PR_FALSE;
// One of the two images didn't load, which one? // One of the two images didn't load, which one?
if (mLowImageRequest == aRequest || !mLowImageRequest) { if (whichLoad == 0 || !mLoads[0].mRequest) {
lowFailed = PR_TRUE;
}
if (mImageRequest == aRequest || !mImageRequest) {
imageFailed = PR_TRUE; imageFailed = PR_TRUE;
} }
if (whichLoad == 1 || !mLoads[1].mRequest) {
lowFailed = PR_TRUE;
}
if (imageFailed && lowFailed) if (imageFailed && lowFailed)
imageFailedToLoad = PR_TRUE; imageFailedToLoad = PR_TRUE;
} }
@ -568,19 +635,25 @@ NS_IMETHODIMP nsImageFrame::OnStopDecode(imgIRequest *aRequest, nsIPresContext *
NS_IMETHODIMP nsImageFrame::FrameChanged(imgIContainer *aContainer, nsIPresContext *aPresContext, gfxIImageFrame *aNewFrame, nsRect *aDirtyRect) NS_IMETHODIMP nsImageFrame::FrameChanged(imgIContainer *aContainer, nsIPresContext *aPresContext, gfxIImageFrame *aNewFrame, nsRect *aDirtyRect)
{ {
nsRect r(*aDirtyRect); if (!mLoads[0].mRequest)
return NS_OK; // if mLoads[0].mRequest is null, this isn't for the first one, so we don't care about it.
float p2t; nsCOMPtr<imgIContainer> con;
aPresContext->GetPixelsToTwips(&p2t); mLoads[0].mRequest->GetImage(getter_AddRefs(con));
r.x = NSIntPixelsToTwips(r.x, p2t); if (aContainer == con.get()) {
r.y = NSIntPixelsToTwips(r.y, p2t); nsRect r(*aDirtyRect);
r.width = NSIntPixelsToTwips(r.width, p2t);
r.height = NSIntPixelsToTwips(r.height, p2t);
mTransform.TransformCoord(&r.x, &r.y, &r.width, &r.height); float p2t;
aPresContext->GetPixelsToTwips(&p2t);
r.x = NSIntPixelsToTwips(r.x, p2t);
r.y = NSIntPixelsToTwips(r.y, p2t);
r.width = NSIntPixelsToTwips(r.width, p2t);
r.height = NSIntPixelsToTwips(r.height, p2t);
Invalidate(aPresContext, r, PR_FALSE); mLoads[0].mTransform.TransformCoord(&r.x, &r.y, &r.width, &r.height);
Invalidate(aPresContext, r, PR_FALSE);
}
return NS_OK; return NS_OK;
} }
@ -597,7 +670,6 @@ nsImageFrame::GetDesiredSize(nsIPresContext* aPresContext,
const nsHTMLReflowState& aReflowState, const nsHTMLReflowState& aReflowState,
nsHTMLReflowMetrics& aDesiredSize) nsHTMLReflowMetrics& aDesiredSize)
{ {
nscoord widthConstraint = NS_INTRINSICSIZE; nscoord widthConstraint = NS_INTRINSICSIZE;
nscoord heightConstraint = NS_INTRINSICSIZE; nscoord heightConstraint = NS_INTRINSICSIZE;
PRBool fixedContentWidth = PR_FALSE; PRBool fixedContentWidth = PR_FALSE;
@ -621,6 +693,18 @@ nsImageFrame::GetDesiredSize(nsIPresContext* aPresContext,
fixedContentHeight = PR_TRUE; fixedContentHeight = PR_TRUE;
} }
// if mLoads[0].mIntrinsicSize.width and height are 0, then we should check to see
// if the size is already known by the image container.
if (mLoads[0].mIntrinsicSize.width == 0 && mLoads[0].mIntrinsicSize.height == 0) {
nsCOMPtr<imgIContainer> con;
mLoads[0].mRequest->GetImage(getter_AddRefs(con));
if (con) {
con->GetWidth(&mLoads[0].mIntrinsicSize.width);
con->GetHeight(&mLoads[0].mIntrinsicSize.height);
}
}
mIntrinsicSize = mLoads[0].mIntrinsicSize;
PRBool haveComputedSize = PR_FALSE; PRBool haveComputedSize = PR_FALSE;
PRBool needIntrinsicImageSize = PR_FALSE; PRBool needIntrinsicImageSize = PR_FALSE;
@ -675,11 +759,13 @@ nsImageFrame::GetDesiredSize(nsIPresContext* aPresContext,
mComputedSize.width = newWidth; mComputedSize.width = newWidth;
mComputedSize.height = newHeight; mComputedSize.height = newHeight;
nsTransform2D *transform = &mLoads[0].mTransform;
if (mComputedSize == mIntrinsicSize) { if (mComputedSize == mIntrinsicSize) {
mTransform.SetToIdentity(); transform->SetToIdentity();
} else { } else {
if (mIntrinsicSize.width != 0 && mIntrinsicSize.height != 0) { if (mIntrinsicSize.width != 0 && mIntrinsicSize.height != 0) {
mTransform.SetToScale(float(mComputedSize.width) / float(mIntrinsicSize.width), transform->SetToScale(float(mComputedSize.width) / float(mIntrinsicSize.width),
float(mComputedSize.height) / float(mIntrinsicSize.height)); float(mComputedSize.height) / float(mIntrinsicSize.height));
} }
} }
@ -977,17 +1063,16 @@ nsImageFrame::Paint(nsIPresContext* aPresContext,
nsCOMPtr<imgIContainer> imgCon; nsCOMPtr<imgIContainer> imgCon;
nsCOMPtr<imgIContainer> lowImgCon; nsCOMPtr<imgIContainer> lowImgCon;
if (mImageRequest) { PRUint32 loadStatus = imgIRequest::STATUS_ERROR;
mImageRequest->GetImage(getter_AddRefs(imgCon));
if (mLoads[0].mRequest) {
mLoads[0].mRequest->GetImage(getter_AddRefs(imgCon));
mLoads[0].mRequest->GetImageStatus(&loadStatus);
} }
if (mLowImageRequest) { if (mLoads[1].mRequest) {
mLowImageRequest->GetImage(getter_AddRefs(lowImgCon)); mLoads[1].mRequest->GetImage(getter_AddRefs(lowImgCon));
} }
PRUint32 loadStatus = imgIRequest::STATUS_ERROR;
if (mImageRequest) {
mImageRequest->GetImageStatus(&loadStatus);
}
if (loadStatus & imgIRequest::STATUS_ERROR || !(imgCon || lowImgCon)) { if (loadStatus & imgIRequest::STATUS_ERROR || !(imgCon || lowImgCon)) {
// No image yet, or image load failed. Draw the alt-text and an icon // No image yet, or image load failed. Draw the alt-text and an icon
// indicating the status // indicating the status
@ -1019,7 +1104,7 @@ nsImageFrame::Paint(nsIPresContext* aPresContext,
if (imgCon) { if (imgCon) {
nsPoint p(inner.x, inner.y); nsPoint p(inner.x, inner.y);
if (mIntrinsicSize == mComputedSize) { if (mLoads[0].mIntrinsicSize == mComputedSize) {
inner.IntersectRect(inner, aDirtyRect); inner.IntersectRect(inner, aDirtyRect);
nsRect r(inner.x, inner.y, inner.width, inner.height); nsRect r(inner.x, inner.y, inner.width, inner.height);
r.x -= mBorderPadding.left; r.x -= mBorderPadding.left;
@ -1027,8 +1112,8 @@ nsImageFrame::Paint(nsIPresContext* aPresContext,
aRenderingContext.DrawImage(imgCon, &r, &p); aRenderingContext.DrawImage(imgCon, &r, &p);
} else { } else {
nsTransform2D trans; nsTransform2D trans;
trans.SetToScale((float(mIntrinsicSize.width) / float(inner.width)), trans.SetToScale((float(mLoads[0].mIntrinsicSize.width) / float(inner.width)),
(float(mIntrinsicSize.height) / float(inner.height))); (float(mLoads[0].mIntrinsicSize.height) / float(inner.height)));
nsRect r(0, 0, inner.width, inner.height); nsRect r(0, 0, inner.width, inner.height);
@ -1409,20 +1494,25 @@ nsImageFrame::AttributeChanged(nsIPresContext* aPresContext,
PRUint32 loadStatus = imgIRequest::STATUS_ERROR; PRUint32 loadStatus = imgIRequest::STATUS_ERROR;
if (mImageRequest) if (mLoads[0].mRequest)
mImageRequest->GetImageStatus(&loadStatus); mLoads[0].mRequest->GetImageStatus(&loadStatus);
if (!(loadStatus & imgIRequest::STATUS_SIZE_AVAILABLE)) { if (!(loadStatus & imgIRequest::STATUS_SIZE_AVAILABLE)) {
if (mImageRequest) { if (mLoads[0].mRequest) {
mFailureReplace = PR_FALSE; // don't cause a CantRenderReplacedElement call mFailureReplace = PR_FALSE; // don't cause a CantRenderReplacedElement call
mImageRequest->Cancel(NS_ERROR_FAILURE); mLoads[0].mRequest->Cancel(NS_ERROR_FAILURE);
mImageRequest = nsnull; mLoads[0].mRequest = nsnull;
} }
mCanSendLoadEvent = PR_TRUE; mCanSendLoadEvent = PR_TRUE;
} }
LoadImage(newSRC, aPresContext, getter_AddRefs(mImageRequest)); if (mLoads[2].mRequest) {
mLoads[2].mRequest->Cancel(NS_ERROR_FAILURE);
mLoads[2].mRequest = nsnull;
}
mLoads[2].mRequest = do_CreateInstance("@mozilla.org/image/request;1");
LoadImage(newSRC, aPresContext, mLoads[2].mRequest);
} }
else if (nsHTMLAtoms::width == aAttribute || nsHTMLAtoms::height == aAttribute) else if (nsHTMLAtoms::width == aAttribute || nsHTMLAtoms::height == aAttribute)
{ // XXX: could check for new width == old width, and make that a no-op { // XXX: could check for new width == old width, and make that a no-op
@ -1448,7 +1538,7 @@ nsImageFrame::GetFrameType(nsIAtom** aType) const
NS_IMETHODIMP NS_IMETHODIMP
nsImageFrame::GetIntrinsicImageSize(nsSize& aSize) nsImageFrame::GetIntrinsicImageSize(nsSize& aSize)
{ {
aSize = mIntrinsicSize; aSize = mLoads[0].mIntrinsicSize;
return NS_OK; return NS_OK;
} }
@ -1459,9 +1549,9 @@ nsImageFrame::GetNaturalImageSize(PRUint32 *naturalWidth,
*naturalWidth = 0; *naturalWidth = 0;
*naturalHeight = 0; *naturalHeight = 0;
if (mImageRequest) { if (mLoads[0].mRequest) {
nsCOMPtr<imgIContainer> container; nsCOMPtr<imgIContainer> container;
mImageRequest->GetImage(getter_AddRefs(container)); mLoads[0].mRequest->GetImage(getter_AddRefs(container));
if (container) { if (container) {
PRInt32 w, h; PRInt32 w, h;
container->GetWidth(&w); container->GetWidth(&w);
@ -1478,7 +1568,7 @@ nsImageFrame::GetNaturalImageSize(PRUint32 *naturalWidth,
NS_IMETHODIMP NS_IMETHODIMP
nsImageFrame::GetImageRequest(imgIRequest **aRequest) nsImageFrame::GetImageRequest(imgIRequest **aRequest)
{ {
*aRequest = mImageRequest; *aRequest = mLoads[0].mRequest;
NS_IF_ADDREF(*aRequest); NS_IF_ADDREF(*aRequest);
return NS_OK; return NS_OK;
} }
@ -1487,13 +1577,13 @@ NS_IMETHODIMP
nsImageFrame::IsImageComplete(PRBool* aComplete) nsImageFrame::IsImageComplete(PRBool* aComplete)
{ {
NS_ENSURE_ARG_POINTER(aComplete); NS_ENSURE_ARG_POINTER(aComplete);
if (!mImageRequest) { if (!mLoads[0].mRequest) {
*aComplete = PR_FALSE; *aComplete = PR_FALSE;
return NS_OK; return NS_OK;
} }
PRUint32 status; PRUint32 status;
mImageRequest->GetImageStatus(&status); mLoads[0].mRequest->GetImageStatus(&status);
*aComplete = ((status & imgIRequest::STATUS_LOAD_COMPLETE) != 0); *aComplete = ((status & imgIRequest::STATUS_LOAD_COMPLETE) != 0);
return NS_OK; return NS_OK;
@ -1516,7 +1606,7 @@ void HaveFixedSize(const nsHTMLReflowState& aReflowState, PRPackedBool& aConstra
nsresult nsresult
nsImageFrame::LoadImage(const nsAReadableString& aSpec, nsIPresContext *aPresContext, imgIRequest **aRequest) nsImageFrame::LoadImage(const nsAReadableString& aSpec, nsIPresContext *aPresContext, imgIRequest *aRequest)
{ {
nsresult rv = NS_OK; nsresult rv = NS_OK;
@ -1561,7 +1651,8 @@ nsImageFrame::LoadImage(const nsAReadableString& aSpec, nsIPresContext *aPresCon
/* set this back to FALSE before we do the real load */ /* set this back to FALSE before we do the real load */
mInitialLoadCompleted = PR_FALSE; mInitialLoadCompleted = PR_FALSE;
return il->LoadImage(uri, loadGroup, mListener, aPresContext, loadFlags, nsnull, aRequest); nsCOMPtr<imgIRequest> tempRequest;
return il->LoadImage(uri, loadGroup, mListener, aPresContext, loadFlags, nsnull, aRequest, getter_AddRefs(tempRequest));
} }
#define INTERNAL_GOPHER_LENGTH 16 /* "internal-gopher-" length */ #define INTERNAL_GOPHER_LENGTH 16 /* "internal-gopher-" length */

Просмотреть файл

@ -74,6 +74,15 @@ private:
nsImageFrame *mFrame; nsImageFrame *mFrame;
}; };
struct ImageLoad {
ImageLoad() : mIntrinsicSize(0,0) { }
nsCOMPtr<imgIRequest> mRequest;
nsSize mIntrinsicSize;
nsTransform2D mTransform;
};
#define ImageFrameSuper nsLeafFrame #define ImageFrameSuper nsLeafFrame
class nsImageFrame : public ImageFrameSuper, public nsIImageFrame { class nsImageFrame : public ImageFrameSuper, public nsIImageFrame {
@ -192,7 +201,7 @@ protected:
nsRect& aInnerArea) const; nsRect& aInnerArea) const;
nsresult LoadImage(const nsAReadableString& aSpec, nsIPresContext *aPresContext, imgIRequest **aRequest); nsresult LoadImage(const nsAReadableString& aSpec, nsIPresContext *aPresContext, imgIRequest *aRequest);
inline PRBool CanLoadImage(nsIURI *aURI); inline PRBool CanLoadImage(nsIURI *aURI);
@ -204,18 +213,26 @@ protected:
void FireDOMEvent(PRUint32 aMessage); void FireDOMEvent(PRUint32 aMessage);
nsImageMap* mImageMap;
nsCOMPtr<imgIRequest> mImageRequest; private:
nsCOMPtr<imgIRequest> mLowImageRequest; inline int GetImageLoad(imgIRequest *aRequest);
nsImageMap* mImageMap;
nsCOMPtr<imgIDecoderObserver> mListener; nsCOMPtr<imgIDecoderObserver> mListener;
/**
* 0 is the current image being displayed on the screen.
* 1 is for the lowsrc image if any.
* 2 is for attribute changed images.
* when the load from 2 completes, it will replace 0.
*/
struct ImageLoad mLoads[3];
nsSize mComputedSize; nsSize mComputedSize;
nsSize mIntrinsicSize; nsSize mIntrinsicSize;
nsTransform2D mTransform;
PRPackedBool mSizeConstrained; PRPackedBool mSizeConstrained;
PRPackedBool mGotInitialReflow; PRPackedBool mGotInitialReflow;
PRPackedBool mInitialLoadCompleted; PRPackedBool mInitialLoadCompleted;

Просмотреть файл

@ -145,7 +145,7 @@ nsBulletFrame::Init(nsIPresContext* aPresContext,
NS_RELEASE(listener); NS_RELEASE(listener);
} }
il->LoadImage(imgURI, loadGroup, mListener, aPresContext, nsIRequest::LOAD_NORMAL, nsnull, getter_AddRefs(mImageRequest)); il->LoadImage(imgURI, loadGroup, mListener, aPresContext, nsIRequest::LOAD_NORMAL, nsnull, nsnull, getter_AddRefs(mImageRequest));
} }
return NS_OK; return NS_OK;
@ -1383,7 +1383,7 @@ nsBulletFrame::Reflow(nsIPresContext* aPresContext,
nsCOMPtr<nsILoadGroup> loadGroup; nsCOMPtr<nsILoadGroup> loadGroup;
GetLoadGroup(aPresContext, getter_AddRefs(loadGroup)); GetLoadGroup(aPresContext, getter_AddRefs(loadGroup));
il->LoadImage(newURI, loadGroup, mListener, aPresContext, nsIRequest::LOAD_NORMAL, nsnull, getter_AddRefs(mImageRequest)); il->LoadImage(newURI, loadGroup, mListener, aPresContext, nsIRequest::LOAD_NORMAL, nsnull, nsnull, getter_AddRefs(mImageRequest));
} }
} }
} }

Просмотреть файл

@ -131,6 +131,24 @@ NS_NewImageFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame)
return NS_OK; return NS_OK;
} }
int
nsImageFrame::GetImageLoad(imgIRequest *aRequest)
{
if (aRequest == mLoads[0].mRequest)
return 0;
else if (aRequest == mLoads[1].mRequest)
return 1;
else if (aRequest == mLoads[2].mRequest)
return 2;
NS_ASSERTION((aRequest == mLoads[0].mRequest &&
aRequest == mLoads[1].mRequest &&
aRequest == mLoads[2].mRequest), "Failure to figure out which imgIRequest this is!");
return -1;
}
nsImageFrame::nsImageFrame() : nsImageFrame::nsImageFrame() :
mIntrinsicSize(0, 0), mIntrinsicSize(0, 0),
mGotInitialReflow(PR_FALSE), mGotInitialReflow(PR_FALSE),
@ -208,17 +226,17 @@ nsImageFrame::Destroy(nsIPresContext* aPresContext)
NS_RELEASE(mImageMap); NS_RELEASE(mImageMap);
} }
if (mImageRequest) for (int i=0; i != 3; ++i) {
mImageRequest->Cancel(NS_ERROR_FAILURE); // NS_BINDING_ABORT ? if (mLoads[i].mRequest) {
if (mLowImageRequest) mLoads[i].mRequest->Cancel(NS_ERROR_FAILURE);
mLowImageRequest->Cancel(NS_ERROR_FAILURE); // NS_BINDING_ABORT ? mLoads[i].mRequest = nsnull;
}
}
// set the frame to null so we don't send messages to a dead object. // set the frame to null so we don't send messages to a dead object.
if (mListener) if (mListener)
NS_REINTERPRET_CAST(nsImageListener*, mListener.get())->SetFrame(nsnull); NS_REINTERPRET_CAST(nsImageListener*, mListener.get())->SetFrame(nsnull);
mImageRequest = nsnull;
mLowImageRequest = nsnull;
mListener = nsnull; mListener = nsnull;
return nsLeafFrame::Destroy(aPresContext); return nsLeafFrame::Destroy(aPresContext);
@ -258,15 +276,17 @@ nsImageFrame::Init(nsIPresContext* aPresContext,
// Set the image loader's source URL and base URL // Set the image loader's source URL and base URL
if (NS_CONTENT_ATTR_HAS_VALUE == lowSrcResult && !lowSrc.IsEmpty()) { if (NS_CONTENT_ATTR_HAS_VALUE == lowSrcResult && !lowSrc.IsEmpty()) {
LoadImage(lowSrc, aPresContext, getter_AddRefs(mLowImageRequest)); mLoads[1].mRequest = do_CreateInstance("@mozilla.org/image/request;1");
LoadImage(lowSrc, aPresContext, mLoads[1].mRequest);
} }
mInitialLoadCompleted = PR_FALSE; mInitialLoadCompleted = PR_FALSE;
mCanSendLoadEvent = PR_TRUE; mCanSendLoadEvent = PR_TRUE;
rv = LoadImage(src, aPresContext, getter_AddRefs(mImageRequest)); // if the image was found in the cache, mLoads[0].mRequest = do_CreateInstance("@mozilla.org/image/request;1");
// it is possible that LoadImage will result in rv = LoadImage(src, aPresContext, mLoads[0].mRequest); // if the image was found in the cache,
// a call to OnStartContainer() // it is possible that LoadImage will result in
// a call to OnStartContainer()
return rv; return rv;
} }
@ -279,8 +299,14 @@ NS_IMETHODIMP nsImageFrame::OnStartDecode(imgIRequest *aRequest, nsIPresContext
NS_IMETHODIMP nsImageFrame::OnStartContainer(imgIRequest *aRequest, nsIPresContext *aPresContext, imgIContainer *aImage) NS_IMETHODIMP nsImageFrame::OnStartContainer(imgIRequest *aRequest, nsIPresContext *aPresContext, imgIContainer *aImage)
{ {
if (!aImage) return NS_ERROR_INVALID_ARG;
mInitialLoadCompleted = PR_TRUE; mInitialLoadCompleted = PR_TRUE;
int whichLoad = GetImageLoad(aRequest);
if (whichLoad == -1) return NS_ERROR_FAILURE;
struct ImageLoad *load= &mLoads[whichLoad];
if (aImage) if (aImage)
{ {
/* Get requested animation policy from the pres context: /* Get requested animation policy from the pres context:
@ -295,11 +321,6 @@ NS_IMETHODIMP nsImageFrame::OnStartContainer(imgIRequest *aRequest, nsIPresConte
} }
nscoord w, h; nscoord w, h;
#ifdef DEBUG_pavlov
NS_ENSURE_ARG_POINTER(aImage);
#else
if (!aImage) return NS_ERROR_INVALID_ARG;
#endif
aImage->GetWidth(&w); aImage->GetWidth(&w);
aImage->GetHeight(&h); aImage->GetHeight(&h);
@ -308,19 +329,19 @@ NS_IMETHODIMP nsImageFrame::OnStartContainer(imgIRequest *aRequest, nsIPresConte
nsSize newsize(NSIntPixelsToTwips(w, p2t), NSIntPixelsToTwips(h, p2t)); nsSize newsize(NSIntPixelsToTwips(w, p2t), NSIntPixelsToTwips(h, p2t));
if (mIntrinsicSize != newsize) { if (load->mIntrinsicSize != newsize) {
mIntrinsicSize = newsize; load->mIntrinsicSize = newsize;
if (mIntrinsicSize.width != 0 && mIntrinsicSize.height != 0) if (load->mIntrinsicSize.width != 0 && load->mIntrinsicSize.height != 0)
mTransform.SetToScale((float(mComputedSize.width) / float(mIntrinsicSize.width)), load->mTransform.SetToScale((float(mComputedSize.width) / float(load->mIntrinsicSize.width)),
(float(mComputedSize.height) / float(mIntrinsicSize.height))); (float(mComputedSize.height) / float(load->mIntrinsicSize.height)));
if (!mSizeConstrained) { if (!mSizeConstrained) {
nsCOMPtr<nsIPresShell> presShell; nsCOMPtr<nsIPresShell> presShell;
aPresContext->GetShell(getter_AddRefs(presShell)); aPresContext->GetShell(getter_AddRefs(presShell));
NS_ASSERTION(mParent, "No parent to pass the reflow request up to."); NS_ASSERTION(mParent, "No parent to pass the reflow request up to.");
NS_ASSERTION(presShell, "No PresShell."); NS_ASSERTION(presShell, "No PresShell.");
if (mParent && presShell && mGotInitialReflow) { // don't reflow if we havn't gotten the inital reflow yet if (mParent && presShell && mGotInitialReflow && whichLoad == 0) { // don't reflow if we havn't gotten the inital reflow yet
mState |= NS_FRAME_IS_DIRTY; mState |= NS_FRAME_IS_DIRTY;
mParent->ReflowDirtyChild(presShell, NS_STATIC_CAST(nsIFrame*, this)); mParent->ReflowDirtyChild(presShell, NS_STATIC_CAST(nsIFrame*, this));
} }
@ -343,6 +364,12 @@ NS_IMETHODIMP nsImageFrame::OnDataAvailable(imgIRequest *aRequest, nsIPresContex
if (!aRect) if (!aRect)
return NS_ERROR_NULL_POINTER; return NS_ERROR_NULL_POINTER;
int whichLoad = GetImageLoad(aRequest);
if (whichLoad == -1) return NS_ERROR_FAILURE;
if (whichLoad != 0) return NS_OK;
struct ImageLoad *load= &mLoads[whichLoad];
nsRect r(aRect->x, aRect->y, aRect->width, aRect->height); nsRect r(aRect->x, aRect->y, aRect->width, aRect->height);
float p2t; float p2t;
@ -352,12 +379,13 @@ NS_IMETHODIMP nsImageFrame::OnDataAvailable(imgIRequest *aRequest, nsIPresContex
r.width = NSIntPixelsToTwips(r.width, p2t); r.width = NSIntPixelsToTwips(r.width, p2t);
r.height = NSIntPixelsToTwips(r.height, p2t); r.height = NSIntPixelsToTwips(r.height, p2t);
mTransform.TransformCoord(&r.x, &r.y, &r.width, &r.height); load->mTransform.TransformCoord(&r.x, &r.y, &r.width, &r.height);
r.x += mBorderPadding.left; r.x += mBorderPadding.left;
r.y += mBorderPadding.top; r.y += mBorderPadding.top;
Invalidate(aPresContext, r, PR_FALSE); if (whichLoad == 0)
Invalidate(aPresContext, r, PR_FALSE);
return NS_OK; return NS_OK;
} }
@ -519,18 +547,57 @@ NS_IMETHODIMP nsImageFrame::OnStopDecode(imgIRequest *aRequest, nsIPresContext *
// check to see if an image error occurred // check to see if an image error occurred
PRBool imageFailedToLoad = PR_FALSE; PRBool imageFailedToLoad = PR_FALSE;
if (NS_FAILED(aStatus)) { // We failed to load the image. Notify the pres shell int whichLoad = GetImageLoad(aRequest);
if (whichLoad == -1) return NS_ERROR_FAILURE;
if (whichLoad == 2) {
if (NS_SUCCEEDED(aStatus)) {
if (mLoads[0].mRequest) {
mLoads[0].mRequest->Cancel(NS_ERROR_FAILURE);
}
mLoads[0].mRequest = mLoads[2].mRequest;
mLoads[0].mIntrinsicSize = mLoads[2].mIntrinsicSize;
// XXX i don't think we always want to set this.
mLoads[0].mTransform = mLoads[2].mTransform;
struct ImageLoad *load= &mLoads[0];
mLoads[2].mRequest = nsnull;
if (!mSizeConstrained && (mLoads[0].mIntrinsicSize != mIntrinsicSize)) {
nsCOMPtr<nsIPresShell> presShell;
aPresContext->GetShell(getter_AddRefs(presShell));
NS_ASSERTION(mParent, "No parent to pass the reflow request up to.");
NS_ASSERTION(presShell, "No PresShell.");
if (mParent && presShell && mGotInitialReflow) { // don't reflow if we havn't gotten the inital reflow yet
mState |= NS_FRAME_IS_DIRTY;
mParent->ReflowDirtyChild(presShell, NS_STATIC_CAST(nsIFrame*, this));
}
} else {
nsSize s;
GetSize(s);
nsRect r(0,0, s.width, s.height);
Invalidate(aPresContext, r, PR_FALSE);
}
} else {
mLoads[2].mRequest = nsnull;
}
} else if (NS_FAILED(aStatus)) {
PRBool lowFailed = PR_FALSE; PRBool lowFailed = PR_FALSE;
PRBool imageFailed = PR_FALSE; PRBool imageFailed = PR_FALSE;
// One of the two images didn't load, which one? // One of the two images didn't load, which one?
if (mLowImageRequest == aRequest || !mLowImageRequest) { if (whichLoad == 0 || !mLoads[0].mRequest) {
lowFailed = PR_TRUE;
}
if (mImageRequest == aRequest || !mImageRequest) {
imageFailed = PR_TRUE; imageFailed = PR_TRUE;
} }
if (whichLoad == 1 || !mLoads[1].mRequest) {
lowFailed = PR_TRUE;
}
if (imageFailed && lowFailed) if (imageFailed && lowFailed)
imageFailedToLoad = PR_TRUE; imageFailedToLoad = PR_TRUE;
} }
@ -568,19 +635,25 @@ NS_IMETHODIMP nsImageFrame::OnStopDecode(imgIRequest *aRequest, nsIPresContext *
NS_IMETHODIMP nsImageFrame::FrameChanged(imgIContainer *aContainer, nsIPresContext *aPresContext, gfxIImageFrame *aNewFrame, nsRect *aDirtyRect) NS_IMETHODIMP nsImageFrame::FrameChanged(imgIContainer *aContainer, nsIPresContext *aPresContext, gfxIImageFrame *aNewFrame, nsRect *aDirtyRect)
{ {
nsRect r(*aDirtyRect); if (!mLoads[0].mRequest)
return NS_OK; // if mLoads[0].mRequest is null, this isn't for the first one, so we don't care about it.
float p2t; nsCOMPtr<imgIContainer> con;
aPresContext->GetPixelsToTwips(&p2t); mLoads[0].mRequest->GetImage(getter_AddRefs(con));
r.x = NSIntPixelsToTwips(r.x, p2t); if (aContainer == con.get()) {
r.y = NSIntPixelsToTwips(r.y, p2t); nsRect r(*aDirtyRect);
r.width = NSIntPixelsToTwips(r.width, p2t);
r.height = NSIntPixelsToTwips(r.height, p2t);
mTransform.TransformCoord(&r.x, &r.y, &r.width, &r.height); float p2t;
aPresContext->GetPixelsToTwips(&p2t);
r.x = NSIntPixelsToTwips(r.x, p2t);
r.y = NSIntPixelsToTwips(r.y, p2t);
r.width = NSIntPixelsToTwips(r.width, p2t);
r.height = NSIntPixelsToTwips(r.height, p2t);
Invalidate(aPresContext, r, PR_FALSE); mLoads[0].mTransform.TransformCoord(&r.x, &r.y, &r.width, &r.height);
Invalidate(aPresContext, r, PR_FALSE);
}
return NS_OK; return NS_OK;
} }
@ -597,7 +670,6 @@ nsImageFrame::GetDesiredSize(nsIPresContext* aPresContext,
const nsHTMLReflowState& aReflowState, const nsHTMLReflowState& aReflowState,
nsHTMLReflowMetrics& aDesiredSize) nsHTMLReflowMetrics& aDesiredSize)
{ {
nscoord widthConstraint = NS_INTRINSICSIZE; nscoord widthConstraint = NS_INTRINSICSIZE;
nscoord heightConstraint = NS_INTRINSICSIZE; nscoord heightConstraint = NS_INTRINSICSIZE;
PRBool fixedContentWidth = PR_FALSE; PRBool fixedContentWidth = PR_FALSE;
@ -621,6 +693,18 @@ nsImageFrame::GetDesiredSize(nsIPresContext* aPresContext,
fixedContentHeight = PR_TRUE; fixedContentHeight = PR_TRUE;
} }
// if mLoads[0].mIntrinsicSize.width and height are 0, then we should check to see
// if the size is already known by the image container.
if (mLoads[0].mIntrinsicSize.width == 0 && mLoads[0].mIntrinsicSize.height == 0) {
nsCOMPtr<imgIContainer> con;
mLoads[0].mRequest->GetImage(getter_AddRefs(con));
if (con) {
con->GetWidth(&mLoads[0].mIntrinsicSize.width);
con->GetHeight(&mLoads[0].mIntrinsicSize.height);
}
}
mIntrinsicSize = mLoads[0].mIntrinsicSize;
PRBool haveComputedSize = PR_FALSE; PRBool haveComputedSize = PR_FALSE;
PRBool needIntrinsicImageSize = PR_FALSE; PRBool needIntrinsicImageSize = PR_FALSE;
@ -675,11 +759,13 @@ nsImageFrame::GetDesiredSize(nsIPresContext* aPresContext,
mComputedSize.width = newWidth; mComputedSize.width = newWidth;
mComputedSize.height = newHeight; mComputedSize.height = newHeight;
nsTransform2D *transform = &mLoads[0].mTransform;
if (mComputedSize == mIntrinsicSize) { if (mComputedSize == mIntrinsicSize) {
mTransform.SetToIdentity(); transform->SetToIdentity();
} else { } else {
if (mIntrinsicSize.width != 0 && mIntrinsicSize.height != 0) { if (mIntrinsicSize.width != 0 && mIntrinsicSize.height != 0) {
mTransform.SetToScale(float(mComputedSize.width) / float(mIntrinsicSize.width), transform->SetToScale(float(mComputedSize.width) / float(mIntrinsicSize.width),
float(mComputedSize.height) / float(mIntrinsicSize.height)); float(mComputedSize.height) / float(mIntrinsicSize.height));
} }
} }
@ -977,17 +1063,16 @@ nsImageFrame::Paint(nsIPresContext* aPresContext,
nsCOMPtr<imgIContainer> imgCon; nsCOMPtr<imgIContainer> imgCon;
nsCOMPtr<imgIContainer> lowImgCon; nsCOMPtr<imgIContainer> lowImgCon;
if (mImageRequest) { PRUint32 loadStatus = imgIRequest::STATUS_ERROR;
mImageRequest->GetImage(getter_AddRefs(imgCon));
if (mLoads[0].mRequest) {
mLoads[0].mRequest->GetImage(getter_AddRefs(imgCon));
mLoads[0].mRequest->GetImageStatus(&loadStatus);
} }
if (mLowImageRequest) { if (mLoads[1].mRequest) {
mLowImageRequest->GetImage(getter_AddRefs(lowImgCon)); mLoads[1].mRequest->GetImage(getter_AddRefs(lowImgCon));
} }
PRUint32 loadStatus = imgIRequest::STATUS_ERROR;
if (mImageRequest) {
mImageRequest->GetImageStatus(&loadStatus);
}
if (loadStatus & imgIRequest::STATUS_ERROR || !(imgCon || lowImgCon)) { if (loadStatus & imgIRequest::STATUS_ERROR || !(imgCon || lowImgCon)) {
// No image yet, or image load failed. Draw the alt-text and an icon // No image yet, or image load failed. Draw the alt-text and an icon
// indicating the status // indicating the status
@ -1019,7 +1104,7 @@ nsImageFrame::Paint(nsIPresContext* aPresContext,
if (imgCon) { if (imgCon) {
nsPoint p(inner.x, inner.y); nsPoint p(inner.x, inner.y);
if (mIntrinsicSize == mComputedSize) { if (mLoads[0].mIntrinsicSize == mComputedSize) {
inner.IntersectRect(inner, aDirtyRect); inner.IntersectRect(inner, aDirtyRect);
nsRect r(inner.x, inner.y, inner.width, inner.height); nsRect r(inner.x, inner.y, inner.width, inner.height);
r.x -= mBorderPadding.left; r.x -= mBorderPadding.left;
@ -1027,8 +1112,8 @@ nsImageFrame::Paint(nsIPresContext* aPresContext,
aRenderingContext.DrawImage(imgCon, &r, &p); aRenderingContext.DrawImage(imgCon, &r, &p);
} else { } else {
nsTransform2D trans; nsTransform2D trans;
trans.SetToScale((float(mIntrinsicSize.width) / float(inner.width)), trans.SetToScale((float(mLoads[0].mIntrinsicSize.width) / float(inner.width)),
(float(mIntrinsicSize.height) / float(inner.height))); (float(mLoads[0].mIntrinsicSize.height) / float(inner.height)));
nsRect r(0, 0, inner.width, inner.height); nsRect r(0, 0, inner.width, inner.height);
@ -1409,20 +1494,25 @@ nsImageFrame::AttributeChanged(nsIPresContext* aPresContext,
PRUint32 loadStatus = imgIRequest::STATUS_ERROR; PRUint32 loadStatus = imgIRequest::STATUS_ERROR;
if (mImageRequest) if (mLoads[0].mRequest)
mImageRequest->GetImageStatus(&loadStatus); mLoads[0].mRequest->GetImageStatus(&loadStatus);
if (!(loadStatus & imgIRequest::STATUS_SIZE_AVAILABLE)) { if (!(loadStatus & imgIRequest::STATUS_SIZE_AVAILABLE)) {
if (mImageRequest) { if (mLoads[0].mRequest) {
mFailureReplace = PR_FALSE; // don't cause a CantRenderReplacedElement call mFailureReplace = PR_FALSE; // don't cause a CantRenderReplacedElement call
mImageRequest->Cancel(NS_ERROR_FAILURE); mLoads[0].mRequest->Cancel(NS_ERROR_FAILURE);
mImageRequest = nsnull; mLoads[0].mRequest = nsnull;
} }
mCanSendLoadEvent = PR_TRUE; mCanSendLoadEvent = PR_TRUE;
} }
LoadImage(newSRC, aPresContext, getter_AddRefs(mImageRequest)); if (mLoads[2].mRequest) {
mLoads[2].mRequest->Cancel(NS_ERROR_FAILURE);
mLoads[2].mRequest = nsnull;
}
mLoads[2].mRequest = do_CreateInstance("@mozilla.org/image/request;1");
LoadImage(newSRC, aPresContext, mLoads[2].mRequest);
} }
else if (nsHTMLAtoms::width == aAttribute || nsHTMLAtoms::height == aAttribute) else if (nsHTMLAtoms::width == aAttribute || nsHTMLAtoms::height == aAttribute)
{ // XXX: could check for new width == old width, and make that a no-op { // XXX: could check for new width == old width, and make that a no-op
@ -1448,7 +1538,7 @@ nsImageFrame::GetFrameType(nsIAtom** aType) const
NS_IMETHODIMP NS_IMETHODIMP
nsImageFrame::GetIntrinsicImageSize(nsSize& aSize) nsImageFrame::GetIntrinsicImageSize(nsSize& aSize)
{ {
aSize = mIntrinsicSize; aSize = mLoads[0].mIntrinsicSize;
return NS_OK; return NS_OK;
} }
@ -1459,9 +1549,9 @@ nsImageFrame::GetNaturalImageSize(PRUint32 *naturalWidth,
*naturalWidth = 0; *naturalWidth = 0;
*naturalHeight = 0; *naturalHeight = 0;
if (mImageRequest) { if (mLoads[0].mRequest) {
nsCOMPtr<imgIContainer> container; nsCOMPtr<imgIContainer> container;
mImageRequest->GetImage(getter_AddRefs(container)); mLoads[0].mRequest->GetImage(getter_AddRefs(container));
if (container) { if (container) {
PRInt32 w, h; PRInt32 w, h;
container->GetWidth(&w); container->GetWidth(&w);
@ -1478,7 +1568,7 @@ nsImageFrame::GetNaturalImageSize(PRUint32 *naturalWidth,
NS_IMETHODIMP NS_IMETHODIMP
nsImageFrame::GetImageRequest(imgIRequest **aRequest) nsImageFrame::GetImageRequest(imgIRequest **aRequest)
{ {
*aRequest = mImageRequest; *aRequest = mLoads[0].mRequest;
NS_IF_ADDREF(*aRequest); NS_IF_ADDREF(*aRequest);
return NS_OK; return NS_OK;
} }
@ -1487,13 +1577,13 @@ NS_IMETHODIMP
nsImageFrame::IsImageComplete(PRBool* aComplete) nsImageFrame::IsImageComplete(PRBool* aComplete)
{ {
NS_ENSURE_ARG_POINTER(aComplete); NS_ENSURE_ARG_POINTER(aComplete);
if (!mImageRequest) { if (!mLoads[0].mRequest) {
*aComplete = PR_FALSE; *aComplete = PR_FALSE;
return NS_OK; return NS_OK;
} }
PRUint32 status; PRUint32 status;
mImageRequest->GetImageStatus(&status); mLoads[0].mRequest->GetImageStatus(&status);
*aComplete = ((status & imgIRequest::STATUS_LOAD_COMPLETE) != 0); *aComplete = ((status & imgIRequest::STATUS_LOAD_COMPLETE) != 0);
return NS_OK; return NS_OK;
@ -1516,7 +1606,7 @@ void HaveFixedSize(const nsHTMLReflowState& aReflowState, PRPackedBool& aConstra
nsresult nsresult
nsImageFrame::LoadImage(const nsAReadableString& aSpec, nsIPresContext *aPresContext, imgIRequest **aRequest) nsImageFrame::LoadImage(const nsAReadableString& aSpec, nsIPresContext *aPresContext, imgIRequest *aRequest)
{ {
nsresult rv = NS_OK; nsresult rv = NS_OK;
@ -1561,7 +1651,8 @@ nsImageFrame::LoadImage(const nsAReadableString& aSpec, nsIPresContext *aPresCon
/* set this back to FALSE before we do the real load */ /* set this back to FALSE before we do the real load */
mInitialLoadCompleted = PR_FALSE; mInitialLoadCompleted = PR_FALSE;
return il->LoadImage(uri, loadGroup, mListener, aPresContext, loadFlags, nsnull, aRequest); nsCOMPtr<imgIRequest> tempRequest;
return il->LoadImage(uri, loadGroup, mListener, aPresContext, loadFlags, nsnull, aRequest, getter_AddRefs(tempRequest));
} }
#define INTERNAL_GOPHER_LENGTH 16 /* "internal-gopher-" length */ #define INTERNAL_GOPHER_LENGTH 16 /* "internal-gopher-" length */

Просмотреть файл

@ -74,6 +74,15 @@ private:
nsImageFrame *mFrame; nsImageFrame *mFrame;
}; };
struct ImageLoad {
ImageLoad() : mIntrinsicSize(0,0) { }
nsCOMPtr<imgIRequest> mRequest;
nsSize mIntrinsicSize;
nsTransform2D mTransform;
};
#define ImageFrameSuper nsLeafFrame #define ImageFrameSuper nsLeafFrame
class nsImageFrame : public ImageFrameSuper, public nsIImageFrame { class nsImageFrame : public ImageFrameSuper, public nsIImageFrame {
@ -192,7 +201,7 @@ protected:
nsRect& aInnerArea) const; nsRect& aInnerArea) const;
nsresult LoadImage(const nsAReadableString& aSpec, nsIPresContext *aPresContext, imgIRequest **aRequest); nsresult LoadImage(const nsAReadableString& aSpec, nsIPresContext *aPresContext, imgIRequest *aRequest);
inline PRBool CanLoadImage(nsIURI *aURI); inline PRBool CanLoadImage(nsIURI *aURI);
@ -204,18 +213,26 @@ protected:
void FireDOMEvent(PRUint32 aMessage); void FireDOMEvent(PRUint32 aMessage);
nsImageMap* mImageMap;
nsCOMPtr<imgIRequest> mImageRequest; private:
nsCOMPtr<imgIRequest> mLowImageRequest; inline int GetImageLoad(imgIRequest *aRequest);
nsImageMap* mImageMap;
nsCOMPtr<imgIDecoderObserver> mListener; nsCOMPtr<imgIDecoderObserver> mListener;
/**
* 0 is the current image being displayed on the screen.
* 1 is for the lowsrc image if any.
* 2 is for attribute changed images.
* when the load from 2 completes, it will replace 0.
*/
struct ImageLoad mLoads[3];
nsSize mComputedSize; nsSize mComputedSize;
nsSize mIntrinsicSize; nsSize mIntrinsicSize;
nsTransform2D mTransform;
PRPackedBool mSizeConstrained; PRPackedBool mSizeConstrained;
PRPackedBool mGotInitialReflow; PRPackedBool mGotInitialReflow;
PRPackedBool mInitialLoadCompleted; PRPackedBool mInitialLoadCompleted;

Просмотреть файл

@ -287,7 +287,7 @@ nsImageBoxFrame::UpdateImage(nsIPresContext* aPresContext, PRBool& aResize)
nsCOMPtr<nsILoadGroup> loadGroup; nsCOMPtr<nsILoadGroup> loadGroup;
GetLoadGroup(aPresContext, getter_AddRefs(loadGroup)); GetLoadGroup(aPresContext, getter_AddRefs(loadGroup));
il->LoadImage(srcURI, loadGroup, mListener, aPresContext, nsIRequest::LOAD_NORMAL, nsnull, getter_AddRefs(mImageRequest)); il->LoadImage(srcURI, loadGroup, mListener, aPresContext, nsIRequest::LOAD_NORMAL, nsnull, nsnull, getter_AddRefs(mImageRequest));
aResize = PR_TRUE; aResize = PR_TRUE;

Просмотреть файл

@ -1336,7 +1336,7 @@ nsOutlinerBodyFrame::GetImage(PRInt32 aRowIndex, const PRUnichar* aColID,
nsresult rv; nsresult rv;
nsCOMPtr<imgILoader> il(do_GetService("@mozilla.org/image/loader;1", &rv)); nsCOMPtr<imgILoader> il(do_GetService("@mozilla.org/image/loader;1", &rv));
il->LoadImage(srcURI, nsnull, listener, mPresContext, nsIRequest::LOAD_NORMAL, nsnull, getter_AddRefs(imageRequest)); il->LoadImage(srcURI, nsnull, listener, mPresContext, nsIRequest::LOAD_NORMAL, nsnull, nsnull, getter_AddRefs(imageRequest));
if (!mImageCache) { if (!mImageCache) {
mImageCache = new nsSupportsHashtable(32); mImageCache = new nsSupportsHashtable(32);

Просмотреть файл

@ -1336,7 +1336,7 @@ nsOutlinerBodyFrame::GetImage(PRInt32 aRowIndex, const PRUnichar* aColID,
nsresult rv; nsresult rv;
nsCOMPtr<imgILoader> il(do_GetService("@mozilla.org/image/loader;1", &rv)); nsCOMPtr<imgILoader> il(do_GetService("@mozilla.org/image/loader;1", &rv));
il->LoadImage(srcURI, nsnull, listener, mPresContext, nsIRequest::LOAD_NORMAL, nsnull, getter_AddRefs(imageRequest)); il->LoadImage(srcURI, nsnull, listener, mPresContext, nsIRequest::LOAD_NORMAL, nsnull, nsnull, getter_AddRefs(imageRequest));
if (!mImageCache) { if (!mImageCache) {
mImageCache = new nsSupportsHashtable(32); mImageCache = new nsSupportsHashtable(32);

Просмотреть файл

@ -1 +0,0 @@
ImageLogging.h

Просмотреть файл

@ -28,7 +28,7 @@ include $(DEPTH)/config/autoconf.mk
MODULE = imglib2 MODULE = imglib2
EXPORTS = ImageLogging.h EXPORTS = ImageErrors.h ImageLogging.h
XPIDLSRCS = imgICache.idl \ XPIDLSRCS = imgICache.idl \
imgIContainer.idl \ imgIContainer.idl \

Просмотреть файл

@ -55,8 +55,13 @@ interface imgILoader : nsISupports
* @param aLoadFlags Load flags for the request * @param aLoadFlags Load flags for the request
* @param aCacheKey cache key to use for a load if the original * @param aCacheKey cache key to use for a load if the original
* image came from a request that had post data * image came from a request that had post data
* @param aRequest A newly created, unused imgIRequest object or NULL for one to
be created for you.
*/ */
imgIRequest loadImage(in nsIURI aURI, in nsILoadGroup aLoadGroup, in imgIDecoderObserver aObserver, in nsISupports aCX, in nsLoadFlags aLoadFlags, in nsISupports cacheKey); imgIRequest loadImage(in nsIURI aURI, in nsILoadGroup aLoadGroup,
in imgIDecoderObserver aObserver, in nsISupports aCX,
in nsLoadFlags aLoadFlags, in nsISupports cacheKey,
in imgIRequest aRequest);
/** /**
* Start the load and decode of an image. * Start the load and decode of an image.

Просмотреть файл

@ -68,14 +68,3 @@ interface imgIRequest : nsIRequest
readonly attribute imgIDecoderObserver decoderObserver; readonly attribute imgIDecoderObserver decoderObserver;
}; };
%{C++
/**
* imagelib specific nsresult success and error codes
*/
#define NS_IMAGELIB_SUCCESS_LOAD_FINISHED NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_IMGLIB, 0)
#define NS_IMAGELIB_ERROR_FAILURE NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_IMGLIB, 5)
#define NS_IMAGELIB_ERROR_NO_DECODER NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_IMGLIB, 6)
%}

Просмотреть файл

@ -25,7 +25,7 @@ DEPTH = ..\..\..
MODULE = imglib2 MODULE = imglib2
XPIDL_MODULE = imglib2 XPIDL_MODULE = imglib2
EXPORTS = ImageLogging.h EXPORTS = ImageErrors.h ImageLogging.h
XPIDLSRCS = \ XPIDLSRCS = \
.\imgICache.idl \ .\imgICache.idl \

Просмотреть файл

@ -52,13 +52,9 @@ static nsModuleComponentInfo components[] =
NS_IMGLOADER_CID, NS_IMGLOADER_CID,
"@mozilla.org/image/loader;1", "@mozilla.org/image/loader;1",
imgLoaderConstructor, }, imgLoaderConstructor, },
{ "image request",
NS_IMGREQUEST_CID,
"@mozilla.org/image/request/real;1",
imgRequestConstructor, },
{ "image request proxy", { "image request proxy",
NS_IMGREQUESTPROXY_CID, NS_IMGREQUESTPROXY_CID,
"@mozilla.org/image/request/proxy;1", "@mozilla.org/image/request;1",
imgRequestProxyConstructor, }, imgRequestProxyConstructor, },
}; };

Просмотреть файл

@ -21,7 +21,6 @@
* Stuart Parmenter <pavlov@netscape.com> * Stuart Parmenter <pavlov@netscape.com>
*/ */
#include "imgLoader.h" #include "imgLoader.h"
#include "nsCOMPtr.h" #include "nsCOMPtr.h"
@ -94,8 +93,8 @@ imgLoader::~imgLoader()
#define SHOULD_RELOAD(flags) (flags & nsIRequest::LOAD_BYPASS_CACHE || flags & nsIRequest::VALIDATE_ALWAYS) #define SHOULD_RELOAD(flags) (flags & nsIRequest::LOAD_BYPASS_CACHE || flags & nsIRequest::VALIDATE_ALWAYS)
/* imgIRequest loadImage (in nsIURI aURI, in nsILoadGroup aLoadGroup, in imgIDecoderObserver aObserver, in nsISupports aCX, in nsLoadFlags aLoadFlags, in nsISupports aCacheKey); */ /* imgIRequest loadImage (in nsIURI aURI, in nsILoadGroup aLoadGroup, in imgIDecoderObserver aObserver, in nsISupports aCX, in nsLoadFlags aLoadFlags, in nsISupports cacheKey, in imgIRequest aRequest); */
NS_IMETHODIMP imgLoader::LoadImage(nsIURI *aURI, nsILoadGroup *aLoadGroup, imgIDecoderObserver *aObserver, nsISupports *aCX, nsLoadFlags aLoadFlags, nsISupports* aCacheKey, imgIRequest **_retval) NS_IMETHODIMP imgLoader::LoadImage(nsIURI *aURI, nsILoadGroup *aLoadGroup, imgIDecoderObserver *aObserver, nsISupports *aCX, nsLoadFlags aLoadFlags, nsISupports *cacheKey, imgIRequest *aRequest, imgIRequest **_retval)
{ {
NS_ASSERTION(aURI, "imgLoader::LoadImage -- NULL URI pointer"); NS_ASSERTION(aURI, "imgLoader::LoadImage -- NULL URI pointer");
@ -232,7 +231,7 @@ NS_IMETHODIMP imgLoader::LoadImage(nsIURI *aURI, nsILoadGroup *aLoadGroup, imgID
LOG_MSG(gImgLog, "imgLoader::LoadImage", "async open failed."); LOG_MSG(gImgLog, "imgLoader::LoadImage", "async open failed.");
nsresult rv = CreateNewProxyForRequest(request, aLoadGroup, aObserver, nsresult rv = CreateNewProxyForRequest(request, aLoadGroup, aObserver,
aCX, aLoadFlags, _retval); aCX, aLoadFlags, aRequest, _retval);
if (NS_SUCCEEDED(rv)) { if (NS_SUCCEEDED(rv)) {
request->OnStartRequest(newChannel, nsnull); request->OnStartRequest(newChannel, nsnull);
request->OnStopRequest(newChannel, nsnull, NS_BINDING_ABORTED); request->OnStopRequest(newChannel, nsnull, NS_BINDING_ABORTED);
@ -250,7 +249,7 @@ NS_IMETHODIMP imgLoader::LoadImage(nsIURI *aURI, nsILoadGroup *aLoadGroup, imgID
LOG_MSG(gImgLog, "imgLoader::LoadImage", "creating proxy request."); LOG_MSG(gImgLog, "imgLoader::LoadImage", "creating proxy request.");
nsresult rv = CreateNewProxyForRequest(request, aLoadGroup, aObserver, aCX, aLoadFlags, _retval); nsresult rv = CreateNewProxyForRequest(request, aLoadGroup, aObserver, aCX, aLoadFlags, aRequest, _retval);
NS_RELEASE(request); NS_RELEASE(request);
@ -308,7 +307,7 @@ NS_IMETHODIMP imgLoader::LoadImageWithChannel(nsIChannel *channel, imgIDecoderOb
nsCOMPtr<nsILoadGroup> loadGroup; nsCOMPtr<nsILoadGroup> loadGroup;
channel->GetLoadGroup(getter_AddRefs(loadGroup)); channel->GetLoadGroup(getter_AddRefs(loadGroup));
nsresult rv = CreateNewProxyForRequest(request, loadGroup, aObserver, cx, nsIRequest::LOAD_NORMAL, _retval); nsresult rv = CreateNewProxyForRequest(request, loadGroup, aObserver, cx, nsIRequest::LOAD_NORMAL, nsnull, _retval);
NS_RELEASE(request); NS_RELEASE(request);
@ -316,11 +315,11 @@ NS_IMETHODIMP imgLoader::LoadImageWithChannel(nsIChannel *channel, imgIDecoderOb
} }
nsresult nsresult
imgLoader::CreateNewProxyForRequest(imgRequest *aRequest, nsILoadGroup *aLoadGroup, imgLoader::CreateNewProxyForRequest(imgRequest *aRequest, nsILoadGroup *aLoadGroup,
imgIDecoderObserver *aObserver, nsISupports *cx, imgIDecoderObserver *aObserver, nsISupports *cx,
nsLoadFlags aLoadFlags, imgIRequest **_retval) nsLoadFlags aLoadFlags, imgIRequest *aProxyRequest,
imgIRequest **_retval)
{ {
LOG_SCOPE_WITH_PARAM(gImgLog, "imgLoader::CreateNewProxyForRequest", "imgRequest", aRequest); LOG_SCOPE_WITH_PARAM(gImgLog, "imgLoader::CreateNewProxyForRequest", "imgRequest", aRequest);
@ -330,9 +329,12 @@ imgLoader::CreateNewProxyForRequest(imgRequest *aRequest, nsILoadGroup *aLoadGro
*/ */
imgRequestProxy *proxyRequest; imgRequestProxy *proxyRequest;
NS_NEWXPCOM(proxyRequest, imgRequestProxy); if (aProxyRequest) {
if (!proxyRequest) return NS_ERROR_OUT_OF_MEMORY; proxyRequest = NS_STATIC_CAST(imgRequestProxy *, aProxyRequest);
} else {
NS_NEWXPCOM(proxyRequest, imgRequestProxy);
if (!proxyRequest) return NS_ERROR_OUT_OF_MEMORY;
}
NS_ADDREF(proxyRequest); NS_ADDREF(proxyRequest);
/* It is important to call |SetLoadFlags()| before calling |Init()| because /* It is important to call |SetLoadFlags()| before calling |Init()| because

Просмотреть файл

@ -52,7 +52,8 @@ public:
private: private:
nsresult CreateNewProxyForRequest(imgRequest *aRequest, nsILoadGroup *aLoadGroup, nsresult CreateNewProxyForRequest(imgRequest *aRequest, nsILoadGroup *aLoadGroup,
imgIDecoderObserver *aObserver, nsISupports *cx, imgIDecoderObserver *aObserver, nsISupports *cx,
nsLoadFlags aLoadFlags, imgIRequest **_retval); nsLoadFlags aLoadFlags, imgIRequest *aRequestProxy,
imgIRequest **_retval);
}; };

Просмотреть файл

@ -27,6 +27,7 @@
#include "imgRequestProxy.h" #include "imgRequestProxy.h"
#include "imgILoader.h" #include "imgILoader.h"
#include "ImageErrors.h"
#include "ImageLogging.h" #include "ImageLogging.h"
#include "gfxIImageFrame.h" #include "gfxIImageFrame.h"