evas: give a Warp 10 engine to XPM loader !

NOTE: If anyone know the moron who did think it was a
great idea to make XPM the Freedesktop recommanded 
choice for icons, please give him a huge SPANK for me !

NOTE: There is in fact no reason why CServe2 and default
loader code are not shared. The number of different line
is small. I highly advise we make the effort to merge
them back soon.



SVN revision: 78424
This commit is contained in:
Cedric BAIL 2012-10-25 08:02:31 +00:00
parent 10ead8d107
commit 0827a05a58
4 changed files with 217 additions and 138 deletions

View File

@ -1124,3 +1124,6 @@
* Added Proxy'source events set APIs * Added Proxy'source events set APIs
2012-10-25 Cedric Bail
* Make XPM loader faster.

View File

@ -19,6 +19,7 @@ Improvements:
* EVAS_GL_NO_BLACKLIST env var to turn off blacklisted drivers in gl * EVAS_GL_NO_BLACKLIST env var to turn off blacklisted drivers in gl
* Evas gl engine can do partial swaps now. * Evas gl engine can do partial swaps now.
* evas_object_del() now takes NULL parameters * evas_object_del() now takes NULL parameters
* make xpm loader faster (from O(N) to O(log(N))).
Fixes: Fixes:
* Fix segmentation fault with the esvg loader. * Fix segmentation fault with the esvg loader.

View File

