CanvasRenderer: Add Drawable::SetClipPath() Api 25/260325/11
authorJunsuChoi <jsuya.choi@samsung.com>
Wed, 23 Jun 2021 08:04:23 +0000 (17:04 +0900)
committerJunsuChoi <jsuya.choi@samsung.com>
Wed, 21 Jul 2021 05:53:25 +0000 (14:53 +0900)
Clipping source drawable based on Path data.

Change-Id: Idd0a20d4d5e0a2243bc1b7781b06f02296fc508d

12 files changed:
dali/devel-api/adaptor-framework/canvas-renderer-drawable.cpp
dali/devel-api/adaptor-framework/canvas-renderer-drawable.h
dali/internal/canvas-renderer/common/drawable-impl.cpp
dali/internal/canvas-renderer/common/drawable-impl.h
dali/internal/canvas-renderer/generic/drawable-impl-generic.cpp
dali/internal/canvas-renderer/generic/drawable-impl-generic.h
dali/internal/canvas-renderer/tizen/canvas-renderer-impl-tizen.cpp
dali/internal/canvas-renderer/tizen/drawable-impl-tizen.cpp
dali/internal/canvas-renderer/tizen/drawable-impl-tizen.h
dali/internal/canvas-renderer/ubuntu/canvas-renderer-impl-ubuntu.cpp
dali/internal/canvas-renderer/ubuntu/drawable-impl-ubuntu.cpp
dali/internal/canvas-renderer/ubuntu/drawable-impl-ubuntu.h

index 1529b42..d29c004 100644 (file)
@@ -74,6 +74,11 @@ Rect<float> CanvasRenderer::Drawable::GetBoundingBox() const
   return GetImplementation(*this).GetBoundingBox();
 }
 
+bool CanvasRenderer::Drawable::SetClipPath(Drawable& clip)
+{
+  return GetImplementation(*this).SetClipPath(clip);
+}
+
 CanvasRenderer::Drawable CanvasRenderer::Drawable::DownCast(BaseHandle handle)
 {
   return CanvasRenderer::Drawable(dynamic_cast<Internal::Adaptor::Drawable*>(handle.GetObjectPtr()));
index d9f0dd3..6251375 100644 (file)
@@ -115,6 +115,13 @@ public:
   Rect<float> GetBoundingBox() const;
 
   /**
+   * @brief The intersection with clip drawable is determined and only the resulting pixels from own drawable are rendered.
+   * @param[in] clip The clip drawable object.
+   * @return Returns True when it's successful. False otherwise.
+   */
+  bool SetClipPath(Drawable& clip);
+
+  /**
    * @brief Downcast a handle to Drawable handle.
    *
    * If handle points to an InputMethodContext the downcast produces valid
index 3856e06..d8d5a57 100644 (file)
@@ -106,6 +106,33 @@ Rect<float> Drawable::GetBoundingBox() const
   return mImpl->GetBoundingBox();
 }
 
+bool Drawable::SetClipPath(Dali::CanvasRenderer::Drawable& clip)
+{
+  if(!mImpl)
+  {
+    return false;
+  }
+  return mImpl->SetClipPath(clip);
+}
+
+Dali::CanvasRenderer::Drawable Drawable::GetCompositionDrawable() const
+{
+  if(!mImpl)
+  {
+    return Dali::CanvasRenderer::Drawable();
+  }
+  return mImpl->GetCompositionDrawable();
+}
+
+Dali::Internal::Adaptor::Drawable::CompositionType Drawable::GetCompositionType() const
+{
+  if(!mImpl)
+  {
+    return Dali::Internal::Adaptor::Drawable::CompositionType::NONE;
+  }
+  return mImpl->GetCompositionType();
+}
+
 void Drawable::SetAdded(bool added)
 {
   if(!mImpl)
index d4439ed..d9fd55e 100644 (file)
@@ -47,6 +47,17 @@ public:
     DRAWABLE_GROUP ///< Meaning of DrawableGorup class that inherits Drawable.
   };
 
+  /**
+   * @brief Enumeration indicating type used in the composition of two objects - the target and the source.
+   */
+  enum class CompositionType
+  {
+    NONE = 0,          ///< Means that type is not defined.
+    CLIP_PATH,         ///< The intersection of the source and the target is determined and only the resulting pixels from the source are rendered.
+    ALPHA_MASK,        ///< The pixels of the source and the target are alpha blended. As a result, only the part of the source, which intersects with the target is visible.
+    ALPHA_MASK_INVERSE ///< The pixels of the source and the complement to the target's pixels are alpha blended. As a result, only the part of the source which is not covered by the target is visible.
+  };
+
 public:
   /**
    * @brief Constructor
@@ -99,6 +110,23 @@ public:
   virtual Rect<float> GetBoundingBox() const;
 
   /**
+   * @copydoc Dali::CanvasRenderer::Drawable::SetClipPath()
+   */
+  virtual bool SetClipPath(Dali::CanvasRenderer::Drawable& clip);
+
+  /**
+   * @brief Returns a composition drawble object.
+   * @return Returns a composition drawble object.
+   */
+  virtual Dali::CanvasRenderer::Drawable GetCompositionDrawable() const;
+
+  /**
+   * @brief Returns a composition type
+   * @return Returns a composition type
+   */
+  virtual CompositionType GetCompositionType() const;
+
+  /**
    * @brief Set whether this drawable object was added to other object(CanvasRenderer or DrawableGroup) or not.
    * @param[in] added Ture if added, false otherwise.
    */
index bbd4bab..d162f59 100644 (file)
@@ -88,6 +88,21 @@ Rect<float> DrawableGeneric::GetBoundingBox() const
   return Rect<float>(0, 0, 0, 0);
 }
 
