зеркало из https://github.com/mozilla/pjs.git
Construct all our image loaders when we create frames so that we can allow arbitrary numbers of image loaders per frame (for multiple background images). (Bug 322475) r+sr=bzbarsky
This commit is contained in:
Родитель
8353f3b1b1
Коммит
6a55a4774c
|
@ -41,6 +41,7 @@
|
||||||
|
|
||||||
#include "nsIDOMDataContainerEvent.h"
|
#include "nsIDOMDataContainerEvent.h"
|
||||||
#include "nsDOMEvent.h"
|
#include "nsDOMEvent.h"
|
||||||
|
#include "nsInterfaceHashtable.h"
|
||||||
|
|
||||||
class nsDOMDataContainerEvent : public nsDOMEvent,
|
class nsDOMDataContainerEvent : public nsDOMEvent,
|
||||||
public nsIDOMDataContainerEvent
|
public nsIDOMDataContainerEvent
|
||||||
|
|
|
@ -1518,9 +1518,12 @@ nsCSSRendering::PaintBackgroundWithSC(nsPresContext* aPresContext,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Lookup the image
|
// Ensure we get invalidated for loads of the image. We need to do
|
||||||
imgIRequest *req = aPresContext->LoadImage(aColor.mBackgroundImage,
|
// this here because this might be the only code that knows about the
|
||||||
aForFrame);
|
// association of the style data with the frame.
|
||||||
|
aPresContext->SetupBackgroundImageLoaders(aForFrame, &aColor);
|
||||||
|
|
||||||
|
imgIRequest *req = aColor.mBackgroundImage;
|
||||||
|
|
||||||
PRUint32 status = imgIRequest::STATUS_ERROR;
|
PRUint32 status = imgIRequest::STATUS_ERROR;
|
||||||
if (req)
|
if (req)
|
||||||
|
@ -1725,9 +1728,16 @@ DrawBorderImage(nsPresContext* aPresContext,
|
||||||
if (aDirtyRect.IsEmpty())
|
if (aDirtyRect.IsEmpty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Clone the image loader and set up animation notifications.
|
// Ensure we get invalidated for loads and animations of the image.
|
||||||
imgIRequest *req =
|
// We need to do this here because this might be the only code that
|
||||||
aPresContext->LoadBorderImage(aBorderStyle.GetBorderImage(), aForFrame);
|
// knows about the association of the style data with the frame.
|
||||||
|
// XXX We shouldn't really... since if anybody is passing in a
|
||||||
|
// different style, they'll potentially have the wrong size for the
|
||||||
|
// border too.
|
||||||
|
aPresContext->SetupBorderImageLoaders(aForFrame, &aBorderStyle);
|
||||||
|
|
||||||
|
imgIRequest *req = aBorderStyle.GetBorderImage();
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
{
|
{
|
||||||
PRUint32 status = imgIRequest::STATUS_ERROR;
|
PRUint32 status = imgIRequest::STATUS_ERROR;
|
||||||
|
|
|
@ -91,7 +91,6 @@
|
||||||
#include "nsLayoutUtils.h"
|
#include "nsLayoutUtils.h"
|
||||||
#include "nsAutoPtr.h"
|
#include "nsAutoPtr.h"
|
||||||
#include "imgIRequest.h"
|
#include "imgIRequest.h"
|
||||||
#include "nsStyleStructInlines.h"
|
|
||||||
|
|
||||||
#include "nsFrameManager.h"
|
#include "nsFrameManager.h"
|
||||||
#ifdef ACCESSIBILITY
|
#ifdef ACCESSIBILITY
|
||||||
|
@ -1085,24 +1084,6 @@ CaptureChange(nsStyleContext* aOldContext, nsStyleContext* aNewContext,
|
||||||
return aMinChange;
|
return aMinChange;
|
||||||
}
|
}
|
||||||
|
|
||||||
static PRBool
|
|
||||||
ShouldStopImage(imgIRequest *aOldImage, imgIRequest *aNewImage)
|
|
||||||
{
|
|
||||||
if (!aOldImage)
|
|
||||||
return PR_FALSE;
|
|
||||||
|
|
||||||
PRBool stopImages = !aNewImage;
|
|
||||||
if (!stopImages) {
|
|
||||||
nsCOMPtr<nsIURI> oldURI, newURI;
|
|
||||||
aOldImage->GetURI(getter_AddRefs(oldURI));
|
|
||||||
aNewImage->GetURI(getter_AddRefs(newURI));
|
|
||||||
PRBool equal;
|
|
||||||
stopImages =
|
|
||||||
NS_FAILED(oldURI->Equals(newURI, &equal)) || !equal;
|
|
||||||
}
|
|
||||||
return stopImages;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Recompute style for aFrame and accumulate changes into aChangeList
|
* Recompute style for aFrame and accumulate changes into aChangeList
|
||||||
* given that aMinChange is already accumulated for an ancestor.
|
* given that aMinChange is already accumulated for an ancestor.
|
||||||
|
@ -1264,33 +1245,6 @@ nsFrameManager::ReResolveStyleContext(nsPresContext *aPresContext,
|
||||||
// if frame gets regenerated, let it keep old context
|
// if frame gets regenerated, let it keep old context
|
||||||
aFrame->SetStyleContext(newContext);
|
aFrame->SetStyleContext(newContext);
|
||||||
}
|
}
|
||||||
// if old context had image and new context does not have the same image,
|
|
||||||
// stop the image load for the frame
|
|
||||||
if (ShouldStopImage(
|
|
||||||
oldContext->GetStyleBackground()->mBackgroundImage,
|
|
||||||
newContext->GetStyleBackground()->mBackgroundImage)) {
|
|
||||||
// stop the image loading for the frame, the image has changed
|
|
||||||
aPresContext->StopBackgroundImageFor(aFrame);
|
|
||||||
}
|
|
||||||
|
|
||||||
imgIRequest *newBorderImage =
|
|
||||||
newContext->GetStyleBorder()->GetBorderImage();
|
|
||||||
if (ShouldStopImage(oldContext->GetStyleBorder()->GetBorderImage(),
|
|
||||||
newBorderImage)) {
|
|
||||||
// stop the image loading for the frame, the image has changed
|
|
||||||
aPresContext->StopBorderImageFor(aFrame);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Since the CalcDifference call depended on the result of
|
|
||||||
// GetActualBorder() and that result depends on whether the
|
|
||||||
// image has loaded, start the image load now so that we'll get
|
|
||||||
// notified when it completes loading and can do a restyle.
|
|
||||||
// Otherwise, the image might finish loading from the network
|
|
||||||
// before we start listening to its notifications, and then
|
|
||||||
// we'll never know that it's finished loading.
|
|
||||||
if (newBorderImage) {
|
|
||||||
aPresContext->LoadBorderImage(newBorderImage, aFrame);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
oldContext->Release();
|
oldContext->Release();
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,36 +63,49 @@
|
||||||
|
|
||||||
NS_IMPL_ISUPPORTS2(nsImageLoader, imgIDecoderObserver, imgIContainerObserver)
|
NS_IMPL_ISUPPORTS2(nsImageLoader, imgIDecoderObserver, imgIContainerObserver)
|
||||||
|
|
||||||
nsImageLoader::nsImageLoader() :
|
nsImageLoader::nsImageLoader(nsIFrame *aFrame, PRBool aReflowOnLoad,
|
||||||
mFrame(nsnull), mPresContext(nsnull)
|
nsImageLoader *aNextLoader)
|
||||||
|
: mFrame(aFrame),
|
||||||
|
mReflowOnLoad(aReflowOnLoad),
|
||||||
|
mNextLoader(aNextLoader)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
nsImageLoader::~nsImageLoader()
|
nsImageLoader::~nsImageLoader()
|
||||||
{
|
{
|
||||||
mFrame = nsnull;
|
mFrame = nsnull;
|
||||||
mPresContext = nsnull;
|
|
||||||
|
|
||||||
if (mRequest) {
|
if (mRequest) {
|
||||||
mRequest->CancelAndForgetObserver(NS_ERROR_FAILURE);
|
mRequest->CancelAndForgetObserver(NS_ERROR_FAILURE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* static */ already_AddRefed<nsImageLoader>
|
||||||
void
|
nsImageLoader::Create(nsIFrame *aFrame, imgIRequest *aRequest,
|
||||||
nsImageLoader::Init(nsIFrame *aFrame, nsPresContext *aPresContext,
|
PRBool aReflowOnLoad, nsImageLoader *aNextLoader)
|
||||||
PRBool aReflowOnLoad)
|
|
||||||
{
|
{
|
||||||
mFrame = aFrame;
|
nsRefPtr<nsImageLoader> loader =
|
||||||
mPresContext = aPresContext;
|
new nsImageLoader(aFrame, aReflowOnLoad, aNextLoader);
|
||||||
mReflowOnLoad = aReflowOnLoad;
|
|
||||||
|
loader->Load(aRequest);
|
||||||
|
|
||||||
|
return loader.forget();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
nsImageLoader::Destroy()
|
nsImageLoader::Destroy()
|
||||||
{
|
{
|
||||||
|
// Destroy the chain with only one level of recursion.
|
||||||
|
nsRefPtr<nsImageLoader> list = mNextLoader;
|
||||||
|
mNextLoader = nsnull;
|
||||||
|
while (list) {
|
||||||
|
nsRefPtr<nsImageLoader> todestroy = list;
|
||||||
|
list = todestroy->mNextLoader;
|
||||||
|
todestroy->mNextLoader = nsnull;
|
||||||
|
todestroy->Destroy();
|
||||||
|
}
|
||||||
|
|
||||||
mFrame = nsnull;
|
mFrame = nsnull;
|
||||||
mPresContext = nsnull;
|
|
||||||
|
|
||||||
if (mRequest) {
|
if (mRequest) {
|
||||||
mRequest->CancelAndForgetObserver(NS_ERROR_FAILURE);
|
mRequest->CancelAndForgetObserver(NS_ERROR_FAILURE);
|
||||||
|
@ -104,28 +117,14 @@ nsImageLoader::Destroy()
|
||||||
nsresult
|
nsresult
|
||||||
nsImageLoader::Load(imgIRequest *aImage)
|
nsImageLoader::Load(imgIRequest *aImage)
|
||||||
{
|
{
|
||||||
|
NS_ASSERTION(!mRequest, "can't reuse image loaders");
|
||||||
|
|
||||||
if (!mFrame)
|
if (!mFrame)
|
||||||
return NS_ERROR_NOT_INITIALIZED;
|
return NS_ERROR_NOT_INITIALIZED;
|
||||||
|
|
||||||
if (!aImage)
|
if (!aImage)
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
|
|
||||||
if (mRequest) {
|
|
||||||
nsCOMPtr<nsIURI> oldURI;
|
|
||||||
mRequest->GetURI(getter_AddRefs(oldURI));
|
|
||||||
nsCOMPtr<nsIURI> newURI;
|
|
||||||
aImage->GetURI(getter_AddRefs(newURI));
|
|
||||||
PRBool eq = PR_FALSE;
|
|
||||||
nsresult rv = newURI->Equals(oldURI, &eq);
|
|
||||||
if (NS_SUCCEEDED(rv) && eq) {
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now cancel the old request so it won't hold a stale ref to us.
|
|
||||||
mRequest->CancelAndForgetObserver(NS_ERROR_FAILURE);
|
|
||||||
mRequest = nsnull;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make sure to clone into a temporary, then set mRequest, since
|
// Make sure to clone into a temporary, then set mRequest, since
|
||||||
// cloning may notify and we don't want to trigger paints from this
|
// cloning may notify and we don't want to trigger paints from this
|
||||||
// code.
|
// code.
|
||||||
|
@ -147,7 +146,7 @@ NS_IMETHODIMP nsImageLoader::OnStartContainer(imgIRequest *aRequest,
|
||||||
* one frame = 1
|
* one frame = 1
|
||||||
* one loop = 2
|
* one loop = 2
|
||||||
*/
|
*/
|
||||||
aImage->SetAnimationMode(mPresContext->ImageAnimationMode());
|
aImage->SetAnimationMode(mFrame->PresContext()->ImageAnimationMode());
|
||||||
// Ensure the animation (if any) is started.
|
// Ensure the animation (if any) is started.
|
||||||
aImage->StartAnimation();
|
aImage->StartAnimation();
|
||||||
}
|
}
|
||||||
|
@ -206,7 +205,7 @@ void
|
||||||
nsImageLoader::RedrawDirtyFrame(const nsRect* aDamageRect)
|
nsImageLoader::RedrawDirtyFrame(const nsRect* aDamageRect)
|
||||||
{
|
{
|
||||||
if (mReflowOnLoad) {
|
if (mReflowOnLoad) {
|
||||||
nsIPresShell *shell = mPresContext->GetPresShell();
|
nsIPresShell *shell = mFrame->PresContext()->GetPresShell();
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
nsresult rv =
|
nsresult rv =
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -37,23 +37,35 @@
|
||||||
*
|
*
|
||||||
* ***** END LICENSE BLOCK ***** */
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
/* class to notify frames of background image loads */
|
/* class to notify frames of background and border image loads */
|
||||||
|
|
||||||
#include "nsStubImageDecoderObserver.h"
|
#include "nsStubImageDecoderObserver.h"
|
||||||
|
|
||||||
class nsPresContext;
|
|
||||||
class nsIFrame;
|
class nsIFrame;
|
||||||
class nsIURI;
|
class nsIURI;
|
||||||
|
|
||||||
#include "imgIRequest.h"
|
#include "imgIRequest.h"
|
||||||
#include "nsCOMPtr.h"
|
#include "nsCOMPtr.h"
|
||||||
|
#include "nsAutoPtr.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Image loaders pass notifications for background and border image
|
||||||
|
* loading and animation on to the frames.
|
||||||
|
*
|
||||||
|
* Each frame's image loaders form a linked list.
|
||||||
|
*/
|
||||||
class nsImageLoader : public nsStubImageDecoderObserver
|
class nsImageLoader : public nsStubImageDecoderObserver
|
||||||
{
|
{
|
||||||
public:
|
private:
|
||||||
nsImageLoader();
|
nsImageLoader(nsIFrame *aFrame, PRBool aReflowOnLoad,
|
||||||
|
nsImageLoader *aNextLoader);
|
||||||
virtual ~nsImageLoader();
|
virtual ~nsImageLoader();
|
||||||
|
|
||||||
|
public:
|
||||||
|
static already_AddRefed<nsImageLoader>
|
||||||
|
Create(nsIFrame *aFrame, imgIRequest *aRequest,
|
||||||
|
PRBool aReflowOnLoad, nsImageLoader *aNextLoader);
|
||||||
|
|
||||||
NS_DECL_ISUPPORTS
|
NS_DECL_ISUPPORTS
|
||||||
|
|
||||||
// imgIDecoderObserver (override nsStubImageDecoderObserver)
|
// imgIDecoderObserver (override nsStubImageDecoderObserver)
|
||||||
|
@ -69,21 +81,17 @@ public:
|
||||||
NS_IMETHOD FrameChanged(imgIContainer *aContainer, gfxIImageFrame *newframe,
|
NS_IMETHOD FrameChanged(imgIContainer *aContainer, gfxIImageFrame *newframe,
|
||||||
nsIntRect *dirtyRect);
|
nsIntRect *dirtyRect);
|
||||||
|
|
||||||
void Init(nsIFrame *aFrame, nsPresContext *aPresContext,
|
|
||||||
PRBool aReflowOnLoad);
|
|
||||||
nsresult Load(imgIRequest *aImage);
|
|
||||||
|
|
||||||
void Destroy();
|
void Destroy();
|
||||||
|
|
||||||
nsIFrame *GetFrame() { return mFrame; }
|
|
||||||
imgIRequest *GetRequest() { return mRequest; }
|
imgIRequest *GetRequest() { return mRequest; }
|
||||||
|
nsImageLoader *GetNextLoader() { return mNextLoader; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
nsresult Load(imgIRequest *aImage);
|
||||||
void RedrawDirtyFrame(const nsRect* aDamageRect);
|
void RedrawDirtyFrame(const nsRect* aDamageRect);
|
||||||
|
|
||||||
private:
|
|
||||||
nsIFrame *mFrame;
|
nsIFrame *mFrame;
|
||||||
nsPresContext *mPresContext;
|
|
||||||
nsCOMPtr<imgIRequest> mRequest;
|
nsCOMPtr<imgIRequest> mRequest;
|
||||||
PRBool mReflowOnLoad;
|
PRBool mReflowOnLoad;
|
||||||
|
nsRefPtr<nsImageLoader> mNextLoader;
|
||||||
};
|
};
|
||||||
|
|
|
@ -89,6 +89,7 @@
|
||||||
#include "nsCSSRules.h"
|
#include "nsCSSRules.h"
|
||||||
#include "nsFontFaceLoader.h"
|
#include "nsFontFaceLoader.h"
|
||||||
#include "nsIEventListenerManager.h"
|
#include "nsIEventListenerManager.h"
|
||||||
|
#include "nsStyleStructInlines.h"
|
||||||
|
|
||||||
#ifdef MOZ_SMIL
|
#ifdef MOZ_SMIL
|
||||||
#include "nsSMILAnimationController.h"
|
#include "nsSMILAnimationController.h"
|
||||||
|
@ -159,7 +160,7 @@ IsVisualCharset(const nsCString& aCharset)
|
||||||
|
|
||||||
|
|
||||||
static PLDHashOperator
|
static PLDHashOperator
|
||||||
destroy_loads(const void * aKey, nsCOMPtr<nsImageLoader>& aData, void* closure)
|
destroy_loads(const void * aKey, nsRefPtr<nsImageLoader>& aData, void* closure)
|
||||||
{
|
{
|
||||||
aData->Destroy();
|
aData->Destroy();
|
||||||
return PL_DHASH_NEXT;
|
return PL_DHASH_NEXT;
|
||||||
|
@ -246,8 +247,8 @@ nsPresContext::nsPresContext(nsIDocument* aDocument, nsPresContextType aType)
|
||||||
|
|
||||||
nsPresContext::~nsPresContext()
|
nsPresContext::~nsPresContext()
|
||||||
{
|
{
|
||||||
mImageLoaders.Enumerate(destroy_loads, nsnull);
|
for (PRUint32 i = 0; i < IMAGE_LOAD_TYPE_COUNT; ++i)
|
||||||
mBorderImageLoaders.Enumerate(destroy_loads, nsnull);
|
mImageLoaders[i].Enumerate(destroy_loads, nsnull);
|
||||||
|
|
||||||
NS_PRECONDITION(!mShell, "Presshell forgot to clear our mShell pointer");
|
NS_PRECONDITION(!mShell, "Presshell forgot to clear our mShell pointer");
|
||||||
SetShell(nsnull);
|
SetShell(nsnull);
|
||||||
|
@ -313,7 +314,7 @@ NS_IMPL_CYCLE_COLLECTING_ADDREF(nsPresContext)
|
||||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(nsPresContext)
|
NS_IMPL_CYCLE_COLLECTING_RELEASE(nsPresContext)
|
||||||
|
|
||||||
static PLDHashOperator
|
static PLDHashOperator
|
||||||
TraverseImageLoader(const void * aKey, nsCOMPtr<nsImageLoader>& aData,
|
TraverseImageLoader(const void * aKey, nsRefPtr<nsImageLoader>& aData,
|
||||||
void* aClosure)
|
void* aClosure)
|
||||||
{
|
{
|
||||||
nsCycleCollectionTraversalCallback *cb =
|
nsCycleCollectionTraversalCallback *cb =
|
||||||
|
@ -331,8 +332,8 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsPresContext)
|
||||||
// NS_IMPL_CYCLE_COLLECTION_TRAVERSE_RAWPTR(mLookAndFeel); // a service
|
// NS_IMPL_CYCLE_COLLECTION_TRAVERSE_RAWPTR(mLookAndFeel); // a service
|
||||||
// NS_IMPL_CYCLE_COLLECTION_TRAVERSE_RAWPTR(mLangGroup); // an atom
|
// NS_IMPL_CYCLE_COLLECTION_TRAVERSE_RAWPTR(mLangGroup); // an atom
|
||||||
|
|
||||||
tmp->mImageLoaders.Enumerate(TraverseImageLoader, &cb);
|
for (PRUint32 i = 0; i < IMAGE_LOAD_TYPE_COUNT; ++i)
|
||||||
tmp->mBorderImageLoaders.Enumerate(TraverseImageLoader, &cb);
|
tmp->mImageLoaders[i].Enumerate(TraverseImageLoader, &cb);
|
||||||
|
|
||||||
// NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mTheme); // a service
|
// NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mTheme); // a service
|
||||||
// NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mLangService); // a service
|
// NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mLangService); // a service
|
||||||
|
@ -354,10 +355,10 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsPresContext)
|
||||||
// NS_RELEASE(tmp->mLookAndFeel); // a service
|
// NS_RELEASE(tmp->mLookAndFeel); // a service
|
||||||
// NS_RELEASE(tmp->mLangGroup); // an atom
|
// NS_RELEASE(tmp->mLangGroup); // an atom
|
||||||
|
|
||||||
tmp->mImageLoaders.Enumerate(destroy_loads, nsnull);
|
for (PRUint32 i = 0; i < IMAGE_LOAD_TYPE_COUNT; ++i) {
|
||||||
tmp->mImageLoaders.Clear();
|
tmp->mImageLoaders[i].Enumerate(destroy_loads, nsnull);
|
||||||
tmp->mBorderImageLoaders.Enumerate(destroy_loads, nsnull);
|
tmp->mImageLoaders[i].Clear();
|
||||||
tmp->mBorderImageLoaders.Clear();
|
}
|
||||||
|
|
||||||
// NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mTheme); // a service
|
// NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mTheme); // a service
|
||||||
// NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mLangService); // a service
|
// NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mLangService); // a service
|
||||||
|
@ -837,11 +838,9 @@ nsPresContext::Init(nsIDeviceContext* aDeviceContext)
|
||||||
mDeviceContext->FlushFontCache();
|
mDeviceContext->FlushFontCache();
|
||||||
mCurAppUnitsPerDevPixel = AppUnitsPerDevPixel();
|
mCurAppUnitsPerDevPixel = AppUnitsPerDevPixel();
|
||||||
|
|
||||||
if (!mImageLoaders.Init())
|
for (PRUint32 i = 0; i < IMAGE_LOAD_TYPE_COUNT; ++i)
|
||||||
return NS_ERROR_OUT_OF_MEMORY;
|
if (!mImageLoaders[i].Init())
|
||||||
|
return NS_ERROR_OUT_OF_MEMORY;
|
||||||
if (!mBorderImageLoaders.Init())
|
|
||||||
return NS_ERROR_OUT_OF_MEMORY;
|
|
||||||
|
|
||||||
// Get the look and feel service here; default colors will be initialized
|
// Get the look and feel service here; default colors will be initialized
|
||||||
// from calling GetUserPreferences() when we get a presshell.
|
// from calling GetUserPreferences() when we get a presshell.
|
||||||
|
@ -1058,10 +1057,13 @@ static void SetImgAnimModeOnImgReq(imgIRequest* aImgReq, PRUint16 aMode)
|
||||||
|
|
||||||
// Enumeration call back for HashTable
|
// Enumeration call back for HashTable
|
||||||
static PLDHashOperator
|
static PLDHashOperator
|
||||||
set_animation_mode(const void * aKey, nsCOMPtr<nsImageLoader>& aData, void* closure)
|
set_animation_mode(const void * aKey, nsRefPtr<nsImageLoader>& aData, void* closure)
|
||||||
{
|
{
|
||||||
imgIRequest* imgReq = aData->GetRequest();
|
for (nsImageLoader *loader = aData; loader;
|
||||||
SetImgAnimModeOnImgReq(imgReq, (PRUint16)NS_PTR_TO_INT32(closure));
|
loader = loader->GetNextLoader()) {
|
||||||
|
imgIRequest* imgReq = loader->GetRequest();
|
||||||
|
SetImgAnimModeOnImgReq(imgReq, (PRUint16)NS_PTR_TO_INT32(closure));
|
||||||
|
}
|
||||||
return PL_DHASH_NEXT;
|
return PL_DHASH_NEXT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1122,8 +1124,8 @@ nsPresContext::SetImageAnimationModeInternal(PRUint16 aMode)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Set the mode on the image loaders.
|
// Set the mode on the image loaders.
|
||||||
mImageLoaders.Enumerate(set_animation_mode, NS_INT32_TO_PTR(aMode));
|
for (PRUint32 i = 0; i < IMAGE_LOAD_TYPE_COUNT; ++i)
|
||||||
mBorderImageLoaders.Enumerate(set_animation_mode, NS_INT32_TO_PTR(aMode));
|
mImageLoaders[i].Enumerate(set_animation_mode, NS_INT32_TO_PTR(aMode));
|
||||||
|
|
||||||
// Now walk the content tree and set the animation mode
|
// Now walk the content tree and set the animation mode
|
||||||
// on all the images.
|
// on all the images.
|
||||||
|
@ -1228,66 +1230,51 @@ nsPresContext::SetFullZoom(float aZoom)
|
||||||
mCurAppUnitsPerDevPixel = AppUnitsPerDevPixel();
|
mCurAppUnitsPerDevPixel = AppUnitsPerDevPixel();
|
||||||
}
|
}
|
||||||
|
|
||||||
imgIRequest*
|
void
|
||||||
nsPresContext::DoLoadImage(nsPresContext::ImageLoaderTable& aTable,
|
nsPresContext::SetImageLoaders(nsIFrame* aTargetFrame,
|
||||||
imgIRequest* aImage,
|
ImageLoadType aType,
|
||||||
nsIFrame* aTargetFrame,
|
nsImageLoader* aImageLoaders)
|
||||||
PRBool aReflowOnLoad)
|
|
||||||
{
|
{
|
||||||
// look and see if we have a loader for the target frame.
|
nsRefPtr<nsImageLoader> oldLoaders;
|
||||||
nsCOMPtr<nsImageLoader> loader;
|
mImageLoaders[aType].Get(aTargetFrame, getter_AddRefs(oldLoaders));
|
||||||
aTable.Get(aTargetFrame, getter_AddRefs(loader));
|
|
||||||
|
|
||||||
if (!loader) {
|
if (aImageLoaders) {
|
||||||
loader = new nsImageLoader();
|
mImageLoaders[aType].Put(aTargetFrame, aImageLoaders);
|
||||||
if (!loader)
|
} else if (oldLoaders) {
|
||||||
return nsnull;
|
mImageLoaders[aType].Remove(aTargetFrame);
|
||||||
|
|
||||||
loader->Init(aTargetFrame, this, aReflowOnLoad);
|
|
||||||
aTable.Put(aTargetFrame, loader);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
loader->Load(aImage);
|
if (oldLoaders)
|
||||||
|
oldLoaders->Destroy();
|
||||||
imgIRequest *request = loader->GetRequest();
|
|
||||||
|
|
||||||
return request;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
imgIRequest*
|
void
|
||||||
nsPresContext::LoadImage(imgIRequest* aImage, nsIFrame* aTargetFrame)
|
nsPresContext::SetupBackgroundImageLoaders(nsIFrame* aFrame,
|
||||||
|
const nsStyleBackground* aStyleBackground)
|
||||||
{
|
{
|
||||||
return DoLoadImage(mImageLoaders, aImage, aTargetFrame, PR_FALSE);
|
nsRefPtr<nsImageLoader> loader =
|
||||||
|
nsImageLoader::Create(aFrame, aStyleBackground->mBackgroundImage,
|
||||||
|
PR_FALSE, nsnull);
|
||||||
|
SetImageLoaders(aFrame, BACKGROUND_IMAGE, loader);
|
||||||
}
|
}
|
||||||
|
|
||||||
imgIRequest*
|
void
|
||||||
nsPresContext::LoadBorderImage(imgIRequest* aImage, nsIFrame* aTargetFrame)
|
nsPresContext::SetupBorderImageLoaders(nsIFrame* aFrame,
|
||||||
|
const nsStyleBorder* aStyleBorder)
|
||||||
{
|
{
|
||||||
return DoLoadImage(mBorderImageLoaders, aImage, aTargetFrame,
|
nsRefPtr<nsImageLoader> loader =
|
||||||
aTargetFrame->GetStyleBorder()->ImageBorderDiffers());
|
nsImageLoader::Create(aFrame, aStyleBorder->GetBorderImage(),
|
||||||
|
aStyleBorder->ImageBorderDiffers(), nsnull);
|
||||||
|
SetImageLoaders(aFrame, BORDER_IMAGE, loader);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
nsPresContext::StopImagesFor(nsIFrame* aTargetFrame)
|
nsPresContext::StopImagesFor(nsIFrame* aTargetFrame)
|
||||||
{
|
{
|
||||||
StopBackgroundImageFor(aTargetFrame);
|
for (PRUint32 i = 0; i < IMAGE_LOAD_TYPE_COUNT; ++i)
|
||||||
StopBorderImageFor(aTargetFrame);
|
SetImageLoaders(aTargetFrame, ImageLoadType(i), nsnull);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
nsPresContext::DoStopImageFor(nsPresContext::ImageLoaderTable& aTable,
|
|
||||||
nsIFrame* aTargetFrame)
|
|
||||||
{
|
|
||||||
nsCOMPtr<nsImageLoader> loader;
|
|
||||||
aTable.Get(aTargetFrame, getter_AddRefs(loader));
|
|
||||||
|
|
||||||
if (loader) {
|
|
||||||
loader->Destroy();
|
|
||||||
|
|
||||||
aTable.Remove(aTargetFrame);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
nsPresContext::SetContainer(nsISupports* aHandler)
|
nsPresContext::SetContainer(nsISupports* aHandler)
|
||||||
{
|
{
|
||||||
|
|
|
@ -60,7 +60,7 @@
|
||||||
#include "nsPropertyTable.h"
|
#include "nsPropertyTable.h"
|
||||||
#include "nsGkAtoms.h"
|
#include "nsGkAtoms.h"
|
||||||
#include "nsIDocument.h"
|
#include "nsIDocument.h"
|
||||||
#include "nsInterfaceHashtable.h"
|
#include "nsRefPtrHashtable.h"
|
||||||
#include "nsCycleCollectionParticipant.h"
|
#include "nsCycleCollectionParticipant.h"
|
||||||
#include "nsChangeHint.h"
|
#include "nsChangeHint.h"
|
||||||
// This also pulls in gfxTypes.h, which we cannot include directly.
|
// This also pulls in gfxTypes.h, which we cannot include directly.
|
||||||
|
@ -93,6 +93,7 @@ class nsILookAndFeel;
|
||||||
class nsICSSPseudoComparator;
|
class nsICSSPseudoComparator;
|
||||||
class nsIAtom;
|
class nsIAtom;
|
||||||
struct nsStyleBackground;
|
struct nsStyleBackground;
|
||||||
|
struct nsStyleBorder;
|
||||||
class nsIRunnable;
|
class nsIRunnable;
|
||||||
class gfxUserFontSet;
|
class gfxUserFontSet;
|
||||||
class nsUserFontSet;
|
class nsUserFontSet;
|
||||||
|
@ -378,41 +379,46 @@ public:
|
||||||
PRBool GetFocusRingOnAnything() const { return mFocusRingOnAnything; }
|
PRBool GetFocusRingOnAnything() const { return mFocusRingOnAnything; }
|
||||||
PRUint8 GetFocusRingStyle() const { return mFocusRingStyle; }
|
PRUint8 GetFocusRingStyle() const { return mFocusRingStyle; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The types of image load types that the pres context needs image
|
||||||
|
* loaders to track invalidation for.
|
||||||
|
*/
|
||||||
|
enum ImageLoadType {
|
||||||
|
BACKGROUND_IMAGE,
|
||||||
|
BORDER_IMAGE,
|
||||||
|
IMAGE_LOAD_TYPE_COUNT
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set up observers so that aTargetFrame will be invalidated when
|
* Set the list of image loaders that track invalidation for a
|
||||||
* aImage loads, where aImage is its background image. Only a single
|
* specific frame and type of image. This list will replace any
|
||||||
* image will be tracked per frame.
|
* previous list for that frame and image type (and null will remove
|
||||||
|
* any previous list).
|
||||||
*/
|
*/
|
||||||
NS_HIDDEN_(imgIRequest*) LoadImage(imgIRequest* aImage,
|
NS_HIDDEN_(void) SetImageLoaders(nsIFrame* aTargetFrame,
|
||||||
nsIFrame* aTargetFrame);
|
ImageLoadType aType,
|
||||||
|
nsImageLoader* aImageLoaders);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set up observers so that aTargetFrame will be invalidated or
|
* Make an appropriate SetImageLoaders call (including potentially
|
||||||
* reflowed (as appropriate) when aImage loads, where aImage is its
|
* with null aImageLoaders) given that aFrame draws its background
|
||||||
* *border* image. Only a single image will be tracked per frame.
|
* based on aStyleBackground.
|
||||||
*/
|
*/
|
||||||
NS_HIDDEN_(imgIRequest*) LoadBorderImage(imgIRequest* aImage,
|
NS_HIDDEN_(void) SetupBackgroundImageLoaders(nsIFrame* aFrame,
|
||||||
nsIFrame* aTargetFrame);
|
const nsStyleBackground*
|
||||||
|
aStyleBackground);
|
||||||
|
|
||||||
private:
|
/**
|
||||||
typedef nsInterfaceHashtable<nsVoidPtrHashKey, nsImageLoader> ImageLoaderTable;
|
* Make an appropriate SetImageLoaders call (including potentially
|
||||||
|
* with null aImageLoaders) given that aFrame draws its border
|
||||||
|
* based on aStyleBorder.
|
||||||
|
*/
|
||||||
|
NS_HIDDEN_(void) SetupBorderImageLoaders(nsIFrame* aFrame,
|
||||||
|
const nsStyleBorder* aStyleBorder);
|
||||||
|
|
||||||
NS_HIDDEN_(imgIRequest*) DoLoadImage(ImageLoaderTable& aTable,
|
|
||||||
imgIRequest* aImage,
|
|
||||||
nsIFrame* aTargetFrame,
|
|
||||||
PRBool aReflowOnLoad);
|
|
||||||
|
|
||||||
NS_HIDDEN_(void) DoStopImageFor(ImageLoaderTable& aTable,
|
|
||||||
nsIFrame* aTargetFrame);
|
|
||||||
public:
|
|
||||||
|
|
||||||
NS_HIDDEN_(void) StopBackgroundImageFor(nsIFrame* aTargetFrame)
|
|
||||||
{ DoStopImageFor(mImageLoaders, aTargetFrame); }
|
|
||||||
NS_HIDDEN_(void) StopBorderImageFor(nsIFrame* aTargetFrame)
|
|
||||||
{ DoStopImageFor(mBorderImageLoaders, aTargetFrame); }
|
|
||||||
/**
|
/**
|
||||||
* This method is called when a frame is being destroyed to
|
* This method is called when a frame is being destroyed to
|
||||||
* ensure that the image load gets disassociated from the prescontext
|
* ensure that the image loads get disassociated from the prescontext
|
||||||
*/
|
*/
|
||||||
NS_HIDDEN_(void) StopImagesFor(nsIFrame* aTargetFrame);
|
NS_HIDDEN_(void) StopImagesFor(nsIFrame* aTargetFrame);
|
||||||
|
|
||||||
|
@ -847,8 +853,9 @@ protected:
|
||||||
nsILinkHandler* mLinkHandler; // [WEAK]
|
nsILinkHandler* mLinkHandler; // [WEAK]
|
||||||
nsIAtom* mLangGroup; // [STRONG]
|
nsIAtom* mLangGroup; // [STRONG]
|
||||||
|
|
||||||
ImageLoaderTable mImageLoaders;
|
nsRefPtrHashtable<nsVoidPtrHashKey, nsImageLoader>
|
||||||
ImageLoaderTable mBorderImageLoaders;
|
mImageLoaders[IMAGE_LOAD_TYPE_COUNT];
|
||||||
|
|
||||||
nsWeakPtr mContainer;
|
nsWeakPtr mContainer;
|
||||||
|
|
||||||
float mTextZoom; // Text zoom, defaults to 1.0
|
float mTextZoom; // Text zoom, defaults to 1.0
|
||||||
|
|
|
@ -518,19 +518,65 @@ nsFrame::GetOffsets(PRInt32 &aStart, PRInt32 &aEnd) const
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static PRBool
|
||||||
|
EqualImages(imgIRequest *aOldImage, imgIRequest *aNewImage)
|
||||||
|
{
|
||||||
|
if (aOldImage == aNewImage)
|
||||||
|
return PR_TRUE;
|
||||||
|
|
||||||
|
if (!aOldImage || !aNewImage)
|
||||||
|
return PR_FALSE;
|
||||||
|
|
||||||
|
nsCOMPtr<nsIURI> oldURI, newURI;
|
||||||
|
aOldImage->GetURI(getter_AddRefs(oldURI));
|
||||||
|
aNewImage->GetURI(getter_AddRefs(newURI));
|
||||||
|
PRBool equal;
|
||||||
|
return NS_SUCCEEDED(oldURI->Equals(newURI, &equal)) && equal;
|
||||||
|
}
|
||||||
|
|
||||||
// Subclass hook for style post processing
|
// Subclass hook for style post processing
|
||||||
/* virtual */ void
|
/* virtual */ void
|
||||||
nsFrame::DidSetStyleContext(nsStyleContext* aOldStyleContext)
|
nsFrame::DidSetStyleContext(nsStyleContext* aOldStyleContext)
|
||||||
{
|
{
|
||||||
// We have to start loading the border image before or during reflow,
|
if (aOldStyleContext) {
|
||||||
// because the border-image's width overrides only apply once the
|
// If the old context had a background image image and new context
|
||||||
// image is loaded. Starting the load of the image means we'll get a
|
// does not have the same image, clear the image load notifier
|
||||||
// reflow when the image loads. (Otherwise, if the image loads
|
// (which keeps the image loading, if it still is) for the frame.
|
||||||
// between reflow and paint, we never get the notification and our
|
// We want to do this conservatively because some frames paint their
|
||||||
// size ends up wrong.)
|
// backgrounds from some other frame's style data, and we don't want
|
||||||
imgIRequest *borderImage = GetStyleBorder()->GetBorderImage();
|
// to clear those notifiers unless we have to. (They'll be reset
|
||||||
if (borderImage) {
|
// when we paint, although we could miss a notification in that
|
||||||
PresContext()->LoadBorderImage(borderImage, this);
|
// interval.)
|
||||||
|
imgIRequest *oldBackgroundImage =
|
||||||
|
aOldStyleContext->GetStyleBackground()->mBackgroundImage;
|
||||||
|
if (oldBackgroundImage &&
|
||||||
|
!EqualImages(oldBackgroundImage,
|
||||||
|
GetStyleBackground()->mBackgroundImage)) {
|
||||||
|
// stop the image loading for the frame, the image has changed
|
||||||
|
PresContext()->SetImageLoaders(this,
|
||||||
|
nsPresContext::BACKGROUND_IMAGE, nsnull);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
imgIRequest *oldBorderImage = aOldStyleContext
|
||||||
|
? aOldStyleContext->GetStyleBorder()->GetBorderImage()
|
||||||
|
: nsnull;
|
||||||
|
// For border-images, we can't be as conservative (we need to set the
|
||||||
|
// new loaders if there has been any change) since the CalcDifference
|
||||||
|
// call depended on the result of GetActualBorder() and that result
|
||||||
|
// depends on whether the image has loaded, start the image load now
|
||||||
|
// so that we'll get notified when it completes loading and can do a
|
||||||
|
// restyle. Otherwise, the image might finish loading from the
|
||||||
|
// network before we start listening to its notifications, and then
|
||||||
|
// we'll never know that it's finished loading. Likewise, we want to
|
||||||
|
// do this for freshly-created frames to prevent a similar race if the
|
||||||
|
// image loads between reflow (which can depend on whether the image
|
||||||
|
// is loaded) and paint. We also don't really care about any callers
|
||||||
|
// who try to paint borders with a different style context, because
|
||||||
|
// they won't have the correct size for the border either.
|
||||||
|
if (!EqualImages(oldBorderImage, GetStyleBorder()->GetBorderImage())) {
|
||||||
|
// stop and restart the image loading/notification
|
||||||
|
PresContext()->SetupBorderImageLoaders(this, GetStyleBorder());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче