From 65233ffeec86a52a2f0a06608d10d752c3ac2869 Mon Sep 17 00:00:00 2001 From: "Eunki, Hong" Date: Wed, 29 Jun 2022 17:16:06 +0900 Subject: [PATCH] Fix crash issue at VisualBase (DoAction + AnimateTo) Case 1 : When we try to change decorated properties by DoAction and UPDATE_PROPERTY, It can be crashed due to the VisualRenderer is not DecoratedVisualRenderer. This patch make we update properties only for valid visual types. Case 2 : When we try to animate with DevelVisual's animatable property, It become crashed. This cause we miss some logic of found registered property. Now, we can run arc-visual.example Change-Id: Icee700608277a4133426bb39a4c30b92ab8acc8f Signed-off-by: Eunki, Hong --- .../src/dali-toolkit/utc-Dali-Visual.cpp | 167 +++++++++++++++++++++ dali-toolkit/internal/visuals/visual-base-impl.cpp | 27 +++- 2 files changed, 189 insertions(+), 5 deletions(-) diff --git a/automated-tests/src/dali-toolkit/utc-Dali-Visual.cpp b/automated-tests/src/dali-toolkit/utc-Dali-Visual.cpp index 7c13fc1..f54a7f0 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-Visual.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-Visual.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -1825,6 +1826,66 @@ int UtcDaliVisualGetPropertyMap13(void) END_TEST; } +int UtcDaliVisualAnimateArcVisual(void) +{ + ToolkitTestApplication application; + tet_infoline("UtcDaliVisualAnimateArcVisual color"); + + static std::vector customUniforms = + { + UniformData("startAngle", Property::Type::FLOAT), + UniformData("sweepAngle", Property::Type::FLOAT), + }; + + TestGraphicsController& graphics = application.GetGraphicsController(); + graphics.AddCustomUniforms(customUniforms); + + VisualFactory factory = VisualFactory::Get(); + Property::Map propertyMap; + propertyMap.Insert(Visual::Property::TYPE, DevelVisual::ARC); + propertyMap.Insert(Visual::Property::MIX_COLOR, Color::BLUE); + propertyMap.Insert(DevelArcVisual::Property::START_ANGLE, 0.0f); + propertyMap.Insert(DevelArcVisual::Property::SWEEP_ANGLE, 90.0f); + propertyMap.Insert(DevelArcVisual::Property::CAP, DevelArcVisual::Cap::ROUND); + propertyMap.Insert(DevelArcVisual::Property::THICKNESS, 20.0f); + Visual::Base arcVisual = factory.CreateVisual(propertyMap); + + DummyControl actor = DummyControl::New(true); + Impl::DummyControl& dummyImpl = static_cast(actor.GetImplementation()); + dummyImpl.RegisterVisual(DummyControl::Property::TEST_VISUAL, arcVisual); + actor.SetProperty(Actor::Property::SIZE, Vector2(2000.f, 2000.f)); + actor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER); + application.GetScene().Add(actor); + + DALI_TEST_EQUALS(actor.GetRendererCount(), 1u, TEST_LOCATION); + + Renderer renderer = actor.GetRendererAt(0); + Property::Index index = renderer.GetPropertyIndex(DevelArcVisual::Property::SWEEP_ANGLE); + + Animation animation = Animation::New(4.0f); + animation.AnimateTo(Property(renderer, index), 50.0f); + animation.AnimateTo(DevelControl::GetVisualProperty(actor, DummyControl::Property::TEST_VISUAL, DevelArcVisual::Property::START_ANGLE), 40.0f); + animation.Play(); + + application.SendNotification(); + application.Render(0); + application.Render(2000u); // halfway point + + float sweepAngle = renderer.GetCurrentProperty(index); + DALI_TEST_EQUALS(sweepAngle, 70.0f, 0.0001f, TEST_LOCATION); + DALI_TEST_EQUALS(application.GetGlAbstraction().CheckUniformValue("startAngle", 20.0f), true, TEST_LOCATION); + DALI_TEST_EQUALS(application.GetGlAbstraction().CheckUniformValue("sweepAngle", 70.0f), true, TEST_LOCATION); + + application.Render(2000u); // another halfway point + + sweepAngle = renderer.GetCurrentProperty(index); + DALI_TEST_EQUALS(sweepAngle, 50.0f, 0.0001f, TEST_LOCATION); + DALI_TEST_EQUALS(application.GetGlAbstraction().CheckUniformValue("startAngle", 40.0f), true, TEST_LOCATION); + DALI_TEST_EQUALS(application.GetGlAbstraction().CheckUniformValue("sweepAngle", 50.0f), true, TEST_LOCATION); + + END_TEST; +} + int UtcDaliVisualAnimateBorderVisual01(void) { ToolkitTestApplication application; @@ -5638,6 +5699,10 @@ int UtcDaliVisualUpdateProperty(void) Vector3 targetMixColor = Vector3(1.0f, 0.4f, 0.2f); bool targetPreMultipliedAlpha = originalMap[Visual::Property::PREMULTIPLIED_ALPHA].Get() ^ true; DevelVisual::FittingMode targetVisualFittingMode = DevelVisual::CENTER; + Vector4 targetCornerRadius = Vector4(10.0f, 0.0f, 1.0f, 2.0f); + float targetBorderlineWidth = 20.0f; + Vector4 targetBorderlineColor = Color::RED; + float targetBorderlineOffset = 1.0f; Property::Map targetPropertyMap; targetPropertyMap[Visual::Property::OPACITY] = targetOpacity; @@ -5645,6 +5710,10 @@ int UtcDaliVisualUpdateProperty(void) targetPropertyMap[Visual::Property::MIX_COLOR] = targetMixColor; targetPropertyMap[Visual::Property::PREMULTIPLIED_ALPHA] = targetPreMultipliedAlpha; targetPropertyMap[DevelVisual::Property::VISUAL_FITTING_MODE] = targetVisualFittingMode; + targetPropertyMap[DevelVisual::Property::CORNER_RADIUS] = targetCornerRadius; + targetPropertyMap[DevelVisual::Property::BORDERLINE_WIDTH] = targetBorderlineWidth; + targetPropertyMap[DevelVisual::Property::BORDERLINE_COLOR] = targetBorderlineColor; + targetPropertyMap[DevelVisual::Property::BORDERLINE_OFFSET] = targetBorderlineOffset; // Update Properties DevelControl::DoAction(dummyControl, DummyControl::Property::TEST_VISUAL, DevelVisual::Action::UPDATE_PROPERTY, targetPropertyMap); @@ -5670,6 +5739,104 @@ int UtcDaliVisualUpdateProperty(void) DALI_TEST_CHECK(visualFittingModeValue); DALI_TEST_EQUALS(visualFittingModeValue->Get(), "CENTER", TEST_LOCATION); + Property::Value* cornerRadiusValue = resultMap.Find(DevelVisual::Property::CORNER_RADIUS, Property::VECTOR4); + DALI_TEST_CHECK(cornerRadiusValue); + DALI_TEST_EQUALS(cornerRadiusValue->Get(), targetCornerRadius, TEST_LOCATION); + + Property::Value* borderlineWidthValue = resultMap.Find(DevelVisual::Property::BORDERLINE_WIDTH, Property::FLOAT); + DALI_TEST_CHECK(borderlineWidthValue); + DALI_TEST_EQUALS(borderlineWidthValue->Get(), targetBorderlineWidth, TEST_LOCATION); + + Property::Value* borderlineColorValue = resultMap.Find(DevelVisual::Property::BORDERLINE_COLOR, Property::VECTOR4); + DALI_TEST_CHECK(borderlineColorValue); + DALI_TEST_EQUALS(borderlineColorValue->Get(), targetBorderlineColor, TEST_LOCATION); + + Property::Value* borderlineOffsetValue = resultMap.Find(DevelVisual::Property::BORDERLINE_OFFSET, Property::FLOAT); + DALI_TEST_CHECK(borderlineOffsetValue); + DALI_TEST_EQUALS(borderlineOffsetValue->Get(), targetBorderlineOffset, TEST_LOCATION); + + END_TEST; +} + +int UtcDaliVisualUpdatePropertyInvalidType(void) +{ + ToolkitTestApplication application; + tet_infoline("UtcDaliVisualUpdatePropertyInvalidType: Test update property by DoAction. But some value is not invalid to update"); + + VisualFactory factory = VisualFactory::Get(); + Property::Map propertyMap; + propertyMap[Visual::Property::TYPE] = Visual::Type::N_PATCH; + propertyMap[ImageVisual::Property::URL] = TEST_NPATCH_FILE_NAME; + + Visual::Base imageVisual = factory.CreateVisual(propertyMap); + + DummyControl dummyControl = DummyControl::New(true); + Impl::DummyControl& dummyImpl = static_cast(dummyControl.GetImplementation()); + dummyImpl.RegisterVisual(DummyControl::Property::TEST_VISUAL, imageVisual); + dummyControl[Actor::Property::SIZE] = Vector2(200.f, 200.f); + application.GetScene().Add(dummyControl); + + application.SendNotification(); + application.Render(); + + // Wait for image loading + DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION); + + application.SendNotification(); + application.Render(); + + Property::Map originalMap; + imageVisual.CreatePropertyMap(originalMap); + + float targetOpacity = 0.5f; + Vector3 targetMixColor = Vector3(1.0f, 0.4f, 0.2f); + bool targetPreMultipliedAlpha = originalMap[Visual::Property::PREMULTIPLIED_ALPHA].Get() ^ true; + DevelVisual::FittingMode targetVisualFittingMode = DevelVisual::CENTER; + Vector4 targetCornerRadius = Vector4(10.0f, 0.0f, 1.0f, 2.0f); + float targetBorderlineWidth = 20.0f; + Vector4 targetBorderlineColor = Color::RED; + float targetBorderlineOffset = 1.0f; + + Property::Map targetPropertyMap; + targetPropertyMap[Visual::Property::OPACITY] = targetOpacity; + targetPropertyMap[ImageVisual::Property::URL] = "foobar"; + targetPropertyMap[Visual::Property::MIX_COLOR] = targetMixColor; + targetPropertyMap[Visual::Property::PREMULTIPLIED_ALPHA] = targetPreMultipliedAlpha; + targetPropertyMap[DevelVisual::Property::VISUAL_FITTING_MODE] = targetVisualFittingMode; + + // Properties that N_PATCH visual could not used. + targetPropertyMap[DevelVisual::Property::CORNER_RADIUS] = targetCornerRadius; + targetPropertyMap[DevelVisual::Property::BORDERLINE_WIDTH] = targetBorderlineWidth; + targetPropertyMap[DevelVisual::Property::BORDERLINE_COLOR] = targetBorderlineColor; + targetPropertyMap[DevelVisual::Property::BORDERLINE_OFFSET] = targetBorderlineOffset; + + // Update Properties + DevelControl::DoAction(dummyControl, DummyControl::Property::TEST_VISUAL, DevelVisual::Action::UPDATE_PROPERTY, targetPropertyMap); + + Property::Map resultMap; + imageVisual.CreatePropertyMap(resultMap); + + // Test property values: they should be updated + Property::Value* colorValue = resultMap.Find(Visual::Property::MIX_COLOR, Property::VECTOR4); + DALI_TEST_CHECK(colorValue); + DALI_TEST_EQUALS(colorValue->Get(), Vector4(targetMixColor.r, targetMixColor.g, targetMixColor.b, targetOpacity), TEST_LOCATION); + + Property::Value* urlValue = resultMap.Find(ImageVisual::Property::URL, Property::STRING); + DALI_TEST_CHECK(urlValue); + // NOTE : NPatchVisual URL must NOT changed. + DALI_TEST_EQUALS(urlValue->Get(), TEST_NPATCH_FILE_NAME, TEST_LOCATION); + + Property::Value* preMultipliedValue = resultMap.Find(Visual::Property::PREMULTIPLIED_ALPHA, Property::BOOLEAN); + DALI_TEST_CHECK(preMultipliedValue); + DALI_TEST_EQUALS(preMultipliedValue->Get(), targetPreMultipliedAlpha, TEST_LOCATION); + + Property::Value* visualFittingModeValue = resultMap.Find(DevelVisual::Property::VISUAL_FITTING_MODE, Property::STRING); + DALI_TEST_CHECK(visualFittingModeValue); + DALI_TEST_EQUALS(visualFittingModeValue->Get(), "CENTER", TEST_LOCATION); + + // We don't check properties value that N_PATCH visual could not used. + // It is undefined. + END_TEST; } diff --git a/dali-toolkit/internal/visuals/visual-base-impl.cpp b/dali-toolkit/internal/visuals/visual-base-impl.cpp index b50cc59..99b6c38 100644 --- a/dali-toolkit/internal/visuals/visual-base-impl.cpp +++ b/dali-toolkit/internal/visuals/visual-base-impl.cpp @@ -27,6 +27,7 @@ #include //INTERNAL HEARDER +#include #include #include #include @@ -295,7 +296,7 @@ void Visual::Base::SetProperties(const Property::Map& propertyMap) mImpl->mBorderlineWidth = width; } - if(DALI_UNLIKELY(mImpl->mRenderer)) + if(DALI_UNLIKELY(mImpl->mRenderer && IsTypeAvailableForBorderline(mImpl->mType))) { // Unusual case. SetProperty called after OnInitialize(). // Assume that DoAction call UPDATE_PROPERTY. @@ -328,7 +329,7 @@ void Visual::Base::SetProperties(const Property::Map& propertyMap) mImpl->mBorderlineColor = color; } - if(DALI_UNLIKELY(mImpl->mRenderer)) + if(DALI_UNLIKELY(mImpl->mRenderer && IsTypeAvailableForBorderline(mImpl->mType))) { // Unusual case. SetProperty called after OnInitialize(). // Assume that DoAction call UPDATE_PROPERTY. @@ -344,7 +345,7 @@ void Visual::Base::SetProperties(const Property::Map& propertyMap) mImpl->mBorderlineOffset = offset; } - if(DALI_UNLIKELY(mImpl->mRenderer)) + if(DALI_UNLIKELY(mImpl->mRenderer && IsTypeAvailableForBorderline(mImpl->mType))) { // Unusual case. SetProperty called after OnInitialize(). // Assume that DoAction call UPDATE_PROPERTY. @@ -376,7 +377,7 @@ void Visual::Base::SetProperties(const Property::Map& propertyMap) } } - if(DALI_UNLIKELY(mImpl->mRenderer)) + if(DALI_UNLIKELY(mImpl->mRenderer && IsTypeAvailableForCornerRadius(mImpl->mType))) { // Unusual case. SetProperty called after OnInitialize(). // Assume that DoAction call UPDATE_PROPERTY. @@ -1233,18 +1234,34 @@ Dali::Property Visual::Base::GetPropertyObject(Dali::Property::Key key) } break; } - // Special case for MIX_COLOR default: { + // Special case for MIX_COLOR if(key.type == Property::Key::INDEX && ((mImpl->mType == Toolkit::Visual::COLOR && key.indexKey == ColorVisual::Property::MIX_COLOR) || (mImpl->mType == Toolkit::Visual::PRIMITIVE && key.indexKey == PrimitiveVisual::Property::MIX_COLOR))) { return Dali::Property(mImpl->mRenderer, VisualRenderer::Property::VISUAL_MIX_COLOR); } + + // Special case for BLUR_RADIUS + if(mImpl->mType == Toolkit::Visual::COLOR && + ((key.type == Property::Key::INDEX && key.indexKey == DevelColorVisual::Property::BLUR_RADIUS) || + (key.type == Property::Key::STRING && key.stringKey == BLUR_RADIUS_NAME))) + { + // Request to color-visual class + return OnGetPropertyObject(key); + } } } + // If it is not VisualRenderer property, check registered Renderer and Shader property. + Property::Index index = GetPropertyIndex(key); + if(index != Property::INVALID_INDEX) + { + return Dali::Property(mImpl->mRenderer, index); + } + // We can't find the property in the base class. // Request to child class return OnGetPropertyObject(key); -- 2.7.4