Re-arrange the Cache code and add more utility functions

This commit is contained in:
radha%netscape.com 1998-08-24 20:11:25 +00:00
Родитель 0d5cb121b9
Коммит 3aa05f6dc7
2 изменённых файлов: 292 добавлений и 549 удалений

Просмотреть файл

@ -41,162 +41,74 @@ void fe_load_default_font(MWContext *context);
int XFE_RDFImage::refCount = 0; int XFE_RDFImage::refCount = 0;
Pixmap XFE_RDFImage::m_badImage = 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;
XFE_RDFImage::XFE_RDFImage(XFE_Component * frame, char * imageURL,fe_colormap * cmap, Widget baseWidget) {
//////////////////////////////////////////////////////////////////////////
// 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 // Initializations
m_urlString = strdup(imageURL);
completelyLoaded = False;
//FrameLoaded = False;
badImage = False;
pairCount = 0; pairCount = 0;
refCount = 0;
m_imageContext = NULL;
fec = NULL;
cxtInitSucceeded = False;
m_image = NULL;
m_mask = NULL;
completeCallback = (completeCallbackPtr) NULL; completeCallback = (completeCallbackPtr) NULL;
callbackData = (void *) NULL; callbackData = (void *) NULL;
m_frame = frame;
imageDrawn = False;
refCount++;
// Create new context
m_imageContext = XP_NewContext();
fec = XP_NEW_ZAP(fe_ContextData);
if (m_imageContext && fec) // Make sure the cache is up and running.
{ XFE_RDFImage::imageCacheInitialize();
m_imageContext->type = MWContextIcon;
CONTEXT_DATA(m_imageContext) = fec;
// Set up the image library callbacks
CONTEXT_DATA(m_imageContext)->DisplayPixmap = (DisplayPixmapPtr)DisplayPixmap;
CONTEXT_DATA(m_imageContext)->NewPixmap = (NewPixmapPtr)NewPixmap;
CONTEXT_DATA(m_imageContext)->ImageComplete = (ImageCompletePtr)ImageComplete;
/* Stolen from Frame.cpp. Maybe we s'd make a generic class for if (cxtInitSucceeded)
* Creation and management of MWContexts addListener(requestedObj, baseWidget, imageURL);
*/
CONTEXT_DATA (m_imageContext)->colormap = cmap;
CONTEXT_WIDGET (m_imageContext) = baseWidget;
CONTEXT_DATA(m_imageContext)->drawing_area = baseWidget;
m_imageContext->funcs = fe_BuildDisplayFunctionTable();
m_imageContext->convertPixX = m_imageContext->convertPixY = 1;
m_imageContext->is_grid_cell = FALSE;
m_imageContext->grid_parent = NULL;
XP_AddContextToList(m_imageContext);
fe_InitIconColors(m_imageContext);
// Use colors from prefs
LO_Color *color;
color = &fe_globalPrefs.links_color;
CONTEXT_DATA(m_imageContext)->link_pixel =
fe_GetPixel(m_imageContext, color->red, color->green, color->blue);
color = &fe_globalPrefs.vlinks_color;
CONTEXT_DATA(m_imageContext)->vlink_pixel =
fe_GetPixel(m_imageContext, color->red, color->green, color->blue);
color = &fe_globalPrefs.text_color;
CONTEXT_DATA(m_imageContext)->default_fg_pixel =
fe_GetPixel(m_imageContext, color->red, color->green, color->blue);
color = &fe_globalPrefs.background_color;
CONTEXT_DATA(m_imageContext)->default_bg_pixel =
fe_GetPixel(m_imageContext, color->red, color->green, color->blue);
SHIST_InitSession (m_imageContext);
fe_load_default_font(m_imageContext);
{
Pixel unused_select_pixel;
XmGetColors (XtScreen (baseWidget),
fe_cmap(m_imageContext),
CONTEXT_DATA (m_imageContext)->default_bg_pixel,
&(CONTEXT_DATA (m_imageContext)->fg_pixel),
&(CONTEXT_DATA (m_imageContext)->top_shadow_pixel),
&(CONTEXT_DATA (m_imageContext)->bottom_shadow_pixel),
&unused_select_pixel);
}
/* Add mapping between MWContext and frame */
ViewGlue_addMapping((XFE_Frame *)m_frame, m_imageContext);
/* Initialize the Imagelib callbacks, Imagecontexts,
* imageobserver and group contexts
*/
if (!fe_init_image_callbacks(m_imageContext))
{
cxtInitSucceeded = False;
return;
}
fe_InitColormap (m_imageContext);
cxtInitSucceeded = True;
}
else
{
cxtInitSucceeded = False;
return;
}
} }
XFE_RDFImage::~XFE_RDFImage() XFE_RDFImage::~XFE_RDFImage()
{ {
int i = 0, j = 0;
free(m_urlString);
free (CONTEXT_DATA (m_imageContext));
free (m_imageContext);
refCount--;
// Delete the bad image if refcount = 0 // Delete the bad image if m_numRDFImagesLoaded = 0
if (refCount == 0) if (m_numRDFImagesLoaded == 0)
{ {
D(printf("Need to delete the bad image\n");) D(printf("Need to delete the bad image here \n");)
XP_FREE(RDFImagesCache);
} }
// Destroy the Image groupcontexts and observers
if (m_imageContext)
{
PRBool observer_removed_p;
if (m_imageContext->color_space)
{
D(printf("Deleting image color spaces\n");)
IL_ReleaseColorSpace(m_imageContext->color_space);
m_imageContext->color_space = NULL;
}
/* Destroy the image group context after removing the image group
* observer
*/
D(printf("Deleting the image observer\n");)
observer_removed_p =
IL_RemoveGroupObserver(m_imageContext->img_cx,
fe_ImageGroupObserver,
(void *)m_imageContext);
IL_DestroyGroupContext(m_imageContext->img_cx);
m_imageContext->img_cx = NULL;
}
} }
/* Set the callback for the requestor */
void void
XFE_RDFImage::setCompleteCallback(completeCallbackPtr callback, void * client_data) XFE_RDFImage::setCompleteCallback(completeCallbackPtr callback, void * client_data)
{ {
@ -206,14 +118,19 @@ XFE_RDFImage::setCompleteCallback(completeCallbackPtr callback, void * client_d
} }
/* Image library callback with the image pixmap and mask. The mask
* mask part is not working right now.
*/
void void
XFE_RDFImage::RDFDisplayPixmap(IL_Pixmap * image, IL_Pixmap * mask, PRInt32 width, PRInt32 height) XFE_RDFImage::RDFDisplayPixmap(IL_Pixmap * image, IL_Pixmap * mask, PRInt32 width, PRInt32 height)
{ {
m_image = image; m_image = image;
m_mask = mask; m_mask = mask;
imageWidth = width;
imageHeight = height;
pairCount++; pairCount++;
if (!imageDrawn) if (!completelyLoaded)
{ {
callbackClientData * client_data = XP_NEW_ZAP(callbackClientData); callbackClientData * client_data = XP_NEW_ZAP(callbackClientData);
client_data->widget = (Widget)callbackData; client_data->widget = (Widget)callbackData;
@ -221,13 +138,15 @@ XFE_RDFImage::RDFDisplayPixmap(IL_Pixmap * image, IL_Pixmap * mask, PRInt32 widt
client_data->mask = getMask(); client_data->mask = getMask();
client_data->width = width; client_data->width = width;
client_data->height = height; client_data->height = height;
completelyLoaded = True;
if (isrequestorAlive)
(*completeCallback)(client_data); (*completeCallback)(client_data);
imageDrawn = True;
} }
return; return;
} }
/* Image library callback */
void void
XFE_RDFImage::RDFNewPixmap(IL_Pixmap * image, Boolean isMask) XFE_RDFImage::RDFNewPixmap(IL_Pixmap * image, Boolean isMask)
{ {
@ -237,15 +156,22 @@ XFE_RDFImage::RDFNewPixmap(IL_Pixmap * image, Boolean isMask)
} }
/* 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 void
XFE_RDFImage::RDFImageComplete(IL_Pixmap * image) XFE_RDFImage::RDFImageComplete(IL_Pixmap * image)
{ {
#ifdef UNDEF #ifdef UNDEF
// Will get a call for both the mask and for the image. // Will get a call for both the mask and for the image.
if (m_image && m_mask) if (m_image && m_mask)
{ {
if (pairCount == 2) if (pairCount == 2)
if (isrequestorAlive)
(*completeCallback)(getPixmap(), getMask(), callbackData); (*completeCallback)(getPixmap(), getMask(), callbackData);
else else
pairCount++; pairCount++;
@ -253,13 +179,14 @@ XFE_RDFImage::RDFImageComplete(IL_Pixmap * image)
else if (m_image) else if (m_image)
{ {
// We have no mask. // We have no mask.
if (isrequestorAlive)
(*completeCallback)(getPixmap(), getMask(), callbackData); (*completeCallback)(getPixmap(), getMask(), callbackData);
} }
#endif /* UNDEF */ #endif /* UNDEF */
} }
/* returns if the image has been completely loaded */
Boolean Boolean
XFE_RDFImage::isImageLoaded(void) XFE_RDFImage::isImageLoaded(void)
{ {
@ -267,47 +194,19 @@ XFE_RDFImage::isImageLoaded(void)
} }
extern "C"
{
void
Icon_GetUrlExitRoutine(URL_Struct *pUrl, int iStatus, MWContext *pContext)
{
// Report any errors.
if(iStatus < 0 && pUrl->error_msg != NULL)
{
printf("Couldn't load image. Need to put the bad image up\n");
#ifdef UNDEF
// Since we cannot load this url, replace it with a bad image.
theImage->m_BadImage = TRUE;
theImage->bits = 0;
theImage->maskbits = 0;
theImage->bmpInfo = 0;
if (!CRDFImage::m_hBadImageBitmap)
CRDFImage::m_hBadImageBitmap = ::LoadBitmap(AfxGetResourceHandle(), MAKEINTRESOURCE(IDB_IMAGE_BAD));
theImage->CompleteCallback();
#endif /* UNDEF */
}
}
}; /* extern C */
/* return the image pixmap */
void Pixmap
XFE_RDFImage::loadImage(void) XFE_RDFImage::getPixmap(void)
{
if (cxtInitSucceeded)
NET_GetURL(NET_CreateURLStruct(m_urlString, NET_DONT_RELOAD), FO_CACHE_AND_PRESENT, m_imageContext, Icon_GetUrlExitRoutine);
}
Pixmap XFE_RDFImage::getPixmap(void)
{ {
if (m_image) if (m_image)
return (Pixmap)(((fe_PixmapClientData *)(m_image->client_data))->pixmap); return (Pixmap)(((fe_PixmapClientData *)(m_image->client_data))->pixmap);
return (Pixmap)NULL; return (Pixmap)NULL;
} }
Pixmap XFE_RDFImage::getMask(void) /* Return the image mask */
Pixmap
XFE_RDFImage::getMask(void)
{ {
if (m_mask) if (m_mask)
return (Pixmap)(((fe_PixmapClientData *)(m_mask->client_data))->pixmap); return (Pixmap)(((fe_PixmapClientData *)(m_mask->client_data))->pixmap);
@ -315,376 +214,203 @@ Pixmap XFE_RDFImage::getMask(void)
} }
/* 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, Image_GetUrlExitRoutine);
}
/*
* 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)
{
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;
}
/*
* 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)
{
int totalImages = m_numRDFImagesLoaded;
for (int i=0; i<totalImages; i++)
{
if (RDFImagesCache[i].requestedObj == obj) {
removeListener(i);
}
}
}
/* free and reset an element in the cache */
void
XFE_RDFImage::removeListener(int i) {
if (!RDFImagesCache[i].isSpaceAvailable) {
// free the string
if (RDFImagesCache[i].imageURL) {
free(RDFImagesCache[i].imageURL);
RDFImagesCache[i].imageURL = (char *) NULL;
}
// Set the widget pointer to NULL
RDFImagesCache[i].widget = NULL;
/* I don't think I need to do this here. The RDFImage
* object can be deleted from the destructor
*/
#ifdef UNDEF #ifdef UNDEF
if (RDFImagesCache[i].obj) {
delete(RDFImagesCache[i].obj);
RDFImagesCache[i].obj = (XFE_RDFImage *) NULL;
}
#endif /* UNDEF */
CRDFImage::~CRDFImage() // reset the requestor's pointer
{ RDFImagesCache[i].requestedObj = (void *)NULL;
// XP_FREE( bmpInfo);
// CDCCX::HugeFree(bits);
// CDCCX::HugeFree(maskbits);
free(pUrl);
CRDFImage::refCount--; // Mark the space to be available
if (refCount == 0) RDFImagesCache[i].isSpaceAvailable = True;
{ m_numRDFImagesLoaded--;
if (CRDFImage::m_hBadImageBitmap)
VERIFY(::DeleteObject(CRDFImage::m_hBadImageBitmap));
}
}
void CRDFImage::AddListener(CCustomImageObject* pObject, HT_Resource r)
{
// We only want to have one copy of the same image in this list.
for (POSITION pos = resourceList.GetHeadPosition();
pos != NULL; )
{
// Enumerate over the list and call remove listener on each image.
CIconCallbackInfo* pInfo = (CIconCallbackInfo*)resourceList.GetNext(pos);
if (pInfo->pObject == pObject &&
pInfo->pResource == r)
return; // We're already listening for this resource.
}
// Add a listener.
CIconCallbackInfo* iconCallbackInfo = new CIconCallbackInfo(pObject, r);
resourceList.AddHead(iconCallbackInfo);
pObject->AddLoadingImage(this);
m_nRefCount++;
if (iconContext == NULL)
{
// Kick off the load.
ProcessIcon();
}
}
void CRDFImage::RemoveListener(CCustomImageObject *pObject)
{
// Listener has been destroyed. Need to get all references to it out of the list.
// Just do this by NULLing out the pObject field of the iconcallbackinfo structs.
for (POSITION pos = resourceList.GetHeadPosition();
pos != NULL; )
{
CIconCallbackInfo* pInfo = (CIconCallbackInfo*)resourceList.GetNext(pos);
if (pInfo->pObject == pObject)
{
pInfo->pObject = NULL;
m_nRefCount--;
if (m_nRefCount == 0 && iconContext)
{
iconContext->Interrupt();
DestroyContext();
return;
}
}
}
}
void CRDFImage::RemoveListenerForSpecificResource(CCustomImageObject *pObject, HT_Resource r)
{
// Listener has been destroyed. Need to get all references to it out of the list.
// Just do this by NULLing out the pObject field of the iconcallbackinfo structs.
for (POSITION pos = resourceList.GetHeadPosition();
pos != NULL; )
{
CIconCallbackInfo* pInfo = (CIconCallbackInfo*)resourceList.GetNext(pos);
if (pInfo->pObject == pObject && pInfo->pResource == r)
{
pInfo->pObject = NULL;
m_nRefCount--;
if (m_nRefCount == 0 && iconContext)
{
iconContext->Interrupt();
DestroyContext();
return;
}
}
} }
} }
void CRDFImage::DestroyContext() /*
* 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 is suppose to
* work with isRequestorAlive()
*/
void
XFE_RDFImage::removeListener(Widget w)
{ {
iconContext->DeleteContextDC(); for (int i=0; i<m_numRDFImagesLoaded; i++)
iconContext->NiceDestruction();
iconContext = NULL;
resourceList.RemoveAll();
}
BOOL CRDFImage::FrameLoaded()
{
return (m_bFrameLoaded);
}
BOOL CRDFImage::FrameSuccessfullyLoaded()
{
return (m_bFrameLoaded && bits);
}
BOOL CRDFImage::CompletelyLoaded()
{
return m_bCompletelyLoaded;
}
static BOOL IsImageMimeType(const CString& theFormat)
{
BOOL val = FALSE;
if (theFormat.CompareNoCase(IMAGE_GIF) == 0)
val = TRUE;
else if (theFormat.CompareNoCase(IMAGE_JPG) == 0)
val = TRUE;
else if (theFormat.CompareNoCase(IMAGE_PJPG) == 0)
val = TRUE;
else if (theFormat.CompareNoCase(IMAGE_PPM) == 0)
val = TRUE;
else if (theFormat.CompareNoCase(IMAGE_PNG) == 0)
val = TRUE;
else if (theFormat.CompareNoCase(IMAGE_XBM) == 0)
val = TRUE;
else if (theFormat.CompareNoCase(IMAGE_XBM2) == 0)
val = TRUE;
else if (theFormat.CompareNoCase(IMAGE_XBM3) == 0)
val = TRUE;
return val;
}
static BOOL ValidNSBitmapFormat(char* extension)
{
CPtrList* allHelpers = &(CHelperApp::m_cplHelpers);
for (POSITION pos = allHelpers->GetHeadPosition(); pos != NULL;)
{ {
CHelperApp* app = (CHelperApp*)allHelpers->GetNext(pos); if (RDFImagesCache[i].widget == w) {
CString helperMime(app->cd_item->ci.type); RDFImagesCache[i].widget = NULL;
}
}
if (IsImageMimeType(helperMime))
{
if (app->cd_item->num_exts > 0)
{
for (int i = 0; i < app->cd_item->num_exts; i++)
{
CString extString(app->cd_item->exts[i]);
if (extString == &extension[1])
return TRUE;
}
}
}
}
return FALSE;
} }
void CRDFImage::ProcessIcon() /* Add a new image to the cache */
void
XFE_RDFImage::addListener(void * requestedObj, Widget w, char * imageURL)
{ {
char *ext = FE_FindFileExt(pUrl);
if (ValidNSBitmapFormat(ext))
{
// If there is no context, create one for processing the image.
hSubDC = ::CreateCompatibleDC(NULL);
if (iconContext == NULL) int i =0;
{ /* Go through the cache and see if there are any existing
iconContext = new CXIcon(this); * space that is available.
iconContext->SubstituteDC(hSubDC); */
iconContext->Initialize(FALSE, NULL, FALSE);
iconContext->SetUseDibPalColors(FALSE); for (i=0; i<m_numRDFImagesLoaded; i++) {
if (RDFImagesCache[i].isSpaceAvailable) {
break;
}
} }
// Temporary hack to disable loading RDF images for the layout integration if (m_numRDFImagesLoaded == MaxRdfImages) {
// build. /* The array is full. realloc */
#ifndef MOZ_NGLAYOUT RDFImagesCache = (RDFImageList *) XP_REALLOC(RDFImagesCache, ((MaxRdfImages + ImageListIncrSize)*sizeof(RDFImageList)));
// Ask for this via client pull. MaxRdfImages +=ImageListIncrSize;
// We may be in the call stack of the image lib, and doing
// lots of fast small get urls causes it to barf due
// to list management not being reentrant.
FEU_ClientPull(iconContext->GetContext(), 0, NET_CreateURLStruct(pUrl, NET_DONT_RELOAD), FO_CACHE_AND_PRESENT, FALSE);
#endif
}
else
{ // handle window internal format BMP
CString extension = ext;
if (extension.CompareNoCase(".bmp"))
{
}
else
{
// TODO: Error handling here, unknow bitmap format.
}
} }
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++;
}
} }
void CRDFImage::CompleteCallback() /*
* This is called by RDFDisplayPixmap(),
* to make sure that the widget that
* requested the image is still around
*/
PRBool
XFE_RDFImage::isrequestorAlive(Widget w)
{ {
m_bCompletelyLoaded = TRUE; for(int i = 0; i<m_numRDFImagesLoaded; i++) {
while (!resourceList.IsEmpty()) if (RDFImagesCache[i].widget == w)
{ return (True);
CIconCallbackInfo* callback = (CIconCallbackInfo*)(resourceList.RemoveHead());
if (callback->pObject)
{
callback->pObject->LoadComplete(callback->pResource);
callback->pObject->RemoveLoadingImage(this);
} }
delete callback; return (False);
}
/*
* 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)
{
for(int i = 0; i<m_numRDFImagesLoaded; i++) {
if (RDFImagesCache[i].widget == w)
return (RDFImagesCache[i].obj);
} }
return (XFE_RDFImage *) NULL;
DestroyContext();
}
void CRDFImage::CompleteFrameCallback()
{
m_bFrameLoaded = TRUE;
for (POSITION pos = resourceList.GetHeadPosition(); pos != NULL; )
{
CIconCallbackInfo* callback = (CIconCallbackInfo*)(resourceList.GetNext(pos));
if (callback->pObject)
{
callback->pObject->LoadComplete(callback->pResource);
}
}
}
CXIcon::CXIcon(CRDFImage* theImage)
{
MWContext *pContext = GetContext();
m_cxType = IconCX;
pContext->type = MWContextIcon;
m_MM = MM_TEXT;
m_hDC = 0;
m_icon = theImage;
m_image = NULL;
m_mask = NULL;
}
CXIcon::~CXIcon()
{
}
BITMAPINFO * CXIcon::NewPixmap(NI_Pixmap *pImage, BOOL isMask)
{
// remember which bitmap we have so we can get the bits later in imageComplete.
if (isMask)
m_mask = pImage;
else m_image = pImage;
return CDCCX::NewPixmap(pImage, isMask);
}
int CXIcon::DisplayPixmap(NI_Pixmap* image, NI_Pixmap* mask, int32 x, int32 y, int32 x_offset, int32 y_offset, int32 width, int32 height, int32 lScaleWidth, int32 lScaleHeight, LTRB& Rect)
{
m_image = image;
m_mask = mask;
m_icon->bmpInfo = FillBitmapInfoHeader(image);
m_icon->bits = image->bits;
if (mask)
m_icon->maskbits = mask->bits;
m_icon->CompleteFrameCallback();
return 1;
}
void CXIcon::ImageComplete(NI_Pixmap* image)
{
// Will get a call for both the mask and for the image.
if (m_image && m_mask)
{
if (m_icon->pairCount == 2)
m_icon->CompleteCallback();
else m_icon->pairCount++;
}
else
{
// We have no mask.
m_icon->CompleteCallback();
}
}
// Don't display partial images.
void CXIcon::AllConnectionsComplete(MWContext *pContext)
{
CDCCX::AllConnectionsComplete(pContext);
}
void CXIcon::NiceDestruction()
{
m_bIdleDestroy = TRUE;
FEU_RequestIdleProcessing(GetContext());
}
// ========================= CCustomImageObject Helpers =============================
CRDFImage* CCustomImageObject::LookupImage(const char* url, HT_Resource r)
{
// Find the image.
void* pData;
CRDFImage* pImage = NULL;
if (CHTFEData::m_CustomURLCache.Lookup(url, pData))
{
pImage = (CRDFImage*)pData;
// Add ourselves to the callback list if the image hasn't completely loaded.
if (!pImage->CompletelyLoaded())
{
// The image is currently loading. Register ourselves with the image so that we will get called
// when the image finishes loading.
pImage->AddListener(this, r);
}
}
else
{
// Create a new NavCenter image.
pImage = new CRDFImage(url);
pImage->AddListener(this, r);
CHTFEData::m_CustomURLCache.SetAt(url, pImage);
}
return pImage;
}
CCustomImageObject::~CCustomImageObject()
{
// The displayer of the image is being destroyed. It should be removed as a listener from all
// images.
for (POSITION pos = loadingImagesList.GetHeadPosition();
pos != NULL; )
{
// Enumerate over the list and call remove listener on each image.
CRDFImage* pImage = (CRDFImage*)loadingImagesList.GetNext(pos);
pImage->RemoveListener(this);
}
}
void CCustomImageObject::AddLoadingImage(CRDFImage* pImage)
{
// We only want to have one copy of the same image in this list.
for (POSITION pos = loadingImagesList.GetHeadPosition();
pos != NULL; )
{
// Enumerate over the list and call remove listener on each image.
CRDFImage* pNavImage = (CRDFImage*)loadingImagesList.GetNext(pos);
if (pNavImage == pImage)
return;
}
// Add the image to the list.
loadingImagesList.AddHead(pImage);
}
void CCustomImageObject::RemoveLoadingImage(CRDFImage* pImage)
{
// Should only occur once in our list. Find and remove.
POSITION pos = loadingImagesList.Find(pImage);
if (pos)
loadingImagesList.RemoveAt(pos);
} }
#endif

Просмотреть файл

@ -20,9 +20,13 @@
Created: Radha Kulkarni <radha@netscape.com>, 06-29-98 Created: Radha Kulkarni <radha@netscape.com>, 06-29-98
*/ */
#ifndef _xfe_rdfimage_h
#define _xfe_rdfimage_h
#include "libimg.h" /* Image library public API */ #include "libimg.h" /* Image library public API */
#include "xfe.h" #include "xfe.h"
#include "View.h" #include "View.h"
#include "Image.h"
extern "C" { extern "C" {
@ -31,6 +35,14 @@ void Icon_GetUrlExitRoutine(URL_Struct *pUrl, int iStatus, MWContext *pContext)
}; };
typedef struct _RDFImageList {
void * requestedObj;
class XFE_RDFImage * obj;
Widget widget;
char * imageURL;
PRBool isSpaceAvailable;
} RDFImageList;
typedef struct _callbackClientData { typedef struct _callbackClientData {
Widget widget; Widget widget;
@ -42,48 +54,53 @@ typedef struct _callbackClientData {
class XFE_RDFImage { class XFE_RDFImage : XFE_Image
{
public: public:
XFE_RDFImage(XFE_Component * frame, char * imageUrl, fe_colormap *, Widget); XFE_RDFImage(XFE_Component * frame, void * requestedObj, char * imageUrl, fe_colormap *, Widget);
~XFE_RDFImage(); ~XFE_RDFImage();
void loadImage();
Pixmap getPixmap();
Pixmap getMask();
Boolean isImageLoaded();
void setCompleteCallback(completeCallbackPtr callback, void * callbackData);
void XFE_RDFImage::RDFDisplayPixmap(IL_Pixmap * image, IL_Pixmap * mask, PRInt32 width, PRInt32 height); void setCompleteCallback(completeCallbackPtr callback, void * callbackData);
void XFE_RDFImage::RDFNewPixmap(IL_Pixmap * image, Boolean isMask); void RDFDisplayPixmap(IL_Pixmap * image, IL_Pixmap * mask, PRInt32 width, PRInt32 height);
void XFE_RDFImage::RDFImageComplete(IL_Pixmap * image); void RDFNewPixmap(IL_Pixmap * image, Boolean isMask);
void RDFImageComplete(IL_Pixmap * image);
void addListener(void * requestedObj, Widget w, char * imageURL);
PRBool isrequestorAlive(Widget w);
virtual Pixmap getPixmap();
virtual Pixmap getMask();
virtual PRInt32 getImageWidth();
virtual PRInt32 getImageHeight();
virtual void loadImage();
virtual Boolean isImageLoaded();
static class XFE_RDFImage * isImageAvailable(char * imageURL);
static void removeListener(void * obj);
static void removeListener(Widget w);
static XFE_RDFImage* getRDFImageObject(Widget);
private: private:
char * m_urlString; // Url string
MWContext * m_imageContext; // Special MWContext
fe_ContextData * fec; // FE specific data for MWContext
IL_Pixmap * m_image;
IL_Pixmap * m_mask;
static Pixmap m_badImage; // Bad image to use if the image loading fails
XFE_Component * m_frame;
Boolean badImage; // Indicates whether to use the bad bitmap
Boolean completelyLoaded; // Indicates if image is completely loaded
Boolean frameLoaded; // Indicates if frame is loaded Boolean frameLoaded; // Indicates if frame is loaded
Boolean cxtInitSucceeded; // Indicates if MWcontext is initialized successfully int pairCount; // Specifies whether pixmap and mask are ready
Boolean imageDrawn;
int pairCount; // Specifies whether both pixmap and mask are available
static int refCount; // Count of # of images loaded static int refCount; // Count of # of images loaded
static int m_numRDFImagesLoaded; // # of images in the cache
static RDFImageList * RDFImagesCache; // Images cache
static unsigned int MaxRdfImages; // Max # of images the cache can hold
static unsigned int ImageListIncrSize; // cache size increment.
static void removeListener(int);
static void imageCacheInitialize();
completeCallbackPtr completeCallback; // Callback to call after complete image has been obtained. completeCallbackPtr completeCallback; // Callback to call after complete image has been obtained.
void * callbackData; void * callbackData;
}; };
#endif /* _xfe_rdfimage_h */