Mozilla/mozilla/cmd/xfe/src/RDFImage.cpp
radha%netscape.com 19ea8191f4 Image rendering code modified. Normal image rendering now happens
in the usual place at image.cpp. only RDF cases are handled here.


git-svn-id: svn://10.0.0.236/trunk@11651 18797224-902f-48f8-a5cc-f745e15eee43
1998-10-01 04:55:50 +00:00

508 lines
12 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (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 Communicator client 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.
*/
/*
RDFImage.cpp - Aurora Image loading class
Created: Radha Kulkarni <radha@netscape.com>, 06-29-98
*/
#include "RDFImage.h"
#include "ViewGlue.h"
#include "xfe.h"
#include "il_util.h"
#ifdef DEBUG_radha
#define D(x) x
#else
#define D(x)
#endif
#if 0
extern "C"
{
void DisplayPixmap(MWContext *, IL_Pixmap *, IL_Pixmap *);
void NewPixmap(MWContext *, IL_Pixmap * image, PRBool mask);
void ImageComplete(MWContext *, IL_Pixmap * image);
void fe_load_default_font(MWContext *context);
};
#endif
int XFE_RDFImage::refCount = 0;
int XFE_RDFImage::m_numRDFImagesLoaded = 0;
RDFImageList * XFE_RDFImage::RDFImagesCache = (RDFImageList *) NULL;
// Max number of images in cache - to be replaced with very clever hash table
unsigned int XFE_RDFImage::MaxRdfImages = 30;
//unsigned int XFE_RDFImage::ImageListIncrSize = 20;
//////////////////////////////////////////////////////////////////////////
// Initialize the images list. This s'd someday be a hash list
void
XFE_RDFImage::imageCacheInitialize()
{
/* The array way of indexing the cache only works for now when
* NavCenterView is the only client of RDFImage. This w'd break or
* corrupt if more clients come in for RDFImage. The cache needs
* to be a Doubly linked list. That will happen in the next round
* of changes to RDFImage.
*/
if (RDFImagesCache == NULL)
{
m_numRDFImagesLoaded = 0;
RDFImagesCache = (RDFImageList *) XP_CALLOC(MaxRdfImages, sizeof(RDFImageList));
}
}
XFE_RDFImage::XFE_RDFImage(XFE_Component * frame,
void * requestedObj,
char * imageURL,
fe_colormap * cmap,
Widget baseWidget)
: XFE_Image(frame, imageURL, cmap, baseWidget)
{
// Initializations
pairCount = 0;
completeCallback = (completeCallbackPtr) NULL;
callbackData = (void *) NULL;
// Make sure the cache is up and running.
// XFE_RDFImage::imageCacheInitialize();
if (cxtInitSucceeded)
addListener(requestedObj, baseWidget, imageURL);
}
XFE_RDFImage::~XFE_RDFImage()
{
int i = 0, j = 0;
// Delete the bad image if m_numRDFImagesLoaded = 0
if (m_numRDFImagesLoaded == 0)
{
D(printf("Need to delete the bad image here \n");)
XP_FREE(RDFImagesCache);
}
}
/* Set the callback for the requestor */
void
XFE_RDFImage::setCompleteCallback(completeCallbackPtr callback, void * client_data)
{
completeCallback = callback;
callbackData = client_data;
}
/* Image library callback with the image pixmap and mask. The mask
* mask part is not working right now.
*/
void
XFE_RDFImage::RDFDisplayPixmap(IL_Pixmap * image, IL_Pixmap * mask, PRInt32 width, PRInt32 height)
{
m_image = image;
m_mask = mask;
imageWidth = width;
imageHeight = height;
pairCount++;
if (!completelyLoaded)
{
callbackClientData * client_data = XP_NEW_ZAP(callbackClientData);
client_data->widget = (Widget)callbackData;
client_data->image = getPixmap();
client_data->mask = getMask();
/*
client_data->width = width;
client_data->height = height;
*/
completelyLoaded = True;
if (isrequestorAlive(client_data->widget))
(*completeCallback)(client_data);
}
return;
}
/* Image library callback */
void
XFE_RDFImage::RDFNewPixmap(IL_Pixmap * image, PRBool isMask)
{
if (isMask)
m_mask = image;
else m_image = image;
}
/* This method is really useful when different images are
* requested. If a request for the same image is made
* in immediate succession like we do right now in NavCenterView.cpp
* this doesn't work. So commented off for now
*/
void
XFE_RDFImage::RDFImageComplete(IL_Pixmap * image)
{
#ifdef UNDEF
// Will get a call for both the mask and for the image.
if (m_image && m_mask)
{
if (pairCount == 2)
if (isrequestorAlive)
(*completeCallback)(getPixmap(), getMask(), callbackData);
else
pairCount++;
}
else if (m_image)
{
// We have no mask.
if (isrequestorAlive)
(*completeCallback)(getPixmap(), getMask(), callbackData);
}
#endif /* UNDEF */
}
/* returns if the image has been completely loaded */
PRBool
XFE_RDFImage::isImageLoaded(void)
{
return (completelyLoaded);
}
/* return the image pixmap */
Pixmap
XFE_RDFImage::getPixmap(void)
{
if (m_image && m_image->client_data)
return (Pixmap)(((fe_PixmapClientData *)(m_image->client_data))->pixmap);
return (Pixmap)NULL;
}
/* Return the image mask */
Pixmap
XFE_RDFImage::getMask(void)
{
if (m_mask && m_mask->client_data)
return (Pixmap)(((fe_PixmapClientData *)(m_mask->client_data))->pixmap);
return (Pixmap)NULL;
}
/* Get image width */
PRInt32
XFE_RDFImage::getImageWidth(void)
{
return(imageWidth);
}
/* Get image height */
PRInt32
XFE_RDFImage::getImageHeight(void)
{
return(imageHeight);
}
/* Call NET_GetURL() to fetch the image */
void
XFE_RDFImage::loadImage(void)
{
if (cxtInitSucceeded)
NET_GetURL(NET_CreateURLStruct(m_urlString, NET_DONT_RELOAD),
FO_CACHE_AND_PRESENT, m_imageContext,
XFE_Image::getURLExit_cb);
}
/*
* Given a imageURL, this method goes thro' the cache and checks if
* is already available. If available, it returns a handle to the
* RDFImageobject, that holds the pixmap for the image.
* The lookup is currently a simple strcmp. But it can be replaced by
* a better system.
*/
XFE_RDFImage *
XFE_RDFImage::isImageAvailable(char * imageURL)
{
RDFImageList * ptr = RDFImagesCache;
if (!ptr)
return (XFE_RDFImage *) NULL;
do
{
if ((!XP_STRCMP(imageURL, ptr->imageURL))) {
/* If the RDFImage object related to the url
* is still around, and the pixmap has been completely loaded,
* return handle to the RDFImage object.
*/
if (ptr->obj && ((ptr->obj)->isImageLoaded()))
return (ptr->obj);
else
/* The image URL is in the cache,but the image is not ready yet */
return((XFE_RDFImage *)NULL);
}
ptr = ptr->next;
} while (ptr != RDFImagesCache);
return (XFE_RDFImage *)NULL;
#ifdef UNDEF
int i = 0;
for (i = 0; i< m_numRDFImagesLoaded; i++)
{
if (!XP_STRCMP(imageURL, RDFImagesCache[i].imageURL))
{
/* If the RDFImage object related to the url
* is still around, and the pixmap has been completely loaded,
* return handle to the RDFImage object.
*/
if (RDFImagesCache[i].obj && ((RDFImagesCache[i].obj)->isImageLoaded()))
return (RDFImagesCache[i].obj);
}
} // for
return (XFE_RDFImage * ) NULL;
#endif /* UNDEF */
}
/*
* Remove a widget from the listener list.
* This s'd be called by the destroy callback of the
* widget that requested the image. This is to take care of cases
* where a specific widget associated with the image goes away, but the
* class that it originated from is not gone. This
* works with isRequestorAlive()
*/
void
XFE_RDFImage::removeListener(Widget w)
{
RDFImageList * ptr = RDFImagesCache;
if (!ptr)
return;
do
{
if (ptr->widget == w) {
ptr->widget = NULL;
}
ptr = ptr->next;
} while (ptr != RDFImagesCache);
}
/*
* This method s'd be called from the requesting object's destructor.
* It basically goes through the cache and deletes all the RDFImage
* objects that the requestor had requested.
*/
void
XFE_RDFImage::removeListener(void * obj)
{
RDFImageList * ptr = RDFImagesCache, *p;
int cnt = m_numRDFImagesLoaded;
if (!ptr)
return;
do
{
if (ptr->requestedObj == obj) {
removeListener(ptr);
// set the pointers properly
ptr->prev->next = ptr->next;
ptr->next->prev = ptr->prev;
p = ptr->next;
if (ptr == RDFImagesCache)
RDFImagesCache = ptr->next;
XP_FREE(ptr);
ptr = p;
}
else
ptr = ptr->next;
cnt--;
} while (/* ptr->next != RDFImagesCache */ cnt != 0) ;
} /* removeListener */
/* free and reset an element in the cache */
void
XFE_RDFImage::removeListener(RDFImageList * ptr) {
// free the string
if (ptr->imageURL) {
free(ptr->imageURL);
}
// Set the widget pointer to NULL
ptr->widget = NULL;
/* Delete the RDFImage object */
if (ptr->obj) {
delete(ptr->obj);
}
// reset the requestor's pointer
ptr->requestedObj = (void *)NULL;
m_numRDFImagesLoaded--;
} /* removeListener */
/* Add a new image to the cache */
void
XFE_RDFImage::addListener(void * requestedObj, Widget w, char * imageURL)
{
RDFImageList * ptr = XP_NEW_ZAP(RDFImageList);
if (m_numRDFImagesLoaded == 0) {
/* First entry */
RDFImagesCache = ptr;
}
ptr->next = RDFImagesCache;
ptr->prev = ((m_numRDFImagesLoaded == 0) ? RDFImagesCache : RDFImagesCache->prev);
(ptr->prev)->next = ptr;
RDFImagesCache->prev = ptr;
ptr->obj = this;
ptr->requestedObj = requestedObj;
ptr->widget = w;
ptr->imageURL = (char *)XP_ALLOC(sizeof(char) * (strlen(imageURL) + 1));
strncpy(ptr->imageURL, imageURL, strlen(imageURL));
m_numRDFImagesLoaded++;
#ifdef UNDEF
/* Go through the cache and see if there are any existing
* space that is available.
*/
for (i=0; i<m_numRDFImagesLoaded; i++) {
if (RDFImagesCache[i].isSpaceAvailable) {
break;
}
}
if (m_numRDFImagesLoaded == MaxRdfImages) {
/* The array is full. realloc */
RDFImagesCache = (RDFImageList *) XP_REALLOC(RDFImagesCache, ((MaxRdfImages + ImageListIncrSize)*sizeof(RDFImageList)));
MaxRdfImages +=ImageListIncrSize;
}
if (m_numRDFImagesLoaded < MaxRdfImages) {
RDFImagesCache[i].obj = this;
RDFImagesCache[i].requestedObj = requestedObj;
RDFImagesCache[i].widget = w;
RDFImagesCache[i].imageURL = (char *)XP_ALLOC(sizeof(char) * (strlen(imageURL) + 1));
strncpy(RDFImagesCache[i].imageURL, imageURL, strlen(imageURL));
RDFImagesCache[i].isSpaceAvailable = False;
m_numRDFImagesLoaded++;
}
#endif /* UNDEF */
} /* addListener */
/*
* This is called by RDFDisplayPixmap(),
* to make sure that the widget that
* requested the image is still around
*/
PRBool
XFE_RDFImage::isrequestorAlive(Widget w)
{
RDFImageList * ptr = RDFImagesCache;
if (!ptr)
return(False);
do
{
if (ptr->widget == w) {
return(True);
}
ptr = ptr->next;
} while (ptr != RDFImagesCache);
return (False);
#ifdef UNDEF
for(int i = 0; i<m_numRDFImagesLoaded; i++) {
if (RDFImagesCache[i].widget == w)
return (True);
}
return (False);
#endif /* UNDEF */
}
/*
* Given a widget id, get a handle to the corresponding RDFImage object
* This is used by the Image library callbacks, for whom the widget id
* is the only link to the XFE world
*/
XFE_RDFImage *
XFE_RDFImage::getRDFImageObject(Widget w)
{
RDFImageList * ptr = RDFImagesCache;
if (!ptr)
return(XFE_RDFImage *) NULL;
do
{
if (ptr->widget == w) {
return(ptr->obj);
}
ptr = ptr->next;
} while (ptr != RDFImagesCache);
return (XFE_RDFImage *)NULL;
#ifdef UNDEF
for(int i = 0; i<m_numRDFImagesLoaded; i++) {
if (RDFImagesCache[i].widget == w)
return (RDFImagesCache[i].obj);
}
return (XFE_RDFImage *) NULL;
#endif /* UNDEF */
}