CanvasRenderer: Refactoring tvgObject management 36/258536/8
authorJunsuChoi <jsuya.choi@samsung.com>
Tue, 18 May 2021 08:08:45 +0000 (17:08 +0900)
committerJunsuChoi <jsuya.choi@samsung.com>
Fri, 4 Jun 2021 08:26:33 +0000 (17:26 +0900)
Thorvg is designed for immediate rendering, tvg objects use unique ptr.
However, CanvasRenderer, Shape, Drawable, and DrawableGroup inherit BaseHandle
and work according to the lifecycle of Dali objects.
CanvasRenderer classes unnecessarily checks whether tvgObject is deleted.
So we don't push each in each AddDrawable method. Just before drawing,
we clear the canvas and push all the objects managed by the list directly.

The memory of the pushed object is managed in the canvas.
Each Drawable class only needs to manage its own tvg object.

Change-Id: I373fbe4a34c8b8a3a72d222744226f84075575d7

18 files changed:
dali/internal/canvas-renderer/common/drawable-group-impl.cpp
dali/internal/canvas-renderer/common/drawable-group-impl.h
dali/internal/canvas-renderer/common/drawable-impl.cpp
dali/internal/canvas-renderer/common/drawable-impl.h
dali/internal/canvas-renderer/tizen/canvas-renderer-impl-tizen.cpp
dali/internal/canvas-renderer/tizen/canvas-renderer-impl-tizen.h
dali/internal/canvas-renderer/tizen/drawable-group-impl-tizen.cpp
dali/internal/canvas-renderer/tizen/drawable-group-impl-tizen.h
dali/internal/canvas-renderer/tizen/drawable-impl-tizen.cpp
dali/internal/canvas-renderer/tizen/drawable-impl-tizen.h
dali/internal/canvas-renderer/tizen/shape-impl-tizen.cpp
dali/internal/canvas-renderer/ubuntu/canvas-renderer-impl-ubuntu.cpp
dali/internal/canvas-renderer/ubuntu/canvas-renderer-impl-ubuntu.h
dali/internal/canvas-renderer/ubuntu/drawable-group-impl-ubuntu.cpp
dali/internal/canvas-renderer/ubuntu/drawable-group-impl-ubuntu.h
dali/internal/canvas-renderer/ubuntu/drawable-impl-ubuntu.cpp
dali/internal/canvas-renderer/ubuntu/drawable-impl-ubuntu.h
dali/internal/canvas-renderer/ubuntu/shape-impl-ubuntu.cpp

index ff3132f..01109ae 100644 (file)
@@ -38,6 +38,11 @@ bool DrawableGroup::Clear()
   return false;
 }
 
+DrawableGroup::DrawableVector DrawableGroup::GetDrawables() const
+{
+  return DrawableVector();
+}
+
 } // namespace Adaptor
 
 } // namespace Internal
index 5a22054..f226dd5 100644 (file)
@@ -38,6 +38,11 @@ class DrawableGroup : public Internal::Adaptor::Drawable
 {
 public:
   /**
+   * @brief List of drawables.
+   */
+  using DrawableVector = std::vector<Dali::CanvasRenderer::Drawable>;
+
+  /**
    * @brief Constructor
    */
   DrawableGroup();
@@ -48,7 +53,7 @@ public:
   ~DrawableGroup() override;
 
   /**
-   * @copydoc Dali::CanvasRenderer::DrawableGroup::AddDrawable()
+   * @copydoc Dali::CanvasRenderer::DrawableGroup::AddDrawable
    */
   virtual bool AddDrawable(Dali::CanvasRenderer::Drawable& drawable);
 
@@ -57,6 +62,12 @@ public:
    */
   virtual bool Clear();
 
+  /**
+   * @brief Get list of drawables that added this group.
+   * @return Returns list of drawables.
+   */
+  virtual DrawableVector GetDrawables() const;
+
   DrawableGroup(const DrawableGroup&) = delete;
   DrawableGroup& operator=(DrawableGroup&) = delete;
   DrawableGroup(DrawableGroup&&)           = delete;
index 993faef..3856e06 100644 (file)
@@ -29,140 +29,158 @@ Drawable::Drawable() = default;
 
 Drawable::~Drawable()
 {
-  if(pImpl)
+  if(mImpl)
   {
-    delete pImpl;
+    delete mImpl;
   }
 }
 
 void Drawable::Create()
 {
-  if(!pImpl)
+  if(!mImpl)
   {
-    pImpl = Internal::Adaptor::DrawableFactory::New();
+    mImpl = Internal::Adaptor::DrawableFactory::New();
   }
 }
 
 bool Drawable::SetOpacity(float opacity)
 {
-  if(!pImpl)
+  if(!mImpl)
   {
     return false;
   }
-  return pImpl->SetOpacity(opacity);
+  return mImpl->SetOpacity(opacity);
 }
 
 float Drawable::GetOpacity() const
 {
-  if(!pImpl)
+  if(!mImpl)
   {
     return 0.0f;
   }
-  return pImpl->GetOpacity();
+  return mImpl->GetOpacity();
 }
 
 bool Drawable::Rotate(Degree degree)
 {
-  if(!pImpl)
+  if(!mImpl)
   {
     return false;
   }
-  return pImpl->Rotate(degree);
+  return mImpl->Rotate(degree);
 }
 
 bool Drawable::Scale(float factor)
 {
-  if(!pImpl)
+  if(!mImpl)
   {
     return false;
   }
-  return pImpl->Scale(factor);
+  return mImpl->Scale(factor);
 }
 
 bool Drawable::Translate(Vector2 translate)
 {
-  if(!pImpl)
+  if(!mImpl)
   {
     return false;
   }
-  return pImpl->Translate(translate);
+  return mImpl->Translate(translate);
 }
 
 bool Drawable::Transform(const Dali::Matrix3& matrix)
 {
-  if(!pImpl)
+  if(!mImpl)
   {
     return false;
   }
-  return pImpl->Transform(matrix);
+  return mImpl->Transform(matrix);
 }
 
 Rect<float> Drawable::GetBoundingBox() const
 {
-  if(!pImpl)
+  if(!mImpl)
   {
     return Rect<float>(0, 0, 0, 0);
   }
-  return pImpl->GetBoundingBox();
+  return mImpl->GetBoundingBox();
 }
 
 void Drawable::SetAdded(bool added)
 {
-  if(!pImpl)
+  if(!mImpl)
   {
     return;
   }
-  pImpl->SetAdded(added);
+  mImpl->SetAdded(added);
 }
 
 bool Drawable::IsAdded() const
 {
-  if(!pImpl)
+  if(!mImpl)
   {
     return false;
   }
-  return pImpl->IsAdded();
+  return mImpl->IsAdded();
 }
 
 void* Drawable::GetObject() const
 {
-  if(!pImpl)
+  if(!mImpl)
   {
     return nullptr;
   }
-  return pImpl->GetObject();
+  return mImpl->GetObject();
 }
 
 void Drawable::SetObject(const void* object)
 {
-  if(!pImpl)
+  if(!mImpl)
   {
     return;
   }
-  pImpl->SetObject(object);
+  mImpl->SetObject(object);
 }
 
 void Drawable::SetChanged(bool changed)
 {
-  if(!pImpl)
+  if(!mImpl)
   {
     return;
   }
-  pImpl->SetChanged(changed);
+  mImpl->SetChanged(changed);
 }
 
 bool Drawable::GetChanged() const
 {
-  if(!pImpl)
+  if(!mImpl)
   {
     return false;
   }
-  return pImpl->GetChanged();
+  return mImpl->GetChanged();
+}
+
+void Drawable::SetType(Drawable::Types type)
+{
+  if(!mImpl)
+  {
+    return;
+  }
+  mImpl->SetType(type);
+}
+
+Drawable::Types Drawable::GetType() const
+{
+  if(!mImpl)
+  {
+    return Drawable::Types::NONE;
+  }
+  return mImpl->GetType();
 }
 
 Dali::Internal::Adaptor::Drawable* Drawable::GetImplementation()
 {
-  return pImpl;
+  return mImpl;
 }
 
 } // namespace Adaptor
