evas: add support for .9.png file to PNG loader.
This support Android 9 patch file format. Only black is a recognized color for both the stretch area and the content area. All other color are associated with being "white". Reviewed-by: Hermet Park <hermetpark@gmail.com> Differential Revision: https://phab.enlightenment.org/D9103
This commit is contained in:
parent
6a93e2ef3d
commit
382c580182
|
@ -10,6 +10,8 @@
|
||||||
#include "evas_private.h"
|
#include "evas_private.h"
|
||||||
|
|
||||||
#define PNG_BYTES_TO_CHECK 4
|
#define PNG_BYTES_TO_CHECK 4
|
||||||
|
#define WHITE 0xFFFFFFFF
|
||||||
|
#define BLACK 0xFF000000
|
||||||
|
|
||||||
typedef struct _Evas_PNG_Info Evas_PNG_Info;
|
typedef struct _Evas_PNG_Info Evas_PNG_Info;
|
||||||
struct _Evas_PNG_Info
|
struct _Evas_PNG_Info
|
||||||
|
@ -17,6 +19,13 @@ struct _Evas_PNG_Info
|
||||||
unsigned char *map;
|
unsigned char *map;
|
||||||
size_t length;
|
size_t length;
|
||||||
size_t position;
|
size_t position;
|
||||||
|
|
||||||
|
png_structp png_ptr;
|
||||||
|
png_infop info_ptr;
|
||||||
|
png_uint_32 w32, h32;
|
||||||
|
int bit_depth, color_type, interlace_type;
|
||||||
|
|
||||||
|
volatile Eina_Bool hasa;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct _Evas_Loader_Internal Evas_Loader_Internal;
|
typedef struct _Evas_Loader_Internal Evas_Loader_Internal;
|
||||||
|
@ -36,6 +45,34 @@ static const Evas_Colorspace cspace_grey_alpha[2] = {
|
||||||
EVAS_COLORSPACE_ARGB8888
|
EVAS_COLORSPACE_ARGB8888
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
_evas_image_png_update_x_content(Eina_Rectangle *r, int index)
|
||||||
|
{
|
||||||
|
if (r->x == 0)
|
||||||
|
{
|
||||||
|
r->x = index;
|
||||||
|
r->w = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
r->w = index - r->x;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_evas_image_png_update_y_content(Eina_Rectangle *r, int index)
|
||||||
|
{
|
||||||
|
if (r->y == 0)
|
||||||
|
{
|
||||||
|
r->y = index;
|
||||||
|
r->h = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
r->h = index - r->y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_evas_image_png_read(png_structp png_ptr, png_bytep out, png_size_t count)
|
_evas_image_png_read(png_structp png_ptr, png_bytep out, png_size_t count)
|
||||||
{
|
{
|
||||||
|
@ -76,77 +113,65 @@ evas_image_load_file_close_png(void *loader_data)
|
||||||
}
|
}
|
||||||
|
|
||||||
static Eina_Bool
|
static Eina_Bool
|
||||||
evas_image_load_file_head_png(void *loader_data,
|
_evas_image_load_file_internal_head_png(Evas_Loader_Internal *loader,
|
||||||
Emile_Image_Property *prop,
|
Evas_Image_Property *prop,
|
||||||
int *error)
|
Evas_PNG_Info *epi,
|
||||||
|
int *error, Eina_Bool close_file)
|
||||||
{
|
{
|
||||||
Evas_Loader_Internal *loader = loader_data;
|
Evas_Image_Load_Opts *opts = loader->opts;
|
||||||
Evas_Image_Load_Opts *opts;
|
Eina_File *f = loader->f;
|
||||||
Eina_File *f;
|
|
||||||
|
|
||||||
Evas_PNG_Info epi;
|
|
||||||
png_structp png_ptr = NULL;
|
|
||||||
png_infop info_ptr = NULL;
|
|
||||||
png_uint_32 w32, h32;
|
|
||||||
int bit_depth, color_type, interlace_type;
|
|
||||||
volatile char hasa;
|
|
||||||
volatile Eina_Bool r = EINA_FALSE;
|
volatile Eina_Bool r = EINA_FALSE;
|
||||||
|
|
||||||
opts = loader->opts;
|
*error = EVAS_LOAD_ERROR_NONE;
|
||||||
f = loader->f;
|
|
||||||
|
|
||||||
hasa = 0;
|
epi->hasa = 0;
|
||||||
epi.map = eina_file_map_all(f, EINA_FILE_RANDOM);
|
epi->map = eina_file_map_all(f, EINA_FILE_RANDOM);
|
||||||
if (!epi.map)
|
if (!epi->map)
|
||||||
{
|
{
|
||||||
*error = EVAS_LOAD_ERROR_CORRUPT_FILE;
|
*error = EVAS_LOAD_ERROR_CORRUPT_FILE;
|
||||||
goto close_file;
|
goto close_file;
|
||||||
}
|
}
|
||||||
epi.length = eina_file_size_get(f);
|
epi->length = eina_file_size_get(f);
|
||||||
epi.position = 0;
|
epi->position = 0;
|
||||||
|
|
||||||
if (epi.length < PNG_BYTES_TO_CHECK)
|
if (epi->length < PNG_BYTES_TO_CHECK)
|
||||||
{
|
{
|
||||||
*error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT;
|
*error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT;
|
||||||
goto close_file;
|
goto close_file;
|
||||||
|
}
|
||||||
|
if (png_sig_cmp(epi->map, 0, PNG_BYTES_TO_CHECK))
|
||||||
|
{
|
||||||
|
*error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT;
|
||||||
|
goto close_file;
|
||||||
|
}
|
||||||
|
epi->png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
|
||||||
|
if (!epi->png_ptr)
|
||||||
|
{
|
||||||
|
*error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
|
||||||
|
goto close_file;
|
||||||
|
}
|
||||||
|
epi->info_ptr = png_create_info_struct(epi->png_ptr);
|
||||||
|
if (!epi->info_ptr)
|
||||||
|
{
|
||||||
|
*error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
|
||||||
|
goto close_file;
|
||||||
|
}
|
||||||
|
png_set_read_fn(epi->png_ptr, epi, _evas_image_png_read);
|
||||||
|
if (setjmp(png_jmpbuf(epi->png_ptr)))
|
||||||
|
{
|
||||||
|
*error = EVAS_LOAD_ERROR_CORRUPT_FILE;
|
||||||
|
goto close_file;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (png_sig_cmp(epi.map, 0, PNG_BYTES_TO_CHECK))
|
png_read_info(epi->png_ptr, epi->info_ptr);
|
||||||
|
png_get_IHDR(epi->png_ptr, epi->info_ptr, (png_uint_32 *) (&epi->w32),
|
||||||
|
(png_uint_32 *) (&epi->h32), &epi->bit_depth, &epi->color_type,
|
||||||
|
&epi->interlace_type, NULL, NULL);
|
||||||
|
if ((epi->w32 < 1) || (epi->h32 < 1) ||
|
||||||
|
(epi->w32 > IMG_MAX_SIZE) || (epi->h32 > IMG_MAX_SIZE) ||
|
||||||
|
IMG_TOO_BIG(epi->w32, epi->h32))
|
||||||
{
|
{
|
||||||
*error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT;
|
if (IMG_TOO_BIG(epi->w32, epi->h32))
|
||||||
goto close_file;
|
|
||||||
}
|
|
||||||
|
|
||||||
png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
|
|
||||||
if (!png_ptr)
|
|
||||||
{
|
|
||||||
*error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
|
|
||||||
goto close_file;
|
|
||||||
}
|
|
||||||
|
|
||||||
info_ptr = png_create_info_struct(png_ptr);
|
|
||||||
if (!info_ptr)
|
|
||||||
{
|
|
||||||
*error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
|
|
||||||
goto close_file;
|
|
||||||
}
|
|
||||||
|
|
||||||
png_set_read_fn(png_ptr, &epi, _evas_image_png_read);
|
|
||||||
|
|
||||||
if (setjmp(png_jmpbuf(png_ptr)))
|
|
||||||
{
|
|
||||||
*error = EVAS_LOAD_ERROR_CORRUPT_FILE;
|
|
||||||
goto close_file;
|
|
||||||
}
|
|
||||||
|
|
||||||
png_read_info(png_ptr, info_ptr);
|
|
||||||
png_get_IHDR(png_ptr, info_ptr, (png_uint_32 *) (&w32),
|
|
||||||
(png_uint_32 *) (&h32), &bit_depth, &color_type,
|
|
||||||
&interlace_type, NULL, NULL);
|
|
||||||
if ((w32 < 1) || (h32 < 1) || (w32 > IMG_MAX_SIZE) || (h32 > IMG_MAX_SIZE) ||
|
|
||||||
IMG_TOO_BIG(w32, h32))
|
|
||||||
{
|
|
||||||
if (IMG_TOO_BIG(w32, h32))
|
|
||||||
*error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
|
*error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
|
||||||
else
|
else
|
||||||
*error = EVAS_LOAD_ERROR_GENERIC;
|
*error = EVAS_LOAD_ERROR_GENERIC;
|
||||||
|
@ -155,28 +180,28 @@ evas_image_load_file_head_png(void *loader_data,
|
||||||
|
|
||||||
if (opts->emile.region.w > 0 && opts->emile.region.h > 0)
|
if (opts->emile.region.w > 0 && opts->emile.region.h > 0)
|
||||||
{
|
{
|
||||||
if (((int) w32 < opts->emile.region.x + opts->emile.region.w) ||
|
if (((int) epi->w32 < opts->emile.region.x + opts->emile.region.w) ||
|
||||||
((int) h32 < opts->emile.region.y + opts->emile.region.h))
|
((int) epi->h32 < opts->emile.region.y + opts->emile.region.h))
|
||||||
{
|
{
|
||||||
*error = EVAS_LOAD_ERROR_GENERIC;
|
*error = EVAS_LOAD_ERROR_GENERIC;
|
||||||
goto close_file;
|
goto close_file;
|
||||||
}
|
}
|
||||||
if(opts->emile.scale_down_by > 1)
|
if(opts->emile.scale_down_by > 1)
|
||||||
{
|
{
|
||||||
prop->w = opts->emile.region.w / opts->emile.scale_down_by;
|
prop->info.w = opts->emile.region.w / opts->emile.scale_down_by;
|
||||||
prop->h = opts->emile.region.h / opts->emile.scale_down_by;
|
prop->info.h = opts->emile.region.h / opts->emile.scale_down_by;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
prop->w = opts->emile.region.w;
|
prop->info.w = opts->emile.region.w;
|
||||||
prop->h = opts->emile.region.h;
|
prop->info.h = opts->emile.region.h;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (opts->emile.scale_down_by > 1)
|
else if (opts->emile.scale_down_by > 1)
|
||||||
{
|
{
|
||||||
prop->w = (int) w32 / opts->emile.scale_down_by;
|
prop->info.w = (int) epi->w32 / opts->emile.scale_down_by;
|
||||||
prop->h = (int) h32 / opts->emile.scale_down_by;
|
prop->info.h = (int) epi->h32 / opts->emile.scale_down_by;
|
||||||
if ((prop->w < 1) || (prop->h < 1))
|
if ((prop->info.w < 1) || (prop->info.h < 1))
|
||||||
{
|
{
|
||||||
*error = EVAS_LOAD_ERROR_GENERIC;
|
*error = EVAS_LOAD_ERROR_GENERIC;
|
||||||
goto close_file;
|
goto close_file;
|
||||||
|
@ -184,40 +209,371 @@ evas_image_load_file_head_png(void *loader_data,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
prop->w = (int) w32;
|
prop->info.w = (int) epi->w32;
|
||||||
prop->h = (int) h32;
|
prop->info.h = (int) epi->h32;
|
||||||
}
|
}
|
||||||
if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) hasa = 1;
|
if (png_get_valid(epi->png_ptr, epi->info_ptr, PNG_INFO_tRNS)) epi->hasa = 1;
|
||||||
switch (color_type)
|
switch (epi->color_type)
|
||||||
{
|
{
|
||||||
case PNG_COLOR_TYPE_RGB_ALPHA:
|
case PNG_COLOR_TYPE_RGB_ALPHA:
|
||||||
hasa = 1;
|
epi->hasa = 1;
|
||||||
break;
|
break;
|
||||||
case PNG_COLOR_TYPE_GRAY_ALPHA:
|
case PNG_COLOR_TYPE_GRAY_ALPHA:
|
||||||
hasa = 1;
|
epi->hasa = 1;
|
||||||
prop->cspaces = cspace_grey_alpha;
|
prop->info.cspaces = cspace_grey_alpha;
|
||||||
break;
|
break;
|
||||||
case PNG_COLOR_TYPE_GRAY:
|
case PNG_COLOR_TYPE_GRAY:
|
||||||
if (!hasa) prop->cspaces = cspace_grey;
|
if (!epi->hasa) prop->info.cspaces = cspace_grey;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (hasa) prop->alpha = 1;
|
if (epi->hasa) prop->info.alpha = 1;
|
||||||
|
|
||||||
|
prop->need_data = eina_str_has_extension(eina_file_filename_get(f), ".9.png");
|
||||||
|
if (prop->need_data)
|
||||||
|
{
|
||||||
|
// Adjust size to take into account the 9 patch pixels information
|
||||||
|
prop->info.w -= 2;
|
||||||
|
prop->info.h -= 2;
|
||||||
|
}
|
||||||
|
|
||||||
*error = EVAS_LOAD_ERROR_NONE;
|
|
||||||
r = EINA_TRUE;
|
r = EINA_TRUE;
|
||||||
|
|
||||||
|
if (!close_file) return r;
|
||||||
|
|
||||||
close_file:
|
close_file:
|
||||||
if (png_ptr) png_destroy_read_struct(&png_ptr,
|
if (epi->png_ptr) png_destroy_read_struct(&epi->png_ptr,
|
||||||
info_ptr ? &info_ptr : NULL,
|
epi->info_ptr ? &epi->info_ptr : NULL,
|
||||||
NULL);
|
NULL);
|
||||||
if (epi.map) eina_file_map_free(f, epi. map);
|
if (epi->map) eina_file_map_free(f, epi->map);
|
||||||
|
memset(epi, 0, sizeof (Evas_PNG_Info));
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Eina_Bool
|
||||||
|
evas_image_load_file_head_png(void *loader_data,
|
||||||
|
Evas_Image_Property *prop,
|
||||||
|
int *error)
|
||||||
|
{
|
||||||
|
Evas_Loader_Internal *loader = loader_data;
|
||||||
|
Evas_PNG_Info epi;
|
||||||
|
|
||||||
|
memset(&epi, 0, sizeof (Evas_PNG_Info));
|
||||||
|
|
||||||
|
if (!_evas_image_load_file_internal_head_png(loader, prop, &epi, error, EINA_TRUE))
|
||||||
|
return EINA_FALSE;
|
||||||
|
|
||||||
|
return EINA_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline Eina_Bool
|
||||||
|
_is_black(DATA32 *ptr)
|
||||||
|
{
|
||||||
|
if (*ptr == BLACK) return EINA_TRUE;
|
||||||
|
return EINA_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Eina_Bool
|
||||||
|
evas_image_load_file_head_with_data_png(void *loader_data,
|
||||||
|
Evas_Image_Property *prop,
|
||||||
|
void *pixels,
|
||||||
|
int *error)
|
||||||
|
{
|
||||||
|
Evas_Loader_Internal *loader = loader_data;
|
||||||
|
Evas_Image_Load_Opts *opts;
|
||||||
|
Eina_File *f;
|
||||||
|
|
||||||
|
unsigned char *src_ptr;
|
||||||
|
unsigned char *pixels2;
|
||||||
|
unsigned char *surface;
|
||||||
|
Evas_PNG_Info epi;
|
||||||
|
Eina_Rectangle region;
|
||||||
|
unsigned int pack_offset;
|
||||||
|
int w, h;
|
||||||
|
char passes;
|
||||||
|
int i, j, p, k;
|
||||||
|
volatile int scale_ratio = 1;
|
||||||
|
int image_w = 0, image_h = 0;
|
||||||
|
volatile Eina_Bool r = EINA_FALSE;
|
||||||
|
Eina_Bool nine_patch = EINA_FALSE;
|
||||||
|
|
||||||
|
opts = loader->opts;
|
||||||
|
f = loader->f;
|
||||||
|
|
||||||
|
memset(&epi, 0, sizeof (Evas_PNG_Info));
|
||||||
|
region = opts->emile.region;
|
||||||
|
|
||||||
|
if (!_evas_image_load_file_internal_head_png(loader, prop, &epi, error, EINA_FALSE))
|
||||||
|
return EINA_FALSE;
|
||||||
|
|
||||||
|
image_w = epi.w32;
|
||||||
|
image_h = epi.h32;
|
||||||
|
|
||||||
|
// We are leveragging region code to not load the border information pixels
|
||||||
|
// from 9patch files into the surface used by Evas
|
||||||
|
if (prop->need_data)
|
||||||
|
{
|
||||||
|
nine_patch = EINA_TRUE;
|
||||||
|
|
||||||
|
region.x += 1;
|
||||||
|
region.y += 1;
|
||||||
|
|
||||||
|
if (region.w > 0 && region.h > 0)
|
||||||
|
{
|
||||||
|
if (region.x + region.w + 1 < image_w) region.w += 1;
|
||||||
|
else region.w = image_w - region.x - 1;
|
||||||
|
if (region.y + region.h + 1 < image_h) region.h += 1;
|
||||||
|
else region.h = image_h - region.y - 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
region.w = image_w - region.x - 1;
|
||||||
|
region.h = image_h - region.y - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
surface = pixels;
|
||||||
|
|
||||||
|
/* Prep for transformations... ultimately we want ARGB */
|
||||||
|
/* expand palette -> RGB if necessary */
|
||||||
|
if (epi.color_type == PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb(epi.png_ptr);
|
||||||
|
/* expand gray (w/reduced bits) -> 8-bit RGB if necessary */
|
||||||
|
if ((epi.color_type == PNG_COLOR_TYPE_GRAY) ||
|
||||||
|
(epi.color_type == PNG_COLOR_TYPE_GRAY_ALPHA))
|
||||||
|
{
|
||||||
|
if (prop->info.cspace == EVAS_COLORSPACE_ARGB8888)
|
||||||
|
png_set_gray_to_rgb(epi.png_ptr);
|
||||||
|
if (epi.bit_depth < 8) png_set_expand_gray_1_2_4_to_8(epi.png_ptr);
|
||||||
|
}
|
||||||
|
/* reduce 16bit color -> 8bit color if necessary */
|
||||||
|
if (epi.bit_depth > 8) png_set_strip_16(epi.png_ptr);
|
||||||
|
/* pack all pixels to byte boundaries */
|
||||||
|
png_set_packing(epi.png_ptr);
|
||||||
|
|
||||||
|
w = prop->info.w;
|
||||||
|
h = prop->info.h;
|
||||||
|
|
||||||
|
switch (prop->info.cspace)
|
||||||
|
{
|
||||||
|
case EVAS_COLORSPACE_ARGB8888:
|
||||||
|
/* we want ARGB */
|
||||||
|
#ifdef WORDS_BIGENDIAN
|
||||||
|
png_set_swap_alpha(epi.png_ptr);
|
||||||
|
if (!epi.hasa) png_set_filler(epi.png_ptr, 0xff, PNG_FILLER_BEFORE);
|
||||||
|
#else
|
||||||
|
png_set_bgr(epi.png_ptr);
|
||||||
|
if (!epi.hasa) png_set_filler(epi.png_ptr, 0xff, PNG_FILLER_AFTER);
|
||||||
|
#endif
|
||||||
|
pack_offset = sizeof(DATA32);
|
||||||
|
break;
|
||||||
|
case EVAS_COLORSPACE_AGRY88:
|
||||||
|
/* we want AGRY */
|
||||||
|
#ifdef WORDS_BIGENDIAN
|
||||||
|
png_set_swap_alpha(epi.png_ptr);
|
||||||
|
if (!epi.hasa) png_set_filler(epi.png_ptr, 0xff, PNG_FILLER_BEFORE);
|
||||||
|
#else
|
||||||
|
if (!epi.hasa) png_set_filler(epi.png_ptr, 0xff, PNG_FILLER_AFTER);
|
||||||
|
#endif
|
||||||
|
pack_offset = sizeof(DATA16);
|
||||||
|
break;
|
||||||
|
case EVAS_COLORSPACE_GRY8: pack_offset = sizeof(DATA8); break;
|
||||||
|
default: abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
passes = png_set_interlace_handling(epi.png_ptr);
|
||||||
|
|
||||||
|
/* we read image line by line in all case because of .9.png */
|
||||||
|
pixels2 = malloc(image_w * image_h * pack_offset);
|
||||||
|
if (!pixels2)
|
||||||
|
{
|
||||||
|
*error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
|
||||||
|
goto close_file;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (p = 0; p < passes; p++)
|
||||||
|
{
|
||||||
|
for (i = 0; i < image_h; i++)
|
||||||
|
png_read_row(epi.png_ptr, pixels2 + (i * image_w * pack_offset), NULL);
|
||||||
|
}
|
||||||
|
png_read_end(epi.png_ptr, epi.info_ptr);
|
||||||
|
|
||||||
|
if (nine_patch && pack_offset != sizeof (DATA32))
|
||||||
|
{
|
||||||
|
*error = EVAS_LOAD_ERROR_CORRUPT_FILE;
|
||||||
|
goto close_file;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nine_patch)
|
||||||
|
{
|
||||||
|
DATA32 *src_ptr1;
|
||||||
|
DATA32 *src_ptr2;
|
||||||
|
Eina_Bool stretchable = EINA_FALSE;
|
||||||
|
Eina_Rectangle optional_content = { 0 };
|
||||||
|
uint8_t current = 0;
|
||||||
|
|
||||||
|
memset(&prop->content, 0, sizeof (Eina_Rectangle));
|
||||||
|
|
||||||
|
// Top line of the image
|
||||||
|
src_ptr1 = (DATA32*) pixels2 + 1;
|
||||||
|
// Bottom line of the image
|
||||||
|
src_ptr2 = src_ptr1 + (image_h - 1) * image_w;
|
||||||
|
|
||||||
|
// Extract top stretch zone and horizontal content area
|
||||||
|
for (i = 1; i < image_w - 1;
|
||||||
|
i++, src_ptr1++, src_ptr2++)
|
||||||
|
{
|
||||||
|
Eina_Bool bp1 = _is_black(src_ptr1);
|
||||||
|
Eina_Bool bp2 = _is_black(src_ptr2);
|
||||||
|
|
||||||
|
// Updating horizontal area where content can be located
|
||||||
|
if (bp2)
|
||||||
|
_evas_image_png_update_x_content(&prop->content, i);
|
||||||
|
|
||||||
|
// In case no content area is provided, let's make it up
|
||||||
|
if (bp1)
|
||||||
|
_evas_image_png_update_x_content(&optional_content, i);
|
||||||
|
|
||||||
|
// Switching from a non stretchable to a stretchable zone or the opposite
|
||||||
|
if (!((stretchable && (bp1)) ||
|
||||||
|
(!stretchable && (!bp1))))
|
||||||
|
{
|
||||||
|
evas_loader_helper_stretch_region_push(&prop->stretch.horizontal.region,
|
||||||
|
¤t, stretchable);
|
||||||
|
stretchable = !stretchable;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Keep counting in the area we are in
|
||||||
|
current++;
|
||||||
|
|
||||||
|
if (current != 0x7F) continue;
|
||||||
|
|
||||||
|
// The bucket is full
|
||||||
|
evas_loader_helper_stretch_region_push(&prop->stretch.horizontal.region,
|
||||||
|
¤t, stretchable);
|
||||||
|
}
|
||||||
|
|
||||||
|
current = 0;
|
||||||
|
|
||||||
|
// Left border of the image
|
||||||
|
src_ptr1 = (DATA32*) pixels2 + image_w;
|
||||||
|
// Right border of the image
|
||||||
|
src_ptr2 = src_ptr1 + (image_w - 1);
|
||||||
|
|
||||||
|
for (i = 1; i < image_h - 1;
|
||||||
|
i++, src_ptr1 += image_w, src_ptr2 += image_w)
|
||||||
|
{
|
||||||
|
Eina_Bool bp1 = _is_black(src_ptr1);
|
||||||
|
Eina_Bool bp2 = _is_black(src_ptr2);
|
||||||
|
|
||||||
|
// Updating vertical area where content can be located
|
||||||
|
if (bp2)
|
||||||
|
_evas_image_png_update_y_content(&prop->content, i);
|
||||||
|
|
||||||
|
// In case no content area is provided, let's make it up
|
||||||
|
if (bp1)
|
||||||
|
_evas_image_png_update_y_content(&optional_content, i);
|
||||||
|
|
||||||
|
// Switching from a non stretchable to a stretchable zone or the opposite
|
||||||
|
if (!((stretchable && (bp1)) ||
|
||||||
|
(!stretchable && (!bp1))))
|
||||||
|
{
|
||||||
|
evas_loader_helper_stretch_region_push(&prop->stretch.vertical.region,
|
||||||
|
¤t, stretchable);
|
||||||
|
stretchable = !stretchable;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Keep counting in the area we are in
|
||||||
|
current++;
|
||||||
|
|
||||||
|
if (current != 0x7F) continue;
|
||||||
|
|
||||||
|
// The bucket is full
|
||||||
|
evas_loader_helper_stretch_region_push(&prop->stretch.vertical.region,
|
||||||
|
¤t, stretchable);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Content zone is optional, if not provided, we should use the one we guessed
|
||||||
|
if (prop->content.x == 0 || prop->content.y == 0)
|
||||||
|
memcpy(&prop->content, &optional_content, sizeof (Eina_Rectangle));
|
||||||
|
|
||||||
|
// Check that the limit of our content zone are correct
|
||||||
|
// This could be handled as an incorrect file completly,
|
||||||
|
// but let's try to recover
|
||||||
|
if (prop->content.x == 0 || prop->content.y == 0)
|
||||||
|
{
|
||||||
|
*error = EVAS_LOAD_ERROR_CORRUPT_FILE;
|
||||||
|
goto close_file;
|
||||||
|
}
|
||||||
|
if ((prop->content.x + prop->content.w >= image_w - 1) &&
|
||||||
|
(prop->content.y + prop->content.h >= image_h - 1))
|
||||||
|
{
|
||||||
|
*error = EVAS_LOAD_ERROR_CORRUPT_FILE;
|
||||||
|
goto close_file;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Correct the work space to be the same as the image one for intersection
|
||||||
|
// with region and correct back afterward.
|
||||||
|
prop->content.x++;
|
||||||
|
prop->content.y++;
|
||||||
|
if (eina_rectangle_intersection(&prop->content, ®ion))
|
||||||
|
{
|
||||||
|
prop->content.x--;
|
||||||
|
prop->content.y--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
src_ptr = pixels2 + (region.y * image_w * pack_offset) + region.x * pack_offset;
|
||||||
|
|
||||||
|
//general case: 4 bytes pixel.
|
||||||
|
if (pack_offset == sizeof(DATA32))
|
||||||
|
{
|
||||||
|
DATA32 *dst_ptr = (DATA32 *) surface;
|
||||||
|
DATA32 *src_ptr2 = (DATA32 *) src_ptr;
|
||||||
|
|
||||||
|
for (i = 0; i < h; i++)
|
||||||
|
{
|
||||||
|
for (j = 0; j < w; j++)
|
||||||
|
{
|
||||||
|
*dst_ptr = *src_ptr2;
|
||||||
|
++dst_ptr;
|
||||||
|
src_ptr2 += scale_ratio;
|
||||||
|
}
|
||||||
|
src_ptr2 += scale_ratio * (image_w - w);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
unsigned char *dst_ptr = surface;
|
||||||
|
|
||||||
|
for (i = 0; i < h; i++)
|
||||||
|
{
|
||||||
|
for (j = 0; j < w; j++)
|
||||||
|
{
|
||||||
|
for (k = 0; k < (int)pack_offset; k++)
|
||||||
|
dst_ptr[k] = src_ptr[k + scale_ratio * j * pack_offset];
|
||||||
|
dst_ptr += pack_offset;
|
||||||
|
}
|
||||||
|
src_ptr += scale_ratio * (image_w - w) * pack_offset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(pixels2);
|
||||||
|
|
||||||
|
prop->info.premul = EINA_TRUE;
|
||||||
|
|
||||||
|
*error = EVAS_LOAD_ERROR_NONE;
|
||||||
|
r = EINA_TRUE;
|
||||||
|
|
||||||
|
close_file:
|
||||||
|
if (epi.png_ptr) png_destroy_read_struct(&epi.png_ptr,
|
||||||
|
epi.info_ptr ? &epi.info_ptr : NULL,
|
||||||
|
NULL);
|
||||||
|
if (epi.map) eina_file_map_free(f, epi.map);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
static Eina_Bool
|
static Eina_Bool
|
||||||
evas_image_load_file_data_png(void *loader_data,
|
evas_image_load_file_data_png(void *loader_data,
|
||||||
Emile_Image_Property *prop,
|
Evas_Image_Property *prop,
|
||||||
void *pixels,
|
void *pixels,
|
||||||
int *error)
|
int *error)
|
||||||
{
|
{
|
||||||
|
@ -226,14 +582,9 @@ evas_image_load_file_data_png(void *loader_data,
|
||||||
Eina_File *f;
|
Eina_File *f;
|
||||||
|
|
||||||
unsigned char *surface;
|
unsigned char *surface;
|
||||||
png_structp png_ptr = NULL;
|
|
||||||
png_infop info_ptr = NULL;
|
|
||||||
Evas_PNG_Info epi;
|
Evas_PNG_Info epi;
|
||||||
png_uint_32 w32, h32;
|
|
||||||
unsigned int pack_offset;
|
unsigned int pack_offset;
|
||||||
int w, h;
|
int w, h;
|
||||||
int bit_depth, color_type, interlace_type;
|
|
||||||
volatile char hasa;
|
|
||||||
char passes;
|
char passes;
|
||||||
int i, j, p, k;
|
int i, j, p, k;
|
||||||
volatile int scale_ratio = 1;
|
volatile int scale_ratio = 1;
|
||||||
|
@ -244,131 +595,76 @@ evas_image_load_file_data_png(void *loader_data,
|
||||||
opts = loader->opts;
|
opts = loader->opts;
|
||||||
f = loader->f;
|
f = loader->f;
|
||||||
|
|
||||||
hasa = 0;
|
memset(&epi, 0, sizeof (Evas_PNG_Info));
|
||||||
|
|
||||||
epi.map = eina_file_map_all(f, EINA_FILE_SEQUENTIAL);
|
if (!_evas_image_load_file_internal_head_png(loader, prop, &epi, error, EINA_FALSE))
|
||||||
if (!epi.map)
|
return EINA_FALSE;
|
||||||
{
|
|
||||||
*error = EVAS_LOAD_ERROR_CORRUPT_FILE;
|
|
||||||
goto close_file;
|
|
||||||
}
|
|
||||||
epi.length = eina_file_size_get(f);
|
|
||||||
epi.position = 0;
|
|
||||||
|
|
||||||
if (epi.length < PNG_BYTES_TO_CHECK)
|
image_w = epi.w32;
|
||||||
{
|
image_h = epi.h32;
|
||||||
*error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT;
|
|
||||||
goto close_file;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* if we havent read the header before, set the header data */
|
|
||||||
if (png_sig_cmp(epi.map, 0, PNG_BYTES_TO_CHECK))
|
|
||||||
{
|
|
||||||
*error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT;
|
|
||||||
goto close_file;
|
|
||||||
}
|
|
||||||
png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
|
|
||||||
if (!png_ptr)
|
|
||||||
{
|
|
||||||
*error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
|
|
||||||
goto close_file;
|
|
||||||
}
|
|
||||||
|
|
||||||
info_ptr = png_create_info_struct(png_ptr);
|
|
||||||
if (!info_ptr)
|
|
||||||
{
|
|
||||||
png_destroy_read_struct(&png_ptr, NULL, NULL);
|
|
||||||
*error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
|
|
||||||
goto close_file;
|
|
||||||
}
|
|
||||||
|
|
||||||
png_set_read_fn(png_ptr, &epi, _evas_image_png_read);
|
|
||||||
|
|
||||||
if (setjmp(png_jmpbuf(png_ptr)))
|
|
||||||
{
|
|
||||||
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
|
||||||
*error = EVAS_LOAD_ERROR_CORRUPT_FILE;
|
|
||||||
goto close_file;
|
|
||||||
}
|
|
||||||
|
|
||||||
png_read_info(png_ptr, info_ptr);
|
|
||||||
png_get_IHDR(png_ptr, info_ptr, (png_uint_32 *) (&w32),
|
|
||||||
(png_uint_32 *) (&h32), &bit_depth, &color_type,
|
|
||||||
&interlace_type, NULL, NULL);
|
|
||||||
image_w = w32;
|
|
||||||
image_h = h32;
|
|
||||||
if (opts->emile.scale_down_by > 1)
|
if (opts->emile.scale_down_by > 1)
|
||||||
{
|
{
|
||||||
scale_ratio = opts->emile.scale_down_by;
|
scale_ratio = opts->emile.scale_down_by;
|
||||||
w32 /= scale_ratio;
|
epi.w32 /= scale_ratio;
|
||||||
h32 /= scale_ratio;
|
epi.h32 /= scale_ratio;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((opts->emile.region.w > 0 && opts->emile.region.h > 0) &&
|
if ((opts->emile.region.w > 0 && opts->emile.region.h > 0) &&
|
||||||
(opts->emile.region.w != image_w || opts->emile.region.h != image_h))
|
(opts->emile.region.w != image_w || opts->emile.region.h != image_h))
|
||||||
{
|
{
|
||||||
w32 = opts->emile.region.w / scale_ratio;
|
epi.w32 = opts->emile.region.w / scale_ratio;
|
||||||
h32 = opts->emile.region.h / scale_ratio;
|
epi.h32 = opts->emile.region.h / scale_ratio;
|
||||||
region_set = 1;
|
region_set = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (prop->w != w32 ||
|
if (prop->info.w != epi.w32 ||
|
||||||
prop->h != h32)
|
prop->info.h != epi.h32)
|
||||||
{
|
{
|
||||||
*error = EVAS_LOAD_ERROR_GENERIC;
|
*error = EVAS_LOAD_ERROR_GENERIC;
|
||||||
goto close_file;
|
goto close_file;
|
||||||
}
|
}
|
||||||
|
|
||||||
surface = pixels;
|
surface = pixels;
|
||||||
if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
|
|
||||||
{
|
|
||||||
/* expand transparency entry -> alpha channel if present */
|
|
||||||
png_set_tRNS_to_alpha(png_ptr);
|
|
||||||
hasa = 1;
|
|
||||||
}
|
|
||||||
if (color_type == PNG_COLOR_TYPE_RGB_ALPHA) hasa = 1;
|
|
||||||
if (color_type == PNG_COLOR_TYPE_GRAY_ALPHA) hasa = 1;
|
|
||||||
if (hasa) prop->alpha = 1;
|
|
||||||
|
|
||||||
/* Prep for transformations... ultimately we want ARGB */
|
/* Prep for transformations... ultimately we want ARGB */
|
||||||
/* expand palette -> RGB if necessary */
|
/* expand palette -> RGB if necessary */
|
||||||
if (color_type == PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb(png_ptr);
|
if (epi.color_type == PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb(epi.png_ptr);
|
||||||
/* expand gray (w/reduced bits) -> 8-bit RGB if necessary */
|
/* expand gray (w/reduced bits) -> 8-bit RGB if necessary */
|
||||||
if ((color_type == PNG_COLOR_TYPE_GRAY) ||
|
if ((epi.color_type == PNG_COLOR_TYPE_GRAY) ||
|
||||||
(color_type == PNG_COLOR_TYPE_GRAY_ALPHA))
|
(epi.color_type == PNG_COLOR_TYPE_GRAY_ALPHA))
|
||||||
{
|
{
|
||||||
if (prop->cspace == EVAS_COLORSPACE_ARGB8888)
|
if (prop->info.cspace == EVAS_COLORSPACE_ARGB8888)
|
||||||
png_set_gray_to_rgb(png_ptr);
|
png_set_gray_to_rgb(epi.png_ptr);
|
||||||
if (bit_depth < 8) png_set_expand_gray_1_2_4_to_8(png_ptr);
|
if (epi.bit_depth < 8) png_set_expand_gray_1_2_4_to_8(epi.png_ptr);
|
||||||
}
|
}
|
||||||
/* reduce 16bit color -> 8bit color if necessary */
|
/* reduce 16bit color -> 8bit color if necessary */
|
||||||
if (bit_depth > 8) png_set_strip_16(png_ptr);
|
if (epi.bit_depth > 8) png_set_strip_16(epi.png_ptr);
|
||||||
/* pack all pixels to byte boundaries */
|
/* pack all pixels to byte boundaries */
|
||||||
png_set_packing(png_ptr);
|
png_set_packing(epi.png_ptr);
|
||||||
|
|
||||||
w = w32;
|
w = epi.w32;
|
||||||
h = h32;
|
h = epi.h32;
|
||||||
|
|
||||||
switch (prop->cspace)
|
switch (prop->info.cspace)
|
||||||
{
|
{
|
||||||
case EVAS_COLORSPACE_ARGB8888:
|
case EVAS_COLORSPACE_ARGB8888:
|
||||||
/* we want ARGB */
|
/* we want ARGB */
|
||||||
#ifdef WORDS_BIGENDIAN
|
#ifdef WORDS_BIGENDIAN
|
||||||
png_set_swap_alpha(png_ptr);
|
png_set_swap_alpha(epi.png_ptr);
|
||||||
if (!hasa) png_set_filler(png_ptr, 0xff, PNG_FILLER_BEFORE);
|
if (!epi.hasa) png_set_filler(epi.png_ptr, 0xff, PNG_FILLER_BEFORE);
|
||||||
#else
|
#else
|
||||||
png_set_bgr(png_ptr);
|
png_set_bgr(epi.png_ptr);
|
||||||
if (!hasa) png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);
|
if (!epi.hasa) png_set_filler(epi.png_ptr, 0xff, PNG_FILLER_AFTER);
|
||||||
#endif
|
#endif
|
||||||
pack_offset = sizeof(DATA32);
|
pack_offset = sizeof(DATA32);
|
||||||
break;
|
break;
|
||||||
case EVAS_COLORSPACE_AGRY88:
|
case EVAS_COLORSPACE_AGRY88:
|
||||||
/* we want AGRY */
|
/* we want AGRY */
|
||||||
#ifdef WORDS_BIGENDIAN
|
#ifdef WORDS_BIGENDIAN
|
||||||
png_set_swap_alpha(png_ptr);
|
png_set_swap_alpha(epi.png_ptr);
|
||||||
if (!hasa) png_set_filler(png_ptr, 0xff, PNG_FILLER_BEFORE);
|
if (!epi.hasa) png_set_filler(epi.png_ptr, 0xff, PNG_FILLER_BEFORE);
|
||||||
#else
|
#else
|
||||||
if (!hasa) png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);
|
if (!epi.hasa) png_set_filler(epi.png_ptr, 0xff, PNG_FILLER_AFTER);
|
||||||
#endif
|
#endif
|
||||||
pack_offset = sizeof(DATA16);
|
pack_offset = sizeof(DATA16);
|
||||||
break;
|
break;
|
||||||
|
@ -376,7 +672,7 @@ evas_image_load_file_data_png(void *loader_data,
|
||||||
default: abort();
|
default: abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
passes = png_set_interlace_handling(png_ptr);
|
passes = png_set_interlace_handling(epi.png_ptr);
|
||||||
|
|
||||||
/* we read image line by line if scale down was set */
|
/* we read image line by line if scale down was set */
|
||||||
if (scale_ratio == 1 && region_set == 0)
|
if (scale_ratio == 1 && region_set == 0)
|
||||||
|
@ -384,9 +680,9 @@ evas_image_load_file_data_png(void *loader_data,
|
||||||
for (p = 0; p < passes; p++)
|
for (p = 0; p < passes; p++)
|
||||||
{
|
{
|
||||||
for (i = 0; i < h; i++)
|
for (i = 0; i < h; i++)
|
||||||
png_read_row(png_ptr, surface + (i * w * pack_offset), NULL);
|
png_read_row(epi.png_ptr, surface + (i * w * pack_offset), NULL);
|
||||||
}
|
}
|
||||||
png_read_end(png_ptr, info_ptr);
|
png_read_end(epi.png_ptr, epi.info_ptr);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -409,9 +705,9 @@ evas_image_load_file_data_png(void *loader_data,
|
||||||
unsigned short *pbuf;
|
unsigned short *pbuf;
|
||||||
|
|
||||||
for (skip_row = 0; skip_row < region_y; skip_row++)
|
for (skip_row = 0; skip_row < region_y; skip_row++)
|
||||||
png_read_row(png_ptr, tmp_line, NULL);
|
png_read_row(epi.png_ptr, tmp_line, NULL);
|
||||||
|
|
||||||
png_read_row(png_ptr, tmp_line, NULL);
|
png_read_row(epi.png_ptr, tmp_line, NULL);
|
||||||
src_ptr = tmp_line + (region_x * pack_offset);
|
src_ptr = tmp_line + (region_x * pack_offset);
|
||||||
|
|
||||||
//The first pixel, of the first line
|
//The first pixel, of the first line
|
||||||
|
@ -450,7 +746,7 @@ evas_image_load_file_data_png(void *loader_data,
|
||||||
//vertical interpolation.
|
//vertical interpolation.
|
||||||
for (j = 0; j < scale_ratio; j++)
|
for (j = 0; j < scale_ratio; j++)
|
||||||
{
|
{
|
||||||
png_read_row(png_ptr, tmp_line, NULL);
|
png_read_row(epi.png_ptr, tmp_line, NULL);
|
||||||
src_ptr = tmp_line + (region_x * pack_offset);
|
src_ptr = tmp_line + (region_x * pack_offset);
|
||||||
|
|
||||||
for (p = 0; p < line_size; ++p)
|
for (p = 0; p < line_size; ++p)
|
||||||
|
@ -486,7 +782,7 @@ evas_image_load_file_data_png(void *loader_data,
|
||||||
}
|
}
|
||||||
|
|
||||||
for (skip_row = region_y + h * scale_ratio; skip_row < image_h; skip_row++)
|
for (skip_row = region_y + h * scale_ratio; skip_row < image_h; skip_row++)
|
||||||
png_read_row(png_ptr, tmp_line, NULL);
|
png_read_row(epi.png_ptr, tmp_line, NULL);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -499,8 +795,9 @@ evas_image_load_file_data_png(void *loader_data,
|
||||||
for (p = 0; p < passes; p++)
|
for (p = 0; p < passes; p++)
|
||||||
{
|
{
|
||||||
for (i = 0; i < image_h; i++)
|
for (i = 0; i < image_h; i++)
|
||||||
png_read_row(png_ptr, pixels2 + (i * image_w * pack_offset), NULL);
|
png_read_row(epi.png_ptr, pixels2 + (i * image_w * pack_offset), NULL);
|
||||||
}
|
}
|
||||||
|
png_read_end(epi.png_ptr, epi.info_ptr);
|
||||||
|
|
||||||
src_ptr = pixels2 + (region_y * image_w * pack_offset) + region_x * pack_offset;
|
src_ptr = pixels2 + (region_y * image_w * pack_offset) + region_x * pack_offset;
|
||||||
|
|
||||||
|
@ -541,15 +838,15 @@ evas_image_load_file_data_png(void *loader_data,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
prop->premul = EINA_TRUE;
|
prop->info.premul = EINA_TRUE;
|
||||||
|
|
||||||
*error = EVAS_LOAD_ERROR_NONE;
|
*error = EVAS_LOAD_ERROR_NONE;
|
||||||
r = EINA_TRUE;
|
r = EINA_TRUE;
|
||||||
|
|
||||||
close_file:
|
close_file:
|
||||||
if (png_ptr) png_destroy_read_struct(&png_ptr,
|
if (epi.png_ptr) png_destroy_read_struct(&epi.png_ptr,
|
||||||
info_ptr ? &info_ptr : NULL,
|
epi.info_ptr ? &epi.info_ptr : NULL,
|
||||||
NULL);
|
NULL);
|
||||||
if (epi.map) eina_file_map_free(f, epi.map);
|
if (epi.map) eina_file_map_free(f, epi.map);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
@ -559,9 +856,9 @@ static Evas_Image_Load_Func evas_image_load_png_func =
|
||||||
EVAS_IMAGE_LOAD_VERSION,
|
EVAS_IMAGE_LOAD_VERSION,
|
||||||
evas_image_load_file_open_png,
|
evas_image_load_file_open_png,
|
||||||
evas_image_load_file_close_png,
|
evas_image_load_file_close_png,
|
||||||
(void*) evas_image_load_file_head_png,
|
evas_image_load_file_head_png,
|
||||||
NULL,
|
evas_image_load_file_head_with_data_png,
|
||||||
(void*) evas_image_load_file_data_png,
|
evas_image_load_file_data_png,
|
||||||
NULL,
|
NULL,
|
||||||
EINA_TRUE,
|
EINA_TRUE,
|
||||||
EINA_FALSE
|
EINA_FALSE
|
||||||
|
|
Loading…
Reference in New Issue