[dali_2.1.17] Merge branch 'devel/master' 10/273610/1
authorDavid Steele <david.steele@samsung.com>
Fri, 8 Apr 2022 11:55:14 +0000 (12:55 +0100)
committerDavid Steele <david.steele@samsung.com>
Fri, 8 Apr 2022 11:55:14 +0000 (12:55 +0100)
Change-Id: I2d53b9caf4c385e8f60f305232837b8c6726d23d

45 files changed:
automated-tests/resources/MRendererTest.gltf [new file with mode: 0644]
automated-tests/src/dali-scene-loader/utc-Dali-Gltf2Loader.cpp
automated-tests/src/dali-toolkit-internal/utc-Dali-Visuals-internal.cpp
automated-tests/src/dali-toolkit/utc-Dali-KeyboardFocusManager.cpp
automated-tests/src/dali-toolkit/utc-Dali-TextEditor.cpp
automated-tests/src/dali-toolkit/utc-Dali-TextField.cpp
automated-tests/src/dali-toolkit/utc-Dali-TextLabel.cpp
dali-scene-loader/internal/gltf2-asset.h
dali-scene-loader/public-api/gltf2-loader.cpp
dali-toolkit/devel-api/focus-manager/focus-finder.cpp
dali-toolkit/internal/controls/text-controls/text-editor-impl.cpp
dali-toolkit/internal/controls/text-controls/text-editor-impl.h
dali-toolkit/internal/controls/text-controls/text-field-impl.cpp
dali-toolkit/internal/controls/text-controls/text-field-impl.h
dali-toolkit/internal/focus-manager/keyboard-focus-manager-impl.cpp
dali-toolkit/internal/focus-manager/keyboard-focus-manager-impl.h
dali-toolkit/internal/text/bounded-paragraph-run.h
dali-toolkit/internal/text/decorator/text-decorator.cpp
dali-toolkit/internal/text/layouts/layout-engine.cpp
dali-toolkit/internal/text/markup-processor-anchor.cpp
dali-toolkit/internal/text/markup-processor-background.cpp
dali-toolkit/internal/text/markup-processor-character-spacing.cpp
dali-toolkit/internal/text/markup-processor-color.cpp
dali-toolkit/internal/text/markup-processor-embedded-item.cpp
dali-toolkit/internal/text/markup-processor-font.cpp
dali-toolkit/internal/text/markup-processor-paragraph.cpp
dali-toolkit/internal/text/markup-processor-paragraph.h
dali-toolkit/internal/text/markup-processor-span.cpp
dali-toolkit/internal/text/markup-processor-strikethrough.cpp
dali-toolkit/internal/text/markup-processor-underline.cpp
dali-toolkit/internal/text/markup-processor.cpp
dali-toolkit/internal/text/markup-tags-and-attributes.h [new file with mode: 0644]
dali-toolkit/internal/text/rendering/text-typesetter.cpp
dali-toolkit/internal/text/text-controller-event-handler.cpp
dali-toolkit/internal/text/text-controller-impl-event-handler.cpp
dali-toolkit/internal/text/text-controller-impl.cpp
dali-toolkit/internal/text/text-controller-impl.h
dali-toolkit/internal/text/text-controller.cpp
dali-toolkit/internal/text/text-controller.h
dali-toolkit/internal/visuals/npatch/npatch-visual.cpp
dali-toolkit/internal/visuals/npatch/npatch-visual.h
dali-toolkit/internal/visuals/visual-factory-cache.cpp
dali-toolkit/internal/visuals/visual-factory-cache.h
dali-toolkit/public-api/dali-toolkit-version.cpp
packaging/dali-toolkit.spec

diff --git a/automated-tests/resources/MRendererTest.gltf b/automated-tests/resources/MRendererTest.gltf
new file mode 100644 (file)
index 0000000..ae3d113
--- /dev/null
@@ -0,0 +1,179 @@
+{\r
+  "scene" : 0,\r
+  "scenes" : [\r
+    {\r
+      "nodes" : [ 0 ]\r
+    }\r
+  ],\r
+\r
+  "nodes" : [\r
+    {\r
+      "mesh" : 0,\r
+      "rotation" : [ 0.0, 0.0, 0.0, 1.0 ],\r
+      "scale": [\r
+          100.0,\r
+          100.0,\r
+          100.0\r
+      ],\r
+      "name": "RootNode"\r
+    }\r
+  ],\r
+\r
+  "meshes" : [\r
+    {\r
+      "primitives" : [ {\r
+        "attributes" : {\r
+          "POSITION" : 1\r
+        },\r
+        "indices" : 0,\r
+        "material": 0\r
+      } ]\r
+    }\r
+  ],\r
+\r
+  "animations": [\r
+    {\r
+      "samplers" : [\r
+        {\r
+          "input" : 2,\r
+          "interpolation" : "LINEAR",\r
+          "output" : 3\r
+        }\r
+      ],\r
+      "channels" : [ {\r
+        "sampler" : 0,\r
+        "target" : {\r
+          "node" : 0,\r
+          "path" : "rotation"\r
+        }\r
+      } ]\r
+    }\r
+  ],\r
+\r
+  "buffers" : [\r
+    {\r
+      "uri" : "simpleTriangle.bin",\r
+      "byteLength" : 44\r
+    },\r
+    {\r
+      "uri" : "animation.bin",\r
+      "byteLength" : 100\r
+    }\r
+  ],\r
+\r
+  "bufferViews" : [\r
+    {\r
+      "buffer" : 0,\r
+      "byteOffset" : 0,\r
+      "byteLength" : 6,\r
+      "target" : 34963\r
+    },\r
+    {\r
+      "buffer" : 0,\r
+      "byteOffset" : 8,\r
+      "byteLength" : 36,\r
+      "target" : 34962\r
+    },\r
+    {\r
+      "buffer" : 1,\r
+      "byteOffset" : 0,\r
+      "byteLength" : 100\r
+    }\r
+  ],\r
+\r
+  "accessors" : [\r
+    {\r
+      "bufferView" : 0,\r
+      "byteOffset" : 0,\r
+      "componentType" : 5123,\r
+      "count" : 3,\r
+      "type" : "SCALAR",\r
+      "max" : [ 2 ],\r
+      "min" : [ 0 ]\r
+    },\r
+    {\r
+      "bufferView" : 1,\r
+      "byteOffset" : 0,\r
+      "componentType" : 5126,\r
+      "count" : 3,\r
+      "type" : "VEC3",\r
+      "max" : [ 1.0, 1.0, 0.0 ],\r
+      "min" : [ 0.0, 0.0, 0.0 ]\r
+    },\r
+    {\r
+      "bufferView" : 2,\r
+      "byteOffset" : 0,\r
+      "componentType" : 5126,\r
+      "count" : 5,\r
+      "type" : "SCALAR",\r
+      "max" : [ 1.0 ],\r
+      "min" : [ 0.0 ]\r
+    },\r
+    {\r
+      "bufferView" : 2,\r
+      "byteOffset" : 20,\r
+      "componentType" : 5126,\r
+      "count" : 5,\r
+      "type" : "VEC4",\r
+      "max" : [ 0.0, 0.0, 1.0, 1.0 ],\r
+      "min" : [ 0.0, 0.0, 0.0, -0.707 ]\r
+    }\r
+  ],\r
+\r
+  "asset" : {\r
+    "generator": "glTF Tools for M-Renderer",\r
+    "version" : "2.0"\r
+  },\r
+\r
+  "materials": [\r
+    {\r
+      "pbrMetallicRoughness":\r
+      {\r
+        "baseColorTexture":\r
+        {\r
+          "index": 0,\r
+          "texCoord": 0\r
+        },\r
+        "metallicFactor": 0,\r
+        "baseColorFactor":\r
+        [\r
+          1,\r
+          1,\r
+          1,\r
+          1\r
+        ],\r
+        "roughnessFactor": 1\r
+      },\r
+      "emissiveFactor":\r
+      [\r
+        0,\r
+        0,\r
+        0\r
+      ],\r
+      "alphaMode": "OPAQUE",\r
+      "doubleSided": false\r
+    }\r
+  ],\r
+\r
+  "textures": [\r
+    {\r
+      "sampler": 0,\r
+      "source": 0\r
+    }\r
+  ],\r
+\r
+  "images": [\r
+    {\r
+      "uri": "AnimatedCube_BaseColor.png"\r
+    }\r
+  ],\r
+\r
+  "samplers": [\r
+    {\r
+      "magFilter": 9729,\r
+      "minFilter": 9986,\r
+      "wrapS": 10497,\r
+      "wrapT": 10497\r
+    }\r
+  ]\r
+}\r
index 3f829dc..47515b3 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ * 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.
 // Enable debug log for test coverage
 #define DEBUG_ENABLED 1
 
+#include <dali-test-suite-utils.h>
+#include <string_view>
+#include "dali-scene-loader/public-api/gltf2-loader.h"
+#include "dali-scene-loader/public-api/load-result.h"
 #include "dali-scene-loader/public-api/resource-bundle.h"
 #include "dali-scene-loader/public-api/scene-definition.h"
-#include "dali-scene-loader/public-api/load-result.h"
-#include "dali-scene-loader/public-api/gltf2-loader.h"
 #include "dali-scene-loader/public-api/shader-definition-factory.h"
-#include <dali-test-suite-utils.h>
-#include <string_view>
 
 using namespace Dali;
 using namespace Dali::SceneLoader;
 
 #define DALI_TEST_THROW(expression, exception, predicate) \
-  {\
-    bool daliTestThrowSuccess__ = false;\
-    try\
-    {\
-      do { expression; } while(0);\
-      printf("No exception was thrown.\n");\
-    }\
-    catch (std::decay<exception>::type& ex)\
-    {\
-      daliTestThrowSuccess__ = predicate(ex);\
-    }\
-    catch (...)\
-    {\
-      printf("Wrong type of exception thrown.\n");\
-    }\
-    DALI_TEST_CHECK(daliTestThrowSuccess__);\
+  {                                                       \
+    bool daliTestThrowSuccess__ = false;                  \
+    try                                                   \
+    {                                                     \
+      do                                                  \
+      {                                                   \
+        expression;                                       \
+      } while(0);                                         \
+      printf("No exception was thrown.\n");               \
+    }                                                     \
+    catch(std::decay<exception>::type & ex)               \
+    {                                                     \
+      daliTestThrowSuccess__ = predicate(ex);             \
+    }                                                     \
+    catch(...)                                            \
+    {                                                     \
+      printf("Wrong type of exception thrown.\n");        \
+    }                                                     \
+    DALI_TEST_CHECK(daliTestThrowSuccess__);              \
   }
 
 namespace
 {
 struct Context
 {
-  ResourceBundle resources;
+  ResourceBundle::PathProvider pathProvider = [](ResourceType::Value type) {
+    return TEST_RESOURCE_DIR "/";
+  };
+
+  ResourceBundle  resources;
   SceneDefinition scene;
 
-  std::vector<AnimationDefinition> animations;
+  std::vector<AnimationDefinition>      animations;
   std::vector<AnimationGroupDefinition> animationGroups;
-  std::vector<CameraParameters> cameras;
-  std::vector<LightParameters> lights;
+  std::vector<CameraParameters>         cameras;
+  std::vector<LightParameters>          lights;
 
-  LoadResult loadResult {
+  LoadResult loadResult{
     resources,
     scene,
     animations,
     animationGroups,
     cameras,
-    lights
-  };
+    lights};
 };
 
 struct ExceptionMessageStartsWith
@@ -77,7 +83,7 @@ struct ExceptionMessageStartsWith
   bool operator()(const std::runtime_error& e)
   {
     const bool success = (0 == strncmp(e.what(), expected.data(), expected.size()));
-    if (!success)
+    if(!success)
     {
       printf("Expected: %s, got: %s.\n", expected.data(), e.what());
     }
@@ -85,7 +91,7 @@ struct ExceptionMessageStartsWith
   }
 };
 
-}
+} // namespace
 
 int UtcDaliGltfLoaderFailedToLoad(void)
 {
@@ -95,8 +101,8 @@ int UtcDaliGltfLoaderFailedToLoad(void)
   sdf.SetResources(ctx.resources);
 
   DALI_TEST_THROW(LoadGltfScene("non-existent.gltf", sdf, ctx.loadResult),
-    std::runtime_error,
-    ExceptionMessageStartsWith{"Failed to load"});
+                  std::runtime_error,
+                  ExceptionMessageStartsWith{"Failed to load"});
 
   DALI_TEST_EQUAL(0, ctx.scene.GetRoots().size());
   DALI_TEST_EQUAL(0, ctx.scene.GetNodeCount());
@@ -123,8 +129,8 @@ int UtcDaliGltfLoaderFailedToParse(void)
   sdf.SetResources(ctx.resources);
 
   DALI_TEST_THROW(LoadGltfScene(TEST_RESOURCE_DIR "/invalid.gltf", sdf, ctx.loadResult),
-    std::runtime_error,
-    ExceptionMessageStartsWith{"Failed to parse"});
+                  std::runtime_error,
+                  ExceptionMessageStartsWith{"Failed to parse"});
 
   DALI_TEST_EQUAL(0, ctx.scene.GetRoots().size());
   DALI_TEST_EQUAL(0, ctx.scene.GetNodeCount());
@@ -159,50 +165,46 @@ int UtcDaliGltfLoaderSuccess1(void)
 
   auto& materials = ctx.resources.mMaterials;
   DALI_TEST_EQUAL(2u, materials.size());