index 3fab28b..8222833 100644 (file)
@@ -41,6 +41,17 @@ class Drawable : public Dali::BaseObject
 {
 public:
   /**
+   * @brief Enumeration for type of drawable.
+   */
+  enum class Types
+  {
+    NONE = 0,      ///< Means that type is not defined.
+    SHAPE,         ///< Meaning of Shape class that inherits Drawable.
+    DRAWABLE_GROUP ///< Meaning of DrawableGorup class that inherits Drawable.
+  };
+
+public:
+  /**
    * @brief Constructor
    */
   Drawable();
@@ -127,6 +138,18 @@ public:
   virtual bool GetChanged() const;
 
   /**
+   * @brief Set drawable's type.
+   * @param[in] type Type of drawable.
+   */
+  virtual void SetType(Types type);
+
+  /**
+   * @brief Get drawable's type.
+   * @return Returns type of drawable.
+   */
+  virtual Types GetType() const;
+
+  /**
    * @brief Returns a drawable's implements object pointer.
    * @return Returns a drawable's implements object pointer.
    */
@@ -138,7 +161,7 @@ public:
   Drawable& operator=(Drawable&&) = delete;
 
 private:
-  Dali::Internal::Adaptor::Drawable* pImpl = nullptr;
+  Dali::Internal::Adaptor::Drawable* mImpl = nullptr;
 };
 
 } // namespace Adaptor
index 5b1328b..f86723d 100644 (file)
@@ -24,6 +24,7 @@
 
 // INTERNAL INCLUDES
 #include <dali/devel-api/adaptor-framework/pixel-buffer.h>
+#include <dali/internal/canvas-renderer/common/drawable-group-impl.h>
 #include <dali/internal/canvas-renderer/common/drawable-impl.h>
 #include <dali/internal/imaging/common/pixel-buffer-impl.h>
 
@@ -66,16 +67,8 @@ CanvasRendererTizen::CanvasRendererTizen(const Vector2& viewBox)
 CanvasRendererTizen::~CanvasRendererTizen()
 {
 #ifdef THORVG_SUPPORT
-  for(auto& it : mDrawables)
-  {
-    Dali::CanvasRenderer::Drawable drawable = it.GetHandle();
-    if(DALI_UNLIKELY(!drawable))
-    {
-      continue;
-    }
-    Internal::Adaptor::Drawable& drawableImpl = GetImplementation(drawable);
-    drawableImpl.SetObject(nullptr);
-  }
+  mDrawables.clear();
+
   //Terminate ThorVG Engine
   tvg::Initializer::term(tvg::CanvasEngine::Sw);
 #endif
@@ -97,10 +90,6 @@ void CanvasRendererTizen::Initialize(const Vector2& viewBox)
   }
 
   MakeTargetBuffer(mSize);
-
-  auto scene = tvg::Scene::gen();
-  mTvgRoot   = scene.get();
-  mTvgCanvas->push(move(scene));
 #endif
 }
 
@@ -111,12 +100,7 @@ bool CanvasRendererTizen::Commit()
 
   for(auto& it : mDrawables)
   {
-    Dali::CanvasRenderer::Drawable drawable = it.GetHandle();
-    if(DALI_UNLIKELY(!drawable))
-    {
-      continue;
-    }
-    Internal::Adaptor::Drawable& drawableImpl = GetImplementation(drawable);
+    Internal::Adaptor::Drawable& drawableImpl = GetImplementation(it);
     if(drawableImpl.GetChanged())
     {
       changed = true;
@@ -143,12 +127,32 @@ bool CanvasRendererTizen::Commit()
     return false;
   }
 
+  if(mTvgCanvas->clear() != tvg::Result::Success)
+  {
+    DALI_LOG_ERROR("ThorVG canvas clear fail [%p]\n", this);
+    return false;
+  }
+
+  auto scene = tvg::Scene::gen();
+  mTvgRoot   = scene.get();
+  for(auto& it : mDrawables)
+  {
+    PushDrawableToGroup(it, mTvgRoot);
+  }
+
+  if(mTvgCanvas->push(move(scene)) != tvg::Result::Success)
+  {
+    DALI_LOG_ERROR("ThorVG canvas push fail [%p]\n", this);
+    return false;
+  }
+
   if(mViewBox != mSize)
   {
     auto scaleX = mSize.width / mViewBox.width;
     auto scaleY = mSize.height / mViewBox.height;
     mTvgRoot->scale(scaleX < scaleY ? scaleX : scaleY);
   }
+
   mTvgCanvas->update(mTvgRoot);
 
   if(mTvgCanvas->draw() != tvg::Result::Success)
@@ -173,34 +177,19 @@ Devel::PixelBuffer CanvasRendererTizen::GetPixelBuffer()
 bool CanvasRendererTizen::AddDrawable(Dali::CanvasRenderer::Drawable& drawable)
 {
 #ifdef THORVG_SUPPORT
-  for(auto& it : mDrawables)
-  {
-    if(it.GetHandle() == drawable)
-    {
-      DALI_LOG_ERROR("Already added [%p]\n", this);
-      return false;
-    }
-  }
-
   Internal::Adaptor::Drawable& drawableImpl = GetImplementation(drawable);
-  tvg::Paint*                  pDrawable    = static_cast<tvg::Paint*>(drawableImpl.GetObject());
-  if(!pDrawable)
+  if(drawableImpl.IsAdded())
   {
-    DALI_LOG_ERROR("Invalid drawable object [%p]\n", this);
+    DALI_LOG_ERROR("Already added [%p][%p]\n", this, &drawable);
     return false;
   }
+
   if(mSize.width < 1.0f || mSize.height < 1.0f)
   {
     DALI_LOG_ERROR("Size is zero [%p]\n", this);
     return false;
   }
 
-  if(mTvgRoot->push(std::unique_ptr<tvg::Paint>(pDrawable)) != tvg::Result::Success)
-  {
-    DALI_LOG_ERROR("Tvg push fail [%p]\n", this);
-    return false;
-  }
-
   drawableImpl.SetAdded(true);
   mDrawables.push_back(drawable);
   mChanged = true;
@@ -252,6 +241,37 @@ void CanvasRendererTizen::MakeTargetBuffer(const Vector2& size)
 #endif
 }
 
+#ifdef THORVG_SUPPORT
+void CanvasRendererTizen::PushDrawableToGroup(Dali::CanvasRenderer::Drawable& drawable, tvg::Scene* parent)
+{
+  Internal::Adaptor::Drawable& drawableImpl        = Dali::GetImplementation(drawable);
+  tvg::Paint*                  tvgDuplicatedObject = static_cast<tvg::Paint*>(drawableImpl.GetObject())->duplicate();
+  if(!tvgDuplicatedObject)
+  {
+    DALI_LOG_ERROR("Invalid drawable object [%p]\n", this);
+    return;
+  }
+  Drawable::Types type = drawableImpl.GetType();
+
+  if(type == Drawable::Types::DRAWABLE_GROUP)
+  {
+    Dali::CanvasRenderer::DrawableGroup& group             = static_cast<Dali::CanvasRenderer::DrawableGroup&>(drawable);
+    Internal::Adaptor::DrawableGroup&    drawableGroupImpl = Dali::GetImplementation(group);
+    DrawableGroup::DrawableVector        drawables         = drawableGroupImpl.GetDrawables();
+    for(auto& it : drawables)
+    {
+      PushDrawableToGroup(it, static_cast<tvg::Scene*>(tvgDuplicatedObject));
+    }
+  }
+
+  if(parent->push(std::move(std::unique_ptr<tvg::Paint>(tvgDuplicatedObject))) != tvg::Result::Success)
+  {
+    DALI_LOG_ERROR("Tvg push fail [%p]\n", this);
+    return;
+  }
+}
+#endif
+
 } // namespace Adaptor
 
 } // namespace Internal
