From f20180dbb4cd52afb0305f2aa7889e81f55ef19e Mon Sep 17 00:00:00 2001 From: Adeel Kazmi Date: Wed, 20 Dec 2017 14:56:24 +0000 Subject: [PATCH] (ColorVisual) Don't render if transparent alpha by default Added a property to force rendering if required. This was needed for the CLIP_CHILDREN use case. Change-Id: Id5beaf92ed38b2beb30439c7ab760c8a762f1d9f --- .../src/dali-toolkit/utc-Dali-Control.cpp | 86 ++++++++++++++++++++++ .../src/dali-toolkit/utc-Dali-Visual.cpp | 51 +++++++++++++ dali-toolkit/devel-api/file.list | 3 +- .../visuals/color-visual-properties-devel.h | 68 +++++++++++++++++ .../internal/visuals/color/color-visual.cpp | 21 +++++- dali-toolkit/internal/visuals/color/color-visual.h | 6 +- .../internal/visuals/visual-string-constants.cpp | 3 + .../internal/visuals/visual-string-constants.h | 3 + dali-toolkit/public-api/controls/control-impl.cpp | 72 +++++++++++++++--- 9 files changed, 300 insertions(+), 13 deletions(-) create mode 100644 dali-toolkit/devel-api/visuals/color-visual-properties-devel.h diff --git a/automated-tests/src/dali-toolkit/utc-Dali-Control.cpp b/automated-tests/src/dali-toolkit/utc-Dali-Control.cpp index 0a4dad2..df48a7d 100755 --- a/automated-tests/src/dali-toolkit/utc-Dali-Control.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-Control.cpp @@ -75,6 +75,18 @@ static void TestKeyInputFocusCallback( Control control ) const char* TEST_LARGE_IMAGE_FILE_NAME = TEST_RESOURCE_DIR "/tbcol.png"; const char* TEST_IMAGE_FILE_NAME = TEST_RESOURCE_DIR "/gallery-small-1.jpg"; +Vector4 GetControlBackgroundColor( Control& control ) +{ + Property::Value propValue = control.GetProperty( Control::Property::BACKGROUND ); + Property::Map* resultMap = propValue.GetMap(); + DALI_TEST_CHECK( resultMap->Find( ColorVisual::Property::MIX_COLOR ) ); + + Vector4 color; + resultMap->Find( ColorVisual::Property::MIX_COLOR )->Get( color ); + + return color; +} + } // namespace /////////////////////////////////////////////////////////////////////////////////////////////////// @@ -458,6 +470,80 @@ int UtcDaliControlBackgroundColor(void) END_TEST; } +int UtcDaliControlBackgroundColorRendererCount(void) +{ + tet_infoline( "Test ensures we only create renderers when non-transparent color is requested or if we our clipping-mode is set to CLIP_CHILDREN" ); + + ToolkitTestApplication application; + Control control = Control::New(); + Stage::GetCurrent().Add( control ); + + tet_infoline( "Set transparent, no renderers should be created" ); + control.SetBackgroundColor( Color::TRANSPARENT ); + application.SendNotification(); + application.Render(); + DALI_TEST_EQUALS( control.GetRendererCount(), 0u, TEST_LOCATION ); + + tet_infoline( "Set transparent alpha with positive RGB values, no renderers should be created, but returned color should reflect what we set" ); + const Vector4 alphaZero( 1.0f, 0.5f, 0.25f, 0.0f ); + control.SetBackgroundColor( alphaZero ); + application.SendNotification(); + application.Render(); + DALI_TEST_EQUALS( control.GetRendererCount(), 0u, TEST_LOCATION ); + DALI_TEST_EQUALS( GetControlBackgroundColor( control ), alphaZero, TEST_LOCATION ); + + tet_infoline( "Set semi transparent alpha with positive RGB values, 1 renderer should be created, but returned color should reflect what we set" ); + const Vector4 semiTransparent( 1.0f, 0.75f, 0.5f, 0.5f ); + control.SetBackgroundColor( semiTransparent ); + application.SendNotification(); + application.Render(); + DALI_TEST_EQUALS( control.GetRendererCount(), 1u, TEST_LOCATION ); + DALI_TEST_EQUALS( GetControlBackgroundColor( control ), semiTransparent, TEST_LOCATION ); + + tet_infoline( "Set transparent, ensure no renderers are created" ); + control.SetBackgroundColor( Color::TRANSPARENT ); + application.SendNotification(); + application.Render(); + DALI_TEST_EQUALS( control.GetRendererCount(), 0u, TEST_LOCATION ); + DALI_TEST_EQUALS( GetControlBackgroundColor( control ), Color::TRANSPARENT, TEST_LOCATION ); + + tet_infoline( "Set control to clip its children, a renderer should be created which will be transparent" ); + control.SetProperty( Actor::Property::CLIPPING_MODE, ClippingMode::CLIP_CHILDREN ); + application.SendNotification(); + application.Render(); + DALI_TEST_EQUALS( control.GetRendererCount(), 1u, TEST_LOCATION ); + DALI_TEST_EQUALS( GetControlBackgroundColor( control ), Color::TRANSPARENT, TEST_LOCATION ); + + tet_infoline( "Set a color, only 1 renderer should exist" ); + control.SetBackgroundColor( Color::RED ); + application.SendNotification(); + application.Render(); + DALI_TEST_EQUALS( control.GetRendererCount(), 1u, TEST_LOCATION ); + DALI_TEST_EQUALS( GetControlBackgroundColor( control ), Color::RED, TEST_LOCATION ); + + tet_infoline( "Clear the background, no renderers" ); + control.ClearBackground(); + application.SendNotification(); + application.Render(); + DALI_TEST_EQUALS( control.GetRendererCount(), 0u, TEST_LOCATION ); + + tet_infoline( "Set control to clip its children again, a renderer should be created which will be transparent" ); + control.SetProperty( Actor::Property::CLIPPING_MODE, ClippingMode::CLIP_CHILDREN ); + application.SendNotification(); + application.Render(); + DALI_TEST_EQUALS( control.GetRendererCount(), 1u, TEST_LOCATION ); + DALI_TEST_EQUALS( GetControlBackgroundColor( control ), Color::TRANSPARENT, TEST_LOCATION ); + + tet_infoline( "Disable clipping, no renderers" ); + control.SetProperty( Actor::Property::CLIPPING_MODE, ClippingMode::DISABLED ); + application.SendNotification(); + application.Render(); + DALI_TEST_EQUALS( control.GetRendererCount(), 0u, TEST_LOCATION ); + DALI_TEST_EQUALS( GetControlBackgroundColor( control ), Color::TRANSPARENT, TEST_LOCATION ); + + END_TEST; +} + int UtcDaliControlBackgroundImage(void) { ToolkitTestApplication application; diff --git a/automated-tests/src/dali-toolkit/utc-Dali-Visual.cpp b/automated-tests/src/dali-toolkit/utc-Dali-Visual.cpp index ab45fc0..bf54997 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-Visual.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-Visual.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -3392,3 +3393,53 @@ int UtcDaliRegisterVisualWithDepthIndex(void) END_TEST; } + +int UtcDaliColorVisualRenderIfTransparentProperty(void) +{ + ToolkitTestApplication application; + tet_infoline( "Test the renderIfTransparent property of ColorVisual" ); + + VisualFactory factory = VisualFactory::Get(); + Property::Map propertyMap; + propertyMap.Insert( Visual::Property::TYPE, Visual::COLOR ); + propertyMap.Insert( ColorVisual::Property::MIX_COLOR, Color::BLUE ); + + tet_infoline( "Check default value" ); + { + Visual::Base testVisual = factory.CreateVisual( propertyMap ); + Property::Map returnedMap; + testVisual.CreatePropertyMap( returnedMap ); + + Property::Value* renderIfTransparentProperty = returnedMap.Find( DevelColorVisual::Property::RENDER_IF_TRANSPARENT ); + DALI_TEST_CHECK( renderIfTransparentProperty ); + DALI_TEST_EQUALS( renderIfTransparentProperty->Get< bool >(), false, TEST_LOCATION ); + } + + propertyMap.Insert( DevelColorVisual::Property::RENDER_IF_TRANSPARENT, true ); + + tet_infoline( "Ensure set to value required" ); + { + Visual::Base testVisual = factory.CreateVisual( propertyMap ); + Property::Map returnedMap; + testVisual.CreatePropertyMap( returnedMap ); + + Property::Value* renderIfTransparentProperty = returnedMap.Find( DevelColorVisual::Property::RENDER_IF_TRANSPARENT ); + DALI_TEST_CHECK( renderIfTransparentProperty ); + DALI_TEST_EQUALS( renderIfTransparentProperty->Get< bool >(), true, TEST_LOCATION ); + } + + propertyMap[ DevelColorVisual::Property::RENDER_IF_TRANSPARENT ] = Color::BLUE; + + tet_infoline( "Ensure it returns default value if set to wrong type" ); + { + Visual::Base testVisual = factory.CreateVisual( propertyMap ); + Property::Map returnedMap; + testVisual.CreatePropertyMap( returnedMap ); + + Property::Value* renderIfTransparentProperty = returnedMap.Find( DevelColorVisual::Property::RENDER_IF_TRANSPARENT ); + DALI_TEST_CHECK( renderIfTransparentProperty ); + DALI_TEST_EQUALS( renderIfTransparentProperty->Get< bool >(), false, TEST_LOCATION ); + } + + END_TEST; +} diff --git a/dali-toolkit/devel-api/file.list b/dali-toolkit/devel-api/file.list index 0bfd7d4..812668b 100644 --- a/dali-toolkit/devel-api/file.list +++ b/dali-toolkit/devel-api/file.list @@ -91,9 +91,10 @@ devel_api_visual_factory_header_files = \ $(devel_api_src_dir)/visual-factory/visual-base.h devel_api_visuals_header_files = \ + $(devel_api_src_dir)/visuals/animated-gradient-visual-properties-devel.h \ + $(devel_api_src_dir)/visuals/color-visual-properties-devel.h \ $(devel_api_src_dir)/visuals/image-visual-properties-devel.h \ $(devel_api_src_dir)/visuals/image-visual-actions-devel.h \ - $(devel_api_src_dir)/visuals/animated-gradient-visual-properties-devel.h \ $(devel_api_src_dir)/visuals/text-visual-properties-devel.h \ $(devel_api_src_dir)/visuals/visual-properties-devel.h diff --git a/dali-toolkit/devel-api/visuals/color-visual-properties-devel.h b/dali-toolkit/devel-api/visuals/color-visual-properties-devel.h new file mode 100644 index 0000000..4eb8b3a --- /dev/null +++ b/dali-toolkit/devel-api/visuals/color-visual-properties-devel.h @@ -0,0 +1,68 @@ +#ifndef DALI_TOOLKIT_COLOR_VISUAL_PROPERTIES_DEVEL_H +#define DALI_TOOLKIT_COLOR_VISUAL_PROPERTIES_DEVEL_H + +/* + * Copyright (c) 2017 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 + +namespace Dali +{ + +namespace Toolkit +{ + + +namespace DevelColorVisual +{ + +/** + * @brief Additional ColorVisual Properties. + */ +namespace Property +{ + +/** + * @brief Enumeration for the instance of additional properties belonging to the ColorVisual. + */ +enum +{ + MIX_COLOR = Toolkit::ColorVisual::Property::MIX_COLOR, + + /** + * @brief Whether to render if the MIX_COLOR is transparent. + * @details Name "renderIfTransparent", type Property::BOOLEAN. + * @note Optional. + * @note By default it's false, i.e. ColorVisual will not render if the MIX_COLOR is transparent. + */ + RENDER_IF_TRANSPARENT = MIX_COLOR + 1, +}; + +} // namespace Property + +} // namespace ColorVisual + +/** + * @} + */ + +} // namespace Toolkit + +} // namespace Dali + +#endif // DALI_TOOLKIT_COLOR_VISUAL_PROPERTIES_DEVEL_H diff --git a/dali-toolkit/internal/visuals/color/color-visual.cpp b/dali-toolkit/internal/visuals/color/color-visual.cpp index 2d8008f..2058e1b 100644 --- a/dali-toolkit/internal/visuals/color/color-visual.cpp +++ b/dali-toolkit/internal/visuals/color/color-visual.cpp @@ -25,6 +25,7 @@ //INTERNAL INCLUDES #include #include +#include #include #include #include @@ -88,7 +89,8 @@ ColorVisualPtr ColorVisual::New( VisualFactoryCache& factoryCache, const Propert } ColorVisual::ColorVisual( VisualFactoryCache& factoryCache ) -: Visual::Base( factoryCache ) +: Visual::Base( factoryCache ), + mRenderIfTransparent( false ) { } @@ -122,13 +124,27 @@ void ColorVisual::DoSetProperties( const Property::Map& propertyMap ) DALI_LOG_ERROR("ColorVisual: mixColor property has incorrect type\n"); } } + + Property::Value* renderIfTransparentValue = propertyMap.Find( Toolkit::DevelColorVisual::Property::RENDER_IF_TRANSPARENT, RENDER_IF_TRANSPARENT_NAME ); + if( renderIfTransparentValue ) + { + if( ! renderIfTransparentValue->Get( mRenderIfTransparent ) ) + { + DALI_LOG_ERROR( "ColorVisual: renderIfTransparent property has incorrect type: %d\n", renderIfTransparentValue->GetType() ); + } + } } void ColorVisual::DoSetOnStage( Actor& actor ) { InitializeRenderer(); - actor.AddRenderer( mImpl->mRenderer ); + // Only add the renderer if it's not fully transparent + // We cannot avoid creating a renderer as it's used in the base class + if( mRenderIfTransparent || mImpl->mMixColor.a > 0.0f ) + { + actor.AddRenderer( mImpl->mRenderer ); + } // Color Visual generated and ready to display ResourceReady( Toolkit::Visual::ResourceStatus::READY ); @@ -139,6 +155,7 @@ void ColorVisual::DoCreatePropertyMap( Property::Map& map ) const map.Clear(); map.Insert( Toolkit::Visual::Property::TYPE, Toolkit::Visual::COLOR ); map.Insert( Toolkit::ColorVisual::Property::MIX_COLOR, mImpl->mMixColor ); + map.Insert( Toolkit::DevelColorVisual::Property::RENDER_IF_TRANSPARENT, mRenderIfTransparent ); } void ColorVisual::DoCreateInstancePropertyMap( Property::Map& map ) const diff --git a/dali-toolkit/internal/visuals/color/color-visual.h b/dali-toolkit/internal/visuals/color/color-visual.h index 939d40e..4b6dca6 100644 --- a/dali-toolkit/internal/visuals/color/color-visual.h +++ b/dali-toolkit/internal/visuals/color/color-visual.h @@ -2,7 +2,7 @@ #define DALI_TOOLKIT_INTERNAL_COLOR_VISUAL_H /* - * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * Copyright (c) 2017 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. @@ -112,6 +112,10 @@ private: // Undefined ColorVisual& operator=( const ColorVisual& colorRenderer ); + +private: + + bool mRenderIfTransparent; ///< Whether we should render even if the mix-color is transparent. }; } // namespace Internal diff --git a/dali-toolkit/internal/visuals/visual-string-constants.cpp b/dali-toolkit/internal/visuals/visual-string-constants.cpp index 9e889cb..079141d 100644 --- a/dali-toolkit/internal/visuals/visual-string-constants.cpp +++ b/dali-toolkit/internal/visuals/visual-string-constants.cpp @@ -72,6 +72,9 @@ const char * const PREMULTIPLIED_ALPHA( "premultipliedAlpha" ); const char * const MIX_COLOR( "mixColor" ); const char * const OPACITY( "opacity" ); +// Color visual +const char * const RENDER_IF_TRANSPARENT_NAME( "renderIfTransparent" ); + // Image visual const char * const IMAGE_URL_NAME( "url" ); const char * const ATLAS_RECT_UNIFORM_NAME( "uAtlasRect" ); diff --git a/dali-toolkit/internal/visuals/visual-string-constants.h b/dali-toolkit/internal/visuals/visual-string-constants.h index eb0b617..1a73da9 100644 --- a/dali-toolkit/internal/visuals/visual-string-constants.h +++ b/dali-toolkit/internal/visuals/visual-string-constants.h @@ -58,6 +58,9 @@ extern const char * const PREMULTIPLIED_ALPHA; extern const char * const MIX_COLOR; extern const char * const OPACITY; +// Color visual +extern const char * const RENDER_IF_TRANSPARENT_NAME; + // Image visual extern const char * const IMAGE_URL_NAME; extern const char * const ATLAS_RECT_UNIFORM_NAME; diff --git a/dali-toolkit/public-api/controls/control-impl.cpp b/dali-toolkit/public-api/controls/control-impl.cpp index 47a12b1..49064a8 100755 --- a/dali-toolkit/public-api/controls/control-impl.cpp +++ b/dali-toolkit/public-api/controls/control-impl.cpp @@ -30,18 +30,19 @@ #include // INTERNAL INCLUDES -#include +#include #include +#include #include #include +#include #include #include -#include #include +#include #include #include #include -#include #include namespace Dali @@ -61,6 +62,30 @@ Debug::Filter* gLogFilter = Debug::Filter::New( Debug::NoLogging, false, "LOG_CO #endif /** + * @brief Replace the background visual if it's a color visual with the renderIfTransparent property set as required. + * @param[in] controlImpl The control implementation + * @param[in] renderIfTransaparent Whether we should render if the color is transparent + */ +void ChangeBackgroundColorVisual( Control& controlImpl, bool renderIfTransparent ) +{ + Internal::Control::Impl& controlDataImpl = Internal::Control::Impl::Get( controlImpl ); + + Toolkit::Visual::Base backgroundVisual = controlDataImpl.GetVisual( Toolkit::Control::Property::BACKGROUND ); + if( backgroundVisual ) + { + Property::Map map; + backgroundVisual.CreatePropertyMap( map ); + Property::Value* typeValue = map.Find( Toolkit::Visual::Property::TYPE ); + if( typeValue && typeValue->Get< int >() == Toolkit::Visual::COLOR ) + { + // Only change it if it's a color visual + map[ Toolkit::DevelColorVisual::Property::RENDER_IF_TRANSPARENT ] = renderIfTransparent; + controlImpl.SetBackground( map ); + } + } +} + +/** * @brief Creates a clipping renderer if required. * (EG. If no renders exist and clipping is enabled). * @param[in] controlImpl The control implementation. @@ -72,13 +97,34 @@ void CreateClippingRenderer( Control& controlImpl ) int clippingMode = ClippingMode::DISABLED; if( self.GetProperty( Actor::Property::CLIPPING_MODE ).Get( clippingMode ) ) { - Internal::Control::Impl& controlDataImpl = Internal::Control::Impl::Get( controlImpl ); - - if( ( clippingMode == ClippingMode::CLIP_CHILDREN ) && - controlDataImpl.mVisuals.Empty() && - ( self.GetRendererCount() == 0u ) ) + switch( clippingMode ) { - controlImpl.SetBackgroundColor( Color::TRANSPARENT ); + case ClippingMode::CLIP_CHILDREN: + { + if( self.GetRendererCount() == 0u ) + { + Internal::Control::Impl& controlDataImpl = Internal::Control::Impl::Get( controlImpl ); + if( controlDataImpl.mVisuals.Empty() ) + { + controlImpl.SetBackgroundColor( Color::TRANSPARENT ); + } + else + { + // We have visuals, check if we've set the background and re-create it to + // render even if transparent (only if it's a color visual) + ChangeBackgroundColorVisual( controlImpl, true ); + } + } + break; + } + + case ClippingMode::DISABLED: + case ClippingMode::CLIP_TO_BOUNDING_BOX: + { + // If we have a background visual, check if it's a color visual and remove the render if transparent flag + ChangeBackgroundColorVisual( controlImpl, false ); + break; + } } } } @@ -168,6 +214,14 @@ void Control::SetBackgroundColor( const Vector4& color ) map[ Toolkit::Visual::Property::TYPE ] = Toolkit::Visual::COLOR; map[ Toolkit::ColorVisual::Property::MIX_COLOR ] = color; + int clippingMode = ClippingMode::DISABLED; + if( ( Self().GetProperty( Actor::Property::CLIPPING_MODE ).Get( clippingMode ) ) && + ( clippingMode == ClippingMode::CLIP_CHILDREN ) ) + { + // If clipping-mode is set to CLIP_CHILDREN, then force visual to add the render even if transparent + map[ Toolkit::DevelColorVisual::Property::RENDER_IF_TRANSPARENT ] = true; + } + SetBackground( map ); } -- 2.7.4