-  const MaterialDefinition materialGroundTruth[] {
-    {
-      MaterialDefinition::ALBEDO | MaterialDefinition::METALLIC | MaterialDefinition::ROUGHNESS |
-        MaterialDefinition::NORMAL | MaterialDefinition::TRANSPARENCY | MaterialDefinition::GLTF_CHANNELS |
-        (0x80 << MaterialDefinition::ALPHA_CUTOFF_SHIFT),
-      0,
-      Vector4(1.f, .766f, .336f, 1.f),
-      1.f,
-      0.f,
-      {
-        { MaterialDefinition::ALBEDO,
-          { "AnimatedCube_BaseColor.png",
-            SamplerFlags::Encode(FilterMode::LINEAR_MIPMAP_LINEAR, FilterMode::LINEAR, WrapMode::CLAMP_TO_EDGE, WrapMode::REPEAT) } },
-        { MaterialDefinition::METALLIC | MaterialDefinition::ROUGHNESS | MaterialDefinition::GLTF_CHANNELS,
-          { "AnimatedCube_MetallicRoughness.png",
-            SamplerFlags::Encode(FilterMode::NEAREST_MIPMAP_LINEAR, FilterMode::NEAREST, WrapMode::CLAMP_TO_EDGE, WrapMode::MIRRORED_REPEAT) } },
-        { MaterialDefinition::NORMAL,
-          { "AnimatedCube_BaseColor.png",
-            SamplerFlags::Encode(FilterMode::LINEAR_MIPMAP_LINEAR, FilterMode::LINEAR, WrapMode::CLAMP_TO_EDGE, WrapMode::REPEAT) } },
-      }
-    },
-    {
-      MaterialDefinition::ALBEDO | MaterialDefinition::METALLIC | MaterialDefinition::ROUGHNESS |
-        MaterialDefinition::NORMAL | MaterialDefinition::GLTF_CHANNELS,
-      0,
-      Vector4(1.f, .766f, .336f, 1.f),
-      1.f,
-      0.f,
-      {
-        { MaterialDefinition::ALBEDO,
-          { "AnimatedCube_BaseColor.png",
-            SamplerFlags::Encode(FilterMode::LINEAR_MIPMAP_LINEAR, FilterMode::LINEAR, WrapMode::CLAMP_TO_EDGE, WrapMode::REPEAT) } },
-        { MaterialDefinition::METALLIC | MaterialDefinition::ROUGHNESS | MaterialDefinition::GLTF_CHANNELS,
-          { "AnimatedCube_MetallicRoughness.png",
-            SamplerFlags::Encode(FilterMode::NEAREST_MIPMAP_LINEAR, FilterMode::NEAREST, WrapMode::CLAMP_TO_EDGE, WrapMode::MIRRORED_REPEAT) } },
-        { MaterialDefinition::NORMAL,
-          { "AnimatedCube_BaseColor.png",
-            SamplerFlags::Encode(FilterMode::LINEAR_MIPMAP_LINEAR, FilterMode::LINEAR, WrapMode::CLAMP_TO_EDGE, WrapMode::REPEAT) } },
-      }
-    },
+  const MaterialDefinition materialGroundTruth[]{
+    {MaterialDefinition::ALBEDO | MaterialDefinition::METALLIC | MaterialDefinition::ROUGHNESS |
+       MaterialDefinition::NORMAL | MaterialDefinition::TRANSPARENCY | MaterialDefinition::GLTF_CHANNELS |
+       (0x80 << MaterialDefinition::ALPHA_CUTOFF_SHIFT),
+     0,
+     Vector4(1.f, .766f, .336f, 1.f),
+     1.f,
+     0.f,
+     {
+       {MaterialDefinition::ALBEDO,
+        {"AnimatedCube_BaseColor.png",
+         SamplerFlags::Encode(FilterMode::LINEAR_MIPMAP_LINEAR, FilterMode::LINEAR, WrapMode::CLAMP_TO_EDGE, WrapMode::REPEAT)}},
+       {MaterialDefinition::METALLIC | MaterialDefinition::ROUGHNESS | MaterialDefinition::GLTF_CHANNELS,
+        {"AnimatedCube_MetallicRoughness.png",
+         SamplerFlags::Encode(FilterMode::NEAREST_MIPMAP_LINEAR, FilterMode::NEAREST, WrapMode::CLAMP_TO_EDGE, WrapMode::MIRRORED_REPEAT)}},
+       {MaterialDefinition::NORMAL,
+        {"AnimatedCube_BaseColor.png",
+         SamplerFlags::Encode(FilterMode::LINEAR_MIPMAP_LINEAR, FilterMode::LINEAR, WrapMode::CLAMP_TO_EDGE, WrapMode::REPEAT)}},
+     }},
+    {MaterialDefinition::ALBEDO | MaterialDefinition::METALLIC | MaterialDefinition::ROUGHNESS |
+       MaterialDefinition::NORMAL | MaterialDefinition::GLTF_CHANNELS,
+     0,
+     Vector4(1.f, .766f, .336f, 1.f),
+     1.f,
+     0.f,
+     {
+       {MaterialDefinition::ALBEDO,
+        {"AnimatedCube_BaseColor.png",
+         SamplerFlags::Encode(FilterMode::LINEAR_MIPMAP_LINEAR, FilterMode::LINEAR, WrapMode::CLAMP_TO_EDGE, WrapMode::REPEAT)}},
+       {MaterialDefinition::METALLIC | MaterialDefinition::ROUGHNESS | MaterialDefinition::GLTF_CHANNELS,
+        {"AnimatedCube_MetallicRoughness.png",
+         SamplerFlags::Encode(FilterMode::NEAREST_MIPMAP_LINEAR, FilterMode::NEAREST, WrapMode::CLAMP_TO_EDGE, WrapMode::MIRRORED_REPEAT)}},
+       {MaterialDefinition::NORMAL,
+        {"AnimatedCube_BaseColor.png",
+         SamplerFlags::Encode(FilterMode::LINEAR_MIPMAP_LINEAR, FilterMode::LINEAR, WrapMode::CLAMP_TO_EDGE, WrapMode::REPEAT)}},
+     }},
   };
 
   auto iMaterial = materials.begin();
-  for (auto& m : materialGroundTruth)
+  for(auto& m : materialGroundTruth)
   {
     printf("material %ld\n", iMaterial - materials.begin());
     auto& md = iMaterial->first;
@@ -214,7 +216,7 @@ int UtcDaliGltfLoaderSuccess1(void)
 
     DALI_TEST_EQUAL(md.mTextureStages.size(), m.mTextureStages.size());
     auto iTexture = md.mTextureStages.begin();
-    for (auto& ts: m.mTextureStages)
+    for(auto& ts : m.mTextureStages)
     {
       printf("texture %ld\n", iTexture - md.mTextureStages.begin());
       DALI_TEST_EQUAL(iTexture->mSemantic, ts.mSemantic);
@@ -228,48 +230,47 @@ int UtcDaliGltfLoaderSuccess1(void)
   auto& meshes = ctx.resources.mMeshes;
   DALI_TEST_EQUAL(2u, meshes.size());
 
-  using Blob = MeshDefinition::Blob;
+  using Blob     = MeshDefinition::Blob;
   using Accessor = MeshDefinition::Accessor;
-  const MeshDefinition meshGroundTruth[] {
+  const MeshDefinition meshGroundTruth[]{
     {
       0,
       Geometry::TRIANGLES,
       "AnimatedCube.bin",
-      Accessor{ Blob{ 0, 0 }, {} },
-      Accessor{ Blob{ 0, 0 }, {} },
-      Accessor{ Blob{ 0, 0 }, {} },
-      Accessor{ Blob{ 0, 0 }, {} },
-      Accessor{ Blob{ 0, 0 }, {} },
+      Accessor{Blob{0, 0}, {}},
+      Accessor{Blob{0, 0}, {}},
+      Accessor{Blob{0, 0}, {}},
+      Accessor{Blob{0, 0}, {}},
+      Accessor{Blob{0, 0}, {}},
     },
     {
       0,
       Geometry::TRIANGLES,
       "AnimatedCube.bin",
-      Accessor{ Blob{ 0, 0 }, {} },
-      Accessor{ Blob{ 0, 0 }, {} },
-      Accessor{ Blob{ 0, 0 }, {} },
-      Accessor{ Blob{ 0, 0 }, {} },
-      Accessor{ Blob{ 0, 0 }, {} },
+      Accessor{Blob{0, 0}, {}},
+      Accessor{Blob{0, 0}, {}},
+      Accessor{Blob{0, 0}, {}},
+      Accessor{Blob{0, 0}, {}},
+      Accessor{Blob{0, 0}, {}},
     },
   };
 
   auto iMesh = meshes.begin();
-  for (auto& m : meshGroundTruth)
+  for(auto& m : meshGroundTruth)
   {
     printf("mesh %ld\n", iMesh - meshes.begin());
 
     auto& md = iMesh->first;
     DALI_TEST_EQUAL(md.mFlags, m.mFlags);
     DALI_TEST_EQUAL(md.mPrimitiveType, m.mPrimitiveType);
-    for (auto mp: {
-      &MeshDefinition::mIndices,
-      &MeshDefinition::mPositions,
-      &MeshDefinition::mNormals,
-      &MeshDefinition::mTexCoords,
-      &MeshDefinition::mTangents,
-      &MeshDefinition::mJoints0,
-      &MeshDefinition::mWeights0
-    })
+    for(auto mp : {
+          &MeshDefinition::mIndices,
+          &MeshDefinition::mPositions,
+          &MeshDefinition::mNormals,
+          &MeshDefinition::mTexCoords,
+          &MeshDefinition::mTangents,
+          &MeshDefinition::mJoints0,
+          &MeshDefinition::mWeights0})
     {
       DALI_TEST_EQUAL((md.*mp).IsDefined(), (m.*mp).IsDefined());
       DALI_TEST_EQUAL((md.*mp).mBlob.IsDefined(), (m.*mp).mBlob.IsDefined());
@@ -296,24 +297,25 @@ int UtcDaliGltfLoaderSuccessShort(void)
   TestApplication app;
 
   const std::string resourcePath = TEST_RESOURCE_DIR "/";
-  auto pathProvider = [resourcePath](ResourceType::Value) {
+  auto              pathProvider = [resourcePath](ResourceType::Value) {
     return resourcePath;
   };
 
   Customization::Choices choices;
-  for (auto modelName : {
-    "2CylinderEngine",
-    "AnimatedMorphCube",
-    "AnimatedMorphSphere",
-    "AnimatedTriangle",
-    "BoxAnimated",
-    "CesiumMan",
-    "CesiumMilkTruck",
-    "EnvironmentTest",
-    "MetalRoughSpheres",
-    "MorphPrimitivesTest",
-    "SimpleSparseAccessor",
-  })
+  for(auto modelName : {
+        "2CylinderEngine",
+        "AnimatedMorphCube",
+        "AnimatedMorphSphere",
+        "AnimatedTriangle",
+        "BoxAnimated",
+        "CesiumMan",
+        "CesiumMilkTruck",
+        "EnvironmentTest",
+        "MetalRoughSpheres",
+        "MorphPrimitivesTest",
+        "MRendererTest",
+        "SimpleSparseAccessor",
+      })
   {
     Context ctx;
 
@@ -329,17 +331,17 @@ int UtcDaliGltfLoaderSuccessShort(void)
     DALI_TEST_CHECK(ctx.scene.GetNodeCount() > 0);
 
     auto& scene = ctx.scene;
-    for (auto iRoot : scene.GetRoots())
+    for(auto iRoot : scene.GetRoots())
     {
-      struct Visitor: NodeDefinition::IVisitor
+      struct Visitor : NodeDefinition::IVisitor
       {
-        struct ResourceReceiver: IResourceReceiver
+        struct ResourceReceiver : IResourceReceiver
         {
           std::vector<bool> mCounts;
 
           void Register(ResourceType::Value type, Index id) override
           {
-            if (type == ResourceType::Mesh)
+            if(type == ResourceType::Mesh)
             {
               mCounts[id] = true;
             }
@@ -348,21 +350,22 @@ int UtcDaliGltfLoaderSuccessShort(void)
 
         void Start(NodeDefinition& n) override
         {
-          if (n.mRenderable)
+          if(n.mRenderable)
           {
             n.mRenderable->RegisterResources(receiver);
           }
         }
 
         void Finish(NodeDefinition& n) override
-        {}
+        {
+        }
       } visitor;
       visitor.receiver.mCounts.resize(resources.mMeshes.size(), false);
 
       scene.Visit(iRoot, choices, visitor);
-      for (uint32_t i0 = 0, i1 = resources.mMeshes.size(); i0 < i1; ++i0)
+      for(uint32_t i0 = 0, i1 = resources.mMeshes.size(); i0 < i1; ++i0)
       {
-        if (visitor.receiver.mCounts[i0])
+        if(visitor.receiver.mCounts[i0])
         {
           auto raw = resources.mMeshes[i0].first.LoadRaw(resourcePath);
           DALI_TEST_CHECK(!raw.mAttribs.empty());
@@ -376,3 +379,59 @@ int UtcDaliGltfLoaderSuccessShort(void)
 
   END_TEST;
 }
+
+int UtcDaliGltfLoaderMRendererTest(void)
+{
+  Context ctx;
+
+  ShaderDefinitionFactory sdf;
+  sdf.SetResources(ctx.resources);
+  auto& resources = ctx.resources;
+  resources.mEnvironmentMaps.push_back({});
+
+  LoadGltfScene(TEST_RESOURCE_DIR "/MRendererTest.gltf", sdf, ctx.loadResult);
+
+  auto& scene = ctx.scene;
+  auto& roots = scene.GetRoots();
+  DALI_TEST_EQUAL(roots.size(), 1u);
+  DALI_TEST_EQUAL(scene.GetNode(roots[0])->mName, "RootNode");
+  DALI_TEST_EQUAL(scene.GetNode(roots[0])->mScale, Vector3(1.0f, 1.0f, 1.0f));
+
+  DALI_TEST_EQUAL(scene.GetNodeCount(), 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(root.GetChildCount(), 1u);
+  DALI_TEST_EQUAL(root.GetChildAt(0).GetProperty(Actor::Property::NAME).Get<std::string>(), "RootNode");
+  DALI_TEST_EQUAL(root.GetChildAt(0).GetProperty(Actor::Property::SCALE).Get<Vector3>(), Vector3(1.0f, 1.0f, 1.0f));
+
+  END_TEST;
+}
index 13464d3..6999ffa 100644 (file)
@@ -26,6 +26,7 @@
 #include <dali-toolkit/devel-api/visual-factory/visual-factory.h>
 #include <dali-toolkit/internal/visuals/visual-factory-cache.h>
 #include <dali-toolkit/internal/visuals/color/color-visual.h>
+#include <dali-toolkit/internal/visuals/npatch/npatch-visual.h>
 #include <dummy-visual.h>
 #include <../dali-toolkit/dali-toolkit-test-utils/dummy-control.h>
 #include <dali-toolkit/devel-api/visuals/arc-visual-properties-devel.h>
@@ -253,3 +254,46 @@ int UtcDaliArcVisualCreateInstancePropertyMap(void)
 
   END_TEST;
 }
+int UtcDaliVisualUpdateBrokenImageRenderer(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline( "UpdateBrokenImageRenderer Test" );
+
+  Toolkit::Internal::VisualFactoryCache* factoryCache = new Toolkit::Internal::VisualFactoryCache(false);
+
+  std::string defaultBrokenImageUrl = "not-9patch.png";
+
+  // Set default broken image
+  factoryCache->SetBrokenImageUrl(defaultBrokenImageUrl, std::vector<std::string>());
+
+  //Created dummy renderer
+  Geometry geometry = factoryCache->GetGeometry(Toolkit::Internal::VisualFactoryCache::QUAD_GEOMETRY);
+  Shader   shader   = Shader::New("foo","bar");
+  Renderer renderer = Renderer::New(geometry, shader);
+
+  DALI_TEST_CHECK(renderer);
+
+  // renderer doesn't changed.
+  factoryCache->UpdateBrokenImageRenderer(renderer, Vector2::ZERO, true);
+  Shader testShader1 = renderer.GetShader();
+
+  // Get default image renderer.
+  factoryCache->UpdateBrokenImageRenderer(renderer, Vector2::ZERO, false);
+  Shader testShader2 = renderer.GetShader();
+
+  // Get default image renderer but nine patch.
+  // Note : This API behavior can be changed. (DALi don't consider about default BrokenImageUrl is failed.
+  defaultBrokenImageUrl = "yes-9patch.9.png";
+  factoryCache->SetBrokenImageUrl(defaultBrokenImageUrl, std::vector<std::string>());
+  factoryCache->UpdateBrokenImageRenderer(renderer, Vector2::ZERO, false);
+  Shader testShader3 = renderer.GetShader();
+
+  DALI_TEST_CHECK(testShader1 != factoryCache->GetShader(Toolkit::Internal::VisualFactoryCache::IMAGE_SHADER));
+  DALI_TEST_CHECK(testShader1 != factoryCache->GetShader(Toolkit::Internal::VisualFactoryCache::NINE_PATCH_SHADER));
+  DALI_TEST_CHECK(testShader2 == factoryCache->GetShader(Toolkit::Internal::VisualFactoryCache::IMAGE_SHADER));
+  DALI_TEST_CHECK(testShader3 == factoryCache->GetShader(Toolkit::Internal::VisualFactoryCache::NINE_PATCH_SHADER));
+
+  delete factoryCache;
+
+  END_TEST;
+}
index 7b08e1a..1ca7bd4 100644 (file)
@@ -1936,8 +1936,8 @@ int UtcDaliKeyboardFocusManagerSetAndGetCurrentFocusActorInTouchMode(void)
   application.SendNotification();
   application.Render();
 
-  // Check that the focus is successfully to clear
-  DALI_TEST_CHECK(manager.GetCurrentFocusActor() == Actor());
+  // Since no focus has been moved, the current focus actor is the same.
+  DALI_TEST_CHECK(manager.GetCurrentFocusActor() == first);
 
   // Make the second actor focusableInTouchMode
   second.SetProperty(DevelActor::Property::TOUCH_FOCUSABLE, true);
@@ -2210,3 +2210,46 @@ int UtcDaliKeyboardFocusManagerChangeFocusDirectionByCustomWheelEvent(void)
 
   END_TEST;
 }
+
+int UtcDaliKeyboardFocusManagerWithUserInteractionEnabled(void)
+{
+  ToolkitTestApplication application;
+
+  tet_infoline(" UtcDaliKeyboardFocusManagerWithUserInteractionEnabled");
+
+  KeyboardFocusManager manager = KeyboardFocusManager::Get();
+  DALI_TEST_CHECK(manager);
+
+  // Create the first actor and add it to the stage
+  Actor first = Actor::New();
+  first.SetProperty(Actor::Property::KEYBOARD_FOCUSABLE, true);
+  application.GetScene().Add(first);
+
+  // Create the second actor and add it to the first actor.
+  Actor second = Actor::New();
+  second.SetProperty(Actor::Property::KEYBOARD_FOCUSABLE, true);
+  first.Add(second);
+
+  // Check that no actor is being focused yet.
+  DALI_TEST_CHECK(manager.GetCurrentFocusActor() == Actor());
+
+  // Check that the focus is set on the first actor
+  DALI_TEST_CHECK(manager.SetCurrentFocusActor(first) == true);
+  DALI_TEST_CHECK(manager.GetCurrentFocusActor() == first);
+
+  // Set USER_INTERACTION_ENABLED false.
+  second.SetProperty(DevelActor::Property::USER_INTERACTION_ENABLED, false);
+
+  // Check that it will fail to set focus on the second actor as it's not userInteractionEnabled
+  DALI_TEST_CHECK(manager.SetCurrentFocusActor(second) == false);
+  DALI_TEST_CHECK(manager.GetCurrentFocusActor() == first);
+
+  // Set KeyboardFocusableChildren true.
+  second.SetProperty(DevelActor::Property::USER_INTERACTION_ENABLED, true);
+
+  // Check that the focus is set on the second actor
+  DALI_TEST_CHECK(manager.SetCurrentFocusActor(second) == true);
+  DALI_TEST_CHECK(manager.GetCurrentFocusActor() == second);
+
+  END_TEST;
+}
\ No newline at end of file
index 19c3583..9db4289 100644 (file)
@@ -20,6 +20,8 @@
 #include <dali-toolkit/devel-api/controls/text-controls/text-editor-devel.h>
 #include <dali-toolkit/devel-api/text/rendering-backend.h>
 #include <dali-toolkit/devel-api/text/text-enumerations-devel.h>
+
+#include <dali/devel-api/actors/actor-devel.h>
 #include <dali/devel-api/adaptor-framework/clipboard.h>
 #include <dali/devel-api/adaptor-framework/key-devel.h>
 #include <dali/devel-api/text-abstraction/font-client.h>
@@ -3630,6 +3632,9 @@ int UtcDaliTextEditorEnableEditing(void)
   application.SendNotification();
   application.Render();
 
+  textEditor.SetProperty(DevelActor::Property::USER_INTERACTION_ENABLED, true);
+  DALI_TEST_EQUALS(textEditor.GetProperty(DevelActor::Property::USER_INTERACTION_ENABLED).Get<bool>(), true, TEST_LOCATION);
+
   textEditor.SetKeyInputFocus();
   textEditor.SetProperty(DevelTextEditor::Property::ENABLE_EDITING, false);
   application.ProcessEvent(GenerateKey("D", "", "D", KEY_D_CODE, 0, 0, Integration::KeyEvent::DOWN, "D", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE));
@@ -3652,6 +3657,24 @@ int UtcDaliTextEditorEnableEditing(void)
   DALI_TEST_EQUALS(textEditor.GetProperty(TextEditor::Property::TEXT).Get<std::string>(), "D", TEST_LOCATION);
   DALI_TEST_EQUALS(textEditor.GetProperty(DevelTextEditor::Property::ENABLE_EDITING).Get<bool>(), true, TEST_LOCATION);
 
+  // Check the user interaction enabled and for coverage
+  DevelTextEditor::SelectWholeText(textEditor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  textEditor.SetKeyInputFocus();
+  textEditor.SetProperty(DevelActor::Property::USER_INTERACTION_ENABLED, false);
+  application.ProcessEvent(GenerateKey("D", "", "D", KEY_D_CODE, 0, 0, Integration::KeyEvent::DOWN, "D", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE));
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS(textEditor.GetProperty(TextEditor::Property::TEXT).Get<std::string>(), "D", TEST_LOCATION);
+  DALI_TEST_EQUALS(textEditor.GetProperty(DevelActor::Property::USER_INTERACTION_ENABLED).Get<bool>(), false, TEST_LOCATION);
+
   END_TEST;
 }
 
@@ -5765,6 +5788,55 @@ int UtcDaliToolkitTextEditorUnderlineTypesGeneration3(void)
   END_TEST;
 }
 
+int UtcDaliToolkitTextEditorMarkupRelativeLineHeight(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliToolkitTextEditorMarkupRelativeLineHeight");
+
+  TextEditor editor = TextEditor::New();
+  editor.SetProperty(Actor::Property::SIZE, Vector2(200.0f, 300.f));
+  editor.SetProperty(TextEditor::Property::POINT_SIZE, 10);
+  editor.SetProperty(TextEditor::Property::TEXT, "line 1\nline 2\nline 3\nline 4\nline 5");
+  editor.SetProperty(DevelTextEditor::Property::RELATIVE_LINE_SIZE, 1.0f);
+  editor.SetProperty(DevelTextEditor::Property::ELLIPSIS, false);
+  editor.SetProperty(TextEditor::Property::ENABLE_MARKUP, true);
+
+  TextEditor editorSingleLineParagraph = TextEditor::New();
+  editorSingleLineParagraph.SetProperty(Actor::Property::SIZE, Vector2(200.0f, 300.f));
+  editorSingleLineParagraph.SetProperty(TextEditor::Property::POINT_SIZE, 10);
+  editorSingleLineParagraph.SetProperty(TextEditor::Property::TEXT, "<p>line 1</p><p rel-line-height=0.5>line 2</p>line 3<p rel-line-height=3>line 4</p>line 5");
+  editorSingleLineParagraph.SetProperty(DevelTextEditor::Property::RELATIVE_LINE_SIZE, 1.0f);
+  editorSingleLineParagraph.SetProperty(DevelTextEditor::Property::ELLIPSIS, false);
+  editorSingleLineParagraph.SetProperty(TextEditor::Property::ENABLE_MARKUP, true);
+
+  TextEditor editorMultiLineParagraph = TextEditor::New();
+  editorMultiLineParagraph.SetProperty(Actor::Property::SIZE, Vector2(200.0f, 300.f));
+  editorMultiLineParagraph.SetProperty(TextEditor::Property::POINT_SIZE, 10);
+  editorMultiLineParagraph.SetProperty(TextEditor::Property::TEXT, "<p>line 1</p><p rel-line-height=0.5>line\n2</p>line 3<p rel-line-height=3>line\n4</p>line 5");
+  editorMultiLineParagraph.SetProperty(DevelTextEditor::Property::RELATIVE_LINE_SIZE, 1.0f);
+  editorMultiLineParagraph.SetProperty(DevelTextEditor::Property::ELLIPSIS, false);
+  editorMultiLineParagraph.SetProperty(TextEditor::Property::ENABLE_MARKUP, true);
+
+  application.GetScene().Add(editor);
+  application.GetScene().Add(editorSingleLineParagraph);
+  application.GetScene().Add(editorMultiLineParagraph);
+  application.SendNotification();
+  application.Render();
+
+  Vector3 naturalSize               = editor.GetNaturalSize();
+  Vector3 relativeSingleNaturalSize = editorSingleLineParagraph.GetNaturalSize();
+  Vector3 relativeMultiNaturalSize  = editorMultiLineParagraph.GetNaturalSize();
+
+  float lineSize = naturalSize.y / 5.0f; //total size/number of lines
+
+  //no effect of relative line size for paragraph with single line
+  DALI_TEST_EQUALS(naturalSize.y, relativeSingleNaturalSize.y, Math::MACHINE_EPSILON_1000, TEST_LOCATION);
+
+  DALI_TEST_EQUALS(lineSize*8.5f, relativeMultiNaturalSize.y, Math::MACHINE_EPSILON_1000, TEST_LOCATION);
+
+  END_TEST;
+}
+
 int UtcDaliToolkitTextEditorRelativeLineHeight(void)
 {
   ToolkitTestApplication application;
@@ -5857,6 +5929,50 @@ int UtcDaliTextEditorTextSizeNegativeLineSpacing(void)
   END_TEST;
 }
 
+int UtcDaliTextEditorLineSpacingKeyArrowDown(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline("UtcDaliTextEditorLineSpacingKeyArrowDown");
+
+  TextEditor editor = TextEditor::New();
+  DALI_TEST_CHECK(editor);
+
+  application.GetScene().Add(editor);
+
+  std::string cutText    = "";
+  std::string copiedText = "";
+
+  editor.SetProperty(TextEditor::Property::TEXT, "l1\nl2\nl3\n4");
+  editor.SetProperty(TextEditor::Property::POINT_SIZE, 10.f);
+  editor.SetProperty(Actor::Property::SIZE, Vector2(300.f, 200.f));
+  editor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT);
+  editor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+  editor.SetProperty(TextEditor::Property::ENABLE_MARKUP, true);
+  editor.SetProperty(TextEditor::Property::LINE_SPACING, -15);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Tap on the text editor
+  TestGenerateTap(application, 1.0f, 1.0f);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Move to second line of the text.
+  application.ProcessEvent(GenerateKey("", "", "", DALI_KEY_CURSOR_DOWN, 0, 0, Integration::KeyEvent::DOWN, "", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE));
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS(editor.GetProperty(DevelTextEditor::Property::PRIMARY_CURSOR_POSITION).Get<int>(), 3, TEST_LOCATION);
+
+  END_TEST;
+}
+
 int UtcDaliTextEditorNegativeLineSpacingWithEllipsis(void)
 {
   ToolkitTestApplication application;
index 48c2bcc..b86f96b 100644 (file)
@@ -22,6 +22,7 @@
 #include <dali/integration-api/events/key-event-integ.h>
 #include <dali/integration-api/events/touch-event-integ.h>
 #include <dali/public-api/rendering/renderer.h>
+#include <dali/devel-api/actors/actor-devel.h>
 
 #include <dali-toolkit-test-suite-utils.h>
 #include <dali-toolkit/dali-toolkit.h>
@@ -3836,6 +3837,9 @@ int UtcDaliTextFieldEnableEditing(void)
   application.SendNotification();
   application.Render();
 
+  textField.SetProperty(DevelActor::Property::USER_INTERACTION_ENABLED, true);
+  DALI_TEST_EQUALS(textField.GetProperty(DevelActor::Property::USER_INTERACTION_ENABLED).Get<bool>(), true, TEST_LOCATION);
+
   textField.SetKeyInputFocus();
   textField.SetProperty(DevelTextField::Property::ENABLE_EDITING, false);
   application.ProcessEvent(GenerateKey("D", "", "D", KEY_D_CODE, 0, 0, Integration::KeyEvent::DOWN, "D", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE));
@@ -3858,6 +3862,24 @@ int UtcDaliTextFieldEnableEditing(void)
   DALI_TEST_EQUALS(textField.GetProperty(TextField::Property::TEXT).Get<std::string>(), "D", TEST_LOCATION);
   DALI_TEST_EQUALS(textField.GetProperty(DevelTextField::Property::ENABLE_EDITING).Get<bool>(), true, TEST_LOCATION);
 
+  // Check the user interaction enabled and for coverage
+  DevelTextField::SelectWholeText(textField);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  textField.SetKeyInputFocus();
+  textField.SetProperty(DevelActor::Property::USER_INTERACTION_ENABLED, false);
+  application.ProcessEvent(GenerateKey("D", "", "D", KEY_D_CODE, 0, 0, Integration::KeyEvent::DOWN, "D", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE));
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS(textField.GetProperty(TextField::Property::TEXT).Get<std::string>(), "D", TEST_LOCATION);
+  DALI_TEST_EQUALS(textField.GetProperty(DevelActor::Property::USER_INTERACTION_ENABLED).Get<bool>(), false, TEST_LOCATION);
+
   END_TEST;
 }
 
index bbd3d77..30aaade 100644 (file)
@@ -2632,6 +2632,58 @@ int UtcDaliToolkitTextLabelStrikethroughGeneration(void)
   END_TEST;
 }
 
+int UtcDaliToolkitTextLabelMarkupRelativeLineHeight(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliToolkitTextLabelMarkupRelativeLineHeight");
+
+  TextLabel label = TextLabel::New();
+  label.SetProperty(Actor::Property::SIZE, Vector2(200.0f, 300.f));
+  label.SetProperty(TextLabel::Property::POINT_SIZE, 10);
+  label.SetProperty(TextLabel::Property::MULTI_LINE, true);
+  label.SetProperty(TextLabel::Property::TEXT, "line 1\nline 2\nline 3\nline 4\nline 5");
+  label.SetProperty(DevelTextLabel::Property::RELATIVE_LINE_SIZE, 1.0f);
+  label.SetProperty(TextLabel::Property::ELLIPSIS, false);
+  label.SetProperty(TextLabel::Property::ENABLE_MARKUP, true);
+
+  TextLabel labelSingleLineParagraph = TextLabel::New();
+  labelSingleLineParagraph.SetProperty(Actor::Property::SIZE, Vector2(200.0f, 300.f));
+  labelSingleLineParagraph.SetProperty(TextLabel::Property::POINT_SIZE, 10);
+  labelSingleLineParagraph.SetProperty(TextLabel::Property::MULTI_LINE, true);
+  labelSingleLineParagraph.SetProperty(TextLabel::Property::TEXT, "<p>line 1</p><p rel-line-height=0.5>line 2</p>line 3<p rel-line-height=3>line 4</p>line 5");
+  labelSingleLineParagraph.SetProperty(DevelTextLabel::Property::RELATIVE_LINE_SIZE, 1.0f);
+  labelSingleLineParagraph.SetProperty(TextLabel::Property::ELLIPSIS, false);
+  labelSingleLineParagraph.SetProperty(TextLabel::Property::ENABLE_MARKUP, true);
+
+  TextLabel labelMultiLineParagraph = TextLabel::New();
+  labelMultiLineParagraph.SetProperty(Actor::Property::SIZE, Vector2(200.0f, 300.f));
+  labelMultiLineParagraph.SetProperty(TextLabel::Property::POINT_SIZE, 10);
+  labelMultiLineParagraph.SetProperty(TextLabel::Property::MULTI_LINE, true);
+  labelMultiLineParagraph.SetProperty(TextLabel::Property::TEXT, "<p>line 1</p><p rel-line-height=0.5>line\n2</p>line 3<p rel-line-height=3>line\n4</p>line 5");
+  labelMultiLineParagraph.SetProperty(DevelTextLabel::Property::RELATIVE_LINE_SIZE, 1.0f);
+  labelMultiLineParagraph.SetProperty(TextLabel::Property::ELLIPSIS, false);
+  labelMultiLineParagraph.SetProperty(TextLabel::Property::ENABLE_MARKUP, true);
+
+  application.GetScene().Add(label);
+  application.GetScene().Add(labelSingleLineParagraph);
+  application.GetScene().Add(labelMultiLineParagraph);
+  application.SendNotification();
+  application.Render();
+
+  Vector3 naturalSize               = label.GetNaturalSize();
+  Vector3 relativeSingleNaturalSize = labelSingleLineParagraph.GetNaturalSize();
+  Vector3 relativeMultiNaturalSize  = labelMultiLineParagraph.GetNaturalSize();
+
+  float lineSize = naturalSize.y / 5.0f; //total size/number of lines
+
+  //no effect of relative line size for paragraph with single line
+  DALI_TEST_EQUALS(naturalSize.y, relativeSingleNaturalSize.y, Math::MACHINE_EPSILON_1000, TEST_LOCATION);
+
+  DALI_TEST_EQUALS(lineSize*8.5f, relativeMultiNaturalSize.y, Math::MACHINE_EPSILON_1000, TEST_LOCATION);
+
+  END_TEST;
+}
+
 int UtcDaliToolkitTextLabelRelativeLineHeight(void)
 {
   ToolkitTestApplication application;
index 1ec67e2..f5bd6b9 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef DALI_SCENE_LOADER_GLTF2_ASSET_H_
 #define DALI_SCENE_LOADER_GLTF2_ASSET_H_
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * 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.
@@ -93,6 +93,7 @@ private:
 
 struct Asset
 {
+  std::string_view mGenerator;
   std::string_view mVersion;
 };
 
index 18923cf..923d0e4 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * 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.
@@ -43,6 +43,11 @@ const std::string ORIENTATION_PROPERTY("orientation");
 const std::string SCALE_PROPERTY("scale");
 const std::string BLEND_SHAPE_WEIGHTS_UNIFORM("uBlendShapeWeight");
 
+const std::string MRENDERER_MODEL_IDENTIFICATION("M-Renderer");
+
+const std::string ROOT_NODE_NAME("RootNode");
+const Vector3     SCALE_TO_ADJUST(100.0f, 100.0f, 100.0f);
+
 const Geometry::Type GLTF2_TO_DALI_PRIMITIVES[]{
   Geometry::POINTS,
   Geometry::LINES,
@@ -692,7 +697,7 @@ void ConvertCamera(const gt::Camera& camera, CameraParameters& camParams)
   }
 }
 
-void ConvertNode(gt::Node const& node, const Index gltfIdx, Index parentIdx, ConversionContext& cctx)
+void ConvertNode(gt::Node const& node, const Index gltfIdx, Index parentIdx, ConversionContext& cctx, bool isMRendererModel)
 {
   auto& output    = cctx.mOutput;
   auto& scene     = output.mScene;
@@ -715,6 +720,11 @@ void ConvertNode(gt::Node const& node, const Index gltfIdx, Index parentIdx, Con
       nodeDef->mPosition    = node.mTranslation;
       nodeDef->mOrientation = node.mRotation;
       nodeDef->mScale       = node.mScale;
+
+      if(isMRendererModel && node.mName == ROOT_NODE_NAME && node.mScale == SCALE_TO_ADJUST)
+      {
+        nodeDef->mScale *= 0.01f;
+      }
     }
 
     return nodeDef;
@@ -774,11 +784,11 @@ void ConvertNode(gt::Node const& node, const Index gltfIdx, Index parentIdx, Con
 
   for(auto& n : node.mChildren)
   {
-    ConvertNode(*n, n.GetIndex(), idx, cctx);
+    ConvertNode(*n, n.GetIndex(), idx, cctx, isMRendererModel);
   }
 }
 
-void ConvertSceneNodes(const gt::Scene& scene, ConversionContext& cctx)
+void ConvertSceneNodes(const gt::Scene& scene, ConversionContext& cctx, bool isMRendererModel)
 {
   auto& outScene = cctx.mOutput.mScene;
   Index rootIdx  = outScene.GetNodeCount();
@@ -788,7 +798,7 @@ void ConvertSceneNodes(const gt::Scene& scene, ConversionContext& cctx)
       break;
 
     case 1:
-      ConvertNode(*scene.mNodes[0], scene.mNodes[0].GetIndex(), INVALID_INDEX, cctx);
+      ConvertNode(*scene.mNodes[0], scene.mNodes[0].GetIndex(), INVALID_INDEX, cctx, isMRendererModel);
       outScene.AddRootNode(rootIdx);
       break;
 
@@ -802,25 +812,25 @@ void ConvertSceneNodes(const gt::Scene& scene, ConversionContext& cctx)
 
       for(auto& n : scene.mNodes)
       {
-        ConvertNode(*n, n.GetIndex(), rootIdx, cctx);
+        ConvertNode(*n, n.GetIndex(), rootIdx, cctx, isMRendererModel);
       }
       break;
     }
   }
 }
 
-void ConvertNodes(const gt::Document& doc, ConversionContext& cctx)
+void ConvertNodes(const gt::Document& doc, ConversionContext& cctx, bool isMRendererModel)
 {
-  ConvertSceneNodes(*doc.mScene, cctx);
+  ConvertSceneNodes(*doc.mScene, cctx, isMRendererModel);
 
   for(uint32_t i = 0, i1 = doc.mScene.GetIndex(); i < i1; ++i)
   {
-    ConvertSceneNodes(doc.mScenes[i], cctx);
+    ConvertSceneNodes(doc.mScenes[i], cctx, isMRendererModel);
   }
 
   for(uint32_t i = doc.mScene.GetIndex() + 1; i < doc.mScenes.size(); ++i)
   {
-    ConvertSceneNodes(doc.mScenes[i], cctx);
+    ConvertSceneNodes(doc.mScenes[i], cctx, isMRendererModel);
   }
 }
 
@@ -1155,10 +1165,23 @@ void LoadGltfScene(const std::string& url, ShaderDefinitionFactory& shaderFactor
 
   gt::Document doc;
 
-  auto& rootObj        = js::Cast<json_object_s>(*root);
-  auto  jsAsset        = js::FindObjectChild("asset", rootObj);
-  auto  jsAssetVersion = js::FindObjectChild("version", js::Cast<json_object_s>(*jsAsset));
-  doc.mAsset.mVersion  = js::Read::StringView(*jsAssetVersion);
+  auto& rootObj = js::Cast<json_object_s>(*root);
+  auto  jsAsset = js::FindObjectChild("asset", rootObj);
+
+  auto jsAssetVersion = js::FindObjectChild("version", js::Cast<json_object_s>(*jsAsset));
+  if(jsAssetVersion)
+  {
+    doc.mAsset.mVersion = js::Read::StringView(*jsAssetVersion);
+  }
+
+  bool isMRendererModel(false);
+  auto jsAssetGenerator = js::FindObjectChild("generator", js::Cast<json_object_s>(*jsAsset));
+  if(jsAssetGenerator)
+  {
+    doc.mAsset.mGenerator = js::Read::StringView(*jsAssetGenerator);
+    isMRendererModel      = (doc.mAsset.mGenerator.find(MRENDERER_MODEL_IDENTIFICATION) != std::string_view::npos);
+  }
+
 
   gt::SetRefReaderObject(doc);
   DOCUMENT_READER.Read(rootObj, doc);
@@ -1168,7 +1191,7 @@ void LoadGltfScene(const std::string& url, ShaderDefinitionFactory& shaderFactor
 
   ConvertMaterials(doc, cctx);
   ConvertMeshes(doc, cctx);
-  ConvertNodes(doc, cctx);
+  ConvertNodes(doc, cctx, isMRendererModel);
   ConvertAnimations(doc, cctx);
 
   ProcessSkins(doc, cctx);
index d338e39..2fdf285 100644 (file)
@@ -343,6 +343,7 @@ bool IsBetterCandidate(Toolkit::Control::KeyboardFocus::Direction direction, Rec
 bool IsFocusable(Actor& actor)\r
 {\r
   return (actor.GetProperty<bool>(Actor::Property::KEYBOARD_FOCUSABLE) &&\r
+          actor.GetProperty<bool>(DevelActor::Property::USER_INTERACTION_ENABLED) &&\r
           actor.GetProperty<bool>(Actor::Property::VISIBLE) &&\r
           actor.GetProperty<Vector4>(Actor::Property::WORLD_COLOR).a > FULLY_TRANSPARENT);\r
 }\r
index d6bae90..42153dc 100644 (file)
@@ -37,6 +37,7 @@
 #include <dali-toolkit/internal/controls/control/control-data-impl.h>
 #include <dali-toolkit/internal/controls/text-controls/common-text-utils.h>
 #include <dali-toolkit/internal/controls/text-controls/text-editor-property-handler.h>
+#include <dali-toolkit/internal/focus-manager/keyboard-focus-manager-impl.h>
 #include <dali-toolkit/internal/styling/style-manager-impl.h>
 #include <dali-toolkit/internal/text/rendering/text-backend.h>
 #include <dali-toolkit/internal/text/text-effects-style.h>
@@ -672,6 +673,31 @@ void TextEditor::ResizeActor(Actor& actor, const Vector2& size)
   }
 }
 
+void TextEditor::OnPropertySet(Property::Index index, const Property::Value& propertyValue)
+{
+  DALI_LOG_INFO(gTextEditorLogFilter, Debug::Verbose, "TextEditor::OnPropertySet index[%d]\n", index);
+
+  switch(index)
+  {
+    case DevelActor::Property::USER_INTERACTION_ENABLED:
+    {
+      const bool enabled = propertyValue.Get<bool>();
+      mController->SetUserInteractionEnabled(enabled);
+      if(mStencil)
+      {
+        float opacity = enabled ? 1.0f : mController->GetDisabledColorOpacity();
+        mStencil.SetProperty(Actor::Property::OPACITY, opacity);
+      }
+      break;
+    }
+    default:
+    {
+      Control::OnPropertySet(index, propertyValue); // up call to control for non-handled properties
+      break;
+    }
+  }
+}
+
 void TextEditor::OnRelayout(const Vector2& size, RelayoutContainer& container)
 {
   DALI_LOG_INFO(gTextEditorLogFilter, Debug::Verbose, "TextEditor OnRelayout\n");
@@ -810,7 +836,10 @@ void TextEditor::OnKeyInputFocusGained()
     notifier.ContentSelectedSignal().Connect(this, &TextEditor::OnClipboardTextSelected);
   }
 
-  mController->KeyboardFocusGainEvent(); // Called in the case of no virtual keyboard to trigger this event
+  if(IsEditable() && mController->IsUserInteractionEnabled())
+  {
+    mController->KeyboardFocusGainEvent(); // Called in the case of no virtual keyboard to trigger this event
+  }
 
   EmitKeyInputFocusSignal(true); // Calls back into the Control hence done last.
 }
@@ -862,6 +891,11 @@ void TextEditor::OnTap(const TapGesture& gesture)
   mController->TapEvent(gesture.GetNumberOfTaps(), localPoint.x - padding.start, localPoint.y - padding.top);
   mController->AnchorEvent(localPoint.x - padding.start, localPoint.y - padding.top);
 
+  Dali::Toolkit::KeyboardFocusManager keyboardFocusManager = Dali::Toolkit::KeyboardFocusManager::Get();
+  if (keyboardFocusManager)
+  {
+    keyboardFocusManager.SetCurrentFocusActor(Self());
+  }
   SetKeyInputFocus();
 }
 
@@ -893,6 +927,11 @@ bool TextEditor::OnKeyEvent(const KeyEvent& event)
     // Make sure ClearKeyInputFocus when only key is up
     if(event.GetState() == KeyEvent::UP)
     {
+      Dali::Toolkit::KeyboardFocusManager keyboardFocusManager = Dali::Toolkit::KeyboardFocusManager::Get();
+      if (keyboardFocusManager)
+      {
+        keyboardFocusManager.ClearFocus();
+      }
       ClearKeyInputFocus();
     }
 
index 5739ac2..c62988a 100644 (file)
@@ -221,6 +221,11 @@ private: // From Control
   void OnSceneConnection(int depth) override;
 
   /**
+   * @copydoc Control::OnPropertySet()
+   */
+  void OnPropertySet(Property::Index index, const Property::Value& propertyValue) override;
+
+  /**
    * @copydoc Dali::CustomActorImpl::OnKeyEvent(const KeyEvent&)
    */
   bool OnKeyEvent(const KeyEvent& event) override;
index 3cbd0b9..b7a6eb4 100644 (file)
@@ -36,6 +36,7 @@
 #include <dali-toolkit/devel-api/text/rendering-backend.h>
 #include <dali-toolkit/internal/controls/text-controls/common-text-utils.h>
 #include <dali-toolkit/internal/controls/text-controls/text-field-property-handler.h>
+#include <dali-toolkit/internal/focus-manager/keyboard-focus-manager-impl.h>
 #include <dali-toolkit/internal/styling/style-manager-impl.h>
 #include <dali-toolkit/internal/text/rendering/text-backend.h>
 #include <dali-toolkit/internal/text/text-effects-style.h>
@@ -607,6 +608,31 @@ void TextField::ResizeActor(Actor& actor, const Vector2& size)
   }
 }
 
+void TextField::OnPropertySet(Property::Index index, const Property::Value& propertyValue)
+{
+  DALI_LOG_INFO(gTextFieldLogFilter, Debug::Verbose, "TextField::OnPropertySet index[%d]\n", index);
+
+  switch(index)
+  {
+    case DevelActor::Property::USER_INTERACTION_ENABLED:
+    {
+      const bool enabled = propertyValue.Get<bool>();
+      mController->SetUserInteractionEnabled(enabled);
+      if(mStencil)
+      {
+        float opacity = enabled ? 1.0f : mController->GetDisabledColorOpacity();
+        mStencil.SetProperty(Actor::Property::OPACITY, opacity);
+      }
+      break;
+    }
+    default:
+    {
+      Control::OnPropertySet(index, propertyValue); // up call to control for non-handled properties
+      break;
+    }
+  }
+}
+
 void TextField::OnRelayout(const Vector2& size, RelayoutContainer& container)
 {
   DALI_LOG_INFO(gTextFieldLogFilter, Debug::Verbose, "TextField OnRelayout\n");
@@ -745,7 +771,10 @@ void TextField::OnKeyInputFocusGained()
     notifier.ContentSelectedSignal().Connect(this, &TextField::OnClipboardTextSelected);
   }
 
-  mController->KeyboardFocusGainEvent(); // Called in the case of no virtual keyboard to trigger this event
+  if(IsEditable() && mController->IsUserInteractionEnabled())
+  {
+    mController->KeyboardFocusGainEvent(); // Called in the case of no virtual keyboard to trigger this event
+  }
 
   EmitKeyInputFocusSignal(true); // Calls back into the Control hence done last.
 }
@@ -796,6 +825,11 @@ void TextField::OnTap(const TapGesture& gesture)
   mController->TapEvent(gesture.GetNumberOfTaps(), localPoint.x - padding.start, localPoint.y - padding.top);
   mController->AnchorEvent(localPoint.x - padding.start, localPoint.y - padding.top);
 
+  Dali::Toolkit::KeyboardFocusManager keyboardFocusManager = Dali::Toolkit::KeyboardFocusManager::Get();
+  if (keyboardFocusManager)
+  {
+    keyboardFocusManager.SetCurrentFocusActor(Self());
+  }
   SetKeyInputFocus();
 }
 
@@ -827,6 +861,11 @@ bool TextField::OnKeyEvent(const KeyEvent& event)
     // Make sure ClearKeyInputFocus when only key is up
     if(event.GetState() == KeyEvent::UP)
     {
+      Dali::Toolkit::KeyboardFocusManager keyboardFocusManager = Dali::Toolkit::KeyboardFocusManager::Get();
+      if (keyboardFocusManager)
+      {
+        keyboardFocusManager.ClearFocus();
+      }
       ClearKeyInputFocus();
     }
 
index d2d7fdf..6c4faa6 100644 (file)
@@ -212,6 +212,11 @@ private: // From Control
   void OnSceneConnection(int depth) override;
 
   /**
+   * @copydoc Control::OnPropertySet()
+   */
+  void OnPropertySet(Property::Index index, const Property::Value& propertyValue) override;
+
+  /**
    * @copydoc Dali::CustomActorImpl::OnKeyEvent(const KeyEvent&)
    */
   bool OnKeyEvent(const KeyEvent& event) override;
index d492a29..a64690e 100644 (file)
@@ -220,7 +220,7 @@ bool KeyboardFocusManager::DoSetCurrentFocusActor(Actor actor)
     }
   }
 