index a6f4e1f..13edf48 100644 (file)
@@ -28,6 +28,7 @@
 #include <dali/devel-api/adaptor-framework/canvas-renderer-drawable.h>
 #include <dali/devel-api/adaptor-framework/canvas-renderer.h>
 #include <dali/devel-api/adaptor-framework/pixel-buffer.h>
+#include <dali/internal/canvas-renderer/common/drawable-group-impl.h>
 #include <dali/internal/canvas-renderer/common/canvas-renderer-impl.h>
 
 namespace Dali
@@ -103,6 +104,16 @@ private:
    */
   void MakeTargetBuffer(const Vector2& size);
 
+#ifdef THORVG_SUPPORT
+  /**
+   * @brief Push drawable object to parent.
+   * If drawable is a type that can have child drawables, it is called recursively.
+   * @param[in] drawable The drawable object.
+   * @param[in] group The scene object of tvg that can be drawable group.
+   */
+  void PushDrawableToGroup(Dali::CanvasRenderer::Drawable& drawable, tvg::Scene* group);
+#endif
+
 private:
   Devel::PixelBuffer mPixelBuffer;
 
@@ -110,9 +121,7 @@ private:
   std::unique_ptr<tvg::SwCanvas> mTvgCanvas;
   tvg::Scene*                    mTvgRoot;
 #endif
-  using DrawableVector         = std::vector<WeakHandle<Dali::CanvasRenderer::Drawable>>;
-  using DrawableVectorIterator = DrawableVector::iterator;
-  DrawableVector mDrawables;
+  DrawableGroup::DrawableVector mDrawables;
 
   Vector2 mSize;
   Vector2 mViewBox;
index 18f7ada..5ec40c8 100644 (file)
@@ -71,29 +71,23 @@ void DrawableGroupTizen::Initialize()
 
   Drawable::Create();
   Drawable::SetObject(static_cast<void*>(mTvgScene));
+  Drawable::SetType(Drawable::Types::DRAWABLE_GROUP);
 #endif
 }
 
 bool DrawableGroupTizen::AddDrawable(Dali::CanvasRenderer::Drawable& drawable)
 {
 #ifdef THORVG_SUPPORT
-  Internal::Adaptor::Drawable& drawableImpl = Dali::GetImplementation(drawable);
-  tvg::Paint*                  pDrawable    = static_cast<tvg::Paint*>(drawableImpl.GetObject());
-  if(!pDrawable)
+  if(!Drawable::GetObject() || !mTvgScene)
   {
-    DALI_LOG_ERROR("Invalid drawable object [%p]\n", this);
+    DALI_LOG_ERROR("DrawableGroup is null\n");
     return false;
   }
 
+  Internal::Adaptor::Drawable& drawableImpl = Dali::GetImplementation(drawable);
   if(drawableImpl.IsAdded())
   {
-    DALI_LOG_ERROR("Already added somewhere [%p][%p]\n", this, &drawable);
-    return false;
-  }
-
-  if(mTvgScene->push(std::unique_ptr<tvg::Paint>(pDrawable)) != tvg::Result::Success)
-  {
-    DALI_LOG_ERROR("Tvg push fail [%p]\n", this);
+    DALI_LOG_ERROR("Already added [%p][%p]\n", this, &drawable);
     return false;
   }
 
@@ -110,7 +104,7 @@ bool DrawableGroupTizen::AddDrawable(Dali::CanvasRenderer::Drawable& drawable)
 bool DrawableGroupTizen::Clear()
 {
 #ifdef THORVG_SUPPORT
-  if(!mTvgScene)
+  if(!Drawable::GetObject() || !mTvgScene)
   {
     DALI_LOG_ERROR("DrawableGroup is null\n");
     return false;
@@ -118,12 +112,7 @@ bool DrawableGroupTizen::Clear()
 
   for(auto& it : mDrawables)
   {
-    Dali::CanvasRenderer::Drawable drawable = it.GetHandle();
-    if(DALI_UNLIKELY(!drawable))
-    {
-      continue;
-    }
-    Internal::Adaptor::Drawable& drawableImpl = Dali::GetImplementation(drawable);
+    Internal::Adaptor::Drawable& drawableImpl = Dali::GetImplementation(it);
     drawableImpl.SetAdded(false);
   }
 
@@ -143,6 +132,11 @@ bool DrawableGroupTizen::Clear()
 #endif
 }
 
+DrawableGroup::DrawableVector DrawableGroupTizen::GetDrawables() const
+{
+  return mDrawables;
+}
+
 } // namespace Adaptor
 
 } // namespace Internal
index dd9acfd..82f6162 100644 (file)
@@ -48,7 +48,7 @@ public:
   static DrawableGroupTizen* New();
 
   /**
-   * @copydoc Dali::CanvasRenderer::DrawableGroup::AddDrawable()
+   * @copydoc Dali::CanvasRenderer::DrawableGroup::AddDrawable
    */
   bool AddDrawable(Dali::CanvasRenderer::Drawable& drawable) override;
 
@@ -57,6 +57,11 @@ public:
    */
   bool Clear() override;
 
+  /**
+   * @copydoc Dali::CanvasRenderer::DrawableGroup::GetDrawables
+   */
+  DrawableVector GetDrawables() const override;
+
 private:
   DrawableGroupTizen(const DrawableGroupTizen&) = delete;
   DrawableGroupTizen& operator=(DrawableGroupTizen&) = delete;
@@ -83,8 +88,6 @@ private:
 #ifdef THORVG_SUPPORT
   tvg::Scene* mTvgScene;
 #endif
-  using DrawableVector         = std::vector<WeakHandle<Dali::CanvasRenderer::Drawable>>;
-  using DrawableVectorIterator = DrawableVector::iterator;
   DrawableVector mDrawables;
 };
 
index 9bae6a6..b8baa3c 100644 (file)
@@ -48,7 +48,8 @@ DrawableTizen* DrawableTizen::New()
 
 DrawableTizen::DrawableTizen()
 : mAdded(false),
-  mChanged(false)
+  mChanged(false),
+  mType(Drawable::Types::NONE)
 #ifdef THORVG_SUPPORT
   ,
   mTvgPaint(nullptr)
