Merge "Add Filter in InputFilter" into devel/master
authorBowon Ryu <bowon.ryu@samsung.com>
Mon, 19 Dec 2022 04:37:28 +0000 (04:37 +0000)
committerGerrit Code Review <gerrit@review>
Mon, 19 Dec 2022 04:37:28 +0000 (04:37 +0000)
67 files changed:
automated-tests/resources/AnimatedCube.gltf
automated-tests/resources/AnimatedCubeStride.gltf [new file with mode: 0644]
automated-tests/resources/BoxAnimated.gltf
automated-tests/src/dali-scene3d/utc-Dali-AnimatedProperty.cpp
automated-tests/src/dali-scene3d/utc-Dali-AnimationDefinition.cpp
automated-tests/src/dali-scene3d/utc-Dali-BvhLoader.cpp
automated-tests/src/dali-scene3d/utc-Dali-DliLoader.cpp
automated-tests/src/dali-scene3d/utc-Dali-FacialAnimation.cpp
automated-tests/src/dali-scene3d/utc-Dali-Gltf2Loader.cpp
automated-tests/src/dali-scene3d/utc-Dali-NodeDefinition.cpp
automated-tests/src/dali-scene3d/utc-Dali-SceneDefinition.cpp
automated-tests/src/dali-toolkit-internal/utc-Dali-Text-TextSpannable.cpp
automated-tests/src/dali-toolkit-internal/utc-Dali-Text-ViewModel.cpp
automated-tests/src/dali-toolkit/CMakeLists.txt
automated-tests/src/dali-toolkit/utc-Dali-AnimatedVectorImageVisual.cpp
automated-tests/src/dali-toolkit/utc-Dali-Text-UnderlineSpan.cpp [new file with mode: 0644]
build/tizen/docs/dali.doxy.in
dali-scene3d/internal/controls/model/model-impl.cpp
dali-scene3d/internal/controls/scene-view/scene-view-impl.cpp
dali-scene3d/internal/controls/scene-view/scene-view-impl.h
dali-scene3d/internal/graphics/shaders/default-physically-based-shader.frag
dali-scene3d/internal/graphics/shaders/skybox-equirectangular-shader.frag [new file with mode: 0644]
dali-scene3d/public-api/controls/scene-view/scene-view.cpp
dali-scene3d/public-api/controls/scene-view/scene-view.h
dali-scene3d/public-api/loader/animated-property.cpp
dali-scene3d/public-api/loader/animated-property.h
dali-scene3d/public-api/loader/gltf2-loader.cpp
dali-scene3d/public-api/loader/material-definition.h
dali-scene3d/public-api/loader/mesh-definition.cpp
dali-scene3d/public-api/loader/node-definition.cpp
dali-scene3d/public-api/loader/node-definition.h
dali-scene3d/public-api/loader/scene-definition.cpp
dali-scene3d/public-api/loader/scene-definition.h
dali-scene3d/public-api/loader/shader-definition-factory.cpp
dali-toolkit/devel-api/file.list
dali-toolkit/devel-api/text/spans/underline-span.cpp [new file with mode: 0644]
dali-toolkit/devel-api/text/spans/underline-span.h [new file with mode: 0644]
dali-toolkit/internal/controls/web-view/web-view-impl.cpp
dali-toolkit/internal/controls/web-view/web-view-impl.h
dali-toolkit/internal/file.list
dali-toolkit/internal/text/controller/text-controller-impl-model-updater.cpp
dali-toolkit/internal/text/controller/text-controller-impl.cpp
dali-toolkit/internal/text/logical-model-impl.cpp
dali-toolkit/internal/text/logical-model-impl.h
dali-toolkit/internal/text/rendering/text-typesetter.cpp
dali-toolkit/internal/text/rendering/view-model.cpp
dali-toolkit/internal/text/rendering/view-model.h
dali-toolkit/internal/text/spannable/spans/underline-span-impl.cpp [new file with mode: 0644]
dali-toolkit/internal/text/spannable/spans/underline-span-impl.h [new file with mode: 0644]
dali-toolkit/internal/text/text-model-interface.h
dali-toolkit/internal/text/text-model.cpp
dali-toolkit/internal/text/text-model.h
dali-toolkit/internal/visuals/animated-image/animated-image-visual.cpp
dali-toolkit/internal/visuals/animated-image/animated-image-visual.h
dali-toolkit/internal/visuals/animated-image/fixed-image-cache.cpp
dali-toolkit/internal/visuals/animated-image/fixed-image-cache.h
dali-toolkit/internal/visuals/animated-image/image-cache.cpp
dali-toolkit/internal/visuals/animated-image/image-cache.h
dali-toolkit/internal/visuals/animated-image/rolling-animated-image-cache.cpp
dali-toolkit/internal/visuals/animated-image/rolling-animated-image-cache.h
dali-toolkit/internal/visuals/animated-image/rolling-image-cache.cpp
dali-toolkit/internal/visuals/animated-image/rolling-image-cache.h
dali-toolkit/internal/visuals/image/image-visual.cpp
dali-toolkit/internal/visuals/image/image-visual.h
dali-toolkit/internal/visuals/text/text-visual.cpp
dali-toolkit/public-api/dali-toolkit-version.cpp
packaging/dali-toolkit.spec

index 455120d..7787c04 100644 (file)
       },
       {
          "mesh" : 1,
-         "name" : "AnimatedCube2"
+         "name" : "AnimatedCube"
       },
       {
 
diff --git a/automated-tests/resources/AnimatedCubeStride.gltf b/automated-tests/resources/AnimatedCubeStride.gltf
new file mode 100644 (file)
index 0000000..d44ac0c
--- /dev/null
@@ -0,0 +1,84 @@
+{
+   "accessors" : [
+      {
+         "bufferView" : 0,
+         "byteOffset" : 0,
+         "componentType" : 5126,
+         "count" : 36,
+         "max" : [
+            1.000000,
+            1.000000,
+            1.000001
+         ],
+         "min" : [
+            -1.000000,
+            -1.000000,
+            -1.000000
+         ],
+         "type" : "VEC3"
+      }
+   ],
+   "asset" : {
+      "generator" : "VKTS glTF 2.0 exporter",
+      "version" : "2.0"
+   },
+   "bufferViews" : [
+      {
+         "buffer" : 0,
+         "byteLength" : 864,
+         "byteOffset" : 132,
+         "target" : 34962,
+         "byteStride": 24
+      }
+   ],
+   "buffers" : [
+      {
+         "byteLength" : 1860,
+         "uri" : "AnimatedCube.bin"
+      }
+   ],
+   "materials" : [
+      {
+         "name" : "AnimatedCube",
+         "pbrMetallicRoughness" : {
+         }
+      },
+      {
+         "name" : "AnimatedCube2",
+         "pbrMetallicRoughness" : {
+         }
+      }
+   ],
+   "meshes" : [
+      {
+         "name" : "AnimatedCube",
+         "primitives" : [
+            {
+               "attributes" : {
+                  "POSITION" : 0
+               }
+            }
+         ]
+      }
+   ],
+   "nodes" : [
+      {
+         "mesh" : 0,
+         "name" : "AnimatedCube",
+         "rotation" : [
+            0.000000,
+            -1.000000,
+            0.000000,
+            0.000000
+         ]
+      }
+   ],
+   "scene" : 0,
+   "scenes" : [
+      {
+         "nodes" : [
+            0
+         ]
+      }
+   ]
+}
\ No newline at end of file
index afa7afb..82e9702 100644 (file)
@@ -14,6 +14,7 @@
     ],\r
     "nodes": [\r
         {\r
+            "name" : "node0",\r
             "children": [\r
                 1\r
             ],\r
             ]\r
         },\r
         {\r
+            "name" : "node1",\r
             "children": [\r
                 2\r
             ]\r
         },\r
         {\r
+            "name" : "node2",\r
             "mesh": 0,\r
             "rotation": [\r
                 -0.0,\r
@@ -39,6 +42,7 @@
             ]\r
         },\r
         {\r
+            "name" : "node3",\r
             "mesh": 1\r
         }\r
     ],\r
