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
return false;
}
+DrawableGroup::DrawableVector DrawableGroup::GetDrawables() const
+{
+ return DrawableVector();
+}
+
} // namespace Adaptor
} // namespace Internal
{
public:
/**
+ * @brief List of drawables.
+ */
+ using DrawableVector = std::vector<Dali::CanvasRenderer::Drawable>;
+
+ /**
* @brief Constructor
*/
DrawableGroup();
~DrawableGroup() override;
/**
- * @copydoc Dali::CanvasRenderer::DrawableGroup::AddDrawable()
+ * @copydoc Dali::CanvasRenderer::DrawableGroup::AddDrawable
*/
virtual bool AddDrawable(Dali::CanvasRenderer::Drawable& drawable);
*/
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;
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
{
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();
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.
*/
Drawable& operator=(Drawable&&) = delete;
private:
- Dali::Internal::Adaptor::Drawable* pImpl = nullptr;
+ Dali::Internal::Adaptor::Drawable* mImpl = nullptr;
};
} // namespace Adaptor
// 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>
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
}
MakeTargetBuffer(mSize);
-
- auto scene = tvg::Scene::gen();
- mTvgRoot = scene.get();
- mTvgCanvas->push(move(scene));
#endif
}
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;
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)
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;
#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
#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
*/
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;
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;
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;
}
bool DrawableGroupTizen::Clear()
{
#ifdef THORVG_SUPPORT
- if(!mTvgScene)
+ if(!Drawable::GetObject() || !mTvgScene)
{
DALI_LOG_ERROR("DrawableGroup is null\n");
return false;
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);
}
#endif
}
+DrawableGroup::DrawableVector DrawableGroupTizen::GetDrawables() const
+{
+ return mDrawables;
+}
+
} // namespace Adaptor
} // namespace Internal
static DrawableGroupTizen* New();
/**
- * @copydoc Dali::CanvasRenderer::DrawableGroup::AddDrawable()
+ * @copydoc Dali::CanvasRenderer::DrawableGroup::AddDrawable
*/
bool AddDrawable(Dali::CanvasRenderer::Drawable& drawable) override;
*/
bool Clear() override;
+ /**
+ * @copydoc Dali::CanvasRenderer::DrawableGroup::GetDrawables
+ */
+ DrawableVector GetDrawables() const override;
+
private:
DrawableGroupTizen(const DrawableGroupTizen&) = delete;
DrawableGroupTizen& operator=(DrawableGroupTizen&) = delete;
#ifdef THORVG_SUPPORT
tvg::Scene* mTvgScene;
#endif
- using DrawableVector = std::vector<WeakHandle<Dali::CanvasRenderer::Drawable>>;
- using DrawableVectorIterator = DrawableVector::iterator;
DrawableVector mDrawables;
};
DrawableTizen::DrawableTizen()
: mAdded(false),
- mChanged(false)
+ mChanged(false),
+ mType(Drawable::Types::NONE)
#ifdef THORVG_SUPPORT
,
mTvgPaint(nullptr)
DrawableTizen::~DrawableTizen()
{
#ifdef THORVG_SUPPORT
- if(mTvgPaint && !mAdded)
+ if(mTvgPaint)
{
delete mTvgPaint;
}
{
mTvgPaint = static_cast<tvg::Paint*>((void*)object);
}
- else
- {
- if(mAdded)
- {
- mTvgPaint = nullptr;
- }
- if(mTvgPaint)
- {
- delete mTvgPaint;
- }
- }
#endif
}
{
return mChanged;
}
+
+void DrawableTizen::SetType(Drawable::Types type)
+{
+ mType = type;
+}
+
+Drawable::Types DrawableTizen::GetType() const
+{
+ return mType;
+}
} // namespace Adaptor
} // namespace Internal
*/
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;
virtual ~DrawableTizen() override;
private:
- bool mAdded;
- bool mChanged;
+ bool mAdded;
+ bool mChanged;
+ Drawable::Types mType;
#ifdef THORVG_SUPPORT
tvg::Paint* mTvgPaint;
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;
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;
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;
bool ShapeTizen::AddMoveTo(Vector2 point)
{
#ifdef THORVG_SUPPORT
- if(!mTvgShape)
+ if(!Drawable::GetObject() || !mTvgShape)
{
DALI_LOG_ERROR("Shape is null\n");
return false;
bool ShapeTizen::AddLineTo(Vector2 line)
{
#ifdef THORVG_SUPPORT
- if(!mTvgShape)
+ if(!Drawable::GetObject() || !mTvgShape)
{
DALI_LOG_ERROR("Shape is null\n");
return false;
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;
bool ShapeTizen::Close()
{
#ifdef THORVG_SUPPORT
- if(!mTvgShape)
+ if(!Drawable::GetObject() || !mTvgShape)
{
DALI_LOG_ERROR("Shape is null\n");
return false;
bool ShapeTizen::ResetPath()
{
#ifdef THORVG_SUPPORT
- if(!mTvgShape)
+ if(!Drawable::GetObject() || !mTvgShape)
{
DALI_LOG_ERROR("Shape is null\n");
return false;
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;
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);
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;
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;
bool ShapeTizen::SetStrokeWidth(float width)
{
#ifdef THORVG_SUPPORT
- if(!mTvgShape)
+ if(!Drawable::GetObject() || !mTvgShape)
{
DALI_LOG_ERROR("Shape is null\n");
return false;
float ShapeTizen::GetStrokeWidth() const
{
#ifdef THORVG_SUPPORT
- if(!mTvgShape)
+ if(!Drawable::GetObject() || !mTvgShape)
{
DALI_LOG_ERROR("Shape is null\n");
return false;
bool ShapeTizen::SetStrokeColor(Vector4 color)
{
#ifdef THORVG_SUPPORT
- if(!mTvgShape)
+ if(!Drawable::GetObject() || !mTvgShape)
{
DALI_LOG_ERROR("Shape is null\n");
return false;
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);
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;
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>();
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");
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;
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;
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;
// 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>
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
}
MakeTargetBuffer(mSize);
-
- auto scene = tvg::Scene::gen();
- mTvgRoot = scene.get();
- mTvgCanvas->push(move(scene));
#endif
}
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;
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)
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;
#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
#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
*/
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;
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;
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;
}
bool DrawableGroupUbuntu::Clear()
{
#ifdef THORVG_SUPPORT
- if(!mTvgScene)
+ if(!Drawable::GetObject() || !mTvgScene)
{
DALI_LOG_ERROR("DrawableGroup is null\n");
return false;
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);
}
#endif
}
+DrawableGroup::DrawableVector DrawableGroupUbuntu::GetDrawables() const
+{
+ return mDrawables;
+}
+
} // namespace Adaptor
} // namespace Internal
static DrawableGroupUbuntu* New();
/**
- * @copydoc Dali::CanvasRenderer::DrawableGroup::AddDrawable()
+ * @copydoc Dali::CanvasRenderer::DrawableGroup::AddDrawable
*/
bool AddDrawable(Dali::CanvasRenderer::Drawable& drawable) override;
*/
bool Clear() override;
+ /**
+ * @copydoc Dali::CanvasRenderer::DrawableGroup::GetDrawables
+ */
+ DrawableVector GetDrawables() const override;
+
private:
DrawableGroupUbuntu(const DrawableGroupUbuntu&) = delete;
DrawableGroupUbuntu& operator=(DrawableGroupUbuntu&) = delete;
#ifdef THORVG_SUPPORT
tvg::Scene* mTvgScene;
#endif
- using DrawableVector = std::vector<WeakHandle<Dali::CanvasRenderer::Drawable>>;
- using DrawableVectorIterator = DrawableVector::iterator;
DrawableVector mDrawables;
};
DrawableUbuntu::DrawableUbuntu()
: mAdded(false),
- mChanged(false)
+ mChanged(false),
+ mType(Drawable::Types::NONE)
#ifdef THORVG_SUPPORT
,
mTvgPaint(nullptr)
DrawableUbuntu::~DrawableUbuntu()
{
#ifdef THORVG_SUPPORT
- if(mTvgPaint && !mAdded)
+ if(mTvgPaint)
{
delete mTvgPaint;
}
{
mTvgPaint = static_cast<tvg::Paint*>((void*)object);
}
- else
- {
- if(mAdded)
- {
- mTvgPaint = nullptr;
- }
- if(mTvgPaint)
- {
- delete mTvgPaint;
- }
- }
#endif
}
{
return mChanged;
}
+
+void DrawableUbuntu::SetType(Drawable::Types type)
+{
+ mType = type;
+}
+
+Drawable::Types DrawableUbuntu::GetType() const
+{
+ return mType;
+}
} // namespace Adaptor
} // namespace Internal
*/
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;
virtual ~DrawableUbuntu() override;
private:
- bool mAdded;
- bool mChanged;
+ bool mAdded;
+ bool mChanged;
+ Drawable::Types mType;
#ifdef THORVG_SUPPORT
tvg::Paint* mTvgPaint;
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;
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;
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;
bool ShapeUbuntu::AddMoveTo(Vector2 point)
{
#ifdef THORVG_SUPPORT
- if(!mTvgShape)
+ if(!Drawable::GetObject() || !mTvgShape)
{
DALI_LOG_ERROR("Shape is null\n");
return false;
bool ShapeUbuntu::AddLineTo(Vector2 line)
{
#ifdef THORVG_SUPPORT
- if(!mTvgShape)
+ if(!Drawable::GetObject() || !mTvgShape)
{
DALI_LOG_ERROR("Shape is null\n");
return false;
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;
bool ShapeUbuntu::Close()
{
#ifdef THORVG_SUPPORT
- if(!mTvgShape)
+ if(!Drawable::GetObject() || !mTvgShape)
{
DALI_LOG_ERROR("Shape is null\n");
return false;
bool ShapeUbuntu::ResetPath()
{
#ifdef THORVG_SUPPORT
- if(!mTvgShape)
+ if(!Drawable::GetObject() || !mTvgShape)
{
DALI_LOG_ERROR("Shape is null\n");
return false;
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;
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);
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;
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;
bool ShapeUbuntu::SetStrokeWidth(float width)
{
#ifdef THORVG_SUPPORT
- if(!mTvgShape)
+ if(!Drawable::GetObject() || !mTvgShape)
{
DALI_LOG_ERROR("Shape is null\n");
return false;
float ShapeUbuntu::GetStrokeWidth() const
{
#ifdef THORVG_SUPPORT
- if(!mTvgShape)
+ if(!Drawable::GetObject() || !mTvgShape)
{
DALI_LOG_ERROR("Shape is null\n");
return false;
bool ShapeUbuntu::SetStrokeColor(Vector4 color)
{
#ifdef THORVG_SUPPORT
- if(!mTvgShape)
+ if(!Drawable::GetObject() || !mTvgShape)
{
DALI_LOG_ERROR("Shape is null\n");
return false;
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);
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;
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>();
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;
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;
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;
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;