Support InnerShadow and Borderline for control 06/323006/7
authorEunki, Hong <eunkiki.hong@samsung.com>
Mon, 21 Apr 2025 10:23:52 +0000 (19:23 +0900)
committerEunki, Hong <eunkiki.hong@samsung.com>
Mon, 28 Apr 2025 05:37:33 +0000 (14:37 +0900)
Let we define new properties for INNER_SHADOW and BORDERLINE.

We should make rendering order as
SHADOW - BACKGROUND - (CONTENT) - INNER_SHADOW - BORDERLINE.
So make INNER_SHADOW and BORDERLINE depth index as DECORATOIN reltive range.

Also, make BORDERLINE_WIDTH animatable properties to make
we control BORDERLINE visual easier, and make it animatable.

Change-Id: I1c8b4be1b0d98399105015c966395ae064c5b726
Signed-off-by: Eunki, Hong <eunkiki.hong@samsung.com>
automated-tests/src/dali-toolkit/utc-Dali-Control.cpp
dali-toolkit/devel-api/controls/control-devel.h
dali-toolkit/internal/controls/control/control-data-impl.cpp
dali-toolkit/internal/controls/control/control-data-impl.h
dali-toolkit/internal/controls/control/control-decoration-data.h [new file with mode: 0644]
dali-toolkit/internal/visuals/visual-base-data-impl.h

index 46ce1c0e6e008fd3cfd7f8e31d5e54506693581b..181f32917cfcbf29cd31c9c5b24faf8978aaf8ea 100644 (file)
@@ -27,6 +27,7 @@
 #include <dali-toolkit/devel-api/controls/control-devel.h>
 #include <dali-toolkit/devel-api/visual-factory/visual-factory.h>
 #include <dali-toolkit/devel-api/visuals/image-visual-actions-devel.h>
+#include <dali-toolkit/devel-api/visuals/visual-properties-devel.h>
 #include <dali-toolkit/public-api/align-enumerations.h>
 #include <dali.h>
 
@@ -719,6 +720,42 @@ int UtcDaliControlShadowProperties(void)
   END_TEST;
 }
 
+int UtcDaliControlInnerShadowProperties(void)
+{
+  ToolkitTestApplication application;
+  Control                control = Control::New();
+
+  DALI_TEST_CHECK(control.GetProperty(DevelControl::Property::INNER_SHADOW).Get<Property::Map>().Empty());
+
+  Property::Map imageMap;
+  imageMap[Toolkit::Visual::Property::TYPE] = Visual::IMAGE;
+  imageMap[ImageVisual::Property::URL]      = "TestImage";
+  control.SetProperty(DevelControl::Property::INNER_SHADOW, imageMap);
+  Property::Value propValue = control.GetProperty(DevelControl::Property::INNER_SHADOW);
+  Property::Map*  resultMap = propValue.GetMap();
+  DALI_TEST_CHECK(resultMap->Find(Toolkit::Visual::Property::TYPE));
+  DALI_TEST_EQUALS(resultMap->Find(Toolkit::Visual::Property::TYPE)->Get<int>(), (int)Visual::IMAGE, TEST_LOCATION);
+  DALI_TEST_CHECK(resultMap->Find(ImageVisual::Property::URL));
+  DALI_TEST_EQUALS(resultMap->Find(ImageVisual::Property::URL)->Get<std::string>(), "TestImage", TEST_LOCATION);
+
+  Property::Map colorMap;
+  colorMap[Visual::Property::TYPE]           = Visual::COLOR;
+  colorMap[ColorVisual::Property::MIX_COLOR] = Color::CYAN;
+  control.SetProperty(DevelControl::Property::INNER_SHADOW, colorMap);
+  propValue = control.GetProperty(DevelControl::Property::INNER_SHADOW);
+  resultMap = propValue.GetMap();
+  DALI_TEST_CHECK(resultMap->Find(Toolkit::Visual::Property::TYPE));
+  DALI_TEST_EQUALS(resultMap->Find(Toolkit::Visual::Property::TYPE)->Get<int>(), (int)Visual::COLOR, TEST_LOCATION);
+  DALI_TEST_CHECK(resultMap->Find(ColorVisual::Property::MIX_COLOR));
+  DALI_TEST_EQUALS(resultMap->Find(ColorVisual::Property::MIX_COLOR)->Get<Vector4>(), Color::CYAN, TEST_LOCATION);
+
+  Property::Map emptyMap;
+  control.SetProperty(DevelControl::Property::INNER_SHADOW, emptyMap);
+  DALI_TEST_CHECK(control.GetProperty(DevelControl::Property::INNER_SHADOW).Get<Property::Map>().Empty());
+
+  END_TEST;
+}
+
 int UtcDaliControlKeyProperties(void)
 {
   ToolkitTestApplication application;
@@ -1609,6 +1646,8 @@ int UtcDaliControlNewWithDisableVisuals(void)
   // Check Background or Shadow with property map skipped
   control.SetProperty(Control::Property::BACKGROUND, propertyMap);
   control.SetProperty(DevelControl::Property::SHADOW, propertyMap);
+  control.SetProperty(DevelControl::Property::INNER_SHADOW, propertyMap);
+  control.SetProperty(DevelControl::Property::BORDERLINE, propertyMap);
 
   application.SendNotification();
   application.Render();
@@ -1672,3 +1711,186 @@ int UtcDaliControlCornerRadius(void)
 
   END_TEST;
 }
