Introduce START_OFFSET Property of gradient visual. 43/322943/12
authorANZ1217 <chihun.jeong@samsung.com>
Thu, 17 Apr 2025 03:10:19 +0000 (12:10 +0900)
committerANZ1217 <chihun.jeong@samsung.com>
Mon, 28 Apr 2025 02:42:55 +0000 (11:42 +0900)
Change-Id: Ib1794497a5cdf532d459297ceb44853e486b4081

automated-tests/src/dali-toolkit/utc-Dali-Visual.cpp
dali-toolkit/internal/graphics/shaders/gradient-visual-shader.frag
dali-toolkit/internal/visuals/gradient/gradient-visual.cpp
dali-toolkit/internal/visuals/gradient/gradient-visual.h
dali-toolkit/internal/visuals/gradient/gradient.cpp
dali-toolkit/internal/visuals/gradient/gradient.h
dali-toolkit/internal/visuals/visual-string-constants.cpp
dali-toolkit/internal/visuals/visual-string-constants.h
dali-toolkit/public-api/visuals/gradient-visual-properties.h

index 8af9b8502b7e15e7e27f7f146d503c683a08df57..f3fc551cee43639ccc46332d300395c12e1af143 100644 (file)
@@ -7083,3 +7083,48 @@ int UtcDaliVisualCutoutPolicyChangeShader01(void)
 
   END_TEST;
 }
+
+int UtcDaliGradientAnimateTest(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline("UtcDaliGradientAnimateTest");
+
+  Control control = Control::New();
+  control[Actor::Property::SIZE] = Vector2(200.f, 200.f);
+
+  // Linear Gradient
+  Dali::Property::Map map;
+  map.Insert(Toolkit::Visual::Property::TYPE, Visual::GRADIENT);
+  Property::Array stopOffsets;
+  stopOffsets.PushBack(0.0f);
+  stopOffsets.PushBack(0.5f);
+  stopOffsets.PushBack(1.0f);
+  map.Insert(GradientVisual::Property::STOP_OFFSET, stopOffsets);
+  Property::Array stopColors;
+  stopColors.PushBack(Vector4(1.0f, 0.0f, 0.0f, 1.0f));
+  stopColors.PushBack(Vector4(0.8f, 1.0f, 0.0f, 1.0f));
+  stopColors.PushBack(Vector4(0.0f, 0.0f, 1.0f, 1.0f));
+  map.Insert(GradientVisual::Property::STOP_COLOR, stopColors);
+  map.Insert(GradientVisual::Property::SPREAD_METHOD, GradientVisual::SpreadMethod::REPEAT);
+  map.Insert(GradientVisual::Property::START_POSITION, Vector2(-100.f, -100.f));
+  map.Insert(GradientVisual::Property::END_POSITION, Vector2(100.f, 100.f));
+  map.Insert(GradientVisual::Property::START_OFFSET, 0.5f);
+
+  control[Dali::Toolkit::Control::Property::BACKGROUND] = map;
+
+  Dali::Property property1 = DevelControl::GetVisualProperty(control, Control::Property::BACKGROUND, GradientVisual::Property::START_OFFSET);
+  DALI_TEST_EQUALS(property1.object.GetProperty(property1.propertyIndex).Get<float>(), 0.5f, TEST_LOCATION);
+
+  Animation animation = Animation::New(1.0f);
+  animation.AnimateTo(DevelControl::GetVisualProperty(control, Control::Property::BACKGROUND, GradientVisual::Property::START_OFFSET), 1.0f);
+  animation.Play();
+
+  application.SendNotification();
+  application.Render(0);     // Ensure animation starts
+  application.Render(1001u); // A Cycle
+
+  Dali::Property property2 = DevelControl::GetVisualProperty(control, Control::Property::BACKGROUND, GradientVisual::Property::START_OFFSET);
+  DALI_TEST_EQUALS(property2.object.GetProperty(property2.propertyIndex).Get<float>(), 1.0f, TEST_LOCATION);
+
+  END_TEST;
+}
\ No newline at end of file
index 7a2572b55070f5e9cf54dd39b4eb73d63fbbef81..338dc4b042739aac29412305aee792230bf98c3a 100644 (file)
@@ -21,6 +21,7 @@ UNIFORM_BLOCK FragBlock
 {
   // scale factor to fit start and end position of gradient.
   UNIFORM highp float uTextureCoordinateScaleFactor;
+  UNIFORM highp float uGradientOffset;
   UNIFORM lowp vec4 uColor;
 
 #ifdef IS_REQUIRED_BORDERLINE
@@ -255,9 +256,9 @@ void main()
 {
 #ifdef RADIAL
   mediump float radialTexCoord = ((length(vTexCoord) - 0.5) * uTextureCoordinateScaleFactor) + 0.5;
-  lowp vec4 textureColor = TEXTURE(sTexture, vec2(radialTexCoord, 0.5)) * uColor;
+  lowp vec4 textureColor = TEXTURE(sTexture, vec2(radialTexCoord + uGradientOffset, 0.5)) * uColor;
 #else
-  lowp vec4 textureColor = TEXTURE(sTexture, vec2(vTexCoord.y, 0.5)) * uColor;
+  lowp vec4 textureColor = TEXTURE(sTexture, vec2(vTexCoord.y + uGradientOffset, 0.5)) * uColor;
 #endif
 
 #if defined(IS_REQUIRED_ROUNDED_CORNER) || defined(IS_REQUIRED_BORDERLINE)
index abd79628a6aeb5f2eef5fbbc7e8ec0f00bf99cbc..9ffc8d4b3c516ce9508c7058bc1f4ef8b09cc6a3 100644 (file)
@@ -63,6 +63,7 @@ DALI_ENUM_TO_STRING_TABLE_END(SPREAD_METHOD)
 // uniform names
 static constexpr std::string_view UNIFORM_ALIGNMENT_MATRIX_NAME("uAlignmentMatrix");
 static constexpr std::string_view UNIFORM_TEXTURE_COORDINATE_SCALE_FACTOR_NAME("uTextureCoordinateScaleFactor");
+static constexpr std::string_view UNIFORM_START_OFFSET_NAME("uGradientOffset");
 
 // default offset value
 static constexpr float DEFAULT_OFFSET_MINIMUM = 0.0f;
@@ -294,6 +295,9 @@ void GradientVisual::OnInitialize()
   float textureSize = static_cast<float>(lookupTexture.GetWidth());
   mImpl->mRenderer.RegisterUniqueProperty(UNIFORM_TEXTURE_COORDINATE_SCALE_FACTOR_NAME, (textureSize - 1.0f) / textureSize);
 
+  float startOffset = mGradient->GetStartOffset();
+  mStartOffsetIndex = mImpl->mRenderer.RegisterUniqueProperty(Toolkit::GradientVisual::Property::START_OFFSET, UNIFORM_START_OFFSET_NAME, startOffset);
+
   // Register transform properties
   mImpl->SetTransformUniforms(mImpl->mRenderer, Direction::LEFT_TO_RIGHT);
 }
@@ -375,6 +379,13 @@ bool GradientVisual::NewGradient(Type gradientType, const Property::Map& propert
     }
   }
 
