Mozilla/mozilla/gfx/src/nsImageGroup.cpp
alecf%netscape.com 4ffddeb00c #45797 - fix consumers of NS_IMPL_ISUPPORTS
r=dveditz


git-svn-id: svn://10.0.0.236/trunk@82745 18797224-902f-48f8-a5cc-f745e15eee43
2000-11-17 20:54:21 +00:00

387 lines
11 KiB
C++

/* -*- 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.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include "nsIServiceManager.h"
#include "nsIImageGroup.h"
#include "nsIImageManager.h"
#include "nsIImageObserver.h"
#include "nsIImageRequest.h"
#include "nsImageRequest.h"
#include "ilIImageRenderer.h"
#include "nsImageNet.h"
#include "nsVoidArray.h"
#include "nsCRT.h"
#include "libimg.h"
#include "il_util.h"
#include "nsIDeviceContext.h"
#include "nsIStreamListener.h"
#include "nsGfxCIID.h"
static NS_DEFINE_IID(kImageManagerCID, NS_IMAGEMANAGER_CID);
class ImageGroupImpl : public nsIImageGroup
{
public:
ImageGroupImpl(nsIImageManager *aManager);
virtual ~ImageGroupImpl();
nsresult Init(nsIDeviceContext *aDeviceContext, nsISupports * aLoadContext);
NS_DECL_AND_IMPL_ZEROING_OPERATOR_NEW
NS_DECL_ISUPPORTS
virtual PRBool AddObserver(nsIImageGroupObserver *aObserver);
virtual PRBool RemoveObserver(nsIImageGroupObserver *aObserver);
virtual nsIImageRequest* GetImage(const char* aUrl,
nsIImageRequestObserver *aObserver,
const nscolor* aBackgroundColor,
PRUint32 aWidth, PRUint32 aHeight,
PRUint32 aFlags);
NS_IMETHOD GetImageFromStream(const char* aURL,
nsIImageRequestObserver *aObserver,
const nscolor* aBackgroundColor,
PRUint32 aWidth, PRUint32 aHeight,
PRUint32 aFlags,
nsIImageRequest*& aResult,
nsIStreamListener*& aListenerResult);
virtual void Interrupt(void);
IL_GroupContext *GetGroupContext() { return mGroupContext; }
nsVoidArray *GetObservers() { return mObservers; }
NS_IMETHOD SetImgLoadAttributes(PRUint32 a_grouploading_attribs);
NS_IMETHOD GetImgLoadAttributes(PRUint32 *a_grouploading_attribs);
nsIImageManager *mManager;
IL_GroupContext *mGroupContext;
nsVoidArray *mObservers;
nsIDeviceContext *mDeviceContext;
ilINetContext* mNetContext;
nsIStreamListener** mListenerRequest;
//ptn
PRUint32 m_grouploading_attribs;
};
ImageGroupImpl::ImageGroupImpl(nsIImageManager *aManager)
{
NS_INIT_REFCNT();
mManager = aManager;
NS_ADDREF(mManager);
}
ImageGroupImpl::~ImageGroupImpl()
{
NS_IF_RELEASE(mDeviceContext);
if (mObservers != nsnull) {
PRInt32 i, count = mObservers->Count();
nsIImageGroupObserver *observer;
for (i = 0; i < count; i++) {
observer = (nsIImageGroupObserver *)mObservers->ElementAt(i);
if (observer != nsnull) {
NS_RELEASE(observer);
}
}
delete mObservers;
}
if (mGroupContext != nsnull) {
IL_DestroyGroupContext(mGroupContext);
}
NS_IF_RELEASE(mManager);
NS_IF_RELEASE(mNetContext);
}
NS_IMPL_ISUPPORTS1(ImageGroupImpl, nsIImageGroup)
static void ns_observer_proc (XP_Observable aSource,
XP_ObservableMsg aMsg,
void* aMsgData,
void* aClosure)
{
ImageGroupImpl *image_group = (ImageGroupImpl *)aClosure;
nsVoidArray *observer_list = image_group->GetObservers();
if (observer_list != nsnull) {
PRInt32 i, count = observer_list->Count();
nsIImageGroupObserver *observer;
for (i = 0; i < count; i++) {
observer = (nsIImageGroupObserver *)observer_list->ElementAt(i);
if (observer != nsnull) {
switch (aMsg) {
case IL_STARTED_LOADING:
observer->Notify(image_group,
nsImageGroupNotification_kStartedLoading);
break;
case IL_ABORTED_LOADING:
observer->Notify(image_group,
nsImageGroupNotification_kAbortedLoading);
case IL_FINISHED_LOADING:
observer->Notify(image_group,
nsImageGroupNotification_kFinishedLoading);
case IL_STARTED_LOOPING:
observer->Notify(image_group,
nsImageGroupNotification_kStartedLooping);
case IL_FINISHED_LOOPING:
observer->Notify(image_group,
nsImageGroupNotification_kFinishedLooping);
}
}
}
}
}
static PRBool
ReconnectHack(void* arg, nsIStreamListener* aListener)
{
ImageGroupImpl* ig = (ImageGroupImpl*) arg;
if (nsnull != ig->mListenerRequest) {
*ig->mListenerRequest = aListener;
NS_ADDREF(aListener);
return PR_TRUE;
}
return PR_FALSE;
}
nsresult
ImageGroupImpl::Init(nsIDeviceContext *aDeviceContext, nsISupports *aLoadContext)
{
ilIImageRenderer *renderer;
nsresult result;
if ((result = NS_NewImageRenderer(&renderer)) != NS_OK) {
return result;
}
mGroupContext = IL_NewGroupContext((void *)aDeviceContext,
renderer);
if (mGroupContext == nsnull) {
return NS_ERROR_OUT_OF_MEMORY;
}
// Create an async net context
result = NS_NewImageNetContext(&mNetContext, aLoadContext, ReconnectHack, this);
if (NS_OK != result) {
return result;
}
mDeviceContext = aDeviceContext;
NS_ADDREF(mDeviceContext);
// Get color space to use for this device context.
IL_ColorSpace* colorSpace;
mDeviceContext->GetILColorSpace(colorSpace);
// Set the image group context display mode
IL_DisplayData displayData;
displayData.dither_mode = IL_Auto;
displayData.color_space = colorSpace;
displayData.progressive_display = PR_TRUE;
IL_SetDisplayMode(mGroupContext,
IL_COLOR_SPACE | IL_PROGRESSIVE_DISPLAY | IL_DITHER_MODE,
&displayData);
// Release the color space
IL_ReleaseColorSpace(colorSpace);
return NS_OK;
}
PRBool
ImageGroupImpl::AddObserver(nsIImageGroupObserver *aObserver)
{
if (aObserver == nsnull) {
return PR_FALSE;
}
if (mObservers == nsnull) {
mObservers = new nsVoidArray();
if (mObservers == nsnull) {
return PR_FALSE;
}
IL_AddGroupObserver(mGroupContext, ns_observer_proc, (void *)this);
}
NS_ADDREF(aObserver);
mObservers->AppendElement((void *)aObserver);
return PR_TRUE;
}
PRBool
ImageGroupImpl::RemoveObserver(nsIImageGroupObserver *aObserver)
{
PRBool ret;
if (aObserver == nsnull || mObservers == nsnull) {
return PR_FALSE;
}
ret = mObservers->RemoveElement((void *)aObserver);
if (ret == PR_TRUE) {
NS_RELEASE(aObserver);
}
return ret;
}
nsIImageRequest*
ImageGroupImpl::GetImage(const char* aUrl,
nsIImageRequestObserver *aObserver,
const nscolor* aBackgroundColor,
PRUint32 aWidth, PRUint32 aHeight,
PRUint32 aFlags)
{
NS_PRECONDITION(nsnull != aUrl, "null URL");
ImageRequestImpl *image_req = new ImageRequestImpl;
if (nsnull != image_req) {
nsresult result;
// Ask the image request object to get the image.
PRUint32 groupload_attrib = 0;
GetImgLoadAttributes(&groupload_attrib);
if(!aFlags)
aFlags = groupload_attrib;
mListenerRequest = nsnull;
result = image_req->Init(mGroupContext, aUrl, aObserver, aBackgroundColor,
aWidth, aHeight, aFlags, mNetContext);
if (NS_SUCCEEDED(result)) {
NS_ADDREF(image_req);
} else {
delete image_req;
image_req = nsnull;
}
}
return image_req;
}
NS_IMETHODIMP
ImageGroupImpl::GetImageFromStream(const char* aUrl,
nsIImageRequestObserver *aObserver,
const nscolor* aBackgroundColor,
PRUint32 aWidth, PRUint32 aHeight,
PRUint32 aFlags,
nsIImageRequest*& aResult,
nsIStreamListener*& aListenerResult)
{
NS_PRECONDITION(nsnull != aUrl, "null URL");
nsresult result = NS_OK;
ImageRequestImpl *image_req = new ImageRequestImpl;
if (nsnull == image_req) {
return NS_ERROR_OUT_OF_MEMORY;
}
// Ask the image request object to get the image.
nsIStreamListener* listener = nsnull;
mListenerRequest = &listener;
PRUint32 groupload_attrib = 0;
GetImgLoadAttributes(&groupload_attrib);
if(!aFlags)
aFlags = groupload_attrib;
result = image_req->Init(mGroupContext, aUrl, aObserver, aBackgroundColor,
aWidth, aHeight, aFlags, mNetContext);
aListenerResult = listener;
mListenerRequest = nsnull;
if (NS_SUCCEEDED(result)) {
NS_ADDREF(image_req);
} else {
delete image_req;
image_req = nsnull;
}
aResult = image_req;
return result;
}
void
ImageGroupImpl::Interrupt(void)
{
if (mGroupContext != nsnull) {
IL_InterruptContext(mGroupContext);
}
}
NS_IMETHODIMP
ImageGroupImpl::SetImgLoadAttributes(PRUint32 a_grouploading_attribs){
m_grouploading_attribs = a_grouploading_attribs;
return NS_OK;
}
NS_IMETHODIMP
ImageGroupImpl::GetImgLoadAttributes(PRUint32 *a_grouploading_attribs){
*a_grouploading_attribs = m_grouploading_attribs;
return NS_OK;
}
extern "C" NS_GFX_(nsresult)
NS_NewImageGroup(nsIImageGroup **aInstancePtrResult)
{
nsresult result;
NS_PRECONDITION(nsnull != aInstancePtrResult, "null ptr");
if (nsnull == aInstancePtrResult) {
return NS_ERROR_NULL_POINTER;
}
nsCOMPtr<nsIImageManager> manager;
manager = do_GetService(kImageManagerCID, &result);
if (NS_FAILED(result)) {
/* This is just to provide backwards compatibility, until the ImageManagerImpl
can be converted to a service on all platforms. Once, we done the conversion
on all platforms, we should be removing the call to NS_NewImageManager(...)
*/
if ((result = NS_NewImageManager(getter_AddRefs(manager))) != NS_OK) {
return result;
}
}
nsIImageGroup *group = new ImageGroupImpl(manager);
if (group == nsnull) {
return NS_ERROR_OUT_OF_MEMORY;
}
return group->QueryInterface(NS_GET_IID(nsIImageGroup), (void **) aInstancePtrResult);
}