+
+int UtcDaliControlBorderline(void)
+{
+  ToolkitTestApplication application;
+
+  Control control = Control::New();
+  control.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
+  control.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+
+  application.GetScene().Add(control);
+
+  float   borderlineWidth  = 10.0f;
+  Vector4 borderlineColor  = Color::BLUE;
+  float   borderlineOffset = 0.2f;
+
+  control.SetProperty(DevelControl::Property::BORDERLINE_WIDTH, borderlineWidth);
+  control.SetProperty(DevelControl::Property::BORDERLINE_COLOR, borderlineColor);
+  control.SetProperty(DevelControl::Property::BORDERLINE_OFFSET, borderlineOffset);
+
+  application.SendNotification();
+  application.Render();
+
+  float   retrievedFloat;
+  Vector4 retrievedVector;
+  DALI_TEST_CHECK(control.GetProperty(DevelControl::Property::BORDERLINE_WIDTH).Get(retrievedFloat));
+  DALI_TEST_EQUALS(retrievedFloat, borderlineWidth, TEST_LOCATION);
+  DALI_TEST_CHECK(control.GetProperty(DevelControl::Property::BORDERLINE_COLOR).Get(retrievedVector));
+  DALI_TEST_EQUALS(retrievedVector, borderlineColor, TEST_LOCATION);
+  DALI_TEST_CHECK(control.GetProperty(DevelControl::Property::BORDERLINE_OFFSET).Get(retrievedFloat));
+  DALI_TEST_EQUALS(retrievedFloat, borderlineOffset, TEST_LOCATION);
+
+  Property::Map retrievedMap;
+
+  tet_printf("Check BORDERLINE visual has not corner radius value yet.\n");
+
+  Property::Value value = control.GetProperty(DevelControl::Property::BORDERLINE);
+  DALI_TEST_CHECK(value.GetMap());
+  retrievedMap = *(value.GetMap());
+
+  Property::Value* valuePtr = retrievedMap.Find(DevelVisual::Property::CORNER_RADIUS);
+  if(valuePtr)
+  {
+    DALI_TEST_CHECK(valuePtr->Get(retrievedVector));
+    DALI_TEST_EQUALS(retrievedVector, Vector4::ZERO, TEST_LOCATION);
+  }
+
+  valuePtr = retrievedMap.Find(DevelVisual::Property::BORDERLINE_WIDTH);
+  DALI_TEST_CHECK(valuePtr);
+  DALI_TEST_CHECK(valuePtr->Get(retrievedFloat));
+  DALI_TEST_EQUALS(retrievedFloat, borderlineWidth, TEST_LOCATION);
+  valuePtr = retrievedMap.Find(DevelVisual::Property::BORDERLINE_COLOR);
+  DALI_TEST_CHECK(valuePtr);
+  DALI_TEST_CHECK(valuePtr->Get(retrievedVector));
+  DALI_TEST_EQUALS(retrievedVector, borderlineColor, TEST_LOCATION);
+  valuePtr = retrievedMap.Find(DevelVisual::Property::BORDERLINE_OFFSET);
+  DALI_TEST_CHECK(valuePtr);
+  DALI_TEST_CHECK(valuePtr->Get(retrievedFloat));
+  DALI_TEST_EQUALS(retrievedFloat, borderlineOffset, TEST_LOCATION);
+
+  tet_printf("Set corner radius. Check BORDERLINE visual has corner radius value now.\n");
+  Vector4 radius    = Vector4(0.5f, 0.5f, 0.5f, 0.5f);
+  Vector4 squreness = Vector4(0.3f, 0.3f, 0.3f, 0.3f);
+  control.SetProperty(DevelControl::Property::CORNER_RADIUS, radius);
+  control.SetProperty(DevelControl::Property::CORNER_RADIUS_POLICY, Toolkit::Visual::Transform::Policy::Type::RELATIVE);
+  control.SetProperty(DevelControl::Property::CORNER_SQUARENESS, squreness);
+
+  value = control.GetProperty(DevelControl::Property::BORDERLINE);
+  DALI_TEST_CHECK(value.GetMap());
+  retrievedMap = *(value.GetMap());
+
+  int retrievedInteger;
+  valuePtr = retrievedMap.Find(DevelVisual::Property::CORNER_RADIUS);
+  DALI_TEST_CHECK(valuePtr);
+  DALI_TEST_CHECK(valuePtr->Get(retrievedVector));
+  DALI_TEST_EQUALS(retrievedVector, radius, TEST_LOCATION);
+  valuePtr = retrievedMap.Find(DevelVisual::Property::CORNER_RADIUS_POLICY);
+  DALI_TEST_CHECK(valuePtr);
+  DALI_TEST_CHECK(valuePtr->Get(retrievedInteger));
+  DALI_TEST_EQUALS(retrievedInteger, (int)Toolkit::Visual::Transform::Policy::Type::RELATIVE, TEST_LOCATION);
+  valuePtr = retrievedMap.Find(DevelVisual::Property::CORNER_SQUARENESS);
+  DALI_TEST_CHECK(valuePtr);
+  DALI_TEST_CHECK(valuePtr->Get(retrievedVector));
+  DALI_TEST_EQUALS(retrievedVector, squreness, TEST_LOCATION);
+
+  valuePtr = retrievedMap.Find(DevelVisual::Property::BORDERLINE_WIDTH);
+  DALI_TEST_CHECK(valuePtr);
+  DALI_TEST_CHECK(valuePtr->Get(retrievedFloat));
+  DALI_TEST_EQUALS(retrievedFloat, borderlineWidth, TEST_LOCATION);
+  valuePtr = retrievedMap.Find(DevelVisual::Property::BORDERLINE_COLOR);
+  DALI_TEST_CHECK(valuePtr);
+  DALI_TEST_CHECK(valuePtr->Get(retrievedVector));
+  DALI_TEST_EQUALS(retrievedVector, borderlineColor, TEST_LOCATION);
+  valuePtr = retrievedMap.Find(DevelVisual::Property::BORDERLINE_OFFSET);
+  DALI_TEST_CHECK(valuePtr);
+  DALI_TEST_CHECK(valuePtr->Get(retrievedFloat));
+  DALI_TEST_EQUALS(retrievedFloat, borderlineOffset, TEST_LOCATION);
+
+  tet_printf("Change borderline value. Check BORDERLINE visual.\n");
+  borderlineWidth  = 20.0f;
+  borderlineColor  = Color::RED;
+  borderlineOffset = -1.0f;
+
+  control.SetProperty(DevelControl::Property::BORDERLINE_WIDTH, borderlineWidth);
+  control.SetProperty(DevelControl::Property::BORDERLINE_COLOR, borderlineColor);
+  control.SetProperty(DevelControl::Property::BORDERLINE_OFFSET, borderlineOffset);
+
+  value = control.GetProperty(DevelControl::Property::BORDERLINE);
+  DALI_TEST_CHECK(value.GetMap());
+  retrievedMap = *(value.GetMap());
+
+  valuePtr = retrievedMap.Find(DevelVisual::Property::CORNER_RADIUS);
+  DALI_TEST_CHECK(valuePtr);
+  DALI_TEST_CHECK(valuePtr->Get(retrievedVector));
+  DALI_TEST_EQUALS(retrievedVector, radius, TEST_LOCATION);
+  valuePtr = retrievedMap.Find(DevelVisual::Property::CORNER_RADIUS_POLICY);
+  DALI_TEST_CHECK(valuePtr);
+  DALI_TEST_CHECK(valuePtr->Get(retrievedInteger));
+  DALI_TEST_EQUALS(retrievedInteger, (int)Toolkit::Visual::Transform::Policy::Type::RELATIVE, TEST_LOCATION);
+  valuePtr = retrievedMap.Find(DevelVisual::Property::CORNER_SQUARENESS);
+  DALI_TEST_CHECK(valuePtr);
+  DALI_TEST_CHECK(valuePtr->Get(retrievedVector));
+  DALI_TEST_EQUALS(retrievedVector, squreness, TEST_LOCATION);
+
+  valuePtr = retrievedMap.Find(DevelVisual::Property::BORDERLINE_WIDTH);
+  DALI_TEST_CHECK(valuePtr);
+  DALI_TEST_CHECK(valuePtr->Get(retrievedFloat));
+  DALI_TEST_EQUALS(retrievedFloat, borderlineWidth, TEST_LOCATION);
+  valuePtr = retrievedMap.Find(DevelVisual::Property::BORDERLINE_COLOR);
+  DALI_TEST_CHECK(valuePtr);
+  DALI_TEST_CHECK(valuePtr->Get(retrievedVector));
+  DALI_TEST_EQUALS(retrievedVector, borderlineColor, TEST_LOCATION);
+  valuePtr = retrievedMap.Find(DevelVisual::Property::BORDERLINE_OFFSET);
+  DALI_TEST_CHECK(valuePtr);
+  DALI_TEST_CHECK(valuePtr->Get(retrievedFloat));
+  DALI_TEST_EQUALS(retrievedFloat, borderlineOffset, TEST_LOCATION);
+
+  tet_printf("Set borderline property forcibly!\n");
+  borderlineWidth  = 30.0f;
+  borderlineColor  = Color::GREEN;
+  borderlineOffset = -0.3f;
+  // Just re-use retrieved map, to reduce duplicated property settings.
+  retrievedMap[DevelVisual::Property::CORNER_RADIUS]        = Vector4(10.f, 20.f, 30.f, 40.f);
+  retrievedMap[DevelVisual::Property::CORNER_RADIUS_POLICY] = (int)Toolkit::Visual::Transform::Policy::Type::ABSOLUTE;
+  retrievedMap[DevelVisual::Property::CORNER_SQUARENESS]    = Vector4(0.7f, 0.6f, 0.5f, 0.4f);
+  retrievedMap[DevelVisual::Property::BORDERLINE_WIDTH]     = borderlineWidth;
+  retrievedMap[DevelVisual::Property::BORDERLINE_COLOR]     = borderlineColor;
+  retrievedMap[DevelVisual::Property::BORDERLINE_OFFSET]    = borderlineOffset;
+
+  control.SetProperty(DevelControl::Property::BORDERLINE, retrievedMap);
+
+  value = control.GetProperty(DevelControl::Property::BORDERLINE);
+  DALI_TEST_CHECK(value.GetMap());
+  retrievedMap = *(value.GetMap());
+
+  // Check we are using Control's corner radius feature instead it's own.
+  valuePtr = retrievedMap.Find(DevelVisual::Property::CORNER_RADIUS);
+  DALI_TEST_CHECK(valuePtr);
+  DALI_TEST_CHECK(valuePtr->Get(retrievedVector));
+  DALI_TEST_EQUALS(retrievedVector, radius, TEST_LOCATION);
+  valuePtr = retrievedMap.Find(DevelVisual::Property::CORNER_RADIUS_POLICY);
+  DALI_TEST_CHECK(valuePtr);
+  DALI_TEST_CHECK(valuePtr->Get(retrievedInteger));
+  DALI_TEST_EQUALS(retrievedInteger, (int)Toolkit::Visual::Transform::Policy::Type::RELATIVE, TEST_LOCATION);
+  valuePtr = retrievedMap.Find(DevelVisual::Property::CORNER_SQUARENESS);
+  DALI_TEST_CHECK(valuePtr);
+  DALI_TEST_CHECK(valuePtr->Get(retrievedVector));
+  DALI_TEST_EQUALS(retrievedVector, squreness, TEST_LOCATION);
+
+  valuePtr = retrievedMap.Find(DevelVisual::Property::BORDERLINE_WIDTH);
+  DALI_TEST_CHECK(valuePtr);
+  DALI_TEST_CHECK(valuePtr->Get(retrievedFloat));
+  DALI_TEST_EQUALS(retrievedFloat, borderlineWidth, TEST_LOCATION);
+  valuePtr = retrievedMap.Find(DevelVisual::Property::BORDERLINE_COLOR);
+  DALI_TEST_CHECK(valuePtr);
+  DALI_TEST_CHECK(valuePtr->Get(retrievedVector));
+  DALI_TEST_EQUALS(retrievedVector, borderlineColor, TEST_LOCATION);
+  valuePtr = retrievedMap.Find(DevelVisual::Property::BORDERLINE_OFFSET);
+  DALI_TEST_CHECK(valuePtr);
+  DALI_TEST_CHECK(valuePtr->Get(retrievedFloat));
+  DALI_TEST_EQUALS(retrievedFloat, borderlineOffset, TEST_LOCATION);
+
+  END_TEST;
+}
index b8764b629b9a78cd8a9eebcfa3e684a98352a2b9..3de84cab4b416ea5fdec2ede68f66d82b1cbe7f8 100644 (file)
@@ -265,6 +265,18 @@ enum
    */
   OFFSCREEN_RENDERING,
 