+bool DrawableGeneric::SetClipPath(Dali::CanvasRenderer::Drawable& clip)
+{
+  return false;
+}
+
+Dali::CanvasRenderer::Drawable DrawableGeneric::GetCompositionDrawable() const
+{
+  return Dali::CanvasRenderer::Drawable();
+}
+
+Drawable::CompositionType DrawableGeneric::GetCompositionType() const
+{
+  return Drawable::CompositionType::NONE;
+}
+
 void DrawableGeneric::SetAdded(bool added)
 {
 }
index 41558a0..2b299dd 100644 (file)
@@ -80,6 +80,21 @@ public:
   Rect<float> GetBoundingBox() const override;
 
   /**
+   * @copydoc Dali::CanvasRenderer::Drawable::SetClipPath()
+   */
+  bool SetClipPath(Dali::CanvasRenderer::Drawable& clip) override;
+
+  /**
+   * @copydoc Internal::Adaptor::Drawable::GetCompositionDrawable()
+   */
+  Dali::CanvasRenderer::Drawable GetCompositionDrawable() const override;
+
+  /**
+   * @copydoc Internal::Adaptor::Drawable::GetCompositionType()
+   */
+  CompositionType GetCompositionType() const override;
+
+  /**
    * @copydoc Internal::Adaptor::Drawable::SetAdded()
    */
   void SetAdded(bool added) override;
index f86723d..422ef2d 100644 (file)
@@ -264,6 +264,35 @@ void CanvasRendererTizen::PushDrawableToGroup(Dali::CanvasRenderer::Drawable& dr
     }
   }
 
+  Dali::CanvasRenderer::Drawable compositeDrawable = drawableImpl.GetCompositionDrawable();
+  if(DALI_UNLIKELY(compositeDrawable))
+  {
+    Internal::Adaptor::Drawable& compositeDrawableImpl = Dali::GetImplementation(compositeDrawable);
+    tvg::Paint*                  tvgCompositeObject    = static_cast<tvg::Paint*>(compositeDrawableImpl.GetObject());
+    if(tvgCompositeObject)
+    {
+      tvg::Paint*     tvgDuplicatedCompositeObject = tvgCompositeObject->duplicate();
+      Drawable::Types type                         = compositeDrawableImpl.GetType();
+
+      if(type == Drawable::Types::DRAWABLE_GROUP)
+      {
+        Dali::CanvasRenderer::DrawableGroup& compositeGroup             = static_cast<Dali::CanvasRenderer::DrawableGroup&>(compositeDrawable);
+        Internal::Adaptor::DrawableGroup&    compositeDrawableGroupImpl = Dali::GetImplementation(compositeGroup);
+        DrawableGroup::DrawableVector        compositeDrawables         = compositeDrawableGroupImpl.GetDrawables();
+        for(auto& it : compositeDrawables)
+        {
+          PushDrawableToGroup(it, static_cast<tvg::Scene*>(tvgDuplicatedCompositeObject));
+        }
+      }
+
+      if(tvgDuplicatedObject->composite(std::move(std::unique_ptr<tvg::Paint>(tvgDuplicatedCompositeObject)), static_cast<tvg::CompositeMethod>(drawableImpl.GetCompositionType())) != tvg::Result::Success)
+      {
+        DALI_LOG_ERROR("Tvg composite fail [%p]\n", this);
+        return;
+      }
+    }
+  }
+
   if(parent->push(std::move(std::unique_ptr<tvg::Paint>(tvgDuplicatedObject))) != tvg::Result::Success)
   {
     DALI_LOG_ERROR("Tvg push fail [%p]\n", this);
index b8baa3c..9333c75 100644 (file)
@@ -49,7 +49,9 @@ DrawableTizen* DrawableTizen::New()
 DrawableTizen::DrawableTizen()
 : mAdded(false),
   mChanged(false),
-  mType(Drawable::Types::NONE)
+  mType(Drawable::Types::NONE),
+  mCompositionType(Drawable::CompositionType::NONE),
+  mCompositionDrawable()
 #ifdef THORVG_SUPPORT
   ,
   mTvgPaint(nullptr)
@@ -210,6 +212,43 @@ Rect<float> DrawableTizen::GetBoundingBox() const
 #endif
 }
 
