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.

Reply via email to