+  /**
+   * @brief The inner shadow of the control. The visual will use DepthIndex::Ranges::DECORATION - 2
+   * @details Name "innerShadow", type Property::MAP.
+   */
+  INNER_SHADOW,
+
+  /**
+   * @brief The inset borderline of the control. The visual will use DepthIndex::Ranges::DECORATION - 1
+   * @details Name "borderline", type Property::MAP.
+   */
+  BORDERLINE,
+
   /**
    * @brief The radius for the rounded corners of the control.
    * @details Name "viewCornerRadius", type Property::VECTOR4
@@ -293,6 +305,30 @@ enum
    * @note It will not create UniformMap internally. So this property don't be used at Render phase.
    */
   CORNER_SQUARENESS,
+
+  /**
+   * @brief The width for the borderline of the control. It will update borderline visual
+   * @details Name "viewBorderlineWidth", type Property::FLOAT.
+   * @see Dali::Toolkit::DevelVisual::Property::Type::BORDERLINE_WIDTH
+   * @note It will not create UniformMap internally. So this property don't be used at Render phase.
+   */
+  BORDERLINE_WIDTH,
+
+  /**
+   * @brief The color for the borderline of the control. It will update borderline visual
+   * @details Name "viewBorderlineColor", type Property::VECTOR4
+   * @see Dali::Toolkit::DevelVisual::Property::Type::BORDERLINE_COLOR
+   * @note It will not create UniformMap internally. So this property don't be used at Render phase.
+   */
+  BORDERLINE_COLOR,
+
+  /**
+   * @brief The offset for the borderline of the control. It will update borderline visual
+   * @details Name "viewBorderlineOffset", type Property::FLOAT.
+   * @see Dali::Toolkit::DevelVisual::Property::Type::BORDERLINE_OFFSET
+   * @note It will not create UniformMap internally. So this property don't be used at Render phase.
+   */
+  BORDERLINE_OFFSET,
 };
 
 } // namespace Property
