#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif
#include "Ps.h"
#include "gcstruct.h"
#include "windowstr.h"
#include <X11/fonts/fntfil.h>
#include <X11/fonts/fntfilst.h>
#define GET 0
#define RESET 1
struct bm_cache_list {
struct bm_cache_list *next;
struct bm_cache_list *prev;
int height;
long id;
char *pBuffer;
};
struct bm_cache_head {
struct bm_cache_list *head;
int width;
struct bm_cache_head *next;
struct bm_cache_head *prev;
};
static struct bm_cache_head *bm_cache = NULL;
static long
PsBmUniqueId(int func)
{
static long unique_id = 0;
if(func == RESET)
{
unique_id = 0;
return 0;
}
else
return ++unique_id;
}
int
PsBmIsImageCached(
int gWidth,
int gHeight,
char *pBuffer)
{
int return_val = 0;
struct bm_cache_head *pList = bm_cache;
while(pList != NULL && !return_val)
{
if(pList->width == gWidth)
{
struct bm_cache_list *pItem = pList->head;
while(pItem != NULL)
{
if(pItem->height == gHeight)
{
int length = 4*(gWidth/32+(gWidth%32!=0))*gHeight;
if(!memcmp(pItem->pBuffer, pBuffer, sizeof(char)*length))
{
return_val = pItem->id;
break;
}
}
else if(pItem->height > gHeight)
break;
pItem = pItem->next;
}
}
else if(pList->width > gWidth)
break;
pList = pList->next;
}
return return_val;
}
int
PsBmPutImageInCache(
int gWidth,
int gHeight,
char *pBuffer)
{
int return_val = 0;
struct bm_cache_head *pList = bm_cache;
struct bm_cache_list *pNew;
int length = 4*(gWidth/32+(gWidth%32!=0))*gHeight;
if(gWidth == 1 && gHeight == 1 && pBuffer[0] == 0)
return return_val;
pNew = (struct bm_cache_list *)malloc(sizeof(struct bm_cache_list));
pNew->next = NULL;
pNew->prev = NULL;
pNew->height = gHeight;
pNew->id = PsBmUniqueId(GET);
pNew->pBuffer = (char *)malloc(sizeof(char)*length);
memcpy(pNew->pBuffer, pBuffer, length);
while(pList != NULL)
{
if(pList->width == gWidth)
{
struct bm_cache_list *pItem = pList->head;
while(pItem != NULL)
{
if(pItem->height >= gHeight)
{
pNew->next = pItem;
pNew->prev = pItem->prev;
if(pItem->prev != NULL)
pItem->prev->next = pNew;
else
pList->head = pNew;
pItem->prev = pNew;
return_val = pNew->id;
break;
}
else if(pItem->next == NULL)
{
pNew->prev = pItem;
pItem->next = pNew;
return_val = pNew->id;
break;
}
pItem = pItem->next;
}
break;
}
pList = pList->next;
}
if(pList == NULL)
{
struct bm_cache_head *pNewList;
pNewList = (struct bm_cache_head *)malloc(sizeof(struct bm_cache_head));
pNewList->next = NULL;
pNewList->prev = NULL;
pNewList->width = gWidth;
pNewList->head = pNew;
if(bm_cache == NULL)
{
bm_cache = pNewList;
return_val = pNew->id;
}
else
{
pList = bm_cache;
while(pList != NULL)
{
if(pList->width > gWidth)
{
pNewList->next = pList;
pNewList->prev = pList->prev;
if(pList->prev != NULL)
pList->prev->next = pNewList;
else
bm_cache = pNewList;
pList->prev = pNewList;
return_val = pNew->id;
break;
}
else if(pList->next == NULL)
{
pNewList->prev = pList;
pList->next = pNewList;
return_val = pNew->id;
break;
}
pList = pList->next;
}
}
}
return return_val;
}
static void
PsBmClearImageCacheItem(
struct bm_cache_list *pItem)
{
if(pItem != NULL)
{
if(pItem->pBuffer != NULL)
free(pItem->pBuffer);
pItem->pBuffer = NULL;
if(pItem->next)
PsBmClearImageCacheItem(pItem->next);
pItem->next = NULL;
free(pItem);
pItem = NULL;
}
}
static void
PsBmClearImageCacheList(
struct bm_cache_head *pList)
{
if(pList != NULL)
{
if(pList->head)
PsBmClearImageCacheItem(pList->head);
pList->head = NULL;
if(pList->next)
PsBmClearImageCacheList(pList->next);
pList->next = NULL;
free(pList);
pList = NULL;
}
}
void
PsBmClearImageCache(void)
{
PsBmClearImageCacheList(bm_cache);
bm_cache = NULL;
PsBmUniqueId(RESET);
}