efl: use Eina_File for PNG to.
authorCedric BAIL <cedric.bail@free.fr>
Thu, 3 Jan 2013 07:57:18 +0000 (07:57 +0000)
committerCedric BAIL <cedric.bail@free.fr>
Thu, 3 Jan 2013 07:57:18 +0000 (07:57 +0000)
SVN revision: 82047

ChangeLog
NEWS
src/modules/evas/loaders/png/evas_image_load_png.c

index 49ab13b..d52ac42 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+2013-01-03  Cedric Bail
+
+       * Use Eina_File for evas png loader.
+
 2013-01-03  Carsten Haitzler (The Rasterman)
 
         * Fixed ecore_con case where freeing server double-frees clients
diff --git a/NEWS b/NEWS
index 595292b..0ec7792 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -70,7 +70,7 @@ Improvements:
     * Display more information with eet -l -v.
     * eina_magic_fail() now throws error messages on NULL pointers instead of critical
     * all efl object-freeing functions now take NULL without crashing or erroring
-    * use Eina_File in webp, gif, tiff and eet loader
+    * use Eina_File in webp, gif, tiff, png and eet loader
 
 Fixes:
     * Fix PPC (big endian) image codec bug.
index e262301..8704b0f 100644 (file)
 # include <Evil.h>
 #endif
 
-#ifdef _WIN32_WCE
-# define E_FOPEN(file, mode) evil_fopen_native((file), (mode))
-# define E_FREAD(buffer, size, count, stream) evil_fread_native(buffer, size, count, stream)
-# define E_FCLOSE(stream) evil_fclose_native(stream)
-#else
-# define E_FOPEN(file, mode) fopen((file), (mode))
-# define E_FREAD(buffer, size, count, stream) fread(buffer, size, count, stream)
-# define E_FCLOSE(stream) fclose(stream)
-#endif
-
 #include "evas_common.h"
 #include "evas_private.h"
 
-
 #define PNG_BYTES_TO_CHECK 4
 
-
 static Eina_Bool evas_image_load_file_head_png(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_png(Image_Entry *ie, const char *file, const char *key, int *error) EINA_ARG_NONNULL(1, 2, 4);
 
@@ -39,34 +27,63 @@ static Evas_Image_Load_Func evas_image_load_png_func =
   EINA_FALSE
 };
 
