From 21896dc50de64916799c13ca79803ac0b14b0715 Mon Sep 17 00:00:00 2001 From: Carsten Haitzler Date: Sat, 12 Aug 2006 09:16:30 +0000 Subject: [PATCH] jose's xpm loader. SVN revision: 24579 --- legacy/evas/configure.in | 31 + .../src/lib/engines/common/evas_image_load.c | 10 +- legacy/evas/src/modules/loaders/Makefile.am | 6 +- .../evas/src/modules/loaders/xpm/.cvsignore | 6 + .../evas/src/modules/loaders/xpm/Makefile.am | 24 + .../modules/loaders/xpm/evas_image_load_xpm.c | 705 ++++++++++++++++++ 6 files changed, 778 insertions(+), 4 deletions(-) create mode 100644 legacy/evas/src/modules/loaders/xpm/.cvsignore create mode 100644 legacy/evas/src/modules/loaders/xpm/Makefile.am create mode 100644 legacy/evas/src/modules/loaders/xpm/evas_image_load_xpm.c diff --git a/legacy/evas/configure.in b/legacy/evas/configure.in index 110685701e..d9ea4c06ff 100644 --- a/legacy/evas/configure.in +++ b/legacy/evas/configure.in @@ -883,6 +883,33 @@ fi AM_CONDITIONAL(BUILD_LOADER_TIFF, test x$have_tiff = xyes) +####################################### +## XPM +have_xpm="yes"; +AC_MSG_CHECKING(whether to enable xpm image loader) + +AC_ARG_ENABLE(image-loader-xpm, + [ --enable-image-loader-xpm enable XPM image loader], [ + if test x"$enableval" = x"yes" ; then + AC_MSG_RESULT(yes) + have_xpm="yes" + else + AC_MSG_RESULT(no) + have_xpm="no" + fi + ], [ + AC_MSG_RESULT($have_xpm) + ] +) +if test "x$have_xpm" = "xyes"; then + AC_MSG_RESULT($have_xpm) +fi + +xpm_cflags="" +xpm_libs="" + +AM_CONDITIONAL(BUILD_LOADER_XPM, test x$have_xpm = xyes) + ##################################################################### ## Cpu based optimizations @@ -1714,6 +1741,8 @@ AC_SUBST(edb_cflags) AC_SUBST(edb_libs) AC_SUBST(tiff_cflags) AC_SUBST(tiff_libs) +AC_SUBST(xpm_cflags) +AC_SUBST(xpm_libs) # Build the list of required libs for evas.pc.in. Only works for libs # which install a .pc file of course @@ -1787,6 +1816,7 @@ src/modules/loaders/gif/Makefile src/modules/loaders/jpeg/Makefile src/modules/loaders/png/Makefile src/modules/loaders/tiff/Makefile +src/modules/loaders/xpm/Makefile src/modules/savers/Makefile src/modules/savers/edb/Makefile src/modules/savers/eet/Makefile @@ -1837,6 +1867,7 @@ echo " JPEG....................: $have_jpeg" echo " EET.....................: $have_eet" echo " EDB.....................: $have_edb" echo " TIFF....................: $have_tiff" +echo " XPM.....................: $have_xpm" # FIXME: need to add modular image loader system # FIXME: add more image loader modules echo diff --git a/legacy/evas/src/lib/engines/common/evas_image_load.c b/legacy/evas/src/lib/engines/common/evas_image_load.c index 98b9b9be57..7c13ed6766 100644 --- a/legacy/evas/src/lib/engines/common/evas_image_load.c +++ b/legacy/evas/src/lib/engines/common/evas_image_load.c @@ -29,14 +29,18 @@ evas_common_load_image_from_file(const char *file, const char *key) p++; if (!strcasecmp(p, "png")) loader = "png"; - if ((!strcasecmp(p, "jpg")) || (!strcasecmp(p, "jpeg")) || + else if ((!strcasecmp(p, "jpg")) || (!strcasecmp(p, "jpeg")) || (!strcasecmp(p, "jfif"))) loader = "jpeg"; - if ((!strcasecmp(p, "eet")) || (!strcasecmp(p, "edj")) || + else if ((!strcasecmp(p, "eet")) || (!strcasecmp(p, "edj")) || (!strcasecmp(p, "eap"))) loader = "eet"; - if (!strcasecmp(p, "edb")) + else if (!strcasecmp(p, "edb")) loader = "edb"; + else if ((!strcasecmp(p, "tiff")) || (!strcasecmp(p, "tif"))) + loader = "tiff"; + else if (!strcasecmp(p, "xpm")) + loader = "xpm"; } if (loader) { diff --git a/legacy/evas/src/modules/loaders/Makefile.am b/legacy/evas/src/modules/loaders/Makefile.am index 8b812e489b..a23123fab6 100644 --- a/legacy/evas/src/modules/loaders/Makefile.am +++ b/legacy/evas/src/modules/loaders/Makefile.am @@ -24,4 +24,8 @@ if BUILD_LOADER_TIFF tiff_subdir = tiff endif -SUBDIRS = $(edb_subdir) $(eet_subdir) $(gif_subdir) $(jpeg_subdir) $(png_subdir) $(tiff_subdir) +if BUILD_LOADER_XPM +xpm_subdir = xpm +endif + +SUBDIRS = $(edb_subdir) $(eet_subdir) $(gif_subdir) $(jpeg_subdir) $(png_subdir) $(tiff_subdir) $(xpm_subdir) diff --git a/legacy/evas/src/modules/loaders/xpm/.cvsignore b/legacy/evas/src/modules/loaders/xpm/.cvsignore new file mode 100644 index 0000000000..a51c9665e0 --- /dev/null +++ b/legacy/evas/src/modules/loaders/xpm/.cvsignore @@ -0,0 +1,6 @@ +.deps +.libs +Makefile +Makefile.in +*.lo +*.la \ No newline at end of file diff --git a/legacy/evas/src/modules/loaders/xpm/Makefile.am b/legacy/evas/src/modules/loaders/xpm/Makefile.am new file mode 100644 index 0000000000..7effc41f20 --- /dev/null +++ b/legacy/evas/src/modules/loaders/xpm/Makefile.am @@ -0,0 +1,24 @@ +## Process this file with automake to produce Makefile.in + +AUTOMAKE_OPTIONS = 1.4 foreign + +# A list of all the files in the current directory which can be regenerated +MAINTAINERCLEANFILES = Makefile.in + +INCLUDES = -I. \ + -I$(top_srcdir)/src/lib \ + -I$(top_srcdir)/src/lib/include \ + @FREETYPE_CFLAGS@ @xpm_cflags@ + +pkgdir = $(libdir)/evas/modules/loaders/xpm/$(MODULE_ARCH) + +pkg_LTLIBRARIES = module.la + +module_la_SOURCES = evas_image_load_xpm.c + +module_la_LIBADD = $(top_builddir)/src/lib/libevas.la +module_la_LDFLAGS = -module -avoid-version -L$(top_builddir)/src/lib -L$(top_builddir)/src/lib/.libs + +module_la_DEPENDENCIES = $(top_builddir)/config.h + +EXTRA_DIST = evas_image_load_xpm.c diff --git a/legacy/evas/src/modules/loaders/xpm/evas_image_load_xpm.c b/legacy/evas/src/modules/loaders/xpm/evas_image_load_xpm.c new file mode 100644 index 0000000000..cd69690b17 --- /dev/null +++ b/legacy/evas/src/modules/loaders/xpm/evas_image_load_xpm.c @@ -0,0 +1,705 @@ +#include "evas_common.h" +#include "evas_private.h" + + +int evas_image_load_file_head_xpm(RGBA_Image *im, const char *file, const char *key); +int evas_image_load_file_data_xpm(RGBA_Image *im, const char *file, const char *key); + +Evas_Image_Load_Func evas_image_load_xpm_func = +{ + evas_image_load_file_head_xpm, + evas_image_load_file_data_xpm +}; + + +static FILE *rgb_txt = NULL; + +static void +xpm_parse_color(char *color, int *r, int *g, int *b) +{ + char buf[4096]; + + /* is a #ff00ff like color */ + if (color[0] == '#') + { + int len; + char val[32]; + + len = strlen(color) - 1; + if (len < 96) + { + int i; + + len /= 3; + for (i = 0; i < len; i++) + val[i] = color[1 + i + (0 * len)]; + val[i] = 0; + 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) + { + *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 */ + if (!rgb_txt) + rgb_txt = fopen("/usr/X11/lib/X11/rgb.txt", "r"); + if (!rgb_txt) + return; + fseek(rgb_txt, 0, SEEK_SET); + while (fgets(buf, 4000, rgb_txt)) + { + if (buf[0] != '!') + { + int rr, gg, bb; + char name[4096]; + + sscanf(buf, "%i %i %i %[^\n]", &rr, &gg, &bb, name); + if (!strcasecmp(name, color)) + { + *r = rr; + *g = gg; + *b = bb; + return; + } + } + } +} + +static void +xpm_parse_done(void) +{ + if (rgb_txt) + fclose(rgb_txt); + rgb_txt = NULL; +} + + +/** FIXME: clean this up and make more efficient **/ +static int +evas_image_load_file_xpm(RGBA_Image *im, const char *file, const char *key, int load_data) +{ + DATA32 *ptr, *end; + FILE *f; + + int pc, c, i, j, k, w, h, ncolors, cpp, comment, transp, + quote, context, len, done, r, g, b, backslash; + char *line, s[256], tok[128], col[256]; + int lsz = 256; + struct _cmap { + unsigned char str[6]; + unsigned char transp; + short r, g, b; + } *cmap; + + short lookup[128 - 32][128 - 32]; + float per = 0.0, per_inc = 0.0; + int last_per = 0, last_y = 0; + int count, pixels; + + if (!file) return 0; + done = 0; +// transp = -1; + transp = 0; + + /* if immediate_load is 1, then dont delay image laoding as below, or */ + /* already data in this image - dont load it again */ + + f = fopen(file, "rb"); + if (!f) + { + xpm_parse_done(); + return 0; + } + fread(s, 1, 9, f); + rewind(f); + s[9] = 0; + if (strcmp("/* XPM */", s)) + { + fclose(f); + xpm_parse_done(); + return 0; + } + + i = 0; + j = 0; + cmap = NULL; + w = 10; + h = 10; + ptr = NULL; + end = NULL; + c = ' '; + comment = 0; + quote = 0; + context = 0; + pixels = 0; + count = 0; + line = malloc(lsz); + if (!line) + { + fclose(f); + xpm_parse_done(); + return 0; + } + + backslash = 0; + memset(lookup, 0, sizeof(lookup)); + while (!done) + { + pc = c; + c = fgetc(f); + if (c == EOF) + break; + if (!quote) + { + if ((pc == '/') && (c == '*')) + comment = 1; + else if ((pc == '*') && (c == '/') && (comment)) + comment = 0; + } + if (!comment) + { + if ((!quote) && (c == '"')) + { + quote = 1; + i = 0; + } + else if ((quote) && (c == '"')) + { + line[i] = 0; + quote = 0; + if (context == 0) + { + /* Header */ + sscanf(line, "%i %i %i %i", &w, &h, &ncolors, &cpp); + if ((ncolors > 32766) || (ncolors < 1)) + { + fprintf(stderr, + "XPM ERROR: XPM files with colors > 32766 or < 1 not supported\n"); + free(line); + fclose(f); + xpm_parse_done(); + return 0; + } + if ((cpp > 5) || (cpp < 1)) + { + fprintf(stderr, + "XPM ERROR: XPM files with characters per pixel > 5 or < 1not supported\n"); + free(line); + fclose(f); + xpm_parse_done(); + return 0; + } + if ((w > 32767) || (w < 1)) + { + fprintf(stderr, + "XPM ERROR: Image width > 32767 or < 1 pixels for file\n"); + free(line); + fclose(f); + xpm_parse_done(); + return 0; + } + if ((h > 32767) || (h < 1)) + { + fprintf(stderr, + "XPM ERROR: Image height > 32767 or < 1 pixels for file\n"); + free(line); + fclose(f); + xpm_parse_done(); + return 0; + } + + if (!cmap) + { + cmap = malloc(sizeof(struct _cmap) * ncolors); + if (!cmap) + { + free(line); + fclose(f); + xpm_parse_done(); + return 0; + } + } + if (!im->image) + { + im->image = evas_common_image_surface_new(im); + if (!im->image) + { + free(cmap); + free(line); + fclose(f); + xpm_parse_done(); + return 0; + } + } + im->image->w = w; + im->image->h = h; + + per_inc = 100.0 / (((float)w) * h); + + 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; + cmap[j].r = -1; + cmap[j].transp = 0; + for (k = cpp; k < len; k++) + { + if (line[k] != ' ') + { + s[0] = 0; + sscanf(&line[k], "%65535s", s); + slen = strlen(s); + k += slen; + if (!strcmp(s, "c")) + iscolor = 1; + 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 (!strcasecmp(col, "none")) + { + transp = 1; + cmap[j].transp = 1; + } + else + { + if ((((cmap[j].r < 0) || + (!strcmp(tok, "c"))) + && (!hascolor))) + { + r = 0; + g = 0; + b = 0; + xpm_parse_color(col, + &r, + &g, + &b); + cmap[j].r = r; + cmap[j].g = g; + cmap[j].b = b; + if (iscolor) + 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); + } + } + } + } + j++; + if (j >= ncolors) + { + if (cpp == 1) + for (i = 0; i < ncolors; i++) + lookup[(int)cmap[i].str[0] - 32][0] = i; + if (cpp == 2) + for (i = 0; i < ncolors; i++) + lookup[(int)cmap[i].str[0] - + 32][(int)cmap[i].str[1] - 32] = i; + context++; + } + +// if (transp >= 0) + im->flags |= RGBA_IMAGE_HAS_ALPHA; + if (load_data) + { + evas_common_image_surface_alloc(im->image); + if (!im->image->data) + { + evas_common_image_surface_free(im->image); + free(cmap); + free(line); + fclose(f); + xpm_parse_done(); + return 0; + } + ptr = im->image->data; + end = ptr + (sizeof(DATA32) * w * h); + pixels = w * h; + } + else + { + free(cmap); + free(line); + fclose(f); + xpm_parse_done(); + return 1; + } + } + else + { + /* Image Data */ + i = 0; + if (cpp == 0) + { + /* Chars per pixel = 0? well u never know */ + } + if (cpp == 1) + { + if (transp) + { + for (i = 0; + ((i < 65536) && (ptr < end) && (line[i])); + i++) + { + col[0] = line[i]; + if (cmap[lookup[(int)col[0] - 32][0]]. + transp) + { + r = (unsigned char) + cmap[lookup[(int)col[0] - 32] + [0]].r; + g = (unsigned char) + cmap[lookup[(int)col[0] - 32] + [0]].g; + b = (unsigned char) + cmap[lookup[(int)col[0] - 32] + [0]].b; + *ptr++ = + 0x00ffffff & ((r << 16) | + (g << 8) | b); + count++; + } + else + { + r = (unsigned char) + cmap[lookup[(int)col[0] - 32] + [0]].r; + g = (unsigned char) + cmap[lookup[(int)col[0] - 32] + [0]].g; + b = (unsigned char) + cmap[lookup[(int)col[0] - 32] + [0]].b; + *ptr++ = + (0xff << 24) | (r << 16) | (g << + 8) | + b; + count++; + } + } + } + else + { + for (i = 0; + ((i < 65536) && (ptr < end) && (line[i])); + i++) + { + col[0] = line[i]; + r = (unsigned char) + cmap[lookup[(int)col[0] - 32][0]].r; + g = (unsigned char) + cmap[lookup[(int)col[0] - 32][0]].g; + b = (unsigned char) + cmap[lookup[(int)col[0] - 32][0]].b; + *ptr++ = + (0xff << 24) | (r << 16) | (g << 8) | + b; + count++; + } + } + } + else if (cpp == 2) + { + if (transp) + { + for (i = 0; + ((i < 65536) && (ptr < end) && (line[i])); + i++) + { + col[0] = line[i++]; + col[1] = line[i]; + if (cmap + [lookup[(int)col[0] - 32] + [(int)col[1] - 32]].transp) + { + r = (unsigned char) + cmap[lookup[(int)col[0] - 32] + [(int)col[1] - 32]].r; + g = (unsigned char) + cmap[lookup[(int)col[0] - 32] + [(int)col[1] - 32]].g; + b = (unsigned char) + cmap[lookup[(int)col[0] - 32] + [(int)col[1] - 32]].b; + *ptr++ = + 0x00ffffff & ((r << 16) | + (g << 8) | b); + count++; + } + else + { + r = (unsigned char) + cmap[lookup[(int)col[0] - 32] + [(int)col[1] - 32]].r; + g = (unsigned char) + cmap[lookup[(int)col[0] - 32] + [(int)col[1] - 32]].g; + b = (unsigned char) + cmap[lookup[(int)col[0] - 32] + [(int)col[1] - 32]].b; + *ptr++ = + (0xff << 24) | (r << 16) | (g << + 8) | + b; + count++; + } + } + } + else + { + for (i = 0; + ((i < 65536) && (ptr < end) && (line[i])); + i++) + { + col[0] = line[i++]; + col[1] = line[i]; + r = (unsigned char) + cmap[lookup[(int)col[0] - 32] + [(int)col[1] - 32]].r; + g = (unsigned char) + cmap[lookup[(int)col[0] - 32] + [(int)col[1] - 32]].g; + b = (unsigned char) + cmap[lookup[(int)col[0] - 32] + [(int)col[1] - 32]].b; + *ptr++ = + (0xff << 24) | (r << 16) | (g << 8) | + b; + count++; + } + } + } + else + { + if (transp) + { + for (i = 0; + ((i < 65536) && (ptr < end) && (line[i])); + i++) + { + for (j = 0; j < cpp; j++, i++) + { + col[j] = line[i]; + } + col[j] = 0; + i--; + for (j = 0; j < ncolors; j++) + { + if (!strcmp(col, cmap[j].str)) + { + if (cmap[j].transp) + { + r = (unsigned char) + cmap[lookup + [(int)col[0] - + 32][0]].r; + g = (unsigned char) + cmap[lookup + [(int)col[0] - + 32][0]].g; + b = (unsigned char) + cmap[lookup + [(int)col[0] - + 32][0]].b; + *ptr++ = + 0x00ffffff & ((r << 16) + | (g << + 8) | + b); + count++; + } + else + { + r = (unsigned char)cmap[j]. + r; + g = (unsigned char)cmap[j]. + g; + b = (unsigned char)cmap[j]. + b; + *ptr++ = + (0xff << 24) | (r << + 16) | + (g << 8) | b; + count++; + } + j = ncolors; + } + } + } + } + else + { + for (i = 0; + ((i < 65536) && (ptr < end) && (line[i])); + i++) + { + for (j = 0; j < cpp; j++, i++) + { + col[j] = line[i]; + } + col[j] = 0; + i--; + for (j = 0; j < ncolors; j++) + { + if (!strcmp(col, cmap[j].str)) + { + r = (unsigned char)cmap[j].r; + g = (unsigned char)cmap[j].g; + b = (unsigned char)cmap[j].b; + *ptr++ = + (0xff << 24) | (r << 16) | + (g << 8) | b; + count++; + j = ncolors; + } + } + } + } + } + per += per_inc; + } + } + } + /* Scan in line from XPM file */ + if ((!comment) && (quote) && (c != '"')) + { + if (c < 32) + c = 32; + else if (c > 127) + c = 127; + if ( c=='\\' ) { + if ( ++backslash<2 ) { + line[i++] = c; + } + else { + backslash = 0; + } + } + else { + backslash = 0; + line[i++] = c; + } + } + if (i >= lsz) + { + lsz += 256; + line = realloc(line, lsz); + if (!line) + { + free(cmap); + fclose(f); + } + } + if (((ptr) && ((ptr - im->image->data) >= (w * h * sizeof(DATA32)))) || + ((context > 1) && (count >= pixels))) + done = 1; + } + + free(cmap); + free(line); + fclose(f); + + xpm_parse_done(); + + return 1; +} + + +int +evas_image_load_file_head_xpm(RGBA_Image *im, const char *file, const char *key) +{ + return evas_image_load_file_xpm(im, file, key, 0); +} + +int +evas_image_load_file_data_xpm(RGBA_Image *im, const char *file, const char *key) +{ + return evas_image_load_file_xpm(im, file, key, 1); +} + + + +int module_open(Evas_Module *em) +{ + if (!em) return 0; + em->functions = (void *)(&evas_image_load_xpm_func); + return 1; +} + +void module_close(void) +{ + +} + +Evas_Module_Api evas_modapi = +{ + EVAS_MODULE_API_VERSION, + EVAS_MODULE_TYPE_IMAGE_LOADER, + "xpm", + "none" +};