From b8205354d194db16f974ed654172da5d6a469a95 Mon Sep 17 00:00:00 2001 From: "troy%netscape.com" Date: Fri, 5 Feb 1999 18:25:29 +0000 Subject: [PATCH] Added CantRenderReplacedElement() to nsIPresShell and changed the image frame code to use it --- layout/base/nsIPresShell.h | 8 +++ layout/base/nsPresShell.cpp | 98 +++++++++++++++++++++++++-- layout/base/public/nsIPresShell.h | 8 +++ layout/generic/nsImageFrame.cpp | 24 ++++--- layout/html/base/src/nsImageFrame.cpp | 24 ++++--- layout/html/base/src/nsPresShell.cpp | 98 +++++++++++++++++++++++++-- 6 files changed, 232 insertions(+), 28 deletions(-) diff --git a/layout/base/nsIPresShell.h b/layout/base/nsIPresShell.h index b84c65f7f49f..e872b2b69b06 100644 --- a/layout/base/nsIPresShell.h +++ b/layout/base/nsIPresShell.h @@ -157,6 +157,14 @@ public: */ NS_IMETHOD CreateRenderingContext(nsIFrame *aFrame, nsIRenderingContext *&aContext) = 0; + // Notification that we were unable to render a replaced element. + // Called when the replaced element can not be rendered, and we should + // instead render the element's contents. + // The content object associated with aFrame should either be a IMG + // element or an OBJECT element. + NS_IMETHOD CantRenderReplacedElement(nsIPresContext* aPresContext, + nsIFrame* aFrame) = 0; + // XXX events // XXX selection diff --git a/layout/base/nsPresShell.cpp b/layout/base/nsPresShell.cpp index 8c61731ba982..57f9afa60c4e 100644 --- a/layout/base/nsPresShell.cpp +++ b/layout/base/nsPresShell.cpp @@ -49,6 +49,9 @@ #include "nsIDOMElement.h" #include "nsHTMLAtoms.h" #include "nsCOMPtr.h" +#include "nsIEventQueueService.h" +#include "nsXPComCIID.h" +#include "nsIServiceManager.h" static PRBool gsNoisyRefs = PR_FALSE; #undef NOISY @@ -146,18 +149,23 @@ FrameHashTable::Remove(nsIFrame* aKey) //---------------------------------------------------------------------- +// Class IID's +static NS_DEFINE_IID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID); +static NS_DEFINE_IID(kRangeListCID, NS_RANGELIST_CID); +static NS_DEFINE_IID(kCRangeCID, NS_RANGE_CID); + +// IID's static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID); static NS_DEFINE_IID(kIPresShellIID, NS_IPRESSHELL_IID); static NS_DEFINE_IID(kIDocumentObserverIID, NS_IDOCUMENT_OBSERVER_IID); static NS_DEFINE_IID(kIViewObserverIID, NS_IVIEWOBSERVER_IID); -static NS_DEFINE_IID(kRangeListCID, NS_RANGELIST_CID); static NS_DEFINE_IID(kISelectionIID, NS_ISELECTION_IID); static NS_DEFINE_IID(kICollectionIID, NS_ICOLLECTION_IID); static NS_DEFINE_IID(kIDOMNodeIID, NS_IDOMNODE_IID); static NS_DEFINE_IID(kIDOMRangeIID, NS_IDOMRANGE_IID); -static NS_DEFINE_IID(kCRangeCID, NS_RANGE_CID); static NS_DEFINE_IID(kIDOMDocumentIID, NS_IDOMDOCUMENT_IID); static NS_DEFINE_IID(kIFocusTrackerIID, NS_IFOCUSTRACKER_IID); +static NS_DEFINE_IID(kIEventQueueServiceIID, NS_IEVENTQUEUESERVICE_IID); class PresShell : public nsIPresShell, public nsIViewObserver, @@ -256,6 +264,8 @@ public: NS_IMETHOD ProcessReflowCommands(); virtual void ClearFrameRefs(nsIFrame*); NS_IMETHOD CreateRenderingContext(nsIFrame *aFrame, nsIRenderingContext *&aContext); + NS_IMETHOD CantRenderReplacedElement(nsIPresContext* aPresContext, + nsIFrame* aFrame); //nsIViewObserver interface @@ -272,6 +282,10 @@ public: NS_IMETHOD SetFocus(nsIFrame *aFrame, nsIFrame *aAnchorFrame); NS_IMETHOD GetFocus(nsIFrame **aFrame, nsIFrame **aAnchorFrame); + + // implementation + void HandleCantRenderReplacedElementEvent(nsIFrame* aFrame); + protected: ~PresShell(); @@ -1034,8 +1048,8 @@ PresShell::ClearFrameRefs(nsIFrame* aFrame) } } -NS_IMETHODIMP PresShell :: CreateRenderingContext(nsIFrame *aFrame, - nsIRenderingContext *&aContext) +NS_IMETHODIMP +PresShell::CreateRenderingContext(nsIFrame *aFrame, nsIRenderingContext *&aContext) { nsIWidget *widget = nsnull; nsIView *view = nsnull; @@ -1074,6 +1088,82 @@ NS_IMETHODIMP PresShell :: CreateRenderingContext(nsIFrame *aFrame, return rv; } +void +PresShell::HandleCantRenderReplacedElementEvent(nsIFrame* aFrame) +{ + // Double-check that we haven't deleted the frame hierarchy + // XXX If we stay with this model we approach, then we need to observe + // aFrame and if it's deleted null out the pointer in the PL event struct + if (nsnull != mRootFrame) { + mStyleSet->CantRenderReplacedElement(mPresContext, aFrame); + ProcessReflowCommands(); + } +} + +struct CantRenderReplacedElementEvent : public PLEvent { + CantRenderReplacedElementEvent(PresShell* aShell, nsIFrame* aFrame); + ~CantRenderReplacedElementEvent(); + + PresShell* mShell; + nsIFrame* mFrame; +}; + +static void PR_CALLBACK +HandlePLEvent(CantRenderReplacedElementEvent* aEvent) +{ + aEvent->mShell->HandleCantRenderReplacedElementEvent(aEvent->mFrame); +} + +static void PR_CALLBACK +DestroyPLEvent(CantRenderReplacedElementEvent* aEvent) +{ + delete aEvent; +} + +CantRenderReplacedElementEvent::CantRenderReplacedElementEvent(PresShell* aShell, + nsIFrame* aFrame) +{ + mShell = aShell; + NS_ADDREF(mShell); + mFrame = aFrame; + PL_InitEvent(this, nsnull, (PLHandleEventProc)::HandlePLEvent, + (PLDestroyEventProc)::DestroyPLEvent); +} + +CantRenderReplacedElementEvent::~CantRenderReplacedElementEvent() +{ + NS_RELEASE(mShell); +} + +NS_IMETHODIMP +PresShell::CantRenderReplacedElement(nsIPresContext* aPresContext, + nsIFrame* aFrame) +{ + nsIEventQueueService* eventService; + nsresult rv; + + // Notify the style set, but post the notification so it doesn't happen + // now + rv = nsServiceManager::GetService(kEventQueueServiceCID, + kIEventQueueServiceIID, + (nsISupports **)&eventService); + if (NS_SUCCEEDED(rv)) { + PLEventQueue* eventQueue; + rv = eventService->GetThreadEventQueue(PR_GetCurrentThread(), + &eventQueue); + nsServiceManager::ReleaseService(kEventQueueServiceCID, eventService); + + if (nsnull != eventQueue) { + CantRenderReplacedElementEvent* ev; + + ev = new CantRenderReplacedElementEvent(this, aFrame); + PL_PostEvent(eventQueue, ev); + } + } + + return rv; +} + #ifdef NS_DEBUG static char* ContentTag(nsIContent* aContent, PRIntn aSlot) diff --git a/layout/base/public/nsIPresShell.h b/layout/base/public/nsIPresShell.h index b84c65f7f49f..e872b2b69b06 100644 --- a/layout/base/public/nsIPresShell.h +++ b/layout/base/public/nsIPresShell.h @@ -157,6 +157,14 @@ public: */ NS_IMETHOD CreateRenderingContext(nsIFrame *aFrame, nsIRenderingContext *&aContext) = 0; + // Notification that we were unable to render a replaced element. + // Called when the replaced element can not be rendered, and we should + // instead render the element's contents. + // The content object associated with aFrame should either be a IMG + // element or an OBJECT element. + NS_IMETHOD CantRenderReplacedElement(nsIPresContext* aPresContext, + nsIFrame* aFrame) = 0; + // XXX events // XXX selection diff --git a/layout/generic/nsImageFrame.cpp b/layout/generic/nsImageFrame.cpp index 55198a4b1f72..7aba778f889f 100644 --- a/layout/generic/nsImageFrame.cpp +++ b/layout/generic/nsImageFrame.cpp @@ -136,11 +136,21 @@ nsHTMLImageLoader::StartLoadImage(nsIPresContext* aPresContext, // Get absolute url the first time through nsresult rv; nsAutoString src; - if (mLoadImageFailed || (nsnull == mURLSpec)) { #ifdef _WIN32 + if (mLoadImageFailed) { + // We've already notified the pres shell that we're unable to render + // the image so just return + return NS_OK; + } else if (nsnull == mURLSpec) { + // No URI was specified for the src. Indicate we're unable to load the + // image and notify the pres shell mLoadImageFailed = PR_TRUE; + nsIPresShell* presShell = aPresContext->GetShell(); + presShell->CantRenderReplacedElement(aPresContext, aForFrame); + NS_RELEASE(presShell); return NS_OK; #else + if (mLoadImageFailed || (nsnull == mURLSpec)) { src.Append(BROKEN_IMAGE_URL); #endif } else if (nsnull == mImageLoader) { @@ -372,16 +382,10 @@ UpdateImageFrame(nsIPresContext& aPresContext, nsIFrame* aFrame, NS_RELEASE(content); } } else if (NS_IMAGE_LOAD_STATUS_ERROR & aStatus) { -#if 0 - // We failed to load the image. Notify the style system + // We failed to load the image. Notify the pres shell nsIPresShell* presShell = aPresContext.GetShell(); - nsIStyleSet* styleSet = presShell->GetStyleSet(); - styleSet->CantRenderReplacedElement(&aPresContext, aFrame); - NS_RELEASE(styleSet); + presShell->CantRenderReplacedElement(&aPresContext, aFrame); NS_RELEASE(presShell); -#else - ; -#endif } return NS_OK; } @@ -673,7 +677,7 @@ nsImageFrame::Paint(nsIPresContext& aPresContext, } if (eFramePaintLayer_Content == aWhichLayer) { - // Now render the image into our inner area (the area without the + // Now render the image into our content area (the area inside the // borders and padding) nsRect inner; GetInnerArea(&aPresContext, inner); diff --git a/layout/html/base/src/nsImageFrame.cpp b/layout/html/base/src/nsImageFrame.cpp index 55198a4b1f72..7aba778f889f 100644 --- a/layout/html/base/src/nsImageFrame.cpp +++ b/layout/html/base/src/nsImageFrame.cpp @@ -136,11 +136,21 @@ nsHTMLImageLoader::StartLoadImage(nsIPresContext* aPresContext, // Get absolute url the first time through nsresult rv; nsAutoString src; - if (mLoadImageFailed || (nsnull == mURLSpec)) { #ifdef _WIN32 + if (mLoadImageFailed) { + // We've already notified the pres shell that we're unable to render + // the image so just return + return NS_OK; + } else if (nsnull == mURLSpec) { + // No URI was specified for the src. Indicate we're unable to load the + // image and notify the pres shell mLoadImageFailed = PR_TRUE; + nsIPresShell* presShell = aPresContext->GetShell(); + presShell->CantRenderReplacedElement(aPresContext, aForFrame); + NS_RELEASE(presShell); return NS_OK; #else + if (mLoadImageFailed || (nsnull == mURLSpec)) { src.Append(BROKEN_IMAGE_URL); #endif } else if (nsnull == mImageLoader) { @@ -372,16 +382,10 @@ UpdateImageFrame(nsIPresContext& aPresContext, nsIFrame* aFrame, NS_RELEASE(content); } } else if (NS_IMAGE_LOAD_STATUS_ERROR & aStatus) { -#if 0 - // We failed to load the image. Notify the style system + // We failed to load the image. Notify the pres shell nsIPresShell* presShell = aPresContext.GetShell(); - nsIStyleSet* styleSet = presShell->GetStyleSet(); - styleSet->CantRenderReplacedElement(&aPresContext, aFrame); - NS_RELEASE(styleSet); + presShell->CantRenderReplacedElement(&aPresContext, aFrame); NS_RELEASE(presShell); -#else - ; -#endif } return NS_OK; } @@ -673,7 +677,7 @@ nsImageFrame::Paint(nsIPresContext& aPresContext, } if (eFramePaintLayer_Content == aWhichLayer) { - // Now render the image into our inner area (the area without the + // Now render the image into our content area (the area inside the // borders and padding) nsRect inner; GetInnerArea(&aPresContext, inner); diff --git a/layout/html/base/src/nsPresShell.cpp b/layout/html/base/src/nsPresShell.cpp index 8c61731ba982..57f9afa60c4e 100644 --- a/layout/html/base/src/nsPresShell.cpp +++ b/layout/html/base/src/nsPresShell.cpp @@ -49,6 +49,9 @@ #include "nsIDOMElement.h" #include "nsHTMLAtoms.h" #include "nsCOMPtr.h" +#include "nsIEventQueueService.h" +#include "nsXPComCIID.h" +#include "nsIServiceManager.h" static PRBool gsNoisyRefs = PR_FALSE; #undef NOISY @@ -146,18 +149,23 @@ FrameHashTable::Remove(nsIFrame* aKey) //---------------------------------------------------------------------- +// Class IID's +static NS_DEFINE_IID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID); +static NS_DEFINE_IID(kRangeListCID, NS_RANGELIST_CID); +static NS_DEFINE_IID(kCRangeCID, NS_RANGE_CID); + +// IID's static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID); static NS_DEFINE_IID(kIPresShellIID, NS_IPRESSHELL_IID); static NS_DEFINE_IID(kIDocumentObserverIID, NS_IDOCUMENT_OBSERVER_IID); static NS_DEFINE_IID(kIViewObserverIID, NS_IVIEWOBSERVER_IID); -static NS_DEFINE_IID(kRangeListCID, NS_RANGELIST_CID); static NS_DEFINE_IID(kISelectionIID, NS_ISELECTION_IID); static NS_DEFINE_IID(kICollectionIID, NS_ICOLLECTION_IID); static NS_DEFINE_IID(kIDOMNodeIID, NS_IDOMNODE_IID); static NS_DEFINE_IID(kIDOMRangeIID, NS_IDOMRANGE_IID); -static NS_DEFINE_IID(kCRangeCID, NS_RANGE_CID); static NS_DEFINE_IID(kIDOMDocumentIID, NS_IDOMDOCUMENT_IID); static NS_DEFINE_IID(kIFocusTrackerIID, NS_IFOCUSTRACKER_IID); +static NS_DEFINE_IID(kIEventQueueServiceIID, NS_IEVENTQUEUESERVICE_IID); class PresShell : public nsIPresShell, public nsIViewObserver, @@ -256,6 +264,8 @@ public: NS_IMETHOD ProcessReflowCommands(); virtual void ClearFrameRefs(nsIFrame*); NS_IMETHOD CreateRenderingContext(nsIFrame *aFrame, nsIRenderingContext *&aContext); + NS_IMETHOD CantRenderReplacedElement(nsIPresContext* aPresContext, + nsIFrame* aFrame); //nsIViewObserver interface @@ -272,6 +282,10 @@ public: NS_IMETHOD SetFocus(nsIFrame *aFrame, nsIFrame *aAnchorFrame); NS_IMETHOD GetFocus(nsIFrame **aFrame, nsIFrame **aAnchorFrame); + + // implementation + void HandleCantRenderReplacedElementEvent(nsIFrame* aFrame); + protected: ~PresShell(); @@ -1034,8 +1048,8 @@ PresShell::ClearFrameRefs(nsIFrame* aFrame) } } -NS_IMETHODIMP PresShell :: CreateRenderingContext(nsIFrame *aFrame, - nsIRenderingContext *&aContext) +NS_IMETHODIMP +PresShell::CreateRenderingContext(nsIFrame *aFrame, nsIRenderingContext *&aContext) { nsIWidget *widget = nsnull; nsIView *view = nsnull; @@ -1074,6 +1088,82 @@ NS_IMETHODIMP PresShell :: CreateRenderingContext(nsIFrame *aFrame, return rv; } +void +PresShell::HandleCantRenderReplacedElementEvent(nsIFrame* aFrame) +{ + // Double-check that we haven't deleted the frame hierarchy + // XXX If we stay with this model we approach, then we need to observe + // aFrame and if it's deleted null out the pointer in the PL event struct + if (nsnull != mRootFrame) { + mStyleSet->CantRenderReplacedElement(mPresContext, aFrame); + ProcessReflowCommands(); + } +} + +struct CantRenderReplacedElementEvent : public PLEvent { + CantRenderReplacedElementEvent(PresShell* aShell, nsIFrame* aFrame); + ~CantRenderReplacedElementEvent(); + + PresShell* mShell; + nsIFrame* mFrame; +}; + +static void PR_CALLBACK +HandlePLEvent(CantRenderReplacedElementEvent* aEvent) +{ + aEvent->mShell->HandleCantRenderReplacedElementEvent(aEvent->mFrame); +} + +static void PR_CALLBACK +DestroyPLEvent(CantRenderReplacedElementEvent* aEvent) +{ + delete aEvent; +} + +CantRenderReplacedElementEvent::CantRenderReplacedElementEvent(PresShell* aShell, + nsIFrame* aFrame) +{ + mShell = aShell; + NS_ADDREF(mShell); + mFrame = aFrame; + PL_InitEvent(this, nsnull, (PLHandleEventProc)::HandlePLEvent, + (PLDestroyEventProc)::DestroyPLEvent); +} + +CantRenderReplacedElementEvent::~CantRenderReplacedElementEvent() +{ + NS_RELEASE(mShell); +} + +NS_IMETHODIMP +PresShell::CantRenderReplacedElement(nsIPresContext* aPresContext, + nsIFrame* aFrame) +{ + nsIEventQueueService* eventService; + nsresult rv; + + // Notify the style set, but post the notification so it doesn't happen + // now + rv = nsServiceManager::GetService(kEventQueueServiceCID, + kIEventQueueServiceIID, + (nsISupports **)&eventService); + if (NS_SUCCEEDED(rv)) { + PLEventQueue* eventQueue; + rv = eventService->GetThreadEventQueue(PR_GetCurrentThread(), + &eventQueue); + nsServiceManager::ReleaseService(kEventQueueServiceCID, eventService); + + if (nsnull != eventQueue) { + CantRenderReplacedElementEvent* ev; + + ev = new CantRenderReplacedElementEvent(this, aFrame); + PL_PostEvent(eventQueue, ev); + } + } + + return rv; +} + #ifdef NS_DEBUG static char* ContentTag(nsIContent* aContent, PRIntn aSlot)