cedric pushed a commit to branch master.

http://git.enlightenment.org/core/efl.git/commit/?id=c8fef4a5567526eb2af9326c24f3a330645e59a0

commit c8fef4a5567526eb2af9326c24f3a330645e59a0
Author: Cedric BAIL <ced...@osg.samsung.com>
Date:   Tue Dec 6 16:22:56 2016 -0800

    emile: add infrastructure for callback to request what to do with image.
    
    First use of this infrastructure is to make JPEG decoding interruptible.
---
 src/lib/emile/emile_image.c | 48 +++++++++++++++++++++++++++++++++++++++++++++
 src/lib/emile/emile_image.h | 32 +++++++++++++++++++++++++++++-
 2 files changed, 79 insertions(+), 1 deletion(-)

diff --git a/src/lib/emile/emile_image.c b/src/lib/emile/emile_image.c
index c7baff8..59af9b4 100644
--- a/src/lib/emile/emile_image.c
+++ b/src/lib/emile/emile_image.c
@@ -125,6 +125,9 @@ struct _Emile_Image
    Eina_Bool             (*data)(Emile_Image *image, Emile_Image_Property 
*prop, unsigned int property_size, void *pixels, Emile_Image_Load_Error *error);
    void                  (*close)(Emile_Image *image);
 
+   Emile_Action_Cb       cancelled;
+   const void           *cancelled_data;
+
    Emile_Colorspace      cspace;
 
    Eina_Bool             bin_source : 1;
@@ -136,6 +139,27 @@ struct _Emile_Image
    Eina_Bool             load_opts : 1;
 };
 