index d4f81737d593aaa3bbca76a09c76df96ce7f7d20..041f2944f324785e0170a106a46cdc03101a6935 100644 (file)
@@ -49,6 +49,8 @@
 #include <dali-toolkit/internal/visuals/visual-base-impl.h>
 #include <dali-toolkit/public-api/controls/image-view/image-view.h>
 #include <dali-toolkit/public-api/focus-manager/keyboard-focus-manager.h>
+#include <dali-toolkit/public-api/visuals/color-visual-properties.h>
+#include <dali-toolkit/public-api/visuals/visual-properties.h>
 
 #include <dali-toolkit/devel-api/visuals/visual-actions-devel.h>
 
@@ -94,6 +96,9 @@ constexpr const char* ACTION_ACCESSIBILITY_READING_RESUMED   = "ReadingResumed";
 constexpr const char* ACTION_ACCESSIBILITY_READING_SKIPPED   = "ReadingSkipped";
 constexpr const char* ACTION_ACCESSIBILITY_READING_STOPPED   = "ReadingStopped";
 
+constexpr int INNER_SHADOW_DEPTH_INDEX = DepthIndex::DECORATION - 2;
+constexpr int BORDERLINE_DEPTH_INDEX   = DepthIndex::DECORATION - 1;
+
 bool PerformAccessibilityAction(Toolkit::Control control, const std::string& actionName, const Property::Map& attributes)
 {
   using Dali::Accessibility::ActionType;
@@ -375,10 +380,15 @@ const PropertyRegistration Control::Impl::PROPERTY_28(typeRegistration, "accessi
 const PropertyRegistration Control::Impl::PROPERTY_29(typeRegistration, "accessibilityStates",            Toolkit::DevelControl::Property::ACCESSIBILITY_STATES,             Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
 const PropertyRegistration Control::Impl::PROPERTY_30(typeRegistration, "accessibilityIsModal",           Toolkit::DevelControl::Property::ACCESSIBILITY_IS_MODAL,           Property::BOOLEAN, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
 const PropertyRegistration Control::Impl::PROPERTY_31(typeRegistration, "offScreenRendering",             Toolkit::DevelControl::Property::OFFSCREEN_RENDERING,              Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
+const PropertyRegistration Control::Impl::PROPERTY_32(typeRegistration, "innerShadow",                    Toolkit::DevelControl::Property::INNER_SHADOW,                     Property::MAP,     &Control::Impl::SetProperty, &Control::Impl::GetProperty);
+const PropertyRegistration Control::Impl::PROPERTY_33(typeRegistration, "borderline",                     Toolkit::DevelControl::Property::BORDERLINE,                       Property::MAP,     &Control::Impl::SetProperty, &Control::Impl::GetProperty);
 
 const AnimatablePropertyRegistration Control::Impl::ANIMATABLE_PROPERTY_1(typeRegistration, "viewCornerRadius",       Toolkit::DevelControl::Property::CORNER_RADIUS,        Property::VECTOR4, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
 const AnimatablePropertyRegistration Control::Impl::ANIMATABLE_PROPERTY_2(typeRegistration, "viewCornerRadiusPolicy", Toolkit::DevelControl::Property::CORNER_RADIUS_POLICY, Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty); ///< Make animatable, for constarint-input
 const AnimatablePropertyRegistration Control::Impl::ANIMATABLE_PROPERTY_3(typeRegistration, "viewCornerSquareness",   Toolkit::DevelControl::Property::CORNER_SQUARENESS,    Property::VECTOR4, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
+const AnimatablePropertyRegistration Control::Impl::ANIMATABLE_PROPERTY_4(typeRegistration, "viewBorderlineWidth",    Toolkit::DevelControl::Property::BORDERLINE_WIDTH,     Property::FLOAT,   &Control::Impl::SetProperty, &Control::Impl::GetProperty);
+const AnimatablePropertyRegistration Control::Impl::ANIMATABLE_PROPERTY_5(typeRegistration, "viewBorderlineColor",    Toolkit::DevelControl::Property::BORDERLINE_COLOR,     Property::VECTOR4, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
+const AnimatablePropertyRegistration Control::Impl::ANIMATABLE_PROPERTY_6(typeRegistration, "viewBorderlineOffset",   Toolkit::DevelControl::Property::BORDERLINE_OFFSET,    Property::FLOAT,   &Control::Impl::SetProperty, &Control::Impl::GetProperty);
 
 // clang-format on
 
@@ -396,9 +406,6 @@ Control::Impl::Impl(Control& controlImpl)
   mCounterClockwiseFocusableActorId(-1),
   mStyleName(""),
   mBackgroundColor(Color::TRANSPARENT),
-  mCornerRadius(Vector4::ZERO),
-  mCornerRadiusPolicy(Toolkit::Visual::Transform::Policy::Type::ABSOLUTE),
-  mCornerSquareness(Vector4::ZERO),
   mRenderEffect(nullptr),
   mStartingPinchScale(nullptr),
   mMargin(0, 0, 0, 0),
@@ -412,6 +419,7 @@ Control::Impl::Impl(Control& controlImpl)
   mPanGestureDetector(),
   mTapGestureDetector(),
   mLongPressGestureDetector(),
+  mDecorationData{nullptr},
   mOffScreenRenderingImpl(nullptr),
   mOffScreenRenderingType(DevelControl::OffScreenRenderingType::NONE),
   mTooltip(NULL),
@@ -610,9 +618,9 @@ void Control::Impl::EnableCornerPropertiesOverridden(Toolkit::Visual::Base& visu
   if(DALI_LIKELY(mVisualData))
   {
     Property::Map map;
-    map[Toolkit::DevelVisual::Property::CORNER_RADIUS]        = mCornerRadius;
-    map[Toolkit::DevelVisual::Property::CORNER_RADIUS_POLICY] = mCornerRadiusPolicy;
-    map[Toolkit::DevelVisual::Property::CORNER_SQUARENESS]    = mCornerSquareness;
+    map[Toolkit::DevelVisual::Property::CORNER_RADIUS]        = DecorationData::GetCornerRadius(mDecorationData);
+    map[Toolkit::DevelVisual::Property::CORNER_RADIUS_POLICY] = DecorationData::GetCornerRadiusPolicy(mDecorationData);
+    map[Toolkit::DevelVisual::Property::CORNER_SQUARENESS]    = DecorationData::GetCornerSquareness(mDecorationData);
 
     mVisualData->EnableCornerPropertiesOverridden(visual, enable, map);
   }
@@ -1092,12 +1100,46 @@ void Control::Impl::SetProperty(BaseObject* object, Property::Index index, const
         break;
       }
 
+      case Toolkit::DevelControl::Property::INNER_SHADOW:
+      {
+        const Property::Map* map = value.GetMap();
+        if(map && !map->Empty())
+        {
+          controlImpl.mImpl->SetInnerShadow(*map);
+        }
+        else
+        {
+          // The shadow is an empty property map, so we should clear the inner shadow
+          controlImpl.mImpl->ClearInnerShadow();
+        }
+        break;
+      }
+
+      case Toolkit::DevelControl::Property::BORDERLINE:
+      {
+        const Property::Map* map = value.GetMap();
+        if(map && !map->Empty())
+        {
+          controlImpl.mImpl->SetBorderline(*map, true);
+        }
+        else
+        {
+          // The shadow is an empty property map, so we should clear the inner shadow
+          controlImpl.mImpl->ClearBorderline();
+        }
+        break;
+      }
+
       case Toolkit::DevelControl::Property::CORNER_RADIUS:
       {
         Vector4 radius;
         if(value.Get(radius))
         {
-          controlImpl.mImpl->SetCornerRadius(radius, controlImpl.mImpl->mCornerRadiusPolicy, controlImpl.mImpl->mCornerSquareness);
+          if(DecorationData::GetCornerRadius(controlImpl.mImpl->mDecorationData) != radius)
+          {
+            DecorationData::SetCornerRadius(controlImpl.mImpl->mDecorationData, radius);
+            controlImpl.mImpl->UpdateCornerRadius();
+          }
         }
         break;
       }
@@ -1107,9 +1149,11 @@ void Control::Impl::SetProperty(BaseObject* object, Property::Index index, const
         int policy;
         if(value.Get(policy))
         {
-          controlImpl.mImpl->SetCornerRadius(controlImpl.mImpl->mCornerRadius,
-                                             static_cast<Toolkit::Visual::Transform::Policy::Type>(policy),
-                                             controlImpl.mImpl->mCornerSquareness);
+          if(DecorationData::GetCornerRadiusPolicy(controlImpl.mImpl->mDecorationData) != policy)
+          {
+            DecorationData::SetCornerRadiusPolicy(controlImpl.mImpl->mDecorationData, policy);
+            controlImpl.mImpl->UpdateCornerRadius();
+          }
         }
         break;
       }
@@ -1119,7 +1163,53 @@ void Control::Impl::SetProperty(BaseObject* object, Property::Index index, const
         Vector4 squareness;
         if(value.Get(squareness))
         {
-          controlImpl.mImpl->SetCornerRadius(controlImpl.mImpl->mCornerRadius, controlImpl.mImpl->mCornerRadiusPolicy, squareness);
+          if(DecorationData::GetCornerSquareness(controlImpl.mImpl->mDecorationData) != squareness)
+          {
+            DecorationData::SetCornerSquareness(controlImpl.mImpl->mDecorationData, squareness);
+            controlImpl.mImpl->UpdateCornerRadius();
+          }
+        }
+        break;
+      }
+
+      case Toolkit::DevelControl::Property::BORDERLINE_WIDTH:
+      {
+        float width;
+        if(value.Get(width))
+        {
+          if(DecorationData::GetBorderlineWidth(controlImpl.mImpl->mDecorationData) != width)
+          {
+            DecorationData::SetBorderlineWidth(controlImpl.mImpl->mDecorationData, width);
+            controlImpl.mImpl->UpdateBorderline();
+          }
+        }
+        break;
+      }
+
+      case Toolkit::DevelControl::Property::BORDERLINE_COLOR:
+      {
+        Vector4 color;
+        if(value.Get(color))
+        {
+          if(DecorationData::GetBorderlineColor(controlImpl.mImpl->mDecorationData) != color)
+          {
+            DecorationData::SetBorderlineColor(controlImpl.mImpl->mDecorationData, color);
+            controlImpl.mImpl->UpdateBorderline();
+          }
+        }
+        break;
+      }
+
+      case Toolkit::DevelControl::Property::BORDERLINE_OFFSET:
+      {
+        float offset;
+        if(value.Get(offset))
+        {
+          if(DecorationData::GetBorderlineOffset(controlImpl.mImpl->mDecorationData) != offset)
+          {
+            DecorationData::SetBorderlineOffset(controlImpl.mImpl->mDecorationData, offset);
+            controlImpl.mImpl->UpdateBorderline();
+          }
         }
         break;
       }
@@ -1336,21 +1426,73 @@ Property::Value Control::Impl::GetProperty(BaseObject* object, Property::Index i
         break;
       }
 
+      case Toolkit::DevelControl::Property::INNER_SHADOW:
+      {
+        Property::Map map;
+
+        if(DALI_LIKELY(controlImpl.mImpl->mVisualData))
+        {
+          Toolkit::Visual::Base visual = controlImpl.mImpl->mVisualData->GetVisual(Toolkit::DevelControl::Property::INNER_SHADOW);
+          if(visual)
+          {
+            visual.CreatePropertyMap(map);
+          }
+        }
+
+        value = map;
+        break;
+      }
+
+      case Toolkit::DevelControl::Property::BORDERLINE:
+      {
+        Property::Map map;
+
+        if(DALI_LIKELY(controlImpl.mImpl->mVisualData))
+        {
+          Toolkit::Visual::Base visual = controlImpl.mImpl->mVisualData->GetVisual(Toolkit::DevelControl::Property::BORDERLINE);
+          if(visual)
+          {
+            visual.CreatePropertyMap(map);
+          }
+        }
+
+        value = map;
+        break;
+      }
+
       case Toolkit::DevelControl::Property::CORNER_RADIUS:
       {
-        value = controlImpl.mImpl->mCornerRadius;
+        value = DecorationData::GetCornerRadius(controlImpl.mImpl->mDecorationData);
         break;
       }
 
       case Toolkit::DevelControl::Property::CORNER_RADIUS_POLICY:
       {
-        value = static_cast<int32_t>(controlImpl.mImpl->mCornerRadiusPolicy);
+        value = DecorationData::GetCornerRadiusPolicy(controlImpl.mImpl->mDecorationData);
         break;
       }
 
       case Toolkit::DevelControl::Property::CORNER_SQUARENESS:
       {
-        value = controlImpl.mImpl->mCornerSquareness;
+        value = DecorationData::GetCornerSquareness(controlImpl.mImpl->mDecorationData);
+        break;
+      }
+
+      case Toolkit::DevelControl::Property::BORDERLINE_WIDTH:
+      {
+        value = DecorationData::GetBorderlineWidth(controlImpl.mImpl->mDecorationData);
+        break;
+      }
+
+      case Toolkit::DevelControl::Property::BORDERLINE_COLOR:
+      {
+        value = DecorationData::GetBorderlineColor(controlImpl.mImpl->mDecorationData);
+        break;
+      }
+
+      case Toolkit::DevelControl::Property::BORDERLINE_OFFSET:
+      {
+        value = DecorationData::GetBorderlineOffset(controlImpl.mImpl->mDecorationData);
         break;
       }
     }
@@ -1591,6 +1733,71 @@ void Control::Impl::ClearShadow()
   }
 }
 
+void Control::Impl::SetInnerShadow(const Property::Map& map)
+{
+  if(DALI_LIKELY(mVisualData))
+  {
+    Toolkit::Visual::Base visual = Toolkit::VisualFactory::Get().CreateVisual(map);
+    visual.SetName("innerShadow");
+
+    if(visual)
+    {
+      mVisualData->RegisterVisual(Toolkit::DevelControl::Property::INNER_SHADOW, visual, INNER_SHADOW_DEPTH_INDEX);
+      EnableCornerPropertiesOverridden(visual, true);
+
+      mControlImpl.RelayoutRequest();
+    }
+  }
+}
+
+void Control::Impl::ClearInnerShadow()
+{
+  if(DALI_LIKELY(mVisualData))
+  {
+    mVisualData->UnregisterVisual(Toolkit::DevelControl::Property::INNER_SHADOW);
+
+    // Trigger a size negotiation request that may be needed when unregistering a visual.
+    mControlImpl.RelayoutRequest();
+  }
+}
+
+void Control::Impl::SetBorderline(const Property::Map& map, bool forciblyCreate)
+{
+  if(DALI_LIKELY(mVisualData))
+  {
+    if(!forciblyCreate)
+    {
+      Toolkit::Internal::Visual::Base* previousVisualImplPtr = mVisualData->GetVisualImplPtr(Toolkit::DevelControl::Property::BORDERLINE);
+      if(previousVisualImplPtr)
+      {
+        previousVisualImplPtr->DoAction(Toolkit::DevelVisual::Action::UPDATE_PROPERTY, map);
+        return;
+      }
+    }
+    Toolkit::Visual::Base visual = Toolkit::VisualFactory::Get().CreateVisual(map);
+    visual.SetName("borderline");
+
+    if(visual)
+    {
+      mVisualData->RegisterVisual(Toolkit::DevelControl::Property::BORDERLINE, visual, BORDERLINE_DEPTH_INDEX);
+      EnableCornerPropertiesOverridden(visual, true);
+
+      mControlImpl.RelayoutRequest();
+    }
+  }
+}
+
+void Control::Impl::ClearBorderline()
+{
+  if(DALI_LIKELY(mVisualData))
+  {
+    mVisualData->UnregisterVisual(Toolkit::DevelControl::Property::BORDERLINE);
+
+    // Trigger a size negotiation request that may be needed when unregistering a visual.
+    mControlImpl.RelayoutRequest();
+  }
+}
+
 Dali::Property Control::Impl::GetVisualProperty(Dali::Property::Index index, Dali::Property::Key visualPropertyKey)
 {
   if(DALI_LIKELY(mVisualData))
@@ -1751,21 +1958,12 @@ void Control::Impl::SetOffScreenRendering(int32_t offScreenRenderingType)
   mOffScreenRenderingType = newType;
 }
 
-void Control::Impl::SetCornerRadius(Vector4 radius, Toolkit::Visual::Transform::Policy::Type policy, Vector4 squareness)
+void Control::Impl::UpdateCornerRadius()
 {
-  if(radius == mCornerRadius && policy == mCornerRadiusPolicy && squareness == mCornerSquareness)
-  {
-    return;
-  }
-
-  mCornerRadius       = radius;
-  mCornerRadiusPolicy = policy;
-  mCornerSquareness   = squareness;
-
   Property::Map map;
-  map[Toolkit::DevelVisual::Property::CORNER_RADIUS]        = radius;
-  map[Toolkit::DevelVisual::Property::CORNER_RADIUS_POLICY] = policy;
-  map[Toolkit::DevelVisual::Property::CORNER_SQUARENESS]    = squareness;
+  map[Toolkit::DevelVisual::Property::CORNER_RADIUS]        = DecorationData::GetCornerRadius(mDecorationData);
+  map[Toolkit::DevelVisual::Property::CORNER_RADIUS_POLICY] = DecorationData::GetCornerRadiusPolicy(mDecorationData);
+  map[Toolkit::DevelVisual::Property::CORNER_SQUARENESS]    = DecorationData::GetCornerSquareness(mDecorationData);
 
   RegisteredVisualContainer& visuals = mVisualData->mVisuals;
   for(auto it = visuals.begin(); it != visuals.end(); it++)
@@ -1787,6 +1985,18 @@ void Control::Impl::SetCornerRadius(Vector4 radius, Toolkit::Visual::Transform::
   }
 }
 
+void Control::Impl::UpdateBorderline()
+{
+  Property::Map map;
+  map[Toolkit::Visual::Property::TYPE]                   = Toolkit::Visual::Type::COLOR;
+  map[Toolkit::ColorVisual::Property::MIX_COLOR]         = Color::TRANSPARENT;
+  map[Toolkit::DevelVisual::Property::BORDERLINE_WIDTH]  = DecorationData::GetBorderlineWidth(mDecorationData);
+  map[Toolkit::DevelVisual::Property::BORDERLINE_COLOR]  = DecorationData::GetBorderlineColor(mDecorationData);
+  map[Toolkit::DevelVisual::Property::BORDERLINE_OFFSET] = DecorationData::GetBorderlineOffset(mDecorationData);
+
+  SetBorderline(map, false);
+}
+
 void Control::Impl::Process(bool postProcessor)
 {
   if(DALI_LIKELY(mVisualData))
index a832860b2a1fe9203bce674724973be3d8543620..2ee794ea81219ffae94b8a8c52ed26edb8ea11b9 100644 (file)
@@ -27,6 +27,7 @@
 
 // INTERNAL INCLUDES
 #include <dali-toolkit/devel-api/controls/control-devel.h>
+#include <dali-toolkit/internal/controls/control/control-decoration-data.h>
 #include <dali-toolkit/internal/controls/render-effects/offscreen-rendering-impl.h>
 #include <dali-toolkit/internal/controls/render-effects/render-effect-impl.h>
 #include <dali-toolkit/internal/controls/tooltip/tooltip.h>
@@ -357,6 +358,29 @@ public:
    */
   void ClearShadow();
 
+  /**
+   * @brief Sets the inner shadow with a property map.
+   * @param[in] map The inner shadow property map
+   */
+  void SetInnerShadow(const Property::Map& map);
+
+  /**
+   * @brief Clear the inner shadow.
+   */
+  void ClearInnerShadow();
+
+  /**
+   * @brief Sets the borderline with a property map.
+   * @param[in] map The borderline property map
+   * @param[in] forciblyCreate Create new visual forcibly, False if we only need to update properties.
+   */
+  void SetBorderline(const Property::Map& map, bool forciblyCreate);
+
+  /**
+   * @brief Clear the borderline.
+   */
+  void ClearBorderline();
+
   /**
    * @copydoc DevelControl::GetVisualProperty()
    */
@@ -490,12 +514,14 @@ private:
   void SetOffScreenRendering(int32_t offScreenRenderingType);
 
   /**
-   * Set corner radius to this control.
-   * @param[in] radius Corner radius property value
-   * @param[in] policy Corner radius policy. Default value is ABSOLUTE.
-   * @param[in] squareness Corner squareness property value
+   * Notify to this control's corner radius changed.
    */
-  void SetCornerRadius(Vector4 radius, Toolkit::Visual::Transform::Policy::Type policy, Vector4 squareness);
+  void UpdateCornerRadius();
+
+  /**
+   * Notify to this control's borderline changed.
+   */
+  void UpdateBorderline();
 
 public:
   Control&            mControlImpl;
@@ -514,9 +540,6 @@ public:
 
   std::string                               mStyleName;
   Vector4                                   mBackgroundColor;    ///< The color of the background visual
-  Vector4                                   mCornerRadius;       ///< The corner radius of this control
-  Toolkit::Visual::Transform::Policy::Type  mCornerRadiusPolicy; ///< The corner radius policy of this control
-  Vector4                                   mCornerSquareness;   ///< The corner squareness of this control
   RenderEffectImplPtr                       mRenderEffect;       ///< The render effect on this control
   Vector3*                                  mStartingPinchScale; ///< The scale when a pinch gesture starts, TODO: consider removing this
   Extents                                   mMargin;             ///< The margin values
@@ -533,6 +556,9 @@ public:
   TapGestureDetector       mTapGestureDetector;
   LongPressGestureDetector mLongPressGestureDetector;
 
+  // Decoration data (CornerRadius, Borderline)
+  DecorationData* mDecorationData;
+
   // Off screen rendering context
   std::unique_ptr<OffScreenRenderingImpl> mOffScreenRenderingImpl;
   DevelControl::OffScreenRenderingType    mOffScreenRenderingType;
@@ -583,10 +609,15 @@ public:
   static const PropertyRegistration PROPERTY_29;
   static const PropertyRegistration PROPERTY_30;
   static const PropertyRegistration PROPERTY_31;
+  static const PropertyRegistration PROPERTY_32;
+  static const PropertyRegistration PROPERTY_33;
 
   static const AnimatablePropertyRegistration ANIMATABLE_PROPERTY_1;
   static const AnimatablePropertyRegistration ANIMATABLE_PROPERTY_2;
   static const AnimatablePropertyRegistration ANIMATABLE_PROPERTY_3;
+  static const AnimatablePropertyRegistration ANIMATABLE_PROPERTY_4;
+  static const AnimatablePropertyRegistration ANIMATABLE_PROPERTY_5;
+  static const AnimatablePropertyRegistration ANIMATABLE_PROPERTY_6;
 };
 
 } // namespace Internal
diff --git a/dali-toolkit/internal/controls/control/control-decoration-data.h b/dali-toolkit/internal/controls/control/control-decoration-data.h
new file mode 100644 (file)
index 0000000..88554b1
--- /dev/null
@@ -0,0 +1,119 @@
+#ifndef DALI_TOOLKIT_CONTROL_DECORATION_DATA_H
+#define DALI_TOOLKIT_CONTROL_DECORATION_DATA_H
+
+/*
+ * Copyright (c) 2025 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 <dali/public-api/math/vector4.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/public-api/visuals/visual-properties.h>
+
+namespace Dali::Toolkit::Internal
+{
+struct DecorationData
+{
+  // Default constructor
+  DecorationData()
+  : mBorderlineColor(Color::BLACK),
+    mCornerRadius(Vector4::ZERO),
+    mCornerSquareness(Vector4::ZERO),
+    mBorderlineWidth(0.0f),
+    mBorderlineOffset(0.0f),
+    mCornerRadiusPolicy(static_cast<int>(Toolkit::Visual::Transform::Policy::ABSOLUTE))
+  {
+  }
+  Vector4 mBorderlineColor;
+  Vector4 mCornerRadius;
+  Vector4 mCornerSquareness;
+  float   mBorderlineWidth;
+  float   mBorderlineOffset;
+  int     mCornerRadiusPolicy;
+
+  /**
+   * @brief Helper API to reduce duplicated codes.
+   *
+   * Keep these API as inline function due to the performance.
+   */
+  static DecorationData* EnsureDecorationData(DecorationData*& data)
+  {
+    if(data == nullptr)
+    {
+      data = new DecorationData();
+    }
+    return data;
+  }
+
+  static float GetBorderlineWidth(const DecorationData* const data)
+  {
+    return data ? data->mBorderlineWidth : 0.0f;
+  }
+  static void SetBorderlineWidth(DecorationData*& data, float value)
+  {
+    EnsureDecorationData(data)->mBorderlineWidth = value;
+  }
+
+  static Vector4 GetBorderlineColor(const DecorationData* const data)
+  {
+    return data ? data->mBorderlineColor : Color::BLACK;
+  }
+  static void SetBorderlineColor(DecorationData*& data, Vector4 value)
+  {
+    EnsureDecorationData(data)->mBorderlineColor = value;
+  }
+
+  static float GetBorderlineOffset(const DecorationData* const data)
+  {
+    return data ? data->mBorderlineOffset : 0.0f;
+  }
+  static void SetBorderlineOffset(DecorationData*& data, float value)
+  {
+    EnsureDecorationData(data)->mBorderlineOffset = value;
+  }
+
+  static Vector4 GetCornerRadius(const DecorationData* const data)
+  {
+    return data ? data->mCornerRadius : Vector4::ZERO;
+  }
+  static void SetCornerRadius(DecorationData*& data, Vector4 value)
+  {
+    EnsureDecorationData(data)->mCornerRadius = value;
+  }
+
+  static int GetCornerRadiusPolicy(const DecorationData* const data)
+  {
+    return data ? data->mCornerRadiusPolicy : static_cast<int>(Toolkit::Visual::Transform::Policy::ABSOLUTE);
+  }
+  static void SetCornerRadiusPolicy(DecorationData*& data, int value)
+  {
+    EnsureDecorationData(data)->mCornerRadiusPolicy = value;
+  }
+
+  static Vector4 GetCornerSquareness(const DecorationData* const data)
+  {
+    return data ? data->mCornerSquareness : Vector4::ZERO;
+  }
+  static void SetCornerSquareness(DecorationData*& data, Vector4 value)
+  {
+    EnsureDecorationData(data)->mCornerSquareness = value;
+  }
+};
+
+} // namespace Dali::Toolkit::Internal
+
+#endif // DALI_TOOLKIT_CONTROL_DECORATION_DATA_H
index 2e0edd602eb35e53ddcb9c42f9fd156f3a7fad79..affff43aa9290d8df9330b9a647c2dcbd86a0e9e 100644 (file)
@@ -24,6 +24,7 @@
 
 // INTERNAL INCLUDES
 #include <dali-toolkit/devel-api/visuals/visual-properties-devel.h>
+#include <dali-toolkit/internal/controls/control/control-decoration-data.h>
 #include <dali-toolkit/internal/visuals/visual-base-impl.h>
 #include <dali-toolkit/internal/visuals/visual-event-observer.h>
 #include <dali-toolkit/public-api/align-enumerations.h>
@@ -114,26 +115,6 @@ struct Base::Impl
     Toolkit::Align::Type mAnchorPoint;
   };
 
-  struct DecorationData
-  {
-    // Default constructor
-    DecorationData()
-    : mBorderlineColor(Color::BLACK),
-      mCornerRadius(Vector4::ZERO),
-      mCornerSquareness(Vector4::ZERO),
-      mBorderlineWidth(0.0f),
-      mBorderlineOffset(0.0f),
-      mCornerRadiusPolicy(static_cast<int>(Toolkit::Visual::Transform::Policy::ABSOLUTE))
-    {
-    }
-    Vector4 mBorderlineColor;
-    Vector4 mCornerRadius;
-    Vector4 mCornerSquareness;
-    float   mBorderlineWidth;
-    float   mBorderlineOffset;
-    int     mCornerRadiusPolicy;
-  };
-
   /**
    * @brief Set the uniform properties onto the renderer.
    * And Register visual transform uniforms if neccessary.
@@ -147,23 +128,14 @@ struct Base::Impl
     }
   }
 
-  DecorationData* EnsureDecorationData()
-  {
-    if(mDecorationData == nullptr)
-    {
-      mDecorationData = new DecorationData();
-    }
-    return mDecorationData;
-  }
-
   /**
    * @brief Get decoration data value : borderline width
    *
    * Keep these API as inline function due to the performance.
    */
-  float GetBorderlineWidth()
+  float GetBorderlineWidth() const
   {
-    return mDecorationData ? mDecorationData->mBorderlineWidth : 0.0f;
+    return DecorationData::GetBorderlineWidth(mDecorationData);
   }
 
   /**
@@ -173,7 +145,7 @@ struct Base::Impl
    */
   void SetBorderlineWidth(float value)
   {
-    EnsureDecorationData()->mBorderlineWidth = value;
+    DecorationData::SetBorderlineWidth(mDecorationData, value);
   }
 
   /**
@@ -181,9 +153,9 @@ struct Base::Impl
    *
    * Keep these API as inline function due to the performance.
    */
-  Vector4 GetBorderlineColor()
+  Vector4 GetBorderlineColor() const
   {
-    return mDecorationData ? mDecorationData->mBorderlineColor : Color::BLACK;
+    return DecorationData::GetBorderlineColor(mDecorationData);
   }
 
   /**
@@ -193,7 +165,7 @@ struct Base::Impl
    */
   void SetBorderlineColor(Vector4 value)
   {
-    EnsureDecorationData()->mBorderlineColor = value;
+    DecorationData::SetBorderlineColor(mDecorationData, value);
   }
 
   /**
@@ -201,9 +173,9 @@ struct Base::Impl
    *
    * Keep these API as inline function due to the performance.
    */
-  float GetBorderlineOffset()
+  float GetBorderlineOffset() const
   {
-    return mDecorationData ? mDecorationData->mBorderlineOffset : 0.0f;
+    return DecorationData::GetBorderlineOffset(mDecorationData);
   }
 
   /**
@@ -213,7 +185,7 @@ struct Base::Impl
    */
   void SetBorderlineOffset(float value)
   {
-    EnsureDecorationData()->mBorderlineOffset = value;
+    DecorationData::SetBorderlineOffset(mDecorationData, value);
   }
 
   /**
@@ -221,9 +193,9 @@ struct Base::Impl
    *
    * Keep these API as inline function due to the performance.
    */
-  Vector4 GetCornerRadius()
+  Vector4 GetCornerRadius() const
   {
-    return mDecorationData ? mDecorationData->mCornerRadius : Vector4::ZERO;
+    return DecorationData::GetCornerRadius(mDecorationData);
   }
 
   /**
@@ -233,7 +205,7 @@ struct Base::Impl
    */
   void SetCornerRadius(Vector4 value)
   {
-    EnsureDecorationData()->mCornerRadius = value;
+    DecorationData::SetCornerRadius(mDecorationData, value);
   }
 
   /**
@@ -241,9 +213,9 @@ struct Base::Impl
    *
    * Keep these API as inline function due to the performance.
    */
-  int GetCornerRadiusPolicy()
+  int GetCornerRadiusPolicy() const
   {
-    return mDecorationData ? mDecorationData->mCornerRadiusPolicy : static_cast<int>(Toolkit::Visual::Transform::Policy::ABSOLUTE);
+    return DecorationData::GetCornerRadiusPolicy(mDecorationData);
   }
 
   /**
@@ -253,7 +225,7 @@ struct Base::Impl
    */
   void SetCornerRadiusPolicy(int value)
   {
-    EnsureDecorationData()->mCornerRadiusPolicy = value;
+    DecorationData::SetCornerRadiusPolicy(mDecorationData, value);
   }
 
   /**
@@ -261,9 +233,9 @@ struct Base::Impl
    *
    * Keep these API as inline function due to the performance.
    */
-  Vector4 GetCornerSquareness()
+  Vector4 GetCornerSquareness() const
   {
-    return mDecorationData ? mDecorationData->mCornerSquareness : Vector4::ZERO;
+    return DecorationData::GetCornerSquareness(mDecorationData);
   }
 
   /**
@@ -273,7 +245,7 @@ struct Base::Impl
    */
   void SetCornerSquareness(Vector4 value)
   {
-    EnsureDecorationData()->mCornerSquareness = value;
+    DecorationData::SetCornerSquareness(mDecorationData, value);
   }
 
   VisualRenderer                  mRenderer;