forked from enlightenment/efl
parent
e076a78519
commit
5acbfcb6e3
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
.deps
|
||||
.libs
|
||||
Makefile
|
||||
Makefile.in
|
||||
*.lo
|
||||
*.la
|
|
@ -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
|
|
@ -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"
|
||||
};
|
||||
|
Loading…
Reference in New Issue