+typedef struct _Evas_PNG_Info Evas_PNG_Info;
+struct _Evas_PNG_Info
+{
+   unsigned char *map;
+   size_t length;
+   size_t position;
+};
+
+static void
+_evas_image_png_read(png_structp png_ptr, png_bytep out, png_size_t count)
+{
+   Evas_PNG_Info *epi = png_ptr->io_ptr;
+
+   if (!epi) return ;
+   if (epi->position == epi->length) return ;
+
+   if (epi->position + count > epi->length) count = epi->length - epi->position;
+   memcpy(out, epi->map + epi->position, count);
+   epi->position += count;
+}
+
 static Eina_Bool
 evas_image_load_file_head_png(Image_Entry *ie, const char *file, const char *key EINA_UNUSED, int *error)
 {
-   png_uint_32 w32, h32;
-   FILE *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;
-   unsigned char buf[PNG_BYTES_TO_CHECK];
    char hasa;
+   Eina_Bool r = EINA_FALSE;
 
    hasa = 0;
-   f = E_FOPEN(file, "rb");
+   f = eina_file_open(file, EINA_FALSE);
    if (!f)
      {
-        ERR("File: '%s' does not exist\n", file);
        *error = EVAS_LOAD_ERROR_DOES_NOT_EXIST;
        return EINA_FALSE;
      }
 
-   /* if we havent read the header before, set the header data */
-   if (E_FREAD(buf, PNG_BYTES_TO_CHECK, 1, f) != 1)
+   epi.map = eina_file_map_all(f, EINA_FILE_SEQUENTIAL);
+   if (!epi.map)
+     {
+        *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)
      {
        *error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT;
        goto close_file;
      }
 
-   if (png_sig_cmp(buf, 0, PNG_BYTES_TO_CHECK))
+   if (png_sig_cmp(epi.map, 0, PNG_BYTES_TO_CHECK))
      {
        *error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT;
        goto close_file;
@@ -82,18 +99,18 @@ evas_image_load_file_head_png(Image_Entry *ie, const char *file, const char *key
    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_init_io(png_ptr, f);
-   png_set_sig_bytes(png_ptr, PNG_BYTES_TO_CHECK);
+
    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,
@@ -101,7 +118,6 @@ evas_image_load_file_head_png(Image_Entry *ie, const char *file, const char *key
    if ((w32 < 1) || (h32 < 1) || (w32 > IMG_MAX_SIZE) || (h32 > IMG_MAX_SIZE) ||
        IMG_TOO_BIG(w32, h32))
      {
-       png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
        if (IMG_TOO_BIG(w32, h32))
          *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
        else
@@ -127,52 +143,66 @@ evas_image_load_file_head_png(Image_Entry *ie, const char *file, const char *key
    if (color_type == PNG_COLOR_TYPE_RGB_ALPHA) hasa = 1;
    if (color_type == PNG_COLOR_TYPE_GRAY_ALPHA) hasa = 1;
    if (hasa) ie->flags.alpha = 1;
-   png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
-   E_FCLOSE(f);
 
    *error = EVAS_LOAD_ERROR_NONE;
-   return EINA_TRUE;
+   r = EINA_TRUE;
 
  close_file:
-   E_FCLOSE(f);
-   return EINA_FALSE;
+   if (png_ptr) png_destroy_read_struct(&png_ptr,
+                                        info_ptr ? &info_ptr : NULL,
+                                        NULL);
+   if (epi.map) eina_file_map_free(f, epi. map);
+   eina_file_close(f);
+
+   return r;
 }
 
 static Eina_Bool
 evas_image_load_file_data_png(Image_Entry *ie, const char *file, const char *key EINA_UNUSED, int *error)
 {
+   Eina_File *f;
    unsigned char *surface;
-   png_uint_32 w32, h32;
-   int w, h;
-   FILE *f;
+   unsigned char **lines;
+   unsigned char *tmp_line;
+   DATA32 *src_ptr, *dst_ptr;
    png_structp png_ptr = NULL;
    png_infop info_ptr = NULL;
+   Evas_PNG_Info epi;
+   png_uint_32 w32, h32;
+   int w, h;
    int bit_depth, color_type, interlace_type;
-   unsigned char buf[PNG_BYTES_TO_CHECK];
-   unsigned char **lines;
    char hasa;
    int i, j;
    int scale_ratio = 1, image_w = 0;
-   unsigned char *tmp_line;
-   DATA32 *src_ptr, *dst_ptr;
+   Eina_Bool r = EINA_FALSE;
 
    hasa = 0;
-   f = E_FOPEN(file, "rb");
+   f = eina_file_open(file, EINA_FALSE);
    if (!f)
      {
        *error = EVAS_LOAD_ERROR_DOES_NOT_EXIST;
        return EINA_FALSE;
      }
 
-   /* if we havent read the header before, set the header data */
-   if (E_FREAD(buf, PNG_BYTES_TO_CHECK, 1, f) != 1)
+   epi.map = eina_file_map_all(f, EINA_FILE_SEQUENTIAL);
+   if (!epi.map)
      {
-       *error = EVAS_LOAD_ERROR_CORRUPT_FILE;
+        *error = EVAS_LOAD_ERROR_CORRUPT_FILE;
         goto close_file;
      }
-   if (png_sig_cmp(buf, 0, PNG_BYTES_TO_CHECK))
+   epi.length = eina_file_size_get(f);
+   epi.position = 0;
+
+   if (epi.length < PNG_BYTES_TO_CHECK)
      {
-       *error = EVAS_LOAD_ERROR_CORRUPT_FILE;
+        *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);
@@ -189,14 +219,16 @@ evas_image_load_file_data_png(Image_Entry *ie, const char *file, const char *key
        *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_init_io(png_ptr, f);
-   png_set_sig_bytes(png_ptr, PNG_BYTES_TO_CHECK);
+
    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,
@@ -212,13 +244,11 @@ evas_image_load_file_data_png(Image_Entry *ie, const char *file, const char *key
    surface = (unsigned char *) evas_cache_image_pixels(ie);
    if (!surface)
      {
-       png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
        *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
        goto close_file;
      }
    if ((w32 != ie->w) || (h32 != ie->h))
      {
-       png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
        *error = EVAS_LOAD_ERROR_GENERIC;
        goto close_file;
      }
@@ -286,16 +316,18 @@ evas_image_load_file_data_png(Image_Entry *ie, const char *file, const char *key
           }
      }
 
-   png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
-   E_FCLOSE(f);
    evas_common_image_premul(ie);
 
    *error = EVAS_LOAD_ERROR_NONE;
-   return EINA_TRUE;
+   r = EINA_TRUE;
 
  close_file:
-   E_FCLOSE(f);
-   return EINA_FALSE;
+   if (png_ptr) png_destroy_read_struct(&png_ptr,
+                                        info_ptr ? &info_ptr : NULL,
+                                        NULL);
+   if (epi.map) eina_file_map_free(f, epi.map);
+   eina_file_close(f);
+   return r;
 }
 
 static int