+static inline Eina_Bool
+_emile_image_cancelled_is(Emile_Image *image)
+{
+   if (!image->cancelled) return EINA_FALSE;
+   return image->cancelled((void*) image->cancelled_data, image, 
EMILE_ACTION_CANCELLED);
+}
+
+#define EMILE_IMAGE_TASK_CHECK(Image, Count, Mask, Error, Error_Handler) \
+  do {                                                                  \
+     Count++;                                                           \
+     if ((Count & Mask) == Mask)                                        \
+       {                                                                \
+          Count = 0;                                                    \
+          if (_emile_image_cancelled_is(Image))                         \
+            {                                                           \
+               *Error = EMILE_IMAGE_LOAD_ERROR_CANCELLED;               \
+               goto Error_Handler;                                      \
+            }                                                           \
+       }                                                                \
+  } while (0);
+
 static const unsigned char *
 _emile_image_file_source_map(Emile_Image *image, unsigned int *length)
 {
@@ -1629,6 +1653,7 @@ _emile_jpeg_data(Emile_Image *image,
    Eina_Bool ptrag_free = EINA_FALSE;
    Eina_Bool r = EINA_FALSE;
    unsigned int length;
+   unsigned short count = 0;
 
    if (sizeof(Emile_Image_Property) != property_size)
      return EINA_FALSE;
@@ -1852,6 +1877,9 @@ _emile_jpeg_data(Emile_Image *image,
           line[i] = data + (i * w * 4);
         for (l = 0; l < h; l += cinfo.rec_outbuf_height)
           {
+             // Check for continuing every 16 scanlines fetch
+             EMILE_IMAGE_TASK_CHECK(image, count, 0xF, error, on_error);
+
              jpeg_read_scanlines(&cinfo, line, cinfo.rec_outbuf_height);
              scans = cinfo.rec_outbuf_height;
              if ((h - l) < scans)
@@ -1998,6 +2026,9 @@ _emile_jpeg_data(Emile_Image *image,
           line[i] = data + (i * w * 3);
         for (l = 0; l < h; l += cinfo.rec_outbuf_height)
           {
+             // Check for continuing every 16 scanlines fetch
+             EMILE_IMAGE_TASK_CHECK(image, count, 0xF, error, on_error);
+
              jpeg_read_scanlines(&cinfo, line, cinfo.rec_outbuf_height);
              scans = cinfo.rec_outbuf_height;
              if ((h - l) < scans)
@@ -2060,6 +2091,9 @@ _emile_jpeg_data(Emile_Image *image,
           line[i] = data + (i * w);
         for (l = 0; l < h; l += cinfo.rec_outbuf_height)
           {
+             // Check for continuing every 16 scanlines fetch
+             EMILE_IMAGE_TASK_CHECK(image, count, 0xF, error, on_error);
+
              jpeg_read_scanlines(&cinfo, line, cinfo.rec_outbuf_height);
              scans = cinfo.rec_outbuf_height;
              if ((h - l) < scans)
@@ -2411,6 +2445,17 @@ emile_image_jpeg_file_open(Eina_File *source,
 }
 
 EAPI void
+emile_image_register(Emile_Image *image, Emile_Action_Cb callback, 
Emile_Action action, const void *data)
+{
+   if (!image) return ;
+   // We only handle one type of callback for now
+   if (action != EMILE_ACTION_CANCELLED) return ;
+
+   image->cancelled_data = data;
+   image->cancelled = callback;
+}
+
+EAPI void
 emile_image_close(Emile_Image *image)
 {
    if (!image)
@@ -2476,6 +2521,9 @@ emile_load_error_str(Emile_Image *source EINA_UNUSED,
 
       case EMILE_IMAGE_LOAD_ERROR_UNKNOWN_FORMAT:
         return "Unexpected file format.";
+
+      case EMILE_IMAGE_LOAD_ERROR_CANCELLED:
+        return "Loading was stopped by an external request.";
      }
    return NULL;
 }
diff --git a/src/lib/emile/emile_image.h b/src/lib/emile/emile_image.h
index 9d6f1af..0eef713 100644
--- a/src/lib/emile/emile_image.h
+++ b/src/lib/emile/emile_image.h
@@ -102,7 +102,8 @@ typedef enum _Emile_Image_Load_Error
   EMILE_IMAGE_LOAD_ERROR_PERMISSION_DENIED = 3,         /**< Permission denied 
to an existing file (or path) */
   EMILE_IMAGE_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED = 4,  /**< Allocation of 
resources failure prevented load */
   EMILE_IMAGE_LOAD_ERROR_CORRUPT_FILE = 5,  /**< File corrupt (but was 
detected as a known format) */
-  EMILE_IMAGE_LOAD_ERROR_UNKNOWN_FORMAT = 6  /**< File is not a known format */
+  EMILE_IMAGE_LOAD_ERROR_UNKNOWN_FORMAT = 6,  /**< File is not a known format 
*/
+  EMILE_IMAGE_LOAD_ERROR_CANCELLED = 7 /**< File loading has been cancelled */
 } Emile_Image_Load_Error; /**< Emile image load error codes one can get - see 
emile_load_error_str() too. */
 
 /**
@@ -141,6 +142,25 @@ typedef struct _Emile_Image_Animated Emile_Image_Animated;
  */
 typedef struct _Emile_Image_Property Emile_Image_Property;
 
+/**
+ * @enum _Emile_Action
+ * @typedef Emile_Action
+ * What action emile is refering to.
+ * @since 1.19
+ */
+typedef enum _Emile_Action
+{
+  EMILE_ACTION_NONE = 0,
+  EMILE_ACTION_CANCELLED = 1
+} Emile_Action;
+
+/**
+ * @typedef Emile_Action_Cb
+ * A callback triggered by emile to learn what to do about a specific action.
+ * @since 1.19
+ */
+typedef Eina_Bool (*Emile_Action_Cb)(void *data, Emile_Image *image, 
Emile_Action action);
+
 struct _Emile_Image_Property
 {
   struct
@@ -286,6 +306,16 @@ EAPI Eina_Bool emile_image_head(Emile_Image * image, 
Emile_Image_Property * prop
 EAPI Eina_Bool emile_image_data(Emile_Image * image, Emile_Image_Property * 
prop, unsigned int property_size, void *pixels, Emile_Image_Load_Error * error);
 
 /**
+ * Register a callback for emile to ask what to do during the processing of an 
image
+ *
+ * @param image The Emile_Image handler to register on.
+ * @param callback The callback to use
+ * @param action The action this callback is triggered on.
+ * @since 1.19
+ */
+EAPI void emile_image_register(Emile_Image *image, Emile_Action_Cb callback, 
Emile_Action action, const void *data);
+
+/**
  * Close an opened image handler.
  *
  * @param source The handler to close.

-- 


Reply via email to