diff --git a/include/gwin/image.h b/include/gwin/image.h index 688435c7..6f4cc289 100644 --- a/include/gwin/image.h +++ b/include/gwin/image.h @@ -32,7 +32,8 @@ // An image window typedef struct GImageObject { GWindowObject g; - gdispImage image; + gdispImage image; // The image itself + GTimer timer; // Timer used for animated images } GImageObject; #ifdef __cplusplus @@ -104,26 +105,6 @@ bool_t gwinImageOpenMemory(GHandle gh, const void* memory); */ gdispImageError gwinImageCache(GHandle gh); - -/** - * @brief Prepare for the next frame/page in the image file. - * @return A time in milliseconds to keep displaying the current frame before trying to draw - * the next frame. Watch out for the special values TIME_IMMEDIATE and TIME_INFINITE. - * - * @param[in] gh The widget handle (must be an image box handle) - * - * @pre gwinImageOpenXxx() must have returned successfully. - * - * @note It will return TIME_IMMEDIATE if the first frame/page hasn't been drawn or if the next frame - * should be drawn immediately. - * @note It will return TIME_INFINITE if another image frame doesn't exist or an error has occurred. - * @note Images that support multiple pages (eg TIFF files) will return TIME_IMMEDIATE between pages - * and then TIME_INFINITE when there are no more pages. - * @note An image that displays a looped animation will never return TIME_INFINITE unless it - * gets an error. - */ -delaytime_t gwinImageNext(GHandle gh); - #ifdef __cplusplus } #endif diff --git a/src/gwin/gimage.c b/src/gwin/gimage.c index 821e7d62..c30662f3 100644 --- a/src/gwin/gimage.c +++ b/src/gwin/gimage.c @@ -88,13 +88,34 @@ static const gwinVMT imageVMT = { 0, // The after-clear routine }; +// This is the callback for the automated redraw for animated images +static void _animatedRedraw(void* gh) { + // draw pending frame + _redraw((GHandle)gh); + + // read the delay for the next frame and set the timer + gtimerStart(&(widget((GHandle)gh)->timer), _animatedRedraw, (void*)gh, FALSE, gdispImageNext(&(widget((GHandle)gh)->image))); +} + +// check for an animated image +static bool_t _checkAnimated(GHandle gh) { + if (widget(gh)->image.flags & GDISP_IMAGE_FLG_ANIMATED) { + gtimerInit(&(widget(gh)->timer)); + gtimerStart(&(widget(gh)->timer), _animatedRedraw, (void*)gh, FALSE, gdispImageNext(&(widget(gh)->image))); + + return true; + } + + return false; +} + GHandle gwinImageCreate(GImageObject *gobj, GWindowInit *pInit) { if (!(gobj = (GImageObject *)_gwindowCreate(&gobj->g, pInit, &imageVMT, 0))) return 0; // Ensure the gdispImageIsOpen() gives valid results gobj->image.type = 0; - + gwinSetVisible((GHandle)gobj, pInit->show); return (GHandle)gobj; @@ -116,8 +137,11 @@ bool_t gwinImageOpenMemory(GHandle gh, const void* memory) { #if GDISP_NEED_CLIP gdispSetClip(gh->x, gh->y, gh->width, gh->height); #endif - _redraw(gh); } + + if(!_checkAnimated(gh)) + _redraw(gh); + return TRUE; } @@ -138,8 +162,11 @@ bool_t gwinImageOpenFile(GHandle gh, const char* filename) { #if GDISP_NEED_CLIP gdispSetClip(gh->x, gh->y, gh->width, gh->height); #endif - _redraw(gh); } + + if(!_checkAnimated(gh)) + _redraw(gh); + return TRUE; } #endif @@ -161,8 +188,11 @@ bool_t gwinImageOpenStream(GHandle gh, void *streamPtr) { #if GDISP_NEED_CLIP gdispSetClip(gh->x, gh->y, gh->width, gh->height); #endif - _redraw(gh); } + + if(!_checkAnimated(gh)) + _redraw(gh); + return TRUE; } #endif @@ -171,14 +201,5 @@ gdispImageError gwinImageCache(GHandle gh) { return gdispImageCache(&widget(gh)->image); } -delaytime_t gwinImageNext(GHandle gh) { - delaytime_t delay; - - delay = gdispImageNext(&widget(gh)->image); - _redraw(gh); - - return delay; -} - #endif // GFX_USE_GWIN && GWIN_NEED_IMAGE /** @} */