summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCedric BAIL <cedric@osg.samsung.com>2016-12-06 16:22:56 -0800
committerCedric BAIL <cedric@osg.samsung.com>2016-12-06 16:34:40 -0800
commitc8fef4a5567526eb2af9326c24f3a330645e59a0 (patch)
tree05bc7216eda9c6c6f402795bb490b024f0c4ce01
parent889944fefef45ee9d715656427d6f1c523ec9867 (diff)
downloadefl-c8fef4a5567526eb2af9326c24f3a330645e59a0.tar.gz
emile: add infrastructure for callback to request what to do with image.
First use of this infrastructure is to make JPEG decoding interruptible.
-rw-r--r--src/lib/emile/emile_image.c48
-rw-r--r--src/lib/emile/emile_image.h32
2 files changed, 79 insertions, 1 deletions
diff --git a/src/lib/emile/emile_image.c b/src/lib/emile/emile_image.c
index c7baff8ea1..59af9b475c 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 9d6f1af8e0..0eef713171 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.