diff --git a/legacy/evas/ChangeLog b/legacy/evas/ChangeLog index 3cf24bfb70..2c8459c6af 100644 --- a/legacy/evas/ChangeLog +++ b/legacy/evas/ChangeLog @@ -162,3 +162,7 @@ are 0 or not and then force alpha off if all are 0". This means you can never have a 100% empty/transparent BMP though in 32bpp mode. + +2011-03-11 Carsten Haitzler (The Rasterman) + + * Add ICO loader to evas (also can load CUR cursor files in theory) diff --git a/legacy/evas/configure.ac b/legacy/evas/configure.ac index d986ce274a..3407e69e93 100644 --- a/legacy/evas/configure.ac +++ b/legacy/evas/configure.ac @@ -126,6 +126,7 @@ want_evas_image_loader_xpm="yes" want_evas_image_loader_bmp="yes" want_evas_image_loader_tga="yes" want_evas_image_loader_wbmp="yes" +want_evas_image_loader_ico="yes" want_evas_font_loader_eet="yes" @@ -820,6 +821,7 @@ EVAS_CHECK_IMAGE_LOADER([TGA], [${want_evas_image_loader_tga}]) EVAS_CHECK_IMAGE_LOADER([WBMP], [${want_evas_image_loader_wbmp}]) +EVAS_CHECK_IMAGE_LOADER([ICO], [${want_evas_image_loader_ico}]) ##################################################################### ## Cpu based optimizations @@ -1595,6 +1597,7 @@ src/modules/loaders/png/Makefile src/modules/loaders/tiff/Makefile src/modules/loaders/xpm/Makefile src/modules/loaders/bmp/Makefile +src/modules/loaders/ico/Makefile src/modules/loaders/tga/Makefile src/modules/loaders/svg/Makefile src/modules/loaders/pmaps/Makefile @@ -1702,6 +1705,7 @@ echo " XPM.....................: $have_evas_image_loader_xpm" echo " BMP.....................: $have_evas_image_loader_bmp" echo " TGA.....................: $have_evas_image_loader_tga" echo " WBMP....................: $have_evas_image_loader_wbmp" +echo " ICO.....................: $have_evas_image_loader_ico" echo echo "Font Sourcing Systems:" echo " EET.....................: $have_evas_font_loader_eet" diff --git a/legacy/evas/m4/evas_check_loader.m4 b/legacy/evas/m4/evas_check_loader.m4 index 00a96185dd..17685e4eb8 100644 --- a/legacy/evas/m4/evas_check_loader.m4 +++ b/legacy/evas/m4/evas_check_loader.m4 @@ -328,6 +328,26 @@ fi ]) +dnl use: EVAS_CHECK_LOADER_DEP_ICO(loader, want_static[, ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]]) + +AC_DEFUN([EVAS_CHECK_LOADER_DEP_ICO], +[ + +have_dep="yes" +evas_image_loader_[]$1[]_cflags="" +evas_image_loader_[]$1[]_libs="" + +AC_SUBST([evas_image_loader_$1_cflags]) +AC_SUBST([evas_image_loader_$1_libs]) + +if test "x${have_dep}" = "xyes" ; then + m4_default([$3], [:]) +else + m4_default([$4], [:]) +fi + +]) + dnl use: EVAS_CHECK_LOADER_DEP_TGA(loader, want_static[, ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]]) AC_DEFUN([EVAS_CHECK_LOADER_DEP_TGA], 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 b1130406d6..ba6b38df78 100644 --- a/legacy/evas/src/lib/engines/common/evas_image_load.c +++ b/legacy/evas/src/lib/engines/common/evas_image_load.c @@ -30,12 +30,14 @@ static const struct ext_loader_s loaders[] = { "pnm", "pmaps" }, { "bmp", "bmp" }, { "tga", "tga" }, - { "wbmp", "wbmp" } + { "wbmp", "wbmp" }, + { "ico", "ico" }, + { "cur", "ico" } }; static const char *loaders_name[] = { - "png", "jpeg", "eet", "xpm", "tiff", "gif", "svg", "pmaps", "edb", "bmp", "tga", "wbmp" + "png", "jpeg", "eet", "xpm", "tiff", "gif", "svg", "pmaps", "edb", "bmp", "tga", "wbmp", "ico" }; struct evas_image_foreach_loader_data diff --git a/legacy/evas/src/lib/file/evas_module.c b/legacy/evas/src/lib/file/evas_module.c index 4e37f1a955..6466abd675 100644 --- a/legacy/evas/src/lib/file/evas_module.c +++ b/legacy/evas/src/lib/file/evas_module.c @@ -125,6 +125,7 @@ EVAS_EINA_STATIC_MODULE_DEFINE(image_loader, eet); EVAS_EINA_STATIC_MODULE_DEFINE(image_loader, edb); EVAS_EINA_STATIC_MODULE_DEFINE(image_loader, tga); EVAS_EINA_STATIC_MODULE_DEFINE(image_loader, wbmp); +EVAS_EINA_STATIC_MODULE_DEFINE(image_loader, ico); EVAS_EINA_STATIC_MODULE_DEFINE(image_saver, edb); EVAS_EINA_STATIC_MODULE_DEFINE(image_saver, eet); EVAS_EINA_STATIC_MODULE_DEFINE(image_saver, jpeg); @@ -240,6 +241,9 @@ static const struct { #ifdef EVAS_STATIC_BUILD_WBMP EVAS_EINA_STATIC_MODULE_USE(image_loader, wbmp), #endif +#ifdef EVAS_STATIC_BUILD_ICO + EVAS_EINA_STATIC_MODULE_USE(image_loader, ico), +#endif #ifdef EVAS_STATIC_BUILD_EDB EVAS_EINA_STATIC_MODULE_USE(image_saver, edb), #endif diff --git a/legacy/evas/src/modules/loaders/ico/Makefile.am b/legacy/evas/src/modules/loaders/ico/Makefile.am new file mode 100644 index 0000000000..c06866d50c --- /dev/null +++ b/legacy/evas/src/modules/loaders/ico/Makefile.am @@ -0,0 +1,32 @@ + +MAINTAINERCLEANFILES = Makefile.in + +AM_CPPFLAGS = \ +-I. \ +-I$(top_srcdir)/src/lib \ +-I$(top_srcdir)/src/lib/include \ +@FREETYPE_CFLAGS@ \ +@EINA_CFLAGS@ \ +@EVIL_CFLAGS@ \ +@WIN32_CPPFLAGS@ + +if BUILD_LOADER_ICO +if !EVAS_STATIC_BUILD_ICO + +pkgdir = $(libdir)/evas/modules/loaders/ico/$(MODULE_ARCH) +pkg_LTLIBRARIES = module.la + +module_la_SOURCES = evas_image_load_ico.c + +module_la_LIBADD = @EINA_LIBS@ @EVIL_LIBS@ $(top_builddir)/src/lib/libevas.la +module_la_LDFLAGS = -no-undefined @lt_enable_auto_import@ -module -avoid-version +module_la_LIBTOOLFLAGS = --tag=disable-static + +else + +noinst_LTLIBRARIES = libevas_loader_ico.la +libevas_loader_ico_la_SOURCES = evas_image_load_ico.c +libevas_loader_ico_la_LIBADD = + +endif +endif diff --git a/legacy/evas/src/modules/loaders/ico/evas_image_load_ico.c b/legacy/evas/src/modules/loaders/ico/evas_image_load_ico.c new file mode 100644 index 0000000000..220192b47c --- /dev/null +++ b/legacy/evas/src/modules/loaders/ico/evas_image_load_ico.c @@ -0,0 +1,725 @@ +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +#ifdef HAVE_EVIL +# include +#endif + +#include "evas_common.h" +#include "evas_private.h" + +static Eina_Bool evas_image_load_file_head_ico(Image_Entry *ie, const char *file, const char *key, int *error) EINA_ARG_NONNULL(1, 2, 4); +static Eina_Bool evas_image_load_file_data_ico(Image_Entry *ie, const char *file, const char *key, int *error) EINA_ARG_NONNULL(1, 2, 4); + +static Evas_Image_Load_Func evas_image_load_ico_func = +{ + EINA_TRUE, + evas_image_load_file_head_ico, + evas_image_load_file_data_ico +}; + +static int +read_ushort(FILE *file, unsigned short *ret) +{ + unsigned char b[2]; + if (fread(b, sizeof(unsigned char), 2, file) != 2) return 0; + *ret = (b[1] << 8) | b[0]; + return 1; +} + +static int +read_uint(FILE *file, unsigned int *ret) +{ + unsigned char b[4]; + if (fread(b, sizeof(unsigned char), 4, file) != 4) return 0; + *ret = ARGB_JOIN(b[3], b[2], b[1], b[0]); + return 1; +} + +enum +{ + SMALLEST, + BIGGEST, + SMALLER, + BIGGER +}; + +static Eina_Bool +evas_image_load_file_head_ico(Image_Entry *ie, const char *file, const char *key, int *error) +{ + unsigned short word; + unsigned char byte; + FILE *f; + int wanted_w = 0, wanted_h = 0, w, h, cols, i, planes = 0, + hot_x = 0, hot_y = 0, bpp = 0, pdelta, search = -1, have_choice = 0, + hasa = 1; + unsigned int bmoffset, bmsize, fsize; + unsigned short reserved, type, count; + struct { + int pdelta; + int w, h; + int cols; + int bpp, planes; + int hot_x, hot_y; + unsigned int bmoffset, bmsize; + } chosen = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + + f = fopen(file, "rb"); + if (!f) + { + *error = EVAS_LOAD_ERROR_DOES_NOT_EXIST; + return EINA_FALSE; + } + + *error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT; + fseek(f, 0, SEEK_END); + fsize = ftell(f); + fseek(f, 0, SEEK_SET); + if (fsize < (6 + 16 + 40)) goto close_file; + + // key: + // NULL == highest res + // biggest == highest res + // smallest == lowest res + // + // smaller == next size SMALLER than load opts WxH (if possible) + // bigger == next size BIGGER than load opts WxH (if possible) + // more ? + + search = BIGGEST; + if ((ie->load_opts.w > 0) && (ie->load_opts.h > 0)) + { + wanted_w = ie->load_opts.w; + wanted_h = ie->load_opts.h; + search = SMALLER; + } + + if (!read_ushort(f, &reserved)) goto close_file; + if (!read_ushort(f, &type)) goto close_file; + if (!read_ushort(f, &count)) goto close_file; + if (!((reserved == 0) && ((type == 1) || (type == 2)) && (count > 0))) + goto close_file; + *error = EVAS_LOAD_ERROR_CORRUPT_FILE; + + if (key) + { + if (!strcmp(key, "biggest")) + { + wanted_w = 0; + wanted_h = 0; + search = BIGGEST; + chosen.pdelta = 0; + } + else if (!strcmp(key, "smallest")) + { + wanted_w = 1; + wanted_h = 1; + search = SMALLEST; + chosen.pdelta = 0x7fffffff; + } + else if (!strcmp(key, "smaller")) + { + chosen.pdelta = 0x7fffffff; + search = SMALLER; + } + else if (!strcmp(key, "bigger")) + { + chosen.pdelta = 0x7fffffff; + search = BIGGER; + } + } + for (i = 0; i < count; i++) + { + if (fread(&byte, 1, 1, f) != 1) goto close_file; + w = byte; + if (w <= 0) w = 256; + if (fread(&byte, 1, 1, f) != 1) goto close_file; + h = byte; + if (h <= 0) h = 256; + if (fread(&byte, 1, 1, f) != 1) goto close_file; + cols = byte; + if (cols <= 0) cols = 256; + if (fread(&byte, 1, 1, f) != 1) goto close_file; + if (!read_ushort(f, &word)) goto close_file; + if (type == 1) planes = word; + else hot_x = word; + if (!read_ushort(f, &word)) goto close_file; + if (type == 1) bpp = word; + else hot_y = word; + if (!read_uint(f, &bmsize)) goto close_file; + if (!read_uint(f, &bmoffset)) goto close_file; + if ((bmsize <= 0) || (bmoffset <= 0) || (bmoffset >= fsize)) goto close_file; + if (search == BIGGEST) + { + pdelta = w * h; + if ((!have_choice) || + ((pdelta >= chosen.pdelta) && + (((bpp >= 3) && (bpp >= chosen.bpp)) || + ((bpp < 3) && (cols >= chosen.cols))))) + { + have_choice = 1; + chosen.pdelta = pdelta; + chosen.w = w; + chosen.h = h; + chosen.cols = cols; + chosen.bpp = bpp; + chosen.planes = planes; + chosen.bmsize = bmsize; + chosen.bmoffset = bmoffset; + } + } + else + { + if (search == SMALLEST) + { + pdelta = w * h; + if ((!have_choice) || + ((pdelta <= chosen.pdelta) && + (((bpp >= 3) && (bpp >= chosen.bpp)) || + ((bpp < 3) && (cols >= chosen.cols))))) + { + have_choice = 1; + chosen.pdelta = pdelta; + chosen.w = w; + chosen.h = h; + chosen.cols = cols; + chosen.bpp = bpp; + chosen.planes = planes; + chosen.bmsize = bmsize; + chosen.bmoffset = bmoffset; + } + } + else if (search == SMALLER) + { + pdelta = (wanted_w * wanted_h) - (w * h); + if ((!have_choice) || + ((w <= wanted_w) && (h <= wanted_h) && + (pdelta <= chosen.pdelta) && + (((bpp >= 3) && (bpp >= chosen.bpp)) || + ((bpp < 3) && (cols >= chosen.cols))))) + { + have_choice = 1; + if (pdelta < 0) pdelta = 0x7fffffff; + chosen.pdelta = pdelta; + chosen.w = w; + chosen.h = h; + chosen.cols = cols; + chosen.bpp = bpp; + chosen.planes = planes; + chosen.bmsize = bmsize; + chosen.bmoffset = bmoffset; + } + } + else if (search == BIGGER) + { + pdelta = (w * h) - (wanted_w * wanted_h); + if ((!have_choice) || + ((w >= wanted_w) && (h >= wanted_h) && + (pdelta <= chosen.pdelta) && + (((bpp >= 3) && (bpp >= chosen.bpp)) || + ((bpp < 3) && (cols >= chosen.cols))))) + { + have_choice = 1; + if (pdelta < 0) pdelta = 0x7fffffff; + chosen.pdelta = pdelta; + chosen.w = w; + chosen.h = h; + chosen.cols = cols; + chosen.bpp = bpp; + chosen.planes = planes; + chosen.bmsize = bmsize; + chosen.bmoffset = bmoffset; + } + } + } + } + if (chosen.bmoffset == 0) goto close_file; + if (fseek(f, chosen.bmoffset, SEEK_SET) != 0) goto close_file; + + w = chosen.w; + h = chosen.h; + if ((w > 256) || (h > 256)) goto close_file; + if ((w < 1) || (h < 1) || (w > IMG_MAX_SIZE) || (h > IMG_MAX_SIZE) || + IMG_TOO_BIG(w, h)) + { + if (IMG_TOO_BIG(w, h)) + *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED; + else + *error = EVAS_LOAD_ERROR_GENERIC; + goto close_file; + } + + ie->w = w; + ie->h = h; + if (hasa) ie->flags.alpha = 1; + + fclose(f); + *error = EVAS_LOAD_ERROR_NONE; + return EINA_TRUE; + + close_file: + fclose(f); + return EINA_FALSE; +} + +static Eina_Bool +evas_image_load_file_data_ico(Image_Entry *ie, const char *file, const char *key, int *error) +{ + unsigned short word; + unsigned char byte; + unsigned int dword; + FILE *f; + int wanted_w = 0, wanted_h = 0, w, h, cols, i, planes = 0, + hot_x = 0, hot_y = 0, bpp = 0, pdelta, search = -1, have_choice = 0, + stride, pstride, j, right_way_up = 0; + unsigned int bmoffset, bmsize, bitcount, compression, imagesize, fsize, + colorsused, colorsimportant, *pal, *surface, *pix, none_zero_alpha = 0; + unsigned short reserved, type, count, planes2; + unsigned char *maskbuf, *pixbuf, *p; + struct { + int pdelta; + int w, h; + int cols; + int bpp, planes; + int hot_x, hot_y; + unsigned int bmoffset, bmsize; + } chosen = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + + f = fopen(file, "rb"); + if (!f) + { + *error = EVAS_LOAD_ERROR_DOES_NOT_EXIST; + return EINA_FALSE; + } + + *error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT; + fseek(f, 0, SEEK_END); + fsize = ftell(f); + fseek(f, 0, SEEK_SET); + if (fsize < (6 + 16 + 40)) goto close_file; + + // key: + // NULL == highest res + // biggest == highest res + // smallest == lowest res + // + // smaller == next size SMALLER than load opts WxH (if possible) + // bigger == next size BIGGER than load opts WxH (if possible) + // more ? + + search = BIGGEST; + if ((ie->load_opts.w > 0) && (ie->load_opts.h > 0)) + { + wanted_w = ie->load_opts.w; + wanted_h = ie->load_opts.h; + search = SMALLER; + } + + if (!read_ushort(f, &reserved)) goto close_file; + if (!read_ushort(f, &type)) goto close_file; + if (!read_ushort(f, &count)) goto close_file; + if (!((reserved == 0) && ((type == 1) || (type == 2)) && (count > 0))) + goto close_file; + *error = EVAS_LOAD_ERROR_CORRUPT_FILE; + + if (key) + { + if (!strcmp(key, "biggest")) + { + wanted_w = 0; + wanted_h = 0; + search = BIGGEST; + chosen.pdelta = 0; + } + else if (!strcmp(key, "smallest")) + { + wanted_w = 1; + wanted_h = 1; + search = SMALLEST; + chosen.pdelta = 0x7fffffff; + } + else if (!strcmp(key, "smaller")) + { + chosen.pdelta = 0x7fffffff; + search = SMALLER; + } + else if (!strcmp(key, "bigger")) + { + chosen.pdelta = 0x7fffffff; + search = BIGGER; + } + } + for (i = 0; i < count; i++) + { + if (fread(&byte, 1, 1, f) != 1) goto close_file; + w = byte; + if (w <= 0) w = 256; + if (fread(&byte, 1, 1, f) != 1) goto close_file; + h = byte; + if (h <= 0) h = 256; + if (fread(&byte, 1, 1, f) != 1) goto close_file; + cols = byte; + if (cols <= 0) cols = 256; + if (fread(&byte, 1, 1, f) != 1) goto close_file; + if (!read_ushort(f, &word)) goto close_file; + if (type == 1) planes = word; + else hot_x = word; + if (!read_ushort(f, &word)) goto close_file; + if (type == 1) bpp = word; + else hot_y = word; + if (!read_uint(f, &bmsize)) goto close_file; + if (!read_uint(f, &bmoffset)) goto close_file; + if ((bmsize <= 0) || (bmoffset <= 0) || (bmoffset >= fsize)) goto close_file; + if (search == BIGGEST) + { + pdelta = w * h; + if ((!have_choice) || + ((pdelta >= chosen.pdelta) && + (((bpp >= 3) && (bpp >= chosen.bpp)) || + ((bpp < 3) && (cols >= chosen.cols))))) + { + have_choice = 1; + chosen.pdelta = pdelta; + chosen.w = w; + chosen.h = h; + chosen.cols = cols; + chosen.bpp = bpp; + chosen.planes = planes; + chosen.bmsize = bmsize; + chosen.bmoffset = bmoffset; + } + } + else + { + if (search == SMALLEST) + { + pdelta = w * h; + if ((!have_choice) || + ((pdelta <= chosen.pdelta) && + (((bpp >= 3) && (bpp >= chosen.bpp)) || + ((bpp < 3) && (cols >= chosen.cols))))) + { + have_choice = 1; + chosen.pdelta = pdelta; + chosen.w = w; + chosen.h = h; + chosen.cols = cols; + chosen.bpp = bpp; + chosen.planes = planes; + chosen.bmsize = bmsize; + chosen.bmoffset = bmoffset; + } + } + else if (search == SMALLER) + { + pdelta = (wanted_w * wanted_h) - (w * h); + if ((!have_choice) || + ((w <= wanted_w) && (h <= wanted_h) && + (pdelta <= chosen.pdelta) && + (((bpp >= 3) && (bpp >= chosen.bpp)) || + ((bpp < 3) && (cols >= chosen.cols))))) + { + have_choice = 1; + if (pdelta < 0) pdelta = 0x7fffffff; + chosen.pdelta = pdelta; + chosen.w = w; + chosen.h = h; + chosen.cols = cols; + chosen.bpp = bpp; + chosen.planes = planes; + chosen.bmsize = bmsize; + chosen.bmoffset = bmoffset; + } + } + else if (search == BIGGER) + { + pdelta = (w * h) - (wanted_w * wanted_h); + if ((!have_choice) || + ((w >= wanted_w) && (h >= wanted_h) && + (pdelta <= chosen.pdelta) && + (((bpp >= 3) && (bpp >= chosen.bpp)) || + ((bpp < 3) && (cols >= chosen.cols))))) + { + have_choice = 1; + if (pdelta < 0) pdelta = 0x7fffffff; + chosen.pdelta = pdelta; + chosen.w = w; + chosen.h = h; + chosen.cols = cols; + chosen.bpp = bpp; + chosen.planes = planes; + chosen.bmsize = bmsize; + chosen.bmoffset = bmoffset; + } + } + } + } + if (chosen.bmoffset == 0) goto close_file; + if (fseek(f, chosen.bmoffset, SEEK_SET) != 0) goto close_file; + + w = chosen.w; + h = chosen.h; + cols = chosen.cols; + bpp = chosen.bpp; + if ((w < 1) || (h < 1) || (w > IMG_MAX_SIZE) || (h > IMG_MAX_SIZE) || + IMG_TOO_BIG(w, h)) + { + if (IMG_TOO_BIG(w, h)) + *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED; + else + *error = EVAS_LOAD_ERROR_GENERIC; + goto close_file; + } + // changed since we loaded header? + if (((int)ie->w != w) || ((int)ie->h != h)) goto close_file; + evas_cache_image_surface_alloc(ie, w, h); + surface = evas_cache_image_pixels(ie); + if (!surface) + { + *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED; + goto close_file; + } + + // read bmp header time... let's do some checking + if (!read_uint(f, &dword)) goto close_file; // headersize - dont care + if (!read_uint(f, &dword)) goto close_file; // width + if ((int)dword != w) goto close_file; + if (!read_uint(f, &dword)) goto close_file; // height + // h will be icon h * 2 - first mask then pixels + if (((int)dword != h) && ((int)dword != (h * 2))) goto close_file; + if (!read_ushort(f, &word)) goto close_file; // planes + planes2 = word; + if (!read_ushort(f, &word)) goto close_file; // bitcount + bitcount = word; + if (!read_uint(f, &dword)) goto close_file; // compression + compression = dword; + if (!read_uint(f, &dword)) goto close_file; // imagesize + imagesize = dword; + if (!read_uint(f, &dword)) goto close_file; // z pixels per m + if (!read_uint(f, &dword)) goto close_file; // y pizels per m + if (!read_uint(f, &dword)) goto close_file; // colors used + colorsused = dword; + if (!read_uint(f, &dword)) goto close_file; // colors important + colorsimportant = dword; + + if (cols == 0) cols = 1 << bitcount; + if (!((bitcount == 1) || (bitcount == 4) || (bitcount == 8) || + (bitcount == 24) || (bitcount == 32))) + goto close_file; + if ((bitcount <= 8) && (cols > 256)) goto close_file; + if (bitcount > 8) cols = 0; + + pal = alloca(256 * 4); + for (i = 0; i < cols; i++) + { + unsigned char a, r, g, b; + + if (fread(&b, 1, 1, f) != 1) goto close_file; + if (fread(&g, 1, 1, f) != 1) goto close_file; + if (fread(&r, 1, 1, f) != 1) goto close_file; + if (fread(&a, 1, 1, f) != 1) goto close_file; + a = 0xff; + pal[i] = ARGB_JOIN(a, r, g, b); + } + stride = ((w + 31) / 32); + maskbuf = alloca(stride * h); + pixbuf = alloca(stride * 32 * 4); // more than enough + pix = surface; + if (bitcount == 1) + { + pstride = stride; + for (i = 0; i < h; i++) + { + if (!right_way_up) pix = surface + ((h - 1 - i) * w); + if (fread(pixbuf, pstride, 1, f) != 1) goto close_file; + p = pixbuf; + for (j = 0; j < w; j++) + { + if ((j & 0x7) == 0x0) + { + *pix = pal[*p >> 7]; + } + else if ((j & 0x7) == 0x1) + { + *pix = pal[(*p >> 6) & 0x1]; + } + else if ((j & 0x7) == 0x2) + { + *pix = pal[(*p >> 5) & 0x1]; + } + else if ((j & 0x7) == 0x3) + { + *pix = pal[(*p >> 4) & 0x1]; + } + else if ((j & 0x7) == 0x4) + { + *pix = pal[(*p >> 3) & 0x1]; + } + else if ((j & 0x7) == 0x5) + { + *pix = pal[(*p >> 2) & 0x1]; + } + else if ((j & 0x7) == 0x6) + { + *pix = pal[(*p >> 1) & 0x1]; + } + else + { + *pix = pal[*p & 0x1]; + p++; + } + pix++; + } + } + } + else if (bitcount == 4) + { + pstride = ((w + 7) / 8) * 4; + for (i = 0; i < h; i++) + { + if (!right_way_up) pix = surface + ((h - 1 - i) * w); + if (fread(pixbuf, pstride, 1, f) != 1) goto close_file; + p = pixbuf; + for (j = 0; j < w; j++) + { + if ((j & 0x1) == 0x1) + { + *pix = pal[*p & 0x0f]; + p++; + } + else + { + *pix = pal[*p >> 4]; + } + pix++; + } + } + } + else if (bitcount == 8) + { + pstride = ((w + 3) / 4) * 4; + for (i = 0; i < h; i++) + { + if (!right_way_up) pix = surface + ((h - 1 - i) * w); + if (fread(pixbuf, pstride, 1, f) != 1) goto close_file; + p = pixbuf; + for (j = 0; j < w; j++) + { + *pix = pal[*p]; + p++; + pix++; + } + } + } + else if (bitcount == 24) + { + pstride = w * 3; + for (i = 0; i < h; i++) + { + if (!right_way_up) pix = surface + ((h - 1 - i) * w); + if (fread(pixbuf, pstride, 1, f) != 1) goto close_file; + p = pixbuf; + for (j = 0; j < w; j++) + { + unsigned char a, r, g, b; + + b = p[0]; + g = p[1]; + r = p[2]; + p += 3; + a = 0xff; + *pix = ARGB_JOIN(a, r, g, b); + pix++; + } + } + } + else if (bitcount == 32) + { + printf("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@***===--- %i\n", bitcount); + pstride = w * 4; + for (i = 0; i < h; i++) + { + if (!right_way_up) pix = surface + ((h - 1 - i) * w); + if (fread(pixbuf, pstride, 1, f) != 1) goto close_file; + p = pixbuf; + for (j = 0; j < w; j++) + { + unsigned char a, r, g, b; + + b = p[0]; + g = p[1]; + r = p[2]; + a = p[3]; + p += 4; + if (a) none_zero_alpha = 1; + *pix = ARGB_JOIN(a, r, g, b); + pix++; + } + } + } + if (!none_zero_alpha) + { + if (fread(maskbuf, stride * 4 * h, 1, f) != 1) goto close_file; + // apply mask + pix = surface; + for (i = 0; i < h; i++) + { + unsigned char *m; + + if (!right_way_up) pix = surface + ((h - 1 - i) * w); + m = maskbuf + (stride * i * 4); + for (j = 0; j < w; j++) + { + if (*m & (1 << (7 - (j & 0x7)))) + A_VAL(pix) = 0x00; + else + A_VAL(pix) = 0xff; + if ((j & 0x7) == 0x7) m++; + pix++; + } + } + } + + fclose(f); + + evas_common_image_premul(ie); + *error = EVAS_LOAD_ERROR_NONE; + return EINA_TRUE; + + close_file: + fclose(f); + return EINA_FALSE; +} + +static int +module_open(Evas_Module *em) +{ + if (!em) return 0; + em->functions = (void *)(&evas_image_load_ico_func); + return 1; +} + +static void +module_close(Evas_Module *em __UNUSED__) +{ +} + +static Evas_Module_Api evas_modapi = +{ + EVAS_MODULE_API_VERSION, + "ico", + "none", + { + module_open, + module_close + } +}; + +EVAS_MODULE_DEFINE(EVAS_MODULE_TYPE_IMAGE_LOADER, image_loader, ico); + +#ifndef EVAS_STATIC_BUILD_ICO +EVAS_EINA_MODULE_DEFINE(image_loader, ico); +#endif