XPM loader: Major overhaul
Simplifying things somewhat, IMO.
This commit is contained in:
parent
13d311561d
commit
33ab27e323
|
@ -1,6 +1,8 @@
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "Imlib2_Loader.h"
|
#include "Imlib2_Loader.h"
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
#define DBG_PFX "LDR-xpm"
|
#define DBG_PFX "LDR-xpm"
|
||||||
|
|
||||||
static const char *const _formats[] = { "xpm" };
|
static const char *const _formats[] = { "xpm" };
|
||||||
|
@ -35,7 +37,7 @@ static FILE *rgb_txt = NULL;
|
||||||
static uint32_t
|
static uint32_t
|
||||||
xpm_parse_color(const char *color)
|
xpm_parse_color(const char *color)
|
||||||
{
|
{
|
||||||
char buf[4096];
|
char buf[256];
|
||||||
int a, r, g, b;
|
int a, r, g, b;
|
||||||
|
|
||||||
a = 0xff;
|
a = 0xff;
|
||||||
|
@ -45,7 +47,6 @@ xpm_parse_color(const char *color)
|
||||||
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)
|
||||||
|
@ -54,17 +55,17 @@ xpm_parse_color(const char *color)
|
||||||
|
|
||||||
len /= 3;
|
len /= 3;
|
||||||
for (i = 0; i < len; i++)
|
for (i = 0; i < len; i++)
|
||||||
val[i] = color[1 + i + (0 * len)];
|
buf[i] = color[1 + i + (0 * len)];
|
||||||
val[i] = 0;
|
buf[i] = '\0';
|
||||||
sscanf(val, "%x", &r);
|
sscanf(buf, "%x", &r);
|
||||||
for (i = 0; i < len; i++)
|
for (i = 0; i < len; i++)
|
||||||
val[i] = color[1 + i + (1 * len)];
|
buf[i] = color[1 + i + (1 * len)];
|
||||||
val[i] = 0;
|
buf[i] = '\0';
|
||||||
sscanf(val, "%x", &g);
|
sscanf(buf, "%x", &g);
|
||||||
for (i = 0; i < len; i++)
|
for (i = 0; i < len; i++)
|
||||||
val[i] = color[1 + i + (2 * len)];
|
buf[i] = color[1 + i + (2 * len)];
|
||||||
val[i] = 0;
|
buf[i] = '\0';
|
||||||
sscanf(val, "%x", &b);
|
sscanf(buf, "%x", &b);
|
||||||
if (len == 1)
|
if (len == 1)
|
||||||
{
|
{
|
||||||
r = (r << 4) | r;
|
r = (r << 4) | r;
|
||||||
|
@ -96,12 +97,12 @@ xpm_parse_color(const char *color)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
fseek(rgb_txt, 0, SEEK_SET);
|
fseek(rgb_txt, 0, SEEK_SET);
|
||||||
while (fgets(buf, 4000, rgb_txt))
|
while (fgets(buf, sizeof(buf), rgb_txt))
|
||||||
{
|
{
|
||||||
if (buf[0] != '!')
|
if (buf[0] != '!')
|
||||||
{
|
{
|
||||||
int rr, gg, bb;
|
int rr, gg, bb;
|
||||||
char name[4096];
|
char name[256];
|
||||||
|
|
||||||
sscanf(buf, "%i %i %i %[^\n]", &rr, &gg, &bb, name);
|
sscanf(buf, "%i %i %i %[^\n]", &rr, &gg, &bb, name);
|
||||||
if (!strcasecmp(name, color))
|
if (!strcasecmp(name, color))
|
||||||
|
@ -160,23 +161,87 @@ xpm_cmap_lookup(const cmap_t *cmap, int nc, int cpp, const char *s)
|
||||||
return cmap[i1].pixel;
|
return cmap[i1].pixel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
xpm_parse_cmap_line(const char *line, int len, int cpp, cmap_t *cme)
|
||||||
|
{
|
||||||
|
char s[256], tag[256], col[256];
|
||||||
|
int i, nr;
|
||||||
|
bool is_tag, is_col, is_eol, hascolor;
|
||||||
|
|
||||||
|
if (len < cpp)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
is_tag = is_col = is_eol = false;
|
||||||
|
hascolor = false;
|
||||||
|
tag[0] = '\0';
|
||||||
|
col[0] = '\0';
|
||||||
|
|
||||||
|
strncpy(cme->str, line, cpp);
|
||||||
|
|
||||||
|
for (i = cpp; i < len;)
|
||||||
|
{
|
||||||
|
s[0] = '\0';
|
||||||
|
nr = 0;
|
||||||
|
sscanf(&line[i], "%255s %n", s, &nr);
|
||||||
|
i += nr;
|
||||||
|
is_tag = !strcmp(s, "c") || !strcmp(s, "m") || !strcmp(s, "s") ||
|
||||||
|
!strcmp(s, "g4") || !strcmp(s, "g");
|
||||||
|
is_eol = i >= len;
|
||||||
|
|
||||||
|
if (!is_tag)
|
||||||
|
{
|
||||||
|
/* Not tag - append to value */
|
||||||
|
if (col[0])
|
||||||
|
{
|
||||||
|
if (strlen(col) < (sizeof(col) - 2))
|
||||||
|
strcat(col, " ");
|
||||||
|
else
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (strlen(col) + strlen(s) < (sizeof(col) - 1))
|
||||||
|
strcat(col, s);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((is_tag || is_eol) && col[0])
|
||||||
|
{
|
||||||
|
/* Next tag or end of line - process color */
|
||||||
|
is_col = !strcmp(tag, "c");
|
||||||
|
if ((is_col || !cme->assigned) && !hascolor)
|
||||||
|
{
|
||||||
|
cme->pixel = xpm_parse_color(col);
|
||||||
|
cme->assigned = 1;
|
||||||
|
cme->transp = cme->pixel == 0x00000000;
|
||||||
|
if (is_col)
|
||||||
|
hascolor = true;
|
||||||
|
DL(" Coltbl tag='%s' col='%s' hasc=%d tr=%d %08x\n",
|
||||||
|
tag, col, hascolor, cme->transp, cme->pixel);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Starting new tag */
|
||||||
|
strcpy(tag, s);
|
||||||
|
col[0] = '\0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
_load(ImlibImage *im, int load_data)
|
_load(ImlibImage *im, int load_data)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc, err;
|
||||||
uint32_t *ptr;
|
uint32_t *ptr;
|
||||||
int pc, c, i, j, k, w, h, ncolors, cpp;
|
int pc, c, i, j, w, h, ncolors, cpp;
|
||||||
int comment, transp, quote, context, len, done, backslash;
|
int context, len;
|
||||||
char *line, s[256], tok[256], col[256];
|
char *line;
|
||||||
int lsz = 256;
|
int lsz = 256;
|
||||||
cmap_t *cmap;
|
cmap_t *cmap;
|
||||||
short lookup[128 - 32][128 - 32];
|
short lookup[128 - 32][128 - 32];
|
||||||
int count, pixels;
|
int count, pixels;
|
||||||
int last_row = 0;
|
int last_row = 0;
|
||||||
|
bool comment, quote, backslash, transp;
|
||||||
|
|
||||||
rc = LOAD_FAIL;
|
rc = LOAD_FAIL;
|
||||||
done = 0;
|
|
||||||
transp = -1;
|
|
||||||
line = NULL;
|
line = NULL;
|
||||||
cmap = NULL;
|
cmap = NULL;
|
||||||
|
|
||||||
|
@ -191,12 +256,12 @@ _load(ImlibImage *im, int load_data)
|
||||||
j = 0;
|
j = 0;
|
||||||
w = 10;
|
w = 10;
|
||||||
h = 10;
|
h = 10;
|
||||||
|
transp = false;
|
||||||
ncolors = 0;
|
ncolors = 0;
|
||||||
cpp = 0;
|
cpp = 0;
|
||||||
ptr = NULL;
|
ptr = NULL;
|
||||||
c = ' ';
|
c = ' ';
|
||||||
comment = 0;
|
comment = quote = backslash = false;
|
||||||
quote = 0;
|
|
||||||
context = 0;
|
context = 0;
|
||||||
pixels = 0;
|
pixels = 0;
|
||||||
count = 0;
|
count = 0;
|
||||||
|
@ -205,9 +270,8 @@ _load(ImlibImage *im, int load_data)
|
||||||
QUIT_WITH_RC(LOAD_OOM);
|
QUIT_WITH_RC(LOAD_OOM);
|
||||||
len = 0;
|
len = 0;
|
||||||
|
|
||||||
backslash = 0;
|
|
||||||
memset(lookup, 0, sizeof(lookup));
|
memset(lookup, 0, sizeof(lookup));
|
||||||
while (!done)
|
for (;;)
|
||||||
{
|
{
|
||||||
pc = c;
|
pc = c;
|
||||||
c = mm_getc();
|
c = mm_getc();
|
||||||
|
@ -217,27 +281,75 @@ _load(ImlibImage *im, int load_data)
|
||||||
if (!quote)
|
if (!quote)
|
||||||
{
|
{
|
||||||
if ((pc == '/') && (c == '*'))
|
if ((pc == '/') && (c == '*'))
|
||||||
comment = 1;
|
comment = true;
|
||||||
else if ((pc == '*') && (c == '/') && (comment))
|
else if ((pc == '*') && (c == '/') && (comment))
|
||||||
comment = 0;
|
comment = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (comment)
|
if (comment)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if ((!quote) && (c == '"'))
|
/* Scan in line from XPM file */
|
||||||
|
if (!quote)
|
||||||
{
|
{
|
||||||
quote = 1;
|
/* Waiting for start quote */
|
||||||
|
if (c != '"')
|
||||||
|
continue;
|
||||||
|
/* Got start quote */
|
||||||
|
quote = true;
|
||||||
len = 0;
|
len = 0;
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
else if ((quote) && (c == '"'))
|
|
||||||
|
if (c != '"')
|
||||||
{
|
{
|
||||||
line[len] = 0;
|
/* Waiting for end quote */
|
||||||
quote = 0;
|
if (c < 32)
|
||||||
|
c = 32;
|
||||||
|
else if (c > 127)
|
||||||
|
c = 127;
|
||||||
|
|
||||||
|
if (c == '\\')
|
||||||
|
{
|
||||||
|
if (!backslash)
|
||||||
|
{
|
||||||
|
line[len++] = c;
|
||||||
|
backslash = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
backslash = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
line[len++] = c;
|
||||||
|
backslash = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (len >= lsz)
|
||||||
|
{
|
||||||
|
char *nline;
|
||||||
|
|
||||||
|
lsz += 256;
|
||||||
|
nline = realloc(line, lsz);
|
||||||
|
if (!nline)
|
||||||
|
QUIT_WITH_RC(LOAD_OOM);
|
||||||
|
line = nline;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Got end quote */
|
||||||
|
line[len] = '\0';
|
||||||
|
quote = false;
|
||||||
|
|
||||||
if (context == 0)
|
if (context == 0)
|
||||||
{
|
{
|
||||||
/* Header */
|
/* Header */
|
||||||
|
DL("Header line: '%s'\n", line);
|
||||||
sscanf(line, "%i %i %i %i", &w, &h, &ncolors, &cpp);
|
sscanf(line, "%i %i %i %i", &w, &h, &ncolors, &cpp);
|
||||||
|
D("Header: WxH=%dx%d ncol=%d cpp=%d\n", w, h, ncolors, cpp);
|
||||||
if ((ncolors > 32766) || (ncolors < 1))
|
if ((ncolors > 32766) || (ncolors < 1))
|
||||||
{
|
{
|
||||||
E("XPM files with colors > 32766 or < 1 not supported\n");
|
E("XPM files with colors > 32766 or < 1 not supported\n");
|
||||||
|
@ -263,95 +375,37 @@ _load(ImlibImage *im, int load_data)
|
||||||
pixels = w * h;
|
pixels = w * h;
|
||||||
|
|
||||||
j = 0;
|
j = 0;
|
||||||
context++;
|
context = 1;
|
||||||
}
|
}
|
||||||
else if (context == 1)
|
else if (context == 1)
|
||||||
{
|
{
|
||||||
/* Color Table */
|
/* Color Table */
|
||||||
if (j < ncolors)
|
DL("Coltbl line: '%s'\n", line);
|
||||||
{
|
|
||||||
int slen;
|
|
||||||
int hascolor;
|
|
||||||
|
|
||||||
hascolor = 0;
|
err = xpm_parse_cmap_line(line, len, cpp, &cmap[j]);
|
||||||
tok[0] = 0;
|
if (err)
|
||||||
col[0] = 0;
|
|
||||||
s[0] = 0;
|
|
||||||
if (len < cpp)
|
|
||||||
goto quit;
|
goto quit;
|
||||||
strncpy(cmap[j].str, line, cpp);
|
|
||||||
for (k = cpp; k < len; k++)
|
if (cmap[j].transp)
|
||||||
{
|
transp = true;
|
||||||
if (line[k] == ' ')
|
|
||||||
|
j++;
|
||||||
|
if (j < ncolors)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
s[0] = 0;
|
/* Got all colors */
|
||||||
sscanf(&line[k], "%255s", s);
|
#define LU(c0, c1) lookup[(int)(c0 - ' ')][(int)(c1 - ' ')]
|
||||||
slen = strlen(s);
|
|
||||||
k += slen;
|
|
||||||
if ((!strcmp(s, "m")) || (!strcmp(s, "s")) ||
|
|
||||||
(!strcmp(s, "g4")) || (!strcmp(s, "g")) ||
|
|
||||||
(!strcmp(s, "c")) || (k >= len))
|
|
||||||
{
|
|
||||||
if (k >= len)
|
|
||||||
{
|
|
||||||
if (col[0])
|
|
||||||
{
|
|
||||||
if (strlen(col) < (sizeof(col) - 2))
|
|
||||||
strcat(col, " ");
|
|
||||||
else
|
|
||||||
done = 1;
|
|
||||||
}
|
|
||||||
if (strlen(col) + strlen(s) < (sizeof(col) - 1))
|
|
||||||
strcat(col, s);
|
|
||||||
}
|
|
||||||
if (col[0])
|
|
||||||
{
|
|
||||||
if ((!cmap[j].assigned || !strcmp(tok, "c")) &&
|
|
||||||
(!hascolor))
|
|
||||||
{
|
|
||||||
cmap[j].pixel = xpm_parse_color(col);
|
|
||||||
cmap[j].assigned = 1;
|
|
||||||
if ((cmap[j].pixel >> 24) != 0xff)
|
|
||||||
cmap[j].transp = 1;
|
|
||||||
if (!strcmp(tok, "c"))
|
|
||||||
hascolor = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
strcpy(tok, s);
|
|
||||||
col[0] = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (col[0])
|
|
||||||
{
|
|
||||||
if (strlen(col) < (sizeof(col) - 2))
|
|
||||||
strcat(col, " ");
|
|
||||||
else
|
|
||||||
done = 1;
|
|
||||||
}
|
|
||||||
if (strlen(col) + strlen(s) < (sizeof(col) - 1))
|
|
||||||
strcat(col, s);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (cmap[j].transp)
|
|
||||||
transp = 1;
|
|
||||||
}
|
|
||||||
j++;
|
|
||||||
if (j >= ncolors)
|
|
||||||
{
|
|
||||||
if (cpp == 1)
|
if (cpp == 1)
|
||||||
for (i = 0; i < ncolors; i++)
|
for (i = 0; i < ncolors; i++)
|
||||||
lookup[(int)cmap[i].str[0] - 32][0] = i;
|
LU(cmap[i].str[0], ' ') = i;
|
||||||
else if (cpp == 2)
|
else if (cpp == 2)
|
||||||
for (i = 0; i < ncolors; i++)
|
for (i = 0; i < ncolors; i++)
|
||||||
lookup[(int)cmap[i].str[0] -
|
LU(cmap[i].str[0], cmap[i].str[1]) = i;
|
||||||
32][(int)cmap[i].str[1] - 32] = i;
|
|
||||||
else
|
else
|
||||||
qsort(cmap, ncolors, sizeof(cmap_t), xpm_cmap_sort);
|
qsort(cmap, ncolors, sizeof(cmap_t), xpm_cmap_sort);
|
||||||
context++;
|
|
||||||
|
|
||||||
im->has_alpha = transp >= 0;
|
im->has_alpha = transp;
|
||||||
|
|
||||||
if (!load_data)
|
if (!load_data)
|
||||||
QUIT_WITH_RC(LOAD_SUCCESS);
|
QUIT_WITH_RC(LOAD_SUCCESS);
|
||||||
|
@ -359,37 +413,28 @@ _load(ImlibImage *im, int load_data)
|
||||||
ptr = __imlib_AllocateData(im);
|
ptr = __imlib_AllocateData(im);
|
||||||
if (!ptr)
|
if (!ptr)
|
||||||
QUIT_WITH_RC(LOAD_OOM);
|
QUIT_WITH_RC(LOAD_OOM);
|
||||||
}
|
|
||||||
|
context = 2;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Image Data */
|
/* Image Data */
|
||||||
|
DL("Data line: '%s'\n", line);
|
||||||
|
|
||||||
if (cpp == 1)
|
if (cpp == 1)
|
||||||
{
|
{
|
||||||
#define CM1(c0) (&cmap[lookup[c0 - ' '][0]])
|
for (i = 0; count < pixels && i <= len - cpp; i += cpp, count++)
|
||||||
for (i = 0; count < pixels && i < len; i++)
|
*ptr++ = cmap[LU(line[i], ' ')].pixel;
|
||||||
{
|
|
||||||
*ptr++ = CM1(line[i])->pixel;
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (cpp == 2)
|
else if (cpp == 2)
|
||||||
{
|
{
|
||||||
#define CM2(c0, c1) (&cmap[lookup[c0 - ' '][c1 - ' ']])
|
for (i = 0; count < pixels && i <= len - cpp; i += cpp, count++)
|
||||||
for (i = 0; count < pixels && i < len - 1; i += 2)
|
*ptr++ = cmap[LU(line[i], line[i + 1])].pixel;
|
||||||
{
|
|
||||||
*ptr++ = CM2(line[i], line[i + 1])->pixel;
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
for (i = 0; count < pixels && i < len - (cpp - 1); i += cpp)
|
for (i = 0; count < pixels && i <= len - cpp; i += cpp, count++)
|
||||||
{
|
|
||||||
*ptr++ = xpm_cmap_lookup(cmap, ncolors, cpp, &line[i]);
|
*ptr++ = xpm_cmap_lookup(cmap, ncolors, cpp, &line[i]);
|
||||||
count++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
i = count / w;
|
i = count / w;
|
||||||
|
@ -400,47 +445,10 @@ _load(ImlibImage *im, int load_data)
|
||||||
|
|
||||||
last_row = i;
|
last_row = i;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Scan in line from XPM file */
|
if (count >= pixels)
|
||||||
if ((quote) && (c != '"'))
|
break;
|
||||||
{
|
|
||||||
if (c < 32)
|
|
||||||
c = 32;
|
|
||||||
else if (c > 127)
|
|
||||||
c = 127;
|
|
||||||
if (c == '\\')
|
|
||||||
{
|
|
||||||
if (++backslash < 2)
|
|
||||||
{
|
|
||||||
line[len++] = c;
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
backslash = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
backslash = 0;
|
|
||||||
line[len++] = c;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (len >= lsz)
|
|
||||||
{
|
|
||||||
char *nline;
|
|
||||||
|
|
||||||
lsz += 256;
|
|
||||||
nline = realloc(line, lsz);
|
|
||||||
if (!nline)
|
|
||||||
QUIT_WITH_RC(LOAD_OOM);
|
|
||||||
line = nline;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((context > 1) && (count >= pixels))
|
|
||||||
done = 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!im->data || !cmap)
|
if (!im->data || !cmap)
|
||||||
|
|
Loading…
Reference in New Issue