+bool DrawableTizen::SetClipPath(Dali::CanvasRenderer::Drawable& clip)
+{
+#ifdef THORVG_SUPPORT
+  if(!mTvgPaint)
+  {
+    DALI_LOG_ERROR("Drawable is null\n");
+    return false;
+  }
+
+  Internal::Adaptor::Drawable& drawableImpl = Dali::GetImplementation(clip);
+  if(drawableImpl.IsAdded())
+  {
+    DALI_LOG_ERROR("Already used [%p][%p]\n", this, &clip);
+    return false;
+  }
+
+  drawableImpl.SetAdded(true);
+  mCompositionDrawable = clip;
+  mCompositionType     = Drawable::CompositionType::CLIP_PATH;
+  Drawable::SetChanged(true);
+
+  return true;
+#else
+  return false;
+#endif
+}
+
+Dali::CanvasRenderer::Drawable DrawableTizen::GetCompositionDrawable() const
+{
+  return mCompositionDrawable;
+}
+
+Drawable::CompositionType DrawableTizen::GetCompositionType() const
+{
+  return mCompositionType;
+}
+
 void DrawableTizen::SetAdded(bool added)
 {
   mAdded = !!added;
index 8229250..f1cd7a7 100644 (file)
@@ -82,6 +82,20 @@ public:
    * @copydoc Dali::CanvasRenderer::Drawable::GetBoundingBox()
    */
   Rect<float> GetBoundingBox() const override;
+  /**
+   * @copydoc Dali::CanvasRenderer::Drawable::SetClipPath()
+   */
+  bool SetClipPath(Dali::CanvasRenderer::Drawable& clip) override;
+
+  /**
+   * @copydoc Internal::Adaptor::Drawable::GetCompositionDrawable()
+   */
+  Dali::CanvasRenderer::Drawable GetCompositionDrawable() const override;
+
+  /**
+   * @copydoc Internal::Adaptor::Drawable::GetCompositionType()
+   */
+  CompositionType GetCompositionType() const override;
 
   /**
    * @copydoc Internal::Adaptor::Drawable::SetAdded()
@@ -140,9 +154,11 @@ protected:
   virtual ~DrawableTizen() override;
 
 private:
-  bool            mAdded;
-  bool            mChanged;
-  Drawable::Types mType;
+  bool                           mAdded;
+  bool                           mChanged;
+  Drawable::Types                mType;
+  Drawable::CompositionType      mCompositionType;
+  Dali::CanvasRenderer::Drawable mCompositionDrawable;
 
 #ifdef THORVG_SUPPORT
   tvg::Paint* mTvgPaint;
index 8efe447..f1d553d 100644 (file)
@@ -264,6 +264,35 @@ void CanvasRendererUbuntu::PushDrawableToGroup(Dali::CanvasRenderer::Drawable& d
     }
   }
 
+  Dali::CanvasRenderer::Drawable compositeDrawable = drawableImpl.GetCompositionDrawable();
+  if(DALI_UNLIKELY(compositeDrawable))
+  {
+    Internal::Adaptor::Drawable& compositeDrawableImpl = Dali::GetImplementation(compositeDrawable);
+    tvg::Paint*                  tvgCompositeObject    = static_cast<tvg::Paint*>(compositeDrawableImpl.GetObject());
+    if(tvgCompositeObject)
+    {
+      tvg::Paint*     tvgDuplicatedCompositeObject = tvgCompositeObject->duplicate();
+      Drawable::Types type                         = compositeDrawableImpl.GetType();
+
+      if(type == Drawable::Types::DRAWABLE_GROUP)
+      {
+        Dali::CanvasRenderer::DrawableGroup& compositeGroup             = static_cast<Dali::CanvasRenderer::DrawableGroup&>(compositeDrawable);
+        Internal::Adaptor::DrawableGroup&    compositeDrawableGroupImpl = Dali::GetImplementation(compositeGroup);
+        DrawableGroup::DrawableVector        compositeDrawables         = compositeDrawableGroupImpl.GetDrawables();
+        for(auto& it : compositeDrawables)
+        {
+          PushDrawableToGroup(it, static_cast<tvg::Scene*>(tvgDuplicatedCompositeObject));
+        }
+      }
+
+      if(tvgDuplicatedObject->composite(std::move(std::unique_ptr<tvg::Paint>(tvgDuplicatedCompositeObject)), static_cast<tvg::CompositeMethod>(drawableImpl.GetCompositionType())) != tvg::Result::Success)
+      {
+        DALI_LOG_ERROR("Tvg composite fail [%p]\n", this);
+        return;
+      }
+    }
+  }
+
   if(group->push(std::move(std::unique_ptr<tvg::Paint>(tvgDuplicatedObject))) != tvg::Result::Success)
   {
     DALI_LOG_ERROR("Tvg push fail [%p]\n", this);
index 36a84aa..f4cb431 100644 (file)
@@ -49,7 +49,9 @@ DrawableUbuntu* DrawableUbuntu::New()
 DrawableUbuntu::DrawableUbuntu()
 : mAdded(false),
   mChanged(false),
-  mType(Drawable::Types::NONE)
+  mType(Drawable::Types::NONE),
+  mCompositionType(Drawable::CompositionType::NONE),
+  mCompositionDrawable()
 #ifdef THORVG_SUPPORT
   ,
   mTvgPaint(nullptr)
@@ -210,6 +212,43 @@ Rect<float> DrawableUbuntu::GetBoundingBox() const
 #endif
 }
 
+bool DrawableUbuntu::SetClipPath(Dali::CanvasRenderer::Drawable& clip)
+{
+#ifdef THORVG_SUPPORT
+  if(!mTvgPaint)
+  {
+    DALI_LOG_ERROR("Drawable is null\n");
+    return false;
+  }
+
+  Internal::Adaptor::Drawable& drawableImpl = Dali::GetImplementation(clip);
+  if(drawableImpl.IsAdded())
+  {
+    DALI_LOG_ERROR("Already used [%p][%p]\n", this, &clip);
+    return false;
+  }
+
+  drawableImpl.SetAdded(true);
+  mCompositionDrawable = clip;
+  mCompositionType     = Drawable::CompositionType::CLIP_PATH;
+  Drawable::SetChanged(true);
+
+  return true;
+#else
+  return false;
+#endif
+}
+
+Dali::CanvasRenderer::Drawable DrawableUbuntu::GetCompositionDrawable() const
+{
+  return mCompositionDrawable;
+}
+
+Drawable::CompositionType DrawableUbuntu::GetCompositionType() const
+{
+  return mCompositionType;
+}
+
 void DrawableUbuntu::SetAdded(bool added)
 {
   mAdded = !!added;
index c91a5d6..45bdc3d 100644 (file)
@@ -84,6 +84,21 @@ public:
   Rect<float> GetBoundingBox() const override;
 
   /**
+   * @copydoc Dali::CanvasRenderer::Drawable::SetClipPath()
+   */
+  bool SetClipPath(Dali::CanvasRenderer::Drawable& clip) override;
+
+  /**
+   * @copydoc Internal::Adaptor::Drawable::GetCompositionDrawable()
+   */
+  Dali::CanvasRenderer::Drawable GetCompositionDrawable() const override;
+
+  /**
+   * @copydoc Internal::Adaptor::Drawable::GetCompositionType()
+   */
+  CompositionType GetCompositionType() const override;
+
+  /**
    * @copydoc Internal::Adaptor::Drawable::SetAdded()
    */
   void SetAdded(bool added) override;
@@ -140,9 +155,11 @@ protected:
   virtual ~DrawableUbuntu() override;
 
 private:
-  bool            mAdded;
-  bool            mChanged;
-  Drawable::Types mType;
+  bool                           mAdded;
+  bool                           mChanged;
+  Drawable::Types                mType;
+  Drawable::CompositionType      mCompositionType;
+  Dali::CanvasRenderer::Drawable mCompositionDrawable;
 
 #ifdef THORVG_SUPPORT
   tvg::Paint* mTvgPaint;