mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-08 04:27:37 +00:00
367 lines
11 KiB
C++
367 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.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 "nsImageRequest.h"
|
|
#include "nsIImageGroup.h"
|
|
#include "nsIImageObserver.h"
|
|
#include "nsIImage.h"
|
|
#include "nsVoidArray.h"
|
|
#include "nsRect.h"
|
|
#include "nsImageNet.h"
|
|
|
|
static NS_DEFINE_IID(kIImageRequestIID, NS_IIMAGEREQUEST_IID);
|
|
|
|
static void ns_observer_proc (XP_Observable aSource,
|
|
XP_ObservableMsg aMsg,
|
|
void* aMsgData,
|
|
void* aClosure);
|
|
|
|
ImageRequestImpl::ImageRequestImpl()
|
|
{
|
|
}
|
|
|
|
ImageRequestImpl::~ImageRequestImpl()
|
|
{
|
|
// Delete the list of observers, and release the reference to the image
|
|
// request observer object
|
|
if (nsnull != mObservers) {
|
|
for (PRInt32 cnt = 0; cnt < mObservers->Count(); cnt++)
|
|
{
|
|
nsIImageRequestObserver* observer;
|
|
observer = (nsIImageRequestObserver*)mObservers->ElementAt(cnt);
|
|
|
|
NS_IF_RELEASE(observer);
|
|
mObservers->ReplaceElementAt(nsnull, cnt);
|
|
}
|
|
delete mObservers;
|
|
}
|
|
|
|
// XP Observer list destroyed by the image library
|
|
}
|
|
|
|
nsresult
|
|
ImageRequestImpl::Init(IL_GroupContext *aGroupContext,
|
|
const char* aUrl,
|
|
nsIImageRequestObserver *aObserver,
|
|
const nscolor* aBackgroundColor,
|
|
PRUint32 aWidth, PRUint32 aHeight,
|
|
PRUint32 aFlags,
|
|
ilINetContext* aNetContext)
|
|
{
|
|
NS_PRECONDITION(nsnull != aGroupContext, "null group context");
|
|
NS_PRECONDITION(nsnull != aUrl, "null URL");
|
|
|
|
NS_Error status;
|
|
IL_IRGB bgcolor;
|
|
PRUint32 flags;
|
|
|
|
mGroupContext = aGroupContext;
|
|
|
|
if (nsnull != aObserver) {
|
|
if (AddObserver(aObserver) == PR_FALSE) {
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
}
|
|
}
|
|
|
|
status = XP_NewObserverList(NULL, &mXPObserver);
|
|
if (status < 0) {
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
}
|
|
|
|
status = XP_AddObserver(mXPObserver, ns_observer_proc, (void *)this);
|
|
if (status < 0) {
|
|
XP_DisposeObserverList(mXPObserver);
|
|
mXPObserver = nsnull;
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
}
|
|
|
|
if (nsnull != aBackgroundColor)
|
|
{
|
|
bgcolor.red = NS_GET_R(*aBackgroundColor);
|
|
bgcolor.green = NS_GET_G(*aBackgroundColor);
|
|
bgcolor.blue = NS_GET_B(*aBackgroundColor);
|
|
}
|
|
|
|
flags = ((aFlags & IL_HIGH_PRIORITY) ? nsImageLoadFlags_kHighPriority : 0) |
|
|
((aFlags & IL_STICKY) ? nsImageLoadFlags_kSticky : 0) |
|
|
((aFlags & IL_BYPASS_CACHE) ? nsImageLoadFlags_kBypassCache : 0) |
|
|
((aFlags & IL_ONLY_FROM_CACHE) ? nsImageLoadFlags_kOnlyFromCache : 0);
|
|
|
|
mImageReq = IL_GetImage(aUrl, aGroupContext, mXPObserver,
|
|
nsnull == aBackgroundColor ? nsnull : &bgcolor,
|
|
aWidth, aHeight, flags, (void *)aNetContext);
|
|
|
|
if (mImageReq == nsnull) {
|
|
XP_DisposeObserverList(mXPObserver);
|
|
mXPObserver = nsnull;
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMPL_ADDREF(ImageRequestImpl)
|
|
NS_IMPL_QUERY_INTERFACE(ImageRequestImpl, kIImageRequestIID)
|
|
|
|
nsrefcnt ImageRequestImpl::Release(void)
|
|
{
|
|
if (--mRefCnt == 0) {
|
|
if (mXPObserver) {
|
|
// Make sure dangling reference to this object goes away
|
|
XP_RemoveObserver(mXPObserver, ns_observer_proc, (void*)this);
|
|
}
|
|
if (mImageReq) {
|
|
IL_DestroyImage(mImageReq);
|
|
}
|
|
NS_DELETEXPCOM(this);
|
|
return 0;
|
|
}
|
|
return mRefCnt;
|
|
}
|
|
|
|
nsIImage*
|
|
ImageRequestImpl::GetImage()
|
|
{
|
|
if (mImageReq != nsnull) {
|
|
IL_Pixmap *pixmap = IL_GetImagePixmap(mImageReq);
|
|
|
|
if (pixmap != nsnull) {
|
|
nsIImage *image = (nsIImage *)pixmap->client_data;
|
|
|
|
if (image != nsnull) {
|
|
NS_ADDREF(image);
|
|
return image;
|
|
}
|
|
}
|
|
}
|
|
|
|
return nsnull;
|
|
}
|
|
|
|
void
|
|
ImageRequestImpl::GetNaturalDimensions(PRUint32 *aWidth, PRUint32 *aHeight)
|
|
{
|
|
if (mImageReq != nsnull) {
|
|
IL_GetNaturalDimensions(mImageReq, (int *)aWidth, (int *)aHeight);
|
|
}
|
|
else {
|
|
*aWidth = 0;
|
|
*aHeight = 0;
|
|
}
|
|
}
|
|
|
|
PRBool
|
|
ImageRequestImpl::AddObserver(nsIImageRequestObserver *aObserver)
|
|
{
|
|
if (aObserver == nsnull) {
|
|
return PR_FALSE;
|
|
}
|
|
|
|
if (mObservers == nsnull) {
|
|
mObservers = new nsVoidArray();
|
|
if (mObservers == nsnull) {
|
|
return PR_FALSE;
|
|
}
|
|
}
|
|
|
|
NS_ADDREF(aObserver);
|
|
mObservers->AppendElement((void *)aObserver);
|
|
|
|
return PR_TRUE;
|
|
}
|
|
|
|
PRBool
|
|
ImageRequestImpl::RemoveObserver(nsIImageRequestObserver *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;
|
|
}
|
|
|
|
void
|
|
ImageRequestImpl::Interrupt()
|
|
{
|
|
if (mImageReq != nsnull) {
|
|
IL_InterruptRequest(mImageReq);
|
|
}
|
|
}
|
|
|
|
|
|
static void ns_observer_proc (XP_Observable aSource,
|
|
XP_ObservableMsg aMsg,
|
|
void* aMsgData,
|
|
void* aClosure)
|
|
{
|
|
ImageRequestImpl *image_request = (ImageRequestImpl *)aClosure;
|
|
IL_MessageData *message_data = (IL_MessageData *)aMsgData;
|
|
nsVoidArray *observer_list = image_request->GetObservers();
|
|
nsIImage *image = nsnull;
|
|
// IL_ImageReq *il_image_req = image_request->GetImageRequest();
|
|
IL_ImageReq *il_image_req = (IL_ImageReq *)aSource;
|
|
|
|
if (il_image_req != nsnull) {
|
|
IL_Pixmap *pixmap = IL_GetImagePixmap(il_image_req);
|
|
|
|
if (pixmap != nsnull) {
|
|
image = (nsIImage *)pixmap->client_data;
|
|
}
|
|
}
|
|
|
|
if (observer_list != nsnull) {
|
|
PRInt32 i, count = observer_list->Count();
|
|
nsIImageRequestObserver *observer;
|
|
for (i = 0; i < count; i++) {
|
|
observer = (nsIImageRequestObserver *)observer_list->ElementAt(i);
|
|
if (observer != nsnull) {
|
|
switch (aMsg) {
|
|
case IL_START_URL:
|
|
observer->Notify(image_request,
|
|
image, nsImageNotification_kStartURL, 0, 0,
|
|
nsnull);
|
|
break;
|
|
case IL_DESCRIPTION:
|
|
observer->Notify(image_request,
|
|
image, nsImageNotification_kDescription, 0, 0,
|
|
message_data->description);
|
|
break;
|
|
case IL_DIMENSIONS:
|
|
observer->Notify(image_request,
|
|
image, nsImageNotification_kDimensions,
|
|
(PRInt32)message_data->width,
|
|
(PRInt32)message_data->height,
|
|
nsnull);
|
|
break;
|
|
case IL_IS_TRANSPARENT:
|
|
observer->Notify(image_request,
|
|
image, nsImageNotification_kIsTransparent, 0, 0,
|
|
nsnull);
|
|
break;
|
|
case IL_PIXMAP_UPDATE:
|
|
{
|
|
nsRect rect(message_data->update_rect.x_origin,
|
|
message_data->update_rect.y_origin,
|
|
message_data->update_rect.width,
|
|
message_data->update_rect.height);
|
|
|
|
observer->Notify(image_request,
|
|
image, nsImageNotification_kPixmapUpdate, 0, 0,
|
|
&rect);
|
|
}
|
|
break;
|
|
case IL_FRAME_COMPLETE:
|
|
observer->Notify(image_request,
|
|
image, nsImageNotification_kFrameComplete, 0, 0,
|
|
nsnull);
|
|
break;
|
|
case IL_PROGRESS:
|
|
observer->Notify(image_request,
|
|
image, nsImageNotification_kProgress,
|
|
message_data->percent_progress, 0,
|
|
nsnull);
|
|
break;
|
|
case IL_IMAGE_COMPLETE:
|
|
observer->Notify(image_request,
|
|
image, nsImageNotification_kImageComplete, 0, 0,
|
|
nsnull);
|
|
break;
|
|
case IL_STOP_URL:
|
|
observer->Notify(image_request,
|
|
image, nsImageNotification_kStopURL, 0, 0,
|
|
nsnull);
|
|
break;
|
|
case IL_IMAGE_DESTROYED:
|
|
image_request->SetImageRequest(nsnull);
|
|
observer->Notify(image_request,
|
|
image, nsImageNotification_kImageDestroyed, 0, 0,
|
|
nsnull);
|
|
break;
|
|
case IL_ABORTED:
|
|
observer->Notify(image_request,
|
|
image, nsImageNotification_kAborted, 0, 0,
|
|
nsnull);
|
|
break;
|
|
case IL_INTERNAL_IMAGE:
|
|
observer->Notify(image_request,
|
|
image, nsImageNotification_kInternalImage, 0, 0,
|
|
nsnull);
|
|
break;
|
|
case IL_NOT_IN_CACHE:
|
|
observer->NotifyError(image_request,
|
|
nsImageError_kNotInCache);
|
|
break;
|
|
case IL_ERROR_NO_DATA:
|
|
observer->NotifyError(image_request,
|
|
nsImageError_kNoData);
|
|
break;
|
|
case IL_ERROR_IMAGE_DATA_CORRUPT:
|
|
observer->NotifyError(image_request,
|
|
nsImageError_kImageDataCorrupt);
|
|
break;
|
|
case IL_ERROR_IMAGE_DATA_TRUNCATED:
|
|
observer->NotifyError(image_request,
|
|
nsImageError_kImageDataTruncated);
|
|
break;
|
|
case IL_ERROR_IMAGE_DATA_ILLEGAL:
|
|
observer->NotifyError(image_request,
|
|
nsImageError_kImageDataIllegal);
|
|
break;
|
|
case IL_ERROR_INTERNAL:
|
|
observer->NotifyError(image_request,
|
|
nsImageError_kInternalError);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* If the IL_ImageReq is being destroyed, clear the reference held by
|
|
* the nsImageRequestImpl...
|
|
*
|
|
* This will prevent a dangling reference in cases where the image group
|
|
* is destroyed before the image request...
|
|
*/
|
|
if ((IL_IMAGE_DESTROYED == aMsg) && (nsnull != image_request)) {
|
|
image_request->SetImageRequest(nsnull);
|
|
image_request->ImageDestroyed();
|
|
}
|
|
}
|
|
|
|
void
|
|
ImageRequestImpl::ImageDestroyed()
|
|
{
|
|
if (mXPObserver) {
|
|
// Make sure dangling reference to this object goes
|
|
// away; this is just in case the image library changes
|
|
// and holds onto the observer list after destroying the
|
|
// image.
|
|
XP_RemoveObserver(mXPObserver, ns_observer_proc, (void*)this);
|
|
mXPObserver = nsnull;
|
|
}
|
|
}
|