volatile Eina_Bool hasa;
};
-typedef struct _Evas_Loader_Internal Evas_Loader_Internal;
-struct _Evas_Loader_Internal
+typedef struct _Loader_Info
{
Eina_File *f;
Evas_Image_Load_Opts *opts;
-};
+ //TIZEN_ONLY(20201111): Support APNG Image Format
+ Evas_Image_Animated *animated;
+ unsigned char *buffer;
+ unsigned char *buffer_pre;
+ //
+} Loader_Info;
+
+//TIZEN_ONLY(20201111): Support APNG Image Format
+typedef struct _Frame_Info
+{
+ int index;
+ int x, y, w, h;
+ double delay;
+ unsigned char dop;
+ unsigned char bop;
+} Frame_Info;
+//
static const Evas_Colorspace cspace_grey[2] = {
EVAS_COLORSPACE_GRY8,
static void *
evas_image_load_file_open_png(Eina_File *f, Eina_Stringshare *key EINA_UNUSED,
Evas_Image_Load_Opts *opts,
- Evas_Image_Animated *animated EINA_UNUSED,
+ Evas_Image_Animated *animated,
int *error)
{
- Evas_Loader_Internal *loader;
-
- loader = calloc(1, sizeof (Evas_Loader_Internal));
+ Loader_Info *loader = calloc(1, sizeof (Loader_Info));
if (!loader)
{
*error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
return NULL;
}
-
- loader->f = f;
+ loader->f = eina_file_dup(f);
loader->opts = opts;
+
+ //TIZEN_ONLY(20201111): Support APNG Image Format
+ loader->animated = animated;
+ //
+
return loader;
}
static void
evas_image_load_file_close_png(void *loader_data)
{
- free(loader_data);
+ //TIZEN_ONLY(20201111): Support APNG Image Format
+ Loader_Info *loader = loader_data;
+ if (loader->f) eina_file_close(loader->f);
+ if (loader->buffer) free(loader->buffer);
+ if (loader->buffer_pre) free(loader->buffer_pre);
+ //
+ free(loader);
}
+
+//TIZEN_ONLY(20201111): Support APNG Image Format
+static void
+_new_frame(Evas_Image_Animated *animated, unsigned char *data, int x, int y, int width, int height, int index, double delay, unsigned char dop, unsigned char bop)
+{
+ // Allocate Frame Data
+ Image_Entry_Frame *frame;
+
+ frame = calloc(1, sizeof(Image_Entry_Frame));
+ if (!frame) return;
+
+ frame->info = calloc(1, sizeof(Frame_Info));
+ if (!frame->info)
+ {
+ free(frame);
+ return;
+ }
+
+ frame->data = calloc(width * height, sizeof(DATA32));
+ if (!frame->data)
+ {
+ free(frame->info);
+ free(frame);
+ return;
+ }
+
+ Frame_Info *finfo = frame->info;
+
+ finfo->x = x;
+ finfo->y = y;
+ finfo->w = width;
+ finfo->h = height;
+ finfo->index = index;
+ finfo->delay = delay;
+ finfo->dop = dop;
+ finfo->bop = bop;
+
+ memcpy(frame->data, data, width * height * sizeof(DATA32));
+
+ animated->frames = eina_list_append(animated->frames, frame);
+}
+
+static Image_Entry_Frame *
+_find_frame(Evas_Image_Animated *animated, int index)
+{
+ // Find Frame
+ Eina_List *l;
+ Image_Entry_Frame *frame;
+
+ if (!animated->frames) return NULL;
+ EINA_LIST_FOREACH(animated->frames, l, frame)
+ {
+ if (((Frame_Info*)frame->info)->index == index)
+ return frame;
+ }
+ return NULL;
+}
+//
+
static Eina_Bool
-_evas_image_load_file_internal_head_png(Evas_Loader_Internal *loader,
+_evas_image_load_file_internal_head_png(Loader_Info *loader,
Evas_Image_Property *prop,
Evas_PNG_Info *epi,
int *error, Eina_Bool is_for_head)
prop->info.h = (int) epi->h32;
}
+ //TIZEN_ONLY(20201111): Support APNG Image Format
+ if (png_get_valid(epi->png_ptr, epi->info_ptr, PNG_INFO_acTL))
+ {
+ png_uint_32 frames = 1;
+ png_uint_32 plays = 0;
+ png_uint_32 w0 = epi->w32;
+ png_uint_32 h0 = epi->h32;
+ png_uint_32 x0 = 0;
+ png_uint_32 y0 = 0;
+ png_get_acTL(epi->png_ptr, epi->info_ptr, &frames, &plays);
+ int channel = png_get_channels(epi->png_ptr, epi->info_ptr);
+
+ png_set_bgr(epi->png_ptr);
+
+ // Define default delay
+ unsigned short delay_num = 1;
+ unsigned short delay_den = 10;
+ unsigned char dop = 0;
+ unsigned char bop = 0;
+
+ if (!loader->buffer)
+ {
+ loader->buffer = calloc(prop->info.w * prop->info.h, sizeof(DATA32));
+ if (!loader->buffer) goto close_file;
+ }
+
+ Evas_Image_Animated *animated = loader->animated;
+
+ // Read Apng Image Frames
+ int i, j;
+ for (i = 0; i < (int)frames; i++)
+ {
+ png_read_frame_head(epi->png_ptr, epi->info_ptr);
+ png_get_next_frame_fcTL(epi->png_ptr, epi->info_ptr, &w0, &h0, &x0, &y0, &delay_num, &delay_den, &dop, &bop);
+ unsigned char *cur_frame = calloc(w0 * h0 * channel, sizeof(unsigned char));
+ if (!cur_frame) goto close_file;
+ double delay = (double)delay_num / delay_den;
+ for (j = 0; j < (int)h0; j++)
+ png_read_row(epi->png_ptr, cur_frame + (j * w0 * channel), NULL);
+ _new_frame(animated, cur_frame, x0, y0, w0, h0, i + 1, delay, dop, bop);
+ free(cur_frame);
+ }
+ png_read_end(epi->png_ptr, epi->info_ptr);
+
+ animated->animated = 1;
+ animated->loop_count = plays;
+ animated->loop_hint = EVAS_IMAGE_ANIMATED_HINT_LOOP;
+ animated->frame_count = frames;
+ }
+ //
+
if (png_get_valid(epi->png_ptr, epi->info_ptr, PNG_INFO_tRNS))
{
/* expand transparency entry -> alpha channel if present */
Evas_Image_Property *prop,
int *error)
{
- Evas_Loader_Internal *loader = loader_data;
+ Loader_Info *loader = loader_data;
Evas_PNG_Info epi;
memset(&epi, 0, sizeof (Evas_PNG_Info));
void *pixels,
int *error)
{
- Evas_Loader_Internal *loader = loader_data;
+ Loader_Info *loader = loader_data;
Evas_Image_Load_Opts *opts;
Eina_File *f;
return r;
}
+//TIZEN_ONLY(20201111): Support APNG Image Format
+static unsigned char*
+_combine_frame(Loader_Info *loader, Evas_Image_Property *prop, Image_Entry_Frame *frame)
+{
+ Frame_Info *finfo = (Frame_Info*)frame->info;
+ uint32_t *buf = (uint32_t*)loader->buffer;
+ uint32_t *src = (uint32_t*)frame->data;
+
+ if (finfo->dop == PNG_DISPOSE_OP_PREVIOUS)
+ {
+ if (!loader->buffer_pre)
+ {
+ loader->buffer_pre = calloc(prop->info.w * prop->info.h, sizeof(DATA32));
+ if (!loader->buffer_pre) return NULL;
+ }
+ memcpy(loader->buffer_pre, buf, prop->info.w * prop->info.h * sizeof(DATA32));
+ }
+
+ int x, y, w, h;
+ x = finfo->x;
+ y = finfo->y;
+ w = finfo->w;
+ h = finfo->h;
+
+ int i, j;
+ // Copy ROI image
+ for (i = 0; i < h; i++)
+ for (j = 0; j < w; j++)
+ buf[((y + i) * prop->info.w) + (x + j)] = src[(i * w) + j];
+
+ return (unsigned char*)buf;
+}
+//
+
static Eina_Bool
evas_image_load_file_data_png(void *loader_data,
Evas_Image_Property *prop,
void *pixels,
int *error)
{
- Evas_Loader_Internal *loader = loader_data;
+ Loader_Info *loader = loader_data;
+ //TIZEN_ONLY(20201111): Support APNG Image Format
+ Evas_Image_Animated *animated = loader->animated;
+ //
Evas_Image_Load_Opts *opts;
Eina_File *f;
memset(&epi, 0, sizeof (Evas_PNG_Info));
+ //TIZEN_ONLY(20201111): Support APNG Image Format
+ if (animated->animated)
+ {
+ surface = pixels;
+ int index = animated->cur_frame;
+ if (index == 0) index = 1;
+ // Find Current Apng Image Frame
+ Image_Entry_Frame *frame = _find_frame(animated, index);
+ if (!frame) goto close_file;
+
+ // Combine Apng Image
+ unsigned char *data = _combine_frame(loader, prop, frame);
+ if (!data) goto close_file;
+ memcpy(surface, data, prop->info.w * prop->info.h * sizeof(DATA32));
+
+ // Apply Dispose Option
+ Frame_Info *finfo = (Frame_Info*)frame->info;
+ if (finfo->dop == PNG_DISPOSE_OP_BACKGROUND)
+ memset(loader->buffer, 0, prop->info.w * prop->info.h * sizeof(DATA32));
+ else if (finfo->dop == PNG_DISPOSE_OP_PREVIOUS)
+ memcpy(loader->buffer, loader->buffer_pre, prop->info.w * prop->info.h * sizeof(DATA32));
+
+ prop->info.premul = EINA_TRUE;
+ r = EINA_TRUE;
+
+ goto close_file;
+ }
+ //
+
if (!_evas_image_load_file_internal_head_png(loader, prop, &epi, error, EINA_FALSE))
return EINA_FALSE;
return r;
}
+//TIZEN_ONLY(20201111): Support APNG Image Format
+static double
+evas_image_load_frame_duration_png(void *loader_data,
+ int start_frame,
+ int frame_num)
+{
+ Loader_Info *loader = loader_data;
+ Evas_Image_Animated *animated = loader->animated;
+
+ if (!animated->animated) return -1.0;
+ if ((start_frame + frame_num) > animated->frame_count) return -1.0;
+ if (frame_num < 0) return -1.0;
+ if (start_frame < 1) return -1.0;
+
+ Image_Entry_Frame *frame = _find_frame(animated, start_frame);
+ if (frame == NULL) return -1.0;
+ Frame_Info *finfo = frame->info;
+
+ return finfo->delay;
+}
+//
+
static Evas_Image_Load_Func evas_image_load_png_func =
{
EVAS_IMAGE_LOAD_VERSION,
evas_image_load_file_head_png,
evas_image_load_file_head_with_data_png,
evas_image_load_file_data_png,
- NULL,
+ //TIZEN_ONLY(20201111): Support APNG Image Format
+ evas_image_load_frame_duration_png,
+ //
EINA_TRUE,
EINA_FALSE
};