2008-11-05 09:21:04 -08:00
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
# include <config.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef HAVE_EVIL
|
|
|
|
# include <Evil.h>
|
|
|
|
#endif
|
|
|
|
|
2013-06-20 03:53:29 -07:00
|
|
|
#include "evas_common_private.h"
|
2006-08-12 02:16:30 -07:00
|
|
|
#include "evas_private.h"
|
|
|
|
|
2010-04-08 15:55:54 -07:00
|
|
|
static int _evas_loader_xpm_log_dom = -1;
|
2010-04-08 10:39:01 -07:00
|
|
|
|
|
|
|
#ifdef ERR
|
|
|
|
# undef ERR
|
|
|
|
#endif
|
|
|
|
#define ERR(...) EINA_LOG_DOM_ERR(_evas_loader_xpm_log_dom, __VA_ARGS__)
|
|
|
|
|
2012-01-02 06:32:21 -08:00
|
|
|
static Eina_File *rgb_txt;
|
|
|
|
static void *rgb_txt_map;
|
2006-08-12 02:16:30 -07:00
|
|
|
|
2012-10-25 01:02:31 -07:00
|
|
|
static int
|
|
|
|
_xpm_hexa_int(const char *s, int len)
|
|
|
|
{
|
|
|
|
const char *hexa = "0123456789abcdef";
|
|
|
|
const char *lookup;
|
|
|
|
int i, c, r;
|
|
|
|
|
|
|
|
for (r = 0, i = 0; i < len; i++)
|
|
|
|
{
|
|
|
|
c = s[i];
|
|
|
|
lookup = strchr(hexa, tolower(c));
|
|
|
|
r = (r << 4) | (lookup ? lookup - hexa : 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
2006-08-12 02:16:30 -07:00
|
|
|
static void
|
|
|
|
xpm_parse_color(char *color, int *r, int *g, int *b)
|
|
|
|
{
|
2012-01-02 06:32:21 -08:00
|
|
|
char *tmp;
|
|
|
|
char *max;
|
|
|
|
char *endline;
|
|
|
|
char buf[4096];
|
2006-08-12 02:16:30 -07:00
|
|
|
|
|
|
|
/* is a #ff00ff like color */
|
|
|
|
if (color[0] == '#')
|
|
|
|
{
|
|
|
|
int len;
|
2008-11-05 09:21:04 -08:00
|
|
|
|
2006-08-12 02:16:30 -07:00
|
|
|
len = strlen(color) - 1;
|
2014-08-14 01:34:39 -07:00
|
|
|
if (len < 13)
|
2006-08-12 02:16:30 -07:00
|
|
|
{
|
2008-11-05 09:21:04 -08:00
|
|
|
|
2006-08-12 02:16:30 -07:00
|
|
|
len /= 3;
|
2012-10-25 01:02:31 -07:00
|
|
|
*r = _xpm_hexa_int(&(color[1 + (0 * len)]), len);
|
|
|
|
*g = _xpm_hexa_int(&(color[1 + (1 * len)]), len);
|
|
|
|
*b = _xpm_hexa_int(&(color[1 + (2 * len)]), len);
|
2006-08-12 02:16:30 -07:00
|
|
|
if (len == 1)
|
|
|
|
{
|
|
|
|
*r = (*r << 4) | *r;
|
|
|
|
*g = (*g << 4) | *g;
|
|
|
|
*b = (*b << 4) | *b;
|
|
|
|
}
|
|
|
|
else if (len > 2)
|
|
|
|
{
|
|
|
|
*r >>= (len - 2) * 4;
|
|
|
|
*g >>= (len - 2) * 4;
|
|
|
|
*b >>= (len - 2) * 4;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
/* look in rgb txt database */
|
2006-09-24 06:03:39 -07:00
|
|
|
if (!rgb_txt) return;
|
2012-01-02 06:32:21 -08:00
|
|
|
tmp = rgb_txt_map;
|
|
|
|
max = tmp + eina_file_size_get(rgb_txt);
|
|
|
|
|
|
|
|
while (tmp < max)
|
2006-08-12 02:16:30 -07:00
|
|
|
{
|
2012-01-02 06:32:21 -08:00
|
|
|
endline = memchr(tmp, '\n', max - tmp);
|
|
|
|
if (!endline) endline = max;
|
|
|
|
if ((*tmp != '!') && ((endline - tmp) < (int) (sizeof(buf) - 1)))
|
2006-08-12 02:16:30 -07:00
|
|
|
{
|
2006-09-24 06:03:39 -07:00
|
|
|
int rr, gg, bb;
|
|
|
|
char name[4096];
|
2008-11-05 09:21:04 -08:00
|
|
|
|
2012-10-25 01:02:31 -07:00
|
|
|
/* FIXME: not really efficient, should be loaded once in memory with a lookup table */
|
2012-01-02 06:32:21 -08:00
|
|
|
memcpy(buf, tmp, endline - tmp);
|
|
|
|
buf[endline - tmp + 1] = '\0';
|
|
|
|
|
2006-09-24 06:03:39 -07:00
|
|
|
if (sscanf(buf, "%i %i %i %[^\n]", &rr, &gg, &bb, name) == 4)
|
|
|
|
{
|
|
|
|
if (!strcasecmp(name, color))
|
|
|
|
{
|
|
|
|
*r = rr;
|
|
|
|
*g = gg;
|
|
|
|
*b = bb;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2006-08-12 02:16:30 -07:00
|
|
|
}
|
2012-01-02 06:32:21 -08:00
|
|
|
tmp = endline + 1;
|
2006-08-12 02:16:30 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-10-25 01:02:31 -07:00
|
|
|
typedef struct _CMap CMap;
|
|
|
|
struct _CMap {
|
|
|
|
EINA_RBTREE;
|
|
|
|
short r, g, b;
|
|
|
|
char str[6];
|
|
|
|
unsigned char transp;
|
|
|
|
};
|
|
|
|
|
|
|
|
Eina_Rbtree_Direction
|
2012-11-04 03:51:42 -08:00
|
|
|
_cmap_cmp_node_cb(const Eina_Rbtree *left, const Eina_Rbtree *right, void *data EINA_UNUSED)
|
2012-10-25 01:02:31 -07:00
|
|
|
{
|
|
|
|
CMap *lcm;
|
|
|
|
CMap *rcm;
|
|
|
|
|
|
|
|
lcm = EINA_RBTREE_CONTAINER_GET(left, CMap);
|
|
|
|
rcm = EINA_RBTREE_CONTAINER_GET(right, CMap);
|
|
|
|
|
|
|
|
if (strcmp(lcm->str, rcm->str) < 0)
|
|
|
|
return EINA_RBTREE_LEFT;
|
|
|
|
return EINA_RBTREE_RIGHT;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2012-11-04 03:51:42 -08:00
|
|
|
_cmap_cmp_key_cb(const Eina_Rbtree *node, const void *key, int length EINA_UNUSED, void *data EINA_UNUSED)
|
2012-10-25 01:02:31 -07:00
|
|
|
{
|
|
|
|
CMap *root = EINA_RBTREE_CONTAINER_GET(node, CMap);
|
|
|
|
|
|
|
|
return strcmp(root->str, key);
|
|
|
|
}
|
|
|
|
|
2006-08-12 02:16:30 -07:00
|
|
|
/** FIXME: clean this up and make more efficient **/
|
2009-12-22 15:11:57 -08:00
|
|
|
static Eina_Bool
|
2013-05-02 01:17:42 -07:00
|
|
|
evas_image_load_file_xpm(Eina_File *f, Evas_Image_Property *prop, void *pixels, int load_data, int *error)
|
2006-08-12 02:16:30 -07:00
|
|
|
{
|
2012-11-14 21:20:21 -08:00
|
|
|
DATA32 *ptr, *end, *head = NULL;
|
2013-05-07 13:33:10 -07:00
|
|
|
const char *map = NULL;
|
2012-10-25 01:02:31 -07:00
|
|
|
size_t length;
|
|
|
|
size_t position;
|
|
|
|
|
|
|
|
int pc, c, i, j, k, w, h, ncolors, cpp, comment, transp,
|
|
|
|
quote, context, len, done, r, g, b, backslash, lu1, lu2;
|
|
|
|
char *line = NULL;
|
2013-02-18 03:48:25 -08:00
|
|
|
char s[256], tok[256], col[256], *tl;
|
2012-10-25 01:02:31 -07:00
|
|
|
int lsz = 256;
|
|
|
|
CMap *cmap = NULL;
|
|
|
|
Eina_Rbtree *root = NULL;
|
|
|
|
|
|
|
|
short lookup[128 - 32][128 - 32];
|
2013-05-02 01:17:42 -07:00
|
|
|
int count, size;
|
|
|
|
Eina_Bool res = EINA_FALSE;
|
2006-08-12 02:16:30 -07:00
|
|
|
|
|
|
|
done = 0;
|
|
|
|
// transp = -1;
|
2006-09-24 06:03:39 -07:00
|
|
|
transp = 1;
|
2006-08-12 02:16:30 -07:00
|
|
|
|
|
|
|
/* if immediate_load is 1, then dont delay image laoding as below, or */
|
|
|
|
/* already data in this image - dont load it again */
|
|
|
|
|
2012-01-02 06:32:21 -08:00
|
|
|
length = eina_file_size_get(f);
|
|
|
|
position = 0;
|
2013-05-02 01:17:42 -07:00
|
|
|
*error = EVAS_LOAD_ERROR_CORRUPT_FILE;
|
2012-01-02 06:32:21 -08:00
|
|
|
if (length < 9)
|
2007-10-28 03:08:32 -07:00
|
|
|
{
|
2013-05-02 01:17:42 -07:00
|
|
|
ERR("XPM ERROR: file size, %zd, is to small", length);
|
|
|
|
goto on_error;
|
2007-10-28 03:08:32 -07:00
|
|
|
}
|
2012-01-02 06:32:21 -08:00
|
|
|
|
2013-08-01 18:25:26 -07:00
|
|
|
map = eina_file_map_all(f, load_data ? EINA_FILE_WILLNEED : EINA_FILE_RANDOM);
|
2012-01-02 06:32:21 -08:00
|
|
|
if (!map)
|
2006-08-12 02:16:30 -07:00
|
|
|
{
|
2013-05-02 01:17:42 -07:00
|
|
|
ERR("XPM ERROR: file failed to mmap");
|
|
|
|
goto on_error;
|
2006-08-12 02:16:30 -07:00
|
|
|
}
|
2008-11-05 09:21:04 -08:00
|
|
|
|
2012-01-02 06:32:21 -08:00
|
|
|
if (strncmp("/* XPM */", map, 9))
|
|
|
|
{
|
|
|
|
*error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT;
|
|
|
|
goto on_error;
|
|
|
|
}
|
|
|
|
|
2006-08-12 02:16:30 -07:00
|
|
|
i = 0;
|
|
|
|
j = 0;
|
|
|
|
cmap = NULL;
|
|
|
|
w = 10;
|
|
|
|
h = 10;
|
|
|
|
ptr = NULL;
|
|
|
|
end = NULL;
|
|
|
|
c = ' ';
|
|
|
|
comment = 0;
|
|
|
|
quote = 0;
|
|
|
|
context = 0;
|
2013-05-02 01:17:42 -07:00
|
|
|
size = 0;
|
2006-08-12 02:16:30 -07:00
|
|
|
count = 0;
|
|
|
|
line = malloc(lsz);
|
|
|
|
if (!line)
|
|
|
|
{
|
2009-12-22 15:11:57 -08:00
|
|
|
*error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
|
2012-01-02 06:32:21 -08:00
|
|
|
goto on_error;
|
2006-08-12 02:16:30 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
backslash = 0;
|
|
|
|
memset(lookup, 0, sizeof(lookup));
|
|
|
|
while (!done)
|
|
|
|
{
|
|
|
|
pc = c;
|
2012-01-02 06:32:21 -08:00
|
|
|
if (position == length) break ;
|
|
|
|
c = (char) map[position++];
|
2006-08-12 02:16:30 -07:00
|
|
|
if (!quote)
|
|
|
|
{
|
|
|
|
if ((pc == '/') && (c == '*'))
|
2006-09-24 06:03:39 -07:00
|
|
|
comment = 1;
|
2006-08-12 02:16:30 -07:00
|
|
|
else if ((pc == '*') && (c == '/') && (comment))
|
2006-09-24 06:03:39 -07:00
|
|
|
comment = 0;
|
2006-08-12 02:16:30 -07:00
|
|
|
}
|
|
|
|
if (!comment)
|
|
|
|
{
|
|
|
|
if ((!quote) && (c == '"'))
|
|
|
|
{
|
|
|
|
quote = 1;
|
|
|
|
i = 0;
|
|
|
|
}
|
|
|
|
else if ((quote) && (c == '"'))
|
|
|
|
{
|
|
|
|
line[i] = 0;
|
|
|
|
quote = 0;
|
|
|
|
if (context == 0)
|
|
|
|
{
|
|
|
|
/* Header */
|
2006-09-24 06:03:39 -07:00
|
|
|
if (sscanf(line, "%i %i %i %i", &w, &h, &ncolors, &cpp) != 4)
|
|
|
|
{
|
2009-10-22 09:39:20 -07:00
|
|
|
ERR("XPM ERROR: XPM file malformed header");
|
2009-12-22 15:11:57 -08:00
|
|
|
*error = EVAS_LOAD_ERROR_CORRUPT_FILE;
|
2012-01-02 06:32:21 -08:00
|
|
|
goto on_error;
|
2006-09-24 06:03:39 -07:00
|
|
|
}
|
2006-08-12 02:16:30 -07:00
|
|
|
if ((ncolors > 32766) || (ncolors < 1))
|
|
|
|
{
|
2009-10-22 09:39:20 -07:00
|
|
|
ERR("XPM ERROR: XPM files with colors > 32766 or < 1 not supported");
|
2009-12-22 15:11:57 -08:00
|
|
|
*error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT;
|
2012-01-02 06:32:21 -08:00
|
|
|
goto on_error;
|
2006-08-12 02:16:30 -07:00
|
|
|
}
|
|
|
|
if ((cpp > 5) || (cpp < 1))
|
|
|
|
{
|
2009-10-22 09:39:20 -07:00
|
|
|
ERR("XPM ERROR: XPM files with characters per pixel > 5 or < 1not supported");
|
2009-12-22 15:11:57 -08:00
|
|
|
*error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT;
|
2012-01-02 06:32:21 -08:00
|
|
|
goto on_error;
|
2006-08-12 02:16:30 -07:00
|
|
|
}
|
2009-09-11 06:44:53 -07:00
|
|
|
if ((w > IMG_MAX_SIZE) || (w < 1))
|
2006-08-12 02:16:30 -07:00
|
|
|
{
|
2009-10-22 09:39:20 -07:00
|
|
|
ERR("XPM ERROR: Image width > IMG_MAX_SIZE or < 1 pixels for file");
|
2009-12-22 15:11:57 -08:00
|
|
|
*error = EVAS_LOAD_ERROR_GENERIC;
|
2012-01-02 06:32:21 -08:00
|
|
|
goto on_error;
|
2006-08-12 02:16:30 -07:00
|
|
|
}
|
2009-09-11 06:44:53 -07:00
|
|
|
if ((h > IMG_MAX_SIZE) || (h < 1))
|
2006-08-12 02:16:30 -07:00
|
|
|
{
|
2009-10-22 09:39:20 -07:00
|
|
|
ERR("XPM ERROR: Image height > IMG_MAX_SIZE or < 1 pixels for file");
|
2009-12-22 15:11:57 -08:00
|
|
|
*error = EVAS_LOAD_ERROR_GENERIC;
|
2012-01-02 06:32:21 -08:00
|
|
|
goto on_error;
|
2009-09-16 02:48:05 -07:00
|
|
|
}
|
|
|
|
if (IMG_TOO_BIG(w, h))
|
|
|
|
{
|
2009-10-22 09:39:20 -07:00
|
|
|
ERR("XPM ERROR: Image just too big to ever allocate");
|
2009-12-22 15:11:57 -08:00
|
|
|
*error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
|
2012-01-02 06:32:21 -08:00
|
|
|
goto on_error;
|
2006-08-12 02:16:30 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!cmap)
|
|
|
|
{
|
2012-10-25 01:02:31 -07:00
|
|
|
cmap = malloc(sizeof(CMap) * ncolors);
|
2006-08-12 02:16:30 -07:00
|
|
|
if (!cmap)
|
|
|
|
{
|
2009-12-22 15:11:57 -08:00
|
|
|
*error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
|
2012-01-02 06:32:21 -08:00
|
|
|
goto on_error;
|
2006-08-12 02:16:30 -07:00
|
|
|
}
|
|
|
|
}
|
2013-05-02 01:17:42 -07:00
|
|
|
|
|
|
|
if (!load_data)
|
|
|
|
{
|
|
|
|
prop->w = w;
|
|
|
|
prop->h = h;
|
|
|
|
}
|
|
|
|
else if ((int) prop->w != w ||
|
|
|
|
(int) prop->h != h)
|
|
|
|
{
|
|
|
|
*error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
|
|
|
|
goto on_error;
|
|
|
|
}
|
|
|
|
|
2006-08-12 02:16:30 -07:00
|
|
|
|
|
|
|
j = 0;
|
|
|
|
context++;
|
|
|
|
}
|
|
|
|
else if (context == 1)
|
|
|
|
{
|
|
|
|
/* Color Table */
|
|
|
|
if (j < ncolors)
|
|
|
|
{
|
|
|
|
int slen;
|
|
|
|
int hascolor, iscolor;
|
|
|
|
|
|
|
|
iscolor = 0;
|
|
|
|
hascolor = 0;
|
|
|
|
tok[0] = 0;
|
|
|
|
col[0] = 0;
|
|
|
|
s[0] = 0;
|
|
|
|
len = strlen(line);
|
|
|
|
strncpy(cmap[j].str, line, cpp);
|
|
|
|
cmap[j].str[cpp] = 0;
|
2012-10-25 01:02:31 -07:00
|
|
|
if (load_data) root = eina_rbtree_inline_insert(root, EINA_RBTREE_GET(&cmap[j]), _cmap_cmp_node_cb, NULL);
|
2006-09-24 06:03:39 -07:00
|
|
|
for (slen = 0; slen < cpp; slen++)
|
|
|
|
{
|
|
|
|
/* fix the ascii of the color string - if its < 32 - just limit to 32 */
|
|
|
|
if (cmap[j].str[slen] < 32) cmap[j].str[slen] = 0;
|
|
|
|
}
|
2006-08-12 02:16:30 -07:00
|
|
|
cmap[j].r = -1;
|
|
|
|
cmap[j].transp = 0;
|
|
|
|
for (k = cpp; k < len; k++)
|
|
|
|
{
|
|
|
|
if (line[k] != ' ')
|
|
|
|
{
|
2012-10-25 01:02:31 -07:00
|
|
|
const char *tmp = strchr(&line[k], ' ');
|
|
|
|
slen = tmp ? tmp - &line[k]: 255;
|
|
|
|
|
|
|
|
strncpy(s, &line[k], slen);
|
|
|
|
s[slen] = 0;
|
2006-08-12 02:16:30 -07:00
|
|
|
k += slen;
|
2012-10-10 00:23:45 -07:00
|
|
|
if (slen == 1 && *s == 'c') iscolor = 1;
|
2012-10-10 01:18:09 -07:00
|
|
|
if ((slen == 1 && ((s[0] == 'm') || (s[0] == 's') || (s[0] == 'g') || (s[0] == 'c'))) ||
|
2012-10-10 00:58:54 -07:00
|
|
|
(slen == 2 && (s[0] == 'g') && (s[1] == '4')) ||
|
2012-10-10 00:23:45 -07:00
|
|
|
(k >= len))
|
2006-08-12 02:16:30 -07:00
|
|
|
{
|
|
|
|
if (k >= len)
|
|
|
|
{
|
|
|
|
if (col[0])
|
|
|
|
{
|
2006-09-24 06:03:39 -07:00
|
|
|
if (strlen(col) < (sizeof(col) - 2))
|
2006-08-12 02:16:30 -07:00
|
|
|
strcat(col, " ");
|
|
|
|
else
|
|
|
|
done = 1;
|
|
|
|
}
|
2006-09-24 06:03:39 -07:00
|
|
|
if ((strlen(col) + strlen(s)) < (sizeof(col) - 1))
|
|
|
|
strcat(col, s);
|
2006-08-12 02:16:30 -07:00
|
|
|
}
|
|
|
|
if (col[0])
|
|
|
|
{
|
|
|
|
if (!strcasecmp(col, "none"))
|
|
|
|
{
|
|
|
|
transp = 1;
|
|
|
|
cmap[j].transp = 1;
|
2006-09-24 06:03:39 -07:00
|
|
|
cmap[j].r = 0;
|
|
|
|
cmap[j].g = 0;
|
|
|
|
cmap[j].b = 0;
|
2006-08-12 02:16:30 -07:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2006-09-24 06:03:39 -07:00
|
|
|
if ((((cmap[j].r < 0) || (!strcmp(tok, "c"))) && (!hascolor)))
|
2006-08-12 02:16:30 -07:00
|
|
|
{
|
2006-09-24 06:03:39 -07:00
|
|
|
r = g = b = 0;
|
|
|
|
xpm_parse_color(col, &r, &g, &b);
|
2006-08-12 02:16:30 -07:00
|
|
|
cmap[j].r = r;
|
|
|
|
cmap[j].g = g;
|
|
|
|
cmap[j].b = b;
|
2006-09-24 06:03:39 -07:00
|
|
|
if (iscolor) hascolor = 1;
|
2006-08-12 02:16:30 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
strcpy(tok, s);
|
|
|
|
col[0] = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (col[0])
|
|
|
|
{
|
|
|
|
if (strlen(col) < ( sizeof(col) - 2))
|
|
|
|
strcat(col, " ");
|
|
|
|
else
|
|
|
|
done = 1;
|
|
|
|
}
|
2006-09-24 06:03:39 -07:00
|
|
|
if ((strlen(col) + strlen(s)) < (sizeof(col) - 1))
|
2006-08-12 02:16:30 -07:00
|
|
|
strcat(col, s);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
j++;
|
2012-10-25 01:02:31 -07:00
|
|
|
if (load_data && j >= ncolors)
|
2006-08-12 02:16:30 -07:00
|
|
|
{
|
|
|
|
if (cpp == 1)
|
2006-09-24 06:03:39 -07:00
|
|
|
{
|
|
|
|
for (i = 0; i < ncolors; i++)
|
|
|
|
lookup[(int)cmap[i].str[0] - 32][0] = i;
|
|
|
|
}
|
2006-08-12 02:16:30 -07:00
|
|
|
if (cpp == 2)
|
2006-09-24 06:03:39 -07:00
|
|
|
{
|
|
|
|
for (i = 0; i < ncolors; i++)
|
|
|
|
lookup[(int)cmap[i].str[0] - 32][(int)cmap[i].str[1] - 32] = i;
|
|
|
|
}
|
2006-08-12 02:16:30 -07:00
|
|
|
context++;
|
|
|
|
}
|
|
|
|
|
2013-05-02 01:17:42 -07:00
|
|
|
if (transp) prop->alpha = 1;
|
2008-11-05 09:21:04 -08:00
|
|
|
|
2006-08-12 02:16:30 -07:00
|
|
|
if (load_data)
|
|
|
|
{
|
2013-05-02 01:17:42 -07:00
|
|
|
ptr = pixels;
|
2012-10-25 01:02:31 -07:00
|
|
|
head = ptr;
|
2008-06-03 02:09:39 -07:00
|
|
|
if (!ptr)
|
2006-08-12 02:16:30 -07:00
|
|
|
{
|
2009-12-22 15:11:57 -08:00
|
|
|
*error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
|
2012-01-02 06:32:21 -08:00
|
|
|
goto on_error;
|
2006-08-12 02:16:30 -07:00
|
|
|
}
|
2013-05-02 01:17:42 -07:00
|
|
|
size = w * h;
|
|
|
|
end = ptr + size;
|
2006-08-12 02:16:30 -07:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2009-12-22 15:11:57 -08:00
|
|
|
*error = EVAS_LOAD_ERROR_NONE;
|
2012-01-02 06:32:21 -08:00
|
|
|
goto on_success;
|
2006-08-12 02:16:30 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Image Data */
|
|
|
|
i = 0;
|
|
|
|
if (cpp == 0)
|
|
|
|
{
|
|
|
|
/* Chars per pixel = 0? well u never know */
|
|
|
|
}
|
2006-09-24 06:03:39 -07:00
|
|
|
/* it's xpm - don't care about speed too much. still faster
|
|
|
|
* that most xpm loaders anyway */
|
|
|
|
else if (cpp == 1)
|
2006-08-12 02:16:30 -07:00
|
|
|
{
|
|
|
|
if (transp)
|
|
|
|
{
|
|
|
|
for (i = 0;
|
|
|
|
((i < 65536) && (ptr < end) && (line[i]));
|
|
|
|
i++)
|
|
|
|
{
|
2006-09-24 06:03:39 -07:00
|
|
|
lu1 = (int)line[i] - 32;
|
|
|
|
if (lu1 < 0) continue;
|
|
|
|
if (cmap[lookup[lu1][0]].transp)
|
2006-08-12 02:16:30 -07:00
|
|
|
{
|
2006-09-24 06:03:39 -07:00
|
|
|
r = (unsigned char)cmap[lookup[lu1][0]].r;
|
|
|
|
g = (unsigned char)cmap[lookup[lu1][0]].g;
|
|
|
|
b = (unsigned char)cmap[lookup[lu1][0]].b;
|
2010-06-07 22:39:46 -07:00
|
|
|
*ptr = RGB_JOIN(r, g, b);
|
2006-09-24 06:03:39 -07:00
|
|
|
ptr++;
|
2006-08-12 02:16:30 -07:00
|
|
|
count++;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2006-09-24 06:03:39 -07:00
|
|
|
r = (unsigned char)cmap[lookup[lu1][0]].r;
|
|
|
|
g = (unsigned char)cmap[lookup[lu1][0]].g;
|
|
|
|
b = (unsigned char)cmap[lookup[lu1][0]].b;
|
2010-06-07 22:39:46 -07:00
|
|
|
*ptr = ARGB_JOIN(0xff, r, g, b);
|
2006-09-24 06:03:39 -07:00
|
|
|
ptr++;
|
2006-08-12 02:16:30 -07:00
|
|
|
count++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
for (i = 0;
|
|
|
|
((i < 65536) && (ptr < end) && (line[i]));
|
|
|
|
i++)
|
|
|
|
{
|
2006-09-24 06:03:39 -07:00
|
|
|
lu1 = (int)line[i] - 32;
|
|
|
|
if (lu1 < 0) continue;
|
|
|
|
r = (unsigned char)cmap[lookup[lu1][0]].r;
|
|
|
|
g = (unsigned char)cmap[lookup[lu1][0]].g;
|
|
|
|
b = (unsigned char)cmap[lookup[lu1][0]].b;
|
2010-06-07 22:39:46 -07:00
|
|
|
*ptr = ARGB_JOIN(0xff, r, g, b);
|
2006-09-24 06:03:39 -07:00
|
|
|
ptr++;
|
|
|
|
count++;
|
2006-08-12 02:16:30 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (cpp == 2)
|
|
|
|
{
|
|
|
|
if (transp)
|
|
|
|
{
|
|
|
|
for (i = 0;
|
|
|
|
((i < 65536) && (ptr < end) && (line[i]));
|
|
|
|
i++)
|
|
|
|
{
|
2006-09-24 06:03:39 -07:00
|
|
|
lu1 = (int)line[i] - 32;
|
|
|
|
i++;
|
|
|
|
lu2 = (int)line[i] - 32;
|
|
|
|
if (lu1 < 0) continue;
|
|
|
|
if (lu2 < 0) continue;
|
|
|
|
if (cmap[lookup[lu1][lu2]].transp)
|
2006-08-12 02:16:30 -07:00
|
|
|
{
|
2006-09-24 06:03:39 -07:00
|
|
|
r = (unsigned char)cmap[lookup[lu1][lu2]].r;
|
|
|
|
g = (unsigned char)cmap[lookup[lu1][lu2]].g;
|
|
|
|
b = (unsigned char)cmap[lookup[lu1][lu2]].b;
|
2010-06-07 22:39:46 -07:00
|
|
|
*ptr = RGB_JOIN(r, g, b);
|
2006-09-24 06:03:39 -07:00
|
|
|
ptr++;
|
2006-08-12 02:16:30 -07:00
|
|
|
count++;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2006-09-24 06:03:39 -07:00
|
|
|
r = (unsigned char)cmap[lookup[lu1][lu2]].r;
|
|
|
|
g = (unsigned char)cmap[lookup[lu1][lu2]].g;
|
|
|
|
b = (unsigned char)cmap[lookup[lu1][lu2]].b;
|
2010-06-07 22:39:46 -07:00
|
|
|
*ptr = ARGB_JOIN(0xff, r, g, b);
|
2006-09-24 06:03:39 -07:00
|
|
|
ptr++;
|
2006-08-12 02:16:30 -07:00
|
|
|
count++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
for (i = 0;
|
|
|
|
((i < 65536) && (ptr < end) && (line[i]));
|
|
|
|
i++)
|
|
|
|
{
|
2006-09-24 06:03:39 -07:00
|
|
|
lu1 = (int)line[i] - 32;
|
|
|
|
i++;
|
|
|
|
lu2 = (int)line[i] - 32;
|
|
|
|
if (lu1 < 0) continue;
|
|
|
|
if (lu2 < 0) continue;
|
|
|
|
r = (unsigned char)cmap[lookup[lu1][lu2]].r;
|
|
|
|
g = (unsigned char)cmap[lookup[lu1][lu2]].g;
|
|
|
|
b = (unsigned char)cmap[lookup[lu1][lu2]].b;
|
2010-06-07 22:39:46 -07:00
|
|
|
*ptr = ARGB_JOIN(0xff, r, g, b);
|
2006-09-24 06:03:39 -07:00
|
|
|
ptr++;
|
|
|
|
count++;
|
2006-08-12 02:16:30 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (transp)
|
|
|
|
{
|
|
|
|
for (i = 0;
|
|
|
|
((i < 65536) && (ptr < end) && (line[i]));
|
|
|
|
i++)
|
|
|
|
{
|
2012-10-25 01:02:31 -07:00
|
|
|
Eina_Rbtree *l;
|
|
|
|
|
2006-08-12 02:16:30 -07:00
|
|
|
for (j = 0; j < cpp; j++, i++)
|
2006-09-24 06:03:39 -07:00
|
|
|
{
|
|
|
|
col[j] = line[i];
|
|
|
|
if (col[j] < 32) col[j] = 32;
|
|
|
|
}
|
2006-08-12 02:16:30 -07:00
|
|
|
col[j] = 0;
|
|
|
|
i--;
|
2012-10-25 01:02:31 -07:00
|
|
|
|
|
|
|
l = eina_rbtree_inline_lookup(root, col, j, _cmap_cmp_key_cb, NULL);
|
|
|
|
if (l)
|
2006-08-12 02:16:30 -07:00
|
|
|
{
|
2012-10-25 01:02:31 -07:00
|
|
|
CMap *cm = EINA_RBTREE_CONTAINER_GET(l, CMap);
|
|
|
|
|
|
|
|
r = (unsigned char)cm->r;
|
|
|
|
g = (unsigned char)cm->g;
|
|
|
|
b = (unsigned char)cm->b;
|
|
|
|
if (cm->transp)
|
2006-08-12 02:16:30 -07:00
|
|
|
{
|
2012-10-25 01:02:31 -07:00
|
|
|
*ptr = RGB_JOIN(r, g, b);
|
2006-08-12 02:16:30 -07:00
|
|
|
}
|
2012-10-25 01:02:31 -07:00
|
|
|
else
|
|
|
|
{
|
|
|
|
*ptr = ARGB_JOIN(0xff, r, g, b);
|
|
|
|
}
|
|
|
|
|
|
|
|
ptr++;
|
|
|
|
count++;
|
2006-08-12 02:16:30 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
for (i = 0;
|
|
|
|
((i < 65536) && (ptr < end) && (line[i]));
|
|
|
|
i++)
|
|
|
|
{
|
2012-10-25 01:02:31 -07:00
|
|
|
Eina_Rbtree *l;
|
|
|
|
|
2006-08-12 02:16:30 -07:00
|
|
|
for (j = 0; j < cpp; j++, i++)
|
|
|
|
{
|
|
|
|
col[j] = line[i];
|
|
|
|
}
|
|
|
|
col[j] = 0;
|
|
|
|
i--;
|
2012-10-25 01:02:31 -07:00
|
|
|
|
|
|
|
l = eina_rbtree_inline_lookup(root, col, 0, _cmap_cmp_key_cb, NULL);
|
|
|
|
if (l)
|
2006-08-12 02:16:30 -07:00
|
|
|
{
|
2012-10-25 01:02:31 -07:00
|
|
|
CMap *cm = EINA_RBTREE_CONTAINER_GET(l, CMap);
|
|
|
|
|
|
|
|
r = (unsigned char)cm->r;
|
|
|
|
g = (unsigned char)cm->g;
|
|
|
|
b = (unsigned char)cm->b;
|
|
|
|
*ptr = ARGB_JOIN(0xff, r, g, b);
|
|
|
|
ptr++;
|
|
|
|
count++;
|
2006-08-12 02:16:30 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* Scan in line from XPM file */
|
|
|
|
if ((!comment) && (quote) && (c != '"'))
|
|
|
|
{
|
2006-09-24 06:03:39 -07:00
|
|
|
if (c < 32) c = 32;
|
|
|
|
else if (c > 127) c = 127;
|
|
|
|
if (c =='\\')
|
|
|
|
{
|
|
|
|
if (++backslash < 2)
|
|
|
|
line[i++] = c;
|
|
|
|
else
|
|
|
|
backslash = 0;
|
2006-08-12 02:16:30 -07:00
|
|
|
}
|
2006-09-24 06:03:39 -07:00
|
|
|
else
|
|
|
|
{
|
|
|
|
backslash = 0;
|
|
|
|
line[i++] = c;
|
2006-08-12 02:16:30 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (i >= lsz)
|
|
|
|
{
|
|
|
|
lsz += 256;
|
2006-09-24 06:03:39 -07:00
|
|
|
tl = realloc(line, lsz);
|
|
|
|
if (!tl) break;
|
|
|
|
line = tl;
|
2006-08-12 02:16:30 -07:00
|
|
|
}
|
2014-08-14 03:53:24 -07:00
|
|
|
if (((ptr) && ((ptr - head) >= (w * h))) ||
|
2013-05-02 01:17:42 -07:00
|
|
|
((context > 1) && (count >= size)))
|
2006-09-24 06:03:39 -07:00
|
|
|
break;
|
2006-08-12 02:16:30 -07:00
|
|
|
}
|
|
|
|
|
2012-01-02 06:32:21 -08:00
|
|
|
on_success:
|
2009-12-22 15:11:57 -08:00
|
|
|
*error = EVAS_LOAD_ERROR_NONE;
|
2013-05-02 01:17:42 -07:00
|
|
|
res = EINA_TRUE;
|
2012-01-02 06:32:21 -08:00
|
|
|
|
|
|
|
on_error:
|
2013-05-02 01:17:42 -07:00
|
|
|
if (map) eina_file_map_free(f, (void*) map);
|
|
|
|
free(cmap);
|
2012-01-02 06:32:21 -08:00
|
|
|
free(line);
|
2013-05-02 01:17:42 -07:00
|
|
|
return res;
|
2006-08-12 02:16:30 -07:00
|
|
|
}
|
|
|
|
|
2013-05-06 03:01:35 -07:00
|
|
|
static void *
|
2013-07-01 23:33:32 -07:00
|
|
|
evas_image_load_file_open_xpm(Eina_File *f, Eina_Stringshare *key EINA_UNUSED,
|
2013-05-02 01:17:42 -07:00
|
|
|
Evas_Image_Load_Opts *opts EINA_UNUSED,
|
|
|
|
Evas_Image_Animated *animated EINA_UNUSED,
|
2013-05-06 03:01:35 -07:00
|
|
|
int *error EINA_UNUSED)
|
|
|
|
{
|
|
|
|
return f;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
evas_image_load_file_close_xpm(void *loader_data EINA_UNUSED)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
static Eina_Bool
|
|
|
|
evas_image_load_file_head_xpm(void *loader_data,
|
|
|
|
Evas_Image_Property *prop,
|
2013-05-02 01:17:42 -07:00
|
|
|
int *error)
|
2006-08-12 02:16:30 -07:00
|
|
|
{
|
2013-05-06 03:01:35 -07:00
|
|
|
Eina_File *f = loader_data;
|
|
|
|
|
2013-05-02 01:17:42 -07:00
|
|
|
return evas_image_load_file_xpm(f, prop, NULL, 0, error);
|
2006-08-12 02:16:30 -07:00
|
|
|
}
|
|
|
|
|
2009-12-22 15:11:57 -08:00
|
|
|
static Eina_Bool
|
2013-05-06 03:01:35 -07:00
|
|
|
evas_image_load_file_data_xpm(void *loader_data,
|
2013-05-02 01:17:42 -07:00
|
|
|
Evas_Image_Property *prop,
|
|
|
|
void *pixels,
|
|
|
|
int *error)
|
2006-08-12 02:16:30 -07:00
|
|
|
{
|
2013-05-06 03:01:35 -07:00
|
|
|
Eina_File *f = loader_data;
|
|
|
|
|
2013-05-02 01:17:42 -07:00
|
|
|
return evas_image_load_file_xpm(f, prop, pixels, 1, error);
|
2006-08-12 02:16:30 -07:00
|
|
|
}
|
|
|
|
|
2013-05-02 01:17:42 -07:00
|
|
|
static Evas_Image_Load_Func evas_image_load_xpm_func =
|
|
|
|
{
|
2013-05-06 03:01:35 -07:00
|
|
|
evas_image_load_file_open_xpm,
|
|
|
|
evas_image_load_file_close_xpm,
|
2013-05-02 01:17:42 -07:00
|
|
|
evas_image_load_file_head_xpm,
|
|
|
|
evas_image_load_file_data_xpm,
|
|
|
|
NULL,
|
2013-05-06 18:50:57 -07:00
|
|
|
EINA_FALSE,
|
2013-05-02 01:17:42 -07:00
|
|
|
EINA_FALSE
|
|
|
|
};
|
|
|
|
|
2009-06-16 06:01:36 -07:00
|
|
|
static int
|
2006-09-06 00:28:46 -07:00
|
|
|
module_open(Evas_Module *em)
|
2006-08-12 02:16:30 -07:00
|
|
|
{
|
|
|
|
if (!em) return 0;
|
2010-10-07 16:46:42 -07:00
|
|
|
_evas_loader_xpm_log_dom = eina_log_domain_register
|
|
|
|
("evas-xpm", EVAS_DEFAULT_LOG_COLOR);
|
2010-04-08 10:39:01 -07:00
|
|
|
if (_evas_loader_xpm_log_dom < 0)
|
|
|
|
{
|
2010-10-07 16:46:42 -07:00
|
|
|
EINA_LOG_ERR("Can not create a module log domain.");
|
2010-04-08 10:39:01 -07:00
|
|
|
return 0;
|
|
|
|
}
|
2012-01-02 06:32:21 -08:00
|
|
|
|
|
|
|
/* Shouldn't we make that PATH configurable ? */
|
|
|
|
rgb_txt = eina_file_open("/usr/lib/X11/rgb.txt", 0);
|
|
|
|
if (!rgb_txt) rgb_txt = eina_file_open("/usr/X11/lib/X11/rgb.txt", 0);
|
|
|
|
if (!rgb_txt) rgb_txt = eina_file_open("/usr/X11R6/lib/X11/rgb.txt", 0);
|
|
|
|
if (!rgb_txt) rgb_txt = eina_file_open("/usr/openwin/lib/X11/rgb.txt", 0);
|
|
|
|
if (rgb_txt)
|
2013-08-01 18:25:26 -07:00
|
|
|
rgb_txt_map = eina_file_map_all(rgb_txt, EINA_FILE_WILLNEED);
|
2006-08-12 02:16:30 -07:00
|
|
|
em->functions = (void *)(&evas_image_load_xpm_func);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2009-06-16 06:01:36 -07:00
|
|
|
static void
|
2012-11-04 03:51:42 -08:00
|
|
|
module_close(Evas_Module *em EINA_UNUSED)
|
2006-08-12 02:16:30 -07:00
|
|
|
{
|
2012-01-02 06:32:21 -08:00
|
|
|
if (rgb_txt)
|
|
|
|
{
|
|
|
|
eina_file_map_free(rgb_txt, rgb_txt_map);
|
|
|
|
eina_file_close(rgb_txt);
|
|
|
|
rgb_txt = NULL;
|
|
|
|
}
|
2010-04-08 10:39:01 -07:00
|
|
|
eina_log_domain_unregister(_evas_loader_xpm_log_dom);
|
2006-08-12 02:16:30 -07:00
|
|
|
}
|
|
|
|
|
2009-06-16 06:01:36 -07:00
|
|
|
static Evas_Module_Api evas_modapi =
|
2006-08-12 02:16:30 -07:00
|
|
|
{
|
|
|
|
EVAS_MODULE_API_VERSION,
|
2009-06-16 06:01:36 -07:00
|
|
|
"xpm",
|
|
|
|
"none",
|
|
|
|
{
|
|
|
|
module_open,
|
|
|
|
module_close
|
|
|
|
}
|
2006-08-12 02:16:30 -07:00
|
|
|
};
|
2009-06-16 06:01:36 -07:00
|
|
|
|
|
|
|
EVAS_MODULE_DEFINE(EVAS_MODULE_TYPE_IMAGE_LOADER, image_loader, xpm);
|
|
|
|
|
|
|
|
#ifndef EVAS_STATIC_BUILD_XPM
|
|
|
|
EVAS_EINA_MODULE_DEFINE(image_loader, xpm);
|
|
|
|
#endif
|