+  Property::Value* startOffset = propertyMap.Find(Toolkit::GradientVisual::Property::START_OFFSET, START_OFFSET_NAME);
+  float startOffsetValue;
+  if(startOffset && startOffset->Get(startOffsetValue))
+  {
+    mGradient->SetStartOffset(startOffsetValue);
+  }
+
   return true;
 }
 
index 05c90be4f43a8f085a169803e6f7911de750d434..94b4523706609e85a63928e2115ba2438c2f6ada 100644 (file)
@@ -176,6 +176,7 @@ private:
   Matrix3                mGradientTransform;
   IntrusivePtr<Gradient> mGradient;
   Type                   mGradientType;
+  Dali::Property::Index  mStartOffsetIndex;
   bool                   mIsOpaque; ///< Set to false if any of the stop colors are not opaque
 };
 
index e96cf327b6f1e31712e2a137847b933a2988ecd9..48c8cb42103b6a3f4c57fec428ac9309310fa5ff 100644 (file)
@@ -23,7 +23,7 @@
 namespace
 {
 // The maximum width of the lookup texture ( it is a 1-dimension texture with the height as 1 )
-const unsigned int MAXIMUM_TEXTURE_RESOLUTION(128u);
+const uint32_t MAXIMUM_TEXTURE_RESOLUTION(512u);
 } // namespace
 
 namespace Dali
