From 5237099d2615445b12a92644f6a401d352b5577e Mon Sep 17 00:00:00 2001 From: JunsuChoi Date: Thu, 24 Dec 2020 15:59:30 +0900 Subject: [PATCH] Implements CanvasView control Control for drawing Vector Primitives. CanvasView can draw a shape in its internal buffer by adding a Dali::CanvasRenderer::Shape object and calling Commit(). Dali::CanvasRenderer::Shape is a command list based on Path. Fill and Stroke properties can be set using setters and getters. Dali::CanvasRenderer::Drawable is a parent class of Dali::CanvasRenderer::Shape and it has common class of classes to be added later (Scene, etc.). Note: Currently, the CanvasView's buffer is using PixelData. This buffer strategy will be changed to tbmBuffer in the future. [API List] class CanvasView : public control New AddDrawable Change-Id: I50ade6fb981e72f3e4ccc1ec34cd82de784a7bd4 --- automated-tests/src/dali-toolkit/CMakeLists.txt | 2 + .../toolkit-canvas-renderer.cpp | 162 ++++++++++++++++ .../src/dali-toolkit/utc-Dali-CanvasView.cpp | 204 +++++++++++++++++++++ .../devel-api/controls/canvas-view/canvas-view.cpp | 83 +++++++++ .../devel-api/controls/canvas-view/canvas-view.h | 151 +++++++++++++++ dali-toolkit/devel-api/file.list | 2 + .../controls/canvas-view/canvas-view-impl.cpp | 179 ++++++++++++++++++ .../controls/canvas-view/canvas-view-impl.h | 125 +++++++++++++ dali-toolkit/internal/file.list | 1 + .../internal/graphics/shaders/canvas-view.frag | 8 + .../internal/graphics/shaders/canvas-view.vert | 10 + doc/dali-toolkit-doc.h | 3 + 12 files changed, 930 insertions(+) create mode 100644 automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-canvas-renderer.cpp create mode 100644 automated-tests/src/dali-toolkit/utc-Dali-CanvasView.cpp create mode 100644 dali-toolkit/devel-api/controls/canvas-view/canvas-view.cpp create mode 100644 dali-toolkit/devel-api/controls/canvas-view/canvas-view.h create mode 100644 dali-toolkit/internal/controls/canvas-view/canvas-view-impl.cpp create mode 100644 dali-toolkit/internal/controls/canvas-view/canvas-view-impl.h create mode 100644 dali-toolkit/internal/graphics/shaders/canvas-view.frag create mode 100644 dali-toolkit/internal/graphics/shaders/canvas-view.vert diff --git a/automated-tests/src/dali-toolkit/CMakeLists.txt b/automated-tests/src/dali-toolkit/CMakeLists.txt index ea6c3fc..1b8e5f7 100755 --- a/automated-tests/src/dali-toolkit/CMakeLists.txt +++ b/automated-tests/src/dali-toolkit/CMakeLists.txt @@ -14,6 +14,7 @@ SET(TC_SOURCES utc-Dali-BloomView.cpp utc-Dali-BubbleEmitter.cpp utc-Dali-Builder.cpp + utc-Dali-CanvasView.cpp utc-Dali-CheckBoxButton.cpp utc-Dali-ConfirmationPopup.cpp utc-Dali-CubeTransitionEffect.cpp @@ -77,6 +78,7 @@ SET(TC_SOURCES SET(TEST_HARNESS_SOURCES dali-toolkit-test-utils/toolkit-adaptor.cpp dali-toolkit-test-utils/toolkit-application.cpp + dali-toolkit-test-utils/toolkit-canvas-renderer.cpp dali-toolkit-test-utils/toolkit-clipboard.cpp dali-toolkit-test-utils/toolkit-clipboard-event-notifier.cpp dali-toolkit-test-utils/toolkit-event-thread-callback.cpp diff --git a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-canvas-renderer.cpp b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-canvas-renderer.cpp new file mode 100644 index 0000000..0d6b87e --- /dev/null +++ b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-canvas-renderer.cpp @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2021 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. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Dali +{ + +namespace Internal +{ + +namespace Adaptor +{ + +class CanvasRenderer: public Dali::BaseObject +{ +public: + CanvasRenderer( const Vector2& size ) + : mPixelBuffer( Devel::PixelBuffer::New(size.width, size.height, Dali::Pixel::RGBA8888) ), + mSize(size) + { + } + + ~CanvasRenderer() + { + } + + bool Commit() + { + return true; + } + + bool AddDrawable(Dali::CanvasRenderer::Drawable& drawable) + { + if (!drawable) + { + return false; + } + return true; + } + + Devel::PixelBuffer GetPixelBuffer() + { + return mPixelBuffer; + } + + + bool SetSize(const Vector2& size) + { + mSize = size; + // For negative test + if ( size.width == -999 && size.height == -999 ) + { + return false; + } + return true; + } + + const Vector2& GetSize() + { + mSize = Vector2(200, 200); + return mSize; + } + + +public: + Devel::PixelBuffer mPixelBuffer; + Vector2 mSize; +}; + +inline CanvasRenderer& GetImplementation( Dali::CanvasRenderer& renderer ) +{ + DALI_ASSERT_ALWAYS( renderer && "CanvasRenderer handle is empty." ); + BaseObject& handle = renderer.GetBaseObject(); + return static_cast< Internal::Adaptor::CanvasRenderer& >( handle ); +} + +inline const CanvasRenderer& GetImplementation( const Dali::CanvasRenderer& renderer ) +{ + DALI_ASSERT_ALWAYS( renderer && "CanvasRenderer handle is empty." ); + const BaseObject& handle = renderer.GetBaseObject(); + return static_cast< const Internal::Adaptor::CanvasRenderer& >( handle ); +} + +} // namespace Adaptor + +} // namespace Internal + + +/********************************************************************************/ +/********************************* PUBLIC CLASS *******************************/ +/********************************************************************************/ + +CanvasRenderer CanvasRenderer::New( const Vector2& size ) +{ + Internal::Adaptor::CanvasRenderer* imageRenderer = new Internal::Adaptor::CanvasRenderer(size); + + return CanvasRenderer( imageRenderer ); +} + +CanvasRenderer::CanvasRenderer() +{ +} + +CanvasRenderer::~CanvasRenderer() +{ +} + +CanvasRenderer::CanvasRenderer( Internal::Adaptor::CanvasRenderer* internal ) +: BaseHandle( internal ) +{ +} + +bool CanvasRenderer::Commit() +{ + return Internal::Adaptor::GetImplementation(*this).Commit(); +} + +Devel::PixelBuffer CanvasRenderer::GetPixelBuffer() +{ + return Internal::Adaptor::GetImplementation(*this).GetPixelBuffer(); +} + +bool CanvasRenderer::AddDrawable(Dali::CanvasRenderer::Drawable& drawable) +{ + return Internal::Adaptor::GetImplementation(*this).AddDrawable(drawable); +} + +bool CanvasRenderer::SetSize(const Vector2& size) +{ + return Internal::Adaptor::GetImplementation(*this).SetSize(size); +} + +const Vector2& CanvasRenderer::GetSize() +{ + return Internal::Adaptor::GetImplementation(*this).GetSize(); +} + + +} // namespace Dali diff --git a/automated-tests/src/dali-toolkit/utc-Dali-CanvasView.cpp b/automated-tests/src/dali-toolkit/utc-Dali-CanvasView.cpp new file mode 100644 index 0000000..1c5128e --- /dev/null +++ b/automated-tests/src/dali-toolkit/utc-Dali-CanvasView.cpp @@ -0,0 +1,204 @@ +/* + * Copyright (c) 2021 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. + * + */ + +#include +#include +#include +#include +#include +#include +#include + + +using namespace Dali; +using namespace Toolkit; + +namespace +{ + + +} // namespace + +void utc_dali_toolkit_canvasview_startup(void) +{ + test_return_value = TET_UNDEF; +} + +void utc_dali_toolkit_canvasview_cleanup(void) +{ + test_return_value = TET_PASS; +} + +int UtcDaliCanvasViewConstructorP(void) +{ + ToolkitTestApplication application; + CanvasView canvasView; + + DALI_TEST_CHECK( !canvasView ); + END_TEST; +} + +int UtcDaliCanvasViewMoveAssignment(void) +{ + ToolkitTestApplication application; + CanvasView canvasView = CanvasView::New(Vector2(100, 100)); + + CanvasView moved = std::move( canvasView ); + DALI_TEST_CHECK( moved ); + DALI_TEST_EQUALS( 1, moved.GetBaseObject().ReferenceCount(), TEST_LOCATION ); + DALI_TEST_CHECK( !canvasView ); + + END_TEST; +} + +int UtcDaliCanvasViewAssignmentConstructorP(void) +{ + ToolkitTestApplication application; + CanvasView canvasView = CanvasView::New(Vector2(100, 100)); + + CanvasView copy( canvasView ); + DALI_TEST_CHECK( copy ); + + DALI_TEST_CHECK( canvasView == copy ); + END_TEST; +} + +int UtcDaliCanvasViewAssignmentOperatorP(void) +{ + ToolkitTestApplication application; + const CanvasView canvasView = CanvasView::New(Vector2(100, 100)); + + CanvasView assign; + DALI_TEST_CHECK( !assign ); + + assign = canvasView ; + DALI_TEST_CHECK( assign == canvasView); + END_TEST; +} + +int UtcDaliCanvasViewNewP(void) +{ + ToolkitTestApplication application; + CanvasView canvasView = CanvasView::New(Vector2(100, 100)); + + DALI_TEST_CHECK( canvasView ); + END_TEST; +} + +int UtcDaliCanvasViewDownCastP(void) +{ + ToolkitTestApplication application; + CanvasView canvasView = CanvasView::New(Vector2(100,100)); + + BaseHandle object(canvasView); + + CanvasView canvasView2 = CanvasView::DownCast( object ); + DALI_TEST_CHECK(canvasView2); + + CanvasView canvasView3 = DownCast< CanvasView >(object); + DALI_TEST_CHECK(canvasView3); + END_TEST; +} + +int UtcDaliCanvasViewDownCastN(void) +{ + ToolkitTestApplication application; + BaseHandle unInitializedObject; + + CanvasView canvasView1 = CanvasView::DownCast( unInitializedObject ); + DALI_TEST_CHECK( !canvasView1 ); + + CanvasView canvasView2 = DownCast< CanvasView >( unInitializedObject ); + DALI_TEST_CHECK( !canvasView2 ); + END_TEST; +} + +int UtcDaliCanvasViewAddP(void) +{ + ToolkitTestApplication application; + CanvasView canvasView = CanvasView::New(Vector2(100,100)); + DALI_TEST_CHECK( canvasView ); + + Dali::CanvasRenderer::Shape shape = Dali::CanvasRenderer::Shape::New(); + + shape.AddRect(Rect(10, 10, 10, 10), Vector2(0, 0)); + + canvasView.AddDrawable(shape); + + END_TEST; +} + +int UtcDaliCanvasViewAddN(void) +{ + ToolkitTestApplication application; + CanvasView canvasView = CanvasView::New(Vector2(100,100)); + DALI_TEST_CHECK( canvasView ); + + Dali::CanvasRenderer::Shape shape; + + canvasView.AddDrawable(shape); + + END_TEST; +} + +int UtcDaliCanvasViewChangeSizeP(void) +{ + ToolkitTestApplication application; + + CanvasView canvasView = CanvasView::New(Vector2(100,100)); + DALI_TEST_CHECK( canvasView ); + + application.GetScene().Add(canvasView); + application.SendNotification(); + application.Render(); + + canvasView.SetProperty(Actor::Property::SIZE, Vector2(300, 300)); + + application.SendNotification(); + application.Render(); + + Property::Value pv = canvasView.GetProperty(Actor::Property::SIZE); + Vector3 v3; + pv.Get(v3); + DALI_TEST_EQUALS( v3, Vector3(300, 300, 0), TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliCanvasViewSizeN(void) +{ + ToolkitTestApplication application; + + CanvasView canvasView = CanvasView::New(Vector2(100,100)); + DALI_TEST_CHECK( canvasView ); + + application.GetScene().Add(canvasView); + application.SendNotification(); + application.Render(); + + canvasView.SetProperty(Actor::Property::SIZE, Vector2(-999, -999)); + + application.SendNotification(); + application.Render(); + + Property::Value pv = canvasView.GetProperty(Actor::Property::SIZE); + Vector3 v3; + pv.Get(v3); + DALI_TEST_EQUALS( v3, Vector3(-999, -999, 0), TEST_LOCATION ); + + END_TEST; +} diff --git a/dali-toolkit/devel-api/controls/canvas-view/canvas-view.cpp b/dali-toolkit/devel-api/controls/canvas-view/canvas-view.cpp new file mode 100644 index 0000000..d6ebc63 --- /dev/null +++ b/dali-toolkit/devel-api/controls/canvas-view/canvas-view.cpp @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2021 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 + +// INTERNAL INCLUDES +#include + +namespace Dali +{ +namespace Toolkit +{ +CanvasView::CanvasView() +{ +} + +CanvasView::CanvasView(const CanvasView& canvasView) +: Control(canvasView) +{ +} + +CanvasView::CanvasView(CanvasView&& rhs) = default; + +CanvasView& CanvasView::operator=(const CanvasView& rhs) +{ + if(&rhs != this) + { + Control::operator=(rhs); + } + return *this; +} + +CanvasView& CanvasView::operator=(CanvasView&& rhs) = default; + +CanvasView::~CanvasView() +{ +} + +CanvasView CanvasView::New(const Vector2& viewBox) +{ + CanvasView canvasView = Internal::CanvasView::New(viewBox); + return canvasView; +} + +CanvasView CanvasView::DownCast(BaseHandle handle) +{ + return Control::DownCast(handle); +} + +void CanvasView::AddDrawable(Dali::CanvasRenderer::Drawable& drawable) +{ + Dali::Toolkit::GetImpl(*this).AddDrawable(drawable); +} + +CanvasView::CanvasView(Internal::CanvasView& implementation) +: Control(implementation) +{ +} + +CanvasView::CanvasView(Dali::Internal::CustomActor* internal) +: Control(internal) +{ + VerifyCustomActorPointer(internal); +} + +} // namespace Toolkit + +} // namespace Dali diff --git a/dali-toolkit/devel-api/controls/canvas-view/canvas-view.h b/dali-toolkit/devel-api/controls/canvas-view/canvas-view.h new file mode 100644 index 0000000..9e59722 --- /dev/null +++ b/dali-toolkit/devel-api/controls/canvas-view/canvas-view.h @@ -0,0 +1,151 @@ +#ifndef DALI_TOOLKIT_CANVAS_VIEW_H +#define DALI_TOOLKIT_CANVAS_VIEW_H + +/* + * Copyright (c) 2021 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. + * + */ + +// INTERNAL INCLUDES +#include + +// EXTERNAL INCLUDES +#include +#include + +namespace Dali +{ +namespace Toolkit +{ +namespace Internal DALI_INTERNAL +{ +class CanvasView; +} +/** + * @addtogroup dali_toolkit_controls_canvas_view + * @{ + */ + +/** + * @brief CanvasView is a class for displaying an vector primitives. + * + * @code + * auto myCanvasView = CanvasView::New( viewBox ) ); //The viewBox is the size of viewbox of CanvasView. + * + * //Create shape and set properties. + * auto shape = Dali::CanvasRenderer::Shape::New(); + * shape.AddRect( 0, 0, 10, 10, 0, 0 ); + * shape.SetFillColor( Vector4( 1.0, 1.0, 1.0, 1.0 ) ); + * myCanvasView.AddDrawable( shape ); + * @endcode + * + * + */ +class DALI_TOOLKIT_API CanvasView : public Control +{ +public: + /** + * @brief Creates an uninitialized CanvasView. + */ + CanvasView(); + + /** + * @brief Creates an initialized CanvasView + * + * @param [in] viewBox The width and height. + * @return A handle to a newly allocated CanvasView + */ + static CanvasView New(const Vector2& viewBox); + + /** + * @brief Destructor. + * + * This is non-virtual since derived Handle types must not contain data or virtual methods. + */ + ~CanvasView(); + + /** + * @brief Copy constructor. + * + * @param[in] canvasView CanvasView to copy. The copied CanvasView will point at the same implementation + */ + CanvasView(const CanvasView& canvasView); + + /** + * @brief Move constructor + * + * @param[in] rhs A reference to the moved handle + */ + CanvasView(CanvasView&& rhs); + + /** + * @brief Assignment operator. + * + * @param[in] canvasView The CanvasView to assign from + * @return The updated CanvasView + */ + CanvasView& operator=(const CanvasView& canvasView); + + /** + * @brief Move assignment + * + * @param[in] rhs A reference to the moved handle + * @return A reference to this + */ + CanvasView& operator=(CanvasView&& rhs); + + /** + * @brief Downcasts a handle to CanvasView handle. + * + * If handle points to a CanvasView, the downcast produces valid handle. + * If not, the returned handle is left uninitialized. + * + * @param[in] handle Handle to an object + * @return Handle to a CanvasView or an uninitialized handle + */ + static CanvasView DownCast(BaseHandle handle); + + /** + * @brief Add drawable object to the CanvasView. + * This method is similar to registration. The added shape is drawn on the inner canvas. + */ + void AddDrawable(Dali::CanvasRenderer::Drawable& drawable); + +public: // Not intended for application developers + /// @cond internal + /** + * @brief Creates a handle using the Toolkit::Internal implementation. + * + * @param[in] implementation The CanvasView implementation + */ + DALI_INTERNAL CanvasView(Internal::CanvasView& implementation); + + /** + * @brief Allows the creation of this CanvasView from an Internal::CustomActor pointer. + * + * @param[in] internal A pointer to the internal CustomActor + */ + DALI_INTERNAL CanvasView(Dali::Internal::CustomActor* internal); + /// @endcond +}; + +/** + * @} + */ +} // namespace Toolkit + +} // namespace Dali + +#endif // DALI_TOOLKIT_CANVAS_VIEW_H diff --git a/dali-toolkit/devel-api/file.list b/dali-toolkit/devel-api/file.list index 0e1ec7d..e94ebe7 100755 --- a/dali-toolkit/devel-api/file.list +++ b/dali-toolkit/devel-api/file.list @@ -10,6 +10,7 @@ SET( devel_api_src_files ${devel_api_src_dir}/builder/json-parser.cpp ${devel_api_src_dir}/builder/tree-node.cpp ${devel_api_src_dir}/controls/accessible-impl.cpp + ${devel_api_src_dir}/controls/canvas-view/canvas-view.cpp ${devel_api_src_dir}/controls/control-devel.cpp ${devel_api_src_dir}/controls/control-wrapper.cpp ${devel_api_src_dir}/controls/control-wrapper-impl.cpp @@ -83,6 +84,7 @@ SET( devel_api_accessibility-manager_header_files SET( devel_api_controls_header_files ${devel_api_src_dir}/controls/accessible-impl.h + ${devel_api_src_dir}/controls/canvas-view/canvas-view.h ${devel_api_src_dir}/controls/control-depth-index-ranges.h ${devel_api_src_dir}/controls/control-devel.h ${devel_api_src_dir}/controls/control-wrapper.h diff --git a/dali-toolkit/internal/controls/canvas-view/canvas-view-impl.cpp b/dali-toolkit/internal/controls/canvas-view/canvas-view-impl.cpp new file mode 100644 index 0000000..07c77d9 --- /dev/null +++ b/dali-toolkit/internal/controls/canvas-view/canvas-view-impl.cpp @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2021 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 "canvas-view-impl.h" + +// EXTERNAL INCLUDES +#include +#include +#include +#include + +// INTERNAL INCLUDES +#include +#include +#include +#include +#include + +namespace Dali +{ +namespace Toolkit +{ +namespace Internal +{ +namespace +{ +BaseHandle Create() +{ + return BaseHandle(); +} +// Setup properties, signals and actions using the type-registry. +DALI_TYPE_REGISTRATION_BEGIN(Toolkit::CanvasView, Toolkit::Control, Create); +DALI_TYPE_REGISTRATION_END() +} // anonymous namespace + +using namespace Dali; + +CanvasView::CanvasView(const Vector2& viewBox) +: Control(ControlBehaviour(CONTROL_BEHAVIOUR_DEFAULT)), + mCanvasRenderer(CanvasRenderer::New(viewBox)), + mTexture(), + mChanged(false) +{ +} + +CanvasView::~CanvasView() +{ + if(Adaptor::IsAvailable()) + { + Adaptor::Get().UnregisterProcessor(*this); + } +} + +Toolkit::CanvasView CanvasView::New(const Vector2& viewBox) +{ + CanvasView* impl = new CanvasView(viewBox); + + Toolkit::CanvasView handle = Toolkit::CanvasView(*impl); + + // Second-phase init of the implementation + // This can only be done after the CustomActor connection has been made... + impl->Initialize(); + + return handle; +} + +///////////////////////////////////////////////////////////// + +void CanvasView::OnInitialize() +{ + // CanvasView can relayout in the OnImageReady, alternative to a signal would be to have a upcall from the Control to CanvasView + Dali::Toolkit::Control handle(GetOwner()); + + DevelControl::SetAccessibilityConstructor(Self(), [](Dali::Actor actor) { + return std::unique_ptr( + new DevelControl::AccessibleImpl(actor, Dali::Accessibility::Role::IMAGE)); + }); + + Self().SetProperty(Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE, true); + + Adaptor::Get().RegisterProcessor(*this); +} + +void CanvasView::OnRelayout(const Vector2& size, RelayoutContainer& container) +{ + if(!mCanvasRenderer || + mCanvasRenderer.GetSize() == size || + !mCanvasRenderer.SetSize(size)) + { + return; + } + mChanged = true; +} + +void CanvasView::OnSizeSet(const Vector3& targetSize) +{ + Control::OnSizeSet(targetSize); + + if(!mCanvasRenderer || + mCanvasRenderer.GetSize() == Vector2(targetSize) || + !mCanvasRenderer.SetSize(Vector2(targetSize))) + { + return; + } + mChanged = true; +} + +void CanvasView::Process() +{ + if(!mCanvasRenderer) + { + return; + } + Commit(); +} + +void CanvasView::Commit() +{ + if(mCanvasRenderer && mCanvasRenderer.Commit()) + { + Devel::PixelBuffer pixbuf = mCanvasRenderer.GetPixelBuffer(); + auto width = pixbuf.GetWidth(); + auto height = pixbuf.GetHeight(); + + Dali::PixelData pixelData = Devel::PixelBuffer::Convert(pixbuf); + if(!pixelData) + { + return; + } + + if(!mTexture || mChanged) + { + mTexture = Texture::New(TextureType::TEXTURE_2D, Dali::Pixel::RGBA8888, width, height); + mTexture.Upload(pixelData); + TextureSet textureSet = TextureSet::New(); + textureSet.SetTexture(0, mTexture); + Geometry geometry = VisualFactoryCache::CreateQuadGeometry(); + Shader shader = Shader::New(SHADER_CANVAS_VIEW_VERT, SHADER_CANVAS_VIEW_FRAG); + Renderer renderer = Renderer::New(geometry, shader); + renderer.SetTextures(textureSet); + renderer.SetProperty(Renderer::Property::BLEND_PRE_MULTIPLIED_ALPHA, true); + + Self().AddRenderer(renderer); + mChanged = false; + } + else + { + //Update texture + mTexture.Upload(pixelData); + } + } +} + +bool CanvasView::AddDrawable(Dali::CanvasRenderer::Drawable& drawable) +{ + if(mCanvasRenderer && mCanvasRenderer.AddDrawable(drawable)) + { + return true; + } + return false; +} +} // namespace Internal +} // namespace Toolkit +} // namespace Dali diff --git a/dali-toolkit/internal/controls/canvas-view/canvas-view-impl.h b/dali-toolkit/internal/controls/canvas-view/canvas-view-impl.h new file mode 100644 index 0000000..bc5c708 --- /dev/null +++ b/dali-toolkit/internal/controls/canvas-view/canvas-view-impl.h @@ -0,0 +1,125 @@ +#ifndef DALI_TOOLKIT_INTERNAL_CANVAS_VIEW_H +#define DALI_TOOLKIT_INTERNAL_CANVAS_VIEW_H + +/* + * Copyright (c) 2021 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 +#include +#include +#include +#include + +// INTERNAL INCLUDES +#include +#include + +namespace Dali +{ +namespace Toolkit +{ +class CanvasView; + +namespace Internal +{ +class CanvasView : public Control, public Integration::Processor +{ +public: + /** + * Construct a new CanvasView. + */ + CanvasView(const Vector2& viewBox); + + /** + * A reference counted object may only be deleted by calling Unreference() + */ + virtual ~CanvasView(); + +public: + /** + * Create a new CanvasView. + * @return A smart-pointer to the newly allocated CanvasView. + */ + static Toolkit::CanvasView New(const Vector2& viewBox); + + /** + * @copydoc Toolkit::Control::CanvasView::AddDrawable + */ + bool AddDrawable(Dali::CanvasRenderer::Drawable& drawable); + +private: // From Control + /** + * @copydoc Control::OnRelayout + */ + void OnRelayout(const Vector2& size, RelayoutContainer& container) override; + + /** + * @copydoc Toolkit::Control::OnSizeSet() + */ + void OnSizeSet(const Vector3& targetSize) override; + + /** + * @copydoc Toolkit::Control::OnInitialize + */ + void OnInitialize() override; + +protected: // Implementation of Processor + /** + * @copydoc Dali::Integration::Processor::Process() + */ + void Process() override; + +private: + /** + * @brief Draw drawables added to CanvasView on inner canvas. + * Then make that buffer into a texture and add it to renderer. + */ + void Commit(); + +private: + CanvasView(const CanvasView&) = delete; + CanvasView& operator=(const CanvasView&) = delete; + +private: + CanvasRenderer mCanvasRenderer; + Dali::Texture mTexture; + bool mChanged; +}; + +} // namespace Internal + +// Helpers for public-api forwarding methods +inline Toolkit::Internal::CanvasView& GetImpl(Toolkit::CanvasView& obj) +{ + DALI_ASSERT_ALWAYS(obj); + Dali::RefObject& handle = obj.GetImplementation(); + return static_cast(handle); +} + +inline const Toolkit::Internal::CanvasView& GetImpl(const Toolkit::CanvasView& obj) +{ + DALI_ASSERT_ALWAYS(obj); + const Dali::RefObject& handle = obj.GetImplementation(); + return static_cast(handle); +} + +} // namespace Toolkit + +} // namespace Dali + +#endif // DALI_TOOLKIT_INTERNAL_CANVAS_VIEW_H diff --git a/dali-toolkit/internal/file.list b/dali-toolkit/internal/file.list index c26fc7c..1fd9511 100644 --- a/dali-toolkit/internal/file.list +++ b/dali-toolkit/internal/file.list @@ -61,6 +61,7 @@ SET( toolkit_src_files ${toolkit_src_dir}/controls/buttons/push-button-impl.cpp ${toolkit_src_dir}/controls/buttons/radio-button-impl.cpp ${toolkit_src_dir}/controls/buttons/toggle-button-impl.cpp + ${toolkit_src_dir}/controls/canvas-view/canvas-view-impl.cpp ${toolkit_src_dir}/controls/control/control-data-impl.cpp ${toolkit_src_dir}/controls/control/control-debug.cpp ${toolkit_src_dir}/controls/control/control-renderers.cpp diff --git a/dali-toolkit/internal/graphics/shaders/canvas-view.frag b/dali-toolkit/internal/graphics/shaders/canvas-view.frag new file mode 100644 index 0000000..e122bca --- /dev/null +++ b/dali-toolkit/internal/graphics/shaders/canvas-view.frag @@ -0,0 +1,8 @@ +uniform lowp vec4 uColor; +varying mediump vec2 vTexCoord; +uniform sampler2D sTexture; + +void main() +{ + gl_FragColor = texture2D(sTexture, vTexCoord) * uColor; +} diff --git a/dali-toolkit/internal/graphics/shaders/canvas-view.vert b/dali-toolkit/internal/graphics/shaders/canvas-view.vert new file mode 100644 index 0000000..6988993 --- /dev/null +++ b/dali-toolkit/internal/graphics/shaders/canvas-view.vert @@ -0,0 +1,10 @@ +attribute mediump vec2 aPosition; +varying mediump vec2 vTexCoord; +uniform highp mat4 uMvpMatrix; +uniform highp vec3 uSize; + +void main() +{ + gl_Position = uMvpMatrix * vec4(aPosition * uSize.xy, 0.0, 1.0); + vTexCoord = aPosition + vec2(0.5); +} diff --git a/doc/dali-toolkit-doc.h b/doc/dali-toolkit-doc.h index 5765d9c..ce364eb 100755 --- a/doc/dali-toolkit-doc.h +++ b/doc/dali-toolkit-doc.h @@ -174,6 +174,9 @@ * @defgroup dali_toolkit_controls_buttons Buttons * @brief Button is a small object on UI that you can press. + * @defgroup dali_toolkit_controls_canvas_view CanvasView + * @brief CanvasView is a class for displaying an vector primitives. + * * @defgroup dali_toolkit_controls_gaussian_blur_view Gaussian Blur View * @brief GaussianBlurView provides a render process that blurs an image. -- 2.7.4