[dali_2.0.4] Merge branch 'devel/master' 56/249056/1
authorAdeel Kazmi <adeel.kazmi@samsung.com>
Fri, 4 Dec 2020 14:57:39 +0000 (14:57 +0000)
committerAdeel Kazmi <adeel.kazmi@samsung.com>
Fri, 4 Dec 2020 14:57:39 +0000 (14:57 +0000)
Change-Id: I75664e4050b6323f4bbd189bfedcdfe12bce408d

50 files changed:
.github/workflows/codeql-analysis.yml [new file with mode: 0644]
automated-tests/src/dali-internal/CMakeLists.txt
automated-tests/src/dali-internal/utc-Dali-Internal-ConstString.cpp [new file with mode: 0644]
automated-tests/src/dali/dali-test-suite-utils/dali-test-suite-utils.h
automated-tests/src/dali/utc-Dali-Actor.cpp
automated-tests/src/dali/utc-Dali-Renderer.cpp
automated-tests/src/dali/utc-Dali-TypeRegistry.cpp
dali/internal/common/blending-options.cpp
dali/internal/common/blending-options.h
dali/internal/common/const-string.cpp [new file with mode: 0644]
dali/internal/common/const-string.h [new file with mode: 0644]
dali/internal/event/actors/actor-declarations.h
dali/internal/event/actors/actor-impl.cpp
dali/internal/event/actors/actor-impl.h
dali/internal/event/actors/actor-relayouter.cpp
dali/internal/event/actors/actor-relayouter.h
dali/internal/event/actors/actor-siblings.cpp [new file with mode: 0644]
dali/internal/event/actors/actor-siblings.h [new file with mode: 0644]
dali/internal/event/common/object-impl.cpp
dali/internal/event/common/object-impl.h
dali/internal/event/common/property-metadata.h
dali/internal/event/common/type-info-impl.cpp
dali/internal/event/common/type-info-impl.h
dali/internal/event/rendering/vertex-buffer-impl.cpp
dali/internal/file.list
dali/internal/render/data-providers/uniform-map-data-provider.h
dali/internal/render/renderers/render-geometry.cpp
dali/internal/render/renderers/render-renderer.cpp
dali/internal/render/renderers/render-vertex-buffer.h
dali/internal/render/shaders/program.cpp
dali/internal/render/shaders/program.h
dali/internal/update/animation/scene-graph-animation.cpp
dali/internal/update/common/property-owner-messages.h
dali/internal/update/common/property-owner.cpp
dali/internal/update/common/property-owner.h
dali/internal/update/common/uniform-map.cpp
dali/internal/update/common/uniform-map.h
dali/internal/update/nodes/node.cpp [changed mode: 0755->0644]
dali/internal/update/nodes/node.h
dali/internal/update/rendering/scene-graph-renderer.cpp
dali/public-api/animation/alpha-function.cpp
dali/public-api/animation/alpha-function.h
dali/public-api/dali-core-version.cpp
dali/public-api/object/handle.cpp
dali/public-api/object/handle.h
dali/public-api/object/ref-object.cpp
dali/public-api/object/ref-object.h
dali/public-api/object/type-info.cpp
dali/public-api/object/type-info.h
packaging/dali.spec

diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml
new file mode 100644 (file)
index 0000000..799e0bc
--- /dev/null
@@ -0,0 +1,69 @@
+# For most projects, this workflow file will not need changing; you simply need
+# to commit it to your repository.
+#
+# You may wish to alter this file to override the set of languages analyzed,
+# or to provide custom queries or build logic.
+#
+# ******** NOTE ********
+# We have attempted to detect the languages in your repository. Please check
+# the `language` matrix defined below to confirm you have the correct set of
+# supported CodeQL languages.
+#
+name: "CodeQL"
+
+on:
+  push:
+    branches: [ master, devel/vulkan ]
+  pull_request:
+    # The branches below must be a subset of the branches above
+    branches: [ master ]
+  schedule:
+    - cron: '24 1 * * 1'
+
+jobs:
+  analyze:
+    name: Analyze
+    runs-on: ubuntu-latest
+
+    strategy:
+      fail-fast: false
+      matrix:
+        language: [ 'cpp' ]
+        # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ]
+        # Learn more:
+        # https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed
+
+    steps:
+    - name: Checkout repository
+      uses: actions/checkout@v2
+
+    # Initializes the CodeQL tools for scanning.
+    - name: Initialize CodeQL
+      uses: github/codeql-action/init@v1
+      with:
+        languages: ${{ matrix.language }}
+        # If you wish to specify custom queries, you can do so here or in a config file.
+        # By default, queries listed here will override any specified in a config file.
+        # Prefix the list here with "+" to use these queries and those in the config file.
+        # queries: ./path/to/local/query, your-org/your-repo/queries@main
+
+    # Autobuild attempts to build any compiled languages  (C/C++, C#, or Java).
+    # If this step fails, then you should remove it and run the build manually (see below)
+    #- name: Autobuild
+    #  uses: github/codeql-action/autobuild@v1
+
+    # â„šī¸ Command-line programs to run using the OS shell.
+    # đŸ“š https://git.io/JvXDl
+
+    # âœī¸ If the Autobuild fails above, remove it and uncomment the following three lines
+    #    and modify them (or add more) to build your code if your project
+    #    uses a compiled language
+
+    - run: |
+       cd build/tizen
+       export DESKTOP_PREFIX=/tmp
+       cmake -DCMAKE_INSTALL_PREFIX=$DESKTOP_PREFIX .
+       make -j8
+
+    - name: Perform CodeQL Analysis
+      uses: github/codeql-action/analyze@v1
index 3ace2e3..e7d2310 100644 (file)
@@ -20,6 +20,7 @@ SET(TC_SOURCES
         utc-Dali-Internal-RotationGesture.cpp
         utc-Dali-Internal-TapGesture.cpp
         utc-Dali-Internal-TapGestureProcessor.cpp
+        utc-Dali-Internal-ConstString.cpp
 )
 
 LIST(APPEND TC_SOURCES
diff --git a/automated-tests/src/dali-internal/utc-Dali-Internal-ConstString.cpp b/automated-tests/src/dali-internal/utc-Dali-Internal-ConstString.cpp
new file mode 100644 (file)
index 0000000..02e65d1
--- /dev/null
@@ -0,0 +1,162 @@
+/*
+ * 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.
+ *
+ */
+
+#include <dali-test-suite-utils.h>
+#include <dali/public-api/dali-core.h>
+
+#include <random>
+#include <string>
+
+// Internal headers are allowed here
+#include <dali/internal/common/const-string.h>
+
+using namespace Dali;
+
+namespace
+{
+std::string RandomString(size_t length)
+{
+  static auto& chrs =
+    "0123456789"
+    "abcdefghijklmnopqrstuvwxyz"
+    "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+
+  thread_local static std::mt19937                                          rg{std::random_device{}()};
+  thread_local static std::uniform_int_distribution<std::string::size_type> pick(0, sizeof(chrs) - 2);
+
+  std::string s;
+
+  s.reserve(length);
+
+  while(length--)
+    s += chrs[pick(rg)];
+
+  return s;
+}
+} // namespace
+
+void utc_dali_internal_conststring_startup(void)
+{
+  test_return_value = TET_UNDEF;
+}
+
+void utc_dali_internal_conststring_cleanup(void)
+{
+  test_return_value = TET_PASS;
+}
+
+int UtcDaliConstStringEmpty(void)
+{
+  Internal::ConstString str1;
+  DALI_TEST_EQUALS(str1.IsEmpty(), true, TEST_LOCATION);
+
+  Internal::ConstString str2("hello");
+  DALI_TEST_EQUALS(str2.IsEmpty(), false, TEST_LOCATION);
+
+  str2.Clear();
+  DALI_TEST_EQUALS(str2.IsEmpty(), true, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliConstStringConstruct(void)
+{
+  Internal::ConstString str1("string1");
+  DALI_TEST_EQUALS(str1.GetCString(), "string1", TEST_LOCATION);
+
+  Internal::ConstString str2("string1");
+
+  DALI_TEST_EQUALS(str2.GetCString(), "string1", TEST_LOCATION);
+
+  bool samePointer = (str1.GetCString() == str2.GetCString());
+  DALI_TEST_EQUALS(samePointer, true, TEST_LOCATION);
+
+  str1.Clear();
+  DALI_TEST_EQUALS(str2.GetCString(), "string1", TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliConstStringConstructStringView(void)
+{
+  Internal::ConstString str1(std::string_view("random string"));
+
+  DALI_TEST_EQUALS(str1.GetStringView().data(), "random string", TEST_LOCATION);
+  DALI_TEST_EQUALS(str1.GetStringView().size(), 13, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliConstStringSetString(void)
+{
+  Internal::ConstString str1(std::string_view("current string"));
+
+  DALI_TEST_EQUALS(str1.GetStringView().data(), "current string", TEST_LOCATION);
+
+  str1.SetString("new string");
+
+  DALI_TEST_EQUALS(str1.GetCString(), "new string", TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliConstStringStressTest(void)
+{
+  static constexpr size_t DB_SIZE = 2000;
+
+  std::vector<std::string> Database;
+  Database.reserve(DB_SIZE);
+
+  std::vector<Internal::ConstString> constStringDB;
+  constStringDB.reserve(DB_SIZE);
+
+  std::vector<Internal::ConstString> constStringDB1;
+  constStringDB1.reserve(DB_SIZE);
+
+  for(auto i = 0u; i < DB_SIZE; i++)
+  {
+    if(i % 3 == 0)
+    {
+      Database.push_back(RandomString(10));
+    }
+    else if(i % 4 == 0)
+    {
+      Database.push_back(RandomString(7));
+    }
+    else
+    {
+      Database.push_back(RandomString(11));
+    }
+    constStringDB.push_back(Internal::ConstString(Database[i]));
+    constStringDB1.push_back(Internal::ConstString(Database[i]));
+  }
+
+  // check eqality betwwen original string and constString
+  for(auto i = 0u; i < DB_SIZE; i++)
+  {
+    DALI_TEST_EQUALS(constStringDB[i].GetCString(), Database[i].c_str(), TEST_LOCATION);
+  }
+
+  // check pointer eqality betwwen 2 constString
+  for(auto i = 0u; i < DB_SIZE; i++)
+  {
+    bool pointerEqual = (constStringDB[i] == constStringDB1[i]);
+    DALI_TEST_EQUALS(pointerEqual, true, TEST_LOCATION);
+  }
+
+  END_TEST;
+}
index b8de978..a4b45c9 100644 (file)
@@ -306,6 +306,38 @@ void DALI_TEST_EQUALS(const std::string& str1, const char* str2, const char* loc
 void DALI_TEST_EQUALS(const char* str1, const std::string& str2, const char* location);
 
 /**
+ * Test whether two strings are equal.
+ * @param[in] str1 The first string
+ * @param[in] str2 The second string
+ * @param[in] location The TEST_LOCATION macro should be used here
+ */
+template<>
+inline void DALI_TEST_EQUALS<const std::string_view>(std::string_view str1, std::string_view str2, const char* location)
+{
+  DALI_TEST_EQUALS(str1.data(), str2.data(), location);
+}
+
+inline void DALI_TEST_EQUALS(std::string_view str1, const char* str2, const char* location)
+{
+  DALI_TEST_EQUALS(str1.data(), str2, location);
+}
+
+inline void DALI_TEST_EQUALS(std::string_view str1, const std::string& str2, const char* location)
+{
+  DALI_TEST_EQUALS(str1.data(), str2.c_str(), location);
+}
+
+inline void DALI_TEST_EQUALS(const std::string& str2, std::string_view str1, const char* location)
+{
+  DALI_TEST_EQUALS(str2.c_str(), str1.data(), location);
+}
+
+inline void DALI_TEST_EQUALS(const char* str1, std::string_view str2, const char* location)
+{
+  DALI_TEST_EQUALS(str1, str2.data(), location);
+}
+
+/**
  * Test if a property value type is equal to a trivial type.
  */
 template<typename Type>
index 5ac38fa..d23681c 100755 (executable)
@@ -5289,6 +5289,117 @@ int UtcDaliActorRaiseAbove(void)
   END_TEST;
 }
 
+int UtcDaliActorRaiseAbove2(void)
+{
+  tet_infoline("UtcDaliActor RaiseToAbove test using SIBLING_ORDER property\n");
+
+  TestApplication application;
+
+  Integration::Scene stage(application.GetScene());
+
+  Actor actorA = Actor::New();
+  Actor actorB = Actor::New();
+  Actor actorC = Actor::New();
+
+  actorA.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
+  actorA.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+
+  actorB.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
+  actorB.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+
+  actorC.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
+  actorC.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+
+  actorA.SetProperty(Actor::Property::WIDTH_RESIZE_POLICY, "FILL_TO_PARENT");
+  actorA.SetProperty(Actor::Property::HEIGHT_RESIZE_POLICY, "FILL_TO_PARENT");
+
+  actorB.SetProperty(Actor::Property::WIDTH_RESIZE_POLICY, "FILL_TO_PARENT");
+  actorB.SetProperty(Actor::Property::HEIGHT_RESIZE_POLICY, "FILL_TO_PARENT");
+
+  actorC.SetProperty(Actor::Property::WIDTH_RESIZE_POLICY, "FILL_TO_PARENT");
+  actorC.SetProperty(Actor::Property::HEIGHT_RESIZE_POLICY, "FILL_TO_PARENT");
+
+  stage.Add(actorA);
+  stage.Add(actorB);
+  stage.Add(actorC);
+
+  ResetTouchCallbacks();
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS(gTouchCallBackCalled, false, TEST_LOCATION);
+  DALI_TEST_EQUALS(gTouchCallBackCalled2, false, TEST_LOCATION);
+  DALI_TEST_EQUALS(gTouchCallBackCalled3, false, TEST_LOCATION);
+
+  // connect to actor touch signals, will use touch callbacks to determine which actor is on top.
+  // Only top actor will get touched.
+  actorA.TouchedSignal().Connect(TestTouchCallback);
+  actorB.TouchedSignal().Connect(TestTouchCallback2);
+  actorC.TouchedSignal().Connect(TestTouchCallback3);
+
+  bool                     orderChangedSignal(false);
+  Actor                    orderChangedActor;
+  ChildOrderChangedFunctor f(orderChangedSignal, orderChangedActor);
+  DevelActor::ChildOrderChangedSignal(stage.GetRootLayer()).Connect(&application, f);
+
+  Dali::Integration::Point point;
+  point.SetDeviceId(1);
+  point.SetState(PointState::DOWN);
+  point.SetScreenPosition(Vector2(10.f, 10.f));
+  Dali::Integration::TouchEvent touchEvent;
+  touchEvent.AddPoint(point);
+
+  application.ProcessEvent(touchEvent);
+
+  DALI_TEST_EQUALS(gTouchCallBackCalled, false, TEST_LOCATION);
+  DALI_TEST_EQUALS(gTouchCallBackCalled2, false, TEST_LOCATION);
+  DALI_TEST_EQUALS(gTouchCallBackCalled3, true, TEST_LOCATION);
+
+  ResetTouchCallbacks();
+
+  tet_printf("Raise actor B Above Actor C\n");
+
+  DALI_TEST_EQUALS(orderChangedSignal, false, TEST_LOCATION);
+  int newOrder = actorC[DevelActor::Property::SIBLING_ORDER];
+  actorB[DevelActor::Property::SIBLING_ORDER] = newOrder;
+  DALI_TEST_EQUALS(orderChangedSignal, true, TEST_LOCATION);
+  DALI_TEST_EQUALS(orderChangedActor, actorB, TEST_LOCATION);
+
+  // Ensure sorting happens at end of Core::ProcessEvents() before next touch
+  application.SendNotification();
+  application.ProcessEvent(touchEvent);
+
+  DALI_TEST_EQUALS(gTouchCallBackCalled, false, TEST_LOCATION);
+  DALI_TEST_EQUALS(gTouchCallBackCalled2, true, TEST_LOCATION);
+  DALI_TEST_EQUALS(gTouchCallBackCalled3, false, TEST_LOCATION);
+
+  ResetTouchCallbacks();
+
+  tet_printf("Raise actor A Above Actor B\n");
+
+  orderChangedSignal = false;
+
+  DALI_TEST_EQUALS(orderChangedSignal, false, TEST_LOCATION);
+  newOrder = actorB[DevelActor::Property::SIBLING_ORDER];
+  actorA[DevelActor::Property::SIBLING_ORDER] = newOrder;
+  DALI_TEST_EQUALS(orderChangedSignal, true, TEST_LOCATION);
+  DALI_TEST_EQUALS(orderChangedActor, actorA, TEST_LOCATION);
+
+  // Ensure sorting happens at end of Core::ProcessEvents() before next touch
+  application.SendNotification();
+
+  application.ProcessEvent(touchEvent); // process a touch event on ordered actors.
+
+  DALI_TEST_EQUALS(gTouchCallBackCalled, true, TEST_LOCATION);
+  DALI_TEST_EQUALS(gTouchCallBackCalled2, false, TEST_LOCATION);
+  DALI_TEST_EQUALS(gTouchCallBackCalled3, false, TEST_LOCATION);
+
+  ResetTouchCallbacks();
+
+  END_TEST;
+}
+
 int UtcDaliActorLowerBelow(void)
 {
   tet_infoline("UtcDaliActor LowerBelow test \n");
@@ -5514,6 +5625,232 @@ int UtcDaliActorLowerBelow(void)
   END_TEST;
 }
 
+
+int UtcDaliActorLowerBelow2(void)
+{
+  tet_infoline("UtcDaliActor LowerBelow test using SIBLING_ORDER property\n");
+
+  TestApplication application;
+
+  Integration::Scene stage(application.GetScene());
+
+  // Set up renderers to add to Actors, float value 1, 2, 3 assigned to each
+  // enables checking of which actor the uniform is assigned too
+  Shader shaderA = CreateShader();
+  shaderA.RegisterProperty("uRendererColor", 1.f);
+
+  Shader shaderB = CreateShader();
+  shaderB.RegisterProperty("uRendererColor", 2.f);
+
+  Shader shaderC = CreateShader();
+  shaderC.RegisterProperty("uRendererColor", 3.f);
+
+  Actor actorA = Actor::New();
+  Actor actorB = Actor::New();
+  Actor actorC = Actor::New();
+
+  // Add renderers to Actors so ( uRendererColor, 1 ) is A, ( uRendererColor, 2 ) is B, and ( uRendererColor, 3 ) is C,
+  Geometry geometry = CreateQuadGeometry();
+
+  Renderer rendererA = Renderer::New(geometry, shaderA);
+  actorA.AddRenderer(rendererA);
+
+  Renderer rendererB = Renderer::New(geometry, shaderB);
+  actorB.AddRenderer(rendererB);
+
+  Renderer rendererC = Renderer::New(geometry, shaderC);
+  actorC.AddRenderer(rendererC);
+
+  actorA.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
+  actorA.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+
+  actorB.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
+  actorB.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+
+  actorC.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
+  actorC.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+
+  actorA.SetProperty(Actor::Property::WIDTH_RESIZE_POLICY, "FILL_TO_PARENT");
+  actorA.SetProperty(Actor::Property::HEIGHT_RESIZE_POLICY, "FILL_TO_PARENT");
+
+  actorB.SetProperty(Actor::Property::WIDTH_RESIZE_POLICY, "FILL_TO_PARENT");
+  actorB.SetProperty(Actor::Property::HEIGHT_RESIZE_POLICY, "FILL_TO_PARENT");
+
+  actorC.SetProperty(Actor::Property::WIDTH_RESIZE_POLICY, "FILL_TO_PARENT");
+  actorC.SetProperty(Actor::Property::HEIGHT_RESIZE_POLICY, "FILL_TO_PARENT");
+
+  Actor container = Actor::New();
+  container.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+  container.SetResizePolicy(ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS);
+  stage.Add(container);
+
+  container.Add(actorA);
+  container.Add(actorB);
+  container.Add(actorC);
+
+  ResetTouchCallbacks();
+
+  // Connect ChildOrderChangedSignal
+  bool                     orderChangedSignal(false);
+  Actor                    orderChangedActor;
+  ChildOrderChangedFunctor f(orderChangedSignal, orderChangedActor);
+  DevelActor::ChildOrderChangedSignal(container).Connect(&application, f);
+
+  // Set up gl abstraction trace so can query the set uniform order
+  TestGlAbstraction& glAbstraction = application.GetGlAbstraction();
+  glAbstraction.EnableSetUniformCallTrace(true);
+  glAbstraction.ResetSetUniformCallStack();
+  TraceCallStack& glSetUniformStack = glAbstraction.GetSetUniformTrace();
+
+  glAbstraction.ResetSetUniformCallStack();
+
+  application.SendNotification();
+  application.Render();
+
+  glSetUniformStack = glAbstraction.GetSetUniformTrace();
+
+  tet_printf("Trace:%s \n", glSetUniformStack.GetTraceString().c_str());
+
+  // Test order of uniforms in stack
+  int indexC = glSetUniformStack.FindIndexFromMethodAndParams("uRendererColor", "3");
+  int indexB = glSetUniformStack.FindIndexFromMethodAndParams("uRendererColor", "2");
+  int indexA = glSetUniformStack.FindIndexFromMethodAndParams("uRendererColor", "1");
+
+  tet_infoline("Testing C above B and A at bottom\n");
+  bool CBA = (indexC > indexB) && (indexB > indexA);
+
+  DALI_TEST_EQUALS(CBA, true, TEST_LOCATION);
+
+  DALI_TEST_EQUALS(gTouchCallBackCalled, false, TEST_LOCATION);
+  DALI_TEST_EQUALS(gTouchCallBackCalled2, false, TEST_LOCATION);
+  DALI_TEST_EQUALS(gTouchCallBackCalled3, false, TEST_LOCATION);
+
+  // connect to actor touch signals, will use touch callbacks to determine which actor is on top.
+  // Only top actor will get touched.
+  actorA.TouchedSignal().Connect(TestTouchCallback);
+  actorB.TouchedSignal().Connect(TestTouchCallback2);
+  actorC.TouchedSignal().Connect(TestTouchCallback3);
+
+  Dali::Integration::Point point;
+  point.SetDeviceId(1);
+  point.SetState(PointState::DOWN);
+  point.SetScreenPosition(Vector2(10.f, 10.f));
+  Dali::Integration::TouchEvent touchEvent;
+  touchEvent.AddPoint(point);
+
+  tet_infoline("UtcDaliActor Test Set up completed \n");
+
+  application.ProcessEvent(touchEvent);
+
+  DALI_TEST_EQUALS(gTouchCallBackCalled, false, TEST_LOCATION);
+  DALI_TEST_EQUALS(gTouchCallBackCalled2, false, TEST_LOCATION);
+  DALI_TEST_EQUALS(gTouchCallBackCalled3, true, TEST_LOCATION);
+
+  ResetTouchCallbacks();
+
+  tet_printf("Lower actor C below Actor B ( actor B and A on same level due to insertion order) so C is below both \n");
+
+  DALI_TEST_EQUALS(orderChangedSignal, false, TEST_LOCATION);
+  actorC[DevelActor::Property::SIBLING_ORDER] = 1;
+  DALI_TEST_EQUALS(orderChangedSignal, true, TEST_LOCATION);
+  DALI_TEST_EQUALS(orderChangedActor, actorC, TEST_LOCATION);
+
+  // Ensure sorting happens at end of Core::ProcessEvents() before next touch
+  application.SendNotification();
+  application.Render();
+
+  application.ProcessEvent(touchEvent); // touch event
+
+  glAbstraction.ResetSetUniformCallStack();
+  glSetUniformStack = glAbstraction.GetSetUniformTrace();
+
+  application.SendNotification();
+  application.Render();
+
+  tet_printf("Trace:%s \n", glSetUniformStack.GetTraceString().c_str());
+
+  // Test order of uniforms in stack
+  indexC = glSetUniformStack.FindIndexFromMethodAndParams("uRendererColor", "3");
+  indexB = glSetUniformStack.FindIndexFromMethodAndParams("uRendererColor", "2");
+  indexA = glSetUniformStack.FindIndexFromMethodAndParams("uRendererColor", "1");
+
+  tet_infoline("Testing render order is A, C, B");
+  DALI_TEST_EQUALS(indexC > indexA, true, TEST_LOCATION);
+  DALI_TEST_EQUALS(indexB > indexC, true, TEST_LOCATION);
+
+  DALI_TEST_EQUALS(gTouchCallBackCalled, false, TEST_LOCATION);
+  DALI_TEST_EQUALS(gTouchCallBackCalled2, true, TEST_LOCATION);
+  DALI_TEST_EQUALS(gTouchCallBackCalled3, false, TEST_LOCATION);
+
+  ResetTouchCallbacks();
+
+  tet_printf("Lower actor C below Actor A leaving B on top\n");
+
+  orderChangedSignal = false;
+
+  DALI_TEST_EQUALS(orderChangedSignal, false, TEST_LOCATION);
+  actorC[DevelActor::Property::SIBLING_ORDER] = 0;
+  DALI_TEST_EQUALS(orderChangedSignal, true, TEST_LOCATION);
+  DALI_TEST_EQUALS(orderChangedActor, actorC, TEST_LOCATION);
+
+  // Ensure sorting happens at end of Core::ProcessEvents() before next touch
+  application.SendNotification();
+  application.Render();
+
+  application.ProcessEvent(touchEvent);
+
+  glAbstraction.ResetSetUniformCallStack();
+  glSetUniformStack = glAbstraction.GetSetUniformTrace();
+
+  application.Render();
+  tet_printf("Trace:%s \n", glSetUniformStack.GetTraceString().c_str());
+
+  // Test order of uniforms in stack
+  indexC = glSetUniformStack.FindIndexFromMethodAndParams("uRendererColor", "3");
+  indexB = glSetUniformStack.FindIndexFromMethodAndParams("uRendererColor", "2");
+  indexA = glSetUniformStack.FindIndexFromMethodAndParams("uRendererColor", "1");
+
+  DALI_TEST_EQUALS(indexA > indexC, true, TEST_LOCATION);
+  DALI_TEST_EQUALS(indexB > indexA, true, TEST_LOCATION);
+
+  DALI_TEST_EQUALS(gTouchCallBackCalled, false, TEST_LOCATION);
+  DALI_TEST_EQUALS(gTouchCallBackCalled2, true, TEST_LOCATION);
+  DALI_TEST_EQUALS(gTouchCallBackCalled3, false, TEST_LOCATION);
+
+  ResetTouchCallbacks();
+
+  tet_printf("Lower actor B below Actor C leaving A on top\n");
+
+  orderChangedSignal = false;
+
+  DALI_TEST_EQUALS(orderChangedSignal, false, TEST_LOCATION);
+  actorB[DevelActor::Property::SIBLING_ORDER] = 0;
+  DALI_TEST_EQUALS(orderChangedSignal, true, TEST_LOCATION);
+  DALI_TEST_EQUALS(orderChangedActor, actorB, TEST_LOCATION);
+
+  // Ensure sorting happens at end of Core::ProcessEvents() before next touch
+  application.SendNotification();
+  application.Render();
+
+  application.ProcessEvent(touchEvent);
+
+  glAbstraction.ResetSetUniformCallStack();
+  glSetUniformStack = glAbstraction.GetSetUniformTrace();
+
+  application.Render();
+  tet_printf("Trace:%s \n", glSetUniformStack.GetTraceString().c_str());
+
+  // Test order of uniforms in stack
+  indexC = glSetUniformStack.FindIndexFromMethodAndParams("uRendererColor", "3");
+  indexB = glSetUniformStack.FindIndexFromMethodAndParams("uRendererColor", "2");
+  indexA = glSetUniformStack.FindIndexFromMethodAndParams("uRendererColor", "1");
+
+  DALI_TEST_EQUALS(indexC > indexB, true, TEST_LOCATION);
+  DALI_TEST_EQUALS(indexA > indexC, true, TEST_LOCATION);
+
+  END_TEST;
+}
+
 int UtcDaliActorRaiseAboveDifferentParentsN(void)
 {
   tet_infoline("UtcDaliActor RaiseToAbove test with actor and target actor having different parents \n");
index b50d710..564ca27 100644 (file)
@@ -1101,6 +1101,80 @@ int UtcDaliRendererSetBlendMode07(void)
   END_TEST;
 }
 
+int UtcDaliRendererSetBlendMode08(void)
+{
+  TestApplication application;
+
+  tet_infoline("Test setting the blend mode to auto with opaque color and Advanced Blend Equation.");
+
+  if( Dali::Capabilities::IsBlendEquationSupported( DevelBlendEquation::SCREEN ) )
+  {
+    Geometry geometry = CreateQuadGeometry();
+    Shader   shader   = CreateShader();
+    Renderer renderer = Renderer::New(geometry, shader);
+
+    Actor actor = Actor::New();
+    actor.SetProperty(Actor::Property::OPACITY, 1.0f);
+    actor.AddRenderer(renderer);
+    actor.SetProperty(Actor::Property::SIZE, Vector2(400.0f, 400.0f));
+    application.GetScene().Add(actor);
+
+    renderer.SetProperty(Renderer::Property::BLEND_MODE, BlendMode::AUTO);
+    renderer.SetProperty( Renderer::Property::BLEND_PRE_MULTIPLIED_ALPHA, true );
+    renderer.SetProperty( DevelRenderer::Property::BLEND_EQUATION, DevelBlendEquation::SCREEN );
+
+    TestGlAbstraction& glAbstraction = application.GetGlAbstraction();
+    glAbstraction.EnableEnableDisableCallTrace(true);
+
+    application.SendNotification();
+    application.Render();
+
+    TraceCallStack&    glEnableStack = glAbstraction.GetEnableDisableTrace();
+    std::ostringstream blendStr;
+    blendStr << GL_BLEND;
+    DALI_TEST_CHECK(glEnableStack.FindMethodAndParams("Enable", blendStr.str().c_str()));
+  }
+
+  END_TEST;
+}
+
+int UtcDaliRendererSetBlendMode08b(void)
+{
+  TestApplication application;
+
+  tet_infoline("Test setting the blend mode to off with opaque color and Advanced Blend Equation.");
+
+  if( Dali::Capabilities::IsBlendEquationSupported( DevelBlendEquation::SCREEN ) )
+  {
+    Geometry geometry = CreateQuadGeometry();
+    Shader   shader   = CreateShader();
+    Renderer renderer = Renderer::New(geometry, shader);
+
+    Actor actor = Actor::New();
+    actor.SetProperty(Actor::Property::OPACITY, 1.0f);
+    actor.AddRenderer(renderer);
+    actor.SetProperty(Actor::Property::SIZE, Vector2(400.0f, 400.0f));
+    application.GetScene().Add(actor);
+
+    renderer.SetProperty(Renderer::Property::BLEND_MODE, BlendMode::OFF);
+    renderer.SetProperty( Renderer::Property::BLEND_PRE_MULTIPLIED_ALPHA, true );
+    renderer.SetProperty( DevelRenderer::Property::BLEND_EQUATION, DevelBlendEquation::SCREEN );
+
+    TestGlAbstraction& glAbstraction = application.GetGlAbstraction();
+    glAbstraction.EnableEnableDisableCallTrace(true);
+
+    application.SendNotification();
+    application.Render();
+
+    TraceCallStack&    glEnableStack = glAbstraction.GetEnableDisableTrace();
+    std::ostringstream blendStr;
+    blendStr << GL_BLEND;
+    DALI_TEST_CHECK(!glEnableStack.FindMethodAndParams("Enable", blendStr.str().c_str()));
+  }
+
+  END_TEST;
+}
+
 int UtcDaliRendererGetBlendMode(void)
 {
   TestApplication application;
index fd7f134..db133de 100644 (file)
@@ -19,6 +19,7 @@
 #include <dali/integration-api/events/hover-event-integ.h>
 #include <dali/integration-api/events/touch-event-integ.h>
 #include <dali/internal/event/common/type-info-impl.h>
+#include <dali/internal/common/const-string.h>
 #include <dali/public-api/dali-core.h>
 #include <stdlib.h>
 
@@ -1691,7 +1692,7 @@ int UtcDaliTypeRegistryChildPropertyRegistrationP(void)
 
   // check the child property type
   Internal::TypeInfo& typeInfoImpl = GetImplementation(typeInfo);
-  Property::Type      type         = typeInfoImpl.GetChildPropertyType(typeInfoImpl.GetChildPropertyIndex("childProp4"));
+  Property::Type      type         = typeInfoImpl.GetChildPropertyType(typeInfoImpl.GetChildPropertyIndex(Dali::Internal::ConstString("childProp4")));
   DALI_TEST_EQUALS(type, Property::INTEGER, TEST_LOCATION);
 
   std::string unRegisteredChildName(typeInfoImpl.GetChildPropertyName(CHILD_PROPERTY_REGISTRATION_START_INDEX + 4));
index 596e544..969d54a 100644 (file)
@@ -495,6 +495,17 @@ bool BlendingOptions::IsAdvancedBlendEquationApplied()
            ( ( indexA   >= BLENDING_EQUATION_ADVANCED_INDEX_START ) && ( indexA   <= BLENDING_EQUATION_ADVANCED_INDEX_END ) ) );
 }
 
+bool BlendingOptions::IsAdvancedBlendEquationIncluded( unsigned int bitmask )
+{
+  unsigned int indexRgb = bitmask & MASK_EQUATION_RGB;
+  indexRgb = indexRgb >> SHIFT_TO_EQUATION_RGB;
+  unsigned int indexA = bitmask & MASK_EQUATION_ALPHA;
+  indexA = indexA >> SHIFT_TO_EQUATION_ALPHA;
+
+  return ( ( ( indexRgb >= BLENDING_EQUATION_ADVANCED_INDEX_START ) && ( indexRgb <= BLENDING_EQUATION_ADVANCED_INDEX_END ) ) ||
+           ( ( indexA   >= BLENDING_EQUATION_ADVANCED_INDEX_START ) && ( indexA   <= BLENDING_EQUATION_ADVANCED_INDEX_END ) ) );
+}
+
 bool BlendingOptions::IsAdvancedBlendEquation( DevelBlendEquation::Type equation )
 {
   switch ( equation )
index f150685..f8a4a3d 100644 (file)
@@ -116,6 +116,12 @@ struct BlendingOptions
   bool IsAdvancedBlendEquationApplied();
 
   /**
+   * Query whether input bit mask include advanced blend equation.
+   * @return True if the bit mask include advanced blend equation.
+   */
+  static bool IsAdvancedBlendEquationIncluded( unsigned int bitmask );
+
+  /**
    * Query whether input blend equation is advanced option.
    * @return True if input blend equation is advanced.
    */
diff --git a/dali/internal/common/const-string.cpp b/dali/internal/common/const-string.cpp
new file mode 100644 (file)
index 0000000..058cc1d
--- /dev/null
@@ -0,0 +1,331 @@
+/*
+ * 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.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/common/const-string.h>
+
+// EXTERNAL INCLUDES
+#include <cstddef>
+#include <cstring>
+#include <functional>
+#include <vector>
+#include <mutex>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+
+// local namespace
+namespace
+{
+class ArenaAllocator
+{
+
+public:
+  ArenaAllocator()
+  {
+    mPages.reserve(10);
+    EnsureSpace();
+  }
+  ~ArenaAllocator()
+  {
+    for(auto& page : mPages)
+    {
+      delete[] page;
+    }
+  }
+  char* Allocate(uint32_t size, uint32_t alignment)
+  {
+    uintptr_t mask          = alignment - 1;
+    uintptr_t alignedOffset = (~reinterpret_cast<uintptr_t>(mCursor) + 1) & mask;
+    uintptr_t totalSize     = size + alignedOffset;
+
+    if(totalSize > static_cast<uintptr_t>(mEnd - mCursor))
+    {
+      EnsureSpace();
+      alignedOffset = (~reinterpret_cast<uintptr_t>(mCursor) + 1) & mask;
+    }
+    char* ptr = mCursor + alignedOffset;
+    mCursor   = ptr + size;
+    return ptr;
+  }
+
+private:
+  void EnsureSpace()
+  {
+    constexpr size_t pageSize = 4096;
+    char*            page     = new char[pageSize];
+    mPages.push_back(page);
+    mCursor = page;
+    mEnd    = mCursor + pageSize;
+  }
+
+  char*              mCursor{nullptr};
+  char*              mEnd{nullptr};
+  std::vector<char*> mPages;
+};
+
+class StringEntry
+{
+public:
+  explicit StringEntry(uint16_t stringLength)
+  : mStringLength(stringLength)
+  {
+  }
+  size_t getStringLength() const
+  {
+    return mStringLength;
+  }
+  const char* GetStringData() const
+  {
+    return reinterpret_cast<const char*>(this + 1);
+  }
+
+  std::string_view GetString() const
+  {
+    return std::string_view(GetStringData(), getStringLength());
+  }
+  /**
+   * GetStringEntryFromData - Given key data that is known to be embedded
+   * into a StringEntry, return the StringEntry itself.
+   */
+  static StringEntry& GetStringEntryFromData(const char* stringData)
+  {
+    char* ptr = const_cast<char*>(stringData) - sizeof(StringEntry);
+    return *reinterpret_cast<StringEntry*>(ptr);
+  }
+  /**
+   * Create a StringEntry from string_view
+   *
+   */
+  static StringEntry* Create(std::string_view str, ArenaAllocator& allocator)
+  {
+    size_t length = str.size();
+
+    // Allocate a new item with space for the string at the end and a null
+    // terminator.
+    size_t allocSize = sizeof(StringEntry) + length + 1;
+    size_t alignment = alignof(StringEntry);
+
+    // Construct the value.
+    StringEntry* newItem = new(allocator.Allocate(allocSize, alignment)) StringEntry(length);
+
+    // Copy the string information.
+    char* strBuffer = const_cast<char*>(newItem->GetStringData());
+    if(length > 0)
+      memcpy(strBuffer, str.data(), length);
+    strBuffer[length] = 0; // Null terminate.
+    return newItem;
+  }
+
+private:
+  uint16_t mStringLength;
+};
+
+class StringPool
+{
+public:
+  unsigned Size() const
+  {
+    return mItems;
+  }
+  StringPool()
+  {
+    Init();
+  }
+
+  static StringPool& Instance()
+  {
+    static StringPool object;
+    return object;
+  }
+
+  const char* Intern(std::string_view str)
+  {
+    const std::lock_guard<std::mutex> lock(mMutex);
+
+    auto  bucketNumber = FindBucket(str);
+    auto& bucket   = mTable[bucketNumber];
+
+    if(bucket)
+    {
+      // string already exists
+      return bucket->GetStringData();
+    }
+
+    // assign the newly created StringEntry to the designated bucket.
+    bucket = StringEntry::Create(str, mAllocator);
+
+    ++mItems;
+
+    bucketNumber = RehashTable(bucketNumber);
+
+    return mTable[bucketNumber]->GetStringData();
+  }
+
+private:
+  unsigned NextBucket(unsigned currentBucket, unsigned totalBucket, unsigned ProbeAmount)
+  {
+    return (currentBucket + ProbeAmount) & (totalBucket - 1);
+  }
+
+  void Init()
+  {
+    unsigned newBuckets = 512;
+    /**
+     * for memory efficiency and cache locality we store the StringEntry and corresponding HashValue  in separate
+     * segments in this way each entry in the bucket will take 12byte instead of 16 if we keep them together.
+     * So we allocate one memory and treat 1st segment as a array of StringEntry* and the second segment as array of
+     * unsigned*.
+     */
+    mTable = static_cast<StringEntry**>(calloc(newBuckets + 1, sizeof(StringEntry**) + sizeof(unsigned)));
+    DALI_ASSERT_ALWAYS(mTable && "calloc returned nullptr");
+
+    mBuckets = newBuckets;
+  }
+
+  unsigned FindBucket(std::string_view name)
+  {
+    unsigned  bucketSize    = mBuckets;
+    unsigned  fullHashValue = std::hash<std::string_view>{}(name);
+    unsigned  bucketNumber      = fullHashValue & (bucketSize - 1);
+    // point to the start of the hashvalue segment.
+    unsigned* hashTable     = reinterpret_cast<unsigned*>(mTable + mBuckets + 1);
+
+    unsigned probeAmt = 1;
+    while(true)
+    {
+      StringEntry* bucketItem = mTable[bucketNumber];
+      // If we found an empty bucket, this key isn't in the table yet, return it.
+      if(!bucketItem)
+      {
+        hashTable[bucketNumber] = fullHashValue;
+        return bucketNumber;
+      }
+
+      if(hashTable[bucketNumber] == fullHashValue)
+      {
+        // If the full hash value matches, check deeply for a match.
+        if(name == bucketItem->GetString())
+        {
+          // We found a match!
+          return bucketNumber;
+        }
+      }
+
+      // Okay, we didn't find the item.  Probe to the next bucket.
+      bucketNumber = NextBucket(bucketNumber, bucketSize, probeAmt);
+
+      // Use quadratic probing, it has fewer clumping artifacts than linear
+      ++probeAmt;
+    }
+  }
+  unsigned RehashTable(unsigned bucketNumber)
+  {
+    unsigned  newSize;
+    unsigned* hashTable = reinterpret_cast<unsigned*>(mTable + mBuckets + 1);
+
+    // If the hash table is now more than 3/4 full.
+    // grow/rehash the table.
+    if((mItems * 4) > (mBuckets * 3))
+    {
+      newSize = mBuckets * 2;
+    }
+    else
+    {
+      return bucketNumber;
+    }
+    unsigned newBucketNumber = bucketNumber;
+
+    // Allocate one extra bucket which will always be non-empty.
+    auto newTable = static_cast<StringEntry**>(calloc(newSize + 1, sizeof(StringEntry*) + sizeof(unsigned)));
+    DALI_ASSERT_ALWAYS(newTable && "calloc returned nullptr");
+
+    // point to the start of the hashvalue segment. as the pointer is of type StringEntry* , but the
+    // second segment keeps only unsigned data hence the reinterpret_cast.
+    unsigned* newHashTable = reinterpret_cast<unsigned*>(newTable + newSize + 1);
+
+    // Rehash all the items into their new buckets.
+    for(unsigned i = 0, j = mBuckets; i != j; ++i)
+    {
+      StringEntry* bucket = mTable[i];
+      if(bucket)
+      {
+        // Fast case, bucket available.
+        unsigned fullHash  = hashTable[i];
+        unsigned newBucket = fullHash & (newSize - 1);
+        if(!newTable[newBucket])
+        {
+          newTable[fullHash & (newSize - 1)]     = bucket;
+          newHashTable[fullHash & (newSize - 1)] = fullHash;
+          if(i == bucketNumber)
+            newBucketNumber = newBucket;
+          continue;
+        }
+
+        // Otherwise probe for a spot.
+        unsigned ProbeSize = 1;
+        do
+        {
+          newBucket = NextBucket(newBucket, newSize, ProbeSize++);
+        } while(newTable[newBucket]);
+
+        // Finally found a slot.  Fill it in.
+        newTable[newBucket]     = bucket;
+        newHashTable[newBucket] = fullHash;
+        if(i == bucketNumber)
+          newBucketNumber = newBucket;
+      }
+    }
+
+    free(mTable);
+
+    mTable   = newTable;
+    mBuckets = newSize;
+    return newBucketNumber;
+  }
+
+private:
+  std::mutex     mMutex;
+  ArenaAllocator mAllocator;
+  StringEntry**  mTable{nullptr};
+  unsigned       mBuckets{0};
+  unsigned       mItems{0};
+};
+
+} // namespace
+
+Dali::Internal::ConstString::ConstString(std::string_view str)
+{
+  mString = StringPool::Instance().Intern(str);
+}
+
+size_t Dali::Internal::ConstString::GetLength() const
+{
+  return mString ? StringEntry::GetStringEntryFromData(mString).getStringLength() : 0;
+}
+
+void Dali::Internal::ConstString::SetString(std::string_view str)
+{
+  if(str.empty())
+  {
+    mString = nullptr;
+  }
+  else
+  {
+    mString = StringPool::Instance().Intern(str);
+  }
+}
diff --git a/dali/internal/common/const-string.h b/dali/internal/common/const-string.h
new file mode 100644 (file)
index 0000000..49b116c
--- /dev/null
@@ -0,0 +1,238 @@
+#ifndef DALI_INTERNAL_CONST_STRING_H
+#define DALI_INTERNAL_CONST_STRING_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.
+ *
+ */
+
+#include <string_view>
+
+namespace Dali
+{
+namespace Internal
+{
+/**
+ * A uniqued constant string class.
+ *
+ * Provides an efficient way to store strings as uniqued strings. After the
+ * strings are uniqued, finding strings that are equal to one another is very
+ * fast as just the pointers need to be compared. It also allows for many
+ * common strings from many different sources to be shared to keep the memory
+ * footprint low.
+ *
+ * No reference counting is done on strings that are added to the string
+ * pool, once strings are added they are in the string pool for the life of
+ * the program.
+ */
+class ConstString
+{
+public:
+  /**
+   * Default constructor
+   *
+   * Initializes the string to an empty string.
+   */
+  ConstString() = default;
+
+  explicit ConstString(std::string_view str);
+
+  /**
+   * Convert to bool operator.
+   *
+   * This allows code to check a ConstString object to see if it contains a
+   * valid string using code such as:
+   *
+   * \code
+   * ConstString str(...);
+   * if (str)
+   * { ...
+   * \endcode
+   *
+   * \return
+   *     /b True this object contains a valid non-empty C string, \b
+   *     false otherwise.
+   */
+  explicit operator bool() const
+  {
+    return !IsEmpty();
+  }
+
+  /**
+   * Equal to operator
+   *
+   * Returns true if this string is equal to the string in \a rhs. This
+   * operation is very fast as it results in a pointer comparison since all
+   * strings are in a uniqued in a global string pool.
+   *
+   * \param[in] rhs
+   *     Another string object to compare this object to.
+   *
+   * \return
+   *     true if this object is equal to \a rhs.
+   *     false if this object is not equal to \a rhs.
+   */
+  bool operator==(ConstString rhs) const
+  {
+    // We can do a pointer compare to compare these strings since they must
+    // come from the same pool in order to be equal.
+    return mString == rhs.mString;
+  }
+
+  /**
+   * Equal to operator against a non-ConstString value.
+   *
+   * Returns true if this string is equal to the string in \a rhs.
+   *
+   * \param[in] rhs
+   *     Another string object to compare this object to.
+   *
+   * \return
+   *     \b true if this object is equal to \a rhs.
+   *     \b false if this object is not equal to \a rhs.
+   */
+  bool operator==(const char* rhs) const
+  {
+    // ConstString differentiates between empty strings and nullptr strings, but
+    // StringRef doesn't. Therefore we have to do this check manually now.
+    if(mString == nullptr && rhs != nullptr)
+      return false;
+    if(mString != nullptr && rhs == nullptr)
+      return false;
+
+    return GetStringView() == rhs;
+  }
+
+  /**
+   * Not equal to operator
+   *
+   * Returns true if this string is not equal to the string in \a rhs. This
+   * operation is very fast as it results in a pointer comparison since all
+   * strings are in a uniqued in a global string pool.
+   *
+   * \param[in] rhs
+   *     Another string object to compare this object to.
+   *
+   * \return
+   *     \b true if this object is not equal to \a rhs.
+   *     \b false if this object is equal to \a rhs.
+   */
+  bool operator!=(ConstString rhs) const
+  {
+    return mString != rhs.mString;
+  }
+
+  /**
+   * Not equal to operator against a non-ConstString value.
+   *
+   * Returns true if this string is not equal to the string in \a rhs.
+   *
+   * \param[in] rhs
+   *     Another string object to compare this object to.
+   *
+   * \return \b true if this object is not equal to \a rhs, false otherwise.
+   */
+  bool operator!=(const char* rhs) const
+  {
+    return !(*this == rhs);
+  }
+
+  /**
+   * Get the string value as a std::string_view
+   *
+   * \return
+   *     Returns a new std::string_view object filled in with the
+   *     needed data.
+   */
+  std::string_view GetStringView() const
+  {
+    return mString ? std::string_view(mString, GetLength()) : std::string_view();
+  }
+
+  /**
+   * Get the string value as a C string.
+   *
+   * Get the value of the contained string as a NULL terminated C string
+   * value. This function will always return nullptr if the string is not valid.
+   *  So this function is a direct accessor to the string pointer value.
+   *
+   * \return
+   *     Returns nullptr the string is invalid, otherwise the C string
+   *     value contained in this object.
+   */
+  const char* GetCString() const
+  {
+    return mString;
+  }
+
+  /**
+   * Get the length in bytes of string value.
+   *
+   * The string pool stores the length of the string, so we can avoid calling
+   * strlen() on the pointer value with this function.
+   *
+   * \return
+   *     Returns the number of bytes that this string occupies in
+   *     memory, not including the NULL termination byte.
+   */
+  size_t GetLength() const;
+
+  /**
+   * Clear this object's state.
+   *
+   * Clear any contained string and reset the value to the empty string
+   * value.
+   */
+  void Clear()
+  {
+    mString = nullptr;
+  }
+
+  /**
+   * Test for empty string.
+   *
+   * \return
+   *     \b true if the contained string is empty.
+   *     \b false if the contained string is not empty.
+   */
+  bool IsEmpty() const
+  {
+    return mString == nullptr || mString[0] == '\0';
+  }
+
+  /**
+   * Set the string_view value.
+   *
+   * Set the string value in the object by uniquing the \a str string value
+   * in our global string pool.
+   *
+   * If the string is already exists in the global string pool, it finds the
+   * current entry and returns the existing value. If it doesn't exist, it is
+   * added to the string pool.
+   *
+   * \param[in] str
+   *     A string_view to add to the string pool.
+   */
+  void SetString(std::string_view str);
+
+private:
+  const char* mString{nullptr};
+};
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // DALI_INTERNAL_CONST_STRING_H
index 72dfdac..f49bd1d 100644 (file)
@@ -37,6 +37,10 @@ using CameraActorPtr = IntrusivePtr<CameraActor>;
 using CustomActorPtr = IntrusivePtr<CustomActor>;
 using LayerPtr       = IntrusivePtr<Layer>;
 
+using ActorContainer = std::vector<ActorPtr>;
+using ActorIter      = ActorContainer::iterator;
+using ActorConstIter = ActorContainer::const_iterator;
+
 } // namespace Internal
 
 } // namespace Dali
index b6960ed..96e5a67 100755 (executable)
 #include <dali/public-api/object/type-registry.h>
 #include <dali/devel-api/common/capabilities.h>
 #include <dali/devel-api/actors/actor-devel.h>
+#include <dali/internal/event/events/actor-gesture-data.h>
 #include <dali/internal/event/actors/actor-property-handler.h>
 #include <dali/internal/event/actors/actor-relayouter.h>
-#include <dali/internal/event/common/event-thread-services.h>
-#include <dali/internal/event/render-tasks/render-task-impl.h>
+#include <dali/internal/event/actors/actor-siblings.h>
 #include <dali/internal/event/actors/camera-actor-impl.h>
-#include <dali/internal/event/render-tasks/render-task-list-impl.h>
+#include <dali/internal/event/common/event-thread-services.h>
+#include <dali/internal/event/common/projection.h>
 #include <dali/internal/event/common/property-helper.h>
-#include <dali/internal/event/common/stage-impl.h>
-#include <dali/internal/event/common/type-info-impl.h>
 #include <dali/internal/event/common/scene-impl.h>
+#include <dali/internal/event/common/stage-impl.h>
 #include <dali/internal/event/common/thread-local-storage.h>
-#include <dali/internal/event/common/projection.h>
+#include <dali/internal/event/common/type-info-impl.h>
+#include <dali/internal/event/render-tasks/render-task-impl.h>
+#include <dali/internal/event/render-tasks/render-task-list-impl.h>
 #include <dali/internal/event/size-negotiation/relayout-controller-impl.h>
 #include <dali/internal/update/nodes/node-messages.h>
-#include <dali/internal/event/events/actor-gesture-data.h>
 #include <dali/integration-api/debug.h>
 
 using Dali::Internal::SceneGraph::Node;
@@ -56,7 +57,6 @@ using Dali::Internal::SceneGraph::PropertyBase;
 
 #if defined(DEBUG_ENABLED)
 Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_DEPTH_TIMER" );
-Debug::Filter* gLogRelayoutFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_RELAYOUT_TIMER" );
 #endif
 
 namespace Dali
@@ -1199,7 +1199,6 @@ uint32_t Actor::AddRenderer( Renderer& renderer )
 
   if(mIsBlendEquationSet)
   {
-    renderer.SetBlendMode(Dali::BlendMode::ON);
     renderer.SetBlendEquation(static_cast<DevelBlendEquation::Type>(mBlendEquation));
   }
 
@@ -1270,7 +1269,6 @@ void Actor::SetBlendEquation(DevelBlendEquation::Type blendEquation)
       for(uint32_t i = 0; i < rendererCount; ++i)
       {
         RendererPtr renderer = GetRendererAt(i);
-        renderer->SetBlendMode(Dali::BlendMode::ON);
         renderer->SetBlendEquation(static_cast<DevelBlendEquation::Type>(blendEquation));
       }
     }
@@ -2269,98 +2267,6 @@ float Actor::CalculateSize( Dimension::Type dimension, const Vector2& maximumSiz
   return 0.0f;  // Default
 }
 
-void Actor::NegotiateDimension( Dimension::Type dimension, const Vector2& allocatedSize, ActorDimensionStack& recursionStack )
-{
-  // Check if it needs to be negotiated
-  if( IsLayoutDirty( dimension ) && !IsLayoutNegotiated( dimension ) )
-  {
-    // Check that we havn't gotten into an infinite loop
-    ActorDimensionPair searchActor = ActorDimensionPair( this, dimension );
-    bool recursionFound = false;
-    for( auto& element : recursionStack )
-    {
-      if( element == searchActor )
-      {
-        recursionFound = true;
-        break;
-      }
-    }
-
-    if( !recursionFound )
-    {
-      // Record the path that we have taken
-      recursionStack.push_back( ActorDimensionPair( this, dimension ) );
-
-      // Dimension dependency check
-      for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
-      {
-        Dimension::Type dimensionToCheck = static_cast< Dimension::Type >( 1 << i );
-
-        if( RelayoutDependentOnDimension( dimension, dimensionToCheck ) )
-        {
-          NegotiateDimension( dimensionToCheck, allocatedSize, recursionStack );
-        }
-      }
-
-      // Parent dependency check
-      Actor* parent = GetParent();
-      if( parent && RelayoutDependentOnParent( dimension ) )
-      {
-        parent->NegotiateDimension( dimension, allocatedSize, recursionStack );
-      }
-
-      // Children dependency check
-      if( RelayoutDependentOnChildren( dimension ) )
-      {
-        for( uint32_t i = 0, count = GetChildCount(); i < count; ++i )
-        {
-          ActorPtr child = GetChildAt( i );
-
-          // Only relayout child first if it is not dependent on this actor
-          if( !child->RelayoutDependentOnParent( dimension ) )
-          {
-            child->NegotiateDimension( dimension, allocatedSize, recursionStack );
-          }
-        }
-      }
-
-      // For deriving classes
-      OnCalculateRelayoutSize( dimension );
-
-      // All dependencies checked, calculate the size and set negotiated flag
-      const float newSize = Relayouter::ClampDimension( *this, CalculateSize( dimension, allocatedSize ), dimension );
-
-      SetNegotiatedDimension( newSize, dimension );
-      SetLayoutNegotiated( true, dimension );
-
-      // For deriving classes
-      OnLayoutNegotiated( newSize, dimension );
-
-      // This actor has been successfully processed, pop it off the recursion stack
-      recursionStack.pop_back();
-    }
-    else
-    {
-      // TODO: Break infinite loop
-      SetLayoutNegotiated( true, dimension );
-    }
-  }
-}
-
-void Actor::NegotiateDimensions( const Vector2& allocatedSize )
-{
-  // Negotiate all dimensions that require it
-  ActorDimensionStack recursionStack;
-
-  for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
-  {
-    const Dimension::Type dimension = static_cast< Dimension::Type >( 1 << i );
-
-    // Negotiate
-    NegotiateDimension( dimension, allocatedSize, recursionStack );
-  }
-}
-
 Vector2 Actor::ApplySizeSetPolicy( const Vector2& size )
 {
   return mRelayoutData->ApplySizeSetPolicy(*this, size);
@@ -2394,56 +2300,7 @@ void Actor::SetNegotiatedSize( RelayoutContainer& container )
 
 void Actor::NegotiateSize( const Vector2& allocatedSize, RelayoutContainer& container )
 {
-  // Force a size negotiation for actors that has assigned size during relayout
-  // This is required as otherwise the flags that force a relayout will not
-  // necessarilly be set. This will occur if the actor has already been laid out.
-  // The dirty flags are then cleared. Then if the actor is added back into the
-  // relayout container afterwards, the dirty flags would still be clear...
-  // causing a relayout to be skipped. Here we force any actors added to the
-  // container to be relayed out.
-  DALI_LOG_TIMER_START( NegSizeTimer1 );
-
-  if( GetUseAssignedSize(Dimension::WIDTH ) )
-  {
-    SetLayoutNegotiated( false, Dimension::WIDTH );
-  }
-  if( GetUseAssignedSize( Dimension::HEIGHT ) )
-  {
-    SetLayoutNegotiated( false, Dimension::HEIGHT );
-  }
-
-  // Do the negotiation
-  NegotiateDimensions( allocatedSize );
-
-  // Set the actor size
-  SetNegotiatedSize( container );
-
-  // Negotiate down to children
-  for( uint32_t i = 0, count = GetChildCount(); i < count; ++i )
-  {
-    ActorPtr child = GetChildAt( i );
-
-    // Forces children that have already been laid out to be relayed out
-    // if they have assigned size during relayout.
-    if( child->GetUseAssignedSize(Dimension::WIDTH) )
-    {
-      child->SetLayoutNegotiated(false, Dimension::WIDTH);
-      child->SetLayoutDirty(true, Dimension::WIDTH);
-    }
-
-    if( child->GetUseAssignedSize(Dimension::HEIGHT) )
-    {
-      child->SetLayoutNegotiated(false, Dimension::HEIGHT);
-      child->SetLayoutDirty(true, Dimension::HEIGHT);
-    }
-
-    // Only relayout if required
-    if( child->RelayoutRequired() )
-    {
-      container.Add( Dali::Actor( child.Get() ), mTargetSize.GetVectorXY() );
-    }
-  }
-  DALI_LOG_TIMER_END( NegSizeTimer1, gLogRelayoutFilter, Debug::Concise, "NegotiateSize() took: ");
+  Relayouter::NegotiateSize(*this, allocatedSize, container);
 }
 
 void Actor::SetUseAssignedSize( bool use, Dimension::Type dimension )
@@ -2471,27 +2328,7 @@ void Actor::RelayoutRequest( Dimension::Type dimension )
 
 void Actor::SetPreferredSize( const Vector2& size )
 {
-  EnsureRelayouter();
-
-  // If valid width or height, then set the resize policy to FIXED
-  // A 0 width or height may also be required so if the resize policy has not been changed, i.e. is still set to DEFAULT,
-  // then change to FIXED as well
-
-  if( size.width > 0.0f || GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::DEFAULT )
-  {
-    SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
-  }
-
-  if( size.height > 0.0f || GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::DEFAULT )
-  {
-    SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
-  }
-
-  mRelayoutData->preferredSize = size;
-
-  mUseAnimatedSize = AnimatedSizeFlag::CLEAR;
-
-  RelayoutRequest();
+  EnsureRelayouter().SetPreferredSize(*this, size);
 }
 
 Vector2 Actor::GetPreferredSize() const
@@ -2555,93 +2392,39 @@ void Actor::SetVisibleInternal( bool visible, SendMessage::Type sendMessage )
   }
 }
 
-void Actor::SetSiblingOrder( uint32_t order )
+void Actor::EmitOrderChangedAndRebuild()
 {
-  if ( mParent )
+  Dali::Actor handle( this );
+  mParent->mChildOrderChangedSignal.Emit( handle );
+  if( mIsOnScene && mScene )
   {
-    ActorContainer& siblings = *(mParent->mChildren);
-    uint32_t currentOrder = GetSiblingOrder();
-
-    if( order != currentOrder )
-    {
-      if( order == 0 )
-      {
-        LowerToBottom();
-      }
-      else if( order < siblings.size() -1 )
-      {
-        if( order > currentOrder )
-        {
-          RaiseAbove( *siblings[order] );
-        }
-        else
-        {
-          LowerBelow( *siblings[order] );
-        }
-      }
-      else
-      {
-        RaiseToTop();
-      }
-    }
+    mScene->RequestRebuildDepthTree();
   }
 }
 
-uint32_t Actor::GetSiblingOrder() const
+void Actor::SetSiblingOrder( uint32_t order )
 {
-  uint32_t order = 0;
-
-  if ( mParent )
+  if( mParent && SiblingHandler::SetSiblingOrder(*(mParent->mChildren), *this, order))
   {
-    ActorContainer& siblings = *(mParent->mChildren);
-    for( std::size_t i = 0; i < siblings.size(); ++i )
-    {
-      if( siblings[i] == this )
-      {
-        order = static_cast<uint32_t>( i );
-        break;
-      }
-    }
+    EmitOrderChangedAndRebuild();
   }
-
-  return order;
 }
 
-void Actor::RequestRebuildDepthTree()
+uint32_t Actor::GetSiblingOrder() const
 {
-  if( mIsOnScene )
+  uint32_t order = 0;
+  if( mParent )
   {
-    if( mScene )
-    {
-      mScene->RequestRebuildDepthTree();
-    }
+    order = SiblingHandler::GetSiblingOrder(*(mParent->mChildren), *this);
   }
+  return order;
 }
 
 void Actor::Raise()
 {
-  if ( mParent )
+  if( mParent && SiblingHandler::Raise(*(mParent->mChildren), *this) )
   {
-    ActorContainer& siblings = *(mParent->mChildren);
-    if( siblings.back() != this ) // If not already at end
-    {
-      for( std::size_t i=0; i<siblings.size(); ++i )
-      {
-        if( siblings[i] == this )
-        {
-          // Swap with next
-          ActorPtr next = siblings[i+1];
-          siblings[i+1] = this;
-          siblings[i] = next;
-          break;
-        }
-      }
-    }
-
-    Dali::Actor handle( this );
-    mParent->mChildOrderChangedSignal.Emit( handle );
-
-    RequestRebuildDepthTree();
+    EmitOrderChangedAndRebuild();
   }
   else
   {
@@ -2651,28 +2434,9 @@ void Actor::Raise()
 
 void Actor::Lower()
 {
-  if ( mParent )
+  if( mParent && SiblingHandler::Lower(*(mParent->mChildren), *this) )
   {
-    ActorContainer& siblings = *(mParent->mChildren);
-    if( siblings.front() != this ) // If not already at beginning
-    {
-      for( std::size_t i=1; i<siblings.size(); ++i )
-      {
-        if( siblings[i] == this )
-        {
-          // Swap with previous
-          ActorPtr previous = siblings[i-1];
-          siblings[i-1] = this;
-          siblings[i] = previous;
-          break;
-        }
-      }
-    }
-
-    Dali::Actor handle( this );
-    mParent->mChildOrderChangedSignal.Emit( handle );
-
-    RequestRebuildDepthTree();
+    EmitOrderChangedAndRebuild();
   }
   else
   {
@@ -2682,23 +2446,9 @@ void Actor::Lower()
 
 void Actor::RaiseToTop()
 {
-  if ( mParent )
+  if( mParent && SiblingHandler::RaiseToTop(*(mParent->mChildren), *this) )
   {
-    ActorContainer& siblings = *(mParent->mChildren);
-    if( siblings.back() != this ) // If not already at end
-    {
-      auto iter = std::find( siblings.begin(), siblings.end(), this );
-      if( iter != siblings.end() )
-      {
-        siblings.erase(iter);
-        siblings.push_back(ActorPtr(this));
-      }
-    }
-
-    Dali::Actor handle( this );
-    mParent->mChildOrderChangedSignal.Emit( handle );
-
-    RequestRebuildDepthTree();
+    EmitOrderChangedAndRebuild();
   }
   else
   {
@@ -2708,25 +2458,9 @@ void Actor::RaiseToTop()
 
 void Actor::LowerToBottom()
 {
-  if ( mParent )
+  if( mParent && SiblingHandler::LowerToBottom(*(mParent->mChildren), *this) )
   {
-    ActorContainer& siblings = *(mParent->mChildren);
-    if( siblings.front() != this ) // If not already at bottom,
-    {
-      ActorPtr thisPtr(this); // ensure this actor remains referenced.
-
-      auto iter = std::find( siblings.begin(), siblings.end(), this );
-      if( iter != siblings.end() )
-      {
-        siblings.erase(iter);
-        siblings.insert(siblings.begin(), thisPtr);
-      }
-    }
-
-    Dali::Actor handle( this );
-    mParent->mChildOrderChangedSignal.Emit( handle );
-
-    RequestRebuildDepthTree();
+    EmitOrderChangedAndRebuild();
   }
   else
   {
@@ -2736,30 +2470,9 @@ void Actor::LowerToBottom()
 
 void Actor::RaiseAbove( Internal::Actor& target )
 {
-  if ( mParent )
+  if( mParent && SiblingHandler::RaiseAbove( *(mParent->mChildren), *this, target ))
   {
-    ActorContainer& siblings = *(mParent->mChildren);
-    if( siblings.back() != this && target.mParent == mParent ) // If not already at top
-    {
-      ActorPtr thisPtr(this); // ensure this actor remains referenced.
-
-      auto targetIter = std::find( siblings.begin(), siblings.end(), &target );
-      auto thisIter   = std::find( siblings.begin(), siblings.end(), this );
-      if( thisIter < targetIter )
-      {
-        siblings.erase(thisIter);
-        // Erasing early invalidates the targetIter. (Conversely, inserting first may also
-        // invalidate thisIter)
-        targetIter = std::find( siblings.begin(), siblings.end(), &target );
-        ++targetIter;
-        siblings.insert(targetIter, thisPtr);
-      }
-
-      Dali::Actor handle( this );
-      mParent->mChildOrderChangedSignal.Emit( handle );
-
-      RequestRebuildDepthTree();
-    }
+    EmitOrderChangedAndRebuild();
   }
   else
   {
@@ -2769,27 +2482,9 @@ void Actor::RaiseAbove( Internal::Actor& target )
 
 void Actor::LowerBelow( Internal::Actor& target )
 {
-  if ( mParent )
+  if( mParent && SiblingHandler::LowerBelow(*(mParent->mChildren), *this, target ) )
   {
-    ActorContainer& siblings = *(mParent->mChildren);
-    if( siblings.front() != this && target.mParent == mParent ) // If not already at bottom
-    {
-      ActorPtr thisPtr(this); // ensure this actor remains referenced.
-
-      auto targetIter = std::find( siblings.begin(), siblings.end(), &target );
-      auto thisIter   = std::find( siblings.begin(), siblings.end(), this );
-
-      if( thisIter > targetIter )
-      {
-        siblings.erase(thisIter); // this only invalidates iterators at or after this point.
-        siblings.insert(targetIter, thisPtr);
-      }
-
-      Dali::Actor handle( this );
-      mParent->mChildOrderChangedSignal.Emit( handle );
-
-      RequestRebuildDepthTree();
-    }
+    EmitOrderChangedAndRebuild();
   }
   else
   {
index 367beeb..b80c212 100755 (executable)
@@ -57,10 +57,6 @@ class RenderTask;
 class Renderer;
 class Scene;
 
-using ActorContainer = std::vector<ActorPtr>;
-using ActorIter      = ActorContainer::iterator;
-using ActorConstIter = ActorContainer::const_iterator;
-
 using RendererContainer = std::vector<RendererPtr>;
 using RendererIter      = RendererContainer::iterator;
 
@@ -1008,28 +1004,6 @@ public:
   bool RelayoutDependentOnDimension( Dimension::Type dimension, Dimension::Type dependentDimension );
 
   /**
-   * Negotiate sizes for a control in all dimensions
-   *
-   * @param[in] allocatedSize The size constraint that the control must respect
-   */
-  void NegotiateDimensions( const Vector2& allocatedSize );
-
-  /**
-   * Negotiate size for a specific dimension
-   *
-   * The algorithm adopts a recursive dependency checking approach. Meaning, that wherever dependencies
-   * are found, e.g. an actor dependent on its parent, the dependency will be calculated first with NegotiatedDimension and
-   * LayoutDimensionNegotiated flags being filled in on the actor.
-   *
-   * @post All actors that exist in the dependency chain connected to the given actor will have had their NegotiatedDimensions
-   * calculated and set as well as the LayoutDimensionNegotiated flags.
-   *
-   * @param[in] dimension The dimension to negotiate on
-   * @param[in] allocatedSize The size constraint that the actor must respect
-   */
-  void NegotiateDimension( Dimension::Type dimension, const Vector2& allocatedSize, ActorDimensionStack& recursionStack );
-
-  /**
    * @brief Calculate the size of a dimension
    *
    * @param[in] dimension The dimension to calculate the size for
@@ -1974,9 +1948,10 @@ private:
   uint32_t GetSiblingOrder() const;
 
   /**
-   * Request that the stage rebuilds the actor depth indices.
+   * Emit ChildOrderChanged signal, and request that the scene
+   * rebuilds the actor depth indices.
    */
-  void RequestRebuildDepthTree();
+  void EmitOrderChangedAndRebuild();
 
   /**
    * @brief Get the current position of the actor in screen coordinates.
@@ -2089,6 +2064,7 @@ private:
   static ActorContainer mNullChildren;  ///< Empty container (shared by all actors, returned by GetChildren() const)
 
   struct PropertyHandler;
+  struct SiblingHandler;
 };
 
 } // namespace Internal
index 5348273..0e1fcf3 100644 (file)
 #include <dali/public-api/math/vector3.h>
 #include <dali/internal/event/size-negotiation/relayout-controller-impl.h>
 
+namespace
+{
+#if defined(DEBUG_ENABLED)
+Debug::Filter* gLogRelayoutFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_RELAYOUT_TIMER" );
+#endif
+} // unnamed namespace
+
 namespace Dali
 {
 
@@ -363,6 +370,29 @@ bool Actor::Relayouter::IsLayoutDirty( Dimension::Type dimension ) const
   return false;
 }
 
+void Actor::Relayouter::SetPreferredSize( Actor& actor, const Vector2& size )
+{
+  // If valid width or height, then set the resize policy to FIXED
+  // A 0 width or height may also be required so if the resize policy has not been changed, i.e. is still set to DEFAULT,
+  // then change to FIXED as well
+
+  if( size.width > 0.0f || GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::DEFAULT )
+  {
+    actor.SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
+  }
+
+  if( size.height > 0.0f || GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::DEFAULT )
+  {
+    actor.SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
+  }
+
+  actor.mRelayoutData->preferredSize = size;
+
+  actor.mUseAnimatedSize = AnimatedSizeFlag::CLEAR;
+
+  actor.RelayoutRequest();
+}
+
 float Actor::Relayouter::ClampDimension( const Internal::Actor& actor, float size, Dimension::Type dimension )
 {
   const float minSize = actor.GetMinimumSize( dimension );
@@ -371,6 +401,152 @@ float Actor::Relayouter::ClampDimension( const Internal::Actor& actor, float siz
   return std::max( minSize, std::min( size, maxSize ) );
 }
 
+void Actor::Relayouter::NegotiateDimension( Actor& actor, Dimension::Type dimension, const Vector2& allocatedSize, Actor::ActorDimensionStack& recursionStack )
+{
+  // Check if it needs to be negotiated
+  if( actor.IsLayoutDirty( dimension ) && !actor.IsLayoutNegotiated( dimension ) )
+  {
+    // Check that we havn't gotten into an infinite loop
+    Actor::ActorDimensionPair searchActor = Actor::ActorDimensionPair( &actor, dimension );
+    bool recursionFound = false;
+    for( auto& element : recursionStack )
+    {
+      if( element == searchActor )
+      {
+        recursionFound = true;
+        break;
+      }
+    }
+
+    if( !recursionFound )
+    {
+      // Record the path that we have taken
+      recursionStack.push_back( Actor::ActorDimensionPair( &actor, dimension ) );
+
+      // Dimension dependency check
+      for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
+      {
+        Dimension::Type dimensionToCheck = static_cast< Dimension::Type >( 1 << i );
+
+        if( actor.RelayoutDependentOnDimension( dimension, dimensionToCheck ) )
+        {
+          NegotiateDimension( actor, dimensionToCheck, allocatedSize, recursionStack );
+        }
+      }
+
+      // Parent dependency check
+      Actor* parent = actor.GetParent();
+      if( parent && actor.RelayoutDependentOnParent( dimension ) )
+      {
+        NegotiateDimension( *parent, dimension, allocatedSize, recursionStack );
+      }
+
+      // Children dependency check
+      if( actor.RelayoutDependentOnChildren( dimension ) )
+      {
+        for( uint32_t i = 0, count = actor.GetChildCount(); i < count; ++i )
+        {
+          ActorPtr child = actor.GetChildAt( i );
+
+          // Only relayout child first if it is not dependent on this actor
+          if( !child->RelayoutDependentOnParent( dimension ) )
+          {
+            NegotiateDimension( *child, dimension, allocatedSize, recursionStack );
+          }
+        }
+      }
+
+      // For deriving classes
+      actor.OnCalculateRelayoutSize( dimension );
+
+      // All dependencies checked, calculate the size and set negotiated flag
+      const float newSize = ClampDimension( actor, actor.CalculateSize( dimension, allocatedSize ), dimension );
+
+      actor.SetNegotiatedDimension( newSize, dimension );
+      actor.SetLayoutNegotiated( true, dimension );
+
+      // For deriving classes
+      actor.OnLayoutNegotiated( newSize, dimension );
+
+      // This actor has been successfully processed, pop it off the recursion stack
+      recursionStack.pop_back();
+    }
+    else
+    {
+      // TODO: Break infinite loop
+      actor.SetLayoutNegotiated( true, dimension );
+    }
+  }
+}
+
+void Actor::Relayouter::NegotiateDimensions(Actor& actor, const Vector2& allocatedSize)
+{
+  // Negotiate all dimensions that require it
+  ActorDimensionStack recursionStack;
+
+  for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
+  {
+    const Dimension::Type dimension = static_cast< Dimension::Type >( 1 << i );
+
+    // Negotiate
+    NegotiateDimension(actor, dimension, allocatedSize, recursionStack);
+  }
+}
+
+void Actor::Relayouter::NegotiateSize(Actor& actor, const Vector2& allocatedSize, RelayoutContainer& container)
+{
+  // Force a size negotiation for actors that has assigned size during relayout
+  // This is required as otherwise the flags that force a relayout will not
+  // necessarilly be set. This will occur if the actor has already been laid out.
+  // The dirty flags are then cleared. Then if the actor is added back into the
+  // relayout container afterwards, the dirty flags would still be clear...
+  // causing a relayout to be skipped. Here we force any actors added to the
+  // container to be relayed out.
+  DALI_LOG_TIMER_START( NegSizeTimer1 );
+
+  if( actor.GetUseAssignedSize(Dimension::WIDTH ) )
+  {
+    actor.SetLayoutNegotiated( false, Dimension::WIDTH );
+  }
+  if( actor.GetUseAssignedSize( Dimension::HEIGHT ) )
+  {
+    actor.SetLayoutNegotiated( false, Dimension::HEIGHT );
+  }
+
+  // Do the negotiation
+  NegotiateDimensions(actor, allocatedSize);
+
+  // Set the actor size
+  actor.SetNegotiatedSize( container );
+
+  // Negotiate down to children
+  for( uint32_t i = 0, count = actor.GetChildCount(); i < count; ++i )
+  {
+    ActorPtr child = actor.GetChildAt( i );
+
+    // Forces children that have already been laid out to be relayed out
+    // if they have assigned size during relayout.
+    if( child->GetUseAssignedSize(Dimension::WIDTH) )
+    {
+      child->SetLayoutNegotiated(false, Dimension::WIDTH);
+      child->SetLayoutDirty(true, Dimension::WIDTH);
+    }
+
+    if( child->GetUseAssignedSize(Dimension::HEIGHT) )
+    {
+      child->SetLayoutNegotiated(false, Dimension::HEIGHT);
+      child->SetLayoutDirty(true, Dimension::HEIGHT);
+    }
+
+    // Only relayout if required
+    if( child->RelayoutRequired() )
+    {
+      container.Add( Dali::Actor( child.Get() ), actor.mTargetSize.GetVectorXY() );
+    }
+  }
+  DALI_LOG_TIMER_END( NegSizeTimer1, gLogRelayoutFilter, Debug::Concise, "NegotiateSize() took: ");
+}
+
 } // namespace Internal
 
 } // namespace Dali
index 335e519..2b4a531 100644 (file)
@@ -94,6 +94,10 @@ struct Actor::Relayouter
   /// @copydoc Actor::IsLayoutDirty
   bool IsLayoutDirty( Dimension::Type dimension ) const;
 
+  /// @copydoc Actor::SetPreferredSize
+  /// @actor[in] actor The Actor whose preferred size we wish to set
+  void SetPreferredSize( Actor& actor, const Vector2& size );
+
   /**
    * @brief Clamp a dimension given the relayout constraints on given actor
    *
@@ -104,6 +108,45 @@ struct Actor::Relayouter
    */
   static float ClampDimension( const Internal::Actor& actor, float size, Dimension::Type dimension );
 
+  /**
+   * Negotiate size for a specific dimension
+   *
+   * The algorithm adopts a recursive dependency checking approach. Meaning, that wherever dependencies
+   * are found, e.g. an actor dependent on its parent, the dependency will be calculated first with NegotiatedDimension and
+   * LayoutDimensionNegotiated flags being filled in on the actor.
+   *
+   * @post All actors that exist in the dependency chain connected to the given actor will have had their NegotiatedDimensions
+   * calculated and set as well as the LayoutDimensionNegotiated flags.
+   *
+   * @param[in] actor The actor whose dimension we are negotiating
+   * @param[in] dimension The dimension to negotiate on
+   * @param[in] allocatedSize The size constraint that the actor must respect
+   */
+  static void NegotiateDimension(Actor& actor, Dimension::Type dimension, const Vector2& allocatedSize, Actor::ActorDimensionStack& recursionStack);
+
+  /**
+   * Negotiate sizes for a control in all dimensions
+   *
+   * @param[in] actor The actor whose dimensions we are negotiating
+   * @param[in] allocatedSize The size constraint that the control must respect
+   */
+  static void NegotiateDimensions(Actor& actor, const Vector2& allocatedSize);
+
+  /**
+   * @brief Called by the RelayoutController to negotiate the size of an actor.
+   *
+   * The size allocated by the the algorithm is passed in which the
+   * actor must adhere to.  A container is passed in as well which
+   * the actor should populate with actors it has not / or does not
+   * need to handle in its size negotiation.
+   *
+   * @param[in] actor The actor whose size we are negotiating
+   * @param[in]      size       The allocated size.
+   * @param[in,out]  container  The container that holds actors that are fed back into the
+   *                            RelayoutController algorithm.
+   */
+  static void NegotiateSize(Actor& actor, const Vector2& allocatedSize, RelayoutContainer& container);
+
 public:
 
   ResizePolicy::Type resizePolicies[ Dimension::DIMENSION_COUNT ];      ///< Resize policies
diff --git a/dali/internal/event/actors/actor-siblings.cpp b/dali/internal/event/actors/actor-siblings.cpp
new file mode 100644 (file)
index 0000000..c8cbf2e
--- /dev/null
@@ -0,0 +1,200 @@
+/*
+ * 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.
+ */
+
+// INTERNAL INCLUDES
+#include <dali/internal/event/actors/actor-impl.h>
+#include <dali/internal/event/actors/actor-siblings.h>
+
+// EXTERNAL INCLUDES
+#include <algorithm>
+
+namespace Dali
+{
+namespace Internal
+{
+
+bool Actor::SiblingHandler::SetSiblingOrder(
+  ActorContainer& siblings,
+  Actor& actor,
+  uint32_t order )
+{
+  bool changed = false;
+
+  uint32_t currentOrder = GetSiblingOrder(siblings, actor);
+  if( order != currentOrder )
+  {
+    if( order == 0 )
+    {
+      changed = LowerToBottom(siblings, actor);
+    }
+    else if( order < siblings.size() -1 )
+    {
+      if( order > currentOrder )
+      {
+        changed = RaiseAbove( siblings, actor, *siblings[order] );
+      }
+      else
+      {
+        changed = LowerBelow( siblings, actor, *siblings[order] );
+      }
+    }
+    else
+    {
+      changed = RaiseToTop(siblings, actor);
+    }
+  }
+  return changed;
+}
+
+uint32_t Actor::SiblingHandler::GetSiblingOrder(const ActorContainer& siblings, const Actor& actor)
+{
+  uint32_t order=0;
+  for( std::size_t i = 0; i < siblings.size(); ++i )
+  {
+    if( siblings[i] == &actor )
+    {
+      order = static_cast<uint32_t>( i );
+      break;
+    }
+  }
+  return order;
+}
+
+bool Actor::SiblingHandler::Raise(ActorContainer& siblings, Actor& actor)
+{
+  bool changed = false;
+  if( siblings.back() != &actor ) // If not already at end
+  {
+    for( std::size_t i=0; i<siblings.size(); ++i )
+    {
+      if( siblings[i] == &actor )
+      {
+        // Swap with next
+        ActorPtr next = siblings[i+1];
+        siblings[i+1] = &actor;
+        siblings[i] = next;
+        changed = true;
+        break;
+      }
+    }
+  }
+  return changed;
+}
+
+bool Actor::SiblingHandler::Lower(ActorContainer& siblings, Actor& actor)
+{
+  bool changed = false;
+  if( siblings.front() != &actor ) // If not already at beginning
+  {
+    for( std::size_t i=1; i<siblings.size(); ++i )
+    {
+      if( siblings[i] == &actor )
+      {
+        // Swap with previous
+        ActorPtr previous = siblings[i-1];
+        siblings[i-1] = &actor;
+        siblings[i] = previous;
+        changed = true;
+        break;
+      }
+    }
+  }
+  return changed;
+}
+
+bool Actor::SiblingHandler::RaiseToTop(ActorContainer& siblings, Actor& actor)
+{
+  bool changed = false;
+  if( siblings.back() != &actor ) // If not already at end
+  {
+    auto iter = std::find( siblings.begin(), siblings.end(), &actor );
+    if( iter != siblings.end() )
+    {
+      siblings.erase(iter);
+      siblings.push_back(ActorPtr(&actor));
+      changed = true;
+    }
+  }
+  return changed;
+}
+
+bool Actor::SiblingHandler::LowerToBottom(ActorContainer& siblings, Actor& actor)
+{
+  bool changed = false;
+  if( siblings.front() != &actor ) // If not already at bottom,
+  {
+    ActorPtr actorPtr(&actor); // ensure actor actor remains referenced.
+
+    auto iter = std::find( siblings.begin(), siblings.end(), &actor );
+    if( iter != siblings.end() )
+    {
+      siblings.erase(iter);
+      siblings.insert(siblings.begin(), actorPtr);
+      changed = true;
+    }
+  }
+  return changed;
+}
+
+bool Actor::SiblingHandler::RaiseAbove(ActorContainer& siblings, Actor& actor, Actor& target)
+{
+  bool raised = false;
+  if( siblings.back() != &actor && target.GetParent() == actor.GetParent() ) // If not already at top
+  {
+    ActorPtr actorPtr(&actor); // ensure actor actor remains referenced.
+
+    auto targetIter = std::find( siblings.begin(), siblings.end(), &target );
+    auto actorIter   = std::find( siblings.begin(), siblings.end(), &actor );
+    if( actorIter < targetIter )
+    {
+      siblings.erase(actorIter);
+      // Erasing early invalidates the targetIter. (Conversely, inserting first may also
+      // invalidate actorIter)
+      targetIter = std::find( siblings.begin(), siblings.end(), &target );
+      ++targetIter;
+      siblings.insert(targetIter, actorPtr);
+    }
+    raised = true;
+  }
+  return raised;
+}
+
+bool Actor::SiblingHandler::LowerBelow(ActorContainer& siblings, Actor& actor, Actor& target)
+{
+  bool lowered = false;
+
+  // If not already at bottom
+  if( siblings.front() != &actor && target.GetParent() == actor.GetParent() )
+  {
+    ActorPtr actorPtr(&actor); // ensure actor actor remains referenced.
+
+    auto targetIter = std::find( siblings.begin(), siblings.end(), &target );
+    auto actorIter   = std::find( siblings.begin(), siblings.end(), &actor );
+
+    if( actorIter > targetIter )
+    {
+      siblings.erase(actorIter); // actor only invalidates iterators at or after actor point.
+      siblings.insert(targetIter, actorPtr);
+    }
+    lowered = true;
+  }
+  return lowered;
+}
+
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/event/actors/actor-siblings.h b/dali/internal/event/actors/actor-siblings.h
new file mode 100644 (file)
index 0000000..9af67ba
--- /dev/null
@@ -0,0 +1,108 @@
+#ifndef DALI_INTERNAL_ACTOR_SIBLINGS_H
+#define DALI_INTERNAL_ACTOR_SIBLINGS_H
+/*
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use actor file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// INTERNAL INCLUDES
+#include <dali/internal/event/actors/actor-impl.h>
+
+namespace Dali
+{
+namespace Internal
+{
+
+struct Actor::SiblingHandler
+{
+  /**
+   * @brief Change the sibling order of the given actor.
+   *
+   * @param[in,out] siblings The container of siblings
+   * @param[in] actor The actor to change
+   * @param[in] order The new order for the actor
+   * @return true if order has been modified
+   */
+  static bool SetSiblingOrder( ActorContainer& siblings, Actor& actor, uint32_t order );
+
+  /**
+   * @brief Get the sibling order of the given actor.
+   *
+   * @param[in] siblings The container of siblings
+   * @param[in] actor The actor to query
+   * @return the order in the sibling array of the actor
+   */
+  static uint32_t GetSiblingOrder(const ActorContainer& siblings, const Actor& actor);
+
+  /**
+   * @brief Raise the actor within the siblings list by one
+   * @param[in,out] siblings The container of siblings
+   * @param[in] actor The actor to move
+   * @return true if order has been modified
+   */
+  static bool Raise(ActorContainer& siblings, Actor& actor);
+
+  /**
+   * @brief Lower the actor within the siblings list by one
+   * @param[in,out] siblings The container of siblings
+   * @param[in] actor The actor to move
+   * @return true if order has been modified
+   */
+  static bool Lower(ActorContainer& siblings, Actor& actor);
+
+  /**
+   * @brief Raise the actor to the top of the siblings list.
+   *
+   * @param[in,out] siblings The container of siblings
+   * @param[in] actor The actor to move
+   * @return true if order has been modified
+   */
+  static bool RaiseToTop(ActorContainer& siblings, Actor& actor);
+
+  /**
+   * @brief Lower the actor to the bottom of the siblings list.
+   *
+   * @param[in,out] siblings The container of siblings
+   * @param[in] actor The actor to move
+   * @return true if order has been modified
+   */
+  static bool LowerToBottom(ActorContainer& siblings, Actor& actor);
+
+  /**
+   * @brief Raise the actor above the target actor within the siblings list.
+   *
+   * @param[in,out] siblings The container of siblings
+   * @param[in] actor The actor to move
+   * @param[in] target The target actor
+   * @return true if order has been modified
+   */
+  static bool RaiseAbove(ActorContainer& siblings, Actor& actor, Actor& target);
+
+  /**
+   * @brief Lower the actor below the target actor within the siblings list.
+   *
+   * @param[in,out] siblings The container of siblings
+   * @param[in] actor The actor to move
+   * @param[in] target The target actor
+   * @return true if order has been modified
+   */
+  static bool LowerBelow(ActorContainer& siblings, Actor& actor, Actor& target);
+};
+
+} // namespace Internal
+
+} // namespace Dali
+
+
+#endif
index 811d3fa..6e71fec 100644 (file)
@@ -34,6 +34,7 @@
 #include <dali/internal/event/common/property-notification-impl.h>
 #include <dali/internal/event/common/stage-impl.h>
 #include <dali/internal/event/common/type-registry-impl.h>
+#include <dali/internal/common/const-string.h>
 
 using Dali::Internal::SceneGraph::AnimatableProperty;
 using Dali::Internal::SceneGraph::PropertyBase;
@@ -110,7 +111,7 @@ uint32_t Object::GetPropertyCount() const
   return count;
 }
 
-std::string Object::GetPropertyName( Property::Index index ) const
+std::string_view Object::GetPropertyName(Property::Index index) const
 {
   DALI_ASSERT_ALWAYS( index > Property::INVALID_INDEX && "Property index out of bounds" );
 
@@ -128,24 +129,24 @@ std::string Object::GetPropertyName( Property::Index index ) const
     CustomPropertyMetadata* custom = FindCustomProperty( index );
     if( custom )
     {
-      return custom->name;
+      return custom->name.GetStringView();
     }
   }
 
   DALI_LOG_ERROR( "Property index %d not found\n", index );
-  return std::string();
+  return {};
 }
 
-Property::Index Object::GetPropertyIndex( Property::Key key ) const
+Property::Index Object::GetPropertyIndex(KeyRef key) const
 {
   Property::Index index = Property::INVALID_INDEX;
 
-  if( key.type == Property::Key::STRING )
+  if(key.mType == Property::Key::STRING)
   {
     const TypeInfo* typeInfo( GetTypeInfo() );
     if ( typeInfo )
     {
-      index = typeInfo->GetPropertyIndex( key.stringKey );
+      index = typeInfo->GetPropertyIndex(key.mString);
     }
   }
 
@@ -157,8 +158,8 @@ Property::Index Object::GetPropertyIndex( Property::Key key ) const
     {
       CustomPropertyMetadata* custom = static_cast<CustomPropertyMetadata*>(*iter);
 
-      if( ( key.type == Property::Key::STRING && custom->name == key.stringKey) ||
-          ( key.type == Property::Key::INDEX && custom->key == key.indexKey ) )
+      if((key.mType == Property::Key::STRING && custom->name == key.mString) ||
+         (key.mType == Property::Key::INDEX && custom->key == key.mIndex))
       {
         if ( custom->childPropertyIndex != Property::INVALID_INDEX )
         {
@@ -334,7 +335,7 @@ void Object::SetProperty(Property::Index index, Property::Value propertyValue)
       if( !custom )
       {
         // If the child property is not registered yet, register it.
-        custom = new CustomPropertyMetadata( "", propertyValue, Property::READ_WRITE );
+        custom = new CustomPropertyMetadata({}, propertyValue, Property::READ_WRITE);
         mCustomProperties.PushBack( custom );
       }
 
@@ -347,7 +348,7 @@ void Object::SetProperty(Property::Index index, Property::Value propertyValue)
         const TypeInfo* parentTypeInfo( parent->GetTypeInfo() );
         if( parentTypeInfo )
         {
-          custom->name = parentTypeInfo->GetChildPropertyName( index );
+          custom->name = ConstString(parentTypeInfo->GetChildPropertyName(index));
         }
       }
     }
@@ -536,14 +537,14 @@ void Object::GetPropertyIndices( Property::IndexContainer& indices ) const
   }
 }
 
-Property::Index Object::RegisterProperty(std::string name, Property::Value propertyValue)
+Property::Index Object::RegisterProperty(std::string_view name, Property::Value propertyValue)
 {
-  return RegisterProperty(std::move(name), Property::INVALID_KEY, std::move(propertyValue), Property::ANIMATABLE);
+  return RegisterProperty(name, Property::INVALID_KEY, std::move(propertyValue), Property::ANIMATABLE);
 }
 
-Property::Index Object::RegisterProperty(std::string name, Property::Index key, Property::Value propertyValue)
+Property::Index Object::RegisterProperty(std::string_view name, Property::Index key, Property::Value propertyValue)
 {
-  return RegisterProperty(std::move(name), key, std::move(propertyValue), Property::ANIMATABLE);
+  return RegisterProperty(name, key, std::move(propertyValue), Property::ANIMATABLE);
 }
 
 void Object::SetProperties( const Property::Map& properties )
@@ -578,18 +579,19 @@ void Object::GetProperties( Property::Map& properties )
   }
 }
 
-Property::Index Object::RegisterProperty(std::string          name,
+Property::Index Object::RegisterProperty(std::string_view     name,
                                          Property::Value      propertyValue,
                                          Property::AccessMode accessMode)
 {
-  return RegisterProperty(std::move(name), Property::INVALID_KEY, std::move(propertyValue), accessMode);
+  return RegisterProperty(name, Property::INVALID_KEY, std::move(propertyValue), accessMode);
 }
 
-Property::Index Object::RegisterProperty(std::string          name,
+Property::Index Object::RegisterProperty(std::string_view     name,
                                          Property::Index      key,
                                          Property::Value      propertyValue,
                                          Property::AccessMode accessMode)
 {
+  auto constString = ConstString(name);
   // If property with the required key already exists, then just set it.
   Property::Index index = Property::INVALID_INDEX;
   if( key != Property::INVALID_KEY ) // Try integer key first if it's valid
@@ -598,7 +600,7 @@ Property::Index Object::RegisterProperty(std::string          name,
   }
   if( index == Property::INVALID_INDEX ) // If it wasn't valid, or doesn't exist, try name
   {
-    index = GetPropertyIndex( name );
+    index = GetPropertyIndex(constString);
   }
 
   if( index != Property::INVALID_INDEX ) // If there was a valid index found by either key, set it.
@@ -611,11 +613,11 @@ Property::Index Object::RegisterProperty(std::string          name,
     if( Property::ANIMATABLE == accessMode )
     {
       index = RegisterSceneGraphProperty(
-        name,
+        constString,
         key,
         PROPERTY_CUSTOM_START_INDEX + static_cast<Property::Index>(mCustomProperties.Count()),
         std::move(propertyValue));
-      AddUniformMapping(index, std::move(name));
+      AddUniformMapping(index, constString);
     }
     else
     {
@@ -623,7 +625,7 @@ Property::Index Object::RegisterProperty(std::string          name,
       index = PROPERTY_CUSTOM_START_INDEX + static_cast<Property::Index>( mCustomProperties.Count() );
 
       CustomPropertyMetadata* customProperty =
-        new CustomPropertyMetadata(std::move(name), std::move(propertyValue), accessMode);
+        new CustomPropertyMetadata(constString, std::move(propertyValue), accessMode);
 
       // Resolve index for the child property
       Object* parent = GetParentObject();
@@ -632,7 +634,7 @@ Property::Index Object::RegisterProperty(std::string          name,
         const TypeInfo* parentTypeInfo( parent->GetTypeInfo() );
         if( parentTypeInfo )
         {
-          Property::Index childPropertyIndex = parentTypeInfo->GetChildPropertyIndex( customProperty->name );
+          Property::Index childPropertyIndex = parentTypeInfo->GetChildPropertyIndex(customProperty->name);
           if( childPropertyIndex != Property::INVALID_INDEX )
           {
             customProperty->childPropertyIndex = childPropertyIndex;
@@ -774,7 +776,7 @@ void Object::NotifyPropertyAnimation( Animation& animation, Property::Index inde
   }
 }
 
-void Object::AddUniformMapping(Property::Index propertyIndex, std::string uniformName) const
+void Object::AddUniformMapping(Property::Index propertyIndex, ConstString uniformName) const
 {
   // Get the address of the property if it's a scene property
   const PropertyInputImpl* propertyPtr = GetSceneObjectInputProperty( propertyIndex );
@@ -802,8 +804,7 @@ void Object::AddUniformMapping(Property::Index propertyIndex, std::string unifor
   {
     const SceneGraph::PropertyOwner& sceneObject = GetSceneObject();
 
-    OwnerPointer<SceneGraph::UniformPropertyMapping> map =
-      new SceneGraph::UniformPropertyMapping(std::move(uniformName), propertyPtr);
+    SceneGraph::UniformPropertyMapping map(uniformName, propertyPtr);
     // Message takes ownership of Uniform map (and will delete it after copy)
     AddUniformMapMessage( const_cast<EventThreadServices&>(GetEventThreadServices()), sceneObject, map );
   }
@@ -812,7 +813,7 @@ void Object::AddUniformMapping(Property::Index propertyIndex, std::string unifor
 void Object::RemoveUniformMapping( const std::string& uniformName ) const
 {
   const SceneGraph::PropertyOwner& sceneObject = GetSceneObject();
-  RemoveUniformMapMessage( const_cast<EventThreadServices&>(GetEventThreadServices()), sceneObject, uniformName);
+  RemoveUniformMapMessage( const_cast<EventThreadServices&>(GetEventThreadServices()), sceneObject, ConstString(uniformName));
 }
 
 void Object::ApplyConstraint( ConstraintBase& constraint )
@@ -1066,7 +1067,7 @@ AnimatablePropertyMetadata* Object::FindAnimatableProperty( Property::Index inde
   return nullptr;
 }
 
-Property::Index Object::RegisterSceneGraphProperty( std::string name, Property::Index key, Property::Index index, Property::Value propertyValue ) const
+Property::Index Object::RegisterSceneGraphProperty(ConstString name, Property::Index key, Property::Index index, Property::Value propertyValue) const
 {
   // Create a new property
   Dali::Internal::OwnerPointer<PropertyBase> newProperty;
@@ -1147,7 +1148,7 @@ Property::Index Object::RegisterSceneGraphProperty( std::string name, Property::
   {
     DALI_ASSERT_ALWAYS( index <= PROPERTY_CUSTOM_MAX_INDEX && "Too many custom properties have been registered" );
 
-    mCustomProperties.PushBack( new CustomPropertyMetadata( std::move(name), key, std::move(propertyValue), property ) );
+    mCustomProperties.PushBack(new CustomPropertyMetadata(name, key, std::move(propertyValue), property));
   }
   else
   {
@@ -1165,7 +1166,7 @@ void Object::RegisterAnimatableProperty( const TypeInfo& typeInfo,
                                           const Property::Value* value ) const
 {
   // If the property is not a component of a base property, register the whole property itself.
-  const std::string& propertyName = typeInfo.GetPropertyName( index );
+  auto            propertyName = ConstString(typeInfo.GetPropertyName(index));
   Property::Value initialValue;
   if( value )
   {
@@ -1236,17 +1237,17 @@ void Object::ResolveChildProperties()
       {
         CustomPropertyMetadata* customProperty = static_cast<CustomPropertyMetadata*>( entry );
 
-        if( customProperty->name.empty() )
+        if(customProperty->name.IsEmpty())
         {
           if( customProperty->childPropertyIndex != Property::INVALID_INDEX )
           {
             // Resolve name for any child property with no name
-            customProperty->name = parentTypeInfo->GetChildPropertyName( customProperty->childPropertyIndex );
+            customProperty->name = ConstString(parentTypeInfo->GetChildPropertyName(customProperty->childPropertyIndex));
           }
         }
         else
         {
-          Property::Index childPropertyIndex = parentTypeInfo->GetChildPropertyIndex( customProperty->name );
+          Property::Index childPropertyIndex = parentTypeInfo->GetChildPropertyIndex(customProperty->name);
           if( childPropertyIndex != Property::INVALID_INDEX )
           {
             // Resolve index for any property with a name that matches the parent's child property name
index fffe3ee..3a65844 100644 (file)
 #include <cstdint> // uint32_t
 
 // INTERNAL INCLUDES
+#include <dali/devel-api/common/owner-container.h>
+#include <dali/devel-api/object/handle-devel.h>
+#include <dali/internal/common/const-string.h>
+#include <dali/internal/event/animation/animation-impl.h>
+#include <dali/internal/event/common/event-thread-services.h>
+#include <dali/internal/event/common/property-input-impl.h>
+#include <dali/internal/event/common/property-metadata.h>
+#include <dali/internal/update/common/property-base.h>
 #include <dali/public-api/animation/constraint.h>
 #include <dali/public-api/common/dali-vector.h>
 #include <dali/public-api/common/vector-wrapper.h>
 #include <dali/public-api/object/base-object.h>
 #include <dali/public-api/object/handle.h>
-#include <dali/public-api/object/property.h>
 #include <dali/public-api/object/property-index-ranges.h>
 #include <dali/public-api/object/property-input.h>
 #include <dali/public-api/object/property-map.h>
 #include <dali/public-api/object/property-notification.h>
-#include <dali/devel-api/common/owner-container.h>
-#include <dali/devel-api/object/handle-devel.h>
-#include <dali/internal/event/animation/animation-impl.h>
-#include <dali/internal/event/common/event-thread-services.h>
-#include <dali/internal/event/common/property-input-impl.h>
-#include <dali/internal/event/common/property-metadata.h>
-#include <dali/internal/update/common/property-base.h>
+#include <dali/public-api/object/property.h>
 
 namespace Dali
 {
@@ -64,6 +65,36 @@ using ConstraintContainer = std::vector< Dali::Constraint >;
 using ConstraintIter = ConstraintContainer::iterator;
 using ConstraintConstIter = ConstraintContainer::const_iterator;
 
+class KeyRef
+{
+public:
+  KeyRef(const Property::Key& key)
+  : mType(key.type)
+  {
+    if(mType == Property::Key::STRING)
+    {
+      mString = ConstString(key.stringKey);
+    }
+    else
+    {
+      mIndex = key.indexKey;
+    }
+  }
+  KeyRef(ConstString str)
+  : mType(Property::Key::STRING)
+  {
+    mString = str;
+  }
+  KeyRef(Property::Index index)
+  : mType(Property::Key::INDEX)
+  {
+    mIndex = index;
+  }
+  Property::Key::Type mType;
+  Property::Index     mIndex{Property::INVALID_INDEX};
+  ConstString         mString;
+};
+
 /**
  * A base class for objects which optionally provide properties.
  * The concrete derived class is responsible for implementing the property system methods.
@@ -145,12 +176,12 @@ public:
   /**
    * @copydoc Dali::Handle::GetPropertyName()
    */
-  std::string GetPropertyName( Property::Index index ) const;
+  std::string_view GetPropertyName(Property::Index index) const;
 
   /**
    * @copydoc Dali::Handle::GetPropertyIndex()
    */
-  Property::Index GetPropertyIndex( Property::Key key ) const;
+  Property::Index GetPropertyIndex(KeyRef key) const;
 
   /**
    * @copydoc Dali::Handle::IsPropertyWritable()
@@ -197,12 +228,12 @@ public:
   /**
    * @copydoc Dali::Handle::RegisterProperty()
    */
-  Property::Index RegisterProperty(std::string name, Property::Value propertyValue);
+  Property::Index RegisterProperty(std::string_view name, Property::Value propertyValue);
 
   /**
    * @copydoc Dali::Handle::RegisterProperty()
    */
-  Property::Index RegisterProperty(std::string name, Property::Index key, Property::Value propertyValue);
+  Property::Index RegisterProperty(std::string_view name, Property::Index key, Property::Value propertyValue);
 
   /**
    * @copydoc Dali::DevelHandle::SetProperties()
@@ -217,12 +248,12 @@ public:
   /**
    * @copydoc Dali::Handle::RegisterProperty(std::string name, Property::Value propertyValue, Property::AccessMode accessMode)
    */
-  Property::Index RegisterProperty(std::string name, Property::Value propertyValue, Property::AccessMode accessMode);
+  Property::Index RegisterProperty(std::string_view name, Property::Value propertyValue, Property::AccessMode accessMode);
 
   /**
    * @brief Implementing method for this override
    */
-  Property::Index RegisterProperty(std::string          name,
+  Property::Index RegisterProperty(std::string_view     name,
                                    Property::Index      key,
                                    Property::Value      propertyValue,
                                    Property::AccessMode accessMode);
@@ -273,7 +304,7 @@ public:
    * @param propertyIndex index of the property
    * @param uniformName name of the uniform (same as property name)
    */
-  void AddUniformMapping(Property::Index propertyIndex, std::string uniformName) const;
+  void AddUniformMapping(Property::Index propertyIndex, ConstString uniformName) const;
 
   /**
    * Removes uniform mapping for given property
@@ -435,7 +466,7 @@ protected:
    * @param [in] value The value of the property.
    * @return The index of the registered property or Property::INVALID_INDEX if registration failed.
    */
-  Property::Index RegisterSceneGraphProperty( std::string name, Property::Index key, Property::Index index, Property::Value propertyValue ) const;
+  Property::Index RegisterSceneGraphProperty(ConstString name, Property::Index key, Property::Index index, Property::Value propertyValue) const;
 
   /**
    * Registers animatable scene property
index 3dbf675..b6a7ed1 100644 (file)
 #include <utility>
 
 // INTERNAL INCLUDES
+#include <dali/internal/common/const-string.h>
 #include <dali/public-api/common/constants.h>
-#include <dali/public-api/object/property.h>
 #include <dali/public-api/object/property-value.h>
+#include <dali/public-api/object/property.h>
 
 namespace Dali
 {
@@ -258,14 +259,14 @@ public:
    *
    * @note A valid sceneGraphProperty is mandatory otherwise this will debug assert.
    */
-  CustomPropertyMetadata( std::string propertyName,
-                          Property::Index propertyKey,
-                          Property::Value propertyValue,
-                          const SceneGraph::PropertyBase* sceneGraphProperty )
-  : PropertyMetadata( std::move(propertyValue), sceneGraphProperty, true ),
-    name( std::move(propertyName) ),
-    key( propertyKey ),
-    childPropertyIndex( Property::INVALID_INDEX )
+  CustomPropertyMetadata(ConstString                     propertyName,
+                         Property::Index                 propertyKey,
+                         Property::Value                 propertyValue,
+                         const SceneGraph::PropertyBase* sceneGraphProperty)
+  : PropertyMetadata(std::move(propertyValue), sceneGraphProperty, true),
+    name(propertyName),
+    key(propertyKey),
+    childPropertyIndex(Property::INVALID_INDEX)
   {
     DALI_ASSERT_DEBUG( sceneGraphProperty && "Uninitialized scene-graph property" );
   }
@@ -278,13 +279,13 @@ public:
    *
    * @note The access mode MUST NOT be animatable otherwise this will debug assert.
    */
-  CustomPropertyMetadata( std::string propertyName,
-                          Property::Value propertyValue,
-                          Property::AccessMode accessMode )
-  : PropertyMetadata( std::move(propertyValue), nullptr, ( accessMode != Property::READ_ONLY ) ),
-    name( std::move(propertyName) ),
-    key( Property::INVALID_KEY ),
-    childPropertyIndex( Property::INVALID_INDEX )
+  CustomPropertyMetadata(ConstString          propertyName,
+                         Property::Value      propertyValue,
+                         Property::AccessMode accessMode)
+  : PropertyMetadata(std::move(propertyValue), nullptr, (accessMode != Property::READ_ONLY)),
+    name(propertyName),
+    key(Property::INVALID_KEY),
+    childPropertyIndex(Property::INVALID_INDEX)
   {
     DALI_ASSERT_DEBUG( accessMode != Property::ANIMATABLE && "Event side only properties should not be animatable" );
   }
@@ -302,8 +303,7 @@ private:
   CustomPropertyMetadata& operator=( const CustomPropertyMetadata& );
 
 public: // Data
-
-  std::string       name;                 ///< The name of the property.
+  ConstString       name;                 ///< The name of the property.
   Property::Index   key;                  ///< The key of the property.
   Property::Index   childPropertyIndex;   ///< The index as a child property.
 };
index 7230c36..7f52423 100644 (file)
@@ -65,8 +65,8 @@ private:
 template <typename T>
 struct PropertyNameFinder
 {
-  PropertyNameFinder( const std::string& find )
-  : mFind( find )
+  PropertyNameFinder(ConstString find)
+  : mFind(find)
   {
   }
 
@@ -76,8 +76,7 @@ struct PropertyNameFinder
   }
 
 private:
-
-  const std::string& mFind;
+  ConstString mFind;
 };
 
 /**
@@ -388,13 +387,13 @@ void TypeInfo::AppendProperties( Dali::Property::IndexContainer& indices,
   }
 }
 
-const std::string& TypeInfo::GetRegisteredPropertyName( Property::Index index ) const
+std::string_view TypeInfo::GetRegisteredPropertyName(Property::Index index) const
 {
   RegisteredPropertyContainer::const_iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
                                                           PairFinder< Property::Index, RegisteredPropertyPair >( index ) );
   if ( iter != mRegisteredProperties.end() )
   {
-    return iter->second.name;
+    return iter->second.name.GetStringView();
   }
   if( GetBaseType( mBaseType, mTypeRegistry, mBaseTypeName ) )
   {
@@ -405,9 +404,9 @@ const std::string& TypeInfo::GetRegisteredPropertyName( Property::Index index )
   return empty;
 }
 
-std::string TypeInfo::GetPropertyName( Property::Index index ) const
+std::string_view TypeInfo::GetPropertyName(Property::Index index) const
 {
-  std::string propertyName;
+  std::string_view propertyName;
   // default or custom
   if ( mDefaultProperties && ( index < DEFAULT_PROPERTY_MAX_COUNT ) )
   {
@@ -423,7 +422,7 @@ std::string TypeInfo::GetPropertyName( Property::Index index ) const
                                                             PairFinder< Property::Index, RegisteredPropertyPair >( index ) );
     if ( iter != mRegisteredProperties.end() )
     {
-      return iter->second.name;
+      return iter->second.name.GetStringView();
     }
   }
   // if not our property, go to parent
@@ -498,7 +497,7 @@ void TypeInfo::AddProperty(std::string name, Property::Index index, Property::Ty
 
     if ( iter == mRegisteredProperties.end() )
     {
-      mRegisteredProperties.push_back(RegisteredPropertyPair(index, RegisteredProperty(type, setFunc, getFunc, std::move(name), Property::INVALID_INDEX, Property::INVALID_COMPONENT_INDEX)));
+      mRegisteredProperties.push_back(RegisteredPropertyPair(index, RegisteredProperty(type, setFunc, getFunc, ConstString(name), Property::INVALID_INDEX, Property::INVALID_COMPONENT_INDEX)));
     }
     else
     {
@@ -523,7 +522,7 @@ void TypeInfo::AddProperty(std::string name, Property::Index index, Property::Ty
 
     if ( iter == mRegisteredProperties.end() )
     {
-      mRegisteredProperties.push_back(RegisteredPropertyPair(index, RegisteredProperty(type, setFunc, getFunc, std::move(name), Property::INVALID_INDEX, Property::INVALID_COMPONENT_INDEX)));
+      mRegisteredProperties.push_back(RegisteredPropertyPair(index, RegisteredProperty(type, setFunc, getFunc, ConstString(name), Property::INVALID_INDEX, Property::INVALID_COMPONENT_INDEX)));
     }
     else
     {
@@ -540,7 +539,7 @@ void TypeInfo::AddAnimatableProperty(std::string name, Property::Index index, Pr
 
   if ( iter == mRegisteredProperties.end() )
   {
-    mRegisteredProperties.push_back(RegisteredPropertyPair(index, RegisteredProperty(type, std::move(name), Property::INVALID_INDEX, Property::INVALID_COMPONENT_INDEX)));
+    mRegisteredProperties.push_back(RegisteredPropertyPair(index, RegisteredProperty(type, ConstString(name), Property::INVALID_INDEX, Property::INVALID_COMPONENT_INDEX)));
   }
   else
   {
@@ -555,7 +554,7 @@ void TypeInfo::AddAnimatableProperty(std::string name, Property::Index index, Pr
 
   if ( iter == mRegisteredProperties.end() )
   {
-    mRegisteredProperties.push_back(RegisteredPropertyPair(index, RegisteredProperty(defaultValue.GetType(), std::move(name), Property::INVALID_INDEX, Property::INVALID_COMPONENT_INDEX)));
+    mRegisteredProperties.push_back(RegisteredPropertyPair(index, RegisteredProperty(defaultValue.GetType(), ConstString(name), Property::INVALID_INDEX, Property::INVALID_COMPONENT_INDEX)));
     mPropertyDefaultValues.push_back(PropertyDefaultValuePair(index, std::move(defaultValue)));
   }
   else
@@ -581,7 +580,7 @@ void TypeInfo::AddAnimatablePropertyComponent(std::string name, Property::Index
 
     if ( iter == mRegisteredProperties.end() )
     {
-      mRegisteredProperties.push_back(RegisteredPropertyPair(index, RegisteredProperty(type, std::move(name), baseIndex, componentIndex)));
+      mRegisteredProperties.push_back(RegisteredPropertyPair(index, RegisteredProperty(type, ConstString(name), baseIndex, componentIndex)));
       success = true;
     }
   }
@@ -596,7 +595,7 @@ void TypeInfo::AddChildProperty(std::string name, Property::Index index, Propert
 
   if ( iter == mRegisteredChildProperties.end() )
   {
-    mRegisteredChildProperties.push_back(RegisteredPropertyPair(index, RegisteredProperty(type, std::move(name), Property::INVALID_INDEX, Property::INVALID_COMPONENT_INDEX)));
+    mRegisteredChildProperties.push_back(RegisteredPropertyPair(index, RegisteredProperty(type, ConstString(name), Property::INVALID_INDEX, Property::INVALID_COMPONENT_INDEX)));
   }
   else
   {
@@ -617,7 +616,7 @@ uint32_t TypeInfo::GetPropertyCount() const
   return count;
 }
 
-Property::Index TypeInfo::GetPropertyIndex( const std::string& name ) const
+Property::Index TypeInfo::GetPropertyIndex(ConstString name) const
 {
   Property::Index index = Property::INVALID_INDEX;
   bool found = false;
@@ -625,9 +624,10 @@ Property::Index TypeInfo::GetPropertyIndex( const std::string& name ) const
   // check default properties
   if( mDefaultProperties )
   {
+    auto stringView = name.GetStringView();
     for( Property::Index tableIndex = 0; tableIndex < mDefaultPropertyCount; ++tableIndex )
     {
-      if(mDefaultProperties[tableIndex].name == name)
+      if(mDefaultProperties[tableIndex].name == stringView)
       {
         index = mDefaultProperties[ tableIndex ].enumIndex;
         found = true;
@@ -694,7 +694,7 @@ int32_t TypeInfo::GetComponentIndex( Property::Index index ) const
   return componentIndex;
 }
 
-Property::Index TypeInfo::GetChildPropertyIndex( const std::string& name ) const
+Property::Index TypeInfo::GetChildPropertyIndex(ConstString name) const
 {
   Property::Index index = Property::INVALID_INDEX;
 
@@ -715,14 +715,14 @@ Property::Index TypeInfo::GetChildPropertyIndex( const std::string& name ) const
   return index;
 }
 
-const std::string& TypeInfo::GetChildPropertyName( Property::Index index ) const
+std::string_view TypeInfo::GetChildPropertyName(Property::Index index) const
 {
   RegisteredPropertyContainer::const_iterator iter = find_if( mRegisteredChildProperties.begin(), mRegisteredChildProperties.end(),
                                                           PairFinder< Property::Index, RegisteredPropertyPair >( index ) );
 
   if ( iter != mRegisteredChildProperties.end() )
   {
-    return iter->second.name;
+    return iter->second.name.GetStringView();
   }
 
   if( GetBaseType( mBaseType, mTypeRegistry, mBaseTypeName ) )
@@ -733,8 +733,7 @@ const std::string& TypeInfo::GetChildPropertyName( Property::Index index ) const
 
   DALI_LOG_ERROR( "Property index %d not found\n", index );
 
-  static std::string empty;
-  return empty;
+  return {};
 }
 
 Property::Type TypeInfo::GetChildPropertyType( Property::Index index ) const
@@ -958,9 +957,9 @@ void TypeInfo::SetProperty(BaseObject* object, Property::Index index, Property::
       if( mCSharpType )
       {
         // CSharp wants a property name not an index
-        const std::string& name = (iter->second).name;
+        auto name = (iter->second).name;
 
-        iter->second.cSharpSetFunc( object,name.c_str(), const_cast< Property::Value* >(&value) );
+        iter->second.cSharpSetFunc(object, name.GetCString(), const_cast<Property::Value*>(&value));
       }
       else
       {
@@ -981,8 +980,7 @@ void TypeInfo::SetProperty(BaseObject* object, Property::Index index, Property::
 
 void TypeInfo::SetProperty(BaseObject* object, const std::string& name, Property::Value value) const
 {
-  RegisteredPropertyContainer::const_iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
-                                                              PropertyNameFinder< RegisteredPropertyPair >( name ) );
+  RegisteredPropertyContainer::const_iterator iter = find_if(mRegisteredProperties.begin(), mRegisteredProperties.end(), PropertyNameFinder<RegisteredPropertyPair>(ConstString(name)));
   if ( iter != mRegisteredProperties.end() )
   {
     DALI_ASSERT_ALWAYS( iter->second.setFunc && "Trying to write to a read-only property" );
@@ -1019,10 +1017,9 @@ Property::Value TypeInfo::GetProperty( const BaseObject *object, Property::Index
       // CSharp wants a property name not an index
       // CSharp callback can't return an object by value, it can only return a pointer
       // CSharp has ownership of the pointer contents, which is fine because we are returning by from this function by value
-      const std::string& name = (iter->second).name;
-
-      return *( iter->second.cSharpGetFunc( const_cast< BaseObject* >( object ), name.c_str()) );
+      auto name = (iter->second).name;
 
+      return *(iter->second.cSharpGetFunc(const_cast<BaseObject*>(object), name.GetCString()));
     }
     else
     {
@@ -1043,10 +1040,7 @@ Property::Value TypeInfo::GetProperty( const BaseObject *object, Property::Index
 
 Property::Value TypeInfo::GetProperty( const BaseObject *object, const std::string& name ) const
 {
-  RegisteredPropertyContainer::const_iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
-                                                            PropertyNameFinder< RegisteredPropertyPair >( name ) );
-
-
+  RegisteredPropertyContainer::const_iterator iter = find_if(mRegisteredProperties.begin(), mRegisteredProperties.end(), PropertyNameFinder<RegisteredPropertyPair>(ConstString(name)));
 
   if( iter != mRegisteredProperties.end() )
   {
index 8ea06a4..616fe8d 100644 (file)
 #include <string>
 
 // INTERNAL INCLUDES
+#include <dali/devel-api/object/csharp-type-info.h>
+#include <dali/internal/common/const-string.h>
+#include <dali/internal/event/object/default-property-metadata.h>
 #include <dali/public-api/object/base-handle.h>
 #include <dali/public-api/object/base-object.h>
-#include <dali/public-api/object/type-info.h>
 #include <dali/public-api/object/property.h>
-#include <dali/devel-api/object/csharp-type-info.h>
-#include <dali/internal/event/object/default-property-metadata.h>
+#include <dali/public-api/object/type-info.h>
 
 namespace Dali
 {
@@ -125,7 +126,7 @@ public:
    * @copydoc Dali::TypeInfo::GetPropertyName() const
    * this API exists to keep the old public API, which cannot be changed
    */
-  const std::string& GetRegisteredPropertyName( Property::Index index ) const;
+  std::string_view GetRegisteredPropertyName(Property::Index index) const;
 
   /**
    * Returns the property name for given index
@@ -133,7 +134,7 @@ public:
    * @param index of the property
    * @return name or empty string
    */
-  std::string GetPropertyName( Property::Index index ) const;
+  std::string_view GetPropertyName(Property::Index index) const;
 
   /*
    * Add an action function
@@ -226,7 +227,7 @@ public:
    * @param[in] name The name of the property.
    * @return The index associated with that name.
    */
-  Property::Index GetPropertyIndex( const std::string& name ) const;
+  Property::Index GetPropertyIndex(ConstString name) const;
 
   /**
    * Given a property index, retrieve the index of its base property.
@@ -272,14 +273,14 @@ public:
    * @param[in] name The name of the child property.
    * @return The index associated with that name.
    */
-  Property::Index GetChildPropertyIndex( const std::string& name ) const;
+  Property::Index GetChildPropertyIndex(ConstString name) const;
 
   /**
    * Retrieve the name of the child property at the given index.
    * @param[in] index The property index.
    * @return The name of the child property.
    */
-  const std::string& GetChildPropertyName( Property::Index index ) const;
+  std::string_view GetChildPropertyName(Property::Index index) const;
 
   /**
    * Retrieve the Property::Type of the child property at the given index.
@@ -337,31 +338,31 @@ private:
 
   struct RegisteredProperty
   {
-    RegisteredProperty(Property::Type propType, std::string propName, Property::Index basePropertyIndex, int32_t componentIndex)
+    RegisteredProperty(Property::Type propType, ConstString propName, Property::Index basePropertyIndex, int32_t componentIndex)
     : type(propType),
       setFunc(nullptr),
       getFunc(nullptr),
-      name(std::move(propName)),
+      name(propName),
       basePropertyIndex(basePropertyIndex),
       componentIndex(componentIndex)
     {
     }
 
-    RegisteredProperty(Property::Type propType, Dali::TypeInfo::SetPropertyFunction set, Dali::TypeInfo::GetPropertyFunction get, std::string propName, Property::Index basePropertyIndex, int componentIndex)
+    RegisteredProperty(Property::Type propType, Dali::TypeInfo::SetPropertyFunction set, Dali::TypeInfo::GetPropertyFunction get, ConstString propName, Property::Index basePropertyIndex, int componentIndex)
     : type(propType),
       setFunc(set),
       getFunc(get),
-      name(std::move(propName)),
+      name(propName),
       basePropertyIndex(basePropertyIndex),
       componentIndex(componentIndex)
     {
     }
 
-    RegisteredProperty(Property::Type propType, Dali::CSharpTypeInfo::SetPropertyFunction set, Dali::CSharpTypeInfo::GetPropertyFunction get, std::string propName, Property::Index basePropertyIndex, int componentIndex)
+    RegisteredProperty(Property::Type propType, Dali::CSharpTypeInfo::SetPropertyFunction set, Dali::CSharpTypeInfo::GetPropertyFunction get, ConstString propName, Property::Index basePropertyIndex, int componentIndex)
     : type(propType),
       cSharpSetFunc(set),
       cSharpGetFunc(get),
-      name(std::move(propName)),
+      name(propName),
       basePropertyIndex(basePropertyIndex),
       componentIndex(componentIndex)
     {
@@ -378,7 +379,7 @@ private:
       Dali::TypeInfo::GetPropertyFunction getFunc = nullptr;
       Dali::CSharpTypeInfo::GetPropertyFunction cSharpGetFunc; // only one field can be initialized but this will have same value anyways
     };
-    std::string name;
+    ConstString     name;
     Property::Index basePropertyIndex = Property::INVALID_INDEX;
     int32_t componentIndex = Property::INVALID_COMPONENT_INDEX;
   };
index 9d131c7..bce5aab 100644 (file)
@@ -215,7 +215,7 @@ void VertexBuffer::Initialize( Dali::Property::Map& formatMap )
     {
       continue;
     }
-    format->components[i].name = component.first.stringKey;
+    format->components[i].name = ConstString(component.first.stringKey);
 
     // enums are stored in the map as int
     Property::Type type = Property::Type( component.second.Get<int>() );
index e3f3e1e..e18a954 100644 (file)
@@ -11,10 +11,12 @@ SET( internal_src_files
   ${internal_src_dir}/common/image-sampler.cpp
   ${internal_src_dir}/common/image-attributes.cpp
   ${internal_src_dir}/common/fixed-size-memory-pool.cpp
+  ${internal_src_dir}/common/const-string.cpp
 
   ${internal_src_dir}/event/actors/actor-impl.cpp
   ${internal_src_dir}/event/actors/actor-property-handler.cpp
   ${internal_src_dir}/event/actors/actor-relayouter.cpp
+  ${internal_src_dir}/event/actors/actor-siblings.cpp
   ${internal_src_dir}/event/actors/custom-actor-internal.cpp
   ${internal_src_dir}/event/actors/layer-impl.cpp
   ${internal_src_dir}/event/actors/layer-list.cpp
index 9160908..68ae5e7 100644 (file)
@@ -16,8 +16,9 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-#include <dali/public-api/common/dali-vector.h>
 #include <dali/internal/common/buffer-index.h>
+#include <dali/internal/update/common/uniform-map.h>
+#include <dali/public-api/common/dali-vector.h>
 
 namespace Dali
 {
@@ -28,7 +29,7 @@ namespace SceneGraph
 class UniformMap;
 class UniformPropertyMapping;
 
-using CollectedUniformMap = Dali::Vector<const UniformPropertyMapping*>;
+using CollectedUniformMap = Dali::Vector<UniformPropertyMapping>;
 
 /**
  * This class maps uniform names to property value pointers.
index d3a2809..0f0a70a 100644 (file)
@@ -87,13 +87,13 @@ void Geometry::GetAttributeLocationFromProgram( Vector<GLint>& attributeLocation
     const uint32_t attributeCount = vertexBuffer->GetAttributeCount();
     for( uint32_t j = 0; j < attributeCount; ++j )
     {
-      const std::string& attributeName = vertexBuffer->GetAttributeName( j );
+      auto attributeName = vertexBuffer->GetAttributeName( j );
       uint32_t index = program.RegisterCustomAttribute( attributeName );
       GLint location = program.GetCustomAttributeLocation( index );
 
       if( -1 == location )
       {
-        DALI_LOG_WARNING( "Attribute not found in the shader: %s\n", attributeName.c_str() );
+        DALI_LOG_WARNING( "Attribute not found in the shader: %s\n", attributeName.GetCString() );
       }
 
       attributeLocation.PushBack( location );
index cb316e8..518c1de 100644 (file)
@@ -255,19 +255,19 @@ void Renderer::SetUniforms( BufferIndex bufferIndex, const SceneGraph::NodeDataP
     uint32_t mapIndex = 0;
     for(; mapIndex < uniformMap.Count() ; ++mapIndex )
     {
-      mUniformIndexMap[mapIndex].propertyValue = uniformMap[mapIndex]->propertyPtr;
-      mUniformIndexMap[mapIndex].uniformIndex = program.RegisterUniform( uniformMap[mapIndex]->uniformName );
+      mUniformIndexMap[mapIndex].propertyValue = uniformMap[mapIndex].propertyPtr;
+      mUniformIndexMap[mapIndex].uniformIndex  = program.RegisterUniform(uniformMap[mapIndex].uniformName);
     }
 
     for( uint32_t nodeMapIndex = 0; nodeMapIndex < uniformMapNode.Count() ; ++nodeMapIndex )
     {
-      uint32_t uniformIndex = program.RegisterUniform( uniformMapNode[nodeMapIndex]->uniformName );
+      uint32_t uniformIndex = program.RegisterUniform(uniformMapNode[nodeMapIndex].uniformName);
       bool found(false);
       for( uint32_t i = 0; i<uniformMap.Count(); ++i )
       {
         if( mUniformIndexMap[i].uniformIndex == uniformIndex )
         {
-          mUniformIndexMap[i].propertyValue = uniformMapNode[nodeMapIndex]->propertyPtr;
+          mUniformIndexMap[i].propertyValue = uniformMapNode[nodeMapIndex].propertyPtr;
           found = true;
           break;
         }
@@ -275,7 +275,7 @@ void Renderer::SetUniforms( BufferIndex bufferIndex, const SceneGraph::NodeDataP
 
       if( !found )
       {
-        mUniformIndexMap[mapIndex].propertyValue = uniformMapNode[nodeMapIndex]->propertyPtr;
+        mUniformIndexMap[mapIndex].propertyValue = uniformMapNode[nodeMapIndex].propertyPtr;
         mUniformIndexMap[mapIndex].uniformIndex = uniformIndex;
         ++mapIndex;
       }
@@ -729,16 +729,16 @@ bool Renderer::Updated(BufferIndex bufferIndex, const SceneGraph::NodeDataProvid
 
   uint64_t hash = 0xc70f6907UL;
   const SceneGraph::CollectedUniformMap& uniformMapNode = node->GetUniformMap( bufferIndex );
-  for (const auto* uniformProperty : uniformMapNode)
+  for(const auto& uniformProperty : uniformMapNode)
   {
-    hash = uniformProperty->propertyPtr->Hash(bufferIndex, hash);
+    hash = uniformProperty.propertyPtr->Hash(bufferIndex, hash);
   }
 
   const SceneGraph::UniformMapDataProvider& uniformMapDataProvider = mRenderDataProvider->GetUniformMap();
   const SceneGraph::CollectedUniformMap& uniformMap = uniformMapDataProvider.GetUniformMap( bufferIndex );
-  for (const auto* uniformProperty : uniformMap)
+  for(const auto& uniformProperty : uniformMap)
   {
-    hash = uniformProperty->propertyPtr->Hash(bufferIndex, hash);
+    hash = uniformProperty.propertyPtr->Hash(bufferIndex, hash);
   }
 
   if (mUniformsHash != hash)
index f2b02b8..37d2aeb 100644 (file)
@@ -24,6 +24,7 @@
 #include <dali/internal/common/owner-pointer.h>
 #include <dali/internal/render/renderers/render-sampler.h>
 #include <dali/internal/render/gl-resources/gpu-buffer.h>
+#include <dali/internal/common/const-string.h>
 
 namespace Dali
 {
@@ -38,7 +39,7 @@ public:
 
   struct Component
   {
-    std::string    name;
+    ConstString    name;
     uint32_t       offset;
     uint32_t       size;
     Property::Type type;
@@ -124,7 +125,7 @@ public:
    * @param[in] index The index of the attribute
    * @return The name of the attribute
    */
-  inline const std::string& GetAttributeName( uint32_t index ) const
+  inline ConstString GetAttributeName( uint32_t index ) const
   {
     DALI_ASSERT_DEBUG( mFormat && "Format should be set ");
     return mFormat->components[index].name;
index 246d0fe..fe333dd 100755 (executable)
@@ -144,7 +144,7 @@ GLint Program::GetAttribLocation( AttribType type )
   return GetCustomAttributeLocation( type );
 }
 
-uint32_t Program::RegisterCustomAttribute( const std::string& name )
+uint32_t Program::RegisterCustomAttribute( ConstString name )
 {
   uint32_t index = 0;
   // find the value from cache
@@ -171,17 +171,17 @@ GLint Program::GetCustomAttributeLocation( uint32_t attributeIndex )
 
   if( location == ATTRIB_UNKNOWN )
   {
-    location = CHECK_GL( mGlAbstraction, mGlAbstraction.GetAttribLocation( mProgramId, mAttributeLocations[ attributeIndex ].first.c_str() ) );
+    location = CHECK_GL( mGlAbstraction, mGlAbstraction.GetAttribLocation( mProgramId, mAttributeLocations[ attributeIndex ].first.GetCString() ) );
 
     mAttributeLocations[ attributeIndex ].second = location;
-    LOG_GL( "GetAttributeLocation(program=%d,%s) = %d\n", mProgramId, mAttributeLocations[ attributeIndex ].first.c_str(), mAttributeLocations[ attributeIndex ].second );
+    LOG_GL( "GetAttributeLocation(program=%d,%s) = %d\n", mProgramId, mAttributeLocations[ attributeIndex ].first.GetCString(), mAttributeLocations[ attributeIndex ].second );
   }
 
   return location;
 }
 
 
-uint32_t Program::RegisterUniform( const std::string& name )
+uint32_t Program::RegisterUniform( ConstString name )
 {
   uint32_t index = 0;
   // find the value from cache
@@ -208,10 +208,10 @@ GLint Program::GetUniformLocation( uint32_t uniformIndex )
 
   if( location == UNIFORM_NOT_QUERIED )
   {
-    location = CHECK_GL( mGlAbstraction, mGlAbstraction.GetUniformLocation( mProgramId, mUniformLocations[ uniformIndex ].first.c_str() ) );
+    location = CHECK_GL( mGlAbstraction, mGlAbstraction.GetUniformLocation( mProgramId, mUniformLocations[ uniformIndex ].first.GetCString() ) );
 
     mUniformLocations[ uniformIndex ].second = location;
-    LOG_GL( "GetUniformLocation(program=%d,%s) = %d\n", mProgramId, mUniformLocations[ uniformIndex ].first.c_str(), mUniformLocations[ uniformIndex ].second );
+    LOG_GL( "GetUniformLocation(program=%d,%s) = %d\n", mProgramId, mUniformLocations[ uniformIndex ].first.GetCString(), mUniformLocations[ uniformIndex ].second );
   }
 
   return location;
@@ -645,7 +645,7 @@ Program::Program( ProgramCache& cache, Internal::ShaderDataPtr shaderData, bool
   mAttributeLocations.reserve( ATTRIB_TYPE_LAST );
   for( uint32_t i = 0; i < ATTRIB_TYPE_LAST; ++i )
   {
-    RegisterCustomAttribute( gStdAttribs[i] );
+    RegisterCustomAttribute( ConstString(gStdAttribs[i]) );
   }
 
   // reserve space for standard uniforms
@@ -653,7 +653,7 @@ Program::Program( ProgramCache& cache, Internal::ShaderDataPtr shaderData, bool
   // reset built in uniform names in cache
   for( uint32_t i = 0; i < UNIFORM_TYPE_LAST; ++i )
   {
-    RegisterUniform( gStdUniforms[ i ] );
+    RegisterUniform( ConstString(gStdUniforms[ i ]) );
   }
 
   // reset values
index 0913989..acdec12 100644 (file)
@@ -27,6 +27,7 @@
 #include <dali/public-api/object/ref-object.h>
 #include <dali/integration-api/gl-abstraction.h>
 #include <dali/internal/common/shader-data.h>
+#include <dali/internal/common/const-string.h>
 
 namespace Dali
 {
@@ -130,7 +131,7 @@ public:
    * @param [in] name attribute name
    * @return the index of the attribute name in local cache
    */
-  uint32_t RegisterCustomAttribute( const std::string& name );
+  uint32_t RegisterCustomAttribute( ConstString name );
 
   /**
    * Gets the location of a pre-registered attribute.
@@ -144,7 +145,7 @@ public:
    * @param [in] name uniform name
    * @return the index of the uniform name in local cache
    */
-  uint32_t RegisterUniform( const std::string& name );
+  uint32_t RegisterUniform( ConstString name );
 
   /**
    * Gets the location of a pre-registered uniform.
@@ -373,7 +374,7 @@ private:  // Data
   Internal::ShaderDataPtr mProgramData;       ///< Shader program source and binary (when compiled & linked or loaded)
 
   // location caches
-  using NameLocationPair = std::pair<std::string, GLint>;
+  using NameLocationPair = std::pair<ConstString, GLint>;
   using Locations        = std::vector<NameLocationPair>;
 
   Locations mAttributeLocations;      ///< attribute location cache
index 10a735f..1ac2e43 100644 (file)
@@ -430,15 +430,17 @@ void Animation::UpdateAnimators( BufferIndex bufferIndex, bool bake, bool animat
   const Vector2 playRange( mPlayRange * mDurationSeconds );
   float elapsedSecondsClamped = Clamp( mElapsedSeconds, playRange.x, playRange.y );
 
-  //Remove animators whose PropertyOwner has been destroyed
-  mAnimators.Erase(std::remove_if(mAnimators.begin(),
-                                  mAnimators.end(),
-                                  [](auto animator) { return animator->Orphan(); }),
-                   mAnimators.end());
+  bool cleanup = false;
 
   //Loop through all animators
   for(auto& animator : mAnimators)
   {
+    if(animator->Orphan())
+    {
+      cleanup = true;
+      continue;
+    }
+
     bool applied(true);
     if(animator->IsEnabled())
     {
@@ -477,6 +479,15 @@ void Animation::UpdateAnimators( BufferIndex bufferIndex, bool bake, bool animat
       INCREASE_COUNTER(PerformanceMonitor::ANIMATORS_APPLIED);
     }
   }
+
+  if(cleanup)
+  {
+    //Remove animators whose PropertyOwner has been destroyed
+    mAnimators.Erase(std::remove_if(mAnimators.begin(),
+                                    mAnimators.end(),
+                                    [](auto& animator) { return animator->Orphan(); }),
+                     mAnimators.end());
+  }
 }
 
 } // namespace SceneGraph
index db5759d..60d9531 100644 (file)
@@ -26,6 +26,7 @@
 #include <dali/internal/event/common/property-input-impl.h>
 #include <dali/internal/update/common/property-owner.h>
 #include <dali/internal/update/animation/scene-graph-constraint-base.h>
+#include <dali/internal/common/const-string.h>
 
 namespace Dali
 {
@@ -253,9 +254,9 @@ inline void RemoveConstraintMessage( EventThreadServices& eventThreadServices, c
   new (slot) LocalType( &owner, &PropertyOwner::RemoveConstraint, &constraint );
 }
 
-inline void AddUniformMapMessage( EventThreadServices& eventThreadServices, const PropertyOwner& owner, OwnerPointer< UniformPropertyMapping >& map )
+inline void AddUniformMapMessage(EventThreadServices& eventThreadServices, const PropertyOwner& owner, UniformPropertyMapping map)
 {
-  using LocalType = MessageValue1<PropertyOwner, OwnerPointer<UniformPropertyMapping> >;
+  using LocalType = MessageValue1<PropertyOwner, UniformPropertyMapping>;
 
   // Reserve some memory inside the message queue
   uint32_t* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
@@ -263,9 +264,9 @@ inline void AddUniformMapMessage( EventThreadServices& eventThreadServices, cons
   new (slot) LocalType( &owner, &PropertyOwner::AddUniformMapping, map );
 }
 
-inline void RemoveUniformMapMessage( EventThreadServices& eventThreadServices, const PropertyOwner& owner, const std::string& uniformName )
+inline void RemoveUniformMapMessage( EventThreadServices& eventThreadServices, const PropertyOwner& owner, ConstString uniformName )
 {
-  using LocalType = MessageValue1<PropertyOwner, std::string>;
+  using LocalType = MessageValue1<PropertyOwner, ConstString>;
 
   // Reserve some memory inside the message queue
   uint32_t* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
index 8d560ca..bd23fe2 100644 (file)
@@ -24,6 +24,7 @@
 // INTERNAL INCLUDES
 #include <dali/public-api/common/dali-common.h>
 #include <dali/internal/update/animation/scene-graph-constraint-base.h>
+#include <dali/internal/common/const-string.h>
 
 namespace Dali
 {
@@ -152,12 +153,12 @@ PropertyOwner::PropertyOwner()
 {
 }
 
-void PropertyOwner::AddUniformMapping( OwnerPointer< UniformPropertyMapping >& map )
+void PropertyOwner::AddUniformMapping(const UniformPropertyMapping& map)
 {
-  mUniformMaps.Add( map.Release() );
+  mUniformMaps.Add(map);
 }
 
-void PropertyOwner::RemoveUniformMapping( const std::string& uniformName )
+void PropertyOwner::RemoveUniformMapping( const ConstString& uniformName )
 {
   mUniformMaps.Remove( uniformName );
 }
index d8f3330..2e6c7da 100644 (file)
@@ -26,6 +26,7 @@
 #include <dali/internal/update/common/scene-graph-buffers.h>
 #include <dali/internal/update/common/uniform-map.h>
 #include <dali/internal/update/animation/scene-graph-constraint-declarations.h>
+#include <dali/internal/common/const-string.h>
 
 
 namespace Dali
@@ -200,12 +201,12 @@ public:
   /**
    * @copydoc UniformMap::Add
    */
-  virtual void AddUniformMapping( OwnerPointer< UniformPropertyMapping >& map );
+  virtual void AddUniformMapping(const UniformPropertyMapping& map);
 
   /**
    * @copydoc UniformMap::Remove
    */
-  virtual void RemoveUniformMapping( const std::string& uniformName );
+  virtual void RemoveUniformMapping( const ConstString& uniformName );
 
   /**
    * Get the mappings table
index c68ac13..6f60e38 100644 (file)
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+#include <algorithm>
+
 // CLASS HEADER
 #include <dali/internal/update/common/uniform-map.h>
 
@@ -23,12 +25,6 @@ namespace Internal
 {
 namespace SceneGraph
 {
-UniformMap::UniformMap() = default;
-
-UniformMap::~UniformMap()
-{
-  // Nothing to do - let the owner container delete the maps
-}
 
 void UniformMap::AddObserver( Observer& observer )
 {
@@ -68,84 +64,46 @@ void UniformMap::MappingChanged()
   }
 }
 
-void UniformMap::Add( UniformPropertyMapping* newMap )
+void UniformMap::Add(UniformPropertyMapping newMap)
 {
-  UniformPropertyMapping::Hash nameHash = CalculateHash( newMap->uniformName );
-
-  bool found = false;
+  auto iter = std::find_if(mUniformMaps.Begin(),
+                           mUniformMaps.End(),
+                           [&](auto& element) { return element.uniformName == newMap.uniformName; });
 
-  for( UniformMapIter iter = mUniformMaps.Begin() ;
-       iter != mUniformMaps.End() ;
-       ++iter )
+  if(iter != mUniformMaps.End())
   {
-    UniformPropertyMapping* map = *iter;
-    if( map->uniformNameHash == nameHash )
-    {
-      if( map->uniformName == newMap->uniformName )
-      {
-        found = true;
-        // Mapping already exists - update it.
-        map->propertyPtr = newMap->propertyPtr;
-        break;
-      }
-    }
+    // Mapping already exists - update it.
+    (*iter).propertyPtr = newMap.propertyPtr;
   }
-
-  if( found == false )
+  else
   {
-    // Take ownership of the new map
+    // add the new map.
     mUniformMaps.PushBack(newMap);
   }
 
   MappingChanged();
 }
 
-void UniformMap::Remove( const std::string& uniformName )
+void UniformMap::Remove( ConstString uniformName )
 {
-  UniformPropertyMapping::Hash nameHash = CalculateHash( uniformName );
-
-  bool found=false;
+  auto iter = std::find_if(mUniformMaps.Begin(),
+                           mUniformMaps.End(),
+                           [&](auto& element) { return element.uniformName == uniformName; });
 
-  for( UniformMapIter iter = mUniformMaps.Begin() ;
-       iter != mUniformMaps.End() ;
-       ++iter )
-  {
-    UniformPropertyMapping* map = *iter;
-    if( map->uniformNameHash == nameHash )
-    {
-      if( map->uniformName == uniformName )
-      {
-        mUniformMaps.Erase( iter );
-        found = true;
-        break;
-      }
-    }
-  }
-
-  if( found )
+  if(iter != mUniformMaps.End())
   {
+    mUniformMaps.Erase(iter);
     MappingChanged();
   }
 }
 
-const PropertyInputImpl* UniformMap::Find( const std::string& uniformName )
+const PropertyInputImpl* UniformMap::Find(ConstString uniformName)
 {
-  UniformPropertyMapping::Hash nameHash = CalculateHash( uniformName );
+  auto iter = std::find_if(mUniformMaps.Begin(),
+                           mUniformMaps.End(),
+                           [&](auto& element) { return element.uniformName == uniformName; });
 
-  for( UniformMapIter iter = mUniformMaps.Begin() ;
-       iter != mUniformMaps.End() ;
-       ++iter )
-  {
-    UniformPropertyMapping* map = *iter;
-    if( map->uniformNameHash == nameHash )
-    {
-      if( map->uniformName == uniformName )
-      {
-        return map->propertyPtr;
-      }
-    }
-  }
-  return nullptr;
+  return (iter != mUniformMaps.End()) ? (*iter).propertyPtr : nullptr;
 }
 
 UniformMap::SizeType UniformMap::Count() const
@@ -155,7 +113,7 @@ UniformMap::SizeType UniformMap::Count() const
 
 const UniformPropertyMapping& UniformMap::operator[]( UniformMap::SizeType index ) const
 {
-  return *mUniformMaps[index];
+  return mUniformMaps[index];
 }
 
 } // SceneGraph
index 2df39e2..4978e7c 100644 (file)
@@ -24,6 +24,7 @@
 // INTERNAL INCLUDES
 #include <dali/devel-api/common/hash.h>
 #include <dali/devel-api/common/owner-container.h>
+#include <dali/internal/common/const-string.h>
 
 namespace Dali
 {
@@ -40,29 +41,19 @@ namespace SceneGraph
 class UniformPropertyMapping
 {
 public:
-  using Hash = unsigned long;
-
   /**
    * Constructor
    */
-  UniformPropertyMapping(std::string theUniformName, const PropertyInputImpl* thePropertyPtr)
+  UniformPropertyMapping(ConstString theUniformName, const PropertyInputImpl* thePropertyPtr)
   : propertyPtr(thePropertyPtr),
-    uniformName(std::move(theUniformName)),
-    uniformNameHash(Dali::CalculateHash(theUniformName))
-  {
-  }
-
-  UniformPropertyMapping()
-  : propertyPtr( nullptr ),
-    uniformName( "" ),
-    uniformNameHash( 0 )
+    uniformName(theUniformName)
   {
   }
 
+  UniformPropertyMapping() = default;
 
-  const PropertyInputImpl* propertyPtr;
-  std::string uniformName;
-  Hash uniformNameHash;
+  const PropertyInputImpl* propertyPtr{nullptr};
+  ConstString uniformName;
 };
 
 /**
@@ -96,16 +87,6 @@ public:
   };
 
   /**
-   * Constructor
-   */
-  UniformMap();
-
-  /**
-   * Destructor
-   */
-  ~UniformMap();
-
-  /**
    * Add an observer that watches for changes in the mappings
    */
   void AddObserver( Observer& observer );
@@ -118,18 +99,18 @@ public:
   /**
    * Add a map to the mappings table.
    */
-  void Add( UniformPropertyMapping* map );
+  void Add(UniformPropertyMapping map);
 
   /**
    * Remove a map from the mappings table
    */
-  void Remove( const std::string& uniformName );
+  void Remove( ConstString uniformName );
 
   /**
    * Find a property given the uniform name.
    * @return The address of the property if it's in the map, or NULL otherwise.
    */
-  const PropertyInputImpl* Find( const std::string& uniformName );
+  const PropertyInputImpl* Find( ConstString uniformName );
 
   /**
    * Get the count of uniforms in the map
@@ -151,7 +132,7 @@ private:
   void MappingChanged();
 
 private:
-  using UniformMapContainer = OwnerContainer<UniformPropertyMapping*>;
+  using UniformMapContainer = Dali::Vector<UniformPropertyMapping>;
   using UniformMapIter      = UniformMapContainer::Iterator;
   using Observers           = Dali::Vector<Observer*>;
   using ObserversIter       = Observers::Iterator;
old mode 100755 (executable)
new mode 100644 (file)
index ae6dd7f..86b4864
@@ -176,13 +176,13 @@ void Node::SetRoot(bool isRoot)
   mIsRoot = isRoot;
 }
 
-void Node::AddUniformMapping( OwnerPointer< UniformPropertyMapping >& map )
+void Node::AddUniformMapping(const UniformPropertyMapping& map)
 {
   PropertyOwner::AddUniformMapping( map );
   mRegenerateUniformMap = 2;
 }
 
-void Node::RemoveUniformMapping( const std::string& uniformName )
+void Node::RemoveUniformMapping( const ConstString& uniformName )
 {
   PropertyOwner::RemoveUniformMapping( uniformName );
   mRegenerateUniformMap = 2;
@@ -204,7 +204,7 @@ void Node::PrepareRender( BufferIndex bufferIndex )
 
       for( UniformMap::SizeType i = 0, count=mUniformMaps.Count(); i<count; ++i )
       {
-        localMap.PushBack( &mUniformMaps[i] );
+        localMap.PushBack(mUniformMaps[i]);
       }
     }
     else if( mRegenerateUniformMap == 1 )
index 7e5a05d..77bd5ac 100644 (file)
@@ -798,12 +798,12 @@ public:
   /**
    * @copydoc UniformMap::Add
    */
-  void AddUniformMapping( OwnerPointer< UniformPropertyMapping >& map ) override;
+  void AddUniformMapping(const UniformPropertyMapping& map) override;
 
   /**
    * @copydoc UniformMap::Remove
    */
-  void RemoveUniformMapping( const std::string& uniformName ) override;
+  void RemoveUniformMapping( const ConstString& uniformName ) override;
 
   /**
    * @copydoc Dali::Internal::SceneGraph::PropertyOwner::IsAnimationPossible
index cce7464..9fde39b 100644 (file)
@@ -29,6 +29,7 @@
 #include <dali/internal/render/renderers/render-geometry.h>
 #include <dali/internal/render/shaders/program.h>
 #include <dali/internal/render/shaders/scene-graph-shader.h>
+#include <dali/internal/common/blending-options.h>
 
 namespace Dali
 {
@@ -60,25 +61,20 @@ void AddMappings( CollectedUniformMap& localMap, const UniformMap& uniformMap )
 
   for( UniformMap::SizeType i = 0, count=uniformMap.Count(); i<count; ++i )
   {
-    UniformPropertyMapping::Hash nameHash = uniformMap[i].uniformNameHash;
     bool found = false;
 
     for( CollectedUniformMap::Iterator iter = localMap.Begin() ; iter != localMap.End() ; ++iter )
     {
-      const UniformPropertyMapping* map = (*iter);
-      if( map->uniformNameHash == nameHash )
+      const UniformPropertyMapping& map = (*iter);
+      if(map.uniformName == uniformMap[i].uniformName)
       {
-        if( map->uniformName == uniformMap[i].uniformName )
-        {
-          found = true;
-          break;
-        }
+        found = true;
+        break;
       }
     }
     if( !found )
     {
-      // it's a new mapping. Add raw ptr to temporary list
-      newUniformMappings.PushBack( &uniformMap[i] );
+      newUniformMappings.PushBack(uniformMap[i]);
     }
   }
 
@@ -91,7 +87,7 @@ void AddMappings( CollectedUniformMap& localMap, const UniformMap& uniformMap )
          iter != end ;
          ++iter )
     {
-      const UniformPropertyMapping* map = (*iter);
+      const UniformPropertyMapping& map = (*iter);
       localMap.PushBack( map );
     }
   }
@@ -192,9 +188,19 @@ bool Renderer::PrepareRender( BufferIndex updateBufferIndex )
     if( mRegenerateUniformMap == REGENERATE_UNIFORM_MAP)
     {
       CollectedUniformMap& localMap = mCollectedUniformMap[ updateBufferIndex ];
-      localMap.Resize(0);
+      localMap.Clear();
 
       const UniformMap& rendererUniformMap = PropertyOwner::GetUniformMap();
+
+      auto size = rendererUniformMap.Count();
+
+      if(mShader)
+      {
+        size += mShader->GetUniformMap().Count();
+      }
+
+      localMap.Reserve(size);
+
       AddMappings( localMap, rendererUniformMap );
 
       if( mShader )
@@ -710,6 +716,12 @@ Renderer::OpacityType Renderer::GetOpacityType( BufferIndex updateBufferIndex, c
     }
     case BlendMode::AUTO:
     {
+      if(BlendingOptions::IsAdvancedBlendEquationIncluded(mBlendBitmask))
+      {
+        opacityType = Renderer::TRANSLUCENT;
+        break;
+      }
+
       bool shaderRequiresBlending( mShader->HintEnabled( Dali::Shader::Hint::OUTPUT_IS_TRANSPARENT ) );
       if( shaderRequiresBlending || ( mTextureSet && mTextureSet->HasAlpha() ) )
       {
@@ -726,6 +738,7 @@ Renderer::OpacityType Renderer::GetOpacityType( BufferIndex updateBufferIndex, c
       {
         opacityType = Renderer::TRANSLUCENT;
       }
+
       break;
     }
     case BlendMode::OFF: // the renderer should never use blending
index 8952092..990cd8f 100644 (file)
 
 namespace Dali
 {
-namespace
-{
-constexpr uint32_t BitMaskOfN(uint32_t bits)
-{
-  return (1 << bits) - 1;
-}
-
-} // unnamed namespace
-
 AlphaFunction::AlphaFunction()
-: mBezierControlPoints(Vector4::ZERO),
-  mCustom(nullptr),
-  mBuiltin(DEFAULT),
-  mMode(BUILTIN_FUNCTION)
+: mMode(BUILTIN_FUNCTION),
+  mBuiltin(DEFAULT)
 {
 }
 
 AlphaFunction::AlphaFunction(BuiltinFunction function)
-: mBezierControlPoints(Vector4::ZERO),
-  mCustom(nullptr),
-  mBuiltin(function),
-  mMode(BUILTIN_FUNCTION)
+: mMode(BUILTIN_FUNCTION),
+  mBuiltin(function)
 {
 }
 
 AlphaFunction::AlphaFunction(AlphaFunctionPrototype function)
-: mBezierControlPoints(Vector4::ZERO),
-  mCustom(function),
+: mMode(CUSTOM_FUNCTION),
   mBuiltin(DEFAULT),
-  mMode(CUSTOM_FUNCTION)
+  mCustom(function)
 {
 }
 
 AlphaFunction::AlphaFunction(const Vector2& controlPoint0, const Vector2& controlPoint1)
-: mBezierControlPoints(
+: mMode(BEZIER),
+  mBuiltin(DEFAULT),
+  mBezierControlPoints(
     Vector4(Clamp(controlPoint0.x, 0.0f, 1.0f),
             controlPoint0.y,
             Clamp(controlPoint1.x, 0.0f, 1.0f),
-            controlPoint1.y)),
-  mCustom(nullptr),
-  mBuiltin(DEFAULT),
-  mMode(BEZIER)
+            controlPoint1.y))
 {
 }
 
 Vector4 AlphaFunction::GetBezierControlPoints() const
 {
-  return mBezierControlPoints;
+  return (mMode == BEZIER) ? mBezierControlPoints : Vector4::ZERO;
 }
 
 AlphaFunctionPrototype AlphaFunction::GetCustomFunction() const
 {
-  return mCustom;
+  return (mMode == CUSTOM_FUNCTION) ? mCustom : nullptr;
 }
 
 AlphaFunction::BuiltinFunction AlphaFunction::GetBuiltinFunction() const
 {
-  return static_cast<AlphaFunction::BuiltinFunction>(mBuiltin & BitMaskOfN(Log<COUNT>::value + 1));
+  return mBuiltin;
 }
 
 AlphaFunction::Mode AlphaFunction::GetMode() const
 {
-  return static_cast<AlphaFunction::Mode>(mMode & BitMaskOfN(2));
+  return mMode;
 }
 
 } // namespace Dali
index 48c32b0..3e006dc 100644 (file)
@@ -18,6 +18,9 @@
  *
  */
 
+// EXTERNAL INCLUDES
+#include <cstdint> // uint8_t
+
 // INTERNAL INCLUDES
 #include <dali/public-api/common/constants.h>
 #include <dali/public-api/common/dali-common.h>
@@ -49,7 +52,7 @@ public:
    * @brief Enumeration for built-in alpha functions.
    * @SINCE_1_0.0
    */
-  enum BuiltinFunction
+  enum BuiltinFunction : uint8_t
   {
     DEFAULT,          ///< Linear @SINCE_1_0.0
     LINEAR,           ///< No transformation @SINCE_1_0.0
@@ -72,7 +75,7 @@ public:
    * @brief Enumeration for all possible functioning modes for the alpha function.
    * @SINCE_1_0.0
    */
-  enum Mode
+  enum Mode : uint8_t
   {
     BUILTIN_FUNCTION, ///< The user has specified a built-in function @SINCE_1_0.0
     CUSTOM_FUNCTION,  ///< The user has provided a custom function @SINCE_1_0.0
@@ -148,10 +151,14 @@ public:
   Mode GetMode() const;
 
 private:
-  Vector4                mBezierControlPoints;             //< Control points for the bezier alpha function
-  AlphaFunctionPrototype mCustom;                          //< Pointer to an alpha function
-  BuiltinFunction        mBuiltin : Log<COUNT>::value + 1; //< Enum indicating the built-in alpha function
-  Mode                   mMode : 2;                        //< Enum indicating the functioning mode of the AlphaFunction
+  Mode            mMode;    //< Enum indicating the functioning mode of the AlphaFunction
+  BuiltinFunction mBuiltin; //< Enum indicating the built-in alpha function
+
+  union
+  {
+    Vector4                mBezierControlPoints; //< Control points for the bezier alpha function
+    AlphaFunctionPrototype mCustom;              //< Pointer to an alpha function
+  };
 };
 
 /**
index 371199a..6316ca2 100644 (file)
@@ -27,7 +27,7 @@ namespace Dali
 {
 const uint32_t    CORE_MAJOR_VERSION = 2;
 const uint32_t    CORE_MINOR_VERSION = 0;
-const uint32_t    CORE_MICRO_VERSION = 3;
+const uint32_t    CORE_MICRO_VERSION = 4;
 const char* const CORE_BUILD_DATE    = __DATE__ " " __TIME__;
 
 #ifdef DEBUG_ENABLED
index b09c0e5..08b331b 100644 (file)
@@ -67,7 +67,7 @@ uint32_t Handle::GetPropertyCount() const
 
 std::string Handle::GetPropertyName(Property::Index index) const
 {
-  return GetImplementation(*this).GetPropertyName(index);
+  return std::string(GetImplementation(*this).GetPropertyName(index));
 }
 
 Property::Index Handle::GetPropertyIndex(Property::Key key) const
@@ -100,19 +100,19 @@ void Handle::SetProperty(Property::Index index, Property::Value propertyValue)
   GetImplementation(*this).SetProperty(index, std::move(propertyValue));
 }
 
-Property::Index Handle::RegisterProperty(std::string name, Property::Value propertyValue)
+Property::Index Handle::RegisterProperty(std::string_view name, Property::Value propertyValue)
 {
-  return GetImplementation(*this).RegisterProperty(std::move(name), std::move(propertyValue));
+  return GetImplementation(*this).RegisterProperty(name, std::move(propertyValue));
 }
 
-Property::Index Handle::RegisterProperty(Property::Index key, std::string name, Property::Value propertyValue)
+Property::Index Handle::RegisterProperty(Property::Index key, std::string_view name, Property::Value propertyValue)
 {
-  return GetImplementation(*this).RegisterProperty(std::move(name), key, std::move(propertyValue));
+  return GetImplementation(*this).RegisterProperty(name, key, std::move(propertyValue));
 }
 
-Property::Index Handle::RegisterProperty(std::string name, Property::Value propertyValue, Property::AccessMode accessMode)
+Property::Index Handle::RegisterProperty(std::string_view name, Property::Value propertyValue, Property::AccessMode accessMode)
 {
-  return GetImplementation(*this).RegisterProperty(std::move(name), std::move(propertyValue), accessMode);
+  return GetImplementation(*this).RegisterProperty(name, std::move(propertyValue), accessMode);
 }
 
 Property::Value Handle::GetProperty(Property::Index index) const
index d7dc63f..eb65c5a 100644 (file)
@@ -289,7 +289,7 @@ public:
    *       - Property::ROTATION
    * @note If a property with the desired name already exists, then the value given is just set.
    */
-  Property::Index RegisterProperty(std::string name, Property::Value propertyValue);
+  Property::Index RegisterProperty(std::string_view name, Property::Value propertyValue);
 
   /**
    * @brief Register a new animatable property with an integer key.
@@ -329,9 +329,9 @@ public:
    *       - Property::ROTATION
    * @note If a property with the desired name already exists, then the value given is just set.
    */
-  Property::Index RegisterProperty(Property::Index key,
-                                   std::string     name,
-                                   Property::Value propertyValue);
+  Property::Index RegisterProperty(Property::Index  key,
+                                   std::string_view name,
+                                   Property::Value  propertyValue);
 
   /**
    * @brief Registers a new property.
@@ -356,7 +356,7 @@ public:
    *       - Property::ROTATION
    * @note If a property with the desired name already exists, then the value given is just set.
    */
-  Property::Index RegisterProperty(std::string name, Property::Value propertyValue, Property::AccessMode accessMode);
+  Property::Index RegisterProperty(std::string_view name, Property::Value propertyValue, Property::AccessMode accessMode);
 
   /**
    * @brief Retrieves a property value.
index f27065d..c3fd11f 100644 (file)
@@ -55,115 +55,15 @@ RefObject& RefObject::operator=(const RefObject&)
 
 void RefObject::Reference()
 {
-  // clang-format off
-  // The inline assembly below was tested on an ARMv8 64 bit platform on
-  // 2015-02-06 and found to run in 11.8 nanoseconds, whereas
-  // __sync_add_and_fetch( address, 1 ) required 18.8 nanoseconds.
-  // Including the assembly here produced one fewer assembly instruction than if
-  // it was wrapped in a function and inlined here by the compiler.
-#if defined __aarch64__
-
-  asm volatile(
-  "1:\tldxr  w1, %[address] \n\t"
-      "add   w1, w1, %[one] \n\t"
-      "stxr  w2,  w1, %[address] \n\t"
-      "cbnz  w2,  1b \n\t"
-      // Outputs:
-    : // Q = A memory address with no offset
-      // ( https://gcc.gnu.org/onlinedocs/gcc/Machine-Constraints.html#Machine-Constraints )
-      [address] "+Q" (mCount)
-      // Inputs:
-    : [one] "Ir" (1)
-      // Clobbers: (explicitly clobber w1 register to hold the loaded value and
-      // register w2 to hold success/fail):
-    : "w1", "w2"
-  );
-
-  // 32 bit ARMv7 version of above:
-  // Better than the code emitted by GCC for __sync_add_and_fetch(), as that
-  // includes two dmb memory barrier instructions: one before and one after the
-  // loop.
-#elif defined __arm__
-
-  asm volatile(
-    "1:\tldrex r1, %[address] \n\t"
-        "add   r1, r1, %[one] \n\t"
-        "strex r2,  r1, %[address] \n\t"
-        "teq   r2,  %[zero] \n\t"
-        "bne   1b \n\t"
-        // Outputs:
-      : [address] "+Q" (mCount)
-        // Inputs:
-      : [zero] "Ir" (0),
-        [one]  "Ir" (1)
-        // Clobbers: (modified registers):
-      : "r1", "r2"
-    );
-
-#else
-
-  // gcc > 4.1 builtin atomic add and fetch:
-  __sync_add_and_fetch( &mCount, 1 );
-
-#endif
-  // clang-format on
+  ++mCount;
 }
 
 void RefObject::Unreference()
 {
-  // clang-format off
-
-  // The output register:
-  int32_t newValue;
-
-#if defined __aarch64__
-
-  asm volatile(
-  "1:\tldxr   %w[newValue], %[address] \n\t"
-      "sub   %w[newValue], %w[newValue], %[one] \n\t"
-      "stxr  w2,  %w[newValue], %[address] \n\t"
-      "cbnz  w2,  1b \n\t"
-    // Outputs:
-  : [newValue] "=&r" (newValue),
-    // Q = A memory address with no offset
-    // ( https://gcc.gnu.org/onlinedocs/gcc/Machine-Constraints.html#Machine-Constraints )
-    [address] "+Q" (mCount)
-    // Inputs:
-  : [one]  "Ir" (1)
-    // Clobbered: I.e., stuff that is modified.
-  : "w2"
-  );
-
-#elif defined __arm__
-
-  asm volatile(
-  "1:\tldrex %[newValue], %[address] \n\t"
-      "sub   %[newValue], %[newValue], %[one] \n\t"
-      "strex r2,  %[newValue], %[address] \n\t"
-      "teq   r2, %[zero] \n\t"
-      "bne   1b \n\t"
-    // Outputs:
-  : [newValue] "=&r" (newValue),
-    [address] "+Q" (mCount)
-    // Inputs:
-    : [zero] "Ir" (0),
-      [one]  "Ir" (1)
-    // Clobbered:
-  : "r2"
-  );
-
-#else
-
-  // gcc > 4.1 builtin atomic subtract and fetch (--mCount; return mCount)
-  newValue = __sync_sub_and_fetch( &mCount, 1 );
-
-#endif
-
-  if( newValue == 0 )
+  if( (--mCount) == 0 )
   {
     delete this;
   }
-  // clang-format on
 }
 
 uint32_t RefObject::ReferenceCount()
index 56e0018..30c26b7 100644 (file)
@@ -20,6 +20,7 @@
 
 // EXTERNAL INCLUDES
 #include <cstdint> // uint32_t
+#include <atomic>
 
 // INTERNAL INCLUDES
 #include <dali/public-api/common/dali-common.h>
@@ -101,7 +102,7 @@ protected:
   RefObject& operator=(const RefObject& rhs);
 
 private:
-  volatile uint32_t mCount; ///< Reference count
+  std::atomic_uint32_t mCount {0u}; ///< Reference count
 };
 
 /**
index 50a1fc9..9d5c3cb 100644 (file)
@@ -88,17 +88,17 @@ void TypeInfo::GetPropertyIndices(Property::IndexContainer& indices) const
   GetImplementation(*this).GetPropertyIndices(indices);
 }
 
-const std::string& TypeInfo::GetPropertyName(Property::Index index) const
+std::string_view TypeInfo::GetPropertyName(Property::Index index) const
 {
   return GetImplementation(*this).GetRegisteredPropertyName(index);
 }
 
 Property::Index TypeInfo::GetChildPropertyIndex(const std::string& name) const
 {
-  return GetImplementation(*this).GetChildPropertyIndex(name);
+  return GetImplementation(*this).GetChildPropertyIndex(Internal::ConstString(name));
 }
 
-const std::string& TypeInfo::GetChildPropertyName(Property::Index index) const
+std::string_view TypeInfo::GetChildPropertyName(Property::Index index) const
 {
   return GetImplementation(*this).GetChildPropertyName(index);
 }
index 164ab17..b278c82 100644 (file)
@@ -240,7 +240,7 @@ public:
    * @exception DaliException If index is not valid.
    * @note this method only works for custom registered properties
    */
-  const std::string& GetPropertyName(Property::Index index) const;
+  std::string_view GetPropertyName(Property::Index index) const;
 
   /**
    * @brief Given a child property name, retrieve the property index associated with it,
@@ -258,7 +258,7 @@ public:
    * @param[in] index The property index
    * @return The name of the property at the given index, or empty string if it does not exist
    */
-  const std::string& GetChildPropertyName(Property::Index index) const;
+  std::string_view GetChildPropertyName(Property::Index index) const;
 
   /**
    * @brief Given a child property index, retrieve the property name associated with it.
index d060792..67515c4 100644 (file)
@@ -1,6 +1,6 @@
 Name:       dali2
 Summary:    DALi 3D Engine
-Version:    2.0.3
+Version:    2.0.4
 Release:    1
 Group:      System/Libraries
 License:    Apache-2.0 and BSD-3-Clause and MIT