--- /dev/null
+SET(name "dali2-vector-animation-renderer-plugin")
+
+SET(CMAKE_C_STANDARD 99)
+SET(CMAKE_CXX_STANDARD 17)
+PROJECT(${name})
+SET(PKG_NAME ${name})
+
+SET(GCC_COMPILER_VERSION_REQUIRED "6")
+IF(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
+ IF(CMAKE_CXX_COMPILER_VERSION VERSION_LESS GCC_COMPILER_VERSION_REQUIRED)
+ MESSAGE(FATAL_ERROR "The GCC required compiler version is " ${GCC_COMPILER_VERSION_REQUIRED})
+ ENDIF()
+ENDIF()
+
+FIND_PACKAGE( PkgConfig REQUIRED )
+PKG_CHECK_MODULES(DALICORE REQUIRED dali2-core)
+PKG_CHECK_MODULES(DALIADAPTOR REQUIRED dali2-adaptor)
+PKG_CHECK_MODULES(DALITOOLKIT REQUIRED dali2-toolkit)
+PKG_CHECK_MODULES(RLOTTIE REQUIRED rlottie)
+
+# Deployment folder should come from spec file or command line:
+SET( PREFIX ${CMAKE_INSTALL_PREFIX})
+SET( EXEC_PREFIX ${CMAKE_INSTALL_PREFIX})
+
+# Set up the include dir
+SET( INCLUDE_DIR $ENV{includedir} )
+IF( NOT INCLUDE_DIR )
+ SET( INCLUDE_DIR ${CMAKE_INSTALL_INCLUDEDIR} )
+ENDIF()
+IF( NOT INCLUDE_DIR )
+ SET( INCLUDE_DIR ${PREFIX}/include )
+ENDIF()
+
+# Set up the lib dir
+SET( LIB_DIR $ENV{libdir} )
+IF( NOT LIB_DIR )
+ SET( LIB_DIR ${CMAKE_INSTALL_LIBDIR} )
+ENDIF()
+IF( NOT LIB_DIR )
+ SET( LIB_DIR ${PREFIX}/lib )
+ENDIF()
+
+# Set up the bin dir
+SET( BIN_DIR $ENV{bindir} )
+IF( NOT BIN_DIR )
+ SET( BIN_DIR ${CMAKE_INSTALL_BINDIR} )
+ENDIF()
+IF( NOT BIN_DIR )
+ SET( BIN_DIR ${PREFIX}/bin )
+ENDIF()
+
+INCLUDE(CheckCXXCompilerFlag)
+
+ADD_COMPILE_OPTIONS( -Werror -Wall -Wextra -Wno-unused-parameter -Wfloat-equal )
+CHECK_CXX_COMPILER_FLAG(-Wno-class-memaccess HAVE_NO_CLASS_MEMACCESS)
+IF (HAVE_NO_CLASS_MEMACCESS)
+ ADD_COMPILE_OPTIONS( -Wno-class-memaccess )
+ENDIF()
+
+CHECK_CXX_COMPILER_FLAG(-Wno-cast-function-type HAVE_NO_CAST_FUNCTION_TYPE)
+IF (HAVE_NO_CAST_FUNCTION_TYPE)
+ ADD_COMPILE_OPTIONS( -Wno-cast-function-type )
+ENDIF()
+
+IF( NOT ${ENABLE_EXPORTALL} )
+ ADD_COMPILE_OPTIONS( "-fvisibility=hidden" )
+ENDIF()
+
+INCLUDE_DIRECTORIES(
+ ${ROOT_SRC_DIR}
+ ${DALICORE_INCLUDE_DIRS}
+ ${DALIADAPTOR_INCLUDE_DIRS}
+ ${INCLUDE_DIR}
+)
+
+SET(SOURCE_DIR "${ROOT_SRC_DIR}/dali-extension/vector-animation-renderer")
+
+SET(SOURCES "")
+
+INCLUDE( ${ROOT_SRC_DIR}/dali-extension/vector-animation-renderer/file-ubuntu.list )
+
+SET(LIBTYPE SHARED)
+IF(DEFINED STATIC)
+ SET(LIBTYPE STATIC)
+ENDIF()
+
+ADD_LIBRARY( ${name} ${LIBTYPE} ${SOURCES} )
+
+SET(OPTIONAL_LIBS ${OPTIONAL_LIBS} -lpthread)
+
+TARGET_LINK_LIBRARIES( ${name}
+ ${OPTIONAL_LIBS}
+ ${DALICORE_LDFLAGS}
+ ${DALIADAPTOR_LDFLAGS}
+ ${RLOTTIE_LDFLAGS}
+)
+
+IF( INSTALL_CMAKE_MODULES )
+ IF( ENABLE_DEBUG )
+ SET( BIN_DIR "${BIN_DIR}/debug" )
+ SET( LIB_DIR "${LIB_DIR}/debug" )
+ ENDIF()
+
+ # Install the library files.
+ INSTALL( TARGETS ${name}
+ EXPORT ${name}-targets
+ LIBRARY DESTINATION ${LIB_DIR}
+ ARCHIVE DESTINATION ${LIB_DIR}
+ RUNTIME DESTINATION ${BIN_DIR}
+ )
+
+ # Install the cmake modules.
+ INSTALL(
+ EXPORT ${name}-targets
+ NAMESPACE ${name}::
+ FILE ${name}-targets.cmake
+ DESTINATION share/${name}
+ )
+
+ FILE( WRITE ${CMAKE_CURRENT_BINARY_DIR}/${name}-config.cmake "
+ include(CMakeFindDependencyMacro)
+ include(\${CMAKE_CURRENT_LIST_DIR}/${name}-targets.cmake)
+ ")
+ INSTALL( FILES ${CMAKE_CURRENT_BINARY_DIR}/${name}-config.cmake DESTINATION share/${name} )
+
+ELSE()
+ # Install the library so file and symlinks.
+ INSTALL( TARGETS ${name} DESTINATION ${LIB_DIR} )
+ENDIF()
+
+# Configuration Messages
+MESSAGE( STATUS "Configuration:\n" )
+MESSAGE( STATUS "Prefix: " ${PREFIX} )
+MESSAGE( STATUS "Lib Dir: " ${LIB_DIR} )
+MESSAGE( STATUS "Bin Dir: " ${BIN_DIR} )
+MESSAGE( STATUS "Include Dir: " ${INCLUDE_DIR} )
+MESSAGE( STATUS "Debug build: " ${ENABLE_DEBUG} )
+MESSAGE( STATUS "Export all symbols: " ${ENABLE_EXPORTALL} )
+MESSAGE( STATUS "Backtrace: " ${ENABLE_BACKTRACE} )
+MESSAGE( STATUS "Scoped Lock backtrace: " ${ENABLE_LOCK_BACKTRACE} )
+MESSAGE( STATUS "Coverage: " ${ENABLE_COVERAGE} )
+MESSAGE( STATUS "Trace: " ${ENABLE_TRACE} )
+MESSAGE( STATUS "Use pkg configure: " ${ENABLE_PKG_CONFIGURE} )
+MESSAGE( STATUS "Enable link test: " ${ENABLE_LINK_TEST} )
+MESSAGE( STATUS "CXXFLAGS: " ${CMAKE_CXX_FLAGS} )
+MESSAGE( STATUS "LDFLAGS: " ${CMAKE_SHARED_LINKER_FLAGS_INIT}${CMAKE_SHARED_LINKER_FLAGS} )
--- /dev/null
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali-extension/vector-animation-renderer/tizen-vector-animation-renderer-x.h>
+
+// EXTERNAL INCLUDES
+#include <dali/devel-api/common/hash.h>
+#include <dali/devel-api/rendering/texture-devel.h>
+#include <dali/integration-api/debug.h>
+#include <dali/public-api/object/property-array.h>
+
+#include <cstring> // for strlen()
+
+// INTERNAL INCLUDES
+#include <dali-extension/vector-animation-renderer/tizen-vector-animation-manager.h>
+
+// The plugin factories
+extern "C" DALI_EXPORT_API Dali::VectorAnimationRendererPlugin* CreateVectorAnimationRendererPlugin(void)
+{
+ return new Dali::Plugin::TizenVectorAnimationRenderer;
+}
+
+namespace Dali
+{
+namespace Plugin
+{
+namespace
+{
+const char* const PIXEL_AREA_UNIFORM_NAME("pixelArea");
+const Vector4 FULL_TEXTURE_RECT(0.f, 0.f, 1.f, 1.f);
+
+#if defined(DEBUG_ENABLED)
+Debug::Filter* gVectorAnimationLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_VECTOR_ANIMATION");
+#endif
+} // unnamed namespace
+
+TizenVectorAnimationRenderer::TizenVectorAnimationRenderer()
+: mUrl(),
+ mMutex(),
+ mRenderer(),
+ mTexture(),
+ mLottieSurface(),
+ mVectorRenderer(),
+ mUploadCompletedSignal(),
+ mTotalFrameNumber(0),
+ mWidth(0),
+ mHeight(0),
+ mDefaultWidth(0),
+ mDefaultHeight(0),
+ mFrameRate(60.0f),
+ mLoadFailed(false),
+ mResourceReady(false),
+ mShaderChanged(false),
+ mResourceReadyTriggered(false),
+ mRenderCallback(std::unique_ptr<EventThreadCallback>(new EventThreadCallback(MakeCallback(this, &TizenVectorAnimationRenderer::OnLottieRendered))))
+{
+ TizenVectorAnimationManager::Get().AddEventHandler(*this);
+}
+
+TizenVectorAnimationRenderer::~TizenVectorAnimationRenderer()
+{
+ Dali::Mutex::ScopedLock lock(mMutex);
+
+ ResetBuffers();
+ DALI_LOG_INFO(gVectorAnimationLogFilter, Debug::Verbose, "this = %p\n", this);
+}
+
+void TizenVectorAnimationRenderer::Finalize()
+{
+ Dali::Mutex::ScopedLock lock(mMutex);
+
+ TizenVectorAnimationManager::Get().RemoveEventHandler(*this);
+
+ mRenderer.Reset();
+ mTexture.Reset();
+ mVectorRenderer.reset();
+ mPropertyCallbacks.clear();
+
+ DALI_LOG_INFO(gVectorAnimationLogFilter, Debug::Verbose, "[%p]\n", this);
+}
+
+bool TizenVectorAnimationRenderer::Load(const std::string& url)
+{
+ Dali::Mutex::ScopedLock lock(mMutex);
+
+ mUrl = url;
+
+ mVectorRenderer = rlottie::Animation::loadFromFile(mUrl);
+ if(!mVectorRenderer)
+ {
+ DALI_LOG_ERROR("Failed to load a Lottie file [%s] [%p]\n", mUrl.c_str(), this);
+ mLoadFailed = true;
+ return false;
+ }
+
+ mTotalFrameNumber = static_cast<uint32_t>(mVectorRenderer->totalFrame());
+ mFrameRate = static_cast<float>(mVectorRenderer->frameRate());
+
+ size_t w, h;
+ mVectorRenderer->size(w, h);
+ mDefaultWidth = static_cast<uint32_t>(w);
+ mDefaultHeight = static_cast<uint32_t>(h);
+
+ DALI_LOG_INFO(gVectorAnimationLogFilter, Debug::Verbose, "file [%s] [%p]\n", url.c_str(), this);
+
+ return true;
+}
+
+bool TizenVectorAnimationRenderer::Load(const Dali::Vector<uint8_t>& data)
+{
+ Dali::Mutex::ScopedLock lock(mMutex);
+
+ std::string jsonData(data.Begin(), data.End()); ///< Convert from raw buffer to string.
+ auto hashValue = Dali::CalculateHash(data); ///< Will be used for rlottie internal cache system.
+
+ mVectorRenderer = rlottie::Animation::loadFromData(std::move(jsonData), std::to_string(hashValue));
+ if(!mVectorRenderer)
+ {
+ DALI_LOG_ERROR("Failed to load a Lottie data [data size : %zu byte] [%p]\n", data.Size(), this);
+ mLoadFailed = true;
+ return false;
+ }
+
+ mTotalFrameNumber = static_cast<uint32_t>(mVectorRenderer->totalFrame());
+ mFrameRate = static_cast<float>(mVectorRenderer->frameRate());
+
+ size_t w, h;
+ mVectorRenderer->size(w, h);
+ mDefaultWidth = static_cast<uint32_t>(w);
+ mDefaultHeight = static_cast<uint32_t>(h);
+
+ DALI_LOG_INFO(gVectorAnimationLogFilter, Debug::Verbose, "data [data size : %zu byte] [%p]\n", data.Size(), this);
+
+ return true;
+}
+
+void TizenVectorAnimationRenderer::OnLottieRendered()
+{
+ Dali::Mutex::ScopedLock lock(mMutex);
+
+ if(mPixelBuffer && mTexture)
+ {
+ PixelData pixelData = mPixelBuffer.CreatePixelData();
+ mTexture.Upload(pixelData);
+ }
+}
+
+void TizenVectorAnimationRenderer::SetRenderer(Renderer renderer)
+{
+ mRenderer = renderer;
+ mShaderChanged = false;
+
+ if(mPixelBuffer)
+ {
+ Dali::Mutex::ScopedLock lock(mMutex);
+
+ if(mResourceReady && mTexture)
+ {
+ TextureSet textureSet = renderer.GetTextures();
+
+ textureSet.SetTexture(0, mTexture);
+
+ mUploadCompletedSignal.Emit();
+ }
+
+ SetShader();
+ }
+}
+
+void TizenVectorAnimationRenderer::SetSize(uint32_t width, uint32_t height)
+{
+ Dali::Mutex::ScopedLock lock(mMutex);
+
+ if(mWidth == width && mHeight == height)
+ {
+ DALI_LOG_INFO(gVectorAnimationLogFilter, Debug::Verbose, "Same size (%d, %d) [%p]\n", mWidth, mHeight, this);
+ return;
+ }
+
+ if(mLoadFailed)
+ {
+ DALI_LOG_INFO(gVectorAnimationLogFilter, Debug::Verbose, "Load is failed. Do not make texture [%p]\n", this);
+ return;
+ }
+
+ mTexture = Texture::New(Dali::TextureType::TEXTURE_2D, Dali::Pixel::BGRA8888, width, height);
+
+ mPixelBuffer = Dali::Devel::PixelBuffer::New(width, height, Dali::Pixel::BGRA8888);
+ mLottieSurface = rlottie::Surface(reinterpret_cast<uint32_t*>(mPixelBuffer.GetBuffer()), width, height, static_cast<size_t>(mPixelBuffer.GetStride() * 4));
+
+ if(mRenderer)
+ {
+ SetShader();
+ }
+
+ mWidth = width;
+ mHeight = height;
+
+ mResourceReady = false;
+
+ DALI_LOG_INFO(gVectorAnimationLogFilter, Debug::Verbose, "width = %d, height = %d [%p]\n", mWidth, mHeight, this);
+}
+
+bool TizenVectorAnimationRenderer::Render(uint32_t frameNumber)
+{
+ Dali::Mutex::ScopedLock lock(mMutex);
+
+ if(!mVectorRenderer || !mPixelBuffer)
+ {
+ return false;
+ }
+
+ mVectorRenderer->renderSync(frameNumber, mLottieSurface);
+ mRenderCallback->Trigger();
+
+ if(!mResourceReady)
+ {
+ mResourceReady = true;
+ mResourceReadyTriggered = true;
+
+ TizenVectorAnimationManager::Get().TriggerEvent(*this);
+ }
+
+ return true;
+}
+
+void TizenVectorAnimationRenderer::RenderStopped()
+{
+}
+
+uint32_t TizenVectorAnimationRenderer::GetTotalFrameNumber() const
+{
+ return mTotalFrameNumber;
+}
+
+float TizenVectorAnimationRenderer::GetFrameRate() const
+{
+ return mFrameRate;
+}
+
+void TizenVectorAnimationRenderer::GetDefaultSize(uint32_t& width, uint32_t& height) const
+{
+ width = mDefaultWidth;
+ height = mDefaultHeight;
+}
+
+void TizenVectorAnimationRenderer::GetLayerInfo(Property::Map& map) const
+{
+ Dali::Mutex::ScopedLock lock(mMutex);
+
+ if(mVectorRenderer)
+ {
+ auto layerInfo = mVectorRenderer->layers();
+
+ for(auto&& iter : layerInfo)
+ {
+ Property::Array frames;
+ frames.PushBack(std::get<1>(iter));
+ frames.PushBack(std::get<2>(iter));
+ map.Add(std::get<0>(iter), frames);
+ }
+ }
+}
+
+bool TizenVectorAnimationRenderer::GetMarkerInfo(const std::string& marker, uint32_t& startFrame, uint32_t& endFrame) const
+{
+ Dali::Mutex::ScopedLock lock(mMutex);
+
+ if(mVectorRenderer)
+ {
+ auto markerList = mVectorRenderer->markers();
+ for(auto&& iter : markerList)
+ {
+ if(std::get<0>(iter).compare(marker) == 0)
+ {
+ startFrame = static_cast<uint32_t>(std::get<1>(iter));
+ endFrame = static_cast<uint32_t>(std::get<2>(iter));
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+void TizenVectorAnimationRenderer::GetMarkerInfo(Property::Map& map) const
+{
+ Dali::Mutex::ScopedLock lock(mMutex);
+
+ if(mVectorRenderer)
+ {
+ auto markerList = mVectorRenderer->markers();
+ for(auto&& iter : markerList)
+ {
+ Property::Array frames;
+ frames.PushBack(std::get<1>(iter));
+ frames.PushBack(std::get<2>(iter));
+ map.Add(std::get<0>(iter), frames);
+ }
+ }
+}
+
+void TizenVectorAnimationRenderer::InvalidateBuffer()
+{
+ Dali::Mutex::ScopedLock lock(mMutex);
+ mResourceReady = false;
+}
+
+void TizenVectorAnimationRenderer::AddPropertyValueCallback(const std::string& keyPath, VectorProperty property, CallbackBase* callback, int32_t id)
+{
+ Dali::Mutex::ScopedLock lock(mMutex);
+
+ mPropertyCallbacks.push_back(std::unique_ptr<CallbackBase>(callback));
+
+ switch(property)
+ {
+ case VectorProperty::FILL_COLOR:
+ {
+ mVectorRenderer->setValue<rlottie::Property::FillColor>(keyPath,
+ [property, callback, id](const rlottie::FrameInfo& info) {
+ Property::Value value = CallbackBase::ExecuteReturn<Property::Value>(*callback, id, property, info.curFrame());
+ Vector3 color;
+ if(value.Get(color))
+ {
+ return rlottie::Color(color.r, color.g, color.b);
+ }
+ return rlottie::Color(1.0f, 1.0f, 1.0f);
+ });
+ break;
+ }
+ case VectorProperty::FILL_OPACITY:
+ {
+ mVectorRenderer->setValue<rlottie::Property::FillOpacity>(keyPath,
+ [property, callback, id](const rlottie::FrameInfo& info) {
+ Property::Value value = CallbackBase::ExecuteReturn<Property::Value>(*callback, id, property, info.curFrame());
+ float opacity;
+ if(value.Get(opacity))
+ {
+ return opacity * 100;
+ }
+ return 100.0f;
+ });
+ break;
+ }
+ case VectorProperty::STROKE_COLOR:
+ {
+ mVectorRenderer->setValue<rlottie::Property::StrokeColor>(keyPath,
+ [property, callback, id](const rlottie::FrameInfo& info) {
+ Property::Value value = CallbackBase::ExecuteReturn<Property::Value>(*callback, id, property, info.curFrame());
+ Vector3 color;
+ if(value.Get(color))
+ {
+ return rlottie::Color(color.r, color.g, color.b);
+ }
+ return rlottie::Color(1.0f, 1.0f, 1.0f);
+ });
+ break;
+ }
+ case VectorProperty::STROKE_OPACITY:
+ {
+ mVectorRenderer->setValue<rlottie::Property::StrokeOpacity>(keyPath,
+ [property, callback, id](const rlottie::FrameInfo& info) {
+ Property::Value value = CallbackBase::ExecuteReturn<Property::Value>(*callback, id, property, info.curFrame());
+ float opacity;
+ if(value.Get(opacity))
+ {
+ return opacity * 100;
+ }
+ return 100.0f;
+ });
+ break;
+ }
+ case VectorProperty::STROKE_WIDTH:
+ {
+ mVectorRenderer->setValue<rlottie::Property::StrokeWidth>(keyPath,
+ [property, callback, id](const rlottie::FrameInfo& info) {
+ Property::Value value = CallbackBase::ExecuteReturn<Property::Value>(*callback, id, property, info.curFrame());
+ float width;
+ if(value.Get(width))
+ {
+ return width;
+ }
+ return 1.0f;
+ });
+ break;
+ }
+ case VectorProperty::TRANSFORM_ANCHOR:
+ {
+ mVectorRenderer->setValue<rlottie::Property::TrAnchor>(keyPath,
+ [property, callback, id](const rlottie::FrameInfo& info) {
+ Property::Value value = CallbackBase::ExecuteReturn<Property::Value>(*callback, id, property, info.curFrame());
+ Vector2 point;
+ if(value.Get(point))
+ {
+ return rlottie::Point(point.x, point.y);
+ }
+ return rlottie::Point(0.0f, 0.0f);
+ });
+ break;
+ }
+ case VectorProperty::TRANSFORM_POSITION:
+ {
+ mVectorRenderer->setValue<rlottie::Property::TrPosition>(keyPath,
+ [property, callback, id](const rlottie::FrameInfo& info) {
+ Property::Value value = CallbackBase::ExecuteReturn<Property::Value>(*callback, id, property, info.curFrame());
+ Vector2 position;
+ if(value.Get(position))
+ {
+ return rlottie::Point(position.x, position.y);
+ }
+ return rlottie::Point(0.0f, 0.0f);
+ });
+ break;
+ }
+ case VectorProperty::TRANSFORM_SCALE:
+ {
+ mVectorRenderer->setValue<rlottie::Property::TrScale>(keyPath,
+ [property, callback, id](const rlottie::FrameInfo& info) {
+ Property::Value value = CallbackBase::ExecuteReturn<Property::Value>(*callback, id, property, info.curFrame());
+ Vector2 scale;
+ if(value.Get(scale))
+ {
+ return rlottie::Size(scale.x, scale.y);
+ }
+ return rlottie::Size(100.0f, 100.0f);
+ });
+ break;
+ }
+ case VectorProperty::TRANSFORM_ROTATION:
+ {
+ mVectorRenderer->setValue<rlottie::Property::TrRotation>(keyPath,
+ [property, callback, id](const rlottie::FrameInfo& info) {
+ Property::Value value = CallbackBase::ExecuteReturn<Property::Value>(*callback, id, property, info.curFrame());
+ float rotation;
+ if(value.Get(rotation))
+ {
+ return rotation;
+ }
+ return 0.0f;
+ });
+ break;
+ }
+ case VectorProperty::TRANSFORM_OPACITY:
+ {
+ mVectorRenderer->setValue<rlottie::Property::TrOpacity>(keyPath,
+ [property, callback, id](const rlottie::FrameInfo& info) {
+ Property::Value value = CallbackBase::ExecuteReturn<Property::Value>(*callback, id, property, info.curFrame());
+ float opacity;
+ if(value.Get(opacity))
+ {
+ return opacity * 100;
+ }
+ return 100.0f;
+ });
+ break;
+ }
+ }
+}
+
+VectorAnimationRendererPlugin::UploadCompletedSignalType& TizenVectorAnimationRenderer::UploadCompletedSignal()
+{
+ return mUploadCompletedSignal;
+}
+
+void TizenVectorAnimationRenderer::NotifyEvent()
+{
+ bool emitSignal = false;
+ {
+ Dali::Mutex::ScopedLock lock(mMutex);
+
+ if(mResourceReadyTriggered)
+ {
+ DALI_LOG_INFO(gVectorAnimationLogFilter, Debug::Verbose, "Set Texture [%p]\n", this);
+
+ // Set texture
+ if(mRenderer && mTexture)
+ {
+ TextureSet textureSet = mRenderer.GetTextures();
+ textureSet.SetTexture(0, mTexture);
+ }
+
+ mResourceReadyTriggered = false;
+ emitSignal = true;
+ }
+ }
+ if(emitSignal)
+ {
+ mUploadCompletedSignal.Emit();
+ }
+}
+
+void TizenVectorAnimationRenderer::SetShader()
+{
+ if(mShaderChanged || !mTexture)
+ {
+ return;
+ }
+
+ // Not implemented
+
+ mShaderChanged = true;
+}
+
+void TizenVectorAnimationRenderer::ResetBuffers()
+{
+ if(mPixelBuffer)
+ {
+ uint32_t bufferSize = mPixelBuffer.GetWidth() * mPixelBuffer.GetHeight() * Dali::Pixel::GetBytesPerPixel(mPixelBuffer.GetPixelFormat());
+ memset(mPixelBuffer.GetBuffer(), 0, bufferSize);
+ }
+}
+
+} // namespace Plugin
+
+} // namespace Dali
--- /dev/null
+#ifndef DALI_TIZEN_VECTOR_ANIMATION_RENDERER_X_H
+#define DALI_TIZEN_VECTOR_ANIMATION_RENDERER_X_H
+
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <dali/devel-api/adaptor-framework/event-thread-callback.h>
+#include <dali/devel-api/adaptor-framework/pixel-buffer.h>
+#include <dali/devel-api/adaptor-framework/vector-animation-renderer-plugin.h>
+#include <dali/devel-api/threading/mutex.h>
+#include <dali/public-api/adaptor-framework/native-image-source.h>
+#include <dali/public-api/common/vector-wrapper.h>
+#include <rlottie.h>
+#include <memory>
+
+// INTERNAL INCLUDES
+#include <dali-extension/vector-animation-renderer/tizen-vector-animation-event-handler.h>
+
+namespace Dali
+{
+namespace Plugin
+{
+/**
+ * @brief Implementation of the Tizen vector animation renderer class which has Tizen platform dependency.
+ */
+class TizenVectorAnimationRenderer : public Dali::VectorAnimationRendererPlugin, public TizenVectorAnimationEventHandler
+{
+public:
+ /**
+ * @brief Constructor.
+ */
+ TizenVectorAnimationRenderer();
+
+ /**
+ * @brief Destructor.
+ */
+ virtual ~TizenVectorAnimationRenderer();
+
+ /**
+ * @copydoc Dali::VectorAnimationRendererPlugin::Finalize()
+ */
+ void Finalize() override;
+
+ /**
+ * @copydoc Dali::VectorAnimationRendererPlugin::Load()
+ */
+ bool Load(const std::string& url) override;
+
+ /**
+ * @copydoc Dali::VectorAnimationRendererPlugin::Load()
+ */
+ bool Load(const Dali::Vector<uint8_t>& data) override;
+
+ /**
+ * @copydoc Dali::VectorAnimationRendererPlugin::SetRenderer()
+ */
+ void SetRenderer(Renderer renderer) override;
+
+ /**
+ * @copydoc Dali::VectorAnimationRendererPlugin::SetSize()
+ */
+ void SetSize(uint32_t width, uint32_t height) override;
+
+ /**
+ * @copydoc Dali::VectorAnimationRendererPlugin::Render()
+ */
+ bool Render(uint32_t frameNumber) override;
+
+ /**
+ * @copydoc Dali::VectorAnimationRendererPlugin::RenderStopped()
+ */
+ void RenderStopped() override;
+
+ /**
+ * @copydoc Dali::VectorAnimationRendererPlugin::GetTotalFrameNumber()
+ */
+ uint32_t GetTotalFrameNumber() const override;
+
+ /**
+ * @copydoc Dali::VectorAnimationRendererPlugin::GetFrameRate()
+ */
+ float GetFrameRate() const override;
+
+ /**
+ * @copydoc Dali::VectorAnimationRendererPlugin::GetDefaultSize()
+ */
+ void GetDefaultSize(uint32_t& width, uint32_t& height) const override;
+
+ /**
+ * @copydoc Dali::VectorAnimationRendererPlugin::GetLayerInfo()
+ */
+ void GetLayerInfo(Property::Map& map) const override;
+
+ /**
+ * @copydoc Dali::VectorAnimationRendererPlugin::GetMarkerInfo()
+ */
+ bool GetMarkerInfo(const std::string& marker, uint32_t& startFrame, uint32_t& endFrame) const override;
+
+ /**
+ * @copydoc Dali::VectorAnimationRendererPlugin::GetMarkerInfo()
+ */
+ void GetMarkerInfo(Property::Map& map) const override;
+
+ /**
+ * @copydoc Dali::VectorAnimationRendererPlugin::InvalidateBuffer()
+ */
+ void InvalidateBuffer() override;
+
+ /**
+ * @copydoc Dali::VectorAnimationRendererPlugin::AddPropertyValueCallback()
+ */
+ void AddPropertyValueCallback(const std::string& keyPath, VectorProperty property, CallbackBase* callback, int32_t id) override;
+
+ /**
+ * @copydoc Dali::VectorAnimationRendererPlugin::UploadCompletedSignal()
+ */
+ UploadCompletedSignalType& UploadCompletedSignal() override;
+
+protected: // Implementation of TizenVectorAnimationEventHandler
+ /**
+ * @copydoc Dali::Plugin::TizenVectorAnimationEventHandler::NotifyEvent()
+ */
+ void NotifyEvent() override;
+
+private:
+ /**
+ * @brief Set shader for NativeImageSourceQueue with custom sampler type and prefix.
+ */
+ void SetShader();
+
+ /**
+ * @brief Reset buffer list.
+ */
+ void ResetBuffers();
+
+ /**
+ * @brief Event callback to process events.
+ */
+ void OnLottieRendered();
+
+private:
+ std::string mUrl; ///< The content file path
+ std::vector<std::unique_ptr<CallbackBase>> mPropertyCallbacks; ///< Property callback list
+
+ mutable Dali::Mutex mMutex; ///< Mutex
+ Dali::Renderer mRenderer; ///< Renderer
+ Dali::Texture mTexture; ///< Texture
+ rlottie::Surface mLottieSurface; ///
+ std::unique_ptr<rlottie::Animation> mVectorRenderer; ///< The vector animation renderer
+ UploadCompletedSignalType mUploadCompletedSignal; ///< Upload completed signal
+ uint32_t mTotalFrameNumber; ///< The total frame number
+ uint32_t mWidth; ///< The width of the surface
+ uint32_t mHeight; ///< The height of the surface
+ uint32_t mDefaultWidth; ///< The width of the surface
+ uint32_t mDefaultHeight; ///< The height of the surface
+ float mFrameRate; ///< The frame rate of the content
+ bool mLoadFailed; ///< Whether the file is loaded
+ bool mResourceReady; ///< Whether the resource is ready
+ bool mShaderChanged; ///< Whether the shader is changed to support native image
+ bool mResourceReadyTriggered; ///< Whether the resource ready is triggered
+ Dali::Devel::PixelBuffer mPixelBuffer; ///
+ std::unique_ptr<EventThreadCallback> mRenderCallback; ///
+};
+
+} // namespace Plugin
+
+} // namespace Dali
+
+#endif // DALI_TIZEN_VECTOR_ANIMATION_RENDERER_X_H