1999-08-01 15:14:11 -07:00
|
|
|
#include "common.h"
|
|
|
|
#include <time.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <dlfcn.h>
|
1999-09-18 23:28:54 -07:00
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <ctype.h>
|
|
|
|
#include <errno.h>
|
1999-08-01 15:14:11 -07:00
|
|
|
#include <X11/Xlib.h>
|
|
|
|
#include "image.h"
|
|
|
|
#include "file.h"
|
1999-08-05 14:51:50 -07:00
|
|
|
#include "loaderpath.h"
|
1999-08-01 15:14:11 -07:00
|
|
|
|
|
|
|
static ImlibImage *images = NULL;
|
|
|
|
static ImlibImagePixmap *pixmaps = NULL;
|
|
|
|
static ImlibLoader *loaders = NULL;
|
|
|
|
static int cache_size = 4096 * 1024;
|
|
|
|
|
|
|
|
void
|
1999-08-04 16:36:07 -07:00
|
|
|
__imlib_SetCacheSize(int size)
|
1999-08-01 15:14:11 -07:00
|
|
|
{
|
|
|
|
cache_size = size;
|
1999-08-04 16:36:07 -07:00
|
|
|
__imlib_CleanupImageCache();
|
|
|
|
__imlib_CleanupImagePixmapCache();
|
1999-08-01 15:14:11 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
1999-08-04 16:36:07 -07:00
|
|
|
__imlib_GetCacheSize(void)
|
1999-08-01 15:14:11 -07:00
|
|
|
{
|
|
|
|
return cache_size;
|
|
|
|
}
|
|
|
|
|
|
|
|
ImlibImage *
|
1999-08-04 16:36:07 -07:00
|
|
|
__imlib_ProduceImage(void)
|
1999-08-01 15:14:11 -07:00
|
|
|
{
|
|
|
|
ImlibImage *im;
|
|
|
|
|
|
|
|
im = malloc(sizeof(ImlibImage));
|
1999-08-04 16:36:07 -07:00
|
|
|
memset(im, 0, sizeof(ImlibImage));
|
1999-08-01 15:14:11 -07:00
|
|
|
im->data = NULL;
|
|
|
|
im->file = NULL;
|
|
|
|
im->flags = F_NONE;
|
|
|
|
im->loader = NULL;
|
|
|
|
im->next = NULL;
|
|
|
|
return im;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
1999-08-04 16:36:07 -07:00
|
|
|
__imlib_ConsumeImage(ImlibImage *im)
|
1999-08-01 15:14:11 -07:00
|
|
|
{
|
|
|
|
if (im->file)
|
|
|
|
free(im->file);
|
1999-09-01 10:36:17 -07:00
|
|
|
if ((IMAGE_FREE_DATA(im)) && (im->data))
|
1999-08-01 15:14:11 -07:00
|
|
|
free(im->data);
|
|
|
|
if (im->format)
|
|
|
|
free(im->format);
|
|
|
|
free(im);
|
|
|
|
}
|
|
|
|
|
|
|
|
ImlibImage *
|
1999-08-04 16:36:07 -07:00
|
|
|
__imlib_FindCachedImage(char *file)
|
1999-08-01 15:14:11 -07:00
|
|
|
{
|
|
|
|
ImlibImage *im, *previous_im;
|
|
|
|
|
|
|
|
im = images;
|
|
|
|
previous_im = NULL;
|
|
|
|
/* go through the images list */
|
|
|
|
while (im)
|
|
|
|
{
|
1999-08-04 16:36:07 -07:00
|
|
|
/* if the filenames match and it's valid */
|
|
|
|
if ((!strcmp(file, im->file)) && (IMAGE_IS_VALID(im)))
|
1999-08-01 15:14:11 -07:00
|
|
|
{
|
|
|
|
/* move the image to the head of the pixmap list */
|
|
|
|
if (previous_im)
|
|
|
|
{
|
|
|
|
previous_im->next = im->next;
|
|
|
|
im->next = images;
|
|
|
|
images = im;
|
|
|
|
}
|
|
|
|
/* return it */
|
|
|
|
return im;
|
|
|
|
}
|
|
|
|
previous_im = im;
|
|
|
|
im = im->next;
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
1999-08-04 16:36:07 -07:00
|
|
|
__imlib_AddImageToCache(ImlibImage *im)
|
1999-08-01 15:14:11 -07:00
|
|
|
{
|
|
|
|
im->next = images;
|
|
|
|
images = im;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
1999-08-04 16:36:07 -07:00
|
|
|
__imlib_RemoveImageFromCache(ImlibImage *im)
|
1999-08-01 15:14:11 -07:00
|
|
|
{
|
|
|
|
ImlibImage *current_im, *previous_im;
|
|
|
|
|
|
|
|
current_im = images;
|
|
|
|
previous_im = NULL;
|
|
|
|
while (current_im)
|
|
|
|
{
|
|
|
|
if (im == current_im)
|
|
|
|
{
|
|
|
|
if (previous_im)
|
|
|
|
previous_im->next = im->next;
|
|
|
|
else
|
|
|
|
images = im->next;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
current_im = current_im->next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
1999-08-04 16:36:07 -07:00
|
|
|
__imlib_CurrentCacheSize(void)
|
1999-08-01 15:14:11 -07:00
|
|
|
{
|
|
|
|
ImlibImage *im;
|
|
|
|
ImlibImagePixmap *ip;
|
|
|
|
int current_cache = 0;
|
|
|
|
|
|
|
|
im = images;
|
|
|
|
while(im)
|
|
|
|
{
|
|
|
|
if (im->references == 0)
|
|
|
|
{
|
|
|
|
if (!(IMAGE_IS_VALID(im)))
|
|
|
|
{
|
1999-08-04 16:36:07 -07:00
|
|
|
__imlib_RemoveImageFromCache(im);
|
|
|
|
__imlib_ConsumeImage(im);
|
1999-08-01 15:14:11 -07:00
|
|
|
}
|
|
|
|
else
|
|
|
|
current_cache += im->w * im->h * sizeof(DATA32);
|
|
|
|
}
|
|
|
|
im = im->next;
|
|
|
|
}
|
|
|
|
ip = pixmaps;
|
|
|
|
while(ip)
|
|
|
|
{
|
|
|
|
if (ip->references == 0)
|
|
|
|
{
|
|
|
|
if (!(IMAGE_IS_VALID(ip->image)))
|
|
|
|
{
|
1999-08-04 16:36:07 -07:00
|
|
|
__imlib_RemoveImagePixmapFromCache(ip);
|
|
|
|
__imlib_ConsumeImagePixmap(ip);
|
1999-08-01 15:14:11 -07:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (ip->pixmap)
|
|
|
|
{
|
|
|
|
if (ip->depth < 8)
|
|
|
|
current_cache += ip->w * ip->h * (ip->depth / 8);
|
|
|
|
else if (ip->depth == 8)
|
|
|
|
current_cache += ip->w * ip->h;
|
|
|
|
else if (ip->depth <= 16)
|
|
|
|
current_cache += ip->w * ip->h * 2;
|
|
|
|
else if (ip->depth <= 32)
|
|
|
|
current_cache += ip->w * ip->h * 4;
|
|
|
|
}
|
|
|
|
if (ip->mask)
|
|
|
|
current_cache += ip->w * ip->h / 8;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ip = ip->next;
|
|
|
|
}
|
1999-08-23 09:55:16 -07:00
|
|
|
return current_cache;
|
1999-08-01 15:14:11 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
1999-08-04 16:36:07 -07:00
|
|
|
__imlib_CleanupImageCache(void)
|
1999-08-01 15:14:11 -07:00
|
|
|
{
|
|
|
|
ImlibImage *im, *im_last;
|
|
|
|
int current_cache;
|
1999-09-12 18:56:57 -07:00
|
|
|
char operation = 0;
|
1999-08-01 15:14:11 -07:00
|
|
|
|
1999-08-04 16:36:07 -07:00
|
|
|
current_cache = __imlib_CurrentCacheSize();
|
1999-08-04 22:27:39 -07:00
|
|
|
im_last = NULL;
|
|
|
|
im = images;
|
|
|
|
while(im)
|
|
|
|
{
|
|
|
|
im_last = im;
|
|
|
|
im = im->next;
|
|
|
|
if ((im_last->references <= 0) &&
|
1999-09-12 18:56:57 -07:00
|
|
|
(!(IMAGE_IS_VALID(im_last))))
|
1999-08-04 22:27:39 -07:00
|
|
|
{
|
|
|
|
__imlib_RemoveImageFromCache(im_last);
|
|
|
|
__imlib_ConsumeImage(im_last);
|
|
|
|
}
|
|
|
|
}
|
1999-08-05 19:08:36 -07:00
|
|
|
while ((current_cache > cache_size) || (operation))
|
1999-08-01 15:14:11 -07:00
|
|
|
{
|
|
|
|
im_last = NULL;
|
|
|
|
operation = 0;
|
|
|
|
im = images;
|
|
|
|
while(im)
|
|
|
|
{
|
|
|
|
if (im->references <= 0)
|
|
|
|
im_last = im;
|
|
|
|
im = im->next;
|
|
|
|
}
|
|
|
|
if (im_last)
|
|
|
|
{
|
1999-08-04 16:36:07 -07:00
|
|
|
__imlib_RemoveImageFromCache(im_last);
|
|
|
|
__imlib_ConsumeImage(im_last);
|
1999-08-01 15:14:11 -07:00
|
|
|
operation = 1;
|
|
|
|
}
|
1999-08-04 16:36:07 -07:00
|
|
|
current_cache = __imlib_CurrentCacheSize();
|
1999-08-01 15:14:11 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ImlibImagePixmap *
|
1999-08-04 16:36:07 -07:00
|
|
|
__imlib_ProduceImagePixmap(void)
|
1999-08-01 15:14:11 -07:00
|
|
|
{
|
|
|
|
ImlibImagePixmap *ip;
|
|
|
|
|
|
|
|
ip = malloc(sizeof(ImlibImagePixmap));
|
1999-08-04 16:36:07 -07:00
|
|
|
memset(ip, 0, sizeof(ImlibImagePixmap));
|
1999-08-01 15:14:11 -07:00
|
|
|
ip->display = NULL;
|
|
|
|
ip->visual = NULL;
|
|
|
|
ip->image = NULL;
|
|
|
|
ip->next = NULL;
|
|
|
|
return ip;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
1999-08-04 16:36:07 -07:00
|
|
|
__imlib_ConsumeImagePixmap(ImlibImagePixmap *ip)
|
1999-08-01 15:14:11 -07:00
|
|
|
{
|
|
|
|
if (ip->pixmap)
|
|
|
|
XFreePixmap(ip->display, ip->pixmap);
|
|
|
|
if (ip->mask)
|
|
|
|
XFreePixmap(ip->display, ip->mask);
|
|
|
|
free(ip);
|
|
|
|
}
|
|
|
|
|
|
|
|
ImlibImagePixmap *
|
1999-08-04 16:36:07 -07:00
|
|
|
__imlib_FindCachedImagePixmap(ImlibImage *im, int w, int h, Display *d, Visual *v,
|
|
|
|
int depth, int sx, int sy, int sw, int sh, Colormap cm,
|
1999-08-28 11:18:29 -07:00
|
|
|
char aa, char hiq, char dmask,
|
|
|
|
long long modification_count)
|
1999-08-01 15:14:11 -07:00
|
|
|
{
|
|
|
|
ImlibImagePixmap *ip, *previous_ip;
|
|
|
|
|
|
|
|
ip = pixmaps;
|
|
|
|
previous_ip = NULL;
|
|
|
|
/* go through the pixmap list */
|
|
|
|
while (ip)
|
|
|
|
{
|
|
|
|
/* if all the pixmap attributes match */
|
|
|
|
if ((ip->w == w) && (ip->h == h) && (ip->depth == depth) &&
|
1999-08-04 16:36:07 -07:00
|
|
|
(!ip->dirty) &&
|
1999-08-01 15:14:11 -07:00
|
|
|
(ip->visual == v) && (ip->display == d) &&
|
1999-08-04 16:36:07 -07:00
|
|
|
(ip->source_x == sx) && (ip->source_x == sy) &&
|
|
|
|
(ip->source_w == sw) && (ip->source_h == sh) &&
|
|
|
|
(ip->colormap == cm) && (ip->antialias == aa) &&
|
1999-08-28 11:18:29 -07:00
|
|
|
(ip->modification_count == modification_count) &&
|
1999-08-04 16:36:07 -07:00
|
|
|
(ip->dither_mask == dmask) &&
|
|
|
|
(ip->border.left == im->border.left) &&
|
|
|
|
(ip->border.right == im->border.right) &&
|
|
|
|
(ip->border.top == im->border.top) &&
|
|
|
|
(ip->border.bottom == im->border.bottom)
|
|
|
|
)
|
1999-08-01 15:14:11 -07:00
|
|
|
{
|
|
|
|
/* move the pixmap to the head of the pixmap list */
|
|
|
|
if (previous_ip)
|
|
|
|
{
|
|
|
|
previous_ip->next = ip->next;
|
|
|
|
ip->next = pixmaps;
|
|
|
|
pixmaps = ip;
|
|
|
|
}
|
|
|
|
/* return it */
|
|
|
|
return ip;
|
|
|
|
}
|
|
|
|
previous_ip = ip;
|
|
|
|
ip = ip->next;
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
1999-08-04 16:36:07 -07:00
|
|
|
__imlib_AddImagePixmapToCache(ImlibImagePixmap *ip)
|
1999-08-01 15:14:11 -07:00
|
|
|
{
|
|
|
|
ip->next = pixmaps;
|
|
|
|
pixmaps = ip;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
1999-08-04 16:36:07 -07:00
|
|
|
__imlib_RemoveImagePixmapFromCache(ImlibImagePixmap *ip)
|
1999-08-01 15:14:11 -07:00
|
|
|
{
|
|
|
|
ImlibImagePixmap *current_ip, *previous_ip;
|
|
|
|
|
|
|
|
current_ip = pixmaps;
|
|
|
|
previous_ip = NULL;
|
|
|
|
while (current_ip)
|
|
|
|
{
|
|
|
|
if (ip == current_ip)
|
|
|
|
{
|
|
|
|
if (previous_ip)
|
|
|
|
previous_ip->next = ip->next;
|
|
|
|
else
|
|
|
|
pixmaps = ip->next;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
current_ip = current_ip->next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
1999-08-23 09:55:16 -07:00
|
|
|
__imlib_CleanupImagePixmapCache(void)
|
1999-08-01 15:14:11 -07:00
|
|
|
{
|
|
|
|
ImlibImagePixmap *ip, *ip_last;
|
|
|
|
int current_cache;
|
1999-09-12 18:56:57 -07:00
|
|
|
char operation = 0;
|
1999-08-04 16:36:07 -07:00
|
|
|
|
|
|
|
current_cache = __imlib_CurrentCacheSize();
|
1999-08-04 22:27:39 -07:00
|
|
|
ip_last = NULL;
|
|
|
|
ip = pixmaps;
|
|
|
|
while(ip)
|
|
|
|
{
|
|
|
|
ip_last = ip;
|
|
|
|
ip = ip->next;
|
|
|
|
if ((ip_last->references <= 0) &&
|
|
|
|
(ip_last->dirty))
|
|
|
|
{
|
|
|
|
__imlib_RemoveImagePixmapFromCache(ip_last);
|
|
|
|
__imlib_ConsumeImagePixmap(ip_last);
|
|
|
|
}
|
|
|
|
}
|
1999-08-05 19:08:36 -07:00
|
|
|
while ((current_cache > cache_size) || (operation))
|
1999-08-01 15:14:11 -07:00
|
|
|
{
|
|
|
|
ip_last = NULL;
|
|
|
|
operation = 0;
|
|
|
|
ip = pixmaps;
|
|
|
|
while(ip)
|
|
|
|
{
|
|
|
|
if (ip->references <= 0)
|
|
|
|
ip_last = ip;
|
|
|
|
ip = ip->next;
|
|
|
|
}
|
|
|
|
if (ip_last)
|
|
|
|
{
|
1999-08-04 16:36:07 -07:00
|
|
|
__imlib_RemoveImagePixmapFromCache(ip_last);
|
|
|
|
__imlib_ConsumeImagePixmap(ip_last);
|
1999-08-01 15:14:11 -07:00
|
|
|
operation = 1;
|
|
|
|
}
|
1999-08-04 16:36:07 -07:00
|
|
|
current_cache = __imlib_CurrentCacheSize();
|
1999-08-01 15:14:11 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1999-08-05 14:51:50 -07:00
|
|
|
#define LOADERS_UNINITIALISED -4444
|
|
|
|
|
|
|
|
static void
|
|
|
|
LTDL_Init(void)
|
|
|
|
{
|
|
|
|
static int errors = LOADERS_UNINITIALISED;
|
|
|
|
|
|
|
|
/* Do this only once! */
|
1999-08-23 09:55:16 -07:00
|
|
|
if ((errors = LOADERS_UNINITIALISED))
|
1999-08-05 14:51:50 -07:00
|
|
|
{
|
|
|
|
errors = lt_dlinit();
|
|
|
|
|
|
|
|
/* Initialise libltdl's memory management. */
|
|
|
|
lt_dlmalloc = malloc;
|
|
|
|
lt_dlfree = free;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Failing ltdl initialisation makes continuing somewhat futile... */
|
|
|
|
if (errors != 0)
|
|
|
|
{
|
|
|
|
const char *dlerror = lt_dlerror();
|
|
|
|
fprintf(stderr, "ERROR: failed to initialise ltdl: %s\n", dlerror);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1999-08-01 15:14:11 -07:00
|
|
|
ImlibLoader *
|
1999-08-04 16:36:07 -07:00
|
|
|
__imlib_ProduceLoader(char *file)
|
1999-08-01 15:14:11 -07:00
|
|
|
{
|
|
|
|
ImlibLoader *l;
|
|
|
|
void (*l_formats)(ImlibLoader *l) ;
|
|
|
|
|
1999-08-05 14:51:50 -07:00
|
|
|
LTDL_Init();
|
|
|
|
|
1999-08-01 15:14:11 -07:00
|
|
|
l = malloc(sizeof(ImlibLoader));
|
|
|
|
l->num_formats = 0;
|
|
|
|
l->formats = NULL;
|
1999-08-05 14:51:50 -07:00
|
|
|
l->handle = lt_dlopenext(file);
|
1999-08-01 15:14:11 -07:00
|
|
|
if (!l->handle)
|
|
|
|
{
|
|
|
|
free(l);
|
|
|
|
return NULL;
|
|
|
|
}
|
1999-08-05 14:51:50 -07:00
|
|
|
l->load = lt_dlsym(l->handle, "load");
|
|
|
|
l->save = lt_dlsym(l->handle, "save");
|
|
|
|
l_formats = lt_dlsym(l->handle, "formats");
|
1999-08-01 15:14:11 -07:00
|
|
|
if ((!(l->load)) || (!(l->save)) || (!(l_formats)))
|
|
|
|
{
|
1999-08-05 14:51:50 -07:00
|
|
|
lt_dlclose(l->handle);
|
1999-08-01 15:14:11 -07:00
|
|
|
free(l);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
l_formats(l);
|
|
|
|
l->file = strdup(file);
|
|
|
|
l->next = NULL;
|
|
|
|
return l;
|
|
|
|
}
|
|
|
|
|
|
|
|
char **
|
1999-08-04 16:36:07 -07:00
|
|
|
__imlib_ListLoaders(int *num_ret)
|
1999-08-01 15:14:11 -07:00
|
|
|
{
|
|
|
|
char **list = NULL, **l, s[4096], *home;
|
|
|
|
int num, i, pi = 0;
|
|
|
|
|
|
|
|
*num_ret = 0;
|
1999-08-04 16:36:07 -07:00
|
|
|
home = __imlib_FileHomeDir(getuid());
|
1999-08-05 14:51:50 -07:00
|
|
|
sprintf(s, "%s/" USER_LOADERS_PATH "/image", home);
|
1999-08-04 16:36:07 -07:00
|
|
|
l = __imlib_FileDir(s, &num);
|
1999-08-01 15:14:11 -07:00
|
|
|
if (num > 0)
|
|
|
|
{
|
|
|
|
*num_ret += num;
|
|
|
|
list = malloc(sizeof(char *) * *num_ret);
|
|
|
|
for (i = 0; i < num; i++)
|
|
|
|
{
|
1999-08-05 14:51:50 -07:00
|
|
|
sprintf(s, "%s/" USER_LOADERS_PATH "/image/%s", home, l[i]);
|
1999-08-01 15:14:11 -07:00
|
|
|
list[i] = strdup(s);
|
|
|
|
}
|
|
|
|
pi = i;
|
1999-08-04 16:36:07 -07:00
|
|
|
__imlib_FileFreeDirList(l, num);
|
1999-08-01 15:14:11 -07:00
|
|
|
}
|
1999-08-05 14:51:50 -07:00
|
|
|
sprintf(s, SYS_LOADERS_PATH "/image");
|
1999-08-04 16:36:07 -07:00
|
|
|
l = __imlib_FileDir(s, &num);
|
1999-08-01 15:14:11 -07:00
|
|
|
if (num > 0)
|
|
|
|
{
|
|
|
|
*num_ret += num;
|
|
|
|
list = realloc(list, sizeof(char *) * *num_ret);
|
|
|
|
for (i = 0; i < num; i++)
|
|
|
|
{
|
1999-08-05 14:51:50 -07:00
|
|
|
sprintf(s, SYS_LOADERS_PATH "/image/%s", l[i]);
|
1999-08-01 15:14:11 -07:00
|
|
|
list[pi + i] = strdup(s);
|
|
|
|
}
|
1999-08-04 16:36:07 -07:00
|
|
|
__imlib_FileFreeDirList(l, num);
|
1999-08-01 15:14:11 -07:00
|
|
|
free(home);
|
|
|
|
}
|
|
|
|
return list;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
1999-08-04 16:36:07 -07:00
|
|
|
__imlib_ConsumeLoader(ImlibLoader *l)
|
1999-08-01 15:14:11 -07:00
|
|
|
{
|
|
|
|
if (l->file)
|
|
|
|
free(l->file);
|
|
|
|
if (l->handle)
|
|
|
|
dlclose(l->handle);
|
|
|
|
if (l->formats)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < l->num_formats; i++)
|
|
|
|
free(l->formats[i]);
|
|
|
|
free(l->formats);
|
|
|
|
}
|
|
|
|
free(l);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
1999-08-04 16:36:07 -07:00
|
|
|
__imlib_RescanLoaders(void)
|
1999-08-01 15:14:11 -07:00
|
|
|
{
|
|
|
|
static time_t last_scan_time = 0;
|
|
|
|
static time_t last_modified_home_time = 0;
|
|
|
|
static time_t last_modified_system_time = 0;
|
|
|
|
time_t current_time;
|
|
|
|
char s[4096], *home;
|
|
|
|
char do_reload = 0;
|
|
|
|
|
|
|
|
/* dont stat the dir and rescan if we checked in the last 5 seconds */
|
|
|
|
current_time = time(NULL);
|
|
|
|
if ((current_time - last_scan_time) < 5)
|
|
|
|
return;
|
|
|
|
/* ok - was the system loaders dir contents modified ? */
|
|
|
|
last_scan_time = current_time;
|
1999-09-18 00:50:37 -07:00
|
|
|
if (__imlib_FileIsDir(SYS_LOADERS_PATH "/image/"))
|
1999-08-01 15:14:11 -07:00
|
|
|
{
|
1999-09-18 00:50:37 -07:00
|
|
|
current_time = __imlib_FileModDate(SYS_LOADERS_PATH "/image/");
|
1999-08-01 15:14:11 -07:00
|
|
|
if (current_time > last_modified_system_time)
|
|
|
|
{
|
|
|
|
/* yup - set the "do_reload" flag */
|
|
|
|
do_reload = 1;
|
|
|
|
last_modified_system_time = current_time;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* ok - was the users own loaders dir contents modified ? */
|
1999-08-04 16:36:07 -07:00
|
|
|
home = __imlib_FileHomeDir(getuid());
|
1999-09-18 00:50:37 -07:00
|
|
|
sprintf(s, "%s/" USER_LOADERS_PATH "/image/", home);
|
1999-08-01 15:14:11 -07:00
|
|
|
free(home);
|
1999-08-04 16:36:07 -07:00
|
|
|
if (__imlib_FileIsDir(s))
|
1999-08-01 15:14:11 -07:00
|
|
|
{
|
1999-08-04 16:36:07 -07:00
|
|
|
current_time = __imlib_FileModDate(s);
|
1999-08-01 15:14:11 -07:00
|
|
|
if (current_time > last_modified_home_time)
|
|
|
|
{
|
|
|
|
/* yup - set the "do_reload" flag */
|
|
|
|
do_reload = 1;
|
|
|
|
last_modified_home_time = current_time;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* if we dont ned to reload the loaders - get out now */
|
|
|
|
if (!do_reload)
|
|
|
|
return;
|
1999-08-04 16:36:07 -07:00
|
|
|
__imlib_RemoveAllLoaders();
|
|
|
|
__imlib_LoadAllLoaders();
|
1999-08-01 15:14:11 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
1999-08-04 16:36:07 -07:00
|
|
|
__imlib_RemoveAllLoaders(void)
|
1999-08-01 15:14:11 -07:00
|
|
|
{
|
|
|
|
ImlibLoader *l, *il;
|
|
|
|
|
|
|
|
l = loaders;
|
|
|
|
while(l)
|
|
|
|
{
|
|
|
|
il = l;
|
|
|
|
l = l->next;
|
1999-08-04 16:36:07 -07:00
|
|
|
__imlib_ConsumeLoader(il);
|
1999-08-01 15:14:11 -07:00
|
|
|
}
|
|
|
|
loaders = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
1999-08-04 16:36:07 -07:00
|
|
|
__imlib_LoadAllLoaders(void)
|
1999-08-01 15:14:11 -07:00
|
|
|
{
|
|
|
|
int i, num;
|
|
|
|
char **list;
|
|
|
|
|
1999-08-04 16:36:07 -07:00
|
|
|
list = __imlib_ListLoaders(&num);
|
1999-08-01 15:14:11 -07:00
|
|
|
if (!list)
|
|
|
|
return;
|
|
|
|
|
|
|
|
for (i = num - 1; i >= 0; i--)
|
|
|
|
{
|
|
|
|
ImlibLoader *l;
|
|
|
|
|
1999-08-04 16:36:07 -07:00
|
|
|
l = __imlib_ProduceLoader(list[i]);
|
1999-08-01 15:14:11 -07:00
|
|
|
if (l)
|
|
|
|
{
|
|
|
|
l->next = loaders;
|
|
|
|
loaders = l;
|
|
|
|
}
|
|
|
|
if (list[i])
|
|
|
|
free(list[i]);
|
|
|
|
}
|
|
|
|
free(list);
|
|
|
|
}
|
|
|
|
|
|
|
|
ImlibLoader *
|
1999-08-04 16:36:07 -07:00
|
|
|
__imlib_FindBestLoaderForFile(char *file)
|
1999-08-01 15:14:11 -07:00
|
|
|
{
|
|
|
|
char *extension, *lower;
|
|
|
|
ImlibLoader *l = NULL;
|
|
|
|
|
|
|
|
/* use the file extension for a "best guess" as to what loader to try */
|
|
|
|
/* first at any rate */
|
1999-08-04 16:36:07 -07:00
|
|
|
extension = strdup(__imlib_FileExtension(file));
|
1999-08-01 15:14:11 -07:00
|
|
|
/* change the extensiont o all lwoer case as all "types" are listed as */
|
|
|
|
/* lower case strings fromt he loader that represent all the possible */
|
|
|
|
/* extensions that file format could have */
|
|
|
|
lower = extension;
|
|
|
|
while (*lower)
|
|
|
|
{
|
|
|
|
*lower = tolower(*lower);
|
|
|
|
lower++;
|
|
|
|
}
|
|
|
|
/* go through the loaders - first loader that claims to handle that */
|
|
|
|
/* image type (extension wise) wins as a first guess to use - NOTE */
|
|
|
|
/* this is an OPTIMISATION - it is possible the file has no extension */
|
|
|
|
/* or has an unrecognised one but still is loadable by a loader. */
|
|
|
|
/* if thkis initial loader failes to load the load mechanism will */
|
|
|
|
/* systematically go from most recently used to least recently used */
|
|
|
|
/* loader until one succeeds - or none are left and all have failed */
|
|
|
|
/* and only if all fail does the laod fail. the lao9der that does */
|
|
|
|
/* succeed gets it way tot he head of the list so it's going */
|
|
|
|
/* to be used first next time in this search mechanims - this */
|
|
|
|
/* assumes you tend to laod a few image types and ones generally */
|
|
|
|
/* of the same format */
|
|
|
|
l = loaders;
|
|
|
|
while (l)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < l->num_formats; i++)
|
|
|
|
{
|
|
|
|
if (!strcmp(l->formats[i], extension))
|
|
|
|
{
|
|
|
|
free(extension);
|
|
|
|
return l;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
l = l->next;
|
|
|
|
}
|
|
|
|
free(extension);
|
|
|
|
return l;
|
|
|
|
}
|
|
|
|
|
1999-08-05 19:08:36 -07:00
|
|
|
void
|
|
|
|
__imlib_SetImageAlphaFlag(ImlibImage *im, char alpha)
|
|
|
|
{
|
|
|
|
if (alpha)
|
|
|
|
SET_FLAG(im->flags, F_HAS_ALPHA);
|
|
|
|
else
|
|
|
|
UNSET_FLAG(im->flags, F_HAS_ALPHA);
|
|
|
|
}
|
|
|
|
|
|
|
|
ImlibImage *
|
|
|
|
__imlib_CreateImage(int w, int h, DATA32 *data)
|
|
|
|
{
|
|
|
|
ImlibImage *im;
|
|
|
|
|
|
|
|
im = __imlib_ProduceImage();
|
|
|
|
im->w = w;
|
|
|
|
im->h = h;
|
|
|
|
im->data = data;
|
|
|
|
im->references = 1;
|
|
|
|
SET_FLAG(im->flags, F_UNCACHEABLE);
|
1999-08-23 09:55:16 -07:00
|
|
|
return im;
|
1999-08-05 19:08:36 -07:00
|
|
|
}
|
|
|
|
|
1999-08-01 15:14:11 -07:00
|
|
|
ImlibImage *
|
1999-08-04 16:36:07 -07:00
|
|
|
__imlib_LoadImage(char *file,
|
|
|
|
void (*progress)(ImlibImage *im, char percent,
|
|
|
|
int update_x, int update_y,
|
|
|
|
int update_w, int update_h),
|
1999-09-18 23:28:54 -07:00
|
|
|
char progress_granularity, char immediate_load, char dont_cache,
|
|
|
|
ImlibLoadError *er)
|
1999-08-01 15:14:11 -07:00
|
|
|
{
|
|
|
|
ImlibImage *im;
|
|
|
|
ImlibLoader *best_loader;
|
|
|
|
|
|
|
|
/* see if we alreayd have the image cached */
|
1999-08-04 16:36:07 -07:00
|
|
|
im = __imlib_FindCachedImage(file);
|
1999-08-01 15:14:11 -07:00
|
|
|
/* if we found a cached image and we shoudl always check that it is */
|
|
|
|
/* accurate to the disk conents if they changed since we last loaded */
|
|
|
|
/* and that it is still a valid image */
|
1999-09-12 18:56:57 -07:00
|
|
|
if ((im) && (IMAGE_IS_VALID(im)))
|
1999-08-01 15:14:11 -07:00
|
|
|
{
|
1999-09-12 18:56:57 -07:00
|
|
|
if (IMAGE_ALWAYS_CHECK_DISK(im))
|
1999-08-01 15:14:11 -07:00
|
|
|
{
|
1999-09-12 18:56:57 -07:00
|
|
|
time_t current_modified_time;
|
|
|
|
|
|
|
|
current_modified_time = __imlib_FileModDate(file);
|
|
|
|
/* if the file on disk is newer than the cached one */
|
|
|
|
if (current_modified_time > im->moddate)
|
|
|
|
{
|
|
|
|
/* invalidate image */
|
|
|
|
SET_FLAG(im->flags, F_INVALID);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* image is ok to re-use - program is just being stupid loading */
|
|
|
|
/* the same data twice */
|
|
|
|
im->references++;
|
|
|
|
return im;
|
|
|
|
}
|
1999-08-01 15:14:11 -07:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
im->references++;
|
|
|
|
return im;
|
1999-09-12 18:56:57 -07:00
|
|
|
}
|
1999-08-01 15:14:11 -07:00
|
|
|
}
|
|
|
|
/* either image in cache is invalid or we dont even have it in cache */
|
|
|
|
/* so produce a new one and load an image into that */
|
1999-08-04 16:36:07 -07:00
|
|
|
im = __imlib_ProduceImage();
|
1999-08-01 15:14:11 -07:00
|
|
|
im->file = strdup(file);
|
1999-08-04 16:36:07 -07:00
|
|
|
im->moddate = __imlib_FileModDate(file);
|
1999-08-01 15:14:11 -07:00
|
|
|
/* ok - just check all our loaders are up to date */
|
1999-08-04 16:36:07 -07:00
|
|
|
__imlib_RescanLoaders();
|
1999-08-01 15:14:11 -07:00
|
|
|
/* take a guess by extension on the best loader to use */
|
1999-08-04 16:36:07 -07:00
|
|
|
best_loader = __imlib_FindBestLoaderForFile(file);
|
1999-09-18 23:28:54 -07:00
|
|
|
errno = 0;
|
1999-08-01 15:14:11 -07:00
|
|
|
if (best_loader)
|
1999-08-02 22:15:34 -07:00
|
|
|
best_loader->load(im, progress, progress_granularity, immediate_load);
|
1999-09-18 23:28:54 -07:00
|
|
|
if (er)
|
|
|
|
{
|
|
|
|
*er = LOAD_ERROR_NONE;
|
|
|
|
if (errno != 0)
|
|
|
|
{
|
|
|
|
*er = LOAD_ERROR_UNKNOWN;
|
|
|
|
if (errno == EEXIST)
|
|
|
|
*er = LOAD_ERROR_FILE_DOES_NOT_EXIST;
|
|
|
|
else if (errno == EISDIR)
|
|
|
|
*er = LOAD_ERROR_FILE_IS_DIRECTORY;
|
|
|
|
else if (errno == EISDIR)
|
|
|
|
*er = LOAD_ERROR_FILE_IS_DIRECTORY;
|
|
|
|
else if (errno == EACCES)
|
|
|
|
*er = LOAD_ERROR_PERMISSION_DENIED_TO_READ;
|
|
|
|
else if (errno == ENAMETOOLONG)
|
|
|
|
*er = LOAD_ERROR_PATH_TOO_LONG;
|
|
|
|
else if (errno == ENOENT)
|
|
|
|
*er = LOAD_ERROR_PATH_COMPONENT_NON_EXISTANT;
|
|
|
|
else if (errno == ENOTDIR)
|
|
|
|
*er = LOAD_ERROR_PATH_COMPONENT_NOT_DIRECTORY;
|
|
|
|
else if (errno == EFAULT)
|
|
|
|
*er = LOAD_ERROR_PATH_POINTS_OUTSIDE_ADDRESS_SPACE;
|
|
|
|
else if (errno == ELOOP)
|
|
|
|
*er = LOAD_ERROR_TOO_MANY_SYMBOLIC_LINKS;
|
|
|
|
else if (errno == ENOMEM)
|
|
|
|
*er = LOAD_ERROR_OUT_OF_MEMORY;
|
|
|
|
else if (errno == EMFILE)
|
|
|
|
*er = LOAD_ERROR_OUT_OF_FILE_DESCRIPTORS;
|
|
|
|
__imlib_ConsumeImage(im);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
errno = 0;
|
|
|
|
}
|
1999-08-01 15:14:11 -07:00
|
|
|
/* width is still 0 - the laoder didnt manage to do anything */
|
|
|
|
if (im->w == 0)
|
|
|
|
{
|
|
|
|
ImlibLoader *l, *previous_l = NULL;
|
|
|
|
l = loaders;
|
|
|
|
/* run through all loaders and try load until one succeeds */
|
|
|
|
while ((l) && (im->w == 0))
|
|
|
|
{
|
|
|
|
/* if its not the best loader that alreayd failed - try load */
|
|
|
|
if (l != best_loader)
|
1999-08-02 22:15:34 -07:00
|
|
|
l->load(im, progress, progress_granularity, immediate_load);
|
1999-08-01 15:14:11 -07:00
|
|
|
/* if it failed - advance */
|
|
|
|
if (im->w == 0)
|
|
|
|
{
|
1999-09-18 23:28:54 -07:00
|
|
|
if (er)
|
|
|
|
{
|
|
|
|
*er = LOAD_ERROR_NONE;
|
|
|
|
if (errno != 0)
|
|
|
|
{
|
|
|
|
*er = LOAD_ERROR_UNKNOWN;
|
|
|
|
if (errno == EEXIST)
|
|
|
|
*er = LOAD_ERROR_FILE_DOES_NOT_EXIST;
|
|
|
|
else if (errno == EISDIR)
|
|
|
|
*er = LOAD_ERROR_FILE_IS_DIRECTORY;
|
|
|
|
else if (errno == EISDIR)
|
|
|
|
*er = LOAD_ERROR_FILE_IS_DIRECTORY;
|
|
|
|
else if (errno == EACCES)
|
|
|
|
*er = LOAD_ERROR_PERMISSION_DENIED_TO_READ;
|
|
|
|
else if (errno == ENAMETOOLONG)
|
|
|
|
*er = LOAD_ERROR_PATH_TOO_LONG;
|
|
|
|
else if (errno == ENOENT)
|
|
|
|
*er = LOAD_ERROR_PATH_COMPONENT_NON_EXISTANT;
|
|
|
|
else if (errno == ENOTDIR)
|
|
|
|
*er = LOAD_ERROR_PATH_COMPONENT_NOT_DIRECTORY;
|
|
|
|
else if (errno == EFAULT)
|
|
|
|
*er = LOAD_ERROR_PATH_POINTS_OUTSIDE_ADDRESS_SPACE;
|
|
|
|
else if (errno == ELOOP)
|
|
|
|
*er = LOAD_ERROR_TOO_MANY_SYMBOLIC_LINKS;
|
|
|
|
else if (errno == ENOMEM)
|
|
|
|
*er = LOAD_ERROR_OUT_OF_MEMORY;
|
|
|
|
else if (errno == EMFILE)
|
|
|
|
*er = LOAD_ERROR_OUT_OF_FILE_DESCRIPTORS;
|
|
|
|
__imlib_ConsumeImage(im);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
errno = 0;
|
|
|
|
}
|
1999-08-01 15:14:11 -07:00
|
|
|
previous_l = l;
|
|
|
|
l = l->next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* if we have a loader then its the loader that succeeded */
|
|
|
|
/* move the successful loader to the head of the list */
|
|
|
|
/* as long as it's not alreayd at the head of the list */
|
|
|
|
if ((l) && (previous_l))
|
|
|
|
{
|
|
|
|
im->loader = l;
|
|
|
|
previous_l->next = l->next;
|
|
|
|
l->next = loaders;
|
|
|
|
loaders = l;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
im->loader = best_loader;
|
|
|
|
/* all loaders have been tried and they all failed. free the skeleton */
|
|
|
|
/* image struct we had and return NULL */
|
|
|
|
if (im->w == 0)
|
|
|
|
{
|
1999-08-04 16:36:07 -07:00
|
|
|
__imlib_ConsumeImage(im);
|
1999-08-01 15:14:11 -07:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* the laod succeeded - make sure the image is refernenced then add */
|
1999-08-02 22:15:34 -07:00
|
|
|
/* it to our cache if dont_cache isnt set */
|
1999-08-01 15:14:11 -07:00
|
|
|
im->references = 1;
|
1999-08-02 22:15:34 -07:00
|
|
|
if (!dont_cache)
|
1999-08-04 16:36:07 -07:00
|
|
|
__imlib_AddImageToCache(im);
|
1999-08-02 22:15:34 -07:00
|
|
|
else
|
|
|
|
SET_FLAG(im->flags, F_UNCACHEABLE);
|
1999-08-01 15:14:11 -07:00
|
|
|
return im;
|
|
|
|
}
|
|
|
|
|
|
|
|
ImlibImagePixmap *
|
1999-08-04 16:36:07 -07:00
|
|
|
__imlib_FindImlibImagePixmapByID(Display *d, Pixmap p)
|
1999-08-01 15:14:11 -07:00
|
|
|
{
|
|
|
|
ImlibImagePixmap *ip;
|
|
|
|
|
|
|
|
ip = pixmaps;
|
|
|
|
/* go through the pixmap list */
|
|
|
|
while (ip)
|
|
|
|
{
|
|
|
|
/* if all the pixmap ID & Display match */
|
|
|
|
if ((ip->pixmap == p) && (ip->display == d))
|
|
|
|
return ip;
|
|
|
|
ip = ip->next;
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
1999-08-04 16:36:07 -07:00
|
|
|
__imlib_FreeImage(ImlibImage *im)
|
1999-08-01 15:14:11 -07:00
|
|
|
{
|
1999-09-12 18:56:57 -07:00
|
|
|
if (im->references >= 0)
|
1999-08-01 15:14:11 -07:00
|
|
|
{
|
|
|
|
im->references--;
|
1999-08-05 19:08:36 -07:00
|
|
|
if (IMAGE_IS_UNCACHEABLE(im))
|
|
|
|
{
|
1999-09-12 18:56:57 -07:00
|
|
|
printf("unchangeable\n");
|
1999-08-05 19:08:36 -07:00
|
|
|
if (im->references == 0)
|
|
|
|
__imlib_ConsumeImage(im);
|
|
|
|
}
|
|
|
|
else
|
1999-09-12 18:56:57 -07:00
|
|
|
__imlib_CleanupImageCache();
|
|
|
|
}
|
1999-08-01 15:14:11 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
1999-08-04 16:36:07 -07:00
|
|
|
__imlib_FreePixmap(Display *d, Pixmap p)
|
1999-08-01 15:14:11 -07:00
|
|
|
{
|
|
|
|
ImlibImagePixmap *ip;
|
|
|
|
|
1999-08-04 16:36:07 -07:00
|
|
|
ip = __imlib_FindImlibImagePixmapByID(d, p);
|
1999-08-01 15:14:11 -07:00
|
|
|
if (ip->references > 0)
|
|
|
|
{
|
|
|
|
ip->references--;
|
1999-08-04 16:36:07 -07:00
|
|
|
__imlib_CleanupImagePixmapCache();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
__imlib_FlushCache(void)
|
|
|
|
{
|
|
|
|
int previous_size;
|
|
|
|
|
|
|
|
previous_size = __imlib_GetCacheSize();
|
|
|
|
__imlib_SetCacheSize(0);
|
|
|
|
__imlib_SetCacheSize(previous_size);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
__imlib_DirtyPixmapsForImage(ImlibImage *im)
|
|
|
|
{
|
|
|
|
ImlibImagePixmap *ip;
|
|
|
|
|
|
|
|
ip = pixmaps;
|
|
|
|
/* go through the pixmap list */
|
|
|
|
while (ip)
|
|
|
|
{
|
|
|
|
/* if image matches */
|
|
|
|
if (ip->image == im)
|
|
|
|
ip->dirty = 1;
|
|
|
|
ip = ip->next;
|
1999-08-01 15:14:11 -07:00
|
|
|
}
|
1999-08-04 16:36:07 -07:00
|
|
|
__imlib_CleanupImagePixmapCache();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
__imlib_DirtyImage(ImlibImage *im)
|
|
|
|
{
|
|
|
|
SET_FLAG(im->flags, F_INVALID);
|
|
|
|
__imlib_DirtyPixmapsForImage(im);
|
1999-08-01 15:14:11 -07:00
|
|
|
}
|
1999-08-04 16:36:07 -07:00
|
|
|
|