+// stop behavior
+DALI_ENUM_TO_STRING_TABLE_BEGIN( STOP_BEHAVIOR )
+DALI_ENUM_TO_STRING_WITH_SCOPE( Dali::Toolkit::DevelImageVisual::StopBehavior, CURRENT_FRAME )
+DALI_ENUM_TO_STRING_WITH_SCOPE( Dali::Toolkit::DevelImageVisual::StopBehavior, FIRST_FRAME )
+DALI_ENUM_TO_STRING_WITH_SCOPE( Dali::Toolkit::DevelImageVisual::StopBehavior, LAST_FRAME )
+DALI_ENUM_TO_STRING_TABLE_END( STOP_BEHAVIOR )
+
+// wrap modes
+DALI_ENUM_TO_STRING_TABLE_BEGIN( WRAP_MODE )
+DALI_ENUM_TO_STRING_WITH_SCOPE( Dali::WrapMode, DEFAULT )
+DALI_ENUM_TO_STRING_WITH_SCOPE( Dali::WrapMode, CLAMP_TO_EDGE )
+DALI_ENUM_TO_STRING_WITH_SCOPE( Dali::WrapMode, REPEAT )
+DALI_ENUM_TO_STRING_WITH_SCOPE( Dali::WrapMode, MIRRORED_REPEAT )
+DALI_ENUM_TO_STRING_TABLE_END( WRAP_MODE )
+
+const Vector4 FULL_TEXTURE_RECT(0.f, 0.f, 1.f, 1.f);
+constexpr auto LOOP_FOREVER = -1;
+
+#if defined(DEBUG_ENABLED)
+Debug::Filter* gAnimImgLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_ANIMATED_IMAGE");
+#endif
+}
+
+
+/**
+ * Multi-image Flow of execution
+ *
+ * | New
+ * | DoSetProperties()
+ * | LoadFirstBatch()
+ * | new cache
+ * | cache->LoadBatch()
+ * |
+ * | DoSetOnStage()
+ * | PrepareTextureSet()
+ * | cache->FirstFrame()
+ * | CreateRenderer() (Doesn't become ready until first frame loads)
+ * | StartFirstFrame()
+ * |
+ * | FrameReady(textureSet)
+ * | start first frame:
+ * | actor.AddRenderer
+ * | start timer
+ * | mRenderer.SetTextures(textureSet)
+ * |
+ * | Timer ticks
+ * | DisplayNextFrame()
+ * | if front frame is ready,
+ * | mRenderer.SetTextures( front frame's texture )
+ * | else
+ * | mWaitingForTexture=true
+ * | cache->LoadBatch()
+ * |
+ * | FrameReady(textureSet)
+ * | mRenderer.SetTextures(textureSet)
+ * V
+ * Time
+ */
+
+AnimatedImageVisualPtr AnimatedImageVisual::New( VisualFactoryCache& factoryCache, ImageVisualShaderFactory& shaderFactory, const VisualUrl& imageUrl, const Property::Map& properties )
+{
+ AnimatedImageVisualPtr visual( new AnimatedImageVisual( factoryCache, shaderFactory ) );
+ visual->InitializeGif( imageUrl );
+ visual->SetProperties( properties );
+
+ if( visual->mFrameCount > 0 )
+ {
+ visual->LoadFirstBatch();
+ }
+
+ return visual;
+}
+
+AnimatedImageVisualPtr AnimatedImageVisual::New( VisualFactoryCache& factoryCache, ImageVisualShaderFactory& shaderFactory, const Property::Array& imageUrls, const Property::Map& properties )
+{
+ AnimatedImageVisualPtr visual( new AnimatedImageVisual( factoryCache, shaderFactory ) );
+ visual->mImageUrls = new ImageCache::UrlList();
+ visual->mImageUrls->reserve( imageUrls.Count() );
+
+ for( unsigned int i=0; i < imageUrls.Count(); ++i)
+ {
+ ImageCache::UrlStore urlStore;
+ urlStore.mTextureId = TextureManager::INVALID_TEXTURE_ID;
+ urlStore.mUrl = imageUrls[i].Get<std::string>();
+ visual->mImageUrls->push_back( urlStore );
+ }
+ visual->mFrameCount = imageUrls.Count();