This is an automated email from the git hooks/post-receive script.
git pushed a commit to branch master
in repository legacy-imlib2.
View the commit online.
commit 33ab27e323f9ee145cd0d13276d0a65994e24cac
Author: Kim Woelders <k...@woelders.dk>
AuthorDate: Fri Mar 22 14:11:11 2024 +0100
XPM loader: Major overhaul
Simplifying things somewhat, IMO.
---
src/modules/loaders/loader_xpm.c | 440 ++++++++++++++++++++-------------------
1 file changed, 224 insertions(+), 216 deletions(-)
diff --git a/src/modules/loaders/loader_xpm.c b/src/modules/loaders/loader_xpm.c
index b549a43..37487f2 100644
--- a/src/modules/loaders/loader_xpm.c
+++ b/src/modules/loaders/loader_xpm.c
@@ -1,6 +1,8 @@
#include "config.h"
#include "Imlib2_Loader.h"
+#include <stdbool.h>
+
#define DBG_PFX "LDR-xpm"
static const char *const _formats[] = { "xpm" };
@@ -35,7 +37,7 @@ static FILE *rgb_txt = NULL;
static uint32_t
xpm_parse_color(const char *color)
{
- char buf[4096];
+ char buf[256];
int a, r, g, b;
a = 0xff;
@@ -45,7 +47,6 @@ xpm_parse_color(const char *color)
if (color[0] == '#')
{
int len;
- char val[32];
len = strlen(color) - 1;
if (len < 96)
@@ -54,17 +55,17 @@ xpm_parse_color(const char *color)
len /= 3;
for (i = 0; i < len; i++)
- val[i] = color[1 + i + (0 * len)];
- val[i] = 0;
- sscanf(val, "%x", &r);
+ buf[i] = color[1 + i + (0 * len)];
+ buf[i] = '\0';
+ sscanf(buf, "%x", &r);
for (i = 0; i < len; i++)
- val[i] = color[1 + i + (1 * len)];
- val[i] = 0;
- sscanf(val, "%x", &g);
+ buf[i] = color[1 + i + (1 * len)];
+ buf[i] = '\0';
+ sscanf(buf, "%x", &g);
for (i = 0; i < len; i++)
- val[i] = color[1 + i + (2 * len)];
- val[i] = 0;
- sscanf(val, "%x", &b);
+ buf[i] = color[1 + i + (2 * len)];
+ buf[i] = '\0';
+ sscanf(buf, "%x", &b);
if (len == 1)
{
r = (r << 4) | r;
@@ -96,12 +97,12 @@ xpm_parse_color(const char *color)
goto done;
fseek(rgb_txt, 0, SEEK_SET);
- while (fgets(buf, 4000, rgb_txt))
+ while (fgets(buf, sizeof(buf), rgb_txt))
{
if (buf[0] != '!')
{
int rr, gg, bb;
- char name[4096];
+ char name[256];
sscanf(buf, "%i %i %i %[^\n]", &rr, &gg, &bb, name);
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;
}
+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
_load(ImlibImage *im, int load_data)
{
- int rc;
+ int rc, err;
uint32_t *ptr;
- int pc, c, i, j, k, w, h, ncolors, cpp;
- int comment, transp, quote, context, len, done, backslash;
- char *line, s[256], tok[256], col[256];
+ int pc, c, i, j, w, h, ncolors, cpp;
+ int context, len;
+ char *line;
int lsz = 256;
cmap_t *cmap;
short lookup[128 - 32][128 - 32];
int count, pixels;
int last_row = 0;
+ bool comment, quote, backslash, transp;
rc = LOAD_FAIL;
- done = 0;
- transp = -1;
line = NULL;
cmap = NULL;
@@ -191,12 +256,12 @@ _load(ImlibImage *im, int load_data)
j = 0;
w = 10;
h = 10;
+ transp = false;
ncolors = 0;
cpp = 0;
ptr = NULL;
c = ' ';
- comment = 0;
- quote = 0;
+ comment = quote = backslash = false;
context = 0;
pixels = 0;
count = 0;
@@ -205,9 +270,8 @@ _load(ImlibImage *im, int load_data)
QUIT_WITH_RC(LOAD_OOM);
len = 0;
- backslash = 0;
memset(lookup, 0, sizeof(lookup));
- while (!done)
+ for (;;)
{
pc = c;
c = mm_getc();
@@ -217,230 +281,174 @@ _load(ImlibImage *im, int load_data)
if (!quote)
{
if ((pc == '/') && (c == '*'))
- comment = 1;
+ comment = true;
else if ((pc == '*') && (c == '/') && (comment))
- comment = 0;
+ comment = false;
}
if (comment)
continue;
- if ((!quote) && (c == '"'))
- {
- quote = 1;
- len = 0;
- }
- else if ((quote) && (c == '"'))
- {
- line[len] = 0;
- quote = 0;
- if (context == 0)
- {
- /* Header */
- sscanf(line, "%i %i %i %i", &w, &h, &ncolors, &cpp);
- if ((ncolors > 32766) || (ncolors < 1))
- {
- E("XPM files with colors > 32766 or < 1 not supported\n");
- goto quit;
- }
- if ((cpp > 5) || (cpp < 1))
- {
- E("XPM files with characters per pixel > 5 or < 1 not supported\n");
- goto quit;
- }
- if (!IMAGE_DIMENSIONS_OK(w, h))
- {
- E("Invalid image dimension: %dx%d\n", w, h);
- goto quit;
- }
- im->w = w;
- im->h = h;
-
- cmap = calloc(ncolors, sizeof(cmap_t));
- if (!cmap)
- QUIT_WITH_RC(LOAD_OOM);
-
- pixels = w * h;
-
- j = 0;
- context++;
- }
- else if (context == 1)
- {
- /* Color Table */
- if (j < ncolors)
- {
- int slen;
- int hascolor;
-
- hascolor = 0;
- tok[0] = 0;
- col[0] = 0;
- s[0] = 0;
- if (len < cpp)
- goto quit;
- strncpy(cmap[j].str, line, cpp);
- for (k = cpp; k < len; k++)
- {
- if (line[k] == ' ')
- continue;
-
- s[0] = 0;
- sscanf(&line[k], "%255s", s);
- 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)
- for (i = 0; i < ncolors; i++)
- lookup[(int)cmap[i].str[0] - 32][0] = i;
- else if (cpp == 2)
- for (i = 0; i < ncolors; i++)
- lookup[(int)cmap[i].str[0] -
- 32][(int)cmap[i].str[1] - 32] = i;
- else
- qsort(cmap, ncolors, sizeof(cmap_t), xpm_cmap_sort);
- context++;
-
- im->has_alpha = transp >= 0;
-
- if (!load_data)
- QUIT_WITH_RC(LOAD_SUCCESS);
-
- ptr = __imlib_AllocateData(im);
- if (!ptr)
- QUIT_WITH_RC(LOAD_OOM);
- }
- }
- else
- {
- /* Image Data */
-
- if (cpp == 1)
- {
-#define CM1(c0) (&cmap[lookup[c0 - ' '][0]])
- for (i = 0; count < pixels && i < len; i++)
- {
- *ptr++ = CM1(line[i])->pixel;
- count++;
- }
- }
- else if (cpp == 2)
- {
-#define CM2(c0, c1) (&cmap[lookup[c0 - ' '][c1 - ' ']])
- for (i = 0; count < pixels && i < len - 1; i += 2)
- {
- *ptr++ = CM2(line[i], line[i + 1])->pixel;
- count++;
- }
- }
- else
- {
- for (i = 0; count < pixels && i < len - (cpp - 1); i += cpp)
- {
- *ptr++ = xpm_cmap_lookup(cmap, ncolors, cpp, &line[i]);
- count++;
- }
- }
-
- i = count / w;
- if (im->lc && i > last_row)
- {
- if (__imlib_LoadProgressRows(im, last_row, i - last_row))
- QUIT_WITH_RC(LOAD_BREAK);
-
- last_row = i;
- }
- }
- }
-
/* Scan in line from XPM file */
- if ((quote) && (c != '"'))
+ if (!quote)
{
+ /* Waiting for start quote */
+ if (c != '"')
+ continue;
+ /* Got start quote */
+ quote = true;
+ len = 0;
+ continue;
+ }
+
+ if (c != '"')
+ {
+ /* Waiting for end quote */
if (c < 32)
c = 32;
else if (c > 127)
c = 127;
+
if (c == '\\')
{
- if (++backslash < 2)
+ if (!backslash)
{
line[len++] = c;
+ backslash = true;
}
else
{
- backslash = 0;
+ backslash = false;
}
}
else
{
- backslash = 0;
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;
}
- if (len >= lsz)
+ /* Got end quote */
+ line[len] = '\0';
+ quote = false;
+
+ if (context == 0)
{
- char *nline;
+ /* Header */
+ DL("Header line: '%s'\n", line);
+ 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))
+ {
+ E("XPM files with colors > 32766 or < 1 not supported\n");
+ goto quit;
+ }
+ if ((cpp > 5) || (cpp < 1))
+ {
+ E("XPM files with characters per pixel > 5 or < 1 not supported\n");
+ goto quit;
+ }
+ if (!IMAGE_DIMENSIONS_OK(w, h))
+ {
+ E("Invalid image dimension: %dx%d\n", w, h);
+ goto quit;
+ }
+ im->w = w;
+ im->h = h;
- lsz += 256;
- nline = realloc(line, lsz);
- if (!nline)
+ cmap = calloc(ncolors, sizeof(cmap_t));
+ if (!cmap)
QUIT_WITH_RC(LOAD_OOM);
- line = nline;
- }
- if ((context > 1) && (count >= pixels))
- done = 1;
+ pixels = w * h;
+
+ j = 0;
+ context = 1;
+ }
+ else if (context == 1)
+ {
+ /* Color Table */
+ DL("Coltbl line: '%s'\n", line);
+
+ err = xpm_parse_cmap_line(line, len, cpp, &cmap[j]);
+ if (err)
+ goto quit;
+
+ if (cmap[j].transp)
+ transp = true;
+
+ j++;
+ if (j < ncolors)
+ continue;
+
+ /* Got all colors */
+#define LU(c0, c1) lookup[(int)(c0 - ' ')][(int)(c1 - ' ')]
+
+ if (cpp == 1)
+ for (i = 0; i < ncolors; i++)
+ LU(cmap[i].str[0], ' ') = i;
+ else if (cpp == 2)
+ for (i = 0; i < ncolors; i++)
+ LU(cmap[i].str[0], cmap[i].str[1]) = i;
+ else
+ qsort(cmap, ncolors, sizeof(cmap_t), xpm_cmap_sort);
+
+ im->has_alpha = transp;
+
+ if (!load_data)
+ QUIT_WITH_RC(LOAD_SUCCESS);
+
+ ptr = __imlib_AllocateData(im);
+ if (!ptr)
+ QUIT_WITH_RC(LOAD_OOM);
+
+ context = 2;
+ }
+ else
+ {
+ /* Image Data */
+ DL("Data line: '%s'\n", line);
+
+ if (cpp == 1)
+ {
+ for (i = 0; count < pixels && i <= len - cpp; i += cpp, count++)
+ *ptr++ = cmap[LU(line[i], ' ')].pixel;
+ }
+ else if (cpp == 2)
+ {
+ for (i = 0; count < pixels && i <= len - cpp; i += cpp, count++)
+ *ptr++ = cmap[LU(line[i], line[i + 1])].pixel;
+ }
+ else
+ {
+ for (i = 0; count < pixels && i <= len - cpp; i += cpp, count++)
+ *ptr++ = xpm_cmap_lookup(cmap, ncolors, cpp, &line[i]);
+ }
+
+ i = count / w;
+ if (im->lc && i > last_row)
+ {
+ if (__imlib_LoadProgressRows(im, last_row, i - last_row))
+ QUIT_WITH_RC(LOAD_BREAK);
+
+ last_row = i;
+ }
+
+ if (count >= pixels)
+ break;
+ }
}
if (!im->data || !cmap)
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.