@@ -34,7 +34,8 @@ namespace Internal
 {
 Gradient::Gradient()
 : mGradientUnits(Toolkit::GradientVisual::Units::OBJECT_BOUNDING_BOX),
-  mSpreadMethod(Toolkit::GradientVisual::SpreadMethod::PAD)
+  mSpreadMethod(Toolkit::GradientVisual::SpreadMethod::PAD),
+  mStartOffset(0.f)
 {
 }
 
@@ -180,23 +181,17 @@ Dali::Texture Gradient::GenerateLookupTexture()
 
 unsigned int Gradient::EstimateTextureResolution()
 {
-  float          minInterval = 1.0;
-  const uint32_t numStops    = mGradientStops.Count();
-  DALI_ASSERT_ALWAYS(numStops > 0u && "The number of gradient stop should not be zero!");
-  for(uint32_t i = 0; i < numStops - 1u; i++)
-  {
-    float interval = mGradientStops[i + 1].mOffset - mGradientStops[i].mOffset;
-    minInterval    = interval > minInterval ? minInterval : interval;
-  }
-  // Use at least three pixels for each segment between two stops
-  unsigned int resolution = static_cast<int>(3.f / (minInterval + Math::MACHINE_EPSILON_100) + 0.5f);
-  // Clamp the resolution to handle the overlapping stops
-  if(resolution > MAXIMUM_TEXTURE_RESOLUTION)
-  {
-    return MAXIMUM_TEXTURE_RESOLUTION;
-  }
+  return MAXIMUM_TEXTURE_RESOLUTION;
+}
 
-  return resolution;
+void Gradient::SetStartOffset(float startOffset)
+{
+  mStartOffset = startOffset;
+}
+
+float Gradient::GetStartOffset() const
+{
+  return mStartOffset;
 }
 
 } // namespace Internal
index f1b154e13d74310c1b5b7533331fefb811c31efa..fe824f219d45b00846b912cf105eb73547ac9939 100644 (file)
@@ -115,6 +115,21 @@ public:
    */
   Dali::Texture GenerateLookupTexture();
 
+  /**
+   * Sets the gradient's start position offset.
+   * @param[in] startOffset The start offset.
+   * @note 0.0 is start position of gradient, 1.0 is end position of gradient.
+   * It is possible to set the startOffset outside the [0, 1] range.
+   * For example, you can animate it from 0.5 to 1.5.
+   */
+  void SetStartOffset(float startOffset);
+
+  /**
+   * Retrieves the gradient's start position offset.
+   * @return The start offset
+   */
+  float GetStartOffset() const;
+
 private:
   /**
    * Estimate the resolution of the lookup texture.
@@ -145,6 +160,7 @@ protected:
   Matrix3                                     mAlignmentTransform;
   Toolkit::GradientVisual::Units::Type        mGradientUnits;
   Toolkit::GradientVisual::SpreadMethod::Type mSpreadMethod;
+  float                                       mStartOffset;
 };
 
 } // namespace Internal
index a54e8ad1d0d936677b95ac5e17d29eda1993b703..020f4c0a0e6e3fb4eb454d83168f5835613f6a9f 100644 (file)
@@ -324,6 +324,7 @@ const char* const STOP_OFFSET_NAME("stopOffset");     // Property::Array FLOAT
 const char* const STOP_COLOR_NAME("stopColor");       // Property::Array VECTOR4
 const char* const UNITS_NAME("units");                // Property::String  "userSpaceOnUse | objectBoundingBox"
 const char* const SPREAD_METHOD_NAME("spreadMethod"); // Property::String  "pad | reflect | repeat"
+const char* const START_OFFSET_NAME("startOffset");   // Property::FLOAT
 
 //mesh visual
 const char* const OBJECT_URL_NAME("objectUrl");
index 936f741f702114df85f9f1e72d90a8a2621ccb3b..3340ec47b962fedd88962495c22e28a2dacf8031 100644 (file)
@@ -190,6 +190,7 @@ extern const char* const STOP_OFFSET_NAME;   // Property::Array FLOAT
 extern const char* const STOP_COLOR_NAME;    // Property::Array VECTOR4
 extern const char* const UNITS_NAME;         // Property::String  "userSpaceOnUse | objectBoundingBox"
 extern const char* const SPREAD_METHOD_NAME; // Property::String  "pad | reflect | repeat"
+extern const char* const START_OFFSET_NAME;  // Property::FLOAT
 
 //mesh visual
 extern const char* const OBJECT_URL_NAME;
index 5e2c6bf9d55dd3387ab44c3374c59b9de0d5524d..84f9b9ea5d0fe1c33aafcfe28d67316605c3976f 100644 (file)
@@ -120,7 +120,15 @@ enum
    * @note Optional. If not supplied, default is SpreadMethod::PAD.
    * @see SpreadMethod::Type
    */
-  SPREAD_METHOD
+  SPREAD_METHOD,
+
+  /**
+   * @brief The offset value that shifts the starting position of the gradient.
+   * @details Name "startOffset", type Property::FLOAT.
+   * @SINCE_2_4.17
+   * @note Optional. If not supplied, default is 0.
+   */
+  START_OFFSET
 };
 
 } // namespace Property