diff --git a/legacy/evas/configure.in b/legacy/evas/configure.in index e40efcf635..a9162b9c69 100644 --- a/legacy/evas/configure.in +++ b/legacy/evas/configure.in @@ -1055,6 +1055,22 @@ fi AM_CONDITIONAL(BUILD_LOADER_SVG, test x$have_svg = xyes) +####################################### +## PMAPS +have_pmaps="yes"; +AC_MSG_CHECKING(whether to enable pmaps image loader) +AC_ARG_ENABLE(image-loader-pmaps, + AC_HELP_STRING([--disable-image-loader-pmaps], [disable PMAPS image loader]), + [ have_pmaps=$enableval ] +) +AC_MSG_RESULT($have_pmaps) + +pmaps_cflags="" +pmaps_libs="" + +AM_CONDITIONAL(BUILD_LOADER_PMAPS, test x$have_pmaps = xyes) + + ##################################################################### ## Cpu based optimizations @@ -1520,6 +1536,8 @@ AC_SUBST(xpm_cflags) AC_SUBST(xpm_libs) AC_SUBST(svg_cflags) AC_SUBST(svg_libs) +AC_SUBST(pmaps_cflags) +AC_SUBST(pmaps_libs) AC_SUBST(altivec_cflags) AC_SUBST(pthread_cflags) AC_SUBST(pthread_libs) @@ -1595,6 +1613,7 @@ src/modules/loaders/png/Makefile src/modules/loaders/tiff/Makefile src/modules/loaders/xpm/Makefile src/modules/loaders/svg/Makefile +src/modules/loaders/pmaps/Makefile src/modules/savers/Makefile src/modules/savers/edb/Makefile src/modules/savers/eet/Makefile @@ -1648,6 +1667,7 @@ echo " EDB.....................: $have_edb_image_loader" echo " TIFF....................: $have_tiff" echo " XPM.....................: $have_xpm" echo " SVG.....................: $have_svg" +echo " PMAPS...................: $have_pmaps" # 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 a28364911c..1b41e61db6 100644 --- a/legacy/evas/src/lib/engines/common/evas_image_load.c +++ b/legacy/evas/src/lib/engines/common/evas_image_load.c @@ -22,7 +22,11 @@ static struct ext_loader_s loaders[] = { { "tif", "tiff" }, { "svg", "svg" }, { "svgz", "svg" }, - { "gif", "gif" } + { "gif", "gif" }, + { "pbm", "pmaps" }, + { "pgm", "pmaps" }, + { "ppm", "pmaps" }, + { "pnm", "pmaps" } }; EAPI int diff --git a/legacy/evas/src/modules/loaders/Makefile.am b/legacy/evas/src/modules/loaders/Makefile.am index 8fe5965874..fceae726ad 100644 --- a/legacy/evas/src/modules/loaders/Makefile.am +++ b/legacy/evas/src/modules/loaders/Makefile.am @@ -32,4 +32,9 @@ if BUILD_LOADER_SVG svg_subdir = svg endif -SUBDIRS = $(edb_subdir) $(eet_subdir) $(gif_subdir) $(jpeg_subdir) $(png_subdir) $(tiff_subdir) $(xpm_subdir) $(svg_subdir) +if BUILD_LOADER_PMAPS +pmaps_subdir = pmaps +endif + + +SUBDIRS = $(edb_subdir) $(eet_subdir) $(gif_subdir) $(jpeg_subdir) $(png_subdir) $(tiff_subdir) $(xpm_subdir) $(svg_subdir) $(pmaps_subdir) diff --git a/legacy/evas/src/modules/loaders/pmaps/.cvsignore b/legacy/evas/src/modules/loaders/pmaps/.cvsignore new file mode 100644 index 0000000000..a51c9665e0 --- /dev/null +++ b/legacy/evas/src/modules/loaders/pmaps/.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/pmaps/Makefile.am b/legacy/evas/src/modules/loaders/pmaps/Makefile.am new file mode 100644 index 0000000000..600e333d31 --- /dev/null +++ b/legacy/evas/src/modules/loaders/pmaps/Makefile.am @@ -0,0 +1,21 @@ + +MAINTAINERCLEANFILES = Makefile.in + +AM_CPPFLAGS = -I. \ + -I$(top_srcdir)/src/lib \ + -I$(top_srcdir)/src/lib/include \ + @FREETYPE_CFLAGS@ @pmaps_cflags@ + +pkgdir = $(libdir)/evas/modules/loaders/pmaps/$(MODULE_ARCH) + +pkg_LTLIBRARIES = module.la + +module_la_SOURCES = evas_image_load_pmaps.c + +module_la_LIBADD = $(top_builddir)/src/lib/libevas.la +module_la_LDFLAGS = @create_shared_lib@ -module -avoid-version + +module_la_LIBTOOLFLAGS = --tag=disable-static +module_la_DEPENDENCIES = $(top_builddir)/config.h + +EXTRA_DIST = evas_image_load_pmaps.c diff --git a/legacy/evas/src/modules/loaders/pmaps/evas_image_load_pmaps.c b/legacy/evas/src/modules/loaders/pmaps/evas_image_load_pmaps.c new file mode 100644 index 0000000000..c7e0216412 --- /dev/null +++ b/legacy/evas/src/modules/loaders/pmaps/evas_image_load_pmaps.c @@ -0,0 +1,571 @@ +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif + +#include "evas_common.h" +#include "evas_private.h" + +#define FILE_BUFFER_SIZE 1024 +#define FILE_BUFFER_UNREAD_SIZE 16 + +static int evas_image_load_file_head_pmaps(RGBA_Image *im, + const char *file, const char *key); +static int evas_image_load_file_data_pmaps(RGBA_Image *im, + const char *file, const char *key); + +Evas_Image_Load_Func evas_image_load_pmaps_func = { + evas_image_load_file_head_pmaps, + evas_image_load_file_data_pmaps +}; + +/* The buffer to load pmaps images */ +typedef struct Pmaps_Buffer Pmaps_Buffer; + +struct Pmaps_Buffer +{ + FILE *file; + + /* the buffer */ + DATA8 buffer[FILE_BUFFER_SIZE]; + DATA8 unread[FILE_BUFFER_UNREAD_SIZE]; + DATA8 *current; + DATA8 *end; + char type[3]; + unsigned char unread_len:7; + unsigned char last_buffer:1; + + /* image properties */ + int w; + int h; + int max; + + /* interface */ + int (*int_get) (Pmaps_Buffer *b, int *val); + int (*color_get) (Pmaps_Buffer *b, DATA32 *color); +}; + +/* internal used functions */ +static int pmaps_buffer_open(Pmaps_Buffer *b, const char *filename); +static void pmaps_buffer_close(Pmaps_Buffer *b); +static int pmaps_buffer_header_parse(Pmaps_Buffer *b); +static int pmaps_buffer_plain_int_get(Pmaps_Buffer *b, int *val); +static int pmaps_buffer_1byte_int_get(Pmaps_Buffer *b, int *val); +static int pmaps_buffer_2byte_int_get(Pmaps_Buffer *b, int *val); +static int pmaps_buffer_gray_get(Pmaps_Buffer *b, DATA32 *color); +static int pmaps_buffer_rgb_get(Pmaps_Buffer *b, DATA32 *color); +static int pmaps_buffer_plain_bw_get(Pmaps_Buffer *b, DATA32 *color); + +static size_t pmaps_buffer_plain_update(Pmaps_Buffer *b); +static size_t pmaps_buffer_raw_update(Pmaps_Buffer *b); +static int pmaps_buffer_comment_skip(Pmaps_Buffer *b); + +static int +evas_image_load_file_head_pmaps(RGBA_Image *im, const char *file, + const char *key) +{ + Pmaps_Buffer b; + + if ((!file)) + return 0; + + if (!pmaps_buffer_open(&b, file)) + { + pmaps_buffer_close(&b); + return 0; + } + + if (!pmaps_buffer_header_parse(&b)) + { + pmaps_buffer_close(&b); + return 0; + } + + if (!im->image) + im->image = evas_common_image_surface_new(im); + if (!im->image) + { + pmaps_buffer_close(&b); + return 0; + } + + im->image->w = b.w; + im->image->h = b.h; + + pmaps_buffer_close(&b); + return 1; + /* we don't have a use for key, skip warnings */ + key = NULL; +} + +static int +evas_image_load_file_data_pmaps(RGBA_Image *im, const char *file, + const char *key) +{ + Pmaps_Buffer b; + int pixels; + DATA32 *ptr; + + if ((!file)) + return 0; + + if (!pmaps_buffer_open(&b, file)) + { + pmaps_buffer_close(&b); + return 0; + } + + if (!pmaps_buffer_header_parse(&b)) + { + pmaps_buffer_close(&b); + return 0; + } + + pixels = b.w * b.h; + + if (!im->image) + im->image = evas_common_image_surface_new(im); + if (!im->image) + { + pmaps_buffer_close(&b); + return 0; + } + + evas_common_image_surface_alloc(im->image); + if (!im->image->data) + { + evas_common_image_surface_free(im->image); + pmaps_buffer_close(&b); + return 0; + } + + ptr = im->image->data; + + if (b.type[1] != '4') + { + while (pixels > 0 && b.color_get(&b, ptr)) + { + pixels--; + ptr++; + } + } + else + { + while (pixels > 0 + && (b.current != b.end || pmaps_buffer_raw_update(&b))) + { + int i; + + for (i = 7; i >= 0 && pixels > 0; i--) + { + if (*b.current & (1 << i)) + *ptr = 0xff000000; + else + *ptr = 0xffffffff; + ptr++; + pixels--; + } + b.current++; + } + } + + /* if there are some pix missing, give them a proper default */ + memset(ptr, 0xff, 4 * pixels); + pmaps_buffer_close(&b); + + return 1; + /* we don't have a use for key, skip warnings */ + key = NULL; +} + +/* internal used functions */ +static int +pmaps_buffer_open(Pmaps_Buffer *b, const char *filename) +{ + size_t len; + + b->file = fopen(filename, "r"); + if (!b->file) + return 0; + + *b->buffer = 0; + *b->unread = 0; + b->last_buffer = 0; + b->unread_len = 0; + + len = pmaps_buffer_plain_update(b); + + if (len < 3) + return 0; + + /* copy the type */ + b->type[0] = b->buffer[0]; + b->type[1] = b->buffer[1]; + b->type[2] = 0; + /* skip the PX */ + b->current = b->buffer + 2; + + return 1; +} + +static void +pmaps_buffer_close(Pmaps_Buffer *b) +{ + if (b->file) + fclose(b->file); +} + +static int +pmaps_buffer_header_parse(Pmaps_Buffer *b) +{ + /* if there is no P at the beginning it is not a file we can parse */ + if (b->type[0] != 'P') + return 0; + + /* get the width */ + if (!pmaps_buffer_plain_int_get(b, &(b->w)) || b->w < 1) + return 0; + + /* get the height */ + if (!pmaps_buffer_plain_int_get(b, &(b->h)) || b->h < 1) + return 0; + + /* get the maximum value. P1 and P4 don't have a maximum value. */ + if (!(b->type[1] == '1' || b->type[1] == '4') + && (!pmaps_buffer_plain_int_get(b, &(b->max)) || b->max < 1)) + return 0; + + /* set up the color get callback */ + switch (b->type[1]) + { + /* Black and White */ + case '1': + b->color_get = pmaps_buffer_plain_bw_get; + break; + case '4': + /* Binary black and white use another format */ + b->color_get = NULL; + break; + case '2': + case '5': + b->color_get = pmaps_buffer_gray_get; + break; + case '3': + case '6': + b->color_get = pmaps_buffer_rgb_get; + break; + case '7': + /* XXX write me */ + return 0; + break; + default: + return 0; + } + /* set up the int get callback */ + switch (b->type[1]) + { + /* RAW */ + case '5': + case '6': + if (b->max < 256) + b->int_get = pmaps_buffer_1byte_int_get; + else + b->int_get = pmaps_buffer_2byte_int_get; + + if (b->current == b->end && !pmaps_buffer_raw_update(b)) + return 0; + + b->current++; + break; + /* Plain */ + case '2': + case '3': + b->int_get = pmaps_buffer_plain_int_get; + break; + /* Black and White Bitmaps don't use that callback */ + case '1': + case '4': + b->int_get = NULL; + /* we need to skip the next character fpr P4 it + * doesn't hurt if we do it for the P1 as well */ + b->current++; + break; + } + return 1; +} + +static size_t +pmaps_buffer_plain_update(Pmaps_Buffer *b) +{ + size_t r; + size_t steps = 0; + + /* if we already are in the last buffer we can not update it */ + if (b->last_buffer) + return 0; + + /* if we have unread bytes we need to put them before the new read + * stuff */ + if (b->unread_len) + memcpy(b->buffer, b->unread, b->unread_len); + + r = fread(&b->buffer[b->unread_len], 1, + FILE_BUFFER_SIZE - b->unread_len - 1, b->file) + b->unread_len; + + /* we haven't read anything nor have we bytes in the unread buffer */ + if (r == 0) + { + b->buffer[0] = '\0'; + b->end = b->buffer; + b->last_buffer = 1; + return 0; + } + + if (r < FILE_BUFFER_SIZE - 1) + { + /*we reached eof */ ; + b->last_buffer = 1; + } + + b->buffer[r] = 0; + r--; + + while (steps < (FILE_BUFFER_UNREAD_SIZE - 2) + && r > 1 && !isspace(b->buffer[r])) + { + steps++; + r--; + } + + if (steps != 0) + { + memcpy(b->unread, &b->buffer[r], steps + 1); + b->unread_len = steps + 1; + } + else + { + b->unread[0] = '\0'; + b->unread_len = 0; + } + + b->buffer[r] = '\0'; + b->current = b->buffer; + b->end = b->buffer + r; + + return r; +} + +static size_t +pmaps_buffer_raw_update(Pmaps_Buffer *b) +{ + size_t r; + + if (b->last_buffer) + return 0; + + if (b->unread_len) + memcpy(b->buffer, b->unread, b->unread_len); + + r = fread(&b->buffer[b->unread_len], 1, + FILE_BUFFER_SIZE - b->unread_len - 1, b->file) + b->unread_len; + + if (r < FILE_BUFFER_SIZE - 1) + { + /*we reached eof */ ; + b->last_buffer = 1; + } + + b->buffer[r] = 0; + b->end = b->buffer + r; + b->current = b->buffer; + + if (b->unread_len) + { + /* the buffer is now read */ + *b->unread = '\0'; + b->unread_len = 0; + } + + return r; +} + +static int +pmaps_buffer_plain_int_get(Pmaps_Buffer *b, int *val) +{ + char *start; + DATA8 lastc; + + /* first skip all white space + * Note: we are skipping here actually every character than is not + * a digit */ + while (!isdigit(*b->current)) + { + if (*b->current == '\0') + { + if (!pmaps_buffer_plain_update(b)) + return 0; + + continue; + } + if (*b->current == '#' && !pmaps_buffer_comment_skip(b)) + return 0; + b->current++; + } + + start = (char *)b->current; + /* now find the end of the number */ + while (isdigit(*b->current)) + b->current++; + + lastc = *b->current; + *b->current = '\0'; + *val = atoi(start); + *b->current = lastc; + + return 1; +} + +static int +pmaps_buffer_1byte_int_get(Pmaps_Buffer *b, int *val) +{ + /* are we at the end of the buffer? */ + if (b->current == b->end && !pmaps_buffer_raw_update(b)) + return 0; + + *val = *b->current; + b->current++; + + return 1; +} +static int +pmaps_buffer_2byte_int_get(Pmaps_Buffer *b, int *val) +{ + /* are we at the end of the buffer? */ + if (b->current == b->end && !pmaps_buffer_raw_update(b)) + return 0; + + *val = (int)(*b->current << 8); + b->current++; + + /* are we at the end of the buffer? */ + if (b->current == b->end && !pmaps_buffer_raw_update(b)) + return 0; + + *val |= *b->current; + b->current++; + + return 1; +} + +static int +pmaps_buffer_comment_skip(Pmaps_Buffer *b) +{ + while (*b->current != '\n') + { + if (*b->current == '\0') + { + if (!pmaps_buffer_plain_update(b)) + return 0; + + continue; + } + b->current++; + } + return 1; +} + +static int +pmaps_buffer_rgb_get(Pmaps_Buffer *b, DATA32 *color) +{ + int vr, vg, vb; + + if (!b->int_get(b, &vr) || !b->int_get(b, &vg) || !b->int_get(b, &vb)) + return 0; + + if (b->max != 255) + { + vr = (vr * 255) / b->max; + vg = (vg * 255) / b->max; + vb = (vb * 255) / b->max; + } + if (vr > 255) + vr = 255; + if (vg > 255) + vg = 255; + if (vb > 255) + vb = 255; + + *color = 0xff000000 | (vr << 16) | (vg << 8) | vb; + + return 1; +} + +static int +pmaps_buffer_gray_get(Pmaps_Buffer *b, DATA32 *color) +{ + int val; + + if (!b->int_get(b, &val)) + return 0; + + if (b->max != 255) + val = (val * 255) / b->max; + if (val > 255) + val = 255; + *color = 0xff000000 | (val << 16) | (val << 8) | val; + + return 1; +} + +static int +pmaps_buffer_plain_bw_get(Pmaps_Buffer *b, DATA32 *val) +{ + /* first skip all white space + * Note: we are skipping here actually every character than is not + * a digit */ + while (!isdigit(*b->current)) + { + if (*b->current == '\0') + { + if (!pmaps_buffer_raw_update(b)) + return 0; + + continue; + } + if (*b->current == '#' && !pmaps_buffer_comment_skip(b)) + return 0; + b->current++; + } + + if (*b->current == '0') + *val = 0xffffffff; + else + *val = 0xff000000; + + b->current++; + + return 1; +} + +/* external functions */ +EAPI int +module_open(Evas_Module *em) +{ + if (!em) + return 0; + em->functions = (void *)(&evas_image_load_pmaps_func); + return 1; +} + +EAPI void +module_close(void) +{ + +} + +EAPI Evas_Module_Api evas_modapi = { + EVAS_MODULE_API_VERSION, + EVAS_MODULE_TYPE_IMAGE_LOADER, + "pmaps", + "none" +}; +