@@ -59,7 +60,7 @@ DrawableTizen::DrawableTizen()
 DrawableTizen::~DrawableTizen()
 {
 #ifdef THORVG_SUPPORT
-  if(mTvgPaint && !mAdded)
+  if(mTvgPaint)
   {
     delete mTvgPaint;
   }
@@ -235,17 +236,6 @@ void DrawableTizen::SetObject(const void* object)
   {
     mTvgPaint = static_cast<tvg::Paint*>((void*)object);
   }
-  else
-  {
-    if(mAdded)
-    {
-      mTvgPaint = nullptr;
-    }
-    if(mTvgPaint)
-    {
-      delete mTvgPaint;
-    }
-  }
 #endif
 }
 
@@ -259,6 +249,16 @@ bool DrawableTizen::GetChanged() const
 {
   return mChanged;
 }
+
+void DrawableTizen::SetType(Drawable::Types type)
+{
+  mType = type;
+}
+
+Drawable::Types DrawableTizen::GetType() const
+{
+  return mType;
+}
 } // namespace Adaptor
 
 } // namespace Internal
index 2d82391..4f281e2 100644 (file)
@@ -113,6 +113,16 @@ public:
    */
   bool GetChanged() const override;
 
+  /**
+   * @copydoc Internal::Adaptor::Drawable::SetType
+   */
+  void SetType(Types type);
+
+  /**
+   * @copydoc Internal::Adaptor::Drawable::GetType
+   */
+  Types GetType() const;
+
   DrawableTizen(const Drawable&) = delete;
   DrawableTizen& operator=(Drawable&) = delete;
   DrawableTizen(Drawable&&)           = delete;
@@ -130,8 +140,9 @@ protected:
   virtual ~DrawableTizen() override;
 
 private:
-  bool mAdded;
-  bool mChanged;
+  bool            mAdded;
+  bool            mChanged;
+  Drawable::Types mType;
 
 #ifdef THORVG_SUPPORT
   tvg::Paint* mTvgPaint;
index 7c8dd2a..014af70 100644 (file)
@@ -68,13 +68,14 @@ void ShapeTizen::Initialize()
 
   Drawable::Create();
   Drawable::SetObject(static_cast<void*>(mTvgShape));
