Merge branch 'devel/master' into tizen_6.5
authortscholb <scholb.kim@samsung.com>
Mon, 1 Nov 2021 08:49:16 +0000 (17:49 +0900)
committertscholb <scholb.kim@samsung.com>
Mon, 1 Nov 2021 08:49:16 +0000 (17:49 +0900)
Change-Id: I06e4a1c0a63bdd1ef377f45081eb6fb6fc94b4b9

90 files changed:
automated-tests/resources/broken_l.9.png [new file with mode: 0755]
automated-tests/resources/broken_m.9.png [new file with mode: 0755]
automated-tests/resources/broken_s.9.png [new file with mode: 0755]
automated-tests/resources/test.tvg [new file with mode: 0644]
automated-tests/src/dali-scene-loader/utc-Dali-StringCallback.cpp
automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-application.cpp
automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-application.h
automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-encoded-image-buffer.cpp
automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-graphics-controller.cpp
automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-canvas-renderer.cpp
automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-web-engine.cpp
automated-tests/src/dali-toolkit/utc-Dali-AnimatedVectorImageVisual.cpp
automated-tests/src/dali-toolkit/utc-Dali-ArcVisual.cpp
automated-tests/src/dali-toolkit/utc-Dali-CanvasView.cpp
automated-tests/src/dali-toolkit/utc-Dali-GlView.cpp
automated-tests/src/dali-toolkit/utc-Dali-ImageView.cpp
automated-tests/src/dali-toolkit/utc-Dali-TextLabel.cpp
automated-tests/src/dali-toolkit/utc-Dali-Transition.cpp
automated-tests/src/dali-toolkit/utc-Dali-Visual.cpp
dali-toolkit/devel-api/controls/control-devel.cpp
dali-toolkit/devel-api/controls/control-devel.h
dali-toolkit/devel-api/file.list
dali-toolkit/devel-api/styling/style-manager-devel.cpp
dali-toolkit/devel-api/styling/style-manager-devel.h
dali-toolkit/devel-api/toolkit-action-index-ranges.h [new file with mode: 0644]
dali-toolkit/devel-api/visuals/animated-image-visual-actions-devel.h
dali-toolkit/devel-api/visuals/animated-vector-image-visual-actions-devel.h
dali-toolkit/devel-api/visuals/arc-visual-actions-devel.h [deleted file]
dali-toolkit/devel-api/visuals/image-visual-actions-devel.h
dali-toolkit/devel-api/visuals/visual-actions-devel.h [moved from dali-toolkit/devel-api/visuals/color-visual-actions-devel.h with 60% similarity]
dali-toolkit/internal/controls/canvas-view/canvas-view-impl.cpp
dali-toolkit/internal/controls/canvas-view/canvas-view-impl.h
dali-toolkit/internal/controls/canvas-view/canvas-view-rasterize-thread.cpp
dali-toolkit/internal/controls/canvas-view/canvas-view-rasterize-thread.h
dali-toolkit/internal/controls/control/control-data-impl.cpp
dali-toolkit/internal/controls/control/control-data-impl.h
dali-toolkit/internal/controls/flex-container/flex-container-impl.cpp
dali-toolkit/internal/controls/gl-view/gl-view-impl.cpp
dali-toolkit/internal/controls/gl-view/gl-view-impl.h
dali-toolkit/internal/controls/gl-view/gl-view-render-thread.cpp
dali-toolkit/internal/controls/gl-view/gl-view-render-thread.h
dali-toolkit/internal/controls/image-view/image-view-impl.cpp
dali-toolkit/internal/controls/image-view/image-view-impl.h
dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-impl-constraints.cpp [new file with mode: 0644]
dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-impl-constraints.h [new file with mode: 0644]
dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-impl.cpp
dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-impl.h
dali-toolkit/internal/controls/table-view/table-view-impl.cpp
dali-toolkit/internal/controls/web-view/web-view-impl.cpp
dali-toolkit/internal/file.list
dali-toolkit/internal/graphics/shaders/color-visual-shader.frag
dali-toolkit/internal/graphics/shaders/gradient-visual-shader.frag
dali-toolkit/internal/graphics/shaders/gradient-visual-shader.vert
dali-toolkit/internal/graphics/shaders/image-visual-shader.frag
dali-toolkit/internal/styling/style-manager-impl.cpp
dali-toolkit/internal/styling/style-manager-impl.h
dali-toolkit/internal/text/multi-language-support-impl.cpp
dali-toolkit/internal/text/text-controller.cpp
dali-toolkit/internal/text/text-controller.h
dali-toolkit/internal/transition/transition-impl.cpp
dali-toolkit/internal/transition/transition-impl.h
dali-toolkit/internal/visuals/animated-image/animated-image-visual.cpp
dali-toolkit/internal/visuals/animated-image/animated-image-visual.h
dali-toolkit/internal/visuals/animated-vector-image/animated-vector-image-visual.cpp
dali-toolkit/internal/visuals/animated-vector-image/vector-animation-task.cpp
dali-toolkit/internal/visuals/arc/arc-visual.cpp
dali-toolkit/internal/visuals/arc/arc-visual.h
dali-toolkit/internal/visuals/color/color-visual.cpp
dali-toolkit/internal/visuals/color/color-visual.h
dali-toolkit/internal/visuals/image/image-visual.cpp
dali-toolkit/internal/visuals/npatch-loader.cpp
dali-toolkit/internal/visuals/npatch/npatch-visual.cpp
dali-toolkit/internal/visuals/svg/svg-visual.cpp
dali-toolkit/internal/visuals/visual-base-data-impl.cpp
dali-toolkit/internal/visuals/visual-base-data-impl.h
dali-toolkit/internal/visuals/visual-base-impl.cpp
dali-toolkit/internal/visuals/visual-factory-cache.cpp
dali-toolkit/internal/visuals/visual-factory-cache.h
dali-toolkit/internal/visuals/visual-factory-impl.cpp
dali-toolkit/internal/visuals/visual-factory-impl.h
dali-toolkit/internal/visuals/visual-url.cpp
dali-toolkit/internal/visuals/visual-url.h
dali-toolkit/public-api/controls/control-impl.cpp
dali-toolkit/public-api/controls/control-impl.h
dali-toolkit/public-api/controls/gl-view/gl-view.cpp
dali-toolkit/public-api/controls/gl-view/gl-view.h
dali-toolkit/public-api/dali-toolkit-version.cpp
dali-toolkit/public-api/transition/transition.cpp
dali-toolkit/public-api/transition/transition.h
packaging/dali-toolkit.spec

diff --git a/automated-tests/resources/broken_l.9.png b/automated-tests/resources/broken_l.9.png
new file mode 100755 (executable)
index 0000000..48f6078
Binary files /dev/null and b/automated-tests/resources/broken_l.9.png differ
diff --git a/automated-tests/resources/broken_m.9.png b/automated-tests/resources/broken_m.9.png
new file mode 100755 (executable)
index 0000000..fd99939
Binary files /dev/null and b/automated-tests/resources/broken_m.9.png differ
diff --git a/automated-tests/resources/broken_s.9.png b/automated-tests/resources/broken_s.9.png
new file mode 100755 (executable)
index 0000000..d2fd5fa
Binary files /dev/null and b/automated-tests/resources/broken_s.9.png differ
diff --git a/automated-tests/resources/test.tvg b/automated-tests/resources/test.tvg
new file mode 100644 (file)
index 0000000..78bb48f
Binary files /dev/null and b/automated-tests/resources/test.tvg differ
index acd5183..113f40a 100644 (file)
@@ -41,6 +41,6 @@ int UtcDaliUtilsDefaultStringCallback(void)
 {
   InstallLogFunction(TestLogFunction);
   DefaultErrorCallback("Hello world!");
-  DALI_TEST_EQUAL(std::string(sBuffer), "2: DefaultErrorCallback Hello world!");
+  DALI_TEST_EQUAL(std::string(sBuffer), "2: string-callback.cpp: DefaultErrorCallback(26) > Hello world!");
   END_TEST;
 }
index 5e69c95..440270a 100644 (file)
@@ -19,6 +19,8 @@
 
 namespace Dali
 {
+const Rect<int> TestApplication::DEFAULT_SURFACE_RECT = Rect<int>(0, 0, TestApplication::DEFAULT_SURFACE_WIDTH, TestApplication::DEFAULT_SURFACE_HEIGHT);
+
 bool TestApplication::mLoggingEnabled = true;
 
 TestApplication::TestApplication(uint32_t surfaceWidth,
@@ -225,7 +227,7 @@ bool TestApplication::PreRenderWithPartialUpdate(uint32_t intervalMilliseconds,
 
 bool TestApplication::RenderWithPartialUpdate(std::vector<Rect<int>>& damagedRects, Rect<int>& clippingRect)
 {
-  mCore->RenderScene(mRenderStatus, mScene, true /*render the off-screen buffers*/, clippingRect);
+  mCore->RenderScene(mRenderStatus, mScene, true /*render the off-screen buffers*/);
   mCore->RenderScene(mRenderStatus, mScene, false /*render the surface*/, clippingRect);
   mCore->PostRender(false /*do not skip rendering*/);
 
index 4f32cd8..02143a7 100644 (file)
@@ -38,6 +38,8 @@ public:
   static const uint32_t DEFAULT_SURFACE_WIDTH  = 480;
   static const uint32_t DEFAULT_SURFACE_HEIGHT = 800;
 
+  static const Rect<int> DEFAULT_SURFACE_RECT;
+
   static constexpr uint32_t DEFAULT_HORIZONTAL_DPI = 220;
   static constexpr uint32_t DEFAULT_VERTICAL_DPI   = 217;
 
index e693098..ef389ed 100644 (file)
@@ -33,8 +33,9 @@ EncodedImageBuffer ConvertFileToEncodedImageBuffer(const char* url)
     Dali::Vector<uint8_t> data;
     data.Resize(size);
     fseek(fp, 0, SEEK_SET);
-    fread(data.Begin(), size, sizeof(uint8_t), fp);
+    size_t realSize = fread(data.Begin(), sizeof(uint8_t), size, fp);
     fclose(fp);
+    data.Resize(realSize);
     buffer = EncodedImageBuffer::New(data);
   }
   return buffer;
index 0886719..d2d8b16 100644 (file)
@@ -379,8 +379,81 @@ GLenum GetBlendOp(Graphics::BlendOp blendOp)
     case Graphics::BlendOp::MAX:
       op = GL_MAX;
       break;
-
-      // @todo Add advanced blend equations
+    case Graphics::BlendOp::MULTIPLY:
+    {
+      op = GL_MULTIPLY;
+      break;
+    }
+    case Graphics::BlendOp::SCREEN:
+    {
+      op = GL_SCREEN;
+      break;
+    }
+    case Graphics::BlendOp::OVERLAY:
+    {
+      op = GL_OVERLAY;
+      break;
+    }
+    case Graphics::BlendOp::DARKEN:
+    {
+      op = GL_DARKEN;
+      break;
+    }
+    case Graphics::BlendOp::LIGHTEN:
+    {
+      op = GL_LIGHTEN;
+      break;
+    }
+    case Graphics::BlendOp::COLOR_DODGE:
+    {
+      op = GL_COLORDODGE;
+      break;
+    }
+    case Graphics::BlendOp::COLOR_BURN:
+    {
+      op = GL_COLORBURN;
+      break;
+    }
+    case Graphics::BlendOp::HARD_LIGHT:
+    {
+      op = GL_HARDLIGHT;
+      break;
+    }
+    case Graphics::BlendOp::SOFT_LIGHT:
+    {
+      op = GL_SOFTLIGHT;
+      break;
+    }
+    case Graphics::BlendOp::DIFFERENCE:
+    {
+      op = GL_DIFFERENCE;
+      break;
+    }
+    case Graphics::BlendOp::EXCLUSION:
+    {
+      op = GL_EXCLUSION;
+      break;
+    }
+    case Graphics::BlendOp::HUE:
+    {
+      op = GL_HSL_HUE;
+      break;
+    }
+    case Graphics::BlendOp::SATURATION:
+    {
+      op = GL_HSL_SATURATION;
+      break;
+    }
+    case Graphics::BlendOp::COLOR:
+    {
+      op = GL_HSL_COLOR;
+      break;
+    }
+    case Graphics::BlendOp::LUMINOSITY:
+    {
+      op = GL_HSL_LUMINOSITY;
+      break;
+    }
   }
   return op;
 }
index 56c0cd8..43aa8ce 100644 (file)
@@ -39,7 +39,7 @@ class CanvasRenderer: public Dali::BaseObject
 public:
   CanvasRenderer( const Vector2& size )
   : mDrawable(nullptr),
-    mPixelBuffer( Devel::PixelBuffer::New(size.width, size.height, Dali::Pixel::RGBA8888) ),
+    mTexture ( Dali::Texture::New( Dali::TextureType::TEXTURE_2D, Pixel::RGBA8888, size.width, size.height ) ),
     mSize(size),
     mViewBox(size)
   {
@@ -59,6 +59,11 @@ public:
      return true;
   }
 
+  Dali::Texture GetRasterizedTexture()
+  {
+    return mTexture;
+  }
+
   bool Rasterize()
   {
      return true;
@@ -97,12 +102,6 @@ public:
     return false;
   }
 
-  Devel::PixelBuffer GetPixelBuffer()
-  {
-    return mPixelBuffer;
-  }
-
-
   bool SetSize(Vector2 size)
   {
     mSize = size;
@@ -137,7 +136,7 @@ public:
 
 public:
    Dali::CanvasRenderer::Drawable* mDrawable;
-   Devel::PixelBuffer mPixelBuffer;
+   Dali::Texture mTexture;
    Vector2 mSize;
    Vector2 mViewBox;
 };
@@ -200,9 +199,9 @@ bool CanvasRenderer::Rasterize()
   return Internal::Adaptor::GetImplementation(*this).Rasterize();
 }
 
-Devel::PixelBuffer CanvasRenderer::GetPixelBuffer()
+Dali::Texture CanvasRenderer::GetRasterizedTexture()
 {
-  return Internal::Adaptor::GetImplementation(*this).GetPixelBuffer();
+  return Internal::Adaptor::GetImplementation(*this).GetRasterizedTexture();
 }
 
 bool CanvasRenderer::AddDrawable(Dali::CanvasRenderer::Drawable& drawable)
index 8f8853c..cd863b9 100755 (executable)
@@ -2056,7 +2056,7 @@ std::string WebEngine::GetUrl() const
   return Internal::Adaptor::GetImplementation( *this ).GetUrl();
 }
 
-NativeImageInterfacePtr WebEngine::GetNativeImageSource()
+NativeImageSourcePtr WebEngine::GetNativeImageSource()
 {
   Any source;
   Dali::NativeImageSourcePtr sourcePtr = Dali::NativeImageSource::New( source );
index 7f43240..1eb713e 100644 (file)
@@ -27,6 +27,7 @@
 #include <dali-toolkit/devel-api/controls/control-devel.h>
 #include <dali-toolkit/devel-api/visuals/visual-properties-devel.h>
 #include <dali-toolkit/devel-api/visuals/image-visual-properties-devel.h>
+#include <dali-toolkit/devel-api/visuals/visual-actions-devel.h>
 #include <dali-toolkit/devel-api/visuals/animated-vector-image-visual-actions-devel.h>
 #include <dali-toolkit/devel-api/visuals/animated-vector-image-visual-signals-devel.h>
 #include <dali/devel-api/rendering/renderer-devel.h>
@@ -707,7 +708,7 @@ int UtcDaliAnimatedVectorImageVisualPlayRange(void)
 
   attributes.Clear();
   attributes.Add( DevelImageVisual::Property::PLAY_RANGE, array );
-  DevelControl::DoAction( actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedVectorImageVisual::Action::UPDATE_PROPERTY, attributes );
+  DevelControl::DoAction( actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelVisual::Action::UPDATE_PROPERTY, attributes );
 
   application.SendNotification();
   application.Render();
@@ -746,7 +747,7 @@ int UtcDaliAnimatedVectorImageVisualPlayRange(void)
 
   attributes.Clear();
   attributes.Add( DevelImageVisual::Property::PLAY_RANGE, array );
-  DevelControl::DoAction( actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedVectorImageVisual::Action::UPDATE_PROPERTY, attributes );
+  DevelControl::DoAction( actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelVisual::Action::UPDATE_PROPERTY, attributes );
 
   application.SendNotification();
   application.Render();
@@ -825,7 +826,7 @@ int UtcDaliAnimatedVectorImageVisualPlayRangeMarker(void)
 
   attributes.Clear();
   attributes.Add( DevelImageVisual::Property::PLAY_RANGE, array );
-  DevelControl::DoAction( actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedVectorImageVisual::Action::UPDATE_PROPERTY, attributes );
+  DevelControl::DoAction( actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelVisual::Action::UPDATE_PROPERTY, attributes );
 
   application.SendNotification();
   application.Render();
@@ -849,7 +850,7 @@ int UtcDaliAnimatedVectorImageVisualPlayRangeMarker(void)
 
   attributes.Clear();
   attributes.Add( DevelImageVisual::Property::PLAY_RANGE, array );
-  DevelControl::DoAction( actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedVectorImageVisual::Action::UPDATE_PROPERTY, attributes );
+  DevelControl::DoAction( actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelVisual::Action::UPDATE_PROPERTY, attributes );
 
   application.SendNotification();
   application.Render();
@@ -956,7 +957,7 @@ int UtcDaliAnimatedVectorImageVisualJumpTo(void)
 
   Property::Map attributes;
   attributes.Add( DevelImageVisual::Property::PLAY_RANGE, array );
-  DevelControl::DoAction( actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedVectorImageVisual::Action::UPDATE_PROPERTY, attributes );
+  DevelControl::DoAction( actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelVisual::Action::UPDATE_PROPERTY, attributes );
 
   DevelControl::DoAction( actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedVectorImageVisual::Action::JUMP_TO, 3 );
 
@@ -979,7 +980,7 @@ int UtcDaliAnimatedVectorImageVisualJumpTo(void)
   array.PushBack( 4 );
 
   attributes.Add( DevelImageVisual::Property::PLAY_RANGE, array );
-  DevelControl::DoAction( actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedVectorImageVisual::Action::UPDATE_PROPERTY, attributes );
+  DevelControl::DoAction( actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelVisual::Action::UPDATE_PROPERTY, attributes );
 
   attributes.Clear();
   DevelControl::DoAction( actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedVectorImageVisual::Action::PLAY, attributes );
@@ -1074,7 +1075,7 @@ int UtcDaliAnimatedVectorImageVisualUpdateProperty(void)
   attributes.Add( DevelImageVisual::Property::PLAY_RANGE, playRange );
   attributes.Add( DevelImageVisual::Property::LOOP_COUNT, 5 );
 
-  DevelControl::DoAction( actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedVectorImageVisual::Action::UPDATE_PROPERTY, attributes );
+  DevelControl::DoAction( actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelVisual::Action::UPDATE_PROPERTY, attributes );
 
   application.SendNotification();
   application.Render();
@@ -1100,7 +1101,7 @@ int UtcDaliAnimatedVectorImageVisualUpdateProperty(void)
 
   attributes.Add( DevelImageVisual::Property::PLAY_RANGE, playRange );
 
-  DevelControl::DoAction( actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedVectorImageVisual::Action::UPDATE_PROPERTY, attributes );
+  DevelControl::DoAction( actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelVisual::Action::UPDATE_PROPERTY, attributes );
 
   application.SendNotification();
   application.Render();
@@ -1125,7 +1126,7 @@ int UtcDaliAnimatedVectorImageVisualUpdateProperty(void)
 
   attributes.Add( DevelImageVisual::Property::LOOP_COUNT, 10 );
 
-  DevelControl::DoAction( actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedVectorImageVisual::Action::UPDATE_PROPERTY, attributes );
+  DevelControl::DoAction( actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelVisual::Action::UPDATE_PROPERTY, attributes );
 
   application.SendNotification();
   application.Render();
@@ -1176,7 +1177,7 @@ int UtcDaliAnimatedVectorImageVisualStopBehavior(void)
   // Change stop behavior
   attributes.Add( DevelImageVisual::Property::STOP_BEHAVIOR, DevelImageVisual::StopBehavior::LAST_FRAME );
 
-  DevelControl::DoAction( actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedVectorImageVisual::Action::UPDATE_PROPERTY, attributes );
+  DevelControl::DoAction( actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelVisual::Action::UPDATE_PROPERTY, attributes );
 
   attributes.Clear();
 
@@ -1201,7 +1202,7 @@ int UtcDaliAnimatedVectorImageVisualStopBehavior(void)
   attributes.Add( DevelImageVisual::Property::STOP_BEHAVIOR, DevelImageVisual::StopBehavior::CURRENT_FRAME );
   attributes.Add( DevelImageVisual::Property::LOOP_COUNT, -1 );
 
-  DevelControl::DoAction( actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedVectorImageVisual::Action::UPDATE_PROPERTY, attributes );
+  DevelControl::DoAction( actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelVisual::Action::UPDATE_PROPERTY, attributes );
 
   attributes.Clear();
 
@@ -1271,7 +1272,7 @@ int UtcDaliAnimatedVectorImageVisualLoopingMode(void)
   // Change stop behavior
   attributes.Add( DevelImageVisual::Property::STOP_BEHAVIOR, DevelImageVisual::StopBehavior::CURRENT_FRAME );
 
-  DevelControl::DoAction( actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedVectorImageVisual::Action::UPDATE_PROPERTY, attributes );
+  DevelControl::DoAction( actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelVisual::Action::UPDATE_PROPERTY, attributes );
 
   // Play again
   DevelControl::DoAction( actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedVectorImageVisual::Action::PLAY, attributes );
@@ -1289,7 +1290,7 @@ int UtcDaliAnimatedVectorImageVisualLoopingMode(void)
   // Change looping mode
   attributes.Add( DevelImageVisual::Property::LOOPING_MODE, DevelImageVisual::LoopingMode::RESTART );
 
-  DevelControl::DoAction( actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedVectorImageVisual::Action::UPDATE_PROPERTY, attributes );
+  DevelControl::DoAction( actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelVisual::Action::UPDATE_PROPERTY, attributes );
 
   // Play again
   DevelControl::DoAction( actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedVectorImageVisual::Action::PLAY, attributes );
@@ -1418,8 +1419,8 @@ int UtcDaliAnimatedVectorImageVisualMultipleInstances(void)
   Property::Map attributes;
   attributes.Add( DevelImageVisual::Property::STOP_BEHAVIOR, DevelImageVisual::StopBehavior::LAST_FRAME );
 
-  DevelControl::DoAction( actor1, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedVectorImageVisual::Action::UPDATE_PROPERTY, attributes );
-  DevelControl::DoAction( actor2, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedVectorImageVisual::Action::UPDATE_PROPERTY, attributes );
+  DevelControl::DoAction( actor1, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelVisual::Action::UPDATE_PROPERTY, attributes );
+  DevelControl::DoAction( actor2, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelVisual::Action::UPDATE_PROPERTY, attributes );
 
   DevelControl::DoAction( actor1, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedVectorImageVisual::Action::PLAY, Property::Map() );
 
index 583ce16..146a1b5 100644 (file)
@@ -22,7 +22,7 @@
 #include <dali-toolkit/devel-api/controls/control-devel.h>
 #include <dali-toolkit/devel-api/visuals/visual-properties-devel.h>
 #include <dali-toolkit/devel-api/visuals/arc-visual-properties-devel.h>
-#include <dali-toolkit/devel-api/visuals/arc-visual-actions-devel.h>
+#include <dali-toolkit/devel-api/visuals/visual-actions-devel.h>
 #include <dali/devel-api/rendering/renderer-devel.h>
 #include "dummy-control.h"
 
@@ -307,7 +307,7 @@ int UtcDaliArcVisualUpdateProperty(void)
             .Add( DevelArcVisual::Property::START_ANGLE, startAngle )
             .Add( DevelArcVisual::Property::SWEEP_ANGLE, sweepAngle );
 
-  DevelControl::DoAction( actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelArcVisual::Action::UPDATE_PROPERTY, attributes );
+  DevelControl::DoAction( actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelVisual::Action::UPDATE_PROPERTY, attributes );
 
   application.SendNotification();
   application.Render();
index 36cf1df..cee41e0 100644 (file)
@@ -302,42 +302,6 @@ int UtcDaliCanvasViewRasterizeTaskGetCanvasViewP(void)
   END_TEST;
 }
 
-int UtcDaliCanvasViewRasterizeTaskGetBufferSizeP(void)
-{
-  ToolkitTestApplication application;
-
-  Dali::Toolkit::Internal::CanvasView* dummyInternalCanvasView = new Dali::Toolkit::Internal::CanvasView(Vector2(100,100));
-  DALI_TEST_CHECK( dummyInternalCanvasView );
-
-  Dali::CanvasRenderer dummyCanvasRenderer = Dali::CanvasRenderer::New(Vector2(100, 100));
-  DALI_TEST_CHECK( dummyCanvasRenderer );
-
-  IntrusivePtr<Dali::Toolkit::Internal::CanvasRendererRasterizingTask> task = new Dali::Toolkit::Internal::CanvasRendererRasterizingTask(dummyInternalCanvasView, dummyCanvasRenderer);
-  DALI_TEST_CHECK( task );
-
-  //There is no rasterized buffer.
-  DALI_TEST_EQUALS( task->GetBufferSize(), Vector2(0, 0), TEST_LOCATION );
-
-  END_TEST;
-}
-
-int UtcDaliCanvasViewRasterizeTaskGetPixelDataP(void)
-{
-
-  Dali::Toolkit::Internal::CanvasView* dummyInternalCanvasView = new Dali::Toolkit::Internal::CanvasView(Vector2(100,100));
-  DALI_TEST_CHECK( dummyInternalCanvasView );
-
-  Dali::CanvasRenderer dummyCanvasRenderer = Dali::CanvasRenderer::New(Vector2(100, 100));
-  DALI_TEST_CHECK( dummyCanvasRenderer );
-
-  IntrusivePtr<Dali::Toolkit::Internal::CanvasRendererRasterizingTask> task = new Dali::Toolkit::Internal::CanvasRendererRasterizingTask(dummyInternalCanvasView, dummyCanvasRenderer);
-  DALI_TEST_CHECK( task );
-
-  DALI_TEST_EQUALS( task->GetPixelData(), PixelData(), TEST_LOCATION );
-
-  END_TEST;
-}
-
 int UtcDaliCanvasViewRasterizeThreadP(void)
 {
   ToolkitTestApplication application;
@@ -488,13 +452,13 @@ int UtcDaliCanvasViewRasterizeThreadRasterizationCompletedSignalP(void)
 {
   ToolkitTestApplication application;
 
-  Dali::Toolkit::Internal::CanvasView* dummyInternalCanvasView = new Dali::Toolkit::Internal::CanvasView(Vector2(100,100));
-  DALI_TEST_CHECK( dummyInternalCanvasView );
+  Dali::Toolkit::CanvasView canvasView = Dali::Toolkit::CanvasView::New(Vector2(100, 100));
+  Dali::Toolkit::Internal::CanvasView& dummyInternalCanvasView = GetImpl(canvasView);
 
   Dali::CanvasRenderer dummyCanvasRenderer = Dali::CanvasRenderer::New(Vector2(100, 100));
   DALI_TEST_CHECK( dummyCanvasRenderer );
 
-  IntrusivePtr<Dali::Toolkit::Internal::CanvasRendererRasterizingTask> task = new Dali::Toolkit::Internal::CanvasRendererRasterizingTask(dummyInternalCanvasView, dummyCanvasRenderer);
+  IntrusivePtr<Dali::Toolkit::Internal::CanvasRendererRasterizingTask> task = new Dali::Toolkit::Internal::CanvasRendererRasterizingTask(&dummyInternalCanvasView, dummyCanvasRenderer);
   DALI_TEST_CHECK( task );
 
   Dali::Toolkit::Internal::CanvasViewRasterizeThread *dummyThread = new Dali::Toolkit::Internal::CanvasViewRasterizeThread();
@@ -504,10 +468,10 @@ int UtcDaliCanvasViewRasterizeThreadRasterizationCompletedSignalP(void)
 
   dummyThread->Process(false);
 
-  PixelData pixelData = CreatePixelData( 100, 100 );
+  auto texture = Texture::New( Dali::TextureType::TEXTURE_2D, Pixel::RGBA8888, 100, 100 );
 
-  dummyThread->RasterizationCompletedSignal().Connect(dummyInternalCanvasView, &Dali::Toolkit::Internal::CanvasView::ApplyRasterizedImage);
-  dummyThread->RasterizationCompletedSignal().Emit(pixelData);
+  dummyThread->RasterizationCompletedSignal().Connect(&dummyInternalCanvasView, &Dali::Toolkit::Internal::CanvasView::ApplyRasterizedImage);
+  dummyThread->RasterizationCompletedSignal().Emit(texture);
 
   application.SendNotification();
   application.Render();
index 9f74b72..9cefe16 100644 (file)
@@ -181,15 +181,15 @@ void resizeCB(Vector2 size)
 {
 }
 
-int UtcDaliGlViewRegisterGlCallbackN(void)
+int UtcDaliGlViewRegisterGlCallbacksN(void)
 {
   ToolkitTestApplication application;
-  tet_infoline("UtcDaliGlViewRegisterGlCallback");
+  tet_infoline("UtcDaliGlViewRegisterGlCallbacksN");
   GlView view;
 
   try
   {
-    view.RegisterGlCallback(Dali::MakeCallback(glInit), Dali::MakeCallback(glRenderFrame), Dali::MakeCallback(glTerminate));
+    view.RegisterGlCallbacks(Dali::MakeCallback(glInit), Dali::MakeCallback(glRenderFrame), Dali::MakeCallback(glTerminate));
     DALI_TEST_CHECK(false);
   }
   catch(...)
@@ -243,7 +243,7 @@ int UtcDaliGlViewWindowVisibilityChanged(void)
   application.GetScene().Add( view );
   view.SetRenderingMode(GlView::RenderingMode::CONTINUOUS);
   view.SetGraphicsConfig(true, true, 0, GlView::GraphicsApiVersion::GLES_VERSION_2_0);
-  view.RegisterGlCallback(Dali::MakeCallback(glInit), Dali::MakeCallback(glRenderFrame), Dali::MakeCallback(glTerminate));
+  view.RegisterGlCallbacks(Dali::MakeCallback(glInit), Dali::MakeCallback(glRenderFrame), Dali::MakeCallback(glTerminate));
   view.SetResizeCallback(Dali::MakeCallback(resizeCB));
 
   application.SendNotification();
@@ -268,7 +268,7 @@ int UtcDaliGlViewOnScene(void)
   application.GetScene().Add( view );
   view.SetRenderingMode(GlView::RenderingMode::CONTINUOUS);
   view.SetGraphicsConfig(true, true, 0, GlView::GraphicsApiVersion::GLES_VERSION_2_0);
-  view.RegisterGlCallback(Dali::MakeCallback(glInit), Dali::MakeCallback(glRenderFrame), Dali::MakeCallback(glTerminate));
+  view.RegisterGlCallbacks(Dali::MakeCallback(glInit), Dali::MakeCallback(glRenderFrame), Dali::MakeCallback(glTerminate));
 
   application.SendNotification();
   application.Render();
@@ -314,7 +314,7 @@ int UtcDaliGlViewResize(void)
 
   application.GetScene().Add( view );
   view.SetGraphicsConfig(true, true, 0, GlView::GraphicsApiVersion::GLES_VERSION_2_0);
-  view.RegisterGlCallback(Dali::MakeCallback(glInit), Dali::MakeCallback(glRenderFrame), Dali::MakeCallback(glTerminate));
+  view.RegisterGlCallbacks(Dali::MakeCallback(glInit), Dali::MakeCallback(glRenderFrame), Dali::MakeCallback(glTerminate));
   view.SetResizeCallback(Dali::MakeCallback(resizeCB));
   view.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
   view.SetProperty(Actor::Property::SIZE, Vector2(360.0f, 360.0f));
index 0450040..e8dd77e 100644 (file)
@@ -30,6 +30,7 @@
 #include <dali-toolkit/devel-api/visuals/visual-properties-devel.h>
 #include <dali-toolkit/public-api/image-loader/image.h>
 #include <dali-toolkit/public-api/image-loader/image-url.h>
+#include <dali-toolkit/devel-api/styling/style-manager-devel.h>
 
 #include <test-native-image.h>
 #include <test-encoded-image-buffer.h>
@@ -61,6 +62,13 @@ const char* TEST_IMAGE_FILE_NAME2 =  "gallery_image_02.jpg";
 const char* TEST_IMAGE_1 = TEST_RESOURCE_DIR "/TB-gloss.png";
 const char* TEST_IMAGE_2 = TEST_RESOURCE_DIR "/tb-norm.png";
 
+const char* TEST_BROKEN_IMAGE_DEFAULT = TEST_RESOURCE_DIR "/broken.png";
+const char* TEST_BROKEN_IMAGE_S = TEST_RESOURCE_DIR "/broken_s.9.png";
+const char* TEST_BROKEN_IMAGE_M = TEST_RESOURCE_DIR "/broken_m.9.png";
+const char* TEST_BROKEN_IMAGE_L = TEST_RESOURCE_DIR "/broken_l.9.png";
+const char* TEST_BROKEN_IMAGE_01 =  TEST_RESOURCE_DIR "/button-up.9.png";
+const char* TEST_BROKEN_IMAGE_02 =  TEST_RESOURCE_DIR "/heartsframe.9.png";
+
 // resolution: 34*34, pixel format: RGBA8888
 static const char* gImage_34_RGBA = TEST_RESOURCE_DIR "/icon-edit.png";
 // resolution: 600*600, pixel format: RGB888
@@ -2883,6 +2891,116 @@ int UtcDaliImageViewSvgRasterizationFailure(void)
   END_TEST;
 }
 
+int UtcDaliImageViewTVGLoading(void)
+{
+  ToolkitTestApplication application;
+
+  tet_infoline("ImageView Testing TVG image loading");
+
+  {
+    ImageView imageView = ImageView::New( );
+
+    imageView.SetImage( TEST_RESOURCE_DIR "/test.tvg" );
+
+    application.GetScene().Add( imageView );
+    DALI_TEST_CHECK( imageView );
+    Vector3 naturalSize = imageView.GetNaturalSize();
+
+    DALI_TEST_EQUALS( naturalSize.width, 100.0f, TEST_LOCATION );
+    DALI_TEST_EQUALS( naturalSize.height, 100.0f, TEST_LOCATION );
+  }
+  END_TEST;
+}
+int UtcDaliImageViewImageLoadFailure01(void)
+{
+  ToolkitTestApplication application;
+
+  Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
+  DevelStyleManager::SetBrokenImageUrl(styleManager, DevelStyleManager::BrokenImageType::SMALL, TEST_BROKEN_IMAGE_S);
+  DevelStyleManager::SetBrokenImageUrl(styleManager, DevelStyleManager::BrokenImageType::NORMAL, TEST_BROKEN_IMAGE_M);
+  DevelStyleManager::SetBrokenImageUrl(styleManager, DevelStyleManager::BrokenImageType::LARGE, TEST_BROKEN_IMAGE_L);
+
+  std::string brokenUrl;
+  brokenUrl = DevelStyleManager::GetBrokenImageUrl(styleManager, DevelStyleManager::BrokenImageType::SMALL);
+  DALI_TEST_EQUALS( TEST_BROKEN_IMAGE_S, brokenUrl, TEST_LOCATION);
+
+  brokenUrl = DevelStyleManager::GetBrokenImageUrl(styleManager, DevelStyleManager::BrokenImageType::NORMAL);
+  DALI_TEST_EQUALS( TEST_BROKEN_IMAGE_M, brokenUrl, TEST_LOCATION);
+
+  brokenUrl = DevelStyleManager::GetBrokenImageUrl(styleManager, DevelStyleManager::BrokenImageType::LARGE);
+  DALI_TEST_EQUALS( TEST_BROKEN_IMAGE_L, brokenUrl, TEST_LOCATION);
+
+  ImageView imageView = ImageView::New("invalidUrl.png");
+  imageView.SetProperty( Actor::Property::SIZE, Vector2( 200.f, 200.f ) );
+
+  application.GetScene().Add( imageView );
+  application.SendNotification();
+  application.Render(16);
+
+  // loading started, this waits for the loader thread
+  DALI_TEST_EQUALS( Test::WaitForEventThreadTrigger( 1 ), true, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliImageViewImageLoadFailure02(void)
+{
+  ToolkitTestApplication application;
+
+  Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
+  DevelStyleManager::SetBrokenImageUrl(styleManager, DevelStyleManager::BrokenImageType::SMALL, TEST_BROKEN_IMAGE_DEFAULT);
+  DevelStyleManager::SetBrokenImageUrl(styleManager, DevelStyleManager::BrokenImageType::NORMAL, TEST_BROKEN_IMAGE_M);
+  DevelStyleManager::SetBrokenImageUrl(styleManager, DevelStyleManager::BrokenImageType::LARGE, TEST_BROKEN_IMAGE_L);
+
+  std::string brokenUrl;
+  brokenUrl = DevelStyleManager::GetBrokenImageUrl(styleManager, DevelStyleManager::BrokenImageType::SMALL);
+  DALI_TEST_EQUALS( TEST_BROKEN_IMAGE_DEFAULT, brokenUrl, TEST_LOCATION);
+
+  brokenUrl = DevelStyleManager::GetBrokenImageUrl(styleManager, DevelStyleManager::BrokenImageType::NORMAL);
+  DALI_TEST_EQUALS( TEST_BROKEN_IMAGE_M, brokenUrl, TEST_LOCATION);
+
+  brokenUrl = DevelStyleManager::GetBrokenImageUrl(styleManager, DevelStyleManager::BrokenImageType::LARGE);
+  DALI_TEST_EQUALS( TEST_BROKEN_IMAGE_L, brokenUrl, TEST_LOCATION);
+
+  ImageView imageView = ImageView::New("invalidUrl.png");
+  imageView.SetProperty( Actor::Property::SIZE, Vector2( 30.f, 30.f ) );
+  application.GetScene().Add( imageView );
+  application.SendNotification();
+  application.Render(16);
+
+  // loading started, this waits for the loader thread
+  DALI_TEST_EQUALS( Test::WaitForEventThreadTrigger( 1 ), true, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliImageViewImageLoadFailure03(void)
+{
+  ToolkitTestApplication application;
+
+  Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
+  DevelStyleManager::SetBrokenImageUrl(styleManager, DevelStyleManager::BrokenImageType::SMALL, TEST_BROKEN_IMAGE_01);
+  DevelStyleManager::SetBrokenImageUrl(styleManager, DevelStyleManager::BrokenImageType::NORMAL, TEST_BROKEN_IMAGE_02);
+
+  std::string brokenUrl;
+  brokenUrl = DevelStyleManager::GetBrokenImageUrl(styleManager, DevelStyleManager::BrokenImageType::SMALL);
+  DALI_TEST_EQUALS( TEST_BROKEN_IMAGE_01, brokenUrl, TEST_LOCATION);
+
+  brokenUrl = DevelStyleManager::GetBrokenImageUrl(styleManager, DevelStyleManager::BrokenImageType::NORMAL);
+  DALI_TEST_EQUALS( TEST_BROKEN_IMAGE_02, brokenUrl, TEST_LOCATION);
+
+  ImageView imageView = ImageView::New("invalidUrl.png");
+  imageView.SetProperty( Actor::Property::SIZE, Vector2( 100.f, 100.f ) );
+  application.GetScene().Add( imageView );
+  application.SendNotification();
+  application.Render(16);
+
+  // loading started, this waits for the loader thread
+  DALI_TEST_EQUALS( Test::WaitForEventThreadTrigger( 1 ), true, TEST_LOCATION );
+
+  END_TEST;
+}
+
 namespace
 {
 
index 5495c9d..c9453e1 100644 (file)
@@ -836,6 +836,13 @@ int UtcDaliToolkitTextLabelEmojisP(void)
   application.SendNotification();
   application.Render();
 
+  // EMOJI + ZWJ + EMOJI case for coverage.
+  const std::string emojiWithZWJ = "&#x1f469;&#x200d;&#x1f52c;";
+  label.SetProperty( TextLabel::Property::TEXT, emojiWithZWJ );
+
+  application.SendNotification();
+  application.Render();
+
   END_TEST;
 }
 
index 7e36d2c..ef1eb2c 100755 (executable)
@@ -118,7 +118,7 @@ int UtcDaliTransitionSetGetProperty01(void)
   application.SendNotification();
   application.Render(20);
 
-  Transition transition = Transition::New(control1, control2, TimePeriod(-0.1f, -0.1f));
+  Transition transition = Transition::New(control1, control2, true, TimePeriod(-0.1f, -0.1f));
   TimePeriod timePeriod = transition.GetTimePeriod();
   DALI_TEST_EQUALS(0.0f, timePeriod.durationSeconds, TEST_LOCATION);
   DALI_TEST_EQUALS(0.0f, timePeriod.delaySeconds, TEST_LOCATION);
@@ -178,7 +178,7 @@ int UtcDaliTransitionSetGetProperty02(void)
   application.SendNotification();
   application.Render(20);
 
-  Transition transition = Transition::New(control1, control2, TimePeriod(-0.1f));
+  Transition transition = Transition::New(control1, control2, true, TimePeriod(-0.1f));
   TimePeriod timePeriod = transition.GetTimePeriod();
   DALI_TEST_EQUALS(0.0f, timePeriod.durationSeconds, TEST_LOCATION);
   DALI_TEST_EQUALS(0.0f, timePeriod.delaySeconds, TEST_LOCATION);
@@ -268,7 +268,7 @@ int UtcDaliTransitionBetweenControlPair(void)
   application.SendNotification();
   application.Render(20);
 
-  Transition transition = Transition::New(control1, control2, TimePeriod(0.5f));
+  Transition transition = Transition::New(control1, control2, true, TimePeriod(0.5f));
   TransitionSet transitionSet = TransitionSet::New();
   transitionSet.AddTransition(transition);
   transitionSet.Play();
@@ -333,6 +333,185 @@ int UtcDaliTransitionBetweenControlPair(void)
   END_TEST;
 }
 
+int UtcDaliTransitionBetweenControlPair2(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliTransitionBetweenControlPair2 - source target will be transitioned.");
+
+  Vector3 sourcePosition(100, 200, 0);
+  Vector3 sourceSize(150, 150, 0);
+  Vector3 sourceScale(1, 2, 0);
+  Vector4 sourceColor(1.0f, 1.0f, 1.0f, 0.5f);
+  float sourceOpacity(0.5f);
+  float sourceRadius(30.f);
+  float sourceBorderlineWidth(60.0f);
+  Vector4 sourceBorderlineColor(1.0f, 0.0f, 0.0f, 1.0f);
+  float sourceBorderlineOffset(1.f);
+  Vector4 sourceRadiusV4 = Vector4(sourceRadius, sourceRadius, sourceRadius, sourceRadius);
+
+  Vector3 destinationPosition(50, 50, 0);
+  Vector3 destinationSize(120, 120, 0);
+  Vector3 destinationScale(2, 1, 0);
+  Vector4 destinationColor(1.0f, 0.5f, 1.0f, 0.8f);
+  float destinationOpacity(0.8f);
+  float destinationRadius(50.f);
+  float destinationBorderlineWidth(80.0f);
+  Vector4 destinationBorderlineColor(0.5f, 1.0f, 0.5f, 0.3f);
+  float destinationBorderlineOffset(-1.0f);
+  Vector4 destinationRadiusV4 = Vector4(destinationRadius, destinationRadius, destinationRadius, destinationRadius);
+
+  Control control1 = Control::New();
+  control1.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+  control1.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
+  control1.SetProperty(Actor::Property::POSITION, sourcePosition);
+  control1.SetProperty(Actor::Property::SIZE, sourceSize);
+  control1.SetProperty(Actor::Property::SCALE, sourceScale);
+  control1.SetProperty(Actor::Property::COLOR, sourceColor);
+  control1.SetProperty(Actor::Property::OPACITY, sourceOpacity);
+  Property::Map controlProperty1;
+  controlProperty1.Insert(Toolkit::Visual::Property::TYPE, Toolkit::Visual::COLOR);
+  controlProperty1.Insert(Toolkit::ColorVisual::Property::MIX_COLOR, Vector4(1.0f, 0.0f, 0.0f, 1.0f));
+  controlProperty1.Insert(Toolkit::DevelVisual::Property::CORNER_RADIUS, sourceRadius);
+  controlProperty1.Insert(Toolkit::DevelVisual::Property::BORDERLINE_WIDTH, sourceBorderlineWidth);
+  controlProperty1.Insert(Toolkit::DevelVisual::Property::BORDERLINE_COLOR, sourceBorderlineColor);
+  controlProperty1.Insert(Toolkit::DevelVisual::Property::BORDERLINE_OFFSET, sourceBorderlineOffset);
+  control1.SetProperty(Toolkit::Control::Property::BACKGROUND, controlProperty1);
+
+  Control control2 = Control::New();
+  control2.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+  control2.SetProperty(Actor::Property::ANCHOR_POINT, ParentOrigin::CENTER);
+  control2.SetProperty(Actor::Property::POSITION, destinationPosition);
+  control2.SetProperty(Actor::Property::SIZE, destinationSize);
+  control2.SetProperty(Actor::Property::SCALE, destinationScale);
+  control2.SetProperty(Actor::Property::COLOR, destinationColor);
+  control2.SetProperty(Actor::Property::OPACITY, destinationOpacity);
+  Property::Map controlProperty2;
+  controlProperty2.Insert(Toolkit::Visual::Property::TYPE, Toolkit::Visual::COLOR);
+  controlProperty2.Insert(Toolkit::ColorVisual::Property::MIX_COLOR, Vector4(1.0f, 1.0f, 0.0f, 0.5f));
+  controlProperty2.Insert(Toolkit::DevelVisual::Property::CORNER_RADIUS, destinationRadius);
+  controlProperty2.Insert(Toolkit::DevelVisual::Property::BORDERLINE_WIDTH, destinationBorderlineWidth);
+  controlProperty2.Insert(Toolkit::DevelVisual::Property::BORDERLINE_COLOR, destinationBorderlineColor);
+  controlProperty2.Insert(Toolkit::DevelVisual::Property::BORDERLINE_OFFSET, destinationBorderlineOffset);
+  control2.SetProperty(Toolkit::Control::Property::BACKGROUND, controlProperty2);
+
+  DALI_TEST_EQUALS(destinationPosition, control2.GetProperty<Vector3>(Actor::Property::POSITION), TEST_LOCATION);
+  Property::Map backgroundMap = control2.GetProperty<Property::Map>(Toolkit::Control::Property::BACKGROUND);
+  Vector4 cornerRadius = backgroundMap.Find(Toolkit::DevelVisual::Property::CORNER_RADIUS)->Get<Vector4>();
+  DALI_TEST_EQUALS(destinationRadiusV4, cornerRadius, TEST_LOCATION);
+  float borderlineWidth = backgroundMap.Find(Toolkit::DevelVisual::Property::BORDERLINE_WIDTH)->Get<float>();
+  DALI_TEST_EQUALS(destinationBorderlineWidth, borderlineWidth, TEST_LOCATION);
+  Vector4 borderlineColor = backgroundMap.Find(Toolkit::DevelVisual::Property::BORDERLINE_COLOR)->Get<Vector4>();
+  DALI_TEST_EQUALS(destinationBorderlineColor, borderlineColor, TEST_LOCATION);
+  float borderlineOffset = backgroundMap.Find(Toolkit::DevelVisual::Property::BORDERLINE_OFFSET)->Get<float>();
+  DALI_TEST_EQUALS(destinationBorderlineOffset, borderlineOffset, TEST_LOCATION);
+
+  application.GetScene().Add(control1);
+  application.GetScene().Add(control2);
+
+  application.SendNotification();
+  application.Render(20);
+
+  Transition transition = Transition::New(control1, control2, false, TimePeriod(0.5f));
+  TransitionSet transitionSet = TransitionSet::New();
+  transitionSet.AddTransition(transition);
+  transitionSet.Play();
+
+  bool signalReceived(false);
+  TransitionFinishCheck finishCheck(signalReceived);
+  transitionSet.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(50);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+
+  DALI_TEST_NOT_EQUALS(destinationPosition, control1.GetCurrentProperty<Vector3>(Actor::Property::POSITION), 0.00001f, TEST_LOCATION);
+  DALI_TEST_EQUALS(1, control1.GetRendererCount(), TEST_LOCATION);
+
+  Dali::Renderer renderer = control1.GetRendererAt(0);
+  Property::Index index = renderer.GetPropertyIndex(DevelVisual::Property::CORNER_RADIUS);
+  cornerRadius = renderer.GetCurrentProperty<Vector4>(index);
+  DALI_TEST_NOT_EQUALS(destinationRadiusV4, cornerRadius, 0.00001f, TEST_LOCATION);
+
+  index = renderer.GetPropertyIndex(DevelVisual::Property::BORDERLINE_WIDTH);
+  borderlineWidth = renderer.GetCurrentProperty<float>(index);
+  DALI_TEST_NOT_EQUALS(destinationBorderlineWidth, borderlineWidth, 0.00001f, TEST_LOCATION);
+
+  index = renderer.GetPropertyIndex(DevelVisual::Property::BORDERLINE_COLOR);
+  borderlineColor = renderer.GetCurrentProperty<Vector4>(index);
+  DALI_TEST_NOT_EQUALS(destinationBorderlineColor, borderlineColor, 0.00001f, TEST_LOCATION);
+
+  index = renderer.GetPropertyIndex(DevelVisual::Property::BORDERLINE_OFFSET);
+  borderlineOffset = renderer.GetCurrentProperty<float>(index);
+  DALI_TEST_NOT_EQUALS(destinationBorderlineOffset, borderlineOffset, 0.00001f, TEST_LOCATION);
+
+  application.SendNotification();
+  application.Render(700);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+
+  // After the transition is finished,
+  // every current and renderer propeties of control1 are equal to destination properties.
+  DALI_TEST_EQUALS(destinationPosition, control1.GetCurrentProperty<Vector3>(Actor::Property::POSITION), TEST_LOCATION);
+  DALI_TEST_EQUALS(destinationSize, control1.GetCurrentProperty<Vector3>(Actor::Property::SIZE), TEST_LOCATION);
+  DALI_TEST_EQUALS(destinationScale, control1.GetCurrentProperty<Vector3>(Actor::Property::SCALE), TEST_LOCATION);
+  DALI_TEST_EQUALS(destinationColor, control1.GetCurrentProperty<Vector4>(Actor::Property::COLOR), TEST_LOCATION);
+  DALI_TEST_EQUALS(destinationOpacity, control1.GetCurrentProperty<float>(Actor::Property::OPACITY), TEST_LOCATION);
+
+  DALI_TEST_EQUALS(1, control1.GetRendererCount(), TEST_LOCATION);
+  renderer = control1.GetRendererAt(0);
+  index = renderer.GetPropertyIndex(DevelVisual::Property::CORNER_RADIUS);
+  cornerRadius = renderer.GetCurrentProperty<Vector4>(index);
+  DALI_TEST_EQUALS(destinationRadiusV4, cornerRadius, TEST_LOCATION);
+
+  index = renderer.GetPropertyIndex(DevelVisual::Property::BORDERLINE_WIDTH);
+  borderlineWidth = renderer.GetCurrentProperty<float>(index);
+  DALI_TEST_EQUALS(destinationBorderlineWidth, borderlineWidth, TEST_LOCATION);
+
+  index = renderer.GetPropertyIndex(DevelVisual::Property::BORDERLINE_COLOR);
+  borderlineColor = renderer.GetCurrentProperty<Vector4>(index);
+  DALI_TEST_EQUALS(destinationBorderlineColor, borderlineColor, TEST_LOCATION);
+
+  index = renderer.GetPropertyIndex(DevelVisual::Property::BORDERLINE_OFFSET);
+  borderlineOffset = renderer.GetCurrentProperty<float>(index);
+  DALI_TEST_EQUALS(destinationBorderlineOffset, borderlineOffset, TEST_LOCATION);
+
+  // every actor properties of control1 are returned to the source properties.
+  DALI_TEST_EQUALS(sourcePosition, control1.GetProperty<Vector3>(Actor::Property::POSITION), TEST_LOCATION);
+  DALI_TEST_EQUALS(sourceSize, control1.GetProperty<Vector3>(Actor::Property::SIZE), TEST_LOCATION);
+  DALI_TEST_EQUALS(sourceScale, control1.GetProperty<Vector3>(Actor::Property::SCALE), TEST_LOCATION);
+  DALI_TEST_EQUALS(sourceColor, control1.GetProperty<Vector4>(Actor::Property::COLOR), TEST_LOCATION);
+  DALI_TEST_EQUALS(sourceOpacity, control1.GetProperty<float>(Actor::Property::OPACITY), TEST_LOCATION);
+
+  application.SendNotification();
+  application.Render(20);
+
+  // after next update, renderer properties are returned to the source properties.
+  DALI_TEST_EQUALS(1, control1.GetRendererCount(), TEST_LOCATION);
+  renderer = control1.GetRendererAt(0);
+  index = renderer.GetPropertyIndex(DevelVisual::Property::CORNER_RADIUS);
+  cornerRadius = renderer.GetCurrentProperty<Vector4>(index);
+  DALI_TEST_EQUALS(sourceRadiusV4, cornerRadius, TEST_LOCATION);
+
+  index = renderer.GetPropertyIndex(DevelVisual::Property::BORDERLINE_WIDTH);
+  borderlineWidth = renderer.GetCurrentProperty<float>(index);
+  DALI_TEST_EQUALS(sourceBorderlineWidth, borderlineWidth, TEST_LOCATION);
+
+  index = renderer.GetPropertyIndex(DevelVisual::Property::BORDERLINE_COLOR);
+  borderlineColor = renderer.GetCurrentProperty<Vector4>(index);
+  DALI_TEST_EQUALS(sourceBorderlineColor, borderlineColor, TEST_LOCATION);
+
+  index = renderer.GetPropertyIndex(DevelVisual::Property::BORDERLINE_OFFSET);
+  borderlineOffset = renderer.GetCurrentProperty<float>(index);
+  DALI_TEST_EQUALS(sourceBorderlineOffset, borderlineOffset, TEST_LOCATION);
+
+  END_TEST;
+}
+
 int UtcDaliTransitionBetweenControlPairWithoutEmptySourceBackground(void)
 {
   ToolkitTestApplication application;
@@ -377,7 +556,7 @@ int UtcDaliTransitionBetweenControlPairWithoutEmptySourceBackground(void)
   application.SendNotification();
   application.Render(20);
 
-  Transition transition = Transition::New(control1, control2, TimePeriod(0.5f));
+  Transition transition = Transition::New(control1, control2, true, TimePeriod(0.5f));
   TransitionSet transitionSet = TransitionSet::New();
   transitionSet.AddTransition(transition);
   transitionSet.Play();
@@ -474,7 +653,7 @@ int UtcDaliTransitionBetweenImageViewPair(void)
   Vector3 startWorldPosition = control1.GetProperty<Vector3>(Actor::Property::WORLD_POSITION);
   Vector3 finishWorldPosition = control2.GetProperty<Vector3>(Actor::Property::WORLD_POSITION);
 
-  Transition transition = Transition::New(control1, control2, TimePeriod(0.5f));
+  Transition transition = Transition::New(control1, control2, true, TimePeriod(0.5f));
   TransitionSet transitionSet = TransitionSet::New();
   transitionSet.AddTransition(transition);
   transitionSet.Play();
@@ -562,7 +741,7 @@ int UtcDaliTransitionBetweenImageViewPairWithDelay(void)
   Vector3 startWorldPosition = control1.GetProperty<Vector3>(Actor::Property::WORLD_POSITION);
   Vector3 finishWorldPosition = control2.GetProperty<Vector3>(Actor::Property::WORLD_POSITION);
 
-  Transition transition = Transition::New(control1, control2, TimePeriod(0.5f, 0.5f));
+  Transition transition = Transition::New(control1, control2, true, TimePeriod(0.5f, 0.5f));
   TransitionSet transitionSet = TransitionSet::New();
   transitionSet.AddTransition(transition);
   transitionSet.Play();
@@ -654,7 +833,7 @@ int UtcDaliTransitionBetweenControlPairWithTree(void)
   application.SendNotification();
   application.Render(20);
 
-  Transition transition = Transition::New(control1, control2, TimePeriod(0.5f));
+  Transition transition = Transition::New(control1, control2, true, TimePeriod(0.5f));
   TransitionSet transitionSet = TransitionSet::New();
   transitionSet.AddTransition(transition);
   transitionSet.Play();
@@ -721,7 +900,7 @@ int UtcDaliTransitionBetweenControlPairWithTreeWithChild(void)
   application.SendNotification();
   application.Render(20);
 
-  Transition transition = Transition::New(control1, control2, TimePeriod(0.5f));
+  Transition transition = Transition::New(control1, control2, true, TimePeriod(0.5f));
   transition.TransitionWithChild(true);
   TransitionSet transitionSet = TransitionSet::New();
   transitionSet.AddTransition(transition);
@@ -801,7 +980,7 @@ int UtcDaliTransitionBetweenControlPairWithTreeWithoutPositionInheritance(void)
   control3.SetProperty(Actor::Property::INHERIT_ORIENTATION, true);
   control3.SetProperty(Actor::Property::INHERIT_SCALE, true);
 
-  transition = Transition::New(control1, control3, TimePeriod(0.5f));
+  transition = Transition::New(control1, control3, true, TimePeriod(0.5f));
   transitionSet = TransitionSet::New();
   transitionSet.AddTransition(transition);
   transitionSet.Play();
@@ -892,7 +1071,7 @@ int UtcDaliTransitionBetweenControlPairWithTreeWithoutOrientationInheritance(voi
   bool signalReceived(false);
   TransitionFinishCheck finishCheck(signalReceived);
 
-  transition = Transition::New(control1, control3, TimePeriod(0.5f));
+  transition = Transition::New(control1, control3, true, TimePeriod(0.5f));
   transitionSet = TransitionSet::New();
   transitionSet.AddTransition(transition);
   transitionSet.Play();
@@ -978,7 +1157,7 @@ int UtcDaliTransitionBetweenControlPairWithTreeWithoutScaleInheritance(void)
   bool signalReceived(false);
   TransitionFinishCheck finishCheck(signalReceived);
 
-  transition = Transition::New(control1, control3, TimePeriod(0.5f));
+  transition = Transition::New(control1, control3, true, TimePeriod(0.5f));
   transitionSet = TransitionSet::New();
   transitionSet.AddTransition(transition);
   transitionSet.Play();
index bd389ad..d1a2e56 100644 (file)
@@ -4352,6 +4352,242 @@ int UtcDaliVisualBorderline(void)
   END_TEST;
 }
 
+int UtcDaliVisualBorderlineBlendModeTest(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline( "UtcDaliVisualBorderlineBlendModeTest" );
+  VisualFactory factory = VisualFactory::Get();
+
+  // Case 1 : Test which doesn't support borderline feature.
+  {
+    tet_printf("Test Unsupported visual type\n");
+    Property::Map propertyMap;
+    propertyMap.Insert(Visual::Property::TYPE, Visual::BORDER);
+    propertyMap.Insert(BorderVisual::Property::COLOR, Color::BLUE);
+    propertyMap.Insert(DevelVisual::Property::BORDERLINE_WIDTH, 1.0f);
+    Visual::Base borderVisual = factory.CreateVisual( propertyMap );
+
+    DummyControl actor = DummyControl::New(true);
+    Impl::DummyControl& dummyImpl = static_cast<Impl::DummyControl&>(actor.GetImplementation());
+    dummyImpl.RegisterVisual( DummyControl::Property::TEST_VISUAL, borderVisual );
+    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::Value blendModeValue = renderer.GetProperty( Renderer::Property::BLEND_MODE );
+    // Visual::BORDER doesn't support BORDERLINE. BlendMode is AUTO.
+    DALI_TEST_EQUALS( blendModeValue.Get<int>(), (int)BlendMode::AUTO, TEST_LOCATION );
+
+    application.GetScene().Remove(actor);
+  }
+
+  // Case 2 : Test which support borderline feature.
+  {
+    tet_printf("Test normal case\n");
+    Property::Map propertyMap;
+    propertyMap.Insert(Visual::Property::TYPE, Visual::COLOR);
+    propertyMap.Insert(ColorVisual::Property::MIX_COLOR, Color::BLUE);
+    propertyMap.Insert(DevelVisual::Property::BORDERLINE_WIDTH, 1.0f);
+    Visual::Base colorVisual = factory.CreateVisual( propertyMap );
+
+    DummyControl actor = DummyControl::New(true);
+    Impl::DummyControl& dummyImpl = static_cast<Impl::DummyControl&>(actor.GetImplementation());
+    dummyImpl.RegisterVisual( DummyControl::Property::TEST_VISUAL, colorVisual );
+    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::Value blendModeValue = renderer.GetProperty( Renderer::Property::BLEND_MODE );
+    // Visual::COLOR support BORDERLINE. BlendMode is ON_WITHOUT_CULL.
+    DALI_TEST_EQUALS( blendModeValue.Get<int>(), (int)BlendMode::ON_WITHOUT_CULL, TEST_LOCATION );
+
+    application.GetScene().Remove(actor);
+  }
+
+  // Case 3 : Test which animated borderline.
+  {
+    tet_printf("Test borderline animate case\n");
+    Property::Map propertyMap;
+    propertyMap.Insert(Visual::Property::TYPE, Visual::COLOR);
+    propertyMap.Insert(ColorVisual::Property::MIX_COLOR, Color::BLUE);
+    Visual::Base colorVisual = factory.CreateVisual( propertyMap );
+
+    DummyControl actor = DummyControl::New(true);
+    Impl::DummyControl& dummyImpl = static_cast<Impl::DummyControl&>(actor.GetImplementation());
+    dummyImpl.RegisterVisual( DummyControl::Property::TEST_VISUAL, colorVisual );
+    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::Value blendModeValue = renderer.GetProperty( Renderer::Property::BLEND_MODE );
+    // BlendMode is AUTO.
+    DALI_TEST_EQUALS( blendModeValue.Get<int>(), (int)BlendMode::AUTO, TEST_LOCATION );
+
+    Animation animation = Animation::New(0.1f);
+    animation.AnimateTo( DevelControl::GetVisualProperty(actor, DummyControl::Property::TEST_VISUAL, DevelVisual::Property::BORDERLINE_WIDTH), 1.0f );
+    animation.Play();
+
+    application.SendNotification();
+    application.Render();
+    application.Render(101u); // End of animation
+
+    blendModeValue = renderer.GetProperty( Renderer::Property::BLEND_MODE );
+    // BlendMode is ON_WITHOUT_CULL.
+    DALI_TEST_EQUALS( blendModeValue.Get<int>(), (int)BlendMode::ON_WITHOUT_CULL, TEST_LOCATION );
+
+    Animation revanimation = Animation::New(0.1f);
+    revanimation.AnimateTo( DevelControl::GetVisualProperty(actor, DummyControl::Property::TEST_VISUAL, DevelVisual::Property::BORDERLINE_WIDTH), 0.0f );
+    revanimation.Play();
+
+    application.SendNotification();
+    application.Render();
+    application.Render(101u); // End of animation
+
+    blendModeValue = renderer.GetProperty( Renderer::Property::BLEND_MODE );
+    // BlendMode is still ON_WITHOUT_CULL.
+    DALI_TEST_EQUALS( blendModeValue.Get<int>(), (int)BlendMode::ON_WITHOUT_CULL, TEST_LOCATION );
+
+    application.GetScene().Remove(actor);
+  }
+
+  // Case 4 : Test which animated corner radius occur.
+  {
+    tet_printf("Test borderline animate case\n");
+    Property::Map propertyMap;
+    propertyMap.Insert(Visual::Property::TYPE, Visual::COLOR);
+    propertyMap.Insert(ColorVisual::Property::MIX_COLOR, Color::BLUE);
+    propertyMap.Insert(DevelVisual::Property::BORDERLINE_WIDTH, 1.0f);
+    Visual::Base colorVisual = factory.CreateVisual( propertyMap );
+
+    DummyControl actor = DummyControl::New(true);
+    Impl::DummyControl& dummyImpl = static_cast<Impl::DummyControl&>(actor.GetImplementation());
+    dummyImpl.RegisterVisual( DummyControl::Property::TEST_VISUAL, colorVisual );
+    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::Value blendModeValue = renderer.GetProperty( Renderer::Property::BLEND_MODE );
+    // BlendMode is ON_WITHOUT_CULL.
+    DALI_TEST_EQUALS( blendModeValue.Get<int>(), (int)BlendMode::ON_WITHOUT_CULL, TEST_LOCATION );
+
+    Animation animation = Animation::New(0.1f);
+    animation.AnimateTo( DevelControl::GetVisualProperty(actor, DummyControl::Property::TEST_VISUAL, DevelVisual::Property::CORNER_RADIUS), Vector4(1.0f, 1.0f, 1.0f, 1.0f) );
+    animation.Play();
+
+    application.SendNotification();
+    application.Render();
+    application.Render(101u); // End of animation
+
+    blendModeValue = renderer.GetProperty( Renderer::Property::BLEND_MODE );
+    // BlendMode is ON_WITHOUT_CULL.
+    DALI_TEST_EQUALS( blendModeValue.Get<int>(), (int)BlendMode::ON_WITHOUT_CULL, TEST_LOCATION );
+
+    application.GetScene().Remove(actor);
+  }
+
+  END_TEST;
+}
+
+int UtcDaliVisualBorderlineColorAnimateTest(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline( "UtcDaliVisualBorderlineColorAnimateTest color" );
+
+  TestGraphicsController& graphics = application.GetGraphicsController();
+  static std::vector<UniformData> customUniforms =
+  {
+    UniformData("mixColor", Property::Type::VECTOR3),
+    UniformData("cornerRadius", Property::Type::VECTOR4),
+    UniformData("cornerRadiusPolicy", Property::Type::FLOAT),
+    UniformData("borderlineWidth", Property::Type::FLOAT),
+    UniformData("borderlineColor", Property::Type::VECTOR4),
+    UniformData("borderlineOffset", Property::Type::FLOAT),
+  };
+  graphics.AddCustomUniforms(customUniforms);
+
+  {
+    const Vector3 INITIAL_MIX_COLOR( 1.0f,0.0f,1.0f );
+    const float   INITIAL_MIX_OPACITY( 0.5f );
+    const Vector4 INITIAL_BORDERLINE_COLOR( 0.0f,1.0f,0.0f,1.0f );
+    const float   INITIAL_ACTOR_OPACITY( 1.0f );
+    const Vector3 TARGET_MIX_COLOR( 1.0f, 0.0f, 0.0f );
+    const float   TARGET_MIX_OPACITY( 0.8f );
+    const Vector4 TARGET_BORDERLINE_COLOR( 1.0f, 0.0f, 1.0f, 0.2f);
+    const float   TARGET_ACTOR_OPACITY( 0.5f );
+
+    VisualFactory factory = VisualFactory::Get();
+    Property::Map propertyMap;
+    propertyMap.Insert(Visual::Property::TYPE,  Visual::COLOR);
+    propertyMap.Insert(Visual::Property::MIX_COLOR, INITIAL_MIX_COLOR);
+    propertyMap.Insert(Visual::Property::OPACITY, INITIAL_MIX_OPACITY);
+    propertyMap.Insert(DevelVisual::Property::BORDERLINE_WIDTH, 1.0f);
+    propertyMap.Insert(DevelVisual::Property::BORDERLINE_COLOR, INITIAL_BORDERLINE_COLOR);
+    Visual::Base visual = factory.CreateVisual( propertyMap );
+
+    DummyControl actor = DummyControl::New(true);
+    Impl::DummyControl& dummyImpl = static_cast<Impl::DummyControl&>(actor.GetImplementation());
+    dummyImpl.RegisterVisual( DummyControl::Property::TEST_VISUAL, visual );
+    actor.SetProperty( Actor::Property::SIZE, Vector2( 2000.f, 2000.f ) );
+    actor.SetProperty( Actor::Property::OPACITY, INITIAL_ACTOR_OPACITY );
+    actor.SetProperty( Actor::Property::PARENT_ORIGIN,ParentOrigin::CENTER);
+    application.GetScene().Add(actor);
+
+    DALI_TEST_EQUALS( actor.GetRendererCount(), 1u, TEST_LOCATION);
+
+    Animation animation = Animation::New(4.0f);
+    animation.AnimateTo( DevelControl::GetVisualProperty(actor, DummyControl::Property::TEST_VISUAL, Visual::Property::MIX_COLOR), TARGET_MIX_COLOR );
+    animation.AnimateTo( DevelControl::GetVisualProperty(actor, DummyControl::Property::TEST_VISUAL, Visual::Property::OPACITY), TARGET_MIX_OPACITY);
+    animation.AnimateTo( DevelControl::GetVisualProperty(actor, DummyControl::Property::TEST_VISUAL, DevelVisual::Property::BORDERLINE_COLOR), TARGET_BORDERLINE_COLOR );
+    animation.AnimateTo( Property(actor, Actor::Property::OPACITY), TARGET_ACTOR_OPACITY);
+    animation.Play();
+
+    TestGlAbstraction& glAbstraction = application.GetGlAbstraction();
+
+    application.SendNotification();
+    application.Render(0);
+    application.Render(2000u); // halfway point
+    application.SendNotification();
+
+    Vector3 halfwayMixColor        = (INITIAL_MIX_COLOR        + TARGET_MIX_COLOR       ) * 0.5f;
+    float   halfwayMixOpacity      = (INITIAL_MIX_OPACITY      + TARGET_MIX_OPACITY     ) * 0.5f;
+    Vector4 halfwayBorderlineColor = (INITIAL_BORDERLINE_COLOR + TARGET_BORDERLINE_COLOR) * 0.5f;
+    float   halfwayActorOpacity    = (INITIAL_ACTOR_OPACITY    + TARGET_ACTOR_OPACITY   ) * 0.5f;
+    halfwayMixOpacity *= halfwayActorOpacity;
+    DALI_TEST_EQUALS( glAbstraction.CheckUniformValue<Vector3>("mixColor", halfwayMixColor), true, TEST_LOCATION );
+    DALI_TEST_EQUALS( glAbstraction.CheckUniformValue<Vector4>("uColor", Vector4(1.0f, 1.0f, 1.0f, halfwayMixOpacity)), true, TEST_LOCATION );
+    DALI_TEST_EQUALS( glAbstraction.CheckUniformValue<Vector4>("uActorColor", Vector4(1.0f, 1.0f, 1.0f, halfwayActorOpacity)), true, TEST_LOCATION );
+    DALI_TEST_EQUALS( glAbstraction.CheckUniformValue<Vector4>("borderlineColor", halfwayBorderlineColor), true, TEST_LOCATION );
+
+    application.Render(2001u); // go past end
+    application.SendNotification(); // Trigger signals
+
+    DALI_TEST_EQUALS( actor.GetCurrentProperty< Vector4 >( Actor::Property::COLOR ), Vector4(1.0f, 1.0f, 1.0f, TARGET_ACTOR_OPACITY), TEST_LOCATION );
+    DALI_TEST_EQUALS( glAbstraction.CheckUniformValue<Vector3>("mixColor", TARGET_MIX_COLOR), true, TEST_LOCATION );
+    DALI_TEST_EQUALS( glAbstraction.CheckUniformValue<Vector4>("uColor", Vector4(1.0f, 1.0f, 1.0f, TARGET_MIX_OPACITY * TARGET_ACTOR_OPACITY) ), true, TEST_LOCATION );
+    DALI_TEST_EQUALS( glAbstraction.CheckUniformValue<Vector4>("uActorColor", Vector4(1.0f, 1.0f, 1.0f, TARGET_ACTOR_OPACITY)), true, TEST_LOCATION );
+    DALI_TEST_EQUALS( glAbstraction.CheckUniformValue<Vector4>("borderlineColor", TARGET_BORDERLINE_COLOR ), true, TEST_LOCATION );
+
+    actor.Unparent();
+  }
+
+  END_TEST;
+}
 
 int UtcDaliColorVisualBlurRadius(void)
 {
index 55becb3..dc7a128 100644 (file)
@@ -122,19 +122,6 @@ Dali::Property GetVisualProperty(Control control, Dali::Property::Index index, D
   return controlDataImpl.GetVisualProperty(index, visualPropertyKey);
 }
 
-void CreateTransitions(Control control, Dali::Animation& animation, Dali::Toolkit::Control source, AlphaFunction alphaFunction, TimePeriod timePeriod)
-{
-  if(animation)
-  {
-    // make visual transition of control visual.
-    Internal::Control&       internalControl = Toolkit::Internal::GetImplementation(control);
-    Internal::Control::Impl& controlDataImpl = Internal::Control::Impl::Get(internalControl);
-    controlDataImpl.MakeVisualTransition(animation, source, Toolkit::Control::Property::BACKGROUND, alphaFunction, timePeriod);
-    controlDataImpl.MakeVisualTransition(animation, source, Toolkit::DevelControl::Property::SHADOW, alphaFunction, timePeriod);
-    internalControl.OnCreateTransitions(animation, source, alphaFunction, timePeriod);
-  }
-}
-
 static Toolkit::Internal::Control::Impl* GetControlImplementation(Dali::Actor actor)
 {
   Dali::Toolkit::Control control = Toolkit::Control::DownCast(actor);
index 36b83f9..8877646 100644 (file)
@@ -371,20 +371,6 @@ DALI_TOOLKIT_API VisualEventSignalType& VisualEventSignal(Control control);
 DALI_TOOLKIT_API Dali::Property GetVisualProperty(Control control, Dali::Property::Index index, Dali::Property::Key visualPropertyKey);
 
 /**
- * @brief Retrieve visual/renderer property animation between this Control and source control.
- * Input animation must be created before this method called.
- * And the animations between this method created are added the input animation.
- * This method generates visual/renderer property animation but not creates Actor property animation.
- *
- * @param[in] control The control
- * @param[in] animation generated animation
- * @param[in] source source control of the animation.
- * @param[in] alphaFunction AlphaFunction of the animation
- * @param[in] timePeriod TimePeriod of the animation
- */
-DALI_TOOLKIT_API void CreateTransitions(Control control, Dali::Animation& animation, Dali::Toolkit::Control source, AlphaFunction alphaFunction, TimePeriod timePeriod);
-
-/**
  * @brief The signal is emmited as a succession of "activate" signal send by accessibility client.
  * @return The signal to connect to
  */
index e94f60b..c88b7a0 100755 (executable)
@@ -77,6 +77,7 @@ SET( devel_api_src_files
 SET( devel_api_header_files
   ${devel_api_src_dir}/direction-enums.h
   ${devel_api_src_dir}/toolkit-property-index-ranges.h
+  ${devel_api_src_dir}/toolkit-action-index-ranges.h
 )
 
 SET( devel_api_accessibility-manager_header_files
@@ -168,13 +169,12 @@ SET( devel_api_visuals_header_files
   ${devel_api_src_dir}/visuals/animated-image-visual-actions-devel.h
   ${devel_api_src_dir}/visuals/animated-vector-image-visual-actions-devel.h
   ${devel_api_src_dir}/visuals/animated-vector-image-visual-signals-devel.h
-  ${devel_api_src_dir}/visuals/arc-visual-actions-devel.h
   ${devel_api_src_dir}/visuals/arc-visual-properties-devel.h
-  ${devel_api_src_dir}/visuals/color-visual-actions-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/text-visual-properties-devel.h
+  ${devel_api_src_dir}/visuals/visual-actions-devel.h
   ${devel_api_src_dir}/visuals/visual-properties-devel.h
 )
 
index 29f0e8b..cc96d45 100644 (file)
@@ -30,6 +30,26 @@ const Property::Map GetConfigurations(StyleManager styleManager)
   return GetImpl(styleManager).GetConfigurations();
 }
 
+void SetBrokenImageUrl(StyleManager styleManager, DevelStyleManager::BrokenImageType brokenImageType, const std::string& brokenImageUrl)
+{
+  return GetImpl(styleManager).SetBrokenImageUrl(brokenImageType, brokenImageUrl);
+}
+
+std::string GetBrokenImageUrl(StyleManager styleManager, DevelStyleManager::BrokenImageType brokenImageType)
+{
+  return GetImpl(styleManager).GetBrokenImageUrl(brokenImageType);
+}
+
+std::vector<std::string> GetBrokenImageUrlList(StyleManager styleManager)
+{
+  return GetImpl(styleManager).GetBrokenImageUrlList();
+}
+
+BrokenImageChangedSignalType& BrokenImageChangedSignal(StyleManager styleManager)
+{
+  return GetImpl(styleManager).BrokenImageChangedSignal();
+}
+
 } // namespace DevelStyleManager
 
 } // namespace Toolkit
index efcff7d..f1e05d7 100644 (file)
@@ -28,6 +28,18 @@ namespace Toolkit
 namespace DevelStyleManager
 {
 /**
+ * @brief The Type of BrokenImage
+ */
+enum class BrokenImageType
+{
+  SMALL,
+  NORMAL,
+  LARGE
+};
+
+using BrokenImageChangedSignalType = Signal<void(StyleManager)>;
+
+/**
  * @brief Gets all currently defined configurations.
  *
  * @pre The Builder has been initialized.
@@ -36,6 +48,43 @@ namespace DevelStyleManager
 **/
 DALI_TOOLKIT_API const Property::Map GetConfigurations(StyleManager styleManager);
 
+/**
+   * @brief Sets an image to be used when a visual has failed to correctly render
+   * @param[in] styleManager The instance of StyleManager
+   * @param[in] brokenImageType The type of broken image
+   * @param[in] brokenImageUrl The broken image url
+   */
+DALI_TOOLKIT_API void SetBrokenImageUrl(StyleManager styleManager, DevelStyleManager::BrokenImageType brokenImageType, const std::string& brokenImageUrl);
+
+/**
+   * @brief Gets an image to be used when a visual has failed to correctly render
+   * @param[in] styleManager The instance of StyleManager
+   * @param[in] brokenImageType BrokenImage type
+   */
+DALI_TOOLKIT_API std::string GetBrokenImageUrl(StyleManager styleManager, DevelStyleManager::BrokenImageType brokenImageType);
+
+/**
+ * @brief Get the Broken Image Url List
+ *
+ * This list is broken images stored in order of SMALL, NORMAL, and LARGE values except if the value is empty.
+ * This API just makes the list without comparing size, so the application must set a value that matches the size.
+ * @param styleManager The instance of StyleManager
+ * @return A List of Broken Image Url
+ */
+DALI_TOOLKIT_API std::vector<std::string> GetBrokenImageUrlList(StyleManager styleManager);
+
+/**
+ * @brief This signal is emitted when the URL of the broken image is set
+ *
+ * A callback of the following type may be connected:
+ * @code
+ *   void YourCallbackName(StyleManager styleManager)
+ * @endcode
+ * @param styleManager The instance of StyleManager
+ * @return The signal to connect to
+ */
+DALI_TOOLKIT_API BrokenImageChangedSignalType& BrokenImageChangedSignal(StyleManager styleManager);
+
 } // namespace DevelStyleManager
 
 } // namespace Toolkit
diff --git a/dali-toolkit/devel-api/toolkit-action-index-ranges.h b/dali-toolkit/devel-api/toolkit-action-index-ranges.h
new file mode 100644 (file)
index 0000000..8e5dbc4
--- /dev/null
@@ -0,0 +1,51 @@
+#ifndef DALI_TOOLKIT_ACTION_INDEX_RANGES_H
+#define DALI_TOOLKIT_ACTION_INDEX_RANGES_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 <dali/public-api/object/property-index-ranges.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+/**
+ * @addtogroup dali_toolkit_controls
+ * @{
+ */
+
+/**
+ * @brief Enumeration for the start and end action ranges.
+ */
+enum ActionRanges
+{
+  VISUAL_ACTION_BASE_START_INDEX = 0,                                    ///< Visual Action Base Start Index.
+  VISUAL_ACTION_BASE_END_INDEX   = VISUAL_ACTION_BASE_START_INDEX + 100, ///< Visual Action Base End Index.
+  VISUAL_ACTION_START_INDEX      = VISUAL_ACTION_BASE_END_INDEX + 1,     ///< Visual Action Start Index.
+  VISUAL_ACTION_END_INDEX        = VISUAL_ACTION_START_INDEX + 100000,   ///< Visual Action End Index.
+};
+
+/**
+ * @}
+ */
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // DALI_TOOLKIT_ACTION_INDEX_RANGES_H
index dbe9631..94ae63c 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_TOOLKIT_DEVEL_API_VISUALS_ANIMATED_IMAGE_VISUAL_ACTIONS_DEVEL_H
 
 /*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ * 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.
@@ -17,6 +17,7 @@
  * limitations under the License.
  *
  */
+#include <dali-toolkit/devel-api/toolkit-action-index-ranges.h>
 
 namespace Dali
 {
@@ -34,10 +35,10 @@ namespace Action
  */
 enum Type
 {
-  PLAY,   ///< Play the animated GIF. This is also Default playback mode.
-  PAUSE,  ///< Pause the animated GIF.
-  STOP,   ///< Stop the animated GIF.
-  JUMP_TO ///< Jump to the specified frame. Property::INTEGER value should be passed.
+  PLAY = VISUAL_ACTION_START_INDEX, ///< Play the animated GIF. This is also Default playback mode.
+  PAUSE,                            ///< Pause the animated GIF.
+  STOP,                             ///< Stop the animated GIF.
+  JUMP_TO                           ///< Jump to the specified frame. Property::INTEGER value should be passed.
 };
 
 } // namespace Action
index 2955d17..ecb91ae 100644 (file)
@@ -17,6 +17,7 @@
  * limitations under the License.
  *
  */
+#include <dali-toolkit/devel-api/toolkit-action-index-ranges.h>
 
 namespace Dali
 {
@@ -34,11 +35,10 @@ namespace Action
  */
 enum Type
 {
-  PLAY,           ///< Play the animated vector image.
-  PAUSE,          ///< Pause the animated vector image.
-  STOP,           ///< Stop the animated vector image. This is also Default playback mode.
-  JUMP_TO,        ///< Jump to the specified frame. Property::INTEGER value should be passed.
-  UPDATE_PROPERTY ///< Update the properties of the animated vector image.
+  PLAY = VISUAL_ACTION_START_INDEX, ///< Play the animated vector image.
+  PAUSE,                            ///< Pause the animated vector image.
+  STOP,                             ///< Stop the animated vector image. This is also Default playback mode.
+  JUMP_TO,                          ///< Jump to the specified frame. Property::INTEGER value should be passed.
 };
 
 } // namespace Action
diff --git a/dali-toolkit/devel-api/visuals/arc-visual-actions-devel.h b/dali-toolkit/devel-api/visuals/arc-visual-actions-devel.h
deleted file mode 100644 (file)
index 9657084..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-#ifndef DALI_TOOLKIT_DEVEL_API_VISUALS_ARC_VISUAL_ACTIONS_DEVEL_H
-#define DALI_TOOLKIT_DEVEL_API_VISUALS_ARC_VISUAL_ACTIONS_DEVEL_H
-
-/*
- * Copyright (c) 2020 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.
- *
- */
-
-namespace Dali
-{
-namespace Toolkit
-{
-namespace DevelArcVisual
-{
-/**
- * @brief Actions that the arc visual can perform.  These actions are called through the Visual::Base::DoAction API.
- */
-namespace Action
-{
-/**
- * @brief The available actions for this visual
- */
-enum Type
-{
-  /**
-   * @brief Update the properties of the visual.
-   * @note DevelArcVisual::Property::THICKNESS, DevelArcVisual::Property::START_ANGLE and DevelArcVisual::Property::SWEEP_ANGLE can be updated.
-   */
-  UPDATE_PROPERTY = 0
-};
-
-} // namespace Action
-
-} // namespace DevelArcVisual
-
-} // namespace Toolkit
-
-} // namespace Dali
-
-#endif // DALI_TOOLKIT_DEVEL_API_VISUALS_ARC_VISUAL_ACTIONS_DEVEL_H
index 89ea2d6..66b4715 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_TOOLKIT_DEVEL_API_VISUALS_IMAGE_VISUAL_ACTIONS_DEVEL_H
 
 /*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ * 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.
@@ -17,6 +17,7 @@
  * limitations under the License.
  *
  */
+#include <dali-toolkit/devel-api/toolkit-action-index-ranges.h>
 
 namespace Dali
 {
@@ -34,7 +35,7 @@ namespace Action
  */
 enum Type
 {
-  RELOAD = 0 ///< Force reloading of the image, all visuals using this image will get the latest one.
+  RELOAD = VISUAL_ACTION_START_INDEX ///< Force reloading of the image, all visuals using this image will get the latest one.
 };
 
 } // namespace Action
@@ -1,8 +1,8 @@
-#ifndef DALI_TOOLKIT_DEVEL_API_VISUALS_COLOR_VISUAL_ACTIONS_DEVEL_H
-#define DALI_TOOLKIT_DEVEL_API_VISUALS_COLOR_VISUAL_ACTIONS_DEVEL_H
+#ifndef DALI_TOOLKIT_DEVEL_API_VISUALS_VISUAL_ACTIONS_DEVEL_H
+#define DALI_TOOLKIT_DEVEL_API_VISUALS_VISUAL_ACTIONS_DEVEL_H
 
 /*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ * 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.
  *
  */
 
+// EXTERNAL INCLUDES
+#include <dali-toolkit/devel-api/toolkit-action-index-ranges.h>
+
 namespace Dali
 {
 namespace Toolkit
 {
-namespace DevelColorVisual
+namespace DevelVisual
 {
+
 /**
- * @brief Actions that the color visual can perform. These actions are called through the Visual::Base::DoAction API.
+ * @brief Actions that the visual can perform. These actions are called through the Visual::Base::DoAction API.
  */
 namespace Action
 {
@@ -37,15 +41,15 @@ enum Type
   /**
    * @brief Update the properties of the visual.
    */
-  UPDATE_PROPERTY = 0
+  UPDATE_PROPERTY = VISUAL_ACTION_BASE_START_INDEX
 };
 
 } // namespace Action
 
-} // namespace DevelColorVisual
+} // namespace DevelVisual
 
 } // namespace Toolkit
 
 } // namespace Dali
 
-#endif // DALI_TOOLKIT_DEVEL_API_VISUALS_COLOR_VISUAL_ACTIONS_DEVEL_H
+#endif // DALI_TOOLKIT_DEVEL_API_VISUALS_VISUAL_ACTIONS_DEVEL_H
index 5741a42..1540b02 100644 (file)
@@ -196,43 +196,21 @@ void CanvasView::AddRasterizationTask()
   }
 }
 
-void CanvasView::ApplyRasterizedImage(PixelData rasterizedPixelData)
+void CanvasView::ApplyRasterizedImage(Texture rasterizedTexture)
 {
-  if(rasterizedPixelData)
+  if (rasterizedTexture && rasterizedTexture.GetWidth() != 0 && rasterizedTexture.GetHeight() != 0)
   {
-    auto rasterizedPixelDataWidth  = rasterizedPixelData.GetWidth();
-    auto rasterizedPixelDataHeight = rasterizedPixelData.GetHeight();
-
-    if(rasterizedPixelDataWidth > 0 && rasterizedPixelDataHeight > 0)
+    if(!mTextureSet)
     {
-      if(!mTexture || mTexture.GetWidth() != rasterizedPixelDataWidth || mTexture.GetHeight() != rasterizedPixelDataHeight)
-      {
-        mTexture = Texture::New(TextureType::TEXTURE_2D, rasterizedPixelData.GetPixelFormat(), rasterizedPixelDataWidth, rasterizedPixelDataHeight);
-        mTexture.Upload(rasterizedPixelData);
-
-        if(!mTextureSet)
-        {
-          mTextureSet       = TextureSet::New();
-          Geometry geometry = VisualFactoryCache::CreateQuadGeometry();
-          Shader   shader   = Shader::New(SHADER_CANVAS_VIEW_VERT, SHADER_CANVAS_VIEW_FRAG);
-          Renderer renderer = Renderer::New(geometry, shader);
-          renderer.SetTextures(mTextureSet);
-          renderer.SetProperty(Renderer::Property::BLEND_PRE_MULTIPLIED_ALPHA, true);
-
-          Actor actor = Self();
-          if(actor)
-          {
-            actor.AddRenderer(renderer);
-          }
-        }
-        mTextureSet.SetTexture(0, mTexture);
-      }
-      else
-      {
-        //Update texture
-        mTexture.Upload(rasterizedPixelData);
-      }
+      mTextureSet       = TextureSet::New();
+      Geometry geometry = VisualFactoryCache::CreateQuadGeometry();
+      Shader   shader   = Shader::New(SHADER_CANVAS_VIEW_VERT, SHADER_CANVAS_VIEW_FRAG);
+      Renderer renderer = Renderer::New(geometry, shader);
+      renderer.SetTextures(mTextureSet);
+      renderer.SetProperty(Renderer::Property::BLEND_PRE_MULTIPLIED_ALPHA, true);
+      Self().AddRenderer(renderer);
     }
+    mTextureSet.SetTexture(0, rasterizedTexture);
   }
 
   //If there are accumulated changes to CanvasRenderer during Rasterize, Rasterize once again.
index 6b6cf93..4e492eb 100644 (file)
@@ -135,9 +135,9 @@ public:
   /**
    * @bried Apply the rasterized image to the canvas view
    *
-   * @param[in] rasterizedPixelData The pixel buffer with the rasterized pixels
+   * @param[in] rasterizedTexture The texture with the rasterized pixels
    */
-  void ApplyRasterizedImage(PixelData rasterizedPixelData);
+  void ApplyRasterizedImage(Texture rasterizedTexture);
 
 private:
   CanvasView(const CanvasView&) = delete;
index 97835c5..ba3daae 100644 (file)
@@ -31,8 +31,7 @@ namespace Internal
 CanvasRendererRasterizingTask::CanvasRendererRasterizingTask(CanvasView* canvasView, CanvasRenderer canvasRenderer)
 : mCanvasView(canvasView),
   mCanvasRenderer(canvasRenderer),
-  mPixelData(PixelData()),
-  mBufferSize(0, 0)
+  mRasterizedTexture()
 {
 }
 
@@ -40,17 +39,7 @@ bool CanvasRendererRasterizingTask::Rasterize()
 {
   if(mCanvasRenderer && mCanvasRenderer.Rasterize())
   {
-    Devel::PixelBuffer pixbuf = mCanvasRenderer.GetPixelBuffer();
-    auto               width  = pixbuf.GetWidth();
-    auto               height = pixbuf.GetHeight();
-    if(width > 0 && height > 0)
-    {
-      mBufferSize.width  = width;
-      mBufferSize.height = height;
-
-      mPixelData = Devel::PixelBuffer::Convert(pixbuf);
-      return true;
-    }
+    return true;
   }
   return false;
 }
@@ -60,14 +49,9 @@ CanvasView* CanvasRendererRasterizingTask::GetCanvasView() const
   return mCanvasView.Get();
 }
 
-PixelData CanvasRendererRasterizingTask::GetPixelData() const
-{
-  return mPixelData;
-}
-
-Vector2 CanvasRendererRasterizingTask::GetBufferSize() const
+Texture CanvasRendererRasterizingTask::GetRasterizedTexture()
 {
-  return mBufferSize;
+  return mCanvasRenderer.GetRasterizedTexture();
 }
 
 CanvasViewRasterizeThread::CanvasViewRasterizeThread()
@@ -220,7 +204,7 @@ void CanvasViewRasterizeThread::ApplyRasterized()
 {
   while(CanvasRendererRasterizingTaskPtr task = NextCompletedTask())
   {
-    RasterizationCompletedSignal().Emit(task->GetPixelData());
+    RasterizationCompletedSignal().Emit(task->GetRasterizedTexture()); // Here texture get
   }
 
   UnregisterProcessor();
index 0c16fd9..f89bb91 100644 (file)
@@ -25,7 +25,6 @@
 #include <dali/devel-api/threading/thread.h>
 #include <dali/integration-api/adaptor-framework/log-factory-interface.h>
 #include <dali/public-api/common/intrusive-ptr.h>
-#include <dali/public-api/images/pixel-data.h>
 #include <dali/public-api/object/ref-object.h>
 #include <dali/public-api/rendering/texture-set.h>
 #include <memory>
@@ -81,15 +80,9 @@ public:
 
   /**
    * Get the rasterization result.
-   * @return The pixel data with the rasterized pixels.
+   * @return The texture with the rasterized pixels.
    */
-  PixelData GetPixelData() const;
-
-  /**
-   * Get size of rasterization result.
-   * @return The size of the pixel data.
-   */
-  Vector2 GetBufferSize() const;
+  Texture GetRasterizedTexture();
 
 private:
   // Undefined
@@ -101,8 +94,7 @@ private:
 private:
   CanvasViewPtr  mCanvasView;
   CanvasRenderer mCanvasRenderer;
-  PixelData      mPixelData;
-  Vector2        mBufferSize;
+  Texture        mRasterizedTexture;
 };
 
 /**
@@ -112,7 +104,7 @@ class CanvasViewRasterizeThread : public Thread, Integration::Processor
 {
 public:
   /// @brief ApplyRasterizedImage Event signal type
-  using RasterizationCompletedSignalType = Signal<void(PixelData)>;
+  using RasterizationCompletedSignalType = Signal<void(Texture)>;
 
 public:
   /**
index f9f4376..b81149c 100644 (file)
@@ -36,6 +36,7 @@
 #include <limits>
 
 // INTERNAL INCLUDES
+#include <dali-toolkit/devel-api/visuals/visual-actions-devel.h>
 #include <dali-toolkit/devel-api/asset-manager/asset-manager.h>
 #include <dali-toolkit/devel-api/controls/control-depth-index-ranges.h>
 #include <dali-toolkit/devel-api/controls/control-devel.h>
@@ -1970,115 +1971,46 @@ Dali::Property Control::Impl::GetVisualProperty(Dali::Property::Index index, Dal
   return Dali::Property(handle, Property::INVALID_INDEX);
 }
 
-void Control::Impl::MakeVisualTransition(Dali::Animation& animation, Dali::Toolkit::Control source, Dali::Property::Index visualIndex, AlphaFunction alphaFunction, TimePeriod timePeriod)
+void Control::Impl::CreateTransitions(std::vector<std::pair<Dali::Property::Index, Dali::Property::Map>>& sourceProperties,
+                                      std::vector<std::pair<Dali::Property::Index, Dali::Property::Map>>& destinationProperties,
+                                      Dali::Toolkit::Control source, Dali::Toolkit::Control destination)
 {
-  Dali::Toolkit::Control sourceHandle      = Dali::Toolkit::Control::DownCast(source);
-  Property::Map          sourceMap         = sourceHandle.GetProperty<Property::Map>(visualIndex);
-  Dali::Toolkit::Control destinationHandle = Dali::Toolkit::Control::DownCast(mControlImpl.Self());
-  Property::Map          destinationMap    = destinationHandle.GetProperty<Property::Map>(visualIndex);
-
-  Vector4 mixColor(1.0f, 1.0f, 1.0f, 1.0f);
-  Vector4 cornerRadius(0.0f, 0.0f, 0.0f, 0.0f);
-  float   borderlineWidth(0.0f);
-  Vector4 borderlineColor(0.0f, 0.0f, 0.0f, 1.0f);
-  float   borderlineOffset(0.0f);
-
-  if(!destinationMap.Empty())
+  // Retrieves background properties to be transitioned.
+  Dali::Property::Map backgroundSourcePropertyMap, backgroundDestinationPropertyMap;
+  mControlImpl.MakeVisualTransition(backgroundSourcePropertyMap, backgroundDestinationPropertyMap, source, destination, Toolkit::Control::Property::BACKGROUND);
+  if(backgroundSourcePropertyMap.Count() > 0)
   {
-    static auto findValueVector4 = [](const Property::Map& map, Property::Index index, const Vector4& defaultValue = Vector4()) -> Vector4 {
-      Property::Value* propertyValue = map.Find(index);
-      if(propertyValue)
-      {
-        return propertyValue->Get<Vector4>();
-      }
-      return defaultValue;
-    };
-
-    static auto findValueFloat = [](const Property::Map& map, Property::Index index, const float& defaultValue = 0.0f) -> float {
-      Property::Value* propertyValue = map.Find(index);
-      if(propertyValue)
-      {
-        return propertyValue->Get<float>();
-      }
-      return defaultValue;
-    };
-
-    mixColor         = findValueVector4(destinationMap, Dali::Toolkit::Visual::Property::MIX_COLOR, mixColor);
-    cornerRadius     = findValueVector4(destinationMap, Toolkit::DevelVisual::Property::CORNER_RADIUS, cornerRadius);
-    borderlineWidth  = findValueFloat(destinationMap, Toolkit::DevelVisual::Property::BORDERLINE_WIDTH, borderlineWidth);
-    borderlineColor  = findValueVector4(destinationMap, Toolkit::DevelVisual::Property::BORDERLINE_COLOR, borderlineColor);
-    borderlineOffset = findValueFloat(destinationMap, Toolkit::DevelVisual::Property::BORDERLINE_OFFSET, borderlineOffset);
-
-    if(sourceMap.Empty())
-    {
-      sourceMap.Insert(Toolkit::Visual::Property::TYPE, Toolkit::Visual::COLOR);
-      sourceMap.Insert(Dali::Toolkit::Visual::Property::MIX_COLOR, Color::TRANSPARENT);
-      sourceMap.Insert(Toolkit::DevelVisual::Property::CORNER_RADIUS, cornerRadius);
-      sourceMap.Insert(Toolkit::DevelVisual::Property::BORDERLINE_WIDTH, borderlineWidth);
-      sourceMap.Insert(Toolkit::DevelVisual::Property::BORDERLINE_COLOR, borderlineColor);
-      sourceMap.Insert(Toolkit::DevelVisual::Property::BORDERLINE_OFFSET, borderlineOffset);
-    }
-
-    Vector4 sourceMixColor         = findValueVector4(sourceMap, Dali::Toolkit::Visual::Property::MIX_COLOR, mixColor);
-    Vector4 sourceCornerRadius     = findValueVector4(sourceMap, Toolkit::DevelVisual::Property::CORNER_RADIUS, cornerRadius);
-    float   sourceBorderlineWidth  = findValueFloat(sourceMap, Toolkit::DevelVisual::Property::BORDERLINE_WIDTH, borderlineWidth);
-    Vector4 sourceBorderlineColor  = findValueVector4(sourceMap, Toolkit::DevelVisual::Property::BORDERLINE_COLOR, borderlineColor);
-    float   sourceBorderlineOffset = findValueFloat(sourceMap, Toolkit::DevelVisual::Property::BORDERLINE_OFFSET, borderlineOffset);
-
-    std::vector<Dali::Property>                              properties;
-    std::vector<std::pair<Property::Value, Property::Value>> values;
-
-    if(Vector3(sourceMixColor) != Vector3(mixColor))
-    {
-      properties.push_back(GetVisualProperty(visualIndex, Dali::Toolkit::Visual::Property::MIX_COLOR));
-      values.push_back(std::make_pair(Vector3(sourceMixColor), Vector3(mixColor)));
-    }
-
-    if(std::abs(sourceMixColor.a - mixColor.a) > Math::MACHINE_EPSILON_1)
-    {
-      properties.push_back(GetVisualProperty(visualIndex, Dali::Toolkit::Visual::Property::OPACITY));
-      values.push_back(std::make_pair(sourceMixColor.a, mixColor.a));
-    }
-
-    if(sourceCornerRadius != cornerRadius)
-    {
-      properties.push_back(GetVisualProperty(visualIndex, Dali::Toolkit::DevelVisual::Property::CORNER_RADIUS));
-      values.push_back(std::make_pair(sourceCornerRadius, cornerRadius));
-    }
+    sourceProperties.push_back(std::pair<Dali::Property::Index, Dali::Property::Map>(Toolkit::Control::Property::BACKGROUND, backgroundSourcePropertyMap));
+    destinationProperties.push_back(std::pair<Dali::Property::Index, Dali::Property::Map>(Toolkit::Control::Property::BACKGROUND, backgroundDestinationPropertyMap));
+  }
 
-    if(sourceBorderlineWidth != borderlineWidth)
-    {
-      properties.push_back(GetVisualProperty(visualIndex, Dali::Toolkit::DevelVisual::Property::BORDERLINE_WIDTH));
-      values.push_back(std::make_pair(sourceBorderlineWidth, borderlineWidth));
-    }
+  // Retrieves shadow properties to be transitioned.
+  Dali::Property::Map shadowSourcePropertyMap, shadowDestinationPropertyMap;
+  mControlImpl.MakeVisualTransition(shadowSourcePropertyMap, shadowDestinationPropertyMap, source, destination, Toolkit::DevelControl::Property::SHADOW);
+  if(shadowSourcePropertyMap.Count() > 0)
+  {
+    sourceProperties.push_back(std::pair<Dali::Property::Index, Dali::Property::Map>(Toolkit::DevelControl::Property::SHADOW, shadowSourcePropertyMap));
+    destinationProperties.push_back(std::pair<Dali::Property::Index, Dali::Property::Map>(Toolkit::DevelControl::Property::SHADOW, shadowDestinationPropertyMap));
+  }
 
-    if(sourceBorderlineColor != borderlineColor)
-    {
-      properties.push_back(GetVisualProperty(visualIndex, Dali::Toolkit::DevelVisual::Property::BORDERLINE_COLOR));
-      values.push_back(std::make_pair(sourceBorderlineColor, borderlineColor));
-    }
+  // Retrieves transition from inherited class.
+  mControlImpl.OnCreateTransitions(sourceProperties, destinationProperties, source, destination);
+}
 
-    if(sourceBorderlineOffset != borderlineOffset)
+void Control::Impl::UpdateVisualProperties(const std::vector<std::pair<Dali::Property::Index, Dali::Property::Map>>& properties)
+{
+  for(auto&& data : properties)
+  {
+    if(data.first == Toolkit::Control::Property::BACKGROUND)
     {
-      properties.push_back(GetVisualProperty(visualIndex, Dali::Toolkit::DevelVisual::Property::BORDERLINE_OFFSET));
-      values.push_back(std::make_pair(sourceBorderlineOffset, borderlineOffset));
+      DoAction(Toolkit::Control::Property::BACKGROUND, DevelVisual::Action::UPDATE_PROPERTY, data.second);
     }
-
-    for(uint32_t i = 0; i < properties.size(); ++i)
+    else if(data.first == Toolkit::DevelControl::Property::SHADOW)
     {
-      if(timePeriod.delaySeconds > 0.0f)
-      {
-        Dali::KeyFrames initialKeyframes = Dali::KeyFrames::New();
-        initialKeyframes.Add(0.0f, values[i].first);
-        initialKeyframes.Add(1.0f, values[i].first);
-        animation.AnimateBetween(properties[i], initialKeyframes, TimePeriod(timePeriod.delaySeconds));
-      }
-      Dali::KeyFrames keyframes = Dali::KeyFrames::New();
-      keyframes.Add(0.0f, values[i].first);
-      keyframes.Add(1.0f, values[i].second);
-      animation.AnimateBetween(properties[i], keyframes, alphaFunction, timePeriod);
+      DoAction(Toolkit::DevelControl::Property::SHADOW, DevelVisual::Action::UPDATE_PROPERTY, data.second);
     }
   }
+  mControlImpl.OnUpdateVisualProperties(properties);
 }
 
 void Control::Impl::EmitResourceReadySignal()
index 94da0fc..55c49a6 100644 (file)
@@ -393,16 +393,32 @@ public:
   Dali::Property GetVisualProperty(Dali::Property::Index index, Dali::Property::Key visualPropertyKey);
 
   /**
-   * @brief Make visual transition from source control to this control about specific Property::Index
-   * If both of source and this control have Property::Index property, than create animation between them.
+   * @brief Retrieves source and destination visual properties for the Transition of this Control.
+   * The properties of this Control will be transitioned from the propeties of source Control to that of destination control.
+   * If a property value is different between source and destination Control,
+   * the property information of each Control will be included in sourceProperties and destinationProperties.
    *
-   * @param[in] animation Return animation from source to this control.
-   * @param[in] source Source control to be used property animation.
-   * @param[in] visualIndex Property::Index to make animation.
-   * @param[in] alphaFunction alpha function of the animation.
-   * @param[in] timePeriod time period of the animation.
+   * @param[out] sourceProperties Source property list to be applied on this Control.
+   * @param[out] destinationProperties Destination property list to be applied on this Control.
+   * @param[in] source Source control of the animation.
+   * @param[in] destination Destination control of the animation.
+   *
+   * @note This method do not handle Actor properties.
+   * And the size and order of the sourceProperties and destinationProperties must be synchronized.
+   *
+   * This method triggers Control::OnCreateTransition().
+   */
+  void CreateTransitions(std::vector<std::pair<Dali::Property::Index, Dali::Property::Map>>& sourceProperties,
+                         std::vector<std::pair<Dali::Property::Index, Dali::Property::Map>>& destinationProperties,
+                         Dali::Toolkit::Control source, Dali::Toolkit::Control destination);
+
+  /**
+   * @brief Update visual properties.
+   * @param[in] properties Property list to be used to update visual properties of this Control.
+   *
+   * @note This method triggers Control::OnUpdateVisualProperties().
    */
-  void MakeVisualTransition(Dali::Animation& animation, Dali::Toolkit::Control source, Dali::Property::Index visualIndex, AlphaFunction alphaFunction, TimePeriod timePeriod);
+  void UpdateVisualProperties(const std::vector<std::pair<Dali::Property::Index, Dali::Property::Map>>& properties);
 
   /**
    * @brief Gets the current control's accessible object.
index a3c092d..4a3b065 100644 (file)
@@ -39,7 +39,7 @@ namespace
 // currently not called from code so compiler will optimize these away, kept here for future debugging
 
 #define FLEX_CONTAINER_TAG "DALI Toolkit::FlexContainer "
-#define FC_LOG(fmt, args, ...) Debug::LogMessage(Debug::DebugInfo, FLEX_CONTAINER_TAG fmt, ##args)
+#define FC_LOG(fmt, args, ...) Debug::LogMessageWithFunctionLine(Debug::DebugInfo, FLEX_CONTAINER_TAG fmt, ##args)
 // #define FLEX_CONTAINER_DEBUG 1
 
 #if defined(FLEX_CONTAINER_DEBUG)
index 64e31d6..b37189a 100644 (file)
@@ -67,11 +67,11 @@ GlView::~GlView()
   }
 }
 
-void GlView::RegisterGlCallback(CallbackBase* initCallback, CallbackBase* renderFrameCallback, CallbackBase* terminateCallback)
+void GlView::RegisterGlCallbacks(CallbackBase* initCallback, CallbackBase* renderFrameCallback, CallbackBase* terminateCallback)
 {
   if(mRenderThread)
   {
-    mRenderThread->RegisterGlCallback(initCallback, renderFrameCallback, terminateCallback);
+    mRenderThread->RegisterGlCallbacks(initCallback, renderFrameCallback, terminateCallback);
   }
 }
 
index c0114ca..2dcb0b1 100644 (file)
@@ -55,9 +55,9 @@ public:
   GlView(Dali::Toolkit::GlView::ColorFormat colorFormat);
 
   /**
-   * @copydoc Dali::Toolkit::GlView::RegisterGlCallback()
+   * @copydoc Dali::Toolkit::GlView::RegisterGlCallbacks()
    */
-  void RegisterGlCallback(CallbackBase* initCallback, CallbackBase* renderFrameCallback, CallbackBase* terminateCallback);
+  void RegisterGlCallbacks(CallbackBase* initCallback, CallbackBase* renderFrameCallback, CallbackBase* terminateCallback);
 
   /**
    * @copydoc Dali::Toolkit::GlView::SetResizeCallback()
index db2e98c..3e84cfd 100644 (file)
@@ -72,7 +72,7 @@ GlViewRenderThread::GlViewRenderThread(Dali::NativeImageSourceQueuePtr queue)
   }
 }
 
-void GlViewRenderThread::RegisterGlCallback(CallbackBase* initCallback, CallbackBase* renderFrameCallback, CallbackBase* terminateCallback)
+void GlViewRenderThread::RegisterGlCallbacks(CallbackBase* initCallback, CallbackBase* renderFrameCallback, CallbackBase* terminateCallback)
 {
   if(!mGlInitCallback && !mGlRenderFrameCallback && !mGlTerminateCallback)
   {
index c27c832..753526e 100644 (file)
@@ -54,9 +54,9 @@ public:
   virtual ~GlViewRenderThread();
 
   /**
-   * @copydoc Dali::Toolkit::GlView::RegisterGlCallback()
+   * @copydoc Dali::Toolkit::GlView::RegisterGlCallbacks()
    */
-  void RegisterGlCallback(CallbackBase* initCallback, CallbackBase* renderFrameCallback, CallbackBase* terminateCallback);
+  void RegisterGlCallbacks(CallbackBase* initCallback, CallbackBase* renderFrameCallback, CallbackBase* terminateCallback);
 
   /**
    * @copydoc Dali::Toolkit::GlView::SetResizeCallback()
index e3701ec..1a653a1 100644 (file)
@@ -24,6 +24,7 @@
 #include <dali/public-api/object/type-registry.h>
 
 // INTERNAL INCLUDES
+#include <dali-toolkit/devel-api/visuals/visual-actions-devel.h>
 #include <dali-toolkit/devel-api/controls/control-devel.h>
 #include <dali-toolkit/devel-api/visual-factory/visual-factory.h>
 #include <dali-toolkit/internal/controls/control/control-data-impl.h>
@@ -284,114 +285,36 @@ void ImageView::OnRelayout(const Vector2& size, RelayoutContainer& container)
   }
 }
 
-void ImageView::OnCreateTransitions(Dali::Animation& animation, Dali::Toolkit::Control source, AlphaFunction alphaFunction, TimePeriod timePeriod)
+void ImageView::OnCreateTransitions(std::vector<std::pair<Dali::Property::Index, Dali::Property::Map>>& sourceProperties,
+                                    std::vector<std::pair<Dali::Property::Index, Dali::Property::Map>>& destinationProperties,
+                                    Dali::Toolkit::Control                                              source,
+                                    Dali::Toolkit::Control                                              destination)
 {
-  Dali::Toolkit::ImageView destinationHandle = Toolkit::ImageView(GetOwner());
-  Toolkit::Visual::Base    destinationVisual = DevelControl::GetVisual(GetImplementation(destinationHandle), Toolkit::ImageView::Property::IMAGE);
-  Property::Map            destinationMap;
-
-  if(!destinationVisual)
-  {
-    return;
-  }
-
-  destinationVisual.CreatePropertyMap(destinationMap);
-
-  static auto findValueVector4 = [](const Property::Map& map, Property::Index index, const Vector4& defaultValue = Vector4()) -> Vector4 {
-    Property::Value* propertyValue = map.Find(index);
-    if(propertyValue)
-    {
-      return propertyValue->Get<Vector4>();
-    }
-    return defaultValue;
-  };
-
-  static auto findValueFloat = [](const Property::Map& map, Property::Index index, const float& defaultValue = 0.0f) -> float {
-    Property::Value* propertyValue = map.Find(index);
-    if(propertyValue)
-    {
-      return propertyValue->Get<float>();
-    }
-    return defaultValue;
-  };
-
-  Vector4 sourceMixColor(0.0f, 0.0f, 0.0f, 0.0f);
-  Vector4 sourceCornerRadius(0.0f, 0.0f, 0.0f, 0.0f);
-  float   sourceBorderlineWidth(0.0f);
-  Vector4 sourceBorderlineColor(0.0f, 0.0f, 0.0f, 1.0f);
-  float   sourceBorderlineOffset(0.0f);
-  Vector4 destinationMixColor         = findValueVector4(destinationMap, Dali::Toolkit::Visual::Property::MIX_COLOR, sourceMixColor);
-  Vector4 destinationCornerRadius     = findValueVector4(destinationMap, Toolkit::DevelVisual::Property::CORNER_RADIUS, sourceCornerRadius);
-  float   destinationBorderlineWidth  = findValueFloat(destinationMap, Toolkit::DevelVisual::Property::BORDERLINE_WIDTH, sourceBorderlineWidth);
-  Vector4 destinationBorderlineColor  = findValueVector4(destinationMap, Toolkit::DevelVisual::Property::BORDERLINE_COLOR, sourceBorderlineColor);
-  float   destinationBorderlineOffset = findValueFloat(destinationMap, Toolkit::DevelVisual::Property::BORDERLINE_OFFSET, sourceBorderlineOffset);
-
-  Dali::Toolkit::ImageView sourceHandle = Dali::Toolkit::ImageView::DownCast(source);
-  Toolkit::Visual::Base    sourceVisual;
-  Property::Map            sourceMap;
-
-  if(sourceHandle)
-  {
-    sourceVisual = DevelControl::GetVisual(GetImplementation(sourceHandle), Toolkit::ImageView::Property::IMAGE);
-  }
-
-  if(sourceVisual)
+  // Retrieves image properties to be transitioned.
+  Dali::Property::Map imageSourcePropertyMap, imageDestinationPropertyMap;
+  MakeVisualTransition(imageSourcePropertyMap, imageDestinationPropertyMap, source, destination, Toolkit::ImageView::Property::IMAGE);
+  if(imageSourcePropertyMap.Count() > 0)
   {
-    sourceVisual.CreatePropertyMap(sourceMap);
-    sourceMixColor         = findValueVector4(sourceMap, Dali::Toolkit::Visual::Property::MIX_COLOR, sourceMixColor);
-    sourceCornerRadius     = findValueVector4(sourceMap, Toolkit::DevelVisual::Property::CORNER_RADIUS, sourceCornerRadius);
-    sourceBorderlineWidth  = findValueFloat(sourceMap, Toolkit::DevelVisual::Property::BORDERLINE_WIDTH, sourceBorderlineWidth);
-    sourceBorderlineColor  = findValueVector4(sourceMap, Toolkit::DevelVisual::Property::BORDERLINE_COLOR, sourceBorderlineColor);
-    sourceBorderlineOffset = findValueFloat(sourceMap, Toolkit::DevelVisual::Property::BORDERLINE_OFFSET, sourceBorderlineOffset);
+    sourceProperties.push_back(std::pair<Dali::Property::Index, Dali::Property::Map>(Toolkit::ImageView::Property::IMAGE, imageSourcePropertyMap));
+    destinationProperties.push_back(std::pair<Dali::Property::Index, Dali::Property::Map>(Toolkit::ImageView::Property::IMAGE, imageDestinationPropertyMap));
   }
+}
 
-  std::vector<Dali::Property>                              properties;
-  std::vector<std::pair<Property::Value, Property::Value>> values;
-
-  if(Vector3(sourceMixColor) != Vector3(destinationMixColor))
-  {
-    properties.push_back(DevelControl::GetVisualProperty(destinationHandle, Toolkit::ImageView::Property::IMAGE, Toolkit::Visual::Property::MIX_COLOR));
-    values.push_back(std::make_pair(Vector3(sourceMixColor), Vector3(destinationMixColor)));
-  }
-  if(std::abs(sourceMixColor.a - destinationMixColor.a) > Math::MACHINE_EPSILON_1)
-  {
-    properties.push_back(DevelControl::GetVisualProperty(destinationHandle, Toolkit::ImageView::Property::IMAGE, Toolkit::Visual::Property::OPACITY));
-    values.push_back(std::make_pair(sourceMixColor.a, destinationMixColor.a));
-  }
-  if(sourceCornerRadius != destinationCornerRadius)
-  {
-    properties.push_back(DevelControl::GetVisualProperty(destinationHandle, Toolkit::ImageView::Property::IMAGE, Toolkit::DevelVisual::Property::CORNER_RADIUS));
-    values.push_back(std::make_pair(sourceCornerRadius, destinationCornerRadius));
-  }
-  if(sourceBorderlineWidth != destinationBorderlineWidth)
-  {
-    properties.push_back(DevelControl::GetVisualProperty(destinationHandle, Toolkit::ImageView::Property::IMAGE, Toolkit::DevelVisual::Property::BORDERLINE_WIDTH));
-    values.push_back(std::make_pair(sourceBorderlineWidth, destinationBorderlineWidth));
-  }
-  if(sourceBorderlineColor != destinationBorderlineColor)
-  {
-    properties.push_back(DevelControl::GetVisualProperty(destinationHandle, Toolkit::ImageView::Property::IMAGE, Toolkit::DevelVisual::Property::BORDERLINE_COLOR));
-    values.push_back(std::make_pair(sourceBorderlineColor, destinationBorderlineColor));
-  }
-  if(sourceBorderlineOffset != destinationBorderlineOffset)
+void ImageView::OnUpdateVisualProperties(const std::vector<std::pair<Dali::Property::Index, Dali::Property::Map>>& properties)
+{
+  Toolkit::Visual::Base visual = DevelControl::GetVisual(*this, Toolkit::ImageView::Property::IMAGE);
+  if(visual)
   {
-    properties.push_back(DevelControl::GetVisualProperty(destinationHandle, Toolkit::ImageView::Property::IMAGE, Toolkit::DevelVisual::Property::BORDERLINE_OFFSET));
-    values.push_back(std::make_pair(sourceBorderlineOffset, destinationBorderlineOffset));
-  }
+    Dali::Toolkit::Control handle(GetOwner());
 
-  for(uint32_t i = 0; i < properties.size(); ++i)
-  {
-    if(timePeriod.delaySeconds > 0.0f)
+    for(auto&& data : properties)
     {
-      Dali::KeyFrames initialKeyframes = Dali::KeyFrames::New();
-      initialKeyframes.Add(0.0f, values[i].first);
-      initialKeyframes.Add(1.0f, values[i].first);
-      animation.AnimateBetween(properties[i], initialKeyframes, TimePeriod(timePeriod.delaySeconds));
+      if(data.first == Toolkit::ImageView::Property::IMAGE)
+      {
+        DevelControl::DoAction(handle, Toolkit::ImageView::Property::IMAGE, DevelVisual::Action::UPDATE_PROPERTY, data.second);
+        break;
+      }
     }
-    Dali::KeyFrames keyframes = Dali::KeyFrames::New();
-    keyframes.Add(0.0f, values[i].first);
-    keyframes.Add(1.0f, values[i].second);
-    animation.AnimateBetween(properties[i], keyframes, alphaFunction, timePeriod);
   }
 }
 
index 023930e..ef48839 100644 (file)
@@ -136,7 +136,15 @@ private: // From Control
   /**
    * @copydoc Toolkit::Control::OnCreateTransitions()
    */
-  virtual void OnCreateTransitions(Dali::Animation& animation, Dali::Toolkit::Control source, AlphaFunction alphaFunction, TimePeriod timePeriod) override;
+  virtual void OnCreateTransitions(std::vector<std::pair<Dali::Property::Index, Dali::Property::Map>>& sourceProperties,
+                                   std::vector<std::pair<Dali::Property::Index, Dali::Property::Map>>& destinationProperties,
+                                   Dali::Toolkit::Control                                              source,
+                                   Dali::Toolkit::Control                                              destination) override;
+
+  /**
+   * @copydoc Toolkit::Control::OnUpdateVisualProperties()
+   */
+  virtual void OnUpdateVisualProperties(const std::vector<std::pair<Dali::Property::Index, Dali::Property::Map>>& properties) override;
 
 private:
   /**
diff --git a/dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-impl-constraints.cpp b/dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-impl-constraints.cpp
new file mode 100644 (file)
index 0000000..24827dd
--- /dev/null
@@ -0,0 +1,552 @@
+/*
+ * 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 <dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-impl-constraints.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/public-api/controls/scrollable/scroll-view/scroll-view-constraints.h>
+#include <dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-impl.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Internal
+{
+namespace
+{
+
+float FinalDefaultAlphaFunction(float offset)
+{
+  return offset * 0.5f;
+}
+
+/**
+ * Internal Relative position Constraint
+ * Generates the relative position value of the scroll view
+ * based on the absolute position, and it's relation to the
+ * scroll domain. This is a value from 0.0f to 1.0f in each
+ * scroll position axis.
+ */
+void InternalRelativePositionConstraint(Vector2& relativePosition, const PropertyInputContainer& inputs)
+{
+  Vector2        position = -inputs[0]->GetVector2();
+  const Vector2& min      = inputs[1]->GetVector2();
+  const Vector2& max      = inputs[2]->GetVector2();
+  const Vector3& size     = inputs[3]->GetVector3();
+
+  position.x = WrapInDomain(position.x, min.x, max.x);
+  position.y = WrapInDomain(position.y, min.y, max.y);
+
+  Vector2 domainSize = (max - min) - size.GetVectorXY();
+
+  relativePosition.x = domainSize.x > Math::MACHINE_EPSILON_1 ? fabsf((position.x - min.x) / domainSize.x) : 0.0f;
+  relativePosition.y = domainSize.y > Math::MACHINE_EPSILON_1 ? fabsf((position.y - min.y) / domainSize.y) : 0.0f;
+}
+
+/**
+ * Internal scroll domain Constraint
+ * Generates the scroll domain of the scroll view.
+ */
+void InternalScrollDomainConstraint(Vector2& scrollDomain, const PropertyInputContainer& inputs)
+{
+  const Vector2& min  = inputs[0]->GetVector2();
+  const Vector2& max  = inputs[1]->GetVector2();
+  const Vector3& size = inputs[2]->GetVector3();
+
+  scrollDomain = (max - min) - size.GetVectorXY();
+}
+
+/**
+ * Internal maximum scroll position Constraint
+ * Generates the maximum scroll position of the scroll view.
+ */
+void InternalPrePositionMaxConstraint(Vector2& scrollMax, const PropertyInputContainer& inputs)
+{
+  const Vector2& max  = inputs[0]->GetVector2();
+  const Vector3& size = inputs[1]->GetVector3();
+
+  scrollMax = max - size.GetVectorXY();
+}
+
+/**
+ * Internal Pre-Position Property Constraint.
+ *
+ * Generates position property based on current position + gesture displacement.
+ * Or generates position property based on positionX/Y.
+ * Note: This is the position prior to any clamping at scroll boundaries.
+ */
+struct InternalPrePositionConstraint
+{
+  InternalPrePositionConstraint(const Vector2&       initialPanPosition,
+                                const Vector2&       initialPanMask,
+                                bool                 axisAutoLock,
+                                float                axisAutoLockGradient,
+                                ScrollView::LockAxis initialLockAxis,
+                                const Vector2&       maxOvershoot,
+                                const RulerPtr&      rulerX,
+                                const RulerPtr&      rulerY)
+  : mLocalStart(initialPanPosition),
+    mInitialPanMask(initialPanMask),
+    mMaxOvershoot(maxOvershoot),
+    mAxisAutoLockGradient(axisAutoLockGradient),
+    mLockAxis(initialLockAxis),
+    mAxisAutoLock(axisAutoLock),
+    mWasPanning(false)
+  {
+    const RulerDomain& rulerDomainX = rulerX->GetDomain();
+    const RulerDomain& rulerDomainY = rulerY->GetDomain();
+    mDomainMin                      = Vector2(rulerDomainX.min, -rulerDomainY.min);
+    mDomainMax                      = Vector2(-rulerDomainX.max, -rulerDomainY.max);
+    mClampX                         = rulerDomainX.enabled;
+    mClampY                         = rulerDomainY.enabled;
+    mFixedRulerX                    = rulerX->GetType() == Ruler::FIXED;
+    mFixedRulerY                    = rulerY->GetType() == Ruler::FIXED;
+  }
+
+  void operator()(Vector2& scrollPostPosition, const PropertyInputContainer& inputs)
+  {
+    const Vector2& panPosition = inputs[0]->GetVector2();
+    const bool&    inGesture   = inputs[1]->GetBoolean();
+
+    // First check if we are within a gesture.
+    // The ScrollView may have received a start gesture from ::OnPan()
+    // while the finish gesture is received now in this constraint.
+    // This gesture must then be rejected as the value will be "old".
+    // Typically the last value from the end of the last gesture.
+    // If we are rejecting the gesture, we simply don't modify the constraint target.
+    if(inGesture)
+    {
+      if(!mWasPanning)
+      {
+        mPrePosition    = scrollPostPosition;
+        mStartPosition  = mPrePosition;
+        mCurrentPanMask = mInitialPanMask;
+        mWasPanning     = true;
+      }
+
+      // Calculate Deltas...
+      const Vector2& currentPosition = panPosition;
+      Vector2        panDelta(currentPosition - mLocalStart);
+
+      // Axis Auto Lock - locks the panning to the horizontal or vertical axis if the pan
+      // appears mostly horizontal or mostly vertical respectively...
+      if(mAxisAutoLock)
+      {
+        mLockAxis = GetLockAxis(panDelta, mLockAxis, mAxisAutoLockGradient);
+        if(mLockAxis == ScrollView::LockVertical)
+        {
+          mCurrentPanMask.y = 0.0f;
+        }
+        else if(mLockAxis == ScrollView::LockHorizontal)
+        {
+          mCurrentPanMask.x = 0.0f;
+        }
+      }
+
+      // Restrict deltas based on ruler enable/disable and axis-lock state...
+      panDelta *= mCurrentPanMask;
+
+      // Perform Position transform based on input deltas...
+      scrollPostPosition = mPrePosition;
+      scrollPostPosition += panDelta;
+
+      // if no wrapping then clamp preposition to maximum overshoot amount
+      const Vector3& size = inputs[2]->GetVector3();
+      if(mClampX)
+      {
+        float newXPosition = Clamp(scrollPostPosition.x, (mDomainMax.x + size.x) - mMaxOvershoot.x, mDomainMin.x + mMaxOvershoot.x);
+        if((newXPosition < scrollPostPosition.x - Math::MACHINE_EPSILON_1) || (newXPosition > scrollPostPosition.x + Math::MACHINE_EPSILON_1))
+        {
+          mPrePosition.x = newXPosition;
+          mLocalStart.x  = panPosition.x;
+        }
+        scrollPostPosition.x = newXPosition;
+      }
+      if(mClampY)
+      {
+        float newYPosition = Clamp(scrollPostPosition.y, (mDomainMax.y + size.y) - mMaxOvershoot.y, mDomainMin.y + mMaxOvershoot.y);
+        if((newYPosition < scrollPostPosition.y - Math::MACHINE_EPSILON_1) || (newYPosition > scrollPostPosition.y + Math::MACHINE_EPSILON_1))
+        {
+          mPrePosition.y = newYPosition;
+          mLocalStart.y  = panPosition.y;
+        }
+        scrollPostPosition.y = newYPosition;
+      }
+
+      // If we are using a fixed ruler in a particular axis, limit the maximum pages scrolled on that axis.
+      if(mFixedRulerX || mFixedRulerY)
+      {
+        // Here we limit the maximum amount that can be moved from the starting position of the gesture to one page.
+        // We do this only if we have a fixed ruler (on that axis) and the mode is enabled.
+        // Note: 1.0f is subtracted to keep the value within one page size (otherwise we stray on to the page after).
+        // Note: A further 1.0f is subtracted to handle a compensation that happens later within the flick handling code in SnapWithVelocity().
+        //       When a flick is completed, an adjustment of 1.0f is sometimes made to allow for the scenario where:
+        //       A flick finishes before the update thread has advanced the scroll position past the previous snap point.
+        Vector2 viewPageSizeLimit(size.x - (1.0f + 1.0f), size.y - (1.0f - 1.0f));
+        Vector2 minPosition(mStartPosition.x - viewPageSizeLimit.x, mStartPosition.y - viewPageSizeLimit.y);
+        Vector2 maxPosition(mStartPosition.x + viewPageSizeLimit.x, mStartPosition.y + viewPageSizeLimit.y);
+
+        if(mFixedRulerX)
+        {
+          scrollPostPosition.x = Clamp(scrollPostPosition.x, minPosition.x, maxPosition.x);
+        }
+        if(mFixedRulerY)
+        {
+          scrollPostPosition.y = Clamp(scrollPostPosition.y, minPosition.y, maxPosition.y);
+        }
+      }
+    }
+  }
+
+  Vector2 mPrePosition;
+  Vector2 mLocalStart;
+  Vector2 mStartPosition;  ///< The start position of the gesture - used to limit scroll amount (not modified by clamping).
+  Vector2 mInitialPanMask; ///< Initial pan mask (based on ruler settings).
+  Vector2 mCurrentPanMask; ///< Current pan mask that can be altered by axis lock mode.
+  Vector2 mDomainMin;
+  Vector2 mDomainMax;
+  Vector2 mMaxOvershoot;
+
+  float                mAxisAutoLockGradient; ///< Set by ScrollView
+  ScrollView::LockAxis mLockAxis;
+
+  bool mAxisAutoLock : 1; ///< Set by ScrollView
+  bool mWasPanning : 1;
+  bool mClampX : 1;
+  bool mClampY : 1;
+  bool mFixedRulerX : 1;
+  bool mFixedRulerY : 1;
+};
+
+/**
+ * Internal Position Property Constraint.
+ *
+ * Generates position property based on pre-position
+ * Note: This is the position after clamping.
+ * (uses result of InternalPrePositionConstraint)
+ */
+struct InternalPositionConstraint
+{
+  InternalPositionConstraint(const RulerDomain& domainX, const RulerDomain& domainY, bool wrap)
+  : mDomainMin(-domainX.min, -domainY.min),
+    mDomainMax(-domainX.max, -domainY.max),
+    mClampX(domainX.enabled),
+    mClampY(domainY.enabled),
+    mWrap(wrap)
+  {
+  }
+
+  void operator()(Vector2& position, const PropertyInputContainer& inputs)
+  {
+    position            = inputs[0]->GetVector2();
+    const Vector2& size = inputs[3]->GetVector3().GetVectorXY();
+    const Vector2& min  = inputs[1]->GetVector2();
+    const Vector2& max  = inputs[2]->GetVector2();
+
+    if(mWrap)
+    {
+      position.x = -WrapInDomain(-position.x, min.x, max.x);
+      position.y = -WrapInDomain(-position.y, min.y, max.y);
+    }
+    else
+    {
+      // clamp post position to domain
+      position.x = mClampX ? Clamp(position.x, mDomainMax.x + size.x, mDomainMin.x) : position.x;
+      position.y = mClampY ? Clamp(position.y, mDomainMax.y + size.y, mDomainMin.y) : position.y;
+    }
+  }
+
+  Vector2 mDomainMin;
+  Vector2 mDomainMax;
+  bool    mClampX;
+  bool    mClampY;
+  bool    mWrap;
+};
+
+/**
+ * This constraint updates the X overshoot property using the difference
+ * SCROLL_PRE_POSITION.x and SCROLL_POSITION.x, returning a relative value between 0.0f and 1.0f
+ */
+struct OvershootXConstraint
+{
+  OvershootXConstraint(float maxOvershoot)
+  : mMaxOvershoot(maxOvershoot)
+  {
+  }
+
+  void operator()(float& current, const PropertyInputContainer& inputs)
+  {
+    if(inputs[2]->GetBoolean())
+    {
+      const Vector2& scrollPrePosition  = inputs[0]->GetVector2();
+      const Vector2& scrollPostPosition = inputs[1]->GetVector2();
+      float          newOvershoot       = scrollPrePosition.x - scrollPostPosition.x;
+      current                           = (newOvershoot > 0.0f ? std::min(newOvershoot, mMaxOvershoot) : std::max(newOvershoot, -mMaxOvershoot)) / mMaxOvershoot;
+    }
+    else
+    {
+      current = 0.0f;
+    }
+  }
+
+  float mMaxOvershoot;
+};
+
+/**
+ * This constraint updates the Y overshoot property using the difference
+ * SCROLL_PRE_POSITION.y and SCROLL_POSITION.y, returning a relative value between 0.0f and 1.0f
+ */
+struct OvershootYConstraint
+{
+  OvershootYConstraint(float maxOvershoot)
+  : mMaxOvershoot(maxOvershoot)
+  {
+  }
+
+  void operator()(float& current, const PropertyInputContainer& inputs)
+  {
+    if(inputs[2]->GetBoolean())
+    {
+      const Vector2& scrollPrePosition  = inputs[0]->GetVector2();
+      const Vector2& scrollPostPosition = inputs[1]->GetVector2();
+      float          newOvershoot       = scrollPrePosition.y - scrollPostPosition.y;
+      current                           = (newOvershoot > 0.0f ? std::min(newOvershoot, mMaxOvershoot) : std::max(newOvershoot, -mMaxOvershoot)) / mMaxOvershoot;
+    }
+    else
+    {
+      current = 0.0f;
+    }
+  }
+
+  float mMaxOvershoot;
+};
+
+/**
+ * Internal Position-Delta Property Constraint.
+ *
+ * Generates position-delta property based on scroll-position + scroll-offset properties.
+ */
+void InternalPositionDeltaConstraint(Vector2& current, const PropertyInputContainer& inputs)
+{
+  const Vector2& scrollPosition = inputs[0]->GetVector2();
+  const Vector2& scrollOffset   = inputs[1]->GetVector2();
+
+  current = scrollPosition + scrollOffset;
+}
+
+/**
+ * Internal Final Position Constraint
+ * The position of content is:
+ * of scroll-position + f(scroll-overshoot)
+ * where f(...) function defines how overshoot
+ * should affect final-position.
+ */
+struct InternalFinalConstraint
+{
+  InternalFinalConstraint(AlphaFunctionPrototype functionX,
+                          AlphaFunctionPrototype functionY)
+  : mFunctionX(functionX),
+    mFunctionY(functionY)
+  {
+  }
+
+  void operator()(Vector2& current, const PropertyInputContainer& inputs)
+  {
+    const float& overshootx = inputs[1]->GetFloat();
+    const float& overshooty = inputs[2]->GetFloat();
+    Vector2      offset(mFunctionX(overshootx),
+                   mFunctionY(overshooty));
+
+    current = inputs[0]->GetVector2() - offset;
+  }
+
+  AlphaFunctionPrototype mFunctionX;
+  AlphaFunctionPrototype mFunctionY;
+};
+
+} // namespace
+
+void ScrollViewConstraints::UpdateMainInternalConstraint(ScrollView& scrollView)
+{
+  // TODO: Only update the constraints which have changed, rather than remove all and add all again.
+  // Requires a dali-core ApplyConstraintAt, or a ReplaceConstraint. The former is probably more flexible.
+  Actor              scrollViewActor = scrollView.Self();
+  PanGestureDetector detector(scrollView.GetPanGestureDetector());
+
+  if(mScrollMainInternalPositionConstraint)
+  {
+    mScrollMainInternalPositionConstraint.Remove();
+    mScrollMainInternalDeltaConstraint.Remove();
+    mScrollMainInternalFinalConstraint.Remove();
+    mScrollMainInternalRelativeConstraint.Remove();
+    mScrollMainInternalDomainConstraint.Remove();
+    mScrollMainInternalPrePositionMaxConstraint.Remove();
+  }
+  if(mScrollMainInternalPrePositionConstraint)
+  {
+    mScrollMainInternalPrePositionConstraint.Remove();
+  }
+
+  // TODO: It's probably better to use a local displacement value as this will give a displacement when scrolling just commences
+  // but we need to make sure than the gesture system gives displacement since last frame (60Hz), not displacement since last touch event (90Hz).
+
+  // 1. First calculate the pre-position (this is the scroll position if no clamping has taken place)
+  Vector2 initialPanMask = Vector2(scrollView.mRulerX->IsEnabled() ? 1.0f : 0.0f, scrollView.mRulerY->IsEnabled() ? 1.0f : 0.0f);
+
+  if(scrollView.mLockAxis == ScrollView::LockVertical)
+  {
+    initialPanMask.y = 0.0f;
+  }
+  else if(scrollView.mLockAxis == ScrollView::LockHorizontal)
+  {
+    initialPanMask.x = 0.0f;
+  }
+
+  if(scrollView.mPanning)
+  {
+    mScrollMainInternalPrePositionConstraint = Constraint::New<Vector2>(scrollViewActor,
+                                                                        Toolkit::ScrollView::Property::SCROLL_PRE_POSITION,
+                                                                        InternalPrePositionConstraint(scrollView.mPanStartPosition,
+                                                                                                      initialPanMask,
+                                                                                                      scrollView.mAxisAutoLock,
+                                                                                                      scrollView.mAxisAutoLockGradient,
+                                                                                                      scrollView.mLockAxis,
+                                                                                                      scrollView.mMaxOvershoot,
+                                                                                                      scrollView.mRulerX,
+                                                                                                      scrollView.mRulerY));
+    mScrollMainInternalPrePositionConstraint.AddSource(Source(detector, PanGestureDetector::Property::LOCAL_POSITION));
+    mScrollMainInternalPrePositionConstraint.AddSource(Source(detector, PanGestureDetector::Property::PANNING));
+    mScrollMainInternalPrePositionConstraint.AddSource(Source(scrollViewActor, Actor::Property::SIZE));
+    mScrollMainInternalPrePositionConstraint.Apply();
+  }
+
+  // 2. Second calculate the clamped position (actual position)
+  mScrollMainInternalPositionConstraint = Constraint::New<Vector2>(scrollViewActor,
+                                                                   Toolkit::ScrollView::Property::SCROLL_POSITION,
+                                                                   InternalPositionConstraint(scrollView.mRulerX->GetDomain(),
+                                                                                              scrollView.mRulerY->GetDomain(),
+                                                                                              scrollView.mWrapMode));
+  mScrollMainInternalPositionConstraint.AddSource(LocalSource(Toolkit::ScrollView::Property::SCROLL_PRE_POSITION));
+  mScrollMainInternalPositionConstraint.AddSource(LocalSource(Toolkit::Scrollable::Property::SCROLL_POSITION_MIN));
+  mScrollMainInternalPositionConstraint.AddSource(LocalSource(Toolkit::Scrollable::Property::SCROLL_POSITION_MAX));
+  mScrollMainInternalPositionConstraint.AddSource(Source(scrollViewActor, Actor::Property::SIZE));
+  mScrollMainInternalPositionConstraint.Apply();
+
+  mScrollMainInternalDeltaConstraint = Constraint::New<Vector2>(scrollViewActor, Toolkit::ScrollView::Property::SCROLL_POSITION_DELTA, InternalPositionDeltaConstraint);
+  mScrollMainInternalDeltaConstraint.AddSource(LocalSource(Toolkit::ScrollView::Property::SCROLL_POSITION));
+  mScrollMainInternalDeltaConstraint.AddSource(LocalSource(Toolkit::ScrollView::Property::SCROLL_DOMAIN_OFFSET));
+  mScrollMainInternalDeltaConstraint.Apply();
+
+  mScrollMainInternalFinalConstraint = Constraint::New<Vector2>(scrollViewActor, Toolkit::ScrollView::Property::SCROLL_FINAL, InternalFinalConstraint(FinalDefaultAlphaFunction, FinalDefaultAlphaFunction));
+  mScrollMainInternalFinalConstraint.AddSource(LocalSource(Toolkit::ScrollView::Property::SCROLL_POSITION));
+  mScrollMainInternalFinalConstraint.AddSource(LocalSource(Toolkit::ScrollView::Property::OVERSHOOT_X));
+  mScrollMainInternalFinalConstraint.AddSource(LocalSource(Toolkit::ScrollView::Property::OVERSHOOT_Y));
+  mScrollMainInternalFinalConstraint.Apply();
+
+  mScrollMainInternalRelativeConstraint = Constraint::New<Vector2>(scrollViewActor, Toolkit::Scrollable::Property::SCROLL_RELATIVE_POSITION, InternalRelativePositionConstraint);
+  mScrollMainInternalRelativeConstraint.AddSource(LocalSource(Toolkit::ScrollView::Property::SCROLL_POSITION));
+  mScrollMainInternalRelativeConstraint.AddSource(LocalSource(Toolkit::Scrollable::Property::SCROLL_POSITION_MIN));
+  mScrollMainInternalRelativeConstraint.AddSource(LocalSource(Toolkit::Scrollable::Property::SCROLL_POSITION_MAX));
+  mScrollMainInternalRelativeConstraint.AddSource(LocalSource(Actor::Property::SIZE));
+  mScrollMainInternalRelativeConstraint.Apply();
+
+  mScrollMainInternalDomainConstraint = Constraint::New<Vector2>(scrollViewActor, Toolkit::ScrollView::Property::SCROLL_DOMAIN_SIZE, InternalScrollDomainConstraint);
+  mScrollMainInternalDomainConstraint.AddSource(LocalSource(Toolkit::Scrollable::Property::SCROLL_POSITION_MIN));
+  mScrollMainInternalDomainConstraint.AddSource(LocalSource(Toolkit::Scrollable::Property::SCROLL_POSITION_MAX));
+  mScrollMainInternalDomainConstraint.AddSource(LocalSource(Actor::Property::SIZE));
+  mScrollMainInternalDomainConstraint.Apply();
+
+  mScrollMainInternalPrePositionMaxConstraint = Constraint::New<Vector2>(scrollViewActor, Toolkit::ScrollView::Property::SCROLL_PRE_POSITION_MAX, InternalPrePositionMaxConstraint);
+  mScrollMainInternalPrePositionMaxConstraint.AddSource(LocalSource(Toolkit::Scrollable::Property::SCROLL_POSITION_MAX));
+  mScrollMainInternalPrePositionMaxConstraint.AddSource(LocalSource(Actor::Property::SIZE));
+  mScrollMainInternalPrePositionMaxConstraint.Apply();
+
+  // When panning we want to make sure overshoot values are affected by pre position and post position
+  SetOvershootConstraintsEnabled(scrollView, !scrollView.mWrapMode);
+}
+
+void ScrollViewConstraints::SetOvershootConstraintsEnabled(ScrollView& scrollView, bool enabled)
+{
+  Actor scrollViewActor(scrollView.Self());
+  // remove and reset, it may now be in wrong order with the main internal constraints
+  if(mScrollMainInternalOvershootXConstraint)
+  {
+    mScrollMainInternalOvershootXConstraint.Remove();
+    mScrollMainInternalOvershootXConstraint.Reset();
+    mScrollMainInternalOvershootYConstraint.Remove();
+    mScrollMainInternalOvershootYConstraint.Reset();
+  }
+  if(enabled)
+  {
+    mScrollMainInternalOvershootXConstraint = Constraint::New<float>(scrollViewActor, Toolkit::ScrollView::Property::OVERSHOOT_X, OvershootXConstraint(scrollView.mMaxOvershoot.x));
+    mScrollMainInternalOvershootXConstraint.AddSource(LocalSource(Toolkit::ScrollView::Property::SCROLL_PRE_POSITION));
+    mScrollMainInternalOvershootXConstraint.AddSource(LocalSource(Toolkit::ScrollView::Property::SCROLL_POSITION));
+    mScrollMainInternalOvershootXConstraint.AddSource(LocalSource(Toolkit::Scrollable::Property::CAN_SCROLL_HORIZONTAL));
+    mScrollMainInternalOvershootXConstraint.Apply();
+
+    mScrollMainInternalOvershootYConstraint = Constraint::New<float>(scrollViewActor, Toolkit::ScrollView::Property::OVERSHOOT_Y, OvershootYConstraint(scrollView.mMaxOvershoot.y));
+    mScrollMainInternalOvershootYConstraint.AddSource(LocalSource(Toolkit::ScrollView::Property::SCROLL_PRE_POSITION));
+    mScrollMainInternalOvershootYConstraint.AddSource(LocalSource(Toolkit::ScrollView::Property::SCROLL_POSITION));
+    mScrollMainInternalOvershootYConstraint.AddSource(LocalSource(Toolkit::Scrollable::Property::CAN_SCROLL_VERTICAL));
+    mScrollMainInternalOvershootYConstraint.Apply();
+  }
+  else
+  {
+    scrollViewActor.SetProperty(Toolkit::ScrollView::Property::OVERSHOOT_X, 0.0f);
+    scrollViewActor.SetProperty(Toolkit::ScrollView::Property::OVERSHOOT_Y, 0.0f);
+  }
+}
+
+void ScrollViewConstraints::SetInternalConstraints(ScrollView& scrollView)
+{
+  // Internal constraints (applied to target ScrollBase Actor itself) /////////
+  UpdateMainInternalConstraint(scrollView);
+
+  // User definable constraints to apply to all child actors //////////////////
+  Actor scrollViewActor = scrollView.Self();
+
+  // Apply some default constraints to ScrollView & its bound actors
+  // Movement + Wrap function
+
+  Constraint constraint;
+
+  // MoveActor (scrolling)
+  constraint = Constraint::New<Vector3>(scrollViewActor, Actor::Property::POSITION, MoveActorConstraint);
+  constraint.AddSource(Source(scrollViewActor, Toolkit::ScrollView::Property::SCROLL_POSITION));
+  constraint.SetRemoveAction(Constraint::DISCARD);
+  scrollView.ApplyConstraintToBoundActors(constraint);
+
+  // WrapActor (wrap functionality)
+  constraint = Constraint::New<Vector3>(scrollViewActor, Actor::Property::POSITION, WrapActorConstraint);
+  constraint.AddSource(LocalSource(Actor::Property::SCALE));
+  constraint.AddSource(LocalSource(Actor::Property::ANCHOR_POINT));
+  constraint.AddSource(LocalSource(Actor::Property::SIZE));
+  constraint.AddSource(Source(scrollViewActor, Toolkit::Scrollable::Property::SCROLL_POSITION_MIN));
+  constraint.AddSource(Source(scrollViewActor, Toolkit::Scrollable::Property::SCROLL_POSITION_MAX));
+  constraint.AddSource(Source(scrollViewActor, Toolkit::ScrollView::Property::WRAP));
+  constraint.SetRemoveAction(Constraint::DISCARD);
+  scrollView.ApplyConstraintToBoundActors(constraint);
+}
+
+
+} // namespace Internal
+
+} // namespace Toolkit
+
+} // namespace Dali
diff --git a/dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-impl-constraints.h b/dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-impl-constraints.h
new file mode 100644 (file)
index 0000000..540a3fd
--- /dev/null
@@ -0,0 +1,89 @@
+#ifndef DALI_TOOLKIT_INTERNAL_SCROLL_VIEW_CONSTRAINTS_H
+#define DALI_TOOLKIT_INTERNAL_SCROLL_VIEW_CONSTRAINTS_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 <dali/public-api/animation/constraint.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Internal
+{
+
+class ScrollView;
+
+/// Sets up and owns the Constraints used by the ScrollView class
+class ScrollViewConstraints
+{
+public:
+
+  ScrollViewConstraints() = default;  ///< Default Constructor
+  ~ScrollViewConstraints() = default; ///< Default Non-Virtual Destructor
+
+  // Not copyable or moveable
+  ScrollViewConstraints(const ScrollViewConstraints&) = delete;
+  ScrollViewConstraints(ScrollViewConstraints&&) = delete;
+  ScrollViewConstraints& operator=(const ScrollViewConstraints&) = delete;
+  ScrollViewConstraints& operator=(ScrollViewConstraints&&) = delete;
+
+  /**
+   * Updates the main internal scroll constraints with new ruler and domain values
+   *
+   * @param[in] scrollView A reference to the scroll view object
+   */
+  void UpdateMainInternalConstraint(Internal::ScrollView& scrollView);
+
+  /**
+   * Enables/disables the overshoot constraints
+   *
+   * @param[in] scrollView A reference to the scroll view object
+   * @param[in] enabled whether to enable or disable the overshoot constraints
+   */
+  void SetOvershootConstraintsEnabled(ScrollView& scrollView, bool enabled);
+
+  /**
+   * Sets internal constraints for this ScrollView.
+   * Many of these internal constraints are based on properties within ScrollView.
+   *
+   * @param[in] scrollView A reference to the scroll view object
+   */
+  void SetInternalConstraints(ScrollView& scrollView);
+
+public:
+
+  Constraint mScrollMainInternalPrePositionConstraint;
+  Constraint mScrollMainInternalPositionConstraint;
+  Constraint mScrollMainInternalOvershootXConstraint;
+  Constraint mScrollMainInternalOvershootYConstraint;
+  Constraint mScrollMainInternalDeltaConstraint;
+  Constraint mScrollMainInternalFinalConstraint;
+  Constraint mScrollMainInternalRelativeConstraint;
+  Constraint mScrollMainInternalDomainConstraint;
+  Constraint mScrollMainInternalPrePositionMaxConstraint;
+};
+
+} // namespace Internal
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // DALI_TOOLKIT_INTERNAL_SCROLL_VIEW_CONSTRAINTS_H
index 8ca6855..86cfc56 100644 (file)
@@ -43,7 +43,7 @@
 //#define ENABLED_SCROLL_STATE_LOGGING
 
 #ifdef ENABLED_SCROLL_STATE_LOGGING
-#define DALI_LOG_SCROLL_STATE(format, ...) Dali::Integration::Log::LogMessage(Dali::Integration::Log::DebugInfo, "%s:%d " format "\n", __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__)
+#define DALI_LOG_SCROLL_STATE(format, ...) Dali::Integration::Log::LogMessageWithFunctionLine(Dali::Integration::Log::DebugInfo, "%s:%d " format "\n", __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__)
 #else
 #define DALI_LOG_SCROLL_STATE(format, ...)
 #endif
 // TODO: Orientation.
 // TODO: upgrade Vector2/3 to support returning Unit vectors, normals, & cross product (dot product is already provided)
 
-using namespace Dali;
-
 namespace
 {
-const float DEFAULT_SLOW_SNAP_ANIMATION_DURATION(0.5f);  ///< Default Drag-Release animation time.
-const float DEFAULT_FAST_SNAP_ANIMATION_DURATION(0.25f); ///< Default Drag-Flick animation time.
-const float DEFAULT_SNAP_OVERSHOOT_DURATION(0.5f);       ///< Default Overshoot snapping animation time.
-const float DEFAULT_MAX_OVERSHOOT(100.0f);               ///< Default maximum allowed overshoot in pixels
-
-const float DEFAULT_AXIS_AUTO_LOCK_GRADIENT(0.36f); ///< Default Axis-AutoLock gradient threshold. default is 0.36:1 (20 degrees)
-const float DEFAULT_FRICTION_COEFFICIENT(1.0f);     ///< Default Friction Co-efficient. (in stage diagonals per second)
-const float DEFAULT_FLICK_SPEED_COEFFICIENT(1.0f);  ///< Default Flick speed coefficient (multiples input touch velocity)
-const float DEFAULT_MAX_FLICK_SPEED(3.0f);          ///< Default Maximum flick speed. (in stage diagonals per second)
-
-const Vector2       DEFAULT_MIN_FLICK_DISTANCE(30.0f, 30.0f);                             ///< minimum distance for pan before flick allowed
-const float         DEFAULT_MIN_FLICK_SPEED_THRESHOLD(500.0f);                            ///< Minimum pan speed required for flick in pixels/s
-const float         FREE_FLICK_SPEED_THRESHOLD                    = 200.0f;               ///< Free-Flick threshold in pixels/ms
-const float         AUTOLOCK_AXIS_MINIMUM_DISTANCE2               = 100.0f;               ///< Auto-lock axis after minimum distance squared.
-const float         FLICK_ORTHO_ANGLE_RANGE                       = 75.0f;                ///< degrees. (if >45, then supports diagonal flicking)
-const Vector2       DEFAULT_WHEEL_SCROLL_DISTANCE_STEP_PROPORTION = Vector2(0.17f, 0.1f); ///< The step of horizontal scroll distance in the proportion of stage size for each wheel event received.
-const unsigned long MINIMUM_TIME_BETWEEN_DOWN_AND_UP_FOR_RESET(150u);
-const float         TOUCH_DOWN_TIMER_INTERVAL = 100.0f;
-const float         DEFAULT_SCROLL_UPDATE_DISTANCE(30.0f); ///< Default distance to travel in pixels for scroll update signal
+using namespace Dali;
+
+constexpr float DEFAULT_SLOW_SNAP_ANIMATION_DURATION(0.5f);  ///< Default Drag-Release animation time.
+constexpr float DEFAULT_FAST_SNAP_ANIMATION_DURATION(0.25f); ///< Default Drag-Flick animation time.
+constexpr float DEFAULT_SNAP_OVERSHOOT_DURATION(0.5f);       ///< Default Overshoot snapping animation time.
+constexpr float DEFAULT_MAX_OVERSHOOT(100.0f);               ///< Default maximum allowed overshoot in pixels
+
+constexpr float DEFAULT_AXIS_AUTO_LOCK_GRADIENT(0.36f); ///< Default Axis-AutoLock gradient threshold. default is 0.36:1 (20 degrees)
+constexpr float DEFAULT_FRICTION_COEFFICIENT(1.0f);     ///< Default Friction Co-efficient. (in stage diagonals per second)
+constexpr float DEFAULT_FLICK_SPEED_COEFFICIENT(1.0f);  ///< Default Flick speed coefficient (multiples input touch velocity)
+constexpr float DEFAULT_MAX_FLICK_SPEED(3.0f);          ///< Default Maximum flick speed. (in stage diagonals per second)
+
+constexpr Dali::Vector2 DEFAULT_MIN_FLICK_DISTANCE(30.0f, 30.0f);  ///< minimum distance for pan before flick allowed
+constexpr float         DEFAULT_MIN_FLICK_SPEED_THRESHOLD(500.0f); ///< Minimum pan speed required for flick in pixels/s
+
+constexpr float FREE_FLICK_SPEED_THRESHOLD      = 200.0f; ///< Free-Flick threshold in pixels/ms
+constexpr float AUTOLOCK_AXIS_MINIMUM_DISTANCE2 = 100.0f; ///< Auto-lock axis after minimum distance squared.
+constexpr float FLICK_ORTHO_ANGLE_RANGE         = 75.0f;  ///< degrees. (if >45, then supports diagonal flicking)
+
+constexpr Dali::Vector2 DEFAULT_WHEEL_SCROLL_DISTANCE_STEP_PROPORTION(0.17f, 0.1f); ///< The step of horizontal scroll distance in the proportion of stage size for each wheel event received.
+
+constexpr unsigned long MINIMUM_TIME_BETWEEN_DOWN_AND_UP_FOR_RESET(150u);
+constexpr float         TOUCH_DOWN_TIMER_INTERVAL = 100.0f;
+constexpr float         DEFAULT_SCROLL_UPDATE_DISTANCE(30.0f); ///< Default distance to travel in pixels for scroll update signal
 
 const std::string INTERNAL_MAX_POSITION_PROPERTY_NAME("internalMaxPosition");
 
@@ -104,7 +107,7 @@ float VectorInDomain(float a, float b, float start, float end, Dali::Toolkit::Di
 {
   if(bias == Dali::Toolkit::DIRECTION_BIAS_NONE)
   {
-    return ShortestDistanceInDomain(a, b, start, end);
+    return Dali::ShortestDistanceInDomain(a, b, start, end);
   }
   //  (a-start + end-b)
   float size = end - start;
@@ -145,22 +148,118 @@ float VectorInDomain(float a, float b, float start, float end, Dali::Toolkit::Di
  * @param anchor The Anchor point of interest.
  * @return The position of the Anchor
  */
-Vector3 GetPositionOfAnchor(Actor& actor, const Vector3& anchor)
+Dali::Vector3 GetPositionOfAnchor(Dali::Actor& actor, const Dali::Vector3& anchor)
 {
-  Vector3 childPosition = actor.GetCurrentProperty<Vector3>(Actor::Property::POSITION);
-  Vector3 childAnchor   = -actor.GetCurrentProperty<Vector3>(Actor::Property::ANCHOR_POINT) + anchor;
-  Vector3 childSize     = actor.GetCurrentProperty<Vector3>(Actor::Property::SIZE);
+  Dali::Vector3 childPosition = actor.GetCurrentProperty<Dali::Vector3>(Dali::Actor::Property::POSITION);
+  Dali::Vector3 childAnchor   = -actor.GetCurrentProperty<Dali::Vector3>(Dali::Actor::Property::ANCHOR_POINT) + anchor;
+  Dali::Vector3 childSize     = actor.GetCurrentProperty<Dali::Vector3>(Dali::Actor::Property::SIZE);
 
   return childPosition + childAnchor * childSize;
 }
 
-// AlphaFunctions /////////////////////////////////////////////////////////////////////////////////
+/**
+ * Returns the closest actor to the given position
+ * @param[in] actor The scrollview actor
+ * @param[in] internalActor The internal actor (to ignore)
+ * @param[in] position The given position
+ * @param[in] dirX Direction to search in
+ * @param[in] dirY Direction to search in
+ * @param[in] dirZ Direction to search in
+ * @return the closest child actor
+ */
+using FindDirection = Dali::Toolkit::Internal::ScrollView::FindDirection;
 
-float FinalDefaultAlphaFunction(float offset)
+Actor FindClosestActorToPosition(
+  CustomActor actor, Actor internalActor, const Vector3& position, FindDirection dirX, FindDirection dirY, FindDirection dirZ)
 {
-  return offset * 0.5f;
+  Actor   closestChild;
+  float   closestDistance2 = 0.0f;
+  Vector3 actualPosition   = position;
+
+  unsigned int numChildren = actor.GetChildCount();
+
+  for(unsigned int i = 0; i < numChildren; ++i)
+  {
+    Actor child = actor.GetChildAt(i);
+
+    if(internalActor == child) // ignore internal actor.
+    {
+      continue;
+    }
+
+    Vector3 childPosition = GetPositionOfAnchor(child, AnchorPoint::CENTER);
+
+    Vector3 delta = childPosition - actualPosition;
+
+    // X-axis checking (only find Actors to the [dirX] of actualPosition)
+    if(dirX > FindDirection::All) // != All,None
+    {
+      FindDirection deltaH = delta.x > 0 ? FindDirection::Right : FindDirection::Left;
+      if(dirX != deltaH)
+      {
+        continue;
+      }
+    }
+
+    // Y-axis checking (only find Actors to the [dirY] of actualPosition)
+    if(dirY > FindDirection::All) // != All,None
+    {
+      FindDirection deltaV = delta.y > 0 ? FindDirection::Down : FindDirection::Up;
+      if(dirY != deltaV)
+      {
+        continue;
+      }
+    }
+
+    // Z-axis checking (only find Actors to the [dirZ] of actualPosition)
+    if(dirZ > FindDirection::All) // != All,None
+    {
+      FindDirection deltaV = delta.y > 0 ? FindDirection::In : FindDirection::Out;
+      if(dirZ != deltaV)
+      {
+        continue;
+      }
+    }
+
+    // compare child to closest child in terms of distance.
+    float distance2 = 0.0f;
+
+    // distance2 = the Square of the relevant dimensions of delta
+    if(dirX != FindDirection::None)
+    {
+      distance2 += delta.x * delta.x;
+    }
+
+    if(dirY != FindDirection::None)
+    {
+      distance2 += delta.y * delta.y;
+    }
+
+    if(dirZ != FindDirection::None)
+    {
+      distance2 += delta.z * delta.z;
+    }
+
+    if(closestChild) // Next time.
+    {
+      if(distance2 < closestDistance2)
+      {
+        closestChild     = child;
+        closestDistance2 = distance2;
+      }
+    }
+    else // First time.
+    {
+      closestChild     = child;
+      closestDistance2 = distance2;
+    }
+  }
+
+  return closestChild;
 }
 
+// AlphaFunctions /////////////////////////////////////////////////////////////////////////////////
+
 /**
  * ConstantDecelerationAlphaFunction
  * Newtoninan distance for constant deceleration
@@ -177,54 +276,257 @@ float ConstantDecelerationAlphaFunction(float progress)
   return progress * 2.0f - progress * progress;
 }
 
-// Internal Constraints ///////////////////////////////////////////////////////////////////////////
-
 /**
- * Internal Relative position Constraint
- * Generates the relative position value of the scroll view
- * based on the absolute position, and it's relation to the
- * scroll domain. This is a value from 0.0f to 1.0f in each
- * scroll position axis.
+ * Clamp a position
+ * @param[in] size The size to clamp to
+ * @param[in] rulerX The horizontal ruler
+ * @param[in] rulerY The vertical ruler
+ * @param[in,out] position The position to clamp
+ * @param[out] clamped the clamped state
  */
-void InternalRelativePositionConstraint(Vector2& relativePosition, const PropertyInputContainer& inputs)
+void ClampPosition(const Vector3& size, Dali::Toolkit::RulerPtr rulerX, Dali::Toolkit::RulerPtr rulerY, Vector2& position, Dali::Toolkit::ClampState2D& clamped)
 {
-  Vector2        position = -inputs[0]->GetVector2();
-  const Vector2& min      = inputs[1]->GetVector2();
-  const Vector2& max      = inputs[2]->GetVector2();
-  const Vector3& size     = inputs[3]->GetVector3();
-
-  position.x = WrapInDomain(position.x, min.x, max.x);
-  position.y = WrapInDomain(position.y, min.y, max.y);
-
-  Vector2 domainSize = (max - min) - size.GetVectorXY();
-
-  relativePosition.x = domainSize.x > Math::MACHINE_EPSILON_1 ? fabsf((position.x - min.x) / domainSize.x) : 0.0f;
-  relativePosition.y = domainSize.y > Math::MACHINE_EPSILON_1 ? fabsf((position.y - min.y) / domainSize.y) : 0.0f;
+  position.x = -rulerX->Clamp(-position.x, size.width, 1.0f, clamped.x);  // NOTE: X & Y rulers think in -ve coordinate system.
+  position.y = -rulerY->Clamp(-position.y, size.height, 1.0f, clamped.y); // That is scrolling RIGHT (e.g. 100.0, 0.0) means moving LEFT.
 }
 
 /**
- * Internal scroll domain Constraint
- * Generates the scroll domain of the scroll view.
+ * TODO: In situations where axes are different (X snap, Y free)
+ * Each axis should really have their own independent animation (time and equation)
+ * Consider, X axis snapping to nearest grid point (EaseOut over fixed time)
+ * Consider, Y axis simulating physics to arrive at a point (Physics equation over variable time)
+ * Currently, the axes have been split however, they both use the same EaseOut equation.
+ *
+ * @param[in] scrollView The main scrollview
+ * @param[in] rulerX The X ruler
+ * @param[in] rulerY The Y ruler
+ * @param[in] lockAxis Which axis (if any) is locked.
+ * @param[in] velocity Current pan velocity
+ * @param[in] maxOvershoot Maximum overshoot
+ * @param[in] inAcessibilityPan True if we are currently panning with accessibility
+ * @param[out] positionSnap The target position of snap animation
+ * @param[out] positionDuration The duration of the snap animation
+ * @param[out] alphaFunction The snap animation alpha function
+ * @param[out] isFlick if we are flicking or not
+ * @param[out] isFreeFlick if we are free flicking or not
  */
-void InternalScrollDomainConstraint(Vector2& scrollDomain, const PropertyInputContainer& inputs)
+void SnapWithVelocity(
+  Dali::Toolkit::Internal::ScrollView&          scrollView,
+  Dali::Toolkit::RulerPtr                       rulerX,
+  Dali::Toolkit::RulerPtr                       rulerY,
+  Dali::Toolkit::Internal::ScrollView::LockAxis lockAxis,
+  Vector2                                       velocity,
+  Vector2                                       maxOvershoot,
+  Vector2&                                      positionSnap,
+  Vector2&                                      positionDuration,
+  AlphaFunction&                                alphaFunction,
+  bool                                          inAccessibilityPan,
+  bool&                                         isFlick,
+  bool&                                         isFreeFlick)
 {
-  const Vector2& min  = inputs[0]->GetVector2();
-  const Vector2& max  = inputs[1]->GetVector2();
-  const Vector3& size = inputs[2]->GetVector3();
+  // Animator takes over now, touches are assumed not to interfere.
+  // And if touches do interfere, then we'll stop animation, update PrePosition
+  // to current mScroll's properties, and then resume.
+  // Note: For Flicking this may work a bit different...
 
-  scrollDomain = (max - min) - size.GetVectorXY();
-}
+  float         angle      = atan2(velocity.y, velocity.x);
+  float         speed2     = velocity.LengthSquared();
+  float         biasX      = 0.5f;
+  float         biasY      = 0.5f;
+  FindDirection horizontal = FindDirection::None;
+  FindDirection vertical   = FindDirection::None;
 
-/**
- * Internal maximum scroll position Constraint
- * Generates the maximum scroll position of the scroll view.
- */
-void InternalPrePositionMaxConstraint(Vector2& scrollMax, const PropertyInputContainer& inputs)
-{
-  const Vector2& max  = inputs[0]->GetVector2();
-  const Vector3& size = inputs[1]->GetVector3();
+  using LockAxis = Dali::Toolkit::Internal::ScrollView::LockAxis;
+
+  // orthoAngleRange = Angle tolerance within the Exact N,E,S,W direction
+  // that will be accepted as a general N,E,S,W flick direction.
+
+  const float orthoAngleRange      = FLICK_ORTHO_ANGLE_RANGE * M_PI / 180.0f;
+  const float flickSpeedThreshold2 = scrollView.GetMinimumSpeedForFlick() * scrollView.GetMinimumSpeedForFlick();
+
+  // Flick logic X Axis
+
+  if(rulerX->IsEnabled() && lockAxis != LockAxis::LockHorizontal)
+  {
+    horizontal = FindDirection::All;
+
+    if(speed2 > flickSpeedThreshold2 || // exceeds flick threshold
+       inAccessibilityPan)              // With AccessibilityPan its easier to move between snap positions
+    {
+      if((angle >= -orthoAngleRange) && (angle < orthoAngleRange)) // Swiping East
+      {
+        biasX = 0.0f, horizontal = FindDirection::Left;
+
+        // This guards against an error where no movement occurs, due to the flick finishing
+        // before the update-thread has advanced mScrollPostPosition past the the previous snap point.
+        positionSnap.x += 1.0f;
+      }
+      else if((angle >= M_PI - orthoAngleRange) || (angle < -M_PI + orthoAngleRange)) // Swiping West
+      {
+        biasX = 1.0f, horizontal = FindDirection::Right;
+
+        // This guards against an error where no movement occurs, due to the flick finishing
+        // before the update-thread has advanced mScrollPostPosition past the the previous snap point.
+        positionSnap.x -= 1.0f;
+      }
+    }
+  }
+
+  // Flick logic Y Axis
+
+  if(rulerY->IsEnabled() && lockAxis != LockAxis::LockVertical)
+  {
+    vertical = FindDirection::All;
+
+    if(speed2 > flickSpeedThreshold2 || // exceeds flick threshold
+       inAccessibilityPan)              // With AccessibilityPan its easier to move between snap positions
+    {
+      if((angle >= M_PI_2 - orthoAngleRange) && (angle < M_PI_2 + orthoAngleRange)) // Swiping South
+      {
+        biasY = 0.0f, vertical = FindDirection::Up;
+      }
+      else if((angle >= -M_PI_2 - orthoAngleRange) && (angle < -M_PI_2 + orthoAngleRange)) // Swiping North
+      {
+        biasY = 1.0f, vertical = FindDirection::Down;
+      }
+    }
+  }
+
+  // isFlick: Whether this gesture is a flick or not.
+  isFlick = (horizontal != FindDirection::All || vertical != FindDirection::All);
+  // isFreeFlick: Whether this gesture is a flick under free panning criteria.
+  isFreeFlick = velocity.LengthSquared() > (FREE_FLICK_SPEED_THRESHOLD * FREE_FLICK_SPEED_THRESHOLD);
+
+  if(isFlick || isFreeFlick)
+  {
+    positionDuration = Vector2::ONE * scrollView.GetScrollFlickDuration();
+    alphaFunction    = scrollView.GetScrollFlickAlphaFunction();
+  }
+
+  // Calculate next positionSnap ////////////////////////////////////////////////////////////
+
+  if(scrollView.GetActorAutoSnap())
+  {
+    Vector3 size = scrollView.Self().GetCurrentProperty<Vector3>(Actor::Property::SIZE);
+
+    Actor child = scrollView.FindClosestActorToPosition(Vector3(size.width * 0.5f, size.height * 0.5f, 0.0f), horizontal, vertical);
+
+    if(!child && isFlick)
+    {
+      // If we conducted a direction limited search and found no actor, then just snap to the closest actor.
+      child = scrollView.FindClosestActorToPosition(Vector3(size.width * 0.5f, size.height * 0.5f, 0.0f));
+    }
+
+    if(child)
+    {
+      Vector2 position = scrollView.Self().GetCurrentProperty<Vector2>(Toolkit::ScrollView::Property::SCROLL_POSITION);
+
+      // Get center-point of the Actor.
+      Vector3 childPosition = GetPositionOfAnchor(child, AnchorPoint::CENTER);
+
+      if(rulerX->IsEnabled())
+      {
+        positionSnap.x = position.x - childPosition.x + size.width * 0.5f;
+      }
+      if(rulerY->IsEnabled())
+      {
+        positionSnap.y = position.y - childPosition.y + size.height * 0.5f;
+      }
+    }
+  }
+
+  Vector2 startPosition = positionSnap;
+  positionSnap.x        = -rulerX->Snap(-positionSnap.x, biasX); // NOTE: X & Y rulers think in -ve coordinate system.
+  positionSnap.y        = -rulerY->Snap(-positionSnap.y, biasY); // That is scrolling RIGHT (e.g. 100.0, 0.0) means moving LEFT.
+
+  Dali::Toolkit::ClampState2D clamped;
+  Vector3                     size = scrollView.Self().GetCurrentProperty<Vector3>(Actor::Property::SIZE);
+  Vector2                     clampDelta(Vector2::ZERO);
+  ClampPosition(size, rulerX, rulerY, positionSnap, clamped);
+
+  if((rulerX->GetType() == Dali::Toolkit::Ruler::FREE || rulerY->GetType() == Dali::Toolkit::Ruler::FREE) &&
+     isFreeFlick && !scrollView.GetActorAutoSnap())
+  {
+    // Calculate target position based on velocity of flick.
+
+    // a = Deceleration (Set to diagonal stage length * friction coefficient)
+    // u = Initial Velocity (Flick velocity)
+    // v = 0 (Final Velocity)
+    // t = Time (Velocity / Deceleration)
+    Vector2 stageSize   = Stage::GetCurrent().GetSize();
+    float   stageLength = Vector3(stageSize.x, stageSize.y, 0.0f).Length();
+    float   a           = (stageLength * scrollView.GetFrictionCoefficient());
+    Vector3 u           = Vector3(velocity.x, velocity.y, 0.0f) * scrollView.GetFlickSpeedCoefficient();
+    float   speed       = u.Length();
+    u /= speed;
+
+    // TODO: Change this to a decay function. (faster you flick, the slower it should be)
+    speed = std::min(speed, stageLength * scrollView.GetMaxFlickSpeed());
+    u *= speed;
+    alphaFunction = ConstantDecelerationAlphaFunction;
+
+    float t = speed / a;
+
+    if(rulerX->IsEnabled() && rulerX->GetType() == Dali::Toolkit::Ruler::FREE)
+    {
+      positionSnap.x += t * u.x * 0.5f;
+    }
+
+    if(rulerY->IsEnabled() && rulerY->GetType() == Dali::Toolkit::Ruler::FREE)
+    {
+      positionSnap.y += t * u.y * 0.5f;
+    }
+
+    clampDelta = positionSnap;
+    ClampPosition(size, rulerX, rulerY, positionSnap, clamped);
+
+    if((positionSnap - startPosition).LengthSquared() > Math::MACHINE_EPSILON_0)
+    {
+      clampDelta -= positionSnap;
+      clampDelta.x = clampDelta.x > 0.0f ? std::min(clampDelta.x, maxOvershoot.x) : std::max(clampDelta.x, -maxOvershoot.x);
+      clampDelta.y = clampDelta.y > 0.0f ? std::min(clampDelta.y, maxOvershoot.y) : std::max(clampDelta.y, -maxOvershoot.y);
+    }
+    else
+    {
+      clampDelta = Vector2::ZERO;
+    }
+
+    // If Axis is Free and has velocity, then calculate time taken
+    // to reach target based on velocity in axis.
+    if(rulerX->IsEnabled() && rulerX->GetType() == Dali::Toolkit::Ruler::FREE)
+    {
+      float deltaX = fabsf(startPosition.x - positionSnap.x);
+
+      if(fabsf(u.x) > Math::MACHINE_EPSILON_1)
+      {
+        positionDuration.x = fabsf(deltaX / u.x);
+      }
+      else
+      {
+        positionDuration.x = 0;
+      }
+    }
+
+    if(rulerY->IsEnabled() && rulerY->GetType() == Dali::Toolkit::Ruler::FREE)
+    {
+      float deltaY = fabsf(startPosition.y - positionSnap.y);
+
+      if(fabsf(u.y) > Math::MACHINE_EPSILON_1)
+      {
+        positionDuration.y = fabsf(deltaY / u.y);
+      }
+      else
+      {
+        positionDuration.y = 0;
+      }
+    }
+  }
 
-  scrollMax = max - size.GetVectorXY();
+  if(scrollView.IsOvershootEnabled())
+  {
+    // Scroll to the end of the overshoot only when overshoot is enabled.
+    positionSnap += clampDelta;
+  }
 }
 
 } // unnamed namespace
@@ -277,336 +579,6 @@ DALI_SIGNAL_REGISTRATION(Toolkit, ScrollView, "valueChanged", SIGNAL_SNAP_STARTE
 
 DALI_TYPE_REGISTRATION_END()
 
-/**
- * Returns whether to lock scrolling to a particular axis
- *
- * @param[in] panDelta Distance panned since gesture started
- * @param[in] currentLockAxis The current lock axis value
- * @param[in] lockGradient How quickly to lock to a particular axis
- *
- * @return The new axis lock state
- */
-ScrollView::LockAxis GetLockAxis(const Vector2& panDelta, ScrollView::LockAxis currentLockAxis, float lockGradient)
-{
-  if(panDelta.LengthSquared() > AUTOLOCK_AXIS_MINIMUM_DISTANCE2 &&
-     currentLockAxis == ScrollView::LockPossible)
-  {
-    float dx = fabsf(panDelta.x);
-    float dy = fabsf(panDelta.y);
-    if(dx * lockGradient >= dy)
-    {
-      // 0.36:1 gradient to the horizontal (deviate < 20 degrees)
-      currentLockAxis = ScrollView::LockVertical;
-    }
-    else if(dy * lockGradient > dx)
-    {
-      // 0.36:1 gradient to the vertical (deviate < 20 degrees)
-      currentLockAxis = ScrollView::LockHorizontal;
-    }
-    else
-    {
-      currentLockAxis = ScrollView::LockNone;
-    }
-  }
-  return currentLockAxis;
-}
-
-/**
- * Internal Pre-Position Property Constraint.
- *
- * Generates position property based on current position + gesture displacement.
- * Or generates position property based on positionX/Y.
- * Note: This is the position prior to any clamping at scroll boundaries.
- */
-struct InternalPrePositionConstraint
-{
-  InternalPrePositionConstraint(const Vector2&       initialPanPosition,
-                                const Vector2&       initialPanMask,
-                                bool                 axisAutoLock,
-                                float                axisAutoLockGradient,
-                                ScrollView::LockAxis initialLockAxis,
-                                const Vector2&       maxOvershoot,
-                                const RulerPtr&      rulerX,
-                                const RulerPtr&      rulerY)
-  : mLocalStart(initialPanPosition),
-    mInitialPanMask(initialPanMask),
-    mMaxOvershoot(maxOvershoot),
-    mAxisAutoLockGradient(axisAutoLockGradient),
-    mLockAxis(initialLockAxis),
-    mAxisAutoLock(axisAutoLock),
-    mWasPanning(false)
-  {
-    const RulerDomain& rulerDomainX = rulerX->GetDomain();
-    const RulerDomain& rulerDomainY = rulerY->GetDomain();
-    mDomainMin                      = Vector2(rulerDomainX.min, -rulerDomainY.min);
-    mDomainMax                      = Vector2(-rulerDomainX.max, -rulerDomainY.max);
-    mClampX                         = rulerDomainX.enabled;
-    mClampY                         = rulerDomainY.enabled;
-    mFixedRulerX                    = rulerX->GetType() == Ruler::FIXED;
-    mFixedRulerY                    = rulerY->GetType() == Ruler::FIXED;
-  }
-
-  void operator()(Vector2& scrollPostPosition, const PropertyInputContainer& inputs)
-  {
-    const Vector2& panPosition = inputs[0]->GetVector2();
-    const bool&    inGesture   = inputs[1]->GetBoolean();
-
-    // First check if we are within a gesture.
-    // The ScrollView may have received a start gesture from ::OnPan()
-    // while the finish gesture is received now in this constraint.
-    // This gesture must then be rejected as the value will be "old".
-    // Typically the last value from the end of the last gesture.
-    // If we are rejecting the gesture, we simply don't modify the constraint target.
-    if(inGesture)
-    {
-      if(!mWasPanning)
-      {
-        mPrePosition    = scrollPostPosition;
-        mStartPosition  = mPrePosition;
-        mCurrentPanMask = mInitialPanMask;
-        mWasPanning     = true;
-      }
-
-      // Calculate Deltas...
-      const Vector2& currentPosition = panPosition;
-      Vector2        panDelta(currentPosition - mLocalStart);
-
-      // Axis Auto Lock - locks the panning to the horizontal or vertical axis if the pan
-      // appears mostly horizontal or mostly vertical respectively...
-      if(mAxisAutoLock)
-      {
-        mLockAxis = GetLockAxis(panDelta, mLockAxis, mAxisAutoLockGradient);
-        if(mLockAxis == ScrollView::LockVertical)
-        {
-          mCurrentPanMask.y = 0.0f;
-        }
-        else if(mLockAxis == ScrollView::LockHorizontal)
-        {
-          mCurrentPanMask.x = 0.0f;
-        }
-      }
-
-      // Restrict deltas based on ruler enable/disable and axis-lock state...
-      panDelta *= mCurrentPanMask;
-
-      // Perform Position transform based on input deltas...
-      scrollPostPosition = mPrePosition;
-      scrollPostPosition += panDelta;
-
-      // if no wrapping then clamp preposition to maximum overshoot amount
-      const Vector3& size = inputs[2]->GetVector3();
-      if(mClampX)
-      {
-        float newXPosition = Clamp(scrollPostPosition.x, (mDomainMax.x + size.x) - mMaxOvershoot.x, mDomainMin.x + mMaxOvershoot.x);
-        if((newXPosition < scrollPostPosition.x - Math::MACHINE_EPSILON_1) || (newXPosition > scrollPostPosition.x + Math::MACHINE_EPSILON_1))
-        {
-          mPrePosition.x = newXPosition;
-          mLocalStart.x  = panPosition.x;
-        }
-        scrollPostPosition.x = newXPosition;
-      }
-      if(mClampY)
-      {
-        float newYPosition = Clamp(scrollPostPosition.y, (mDomainMax.y + size.y) - mMaxOvershoot.y, mDomainMin.y + mMaxOvershoot.y);
-        if((newYPosition < scrollPostPosition.y - Math::MACHINE_EPSILON_1) || (newYPosition > scrollPostPosition.y + Math::MACHINE_EPSILON_1))
-        {
-          mPrePosition.y = newYPosition;
-          mLocalStart.y  = panPosition.y;
-        }
-        scrollPostPosition.y = newYPosition;
-      }
-
-      // If we are using a fixed ruler in a particular axis, limit the maximum pages scrolled on that axis.
-      if(mFixedRulerX || mFixedRulerY)
-      {
-        // Here we limit the maximum amount that can be moved from the starting position of the gesture to one page.
-        // We do this only if we have a fixed ruler (on that axis) and the mode is enabled.
-        // Note: 1.0f is subtracted to keep the value within one page size (otherwise we stray on to the page after).
-        // Note: A further 1.0f is subtracted to handle a compensation that happens later within the flick handling code in SnapWithVelocity().
-        //       When a flick is completed, an adjustment of 1.0f is sometimes made to allow for the scenario where:
-        //       A flick finishes before the update thread has advanced the scroll position past the previous snap point.
-        Vector2 viewPageSizeLimit(size.x - (1.0f + 1.0f), size.y - (1.0f - 1.0f));
-        Vector2 minPosition(mStartPosition.x - viewPageSizeLimit.x, mStartPosition.y - viewPageSizeLimit.y);
-        Vector2 maxPosition(mStartPosition.x + viewPageSizeLimit.x, mStartPosition.y + viewPageSizeLimit.y);
-
-        if(mFixedRulerX)
-        {
-          scrollPostPosition.x = Clamp(scrollPostPosition.x, minPosition.x, maxPosition.x);
-        }
-        if(mFixedRulerY)
-        {
-          scrollPostPosition.y = Clamp(scrollPostPosition.y, minPosition.y, maxPosition.y);
-        }
-      }
-    }
-  }
-
-  Vector2 mPrePosition;
-  Vector2 mLocalStart;
-  Vector2 mStartPosition;  ///< The start position of the gesture - used to limit scroll amount (not modified by clamping).
-  Vector2 mInitialPanMask; ///< Initial pan mask (based on ruler settings).
-  Vector2 mCurrentPanMask; ///< Current pan mask that can be altered by axis lock mode.
-  Vector2 mDomainMin;
-  Vector2 mDomainMax;
-  Vector2 mMaxOvershoot;
-
-  float                mAxisAutoLockGradient; ///< Set by ScrollView
-  ScrollView::LockAxis mLockAxis;
-
-  bool mAxisAutoLock : 1; ///< Set by ScrollView
-  bool mWasPanning : 1;
-  bool mClampX : 1;
-  bool mClampY : 1;
-  bool mFixedRulerX : 1;
-  bool mFixedRulerY : 1;
-};
-
-/**
- * Internal Position Property Constraint.
- *
- * Generates position property based on pre-position
- * Note: This is the position after clamping.
- * (uses result of InternalPrePositionConstraint)
- */
-struct InternalPositionConstraint
-{
-  InternalPositionConstraint(const RulerDomain& domainX, const RulerDomain& domainY, bool wrap)
-  : mDomainMin(-domainX.min, -domainY.min),
-    mDomainMax(-domainX.max, -domainY.max),
-    mClampX(domainX.enabled),
-    mClampY(domainY.enabled),
-    mWrap(wrap)
-  {
-  }
-
-  void operator()(Vector2& position, const PropertyInputContainer& inputs)
-  {
-    position            = inputs[0]->GetVector2();
-    const Vector2& size = inputs[3]->GetVector3().GetVectorXY();
-    const Vector2& min  = inputs[1]->GetVector2();
-    const Vector2& max  = inputs[2]->GetVector2();
-
-    if(mWrap)
-    {
-      position.x = -WrapInDomain(-position.x, min.x, max.x);
-      position.y = -WrapInDomain(-position.y, min.y, max.y);
-    }
-    else
-    {
-      // clamp post position to domain
-      position.x = mClampX ? Clamp(position.x, mDomainMax.x + size.x, mDomainMin.x) : position.x;
-      position.y = mClampY ? Clamp(position.y, mDomainMax.y + size.y, mDomainMin.y) : position.y;
-    }
-  }
-
-  Vector2 mDomainMin;
-  Vector2 mDomainMax;
-  bool    mClampX;
-  bool    mClampY;
-  bool    mWrap;
-};
-
-/**
- * This constraint updates the X overshoot property using the difference
- * SCROLL_PRE_POSITION.x and SCROLL_POSITION.x, returning a relative value between 0.0f and 1.0f
- */
-struct OvershootXConstraint
-{
-  OvershootXConstraint(float maxOvershoot)
-  : mMaxOvershoot(maxOvershoot)
-  {
-  }
-
-  void operator()(float& current, const PropertyInputContainer& inputs)
-  {
-    if(inputs[2]->GetBoolean())
-    {
-      const Vector2& scrollPrePosition  = inputs[0]->GetVector2();
-      const Vector2& scrollPostPosition = inputs[1]->GetVector2();
-      float          newOvershoot       = scrollPrePosition.x - scrollPostPosition.x;
-      current                           = (newOvershoot > 0.0f ? std::min(newOvershoot, mMaxOvershoot) : std::max(newOvershoot, -mMaxOvershoot)) / mMaxOvershoot;
-    }
-    else
-    {
-      current = 0.0f;
-    }
-  }
-
-  float mMaxOvershoot;
-};
-
-/**
- * This constraint updates the Y overshoot property using the difference
- * SCROLL_PRE_POSITION.y and SCROLL_POSITION.y, returning a relative value between 0.0f and 1.0f
- */
-struct OvershootYConstraint
-{
-  OvershootYConstraint(float maxOvershoot)
-  : mMaxOvershoot(maxOvershoot)
-  {
-  }
-
-  void operator()(float& current, const PropertyInputContainer& inputs)
-  {
-    if(inputs[2]->GetBoolean())
-    {
-      const Vector2& scrollPrePosition  = inputs[0]->GetVector2();
-      const Vector2& scrollPostPosition = inputs[1]->GetVector2();
-      float          newOvershoot       = scrollPrePosition.y - scrollPostPosition.y;
-      current                           = (newOvershoot > 0.0f ? std::min(newOvershoot, mMaxOvershoot) : std::max(newOvershoot, -mMaxOvershoot)) / mMaxOvershoot;
-    }
-    else
-    {
-      current = 0.0f;
-    }
-  }
-
-  float mMaxOvershoot;
-};
-
-/**
- * Internal Position-Delta Property Constraint.
- *
- * Generates position-delta property based on scroll-position + scroll-offset properties.
- */
-void InternalPositionDeltaConstraint(Vector2& current, const PropertyInputContainer& inputs)
-{
-  const Vector2& scrollPosition = inputs[0]->GetVector2();
-  const Vector2& scrollOffset   = inputs[1]->GetVector2();
-
-  current = scrollPosition + scrollOffset;
-}
-
-/**
- * Internal Final Position Constraint
- * The position of content is:
- * of scroll-position + f(scroll-overshoot)
- * where f(...) function defines how overshoot
- * should affect final-position.
- */
-struct InternalFinalConstraint
-{
-  InternalFinalConstraint(AlphaFunctionPrototype functionX,
-                          AlphaFunctionPrototype functionY)
-  : mFunctionX(functionX),
-    mFunctionY(functionY)
-  {
-  }
-
-  void operator()(Vector2& current, const PropertyInputContainer& inputs)
-  {
-    const float& overshootx = inputs[1]->GetFloat();
-    const float& overshooty = inputs[2]->GetFloat();
-    Vector2      offset(mFunctionX(overshootx),
-                   mFunctionY(overshooty));
-
-    current = inputs[0]->GetVector2() - offset;
-  }
-
-  AlphaFunctionPrototype mFunctionX;
-  AlphaFunctionPrototype mFunctionY;
-};
-
 } // namespace
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -702,7 +674,7 @@ void ScrollView::OnInitialize()
   self.SetProperty(Toolkit::Scrollable::Property::CAN_SCROLL_HORIZONTAL, mCanScrollHorizontal);
 
   UpdatePropertyDomain();
-  SetInternalConstraints();
+  mConstraints.SetInternalConstraints(*this);
 
   // Connect wheel event
   self.WheelEventSignal().Connect(this, &ScrollView::OnWheelEvent);
@@ -746,46 +718,6 @@ ScrollView::~ScrollView()
   DALI_LOG_SCROLL_STATE("[0x%X]", this);
 }
 
-AlphaFunction ScrollView::GetScrollSnapAlphaFunction() const
-{
-  return mSnapAlphaFunction;
-}
-
-void ScrollView::SetScrollSnapAlphaFunction(AlphaFunction alpha)
-{
-  mSnapAlphaFunction = alpha;
-}
-
-AlphaFunction ScrollView::GetScrollFlickAlphaFunction() const
-{
-  return mFlickAlphaFunction;
-}
-
-void ScrollView::SetScrollFlickAlphaFunction(AlphaFunction alpha)
-{
-  mFlickAlphaFunction = alpha;
-}
-
-float ScrollView::GetScrollSnapDuration() const
-{
-  return mSnapDuration;
-}
-
-void ScrollView::SetScrollSnapDuration(float time)
-{
-  mSnapDuration = time;
-}
-
-float ScrollView::GetScrollFlickDuration() const
-{
-  return mFlickDuration;
-}
-
-void ScrollView::SetScrollFlickDuration(float time)
-{
-  mFlickDuration = time;
-}
-
 void ScrollView::ApplyEffect(Toolkit::ScrollViewEffect effect)
 {
   Dali::Toolkit::ScrollView self = Dali::Toolkit::ScrollView::DownCast(Self());
@@ -858,22 +790,12 @@ void ScrollView::RemoveConstraintsFromChildren()
   RemoveConstraintsFromBoundActors();
 }
 
-const RulerPtr ScrollView::GetRulerX() const
-{
-  return mRulerX;
-}
-
-const RulerPtr ScrollView::GetRulerY() const
-{
-  return mRulerY;
-}
-
 void ScrollView::SetRulerX(RulerPtr ruler)
 {
   mRulerX = ruler;
 
   UpdatePropertyDomain();
-  UpdateMainInternalConstraint();
+  mConstraints.UpdateMainInternalConstraint(*this);
 }
 
 void ScrollView::SetRulerY(RulerPtr ruler)
@@ -881,7 +803,7 @@ void ScrollView::SetRulerY(RulerPtr ruler)
   mRulerY = ruler;
 
   UpdatePropertyDomain();
-  UpdateMainInternalConstraint();
+  mConstraints.UpdateMainInternalConstraint(*this);
 }
 
 void ScrollView::UpdatePropertyDomain()
@@ -981,11 +903,6 @@ void ScrollView::UpdatePropertyDomain()
   }
 }
 
-bool ScrollView::GetScrollSensitive()
-{
-  return mSensitive;
-}
-
 void ScrollView::SetScrollSensitive(bool sensitive)
 {
   Actor              self = Self();
@@ -1023,22 +940,7 @@ void ScrollView::SetMaxOvershoot(float overshootX, float overshootY)
   mMaxOvershoot.y      = overshootY;
   mUserMaxOvershoot    = mMaxOvershoot;
   mDefaultMaxOvershoot = false;
-  UpdateMainInternalConstraint();
-}
-
-void ScrollView::SetSnapOvershootAlphaFunction(AlphaFunction alpha)
-{
-  mSnapOvershootAlphaFunction = alpha;
-}
-
-float ScrollView::GetSnapOvershootDuration()
-{
-  return mSnapOvershootDuration;
-}
-
-void ScrollView::SetSnapOvershootDuration(float duration)
-{
-  mSnapOvershootDuration = duration;
+  mConstraints.UpdateMainInternalConstraint(*this);
 }
 
 bool ScrollView::GetActorAutoSnap()
@@ -1046,64 +948,29 @@ bool ScrollView::GetActorAutoSnap()
   return mActorAutoSnapEnabled;
 }
 
-void ScrollView::SetActorAutoSnap(bool enable)
-{
-  mActorAutoSnapEnabled = enable;
-}
-
 void ScrollView::SetAutoResize(bool enable)
 {
   mAutoResizeContainerEnabled = enable;
   // TODO: This needs a lot of issues to be addressed before working.
 }
 
-bool ScrollView::GetWrapMode() const
-{
-  return mWrapMode;
-}
-
 void ScrollView::SetWrapMode(bool enable)
 {
   mWrapMode = enable;
   Self().SetProperty(Toolkit::ScrollView::Property::WRAP, enable);
 }
 
-int ScrollView::GetScrollUpdateDistance() const
-{
-  return mScrollUpdateDistance;
-}
-
-void ScrollView::SetScrollUpdateDistance(int distance)
-{
-  mScrollUpdateDistance = distance;
-}
-
-bool ScrollView::GetAxisAutoLock() const
-{
-  return mAxisAutoLock;
-}
-
 void ScrollView::SetAxisAutoLock(bool enable)
 {
   mAxisAutoLock = enable;
-  UpdateMainInternalConstraint();
-}
-
-float ScrollView::GetAxisAutoLockGradient() const
-{
-  return mAxisAutoLockGradient;
+  mConstraints.UpdateMainInternalConstraint(*this);
 }
 
 void ScrollView::SetAxisAutoLockGradient(float gradient)
 {
   DALI_ASSERT_DEBUG(gradient >= 0.0f && gradient <= 1.0f);
   mAxisAutoLockGradient = gradient;
-  UpdateMainInternalConstraint();
-}
-
-float ScrollView::GetFrictionCoefficient() const
-{
-  return mFrictionCoefficient;
+  mConstraints.UpdateMainInternalConstraint(*this);
 }
 
 void ScrollView::SetFrictionCoefficient(float friction)
@@ -1112,56 +979,6 @@ void ScrollView::SetFrictionCoefficient(float friction)
   mFrictionCoefficient = friction;
 }
 
-float ScrollView::GetFlickSpeedCoefficient() const
-{
-  return mFlickSpeedCoefficient;
-}
-
-void ScrollView::SetFlickSpeedCoefficient(float speed)
-{
-  mFlickSpeedCoefficient = speed;
-}
-
-Vector2 ScrollView::GetMinimumDistanceForFlick() const
-{
-  return mMinFlickDistance;
-}
-
-void ScrollView::SetMinimumDistanceForFlick(const Vector2& distance)
-{
-  mMinFlickDistance = distance;
-}
-
-float ScrollView::GetMinimumSpeedForFlick() const
-{
-  return mFlickSpeedThreshold;
-}
-
-void ScrollView::SetMinimumSpeedForFlick(float speed)
-{
-  mFlickSpeedThreshold = speed;
-}
-
-float ScrollView::GetMaxFlickSpeed() const
-{
-  return mMaxFlickSpeed;
-}
-
-void ScrollView::SetMaxFlickSpeed(float speed)
-{
-  mMaxFlickSpeed = speed;
-}
-
-void ScrollView::SetWheelScrollDistanceStep(Vector2 step)
-{
-  mWheelScrollDistanceStep = step;
-}
-
-Vector2 ScrollView::GetWheelScrollDistanceStep() const
-{
-  return mWheelScrollDistanceStep;
-}
-
 unsigned int ScrollView::GetCurrentPage() const
 {
   // in case animation is currently taking place.
@@ -1229,9 +1046,9 @@ void ScrollView::TransformTo(const Vector2& position, float duration, AlphaFunct
     mGestureStackDepth = 0;
     self.SetProperty(Toolkit::ScrollView::Property::PANNING, false);
 
-    if(mScrollMainInternalPrePositionConstraint)
+    if(mConstraints.mScrollMainInternalPrePositionConstraint)
     {
-      mScrollMainInternalPrePositionConstraint.Remove();
+      mConstraints.mScrollMainInternalPrePositionConstraint.Remove();
     }
   }
 
@@ -1244,408 +1061,126 @@ void ScrollView::TransformTo(const Vector2& position, float duration, AlphaFunct
                              Vector2::ONE * duration,
                              alpha,
                              true,
-                             horizontalBias,
-                             verticalBias,
-                             SNAP);
-
-  if(!animating)
-  {
-    // if not animating, then this pan has completed right now.
-    self.SetProperty(Toolkit::ScrollView::Property::SCROLLING, false);
-    mScrolling = false;
-
-    // If we have no duration, then in the next update frame, we will be at the position specified as we just set.
-    // In this scenario, we cannot return the currentScrollPosition as this is out-of-date and should instead return the requested final position
-    Vector2 completedPosition(currentScrollPosition);
-    if(duration <= Math::MACHINE_EPSILON_10)
-    {
-      completedPosition = position;
-    }
-
-    DALI_LOG_SCROLL_STATE("[0x%X] mScrollCompletedSignal 2 [%.2f, %.2f]", this, completedPosition.x, completedPosition.y);
-    SetScrollUpdateNotification(false);
-    mScrollCompletedSignal.Emit(completedPosition);
-  }
-}
-
-void ScrollView::ScrollTo(const Vector2& position)
-{
-  ScrollTo(position, mSnapDuration);
-}
-
-void ScrollView::ScrollTo(const Vector2& position, float duration)
-{
-  ScrollTo(position, duration, DIRECTION_BIAS_NONE, DIRECTION_BIAS_NONE);
-}
-
-void ScrollView::ScrollTo(const Vector2& position, float duration, AlphaFunction alpha)
-{
-  ScrollTo(position, duration, alpha, DIRECTION_BIAS_NONE, DIRECTION_BIAS_NONE);
-}
-
-void ScrollView::ScrollTo(const Vector2& position, float duration, DirectionBias horizontalBias, DirectionBias verticalBias)
-{
-  ScrollTo(position, duration, mSnapAlphaFunction, horizontalBias, verticalBias);
-}
-
-void ScrollView::ScrollTo(const Vector2& position, float duration, AlphaFunction alpha, DirectionBias horizontalBias, DirectionBias verticalBias)
-{
-  DALI_LOG_SCROLL_STATE("[0x%X] position[%.2f, %.2f] duration[%.2f], bias[%d, %d]", this, position.x, position.y, duration, int(horizontalBias), int(verticalBias));
-  TransformTo(position, duration, alpha, horizontalBias, verticalBias);
-}
-
-void ScrollView::ScrollTo(unsigned int page)
-{
-  ScrollTo(page, mSnapDuration);
-}
-
-void ScrollView::ScrollTo(unsigned int page, float duration, DirectionBias bias)
-{
-  Vector2      position;
-  unsigned int volume;
-  unsigned int libraries;
-
-  // The position to scroll to is continuous and linear
-  // unless a domain has been enabled on the X axis.
-  // or if WrapMode has been enabled.
-  bool carryX = mRulerX->GetDomain().enabled | mWrapMode;
-  bool carryY = mRulerY->GetDomain().enabled | mWrapMode;
-
-  position.x = mRulerX->GetPositionFromPage(page, volume, carryX);
-  position.y = mRulerY->GetPositionFromPage(volume, libraries, carryY);
-
-  ScrollTo(position, duration, bias, bias);
-}
-
-void ScrollView::ScrollTo(Actor& actor)
-{
-  ScrollTo(actor, mSnapDuration);
-}
-
-void ScrollView::ScrollTo(Actor& actor, float duration)
-{
-  DALI_ASSERT_ALWAYS(actor.GetParent() == Self());
-
-  Actor   self        = Self();
-  Vector3 size        = self.GetCurrentProperty<Vector3>(Actor::Property::SIZE);
-  Vector3 position    = actor.GetCurrentProperty<Vector3>(Actor::Property::POSITION);
-  Vector2 prePosition = GetPropertyPrePosition();
-  position.GetVectorXY() -= prePosition;
-
-  ScrollTo(Vector2(position.x - size.width * 0.5f, position.y - size.height * 0.5f), duration);
-}
-
-Actor ScrollView::FindClosestActor()
-{
-  Actor   self = Self();
-  Vector3 size = self.GetCurrentProperty<Vector3>(Actor::Property::SIZE);
-
-  return FindClosestActorToPosition(Vector3(size.width * 0.5f, size.height * 0.5f, 0.0f));
-}
-
-Actor ScrollView::FindClosestActorToPosition(const Vector3& position, FindDirection dirX, FindDirection dirY, FindDirection dirZ)
-{
-  Actor   closestChild;
-  float   closestDistance2 = 0.0f;
-  Vector3 actualPosition   = position;
-
-  unsigned int numChildren = Self().GetChildCount();
-
-  for(unsigned int i = 0; i < numChildren; ++i)
-  {
-    Actor child = Self().GetChildAt(i);
-
-    if(mInternalActor == child) // ignore internal actor.
-    {
-      continue;
-    }
-
-    Vector3 childPosition = GetPositionOfAnchor(child, AnchorPoint::CENTER);
-
-    Vector3 delta = childPosition - actualPosition;
-
-    // X-axis checking (only find Actors to the [dirX] of actualPosition)
-    if(dirX > All) // != All,None
-    {
-      FindDirection deltaH = delta.x > 0 ? Right : Left;
-      if(dirX != deltaH)
-      {
-        continue;
-      }
-    }
-
-    // Y-axis checking (only find Actors to the [dirY] of actualPosition)
-    if(dirY > All) // != All,None
-    {
-      FindDirection deltaV = delta.y > 0 ? Down : Up;
-      if(dirY != deltaV)
-      {
-        continue;
-      }
-    }
-
-    // Z-axis checking (only find Actors to the [dirZ] of actualPosition)
-    if(dirZ > All) // != All,None
-    {
-      FindDirection deltaV = delta.y > 0 ? In : Out;
-      if(dirZ != deltaV)
-      {
-        continue;
-      }
-    }
-
-    // compare child to closest child in terms of distance.
-    float distance2 = 0.0f;
-
-    // distance2 = the Square of the relevant dimensions of delta
-    if(dirX != None)
-    {
-      distance2 += delta.x * delta.x;
-    }
-
-    if(dirY != None)
-    {
-      distance2 += delta.y * delta.y;
-    }
-
-    if(dirZ != None)
-    {
-      distance2 += delta.z * delta.z;
-    }
-
-    if(closestChild) // Next time.
-    {
-      if(distance2 < closestDistance2)
-      {
-        closestChild     = child;
-        closestDistance2 = distance2;
-      }
-    }
-    else // First time.
-    {
-      closestChild     = child;
-      closestDistance2 = distance2;
-    }
-  }
-
-  return closestChild;
-}
-
-bool ScrollView::ScrollToSnapPoint()
-{
-  DALI_LOG_SCROLL_STATE("[0x%X]", this);
-  Vector2 stationaryVelocity = Vector2(0.0f, 0.0f);
-  return SnapWithVelocity(stationaryVelocity);
-}
-
-// TODO: In situations where axes are different (X snap, Y free)
-// Each axis should really have their own independent animation (time and equation)
-// Consider, X axis snapping to nearest grid point (EaseOut over fixed time)
-// Consider, Y axis simulating physics to arrive at a point (Physics equation over variable time)
-// Currently, the axes have been split however, they both use the same EaseOut equation.
-bool ScrollView::SnapWithVelocity(Vector2 velocity)
-{
-  // Animator takes over now, touches are assumed not to interfere.
-  // And if touches do interfere, then we'll stop animation, update PrePosition
-  // to current mScroll's properties, and then resume.
-  // Note: For Flicking this may work a bit different...
-
-  float         angle            = atan2(velocity.y, velocity.x);
-  float         speed2           = velocity.LengthSquared();
-  AlphaFunction alphaFunction    = mSnapAlphaFunction;
-  Vector2       positionDuration = Vector2::ONE * mSnapDuration;
-  float         biasX            = 0.5f;
-  float         biasY            = 0.5f;
-  FindDirection horizontal       = None;
-  FindDirection vertical         = None;
-
-  // orthoAngleRange = Angle tolerance within the Exact N,E,S,W direction
-  // that will be accepted as a general N,E,S,W flick direction.
-
-  const float orthoAngleRange      = FLICK_ORTHO_ANGLE_RANGE * M_PI / 180.0f;
-  const float flickSpeedThreshold2 = mFlickSpeedThreshold * mFlickSpeedThreshold;
-
-  Vector2 positionSnap = mScrollPrePosition;
-
-  // Flick logic X Axis
-
-  if(mRulerX->IsEnabled() && mLockAxis != LockHorizontal)
-  {
-    horizontal = All;
-
-    if(speed2 > flickSpeedThreshold2 || // exceeds flick threshold
-       mInAccessibilityPan)             // With AccessibilityPan its easier to move between snap positions
-    {
-      if((angle >= -orthoAngleRange) && (angle < orthoAngleRange)) // Swiping East
-      {
-        biasX = 0.0f, horizontal = Left;
-
-        // This guards against an error where no movement occurs, due to the flick finishing
-        // before the update-thread has advanced mScrollPostPosition past the the previous snap point.
-        positionSnap.x += 1.0f;
-      }
-      else if((angle >= M_PI - orthoAngleRange) || (angle < -M_PI + orthoAngleRange)) // Swiping West
-      {
-        biasX = 1.0f, horizontal = Right;
-
-        // This guards against an error where no movement occurs, due to the flick finishing
-        // before the update-thread has advanced mScrollPostPosition past the the previous snap point.
-        positionSnap.x -= 1.0f;
-      }
-    }
-  }
-
-  // Flick logic Y Axis
+                             horizontalBias,
+                             verticalBias,
+                             SNAP);
 
-  if(mRulerY->IsEnabled() && mLockAxis != LockVertical)
+  if(!animating)
   {
-    vertical = All;
+    // if not animating, then this pan has completed right now.
+    self.SetProperty(Toolkit::ScrollView::Property::SCROLLING, false);
+    mScrolling = false;
 
-    if(speed2 > flickSpeedThreshold2 || // exceeds flick threshold
-       mInAccessibilityPan)             // With AccessibilityPan its easier to move between snap positions
+    // If we have no duration, then in the next update frame, we will be at the position specified as we just set.
+    // In this scenario, we cannot return the currentScrollPosition as this is out-of-date and should instead return the requested final position
+    Vector2 completedPosition(currentScrollPosition);
+    if(duration <= Math::MACHINE_EPSILON_10)
     {
-      if((angle >= M_PI_2 - orthoAngleRange) && (angle < M_PI_2 + orthoAngleRange)) // Swiping South
-      {
-        biasY = 0.0f, vertical = Up;
-      }
-      else if((angle >= -M_PI_2 - orthoAngleRange) && (angle < -M_PI_2 + orthoAngleRange)) // Swiping North
-      {
-        biasY = 1.0f, vertical = Down;
-      }
+      completedPosition = position;
     }
-  }
 
-  // isFlick: Whether this gesture is a flick or not.
-  bool isFlick = (horizontal != All || vertical != All);
-  // isFreeFlick: Whether this gesture is a flick under free panning criteria.
-  bool isFreeFlick = velocity.LengthSquared() > (FREE_FLICK_SPEED_THRESHOLD * FREE_FLICK_SPEED_THRESHOLD);
-
-  if(isFlick || isFreeFlick)
-  {
-    positionDuration = Vector2::ONE * mFlickDuration;
-    alphaFunction    = mFlickAlphaFunction;
+    DALI_LOG_SCROLL_STATE("[0x%X] mScrollCompletedSignal 2 [%.2f, %.2f]", this, completedPosition.x, completedPosition.y);
+    SetScrollUpdateNotification(false);
+    mScrollCompletedSignal.Emit(completedPosition);
   }
+}
 
-  // Calculate next positionSnap ////////////////////////////////////////////////////////////
-
-  if(mActorAutoSnapEnabled)
-  {
-    Vector3 size = Self().GetCurrentProperty<Vector3>(Actor::Property::SIZE);
+void ScrollView::ScrollTo(const Vector2& position)
+{
+  ScrollTo(position, mSnapDuration);
+}
 
-    Actor child = FindClosestActorToPosition(Vector3(size.width * 0.5f, size.height * 0.5f, 0.0f), horizontal, vertical);
+void ScrollView::ScrollTo(const Vector2& position, float duration)
+{
+  ScrollTo(position, duration, DIRECTION_BIAS_NONE, DIRECTION_BIAS_NONE);
+}
 
-    if(!child && isFlick)
-    {
-      // If we conducted a direction limited search and found no actor, then just snap to the closest actor.
-      child = FindClosestActorToPosition(Vector3(size.width * 0.5f, size.height * 0.5f, 0.0f));
-    }
+void ScrollView::ScrollTo(const Vector2& position, float duration, AlphaFunction alpha)
+{
+  ScrollTo(position, duration, alpha, DIRECTION_BIAS_NONE, DIRECTION_BIAS_NONE);
+}
 
-    if(child)
-    {
-      Vector2 position = Self().GetCurrentProperty<Vector2>(Toolkit::ScrollView::Property::SCROLL_POSITION);
+void ScrollView::ScrollTo(const Vector2& position, float duration, DirectionBias horizontalBias, DirectionBias verticalBias)
+{
+  ScrollTo(position, duration, mSnapAlphaFunction, horizontalBias, verticalBias);
+}
 
-      // Get center-point of the Actor.
-      Vector3 childPosition = GetPositionOfAnchor(child, AnchorPoint::CENTER);
+void ScrollView::ScrollTo(const Vector2& position, float duration, AlphaFunction alpha, DirectionBias horizontalBias, DirectionBias verticalBias)
+{
+  DALI_LOG_SCROLL_STATE("[0x%X] position[%.2f, %.2f] duration[%.2f], bias[%d, %d]", this, position.x, position.y, duration, int(horizontalBias), int(verticalBias));
+  TransformTo(position, duration, alpha, horizontalBias, verticalBias);
+}
 
-      if(mRulerX->IsEnabled())
-      {
-        positionSnap.x = position.x - childPosition.x + size.width * 0.5f;
-      }
-      if(mRulerY->IsEnabled())
-      {
-        positionSnap.y = position.y - childPosition.y + size.height * 0.5f;
-      }
-    }
-  }
+void ScrollView::ScrollTo(unsigned int page)
+{
+  ScrollTo(page, mSnapDuration);
+}
 
-  Vector2 startPosition = positionSnap;
-  positionSnap.x        = -mRulerX->Snap(-positionSnap.x, biasX); // NOTE: X & Y rulers think in -ve coordinate system.
-  positionSnap.y        = -mRulerY->Snap(-positionSnap.y, biasY); // That is scrolling RIGHT (e.g. 100.0, 0.0) means moving LEFT.
+void ScrollView::ScrollTo(unsigned int page, float duration, DirectionBias bias)
+{
+  Vector2      position;
+  unsigned int volume;
+  unsigned int libraries;
 
-  Vector2 clampDelta(Vector2::ZERO);
-  ClampPosition(positionSnap);
+  // The position to scroll to is continuous and linear
+  // unless a domain has been enabled on the X axis.
+  // or if WrapMode has been enabled.
+  bool carryX = mRulerX->GetDomain().enabled | mWrapMode;
+  bool carryY = mRulerY->GetDomain().enabled | mWrapMode;
 
-  if((mRulerX->GetType() == Ruler::FREE || mRulerY->GetType() == Ruler::FREE) && isFreeFlick && !mActorAutoSnapEnabled)
-  {
-    // Calculate target position based on velocity of flick.
+  position.x = mRulerX->GetPositionFromPage(page, volume, carryX);
+  position.y = mRulerY->GetPositionFromPage(volume, libraries, carryY);
 
-    // a = Deceleration (Set to diagonal stage length * friction coefficient)
-    // u = Initial Velocity (Flick velocity)
-    // v = 0 (Final Velocity)
-    // t = Time (Velocity / Deceleration)
-    Vector2 stageSize   = Stage::GetCurrent().GetSize();
-    float   stageLength = Vector3(stageSize.x, stageSize.y, 0.0f).Length();
-    float   a           = (stageLength * mFrictionCoefficient);
-    Vector3 u           = Vector3(velocity.x, velocity.y, 0.0f) * mFlickSpeedCoefficient;
-    float   speed       = u.Length();
-    u /= speed;
+  ScrollTo(position, duration, bias, bias);
+}
 
-    // TODO: Change this to a decay function. (faster you flick, the slower it should be)
-    speed = std::min(speed, stageLength * mMaxFlickSpeed);
-    u *= speed;
-    alphaFunction = ConstantDecelerationAlphaFunction;
+void ScrollView::ScrollTo(Actor& actor)
+{
+  ScrollTo(actor, mSnapDuration);
+}
 
-    float t = speed / a;
+void ScrollView::ScrollTo(Actor& actor, float duration)
+{
+  DALI_ASSERT_ALWAYS(actor.GetParent() == Self());
 
-    if(mRulerX->IsEnabled() && mRulerX->GetType() == Ruler::FREE)
-    {
-      positionSnap.x += t * u.x * 0.5f;
-    }
+  Actor   self        = Self();
+  Vector3 size        = self.GetCurrentProperty<Vector3>(Actor::Property::SIZE);
+  Vector3 position    = actor.GetCurrentProperty<Vector3>(Actor::Property::POSITION);
+  Vector2 prePosition = GetPropertyPrePosition();
+  position.GetVectorXY() -= prePosition;
 
-    if(mRulerY->IsEnabled() && mRulerY->GetType() == Ruler::FREE)
-    {
-      positionSnap.y += t * u.y * 0.5f;
-    }
+  ScrollTo(Vector2(position.x - size.width * 0.5f, position.y - size.height * 0.5f), duration);
+}
 
-    clampDelta = positionSnap;
-    ClampPosition(positionSnap);
-    if((positionSnap - startPosition).LengthSquared() > Math::MACHINE_EPSILON_0)
-    {
-      clampDelta -= positionSnap;
-      clampDelta.x = clampDelta.x > 0.0f ? std::min(clampDelta.x, mMaxOvershoot.x) : std::max(clampDelta.x, -mMaxOvershoot.x);
-      clampDelta.y = clampDelta.y > 0.0f ? std::min(clampDelta.y, mMaxOvershoot.y) : std::max(clampDelta.y, -mMaxOvershoot.y);
-    }
-    else
-    {
-      clampDelta = Vector2::ZERO;
-    }
+Actor ScrollView::FindClosestActor()
+{
+  Actor   self = Self();
+  Vector3 size = self.GetCurrentProperty<Vector3>(Actor::Property::SIZE);
 
-    // If Axis is Free and has velocity, then calculate time taken
-    // to reach target based on velocity in axis.
-    if(mRulerX->IsEnabled() && mRulerX->GetType() == Ruler::FREE)
-    {
-      float deltaX = fabsf(startPosition.x - positionSnap.x);
+  return FindClosestActorToPosition(Vector3(size.width * 0.5f, size.height * 0.5f, 0.0f));
+}
 
-      if(fabsf(u.x) > Math::MACHINE_EPSILON_1)
-      {
-        positionDuration.x = fabsf(deltaX / u.x);
-      }
-      else
-      {
-        positionDuration.x = 0;
-      }
-    }
+Actor ScrollView::FindClosestActorToPosition(const Vector3& position, FindDirection dirX, FindDirection dirY, FindDirection dirZ)
+{
+  return ::FindClosestActorToPosition(Self(), mInternalActor, position, dirX, dirY, dirZ);
+}
 
-    if(mRulerY->IsEnabled() && mRulerY->GetType() == Ruler::FREE)
-    {
-      float deltaY = fabsf(startPosition.y - positionSnap.y);
+bool ScrollView::ScrollToSnapPoint()
+{
+  DALI_LOG_SCROLL_STATE("[0x%X]", this);
+  Vector2 stationaryVelocity = Vector2(0.0f, 0.0f);
+  return SnapWithVelocity(stationaryVelocity);
+}
 
-      if(fabsf(u.y) > Math::MACHINE_EPSILON_1)
-      {
-        positionDuration.y = fabsf(deltaY / u.y);
-      }
-      else
-      {
-        positionDuration.y = 0;
-      }
-    }
-  }
+bool ScrollView::SnapWithVelocity(Vector2 velocity)
+{
+  Vector2       positionSnap     = mScrollPrePosition;
+  Vector2       positionDuration = Vector2::ONE * mSnapDuration;
+  AlphaFunction alphaFunction    = mSnapAlphaFunction;
+  bool          isFlick;
+  bool          isFreeFlick;
 
-  if(IsOvershootEnabled())
-  {
-    // Scroll to the end of the overshoot only when overshoot is enabled.
-    positionSnap += clampDelta;
-  }
+  ::SnapWithVelocity(*this, mRulerX, mRulerY, mLockAxis, velocity, mMaxOvershoot, positionSnap, positionDuration, alphaFunction, mInAccessibilityPan, isFlick, isFreeFlick);
 
   bool animating = AnimateTo(positionSnap, positionDuration, alphaFunction, false, DIRECTION_BIAS_NONE, DIRECTION_BIAS_NONE, isFlick || isFreeFlick ? FLICK : SNAP);
 
@@ -1698,7 +1233,7 @@ bool ScrollView::AnimateTo(const Vector2& position, const Vector2& positionDurat
   // Position Delta ///////////////////////////////////////////////////////
   if(positionChanged)
   {
-    UpdateMainInternalConstraint();
+    mConstraints.UpdateMainInternalConstraint(*this);
     if(mWrapMode && findShortcuts)
     {
       // In Wrap Mode, the shortest distance is a little less intuitive...
@@ -1771,7 +1306,7 @@ void ScrollView::EnableScrollOvershoot(bool enable)
     }
   }
 
-  UpdateMainInternalConstraint();
+  mConstraints.UpdateMainInternalConstraint(*this);
 }
 
 void ScrollView::AddOverlay(Actor actor)
@@ -1826,7 +1361,7 @@ Toolkit::ScrollView::SnapStartedSignalType& ScrollView::SnapStartedSignal()
 bool ScrollView::AccessibleImpl::ScrollToChild(Actor child)
 {
   auto scrollView = Dali::Toolkit::ScrollView::DownCast(Self());
-  if (Toolkit::GetImpl(scrollView).FindClosestActor() == child)
+  if(Toolkit::GetImpl(scrollView).FindClosestActor() == child)
   {
     return false;
   }
@@ -1963,7 +1498,7 @@ void ScrollView::OnSizeSet(const Vector3& size)
     }
   }
   UpdatePropertyDomain();
-  UpdateMainInternalConstraint();
+  mConstraints.UpdateMainInternalConstraint(*this);
   if(IsOvershootEnabled())
   {
     mOvershootIndicator->Reset();
@@ -2503,7 +2038,7 @@ void ScrollView::OnPan(const PanGesture& gesture)
       self.SetProperty(Toolkit::ScrollView::Property::PANNING, true);
       self.SetProperty(Toolkit::ScrollView::Property::START_PAGE_POSITION, Vector3(position.x, position.y, 0.0f));
 
-      UpdateMainInternalConstraint();
+      mConstraints.UpdateMainInternalConstraint(*this);
       Toolkit::ScrollBar scrollBar = mScrollBar.GetHandle();
       if(scrollBar && mTransientScrollBar)
       {
@@ -2546,9 +2081,9 @@ void ScrollView::OnPan(const PanGesture& gesture)
         mPanning      = false;
         self.SetProperty(Toolkit::ScrollView::Property::PANNING, false);
 
-        if(mScrollMainInternalPrePositionConstraint)
+        if(mConstraints.mScrollMainInternalPrePositionConstraint)
         {
-          mScrollMainInternalPrePositionConstraint.Remove();
+          mConstraints.mScrollMainInternalPrePositionConstraint.Remove();
         }
 
         Toolkit::ScrollBar scrollBar = mScrollBar.GetHandle();
@@ -2704,8 +2239,7 @@ void ScrollView::ClampPosition(Vector2& position, ClampState2D& clamped) const
 {
   Vector3 size = Self().GetCurrentProperty<Vector3>(Actor::Property::SIZE);
 
-  position.x = -mRulerX->Clamp(-position.x, size.width, 1.0f, clamped.x);  // NOTE: X & Y rulers think in -ve coordinate system.
-  position.y = -mRulerY->Clamp(-position.y, size.height, 1.0f, clamped.y); // That is scrolling RIGHT (e.g. 100.0, 0.0) means moving LEFT.
+  ::ClampPosition(size, mRulerX, mRulerY, position, clamped);
 }
 
 void ScrollView::WrapPosition(Vector2& position) const
@@ -2727,168 +2261,6 @@ void ScrollView::WrapPosition(Vector2& position) const
   }
 }
 
-void ScrollView::UpdateMainInternalConstraint()
-{
-  // TODO: Only update the constraints which have changed, rather than remove all and add all again.
-  // Requires a dali-core ApplyConstraintAt, or a ReplaceConstraint. The former is probably more flexible.
-  Actor              self = Self();
-  PanGestureDetector detector(GetPanGestureDetector());
-
-  if(mScrollMainInternalPositionConstraint)
-  {
-    mScrollMainInternalPositionConstraint.Remove();
-    mScrollMainInternalDeltaConstraint.Remove();
-    mScrollMainInternalFinalConstraint.Remove();
-    mScrollMainInternalRelativeConstraint.Remove();
-    mScrollMainInternalDomainConstraint.Remove();
-    mScrollMainInternalPrePositionMaxConstraint.Remove();
-  }
-  if(mScrollMainInternalPrePositionConstraint)
-  {
-    mScrollMainInternalPrePositionConstraint.Remove();
-  }
-
-  // TODO: It's probably better to use a local displacement value as this will give a displacement when scrolling just commences
-  // but we need to make sure than the gesture system gives displacement since last frame (60Hz), not displacement since last touch event (90Hz).
-
-  // 1. First calculate the pre-position (this is the scroll position if no clamping has taken place)
-  Vector2 initialPanMask = Vector2(mRulerX->IsEnabled() ? 1.0f : 0.0f, mRulerY->IsEnabled() ? 1.0f : 0.0f);
-
-  if(mLockAxis == LockVertical)
-  {
-    initialPanMask.y = 0.0f;
-  }
-  else if(mLockAxis == LockHorizontal)
-  {
-    initialPanMask.x = 0.0f;
-  }
-
-  if(mPanning)
-  {
-    mScrollMainInternalPrePositionConstraint = Constraint::New<Vector2>(self,
-                                                                        Toolkit::ScrollView::Property::SCROLL_PRE_POSITION,
-                                                                        InternalPrePositionConstraint(mPanStartPosition,
-                                                                                                      initialPanMask,
-                                                                                                      mAxisAutoLock,
-                                                                                                      mAxisAutoLockGradient,
-                                                                                                      mLockAxis,
-                                                                                                      mMaxOvershoot,
-                                                                                                      mRulerX,
-                                                                                                      mRulerY));
-    mScrollMainInternalPrePositionConstraint.AddSource(Source(detector, PanGestureDetector::Property::LOCAL_POSITION));
-    mScrollMainInternalPrePositionConstraint.AddSource(Source(detector, PanGestureDetector::Property::PANNING));
-    mScrollMainInternalPrePositionConstraint.AddSource(Source(self, Actor::Property::SIZE));
-    mScrollMainInternalPrePositionConstraint.Apply();
-  }
-
-  // 2. Second calculate the clamped position (actual position)
-  mScrollMainInternalPositionConstraint = Constraint::New<Vector2>(self,
-                                                                   Toolkit::ScrollView::Property::SCROLL_POSITION,
-                                                                   InternalPositionConstraint(mRulerX->GetDomain(),
-                                                                                              mRulerY->GetDomain(),
-                                                                                              mWrapMode));
-  mScrollMainInternalPositionConstraint.AddSource(LocalSource(Toolkit::ScrollView::Property::SCROLL_PRE_POSITION));
-  mScrollMainInternalPositionConstraint.AddSource(LocalSource(Toolkit::Scrollable::Property::SCROLL_POSITION_MIN));
-  mScrollMainInternalPositionConstraint.AddSource(LocalSource(Toolkit::Scrollable::Property::SCROLL_POSITION_MAX));
-  mScrollMainInternalPositionConstraint.AddSource(Source(self, Actor::Property::SIZE));
-  mScrollMainInternalPositionConstraint.Apply();
-
-  mScrollMainInternalDeltaConstraint = Constraint::New<Vector2>(self, Toolkit::ScrollView::Property::SCROLL_POSITION_DELTA, InternalPositionDeltaConstraint);
-  mScrollMainInternalDeltaConstraint.AddSource(LocalSource(Toolkit::ScrollView::Property::SCROLL_POSITION));
-  mScrollMainInternalDeltaConstraint.AddSource(LocalSource(Toolkit::ScrollView::Property::SCROLL_DOMAIN_OFFSET));
-  mScrollMainInternalDeltaConstraint.Apply();
-
-  mScrollMainInternalFinalConstraint = Constraint::New<Vector2>(self, Toolkit::ScrollView::Property::SCROLL_FINAL, InternalFinalConstraint(FinalDefaultAlphaFunction, FinalDefaultAlphaFunction));
-  mScrollMainInternalFinalConstraint.AddSource(LocalSource(Toolkit::ScrollView::Property::SCROLL_POSITION));
-  mScrollMainInternalFinalConstraint.AddSource(LocalSource(Toolkit::ScrollView::Property::OVERSHOOT_X));
-  mScrollMainInternalFinalConstraint.AddSource(LocalSource(Toolkit::ScrollView::Property::OVERSHOOT_Y));
-  mScrollMainInternalFinalConstraint.Apply();
-
-  mScrollMainInternalRelativeConstraint = Constraint::New<Vector2>(self, Toolkit::Scrollable::Property::SCROLL_RELATIVE_POSITION, InternalRelativePositionConstraint);
-  mScrollMainInternalRelativeConstraint.AddSource(LocalSource(Toolkit::ScrollView::Property::SCROLL_POSITION));
-  mScrollMainInternalRelativeConstraint.AddSource(LocalSource(Toolkit::Scrollable::Property::SCROLL_POSITION_MIN));
-  mScrollMainInternalRelativeConstraint.AddSource(LocalSource(Toolkit::Scrollable::Property::SCROLL_POSITION_MAX));
-  mScrollMainInternalRelativeConstraint.AddSource(LocalSource(Actor::Property::SIZE));
-  mScrollMainInternalRelativeConstraint.Apply();
-
-  mScrollMainInternalDomainConstraint = Constraint::New<Vector2>(self, Toolkit::ScrollView::Property::SCROLL_DOMAIN_SIZE, InternalScrollDomainConstraint);
-  mScrollMainInternalDomainConstraint.AddSource(LocalSource(Toolkit::Scrollable::Property::SCROLL_POSITION_MIN));
-  mScrollMainInternalDomainConstraint.AddSource(LocalSource(Toolkit::Scrollable::Property::SCROLL_POSITION_MAX));
-  mScrollMainInternalDomainConstraint.AddSource(LocalSource(Actor::Property::SIZE));
-  mScrollMainInternalDomainConstraint.Apply();
-
-  mScrollMainInternalPrePositionMaxConstraint = Constraint::New<Vector2>(self, Toolkit::ScrollView::Property::SCROLL_PRE_POSITION_MAX, InternalPrePositionMaxConstraint);
-  mScrollMainInternalPrePositionMaxConstraint.AddSource(LocalSource(Toolkit::Scrollable::Property::SCROLL_POSITION_MAX));
-  mScrollMainInternalPrePositionMaxConstraint.AddSource(LocalSource(Actor::Property::SIZE));
-  mScrollMainInternalPrePositionMaxConstraint.Apply();
-
-  // When panning we want to make sure overshoot values are affected by pre position and post position
-  SetOvershootConstraintsEnabled(!mWrapMode);
-}
-
-void ScrollView::SetOvershootConstraintsEnabled(bool enabled)
-{
-  Actor self(Self());
-  // remove and reset, it may now be in wrong order with the main internal constraints
-  if(mScrollMainInternalOvershootXConstraint)
-  {
-    mScrollMainInternalOvershootXConstraint.Remove();
-    mScrollMainInternalOvershootXConstraint.Reset();
-    mScrollMainInternalOvershootYConstraint.Remove();
-    mScrollMainInternalOvershootYConstraint.Reset();
-  }
-  if(enabled)
-  {
-    mScrollMainInternalOvershootXConstraint = Constraint::New<float>(self, Toolkit::ScrollView::Property::OVERSHOOT_X, OvershootXConstraint(mMaxOvershoot.x));
-    mScrollMainInternalOvershootXConstraint.AddSource(LocalSource(Toolkit::ScrollView::Property::SCROLL_PRE_POSITION));
-    mScrollMainInternalOvershootXConstraint.AddSource(LocalSource(Toolkit::ScrollView::Property::SCROLL_POSITION));
-    mScrollMainInternalOvershootXConstraint.AddSource(LocalSource(Toolkit::Scrollable::Property::CAN_SCROLL_HORIZONTAL));
-    mScrollMainInternalOvershootXConstraint.Apply();
-
-    mScrollMainInternalOvershootYConstraint = Constraint::New<float>(self, Toolkit::ScrollView::Property::OVERSHOOT_Y, OvershootYConstraint(mMaxOvershoot.y));
-    mScrollMainInternalOvershootYConstraint.AddSource(LocalSource(Toolkit::ScrollView::Property::SCROLL_PRE_POSITION));
-    mScrollMainInternalOvershootYConstraint.AddSource(LocalSource(Toolkit::ScrollView::Property::SCROLL_POSITION));
-    mScrollMainInternalOvershootYConstraint.AddSource(LocalSource(Toolkit::Scrollable::Property::CAN_SCROLL_VERTICAL));
-    mScrollMainInternalOvershootYConstraint.Apply();
-  }
-  else
-  {
-    self.SetProperty(Toolkit::ScrollView::Property::OVERSHOOT_X, 0.0f);
-    self.SetProperty(Toolkit::ScrollView::Property::OVERSHOOT_Y, 0.0f);
-  }
-}
-
-void ScrollView::SetInternalConstraints()
-{
-  // Internal constraints (applied to target ScrollBase Actor itself) /////////
-  UpdateMainInternalConstraint();
-
-  // User definable constraints to apply to all child actors //////////////////
-  Actor self = Self();
-
-  // Apply some default constraints to ScrollView & its bound actors
-  // Movement + Wrap function
-
-  Constraint constraint;
-
-  // MoveActor (scrolling)
-  constraint = Constraint::New<Vector3>(self, Actor::Property::POSITION, MoveActorConstraint);
-  constraint.AddSource(Source(self, Toolkit::ScrollView::Property::SCROLL_POSITION));
-  constraint.SetRemoveAction(Constraint::DISCARD);
-  ApplyConstraintToBoundActors(constraint);
-
-  // WrapActor (wrap functionality)
-  constraint = Constraint::New<Vector3>(self, Actor::Property::POSITION, WrapActorConstraint);
-  constraint.AddSource(LocalSource(Actor::Property::SCALE));
-  constraint.AddSource(LocalSource(Actor::Property::ANCHOR_POINT));
-  constraint.AddSource(LocalSource(Actor::Property::SIZE));
-  constraint.AddSource(Source(self, Toolkit::Scrollable::Property::SCROLL_POSITION_MIN));
-  constraint.AddSource(Source(self, Toolkit::Scrollable::Property::SCROLL_POSITION_MAX));
-  constraint.AddSource(Source(self, Toolkit::ScrollView::Property::WRAP));
-  constraint.SetRemoveAction(Constraint::DISCARD);
-  ApplyConstraintToBoundActors(constraint);
-}
-
 void ScrollView::SetProperty(BaseObject* object, Property::Index index, const Property::Value& value)
 {
   Toolkit::ScrollView scrollView = Toolkit::ScrollView::DownCast(Dali::BaseHandle(object));
@@ -3051,6 +2423,31 @@ void ScrollView::SetScrollMode(const Property::Map& scrollModeMap)
   SetRulerY(rulerY);
 }
 
+ScrollView::LockAxis GetLockAxis(const Vector2& panDelta, ScrollView::LockAxis currentLockAxis, float lockGradient)
+{
+  if(panDelta.LengthSquared() > AUTOLOCK_AXIS_MINIMUM_DISTANCE2 &&
+     currentLockAxis == ScrollView::LockPossible)
+  {
+    float dx = fabsf(panDelta.x);
+    float dy = fabsf(panDelta.y);
+    if(dx * lockGradient >= dy)
+    {
+      // 0.36:1 gradient to the horizontal (deviate < 20 degrees)
+      currentLockAxis = ScrollView::LockVertical;
+    }
+    else if(dy * lockGradient > dx)
+    {
+      // 0.36:1 gradient to the vertical (deviate < 20 degrees)
+      currentLockAxis = ScrollView::LockHorizontal;
+    }
+    else
+    {
+      currentLockAxis = ScrollView::LockNone;
+    }
+  }
+  return currentLockAxis;
+}
+
 } // namespace Internal
 
 } // namespace Toolkit
index aee050e..4d871a7 100644 (file)
@@ -30,6 +30,7 @@
 #include <dali-toolkit/public-api/controls/control-impl.h>
 #include <dali-toolkit/public-api/controls/scrollable/scroll-view/scroll-view-effect.h>
 #include <dali-toolkit/public-api/controls/scrollable/scroll-view/scroll-view.h>
+#include <dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-impl-constraints.h>
 
 namespace Dali
 {
@@ -103,42 +104,66 @@ public:
   /**
    * @copydoc Toolkit::ScrollView::GetScrollSnapAlphaFunction
    */
-  AlphaFunction GetScrollSnapAlphaFunction() const;
+  AlphaFunction GetScrollSnapAlphaFunction() const
+  {
+    return mSnapAlphaFunction;
+  }
 
   /**
    * @copydoc Toolkit::ScrollView::SetScrollSnapAlphaFunction
    */
-  void SetScrollSnapAlphaFunction(AlphaFunction alpha);
+  void SetScrollSnapAlphaFunction(AlphaFunction alpha)
+  {
+    mSnapAlphaFunction = alpha;
+  }
 
   /**
    * @copydoc Toolkit::ScrollView::GetScrollFlickAlphaFunction
    */
-  AlphaFunction GetScrollFlickAlphaFunction() const;
+  AlphaFunction GetScrollFlickAlphaFunction() const
+  {
+    return mFlickAlphaFunction;
+  }
 
   /**
    * @copydoc Toolkit::ScrollView::SetScrollFlickAlphaFunction
    */
-  void SetScrollFlickAlphaFunction(AlphaFunction alpha);
+  void SetScrollFlickAlphaFunction(AlphaFunction alpha)
+  {
+    mFlickAlphaFunction = alpha;
+  }
 
   /**
    * @copydoc Toolkit::ScrollView::GetScrollSnapDuration
    */
-  float GetScrollSnapDuration() const;
+  float GetScrollSnapDuration() const
+  {
+    return mSnapDuration;
+  }
 
   /**
    * @copydoc Toolkit::ScrollView::SetScrollSnapDuration
    */
-  void SetScrollSnapDuration(float time);
+  void SetScrollSnapDuration(float time)
+  {
+    mSnapDuration = time;
+  }
 
   /**
    * @copydoc Toolkit::ScrollView::GetScrollFlickDuration
    */
-  float GetScrollFlickDuration() const;
+  float GetScrollFlickDuration() const
+  {
+    return mFlickDuration;
+  }
 
   /**
    * @copydoc Toolkit::ScrollView::SetScrollFlickDuration
    */
-  void SetScrollFlickDuration(float time);
+  void SetScrollFlickDuration(float time)
+  {
+    mFlickDuration = time;
+  }
 
   /**
    * @copydoc Toolkit::ScrollView::ApplyEffect
@@ -168,12 +193,18 @@ public:
   /**
    * @copydoc Toolkit::ScrollView::GetRulerX
    */
-  const RulerPtr GetRulerX() const;
+  const RulerPtr GetRulerX() const
+  {
+    return mRulerX;
+  }
 
   /**
    * @copydoc Toolkit::ScrollView::GetRulerY
    */
-  const RulerPtr GetRulerY() const;
+  const RulerPtr GetRulerY() const
+  {
+    return mRulerY;
+  }
 
   /**
    * @copydoc Toolkit::ScrollView::SetRulerX
@@ -190,7 +221,10 @@ public:
    *
    * @return whether the touch sensitivity is true or false.
    */
-  bool GetScrollSensitive();
+  bool GetScrollSensitive()
+  {
+    return mSensitive;
+  }
 
   /**
    * @copydoc Toolkit::ScrollView::SetScrollSensitive
@@ -205,19 +239,28 @@ public:
   /**
    * @copydoc Toolkit::ScrollView::SetSnapOvershootAlphaFunction
    */
-  void SetSnapOvershootAlphaFunction(AlphaFunction alpha);
+  void SetSnapOvershootAlphaFunction(AlphaFunction alpha)
+  {
+    mSnapOvershootAlphaFunction = alpha;
+  }
 
   /**
    * Retrieve the duartion of Snap Overshoot animation
    *
    * @return the duration.
    */
-  float GetSnapOvershootDuration();
+  float GetSnapOvershootDuration()
+  {
+    return mSnapOvershootDuration;
+  }
 
   /**
    * @copydoc Toolkit::ScrollView::SetSnapOvershootDuration
    */
-  void SetSnapOvershootDuration(float duration);
+  void SetSnapOvershootDuration(float duration)
+  {
+    mSnapOvershootDuration = duration;
+  }
 
   /**
    * Retrieve whether Actor Auto-Snap mode is enabled or not.
@@ -229,7 +272,10 @@ public:
   /**
    * @copydoc Toolkit::ScrollView::SetActorAutoSnap
    */
-  void SetActorAutoSnap(bool enable);
+  void SetActorAutoSnap(bool enable)
+  {
+    mActorAutoSnapEnabled = enable;
+  }
 
   /**
    * Enables or Disables Auto Resizing mode for ScrollView contents.
@@ -251,7 +297,10 @@ public:
    *
    * @return Wrap Mode Enabled flag.
    */
-  bool GetWrapMode() const;
+  bool GetWrapMode() const
+  {
+    return mWrapMode;
+  }
 
   /**
    * @copydoc Toolkit::ScrollView::SetWrapMode
@@ -261,17 +310,26 @@ public:
   /**
    * @copydoc Toolkit::ScrollView::GetScrollupdateDistance
    */
-  int GetScrollUpdateDistance() const;
+  int GetScrollUpdateDistance() const
+  {
+    return mScrollUpdateDistance;
+  }
 
   /**
    * @copydoc Toolkit::ScrollView::SetScrollUpdateDistance
    */
-  void SetScrollUpdateDistance(int distance);
+  void SetScrollUpdateDistance(int distance)
+  {
+    mScrollUpdateDistance = distance;
+  }
 
   /**
    * @copydoc Toolkit::ScrollView::GetAxisAutoLock
    */
-  bool GetAxisAutoLock() const;
+  bool GetAxisAutoLock() const
+  {
+    return mAxisAutoLock;
+  }
 
   /**
    * @copydoc Toolkit::ScrollView::SetAxisAutoLock
@@ -281,7 +339,10 @@ public:
   /**
    * @copydoc Toolkit::ScrollView::GetAxisAutoLockGradient
    */
-  float GetAxisAutoLockGradient() const;
+  float GetAxisAutoLockGradient() const
+  {
+    return mAxisAutoLockGradient;
+  }
 
   /**
    * @copydoc Toolkit::ScrollView::SetAxisAutoLockGradient
@@ -291,7 +352,10 @@ public:
   /**
    * @copydoc Toolkit::ScrollView::GetFrictionCoefficient
    */
-  float GetFrictionCoefficient() const;
+  float GetFrictionCoefficient() const
+  {
+    return mFrictionCoefficient;
+  }
 
   /**
    * @copydoc Toolkit::ScrollView::SetFrictionCoefficient
@@ -301,52 +365,82 @@ public:
   /**
    * @copydoc Toolkit::ScrollView::GetFlickSpeedCoefficient
    */
-  float GetFlickSpeedCoefficient() const;
+  float GetFlickSpeedCoefficient() const
+  {
+    return mFlickSpeedCoefficient;
+  }
 
   /**
    * @copydoc Toolkit::ScrollView::SetFlickSpeedCoefficient
    */
-  void SetFlickSpeedCoefficient(float speed);
+  void SetFlickSpeedCoefficient(float speed)
+  {
+    mFlickSpeedCoefficient = speed;
+  }
 
   /**
    * @copydoc Toolkit::ScrollView::GetMinimumDistanceForFlick
    */
-  Vector2 GetMinimumDistanceForFlick() const;
+  Vector2 GetMinimumDistanceForFlick() const
+  {
+    return mMinFlickDistance;
+  }
 
   /**
    * @copydoc Toolkit::ScrollView::SetMinimumDistanceForFlick
    */
-  void SetMinimumDistanceForFlick(const Vector2& distance);
+  void SetMinimumDistanceForFlick(const Vector2& distance)
+  {
+    mMinFlickDistance = distance;
+  }
 
   /**
    * @copydoc Toolkit::ScrollView::GetMinimumSpeedForFlick
    */
-  float GetMinimumSpeedForFlick() const;
+  float GetMinimumSpeedForFlick() const
+  {
+    return mFlickSpeedThreshold;
+  }
 
   /**
    * @copydoc Toolkit::ScrollView::SetMinimumSpeedForFlick
    */
-  void SetMinimumSpeedForFlick(float speed);
+  void SetMinimumSpeedForFlick(float speed)
+  {
+    mFlickSpeedThreshold = speed;
+  }
 
   /**
    * @copydoc Toolkit::ScrollView::GetMaxFlickSpeed
    */
-  float GetMaxFlickSpeed() const;
+  float GetMaxFlickSpeed() const
+  {
+    return mMaxFlickSpeed;
+  }
 
   /**
    * @copydoc Toolkit::ScrollView::SetMaxFlickSpeed
    */
-  void SetMaxFlickSpeed(float speed);
+  void SetMaxFlickSpeed(float speed)
+  {
+    mMaxFlickSpeed = speed;
+  }
 
   /**
    * @copydoc Toolkit::ScrollView::GetWheelScrollDistanceStep
    */
-  Vector2 GetWheelScrollDistanceStep() const;
+  Vector2 GetWheelScrollDistanceStep() const
+  {
+    return mWheelScrollDistanceStep;
+  }
 
   /**
    * @copydoc Toolkit::ScrollView::SetWheelScrollDistanceStep
    */
-  void SetWheelScrollDistanceStep(Vector2 step);
+  void SetWheelScrollDistanceStep(Vector2 step)
+  {
+    mWheelScrollDistanceStep = step;
+  }
 
   /**
    * @copydoc Toolkit::ScrollView::GetCurrentPage
@@ -765,26 +859,6 @@ private:
    */
   void WrapPosition(Vector2& position) const;
 
-  /**
-   * Updates the main internal scroll constraints with new ruler and domain
-   * values
-   */
-  void UpdateMainInternalConstraint();
-
-  /**
-   * Enables/disables the overshoot constraints
-   *
-   * @param[in] enabled whether to enable or disable the overshoot constraints
-   */
-  void SetOvershootConstraintsEnabled(bool enabled);
-
-  /**
-   * Sets internal constraints for this ScrollView.
-   * Many of these internal constraints are based on properties within
-   * ScrollView.
-   */
-  void SetInternalConstraints();
-
 protected:
   struct AccessibleImpl : public Scrollable::AccessibleImpl
   {
@@ -865,6 +939,8 @@ private:
   ScrollView& operator=(const ScrollView& rhs);
 
 private:
+  ScrollViewConstraints mConstraints;
+
   unsigned long mTouchDownTime; ///< The touch down time
 
   int     mGestureStackDepth; ///< How many gestures are currently occuring.
@@ -922,17 +998,6 @@ private:
 
   Vector2 mWheelScrollDistanceStep; ///< The step of scroll distance in actor coordinates in X and Y axes for each wheel event received.
 
-  //ScrollInternalConstraintsPtr mScrollInternalConstraints;
-  Constraint mScrollMainInternalPrePositionConstraint;
-  Constraint mScrollMainInternalPositionConstraint;
-  Constraint mScrollMainInternalOvershootXConstraint;
-  Constraint mScrollMainInternalOvershootYConstraint;
-  Constraint mScrollMainInternalDeltaConstraint;
-  Constraint mScrollMainInternalFinalConstraint;
-  Constraint mScrollMainInternalRelativeConstraint;
-  Constraint mScrollMainInternalDomainConstraint;
-  Constraint mScrollMainInternalPrePositionMaxConstraint;
-
   ScrollOvershootIndicatorPtr    mOvershootIndicator;
   WeakHandle<Toolkit::ScrollBar> mScrollBar;
 
@@ -953,8 +1018,21 @@ private:
   bool mCanScrollHorizontal : 1;        ///< Local value of our property to check against
   bool mCanScrollVertical : 1;          ///< Local value of our property to check against
   bool mTransientScrollBar : 1;         ///< True if scroll-bar should be automatically show/hidden during/after panning
+
+  friend ScrollViewConstraints;
 };
 
+/**
+ * Returns whether to lock scrolling to a particular axis
+ *
+ * @param[in] panDelta Distance panned since gesture started
+ * @param[in] currentLockAxis The current lock axis value
+ * @param[in] lockGradient How quickly to lock to a particular axis
+ *
+ * @return The new axis lock state
+ */
+ScrollView::LockAxis GetLockAxis(const Vector2& panDelta, ScrollView::LockAxis currentLockAxis, float lockGradient);
+
 } // namespace Internal
 
 // Helpers for public-api forwarding methods
index 4b3e019..9aec5ba 100644 (file)
@@ -51,7 +51,7 @@ bool FitToChild(Actor actor, Dimension::Type dimension)
 // currently not called from code so compiler will optimize these away, kept here for future debugging
 
 #define TABLEVIEW_TAG "DALI Toolkit::TableView "
-#define TV_LOG(fmt, args, ...) Debug::LogMessage(Debug::DebugInfo, TABLEVIEW_TAG fmt, ##args)
+#define TV_LOG(fmt, args, ...) Debug::LogMessageWithFunctionLine(Debug::DebugInfo, TABLEVIEW_TAG fmt, ##args)
 //#define TABLEVIEW_DEBUG 1
 
 #if defined(TABLEVIEW_DEBUG)
index 77b29ca..85b2fe1 100755 (executable)
 #include <dali-toolkit/devel-api/controls/web-view/web-context.h>
 #include <dali-toolkit/devel-api/controls/web-view/web-cookie-manager.h>
 #include <dali-toolkit/devel-api/controls/web-view/web-settings.h>
-#include <dali-toolkit/devel-api/image-loader/texture-manager.h>
 #include <dali-toolkit/internal/visuals/visual-factory-impl.h>
 #include <dali-toolkit/public-api/image-loader/image.h>
-#include <dali-toolkit/public-api/visuals/image-visual-properties.h>
 #include <dali-toolkit/public-api/image-loader/image-url.h>
+#include <dali-toolkit/public-api/visuals/image-visual-properties.h>
 
 namespace Dali
 {
@@ -634,7 +633,7 @@ Dali::Toolkit::ImageView WebView::CreateImageView(Dali::PixelData pixel) const
     return Dali::Toolkit::ImageView();
   }
 
-  Dali::Toolkit::ImageUrl url       = Dali::Toolkit::Image::GenerateUrl(pixel);
+  Dali::Toolkit::ImageUrl  url       = Dali::Toolkit::Image::GenerateUrl(pixel);
   Dali::Toolkit::ImageView imageView = Dali::Toolkit::ImageView::New(url.GetUrl());
   imageView.SetProperty(Dali::Actor::Property::SIZE, Vector2(pixel.GetWidth(), pixel.GetHeight()));
   return imageView;
@@ -777,9 +776,8 @@ void WebView::OnInitialFrameRendered()
 {
   mWebEngine.FrameRenderedSignal().Disconnect(this, &WebView::OnInitialFrameRendered);
 
-  Texture           texture        = Dali::Texture::New(*mWebEngine.GetNativeImageSource());
-  const std::string nativeImageUrl = Dali::Toolkit::TextureManager::AddTexture(texture);
-  mVisual                          = Toolkit::VisualFactory::Get().CreateVisual({{Toolkit::Visual::Property::TYPE, Toolkit::Visual::IMAGE}, {Toolkit::ImageVisual::Property::URL, nativeImageUrl}});
+  Dali::Toolkit::ImageUrl nativeImageUrl = Dali::Toolkit::Image::GenerateUrl(mWebEngine.GetNativeImageSource());
+  mVisual                                = Toolkit::VisualFactory::Get().CreateVisual({{Toolkit::Visual::Property::TYPE, Toolkit::Visual::IMAGE}, {Toolkit::ImageVisual::Property::URL, nativeImageUrl.GetUrl()}});
 
   if(mVisual)
   {
index f1aa866..7fb8e01 100644 (file)
@@ -92,6 +92,7 @@ SET( toolkit_src_files
    ${toolkit_src_dir}/controls/scrollable/scroll-view/scroll-overshoot-indicator-impl.cpp
    ${toolkit_src_dir}/controls/scrollable/scroll-view/scroll-view-effect-impl.cpp
    ${toolkit_src_dir}/controls/scrollable/scroll-view/scroll-view-impl.cpp
+   ${toolkit_src_dir}/controls/scrollable/scroll-view/scroll-view-impl-constraints.cpp
    ${toolkit_src_dir}/controls/scrollable/scroll-view/scroll-view-page-path-effect-impl.cpp
    ${toolkit_src_dir}/controls/scene3d-view/scene3d-view-impl.cpp
    ${toolkit_src_dir}/controls/scene3d-view/gltf-loader.cpp
index cf1eb08..3e3d19d 100644 (file)
@@ -122,32 +122,54 @@ lowp vec4 convertBorderlineColor(lowp vec4 textureColor)
   {
     // potential is inside borderline range.
     borderlineOpacity = smoothstep(gMinInlinePotential, gMaxInlinePotential, potential);
+
+    // Muliply borderlineWidth to resolve very thin borderline
+    borderlineOpacity *= min(1.0, borderlineWidth);
   }
 
-  lowp vec3  BorderlineColorRGB   = borderlineColor.rgb * uActorColor.rgb;
-  lowp float BorderlineColorAlpha = borderlineColor.a * uActorColor.a;
+  lowp vec3  borderlineColorRGB   = borderlineColor.rgb * uActorColor.rgb;
+  lowp float borderlineColorAlpha = borderlineColor.a * uActorColor.a;
+  // NOTE : color-visual is always not preMultiplied.
 
-  //calculate inside of borderline when outilneColor.a < 1.0
-  if(borderlineColor.a < 1.0)
+  // Calculate inside of borderline when alpha is between (0.0  1.0). So we need to apply texture color.
+  // If borderlineOpacity is exactly 0.0, we always use whole texture color. In this case, we don't need to run below code.
+  // But if borderlineOpacity > 0.0 and borderlineColor.a == 0.0, we need to apply tCornerRadius.
+  if(borderlineOpacity > 0.0 && borderlineColor.a * borderlineOpacity < 1.0)
   {
     mediump float tCornerRadius = -gCenterPosition;
     mediump float MaxTexturelinePotential = tCornerRadius + gPotentialRange;
     mediump float MinTexturelinePotential = tCornerRadius - gPotentialRange;
     if(potential > MaxTexturelinePotential)
     {
-      // potential is out of texture range. use borderline color instead of texture
-      textureColor = vec4(BorderlineColorRGB, 0.0);
+      // potential is out of texture range.
+      textureColor = vec4(0.0);
     }
-    else if(potential > MinTexturelinePotential)
+    else
     {
-      // potential is in texture range
-      textureColor = mix(textureColor, vec4(BorderlineColorRGB, 0.0), smoothstep(MinTexturelinePotential, MaxTexturelinePotential, potential));
+      // potential is in texture range.
+      lowp float textureAlphaScale = mix(1.0, 0.0, smoothstep(MinTexturelinePotential, MaxTexturelinePotential, potential));
+      textureColor.a *= textureAlphaScale;
+      textureColor.rgb *= textureColor.a;
     }
-    // TODO : need to fix here when uColor.a = 0.0 and uActorColor.a != 0
-    borderlineOpacity *= borderlineColor.a;
-    return mix(textureColor, vec4(BorderlineColorRGB, 1.0), borderlineOpacity);
+
+    // NOTE : color-visual is always not preMultiplied.
+    borderlineColorAlpha *= borderlineOpacity;
+    borderlineColorRGB *= borderlineColorAlpha;
+    // We use pre-multiplied color to reduce operations.
+    // In here, textureColor and borderlineColorRGB is pre-multiplied color now.
+
+    // Manual blend operation with premultiplied colors.
+    // Final alpha = borderlineColorAlpha + (1.0 - borderlineColorAlpha) * textureColor.a.
+    // (Final rgb * alpha) =  borderlineColorRGB + (1.0 - borderlineColorAlpha) * textureColor.rgb
+    // If preMultipliedAlpha == 1.0, just return vec4(rgb*alpha, alpha)
+    // Else, return vec4((rgb*alpha) / alpha, alpha)
+
+    lowp float finalAlpha = mix(textureColor.a, 1.0, borderlineColorAlpha);
+    lowp vec3  finalMultipliedRGB = borderlineColorRGB + (1.0 - borderlineColorAlpha) * textureColor.rgb;
+    // TODO : Need to find some way without division
+    return vec4(finalMultipliedRGB / finalAlpha, finalAlpha);
   }
-  return mix(textureColor, vec4(BorderlineColorRGB, BorderlineColorAlpha), borderlineOpacity);
+  return mix(textureColor, vec4(borderlineColorRGB, borderlineColorAlpha), borderlineOpacity);
 }
 #endif
 
@@ -219,18 +241,18 @@ mediump float calculateBlurOpacity()
 
     // solve (v.x - x)^2 + (v.y - x)^2 = (cr / cy * x)^2
 #if IS_REQUIRED_ROUNDED_CORNER
-    // NOTE : lowspec HW cannot calculate here. need to reduce numeric error
-    mediump float A = (cr * cr - 2.0 * cy * cy);
-    mediump float B = cy * (v.x + v.y);
-    mediump float V = dot(v,v);
-    mediump float D = B * B + A * V;
+    // Note : lowspec HW cannot calculate here. need to reduce numeric error
+    highp float A = (cr * cr - 2.0 * cy * cy);
+    highp float B = cy * (v.x + v.y);
+    highp float V = dot(v,v);
+    highp float D = B * B + A * V;
     potential = V * (cr + cy) / (sqrt(D) + B);
 #else
     // We can simplify this value cause cy = 0.8 * blurRadius, cr = 1.2 * blurRadius
     // potential = 5.0*(sqrt(4.0*(v.x+v.y)^2 + dot(v,v)) - 2.0*(v.x+v.y));
     //           = 10.0*(v.x+v.y) * (sqrt(1.0 + (length(v) / (2.0*(v.x+v.y)))^2) - 1.0);
     //           = 10.0*(v.x+v.y) * (sqrt(1.25 - x + x^2) - 1.0);
-    //          ~= 10.0*(v.x+v.y) * (0.11803399 - 0.44721360x + 0.35777088x^2 - 0.14310x^3 + O(x^4)) (Taylor series)
+    //          ~= 10.0*(v.x+v.y) * (0.11803399 - 0.44721360x + 0.35777088x^2 - 0.14310x^3 + O(x^5)) (Taylor series)
     //          ~= -1.0557281 * (v.x + v.y) + 2.236068 * length(v) - ~~~ (here, x <= 0.5 * (1.0 - sqrt(0.5)) < 0.1464467)
     // Note : This simplify need cause we should use it on lowspec HW.
     mediump float x = 0.5 * (1.0 - length(v) / (v.x + v.y));
index 78f8f22..80090f8 100644 (file)
@@ -121,35 +121,54 @@ lowp vec4 convertBorderlineColor(lowp vec4 textureColor)
   {
     // potential is inside borderline range.
     borderlineOpacity = smoothstep(gMinInlinePotential, gMaxInlinePotential, potential);
+
+    // Muliply borderlineWidth to resolve very thin borderline
+    borderlineOpacity *= min(1.0, borderlineWidth);
   }
 
-  lowp vec3  BorderlineColorRGB   = borderlineColor.rgb * uActorColor.rgb;
-  lowp float BorderlineColorAlpha = borderlineColor.a * uActorColor.a;
-  // Gradient is always preMultiplied.
-  BorderlineColorRGB *= BorderlineColorAlpha;
+  lowp vec3  borderlineColorRGB   = borderlineColor.rgb * uActorColor.rgb;
+  lowp float borderlineColorAlpha = borderlineColor.a * uActorColor.a;
+  // NOTE : gradient-visual is always preMultiplied.
+  borderlineColorRGB *= borderlineColorAlpha;
 
-  //calculate inside of borderline when outilneColor.a < 1.0
-  if(borderlineColor.a < 1.0)
+  // Calculate inside of borderline when alpha is between (0.0  1.0). So we need to apply texture color.
+  // If borderlineOpacity is exactly 0.0, we always use whole texture color. In this case, we don't need to run below code.
+  // But if borderlineOpacity > 0.0 and borderlineColor.a == 0.0, we need to apply tCornerRadius.
+  if(borderlineOpacity > 0.0 && borderlineColor.a * borderlineOpacity < 1.0)
   {
     mediump float tCornerRadius = -gCenterPosition;
     mediump float MaxTexturelinePotential = tCornerRadius + gPotentialRange;
     mediump float MinTexturelinePotential = tCornerRadius - gPotentialRange;
-    lowp vec3 BorderlineColorRGB = borderlineColor.xyz * borderlineColor.a;
     if(potential > MaxTexturelinePotential)
     {
-      // potential is out of texture range. use borderline color instead of texture
-      textureColor = vec4(BorderlineColorRGB, 0.0);
+      // potential is out of texture range.
+      textureColor = vec4(0.0);
     }
-    else if(potential > MinTexturelinePotential)
+    else
     {
-      // potential is in texture range
-      textureColor = mix(textureColor, vec4(BorderlineColorRGB, 0.0), smoothstep(MinTexturelinePotential, MaxTexturelinePotential, potential));
+      // potential is in texture range.
+      lowp float textureAlphaScale = mix(1.0, 0.0, smoothstep(MinTexturelinePotential, MaxTexturelinePotential, potential));
+      textureColor.a *= textureAlphaScale;
+      textureColor.rgb *= textureAlphaScale;
     }
-    // TODO : need to fix here when uColor.a = 0.0 and uActorColor.a != 0
-    borderlineOpacity *= borderlineColor.a;
-    return mix(textureColor, vec4(BorderlineColorRGB, 1.0), borderlineOpacity);
+
+    // NOTE : gradient-visual is always preMultiplied.
+    borderlineColorAlpha *= borderlineOpacity;
+    borderlineColorRGB *= borderlineOpacity;
+    // We use pre-multiplied color to reduce operations.
+    // In here, textureColor and borderlineColorRGB is pre-multiplied color now.
+
+    // Manual blend operation with premultiplied colors.
+    // Final alpha = borderlineColorAlpha + (1.0 - borderlineColorAlpha) * textureColor.a.
+    // (Final rgb * alpha) =  borderlineColorRGB + (1.0 - borderlineColorAlpha) * textureColor.rgb
+    // If preMultipliedAlpha == 1.0, just return vec4(rgb*alpha, alpha)
+    // Else, return vec4((rgb*alpha) / alpha, alpha)
+
+    lowp float finalAlpha = mix(textureColor.a, 1.0, borderlineColorAlpha);
+    lowp vec3  finalMultipliedRGB = borderlineColorRGB + (1.0 - borderlineColorAlpha) * textureColor.rgb;
+    return vec4(finalMultipliedRGB, finalAlpha);
   }
-  return mix(textureColor, vec4(BorderlineColorRGB, BorderlineColorAlpha), borderlineOpacity);
+  return mix(textureColor, vec4(borderlineColorRGB, borderlineColorAlpha), borderlineOpacity);
 }
 #endif
 
index f9e80fe..edaf643 100644 (file)
@@ -61,8 +61,10 @@ vec4 ComputeVertexPosition()
   vOptRectSize -= 0.2929 * maxRadius + 1.0;
 #endif
 
+  mediump vec4 vertexPosition = vec4(aPosition, 0.0, 1.0);
 #if IS_REQUIRED_BORDERLINE
   vPosition = aPosition * (visualSize + (1.0 + clamp(borderlineOffset, -1.0, 1.0)) * borderlineWidth);
+  vertexPosition.xy *= (1.0 + (1.0 + clamp(borderlineOffset, -1.0, 1.0)) * borderlineWidth / visualSize);
   vOptRectSize -= (1.0 - clamp(borderlineOffset, -1.0, 1.0)) * 0.5 * borderlineWidth + 1.0;
 #elif IS_REQUIRED_ROUNDED_CORNER
   vPosition = aPosition * visualSize;
@@ -70,15 +72,16 @@ vec4 ComputeVertexPosition()
   mediump vec2 vPosition = aPosition * visualSize;
 #endif
 
+#if USER_SPACE
+  vertexPosition.xyz *= uSize;
+#endif
+
+  vTexCoord = (uAlignmentMatrix*vertexPosition.xyw).xy;
+
   return vec4(vPosition + anchorPoint * visualSize + (visualOffset + origin) * uSize.xy, 0.0, 1.0);
 }
 
 void main()
 {
-  mediump vec4 vertexPosition = vec4(aPosition, 0.0, 1.0);
   gl_Position = uMvpMatrix * ComputeVertexPosition();
-#if USER_SPACE
-  vertexPosition.xyz *= uSize;
-#endif
-  vTexCoord = (uAlignmentMatrix*vertexPosition.xyw).xy;
 }
index 676c02b..37f080f 100644 (file)
@@ -143,33 +143,53 @@ lowp vec4 convertBorderlineColor(lowp vec4 textureColor)
   {
     // potential is inside borderline range.
     borderlineOpacity = smoothstep(gMinInlinePotential, gMaxInlinePotential, potential);
+
+    // Muliply borderlineWidth to resolve very thin borderline
+    borderlineOpacity *= min(1.0, borderlineWidth);
   }
 
-  lowp vec3  BorderlineColorRGB   = borderlineColor.rgb * uActorColor.rgb;
-  lowp float BorderlineColorAlpha = borderlineColor.a * uActorColor.a;
-  BorderlineColorRGB *= mix(1.0, BorderlineColorAlpha, preMultipliedAlpha);
+  lowp vec3  borderlineColorRGB   = borderlineColor.rgb * uActorColor.rgb;
+  lowp float borderlineColorAlpha = borderlineColor.a * uActorColor.a;
+  borderlineColorRGB *= mix(1.0, borderlineColorAlpha, preMultipliedAlpha);
 
-  //calculate inside of borderline when outilneColor.a < 1.0
-  if(borderlineColor.a < 1.0)
+  // Calculate inside of borderline when alpha is between (0.0  1.0). So we need to apply texture color.
+  // If borderlineOpacity is exactly 0.0, we always use whole texture color. In this case, we don't need to run below code.
+  // But if borderlineOpacity > 0.0 and borderlineColor.a == 0.0, we need to apply tCornerRadius.
+  if(borderlineOpacity > 0.0 && borderlineColor.a * borderlineOpacity < 1.0)
   {
     mediump float tCornerRadius = -gCenterPosition;
     mediump float MaxTexturelinePotential = tCornerRadius + gPotentialRange;
     mediump float MinTexturelinePotential = tCornerRadius - gPotentialRange;
     if(potential > MaxTexturelinePotential)
     {
-      // potential is out of texture range. use borderline color instead of texture
-      textureColor = vec4(BorderlineColorRGB, 0.0);
+      // potential is out of texture range.
+      textureColor = vec4(0.0);
     }
-    else if(potential > MinTexturelinePotential)
+    else
     {
-      // potential is in texture range
-      textureColor = mix(textureColor, vec4(BorderlineColorRGB, 0.0), smoothstep(MinTexturelinePotential, MaxTexturelinePotential, potential));
+      // potential is in texture range.
+      lowp float textureAlphaScale = mix(1.0, 0.0, smoothstep(MinTexturelinePotential, MaxTexturelinePotential, potential));
+      textureColor.a *= textureAlphaScale;
+      textureColor.rgb *= mix(textureColor.a, textureAlphaScale, preMultipliedAlpha);
     }
-    // TODO : need to fix here when uColor.a = 0.0 and uActorColor.a != 0
-    borderlineOpacity *= borderlineColor.a;
-    return mix(textureColor, vec4(BorderlineColorRGB, 1.0), borderlineOpacity);
+
+    borderlineColorAlpha *= borderlineOpacity;
+    borderlineColorRGB *= mix(borderlineColorAlpha, borderlineOpacity, preMultipliedAlpha);
+    // We use pre-multiplied color to reduce operations.
+    // In here, textureColor and borderlineColorRGB is pre-multiplied color now.
+
+    // Manual blend operation with premultiplied colors.
+    // Final alpha = borderlineColorAlpha + (1.0 - borderlineColorAlpha) * textureColor.a.
+    // (Final rgb * alpha) =  borderlineColorRGB + (1.0 - borderlineColorAlpha) * textureColor.rgb
+    // If preMultipliedAlpha == 1.0, just return vec4(rgb*alpha, alpha)
+    // Else, return vec4((rgb*alpha) / alpha, alpha)
+
+    lowp float finalAlpha = mix(textureColor.a, 1.0, borderlineColorAlpha);
+    lowp vec3  finalMultipliedRGB = borderlineColorRGB + (1.0 - borderlineColorAlpha) * textureColor.rgb;
+    // TODO : Need to find some way without division
+    return vec4(finalMultipliedRGB * mix(1.0 / finalAlpha, 1.0, preMultipliedAlpha), finalAlpha);
   }
-  return mix(textureColor, vec4(BorderlineColorRGB, BorderlineColorAlpha), borderlineOpacity);
+  return mix(textureColor, vec4(borderlineColorRGB, borderlineColorAlpha), borderlineOpacity);
 }
 #endif
 
index 0968081..959724b 100644 (file)
@@ -45,6 +45,8 @@ const char* APPLICATION_RESOURCE_PATH_KEY = "APPLICATION_RESOURCE_PATH";
 
 const char* DEFAULT_TOOLKIT_PACKAGE_PATH = "/toolkit/";
 
+static constexpr int32_t COUNT_BROKEN_IMAGE_MAX = 3;
+
 #if defined(DEBUG_ENABLED)
 Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_STYLE");
 #endif
@@ -125,6 +127,9 @@ StyleManager::StyleManager()
 
   // Sound & haptic style
   mFeedbackStyle = new FeedbackStyle();
+
+  // Initialize BrokenImages
+  mBrokenImageUrls.assign(COUNT_BROKEN_IMAGE_MAX, "");
 }
 
 StyleManager::~StyleManager()
@@ -230,6 +235,11 @@ Toolkit::StyleManager::StyleChangedSignalType& StyleManager::ControlStyleChangeS
   return mControlStyleChangeSignal;
 }
 
+Toolkit::DevelStyleManager::BrokenImageChangedSignalType& StyleManager::BrokenImageChangedSignal()
+{
+  return mBrokenImageChangedSignal;
+}
+
 void StyleManager::SetTheme(const std::string& themeFile)
 {
   bool themeLoaded = false;
@@ -309,6 +319,34 @@ const Property::Map StyleManager::GetConfigurations()
   return result;
 }
 
+void StyleManager::SetBrokenImageUrl(DevelStyleManager::BrokenImageType brokenImageType, const std::string& brokenImageUrl)
+{
+  int brokenType = static_cast<int>(brokenImageType);
+  mBrokenImageUrls[brokenType] = brokenImageUrl;
+  Toolkit::StyleManager styleManager = StyleManager::Get();
+  mBrokenImageChangedSignal.Emit(styleManager);
+}
+
+std::string StyleManager::GetBrokenImageUrl(DevelStyleManager::BrokenImageType brokenImageType)
+{
+  int brokenType = static_cast<int>(brokenImageType);
+  return mBrokenImageUrls[brokenType];
+}
+
+std::vector<std::string> StyleManager::GetBrokenImageUrlList()
+{
+  // create a list for brokenImage
+  std::vector<std::string> brokenImageUrlList;
+  for(int i = 0; i < COUNT_BROKEN_IMAGE_MAX; i++)
+  {
+    if(!mBrokenImageUrls[i].empty())
+    {
+      brokenImageUrlList.push_back(mBrokenImageUrls[i]);
+    }
+  }
+  return brokenImageUrlList;
+}
+
 bool StyleManager::LoadFile(const std::string& filename, std::string& stringOut)
 {
   DALI_ASSERT_DEBUG(0 != filename.length());
index b6eaff5..56e61f0 100644 (file)
@@ -30,6 +30,7 @@
 #include <dali-toolkit/devel-api/builder/builder.h>
 #include <dali-toolkit/internal/builder/style.h>
 #include <dali-toolkit/public-api/styling/style-manager.h>
+#include <dali-toolkit/devel-api/styling/style-manager-devel.h>
 
 namespace Dali
 {
@@ -95,6 +96,21 @@ public: // Public API
   const Property::Map GetConfigurations();
 
   /**
+   * @copydoc Toolkit::DevelStyleManager::SetBrokenImageUrl
+   */
+  void SetBrokenImageUrl(DevelStyleManager::BrokenImageType brokenImageType, const std::string& brokenImageUrl);
+
+  /**
+   * @copydoc Toolkit::DevelStyleManager::GetBrokenImageUrl
+   */
+  std::string GetBrokenImageUrl(DevelStyleManager::BrokenImageType brokenImageType);
+
+  /**
+   * @copydoc Toolkit::DevelStyleManager::GetBrokenImageUrlList
+   */
+  std::vector<std::string> GetBrokenImageUrlList();
+
+  /**
    * @brief Apply the theme style to a control.
    *
    * @param[in] control The control to apply style.
@@ -136,6 +152,12 @@ public:
    */
   Toolkit::StyleManager::StyleChangedSignalType& ControlStyleChangeSignal();
 
+  /**
+   * This signal is sent to the visual factory following a broken image change.
+   * It should not be exposed in the public API
+   */
+  Toolkit::DevelStyleManager::BrokenImageChangedSignalType& BrokenImageChangedSignal();
+
 private:
   typedef std::vector<std::string> StringList;
 
@@ -233,9 +255,12 @@ private:
 
   Toolkit::Internal::FeedbackStyle* mFeedbackStyle; ///< Feedback style
 
+  std::vector<std::string> mBrokenImageUrls;    ///< Broken Image Urls received from user
+
   // Signals
-  Toolkit::StyleManager::StyleChangedSignalType mControlStyleChangeSignal; ///< Emitted when the style( theme/font ) changes for the controls to style themselves
-  Toolkit::StyleManager::StyleChangedSignalType mStyleChangedSignal;       ///< Emitted after the controls have been styled
+  Toolkit::StyleManager::StyleChangedSignalType            mControlStyleChangeSignal; ///< Emitted when the style( theme/font ) changes for the controls to style themselves
+  Toolkit::StyleManager::StyleChangedSignalType            mStyleChangedSignal;       ///< Emitted after the controls have been styled
+  Toolkit::DevelStyleManager::BrokenImageChangedSignalType mBrokenImageChangedSignal; ///< Emitted after brokenImageChangedSignal
 };
 
 } // namespace Internal
index a0e6ae5..82470f8 100644 (file)
@@ -228,7 +228,8 @@ void MultilanguageSupport::SetScripts(const Vector<Character>& text,
       // Check if whether is right to left markup and Keeps true if the previous value was true.
       currentScriptRun.isRightToLeft = currentScriptRun.isRightToLeft || TextAbstraction::IsRightToLeftMark(character);
 
-      if(TextAbstraction::EMOJI == currentScriptRun.script)
+      // ZWJ, ZWNJ between emojis should be treated as EMOJI.
+      if(TextAbstraction::EMOJI == currentScriptRun.script && !(TextAbstraction::IsZeroWidthJoiner(character) || TextAbstraction::IsZeroWidthNonJoiner(character)))
       {
         // Emojis doesn't mix well with characters common to all scripts. Insert the emoji run.
         scripts.Insert(scripts.Begin() + scriptIndex, currentScriptRun);
@@ -444,7 +445,8 @@ void MultilanguageSupport::ValidateFonts(const Vector<Character>&
   Vector<ScriptRun>::ConstIterator scriptRunEndIt          = scripts.End();
   bool                             isNewParagraphCharacter = false;
 
-  bool isPreviousEmojiScript = false;
+  bool   isPreviousEmojiScript = false;
+  FontId previousEmojiFontId   = 0u;
 
   CharacterIndex lastCharacter = startIndex + numberOfCharacters;
   for(Length index = startIndex; index < lastCharacter; ++index)
@@ -535,6 +537,16 @@ void MultilanguageSupport::ValidateFonts(const Vector<Character>&
       currentFontRun.isBoldRequired                  = false;
     }
 
+    // ZWJ, ZWNJ between emojis should use the previous emoji font.
+    if(isEmojiScript && (TextAbstraction::IsZeroWidthJoiner(character) || TextAbstraction::IsZeroWidthNonJoiner(character)))
+    {
+      if(0u != previousEmojiFontId)
+      {
+        fontId      = previousEmojiFontId;
+        isValidFont = true;
+      }
+    }
+
     // If the given font is not valid, it means either:
     // - there is no cached font for the current script yet or,
     // - the user has set a different font than the default one for the current script or,
@@ -647,6 +659,15 @@ void MultilanguageSupport::ValidateFonts(const Vector<Character>&
       }   // !isValidFont (2)
     }     // !isValidFont (1)
 
+    // Store the font id when the first character is an emoji.
+    if(isEmojiScript && !isPreviousEmojiScript)
+    {
+      if(0u != fontId)
+      {
+        previousEmojiFontId = fontId;
+      }
+    }
+
 #ifdef DEBUG_ENABLED
     {
       Dali::TextAbstraction::FontDescription description;
index 30c6e04..6e4d361 100644 (file)
@@ -46,48 +46,76 @@ constexpr float MAX_FLOAT = std::numeric_limits<float>::max();
 
 const std::string EMPTY_STRING("");
 
-int ConvertPixelToPint(float pixel)
+template<typename Type>
+void EnsureCreated(Type*& object)
 {
-  unsigned int                      horizontalDpi = 0u;
-  unsigned int                      verticalDpi   = 0u;
-  Dali::TextAbstraction::FontClient fontClient    = Dali::TextAbstraction::FontClient::Get();
-  fontClient.GetDpi(horizontalDpi, verticalDpi);
-
-  return (pixel * 72.f) / static_cast<float>(horizontalDpi);
+  if(!object)
+  {
+    object = new Type();
+  }
 }
 
-} // namespace
+template<typename Type>
+void EnsureCreated(std::unique_ptr<Type>& object)
+{
+  if(!object)
+  {
+    object = std::unique_ptr<Type>(new Type());
+  }
+}
 
-namespace Dali
+template<typename Type, typename Arg1>
+void EnsureCreated(Type*& object, Arg1 arg1)
 {
-namespace Toolkit
+  if(!object)
+  {
+    object = new Type(arg1);
+  }
+}
+
+template<typename Type, typename Arg1, typename Arg2>
+void EnsureCreated(Type*& object, Arg1 arg1, Arg2 arg2)
 {
-namespace Text
+  if(!object)
+  {
+    object = new Type(arg1, arg2);
+  }
+}
+
+float GetDpi()
 {
-// public : Constructor.
+  unsigned int                      horizontalDpi = 0u;
+  unsigned int                      verticalDpi   = 0u;
+  Dali::TextAbstraction::FontClient fontClient    = Dali::TextAbstraction::FontClient::Get();
+  fontClient.GetDpi(horizontalDpi, verticalDpi);
+  return static_cast<float>(horizontalDpi);
+}
 
-ControllerPtr Controller::New()
+float ConvertPixelToPoint(float pixel)
 {
-  return ControllerPtr(new Controller());
+  return pixel * 72.0f / GetDpi();
 }
 
-ControllerPtr Controller::New(ControlInterface* controlInterface)
+float ConvertPointToPixel(float point)
 {
-  return ControllerPtr(new Controller(controlInterface));
+  // Pixel size = Point size * DPI / 72.f
+  return point * GetDpi() / 72.0f;
 }
 
-ControllerPtr Controller::New(ControlInterface*           controlInterface,
-                              EditableControlInterface*   editableControlInterface,
-                              SelectableControlInterface* selectableControlInterface,
-                              AnchorControlInterface*     anchorControlInterface)
+void UpdateCursorPosition(Dali::Toolkit::Text::EventData* eventData)
 {
-  return ControllerPtr(new Controller(controlInterface,
-                                      editableControlInterface,
-                                      selectableControlInterface,
-                                      anchorControlInterface));
+  if(eventData && Dali::Toolkit::Text::EventData::IsEditingState(eventData->mState))
+  {
+    // Update the cursor position if it's in editing mode
+    eventData->mDecoratorUpdated     = true;
+    eventData->mUpdateCursorPosition = true; // Cursor position should be updated when the font size is updated.
+  }
 }
 
-// public : Configure the text controller.
+} // namespace
+
+namespace Dali::Toolkit::Text
+{
 
 void Controller::EnableTextInput(DecoratorPtr decorator, InputMethodContext& inputMethodContext)
 {
@@ -100,10 +128,7 @@ void Controller::EnableTextInput(DecoratorPtr decorator, InputMethodContext& inp
     return;
   }
 
-  if(NULL == mImpl->mEventData)
-  {
-    mImpl->mEventData = new EventData(decorator, inputMethodContext);
-  }
+  EnsureCreated(mImpl->mEventData, decorator, inputMethodContext);
 }
 
 void Controller::SetGlyphType(TextAbstraction::GlyphType glyphType)
@@ -147,24 +172,20 @@ void Controller::SetAutoScrollEnabled(bool enable)
 
   if(mImpl->mLayoutEngine.GetLayout() == Layout::Engine::SINGLE_LINE_BOX)
   {
+    mImpl->mOperationsPending = static_cast<OperationsMask>(mImpl->mOperationsPending |
+                                                            LAYOUT |
+                                                            ALIGN |
+                                                            UPDATE_LAYOUT_SIZE |
+                                                            REORDER);
+
     if(enable)
     {
       DALI_LOG_INFO(gLogFilter, Debug::General, "Controller::SetAutoScrollEnabled for SINGLE_LINE_BOX\n");
-      mImpl->mOperationsPending = static_cast<OperationsMask>(mImpl->mOperationsPending |
-                                                              LAYOUT |
-                                                              ALIGN |
-                                                              UPDATE_LAYOUT_SIZE |
-                                                              UPDATE_DIRECTION |
-                                                              REORDER);
+      mImpl->mOperationsPending = static_cast<OperationsMask>(mImpl->mOperationsPending | UPDATE_DIRECTION);
     }
     else
     {
       DALI_LOG_INFO(gLogFilter, Debug::General, "Controller::SetAutoScrollEnabled Disabling autoscroll\n");
-      mImpl->mOperationsPending = static_cast<OperationsMask>(mImpl->mOperationsPending |
-                                                              LAYOUT |
-                                                              ALIGN |
-                                                              UPDATE_LAYOUT_SIZE |
-                                                              REORDER);
     }
 
     mImpl->mIsAutoScrollEnabled = enable;
@@ -192,62 +213,42 @@ CharacterDirection Controller::GetAutoScrollDirection() const
 float Controller::GetAutoScrollLineAlignment() const
 {
   float offset = 0.f;
-
-  if(mImpl->mModel->mVisualModel &&
-     (0u != mImpl->mModel->mVisualModel->mLines.Count()))
+  if(mImpl->mModel->mVisualModel && (0u != mImpl->mModel->mVisualModel->mLines.Count()))
   {
     offset = (*mImpl->mModel->mVisualModel->mLines.Begin()).alignmentOffset;
   }
-
   return offset;
 }
 
 void Controller::SetHorizontalScrollEnabled(bool enable)
 {
-  if((NULL != mImpl->mEventData) &&
-     mImpl->mEventData->mDecorator)
+  if(mImpl->mEventData && mImpl->mEventData->mDecorator)
   {
     mImpl->mEventData->mDecorator->SetHorizontalScrollEnabled(enable);
   }
 }
+
 bool Controller::IsHorizontalScrollEnabled() const
 {
-  if((NULL != mImpl->mEventData) &&
-     mImpl->mEventData->mDecorator)
-  {
-    return mImpl->mEventData->mDecorator->IsHorizontalScrollEnabled();
-  }
-
-  return false;
+  return mImpl->mEventData && mImpl->mEventData->mDecorator && mImpl->mEventData->mDecorator->IsHorizontalScrollEnabled();
 }
 
 void Controller::SetVerticalScrollEnabled(bool enable)
 {
-  if((NULL != mImpl->mEventData) &&
-     mImpl->mEventData->mDecorator)
+  if(mImpl->mEventData && mImpl->mEventData->mDecorator)
   {
-    if(mImpl->mEventData->mDecorator)
-    {
-      mImpl->mEventData->mDecorator->SetVerticalScrollEnabled(enable);
-    }
+    mImpl->mEventData->mDecorator->SetVerticalScrollEnabled(enable);
   }
 }
 
 bool Controller::IsVerticalScrollEnabled() const
 {
-  if((NULL != mImpl->mEventData) &&
-     mImpl->mEventData->mDecorator)
-  {
-    return mImpl->mEventData->mDecorator->IsVerticalScrollEnabled();
-  }
-
-  return false;
+  return mImpl->mEventData && mImpl->mEventData->mDecorator && mImpl->mEventData->mDecorator->IsVerticalScrollEnabled();
 }
 
 void Controller::SetSmoothHandlePanEnabled(bool enable)
 {
-  if((NULL != mImpl->mEventData) &&
-     mImpl->mEventData->mDecorator)
+  if(mImpl->mEventData && mImpl->mEventData->mDecorator)
   {
     mImpl->mEventData->mDecorator->SetSmoothHandlePanEnabled(enable);
   }
@@ -255,13 +256,7 @@ void Controller::SetSmoothHandlePanEnabled(bool enable)
 
 bool Controller::IsSmoothHandlePanEnabled() const
 {
-  if((NULL != mImpl->mEventData) &&
-     mImpl->mEventData->mDecorator)
-  {
-    return mImpl->mEventData->mDecorator->IsSmoothHandlePanEnabled();
-  }
-
-  return false;
+  return mImpl->mEventData && mImpl->mEventData->mDecorator && mImpl->mEventData->mDecorator->IsSmoothHandlePanEnabled();
 }
 
 void Controller::SetMaximumNumberOfCharacters(Length maxCharacters)
@@ -278,12 +273,11 @@ void Controller::SetEnableCursorBlink(bool enable)
 {
   DALI_ASSERT_DEBUG(NULL != mImpl->mEventData && "TextInput disabled");
 
-  if(NULL != mImpl->mEventData)
+  if(mImpl->mEventData)
   {
     mImpl->mEventData->mCursorBlinkEnabled = enable;
 
-    if(!enable &&
-       mImpl->mEventData->mDecorator)
+    if(!enable && mImpl->mEventData->mDecorator)
     {
       mImpl->mEventData->mDecorator->StopCursorBlink();
     }
@@ -292,12 +286,7 @@ void Controller::SetEnableCursorBlink(bool enable)
 
 bool Controller::GetEnableCursorBlink() const
 {
-  if(NULL != mImpl->mEventData)
-  {
-    return mImpl->mEventData->mCursorBlinkEnabled;
-  }
-
-  return false;
+  return mImpl->mEventData && mImpl->mEventData->mCursorBlinkEnabled;
 }
 
 void Controller::SetMultiLineEnabled(bool enable)
@@ -367,9 +356,7 @@ void Controller::SetVerticalAlignment(VerticalAlignment::Type alignment)
   {
     // Set the alignment.
     mImpl->mModel->mVerticalAlignment = alignment;
-
     mImpl->mOperationsPending = static_cast<OperationsMask>(mImpl->mOperationsPending | ALIGN);
-
     mImpl->RequestRelayout();
   }
 }
@@ -484,19 +471,7 @@ bool Controller::IsTextFitEnabled() const
 
 void Controller::SetTextFitMinSize(float minSize, FontSizeType type)
 {
-  switch(type)
-  {
-    case POINT_SIZE:
-    {
-      mImpl->mTextFitMinSize = minSize;
-      break;
-    }
-    case PIXEL_SIZE:
-    {
-      mImpl->mTextFitMinSize = ConvertPixelToPint(minSize);
-      break;
-    }
-  }
+  mImpl->mTextFitMinSize = (type == POINT_SIZE) ? minSize : ConvertPixelToPoint(minSize);
 }
 
 float Controller::GetTextFitMinSize() const
@@ -506,19 +481,7 @@ float Controller::GetTextFitMinSize() const
 
 void Controller::SetTextFitMaxSize(float maxSize, FontSizeType type)
 {
-  switch(type)
-  {
-    case POINT_SIZE:
-    {
-      mImpl->mTextFitMaxSize = maxSize;
-      break;
-    }
-    case PIXEL_SIZE:
-    {
-      mImpl->mTextFitMaxSize = ConvertPixelToPint(maxSize);
-      break;
-    }
-  }
+  mImpl->mTextFitMaxSize = (type == POINT_SIZE) ? maxSize : ConvertPixelToPoint(maxSize);
 }
 
 float Controller::GetTextFitMaxSize() const
@@ -528,19 +491,7 @@ float Controller::GetTextFitMaxSize() const
 
 void Controller::SetTextFitStepSize(float step, FontSizeType type)
 {
-  switch(type)
-  {
-    case POINT_SIZE:
-    {
-      mImpl->mTextFitStepSize = step;
-      break;
-    }
-    case PIXEL_SIZE:
-    {
-      mImpl->mTextFitStepSize = ConvertPixelToPint(step);
-      break;
-    }
-  }
+  mImpl->mTextFitStepSize = (type == POINT_SIZE) ? step : ConvertPixelToPoint(step);
 }
 
 float Controller::GetTextFitStepSize() const
@@ -608,8 +559,6 @@ bool Controller::IsGrabHandlePopupEnabled() const
   return mImpl->mEventData->mGrabHandlePopupEnabled;
 }
 
-// public : Update
-
 void Controller::SetText(const std::string& text)
 {
   TextUpdater::SetText(*this, text);
@@ -678,28 +627,16 @@ void Controller::SendSelectionToClipboard(bool deleteAfterSending)
   mImpl->SendSelectionToClipboard(deleteAfterSending);
 }
 
-// public : Default style & Input style
-
 void Controller::SetDefaultFontFamily(const std::string& defaultFontFamily)
 {
-  if(NULL == mImpl->mFontDefaults)
-  {
-    mImpl->mFontDefaults = new FontDefaults();
-  }
+  EnsureCreated(mImpl->mFontDefaults);
 
   mImpl->mFontDefaults->mFontDescription.family = defaultFontFamily;
   DALI_LOG_INFO(gLogFilter, Debug::General, "Controller::SetDefaultFontFamily %s\n", defaultFontFamily.c_str());
   mImpl->mFontDefaults->familyDefined = !defaultFontFamily.empty();
 
-  if(mImpl->mEventData)
-  {
-    // Update the cursor position if it's in editing mode
-    if(EventData::IsEditingState(mImpl->mEventData->mState))
-    {
-      mImpl->mEventData->mDecoratorUpdated     = true;
-      mImpl->mEventData->mUpdateCursorPosition = true; // Cursor position should be updated when the font family is updated.
-    }
-  }
+  // Update the cursor position if it's in editing mode
+  UpdateCursorPosition(mImpl->mEventData);
 
   // Clear the font-specific data
   ClearFontData();
@@ -709,12 +646,7 @@ void Controller::SetDefaultFontFamily(const std::string& defaultFontFamily)
 
 const std::string& Controller::GetDefaultFontFamily() const
 {
-  if(NULL != mImpl->mFontDefaults)
-  {
-    return mImpl->mFontDefaults->mFontDescription.family;
-  }
-
-  return EMPTY_STRING;
+  return mImpl->mFontDefaults ? mImpl->mFontDefaults->mFontDescription.family : EMPTY_STRING;
 }
 
 void Controller::SetPlaceholderFontFamily(const std::string& placeholderTextFontFamily)
@@ -729,23 +661,13 @@ const std::string& Controller::GetPlaceholderFontFamily() const
 
 void Controller::SetDefaultFontWeight(FontWeight weight)
 {
-  if(NULL == mImpl->mFontDefaults)
-  {
-    mImpl->mFontDefaults = new FontDefaults();
-  }
+  EnsureCreated(mImpl->mFontDefaults);
 
   mImpl->mFontDefaults->mFontDescription.weight = weight;
   mImpl->mFontDefaults->weightDefined           = true;
 
-  if(mImpl->mEventData)
-  {
-    // Update the cursor position if it's in editing mode
-    if(EventData::IsEditingState(mImpl->mEventData->mState))
-    {
-      mImpl->mEventData->mDecoratorUpdated     = true;
-      mImpl->mEventData->mUpdateCursorPosition = true; // Cursor position should be updated when the font weight is updated.
-    }
-  }
+  // Update the cursor position if it's in editing mode
+  UpdateCursorPosition(mImpl->mEventData);
 
   // Clear the font-specific data
   ClearFontData();
@@ -755,22 +677,12 @@ void Controller::SetDefaultFontWeight(FontWeight weight)
 
 bool Controller::IsDefaultFontWeightDefined() const
 {
-  if(NULL != mImpl->mFontDefaults)
-  {
-    return mImpl->mFontDefaults->weightDefined;
-  }
-
-  return false;
+  return mImpl->mFontDefaults && mImpl->mFontDefaults->weightDefined;
 }
 
 FontWeight Controller::GetDefaultFontWeight() const
 {
-  if(NULL != mImpl->mFontDefaults)
-  {
-    return mImpl->mFontDefaults->mFontDescription.weight;
-  }
-
-  return TextAbstraction::FontWeight::NORMAL;
+  return mImpl->mFontDefaults ? mImpl->mFontDefaults->mFontDescription.weight : TextAbstraction::FontWeight::NORMAL;
 }
 
 void Controller::SetPlaceholderTextFontWeight(FontWeight weight)
@@ -781,7 +693,6 @@ void Controller::SetPlaceholderTextFontWeight(FontWeight weight)
 bool Controller::IsPlaceholderTextFontWeightDefined() const
 {
   return PlaceholderHandler::IsPlaceholderTextFontWeightDefined(*this);
-  ;
 }
 
 FontWeight Controller::GetPlaceholderTextFontWeight() const
@@ -791,23 +702,13 @@ FontWeight Controller::GetPlaceholderTextFontWeight() const
 
 void Controller::SetDefaultFontWidth(FontWidth width)
 {
-  if(NULL == mImpl->mFontDefaults)
-  {
-    mImpl->mFontDefaults = new FontDefaults();
-  }
+  EnsureCreated(mImpl->mFontDefaults);
 
   mImpl->mFontDefaults->mFontDescription.width = width;
   mImpl->mFontDefaults->widthDefined           = true;
 
-  if(mImpl->mEventData)
-  {
-    // Update the cursor position if it's in editing mode
-    if(EventData::IsEditingState(mImpl->mEventData->mState))
-    {
-      mImpl->mEventData->mDecoratorUpdated     = true;
-      mImpl->mEventData->mUpdateCursorPosition = true; // Cursor position should be updated when the font width is updated.
-    }
-  }
+  // Update the cursor position if it's in editing mode
+  UpdateCursorPosition(mImpl->mEventData);
 
   // Clear the font-specific data
   ClearFontData();
@@ -817,22 +718,12 @@ void Controller::SetDefaultFontWidth(FontWidth width)
 
 bool Controller::IsDefaultFontWidthDefined() const
 {
-  if(NULL != mImpl->mFontDefaults)
-  {
-    return mImpl->mFontDefaults->widthDefined;
-  }
-
-  return false;
+  return mImpl->mFontDefaults && mImpl->mFontDefaults->widthDefined;
 }
 
 FontWidth Controller::GetDefaultFontWidth() const
 {
-  if(NULL != mImpl->mFontDefaults)
-  {
-    return mImpl->mFontDefaults->mFontDescription.width;
-  }
-
-  return TextAbstraction::FontWidth::NORMAL;
+  return mImpl->mFontDefaults ? mImpl->mFontDefaults->mFontDescription.width : TextAbstraction::FontWidth::NORMAL;
 }
 
 void Controller::SetPlaceholderTextFontWidth(FontWidth width)
@@ -852,23 +743,13 @@ FontWidth Controller::GetPlaceholderTextFontWidth() const
 
 void Controller::SetDefaultFontSlant(FontSlant slant)
 {
-  if(NULL == mImpl->mFontDefaults)
-  {
-    mImpl->mFontDefaults = new FontDefaults();
-  }
+  EnsureCreated(mImpl->mFontDefaults);
 
   mImpl->mFontDefaults->mFontDescription.slant = slant;
   mImpl->mFontDefaults->slantDefined           = true;
 
-  if(mImpl->mEventData)
-  {
-    // Update the cursor position if it's in editing mode
-    if(EventData::IsEditingState(mImpl->mEventData->mState))
-    {
-      mImpl->mEventData->mDecoratorUpdated     = true;
-      mImpl->mEventData->mUpdateCursorPosition = true; // Cursor position should be updated when the font slant is updated.
-    }
-  }
+  // Update the cursor position if it's in editing mode
+  UpdateCursorPosition(mImpl->mEventData);
 
   // Clear the font-specific data
   ClearFontData();
@@ -878,21 +759,12 @@ void Controller::SetDefaultFontSlant(FontSlant slant)
 
 bool Controller::IsDefaultFontSlantDefined() const
 {
-  if(NULL != mImpl->mFontDefaults)
-  {
-    return mImpl->mFontDefaults->slantDefined;
-  }
-  return false;
+  return mImpl->mFontDefaults && mImpl->mFontDefaults->slantDefined;
 }
 
 FontSlant Controller::GetDefaultFontSlant() const
 {
-  if(NULL != mImpl->mFontDefaults)
-  {
-    return mImpl->mFontDefaults->mFontDescription.slant;
-  }
-
-  return TextAbstraction::FontSlant::NORMAL;
+  return mImpl->mFontDefaults ? mImpl->mFontDefaults->mFontDescription.slant : TextAbstraction::FontSlant::NORMAL;
 }
 
 void Controller::SetPlaceholderTextFontSlant(FontSlant slant)
@@ -914,15 +786,8 @@ void Controller::SetFontSizeScale(float scale)
 {
   mImpl->mFontSizeScale = scale;
 
-  if(mImpl->mEventData)
-  {
-    // Update the cursor position if it's in editing mode
-    if(EventData::IsEditingState(mImpl->mEventData->mState))
-    {
-      mImpl->mEventData->mDecoratorUpdated     = true;
-      mImpl->mEventData->mUpdateCursorPosition = true; // Cursor position should be updated when the font size is updated.
-    }
-  }
+  // Update the cursor position if it's in editing mode
+  UpdateCursorPosition(mImpl->mEventData);
 
   // Clear the font-specific data
   ClearFontData();
@@ -932,52 +797,18 @@ void Controller::SetFontSizeScale(float scale)
 
 float Controller::GetFontSizeScale() const
 {
-  if(nullptr != mImpl->mFontDefaults)
-  {
-    return mImpl->mFontSizeScale;
-  }
-
-  return 1.f;
+  return mImpl->mFontDefaults ? mImpl->mFontSizeScale : 1.0f;
 }
 
 void Controller::SetDefaultFontSize(float fontSize, FontSizeType type)
 {
-  if(NULL == mImpl->mFontDefaults)
-  {
-    mImpl->mFontDefaults = new FontDefaults();
-  }
+  EnsureCreated(mImpl->mFontDefaults);
 
-  switch(type)
-  {
-    case POINT_SIZE:
-    {
-      mImpl->mFontDefaults->mDefaultPointSize = fontSize;
-      mImpl->mFontDefaults->sizeDefined       = true;
-      break;
-    }
-    case PIXEL_SIZE:
-    {
-      // Point size = Pixel size * 72.f / DPI
-      unsigned int                horizontalDpi = 0u;
-      unsigned int                verticalDpi   = 0u;
-      TextAbstraction::FontClient fontClient    = TextAbstraction::FontClient::Get();
-      fontClient.GetDpi(horizontalDpi, verticalDpi);
-
-      mImpl->mFontDefaults->mDefaultPointSize = (fontSize * 72.f) / static_cast<float>(horizontalDpi);
-      mImpl->mFontDefaults->sizeDefined       = true;
-      break;
-    }
-  }
+  mImpl->mFontDefaults->mDefaultPointSize = (type == POINT_SIZE) ? fontSize : ConvertPixelToPoint(fontSize);
+  mImpl->mFontDefaults->sizeDefined       = true;
 
-  if(mImpl->mEventData)
-  {
-    // Update the cursor position if it's in editing mode
-    if(EventData::IsEditingState(mImpl->mEventData->mState))
-    {
-      mImpl->mEventData->mDecoratorUpdated     = true;
-      mImpl->mEventData->mUpdateCursorPosition = true; // Cursor position should be updated when the font size is updated.
-    }
-  }
+  // Update the cursor position if it's in editing mode
+  UpdateCursorPosition(mImpl->mEventData);
 
   // Clear the font-specific data
   ClearFontData();
@@ -987,32 +818,11 @@ void Controller::SetDefaultFontSize(float fontSize, FontSizeType type)
 
 float Controller::GetDefaultFontSize(FontSizeType type) const
 {
-  float value = 0.0f;
-  if(NULL != mImpl->mFontDefaults)
+  if(mImpl->mFontDefaults)
   {
-    switch(type)
-    {
-      case POINT_SIZE:
-      {
-        value = mImpl->mFontDefaults->mDefaultPointSize;
-        break;
-      }
-      case PIXEL_SIZE:
-      {
-        // Pixel size = Point size * DPI / 72.f
-        unsigned int                horizontalDpi = 0u;
-        unsigned int                verticalDpi   = 0u;
-        TextAbstraction::FontClient fontClient    = TextAbstraction::FontClient::Get();
-        fontClient.GetDpi(horizontalDpi, verticalDpi);
-
-        value = mImpl->mFontDefaults->mDefaultPointSize * static_cast<float>(horizontalDpi) / 72.f;
-        break;
-      }
-    }
-    return value;
+    return (type == POINT_SIZE) ? mImpl->mFontDefaults->mDefaultPointSize : ConvertPointToPixel(mImpl->mFontDefaults->mDefaultPointSize);
   }
-
-  return value;
+  return 0.0f;
 }
 
 void Controller::SetPlaceholderTextFontSize(float fontSize, FontSizeType type)
@@ -1032,11 +842,8 @@ void Controller::SetDefaultColor(const Vector4& color)
   if(!mImpl->IsShowingPlaceholderText())
   {
     mImpl->mModel->mVisualModel->SetTextColor(color);
-
     mImpl->mModel->mLogicalModel->mColorRuns.Clear();
-
     mImpl->mOperationsPending = static_cast<OperationsMask>(mImpl->mOperationsPending | COLOR);
-
     mImpl->RequestRelayout();
   }
 }
@@ -1059,7 +866,6 @@ const Vector4& Controller::GetPlaceholderTextColor() const
 void Controller::SetShadowOffset(const Vector2& shadowOffset)
 {
   mImpl->mModel->mVisualModel->SetShadowOffset(shadowOffset);
-
   mImpl->RequestRelayout();
 }
 
@@ -1071,7 +877,6 @@ const Vector2& Controller::GetShadowOffset() const
 void Controller::SetShadowColor(const Vector4& shadowColor)
 {
   mImpl->mModel->mVisualModel->SetShadowColor(shadowColor);
-
   mImpl->RequestRelayout();
 }
 
@@ -1085,7 +890,6 @@ void Controller::SetShadowBlurRadius(const float& shadowBlurRadius)
   if(fabsf(GetShadowBlurRadius() - shadowBlurRadius) > Math::MACHINE_EPSILON_1)
   {
     mImpl->mModel->mVisualModel->SetShadowBlurRadius(shadowBlurRadius);
-
     mImpl->RequestRelayout();
   }
 }
@@ -1098,7 +902,6 @@ const float& Controller::GetShadowBlurRadius() const
 void Controller::SetUnderlineColor(const Vector4& color)
 {
   mImpl->mModel->mVisualModel->SetUnderlineColor(color);
-
   mImpl->RequestRelayout();
 }
 
@@ -1110,7 +913,6 @@ const Vector4& Controller::GetUnderlineColor() const
 void Controller::SetUnderlineEnabled(bool enabled)
 {
   mImpl->mModel->mVisualModel->SetUnderlineEnabled(enabled);
-
   mImpl->RequestRelayout();
 }
 
@@ -1122,7 +924,6 @@ bool Controller::IsUnderlineEnabled() const
 void Controller::SetUnderlineHeight(float height)
 {
   mImpl->mModel->mVisualModel->SetUnderlineHeight(height);
-
   mImpl->RequestRelayout();
 }
 
@@ -1134,7 +935,6 @@ float Controller::GetUnderlineHeight() const
 void Controller::SetOutlineColor(const Vector4& color)
 {
   mImpl->mModel->mVisualModel->SetOutlineColor(color);
-
   mImpl->RequestRelayout();
 }
 
@@ -1146,7 +946,6 @@ const Vector4& Controller::GetOutlineColor() const
 void Controller::SetOutlineWidth(uint16_t width)
 {
   mImpl->mModel->mVisualModel->SetOutlineWidth(width);
-
   mImpl->RequestRelayout();
 }
 
@@ -1158,7 +957,6 @@ uint16_t Controller::GetOutlineWidth() const
 void Controller::SetBackgroundColor(const Vector4& color)
 {
   mImpl->mModel->mVisualModel->SetBackgroundColor(color);
-
   mImpl->RequestRelayout();
 }
 
@@ -1170,7 +968,6 @@ const Vector4& Controller::GetBackgroundColor() const
 void Controller::SetBackgroundEnabled(bool enabled)
 {
   mImpl->mModel->mVisualModel->SetBackgroundEnabled(enabled);
-
   mImpl->RequestRelayout();
 }
 
@@ -1181,42 +978,24 @@ bool Controller::IsBackgroundEnabled() const
 
 void Controller::SetDefaultEmbossProperties(const std::string& embossProperties)
 {
-  if(NULL == mImpl->mEmbossDefaults)
-  {
-    mImpl->mEmbossDefaults = new EmbossDefaults();
-  }
-
+  EnsureCreated(mImpl->mEmbossDefaults);
   mImpl->mEmbossDefaults->properties = embossProperties;
 }
 
 const std::string& Controller::GetDefaultEmbossProperties() const
 {
-  if(NULL != mImpl->mEmbossDefaults)
-  {
-    return mImpl->mEmbossDefaults->properties;
-  }
-
-  return EMPTY_STRING;
+  return mImpl->mEmbossDefaults ? mImpl->mEmbossDefaults->properties : EMPTY_STRING;
 }
 
 void Controller::SetDefaultOutlineProperties(const std::string& outlineProperties)
 {
-  if(NULL == mImpl->mOutlineDefaults)
-  {
-    mImpl->mOutlineDefaults = new OutlineDefaults();
-  }
-
+  EnsureCreated(mImpl->mOutlineDefaults);
   mImpl->mOutlineDefaults->properties = outlineProperties;
 }
 
 const std::string& Controller::GetDefaultOutlineProperties() const
 {
-  if(NULL != mImpl->mOutlineDefaults)
-  {
-    return mImpl->mOutlineDefaults->properties;
-  }
-
-  return EMPTY_STRING;
+  return mImpl->mOutlineDefaults ? mImpl->mOutlineDefaults->properties : EMPTY_STRING;
 }
 
 void Controller::RelayoutForNewLineSize()
@@ -1228,7 +1007,7 @@ void Controller::RelayoutForNewLineSize()
   mImpl->mOperationsPending                          = static_cast<OperationsMask>(mImpl->mOperationsPending | LAYOUT);
 
   //remove selection
-  if((mImpl->mEventData != nullptr) && (mImpl->mEventData->mState == EventData::SELECTING))
+  if(mImpl->mEventData && mImpl->mEventData->mState == EventData::SELECTING)
   {
     mImpl->ChangeState(EventData::EDITING);
   }
@@ -1274,7 +1053,7 @@ float Controller::GetDefaultLineSize() const
 
 void Controller::SetInputColor(const Vector4& color)
 {
-  if(NULL != mImpl->mEventData)
+  if(mImpl->mEventData)
   {
     mImpl->mEventData->mInputStyle.textColor      = color;
     mImpl->mEventData->mInputStyle.isDefaultColor = false;
@@ -1318,13 +1097,8 @@ void Controller::SetInputColor(const Vector4& color)
 
 const Vector4& Controller::GetInputColor() const
 {
-  if(NULL != mImpl->mEventData)
-  {
-    return mImpl->mEventData->mInputStyle.textColor;
-  }
-
-  // Return the default text's color if there is no EventData.
-  return mImpl->mTextColor;
+  // Return event text input color if we have it, otherwise just return the default text's color
+  return mImpl->mEventData ? mImpl->mEventData->mInputStyle.textColor : mImpl->mTextColor;
 }
 
 void Controller::SetInputFontFamily(const std::string& fontFamily)
@@ -1394,7 +1168,7 @@ float Controller::GetInputFontPointSize() const
 
 void Controller::SetInputLineSpacing(float lineSpacing)
 {
-  if(NULL != mImpl->mEventData)
+  if(mImpl->mEventData)
   {
     mImpl->mEventData->mInputStyle.lineSpacing          = lineSpacing;
     mImpl->mEventData->mInputStyle.isLineSpacingDefined = true;
@@ -1403,17 +1177,12 @@ void Controller::SetInputLineSpacing(float lineSpacing)
 
 float Controller::GetInputLineSpacing() const
 {
-  if(NULL != mImpl->mEventData)
-  {
-    return mImpl->mEventData->mInputStyle.lineSpacing;
-  }
-
-  return 0.f;
+  return mImpl->mEventData ? mImpl->mEventData->mInputStyle.lineSpacing : 0.0f;
 }
 
 void Controller::SetInputShadowProperties(const std::string& shadowProperties)
 {
-  if(NULL != mImpl->mEventData)
+  if(mImpl->mEventData)
   {
     mImpl->mEventData->mInputStyle.shadowProperties = shadowProperties;
   }
@@ -1421,17 +1190,12 @@ void Controller::SetInputShadowProperties(const std::string& shadowProperties)
 
 const std::string& Controller::GetInputShadowProperties() const
 {
-  if(NULL != mImpl->mEventData)
-  {
-    return mImpl->mEventData->mInputStyle.shadowProperties;
-  }
-
-  return EMPTY_STRING;
+  return mImpl->mEventData ? mImpl->mEventData->mInputStyle.shadowProperties : EMPTY_STRING;
 }
 
 void Controller::SetInputUnderlineProperties(const std::string& underlineProperties)
 {
-  if(NULL != mImpl->mEventData)
+  if(mImpl->mEventData)
   {
     mImpl->mEventData->mInputStyle.underlineProperties = underlineProperties;
   }
@@ -1439,17 +1203,12 @@ void Controller::SetInputUnderlineProperties(const std::string& underlinePropert
 
 const std::string& Controller::GetInputUnderlineProperties() const
 {
-  if(NULL != mImpl->mEventData)
-  {
-    return mImpl->mEventData->mInputStyle.underlineProperties;
-  }
-
-  return EMPTY_STRING;
+  return mImpl->mEventData ? mImpl->mEventData->mInputStyle.underlineProperties : EMPTY_STRING;
 }
 
 void Controller::SetInputEmbossProperties(const std::string& embossProperties)
 {
-  if(NULL != mImpl->mEventData)
+  if(mImpl->mEventData)
   {
     mImpl->mEventData->mInputStyle.embossProperties = embossProperties;
   }
@@ -1457,17 +1216,12 @@ void Controller::SetInputEmbossProperties(const std::string& embossProperties)
 
 const std::string& Controller::GetInputEmbossProperties() const
 {
-  if(NULL != mImpl->mEventData)
-  {
-    return mImpl->mEventData->mInputStyle.embossProperties;
-  }
-
-  return GetDefaultEmbossProperties();
+  return mImpl->mEventData ? mImpl->mEventData->mInputStyle.embossProperties : GetDefaultEmbossProperties();
 }
 
 void Controller::SetInputOutlineProperties(const std::string& outlineProperties)
 {
-  if(NULL != mImpl->mEventData)
+  if(mImpl->mEventData)
   {
     mImpl->mEventData->mInputStyle.outlineProperties = outlineProperties;
   }
@@ -1475,17 +1229,12 @@ void Controller::SetInputOutlineProperties(const std::string& outlineProperties)
 
 const std::string& Controller::GetInputOutlineProperties() const
 {
-  if(NULL != mImpl->mEventData)
-  {
-    return mImpl->mEventData->mInputStyle.outlineProperties;
-  }
-
-  return GetDefaultOutlineProperties();
+  return mImpl->mEventData ? mImpl->mEventData->mInputStyle.outlineProperties : GetDefaultOutlineProperties();
 }
 
 void Controller::SetInputModePassword(bool passwordInput)
 {
-  if(NULL != mImpl->mEventData)
+  if(mImpl->mEventData)
   {
     mImpl->mEventData->mPasswordInput = passwordInput;
   }
@@ -1493,16 +1242,12 @@ void Controller::SetInputModePassword(bool passwordInput)
 
 bool Controller::IsInputModePassword()
 {
-  if(NULL != mImpl->mEventData)
-  {
-    return mImpl->mEventData->mPasswordInput;
-  }
-  return false;
+  return mImpl->mEventData && mImpl->mEventData->mPasswordInput;
 }
 
 void Controller::SetNoTextDoubleTapAction(NoTextTap::Action action)
 {
-  if(NULL != mImpl->mEventData)
+  if(mImpl->mEventData)
   {
     mImpl->mEventData->mDoubleTapAction = action;
   }
@@ -1510,19 +1255,12 @@ void Controller::SetNoTextDoubleTapAction(NoTextTap::Action action)
 
 Controller::NoTextTap::Action Controller::GetNoTextDoubleTapAction() const
 {
-  NoTextTap::Action action = NoTextTap::NO_ACTION;
-
-  if(NULL != mImpl->mEventData)
-  {
-    action = mImpl->mEventData->mDoubleTapAction;
-  }
-
-  return action;
+  return mImpl->mEventData ? mImpl->mEventData->mDoubleTapAction : NoTextTap::NO_ACTION;
 }
 
 void Controller::SetNoTextLongPressAction(NoTextTap::Action action)
 {
-  if(NULL != mImpl->mEventData)
+  if(mImpl->mEventData)
   {
     mImpl->mEventData->mLongPressAction = action;
   }
@@ -1530,14 +1268,7 @@ void Controller::SetNoTextLongPressAction(NoTextTap::Action action)
 
 Controller::NoTextTap::Action Controller::GetNoTextLongPressAction() const
 {
-  NoTextTap::Action action = NoTextTap::NO_ACTION;
-
-  if(NULL != mImpl->mEventData)
-  {
-    action = mImpl->mEventData->mLongPressAction;
-  }
-
-  return action;
+  return mImpl->mEventData ? mImpl->mEventData->mLongPressAction : NoTextTap::NO_ACTION;
 }
 
 bool Controller::IsUnderlineSetByString()
@@ -1580,8 +1311,6 @@ void Controller::FontStyleSetByString(bool setByString)
   mImpl->mFontStyleSetByString = setByString;
 }
 
-// public : Queries & retrieves.
-
 Layout::Engine& Controller::GetLayoutEngine()
 {
   return mImpl->mLayoutEngine;
@@ -1615,8 +1344,7 @@ float Controller::GetHeightForWidth(float width)
 int Controller::GetLineCount(float width)
 {
   GetHeightForWidth(width);
-  int numberofLines = mImpl->mModel->GetNumberOfLines();
-  return numberofLines;
+  return mImpl->mModel->GetNumberOfLines();
 }
 
 const ModelInterface* const Controller::GetTextModel() const
@@ -1650,16 +1378,13 @@ bool Controller::GetTextScrollInfo(float& scrollPosition, float& controlHeight,
 
 void Controller::SetHiddenInputOption(const Property::Map& options)
 {
-  if(NULL == mImpl->mHiddenInput)
-  {
-    mImpl->mHiddenInput = new HiddenText(this);
-  }
+  EnsureCreated<HiddenText, Controller*>(mImpl->mHiddenInput, this);
   mImpl->mHiddenInput->SetProperties(options);
 }
 
 void Controller::GetHiddenInputOption(Property::Map& options)
 {
-  if(NULL != mImpl->mHiddenInput)
+  if(mImpl->mHiddenInput)
   {
     mImpl->mHiddenInput->GetProperties(options);
   }
@@ -1667,16 +1392,13 @@ void Controller::GetHiddenInputOption(Property::Map& options)
 
 void Controller::SetInputFilterOption(const Property::Map& options)
 {
-  if(!mImpl->mInputFilter)
-  {
-    mImpl->mInputFilter = std::unique_ptr<InputFilter>(new InputFilter());
-  }
+  EnsureCreated(mImpl->mInputFilter);
   mImpl->mInputFilter->SetProperties(options);
 }
 
 void Controller::GetInputFilterOption(Property::Map& options)
 {
-  if(NULL != mImpl->mInputFilter)
+  if(mImpl->mInputFilter)
   {
     mImpl->mInputFilter->GetProperties(options);
   }
@@ -1757,8 +1479,6 @@ void Controller::SetEllipsisPosition(Toolkit::DevelText::EllipsisPosition::Type
   mImpl->mModel->mVisualModel->SetEllipsisPosition(ellipsisPosition);
 }
 
-// public : Relayout.
-
 Controller::UpdateTextType Controller::Relayout(const Size& size, Dali::LayoutDirection::Type layoutDirection)
 {
   return Relayouter::Relayout(*this, size, layoutDirection);
@@ -1769,8 +1489,6 @@ void Controller::RequestRelayout()
   mImpl->RequestRelayout();
 }
 
-// public : Input style change signals.
-
 bool Controller::IsInputStyleChangedSignalsQueueEmpty()
 {
   return (NULL == mImpl->mEventData) || (0u == mImpl->mEventData->mInputStyleChangedQueue.Count());
@@ -1778,31 +1496,20 @@ bool Controller::IsInputStyleChangedSignalsQueueEmpty()
 
 void Controller::ProcessInputStyleChangedSignals()
 {
-  if(NULL == mImpl->mEventData)
-  {
-    // Nothing to do.
-    return;
-  }
-
-  for(Vector<InputStyle::Mask>::ConstIterator it    = mImpl->mEventData->mInputStyleChangedQueue.Begin(),
-                                              endIt = mImpl->mEventData->mInputStyleChangedQueue.End();
-      it != endIt;
-      ++it)
+  if(mImpl->mEventData)
   {
-    const InputStyle::Mask mask = *it;
-
-    if(NULL != mImpl->mEditableControlInterface)
+    if(mImpl->mEditableControlInterface)
     {
-      // Emit the input style changed signal.
-      mImpl->mEditableControlInterface->InputStyleChanged(mask);
+      // Emit the input style changed signal for each mask
+      std::for_each(mImpl->mEventData->mInputStyleChangedQueue.begin(),
+                    mImpl->mEventData->mInputStyleChangedQueue.end(),
+                    [&](const auto mask) { mImpl->mEditableControlInterface->InputStyleChanged(mask); } );
     }
-  }
 
-  mImpl->mEventData->mInputStyleChangedQueue.Clear();
+    mImpl->mEventData->mInputStyleChangedQueue.Clear();
+  }
 }
 
-// public : Text-input Event Queuing.
-
 void Controller::KeyboardFocusGainEvent()
 {
   EventHandler::KeyboardFocusGainEvent(*this);
@@ -1933,7 +1640,7 @@ string Controller::CutText()
 
   if(!IsEditable())
   {
-    return "";
+    return EMPTY_STRING;
   }
 
   mImpl->SendSelectionToClipboard(true); // Synchronous call to modify text
@@ -1976,8 +1683,6 @@ void Controller::PasteClipboardItemEvent()
   EventHandler::PasteClipboardItemEvent(*this);
 }
 
-// protected : Inherit from Text::Decorator::ControllerInterface.
-
 void Controller::GetTargetSize(Vector2& targetSize)
 {
   targetSize = mImpl->mModel->mVisualModel->mControlSize;
@@ -1985,7 +1690,7 @@ void Controller::GetTargetSize(Vector2& targetSize)
 
 void Controller::AddDecoration(Actor& actor, bool needsClipping)
 {
-  if(NULL != mImpl->mEditableControlInterface)
+  if(mImpl->mEditableControlInterface)
   {
     mImpl->mEditableControlInterface->AddDecoration(actor, needsClipping);
   }
@@ -2037,22 +1742,14 @@ void Controller::ScrollBy(Vector2 scroll)
 
 float Controller::GetHorizontalScrollPosition()
 {
-  if(mImpl->mEventData)
-  {
-    //scroll values are negative internally so we convert them to positive numbers
-    return -mImpl->mModel->mScrollPosition.x;
-  }
-  return 0;
+  // Scroll values are negative internally so we convert them to positive numbers
+  return mImpl->mEventData ? -mImpl->mModel->mScrollPosition.x : 0.0f;
 }
 
 float Controller::GetVerticalScrollPosition()
 {
-  if(mImpl->mEventData)
-  {
-    //scroll values are negative internally so we convert them to positive numbers
-    return -mImpl->mModel->mScrollPosition.y;
-  }
-  return 0;
+  // Scroll values are negative internally so we convert them to positive numbers
+  return mImpl->mEventData ? -mImpl->mModel->mScrollPosition.y : 0.0f;
 }
 
 void Controller::DecorationEvent(HandleType handleType, HandleState state, float x, float y)
@@ -2060,8 +1757,6 @@ void Controller::DecorationEvent(HandleType handleType, HandleState state, float
   EventHandler::DecorationEvent(*this, handleType, state, x, y);
 }
 
-// protected : Inherit from TextSelectionPopup::TextPopupButtonCallbackInterface.
-
 void Controller::TextPopupButtonTouched(Dali::Toolkit::TextSelectionPopup::Buttons button)
 {
   EventHandler::TextPopupButtonTouched(*this, button);
@@ -2076,8 +1771,6 @@ void Controller::DisplayTimeExpired()
   mImpl->RequestRelayout();
 }
 
-// private : Update.
-
 void Controller::InsertText(const std::string& text, Controller::InsertType type)
 {
   TextUpdater::InsertText(*this, text, type);
@@ -2088,9 +1781,7 @@ void Controller::PasteText(const std::string& stringToPaste)
   TextUpdater::PasteText(*this, stringToPaste);
 }
 
-bool Controller::RemoveText(int                  cursorOffset,
-                            int                  numberOfCharacters,
-                            UpdateInputStyleType type)
+bool Controller::RemoveText(int cursorOffset, int numberOfCharacters, UpdateInputStyleType type)
 {
   return TextUpdater::RemoveText(*this, cursorOffset, numberOfCharacters, type);
 }
@@ -2100,24 +1791,17 @@ bool Controller::RemoveSelectedText()
   return TextUpdater::RemoveSelectedText(*this);
 }
 
-void Controller::InsertTextAnchor(int            numberOfCharacters,
-                                  CharacterIndex previousCursorIndex)
+void Controller::InsertTextAnchor(int numberOfCharacters, CharacterIndex previousCursorIndex)
 {
   TextUpdater::InsertTextAnchor(*this, numberOfCharacters, previousCursorIndex);
 }
 
-void Controller::RemoveTextAnchor(int            cursorOffset,
-                                  int            numberOfCharacters,
-                                  CharacterIndex previousCursorIndex)
+void Controller::RemoveTextAnchor(int cursorOffset, int numberOfCharacters, CharacterIndex previousCursorIndex)
 {
   TextUpdater::RemoveTextAnchor(*this, cursorOffset, numberOfCharacters, previousCursorIndex);
 }
 
-// private : Relayout.
-
-bool Controller::DoRelayout(const Size&    size,
-                            OperationsMask operationsRequired,
-                            Size&          layoutSize)
+bool Controller::DoRelayout(const Size& size, OperationsMask operationsRequired, Size& layoutSize)
 {
   return Relayouter::DoRelayout(*this, size, operationsRequired, layoutSize);
 }
@@ -2127,8 +1811,6 @@ void Controller::CalculateVerticalOffset(const Size& controlSize)
   Relayouter::CalculateVerticalOffset(*this, controlSize);
 }
 
-// private : Events.
-
 void Controller::ProcessModifyEvents()
 {
   EventHandler::ProcessModifyEvents(*this);
@@ -2224,7 +1906,7 @@ CharacterIndex Controller::GetCursorPosition()
 
 void Controller::ResetScrollPosition()
 {
-  if(NULL != mImpl->mEventData)
+  if(mImpl->mEventData)
   {
     // Reset the scroll position.
     mImpl->mModel->mScrollPosition                = Vector2::ZERO;
@@ -2252,18 +1934,6 @@ Actor Controller::CreateBackgroundActor()
   return mImpl->CreateBackgroundActor();
 }
 
-// private : Private contructors & copy operator.
-
-Controller::Controller()
-: Controller(nullptr, nullptr, nullptr, nullptr)
-{
-}
-
-Controller::Controller(ControlInterface* controlInterface)
-: Controller(controlInterface, nullptr, nullptr, nullptr)
-{
-}
-
 Controller::Controller(ControlInterface*           controlInterface,
                        EditableControlInterface*   editableControlInterface,
                        SelectableControlInterface* selectableControlInterface,
@@ -2272,17 +1942,9 @@ Controller::Controller(ControlInterface*           controlInterface,
 {
 }
 
-// The copy constructor and operator are left unimplemented.
-
-// protected : Destructor.
-
 Controller::~Controller()
 {
   delete mImpl;
 }
 
-} // namespace Text
-
-} // namespace Toolkit
-
-} // namespace Dali
+} // namespace Dali::Toolkit::Text
index 9302cf5..3240384 100644 (file)
 #include <dali-toolkit/internal/text/text-selectable-control-interface.h>
 #include <dali-toolkit/public-api/text/text-enumerations.h>
 
-namespace Dali
-{
-namespace Toolkit
-{
-namespace Text
+namespace Dali::Toolkit::Text
 {
 class Controller;
 class ControlInterface;
@@ -170,7 +166,10 @@ public: // Constructor.
    *
    * @return A pointer to a new Controller.
    */
-  static ControllerPtr New();
+  static ControllerPtr New()
+  {
+    return ControllerPtr(new Controller());
+  }
 
   /**
    * @brief Create a new instance of a Controller.
@@ -179,7 +178,10 @@ public: // Constructor.
    *
    * @return A pointer to a new Controller.
    */
-  static ControllerPtr New(ControlInterface* controlInterface);
+  static ControllerPtr New(ControlInterface* controlInterface)
+  {
+    return ControllerPtr(new Controller(controlInterface));
+  }
 
   /**
    * @brief Create a new instance of a Controller.
@@ -194,7 +196,13 @@ public: // Constructor.
   static ControllerPtr New(ControlInterface*           controlInterface,
                            EditableControlInterface*   editableControlInterface,
                            SelectableControlInterface* selectableControlInterface,
-                           AnchorControlInterface*     anchorControlInterface);
+                           AnchorControlInterface*     anchorControlInterface)
+  {
+    return ControllerPtr(new Controller(controlInterface,
+                                        editableControlInterface,
+                                        selectableControlInterface,
+                                        anchorControlInterface));
+  }
 
 public: // Configure the text controller.
   /**
@@ -1897,12 +1905,18 @@ private: // Private contructors & copy operator.
   /**
    * @brief Private constructor.
    */
-  Controller();
+  Controller()
+  : Controller(nullptr, nullptr, nullptr, nullptr)
+  {
+  }
 
   /**
    * @brief Private constructor.
    */
-  Controller(ControlInterface* controlInterface);
+  Controller(ControlInterface* controlInterface)
+  : Controller(controlInterface, nullptr, nullptr, nullptr)
+  {
+  }
 
   /**
    * @brief Private constructor.
@@ -1912,11 +1926,8 @@ private: // Private contructors & copy operator.
              SelectableControlInterface* selectableControlInterface,
              AnchorControlInterface*     anchorControlInterface);
 
-  // Undefined
-  Controller(const Controller& handle);
-
-  // Undefined
-  Controller& operator=(const Controller& handle);
+  Controller(const Controller& handle) = delete;
+  Controller& operator=(const Controller& handle) = delete;
 
 protected: // Destructor.
   /**
@@ -1937,10 +1948,6 @@ private:
   Impl* mImpl;
 };
 
-} // namespace Text
-
-} // namespace Toolkit
-
-} // namespace Dali
+} // namespace Dali::Toolkit::Text
 
 #endif // DALI_TOOLKIT_TEXT_CONTROLLER_H
index 2cbd14d..78ba8db 100644 (file)
@@ -27,6 +27,7 @@
 
 // INTERNAL INCLUDES
 #include <dali-toolkit/devel-api/controls/control-devel.h>
+#include <dali-toolkit/internal/controls/control/control-data-impl.h>
 
 namespace Dali
 {
@@ -37,10 +38,9 @@ namespace Internal
 namespace
 {
 const Dali::AlphaFunction DEFAULT_ALPHA_FUNCTION(Dali::AlphaFunction::DEFAULT);
-
 } // anonymous namespace
 
-TransitionPtr Transition::New(Dali::Toolkit::Control source, Dali::Toolkit::Control destination, TimePeriod timePeriod)
+TransitionPtr Transition::New(Dali::Toolkit::Control source, Dali::Toolkit::Control destination, bool useDestinationTarget, TimePeriod timePeriod)
 {
   float delaySeconds = timePeriod.delaySeconds;
   if(delaySeconds < 0.0f)
@@ -56,7 +56,7 @@ TransitionPtr Transition::New(Dali::Toolkit::Control source, Dali::Toolkit::Cont
     durationSeconds = 0.0f;
   }
 
-  TransitionPtr transition = new Transition(source, destination, TimePeriod(delaySeconds, durationSeconds));
+  TransitionPtr transition = new Transition(source, destination, useDestinationTarget, TimePeriod(delaySeconds, durationSeconds));
 
   // Second-phase construction
   transition->Initialize();
@@ -64,12 +64,14 @@ TransitionPtr Transition::New(Dali::Toolkit::Control source, Dali::Toolkit::Cont
   return transition;
 }
 
-Transition::Transition(Dali::Toolkit::Control source, Dali::Toolkit::Control destination, TimePeriod timePeriod)
+Transition::Transition(Dali::Toolkit::Control source, Dali::Toolkit::Control destination, bool useDestinationTarget, TimePeriod timePeriod)
 : TransitionBase(),
+  mUseDestinationTarget(useDestinationTarget),
+  mOriginalSize(),
   mSourceControl(source),
   mDestinationControl(destination)
 {
-  SetTarget(destination);
+  SetTarget(mUseDestinationTarget ? destination : source);
   SetTimePeriod(timePeriod);
   SetPairTransition(true);
 }
@@ -90,16 +92,15 @@ void Transition::OnPlay()
   }
 
   //Make startPropertyMap and finishPropertyMap to use for property animation.
-  Matrix     sourceWorldTransform = sourceControl[Dali::Actor::Property::WORLD_MATRIX];
+  Matrix     sourceWorldTransform = GetWorldTransform(sourceControl);
   Vector3    sourcePosition, sourceScale;
   Quaternion sourceOrientation;
   sourceWorldTransform.GetTransformComponents(sourcePosition, sourceOrientation, sourceScale);
 
-  Vector3    destinationPosition    = destinationControl[Dali::Actor::Property::POSITION];
-  Vector3    destinationScale       = destinationControl[Dali::Actor::Property::SCALE];
-  Quaternion destinationOrientation = destinationControl[Dali::Actor::Property::ORIENTATION];
-  Vector4    targetColor            = destinationControl[Dali::Actor::Property::COLOR];
-  Vector3    targetSize             = destinationControl[Dali::Actor::Property::SIZE];
+  Matrix     destinationWorldTransform = GetWorldTransform(destinationControl);
+  Vector3    destinationPosition, destinationScale;
+  Quaternion destinationOrientation;
+  destinationWorldTransform.GetTransformComponents(destinationPosition, destinationOrientation, destinationScale);
 
   Property::Map startPropertyMap;
   Property::Map finishPropertyMap;
@@ -114,29 +115,36 @@ void Transition::OnPlay()
   startPropertyMap.Insert(Dali::Actor::Property::SCALE, sourceScale);
   finishPropertyMap.Insert(Dali::Actor::Property::SCALE, destinationScale);
 
-  Vector4 sourceColor = sourceControl.GetCurrentProperty<Vector4>(Dali::Actor::Property::WORLD_COLOR);
+  Vector4 sourceColor      = GetWorldColor(sourceControl);
+  Vector4 destinationColor = GetWorldColor(destinationControl);
   startPropertyMap.Insert(Dali::Actor::Property::COLOR, sourceColor);
-  finishPropertyMap.Insert(Dali::Actor::Property::COLOR, targetColor);
+  finishPropertyMap.Insert(Dali::Actor::Property::COLOR, destinationColor);
 
   // Set animation for other properties if source and destination is different.
-  Vector3 sourceSize = sourceControl.GetCurrentProperty<Vector3>(Dali::Actor::Property::SIZE);
-  if(sourceSize != targetSize)
+  Vector3 sourceSize      = sourceControl[Dali::Actor::Property::SIZE];
+  Vector3 destinationSize = destinationControl[Dali::Actor::Property::SIZE];
+  if(sourceSize != destinationSize)
   {
     startPropertyMap.Insert(Dali::Actor::Property::SIZE, sourceSize);
-    finishPropertyMap.Insert(Dali::Actor::Property::SIZE, targetSize);
+    finishPropertyMap.Insert(Dali::Actor::Property::SIZE, destinationSize);
+    if(!mUseDestinationTarget)
+    {
+      mOriginalSize = GetTargetControl().GetProperty<Vector3>(Dali::Actor::Property::SIZE);
+    }
   }
 
   SetStartPropertyMap(startPropertyMap);
   SetFinishPropertyMap(finishPropertyMap);
 
   // source View becomes transparent during transition.
+  Dali::Toolkit::Control waitingControl = GetWaitingControl();
   if(IsTransitionWithChild())
   {
-    sourceControl[Dali::Actor::Property::VISIBLE] = false;
+    waitingControl[Dali::Actor::Property::VISIBLE] = false;
   }
   else
   {
-    GetImplementation(sourceControl).SetTransparent(true);
+    GetImplementation(waitingControl).SetTransparent(true);
   }
 
   Dali::Animation animation = GetAnimation();
@@ -145,27 +153,82 @@ void Transition::OnPlay()
     DALI_LOG_ERROR("animation is still not initialized\n");
     return;
   }
-  Dali::Toolkit::DevelControl::CreateTransitions(destinationControl, animation, sourceControl, GetAlphaFunction(), GetTimePeriod());
+
+  mOriginalVisualProperties.clear();
+  std::vector<std::pair<Dali::Property::Index, Dali::Property::Map>> destinationVisualProperties;
+  Dali::Toolkit::Control                                             targetControl   = GetTargetControl();
+  Internal::Control&                                                 internalControl = Toolkit::Internal::GetImplementation(targetControl);
+  Internal::Control::Impl&                                           controlDataImpl = Toolkit::Internal::Control::Impl::Get(internalControl);
+  controlDataImpl.CreateTransitions(mOriginalVisualProperties, destinationVisualProperties, sourceControl, destinationControl);
+
+  for(uint32_t index = 0; index < mOriginalVisualProperties.size(); ++index)
+  {
+    Dali::Property::Map source      = mOriginalVisualProperties[index].second;
+    Dali::Property::Map destination = destinationVisualProperties[index].second;
+    for(size_t i = 0; i < source.Count(); ++i)
+    {
+      Dali::Property property = DevelControl::GetVisualProperty(targetControl, mOriginalVisualProperties[index].first, source.GetKeyAt(i));
+      if(GetTimePeriod().delaySeconds > 0.0f)
+      {
+        Dali::KeyFrames initialKeyframes = Dali::KeyFrames::New();
+        initialKeyframes.Add(0.0f, source.GetValue(i));
+        animation.AnimateBetween(property, initialKeyframes, TimePeriod(GetTimePeriod().delaySeconds));
+      }
+      Dali::KeyFrames keyframes = Dali::KeyFrames::New();
+      keyframes.Add(0.0f, source.GetValue(i));
+      keyframes.Add(1.0f, destination.GetValue(i));
+      animation.AnimateBetween(property, keyframes, GetAlphaFunction(), GetTimePeriod());
+    }
+  }
 }
 
 void Transition::OnFinished()
 {
-  Dali::Toolkit::Control sourceControl = mSourceControl.GetHandle();
-  if(!sourceControl)
+  Dali::Toolkit::Control waitingControl = GetWaitingControl();
+  if(!waitingControl)
   {
     return;
   }
 
+  if(!mUseDestinationTarget)
+  {
+    Dali::Toolkit::Control target         = GetTargetControl();
+    Dali::Animation        resetAnimation = Dali::Animation::New(0.0f);
+    if(mOriginalSize != target.GetProperty<Vector3>(Dali::Actor::Property::SIZE))
+    {
+      // Use Animation not to notify size change and not to change width and height resize policy.
+      resetAnimation.AnimateTo(Dali::Property(target, Dali::Actor::Property::SIZE), mOriginalSize);
+    }
+    resetAnimation.Play();
+
+    Dali::Toolkit::Control   targetControl   = GetTargetControl();
+    Internal::Control&       internalControl = Toolkit::Internal::GetImplementation(targetControl);
+    Internal::Control::Impl& controlDataImpl = Toolkit::Internal::Control::Impl::Get(internalControl);
+    controlDataImpl.UpdateVisualProperties(mOriginalVisualProperties);
+  }
+
   if(IsTransitionWithChild())
   {
-    sourceControl[Dali::Actor::Property::VISIBLE] = true;
+    waitingControl[Dali::Actor::Property::VISIBLE] = true;
   }
   else
   {
-    GetImplementation(sourceControl).SetTransparent(false);
+    GetImplementation(waitingControl).SetTransparent(false);
   }
 }
 
+Dali::Toolkit::Control Transition::GetTargetControl()
+{
+  Dali::Toolkit::Control target = mUseDestinationTarget ? mDestinationControl.GetHandle() : mSourceControl.GetHandle();
+  return target;
+}
+
+Dali::Toolkit::Control Transition::GetWaitingControl()
+{
+  Dali::Toolkit::Control waitingControl = mUseDestinationTarget ? mSourceControl.GetHandle() : mDestinationControl.GetHandle();
+  return waitingControl;
+}
+
 } // namespace Internal
 
 } // namespace Toolkit
index 6aa1374..7230e2b 100644 (file)
@@ -41,10 +41,11 @@ public:
    * @brief Create a new Transition object.
    * @param[in] source A source control of this transition.
    * @param[in] destination A destination control of this transition.
+   * @param[in] useDestinationTarget True if this transition uses destination control as target.
    * @param[in] timePeriod The timePeriod of the animation.
    * @return A smart-pointer to the newly allocated Transition.
    */
-  static TransitionPtr New(Dali::Toolkit::Control source, Dali::Toolkit::Control destination, TimePeriod timePeriod);
+  static TransitionPtr New(Dali::Toolkit::Control source, Dali::Toolkit::Control destination, bool useDestinationTarget, TimePeriod timePeriod);
 
 protected:
   /**
@@ -63,6 +64,7 @@ protected:
    */
   Transition(Dali::Toolkit::Control source,
              Dali::Toolkit::Control destination,
+             bool                   useDestinationTarget,
              TimePeriod             timePeriod);
 
   /**
@@ -78,8 +80,15 @@ private:
   Transition& operator=(const Transition& rhs);
 
 private:
-  WeakHandle<Dali::Toolkit::Control> mSourceControl;
-  WeakHandle<Dali::Toolkit::Control> mDestinationControl;
+  Dali::Toolkit::Control GetTargetControl();
+  Dali::Toolkit::Control GetWaitingControl();
+
+private:
+  bool                                                               mUseDestinationTarget;
+  Vector3                                                            mOriginalSize;
+  std::vector<std::pair<Dali::Property::Index, Dali::Property::Map>> mOriginalVisualProperties;
+  WeakHandle<Dali::Toolkit::Control>                                 mSourceControl;
+  WeakHandle<Dali::Toolkit::Control>                                 mDestinationControl;
 };
 
 } // namespace Internal
index da54e1e..d8d61d3 100644 (file)
@@ -187,9 +187,9 @@ AnimatedImageVisual::AnimatedImageVisual(VisualFactoryCache& factoryCache, Image
   mUrlIndex(0),
   mFrameCount(0),
   mImageSize(),
+  mActionStatus(DevelAnimatedImageVisual::Action::PLAY),
   mWrapModeU(WrapMode::DEFAULT),
   mWrapModeV(WrapMode::DEFAULT),
-  mActionStatus(DevelAnimatedImageVisual::Action::PLAY),
   mStopBehavior(DevelImageVisual::StopBehavior::CURRENT_FRAME),
   mStartFirstFrame(false),
   mIsJumpTo(false)
@@ -807,9 +807,14 @@ TextureSet AnimatedImageVisual::SetLoadingFailed()
   DALI_LOG_INFO(gAnimImgLogFilter, Debug::Concise, "ResourceReady(ResourceStatus::FAILED)\n");
   ResourceReady(Toolkit::Visual::ResourceStatus::FAILED);
 
-  TextureSet textureSet  = TextureSet::New();
-  Texture    brokenImage = mFactoryCache.GetBrokenVisualImage();
-  textureSet.SetTexture(0u, brokenImage);
+  Actor actor = mPlacementActor.GetHandle();
+  Vector2 imageSize = Vector2::ZERO;
+  if(actor)
+  {
+    imageSize = actor.GetProperty(Actor::Property::SIZE).Get<Vector2>();
+  }
+  mFactoryCache.UpdateBrokenImageRenderer(mImpl->mRenderer, imageSize);
+  TextureSet textureSet = mImpl->mRenderer.GetTextures();
 
   if(mFrameDelayTimer)
   {
index 347e9d3..1d21356 100644 (file)
@@ -275,9 +275,10 @@ private:
   uint32_t        mFrameCount; // Number of frames
   ImageDimensions mImageSize;
 
+  DevelAnimatedImageVisual::Action::Type mActionStatus;
+
   Dali::WrapMode::Type                   mWrapModeU : 3;
   Dali::WrapMode::Type                   mWrapModeV : 3;
-  DevelAnimatedImageVisual::Action::Type mActionStatus : 3;
   DevelImageVisual::StopBehavior::Type   mStopBehavior : 2;
   bool                                   mStartFirstFrame : 1;
   bool                                   mIsJumpTo : 1;
index 35d7456..26495bf 100644 (file)
@@ -25,6 +25,7 @@
 #include <dali/integration-api/debug.h>
 
 // INTERNAL INCLUDES
+#include <dali-toolkit/devel-api/visuals/visual-actions-devel.h>
 #include <dali-toolkit/devel-api/visuals/animated-vector-image-visual-signals-devel.h>
 #include <dali-toolkit/devel-api/visuals/image-visual-properties-devel.h>
 #include <dali-toolkit/internal/visuals/animated-vector-image/vector-animation-manager.h>
@@ -305,14 +306,10 @@ void AnimatedVectorImageVisual::DoSetOnScene(Actor& actor)
 
   if(mLoadFailed)
   {
-    TextureSet textureSet = TextureSet::New();
-    mImpl->mRenderer.SetTextures(textureSet);
-
-    Texture brokenImage = mFactoryCache.GetBrokenVisualImage();
-    textureSet.SetTexture(0u, brokenImage);
-
+    Vector2 imageSize = Vector2::ZERO;
+    imageSize = actor.GetProperty(Actor::Property::SIZE).Get<Vector2>();
+    mFactoryCache.UpdateBrokenImageRenderer(mImpl->mRenderer, imageSize);
     actor.AddRenderer(mImpl->mRenderer);
-
     ResourceReady(Toolkit::Visual::ResourceStatus::FAILED);
   }
   else
@@ -449,15 +446,6 @@ void AnimatedVectorImageVisual::OnDoAction(const Property::Index actionId, const
       }
       break;
     }
-    case DevelAnimatedVectorImageVisual::Action::UPDATE_PROPERTY:
-    {
-      const Property::Map* map = attributes.GetMap();
-      if(map)
-      {
-        DoSetProperties(*map);
-      }
-      break;
-    }
   }
 
   TriggerVectorRasterization();
index 91bdc42..86a37ab 100644 (file)
@@ -528,10 +528,11 @@ VectorAnimationTask::TimePoint VectorAnimationTask::CalculateNextFrameTime(bool
   // is casted to use the default duration.
   mNextFrameStartTime = std::chrono::time_point_cast<TimePoint::duration>(mNextFrameStartTime + std::chrono::microseconds(mFrameDurationMicroSeconds));
   auto current        = std::chrono::steady_clock::now();
+  mDroppedFrames      = 0;
+
   if(renderNow)
   {
     mNextFrameStartTime = current;
-    mDroppedFrames      = 0;
   }
   else if(mNextFrameStartTime < current)
   {
index 76328f4..a1c79e9 100644 (file)
@@ -22,7 +22,6 @@
 #include <dali/integration-api/debug.h>
 
 //INTERNAL INCLUDES
-#include <dali-toolkit/devel-api/visuals/arc-visual-actions-devel.h>
 #include <dali-toolkit/devel-api/visuals/visual-properties-devel.h>
 #include <dali-toolkit/internal/graphics/builtin-shader-extern-gen.h>
 #include <dali-toolkit/internal/visuals/visual-base-data-impl.h>
@@ -188,23 +187,6 @@ void ArcVisual::OnSetTransform()
   }
 }
 
-void ArcVisual::OnDoAction(const Property::Index actionId, const Property::Value& attributes)
-{
-  // Check if action is valid for this visual type and perform action if possible
-  switch(actionId)
-  {
-    case DevelArcVisual::Action::UPDATE_PROPERTY:
-    {
-      const Property::Map* map = attributes.GetMap();
-      if(map)
-      {
-        DoSetProperties(*map);
-      }
-      break;
-    }
-  }
-}
-
 void ArcVisual::OnInitialize()
 {
   Geometry geometry = mFactoryCache.GetGeometry(VisualFactoryCache::QUAD_GEOMETRY);
index 4746351..011b946 100644 (file)
@@ -107,11 +107,6 @@ protected:
    */
   void OnSetTransform() override;
 
-  /**
-   * @copydoc Visual::Base::OnDoAction
-   */
-  void OnDoAction(const Property::Index actionId, const Property::Value& attributes) override;
-
 private:
   // Undefined
   ArcVisual(const ArcVisual& arcVisual) = delete;
index 9863364..73b0931 100644 (file)
@@ -23,7 +23,6 @@
 #include <dali/integration-api/debug.h>
 
 //INTERNAL INCLUDES
-#include <dali-toolkit/devel-api/visuals/color-visual-actions-devel.h>
 #include <dali-toolkit/devel-api/visuals/color-visual-properties-devel.h>
 #include <dali-toolkit/internal/graphics/builtin-shader-extern-gen.h>
 #include <dali-toolkit/internal/visuals/visual-base-data-impl.h>
@@ -72,7 +71,7 @@ ColorVisual::ColorVisual(VisualFactoryCache& factoryCache)
 : Visual::Base(factoryCache, Visual::FittingMode::FILL, Toolkit::Visual::COLOR),
   mBlurRadius(0.0f),
   mBlurRadiusIndex(Property::INVALID_INDEX),
-  mNeedBlurRadius(false)
+  mAlwaysUsingBlurRadius(false)
 {
 }
 
@@ -161,23 +160,6 @@ void ColorVisual::OnSetTransform()
   }
 }
 
-void ColorVisual::OnDoAction(const Property::Index actionId, const Property::Value& attributes)
-{
-  // Check if action is valid for this visual type and perform action if possible
-  switch(actionId)
-  {
-    case DevelColorVisual::Action::UPDATE_PROPERTY:
-    {
-      const Property::Map* map = attributes.GetMap();
-      if(map)
-      {
-        DoSetProperties(*map);
-      }
-      break;
-    }
-  }
-}
-
 void ColorVisual::UpdateShader()
 {
   if(mImpl->mRenderer)
@@ -217,7 +199,7 @@ Shader ColorVisual::GenerateShader() const
 
   bool roundedCorner = IsRoundedCornerRequired();
   bool borderline    = IsBorderlineRequired();
-  bool blur          = !EqualsZero(mBlurRadius) || mNeedBlurRadius;
+  bool blur          = !EqualsZero(mBlurRadius) || mAlwaysUsingBlurRadius;
   int shaderTypeFlag = ColorVisualRequireFlag::DEFAULT;
 
   if(roundedCorner)
@@ -276,9 +258,10 @@ Dali::Property ColorVisual::OnGetPropertyObject(Dali::Property::Key key)
   {
     mBlurRadiusIndex = mImpl->mRenderer.RegisterProperty(DevelColorVisual::Property::BLUR_RADIUS, BLUR_RADIUS_NAME, mBlurRadius);
 
-    mImpl->mRenderer.SetProperty(Renderer::Property::BLEND_MODE, BlendMode::ON);
+    // Blur is animated now. we always have to use blur feature.
+    mAlwaysUsingBlurRadius = true;
 
-    mNeedBlurRadius = true;
+    mImpl->mRenderer.SetProperty(Renderer::Property::BLEND_MODE, BlendMode::ON);
 
     // Change shader
     UpdateShader();
index 1f2af5c..5edf2ba 100644 (file)
@@ -104,11 +104,6 @@ protected:
   void OnSetTransform() override;
 
   /**
-   * @copydoc Visual::Base::OnDoAction
-   */
-  void OnDoAction(const Property::Index actionId, const Property::Value& attributes) override;
-
-  /**
    * @copydoc Visual::Base::UpdateShader
    */
   void UpdateShader() override;
@@ -131,9 +126,9 @@ private:
   ColorVisual& operator=(const ColorVisual& colorRenderer);
 
 private:
-  float           mBlurRadius;      ///< The blur radius
-  Property::Index mBlurRadiusIndex; ///< The blur radius property index
-  bool            mNeedBlurRadius;  ///< Whether we need the blur radius in shader.
+  float           mBlurRadius;                ///< The blur radius
+  Property::Index mBlurRadiusIndex;           ///< The blur radius property index
+  bool            mAlwaysUsingBlurRadius : 1; ///< Whether we need the blur radius in shader always.
 };
 
 } // namespace Internal
index 0251a1d..7e404ca 100644 (file)
@@ -513,8 +513,14 @@ void ImageVisual::GetNaturalSize(Vector2& naturalSize)
       }
       else
       {
-        Texture brokenImage = mFactoryCache.GetBrokenVisualImage();
-
+        Actor actor = mPlacementActor.GetHandle();
+        Vector2 imageSize = Vector2::ZERO;
+        if(actor)
+        {
+          imageSize = actor.GetProperty(Actor::Property::SIZE).Get<Vector2>();
+        }
+        mFactoryCache.UpdateBrokenImageRenderer(mImpl->mRenderer, imageSize);
+        Texture brokenImage = mImpl->mRenderer.GetTextures().GetTexture(0);
         naturalSize.x = brokenImage.GetWidth();
         naturalSize.y = brokenImage.GetWidth();
       }
@@ -710,12 +716,12 @@ void ImageVisual::DoSetOnScene(Actor& actor)
   }
   else if(mLoadState == TextureManager::LoadState::LOAD_FAILED)
   {
-    Texture brokenImage = mFactoryCache.GetBrokenVisualImage();
-
-    mTextures = TextureSet::New();
-    mTextures.SetTexture(0u, brokenImage);
-    mImpl->mRenderer.SetTextures(mTextures);
-
+    Vector2 imageSize = Vector2::ZERO;
+    if(actor)
+    {
+      imageSize = actor.GetProperty(Actor::Property::SIZE).Get<Vector2>();
+    }
+    mFactoryCache.UpdateBrokenImageRenderer(mImpl->mRenderer, imageSize);
     actor.AddRenderer(mImpl->mRenderer);
     mPlacementActor.Reset();
 
@@ -860,26 +866,30 @@ void ImageVisual::UploadComplete(bool loadingSuccess, int32_t textureId, Texture
     EnablePreMultipliedAlpha(preMultiplied);
 
     Actor actor = mPlacementActor.GetHandle();
-    if(actor)
+    if(!loadingSuccess)
     {
-      actor.AddRenderer(mImpl->mRenderer);
-      // reset the weak handle so that the renderer only get added to actor once
-      mPlacementActor.Reset();
+      Vector2 imageSize = Vector2::ZERO;
+      if(actor)
+      {
+        imageSize = actor.GetProperty(Actor::Property::SIZE).Get<Vector2>();
+      }
+      mFactoryCache.UpdateBrokenImageRenderer(mImpl->mRenderer, imageSize);
+      textureSet = mImpl->mRenderer.GetTextures();
     }
-
-    if(!loadingSuccess)
+    else
     {
-      Texture brokenImage = mFactoryCache.GetBrokenVisualImage();
-
-      textureSet = TextureSet::New();
-      textureSet.SetTexture(0u, brokenImage);
+      Sampler sampler = Sampler::New();
+      sampler.SetWrapMode(mWrapModeU, mWrapModeV);
+      textureSet.SetSampler(0u, sampler);
       mImpl->mRenderer.SetTextures(textureSet);
     }
 
-    Sampler sampler = Sampler::New();
-    sampler.SetWrapMode(mWrapModeU, mWrapModeV);
-    textureSet.SetSampler(0u, sampler);
-    mImpl->mRenderer.SetTextures(textureSet);
+    if(actor)
+    {
+      actor.AddRenderer(mImpl->mRenderer);
+      // reset the weak handle so that the renderer only get added to actor once
+      mPlacementActor.Reset();
+    }
   }
 
   // Storing TextureSet needed when renderer staged.
index 5f8ddff..cb2850d 100644 (file)
@@ -104,7 +104,6 @@ std::size_t NPatchLoader::Load(TextureManager& textureManager, TextureUploadObse
             newData->AddObserver(textureObserver);
 
             mCache.PushBack(newData);
-
             return newData->GetId(); // valid ids start from 1u
           }
         }
@@ -133,7 +132,6 @@ std::size_t NPatchLoader::Load(TextureManager& textureManager, TextureUploadObse
     preMultiplyOnLoad = (preMultiplyOnLoading == TextureManager::MultiplyOnLoad::MULTIPLY_ON_LOAD) ? true : false;
     data->SetLoadedNPatchData(pixelBuffer, preMultiplyOnLoad);
   }
-
   return data->GetId();
 }
 
index d9c26aa..e87e244 100644 (file)
@@ -562,7 +562,14 @@ void NPatchVisual::ApplyTextureAndUniforms()
     DALI_LOG_ERROR("The N patch image '%s' is not a valid N patch image\n", mImageUrl.GetUrl().c_str());
     textureSet = TextureSet::New();
 
-    Texture croppedImage = mFactoryCache.GetBrokenVisualImage();
+    Actor actor = mPlacementActor.GetHandle();
+    Vector2 imageSize = Vector2::ZERO;
+    if(actor)
+    {
+      imageSize = actor.GetProperty(Actor::Property::SIZE).Get<Vector2>();
+    }
+    mFactoryCache.UpdateBrokenImageRenderer(mImpl->mRenderer, imageSize);
+    Texture croppedImage = mImpl->mRenderer.GetTextures().GetTexture(0);
     textureSet.SetTexture(0u, croppedImage);
     mImpl->mRenderer.RegisterProperty("uFixed[0]", Vector2::ZERO);
     mImpl->mRenderer.RegisterProperty("uFixed[1]", Vector2::ZERO);
index 67fd435..5d1fff1 100644 (file)
@@ -157,9 +157,9 @@ void SvgVisual::DoSetOnScene(Actor& actor)
 
   if(mLoadFailed)
   {
-    Texture brokenImage = mFactoryCache.GetBrokenVisualImage();
-    textureSet.SetTexture(0u, brokenImage);
-
+    Vector2 imageSize = Vector2::ZERO;
+    imageSize = actor.GetProperty(Actor::Property::SIZE).Get<Vector2>();
+    mFactoryCache.UpdateBrokenImageRenderer(mImpl->mRenderer, imageSize);
     actor.AddRenderer(mImpl->mRenderer);
 
     ResourceReady(Toolkit::Visual::ResourceStatus::FAILED);
@@ -327,11 +327,9 @@ void SvgVisual::ApplyRasterizedImage(VectorImageRenderer vectorRenderer, PixelDa
     Actor actor = mPlacementActor.GetHandle();
     if(actor)
     {
-      TextureSet textureSet = mImpl->mRenderer.GetTextures();
-
-      Texture brokenImage = mFactoryCache.GetBrokenVisualImage();
-      textureSet.SetTexture(0u, brokenImage);
-
+      Vector2 imageSize = Vector2::ZERO;
+      imageSize = actor.GetProperty(Actor::Property::SIZE).Get<Vector2>();
+      mFactoryCache.UpdateBrokenImageRenderer(mImpl->mRenderer, imageSize);
       actor.AddRenderer(mImpl->mRenderer);
     }
 
index 53b5246..8106899 100644 (file)
@@ -134,8 +134,8 @@ Internal::Visual::Base::Impl::Impl(FittingMode fittingMode, Toolkit::Visual::Typ
   mFlags(0),
   mResourceStatus(Toolkit::Visual::ResourceStatus::PREPARING),
   mType(type),
-  mNeedCornerRadius(false),
-  mNeedBorderline(false)
+  mAlwaysUsingBorderline(false),
+  mAlwaysUsingCornerRadius(false)
 {
 }
 
index 52e0d98..64ab52f 100644 (file)
@@ -134,12 +134,12 @@ struct Base::Impl
   Property::Index                 mBorderlineColorIndex;
   Property::Index                 mBorderlineOffsetIndex;
   Property::Index                 mCornerRadiusIndex;
-  FittingMode                     mFittingMode; //< How the contents should fit the view
+  FittingMode                     mFittingMode; ///< How the contents should fit the view
   int                             mFlags;
   Toolkit::Visual::ResourceStatus mResourceStatus;
   const Toolkit::Visual::Type     mType;
-  bool                            mNeedCornerRadius;
-  bool                            mNeedBorderline;
+  bool                            mAlwaysUsingBorderline : 1;   ///< Whether we need the borderline in shader always.
+  bool                            mAlwaysUsingCornerRadius : 1; ///< Whether we need the corner radius in shader always.
 };
 
 } // namespace Visual
index f518895..f0a7af4 100644 (file)
@@ -25,6 +25,7 @@
 #include <dali/integration-api/debug.h>
 
 //INTERNAL HEARDER
+#include <dali-toolkit/devel-api/visuals/visual-actions-devel.h>
 #include <dali-toolkit/devel-api/visuals/visual-properties-devel.h>
 #include <dali-toolkit/internal/helpers/property-helper.h>
 #include <dali-toolkit/internal/visuals/visual-base-data-impl.h>
@@ -294,6 +295,11 @@ void Visual::Base::SetProperties(const Property::Map& propertyMap)
         {
           mImpl->mBorderlineWidth = width;
         }
+
+        if(mImpl->mBorderlineWidthIndex != Property::INVALID_INDEX)
+        {
+          mImpl->mRenderer.SetProperty(mImpl->mBorderlineWidthIndex, mImpl->mBorderlineWidth);
+        }
         break;
       }
       case Toolkit::DevelVisual::Property::BORDERLINE_COLOR:
@@ -303,6 +309,11 @@ void Visual::Base::SetProperties(const Property::Map& propertyMap)
         {
           mImpl->mBorderlineColor = color;
         }
+
+        if(mImpl->mBorderlineColorIndex != Property::INVALID_INDEX)
+        {
+          mImpl->mRenderer.SetProperty(mImpl->mBorderlineColorIndex, mImpl->mBorderlineColor);
+        }
         break;
       }
       case Toolkit::DevelVisual::Property::BORDERLINE_OFFSET:
@@ -312,6 +323,11 @@ void Visual::Base::SetProperties(const Property::Map& propertyMap)
         {
           mImpl->mBorderlineOffset = offset;
         }
+
+        if(mImpl->mBorderlineOffsetIndex != Property::INVALID_INDEX)
+        {
+          mImpl->mRenderer.SetProperty(mImpl->mBorderlineOffsetIndex, mImpl->mBorderlineOffset);
+        }
         break;
       }
       case Toolkit::DevelVisual::Property::CORNER_RADIUS:
@@ -337,6 +353,11 @@ void Visual::Base::SetProperties(const Property::Map& propertyMap)
             mImpl->mCornerRadius = Vector4(radius, radius, radius, radius);
           }
         }
+
+        if(mImpl->mCornerRadiusIndex != Property::INVALID_INDEX)
+        {
+          mImpl->mRenderer.SetProperty(mImpl->mCornerRadiusIndex, mImpl->mCornerRadius);
+        }
         break;
       }
       case Toolkit::DevelVisual::Property::CORNER_RADIUS_POLICY:
@@ -423,6 +444,20 @@ void Visual::Base::GetNaturalSize(Vector2& naturalSize)
 void Visual::Base::DoAction(const Property::Index actionId, const Property::Value attributes)
 {
   OnDoAction(actionId, attributes);
+
+  // Check if action is valid for this visual type and perform action if possible
+  switch(actionId)
+  {
+    case DevelVisual::Action::UPDATE_PROPERTY:
+    {
+      const Property::Map* map = attributes.GetMap();
+      if(map)
+      {
+        SetProperties(*map);
+      }
+      break;
+    }
+  }
 }
 
 void Visual::Base::SetDepthIndex(int index)
@@ -583,7 +618,7 @@ bool Visual::Base::IsRoundedCornerRequired() const
       // Update values from Renderer
       mImpl->mCornerRadius = mImpl->mRenderer.GetProperty<Vector4>(mImpl->mCornerRadiusIndex);
     }
-    return !(mImpl->mCornerRadius == Vector4::ZERO) || mImpl->mNeedCornerRadius;
+    return !(mImpl->mCornerRadius == Vector4::ZERO) || mImpl->mAlwaysUsingCornerRadius;
   }
   return false;
 }
@@ -598,7 +633,7 @@ bool Visual::Base::IsBorderlineRequired() const
       // Update values from Renderer
       mImpl->mBorderlineWidth = mImpl->mRenderer.GetProperty<float>(mImpl->mBorderlineWidthIndex);
     }
-    return !EqualsZero(mImpl->mBorderlineWidth) || mImpl->mNeedBorderline;
+    return !EqualsZero(mImpl->mBorderlineWidth) || mImpl->mAlwaysUsingBorderline;
   }
   return false;
 }
@@ -968,7 +1003,9 @@ Dali::Property Visual::Base::GetPropertyObject(Dali::Property::Key key)
       mImpl->mBorderlineWidthIndex  = mImpl->mRenderer.RegisterProperty(DevelVisual::Property::BORDERLINE_WIDTH, BORDERLINE_WIDTH, mImpl->mBorderlineWidth);
       mImpl->mBorderlineColorIndex  = mImpl->mRenderer.RegisterProperty(DevelVisual::Property::BORDERLINE_COLOR, BORDERLINE_COLOR, mImpl->mBorderlineColor);
       mImpl->mBorderlineOffsetIndex = mImpl->mRenderer.RegisterProperty(DevelVisual::Property::BORDERLINE_OFFSET, BORDERLINE_OFFSET, mImpl->mBorderlineOffset);
-      mImpl->mNeedBorderline        = true;
+
+      // Borderline is animated now. we always have to use borderline feature.
+      mImpl->mAlwaysUsingBorderline = true;
 
       index = mImpl->mRenderer.GetPropertyIndex(key);
 
@@ -981,14 +1018,16 @@ Dali::Property Visual::Base::GetPropertyObject(Dali::Property::Key key)
       mImpl->mCornerRadiusIndex = mImpl->mRenderer.RegisterProperty(DevelVisual::Property::CORNER_RADIUS, CORNER_RADIUS, mImpl->mCornerRadius);
       mImpl->mRenderer.RegisterProperty(CORNER_RADIUS_POLICY, mImpl->mCornerRadiusPolicy);
 
-      if(!mImpl->mNeedBorderline)
+      // ConerRadius is animated now. we always have to use corner radius feature.
+      mImpl->mAlwaysUsingCornerRadius = true;
+
+      if(!IsBorderlineRequired())
       {
-        // If mNeedBorderline is true, BLEND_MODE is already BlendMode::ON_WITHOUT_CULL. So we don't overwrite it.
+        // If IsBorderlineRequired is true, BLEND_MODE is already BlendMode::ON_WITHOUT_CULL. So we don't overwrite it.
         mImpl->mRenderer.SetProperty(Renderer::Property::BLEND_MODE, BlendMode::ON);
       }
 
-      index                    = mImpl->mCornerRadiusIndex;
-      mImpl->mNeedCornerRadius = true;
+      index = mImpl->mCornerRadiusIndex;
 
       // Change shader
       UpdateShader();
index b4fde0a..febd285 100644 (file)
@@ -26,6 +26,8 @@
 #include <dali-toolkit/internal/visuals/color/color-visual.h>
 #include <dali-toolkit/internal/visuals/image-atlas-manager.h>
 #include <dali-toolkit/internal/visuals/svg/svg-visual.h>
+#include <dali-toolkit/internal/graphics/builtin-shader-extern-gen.h>
+#include <dali/integration-api/debug.h>
 
 namespace Dali
 {
@@ -33,11 +35,73 @@ namespace Toolkit
 {
 namespace Internal
 {
+namespace
+{
+
+/**
+ * @brief Creates the geometry formed from the vertices and indices
+ *
+ * @param[in]  vertices             The vertices to generate the geometry from
+ * @param[in]  indices              The indices to generate the geometry from
+ * @return The geometry formed from the vertices and indices
+ */
+Geometry GenerateGeometry(const Vector<Vector2>& vertices, const Vector<unsigned short>& indices)
+{
+  Property::Map vertexFormat;
+  vertexFormat["aPosition"] = Property::VECTOR2;
+  VertexBuffer vertexBuffer = VertexBuffer::New(vertexFormat);
+  if(vertices.Size() > 0)
+  {
+    vertexBuffer.SetData(&vertices[0], vertices.Size());
+  }
+
+  // Create the geometry object
+  Geometry geometry = Geometry::New();
+  geometry.AddVertexBuffer(vertexBuffer);
+  if(indices.Size() > 0)
+  {
+    geometry.SetIndexBuffer(&indices[0], indices.Size());
+  }
+
+  return geometry;
+}
+
+/**
+ * @brief Adds the indices to form a quad composed off two triangles where the indices are organised in a grid
+ *
+ * @param[out] indices     The indices to add to
+ * @param[in]  rowIdx      The row index to start the quad
+ * @param[in]  nextRowIdx  The index to the next row
+ */
+void AddQuadIndices(Vector<unsigned short>& indices, unsigned int rowIdx, unsigned int nextRowIdx)
+{
+  indices.PushBack(rowIdx);
+  indices.PushBack(nextRowIdx + 1);
+  indices.PushBack(rowIdx + 1);
+
+  indices.PushBack(rowIdx);
+  indices.PushBack(nextRowIdx);
+  indices.PushBack(nextRowIdx + 1);
+}
+
+/**
+ * @brief Adds the vertices to create for npatch
+ * @param[out] vertices The vertices to add to
+ * @param[in]  x        The x value of vector
+ * @param[in]  y        The y value of vector
+ */
+void AddVertex(Vector<Vector2>& vertices, unsigned int x, unsigned int y)
+{
+  vertices.PushBack(Vector2(x, y));
+}
+
+} //unnamed namespace
+
 VisualFactoryCache::VisualFactoryCache(bool preMultiplyOnLoad)
 : mSvgRasterizeThread(NULL),
   mVectorAnimationManager(),
-  mBrokenImageUrl(""),
-  mPreMultiplyOnLoad(preMultiplyOnLoad)
+  mPreMultiplyOnLoad(preMultiplyOnLoad),
+  mBrokenImageInfoContainer()
 {
 }
 
@@ -104,7 +168,10 @@ ImageAtlasManagerPtr VisualFactoryCache::GetAtlasManager()
   if(!mAtlasManager)
   {
     mAtlasManager = new ImageAtlasManager();
-    mAtlasManager->SetBrokenImage(mBrokenImageUrl);
+    if(!mBrokenImageInfoContainer.empty())
+    {
+      mAtlasManager->SetBrokenImage(mBrokenImageInfoContainer[0].url);
+    }
   }
 
   return mAtlasManager;
@@ -207,20 +274,22 @@ Geometry VisualFactoryCache::CreateGridGeometry(Uint16Pair gridSize)
   return geometry;
 }
 
-Texture VisualFactoryCache::GetBrokenVisualImage()
+Texture VisualFactoryCache::GetBrokenVisualImage(uint32_t brokenIndex)
 {
-  if(!mBrokenImageTexture && mBrokenImageUrl.size())
+  if(!(mBrokenImageInfoContainer[brokenIndex].texture))
   {
-    PixelData          data;
-    Devel::PixelBuffer pixelBuffer = LoadImageFromFile(mBrokenImageUrl);
+    PixelData          pixelData;
+    Devel::PixelBuffer pixelBuffer = LoadImageFromFile(mBrokenImageInfoContainer[brokenIndex].url);
     if(pixelBuffer)
     {
-      data                = Devel::PixelBuffer::Convert(pixelBuffer); // takes ownership of buffer
-      mBrokenImageTexture = Texture::New(Dali::TextureType::TEXTURE_2D, data.GetPixelFormat(), data.GetWidth(), data.GetHeight());
-      mBrokenImageTexture.Upload(data);
+      pixelData                = Devel::PixelBuffer::Convert(pixelBuffer); // takes ownership of buffer
+      mBrokenImageInfoContainer[brokenIndex].texture  = Texture::New(Dali::TextureType::TEXTURE_2D, pixelData.GetPixelFormat(), pixelData.GetWidth(), pixelData.GetHeight());
+      mBrokenImageInfoContainer[brokenIndex].texture.Upload(pixelData);
+      mBrokenImageInfoContainer[brokenIndex].width = pixelData.GetWidth();
+      mBrokenImageInfoContainer[brokenIndex].height = pixelData.GetHeight();
     }
   }
-  return mBrokenImageTexture;
+  return mBrokenImageInfoContainer[brokenIndex].texture;
 }
 
 void VisualFactoryCache::SetPreMultiplyOnLoad(bool preMultiply)
@@ -233,16 +302,274 @@ bool VisualFactoryCache::GetPreMultiplyOnLoad()
   return mPreMultiplyOnLoad;
 }
 
-void VisualFactoryCache::SetBrokenImageUrl(const std::string& brokenImageUrl)
+void VisualFactoryCache::SetBrokenImageUrl(const std::vector<std::string>& brokenImageUrlList)
 {
-  mBrokenImageUrl = brokenImageUrl;
+  mBrokenImageInfoContainer.clear();
+  mBrokenImageInfoContainer.assign(brokenImageUrlList.size(), BrokenImageInfo());
+  for(unsigned int i = 0; i < brokenImageUrlList.size(); i++)
+  {
+    mBrokenImageInfoContainer[i].url = brokenImageUrlList[i];
+  }
+}
 
-  if(!mAtlasManager)
+VisualUrl::Type VisualFactoryCache::GetBrokenImageVisualType(int index)
+{
+  return mBrokenImageInfoContainer[index].visualType;
+}
+
+Geometry VisualFactoryCache::CreateNPatchGeometry(Uint16Pair gridSize)
+{
+  uint16_t gridWidth  = gridSize.GetWidth();
+  uint16_t gridHeight = gridSize.GetHeight();
+
+  // Create vertices
+  Vector<Vector2> vertices;
+  vertices.Reserve((gridWidth + 1) * (gridHeight + 1));
+
+  for(int y = 0; y < gridHeight + 1; ++y)
   {
-    mAtlasManager = new ImageAtlasManager();
+    for(int x = 0; x < gridWidth + 1; ++x)
+    {
+      AddVertex(vertices, x, y);
+    }
+  }
+
+  // Create indices
+  Vector<unsigned short> indices;
+  indices.Reserve(gridWidth * gridHeight * 6);
+
+  unsigned int rowIdx     = 0;
+  unsigned int nextRowIdx = gridWidth + 1;
+  for(int y = 0; y < gridHeight; ++y, ++nextRowIdx, ++rowIdx)
+  {
+    for(int x = 0; x < gridWidth; ++x, ++nextRowIdx, ++rowIdx)
+    {
+      AddQuadIndices(indices, rowIdx, nextRowIdx);
+    }
+  }
+
+  return GenerateGeometry(vertices, indices);
+}
+
+Geometry VisualFactoryCache::GetNPatchGeometry(int index)
+{
+  Geometry          geometry;
+  const NPatchData* data;
+  if(mNPatchLoader.GetNPatchData(mBrokenImageInfoContainer[index].npatchId, data) && data->GetLoadingState() == NPatchData::LoadingState::LOAD_COMPLETE)
+  {
+    if(data->GetStretchPixelsX().Size() == 1 && data->GetStretchPixelsY().Size() == 1)
+    {
+      geometry = GetGeometry(VisualFactoryCache::NINE_PATCH_GEOMETRY);
+      if(!geometry)
+      {
+        geometry = CreateNPatchGeometry(Uint16Pair(3,3));
+        SaveGeometry(VisualFactoryCache::NINE_PATCH_GEOMETRY, geometry);
+      }
+    }
+    else if(data->GetStretchPixelsX().Size() > 0 || data->GetStretchPixelsY().Size() > 0)
+    {
+      Uint16Pair gridSize(2 * data->GetStretchPixelsX().Size() + 1, 2 * data->GetStretchPixelsY().Size() + 1);
+      geometry = CreateNPatchGeometry(gridSize);
+    }
+  }
+  else
+  {
+    // no N patch data so use default geometry
+    geometry = GetGeometry(VisualFactoryCache::NINE_PATCH_GEOMETRY);
+    if(!geometry)
+    {
+      geometry = CreateNPatchGeometry(Uint16Pair(3,3));
+      SaveGeometry(VisualFactoryCache::NINE_PATCH_GEOMETRY, geometry);
+    }
+  }
+  return geometry;
+}
+
+Shader VisualFactoryCache::GetNPatchShader(int index)
+{
+  Shader            shader;
+  const NPatchData* data;
+  // 0 is either no data (load failed?) or no stretch regions on image
+  // for both cases we use the default shader
+  NPatchUtility::StretchRanges::SizeType xStretchCount = 0;
+  NPatchUtility::StretchRanges::SizeType yStretchCount = 0;
+
+  // ask loader for the regions
+  if(mNPatchLoader.GetNPatchData(mBrokenImageInfoContainer[index].npatchId, data))
+  {
+    xStretchCount = data->GetStretchPixelsX().Count();
+    yStretchCount = data->GetStretchPixelsY().Count();
+  }
+
+  if(DALI_LIKELY((xStretchCount == 0 && yStretchCount == 0)))
+  {
+    shader = GetShader(VisualFactoryCache::NINE_PATCH_SHADER);
+    if(DALI_UNLIKELY(!shader))
+    {
+      shader = Shader::New(SHADER_NPATCH_VISUAL_3X3_SHADER_VERT, SHADER_NPATCH_VISUAL_SHADER_FRAG);
+
+      // Only cache vanilla 9 patch shaders
+      SaveShader(VisualFactoryCache::NINE_PATCH_SHADER, shader);
+    }
+  }
+  else if(xStretchCount > 0 || yStretchCount > 0)
+  {
+    std::stringstream vertexShader;
+    vertexShader << "#define FACTOR_SIZE_X " << xStretchCount + 2 << "\n"
+                 << "#define FACTOR_SIZE_Y " << yStretchCount + 2 << "\n"
+                 << SHADER_NPATCH_VISUAL_SHADER_VERT;
+    shader = Shader::New(vertexShader.str(), SHADER_NPATCH_VISUAL_SHADER_FRAG);
+  }
+  return shader;
+}
+
+void VisualFactoryCache::RegisterStretchProperties(Renderer& renderer, const char* uniformName, const NPatchUtility::StretchRanges& stretchPixels, uint16_t imageExtent)
+{
+  uint16_t     prevEnd     = 0;
+  uint16_t     prevFix     = 0;
+  uint16_t     prevStretch = 0;
+  unsigned int i           = 1;
+  for(NPatchUtility::StretchRanges::ConstIterator it = stretchPixels.Begin(); it != stretchPixels.End(); ++it, ++i)
+  {
+    uint16_t start = it->GetX();
+    uint16_t end   = it->GetY();
+
+    uint16_t fix     = prevFix + start - prevEnd;
+    uint16_t stretch = prevStretch + end - start;
+
+    std::stringstream uniform;
+    uniform << uniformName << "[" << i << "]";
+    renderer.RegisterProperty(uniform.str(), Vector2(fix, stretch));
+
+    prevEnd     = end;
+    prevFix     = fix;
+    prevStretch = stretch;
+  }
+
+  {
+    prevFix += imageExtent - prevEnd;
+    std::stringstream uniform;
+    uniform << uniformName << "[" << i << "]";
+    renderer.RegisterProperty(uniform.str(), Vector2(prevFix, prevStretch));
+  }
+}
+
+void VisualFactoryCache::ApplyTextureAndUniforms(Renderer& renderer, int index)
+{
+  const NPatchData* data;
+  TextureSet        textureSet;
+  if(mNPatchLoader.GetNPatchData(mBrokenImageInfoContainer[index].npatchId, data) && data->GetLoadingState() == NPatchData::LoadingState::LOAD_COMPLETE)
+  {
+    textureSet = data->GetTextures();
+    mBrokenImageInfoContainer[index].texture = data->GetTextures().GetTexture(0);
+
+    if(data->GetStretchPixelsX().Size() == 1 && data->GetStretchPixelsY().Size() == 1)
+    {
+      //special case for 9 patch
+      Uint16Pair stretchX = data->GetStretchPixelsX()[0];
+      Uint16Pair stretchY = data->GetStretchPixelsY()[0];
+
+      uint16_t stretchWidth  = (stretchX.GetY() >= stretchX.GetX()) ? stretchX.GetY() - stretchX.GetX() : 0;
+      uint16_t stretchHeight = (stretchY.GetY() >= stretchY.GetX()) ? stretchY.GetY() - stretchY.GetX() : 0;
+
+      renderer.RegisterProperty("uFixed[0]", Vector2::ZERO);
+      renderer.RegisterProperty("uFixed[1]", Vector2(stretchX.GetX(), stretchY.GetX()));
+      renderer.RegisterProperty("uFixed[2]", Vector2(data->GetCroppedWidth() - stretchWidth, data->GetCroppedHeight() - stretchHeight));
+      renderer.RegisterProperty("uStretchTotal", Vector2(stretchWidth, stretchHeight));
+    }
+    else
+    {
+      renderer.RegisterProperty("uNinePatchFactorsX[0]", Vector2::ZERO);
+      renderer.RegisterProperty("uNinePatchFactorsY[0]", Vector2::ZERO);
+
+      RegisterStretchProperties(renderer, "uNinePatchFactorsX", data->GetStretchPixelsX(), data->GetCroppedWidth());
+      RegisterStretchProperties(renderer, "uNinePatchFactorsY", data->GetStretchPixelsY(), data->GetCroppedHeight());
+    }
+    renderer.SetTextures(textureSet);
+  }
+}
+
+void VisualFactoryCache::UpdateBrokenImageRenderer(Renderer& renderer, const Vector2& size)
+{
+  // Load Information for broken image
+  for(uint32_t index = 0; index < mBrokenImageInfoContainer.size(); index++)
+  {
+    if(mBrokenImageInfoContainer[index].width == 0 && mBrokenImageInfoContainer[index].height == 0)
+    {
+      if(!mBrokenImageInfoContainer[index].url.empty())
+      {
+        VisualUrl visualUrl(mBrokenImageInfoContainer[index].url);
+        mBrokenImageInfoContainer[index].visualType = visualUrl.GetType();
+        if(mBrokenImageInfoContainer[index].visualType == VisualUrl::Type::N_PATCH)
+        {
+          const NPatchData* data;
+          Rect<int> border;
+          mBrokenImageInfoContainer[index].npatchId = mNPatchLoader.Load( mTextureManager, NULL, mBrokenImageInfoContainer[index].url, border, mPreMultiplyOnLoad, true);
+          if(mNPatchLoader.GetNPatchData(mBrokenImageInfoContainer[index].npatchId, data) && data->GetLoadingState() == NPatchData::LoadingState::LOAD_COMPLETE)
+          {
+            mBrokenImageInfoContainer[index].width = data->GetCroppedWidth();
+            mBrokenImageInfoContainer[index].height = data->GetCroppedHeight();
+          }
+          else
+          {
+            DALI_LOG_ERROR("Can't update renderer for broken image. maybe image loading is failed [path:%s] \n",mBrokenImageInfoContainer[index].url.c_str());
+          }
+        }
+        else
+        {
+          GetBrokenVisualImage(index);
+        }
+      }
+    }
+  }
+
+  // Set Texutre to renderer
+  int brokenIndex = GetProperBrokenImageIndex(size);
+  if(GetBrokenImageVisualType(brokenIndex) == VisualUrl::N_PATCH)
+  {
+    // Set geometry and shader for npatch
+    Geometry geometry = GetNPatchGeometry(brokenIndex);
+    Shader shader = GetNPatchShader(brokenIndex);
+    renderer.SetGeometry(geometry);
+    renderer.SetShader(shader);
+    ApplyTextureAndUniforms(renderer, brokenIndex);
+  }
+  else
+  {
+    Texture brokenImage = GetBrokenVisualImage(brokenIndex);
+    TextureSet textureSet = TextureSet::New();
+    textureSet.SetTexture(0u, brokenImage);
+    renderer.SetTextures(textureSet);
+  }
+}
+
+int32_t VisualFactoryCache::GetProperBrokenImageIndex(const Vector2& size)
+{
+  // Sets the default broken type
+  int32_t returnIndex = 0;
+  if((size.width == 0 || size.height == 0))
+  {
+    // To do : Need to add observer about size
+    return returnIndex;
+  }
+
+  // Find the proper value if we know the size of the image
+  for(int32_t index = static_cast<int32_t>(mBrokenImageInfoContainer.size()) - 1; index >= 0; index--)
+  {
+    // Skip if the value is not set
+    if(mBrokenImageInfoContainer[index].width == 0 || mBrokenImageInfoContainer[index].height == 0)
+    {
+      continue;
+    }
+
+    if(mBrokenImageInfoContainer[index].width < size.width && mBrokenImageInfoContainer[index].height < size.height)
+    {
+      returnIndex = index;
+      break;
+    }
   }
 
-  mAtlasManager->SetBrokenImage(mBrokenImageUrl);
+  return returnIndex;
 }
 
 } // namespace Internal
index 6e8f37d..b23c010 100644 (file)
@@ -28,6 +28,7 @@
 #include <dali-toolkit/internal/visuals/npatch-loader.h>
 #include <dali-toolkit/internal/visuals/svg/svg-rasterize-thread.h>
 #include <dali-toolkit/internal/visuals/texture-manager-impl.h>
+#include <dali/devel-api/rendering/renderer-devel.h>
 
 namespace Dali
 {
@@ -177,12 +178,6 @@ public:
   static Geometry CreateGridGeometry(Uint16Pair gridSize);
 
   /**
-   * @brief Returns a new Texture to use when a visual has failed to correctly render
-   * @return The broken image texture.
-   */
-  Texture GetBrokenVisualImage();
-
-  /**
    * @copydoc Toolkit::VisualFactory::SetPreMultiplyOnLoad()
    */
   void SetPreMultiplyOnLoad(bool preMultiply);
@@ -194,9 +189,16 @@ public:
 
   /**
    * @brief Set an image to be used when a visual has failed to correctly render
-   * @param[in] brokenImageUrl The broken image url.
+   * @param[in] brokenImageUrlList The broken image url list
    */
-  void SetBrokenImageUrl(const std::string& brokenImageUrl);
+  void SetBrokenImageUrl(const std::vector<std::string>& brokenImageUrlList);
+
+  /**
+   * @brief Update the broken image Renderer object
+   * @param[in,out] renderer renderer for broken image
+   * @param[in] size the size of actor
+   */
+  void UpdateBrokenImageRenderer(Renderer& renderer, const Vector2& size);
 
 public:
   /**
@@ -241,17 +243,108 @@ protected:
   VisualFactoryCache& operator=(const VisualFactoryCache& rhs);
 
 private:
+  /**
+   * @brief Returns a cached Texture to use when a visual has failed to correctly render
+   * @param[in] brokenIndex The index of broken image
+   *
+   * @return The broken image texture.
+   */
+  Texture GetBrokenVisualImage(uint32_t brokenIndex);
+
+  /**
+   * @brief Gets the Proper broken image index
+   * @param[in] size The size of actor
+   *
+   * @return The index of broken image
+   */
+  int32_t GetProperBrokenImageIndex(const Vector2& size);
+
+  /**
+   * @brief Apply a texture and uniforms
+   *
+   * @param[in,out] renderer The renderer for broken image
+   * @param[in] index The index of broken image
+   */
+  void ApplyTextureAndUniforms(Renderer& renderer, int index);
+
+  /**
+   * @brief Creates a Npatch Geometry object
+   *
+   * @param[in] gridSize The gridSize for creating a geometry
+   * @return The Geometry for NPatch
+   */
+  Geometry CreateNPatchGeometry(Uint16Pair gridSize);
+
+  /**
+   * @brief Gets a geometry for npatch image
+   *
+   * @param[in] index the index of broken image
+   * @return The Geometry for NPatch
+   */
+  Geometry GetNPatchGeometry(int index);
+
+  /**
+   * @brief Gets the Npatch Shader object
+   *
+   * @param[in] index The index of broken image
+   * @return The Shader for NPatch
+   */
+  Shader GetNPatchShader(int index);
+
+  /**
+   * @brief Registers a properties for Stretch Ranges
+   *
+   * @param[in,out] renderer The renderer for broken image
+   * @param[in] uniformName The name of the uniform
+   * @param[in] stretchPixels The stretchable pixels in the cropped image space
+   * @param[in] imageExtent The imageExtent
+   */
+  void RegisterStretchProperties(Renderer& renderer, const char* uniformName, const NPatchUtility::StretchRanges& stretchPixels, uint16_t imageExtent);
+
+  /**
+   * @brief Returns a broken image type
+   * @param[in] index BrokenImage index
+   * @return The broken image type.
+   */
+  VisualUrl::Type GetBrokenImageVisualType(int index);
+
+private:
+  struct BrokenImageInfo
+  {
+    BrokenImageInfo()
+    :visualType(),
+     url(""),
+     npatchId(NPatchData::INVALID_NPATCH_DATA_ID),
+     texture(),
+     width(0),
+     height(0)
+    {
+    }
+
+    ~BrokenImageInfo()
+    {
+    }
+
+    // Data
+    VisualUrl::Type                         visualType;
+    std::string                             url;
+    NPatchData::NPatchDataId                npatchId;
+    Texture                                 texture;
+    uint32_t                                width;
+    uint32_t                                height;
+  };
+
   Geometry mGeometry[GEOMETRY_TYPE_MAX + 1];
   Shader   mShader[SHADER_TYPE_MAX + 1];
 
   ImageAtlasManagerPtr                    mAtlasManager;
   TextureManager                          mTextureManager;
   NPatchLoader                            mNPatchLoader;
-  Texture                                 mBrokenImageTexture;
+
   SvgRasterizeThread*                     mSvgRasterizeThread;
   std::unique_ptr<VectorAnimationManager> mVectorAnimationManager;
-  std::string                             mBrokenImageUrl;
   bool                                    mPreMultiplyOnLoad;
+  std::vector<BrokenImageInfo>            mBrokenImageInfoContainer;
 };
 
 } // namespace Internal
index 8c4b2f8..112fdd3 100644 (file)
@@ -91,19 +91,15 @@ void VisualFactory::OnStyleChangedSignal(Toolkit::StyleManager styleManager, Sty
 {
   if(type == StyleChange::THEME_CHANGE)
   {
-    const std::string imageDirPath   = AssetManager::GetDaliImagePath();
-    std::string       brokenImageUrl = imageDirPath + BROKEN_IMAGE_FILE_NAME;
-
-    Property::Map config = Toolkit::DevelStyleManager::GetConfigurations(styleManager);
-    config["brokenImageUrl"].Get(brokenImageUrl);
-
-    if(mFactoryCache)
-    {
-      mFactoryCache->SetBrokenImageUrl(brokenImageUrl);
-    }
+    SetBrokenImageUrl(styleManager);
   }
 }
 
+void VisualFactory::OnBrokenImageChangedSignal(Toolkit::StyleManager styleManager)
+{
+  SetBrokenImageUrl(styleManager);
+}
+
 Toolkit::Visual::Base VisualFactory::CreateVisual(const Property::Map& propertyMap)
 {
   Visual::BasePtr visualPtr;
@@ -154,6 +150,7 @@ Toolkit::Visual::Base VisualFactory::CreateVisual(const Property::Map& propertyM
                 visualPtr = NPatchVisual::New(GetFactoryCache(), GetImageVisualShaderFactory(), visualUrl, propertyMap);
                 break;
               }
+              case VisualUrl::TVG:
               case VisualUrl::SVG:
               {
                 visualPtr = SvgVisual::New(GetFactoryCache(), GetImageVisualShaderFactory(), visualUrl, propertyMap);
@@ -318,6 +315,7 @@ Toolkit::Visual::Base VisualFactory::CreateVisual(const std::string& url, ImageD
         visualPtr = NPatchVisual::New(GetFactoryCache(), GetImageVisualShaderFactory(), visualUrl);
         break;
       }
+      case VisualUrl::TVG:
       case VisualUrl::SVG:
       {
         visualPtr = SvgVisual::New(GetFactoryCache(), GetImageVisualShaderFactory(), visualUrl);
@@ -370,24 +368,43 @@ Internal::TextureManager& VisualFactory::GetTextureManager()
   return GetFactoryCache().GetTextureManager();
 }
 
+void VisualFactory::SetBrokenImageUrl(Toolkit::StyleManager& styleManager)
+{
+  const std::string imageDirPath   = AssetManager::GetDaliImagePath();
+  std::string       brokenImageUrl = imageDirPath + BROKEN_IMAGE_FILE_NAME;
+  std::vector<std::string> customBrokenImageUrlList;
+
+  if(styleManager)
+  {
+    customBrokenImageUrlList = Toolkit::DevelStyleManager::GetBrokenImageUrlList(styleManager);
+    if(customBrokenImageUrlList.size() == 0)
+    {
+      Property::Map config = Toolkit::DevelStyleManager::GetConfigurations(styleManager);
+      config["brokenImageUrl"].Get(brokenImageUrl);
+      customBrokenImageUrlList.push_back(brokenImageUrl);
+    }
+    mFactoryCache->SetBrokenImageUrl(customBrokenImageUrlList);
+  }
+  else
+  {
+    // Set default image
+    customBrokenImageUrlList.push_back(brokenImageUrl);
+    mFactoryCache->SetBrokenImageUrl(customBrokenImageUrlList);
+  }
+}
+
 Internal::VisualFactoryCache& VisualFactory::GetFactoryCache()
 {
   if(!mFactoryCache)
   {
     mFactoryCache = std::unique_ptr<VisualFactoryCache>(new VisualFactoryCache(mPreMultiplyOnLoad));
-
-    const std::string imageDirPath   = AssetManager::GetDaliImagePath();
-    std::string       brokenImageUrl = imageDirPath + BROKEN_IMAGE_FILE_NAME;
-
     Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
     if(styleManager)
     {
-      Property::Map config = Toolkit::DevelStyleManager::GetConfigurations(styleManager);
-      config["brokenImageUrl"].Get(brokenImageUrl);
       styleManager.StyleChangedSignal().Connect(mSlotDelegate, &VisualFactory::OnStyleChangedSignal);
+      Toolkit::DevelStyleManager::BrokenImageChangedSignal(styleManager).Connect(mSlotDelegate, &VisualFactory::OnBrokenImageChangedSignal);
     }
-
-    mFactoryCache->SetBrokenImageUrl(brokenImageUrl);
+    SetBrokenImageUrl(styleManager);
   }
   return *mFactoryCache;
 }
index f038301..a5ecda8 100644 (file)
@@ -58,6 +58,13 @@ public:
   void OnStyleChangedSignal(Toolkit::StyleManager styleManager, StyleChange::Type type);
 
   /**
+   * @brief BrokenImageChanged callback
+   *
+   * @param[in] styleManager Handle for style manager.
+   */
+  void OnBrokenImageChangedSignal(Toolkit::StyleManager styleManager);
+
+  /**
    * @copydoc Toolkit::VisualFactory::CreateVisual( const Property::Map& )
    */
   Toolkit::Visual::Base CreateVisual(const Property::Map& propertyMap);
@@ -90,6 +97,12 @@ protected:
 
 private:
   /**
+   * @brief Set the Broken Image url
+   * @param[in] styleManager The instance of StyleManager
+   */
+  void SetBrokenImageUrl(Toolkit::StyleManager& styleManager);
+
+  /**
    * Get the factory cache, creating it if necessary.
    */
   Internal::VisualFactoryCache& GetFactoryCache();
index 30d9c02..0ad5778 100644 (file)
@@ -118,7 +118,9 @@ VisualUrl::Type ResolveType(const std::string& url)
     char         GIF[4]    = {'f', 'i', 'g', '.'};
     char         WEBP[5]   = {'p', 'b', 'e', 'w', '.'};
     char         JSON[5]   = {'n', 'o', 's', 'j', '.'};
+    char         TVG[4]    = {'g', 'v', 't', '.'};
     unsigned int svgScore  = 0;
+    unsigned int tvgScore  = 0;
     unsigned int gifScore  = 0;
     unsigned int webpScore = 0;
     unsigned int jsonScore = 0;
@@ -135,6 +137,14 @@ VisualUrl::Type ResolveType(const std::string& url)
           return VisualUrl::SVG;
         }
       }
+      if((offsetFromEnd < sizeof(TVG)) && (currentChar == TVG[offsetFromEnd]))
+      {
+        // early out if TVG as can't be used in N patch for now
+        if(++tvgScore == sizeof(TVG))
+        {
+          return VisualUrl::TVG;
+        }
+      }
       if((offsetFromEnd < sizeof(GIF)) && (currentChar == GIF[offsetFromEnd]))
       {
         // early out if GIF as can't be used in N patch for now
index 555e383..08a276a 100644 (file)
@@ -38,7 +38,8 @@ public:
     SVG,
     GIF,
     WEBP,
-    JSON
+    JSON,
+    TVG
   };
 
   enum ProtocolType
index 17db11b..64745d0 100644 (file)
@@ -37,7 +37,7 @@
 #include <dali-toolkit/devel-api/controls/control-depth-index-ranges.h>
 #include <dali-toolkit/devel-api/controls/control-devel.h>
 #include <dali-toolkit/devel-api/focus-manager/keyinput-focus-manager.h>
-#include <dali-toolkit/devel-api/visuals/color-visual-actions-devel.h>
+#include <dali-toolkit/devel-api/visuals/visual-actions-devel.h>
 #include <dali-toolkit/devel-api/visuals/color-visual-properties-devel.h>
 #include <dali-toolkit/internal/controls/control/control-data-impl.h>
 #include <dali-toolkit/internal/styling/style-manager-impl.h>
@@ -133,7 +133,7 @@ void Control::SetBackgroundColor(const Vector4& color)
   if(visual && visual.GetType() == Toolkit::Visual::COLOR)
   {
     // Update background color only
-    mImpl->DoAction(Toolkit::Control::Property::BACKGROUND, DevelColorVisual::Action::UPDATE_PROPERTY, map);
+    mImpl->DoAction(Toolkit::Control::Property::BACKGROUND, DevelVisual::Action::UPDATE_PROPERTY, map);
     return;
   }
 
@@ -702,6 +702,102 @@ void Control::SignalDisconnected(SlotObserver* slotObserver, CallbackBase* callb
   mImpl->SignalDisconnected(slotObserver, callback);
 }
 
+void Control::MakeVisualTransition(Dali::Property::Map& sourcePropertyMap, Dali::Property::Map& destinationPropertyMap,
+                                   Dali::Toolkit::Control source, Dali::Toolkit::Control destination, Dali::Property::Index visualIndex)
+{
+  sourcePropertyMap.Clear();
+  destinationPropertyMap.Clear();
+
+  Toolkit::Visual::Base sourceVisual      = DevelControl::GetVisual(GetImplementation(source), visualIndex);
+  Toolkit::Visual::Base destinationVisual = DevelControl::GetVisual(GetImplementation(destination), visualIndex);
+
+  // If source or destination doesn't have the visual, do not create transition for the visual.
+  if(!sourceVisual || !destinationVisual)
+  {
+    return;
+  }
+
+  Property::Map sourceMap;
+  Property::Map destinationMap;
+  sourceVisual.CreatePropertyMap(sourceMap);
+  destinationVisual.CreatePropertyMap(destinationMap);
+
+  static auto findValueVector4 = [](const Property::Map& map, Property::Index index, const Vector4& defaultValue = Vector4()) -> Vector4
+  {
+    Property::Value* propertyValue = map.Find(index);
+    if(propertyValue)
+    {
+      return propertyValue->Get<Vector4>();
+    }
+    return defaultValue;
+  };
+
+  static auto findValueFloat = [](const Property::Map& map, Property::Index index, const float& defaultValue = 0.0f) -> float
+  {
+    Property::Value* propertyValue = map.Find(index);
+    if(propertyValue)
+    {
+      return propertyValue->Get<float>();
+    }
+    return defaultValue;
+  };
+
+  Vector4 defaultMixColor(Color::TRANSPARENT);
+  Vector4 defaultCornerRadius(0.0f, 0.0f, 0.0f, 0.0f);
+  float   defaultBorderlineWidth(0.0f);
+  Vector4 defaultBorderlineColor(0.0f, 0.0f, 0.0f, 1.0f);
+  float   defaultBorderlineOffset(0.0f);
+
+  Vector4 sourceMixColor         = findValueVector4(sourceMap, Dali::Toolkit::Visual::Property::MIX_COLOR, defaultMixColor);
+  Vector4 sourceCornerRadius     = findValueVector4(sourceMap, Toolkit::DevelVisual::Property::CORNER_RADIUS, defaultCornerRadius);
+  float   sourceBorderlineWidth  = findValueFloat(sourceMap, Toolkit::DevelVisual::Property::BORDERLINE_WIDTH, defaultBorderlineWidth);
+  Vector4 sourceBorderlineColor  = findValueVector4(sourceMap, Toolkit::DevelVisual::Property::BORDERLINE_COLOR, defaultBorderlineColor);
+  float   sourceBorderlineOffset = findValueFloat(sourceMap, Toolkit::DevelVisual::Property::BORDERLINE_OFFSET, defaultBorderlineOffset);
+
+  Vector4 destinationMixColor         = findValueVector4(destinationMap, Dali::Toolkit::Visual::Property::MIX_COLOR, defaultMixColor);
+  Vector4 destinationCornerRadius     = findValueVector4(destinationMap, Toolkit::DevelVisual::Property::CORNER_RADIUS, defaultCornerRadius);
+  float   destinationBorderlineWidth  = findValueFloat(destinationMap, Toolkit::DevelVisual::Property::BORDERLINE_WIDTH, defaultBorderlineWidth);
+  Vector4 destinationBorderlineColor  = findValueVector4(destinationMap, Toolkit::DevelVisual::Property::BORDERLINE_COLOR, defaultBorderlineColor);
+  float   destinationBorderlineOffset = findValueFloat(destinationMap, Toolkit::DevelVisual::Property::BORDERLINE_OFFSET, defaultBorderlineOffset);
+
+  // If the value of the source Control and that of destination Control is different, the property should be transitioned.
+  if(Vector3(sourceMixColor) != Vector3(destinationMixColor))
+  {
+    sourcePropertyMap.Add(Dali::Toolkit::Visual::Property::MIX_COLOR, Vector3(sourceMixColor));
+    destinationPropertyMap.Add(Dali::Toolkit::Visual::Property::MIX_COLOR, Vector3(destinationMixColor));
+  }
+
+  if(std::abs(sourceMixColor.a - destinationMixColor.a) > Math::MACHINE_EPSILON_1)
+  {
+    sourcePropertyMap.Add(Dali::Toolkit::Visual::Property::OPACITY, sourceMixColor.a);
+    destinationPropertyMap.Add(Dali::Toolkit::Visual::Property::OPACITY, destinationMixColor.a);
+  }
+
+  if(sourceCornerRadius != destinationCornerRadius)
+  {
+    sourcePropertyMap.Add(Dali::Toolkit::DevelVisual::Property::CORNER_RADIUS, sourceCornerRadius);
+    destinationPropertyMap.Add(Dali::Toolkit::DevelVisual::Property::CORNER_RADIUS, destinationCornerRadius);
+  }
+
+  if(sourceBorderlineWidth != destinationBorderlineWidth)
+  {
+    sourcePropertyMap.Add(Dali::Toolkit::DevelVisual::Property::BORDERLINE_WIDTH, sourceBorderlineWidth);
+    destinationPropertyMap.Add(Dali::Toolkit::DevelVisual::Property::BORDERLINE_WIDTH, destinationBorderlineWidth);
+  }
+
+  if(sourceBorderlineColor != destinationBorderlineColor)
+  {
+    sourcePropertyMap.Add(Dali::Toolkit::DevelVisual::Property::BORDERLINE_COLOR, sourceBorderlineColor);
+    destinationPropertyMap.Add(Dali::Toolkit::DevelVisual::Property::BORDERLINE_COLOR, destinationBorderlineColor);
+  }
+
+  if(sourceBorderlineOffset != destinationBorderlineOffset)
+  {
+    sourcePropertyMap.Add(Dali::Toolkit::DevelVisual::Property::BORDERLINE_OFFSET, sourceBorderlineOffset);
+    destinationPropertyMap.Add(Dali::Toolkit::DevelVisual::Property::BORDERLINE_OFFSET, destinationBorderlineOffset);
+  }
+}
+
 Control& GetImplementation(Dali::Toolkit::Control& handle)
 {
   CustomActorImpl& customInterface = handle.GetImplementation();
index 9a68ca1..48c6b9c 100644 (file)
@@ -45,6 +45,7 @@ class StyleManager;
 
 namespace Internal
 {
+
 /**
  * @brief This is the internal base class for all controls.
  *
@@ -617,18 +618,47 @@ public: // API for derived classes to override
     return NULL;
   }
 
-  // Transition
+  // Transition APIs
+
+  /**
+   * @brief Make visual transition from source control to destination control about specific Visual.
+   * If both of source and destination control have same visual index, than generates information for the transition of this Control.
+   *
+   * @param[out] sourcePropertyMap Source property map to be applied on this Control.
+   * @param[out] destinationPropertyMap Destination property map to be applied on this Control.
+   * @param[in] source Source control of the animation.
+   * @param[in] destination Destination control of the animation.
+   * @param[in] visualIndex Property::Index to make animation.
+   */
+  void MakeVisualTransition(Dali::Property::Map& sourcePropertyMap, Dali::Property::Map& destinationPropertyMap,
+                            Dali::Toolkit::Control source, Dali::Toolkit::Control destination, Dali::Property::Index visualIndex);
 
   /**
-   * @brief Retrieve visual property animations.
-   * This Control is a destination.
+   * @brief Retrieves source and destination visual properties for the Transition of this Control.
+   * The properties of this Control will be transitioned from the propeties of source Control to that of destination control.
+   * If a property value is different between source and destination Control,
+   * the property information of each Control will be included in sourceProperties and destinationProperties.
+   *
+   * @param[out] sourceProperties Source property list to be applied on this Control.
+   * @param[out] destinationProperties Destination property list to be applied on this Control.
+   * @param[in] source Source control of the animation.
+   * @param[in] destination Destination control of the animation.
    *
-   * @param[in] animation generated animation
-   * @param[in] source source control of the animation.
-   * @param[in] alphaFunction AlphaFunction of the animation
-   * @param[in] timePeriod TimePeriod of the animation
+   * @note This method do not handle Actor properties.
+   * And the size and order of the sourceProperties and destinationProperties must be synchronized.
+   */
+  virtual void OnCreateTransitions(std::vector<std::pair<Dali::Property::Index, Dali::Property::Map>>& sourceProperties,
+                                   std::vector<std::pair<Dali::Property::Index, Dali::Property::Map>>& destinationProperties,
+                                   Dali::Toolkit::Control                                              source,
+                                   Dali::Toolkit::Control                                              destination)
+  {
+  }
+
+  /**
+   * @brief Update visual properties.
+   * @param[in] properties Property list to be used to update visual properties of this Control.
    */
-  virtual void OnCreateTransitions(Dali::Animation& animation, Dali::Toolkit::Control source, AlphaFunction alphaFunction, TimePeriod timePeriod)
+  virtual void OnUpdateVisualProperties(const std::vector<std::pair<Dali::Property::Index, Dali::Property::Map>>& properties)
   {
   }
 
index b5f6a8c..958d031 100644 (file)
@@ -51,9 +51,9 @@ GlView GlView::DownCast(BaseHandle handle)
   return Control::DownCast<GlView, Internal::GlView>(handle);
 }
 
-void GlView::RegisterGlCallback(CallbackBase* initCallback, CallbackBase* renderFrameCallback, CallbackBase* terminateCallback)
+void GlView::RegisterGlCallbacks(CallbackBase* initCallback, CallbackBase* renderFrameCallback, CallbackBase* terminateCallback)
 {
-  Dali::Toolkit::GetImpl(*this).RegisterGlCallback(initCallback, renderFrameCallback, terminateCallback);
+  Dali::Toolkit::GetImpl(*this).RegisterGlCallbacks(initCallback, renderFrameCallback, terminateCallback);
 }
 
 void GlView::SetResizeCallback(CallbackBase* resizeCallback)
index be13db9..57c3201 100644 (file)
@@ -165,7 +165,7 @@ public:
    * <b>You can't call Dali APIs in your callbacks because it is invoked in GlView's own render thread.</b>
    * And this must be called before adding GlView to the scene.
    */
-  void RegisterGlCallback(CallbackBase* initCallback, CallbackBase* renderFrameCallback, CallbackBase* terminateCallback);
+  void RegisterGlCallbacks(CallbackBase* initCallback, CallbackBase* renderFrameCallback, CallbackBase* terminateCallback);
 
   /**
    * @brief Sets the ResizeCallback of the GlView.
index 4129c6e..65c85c0 100644 (file)
@@ -29,7 +29,7 @@ namespace Toolkit
 {
 const unsigned int TOOLKIT_MAJOR_VERSION = 2;
 const unsigned int TOOLKIT_MINOR_VERSION = 0;
-const unsigned int TOOLKIT_MICRO_VERSION = 45;
+const unsigned int TOOLKIT_MICRO_VERSION = 50;
 const char* const  TOOLKIT_BUILD_DATE    = __DATE__ " " __TIME__;
 
 #ifdef DEBUG_ENABLED
index 3e2f378..57f7364 100644 (file)
@@ -32,9 +32,9 @@ Transition::Transition(Internal::Transition* transition)
 {
 }
 
-Transition Transition::New(Dali::Toolkit::Control source, Dali::Toolkit::Control destination, TimePeriod timePeriod)
+Transition Transition::New(Dali::Toolkit::Control source, Dali::Toolkit::Control destination, bool useDestinationTarget, TimePeriod timePeriod)
 {
-  Internal::TransitionPtr internal = Dali::Toolkit::Internal::Transition::New(source, destination, timePeriod);
+  Internal::TransitionPtr internal = Dali::Toolkit::Internal::Transition::New(source, destination, useDestinationTarget, timePeriod);
 
   return Transition(internal.Get());
 }
index 634face..fa27fa6 100644 (file)
@@ -51,13 +51,14 @@ public:
   /**
    * @brief Creates an initialized Transition.
    *
-   * @param[in] source Source
-   * @param[in] destination Destination
+   * @param[in] source A source control of this transition.
+   * @param[in] destination A destination control of this transition.
+   * @param[in] useDestinationTarget True if this transition uses destination control as target.
    * @param[in] timePeriod The duration in seconds
    * @return A handle to a newly allocated Dali resource
    * @note durationSeconds can not be negative.
    */
-  static Transition New(Dali::Toolkit::Control source, Dali::Toolkit::Control destination, TimePeriod timePeriod);
+  static Transition New(Dali::Toolkit::Control source, Dali::Toolkit::Control destination, bool useDestinationTarget, TimePeriod timePeriod);
 
   /**
    * @brief Downcasts a handle to Transition handle.
index bb31462..2b96025 100644 (file)
@@ -1,6 +1,6 @@
 Name:       dali2-toolkit
 Summary:    Dali 3D engine Toolkit
-Version:    2.0.45
+Version:    2.0.50
 Release:    1
 Group:      System/Libraries
 License:    Apache-2.0 and BSD-3-Clause and MIT