@ -6,6 +6,8 @@
# include <Evil.h> # include <Evil.h>
#endif #endif
#include <ctype.h>
#include "evas_macros.h" #include "evas_macros.h"
#include "evas_cserve2.h" #include "evas_cserve2.h"
@ -14,6 +16,23 @@
static Eina_File *rgb_txt; static Eina_File *rgb_txt;
static void *rgb_txt_map; static void *rgb_txt_map;
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;
}
static void static void
xpm_parse_color(char *color, int *r, int *g, int *b) xpm_parse_color(char *color, int *r, int *g, int *b)
{ {
@ -26,26 +45,15 @@ xpm_parse_color(char *color, int *r, int *g, int *b)
if (color[0] == '#') if (color[0] == '#')
{ {
int len; int len;
char val[32];
len = strlen(color) - 1; len = strlen(color) - 1;
if (len < 96) if (len < 96)
{ {
int i;
len /= 3; len /= 3;
for (i = 0; i < len; i++) *r = _xpm_hexa_int(&(color[1 + (0 * len)]), len);
val[i] = color[1 + i + (0 * len)]; *g = _xpm_hexa_int(&(color[1 + (1 * len)]), len);
val[i] = 0; *b = _xpm_hexa_int(&(color[1 + (2 * len)]), len);
sscanf(val, "%x", r);
for (i = 0; i < len; i++)
val[i] = color[1 + i + (1 * len)];
val[i] = 0;
sscanf(val, "%x", g);
for (i = 0; i < len; i++)
val[i] = color[1 + i + (2 * len)];
val[i] = 0;
sscanf(val, "%x", b);
if (len == 1) if (len == 1)
{ {
*r = (*r << 4) | *r; *r = (*r << 4) | *r;
@ -75,7 +83,7 @@ xpm_parse_color(char *color, int *r, int *g, int *b)
int rr, gg, bb; int rr, gg, bb;
char name[4096]; char name[4096];
/* FIXME: not really efficient */ /* FIXME: not really efficient, should be loaded once in memory with a lookup table */
memcpy(buf, tmp, endline - tmp); memcpy(buf, tmp, endline - tmp);
buf[endline - tmp + 1] = '\0'; buf[endline - tmp + 1] = '\0';
@ -94,29 +102,56 @@ xpm_parse_color(char *color, int *r, int *g, int *b)
} }
} }
typedef struct _CMap CMap;
struct _CMap {
EINA_RBTREE;
short r, g, b;
char str[6];
unsigned char transp;
};
Eina_Rbtree_Direction
_cmap_cmp_node_cb(const Eina_Rbtree *left, const Eina_Rbtree *right, void *data __UNUSED__)
{
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
_cmap_cmp_key_cb(const Eina_Rbtree *node, const void *key, int length __UNUSED__, void *data __UNUSED__)
{
CMap *root = EINA_RBTREE_CONTAINER_GET(node, CMap);
return strcmp(root->str, key);
}
/** FIXME: clean this up and make more efficient **/ /** FIXME: clean this up and make more efficient **/
static Eina_Bool static Eina_Bool
evas_image_load_file_xpm(Evas_Img_Load_Params *ilp, const char *file, const char *key __UNUSED__, int load_data, int *error) evas_image_load_file_xpm(Evas_Img_Load_Params *ilp, const char *file, const char *key __UNUSED__, int load_data, int *error)
{ {
DATA32 *ptr, *end; DATA32 *ptr, *end;
Eina_File *f; Eina_File *f;
const char *map; const char *map;
size_t length; size_t length;
size_t position; size_t position;
int pc, c, i, j, k, w, h, ncolors, cpp, comment, transp, int pc, c, i, j, k, w, h, ncolors, cpp, comment, transp,
quote, context, len, done, r, g, b, backslash, lu1, lu2; quote, context, len, done, r, g, b, backslash, lu1, lu2;
char *line = NULL; char *line = NULL;
char s[256], tok[128], col[256], *tl; char s[256], tok[128], col[256], *tl;
int lsz = 256; int lsz = 256;
struct _cmap { CMap *cmap = NULL;
char str[6]; Eina_Rbtree *root = NULL;
unsigned char transp;
short r, g, b;
} *cmap = NULL;
short lookup[128 - 32][128 - 32]; short lookup[128 - 32][128 - 32];
int count, pixels; int count, pixels;
done = 0; done = 0;
// transp = -1; // transp = -1;
@ -235,7 +270,7 @@ evas_image_load_file_xpm(Evas_Img_Load_Params *ilp, const char *file, const char
if (!cmap) if (!cmap)
{ {
cmap = malloc(sizeof(struct _cmap) * ncolors); cmap = malloc(sizeof(CMap) * ncolors);
if (!cmap) if (!cmap)
{ {
*error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED; *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
@ -264,6 +299,7 @@ evas_image_load_file_xpm(Evas_Img_Load_Params *ilp, const char *file, const char
len = strlen(line); len = strlen(line);
strncpy(cmap[j].str, line, cpp); strncpy(cmap[j].str, line, cpp);
cmap[j].str[cpp] = 0; cmap[j].str[cpp] = 0;
if (load_data) root = eina_rbtree_inline_insert(root, EINA_RBTREE_GET(&cmap[j]), _cmap_cmp_node_cb, NULL);
for (slen = 0; slen < cpp; slen++) for (slen = 0; slen < cpp; slen++)
{ {
/* fix the ascii of the color string - if its < 32 - just limit to 32 */ /* fix the ascii of the color string - if its < 32 - just limit to 32 */
@ -275,9 +311,11 @@ evas_image_load_file_xpm(Evas_Img_Load_Params *ilp, const char *file, const char
{ {
if (line[k] != ' ') if (line[k] != ' ')
{ {
s[0] = 0; const char *tmp = strchr(&line[k], ' ');
sscanf(&line[k], "%255s", s); slen = tmp ? tmp - &line[k]: 255;
slen = strlen(s);
strncpy(s, &line[k], slen);
s[slen] = 0;
k += slen; k += slen;
if (!strcmp(s, "c")) iscolor = 1; if (!strcmp(s, "c")) iscolor = 1;
if ((!strcmp(s, "m")) || (!strcmp(s, "s")) if ((!strcmp(s, "m")) || (!strcmp(s, "s"))
@ -490,6 +528,8 @@ evas_image_load_file_xpm(Evas_Img_Load_Params *ilp, const char *file, const char
((i < 65536) && (ptr < end) && (line[i])); ((i < 65536) && (ptr < end) && (line[i]));
i++) i++)
{ {
Eina_Rbtree *l;
for (j = 0; j < cpp; j++, i++) for (j = 0; j < cpp; j++, i++)
{ {
col[j] = line[i]; col[j] = line[i];
@ -497,30 +537,26 @@ evas_image_load_file_xpm(Evas_Img_Load_Params *ilp, const char *file, const char
} }
col[j] = 0; col[j] = 0;
i--; i--;
for (j = 0; j < ncolors; j++)
l = eina_rbtree_inline_lookup(root, col, j, _cmap_cmp_key_cb, NULL);
if (l)
{ {
if (!strcmp(col, cmap[j].str)) 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)
{ {
if (cmap[j].transp) *ptr = RGB_JOIN(r, g, b);
{
r = (unsigned char)cmap[j].r;
g = (unsigned char)cmap[j].g;
b = (unsigned char)cmap[j].b;
*ptr = RGB_JOIN(r, g, b);
ptr++;
count++;
}
else
{
r = (unsigned char)cmap[j].r;
g = (unsigned char)cmap[j].g;
b = (unsigned char)cmap[j].b;
*ptr = ARGB_JOIN(0xff, r, g, b);
ptr++;
count++;
}
break;
} }
else
{
*ptr = ARGB_JOIN(0xff, r, g, b);
}
ptr++;
count++;
} }
} }
} }
@ -530,24 +566,26 @@ evas_image_load_file_xpm(Evas_Img_Load_Params *ilp, const char *file, const char
((i < 65536) && (ptr < end) && (line[i])); ((i < 65536) && (ptr < end) && (line[i]));
i++) i++)
{ {
Eina_Rbtree *l;
for (j = 0; j < cpp; j++, i++) for (j = 0; j < cpp; j++, i++)
{ {
col[j] = line[i]; col[j] = line[i];
} }
col[j] = 0; col[j] = 0;
i--; i--;
for (j = 0; j < ncolors; j++)
l = eina_rbtree_inline_lookup(root, col, 0, _cmap_cmp_key_cb, NULL);
if (l)
{ {
if (!strcmp(col, cmap[j].str)) CMap *cm = EINA_RBTREE_CONTAINER_GET(l, CMap);
{
r = (unsigned char)cmap[j].r; r = (unsigned char)cm->r;
g = (unsigned char)cmap[j].g; g = (unsigned char)cm->g;
b = (unsigned char)cmap[j].b; b = (unsigned char)cm->b;
*ptr = ARGB_JOIN(0xff, r, g, b); *ptr = ARGB_JOIN(0xff, r, g, b);
ptr++; ptr++;
count++; count++;
break;
}
} }
} }
} }

View File

@ -31,6 +31,23 @@ static Evas_Image_Load_Func evas_image_load_xpm_func =
static Eina_File *rgb_txt; static Eina_File *rgb_txt;
static void *rgb_txt_map; static void *rgb_txt_map;
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;
}
static void static void
xpm_parse_color(char *color, int *r, int *g, int *b) xpm_parse_color(char *color, int *r, int *g, int *b)
{ {
@ -43,26 +60,15 @@ xpm_parse_color(char *color, int *r, int *g, int *b)
if (color[0] == '#') if (color[0] == '#')
{ {
int len; int len;
char val[32];
len = strlen(color) - 1; len = strlen(color) - 1;
if (len < 96) if (len < 96)
{ {
int i;
len /= 3; len /= 3;
for (i = 0; i < len; i++) *r = _xpm_hexa_int(&(color[1 + (0 * len)]), len);
val[i] = color[1 + i + (0 * len)]; *g = _xpm_hexa_int(&(color[1 + (1 * len)]), len);
val[i] = 0; *b = _xpm_hexa_int(&(color[1 + (2 * len)]), len);
sscanf(val, "%x", r);
for (i = 0; i < len; i++)
val[i] = color[1 + i + (1 * len)];
val[i] = 0;
sscanf(val, "%x", g);
for (i = 0; i < len; i++)
val[i] = color[1 + i + (2 * len)];
val[i] = 0;
sscanf(val, "%x", b);
if (len == 1) if (len == 1)
{ {
*r = (*r << 4) | *r; *r = (*r << 4) | *r;
@ -92,7 +98,7 @@ xpm_parse_color(char *color, int *r, int *g, int *b)
int rr, gg, bb; int rr, gg, bb;
char name[4096]; char name[4096];
/* FIXME: not really efficient */ /* FIXME: not really efficient, should be loaded once in memory with a lookup table */
memcpy(buf, tmp, endline - tmp); memcpy(buf, tmp, endline - tmp);
buf[endline - tmp + 1] = '\0'; buf[endline - tmp + 1] = '\0';
@ -111,29 +117,56 @@ xpm_parse_color(char *color, int *r, int *g, int *b)
} }
} }
typedef struct _CMap CMap;
struct _CMap {
EINA_RBTREE;
short r, g, b;
char str[6];
unsigned char transp;
};
Eina_Rbtree_Direction
_cmap_cmp_node_cb(const Eina_Rbtree *left, const Eina_Rbtree *right, void *data __UNUSED__)
{
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
_cmap_cmp_key_cb(const Eina_Rbtree *node, const void *key, int length __UNUSED__, void *data __UNUSED__)
{
CMap *root = EINA_RBTREE_CONTAINER_GET(node, CMap);
return strcmp(root->str, key);
}
/** FIXME: clean this up and make more efficient **/ /** FIXME: clean this up and make more efficient **/
static Eina_Bool static Eina_Bool
evas_image_load_file_xpm(Image_Entry *ie, const char *file, const char *key __UNUSED__, int load_data, int *error) evas_image_load_file_xpm(Image_Entry *ie, const char *file, const char *key __UNUSED__, int load_data, int *error)
{ {
DATA32 *ptr, *end; DATA32 *ptr, *end, *head;
Eina_File *f; Eina_File *f;
const char *map; const char *map;
size_t length; size_t length;
size_t position; size_t position;
int pc, c, i, j, k, w, h, ncolors, cpp, comment, transp, int pc, c, i, j, k, w, h, ncolors, cpp, comment, transp,
quote, context, len, done, r, g, b, backslash, lu1, lu2; quote, context, len, done, r, g, b, backslash, lu1, lu2;
char *line = NULL; char *line = NULL;
char s[256], tok[128], col[256], *tl; char s[256], tok[128], col[256], *tl;
int lsz = 256; int lsz = 256;
struct _cmap { CMap *cmap = NULL;
char str[6]; Eina_Rbtree *root = NULL;
unsigned char transp;
short r, g, b;
} *cmap = NULL;
short lookup[128 - 32][128 - 32]; short lookup[128 - 32][128 - 32];
int count, pixels; int count, pixels;
done = 0; done = 0;
// transp = -1; // transp = -1;
@ -264,7 +297,7 @@ evas_image_load_file_xpm(Image_Entry *ie, const char *file, const char *key __UN
if (!cmap) if (!cmap)
{ {
cmap = malloc(sizeof(struct _cmap) * ncolors); cmap = malloc(sizeof(CMap) * ncolors);
if (!cmap) if (!cmap)
{ {
*error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED; *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
@ -293,6 +326,7 @@ evas_image_load_file_xpm(Image_Entry *ie, const char *file, const char *key __UN
len = strlen(line); len = strlen(line);
strncpy(cmap[j].str, line, cpp); strncpy(cmap[j].str, line, cpp);
cmap[j].str[cpp] = 0; cmap[j].str[cpp] = 0;
if (load_data) root = eina_rbtree_inline_insert(root, EINA_RBTREE_GET(&cmap[j]), _cmap_cmp_node_cb, NULL);
for (slen = 0; slen < cpp; slen++) for (slen = 0; slen < cpp; slen++)
{ {
/* fix the ascii of the color string - if its < 32 - just limit to 32 */ /* fix the ascii of the color string - if its < 32 - just limit to 32 */
@ -304,9 +338,11 @@ evas_image_load_file_xpm(Image_Entry *ie, const char *file, const char *key __UN
{ {
if (line[k] != ' ') if (line[k] != ' ')
{ {
s[0] = 0; const char *tmp = strchr(&line[k], ' ');
sscanf(&line[k], "%255s", s); slen = tmp ? tmp - &line[k]: 255;
slen = strlen(s);
strncpy(s, &line[k], slen);
s[slen] = 0;
k += slen; k += slen;
if (slen == 1 && *s == 'c') iscolor = 1; if (slen == 1 && *s == 'c') iscolor = 1;
if ((slen == 1 && ((s[0] == 'm') || (s[0] == 's') || (s[0] == 'g') || (s[0] == 'c'))) || if ((slen == 1 && ((s[0] == 'm') || (s[0] == 's') || (s[0] == 'g') || (s[0] == 'c'))) ||
@ -367,7 +403,7 @@ evas_image_load_file_xpm(Image_Entry *ie, const char *file, const char *key __UN
} }
} }
j++; j++;
if (j >= ncolors) if (load_data && j >= ncolors)
{ {
if (cpp == 1) if (cpp == 1)
{ {
@ -388,6 +424,7 @@ evas_image_load_file_xpm(Image_Entry *ie, const char *file, const char *key __UN
{ {
evas_cache_image_surface_alloc(ie, w, h); evas_cache_image_surface_alloc(ie, w, h);
ptr = evas_cache_image_pixels(ie); ptr = evas_cache_image_pixels(ie);
head = ptr;
if (!ptr) if (!ptr)
{ {
*error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED; *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
@ -520,6 +557,8 @@ evas_image_load_file_xpm(Image_Entry *ie, const char *file, const char *key __UN
((i < 65536) && (ptr < end) && (line[i])); ((i < 65536) && (ptr < end) && (line[i]));
i++) i++)
{ {
Eina_Rbtree *l;
for (j = 0; j < cpp; j++, i++) for (j = 0; j < cpp; j++, i++)
{ {
col[j] = line[i]; col[j] = line[i];
@ -527,30 +566,26 @@ evas_image_load_file_xpm(Image_Entry *ie, const char *file, const char *key __UN
} }
col[j] = 0; col[j] = 0;
i--; i--;
for (j = 0; j < ncolors; j++)
l = eina_rbtree_inline_lookup(root, col, j, _cmap_cmp_key_cb, NULL);
if (l)
{ {
if (!strcmp(col, cmap[j].str)) 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)
{ {
if (cmap[j].transp) *ptr = RGB_JOIN(r, g, b);
{
r = (unsigned char)cmap[j].r;
g = (unsigned char)cmap[j].g;
b = (unsigned char)cmap[j].b;
*ptr = RGB_JOIN(r, g, b);
ptr++;
count++;
}
else
{
r = (unsigned char)cmap[j].r;
g = (unsigned char)cmap[j].g;
b = (unsigned char)cmap[j].b;
*ptr = ARGB_JOIN(0xff, r, g, b);
ptr++;
count++;
}
break;
} }
else
{
*ptr = ARGB_JOIN(0xff, r, g, b);
}
ptr++;
count++;
} }
} }
} }
@ -560,24 +595,26 @@ evas_image_load_file_xpm(Image_Entry *ie, const char *file, const char *key __UN
((i < 65536) && (ptr < end) && (line[i])); ((i < 65536) && (ptr < end) && (line[i]));
i++) i++)
{ {
Eina_Rbtree *l;
for (j = 0; j < cpp; j++, i++) for (j = 0; j < cpp; j++, i++)
{ {
col[j] = line[i]; col[j] = line[i];
} }
col[j] = 0; col[j] = 0;
i--; i--;
for (j = 0; j < ncolors; j++)
l = eina_rbtree_inline_lookup(root, col, 0, _cmap_cmp_key_cb, NULL);
if (l)
{ {
if (!strcmp(col, cmap[j].str)) CMap *cm = EINA_RBTREE_CONTAINER_GET(l, CMap);
{
r = (unsigned char)cmap[j].r; r = (unsigned char)cm->r;
g = (unsigned char)cmap[j].g; g = (unsigned char)cm->g;
b = (unsigned char)cmap[j].b; b = (unsigned char)cm->b;
*ptr = ARGB_JOIN(0xff, r, g, b); *ptr = ARGB_JOIN(0xff, r, g, b);
ptr++; ptr++;
count++; count++;
break;
}
} }
} }
} }
@ -610,7 +647,7 @@ evas_image_load_file_xpm(Image_Entry *ie, const char *file, const char *key __UN
if (!tl) break; if (!tl) break;
line = tl; line = tl;
} }
if (((ptr) && ((ptr - evas_cache_image_pixels(ie)) >= (w * h * (int)sizeof(DATA32)))) || if (((ptr) && ((ptr - head) >= (w * h * (int)sizeof(DATA32)))) ||
((context > 1) && (count >= pixels))) ((context > 1) && (count >= pixels)))
break; break;
} }