-  if(actor && actor.GetProperty<bool>(Actor::Property::KEYBOARD_FOCUSABLE) && actor.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
+  if(actor && actor.GetProperty<bool>(Actor::Property::KEYBOARD_FOCUSABLE) && actor.GetProperty<bool>(DevelActor::Property::USER_INTERACTION_ENABLED) && actor.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
   {
     Integration::SceneHolder currentWindow = Integration::SceneHolder::Get(actor);
 
@@ -244,7 +244,7 @@ bool KeyboardFocusManager::DoSetCurrentFocusActor(Actor actor)
   }
 
   // Check whether the actor is in the stage and is keyboard focusable.
-  if(actor && actor.GetProperty<bool>(Actor::Property::KEYBOARD_FOCUSABLE) && actor.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
+  if(actor && actor.GetProperty<bool>(Actor::Property::KEYBOARD_FOCUSABLE) && actor.GetProperty<bool>(DevelActor::Property::USER_INTERACTION_ENABLED) && actor.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
   {
     if((mIsFocusIndicatorShown == SHOW) && (mEnableFocusIndicator == ENABLE))
     {
@@ -552,7 +552,7 @@ bool KeyboardFocusManager::MoveFocus(Toolkit::Control::KeyboardFocus::Direction
       }
     }
 
-    if(nextFocusableActor && nextFocusableActor.GetProperty<bool>(Actor::Property::KEYBOARD_FOCUSABLE))
+    if(nextFocusableActor && nextFocusableActor.GetProperty<bool>(Actor::Property::KEYBOARD_FOCUSABLE) && nextFocusableActor.GetProperty<bool>(DevelActor::Property::USER_INTERACTION_ENABLED))
     {
       // Whether the next focusable actor is a layout control
       if(IsLayoutControl(nextFocusableActor))
@@ -578,7 +578,7 @@ bool KeyboardFocusManager::DoMoveFocusWithinLayoutControl(Toolkit::Control contr
   Actor nextFocusableActor = GetImplementation(control).GetNextKeyboardFocusableActor(actor, direction, mFocusGroupLoopEnabled);
   if(nextFocusableActor)
   {
-    if(!nextFocusableActor.GetProperty<bool>(Actor::Property::KEYBOARD_FOCUSABLE))
+    if(!(nextFocusableActor.GetProperty<bool>(Actor::Property::KEYBOARD_FOCUSABLE) || nextFocusableActor.GetProperty<bool>(DevelActor::Property::USER_INTERACTION_ENABLED)))
     {
       // If the actor is not focusable, ask the same layout control for the next actor to focus
       return DoMoveFocusWithinLayoutControl(control, nextFocusableActor, direction);
@@ -597,7 +597,7 @@ bool KeyboardFocusManager::DoMoveFocusWithinLayoutControl(Toolkit::Control contr
         mIsWaitingKeyboardFocusChangeCommit = false;
       }
 
-      if(committedFocusActor && committedFocusActor.GetProperty<bool>(Actor::Property::KEYBOARD_FOCUSABLE))
+      if(committedFocusActor && committedFocusActor.GetProperty<bool>(Actor::Property::KEYBOARD_FOCUSABLE) && committedFocusActor.GetProperty<bool>(DevelActor::Property::USER_INTERACTION_ENABLED))
       {
         // Whether the commited focusable actor is a layout control
         if(IsLayoutControl(committedFocusActor))
@@ -679,14 +679,10 @@ void KeyboardFocusManager::DoKeyboardEnter(Actor actor)
 
 void KeyboardFocusManager::ClearFocus()
 {
+  ClearFocusIndicator();
   Actor actor = GetCurrentFocusActor();
   if(actor)
   {
-    if(mFocusIndicatorActor)
-    {
-      actor.Remove(mFocusIndicatorActor);
-    }
-
     // Send notification for the change of focus actor
     if(!mFocusChangedSignal.Empty())
     {
@@ -700,8 +696,19 @@ void KeyboardFocusManager::ClearFocus()
       currentlyFocusedControl.ClearKeyInputFocus();
     }
   }
-
   mCurrentFocusActor.Reset();
+}
+
+void KeyboardFocusManager::ClearFocusIndicator()
+{
+  Actor actor = GetCurrentFocusActor();
+  if(actor)
+  {
+    if(mFocusIndicatorActor)
+    {
+      actor.Remove(mFocusIndicatorActor);
+    }
+  }
   mIsFocusIndicatorShown = (mAlwaysShowIndicator == ALWAYS_SHOW) ? SHOW : HIDE;
 }
 
@@ -1003,18 +1010,30 @@ void KeyboardFocusManager::OnTouch(const TouchEvent& touch)
   // We only do this on a Down event, otherwise the clear action may override a manually focused actor.
   if(((touch.GetPointCount() < 1) || (touch.GetState(0) == PointState::DOWN)))
   {
-    // If mClearFocusOnTouch is false, do not clear the focus even if user touch the screen.
-    if(mClearFocusOnTouch)
+    // If you touch the currently focused actor again, you don't need to do SetCurrentFocusActor again.
+    Actor hitActor = touch.GetHitActor(0);
+    if(hitActor && hitActor == GetCurrentFocusActor())
     {
-      ClearFocus();
+      return;
     }
-
     // If KEYBOARD_FOCUSABLE and TOUCH_FOCUSABLE is true, set focus actor
-    Actor hitActor = touch.GetHitActor(0);
     if(hitActor && hitActor.GetProperty<bool>(Actor::Property::KEYBOARD_FOCUSABLE) && hitActor.GetProperty<bool>(DevelActor::Property::TOUCH_FOCUSABLE))
     {
+      // If mClearFocusOnTouch is false, do not clear the focus
+      if(mClearFocusOnTouch)
+      {
+        ClearFocus();
+      }
       SetCurrentFocusActor(hitActor);
     }
+    else
+    {
+      // If mClearFocusOnTouch is false, do not clear the focus indicator even if user touch the screen.
+      if(mClearFocusOnTouch)
+      {
+        ClearFocusIndicator();
+      }
+    }
   }
 }
 
index 3b09623..ae06097 100644 (file)
@@ -323,6 +323,11 @@ private:
    */
   bool EmitCustomWheelSignals(Actor actor, const WheelEvent& event);
 
+  /**
+   * Clear the focus indicator actor.
+   */
+  void ClearFocusIndicator();
+
 private:
   // Undefined
   KeyboardFocusManager(const KeyboardFocusManager&);
index ec15ff4..4b3150e 100644 (file)
@@ -48,13 +48,17 @@ struct BoundedParagraphRun
   BoundedParagraphRun()
   : characterRun{},
     horizontalAlignment(Text::HorizontalAlignment::BEGIN),
-    horizontalAlignmentDefined{false}
+    relativeLineSize(1),
+    horizontalAlignmentDefined{false},
+    relativeLineSizeDefined(false)
   {
   }
 
   CharacterRun                    characterRun;                   ///< The initial character index within the whole text and the number of characters of the run.
   Text::HorizontalAlignment::Type horizontalAlignment;            ///< The paragraph horizontal alignment. Values "BEGIN" "CENTER" "END".
+  float                           relativeLineSize;               ///< The relative line height to be used for this paragaraph.
   bool                            horizontalAlignmentDefined : 1; ///< Whether the horizontal alignment is defined.
+  bool                            relativeLineSizeDefined : 1;    ///< Whether the relative line height is defined for this paragraph.
 };
 
 } // namespace Text
index f4d2ca4..d89adf9 100644 (file)
@@ -2109,6 +2109,27 @@ int Decorator::GetCursorWidth() const
 void Decorator::SetEditable(bool editable)
 {
   mImpl->mHidePrimaryCursorAndGrabHandle = !editable;
+  // If editable is false, all decorators should be disabled.
+  if(!editable)
+  {
+    if(IsHighlightActive())
+    {
+      SetHighlightActive(false);
+    }
+    if(IsHandleActive(LEFT_SELECTION_HANDLE))
+    {
+      SetHandleActive(LEFT_SELECTION_HANDLE, false);
+    }
+    if(IsHandleActive(RIGHT_SELECTION_HANDLE))
+    {
+      SetHandleActive(RIGHT_SELECTION_HANDLE, false);
+    }
+    if(IsPopupActive())
+    {
+      SetPopupActive(false);
+    }
+  }
+
   mImpl->Relayout(mImpl->mControlSize);
 }
 /** Handles **/
index 3fcc82c..41e41a9 100644 (file)
@@ -97,7 +97,8 @@ struct LineLayout
     glyphIndexInSecondHalfLine{0u},
     characterIndexInSecondHalfLine{0u},
     numberOfGlyphsInSecondHalfLine{0u},
-    numberOfCharactersInSecondHalfLine{0u}
+    numberOfCharactersInSecondHalfLine{0u},
+    relativeLineSize{1.0f}
 
   {
   }
@@ -120,6 +121,7 @@ struct LineLayout
     characterIndexInSecondHalfLine     = 0u;
     numberOfGlyphsInSecondHalfLine     = 0u;
     numberOfCharactersInSecondHalfLine = 0u;
+    relativeLineSize                   = 1.0f;
   }
 
   GlyphIndex         glyphIndex;                ///< Index of the first glyph to be laid-out.
@@ -140,6 +142,8 @@ struct LineLayout
   CharacterIndex characterIndexInSecondHalfLine;     ///< Index of the first character to be laid-out for the second half of line.
   Length         numberOfGlyphsInSecondHalfLine;     ///< The number of glyph which fit in one line for the second half of line.
   Length         numberOfCharactersInSecondHalfLine; ///< The number of characters which fit in one line for the second half of line.
+
+  float relativeLineSize; ///< The relative line size to be applied for this line.
 };
 
 struct LayoutBidiParameters
@@ -173,9 +177,10 @@ struct Engine::Impl
    * @brief get the line spacing.
    *
    * @param[in] textSize The text size.
+   * @param[in] relativeLineSize The relative line size to be applied.
    * @return the line spacing value.
    */
-  float GetLineSpacing(float textSize)
+  float GetLineSpacing(float textSize, float relativeLineSize)
   {
     float lineSpacing;
     float relTextSize;
@@ -188,10 +193,10 @@ struct Engine::Impl
     lineSpacing += mDefaultLineSpacing;
 
     //subtract line spcaing if relativeLineSize < 1 & larger than min height
-    relTextSize = textSize * mRelativeLineSize;
+    relTextSize = textSize * relativeLineSize;
     if(relTextSize > mDefaultLineSize)
     {
-      if(mRelativeLineSize < 1)
+      if(relativeLineSize < 1)
       {
         //subtract the difference (always will be positive)
         lineSpacing -= (textSize - relTextSize);
@@ -240,7 +245,7 @@ struct Engine::Impl
     // Sets the minimum descender.
     lineLayout.descender = std::min(lineLayout.descender, fontMetrics.descender);
 
-    lineLayout.lineSpacing = GetLineSpacing(lineLayout.ascender + -lineLayout.descender);
+    lineLayout.lineSpacing = GetLineSpacing(lineLayout.ascender + -lineLayout.descender, lineLayout.relativeLineSize);
   }
 
   /**
@@ -740,6 +745,8 @@ struct Engine::Impl
     // It needs to add as well space for the cursor if the text is in edit mode and extra space in case the text is outlined.
     tmpLineLayout.penX = -glyphMetrics.xBearing + mCursorWidth + outlineWidth;
 
+    tmpLineLayout.relativeLineSize = lineLayout.relativeLineSize;
+
     // Calculate the line height if there is no characters.
     FontId lastFontId = glyphMetrics.fontId;
     UpdateLineHeight(glyphMetrics, tmpLineLayout);
@@ -1268,6 +1275,9 @@ struct Engine::Impl
 
       LineRun*   lineRun = nullptr;
       LineLayout ellipsisLayout;
+
+      ellipsisLayout.relativeLineSize = layout.relativeLineSize;
+
       if(0u != numberOfLines)
       {
         // Get the last line and layout it again with the 'completelyFill' flag to true.
@@ -1424,7 +1434,7 @@ struct Engine::Impl
     lineRun.direction = layout.direction;
     lineRun.ellipsis  = false;
 
-    lineRun.lineSpacing = GetLineSpacing(lineRun.ascender + -lineRun.descender);
+    lineRun.lineSpacing = GetLineSpacing(lineRun.ascender + -lineRun.descender, layout.relativeLineSize);
 
     // Update the actual size.
     if(lineRun.width > layoutSize.width)
@@ -1478,7 +1488,11 @@ struct Engine::Impl
     lineRun.direction                       = LTR;
     lineRun.ellipsis                        = false;
 
-    lineRun.lineSpacing = GetLineSpacing(lineRun.ascender + -lineRun.descender);
+    BoundedParagraphRun currentParagraphRun;
+    LineLayout          tempLineLayout;
+    (GetBoundedParagraph(layoutParameters.textModel->GetBoundedParagraphRuns(), characterIndex, currentParagraphRun) ? SetRelativeLineSize(&currentParagraphRun, tempLineLayout) : SetRelativeLineSize(nullptr, tempLineLayout));
+
+    lineRun.lineSpacing = GetLineSpacing(lineRun.ascender + -lineRun.descender, tempLineLayout.relativeLineSize);
 
     layoutSize.height += GetLineHeight(lineRun, true);
   }
@@ -1538,6 +1552,51 @@ struct Engine::Impl
     }
   }
 
+  /**
+   * @brief Sets the relative line size for the LineLayout
+   *
+   * @param[in] currentParagraphRun Contains the bounded paragraph for this line layout.
+   * @param[in,out] lineLayout The line layout to be updated.
+   */
+  void SetRelativeLineSize(BoundedParagraphRun* currentParagraphRun, LineLayout& lineLayout)
+  {
+    lineLayout.relativeLineSize = mRelativeLineSize;
+
+    if(currentParagraphRun != nullptr && currentParagraphRun->relativeLineSizeDefined)
+    {
+      lineLayout.relativeLineSize = currentParagraphRun->relativeLineSize;
+    }
+  }
+
+  /**
+   * @brief Get the bounded paragraph for the characterIndex if exists.
+   *
+   * @param[in] boundedParagraphRuns The bounded paragraph list to search in.
+   * @param[in] characterIndex The character index to get bounded paragraph for.
+   * @param[out] currentParagraphRun Contains the bounded paragraph if found for the characterIndex.
+   *
+   * @return returns true if a bounded paragraph was found.
+   */
+  bool GetBoundedParagraph(const Vector<BoundedParagraphRun> boundedParagraphRuns, CharacterIndex characterIndex, BoundedParagraphRun& currentParagraphRun)
+  {
+    for(Vector<BoundedParagraphRun>::Iterator it    = boundedParagraphRuns.Begin(),
+                                              endIt = boundedParagraphRuns.End();
+        it != endIt;
+        ++it)
+    {
+      BoundedParagraphRun& tempParagraphRun = *it;
+
+      if(characterIndex >= tempParagraphRun.characterRun.characterIndex &&
+         characterIndex < (tempParagraphRun.characterRun.characterIndex + tempParagraphRun.characterRun.numberOfCharacters))
+      {
+        currentParagraphRun = tempParagraphRun;
+        return true;
+      }
+    }
+
+    return false;
+  }
+
   bool LayoutText(Parameters&                       layoutParameters,
                   Size&                             layoutSize,
                   bool                              elideTextEnabled,
@@ -1556,7 +1615,8 @@ struct Engine::Impl
     layoutParameters.textModel->mVisualModel->SetFirstMiddleIndexOfElidedGlyphs(0u);
     layoutParameters.textModel->mVisualModel->SetSecondMiddleIndexOfElidedGlyphs(0u);
 
-    Vector<LineRun>& lines = layoutParameters.textModel->mVisualModel->mLines;
+    Vector<LineRun>&                   lines                = layoutParameters.textModel->mVisualModel->mLines;
+    const Vector<BoundedParagraphRun>& boundedParagraphRuns = layoutParameters.textModel->GetBoundedParagraphRuns();
 
     if(0u == layoutParameters.numberOfGlyphs)
     {
@@ -1616,7 +1676,7 @@ struct Engine::Impl
     // Retrieve BiDi info.
     const bool hasBidiParagraphs = !layoutParameters.textModel->mLogicalModel->mBidirectionalParagraphInfo.Empty();
 
-    const CharacterIndex* const                  glyphsToCharactersBuffer    = hasBidiParagraphs ? layoutParameters.textModel->mVisualModel->mGlyphsToCharacters.Begin() : nullptr;
+    const CharacterIndex* const                  glyphsToCharactersBuffer    = layoutParameters.textModel->mVisualModel->mGlyphsToCharacters.Begin();
     const Vector<BidirectionalParagraphInfoRun>& bidirectionalParagraphsInfo = layoutParameters.textModel->mLogicalModel->mBidirectionalParagraphInfo;
     const Vector<BidirectionalLineInfoRun>&      bidirectionalLinesInfo      = layoutParameters.textModel->mLogicalModel->mBidirectionalLineInfo;
 
@@ -1720,6 +1780,10 @@ struct Engine::Impl
       LineLayout layout;
       layout.direction  = layoutBidiParameters.paragraphDirection;
       layout.glyphIndex = index;
+
+      BoundedParagraphRun currentParagraphRun;
+      (GetBoundedParagraph(boundedParagraphRuns, *(glyphsToCharactersBuffer + index), currentParagraphRun) ? SetRelativeLineSize(&currentParagraphRun, layout) : SetRelativeLineSize(nullptr, layout));
+
       GetLineLayoutForBox(layoutParameters,
                           layoutBidiParameters,
                           layout,
@@ -1734,6 +1798,14 @@ struct Engine::Impl
       DALI_LOG_INFO(gLogFilter, Debug::Verbose, "  number of characters %d\n", layout.numberOfCharacters);
       DALI_LOG_INFO(gLogFilter, Debug::Verbose, "                length %f\n", layout.length);
 
+      CharacterIndex lastCharacterInParagraph = currentParagraphRun.characterRun.characterIndex + currentParagraphRun.characterRun.numberOfCharacters - 1;
+
+      //check if this is the last line in paragraph, if false we should use the default relative line size (the one set using the property)
+      if(lastCharacterInParagraph >= layout.characterIndex && lastCharacterInParagraph < layout.characterIndex+layout.numberOfCharacters)
+      {
+        layout.relativeLineSize = mRelativeLineSize;
+      }
+
       if(0u == layout.numberOfGlyphs + layout.numberOfGlyphsInSecondHalfLine)
       {
         // The width is too small and no characters are laid-out.
@@ -1877,7 +1949,7 @@ struct Engine::Impl
         }
 
         // Updates the vertical pen's position.
-        penY += -layout.descender + layout.lineSpacing + GetLineSpacing(layout.ascender + -layout.descender);
+        penY += -layout.descender + layout.lineSpacing + GetLineSpacing(layout.ascender + -layout.descender, layout.relativeLineSize);
 
         // Increase the glyph index.
         index = nextIndex;
index 4c4bb29..771ff4e 100644 (file)
@@ -25,6 +25,7 @@
 // INTERNAL INCLUDES
 #include <dali-toolkit/internal/text/anchor.h>
 #include <dali-toolkit/internal/text/markup-processor-helper-functions.h>
+#include <dali-toolkit/internal/text/markup-tags-and-attributes.h>
 
 namespace Dali
 {
@@ -32,18 +33,13 @@ namespace Toolkit
 {
 namespace Text
 {
-namespace
-{
-const std::string XHTML_HREF_ATTRIBUTE("href");
-} // namespace
-
 void ProcessAnchor(const Tag& tag, Anchor& anchor)
 {
   anchor.href = nullptr;
 
   for(auto&& attribute : tag.attributes)
   {
-    if(TokenComparison(XHTML_HREF_ATTRIBUTE, attribute.nameBuffer, attribute.nameLength))
+    if(TokenComparison(MARKUP::ANCHOR_ATTRIBUTES::HREF, attribute.nameBuffer, attribute.nameLength))
     {
       Length hrefLength = attribute.valueLength + 1;
       anchor.href       = new char[hrefLength];
index 8a9910e..7f0e8ae 100644 (file)
@@ -25,6 +25,7 @@
 // INTERNAL INCLUDES
 #include <dali-toolkit/internal/text/color-run.h>
 #include <dali-toolkit/internal/text/markup-processor-helper-functions.h>
+#include <dali-toolkit/internal/text/markup-tags-and-attributes.h>
 
 namespace Dali
 {
@@ -32,16 +33,11 @@ namespace Toolkit
 {
 namespace Text
 {
-namespace
-{
-const std::string XHTML_COLOR_ATTRIBUTE("color");
-} // namespace
-
 void ProcessBackground(const Tag& tag, ColorRun& colorRun)
 {
   for(auto&& attribute : tag.attributes)
   {
-    if(TokenComparison(XHTML_COLOR_ATTRIBUTE, attribute.nameBuffer, attribute.nameLength))
+    if(TokenComparison(MARKUP::BACKGROUND_ATTRIBUTES::COLOR, attribute.nameBuffer, attribute.nameLength))
     {
       ColorStringToVector4(attribute.valueBuffer, attribute.valueLength, colorRun.color);
     }
index f0ef362..cce30dd 100644 (file)
@@ -25,6 +25,7 @@
 #include <dali-toolkit/internal/text/character-spacing-character-run.h>
 #include <dali-toolkit/internal/text/markup-processor-attribute-helper-functions.h>
 #include <dali-toolkit/internal/text/markup-processor-helper-functions.h>
+#include <dali-toolkit/internal/text/markup-tags-and-attributes.h>
 
 namespace Dali
 {
@@ -32,12 +33,6 @@ namespace Toolkit
 {
 namespace Text
 {
-namespace
-{
-const std::string XHTML_VALUE_ATTRIBUTE("value");
-
-} // namespace
-
 void ProcessValueAttribute(const Attribute& attribute, CharacterSpacingCharacterRun& characterSpacingCharacterRun)
 {
   characterSpacingCharacterRun.value = ProcessFloatAttribute(attribute);
@@ -52,7 +47,7 @@ void ProcessCharacterSpacingTag(const Tag& tag, CharacterSpacingCharacterRun& ch
   {
     const Attribute& attribute(*it);
 
-    if(TokenComparison(XHTML_VALUE_ATTRIBUTE, attribute.nameBuffer, attribute.nameLength))
+    if(TokenComparison(MARKUP::CHARACTER_SPACING_ATTRIBUTES::VALUE, attribute.nameBuffer, attribute.nameLength))
     {
       ProcessValueAttribute(attribute, characterSpacingCharacterRun);
     }
index d5fce04..4fb95ef 100644 (file)
@@ -24,6 +24,7 @@
 // INTERNAL INCLUDES
 #include <dali-toolkit/internal/text/color-run.h>
 #include <dali-toolkit/internal/text/markup-processor-helper-functions.h>
+#include <dali-toolkit/internal/text/markup-tags-and-attributes.h>
 
 namespace Dali
 {
@@ -31,11 +32,6 @@ namespace Toolkit
 {
 namespace Text
 {
-namespace
-{
-const std::string XHTML_VALUE_ATTRIBUTE("value");
-}
-
 void ProcessColor(const Attribute& attribute, ColorRun& colorRun)
 {
   ColorStringToVector4(attribute.valueBuffer, attribute.valueLength, colorRun.color);
@@ -49,7 +45,7 @@ void ProcessColorTag(const Tag& tag, ColorRun& colorRun)
       ++it)
   {
     const Attribute& attribute(*it);
-    if(TokenComparison(XHTML_VALUE_ATTRIBUTE, attribute.nameBuffer, attribute.nameLength))
+    if(TokenComparison(MARKUP::COLOR_ATTRIBUTES::VALUE, attribute.nameBuffer, attribute.nameLength))
     {
       ProcessColor(attribute, colorRun);
     }
index 1bfa3f4..94d6fd4 100644 (file)
@@ -25,6 +25,7 @@
 // INTERNAL INCLUDES
 #include <dali-toolkit/internal/text/embedded-item.h>
 #include <dali-toolkit/internal/text/markup-processor-helper-functions.h>
+#include <dali-toolkit/internal/text/markup-tags-and-attributes.h>
 
 namespace Dali
 {
@@ -34,11 +35,6 @@ namespace Text
 {
 namespace
 {
-const std::string XHTML_URL_ATTRIBUTE("url");
-const std::string XHTML_WIDTH_ATTRIBUTE("width");
-const std::string XHTML_HEIGHT_ATTRIBUTE("height");
-const std::string XHTML_COLOR_BLENDING_ATTRIBUTE("color-blending");
-
 const std::string NONE("none");
 const std::string MULTIPLY("multiply");
 } // namespace
@@ -57,22 +53,22 @@ void ProcessEmbeddedItem(const Tag& tag, EmbeddedItem& embeddedItem)
       ++it)
   {
     const Attribute& attribute(*it);
-    if(TokenComparison(XHTML_URL_ATTRIBUTE, attribute.nameBuffer, attribute.nameLength))
+    if(TokenComparison(MARKUP::EMBEDDED_ITEM_ATTRIBUTES::URL, attribute.nameBuffer, attribute.nameLength))
     {
       embeddedItem.urlLength = attribute.valueLength;
       embeddedItem.url       = new char[embeddedItem.urlLength];
       memcpy(embeddedItem.url, attribute.valueBuffer, embeddedItem.urlLength);
       // The memory is freed when the font run is removed from the logical model.
     }
-    else if(TokenComparison(XHTML_WIDTH_ATTRIBUTE, attribute.nameBuffer, attribute.nameLength))
+    else if(TokenComparison(MARKUP::EMBEDDED_ITEM_ATTRIBUTES::WIDTH, attribute.nameBuffer, attribute.nameLength))
     {
       embeddedItem.width = StringToUint(attribute.valueBuffer);
     }
-    else if(TokenComparison(XHTML_HEIGHT_ATTRIBUTE, attribute.nameBuffer, attribute.nameLength))
+    else if(TokenComparison(MARKUP::EMBEDDED_ITEM_ATTRIBUTES::HEIGHT, attribute.nameBuffer, attribute.nameLength))
     {
       embeddedItem.height = StringToUint(attribute.valueBuffer);
     }
-    else if(TokenComparison(XHTML_COLOR_BLENDING_ATTRIBUTE, attribute.nameBuffer, attribute.nameLength))
+    else if(TokenComparison(MARKUP::EMBEDDED_ITEM_ATTRIBUTES::COLOR_BLENDING, attribute.nameBuffer, attribute.nameLength))
     {
       if(TokenComparison(MULTIPLY, attribute.valueBuffer, attribute.valueLength))
       {
index 0c469b8..802f9e9 100644 (file)
@@ -26,6 +26,7 @@
 #include <dali-toolkit/internal/text/font-description-run.h>
 #include <dali-toolkit/internal/text/markup-processor-attribute-helper-functions.h>
 #include <dali-toolkit/internal/text/markup-processor-helper-functions.h>
+#include <dali-toolkit/internal/text/markup-tags-and-attributes.h>
 #include <dali-toolkit/internal/text/text-font-style.h>
 
 namespace Dali
@@ -36,12 +37,6 @@ namespace Text
 {
 namespace
 {
-const std::string XHTML_FAMILY_ATTRIBUTE("family");
-const std::string XHTML_SIZE_ATTRIBUTE("size");
-const std::string XHTML_WEIGHT_ATTRIBUTE("weight");
-const std::string XHTML_WIDTH_ATTRIBUTE("width");
-const std::string XHTML_SLANT_ATTRIBUTE("slant");
-
 const std::string  FONT_PREFIX("font-");
 const unsigned int FONT_PREFIX_LENGTH      = 5u;
 const unsigned int MIN_FONT_ATTRIBUTE_SIZE = 4u;   ///< The minimum length of any of the possible 'weight', 'width' , 'slant' or 'size' values.
@@ -97,23 +92,23 @@ void ProcessFontTag(const Tag& tag, FontDescriptionRun& fontRun)
   {
     const Attribute& attribute(*it);
 
-    if(TokenComparison(XHTML_FAMILY_ATTRIBUTE, attribute.nameBuffer, attribute.nameLength))
+    if(TokenComparison(MARKUP::FONT_ATTRIBUTES::FAMILY, attribute.nameBuffer, attribute.nameLength))
     {
       ProcessFontFamily(attribute, fontRun);
     }
-    else if(TokenComparison(XHTML_SIZE_ATTRIBUTE, attribute.nameBuffer, attribute.nameLength))
+    else if(TokenComparison(MARKUP::FONT_ATTRIBUTES::SIZE, attribute.nameBuffer, attribute.nameLength))
     {
       ProcessFontSize(attribute, fontRun);
     }
-    else if(TokenComparison(XHTML_WEIGHT_ATTRIBUTE, attribute.nameBuffer, attribute.nameLength))
+    else if(TokenComparison(MARKUP::FONT_ATTRIBUTES::WEIGHT, attribute.nameBuffer, attribute.nameLength))
     {
       ProcessFontWeight(attribute, fontRun);
     }
-    else if(TokenComparison(XHTML_WIDTH_ATTRIBUTE, attribute.nameBuffer, attribute.nameLength))
+    else if(TokenComparison(MARKUP::FONT_ATTRIBUTES::WIDTH, attribute.nameBuffer, attribute.nameLength))
     {
       ProcessFontWidth(attribute, fontRun);
     }
-    else if(TokenComparison(XHTML_SLANT_ATTRIBUTE, attribute.nameBuffer, attribute.nameLength))
+    else if(TokenComparison(MARKUP::FONT_ATTRIBUTES::SLANT, attribute.nameBuffer, attribute.nameLength))
     {
       ProcessFontSlant(attribute, fontRun);
     }
index 35a1cc5..e470bec 100644 (file)
@@ -24,6 +24,7 @@
 // INTERNAL INCLUDES
 #include <dali-toolkit/internal/text/bounded-paragraph-run.h>
 #include <dali-toolkit/internal/text/markup-processor-helper-functions.h>
+#include <dali-toolkit/internal/text/markup-tags-and-attributes.h>
 
 namespace Dali
 {
@@ -31,11 +32,6 @@ namespace Toolkit
 {
 namespace Text
 {
-namespace
-{
-const std::string XHTML_ALIGN_ATTRIBUTE("align");
-}
-
 void ProcessHorizontalAlignment(const Attribute& attribute, BoundedParagraphRun& boundedParagraphRun)
 {
   boundedParagraphRun.horizontalAlignmentDefined = HorizontalAlignmentTypeStringToTypeValue(attribute.valueBuffer,
@@ -43,6 +39,12 @@ void ProcessHorizontalAlignment(const Attribute& attribute, BoundedParagraphRun&
                                                                                             boundedParagraphRun.horizontalAlignment);
 }
 
+void ProcessRelativeLineHeight(const Attribute& attribute, BoundedParagraphRun& boundedParagraphRun)
+{
+  boundedParagraphRun.relativeLineSize        = StringToFloat(attribute.valueBuffer);
+  boundedParagraphRun.relativeLineSizeDefined = true;
+}
+
 void ProcessAttributesOfParagraphTag(const Tag& tag, BoundedParagraphRun& boundedParagraphRun)
 {
   // By default the align attribute is not defined until it's parsed.
@@ -54,13 +56,16 @@ void ProcessAttributesOfParagraphTag(const Tag& tag, BoundedParagraphRun& bounde
       ++it)
   {
     const Attribute& attribute(*it);
-    if(TokenComparison(XHTML_ALIGN_ATTRIBUTE, attribute.nameBuffer, attribute.nameLength))
+    if(TokenComparison(MARKUP::PARAGRAPH_ATTRIBUTES::ALIGN, attribute.nameBuffer, attribute.nameLength))
     {
       ProcessHorizontalAlignment(attribute, boundedParagraphRun);
     }
+    else if(TokenComparison(MARKUP::PARAGRAPH_ATTRIBUTES::RELATIVE_LINE_HEIGHT, attribute.nameBuffer, attribute.nameLength))
+    {
+      ProcessRelativeLineHeight(attribute, boundedParagraphRun);
+    }
   }
 }
-
 } // namespace Text
 
 } // namespace Toolkit
index 484b3a5..2859794 100644 (file)
@@ -44,6 +44,14 @@ void ProcessHorizontalAlignment(const Attribute& attribute, BoundedParagraphRun&
  */
 void ProcessAttributesOfParagraphTag(const Tag& tag, BoundedParagraphRun& boundedParagraphRun);
 
+/**
+ * @brief Retrieves the relative line height value from the paragraph tag and sets it to the bounded paragraph run.
+ *
+ * @param[in] attribute the relative line height attribute.
+ * @param[in,out] boundedParagraphRun The bounded paragraph run.
+ */
+void ProcessRelativeLineHeight(const Attribute& attribute, BoundedParagraphRun& boundedParagraphRun);
+
 } // namespace Text
 
 } // namespace Toolkit
index 19810ee..3e20c6f 100644 (file)
@@ -29,6 +29,7 @@
 #include <dali-toolkit/internal/text/markup-processor-helper-functions.h>
 #include <dali-toolkit/internal/text/markup-processor-strikethrough.h>
 #include <dali-toolkit/internal/text/markup-processor-underline.h>
+#include <dali-toolkit/internal/text/markup-tags-and-attributes.h>
 
 namespace Dali
 {
@@ -36,35 +37,6 @@ namespace Toolkit
 {
 namespace Text
 {
-namespace
-{
-const std::string XHTML_FAMILY_ATTRIBUTE("font-family");
-const std::string XHTML_SIZE_ATTRIBUTE("font-size");
-const std::string XHTML_WEIGHT_ATTRIBUTE("font-weight");
-const std::string XHTML_WIDTH_ATTRIBUTE("font-width");
-const std::string XHTML_SLANT_ATTRIBUTE("font-slant");
-
-const std::string XHTML_COLOR_ATTRIBUTE("text-color");
-const std::string XHTML_BACKGROUND_COLOR_ATTRIBUTE("background-color");
-
-//the underlined character's attributes
-const std::string XHTML_UNDERLINE_COLOR_ATTRIBUTE("u-color");
-const std::string XHTML_UNDERLINE_HEIGHT_ATTRIBUTE("u-height");
-const std::string XHTML_UNDERLINE_TYPE_ATTRIBUTE("u-type");
-const std::string XHTML_UNDERLINE_DASH_GAP_ATTRIBUTE("u-dash-gap");
-const std::string XHTML_UNDERLINE_DASH_WIDTH_ATTRIBUTE("u-dash-width");
-
-//the strikethroughed character's attributes
-const std::string XHTML_STRIKETHROUGH_COLOR_ATTRIBUTE("s-color");
-const std::string XHTML_STRIKETHROUGH_HEIGHT_ATTRIBUTE("s-height");
-
-//the character-spacing character's attributes
-const std::string XHTML_CHARACTER_SPACING_VALUE_ATTRIBUTE("char-space-value");
-
-//NOTE: the MAX_NUM_OF_ATTRIBUTES in "markup-processor.cpp" should be updated when add a new attribute for span tag.
-
-} // namespace
-
 void ProcessSpanTag(const Tag&                    tag,
                     ColorRun&                     colorRun,
                     FontDescriptionRun&           fontRun,
@@ -86,77 +58,77 @@ void ProcessSpanTag(const Tag&                    tag,
   {
     const Attribute& attribute(*it);
 
-    if(TokenComparison(XHTML_COLOR_ATTRIBUTE, attribute.nameBuffer, attribute.nameLength))
+    if(TokenComparison(MARKUP::SPAN_ATTRIBUTES::TEXT_COLOR, attribute.nameBuffer, attribute.nameLength))
     {
       isColorDefined = true;
       ProcessColor(attribute, colorRun);
     }
-    else if(TokenComparison(XHTML_BACKGROUND_COLOR_ATTRIBUTE, attribute.nameBuffer, attribute.nameLength))
+    else if(TokenComparison(MARKUP::SPAN_ATTRIBUTES::BACKGROUND_COLOR, attribute.nameBuffer, attribute.nameLength))
     {
       isBackgroundColorDefined = true;
       ProcessColor(attribute, backgroundColorRun);
     }
-    else if(TokenComparison(XHTML_FAMILY_ATTRIBUTE, attribute.nameBuffer, attribute.nameLength))
+    else if(TokenComparison(MARKUP::SPAN_ATTRIBUTES::FONT_FAMILY, attribute.nameBuffer, attribute.nameLength))
     {
       isFontDefined = true;
       ProcessFontFamily(attribute, fontRun);
     }
-    else if(TokenComparison(XHTML_SIZE_ATTRIBUTE, attribute.nameBuffer, attribute.nameLength))
+    else if(TokenComparison(MARKUP::SPAN_ATTRIBUTES::FONT_SIZE, attribute.nameBuffer, attribute.nameLength))
     {
       isFontDefined = true;
       ProcessFontSize(attribute, fontRun);
     }
-    else if(TokenComparison(XHTML_WEIGHT_ATTRIBUTE, attribute.nameBuffer, attribute.nameLength))
+    else if(TokenComparison(MARKUP::SPAN_ATTRIBUTES::FONT_WEIGHT, attribute.nameBuffer, attribute.nameLength))
     {
       isFontDefined = true;
       ProcessFontWeight(attribute, fontRun);
     }
-    else if(TokenComparison(XHTML_WIDTH_ATTRIBUTE, attribute.nameBuffer, attribute.nameLength))
+    else if(TokenComparison(MARKUP::SPAN_ATTRIBUTES::FONT_WIDTH, attribute.nameBuffer, attribute.nameLength))
     {
       isFontDefined = true;
       ProcessFontWidth(attribute, fontRun);
     }
-    else if(TokenComparison(XHTML_SLANT_ATTRIBUTE, attribute.nameBuffer, attribute.nameLength))
+    else if(TokenComparison(MARKUP::SPAN_ATTRIBUTES::FONT_SLANT, attribute.nameBuffer, attribute.nameLength))
     {
       isFontDefined = true;
       ProcessFontSlant(attribute, fontRun);
     }
-    else if(TokenComparison(XHTML_UNDERLINE_COLOR_ATTRIBUTE, attribute.nameBuffer, attribute.nameLength))
+    else if(TokenComparison(MARKUP::SPAN_ATTRIBUTES::UNDERLINE_COLOR, attribute.nameBuffer, attribute.nameLength))
     {
       isUnderlinedCharacterDefined = true;
       ProcessColorAttribute(attribute, underlinedCharacterRun);
     }
-    else if(TokenComparison(XHTML_UNDERLINE_HEIGHT_ATTRIBUTE, attribute.nameBuffer, attribute.nameLength))
+    else if(TokenComparison(MARKUP::SPAN_ATTRIBUTES::UNDERLINE_HEIGHT, attribute.nameBuffer, attribute.nameLength))
     {
       isUnderlinedCharacterDefined = true;
       ProcessHeightAttribute(attribute, underlinedCharacterRun);
     }
-    else if(TokenComparison(XHTML_UNDERLINE_TYPE_ATTRIBUTE, attribute.nameBuffer, attribute.nameLength))
+    else if(TokenComparison(MARKUP::SPAN_ATTRIBUTES::UNDERLINE_TYPE, attribute.nameBuffer, attribute.nameLength))
     {
       isUnderlinedCharacterDefined = true;
       ProcessTypeAttribute(attribute, underlinedCharacterRun);
     }
-    else if(TokenComparison(XHTML_UNDERLINE_DASH_GAP_ATTRIBUTE, attribute.nameBuffer, attribute.nameLength))
+    else if(TokenComparison(MARKUP::SPAN_ATTRIBUTES::UNDERLINE_DASH_GAP, attribute.nameBuffer, attribute.nameLength))
     {
       isUnderlinedCharacterDefined = true;
       ProcessDashGapAttribute(attribute, underlinedCharacterRun);
     }
-    else if(TokenComparison(XHTML_UNDERLINE_DASH_WIDTH_ATTRIBUTE, attribute.nameBuffer, attribute.nameLength))
+    else if(TokenComparison(MARKUP::SPAN_ATTRIBUTES::UNDERLINE_DASH_WIDTH, attribute.nameBuffer, attribute.nameLength))
     {
       isUnderlinedCharacterDefined = true;
       ProcessDashWidthAttribute(attribute, underlinedCharacterRun);
     }
-    else if(TokenComparison(XHTML_STRIKETHROUGH_COLOR_ATTRIBUTE, attribute.nameBuffer, attribute.nameLength))
+    else if(TokenComparison(MARKUP::SPAN_ATTRIBUTES::STRIKETHROUGH_COLOR, attribute.nameBuffer, attribute.nameLength))
     {
       isStrikethroughDefined = true;
       ProcessColorAttribute(attribute, strikethroughRun);
     }
-    else if(TokenComparison(XHTML_STRIKETHROUGH_HEIGHT_ATTRIBUTE, attribute.nameBuffer, attribute.nameLength))
+    else if(TokenComparison(MARKUP::SPAN_ATTRIBUTES::STRIKETHROUGH_HEIGHT, attribute.nameBuffer, attribute.nameLength))
     {
       isStrikethroughDefined = true;
       ProcessHeightAttribute(attribute, strikethroughRun);
     }
-    else if(TokenComparison(XHTML_CHARACTER_SPACING_VALUE_ATTRIBUTE, attribute.nameBuffer, attribute.nameLength))
+    else if(TokenComparison(MARKUP::SPAN_ATTRIBUTES::CHARACTER_SPACING_VALUE, attribute.nameBuffer, attribute.nameLength))
     {
       isCharacterSpacingDefined = true;
       ProcessValueAttribute(attribute, characterSpacingCharacterRun);
index 2f0ea5d..10e104c 100644 (file)
@@ -24,6 +24,7 @@
 // INTERNAL INCLUDES
 #include <dali-toolkit/internal/text/markup-processor-attribute-helper-functions.h>
 #include <dali-toolkit/internal/text/markup-processor-helper-functions.h>
+#include <dali-toolkit/internal/text/markup-tags-and-attributes.h>
 #include <dali-toolkit/internal/text/strikethrough-character-run.h>
 
 namespace Dali
@@ -32,12 +33,6 @@ namespace Toolkit
 {
 namespace Text
 {
-namespace
-{
-const std::string XHTML_COLOR_ATTRIBUTE("color");
-const std::string XHTML_HEIGHT_ATTRIBUTE("height");
-} // namespace
-
 void ProcessColorAttribute(const Attribute& attribute, StrikethroughCharacterRun& strikethroughRun)
 
 {
@@ -60,11 +55,11 @@ void ProcessStrikethroughTag(const Tag& tag, StrikethroughCharacterRun& striketh
   {
     const Attribute& attribute(*it);
 
-    if(TokenComparison(XHTML_COLOR_ATTRIBUTE, attribute.nameBuffer, attribute.nameLength))
+    if(TokenComparison(MARKUP::STRIKETHROUGH_ATTRIBUTES::COLOR, attribute.nameBuffer, attribute.nameLength))
     {
       ProcessColorAttribute(attribute, strikethroughRun);
     }
-    else if(TokenComparison(XHTML_HEIGHT_ATTRIBUTE, attribute.nameBuffer, attribute.nameLength))
+    else if(TokenComparison(MARKUP::STRIKETHROUGH_ATTRIBUTES::HEIGHT, attribute.nameBuffer, attribute.nameLength))
     {
       ProcessHeightAttribute(attribute, strikethroughRun);
     }
index 8f19b5a..08b9f1e 100644 (file)
@@ -24,6 +24,7 @@
 // INTERNAL INCLUDES
 #include <dali-toolkit/internal/text/markup-processor-attribute-helper-functions.h>
 #include <dali-toolkit/internal/text/markup-processor-helper-functions.h>
+#include <dali-toolkit/internal/text/markup-tags-and-attributes.h>
 #include <dali-toolkit/internal/text/text-effects-style.h>
 #include <dali-toolkit/internal/text/underlined-character-run.h>
 
@@ -35,12 +36,6 @@ namespace Text
 {
 namespace
 {
-const std::string XHTML_COLOR_ATTRIBUTE("color");
-const std::string XHTML_HEIGHT_ATTRIBUTE("height");
-const std::string XHTML_TYPE_ATTRIBUTE("type");
-const std::string XHTML_DASH_GAP_ATTRIBUTE("dash-gap");
-const std::string XHTML_DASH_WIDTH_ATTRIBUTE("dash-width");
-
 const unsigned int MAX_TYPE_ATTRIBUTE_SIZE = 7u; ///< The maximum length of any of the possible 'type' values.
 
 } // namespace
@@ -85,23 +80,23 @@ void ProcessUnderlineTag(const Tag& tag, UnderlinedCharacterRun& underlinedChara
   {
     const Attribute& attribute(*it);
 
-    if(TokenComparison(XHTML_COLOR_ATTRIBUTE, attribute.nameBuffer, attribute.nameLength))
+    if(TokenComparison(MARKUP::UNDERLINE_ATTRIBUTES::COLOR, attribute.nameBuffer, attribute.nameLength))
     {
       ProcessColorAttribute(attribute, underlinedCharacterRun);
     }
-    else if(TokenComparison(XHTML_HEIGHT_ATTRIBUTE, attribute.nameBuffer, attribute.nameLength))
+    else if(TokenComparison(MARKUP::UNDERLINE_ATTRIBUTES::HEIGHT, attribute.nameBuffer, attribute.nameLength))
     {
       ProcessHeightAttribute(attribute, underlinedCharacterRun);
     }
-    else if(TokenComparison(XHTML_TYPE_ATTRIBUTE, attribute.nameBuffer, attribute.nameLength))
+    else if(TokenComparison(MARKUP::UNDERLINE_ATTRIBUTES::TYPE, attribute.nameBuffer, attribute.nameLength))
     {
       ProcessTypeAttribute(attribute, underlinedCharacterRun);
     }
-    else if(TokenComparison(XHTML_DASH_GAP_ATTRIBUTE, attribute.nameBuffer, attribute.nameLength))
+    else if(TokenComparison(MARKUP::UNDERLINE_ATTRIBUTES::DASH_GAP, attribute.nameBuffer, attribute.nameLength))
     {
       ProcessDashGapAttribute(attribute, underlinedCharacterRun);
     }
-    else if(TokenComparison(XHTML_DASH_WIDTH_ATTRIBUTE, attribute.nameBuffer, attribute.nameLength))
+    else if(TokenComparison(MARKUP::UNDERLINE_ATTRIBUTES::DASH_WIDTH, attribute.nameBuffer, attribute.nameLength))
     {
       ProcessDashWidthAttribute(attribute, underlinedCharacterRun);
     }
index 1df19ca..60eb03b 100644 (file)
@@ -36,6 +36,7 @@
 #include <dali-toolkit/internal/text/markup-processor-span.h>
 #include <dali-toolkit/internal/text/markup-processor-strikethrough.h>
 #include <dali-toolkit/internal/text/markup-processor-underline.h>
+#include <dali-toolkit/internal/text/markup-tags-and-attributes.h>
 #include <dali-toolkit/internal/text/xhtml-entities.h>
 
 namespace Dali
@@ -46,25 +47,6 @@ namespace Text
 {
 namespace
 {
-// HTML-ISH tag and attribute constants.
-// Note they must be lower case in order to make the comparison to work
-// as the parser converts all the read tags to lower case.
-const std::string XHTML_COLOR_TAG("color");
-const std::string XHTML_FONT_TAG("font");
-const std::string XHTML_B_TAG("b");
-const std::string XHTML_I_TAG("i");
-const std::string XHTML_U_TAG("u");
-const std::string XHTML_SHADOW_TAG("shadow");
-const std::string XHTML_GLOW_TAG("glow");
-const std::string XHTML_OUTLINE_TAG("outline");
-const std::string XHTML_ITEM_TAG("item");
-const std::string XHTML_ANCHOR_TAG("a");
-const std::string XHTML_BACKGROUND_TAG("background");
-const std::string XHTML_SPAN_TAG("span");
-const std::string XHTML_STRIKETHROUGH_TAG("s");
-const std::string XHTML_PARAGRAPH_TAG("p");
-const std::string XHTML_CHARACTER_SPACING_TAG("char-spacing");
-
 const char LESS_THAN      = '<';
 const char GREATER_THAN   = '>';
 const char EQUAL          = '=';
@@ -1117,12 +1099,12 @@ void ProcessMarkupString(const std::string& markupString, MarkupProcessData& mar
              markupStringEndBuffer,
              tag))
     {
-      if(TokenComparison(XHTML_COLOR_TAG, tag.buffer, tag.length))
+      if(TokenComparison(MARKUP::TAG::COLOR, tag.buffer, tag.length))
       {
         ProcessTagForRun<ColorRun>(
           markupProcessData.colorRuns, styleStack, tag, characterIndex, colorRunIndex, colorTagReference, [](const Tag& tag, ColorRun& run) { ProcessColorTag(tag, run); });
       } // <color></color>
-      else if(TokenComparison(XHTML_I_TAG, tag.buffer, tag.length))
+      else if(TokenComparison(MARKUP::TAG::ITALIC, tag.buffer, tag.length))
       {
         ProcessTagForRun<FontDescriptionRun>(
           markupProcessData.fontRuns, styleStack, tag, characterIndex, fontRunIndex, iTagReference, [](const Tag&, FontDescriptionRun& fontRun) {
@@ -1130,12 +1112,12 @@ void ProcessMarkupString(const std::string& markupString, MarkupProcessData& mar
             fontRun.slantDefined = true;
           });
       } // <i></i>
-      else if(TokenComparison(XHTML_U_TAG, tag.buffer, tag.length))
+      else if(TokenComparison(MARKUP::TAG::UNDERLINE, tag.buffer, tag.length))
       {
         ProcessTagForRun<UnderlinedCharacterRun>(
           markupProcessData.underlinedCharacterRuns, styleStack, tag, characterIndex, underlinedCharacterRunIndex, uTagReference, [](const Tag& tag, UnderlinedCharacterRun& run) { ProcessUnderlineTag(tag, run); });
       } // <u></u>
-      else if(TokenComparison(XHTML_B_TAG, tag.buffer, tag.length))
+      else if(TokenComparison(MARKUP::TAG::BOLD, tag.buffer, tag.length))
       {
         ProcessTagForRun<FontDescriptionRun>(
           markupProcessData.fontRuns, styleStack, tag, characterIndex, fontRunIndex, bTagReference, [](const Tag&, FontDescriptionRun& fontRun) {
@@ -1143,12 +1125,12 @@ void ProcessMarkupString(const std::string& markupString, MarkupProcessData& mar
             fontRun.weightDefined = true;
           });
       } // <b></b>
-      else if(TokenComparison(XHTML_FONT_TAG, tag.buffer, tag.length))
+      else if(TokenComparison(MARKUP::TAG::FONT, tag.buffer, tag.length))
       {
         ProcessTagForRun<FontDescriptionRun>(
           markupProcessData.fontRuns, styleStack, tag, characterIndex, fontRunIndex, fontTagReference, [](const Tag& tag, FontDescriptionRun& fontRun) { ProcessFontTag(tag, fontRun); });
       } // <font></font>
-      else if(TokenComparison(XHTML_ANCHOR_TAG, tag.buffer, tag.length))
+      else if(TokenComparison(MARKUP::TAG::ANCHOR, tag.buffer, tag.length))
       {
         /* Anchor */
         ProcessAnchorTag(markupProcessData, tag, characterIndex);
@@ -1166,31 +1148,31 @@ void ProcessMarkupString(const std::string& markupString, MarkupProcessData& mar
             ProcessUnderlineTag(tag, run);
           });
       } // <a href=https://www.tizen.org>tizen</a>
-      else if(TokenComparison(XHTML_SHADOW_TAG, tag.buffer, tag.length))
+      else if(TokenComparison(MARKUP::TAG::SHADOW, tag.buffer, tag.length))
       {
         // TODO: If !tag.isEndTag, then create a new shadow run.
         //       else Pop the top of the stack and set the number of characters of the run.
       } // <shadow></shadow>
-      else if(TokenComparison(XHTML_GLOW_TAG, tag.buffer, tag.length))
+      else if(TokenComparison(MARKUP::TAG::GLOW, tag.buffer, tag.length))
       {
         // TODO: If !tag.isEndTag, then create a new glow run.
         //       else Pop the top of the stack and set the number of characters of the run.
       } // <glow></glow>
-      else if(TokenComparison(XHTML_OUTLINE_TAG, tag.buffer, tag.length))
+      else if(TokenComparison(MARKUP::TAG::OUTLINE, tag.buffer, tag.length))
       {
         // TODO: If !tag.isEndTag, then create a new outline run.
         //       else Pop the top of the stack and set the number of characters of the run.
       } // <outline></outline>
-      else if(TokenComparison(XHTML_ITEM_TAG, tag.buffer, tag.length))
+      else if(TokenComparison(MARKUP::TAG::EMBEDDED_ITEM, tag.buffer, tag.length))
       {
         ProcessItemTag(markupProcessData, tag, characterIndex);
       }
-      else if(TokenComparison(XHTML_BACKGROUND_TAG, tag.buffer, tag.length))
+      else if(TokenComparison(MARKUP::TAG::BACKGROUND, tag.buffer, tag.length))
       {
         ProcessTagForRun<ColorRun>(
           markupProcessData.backgroundColorRuns, styleStack, tag, characterIndex, backgroundRunIndex, backgroundTagReference, [](const Tag& tag, ColorRun& run) { ProcessBackground(tag, run); });
       }
-      else if(TokenComparison(XHTML_SPAN_TAG, tag.buffer, tag.length))
+      else if(TokenComparison(MARKUP::TAG::SPAN, tag.buffer, tag.length))
       {
         ProcessSpanForRun(tag,
                           spanStack,
@@ -1209,18 +1191,18 @@ void ProcessMarkupString(const std::string& markupString, MarkupProcessData& mar
                           characterIndex,
                           spanTagReference);
       }
-      else if(TokenComparison(XHTML_STRIKETHROUGH_TAG, tag.buffer, tag.length))
+      else if(TokenComparison(MARKUP::TAG::STRIKETHROUGH, tag.buffer, tag.length))
       {
         ProcessTagForRun<StrikethroughCharacterRun>(
           markupProcessData.strikethroughCharacterRuns, styleStack, tag, characterIndex, strikethroughCharacterRunIndex, sTagReference, [](const Tag& tag, StrikethroughCharacterRun& run) { ProcessStrikethroughTag(tag, run); });
       } // <s></s>
-      else if(TokenComparison(XHTML_PARAGRAPH_TAG, tag.buffer, tag.length))
+      else if(TokenComparison(MARKUP::TAG::PARAGRAPH, tag.buffer, tag.length))
       {
         ProcessParagraphTag(markupProcessData, tag, (markupStringBuffer == markupStringEndBuffer), characterIndex);
         ProcessTagForRun<BoundedParagraphRun>(
           markupProcessData.boundedParagraphRuns, styleStack, tag, characterIndex, boundedParagraphRunIndex, pTagReference, [](const Tag& tag, BoundedParagraphRun& run) { ProcessAttributesOfParagraphTag(tag, run); });
       } // <p></p>
-      else if(TokenComparison(XHTML_CHARACTER_SPACING_TAG, tag.buffer, tag.length))
+      else if(TokenComparison(MARKUP::TAG::CHARACTER_SPACING, tag.buffer, tag.length))
       {
         ProcessTagForRun<CharacterSpacingCharacterRun>(
           markupProcessData.characterSpacingCharacterRuns, styleStack, tag, characterIndex, characterSpacingCharacterRunIndex, characterSpacingTagReference, [](const Tag& tag, CharacterSpacingCharacterRun& run) { ProcessCharacterSpacingTag(tag, run); });
diff --git a/dali-toolkit/internal/text/markup-tags-and-attributes.h b/dali-toolkit/internal/text/markup-tags-and-attributes.h
new file mode 100644 (file)
index 0000000..0f75d6a
--- /dev/null
@@ -0,0 +1,719 @@
+#ifndef DALI_TOOLKIT_TEXT_MARKUPS_AND_ATTRIBUTES_H
+#define DALI_TOOLKIT_TEXT_MARKUPS_AND_ATTRIBUTES_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 <string>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Text
+{
+/**
+ * @brief Use markup styling to style Text-Controller.
+ * The markup tag is opend by <> and closed by </>
+ *
+ * @details You can use markup elements to change the style of the text.
+ * Since the text controls do not process markup elements by default, you must first set the EnableMarkup property of the Text-Controller  to true:
+ *
+ * @note The markup processor does not check for markup validity, and styles are rendered in priority order.
+ * Incorrect or incompatible elements can cause the text to be rendered incorrectly.
+ */
+namespace MARKUP
+{
+namespace TAG
+{
+// HTML-ISH tag and attribute constants.
+// Note they must be lower case in order to make the comparison to work
+// as the parser converts all the read tags to lower case.
+
+/**
+ * @brief Sets the color for the characters inside the element.
+ *
+ * The following example explains how to apply it:
+ * @code
+ *
+ * textController.Text = "<color value='red'>Hello world</color>";
+ *
+ * @endcode
+ *
+ * @see COLOR_ATTRIBUTES
+ *
+ */
+static const std::string COLOR("color");
+
+/**
+ * @brief Sets the font values for the characters inside the element.
+ *
+ * The following example explains how to apply it:
+ * @code
+ *
+ * textController.Text = "<font family='DejaVuSerif' size='18'>Hello world</font>";
+ *
+ * @endcode
+ *
+ * @see FONT_ATTRIBUTES
+ */
+static const std::string FONT("font");
+
+/**
+ * @brief Sets Bold decoration for the characters inside the element.
+ *
+ * The following example explains how to apply it:
+ * @code
+ *
+ * textController.Text = "<b>Hello world</b>";
+ *
+ * @endcode
+ *
+ * @see
+ */
+static const std::string BOLD("b");
+
+/**
+ * @brief Sets Italic decoration for the characters inside the element.
+ *
+ * The following example explains how to apply it:
+ * @code
+ *
+ * textController.Text = "<i>Hello world</i>";
+ *
+ * @endcode
+ *
+ */
+static const std::string ITALIC("i");
+
+/**
+ * @brief Sets the underlined values for the characters inside the element.
+ *
+ * The following example explains how to apply it:
+ * @code
+ *
+ * textController.Text = "<u>Hello world</u>";
+ *
+ * @endcode
+ *
+ * @see UNDERLINE_ATTRIBUTES
+ */
+static const std::string UNDERLINE("u");
+
+/**
+ * @todo Sets the shadow for the characters inside the element.
+ *
+ */
+static const std::string SHADOW("shadow"); ///< This tag under construction.
+
+/**
+ * @todo Sets the glow for the characters inside the element.
+ *
+ */
+static const std::string GLOW("glow"); ///< This tag under construction.
+
+/**
+ * @todo Sets the outline for the characters inside the element.
+ *
+ */
+static const std::string OUTLINE("outline"); ///< This tag under construction.
+
+/**
+ * @brief Defines an embedded item within the text.
+ *
+ * The following example explains how to apply it:
+ * @code
+ *
+ * textController.Text = "<item 'width'=26 'height'=26 'url'='path/image.png' 'color-blending'='multiply'/>";
+ *
+ * @endcode
+ *
+ * @see EMBEDDED_ITEM_ATTRIBUTES
+ */
+static const std::string EMBEDDED_ITEM("item");
+
+/**
+ * @brief Defines a hyperlink for the text inside the element.
+ *
+ * The following example explains how to apply it:
+ * @code
+ *
+ * textController.Text = "<a href='https://www.tizen.org'>TIZEN</a>";
+ *
+ * @endcode
+ *
+ * @see ANCHOR_ATTRIBUTES
+ */
+static const std::string ANCHOR("a");
+
+/**
+ * @brief Sets the background color for the characters inside the element.
+ *
+ * The following example explains how to apply it:
+ * @code
+ *
+ * textController.Text = "<background color='yellow'>Hello world</background>";
+ *
+ * @endcode
+ *
+ * @see BACKGROUND_ATTRIBUTES
+ */
+static const std::string BACKGROUND("background");
+
+/**
+ * @brief Use span tag to set many styles on character's level for the characters inside the element.
+ *
+ * The following example explains how to apply it:
+ * @code
+ *
+ * textController.Text = "<span font-size='20' font-family='DejaVu Sans' font-width='condensed' font-slant='italic' text-color='green' char-space-value='10.0f'>Hello world</span>";
+ *
+ * @endcode
+ *
+ * @see SPAN_ATTRIBUTES
+ */
+static const std::string SPAN("span");
+
+/**
+ * @brief Sets the strikethrough values for the characters inside the element.
+ *
+ * The following example explains how to apply it:
+ * @code
+ *
+ * textController.Text = "<s>Hello world</s>";
+ *
+ * @endcode
+ *
+ * @see STRIKETHROUGH_ATTRIBUTES
+ */
+static const std::string STRIKETHROUGH("s");
+
+/**
+ * @brief Use paragraph tag to set many styles on paragraph's level for the lines inside the element.
+ *
+ * The following example explains how to apply it:
+ * @code
+ *
+ * textController.Text = "test before paragraph tag <p>test paragraph tag </p>test after paragraph tag ";
+ *
+ * @endcode
+ *
+ * @see PARAGRAPH_ATTRIBUTES
+ */
+static const std::string PARAGRAPH("p");
+
+/**
+ * @brief Sets the character spacing values for the characters inside the element.
+ *
+ * The following example explains how to apply it:
+ * @code
+ *
+ * textController.Text = "<char-spacing value='3.0f'>Hello world</char-spacing>";
+ *
+ * @endcode
+ *
+ * @see CHARACTER_SPACING_ATTRIBUTES
+ */
+static const std::string CHARACTER_SPACING("char-spacing");
+} // namespace TAG
+
+namespace COLOR_ATTRIBUTES
+{
+/**
+ * @brief Use the value attribute to define the color.
+ * The supported attribute values are red, green, blue, yellow, magenta, cyan, white, black, and transparent.
+ * Web colors and colors represented in 32-bit hexadecimal 0xAARRGGBB format are also supported.
+ *
+ * The following examples show text in red color:
+ * @code
+ *
+ * textController.Text = "<color value='red'>Hello world</color>"; /// Color coded with a text constant
+ *
+ * @endcode
+ *
+ * @code
+ *
+ * textController.Text = "<color value='0xFFFF0000'>Hello world</color>"); /// Color packed inside an ARGB hexadecimal value
+ *
+ * @endcode
+ */
+static const std::string VALUE("value");
+} // namespace COLOR_ATTRIBUTES
+
+namespace FONT_ATTRIBUTES
+{
+/**
+ * @brief Use the family attribute to define the font name.
+ *
+ * Example:
+ * @code
+ *
+ * textController.Text = "<font family='SamsungSans' >Hello world</font>";
+ *
+ * @endcode
+ *
+ */
+static const std::string FAMILY("family");
+
+/**
+ * @brief Use the size attribute to define the font size in points.
+ *
+ * Example:
+ * @code
+ *
+ * textController.Text = "<font size='50' >Hello world</font>";
+ *
+ * @endcode
+ *
+ */
+static const std::string SIZE("size");
+
+/**
+ * @brief Use the weight attribute to define the font weight.
+ *
+ * Example:
+ * @code
+ *
+ * textController.Text = "<font weight='bold' >Hello world</font>";
+ *
+ * @endcode
+ *
+ */
+static const std::string WEIGHT("weight");
+
+/**
+ * @brief Use the width attribute to define the font width.
+ *
+ * Example:
+ * @code
+ *
+ * textController.Text = "<font width='condensed' >Hello world</font>";
+ *
+ * @endcode
+ *
+ */
+static const std::string WIDTH("width");
+
+/**
+ * @brief Use the slant attribute to define the font slant.
+ *
+ * Example:
+ * @code
+ *
+ * textController.Text = "<font slant='italic' >Hello world</font>";
+ *
+ * @endcode
+ *
+ */
+static const std::string SLANT("slant");
+} // namespace FONT_ATTRIBUTES
+
+namespace UNDERLINE_ATTRIBUTES
+{
+/**
+ * @brief Use the color attribute to define the color of underline.
+ * The supported attribute values are red, green, blue, yellow, magenta, cyan, white, black, and transparent.
+ * Web colors and colors represented in 32-bit hexadecimal 0xAARRGGBB format are also supported.
+ *
+ * The following example explains how to apply it:
+ * @code
+ *
+ * textController.Text = "<u color='green'>Hello world</u>";
+ *
+ * @endcode
+ */
+static const std::string COLOR("color");
+
+/**
+ * @brief Use the height attribute to define the height of underline.
+ * It is float value.
+ *
+ * The following example explains how to apply it:
+ * @code
+ *
+ * textController.Text = "<u height='2.0f'>Hello world</u>";
+ *
+ * @endcode
+ */
+static const std::string HEIGHT("height");
+
+/**
+ * @brief Use the type attribute to define the type of underline.
+ * The supported attribute values are solid, dashed and double
+ * The default value is solid
+ *
+ * The following example explains how to apply it:
+ * @code
+ *
+ * textController.Text = "<u type='double'>Hello world</u>";
+ *
+ * @endcode
+ */
+static const std::string TYPE("type");
+
+/**
+ * @brief Use the dash-gap attribute to define the dash-gap of underline.
+ * The gap in pixels between the dashes of the dashed underline. Only valid when "DASHED" underline type is used.
+ *
+ * It is float value.
+ * @note If not provided then the default gap is used (1 pixel).
+ *
+ * The following example explains how to apply it:
+ * @code
+ *
+ * textController.Text = "<u type='dashed' dash-gap='2.0f'>Hello world</u>";
+ *
+ * @endcode
+ */
+static const std::string DASH_GAP("dash-gap");
+
+/**
+ * @brief Use the dash-width attribute to define the dash-width of underline.
+ * The width in pixels of the dashes of the dashed underline. Only valid when "DASHED" underline type is used.
+ * It is float value.
+ * @note If not provided then the default width is used (2 pixel).
+ *
+ * The following example explains how to apply it:
+ * @code
+ *
+ * textController.Text = "<u type='dashed' dash-width='3.0f'>Hello world</u>";
+ *
+ * @endcode
+ */
+static const std::string DASH_WIDTH("dash-width");
+
+} // namespace UNDERLINE_ATTRIBUTES
+
+namespace SPAN_ATTRIBUTES
+{
+//NOTE: the MAX_NUM_OF_ATTRIBUTES in "markup-processor.cpp" should be updated when add a new attribute for span tag.
+
+/**
+ * @brief The font family attribute.
+ *
+ * Example:
+ * @code
+ * textController.Text = "<span font-family='SamsungSans' >Hello world</span>";
+ * @endcode
+ * @see FONT_ATTRIBUTES::FAMILY
+ */
+static const std::string FONT_FAMILY("font-family");
+
+/**
+ * @brief The font size attribute.
+ *
+ * Example:
+ * @code
+ * textController.Text = "<span font-size='50' >Hello world</span>";
+ * @endcode
+ * @see FONT_ATTRIBUTES::SIZE
+ */
+static const std::string FONT_SIZE("font-size");
+
+/**
+ * @brief The font weight attribute.
+ *
+ * Example:
+ * @code
+ * textController.Text = "<span font-weight='bold' >Hello world</span>";
+ * @endcode
+ * @see FONT_ATTRIBUTES::WEIGHT
+ */
+static const std::string FONT_WEIGHT("font-weight");
+
+/**
+ * @brief The font width attribute.
+ *
+ * Example:
+ * @code
+ * textController.Text = "<span font-width='condensed' >Hello world</span>";
+ * @endcode
+ * @see FONT_ATTRIBUTES::WIDTH
+ */
+static const std::string FONT_WIDTH("font-width");
+
+/**
+ * @brief The font slant attribute.
+ *
+ * Example:
+ * @code
+ * textController.Text = "<span font-slant='italic' >Hello world</span>";
+ * @endcode
+ * @see FONT_ATTRIBUTES::SLANT
+ */
+static const std::string FONT_SLANT("font-slant");
+
+/**
+ * @brief The color value attribute.
+ *
+ * Example:
+ * @code
+ * textController.Text = "<span text-color='blue' >Hello world</span>";
+ * @endcode
+ * @see COLOR_ATTRIBUTES::VALUE
+ */
+static const std::string TEXT_COLOR("text-color");
+
+/**
+ * @brief The background color attribute.
+ *
+ * Example:
+ * @code
+ * textController.Text = "<span background-color='yellow' >Hello world</span>";
+ * @endcode
+ * @see BACKGROUND_ATTRIBUTES::COLOR
+ */
+static const std::string BACKGROUND_COLOR("background-color");
+
+/**
+ * @brief The undeline color attribute.
+ *
+ * Example:
+ * @code
+ * textController.Text = "<span u-color='green' >Hello world</span>";
+ * @endcode
+ * @see UNDERLINE_ATTRIBUTES::COLOR
+ */
+static const std::string UNDERLINE_COLOR("u-color");
+
+/**
+ * @brief The undeline height attribute.
+ *
+ * Example:
+ * @code
+ * textController.Text = "<span u-height='3.0f' >Hello world</span>";
+ * @endcode
+ * @see UNDERLINE_ATTRIBUTES::HEIGHT
+ */
+static const std::string UNDERLINE_HEIGHT("u-height");
+
+/**
+ * @brief The undeline type attribute.
+ *
+ * Example:
+ * @code
+ * textController.Text = "<span u-type='solid' >Hello world</span>";
+ * @endcode
+ * @see UNDERLINE_ATTRIBUTES::TYPE
+ */
+static const std::string UNDERLINE_TYPE("u-type");
+
+/**
+ * @brief The undeline dash-gap attribute.
+ *
+ * Example:
+ * @code
+ * textController.Text = "<span u-type='dashed' u-dash-gap='2.0f' >Hello world</span>";
+ * @endcode
+ * @see UNDERLINE_ATTRIBUTES::DASH_GAP
+ */
+static const std::string UNDERLINE_DASH_GAP("u-dash-gap");
+
+/**
+ * @brief The undeline dash-width attribute.
+ *
+ * Example:
+ * @code
+ * textController.Text = "<span u-type='dashed' u-dash-width='4.0f' >Hello world</span>";
+ * @endcode
+ * @see UNDERLINE_ATTRIBUTES::DASH_WIDTH
+ */
+static const std::string UNDERLINE_DASH_WIDTH("u-dash-width");
+
+/**
+ * @brief The strikethrough color attribute.
+ *
+ * Example:
+ * @code
+ * textController.Text = "<span s-color='green' >Hello world</span>";
+ * @endcode
+ * @see STRIKETHROUGH_ATTRIBUTES::COLOR
+ */
+static const std::string STRIKETHROUGH_COLOR("s-color");
+
+/**
+ * @brief The strikethrough height attribute.
+ *
+ * Example:
+ * @code
+ * textController.Text = "<span s-height='3.0f' >Hello world</span>";
+ * @endcode
+ * @see STRIKETHROUGH_ATTRIBUTES::HEIGHT
+ */
+static const std::string STRIKETHROUGH_HEIGHT("s-height");
+
+/**
+ * @brief The character-spacing value attribute.
+ *
+ * Example:
+ * @code
+ * textController.Text = "<span char-space-value='5.0f' >Hello world</span>";
+ * @endcode
+ * @see CHARACTER_SPACING_ATTRIBUTES::VALUE
+ */
+static const std::string CHARACTER_SPACING_VALUE("char-space-value");
+} // namespace SPAN_ATTRIBUTES
+
+namespace STRIKETHROUGH_ATTRIBUTES
+{
+/**
+ * @brief Use the color attribute to define the color of strikethrough.
+ * The supported attribute values are red, green, blue, yellow, magenta, cyan, white, black, and transparent.
+ * Web colors and colors represented in 32-bit hexadecimal 0xAARRGGBB format are also supported.
+ *
+ * The following example explains how to apply it:
+ * @code
+ *
+ * textController.Text = "<s color='green'>Hello world</s>";
+ *
+ * @endcode
+ */
+static const std::string COLOR("color");
+
+/**
+ * @brief Use the height attribute to define the height of strikethrough.
+ * It is float value.
+ *
+ * The following example explains how to apply it:
+ * @code
+ *
+ * textController.Text = "<s height='2.0f'>Hello world</s>";
+ *
+ * @endcode
+ */
+static const std::string HEIGHT("height");
+} // namespace STRIKETHROUGH_ATTRIBUTES
+
+namespace PARAGRAPH_ATTRIBUTES
+{
+/**
+ * @brief Use the align attribute to define the horizontal alignment of paragraph.
+ * The supported attribute values are begin, center and end .
+ *
+ * The following example explains how to apply it:
+ * @code
+ *
+ * textController.Text = ""text outside<p align='end'>Paragraph end</p>text outside<p align='center'>Paragraph center</p>text outside<p align='begin' >Paragraph begin</p>";
+ *
+ * @endcode
+ */
+static const std::string ALIGN("align");
+
+/**
+ * @brief Use the rrel-line-height attribute to define the relative height of the line (a factor that will be multiplied by text height).
+ * It is float value.
+ *
+ * The following example explains how to apply it:
+ * @code
+ *
+ * textController.Text = "<p>line 1</p><p rel-line-height=0.5>line\n2</p>line 3<p rel-line-height=3>line\n4</p>line 5";
+ *
+ * @endcode
+ * @note If the value is less than 1, the lines could to be overlapped.
+ */
+static const std::string RELATIVE_LINE_HEIGHT("rel-line-height");
+
+} // namespace PARAGRAPH_ATTRIBUTES
+
+namespace CHARACTER_SPACING_ATTRIBUTES
+{
+/**
+ * @brief Use the value attribute to define the spaces between characters in Pixels.
+ *  A positive value will make the characters far apart (expanded) and a negative value will bring them closer (condensed).
+ *
+ * Examples:
+ * @code
+ *
+ * textController.Text = "<char-spacing value='5.0f'>Hello world</char-spacing>"; /// Expanded
+ *
+ * @endcode
+ *
+ * @code
+ *
+ * textController.Text = "<char-spacing value='-5.0f'>Hello world</char-spacing>"); /// Condensed
+ *
+ * @endcode
+ */
+static const std::string VALUE("value");
+} // namespace CHARACTER_SPACING_ATTRIBUTES
+namespace BACKGROUND_ATTRIBUTES
+{
+/**
+ * @brief Use the value attribute to define the color of background.
+ * The supported attribute values are red, green, blue, yellow, magenta, cyan, white, black, and transparent.
+ * Web colors and colors represented in 32-bit hexadecimal 0xAARRGGBB format are also supported.
+ *
+ * The following example explains how to apply it:
+ * @code
+ *
+ * textController.Text = "<background color='green'>Hello world</background>";
+ *
+ * @endcode
+ */
+static const std::string COLOR("color");
+
+} // namespace BACKGROUND_ATTRIBUTES
+
+namespace EMBEDDED_ITEM_ATTRIBUTES
+{
+/**
+ * @brief Use the url attribute to define url path of the image.
+ *
+ * @note  The url of the image is optional. If there is no image
+ * the layout engine will use the width and height to
+ * create a space inside the text. This gap can be filled later.
+ */
+static const std::string URL("url");
+
+/**
+ * @brief Use the width attribute to define the width of the item.
+ */
+static const std::string WIDTH("width");
+
+/**
+ * @brief Use the height attribute to define the height of the item.
+ */
+static const std::string HEIGHT("height");
+
+/**
+ * @brief Use the color-blending attribute to define whether the color of the image is multiplied by the color of the text.
+ *
+ * @note A color blending mode can be set. The default is NONE, the image will use its own color. If MULTIPLY is set, the color
+ * of the image will be multiplied by the color of the text.
+ */
+static const std::string COLOR_BLENDING("color-blending");
+} // namespace EMBEDDED_ITEM_ATTRIBUTES
+
+namespace ANCHOR_ATTRIBUTES
+{
+/**
+ * @brief Use the href attribute to define the url of hyperlink.
+ */
+static const std::string HREF("href");
+
+} // namespace ANCHOR_ATTRIBUTES
+
+} // namespace MARKUP
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // DALI_TOOLKIT_TEXT_MARKUPS_AND_ATTRIBUTES_H
index 628434e..500a081 100644 (file)
@@ -848,12 +848,6 @@ Devel::PixelBuffer Typesetter::CreateImageBuffer(const unsigned int bufferWidth,
     // Increases the vertical offset with the line's ascender.
     glyphData.verticalOffset += static_cast<int>(line.ascender);
 
-    // Include line spacing after first line
-    if(lineIndex > 0u)
-    {
-      glyphData.verticalOffset += static_cast<int>(line.lineSpacing);
-    }
-
     // Retrieves the glyph's outline width
     float outlineWidth = static_cast<float>(mModel->GetOutlineWidth());
 
@@ -1158,8 +1152,8 @@ Devel::PixelBuffer Typesetter::CreateImageBuffer(const unsigned int bufferWidth,
       DrawStrikethrough(bufferWidth, bufferHeight, glyphData, baseline, strikethroughStartingYPosition, maxStrikethroughHeight, lineExtentLeft, lineExtentRight, modelStrikethroughProperties, currentStrikethroughProperties, line);
     }
 
-    // Increases the vertical offset with the line's descender.
-    glyphData.verticalOffset += static_cast<int>(-line.descender);
+    // Increases the vertical offset with the line's descender & line spacing.
+    glyphData.verticalOffset += static_cast<int>(-line.descender+line.lineSpacing);
   }
 
   return glyphData.bitmapBuffer;
index 7494cb6..d5c41a1 100644 (file)
@@ -117,6 +117,7 @@ bool Controller::EventHandler::KeyEvent(Controller& controller, const Dali::KeyE
 
   bool textChanged    = false;
   bool relayoutNeeded = false;
+  bool isEditable     = controller.IsEditable() && controller.IsUserInteractionEnabled();
 
   if((NULL != controller.mImpl->mEventData) &&
      (keyEvent.GetState() == KeyEvent::DOWN))
@@ -148,7 +149,7 @@ bool Controller::EventHandler::KeyEvent(Controller& controller, const Dali::KeyE
             (Dali::DALI_KEY_CURSOR_DOWN == keyCode))
     {
       // If don't have any text, do nothing.
-      if(!controller.mImpl->mTextUpdateInfo.mPreviousNumberOfCharacters)
+      if(!controller.mImpl->mTextUpdateInfo.mPreviousNumberOfCharacters || !isEditable)
       {
         return false;
       }
@@ -207,7 +208,7 @@ bool Controller::EventHandler::KeyEvent(Controller& controller, const Dali::KeyE
       // Do nothing
       return false;
     }
-    else if(keyEvent.IsCtrlModifier() && !keyEvent.IsShiftModifier())
+    else if(keyEvent.IsCtrlModifier() && !keyEvent.IsShiftModifier() && isEditable)
     {
       bool consumed = false;
       if(keyName == KEY_C_NAME || keyName == KEY_INSERT_NAME || logicalKey == KEY_C_NAME || logicalKey == KEY_INSERT_NAME)
@@ -273,7 +274,7 @@ bool Controller::EventHandler::KeyEvent(Controller& controller, const Dali::KeyE
     else
     {
       DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Controller::KeyEvent %p keyString %s\n", &controller, keyString.c_str());
-      if(!controller.IsEditable()) return false;
+      if(!isEditable) return false;
 
       std::string refinedKey = keyString;
       if(controller.mImpl->mInputFilter != NULL && !refinedKey.empty())
index cee6a88..1ed8c7f 100644 (file)
@@ -379,14 +379,15 @@ void ControllerImplEventHandler::OnCursorKeyEvent(Controller::Impl& impl, const
       impl.GetCursorPosition(primaryCursorPosition, cursorInfo);
 
       // Get the line below.
-      const LineRun& line = *(visualModel->mLines.Begin() + lineIndex + 1u);
+      const LineRun& nextline = *(visualModel->mLines.Begin() + lineIndex + 1u);
+      const LineRun& currline = *(visualModel->mLines.Begin() + lineIndex);
 
       // Get last line index
       const LineIndex lastLineIndex = (visualModel->mLines.Size() > 0 ? visualModel->mLines.Size() - 1u : 0);
       const bool      isLastLine    = (lineIndex + 1u == lastLineIndex);
 
       // Get the next hit 'y' point.
-      const float hitPointY = cursorInfo.lineOffset + cursorInfo.lineHeight + 0.5f * GetLineHeight(line, isLastLine);
+      const float hitPointY = cursorInfo.lineOffset + GetLineHeight(currline, false) + 0.5f * GetLineHeight(nextline, isLastLine);
 
       // Use the cursor hook position 'x' and the next hit 'y' position to calculate the new cursor index.
       bool matchedCharacter = false;
index 318c196..c24a5cf 100644 (file)
@@ -909,7 +909,8 @@ void Controller::Impl::SetEditable(bool editable)
 
     if(mEventData->mDecorator)
     {
-      mEventData->mDecorator->SetEditable(editable);
+      bool decoratorEditable = editable && mIsUserInteractionEnabled;
+      mEventData->mDecorator->SetEditable(decoratorEditable);
     }
   }
 }
@@ -1874,6 +1875,17 @@ void Controller::Impl::SetDefaultColor(const Vector4& color)
   }
 }
 
+void Controller::Impl::SetUserInteractionEnabled(bool enabled)
+{
+  mIsUserInteractionEnabled = enabled;
+
+  if(mEventData && mEventData->mDecorator)
+  {
+    bool editable = mEventData->mEditingEnabled && enabled;
+    mEventData->mDecorator->SetEditable(editable);
+  }
+}
+
 void Controller::Impl::ClearFontData()
 {
   if(mFontDefaults)
index 8be1767..5944039 100644 (file)
@@ -41,6 +41,7 @@ const float DEFAULT_TEXTFIT_MIN     = 10.f;
 const float DEFAULT_TEXTFIT_MAX     = 100.f;
 const float DEFAULT_TEXTFIT_STEP    = 1.f;
 const float DEFAULT_FONT_SIZE_SCALE = 1.f;
+const float DEFAULT_DISABLED_COLOR_OPACITY = 0.3f;
 
 //Forward declarations
 struct CursorInfo;
@@ -358,10 +359,12 @@ struct Controller::Impl
     mTextFitMaxSize(DEFAULT_TEXTFIT_MAX),
     mTextFitStepSize(DEFAULT_TEXTFIT_STEP),
     mFontSizeScale(DEFAULT_FONT_SIZE_SCALE),
+    mDisabledColorOpacity(DEFAULT_DISABLED_COLOR_OPACITY),
     mFontSizeScaleEnabled(true),
     mTextFitEnabled(false),
     mTextFitChanged(false),
-    mIsLayoutDirectionChanged(false)
+    mIsLayoutDirectionChanged(false),
+    mIsUserInteractionEnabled(true)
   {
     mModel = Model::New();
 
@@ -874,6 +877,11 @@ struct Controller::Impl
   void SetDefaultColor(const Vector4& color);
 
   /**
+   * @copydoc Controller::SetUserInteractionEnabled()
+   */
+  void SetUserInteractionEnabled(bool enabled);
+
+  /**
    * @brief Helper to clear font-specific data (only).
    */
   void ClearFontData();
@@ -1014,10 +1022,12 @@ public:
   float mTextFitMaxSize;               ///< Maximum Font Size for text fit. Default 100
   float mTextFitStepSize;              ///< Step Size for font intervalse. Default 1
   float mFontSizeScale;                ///< Scale value for Font Size. Default 1.0
+  float mDisabledColorOpacity;         ///< Color opacity when disabled.
   bool  mFontSizeScaleEnabled : 1;     ///< Whether the font size scale is enabled.
   bool  mTextFitEnabled : 1;           ///< Whether the text's fit is enabled.
   bool  mTextFitChanged : 1;           ///< Whether the text fit property has changed.
   bool  mIsLayoutDirectionChanged : 1; ///< Whether the layout has changed.
+  bool  mIsUserInteractionEnabled : 1; ///< Whether the user interaction is enabled.
 
 private:
   friend ControllerImplEventHandler;
index b0f740d..bf92f6a 100644 (file)
@@ -747,6 +747,26 @@ const Vector4& Controller::GetDefaultColor() const
   return mImpl->mTextColor;
 }
 
+void Controller::SetDisabledColorOpacity(float opacity)
+{
+  mImpl->mDisabledColorOpacity = opacity;
+}
+
+float Controller::GetDisabledColorOpacity() const
+{
+  return mImpl->mDisabledColorOpacity;
+}
+
+void Controller::SetUserInteractionEnabled(bool enabled)
+{
+  mImpl->SetUserInteractionEnabled(enabled);
+}
+
+bool Controller::IsUserInteractionEnabled() const
+{
+  return mImpl->mIsUserInteractionEnabled;
+}
+
 void Controller::SetPlaceholderTextColor(const Vector4& textColor)
 {
   PlaceholderHandler::SetPlaceholderTextColor(*this, textColor);
index 81a0318..3e987dd 100644 (file)
@@ -504,6 +504,20 @@ public: // Configure the text controller.
   bool IsTextFitChanged() const;
 
   /**
+   * @brief Sets disabled color opacity.
+   *
+   * @param[in] opacity The color opacity value in disabled state.
+   */
+  void SetDisabledColorOpacity(float opacity);
+
+  /**
+   * @brief Retrieves the disabled color opacity.
+   *
+   * @return The disabled color opacity value for disabled state.
+   */
+  float GetDisabledColorOpacity() const;
+
+  /**
    * @brief Enable or disable the placeholder text elide.
    * @param enabled Whether to enable the placeholder text elide.
    */
@@ -1004,6 +1018,20 @@ public: // Default style & Input style
   const Vector4& GetDefaultColor() const;
 
   /**
+   * @brief Sets the user interaction enabled.
+   *
+   * @param enabled whether to enable the user interaction.
+   */
+  void SetUserInteractionEnabled(bool enabled);
+
+  /**
+   * @brief Whether the user interaction is enabled.
+   *
+   * @return true if the user interaction is enabled, false otherwise.
+   */
+  bool IsUserInteractionEnabled() const;
+
+  /**
    * @brief Set the text color
    *
    * @param textColor The text color
index 71d8cba..831d4b4 100644 (file)
@@ -90,6 +90,12 @@ void NPatchVisual::LoadImages()
     // Load the auxiliary image
     auto preMultiplyOnLoading = TextureManager::MultiplyOnLoad::LOAD_WITHOUT_MULTIPLY;
     mAuxiliaryPixelBuffer     = textureManager.LoadPixelBuffer(mAuxiliaryUrl, Dali::ImageDimensions(), FittingMode::DEFAULT, SamplingMode::BOX_THEN_LINEAR, synchronousLoading, this, true, preMultiplyOnLoading);
+
+    // If synchronousLoading is true, we can check the auxiliaryResource's statue now.
+    if(synchronousLoading)
+    {
+      mAuxiliaryResourceStatus = mAuxiliaryPixelBuffer ? Toolkit::Visual::ResourceStatus::READY : Toolkit::Visual::ResourceStatus::FAILED;
+    }
   }
 }
 
@@ -202,7 +208,10 @@ void NPatchVisual::DoSetOnScene(Actor& actor)
     mImpl->mRenderer.SetShader(shader);
 
     mPlacementActor = actor;
-    if(data->GetLoadingState() != NPatchData::LoadingState::LOADING)
+    // If all reasources are already loaded, apply textures and uniforms now
+    // else, will be completed uploaded at LoadComplete function asynchronously.
+    if(data->GetLoadingState() != NPatchData::LoadingState::LOADING &&
+       (!mAuxiliaryUrl.IsValid() || mAuxiliaryResourceStatus != Toolkit::Visual::ResourceStatus::PREPARING))
     {
       if(RenderingAddOn::Get().IsValid())
       {
@@ -214,7 +223,15 @@ void NPatchVisual::DoSetOnScene(Actor& actor)
       mPlacementActor.Reset();
 
       // npatch loaded and ready to display
-      ResourceReady(Toolkit::Visual::ResourceStatus::READY);
+      if(data->GetLoadingState() != NPatchData::LoadingState::LOAD_COMPLETE ||
+         (mAuxiliaryUrl.IsValid() && mAuxiliaryResourceStatus != Toolkit::Visual::ResourceStatus::READY))
+      {
+        ResourceReady(Toolkit::Visual::ResourceStatus::FAILED);
+      }
+      else
+      {
+        ResourceReady(Toolkit::Visual::ResourceStatus::READY);
+      }
     }
   }
 }
@@ -240,6 +257,12 @@ void NPatchVisual::OnSetTransform()
   }
 }
 
+bool NPatchVisual::IsResourceReady() const
+{
+  return (mImpl->mResourceStatus == Toolkit::Visual::ResourceStatus::READY ||
+          mImpl->mResourceStatus == Toolkit::Visual::ResourceStatus::FAILED);
+}
+
 void NPatchVisual::DoCreatePropertyMap(Property::Map& map) const
 {
   map.Clear();
@@ -275,6 +298,7 @@ NPatchVisual::NPatchVisual(VisualFactoryCache& factoryCache, ImageVisualShaderFa
   mImageUrl(),
   mAuxiliaryUrl(),
   mId(NPatchData::INVALID_NPATCH_DATA_ID),
+  mAuxiliaryResourceStatus(Toolkit::Visual::ResourceStatus::PREPARING),
   mBorderOnly(false),
   mBorder(),
   mAuxiliaryImageAlpha(0.0f),
@@ -451,6 +475,40 @@ void NPatchVisual::ApplyTextureAndUniforms()
   {
     textureSet = data->GetTextures();
     NPatchHelper::ApplyTextureAndUniforms(mImpl->mRenderer, data);
+
+    if(mAuxiliaryPixelBuffer)
+    {
+      // If the auxiliary image is smaller than the un-stretched NPatch, use CPU resizing to enlarge it to the
+      // same size as the unstretched NPatch. This will give slightly higher quality results than just relying
+      // on GL interpolation alone.
+      if(mAuxiliaryPixelBuffer.GetWidth() < data->GetCroppedWidth() &&
+         mAuxiliaryPixelBuffer.GetHeight() < data->GetCroppedHeight())
+      {
+        mAuxiliaryPixelBuffer.Resize(data->GetCroppedWidth(), data->GetCroppedHeight());
+      }
+
+      // Note, this resets mAuxiliaryPixelBuffer handle
+      auto auxiliaryPixelData = Devel::PixelBuffer::Convert(mAuxiliaryPixelBuffer);
+
+      auto texture = Texture::New(TextureType::TEXTURE_2D,
+                                  auxiliaryPixelData.GetPixelFormat(),
+                                  auxiliaryPixelData.GetWidth(),
+                                  auxiliaryPixelData.GetHeight());
+      texture.Upload(auxiliaryPixelData);
+
+      // TODO : This code exist due to the texture cache manager hold TextureSet, not Texture.
+      // If we call textureSet.SetTexture(1, texture) directly, the cached TextureSet also be changed.
+      // We should make pass utc-Dali-VisualFactory.cpp UtcDaliNPatchVisualAuxiliaryImage02().
+      TextureSet tempTextureSet = TextureSet::New();
+      tempTextureSet.SetTexture(0, textureSet.GetTexture(0));
+      tempTextureSet.SetTexture(1, texture);
+      textureSet = tempTextureSet;
+
+      mImpl->mRenderer.RegisterProperty(DevelImageVisual::Property::AUXILIARY_IMAGE_ALPHA,
+                                        AUXILIARY_IMAGE_ALPHA_NAME,
+                                        mAuxiliaryImageAlpha);
+    }
+    mImpl->mRenderer.SetTextures(textureSet);
   }
   else
   {
@@ -463,34 +521,8 @@ void NPatchVisual::ApplyTextureAndUniforms()
     {
       imageSize = actor.GetProperty(Actor::Property::SIZE).Get<Vector2>();
     }
-    mFactoryCache.UpdateBrokenImageRenderer(mImpl->mRenderer, imageSize);
-  }
-
-  if(mAuxiliaryPixelBuffer)
-  {
-    // If the auxiliary image is smaller than the un-stretched NPatch, use CPU resizing to enlarge it to the
-    // same size as the unstretched NPatch. This will give slightly higher quality results than just relying
-    // on GL interpolation alone.
-    if(mAuxiliaryPixelBuffer.GetWidth() < data->GetCroppedWidth() &&
-       mAuxiliaryPixelBuffer.GetHeight() < data->GetCroppedHeight())
-    {
-      mAuxiliaryPixelBuffer.Resize(data->GetCroppedWidth(), data->GetCroppedHeight());
-    }
-
-    // Note, this resets mAuxiliaryPixelBuffer handle
-    auto auxiliaryPixelData = Devel::PixelBuffer::Convert(mAuxiliaryPixelBuffer);
-
-    auto texture = Texture::New(TextureType::TEXTURE_2D,
-                                auxiliaryPixelData.GetPixelFormat(),
-                                auxiliaryPixelData.GetWidth(),
-                                auxiliaryPixelData.GetHeight());
-    texture.Upload(auxiliaryPixelData);
-    textureSet.SetTexture(1, texture);
-    mImpl->mRenderer.RegisterProperty(DevelImageVisual::Property::AUXILIARY_IMAGE_ALPHA,
-                                      AUXILIARY_IMAGE_ALPHA_NAME,
-                                      mAuxiliaryImageAlpha);
+    mFactoryCache.UpdateBrokenImageRenderer(mImpl->mRenderer, imageSize, false);
   }
-  mImpl->mRenderer.SetTextures(textureSet);
 
   // Register transform properties
   mImpl->mTransform.SetUniforms(mImpl->mRenderer, Direction::LEFT_TO_RIGHT);
@@ -516,55 +548,60 @@ Geometry NPatchVisual::GetNinePatchGeometry(VisualFactoryCache::GeometryType sub
 
 void NPatchVisual::SetResource()
 {
-  const NPatchData* data;
-  if(mImpl->mRenderer && mLoader.GetNPatchData(mId, data))
-  {
-    Geometry geometry = CreateGeometry();
-    Shader   shader   = CreateShader();
+  Geometry geometry = CreateGeometry();
+  Shader   shader   = CreateShader();
 
-    mImpl->mRenderer.SetGeometry(geometry);
-    mImpl->mRenderer.SetShader(shader);
-
-    Actor actor = mPlacementActor.GetHandle();
-    if(actor)
-    {
-      ApplyTextureAndUniforms();
-      actor.AddRenderer(mImpl->mRenderer);
-      mPlacementActor.Reset();
+  mImpl->mRenderer.SetGeometry(geometry);
+  mImpl->mRenderer.SetShader(shader);
 
-      // npatch loaded and ready to display
-      ResourceReady(Toolkit::Visual::ResourceStatus::READY);
-    }
+  Actor actor = mPlacementActor.GetHandle();
+  if(actor)
+  {
+    ApplyTextureAndUniforms();
+    actor.AddRenderer(mImpl->mRenderer);
+    mPlacementActor.Reset();
   }
 }
 
 void NPatchVisual::LoadComplete(bool loadSuccess, TextureInformation textureInformation)
 {
-  if(textureInformation.returnType == TextureUploadObserver::ReturnType::TEXTURE)
+  if(textureInformation.returnType == TextureUploadObserver::ReturnType::TEXTURE) // For the Url.
   {
-    EnablePreMultipliedAlpha(textureInformation.preMultiplied);
-    if(!loadSuccess)
-    {
-      // Image loaded and ready to display
-      ResourceReady(Toolkit::Visual::ResourceStatus::FAILED);
-    }
-
-    if(mAuxiliaryPixelBuffer || !mAuxiliaryUrl.IsValid())
+    if(loadSuccess)
     {
-      SetResource();
+      EnablePreMultipliedAlpha(textureInformation.preMultiplied);
     }
   }
-  else // for the ReturnType::PIXEL_BUFFER
+  else // For the AuxiliaryUrl : ReturnType::PIXEL_BUFFER
   {
     if(loadSuccess && textureInformation.url == mAuxiliaryUrl.GetUrl())
     {
-      mAuxiliaryPixelBuffer = textureInformation.pixelBuffer;
-      SetResource();
+      mAuxiliaryPixelBuffer    = textureInformation.pixelBuffer;
+      mAuxiliaryResourceStatus = Toolkit::Visual::ResourceStatus::READY;
     }
     else
     {
-      // Image loaded and ready to display
-      ResourceReady(Toolkit::Visual::ResourceStatus::FAILED);
+      mAuxiliaryResourceStatus = Toolkit::Visual::ResourceStatus::FAILED;
+    }
+  }
+  // If auxiliaryUrl didn't set || auxiliaryUrl load done.
+  if(!mAuxiliaryUrl.IsValid() || mAuxiliaryResourceStatus != Toolkit::Visual::ResourceStatus::PREPARING)
+  {
+    const NPatchData* data;
+    // and.. If Url loading done.
+    if(mImpl->mRenderer && mLoader.GetNPatchData(mId, data) && data->GetLoadingState() != NPatchData::LoadingState::LOADING)
+    {
+      SetResource();
+      // npatch loaded and ready to display
+      if(data->GetLoadingState() != NPatchData::LoadingState::LOAD_COMPLETE ||
+         (mAuxiliaryUrl.IsValid() && mAuxiliaryResourceStatus != Toolkit::Visual::ResourceStatus::READY))
+      {
+        ResourceReady(Toolkit::Visual::ResourceStatus::FAILED);
+      }
+      else
+      {
+        ResourceReady(Toolkit::Visual::ResourceStatus::READY);
+      }
     }
   }
 }
index ac66c45..d537a37 100644 (file)
@@ -137,6 +137,11 @@ protected:
    */
   void OnSetTransform() override;
 
+  /**
+   * @copydoc Visual::Base::IsResourceReady
+   */
+  bool IsResourceReady() const override;
+
 private:
   /**
    * Loads the NPatch image and the Auxiliary image if needed
@@ -218,14 +223,15 @@ private:
   WeakHandle<Actor>                         mPlacementActor; ///< Weakhandle to contain Actor during texture loading
   NPatchLoader&                             mLoader;         ///< reference to N patch loader for fast access
   ImageVisualShaderFactory&                 mImageVisualShaderFactory;
-  VisualUrl                                 mImageUrl;             ///< The url to the N patch to load
-  VisualUrl                                 mAuxiliaryUrl;         ///< An auxiliary image that can be displayed on top of the N-Patch
-  NPatchData::NPatchDataId                  mId;                   ///< id of the N patch (from loader/cache)
-  Devel::PixelBuffer                        mAuxiliaryPixelBuffer; ///< pixel buffer of the auxiliary mask image
-  bool                                      mBorderOnly;           ///< if only border is desired
-  Rect<int>                                 mBorder;               ///< The size of the border
-  float                                     mAuxiliaryImageAlpha;  ///< The alpha value for the auxiliary image only
-  Toolkit::ImageVisual::ReleasePolicy::Type mReleasePolicy;        ///< The release policy to determine when an image should no longer be cached.
+  VisualUrl                                 mImageUrl;                ///< The url to the N patch to load
+  VisualUrl                                 mAuxiliaryUrl;            ///< An auxiliary image that can be displayed on top of the N-Patch
+  NPatchData::NPatchDataId                  mId;                      ///< id of the N patch (from loader/cache)
+  Devel::PixelBuffer                        mAuxiliaryPixelBuffer;    ///< pixel buffer of the auxiliary mask image
+  Toolkit::Visual::ResourceStatus           mAuxiliaryResourceStatus; ///< resource status for auxiliary mask image
+  bool                                      mBorderOnly;              ///< if only border is desired
+  Rect<int>                                 mBorder;                  ///< The size of the border
+  float                                     mAuxiliaryImageAlpha;     ///< The alpha value for the auxiliary image only
+  Toolkit::ImageVisual::ReleasePolicy::Type mReleasePolicy;           ///< The release policy to determine when an image should no longer be cached.
 };
 
 } // namespace Internal
index a65c779..d7932d2 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * 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.
 #include <dali/devel-api/common/hash.h>
 
 // INTERNAL INCLUDES
+#include <dali-toolkit/devel-api/utility/npatch-helper.h>
+#include <dali-toolkit/internal/graphics/builtin-shader-extern-gen.h>
 #include <dali-toolkit/internal/visuals/animated-vector-image/vector-animation-manager.h>
 #include <dali-toolkit/internal/visuals/color/color-visual.h>
 #include <dali-toolkit/internal/visuals/image-atlas-manager.h>
 #include <dali-toolkit/internal/visuals/svg/svg-visual.h>
-#include <dali-toolkit/internal/graphics/builtin-shader-extern-gen.h>
-#include <dali-toolkit/devel-api/utility/npatch-helper.h>
+#include <dali-toolkit/internal/visuals/visual-string-constants.h>
 #include <dali/integration-api/debug.h>
 
 namespace Dali
@@ -36,6 +37,10 @@ namespace Toolkit
 {
 namespace Internal
 {
+namespace
+{
+const Vector4 FULL_TEXTURE_RECT(0.f, 0.f, 1.f, 1.f);
+}
 
 VisualFactoryCache::VisualFactoryCache(bool preMultiplyOnLoad)
 : mSvgRasterizeThread(NULL),
@@ -221,10 +226,10 @@ Texture VisualFactoryCache::GetBrokenVisualImage(uint32_t brokenIndex)
     Devel::PixelBuffer pixelBuffer = LoadImageFromFile(mBrokenImageInfoContainer[brokenIndex].url);
     if(pixelBuffer)
     {
-      pixelData                = Devel::PixelBuffer::Convert(pixelBuffer); // takes ownership of buffer
-      mBrokenImageInfoContainer[brokenIndex].texture  = Texture::New(Dali::TextureType::TEXTURE_2D, pixelData.GetPixelFormat(), pixelData.GetWidth(), pixelData.GetHeight());
+      pixelData                                      = Devel::PixelBuffer::Convert(pixelBuffer); // takes ownership of buffer
+      mBrokenImageInfoContainer[brokenIndex].texture = Texture::New(Dali::TextureType::TEXTURE_2D, pixelData.GetPixelFormat(), pixelData.GetWidth(), pixelData.GetHeight());
       mBrokenImageInfoContainer[brokenIndex].texture.Upload(pixelData);
-      mBrokenImageInfoContainer[brokenIndex].width = pixelData.GetWidth();
+      mBrokenImageInfoContainer[brokenIndex].width  = pixelData.GetWidth();
       mBrokenImageInfoContainer[brokenIndex].height = pixelData.GetHeight();
     }
   }
@@ -270,7 +275,7 @@ Geometry VisualFactoryCache::GetNPatchGeometry(int index)
       geometry = GetGeometry(VisualFactoryCache::NINE_PATCH_GEOMETRY);
       if(!geometry)
       {
-        geometry = NPatchHelper::CreateGridGeometry(Uint16Pair(3,3));
+        geometry = NPatchHelper::CreateGridGeometry(Uint16Pair(3, 3));
         SaveGeometry(VisualFactoryCache::NINE_PATCH_GEOMETRY, geometry);
       }
     }
@@ -286,7 +291,7 @@ Geometry VisualFactoryCache::GetNPatchGeometry(int index)
     geometry = GetGeometry(VisualFactoryCache::NINE_PATCH_GEOMETRY);
     if(!geometry)
     {
-      geometry = NPatchHelper::CreateGridGeometry(Uint16Pair(3,3));
+      geometry = NPatchHelper::CreateGridGeometry(Uint16Pair(3, 3));
       SaveGeometry(VisualFactoryCache::NINE_PATCH_GEOMETRY, geometry);
     }
   }
@@ -337,16 +342,15 @@ void VisualFactoryCache::ApplyTextureAndUniforms(Renderer& renderer, int index)
   TextureSet        textureSet;
   if(mNPatchLoader.GetNPatchData(mBrokenImageInfoContainer[index].npatchId, data) && data->GetLoadingState() == NPatchData::LoadingState::LOAD_COMPLETE)
   {
-    textureSet = data->GetTextures();
+    textureSet                               = data->GetTextures();
     mBrokenImageInfoContainer[index].texture = textureSet.GetTexture(0);
     NPatchHelper::ApplyTextureAndUniforms(renderer, data);
     renderer.SetTextures(textureSet);
   }
 }
 
-void VisualFactoryCache::UpdateBrokenImageRenderer(Renderer& renderer, const Vector2& size)
+void VisualFactoryCache::UpdateBrokenImageRenderer(Renderer& renderer, const Vector2& size, const bool& rendererIsImage)
 {
-
   bool useDefaultBrokenImage = false;
   if(mBrokenImageInfoContainer.size() == 0)
   {
@@ -354,7 +358,7 @@ void VisualFactoryCache::UpdateBrokenImageRenderer(Renderer& renderer, const Vec
   }
 
   // Load Information for broken image
-  for(uint32_t index = 0; (index  < mBrokenImageInfoContainer.size()) && !useDefaultBrokenImage; index++)
+  for(uint32_t index = 0; (index < mBrokenImageInfoContainer.size()) && !useDefaultBrokenImage; index++)
   {
     if(mBrokenImageInfoContainer[index].width == 0 && mBrokenImageInfoContainer[index].height == 0)
     {
@@ -365,16 +369,16 @@ void VisualFactoryCache::UpdateBrokenImageRenderer(Renderer& renderer, const Vec
         if(mBrokenImageInfoContainer[index].visualType == VisualUrl::Type::N_PATCH)
         {
           const NPatchData* data;
-          Rect<int> border;
-          mBrokenImageInfoContainer[index].npatchId = mNPatchLoader.Load( mTextureManager, NULL, mBrokenImageInfoContainer[index].url, border, mPreMultiplyOnLoad, true);
+          Rect<int>         border;
+          mBrokenImageInfoContainer[index].npatchId = mNPatchLoader.Load(mTextureManager, NULL, mBrokenImageInfoContainer[index].url, border, mPreMultiplyOnLoad, true);
           if(mNPatchLoader.GetNPatchData(mBrokenImageInfoContainer[index].npatchId, data) && data->GetLoadingState() == NPatchData::LoadingState::LOAD_COMPLETE)
           {
-            mBrokenImageInfoContainer[index].width = data->GetCroppedWidth();
+            mBrokenImageInfoContainer[index].width  = data->GetCroppedWidth();
             mBrokenImageInfoContainer[index].height = data->GetCroppedHeight();
           }
           else
           {
-            DALI_LOG_ERROR("Can't update renderer for broken image. maybe image loading is failed [index:%d] [path:%s] \n",index, mBrokenImageInfoContainer[index].url.c_str());
+            DALI_LOG_ERROR("Can't update renderer for broken image. maybe image loading is failed [index:%d] [path:%s] \n", index, mBrokenImageInfoContainer[index].url.c_str());
             useDefaultBrokenImage = true;
           }
         }
@@ -382,7 +386,7 @@ void VisualFactoryCache::UpdateBrokenImageRenderer(Renderer& renderer, const Vec
         {
           if(!GetBrokenVisualImage(index))
           {
-            DALI_LOG_ERROR("Can't update renderer for broken image. maybe image loading is failed [index:%d] [path:%s] \n",index, mBrokenImageInfoContainer[index].url.c_str());
+            DALI_LOG_ERROR("Can't update renderer for broken image. maybe image loading is failed [index:%d] [path:%s] \n", index, mBrokenImageInfoContainer[index].url.c_str());
             useDefaultBrokenImage = true;
           }
         }
@@ -401,24 +405,42 @@ void VisualFactoryCache::UpdateBrokenImageRenderer(Renderer& renderer, const Vec
     mBrokenImageInfoContainer[defaultBrokenIndex].url = mDefaultBrokenImageUrl;
     VisualUrl visualUrl(mBrokenImageInfoContainer[defaultBrokenIndex].url);
     mBrokenImageInfoContainer[defaultBrokenIndex].visualType = visualUrl.GetType();
-    mUseDefaultBrokenImageOnly = true;
+    mUseDefaultBrokenImageOnly                               = true;
   }
 
   // Set Texutre to renderer
   int brokenIndex = GetProperBrokenImageIndex(size);
   if(GetBrokenImageVisualType(brokenIndex) == VisualUrl::N_PATCH)
   {
+    DALI_LOG_ERROR("Broken npatch?");
     // Set geometry and shader for npatch
     Geometry geometry = GetNPatchGeometry(brokenIndex);
-    Shader shader = GetNPatchShader(brokenIndex);
+    Shader   shader   = GetNPatchShader(brokenIndex);
     renderer.SetGeometry(geometry);
     renderer.SetShader(shader);
     ApplyTextureAndUniforms(renderer, brokenIndex);
   }
   else
   {
-    Texture brokenImage = GetBrokenVisualImage(brokenIndex);
-    TextureSet textureSet = TextureSet::New();
+    DALI_LOG_ERROR("Broken single image");
+    // Create single image renderer only if rederer is not use normal ImageShader. i.e. npatch visual.
+    if(!rendererIsImage)
+    {
+      Geometry geometry = GetGeometry(QUAD_GEOMETRY);
+      Shader   shader   = GetShader(IMAGE_SHADER);
+      if(!shader)
+      {
+        std::string vertexShader   = std::string(Dali::Shader::GetVertexShaderPrefix() + SHADER_IMAGE_VISUAL_SHADER_VERT.data());
+        std::string fragmentShader = std::string(Dali::Shader::GetFragmentShaderPrefix() + SHADER_IMAGE_VISUAL_SHADER_FRAG.data());
+        shader                     = Shader::New(vertexShader, fragmentShader);
+        shader.RegisterProperty(PIXEL_AREA_UNIFORM_NAME, FULL_TEXTURE_RECT);
+        SaveShader(IMAGE_SHADER, shader);
+      }
+      renderer.SetGeometry(geometry);
+      renderer.SetShader(shader);
+    }
+    Texture    brokenImage = GetBrokenVisualImage(brokenIndex);
+    TextureSet textureSet  = TextureSet::New();
     textureSet.SetTexture(0u, brokenImage);
     renderer.SetTextures(textureSet);
   }
@@ -428,7 +450,7 @@ int32_t VisualFactoryCache::GetProperBrokenImageIndex(const Vector2& size)
 {
   // Sets the default broken type
   int32_t returnIndex = 0;
-  if((size.width == 0 || size.height == 0) || mUseDefaultBrokenImageOnly )
+  if((size.width == 0 || size.height == 0) || mUseDefaultBrokenImageOnly)
   {
     // To do : Need to add observer about size
     return returnIndex;
index 3ed626f..417f4d4 100644 (file)
@@ -201,8 +201,11 @@ public:
    * @brief Update the broken image Renderer object
    * @param[in,out] renderer renderer for broken image
    * @param[in] size the size of actor
+   * @param[in] rendererIsImage True if input renderer use image shader already.
+   *                            If true, we don't need to create new renderer when broken image is single image.
+   *                            Most of user experience use normal images. So It can reduce runtime.
    */
-  void UpdateBrokenImageRenderer(Renderer& renderer, const Vector2& size);
+  void UpdateBrokenImageRenderer(Renderer& renderer, const Vector2& size, const bool& rendererIsImage = true);
 
 public:
   /**
index 7b27bbf..6f9e75d 100644 (file)
@@ -29,7 +29,7 @@ namespace Toolkit
 {
 const unsigned int TOOLKIT_MAJOR_VERSION = 2;
 const unsigned int TOOLKIT_MINOR_VERSION = 1;
-const unsigned int TOOLKIT_MICRO_VERSION = 16;
+const unsigned int TOOLKIT_MICRO_VERSION = 17;
 const char* const  TOOLKIT_BUILD_DATE    = __DATE__ " " __TIME__;
 
 #ifdef DEBUG_ENABLED
index 6e1ab5c..01aa94e 100644 (file)
@@ -1,6 +1,6 @@
 Name:       dali2-toolkit
 Summary:    Dali 3D engine Toolkit
-Version:    2.1.16
+Version:    2.1.17
 Release:    1
 Group:      System/Libraries
 License:    Apache-2.0 and BSD-3-Clause and MIT