+  Drawable::SetType(Drawable::Types::SHAPE);
 #endif
 }
 
 bool ShapeTizen::AddRect(Rect<float> rect, Vector2 roundedCorner)
 {
 #ifdef THORVG_SUPPORT
-  if(!mTvgShape)
+  if(!Drawable::GetObject() || !mTvgShape)
   {
     DALI_LOG_ERROR("Shape is null [%p]\n", this);
     return false;
@@ -94,7 +95,7 @@ bool ShapeTizen::AddRect(Rect<float> rect, Vector2 roundedCorner)
 bool ShapeTizen::AddCircle(Vector2 center, Vector2 radius)
 {
 #ifdef THORVG_SUPPORT
-  if(!mTvgShape)
+  if(!Drawable::GetObject() || !mTvgShape)
   {
     DALI_LOG_ERROR("Shape is null [%p]\n", this);
     return false;
@@ -114,7 +115,7 @@ bool ShapeTizen::AddCircle(Vector2 center, Vector2 radius)
 bool ShapeTizen::AddArc(Vector2 center, float radius, float startAngle, float sweep, bool pie)
 {
 #ifdef THORVG_SUPPORT
-  if(!mTvgShape)
+  if(!Drawable::GetObject() || !mTvgShape)
   {
     DALI_LOG_ERROR("Shape is null\n");
     return false;
@@ -135,7 +136,7 @@ bool ShapeTizen::AddArc(Vector2 center, float radius, float startAngle, float sw
 bool ShapeTizen::AddMoveTo(Vector2 point)
 {
 #ifdef THORVG_SUPPORT
-  if(!mTvgShape)
+  if(!Drawable::GetObject() || !mTvgShape)
   {
     DALI_LOG_ERROR("Shape is null\n");
     return false;
@@ -156,7 +157,7 @@ bool ShapeTizen::AddMoveTo(Vector2 point)
 bool ShapeTizen::AddLineTo(Vector2 line)
 {
 #ifdef THORVG_SUPPORT
-  if(!mTvgShape)
+  if(!Drawable::GetObject() || !mTvgShape)
   {
     DALI_LOG_ERROR("Shape is null\n");
     return false;
@@ -177,7 +178,7 @@ bool ShapeTizen::AddLineTo(Vector2 line)
 bool ShapeTizen::AddCubicTo(Vector2 controlPoint1, Vector2 controlPoint2, Vector2 endPoint)
 {
 #ifdef THORVG_SUPPORT
-  if(!mTvgShape)
+  if(!Drawable::GetObject() || !mTvgShape)
   {
     DALI_LOG_ERROR("Shape is null\n");
     return false;
@@ -198,7 +199,7 @@ bool ShapeTizen::AddCubicTo(Vector2 controlPoint1, Vector2 controlPoint2, Vector
 bool ShapeTizen::Close()
 {
 #ifdef THORVG_SUPPORT
-  if(!mTvgShape)
+  if(!Drawable::GetObject() || !mTvgShape)
   {
     DALI_LOG_ERROR("Shape is null\n");
     return false;
@@ -219,7 +220,7 @@ bool ShapeTizen::Close()
 bool ShapeTizen::ResetPath()
 {
 #ifdef THORVG_SUPPORT
-  if(!mTvgShape)
+  if(!Drawable::GetObject() || !mTvgShape)
   {
     DALI_LOG_ERROR("Shape is null\n");
     return false;
@@ -240,7 +241,7 @@ bool ShapeTizen::ResetPath()
 bool ShapeTizen::SetFillColor(Vector4 color)
 {
 #ifdef THORVG_SUPPORT
-  if(!mTvgShape)
+  if(!Drawable::GetObject() || !mTvgShape)
   {
     DALI_LOG_ERROR("Shape is null [%p]\n", this);
     return false;
@@ -261,7 +262,7 @@ bool ShapeTizen::SetFillColor(Vector4 color)
 Vector4 ShapeTizen::GetFillColor() const
 {
 #ifdef THORVG_SUPPORT
-  if(!mTvgShape)
+  if(!Drawable::GetObject() || !mTvgShape)
   {
     DALI_LOG_ERROR("Shape is null [%p]\n", this);
     return Vector4(0, 0, 0, 0);
@@ -282,7 +283,7 @@ Vector4 ShapeTizen::GetFillColor() const
 bool ShapeTizen::SetFillRule(Dali::CanvasRenderer::Shape::FillRule rule)
 {
 #ifdef THORVG_SUPPORT
-  if(!mTvgShape)
+  if(!Drawable::GetObject() || !mTvgShape)
   {
     DALI_LOG_ERROR("Shape is null\n");
     return false;
@@ -302,7 +303,7 @@ bool ShapeTizen::SetFillRule(Dali::CanvasRenderer::Shape::FillRule rule)
 Dali::CanvasRenderer::Shape::FillRule ShapeTizen::GetFillRule() const
 {
 #ifdef THORVG_SUPPORT
-  if(!mTvgShape)
+  if(!Drawable::GetObject() || !mTvgShape)
   {
     DALI_LOG_ERROR("Shape is null\n");
     return Dali::CanvasRenderer::Shape::FillRule::WINDING;
@@ -318,7 +319,7 @@ Dali::CanvasRenderer::Shape::FillRule ShapeTizen::GetFillRule() const
 bool ShapeTizen::SetStrokeWidth(float width)
 {
 #ifdef THORVG_SUPPORT
-  if(!mTvgShape)
+  if(!Drawable::GetObject() || !mTvgShape)
   {
     DALI_LOG_ERROR("Shape is null\n");
     return false;
@@ -339,7 +340,7 @@ bool ShapeTizen::SetStrokeWidth(float width)
 float ShapeTizen::GetStrokeWidth() const
 {
 #ifdef THORVG_SUPPORT
-  if(!mTvgShape)
+  if(!Drawable::GetObject() || !mTvgShape)
   {
     DALI_LOG_ERROR("Shape is null\n");
     return false;
@@ -353,7 +354,7 @@ float ShapeTizen::GetStrokeWidth() const
 bool ShapeTizen::SetStrokeColor(Vector4 color)
 {
 #ifdef THORVG_SUPPORT
-  if(!mTvgShape)
+  if(!Drawable::GetObject() || !mTvgShape)
   {
     DALI_LOG_ERROR("Shape is null\n");
     return false;
@@ -374,7 +375,7 @@ bool ShapeTizen::SetStrokeColor(Vector4 color)
 Vector4 ShapeTizen::GetStrokeColor() const
 {
 #ifdef THORVG_SUPPORT
-  if(!mTvgShape)
+  if(!Drawable::GetObject() || !mTvgShape)
   {
     DALI_LOG_ERROR("Shape is null\n");
     return Vector4(0, 0, 0, 0);
@@ -396,7 +397,7 @@ Vector4 ShapeTizen::GetStrokeColor() const
 bool ShapeTizen::SetStrokeDash(const Dali::Vector<float> dashPattern)
 {
 #ifdef THORVG_SUPPORT
-  if(!mTvgShape)
+  if(!Drawable::GetObject() || !mTvgShape)
   {
     DALI_LOG_ERROR("Shape is null\n");
     return false;
@@ -424,7 +425,7 @@ bool ShapeTizen::SetStrokeDash(const Dali::Vector<float> dashPattern)
 Dali::Vector<float> ShapeTizen::GetStrokeDash() const
 {
 #ifdef THORVG_SUPPORT
-  if(!mTvgShape)
+  if(!Drawable::GetObject() || !mTvgShape)
   {
     DALI_LOG_ERROR("Shape is null\n");
     return Vector<float>();
@@ -456,12 +457,11 @@ Dali::Vector<float> ShapeTizen::GetStrokeDash() const
 bool ShapeTizen::SetStrokeCap(Dali::CanvasRenderer::Shape::StrokeCap cap)
 {
 #ifdef THORVG_SUPPORT
-  if(!mTvgShape)
+  if(!Drawable::GetObject() || !mTvgShape)
   {
     DALI_LOG_ERROR("Shape is null\n");
     return false;
   }
-
   if(static_cast<tvg::Shape*>(mTvgShape)->stroke(static_cast<tvg::StrokeCap>(cap)) != tvg::Result::Success)
   {
     DALI_LOG_ERROR("SetStrokeCap fail.\n");
@@ -477,7 +477,7 @@ bool ShapeTizen::SetStrokeCap(Dali::CanvasRenderer::Shape::StrokeCap cap)
 Dali::CanvasRenderer::Shape::StrokeCap ShapeTizen::GetStrokeCap() const
 {
 #ifdef THORVG_SUPPORT
-  if(!mTvgShape)
+  if(!Drawable::GetObject() || !mTvgShape)
   {
     DALI_LOG_ERROR("Shape is null\n");
     return Dali::CanvasRenderer::Shape::StrokeCap::SQUARE;
@@ -493,7 +493,7 @@ Dali::CanvasRenderer::Shape::StrokeCap ShapeTizen::GetStrokeCap() const
 bool ShapeTizen::SetStrokeJoin(Dali::CanvasRenderer::Shape::StrokeJoin join)
 {
 #ifdef THORVG_SUPPORT
-  if(!mTvgShape)
+  if(!Drawable::GetObject() || !mTvgShape)
   {
     DALI_LOG_ERROR("Shape is null\n");
     return false;
@@ -514,7 +514,7 @@ bool ShapeTizen::SetStrokeJoin(Dali::CanvasRenderer::Shape::StrokeJoin join)
 Dali::CanvasRenderer::Shape::StrokeJoin ShapeTizen::GetStrokeJoin() const
 {
 #ifdef THORVG_SUPPORT
-  if(!mTvgShape)
+  if(!Drawable::GetObject() || !mTvgShape)
   {
     DALI_LOG_ERROR("Shape is null\n");
     return Dali::CanvasRenderer::Shape::StrokeJoin::BEVEL;
index 43705e6..8efe447 100644 (file)
@@ -24,6 +24,7 @@
 
 // INTERNAL INCLUDES
 #include <dali/devel-api/adaptor-framework/pixel-buffer.h>
+#include <dali/internal/canvas-renderer/common/drawable-group-impl.h>
 #include <dali/internal/canvas-renderer/common/drawable-impl.h>
 #include <dali/internal/imaging/common/pixel-buffer-impl.h>
 
@@ -66,16 +67,8 @@ CanvasRendererUbuntu::CanvasRendererUbuntu(const Vector2& viewBox)
 CanvasRendererUbuntu::~CanvasRendererUbuntu()
 {
 #ifdef THORVG_SUPPORT
-  for(auto& it : mDrawables)
-  {
-    Dali::CanvasRenderer::Drawable drawable = it.GetHandle();
-    if(DALI_UNLIKELY(!drawable))
-    {
-      continue;
-    }
-    Internal::Adaptor::Drawable& drawableImpl = GetImplementation(drawable);
-    drawableImpl.SetObject(nullptr);
-  }
+  mDrawables.clear();
+
   //Terminate ThorVG Engine
   tvg::Initializer::term(tvg::CanvasEngine::Sw);
 #endif
@@ -97,10 +90,6 @@ void CanvasRendererUbuntu::Initialize(const Vector2& viewBox)
   }
 
   MakeTargetBuffer(mSize);
-
-  auto scene = tvg::Scene::gen();
-  mTvgRoot   = scene.get();
-  mTvgCanvas->push(move(scene));
 #endif
 }
 
@@ -111,12 +100,7 @@ bool CanvasRendererUbuntu::Commit()
 
   for(auto& it : mDrawables)
   {
-    Dali::CanvasRenderer::Drawable drawable = it.GetHandle();
-    if(DALI_UNLIKELY(!drawable))
-    {
-      continue;
-    }
-    Internal::Adaptor::Drawable& drawableImpl = GetImplementation(drawable);
+    Internal::Adaptor::Drawable& drawableImpl = GetImplementation(it);
     if(drawableImpl.GetChanged())
     {
       changed = true;
@@ -143,12 +127,32 @@ bool CanvasRendererUbuntu::Commit()
     return false;
   }
 
+  if(mTvgCanvas->clear() != tvg::Result::Success)
+  {
+    DALI_LOG_ERROR("ThorVG canvas clear fail [%p]\n", this);
+    return false;
+  }
+
+  auto scene = tvg::Scene::gen();
+  mTvgRoot   = scene.get();
+  for(auto& it : mDrawables)
+  {
+    PushDrawableToGroup(it, mTvgRoot);
+  }
+
+  if(mTvgCanvas->push(move(scene)) != tvg::Result::Success)
+  {
+    DALI_LOG_ERROR("ThorVG canvas push fail [%p]\n", this);
+    return false;
+  }
+
   if(mViewBox != mSize)
   {
     auto scaleX = mSize.width / mViewBox.width;
     auto scaleY = mSize.height / mViewBox.height;
     mTvgRoot->scale(scaleX < scaleY ? scaleX : scaleY);
   }
+
   mTvgCanvas->update(mTvgRoot);
 
   if(mTvgCanvas->draw() != tvg::Result::Success)
@@ -173,34 +177,19 @@ Devel::PixelBuffer CanvasRendererUbuntu::GetPixelBuffer()
 bool CanvasRendererUbuntu::AddDrawable(Dali::CanvasRenderer::Drawable& drawable)
 {
 #ifdef THORVG_SUPPORT
-  for(auto& it : mDrawables)
-  {
-    if(it.GetHandle() == drawable)
-    {
-      DALI_LOG_ERROR("Already added [%p]\n", this);
-      return false;
-    }
-  }
-
   Internal::Adaptor::Drawable& drawableImpl = GetImplementation(drawable);
-  tvg::Paint*                  pDrawable    = static_cast<tvg::Paint*>(drawableImpl.GetObject());
-  if(!pDrawable)
+  if(drawableImpl.IsAdded())
   {
-    DALI_LOG_ERROR("Invalid drawable object [%p]\n", this);
+    DALI_LOG_ERROR("Already added [%p][%p]\n", this, &drawable);
     return false;
   }
+
   if(mSize.width < 1.0f || mSize.height < 1.0f)
   {
     DALI_LOG_ERROR("Size is zero [%p]\n", this);
     return false;
   }
 
-  if(mTvgRoot->push(std::unique_ptr<tvg::Paint>(pDrawable)) != tvg::Result::Success)
-  {
-    DALI_LOG_ERROR("Tvg push fail [%p]\n", this);
-    return false;
-  }
-
   drawableImpl.SetAdded(true);
   mDrawables.push_back(drawable);
   mChanged = true;
@@ -252,6 +241,37 @@ void CanvasRendererUbuntu::MakeTargetBuffer(const Vector2& size)
 #endif
 }
 
+#ifdef THORVG_SUPPORT
+void CanvasRendererUbuntu::PushDrawableToGroup(Dali::CanvasRenderer::Drawable& drawable, tvg::Scene* group)
+{
+  Internal::Adaptor::Drawable& drawableImpl        = Dali::GetImplementation(drawable);
+  tvg::Paint*                  tvgDuplicatedObject = static_cast<tvg::Paint*>(drawableImpl.GetObject())->duplicate();
+  if(!tvgDuplicatedObject)
+  {
+    DALI_LOG_ERROR("Invalid drawable object [%p]\n", this);
+    return;
+  }
+  Drawable::Types type = drawableImpl.GetType();
+
+  if(type == Drawable::Types::DRAWABLE_GROUP)
+  {
+    Dali::CanvasRenderer::DrawableGroup& group             = static_cast<Dali::CanvasRenderer::DrawableGroup&>(drawable);
+    Internal::Adaptor::DrawableGroup&    drawableGroupImpl = Dali::GetImplementation(group);
+    DrawableGroup::DrawableVector        drawables         = drawableGroupImpl.GetDrawables();
+    for(auto& it : drawables)
+    {
+      PushDrawableToGroup(it, static_cast<tvg::Scene*>(tvgDuplicatedObject));
+    }
+  }
+
+  if(group->push(std::move(std::unique_ptr<tvg::Paint>(tvgDuplicatedObject))) != tvg::Result::Success)
+  {
+    DALI_LOG_ERROR("Tvg push fail [%p]\n", this);
+    return;
+  }
+}
+#endif
+
 } // namespace Adaptor
 
 } // namespace Internal
index de5188a..2c91ab8 100644 (file)
 #ifdef THORVG_SUPPORT
 #include <thorvg.h>
 #endif
-#include <dali/public-api/object/base-object.h>
 #include <dali/public-api/object/weak-handle.h>
 
 // INTERNAL INCLUDES
 #include <dali/devel-api/adaptor-framework/canvas-renderer-drawable.h>
 #include <dali/devel-api/adaptor-framework/canvas-renderer.h>
 #include <dali/devel-api/adaptor-framework/pixel-buffer.h>
+#include <dali/internal/canvas-renderer/common/drawable-group-impl.h>
 #include <dali/internal/canvas-renderer/common/canvas-renderer-impl.h>
 
 namespace Dali
@@ -104,6 +104,16 @@ private:
    */
   void MakeTargetBuffer(const Vector2& size);
 
+#ifdef THORVG_SUPPORT
+  /**
+   * @brief Push drawable object to parent.
+   * If drawable is a type that can have child drawables, it is called recursively.
+   * @param[in] drawable The drawable object.
+   * @param[in] group The scene object of tvg that can be drawable group.
+   */
+  void PushDrawableToGroup(Dali::CanvasRenderer::Drawable& drawable, tvg::Scene* group);
+#endif
+
 private:
   Devel::PixelBuffer mPixelBuffer;
 
@@ -111,9 +121,7 @@ private:
   std::unique_ptr<tvg::SwCanvas> mTvgCanvas;
   tvg::Scene*                    mTvgRoot;
 #endif
-  using DrawableVector         = std::vector<WeakHandle<Dali::CanvasRenderer::Drawable>>;
-  using DrawableVectorIterator = DrawableVector::iterator;
-  DrawableVector mDrawables;
+  DrawableGroup::DrawableVector mDrawables;
 
   Vector2 mSize;
   Vector2 mViewBox;
index 2a495c3..5a80ff3 100644 (file)
@@ -71,29 +71,23 @@ void DrawableGroupUbuntu::Initialize()
 
   Drawable::Create();
   Drawable::SetObject(static_cast<void*>(mTvgScene));
+  Drawable::SetType(Drawable::Types::DRAWABLE_GROUP);
 #endif
 }
 
 bool DrawableGroupUbuntu::AddDrawable(Dali::CanvasRenderer::Drawable& drawable)
 {
 #ifdef THORVG_SUPPORT
-  Internal::Adaptor::Drawable& drawableImpl = Dali::GetImplementation(drawable);
-  tvg::Paint*                  pDrawable    = static_cast<tvg::Paint*>(drawableImpl.GetObject());
-  if(!pDrawable)
+  if(!Drawable::GetObject() || !mTvgScene)
   {
-    DALI_LOG_ERROR("Invalid drawable object [%p]\n", this);
+    DALI_LOG_ERROR("DrawableGroup is null\n");
     return false;
   }
 
+  Internal::Adaptor::Drawable& drawableImpl = Dali::GetImplementation(drawable);
   if(drawableImpl.IsAdded())
   {
-    DALI_LOG_ERROR("Already added somewhere [%p][%p]\n", this, &drawable);
-    return false;
-  }
-
-  if(mTvgScene->push(std::unique_ptr<tvg::Paint>(pDrawable)) != tvg::Result::Success)
-  {
-    DALI_LOG_ERROR("Tvg push fail [%p]\n", this);
+    DALI_LOG_ERROR("Already added [%p][%p]\n", this, &drawable);
     return false;
   }
 
@@ -110,7 +104,7 @@ bool DrawableGroupUbuntu::AddDrawable(Dali::CanvasRenderer::Drawable& drawable)
 bool DrawableGroupUbuntu::Clear()
 {
 #ifdef THORVG_SUPPORT
-  if(!mTvgScene)
+  if(!Drawable::GetObject() || !mTvgScene)
   {
     DALI_LOG_ERROR("DrawableGroup is null\n");
     return false;
@@ -118,12 +112,7 @@ bool DrawableGroupUbuntu::Clear()
 
   for(auto& it : mDrawables)
   {
-    Dali::CanvasRenderer::Drawable drawable = it.GetHandle();
-    if(DALI_UNLIKELY(!drawable))
-    {
-      continue;
-    }
-    Internal::Adaptor::Drawable& drawableImpl = Dali::GetImplementation(drawable);
+    Internal::Adaptor::Drawable& drawableImpl = Dali::GetImplementation(it);
     drawableImpl.SetAdded(false);
   }
 
@@ -143,6 +132,11 @@ bool DrawableGroupUbuntu::Clear()
 #endif
 }
 
+DrawableGroup::DrawableVector DrawableGroupUbuntu::GetDrawables() const
+{
+  return mDrawables;
+}
+
 } // namespace Adaptor
 
 } // namespace Internal
index 4b01b41..31439c7 100644 (file)
@@ -48,7 +48,7 @@ public:
   static DrawableGroupUbuntu* New();
 
   /**
-   * @copydoc Dali::CanvasRenderer::DrawableGroup::AddDrawable()
+   * @copydoc Dali::CanvasRenderer::DrawableGroup::AddDrawable
    */
   bool AddDrawable(Dali::CanvasRenderer::Drawable& drawable) override;
 
@@ -57,6 +57,11 @@ public:
    */
   bool Clear() override;
 
+  /**
+   * @copydoc Dali::CanvasRenderer::DrawableGroup::GetDrawables
+   */
+  DrawableVector GetDrawables() const override;
+
 private:
   DrawableGroupUbuntu(const DrawableGroupUbuntu&) = delete;
   DrawableGroupUbuntu& operator=(DrawableGroupUbuntu&) = delete;
@@ -83,8 +88,6 @@ private:
 #ifdef THORVG_SUPPORT
   tvg::Scene* mTvgScene;
 #endif
-  using DrawableVector         = std::vector<WeakHandle<Dali::CanvasRenderer::Drawable>>;
-  using DrawableVectorIterator = DrawableVector::iterator;
   DrawableVector mDrawables;
 };
 
index e0ab529..36a84aa 100644 (file)
@@ -48,7 +48,8 @@ DrawableUbuntu* DrawableUbuntu::New()
 
 DrawableUbuntu::DrawableUbuntu()
 : mAdded(false),
-  mChanged(false)
+  mChanged(false),
+  mType(Drawable::Types::NONE)
 #ifdef THORVG_SUPPORT
   ,
   mTvgPaint(nullptr)
@@ -59,7 +60,7 @@ DrawableUbuntu::DrawableUbuntu()
 DrawableUbuntu::~DrawableUbuntu()
 {
 #ifdef THORVG_SUPPORT
-  if(mTvgPaint && !mAdded)
+  if(mTvgPaint)
   {
     delete mTvgPaint;
   }
@@ -235,17 +236,6 @@ void DrawableUbuntu::SetObject(const void* object)
   {
     mTvgPaint = static_cast<tvg::Paint*>((void*)object);
   }
-  else
-  {
-    if(mAdded)
-    {
-      mTvgPaint = nullptr;
-    }
-    if(mTvgPaint)
-    {
-      delete mTvgPaint;
-    }
-  }
 #endif
 }
 
@@ -259,6 +249,16 @@ bool DrawableUbuntu::GetChanged() const
 {
   return mChanged;
 }
+
+void DrawableUbuntu::SetType(Drawable::Types type)
+{
+  mType = type;
+}
+
+Drawable::Types DrawableUbuntu::GetType() const
+{
+  return mType;
+}
 } // namespace Adaptor
 
 } // namespace Internal
index 12bfff0..7c0c22d 100644 (file)
@@ -113,6 +113,16 @@ public:
    */
   bool GetChanged() const override;
 
+  /**
+   * @copydoc Internal::Adaptor::Drawable::SetType
+   */
+  void SetType(Types type);
+
+  /**
+   * @copydoc Internal::Adaptor::Drawable::GetType
+   */
+  Types GetType() const;
+
   DrawableUbuntu(const Drawable&) = delete;
   DrawableUbuntu& operator=(Drawable&) = delete;
   DrawableUbuntu(Drawable&&)           = delete;
@@ -130,8 +140,9 @@ protected:
   virtual ~DrawableUbuntu() override;
 
 private:
-  bool mAdded;
-  bool mChanged;
+  bool            mAdded;
+  bool            mChanged;
+  Drawable::Types mType;
 
 #ifdef THORVG_SUPPORT
   tvg::Paint* mTvgPaint;
index 3605083..3ed67e7 100644 (file)
@@ -68,13 +68,14 @@ void ShapeUbuntu::Initialize()
 
   Drawable::Create();
   Drawable::SetObject(static_cast<void*>(mTvgShape));
+  Drawable::SetType(Drawable::Types::SHAPE);
 #endif
 }
 
 bool ShapeUbuntu::AddRect(Rect<float> rect, Vector2 roundedCorner)
 {
 #ifdef THORVG_SUPPORT
-  if(!mTvgShape)
+  if(!Drawable::GetObject() || !mTvgShape)
   {
     DALI_LOG_ERROR("Shape is null [%p]\n", this);
     return false;
@@ -94,7 +95,7 @@ bool ShapeUbuntu::AddRect(Rect<float> rect, Vector2 roundedCorner)
 bool ShapeUbuntu::AddCircle(Vector2 center, Vector2 radius)
 {
 #ifdef THORVG_SUPPORT
-  if(!mTvgShape)
+  if(!Drawable::GetObject() || !mTvgShape)
   {
     DALI_LOG_ERROR("Shape is null [%p]\n", this);
     return false;
@@ -114,7 +115,7 @@ bool ShapeUbuntu::AddCircle(Vector2 center, Vector2 radius)
 bool ShapeUbuntu::AddArc(Vector2 center, float radius, float startAngle, float sweep, bool pie)
 {
 #ifdef THORVG_SUPPORT
-  if(!mTvgShape)
+  if(!Drawable::GetObject() || !mTvgShape)
   {
     DALI_LOG_ERROR("Shape is null\n");
     return false;
@@ -135,7 +136,7 @@ bool ShapeUbuntu::AddArc(Vector2 center, float radius, float startAngle, float s
 bool ShapeUbuntu::AddMoveTo(Vector2 point)
 {
 #ifdef THORVG_SUPPORT
-  if(!mTvgShape)
+  if(!Drawable::GetObject() || !mTvgShape)
   {
     DALI_LOG_ERROR("Shape is null\n");
     return false;
@@ -156,7 +157,7 @@ bool ShapeUbuntu::AddMoveTo(Vector2 point)
 bool ShapeUbuntu::AddLineTo(Vector2 line)
 {
 #ifdef THORVG_SUPPORT
-  if(!mTvgShape)
+  if(!Drawable::GetObject() || !mTvgShape)
   {
     DALI_LOG_ERROR("Shape is null\n");
     return false;
@@ -177,7 +178,7 @@ bool ShapeUbuntu::AddLineTo(Vector2 line)
 bool ShapeUbuntu::AddCubicTo(Vector2 controlPoint1, Vector2 controlPoint2, Vector2 endPoint)
 {
 #ifdef THORVG_SUPPORT
-  if(!mTvgShape)
+  if(!Drawable::GetObject() || !mTvgShape)
   {
     DALI_LOG_ERROR("Shape is null\n");
     return false;
@@ -198,7 +199,7 @@ bool ShapeUbuntu::AddCubicTo(Vector2 controlPoint1, Vector2 controlPoint2, Vecto
 bool ShapeUbuntu::Close()
 {
 #ifdef THORVG_SUPPORT
-  if(!mTvgShape)
+  if(!Drawable::GetObject() || !mTvgShape)
   {
     DALI_LOG_ERROR("Shape is null\n");
     return false;
@@ -219,7 +220,7 @@ bool ShapeUbuntu::Close()
 bool ShapeUbuntu::ResetPath()
 {
 #ifdef THORVG_SUPPORT
-  if(!mTvgShape)
+  if(!Drawable::GetObject() || !mTvgShape)
   {
     DALI_LOG_ERROR("Shape is null\n");
     return false;
@@ -240,7 +241,7 @@ bool ShapeUbuntu::ResetPath()
 bool ShapeUbuntu::SetFillColor(Vector4 color)
 {
 #ifdef THORVG_SUPPORT
-  if(!mTvgShape)
+  if(!Drawable::GetObject() || !mTvgShape)
   {
     DALI_LOG_ERROR("Shape is null [%p]\n", this);
     return false;
@@ -261,7 +262,7 @@ bool ShapeUbuntu::SetFillColor(Vector4 color)
 Vector4 ShapeUbuntu::GetFillColor() const
 {
 #ifdef THORVG_SUPPORT
-  if(!mTvgShape)
+  if(!Drawable::GetObject() || !mTvgShape)
   {
     DALI_LOG_ERROR("Shape is null [%p]\n", this);
     return Vector4(0, 0, 0, 0);
@@ -282,7 +283,7 @@ Vector4 ShapeUbuntu::GetFillColor() const
 bool ShapeUbuntu::SetFillRule(Dali::CanvasRenderer::Shape::FillRule rule)
 {
 #ifdef THORVG_SUPPORT
-  if(!mTvgShape)
+  if(!Drawable::GetObject() || !mTvgShape)
   {
     DALI_LOG_ERROR("Shape is null\n");
     return false;
@@ -302,7 +303,7 @@ bool ShapeUbuntu::SetFillRule(Dali::CanvasRenderer::Shape::FillRule rule)
 Dali::CanvasRenderer::Shape::FillRule ShapeUbuntu::GetFillRule() const
 {
 #ifdef THORVG_SUPPORT
-  if(!mTvgShape)
+  if(!Drawable::GetObject() || !mTvgShape)
   {
     DALI_LOG_ERROR("Shape is null\n");
     return Dali::CanvasRenderer::Shape::FillRule::WINDING;
@@ -318,7 +319,7 @@ Dali::CanvasRenderer::Shape::FillRule ShapeUbuntu::GetFillRule() const
 bool ShapeUbuntu::SetStrokeWidth(float width)
 {
 #ifdef THORVG_SUPPORT
-  if(!mTvgShape)
+  if(!Drawable::GetObject() || !mTvgShape)
   {
     DALI_LOG_ERROR("Shape is null\n");
     return false;
@@ -339,7 +340,7 @@ bool ShapeUbuntu::SetStrokeWidth(float width)
 float ShapeUbuntu::GetStrokeWidth() const
 {
 #ifdef THORVG_SUPPORT
-  if(!mTvgShape)
+  if(!Drawable::GetObject() || !mTvgShape)
   {
     DALI_LOG_ERROR("Shape is null\n");
     return false;
@@ -353,7 +354,7 @@ float ShapeUbuntu::GetStrokeWidth() const
 bool ShapeUbuntu::SetStrokeColor(Vector4 color)
 {
 #ifdef THORVG_SUPPORT
-  if(!mTvgShape)
+  if(!Drawable::GetObject() || !mTvgShape)
   {
     DALI_LOG_ERROR("Shape is null\n");
     return false;
@@ -374,7 +375,7 @@ bool ShapeUbuntu::SetStrokeColor(Vector4 color)
 Vector4 ShapeUbuntu::GetStrokeColor() const
 {
 #ifdef THORVG_SUPPORT
-  if(!mTvgShape)
+  if(!Drawable::GetObject() || !mTvgShape)
   {
     DALI_LOG_ERROR("Shape is null\n");
     return Vector4(0, 0, 0, 0);
@@ -396,7 +397,7 @@ Vector4 ShapeUbuntu::GetStrokeColor() const
 bool ShapeUbuntu::SetStrokeDash(const Dali::Vector<float> dashPattern)
 {
 #ifdef THORVG_SUPPORT
-  if(!mTvgShape)
+  if(!Drawable::GetObject() || !mTvgShape)
   {
     DALI_LOG_ERROR("Shape is null\n");
     return false;
@@ -424,7 +425,7 @@ bool ShapeUbuntu::SetStrokeDash(const Dali::Vector<float> dashPattern)
 Dali::Vector<float> ShapeUbuntu::GetStrokeDash() const
 {
 #ifdef THORVG_SUPPORT
-  if(!mTvgShape)
+  if(!Drawable::GetObject() || !mTvgShape)
   {
     DALI_LOG_ERROR("Shape is null\n");
     return Vector<float>();
@@ -456,7 +457,7 @@ Dali::Vector<float> ShapeUbuntu::GetStrokeDash() const
 bool ShapeUbuntu::SetStrokeCap(Dali::CanvasRenderer::Shape::StrokeCap cap)
 {
 #ifdef THORVG_SUPPORT
-  if(!mTvgShape)
+  if(!Drawable::GetObject() || !mTvgShape)
   {
     DALI_LOG_ERROR("Shape is null\n");
     return false;
@@ -476,7 +477,7 @@ bool ShapeUbuntu::SetStrokeCap(Dali::CanvasRenderer::Shape::StrokeCap cap)
 Dali::CanvasRenderer::Shape::StrokeCap ShapeUbuntu::GetStrokeCap() const
 {
 #ifdef THORVG_SUPPORT
-  if(!mTvgShape)
+  if(!Drawable::GetObject() || !mTvgShape)
   {
     DALI_LOG_ERROR("Shape is null\n");
     return Dali::CanvasRenderer::Shape::StrokeCap::SQUARE;
@@ -492,7 +493,7 @@ Dali::CanvasRenderer::Shape::StrokeCap ShapeUbuntu::GetStrokeCap() const
 bool ShapeUbuntu::SetStrokeJoin(Dali::CanvasRenderer::Shape::StrokeJoin join)
 {
 #ifdef THORVG_SUPPORT
-  if(!mTvgShape)
+  if(!Drawable::GetObject() || !mTvgShape)
   {
     DALI_LOG_ERROR("Shape is null\n");
     return false;
@@ -513,7 +514,7 @@ bool ShapeUbuntu::SetStrokeJoin(Dali::CanvasRenderer::Shape::StrokeJoin join)
 Dali::CanvasRenderer::Shape::StrokeJoin ShapeUbuntu::GetStrokeJoin() const
 {
 #ifdef THORVG_SUPPORT
-  if(!mTvgShape)
+  if(!Drawable::GetObject() || !mTvgShape)
   {
     DALI_LOG_ERROR("Shape is null\n");
     return Dali::CanvasRenderer::Shape::StrokeJoin::BEVEL;