diff --git a/layout/base/public/nsIFrameImageLoader.h b/layout/base/public/nsIFrameImageLoader.h new file mode 100644 index 000000000000..0b8fccae0161 --- /dev/null +++ b/layout/base/public/nsIFrameImageLoader.h @@ -0,0 +1,66 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public License + * Version 1.0 (the "NPL"); you may not use this file except in + * compliance with the NPL. You may obtain a copy of the NPL at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the NPL is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL + * for the specific language governing rights and limitations under the + * NPL. + * + * The Initial Developer of this code under the NPL is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All Rights + * Reserved. + */ +#ifndef nsIFrameImageLoader_h___ +#define nsIFrameImageLoader_h___ + +#include "nslayout.h" +#include "nsIImageObserver.h" +class nsIFrame; +class nsIImage; +class nsIImageGroup; +class nsIPresContext; +class nsString; +struct nsSize; + +/* a9970300-e918-11d1-89cc-006008911b81 */ +#define NS_IFRAME_IMAGE_LOADER_IID \ + { 0xa9970300,0xe918,0x11d1,{0x89, 0xcc, 0x00, 0x60, 0x08, 0x91, 0x1b, 0x81} } + +/** + * Abstract interface for frame image loaders. Frame image loaders + * know how to respond to nsIImageRequestObserver notifications and + * generate the appropriate rendering/reflow operation for a target + * frame. + */ +class nsIFrameImageLoader : public nsIImageRequestObserver { +public: + NS_IMETHOD Init(nsIPresContext* aPresContext, + nsIImageGroup* aGroup, + const nsString& aURL, + nsIFrame* aTargetFrame, + PRBool aNeedSizeUpdate) = 0; + + NS_IMETHOD GetTargetFrame(nsIFrame*& aFrameResult) const = 0; + + NS_IMETHOD GetURL(nsString& aResult) const = 0; + + NS_IMETHOD GetImage(nsIImage*& aResult) const = 0; + + NS_IMETHOD GetSize(nsSize& aResult) const = 0; + + NS_IMETHOD GetImageLoadStatus(PRIntn& aLoadStatus) const = 0; +}; + +// Image load status bit values +#define NS_IMAGE_LOAD_STATUS_NONE 0x0 +#define NS_IMAGE_LOAD_STATUS_SIZE_REQUESTED 0x1 +#define NS_IMAGE_LOAD_STATUS_SIZE_AVAILABLE 0x2 +#define NS_IMAGE_LOAD_STATUS_IMAGE_READY 0x4 +#define NS_IMAGE_LOAD_STATUS_ERROR 0x8 + +#endif /* nsIFrameImageLoader_h___ */ diff --git a/layout/base/src/nsFrameImageLoader.cpp b/layout/base/src/nsFrameImageLoader.cpp new file mode 100644 index 000000000000..14cf6eaacd29 --- /dev/null +++ b/layout/base/src/nsFrameImageLoader.cpp @@ -0,0 +1,267 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public License + * Version 1.0 (the "NPL"); you may not use this file except in + * compliance with the NPL. You may obtain a copy of the NPL at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the NPL is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL + * for the specific language governing rights and limitations under the + * NPL. + * + * The Initial Developer of this code under the NPL is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All Rights + * Reserved. + */ +#include "nsFrameImageLoader.h" +#include "nsIPresContext.h" +#include "nsIPresShell.h" +#include "nsIViewManager.h" +#include "nsIView.h" +#include "nsIFrame.h" +#include "nsIURL.h" +#include "nsIDocument.h" +#include "nsIContent.h" +#include "nsIImageGroup.h" +#include "nsIImageRequest.h" +#include "nsString.h" + +#undef NOISY + +static NS_DEFINE_IID(kIFrameImageLoaderIID, NS_IFRAME_IMAGE_LOADER_IID); +static NS_DEFINE_IID(kIImageRequestObserverIID, NS_IIMAGEREQUESTOBSERVER_IID); +static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID); + +NS_LAYOUT nsresult +NS_NewFrameImageLoader(nsIFrameImageLoader** aInstancePtrResult) +{ + nsFrameImageLoader* it = new nsFrameImageLoader(); + if (nsnull == it) { + return NS_ERROR_OUT_OF_MEMORY; + } + return it->QueryInterface(kIFrameImageLoaderIID, + (void**) aInstancePtrResult); +} + +nsFrameImageLoader::nsFrameImageLoader() +{ + NS_INIT_REFCNT(); + mImage = nsnull; + mSize.width = 0; + mSize.height = 0; + mError = (nsImageError) -1; + mTargetFrame = nsnull; + mPresContext = nsnull; + mImageRequest = nsnull; + mImageLoadStatus = NS_IMAGE_LOAD_STATUS_NONE; +} + +nsFrameImageLoader::~nsFrameImageLoader() +{ + NS_IF_RELEASE(mImageRequest); + NS_IF_RELEASE(mPresContext); +} + +NS_IMPL_ADDREF(nsFrameImageLoader) + +NS_IMPL_RELEASE(nsFrameImageLoader) + +NS_METHOD +nsFrameImageLoader::QueryInterface(REFNSIID aIID, + void** aInstancePtr) +{ + if (NULL == aInstancePtr) { + return NS_ERROR_NULL_POINTER; + } + if (aIID.Equals(kIImageRequestObserverIID)) { + *aInstancePtr = (void*) ((nsIImageRequestObserver*) this); + AddRef(); + return NS_OK; + } + if (aIID.Equals(kIFrameImageLoaderIID)) { + *aInstancePtr = (void*) ((nsIFrameImageLoader*) this); + AddRef(); + return NS_OK; + } + if (aIID.Equals(kISupportsIID)) { + *aInstancePtr = (void*) ((nsISupports*) this); + AddRef(); + return NS_OK; + } + return NS_NOINTERFACE; +} + +nsresult +nsFrameImageLoader::Init(nsIPresContext* aPresContext, + nsIImageGroup* aGroup, + const nsString& aURL, + nsIFrame* aTargetFrame, + PRBool aNeedSizeUpdate) +{ + NS_PRECONDITION(nsnull != aPresContext, "null ptr"); + NS_PRECONDITION(nsnull == mPresContext, "double init"); + + if (nsnull == aPresContext) { + return NS_ERROR_NULL_POINTER; + } + if (nsnull != mPresContext) { + return NS_ERROR_ALREADY_INITIALIZED; + } + mTargetFrame = aTargetFrame; + mPresContext = aPresContext; + NS_IF_ADDREF(mPresContext); + if (aNeedSizeUpdate) { + mImageLoadStatus = NS_IMAGE_LOAD_STATUS_SIZE_REQUESTED; + } +#ifdef NOISY + printf("loading for %p (%x)\n", mTargetFrame, mImageLoadStatus); +#endif + + // Start image load request + mURL = aURL; + char* cp = aURL.ToNewCString(); + mImageRequest = aGroup->GetImage(cp, this, NS_RGB(255,255,255), 0, 0, 0); + delete cp; + + return NS_OK; +} + +void +nsFrameImageLoader::Notify(nsIImageRequest *aImageRequest, + nsIImage *aImage, + nsImageNotification aNotificationType, + PRInt32 aParam1, PRInt32 aParam2, + void *aParam3) +{ + switch (aNotificationType) { + case nsImageNotification_kDimensions: +#ifdef NOISY + printf("image for %p: %d x %d\n", mTargetFrame, aParam1, aParam2); +#endif + mSize.width = aParam1; + mSize.height = aParam2; + mImageLoadStatus |= NS_IMAGE_LOAD_STATUS_SIZE_AVAILABLE; + if (0 != (mImageLoadStatus & NS_IMAGE_LOAD_STATUS_SIZE_REQUESTED)) { + ReflowFrame(); + } + break; + + case nsImageNotification_kPixmapUpdate: + case nsImageNotification_kImageComplete: + case nsImageNotification_kFrameComplete: + if ((mImage == nsnull) && (nsnull != aImage)) { + mImage = aImage; + NS_ADDREF(aImage); + } + mImageLoadStatus |= NS_IMAGE_LOAD_STATUS_IMAGE_READY; + DamageRepairFrame(); + break; + } +} + +void +nsFrameImageLoader::NotifyError(nsIImageRequest *aImageRequest, + nsImageError aErrorType) +{ + mError = aErrorType; + mImageLoadStatus |= NS_IMAGE_LOAD_STATUS_ERROR; + if (0 != (mImageLoadStatus & NS_IMAGE_LOAD_STATUS_SIZE_REQUESTED)) { + ReflowFrame(); + } + else { + DamageRepairFrame(); + } +} + +static PRBool gXXXInstalledColorMap; + +void +nsFrameImageLoader::DamageRepairFrame() +{ + // XXX this should be done somewhere else, like when the window + // is created or something??? + // XXX maybe there should be a seperate notification service for + // colormap events? + nsIWidget* window; + mTargetFrame->GetWindow(window); + if (!gXXXInstalledColorMap && mImage) { + nsColorMap* cmap = mImage->GetColorMap(); + if ((nsnull != cmap) && (cmap->NumColors > 0)) { + window->SetColorMap(cmap); + } + gXXXInstalledColorMap = PR_TRUE; + } + + // Determine damaged area and tell view manager to redraw it + nsPoint offset; + nsRect bounds; + nsIView* view; + mTargetFrame->GetRect(bounds); + mTargetFrame->GetOffsetFromView(offset, view); + nsIViewManager* vm = view->GetViewManager(); + bounds.x = offset.x; + bounds.y = offset.y; + vm->UpdateView(view, bounds, 0); + NS_RELEASE(vm); + NS_RELEASE(view); +} + +void +nsFrameImageLoader::ReflowFrame() +{ + nsIContent* content; + mTargetFrame->GetContent(content); + if (nsnull != content) { + nsIPresShell* shell; + shell = mPresContext->GetShell(); + if (nsnull != shell) { + shell->EnterReflowLock(); + shell->BeginUpdate(); +#ifdef NOISY + printf(" reflow %p\n", mTargetFrame); +#endif + shell->ContentChanged(content, nsnull); + shell->EndUpdate(); + shell->ExitReflowLock(); + NS_RELEASE(shell); + } + NS_RELEASE(content); + } +} + +NS_METHOD +nsFrameImageLoader::GetTargetFrame(nsIFrame*& aFrameResult) const +{ + aFrameResult = mTargetFrame; + return NS_OK; +} + +NS_METHOD +nsFrameImageLoader::GetURL(nsString& aResult) const +{ + aResult = mURL; + return NS_OK; +} + +NS_METHOD +nsFrameImageLoader::GetImage(nsIImage*& aResult) const +{ + aResult = mImage; + return NS_OK; +} + +NS_METHOD +nsFrameImageLoader::GetSize(nsSize& aResult) const +{ + aResult = mSize; + return NS_OK; +} + +NS_METHOD +nsFrameImageLoader::GetImageLoadStatus(PRIntn& aLoadStatus) const +{ + aLoadStatus = mImageLoadStatus; + return NS_OK; +} diff --git a/layout/base/src/nsFrameImageLoader.h b/layout/base/src/nsFrameImageLoader.h new file mode 100644 index 000000000000..758ccbfc08a2 --- /dev/null +++ b/layout/base/src/nsFrameImageLoader.h @@ -0,0 +1,78 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public License + * Version 1.0 (the "NPL"); you may not use this file except in + * compliance with the NPL. You may obtain a copy of the NPL at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the NPL is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL + * for the specific language governing rights and limitations under the + * NPL. + * + * The Initial Developer of this code under the NPL is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All Rights + * Reserved. + */ +#ifndef nsFrameImageLoader_h___ +#define nsFrameImageLoader_h___ + +#include "nsIFrameImageLoader.h" +#include "nsSize.h" +#include "nsString.h" + +/** + * An image loader for frame's. + */ +class nsFrameImageLoader : public nsIFrameImageLoader { +public: + + // nsISupports + NS_DECL_ISUPPORTS + + // nsIImageRequestObserver + virtual void Notify(nsIImageRequest *aImageRequest, + nsIImage *aImage, + nsImageNotification aNotificationType, + PRInt32 aParam1, PRInt32 aParam2, + void *aParam3); + virtual void NotifyError(nsIImageRequest *aImageRequest, + nsImageError aErrorType); + + // nsIFrameImageLoader + NS_IMETHOD Init(nsIPresContext* aPresContext, + nsIImageGroup* aGroup, + const nsString& aURL, + nsIFrame* aTargetFrame, + PRBool aNeedSizeUpdate); + NS_IMETHOD GetTargetFrame(nsIFrame*& aFrameResult) const; + NS_IMETHOD GetURL(nsString& aResult) const; + NS_IMETHOD GetImage(nsIImage*& aResult) const; + NS_IMETHOD GetSize(nsSize& aResult) const; + NS_IMETHOD GetImageLoadStatus(PRIntn& aLoadStatus) const; + +protected: + nsFrameImageLoader(); + ~nsFrameImageLoader(); + + void ReflowFrame(); + + void DamageRepairFrame(); + + nsString mURL; + nsIImage* mImage; + nsSize mSize; + nsImageError mError; + nsIFrame* mTargetFrame; + nsIPresContext* mPresContext; + nsIImageRequest* mImageRequest; + PRUint8 mImageLoadStatus; + + friend NS_LAYOUT nsresult NS_NewFrameImageLoader(nsIFrameImageLoader**); +}; + +extern NS_LAYOUT nsresult + NS_NewFrameImageLoader(nsIFrameImageLoader** aInstancePtrResult); + +#endif /* nsFrameImageLoader_h___ */