index 0a59e26..6c4502f 100644 (file)
@@ -31,6 +31,7 @@ int UtcDaliAnimatedPropertyGetPropertyType(void)
   actor.SetProperty(Actor::Property::NAME, "ChristopherPlummer");
 
   AnimatedProperty animProp {
+    INVALID_INDEX,
    "ChristopherPlummer",
    "position",
    KeyFrames(),
index 5cde1b9..99b0aaf 100644 (file)
@@ -44,8 +44,8 @@ int UtcDaliAnimationDefinitionReAnimate(void)
   auto actor = Actor::New();
   actor.SetProperty(Actor::Property::NAME, "ChristopherPlummer");
 
-  auto getActor = [&actor](const std::string& name) {
-    return actor.FindChildByName(name);
+  auto getActor = [&actor](const Dali::Scene3D::Loader::AnimatedProperty& property) {
+    return actor.FindChildByName(property.mNodeName);
   };
 
   for (bool b: { false, true })
@@ -57,6 +57,7 @@ int UtcDaliAnimationDefinitionReAnimate(void)
     animDef.mEndAction = Animation::BAKE_FINAL;
     animDef.mSpeedFactor = .7f;
     animDef.mProperties.push_back(AnimatedProperty{
+     INVALID_INDEX,
      "ChristopherPlummer",
      "position",
      KeyFrames(),
@@ -84,8 +85,8 @@ int UtcDaliAnimationDefinitionReAnimateKeyFrames(void)
   auto actor = Actor::New();
   actor.SetProperty(Actor::Property::NAME, "ChristopherPlummer");
 
-  auto getActor = [&actor](const std::string& name) {
-    return actor.FindChildByName(name);
+  auto getActor = [&actor](const Dali::Scene3D::Loader::AnimatedProperty& property) {
+    return actor.FindChildByName(property.mNodeName);
   };
 
   KeyFrames kf = KeyFrames::New();
@@ -99,6 +100,7 @@ int UtcDaliAnimationDefinitionReAnimateKeyFrames(void)
   animDef.mEndAction = Animation::BAKE_FINAL;
   animDef.mSpeedFactor = .7f;
   animDef.mProperties.push_back(AnimatedProperty{
+   INVALID_INDEX,
    "ChristopherPlummer",
    "position",
    kf,
index 91fdb19..db5f525 100644 (file)
@@ -57,8 +57,8 @@ int UtcDaliLoadBvh(void)
   first.SetProperty(Actor::Property::NAME, "first");
   root.Add(first);
 
-  auto getActor = [&root](const std::string& name) {
-    return root.FindChildByName(name);
+  auto getActor = [&root](const Dali::Scene3D::Loader::AnimatedProperty& property) {
+    return root.FindChildByName(property.mNodeName);
   };
 
   Animation animation = animDef.ReAnimate(getActor);
index c663327..9d67ab4 100644 (file)
@@ -169,7 +169,6 @@ int UtcDaliDliLoaderLoadSceneAssertions(void)
     {"node-renderable-mesh-invalid-type", "Invalid Mesh index type"},
     {"node-renderable-mesh-out-of-bounds", "out of bounds"},
     {"node-child-invalid-type", "invalid index type"},
-    {"node-name-already-used", "name already used"},
     // from ParseAnimations()
     {"animation-failed-to-open", "Failed to open animation data"}};
   for(auto& i : pathExceptionPairs)
index 22692e0..2e97dc9 100644 (file)
@@ -77,8 +77,8 @@ int UtcDaliLoadFacialAnimation(void)
     actor.RegisterProperty(weightName, 0.0f);
   }
 
-  auto getActor = [&actor](const std::string& name) {
-    return actor.FindChildByName(name);
+  auto getActor = [&actor](const Dali::Scene3D::Loader::AnimatedProperty& property) {
+    return actor.FindChildByName(property.mNodeName);
   };
 
   auto anim = animDef.ReAnimate(getActor);
index eb19c4d..3ebf5de 100644 (file)
@@ -213,6 +213,8 @@ int UtcDaliGltfLoaderSuccess1(void)
      false,
      true,
      false,
+     true,
+     true,
      {
        {MaterialDefinition::ALBEDO,
         {"AnimatedCube_BaseColor.png",
@@ -263,6 +265,8 @@ int UtcDaliGltfLoaderSuccess1(void)
      true,
      true,
      false,
+     true,
+     false,
      {
        {MaterialDefinition::ALBEDO,
         {"AnimatedCube_BaseColor.png",
@@ -313,6 +317,8 @@ int UtcDaliGltfLoaderSuccess1(void)
     DALI_TEST_EQUAL(md.mNeedAlbedoTexture, m.mNeedAlbedoTexture);
     DALI_TEST_EQUAL(md.mNeedMetallicRoughnessTexture, m.mNeedMetallicRoughnessTexture);
     DALI_TEST_EQUAL(md.mNeedNormalTexture, m.mNeedNormalTexture);
+    DALI_TEST_EQUAL(md.mIsOpaque, m.mIsOpaque);
+    DALI_TEST_EQUAL(md.mIsMask, m.mIsMask);
 
     DALI_TEST_EQUAL(md.mTextureStages.size(), m.mTextureStages.size());
     auto iTexture = md.mTextureStages.begin();
@@ -399,6 +405,33 @@ int UtcDaliGltfLoaderSuccess1(void)
   END_TEST;
 }
 
+int UtcDaliGltfLoaderSuccess2(void)
+{
+  Context ctx;
+  ShaderDefinitionFactory sdf;
+  sdf.SetResources(ctx.resources);
+
+  LoadGltfScene(TEST_RESOURCE_DIR "/AnimatedCubeStride.gltf", sdf, ctx.loadResult);
+
+  DALI_TEST_EQUAL(1u, ctx.scene.GetRoots().size());
+  DALI_TEST_EQUAL(1u, ctx.scene.GetNodeCount());
+
+  TestApplication app;
+
+  Customization::Choices choices;
+  for(auto iRoot : ctx.scene.GetRoots())
+  {
+    auto resourceRefs = ctx.resources.CreateRefCounter();
+    ctx.scene.CountResourceRefs(iRoot, choices, resourceRefs);
+    ctx.resources.LoadResources(resourceRefs, ctx.pathProvider);
+  }
+
+  DALI_TEST_EQUAL(true, ctx.resources.mMeshes[0u].first.mPositions.IsDefined());
+  DALI_TEST_EQUAL(432, ctx.resources.mMeshes[0u].first.mPositions.mBlob.mLength);
+
+  END_TEST;
+}
+
 int UtcDaliGltfLoaderSuccessShort(void)
 {
   TestApplication app;
@@ -546,3 +579,59 @@ int UtcDaliGltfLoaderMRendererTest(void)
 
   END_TEST;
 }
+
+
+int UtcDaliGltfLoaderAnimationLoadingTest(void)
+{
+  Context ctx;
+
+  ShaderDefinitionFactory sdf;
+  sdf.SetResources(ctx.resources);
+  auto& resources = ctx.resources;
+
+  LoadGltfScene(TEST_RESOURCE_DIR "/BoxAnimated.gltf", sdf, ctx.loadResult);
+
+  auto& scene = ctx.scene;
+  auto& roots = scene.GetRoots();
+  DALI_TEST_EQUAL(roots.size(), 1u);
+
+  ViewProjection viewProjection;
+  Transforms     xforms{
+    MatrixStack{},
+    viewProjection};
+  NodeDefinition::CreateParams nodeParams{
+    resources,
+    xforms,
+  };
+
+  Customization::Choices choices;
+
+  TestApplication app;
+
+  Actor root = Actor::New();
+  SetActorCentered(root);
+  for(auto iRoot : roots)
+  {
+    auto resourceRefs = resources.CreateRefCounter();
+    scene.CountResourceRefs(iRoot, choices, resourceRefs);
+    resources.CountEnvironmentReferences(resourceRefs);
+    resources.LoadResources(resourceRefs, ctx.pathProvider);
+    if(auto actor = scene.CreateNodes(iRoot, choices, nodeParams))
+    {
+      scene.ConfigureSkeletonJoints(iRoot, resources.mSkeletons, actor);
+      scene.ConfigureSkinningShaders(resources, actor, std::move(nodeParams.mSkinnables));
+      scene.ApplyConstraints(actor, std::move(nodeParams.mConstrainables));
+      root.Add(actor);
+    }
+  }
+
+  DALI_TEST_EQUAL(ctx.loadResult.mAnimationDefinitions.size(), 1u);
+  DALI_TEST_EQUAL(ctx.loadResult.mAnimationDefinitions[0].mProperties.size(), 2u);
+
+  uint32_t id = ctx.loadResult.mScene.GetNode(ctx.loadResult.mAnimationDefinitions[0].mProperties[0].mNodeIndex)->mNodeId;
+  DALI_TEST_EQUAL(id, root.FindChildByName("node2").GetProperty<int32_t>(Dali::Actor::Property::ID));
+  uint32_t id2 = ctx.loadResult.mScene.GetNode(ctx.loadResult.mAnimationDefinitions[0].mProperties[1].mNodeIndex)->mNodeId;
+  DALI_TEST_EQUAL(id2, root.FindChildByName("node0").GetProperty<int32_t>(Dali::Actor::Property::ID));
+
+  END_TEST;
+}
index 415e2e1..2b7c319 100644 (file)
@@ -101,6 +101,7 @@ int UtcDaliNodeDefinitionProperties(void)
   TestApplication testApp;
   NodeDefinition  nodeDef{
     "testRootNode",
+    INVALID_INDEX,
     Vector3{-100.f, 100.f, -500.f},
     Quaternion{Radian(Degree(45.f)), Vector3::ZAXIS},
     Vector3{2.f, 4.f, 8.f},
index dc2fc92..e7126eb 100644 (file)
@@ -42,10 +42,9 @@ int UtcDaliSceneDefinitionAddNode(void)
   auto node2 = new NodeDefinition();
   node2->mName = node->mName;
   result = sceneDef.AddNode(std::unique_ptr<NodeDefinition>{ node2 });
-  DALI_TEST_EQUAL(result, static_cast<NodeDefinition*>(nullptr)); // failed
-  DALI_TEST_EQUAL(sceneDef.GetNodeCount(), 1u); // still
-  DALI_TEST_EQUAL(sceneDef.GetNode(0), node); // still
-  DALI_TEST_EQUAL(sceneDef.FindNode(node->mName), node); // still
+  DALI_TEST_EQUAL(result, node2);
+  DALI_TEST_EQUAL(sceneDef.GetNodeCount(), 2u);
+  DALI_TEST_EQUAL(sceneDef.GetNode(1), node2);
 
   auto child = new NodeDefinition();
   child->mName = "Second";
@@ -55,11 +54,11 @@ int UtcDaliSceneDefinitionAddNode(void)
 
   result = sceneDef.AddNode(std::unique_ptr<NodeDefinition>{ child });
   DALI_TEST_EQUAL(result, child);
-  DALI_TEST_EQUAL(sceneDef.GetNodeCount(), 2u);
-  DALI_TEST_EQUAL(sceneDef.GetNode(1), child);
+  DALI_TEST_EQUAL(sceneDef.GetNodeCount(), 3u);
+  DALI_TEST_EQUAL(sceneDef.GetNode(2), child);
   DALI_TEST_EQUAL(sceneDef.FindNode(child->mName), child);
 
-  DALI_TEST_EQUAL(node->mChildren[0], 1u); // these are hooked up by AddNode, base on parent idx.
+  DALI_TEST_EQUAL(node->mChildren[0], 2u); // these are hooked up by AddNode, base on parent idx.
 
   END_TEST;
 }
index 098e660..1143326 100644 (file)
 #include <dali-toolkit/devel-api/text/spannable-string.h>
 #include <dali-toolkit/devel-api/text/spans/font-span.h>
 #include <dali-toolkit/devel-api/text/spans/foreground-color-span.h>
+#include <dali-toolkit/devel-api/text/spans/underline-span.h>
 #include <dali-toolkit/devel-api/text/text-enumerations-devel.h>
 #include <dali-toolkit/internal/controls/text-controls/text-editor-impl.h>
 #include <dali-toolkit/internal/controls/text-controls/text-field-impl.h>
 #include <dali-toolkit/internal/controls/text-controls/text-label-impl.h>
+#include <dali-toolkit/internal/text/controller/text-controller.h>
 #include <dali-toolkit/internal/text/font-description-run.h>
+#include <dali-toolkit/internal/text/rendering/text-typesetter.h>
+#include <dali-toolkit/internal/text/rendering/view-model.h>
+#include <dali-toolkit/internal/text/text-view.h>
 #include <dali-toolkit/public-api/text/text-enumerations.h>
+#include <toolkit-text-utils.h>
 
 using namespace Dali;
 using namespace Toolkit;
@@ -38,7 +44,7 @@ using namespace Toolkit;
 namespace
 {
 const std::string DEFAULT_FONT_DIR("/resources/fonts");
-const float PIXEL_FORMAT_64_FACTOR = 64.f; ///< 64.f is used to convert from point size to 26.6 pixel format.
+const float       PIXEL_FORMAT_64_FACTOR = 64.f; ///< 64.f is used to convert from point size to 26.6 pixel format.
 } // namespace
 
 Text::SpannableString CreateSpannableStringForForegroundColorSpan()
@@ -71,6 +77,19 @@ Text::SpannableString CreateSpannableStringForFontSpan()
   return spannableString;
 }
 
+Text::SpannableString CreateSpannableStringForUnderlineSpan()
+{
+  Text::SpannableString spannableString = Text::SpannableString::New("Hello World");
+  DALI_TEST_CHECK(spannableString);
+
+  auto isAddedUnderlineSpan = spannableString.AttachSpan(
+    Text::UnderlineSpan::NewDashed(Color::GREEN, 5.0f, 2.0f, 3.0f),
+    Text::Range::New(5u, 7u));
+  DALI_TEST_CHECK(isAddedUnderlineSpan);
+
+  return spannableString;
+}
+
 void CheckColorIndices(const Text::ColorIndex* const colorIndicesBuffer,
                        uint32_t                      numberOfIndices,
                        std::vector<uint32_t>         indicesToCheck,
@@ -100,8 +119,8 @@ int UtcDaliToolkitTextLabelSetSpannedText(void)
   application.SendNotification();
   application.Render();
 
-  Toolkit::Internal::TextLabel& labelImpl           = GetImpl(textLabel);
-  const Text::ColorIndex* const colorIndicesBuffer  = labelImpl.GetTextController()->GetTextModel()->GetColorIndices();
+  Toolkit::Internal::TextLabel& labelImpl          = GetImpl(textLabel);
+  const Text::ColorIndex* const colorIndicesBuffer = labelImpl.GetTextController()->GetTextModel()->GetColorIndices();
 
   CheckColorIndices(colorIndicesBuffer, 4u, {0u, 5u, 7u, 10u}, {0u, 1u, 1u, 0u});
 
@@ -182,7 +201,7 @@ int UtcDaliToolkitTextLabelSetSpannedText_FontSpan(void)
   application.SendNotification();
   application.Render();
 
-  Toolkit::Internal::TextLabel&               labelImpl  = GetImpl(textLabel);
+  Toolkit::Internal::TextLabel&               labelImpl     = GetImpl(textLabel);
   const Vector<Dali::Toolkit::Text::FontRun>& validFontRuns = labelImpl.GetTextController()->GetTextModel()->GetFontRuns();
 
   DALI_TEST_EQUALS(validFontRuns.Count(), 3u, TEST_LOCATION);
@@ -212,4 +231,135 @@ int UtcDaliToolkitTextLabelSetSpannedText_FontSpan(void)
   DALI_TEST_EQUALS(validFontDescriptionRuns[0].slant, Dali::TextAbstraction::FontSlant::OBLIQUE, TEST_LOCATION);
 
   END_TEST;
+}
+
+int UtcDaliTextModelIsSpannedTextPlaced(void)
+
+{
+  tet_infoline(" UtcDaliTextModelIsSpannedTextPlaced");
+
+  ToolkitTestApplication application;
+
+  // Create spanned-text and set it
+  Text::SpannableString spannedText = Text::SpannableString::New("Hello Ù…رحبا");
+  DALI_TEST_CHECK(spannedText);
+
+  // Creates a text controller.
+  Dali::Toolkit::Text::ControllerPtr         controllerTextEditor = Dali::Toolkit::Text::Controller::New();
+  const Dali::Toolkit::Text::ModelInterface* modelEditor          = controllerTextEditor->GetTextModel();
+
+  // Tests the rendering controller has been created.
+  Dali::Toolkit::Text::TypesetterPtr typesetterEditor = Dali::Toolkit::Text::Typesetter::New(controllerTextEditor->GetTextModel());
+  DALI_TEST_CHECK(typesetterEditor);
+
+  // Tests the view model has been created.
+  Dali::Toolkit::Text::ViewModel* viewModelEditor = typesetterEditor->GetViewModel();
+  DALI_TEST_CHECK(viewModelEditor);
+
+  // Configures the text controller similarly to the text-editor.
+  Dali::Toolkit::Text::ConfigureTextEditor(controllerTextEditor);
+
+  DALI_TEST_EQUALS(false, modelEditor->IsSpannedTextPlaced(), TEST_LOCATION);
+  DALI_TEST_EQUALS(false, viewModelEditor->IsSpannedTextPlaced(), TEST_LOCATION);
+
+  controllerTextEditor->SetSpannedText(spannedText);
+
+  DALI_TEST_EQUALS(true, modelEditor->IsSpannedTextPlaced(), TEST_LOCATION);
+  DALI_TEST_EQUALS(true, viewModelEditor->IsSpannedTextPlaced(), TEST_LOCATION);
+
+  // Creates a text controller.
+  Dali::Toolkit::Text::ControllerPtr         controllerTextLabel = Dali::Toolkit::Text::Controller::New();
+  const Dali::Toolkit::Text::ModelInterface* modelLabel          = controllerTextLabel->GetTextModel();
+
+  // Tests the rendering controller has been created.
+  Dali::Toolkit::Text::TypesetterPtr typesetterLabel = Dali::Toolkit::Text::Typesetter::New(controllerTextLabel->GetTextModel());
+  DALI_TEST_CHECK(typesetterLabel);
+
+  // Tests the view model has been created.
+  Dali::Toolkit::Text::ViewModel* viewModelLabel = typesetterLabel->GetViewModel();
+  DALI_TEST_CHECK(viewModelLabel);
+
+  // Configures the text controller similarly to the text-label.
+  Dali::Toolkit::Text::ConfigureTextLabel(controllerTextLabel);
+
+  DALI_TEST_EQUALS(false, modelLabel->IsSpannedTextPlaced(), TEST_LOCATION);
+  DALI_TEST_EQUALS(false, viewModelLabel->IsSpannedTextPlaced(), TEST_LOCATION);
+
+  controllerTextLabel->SetSpannedText(spannedText);
+
+  DALI_TEST_EQUALS(true, modelLabel->IsSpannedTextPlaced(), TEST_LOCATION);
+  DALI_TEST_EQUALS(true, viewModelLabel->IsSpannedTextPlaced(), TEST_LOCATION);
+
+  // Creates a text controller.
+  Dali::Toolkit::Text::ControllerPtr         controllerTextField = Dali::Toolkit::Text::Controller::New();
+  const Dali::Toolkit::Text::ModelInterface* modelField          = controllerTextField->GetTextModel();
+
+  // Tests the rendering controller has been created.
+  Dali::Toolkit::Text::TypesetterPtr typesetterField = Dali::Toolkit::Text::Typesetter::New(controllerTextField->GetTextModel());
+  DALI_TEST_CHECK(typesetterField);
+
+  // Tests the view model has been created.
+  Dali::Toolkit::Text::ViewModel* viewModelField = typesetterField->GetViewModel();
+  DALI_TEST_CHECK(viewModelField);
+
+  // Configures the text controller similarly to the text-field.
+  Dali::Toolkit::Text::ConfigureTextField(controllerTextField);
+
+  DALI_TEST_EQUALS(false, modelField->IsSpannedTextPlaced(), TEST_LOCATION);
+  DALI_TEST_EQUALS(false, viewModelField->IsSpannedTextPlaced(), TEST_LOCATION);
+
+  controllerTextField->SetSpannedText(spannedText);
+
+  DALI_TEST_EQUALS(true, modelField->IsSpannedTextPlaced(), TEST_LOCATION);
+  DALI_TEST_EQUALS(true, viewModelField->IsSpannedTextPlaced(), TEST_LOCATION);
+
+  tet_result(TET_PASS);
+
+  END_TEST;
+}
+
+int UtcDaliToolkitTextLabelSetSpannedText_UnderlineSpan(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliToolkitTextLabelSetSpannedText_UnderlineSpan ");
+
+  Dali::Toolkit::Text::UnderlineStyleProperties expectedProperties = {
+    Text::Underline::DASHED,
+    Color::GREEN,
+    5u,
+    2u,
+    3u,
+    true,
+    true,
+    true,
+    true,
+    true};
+
+  TextLabel textLabel = TextLabel::New();
+  DALI_TEST_CHECK(textLabel);
+  application.GetScene().Add(textLabel);
+
+  Text::SpannableString spannableString = CreateSpannableStringForUnderlineSpan();
+
+  Text::SetSpannedText(textLabel, spannableString);
+
+  application.SendNotification();
+  application.Render();
+
+  Toolkit::Internal::TextLabel& labelImpl             = GetImpl(textLabel);
+  const Text::Length            numberOfUnderlineRuns = labelImpl.GetTextController()->GetTextModel()->GetNumberOfUnderlineRuns();
+
+  DALI_TEST_EQUALS(numberOfUnderlineRuns, 1u, TEST_LOCATION);
+
+  Vector<Dali::Toolkit::Text::UnderlinedGlyphRun> underlineRuns;
+
+  underlineRuns.Resize(numberOfUnderlineRuns);
+
+  labelImpl.GetTextController()->GetTextModel()->GetUnderlineRuns(underlineRuns.Begin(), 0u, numberOfUnderlineRuns);
+
+  DALI_TEST_EQUALS(underlineRuns[0].glyphRun.glyphIndex, 5u, TEST_LOCATION);
+  DALI_TEST_EQUALS(underlineRuns[0].glyphRun.numberOfGlyphs, 3u, TEST_LOCATION);
+  DALI_TEST_CHECK(underlineRuns[0].properties == expectedProperties);
+
+  END_TEST;
 }
\ No newline at end of file
index 80f8092..b13fcda 100755 (executable)
 
 #include <dali-toolkit-test-suite-utils.h>
 #include <dali-toolkit/dali-toolkit.h>
-#include <toolkit-text-utils.h>
-#include <dali-toolkit/internal/text/font-description-run.h>
+#include <dali-toolkit/devel-api/text/spannable-string.h>
 #include <dali-toolkit/internal/text/controller/text-controller.h>
+#include <dali-toolkit/internal/text/font-description-run.h>
 #include <dali-toolkit/internal/text/rendering/text-typesetter.h>
 #include <dali-toolkit/internal/text/rendering/view-model.h>
+#include <toolkit-text-utils.h>
 
 using namespace Dali;
 using namespace Toolkit;
index f4643e3..5914024 100755 (executable)
@@ -45,6 +45,7 @@ SET(TC_SOURCES
   utc-Dali-Text-FontSpan.cpp
   utc-Dali-Text-Range.cpp
   utc-Dali-Text-SpannableString.cpp
+  utc-Dali-Text-UnderlineSpan.cpp
   utc-Dali-TextEditor.cpp
   utc-Dali-TextField.cpp
   utc-Dali-TextGeometry.cpp
index cdd58b4..1c9daf7 100644 (file)
@@ -1972,6 +1972,9 @@ int UtcDaliAnimatedVectorImageVisualDynamicProperty(void)
   DummyControlImpl& dummyImpl = static_cast<DummyControlImpl&>(actor.GetImplementation());
   dummyImpl.RegisterVisual(DummyControl::Property::TEST_VISUAL, visual);
 
+  Vector2 controlSize(20.f, 30.f);
+  actor.SetProperty(Actor::Property::SIZE, controlSize);
+
   application.GetScene().Add(actor);
 
   gDynamicPropertyCallbackFired = false;
diff --git a/automated-tests/src/dali-toolkit/utc-Dali-Text-UnderlineSpan.cpp b/automated-tests/src/dali-toolkit/utc-Dali-Text-UnderlineSpan.cpp
new file mode 100644 (file)
index 0000000..c816cce
--- /dev/null
@@ -0,0 +1,205 @@
+/*
+ * Copyright (c) 2022 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 <stdlib.h>
+#include <unistd.h>
+#include <iostream>
+
+#include <dali-toolkit-test-suite-utils.h>
+#include <dali-toolkit/dali-toolkit.h>
+#include <dali-toolkit/devel-api/text/spans/underline-span.h>
+
+using namespace Dali;
+using namespace Toolkit;
+
+int UtcDaliToolkitTextUnderlineSpanNew(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliToolkitTextUnderlineSpanNew");
+
+  auto underlineSpan = Text::UnderlineSpan::New();
+  DALI_TEST_CHECK(underlineSpan);
+
+  END_TEST;
+}
+
+int UtcDaliToolkitTextUnderlineSpanNewSolid(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliToolkitTextUnderlineSpanNewSolid");
+
+  auto underlineSpan = Text::UnderlineSpan::NewSolid(Color::GREEN, 5.0f);
+  DALI_TEST_CHECK(underlineSpan);
+
+  END_TEST;
+}
+
+int UtcDaliToolkitTextUnderlineSpanNewDashed(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliToolkitTextUnderlineSpanNewDashed");
+
+  auto underlineSpan = Text::UnderlineSpan::NewDashed(Color::GREEN, 5.0f, 2.0f, 3.0f);
+  DALI_TEST_CHECK(underlineSpan);
+
+  END_TEST;
+}
+
+int UtcDaliToolkitTextUnderlineSpanNewDouble(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliToolkitTextUnderlineSpanNewDouble");
+
+  auto underlineSpan = Text::UnderlineSpan::NewDouble(Color::GREEN, 5.0f);
+  DALI_TEST_CHECK(underlineSpan);
+
+  END_TEST;
+}
+
+int UtcDaliToolkitTextGetType(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliToolkitTextGetType");
+
+  auto underlineSpan = Text::UnderlineSpan::NewDouble(Color::GREEN, 5.0f);
+  DALI_TEST_CHECK(underlineSpan);
+  DALI_TEST_EQUALS(Text::Underline::DOUBLE, underlineSpan.GetType(), TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliToolkitTextIsTypeDefined(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliToolkitTextIsTypeDefined");
+
+  auto underlineSpan = Text::UnderlineSpan::NewDouble(Color::GREEN, 5.0f);
+  DALI_TEST_CHECK(underlineSpan);
+  DALI_TEST_EQUALS(true, underlineSpan.IsTypeDefined(), TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliToolkitTextGetColor(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliToolkitTextGetColor");
+
+  auto underlineSpan = Text::UnderlineSpan::NewSolid(Color::GREEN, 5.0f);
+  DALI_TEST_CHECK(underlineSpan);
+  DALI_TEST_EQUALS(Color::GREEN, underlineSpan.GetColor(), TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliToolkitTextIsColorDefined(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliToolkitTextIsColorDefined");
+
+  auto underlineSpan = Text::UnderlineSpan::NewSolid(Color::GREEN, 5.0f);
+  DALI_TEST_CHECK(underlineSpan);
+  DALI_TEST_EQUALS(true, underlineSpan.IsColorDefined(), TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliToolkitTextGetHeight(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliToolkitTextGetHeight");
+
+  auto underlineSpan = Text::UnderlineSpan::NewSolid(Color::GREEN, 5.0f);
+  DALI_TEST_CHECK(underlineSpan);
+  DALI_TEST_EQUALS(5.0f, underlineSpan.GetHeight(), TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliToolkitTextIsHeightDefined(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliToolkitTextIsHeightDefined");
+
+  auto underlineSpan = Text::UnderlineSpan::NewSolid(Color::GREEN, 5.0f);
+  DALI_TEST_CHECK(underlineSpan);
+  DALI_TEST_EQUALS(true, underlineSpan.IsHeightDefined(), TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliToolkitTextGetDashGap(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliToolkitTextGetDashGap");
+
+  auto underlineSpan = Text::UnderlineSpan::NewDashed(Color::GREEN, 5.0f, 2.0f, 3.0f);
+  DALI_TEST_CHECK(underlineSpan);
+  DALI_TEST_EQUALS(2.0f, underlineSpan.GetDashGap(), TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliToolkitTextIsDashGapDefined(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliToolkitTextIsDashGapDefined");
+
+  auto underlineSpan = Text::UnderlineSpan::NewDashed(Color::GREEN, 5.0f, 2.0f, 3.0f);
+  DALI_TEST_CHECK(underlineSpan);
+  DALI_TEST_EQUALS(true, underlineSpan.IsDashGapDefined(), TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliToolkitTextGetDashWidth(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliToolkitTextGetDashWidth");
+
+  auto underlineSpan = Text::UnderlineSpan::NewDashed(Color::GREEN, 5.0f, 2.0f, 3.0f);
+  DALI_TEST_CHECK(underlineSpan);
+  DALI_TEST_EQUALS(3.0f, underlineSpan.GetDashWidth(), TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliToolkitTextIsDashWidthDefined(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliToolkitTextIsDashWidthDefined");
+
+  auto underlineSpan = Text::UnderlineSpan::NewDashed(Color::GREEN, 5.0f, 2.0f, 3.0f);
+  DALI_TEST_CHECK(underlineSpan);
+  DALI_TEST_EQUALS(true, underlineSpan.IsDashWidthDefined(), TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliToolkitTextUnderlineSpanDownCast(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliToolkitTextUnderlineSpanDownCast");
+
+  Text::BaseSpan baseSpan = Text::UnderlineSpan::New();
+  DALI_TEST_CHECK(baseSpan);
+
+  Text::UnderlineSpan underlineSpan = Text::UnderlineSpan::DownCast(baseSpan);
+  DALI_TEST_CHECK(underlineSpan);
+
+  END_TEST;
+}
index 1fc3cc8..921ee6e 100644 (file)
@@ -1,4 +1,9 @@
 # Doxyfile 1.8.11
+# Note : If you want to upgrade Doxyfile into 1.9.1
+# Find "###1.9.1###" and remove these comments.
+# For example,
+# ###1.9.1###PYTHON_DOCSTRING = YES -->
+# PYTHON_DOCSTRING = YES
 
 # This file describes the settings to be used by the documentation system
 # doxygen (www.doxygen.org) for a project.
 # Project related configuration options
 #---------------------------------------------------------------------------
 
-# This tag specifies the encoding used for all characters in the config file
-# that follow. The default is UTF-8 which is also the encoding used for all text
-# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv
-# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv
-# for the list of possible encodings.
+# This tag specifies the encoding used for all characters in the configuration
+# file that follow. The default is UTF-8 which is also the encoding used for all
+# text before the first occurrence of this tag. Doxygen uses libiconv (or the
+# iconv built into libc) for the transcoding. See
+# https://www.gnu.org/software/libiconv/ for the list of possible encodings.
 # The default value is: UTF-8.
 
 DOXYFILE_ENCODING      = UTF-8
@@ -93,6 +98,14 @@ ALLOW_UNICODE_NAMES    = NO
 
 OUTPUT_LANGUAGE        = English
 
+# The OUTPUT_TEXT_DIRECTION tag is used to specify the direction in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all generated output in the proper direction.
+# Possible values are: None, LTR, RTL and Context.
+# The default value is: None.
+
+OUTPUT_TEXT_DIRECTION = None
+
 # If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member
 # descriptions after the members that are listed in the file and class
 # documentation (similar to Javadoc). Set to NO to disable this.
@@ -189,6 +202,16 @@ SHORT_NAMES            = NO
 
 JAVADOC_AUTOBRIEF      = YES
 
+# If the JAVADOC_BANNER tag is set to YES then doxygen will interpret a line
+# such as
+# /***************
+# as being the beginning of a Javadoc-style comment "banner". If set to NO, the
+# Javadoc-style will behave just like regular comments and it will not be
+# interpreted by doxygen.
+# The default value is: NO.
+
+JAVADOC_BANNER = NO
+
 # If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first
 # line (until the first dot) of a Qt-style comment as the brief description. If
 # set to NO, the Qt-style will behave just like regular Qt-style comments (thus
@@ -209,6 +232,14 @@ QT_AUTOBRIEF           = NO
 
 MULTILINE_CPP_IS_BRIEF = NO
 
+# By default Python docstrings are displayed as preformatted text and doxygen's
+# special commands cannot be used. By setting PYTHON_DOCSTRING to NO the
+# doxygen's special commands can be used and the contents of the docstring
+# documentation blocks is shown as doxygen documentation.
+# The default value is: YES.
+
+###1.9.1###PYTHON_DOCSTRING = YES
+
 # If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the
 # documentation from any documented member that it re-implements.
 # The default value is: YES.
@@ -236,7 +267,12 @@ TAB_SIZE               = 2
 # will allow you to put the command \sideeffect (or @sideeffect) in the
 # documentation, which will result in a user-defined paragraph with heading
 # "Side Effects:". You can put \n's in the value part of an alias to insert
-# newlines.
+# newlines (in the resulting output). You can put ^^ in the value part of an
+# alias to insert a newline as if a physical newline was in the original file.
+# When you need a literal { or } or , in the value part of an alias you have to
+# escape them by means of a backslash (\), this can lead to conflicts with the
+# commands \{ and \} for these it is advised to use the version @{ and @} or use
+# a double escape (\\{ and \\})
 
 ALIASES                =
 # Clip alias inserts the specified file between two text markers.
@@ -454,12 +490,6 @@ ALIASES += REMARK_RAWVIDEO=""
 #ALIASES += REMARK_STORAGE="@remarks %http://tizen.org/privilege/mediastorage is needed if @a url is relevant to media storage. @remarks %http://tizen.org/privilege/externalstorage is needed if @a url is relevant to external storage."
 #ALIASES += REMARK_RAWVIDEO="@remarks %http://tizen.org/feature/multimedia.raw_video is needed if UNDERLAY is false. If the feature isn't supported, UNDERLAY is always true."
 
-# This tag can be used to specify a number of word-keyword mappings (TCL only).
-# A mapping has the form "name=value". For example adding "class=itcl::class"
-# will allow you to use the command class in the itcl::class meaning.
-
-TCL_SUBST              =
-
 # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
 # only. Doxygen will then generate output that is more tailored for C. For
 # instance, some of the names that are used will be different. The list of all
@@ -488,28 +518,40 @@ OPTIMIZE_FOR_FORTRAN   = NO
 
 OPTIMIZE_OUTPUT_VHDL   = NO
 
+# Set the OPTIMIZE_OUTPUT_SLICE tag to YES if your project consists of Slice
+# sources only. Doxygen will then generate output that is more tailored for that
+# language. For instance, namespaces will be presented as modules, types will be
+# separated into more groups, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_SLICE = NO
+
 # Doxygen selects the parser to use depending on the extension of the files it
 # parses. With this tag you can assign which parser to use for a given
 # extension. Doxygen has a built-in mapping, but you can override or extend it
 # using this tag. The format is ext=language, where ext is a file extension, and
-# language is one of the parsers supported by doxygen: IDL, Java, Javascript,
-# C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran:
-# FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran:
-# Fortran. In the later case the parser tries to guess whether the code is fixed
-# or free formatted code, this is the default for Fortran type files), VHDL. For
-# instance to make doxygen treat .inc files as Fortran files (default is PHP),
-# and .f files as C (default is Fortran), use: inc=Fortran f=C.
+# language is one of the parsers supported by doxygen: IDL, Java, JavaScript,
+# Csharp (C#), C, C++, D, PHP, md (Markdown), Objective-C, Python, Slice, VHDL,
+# Fortran (fixed format Fortran: FortranFixed, free formatted Fortran:
+# FortranFree, unknown formatted Fortran: Fortran. In the later case the parser
+# tries to guess whether the code is fixed or free formatted code, this is the
+# default for Fortran type files). For instance to make doxygen treat .inc files
+# as Fortran files (default is PHP), and .f files as C (default is Fortran),
+# use: inc=Fortran f=C.
 #
 # Note: For files without extension you can use no_extension as a placeholder.
 #
 # Note that for custom extensions you also need to set FILE_PATTERNS otherwise
-# the files are not read by doxygen.
+# the files are not read by doxygen. When specifying no_extension you should add
+# * to the FILE_PATTERNS.
+#
+# Note see also the list of default file extension mappings.
 
 EXTENSION_MAPPING      =
 
 # If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments
 # according to the Markdown format, which allows for more readable
-# documentation. See http://daringfireball.net/projects/markdown/ for details.
+# documentation. See https://daringfireball.net/projects/markdown/ for details.
 # The output of markdown processing is further processed by doxygen, so you can
 # mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in
 # case of backward compatibilities issues.
@@ -517,6 +559,15 @@ EXTENSION_MAPPING      =
 
 MARKDOWN_SUPPORT       = YES
 
+# When the TOC_INCLUDE_HEADINGS tag is set to a non-zero value, all headings up
+# to that level are automatically included in the table of contents, even if
+# they do not have an id attribute.
+# Note: This feature currently applies only to Markdown headings.
+# Minimum value: 0, maximum value: 99, default value: 5.
+# This tag requires that the tag MARKDOWN_SUPPORT is set to YES.
+
+TOC_INCLUDE_HEADINGS = 5
+
 # When enabled doxygen tries to link words that correspond to documented
 # classes, or namespaces to their corresponding documentation. Such a link can
 # be prevented in individual cases by putting a % sign in front of the word or
@@ -542,7 +593,7 @@ BUILTIN_STL_SUPPORT    = YES
 CPP_CLI_SUPPORT        = NO
 
 # Set the SIP_SUPPORT tag to YES if your project consists of sip (see:
-# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen
+# https://www.riverbankcomputing.com/software/sip/intro) sources only. Doxygen
 # will parse them like normal C++ but will assume all classes use public instead
 # of private inheritance when no explicit protection keyword is present.
 # The default value is: NO.
@@ -628,6 +679,19 @@ TYPEDEF_HIDES_STRUCT   = NO
 
 LOOKUP_CACHE_SIZE      = 0
 
+# The NUM_PROC_THREADS specifies the number threads doxygen is allowed to use
+# during processing. When set to 0 doxygen will based this on the number of
+# cores available in the system. You can set it explicitly to a value larger
+# than 0 to get more control over the balance between CPU load and processing
+# speed. At this moment only the input processing can be done using multiple
+# threads. Since this is still an experimental feature the default is set to 1,
+# which efficively disables parallel processing. Please report any issues you
+# encounter. Generating dot graphs in parallel is controlled by the
+# DOT_NUM_THREADS setting.
+# Minimum value: 0, maximum value: 32, default value: 1.
+
+###1.9.1###NUM_PROC_THREADS = 1
+
 #---------------------------------------------------------------------------
 # Build related configuration options
 #---------------------------------------------------------------------------
@@ -648,6 +712,12 @@ EXTRACT_ALL            = YES
 
 EXTRACT_PRIVATE        = YES
 
+# If the EXTRACT_PRIV_VIRTUAL tag is set to YES, documented private virtual
+# methods of a class will be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PRIV_VIRTUAL = NO
+
 # If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal
 # scope will be included in the documentation.
 # The default value is: NO.
@@ -685,6 +755,13 @@ EXTRACT_LOCAL_METHODS  = NO
 
 EXTRACT_ANON_NSPACES   = NO
 
+# If this flag is set to YES, the name of an unnamed parameter in a declaration
+# will be determined by the corresponding definition. By default unnamed
+# parameters remain unnamed in the output.
+# The default value is: YES.
+
+###1.9.1###RESOLVE_UNNAMED_PARAMS = YES
+
 # If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all
 # undocumented members inside documented classes or files. If set to NO these
 # members will be included in the various overviews, but no documentation
@@ -702,8 +779,8 @@ HIDE_UNDOC_MEMBERS     = NO
 HIDE_UNDOC_CLASSES     = NO
 
 # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend
-# (class|struct|union) declarations. If set to NO, these declarations will be
-# included in the documentation.
+# declarations. If set to NO, these declarations will be included in the
+# documentation.
 # The default value is: NO.
 
 HIDE_FRIEND_COMPOUNDS  = NO
@@ -722,11 +799,18 @@ HIDE_IN_BODY_DOCS      = NO
 
 INTERNAL_DOCS          = NO
 
-# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file
-# names in lower-case letters. If set to YES, upper-case letters are also
-# allowed. This is useful if you have classes or files whose names only differ
-# in case and if your file system supports case sensitive file names. Windows
-# and Mac users are advised to set this option to NO.
+# With the correct setting of option CASE_SENSE_NAMES doxygen will better be
+# able to match the capabilities of the underlying filesystem. In case the
+# filesystem is case sensitive (i.e. it supports files in the same directory
+# whose names only differ in casing), the option must be set to YES to properly
+# deal with such files in case they appear in the input. For filesystems that
+# are not case sensitive the option should be be set to NO to properly deal with
+# output files written for symbols that only differ in casing, such as for two
+# classes, one named CLASS and the other named Class, and to also support
+# references to files without having to specify the exact matching casing. On
+# Windows (including Cygwin) and MacOS, users should typically set this option
+# to NO, whereas on Linux or other Unix flavors it should typically be set to
+# YES.
 # The default value is: system dependent.
 
 CASE_SENSE_NAMES       = NO
@@ -913,7 +997,7 @@ LAYOUT_FILE            = @DOXYGEN_DOCS_DIR@/DaliLayout.xml
 # The CITE_BIB_FILES tag can be used to specify one or more bib files containing
 # the reference definitions. This must be a list of .bib files. The .bib
 # extension is automatically appended if omitted. This requires the bibtex tool
-# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info.
+# to be installed. See also https://en.wikipedia.org/wiki/BibTeX for more info.
 # For LaTeX the style of the bibliography can be controlled using
 # LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the
 # search path. See also \cite for info how to create references.
@@ -958,13 +1042,17 @@ WARN_IF_DOC_ERROR      = YES
 # This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that
 # are documented, but have no documentation for their parameters or return
 # value. If set to NO, doxygen will only warn about wrong or incomplete
-# parameter documentation, but not about the absence of documentation.
+# parameter documentation, but not about the absence of documentation. If
+# EXTRACT_ALL is set to YES then this flag will automatically be disabled.
 # The default value is: NO.
 
 WARN_NO_PARAMDOC       = YES
 
 # If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when
-# a warning is encountered.
+# a warning is encountered. If the WARN_AS_ERROR tag is set to FAIL_ON_WARNINGS
+# then doxygen will continue running as if WARN_AS_ERROR tag is set to NO, but
+# at the end of the doxygen process doxygen will return with a non-zero status.
+# Possible values are: NO, YES and FAIL_ON_WARNINGS.
 # The default value is: NO.
 
 WARN_AS_ERROR          = NO
@@ -1009,8 +1097,8 @@ INPUT                  = @DOXYGEN_DOCS_DIR@/content \
 # This tag can be used to specify the character encoding of the source files
 # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
 # libiconv (or the iconv built into libc) for the transcoding. See the libiconv
-# documentation (see: http://www.gnu.org/software/libiconv) for the list of
-# possible encodings.
+# documentation (see:
+# https://www.gnu.org/software/libiconv/) for the list of possible encodings.
 # The default value is: UTF-8.
 
 INPUT_ENCODING         = UTF-8
@@ -1023,11 +1111,15 @@ INPUT_ENCODING         = UTF-8
 # need to set EXTENSION_MAPPING for the extension otherwise the files are not
 # read by doxygen.
 #
+# Note the list of default checked file patterns might differ from the list of
+# default file extension mappings.
+#
 # If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp,
 # *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h,
 # *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc,
-# *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.pyw, *.f90, *.f, *.for, *.tcl,
-# *.vhd, *.vhdl, *.ucf, *.qsf, *.as and *.js.
+# *.m, *.markdown, *.md, *.mm, *.dox (to be provided as doxygen C comment),
+# *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, *.f18, *.f, *.for, *.vhd, *.vhdl,
+# *.ucf, *.qsf and *.ice.
 
 FILE_PATTERNS          = *.h \
                          *.md
@@ -1187,7 +1279,7 @@ INLINE_SOURCES         = NO
 STRIP_CODE_COMMENTS    = NO
 
 # If the REFERENCED_BY_RELATION tag is set to YES then for each documented
-# function all documented functions referencing it will be listed.
+# entity all documented functions referencing it will be listed.
 # The default value is: NO.
 
 REFERENCED_BY_RELATION = NO
@@ -1219,12 +1311,12 @@ SOURCE_TOOLTIPS        = YES
 # If the USE_HTAGS tag is set to YES then the references to source code will
 # point to the HTML generated by the htags(1) tool instead of doxygen built-in
 # source browser. The htags tool is part of GNU's global source tagging system
-# (see http://www.gnu.org/software/global/global.html). You will need version
+# (see https://www.gnu.org/software/global/global.html). You will need version
 # 4.8.6 or higher.
 #
 # To use it do the following:
 # - Install the latest version of global
-# - Enable SOURCE_BROWSER and USE_HTAGS in the config file
+# - Enable SOURCE_BROWSER and USE_HTAGS in the configuration file
 # - Make sure the INPUT points to the root of the source tree
 # - Run doxygen as normal
 #
@@ -1247,16 +1339,22 @@ USE_HTAGS              = NO
 VERBATIM_HEADERS       = YES
 
 # If the CLANG_ASSISTED_PARSING tag is set to YES then doxygen will use the
-# clang parser (see: http://clang.llvm.org/) for more accurate parsing at the
-# cost of reduced performance. This can be particularly helpful with template
-# rich C++ code for which doxygen's built-in parser lacks the necessary type
-# information.
+# clang parser (see:
+# http://clang.llvm.org/) for more accurate parsing at the cost of reduced
+# performance. This can be particularly helpful with template rich C++ code for
+# which doxygen's built-in parser lacks the necessary type information.
 # Note: The availability of this option depends on whether or not doxygen was
-# generated with the -Duse-libclang=ON option for CMake.
+# generated with the -Duse_libclang=ON option for CMake.
 # The default value is: NO.
 
 CLANG_ASSISTED_PARSING = NO
 
+# If clang assisted parsing is enabled and the CLANG_ADD_INC_PATHS tag is set to
+# YES then doxygen will add the directory of each input to the include path.
+# The default value is: YES.
+
+###1.9.1###CLANG_ADD_INC_PATHS = YES
+
 # If clang assisted parsing is enabled you can provide the compiler with command
 # line options that you would normally use when invoking the compiler. Note that
 # the include paths will already be set by doxygen for the files and directories
@@ -1265,6 +1363,19 @@ CLANG_ASSISTED_PARSING = NO
 
 CLANG_OPTIONS          =
 
+# If clang assisted parsing is enabled you can provide the clang parser with the
+# path to the directory containing a file called compile_commands.json. This
+# file is the compilation database (see:
+# http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html) containing the
+# options used when the source files were built. This is equivalent to
+# specifying the -p option to a clang tool, such as clang-check. These options
+# will then be passed to the parser. Any options specified with CLANG_OPTIONS
+# will be added as well.
+# Note: The availability of this option depends on whether or not doxygen was
+# generated with the -Duse_libclang=ON option for CMake.
+
+CLANG_DATABASE_PATH =
+
 #---------------------------------------------------------------------------
 # Configuration options related to the alphabetical class index
 #---------------------------------------------------------------------------
@@ -1276,13 +1387,6 @@ CLANG_OPTIONS          =
 
 ALPHABETICAL_INDEX     = NO
 
-# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in
-# which the alphabetical index list will be split.
-# Minimum value: 1, maximum value: 20, default value: 5.
-# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
-
-COLS_IN_ALPHA_INDEX    = 5
-
 # In case all classes in a project start with a common prefix, all classes will
 # be put under the same header in the alphabetical index. The IGNORE_PREFIX tag
 # can be used to specify a prefix (or a list of prefixes) that should be ignored
@@ -1383,7 +1487,7 @@ HTML_EXTRA_FILES       =
 # The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
 # will adjust the colors in the style sheet and background images according to
 # this color. Hue is specified as an angle on a colorwheel, see
-# http://en.wikipedia.org/wiki/Hue for more information. For instance the value
+# https://en.wikipedia.org/wiki/Hue for more information. For instance the value
 # 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300
 # purple, and 360 is red again.
 # Minimum value: 0, maximum value: 359, default value: 220.
@@ -1419,6 +1523,17 @@ HTML_COLORSTYLE_GAMMA  = 80
 
 HTML_TIMESTAMP         = YES
 
+# If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML
+# documentation will contain a main index with vertical navigation menus that
+# are dynamically created via JavaScript. If disabled, the navigation index will
+# consists of multiple levels of tabs that are statically embedded in every HTML
+# page. Disable this option to support browsers that do not have JavaScript,
+# like the Qt help browser.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_DYNAMIC_MENUS = YES
+
 # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
 # documentation will contain sections that can be hidden and shown after the
 # page has loaded.
@@ -1442,13 +1557,14 @@ HTML_INDEX_NUM_ENTRIES = 100
 
 # If the GENERATE_DOCSET tag is set to YES, additional index files will be
 # generated that can be used as input for Apple's Xcode 3 integrated development
-# environment (see: http://developer.apple.com/tools/xcode/), introduced with
-# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a
-# Makefile in the HTML output directory. Running make will produce the docset in
-# that directory and running make install will install the docset in
+# environment (see:
+# https://developer.apple.com/xcode/), introduced with OSX 10.5 (Leopard). To
+# create a documentation set, doxygen will generate a Makefile in the HTML
+# output directory. Running make will produce the docset in that directory and
+# running make install will install the docset in
 # ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at
-# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html
-# for more information.
+# startup. See https://developer.apple.com/library/archive/featuredarticles/Doxy
+# genXcode/_index.html for more information.
 # The default value is: NO.
 # This tag requires that the tag GENERATE_HTML is set to YES.
 
@@ -1487,8 +1603,8 @@ DOCSET_PUBLISHER_NAME  = Publisher
 # If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three
 # additional HTML index files: index.hhp, index.hhc, and index.hhk. The
 # index.hhp is a project file that can be read by Microsoft's HTML Help Workshop
-# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on
-# Windows.
+# (see:
+# https://www.microsoft.com/en-us/download/details.aspx?id=21138) on Windows.
 #
 # The HTML Help Workshop contains a compiler that can convert all HTML output
 # generated by doxygen into a single compiled HTML file (.chm). Compiled HTML
@@ -1518,7 +1634,7 @@ CHM_FILE               = dali.chm
 HHC_LOCATION           =
 
 # The GENERATE_CHI flag controls if a separate .chi index file is generated
-# (YES) or that it should be included in the master .chm file (NO).
+# (YES) or that it should be included in the main .chm file (NO).
 # The default value is: NO.
 # This tag requires that the tag GENERATE_HTMLHELP is set to YES.
 
@@ -1563,7 +1679,8 @@ QCH_FILE               = "Dali.qch"
 
 # The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help
 # Project output. For more information please see Qt Help Project / Namespace
-# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace).
+# (see:
+# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace).
 # The default value is: org.doxygen.Project.
 # This tag requires that the tag GENERATE_QHP is set to YES.
 
@@ -1571,8 +1688,8 @@ QHP_NAMESPACE          = "Dali"
 
 # The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt
 # Help Project output. For more information please see Qt Help Project / Virtual
-# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual-
-# folders).
+# Folders (see:
+# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual-folders).
 # The default value is: doc.
 # This tag requires that the tag GENERATE_QHP is set to YES.
 
@@ -1580,30 +1697,30 @@ QHP_VIRTUAL_FOLDER     = doc
 
 # If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom
 # filter to add. For more information please see Qt Help Project / Custom
-# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
-# filters).
+# Filters (see:
+# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters).
 # This tag requires that the tag GENERATE_QHP is set to YES.
 
 QHP_CUST_FILTER_NAME   =
 
 # The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the
 # custom filter to add. For more information please see Qt Help Project / Custom
-# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
-# filters).
+# Filters (see:
+# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters).
 # This tag requires that the tag GENERATE_QHP is set to YES.
 
 QHP_CUST_FILTER_ATTRS  =
 
 # The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
 # project's filter section matches. Qt Help Project / Filter Attributes (see:
-# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes).
+# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#filter-attributes).
 # This tag requires that the tag GENERATE_QHP is set to YES.
 
 QHP_SECT_FILTER_ATTRS  =
 
-# The QHG_LOCATION tag can be used to specify the location of Qt's
-# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the
-# generated .qhp file.
+# The QHG_LOCATION tag can be used to specify the location (absolute path
+# including file name) of Qt's qhelpgenerator. If non-empty doxygen will try to
+# run qhelpgenerator on the generated .qhp file.
 # This tag requires that the tag GENERATE_QHP is set to YES.
 
 QHG_LOCATION           =
@@ -1680,6 +1797,17 @@ TREEVIEW_WIDTH         = 250
 
 EXT_LINKS_IN_WINDOW    = NO
 
+# If the HTML_FORMULA_FORMAT option is set to svg, doxygen will use the pdf2svg
+# tool (see https://github.com/dawbarton/pdf2svg) or inkscape (see
+# https://inkscape.org) to generate formulas as SVG images instead of PNGs for
+# the HTML output. These images will generally look nicer at scaled resolutions.
+# Possible values are: png (the default) and svg (looks nicer but requires the
+# pdf2svg or inkscape tool).
+# The default value is: png.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+###1.9.1###HTML_FORMULA_FORMAT = png
+
 # Use this tag to change the font size of LaTeX formulas included as images in
 # the HTML documentation. When you change the font size after a successful
 # doxygen run you need to manually remove any form_*.png images from the HTML
@@ -1689,7 +1817,7 @@ EXT_LINKS_IN_WINDOW    = NO
 
 FORMULA_FONTSIZE       = 10
 
-# Use the FORMULA_TRANPARENT tag to determine whether or not the images
+# Use the FORMULA_TRANSPARENT tag to determine whether or not the images
 # generated for formulas are transparent PNGs. Transparent PNGs are not
 # supported properly for IE 6.0, but are supported on all modern browsers.
 #
@@ -1700,8 +1828,14 @@ FORMULA_FONTSIZE       = 10
 
 FORMULA_TRANSPARENT    = YES
 
+# The FORMULA_MACROFILE can contain LaTeX \newcommand and \renewcommand commands
+# to create new LaTeX commands to be used in formulas as building blocks. See
+# the section "Including formulas" for details.
+
+FORMULA_MACROFILE =
+
 # Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see
-# http://www.mathjax.org) which uses client side Javascript for the rendering
+# https://www.mathjax.org) which uses client side JavaScript for the rendering
 # instead of using pre-rendered bitmaps. Use this if you do not have LaTeX
 # installed or if you want to formulas look prettier in the HTML output. When
 # enabled you may also need to install MathJax separately and configure the path
@@ -1713,7 +1847,7 @@ USE_MATHJAX            = NO
 
 # When MathJax is enabled you can set the default output format to be used for
 # the MathJax output. See the MathJax site (see:
-# http://docs.mathjax.org/en/latest/output.html) for more details.
+# http://docs.mathjax.org/en/v2.7-latest/output.html) for more details.
 # Possible values are: HTML-CSS (which is slower, but has the best
 # compatibility), NativeMML (i.e. MathML) and SVG.
 # The default value is: HTML-CSS.
@@ -1728,8 +1862,8 @@ MATHJAX_FORMAT         = HTML-CSS
 # MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax
 # Content Delivery Network so you can quickly see the result without installing
 # MathJax. However, it is strongly recommended to install a local copy of
-# MathJax from http://www.mathjax.org before deployment.
-# The default value is: http://cdn.mathjax.org/mathjax/latest.
+# MathJax from https://www.mathjax.org before deployment.
+# The default value is: https://cdn.jsdelivr.net/npm/mathjax@2.
 # This tag requires that the tag USE_MATHJAX is set to YES.
 
 MATHJAX_RELPATH        = http://cdn.mathjax.org/mathjax/latest
@@ -1743,7 +1877,8 @@ MATHJAX_EXTENSIONS     =
 
 # The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces
 # of code that will be used on startup of the MathJax code. See the MathJax site
-# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an
+# (see:
+# http://docs.mathjax.org/en/v2.7-latest/output.html) for more details. For an
 # example see the documentation.
 # This tag requires that the tag USE_MATHJAX is set to YES.
 
@@ -1771,7 +1906,7 @@ MATHJAX_CODEFILE       =
 SEARCHENGINE           = NO
 
 # When the SERVER_BASED_SEARCH tag is enabled the search engine will be
-# implemented using a web server instead of a web client using Javascript. There
+# implemented using a web server instead of a web client using JavaScript. There
 # are two flavors of web server based searching depending on the EXTERNAL_SEARCH
 # setting. When disabled, doxygen will generate a PHP script for searching and
 # an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing
@@ -1790,7 +1925,8 @@ SERVER_BASED_SEARCH    = NO
 #
 # Doxygen ships with an example indexer (doxyindexer) and search engine
 # (doxysearch.cgi) which are based on the open source search engine library
-# Xapian (see: http://xapian.org/).
+# Xapian (see:
+# https://xapian.org/).
 #
 # See the section "External Indexing and Searching" for details.
 # The default value is: NO.
@@ -1803,8 +1939,9 @@ EXTERNAL_SEARCH        = NO
 #
 # Doxygen ships with an example indexer (doxyindexer) and search engine
 # (doxysearch.cgi) which are based on the open source search engine library
-# Xapian (see: http://xapian.org/). See the section "External Indexing and
-# Searching" for details.
+# Xapian (see:
+# https://xapian.org/). See the section "External Indexing and Searching" for
+# details.
 # This tag requires that the tag SEARCHENGINE is set to YES.
 
 SEARCHENGINE_URL       =
@@ -1855,21 +1992,35 @@ LATEX_OUTPUT           = latex
 # The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
 # invoked.
 #
-# Note that when enabling USE_PDFLATEX this option is only used for generating
-# bitmaps for formulas in the HTML output, but not in the Makefile that is
-# written to the output directory.
-# The default file is: latex.
+# Note that when not enabling USE_PDFLATEX the default is latex when enabling
+# USE_PDFLATEX the default is pdflatex and when in the later case latex is
+# chosen this is overwritten by pdflatex. For specific output languages the
+# default can have been set differently, this depends on the implementation of
+# the output language.
 # This tag requires that the tag GENERATE_LATEX is set to YES.
 
 LATEX_CMD_NAME         = latex
 
 # The MAKEINDEX_CMD_NAME tag can be used to specify the command name to generate
 # index for LaTeX.
+# Note: This tag is used in the Makefile / make.bat.
+# See also: LATEX_MAKEINDEX_CMD for the part in the generated output file
+# (.tex).
 # The default file is: makeindex.
 # This tag requires that the tag GENERATE_LATEX is set to YES.
 
 MAKEINDEX_CMD_NAME     = makeindex
 
+# The LATEX_MAKEINDEX_CMD tag can be used to specify the command name to
+# generate index for LaTeX. In case there is no backslash (\) as first character
+# it will be automatically added in the LaTeX code.
+# Note: This tag is used in the generated output file (.tex).
+# See also: MAKEINDEX_CMD_NAME for the part in the Makefile / make.bat.
+# The default value is: makeindex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_MAKEINDEX_CMD = makeindex
+
 # If the COMPACT_LATEX tag is set to YES, doxygen generates more compact LaTeX
 # documents. This may be useful for small projects and may help to save some
 # trees in general.
@@ -1885,7 +2036,7 @@ COMPACT_LATEX          = NO
 # The default value is: a4.
 # This tag requires that the tag GENERATE_LATEX is set to YES.
 
-PAPER_TYPE             = a4wide
+PAPER_TYPE             = a4
 
 # The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names
 # that should be included in the LaTeX output. The package can be specified just
@@ -1954,9 +2105,11 @@ LATEX_EXTRA_FILES      =
 
 PDF_HYPERLINKS         = YES
 
-# If the USE_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate
-# the PDF file directly from the LaTeX files. Set this option to YES, to get a
-# higher quality PDF documentation.
+# If the USE_PDFLATEX tag is set to YES, doxygen will use the engine as
+# specified with LATEX_CMD_NAME to generate the PDF file directly from the LaTeX
+# files. Set this option to YES, to get a higher quality PDF documentation.
+#
+# See also section LATEX_CMD_NAME for selecting the engine.
 # The default value is: YES.
 # This tag requires that the tag GENERATE_LATEX is set to YES.
 
@@ -1990,7 +2143,7 @@ LATEX_SOURCE_CODE      = NO
 
 # The LATEX_BIB_STYLE tag can be used to specify the style to use for the
 # bibliography, e.g. plainnat, or ieeetr. See
-# http://en.wikipedia.org/wiki/BibTeX and \cite for more info.
+# https://en.wikipedia.org/wiki/BibTeX and \cite for more info.
 # The default value is: plain.
 # This tag requires that the tag GENERATE_LATEX is set to YES.
 
@@ -2004,6 +2157,14 @@ LATEX_BIB_STYLE        = plain
 
 LATEX_TIMESTAMP        = NO
 
+# The LATEX_EMOJI_DIRECTORY tag is used to specify the (relative or absolute)
+# path from which the emoji images will be read. If a relative path is entered,
+# it will be relative to the LATEX_OUTPUT directory. If left blank the
+# LATEX_OUTPUT directory will be used.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EMOJI_DIRECTORY =
+
 #---------------------------------------------------------------------------
 # Configuration options related to the RTF output
 #---------------------------------------------------------------------------
@@ -2043,9 +2204,9 @@ COMPACT_RTF            = NO
 
 RTF_HYPERLINKS         = NO
 
-# Load stylesheet definitions from file. Syntax is similar to doxygen's config
-# file, i.e. a series of assignments. You only have to provide replacements,
-# missing definitions are set to their default value.
+# Load stylesheet definitions from file. Syntax is similar to doxygen's
+# configuration file, i.e. a series of assignments. You only have to provide
+# replacements, missing definitions are set to their default value.
 #
 # See also section "Doxygen usage" for information on how to generate the
 # default style sheet that doxygen normally uses.
@@ -2054,8 +2215,8 @@ RTF_HYPERLINKS         = NO
 RTF_STYLESHEET_FILE    =
 
 # Set optional variables used in the generation of an RTF document. Syntax is
-# similar to doxygen's config file. A template extensions file can be generated
-# using doxygen -e rtf extensionFile.
+# similar to doxygen's configuration file. A template extensions file can be
+# generated using doxygen -e rtf extensionFile.
 # This tag requires that the tag GENERATE_RTF is set to YES.
 
 RTF_EXTENSIONS_FILE    =
@@ -2141,6 +2302,13 @@ XML_OUTPUT             = xml
 
 XML_PROGRAMLISTING     = YES
 
+# If the XML_NS_MEMB_FILE_SCOPE tag is set to YES, doxygen will include
+# namespace members in file scope as well, matching the HTML output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_NS_MEMB_FILE_SCOPE = NO
+
 #---------------------------------------------------------------------------
 # Configuration options related to the DOCBOOK output
 #---------------------------------------------------------------------------
@@ -2173,9 +2341,9 @@ DOCBOOK_PROGRAMLISTING = NO
 #---------------------------------------------------------------------------
 
 # If the GENERATE_AUTOGEN_DEF tag is set to YES, doxygen will generate an
-# AutoGen Definitions (see http://autogen.sf.net) file that captures the
-# structure of the code including all documentation. Note that this feature is
-# still experimental and incomplete at the moment.
+# AutoGen Definitions (see http://autogen.sourceforge.net/) file that captures
+# the structure of the code including all documentation. Note that this feature
+# is still experimental and incomplete at the moment.
 # The default value is: NO.
 
 GENERATE_AUTOGEN_DEF   = NO
@@ -2346,12 +2514,6 @@ EXTERNAL_GROUPS        = YES
 
 EXTERNAL_PAGES         = YES
 
-# The PERL_PATH should be the absolute path and name of the perl script
-# interpreter (i.e. the result of 'which perl').
-# The default file (with absolute path) is: /usr/bin/perl.
-
-#PERL_PATH              = /usr/bin/perl
-
 #---------------------------------------------------------------------------
 # Configuration options related to the dot tool
 #---------------------------------------------------------------------------
@@ -2365,15 +2527,6 @@ EXTERNAL_PAGES         = YES
 
 CLASS_DIAGRAMS         = YES
 
-# You can define message sequence charts within doxygen comments using the \msc
-# command. Doxygen will then run the mscgen tool (see:
-# http://www.mcternan.me.uk/mscgen/)) to produce the chart and insert it in the
-# documentation. The MSCGEN_PATH tag allows you to specify the directory where
-# the mscgen tool resides. If left empty the tool is assumed to be found in the
-# default search path.
-
-#MSCGEN_PATH            =
-
 # You can include diagrams made with dia in doxygen documentation. Doxygen will
 # then run dia to produce the diagram and insert it in the documentation. The
 # DIA_PATH tag allows you to specify the directory where the dia binary resides.
@@ -2471,9 +2624,31 @@ UML_LOOK               = NO
 # but if the number exceeds 15, the total amount of fields shown is limited to
 # 10.
 # Minimum value: 0, maximum value: 100, default value: 10.
+# This tag requires that the tag UML_LOOK is set to YES.
+
+UML_LIMIT_NUM_FIELDS = 10
+
+# If the DOT_UML_DETAILS tag is set to NO, doxygen will show attributes and
+# methods without types and arguments in the UML graphs. If the DOT_UML_DETAILS
+# tag is set to YES, doxygen will add type and arguments for attributes and
+# methods in the UML graphs. If the DOT_UML_DETAILS tag is set to NONE, doxygen
+# will not generate fields with class member information in the UML graphs. The
+# class diagrams will look similar to the default class diagrams but using UML
+# notation for the relationships.
+# Possible values are: NO, YES and NONE.
+# The default value is: NO.
+# This tag requires that the tag UML_LOOK is set to YES.
+
+###1.9.1###DOT_UML_DETAILS = NO
+
+# The DOT_WRAP_THRESHOLD tag can be used to set the maximum number of characters
+# to display on a single line. If the actual line length exceeds this threshold
+# significantly it will wrapped across multiple lines. Some heuristics are apply
+# to avoid ugly line breaks.
+# Minimum value: 0, maximum value: 1000, default value: 17.
 # This tag requires that the tag HAVE_DOT is set to YES.
 
-UML_LIMIT_NUM_FIELDS   = 10
+###1.9.1###DOT_WRAP_THRESHOLD = 17
 
 # If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and
 # collaboration graphs will show the relations between templates and their
@@ -2603,6 +2778,11 @@ DIAFILE_DIRS           =
 
 PLANTUML_JAR_PATH      =
 
+# When using plantuml, the PLANTUML_CFG_FILE tag can be used to specify a
+# configuration file for plantuml.
+
+PLANTUML_CFG_FILE =
+
 # When using plantuml, the specified paths are searched for files specified by
 # the !include statement in a plantuml block.
 
@@ -2661,9 +2841,11 @@ DOT_MULTI_TARGETS      = NO
 
 GENERATE_LEGEND        = YES
 
-# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate dot
+# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate
 # files that are used to generate the various graphs.
+#
+# Note: This setting is not only used for dot files but also for msc and
+# plantuml temporary files.
 # The default value is: YES.
-# This tag requires that the tag HAVE_DOT is set to YES.
 
 DOT_CLEANUP            = YES
index 73f1248..8b95f82 100644 (file)
@@ -507,8 +507,8 @@ void Model::LoadModel()
 
   if(!animations.empty())
   {
-    auto getActor = [&](const std::string& name) {
-      return mModelRoot.FindChildByName(name);
+    auto getActor = [&](const Scene3D::Loader::AnimatedProperty& property) {
+      return mModelRoot.FindChildById(scene.GetNode(property.mNodeIndex)->mNodeId);
     };
 
     mAnimations.clear();
index e8fb48e..169cef9 100644 (file)
@@ -25,6 +25,7 @@
 #include <dali-toolkit/internal/controls/control/control-data-impl.h>
 #include <dali-toolkit/public-api/image-loader/image-url.h>
 #include <dali-toolkit/public-api/image-loader/image.h>
+#include <dali-toolkit/public-api/image-loader/sync-image-loader.h>
 #include <dali/devel-api/actors/camera-actor-devel.h>
 #include <dali/devel-api/adaptor-framework/window-devel.h>
 #include <dali/devel-api/common/stage.h>
@@ -65,7 +66,7 @@ constexpr uint8_t DEFAULT_FRAME_BUFFER_MULTI_SAMPLING_LEVEL = 4u;
 
 static constexpr std::string_view SKYBOX_INTENSITY_STRING = "uIntensity";
 
-Dali::Actor CreateSkybox(const std::string& skyboxUrl)
+Dali::Actor CreateSkybox(const std::string& skyboxUrl, Scene3D::SceneView::SkyboxType skyboxType)
 {
   struct Vertex
   {
@@ -121,7 +122,6 @@ Dali::Actor CreateSkybox(const std::string& skyboxUrl)
     {Vector3(-1.0f, -1.0f, 1.0f)},
     {Vector3(1.0f, -1.0f, 1.0f)}};
 
-  Dali::Shader       shaderSkybox = Shader::New(SHADER_SKYBOX_SHADER_VERT.data(), SHADER_SKYBOX_SHADER_FRAG.data());
   Dali::VertexBuffer vertexBuffer = Dali::VertexBuffer::New(Property::Map().Add("aPosition", Property::VECTOR3));
   vertexBuffer.SetData(skyboxVertices, sizeof(skyboxVertices) / sizeof(Vertex));
 
@@ -129,11 +129,29 @@ Dali::Actor CreateSkybox(const std::string& skyboxUrl)
   skyboxGeometry.AddVertexBuffer(vertexBuffer);
   skyboxGeometry.SetType(Geometry::TRIANGLES);
 
-  Dali::Texture    skyboxTexture  = Dali::Scene3D::Loader::LoadCubeMap(skyboxUrl);
+  Dali::Texture  skyboxTexture;
+  Dali::Shader   shaderSkybox;
+  Dali::Renderer skyboxRenderer;
+
+  if(skyboxType == Scene3D::SceneView::SkyboxType::CUBEMAP)
+  {
+    skyboxTexture = Dali::Scene3D::Loader::LoadCubeMap(skyboxUrl);
+    shaderSkybox  = Shader::New(SHADER_SKYBOX_SHADER_VERT.data(), SHADER_SKYBOX_SHADER_FRAG.data());
+  }
+  else // Scene3D::SceneView::SkyboxType::EQUIRECTANGULAR
+  {
+    // Load image from file
+    PixelData pixels = Dali::Toolkit::SyncImageLoader::Load(skyboxUrl);
+
+    skyboxTexture = Texture::New(TextureType::TEXTURE_2D, pixels.GetPixelFormat(), pixels.GetWidth(), pixels.GetHeight());
+    skyboxTexture.Upload(pixels, 0, 0, 0, 0, pixels.GetWidth(), pixels.GetHeight());
+    shaderSkybox = Shader::New(SHADER_SKYBOX_SHADER_VERT.data(), SHADER_SKYBOX_EQUIRECTANGULAR_SHADER_FRAG.data());
+  }
+
   Dali::TextureSet skyboxTextures = TextureSet::New();
   skyboxTextures.SetTexture(0, skyboxTexture);
 
-  Dali::Renderer skyboxRenderer = Renderer::New(skyboxGeometry, shaderSkybox);
+  skyboxRenderer = Renderer::New(skyboxGeometry, shaderSkybox);
   skyboxRenderer.SetTextures(skyboxTextures);
   skyboxRenderer.SetProperty(Renderer::Property::DEPTH_INDEX, 2.0f);
   // Enables the depth test.
@@ -338,7 +356,7 @@ bool SceneView::IsUsingFramebuffer() const
   return mUseFrameBuffer;
 }
 
-void SceneView::SetSkybox(const std::string& skyboxUrl)
+void SceneView::SetSkybox(const std::string& skyboxUrl, Scene3D::SceneView::SkyboxType skyboxType)
 {
   mSkyboxResourceReady = false;
   if(mSkybox)
@@ -346,7 +364,7 @@ void SceneView::SetSkybox(const std::string& skyboxUrl)
     mSkybox.Unparent();
     mSkybox.Reset();
   }
-  mSkybox = CreateSkybox(skyboxUrl);
+  mSkybox = CreateSkybox(skyboxUrl, skyboxType);
   SetSkyboxIntensity(mSkyboxIntensity);
   SetSkyboxOrientation(mSkyboxOrientation);
   if(mRootLayer)
@@ -550,10 +568,19 @@ void SceneView::UpdateRenderTask()
         Property::Map imagePropertyMap;
         imagePropertyMap.Insert(Toolkit::Visual::Property::TYPE, Toolkit::Visual::IMAGE);
         imagePropertyMap.Insert(Toolkit::ImageVisual::Property::URL, imageUrl.GetUrl());
+        // To make sure this visual call LoadTexture API immediate.
+        imagePropertyMap.Insert(Toolkit::ImageVisual::Property::LOAD_POLICY, Toolkit::ImageVisual::LoadPolicy::IMMEDIATE);
+        imagePropertyMap.Insert(Toolkit::ImageVisual::Property::RELEASE_POLICY, Toolkit::ImageVisual::ReleasePolicy::DESTROYED);
         // To flip rendered scene without CameraActor::SetInvertYAxis() to avoid backface culling.
         imagePropertyMap.Insert(Toolkit::ImageVisual::Property::PIXEL_AREA, Vector4(0.0f, 1.0f, 1.0f, -1.0f));
         mVisual = Toolkit::VisualFactory::Get().CreateVisual(imagePropertyMap);
 
+        // Use premultiplied alpha when we use FBO
+        if(mVisual)
+        {
+          Toolkit::GetImplementation(mVisual).EnablePreMultipliedAlpha(true);
+        }
+
         Toolkit::DevelControl::RegisterVisual(*this, RENDERING_BUFFER, mVisual);
 
         mRenderTask.SetFrameBuffer(mFrameBuffer);
index f5e4f82..def2b83 100644 (file)
@@ -140,7 +140,7 @@ public:
   /**
    * @copydoc SceneView::SetSkybox()
    */
-  void SetSkybox(const std::string& skyboxUrl);
+  void SetSkybox(const std::string& skyboxUrl, Scene3D::SceneView::SkyboxType skyboxType);
 
   /**
    * @copydoc SceneView::SetSkyboxIntensity()
index 8c9e7ea..bca3ba0 100644 (file)
@@ -55,15 +55,6 @@ uniform sampler2D sAlbedoMetal;
 uniform sampler2D sNormalRoughness;
 #endif
 
-uniform float uSpecularFactor;
-uniform vec3  uSpecularColorFactor;
-#ifdef MATERIAL_SPECULAR_TEXTURE
-uniform sampler2D sSpecular;
-#endif
-#ifdef MATERIAL_SPECULAR_COLOR_TEXTURE
-uniform sampler2D sSpecularColor;
-#endif
-
 #ifdef OCCLUSION
 uniform sampler2D sOcclusion;
 uniform float uOcclusionStrength;
@@ -74,6 +65,15 @@ uniform sampler2D sEmissive;
 uniform vec3 uEmissiveFactor;
 #endif
 
+uniform float uSpecularFactor;
+uniform vec3  uSpecularColorFactor;
+#ifdef MATERIAL_SPECULAR_TEXTURE
+uniform sampler2D sSpecular;
+#endif
+#ifdef MATERIAL_SPECULAR_COLOR_TEXTURE
+uniform sampler2D sSpecularColor;
+#endif
+
 //// For IBL
 uniform sampler2D sbrdfLUT;
 uniform samplerCube sDiffuseEnvSampler;
@@ -146,12 +146,15 @@ void main()
 #endif // THREE_TEX
 
   // The value of uOpaque and uMask can be 0.0 or 1.0.
+  // If uMask is 1.0, a Pixel that has bigger alpha than uAlphaThreashold becomes fully opaque,
+  // and, a pixel that has smaller alpha than uAlphaThreashold becomes fully transparent.
   // If uOpaque is 1.0, alpha value of final color is 1.0;
-  // If uOpaque is 0.0 and uMask is 1.0, alpha value of final color is 0.0 when input alpha is lower than uAlphaThreshold or
-  // 1.0 when input alpha is larger than uAlphaThreshold.
   // https://www.khronos.org/registry/glTF/specs/2.0/glTF-2.0.html#_material_alphamode
+  if(uMask > 0.5 && baseColor.a < uAlphaThreshold)
+  {
+    discard;
+  }
   baseColor.a = mix(baseColor.a, 1.0, uOpaque);
-  baseColor.a = min(mix(baseColor.a, floor(baseColor.a - uAlphaThreshold + 1.0), uMask), 1.0);
 
   metallic = clamp(metallic, 0.0, 1.0);
   // Roughness is authored as perceptual roughness; as is convention,
diff --git a/dali-scene3d/internal/graphics/shaders/skybox-equirectangular-shader.frag b/dali-scene3d/internal/graphics/shaders/skybox-equirectangular-shader.frag
new file mode 100644 (file)
index 0000000..c57c608
--- /dev/null
@@ -0,0 +1,38 @@
+// Fragment shader for a skybox in equirectangular projection
+precision mediump float;
+
+uniform sampler2D uSkyBoxEquirectangularTexture;
+
+uniform vec4  uColor;
+uniform float uIntensity;
+
+varying vec3 vTexCoord;
+
+// Take the sample direction as interpolated from the cube's local position,
+// and use this direction vector and the spherical to cartesian coordinate
+// conversion to sample the equirectangular map as if it's a cube map.
+
+const float M_1_PI = 0.3183; // The reciprocal of pi in radians
+const float M_1_2PI = 0.1591; // The reciprocal of 2*pi in radians
+
+const vec2 inverseAtan = vec2(M_1_2PI, M_1_PI);
+
+vec2 SampleEquirectangularMapAsCubeMap(vec3 v)
+{
+    vec2 uv = vec2(atan(v.z, v.x), asin(v.y));
+    uv *= inverseAtan;
+    uv += 0.5;
+    return uv;
+}
+
+void main()
+{
+  // Project the equirectangular map to a cube's faces
+  vec2 uv = SampleEquirectangularMapAsCubeMap(normalize(vTexCoord));
+
+  // Flip the texture UVs vertically
+  vec2 uvFlippped = vec2(uv.x, 1.0 - uv.y);
+
+  vec4 texColor = texture2D( uSkyBoxEquirectangularTexture, uvFlippped ) * uIntensity;
+  gl_FragColor = texColor * uColor;
+}
index bc41050..732c1d6 100644 (file)
@@ -127,9 +127,9 @@ bool SceneView::IsUsingFramebuffer() const
   return GetImpl(*this).IsUsingFramebuffer();
 }
 
-void SceneView::SetSkybox(const std::string& skyboxUrl)
+void SceneView::SetSkybox(const std::string& skyboxUrl, SkyboxType skyboxType)
 {
-  GetImpl(*this).SetSkybox(skyboxUrl);
+  GetImpl(*this).SetSkybox(skyboxUrl, skyboxType);
 }
 
 void SceneView::SetSkyboxIntensity(float intensity)
index 9c72d9c..7c4f67b 100644 (file)
@@ -104,6 +104,16 @@ class DALI_SCENE3D_API SceneView : public Dali::Toolkit::Control
 {
 public:
   /**
+   * @brief The skybox types
+   * @SINCE_2_2.6
+   */
+  enum class SkyboxType
+  {
+    CUBEMAP,        ///< Skybox in cubemap
+    EQUIRECTANGULAR ///< Skybox in equirectangular projection
+  };
+
+  /**
    * @brief Create an initialized SceneView.
    *
    * @SINCE_2_1.38
@@ -320,9 +330,10 @@ public:
    * Skybox texture is asynchronously loaded. When loading is finished, ResourceReady is emitted.
    *
    * @SINCE_2_2.0
-   * @param[in] skyboxUrl Cube map image url for skybox.
+   * @param[in] skyboxUrl image url for skybox.
+   * @param[in] skyboxType The skybox type (by default it is cubemap).
    */
-  void SetSkybox(const std::string& skyboxUrl);
+  void SetSkybox(const std::string& skyboxUrl, SkyboxType skyboxType = SkyboxType::CUBEMAP);
 
   /**
    * @brief Sets Skybox intensity.
index 5f15815..83ae2df 100644 (file)
@@ -24,7 +24,7 @@ namespace Loader
 {
 void AnimatedProperty::Animate(Animation& anim, GetActor getActor)
 {
-  if(Actor actor = getActor(mNodeName))
+  if(Actor actor = getActor(*this))
   {
     Property prop = GetProperty(actor);
     if(mKeyFrames)
index 6433d5c..87fe87a 100644 (file)
@@ -19,6 +19,8 @@
 
 // INTERNAL INCLUDES
 #include "dali-scene3d/public-api/api.h"
+#include "dali-scene3d/public-api/loader/index.h"
+
 
 // EXTERNAL INCLUDES
 #include <functional>
@@ -44,10 +46,10 @@ struct DALI_SCENE3D_API AnimatedProperty
 {
 public: // METHODS
   /**
-   * @brief Function to obtain an Actor based on its name. Its processing will
+   * @brief Function to obtain an Actor based on its property. Its processing will
    *  ignore empty handles returned by it.
    */
-  using GetActor = std::function<Actor(const std::string&)>;
+  using GetActor = std::function<Actor(const AnimatedProperty&)>;
 
   /**
    * @return The Property object (of the given @a actor) whose value is being animated.
@@ -82,6 +84,7 @@ public: // DATA
     bool            mIsRelative;
   };
 
+  Index       mNodeIndex = INVALID_INDEX;
   std::string mNodeName;
   std::string mPropertyName;
 
index 75d7ad0..257ba32 100644 (file)
@@ -425,7 +425,10 @@ SamplerFlags::Type ConvertSampler(const gt::Ref<gt::Sampler>& s)
 {
   if(s)
   {
-    return (s->mMinFilter < gt::Filter::NEAREST_MIPMAP_NEAREST) ? (s->mMinFilter - gt::Filter::NEAREST) : ((s->mMinFilter - gt::Filter::NEAREST_MIPMAP_NEAREST) + 2) | ((s->mMagFilter - gt::Filter::NEAREST) << SamplerFlags::FILTER_MAG_SHIFT) | (ConvertWrapMode(s->mWrapS) << SamplerFlags::WRAP_S_SHIFT) | (ConvertWrapMode(s->mWrapT) << SamplerFlags::WRAP_T_SHIFT);
+    return ((s->mMinFilter < gt::Filter::NEAREST_MIPMAP_NEAREST) ? (s->mMinFilter - gt::Filter::NEAREST) : ((s->mMinFilter - gt::Filter::NEAREST_MIPMAP_NEAREST) + 2)) | 
+           ((s->mMagFilter - gt::Filter::NEAREST) << SamplerFlags::FILTER_MAG_SHIFT) | 
+           (ConvertWrapMode(s->mWrapS) << SamplerFlags::WRAP_S_SHIFT) | 
+           (ConvertWrapMode(s->mWrapT) << SamplerFlags::WRAP_T_SHIFT);
   }
   else
   {
@@ -459,13 +462,14 @@ void ConvertMaterial(const gt::Material& material, const std::unordered_map<std:
   MaterialDefinition matDef;
 
   auto& pbr = material.mPbrMetallicRoughness;
-  if(pbr.mBaseColorFactor.a < 1.f)
+  if(material.mAlphaMode == gt::AlphaMode::BLEND)
   {
+    matDef.mIsOpaque = false;
     matDef.mFlags |= MaterialDefinition::TRANSPARENCY;
   }
-
-  if(material.mAlphaMode == gt::AlphaMode::MASK)
+  else if(material.mAlphaMode == gt::AlphaMode::MASK)
   {
+    matDef.mIsMask = true;
     matDef.SetAlphaCutoff(std::min(1.f, std::max(0.f, material.mAlphaCutoff)));
   }
 
@@ -888,16 +892,24 @@ void ConvertSceneNodes(const gt::Scene& scene, ConversionContext& context, bool
 
 void ConvertNodes(const gt::Document& doc, ConversionContext& context, bool isMRendererModel)
 {
-  ConvertSceneNodes(*doc.mScene, context, isMRendererModel);
-
-  for(uint32_t i = 0, i1 = doc.mScene.GetIndex(); i < i1; ++i)
+  if(!doc.mScenes.empty())
   {
-    ConvertSceneNodes(doc.mScenes[i], context, isMRendererModel);
-  }
+    uint32_t rootSceneIndex = 0u;
+    if(doc.mScene)
+    {
+      rootSceneIndex = doc.mScene.GetIndex();
+    }
+    ConvertSceneNodes(doc.mScenes[rootSceneIndex], context, isMRendererModel);
 
-  for(uint32_t i = doc.mScene.GetIndex() + 1; i < doc.mScenes.size(); ++i)
-  {
-    ConvertSceneNodes(doc.mScenes[i], context, isMRendererModel);
+    for(uint32_t i = 0, i1 = rootSceneIndex; i < i1; ++i)
+    {
+      ConvertSceneNodes(doc.mScenes[i], context, isMRendererModel);
+    }
+
+    for(uint32_t i = rootSceneIndex + 1; i < doc.mScenes.size(); ++i)
+    {
+      ConvertSceneNodes(doc.mScenes[i], context, isMRendererModel);
+    }
   }
 }
 
@@ -951,7 +963,7 @@ float LoadKeyFrames(const std::string& path, const gt::Animation::Channel& chann
   return duration;
 }
 
-float LoadBlendShapeKeyFrames(const std::string& path, const gt::Animation::Channel& channel, const std::string& nodeName, uint32_t& propertyIndex, std::vector<Dali::Scene3D::Loader::AnimatedProperty>& properties)
+float LoadBlendShapeKeyFrames(const std::string& path, const gt::Animation::Channel& channel, Index nodeIndex, uint32_t& propertyIndex, std::vector<Dali::Scene3D::Loader::AnimatedProperty>& properties)
 {
   const gltf2::Accessor& input  = *channel.mSampler->mInput;
   const gltf2::Accessor& output = *channel.mSampler->mOutput;
@@ -969,7 +981,7 @@ float LoadBlendShapeKeyFrames(const std::string& path, const gt::Animation::Chan
   {
     AnimatedProperty& animatedProperty = properties[propertyIndex++];
 
-    animatedProperty.mNodeName = nodeName;
+    animatedProperty.mNodeIndex = nodeIndex;
     snprintf(pWeightName, remainingSize, "%d]", weightIndex);
     animatedProperty.mPropertyName = std::string(weightNameBuffer);
 
@@ -1001,27 +1013,23 @@ void ConvertAnimations(const gt::Document& doc, ConversionContext& context)
     }
 
     uint32_t numberOfProperties = 0u;
-
     for(const auto& channel : animation.mChannels)
     {
-      numberOfProperties += channel.mSampler->mOutput->mCount;
-    }
-    animationDef.mProperties.resize(numberOfProperties);
-
-    Index propertyIndex = 0u;
-    for(const auto& channel : animation.mChannels)
-    {
-      std::string nodeName;
-      if(!channel.mTarget.mNode->mName.empty())
+      if(channel.mTarget.mPath == gt::Animation::Channel::Target::WEIGHTS)
       {
-        nodeName = channel.mTarget.mNode->mName;
+        numberOfProperties += channel.mSampler->mOutput->mCount / channel.mSampler->mInput->mCount;
       }
       else
       {
-        Index index = context.mNodeIndices.GetRuntimeId(channel.mTarget.mNode.GetIndex());
-        nodeName    = context.mOutput.mScene.GetNode(index)->mName;
+        numberOfProperties++;
       }
+    }
+    animationDef.mProperties.resize(numberOfProperties);
 
+    Index propertyIndex = 0u;
+    for(const auto& channel : animation.mChannels)
+    {
+      Index nodeIndex    = context.mNodeIndices.GetRuntimeId(channel.mTarget.mNode.GetIndex());
       float duration = 0.f;
 
       switch(channel.mTarget.mPath)
@@ -1030,7 +1038,7 @@ void ConvertAnimations(const gt::Document& doc, ConversionContext& context)
         {
           AnimatedProperty& animatedProperty = animationDef.mProperties[propertyIndex];
 
-          animatedProperty.mNodeName     = nodeName;
+          animatedProperty.mNodeIndex    = nodeIndex;
           animatedProperty.mPropertyName = POSITION_PROPERTY;
 
           animatedProperty.mKeyFrames = KeyFrames::New();
@@ -1043,7 +1051,7 @@ void ConvertAnimations(const gt::Document& doc, ConversionContext& context)
         {
           AnimatedProperty& animatedProperty = animationDef.mProperties[propertyIndex];
 
-          animatedProperty.mNodeName     = nodeName;
+          animatedProperty.mNodeIndex    = nodeIndex;
           animatedProperty.mPropertyName = ORIENTATION_PROPERTY;
 
           animatedProperty.mKeyFrames = KeyFrames::New();
@@ -1056,7 +1064,7 @@ void ConvertAnimations(const gt::Document& doc, ConversionContext& context)
         {
           AnimatedProperty& animatedProperty = animationDef.mProperties[propertyIndex];
 
-          animatedProperty.mNodeName     = nodeName;
+          animatedProperty.mNodeIndex    = nodeIndex;
           animatedProperty.mPropertyName = SCALE_PROPERTY;
 
           animatedProperty.mKeyFrames = KeyFrames::New();
@@ -1067,7 +1075,7 @@ void ConvertAnimations(const gt::Document& doc, ConversionContext& context)
         }
         case gt::Animation::Channel::Target::WEIGHTS:
         {
-          duration = LoadBlendShapeKeyFrames(context.mPath, channel, nodeName, propertyIndex, animationDef.mProperties);
+          duration = LoadBlendShapeKeyFrames(context.mPath, channel, nodeIndex, propertyIndex, animationDef.mProperties);
 
           break;
         }
index 08b59c6..e6df18e 100644 (file)
@@ -244,6 +244,9 @@ public: // DATA
   bool mNeedNormalTexture            = true;
   bool mDoubleSided                  = false;
 
+  bool mIsOpaque = true;
+  bool mIsMask   = false;
+
   std::vector<TextureStage> mTextureStages;
 };
 
index f147ca7..4b8f21d 100644 (file)
@@ -82,18 +82,22 @@ bool ReadBlob(const MeshDefinition::Blob& descriptor, std::istream& source, uint
   }
   else
   {
-    DALI_ASSERT_DEBUG(descriptor.mStride > descriptor.mElementSizeHint);
-    const uint32_t diff     = descriptor.mStride - descriptor.mElementSizeHint;
-    uint32_t       readSize = 0;
-    while(readSize < descriptor.mLength &&
-          source.read(reinterpret_cast<char*>(target), descriptor.mElementSizeHint) &&
-          source.seekg(diff, std::istream::cur))
-    {
-      readSize += descriptor.mStride;
-      target += descriptor.mElementSizeHint;
+    if(descriptor.mStride > descriptor.mElementSizeHint)
+    {
+      const uint32_t diff      = descriptor.mStride - descriptor.mElementSizeHint;
+      uint32_t       readSize  = 0;
+      uint32_t       totalSize = (descriptor.mLength / descriptor.mElementSizeHint) * descriptor.mStride;
+      while(readSize < totalSize &&
+            source.read(reinterpret_cast<char*>(target), descriptor.mElementSizeHint) &&
+            source.seekg(diff, std::istream::cur))
+      {
+        readSize += descriptor.mStride;
+        target += descriptor.mElementSizeHint;
+      }
+      return readSize == totalSize;
     }
-    return readSize == descriptor.mLength;
   }
+  return false;
 }
 
 template<typename T>
@@ -518,7 +522,7 @@ MeshDefinition::Blob::Blob(uint32_t offset, uint32_t length, uint16_t stride, ui
 
 uint32_t MeshDefinition::Blob::GetBufferSize() const
 {
-  return IsConsecutive() ? mLength : (mLength * mElementSizeHint / mStride);
+  return mLength;
 }
 
 void MeshDefinition::Blob::ComputeMinMax(uint32_t numComponents, uint32_t count, float* values)
index bbed301..df4e0c4 100644 (file)
@@ -63,9 +63,11 @@ void NodeDefinition::Renderable::OnCreate(const NodeDefinition& node, CreatePara
 
 const std::string NodeDefinition::ORIGINAL_MATRIX_PROPERTY_NAME = "originalMatrix";
 
-Actor NodeDefinition::CreateActor(CreateParams& params) const
+Actor NodeDefinition::CreateActor(CreateParams& params)
 {
   Actor actor = Actor::New();
+  mNodeId     = actor.GetProperty<int32_t>(Dali::Actor::Property::ID);
+
   SetActorCentered(actor);
 
   actor.SetProperty(Actor::Property::NAME, mName);
@@ -244,20 +246,10 @@ void ModelRenderable::OnCreate(const NodeDefinition& node, NodeDefinition::Creat
   renderer.RegisterProperty(IBL_INTENSITY_STRING.data(), resources.mEnvironmentMaps[envIdx].first.mIblIntensity);
   renderer.RegisterProperty(IBL_Y_DIRECTION.data(), resources.mEnvironmentMaps[envIdx].first.mYDirection);
 
-  float opaque      = 0.0f;
-  float mask        = 0.0f;
+  float opaque      = matDef.mIsOpaque ? 1.0f : 0.0f;
+  float mask        = matDef.mIsMask ? 1.0f : 0.0f;
   float alphaCutoff = matDef.GetAlphaCutoff();
-  if(!MaskMatch(matDef.mFlags, MaterialDefinition::TRANSPARENCY))
-  {
-    opaque = 1.0f;
-  }
-  else
-  {
-    if(alphaCutoff > 0.f)
-    {
-      mask = 1.0f;
-    }
-  }
+
   renderer.RegisterProperty("uOpaque", opaque);
   renderer.RegisterProperty("uMask", mask);
   renderer.RegisterProperty("uAlphaThreshold", alphaCutoff);
index fde74e2..d713ed5 100644 (file)
@@ -218,7 +218,7 @@ public: // METHODS
    * @brief Creates a DALi Actor from this definition only.
    * @note Not recursive.
    */
-  Actor CreateActor(CreateParams& params) const;
+  Actor CreateActor(CreateParams& params);
 
   /**
    * @brief Gets local space matrix of this node
@@ -253,6 +253,7 @@ public: // DATA
   static const std::string ORIGINAL_MATRIX_PROPERTY_NAME;
 
   std::string mName;
+  uint32_t    mNodeId = INVALID_INDEX;
 
   Vector3    mPosition    = Vector3::ZERO;
   Quaternion mOrientation = Quaternion::IDENTITY;
index a117e1e..b6a2743 100644 (file)
@@ -164,7 +164,7 @@ void AddJointDebugVisual(Actor aJoint)
 }
 #endif //DEBUG_JOINTS
 
-class ActorCreatorVisitor : public NodeDefinition::IConstVisitor
+class ActorCreatorVisitor : public NodeDefinition::IVisitor
 {
 public:
   ActorCreatorVisitor(NodeDefinition::CreateParams& params)
@@ -172,7 +172,7 @@ public:
   {
   }
 
-  void Start(const NodeDefinition& n)
+  void Start(NodeDefinition& n)
   {
     mCreationContext.mXforms.modelStack.Push(n.GetLocalSpace());
 
@@ -188,7 +188,7 @@ public:
     mActorStack.push_back(a);
   }
 
-  void Finish(const NodeDefinition& n)
+  void Finish(NodeDefinition& n)
   {
     mActorStack.pop_back();
     mCreationContext.mXforms.modelStack.Pop();
@@ -469,7 +469,7 @@ void SceneDefinition::CountResourceRefs(Index iNode, const Customization::Choice
   Visit(iNode, choices, refCounterVisitor);
 }
 
-Actor SceneDefinition::CreateNodes(Index iNode, const Customization::Choices& choices, NodeDefinition::CreateParams& params) const
+Actor SceneDefinition::CreateNodes(Index iNode, const Customization::Choices& choices, NodeDefinition::CreateParams& params)
 {
   ActorCreatorVisitor actorCreatorVisitor(params);
 
@@ -526,11 +526,6 @@ void SceneDefinition::GetCustomizationOptions(const Customization::Choices& choi
 
 NodeDefinition* SceneDefinition::AddNode(std::unique_ptr<NodeDefinition>&& nodeDef)
 {
-  if(!nodeDef->mName.empty() && FindNode(nodeDef->mName))
-  {
-    return nullptr;
-  }
-
   // add next index (to which we're about to push) as a child to the designated parent, if any.
   if(nodeDef->mParentIdx != INVALID_INDEX)
   {
index 0f40f5b..ecb5cff 100644 (file)
@@ -113,7 +113,7 @@ public: // METHODS
    *  from node definitions.
    * @return Handle to the root actor.
    */
-  Actor CreateNodes(Index iNode, const Customization::Choices& choices, NodeDefinition::CreateParams& params) const;
+  Actor CreateNodes(Index iNode, const Customization::Choices& choices, NodeDefinition::CreateParams& params);
 
   /*
    * @brief Creates / update a registry of mappings from customization tags to
index a341d20..8a5b639 100644 (file)
@@ -93,24 +93,24 @@ uint64_t HashNode(const MaterialDefinition& materialDef, const MeshDefinition& m
     hash.Add("SSS");
   }
 
-  if(MaskMatch(materialDef.mFlags, MaterialDefinition::SPECULAR))
+  if(MaskMatch(materialDef.mFlags, MaterialDefinition::OCCLUSION))
   {
-    hash.Add("SPECTEX");
+    hash.Add("OCCL" /*USION*/);
   }
 
-  if(MaskMatch(materialDef.mFlags, MaterialDefinition::SPECULAR_COLOR))
+  if(MaskMatch(materialDef.mFlags, MaterialDefinition::EMISSIVE))
   {
-    hash.Add("SPECCOLTEX");
+    hash.Add("EMIS" /*SIVE*/);
   }
 
-  if(MaskMatch(materialDef.mFlags, MaterialDefinition::OCCLUSION))
+  if(MaskMatch(materialDef.mFlags, MaterialDefinition::SPECULAR))
   {
-    hash.Add("OCCL" /*USION*/);
+    hash.Add("SPECTEX");
   }
 
-  if(MaskMatch(materialDef.mFlags, MaterialDefinition::EMISSIVE))
+  if(MaskMatch(materialDef.mFlags, MaterialDefinition::SPECULAR_COLOR))
   {
-    hash.Add("EMIS" /*SIVE*/);
+    hash.Add("SPECCOLTEX");
   }
 
   if(MaskMatch(materialDef.mFlags, MaterialDefinition::GLTF_CHANNELS))
@@ -256,24 +256,24 @@ Index ShaderDefinitionFactory::ProduceShader(NodeDefinition::Renderable& rendera
       shaderDef.mDefines.push_back("SSS");
     }
 
-    if(MaskMatch(materialDef.mFlags, MaterialDefinition::SPECULAR))
+    if(MaskMatch(materialDef.mFlags, MaterialDefinition::OCCLUSION))
     {
-      shaderDef.mDefines.push_back("MATERIAL_SPECULAR_TEXTURE");
+      shaderDef.mDefines.push_back("OCCLUSION");
     }
 
-    if(MaskMatch(materialDef.mFlags, MaterialDefinition::SPECULAR_COLOR))
+    if(MaskMatch(materialDef.mFlags, MaterialDefinition::EMISSIVE))
     {
-      shaderDef.mDefines.push_back("MATERIAL_SPECULAR_COLOR_TEXTURE");
+      shaderDef.mDefines.push_back("EMISSIVE");
     }
 
-    if(MaskMatch(materialDef.mFlags, MaterialDefinition::OCCLUSION))
+    if(MaskMatch(materialDef.mFlags, MaterialDefinition::SPECULAR))
     {
-      shaderDef.mDefines.push_back("OCCLUSION");
+      shaderDef.mDefines.push_back("MATERIAL_SPECULAR_TEXTURE");
     }
 
-    if(MaskMatch(materialDef.mFlags, MaterialDefinition::EMISSIVE))
+    if(MaskMatch(materialDef.mFlags, MaterialDefinition::SPECULAR_COLOR))
     {
-      shaderDef.mDefines.push_back("EMISSIVE");
+      shaderDef.mDefines.push_back("MATERIAL_SPECULAR_COLOR_TEXTURE");
     }
 
     if(MaskMatch(materialDef.mFlags, MaterialDefinition::GLTF_CHANNELS))
index b2ac025..54cb62e 100755 (executable)
@@ -69,6 +69,7 @@ SET( devel_api_src_files
   ${devel_api_src_dir}/text/spans/base-span.cpp
   ${devel_api_src_dir}/text/spans/foreground-color-span.cpp
   ${devel_api_src_dir}/text/spans/font-span.cpp
+  ${devel_api_src_dir}/text/spans/underline-span.cpp
   ${devel_api_src_dir}/transition-effects/cube-transition-cross-effect.cpp
   ${devel_api_src_dir}/transition-effects/cube-transition-effect.cpp
   ${devel_api_src_dir}/transition-effects/cube-transition-fold-effect.cpp
@@ -251,6 +252,7 @@ SET( devel_api_text_header_files
   ${devel_api_src_dir}/text/spans/base-span.h
   ${devel_api_src_dir}/text/spans/foreground-color-span.h
   ${devel_api_src_dir}/text/spans/font-span.h
+  ${devel_api_src_dir}/text/spans/underline-span.h
 )
 
 SET( devel_api_tool_bar_header_files
diff --git a/dali-toolkit/devel-api/text/spans/underline-span.cpp b/dali-toolkit/devel-api/text/spans/underline-span.cpp
new file mode 100644 (file)
index 0000000..4760ed1
--- /dev/null
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali-toolkit/devel-api/text/spans/underline-span.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/spannable/spans/underline-span-impl.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Text
+{
+UnderlineSpan UnderlineSpan::New()
+{
+  return Internal::UnderlineSpan::New();
+}
+
+UnderlineSpan UnderlineSpan::NewSolid(Vector4 color, float height)
+{
+  return Internal::UnderlineSpan::NewSolid(color, height);
+}
+
+UnderlineSpan UnderlineSpan::NewDashed(Vector4 color, float height, float dashGap, float dashWidth)
+{
+  return Internal::UnderlineSpan::NewDashed(color, height, dashGap, dashWidth);
+}
+
+UnderlineSpan UnderlineSpan::NewDouble(Vector4 color, float height)
+{
+  return Internal::UnderlineSpan::NewDouble(color, height);
+}
+
+UnderlineSpan::UnderlineSpan(Internal::UnderlineSpan* internal)
+: BaseSpan(internal)
+{
+}
+
+UnderlineSpan::UnderlineSpan() = default;
+
+UnderlineSpan::UnderlineSpan(const UnderlineSpan& rhs) = default;
+
+UnderlineSpan::UnderlineSpan(UnderlineSpan&& rhs) = default;
+
+UnderlineSpan& UnderlineSpan::operator=(const UnderlineSpan& rhs) = default;
+
+UnderlineSpan& UnderlineSpan::operator=(UnderlineSpan&& rhs) = default;
+
+UnderlineSpan::~UnderlineSpan() = default;
+
+//Methods
+
+const Text::Underline::Type UnderlineSpan::GetType() const
+{
+  return GetImplementation(*this).GetType();
+}
+
+bool UnderlineSpan::IsTypeDefined() const
+{
+  return GetImplementation(*this).IsTypeDefined();
+}
+
+const Vector4 UnderlineSpan::GetColor() const
+{
+  return GetImplementation(*this).GetColor();
+}
+
+bool UnderlineSpan::IsColorDefined() const
+{
+  return GetImplementation(*this).IsColorDefined();
+}
+
+const float UnderlineSpan::GetHeight() const
+{
+  return GetImplementation(*this).GetHeight();
+}
+
+bool UnderlineSpan::IsHeightDefined() const
+{
+  return GetImplementation(*this).IsHeightDefined();
+}
+
+const float UnderlineSpan::GetDashGap() const
+{
+  return GetImplementation(*this).GetDashGap();
+}
+
+bool UnderlineSpan::IsDashGapDefined() const
+{
+  return GetImplementation(*this).IsDashGapDefined();
+}
+
+const float UnderlineSpan::GetDashWidth() const
+{
+  return GetImplementation(*this).GetDashWidth();
+}
+
+bool UnderlineSpan::IsDashWidthDefined() const
+{
+  return GetImplementation(*this).IsDashWidthDefined();
+}
+
+UnderlineSpan UnderlineSpan::DownCast(BaseHandle handle)
+{
+  return UnderlineSpan(dynamic_cast<Dali::Toolkit::Text::Internal::UnderlineSpan*>(handle.GetObjectPtr()));
+}
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
diff --git a/dali-toolkit/devel-api/text/spans/underline-span.h b/dali-toolkit/devel-api/text/spans/underline-span.h
new file mode 100644 (file)
index 0000000..d233c73
--- /dev/null
@@ -0,0 +1,218 @@
+#ifndef DALI_TOOLKIT_TEXT_UNDERLINE_SPAN_H
+#define DALI_TOOLKIT_TEXT_UNDERLINE_SPAN_H
+
+/*
+ * Copyright (c) 2022 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-toolkit/devel-api/text/spans/base-span.h>
+#include <dali-toolkit/public-api/text/text-enumerations.h>
+#include <dali/public-api/common/constants.h>
+#include <dali/public-api/math/vector4.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Text
+{
+namespace Internal DALI_INTERNAL
+{
+class UnderlineSpan;
+}
+
+/**
+ * @brief UnderlineSpan is a handle to an object that specifies the underline properties for range of characters.
+ */
+class DALI_TOOLKIT_API UnderlineSpan : public BaseSpan
+{
+public:
+  /**
+   * @brief Create an initialized UnderlineSpan.
+   *
+   * @return A handle to a newly allocated Dali resource
+   */
+  static UnderlineSpan New();
+
+  /**
+   * @brief Create an initialized UnderlineSpan.
+   *
+   * @param[in] color The color of line.
+   * @param[in] height The height of line.
+   *
+   * @return A handle to a newly allocated Dali resource
+   */
+  static UnderlineSpan NewSolid(Vector4 color, float height);
+
+  /**
+   * @brief Create an initialized UnderlineSpan.
+   *
+   * @param[in] color The color of line.
+   * @param[in] height The height of line.
+   * @param[in] dashGap The dash-gap of line.
+   * @param[in] dashWidth The dash-width of line.
+   *
+   * @return A handle to a newly allocated Dali resource
+   */
+  static UnderlineSpan NewDashed(Vector4 color, float height, float dashGap, float dashWidth);
+
+  /**
+   * @brief Create an initialized UnderlineSpan.
+   *
+   * @param[in] color The color of line.
+   * @param[in] height The height of line.
+   *
+   * @return A handle to a newly allocated Dali resource
+   */
+  static UnderlineSpan NewDouble(Vector4 color, float height);
+
+  /**
+   * @brief Creates an uninitialized UnderlineSpan handle.
+   *
+   * Calling member functions with an uninitialized UnderlineSpan handle is not allowed.
+   */
+  UnderlineSpan();
+
+  /**
+   * @brief Copy constructor.
+   * @param[in] rhs A reference to the copied handle
+   */
+  UnderlineSpan(const UnderlineSpan& rhs);
+
+  /**
+   * @brief Move constructor.
+   * @param[in] rhs A reference to the handle to move
+   */
+  UnderlineSpan(UnderlineSpan&& rhs);
+
+  /**
+   * @brief Assignment operator.
+   * @param[in] rhs A reference to the copied handle
+   * @return A reference to this
+   */
+  UnderlineSpan& operator=(const UnderlineSpan& rhs);
+
+  /**
+   * @brief Move assignment operator.
+   * @param[in] rhs A reference to the moved handle
+   * @return A reference to this
+   */
+  UnderlineSpan& operator=(UnderlineSpan&& rhs);
+
+  /**
+   * @brief Non virtual destructor.
+   */
+  ~UnderlineSpan();
+
+  /**
+   * @brief Downcasts to a UnderlineSpan handle.
+   * If handle is not a UnderlineSpan, the returned handle is left uninitialized.
+   *
+   * @param[in] handle Handle to an object
+   * @return UnderlineSpan handle or an uninitialized handle
+   */
+  static UnderlineSpan DownCast(BaseHandle handle);
+
+public: //Methods
+  /**
+   * @brief Retrive the type of line.
+   *
+   * @return A type value.
+   */
+  const Text::Underline::Type GetType() const;
+
+  /**
+   * @brief Retrieve whether the type is defined.
+   *
+   * @return The return is true if type is defined, otherwise false.
+   */
+  bool IsTypeDefined() const;
+
+  /**
+   * @brief Retrive the color of line.
+   *
+   * @return A color value.
+   */
+  const Vector4 GetColor() const;
+
+  /**
+   * @brief Retrieve whether the color is defined.
+   *
+   * @return The return is true if color is defined, otherwise false.
+   */
+  bool IsColorDefined() const;
+
+  /**
+   * @brief Retrive the height of line.
+   *
+   * @return A height value.
+   */
+  const float GetHeight() const;
+
+  /**
+   * @brief Retrieve whether the height is defined.
+   *
+   * @return The return is true if height is defined, otherwise false.
+   */
+  bool IsHeightDefined() const;
+
+  /**
+   * @brief Retrive the dash-gap of line.
+   *
+   * @return A dash-gap value.
+   */
+  const float GetDashGap() const;
+
+  /**
+   * @brief Retrieve whether the dash-gap is defined.
+   *
+   * @return The return is true if dash-gap is defined, otherwise false.
+   */
+  bool IsDashGapDefined() const;
+
+  /**
+   * @brief Retrive the dash-width of line.
+   *
+   * @return A dash-width value.
+   */
+  const float GetDashWidth() const;
+
+  /**
+   * @brief Retrieve whether the dash-width is defined.
+   *
+   * @return The return is true if dash-width is defined, otherwise false.
+   */
+  bool IsDashWidthDefined() const;
+
+public: // Not intended for application developers
+  /// @cond internal
+  /**
+   * @brief This constructor is used internally to Create an initialized UnderlineSpan handle.
+   *
+   * @param[in] underlineSpan Pointer to internal UnderlineSpan
+   */
+  explicit DALI_INTERNAL UnderlineSpan(Internal::UnderlineSpan* underlineSpan);
+  /// @endcond
+};
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // DALI_TOOLKIT_TEXT_UNDERLINE_SPAN_H
index 632baaf..68aec5e 100755 (executable)
@@ -1288,6 +1288,18 @@ WebView::WebViewAccessible::WebViewAccessible(Dali::Actor self, Dali::WebEngine&
   }
 }
 
+Dali::Accessibility::Attributes WebView::WebViewAccessible::GetAttributes() const
+{
+  auto attributes = DevelControl::ControlAccessible::GetAttributes();
+
+  if(mRemoteChild.GetAddress())
+  {
+    attributes.insert_or_assign("child_bus", mRemoteChild.GetAddress().GetBus());
+  }
+
+  return attributes;
+}
+
 void WebView::WebViewAccessible::DoGetChildren(std::vector<Dali::Accessibility::Accessible*>& children)
 {
   if(mRemoteChild.GetAddress())
index 6f5e386..cfbb31e 100755 (executable)
@@ -689,6 +689,11 @@ protected:
 
   protected:
     /**
+     * @copydoc Dali::Accessibility::Accessible::GetAttributes()
+     */
+    Dali::Accessibility::Attributes GetAttributes() const override;
+
+    /**
      * @copydoc Dali::Accessibility::ActorAccessible::DoGetChildren()
      */
     void DoGetChildren(std::vector<Dali::Accessibility::Accessible*>& children) override;
index 96d2a53..0ffdbfc 100644 (file)
@@ -163,6 +163,7 @@ SET( toolkit_src_files
    ${toolkit_src_dir}/text/spannable/spans/base-span-impl.cpp
    ${toolkit_src_dir}/text/spannable/spans/foreground-color-span-impl.cpp
    ${toolkit_src_dir}/text/spannable/spans/font-span-impl.cpp
+   ${toolkit_src_dir}/text/spannable/spans/underline-span-impl.cpp
    ${toolkit_src_dir}/text/spannable/span-ranges-container-impl.cpp
    ${toolkit_src_dir}/text/hyphenator.cpp
    ${toolkit_src_dir}/text/text-enumerations-impl.cpp
index ff4697b..d29ac70 100644 (file)
@@ -387,7 +387,8 @@ bool ControllerImplModelUpdater::Update(Controller::Impl& impl, OperationsMask o
           impl.mModel->mVisualModel->mUnderlineRuns.PushBack(underlineRun);
 
           //Mark-up processor case
-          if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled())
+          if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled() ||
+             impl.mModel->mLogicalModel->mUnderlineRunsUpdated)
           {
             impl.CopyUnderlinedFromLogicalToVisualModels(false);
           }
@@ -428,7 +429,8 @@ bool ControllerImplModelUpdater::Update(Controller::Impl& impl, OperationsMask o
           impl.mModel->mLogicalModel->mColorRuns.PushBack(colorRun);
 
           //Mark-up processor case
-          if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled())
+          if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled() ||
+             impl.mModel->mLogicalModel->mUnderlineRunsUpdated)
           {
             impl.CopyUnderlinedFromLogicalToVisualModels(false);
           }
@@ -443,7 +445,8 @@ bool ControllerImplModelUpdater::Update(Controller::Impl& impl, OperationsMask o
           impl.mModel->mLogicalModel->mBackgroundColorRuns.PushBack(backgroundColorRun);
 
           //Mark-up processor case
-          if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled())
+          if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled() ||
+             impl.mModel->mLogicalModel->mUnderlineRunsUpdated)
           {
             impl.CopyUnderlinedFromLogicalToVisualModels(false);
           }
@@ -464,7 +467,8 @@ bool ControllerImplModelUpdater::Update(Controller::Impl& impl, OperationsMask o
           impl.mModel->mVisualModel->mUnderlineRuns.PushBack(underlineRun);
 
           //Mark-up processor case
-          if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled())
+          if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled() ||
+             impl.mModel->mLogicalModel->mUnderlineRunsUpdated)
           {
             impl.CopyUnderlinedFromLogicalToVisualModels(false);
           }
@@ -485,7 +489,8 @@ bool ControllerImplModelUpdater::Update(Controller::Impl& impl, OperationsMask o
           impl.mModel->mVisualModel->mUnderlineRuns.PushBack(underlineRun);
 
           //Mark-up processor case
-          if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled())
+          if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled() ||
+             impl.mModel->mLogicalModel->mUnderlineRunsUpdated)
           {
             impl.CopyUnderlinedFromLogicalToVisualModels(false);
           }
@@ -506,7 +511,8 @@ bool ControllerImplModelUpdater::Update(Controller::Impl& impl, OperationsMask o
           impl.mModel->mVisualModel->mUnderlineRuns.PushBack(underlineRun);
 
           //Mark-up processor case
-          if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled())
+          if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled() ||
+             impl.mModel->mLogicalModel->mUnderlineRunsUpdated)
           {
             impl.CopyUnderlinedFromLogicalToVisualModels(false);
           }
@@ -527,7 +533,8 @@ bool ControllerImplModelUpdater::Update(Controller::Impl& impl, OperationsMask o
           impl.mModel->mVisualModel->mUnderlineRuns.PushBack(underlineRun);
 
           //Mark-up processor case
-          if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled())
+          if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled() ||
+             impl.mModel->mLogicalModel->mUnderlineRunsUpdated)
           {
             impl.CopyUnderlinedFromLogicalToVisualModels(false);
           }
@@ -575,7 +582,8 @@ bool ControllerImplModelUpdater::Update(Controller::Impl& impl, OperationsMask o
        (0u != impl.mModel->mVisualModel->mCharactersToGlyph.Count())))
   {
     //Mark-up processor case
-    if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled())
+    if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled() ||
+       impl.mModel->mLogicalModel->mUnderlineRunsUpdated)
     {
       impl.CopyUnderlinedFromLogicalToVisualModels(true);
       impl.CopyStrikethroughFromLogicalToVisualModels();
index 8b6d8cb..46d9263 100644 (file)
@@ -1721,6 +1721,9 @@ void Controller::Impl::CopyUnderlinedFromLogicalToVisualModels(bool shouldClearP
 
     mModel->mVisualModel->mUnderlineRuns.PushBack(underlineGlyphRun);
   }
+
+  // Reset flag. The updates have been applied from logical to visual.
+  mModel->mLogicalModel->mUnderlineRunsUpdated = false;
 }
 
 void Controller::Impl::CopyStrikethroughFromLogicalToVisualModels()
index a4e5db2..123d8ea 100644 (file)
@@ -659,7 +659,8 @@ LogicalModel::~LogicalModel()
 
 LogicalModel::LogicalModel()
 : mBidirectionalLineIndex(0u),
-  mSpannedTextPlaced(false)
+  mSpannedTextPlaced(false),
+  mUnderlineRunsUpdated(false)
 {
 }
 
index ba67488..546e308 100644 (file)
@@ -263,6 +263,8 @@ public:
 
   BidirectionalLineRunIndex mBidirectionalLineIndex; ///< The last fetched bidirectional line info.
   bool                      mSpannedTextPlaced : 1;  ///< Whether the spanned-text is placed.
+
+  bool mUnderlineRunsUpdated : 1; /// Whether the UnderlinedCharacterRuns is updated. (Added for SpannedText)
 };
 
 } // namespace Text
index 73ae2c5..343f6cb 100644 (file)
@@ -1052,7 +1052,7 @@ PixelData Typesetter::Render(const Vector2& size, Toolkit::DevelText::TextDirect
       }
 
       // Markup-Processor for overlay styles
-      if(mModel->IsMarkupProcessorEnabled())
+      if(mModel->IsMarkupProcessorEnabled() || mModel->IsSpannedTextPlaced())
       {
         if(mModel->IsMarkupUnderlineSet())
         {
index e743b36..725f945 100644 (file)
@@ -305,6 +305,11 @@ bool ViewModel::IsMarkupProcessorEnabled() const
   return mModel->IsMarkupProcessorEnabled();
 }
 
+bool ViewModel::IsSpannedTextPlaced() const
+{
+  return mModel->IsSpannedTextPlaced();
+}
+
 const GlyphInfo* ViewModel::GetHyphens() const
 {
   return mModel->GetHyphens();
index 71ad8bb..0e0c64e 100644 (file)
@@ -267,6 +267,11 @@ public:
   bool IsMarkupProcessorEnabled() const override;
 
   /**
+   * @copydoc ModelInterface::IsSpannedTextPlaced()
+   */
+  bool IsSpannedTextPlaced() const override;
+
+  /**
   * @copydoc ModelInterface::GetHyphens()
   */
   const GlyphInfo* GetHyphens() const override;
diff --git a/dali-toolkit/internal/text/spannable/spans/underline-span-impl.cpp b/dali-toolkit/internal/text/spannable/spans/underline-span-impl.cpp
new file mode 100644 (file)
index 0000000..32d219f
--- /dev/null
@@ -0,0 +1,195 @@
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali-toolkit/internal/text/spannable/spans/underline-span-impl.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/color-run.h>
+#include <dali-toolkit/internal/text/markup-tags-and-attributes.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Text
+{
+namespace Internal
+{
+struct UnderlineSpan::Impl
+{
+  UnderlineStyleProperties mUnderlineProperties; ///< The properties of underline style.
+};
+
+UnderlineSpan::UnderlineSpan()
+: BaseSpan()
+{
+  mImpl = std::make_unique<Impl>();
+}
+
+UnderlineSpan ::~UnderlineSpan()
+{
+}
+
+Dali::Toolkit::Text::UnderlineSpan UnderlineSpan::New()
+{
+  UnderlineSpanPtr object = new UnderlineSpan();
+
+  Dali::Toolkit::Text::UnderlineSpan handle = Dali::Toolkit::Text::UnderlineSpan(object.Get());
+
+  return handle;
+}
+
+Dali::Toolkit::Text::UnderlineSpan UnderlineSpan::NewSolid(Vector4 color, float height)
+{
+  UnderlineSpanPtr object = new UnderlineSpan();
+  object->SetType(Text::Underline::SOLID);
+  object->SetColor(color);
+  object->SetHeight(height);
+
+  Dali::Toolkit::Text::UnderlineSpan handle = Dali::Toolkit::Text::UnderlineSpan(object.Get());
+
+  return handle;
+}
+
+Dali::Toolkit::Text::UnderlineSpan UnderlineSpan::NewDashed(Vector4 color, float height, float dashGap, float dashWidth)
+{
+  UnderlineSpanPtr object = new UnderlineSpan();
+  object->SetType(Text::Underline::DASHED);
+  object->SetColor(color);
+  object->SetHeight(height);
+  object->SetDashGap(dashGap);
+  object->SetDashWidth(dashWidth);
+
+  Dali::Toolkit::Text::UnderlineSpan handle = Dali::Toolkit::Text::UnderlineSpan(object.Get());
+
+  return handle;
+}
+
+Dali::Toolkit::Text::UnderlineSpan UnderlineSpan::NewDouble(Vector4 color, float height)
+{
+  UnderlineSpanPtr object = new UnderlineSpan();
+  object->SetType(Text::Underline::DOUBLE);
+  object->SetColor(color);
+  object->SetHeight(height);
+
+  Dali::Toolkit::Text::UnderlineSpan handle = Dali::Toolkit::Text::UnderlineSpan(object.Get());
+
+  return handle;
+}
+
+//Methods
+
+const Text::Underline::Type UnderlineSpan::GetType() const
+{
+  return mImpl->mUnderlineProperties.type;
+}
+
+bool UnderlineSpan::IsTypeDefined() const
+{
+  return mImpl->mUnderlineProperties.typeDefined;
+}
+
+void UnderlineSpan::SetType(const Text::Underline::Type& type)
+{
+  mImpl->mUnderlineProperties.type        = type;
+  mImpl->mUnderlineProperties.typeDefined = true;
+}
+
+const Vector4 UnderlineSpan::GetColor() const
+{
+  return mImpl->mUnderlineProperties.color;
+}
+
+bool UnderlineSpan::IsColorDefined() const
+{
+  return mImpl->mUnderlineProperties.colorDefined;
+}
+
+void UnderlineSpan::SetColor(const Vector4& color)
+{
+  mImpl->mUnderlineProperties.color        = color;
+  mImpl->mUnderlineProperties.colorDefined = true;
+}
+
+const float UnderlineSpan::GetHeight() const
+{
+  return mImpl->mUnderlineProperties.height;
+}
+
+bool UnderlineSpan::IsHeightDefined() const
+{
+  return mImpl->mUnderlineProperties.heightDefined;
+}
+
+void UnderlineSpan::SetHeight(const float& height)
+{
+  mImpl->mUnderlineProperties.height        = height;
+  mImpl->mUnderlineProperties.heightDefined = true;
+}
+
+const float UnderlineSpan::GetDashGap() const
+{
+  return mImpl->mUnderlineProperties.dashGap;
+}
+
+bool UnderlineSpan::IsDashGapDefined() const
+{
+  return mImpl->mUnderlineProperties.dashGapDefined;
+}
+
+void UnderlineSpan::SetDashGap(const float& dashGap)
+{
+  mImpl->mUnderlineProperties.dashGap        = dashGap;
+  mImpl->mUnderlineProperties.dashGapDefined = true;
+}
+
+const float UnderlineSpan::GetDashWidth() const
+{
+  return mImpl->mUnderlineProperties.dashWidth;
+}
+
+bool UnderlineSpan::IsDashWidthDefined() const
+{
+  return mImpl->mUnderlineProperties.dashWidthDefined;
+}
+
+void UnderlineSpan::SetDashWidth(const float& dashWidth)
+{
+  mImpl->mUnderlineProperties.dashWidth        = dashWidth;
+  mImpl->mUnderlineProperties.dashWidthDefined = true;
+}
+
+void UnderlineSpan::CreateStyleCharacterRun(IntrusivePtr<LogicalModel>& logicalModel, const Dali::Toolkit::Text::Range& range) const
+{
+  UnderlinedCharacterRun underlinedCharacterRun;
+  underlinedCharacterRun.characterRun.characterIndex     = range.GetStartIndex();
+  underlinedCharacterRun.characterRun.numberOfCharacters = range.GetNumberOfIndices();
+
+  underlinedCharacterRun.properties = mImpl->mUnderlineProperties;
+  logicalModel->mUnderlinedCharacterRuns.PushBack(underlinedCharacterRun);
+
+  logicalModel->mUnderlineRunsUpdated = true;
+}
+
+} // namespace Internal
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
diff --git a/dali-toolkit/internal/text/spannable/spans/underline-span-impl.h b/dali-toolkit/internal/text/spannable/spans/underline-span-impl.h
new file mode 100644 (file)
index 0000000..9761979
--- /dev/null
@@ -0,0 +1,229 @@
+#ifndef DALI_TOOLKIT_INTERNAL_TEXT_UNDERLINE_SPAN_IMPL_H
+#define DALI_TOOLKIT_INTERNAL_TEXT_UNDERLINE_SPAN_IMPL_H
+
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <dali-toolkit/devel-api/text/spans/underline-span.h>
+#include <memory>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/logical-model-impl.h>
+#include <dali-toolkit/internal/text/spannable/spans/base-span-impl.h>
+#include <dali/public-api/math/vector4.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Text
+{
+namespace Internal
+{
+class UnderlineSpan;
+using UnderlineSpanPtr = IntrusivePtr<UnderlineSpan>;
+
+/**
+ * @copydoc Dali::Toolkit::Text::UnderlineSpan
+ */
+class UnderlineSpan : public BaseSpan
+{
+public:
+  /**
+   * @brief Creates a new UnderlineSpan object.
+   *
+   * @return A new UnderlineSpan object.
+   */
+  static Dali::Toolkit::Text::UnderlineSpan New();
+
+  /**
+   * @brief Creates a new UnderlineSpan object.
+   *
+   * @param[in] color The color of line.
+   * @param[in] height The height of line.
+   *
+   * @return A new UnderlineSpan object.
+   */
+  static Dali::Toolkit::Text::UnderlineSpan NewSolid(Vector4 color, float height);
+
+  /**
+   *
+   * @param[in] color The color of line.
+   * @param[in] height The height of line.
+   * @param[in] dashGap The dash-gap of line.
+   * @param[in] dashWidth The dash-width of line.
+   *
+   * @return A new UnderlineSpan object.
+   */
+  static Dali::Toolkit::Text::UnderlineSpan NewDashed(Vector4 color, float height, float dashGap, float dashWidth);
+
+  /**
+   * @brief Creates a new UnderlineSpan object.
+   *
+   * @param[in] color The color of line.
+   * @param[in] height The height of line.
+   *
+   * @return A new UnderlineSpan object.
+   */
+  static Dali::Toolkit::Text::UnderlineSpan NewDouble(Vector4 color, float height);
+
+  /**
+   * Default Constructor
+   */
+  UnderlineSpan();
+
+  UnderlineSpan(const UnderlineSpan&) = delete;            ///< Deleted copy constructor
+  UnderlineSpan(UnderlineSpan&&)      = delete;            ///< Deleted move constructor
+  UnderlineSpan& operator=(const UnderlineSpan&) = delete; ///< Deleted copy assignment operator
+  UnderlineSpan& operator=(UnderlineSpan&&) = delete;      ///< Deleted move assignment operator
+
+  /**
+   * @brief Destructor
+   *
+   * A reference counted object may only be deleted by calling Unreference()
+   */
+  ~UnderlineSpan() override;
+
+public: //Methods
+  /**
+   * @copydoc Dali::Toolkit::Text::UnderlineSpan::GetType()
+   */
+  const Text::Underline::Type GetType() const;
+
+  /**
+   * @copydoc Dali::Toolkit::Text::UnderlineSpan::IsTypeDefined()
+   */
+  bool IsTypeDefined() const;
+
+  /**
+   * @copydoc Dali::Toolkit::Text::UnderlineSpan::GetColor()
+   */
+  const Vector4 GetColor() const;
+
+  /**
+   * @copydoc Dali::Toolkit::Text::UnderlineSpan::IsColorDefined()
+   */
+  bool IsColorDefined() const;
+
+  /**
+   * @copydoc Dali::Toolkit::Text::UnderlineSpan::GetHeight()
+   */
+  const float GetHeight() const;
+
+  /**
+   * @copydoc Dali::Toolkit::Text::UnderlineSpan::IsHeightDefined()
+   */
+  bool IsHeightDefined() const;
+
+  /**
+   * @copydoc Dali::Toolkit::Text::UnderlineSpan::GetDashGap()
+   */
+  const float GetDashGap() const;
+
+  /**
+   * @copydoc Dali::Toolkit::Text::UnderlineSpan::IsDashGapDefined()
+   */
+  bool IsDashGapDefined() const;
+
+  /**
+   * @copydoc Dali::Toolkit::Text::UnderlineSpan::GetDashWidth()
+   */
+  const float GetDashWidth() const;
+
+  /**
+   * @copydoc Dali::Toolkit::Text::UnderlineSpan::IsDashWidthDefined()
+   */
+  bool IsDashWidthDefined() const;
+
+public: //Methods. Not intended for application developers
+  /**
+   * @brief Set the type of underline.
+   *
+   * @param[in] type The type of line.
+   */
+  void SetType(const Text::Underline::Type& type);
+
+  /**
+   * @brief Set the color of underline.
+   *
+   * @param[in] color The color of line.
+   */
+  void SetColor(const Vector4& color);
+
+  /**
+   * @brief Set the height of underline.
+   *
+   * @param[in] height The height of line.
+   */
+  void SetHeight(const float& height);
+
+  /**
+   * @brief Set the dash-gap of underline.
+   *
+   * @param[in] dashGap The dash-gap of line.
+   */
+  void SetDashGap(const float& dashGap);
+
+  /**
+    * @brief Set the dash-width of underline.
+    *
+    * @param[in] dashWidth The dash-width of line.
+    */
+  void SetDashWidth(const float& dashWidth);
+
+public: //Methods for internal only
+        /**
+   * @copydoc Dali::Toolkit::Text::BaseSpan::CreateStyleCharacterRun
+   */
+  void CreateStyleCharacterRun(IntrusivePtr<LogicalModel>& logicalModel, const Dali::Toolkit::Text::Range& range) const override;
+
+private:
+  struct Impl;
+  std::unique_ptr<Impl> mImpl{nullptr};
+
+}; // class UnderlineSpan
+
+} // namespace Internal
+
+// Helpers for public-api forwarding methods
+
+inline Internal::UnderlineSpan& GetImplementation(Dali::Toolkit::Text::UnderlineSpan& underlineSpan)
+{
+  DALI_ASSERT_ALWAYS(underlineSpan && "underlineSpan handle is empty");
+
+  BaseObject& object = underlineSpan.GetBaseObject();
+
+  return static_cast<Internal::UnderlineSpan&>(object);
+}
+
+inline const Internal::UnderlineSpan& GetImplementation(const Dali::Toolkit::Text::UnderlineSpan& underlineSpan)
+{
+  DALI_ASSERT_ALWAYS(underlineSpan && "underlineSpan handle is empty");
+
+  const BaseObject& object = underlineSpan.GetBaseObject();
+
+  return static_cast<const Internal::UnderlineSpan&>(object);
+}
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // DALI_TOOLKIT_INTERNAL_TEXT_UNDERLINE_SPAN_IMPL_H
\ No newline at end of file
index df37c17..4859597 100644 (file)
@@ -350,6 +350,15 @@ public:
   virtual bool IsMarkupProcessorEnabled() const = 0;
 
   /**
+   * @brief Retrieves whether the spanned-text is placed.
+   *
+   * By default is disabled.
+   *
+   * @return @e true if the spanned-text is placed, otherwise returns @e false.
+   */
+  virtual bool IsSpannedTextPlaced() const = 0;
+
+  /**
    * @brief Returns the hyphens glyph info.
    *
    * @return hyphens glyph info.
index d6a26ed..b1d4d02 100644 (file)
@@ -247,6 +247,11 @@ bool Model::IsMarkupProcessorEnabled() const
   return mVisualModel->IsMarkupProcessorEnabled();
 }
 
+bool Model::IsSpannedTextPlaced() const
+{
+  return mLogicalModel->mSpannedTextPlaced;
+}
+
 const GlyphInfo* Model::GetHyphens() const
 {
   return mVisualModel->mHyphen.glyph.Begin();
index 0e224e5..945d5fc 100644 (file)
@@ -265,6 +265,11 @@ public:
   bool IsMarkupProcessorEnabled() const override;
 
   /**
+   * @copydoc ModelInterface::IsSpannedTextPlaced()
+   */
+  bool IsSpannedTextPlaced() const override;
+
+  /**
   * @copydoc ModelInterface::GetHyphens()
   */
   const GlyphInfo* GetHyphens() const override;
index 3e8387f..e1ec6cf 100644 (file)
@@ -198,7 +198,7 @@ void AnimatedImageVisual::CreateImageCache()
 
   if(mAnimatedImageLoading)
   {
-    mImageCache = new RollingAnimatedImageCache(textureManager, mDesiredSize, mFittingMode, mSamplingMode, mAnimatedImageLoading, mMaskingData, *this, mCacheSize, mBatchSize, mWrapModeU, mWrapModeV, IsSynchronousLoadingRequired(), mFactoryCache.GetPreMultiplyOnLoad());
+    mImageCache = new RollingAnimatedImageCache(textureManager, mDesiredSize, mFittingMode, mSamplingMode, mAnimatedImageLoading, mMaskingData, *this, mCacheSize, mBatchSize, mWrapModeU, mWrapModeV, IsSynchronousLoadingRequired(), IsPreMultipliedAlphaEnabled());
   }
   else if(mImageUrls)
   {
@@ -209,11 +209,11 @@ void AnimatedImageVisual::CreateImageCache()
     uint16_t cacheSize = std::max(std::min(std::max(batchSize, mCacheSize), numUrls), MINIMUM_CACHESIZE);
     if(cacheSize < numUrls)
     {
-      mImageCache = new RollingImageCache(textureManager, mDesiredSize, mFittingMode, mSamplingMode, *mImageUrls, mMaskingData, *this, cacheSize, batchSize, mFrameDelay);
+      mImageCache = new RollingImageCache(textureManager, mDesiredSize, mFittingMode, mSamplingMode, *mImageUrls, mMaskingData, *this, cacheSize, batchSize, mFrameDelay, IsPreMultipliedAlphaEnabled());
     }
     else
     {
-      mImageCache = new FixedImageCache(textureManager, mDesiredSize, mFittingMode, mSamplingMode, *mImageUrls, mMaskingData, *this, batchSize, mFrameDelay);
+      mImageCache = new FixedImageCache(textureManager, mDesiredSize, mFittingMode, mSamplingMode, *mImageUrls, mMaskingData, *this, batchSize, mFrameDelay, IsPreMultipliedAlphaEnabled());
     }
   }
 
@@ -940,8 +940,10 @@ void AnimatedImageVisual::SetImageSize(TextureSet& textureSet)
   }
 }
 
-void AnimatedImageVisual::FrameReady(TextureSet textureSet, uint32_t interval)
+void AnimatedImageVisual::FrameReady(TextureSet textureSet, uint32_t interval, bool preMultiplied)
 {
+  EnablePreMultipliedAlpha(preMultiplied);
+
   // When image visual requested to load new frame to mImageCache and it is failed.
   if(!mImageCache || !textureSet)
   {
index 243b989..84113a1 100644 (file)
@@ -228,8 +228,9 @@ private:
    * @brief Called when the next frame is ready.
    * @param[in] textureSet the texture set to apply
    * @param[in] interval interval(ms) for the frame
+   * @param[in] preMultiplied whether the texture is premultied alpha or not.
    */
-  void FrameReady(TextureSet textureSet, uint32_t interval) override;
+  void FrameReady(TextureSet textureSet, uint32_t interval, bool preMultiplied) override;
 
   /**
    * @brief Display the next frame. It is called when the mFrameDelayTimer ticks.
index c40f802..854a7a0 100644 (file)
@@ -43,8 +43,9 @@ FixedImageCache::FixedImageCache(TextureManager&                     textureMana
                                  TextureManager::MaskingDataPointer& maskingData,
                                  ImageCache::FrameReadyObserver&     observer,
                                  uint32_t                            batchSize,
-                                 uint32_t                            interval)
-: ImageCache(textureManager, size, fittingMode, samplingMode, maskingData, observer, batchSize, interval),
+                                 uint32_t                            interval,
+                                 bool                                preMultiplyOnLoad)
+: ImageCache(textureManager, size, fittingMode, samplingMode, maskingData, observer, batchSize, interval, preMultiplyOnLoad),
   mImageUrls(urlList),
   mFront(FIRST_FRAME_INDEX)
 {
@@ -133,9 +134,11 @@ void FixedImageCache::LoadBatch()
     ImageAtlasManagerPtr  imageAtlasManager  = nullptr;
     Vector4               textureRect;
     Dali::ImageDimensions textureRectSize;
-    auto                  preMultiply = TextureManager::MultiplyOnLoad::LOAD_WITHOUT_MULTIPLY;
 
-    mTextureManager.LoadTexture(url, mDesiredSize, mFittingMode, mSamplingMode, mMaskingData, synchronousLoading, mImageUrls[frameIndex].mTextureId, textureRect, textureRectSize, atlasingStatus, loadingStatus, this, atlasObserver, imageAtlasManager, ENABLE_ORIENTATION_CORRECTION, TextureManager::ReloadPolicy::CACHED, preMultiply);
+    auto preMultiplyOnLoading = mPreMultiplyOnLoad ? TextureManager::MultiplyOnLoad::MULTIPLY_ON_LOAD
+                                                   : TextureManager::MultiplyOnLoad::LOAD_WITHOUT_MULTIPLY;
+
+    mTextureManager.LoadTexture(url, mDesiredSize, mFittingMode, mSamplingMode, mMaskingData, synchronousLoading, mImageUrls[frameIndex].mTextureId, textureRect, textureRectSize, atlasingStatus, loadingStatus, this, atlasObserver, imageAtlasManager, ENABLE_ORIENTATION_CORRECTION, TextureManager::ReloadPolicy::CACHED, preMultiplyOnLoading);
     mRequestingLoad = false;
   }
 }
@@ -152,11 +155,11 @@ TextureSet FixedImageCache::GetFrontTextureSet() const
   return textureSet;
 }
 
-void FixedImageCache::CheckFrontFrame(bool wasReady)
+void FixedImageCache::CheckFrontFrame(bool wasReady, bool preMultiplied)
 {
   if(wasReady == false && IsFrontReady())
   {
-    mObserver.FrameReady(GetFrontTextureSet(), mInterval);
+    mObserver.FrameReady(GetFrontTextureSet(), mInterval, preMultiplied);
   }
 }
 
@@ -199,12 +202,13 @@ void FixedImageCache::LoadComplete(bool loadSuccess, TextureInformation textureI
     {
       mReadyFlags.back() = true;
     }
-    CheckFrontFrame(frontFrameReady);
+    CheckFrontFrame(frontFrameReady, textureInformation.preMultiplied);
   }
   else
   {
     mLoadState = TextureManager::LoadState::LOAD_FAILED;
-    mObserver.FrameReady(TextureSet(), 0);
+    // preMultiplied should be false because broken image don't premultiply alpha on load
+    mObserver.FrameReady(TextureSet(), 0, false);
   }
 }
 
index 90e2c8f..7cbfa63 100644 (file)
@@ -32,15 +32,16 @@ class FixedImageCache : public ImageCache, public TextureUploadObserver
 public:
   /**
    * Constructor.
-   * @param[in] textureManager The texture manager
-   * @param[in] size           The width and height to fit the loaded image to.
-   * @param[in] fittingMode    The FittingMode of the resource to load
-   * @param[in] samplingMode   The SamplingMode of the resource to load
-   * @param[in] urlList        List of urls to cache
-   * @param[in] maskingData    Masking data to be applied.
-   * @param[in] observer       FrameReady observer
-   * @param[in] batchSize      The size of a batch to load
-   * @param[in] interval       Time interval between each frame
+   * @param[in] textureManager    The texture manager
+   * @param[in] size              The width and height to fit the loaded image to.
+   * @param[in] fittingMode       The FittingMode of the resource to load
+   * @param[in] samplingMode      The SamplingMode of the resource to load
+   * @param[in] urlList           List of urls to cache
+   * @param[in] maskingData       Masking data to be applied.
+   * @param[in] observer          FrameReady observer
+   * @param[in] batchSize         The size of a batch to load
+   * @param[in] interval          Time interval between each frame
+   * @param[in] preMultiplyOnLoad The flag if image's color should be multiplied by it's alpha
    *
    * This will start loading textures immediately, according to the
    * batch and cache sizes. The cache is as large as the number of urls.
@@ -53,7 +54,8 @@ public:
                   TextureManager::MaskingDataPointer& maskingData,
                   ImageCache::FrameReadyObserver&     observer,
                   uint32_t                            batchSize,
-                  uint32_t                            interval);
+                  uint32_t                            interval,
+                  bool                                preMultiplyOnLoad);
 
   ~FixedImageCache() override;
 
@@ -111,8 +113,9 @@ private:
    * @brief Check if the front frame has become ready - if so, inform observer
    *
    * @param[in] wasReady Readiness before call.
+   * @param[in] preMultiplied whether the texture is premultied alpha or not.
    */
-  void CheckFrontFrame(bool wasReady);
+  void CheckFrontFrame(bool wasReady, bool preMultiplied);
 
 protected:
   /**
index 3b5131f..41879c7 100644 (file)
@@ -29,7 +29,8 @@ ImageCache::ImageCache(TextureManager&                     textureManager,
                        TextureManager::MaskingDataPointer& maskingData,
                        ImageCache::FrameReadyObserver&     observer,
                        uint32_t                            batchSize,
-                       uint32_t                            interval)
+                       uint32_t                            interval,
+                       bool                                preMultiplyOnLoad)
 : mTextureManager(textureManager),
   mObserver(observer),
   mMaskingData(maskingData),
@@ -40,6 +41,7 @@ ImageCache::ImageCache(TextureManager&                     textureManager,
   mInterval(interval),
   mLoadState(TextureManager::LoadState::NOT_STARTED),
   mRequestingLoad(false),
+  mPreMultiplyOnLoad(preMultiplyOnLoad),
   mTextureManagerAlive(true)
 {
   mTextureManager.AddObserver(*this);
index f65d60b..b15101e 100644 (file)
@@ -40,8 +40,9 @@ public:
      * @brief Informs observer when the next texture set is ready to display
      * @param[in] textureSet The ready texture set
      * @param[in] interval interval(ms) for the frame
+     * @param[in] preMultiplied whether the texture is premultied alpha or not.
      */
-    virtual void FrameReady(TextureSet textureSet, uint32_t interval) = 0;
+    virtual void FrameReady(TextureSet textureSet, uint32_t interval, bool preMultiplied) = 0;
   };
 
   struct UrlStore
@@ -58,14 +59,15 @@ public:
 public:
   /**
    * @brief Constructor.
-   * @param[in] textureManager The texture manager
-   * @param[in] size           The width and height to fit the loaded image to.
-   * @param[in] fittingMode    The FittingMode of the resource to load
-   * @param[in] samplingMode   The SamplingMode of the resource to load
-   * @param[in] observer       FrameReady observer
-   * @param[in] maskingData    Masking data to be applied.
-   * @param[in] batchSize The size of a batch to load
-   * @param[in] interval Time interval(ms) between each frame
+   * @param[in] textureManager    The texture manager
+   * @param[in] size              The width and height to fit the loaded image to.
+   * @param[in] fittingMode       The FittingMode of the resource to load
+   * @param[in] samplingMode      The SamplingMode of the resource to load
+   * @param[in] observer          FrameReady observer
+   * @param[in] maskingData       Masking data to be applied.
+   * @param[in] batchSize         The size of a batch to load
+   * @param[in] interval          Time interval(ms) between each frame
+   * @param[in] preMultiplyOnLoad The flag if image's color should be multiplied by it's alpha
    *
    * This will start loading textures immediately, according to the
    * batch and cache sizes. The cache is as large as the number of urls.
@@ -77,7 +79,8 @@ public:
              TextureManager::MaskingDataPointer& maskingData,
              ImageCache::FrameReadyObserver&     observer,
              uint32_t                            batchSize,
-             uint32_t                            interval);
+             uint32_t                            interval,
+             bool                                preMultiplyOnLoad);
 
   virtual ~ImageCache();
 
@@ -152,6 +155,7 @@ protected:
   uint32_t                            mInterval;
   TextureManager::LoadState           mLoadState;
   bool                                mRequestingLoad : 1;
+  bool                                mPreMultiplyOnLoad : 1;
   bool                                mTextureManagerAlive : 1;
 };
 
index 995ea60..f23456c 100644 (file)
@@ -73,7 +73,7 @@ RollingAnimatedImageCache::RollingAnimatedImageCache(TextureManager&
                                                      const Dali::WrapMode::Type&         wrapModeV,
                                                      bool                                isSynchronousLoading,
                                                      bool                                preMultiplyOnLoad)
-: ImageCache(textureManager, size, fittingMode, samplingMode, maskingData, observer, batchSize, 0u),
+: ImageCache(textureManager, size, fittingMode, samplingMode, maskingData, observer, batchSize, 0u, preMultiplyOnLoad),
   mImageUrl(animatedImageLoading.GetUrl()),
   mAnimatedImageLoading(animatedImageLoading),
   mFrameCount(SINGLE_IMAGE_COUNT),
@@ -82,8 +82,7 @@ RollingAnimatedImageCache::RollingAnimatedImageCache(TextureManager&
   mQueue(cacheSize),
   mWrapModeU(wrapModeU),
   mWrapModeV(wrapModeV),
-  mIsSynchronousLoading(isSynchronousLoading),
-  mPreMultiplyOnLoad(preMultiplyOnLoad)
+  mIsSynchronousLoading(isSynchronousLoading)
 {
   mTextureIds.resize(mFrameCount);
   mIntervals.assign(mFrameCount, 0);
@@ -111,7 +110,10 @@ TextureSet RollingAnimatedImageCache::Frame(uint32_t frameIndex)
   bool synchronouslyLoaded = false;
   if(mIsSynchronousLoading && mQueue.IsEmpty())
   {
-    textureSet        = RequestFrameLoading(frameIndex, true);
+    auto preMultiplyOnLoading = mPreMultiplyOnLoad ? TextureManager::MultiplyOnLoad::MULTIPLY_ON_LOAD
+                                                   : TextureManager::MultiplyOnLoad::LOAD_WITHOUT_MULTIPLY;
+
+    textureSet        = RequestFrameLoading(frameIndex, true, preMultiplyOnLoading);
     batchFrameIndex   = (frameIndex + 1) % mFrameCount;
     uint32_t interval = 0u;
     if(textureSet)
@@ -119,7 +121,7 @@ TextureSet RollingAnimatedImageCache::Frame(uint32_t frameIndex)
       synchronouslyLoaded = true;
       interval            = mAnimatedImageLoading.GetFrameInterval(mQueue.Back().mFrameNumber);
     }
-    MakeFrameReady(synchronouslyLoaded, textureSet, interval);
+    MakeFrameReady(synchronouslyLoaded, textureSet, interval, preMultiplyOnLoading == TextureManager::MultiplyOnLoad::MULTIPLY_ON_LOAD);
   }
 
   if(popExist || mQueue.IsEmpty() || synchronouslyLoaded)
@@ -191,7 +193,15 @@ bool RollingAnimatedImageCache::IsFrontReady() const
   return (!mQueue.IsEmpty() && mQueue.Front().mReady);
 }
 
-TextureSet RollingAnimatedImageCache::RequestFrameLoading(uint32_t frameIndex, bool synchronousLoading)
+TextureSet RollingAnimatedImageCache::RequestFrameLoading(uint32_t frameIndex)
+{
+  auto preMultiplyOnLoading = mPreMultiplyOnLoad ? TextureManager::MultiplyOnLoad::MULTIPLY_ON_LOAD
+                                                 : TextureManager::MultiplyOnLoad::LOAD_WITHOUT_MULTIPLY;
+
+  return RequestFrameLoading(frameIndex, false, preMultiplyOnLoading);
+}
+
+TextureSet RollingAnimatedImageCache::RequestFrameLoading(uint32_t frameIndex, bool synchronousLoading, TextureManager::MultiplyOnLoad& preMultiplyOnLoading)
 {
   ImageFrame imageFrame;
   imageFrame.mFrameNumber = frameIndex;
@@ -201,9 +211,6 @@ TextureSet RollingAnimatedImageCache::RequestFrameLoading(uint32_t frameIndex, b
 
   mLoadState = TextureManager::LoadState::LOADING;
 
-  auto preMultiplyOnLoading = mPreMultiplyOnLoad ? TextureManager::MultiplyOnLoad::MULTIPLY_ON_LOAD
-                                                 : TextureManager::MultiplyOnLoad::LOAD_WITHOUT_MULTIPLY;
-
   TextureManager::TextureId loadTextureId = TextureManager::INVALID_TEXTURE_ID;
   TextureSet                textureSet    = mTextureManager.LoadAnimatedImageTexture(mImageUrl,
                                                                    mAnimatedImageLoading,
@@ -238,7 +245,7 @@ void RollingAnimatedImageCache::LoadBatch(uint32_t frameIndex)
   {
     if(mLoadState != TextureManager::LoadState::LOADING)
     {
-      RequestFrameLoading(frameIndex, false);
+      RequestFrameLoading(frameIndex);
     }
     else
     {
@@ -309,12 +316,13 @@ void RollingAnimatedImageCache::ClearCache()
   mLoadState = TextureManager::LoadState::NOT_STARTED;
 }
 
-void RollingAnimatedImageCache::MakeFrameReady(bool loadSuccess, TextureSet textureSet, uint32_t interval)
+void RollingAnimatedImageCache::MakeFrameReady(bool loadSuccess, TextureSet textureSet, uint32_t interval, bool preMultiplied)
 {
   if(!loadSuccess)
   {
     mLoadState = TextureManager::LoadState::LOAD_FAILED;
-    mObserver.FrameReady(TextureSet(), 0);
+    // preMultiplied should be false because broken image don't premultiply alpha on load
+    mObserver.FrameReady(TextureSet(), 0, false);
   }
   else
   {
@@ -337,7 +345,7 @@ void RollingAnimatedImageCache::MakeFrameReady(bool loadSuccess, TextureSet text
     // If it is, notify frame ready to observer.
     if(frontFrameReady == false && IsFrontReady())
     {
-      mObserver.FrameReady(textureSet, interval);
+      mObserver.FrameReady(textureSet, interval, preMultiplied);
     }
   }
 }
@@ -354,7 +362,7 @@ void RollingAnimatedImageCache::LoadComplete(bool loadSuccess, TextureInformatio
     textureInformation.textureSet.SetSampler(0u, sampler);
   }
 
-  MakeFrameReady(loadSuccess, textureInformation.textureSet, textureInformation.interval);
+  MakeFrameReady(loadSuccess, textureInformation.textureSet, textureInformation.interval, textureInformation.preMultiplied);
 
   if(loadSuccess)
   {
@@ -365,7 +373,7 @@ void RollingAnimatedImageCache::LoadComplete(bool loadSuccess, TextureInformatio
     {
       uint32_t loadingIndex = mLoadWaitingQueue.front();
       mLoadWaitingQueue.erase(mLoadWaitingQueue.begin());
-      RequestFrameLoading(loadingIndex, false);
+      RequestFrameLoading(loadingIndex);
     }
     else if(mQueue.Count() == 1u && textureInformation.frameCount > SINGLE_IMAGE_COUNT)
     {
index c827e40..a42854b 100644 (file)
@@ -116,14 +116,25 @@ private:
   bool IsFrontReady() const;
 
   /**
+   * @brief Request to Load a frame asynchronously
+   *
+   * @param[in] frameIndex index of frame to be loaded.
+   *
+   * @return the texture set currently loaded.
+   */
+  TextureSet RequestFrameLoading(uint32_t frameIndex);
+
+  /**
    * @brief Request to Load a frame
    *
-   * @param[in] frameIndex          index of frame to be loaded.
-   * @param[in] synchronousLoading  true if the frame should be loaded synchronously
+   * @param[in] frameIndex             Index of frame to be loaded.
+   * @param[in] synchronousLoading     True if the frame should be loaded synchronously
+   * @param[in,out] preMultiplyOnLoad  True if the image color should be multiplied by it's alpha. Set to false if the
+   *                                   image has no alpha channel
    *
    * @return the texture set currently loaded.
    */
-  TextureSet RequestFrameLoading(uint32_t frameIndex, bool synchronousLoading);
+  TextureSet RequestFrameLoading(uint32_t frameIndex, bool synchronousLoading, TextureManager::MultiplyOnLoad& preMultiplyOnLoading);
 
   /**
    * @brief Load the next batch of images
@@ -159,8 +170,9 @@ private:
    * @param[in] loadSuccess whether the loading is succeded or not.
    * @param[in] textureSet textureSet for this frame.
    * @param[in] interval interval between this frame and next frame.
+   * @param[in] preMultiplied whether the texture is premultied alpha or not.
    */
-  void MakeFrameReady(bool loadSuccess, TextureSet textureSet, uint32_t interval);
+  void MakeFrameReady(bool loadSuccess, TextureSet textureSet, uint32_t interval, bool preMultiplied);
 
   /**
    * @brief Pop front entity of Cache.
@@ -195,7 +207,6 @@ private:
   Dali::WrapMode::Type       mWrapModeU : 3;
   Dali::WrapMode::Type       mWrapModeV : 3;
   bool                       mIsSynchronousLoading;
-  bool                       mPreMultiplyOnLoad;
 };
 
 } // namespace Internal
index 19f025d..99e12e6 100644 (file)
@@ -66,8 +66,9 @@ RollingImageCache::RollingImageCache(TextureManager&                     texture
                                      ImageCache::FrameReadyObserver&     observer,
                                      uint16_t                            cacheSize,
                                      uint16_t                            batchSize,
-                                     uint32_t                            interval)
-: ImageCache(textureManager, size, fittingMode, samplingMode, maskingData, observer, batchSize, interval),
+                                     uint32_t                            interval,
+                                     bool                                preMultiplyOnLoad)
+: ImageCache(textureManager, size, fittingMode, samplingMode, maskingData, observer, batchSize, interval, preMultiplyOnLoad),
   mImageUrls(urlList),
   mQueue(cacheSize)
 {
@@ -167,11 +168,13 @@ void RollingImageCache::LoadBatch(uint32_t frameIndex)
     ImageAtlasManagerPtr  imageAtlasManager  = nullptr;
     Vector4               textureRect;
     Dali::ImageDimensions textureRectSize;
-    auto                  preMultiply = TextureManager::MultiplyOnLoad::LOAD_WITHOUT_MULTIPLY;
+
+    auto preMultiplyOnLoading = mPreMultiplyOnLoad ? TextureManager::MultiplyOnLoad::MULTIPLY_ON_LOAD
+                                                   : TextureManager::MultiplyOnLoad::LOAD_WITHOUT_MULTIPLY;
 
     TextureManager::TextureId loadTextureId = TextureManager::INVALID_TEXTURE_ID;
     TextureSet                textureSet    = mTextureManager.LoadTexture(
-      url, mDesiredSize, mFittingMode, mSamplingMode, mMaskingData, synchronousLoading, loadTextureId, textureRect, textureRectSize, atlasingStatus, loadingStatus, this, atlasObserver, imageAtlasManager, ENABLE_ORIENTATION_CORRECTION, TextureManager::ReloadPolicy::CACHED, preMultiply);
+      url, mDesiredSize, mFittingMode, mSamplingMode, mMaskingData, synchronousLoading, loadTextureId, textureRect, textureRectSize, atlasingStatus, loadingStatus, this, atlasObserver, imageAtlasManager, ENABLE_ORIENTATION_CORRECTION, TextureManager::ReloadPolicy::CACHED, preMultiplyOnLoading);
     mImageUrls[imageFrame.mUrlIndex].mTextureId = loadTextureId;
 
     mRequestingLoad = false;
@@ -259,13 +262,14 @@ void RollingImageCache::LoadComplete(bool loadSuccess, TextureInformation textur
         sampler.SetWrapMode(Dali::WrapMode::Type::DEFAULT, Dali::WrapMode::Type::DEFAULT);
         textureInformation.textureSet.SetSampler(0u, sampler);
       }
-      mObserver.FrameReady(textureInformation.textureSet, mInterval);
+      mObserver.FrameReady(textureInformation.textureSet, mInterval, textureInformation.preMultiplied);
     }
   }
   else
   {
     mLoadState = TextureManager::LoadState::LOAD_FAILED;
-    mObserver.FrameReady(TextureSet(), 0);
+    // preMultiplied should be false because broken image don't premultiply alpha on load
+    mObserver.FrameReady(TextureSet(), 0, false);
   }
 
   LOG_CACHE;
index 8fbaad6..59fa6a7 100644 (file)
@@ -37,16 +37,17 @@ class RollingImageCache : public ImageCache, public TextureUploadObserver
 public:
   /**
    * Constructor.
-   * @param[in] textureManager The texture manager
-   * @param[in] size           The width and height to fit the loaded image to.
-   * @param[in] fittingMode    The FittingMode of the resource to load
-   * @param[in] samplingMode   The SamplingMode of the resource to load
-   * @param[in] urlList        List of urls to cache
-   * @param[in] maskingData    Masking data to be applied.
-   * @param[in] observer       FrameReady observer
-   * @param[in] cacheSize      The size of the cache
-   * @param[in] batchSize      The size of a batch to load
-   * @param[in] interval       Time interval between each frame
+   * @param[in] textureManager    The texture manager
+   * @param[in] size              The width and height to fit the loaded image to.
+   * @param[in] fittingMode       The FittingMode of the resource to load
+   * @param[in] samplingMode      The SamplingMode of the resource to load
+   * @param[in] urlList           List of urls to cache
+   * @param[in] maskingData       Masking data to be applied.
+   * @param[in] observer          FrameReady observer
+   * @param[in] cacheSize         The size of the cache
+   * @param[in] batchSize         The size of a batch to load
+   * @param[in] interval          Time interval between each frame
+   * @param[in] preMultiplyOnLoad The flag if image's color should be multiplied by it's alpha
    *
    * This will start loading textures immediately, according to the
    * batch and cache sizes.
@@ -60,7 +61,8 @@ public:
                     ImageCache::FrameReadyObserver&     observer,
                     uint16_t                            cacheSize,
                     uint16_t                            batchSize,
-                    uint32_t                            interval);
+                    uint32_t                            interval,
+                    bool                                preMultiplyOnLoad);
 
   /**
    * Destructor
index 2fcf2a9..0669ed5 100644 (file)
@@ -525,6 +525,11 @@ void ImageVisual::GetNaturalSize(Vector2& naturalSize)
         {
           imageSize = actor.GetProperty(Actor::Property::SIZE).Get<Vector2>();
         }
+        else
+        {
+          imageSize = mPlacementActorSize;
+        }
+
         mFactoryCache.UpdateBrokenImageRenderer(mImpl->mRenderer, imageSize);
         Texture brokenImage = mImpl->mRenderer.GetTextures().GetTexture(0);
         naturalSize.x       = brokenImage.GetWidth();
@@ -757,8 +762,10 @@ void ImageVisual::DoSetOnScene(Actor& actor)
     Vector2 imageSize = Vector2::ZERO;
     if(actor)
     {
-      imageSize = actor.GetProperty(Actor::Property::SIZE).Get<Vector2>();
+      imageSize  = actor.GetProperty(Actor::Property::SIZE).Get<Vector2>();
+      mPlacementActorSize = imageSize;
     }
+
     mFactoryCache.UpdateBrokenImageRenderer(mImpl->mRenderer, imageSize);
     actor.AddRenderer(mImpl->mRenderer);
     mPlacementActor.Reset();
@@ -905,8 +912,14 @@ void ImageVisual::LoadComplete(bool loadingSuccess, TextureInformation textureIn
       Vector2 imageSize = Vector2::ZERO;
       if(actor)
       {
-        imageSize = actor.GetProperty(Actor::Property::SIZE).Get<Vector2>();
+        imageSize  = actor.GetProperty(Actor::Property::SIZE).Get<Vector2>();
+        mPlacementActorSize = imageSize;
       }
+      else
+      {
+        imageSize = mPlacementActorSize;
+      }
+
       mFactoryCache.UpdateBrokenImageRenderer(mImpl->mRenderer, imageSize);
       textureInformation.textureSet = mImpl->mRenderer.GetTextures();
     }
index 307ab19..4712f39 100644 (file)
@@ -332,6 +332,7 @@ private:
   TextureManager::TextureId mTextureId;
   TextureSet                mTextures;
   Vector2                   mTextureSize;
+  Vector2                   mPlacementActorSize;
 
   ImageVisualShaderFactory& mImageVisualShaderFactory;
 
index 14e1ce3..ed778f4 100644 (file)
@@ -565,12 +565,12 @@ void TextVisual::UpdateRenderer()
 
       const bool outlineEnabled             = (mController->GetTextModel()->GetOutlineWidth() > Math::MACHINE_EPSILON_1);
       const bool backgroundEnabled          = mController->GetTextModel()->IsBackgroundEnabled();
-      const bool markupProcessorEnabled     = mController->IsMarkupProcessorEnabled();
-      const bool markupUnderlineEnabled     = markupProcessorEnabled && mController->GetTextModel()->IsMarkupUnderlineSet();
-      const bool markupStrikethroughEnabled = markupProcessorEnabled && mController->GetTextModel()->IsMarkupStrikethroughSet();
+      const bool markupOrSpannedText        = mController->IsMarkupProcessorEnabled() || mController->GetTextModel()->IsSpannedTextPlaced();
+      const bool markupUnderlineEnabled     = markupOrSpannedText && mController->GetTextModel()->IsMarkupUnderlineSet();
+      const bool markupStrikethroughEnabled = markupOrSpannedText && mController->GetTextModel()->IsMarkupStrikethroughSet();
       const bool underlineEnabled           = mController->GetTextModel()->IsUnderlineEnabled() || markupUnderlineEnabled;
       const bool strikethroughEnabled       = mController->GetTextModel()->IsStrikethroughEnabled() || markupStrikethroughEnabled;
-      const bool styleEnabled               = (shadowEnabled || outlineEnabled || backgroundEnabled || markupProcessorEnabled);
+      const bool styleEnabled               = (shadowEnabled || outlineEnabled || backgroundEnabled || markupOrSpannedText);
       const bool isOverlayStyle             = underlineEnabled || strikethroughEnabled;
 
       AddRenderer(control, relayoutSize, hasMultipleTextColors, containsColorGlyph, styleEnabled, isOverlayStyle);
index 5161cd1..182013c 100644 (file)
@@ -29,7 +29,7 @@ namespace Toolkit
 {
 const unsigned int TOOLKIT_MAJOR_VERSION = 2;
 const unsigned int TOOLKIT_MINOR_VERSION = 2;
-const unsigned int TOOLKIT_MICRO_VERSION = 4;
+const unsigned int TOOLKIT_MICRO_VERSION = 6;
 const char* const  TOOLKIT_BUILD_DATE    = __DATE__ " " __TIME__;
 
 #ifdef DEBUG_ENABLED
index f686d38..08608df 100644 (file)
@@ -1,6 +1,6 @@
 Name:       dali2-toolkit
 Summary:    Dali 3D engine Toolkit
-Version:    2.2.4
+Version:    2.2.6
 Release:    1
 Group:      System/Libraries
 License:    Apache-2.0 and BSD-3-Clause and MIT